]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs3.patch
- up to 3.6.1; experimental vserver patch
[packages/kernel.git] / kernel-aufs3.patch
CommitLineData
2dfbb274 1aufs3.5 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
2dfbb274 36aufs3.5 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
2dfbb274 65index 7bf08fa..e3c40b5 100644
7f207e10
AM
66--- a/fs/splice.c
67+++ b/fs/splice.c
2dfbb274 68@@ -1090,8 +1090,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);
2dfbb274 79@@ -1118,9 +1118,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 116diff --git a/include/linux/splice.h b/include/linux/splice.h
2dfbb274 117index 09a545a..1ac5727 100644
1e00d052
AM
118--- a/include/linux/splice.h
119+++ b/include/linux/splice.h
2dfbb274 120@@ -91,4 +91,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *);
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
2dfbb274 131aufs3.5 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
2dfbb274 268index 1540632..2463289 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
2dfbb274 280index e3c40b5..3afc547 100644
7f207e10
AM
281--- a/fs/splice.c
282+++ b/fs/splice.c
2dfbb274 283@@ -1114,6 +1114,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.
2dfbb274 291@@ -1140,6 +1141,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
2dfbb274 336index 860aeb3..ffb57bf 100644
7f207e10
AM
337--- a/security/security.c
338+++ b/security/security.c
2dfbb274 339@@ -384,6 +384,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 {
2dfbb274 347@@ -400,6 +401,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)
2dfbb274 355@@ -408,6 +410,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)
2dfbb274 363@@ -426,6 +429,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 {
2dfbb274 371@@ -433,6 +437,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 {
2dfbb274 379@@ -440,6 +445,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 {
2dfbb274 387@@ -516,6 +522,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 {
2dfbb274 395@@ -530,6 +537,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 {
2dfbb274 403@@ -645,6 +653,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 {
2dfbb274 411@@ -705,6 +714,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
2dfbb274 421+++ linux/Documentation/ABI/testing/debugfs-aufs 2012-08-26 08:39:00.753841216 +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
2dfbb274 462+++ linux/Documentation/ABI/testing/sysfs-aufs 2012-08-26 08:39:00.753841216 +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
2dfbb274 490+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2012-08-26 08:39:00.757174634 +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
2dfbb274 656+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2012-08-26 08:39:00.757174634 +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
2dfbb274 886+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2012-08-26 08:39:00.757174634 +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
2dfbb274 996+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2012-08-26 08:39:00.757174634 +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
2dfbb274 1076+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2012-08-26 08:39:00.757174634 +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
2dfbb274 1145+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2012-08-26 08:39:00.757174634 +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
2dfbb274 1196+++ linux/Documentation/filesystems/aufs/design/07export.txt 2012-08-26 08:39:00.757174634 +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
2dfbb274 1259+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2012-08-26 08:39:00.757174634 +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
2dfbb274 1316+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2012-08-26 08:39:00.757174634 +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
2dfbb274 1367+++ linux/Documentation/filesystems/aufs/design/99plan.txt 2012-08-26 08:39:00.757174634 +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
2dfbb274 1467+++ linux/Documentation/filesystems/aufs/README 2012-08-26 08:39:00.757174634 +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).
2dfbb274 1780+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12 and 2012/3, 6).
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
2dfbb274 1801+++ linux/fs/aufs/aufs.h 2012-08-26 08:39:00.757174634 +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
2dfbb274 1865+++ linux/fs/aufs/branch.c 2012-08-26 08:39:00.757174634 +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
2dfbb274 3038+++ linux/fs/aufs/branch.h 2012-08-26 08:39:00.757174634 +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
2dfbb274 3272+++ linux/fs/aufs/conf.mk 2012-08-26 08:39:00.757174634 +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
2dfbb274 3314+++ linux/fs/aufs/cpup.c 2012-08-26 08:39:00.757174634 +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
2dfbb274 4402+++ linux/fs/aufs/cpup.h 2012-08-26 08:39:00.757174634 +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
2dfbb274 4487+++ linux/fs/aufs/dbgaufs.c 2012-08-26 08:39:00.757174634 +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
2dfbb274 4825+++ linux/fs/aufs/dbgaufs.h 2012-08-26 08:39:00.757174634 +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
2dfbb274 4878+++ linux/fs/aufs/dcsub.c 2012-08-26 08:39:00.757174634 +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
2dfbb274 5125+++ linux/fs/aufs/dcsub.h 2012-08-26 08:39:00.757174634 +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
2dfbb274 5223+++ linux/fs/aufs/debug.c 2012-08-26 08:39:00.757174634 +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
2dfbb274 5716+++ linux/fs/aufs/debug.h 2012-08-26 08:39:00.757174634 +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
2dfbb274 5962+++ linux/fs/aufs/dentry.c 2012-08-26 08:39:00.757174634 +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 6340+ || !uid_eq(ia->i_uid, h_inode->i_uid)
2dfbb274 6341+ || !gid_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
2dfbb274 7106+++ linux/fs/aufs/dentry.h 2012-08-26 08:39:00.757174634 +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
2dfbb274 7347+++ linux/fs/aufs/dinfo.c 2012-08-26 08:39:00.757174634 +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
2dfbb274 7894+++ linux/fs/aufs/dir.c 2012-08-26 08:39:00.757174634 +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
2dfbb274 8534+++ linux/fs/aufs/dir.h 2012-08-26 08:39:00.760508065 +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
2dfbb274 8675+++ linux/fs/aufs/dynop.c 2012-08-26 08:39:00.760508065 +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
2dfbb274 9056+++ linux/fs/aufs/dynop.h 2012-08-26 08:39:00.760508065 +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
2dfbb274 9136+++ linux/fs/aufs/export.c 2012-08-26 08:39:00.760508065 +0200
0c3ec466 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
2dfbb274 9950+++ linux/fs/aufs/file.c 2012-08-26 08:39:00.760508065 +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
2dfbb274
AM
10630+++ linux/fs/aufs/file.h 2012-08-26 08:39:00.760508065 +0200
10631@@ -0,0 +1,298 @@
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+
4a4d8108
AM
10715+/* poll.c */
10716+#ifdef CONFIG_AUFS_POLL
10717+unsigned int aufs_poll(struct file *file, poll_table *wait);
10718+#endif
1facf9fc 10719+
4a4d8108
AM
10720+#ifdef CONFIG_AUFS_BR_HFSPLUS
10721+/* hfsplus.c */
10722+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
10723+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
10724+ struct file *h_file);
10725+#else
10726+static inline
10727+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 10728+{
4a4d8108
AM
10729+ return NULL;
10730+}
1facf9fc 10731+
4a4d8108
AM
10732+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
10733+ struct file *h_file);
10734+#endif
1facf9fc 10735+
4a4d8108
AM
10736+/* f_op.c */
10737+extern const struct file_operations aufs_file_fop;
4a4d8108
AM
10738+int au_do_open_nondir(struct file *file, int flags);
10739+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
10740+
10741+#ifdef CONFIG_AUFS_SP_IATTR
10742+/* f_op_sp.c */
10743+int au_special_file(umode_t mode);
10744+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
10745+#else
10746+AuStubInt0(au_special_file, umode_t mode)
10747+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
10748+ dev_t rdev)
10749+{
10750+ init_special_inode(inode, mode, rdev);
10751+}
10752+#endif
1facf9fc 10753+
4a4d8108
AM
10754+/* finfo.c */
10755+void au_hfput(struct au_hfile *hf, struct file *file);
10756+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
10757+ struct file *h_file);
1facf9fc 10758+
4a4d8108 10759+void au_update_figen(struct file *file);
4a4d8108
AM
10760+struct au_fidir *au_fidir_alloc(struct super_block *sb);
10761+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 10762+
4a4d8108
AM
10763+void au_fi_init_once(void *_fi);
10764+void au_finfo_fin(struct file *file);
10765+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 10766+
4a4d8108
AM
10767+/* ioctl.c */
10768+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
10769+#ifdef CONFIG_COMPAT
10770+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
10771+ unsigned long arg);
10772+#endif
1facf9fc 10773+
4a4d8108 10774+/* ---------------------------------------------------------------------- */
1facf9fc 10775+
4a4d8108
AM
10776+static inline struct au_finfo *au_fi(struct file *file)
10777+{
10778+ return file->private_data;
10779+}
1facf9fc 10780+
4a4d8108 10781+/* ---------------------------------------------------------------------- */
1facf9fc 10782+
4a4d8108
AM
10783+/*
10784+ * fi_read_lock, fi_write_lock,
10785+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
10786+ */
10787+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 10788+
4a4d8108
AM
10789+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
10790+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
10791+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 10792+
1308ab2a 10793+/* ---------------------------------------------------------------------- */
10794+
4a4d8108
AM
10795+/* todo: hard/soft set? */
10796+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 10797+{
4a4d8108
AM
10798+ FiMustAnyLock(file);
10799+ return au_fi(file)->fi_btop;
10800+}
dece6358 10801+
4a4d8108
AM
10802+static inline aufs_bindex_t au_fbend_dir(struct file *file)
10803+{
10804+ FiMustAnyLock(file);
10805+ AuDebugOn(!au_fi(file)->fi_hdir);
10806+ return au_fi(file)->fi_hdir->fd_bbot;
10807+}
1facf9fc 10808+
4a4d8108
AM
10809+static inline struct au_vdir *au_fvdir_cache(struct file *file)
10810+{
10811+ FiMustAnyLock(file);
10812+ AuDebugOn(!au_fi(file)->fi_hdir);
10813+ return au_fi(file)->fi_hdir->fd_vdir_cache;
10814+}
1facf9fc 10815+
4a4d8108
AM
10816+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
10817+{
10818+ FiMustWriteLock(file);
10819+ au_fi(file)->fi_btop = bindex;
10820+}
1facf9fc 10821+
4a4d8108
AM
10822+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
10823+{
10824+ FiMustWriteLock(file);
10825+ AuDebugOn(!au_fi(file)->fi_hdir);
10826+ au_fi(file)->fi_hdir->fd_bbot = bindex;
10827+}
1308ab2a 10828+
4a4d8108
AM
10829+static inline void au_set_fvdir_cache(struct file *file,
10830+ struct au_vdir *vdir_cache)
10831+{
10832+ FiMustWriteLock(file);
10833+ AuDebugOn(!au_fi(file)->fi_hdir);
10834+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
10835+}
dece6358 10836+
4a4d8108
AM
10837+static inline struct file *au_hf_top(struct file *file)
10838+{
10839+ FiMustAnyLock(file);
10840+ AuDebugOn(au_fi(file)->fi_hdir);
10841+ return au_fi(file)->fi_htop.hf_file;
10842+}
1facf9fc 10843+
4a4d8108
AM
10844+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
10845+{
10846+ FiMustAnyLock(file);
10847+ AuDebugOn(!au_fi(file)->fi_hdir);
10848+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
10849+}
10850+
4a4d8108
AM
10851+/* todo: memory barrier? */
10852+static inline unsigned int au_figen(struct file *f)
dece6358 10853+{
4a4d8108
AM
10854+ return atomic_read(&au_fi(f)->fi_generation);
10855+}
dece6358 10856+
2cbb1c4b
JR
10857+static inline void au_set_mmapped(struct file *f)
10858+{
10859+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
10860+ return;
0c3ec466 10861+ pr_warn("fi_mmapped wrapped around\n");
2cbb1c4b
JR
10862+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
10863+ ;
10864+}
10865+
10866+static inline void au_unset_mmapped(struct file *f)
10867+{
10868+ atomic_dec(&au_fi(f)->fi_mmapped);
10869+}
10870+
4a4d8108
AM
10871+static inline int au_test_mmapped(struct file *f)
10872+{
2cbb1c4b
JR
10873+ return atomic_read(&au_fi(f)->fi_mmapped);
10874+}
10875+
10876+/* customize vma->vm_file */
10877+
10878+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
10879+ struct file *file)
10880+{
53392da6
AM
10881+ struct file *f;
10882+
10883+ f = vma->vm_file;
2cbb1c4b
JR
10884+ get_file(file);
10885+ vma->vm_file = file;
53392da6 10886+ fput(f);
2cbb1c4b
JR
10887+}
10888+
10889+#ifdef CONFIG_MMU
10890+#define AuDbgVmRegion(file, vma) do {} while (0)
10891+
10892+static inline void au_vm_file_reset(struct vm_area_struct *vma,
10893+ struct file *file)
10894+{
10895+ au_do_vm_file_reset(vma, file);
10896+}
10897+#else
10898+#define AuDbgVmRegion(file, vma) \
10899+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
10900+
10901+static inline void au_vm_file_reset(struct vm_area_struct *vma,
10902+ struct file *file)
10903+{
53392da6
AM
10904+ struct file *f;
10905+
2cbb1c4b 10906+ au_do_vm_file_reset(vma, file);
53392da6 10907+ f = vma->vm_region->vm_file;
2cbb1c4b
JR
10908+ get_file(file);
10909+ vma->vm_region->vm_file = file;
53392da6 10910+ fput(f);
2cbb1c4b
JR
10911+}
10912+#endif /* CONFIG_MMU */
10913+
10914+/* handle vma->vm_prfile */
10915+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
10916+ struct file *file)
10917+{
10918+#ifdef CONFIG_AUFS_PROC_MAP
10919+ get_file(file);
10920+ vma->vm_prfile = file;
10921+#ifndef CONFIG_MMU
10922+ get_file(file);
10923+ vma->vm_region->vm_prfile = file;
10924+#endif
10925+#endif
4a4d8108 10926+}
1308ab2a 10927+
4a4d8108
AM
10928+#endif /* __KERNEL__ */
10929+#endif /* __AUFS_FILE_H__ */
7f207e10
AM
10930diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
10931--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 10932+++ linux/fs/aufs/finfo.c 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 10933@@ -0,0 +1,156 @@
4a4d8108 10934+/*
f6c5ef8b 10935+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
10936+ *
10937+ * This program, aufs is free software; you can redistribute it and/or modify
10938+ * it under the terms of the GNU General Public License as published by
10939+ * the Free Software Foundation; either version 2 of the License, or
10940+ * (at your option) any later version.
10941+ *
10942+ * This program is distributed in the hope that it will be useful,
10943+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10944+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10945+ * GNU General Public License for more details.
10946+ *
10947+ * You should have received a copy of the GNU General Public License
10948+ * along with this program; if not, write to the Free Software
10949+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10950+ */
1308ab2a 10951+
4a4d8108
AM
10952+/*
10953+ * file private data
10954+ */
1facf9fc 10955+
4a4d8108 10956+#include "aufs.h"
1facf9fc 10957+
4a4d8108
AM
10958+void au_hfput(struct au_hfile *hf, struct file *file)
10959+{
10960+ /* todo: direct access f_flags */
2cbb1c4b 10961+ if (vfsub_file_flags(file) & __FMODE_EXEC)
4a4d8108
AM
10962+ allow_write_access(hf->hf_file);
10963+ fput(hf->hf_file);
10964+ hf->hf_file = NULL;
e49829fe 10965+ atomic_dec(&hf->hf_br->br_count);
4a4d8108
AM
10966+ hf->hf_br = NULL;
10967+}
1facf9fc 10968+
4a4d8108
AM
10969+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
10970+{
10971+ struct au_finfo *finfo = au_fi(file);
10972+ struct au_hfile *hf;
10973+ struct au_fidir *fidir;
10974+
10975+ fidir = finfo->fi_hdir;
10976+ if (!fidir) {
10977+ AuDebugOn(finfo->fi_btop != bindex);
10978+ hf = &finfo->fi_htop;
10979+ } else
10980+ hf = fidir->fd_hfile + bindex;
10981+
10982+ if (hf && hf->hf_file)
10983+ au_hfput(hf, file);
10984+ if (val) {
10985+ FiMustWriteLock(file);
10986+ hf->hf_file = val;
10987+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 10988+ }
4a4d8108 10989+}
1facf9fc 10990+
4a4d8108
AM
10991+void au_update_figen(struct file *file)
10992+{
10993+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
10994+ /* smp_mb(); */ /* atomic_set */
1facf9fc 10995+}
10996+
4a4d8108
AM
10997+/* ---------------------------------------------------------------------- */
10998+
4a4d8108
AM
10999+struct au_fidir *au_fidir_alloc(struct super_block *sb)
11000+{
11001+ struct au_fidir *fidir;
11002+ int nbr;
11003+
11004+ nbr = au_sbend(sb) + 1;
11005+ if (nbr < 2)
11006+ nbr = 2; /* initial allocate for 2 branches */
11007+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
11008+ if (fidir) {
11009+ fidir->fd_bbot = -1;
11010+ fidir->fd_nent = nbr;
11011+ fidir->fd_vdir_cache = NULL;
11012+ }
11013+
11014+ return fidir;
11015+}
11016+
11017+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
11018+{
11019+ int err;
11020+ struct au_fidir *fidir, *p;
11021+
11022+ AuRwMustWriteLock(&finfo->fi_rwsem);
11023+ fidir = finfo->fi_hdir;
11024+ AuDebugOn(!fidir);
11025+
11026+ err = -ENOMEM;
11027+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
11028+ GFP_NOFS);
11029+ if (p) {
11030+ p->fd_nent = nbr;
11031+ finfo->fi_hdir = p;
11032+ err = 0;
11033+ }
1facf9fc 11034+
dece6358 11035+ return err;
1facf9fc 11036+}
1308ab2a 11037+
11038+/* ---------------------------------------------------------------------- */
11039+
4a4d8108 11040+void au_finfo_fin(struct file *file)
1308ab2a 11041+{
4a4d8108
AM
11042+ struct au_finfo *finfo;
11043+
7f207e10
AM
11044+ au_nfiles_dec(file->f_dentry->d_sb);
11045+
4a4d8108
AM
11046+ finfo = au_fi(file);
11047+ AuDebugOn(finfo->fi_hdir);
11048+ AuRwDestroy(&finfo->fi_rwsem);
11049+ au_cache_free_finfo(finfo);
1308ab2a 11050+}
1308ab2a 11051+
e49829fe 11052+void au_fi_init_once(void *_finfo)
4a4d8108 11053+{
e49829fe 11054+ struct au_finfo *finfo = _finfo;
2cbb1c4b 11055+ static struct lock_class_key aufs_fi;
1308ab2a 11056+
e49829fe
JR
11057+ au_rw_init(&finfo->fi_rwsem);
11058+ au_rw_class(&finfo->fi_rwsem, &aufs_fi);
4a4d8108 11059+}
1308ab2a 11060+
4a4d8108
AM
11061+int au_finfo_init(struct file *file, struct au_fidir *fidir)
11062+{
9dbd164d 11063+ int err, lc_idx;
4a4d8108
AM
11064+ struct au_finfo *finfo;
11065+ struct dentry *dentry;
11066+
11067+ err = -ENOMEM;
11068+ dentry = file->f_dentry;
11069+ finfo = au_cache_alloc_finfo();
11070+ if (unlikely(!finfo))
11071+ goto out;
11072+
11073+ err = 0;
7f207e10 11074+ au_nfiles_inc(dentry->d_sb);
9dbd164d
AM
11075+ lc_idx = AuLcNonDir_FIINFO;
11076+ if (fidir)
11077+ lc_idx = AuLcDir_FIINFO;
11078+ au_rw_class(&finfo->fi_rwsem, au_lc_key + lc_idx);
4a4d8108
AM
11079+ au_rw_write_lock(&finfo->fi_rwsem);
11080+ finfo->fi_btop = -1;
11081+ finfo->fi_hdir = fidir;
11082+ atomic_set(&finfo->fi_generation, au_digen(dentry));
11083+ /* smp_mb(); */ /* atomic_set */
11084+
11085+ file->private_data = finfo;
11086+
11087+out:
11088+ return err;
11089+}
7f207e10
AM
11090diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
11091--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274
AM
11092+++ linux/fs/aufs/f_op.c 2012-08-26 08:39:00.760508065 +0200
11093@@ -0,0 +1,727 @@
dece6358 11094+/*
f6c5ef8b 11095+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
11096+ *
11097+ * This program, aufs is free software; you can redistribute it and/or modify
11098+ * it under the terms of the GNU General Public License as published by
11099+ * the Free Software Foundation; either version 2 of the License, or
11100+ * (at your option) any later version.
11101+ *
11102+ * This program is distributed in the hope that it will be useful,
11103+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11104+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11105+ * GNU General Public License for more details.
11106+ *
11107+ * You should have received a copy of the GNU General Public License
11108+ * along with this program; if not, write to the Free Software
11109+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11110+ */
1facf9fc 11111+
11112+/*
4a4d8108 11113+ * file and vm operations
1facf9fc 11114+ */
dece6358 11115+
4a4d8108
AM
11116+#include <linux/fs_stack.h>
11117+#include <linux/mman.h>
4a4d8108 11118+#include <linux/security.h>
dece6358
AM
11119+#include "aufs.h"
11120+
4a4d8108 11121+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 11122+{
4a4d8108
AM
11123+ int err;
11124+ aufs_bindex_t bindex;
11125+ struct file *h_file;
11126+ struct dentry *dentry;
11127+ struct au_finfo *finfo;
11128+
11129+ FiMustWriteLock(file);
11130+
4a4d8108 11131+ dentry = file->f_dentry;
027c5e7a
AM
11132+ err = au_d_alive(dentry);
11133+ if (unlikely(err))
11134+ goto out;
11135+
4a4d8108
AM
11136+ finfo = au_fi(file);
11137+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 11138+ atomic_set(&finfo->fi_mmapped, 0);
4a4d8108
AM
11139+ bindex = au_dbstart(dentry);
11140+ h_file = au_h_open(dentry, bindex, flags, file);
11141+ if (IS_ERR(h_file))
11142+ err = PTR_ERR(h_file);
11143+ else {
11144+ au_set_fbstart(file, bindex);
11145+ au_set_h_fptr(file, bindex, h_file);
11146+ au_update_figen(file);
11147+ /* todo: necessary? */
11148+ /* file->f_ra = h_file->f_ra; */
11149+ }
027c5e7a
AM
11150+
11151+out:
4a4d8108 11152+ return err;
1facf9fc 11153+}
11154+
4a4d8108
AM
11155+static int aufs_open_nondir(struct inode *inode __maybe_unused,
11156+ struct file *file)
1facf9fc 11157+{
4a4d8108 11158+ int err;
1308ab2a 11159+ struct super_block *sb;
1facf9fc 11160+
2cbb1c4b 11161+ AuDbg("%.*s, f_flags 0x%x, f_mode 0x%x\n",
4a4d8108
AM
11162+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
11163+ file->f_mode);
1facf9fc 11164+
4a4d8108
AM
11165+ sb = file->f_dentry->d_sb;
11166+ si_read_lock(sb, AuLock_FLUSH);
11167+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
11168+ si_read_unlock(sb);
11169+ return err;
11170+}
1facf9fc 11171+
4a4d8108
AM
11172+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
11173+{
11174+ struct au_finfo *finfo;
11175+ aufs_bindex_t bindex;
1facf9fc 11176+
4a4d8108
AM
11177+ finfo = au_fi(file);
11178+ bindex = finfo->fi_btop;
0c5527e5
AM
11179+ if (bindex >= 0) {
11180+ /* remove me from sb->s_files */
11181+ file_sb_list_del(file);
4a4d8108 11182+ au_set_h_fptr(file, bindex, NULL);
0c5527e5 11183+ }
7f207e10 11184+
4a4d8108
AM
11185+ au_finfo_fin(file);
11186+ return 0;
1facf9fc 11187+}
11188+
4a4d8108
AM
11189+/* ---------------------------------------------------------------------- */
11190+
11191+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 11192+{
1308ab2a 11193+ int err;
4a4d8108
AM
11194+ struct file *h_file;
11195+
11196+ err = 0;
11197+ h_file = au_hf_top(file);
11198+ if (h_file)
11199+ err = vfsub_flush(h_file, id);
11200+ return err;
11201+}
11202+
11203+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
11204+{
11205+ return au_do_flush(file, id, au_do_flush_nondir);
11206+}
11207+
11208+/* ---------------------------------------------------------------------- */
9dbd164d
AM
11209+/*
11210+ * read and write functions acquire [fdi]_rwsem once, but release before
11211+ * mmap_sem. This is because to stop a race condition between mmap(2).
11212+ * Releasing these aufs-rwsem should be safe, no branch-mamagement (by keeping
11213+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in
11214+ * read functions after [fdi]_rwsem are released, but it should be harmless.
11215+ */
4a4d8108
AM
11216+
11217+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
11218+ loff_t *ppos)
11219+{
11220+ ssize_t err;
dece6358 11221+ struct dentry *dentry;
4a4d8108 11222+ struct file *h_file;
dece6358 11223+ struct super_block *sb;
1facf9fc 11224+
dece6358
AM
11225+ dentry = file->f_dentry;
11226+ sb = dentry->d_sb;
e49829fe 11227+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 11228+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
11229+ if (unlikely(err))
11230+ goto out;
1facf9fc 11231+
4a4d8108 11232+ h_file = au_hf_top(file);
9dbd164d
AM
11233+ get_file(h_file);
11234+ di_read_unlock(dentry, AuLock_IR);
11235+ fi_read_unlock(file);
11236+
11237+ /* filedata may be obsoleted by concurrent copyup, but no problem */
4a4d8108
AM
11238+ err = vfsub_read_u(h_file, buf, count, ppos);
11239+ /* todo: necessary? */
11240+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11241+ /* update without lock, I don't think it a problem */
4a4d8108 11242+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11243+ fput(h_file);
1308ab2a 11244+
4f0767ce 11245+out:
dece6358
AM
11246+ si_read_unlock(sb);
11247+ return err;
11248+}
1facf9fc 11249+
e49829fe
JR
11250+/*
11251+ * todo: very ugly
11252+ * it locks both of i_mutex and si_rwsem for read in safe.
11253+ * if the plink maintenance mode continues forever (that is the problem),
11254+ * may loop forever.
11255+ */
11256+static void au_mtx_and_read_lock(struct inode *inode)
11257+{
11258+ int err;
11259+ struct super_block *sb = inode->i_sb;
11260+
11261+ while (1) {
11262+ mutex_lock(&inode->i_mutex);
11263+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
11264+ if (!err)
11265+ break;
11266+ mutex_unlock(&inode->i_mutex);
11267+ si_read_lock(sb, AuLock_NOPLMW);
11268+ si_read_unlock(sb);
11269+ }
11270+}
11271+
4a4d8108
AM
11272+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
11273+ size_t count, loff_t *ppos)
dece6358 11274+{
4a4d8108
AM
11275+ ssize_t err;
11276+ struct au_pin pin;
dece6358 11277+ struct dentry *dentry;
9dbd164d 11278+ struct super_block *sb;
4a4d8108 11279+ struct inode *inode;
4a4d8108
AM
11280+ struct file *h_file;
11281+ char __user *buf = (char __user *)ubuf;
1facf9fc 11282+
dece6358 11283+ dentry = file->f_dentry;
9dbd164d 11284+ sb = dentry->d_sb;
4a4d8108 11285+ inode = dentry->d_inode;
e49829fe 11286+ au_mtx_and_read_lock(inode);
1facf9fc 11287+
4a4d8108
AM
11288+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11289+ if (unlikely(err))
11290+ goto out;
1facf9fc 11291+
4a4d8108
AM
11292+ err = au_ready_to_write(file, -1, &pin);
11293+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11294+ if (unlikely(err)) {
11295+ di_read_unlock(dentry, AuLock_IR);
11296+ fi_write_unlock(file);
11297+ goto out;
11298+ }
1facf9fc 11299+
4a4d8108 11300+ h_file = au_hf_top(file);
9dbd164d 11301+ get_file(h_file);
4a4d8108 11302+ au_unpin(&pin);
9dbd164d
AM
11303+ di_read_unlock(dentry, AuLock_IR);
11304+ fi_write_unlock(file);
11305+
4a4d8108 11306+ err = vfsub_write_u(h_file, buf, count, ppos);
9dbd164d 11307+ ii_write_lock_child(inode);
4a4d8108
AM
11308+ au_cpup_attr_timesizes(inode);
11309+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11310+ ii_write_unlock(inode);
11311+ fput(h_file);
1facf9fc 11312+
4f0767ce 11313+out:
9dbd164d 11314+ si_read_unlock(sb);
4a4d8108 11315+ mutex_unlock(&inode->i_mutex);
dece6358
AM
11316+ return err;
11317+}
1facf9fc 11318+
4a4d8108
AM
11319+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
11320+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 11321+{
4a4d8108
AM
11322+ ssize_t err;
11323+ struct file *file;
11324+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
11325+ loff_t);
1facf9fc 11326+
4a4d8108
AM
11327+ err = security_file_permission(h_file, rw);
11328+ if (unlikely(err))
11329+ goto out;
1facf9fc 11330+
4a4d8108
AM
11331+ err = -ENOSYS;
11332+ func = NULL;
11333+ if (rw == MAY_READ)
11334+ func = h_file->f_op->aio_read;
11335+ else if (rw == MAY_WRITE)
11336+ func = h_file->f_op->aio_write;
11337+ if (func) {
11338+ file = kio->ki_filp;
11339+ kio->ki_filp = h_file;
2cbb1c4b 11340+ lockdep_off();
4a4d8108 11341+ err = func(kio, iov, nv, pos);
2cbb1c4b 11342+ lockdep_on();
4a4d8108
AM
11343+ kio->ki_filp = file;
11344+ } else
11345+ /* currently there is no such fs */
11346+ WARN_ON_ONCE(1);
1facf9fc 11347+
4f0767ce 11348+out:
dece6358
AM
11349+ return err;
11350+}
1facf9fc 11351+
4a4d8108
AM
11352+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
11353+ unsigned long nv, loff_t pos)
1facf9fc 11354+{
4a4d8108
AM
11355+ ssize_t err;
11356+ struct file *file, *h_file;
11357+ struct dentry *dentry;
dece6358 11358+ struct super_block *sb;
1facf9fc 11359+
4a4d8108 11360+ file = kio->ki_filp;
dece6358 11361+ dentry = file->f_dentry;
1308ab2a 11362+ sb = dentry->d_sb;
e49829fe 11363+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11364+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11365+ if (unlikely(err))
11366+ goto out;
11367+
11368+ h_file = au_hf_top(file);
9dbd164d
AM
11369+ get_file(h_file);
11370+ di_read_unlock(dentry, AuLock_IR);
11371+ fi_read_unlock(file);
11372+
4a4d8108
AM
11373+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
11374+ /* todo: necessary? */
11375+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11376+ /* update without lock, I don't think it a problem */
4a4d8108 11377+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11378+ fput(h_file);
1facf9fc 11379+
4f0767ce 11380+out:
4a4d8108 11381+ si_read_unlock(sb);
1308ab2a 11382+ return err;
11383+}
1facf9fc 11384+
4a4d8108
AM
11385+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
11386+ unsigned long nv, loff_t pos)
1308ab2a 11387+{
4a4d8108
AM
11388+ ssize_t err;
11389+ struct au_pin pin;
11390+ struct dentry *dentry;
11391+ struct inode *inode;
4a4d8108 11392+ struct file *file, *h_file;
9dbd164d 11393+ struct super_block *sb;
1308ab2a 11394+
4a4d8108 11395+ file = kio->ki_filp;
1308ab2a 11396+ dentry = file->f_dentry;
9dbd164d 11397+ sb = dentry->d_sb;
1308ab2a 11398+ inode = dentry->d_inode;
e49829fe
JR
11399+ au_mtx_and_read_lock(inode);
11400+
4a4d8108
AM
11401+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11402+ if (unlikely(err))
1308ab2a 11403+ goto out;
1facf9fc 11404+
4a4d8108
AM
11405+ err = au_ready_to_write(file, -1, &pin);
11406+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11407+ if (unlikely(err)) {
11408+ di_read_unlock(dentry, AuLock_IR);
11409+ fi_write_unlock(file);
11410+ goto out;
11411+ }
1facf9fc 11412+
4a4d8108 11413+ h_file = au_hf_top(file);
9dbd164d
AM
11414+ get_file(h_file);
11415+ au_unpin(&pin);
11416+ di_read_unlock(dentry, AuLock_IR);
11417+ fi_write_unlock(file);
11418+
4a4d8108 11419+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
9dbd164d 11420+ ii_write_lock_child(inode);
4a4d8108
AM
11421+ au_cpup_attr_timesizes(inode);
11422+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11423+ ii_write_unlock(inode);
11424+ fput(h_file);
1facf9fc 11425+
4f0767ce 11426+out:
9dbd164d 11427+ si_read_unlock(sb);
4a4d8108 11428+ mutex_unlock(&inode->i_mutex);
dece6358 11429+ return err;
1facf9fc 11430+}
11431+
4a4d8108
AM
11432+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
11433+ struct pipe_inode_info *pipe, size_t len,
11434+ unsigned int flags)
1facf9fc 11435+{
4a4d8108
AM
11436+ ssize_t err;
11437+ struct file *h_file;
11438+ struct dentry *dentry;
dece6358 11439+ struct super_block *sb;
1facf9fc 11440+
dece6358 11441+ dentry = file->f_dentry;
dece6358 11442+ sb = dentry->d_sb;
e49829fe 11443+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11444+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11445+ if (unlikely(err))
dece6358 11446+ goto out;
1facf9fc 11447+
4a4d8108
AM
11448+ err = -EINVAL;
11449+ h_file = au_hf_top(file);
9dbd164d 11450+ get_file(h_file);
4a4d8108 11451+ if (au_test_loopback_kthread()) {
87a755f4
AM
11452+ au_warn_loopback(h_file->f_dentry->d_sb);
11453+ if (file->f_mapping != h_file->f_mapping) {
11454+ file->f_mapping = h_file->f_mapping;
11455+ smp_mb(); /* unnecessary? */
11456+ }
1308ab2a 11457+ }
9dbd164d
AM
11458+ di_read_unlock(dentry, AuLock_IR);
11459+ fi_read_unlock(file);
11460+
4a4d8108
AM
11461+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
11462+ /* todo: necessasry? */
11463+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11464+ /* update without lock, I don't think it a problem */
4a4d8108 11465+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11466+ fput(h_file);
1facf9fc 11467+
4f0767ce 11468+out:
4a4d8108 11469+ si_read_unlock(sb);
dece6358 11470+ return err;
1facf9fc 11471+}
11472+
4a4d8108
AM
11473+static ssize_t
11474+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
11475+ size_t len, unsigned int flags)
1facf9fc 11476+{
4a4d8108
AM
11477+ ssize_t err;
11478+ struct au_pin pin;
11479+ struct dentry *dentry;
11480+ struct inode *inode;
4a4d8108 11481+ struct file *h_file;
9dbd164d 11482+ struct super_block *sb;
1facf9fc 11483+
4a4d8108 11484+ dentry = file->f_dentry;
9dbd164d 11485+ sb = dentry->d_sb;
4a4d8108 11486+ inode = dentry->d_inode;
e49829fe 11487+ au_mtx_and_read_lock(inode);
9dbd164d 11488+
4a4d8108
AM
11489+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11490+ if (unlikely(err))
11491+ goto out;
1facf9fc 11492+
4a4d8108
AM
11493+ err = au_ready_to_write(file, -1, &pin);
11494+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11495+ if (unlikely(err)) {
11496+ di_read_unlock(dentry, AuLock_IR);
11497+ fi_write_unlock(file);
11498+ goto out;
11499+ }
1facf9fc 11500+
4a4d8108 11501+ h_file = au_hf_top(file);
9dbd164d 11502+ get_file(h_file);
4a4d8108 11503+ au_unpin(&pin);
9dbd164d
AM
11504+ di_read_unlock(dentry, AuLock_IR);
11505+ fi_write_unlock(file);
11506+
4a4d8108 11507+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
9dbd164d 11508+ ii_write_lock_child(inode);
4a4d8108
AM
11509+ au_cpup_attr_timesizes(inode);
11510+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11511+ ii_write_unlock(inode);
11512+ fput(h_file);
1facf9fc 11513+
4f0767ce 11514+out:
9dbd164d 11515+ si_read_unlock(sb);
4a4d8108
AM
11516+ mutex_unlock(&inode->i_mutex);
11517+ return err;
11518+}
1facf9fc 11519+
4a4d8108
AM
11520+/* ---------------------------------------------------------------------- */
11521+
9dbd164d
AM
11522+/*
11523+ * The locking order around current->mmap_sem.
11524+ * - in most and regular cases
11525+ * file I/O syscall -- aufs_read() or something
11526+ * -- si_rwsem for read -- mmap_sem
11527+ * (Note that [fdi]i_rwsem are released before mmap_sem).
11528+ * - in mmap case
11529+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem
11530+ * This AB-BA order is definitly bad, but is not a problem since "si_rwsem for
11531+ * read" allows muliple processes to acquire it and [fdi]i_rwsem are not held in
11532+ * file I/O. Aufs needs to stop lockdep in aufs_mmap() though.
11533+ * It means that when aufs acquires si_rwsem for write, the process should never
11534+ * acquire mmap_sem.
11535+ *
11536+ * Actually aufs_readdir() holds [fdi]i_rwsem before mmap_sem, but this is not a
11537+ * problem either since any directory is not able to be mmap-ed.
11538+ * The similar scenario is applied to aufs_readlink() too.
11539+ */
11540+
2dfbb274
AM
11541+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
11542+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
11543+
11544+static unsigned long au_arch_prot_conv(unsigned long flags)
11545+{
11546+ /* currently ppc64 only */
11547+#ifdef CONFIG_PPC64
11548+ /* cf. linux/arch/powerpc/include/asm/mman.h */
11549+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
11550+ return AuConv_VM_PROT(flags, SAO);
11551+#else
11552+ AuDebugOn(arch_calc_vm_prot_bits(-1));
11553+ return 0;
11554+#endif
11555+}
11556+
11557+static unsigned long au_prot_conv(unsigned long flags)
11558+{
11559+ return AuConv_VM_PROT(flags, READ)
11560+ | AuConv_VM_PROT(flags, WRITE)
11561+ | AuConv_VM_PROT(flags, EXEC)
11562+ | au_arch_prot_conv(flags);
11563+}
11564+
11565+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
11566+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
11567+
11568+static unsigned long au_flag_conv(unsigned long flags)
11569+{
11570+ return AuConv_VM_MAP(flags, GROWSDOWN)
11571+ | AuConv_VM_MAP(flags, DENYWRITE)
11572+ | AuConv_VM_MAP(flags, EXECUTABLE)
11573+ | AuConv_VM_MAP(flags, LOCKED);
11574+}
11575+
9dbd164d 11576+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 11577+{
4a4d8108
AM
11578+ int err;
11579+ aufs_bindex_t bstart;
11580+ const unsigned char wlock
9dbd164d 11581+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
4a4d8108
AM
11582+ struct dentry *dentry;
11583+ struct super_block *sb;
9dbd164d
AM
11584+ struct file *h_file;
11585+ struct au_branch *br;
11586+ struct au_pin pin;
11587+
11588+ AuDbgVmRegion(file, vma);
1308ab2a 11589+
4a4d8108
AM
11590+ dentry = file->f_dentry;
11591+ sb = dentry->d_sb;
9dbd164d 11592+ lockdep_off();
e49829fe 11593+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108
AM
11594+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11595+ if (unlikely(err))
11596+ goto out;
11597+
4a4d8108 11598+ if (wlock) {
4a4d8108
AM
11599+ err = au_ready_to_write(file, -1, &pin);
11600+ di_write_unlock(dentry);
9dbd164d
AM
11601+ if (unlikely(err)) {
11602+ fi_write_unlock(file);
11603+ goto out;
11604+ }
4a4d8108
AM
11605+ au_unpin(&pin);
11606+ } else
11607+ di_write_unlock(dentry);
9dbd164d 11608+
4a4d8108 11609+ bstart = au_fbstart(file);
9dbd164d
AM
11610+ br = au_sbr(sb, bstart);
11611+ h_file = au_hf_top(file);
11612+ get_file(h_file);
2cbb1c4b 11613+ au_set_mmapped(file);
4a4d8108 11614+ fi_write_unlock(file);
9dbd164d 11615+ lockdep_on();
1308ab2a 11616+
9dbd164d 11617+ au_vm_file_reset(vma, h_file);
2dfbb274
AM
11618+ err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags),
11619+ au_flag_conv(vma->vm_flags));
9dbd164d
AM
11620+ if (!err)
11621+ err = h_file->f_op->mmap(h_file, vma);
2cbb1c4b
JR
11622+ if (unlikely(err))
11623+ goto out_reset;
4a4d8108 11624+
2cbb1c4b 11625+ au_vm_prfile_set(vma, file);
4a4d8108 11626+ /* update without lock, I don't think it a problem */
2cbb1c4b 11627+ fsstack_copy_attr_atime(file->f_dentry->d_inode,
9dbd164d 11628+ h_file->f_dentry->d_inode);
2cbb1c4b 11629+ goto out_fput; /* success */
4a4d8108 11630+
2cbb1c4b
JR
11631+out_reset:
11632+ au_unset_mmapped(file);
11633+ au_vm_file_reset(vma, file);
11634+out_fput:
9dbd164d
AM
11635+ fput(h_file);
11636+ lockdep_off();
4f0767ce 11637+out:
9dbd164d
AM
11638+ si_read_unlock(sb);
11639+ lockdep_on();
11640+ AuTraceErr(err);
4a4d8108
AM
11641+ return err;
11642+}
11643+
11644+/* ---------------------------------------------------------------------- */
11645+
1e00d052
AM
11646+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end,
11647+ int datasync)
4a4d8108
AM
11648+{
11649+ int err;
11650+ struct au_pin pin;
b752ccd1 11651+ struct dentry *dentry;
4a4d8108
AM
11652+ struct inode *inode;
11653+ struct file *h_file;
11654+ struct super_block *sb;
11655+
b752ccd1 11656+ dentry = file->f_dentry;
4a4d8108 11657+ inode = dentry->d_inode;
4a4d8108 11658+ sb = dentry->d_sb;
1e00d052 11659+ mutex_lock(&inode->i_mutex);
e49829fe
JR
11660+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
11661+ if (unlikely(err))
11662+ goto out;
4a4d8108
AM
11663+
11664+ err = 0; /* -EBADF; */ /* posix? */
11665+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
e49829fe 11666+ goto out_si;
4a4d8108
AM
11667+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11668+ if (unlikely(err))
e49829fe 11669+ goto out_si;
4a4d8108
AM
11670+
11671+ err = au_ready_to_write(file, -1, &pin);
11672+ di_downgrade_lock(dentry, AuLock_IR);
11673+ if (unlikely(err))
11674+ goto out_unlock;
11675+ au_unpin(&pin);
11676+
11677+ err = -EINVAL;
11678+ h_file = au_hf_top(file);
53392da6
AM
11679+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
11680+ au_cpup_attr_timesizes(inode);
4a4d8108 11681+
4f0767ce 11682+out_unlock:
4a4d8108 11683+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 11684+ fi_write_unlock(file);
e49829fe 11685+out_si:
953406b4 11686+ si_read_unlock(sb);
e49829fe 11687+out:
1e00d052 11688+ mutex_unlock(&inode->i_mutex);
4a4d8108 11689+ return err;
dece6358
AM
11690+}
11691+
4a4d8108
AM
11692+/* no one supports this operation, currently */
11693+#if 0
11694+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 11695+{
4a4d8108
AM
11696+ int err;
11697+ struct au_pin pin;
1308ab2a 11698+ struct dentry *dentry;
4a4d8108
AM
11699+ struct inode *inode;
11700+ struct file *file, *h_file;
1308ab2a 11701+
4a4d8108 11702+ file = kio->ki_filp;
1308ab2a 11703+ dentry = file->f_dentry;
4a4d8108 11704+ inode = dentry->d_inode;
e49829fe 11705+ au_mtx_and_read_lock(inode);
4a4d8108
AM
11706+
11707+ err = 0; /* -EBADF; */ /* posix? */
11708+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
11709+ goto out;
11710+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11711+ if (unlikely(err))
1308ab2a 11712+ goto out;
11713+
4a4d8108
AM
11714+ err = au_ready_to_write(file, -1, &pin);
11715+ di_downgrade_lock(dentry, AuLock_IR);
11716+ if (unlikely(err))
11717+ goto out_unlock;
11718+ au_unpin(&pin);
1308ab2a 11719+
4a4d8108
AM
11720+ err = -ENOSYS;
11721+ h_file = au_hf_top(file);
11722+ if (h_file->f_op && h_file->f_op->aio_fsync) {
11723+ struct dentry *h_d;
11724+ struct mutex *h_mtx;
1308ab2a 11725+
4a4d8108
AM
11726+ h_d = h_file->f_dentry;
11727+ h_mtx = &h_d->d_inode->i_mutex;
11728+ if (!is_sync_kiocb(kio)) {
11729+ get_file(h_file);
11730+ fput(file);
11731+ }
11732+ kio->ki_filp = h_file;
11733+ err = h_file->f_op->aio_fsync(kio, datasync);
11734+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
11735+ if (!err)
11736+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
11737+ /*ignore*/
11738+ au_cpup_attr_timesizes(inode);
11739+ mutex_unlock(h_mtx);
11740+ }
1308ab2a 11741+
4f0767ce 11742+out_unlock:
4a4d8108
AM
11743+ di_read_unlock(dentry, AuLock_IR);
11744+ fi_write_unlock(file);
4f0767ce 11745+out:
e49829fe 11746+ si_read_unlock(inode->sb);
4a4d8108
AM
11747+ mutex_unlock(&inode->i_mutex);
11748+ return err;
dece6358 11749+}
4a4d8108 11750+#endif
dece6358 11751+
4a4d8108 11752+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 11753+{
4a4d8108
AM
11754+ int err;
11755+ struct file *h_file;
11756+ struct dentry *dentry;
11757+ struct super_block *sb;
1308ab2a 11758+
4a4d8108
AM
11759+ dentry = file->f_dentry;
11760+ sb = dentry->d_sb;
e49829fe 11761+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11762+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11763+ if (unlikely(err))
11764+ goto out;
11765+
11766+ h_file = au_hf_top(file);
11767+ if (h_file->f_op && h_file->f_op->fasync)
11768+ err = h_file->f_op->fasync(fd, h_file, flag);
11769+
11770+ di_read_unlock(dentry, AuLock_IR);
11771+ fi_read_unlock(file);
1308ab2a 11772+
4f0767ce 11773+out:
4a4d8108 11774+ si_read_unlock(sb);
1308ab2a 11775+ return err;
dece6358 11776+}
4a4d8108
AM
11777+
11778+/* ---------------------------------------------------------------------- */
11779+
11780+/* no one supports this operation, currently */
11781+#if 0
11782+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
11783+ size_t len, loff_t *pos , int more)
11784+{
11785+}
11786+#endif
11787+
11788+/* ---------------------------------------------------------------------- */
11789+
11790+const struct file_operations aufs_file_fop = {
11791+ .owner = THIS_MODULE,
2cbb1c4b 11792+
027c5e7a 11793+ .llseek = default_llseek,
4a4d8108
AM
11794+
11795+ .read = aufs_read,
11796+ .write = aufs_write,
11797+ .aio_read = aufs_aio_read,
11798+ .aio_write = aufs_aio_write,
11799+#ifdef CONFIG_AUFS_POLL
11800+ .poll = aufs_poll,
11801+#endif
11802+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
11803+#ifdef CONFIG_COMPAT
11804+ .compat_ioctl = aufs_ioctl_nondir, /* same */
11805+#endif
4a4d8108
AM
11806+ .mmap = aufs_mmap,
11807+ .open = aufs_open_nondir,
11808+ .flush = aufs_flush_nondir,
11809+ .release = aufs_release_nondir,
11810+ .fsync = aufs_fsync_nondir,
11811+ /* .aio_fsync = aufs_aio_fsync_nondir, */
11812+ .fasync = aufs_fasync,
11813+ /* .sendpage = aufs_sendpage, */
11814+ .splice_write = aufs_splice_write,
11815+ .splice_read = aufs_splice_read,
11816+#if 0
11817+ .aio_splice_write = aufs_aio_splice_write,
11818+ .aio_splice_read = aufs_aio_splice_read
11819+#endif
11820+};
7f207e10
AM
11821diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
11822--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 11823+++ linux/fs/aufs/f_op_sp.c 2012-08-26 08:39:00.760508065 +0200
0c3ec466 11824@@ -0,0 +1,295 @@
1308ab2a 11825+/*
f6c5ef8b 11826+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1308ab2a 11827+ *
11828+ * This program, aufs is free software; you can redistribute it and/or modify
11829+ * it under the terms of the GNU General Public License as published by
11830+ * the Free Software Foundation; either version 2 of the License, or
11831+ * (at your option) any later version.
11832+ *
11833+ * This program is distributed in the hope that it will be useful,
11834+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11835+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11836+ * GNU General Public License for more details.
11837+ *
11838+ * You should have received a copy of the GNU General Public License
11839+ * along with this program; if not, write to the Free Software
11840+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11841+ */
dece6358 11842+
1308ab2a 11843+/*
4a4d8108
AM
11844+ * file operations for special files.
11845+ * while they exist in aufs virtually,
11846+ * their file I/O is handled out of aufs.
1308ab2a 11847+ */
11848+
4a4d8108 11849+#include "aufs.h"
1308ab2a 11850+
4a4d8108
AM
11851+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
11852+ unsigned long nv, loff_t pos)
dece6358 11853+{
4a4d8108
AM
11854+ ssize_t err;
11855+ aufs_bindex_t bstart;
11856+ unsigned char wbr;
11857+ struct file *file, *h_file;
11858+ struct super_block *sb;
1308ab2a 11859+
4a4d8108
AM
11860+ file = kio->ki_filp;
11861+ sb = file->f_dentry->d_sb;
11862+ si_read_lock(sb, AuLock_FLUSH);
11863+ fi_read_lock(file);
11864+ bstart = au_fbstart(file);
11865+ h_file = au_hf_top(file);
11866+ fi_read_unlock(file);
11867+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
11868+ si_read_unlock(sb);
11869+
11870+ /* do not change the file in kio */
11871+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
11872+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
11873+ if (err > 0 && wbr)
11874+ file_accessed(h_file);
11875+
11876+ return err;
11877+}
11878+
11879+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
11880+ unsigned long nv, loff_t pos)
11881+{
11882+ ssize_t err;
11883+ aufs_bindex_t bstart;
11884+ unsigned char wbr;
11885+ struct super_block *sb;
11886+ struct file *file, *h_file;
11887+
11888+ file = kio->ki_filp;
11889+ sb = file->f_dentry->d_sb;
11890+ si_read_lock(sb, AuLock_FLUSH);
11891+ fi_read_lock(file);
11892+ bstart = au_fbstart(file);
11893+ h_file = au_hf_top(file);
11894+ fi_read_unlock(file);
11895+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
11896+ si_read_unlock(sb);
11897+
11898+ /* do not change the file in kio */
11899+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
11900+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
4a4d8108
AM
11901+ return err;
11902+}
11903+
11904+/* ---------------------------------------------------------------------- */
11905+
11906+static int aufs_release_sp(struct inode *inode, struct file *file)
11907+{
11908+ int err;
11909+ struct file *h_file;
11910+
11911+ fi_read_lock(file);
11912+ h_file = au_hf_top(file);
11913+ fi_read_unlock(file);
11914+ /* close this fifo in aufs */
11915+ err = h_file->f_op->release(inode, file); /* ignore */
11916+ aufs_release_nondir(inode, file); /* ignore */
11917+ return err;
11918+}
11919+
11920+/* ---------------------------------------------------------------------- */
11921+
11922+/* currently, support only FIFO */
4f0767ce
JR
11923+enum {
11924+ AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
11925+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
11926+ AuSp_Last
11927+};
4a4d8108
AM
11928+static int aufs_open_sp(struct inode *inode, struct file *file);
11929+static struct au_sp_fop {
11930+ int done;
11931+ struct file_operations fop; /* not 'const' */
11932+ spinlock_t spin;
11933+} au_sp_fop[AuSp_Last] = {
11934+ [AuSp_FIFO] = {
11935+ .fop = {
11936+ .owner = THIS_MODULE,
11937+ .open = aufs_open_sp
11938+ }
11939+ }
11940+};
11941+
11942+static void au_init_fop_sp(struct file *file)
11943+{
11944+ struct au_sp_fop *p;
11945+ int i;
11946+ struct file *h_file;
11947+
11948+ p = au_sp_fop;
11949+ if (unlikely(!p->done)) {
11950+ /* initialize first time only */
11951+ static DEFINE_SPINLOCK(spin);
11952+
11953+ spin_lock(&spin);
11954+ if (!p->done) {
11955+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
11956+ != AuSp_Last);
11957+ for (i = 0; i < AuSp_Last; i++)
11958+ spin_lock_init(&p[i].spin);
11959+ p->done = 1;
11960+ }
11961+ spin_unlock(&spin);
11962+ }
11963+
11964+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
11965+ case FMODE_READ:
11966+ i = AuSp_FIFO_R;
11967+ break;
11968+ case FMODE_WRITE:
11969+ i = AuSp_FIFO_W;
11970+ break;
11971+ case FMODE_READ | FMODE_WRITE:
11972+ i = AuSp_FIFO_RW;
11973+ break;
11974+ default:
11975+ BUG();
11976+ }
11977+
11978+ p += i;
11979+ if (unlikely(!p->done)) {
11980+ /* initialize first time only */
11981+ h_file = au_hf_top(file);
11982+ spin_lock(&p->spin);
11983+ if (!p->done) {
11984+ p->fop = *h_file->f_op;
11985+ p->fop.owner = THIS_MODULE;
11986+ if (p->fop.aio_read)
11987+ p->fop.aio_read = aufs_aio_read_sp;
11988+ if (p->fop.aio_write)
11989+ p->fop.aio_write = aufs_aio_write_sp;
11990+ p->fop.release = aufs_release_sp;
11991+ p->done = 1;
11992+ }
11993+ spin_unlock(&p->spin);
11994+ }
11995+ file->f_op = &p->fop;
11996+}
11997+
11998+static int au_cpup_sp(struct dentry *dentry)
11999+{
12000+ int err;
12001+ aufs_bindex_t bcpup;
12002+ struct au_pin pin;
12003+ struct au_wr_dir_args wr_dir_args = {
12004+ .force_btgt = -1,
12005+ .flags = 0
12006+ };
12007+
12008+ AuDbg("%.*s\n", AuDLNPair(dentry));
12009+
12010+ di_read_unlock(dentry, AuLock_IR);
12011+ di_write_lock_child(dentry);
12012+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
12013+ if (unlikely(err < 0))
12014+ goto out;
12015+ bcpup = err;
12016+ err = 0;
12017+ if (bcpup == au_dbstart(dentry))
12018+ goto out; /* success */
12019+
12020+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
12021+ AuPin_MNT_WRITE);
12022+ if (!err) {
12023+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
12024+ au_unpin(&pin);
12025+ }
12026+
4f0767ce 12027+out:
4a4d8108
AM
12028+ di_downgrade_lock(dentry, AuLock_IR);
12029+ return err;
12030+}
12031+
12032+static int au_do_open_sp(struct file *file, int flags)
12033+{
12034+ int err;
12035+ struct dentry *dentry;
12036+ struct super_block *sb;
12037+ struct file *h_file;
12038+ struct inode *h_inode;
12039+
12040+ dentry = file->f_dentry;
12041+ AuDbg("%.*s\n", AuDLNPair(dentry));
12042+
12043+ /*
12044+ * try copying-up.
12045+ * operate on the ro branch is not an error.
12046+ */
12047+ au_cpup_sp(dentry); /* ignore */
12048+
12049+ /* prepare h_file */
12050+ err = au_do_open_nondir(file, vfsub_file_flags(file));
12051+ if (unlikely(err))
12052+ goto out;
12053+
12054+ sb = dentry->d_sb;
12055+ h_file = au_hf_top(file);
12056+ h_inode = h_file->f_dentry->d_inode;
12057+ di_read_unlock(dentry, AuLock_IR);
12058+ fi_write_unlock(file);
12059+ si_read_unlock(sb);
12060+ /* open this fifo in aufs */
12061+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
12062+ si_noflush_read_lock(sb);
12063+ fi_write_lock(file);
12064+ di_read_lock_child(dentry, AuLock_IR);
12065+ if (!err)
12066+ au_init_fop_sp(file);
4a4d8108 12067+
4f0767ce 12068+out:
4a4d8108
AM
12069+ return err;
12070+}
12071+
12072+static int aufs_open_sp(struct inode *inode, struct file *file)
12073+{
12074+ int err;
12075+ struct super_block *sb;
12076+
12077+ sb = file->f_dentry->d_sb;
12078+ si_read_lock(sb, AuLock_FLUSH);
12079+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
12080+ si_read_unlock(sb);
12081+ return err;
12082+}
12083+
12084+/* ---------------------------------------------------------------------- */
12085+
12086+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
12087+{
12088+ init_special_inode(inode, mode, rdev);
12089+
12090+ switch (mode & S_IFMT) {
12091+ case S_IFIFO:
12092+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
12093+ /*FALLTHROUGH*/
12094+ case S_IFCHR:
12095+ case S_IFBLK:
12096+ case S_IFSOCK:
12097+ break;
12098+ default:
12099+ AuDebugOn(1);
12100+ }
12101+}
12102+
12103+int au_special_file(umode_t mode)
12104+{
12105+ int ret;
12106+
12107+ ret = 0;
12108+ switch (mode & S_IFMT) {
12109+ case S_IFIFO:
12110+#if 0
12111+ case S_IFCHR:
12112+ case S_IFBLK:
12113+ case S_IFSOCK:
12114+#endif
12115+ ret = 1;
12116+ }
12117+
12118+ return ret;
12119+}
7f207e10
AM
12120diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
12121--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 12122+++ linux/fs/aufs/fstype.h 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 12123@@ -0,0 +1,496 @@
4a4d8108 12124+/*
f6c5ef8b 12125+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
12126+ *
12127+ * This program, aufs is free software; you can redistribute it and/or modify
12128+ * it under the terms of the GNU General Public License as published by
12129+ * the Free Software Foundation; either version 2 of the License, or
12130+ * (at your option) any later version.
12131+ *
12132+ * This program is distributed in the hope that it will be useful,
12133+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12134+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12135+ * GNU General Public License for more details.
12136+ *
12137+ * You should have received a copy of the GNU General Public License
12138+ * along with this program; if not, write to the Free Software
12139+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12140+ */
12141+
12142+/*
12143+ * judging filesystem type
12144+ */
12145+
12146+#ifndef __AUFS_FSTYPE_H__
12147+#define __AUFS_FSTYPE_H__
12148+
12149+#ifdef __KERNEL__
12150+
12151+#include <linux/fs.h>
12152+#include <linux/magic.h>
12153+#include <linux/romfs_fs.h>
4a4d8108
AM
12154+
12155+static inline int au_test_aufs(struct super_block *sb)
12156+{
12157+ return sb->s_magic == AUFS_SUPER_MAGIC;
12158+}
12159+
12160+static inline const char *au_sbtype(struct super_block *sb)
12161+{
12162+ return sb->s_type->name;
12163+}
1308ab2a 12164+
12165+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
12166+{
12167+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
12168+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
12169+#else
12170+ return 0;
12171+#endif
12172+}
12173+
1308ab2a 12174+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 12175+{
1308ab2a 12176+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
12177+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
12178+#else
12179+ return 0;
12180+#endif
12181+}
12182+
1308ab2a 12183+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 12184+{
1308ab2a 12185+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
12186+ return sb->s_magic == CRAMFS_MAGIC;
12187+#endif
12188+ return 0;
12189+}
12190+
12191+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
12192+{
12193+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
12194+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
12195+#else
12196+ return 0;
12197+#endif
12198+}
12199+
1308ab2a 12200+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 12201+{
1308ab2a 12202+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
12203+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
12204+#else
12205+ return 0;
12206+#endif
12207+}
12208+
1308ab2a 12209+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 12210+{
1308ab2a 12211+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
12212+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
12213+#else
12214+ return 0;
12215+#endif
12216+}
12217+
1308ab2a 12218+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 12219+{
1308ab2a 12220+#ifdef CONFIG_TMPFS
12221+ return sb->s_magic == TMPFS_MAGIC;
12222+#else
12223+ return 0;
dece6358 12224+#endif
dece6358
AM
12225+}
12226+
1308ab2a 12227+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 12228+{
1308ab2a 12229+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
12230+ return !strcmp(au_sbtype(sb), "ecryptfs");
12231+#else
12232+ return 0;
12233+#endif
1facf9fc 12234+}
12235+
1308ab2a 12236+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 12237+{
1308ab2a 12238+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
12239+ return sb->s_magic == SMB_SUPER_MAGIC;
12240+#else
12241+ return 0;
1facf9fc 12242+#endif
1facf9fc 12243+}
12244+
1308ab2a 12245+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 12246+{
1308ab2a 12247+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
12248+ return sb->s_magic == OCFS2_SUPER_MAGIC;
12249+#else
12250+ return 0;
12251+#endif
1facf9fc 12252+}
12253+
1308ab2a 12254+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 12255+{
1308ab2a 12256+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
12257+ return sb->s_magic == DLMFS_MAGIC;
12258+#else
12259+ return 0;
12260+#endif
1facf9fc 12261+}
12262+
1308ab2a 12263+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 12264+{
1308ab2a 12265+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
12266+ return sb->s_magic == CODA_SUPER_MAGIC;
12267+#else
12268+ return 0;
12269+#endif
12270+}
12271+
12272+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
12273+{
12274+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
12275+ return sb->s_magic == V9FS_MAGIC;
12276+#else
12277+ return 0;
12278+#endif
12279+}
12280+
12281+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
12282+{
12283+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
12284+ return sb->s_magic == EXT4_SUPER_MAGIC;
12285+#else
12286+ return 0;
12287+#endif
12288+}
12289+
12290+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
12291+{
12292+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
12293+ return !strcmp(au_sbtype(sb), "sysv");
12294+#else
12295+ return 0;
12296+#endif
12297+}
12298+
12299+static inline int au_test_ramfs(struct super_block *sb)
12300+{
12301+ return sb->s_magic == RAMFS_MAGIC;
12302+}
12303+
12304+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
12305+{
12306+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
12307+ return sb->s_magic == UBIFS_SUPER_MAGIC;
12308+#else
12309+ return 0;
12310+#endif
12311+}
12312+
12313+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
12314+{
12315+#ifdef CONFIG_PROC_FS
12316+ return sb->s_magic == PROC_SUPER_MAGIC;
12317+#else
12318+ return 0;
12319+#endif
12320+}
12321+
12322+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
12323+{
12324+#ifdef CONFIG_SYSFS
12325+ return sb->s_magic == SYSFS_MAGIC;
12326+#else
12327+ return 0;
12328+#endif
12329+}
12330+
12331+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
12332+{
12333+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
12334+ return sb->s_magic == CONFIGFS_MAGIC;
12335+#else
12336+ return 0;
12337+#endif
12338+}
12339+
12340+static inline int au_test_minix(struct super_block *sb __maybe_unused)
12341+{
12342+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
12343+ return sb->s_magic == MINIX3_SUPER_MAGIC
12344+ || sb->s_magic == MINIX2_SUPER_MAGIC
12345+ || sb->s_magic == MINIX2_SUPER_MAGIC2
12346+ || sb->s_magic == MINIX_SUPER_MAGIC
12347+ || sb->s_magic == MINIX_SUPER_MAGIC2;
12348+#else
12349+ return 0;
12350+#endif
12351+}
12352+
12353+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
12354+{
12355+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
12356+ return sb->s_magic == CIFS_MAGIC_NUMBER;
12357+#else
12358+ return 0;
12359+#endif
12360+}
12361+
12362+static inline int au_test_fat(struct super_block *sb __maybe_unused)
12363+{
12364+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
12365+ return sb->s_magic == MSDOS_SUPER_MAGIC;
12366+#else
12367+ return 0;
12368+#endif
12369+}
12370+
12371+static inline int au_test_msdos(struct super_block *sb)
12372+{
12373+ return au_test_fat(sb);
12374+}
12375+
12376+static inline int au_test_vfat(struct super_block *sb)
12377+{
12378+ return au_test_fat(sb);
12379+}
12380+
12381+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
12382+{
12383+#ifdef CONFIG_SECURITYFS
12384+ return sb->s_magic == SECURITYFS_MAGIC;
12385+#else
12386+ return 0;
12387+#endif
12388+}
12389+
12390+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
12391+{
12392+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
12393+ return sb->s_magic == SQUASHFS_MAGIC;
12394+#else
12395+ return 0;
12396+#endif
12397+}
12398+
12399+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
12400+{
12401+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
12402+ return sb->s_magic == BTRFS_SUPER_MAGIC;
12403+#else
12404+ return 0;
12405+#endif
12406+}
12407+
12408+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
12409+{
12410+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
12411+ return sb->s_magic == XENFS_SUPER_MAGIC;
12412+#else
12413+ return 0;
12414+#endif
12415+}
12416+
12417+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
12418+{
12419+#ifdef CONFIG_DEBUG_FS
12420+ return sb->s_magic == DEBUGFS_MAGIC;
12421+#else
12422+ return 0;
12423+#endif
12424+}
12425+
12426+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
12427+{
12428+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
12429+ return sb->s_magic == NILFS_SUPER_MAGIC;
12430+#else
12431+ return 0;
12432+#endif
12433+}
12434+
4a4d8108
AM
12435+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
12436+{
12437+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
12438+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
12439+#else
12440+ return 0;
12441+#endif
12442+}
12443+
1308ab2a 12444+/* ---------------------------------------------------------------------- */
12445+/*
12446+ * they can't be an aufs branch.
12447+ */
12448+static inline int au_test_fs_unsuppoted(struct super_block *sb)
12449+{
12450+ return
12451+#ifndef CONFIG_AUFS_BR_RAMFS
12452+ au_test_ramfs(sb) ||
12453+#endif
12454+ au_test_procfs(sb)
12455+ || au_test_sysfs(sb)
12456+ || au_test_configfs(sb)
12457+ || au_test_debugfs(sb)
12458+ || au_test_securityfs(sb)
12459+ || au_test_xenfs(sb)
12460+ || au_test_ecryptfs(sb)
12461+ /* || !strcmp(au_sbtype(sb), "unionfs") */
12462+ || au_test_aufs(sb); /* will be supported in next version */
12463+}
12464+
12465+/*
12466+ * If the filesystem supports NFS-export, then it has to support NULL as
12467+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
12468+ * We can apply this principle when we handle a lower filesystem.
12469+ */
12470+static inline int au_test_fs_null_nd(struct super_block *sb)
12471+{
12472+ return !!sb->s_export_op;
12473+}
12474+
12475+static inline int au_test_fs_remote(struct super_block *sb)
12476+{
12477+ return !au_test_tmpfs(sb)
12478+#ifdef CONFIG_AUFS_BR_RAMFS
12479+ && !au_test_ramfs(sb)
12480+#endif
12481+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
12482+}
12483+
12484+/* ---------------------------------------------------------------------- */
12485+
12486+/*
12487+ * Note: these functions (below) are created after reading ->getattr() in all
12488+ * filesystems under linux/fs. it means we have to do so in every update...
12489+ */
12490+
12491+/*
12492+ * some filesystems require getattr to refresh the inode attributes before
12493+ * referencing.
12494+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
12495+ * and leave the work for d_revalidate()
12496+ */
12497+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
12498+{
12499+ return au_test_nfs(sb)
12500+ || au_test_fuse(sb)
12501+ /* || au_test_smbfs(sb) */ /* untested */
12502+ /* || au_test_ocfs2(sb) */ /* untested */
12503+ /* || au_test_btrfs(sb) */ /* untested */
12504+ /* || au_test_coda(sb) */ /* untested */
12505+ /* || au_test_v9fs(sb) */ /* untested */
12506+ ;
12507+}
12508+
12509+/*
12510+ * filesystems which don't maintain i_size or i_blocks.
12511+ */
12512+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
12513+{
12514+ return au_test_xfs(sb)
4a4d8108
AM
12515+ || au_test_btrfs(sb)
12516+ || au_test_ubifs(sb)
12517+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 12518+ /* || au_test_ext4(sb) */ /* untested */
12519+ /* || au_test_ocfs2(sb) */ /* untested */
12520+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
12521+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 12522+ /* || au_test_minix(sb) */ /* untested */
12523+ ;
12524+}
12525+
12526+/*
12527+ * filesystems which don't store the correct value in some of their inode
12528+ * attributes.
12529+ */
12530+static inline int au_test_fs_bad_iattr(struct super_block *sb)
12531+{
12532+ return au_test_fs_bad_iattr_size(sb)
12533+ /* || au_test_cifs(sb) */ /* untested */
12534+ || au_test_fat(sb)
12535+ || au_test_msdos(sb)
12536+ || au_test_vfat(sb);
1facf9fc 12537+}
12538+
12539+/* they don't check i_nlink in link(2) */
12540+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
12541+{
12542+ return au_test_tmpfs(sb)
12543+#ifdef CONFIG_AUFS_BR_RAMFS
12544+ || au_test_ramfs(sb)
12545+#endif
4a4d8108
AM
12546+ || au_test_ubifs(sb)
12547+ || au_test_btrfs(sb)
12548+ || au_test_hfsplus(sb);
1facf9fc 12549+}
12550+
12551+/*
12552+ * filesystems which sets S_NOATIME and S_NOCMTIME.
12553+ */
12554+static inline int au_test_fs_notime(struct super_block *sb)
12555+{
12556+ return au_test_nfs(sb)
12557+ || au_test_fuse(sb)
dece6358 12558+ || au_test_ubifs(sb)
1facf9fc 12559+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 12560+ ;
12561+}
12562+
12563+/*
12564+ * filesystems which requires replacing i_mapping.
12565+ */
12566+static inline int au_test_fs_bad_mapping(struct super_block *sb)
12567+{
dece6358
AM
12568+ return au_test_fuse(sb)
12569+ || au_test_ubifs(sb);
1facf9fc 12570+}
12571+
12572+/* temporary support for i#1 in cramfs */
12573+static inline int au_test_fs_unique_ino(struct inode *inode)
12574+{
12575+ if (au_test_cramfs(inode->i_sb))
12576+ return inode->i_ino != 1;
12577+ return 1;
12578+}
12579+
12580+/* ---------------------------------------------------------------------- */
12581+
12582+/*
12583+ * the filesystem where the xino files placed must support i/o after unlink and
12584+ * maintain i_size and i_blocks.
12585+ */
12586+static inline int au_test_fs_bad_xino(struct super_block *sb)
12587+{
12588+ return au_test_fs_remote(sb)
12589+ || au_test_fs_bad_iattr_size(sb)
12590+#ifdef CONFIG_AUFS_BR_RAMFS
12591+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
12592+#else
12593+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
12594+#endif
12595+ /* don't want unnecessary work for xino */
12596+ || au_test_aufs(sb)
1308ab2a 12597+ || au_test_ecryptfs(sb)
12598+ || au_test_nilfs(sb);
1facf9fc 12599+}
12600+
12601+static inline int au_test_fs_trunc_xino(struct super_block *sb)
12602+{
12603+ return au_test_tmpfs(sb)
12604+ || au_test_ramfs(sb);
12605+}
12606+
12607+/*
12608+ * test if the @sb is real-readonly.
12609+ */
12610+static inline int au_test_fs_rr(struct super_block *sb)
12611+{
12612+ return au_test_squashfs(sb)
12613+ || au_test_iso9660(sb)
12614+ || au_test_cramfs(sb)
12615+ || au_test_romfs(sb);
12616+}
12617+
12618+#endif /* __KERNEL__ */
12619+#endif /* __AUFS_FSTYPE_H__ */
7f207e10
AM
12620diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
12621--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 12622+++ linux/fs/aufs/hfsnotify.c 2012-08-26 08:39:00.760508065 +0200
0c3ec466 12623@@ -0,0 +1,257 @@
1facf9fc 12624+/*
f6c5ef8b 12625+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 12626+ *
12627+ * This program, aufs is free software; you can redistribute it and/or modify
12628+ * it under the terms of the GNU General Public License as published by
12629+ * the Free Software Foundation; either version 2 of the License, or
12630+ * (at your option) any later version.
dece6358
AM
12631+ *
12632+ * This program is distributed in the hope that it will be useful,
12633+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12634+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12635+ * GNU General Public License for more details.
12636+ *
12637+ * You should have received a copy of the GNU General Public License
12638+ * along with this program; if not, write to the Free Software
12639+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 12640+ */
12641+
12642+/*
4a4d8108 12643+ * fsnotify for the lower directories
1facf9fc 12644+ */
12645+
12646+#include "aufs.h"
12647+
4a4d8108
AM
12648+/* FS_IN_IGNORED is unnecessary */
12649+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
12650+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 12651+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
7eafdf33 12652+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0);
1facf9fc 12653+
0c5527e5 12654+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 12655+{
0c5527e5
AM
12656+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
12657+ hn_mark);
4a4d8108 12658+ AuDbg("here\n");
7eafdf33
AM
12659+ au_cache_free_hnotify(hn);
12660+ smp_mb__before_atomic_dec();
12661+ atomic64_dec(&au_hfsn_ifree);
12662+ wake_up(&au_hfsn_wq);
4a4d8108 12663+}
1facf9fc 12664+
027c5e7a 12665+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 12666+{
027c5e7a
AM
12667+ struct au_hnotify *hn;
12668+ struct super_block *sb;
12669+ struct au_branch *br;
0c5527e5 12670+ struct fsnotify_mark *mark;
027c5e7a 12671+ aufs_bindex_t bindex;
1facf9fc 12672+
027c5e7a
AM
12673+ hn = hinode->hi_notify;
12674+ sb = hn->hn_aufs_inode->i_sb;
12675+ bindex = au_br_index(sb, hinode->hi_id);
12676+ br = au_sbr(sb, bindex);
0c5527e5
AM
12677+ mark = &hn->hn_mark;
12678+ fsnotify_init_mark(mark, au_hfsn_free_mark);
12679+ mark->mask = AuHfsnMask;
7f207e10
AM
12680+ /*
12681+ * by udba rename or rmdir, aufs assign a new inode to the known
12682+ * h_inode, so specify 1 to allow dups.
12683+ */
027c5e7a
AM
12684+ return fsnotify_add_mark(mark, br->br_hfsn_group, hinode->hi_inode,
12685+ /*mnt*/NULL, /*allow_dups*/1);
1facf9fc 12686+}
12687+
7eafdf33 12688+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn)
1facf9fc 12689+{
0c5527e5 12690+ struct fsnotify_mark *mark;
7eafdf33
AM
12691+ unsigned long long ull;
12692+
12693+ ull = atomic64_inc_return(&au_hfsn_ifree);
12694+ BUG_ON(!ull);
953406b4 12695+
0c5527e5
AM
12696+ mark = &hn->hn_mark;
12697+ fsnotify_destroy_mark(mark);
12698+ fsnotify_put_mark(mark);
7f207e10 12699+
7eafdf33
AM
12700+ /* free hn by myself */
12701+ return 0;
1facf9fc 12702+}
12703+
12704+/* ---------------------------------------------------------------------- */
12705+
4a4d8108 12706+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 12707+{
0c5527e5 12708+ struct fsnotify_mark *mark;
1facf9fc 12709+
0c5527e5
AM
12710+ mark = &hinode->hi_notify->hn_mark;
12711+ spin_lock(&mark->lock);
1facf9fc 12712+ if (do_set) {
0c5527e5
AM
12713+ AuDebugOn(mark->mask & AuHfsnMask);
12714+ mark->mask |= AuHfsnMask;
1facf9fc 12715+ } else {
0c5527e5
AM
12716+ AuDebugOn(!(mark->mask & AuHfsnMask));
12717+ mark->mask &= ~AuHfsnMask;
1facf9fc 12718+ }
0c5527e5 12719+ spin_unlock(&mark->lock);
4a4d8108 12720+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 12721+}
12722+
4a4d8108 12723+/* ---------------------------------------------------------------------- */
1facf9fc 12724+
4a4d8108
AM
12725+/* #define AuDbgHnotify */
12726+#ifdef AuDbgHnotify
12727+static char *au_hfsn_name(u32 mask)
12728+{
12729+#ifdef CONFIG_AUFS_DEBUG
12730+#define test_ret(flag) if (mask & flag) \
12731+ return #flag;
12732+ test_ret(FS_ACCESS);
12733+ test_ret(FS_MODIFY);
12734+ test_ret(FS_ATTRIB);
12735+ test_ret(FS_CLOSE_WRITE);
12736+ test_ret(FS_CLOSE_NOWRITE);
12737+ test_ret(FS_OPEN);
12738+ test_ret(FS_MOVED_FROM);
12739+ test_ret(FS_MOVED_TO);
12740+ test_ret(FS_CREATE);
12741+ test_ret(FS_DELETE);
12742+ test_ret(FS_DELETE_SELF);
12743+ test_ret(FS_MOVE_SELF);
12744+ test_ret(FS_UNMOUNT);
12745+ test_ret(FS_Q_OVERFLOW);
12746+ test_ret(FS_IN_IGNORED);
12747+ test_ret(FS_IN_ISDIR);
12748+ test_ret(FS_IN_ONESHOT);
12749+ test_ret(FS_EVENT_ON_CHILD);
12750+ return "";
12751+#undef test_ret
12752+#else
12753+ return "??";
12754+#endif
1facf9fc 12755+}
4a4d8108 12756+#endif
1facf9fc 12757+
12758+/* ---------------------------------------------------------------------- */
12759+
4a4d8108 12760+static int au_hfsn_handle_event(struct fsnotify_group *group,
0c5527e5
AM
12761+ struct fsnotify_mark *inode_mark,
12762+ struct fsnotify_mark *vfsmount_mark,
4a4d8108 12763+ struct fsnotify_event *event)
1facf9fc 12764+{
12765+ int err;
4a4d8108
AM
12766+ struct au_hnotify *hnotify;
12767+ struct inode *h_dir, *h_inode;
12768+ __u32 mask;
0c3ec466 12769+ struct qstr h_child_qstr = QSTR_INIT(event->file_name, event->name_len);
4a4d8108
AM
12770+
12771+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 12772+
12773+ err = 0;
0c5527e5 12774+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108
AM
12775+ mask = event->mask;
12776+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 12777+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 12778+ goto out;
1facf9fc 12779+
4a4d8108
AM
12780+ h_dir = event->to_tell;
12781+ h_inode = event->inode;
12782+#ifdef AuDbgHnotify
12783+ au_debug(1);
12784+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
12785+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
12786+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
12787+ h_dir->i_ino, mask, au_hfsn_name(mask),
12788+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
12789+ /* WARN_ON(1); */
1facf9fc 12790+ }
4a4d8108 12791+ au_debug(0);
1facf9fc 12792+#endif
4a4d8108 12793+
0c5527e5
AM
12794+ AuDebugOn(!inode_mark);
12795+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
12796+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
1facf9fc 12797+
4a4d8108
AM
12798+out:
12799+ return err;
12800+}
1facf9fc 12801+
027c5e7a 12802+/* isn't it waste to ask every registered 'group'? */
7f207e10 12803+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
4a4d8108 12804+/* it should be exported to modules */
7f207e10
AM
12805+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
12806+ struct inode *h_inode,
0c5527e5
AM
12807+ struct fsnotify_mark *inode_mark,
12808+ struct fsnotify_mark *vfsmount_mark,
12809+ __u32 mask, void *data, int data_type)
4a4d8108 12810+{
4a4d8108 12811+ mask = (mask & ~FS_EVENT_ON_CHILD);
7f207e10 12812+ return inode_mark->mask & mask;
4a4d8108
AM
12813+}
12814+
12815+static struct fsnotify_ops au_hfsn_ops = {
12816+ .should_send_event = au_hfsn_should_send_event,
12817+ .handle_event = au_hfsn_handle_event
12818+};
12819+
12820+/* ---------------------------------------------------------------------- */
12821+
027c5e7a
AM
12822+static void au_hfsn_fin_br(struct au_branch *br)
12823+{
12824+ if (br->br_hfsn_group)
12825+ fsnotify_put_group(br->br_hfsn_group);
12826+}
12827+
12828+static int au_hfsn_init_br(struct au_branch *br, int perm)
12829+{
12830+ br->br_hfsn_group = NULL;
12831+ br->br_hfsn_ops = au_hfsn_ops;
12832+ return 0;
12833+}
12834+
12835+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
4a4d8108
AM
12836+{
12837+ int err;
1facf9fc 12838+
4a4d8108 12839+ err = 0;
027c5e7a
AM
12840+ if (udba != AuOpt_UDBA_HNOTIFY
12841+ || !au_br_hnotifyable(perm)) {
12842+ au_hfsn_fin_br(br);
12843+ br->br_hfsn_group = NULL;
12844+ goto out;
12845+ }
12846+
12847+ if (br->br_hfsn_group)
12848+ goto out;
12849+
12850+ br->br_hfsn_group = fsnotify_alloc_group(&br->br_hfsn_ops);
12851+ if (IS_ERR(br->br_hfsn_group)) {
12852+ err = PTR_ERR(br->br_hfsn_group);
0c5527e5 12853+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
027c5e7a 12854+ br->br_hfsn_group = NULL;
4a4d8108 12855+ }
1facf9fc 12856+
027c5e7a 12857+out:
1facf9fc 12858+ AuTraceErr(err);
12859+ return err;
12860+}
12861+
7eafdf33
AM
12862+/* ---------------------------------------------------------------------- */
12863+
12864+static void au_hfsn_fin(void)
12865+{
12866+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree));
12867+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree));
12868+}
12869+
4a4d8108
AM
12870+const struct au_hnotify_op au_hnotify_op = {
12871+ .ctl = au_hfsn_ctl,
12872+ .alloc = au_hfsn_alloc,
12873+ .free = au_hfsn_free,
1facf9fc 12874+
7eafdf33
AM
12875+ .fin = au_hfsn_fin,
12876+
027c5e7a
AM
12877+ .reset_br = au_hfsn_reset_br,
12878+ .fin_br = au_hfsn_fin_br,
12879+ .init_br = au_hfsn_init_br
4a4d8108 12880+};
7f207e10
AM
12881diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
12882--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 12883+++ linux/fs/aufs/hfsplus.c 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 12884@@ -0,0 +1,57 @@
4a4d8108 12885+/*
f6c5ef8b 12886+ * Copyright (C) 2010-2012 Junjiro R. Okajima
4a4d8108
AM
12887+ *
12888+ * This program, aufs is free software; you can redistribute it and/or modify
12889+ * it under the terms of the GNU General Public License as published by
12890+ * the Free Software Foundation; either version 2 of the License, or
12891+ * (at your option) any later version.
12892+ *
12893+ * This program is distributed in the hope that it will be useful,
12894+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12895+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12896+ * GNU General Public License for more details.
12897+ *
12898+ * You should have received a copy of the GNU General Public License
12899+ * along with this program; if not, write to the Free Software
12900+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12901+ */
1facf9fc 12902+
4a4d8108
AM
12903+/*
12904+ * special support for filesystems which aqucires an inode mutex
12905+ * at final closing a file, eg, hfsplus.
12906+ *
12907+ * This trick is very simple and stupid, just to open the file before really
12908+ * neceeary open to tell hfsplus that this is not the final closing.
12909+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
12910+ * and au_h_open_post() after releasing it.
12911+ */
1facf9fc 12912+
4a4d8108 12913+#include "aufs.h"
1facf9fc 12914+
4a4d8108
AM
12915+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
12916+{
12917+ struct file *h_file;
12918+ struct dentry *h_dentry;
1facf9fc 12919+
4a4d8108
AM
12920+ h_dentry = au_h_dptr(dentry, bindex);
12921+ AuDebugOn(!h_dentry);
12922+ AuDebugOn(!h_dentry->d_inode);
12923+ IMustLock(h_dentry->d_inode);
12924+
12925+ h_file = NULL;
12926+ if (au_test_hfsplus(h_dentry->d_sb)
12927+ && S_ISREG(h_dentry->d_inode->i_mode))
12928+ h_file = au_h_open(dentry, bindex,
12929+ O_RDONLY | O_NOATIME | O_LARGEFILE,
12930+ /*file*/NULL);
12931+ return h_file;
1facf9fc 12932+}
12933+
4a4d8108
AM
12934+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
12935+ struct file *h_file)
12936+{
12937+ if (h_file) {
12938+ fput(h_file);
12939+ au_sbr_put(dentry->d_sb, bindex);
12940+ }
12941+}
7f207e10
AM
12942diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
12943--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 12944+++ linux/fs/aufs/hnotify.c 2012-08-26 08:39:00.760508065 +0200
53392da6 12945@@ -0,0 +1,712 @@
e49829fe 12946+/*
f6c5ef8b 12947+ * Copyright (C) 2005-2012 Junjiro R. Okajima
e49829fe
JR
12948+ *
12949+ * This program, aufs is free software; you can redistribute it and/or modify
12950+ * it under the terms of the GNU General Public License as published by
12951+ * the Free Software Foundation; either version 2 of the License, or
12952+ * (at your option) any later version.
12953+ *
12954+ * This program is distributed in the hope that it will be useful,
12955+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12956+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12957+ * GNU General Public License for more details.
12958+ *
12959+ * You should have received a copy of the GNU General Public License
12960+ * along with this program; if not, write to the Free Software
12961+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12962+ */
12963+
12964+/*
7f207e10 12965+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
12966+ */
12967+
12968+#include "aufs.h"
12969+
027c5e7a 12970+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
12971+{
12972+ int err;
7f207e10 12973+ struct au_hnotify *hn;
1facf9fc 12974+
4a4d8108
AM
12975+ err = -ENOMEM;
12976+ hn = au_cache_alloc_hnotify();
12977+ if (hn) {
12978+ hn->hn_aufs_inode = inode;
027c5e7a
AM
12979+ hinode->hi_notify = hn;
12980+ err = au_hnotify_op.alloc(hinode);
12981+ AuTraceErr(err);
12982+ if (unlikely(err)) {
12983+ hinode->hi_notify = NULL;
4a4d8108
AM
12984+ au_cache_free_hnotify(hn);
12985+ /*
12986+ * The upper dir was removed by udba, but the same named
12987+ * dir left. In this case, aufs assignes a new inode
12988+ * number and set the monitor again.
12989+ * For the lower dir, the old monitnor is still left.
12990+ */
12991+ if (err == -EEXIST)
12992+ err = 0;
12993+ }
1308ab2a 12994+ }
1308ab2a 12995+
027c5e7a 12996+ AuTraceErr(err);
1308ab2a 12997+ return err;
dece6358 12998+}
1facf9fc 12999+
4a4d8108 13000+void au_hn_free(struct au_hinode *hinode)
dece6358 13001+{
4a4d8108 13002+ struct au_hnotify *hn;
1facf9fc 13003+
4a4d8108
AM
13004+ hn = hinode->hi_notify;
13005+ if (hn) {
4a4d8108 13006+ hinode->hi_notify = NULL;
7eafdf33
AM
13007+ if (au_hnotify_op.free(hinode, hn))
13008+ au_cache_free_hnotify(hn);
4a4d8108
AM
13009+ }
13010+}
dece6358 13011+
4a4d8108 13012+/* ---------------------------------------------------------------------- */
dece6358 13013+
4a4d8108
AM
13014+void au_hn_ctl(struct au_hinode *hinode, int do_set)
13015+{
13016+ if (hinode->hi_notify)
13017+ au_hnotify_op.ctl(hinode, do_set);
13018+}
13019+
13020+void au_hn_reset(struct inode *inode, unsigned int flags)
13021+{
13022+ aufs_bindex_t bindex, bend;
13023+ struct inode *hi;
13024+ struct dentry *iwhdentry;
1facf9fc 13025+
1308ab2a 13026+ bend = au_ibend(inode);
4a4d8108
AM
13027+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
13028+ hi = au_h_iptr(inode, bindex);
13029+ if (!hi)
13030+ continue;
1308ab2a 13031+
4a4d8108
AM
13032+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
13033+ iwhdentry = au_hi_wh(inode, bindex);
13034+ if (iwhdentry)
13035+ dget(iwhdentry);
13036+ au_igrab(hi);
13037+ au_set_h_iptr(inode, bindex, NULL, 0);
13038+ au_set_h_iptr(inode, bindex, au_igrab(hi),
13039+ flags & ~AuHi_XINO);
13040+ iput(hi);
13041+ dput(iwhdentry);
13042+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 13043+ }
1facf9fc 13044+}
13045+
1308ab2a 13046+/* ---------------------------------------------------------------------- */
1facf9fc 13047+
4a4d8108 13048+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 13049+{
4a4d8108
AM
13050+ int err;
13051+ aufs_bindex_t bindex, bend, bfound, bstart;
13052+ struct inode *h_i;
1facf9fc 13053+
4a4d8108
AM
13054+ err = 0;
13055+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 13056+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
13057+ goto out;
13058+ }
1facf9fc 13059+
4a4d8108
AM
13060+ bfound = -1;
13061+ bend = au_ibend(inode);
13062+ bstart = au_ibstart(inode);
13063+#if 0 /* reserved for future use */
13064+ if (bindex == bend) {
13065+ /* keep this ino in rename case */
13066+ goto out;
13067+ }
13068+#endif
13069+ for (bindex = bstart; bindex <= bend; bindex++)
13070+ if (au_h_iptr(inode, bindex) == h_inode) {
13071+ bfound = bindex;
13072+ break;
13073+ }
13074+ if (bfound < 0)
1308ab2a 13075+ goto out;
1facf9fc 13076+
4a4d8108
AM
13077+ for (bindex = bstart; bindex <= bend; bindex++) {
13078+ h_i = au_h_iptr(inode, bindex);
13079+ if (!h_i)
13080+ continue;
1facf9fc 13081+
4a4d8108
AM
13082+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
13083+ /* ignore this error */
13084+ /* bad action? */
1facf9fc 13085+ }
1facf9fc 13086+
4a4d8108 13087+ /* children inode number will be broken */
1facf9fc 13088+
4f0767ce 13089+out:
4a4d8108
AM
13090+ AuTraceErr(err);
13091+ return err;
1facf9fc 13092+}
13093+
4a4d8108 13094+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 13095+{
4a4d8108
AM
13096+ int err, i, j, ndentry;
13097+ struct au_dcsub_pages dpages;
13098+ struct au_dpage *dpage;
13099+ struct dentry **dentries;
1facf9fc 13100+
4a4d8108
AM
13101+ err = au_dpages_init(&dpages, GFP_NOFS);
13102+ if (unlikely(err))
13103+ goto out;
13104+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
13105+ if (unlikely(err))
13106+ goto out_dpages;
1facf9fc 13107+
4a4d8108
AM
13108+ for (i = 0; i < dpages.ndpage; i++) {
13109+ dpage = dpages.dpages + i;
13110+ dentries = dpage->dentries;
13111+ ndentry = dpage->ndentry;
13112+ for (j = 0; j < ndentry; j++) {
13113+ struct dentry *d;
13114+
13115+ d = dentries[j];
13116+ if (IS_ROOT(d))
13117+ continue;
13118+
4a4d8108
AM
13119+ au_digen_dec(d);
13120+ if (d->d_inode)
13121+ /* todo: reset children xino?
13122+ cached children only? */
13123+ au_iigen_dec(d->d_inode);
1308ab2a 13124+ }
dece6358 13125+ }
1facf9fc 13126+
4f0767ce 13127+out_dpages:
4a4d8108 13128+ au_dpages_free(&dpages);
dece6358 13129+
027c5e7a 13130+#if 0
4a4d8108
AM
13131+ /* discard children */
13132+ dentry_unhash(dentry);
13133+ dput(dentry);
027c5e7a 13134+#endif
4f0767ce 13135+out:
dece6358
AM
13136+ return err;
13137+}
13138+
1308ab2a 13139+/*
4a4d8108 13140+ * return 0 if processed.
1308ab2a 13141+ */
4a4d8108
AM
13142+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
13143+ const unsigned int isdir)
dece6358 13144+{
1308ab2a 13145+ int err;
4a4d8108
AM
13146+ struct dentry *d;
13147+ struct qstr *dname;
1facf9fc 13148+
4a4d8108
AM
13149+ err = 1;
13150+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 13151+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
13152+ err = 0;
13153+ goto out;
13154+ }
dece6358 13155+
4a4d8108
AM
13156+ if (!isdir) {
13157+ AuDebugOn(!name);
13158+ au_iigen_dec(inode);
027c5e7a 13159+ spin_lock(&inode->i_lock);
4a4d8108 13160+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
027c5e7a 13161+ spin_lock(&d->d_lock);
4a4d8108
AM
13162+ dname = &d->d_name;
13163+ if (dname->len != nlen
027c5e7a
AM
13164+ && memcmp(dname->name, name, nlen)) {
13165+ spin_unlock(&d->d_lock);
4a4d8108 13166+ continue;
027c5e7a 13167+ }
4a4d8108 13168+ err = 0;
4a4d8108
AM
13169+ au_digen_dec(d);
13170+ spin_unlock(&d->d_lock);
13171+ break;
1facf9fc 13172+ }
027c5e7a 13173+ spin_unlock(&inode->i_lock);
1308ab2a 13174+ } else {
027c5e7a 13175+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
13176+ d = d_find_alias(inode);
13177+ if (!d) {
13178+ au_iigen_dec(inode);
13179+ goto out;
13180+ }
1facf9fc 13181+
027c5e7a 13182+ spin_lock(&d->d_lock);
4a4d8108 13183+ dname = &d->d_name;
027c5e7a
AM
13184+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
13185+ spin_unlock(&d->d_lock);
4a4d8108 13186+ err = hn_gen_tree(d);
027c5e7a
AM
13187+ spin_lock(&d->d_lock);
13188+ }
13189+ spin_unlock(&d->d_lock);
4a4d8108
AM
13190+ dput(d);
13191+ }
1facf9fc 13192+
4f0767ce 13193+out:
4a4d8108 13194+ AuTraceErr(err);
1308ab2a 13195+ return err;
13196+}
dece6358 13197+
4a4d8108 13198+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 13199+{
4a4d8108
AM
13200+ int err;
13201+ struct inode *inode;
1facf9fc 13202+
4a4d8108
AM
13203+ inode = dentry->d_inode;
13204+ if (IS_ROOT(dentry)
13205+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
13206+ ) {
0c3ec466 13207+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
13208+ return 0;
13209+ }
1308ab2a 13210+
4a4d8108
AM
13211+ err = 0;
13212+ if (!isdir) {
4a4d8108
AM
13213+ au_digen_dec(dentry);
13214+ if (inode)
13215+ au_iigen_dec(inode);
13216+ } else {
027c5e7a 13217+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
13218+ if (inode)
13219+ err = hn_gen_tree(dentry);
13220+ }
13221+
13222+ AuTraceErr(err);
13223+ return err;
1facf9fc 13224+}
13225+
4a4d8108 13226+/* ---------------------------------------------------------------------- */
1facf9fc 13227+
4a4d8108
AM
13228+/* hnotify job flags */
13229+#define AuHnJob_XINO0 1
13230+#define AuHnJob_GEN (1 << 1)
13231+#define AuHnJob_DIRENT (1 << 2)
13232+#define AuHnJob_ISDIR (1 << 3)
13233+#define AuHnJob_TRYXINO0 (1 << 4)
13234+#define AuHnJob_MNTPNT (1 << 5)
13235+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
13236+#define au_fset_hnjob(flags, name) \
13237+ do { (flags) |= AuHnJob_##name; } while (0)
13238+#define au_fclr_hnjob(flags, name) \
13239+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 13240+
4a4d8108
AM
13241+enum {
13242+ AuHn_CHILD,
13243+ AuHn_PARENT,
13244+ AuHnLast
13245+};
1facf9fc 13246+
4a4d8108
AM
13247+struct au_hnotify_args {
13248+ struct inode *h_dir, *dir, *h_child_inode;
13249+ u32 mask;
13250+ unsigned int flags[AuHnLast];
13251+ unsigned int h_child_nlen;
13252+ char h_child_name[];
13253+};
1facf9fc 13254+
4a4d8108
AM
13255+struct hn_job_args {
13256+ unsigned int flags;
13257+ struct inode *inode, *h_inode, *dir, *h_dir;
13258+ struct dentry *dentry;
13259+ char *h_name;
13260+ int h_nlen;
13261+};
1308ab2a 13262+
4a4d8108
AM
13263+static int hn_job(struct hn_job_args *a)
13264+{
13265+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 13266+
4a4d8108
AM
13267+ /* reset xino */
13268+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
13269+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 13270+
4a4d8108
AM
13271+ if (au_ftest_hnjob(a->flags, TRYXINO0)
13272+ && a->inode
13273+ && a->h_inode) {
13274+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
13275+ if (!a->h_inode->i_nlink)
13276+ hn_xino(a->inode, a->h_inode); /* ignore this error */
13277+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 13278+ }
1facf9fc 13279+
4a4d8108
AM
13280+ /* make the generation obsolete */
13281+ if (au_ftest_hnjob(a->flags, GEN)) {
13282+ int err = -1;
13283+ if (a->inode)
13284+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
13285+ isdir);
13286+ if (err && a->dentry)
13287+ hn_gen_by_name(a->dentry, isdir);
13288+ /* ignore this error */
1facf9fc 13289+ }
1facf9fc 13290+
4a4d8108
AM
13291+ /* make dir entries obsolete */
13292+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
13293+ struct au_vdir *vdir;
1facf9fc 13294+
4a4d8108
AM
13295+ vdir = au_ivdir(a->inode);
13296+ if (vdir)
13297+ vdir->vd_jiffy = 0;
13298+ /* IMustLock(a->inode); */
13299+ /* a->inode->i_version++; */
13300+ }
1facf9fc 13301+
4a4d8108
AM
13302+ /* can do nothing but warn */
13303+ if (au_ftest_hnjob(a->flags, MNTPNT)
13304+ && a->dentry
13305+ && d_mountpoint(a->dentry))
0c3ec466
AM
13306+ pr_warn("mount-point %.*s is removed or renamed\n",
13307+ AuDLNPair(a->dentry));
1facf9fc 13308+
4a4d8108 13309+ return 0;
1308ab2a 13310+}
1facf9fc 13311+
1308ab2a 13312+/* ---------------------------------------------------------------------- */
1facf9fc 13313+
4a4d8108
AM
13314+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
13315+ struct inode *dir)
1308ab2a 13316+{
4a4d8108
AM
13317+ struct dentry *dentry, *d, *parent;
13318+ struct qstr *dname;
1308ab2a 13319+
4a4d8108
AM
13320+ parent = d_find_alias(dir);
13321+ if (!parent)
13322+ return NULL;
1308ab2a 13323+
4a4d8108 13324+ dentry = NULL;
027c5e7a 13325+ spin_lock(&parent->d_lock);
4a4d8108
AM
13326+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
13327+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
027c5e7a 13328+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
13329+ dname = &d->d_name;
13330+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
13331+ goto cont_unlock;
13332+ if (au_di(d))
13333+ au_digen_dec(d);
13334+ else
13335+ goto cont_unlock;
13336+ if (d->d_count) {
13337+ dentry = dget_dlock(d);
4a4d8108 13338+ spin_unlock(&d->d_lock);
027c5e7a 13339+ break;
dece6358 13340+ }
1facf9fc 13341+
027c5e7a
AM
13342+ cont_unlock:
13343+ spin_unlock(&d->d_lock);
1308ab2a 13344+ }
027c5e7a 13345+ spin_unlock(&parent->d_lock);
4a4d8108 13346+ dput(parent);
1facf9fc 13347+
4a4d8108
AM
13348+ if (dentry)
13349+ di_write_lock_child(dentry);
1308ab2a 13350+
4a4d8108
AM
13351+ return dentry;
13352+}
dece6358 13353+
4a4d8108
AM
13354+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
13355+ aufs_bindex_t bindex, ino_t h_ino)
13356+{
13357+ struct inode *inode;
13358+ ino_t ino;
13359+ int err;
13360+
13361+ inode = NULL;
13362+ err = au_xino_read(sb, bindex, h_ino, &ino);
13363+ if (!err && ino)
13364+ inode = ilookup(sb, ino);
13365+ if (!inode)
13366+ goto out;
13367+
13368+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 13369+ pr_warn("wrong root branch\n");
4a4d8108
AM
13370+ iput(inode);
13371+ inode = NULL;
13372+ goto out;
1308ab2a 13373+ }
13374+
4a4d8108 13375+ ii_write_lock_child(inode);
1308ab2a 13376+
4f0767ce 13377+out:
4a4d8108 13378+ return inode;
dece6358
AM
13379+}
13380+
4a4d8108 13381+static void au_hn_bh(void *_args)
1facf9fc 13382+{
4a4d8108
AM
13383+ struct au_hnotify_args *a = _args;
13384+ struct super_block *sb;
13385+ aufs_bindex_t bindex, bend, bfound;
13386+ unsigned char xino, try_iput;
1facf9fc 13387+ int err;
1308ab2a 13388+ struct inode *inode;
4a4d8108
AM
13389+ ino_t h_ino;
13390+ struct hn_job_args args;
13391+ struct dentry *dentry;
13392+ struct au_sbinfo *sbinfo;
1facf9fc 13393+
4a4d8108
AM
13394+ AuDebugOn(!_args);
13395+ AuDebugOn(!a->h_dir);
13396+ AuDebugOn(!a->dir);
13397+ AuDebugOn(!a->mask);
13398+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
13399+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
13400+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 13401+
4a4d8108
AM
13402+ inode = NULL;
13403+ dentry = NULL;
13404+ /*
13405+ * do not lock a->dir->i_mutex here
13406+ * because of d_revalidate() may cause a deadlock.
13407+ */
13408+ sb = a->dir->i_sb;
13409+ AuDebugOn(!sb);
13410+ sbinfo = au_sbi(sb);
13411+ AuDebugOn(!sbinfo);
7f207e10 13412+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 13413+
4a4d8108
AM
13414+ ii_read_lock_parent(a->dir);
13415+ bfound = -1;
13416+ bend = au_ibend(a->dir);
13417+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
13418+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
13419+ bfound = bindex;
13420+ break;
13421+ }
13422+ ii_read_unlock(a->dir);
13423+ if (unlikely(bfound < 0))
13424+ goto out;
1facf9fc 13425+
4a4d8108
AM
13426+ xino = !!au_opt_test(au_mntflags(sb), XINO);
13427+ h_ino = 0;
13428+ if (a->h_child_inode)
13429+ h_ino = a->h_child_inode->i_ino;
1facf9fc 13430+
4a4d8108
AM
13431+ if (a->h_child_nlen
13432+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
13433+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
13434+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
13435+ a->dir);
13436+ try_iput = 0;
13437+ if (dentry)
13438+ inode = dentry->d_inode;
13439+ if (xino && !inode && h_ino
13440+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
13441+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
13442+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
13443+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
13444+ try_iput = 1;
13445+ }
1facf9fc 13446+
4a4d8108
AM
13447+ args.flags = a->flags[AuHn_CHILD];
13448+ args.dentry = dentry;
13449+ args.inode = inode;
13450+ args.h_inode = a->h_child_inode;
13451+ args.dir = a->dir;
13452+ args.h_dir = a->h_dir;
13453+ args.h_name = a->h_child_name;
13454+ args.h_nlen = a->h_child_nlen;
13455+ err = hn_job(&args);
13456+ if (dentry) {
027c5e7a 13457+ if (au_di(dentry))
4a4d8108
AM
13458+ di_write_unlock(dentry);
13459+ dput(dentry);
13460+ }
13461+ if (inode && try_iput) {
13462+ ii_write_unlock(inode);
13463+ iput(inode);
13464+ }
1facf9fc 13465+
4a4d8108
AM
13466+ ii_write_lock_parent(a->dir);
13467+ args.flags = a->flags[AuHn_PARENT];
13468+ args.dentry = NULL;
13469+ args.inode = a->dir;
13470+ args.h_inode = a->h_dir;
13471+ args.dir = NULL;
13472+ args.h_dir = NULL;
13473+ args.h_name = NULL;
13474+ args.h_nlen = 0;
13475+ err = hn_job(&args);
13476+ ii_write_unlock(a->dir);
1facf9fc 13477+
4f0767ce 13478+out:
4a4d8108
AM
13479+ iput(a->h_child_inode);
13480+ iput(a->h_dir);
13481+ iput(a->dir);
027c5e7a
AM
13482+ si_write_unlock(sb);
13483+ au_nwt_done(&sbinfo->si_nowait);
1308ab2a 13484+ kfree(a);
dece6358 13485+}
1facf9fc 13486+
4a4d8108
AM
13487+/* ---------------------------------------------------------------------- */
13488+
13489+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
13490+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 13491+{
4a4d8108 13492+ int err, len;
53392da6 13493+ unsigned int flags[AuHnLast], f;
4a4d8108
AM
13494+ unsigned char isdir, isroot, wh;
13495+ struct inode *dir;
13496+ struct au_hnotify_args *args;
13497+ char *p, *h_child_name;
dece6358 13498+
1308ab2a 13499+ err = 0;
4a4d8108
AM
13500+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
13501+ dir = igrab(hnotify->hn_aufs_inode);
13502+ if (!dir)
13503+ goto out;
1facf9fc 13504+
4a4d8108
AM
13505+ isroot = (dir->i_ino == AUFS_ROOT_INO);
13506+ wh = 0;
13507+ h_child_name = (void *)h_child_qstr->name;
13508+ len = h_child_qstr->len;
13509+ if (h_child_name) {
13510+ if (len > AUFS_WH_PFX_LEN
13511+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
13512+ h_child_name += AUFS_WH_PFX_LEN;
13513+ len -= AUFS_WH_PFX_LEN;
13514+ wh = 1;
13515+ }
1facf9fc 13516+ }
dece6358 13517+
4a4d8108
AM
13518+ isdir = 0;
13519+ if (h_child_inode)
13520+ isdir = !!S_ISDIR(h_child_inode->i_mode);
13521+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
13522+ flags[AuHn_CHILD] = 0;
13523+ if (isdir)
13524+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
13525+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
13526+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
13527+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
13528+ case FS_MOVED_FROM:
13529+ case FS_MOVED_TO:
13530+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
13531+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
13532+ /*FALLTHROUGH*/
13533+ case FS_CREATE:
13534+ AuDebugOn(!h_child_name || !h_child_inode);
13535+ break;
1facf9fc 13536+
4a4d8108
AM
13537+ case FS_DELETE:
13538+ /*
13539+ * aufs never be able to get this child inode.
13540+ * revalidation should be in d_revalidate()
13541+ * by checking i_nlink, i_generation or d_unhashed().
13542+ */
13543+ AuDebugOn(!h_child_name);
13544+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
13545+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
13546+ break;
dece6358 13547+
4a4d8108
AM
13548+ default:
13549+ AuDebugOn(1);
13550+ }
1308ab2a 13551+
4a4d8108
AM
13552+ if (wh)
13553+ h_child_inode = NULL;
1308ab2a 13554+
4a4d8108
AM
13555+ err = -ENOMEM;
13556+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 13557+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
13558+ if (unlikely(!args)) {
13559+ AuErr1("no memory\n");
13560+ iput(dir);
13561+ goto out;
13562+ }
13563+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
13564+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
13565+ args->mask = mask;
13566+ args->dir = dir;
13567+ args->h_dir = igrab(h_dir);
13568+ if (h_child_inode)
13569+ h_child_inode = igrab(h_child_inode); /* can be NULL */
13570+ args->h_child_inode = h_child_inode;
13571+ args->h_child_nlen = len;
13572+ if (len) {
13573+ p = (void *)args;
13574+ p += sizeof(*args);
13575+ memcpy(p, h_child_name, len);
13576+ p[len] = 0;
1308ab2a 13577+ }
1308ab2a 13578+
53392da6
AM
13579+ f = 0;
13580+ if (!dir->i_nlink)
13581+ f = AuWkq_NEST;
13582+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f);
4a4d8108
AM
13583+ if (unlikely(err)) {
13584+ pr_err("wkq %d\n", err);
13585+ iput(args->h_child_inode);
13586+ iput(args->h_dir);
13587+ iput(args->dir);
13588+ kfree(args);
1facf9fc 13589+ }
1facf9fc 13590+
4a4d8108 13591+out:
1facf9fc 13592+ return err;
13593+}
13594+
027c5e7a
AM
13595+/* ---------------------------------------------------------------------- */
13596+
13597+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
13598+{
13599+ int err;
13600+
13601+ AuDebugOn(!(udba & AuOptMask_UDBA));
13602+
13603+ err = 0;
13604+ if (au_hnotify_op.reset_br)
13605+ err = au_hnotify_op.reset_br(udba, br, perm);
13606+
13607+ return err;
13608+}
13609+
13610+int au_hnotify_init_br(struct au_branch *br, int perm)
13611+{
13612+ int err;
13613+
13614+ err = 0;
13615+ if (au_hnotify_op.init_br)
13616+ err = au_hnotify_op.init_br(br, perm);
13617+
13618+ return err;
13619+}
13620+
13621+void au_hnotify_fin_br(struct au_branch *br)
13622+{
13623+ if (au_hnotify_op.fin_br)
13624+ au_hnotify_op.fin_br(br);
13625+}
13626+
4a4d8108
AM
13627+static void au_hn_destroy_cache(void)
13628+{
13629+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
13630+ au_cachep[AuCache_HNOTIFY] = NULL;
13631+}
1308ab2a 13632+
4a4d8108 13633+int __init au_hnotify_init(void)
1facf9fc 13634+{
1308ab2a 13635+ int err;
1308ab2a 13636+
4a4d8108
AM
13637+ err = -ENOMEM;
13638+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
13639+ if (au_cachep[AuCache_HNOTIFY]) {
027c5e7a
AM
13640+ err = 0;
13641+ if (au_hnotify_op.init)
13642+ err = au_hnotify_op.init();
4a4d8108
AM
13643+ if (unlikely(err))
13644+ au_hn_destroy_cache();
1308ab2a 13645+ }
1308ab2a 13646+ AuTraceErr(err);
4a4d8108 13647+ return err;
1308ab2a 13648+}
13649+
4a4d8108 13650+void au_hnotify_fin(void)
1308ab2a 13651+{
027c5e7a
AM
13652+ if (au_hnotify_op.fin)
13653+ au_hnotify_op.fin();
4a4d8108
AM
13654+ /* cf. au_cache_fin() */
13655+ if (au_cachep[AuCache_HNOTIFY])
13656+ au_hn_destroy_cache();
dece6358 13657+}
7f207e10
AM
13658diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
13659--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 13660+++ linux/fs/aufs/iinfo.c 2012-08-26 08:39:00.760508065 +0200
027c5e7a 13661@@ -0,0 +1,264 @@
dece6358 13662+/*
f6c5ef8b 13663+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
13664+ *
13665+ * This program, aufs is free software; you can redistribute it and/or modify
13666+ * it under the terms of the GNU General Public License as published by
13667+ * the Free Software Foundation; either version 2 of the License, or
13668+ * (at your option) any later version.
13669+ *
13670+ * This program is distributed in the hope that it will be useful,
13671+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13672+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13673+ * GNU General Public License for more details.
13674+ *
13675+ * You should have received a copy of the GNU General Public License
13676+ * along with this program; if not, write to the Free Software
13677+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13678+ */
1facf9fc 13679+
dece6358 13680+/*
4a4d8108 13681+ * inode private data
dece6358 13682+ */
1facf9fc 13683+
1308ab2a 13684+#include "aufs.h"
1facf9fc 13685+
4a4d8108 13686+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 13687+{
4a4d8108 13688+ struct inode *h_inode;
1facf9fc 13689+
4a4d8108 13690+ IiMustAnyLock(inode);
1facf9fc 13691+
4a4d8108
AM
13692+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
13693+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
13694+ return h_inode;
13695+}
1facf9fc 13696+
4a4d8108
AM
13697+/* todo: hard/soft set? */
13698+void au_hiput(struct au_hinode *hinode)
13699+{
13700+ au_hn_free(hinode);
13701+ dput(hinode->hi_whdentry);
13702+ iput(hinode->hi_inode);
13703+}
1facf9fc 13704+
4a4d8108
AM
13705+unsigned int au_hi_flags(struct inode *inode, int isdir)
13706+{
13707+ unsigned int flags;
13708+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 13709+
4a4d8108
AM
13710+ flags = 0;
13711+ if (au_opt_test(mnt_flags, XINO))
13712+ au_fset_hi(flags, XINO);
13713+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
13714+ au_fset_hi(flags, HNOTIFY);
13715+ return flags;
1facf9fc 13716+}
13717+
4a4d8108
AM
13718+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
13719+ struct inode *h_inode, unsigned int flags)
1308ab2a 13720+{
4a4d8108
AM
13721+ struct au_hinode *hinode;
13722+ struct inode *hi;
13723+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 13724+
4a4d8108 13725+ IiMustWriteLock(inode);
dece6358 13726+
4a4d8108
AM
13727+ hinode = iinfo->ii_hinode + bindex;
13728+ hi = hinode->hi_inode;
13729+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
13730+
13731+ if (hi)
13732+ au_hiput(hinode);
13733+ hinode->hi_inode = h_inode;
13734+ if (h_inode) {
13735+ int err;
13736+ struct super_block *sb = inode->i_sb;
13737+ struct au_branch *br;
13738+
027c5e7a
AM
13739+ AuDebugOn(inode->i_mode
13740+ && (h_inode->i_mode & S_IFMT)
13741+ != (inode->i_mode & S_IFMT));
4a4d8108
AM
13742+ if (bindex == iinfo->ii_bstart)
13743+ au_cpup_igen(inode, h_inode);
13744+ br = au_sbr(sb, bindex);
13745+ hinode->hi_id = br->br_id;
13746+ if (au_ftest_hi(flags, XINO)) {
13747+ err = au_xino_write(sb, bindex, h_inode->i_ino,
13748+ inode->i_ino);
13749+ if (unlikely(err))
13750+ AuIOErr1("failed au_xino_write() %d\n", err);
13751+ }
13752+
13753+ if (au_ftest_hi(flags, HNOTIFY)
13754+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 13755+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
13756+ if (unlikely(err))
13757+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 13758+ }
13759+ }
4a4d8108 13760+}
dece6358 13761+
4a4d8108
AM
13762+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
13763+ struct dentry *h_wh)
13764+{
13765+ struct au_hinode *hinode;
dece6358 13766+
4a4d8108
AM
13767+ IiMustWriteLock(inode);
13768+
13769+ hinode = au_ii(inode)->ii_hinode + bindex;
13770+ AuDebugOn(hinode->hi_whdentry);
13771+ hinode->hi_whdentry = h_wh;
1facf9fc 13772+}
13773+
4a4d8108 13774+void au_update_iigen(struct inode *inode)
1308ab2a 13775+{
4a4d8108
AM
13776+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
13777+ /* smp_mb(); */ /* atomic_set */
13778+}
1facf9fc 13779+
4a4d8108
AM
13780+/* it may be called at remount time, too */
13781+void au_update_ibrange(struct inode *inode, int do_put_zero)
13782+{
13783+ struct au_iinfo *iinfo;
027c5e7a 13784+ aufs_bindex_t bindex, bend;
1facf9fc 13785+
4a4d8108 13786+ iinfo = au_ii(inode);
027c5e7a 13787+ if (!iinfo)
4a4d8108 13788+ return;
1facf9fc 13789+
4a4d8108 13790+ IiMustWriteLock(inode);
1facf9fc 13791+
027c5e7a 13792+ if (do_put_zero && iinfo->ii_bstart >= 0) {
4a4d8108
AM
13793+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
13794+ bindex++) {
13795+ struct inode *h_i;
1facf9fc 13796+
4a4d8108 13797+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
027c5e7a
AM
13798+ if (h_i && !h_i->i_nlink)
13799+ au_set_h_iptr(inode, bindex, NULL, 0);
13800+ }
4a4d8108
AM
13801+ }
13802+
027c5e7a
AM
13803+ iinfo->ii_bstart = -1;
13804+ iinfo->ii_bend = -1;
13805+ bend = au_sbend(inode->i_sb);
13806+ for (bindex = 0; bindex <= bend; bindex++)
13807+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
13808+ iinfo->ii_bstart = bindex;
4a4d8108 13809+ break;
027c5e7a
AM
13810+ }
13811+ if (iinfo->ii_bstart >= 0)
13812+ for (bindex = bend; bindex >= iinfo->ii_bstart; bindex--)
13813+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
13814+ iinfo->ii_bend = bindex;
13815+ break;
13816+ }
13817+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend);
1308ab2a 13818+}
1facf9fc 13819+
dece6358 13820+/* ---------------------------------------------------------------------- */
1facf9fc 13821+
4a4d8108 13822+void au_icntnr_init_once(void *_c)
dece6358 13823+{
4a4d8108
AM
13824+ struct au_icntnr *c = _c;
13825+ struct au_iinfo *iinfo = &c->iinfo;
e49829fe 13826+ static struct lock_class_key aufs_ii;
1facf9fc 13827+
4a4d8108 13828+ au_rw_init(&iinfo->ii_rwsem);
e49829fe 13829+ au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
4a4d8108
AM
13830+ inode_init_once(&c->vfs_inode);
13831+}
1facf9fc 13832+
4a4d8108
AM
13833+int au_iinfo_init(struct inode *inode)
13834+{
13835+ struct au_iinfo *iinfo;
13836+ struct super_block *sb;
13837+ int nbr, i;
1facf9fc 13838+
4a4d8108
AM
13839+ sb = inode->i_sb;
13840+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
13841+ nbr = au_sbend(sb) + 1;
13842+ if (unlikely(nbr <= 0))
13843+ nbr = 1;
13844+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
13845+ if (iinfo->ii_hinode) {
7f207e10 13846+ au_ninodes_inc(sb);
4a4d8108
AM
13847+ for (i = 0; i < nbr; i++)
13848+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 13849+
4a4d8108
AM
13850+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
13851+ /* smp_mb(); */ /* atomic_set */
13852+ iinfo->ii_bstart = -1;
13853+ iinfo->ii_bend = -1;
13854+ iinfo->ii_vdir = NULL;
13855+ return 0;
1308ab2a 13856+ }
4a4d8108
AM
13857+ return -ENOMEM;
13858+}
1facf9fc 13859+
4a4d8108
AM
13860+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
13861+{
13862+ int err, sz;
13863+ struct au_hinode *hip;
1facf9fc 13864+
4a4d8108
AM
13865+ AuRwMustWriteLock(&iinfo->ii_rwsem);
13866+
13867+ err = -ENOMEM;
13868+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
13869+ if (!sz)
13870+ sz = sizeof(*hip);
13871+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
13872+ if (hip) {
13873+ iinfo->ii_hinode = hip;
13874+ err = 0;
1308ab2a 13875+ }
4a4d8108 13876+
1308ab2a 13877+ return err;
1facf9fc 13878+}
13879+
4a4d8108 13880+void au_iinfo_fin(struct inode *inode)
1facf9fc 13881+{
4a4d8108
AM
13882+ struct au_iinfo *iinfo;
13883+ struct au_hinode *hi;
13884+ struct super_block *sb;
b752ccd1
AM
13885+ aufs_bindex_t bindex, bend;
13886+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 13887+
4a4d8108
AM
13888+ iinfo = au_ii(inode);
13889+ /* bad_inode case */
13890+ if (!iinfo)
13891+ return;
1308ab2a 13892+
b752ccd1 13893+ sb = inode->i_sb;
7f207e10 13894+ au_ninodes_dec(sb);
b752ccd1
AM
13895+ if (si_pid_test(sb))
13896+ au_xino_delete_inode(inode, unlinked);
13897+ else {
13898+ /*
13899+ * it is safe to hide the dependency between sbinfo and
13900+ * sb->s_umount.
13901+ */
13902+ lockdep_off();
13903+ si_noflush_read_lock(sb);
13904+ au_xino_delete_inode(inode, unlinked);
13905+ si_read_unlock(sb);
13906+ lockdep_on();
13907+ }
13908+
4a4d8108
AM
13909+ if (iinfo->ii_vdir)
13910+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 13911+
b752ccd1
AM
13912+ bindex = iinfo->ii_bstart;
13913+ if (bindex >= 0) {
13914+ hi = iinfo->ii_hinode + bindex;
4a4d8108 13915+ bend = iinfo->ii_bend;
b752ccd1
AM
13916+ while (bindex++ <= bend) {
13917+ if (hi->hi_inode)
4a4d8108 13918+ au_hiput(hi);
4a4d8108
AM
13919+ hi++;
13920+ }
13921+ }
4a4d8108 13922+ kfree(iinfo->ii_hinode);
027c5e7a 13923+ iinfo->ii_hinode = NULL;
4a4d8108 13924+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 13925+}
7f207e10
AM
13926diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
13927--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274
AM
13928+++ linux/fs/aufs/inode.c 2012-08-26 08:39:00.760508065 +0200
13929@@ -0,0 +1,478 @@
4a4d8108 13930+/*
f6c5ef8b 13931+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
13932+ *
13933+ * This program, aufs is free software; you can redistribute it and/or modify
13934+ * it under the terms of the GNU General Public License as published by
13935+ * the Free Software Foundation; either version 2 of the License, or
13936+ * (at your option) any later version.
13937+ *
13938+ * This program is distributed in the hope that it will be useful,
13939+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13940+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13941+ * GNU General Public License for more details.
13942+ *
13943+ * You should have received a copy of the GNU General Public License
13944+ * along with this program; if not, write to the Free Software
13945+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13946+ */
1facf9fc 13947+
4a4d8108
AM
13948+/*
13949+ * inode functions
13950+ */
1facf9fc 13951+
4a4d8108 13952+#include "aufs.h"
1308ab2a 13953+
4a4d8108
AM
13954+struct inode *au_igrab(struct inode *inode)
13955+{
13956+ if (inode) {
13957+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 13958+ ihold(inode);
1facf9fc 13959+ }
4a4d8108
AM
13960+ return inode;
13961+}
1facf9fc 13962+
4a4d8108
AM
13963+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
13964+{
13965+ au_cpup_attr_all(inode, /*force*/0);
13966+ au_update_iigen(inode);
13967+ if (do_version)
13968+ inode->i_version++;
dece6358 13969+}
1facf9fc 13970+
027c5e7a 13971+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 13972+{
4a4d8108 13973+ int err, e;
027c5e7a 13974+ umode_t type;
4a4d8108 13975+ aufs_bindex_t bindex, new_bindex;
1308ab2a 13976+ struct super_block *sb;
4a4d8108 13977+ struct au_iinfo *iinfo;
027c5e7a 13978+ struct au_hinode *p, *q, tmp;
1facf9fc 13979+
4a4d8108 13980+ IiMustWriteLock(inode);
1facf9fc 13981+
027c5e7a 13982+ *update = 0;
4a4d8108 13983+ sb = inode->i_sb;
027c5e7a 13984+ type = inode->i_mode & S_IFMT;
4a4d8108
AM
13985+ iinfo = au_ii(inode);
13986+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
13987+ if (unlikely(err))
1308ab2a 13988+ goto out;
1facf9fc 13989+
027c5e7a 13990+ AuDebugOn(iinfo->ii_bstart < 0);
4a4d8108 13991+ p = iinfo->ii_hinode + iinfo->ii_bstart;
4a4d8108
AM
13992+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
13993+ bindex++, p++) {
13994+ if (!p->hi_inode)
13995+ continue;
1facf9fc 13996+
027c5e7a 13997+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
13998+ new_bindex = au_br_index(sb, p->hi_id);
13999+ if (new_bindex == bindex)
14000+ continue;
1facf9fc 14001+
4a4d8108 14002+ if (new_bindex < 0) {
027c5e7a 14003+ *update = 1;
4a4d8108
AM
14004+ au_hiput(p);
14005+ p->hi_inode = NULL;
14006+ continue;
1308ab2a 14007+ }
4a4d8108
AM
14008+
14009+ if (new_bindex < iinfo->ii_bstart)
14010+ iinfo->ii_bstart = new_bindex;
14011+ if (iinfo->ii_bend < new_bindex)
14012+ iinfo->ii_bend = new_bindex;
14013+ /* swap two lower inode, and loop again */
14014+ q = iinfo->ii_hinode + new_bindex;
14015+ tmp = *q;
14016+ *q = *p;
14017+ *p = tmp;
14018+ if (tmp.hi_inode) {
14019+ bindex--;
14020+ p--;
1308ab2a 14021+ }
14022+ }
4a4d8108
AM
14023+ au_update_ibrange(inode, /*do_put_zero*/0);
14024+ e = au_dy_irefresh(inode);
14025+ if (unlikely(e && !err))
14026+ err = e;
1facf9fc 14027+
4f0767ce 14028+out:
027c5e7a
AM
14029+ AuTraceErr(err);
14030+ return err;
14031+}
14032+
14033+int au_refresh_hinode_self(struct inode *inode)
14034+{
14035+ int err, update;
14036+
14037+ err = au_ii_refresh(inode, &update);
14038+ if (!err)
14039+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
14040+
14041+ AuTraceErr(err);
4a4d8108
AM
14042+ return err;
14043+}
1facf9fc 14044+
4a4d8108
AM
14045+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
14046+{
027c5e7a 14047+ int err, e, update;
4a4d8108 14048+ unsigned int flags;
027c5e7a 14049+ umode_t mode;
4a4d8108 14050+ aufs_bindex_t bindex, bend;
027c5e7a 14051+ unsigned char isdir;
4a4d8108
AM
14052+ struct au_hinode *p;
14053+ struct au_iinfo *iinfo;
1facf9fc 14054+
027c5e7a 14055+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
14056+ if (unlikely(err))
14057+ goto out;
14058+
14059+ update = 0;
14060+ iinfo = au_ii(inode);
14061+ p = iinfo->ii_hinode + iinfo->ii_bstart;
027c5e7a
AM
14062+ mode = (inode->i_mode & S_IFMT);
14063+ isdir = S_ISDIR(mode);
4a4d8108
AM
14064+ flags = au_hi_flags(inode, isdir);
14065+ bend = au_dbend(dentry);
14066+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
14067+ struct inode *h_i;
14068+ struct dentry *h_d;
14069+
14070+ h_d = au_h_dptr(dentry, bindex);
14071+ if (!h_d || !h_d->d_inode)
14072+ continue;
14073+
027c5e7a 14074+ AuDebugOn(mode != (h_d->d_inode->i_mode & S_IFMT));
4a4d8108
AM
14075+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
14076+ h_i = au_h_iptr(inode, bindex);
14077+ if (h_i) {
14078+ if (h_i == h_d->d_inode)
14079+ continue;
14080+ err = -EIO;
14081+ break;
14082+ }
14083+ }
14084+ if (bindex < iinfo->ii_bstart)
14085+ iinfo->ii_bstart = bindex;
14086+ if (iinfo->ii_bend < bindex)
14087+ iinfo->ii_bend = bindex;
14088+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
14089+ update = 1;
1308ab2a 14090+ }
4a4d8108
AM
14091+ au_update_ibrange(inode, /*do_put_zero*/0);
14092+ e = au_dy_irefresh(inode);
14093+ if (unlikely(e && !err))
14094+ err = e;
027c5e7a
AM
14095+ if (!err)
14096+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 14097+
4f0767ce 14098+out:
4a4d8108 14099+ AuTraceErr(err);
1308ab2a 14100+ return err;
dece6358
AM
14101+}
14102+
4a4d8108 14103+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 14104+{
4a4d8108
AM
14105+ int err;
14106+ unsigned int flags;
14107+ umode_t mode;
14108+ aufs_bindex_t bindex, bstart, btail;
14109+ unsigned char isdir;
14110+ struct dentry *h_dentry;
14111+ struct inode *h_inode;
14112+ struct au_iinfo *iinfo;
dece6358 14113+
4a4d8108 14114+ IiMustWriteLock(inode);
dece6358 14115+
4a4d8108
AM
14116+ err = 0;
14117+ isdir = 0;
14118+ bstart = au_dbstart(dentry);
14119+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
14120+ mode = h_inode->i_mode;
14121+ switch (mode & S_IFMT) {
14122+ case S_IFREG:
14123+ btail = au_dbtail(dentry);
14124+ inode->i_op = &aufs_iop;
14125+ inode->i_fop = &aufs_file_fop;
14126+ err = au_dy_iaop(inode, bstart, h_inode);
14127+ if (unlikely(err))
14128+ goto out;
14129+ break;
14130+ case S_IFDIR:
14131+ isdir = 1;
14132+ btail = au_dbtaildir(dentry);
14133+ inode->i_op = &aufs_dir_iop;
14134+ inode->i_fop = &aufs_dir_fop;
14135+ break;
14136+ case S_IFLNK:
14137+ btail = au_dbtail(dentry);
14138+ inode->i_op = &aufs_symlink_iop;
14139+ break;
14140+ case S_IFBLK:
14141+ case S_IFCHR:
14142+ case S_IFIFO:
14143+ case S_IFSOCK:
14144+ btail = au_dbtail(dentry);
14145+ inode->i_op = &aufs_iop;
14146+ au_init_special_fop(inode, mode, h_inode->i_rdev);
14147+ break;
14148+ default:
14149+ AuIOErr("Unknown file type 0%o\n", mode);
14150+ err = -EIO;
1308ab2a 14151+ goto out;
4a4d8108 14152+ }
dece6358 14153+
4a4d8108
AM
14154+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
14155+ flags = au_hi_flags(inode, isdir);
14156+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
14157+ && au_ftest_hi(flags, HNOTIFY)
14158+ && dentry->d_name.len > AUFS_WH_PFX_LEN
14159+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
14160+ au_fclr_hi(flags, HNOTIFY);
14161+ iinfo = au_ii(inode);
14162+ iinfo->ii_bstart = bstart;
14163+ iinfo->ii_bend = btail;
14164+ for (bindex = bstart; bindex <= btail; bindex++) {
14165+ h_dentry = au_h_dptr(dentry, bindex);
14166+ if (h_dentry)
14167+ au_set_h_iptr(inode, bindex,
14168+ au_igrab(h_dentry->d_inode), flags);
14169+ }
14170+ au_cpup_attr_all(inode, /*force*/1);
dece6358 14171+
4f0767ce 14172+out:
4a4d8108
AM
14173+ return err;
14174+}
dece6358 14175+
027c5e7a
AM
14176+/*
14177+ * successful returns with iinfo write_locked
14178+ * minus: errno
14179+ * zero: success, matched
14180+ * plus: no error, but unmatched
14181+ */
14182+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
14183+{
14184+ int err;
14185+ aufs_bindex_t bindex, bend;
14186+ struct inode *h_inode, *h_dinode;
dece6358 14187+
4a4d8108
AM
14188+ /*
14189+ * before this function, if aufs got any iinfo lock, it must be only
14190+ * one, the parent dir.
14191+ * it can happen by UDBA and the obsoleted inode number.
14192+ */
14193+ err = -EIO;
14194+ if (unlikely(inode->i_ino == parent_ino(dentry)))
14195+ goto out;
14196+
027c5e7a 14197+ err = 1;
4a4d8108
AM
14198+ ii_write_lock_new_child(inode);
14199+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
14200+ bend = au_ibend(inode);
14201+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
14202+ h_inode = au_h_iptr(inode, bindex);
14203+ if (h_inode && h_inode == h_dinode) {
4a4d8108 14204+ err = 0;
027c5e7a 14205+ if (au_iigen_test(inode, au_digen(dentry)))
4a4d8108
AM
14206+ err = au_refresh_hinode(inode, dentry);
14207+ break;
1308ab2a 14208+ }
1facf9fc 14209+ }
dece6358 14210+
4a4d8108
AM
14211+ if (unlikely(err))
14212+ ii_write_unlock(inode);
4f0767ce 14213+out:
1facf9fc 14214+ return err;
14215+}
1facf9fc 14216+
4a4d8108
AM
14217+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
14218+ unsigned int d_type, ino_t *ino)
1facf9fc 14219+{
4a4d8108
AM
14220+ int err;
14221+ struct mutex *mtx;
1facf9fc 14222+
b752ccd1 14223+ /* prevent hardlinked inode number from race condition */
4a4d8108 14224+ mtx = NULL;
b752ccd1 14225+ if (d_type != DT_DIR) {
4a4d8108
AM
14226+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
14227+ mutex_lock(mtx);
14228+ }
14229+ err = au_xino_read(sb, bindex, h_ino, ino);
14230+ if (unlikely(err))
14231+ goto out;
1308ab2a 14232+
4a4d8108
AM
14233+ if (!*ino) {
14234+ err = -EIO;
14235+ *ino = au_xino_new_ino(sb);
14236+ if (unlikely(!*ino))
1facf9fc 14237+ goto out;
4a4d8108
AM
14238+ err = au_xino_write(sb, bindex, h_ino, *ino);
14239+ if (unlikely(err))
1308ab2a 14240+ goto out;
1308ab2a 14241+ }
1facf9fc 14242+
4f0767ce 14243+out:
b752ccd1 14244+ if (mtx)
4a4d8108 14245+ mutex_unlock(mtx);
1facf9fc 14246+ return err;
14247+}
14248+
4a4d8108
AM
14249+/* successful returns with iinfo write_locked */
14250+/* todo: return with unlocked? */
14251+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 14252+{
b752ccd1 14253+ struct inode *inode, *h_inode;
4a4d8108
AM
14254+ struct dentry *h_dentry;
14255+ struct super_block *sb;
b752ccd1 14256+ struct mutex *mtx;
4a4d8108 14257+ ino_t h_ino, ino;
2dfbb274 14258+ int err, lc_idx;
4a4d8108 14259+ aufs_bindex_t bstart;
1facf9fc 14260+
4a4d8108
AM
14261+ sb = dentry->d_sb;
14262+ bstart = au_dbstart(dentry);
14263+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
14264+ h_inode = h_dentry->d_inode;
14265+ h_ino = h_inode->i_ino;
14266+
14267+ /*
14268+ * stop 'race'-ing between hardlinks under different
14269+ * parents.
14270+ */
14271+ mtx = NULL;
14272+ if (!S_ISDIR(h_inode->i_mode))
14273+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
14274+
4f0767ce 14275+new_ino:
b752ccd1
AM
14276+ if (mtx)
14277+ mutex_lock(mtx);
4a4d8108
AM
14278+ err = au_xino_read(sb, bstart, h_ino, &ino);
14279+ inode = ERR_PTR(err);
14280+ if (unlikely(err))
14281+ goto out;
b752ccd1 14282+
4a4d8108
AM
14283+ if (!ino) {
14284+ ino = au_xino_new_ino(sb);
14285+ if (unlikely(!ino)) {
14286+ inode = ERR_PTR(-EIO);
dece6358
AM
14287+ goto out;
14288+ }
14289+ }
1facf9fc 14290+
4a4d8108
AM
14291+ AuDbg("i%lu\n", (unsigned long)ino);
14292+ inode = au_iget_locked(sb, ino);
14293+ err = PTR_ERR(inode);
14294+ if (IS_ERR(inode))
1facf9fc 14295+ goto out;
1facf9fc 14296+
4a4d8108
AM
14297+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
14298+ if (inode->i_state & I_NEW) {
2dfbb274
AM
14299+ lc_idx = AuLcNonDir_IIINFO;
14300+ if (S_ISLNK(h_inode->i_mode))
14301+ lc_idx = AuLcSymlink_IIINFO;
14302+ else if (S_ISDIR(h_inode->i_mode))
14303+ lc_idx = AuLcDir_IIINFO;
14304+ au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + lc_idx);
14305+
4a4d8108
AM
14306+ ii_write_lock_new_child(inode);
14307+ err = set_inode(inode, dentry);
14308+ if (!err) {
14309+ unlock_new_inode(inode);
14310+ goto out; /* success */
14311+ }
1308ab2a 14312+
027c5e7a
AM
14313+ /*
14314+ * iget_failed() calls iput(), but we need to call
14315+ * ii_write_unlock() after iget_failed(). so dirty hack for
14316+ * i_count.
14317+ */
14318+ atomic_inc(&inode->i_count);
4a4d8108 14319+ iget_failed(inode);
027c5e7a
AM
14320+ ii_write_unlock(inode);
14321+ au_xino_write(sb, bstart, h_ino, /*ino*/0);
14322+ /* ignore this error */
14323+ goto out_iput;
14324+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
14325+ /*
14326+ * horrible race condition between lookup, readdir and copyup
14327+ * (or something).
14328+ */
14329+ if (mtx)
14330+ mutex_unlock(mtx);
027c5e7a
AM
14331+ err = reval_inode(inode, dentry);
14332+ if (unlikely(err < 0)) {
14333+ mtx = NULL;
14334+ goto out_iput;
14335+ }
14336+
b752ccd1
AM
14337+ if (!err) {
14338+ mtx = NULL;
4a4d8108 14339+ goto out; /* success */
b752ccd1
AM
14340+ } else if (mtx)
14341+ mutex_lock(mtx);
4a4d8108
AM
14342+ }
14343+
14344+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
14345+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
14346+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
14347+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
14348+ (unsigned long)h_ino, (unsigned long)ino);
14349+ ino = 0;
14350+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
14351+ if (!err) {
14352+ iput(inode);
b752ccd1
AM
14353+ if (mtx)
14354+ mutex_unlock(mtx);
4a4d8108
AM
14355+ goto new_ino;
14356+ }
1308ab2a 14357+
4f0767ce 14358+out_iput:
4a4d8108 14359+ iput(inode);
4a4d8108 14360+ inode = ERR_PTR(err);
4f0767ce 14361+out:
b752ccd1
AM
14362+ if (mtx)
14363+ mutex_unlock(mtx);
4a4d8108 14364+ return inode;
1facf9fc 14365+}
14366+
4a4d8108 14367+/* ---------------------------------------------------------------------- */
1facf9fc 14368+
4a4d8108
AM
14369+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
14370+ struct inode *inode)
14371+{
14372+ int err;
1facf9fc 14373+
4a4d8108 14374+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 14375+
4a4d8108
AM
14376+ /* pseudo-link after flushed may happen out of bounds */
14377+ if (!err
14378+ && inode
14379+ && au_ibstart(inode) <= bindex
14380+ && bindex <= au_ibend(inode)) {
14381+ /*
14382+ * permission check is unnecessary since vfsub routine
14383+ * will be called later
14384+ */
14385+ struct inode *hi = au_h_iptr(inode, bindex);
14386+ if (hi)
14387+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 14388+ }
14389+
4a4d8108
AM
14390+ return err;
14391+}
dece6358 14392+
4a4d8108
AM
14393+int au_test_h_perm(struct inode *h_inode, int mask)
14394+{
2dfbb274 14395+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
4a4d8108
AM
14396+ return 0;
14397+ return inode_permission(h_inode, mask);
14398+}
1facf9fc 14399+
4a4d8108
AM
14400+int au_test_h_perm_sio(struct inode *h_inode, int mask)
14401+{
14402+ if (au_test_nfs(h_inode->i_sb)
14403+ && (mask & MAY_WRITE)
14404+ && S_ISDIR(h_inode->i_mode))
14405+ mask |= MAY_READ; /* force permission check */
14406+ return au_test_h_perm(h_inode, mask);
1facf9fc 14407+}
7f207e10
AM
14408diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
14409--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 14410+++ linux/fs/aufs/inode.h 2012-08-26 08:39:00.760508065 +0200
7eafdf33 14411@@ -0,0 +1,560 @@
4a4d8108 14412+/*
f6c5ef8b 14413+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
14414+ *
14415+ * This program, aufs is free software; you can redistribute it and/or modify
14416+ * it under the terms of the GNU General Public License as published by
14417+ * the Free Software Foundation; either version 2 of the License, or
14418+ * (at your option) any later version.
14419+ *
14420+ * This program is distributed in the hope that it will be useful,
14421+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14422+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14423+ * GNU General Public License for more details.
14424+ *
14425+ * You should have received a copy of the GNU General Public License
14426+ * along with this program; if not, write to the Free Software
14427+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14428+ */
1facf9fc 14429+
1308ab2a 14430+/*
4a4d8108 14431+ * inode operations
1308ab2a 14432+ */
dece6358 14433+
4a4d8108
AM
14434+#ifndef __AUFS_INODE_H__
14435+#define __AUFS_INODE_H__
dece6358 14436+
4a4d8108 14437+#ifdef __KERNEL__
1308ab2a 14438+
4a4d8108 14439+#include <linux/fsnotify.h>
4a4d8108 14440+#include "rwsem.h"
1308ab2a 14441+
4a4d8108 14442+struct vfsmount;
1facf9fc 14443+
4a4d8108
AM
14444+struct au_hnotify {
14445+#ifdef CONFIG_AUFS_HNOTIFY
14446+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 14447+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 14448+ struct fsnotify_mark hn_mark;
4a4d8108 14449+#endif
7f207e10 14450+ struct inode *hn_aufs_inode; /* no get/put */
4a4d8108
AM
14451+#endif
14452+} ____cacheline_aligned_in_smp;
1facf9fc 14453+
4a4d8108
AM
14454+struct au_hinode {
14455+ struct inode *hi_inode;
14456+ aufs_bindex_t hi_id;
14457+#ifdef CONFIG_AUFS_HNOTIFY
14458+ struct au_hnotify *hi_notify;
14459+#endif
dece6358 14460+
4a4d8108
AM
14461+ /* reference to the copied-up whiteout with get/put */
14462+ struct dentry *hi_whdentry;
14463+};
dece6358 14464+
4a4d8108
AM
14465+struct au_vdir;
14466+struct au_iinfo {
14467+ atomic_t ii_generation;
14468+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 14469+
4a4d8108
AM
14470+ struct au_rwsem ii_rwsem;
14471+ aufs_bindex_t ii_bstart, ii_bend;
14472+ __u32 ii_higen;
14473+ struct au_hinode *ii_hinode;
14474+ struct au_vdir *ii_vdir;
14475+};
1facf9fc 14476+
4a4d8108
AM
14477+struct au_icntnr {
14478+ struct au_iinfo iinfo;
14479+ struct inode vfs_inode;
14480+} ____cacheline_aligned_in_smp;
1308ab2a 14481+
4a4d8108
AM
14482+/* au_pin flags */
14483+#define AuPin_DI_LOCKED 1
14484+#define AuPin_MNT_WRITE (1 << 1)
14485+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
14486+#define au_fset_pin(flags, name) \
14487+ do { (flags) |= AuPin_##name; } while (0)
14488+#define au_fclr_pin(flags, name) \
14489+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
14490+
14491+struct au_pin {
14492+ /* input */
14493+ struct dentry *dentry;
14494+ unsigned int udba;
14495+ unsigned char lsc_di, lsc_hi, flags;
14496+ aufs_bindex_t bindex;
14497+
14498+ /* output */
14499+ struct dentry *parent;
14500+ struct au_hinode *hdir;
14501+ struct vfsmount *h_mnt;
14502+};
1facf9fc 14503+
1308ab2a 14504+/* ---------------------------------------------------------------------- */
14505+
4a4d8108 14506+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 14507+{
4a4d8108 14508+ struct au_iinfo *iinfo;
1facf9fc 14509+
4a4d8108
AM
14510+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
14511+ if (iinfo->ii_hinode)
14512+ return iinfo;
14513+ return NULL; /* debugging bad_inode case */
14514+}
1facf9fc 14515+
4a4d8108 14516+/* ---------------------------------------------------------------------- */
1facf9fc 14517+
4a4d8108
AM
14518+/* inode.c */
14519+struct inode *au_igrab(struct inode *inode);
027c5e7a 14520+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
14521+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
14522+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
14523+ unsigned int d_type, ino_t *ino);
14524+struct inode *au_new_inode(struct dentry *dentry, int must_new);
14525+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
14526+ struct inode *inode);
14527+int au_test_h_perm(struct inode *h_inode, int mask);
14528+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 14529+
4a4d8108
AM
14530+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
14531+ ino_t h_ino, unsigned int d_type, ino_t *ino)
14532+{
14533+#ifdef CONFIG_AUFS_SHWH
14534+ return au_ino(sb, bindex, h_ino, d_type, ino);
14535+#else
14536+ return 0;
14537+#endif
14538+}
1facf9fc 14539+
4a4d8108
AM
14540+/* i_op.c */
14541+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 14542+
4a4d8108
AM
14543+/* au_wr_dir flags */
14544+#define AuWrDir_ADD_ENTRY 1
14545+#define AuWrDir_ISDIR (1 << 1)
14546+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
14547+#define au_fset_wrdir(flags, name) \
14548+ do { (flags) |= AuWrDir_##name; } while (0)
14549+#define au_fclr_wrdir(flags, name) \
14550+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 14551+
4a4d8108
AM
14552+struct au_wr_dir_args {
14553+ aufs_bindex_t force_btgt;
14554+ unsigned char flags;
14555+};
14556+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14557+ struct au_wr_dir_args *args);
dece6358 14558+
4a4d8108
AM
14559+struct dentry *au_pinned_h_parent(struct au_pin *pin);
14560+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
14561+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14562+ unsigned int udba, unsigned char flags);
14563+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14564+ unsigned int udba, unsigned char flags) __must_check;
14565+int au_do_pin(struct au_pin *pin) __must_check;
14566+void au_unpin(struct au_pin *pin);
1facf9fc 14567+
4a4d8108
AM
14568+/* i_op_add.c */
14569+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
14570+ struct dentry *h_parent, int isdir);
7eafdf33
AM
14571+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
14572+ dev_t dev);
4a4d8108 14573+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
7eafdf33 14574+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
4a4d8108
AM
14575+ struct nameidata *nd);
14576+int aufs_link(struct dentry *src_dentry, struct inode *dir,
14577+ struct dentry *dentry);
7eafdf33 14578+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
1facf9fc 14579+
4a4d8108
AM
14580+/* i_op_del.c */
14581+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
14582+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14583+ struct dentry *h_parent, int isdir);
14584+int aufs_unlink(struct inode *dir, struct dentry *dentry);
14585+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 14586+
4a4d8108
AM
14587+/* i_op_ren.c */
14588+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
14589+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
14590+ struct inode *dir, struct dentry *dentry);
1facf9fc 14591+
4a4d8108
AM
14592+/* iinfo.c */
14593+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
14594+void au_hiput(struct au_hinode *hinode);
14595+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
14596+ struct dentry *h_wh);
14597+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 14598+
4a4d8108
AM
14599+/* hinode flags */
14600+#define AuHi_XINO 1
14601+#define AuHi_HNOTIFY (1 << 1)
14602+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
14603+#define au_fset_hi(flags, name) \
14604+ do { (flags) |= AuHi_##name; } while (0)
14605+#define au_fclr_hi(flags, name) \
14606+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 14607+
4a4d8108
AM
14608+#ifndef CONFIG_AUFS_HNOTIFY
14609+#undef AuHi_HNOTIFY
14610+#define AuHi_HNOTIFY 0
14611+#endif
1facf9fc 14612+
4a4d8108
AM
14613+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
14614+ struct inode *h_inode, unsigned int flags);
1facf9fc 14615+
4a4d8108
AM
14616+void au_update_iigen(struct inode *inode);
14617+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 14618+
4a4d8108
AM
14619+void au_icntnr_init_once(void *_c);
14620+int au_iinfo_init(struct inode *inode);
14621+void au_iinfo_fin(struct inode *inode);
14622+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 14623+
e49829fe 14624+#ifdef CONFIG_PROC_FS
4a4d8108 14625+/* plink.c */
e49829fe
JR
14626+int au_plink_maint(struct super_block *sb, int flags);
14627+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
14628+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
14629+#ifdef CONFIG_AUFS_DEBUG
14630+void au_plink_list(struct super_block *sb);
14631+#else
14632+AuStubVoid(au_plink_list, struct super_block *sb)
14633+#endif
14634+int au_plink_test(struct inode *inode);
14635+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
14636+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
14637+ struct dentry *h_dentry);
e49829fe
JR
14638+void au_plink_put(struct super_block *sb, int verbose);
14639+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 14640+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
14641+#else
14642+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
14643+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
14644+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
14645+AuStubVoid(au_plink_list, struct super_block *sb);
14646+AuStubInt0(au_plink_test, struct inode *inode);
14647+AuStub(struct dentry *, au_plink_lkup, return NULL,
14648+ struct inode *inode, aufs_bindex_t bindex);
14649+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
14650+ struct dentry *h_dentry);
14651+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
14652+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
14653+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
14654+#endif /* CONFIG_PROC_FS */
1facf9fc 14655+
4a4d8108 14656+/* ---------------------------------------------------------------------- */
1308ab2a 14657+
4a4d8108
AM
14658+/* lock subclass for iinfo */
14659+enum {
14660+ AuLsc_II_CHILD, /* child first */
14661+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
14662+ AuLsc_II_CHILD3, /* copyup dirs */
14663+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
14664+ AuLsc_II_PARENT2,
14665+ AuLsc_II_PARENT3, /* copyup dirs */
14666+ AuLsc_II_NEW_CHILD
14667+};
1308ab2a 14668+
1facf9fc 14669+/*
4a4d8108
AM
14670+ * ii_read_lock_child, ii_write_lock_child,
14671+ * ii_read_lock_child2, ii_write_lock_child2,
14672+ * ii_read_lock_child3, ii_write_lock_child3,
14673+ * ii_read_lock_parent, ii_write_lock_parent,
14674+ * ii_read_lock_parent2, ii_write_lock_parent2,
14675+ * ii_read_lock_parent3, ii_write_lock_parent3,
14676+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 14677+ */
4a4d8108
AM
14678+#define AuReadLockFunc(name, lsc) \
14679+static inline void ii_read_lock_##name(struct inode *i) \
14680+{ \
14681+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
14682+}
14683+
14684+#define AuWriteLockFunc(name, lsc) \
14685+static inline void ii_write_lock_##name(struct inode *i) \
14686+{ \
14687+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
14688+}
14689+
14690+#define AuRWLockFuncs(name, lsc) \
14691+ AuReadLockFunc(name, lsc) \
14692+ AuWriteLockFunc(name, lsc)
14693+
14694+AuRWLockFuncs(child, CHILD);
14695+AuRWLockFuncs(child2, CHILD2);
14696+AuRWLockFuncs(child3, CHILD3);
14697+AuRWLockFuncs(parent, PARENT);
14698+AuRWLockFuncs(parent2, PARENT2);
14699+AuRWLockFuncs(parent3, PARENT3);
14700+AuRWLockFuncs(new_child, NEW_CHILD);
14701+
14702+#undef AuReadLockFunc
14703+#undef AuWriteLockFunc
14704+#undef AuRWLockFuncs
1facf9fc 14705+
14706+/*
4a4d8108 14707+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 14708+ */
4a4d8108 14709+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 14710+
4a4d8108
AM
14711+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
14712+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
14713+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 14714+
4a4d8108 14715+/* ---------------------------------------------------------------------- */
1308ab2a 14716+
027c5e7a
AM
14717+static inline void au_icntnr_init(struct au_icntnr *c)
14718+{
14719+#ifdef CONFIG_AUFS_DEBUG
14720+ c->vfs_inode.i_mode = 0;
14721+#endif
14722+}
14723+
4a4d8108
AM
14724+static inline unsigned int au_iigen(struct inode *inode)
14725+{
14726+ return atomic_read(&au_ii(inode)->ii_generation);
14727+}
1308ab2a 14728+
4a4d8108
AM
14729+/* tiny test for inode number */
14730+/* tmpfs generation is too rough */
14731+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
14732+{
14733+ struct au_iinfo *iinfo;
1308ab2a 14734+
4a4d8108
AM
14735+ iinfo = au_ii(inode);
14736+ AuRwMustAnyLock(&iinfo->ii_rwsem);
14737+ return !(iinfo->ii_hsb1 == h_inode->i_sb
14738+ && iinfo->ii_higen == h_inode->i_generation);
14739+}
1308ab2a 14740+
4a4d8108
AM
14741+static inline void au_iigen_dec(struct inode *inode)
14742+{
e49829fe 14743+ atomic_dec(&au_ii(inode)->ii_generation);
027c5e7a
AM
14744+}
14745+
14746+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
14747+{
14748+ int err;
14749+
14750+ err = 0;
14751+ if (unlikely(inode && au_iigen(inode) != sigen))
14752+ err = -EIO;
14753+
14754+ return err;
4a4d8108 14755+}
1308ab2a 14756+
4a4d8108 14757+/* ---------------------------------------------------------------------- */
1308ab2a 14758+
4a4d8108
AM
14759+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
14760+ aufs_bindex_t bindex)
14761+{
14762+ IiMustAnyLock(inode);
14763+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
14764+}
1308ab2a 14765+
4a4d8108
AM
14766+static inline aufs_bindex_t au_ibstart(struct inode *inode)
14767+{
14768+ IiMustAnyLock(inode);
14769+ return au_ii(inode)->ii_bstart;
14770+}
1308ab2a 14771+
4a4d8108
AM
14772+static inline aufs_bindex_t au_ibend(struct inode *inode)
14773+{
14774+ IiMustAnyLock(inode);
14775+ return au_ii(inode)->ii_bend;
14776+}
1308ab2a 14777+
4a4d8108
AM
14778+static inline struct au_vdir *au_ivdir(struct inode *inode)
14779+{
14780+ IiMustAnyLock(inode);
14781+ return au_ii(inode)->ii_vdir;
14782+}
1308ab2a 14783+
4a4d8108
AM
14784+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
14785+{
14786+ IiMustAnyLock(inode);
14787+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
14788+}
1308ab2a 14789+
4a4d8108 14790+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 14791+{
4a4d8108
AM
14792+ IiMustWriteLock(inode);
14793+ au_ii(inode)->ii_bstart = bindex;
14794+}
1308ab2a 14795+
4a4d8108
AM
14796+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
14797+{
14798+ IiMustWriteLock(inode);
14799+ au_ii(inode)->ii_bend = bindex;
1308ab2a 14800+}
14801+
4a4d8108
AM
14802+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
14803+{
14804+ IiMustWriteLock(inode);
14805+ au_ii(inode)->ii_vdir = vdir;
14806+}
1facf9fc 14807+
4a4d8108 14808+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 14809+{
4a4d8108
AM
14810+ IiMustAnyLock(inode);
14811+ return au_ii(inode)->ii_hinode + bindex;
14812+}
dece6358 14813+
4a4d8108 14814+/* ---------------------------------------------------------------------- */
1facf9fc 14815+
4a4d8108
AM
14816+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
14817+{
14818+ if (pin)
14819+ return pin->parent;
14820+ return NULL;
1facf9fc 14821+}
14822+
4a4d8108 14823+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 14824+{
4a4d8108
AM
14825+ if (pin && pin->hdir)
14826+ return pin->hdir->hi_inode;
14827+ return NULL;
1308ab2a 14828+}
1facf9fc 14829+
4a4d8108
AM
14830+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
14831+{
14832+ if (pin)
14833+ return pin->hdir;
14834+ return NULL;
14835+}
1facf9fc 14836+
4a4d8108 14837+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 14838+{
4a4d8108
AM
14839+ if (pin)
14840+ pin->dentry = dentry;
14841+}
1308ab2a 14842+
4a4d8108
AM
14843+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
14844+ unsigned char lflag)
14845+{
14846+ if (pin) {
7f207e10 14847+ if (lflag)
4a4d8108 14848+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 14849+ else
4a4d8108 14850+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 14851+ }
4a4d8108
AM
14852+}
14853+
14854+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
14855+{
14856+ if (pin) {
14857+ dput(pin->parent);
14858+ pin->parent = dget(parent);
1facf9fc 14859+ }
4a4d8108 14860+}
1facf9fc 14861+
4a4d8108
AM
14862+/* ---------------------------------------------------------------------- */
14863+
027c5e7a 14864+struct au_branch;
4a4d8108
AM
14865+#ifdef CONFIG_AUFS_HNOTIFY
14866+struct au_hnotify_op {
14867+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a 14868+ int (*alloc)(struct au_hinode *hinode);
7eafdf33
AM
14869+
14870+ /*
14871+ * if it returns true, the the caller should free hinode->hi_notify,
14872+ * otherwise ->free() frees it.
14873+ */
14874+ int (*free)(struct au_hinode *hinode,
14875+ struct au_hnotify *hn) __must_check;
4a4d8108
AM
14876+
14877+ void (*fin)(void);
14878+ int (*init)(void);
027c5e7a
AM
14879+
14880+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
14881+ void (*fin_br)(struct au_branch *br);
14882+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
14883+};
14884+
14885+/* hnotify.c */
027c5e7a 14886+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
14887+void au_hn_free(struct au_hinode *hinode);
14888+void au_hn_ctl(struct au_hinode *hinode, int do_set);
14889+void au_hn_reset(struct inode *inode, unsigned int flags);
14890+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
14891+ struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
14892+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
14893+int au_hnotify_init_br(struct au_branch *br, int perm);
14894+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
14895+int __init au_hnotify_init(void);
14896+void au_hnotify_fin(void);
14897+
7f207e10 14898+/* hfsnotify.c */
4a4d8108
AM
14899+extern const struct au_hnotify_op au_hnotify_op;
14900+
14901+static inline
14902+void au_hn_init(struct au_hinode *hinode)
14903+{
14904+ hinode->hi_notify = NULL;
1308ab2a 14905+}
14906+
53392da6
AM
14907+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
14908+{
14909+ return hinode->hi_notify;
14910+}
14911+
4a4d8108
AM
14912+#else
14913+static inline
14914+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
027c5e7a 14915+ struct inode *inode __maybe_unused)
1308ab2a 14916+{
4a4d8108
AM
14917+ return -EOPNOTSUPP;
14918+}
1308ab2a 14919+
53392da6
AM
14920+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
14921+{
14922+ return NULL;
14923+}
14924+
4a4d8108
AM
14925+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
14926+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
14927+ int do_set __maybe_unused)
14928+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
14929+ unsigned int flags __maybe_unused)
027c5e7a
AM
14930+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
14931+ struct au_branch *br __maybe_unused,
14932+ int perm __maybe_unused)
14933+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
14934+ int perm __maybe_unused)
14935+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
14936+AuStubInt0(__init au_hnotify_init, void)
14937+AuStubVoid(au_hnotify_fin, void)
14938+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
14939+#endif /* CONFIG_AUFS_HNOTIFY */
14940+
14941+static inline void au_hn_suspend(struct au_hinode *hdir)
14942+{
14943+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 14944+}
14945+
4a4d8108 14946+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 14947+{
4a4d8108
AM
14948+ au_hn_ctl(hdir, /*do_set*/1);
14949+}
1308ab2a 14950+
4a4d8108
AM
14951+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
14952+{
14953+ mutex_lock(&hdir->hi_inode->i_mutex);
14954+ au_hn_suspend(hdir);
14955+}
dece6358 14956+
4a4d8108
AM
14957+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
14958+ unsigned int sc __maybe_unused)
14959+{
14960+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
14961+ au_hn_suspend(hdir);
1facf9fc 14962+}
1facf9fc 14963+
4a4d8108
AM
14964+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
14965+{
14966+ au_hn_resume(hdir);
14967+ mutex_unlock(&hdir->hi_inode->i_mutex);
14968+}
14969+
14970+#endif /* __KERNEL__ */
14971+#endif /* __AUFS_INODE_H__ */
7f207e10
AM
14972diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
14973--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 14974+++ linux/fs/aufs/ioctl.c 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 14975@@ -0,0 +1,196 @@
4a4d8108 14976+/*
f6c5ef8b 14977+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
14978+ *
14979+ * This program, aufs is free software; you can redistribute it and/or modify
14980+ * it under the terms of the GNU General Public License as published by
14981+ * the Free Software Foundation; either version 2 of the License, or
14982+ * (at your option) any later version.
14983+ *
14984+ * This program is distributed in the hope that it will be useful,
14985+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14986+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14987+ * GNU General Public License for more details.
14988+ *
14989+ * You should have received a copy of the GNU General Public License
14990+ * along with this program; if not, write to the Free Software
14991+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14992+ */
14993+
14994+/*
14995+ * ioctl
14996+ * plink-management and readdir in userspace.
14997+ * assist the pathconf(3) wrapper library.
14998+ */
14999+
4a4d8108
AM
15000+#include "aufs.h"
15001+
1e00d052 15002+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
4a4d8108
AM
15003+{
15004+ int err, fd;
15005+ aufs_bindex_t wbi, bindex, bend;
15006+ struct file *h_file;
15007+ struct super_block *sb;
15008+ struct dentry *root;
1e00d052
AM
15009+ struct au_branch *br;
15010+ struct aufs_wbr_fd wbrfd = {
15011+ .oflags = au_dir_roflags,
15012+ .brid = -1
15013+ };
15014+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
15015+ | O_NOATIME | O_CLOEXEC;
4a4d8108 15016+
1e00d052
AM
15017+ AuDebugOn(wbrfd.oflags & ~valid);
15018+
15019+ if (arg) {
15020+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
15021+ if (unlikely(err)) {
15022+ err = -EFAULT;
15023+ goto out;
15024+ }
15025+
15026+ err = -EINVAL;
15027+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
15028+ wbrfd.oflags |= au_dir_roflags;
15029+ AuDbg("0%o\n", wbrfd.oflags);
15030+ if (unlikely(wbrfd.oflags & ~valid))
15031+ goto out;
15032+ }
15033+
15034+ fd = get_unused_fd();
15035+ err = fd;
15036+ if (unlikely(fd < 0))
4a4d8108 15037+ goto out;
4a4d8108 15038+
1e00d052 15039+ h_file = ERR_PTR(-EINVAL);
4a4d8108 15040+ wbi = 0;
1e00d052 15041+ br = NULL;
4a4d8108
AM
15042+ sb = path->dentry->d_sb;
15043+ root = sb->s_root;
15044+ aufs_read_lock(root, AuLock_IR);
1e00d052
AM
15045+ bend = au_sbend(sb);
15046+ if (wbrfd.brid >= 0) {
15047+ wbi = au_br_index(sb, wbrfd.brid);
15048+ if (unlikely(wbi < 0 || wbi > bend))
15049+ goto out_unlock;
15050+ }
15051+
15052+ h_file = ERR_PTR(-ENOENT);
15053+ br = au_sbr(sb, wbi);
15054+ if (!au_br_writable(br->br_perm)) {
15055+ if (arg)
15056+ goto out_unlock;
15057+
15058+ bindex = wbi + 1;
15059+ wbi = -1;
15060+ for (; bindex <= bend; bindex++) {
15061+ br = au_sbr(sb, bindex);
15062+ if (au_br_writable(br->br_perm)) {
4a4d8108 15063+ wbi = bindex;
1e00d052 15064+ br = au_sbr(sb, wbi);
4a4d8108
AM
15065+ break;
15066+ }
15067+ }
4a4d8108
AM
15068+ }
15069+ AuDbg("wbi %d\n", wbi);
1e00d052
AM
15070+ if (wbi >= 0)
15071+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL);
15072+
15073+out_unlock:
4a4d8108
AM
15074+ aufs_read_unlock(root, AuLock_IR);
15075+ err = PTR_ERR(h_file);
15076+ if (IS_ERR(h_file))
15077+ goto out_fd;
15078+
1e00d052 15079+ atomic_dec(&br->br_count); /* cf. au_h_open() */
4a4d8108
AM
15080+ fd_install(fd, h_file);
15081+ err = fd;
15082+ goto out; /* success */
15083+
4f0767ce 15084+out_fd:
4a4d8108 15085+ put_unused_fd(fd);
4f0767ce 15086+out:
1e00d052 15087+ AuTraceErr(err);
4a4d8108
AM
15088+ return err;
15089+}
15090+
15091+/* ---------------------------------------------------------------------- */
15092+
15093+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
15094+{
15095+ long err;
15096+
15097+ switch (cmd) {
4a4d8108
AM
15098+ case AUFS_CTL_RDU:
15099+ case AUFS_CTL_RDU_INO:
15100+ err = au_rdu_ioctl(file, cmd, arg);
15101+ break;
15102+
15103+ case AUFS_CTL_WBR_FD:
1e00d052 15104+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
15105+ break;
15106+
027c5e7a
AM
15107+ case AUFS_CTL_IBUSY:
15108+ err = au_ibusy_ioctl(file, arg);
15109+ break;
15110+
4a4d8108
AM
15111+ default:
15112+ /* do not call the lower */
15113+ AuDbg("0x%x\n", cmd);
15114+ err = -ENOTTY;
15115+ }
15116+
15117+ AuTraceErr(err);
15118+ return err;
15119+}
15120+
15121+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
15122+{
15123+ long err;
15124+
15125+ switch (cmd) {
15126+ case AUFS_CTL_WBR_FD:
1e00d052 15127+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
15128+ break;
15129+
15130+ default:
15131+ /* do not call the lower */
15132+ AuDbg("0x%x\n", cmd);
15133+ err = -ENOTTY;
15134+ }
15135+
15136+ AuTraceErr(err);
15137+ return err;
15138+}
b752ccd1
AM
15139+
15140+#ifdef CONFIG_COMPAT
15141+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
15142+ unsigned long arg)
15143+{
15144+ long err;
15145+
15146+ switch (cmd) {
15147+ case AUFS_CTL_RDU:
15148+ case AUFS_CTL_RDU_INO:
15149+ err = au_rdu_compat_ioctl(file, cmd, arg);
15150+ break;
15151+
027c5e7a
AM
15152+ case AUFS_CTL_IBUSY:
15153+ err = au_ibusy_compat_ioctl(file, arg);
15154+ break;
15155+
b752ccd1
AM
15156+ default:
15157+ err = aufs_ioctl_dir(file, cmd, arg);
15158+ }
15159+
15160+ AuTraceErr(err);
15161+ return err;
15162+}
15163+
15164+#if 0 /* unused yet */
15165+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
15166+ unsigned long arg)
15167+{
15168+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
15169+}
15170+#endif
15171+#endif
7f207e10
AM
15172diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
15173--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 15174+++ linux/fs/aufs/i_op_add.c 2012-08-26 08:39:00.760508065 +0200
7eafdf33 15175@@ -0,0 +1,712 @@
4a4d8108 15176+/*
f6c5ef8b 15177+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
15178+ *
15179+ * This program, aufs is free software; you can redistribute it and/or modify
15180+ * it under the terms of the GNU General Public License as published by
15181+ * the Free Software Foundation; either version 2 of the License, or
15182+ * (at your option) any later version.
15183+ *
15184+ * This program is distributed in the hope that it will be useful,
15185+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15186+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15187+ * GNU General Public License for more details.
15188+ *
15189+ * You should have received a copy of the GNU General Public License
15190+ * along with this program; if not, write to the Free Software
15191+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15192+ */
15193+
15194+/*
15195+ * inode operations (add entry)
15196+ */
15197+
15198+#include "aufs.h"
15199+
15200+/*
15201+ * final procedure of adding a new entry, except link(2).
15202+ * remove whiteout, instantiate, copyup the parent dir's times and size
15203+ * and update version.
15204+ * if it failed, re-create the removed whiteout.
15205+ */
15206+static int epilog(struct inode *dir, aufs_bindex_t bindex,
15207+ struct dentry *wh_dentry, struct dentry *dentry)
15208+{
15209+ int err, rerr;
15210+ aufs_bindex_t bwh;
15211+ struct path h_path;
15212+ struct inode *inode, *h_dir;
15213+ struct dentry *wh;
15214+
15215+ bwh = -1;
15216+ if (wh_dentry) {
15217+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
15218+ IMustLock(h_dir);
15219+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
15220+ bwh = au_dbwh(dentry);
15221+ h_path.dentry = wh_dentry;
15222+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
15223+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
15224+ dentry);
15225+ if (unlikely(err))
15226+ goto out;
15227+ }
15228+
15229+ inode = au_new_inode(dentry, /*must_new*/1);
15230+ if (!IS_ERR(inode)) {
15231+ d_instantiate(dentry, inode);
15232+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
15233+ IMustLock(dir);
15234+ if (au_ibstart(dir) == au_dbstart(dentry))
15235+ au_cpup_attr_timesizes(dir);
15236+ dir->i_version++;
15237+ return 0; /* success */
15238+ }
15239+
15240+ err = PTR_ERR(inode);
15241+ if (!wh_dentry)
15242+ goto out;
15243+
15244+ /* revert */
15245+ /* dir inode is locked */
15246+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
15247+ rerr = PTR_ERR(wh);
15248+ if (IS_ERR(wh)) {
15249+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15250+ AuDLNPair(dentry), err, rerr);
15251+ err = -EIO;
15252+ } else
15253+ dput(wh);
15254+
4f0767ce 15255+out:
4a4d8108
AM
15256+ return err;
15257+}
15258+
027c5e7a
AM
15259+static int au_d_may_add(struct dentry *dentry)
15260+{
15261+ int err;
15262+
15263+ err = 0;
15264+ if (unlikely(d_unhashed(dentry)))
15265+ err = -ENOENT;
15266+ if (unlikely(dentry->d_inode))
15267+ err = -EEXIST;
15268+ return err;
15269+}
15270+
4a4d8108
AM
15271+/*
15272+ * simple tests for the adding inode operations.
15273+ * following the checks in vfs, plus the parent-child relationship.
15274+ */
15275+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
15276+ struct dentry *h_parent, int isdir)
15277+{
15278+ int err;
15279+ umode_t h_mode;
15280+ struct dentry *h_dentry;
15281+ struct inode *h_inode;
15282+
15283+ err = -ENAMETOOLONG;
15284+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
15285+ goto out;
15286+
15287+ h_dentry = au_h_dptr(dentry, bindex);
15288+ h_inode = h_dentry->d_inode;
15289+ if (!dentry->d_inode) {
15290+ err = -EEXIST;
15291+ if (unlikely(h_inode))
15292+ goto out;
15293+ } else {
15294+ /* rename(2) case */
15295+ err = -EIO;
15296+ if (unlikely(!h_inode || !h_inode->i_nlink))
15297+ goto out;
15298+
15299+ h_mode = h_inode->i_mode;
15300+ if (!isdir) {
15301+ err = -EISDIR;
15302+ if (unlikely(S_ISDIR(h_mode)))
15303+ goto out;
15304+ } else if (unlikely(!S_ISDIR(h_mode))) {
15305+ err = -ENOTDIR;
15306+ goto out;
15307+ }
15308+ }
15309+
15310+ err = 0;
15311+ /* expected parent dir is locked */
15312+ if (unlikely(h_parent != h_dentry->d_parent))
15313+ err = -EIO;
15314+
4f0767ce 15315+out:
4a4d8108
AM
15316+ AuTraceErr(err);
15317+ return err;
15318+}
15319+
15320+/*
15321+ * initial procedure of adding a new entry.
15322+ * prepare writable branch and the parent dir, lock it,
15323+ * and lookup whiteout for the new entry.
15324+ */
15325+static struct dentry*
15326+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
15327+ struct dentry *src_dentry, struct au_pin *pin,
15328+ struct au_wr_dir_args *wr_dir_args)
15329+{
15330+ struct dentry *wh_dentry, *h_parent;
15331+ struct super_block *sb;
15332+ struct au_branch *br;
15333+ int err;
15334+ unsigned int udba;
15335+ aufs_bindex_t bcpup;
15336+
15337+ AuDbg("%.*s\n", AuDLNPair(dentry));
15338+
15339+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
15340+ bcpup = err;
15341+ wh_dentry = ERR_PTR(err);
15342+ if (unlikely(err < 0))
15343+ goto out;
15344+
15345+ sb = dentry->d_sb;
15346+ udba = au_opt_udba(sb);
15347+ err = au_pin(pin, dentry, bcpup, udba,
15348+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15349+ wh_dentry = ERR_PTR(err);
15350+ if (unlikely(err))
15351+ goto out;
15352+
15353+ h_parent = au_pinned_h_parent(pin);
15354+ if (udba != AuOpt_UDBA_NONE
15355+ && au_dbstart(dentry) == bcpup)
15356+ err = au_may_add(dentry, bcpup, h_parent,
15357+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
15358+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
15359+ err = -ENAMETOOLONG;
15360+ wh_dentry = ERR_PTR(err);
15361+ if (unlikely(err))
15362+ goto out_unpin;
15363+
15364+ br = au_sbr(sb, bcpup);
15365+ if (dt) {
15366+ struct path tmp = {
15367+ .dentry = h_parent,
15368+ .mnt = br->br_mnt
15369+ };
15370+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
15371+ }
15372+
15373+ wh_dentry = NULL;
15374+ if (bcpup != au_dbwh(dentry))
15375+ goto out; /* success */
15376+
15377+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
15378+
4f0767ce 15379+out_unpin:
4a4d8108
AM
15380+ if (IS_ERR(wh_dentry))
15381+ au_unpin(pin);
4f0767ce 15382+out:
4a4d8108
AM
15383+ return wh_dentry;
15384+}
15385+
15386+/* ---------------------------------------------------------------------- */
15387+
15388+enum { Mknod, Symlink, Creat };
15389+struct simple_arg {
15390+ int type;
15391+ union {
15392+ struct {
7eafdf33 15393+ umode_t mode;
4a4d8108
AM
15394+ struct nameidata *nd;
15395+ } c;
15396+ struct {
15397+ const char *symname;
15398+ } s;
15399+ struct {
7eafdf33 15400+ umode_t mode;
4a4d8108
AM
15401+ dev_t dev;
15402+ } m;
15403+ } u;
15404+};
15405+
15406+static int add_simple(struct inode *dir, struct dentry *dentry,
15407+ struct simple_arg *arg)
15408+{
15409+ int err;
15410+ aufs_bindex_t bstart;
15411+ unsigned char created;
15412+ struct au_dtime dt;
15413+ struct au_pin pin;
15414+ struct path h_path;
15415+ struct dentry *wh_dentry, *parent;
15416+ struct inode *h_dir;
15417+ struct au_wr_dir_args wr_dir_args = {
15418+ .force_btgt = -1,
15419+ .flags = AuWrDir_ADD_ENTRY
15420+ };
15421+
15422+ AuDbg("%.*s\n", AuDLNPair(dentry));
15423+ IMustLock(dir);
15424+
15425+ parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
15426+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15427+ if (unlikely(err))
15428+ goto out;
15429+ err = au_d_may_add(dentry);
15430+ if (unlikely(err))
15431+ goto out_unlock;
4a4d8108
AM
15432+ di_write_lock_parent(parent);
15433+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
15434+ &wr_dir_args);
15435+ err = PTR_ERR(wh_dentry);
15436+ if (IS_ERR(wh_dentry))
027c5e7a 15437+ goto out_parent;
4a4d8108
AM
15438+
15439+ bstart = au_dbstart(dentry);
15440+ h_path.dentry = au_h_dptr(dentry, bstart);
15441+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
15442+ h_dir = au_pinned_h_dir(&pin);
15443+ switch (arg->type) {
15444+ case Creat:
15445+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
15446+ break;
15447+ case Symlink:
15448+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
15449+ break;
15450+ case Mknod:
15451+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
15452+ break;
15453+ default:
15454+ BUG();
15455+ }
15456+ created = !err;
15457+ if (!err)
15458+ err = epilog(dir, bstart, wh_dentry, dentry);
15459+
15460+ /* revert */
15461+ if (unlikely(created && err && h_path.dentry->d_inode)) {
15462+ int rerr;
15463+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
15464+ if (rerr) {
15465+ AuIOErr("%.*s revert failure(%d, %d)\n",
15466+ AuDLNPair(dentry), err, rerr);
15467+ err = -EIO;
15468+ }
15469+ au_dtime_revert(&dt);
4a4d8108
AM
15470+ }
15471+
15472+ au_unpin(&pin);
15473+ dput(wh_dentry);
15474+
027c5e7a
AM
15475+out_parent:
15476+ di_write_unlock(parent);
15477+out_unlock:
4a4d8108
AM
15478+ if (unlikely(err)) {
15479+ au_update_dbstart(dentry);
15480+ d_drop(dentry);
15481+ }
4a4d8108 15482+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15483+out:
4a4d8108
AM
15484+ return err;
15485+}
15486+
7eafdf33
AM
15487+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
15488+ dev_t dev)
4a4d8108
AM
15489+{
15490+ struct simple_arg arg = {
15491+ .type = Mknod,
15492+ .u.m = {
15493+ .mode = mode,
15494+ .dev = dev
15495+ }
15496+ };
15497+ return add_simple(dir, dentry, &arg);
15498+}
15499+
15500+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
15501+{
15502+ struct simple_arg arg = {
15503+ .type = Symlink,
15504+ .u.s.symname = symname
15505+ };
15506+ return add_simple(dir, dentry, &arg);
15507+}
15508+
7eafdf33 15509+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
4a4d8108
AM
15510+ struct nameidata *nd)
15511+{
15512+ struct simple_arg arg = {
15513+ .type = Creat,
15514+ .u.c = {
15515+ .mode = mode,
15516+ .nd = nd
15517+ }
15518+ };
15519+ return add_simple(dir, dentry, &arg);
15520+}
15521+
15522+/* ---------------------------------------------------------------------- */
15523+
15524+struct au_link_args {
15525+ aufs_bindex_t bdst, bsrc;
15526+ struct au_pin pin;
15527+ struct path h_path;
15528+ struct dentry *src_parent, *parent;
15529+};
15530+
15531+static int au_cpup_before_link(struct dentry *src_dentry,
15532+ struct au_link_args *a)
15533+{
15534+ int err;
15535+ struct dentry *h_src_dentry;
15536+ struct mutex *h_mtx;
15537+ struct file *h_file;
15538+
15539+ di_read_lock_parent(a->src_parent, AuLock_IR);
15540+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
15541+ if (unlikely(err))
15542+ goto out;
15543+
15544+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
15545+ h_mtx = &h_src_dentry->d_inode->i_mutex;
15546+ err = au_pin(&a->pin, src_dentry, a->bdst,
15547+ au_opt_udba(src_dentry->d_sb),
15548+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15549+ if (unlikely(err))
15550+ goto out;
15551+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15552+ h_file = au_h_open_pre(src_dentry, a->bsrc);
15553+ if (IS_ERR(h_file)) {
15554+ err = PTR_ERR(h_file);
15555+ h_file = NULL;
15556+ } else
1e00d052 15557+ err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
4a4d8108
AM
15558+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
15559+ mutex_unlock(h_mtx);
15560+ au_h_open_post(src_dentry, a->bsrc, h_file);
15561+ au_unpin(&a->pin);
15562+
4f0767ce 15563+out:
4a4d8108
AM
15564+ di_read_unlock(a->src_parent, AuLock_IR);
15565+ return err;
15566+}
15567+
15568+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
15569+{
15570+ int err;
15571+ unsigned char plink;
15572+ struct inode *h_inode, *inode;
15573+ struct dentry *h_src_dentry;
15574+ struct super_block *sb;
15575+ struct file *h_file;
15576+
15577+ plink = 0;
15578+ h_inode = NULL;
15579+ sb = src_dentry->d_sb;
15580+ inode = src_dentry->d_inode;
15581+ if (au_ibstart(inode) <= a->bdst)
15582+ h_inode = au_h_iptr(inode, a->bdst);
15583+ if (!h_inode || !h_inode->i_nlink) {
15584+ /* copyup src_dentry as the name of dentry. */
15585+ au_set_dbstart(src_dentry, a->bdst);
15586+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
15587+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
15588+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
15589+ h_file = au_h_open_pre(src_dentry, a->bsrc);
15590+ if (IS_ERR(h_file)) {
15591+ err = PTR_ERR(h_file);
15592+ h_file = NULL;
15593+ } else
15594+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
15595+ -1, AuCpup_KEEPLINO,
15596+ a->parent);
15597+ mutex_unlock(&h_inode->i_mutex);
15598+ au_h_open_post(src_dentry, a->bsrc, h_file);
15599+ au_set_h_dptr(src_dentry, a->bdst, NULL);
15600+ au_set_dbstart(src_dentry, a->bsrc);
15601+ } else {
15602+ /* the inode of src_dentry already exists on a.bdst branch */
15603+ h_src_dentry = d_find_alias(h_inode);
15604+ if (!h_src_dentry && au_plink_test(inode)) {
15605+ plink = 1;
15606+ h_src_dentry = au_plink_lkup(inode, a->bdst);
15607+ err = PTR_ERR(h_src_dentry);
15608+ if (IS_ERR(h_src_dentry))
15609+ goto out;
15610+
15611+ if (unlikely(!h_src_dentry->d_inode)) {
15612+ dput(h_src_dentry);
15613+ h_src_dentry = NULL;
15614+ }
15615+
15616+ }
15617+ if (h_src_dentry) {
15618+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
15619+ &a->h_path);
15620+ dput(h_src_dentry);
15621+ } else {
15622+ AuIOErr("no dentry found for hi%lu on b%d\n",
15623+ h_inode->i_ino, a->bdst);
15624+ err = -EIO;
15625+ }
15626+ }
15627+
15628+ if (!err && !plink)
15629+ au_plink_append(inode, a->bdst, a->h_path.dentry);
15630+
15631+out:
2cbb1c4b 15632+ AuTraceErr(err);
4a4d8108
AM
15633+ return err;
15634+}
15635+
15636+int aufs_link(struct dentry *src_dentry, struct inode *dir,
15637+ struct dentry *dentry)
15638+{
15639+ int err, rerr;
15640+ struct au_dtime dt;
15641+ struct au_link_args *a;
15642+ struct dentry *wh_dentry, *h_src_dentry;
15643+ struct inode *inode;
15644+ struct super_block *sb;
15645+ struct au_wr_dir_args wr_dir_args = {
15646+ /* .force_btgt = -1, */
15647+ .flags = AuWrDir_ADD_ENTRY
15648+ };
15649+
15650+ IMustLock(dir);
15651+ inode = src_dentry->d_inode;
15652+ IMustLock(inode);
15653+
4a4d8108
AM
15654+ err = -ENOMEM;
15655+ a = kzalloc(sizeof(*a), GFP_NOFS);
15656+ if (unlikely(!a))
15657+ goto out;
15658+
15659+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
15660+ err = aufs_read_and_write_lock2(dentry, src_dentry,
15661+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
15662+ if (unlikely(err))
15663+ goto out_kfree;
027c5e7a
AM
15664+ err = au_d_hashed_positive(src_dentry);
15665+ if (unlikely(err))
15666+ goto out_unlock;
15667+ err = au_d_may_add(dentry);
15668+ if (unlikely(err))
15669+ goto out_unlock;
e49829fe 15670+
4a4d8108 15671+ a->src_parent = dget_parent(src_dentry);
2cbb1c4b 15672+ wr_dir_args.force_btgt = au_ibstart(inode);
4a4d8108
AM
15673+
15674+ di_write_lock_parent(a->parent);
15675+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
15676+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
15677+ &wr_dir_args);
15678+ err = PTR_ERR(wh_dentry);
15679+ if (IS_ERR(wh_dentry))
027c5e7a 15680+ goto out_parent;
4a4d8108
AM
15681+
15682+ err = 0;
15683+ sb = dentry->d_sb;
15684+ a->bdst = au_dbstart(dentry);
15685+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
15686+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
2cbb1c4b
JR
15687+ a->bsrc = au_ibstart(inode);
15688+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
15689+ if (!h_src_dentry) {
15690+ a->bsrc = au_dbstart(src_dentry);
15691+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
15692+ AuDebugOn(!h_src_dentry);
15693+ } else if (IS_ERR(h_src_dentry))
15694+ goto out_parent;
15695+
4a4d8108
AM
15696+ if (au_opt_test(au_mntflags(sb), PLINK)) {
15697+ if (a->bdst < a->bsrc
15698+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
15699+ err = au_cpup_or_link(src_dentry, a);
2cbb1c4b 15700+ else
4a4d8108
AM
15701+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
15702+ &a->h_path);
2cbb1c4b 15703+ dput(h_src_dentry);
4a4d8108
AM
15704+ } else {
15705+ /*
15706+ * copyup src_dentry to the branch we process,
15707+ * and then link(2) to it.
15708+ */
2cbb1c4b 15709+ dput(h_src_dentry);
4a4d8108
AM
15710+ if (a->bdst < a->bsrc
15711+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
15712+ au_unpin(&a->pin);
15713+ di_write_unlock(a->parent);
15714+ err = au_cpup_before_link(src_dentry, a);
15715+ di_write_lock_parent(a->parent);
15716+ if (!err)
15717+ err = au_pin(&a->pin, dentry, a->bdst,
15718+ au_opt_udba(sb),
15719+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15720+ if (unlikely(err))
15721+ goto out_wh;
15722+ }
15723+ if (!err) {
15724+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
15725+ err = -ENOENT;
15726+ if (h_src_dentry && h_src_dentry->d_inode)
15727+ err = vfsub_link(h_src_dentry,
15728+ au_pinned_h_dir(&a->pin),
15729+ &a->h_path);
15730+ }
15731+ }
15732+ if (unlikely(err))
15733+ goto out_unpin;
15734+
15735+ if (wh_dentry) {
15736+ a->h_path.dentry = wh_dentry;
15737+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
15738+ dentry);
15739+ if (unlikely(err))
15740+ goto out_revert;
15741+ }
15742+
15743+ dir->i_version++;
15744+ if (au_ibstart(dir) == au_dbstart(dentry))
15745+ au_cpup_attr_timesizes(dir);
15746+ inc_nlink(inode);
15747+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
15748+ d_instantiate(dentry, au_igrab(inode));
15749+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
15750+ /* some filesystem calls d_drop() */
15751+ d_drop(dentry);
15752+ goto out_unpin; /* success */
15753+
4f0767ce 15754+out_revert:
4a4d8108 15755+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
027c5e7a
AM
15756+ if (unlikely(rerr)) {
15757+ AuIOErr("%.*s reverting failed(%d, %d)\n",
15758+ AuDLNPair(dentry), err, rerr);
15759+ err = -EIO;
15760+ }
4a4d8108 15761+ au_dtime_revert(&dt);
4f0767ce 15762+out_unpin:
4a4d8108 15763+ au_unpin(&a->pin);
4f0767ce 15764+out_wh:
4a4d8108 15765+ dput(wh_dentry);
027c5e7a
AM
15766+out_parent:
15767+ di_write_unlock(a->parent);
15768+ dput(a->src_parent);
4f0767ce 15769+out_unlock:
4a4d8108
AM
15770+ if (unlikely(err)) {
15771+ au_update_dbstart(dentry);
15772+ d_drop(dentry);
15773+ }
4a4d8108 15774+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 15775+out_kfree:
4a4d8108 15776+ kfree(a);
4f0767ce 15777+out:
4a4d8108
AM
15778+ return err;
15779+}
15780+
7eafdf33 15781+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
4a4d8108
AM
15782+{
15783+ int err, rerr;
15784+ aufs_bindex_t bindex;
15785+ unsigned char diropq;
15786+ struct path h_path;
15787+ struct dentry *wh_dentry, *parent, *opq_dentry;
15788+ struct mutex *h_mtx;
15789+ struct super_block *sb;
15790+ struct {
15791+ struct au_pin pin;
15792+ struct au_dtime dt;
15793+ } *a; /* reduce the stack usage */
15794+ struct au_wr_dir_args wr_dir_args = {
15795+ .force_btgt = -1,
15796+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
15797+ };
15798+
15799+ IMustLock(dir);
15800+
15801+ err = -ENOMEM;
15802+ a = kmalloc(sizeof(*a), GFP_NOFS);
15803+ if (unlikely(!a))
15804+ goto out;
15805+
027c5e7a
AM
15806+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15807+ if (unlikely(err))
15808+ goto out_free;
15809+ err = au_d_may_add(dentry);
15810+ if (unlikely(err))
15811+ goto out_unlock;
15812+
4a4d8108
AM
15813+ parent = dentry->d_parent; /* dir inode is locked */
15814+ di_write_lock_parent(parent);
15815+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
15816+ &a->pin, &wr_dir_args);
15817+ err = PTR_ERR(wh_dentry);
15818+ if (IS_ERR(wh_dentry))
027c5e7a 15819+ goto out_parent;
4a4d8108
AM
15820+
15821+ sb = dentry->d_sb;
15822+ bindex = au_dbstart(dentry);
15823+ h_path.dentry = au_h_dptr(dentry, bindex);
15824+ h_path.mnt = au_sbr_mnt(sb, bindex);
15825+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
15826+ if (unlikely(err))
027c5e7a 15827+ goto out_unpin;
4a4d8108
AM
15828+
15829+ /* make the dir opaque */
15830+ diropq = 0;
15831+ h_mtx = &h_path.dentry->d_inode->i_mutex;
15832+ if (wh_dentry
15833+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
15834+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15835+ opq_dentry = au_diropq_create(dentry, bindex);
15836+ mutex_unlock(h_mtx);
15837+ err = PTR_ERR(opq_dentry);
15838+ if (IS_ERR(opq_dentry))
15839+ goto out_dir;
15840+ dput(opq_dentry);
15841+ diropq = 1;
15842+ }
15843+
15844+ err = epilog(dir, bindex, wh_dentry, dentry);
15845+ if (!err) {
15846+ inc_nlink(dir);
027c5e7a 15847+ goto out_unpin; /* success */
4a4d8108
AM
15848+ }
15849+
15850+ /* revert */
15851+ if (diropq) {
15852+ AuLabel(revert opq);
15853+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15854+ rerr = au_diropq_remove(dentry, bindex);
15855+ mutex_unlock(h_mtx);
15856+ if (rerr) {
15857+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
15858+ AuDLNPair(dentry), err, rerr);
15859+ err = -EIO;
15860+ }
15861+ }
15862+
4f0767ce 15863+out_dir:
4a4d8108
AM
15864+ AuLabel(revert dir);
15865+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
15866+ if (rerr) {
15867+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
15868+ AuDLNPair(dentry), err, rerr);
15869+ err = -EIO;
15870+ }
4a4d8108 15871+ au_dtime_revert(&a->dt);
027c5e7a 15872+out_unpin:
4a4d8108
AM
15873+ au_unpin(&a->pin);
15874+ dput(wh_dentry);
027c5e7a
AM
15875+out_parent:
15876+ di_write_unlock(parent);
15877+out_unlock:
4a4d8108
AM
15878+ if (unlikely(err)) {
15879+ au_update_dbstart(dentry);
15880+ d_drop(dentry);
15881+ }
4a4d8108 15882+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15883+out_free:
4a4d8108 15884+ kfree(a);
4f0767ce 15885+out:
4a4d8108
AM
15886+ return err;
15887+}
7f207e10
AM
15888diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
15889--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274
AM
15890+++ linux/fs/aufs/i_op.c 2012-08-26 08:39:00.760508065 +0200
15891@@ -0,0 +1,1009 @@
4a4d8108 15892+/*
f6c5ef8b 15893+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
15894+ *
15895+ * This program, aufs is free software; you can redistribute it and/or modify
15896+ * it under the terms of the GNU General Public License as published by
15897+ * the Free Software Foundation; either version 2 of the License, or
15898+ * (at your option) any later version.
15899+ *
15900+ * This program is distributed in the hope that it will be useful,
15901+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15902+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15903+ * GNU General Public License for more details.
15904+ *
15905+ * You should have received a copy of the GNU General Public License
15906+ * along with this program; if not, write to the Free Software
15907+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15908+ */
1facf9fc 15909+
1308ab2a 15910+/*
4a4d8108 15911+ * inode operations (except add/del/rename)
1308ab2a 15912+ */
4a4d8108
AM
15913+
15914+#include <linux/device_cgroup.h>
15915+#include <linux/fs_stack.h>
92d182d2 15916+#include <linux/mm.h>
4a4d8108
AM
15917+#include <linux/namei.h>
15918+#include <linux/security.h>
4a4d8108
AM
15919+#include "aufs.h"
15920+
1e00d052 15921+static int h_permission(struct inode *h_inode, int mask,
4a4d8108 15922+ struct vfsmount *h_mnt, int brperm)
1facf9fc 15923+{
1308ab2a 15924+ int err;
4a4d8108 15925+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 15926+
4a4d8108
AM
15927+ err = -EACCES;
15928+ if ((write_mask && IS_IMMUTABLE(h_inode))
15929+ || ((mask & MAY_EXEC)
15930+ && S_ISREG(h_inode->i_mode)
15931+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
15932+ || !(h_inode->i_mode & S_IXUGO))))
15933+ goto out;
15934+
15935+ /*
15936+ * - skip the lower fs test in the case of write to ro branch.
15937+ * - nfs dir permission write check is optimized, but a policy for
15938+ * link/rename requires a real check.
15939+ */
15940+ if ((write_mask && !au_br_writable(brperm))
15941+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
15942+ && write_mask && !(mask & MAY_READ))
15943+ || !h_inode->i_op->permission) {
15944+ /* AuLabel(generic_permission); */
1e00d052 15945+ err = generic_permission(h_inode, mask);
1308ab2a 15946+ } else {
4a4d8108 15947+ /* AuLabel(h_inode->permission); */
1e00d052 15948+ err = h_inode->i_op->permission(h_inode, mask);
4a4d8108
AM
15949+ AuTraceErr(err);
15950+ }
1facf9fc 15951+
4a4d8108
AM
15952+ if (!err)
15953+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 15954+ if (!err)
4a4d8108 15955+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
15956+
15957+#if 0
15958+ if (!err) {
15959+ /* todo: do we need to call ima_path_check()? */
15960+ struct path h_path = {
15961+ .dentry =
15962+ .mnt = h_mnt
15963+ };
15964+ err = ima_path_check(&h_path,
15965+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
15966+ IMA_COUNT_LEAVE);
1308ab2a 15967+ }
4a4d8108 15968+#endif
dece6358 15969+
4f0767ce 15970+out:
1308ab2a 15971+ return err;
15972+}
dece6358 15973+
1e00d052 15974+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 15975+{
15976+ int err;
4a4d8108
AM
15977+ aufs_bindex_t bindex, bend;
15978+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
15979+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
15980+ struct inode *h_inode;
15981+ struct super_block *sb;
15982+ struct au_branch *br;
1facf9fc 15983+
027c5e7a 15984+ /* todo: support rcu-walk? */
1e00d052 15985+ if (mask & MAY_NOT_BLOCK)
027c5e7a
AM
15986+ return -ECHILD;
15987+
4a4d8108
AM
15988+ sb = inode->i_sb;
15989+ si_read_lock(sb, AuLock_FLUSH);
15990+ ii_read_lock_child(inode);
027c5e7a
AM
15991+#if 0
15992+ err = au_iigen_test(inode, au_sigen(sb));
15993+ if (unlikely(err))
15994+ goto out;
15995+#endif
dece6358 15996+
4a4d8108
AM
15997+ if (!isdir || write_mask) {
15998+ err = au_busy_or_stale();
15999+ h_inode = au_h_iptr(inode, au_ibstart(inode));
16000+ if (unlikely(!h_inode
16001+ || (h_inode->i_mode & S_IFMT)
16002+ != (inode->i_mode & S_IFMT)))
16003+ goto out;
1facf9fc 16004+
4a4d8108
AM
16005+ err = 0;
16006+ bindex = au_ibstart(inode);
16007+ br = au_sbr(sb, bindex);
1e00d052 16008+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
4a4d8108
AM
16009+ if (write_mask
16010+ && !err
16011+ && !special_file(h_inode->i_mode)) {
16012+ /* test whether the upper writable branch exists */
16013+ err = -EROFS;
16014+ for (; bindex >= 0; bindex--)
16015+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
16016+ err = 0;
16017+ break;
16018+ }
16019+ }
16020+ goto out;
16021+ }
dece6358 16022+
4a4d8108 16023+ /* non-write to dir */
1308ab2a 16024+ err = 0;
4a4d8108
AM
16025+ bend = au_ibend(inode);
16026+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
16027+ h_inode = au_h_iptr(inode, bindex);
16028+ if (h_inode) {
16029+ err = au_busy_or_stale();
16030+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
16031+ break;
16032+
16033+ br = au_sbr(sb, bindex);
1e00d052 16034+ err = h_permission(h_inode, mask, br->br_mnt,
4a4d8108
AM
16035+ br->br_perm);
16036+ }
16037+ }
1308ab2a 16038+
4f0767ce 16039+out:
4a4d8108
AM
16040+ ii_read_unlock(inode);
16041+ si_read_unlock(sb);
1308ab2a 16042+ return err;
16043+}
16044+
4a4d8108 16045+/* ---------------------------------------------------------------------- */
1facf9fc 16046+
4a4d8108
AM
16047+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
16048+ struct nameidata *nd)
16049+{
16050+ struct dentry *ret, *parent;
b752ccd1 16051+ struct inode *inode;
4a4d8108 16052+ struct super_block *sb;
9dbd164d 16053+ int err, npositive, lc_idx;
dece6358 16054+
4a4d8108 16055+ IMustLock(dir);
1308ab2a 16056+
4a4d8108 16057+ sb = dir->i_sb;
7f207e10
AM
16058+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16059+ ret = ERR_PTR(err);
16060+ if (unlikely(err))
16061+ goto out;
16062+
4a4d8108
AM
16063+ ret = ERR_PTR(-ENAMETOOLONG);
16064+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
7f207e10 16065+ goto out_si;
4a4d8108
AM
16066+ err = au_di_init(dentry);
16067+ ret = ERR_PTR(err);
16068+ if (unlikely(err))
7f207e10 16069+ goto out_si;
1308ab2a 16070+
9dbd164d 16071+ inode = NULL;
027c5e7a 16072+ npositive = 0; /* suppress a warning */
4a4d8108
AM
16073+ parent = dentry->d_parent; /* dir inode is locked */
16074+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
16075+ err = au_alive_dir(parent);
16076+ if (!err)
16077+ err = au_digen_test(parent, au_sigen(sb));
16078+ if (!err) {
16079+ npositive = au_lkup_dentry(dentry, au_dbstart(parent),
16080+ /*type*/0, nd);
16081+ err = npositive;
16082+ }
4a4d8108 16083+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
16084+ ret = ERR_PTR(err);
16085+ if (unlikely(err < 0))
16086+ goto out_unlock;
1308ab2a 16087+
4a4d8108 16088+ if (npositive) {
b752ccd1 16089+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 16090+ ret = (void *)inode;
1facf9fc 16091+ }
9dbd164d
AM
16092+ if (IS_ERR(inode)) {
16093+ inode = NULL;
4a4d8108 16094+ goto out_unlock;
9dbd164d 16095+ }
4a4d8108
AM
16096+
16097+ ret = d_splice_alias(inode, dentry);
7f207e10 16098+ if (unlikely(IS_ERR(ret) && inode)) {
4a4d8108 16099+ ii_write_unlock(inode);
7f207e10 16100+ iput(inode);
2dfbb274 16101+ inode = NULL;
7f207e10 16102+ }
1facf9fc 16103+
4f0767ce 16104+out_unlock:
4a4d8108 16105+ di_write_unlock(dentry);
2dfbb274 16106+ if (inode) {
9dbd164d
AM
16107+ lc_idx = AuLcNonDir_DIINFO;
16108+ if (S_ISLNK(inode->i_mode))
16109+ lc_idx = AuLcSymlink_DIINFO;
16110+ else if (S_ISDIR(inode->i_mode))
16111+ lc_idx = AuLcDir_DIINFO;
16112+ au_rw_class(&au_di(dentry)->di_rwsem, au_lc_key + lc_idx);
16113+ }
7f207e10 16114+out_si:
4a4d8108 16115+ si_read_unlock(sb);
7f207e10 16116+out:
4a4d8108
AM
16117+ return ret;
16118+}
1facf9fc 16119+
4a4d8108 16120+/* ---------------------------------------------------------------------- */
1facf9fc 16121+
4a4d8108
AM
16122+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
16123+ const unsigned char add_entry, aufs_bindex_t bcpup,
16124+ aufs_bindex_t bstart)
16125+{
16126+ int err;
16127+ struct dentry *h_parent;
16128+ struct inode *h_dir;
1facf9fc 16129+
027c5e7a 16130+ if (add_entry)
4a4d8108 16131+ IMustLock(parent->d_inode);
027c5e7a 16132+ else
4a4d8108
AM
16133+ di_write_lock_parent(parent);
16134+
16135+ err = 0;
16136+ if (!au_h_dptr(parent, bcpup)) {
16137+ if (bstart < bcpup)
16138+ err = au_cpdown_dirs(dentry, bcpup);
16139+ else
16140+ err = au_cpup_dirs(dentry, bcpup);
16141+ }
16142+ if (!err && add_entry) {
16143+ h_parent = au_h_dptr(parent, bcpup);
16144+ h_dir = h_parent->d_inode;
16145+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
16146+ err = au_lkup_neg(dentry, bcpup);
16147+ /* todo: no unlock here */
16148+ mutex_unlock(&h_dir->i_mutex);
027c5e7a
AM
16149+
16150+ AuDbg("bcpup %d\n", bcpup);
16151+ if (!err) {
16152+ if (!dentry->d_inode)
16153+ au_set_h_dptr(dentry, bstart, NULL);
4a4d8108
AM
16154+ au_update_dbrange(dentry, /*do_put_zero*/0);
16155+ }
1308ab2a 16156+ }
1facf9fc 16157+
4a4d8108
AM
16158+ if (!add_entry)
16159+ di_write_unlock(parent);
16160+ if (!err)
16161+ err = bcpup; /* success */
1308ab2a 16162+
027c5e7a 16163+ AuTraceErr(err);
4a4d8108
AM
16164+ return err;
16165+}
1facf9fc 16166+
4a4d8108
AM
16167+/*
16168+ * decide the branch and the parent dir where we will create a new entry.
16169+ * returns new bindex or an error.
16170+ * copyup the parent dir if needed.
16171+ */
16172+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
16173+ struct au_wr_dir_args *args)
16174+{
16175+ int err;
16176+ aufs_bindex_t bcpup, bstart, src_bstart;
16177+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
16178+ ADD_ENTRY);
16179+ struct super_block *sb;
16180+ struct dentry *parent;
16181+ struct au_sbinfo *sbinfo;
1facf9fc 16182+
4a4d8108
AM
16183+ sb = dentry->d_sb;
16184+ sbinfo = au_sbi(sb);
16185+ parent = dget_parent(dentry);
16186+ bstart = au_dbstart(dentry);
16187+ bcpup = bstart;
16188+ if (args->force_btgt < 0) {
16189+ if (src_dentry) {
16190+ src_bstart = au_dbstart(src_dentry);
16191+ if (src_bstart < bstart)
16192+ bcpup = src_bstart;
16193+ } else if (add_entry) {
16194+ err = AuWbrCreate(sbinfo, dentry,
16195+ au_ftest_wrdir(args->flags, ISDIR));
16196+ bcpup = err;
16197+ }
1facf9fc 16198+
4a4d8108
AM
16199+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
16200+ if (add_entry)
16201+ err = AuWbrCopyup(sbinfo, dentry);
16202+ else {
16203+ if (!IS_ROOT(dentry)) {
16204+ di_read_lock_parent(parent, !AuLock_IR);
16205+ err = AuWbrCopyup(sbinfo, dentry);
16206+ di_read_unlock(parent, !AuLock_IR);
16207+ } else
16208+ err = AuWbrCopyup(sbinfo, dentry);
16209+ }
16210+ bcpup = err;
16211+ if (unlikely(err < 0))
16212+ goto out;
16213+ }
16214+ } else {
16215+ bcpup = args->force_btgt;
16216+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 16217+ }
027c5e7a 16218+
4a4d8108
AM
16219+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
16220+ err = bcpup;
16221+ if (bcpup == bstart)
16222+ goto out; /* success */
4a4d8108
AM
16223+
16224+ /* copyup the new parent into the branch we process */
16225+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
027c5e7a
AM
16226+ if (err >= 0) {
16227+ if (!dentry->d_inode) {
16228+ au_set_h_dptr(dentry, bstart, NULL);
16229+ au_set_dbstart(dentry, bcpup);
16230+ au_set_dbend(dentry, bcpup);
16231+ }
16232+ AuDebugOn(add_entry && !au_h_dptr(dentry, bcpup));
16233+ }
4a4d8108 16234+
4f0767ce 16235+out:
4a4d8108 16236+ dput(parent);
dece6358
AM
16237+ return err;
16238+}
1facf9fc 16239+
1308ab2a 16240+/* ---------------------------------------------------------------------- */
16241+
4a4d8108 16242+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 16243+{
4a4d8108
AM
16244+ if (pin && pin->parent)
16245+ return au_h_dptr(pin->parent, pin->bindex);
16246+ return NULL;
dece6358 16247+}
1facf9fc 16248+
4a4d8108 16249+void au_unpin(struct au_pin *p)
dece6358 16250+{
e49829fe 16251+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
4a4d8108
AM
16252+ mnt_drop_write(p->h_mnt);
16253+ if (!p->hdir)
16254+ return;
1facf9fc 16255+
4a4d8108
AM
16256+ au_hn_imtx_unlock(p->hdir);
16257+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16258+ di_read_unlock(p->parent, AuLock_IR);
16259+ iput(p->hdir->hi_inode);
16260+ dput(p->parent);
16261+ p->parent = NULL;
16262+ p->hdir = NULL;
16263+ p->h_mnt = NULL;
16264+}
1308ab2a 16265+
4a4d8108
AM
16266+int au_do_pin(struct au_pin *p)
16267+{
16268+ int err;
16269+ struct super_block *sb;
16270+ struct dentry *h_dentry, *h_parent;
16271+ struct au_branch *br;
16272+ struct inode *h_dir;
16273+
16274+ err = 0;
16275+ sb = p->dentry->d_sb;
16276+ br = au_sbr(sb, p->bindex);
16277+ if (IS_ROOT(p->dentry)) {
16278+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
16279+ p->h_mnt = br->br_mnt;
16280+ err = mnt_want_write(p->h_mnt);
16281+ if (unlikely(err)) {
16282+ au_fclr_pin(p->flags, MNT_WRITE);
16283+ goto out_err;
16284+ }
16285+ }
dece6358 16286+ goto out;
1facf9fc 16287+ }
16288+
4a4d8108
AM
16289+ h_dentry = NULL;
16290+ if (p->bindex <= au_dbend(p->dentry))
16291+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 16292+
4a4d8108
AM
16293+ p->parent = dget_parent(p->dentry);
16294+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16295+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 16296+
4a4d8108
AM
16297+ h_dir = NULL;
16298+ h_parent = au_h_dptr(p->parent, p->bindex);
16299+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
16300+ if (p->hdir)
16301+ h_dir = p->hdir->hi_inode;
dece6358 16302+
b752ccd1
AM
16303+ /*
16304+ * udba case, or
16305+ * if DI_LOCKED is not set, then p->parent may be different
16306+ * and h_parent can be NULL.
16307+ */
16308+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
e49829fe 16309+ err = -EBUSY;
4a4d8108
AM
16310+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16311+ di_read_unlock(p->parent, AuLock_IR);
16312+ dput(p->parent);
16313+ p->parent = NULL;
16314+ goto out_err;
16315+ }
1308ab2a 16316+
4a4d8108
AM
16317+ au_igrab(h_dir);
16318+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 16319+
4a4d8108
AM
16320+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
16321+ err = -EBUSY;
16322+ goto out_unpin;
16323+ }
16324+ if (h_dentry) {
16325+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
16326+ if (unlikely(err)) {
16327+ au_fclr_pin(p->flags, MNT_WRITE);
16328+ goto out_unpin;
16329+ }
1facf9fc 16330+ }
dece6358 16331+
4a4d8108
AM
16332+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
16333+ p->h_mnt = br->br_mnt;
16334+ err = mnt_want_write(p->h_mnt);
dece6358 16335+ if (unlikely(err)) {
4a4d8108
AM
16336+ au_fclr_pin(p->flags, MNT_WRITE);
16337+ goto out_unpin;
dece6358
AM
16338+ }
16339+ }
4a4d8108
AM
16340+ goto out; /* success */
16341+
4f0767ce 16342+out_unpin:
4a4d8108 16343+ au_unpin(p);
4f0767ce 16344+out_err:
4a4d8108
AM
16345+ pr_err("err %d\n", err);
16346+ err = au_busy_or_stale();
4f0767ce 16347+out:
1facf9fc 16348+ return err;
16349+}
16350+
4a4d8108
AM
16351+void au_pin_init(struct au_pin *p, struct dentry *dentry,
16352+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
16353+ unsigned int udba, unsigned char flags)
16354+{
16355+ p->dentry = dentry;
16356+ p->udba = udba;
16357+ p->lsc_di = lsc_di;
16358+ p->lsc_hi = lsc_hi;
16359+ p->flags = flags;
16360+ p->bindex = bindex;
16361+
16362+ p->parent = NULL;
16363+ p->hdir = NULL;
16364+ p->h_mnt = NULL;
16365+}
16366+
16367+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
16368+ unsigned int udba, unsigned char flags)
16369+{
16370+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
16371+ udba, flags);
16372+ return au_do_pin(pin);
16373+}
16374+
dece6358
AM
16375+/* ---------------------------------------------------------------------- */
16376+
1308ab2a 16377+/*
4a4d8108
AM
16378+ * ->setattr() and ->getattr() are called in various cases.
16379+ * chmod, stat: dentry is revalidated.
16380+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
16381+ * unhashed.
16382+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 16383+ */
027c5e7a 16384+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
4a4d8108 16385+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 16386+{
4a4d8108
AM
16387+ int err;
16388+ struct inode *inode;
16389+ struct dentry *parent;
1facf9fc 16390+
1308ab2a 16391+ err = 0;
4a4d8108 16392+ inode = dentry->d_inode;
027c5e7a 16393+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
16394+ parent = dget_parent(dentry);
16395+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 16396+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
16397+ di_read_unlock(parent, AuLock_IR);
16398+ dput(parent);
dece6358 16399+ }
1facf9fc 16400+
4a4d8108 16401+ AuTraceErr(err);
1308ab2a 16402+ return err;
16403+}
dece6358 16404+
4a4d8108
AM
16405+#define AuIcpup_DID_CPUP 1
16406+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
7f207e10
AM
16407+#define au_fset_icpup(flags, name) \
16408+ do { (flags) |= AuIcpup_##name; } while (0)
16409+#define au_fclr_icpup(flags, name) \
16410+ do { (flags) &= ~AuIcpup_##name; } while (0)
1308ab2a 16411+
4a4d8108
AM
16412+struct au_icpup_args {
16413+ unsigned char flags;
16414+ unsigned char pin_flags;
16415+ aufs_bindex_t btgt;
16416+ unsigned int udba;
16417+ struct au_pin pin;
16418+ struct path h_path;
16419+ struct inode *h_inode;
16420+};
1308ab2a 16421+
4a4d8108
AM
16422+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
16423+ struct au_icpup_args *a)
1308ab2a 16424+{
16425+ int err;
4a4d8108 16426+ loff_t sz;
e49829fe 16427+ aufs_bindex_t bstart, ibstart;
4a4d8108
AM
16428+ struct dentry *hi_wh, *parent;
16429+ struct inode *inode;
16430+ struct file *h_file;
16431+ struct au_wr_dir_args wr_dir_args = {
16432+ .force_btgt = -1,
16433+ .flags = 0
16434+ };
16435+
16436+ bstart = au_dbstart(dentry);
16437+ inode = dentry->d_inode;
16438+ if (S_ISDIR(inode->i_mode))
16439+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16440+ /* plink or hi_wh() case */
e49829fe 16441+ ibstart = au_ibstart(inode);
027c5e7a 16442+ if (bstart != ibstart && !au_test_ro(inode->i_sb, ibstart, inode))
e49829fe 16443+ wr_dir_args.force_btgt = ibstart;
4a4d8108
AM
16444+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
16445+ if (unlikely(err < 0))
16446+ goto out;
16447+ a->btgt = err;
16448+ if (err != bstart)
16449+ au_fset_icpup(a->flags, DID_CPUP);
16450+
16451+ err = 0;
16452+ a->pin_flags = AuPin_MNT_WRITE;
16453+ parent = NULL;
16454+ if (!IS_ROOT(dentry)) {
16455+ au_fset_pin(a->pin_flags, DI_LOCKED);
16456+ parent = dget_parent(dentry);
16457+ di_write_lock_parent(parent);
16458+ }
16459+
16460+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
16461+ if (unlikely(err))
16462+ goto out_parent;
16463+
16464+ a->h_path.dentry = au_h_dptr(dentry, bstart);
16465+ a->h_inode = a->h_path.dentry->d_inode;
16466+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
16467+ sz = -1;
16468+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
16469+ sz = ia->ia_size;
16470+
16471+ h_file = NULL;
16472+ hi_wh = NULL;
027c5e7a 16473+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
16474+ hi_wh = au_hi_wh(inode, a->btgt);
16475+ if (!hi_wh) {
16476+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
16477+ if (unlikely(err))
16478+ goto out_unlock;
16479+ hi_wh = au_hi_wh(inode, a->btgt);
16480+ /* todo: revalidate hi_wh? */
16481+ }
16482+ }
16483+
16484+ if (parent) {
16485+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
16486+ di_downgrade_lock(parent, AuLock_IR);
16487+ dput(parent);
16488+ parent = NULL;
16489+ }
16490+ if (!au_ftest_icpup(a->flags, DID_CPUP))
16491+ goto out; /* success */
16492+
16493+ if (!d_unhashed(dentry)) {
16494+ h_file = au_h_open_pre(dentry, bstart);
16495+ if (IS_ERR(h_file)) {
16496+ err = PTR_ERR(h_file);
16497+ h_file = NULL;
16498+ } else
16499+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
16500+ AuCpup_DTIME);
16501+ if (!err)
16502+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
16503+ } else if (!hi_wh)
16504+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
16505+ else
16506+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 16507+
4f0767ce 16508+out_unlock:
4a4d8108
AM
16509+ mutex_unlock(&a->h_inode->i_mutex);
16510+ au_h_open_post(dentry, bstart, h_file);
16511+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 16512+ if (!err) {
4a4d8108 16513+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 16514+ goto out; /* success */
1facf9fc 16515+ }
dece6358 16516+
4a4d8108 16517+ au_unpin(&a->pin);
4f0767ce 16518+out_parent:
4a4d8108
AM
16519+ if (parent) {
16520+ di_write_unlock(parent);
16521+ dput(parent);
16522+ }
4f0767ce 16523+out:
1facf9fc 16524+ return err;
16525+}
16526+
4a4d8108 16527+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 16528+{
4a4d8108
AM
16529+ int err;
16530+ struct inode *inode;
16531+ struct super_block *sb;
16532+ struct file *file;
16533+ struct au_icpup_args *a;
1facf9fc 16534+
4a4d8108
AM
16535+ inode = dentry->d_inode;
16536+ IMustLock(inode);
dece6358 16537+
4a4d8108
AM
16538+ err = -ENOMEM;
16539+ a = kzalloc(sizeof(*a), GFP_NOFS);
16540+ if (unlikely(!a))
16541+ goto out;
1facf9fc 16542+
4a4d8108
AM
16543+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
16544+ ia->ia_valid &= ~ATTR_MODE;
dece6358 16545+
4a4d8108
AM
16546+ file = NULL;
16547+ sb = dentry->d_sb;
e49829fe
JR
16548+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16549+ if (unlikely(err))
16550+ goto out_kfree;
16551+
4a4d8108
AM
16552+ if (ia->ia_valid & ATTR_FILE) {
16553+ /* currently ftruncate(2) only */
16554+ AuDebugOn(!S_ISREG(inode->i_mode));
16555+ file = ia->ia_file;
16556+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
16557+ if (unlikely(err))
16558+ goto out_si;
16559+ ia->ia_file = au_hf_top(file);
16560+ a->udba = AuOpt_UDBA_NONE;
16561+ } else {
16562+ /* fchmod() doesn't pass ia_file */
16563+ a->udba = au_opt_udba(sb);
027c5e7a
AM
16564+ di_write_lock_child(dentry);
16565+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
16566+ if (d_unhashed(dentry))
16567+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
16568+ if (a->udba != AuOpt_UDBA_NONE) {
16569+ AuDebugOn(IS_ROOT(dentry));
16570+ err = au_reval_for_attr(dentry, au_sigen(sb));
16571+ if (unlikely(err))
16572+ goto out_dentry;
16573+ }
dece6358 16574+ }
dece6358 16575+
4a4d8108
AM
16576+ err = au_pin_and_icpup(dentry, ia, a);
16577+ if (unlikely(err < 0))
16578+ goto out_dentry;
16579+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
16580+ ia->ia_file = NULL;
16581+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 16582+ }
dece6358 16583+
4a4d8108
AM
16584+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
16585+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
16586+ == (ATTR_MODE | ATTR_CTIME)) {
7eafdf33 16587+ err = security_path_chmod(&a->h_path, ia->ia_mode);
4a4d8108
AM
16588+ if (unlikely(err))
16589+ goto out_unlock;
16590+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
16591+ && (ia->ia_valid & ATTR_CTIME)) {
0c3ec466
AM
16592+ err = security_path_chown(&a->h_path, vfsub_ia_uid(ia),
16593+ vfsub_ia_gid(ia));
4a4d8108
AM
16594+ if (unlikely(err))
16595+ goto out_unlock;
16596+ }
dece6358 16597+
4a4d8108
AM
16598+ if (ia->ia_valid & ATTR_SIZE) {
16599+ struct file *f;
1308ab2a 16600+
953406b4 16601+ if (ia->ia_size < i_size_read(inode))
4a4d8108 16602+ /* unmap only */
953406b4 16603+ truncate_setsize(inode, ia->ia_size);
1308ab2a 16604+
4a4d8108
AM
16605+ f = NULL;
16606+ if (ia->ia_valid & ATTR_FILE)
16607+ f = ia->ia_file;
16608+ mutex_unlock(&a->h_inode->i_mutex);
16609+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
16610+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
16611+ } else
16612+ err = vfsub_notify_change(&a->h_path, ia);
16613+ if (!err)
16614+ au_cpup_attr_changeable(inode);
1308ab2a 16615+
4f0767ce 16616+out_unlock:
4a4d8108
AM
16617+ mutex_unlock(&a->h_inode->i_mutex);
16618+ au_unpin(&a->pin);
027c5e7a
AM
16619+ if (unlikely(err))
16620+ au_update_dbstart(dentry);
4f0767ce 16621+out_dentry:
4a4d8108
AM
16622+ di_write_unlock(dentry);
16623+ if (file) {
16624+ fi_write_unlock(file);
16625+ ia->ia_file = file;
16626+ ia->ia_valid |= ATTR_FILE;
16627+ }
4f0767ce 16628+out_si:
4a4d8108 16629+ si_read_unlock(sb);
e49829fe 16630+out_kfree:
4a4d8108 16631+ kfree(a);
4f0767ce 16632+out:
4a4d8108
AM
16633+ AuTraceErr(err);
16634+ return err;
1facf9fc 16635+}
16636+
4a4d8108
AM
16637+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
16638+ unsigned int nlink)
1facf9fc 16639+{
9dbd164d
AM
16640+ unsigned int n;
16641+
4a4d8108 16642+ inode->i_mode = st->mode;
0c3ec466
AM
16643+ i_uid_write(inode, st->uid);
16644+ i_gid_write(inode, st->gid);
4a4d8108
AM
16645+ inode->i_atime = st->atime;
16646+ inode->i_mtime = st->mtime;
16647+ inode->i_ctime = st->ctime;
1facf9fc 16648+
4a4d8108
AM
16649+ au_cpup_attr_nlink(inode, /*force*/0);
16650+ if (S_ISDIR(inode->i_mode)) {
9dbd164d
AM
16651+ n = inode->i_nlink;
16652+ n -= nlink;
16653+ n += st->nlink;
7eafdf33 16654+ /* 0 can happen */
92d182d2 16655+ set_nlink(inode, n);
4a4d8108 16656+ }
1facf9fc 16657+
4a4d8108
AM
16658+ spin_lock(&inode->i_lock);
16659+ inode->i_blocks = st->blocks;
16660+ i_size_write(inode, st->size);
16661+ spin_unlock(&inode->i_lock);
1facf9fc 16662+}
16663+
4a4d8108
AM
16664+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
16665+ struct dentry *dentry, struct kstat *st)
1facf9fc 16666+{
4a4d8108
AM
16667+ int err;
16668+ unsigned int mnt_flags;
16669+ aufs_bindex_t bindex;
16670+ unsigned char udba_none, positive;
16671+ struct super_block *sb, *h_sb;
16672+ struct inode *inode;
16673+ struct vfsmount *h_mnt;
16674+ struct dentry *h_dentry;
1facf9fc 16675+
4a4d8108
AM
16676+ sb = dentry->d_sb;
16677+ inode = dentry->d_inode;
7f207e10
AM
16678+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16679+ if (unlikely(err))
16680+ goto out;
4a4d8108
AM
16681+ mnt_flags = au_mntflags(sb);
16682+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 16683+
4a4d8108 16684+ /* support fstat(2) */
027c5e7a 16685+ if (!d_unlinked(dentry) && !udba_none) {
4a4d8108 16686+ unsigned int sigen = au_sigen(sb);
027c5e7a
AM
16687+ err = au_digen_test(dentry, sigen);
16688+ if (!err) {
4a4d8108 16689+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a
AM
16690+ err = au_dbrange_test(dentry);
16691+ if (unlikely(err))
16692+ goto out_unlock;
16693+ } else {
4a4d8108
AM
16694+ AuDebugOn(IS_ROOT(dentry));
16695+ di_write_lock_child(dentry);
027c5e7a
AM
16696+ err = au_dbrange_test(dentry);
16697+ if (!err)
16698+ err = au_reval_for_attr(dentry, sigen);
4a4d8108
AM
16699+ di_downgrade_lock(dentry, AuLock_IR);
16700+ if (unlikely(err))
7f207e10 16701+ goto out_unlock;
4a4d8108
AM
16702+ }
16703+ } else
16704+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 16705+
4a4d8108
AM
16706+ bindex = au_ibstart(inode);
16707+ h_mnt = au_sbr_mnt(sb, bindex);
16708+ h_sb = h_mnt->mnt_sb;
16709+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
16710+ goto out_fill; /* success */
1facf9fc 16711+
4a4d8108
AM
16712+ h_dentry = NULL;
16713+ if (au_dbstart(dentry) == bindex)
16714+ h_dentry = dget(au_h_dptr(dentry, bindex));
16715+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
16716+ h_dentry = au_plink_lkup(inode, bindex);
16717+ if (IS_ERR(h_dentry))
16718+ goto out_fill; /* pretending success */
16719+ }
16720+ /* illegally overlapped or something */
16721+ if (unlikely(!h_dentry))
16722+ goto out_fill; /* pretending success */
16723+
16724+ positive = !!h_dentry->d_inode;
16725+ if (positive)
16726+ err = vfs_getattr(h_mnt, h_dentry, st);
16727+ dput(h_dentry);
16728+ if (!err) {
16729+ if (positive)
16730+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
16731+ goto out_fill; /* success */
1facf9fc 16732+ }
7f207e10
AM
16733+ AuTraceErr(err);
16734+ goto out_unlock;
4a4d8108 16735+
4f0767ce 16736+out_fill:
4a4d8108 16737+ generic_fillattr(inode, st);
7f207e10 16738+out_unlock:
4a4d8108
AM
16739+ di_read_unlock(dentry, AuLock_IR);
16740+ si_read_unlock(sb);
7f207e10
AM
16741+out:
16742+ AuTraceErr(err);
4a4d8108 16743+ return err;
1facf9fc 16744+}
16745+
16746+/* ---------------------------------------------------------------------- */
16747+
4a4d8108
AM
16748+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
16749+ int bufsiz)
1facf9fc 16750+{
16751+ int err;
4a4d8108
AM
16752+ struct super_block *sb;
16753+ struct dentry *h_dentry;
1facf9fc 16754+
4a4d8108
AM
16755+ err = -EINVAL;
16756+ h_dentry = au_h_dptr(dentry, bindex);
16757+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
16758+ goto out;
1facf9fc 16759+
4a4d8108
AM
16760+ err = security_inode_readlink(h_dentry);
16761+ if (unlikely(err))
dece6358 16762+ goto out;
1facf9fc 16763+
4a4d8108
AM
16764+ sb = dentry->d_sb;
16765+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
16766+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
16767+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 16768+ }
4a4d8108 16769+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 16770+
4f0767ce 16771+out:
4a4d8108
AM
16772+ return err;
16773+}
1facf9fc 16774+
4a4d8108
AM
16775+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
16776+{
16777+ int err;
1facf9fc 16778+
027c5e7a
AM
16779+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
16780+ if (unlikely(err))
16781+ goto out;
16782+ err = au_d_hashed_positive(dentry);
16783+ if (!err)
16784+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
4a4d8108 16785+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 16786+
027c5e7a 16787+out:
4a4d8108
AM
16788+ return err;
16789+}
1facf9fc 16790+
4a4d8108
AM
16791+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
16792+{
16793+ int err;
4a4d8108 16794+ mm_segment_t old_fs;
b752ccd1
AM
16795+ union {
16796+ char *k;
16797+ char __user *u;
16798+ } buf;
1facf9fc 16799+
4a4d8108 16800+ err = -ENOMEM;
b752ccd1
AM
16801+ buf.k = __getname_gfp(GFP_NOFS);
16802+ if (unlikely(!buf.k))
4a4d8108 16803+ goto out;
1facf9fc 16804+
027c5e7a
AM
16805+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
16806+ if (unlikely(err))
16807+ goto out_name;
16808+
16809+ err = au_d_hashed_positive(dentry);
16810+ if (!err) {
16811+ old_fs = get_fs();
16812+ set_fs(KERNEL_DS);
16813+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
16814+ set_fs(old_fs);
16815+ }
4a4d8108 16816+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 16817+
4a4d8108 16818+ if (err >= 0) {
b752ccd1 16819+ buf.k[err] = 0;
4a4d8108 16820+ /* will be freed by put_link */
b752ccd1 16821+ nd_set_link(nd, buf.k);
4a4d8108 16822+ return NULL; /* success */
1308ab2a 16823+ }
1facf9fc 16824+
027c5e7a
AM
16825+out_name:
16826+ __putname(buf.k);
4f0767ce 16827+out:
4a4d8108
AM
16828+ path_put(&nd->path);
16829+ AuTraceErr(err);
16830+ return ERR_PTR(err);
16831+}
1facf9fc 16832+
4a4d8108
AM
16833+static void aufs_put_link(struct dentry *dentry __maybe_unused,
16834+ struct nameidata *nd, void *cookie __maybe_unused)
16835+{
16836+ __putname(nd_get_link(nd));
16837+}
1facf9fc 16838+
4a4d8108 16839+/* ---------------------------------------------------------------------- */
1facf9fc 16840+
0c3ec466 16841+static int aufs_update_time(struct inode *inode, struct timespec *ts, int flags)
4a4d8108 16842+{
0c3ec466
AM
16843+ int err;
16844+ struct super_block *sb;
16845+ struct inode *h_inode;
16846+
16847+ sb = inode->i_sb;
16848+ /* mmap_sem might be acquired already, cf. aufs_mmap() */
16849+ lockdep_off();
16850+ si_read_lock(sb, AuLock_FLUSH);
16851+ ii_write_lock_child(inode);
16852+ lockdep_on();
16853+ h_inode = au_h_iptr(inode, au_ibstart(inode));
16854+ err = vfsub_update_time(h_inode, ts, flags);
16855+ lockdep_off();
16856+ ii_write_unlock(inode);
16857+ si_read_unlock(sb);
16858+ lockdep_on();
16859+ return err;
4a4d8108 16860+}
1facf9fc 16861+
4a4d8108 16862+/* ---------------------------------------------------------------------- */
1308ab2a 16863+
4a4d8108
AM
16864+struct inode_operations aufs_symlink_iop = {
16865+ .permission = aufs_permission,
16866+ .setattr = aufs_setattr,
16867+ .getattr = aufs_getattr,
0c3ec466 16868+
4a4d8108
AM
16869+ .readlink = aufs_readlink,
16870+ .follow_link = aufs_follow_link,
0c3ec466
AM
16871+ .put_link = aufs_put_link,
16872+
16873+ /* .update_time = aufs_update_time */
4a4d8108
AM
16874+};
16875+
16876+struct inode_operations aufs_dir_iop = {
16877+ .create = aufs_create,
16878+ .lookup = aufs_lookup,
16879+ .link = aufs_link,
16880+ .unlink = aufs_unlink,
16881+ .symlink = aufs_symlink,
16882+ .mkdir = aufs_mkdir,
16883+ .rmdir = aufs_rmdir,
16884+ .mknod = aufs_mknod,
16885+ .rename = aufs_rename,
16886+
16887+ .permission = aufs_permission,
16888+ .setattr = aufs_setattr,
0c3ec466
AM
16889+ .getattr = aufs_getattr,
16890+
16891+ .update_time = aufs_update_time
4a4d8108
AM
16892+};
16893+
16894+struct inode_operations aufs_iop = {
16895+ .permission = aufs_permission,
16896+ .setattr = aufs_setattr,
16897+ .getattr = aufs_getattr,
0c3ec466
AM
16898+
16899+ .update_time = aufs_update_time
4a4d8108 16900+};
7f207e10
AM
16901diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
16902--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 16903+++ linux/fs/aufs/i_op_del.c 2012-08-26 08:39:00.760508065 +0200
53392da6 16904@@ -0,0 +1,478 @@
1facf9fc 16905+/*
f6c5ef8b 16906+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 16907+ *
16908+ * This program, aufs is free software; you can redistribute it and/or modify
16909+ * it under the terms of the GNU General Public License as published by
16910+ * the Free Software Foundation; either version 2 of the License, or
16911+ * (at your option) any later version.
dece6358
AM
16912+ *
16913+ * This program is distributed in the hope that it will be useful,
16914+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16915+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16916+ * GNU General Public License for more details.
16917+ *
16918+ * You should have received a copy of the GNU General Public License
16919+ * along with this program; if not, write to the Free Software
16920+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16921+ */
16922+
16923+/*
4a4d8108 16924+ * inode operations (del entry)
1308ab2a 16925+ */
dece6358 16926+
1308ab2a 16927+#include "aufs.h"
dece6358 16928+
4a4d8108
AM
16929+/*
16930+ * decide if a new whiteout for @dentry is necessary or not.
16931+ * when it is necessary, prepare the parent dir for the upper branch whose
16932+ * branch index is @bcpup for creation. the actual creation of the whiteout will
16933+ * be done by caller.
16934+ * return value:
16935+ * 0: wh is unnecessary
16936+ * plus: wh is necessary
16937+ * minus: error
16938+ */
16939+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 16940+{
4a4d8108
AM
16941+ int need_wh, err;
16942+ aufs_bindex_t bstart;
16943+ struct super_block *sb;
dece6358 16944+
4a4d8108
AM
16945+ sb = dentry->d_sb;
16946+ bstart = au_dbstart(dentry);
16947+ if (*bcpup < 0) {
16948+ *bcpup = bstart;
16949+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
16950+ err = AuWbrCopyup(au_sbi(sb), dentry);
16951+ *bcpup = err;
16952+ if (unlikely(err < 0))
16953+ goto out;
16954+ }
16955+ } else
16956+ AuDebugOn(bstart < *bcpup
16957+ || au_test_ro(sb, *bcpup, dentry->d_inode));
16958+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 16959+
4a4d8108
AM
16960+ if (*bcpup != bstart) {
16961+ err = au_cpup_dirs(dentry, *bcpup);
16962+ if (unlikely(err))
16963+ goto out;
16964+ need_wh = 1;
16965+ } else {
027c5e7a 16966+ struct au_dinfo *dinfo, *tmp;
4a4d8108 16967+
027c5e7a
AM
16968+ need_wh = -ENOMEM;
16969+ dinfo = au_di(dentry);
16970+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
16971+ if (tmp) {
16972+ au_di_cp(tmp, dinfo);
16973+ au_di_swap(tmp, dinfo);
16974+ /* returns the number of positive dentries */
16975+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
16976+ /*nd*/NULL);
16977+ au_di_swap(tmp, dinfo);
16978+ au_rw_write_unlock(&tmp->di_rwsem);
16979+ au_di_free(tmp);
4a4d8108
AM
16980+ }
16981+ }
16982+ AuDbg("need_wh %d\n", need_wh);
16983+ err = need_wh;
16984+
4f0767ce 16985+out:
4a4d8108 16986+ return err;
1facf9fc 16987+}
16988+
4a4d8108
AM
16989+/*
16990+ * simple tests for the del-entry operations.
16991+ * following the checks in vfs, plus the parent-child relationship.
16992+ */
16993+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
16994+ struct dentry *h_parent, int isdir)
1facf9fc 16995+{
4a4d8108
AM
16996+ int err;
16997+ umode_t h_mode;
16998+ struct dentry *h_dentry, *h_latest;
1308ab2a 16999+ struct inode *h_inode;
1facf9fc 17000+
4a4d8108
AM
17001+ h_dentry = au_h_dptr(dentry, bindex);
17002+ h_inode = h_dentry->d_inode;
17003+ if (dentry->d_inode) {
17004+ err = -ENOENT;
17005+ if (unlikely(!h_inode || !h_inode->i_nlink))
17006+ goto out;
1facf9fc 17007+
4a4d8108
AM
17008+ h_mode = h_inode->i_mode;
17009+ if (!isdir) {
17010+ err = -EISDIR;
17011+ if (unlikely(S_ISDIR(h_mode)))
17012+ goto out;
17013+ } else if (unlikely(!S_ISDIR(h_mode))) {
17014+ err = -ENOTDIR;
17015+ goto out;
17016+ }
17017+ } else {
17018+ /* rename(2) case */
17019+ err = -EIO;
17020+ if (unlikely(h_inode))
17021+ goto out;
17022+ }
1facf9fc 17023+
4a4d8108
AM
17024+ err = -ENOENT;
17025+ /* expected parent dir is locked */
17026+ if (unlikely(h_parent != h_dentry->d_parent))
17027+ goto out;
17028+ err = 0;
17029+
17030+ /*
17031+ * rmdir a dir may break the consistency on some filesystem.
17032+ * let's try heavy test.
17033+ */
17034+ err = -EACCES;
17035+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
17036+ goto out;
17037+
17038+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
17039+ au_sbr(dentry->d_sb, bindex));
17040+ err = -EIO;
17041+ if (IS_ERR(h_latest))
17042+ goto out;
17043+ if (h_latest == h_dentry)
17044+ err = 0;
17045+ dput(h_latest);
17046+
4f0767ce 17047+out:
4a4d8108 17048+ return err;
1308ab2a 17049+}
1facf9fc 17050+
4a4d8108
AM
17051+/*
17052+ * decide the branch where we operate for @dentry. the branch index will be set
17053+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
17054+ * dir for reverting.
17055+ * when a new whiteout is necessary, create it.
17056+ */
17057+static struct dentry*
17058+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
17059+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 17060+{
4a4d8108
AM
17061+ struct dentry *wh_dentry;
17062+ struct super_block *sb;
17063+ struct path h_path;
17064+ int err, need_wh;
17065+ unsigned int udba;
17066+ aufs_bindex_t bcpup;
dece6358 17067+
4a4d8108
AM
17068+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
17069+ wh_dentry = ERR_PTR(need_wh);
17070+ if (unlikely(need_wh < 0))
17071+ goto out;
17072+
17073+ sb = dentry->d_sb;
17074+ udba = au_opt_udba(sb);
17075+ bcpup = *rbcpup;
17076+ err = au_pin(pin, dentry, bcpup, udba,
17077+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
17078+ wh_dentry = ERR_PTR(err);
17079+ if (unlikely(err))
17080+ goto out;
17081+
17082+ h_path.dentry = au_pinned_h_parent(pin);
17083+ if (udba != AuOpt_UDBA_NONE
17084+ && au_dbstart(dentry) == bcpup) {
17085+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
17086+ wh_dentry = ERR_PTR(err);
17087+ if (unlikely(err))
17088+ goto out_unpin;
17089+ }
17090+
17091+ h_path.mnt = au_sbr_mnt(sb, bcpup);
17092+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
17093+ wh_dentry = NULL;
17094+ if (!need_wh)
17095+ goto out; /* success, no need to create whiteout */
17096+
17097+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
17098+ if (IS_ERR(wh_dentry))
17099+ goto out_unpin;
17100+
17101+ /* returns with the parent is locked and wh_dentry is dget-ed */
17102+ goto out; /* success */
17103+
4f0767ce 17104+out_unpin:
4a4d8108 17105+ au_unpin(pin);
4f0767ce 17106+out:
4a4d8108 17107+ return wh_dentry;
1facf9fc 17108+}
17109+
4a4d8108
AM
17110+/*
17111+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
17112+ * in order to be revertible and save time for removing many child whiteouts
17113+ * under the dir.
17114+ * returns 1 when there are too many child whiteout and caller should remove
17115+ * them asynchronously. returns 0 when the number of children is enough small to
17116+ * remove now or the branch fs is a remote fs.
17117+ * otherwise return an error.
17118+ */
17119+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
17120+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 17121+{
4a4d8108
AM
17122+ int rmdir_later, err, dirwh;
17123+ struct dentry *h_dentry;
17124+ struct super_block *sb;
17125+
17126+ sb = dentry->d_sb;
17127+ SiMustAnyLock(sb);
17128+ h_dentry = au_h_dptr(dentry, bindex);
17129+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
17130+ if (unlikely(err))
17131+ goto out;
17132+
17133+ /* stop monitoring */
17134+ au_hn_free(au_hi(dentry->d_inode, bindex));
17135+
17136+ if (!au_test_fs_remote(h_dentry->d_sb)) {
17137+ dirwh = au_sbi(sb)->si_dirwh;
17138+ rmdir_later = (dirwh <= 1);
17139+ if (!rmdir_later)
17140+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
17141+ dirwh);
17142+ if (rmdir_later)
17143+ return rmdir_later;
17144+ }
1facf9fc 17145+
4a4d8108
AM
17146+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
17147+ if (unlikely(err)) {
17148+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
17149+ AuDLNPair(h_dentry), bindex, err);
17150+ err = 0;
17151+ }
dece6358 17152+
4f0767ce 17153+out:
4a4d8108
AM
17154+ AuTraceErr(err);
17155+ return err;
17156+}
1308ab2a 17157+
4a4d8108
AM
17158+/*
17159+ * final procedure for deleting a entry.
17160+ * maintain dentry and iattr.
17161+ */
17162+static void epilog(struct inode *dir, struct dentry *dentry,
17163+ aufs_bindex_t bindex)
17164+{
17165+ struct inode *inode;
1308ab2a 17166+
4a4d8108
AM
17167+ inode = dentry->d_inode;
17168+ d_drop(dentry);
17169+ inode->i_ctime = dir->i_ctime;
1308ab2a 17170+
4a4d8108
AM
17171+ if (au_ibstart(dir) == bindex)
17172+ au_cpup_attr_timesizes(dir);
17173+ dir->i_version++;
1facf9fc 17174+}
17175+
4a4d8108
AM
17176+/*
17177+ * when an error happened, remove the created whiteout and revert everything.
17178+ */
7f207e10
AM
17179+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
17180+ aufs_bindex_t bwh, struct dentry *wh_dentry,
17181+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 17182+{
4a4d8108
AM
17183+ int rerr;
17184+ struct path h_path = {
17185+ .dentry = wh_dentry,
7f207e10 17186+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 17187+ };
dece6358 17188+
7f207e10 17189+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
17190+ if (!rerr) {
17191+ au_set_dbwh(dentry, bwh);
17192+ au_dtime_revert(dt);
17193+ return 0;
17194+ }
dece6358 17195+
4a4d8108
AM
17196+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
17197+ AuDLNPair(dentry), err, rerr);
17198+ return -EIO;
1facf9fc 17199+}
17200+
4a4d8108 17201+/* ---------------------------------------------------------------------- */
1facf9fc 17202+
4a4d8108 17203+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 17204+{
4a4d8108
AM
17205+ int err;
17206+ aufs_bindex_t bwh, bindex, bstart;
17207+ struct au_dtime dt;
17208+ struct au_pin pin;
17209+ struct path h_path;
17210+ struct inode *inode, *h_dir;
17211+ struct dentry *parent, *wh_dentry;
1facf9fc 17212+
4a4d8108 17213+ IMustLock(dir);
027c5e7a
AM
17214+
17215+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
17216+ if (unlikely(err))
17217+ goto out;
17218+ err = au_d_hashed_positive(dentry);
17219+ if (unlikely(err))
17220+ goto out_unlock;
4a4d8108 17221+ inode = dentry->d_inode;
4a4d8108 17222+ IMustLock(inode);
027c5e7a
AM
17223+ err = -EISDIR;
17224+ if (unlikely(S_ISDIR(inode->i_mode)))
17225+ goto out_unlock; /* possible? */
1facf9fc 17226+
4a4d8108
AM
17227+ bstart = au_dbstart(dentry);
17228+ bwh = au_dbwh(dentry);
17229+ bindex = -1;
027c5e7a
AM
17230+ parent = dentry->d_parent; /* dir inode is locked */
17231+ di_write_lock_parent(parent);
4a4d8108
AM
17232+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
17233+ err = PTR_ERR(wh_dentry);
17234+ if (IS_ERR(wh_dentry))
027c5e7a 17235+ goto out_parent;
1facf9fc 17236+
4a4d8108
AM
17237+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
17238+ h_path.dentry = au_h_dptr(dentry, bstart);
17239+ dget(h_path.dentry);
17240+ if (bindex == bstart) {
17241+ h_dir = au_pinned_h_dir(&pin);
17242+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
17243+ } else {
17244+ /* dir inode is locked */
17245+ h_dir = wh_dentry->d_parent->d_inode;
17246+ IMustLock(h_dir);
17247+ err = 0;
17248+ }
dece6358 17249+
4a4d8108 17250+ if (!err) {
7f207e10 17251+ vfsub_drop_nlink(inode);
4a4d8108
AM
17252+ epilog(dir, dentry, bindex);
17253+
17254+ /* update target timestamps */
17255+ if (bindex == bstart) {
17256+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
17257+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
17258+ } else
17259+ /* todo: this timestamp may be reverted later */
17260+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 17261+ goto out_unpin; /* success */
1facf9fc 17262+ }
17263+
4a4d8108
AM
17264+ /* revert */
17265+ if (wh_dentry) {
17266+ int rerr;
17267+
7f207e10 17268+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
17269+ if (rerr)
17270+ err = rerr;
dece6358 17271+ }
1facf9fc 17272+
027c5e7a 17273+out_unpin:
4a4d8108
AM
17274+ au_unpin(&pin);
17275+ dput(wh_dentry);
17276+ dput(h_path.dentry);
027c5e7a 17277+out_parent:
4a4d8108 17278+ di_write_unlock(parent);
027c5e7a 17279+out_unlock:
4a4d8108 17280+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 17281+out:
4a4d8108 17282+ return err;
dece6358
AM
17283+}
17284+
4a4d8108 17285+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 17286+{
4a4d8108
AM
17287+ int err, rmdir_later;
17288+ aufs_bindex_t bwh, bindex, bstart;
17289+ struct au_dtime dt;
17290+ struct au_pin pin;
17291+ struct inode *inode;
17292+ struct dentry *parent, *wh_dentry, *h_dentry;
17293+ struct au_whtmp_rmdir *args;
1facf9fc 17294+
4a4d8108 17295+ IMustLock(dir);
027c5e7a
AM
17296+
17297+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
17298+ if (unlikely(err))
4a4d8108 17299+ goto out;
53392da6
AM
17300+ err = au_alive_dir(dentry);
17301+ if (unlikely(err))
027c5e7a 17302+ goto out_unlock;
53392da6 17303+ inode = dentry->d_inode;
4a4d8108 17304+ IMustLock(inode);
027c5e7a
AM
17305+ err = -ENOTDIR;
17306+ if (unlikely(!S_ISDIR(inode->i_mode)))
17307+ goto out_unlock; /* possible? */
dece6358 17308+
4a4d8108
AM
17309+ err = -ENOMEM;
17310+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
17311+ if (unlikely(!args))
17312+ goto out_unlock;
dece6358 17313+
4a4d8108
AM
17314+ parent = dentry->d_parent; /* dir inode is locked */
17315+ di_write_lock_parent(parent);
17316+ err = au_test_empty(dentry, &args->whlist);
17317+ if (unlikely(err))
027c5e7a 17318+ goto out_parent;
1facf9fc 17319+
4a4d8108
AM
17320+ bstart = au_dbstart(dentry);
17321+ bwh = au_dbwh(dentry);
17322+ bindex = -1;
17323+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
17324+ err = PTR_ERR(wh_dentry);
17325+ if (IS_ERR(wh_dentry))
027c5e7a 17326+ goto out_parent;
1facf9fc 17327+
4a4d8108
AM
17328+ h_dentry = au_h_dptr(dentry, bstart);
17329+ dget(h_dentry);
17330+ rmdir_later = 0;
17331+ if (bindex == bstart) {
17332+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
17333+ if (err > 0) {
17334+ rmdir_later = err;
17335+ err = 0;
17336+ }
17337+ } else {
17338+ /* stop monitoring */
17339+ au_hn_free(au_hi(inode, bstart));
17340+
17341+ /* dir inode is locked */
17342+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 17343+ err = 0;
17344+ }
17345+
4a4d8108 17346+ if (!err) {
027c5e7a 17347+ vfsub_dead_dir(inode);
4a4d8108
AM
17348+ au_set_dbdiropq(dentry, -1);
17349+ epilog(dir, dentry, bindex);
1308ab2a 17350+
4a4d8108
AM
17351+ if (rmdir_later) {
17352+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
17353+ args = NULL;
17354+ }
1308ab2a 17355+
4a4d8108 17356+ goto out_unpin; /* success */
1facf9fc 17357+ }
17358+
4a4d8108
AM
17359+ /* revert */
17360+ AuLabel(revert);
17361+ if (wh_dentry) {
17362+ int rerr;
1308ab2a 17363+
7f207e10 17364+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
17365+ if (rerr)
17366+ err = rerr;
1facf9fc 17367+ }
17368+
4f0767ce 17369+out_unpin:
4a4d8108
AM
17370+ au_unpin(&pin);
17371+ dput(wh_dentry);
17372+ dput(h_dentry);
027c5e7a 17373+out_parent:
4a4d8108
AM
17374+ di_write_unlock(parent);
17375+ if (args)
17376+ au_whtmp_rmdir_free(args);
4f0767ce 17377+out_unlock:
4a4d8108 17378+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 17379+out:
4a4d8108
AM
17380+ AuTraceErr(err);
17381+ return err;
dece6358 17382+}
7f207e10
AM
17383diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
17384--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 17385+++ linux/fs/aufs/i_op_ren.c 2012-08-26 08:39:00.760508065 +0200
7eafdf33 17386@@ -0,0 +1,1026 @@
1facf9fc 17387+/*
f6c5ef8b 17388+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 17389+ *
17390+ * This program, aufs is free software; you can redistribute it and/or modify
17391+ * it under the terms of the GNU General Public License as published by
17392+ * the Free Software Foundation; either version 2 of the License, or
17393+ * (at your option) any later version.
dece6358
AM
17394+ *
17395+ * This program is distributed in the hope that it will be useful,
17396+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17397+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17398+ * GNU General Public License for more details.
17399+ *
17400+ * You should have received a copy of the GNU General Public License
17401+ * along with this program; if not, write to the Free Software
17402+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17403+ */
17404+
17405+/*
4a4d8108
AM
17406+ * inode operation (rename entry)
17407+ * todo: this is crazy monster
1facf9fc 17408+ */
17409+
17410+#include "aufs.h"
17411+
4a4d8108
AM
17412+enum { AuSRC, AuDST, AuSrcDst };
17413+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 17414+
4a4d8108
AM
17415+#define AuRen_ISDIR 1
17416+#define AuRen_ISSAMEDIR (1 << 1)
17417+#define AuRen_WHSRC (1 << 2)
17418+#define AuRen_WHDST (1 << 3)
17419+#define AuRen_MNT_WRITE (1 << 4)
17420+#define AuRen_DT_DSTDIR (1 << 5)
17421+#define AuRen_DIROPQ (1 << 6)
17422+#define AuRen_CPUP (1 << 7)
17423+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
17424+#define au_fset_ren(flags, name) \
17425+ do { (flags) |= AuRen_##name; } while (0)
17426+#define au_fclr_ren(flags, name) \
17427+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 17428+
4a4d8108
AM
17429+struct au_ren_args {
17430+ struct {
17431+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
17432+ *wh_dentry;
17433+ struct inode *dir, *inode;
17434+ struct au_hinode *hdir;
17435+ struct au_dtime dt[AuParentChild];
17436+ aufs_bindex_t bstart;
17437+ } sd[AuSrcDst];
1facf9fc 17438+
4a4d8108
AM
17439+#define src_dentry sd[AuSRC].dentry
17440+#define src_dir sd[AuSRC].dir
17441+#define src_inode sd[AuSRC].inode
17442+#define src_h_dentry sd[AuSRC].h_dentry
17443+#define src_parent sd[AuSRC].parent
17444+#define src_h_parent sd[AuSRC].h_parent
17445+#define src_wh_dentry sd[AuSRC].wh_dentry
17446+#define src_hdir sd[AuSRC].hdir
17447+#define src_h_dir sd[AuSRC].hdir->hi_inode
17448+#define src_dt sd[AuSRC].dt
17449+#define src_bstart sd[AuSRC].bstart
1facf9fc 17450+
4a4d8108
AM
17451+#define dst_dentry sd[AuDST].dentry
17452+#define dst_dir sd[AuDST].dir
17453+#define dst_inode sd[AuDST].inode
17454+#define dst_h_dentry sd[AuDST].h_dentry
17455+#define dst_parent sd[AuDST].parent
17456+#define dst_h_parent sd[AuDST].h_parent
17457+#define dst_wh_dentry sd[AuDST].wh_dentry
17458+#define dst_hdir sd[AuDST].hdir
17459+#define dst_h_dir sd[AuDST].hdir->hi_inode
17460+#define dst_dt sd[AuDST].dt
17461+#define dst_bstart sd[AuDST].bstart
17462+
17463+ struct dentry *h_trap;
17464+ struct au_branch *br;
17465+ struct au_hinode *src_hinode;
17466+ struct path h_path;
17467+ struct au_nhash whlist;
027c5e7a 17468+ aufs_bindex_t btgt, src_bwh, src_bdiropq;
1facf9fc 17469+
1308ab2a 17470+ unsigned int flags;
1facf9fc 17471+
4a4d8108
AM
17472+ struct au_whtmp_rmdir *thargs;
17473+ struct dentry *h_dst;
17474+};
1308ab2a 17475+
4a4d8108 17476+/* ---------------------------------------------------------------------- */
1308ab2a 17477+
4a4d8108
AM
17478+/*
17479+ * functions for reverting.
17480+ * when an error happened in a single rename systemcall, we should revert
17481+ * everything as if nothing happend.
17482+ * we don't need to revert the copied-up/down the parent dir since they are
17483+ * harmless.
17484+ */
1facf9fc 17485+
4a4d8108
AM
17486+#define RevertFailure(fmt, ...) do { \
17487+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
17488+ ##__VA_ARGS__, err, rerr); \
17489+ err = -EIO; \
17490+} while (0)
1facf9fc 17491+
4a4d8108 17492+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 17493+{
4a4d8108 17494+ int rerr;
1facf9fc 17495+
4a4d8108
AM
17496+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
17497+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
17498+ au_hn_imtx_unlock(a->src_hinode);
027c5e7a 17499+ au_set_dbdiropq(a->src_dentry, a->src_bdiropq);
4a4d8108
AM
17500+ if (rerr)
17501+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
17502+}
1facf9fc 17503+
4a4d8108
AM
17504+static void au_ren_rev_rename(int err, struct au_ren_args *a)
17505+{
17506+ int rerr;
1facf9fc 17507+
4a4d8108
AM
17508+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
17509+ a->br, /*nd*/NULL);
17510+ rerr = PTR_ERR(a->h_path.dentry);
17511+ if (IS_ERR(a->h_path.dentry)) {
17512+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
17513+ return;
1facf9fc 17514+ }
17515+
4a4d8108
AM
17516+ rerr = vfsub_rename(a->dst_h_dir,
17517+ au_h_dptr(a->src_dentry, a->btgt),
17518+ a->src_h_dir, &a->h_path);
17519+ d_drop(a->h_path.dentry);
17520+ dput(a->h_path.dentry);
17521+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
17522+ if (rerr)
17523+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 17524+}
17525+
4a4d8108 17526+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 17527+{
4a4d8108 17528+ int rerr;
1facf9fc 17529+
4a4d8108
AM
17530+ a->h_path.dentry = a->dst_h_dentry;
17531+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
17532+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
17533+ au_set_dbstart(a->src_dentry, a->src_bstart);
17534+ if (rerr)
17535+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 17536+}
17537+
4a4d8108 17538+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 17539+{
4a4d8108 17540+ int rerr;
dece6358 17541+
4a4d8108
AM
17542+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
17543+ a->br, /*nd*/NULL);
17544+ rerr = PTR_ERR(a->h_path.dentry);
17545+ if (IS_ERR(a->h_path.dentry)) {
17546+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
17547+ return;
17548+ }
17549+ if (a->h_path.dentry->d_inode) {
17550+ d_drop(a->h_path.dentry);
17551+ dput(a->h_path.dentry);
17552+ return;
dece6358
AM
17553+ }
17554+
4a4d8108
AM
17555+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
17556+ d_drop(a->h_path.dentry);
17557+ dput(a->h_path.dentry);
17558+ if (!rerr)
17559+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
17560+ else
17561+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
17562+}
1308ab2a 17563+
4a4d8108
AM
17564+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
17565+{
17566+ int rerr;
1308ab2a 17567+
4a4d8108
AM
17568+ a->h_path.dentry = a->src_wh_dentry;
17569+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 17570+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108
AM
17571+ if (rerr)
17572+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
17573+}
4a4d8108 17574+#undef RevertFailure
1facf9fc 17575+
1308ab2a 17576+/* ---------------------------------------------------------------------- */
17577+
4a4d8108
AM
17578+/*
17579+ * when we have to copyup the renaming entry, do it with the rename-target name
17580+ * in order to minimize the cost (the later actual rename is unnecessary).
17581+ * otherwise rename it on the target branch.
17582+ */
17583+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 17584+{
dece6358 17585+ int err;
4a4d8108 17586+ struct dentry *d;
1facf9fc 17587+
4a4d8108
AM
17588+ d = a->src_dentry;
17589+ if (au_dbstart(d) == a->btgt) {
17590+ a->h_path.dentry = a->dst_h_dentry;
17591+ if (au_ftest_ren(a->flags, DIROPQ)
17592+ && au_dbdiropq(d) == a->btgt)
17593+ au_fclr_ren(a->flags, DIROPQ);
17594+ AuDebugOn(au_dbstart(d) != a->btgt);
17595+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
17596+ a->dst_h_dir, &a->h_path);
17597+ } else {
17598+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
17599+ struct file *h_file;
1308ab2a 17600+
4a4d8108
AM
17601+ au_fset_ren(a->flags, CPUP);
17602+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
17603+ au_set_dbstart(d, a->btgt);
17604+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
17605+ h_file = au_h_open_pre(d, a->src_bstart);
17606+ if (IS_ERR(h_file)) {
17607+ err = PTR_ERR(h_file);
17608+ h_file = NULL;
17609+ } else
17610+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
17611+ !AuCpup_DTIME, a->dst_parent);
17612+ mutex_unlock(h_mtx);
17613+ au_h_open_post(d, a->src_bstart, h_file);
17614+ if (!err) {
17615+ d = a->dst_dentry;
17616+ au_set_h_dptr(d, a->btgt, NULL);
17617+ au_update_dbstart(d);
17618+ } else {
17619+ au_set_h_dptr(d, a->btgt, NULL);
17620+ au_set_dbstart(d, a->src_bstart);
17621+ }
1308ab2a 17622+ }
027c5e7a
AM
17623+ if (!err && a->h_dst)
17624+ /* it will be set to dinfo later */
17625+ dget(a->h_dst);
1facf9fc 17626+
dece6358
AM
17627+ return err;
17628+}
1facf9fc 17629+
4a4d8108
AM
17630+/* cf. aufs_rmdir() */
17631+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 17632+{
4a4d8108
AM
17633+ int err;
17634+ struct inode *dir;
1facf9fc 17635+
4a4d8108
AM
17636+ dir = a->dst_dir;
17637+ SiMustAnyLock(dir->i_sb);
17638+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
17639+ au_sbi(dir->i_sb)->si_dirwh)
17640+ || au_test_fs_remote(a->h_dst->d_sb)) {
17641+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
17642+ if (unlikely(err))
0c3ec466
AM
17643+ pr_warn("failed removing whtmp dir %.*s (%d), "
17644+ "ignored.\n", AuDLNPair(a->h_dst), err);
4a4d8108
AM
17645+ } else {
17646+ au_nhash_wh_free(&a->thargs->whlist);
17647+ a->thargs->whlist = a->whlist;
17648+ a->whlist.nh_num = 0;
17649+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
17650+ dput(a->h_dst);
17651+ a->thargs = NULL;
17652+ }
17653+
17654+ return 0;
1308ab2a 17655+}
1facf9fc 17656+
4a4d8108
AM
17657+/* make it 'opaque' dir. */
17658+static int au_ren_diropq(struct au_ren_args *a)
17659+{
17660+ int err;
17661+ struct dentry *diropq;
1facf9fc 17662+
4a4d8108 17663+ err = 0;
027c5e7a 17664+ a->src_bdiropq = au_dbdiropq(a->src_dentry);
4a4d8108
AM
17665+ a->src_hinode = au_hi(a->src_inode, a->btgt);
17666+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
17667+ diropq = au_diropq_create(a->src_dentry, a->btgt);
17668+ au_hn_imtx_unlock(a->src_hinode);
17669+ if (IS_ERR(diropq))
17670+ err = PTR_ERR(diropq);
17671+ dput(diropq);
1facf9fc 17672+
4a4d8108
AM
17673+ return err;
17674+}
1facf9fc 17675+
4a4d8108
AM
17676+static int do_rename(struct au_ren_args *a)
17677+{
17678+ int err;
17679+ struct dentry *d, *h_d;
1facf9fc 17680+
4a4d8108
AM
17681+ /* prepare workqueue args for asynchronous rmdir */
17682+ h_d = a->dst_h_dentry;
17683+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
17684+ err = -ENOMEM;
17685+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
17686+ if (unlikely(!a->thargs))
17687+ goto out;
17688+ a->h_dst = dget(h_d);
17689+ }
1facf9fc 17690+
4a4d8108
AM
17691+ /* create whiteout for src_dentry */
17692+ if (au_ftest_ren(a->flags, WHSRC)) {
027c5e7a
AM
17693+ a->src_bwh = au_dbwh(a->src_dentry);
17694+ AuDebugOn(a->src_bwh >= 0);
4a4d8108
AM
17695+ a->src_wh_dentry
17696+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
17697+ err = PTR_ERR(a->src_wh_dentry);
17698+ if (IS_ERR(a->src_wh_dentry))
17699+ goto out_thargs;
17700+ }
1facf9fc 17701+
4a4d8108
AM
17702+ /* lookup whiteout for dentry */
17703+ if (au_ftest_ren(a->flags, WHDST)) {
17704+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
17705+ a->br);
17706+ err = PTR_ERR(h_d);
17707+ if (IS_ERR(h_d))
17708+ goto out_whsrc;
17709+ if (!h_d->d_inode)
17710+ dput(h_d);
17711+ else
17712+ a->dst_wh_dentry = h_d;
17713+ }
1facf9fc 17714+
4a4d8108
AM
17715+ /* rename dentry to tmpwh */
17716+ if (a->thargs) {
17717+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
17718+ if (unlikely(err))
17719+ goto out_whdst;
dece6358 17720+
4a4d8108
AM
17721+ d = a->dst_dentry;
17722+ au_set_h_dptr(d, a->btgt, NULL);
17723+ err = au_lkup_neg(d, a->btgt);
17724+ if (unlikely(err))
17725+ goto out_whtmp;
17726+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
17727+ }
1facf9fc 17728+
4a4d8108
AM
17729+ /* cpup src */
17730+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
17731+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
17732+ struct file *h_file;
1facf9fc 17733+
4a4d8108
AM
17734+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
17735+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
17736+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
17737+ if (IS_ERR(h_file)) {
17738+ err = PTR_ERR(h_file);
17739+ h_file = NULL;
17740+ } else
17741+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
17742+ !AuCpup_DTIME);
17743+ mutex_unlock(h_mtx);
17744+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
17745+ if (unlikely(err))
17746+ goto out_whtmp;
17747+ }
1facf9fc 17748+
4a4d8108
AM
17749+ /* rename by vfs_rename or cpup */
17750+ d = a->dst_dentry;
17751+ if (au_ftest_ren(a->flags, ISDIR)
17752+ && (a->dst_wh_dentry
17753+ || au_dbdiropq(d) == a->btgt
17754+ /* hide the lower to keep xino */
17755+ || a->btgt < au_dbend(d)
17756+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
17757+ au_fset_ren(a->flags, DIROPQ);
17758+ err = au_ren_or_cpup(a);
17759+ if (unlikely(err))
17760+ /* leave the copied-up one */
17761+ goto out_whtmp;
1308ab2a 17762+
4a4d8108
AM
17763+ /* make dir opaque */
17764+ if (au_ftest_ren(a->flags, DIROPQ)) {
17765+ err = au_ren_diropq(a);
17766+ if (unlikely(err))
17767+ goto out_rename;
17768+ }
1308ab2a 17769+
4a4d8108
AM
17770+ /* update target timestamps */
17771+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
17772+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
17773+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
17774+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 17775+
4a4d8108
AM
17776+ /* remove whiteout for dentry */
17777+ if (a->dst_wh_dentry) {
17778+ a->h_path.dentry = a->dst_wh_dentry;
17779+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
17780+ a->dst_dentry);
17781+ if (unlikely(err))
17782+ goto out_diropq;
17783+ }
1facf9fc 17784+
4a4d8108
AM
17785+ /* remove whtmp */
17786+ if (a->thargs)
17787+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 17788+
4a4d8108
AM
17789+ err = 0;
17790+ goto out_success;
17791+
4f0767ce 17792+out_diropq:
4a4d8108
AM
17793+ if (au_ftest_ren(a->flags, DIROPQ))
17794+ au_ren_rev_diropq(err, a);
4f0767ce 17795+out_rename:
4a4d8108
AM
17796+ if (!au_ftest_ren(a->flags, CPUP))
17797+ au_ren_rev_rename(err, a);
17798+ else
17799+ au_ren_rev_cpup(err, a);
027c5e7a 17800+ dput(a->h_dst);
4f0767ce 17801+out_whtmp:
4a4d8108
AM
17802+ if (a->thargs)
17803+ au_ren_rev_whtmp(err, a);
4f0767ce 17804+out_whdst:
4a4d8108
AM
17805+ dput(a->dst_wh_dentry);
17806+ a->dst_wh_dentry = NULL;
4f0767ce 17807+out_whsrc:
4a4d8108
AM
17808+ if (a->src_wh_dentry)
17809+ au_ren_rev_whsrc(err, a);
4f0767ce 17810+out_success:
4a4d8108
AM
17811+ dput(a->src_wh_dentry);
17812+ dput(a->dst_wh_dentry);
4f0767ce 17813+out_thargs:
4a4d8108
AM
17814+ if (a->thargs) {
17815+ dput(a->h_dst);
17816+ au_whtmp_rmdir_free(a->thargs);
17817+ a->thargs = NULL;
17818+ }
4f0767ce 17819+out:
4a4d8108 17820+ return err;
dece6358 17821+}
1facf9fc 17822+
1308ab2a 17823+/* ---------------------------------------------------------------------- */
1facf9fc 17824+
4a4d8108
AM
17825+/*
17826+ * test if @dentry dir can be rename destination or not.
17827+ * success means, it is a logically empty dir.
17828+ */
17829+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 17830+{
4a4d8108 17831+ return au_test_empty(dentry, whlist);
1308ab2a 17832+}
1facf9fc 17833+
4a4d8108
AM
17834+/*
17835+ * test if @dentry dir can be rename source or not.
17836+ * if it can, return 0 and @children is filled.
17837+ * success means,
17838+ * - it is a logically empty dir.
17839+ * - or, it exists on writable branch and has no children including whiteouts
17840+ * on the lower branch.
17841+ */
17842+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
17843+{
17844+ int err;
17845+ unsigned int rdhash;
17846+ aufs_bindex_t bstart;
1facf9fc 17847+
4a4d8108
AM
17848+ bstart = au_dbstart(dentry);
17849+ if (bstart != btgt) {
17850+ struct au_nhash whlist;
dece6358 17851+
4a4d8108
AM
17852+ SiMustAnyLock(dentry->d_sb);
17853+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
17854+ if (!rdhash)
17855+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
17856+ dentry));
17857+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
17858+ if (unlikely(err))
17859+ goto out;
17860+ err = au_test_empty(dentry, &whlist);
17861+ au_nhash_wh_free(&whlist);
17862+ goto out;
17863+ }
dece6358 17864+
4a4d8108
AM
17865+ if (bstart == au_dbtaildir(dentry))
17866+ return 0; /* success */
dece6358 17867+
4a4d8108 17868+ err = au_test_empty_lower(dentry);
1facf9fc 17869+
4f0767ce 17870+out:
4a4d8108
AM
17871+ if (err == -ENOTEMPTY) {
17872+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
17873+ " is not supported\n");
17874+ err = -EXDEV;
17875+ }
17876+ return err;
17877+}
1308ab2a 17878+
4a4d8108
AM
17879+/* side effect: sets whlist and h_dentry */
17880+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 17881+{
4a4d8108
AM
17882+ int err;
17883+ unsigned int rdhash;
17884+ struct dentry *d;
1facf9fc 17885+
4a4d8108
AM
17886+ d = a->dst_dentry;
17887+ SiMustAnyLock(d->d_sb);
1facf9fc 17888+
4a4d8108
AM
17889+ err = 0;
17890+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
17891+ rdhash = au_sbi(d->d_sb)->si_rdhash;
17892+ if (!rdhash)
17893+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
17894+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
17895+ if (unlikely(err))
17896+ goto out;
1308ab2a 17897+
4a4d8108
AM
17898+ au_set_dbstart(d, a->dst_bstart);
17899+ err = may_rename_dstdir(d, &a->whlist);
17900+ au_set_dbstart(d, a->btgt);
17901+ }
17902+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
17903+ if (unlikely(err))
17904+ goto out;
17905+
17906+ d = a->src_dentry;
17907+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
17908+ if (au_ftest_ren(a->flags, ISDIR)) {
17909+ err = may_rename_srcdir(d, a->btgt);
17910+ if (unlikely(err)) {
17911+ au_nhash_wh_free(&a->whlist);
17912+ a->whlist.nh_num = 0;
17913+ }
17914+ }
4f0767ce 17915+out:
4a4d8108 17916+ return err;
1facf9fc 17917+}
17918+
4a4d8108 17919+/* ---------------------------------------------------------------------- */
1facf9fc 17920+
4a4d8108
AM
17921+/*
17922+ * simple tests for rename.
17923+ * following the checks in vfs, plus the parent-child relationship.
17924+ */
17925+static int au_may_ren(struct au_ren_args *a)
17926+{
17927+ int err, isdir;
17928+ struct inode *h_inode;
1facf9fc 17929+
4a4d8108
AM
17930+ if (a->src_bstart == a->btgt) {
17931+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
17932+ au_ftest_ren(a->flags, ISDIR));
17933+ if (unlikely(err))
17934+ goto out;
17935+ err = -EINVAL;
17936+ if (unlikely(a->src_h_dentry == a->h_trap))
17937+ goto out;
17938+ }
1facf9fc 17939+
4a4d8108
AM
17940+ err = 0;
17941+ if (a->dst_bstart != a->btgt)
17942+ goto out;
1facf9fc 17943+
027c5e7a
AM
17944+ err = -ENOTEMPTY;
17945+ if (unlikely(a->dst_h_dentry == a->h_trap))
17946+ goto out;
17947+
4a4d8108
AM
17948+ err = -EIO;
17949+ h_inode = a->dst_h_dentry->d_inode;
17950+ isdir = !!au_ftest_ren(a->flags, ISDIR);
17951+ if (!a->dst_dentry->d_inode) {
17952+ if (unlikely(h_inode))
17953+ goto out;
17954+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
17955+ isdir);
17956+ } else {
17957+ if (unlikely(!h_inode || !h_inode->i_nlink))
17958+ goto out;
17959+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
17960+ isdir);
17961+ if (unlikely(err))
17962+ goto out;
4a4d8108 17963+ }
1facf9fc 17964+
4f0767ce 17965+out:
4a4d8108
AM
17966+ if (unlikely(err == -ENOENT || err == -EEXIST))
17967+ err = -EIO;
17968+ AuTraceErr(err);
17969+ return err;
17970+}
1facf9fc 17971+
1308ab2a 17972+/* ---------------------------------------------------------------------- */
1facf9fc 17973+
4a4d8108
AM
17974+/*
17975+ * locking order
17976+ * (VFS)
17977+ * - src_dir and dir by lock_rename()
17978+ * - inode if exitsts
17979+ * (aufs)
17980+ * - lock all
17981+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
17982+ * + si_read_lock
17983+ * + di_write_lock2_child()
17984+ * + di_write_lock_child()
17985+ * + ii_write_lock_child()
17986+ * + di_write_lock_child2()
17987+ * + ii_write_lock_child2()
17988+ * + src_parent and parent
17989+ * + di_write_lock_parent()
17990+ * + ii_write_lock_parent()
17991+ * + di_write_lock_parent2()
17992+ * + ii_write_lock_parent2()
17993+ * + lower src_dir and dir by vfsub_lock_rename()
17994+ * + verify the every relationships between child and parent. if any
17995+ * of them failed, unlock all and return -EBUSY.
17996+ */
17997+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 17998+{
4a4d8108
AM
17999+ struct super_block *sb;
18000+
18001+ sb = a->dst_dentry->d_sb;
18002+ if (au_ftest_ren(a->flags, MNT_WRITE))
18003+ mnt_drop_write(a->br->br_mnt);
18004+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
18005+ a->dst_h_parent, a->dst_hdir);
1308ab2a 18006+}
18007+
4a4d8108 18008+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 18009+{
4a4d8108
AM
18010+ int err;
18011+ unsigned int udba;
1308ab2a 18012+
4a4d8108
AM
18013+ err = 0;
18014+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
18015+ a->src_hdir = au_hi(a->src_dir, a->btgt);
18016+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
18017+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
18018+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
18019+ a->dst_h_parent, a->dst_hdir);
18020+ udba = au_opt_udba(a->src_dentry->d_sb);
18021+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
18022+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
18023+ err = au_busy_or_stale();
18024+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
18025+ err = au_h_verify(a->src_h_dentry, udba,
18026+ a->src_h_parent->d_inode, a->src_h_parent,
18027+ a->br);
18028+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
18029+ err = au_h_verify(a->dst_h_dentry, udba,
18030+ a->dst_h_parent->d_inode, a->dst_h_parent,
18031+ a->br);
18032+ if (!err) {
18033+ err = mnt_want_write(a->br->br_mnt);
18034+ if (unlikely(err))
18035+ goto out_unlock;
18036+ au_fset_ren(a->flags, MNT_WRITE);
18037+ goto out; /* success */
18038+ }
18039+
18040+ err = au_busy_or_stale();
18041+
4f0767ce 18042+out_unlock:
4a4d8108 18043+ au_ren_unlock(a);
4f0767ce 18044+out:
4a4d8108 18045+ return err;
1facf9fc 18046+}
18047+
18048+/* ---------------------------------------------------------------------- */
18049+
4a4d8108 18050+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 18051+{
4a4d8108 18052+ struct inode *dir;
dece6358 18053+
4a4d8108
AM
18054+ dir = a->dst_dir;
18055+ dir->i_version++;
18056+ if (au_ftest_ren(a->flags, ISDIR)) {
18057+ /* is this updating defined in POSIX? */
18058+ au_cpup_attr_timesizes(a->src_inode);
18059+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 18060+ }
027c5e7a 18061+
4a4d8108
AM
18062+ if (au_ibstart(dir) == a->btgt)
18063+ au_cpup_attr_timesizes(dir);
dece6358 18064+
4a4d8108
AM
18065+ if (au_ftest_ren(a->flags, ISSAMEDIR))
18066+ return;
dece6358 18067+
4a4d8108
AM
18068+ dir = a->src_dir;
18069+ dir->i_version++;
18070+ if (au_ftest_ren(a->flags, ISDIR))
18071+ au_cpup_attr_nlink(dir, /*force*/1);
18072+ if (au_ibstart(dir) == a->btgt)
18073+ au_cpup_attr_timesizes(dir);
1facf9fc 18074+}
18075+
4a4d8108 18076+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 18077+{
4a4d8108
AM
18078+ aufs_bindex_t bend, bindex;
18079+ struct dentry *d, *h_d;
18080+ struct inode *i, *h_i;
18081+ struct super_block *sb;
dece6358 18082+
027c5e7a
AM
18083+ d = a->dst_dentry;
18084+ d_drop(d);
18085+ if (a->h_dst)
18086+ /* already dget-ed by au_ren_or_cpup() */
18087+ au_set_h_dptr(d, a->btgt, a->h_dst);
18088+
18089+ i = a->dst_inode;
18090+ if (i) {
18091+ if (!au_ftest_ren(a->flags, ISDIR))
18092+ vfsub_drop_nlink(i);
18093+ else {
18094+ vfsub_dead_dir(i);
18095+ au_cpup_attr_timesizes(i);
18096+ }
18097+ au_update_dbrange(d, /*do_put_zero*/1);
18098+ } else {
18099+ bend = a->btgt;
18100+ for (bindex = au_dbstart(d); bindex < bend; bindex++)
18101+ au_set_h_dptr(d, bindex, NULL);
18102+ bend = au_dbend(d);
18103+ for (bindex = a->btgt + 1; bindex <= bend; bindex++)
18104+ au_set_h_dptr(d, bindex, NULL);
18105+ au_update_dbrange(d, /*do_put_zero*/0);
18106+ }
18107+
4a4d8108
AM
18108+ d = a->src_dentry;
18109+ au_set_dbwh(d, -1);
18110+ bend = au_dbend(d);
18111+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
18112+ h_d = au_h_dptr(d, bindex);
18113+ if (h_d)
18114+ au_set_h_dptr(d, bindex, NULL);
18115+ }
18116+ au_set_dbend(d, a->btgt);
18117+
18118+ sb = d->d_sb;
18119+ i = a->src_inode;
18120+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
18121+ return; /* success */
18122+
18123+ bend = au_ibend(i);
18124+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
18125+ h_i = au_h_iptr(i, bindex);
18126+ if (h_i) {
18127+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
18128+ /* ignore this error */
18129+ au_set_h_iptr(i, bindex, NULL, 0);
18130+ }
18131+ }
18132+ au_set_ibend(i, a->btgt);
1308ab2a 18133+}
dece6358 18134+
4a4d8108
AM
18135+/* ---------------------------------------------------------------------- */
18136+
18137+/* mainly for link(2) and rename(2) */
18138+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 18139+{
4a4d8108
AM
18140+ aufs_bindex_t bdiropq, bwh;
18141+ struct dentry *parent;
18142+ struct au_branch *br;
18143+
18144+ parent = dentry->d_parent;
18145+ IMustLock(parent->d_inode); /* dir is locked */
18146+
18147+ bdiropq = au_dbdiropq(parent);
18148+ bwh = au_dbwh(dentry);
18149+ br = au_sbr(dentry->d_sb, btgt);
18150+ if (au_br_rdonly(br)
18151+ || (0 <= bdiropq && bdiropq < btgt)
18152+ || (0 <= bwh && bwh < btgt))
18153+ btgt = -1;
18154+
18155+ AuDbg("btgt %d\n", btgt);
18156+ return btgt;
1facf9fc 18157+}
18158+
4a4d8108
AM
18159+/* sets src_bstart, dst_bstart and btgt */
18160+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 18161+{
4a4d8108
AM
18162+ int err;
18163+ struct au_wr_dir_args wr_dir_args = {
18164+ /* .force_btgt = -1, */
18165+ .flags = AuWrDir_ADD_ENTRY
18166+ };
dece6358 18167+
4a4d8108
AM
18168+ a->src_bstart = au_dbstart(a->src_dentry);
18169+ a->dst_bstart = au_dbstart(a->dst_dentry);
18170+ if (au_ftest_ren(a->flags, ISDIR))
18171+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
18172+ wr_dir_args.force_btgt = a->src_bstart;
18173+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
18174+ wr_dir_args.force_btgt = a->dst_bstart;
18175+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
18176+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
18177+ a->btgt = err;
dece6358 18178+
4a4d8108 18179+ return err;
1facf9fc 18180+}
18181+
4a4d8108 18182+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 18183+{
4a4d8108
AM
18184+ a->h_path.dentry = a->src_h_parent;
18185+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
18186+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
18187+ a->h_path.dentry = a->dst_h_parent;
18188+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
18189+ }
1facf9fc 18190+
4a4d8108
AM
18191+ au_fclr_ren(a->flags, DT_DSTDIR);
18192+ if (!au_ftest_ren(a->flags, ISDIR))
18193+ return;
dece6358 18194+
4a4d8108
AM
18195+ a->h_path.dentry = a->src_h_dentry;
18196+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
18197+ if (a->dst_h_dentry->d_inode) {
18198+ au_fset_ren(a->flags, DT_DSTDIR);
18199+ a->h_path.dentry = a->dst_h_dentry;
18200+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
18201+ }
1308ab2a 18202+}
dece6358 18203+
4a4d8108 18204+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 18205+{
4a4d8108
AM
18206+ struct dentry *h_d;
18207+ struct mutex *h_mtx;
18208+
18209+ au_dtime_revert(a->src_dt + AuPARENT);
18210+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
18211+ au_dtime_revert(a->dst_dt + AuPARENT);
18212+
18213+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
18214+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
18215+ h_mtx = &h_d->d_inode->i_mutex;
18216+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
18217+ au_dtime_revert(a->src_dt + AuCHILD);
18218+ mutex_unlock(h_mtx);
18219+
18220+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
18221+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
18222+ h_mtx = &h_d->d_inode->i_mutex;
18223+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
18224+ au_dtime_revert(a->dst_dt + AuCHILD);
18225+ mutex_unlock(h_mtx);
1facf9fc 18226+ }
18227+ }
18228+}
18229+
4a4d8108
AM
18230+/* ---------------------------------------------------------------------- */
18231+
18232+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
18233+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 18234+{
e49829fe 18235+ int err, flags;
4a4d8108
AM
18236+ /* reduce stack space */
18237+ struct au_ren_args *a;
18238+
18239+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
18240+ IMustLock(_src_dir);
18241+ IMustLock(_dst_dir);
18242+
18243+ err = -ENOMEM;
18244+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
18245+ a = kzalloc(sizeof(*a), GFP_NOFS);
18246+ if (unlikely(!a))
18247+ goto out;
18248+
18249+ a->src_dir = _src_dir;
18250+ a->src_dentry = _src_dentry;
18251+ a->src_inode = a->src_dentry->d_inode;
18252+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
18253+ a->dst_dir = _dst_dir;
18254+ a->dst_dentry = _dst_dentry;
18255+ a->dst_inode = a->dst_dentry->d_inode;
18256+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
18257+ if (a->dst_inode) {
18258+ IMustLock(a->dst_inode);
18259+ au_igrab(a->dst_inode);
1facf9fc 18260+ }
1facf9fc 18261+
4a4d8108 18262+ err = -ENOTDIR;
027c5e7a 18263+ flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
4a4d8108
AM
18264+ if (S_ISDIR(a->src_inode->i_mode)) {
18265+ au_fset_ren(a->flags, ISDIR);
18266+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
18267+ goto out_free;
e49829fe
JR
18268+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
18269+ AuLock_DIR | flags);
4a4d8108 18270+ } else
e49829fe
JR
18271+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
18272+ flags);
18273+ if (unlikely(err))
18274+ goto out_free;
1facf9fc 18275+
027c5e7a
AM
18276+ err = au_d_hashed_positive(a->src_dentry);
18277+ if (unlikely(err))
18278+ goto out_unlock;
18279+ err = -ENOENT;
18280+ if (a->dst_inode) {
18281+ /*
18282+ * If it is a dir, VFS unhash dst_dentry before this
18283+ * function. It means we cannot rely upon d_unhashed().
18284+ */
18285+ if (unlikely(!a->dst_inode->i_nlink))
18286+ goto out_unlock;
18287+ if (!S_ISDIR(a->dst_inode->i_mode)) {
18288+ err = au_d_hashed_positive(a->dst_dentry);
18289+ if (unlikely(err))
18290+ goto out_unlock;
18291+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
18292+ goto out_unlock;
18293+ } else if (unlikely(d_unhashed(a->dst_dentry)))
18294+ goto out_unlock;
18295+
7eafdf33
AM
18296+ /*
18297+ * is it possible?
18298+ * yes, it happend (in linux-3.3-rcN) but I don't know why.
18299+ * there may exist a problem somewhere else.
18300+ */
18301+ err = -EINVAL;
18302+ if (unlikely(a->dst_parent->d_inode == a->src_dentry->d_inode))
18303+ goto out_unlock;
18304+
4a4d8108
AM
18305+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
18306+ di_write_lock_parent(a->dst_parent);
1facf9fc 18307+
4a4d8108
AM
18308+ /* which branch we process */
18309+ err = au_ren_wbr(a);
18310+ if (unlikely(err < 0))
027c5e7a 18311+ goto out_parent;
4a4d8108
AM
18312+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
18313+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 18314+
4a4d8108
AM
18315+ /* are they available to be renamed */
18316+ err = au_ren_may_dir(a);
18317+ if (unlikely(err))
18318+ goto out_children;
1facf9fc 18319+
4a4d8108
AM
18320+ /* prepare the writable parent dir on the same branch */
18321+ if (a->dst_bstart == a->btgt) {
18322+ au_fset_ren(a->flags, WHDST);
18323+ } else {
18324+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
18325+ if (unlikely(err))
18326+ goto out_children;
18327+ }
1facf9fc 18328+
4a4d8108
AM
18329+ if (a->src_dir != a->dst_dir) {
18330+ /*
18331+ * this temporary unlock is safe,
18332+ * because both dir->i_mutex are locked.
18333+ */
18334+ di_write_unlock(a->dst_parent);
18335+ di_write_lock_parent(a->src_parent);
18336+ err = au_wr_dir_need_wh(a->src_dentry,
18337+ au_ftest_ren(a->flags, ISDIR),
18338+ &a->btgt);
18339+ di_write_unlock(a->src_parent);
18340+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
18341+ au_fclr_ren(a->flags, ISSAMEDIR);
18342+ } else
18343+ err = au_wr_dir_need_wh(a->src_dentry,
18344+ au_ftest_ren(a->flags, ISDIR),
18345+ &a->btgt);
18346+ if (unlikely(err < 0))
18347+ goto out_children;
18348+ if (err)
18349+ au_fset_ren(a->flags, WHSRC);
1facf9fc 18350+
4a4d8108
AM
18351+ /* lock them all */
18352+ err = au_ren_lock(a);
18353+ if (unlikely(err))
18354+ goto out_children;
1facf9fc 18355+
4a4d8108
AM
18356+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
18357+ err = au_may_ren(a);
18358+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
18359+ err = -ENAMETOOLONG;
18360+ if (unlikely(err))
18361+ goto out_hdir;
1facf9fc 18362+
4a4d8108
AM
18363+ /* store timestamps to be revertible */
18364+ au_ren_dt(a);
1facf9fc 18365+
4a4d8108
AM
18366+ /* here we go */
18367+ err = do_rename(a);
18368+ if (unlikely(err))
18369+ goto out_dt;
18370+
18371+ /* update dir attributes */
18372+ au_ren_refresh_dir(a);
18373+
18374+ /* dput/iput all lower dentries */
18375+ au_ren_refresh(a);
18376+
18377+ goto out_hdir; /* success */
18378+
4f0767ce 18379+out_dt:
4a4d8108 18380+ au_ren_rev_dt(err, a);
4f0767ce 18381+out_hdir:
4a4d8108 18382+ au_ren_unlock(a);
4f0767ce 18383+out_children:
4a4d8108 18384+ au_nhash_wh_free(&a->whlist);
027c5e7a
AM
18385+ if (err && a->dst_inode && a->dst_bstart != a->btgt) {
18386+ AuDbg("bstart %d, btgt %d\n", a->dst_bstart, a->btgt);
18387+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
18388+ au_set_dbstart(a->dst_dentry, a->dst_bstart);
4a4d8108 18389+ }
027c5e7a 18390+out_parent:
4a4d8108
AM
18391+ if (!err)
18392+ d_move(a->src_dentry, a->dst_dentry);
027c5e7a
AM
18393+ else {
18394+ au_update_dbstart(a->dst_dentry);
18395+ if (!a->dst_inode)
18396+ d_drop(a->dst_dentry);
18397+ }
4a4d8108
AM
18398+ if (au_ftest_ren(a->flags, ISSAMEDIR))
18399+ di_write_unlock(a->dst_parent);
18400+ else
18401+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 18402+out_unlock:
4a4d8108 18403+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 18404+out_free:
4a4d8108
AM
18405+ iput(a->dst_inode);
18406+ if (a->thargs)
18407+ au_whtmp_rmdir_free(a->thargs);
18408+ kfree(a);
4f0767ce 18409+out:
4a4d8108
AM
18410+ AuTraceErr(err);
18411+ return err;
1308ab2a 18412+}
7f207e10
AM
18413diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
18414--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
2dfbb274 18415+++ linux/fs/aufs/Kconfig 2012-08-26 08:39:00.757174634 +0200
2cbb1c4b 18416@@ -0,0 +1,203 @@
4a4d8108
AM
18417+config AUFS_FS
18418+ tristate "Aufs (Advanced multi layered unification filesystem) support"
18419+ depends on EXPERIMENTAL
18420+ help
18421+ Aufs is a stackable unification filesystem such as Unionfs,
18422+ which unifies several directories and provides a merged single
18423+ directory.
18424+ In the early days, aufs was entirely re-designed and
18425+ re-implemented Unionfs Version 1.x series. Introducing many
18426+ original ideas, approaches and improvements, it becomes totally
18427+ different from Unionfs while keeping the basic features.
1facf9fc 18428+
4a4d8108
AM
18429+if AUFS_FS
18430+choice
18431+ prompt "Maximum number of branches"
18432+ default AUFS_BRANCH_MAX_127
18433+ help
18434+ Specifies the maximum number of branches (or member directories)
18435+ in a single aufs. The larger value consumes more system
18436+ resources and has a minor impact to performance.
18437+config AUFS_BRANCH_MAX_127
18438+ bool "127"
18439+ help
18440+ Specifies the maximum number of branches (or member directories)
18441+ in a single aufs. The larger value consumes more system
18442+ resources and has a minor impact to performance.
18443+config AUFS_BRANCH_MAX_511
18444+ bool "511"
18445+ help
18446+ Specifies the maximum number of branches (or member directories)
18447+ in a single aufs. The larger value consumes more system
18448+ resources and has a minor impact to performance.
18449+config AUFS_BRANCH_MAX_1023
18450+ bool "1023"
18451+ help
18452+ Specifies the maximum number of branches (or member directories)
18453+ in a single aufs. The larger value consumes more system
18454+ resources and has a minor impact to performance.
18455+config AUFS_BRANCH_MAX_32767
18456+ bool "32767"
18457+ help
18458+ Specifies the maximum number of branches (or member directories)
18459+ in a single aufs. The larger value consumes more system
18460+ resources and has a minor impact to performance.
18461+endchoice
1facf9fc 18462+
e49829fe
JR
18463+config AUFS_SBILIST
18464+ bool
18465+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
18466+ default y
18467+ help
18468+ Automatic configuration for internal use.
18469+ When aufs supports Magic SysRq or /proc, enabled automatically.
18470+
4a4d8108
AM
18471+config AUFS_HNOTIFY
18472+ bool "Detect direct branch access (bypassing aufs)"
18473+ help
18474+ If you want to modify files on branches directly, eg. bypassing aufs,
18475+ and want aufs to detect the changes of them fully, then enable this
18476+ option and use 'udba=notify' mount option.
7f207e10 18477+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
18478+ It will have a negative impact to the performance.
18479+ See detail in aufs.5.
dece6358 18480+
4a4d8108
AM
18481+choice
18482+ prompt "method" if AUFS_HNOTIFY
18483+ default AUFS_HFSNOTIFY
18484+config AUFS_HFSNOTIFY
18485+ bool "fsnotify"
18486+ select FSNOTIFY
4a4d8108 18487+endchoice
1facf9fc 18488+
4a4d8108
AM
18489+config AUFS_EXPORT
18490+ bool "NFS-exportable aufs"
2cbb1c4b 18491+ depends on EXPORTFS
4a4d8108
AM
18492+ help
18493+ If you want to export your mounted aufs via NFS, then enable this
18494+ option. There are several requirements for this configuration.
18495+ See detail in aufs.5.
1facf9fc 18496+
4a4d8108
AM
18497+config AUFS_INO_T_64
18498+ bool
18499+ depends on AUFS_EXPORT
18500+ depends on 64BIT && !(ALPHA || S390)
18501+ default y
18502+ help
18503+ Automatic configuration for internal use.
18504+ /* typedef unsigned long/int __kernel_ino_t */
18505+ /* alpha and s390x are int */
1facf9fc 18506+
4a4d8108
AM
18507+config AUFS_RDU
18508+ bool "Readdir in userspace"
18509+ help
18510+ Aufs has two methods to provide a merged view for a directory,
18511+ by a user-space library and by kernel-space natively. The latter
18512+ is always enabled but sometimes large and slow.
18513+ If you enable this option, install the library in aufs2-util
18514+ package, and set some environment variables for your readdir(3),
18515+ then the work will be handled in user-space which generally
18516+ shows better performance in most cases.
18517+ See detail in aufs.5.
1facf9fc 18518+
2cbb1c4b
JR
18519+config AUFS_PROC_MAP
18520+ bool "support for /proc/maps and lsof(1)"
18521+ depends on PROC_FS
18522+ help
18523+ When you issue mmap(2) in aufs, it is actually a direct mmap(2)
18524+ call to the file on the branch fs since the file in aufs is
18525+ purely virtual. And the file path printed in /proc/maps (and
18526+ others) will be the path on the branch fs. In most cases, it
18527+ does no harm. But some utilities like lsof(1) may confuse since
18528+ the utility or user may expect the file path in aufs to be
18529+ printed.
18530+ To address this issue, aufs provides a patch which introduces a
18531+ new member called vm_prfile into struct vm_are_struct. The patch
18532+ is meaningless without enabling this configuration since nobody
18533+ sets the new vm_prfile member.
18534+ If you don't apply the patch, then enabling this configuration
18535+ will cause a compile error.
18536+ This approach is fragile since if someone else make some changes
18537+ around vm_file, then vm_prfile may not work anymore. As a
18538+ workaround such case, aufs provides this configuration. If you
18539+ disable it, then lsof(1) may produce incorrect result but the
18540+ problem will be gone even if the aufs patch is applied (I hope).
18541+
4a4d8108
AM
18542+config AUFS_SP_IATTR
18543+ bool "Respect the attributes (mtime/ctime mainly) of special files"
18544+ help
18545+ When you write something to a special file, some attributes of it
18546+ (mtime/ctime mainly) may be updated. Generally such updates are
18547+ less important (actually some device drivers and NFS ignore
18548+ it). But some applications (such like test program) requires
18549+ such updates. If you need these updates, then enable this
18550+ configuration which introduces some overhead.
18551+ Currently this configuration handles FIFO only.
1facf9fc 18552+
4a4d8108
AM
18553+config AUFS_SHWH
18554+ bool "Show whiteouts"
18555+ help
18556+ If you want to make the whiteouts in aufs visible, then enable
18557+ this option and specify 'shwh' mount option. Although it may
18558+ sounds like philosophy or something, but in technically it
18559+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 18560+
4a4d8108
AM
18561+config AUFS_BR_RAMFS
18562+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
18563+ help
18564+ If you want to use ramfs as an aufs branch fs, then enable this
18565+ option. Generally tmpfs is recommended.
18566+ Aufs prohibited them to be a branch fs by default, because
18567+ initramfs becomes unusable after switch_root or something
18568+ generally. If you sets initramfs as an aufs branch and boot your
18569+ system by switch_root, you will meet a problem easily since the
18570+ files in initramfs may be inaccessible.
18571+ Unless you are going to use ramfs as an aufs branch fs without
18572+ switch_root or something, leave it N.
1facf9fc 18573+
4a4d8108
AM
18574+config AUFS_BR_FUSE
18575+ bool "Fuse fs as an aufs branch"
18576+ depends on FUSE_FS
18577+ select AUFS_POLL
18578+ help
18579+ If you want to use fuse-based userspace filesystem as an aufs
18580+ branch fs, then enable this option.
18581+ It implements the internal poll(2) operation which is
18582+ implemented by fuse only (curretnly).
1facf9fc 18583+
4a4d8108
AM
18584+config AUFS_POLL
18585+ bool
18586+ help
18587+ Automatic configuration for internal use.
1facf9fc 18588+
4a4d8108
AM
18589+config AUFS_BR_HFSPLUS
18590+ bool "Hfsplus as an aufs branch"
18591+ depends on HFSPLUS_FS
18592+ default y
18593+ help
18594+ If you want to use hfsplus fs as an aufs branch fs, then enable
18595+ this option. This option introduces a small overhead at
18596+ copying-up a file on hfsplus.
1facf9fc 18597+
4a4d8108
AM
18598+config AUFS_BDEV_LOOP
18599+ bool
18600+ depends on BLK_DEV_LOOP
18601+ default y
18602+ help
18603+ Automatic configuration for internal use.
18604+ Convert =[ym] into =y.
1308ab2a 18605+
4a4d8108
AM
18606+config AUFS_DEBUG
18607+ bool "Debug aufs"
18608+ help
18609+ Enable this to compile aufs internal debug code.
18610+ It will have a negative impact to the performance.
18611+
18612+config AUFS_MAGIC_SYSRQ
18613+ bool
18614+ depends on AUFS_DEBUG && MAGIC_SYSRQ
18615+ default y
18616+ help
18617+ Automatic configuration for internal use.
18618+ When aufs supports Magic SysRq, enabled automatically.
18619+endif
7f207e10
AM
18620diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
18621--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 18622+++ linux/fs/aufs/loop.c 2012-08-26 08:39:00.760508065 +0200
87a755f4 18623@@ -0,0 +1,133 @@
1facf9fc 18624+/*
f6c5ef8b 18625+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18626+ *
18627+ * This program, aufs is free software; you can redistribute it and/or modify
18628+ * it under the terms of the GNU General Public License as published by
18629+ * the Free Software Foundation; either version 2 of the License, or
18630+ * (at your option) any later version.
dece6358
AM
18631+ *
18632+ * This program is distributed in the hope that it will be useful,
18633+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18634+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18635+ * GNU General Public License for more details.
18636+ *
18637+ * You should have received a copy of the GNU General Public License
18638+ * along with this program; if not, write to the Free Software
18639+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18640+ */
18641+
18642+/*
18643+ * support for loopback block device as a branch
18644+ */
18645+
18646+#include <linux/loop.h>
18647+#include "aufs.h"
18648+
18649+/*
18650+ * test if two lower dentries have overlapping branches.
18651+ */
b752ccd1 18652+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 18653+{
b752ccd1 18654+ struct super_block *h_sb;
1facf9fc 18655+ struct loop_device *l;
18656+
b752ccd1
AM
18657+ h_sb = h_adding->d_sb;
18658+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 18659+ return 0;
18660+
b752ccd1
AM
18661+ l = h_sb->s_bdev->bd_disk->private_data;
18662+ h_adding = l->lo_backing_file->f_dentry;
18663+ /*
18664+ * h_adding can be local NFS.
18665+ * in this case aufs cannot detect the loop.
18666+ */
18667+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 18668+ return 1;
b752ccd1 18669+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 18670+}
18671+
18672+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
18673+int au_test_loopback_kthread(void)
18674+{
b752ccd1
AM
18675+ int ret;
18676+ struct task_struct *tsk = current;
18677+
18678+ ret = 0;
18679+ if (tsk->flags & PF_KTHREAD) {
18680+ const char c = tsk->comm[4];
18681+ ret = ('0' <= c && c <= '9'
18682+ && !strncmp(tsk->comm, "loop", 4));
18683+ }
1facf9fc 18684+
b752ccd1 18685+ return ret;
1facf9fc 18686+}
87a755f4
AM
18687+
18688+/* ---------------------------------------------------------------------- */
18689+
18690+#define au_warn_loopback_step 16
18691+static int au_warn_loopback_nelem = au_warn_loopback_step;
18692+static unsigned long *au_warn_loopback_array;
18693+
18694+void au_warn_loopback(struct super_block *h_sb)
18695+{
18696+ int i, new_nelem;
18697+ unsigned long *a, magic;
18698+ static DEFINE_SPINLOCK(spin);
18699+
18700+ magic = h_sb->s_magic;
18701+ spin_lock(&spin);
18702+ a = au_warn_loopback_array;
18703+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
18704+ if (a[i] == magic) {
18705+ spin_unlock(&spin);
18706+ return;
18707+ }
18708+
18709+ /* h_sb is new to us, print it */
18710+ if (i < au_warn_loopback_nelem) {
18711+ a[i] = magic;
18712+ goto pr;
18713+ }
18714+
18715+ /* expand the array */
18716+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
18717+ a = au_kzrealloc(au_warn_loopback_array,
18718+ au_warn_loopback_nelem * sizeof(unsigned long),
18719+ new_nelem * sizeof(unsigned long), GFP_ATOMIC);
18720+ if (a) {
18721+ au_warn_loopback_nelem = new_nelem;
18722+ au_warn_loopback_array = a;
18723+ a[i] = magic;
18724+ goto pr;
18725+ }
18726+
18727+ spin_unlock(&spin);
18728+ AuWarn1("realloc failed, ignored\n");
18729+ return;
18730+
18731+pr:
18732+ spin_unlock(&spin);
0c3ec466
AM
18733+ pr_warn("you may want to try another patch for loopback file "
18734+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
87a755f4
AM
18735+}
18736+
18737+int au_loopback_init(void)
18738+{
18739+ int err;
18740+ struct super_block *sb __maybe_unused;
18741+
18742+ AuDebugOn(sizeof(sb->s_magic) != sizeof(unsigned long));
18743+
18744+ err = 0;
18745+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
18746+ sizeof(unsigned long), GFP_NOFS);
18747+ if (unlikely(!au_warn_loopback_array))
18748+ err = -ENOMEM;
18749+
18750+ return err;
18751+}
18752+
18753+void au_loopback_fin(void)
18754+{
18755+ kfree(au_warn_loopback_array);
18756+}
7f207e10
AM
18757diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
18758--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 18759+++ linux/fs/aufs/loop.h 2012-08-26 08:39:00.760508065 +0200
87a755f4 18760@@ -0,0 +1,50 @@
1facf9fc 18761+/*
f6c5ef8b 18762+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18763+ *
18764+ * This program, aufs is free software; you can redistribute it and/or modify
18765+ * it under the terms of the GNU General Public License as published by
18766+ * the Free Software Foundation; either version 2 of the License, or
18767+ * (at your option) any later version.
dece6358
AM
18768+ *
18769+ * This program is distributed in the hope that it will be useful,
18770+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18771+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18772+ * GNU General Public License for more details.
18773+ *
18774+ * You should have received a copy of the GNU General Public License
18775+ * along with this program; if not, write to the Free Software
18776+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18777+ */
18778+
18779+/*
18780+ * support for loopback mount as a branch
18781+ */
18782+
18783+#ifndef __AUFS_LOOP_H__
18784+#define __AUFS_LOOP_H__
18785+
18786+#ifdef __KERNEL__
18787+
dece6358
AM
18788+struct dentry;
18789+struct super_block;
1facf9fc 18790+
18791+#ifdef CONFIG_AUFS_BDEV_LOOP
18792+/* loop.c */
b752ccd1 18793+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 18794+int au_test_loopback_kthread(void);
87a755f4
AM
18795+void au_warn_loopback(struct super_block *h_sb);
18796+
18797+int au_loopback_init(void);
18798+void au_loopback_fin(void);
1facf9fc 18799+#else
4a4d8108 18800+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 18801+ struct dentry *h_adding)
4a4d8108 18802+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
18803+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
18804+
18805+AuStubInt0(au_loopback_init, void)
18806+AuStubVoid(au_loopback_fin, void)
1facf9fc 18807+#endif /* BLK_DEV_LOOP */
18808+
18809+#endif /* __KERNEL__ */
18810+#endif /* __AUFS_LOOP_H__ */
7f207e10
AM
18811diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
18812--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
2dfbb274 18813+++ linux/fs/aufs/magic.mk 2012-08-26 08:39:00.760508065 +0200
4a4d8108 18814@@ -0,0 +1,54 @@
1facf9fc 18815+
18816+# defined in ${srctree}/fs/fuse/inode.c
18817+# tristate
18818+ifdef CONFIG_FUSE_FS
18819+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
18820+endif
18821+
18822+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
18823+# tristate
18824+ifdef CONFIG_OCFS2_FS
18825+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
18826+endif
18827+
18828+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
18829+# tristate
18830+ifdef CONFIG_OCFS2_FS_O2CB
18831+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
18832+endif
18833+
1facf9fc 18834+# defined in ${srctree}/fs/cifs/cifsfs.c
18835+# tristate
18836+ifdef CONFIG_CIFS_FS
18837+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
18838+endif
18839+
18840+# defined in ${srctree}/fs/xfs/xfs_sb.h
18841+# tristate
18842+ifdef CONFIG_XFS_FS
18843+ccflags-y += -DXFS_SB_MAGIC=0x58465342
18844+endif
18845+
18846+# defined in ${srctree}/fs/configfs/mount.c
18847+# tristate
18848+ifdef CONFIG_CONFIGFS_FS
18849+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
18850+endif
18851+
18852+# defined in ${srctree}/fs/9p/v9fs.h
18853+# tristate
18854+ifdef CONFIG_9P_FS
18855+ccflags-y += -DV9FS_MAGIC=0x01021997
18856+endif
18857+
18858+# defined in ${srctree}/fs/ubifs/ubifs.h
18859+# tristate
18860+ifdef CONFIG_UBIFS_FS
18861+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
18862+endif
4a4d8108
AM
18863+
18864+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
18865+# tristate
18866+ifdef CONFIG_HFSPLUS_FS
18867+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
18868+endif
7f207e10
AM
18869diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
18870--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
2dfbb274
AM
18871+++ linux/fs/aufs/Makefile 2012-08-26 08:39:00.757174634 +0200
18872@@ -0,0 +1,42 @@
4a4d8108
AM
18873+
18874+include ${src}/magic.mk
18875+ifeq (${CONFIG_AUFS_FS},m)
18876+include ${src}/conf.mk
18877+endif
18878+-include ${src}/priv_def.mk
18879+
18880+# cf. include/linux/kernel.h
18881+# enable pr_debug
18882+ccflags-y += -DDEBUG
f6c5ef8b
AM
18883+# sparse requires the full pathname
18884+ifdef M
18885+ccflags-y += -include ${M}/../../include/linux/aufs_type.h
18886+else
18887+ccflags-y += -include ${srctree}/include/linux/aufs_type.h
18888+endif
4a4d8108
AM
18889+
18890+obj-$(CONFIG_AUFS_FS) += aufs.o
18891+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
18892+ wkq.o vfsub.o dcsub.o \
e49829fe 18893+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
18894+ dinfo.o dentry.o \
18895+ dynop.o \
18896+ finfo.o file.o f_op.o \
18897+ dir.o vdir.o \
18898+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
18899+ ioctl.o
18900+
18901+# all are boolean
e49829fe 18902+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
18903+aufs-$(CONFIG_SYSFS) += sysfs.o
18904+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
18905+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
18906+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
18907+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108
AM
18908+aufs-$(CONFIG_AUFS_EXPORT) += export.o
18909+aufs-$(CONFIG_AUFS_POLL) += poll.o
18910+aufs-$(CONFIG_AUFS_RDU) += rdu.o
18911+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
18912+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
18913+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
18914+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10
AM
18915diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
18916--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 18917+++ linux/fs/aufs/module.c 2012-08-26 08:39:00.760508065 +0200
7eafdf33 18918@@ -0,0 +1,196 @@
1facf9fc 18919+/*
f6c5ef8b 18920+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18921+ *
18922+ * This program, aufs is free software; you can redistribute it and/or modify
18923+ * it under the terms of the GNU General Public License as published by
18924+ * the Free Software Foundation; either version 2 of the License, or
18925+ * (at your option) any later version.
dece6358
AM
18926+ *
18927+ * This program is distributed in the hope that it will be useful,
18928+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18929+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18930+ * GNU General Public License for more details.
18931+ *
18932+ * You should have received a copy of the GNU General Public License
18933+ * along with this program; if not, write to the Free Software
18934+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18935+ */
18936+
18937+/*
18938+ * module global variables and operations
18939+ */
18940+
18941+#include <linux/module.h>
18942+#include <linux/seq_file.h>
18943+#include "aufs.h"
18944+
18945+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
18946+{
18947+ if (new_sz <= nused)
18948+ return p;
18949+
18950+ p = krealloc(p, new_sz, gfp);
18951+ if (p)
18952+ memset(p + nused, 0, new_sz - nused);
18953+ return p;
18954+}
18955+
18956+/* ---------------------------------------------------------------------- */
18957+
18958+/*
18959+ * aufs caches
18960+ */
18961+struct kmem_cache *au_cachep[AuCache_Last];
18962+static int __init au_cache_init(void)
18963+{
4a4d8108 18964+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 18965+ if (au_cachep[AuCache_DINFO])
027c5e7a 18966+ /* SLAB_DESTROY_BY_RCU */
4a4d8108
AM
18967+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
18968+ au_icntnr_init_once);
1facf9fc 18969+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
18970+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
18971+ au_fi_init_once);
1facf9fc 18972+ if (au_cachep[AuCache_FINFO])
18973+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
18974+ if (au_cachep[AuCache_VDIR])
18975+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
18976+ if (au_cachep[AuCache_DEHSTR])
18977+ return 0;
18978+
18979+ return -ENOMEM;
18980+}
18981+
18982+static void au_cache_fin(void)
18983+{
18984+ int i;
4a4d8108 18985+
7eafdf33
AM
18986+ /* excluding AuCache_HNOTIFY */
18987+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
18988+ for (i = 0; i < AuCache_HNOTIFY; i++)
1facf9fc 18989+ if (au_cachep[i]) {
18990+ kmem_cache_destroy(au_cachep[i]);
18991+ au_cachep[i] = NULL;
18992+ }
18993+}
18994+
18995+/* ---------------------------------------------------------------------- */
18996+
18997+int au_dir_roflags;
18998+
e49829fe 18999+#ifdef CONFIG_AUFS_SBILIST
1e00d052
AM
19000+/*
19001+ * iterate_supers_type() doesn't protect us from
19002+ * remounting (branch management)
19003+ */
e49829fe
JR
19004+struct au_splhead au_sbilist;
19005+#endif
19006+
9dbd164d
AM
19007+struct lock_class_key au_lc_key[AuLcKey_Last];
19008+
1facf9fc 19009+/*
19010+ * functions for module interface.
19011+ */
19012+MODULE_LICENSE("GPL");
19013+/* MODULE_LICENSE("GPL v2"); */
dece6358 19014+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 19015+MODULE_DESCRIPTION(AUFS_NAME
19016+ " -- Advanced multi layered unification filesystem");
19017+MODULE_VERSION(AUFS_VERSION);
19018+
1facf9fc 19019+/* this module parameter has no meaning when SYSFS is disabled */
19020+int sysaufs_brs = 1;
19021+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
19022+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
19023+
19024+/* ---------------------------------------------------------------------- */
19025+
19026+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
19027+
19028+int au_seq_path(struct seq_file *seq, struct path *path)
19029+{
19030+ return seq_path(seq, path, au_esc_chars);
19031+}
19032+
19033+/* ---------------------------------------------------------------------- */
19034+
19035+static int __init aufs_init(void)
19036+{
19037+ int err, i;
19038+ char *p;
19039+
19040+ p = au_esc_chars;
19041+ for (i = 1; i <= ' '; i++)
19042+ *p++ = i;
19043+ *p++ = '\\';
19044+ *p++ = '\x7f';
19045+ *p = 0;
19046+
19047+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
19048+
e49829fe 19049+ au_sbilist_init();
1facf9fc 19050+ sysaufs_brs_init();
19051+ au_debug_init();
4a4d8108 19052+ au_dy_init();
1facf9fc 19053+ err = sysaufs_init();
19054+ if (unlikely(err))
19055+ goto out;
e49829fe 19056+ err = au_procfs_init();
4f0767ce 19057+ if (unlikely(err))
953406b4 19058+ goto out_sysaufs;
e49829fe
JR
19059+ err = au_wkq_init();
19060+ if (unlikely(err))
19061+ goto out_procfs;
87a755f4 19062+ err = au_loopback_init();
1facf9fc 19063+ if (unlikely(err))
19064+ goto out_wkq;
87a755f4
AM
19065+ err = au_hnotify_init();
19066+ if (unlikely(err))
19067+ goto out_loopback;
1facf9fc 19068+ err = au_sysrq_init();
19069+ if (unlikely(err))
19070+ goto out_hin;
19071+ err = au_cache_init();
19072+ if (unlikely(err))
19073+ goto out_sysrq;
19074+ err = register_filesystem(&aufs_fs_type);
19075+ if (unlikely(err))
19076+ goto out_cache;
4a4d8108
AM
19077+ /* since we define pr_fmt, call printk directly */
19078+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 19079+ goto out; /* success */
19080+
4f0767ce 19081+out_cache:
1facf9fc 19082+ au_cache_fin();
4f0767ce 19083+out_sysrq:
1facf9fc 19084+ au_sysrq_fin();
4f0767ce 19085+out_hin:
4a4d8108 19086+ au_hnotify_fin();
87a755f4
AM
19087+out_loopback:
19088+ au_loopback_fin();
4f0767ce 19089+out_wkq:
1facf9fc 19090+ au_wkq_fin();
e49829fe
JR
19091+out_procfs:
19092+ au_procfs_fin();
4f0767ce 19093+out_sysaufs:
1facf9fc 19094+ sysaufs_fin();
4a4d8108 19095+ au_dy_fin();
4f0767ce 19096+out:
1facf9fc 19097+ return err;
19098+}
19099+
19100+static void __exit aufs_exit(void)
19101+{
19102+ unregister_filesystem(&aufs_fs_type);
19103+ au_cache_fin();
19104+ au_sysrq_fin();
4a4d8108 19105+ au_hnotify_fin();
87a755f4 19106+ au_loopback_fin();
1facf9fc 19107+ au_wkq_fin();
e49829fe 19108+ au_procfs_fin();
1facf9fc 19109+ sysaufs_fin();
4a4d8108 19110+ au_dy_fin();
1facf9fc 19111+}
19112+
19113+module_init(aufs_init);
19114+module_exit(aufs_exit);
7f207e10
AM
19115diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
19116--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 19117+++ linux/fs/aufs/module.h 2012-08-26 08:39:00.760508065 +0200
7eafdf33 19118@@ -0,0 +1,105 @@
1facf9fc 19119+/*
f6c5ef8b 19120+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 19121+ *
19122+ * This program, aufs is free software; you can redistribute it and/or modify
19123+ * it under the terms of the GNU General Public License as published by
19124+ * the Free Software Foundation; either version 2 of the License, or
19125+ * (at your option) any later version.
dece6358
AM
19126+ *
19127+ * This program is distributed in the hope that it will be useful,
19128+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19129+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19130+ * GNU General Public License for more details.
19131+ *
19132+ * You should have received a copy of the GNU General Public License
19133+ * along with this program; if not, write to the Free Software
19134+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19135+ */
19136+
19137+/*
19138+ * module initialization and module-global
19139+ */
19140+
19141+#ifndef __AUFS_MODULE_H__
19142+#define __AUFS_MODULE_H__
19143+
19144+#ifdef __KERNEL__
19145+
19146+#include <linux/slab.h>
19147+
dece6358
AM
19148+struct path;
19149+struct seq_file;
19150+
1facf9fc 19151+/* module parameters */
1facf9fc 19152+extern int sysaufs_brs;
19153+
19154+/* ---------------------------------------------------------------------- */
19155+
19156+extern int au_dir_roflags;
19157+
9dbd164d
AM
19158+enum {
19159+ AuLcNonDir_FIINFO,
19160+ AuLcNonDir_DIINFO,
19161+ AuLcNonDir_IIINFO,
19162+
19163+ AuLcDir_FIINFO,
19164+ AuLcDir_DIINFO,
19165+ AuLcDir_IIINFO,
19166+
19167+ AuLcSymlink_DIINFO,
19168+ AuLcSymlink_IIINFO,
19169+
19170+ AuLcKey_Last
19171+};
19172+extern struct lock_class_key au_lc_key[AuLcKey_Last];
19173+
1facf9fc 19174+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
19175+int au_seq_path(struct seq_file *seq, struct path *path);
19176+
e49829fe
JR
19177+#ifdef CONFIG_PROC_FS
19178+/* procfs.c */
19179+int __init au_procfs_init(void);
19180+void au_procfs_fin(void);
19181+#else
19182+AuStubInt0(au_procfs_init, void);
19183+AuStubVoid(au_procfs_fin, void);
19184+#endif
19185+
4f0767ce
JR
19186+/* ---------------------------------------------------------------------- */
19187+
19188+/* kmem cache */
1facf9fc 19189+enum {
19190+ AuCache_DINFO,
19191+ AuCache_ICNTNR,
19192+ AuCache_FINFO,
19193+ AuCache_VDIR,
19194+ AuCache_DEHSTR,
7eafdf33 19195+ AuCache_HNOTIFY, /* must be last */
1facf9fc 19196+ AuCache_Last
19197+};
19198+
4a4d8108
AM
19199+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
19200+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
19201+#define AuCacheCtor(type, ctor) \
19202+ kmem_cache_create(#type, sizeof(struct type), \
19203+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 19204+
19205+extern struct kmem_cache *au_cachep[];
19206+
19207+#define AuCacheFuncs(name, index) \
4a4d8108 19208+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 19209+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 19210+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 19211+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
19212+
19213+AuCacheFuncs(dinfo, DINFO);
19214+AuCacheFuncs(icntnr, ICNTNR);
19215+AuCacheFuncs(finfo, FINFO);
19216+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
19217+AuCacheFuncs(vdir_dehstr, DEHSTR);
19218+#ifdef CONFIG_AUFS_HNOTIFY
19219+AuCacheFuncs(hnotify, HNOTIFY);
19220+#endif
1facf9fc 19221+
4a4d8108
AM
19222+#endif /* __KERNEL__ */
19223+#endif /* __AUFS_MODULE_H__ */
7f207e10
AM
19224diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
19225--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 19226+++ linux/fs/aufs/opts.c 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 19227@@ -0,0 +1,1677 @@
1facf9fc 19228+/*
f6c5ef8b 19229+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 19230+ *
19231+ * This program, aufs is free software; you can redistribute it and/or modify
19232+ * it under the terms of the GNU General Public License as published by
19233+ * the Free Software Foundation; either version 2 of the License, or
19234+ * (at your option) any later version.
dece6358
AM
19235+ *
19236+ * This program is distributed in the hope that it will be useful,
19237+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19238+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19239+ * GNU General Public License for more details.
19240+ *
19241+ * You should have received a copy of the GNU General Public License
19242+ * along with this program; if not, write to the Free Software
19243+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19244+ */
19245+
19246+/*
19247+ * mount options/flags
19248+ */
19249+
dece6358 19250+#include <linux/namei.h>
1facf9fc 19251+#include <linux/types.h> /* a distribution requires */
19252+#include <linux/parser.h>
19253+#include "aufs.h"
19254+
19255+/* ---------------------------------------------------------------------- */
19256+
19257+enum {
19258+ Opt_br,
19259+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
19260+ Opt_idel, Opt_imod, Opt_ireorder,
19261+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 19262+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 19263+ Opt_xino, Opt_zxino, Opt_noxino,
19264+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
19265+ Opt_trunc_xino_path, Opt_itrunc_xino,
19266+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 19267+ Opt_shwh, Opt_noshwh,
1facf9fc 19268+ Opt_plink, Opt_noplink, Opt_list_plink,
19269+ Opt_udba,
4a4d8108 19270+ Opt_dio, Opt_nodio,
1facf9fc 19271+ /* Opt_lock, Opt_unlock, */
19272+ Opt_cmd, Opt_cmd_args,
19273+ Opt_diropq_a, Opt_diropq_w,
19274+ Opt_warn_perm, Opt_nowarn_perm,
19275+ Opt_wbr_copyup, Opt_wbr_create,
19276+ Opt_refrof, Opt_norefrof,
19277+ Opt_verbose, Opt_noverbose,
19278+ Opt_sum, Opt_nosum, Opt_wsum,
19279+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
19280+};
19281+
19282+static match_table_t options = {
19283+ {Opt_br, "br=%s"},
19284+ {Opt_br, "br:%s"},
19285+
19286+ {Opt_add, "add=%d:%s"},
19287+ {Opt_add, "add:%d:%s"},
19288+ {Opt_add, "ins=%d:%s"},
19289+ {Opt_add, "ins:%d:%s"},
19290+ {Opt_append, "append=%s"},
19291+ {Opt_append, "append:%s"},
19292+ {Opt_prepend, "prepend=%s"},
19293+ {Opt_prepend, "prepend:%s"},
19294+
19295+ {Opt_del, "del=%s"},
19296+ {Opt_del, "del:%s"},
19297+ /* {Opt_idel, "idel:%d"}, */
19298+ {Opt_mod, "mod=%s"},
19299+ {Opt_mod, "mod:%s"},
19300+ /* {Opt_imod, "imod:%d:%s"}, */
19301+
19302+ {Opt_dirwh, "dirwh=%d"},
19303+
19304+ {Opt_xino, "xino=%s"},
19305+ {Opt_noxino, "noxino"},
19306+ {Opt_trunc_xino, "trunc_xino"},
19307+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
19308+ {Opt_notrunc_xino, "notrunc_xino"},
19309+ {Opt_trunc_xino_path, "trunc_xino=%s"},
19310+ {Opt_itrunc_xino, "itrunc_xino=%d"},
19311+ /* {Opt_zxino, "zxino=%s"}, */
19312+ {Opt_trunc_xib, "trunc_xib"},
19313+ {Opt_notrunc_xib, "notrunc_xib"},
19314+
e49829fe 19315+#ifdef CONFIG_PROC_FS
1facf9fc 19316+ {Opt_plink, "plink"},
e49829fe
JR
19317+#else
19318+ {Opt_ignore_silent, "plink"},
19319+#endif
19320+
1facf9fc 19321+ {Opt_noplink, "noplink"},
e49829fe 19322+
1facf9fc 19323+#ifdef CONFIG_AUFS_DEBUG
19324+ {Opt_list_plink, "list_plink"},
19325+#endif
19326+
19327+ {Opt_udba, "udba=%s"},
19328+
4a4d8108
AM
19329+ {Opt_dio, "dio"},
19330+ {Opt_nodio, "nodio"},
19331+
1facf9fc 19332+ {Opt_diropq_a, "diropq=always"},
19333+ {Opt_diropq_a, "diropq=a"},
19334+ {Opt_diropq_w, "diropq=whiteouted"},
19335+ {Opt_diropq_w, "diropq=w"},
19336+
19337+ {Opt_warn_perm, "warn_perm"},
19338+ {Opt_nowarn_perm, "nowarn_perm"},
19339+
19340+ /* keep them temporary */
19341+ {Opt_ignore_silent, "coo=%s"},
19342+ {Opt_ignore_silent, "nodlgt"},
19343+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 19344+ {Opt_ignore_silent, "clean_plink"},
19345+
dece6358
AM
19346+#ifdef CONFIG_AUFS_SHWH
19347+ {Opt_shwh, "shwh"},
19348+#endif
19349+ {Opt_noshwh, "noshwh"},
19350+
1facf9fc 19351+ {Opt_rendir, "rendir=%d"},
19352+
19353+ {Opt_refrof, "refrof"},
19354+ {Opt_norefrof, "norefrof"},
19355+
19356+ {Opt_verbose, "verbose"},
19357+ {Opt_verbose, "v"},
19358+ {Opt_noverbose, "noverbose"},
19359+ {Opt_noverbose, "quiet"},
19360+ {Opt_noverbose, "q"},
19361+ {Opt_noverbose, "silent"},
19362+
19363+ {Opt_sum, "sum"},
19364+ {Opt_nosum, "nosum"},
19365+ {Opt_wsum, "wsum"},
19366+
19367+ {Opt_rdcache, "rdcache=%d"},
19368+ {Opt_rdblk, "rdblk=%d"},
dece6358 19369+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 19370+ {Opt_rdhash, "rdhash=%d"},
dece6358 19371+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 19372+
19373+ {Opt_wbr_create, "create=%s"},
19374+ {Opt_wbr_create, "create_policy=%s"},
19375+ {Opt_wbr_copyup, "cpup=%s"},
19376+ {Opt_wbr_copyup, "copyup=%s"},
19377+ {Opt_wbr_copyup, "copyup_policy=%s"},
19378+
19379+ /* internal use for the scripts */
19380+ {Opt_ignore_silent, "si=%s"},
19381+
19382+ {Opt_br, "dirs=%s"},
19383+ {Opt_ignore, "debug=%d"},
19384+ {Opt_ignore, "delete=whiteout"},
19385+ {Opt_ignore, "delete=all"},
19386+ {Opt_ignore, "imap=%s"},
19387+
1308ab2a 19388+ /* temporary workaround, due to old mount(8)? */
19389+ {Opt_ignore_silent, "relatime"},
19390+
1facf9fc 19391+ {Opt_err, NULL}
19392+};
19393+
19394+/* ---------------------------------------------------------------------- */
19395+
19396+static const char *au_parser_pattern(int val, struct match_token *token)
19397+{
19398+ while (token->pattern) {
19399+ if (token->token == val)
19400+ return token->pattern;
19401+ token++;
19402+ }
19403+ BUG();
19404+ return "??";
19405+}
19406+
19407+/* ---------------------------------------------------------------------- */
19408+
1e00d052 19409+static match_table_t brperm = {
1facf9fc 19410+ {AuBrPerm_RO, AUFS_BRPERM_RO},
19411+ {AuBrPerm_RR, AUFS_BRPERM_RR},
19412+ {AuBrPerm_RW, AUFS_BRPERM_RW},
1e00d052
AM
19413+ {0, NULL}
19414+};
1facf9fc 19415+
1e00d052
AM
19416+static match_table_t brrattr = {
19417+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
19418+ {0, NULL}
19419+};
1facf9fc 19420+
1e00d052
AM
19421+static match_table_t brwattr = {
19422+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
19423+ {0, NULL}
1facf9fc 19424+};
19425+
1e00d052
AM
19426+#define AuBrStr_LONGEST AUFS_BRPERM_RW "+" AUFS_BRWATTR_NLWH
19427+
19428+static int br_attr_val(char *str, match_table_t table, substring_t args[])
19429+{
19430+ int attr, v;
19431+ char *p;
19432+
19433+ attr = 0;
19434+ do {
19435+ p = strchr(str, '+');
19436+ if (p)
19437+ *p = 0;
19438+ v = match_token(str, table, args);
19439+ if (v)
19440+ attr |= v;
19441+ else {
19442+ if (p)
19443+ *p = '+';
0c3ec466 19444+ pr_warn("ignored branch attribute %s\n", str);
1e00d052
AM
19445+ break;
19446+ }
19447+ if (p)
19448+ str = p + 1;
19449+ } while (p);
19450+
19451+ return attr;
19452+}
19453+
4a4d8108 19454+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 19455+{
19456+ int val;
1e00d052 19457+ char *p;
1facf9fc 19458+ substring_t args[MAX_OPT_ARGS];
19459+
1e00d052
AM
19460+ p = strchr(perm, '+');
19461+ if (p)
19462+ *p = 0;
19463+ val = match_token(perm, brperm, args);
19464+ if (!val) {
19465+ if (p)
19466+ *p = '+';
0c3ec466 19467+ pr_warn("ignored branch permission %s\n", perm);
1e00d052
AM
19468+ val = AuBrPerm_RO;
19469+ goto out;
19470+ }
19471+ if (!p)
19472+ goto out;
19473+
19474+ switch (val) {
19475+ case AuBrPerm_RO:
19476+ case AuBrPerm_RR:
19477+ val |= br_attr_val(p + 1, brrattr, args);
19478+ break;
19479+ case AuBrPerm_RW:
19480+ val |= br_attr_val(p + 1, brwattr, args);
19481+ break;
19482+ }
19483+
19484+out:
1facf9fc 19485+ return val;
19486+}
19487+
1e00d052
AM
19488+/* Caller should free the return value */
19489+char *au_optstr_br_perm(int brperm)
1facf9fc 19490+{
1e00d052
AM
19491+ char *p, a[sizeof(AuBrStr_LONGEST)];
19492+ int sz;
19493+
19494+#define SetPerm(str) do { \
19495+ sz = sizeof(str); \
19496+ memcpy(a, str, sz); \
19497+ p = a + sz - 1; \
19498+ } while (0)
19499+
19500+#define AppendAttr(flag, str) do { \
19501+ if (brperm & flag) { \
19502+ sz = sizeof(str); \
19503+ *p++ = '+'; \
19504+ memcpy(p, str, sz); \
19505+ p += sz - 1; \
19506+ } \
19507+ } while (0)
19508+
19509+ switch (brperm & AuBrPerm_Mask) {
19510+ case AuBrPerm_RO:
19511+ SetPerm(AUFS_BRPERM_RO);
19512+ break;
19513+ case AuBrPerm_RR:
19514+ SetPerm(AUFS_BRPERM_RR);
19515+ break;
19516+ case AuBrPerm_RW:
19517+ SetPerm(AUFS_BRPERM_RW);
19518+ break;
19519+ default:
19520+ AuDebugOn(1);
19521+ }
19522+
19523+ AppendAttr(AuBrRAttr_WH, AUFS_BRRATTR_WH);
19524+ AppendAttr(AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH);
19525+
19526+ AuDebugOn(strlen(a) >= sizeof(a));
19527+ return kstrdup(a, GFP_NOFS);
19528+#undef SetPerm
19529+#undef AppendAttr
1facf9fc 19530+}
19531+
19532+/* ---------------------------------------------------------------------- */
19533+
19534+static match_table_t udbalevel = {
19535+ {AuOpt_UDBA_REVAL, "reval"},
19536+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
19537+#ifdef CONFIG_AUFS_HNOTIFY
19538+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
19539+#ifdef CONFIG_AUFS_HFSNOTIFY
19540+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 19541+#endif
1facf9fc 19542+#endif
19543+ {-1, NULL}
19544+};
19545+
4a4d8108 19546+static int noinline_for_stack udba_val(char *str)
1facf9fc 19547+{
19548+ substring_t args[MAX_OPT_ARGS];
19549+
7f207e10 19550+ return match_token(str, udbalevel, args);
1facf9fc 19551+}
19552+
19553+const char *au_optstr_udba(int udba)
19554+{
19555+ return au_parser_pattern(udba, (void *)udbalevel);
19556+}
19557+
19558+/* ---------------------------------------------------------------------- */
19559+
19560+static match_table_t au_wbr_create_policy = {
19561+ {AuWbrCreate_TDP, "tdp"},
19562+ {AuWbrCreate_TDP, "top-down-parent"},
19563+ {AuWbrCreate_RR, "rr"},
19564+ {AuWbrCreate_RR, "round-robin"},
19565+ {AuWbrCreate_MFS, "mfs"},
19566+ {AuWbrCreate_MFS, "most-free-space"},
19567+ {AuWbrCreate_MFSV, "mfs:%d"},
19568+ {AuWbrCreate_MFSV, "most-free-space:%d"},
19569+
19570+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
19571+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
19572+ {AuWbrCreate_PMFS, "pmfs"},
19573+ {AuWbrCreate_PMFSV, "pmfs:%d"},
19574+
19575+ {-1, NULL}
19576+};
19577+
dece6358
AM
19578+/*
19579+ * cf. linux/lib/parser.c and cmdline.c
19580+ * gave up calling memparse() since it uses simple_strtoull() instead of
9dbd164d 19581+ * kstrto...().
dece6358 19582+ */
4a4d8108
AM
19583+static int noinline_for_stack
19584+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 19585+{
19586+ int err;
19587+ unsigned int len;
19588+ char a[32];
19589+
19590+ err = -ERANGE;
19591+ len = s->to - s->from;
19592+ if (len + 1 <= sizeof(a)) {
19593+ memcpy(a, s->from, len);
19594+ a[len] = '\0';
9dbd164d 19595+ err = kstrtoull(a, 0, result);
1facf9fc 19596+ }
19597+ return err;
19598+}
19599+
19600+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
19601+ struct au_opt_wbr_create *create)
19602+{
19603+ int err;
19604+ unsigned long long ull;
19605+
19606+ err = 0;
19607+ if (!au_match_ull(arg, &ull))
19608+ create->mfsrr_watermark = ull;
19609+ else {
4a4d8108 19610+ pr_err("bad integer in %s\n", str);
1facf9fc 19611+ err = -EINVAL;
19612+ }
19613+
19614+ return err;
19615+}
19616+
19617+static int au_wbr_mfs_sec(substring_t *arg, char *str,
19618+ struct au_opt_wbr_create *create)
19619+{
19620+ int n, err;
19621+
19622+ err = 0;
027c5e7a 19623+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 19624+ create->mfs_second = n;
19625+ else {
4a4d8108 19626+ pr_err("bad integer in %s\n", str);
1facf9fc 19627+ err = -EINVAL;
19628+ }
19629+
19630+ return err;
19631+}
19632+
4a4d8108
AM
19633+static int noinline_for_stack
19634+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 19635+{
19636+ int err, e;
19637+ substring_t args[MAX_OPT_ARGS];
19638+
19639+ err = match_token(str, au_wbr_create_policy, args);
19640+ create->wbr_create = err;
19641+ switch (err) {
19642+ case AuWbrCreate_MFSRRV:
19643+ e = au_wbr_mfs_wmark(&args[0], str, create);
19644+ if (!e)
19645+ e = au_wbr_mfs_sec(&args[1], str, create);
19646+ if (unlikely(e))
19647+ err = e;
19648+ break;
19649+ case AuWbrCreate_MFSRR:
19650+ e = au_wbr_mfs_wmark(&args[0], str, create);
19651+ if (unlikely(e)) {
19652+ err = e;
19653+ break;
19654+ }
19655+ /*FALLTHROUGH*/
19656+ case AuWbrCreate_MFS:
19657+ case AuWbrCreate_PMFS:
027c5e7a 19658+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 19659+ break;
19660+ case AuWbrCreate_MFSV:
19661+ case AuWbrCreate_PMFSV:
19662+ e = au_wbr_mfs_sec(&args[0], str, create);
19663+ if (unlikely(e))
19664+ err = e;
19665+ break;
19666+ }
19667+
19668+ return err;
19669+}
19670+
19671+const char *au_optstr_wbr_create(int wbr_create)
19672+{
19673+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
19674+}
19675+
19676+static match_table_t au_wbr_copyup_policy = {
19677+ {AuWbrCopyup_TDP, "tdp"},
19678+ {AuWbrCopyup_TDP, "top-down-parent"},
19679+ {AuWbrCopyup_BUP, "bup"},
19680+ {AuWbrCopyup_BUP, "bottom-up-parent"},
19681+ {AuWbrCopyup_BU, "bu"},
19682+ {AuWbrCopyup_BU, "bottom-up"},
19683+ {-1, NULL}
19684+};
19685+
4a4d8108 19686+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 19687+{
19688+ substring_t args[MAX_OPT_ARGS];
19689+
19690+ return match_token(str, au_wbr_copyup_policy, args);
19691+}
19692+
19693+const char *au_optstr_wbr_copyup(int wbr_copyup)
19694+{
19695+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
19696+}
19697+
19698+/* ---------------------------------------------------------------------- */
19699+
19700+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
19701+
19702+static void dump_opts(struct au_opts *opts)
19703+{
19704+#ifdef CONFIG_AUFS_DEBUG
19705+ /* reduce stack space */
19706+ union {
19707+ struct au_opt_add *add;
19708+ struct au_opt_del *del;
19709+ struct au_opt_mod *mod;
19710+ struct au_opt_xino *xino;
19711+ struct au_opt_xino_itrunc *xino_itrunc;
19712+ struct au_opt_wbr_create *create;
19713+ } u;
19714+ struct au_opt *opt;
19715+
19716+ opt = opts->opt;
19717+ while (opt->type != Opt_tail) {
19718+ switch (opt->type) {
19719+ case Opt_add:
19720+ u.add = &opt->add;
19721+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
19722+ u.add->bindex, u.add->pathname, u.add->perm,
19723+ u.add->path.dentry);
19724+ break;
19725+ case Opt_del:
19726+ case Opt_idel:
19727+ u.del = &opt->del;
19728+ AuDbg("del {%s, %p}\n",
19729+ u.del->pathname, u.del->h_path.dentry);
19730+ break;
19731+ case Opt_mod:
19732+ case Opt_imod:
19733+ u.mod = &opt->mod;
19734+ AuDbg("mod {%s, 0x%x, %p}\n",
19735+ u.mod->path, u.mod->perm, u.mod->h_root);
19736+ break;
19737+ case Opt_append:
19738+ u.add = &opt->add;
19739+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
19740+ u.add->bindex, u.add->pathname, u.add->perm,
19741+ u.add->path.dentry);
19742+ break;
19743+ case Opt_prepend:
19744+ u.add = &opt->add;
19745+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
19746+ u.add->bindex, u.add->pathname, u.add->perm,
19747+ u.add->path.dentry);
19748+ break;
19749+ case Opt_dirwh:
19750+ AuDbg("dirwh %d\n", opt->dirwh);
19751+ break;
19752+ case Opt_rdcache:
19753+ AuDbg("rdcache %d\n", opt->rdcache);
19754+ break;
19755+ case Opt_rdblk:
19756+ AuDbg("rdblk %u\n", opt->rdblk);
19757+ break;
dece6358
AM
19758+ case Opt_rdblk_def:
19759+ AuDbg("rdblk_def\n");
19760+ break;
1facf9fc 19761+ case Opt_rdhash:
19762+ AuDbg("rdhash %u\n", opt->rdhash);
19763+ break;
dece6358
AM
19764+ case Opt_rdhash_def:
19765+ AuDbg("rdhash_def\n");
19766+ break;
1facf9fc 19767+ case Opt_xino:
19768+ u.xino = &opt->xino;
19769+ AuDbg("xino {%s %.*s}\n",
19770+ u.xino->path,
19771+ AuDLNPair(u.xino->file->f_dentry));
19772+ break;
19773+ case Opt_trunc_xino:
19774+ AuLabel(trunc_xino);
19775+ break;
19776+ case Opt_notrunc_xino:
19777+ AuLabel(notrunc_xino);
19778+ break;
19779+ case Opt_trunc_xino_path:
19780+ case Opt_itrunc_xino:
19781+ u.xino_itrunc = &opt->xino_itrunc;
19782+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
19783+ break;
19784+
19785+ case Opt_noxino:
19786+ AuLabel(noxino);
19787+ break;
19788+ case Opt_trunc_xib:
19789+ AuLabel(trunc_xib);
19790+ break;
19791+ case Opt_notrunc_xib:
19792+ AuLabel(notrunc_xib);
19793+ break;
dece6358
AM
19794+ case Opt_shwh:
19795+ AuLabel(shwh);
19796+ break;
19797+ case Opt_noshwh:
19798+ AuLabel(noshwh);
19799+ break;
1facf9fc 19800+ case Opt_plink:
19801+ AuLabel(plink);
19802+ break;
19803+ case Opt_noplink:
19804+ AuLabel(noplink);
19805+ break;
19806+ case Opt_list_plink:
19807+ AuLabel(list_plink);
19808+ break;
19809+ case Opt_udba:
19810+ AuDbg("udba %d, %s\n",
19811+ opt->udba, au_optstr_udba(opt->udba));
19812+ break;
4a4d8108
AM
19813+ case Opt_dio:
19814+ AuLabel(dio);
19815+ break;
19816+ case Opt_nodio:
19817+ AuLabel(nodio);
19818+ break;
1facf9fc 19819+ case Opt_diropq_a:
19820+ AuLabel(diropq_a);
19821+ break;
19822+ case Opt_diropq_w:
19823+ AuLabel(diropq_w);
19824+ break;
19825+ case Opt_warn_perm:
19826+ AuLabel(warn_perm);
19827+ break;
19828+ case Opt_nowarn_perm:
19829+ AuLabel(nowarn_perm);
19830+ break;
19831+ case Opt_refrof:
19832+ AuLabel(refrof);
19833+ break;
19834+ case Opt_norefrof:
19835+ AuLabel(norefrof);
19836+ break;
19837+ case Opt_verbose:
19838+ AuLabel(verbose);
19839+ break;
19840+ case Opt_noverbose:
19841+ AuLabel(noverbose);
19842+ break;
19843+ case Opt_sum:
19844+ AuLabel(sum);
19845+ break;
19846+ case Opt_nosum:
19847+ AuLabel(nosum);
19848+ break;
19849+ case Opt_wsum:
19850+ AuLabel(wsum);
19851+ break;
19852+ case Opt_wbr_create:
19853+ u.create = &opt->wbr_create;
19854+ AuDbg("create %d, %s\n", u.create->wbr_create,
19855+ au_optstr_wbr_create(u.create->wbr_create));
19856+ switch (u.create->wbr_create) {
19857+ case AuWbrCreate_MFSV:
19858+ case AuWbrCreate_PMFSV:
19859+ AuDbg("%d sec\n", u.create->mfs_second);
19860+ break;
19861+ case AuWbrCreate_MFSRR:
19862+ AuDbg("%llu watermark\n",
19863+ u.create->mfsrr_watermark);
19864+ break;
19865+ case AuWbrCreate_MFSRRV:
19866+ AuDbg("%llu watermark, %d sec\n",
19867+ u.create->mfsrr_watermark,
19868+ u.create->mfs_second);
19869+ break;
19870+ }
19871+ break;
19872+ case Opt_wbr_copyup:
19873+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
19874+ au_optstr_wbr_copyup(opt->wbr_copyup));
19875+ break;
19876+ default:
19877+ BUG();
19878+ }
19879+ opt++;
19880+ }
19881+#endif
19882+}
19883+
19884+void au_opts_free(struct au_opts *opts)
19885+{
19886+ struct au_opt *opt;
19887+
19888+ opt = opts->opt;
19889+ while (opt->type != Opt_tail) {
19890+ switch (opt->type) {
19891+ case Opt_add:
19892+ case Opt_append:
19893+ case Opt_prepend:
19894+ path_put(&opt->add.path);
19895+ break;
19896+ case Opt_del:
19897+ case Opt_idel:
19898+ path_put(&opt->del.h_path);
19899+ break;
19900+ case Opt_mod:
19901+ case Opt_imod:
19902+ dput(opt->mod.h_root);
19903+ break;
19904+ case Opt_xino:
19905+ fput(opt->xino.file);
19906+ break;
19907+ }
19908+ opt++;
19909+ }
19910+}
19911+
19912+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
19913+ aufs_bindex_t bindex)
19914+{
19915+ int err;
19916+ struct au_opt_add *add = &opt->add;
19917+ char *p;
19918+
19919+ add->bindex = bindex;
1e00d052 19920+ add->perm = AuBrPerm_RO;
1facf9fc 19921+ add->pathname = opt_str;
19922+ p = strchr(opt_str, '=');
19923+ if (p) {
19924+ *p++ = 0;
19925+ if (*p)
19926+ add->perm = br_perm_val(p);
19927+ }
19928+
19929+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
19930+ if (!err) {
19931+ if (!p) {
19932+ add->perm = AuBrPerm_RO;
19933+ if (au_test_fs_rr(add->path.dentry->d_sb))
19934+ add->perm = AuBrPerm_RR;
19935+ else if (!bindex && !(sb_flags & MS_RDONLY))
19936+ add->perm = AuBrPerm_RW;
19937+ }
19938+ opt->type = Opt_add;
19939+ goto out;
19940+ }
4a4d8108 19941+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 19942+ err = -EINVAL;
19943+
4f0767ce 19944+out:
1facf9fc 19945+ return err;
19946+}
19947+
19948+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
19949+{
19950+ int err;
19951+
19952+ del->pathname = args[0].from;
19953+ AuDbg("del path %s\n", del->pathname);
19954+
19955+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
19956+ if (unlikely(err))
4a4d8108 19957+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 19958+
19959+ return err;
19960+}
19961+
19962+#if 0 /* reserved for future use */
19963+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
19964+ struct au_opt_del *del, substring_t args[])
19965+{
19966+ int err;
19967+ struct dentry *root;
19968+
19969+ err = -EINVAL;
19970+ root = sb->s_root;
19971+ aufs_read_lock(root, AuLock_FLUSH);
19972+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 19973+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 19974+ goto out;
19975+ }
19976+
19977+ err = 0;
19978+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
19979+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
19980+
4f0767ce 19981+out:
1facf9fc 19982+ aufs_read_unlock(root, !AuLock_IR);
19983+ return err;
19984+}
19985+#endif
19986+
4a4d8108
AM
19987+static int noinline_for_stack
19988+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 19989+{
19990+ int err;
19991+ struct path path;
19992+ char *p;
19993+
19994+ err = -EINVAL;
19995+ mod->path = args[0].from;
19996+ p = strchr(mod->path, '=');
19997+ if (unlikely(!p)) {
4a4d8108 19998+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 19999+ goto out;
20000+ }
20001+
20002+ *p++ = 0;
20003+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
20004+ if (unlikely(err)) {
4a4d8108 20005+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 20006+ goto out;
20007+ }
20008+
20009+ mod->perm = br_perm_val(p);
20010+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
20011+ mod->h_root = dget(path.dentry);
20012+ path_put(&path);
20013+
4f0767ce 20014+out:
1facf9fc 20015+ return err;
20016+}
20017+
20018+#if 0 /* reserved for future use */
20019+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
20020+ struct au_opt_mod *mod, substring_t args[])
20021+{
20022+ int err;
20023+ struct dentry *root;
20024+
20025+ err = -EINVAL;
20026+ root = sb->s_root;
20027+ aufs_read_lock(root, AuLock_FLUSH);
20028+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 20029+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 20030+ goto out;
20031+ }
20032+
20033+ err = 0;
20034+ mod->perm = br_perm_val(args[1].from);
20035+ AuDbg("mod path %s, perm 0x%x, %s\n",
20036+ mod->path, mod->perm, args[1].from);
20037+ mod->h_root = dget(au_h_dptr(root, bindex));
20038+
4f0767ce 20039+out:
1facf9fc 20040+ aufs_read_unlock(root, !AuLock_IR);
20041+ return err;
20042+}
20043+#endif
20044+
20045+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
20046+ substring_t args[])
20047+{
20048+ int err;
20049+ struct file *file;
20050+
20051+ file = au_xino_create(sb, args[0].from, /*silent*/0);
20052+ err = PTR_ERR(file);
20053+ if (IS_ERR(file))
20054+ goto out;
20055+
20056+ err = -EINVAL;
20057+ if (unlikely(file->f_dentry->d_sb == sb)) {
20058+ fput(file);
4a4d8108 20059+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 20060+ goto out;
20061+ }
20062+
20063+ err = 0;
20064+ xino->file = file;
20065+ xino->path = args[0].from;
20066+
4f0767ce 20067+out:
1facf9fc 20068+ return err;
20069+}
20070+
4a4d8108
AM
20071+static int noinline_for_stack
20072+au_opts_parse_xino_itrunc_path(struct super_block *sb,
20073+ struct au_opt_xino_itrunc *xino_itrunc,
20074+ substring_t args[])
1facf9fc 20075+{
20076+ int err;
20077+ aufs_bindex_t bend, bindex;
20078+ struct path path;
20079+ struct dentry *root;
20080+
20081+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
20082+ if (unlikely(err)) {
4a4d8108 20083+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 20084+ goto out;
20085+ }
20086+
20087+ xino_itrunc->bindex = -1;
20088+ root = sb->s_root;
20089+ aufs_read_lock(root, AuLock_FLUSH);
20090+ bend = au_sbend(sb);
20091+ for (bindex = 0; bindex <= bend; bindex++) {
20092+ if (au_h_dptr(root, bindex) == path.dentry) {
20093+ xino_itrunc->bindex = bindex;
20094+ break;
20095+ }
20096+ }
20097+ aufs_read_unlock(root, !AuLock_IR);
20098+ path_put(&path);
20099+
20100+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 20101+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 20102+ err = -EINVAL;
20103+ }
20104+
4f0767ce 20105+out:
1facf9fc 20106+ return err;
20107+}
20108+
20109+/* called without aufs lock */
20110+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
20111+{
20112+ int err, n, token;
20113+ aufs_bindex_t bindex;
20114+ unsigned char skipped;
20115+ struct dentry *root;
20116+ struct au_opt *opt, *opt_tail;
20117+ char *opt_str;
20118+ /* reduce the stack space */
20119+ union {
20120+ struct au_opt_xino_itrunc *xino_itrunc;
20121+ struct au_opt_wbr_create *create;
20122+ } u;
20123+ struct {
20124+ substring_t args[MAX_OPT_ARGS];
20125+ } *a;
20126+
20127+ err = -ENOMEM;
20128+ a = kmalloc(sizeof(*a), GFP_NOFS);
20129+ if (unlikely(!a))
20130+ goto out;
20131+
20132+ root = sb->s_root;
20133+ err = 0;
20134+ bindex = 0;
20135+ opt = opts->opt;
20136+ opt_tail = opt + opts->max_opt - 1;
20137+ opt->type = Opt_tail;
20138+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
20139+ err = -EINVAL;
20140+ skipped = 0;
20141+ token = match_token(opt_str, options, a->args);
20142+ switch (token) {
20143+ case Opt_br:
20144+ err = 0;
20145+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
20146+ && *opt_str) {
20147+ err = opt_add(opt, opt_str, opts->sb_flags,
20148+ bindex++);
20149+ if (unlikely(!err && ++opt > opt_tail)) {
20150+ err = -E2BIG;
20151+ break;
20152+ }
20153+ opt->type = Opt_tail;
20154+ skipped = 1;
20155+ }
20156+ break;
20157+ case Opt_add:
20158+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20159+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20160+ break;
20161+ }
20162+ bindex = n;
20163+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
20164+ bindex);
20165+ if (!err)
20166+ opt->type = token;
20167+ break;
20168+ case Opt_append:
20169+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
20170+ /*dummy bindex*/1);
20171+ if (!err)
20172+ opt->type = token;
20173+ break;
20174+ case Opt_prepend:
20175+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
20176+ /*bindex*/0);
20177+ if (!err)
20178+ opt->type = token;
20179+ break;
20180+ case Opt_del:
20181+ err = au_opts_parse_del(&opt->del, a->args);
20182+ if (!err)
20183+ opt->type = token;
20184+ break;
20185+#if 0 /* reserved for future use */
20186+ case Opt_idel:
20187+ del->pathname = "(indexed)";
20188+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 20189+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20190+ break;
20191+ }
20192+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
20193+ if (!err)
20194+ opt->type = token;
20195+ break;
20196+#endif
20197+ case Opt_mod:
20198+ err = au_opts_parse_mod(&opt->mod, a->args);
20199+ if (!err)
20200+ opt->type = token;
20201+ break;
20202+#ifdef IMOD /* reserved for future use */
20203+ case Opt_imod:
20204+ u.mod->path = "(indexed)";
20205+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20206+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20207+ break;
20208+ }
20209+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
20210+ if (!err)
20211+ opt->type = token;
20212+ break;
20213+#endif
20214+ case Opt_xino:
20215+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
20216+ if (!err)
20217+ opt->type = token;
20218+ break;
20219+
20220+ case Opt_trunc_xino_path:
20221+ err = au_opts_parse_xino_itrunc_path
20222+ (sb, &opt->xino_itrunc, a->args);
20223+ if (!err)
20224+ opt->type = token;
20225+ break;
20226+
20227+ case Opt_itrunc_xino:
20228+ u.xino_itrunc = &opt->xino_itrunc;
20229+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20230+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20231+ break;
20232+ }
20233+ u.xino_itrunc->bindex = n;
20234+ aufs_read_lock(root, AuLock_FLUSH);
20235+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 20236+ pr_err("out of bounds, %d\n", n);
1facf9fc 20237+ aufs_read_unlock(root, !AuLock_IR);
20238+ break;
20239+ }
20240+ aufs_read_unlock(root, !AuLock_IR);
20241+ err = 0;
20242+ opt->type = token;
20243+ break;
20244+
20245+ case Opt_dirwh:
20246+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
20247+ break;
20248+ err = 0;
20249+ opt->type = token;
20250+ break;
20251+
20252+ case Opt_rdcache:
027c5e7a
AM
20253+ if (unlikely(match_int(&a->args[0], &n))) {
20254+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20255+ break;
027c5e7a
AM
20256+ }
20257+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
20258+ pr_err("rdcache must be smaller than %d\n",
20259+ AUFS_RDCACHE_MAX);
20260+ break;
20261+ }
20262+ opt->rdcache = n;
1facf9fc 20263+ err = 0;
20264+ opt->type = token;
20265+ break;
20266+ case Opt_rdblk:
20267+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 20268+ || n < 0
1facf9fc 20269+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 20270+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20271+ break;
20272+ }
1308ab2a 20273+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
20274+ pr_err("rdblk must be larger than %d\n",
20275+ NAME_MAX);
1facf9fc 20276+ break;
20277+ }
20278+ opt->rdblk = n;
20279+ err = 0;
20280+ opt->type = token;
20281+ break;
20282+ case Opt_rdhash:
20283+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 20284+ || n < 0
1facf9fc 20285+ || n * sizeof(struct hlist_head)
20286+ > KMALLOC_MAX_SIZE)) {
4a4d8108 20287+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20288+ break;
20289+ }
20290+ opt->rdhash = n;
20291+ err = 0;
20292+ opt->type = token;
20293+ break;
20294+
20295+ case Opt_trunc_xino:
20296+ case Opt_notrunc_xino:
20297+ case Opt_noxino:
20298+ case Opt_trunc_xib:
20299+ case Opt_notrunc_xib:
dece6358
AM
20300+ case Opt_shwh:
20301+ case Opt_noshwh:
1facf9fc 20302+ case Opt_plink:
20303+ case Opt_noplink:
20304+ case Opt_list_plink:
4a4d8108
AM
20305+ case Opt_dio:
20306+ case Opt_nodio:
1facf9fc 20307+ case Opt_diropq_a:
20308+ case Opt_diropq_w:
20309+ case Opt_warn_perm:
20310+ case Opt_nowarn_perm:
20311+ case Opt_refrof:
20312+ case Opt_norefrof:
20313+ case Opt_verbose:
20314+ case Opt_noverbose:
20315+ case Opt_sum:
20316+ case Opt_nosum:
20317+ case Opt_wsum:
dece6358
AM
20318+ case Opt_rdblk_def:
20319+ case Opt_rdhash_def:
1facf9fc 20320+ err = 0;
20321+ opt->type = token;
20322+ break;
20323+
20324+ case Opt_udba:
20325+ opt->udba = udba_val(a->args[0].from);
20326+ if (opt->udba >= 0) {
20327+ err = 0;
20328+ opt->type = token;
20329+ } else
4a4d8108 20330+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20331+ break;
20332+
20333+ case Opt_wbr_create:
20334+ u.create = &opt->wbr_create;
20335+ u.create->wbr_create
20336+ = au_wbr_create_val(a->args[0].from, u.create);
20337+ if (u.create->wbr_create >= 0) {
20338+ err = 0;
20339+ opt->type = token;
20340+ } else
4a4d8108 20341+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20342+ break;
20343+ case Opt_wbr_copyup:
20344+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
20345+ if (opt->wbr_copyup >= 0) {
20346+ err = 0;
20347+ opt->type = token;
20348+ } else
4a4d8108 20349+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20350+ break;
20351+
20352+ case Opt_ignore:
0c3ec466 20353+ pr_warn("ignored %s\n", opt_str);
1facf9fc 20354+ /*FALLTHROUGH*/
20355+ case Opt_ignore_silent:
20356+ skipped = 1;
20357+ err = 0;
20358+ break;
20359+ case Opt_err:
4a4d8108 20360+ pr_err("unknown option %s\n", opt_str);
1facf9fc 20361+ break;
20362+ }
20363+
20364+ if (!err && !skipped) {
20365+ if (unlikely(++opt > opt_tail)) {
20366+ err = -E2BIG;
20367+ opt--;
20368+ opt->type = Opt_tail;
20369+ break;
20370+ }
20371+ opt->type = Opt_tail;
20372+ }
20373+ }
20374+
20375+ kfree(a);
20376+ dump_opts(opts);
20377+ if (unlikely(err))
20378+ au_opts_free(opts);
20379+
4f0767ce 20380+out:
1facf9fc 20381+ return err;
20382+}
20383+
20384+static int au_opt_wbr_create(struct super_block *sb,
20385+ struct au_opt_wbr_create *create)
20386+{
20387+ int err;
20388+ struct au_sbinfo *sbinfo;
20389+
dece6358
AM
20390+ SiMustWriteLock(sb);
20391+
1facf9fc 20392+ err = 1; /* handled */
20393+ sbinfo = au_sbi(sb);
20394+ if (sbinfo->si_wbr_create_ops->fin) {
20395+ err = sbinfo->si_wbr_create_ops->fin(sb);
20396+ if (!err)
20397+ err = 1;
20398+ }
20399+
20400+ sbinfo->si_wbr_create = create->wbr_create;
20401+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
20402+ switch (create->wbr_create) {
20403+ case AuWbrCreate_MFSRRV:
20404+ case AuWbrCreate_MFSRR:
20405+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
20406+ /*FALLTHROUGH*/
20407+ case AuWbrCreate_MFS:
20408+ case AuWbrCreate_MFSV:
20409+ case AuWbrCreate_PMFS:
20410+ case AuWbrCreate_PMFSV:
e49829fe
JR
20411+ sbinfo->si_wbr_mfs.mfs_expire
20412+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 20413+ break;
20414+ }
20415+
20416+ if (sbinfo->si_wbr_create_ops->init)
20417+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
20418+
20419+ return err;
20420+}
20421+
20422+/*
20423+ * returns,
20424+ * plus: processed without an error
20425+ * zero: unprocessed
20426+ */
20427+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
20428+ struct au_opts *opts)
20429+{
20430+ int err;
20431+ struct au_sbinfo *sbinfo;
20432+
dece6358
AM
20433+ SiMustWriteLock(sb);
20434+
1facf9fc 20435+ err = 1; /* handled */
20436+ sbinfo = au_sbi(sb);
20437+ switch (opt->type) {
20438+ case Opt_udba:
20439+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
20440+ sbinfo->si_mntflags |= opt->udba;
20441+ opts->given_udba |= opt->udba;
20442+ break;
20443+
20444+ case Opt_plink:
20445+ au_opt_set(sbinfo->si_mntflags, PLINK);
20446+ break;
20447+ case Opt_noplink:
20448+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 20449+ au_plink_put(sb, /*verbose*/1);
1facf9fc 20450+ au_opt_clr(sbinfo->si_mntflags, PLINK);
20451+ break;
20452+ case Opt_list_plink:
20453+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
20454+ au_plink_list(sb);
20455+ break;
20456+
4a4d8108
AM
20457+ case Opt_dio:
20458+ au_opt_set(sbinfo->si_mntflags, DIO);
20459+ au_fset_opts(opts->flags, REFRESH_DYAOP);
20460+ break;
20461+ case Opt_nodio:
20462+ au_opt_clr(sbinfo->si_mntflags, DIO);
20463+ au_fset_opts(opts->flags, REFRESH_DYAOP);
20464+ break;
20465+
1facf9fc 20466+ case Opt_diropq_a:
20467+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
20468+ break;
20469+ case Opt_diropq_w:
20470+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
20471+ break;
20472+
20473+ case Opt_warn_perm:
20474+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
20475+ break;
20476+ case Opt_nowarn_perm:
20477+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
20478+ break;
20479+
20480+ case Opt_refrof:
20481+ au_opt_set(sbinfo->si_mntflags, REFROF);
20482+ break;
20483+ case Opt_norefrof:
20484+ au_opt_clr(sbinfo->si_mntflags, REFROF);
20485+ break;
20486+
20487+ case Opt_verbose:
20488+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
20489+ break;
20490+ case Opt_noverbose:
20491+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
20492+ break;
20493+
20494+ case Opt_sum:
20495+ au_opt_set(sbinfo->si_mntflags, SUM);
20496+ break;
20497+ case Opt_wsum:
20498+ au_opt_clr(sbinfo->si_mntflags, SUM);
20499+ au_opt_set(sbinfo->si_mntflags, SUM_W);
20500+ case Opt_nosum:
20501+ au_opt_clr(sbinfo->si_mntflags, SUM);
20502+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
20503+ break;
20504+
20505+ case Opt_wbr_create:
20506+ err = au_opt_wbr_create(sb, &opt->wbr_create);
20507+ break;
20508+ case Opt_wbr_copyup:
20509+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
20510+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
20511+ break;
20512+
20513+ case Opt_dirwh:
20514+ sbinfo->si_dirwh = opt->dirwh;
20515+ break;
20516+
20517+ case Opt_rdcache:
e49829fe
JR
20518+ sbinfo->si_rdcache
20519+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 20520+ break;
20521+ case Opt_rdblk:
20522+ sbinfo->si_rdblk = opt->rdblk;
20523+ break;
dece6358
AM
20524+ case Opt_rdblk_def:
20525+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
20526+ break;
1facf9fc 20527+ case Opt_rdhash:
20528+ sbinfo->si_rdhash = opt->rdhash;
20529+ break;
dece6358
AM
20530+ case Opt_rdhash_def:
20531+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
20532+ break;
20533+
20534+ case Opt_shwh:
20535+ au_opt_set(sbinfo->si_mntflags, SHWH);
20536+ break;
20537+ case Opt_noshwh:
20538+ au_opt_clr(sbinfo->si_mntflags, SHWH);
20539+ break;
1facf9fc 20540+
20541+ case Opt_trunc_xino:
20542+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
20543+ break;
20544+ case Opt_notrunc_xino:
20545+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
20546+ break;
20547+
20548+ case Opt_trunc_xino_path:
20549+ case Opt_itrunc_xino:
20550+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
20551+ if (!err)
20552+ err = 1;
20553+ break;
20554+
20555+ case Opt_trunc_xib:
20556+ au_fset_opts(opts->flags, TRUNC_XIB);
20557+ break;
20558+ case Opt_notrunc_xib:
20559+ au_fclr_opts(opts->flags, TRUNC_XIB);
20560+ break;
20561+
20562+ default:
20563+ err = 0;
20564+ break;
20565+ }
20566+
20567+ return err;
20568+}
20569+
20570+/*
20571+ * returns tri-state.
20572+ * plus: processed without an error
20573+ * zero: unprocessed
20574+ * minus: error
20575+ */
20576+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
20577+ struct au_opts *opts)
20578+{
20579+ int err, do_refresh;
20580+
20581+ err = 0;
20582+ switch (opt->type) {
20583+ case Opt_append:
20584+ opt->add.bindex = au_sbend(sb) + 1;
20585+ if (opt->add.bindex < 0)
20586+ opt->add.bindex = 0;
20587+ goto add;
20588+ case Opt_prepend:
20589+ opt->add.bindex = 0;
20590+ add:
20591+ case Opt_add:
20592+ err = au_br_add(sb, &opt->add,
20593+ au_ftest_opts(opts->flags, REMOUNT));
20594+ if (!err) {
20595+ err = 1;
027c5e7a 20596+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20597+ }
20598+ break;
20599+
20600+ case Opt_del:
20601+ case Opt_idel:
20602+ err = au_br_del(sb, &opt->del,
20603+ au_ftest_opts(opts->flags, REMOUNT));
20604+ if (!err) {
20605+ err = 1;
20606+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 20607+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20608+ }
20609+ break;
20610+
20611+ case Opt_mod:
20612+ case Opt_imod:
20613+ err = au_br_mod(sb, &opt->mod,
20614+ au_ftest_opts(opts->flags, REMOUNT),
20615+ &do_refresh);
20616+ if (!err) {
20617+ err = 1;
027c5e7a
AM
20618+ if (do_refresh)
20619+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20620+ }
20621+ break;
20622+ }
20623+
20624+ return err;
20625+}
20626+
20627+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
20628+ struct au_opt_xino **opt_xino,
20629+ struct au_opts *opts)
20630+{
20631+ int err;
20632+ aufs_bindex_t bend, bindex;
20633+ struct dentry *root, *parent, *h_root;
20634+
20635+ err = 0;
20636+ switch (opt->type) {
20637+ case Opt_xino:
20638+ err = au_xino_set(sb, &opt->xino,
20639+ !!au_ftest_opts(opts->flags, REMOUNT));
20640+ if (unlikely(err))
20641+ break;
20642+
20643+ *opt_xino = &opt->xino;
20644+ au_xino_brid_set(sb, -1);
20645+
20646+ /* safe d_parent access */
20647+ parent = opt->xino.file->f_dentry->d_parent;
20648+ root = sb->s_root;
20649+ bend = au_sbend(sb);
20650+ for (bindex = 0; bindex <= bend; bindex++) {
20651+ h_root = au_h_dptr(root, bindex);
20652+ if (h_root == parent) {
20653+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
20654+ break;
20655+ }
20656+ }
20657+ break;
20658+
20659+ case Opt_noxino:
20660+ au_xino_clr(sb);
20661+ au_xino_brid_set(sb, -1);
20662+ *opt_xino = (void *)-1;
20663+ break;
20664+ }
20665+
20666+ return err;
20667+}
20668+
20669+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
20670+ unsigned int pending)
20671+{
20672+ int err;
20673+ aufs_bindex_t bindex, bend;
20674+ unsigned char do_plink, skip, do_free;
20675+ struct au_branch *br;
20676+ struct au_wbr *wbr;
20677+ struct dentry *root;
20678+ struct inode *dir, *h_dir;
20679+ struct au_sbinfo *sbinfo;
20680+ struct au_hinode *hdir;
20681+
dece6358
AM
20682+ SiMustAnyLock(sb);
20683+
1facf9fc 20684+ sbinfo = au_sbi(sb);
20685+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
20686+
dece6358
AM
20687+ if (!(sb_flags & MS_RDONLY)) {
20688+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
0c3ec466 20689+ pr_warn("first branch should be rw\n");
dece6358 20690+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
0c3ec466 20691+ pr_warn("shwh should be used with ro\n");
dece6358 20692+ }
1facf9fc 20693+
4a4d8108 20694+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 20695+ && !au_opt_test(sbinfo->si_mntflags, XINO))
0c3ec466 20696+ pr_warn("udba=*notify requires xino\n");
1facf9fc 20697+
20698+ err = 0;
20699+ root = sb->s_root;
4a4d8108 20700+ dir = root->d_inode;
1facf9fc 20701+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
20702+ bend = au_sbend(sb);
20703+ for (bindex = 0; !err && bindex <= bend; bindex++) {
20704+ skip = 0;
20705+ h_dir = au_h_iptr(dir, bindex);
20706+ br = au_sbr(sb, bindex);
20707+ do_free = 0;
20708+
20709+ wbr = br->br_wbr;
20710+ if (wbr)
20711+ wbr_wh_read_lock(wbr);
20712+
1e00d052 20713+ if (!au_br_writable(br->br_perm)) {
1facf9fc 20714+ do_free = !!wbr;
20715+ skip = (!wbr
20716+ || (!wbr->wbr_whbase
20717+ && !wbr->wbr_plink
20718+ && !wbr->wbr_orph));
1e00d052 20719+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 20720+ /* skip = (!br->br_whbase && !br->br_orph); */
20721+ skip = (!wbr || !wbr->wbr_whbase);
20722+ if (skip && wbr) {
20723+ if (do_plink)
20724+ skip = !!wbr->wbr_plink;
20725+ else
20726+ skip = !wbr->wbr_plink;
20727+ }
1e00d052 20728+ } else {
1facf9fc 20729+ /* skip = (br->br_whbase && br->br_ohph); */
20730+ skip = (wbr && wbr->wbr_whbase);
20731+ if (skip) {
20732+ if (do_plink)
20733+ skip = !!wbr->wbr_plink;
20734+ else
20735+ skip = !wbr->wbr_plink;
20736+ }
1facf9fc 20737+ }
20738+ if (wbr)
20739+ wbr_wh_read_unlock(wbr);
20740+
20741+ if (skip)
20742+ continue;
20743+
20744+ hdir = au_hi(dir, bindex);
4a4d8108 20745+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 20746+ if (wbr)
20747+ wbr_wh_write_lock(wbr);
20748+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
20749+ if (wbr)
20750+ wbr_wh_write_unlock(wbr);
4a4d8108 20751+ au_hn_imtx_unlock(hdir);
1facf9fc 20752+
20753+ if (!err && do_free) {
20754+ kfree(wbr);
20755+ br->br_wbr = NULL;
20756+ }
20757+ }
20758+
20759+ return err;
20760+}
20761+
20762+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
20763+{
20764+ int err;
20765+ unsigned int tmp;
027c5e7a 20766+ aufs_bindex_t bindex, bend;
1facf9fc 20767+ struct au_opt *opt;
20768+ struct au_opt_xino *opt_xino, xino;
20769+ struct au_sbinfo *sbinfo;
027c5e7a 20770+ struct au_branch *br;
1facf9fc 20771+
dece6358
AM
20772+ SiMustWriteLock(sb);
20773+
1facf9fc 20774+ err = 0;
20775+ opt_xino = NULL;
20776+ opt = opts->opt;
20777+ while (err >= 0 && opt->type != Opt_tail)
20778+ err = au_opt_simple(sb, opt++, opts);
20779+ if (err > 0)
20780+ err = 0;
20781+ else if (unlikely(err < 0))
20782+ goto out;
20783+
20784+ /* disable xino and udba temporary */
20785+ sbinfo = au_sbi(sb);
20786+ tmp = sbinfo->si_mntflags;
20787+ au_opt_clr(sbinfo->si_mntflags, XINO);
20788+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
20789+
20790+ opt = opts->opt;
20791+ while (err >= 0 && opt->type != Opt_tail)
20792+ err = au_opt_br(sb, opt++, opts);
20793+ if (err > 0)
20794+ err = 0;
20795+ else if (unlikely(err < 0))
20796+ goto out;
20797+
20798+ bend = au_sbend(sb);
20799+ if (unlikely(bend < 0)) {
20800+ err = -EINVAL;
4a4d8108 20801+ pr_err("no branches\n");
1facf9fc 20802+ goto out;
20803+ }
20804+
20805+ if (au_opt_test(tmp, XINO))
20806+ au_opt_set(sbinfo->si_mntflags, XINO);
20807+ opt = opts->opt;
20808+ while (!err && opt->type != Opt_tail)
20809+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
20810+ if (unlikely(err))
20811+ goto out;
20812+
20813+ err = au_opts_verify(sb, sb->s_flags, tmp);
20814+ if (unlikely(err))
20815+ goto out;
20816+
20817+ /* restore xino */
20818+ if (au_opt_test(tmp, XINO) && !opt_xino) {
20819+ xino.file = au_xino_def(sb);
20820+ err = PTR_ERR(xino.file);
20821+ if (IS_ERR(xino.file))
20822+ goto out;
20823+
20824+ err = au_xino_set(sb, &xino, /*remount*/0);
20825+ fput(xino.file);
20826+ if (unlikely(err))
20827+ goto out;
20828+ }
20829+
20830+ /* restore udba */
027c5e7a 20831+ tmp &= AuOptMask_UDBA;
1facf9fc 20832+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a
AM
20833+ sbinfo->si_mntflags |= tmp;
20834+ bend = au_sbend(sb);
20835+ for (bindex = 0; bindex <= bend; bindex++) {
20836+ br = au_sbr(sb, bindex);
20837+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
20838+ if (unlikely(err))
20839+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
20840+ bindex, err);
20841+ /* go on even if err */
20842+ }
4a4d8108 20843+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 20844+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 20845+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 20846+ }
20847+
4f0767ce 20848+out:
1facf9fc 20849+ return err;
20850+}
20851+
20852+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
20853+{
20854+ int err, rerr;
20855+ struct inode *dir;
20856+ struct au_opt_xino *opt_xino;
20857+ struct au_opt *opt;
20858+ struct au_sbinfo *sbinfo;
20859+
dece6358
AM
20860+ SiMustWriteLock(sb);
20861+
1facf9fc 20862+ dir = sb->s_root->d_inode;
20863+ sbinfo = au_sbi(sb);
20864+ err = 0;
20865+ opt_xino = NULL;
20866+ opt = opts->opt;
20867+ while (err >= 0 && opt->type != Opt_tail) {
20868+ err = au_opt_simple(sb, opt, opts);
20869+ if (!err)
20870+ err = au_opt_br(sb, opt, opts);
20871+ if (!err)
20872+ err = au_opt_xino(sb, opt, &opt_xino, opts);
20873+ opt++;
20874+ }
20875+ if (err > 0)
20876+ err = 0;
20877+ AuTraceErr(err);
20878+ /* go on even err */
20879+
20880+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
20881+ if (unlikely(rerr && !err))
20882+ err = rerr;
20883+
20884+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
20885+ rerr = au_xib_trunc(sb);
20886+ if (unlikely(rerr && !err))
20887+ err = rerr;
20888+ }
20889+
20890+ /* will be handled by the caller */
027c5e7a 20891+ if (!au_ftest_opts(opts->flags, REFRESH)
1facf9fc 20892+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
027c5e7a 20893+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20894+
20895+ AuDbg("status 0x%x\n", opts->flags);
20896+ return err;
20897+}
20898+
20899+/* ---------------------------------------------------------------------- */
20900+
20901+unsigned int au_opt_udba(struct super_block *sb)
20902+{
20903+ return au_mntflags(sb) & AuOptMask_UDBA;
20904+}
7f207e10
AM
20905diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
20906--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 20907+++ linux/fs/aufs/opts.h 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 20908@@ -0,0 +1,209 @@
1facf9fc 20909+/*
f6c5ef8b 20910+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 20911+ *
20912+ * This program, aufs is free software; you can redistribute it and/or modify
20913+ * it under the terms of the GNU General Public License as published by
20914+ * the Free Software Foundation; either version 2 of the License, or
20915+ * (at your option) any later version.
dece6358
AM
20916+ *
20917+ * This program is distributed in the hope that it will be useful,
20918+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20919+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20920+ * GNU General Public License for more details.
20921+ *
20922+ * You should have received a copy of the GNU General Public License
20923+ * along with this program; if not, write to the Free Software
20924+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20925+ */
20926+
20927+/*
20928+ * mount options/flags
20929+ */
20930+
20931+#ifndef __AUFS_OPTS_H__
20932+#define __AUFS_OPTS_H__
20933+
20934+#ifdef __KERNEL__
20935+
dece6358 20936+#include <linux/path.h>
1facf9fc 20937+
dece6358
AM
20938+struct file;
20939+struct super_block;
20940+
1facf9fc 20941+/* ---------------------------------------------------------------------- */
20942+
20943+/* mount flags */
20944+#define AuOpt_XINO 1 /* external inode number bitmap
20945+ and translation table */
20946+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
20947+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
20948+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 20949+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
20950+#define AuOpt_SHWH (1 << 5) /* show whiteout */
20951+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
20952+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
20953+#define AuOpt_REFROF (1 << 8) /* unimplemented */
20954+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
20955+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
20956+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
20957+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
20958+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 20959+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 20960+
4a4d8108
AM
20961+#ifndef CONFIG_AUFS_HNOTIFY
20962+#undef AuOpt_UDBA_HNOTIFY
20963+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 20964+#endif
dece6358
AM
20965+#ifndef CONFIG_AUFS_SHWH
20966+#undef AuOpt_SHWH
20967+#define AuOpt_SHWH 0
20968+#endif
1facf9fc 20969+
20970+#define AuOpt_Def (AuOpt_XINO \
20971+ | AuOpt_UDBA_REVAL \
20972+ | AuOpt_PLINK \
20973+ /* | AuOpt_DIRPERM1 */ \
20974+ | AuOpt_WARN_PERM)
20975+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
20976+ | AuOpt_UDBA_REVAL \
4a4d8108 20977+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 20978+
20979+#define au_opt_test(flags, name) (flags & AuOpt_##name)
20980+#define au_opt_set(flags, name) do { \
20981+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
20982+ ((flags) |= AuOpt_##name); \
20983+} while (0)
20984+#define au_opt_set_udba(flags, name) do { \
20985+ (flags) &= ~AuOptMask_UDBA; \
20986+ ((flags) |= AuOpt_##name); \
20987+} while (0)
7f207e10
AM
20988+#define au_opt_clr(flags, name) do { \
20989+ ((flags) &= ~AuOpt_##name); \
20990+} while (0)
1facf9fc 20991+
e49829fe
JR
20992+static inline unsigned int au_opts_plink(unsigned int mntflags)
20993+{
20994+#ifdef CONFIG_PROC_FS
20995+ return mntflags;
20996+#else
20997+ return mntflags & ~AuOpt_PLINK;
20998+#endif
20999+}
21000+
1facf9fc 21001+/* ---------------------------------------------------------------------- */
21002+
21003+/* policies to select one among multiple writable branches */
21004+enum {
21005+ AuWbrCreate_TDP, /* top down parent */
21006+ AuWbrCreate_RR, /* round robin */
21007+ AuWbrCreate_MFS, /* most free space */
21008+ AuWbrCreate_MFSV, /* mfs with seconds */
21009+ AuWbrCreate_MFSRR, /* mfs then rr */
21010+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
21011+ AuWbrCreate_PMFS, /* parent and mfs */
21012+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
21013+
21014+ AuWbrCreate_Def = AuWbrCreate_TDP
21015+};
21016+
21017+enum {
21018+ AuWbrCopyup_TDP, /* top down parent */
21019+ AuWbrCopyup_BUP, /* bottom up parent */
21020+ AuWbrCopyup_BU, /* bottom up */
21021+
21022+ AuWbrCopyup_Def = AuWbrCopyup_TDP
21023+};
21024+
21025+/* ---------------------------------------------------------------------- */
21026+
21027+struct au_opt_add {
21028+ aufs_bindex_t bindex;
21029+ char *pathname;
21030+ int perm;
21031+ struct path path;
21032+};
21033+
21034+struct au_opt_del {
21035+ char *pathname;
21036+ struct path h_path;
21037+};
21038+
21039+struct au_opt_mod {
21040+ char *path;
21041+ int perm;
21042+ struct dentry *h_root;
21043+};
21044+
21045+struct au_opt_xino {
21046+ char *path;
21047+ struct file *file;
21048+};
21049+
21050+struct au_opt_xino_itrunc {
21051+ aufs_bindex_t bindex;
21052+};
21053+
21054+struct au_opt_wbr_create {
21055+ int wbr_create;
21056+ int mfs_second;
21057+ unsigned long long mfsrr_watermark;
21058+};
21059+
21060+struct au_opt {
21061+ int type;
21062+ union {
21063+ struct au_opt_xino xino;
21064+ struct au_opt_xino_itrunc xino_itrunc;
21065+ struct au_opt_add add;
21066+ struct au_opt_del del;
21067+ struct au_opt_mod mod;
21068+ int dirwh;
21069+ int rdcache;
21070+ unsigned int rdblk;
21071+ unsigned int rdhash;
21072+ int udba;
21073+ struct au_opt_wbr_create wbr_create;
21074+ int wbr_copyup;
21075+ };
21076+};
21077+
21078+/* opts flags */
21079+#define AuOpts_REMOUNT 1
027c5e7a
AM
21080+#define AuOpts_REFRESH (1 << 1)
21081+#define AuOpts_TRUNC_XIB (1 << 2)
21082+#define AuOpts_REFRESH_DYAOP (1 << 3)
1facf9fc 21083+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
21084+#define au_fset_opts(flags, name) \
21085+ do { (flags) |= AuOpts_##name; } while (0)
21086+#define au_fclr_opts(flags, name) \
21087+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 21088+
21089+struct au_opts {
21090+ struct au_opt *opt;
21091+ int max_opt;
21092+
21093+ unsigned int given_udba;
21094+ unsigned int flags;
21095+ unsigned long sb_flags;
21096+};
21097+
21098+/* ---------------------------------------------------------------------- */
21099+
1e00d052 21100+char *au_optstr_br_perm(int brperm);
1facf9fc 21101+const char *au_optstr_udba(int udba);
21102+const char *au_optstr_wbr_copyup(int wbr_copyup);
21103+const char *au_optstr_wbr_create(int wbr_create);
21104+
21105+void au_opts_free(struct au_opts *opts);
21106+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
21107+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
21108+ unsigned int pending);
21109+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
21110+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
21111+
21112+unsigned int au_opt_udba(struct super_block *sb);
21113+
21114+/* ---------------------------------------------------------------------- */
21115+
21116+#endif /* __KERNEL__ */
21117+#endif /* __AUFS_OPTS_H__ */
7f207e10
AM
21118diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
21119--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 21120+++ linux/fs/aufs/plink.c 2012-08-26 08:39:00.763841498 +0200
0c3ec466 21121@@ -0,0 +1,511 @@
1facf9fc 21122+/*
f6c5ef8b 21123+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 21124+ *
21125+ * This program, aufs is free software; you can redistribute it and/or modify
21126+ * it under the terms of the GNU General Public License as published by
21127+ * the Free Software Foundation; either version 2 of the License, or
21128+ * (at your option) any later version.
dece6358
AM
21129+ *
21130+ * This program is distributed in the hope that it will be useful,
21131+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21132+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21133+ * GNU General Public License for more details.
21134+ *
21135+ * You should have received a copy of the GNU General Public License
21136+ * along with this program; if not, write to the Free Software
21137+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21138+ */
21139+
21140+/*
21141+ * pseudo-link
21142+ */
21143+
21144+#include "aufs.h"
21145+
21146+/*
e49829fe 21147+ * the pseudo-link maintenance mode.
1facf9fc 21148+ * during a user process maintains the pseudo-links,
21149+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
21150+ *
21151+ * Flags
21152+ * NOPLM:
21153+ * For entry functions which will handle plink, and i_mutex is already held
21154+ * in VFS.
21155+ * They cannot wait and should return an error at once.
21156+ * Callers has to check the error.
21157+ * NOPLMW:
21158+ * For entry functions which will handle plink, but i_mutex is not held
21159+ * in VFS.
21160+ * They can wait the plink maintenance mode to finish.
21161+ *
21162+ * They behave like F_SETLK and F_SETLKW.
21163+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 21164+ */
e49829fe
JR
21165+
21166+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 21167+{
e49829fe
JR
21168+ int err;
21169+ pid_t pid, ppid;
21170+ struct au_sbinfo *sbi;
dece6358
AM
21171+
21172+ SiMustAnyLock(sb);
21173+
e49829fe
JR
21174+ err = 0;
21175+ if (!au_opt_test(au_mntflags(sb), PLINK))
21176+ goto out;
21177+
21178+ sbi = au_sbi(sb);
21179+ pid = sbi->si_plink_maint_pid;
21180+ if (!pid || pid == current->pid)
21181+ goto out;
21182+
21183+ /* todo: it highly depends upon /sbin/mount.aufs */
21184+ rcu_read_lock();
21185+ ppid = task_pid_vnr(rcu_dereference(current->real_parent));
21186+ rcu_read_unlock();
21187+ if (pid == ppid)
21188+ goto out;
21189+
21190+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
21191+ /* if there is no i_mutex lock in VFS, we don't need to wait */
21192+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
21193+ while (sbi->si_plink_maint_pid) {
21194+ si_read_unlock(sb);
21195+ /* gave up wake_up_bit() */
21196+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
21197+
21198+ if (au_ftest_lock(flags, FLUSH))
21199+ au_nwt_flush(&sbi->si_nowait);
21200+ si_noflush_read_lock(sb);
21201+ }
21202+ } else if (au_ftest_lock(flags, NOPLM)) {
21203+ AuDbg("ppid %d, pid %d\n", ppid, pid);
21204+ err = -EAGAIN;
21205+ }
21206+
21207+out:
21208+ return err;
4a4d8108
AM
21209+}
21210+
e49829fe 21211+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 21212+{
4a4d8108 21213+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 21214+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 21215+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 21216+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
21217+}
21218+
e49829fe 21219+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
21220+{
21221+ int err;
4a4d8108
AM
21222+ struct au_sbinfo *sbinfo;
21223+
21224+ err = 0;
4a4d8108
AM
21225+ sbinfo = au_sbi(sb);
21226+ /* make sure i am the only one in this fs */
e49829fe
JR
21227+ si_write_lock(sb, AuLock_FLUSH);
21228+ if (au_opt_test(au_mntflags(sb), PLINK)) {
21229+ spin_lock(&sbinfo->si_plink_maint_lock);
21230+ if (!sbinfo->si_plink_maint_pid)
21231+ sbinfo->si_plink_maint_pid = current->pid;
21232+ else
21233+ err = -EBUSY;
21234+ spin_unlock(&sbinfo->si_plink_maint_lock);
21235+ }
4a4d8108
AM
21236+ si_write_unlock(sb);
21237+
21238+ return err;
1facf9fc 21239+}
21240+
21241+/* ---------------------------------------------------------------------- */
21242+
21243+struct pseudo_link {
4a4d8108
AM
21244+ union {
21245+ struct list_head list;
21246+ struct rcu_head rcu;
21247+ };
1facf9fc 21248+ struct inode *inode;
21249+};
21250+
21251+#ifdef CONFIG_AUFS_DEBUG
21252+void au_plink_list(struct super_block *sb)
21253+{
21254+ struct au_sbinfo *sbinfo;
21255+ struct list_head *plink_list;
21256+ struct pseudo_link *plink;
21257+
dece6358
AM
21258+ SiMustAnyLock(sb);
21259+
1facf9fc 21260+ sbinfo = au_sbi(sb);
21261+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21262+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21263+
21264+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21265+ rcu_read_lock();
21266+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 21267+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 21268+ rcu_read_unlock();
1facf9fc 21269+}
21270+#endif
21271+
21272+/* is the inode pseudo-linked? */
21273+int au_plink_test(struct inode *inode)
21274+{
21275+ int found;
21276+ struct au_sbinfo *sbinfo;
21277+ struct list_head *plink_list;
21278+ struct pseudo_link *plink;
21279+
21280+ sbinfo = au_sbi(inode->i_sb);
dece6358 21281+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 21282+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 21283+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 21284+
21285+ found = 0;
21286+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21287+ rcu_read_lock();
21288+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 21289+ if (plink->inode == inode) {
21290+ found = 1;
21291+ break;
21292+ }
4a4d8108 21293+ rcu_read_unlock();
1facf9fc 21294+ return found;
21295+}
21296+
21297+/* ---------------------------------------------------------------------- */
21298+
21299+/*
21300+ * generate a name for plink.
21301+ * the file will be stored under AUFS_WH_PLINKDIR.
21302+ */
21303+/* 20 is max digits length of ulong 64 */
21304+#define PLINK_NAME_LEN ((20 + 1) * 2)
21305+
21306+static int plink_name(char *name, int len, struct inode *inode,
21307+ aufs_bindex_t bindex)
21308+{
21309+ int rlen;
21310+ struct inode *h_inode;
21311+
21312+ h_inode = au_h_iptr(inode, bindex);
21313+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
21314+ return rlen;
21315+}
21316+
7f207e10
AM
21317+struct au_do_plink_lkup_args {
21318+ struct dentry **errp;
21319+ struct qstr *tgtname;
21320+ struct dentry *h_parent;
21321+ struct au_branch *br;
21322+};
21323+
21324+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
21325+ struct dentry *h_parent,
21326+ struct au_branch *br)
21327+{
21328+ struct dentry *h_dentry;
21329+ struct mutex *h_mtx;
21330+
21331+ h_mtx = &h_parent->d_inode->i_mutex;
21332+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
21333+ h_dentry = au_lkup_one(tgtname, h_parent, br, /*nd*/NULL);
21334+ mutex_unlock(h_mtx);
21335+ return h_dentry;
21336+}
21337+
21338+static void au_call_do_plink_lkup(void *args)
21339+{
21340+ struct au_do_plink_lkup_args *a = args;
21341+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
21342+}
21343+
1facf9fc 21344+/* lookup the plink-ed @inode under the branch at @bindex */
21345+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
21346+{
21347+ struct dentry *h_dentry, *h_parent;
21348+ struct au_branch *br;
21349+ struct inode *h_dir;
7f207e10 21350+ int wkq_err;
1facf9fc 21351+ char a[PLINK_NAME_LEN];
0c3ec466 21352+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 21353+
e49829fe
JR
21354+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
21355+
1facf9fc 21356+ br = au_sbr(inode->i_sb, bindex);
21357+ h_parent = br->br_wbr->wbr_plink;
21358+ h_dir = h_parent->d_inode;
21359+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
21360+
2dfbb274 21361+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
7f207e10
AM
21362+ struct au_do_plink_lkup_args args = {
21363+ .errp = &h_dentry,
21364+ .tgtname = &tgtname,
21365+ .h_parent = h_parent,
21366+ .br = br
21367+ };
21368+
21369+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
21370+ if (unlikely(wkq_err))
21371+ h_dentry = ERR_PTR(wkq_err);
21372+ } else
21373+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
21374+
1facf9fc 21375+ return h_dentry;
21376+}
21377+
21378+/* create a pseudo-link */
21379+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
21380+ struct dentry *h_dentry, struct au_branch *br)
21381+{
21382+ int err;
21383+ struct path h_path = {
21384+ .mnt = br->br_mnt
21385+ };
21386+ struct inode *h_dir;
21387+
21388+ h_dir = h_parent->d_inode;
7f207e10 21389+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
4f0767ce 21390+again:
1facf9fc 21391+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
21392+ err = PTR_ERR(h_path.dentry);
21393+ if (IS_ERR(h_path.dentry))
21394+ goto out;
21395+
21396+ err = 0;
21397+ /* wh.plink dir is not monitored */
7f207e10 21398+ /* todo: is it really safe? */
1facf9fc 21399+ if (h_path.dentry->d_inode
21400+ && h_path.dentry->d_inode != h_dentry->d_inode) {
21401+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
21402+ dput(h_path.dentry);
21403+ h_path.dentry = NULL;
21404+ if (!err)
21405+ goto again;
21406+ }
21407+ if (!err && !h_path.dentry->d_inode)
21408+ err = vfsub_link(h_dentry, h_dir, &h_path);
21409+ dput(h_path.dentry);
21410+
4f0767ce 21411+out:
7f207e10 21412+ mutex_unlock(&h_dir->i_mutex);
1facf9fc 21413+ return err;
21414+}
21415+
21416+struct do_whplink_args {
21417+ int *errp;
21418+ struct qstr *tgt;
21419+ struct dentry *h_parent;
21420+ struct dentry *h_dentry;
21421+ struct au_branch *br;
21422+};
21423+
21424+static void call_do_whplink(void *args)
21425+{
21426+ struct do_whplink_args *a = args;
21427+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
21428+}
21429+
21430+static int whplink(struct dentry *h_dentry, struct inode *inode,
21431+ aufs_bindex_t bindex, struct au_branch *br)
21432+{
21433+ int err, wkq_err;
21434+ struct au_wbr *wbr;
21435+ struct dentry *h_parent;
21436+ struct inode *h_dir;
21437+ char a[PLINK_NAME_LEN];
0c3ec466 21438+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 21439+
21440+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
21441+ h_parent = wbr->wbr_plink;
21442+ h_dir = h_parent->d_inode;
21443+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
21444+
21445+ /* always superio. */
2dfbb274 21446+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
1facf9fc 21447+ struct do_whplink_args args = {
21448+ .errp = &err,
21449+ .tgt = &tgtname,
21450+ .h_parent = h_parent,
21451+ .h_dentry = h_dentry,
21452+ .br = br
21453+ };
21454+ wkq_err = au_wkq_wait(call_do_whplink, &args);
21455+ if (unlikely(wkq_err))
21456+ err = wkq_err;
21457+ } else
21458+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 21459+
21460+ return err;
21461+}
21462+
21463+/* free a single plink */
21464+static void do_put_plink(struct pseudo_link *plink, int do_del)
21465+{
1facf9fc 21466+ if (do_del)
21467+ list_del(&plink->list);
4a4d8108
AM
21468+ iput(plink->inode);
21469+ kfree(plink);
21470+}
21471+
21472+static void do_put_plink_rcu(struct rcu_head *rcu)
21473+{
21474+ struct pseudo_link *plink;
21475+
21476+ plink = container_of(rcu, struct pseudo_link, rcu);
21477+ iput(plink->inode);
1facf9fc 21478+ kfree(plink);
21479+}
21480+
21481+/*
21482+ * create a new pseudo-link for @h_dentry on @bindex.
21483+ * the linked inode is held in aufs @inode.
21484+ */
21485+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
21486+ struct dentry *h_dentry)
21487+{
21488+ struct super_block *sb;
21489+ struct au_sbinfo *sbinfo;
21490+ struct list_head *plink_list;
4a4d8108 21491+ struct pseudo_link *plink, *tmp;
1facf9fc 21492+ int found, err, cnt;
21493+
21494+ sb = inode->i_sb;
21495+ sbinfo = au_sbi(sb);
21496+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21497+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21498+
1facf9fc 21499+ cnt = 0;
21500+ found = 0;
21501+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21502+ rcu_read_lock();
21503+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 21504+ cnt++;
21505+ if (plink->inode == inode) {
21506+ found = 1;
21507+ break;
21508+ }
21509+ }
4a4d8108
AM
21510+ rcu_read_unlock();
21511+ if (found)
1facf9fc 21512+ return;
4a4d8108
AM
21513+
21514+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
21515+ if (tmp)
21516+ tmp->inode = au_igrab(inode);
21517+ else {
21518+ err = -ENOMEM;
21519+ goto out;
1facf9fc 21520+ }
21521+
4a4d8108
AM
21522+ spin_lock(&sbinfo->si_plink.spin);
21523+ list_for_each_entry(plink, plink_list, list) {
21524+ if (plink->inode == inode) {
21525+ found = 1;
21526+ break;
21527+ }
1facf9fc 21528+ }
4a4d8108
AM
21529+ if (!found)
21530+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 21531+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
21532+ if (!found) {
21533+ cnt++;
21534+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
21535+ "unexpectedly many pseudo links, %d\n", cnt);
1facf9fc 21536+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
21537+ } else {
21538+ do_put_plink(tmp, 0);
21539+ return;
1facf9fc 21540+ }
21541+
4a4d8108 21542+out:
1facf9fc 21543+ if (unlikely(err)) {
0c3ec466 21544+ pr_warn("err %d, damaged pseudo link.\n", err);
4a4d8108
AM
21545+ if (tmp) {
21546+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
21547+ call_rcu(&tmp->rcu, do_put_plink_rcu);
21548+ }
1facf9fc 21549+ }
21550+}
21551+
21552+/* free all plinks */
e49829fe 21553+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 21554+{
21555+ struct au_sbinfo *sbinfo;
21556+ struct list_head *plink_list;
21557+ struct pseudo_link *plink, *tmp;
21558+
dece6358
AM
21559+ SiMustWriteLock(sb);
21560+
1facf9fc 21561+ sbinfo = au_sbi(sb);
21562+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21563+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21564+
21565+ plink_list = &sbinfo->si_plink.head;
21566+ /* no spin_lock since sbinfo is write-locked */
e49829fe 21567+ WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
1facf9fc 21568+ list_for_each_entry_safe(plink, tmp, plink_list, list)
21569+ do_put_plink(plink, 0);
21570+ INIT_LIST_HEAD(plink_list);
21571+}
21572+
e49829fe
JR
21573+void au_plink_clean(struct super_block *sb, int verbose)
21574+{
21575+ struct dentry *root;
21576+
21577+ root = sb->s_root;
21578+ aufs_write_lock(root);
21579+ if (au_opt_test(au_mntflags(sb), PLINK))
21580+ au_plink_put(sb, verbose);
21581+ aufs_write_unlock(root);
21582+}
21583+
1facf9fc 21584+/* free the plinks on a branch specified by @br_id */
21585+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
21586+{
21587+ struct au_sbinfo *sbinfo;
21588+ struct list_head *plink_list;
21589+ struct pseudo_link *plink, *tmp;
21590+ struct inode *inode;
21591+ aufs_bindex_t bstart, bend, bindex;
21592+ unsigned char do_put;
21593+
dece6358
AM
21594+ SiMustWriteLock(sb);
21595+
1facf9fc 21596+ sbinfo = au_sbi(sb);
21597+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21598+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21599+
21600+ plink_list = &sbinfo->si_plink.head;
21601+ /* no spin_lock since sbinfo is write-locked */
21602+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
21603+ do_put = 0;
21604+ inode = au_igrab(plink->inode);
21605+ ii_write_lock_child(inode);
21606+ bstart = au_ibstart(inode);
21607+ bend = au_ibend(inode);
21608+ if (bstart >= 0) {
21609+ for (bindex = bstart; bindex <= bend; bindex++) {
21610+ if (!au_h_iptr(inode, bindex)
21611+ || au_ii_br_id(inode, bindex) != br_id)
21612+ continue;
21613+ au_set_h_iptr(inode, bindex, NULL, 0);
21614+ do_put = 1;
21615+ break;
21616+ }
21617+ } else
21618+ do_put_plink(plink, 1);
21619+
dece6358
AM
21620+ if (do_put) {
21621+ for (bindex = bstart; bindex <= bend; bindex++)
21622+ if (au_h_iptr(inode, bindex)) {
21623+ do_put = 0;
21624+ break;
21625+ }
21626+ if (do_put)
21627+ do_put_plink(plink, 1);
21628+ }
21629+ ii_write_unlock(inode);
21630+ iput(inode);
21631+ }
21632+}
7f207e10
AM
21633diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
21634--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 21635+++ linux/fs/aufs/poll.c 2012-08-26 08:39:00.763841498 +0200
dece6358
AM
21636@@ -0,0 +1,56 @@
21637+/*
f6c5ef8b 21638+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
21639+ *
21640+ * This program, aufs is free software; you can redistribute it and/or modify
21641+ * it under the terms of the GNU General Public License as published by
21642+ * the Free Software Foundation; either version 2 of the License, or
21643+ * (at your option) any later version.
21644+ *
21645+ * This program is distributed in the hope that it will be useful,
21646+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21647+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21648+ * GNU General Public License for more details.
21649+ *
21650+ * You should have received a copy of the GNU General Public License
21651+ * along with this program; if not, write to the Free Software
21652+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21653+ */
21654+
1308ab2a 21655+/*
21656+ * poll operation
21657+ * There is only one filesystem which implements ->poll operation, currently.
21658+ */
21659+
21660+#include "aufs.h"
21661+
21662+unsigned int aufs_poll(struct file *file, poll_table *wait)
21663+{
21664+ unsigned int mask;
21665+ int err;
21666+ struct file *h_file;
21667+ struct dentry *dentry;
21668+ struct super_block *sb;
21669+
21670+ /* We should pretend an error happened. */
21671+ mask = POLLERR /* | POLLIN | POLLOUT */;
21672+ dentry = file->f_dentry;
21673+ sb = dentry->d_sb;
e49829fe 21674+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 21675+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
21676+ if (unlikely(err))
21677+ goto out;
21678+
21679+ /* it is not an error if h_file has no operation */
21680+ mask = DEFAULT_POLLMASK;
4a4d8108 21681+ h_file = au_hf_top(file);
1308ab2a 21682+ if (h_file->f_op && h_file->f_op->poll)
21683+ mask = h_file->f_op->poll(h_file, wait);
21684+
21685+ di_read_unlock(dentry, AuLock_IR);
21686+ fi_read_unlock(file);
21687+
4f0767ce 21688+out:
1308ab2a 21689+ si_read_unlock(sb);
21690+ AuTraceErr((int)mask);
21691+ return mask;
21692+}
7f207e10
AM
21693diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
21694--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 21695+++ linux/fs/aufs/procfs.c 2012-08-26 08:39:00.763841498 +0200
53392da6 21696@@ -0,0 +1,170 @@
e49829fe 21697+/*
f6c5ef8b 21698+ * Copyright (C) 2010-2012 Junjiro R. Okajima
e49829fe
JR
21699+ *
21700+ * This program, aufs is free software; you can redistribute it and/or modify
21701+ * it under the terms of the GNU General Public License as published by
21702+ * the Free Software Foundation; either version 2 of the License, or
21703+ * (at your option) any later version.
21704+ *
21705+ * This program is distributed in the hope that it will be useful,
21706+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21707+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21708+ * GNU General Public License for more details.
21709+ *
21710+ * You should have received a copy of the GNU General Public License
21711+ * along with this program; if not, write to the Free Software
21712+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21713+ */
21714+
21715+/*
21716+ * procfs interfaces
21717+ */
21718+
21719+#include <linux/proc_fs.h>
21720+#include "aufs.h"
21721+
21722+static int au_procfs_plm_release(struct inode *inode, struct file *file)
21723+{
21724+ struct au_sbinfo *sbinfo;
21725+
21726+ sbinfo = file->private_data;
21727+ if (sbinfo) {
21728+ au_plink_maint_leave(sbinfo);
21729+ kobject_put(&sbinfo->si_kobj);
21730+ }
21731+
21732+ return 0;
21733+}
21734+
21735+static void au_procfs_plm_write_clean(struct file *file)
21736+{
21737+ struct au_sbinfo *sbinfo;
21738+
21739+ sbinfo = file->private_data;
21740+ if (sbinfo)
21741+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
21742+}
21743+
21744+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
21745+{
21746+ int err;
21747+ struct super_block *sb;
21748+ struct au_sbinfo *sbinfo;
21749+
21750+ err = -EBUSY;
21751+ if (unlikely(file->private_data))
21752+ goto out;
21753+
21754+ sb = NULL;
53392da6 21755+ /* don't use au_sbilist_lock() here */
e49829fe
JR
21756+ spin_lock(&au_sbilist.spin);
21757+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
21758+ if (id == sysaufs_si_id(sbinfo)) {
21759+ kobject_get(&sbinfo->si_kobj);
21760+ sb = sbinfo->si_sb;
21761+ break;
21762+ }
21763+ spin_unlock(&au_sbilist.spin);
21764+
21765+ err = -EINVAL;
21766+ if (unlikely(!sb))
21767+ goto out;
21768+
21769+ err = au_plink_maint_enter(sb);
21770+ if (!err)
21771+ /* keep kobject_get() */
21772+ file->private_data = sbinfo;
21773+ else
21774+ kobject_put(&sbinfo->si_kobj);
21775+out:
21776+ return err;
21777+}
21778+
21779+/*
21780+ * Accept a valid "si=xxxx" only.
21781+ * Once it is accepted successfully, accept "clean" too.
21782+ */
21783+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
21784+ size_t count, loff_t *ppos)
21785+{
21786+ ssize_t err;
21787+ unsigned long id;
21788+ /* last newline is allowed */
21789+ char buf[3 + sizeof(unsigned long) * 2 + 1];
21790+
21791+ err = -EACCES;
21792+ if (unlikely(!capable(CAP_SYS_ADMIN)))
21793+ goto out;
21794+
21795+ err = -EINVAL;
21796+ if (unlikely(count > sizeof(buf)))
21797+ goto out;
21798+
21799+ err = copy_from_user(buf, ubuf, count);
21800+ if (unlikely(err)) {
21801+ err = -EFAULT;
21802+ goto out;
21803+ }
21804+ buf[count] = 0;
21805+
21806+ err = -EINVAL;
21807+ if (!strcmp("clean", buf)) {
21808+ au_procfs_plm_write_clean(file);
21809+ goto out_success;
21810+ } else if (unlikely(strncmp("si=", buf, 3)))
21811+ goto out;
21812+
9dbd164d 21813+ err = kstrtoul(buf + 3, 16, &id);
e49829fe
JR
21814+ if (unlikely(err))
21815+ goto out;
21816+
21817+ err = au_procfs_plm_write_si(file, id);
21818+ if (unlikely(err))
21819+ goto out;
21820+
21821+out_success:
21822+ err = count; /* success */
21823+out:
21824+ return err;
21825+}
21826+
21827+static const struct file_operations au_procfs_plm_fop = {
21828+ .write = au_procfs_plm_write,
21829+ .release = au_procfs_plm_release,
21830+ .owner = THIS_MODULE
21831+};
21832+
21833+/* ---------------------------------------------------------------------- */
21834+
21835+static struct proc_dir_entry *au_procfs_dir;
21836+
21837+void au_procfs_fin(void)
21838+{
21839+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
21840+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
21841+}
21842+
21843+int __init au_procfs_init(void)
21844+{
21845+ int err;
21846+ struct proc_dir_entry *entry;
21847+
21848+ err = -ENOMEM;
21849+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
21850+ if (unlikely(!au_procfs_dir))
21851+ goto out;
21852+
21853+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
21854+ au_procfs_dir, &au_procfs_plm_fop);
21855+ if (unlikely(!entry))
21856+ goto out_dir;
21857+
21858+ err = 0;
21859+ goto out; /* success */
21860+
21861+
21862+out_dir:
21863+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
21864+out:
21865+ return err;
21866+}
7f207e10
AM
21867diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
21868--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 21869+++ linux/fs/aufs/rdu.c 2012-08-26 08:39:00.763841498 +0200
92d182d2 21870@@ -0,0 +1,384 @@
1308ab2a 21871+/*
f6c5ef8b 21872+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1308ab2a 21873+ *
21874+ * This program, aufs is free software; you can redistribute it and/or modify
21875+ * it under the terms of the GNU General Public License as published by
21876+ * the Free Software Foundation; either version 2 of the License, or
21877+ * (at your option) any later version.
21878+ *
21879+ * This program is distributed in the hope that it will be useful,
21880+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21881+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21882+ * GNU General Public License for more details.
21883+ *
21884+ * You should have received a copy of the GNU General Public License
21885+ * along with this program; if not, write to the Free Software
21886+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21887+ */
21888+
21889+/*
21890+ * readdir in userspace.
21891+ */
21892+
b752ccd1 21893+#include <linux/compat.h>
4a4d8108 21894+#include <linux/fs_stack.h>
1308ab2a 21895+#include <linux/security.h>
1308ab2a 21896+#include "aufs.h"
21897+
21898+/* bits for struct aufs_rdu.flags */
21899+#define AuRdu_CALLED 1
21900+#define AuRdu_CONT (1 << 1)
21901+#define AuRdu_FULL (1 << 2)
21902+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
21903+#define au_fset_rdu(flags, name) \
21904+ do { (flags) |= AuRdu_##name; } while (0)
21905+#define au_fclr_rdu(flags, name) \
21906+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 21907+
21908+struct au_rdu_arg {
21909+ struct aufs_rdu *rdu;
21910+ union au_rdu_ent_ul ent;
21911+ unsigned long end;
21912+
21913+ struct super_block *sb;
21914+ int err;
21915+};
21916+
21917+static int au_rdu_fill(void *__arg, const char *name, int nlen,
21918+ loff_t offset, u64 h_ino, unsigned int d_type)
21919+{
21920+ int err, len;
21921+ struct au_rdu_arg *arg = __arg;
21922+ struct aufs_rdu *rdu = arg->rdu;
21923+ struct au_rdu_ent ent;
21924+
21925+ err = 0;
21926+ arg->err = 0;
21927+ au_fset_rdu(rdu->cookie.flags, CALLED);
21928+ len = au_rdu_len(nlen);
21929+ if (arg->ent.ul + len < arg->end) {
21930+ ent.ino = h_ino;
21931+ ent.bindex = rdu->cookie.bindex;
21932+ ent.type = d_type;
21933+ ent.nlen = nlen;
4a4d8108
AM
21934+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
21935+ ent.type = DT_UNKNOWN;
1308ab2a 21936+
9dbd164d 21937+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 21938+ err = -EFAULT;
21939+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
21940+ goto out;
21941+ if (copy_to_user(arg->ent.e->name, name, nlen))
21942+ goto out;
21943+ /* the terminating NULL */
21944+ if (__put_user(0, arg->ent.e->name + nlen))
21945+ goto out;
21946+ err = 0;
21947+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
21948+ arg->ent.ul += len;
21949+ rdu->rent++;
21950+ } else {
21951+ err = -EFAULT;
21952+ au_fset_rdu(rdu->cookie.flags, FULL);
21953+ rdu->full = 1;
21954+ rdu->tail = arg->ent;
21955+ }
21956+
4f0767ce 21957+out:
1308ab2a 21958+ /* AuTraceErr(err); */
21959+ return err;
21960+}
21961+
21962+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
21963+{
21964+ int err;
21965+ loff_t offset;
21966+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
21967+
92d182d2 21968+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
1308ab2a 21969+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
21970+ err = offset;
21971+ if (unlikely(offset != cookie->h_pos))
21972+ goto out;
21973+
21974+ err = 0;
21975+ do {
21976+ arg->err = 0;
21977+ au_fclr_rdu(cookie->flags, CALLED);
21978+ /* smp_mb(); */
21979+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
21980+ if (err >= 0)
21981+ err = arg->err;
21982+ } while (!err
21983+ && au_ftest_rdu(cookie->flags, CALLED)
21984+ && !au_ftest_rdu(cookie->flags, FULL));
21985+ cookie->h_pos = h_file->f_pos;
21986+
4f0767ce 21987+out:
1308ab2a 21988+ AuTraceErr(err);
21989+ return err;
21990+}
21991+
21992+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
21993+{
21994+ int err;
21995+ aufs_bindex_t bend;
21996+ struct au_rdu_arg arg;
21997+ struct dentry *dentry;
21998+ struct inode *inode;
21999+ struct file *h_file;
22000+ struct au_rdu_cookie *cookie = &rdu->cookie;
22001+
22002+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
22003+ if (unlikely(err)) {
22004+ err = -EFAULT;
22005+ AuTraceErr(err);
22006+ goto out;
22007+ }
22008+ rdu->rent = 0;
22009+ rdu->tail = rdu->ent;
22010+ rdu->full = 0;
22011+ arg.rdu = rdu;
22012+ arg.ent = rdu->ent;
22013+ arg.end = arg.ent.ul;
22014+ arg.end += rdu->sz;
22015+
22016+ err = -ENOTDIR;
22017+ if (unlikely(!file->f_op || !file->f_op->readdir))
22018+ goto out;
22019+
22020+ err = security_file_permission(file, MAY_READ);
22021+ AuTraceErr(err);
22022+ if (unlikely(err))
22023+ goto out;
22024+
22025+ dentry = file->f_dentry;
22026+ inode = dentry->d_inode;
22027+#if 1
22028+ mutex_lock(&inode->i_mutex);
22029+#else
22030+ err = mutex_lock_killable(&inode->i_mutex);
22031+ AuTraceErr(err);
22032+ if (unlikely(err))
22033+ goto out;
22034+#endif
1308ab2a 22035+
22036+ arg.sb = inode->i_sb;
e49829fe
JR
22037+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
22038+ if (unlikely(err))
22039+ goto out_mtx;
027c5e7a
AM
22040+ err = au_alive_dir(dentry);
22041+ if (unlikely(err))
22042+ goto out_si;
e49829fe 22043+ /* todo: reval? */
1308ab2a 22044+ fi_read_lock(file);
22045+
22046+ err = -EAGAIN;
22047+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
22048+ && cookie->generation != au_figen(file)))
22049+ goto out_unlock;
22050+
22051+ err = 0;
22052+ if (!rdu->blk) {
22053+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
22054+ if (!rdu->blk)
22055+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
22056+ }
22057+ bend = au_fbstart(file);
22058+ if (cookie->bindex < bend)
22059+ cookie->bindex = bend;
4a4d8108 22060+ bend = au_fbend_dir(file);
1308ab2a 22061+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
22062+ for (; !err && cookie->bindex <= bend;
22063+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 22064+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 22065+ if (!h_file)
22066+ continue;
22067+
22068+ au_fclr_rdu(cookie->flags, FULL);
22069+ err = au_rdu_do(h_file, &arg);
22070+ AuTraceErr(err);
22071+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
22072+ break;
22073+ }
22074+ AuDbg("rent %llu\n", rdu->rent);
22075+
22076+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
22077+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
22078+ au_fset_rdu(cookie->flags, CONT);
22079+ cookie->generation = au_figen(file);
22080+ }
22081+
22082+ ii_read_lock_child(inode);
22083+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
22084+ ii_read_unlock(inode);
22085+
4f0767ce 22086+out_unlock:
1308ab2a 22087+ fi_read_unlock(file);
027c5e7a 22088+out_si:
1308ab2a 22089+ si_read_unlock(arg.sb);
4f0767ce 22090+out_mtx:
1308ab2a 22091+ mutex_unlock(&inode->i_mutex);
4f0767ce 22092+out:
1308ab2a 22093+ AuTraceErr(err);
22094+ return err;
22095+}
22096+
22097+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
22098+{
22099+ int err;
22100+ ino_t ino;
22101+ unsigned long long nent;
22102+ union au_rdu_ent_ul *u;
22103+ struct au_rdu_ent ent;
22104+ struct super_block *sb;
22105+
22106+ err = 0;
22107+ nent = rdu->nent;
22108+ u = &rdu->ent;
22109+ sb = file->f_dentry->d_sb;
22110+ si_read_lock(sb, AuLock_FLUSH);
22111+ while (nent-- > 0) {
9dbd164d 22112+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 22113+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
22114+ if (!err)
22115+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 22116+ if (unlikely(err)) {
22117+ err = -EFAULT;
22118+ AuTraceErr(err);
22119+ break;
22120+ }
22121+
22122+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
22123+ if (!ent.wh)
22124+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
22125+ else
22126+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
22127+ &ino);
22128+ if (unlikely(err)) {
22129+ AuTraceErr(err);
22130+ break;
22131+ }
22132+
22133+ err = __put_user(ino, &u->e->ino);
22134+ if (unlikely(err)) {
22135+ err = -EFAULT;
22136+ AuTraceErr(err);
22137+ break;
22138+ }
22139+ u->ul += au_rdu_len(ent.nlen);
22140+ }
22141+ si_read_unlock(sb);
22142+
22143+ return err;
22144+}
22145+
22146+/* ---------------------------------------------------------------------- */
22147+
22148+static int au_rdu_verify(struct aufs_rdu *rdu)
22149+{
b752ccd1 22150+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 22151+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 22152+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 22153+ rdu->blk,
22154+ rdu->rent, rdu->shwh, rdu->full,
22155+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
22156+ rdu->cookie.generation);
dece6358 22157+
b752ccd1 22158+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 22159+ return 0;
dece6358 22160+
b752ccd1
AM
22161+ AuDbg("%u:%u\n",
22162+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 22163+ return -EINVAL;
22164+}
22165+
22166+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 22167+{
1308ab2a 22168+ long err, e;
22169+ struct aufs_rdu rdu;
22170+ void __user *p = (void __user *)arg;
dece6358 22171+
1308ab2a 22172+ err = copy_from_user(&rdu, p, sizeof(rdu));
22173+ if (unlikely(err)) {
22174+ err = -EFAULT;
22175+ AuTraceErr(err);
22176+ goto out;
22177+ }
22178+ err = au_rdu_verify(&rdu);
dece6358
AM
22179+ if (unlikely(err))
22180+ goto out;
22181+
1308ab2a 22182+ switch (cmd) {
22183+ case AUFS_CTL_RDU:
22184+ err = au_rdu(file, &rdu);
22185+ if (unlikely(err))
22186+ break;
dece6358 22187+
1308ab2a 22188+ e = copy_to_user(p, &rdu, sizeof(rdu));
22189+ if (unlikely(e)) {
22190+ err = -EFAULT;
22191+ AuTraceErr(err);
22192+ }
22193+ break;
22194+ case AUFS_CTL_RDU_INO:
22195+ err = au_rdu_ino(file, &rdu);
22196+ break;
22197+
22198+ default:
4a4d8108 22199+ /* err = -ENOTTY; */
1308ab2a 22200+ err = -EINVAL;
22201+ }
dece6358 22202+
4f0767ce 22203+out:
1308ab2a 22204+ AuTraceErr(err);
22205+ return err;
1facf9fc 22206+}
b752ccd1
AM
22207+
22208+#ifdef CONFIG_COMPAT
22209+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
22210+{
22211+ long err, e;
22212+ struct aufs_rdu rdu;
22213+ void __user *p = compat_ptr(arg);
22214+
22215+ /* todo: get_user()? */
22216+ err = copy_from_user(&rdu, p, sizeof(rdu));
22217+ if (unlikely(err)) {
22218+ err = -EFAULT;
22219+ AuTraceErr(err);
22220+ goto out;
22221+ }
22222+ rdu.ent.e = compat_ptr(rdu.ent.ul);
22223+ err = au_rdu_verify(&rdu);
22224+ if (unlikely(err))
22225+ goto out;
22226+
22227+ switch (cmd) {
22228+ case AUFS_CTL_RDU:
22229+ err = au_rdu(file, &rdu);
22230+ if (unlikely(err))
22231+ break;
22232+
22233+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
22234+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
22235+ e = copy_to_user(p, &rdu, sizeof(rdu));
22236+ if (unlikely(e)) {
22237+ err = -EFAULT;
22238+ AuTraceErr(err);
22239+ }
22240+ break;
22241+ case AUFS_CTL_RDU_INO:
22242+ err = au_rdu_ino(file, &rdu);
22243+ break;
22244+
22245+ default:
22246+ /* err = -ENOTTY; */
22247+ err = -EINVAL;
22248+ }
22249+
4f0767ce 22250+out:
b752ccd1
AM
22251+ AuTraceErr(err);
22252+ return err;
22253+}
22254+#endif
7f207e10
AM
22255diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
22256--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 22257+++ linux/fs/aufs/rwsem.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 22258@@ -0,0 +1,188 @@
1facf9fc 22259+/*
f6c5ef8b 22260+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22261+ *
22262+ * This program, aufs is free software; you can redistribute it and/or modify
22263+ * it under the terms of the GNU General Public License as published by
22264+ * the Free Software Foundation; either version 2 of the License, or
22265+ * (at your option) any later version.
dece6358
AM
22266+ *
22267+ * This program is distributed in the hope that it will be useful,
22268+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22269+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22270+ * GNU General Public License for more details.
22271+ *
22272+ * You should have received a copy of the GNU General Public License
22273+ * along with this program; if not, write to the Free Software
22274+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22275+ */
22276+
22277+/*
22278+ * simple read-write semaphore wrappers
22279+ */
22280+
22281+#ifndef __AUFS_RWSEM_H__
22282+#define __AUFS_RWSEM_H__
22283+
22284+#ifdef __KERNEL__
22285+
4a4d8108 22286+#include "debug.h"
dece6358
AM
22287+
22288+struct au_rwsem {
22289+ struct rw_semaphore rwsem;
22290+#ifdef CONFIG_AUFS_DEBUG
22291+ /* just for debugging, not almighty counter */
22292+ atomic_t rcnt, wcnt;
22293+#endif
22294+};
22295+
22296+#ifdef CONFIG_AUFS_DEBUG
22297+#define AuDbgCntInit(rw) do { \
22298+ atomic_set(&(rw)->rcnt, 0); \
22299+ atomic_set(&(rw)->wcnt, 0); \
22300+ smp_mb(); /* atomic set */ \
22301+} while (0)
22302+
e49829fe 22303+#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
dece6358 22304+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
e49829fe 22305+#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
dece6358
AM
22306+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
22307+#else
22308+#define AuDbgCntInit(rw) do {} while (0)
22309+#define AuDbgRcntInc(rw) do {} while (0)
22310+#define AuDbgRcntDec(rw) do {} while (0)
22311+#define AuDbgWcntInc(rw) do {} while (0)
22312+#define AuDbgWcntDec(rw) do {} while (0)
22313+#endif /* CONFIG_AUFS_DEBUG */
22314+
22315+/* to debug easier, do not make them inlined functions */
22316+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
22317+/* rwsem_is_locked() is unusable */
22318+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
22319+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
22320+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
22321+ && atomic_read(&(rw)->wcnt) <= 0)
22322+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
22323+ || atomic_read(&(rw)->wcnt))
22324+
e49829fe
JR
22325+#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
22326+
dece6358
AM
22327+static inline void au_rw_init(struct au_rwsem *rw)
22328+{
22329+ AuDbgCntInit(rw);
22330+ init_rwsem(&rw->rwsem);
22331+}
22332+
22333+static inline void au_rw_init_wlock(struct au_rwsem *rw)
22334+{
22335+ au_rw_init(rw);
22336+ down_write(&rw->rwsem);
22337+ AuDbgWcntInc(rw);
22338+}
22339+
22340+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
22341+ unsigned int lsc)
22342+{
22343+ au_rw_init(rw);
22344+ down_write_nested(&rw->rwsem, lsc);
22345+ AuDbgWcntInc(rw);
22346+}
22347+
22348+static inline void au_rw_read_lock(struct au_rwsem *rw)
22349+{
22350+ down_read(&rw->rwsem);
22351+ AuDbgRcntInc(rw);
22352+}
22353+
22354+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
22355+{
22356+ down_read_nested(&rw->rwsem, lsc);
22357+ AuDbgRcntInc(rw);
22358+}
22359+
22360+static inline void au_rw_read_unlock(struct au_rwsem *rw)
22361+{
22362+ AuRwMustReadLock(rw);
22363+ AuDbgRcntDec(rw);
22364+ up_read(&rw->rwsem);
22365+}
22366+
22367+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
22368+{
22369+ AuRwMustWriteLock(rw);
22370+ AuDbgRcntInc(rw);
22371+ AuDbgWcntDec(rw);
22372+ downgrade_write(&rw->rwsem);
22373+}
22374+
22375+static inline void au_rw_write_lock(struct au_rwsem *rw)
22376+{
22377+ down_write(&rw->rwsem);
22378+ AuDbgWcntInc(rw);
22379+}
22380+
22381+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
22382+ unsigned int lsc)
22383+{
22384+ down_write_nested(&rw->rwsem, lsc);
22385+ AuDbgWcntInc(rw);
22386+}
1facf9fc 22387+
dece6358
AM
22388+static inline void au_rw_write_unlock(struct au_rwsem *rw)
22389+{
22390+ AuRwMustWriteLock(rw);
22391+ AuDbgWcntDec(rw);
22392+ up_write(&rw->rwsem);
22393+}
22394+
22395+/* why is not _nested version defined */
22396+static inline int au_rw_read_trylock(struct au_rwsem *rw)
22397+{
22398+ int ret = down_read_trylock(&rw->rwsem);
22399+ if (ret)
22400+ AuDbgRcntInc(rw);
22401+ return ret;
22402+}
22403+
22404+static inline int au_rw_write_trylock(struct au_rwsem *rw)
22405+{
22406+ int ret = down_write_trylock(&rw->rwsem);
22407+ if (ret)
22408+ AuDbgWcntInc(rw);
22409+ return ret;
22410+}
22411+
22412+#undef AuDbgCntInit
22413+#undef AuDbgRcntInc
22414+#undef AuDbgRcntDec
22415+#undef AuDbgWcntInc
22416+#undef AuDbgWcntDec
1facf9fc 22417+
22418+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
22419+static inline void prefix##_read_lock(param) \
dece6358 22420+{ au_rw_read_lock(rwsem); } \
1facf9fc 22421+static inline void prefix##_write_lock(param) \
dece6358 22422+{ au_rw_write_lock(rwsem); } \
1facf9fc 22423+static inline int prefix##_read_trylock(param) \
dece6358 22424+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 22425+static inline int prefix##_write_trylock(param) \
dece6358 22426+{ return au_rw_write_trylock(rwsem); }
1facf9fc 22427+/* why is not _nested version defined */
22428+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 22429+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 22430+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 22431+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 22432+
22433+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
22434+static inline void prefix##_read_unlock(param) \
dece6358 22435+{ au_rw_read_unlock(rwsem); } \
1facf9fc 22436+static inline void prefix##_write_unlock(param) \
dece6358 22437+{ au_rw_write_unlock(rwsem); } \
1facf9fc 22438+static inline void prefix##_downgrade_lock(param) \
dece6358 22439+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 22440+
22441+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
22442+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
22443+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
22444+
22445+#endif /* __KERNEL__ */
22446+#endif /* __AUFS_RWSEM_H__ */
7f207e10
AM
22447diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
22448--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 22449+++ linux/fs/aufs/sbinfo.c 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 22450@@ -0,0 +1,343 @@
1facf9fc 22451+/*
f6c5ef8b 22452+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22453+ *
22454+ * This program, aufs is free software; you can redistribute it and/or modify
22455+ * it under the terms of the GNU General Public License as published by
22456+ * the Free Software Foundation; either version 2 of the License, or
22457+ * (at your option) any later version.
dece6358
AM
22458+ *
22459+ * This program is distributed in the hope that it will be useful,
22460+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22461+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22462+ * GNU General Public License for more details.
22463+ *
22464+ * You should have received a copy of the GNU General Public License
22465+ * along with this program; if not, write to the Free Software
22466+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22467+ */
22468+
22469+/*
22470+ * superblock private data
22471+ */
22472+
22473+#include "aufs.h"
22474+
22475+/*
22476+ * they are necessary regardless sysfs is disabled.
22477+ */
22478+void au_si_free(struct kobject *kobj)
22479+{
22480+ struct au_sbinfo *sbinfo;
b752ccd1 22481+ char *locked __maybe_unused; /* debug only */
1facf9fc 22482+
22483+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
22484+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
e49829fe 22485+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
1facf9fc 22486+
e49829fe 22487+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 22488+ au_br_free(sbinfo);
e49829fe 22489+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1
AM
22490+
22491+ AuDebugOn(radix_tree_gang_lookup
22492+ (&sbinfo->au_si_pid.tree, (void **)&locked,
22493+ /*first_index*/PID_MAX_DEFAULT - 1,
22494+ /*max_items*/sizeof(locked)/sizeof(*locked)));
22495+
1facf9fc 22496+ kfree(sbinfo->si_branch);
b752ccd1 22497+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 22498+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 22499+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 22500+
22501+ kfree(sbinfo);
22502+}
22503+
22504+int au_si_alloc(struct super_block *sb)
22505+{
22506+ int err;
22507+ struct au_sbinfo *sbinfo;
e49829fe 22508+ static struct lock_class_key aufs_si;
1facf9fc 22509+
22510+ err = -ENOMEM;
4a4d8108 22511+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 22512+ if (unlikely(!sbinfo))
22513+ goto out;
22514+
b752ccd1
AM
22515+ BUILD_BUG_ON(sizeof(unsigned long) !=
22516+ sizeof(*sbinfo->au_si_pid.bitmap));
22517+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
22518+ sizeof(*sbinfo->au_si_pid.bitmap),
22519+ GFP_NOFS);
22520+ if (unlikely(!sbinfo->au_si_pid.bitmap))
22521+ goto out_sbinfo;
22522+
1facf9fc 22523+ /* will be reallocated separately */
22524+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
22525+ if (unlikely(!sbinfo->si_branch))
b752ccd1 22526+ goto out_pidmap;
1facf9fc 22527+
1facf9fc 22528+ err = sysaufs_si_init(sbinfo);
22529+ if (unlikely(err))
22530+ goto out_br;
22531+
22532+ au_nwt_init(&sbinfo->si_nowait);
dece6358 22533+ au_rw_init_wlock(&sbinfo->si_rwsem);
e49829fe 22534+ au_rw_class(&sbinfo->si_rwsem, &aufs_si);
b752ccd1
AM
22535+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
22536+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
22537+
7f207e10 22538+ atomic_long_set(&sbinfo->si_ninodes, 0);
7f207e10
AM
22539+ atomic_long_set(&sbinfo->si_nfiles, 0);
22540+
1facf9fc 22541+ sbinfo->si_bend = -1;
1facf9fc 22542+
22543+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
22544+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
22545+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
22546+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 22547+
e49829fe 22548+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 22549+
1facf9fc 22550+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 22551+ sbinfo->si_xino_brid = -1;
22552+ /* leave si_xib_last_pindex and si_xib_next_bit */
22553+
e49829fe 22554+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 22555+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
22556+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
22557+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
22558+
22559+ au_spl_init(&sbinfo->si_plink);
22560+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 22561+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 22562+
22563+ /* leave other members for sysaufs and si_mnt. */
22564+ sbinfo->si_sb = sb;
22565+ sb->s_fs_info = sbinfo;
b752ccd1 22566+ si_pid_set(sb);
1facf9fc 22567+ au_debug_sbinfo_init(sbinfo);
22568+ return 0; /* success */
22569+
4f0767ce 22570+out_br:
1facf9fc 22571+ kfree(sbinfo->si_branch);
4f0767ce 22572+out_pidmap:
b752ccd1 22573+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 22574+out_sbinfo:
1facf9fc 22575+ kfree(sbinfo);
4f0767ce 22576+out:
1facf9fc 22577+ return err;
22578+}
22579+
22580+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
22581+{
22582+ int err, sz;
22583+ struct au_branch **brp;
22584+
dece6358
AM
22585+ AuRwMustWriteLock(&sbinfo->si_rwsem);
22586+
1facf9fc 22587+ err = -ENOMEM;
22588+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
22589+ if (unlikely(!sz))
22590+ sz = sizeof(*brp);
22591+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
22592+ if (brp) {
22593+ sbinfo->si_branch = brp;
22594+ err = 0;
22595+ }
22596+
22597+ return err;
22598+}
22599+
22600+/* ---------------------------------------------------------------------- */
22601+
22602+unsigned int au_sigen_inc(struct super_block *sb)
22603+{
22604+ unsigned int gen;
22605+
dece6358
AM
22606+ SiMustWriteLock(sb);
22607+
1facf9fc 22608+ gen = ++au_sbi(sb)->si_generation;
22609+ au_update_digen(sb->s_root);
22610+ au_update_iigen(sb->s_root->d_inode);
22611+ sb->s_root->d_inode->i_version++;
22612+ return gen;
22613+}
22614+
22615+aufs_bindex_t au_new_br_id(struct super_block *sb)
22616+{
22617+ aufs_bindex_t br_id;
22618+ int i;
22619+ struct au_sbinfo *sbinfo;
22620+
dece6358
AM
22621+ SiMustWriteLock(sb);
22622+
1facf9fc 22623+ sbinfo = au_sbi(sb);
22624+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
22625+ br_id = ++sbinfo->si_last_br_id;
7f207e10 22626+ AuDebugOn(br_id < 0);
1facf9fc 22627+ if (br_id && au_br_index(sb, br_id) < 0)
22628+ return br_id;
22629+ }
22630+
22631+ return -1;
22632+}
22633+
22634+/* ---------------------------------------------------------------------- */
22635+
e49829fe
JR
22636+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
22637+int si_read_lock(struct super_block *sb, int flags)
22638+{
22639+ int err;
22640+
22641+ err = 0;
22642+ if (au_ftest_lock(flags, FLUSH))
22643+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22644+
22645+ si_noflush_read_lock(sb);
22646+ err = au_plink_maint(sb, flags);
22647+ if (unlikely(err))
22648+ si_read_unlock(sb);
22649+
22650+ return err;
22651+}
22652+
22653+int si_write_lock(struct super_block *sb, int flags)
22654+{
22655+ int err;
22656+
22657+ if (au_ftest_lock(flags, FLUSH))
22658+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22659+
22660+ si_noflush_write_lock(sb);
22661+ err = au_plink_maint(sb, flags);
22662+ if (unlikely(err))
22663+ si_write_unlock(sb);
22664+
22665+ return err;
22666+}
22667+
1facf9fc 22668+/* dentry and super_block lock. call at entry point */
e49829fe 22669+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 22670+{
e49829fe 22671+ int err;
027c5e7a 22672+ struct super_block *sb;
e49829fe 22673+
027c5e7a
AM
22674+ sb = dentry->d_sb;
22675+ err = si_read_lock(sb, flags);
22676+ if (unlikely(err))
22677+ goto out;
22678+
22679+ if (au_ftest_lock(flags, DW))
22680+ di_write_lock_child(dentry);
22681+ else
22682+ di_read_lock_child(dentry, flags);
22683+
22684+ if (au_ftest_lock(flags, GEN)) {
22685+ err = au_digen_test(dentry, au_sigen(sb));
22686+ AuDebugOn(!err && au_dbrange_test(dentry));
22687+ if (unlikely(err))
22688+ aufs_read_unlock(dentry, flags);
e49829fe
JR
22689+ }
22690+
027c5e7a 22691+out:
e49829fe 22692+ return err;
1facf9fc 22693+}
22694+
22695+void aufs_read_unlock(struct dentry *dentry, int flags)
22696+{
22697+ if (au_ftest_lock(flags, DW))
22698+ di_write_unlock(dentry);
22699+ else
22700+ di_read_unlock(dentry, flags);
22701+ si_read_unlock(dentry->d_sb);
22702+}
22703+
22704+void aufs_write_lock(struct dentry *dentry)
22705+{
e49829fe 22706+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 22707+ di_write_lock_child(dentry);
22708+}
22709+
22710+void aufs_write_unlock(struct dentry *dentry)
22711+{
22712+ di_write_unlock(dentry);
22713+ si_write_unlock(dentry->d_sb);
22714+}
22715+
e49829fe 22716+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 22717+{
e49829fe 22718+ int err;
027c5e7a
AM
22719+ unsigned int sigen;
22720+ struct super_block *sb;
e49829fe 22721+
027c5e7a
AM
22722+ sb = d1->d_sb;
22723+ err = si_read_lock(sb, flags);
22724+ if (unlikely(err))
22725+ goto out;
22726+
22727+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
22728+
22729+ if (au_ftest_lock(flags, GEN)) {
22730+ sigen = au_sigen(sb);
22731+ err = au_digen_test(d1, sigen);
22732+ AuDebugOn(!err && au_dbrange_test(d1));
22733+ if (!err) {
22734+ err = au_digen_test(d2, sigen);
22735+ AuDebugOn(!err && au_dbrange_test(d2));
22736+ }
22737+ if (unlikely(err))
22738+ aufs_read_and_write_unlock2(d1, d2);
22739+ }
22740+
22741+out:
e49829fe 22742+ return err;
1facf9fc 22743+}
22744+
22745+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
22746+{
22747+ di_write_unlock2(d1, d2);
22748+ si_read_unlock(d1->d_sb);
22749+}
b752ccd1
AM
22750+
22751+/* ---------------------------------------------------------------------- */
22752+
22753+int si_pid_test_slow(struct super_block *sb)
22754+{
22755+ void *p;
22756+
22757+ rcu_read_lock();
22758+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
22759+ rcu_read_unlock();
22760+
027c5e7a 22761+ return (long)!!p;
b752ccd1
AM
22762+}
22763+
22764+void si_pid_set_slow(struct super_block *sb)
22765+{
22766+ int err;
22767+ struct au_sbinfo *sbinfo;
22768+
22769+ AuDebugOn(si_pid_test_slow(sb));
22770+
22771+ sbinfo = au_sbi(sb);
22772+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
22773+ AuDebugOn(err);
22774+ spin_lock(&sbinfo->au_si_pid.tree_lock);
22775+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
027c5e7a 22776+ /*any valid ptr*/sb);
b752ccd1
AM
22777+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
22778+ AuDebugOn(err);
22779+ radix_tree_preload_end();
22780+}
22781+
22782+void si_pid_clr_slow(struct super_block *sb)
22783+{
22784+ void *p;
22785+ struct au_sbinfo *sbinfo;
22786+
22787+ AuDebugOn(!si_pid_test_slow(sb));
22788+
22789+ sbinfo = au_sbi(sb);
22790+ spin_lock(&sbinfo->au_si_pid.tree_lock);
22791+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
22792+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
b752ccd1 22793+}
7f207e10
AM
22794diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
22795--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 22796+++ linux/fs/aufs/spl.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 22797@@ -0,0 +1,62 @@
1facf9fc 22798+/*
f6c5ef8b 22799+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22800+ *
22801+ * This program, aufs is free software; you can redistribute it and/or modify
22802+ * it under the terms of the GNU General Public License as published by
22803+ * the Free Software Foundation; either version 2 of the License, or
22804+ * (at your option) any later version.
dece6358
AM
22805+ *
22806+ * This program is distributed in the hope that it will be useful,
22807+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22808+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22809+ * GNU General Public License for more details.
22810+ *
22811+ * You should have received a copy of the GNU General Public License
22812+ * along with this program; if not, write to the Free Software
22813+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22814+ */
22815+
22816+/*
22817+ * simple list protected by a spinlock
22818+ */
22819+
22820+#ifndef __AUFS_SPL_H__
22821+#define __AUFS_SPL_H__
22822+
22823+#ifdef __KERNEL__
22824+
1facf9fc 22825+struct au_splhead {
22826+ spinlock_t spin;
22827+ struct list_head head;
22828+};
22829+
22830+static inline void au_spl_init(struct au_splhead *spl)
22831+{
22832+ spin_lock_init(&spl->spin);
22833+ INIT_LIST_HEAD(&spl->head);
22834+}
22835+
22836+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
22837+{
22838+ spin_lock(&spl->spin);
22839+ list_add(list, &spl->head);
22840+ spin_unlock(&spl->spin);
22841+}
22842+
22843+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
22844+{
22845+ spin_lock(&spl->spin);
22846+ list_del(list);
22847+ spin_unlock(&spl->spin);
22848+}
22849+
4a4d8108
AM
22850+static inline void au_spl_del_rcu(struct list_head *list,
22851+ struct au_splhead *spl)
22852+{
22853+ spin_lock(&spl->spin);
22854+ list_del_rcu(list);
22855+ spin_unlock(&spl->spin);
22856+}
22857+
1facf9fc 22858+#endif /* __KERNEL__ */
22859+#endif /* __AUFS_SPL_H__ */
7f207e10
AM
22860diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
22861--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 22862+++ linux/fs/aufs/super.c 2012-08-26 08:39:00.763841498 +0200
92d182d2 22863@@ -0,0 +1,962 @@
1facf9fc 22864+/*
f6c5ef8b 22865+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22866+ *
22867+ * This program, aufs is free software; you can redistribute it and/or modify
22868+ * it under the terms of the GNU General Public License as published by
22869+ * the Free Software Foundation; either version 2 of the License, or
22870+ * (at your option) any later version.
dece6358
AM
22871+ *
22872+ * This program is distributed in the hope that it will be useful,
22873+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22874+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22875+ * GNU General Public License for more details.
22876+ *
22877+ * You should have received a copy of the GNU General Public License
22878+ * along with this program; if not, write to the Free Software
22879+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22880+ */
22881+
22882+/*
22883+ * mount and super_block operations
22884+ */
22885+
f6c5ef8b 22886+#include <linux/mm.h>
dece6358 22887+#include <linux/module.h>
1facf9fc 22888+#include <linux/seq_file.h>
22889+#include <linux/statfs.h>
7f207e10
AM
22890+#include <linux/vmalloc.h>
22891+#include <linux/writeback.h>
1facf9fc 22892+#include "aufs.h"
22893+
22894+/*
22895+ * super_operations
22896+ */
22897+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
22898+{
22899+ struct au_icntnr *c;
22900+
22901+ c = au_cache_alloc_icntnr();
22902+ if (c) {
027c5e7a 22903+ au_icntnr_init(c);
1facf9fc 22904+ c->vfs_inode.i_version = 1; /* sigen(sb); */
22905+ c->iinfo.ii_hinode = NULL;
22906+ return &c->vfs_inode;
22907+ }
22908+ return NULL;
22909+}
22910+
027c5e7a
AM
22911+static void aufs_destroy_inode_cb(struct rcu_head *head)
22912+{
22913+ struct inode *inode = container_of(head, struct inode, i_rcu);
22914+
22915+ INIT_LIST_HEAD(&inode->i_dentry);
22916+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
22917+}
22918+
1facf9fc 22919+static void aufs_destroy_inode(struct inode *inode)
22920+{
22921+ au_iinfo_fin(inode);
027c5e7a 22922+ call_rcu(&inode->i_rcu, aufs_destroy_inode_cb);
1facf9fc 22923+}
22924+
22925+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
22926+{
22927+ struct inode *inode;
22928+ int err;
22929+
22930+ inode = iget_locked(sb, ino);
22931+ if (unlikely(!inode)) {
22932+ inode = ERR_PTR(-ENOMEM);
22933+ goto out;
22934+ }
22935+ if (!(inode->i_state & I_NEW))
22936+ goto out;
22937+
22938+ err = au_xigen_new(inode);
22939+ if (!err)
22940+ err = au_iinfo_init(inode);
22941+ if (!err)
22942+ inode->i_version++;
22943+ else {
22944+ iget_failed(inode);
22945+ inode = ERR_PTR(err);
22946+ }
22947+
4f0767ce 22948+out:
1facf9fc 22949+ /* never return NULL */
22950+ AuDebugOn(!inode);
22951+ AuTraceErrPtr(inode);
22952+ return inode;
22953+}
22954+
22955+/* lock free root dinfo */
22956+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
22957+{
22958+ int err;
22959+ aufs_bindex_t bindex, bend;
22960+ struct path path;
4a4d8108 22961+ struct au_hdentry *hdp;
1facf9fc 22962+ struct au_branch *br;
1e00d052 22963+ char *perm;
1facf9fc 22964+
22965+ err = 0;
22966+ bend = au_sbend(sb);
4a4d8108 22967+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 22968+ for (bindex = 0; !err && bindex <= bend; bindex++) {
22969+ br = au_sbr(sb, bindex);
22970+ path.mnt = br->br_mnt;
4a4d8108 22971+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 22972+ err = au_seq_path(seq, &path);
1e00d052
AM
22973+ if (err > 0) {
22974+ perm = au_optstr_br_perm(br->br_perm);
22975+ if (perm) {
22976+ err = seq_printf(seq, "=%s", perm);
22977+ kfree(perm);
22978+ if (err == -1)
22979+ err = -E2BIG;
22980+ } else
22981+ err = -ENOMEM;
22982+ }
1facf9fc 22983+ if (!err && bindex != bend)
22984+ err = seq_putc(seq, ':');
22985+ }
22986+
22987+ return err;
22988+}
22989+
22990+static void au_show_wbr_create(struct seq_file *m, int v,
22991+ struct au_sbinfo *sbinfo)
22992+{
22993+ const char *pat;
22994+
dece6358
AM
22995+ AuRwMustAnyLock(&sbinfo->si_rwsem);
22996+
1facf9fc 22997+ seq_printf(m, ",create=");
22998+ pat = au_optstr_wbr_create(v);
22999+ switch (v) {
23000+ case AuWbrCreate_TDP:
23001+ case AuWbrCreate_RR:
23002+ case AuWbrCreate_MFS:
23003+ case AuWbrCreate_PMFS:
23004+ seq_printf(m, pat);
23005+ break;
23006+ case AuWbrCreate_MFSV:
23007+ seq_printf(m, /*pat*/"mfs:%lu",
e49829fe
JR
23008+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
23009+ / MSEC_PER_SEC);
1facf9fc 23010+ break;
23011+ case AuWbrCreate_PMFSV:
23012+ seq_printf(m, /*pat*/"pmfs:%lu",
e49829fe
JR
23013+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
23014+ / MSEC_PER_SEC);
1facf9fc 23015+ break;
23016+ case AuWbrCreate_MFSRR:
23017+ seq_printf(m, /*pat*/"mfsrr:%llu",
23018+ sbinfo->si_wbr_mfs.mfsrr_watermark);
23019+ break;
23020+ case AuWbrCreate_MFSRRV:
23021+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
23022+ sbinfo->si_wbr_mfs.mfsrr_watermark,
e49829fe
JR
23023+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
23024+ / MSEC_PER_SEC);
1facf9fc 23025+ break;
23026+ }
23027+}
23028+
7eafdf33 23029+static int au_show_xino(struct seq_file *seq, struct super_block *sb)
1facf9fc 23030+{
23031+#ifdef CONFIG_SYSFS
23032+ return 0;
23033+#else
23034+ int err;
23035+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
23036+ aufs_bindex_t bindex, brid;
1facf9fc 23037+ struct qstr *name;
23038+ struct file *f;
23039+ struct dentry *d, *h_root;
4a4d8108 23040+ struct au_hdentry *hdp;
1facf9fc 23041+
dece6358
AM
23042+ AuRwMustAnyLock(&sbinfo->si_rwsem);
23043+
1facf9fc 23044+ err = 0;
1facf9fc 23045+ f = au_sbi(sb)->si_xib;
23046+ if (!f)
23047+ goto out;
23048+
23049+ /* stop printing the default xino path on the first writable branch */
23050+ h_root = NULL;
23051+ brid = au_xino_brid(sb);
23052+ if (brid >= 0) {
23053+ bindex = au_br_index(sb, brid);
4a4d8108
AM
23054+ hdp = au_di(sb->s_root)->di_hdentry;
23055+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 23056+ }
23057+ d = f->f_dentry;
23058+ name = &d->d_name;
23059+ /* safe ->d_parent because the file is unlinked */
23060+ if (d->d_parent == h_root
23061+ && name->len == len
23062+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
23063+ goto out;
23064+
23065+ seq_puts(seq, ",xino=");
23066+ err = au_xino_path(seq, f);
23067+
4f0767ce 23068+out:
1facf9fc 23069+ return err;
23070+#endif
23071+}
23072+
23073+/* seq_file will re-call me in case of too long string */
7eafdf33 23074+static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
1facf9fc 23075+{
027c5e7a 23076+ int err;
1facf9fc 23077+ unsigned int mnt_flags, v;
23078+ struct super_block *sb;
23079+ struct au_sbinfo *sbinfo;
23080+
23081+#define AuBool(name, str) do { \
23082+ v = au_opt_test(mnt_flags, name); \
23083+ if (v != au_opt_test(AuOpt_Def, name)) \
23084+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
23085+} while (0)
23086+
23087+#define AuStr(name, str) do { \
23088+ v = mnt_flags & AuOptMask_##name; \
23089+ if (v != (AuOpt_Def & AuOptMask_##name)) \
23090+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
23091+} while (0)
23092+
23093+#define AuUInt(name, str, val) do { \
23094+ if (val != AUFS_##name##_DEF) \
23095+ seq_printf(m, "," #str "=%u", val); \
23096+} while (0)
23097+
23098+ /* lock free root dinfo */
7eafdf33 23099+ sb = dentry->d_sb;
1facf9fc 23100+ si_noflush_read_lock(sb);
23101+ sbinfo = au_sbi(sb);
23102+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
23103+
23104+ mnt_flags = au_mntflags(sb);
23105+ if (au_opt_test(mnt_flags, XINO)) {
7eafdf33 23106+ err = au_show_xino(m, sb);
1facf9fc 23107+ if (unlikely(err))
23108+ goto out;
23109+ } else
23110+ seq_puts(m, ",noxino");
23111+
23112+ AuBool(TRUNC_XINO, trunc_xino);
23113+ AuStr(UDBA, udba);
dece6358 23114+ AuBool(SHWH, shwh);
1facf9fc 23115+ AuBool(PLINK, plink);
4a4d8108 23116+ AuBool(DIO, dio);
1facf9fc 23117+ /* AuBool(DIRPERM1, dirperm1); */
23118+ /* AuBool(REFROF, refrof); */
23119+
23120+ v = sbinfo->si_wbr_create;
23121+ if (v != AuWbrCreate_Def)
23122+ au_show_wbr_create(m, v, sbinfo);
23123+
23124+ v = sbinfo->si_wbr_copyup;
23125+ if (v != AuWbrCopyup_Def)
23126+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
23127+
23128+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
23129+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
23130+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
23131+
23132+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
23133+
027c5e7a
AM
23134+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
23135+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 23136+
23137+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
23138+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
23139+
23140+ AuBool(SUM, sum);
23141+ /* AuBool(SUM_W, wsum); */
23142+ AuBool(WARN_PERM, warn_perm);
23143+ AuBool(VERBOSE, verbose);
23144+
4f0767ce 23145+out:
1facf9fc 23146+ /* be sure to print "br:" last */
23147+ if (!sysaufs_brs) {
23148+ seq_puts(m, ",br:");
23149+ au_show_brs(m, sb);
23150+ }
23151+ si_read_unlock(sb);
23152+ return 0;
23153+
1facf9fc 23154+#undef AuBool
23155+#undef AuStr
4a4d8108 23156+#undef AuUInt
1facf9fc 23157+}
23158+
23159+/* ---------------------------------------------------------------------- */
23160+
23161+/* sum mode which returns the summation for statfs(2) */
23162+
23163+static u64 au_add_till_max(u64 a, u64 b)
23164+{
23165+ u64 old;
23166+
23167+ old = a;
23168+ a += b;
92d182d2
AM
23169+ if (old <= a)
23170+ return a;
23171+ return ULLONG_MAX;
23172+}
23173+
23174+static u64 au_mul_till_max(u64 a, long mul)
23175+{
23176+ u64 old;
23177+
23178+ old = a;
23179+ a *= mul;
23180+ if (old <= a)
1facf9fc 23181+ return a;
23182+ return ULLONG_MAX;
23183+}
23184+
23185+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
23186+{
23187+ int err;
92d182d2 23188+ long bsize, factor;
1facf9fc 23189+ u64 blocks, bfree, bavail, files, ffree;
23190+ aufs_bindex_t bend, bindex, i;
23191+ unsigned char shared;
7f207e10 23192+ struct path h_path;
1facf9fc 23193+ struct super_block *h_sb;
23194+
92d182d2
AM
23195+ err = 0;
23196+ bsize = LONG_MAX;
23197+ files = 0;
23198+ ffree = 0;
1facf9fc 23199+ blocks = 0;
23200+ bfree = 0;
23201+ bavail = 0;
1facf9fc 23202+ bend = au_sbend(sb);
92d182d2 23203+ for (bindex = 0; bindex <= bend; bindex++) {
7f207e10
AM
23204+ h_path.mnt = au_sbr_mnt(sb, bindex);
23205+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 23206+ shared = 0;
92d182d2 23207+ for (i = 0; !shared && i < bindex; i++)
1facf9fc 23208+ shared = (au_sbr_sb(sb, i) == h_sb);
23209+ if (shared)
23210+ continue;
23211+
23212+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
23213+ h_path.dentry = h_path.mnt->mnt_root;
23214+ err = vfs_statfs(&h_path, buf);
1facf9fc 23215+ if (unlikely(err))
23216+ goto out;
23217+
92d182d2
AM
23218+ if (bsize > buf->f_bsize) {
23219+ /*
23220+ * we will reduce bsize, so we have to expand blocks
23221+ * etc. to match them again
23222+ */
23223+ factor = (bsize / buf->f_bsize);
23224+ blocks = au_mul_till_max(blocks, factor);
23225+ bfree = au_mul_till_max(bfree, factor);
23226+ bavail = au_mul_till_max(bavail, factor);
23227+ bsize = buf->f_bsize;
23228+ }
23229+
23230+ factor = (buf->f_bsize / bsize);
23231+ blocks = au_add_till_max(blocks,
23232+ au_mul_till_max(buf->f_blocks, factor));
23233+ bfree = au_add_till_max(bfree,
23234+ au_mul_till_max(buf->f_bfree, factor));
23235+ bavail = au_add_till_max(bavail,
23236+ au_mul_till_max(buf->f_bavail, factor));
1facf9fc 23237+ files = au_add_till_max(files, buf->f_files);
23238+ ffree = au_add_till_max(ffree, buf->f_ffree);
23239+ }
23240+
92d182d2 23241+ buf->f_bsize = bsize;
1facf9fc 23242+ buf->f_blocks = blocks;
23243+ buf->f_bfree = bfree;
23244+ buf->f_bavail = bavail;
23245+ buf->f_files = files;
23246+ buf->f_ffree = ffree;
92d182d2 23247+ buf->f_frsize = 0;
1facf9fc 23248+
4f0767ce 23249+out:
1facf9fc 23250+ return err;
23251+}
23252+
23253+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
23254+{
23255+ int err;
7f207e10 23256+ struct path h_path;
1facf9fc 23257+ struct super_block *sb;
23258+
23259+ /* lock free root dinfo */
23260+ sb = dentry->d_sb;
23261+ si_noflush_read_lock(sb);
7f207e10 23262+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 23263+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
23264+ h_path.mnt = au_sbr_mnt(sb, 0);
23265+ h_path.dentry = h_path.mnt->mnt_root;
23266+ err = vfs_statfs(&h_path, buf);
23267+ } else
1facf9fc 23268+ err = au_statfs_sum(sb, buf);
23269+ si_read_unlock(sb);
23270+
23271+ if (!err) {
23272+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 23273+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 23274+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
23275+ }
23276+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
23277+
23278+ return err;
23279+}
23280+
23281+/* ---------------------------------------------------------------------- */
23282+
1facf9fc 23283+/* final actions when unmounting a file system */
23284+static void aufs_put_super(struct super_block *sb)
23285+{
23286+ struct au_sbinfo *sbinfo;
23287+
23288+ sbinfo = au_sbi(sb);
23289+ if (!sbinfo)
23290+ return;
23291+
1facf9fc 23292+ dbgaufs_si_fin(sbinfo);
23293+ kobject_put(&sbinfo->si_kobj);
23294+}
23295+
23296+/* ---------------------------------------------------------------------- */
23297+
7f207e10
AM
23298+void au_array_free(void *array)
23299+{
23300+ if (array) {
23301+ if (!is_vmalloc_addr(array))
23302+ kfree(array);
23303+ else
23304+ vfree(array);
23305+ }
23306+}
23307+
23308+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
23309+{
23310+ void *array;
23311+ unsigned long long n;
23312+
23313+ array = NULL;
23314+ n = 0;
23315+ if (!*hint)
23316+ goto out;
23317+
23318+ if (*hint > ULLONG_MAX / sizeof(array)) {
23319+ array = ERR_PTR(-EMFILE);
23320+ pr_err("hint %llu\n", *hint);
23321+ goto out;
23322+ }
23323+
23324+ array = kmalloc(sizeof(array) * *hint, GFP_NOFS);
23325+ if (unlikely(!array))
23326+ array = vmalloc(sizeof(array) * *hint);
23327+ if (unlikely(!array)) {
23328+ array = ERR_PTR(-ENOMEM);
23329+ goto out;
23330+ }
23331+
23332+ n = cb(array, *hint, arg);
23333+ AuDebugOn(n > *hint);
23334+
23335+out:
23336+ *hint = n;
23337+ return array;
23338+}
23339+
23340+static unsigned long long au_iarray_cb(void *a,
23341+ unsigned long long max __maybe_unused,
23342+ void *arg)
23343+{
23344+ unsigned long long n;
23345+ struct inode **p, *inode;
23346+ struct list_head *head;
23347+
23348+ n = 0;
23349+ p = a;
23350+ head = arg;
2cbb1c4b 23351+ spin_lock(&inode_sb_list_lock);
7f207e10
AM
23352+ list_for_each_entry(inode, head, i_sb_list) {
23353+ if (!is_bad_inode(inode)
23354+ && au_ii(inode)->ii_bstart >= 0) {
2cbb1c4b
JR
23355+ spin_lock(&inode->i_lock);
23356+ if (atomic_read(&inode->i_count)) {
23357+ au_igrab(inode);
23358+ *p++ = inode;
23359+ n++;
23360+ AuDebugOn(n > max);
23361+ }
23362+ spin_unlock(&inode->i_lock);
7f207e10
AM
23363+ }
23364+ }
2cbb1c4b 23365+ spin_unlock(&inode_sb_list_lock);
7f207e10
AM
23366+
23367+ return n;
23368+}
23369+
23370+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
23371+{
23372+ *max = atomic_long_read(&au_sbi(sb)->si_ninodes);
23373+ return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
23374+}
23375+
23376+void au_iarray_free(struct inode **a, unsigned long long max)
23377+{
23378+ unsigned long long ull;
23379+
23380+ for (ull = 0; ull < max; ull++)
23381+ iput(a[ull]);
23382+ au_array_free(a);
23383+}
23384+
23385+/* ---------------------------------------------------------------------- */
23386+
1facf9fc 23387+/*
23388+ * refresh dentry and inode at remount time.
23389+ */
027c5e7a
AM
23390+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
23391+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
23392+ struct dentry *parent)
1facf9fc 23393+{
23394+ int err;
1facf9fc 23395+
23396+ di_write_lock_child(dentry);
1facf9fc 23397+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
23398+ err = au_refresh_dentry(dentry, parent);
23399+ if (!err && dir_flags)
23400+ au_hn_reset(dentry->d_inode, dir_flags);
1facf9fc 23401+ di_read_unlock(parent, AuLock_IR);
1facf9fc 23402+ di_write_unlock(dentry);
23403+
23404+ return err;
23405+}
23406+
027c5e7a
AM
23407+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
23408+ struct au_sbinfo *sbinfo,
23409+ const unsigned int dir_flags)
1facf9fc 23410+{
027c5e7a
AM
23411+ int err;
23412+ struct dentry *parent;
23413+ struct inode *inode;
23414+
23415+ err = 0;
23416+ parent = dget_parent(dentry);
23417+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
23418+ inode = dentry->d_inode;
23419+ if (inode) {
23420+ if (!S_ISDIR(inode->i_mode))
23421+ err = au_do_refresh(dentry, /*dir_flags*/0,
23422+ parent);
23423+ else {
23424+ err = au_do_refresh(dentry, dir_flags, parent);
23425+ if (unlikely(err))
23426+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
23427+ }
23428+ } else
23429+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
23430+ AuDbgDentry(dentry);
23431+ }
23432+ dput(parent);
23433+
23434+ AuTraceErr(err);
23435+ return err;
1facf9fc 23436+}
23437+
027c5e7a 23438+static int au_refresh_d(struct super_block *sb)
1facf9fc 23439+{
23440+ int err, i, j, ndentry, e;
027c5e7a 23441+ unsigned int sigen;
1facf9fc 23442+ struct au_dcsub_pages dpages;
23443+ struct au_dpage *dpage;
027c5e7a
AM
23444+ struct dentry **dentries, *d;
23445+ struct au_sbinfo *sbinfo;
23446+ struct dentry *root = sb->s_root;
23447+ const unsigned int dir_flags = au_hi_flags(root->d_inode, /*isdir*/1);
1facf9fc 23448+
027c5e7a
AM
23449+ err = au_dpages_init(&dpages, GFP_NOFS);
23450+ if (unlikely(err))
1facf9fc 23451+ goto out;
027c5e7a
AM
23452+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
23453+ if (unlikely(err))
1facf9fc 23454+ goto out_dpages;
1facf9fc 23455+
027c5e7a
AM
23456+ sigen = au_sigen(sb);
23457+ sbinfo = au_sbi(sb);
23458+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 23459+ dpage = dpages.dpages + i;
23460+ dentries = dpage->dentries;
23461+ ndentry = dpage->ndentry;
027c5e7a 23462+ for (j = 0; j < ndentry; j++) {
1facf9fc 23463+ d = dentries[j];
027c5e7a
AM
23464+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags);
23465+ if (unlikely(e && !err))
23466+ err = e;
23467+ /* go on even err */
1facf9fc 23468+ }
23469+ }
23470+
4f0767ce 23471+out_dpages:
1facf9fc 23472+ au_dpages_free(&dpages);
4f0767ce 23473+out:
1facf9fc 23474+ return err;
23475+}
23476+
027c5e7a 23477+static int au_refresh_i(struct super_block *sb)
1facf9fc 23478+{
027c5e7a
AM
23479+ int err, e;
23480+ unsigned int sigen;
23481+ unsigned long long max, ull;
23482+ struct inode *inode, **array;
1facf9fc 23483+
027c5e7a
AM
23484+ array = au_iarray_alloc(sb, &max);
23485+ err = PTR_ERR(array);
23486+ if (IS_ERR(array))
23487+ goto out;
1facf9fc 23488+
23489+ err = 0;
027c5e7a
AM
23490+ sigen = au_sigen(sb);
23491+ for (ull = 0; ull < max; ull++) {
23492+ inode = array[ull];
23493+ if (au_iigen(inode) != sigen) {
1facf9fc 23494+ ii_write_lock_child(inode);
027c5e7a 23495+ e = au_refresh_hinode_self(inode);
1facf9fc 23496+ ii_write_unlock(inode);
23497+ if (unlikely(e)) {
027c5e7a 23498+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 23499+ if (!err)
23500+ err = e;
23501+ /* go on even if err */
23502+ }
23503+ }
1facf9fc 23504+ }
23505+
027c5e7a 23506+ au_iarray_free(array, max);
1facf9fc 23507+
4f0767ce 23508+out:
1facf9fc 23509+ return err;
23510+}
23511+
027c5e7a 23512+static void au_remount_refresh(struct super_block *sb)
1facf9fc 23513+{
027c5e7a
AM
23514+ int err, e;
23515+ unsigned int udba;
23516+ aufs_bindex_t bindex, bend;
1facf9fc 23517+ struct dentry *root;
23518+ struct inode *inode;
027c5e7a 23519+ struct au_branch *br;
1facf9fc 23520+
23521+ au_sigen_inc(sb);
027c5e7a 23522+ au_fclr_si(au_sbi(sb), FAILED_REFRESH_DIR);
1facf9fc 23523+
23524+ root = sb->s_root;
23525+ DiMustNoWaiters(root);
23526+ inode = root->d_inode;
23527+ IiMustNoWaiters(inode);
1facf9fc 23528+
027c5e7a
AM
23529+ udba = au_opt_udba(sb);
23530+ bend = au_sbend(sb);
23531+ for (bindex = 0; bindex <= bend; bindex++) {
23532+ br = au_sbr(sb, bindex);
23533+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 23534+ if (unlikely(err))
027c5e7a
AM
23535+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
23536+ bindex, err);
23537+ /* go on even if err */
1facf9fc 23538+ }
027c5e7a 23539+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 23540+
027c5e7a
AM
23541+ di_write_unlock(root);
23542+ err = au_refresh_d(sb);
23543+ e = au_refresh_i(sb);
23544+ if (unlikely(e && !err))
23545+ err = e;
1facf9fc 23546+ /* aufs_write_lock() calls ..._child() */
23547+ di_write_lock_child(root);
027c5e7a
AM
23548+
23549+ au_cpup_attr_all(inode, /*force*/1);
23550+
23551+ if (unlikely(err))
23552+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 23553+}
23554+
23555+/* stop extra interpretation of errno in mount(8), and strange error messages */
23556+static int cvt_err(int err)
23557+{
23558+ AuTraceErr(err);
23559+
23560+ switch (err) {
23561+ case -ENOENT:
23562+ case -ENOTDIR:
23563+ case -EEXIST:
23564+ case -EIO:
23565+ err = -EINVAL;
23566+ }
23567+ return err;
23568+}
23569+
23570+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
23571+{
4a4d8108
AM
23572+ int err, do_dx;
23573+ unsigned int mntflags;
1facf9fc 23574+ struct au_opts opts;
23575+ struct dentry *root;
23576+ struct inode *inode;
23577+ struct au_sbinfo *sbinfo;
23578+
23579+ err = 0;
23580+ root = sb->s_root;
23581+ if (!data || !*data) {
e49829fe
JR
23582+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
23583+ if (!err) {
23584+ di_write_lock_child(root);
23585+ err = au_opts_verify(sb, *flags, /*pending*/0);
23586+ aufs_write_unlock(root);
23587+ }
1facf9fc 23588+ goto out;
23589+ }
23590+
23591+ err = -ENOMEM;
23592+ memset(&opts, 0, sizeof(opts));
23593+ opts.opt = (void *)__get_free_page(GFP_NOFS);
23594+ if (unlikely(!opts.opt))
23595+ goto out;
23596+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
23597+ opts.flags = AuOpts_REMOUNT;
23598+ opts.sb_flags = *flags;
23599+
23600+ /* parse it before aufs lock */
23601+ err = au_opts_parse(sb, data, &opts);
23602+ if (unlikely(err))
23603+ goto out_opts;
23604+
23605+ sbinfo = au_sbi(sb);
23606+ inode = root->d_inode;
23607+ mutex_lock(&inode->i_mutex);
e49829fe
JR
23608+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
23609+ if (unlikely(err))
23610+ goto out_mtx;
23611+ di_write_lock_child(root);
1facf9fc 23612+
23613+ /* au_opts_remount() may return an error */
23614+ err = au_opts_remount(sb, &opts);
23615+ au_opts_free(&opts);
23616+
027c5e7a
AM
23617+ if (au_ftest_opts(opts.flags, REFRESH))
23618+ au_remount_refresh(sb);
1facf9fc 23619+
4a4d8108
AM
23620+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
23621+ mntflags = au_mntflags(sb);
23622+ do_dx = !!au_opt_test(mntflags, DIO);
23623+ au_dy_arefresh(do_dx);
23624+ }
23625+
1facf9fc 23626+ aufs_write_unlock(root);
953406b4 23627+
e49829fe
JR
23628+out_mtx:
23629+ mutex_unlock(&inode->i_mutex);
4f0767ce 23630+out_opts:
1facf9fc 23631+ free_page((unsigned long)opts.opt);
4f0767ce 23632+out:
1facf9fc 23633+ err = cvt_err(err);
23634+ AuTraceErr(err);
23635+ return err;
23636+}
23637+
4a4d8108 23638+static const struct super_operations aufs_sop = {
1facf9fc 23639+ .alloc_inode = aufs_alloc_inode,
23640+ .destroy_inode = aufs_destroy_inode,
b752ccd1 23641+ /* always deleting, no clearing */
1facf9fc 23642+ .drop_inode = generic_delete_inode,
23643+ .show_options = aufs_show_options,
23644+ .statfs = aufs_statfs,
23645+ .put_super = aufs_put_super,
23646+ .remount_fs = aufs_remount_fs
23647+};
23648+
23649+/* ---------------------------------------------------------------------- */
23650+
23651+static int alloc_root(struct super_block *sb)
23652+{
23653+ int err;
23654+ struct inode *inode;
23655+ struct dentry *root;
23656+
23657+ err = -ENOMEM;
23658+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
23659+ err = PTR_ERR(inode);
23660+ if (IS_ERR(inode))
23661+ goto out;
23662+
23663+ inode->i_op = &aufs_dir_iop;
23664+ inode->i_fop = &aufs_dir_fop;
23665+ inode->i_mode = S_IFDIR;
9dbd164d 23666+ set_nlink(inode, 2);
1facf9fc 23667+ unlock_new_inode(inode);
23668+
92d182d2 23669+ root = d_make_root(inode);
1facf9fc 23670+ if (unlikely(!root))
92d182d2 23671+ goto out;
1facf9fc 23672+ err = PTR_ERR(root);
23673+ if (IS_ERR(root))
92d182d2 23674+ goto out;
1facf9fc 23675+
4a4d8108 23676+ err = au_di_init(root);
1facf9fc 23677+ if (!err) {
23678+ sb->s_root = root;
23679+ return 0; /* success */
23680+ }
23681+ dput(root);
1facf9fc 23682+
4f0767ce 23683+out:
1facf9fc 23684+ return err;
1facf9fc 23685+}
23686+
23687+static int aufs_fill_super(struct super_block *sb, void *raw_data,
23688+ int silent __maybe_unused)
23689+{
23690+ int err;
23691+ struct au_opts opts;
23692+ struct dentry *root;
23693+ struct inode *inode;
23694+ char *arg = raw_data;
23695+
23696+ if (unlikely(!arg || !*arg)) {
23697+ err = -EINVAL;
4a4d8108 23698+ pr_err("no arg\n");
1facf9fc 23699+ goto out;
23700+ }
23701+
23702+ err = -ENOMEM;
23703+ memset(&opts, 0, sizeof(opts));
23704+ opts.opt = (void *)__get_free_page(GFP_NOFS);
23705+ if (unlikely(!opts.opt))
23706+ goto out;
23707+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
23708+ opts.sb_flags = sb->s_flags;
23709+
23710+ err = au_si_alloc(sb);
23711+ if (unlikely(err))
23712+ goto out_opts;
23713+
23714+ /* all timestamps always follow the ones on the branch */
23715+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
23716+ sb->s_op = &aufs_sop;
027c5e7a 23717+ sb->s_d_op = &aufs_dop;
1facf9fc 23718+ sb->s_magic = AUFS_SUPER_MAGIC;
23719+ sb->s_maxbytes = 0;
23720+ au_export_init(sb);
23721+
23722+ err = alloc_root(sb);
23723+ if (unlikely(err)) {
23724+ si_write_unlock(sb);
23725+ goto out_info;
23726+ }
23727+ root = sb->s_root;
23728+ inode = root->d_inode;
23729+
23730+ /*
23731+ * actually we can parse options regardless aufs lock here.
23732+ * but at remount time, parsing must be done before aufs lock.
23733+ * so we follow the same rule.
23734+ */
23735+ ii_write_lock_parent(inode);
23736+ aufs_write_unlock(root);
23737+ err = au_opts_parse(sb, arg, &opts);
23738+ if (unlikely(err))
23739+ goto out_root;
23740+
23741+ /* lock vfs_inode first, then aufs. */
23742+ mutex_lock(&inode->i_mutex);
1facf9fc 23743+ aufs_write_lock(root);
23744+ err = au_opts_mount(sb, &opts);
23745+ au_opts_free(&opts);
1facf9fc 23746+ aufs_write_unlock(root);
23747+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
23748+ if (!err)
23749+ goto out_opts; /* success */
1facf9fc 23750+
4f0767ce 23751+out_root:
1facf9fc 23752+ dput(root);
23753+ sb->s_root = NULL;
4f0767ce 23754+out_info:
2cbb1c4b 23755+ dbgaufs_si_fin(au_sbi(sb));
1facf9fc 23756+ kobject_put(&au_sbi(sb)->si_kobj);
23757+ sb->s_fs_info = NULL;
4f0767ce 23758+out_opts:
1facf9fc 23759+ free_page((unsigned long)opts.opt);
4f0767ce 23760+out:
1facf9fc 23761+ AuTraceErr(err);
23762+ err = cvt_err(err);
23763+ AuTraceErr(err);
23764+ return err;
23765+}
23766+
23767+/* ---------------------------------------------------------------------- */
23768+
027c5e7a
AM
23769+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
23770+ const char *dev_name __maybe_unused,
23771+ void *raw_data)
1facf9fc 23772+{
027c5e7a 23773+ struct dentry *root;
1facf9fc 23774+ struct super_block *sb;
23775+
23776+ /* all timestamps always follow the ones on the branch */
23777+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
23778+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
23779+ if (IS_ERR(root))
23780+ goto out;
23781+
23782+ sb = root->d_sb;
23783+ si_write_lock(sb, !AuLock_FLUSH);
23784+ sysaufs_brs_add(sb, 0);
23785+ si_write_unlock(sb);
23786+ au_sbilist_add(sb);
23787+
23788+out:
23789+ return root;
1facf9fc 23790+}
23791+
e49829fe
JR
23792+static void aufs_kill_sb(struct super_block *sb)
23793+{
23794+ struct au_sbinfo *sbinfo;
23795+
23796+ sbinfo = au_sbi(sb);
23797+ if (sbinfo) {
23798+ au_sbilist_del(sb);
23799+ aufs_write_lock(sb->s_root);
23800+ if (sbinfo->si_wbr_create_ops->fin)
23801+ sbinfo->si_wbr_create_ops->fin(sb);
23802+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
23803+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
027c5e7a 23804+ au_remount_refresh(sb);
e49829fe
JR
23805+ }
23806+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
23807+ au_plink_put(sb, /*verbose*/1);
23808+ au_xino_clr(sb);
1e00d052 23809+ sbinfo->si_sb = NULL;
e49829fe 23810+ aufs_write_unlock(sb->s_root);
e49829fe
JR
23811+ au_nwt_flush(&sbinfo->si_nowait);
23812+ }
23813+ generic_shutdown_super(sb);
23814+}
23815+
1facf9fc 23816+struct file_system_type aufs_fs_type = {
23817+ .name = AUFS_FSTYPE,
23818+ .fs_flags =
23819+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
23820+ | FS_REVAL_DOT, /* for NFS branch and udba */
027c5e7a 23821+ .mount = aufs_mount,
e49829fe 23822+ .kill_sb = aufs_kill_sb,
1facf9fc 23823+ /* no need to __module_get() and module_put(). */
23824+ .owner = THIS_MODULE,
23825+};
7f207e10
AM
23826diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
23827--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 23828+++ linux/fs/aufs/super.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 23829@@ -0,0 +1,546 @@
1facf9fc 23830+/*
f6c5ef8b 23831+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 23832+ *
23833+ * This program, aufs is free software; you can redistribute it and/or modify
23834+ * it under the terms of the GNU General Public License as published by
23835+ * the Free Software Foundation; either version 2 of the License, or
23836+ * (at your option) any later version.
dece6358
AM
23837+ *
23838+ * This program is distributed in the hope that it will be useful,
23839+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23840+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23841+ * GNU General Public License for more details.
23842+ *
23843+ * You should have received a copy of the GNU General Public License
23844+ * along with this program; if not, write to the Free Software
23845+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23846+ */
23847+
23848+/*
23849+ * super_block operations
23850+ */
23851+
23852+#ifndef __AUFS_SUPER_H__
23853+#define __AUFS_SUPER_H__
23854+
23855+#ifdef __KERNEL__
23856+
23857+#include <linux/fs.h>
1facf9fc 23858+#include "rwsem.h"
23859+#include "spl.h"
23860+#include "wkq.h"
23861+
23862+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
23863+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
23864+ loff_t *);
23865+
23866+/* policies to select one among multiple writable branches */
23867+struct au_wbr_copyup_operations {
23868+ int (*copyup)(struct dentry *dentry);
23869+};
23870+
23871+struct au_wbr_create_operations {
23872+ int (*create)(struct dentry *dentry, int isdir);
23873+ int (*init)(struct super_block *sb);
23874+ int (*fin)(struct super_block *sb);
23875+};
23876+
23877+struct au_wbr_mfs {
23878+ struct mutex mfs_lock; /* protect this structure */
23879+ unsigned long mfs_jiffy;
23880+ unsigned long mfs_expire;
23881+ aufs_bindex_t mfs_bindex;
23882+
23883+ unsigned long long mfsrr_bytes;
23884+ unsigned long long mfsrr_watermark;
23885+};
23886+
1facf9fc 23887+struct au_branch;
23888+struct au_sbinfo {
23889+ /* nowait tasks in the system-wide workqueue */
23890+ struct au_nowait_tasks si_nowait;
23891+
b752ccd1
AM
23892+ /*
23893+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
23894+ * rwsem for au_sbinfo is necessary.
23895+ */
dece6358 23896+ struct au_rwsem si_rwsem;
1facf9fc 23897+
b752ccd1
AM
23898+ /* prevent recursive locking in deleting inode */
23899+ struct {
23900+ unsigned long *bitmap;
23901+ spinlock_t tree_lock;
23902+ struct radix_tree_root tree;
23903+ } au_si_pid;
23904+
7f207e10
AM
23905+ /*
23906+ * dirty approach to protect sb->sb_inodes and ->s_files from remount.
23907+ */
23908+ atomic_long_t si_ninodes, si_nfiles;
23909+
1facf9fc 23910+ /* branch management */
23911+ unsigned int si_generation;
23912+
23913+ /* see above flags */
23914+ unsigned char au_si_status;
23915+
23916+ aufs_bindex_t si_bend;
7f207e10
AM
23917+
23918+ /* dirty trick to keep br_id plus */
23919+ unsigned int si_last_br_id :
23920+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 23921+ struct au_branch **si_branch;
23922+
23923+ /* policy to select a writable branch */
23924+ unsigned char si_wbr_copyup;
23925+ unsigned char si_wbr_create;
23926+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
23927+ struct au_wbr_create_operations *si_wbr_create_ops;
23928+
23929+ /* round robin */
23930+ atomic_t si_wbr_rr_next;
23931+
23932+ /* most free space */
23933+ struct au_wbr_mfs si_wbr_mfs;
23934+
23935+ /* mount flags */
23936+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
23937+ unsigned int si_mntflags;
23938+
23939+ /* external inode number (bitmap and translation table) */
23940+ au_readf_t si_xread;
23941+ au_writef_t si_xwrite;
23942+ struct file *si_xib;
23943+ struct mutex si_xib_mtx; /* protect xib members */
23944+ unsigned long *si_xib_buf;
23945+ unsigned long si_xib_last_pindex;
23946+ int si_xib_next_bit;
23947+ aufs_bindex_t si_xino_brid;
23948+ /* reserved for future use */
23949+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
23950+
23951+#ifdef CONFIG_AUFS_EXPORT
23952+ /* i_generation */
23953+ struct file *si_xigen;
23954+ atomic_t si_xigen_next;
23955+#endif
23956+
23957+ /* vdir parameters */
e49829fe 23958+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 23959+ unsigned int si_rdblk; /* deblk size */
23960+ unsigned int si_rdhash; /* hash size */
23961+
23962+ /*
23963+ * If the number of whiteouts are larger than si_dirwh, leave all of
23964+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
23965+ * future fsck.aufs or kernel thread will remove them later.
23966+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
23967+ */
23968+ unsigned int si_dirwh;
23969+
23970+ /*
23971+ * rename(2) a directory with all children.
23972+ */
23973+ /* reserved for future use */
23974+ /* int si_rendir; */
23975+
23976+ /* pseudo_link list */
23977+ struct au_splhead si_plink;
23978+ wait_queue_head_t si_plink_wq;
4a4d8108 23979+ spinlock_t si_plink_maint_lock;
e49829fe 23980+ pid_t si_plink_maint_pid;
1facf9fc 23981+
23982+ /*
23983+ * sysfs and lifetime management.
23984+ * this is not a small structure and it may be a waste of memory in case
23985+ * of sysfs is disabled, particulary when many aufs-es are mounted.
23986+ * but using sysfs is majority.
23987+ */
23988+ struct kobject si_kobj;
23989+#ifdef CONFIG_DEBUG_FS
23990+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
23991+#ifdef CONFIG_AUFS_EXPORT
23992+ struct dentry *si_dbgaufs_xigen;
23993+#endif
23994+#endif
23995+
e49829fe
JR
23996+#ifdef CONFIG_AUFS_SBILIST
23997+ struct list_head si_list;
23998+#endif
23999+
1facf9fc 24000+ /* dirty, necessary for unmounting, sysfs and sysrq */
24001+ struct super_block *si_sb;
24002+};
24003+
dece6358
AM
24004+/* sbinfo status flags */
24005+/*
24006+ * set true when refresh_dirs() failed at remount time.
24007+ * then try refreshing dirs at access time again.
24008+ * if it is false, refreshing dirs at access time is unnecesary
24009+ */
027c5e7a 24010+#define AuSi_FAILED_REFRESH_DIR 1
dece6358
AM
24011+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
24012+ unsigned int flag)
24013+{
24014+ AuRwMustAnyLock(&sbi->si_rwsem);
24015+ return sbi->au_si_status & flag;
24016+}
24017+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
24018+#define au_fset_si(sbinfo, name) do { \
24019+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
24020+ (sbinfo)->au_si_status |= AuSi_##name; \
24021+} while (0)
24022+#define au_fclr_si(sbinfo, name) do { \
24023+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
24024+ (sbinfo)->au_si_status &= ~AuSi_##name; \
24025+} while (0)
24026+
1facf9fc 24027+/* ---------------------------------------------------------------------- */
24028+
24029+/* policy to select one among writable branches */
4a4d8108
AM
24030+#define AuWbrCopyup(sbinfo, ...) \
24031+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
24032+#define AuWbrCreate(sbinfo, ...) \
24033+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 24034+
24035+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
24036+#define AuLock_DW 1 /* write-lock dentry */
24037+#define AuLock_IR (1 << 1) /* read-lock inode */
24038+#define AuLock_IW (1 << 2) /* write-lock inode */
24039+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
24040+#define AuLock_DIR (1 << 4) /* target is a dir */
e49829fe
JR
24041+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
24042+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 24043+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 24044+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
24045+#define au_fset_lock(flags, name) \
24046+ do { (flags) |= AuLock_##name; } while (0)
24047+#define au_fclr_lock(flags, name) \
24048+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 24049+
24050+/* ---------------------------------------------------------------------- */
24051+
24052+/* super.c */
24053+extern struct file_system_type aufs_fs_type;
24054+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
7f207e10
AM
24055+typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max,
24056+ void *arg);
24057+void au_array_free(void *array);
24058+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg);
24059+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
24060+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 24061+
24062+/* sbinfo.c */
24063+void au_si_free(struct kobject *kobj);
24064+int au_si_alloc(struct super_block *sb);
24065+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
24066+
24067+unsigned int au_sigen_inc(struct super_block *sb);
24068+aufs_bindex_t au_new_br_id(struct super_block *sb);
24069+
e49829fe
JR
24070+int si_read_lock(struct super_block *sb, int flags);
24071+int si_write_lock(struct super_block *sb, int flags);
24072+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 24073+void aufs_read_unlock(struct dentry *dentry, int flags);
24074+void aufs_write_lock(struct dentry *dentry);
24075+void aufs_write_unlock(struct dentry *dentry);
e49829fe 24076+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 24077+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
24078+
b752ccd1
AM
24079+int si_pid_test_slow(struct super_block *sb);
24080+void si_pid_set_slow(struct super_block *sb);
24081+void si_pid_clr_slow(struct super_block *sb);
24082+
1facf9fc 24083+/* wbr_policy.c */
24084+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
24085+extern struct au_wbr_create_operations au_wbr_create_ops[];
24086+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
24087+
24088+/* ---------------------------------------------------------------------- */
24089+
24090+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
24091+{
24092+ return sb->s_fs_info;
24093+}
24094+
24095+/* ---------------------------------------------------------------------- */
24096+
24097+#ifdef CONFIG_AUFS_EXPORT
24098+void au_export_init(struct super_block *sb);
24099+
b752ccd1 24100+static inline int au_test_nfsd(void)
1facf9fc 24101+{
b752ccd1
AM
24102+ struct task_struct *tsk = current;
24103+
24104+ return (tsk->flags & PF_KTHREAD)
24105+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 24106+}
24107+
b752ccd1 24108+void au_xigen_inc(struct inode *inode);
1facf9fc 24109+int au_xigen_new(struct inode *inode);
24110+int au_xigen_set(struct super_block *sb, struct file *base);
24111+void au_xigen_clr(struct super_block *sb);
24112+
24113+static inline int au_busy_or_stale(void)
24114+{
b752ccd1 24115+ if (!au_test_nfsd())
1facf9fc 24116+ return -EBUSY;
24117+ return -ESTALE;
24118+}
24119+#else
4a4d8108 24120+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
24121+AuStubInt0(au_test_nfsd, void)
24122+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
24123+AuStubInt0(au_xigen_new, struct inode *inode)
24124+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
24125+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 24126+static inline int au_busy_or_stale(void)
24127+{
24128+ return -EBUSY;
24129+}
24130+#endif /* CONFIG_AUFS_EXPORT */
24131+
24132+/* ---------------------------------------------------------------------- */
24133+
e49829fe
JR
24134+#ifdef CONFIG_AUFS_SBILIST
24135+/* module.c */
24136+extern struct au_splhead au_sbilist;
24137+
24138+static inline void au_sbilist_init(void)
24139+{
24140+ au_spl_init(&au_sbilist);
24141+}
24142+
24143+static inline void au_sbilist_add(struct super_block *sb)
24144+{
24145+ au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
24146+}
24147+
24148+static inline void au_sbilist_del(struct super_block *sb)
24149+{
24150+ au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
24151+}
53392da6
AM
24152+
24153+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
24154+static inline void au_sbilist_lock(void)
24155+{
24156+ spin_lock(&au_sbilist.spin);
24157+}
24158+
24159+static inline void au_sbilist_unlock(void)
24160+{
24161+ spin_unlock(&au_sbilist.spin);
24162+}
24163+#define AuGFP_SBILIST GFP_ATOMIC
24164+#else
24165+AuStubVoid(au_sbilist_lock, void)
24166+AuStubVoid(au_sbilist_unlock, void)
24167+#define AuGFP_SBILIST GFP_NOFS
24168+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
e49829fe
JR
24169+#else
24170+AuStubVoid(au_sbilist_init, void)
24171+AuStubVoid(au_sbilist_add, struct super_block*)
24172+AuStubVoid(au_sbilist_del, struct super_block*)
53392da6
AM
24173+AuStubVoid(au_sbilist_lock, void)
24174+AuStubVoid(au_sbilist_unlock, void)
24175+#define AuGFP_SBILIST GFP_NOFS
e49829fe
JR
24176+#endif
24177+
24178+/* ---------------------------------------------------------------------- */
24179+
1facf9fc 24180+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
24181+{
dece6358
AM
24182+ /*
24183+ * This function is a dynamic '__init' fucntion actually,
24184+ * so the tiny check for si_rwsem is unnecessary.
24185+ */
24186+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 24187+#ifdef CONFIG_DEBUG_FS
24188+ sbinfo->si_dbgaufs = NULL;
24189+ sbinfo->si_dbgaufs_xib = NULL;
24190+#ifdef CONFIG_AUFS_EXPORT
24191+ sbinfo->si_dbgaufs_xigen = NULL;
24192+#endif
24193+#endif
24194+}
24195+
24196+/* ---------------------------------------------------------------------- */
24197+
b752ccd1
AM
24198+static inline pid_t si_pid_bit(void)
24199+{
24200+ /* the origin of pid is 1, but the bitmap's is 0 */
24201+ return current->pid - 1;
24202+}
24203+
24204+static inline int si_pid_test(struct super_block *sb)
24205+{
24206+ pid_t bit = si_pid_bit();
24207+ if (bit < PID_MAX_DEFAULT)
24208+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24209+ else
24210+ return si_pid_test_slow(sb);
24211+}
24212+
24213+static inline void si_pid_set(struct super_block *sb)
24214+{
24215+ pid_t bit = si_pid_bit();
24216+ if (bit < PID_MAX_DEFAULT) {
24217+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
24218+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24219+ /* smp_mb(); */
24220+ } else
24221+ si_pid_set_slow(sb);
24222+}
24223+
24224+static inline void si_pid_clr(struct super_block *sb)
24225+{
24226+ pid_t bit = si_pid_bit();
24227+ if (bit < PID_MAX_DEFAULT) {
24228+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
24229+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24230+ /* smp_mb(); */
24231+ } else
24232+ si_pid_clr_slow(sb);
24233+}
24234+
24235+/* ---------------------------------------------------------------------- */
24236+
1facf9fc 24237+/* lock superblock. mainly for entry point functions */
24238+/*
b752ccd1
AM
24239+ * __si_read_lock, __si_write_lock,
24240+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 24241+ */
b752ccd1 24242+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 24243+
dece6358
AM
24244+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
24245+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
24246+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
24247+
b752ccd1
AM
24248+static inline void si_noflush_read_lock(struct super_block *sb)
24249+{
24250+ __si_read_lock(sb);
24251+ si_pid_set(sb);
24252+}
24253+
24254+static inline int si_noflush_read_trylock(struct super_block *sb)
24255+{
24256+ int locked = __si_read_trylock(sb);
24257+ if (locked)
24258+ si_pid_set(sb);
24259+ return locked;
24260+}
24261+
24262+static inline void si_noflush_write_lock(struct super_block *sb)
24263+{
24264+ __si_write_lock(sb);
24265+ si_pid_set(sb);
24266+}
24267+
24268+static inline int si_noflush_write_trylock(struct super_block *sb)
24269+{
24270+ int locked = __si_write_trylock(sb);
24271+ if (locked)
24272+ si_pid_set(sb);
24273+ return locked;
24274+}
24275+
e49829fe 24276+#if 0 /* unused */
1facf9fc 24277+static inline int si_read_trylock(struct super_block *sb, int flags)
24278+{
24279+ if (au_ftest_lock(flags, FLUSH))
24280+ au_nwt_flush(&au_sbi(sb)->si_nowait);
24281+ return si_noflush_read_trylock(sb);
24282+}
e49829fe 24283+#endif
1facf9fc 24284+
b752ccd1
AM
24285+static inline void si_read_unlock(struct super_block *sb)
24286+{
24287+ si_pid_clr(sb);
24288+ __si_read_unlock(sb);
24289+}
24290+
b752ccd1 24291+#if 0 /* unused */
1facf9fc 24292+static inline int si_write_trylock(struct super_block *sb, int flags)
24293+{
24294+ if (au_ftest_lock(flags, FLUSH))
24295+ au_nwt_flush(&au_sbi(sb)->si_nowait);
24296+ return si_noflush_write_trylock(sb);
24297+}
b752ccd1
AM
24298+#endif
24299+
24300+static inline void si_write_unlock(struct super_block *sb)
24301+{
24302+ si_pid_clr(sb);
24303+ __si_write_unlock(sb);
24304+}
24305+
24306+#if 0 /* unused */
24307+static inline void si_downgrade_lock(struct super_block *sb)
24308+{
24309+ __si_downgrade_lock(sb);
24310+}
24311+#endif
1facf9fc 24312+
24313+/* ---------------------------------------------------------------------- */
24314+
24315+static inline aufs_bindex_t au_sbend(struct super_block *sb)
24316+{
dece6358 24317+ SiMustAnyLock(sb);
1facf9fc 24318+ return au_sbi(sb)->si_bend;
24319+}
24320+
24321+static inline unsigned int au_mntflags(struct super_block *sb)
24322+{
dece6358 24323+ SiMustAnyLock(sb);
1facf9fc 24324+ return au_sbi(sb)->si_mntflags;
24325+}
24326+
24327+static inline unsigned int au_sigen(struct super_block *sb)
24328+{
dece6358 24329+ SiMustAnyLock(sb);
1facf9fc 24330+ return au_sbi(sb)->si_generation;
24331+}
24332+
7f207e10
AM
24333+static inline void au_ninodes_inc(struct super_block *sb)
24334+{
24335+ atomic_long_inc(&au_sbi(sb)->si_ninodes);
24336+}
24337+
24338+static inline void au_ninodes_dec(struct super_block *sb)
24339+{
24340+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes));
24341+ atomic_long_dec(&au_sbi(sb)->si_ninodes);
24342+}
24343+
24344+static inline void au_nfiles_inc(struct super_block *sb)
24345+{
24346+ atomic_long_inc(&au_sbi(sb)->si_nfiles);
24347+}
24348+
24349+static inline void au_nfiles_dec(struct super_block *sb)
24350+{
24351+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles));
24352+ atomic_long_dec(&au_sbi(sb)->si_nfiles);
24353+}
24354+
1facf9fc 24355+static inline struct au_branch *au_sbr(struct super_block *sb,
24356+ aufs_bindex_t bindex)
24357+{
dece6358 24358+ SiMustAnyLock(sb);
1facf9fc 24359+ return au_sbi(sb)->si_branch[0 + bindex];
24360+}
24361+
24362+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
24363+{
dece6358 24364+ SiMustWriteLock(sb);
1facf9fc 24365+ au_sbi(sb)->si_xino_brid = brid;
24366+}
24367+
24368+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
24369+{
dece6358 24370+ SiMustAnyLock(sb);
1facf9fc 24371+ return au_sbi(sb)->si_xino_brid;
24372+}
24373+
24374+#endif /* __KERNEL__ */
24375+#endif /* __AUFS_SUPER_H__ */
7f207e10
AM
24376diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
24377--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 24378+++ linux/fs/aufs/sysaufs.c 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 24379@@ -0,0 +1,105 @@
1facf9fc 24380+/*
f6c5ef8b 24381+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24382+ *
24383+ * This program, aufs is free software; you can redistribute it and/or modify
24384+ * it under the terms of the GNU General Public License as published by
24385+ * the Free Software Foundation; either version 2 of the License, or
24386+ * (at your option) any later version.
dece6358
AM
24387+ *
24388+ * This program is distributed in the hope that it will be useful,
24389+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24390+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24391+ * GNU General Public License for more details.
24392+ *
24393+ * You should have received a copy of the GNU General Public License
24394+ * along with this program; if not, write to the Free Software
24395+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24396+ */
24397+
24398+/*
24399+ * sysfs interface and lifetime management
24400+ * they are necessary regardless sysfs is disabled.
24401+ */
24402+
1facf9fc 24403+#include <linux/random.h>
1facf9fc 24404+#include "aufs.h"
24405+
24406+unsigned long sysaufs_si_mask;
e49829fe 24407+struct kset *sysaufs_kset;
1facf9fc 24408+
24409+#define AuSiAttr(_name) { \
24410+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
24411+ .show = sysaufs_si_##_name, \
24412+}
24413+
24414+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
24415+struct attribute *sysaufs_si_attrs[] = {
24416+ &sysaufs_si_attr_xi_path.attr,
24417+ NULL,
24418+};
24419+
4a4d8108 24420+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 24421+ .show = sysaufs_si_show
24422+};
24423+
24424+static struct kobj_type au_sbi_ktype = {
24425+ .release = au_si_free,
24426+ .sysfs_ops = &au_sbi_ops,
24427+ .default_attrs = sysaufs_si_attrs
24428+};
24429+
24430+/* ---------------------------------------------------------------------- */
24431+
24432+int sysaufs_si_init(struct au_sbinfo *sbinfo)
24433+{
24434+ int err;
24435+
e49829fe 24436+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 24437+ /* cf. sysaufs_name() */
24438+ err = kobject_init_and_add
e49829fe 24439+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 24440+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
24441+
24442+ dbgaufs_si_null(sbinfo);
24443+ if (!err) {
24444+ err = dbgaufs_si_init(sbinfo);
24445+ if (unlikely(err))
24446+ kobject_put(&sbinfo->si_kobj);
24447+ }
24448+ return err;
24449+}
24450+
24451+void sysaufs_fin(void)
24452+{
24453+ dbgaufs_fin();
e49829fe
JR
24454+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
24455+ kset_unregister(sysaufs_kset);
1facf9fc 24456+}
24457+
24458+int __init sysaufs_init(void)
24459+{
24460+ int err;
24461+
24462+ do {
24463+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
24464+ } while (!sysaufs_si_mask);
24465+
4a4d8108 24466+ err = -EINVAL;
e49829fe
JR
24467+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
24468+ if (unlikely(!sysaufs_kset))
4a4d8108 24469+ goto out;
e49829fe
JR
24470+ err = PTR_ERR(sysaufs_kset);
24471+ if (IS_ERR(sysaufs_kset))
1facf9fc 24472+ goto out;
e49829fe 24473+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 24474+ if (unlikely(err)) {
e49829fe 24475+ kset_unregister(sysaufs_kset);
1facf9fc 24476+ goto out;
24477+ }
24478+
24479+ err = dbgaufs_init();
24480+ if (unlikely(err))
24481+ sysaufs_fin();
4f0767ce 24482+out:
1facf9fc 24483+ return err;
24484+}
7f207e10
AM
24485diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
24486--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 24487+++ linux/fs/aufs/sysaufs.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 24488@@ -0,0 +1,104 @@
1facf9fc 24489+/*
f6c5ef8b 24490+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24491+ *
24492+ * This program, aufs is free software; you can redistribute it and/or modify
24493+ * it under the terms of the GNU General Public License as published by
24494+ * the Free Software Foundation; either version 2 of the License, or
24495+ * (at your option) any later version.
dece6358
AM
24496+ *
24497+ * This program is distributed in the hope that it will be useful,
24498+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24499+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24500+ * GNU General Public License for more details.
24501+ *
24502+ * You should have received a copy of the GNU General Public License
24503+ * along with this program; if not, write to the Free Software
24504+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24505+ */
24506+
24507+/*
24508+ * sysfs interface and mount lifetime management
24509+ */
24510+
24511+#ifndef __SYSAUFS_H__
24512+#define __SYSAUFS_H__
24513+
24514+#ifdef __KERNEL__
24515+
1facf9fc 24516+#include <linux/sysfs.h>
1facf9fc 24517+#include "module.h"
24518+
dece6358
AM
24519+struct super_block;
24520+struct au_sbinfo;
24521+
1facf9fc 24522+struct sysaufs_si_attr {
24523+ struct attribute attr;
24524+ int (*show)(struct seq_file *seq, struct super_block *sb);
24525+};
24526+
24527+/* ---------------------------------------------------------------------- */
24528+
24529+/* sysaufs.c */
24530+extern unsigned long sysaufs_si_mask;
e49829fe 24531+extern struct kset *sysaufs_kset;
1facf9fc 24532+extern struct attribute *sysaufs_si_attrs[];
24533+int sysaufs_si_init(struct au_sbinfo *sbinfo);
24534+int __init sysaufs_init(void);
24535+void sysaufs_fin(void);
24536+
24537+/* ---------------------------------------------------------------------- */
24538+
24539+/* some people doesn't like to show a pointer in kernel */
24540+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
24541+{
24542+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
24543+}
24544+
24545+#define SysaufsSiNamePrefix "si_"
24546+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
24547+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
24548+{
24549+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
24550+ sysaufs_si_id(sbinfo));
24551+}
24552+
24553+struct au_branch;
24554+#ifdef CONFIG_SYSFS
24555+/* sysfs.c */
24556+extern struct attribute_group *sysaufs_attr_group;
24557+
24558+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
24559+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
24560+ char *buf);
24561+
24562+void sysaufs_br_init(struct au_branch *br);
24563+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
24564+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
24565+
24566+#define sysaufs_brs_init() do {} while (0)
24567+
24568+#else
24569+#define sysaufs_attr_group NULL
24570+
4a4d8108 24571+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 24572+
24573+static inline
24574+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
24575+ char *buf)
24576+{
24577+ return 0;
24578+}
24579+
4a4d8108
AM
24580+AuStubVoid(sysaufs_br_init, struct au_branch *br)
24581+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
24582+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 24583+
24584+static inline void sysaufs_brs_init(void)
24585+{
24586+ sysaufs_brs = 0;
24587+}
24588+
24589+#endif /* CONFIG_SYSFS */
24590+
24591+#endif /* __KERNEL__ */
24592+#endif /* __SYSAUFS_H__ */
7f207e10
AM
24593diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
24594--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 24595+++ linux/fs/aufs/sysfs.c 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 24596@@ -0,0 +1,257 @@
1facf9fc 24597+/*
f6c5ef8b 24598+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24599+ *
24600+ * This program, aufs is free software; you can redistribute it and/or modify
24601+ * it under the terms of the GNU General Public License as published by
24602+ * the Free Software Foundation; either version 2 of the License, or
24603+ * (at your option) any later version.
dece6358
AM
24604+ *
24605+ * This program is distributed in the hope that it will be useful,
24606+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24607+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24608+ * GNU General Public License for more details.
24609+ *
24610+ * You should have received a copy of the GNU General Public License
24611+ * along with this program; if not, write to the Free Software
24612+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24613+ */
24614+
24615+/*
24616+ * sysfs interface
24617+ */
24618+
1facf9fc 24619+#include <linux/seq_file.h>
1facf9fc 24620+#include "aufs.h"
24621+
4a4d8108
AM
24622+#ifdef CONFIG_AUFS_FS_MODULE
24623+/* this entry violates the "one line per file" policy of sysfs */
24624+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
24625+ char *buf)
24626+{
24627+ ssize_t err;
24628+ static char *conf =
24629+/* this file is generated at compiling */
24630+#include "conf.str"
24631+ ;
24632+
24633+ err = snprintf(buf, PAGE_SIZE, conf);
24634+ if (unlikely(err >= PAGE_SIZE))
24635+ err = -EFBIG;
24636+ return err;
24637+}
24638+
24639+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
24640+#endif
24641+
1facf9fc 24642+static struct attribute *au_attr[] = {
4a4d8108
AM
24643+#ifdef CONFIG_AUFS_FS_MODULE
24644+ &au_config_attr.attr,
24645+#endif
1facf9fc 24646+ NULL, /* need to NULL terminate the list of attributes */
24647+};
24648+
24649+static struct attribute_group sysaufs_attr_group_body = {
24650+ .attrs = au_attr
24651+};
24652+
24653+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
24654+
24655+/* ---------------------------------------------------------------------- */
24656+
24657+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
24658+{
24659+ int err;
24660+
dece6358
AM
24661+ SiMustAnyLock(sb);
24662+
1facf9fc 24663+ err = 0;
24664+ if (au_opt_test(au_mntflags(sb), XINO)) {
24665+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
24666+ seq_putc(seq, '\n');
24667+ }
24668+ return err;
24669+}
24670+
24671+/*
24672+ * the lifetime of branch is independent from the entry under sysfs.
24673+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
24674+ * unlinked.
24675+ */
24676+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
24677+ aufs_bindex_t bindex)
24678+{
1e00d052 24679+ int err;
1facf9fc 24680+ struct path path;
24681+ struct dentry *root;
24682+ struct au_branch *br;
1e00d052 24683+ char *perm;
1facf9fc 24684+
24685+ AuDbg("b%d\n", bindex);
24686+
1e00d052 24687+ err = 0;
1facf9fc 24688+ root = sb->s_root;
24689+ di_read_lock_parent(root, !AuLock_IR);
24690+ br = au_sbr(sb, bindex);
24691+ path.mnt = br->br_mnt;
24692+ path.dentry = au_h_dptr(root, bindex);
24693+ au_seq_path(seq, &path);
24694+ di_read_unlock(root, !AuLock_IR);
1e00d052
AM
24695+ perm = au_optstr_br_perm(br->br_perm);
24696+ if (perm) {
24697+ err = seq_printf(seq, "=%s\n", perm);
24698+ kfree(perm);
24699+ if (err == -1)
24700+ err = -E2BIG;
24701+ } else
24702+ err = -ENOMEM;
24703+ return err;
1facf9fc 24704+}
24705+
24706+/* ---------------------------------------------------------------------- */
24707+
24708+static struct seq_file *au_seq(char *p, ssize_t len)
24709+{
24710+ struct seq_file *seq;
24711+
24712+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
24713+ if (seq) {
24714+ /* mutex_init(&seq.lock); */
24715+ seq->buf = p;
24716+ seq->size = len;
24717+ return seq; /* success */
24718+ }
24719+
24720+ seq = ERR_PTR(-ENOMEM);
24721+ return seq;
24722+}
24723+
24724+#define SysaufsBr_PREFIX "br"
24725+
24726+/* todo: file size may exceed PAGE_SIZE */
24727+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 24728+ char *buf)
1facf9fc 24729+{
24730+ ssize_t err;
24731+ long l;
24732+ aufs_bindex_t bend;
24733+ struct au_sbinfo *sbinfo;
24734+ struct super_block *sb;
24735+ struct seq_file *seq;
24736+ char *name;
24737+ struct attribute **cattr;
24738+
24739+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
24740+ sb = sbinfo->si_sb;
1308ab2a 24741+
24742+ /*
24743+ * prevent a race condition between sysfs and aufs.
24744+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
24745+ * prohibits maintaining the sysfs entries.
24746+ * hew we acquire read lock after sysfs_get_active_two().
24747+ * on the other hand, the remount process may maintain the sysfs/aufs
24748+ * entries after acquiring write lock.
24749+ * it can cause a deadlock.
24750+ * simply we gave up processing read here.
24751+ */
24752+ err = -EBUSY;
24753+ if (unlikely(!si_noflush_read_trylock(sb)))
24754+ goto out;
1facf9fc 24755+
24756+ seq = au_seq(buf, PAGE_SIZE);
24757+ err = PTR_ERR(seq);
24758+ if (IS_ERR(seq))
1308ab2a 24759+ goto out_unlock;
1facf9fc 24760+
24761+ name = (void *)attr->name;
24762+ cattr = sysaufs_si_attrs;
24763+ while (*cattr) {
24764+ if (!strcmp(name, (*cattr)->name)) {
24765+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
24766+ ->show(seq, sb);
24767+ goto out_seq;
24768+ }
24769+ cattr++;
24770+ }
24771+
24772+ bend = au_sbend(sb);
24773+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
24774+ name += sizeof(SysaufsBr_PREFIX) - 1;
9dbd164d 24775+ err = kstrtol(name, 10, &l);
1facf9fc 24776+ if (!err) {
24777+ if (l <= bend)
24778+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
24779+ else
24780+ err = -ENOENT;
24781+ }
24782+ goto out_seq;
24783+ }
24784+ BUG();
24785+
4f0767ce 24786+out_seq:
1facf9fc 24787+ if (!err) {
24788+ err = seq->count;
24789+ /* sysfs limit */
24790+ if (unlikely(err == PAGE_SIZE))
24791+ err = -EFBIG;
24792+ }
24793+ kfree(seq);
4f0767ce 24794+out_unlock:
1facf9fc 24795+ si_read_unlock(sb);
4f0767ce 24796+out:
1facf9fc 24797+ return err;
24798+}
24799+
24800+/* ---------------------------------------------------------------------- */
24801+
24802+void sysaufs_br_init(struct au_branch *br)
24803+{
4a4d8108
AM
24804+ struct attribute *attr = &br->br_attr;
24805+
24806+ sysfs_attr_init(attr);
24807+ attr->name = br->br_name;
24808+ attr->mode = S_IRUGO;
1facf9fc 24809+}
24810+
24811+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
24812+{
24813+ struct au_branch *br;
24814+ struct kobject *kobj;
24815+ aufs_bindex_t bend;
24816+
24817+ dbgaufs_brs_del(sb, bindex);
24818+
24819+ if (!sysaufs_brs)
24820+ return;
24821+
24822+ kobj = &au_sbi(sb)->si_kobj;
24823+ bend = au_sbend(sb);
24824+ for (; bindex <= bend; bindex++) {
24825+ br = au_sbr(sb, bindex);
24826+ sysfs_remove_file(kobj, &br->br_attr);
24827+ }
24828+}
24829+
24830+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
24831+{
24832+ int err;
24833+ aufs_bindex_t bend;
24834+ struct kobject *kobj;
24835+ struct au_branch *br;
24836+
24837+ dbgaufs_brs_add(sb, bindex);
24838+
24839+ if (!sysaufs_brs)
24840+ return;
24841+
24842+ kobj = &au_sbi(sb)->si_kobj;
24843+ bend = au_sbend(sb);
24844+ for (; bindex <= bend; bindex++) {
24845+ br = au_sbr(sb, bindex);
24846+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
24847+ "%d", bindex);
24848+ err = sysfs_create_file(kobj, &br->br_attr);
24849+ if (unlikely(err))
0c3ec466
AM
24850+ pr_warn("failed %s under sysfs(%d)\n",
24851+ br->br_name, err);
1facf9fc 24852+ }
24853+}
7f207e10
AM
24854diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
24855--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 24856+++ linux/fs/aufs/sysrq.c 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 24857@@ -0,0 +1,148 @@
1facf9fc 24858+/*
f6c5ef8b 24859+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24860+ *
24861+ * This program, aufs is free software; you can redistribute it and/or modify
24862+ * it under the terms of the GNU General Public License as published by
24863+ * the Free Software Foundation; either version 2 of the License, or
24864+ * (at your option) any later version.
dece6358
AM
24865+ *
24866+ * This program is distributed in the hope that it will be useful,
24867+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24868+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24869+ * GNU General Public License for more details.
24870+ *
24871+ * You should have received a copy of the GNU General Public License
24872+ * along with this program; if not, write to the Free Software
24873+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24874+ */
24875+
24876+/*
24877+ * magic sysrq hanlder
24878+ */
24879+
1facf9fc 24880+/* #include <linux/sysrq.h> */
027c5e7a 24881+#include <linux/writeback.h>
1facf9fc 24882+#include "aufs.h"
24883+
24884+/* ---------------------------------------------------------------------- */
24885+
24886+static void sysrq_sb(struct super_block *sb)
24887+{
24888+ char *plevel;
24889+ struct au_sbinfo *sbinfo;
24890+ struct file *file;
24891+
24892+ plevel = au_plevel;
24893+ au_plevel = KERN_WARNING;
1facf9fc 24894+
24895+ sbinfo = au_sbi(sb);
4a4d8108
AM
24896+ /* since we define pr_fmt, call printk directly */
24897+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
24898+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 24899+ au_dpri_sb(sb);
027c5e7a
AM
24900+
24901+#if 0
4a4d8108 24902+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 24903+ au_dpri_dentry(sb->s_root);
4a4d8108 24904+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 24905+ au_dpri_inode(sb->s_root->d_inode);
027c5e7a
AM
24906+#endif
24907+
1facf9fc 24908+#if 0
027c5e7a
AM
24909+ do {
24910+ int err, i, j, ndentry;
24911+ struct au_dcsub_pages dpages;
24912+ struct au_dpage *dpage;
24913+
24914+ err = au_dpages_init(&dpages, GFP_ATOMIC);
24915+ if (unlikely(err))
24916+ break;
24917+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
24918+ if (!err)
24919+ for (i = 0; i < dpages.ndpage; i++) {
24920+ dpage = dpages.dpages + i;
24921+ ndentry = dpage->ndentry;
24922+ for (j = 0; j < ndentry; j++)
24923+ au_dpri_dentry(dpage->dentries[j]);
24924+ }
24925+ au_dpages_free(&dpages);
24926+ } while (0);
24927+#endif
24928+
24929+#if 1
24930+ {
24931+ struct inode *i;
24932+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
2cbb1c4b
JR
24933+ spin_lock(&inode_sb_list_lock);
24934+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
24935+ spin_lock(&i->i_lock);
027c5e7a
AM
24936+ if (1 || list_empty(&i->i_dentry))
24937+ au_dpri_inode(i);
2cbb1c4b
JR
24938+ spin_unlock(&i->i_lock);
24939+ }
24940+ spin_unlock(&inode_sb_list_lock);
027c5e7a 24941+ }
1facf9fc 24942+#endif
4a4d8108 24943+ printk(KERN_WARNING AUFS_NAME ": files\n");
0c3ec466 24944+ lg_global_lock(&files_lglock);
0c5527e5 24945+ do_file_list_for_each_entry(sb, file) {
4a4d8108
AM
24946+ umode_t mode;
24947+ mode = file->f_dentry->d_inode->i_mode;
24948+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 24949+ au_dpri_file(file);
0c5527e5 24950+ } while_file_list_for_each_entry;
0c3ec466 24951+ lg_global_unlock(&files_lglock);
e49829fe 24952+ printk(KERN_WARNING AUFS_NAME ": done\n");
1facf9fc 24953+
24954+ au_plevel = plevel;
1facf9fc 24955+}
24956+
24957+/* ---------------------------------------------------------------------- */
24958+
24959+/* module parameter */
24960+static char *aufs_sysrq_key = "a";
24961+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
24962+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
24963+
0c5527e5 24964+static void au_sysrq(int key __maybe_unused)
1facf9fc 24965+{
1facf9fc 24966+ struct au_sbinfo *sbinfo;
24967+
027c5e7a 24968+ lockdep_off();
53392da6 24969+ au_sbilist_lock();
e49829fe 24970+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
1facf9fc 24971+ sysrq_sb(sbinfo->si_sb);
53392da6 24972+ au_sbilist_unlock();
027c5e7a 24973+ lockdep_on();
1facf9fc 24974+}
24975+
24976+static struct sysrq_key_op au_sysrq_op = {
24977+ .handler = au_sysrq,
24978+ .help_msg = "Aufs",
24979+ .action_msg = "Aufs",
24980+ .enable_mask = SYSRQ_ENABLE_DUMP
24981+};
24982+
24983+/* ---------------------------------------------------------------------- */
24984+
24985+int __init au_sysrq_init(void)
24986+{
24987+ int err;
24988+ char key;
24989+
24990+ err = -1;
24991+ key = *aufs_sysrq_key;
24992+ if ('a' <= key && key <= 'z')
24993+ err = register_sysrq_key(key, &au_sysrq_op);
24994+ if (unlikely(err))
4a4d8108 24995+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 24996+ return err;
24997+}
24998+
24999+void au_sysrq_fin(void)
25000+{
25001+ int err;
25002+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
25003+ if (unlikely(err))
4a4d8108 25004+ pr_err("err %d (ignored)\n", err);
1facf9fc 25005+}
7f207e10
AM
25006diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
25007--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 25008+++ linux/fs/aufs/vdir.c 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 25009@@ -0,0 +1,885 @@
1facf9fc 25010+/*
f6c5ef8b 25011+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 25012+ *
25013+ * This program, aufs is free software; you can redistribute it and/or modify
25014+ * it under the terms of the GNU General Public License as published by
25015+ * the Free Software Foundation; either version 2 of the License, or
25016+ * (at your option) any later version.
dece6358
AM
25017+ *
25018+ * This program is distributed in the hope that it will be useful,
25019+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25020+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25021+ * GNU General Public License for more details.
25022+ *
25023+ * You should have received a copy of the GNU General Public License
25024+ * along with this program; if not, write to the Free Software
25025+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25026+ */
25027+
25028+/*
25029+ * virtual or vertical directory
25030+ */
25031+
25032+#include "aufs.h"
25033+
dece6358 25034+static unsigned int calc_size(int nlen)
1facf9fc 25035+{
dece6358 25036+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 25037+}
25038+
25039+static int set_deblk_end(union au_vdir_deblk_p *p,
25040+ union au_vdir_deblk_p *deblk_end)
25041+{
25042+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
25043+ p->de->de_str.len = 0;
25044+ /* smp_mb(); */
25045+ return 0;
25046+ }
25047+ return -1; /* error */
25048+}
25049+
25050+/* returns true or false */
25051+static int is_deblk_end(union au_vdir_deblk_p *p,
25052+ union au_vdir_deblk_p *deblk_end)
25053+{
25054+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
25055+ return !p->de->de_str.len;
25056+ return 1;
25057+}
25058+
25059+static unsigned char *last_deblk(struct au_vdir *vdir)
25060+{
25061+ return vdir->vd_deblk[vdir->vd_nblk - 1];
25062+}
25063+
25064+/* ---------------------------------------------------------------------- */
25065+
1308ab2a 25066+/* estimate the apropriate size for name hash table */
25067+unsigned int au_rdhash_est(loff_t sz)
25068+{
25069+ unsigned int n;
25070+
25071+ n = UINT_MAX;
25072+ sz >>= 10;
25073+ if (sz < n)
25074+ n = sz;
25075+ if (sz < AUFS_RDHASH_DEF)
25076+ n = AUFS_RDHASH_DEF;
4a4d8108 25077+ /* pr_info("n %u\n", n); */
1308ab2a 25078+ return n;
25079+}
25080+
1facf9fc 25081+/*
25082+ * the allocated memory has to be freed by
dece6358 25083+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 25084+ */
dece6358 25085+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 25086+{
1facf9fc 25087+ struct hlist_head *head;
dece6358 25088+ unsigned int u;
1facf9fc 25089+
dece6358
AM
25090+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
25091+ if (head) {
25092+ nhash->nh_num = num_hash;
25093+ nhash->nh_head = head;
25094+ for (u = 0; u < num_hash; u++)
1facf9fc 25095+ INIT_HLIST_HEAD(head++);
dece6358 25096+ return 0; /* success */
1facf9fc 25097+ }
1facf9fc 25098+
dece6358 25099+ return -ENOMEM;
1facf9fc 25100+}
25101+
dece6358
AM
25102+static void nhash_count(struct hlist_head *head)
25103+{
25104+#if 0
25105+ unsigned long n;
25106+ struct hlist_node *pos;
25107+
25108+ n = 0;
25109+ hlist_for_each(pos, head)
25110+ n++;
4a4d8108 25111+ pr_info("%lu\n", n);
dece6358
AM
25112+#endif
25113+}
25114+
25115+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 25116+{
1facf9fc 25117+ struct au_vdir_wh *tpos;
25118+ struct hlist_node *pos, *node;
25119+
dece6358
AM
25120+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
25121+ /* hlist_del(pos); */
25122+ kfree(tpos);
1facf9fc 25123+ }
25124+}
25125+
dece6358 25126+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 25127+{
dece6358
AM
25128+ struct au_vdir_dehstr *tpos;
25129+ struct hlist_node *pos, *node;
1facf9fc 25130+
dece6358
AM
25131+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
25132+ /* hlist_del(pos); */
4a4d8108 25133+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 25134+ }
1facf9fc 25135+}
25136+
dece6358
AM
25137+static void au_nhash_do_free(struct au_nhash *nhash,
25138+ void (*free)(struct hlist_head *head))
1facf9fc 25139+{
1308ab2a 25140+ unsigned int n;
1facf9fc 25141+ struct hlist_head *head;
1facf9fc 25142+
dece6358 25143+ n = nhash->nh_num;
1308ab2a 25144+ if (!n)
25145+ return;
25146+
dece6358 25147+ head = nhash->nh_head;
1308ab2a 25148+ while (n-- > 0) {
dece6358
AM
25149+ nhash_count(head);
25150+ free(head++);
1facf9fc 25151+ }
dece6358 25152+ kfree(nhash->nh_head);
1facf9fc 25153+}
25154+
dece6358 25155+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 25156+{
dece6358
AM
25157+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
25158+}
1facf9fc 25159+
dece6358
AM
25160+static void au_nhash_de_free(struct au_nhash *delist)
25161+{
25162+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 25163+}
25164+
25165+/* ---------------------------------------------------------------------- */
25166+
25167+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
25168+ int limit)
25169+{
25170+ int num;
25171+ unsigned int u, n;
25172+ struct hlist_head *head;
25173+ struct au_vdir_wh *tpos;
25174+ struct hlist_node *pos;
25175+
25176+ num = 0;
25177+ n = whlist->nh_num;
25178+ head = whlist->nh_head;
1308ab2a 25179+ for (u = 0; u < n; u++, head++)
1facf9fc 25180+ hlist_for_each_entry(tpos, pos, head, wh_hash)
25181+ if (tpos->wh_bindex == btgt && ++num > limit)
25182+ return 1;
1facf9fc 25183+ return 0;
25184+}
25185+
25186+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 25187+ unsigned char *name,
1facf9fc 25188+ unsigned int len)
25189+{
dece6358
AM
25190+ unsigned int v;
25191+ /* const unsigned int magic_bit = 12; */
25192+
1308ab2a 25193+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
25194+
dece6358
AM
25195+ v = 0;
25196+ while (len--)
25197+ v += *name++;
25198+ /* v = hash_long(v, magic_bit); */
25199+ v %= nhash->nh_num;
25200+ return nhash->nh_head + v;
25201+}
25202+
25203+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
25204+ int nlen)
25205+{
25206+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 25207+}
25208+
25209+/* returns found or not */
dece6358 25210+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 25211+{
25212+ struct hlist_head *head;
25213+ struct au_vdir_wh *tpos;
25214+ struct hlist_node *pos;
25215+ struct au_vdir_destr *str;
25216+
dece6358 25217+ head = au_name_hash(whlist, name, nlen);
1facf9fc 25218+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
25219+ str = &tpos->wh_str;
25220+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
25221+ if (au_nhash_test_name(str, name, nlen))
25222+ return 1;
25223+ }
25224+ return 0;
25225+}
25226+
25227+/* returns found(true) or not */
25228+static int test_known(struct au_nhash *delist, char *name, int nlen)
25229+{
25230+ struct hlist_head *head;
25231+ struct au_vdir_dehstr *tpos;
25232+ struct hlist_node *pos;
25233+ struct au_vdir_destr *str;
25234+
25235+ head = au_name_hash(delist, name, nlen);
25236+ hlist_for_each_entry(tpos, pos, head, hash) {
25237+ str = tpos->str;
25238+ AuDbg("%.*s\n", str->len, str->name);
25239+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 25240+ return 1;
25241+ }
25242+ return 0;
25243+}
25244+
dece6358
AM
25245+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
25246+ unsigned char d_type)
25247+{
25248+#ifdef CONFIG_AUFS_SHWH
25249+ wh->wh_ino = ino;
25250+ wh->wh_type = d_type;
25251+#endif
25252+}
25253+
25254+/* ---------------------------------------------------------------------- */
25255+
25256+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
25257+ unsigned int d_type, aufs_bindex_t bindex,
25258+ unsigned char shwh)
1facf9fc 25259+{
25260+ int err;
25261+ struct au_vdir_destr *str;
25262+ struct au_vdir_wh *wh;
25263+
dece6358 25264+ AuDbg("%.*s\n", nlen, name);
1308ab2a 25265+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
25266+
1facf9fc 25267+ err = -ENOMEM;
dece6358 25268+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 25269+ if (unlikely(!wh))
25270+ goto out;
25271+
25272+ err = 0;
25273+ wh->wh_bindex = bindex;
dece6358
AM
25274+ if (shwh)
25275+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 25276+ str = &wh->wh_str;
dece6358
AM
25277+ str->len = nlen;
25278+ memcpy(str->name, name, nlen);
25279+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 25280+ /* smp_mb(); */
25281+
4f0767ce 25282+out:
1facf9fc 25283+ return err;
25284+}
25285+
1facf9fc 25286+static int append_deblk(struct au_vdir *vdir)
25287+{
25288+ int err;
dece6358 25289+ unsigned long ul;
1facf9fc 25290+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
25291+ union au_vdir_deblk_p p, deblk_end;
25292+ unsigned char **o;
25293+
25294+ err = -ENOMEM;
dece6358
AM
25295+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
25296+ GFP_NOFS);
1facf9fc 25297+ if (unlikely(!o))
25298+ goto out;
25299+
25300+ vdir->vd_deblk = o;
25301+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
25302+ if (p.deblk) {
25303+ ul = vdir->vd_nblk++;
25304+ vdir->vd_deblk[ul] = p.deblk;
25305+ vdir->vd_last.ul = ul;
25306+ vdir->vd_last.p.deblk = p.deblk;
25307+ deblk_end.deblk = p.deblk + deblk_sz;
25308+ err = set_deblk_end(&p, &deblk_end);
25309+ }
25310+
4f0767ce 25311+out:
1facf9fc 25312+ return err;
25313+}
25314+
dece6358
AM
25315+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
25316+ unsigned int d_type, struct au_nhash *delist)
25317+{
25318+ int err;
25319+ unsigned int sz;
25320+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
25321+ union au_vdir_deblk_p p, *room, deblk_end;
25322+ struct au_vdir_dehstr *dehstr;
25323+
25324+ p.deblk = last_deblk(vdir);
25325+ deblk_end.deblk = p.deblk + deblk_sz;
25326+ room = &vdir->vd_last.p;
25327+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
25328+ || !is_deblk_end(room, &deblk_end));
25329+
25330+ sz = calc_size(nlen);
25331+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
25332+ err = append_deblk(vdir);
25333+ if (unlikely(err))
25334+ goto out;
25335+
25336+ p.deblk = last_deblk(vdir);
25337+ deblk_end.deblk = p.deblk + deblk_sz;
25338+ /* smp_mb(); */
25339+ AuDebugOn(room->deblk != p.deblk);
25340+ }
25341+
25342+ err = -ENOMEM;
4a4d8108 25343+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
25344+ if (unlikely(!dehstr))
25345+ goto out;
25346+
25347+ dehstr->str = &room->de->de_str;
25348+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
25349+ room->de->de_ino = ino;
25350+ room->de->de_type = d_type;
25351+ room->de->de_str.len = nlen;
25352+ memcpy(room->de->de_str.name, name, nlen);
25353+
25354+ err = 0;
25355+ room->deblk += sz;
25356+ if (unlikely(set_deblk_end(room, &deblk_end)))
25357+ err = append_deblk(vdir);
25358+ /* smp_mb(); */
25359+
4f0767ce 25360+out:
dece6358
AM
25361+ return err;
25362+}
25363+
25364+/* ---------------------------------------------------------------------- */
25365+
25366+void au_vdir_free(struct au_vdir *vdir)
25367+{
25368+ unsigned char **deblk;
25369+
25370+ deblk = vdir->vd_deblk;
25371+ while (vdir->vd_nblk--)
25372+ kfree(*deblk++);
25373+ kfree(vdir->vd_deblk);
25374+ au_cache_free_vdir(vdir);
25375+}
25376+
1308ab2a 25377+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 25378+{
25379+ struct au_vdir *vdir;
1308ab2a 25380+ struct super_block *sb;
1facf9fc 25381+ int err;
25382+
1308ab2a 25383+ sb = file->f_dentry->d_sb;
dece6358
AM
25384+ SiMustAnyLock(sb);
25385+
1facf9fc 25386+ err = -ENOMEM;
25387+ vdir = au_cache_alloc_vdir();
25388+ if (unlikely(!vdir))
25389+ goto out;
25390+
25391+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
25392+ if (unlikely(!vdir->vd_deblk))
25393+ goto out_free;
25394+
25395+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 25396+ if (!vdir->vd_deblk_sz) {
25397+ /* estimate the apropriate size for deblk */
25398+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 25399+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 25400+ }
1facf9fc 25401+ vdir->vd_nblk = 0;
25402+ vdir->vd_version = 0;
25403+ vdir->vd_jiffy = 0;
25404+ err = append_deblk(vdir);
25405+ if (!err)
25406+ return vdir; /* success */
25407+
25408+ kfree(vdir->vd_deblk);
25409+
4f0767ce 25410+out_free:
1facf9fc 25411+ au_cache_free_vdir(vdir);
4f0767ce 25412+out:
1facf9fc 25413+ vdir = ERR_PTR(err);
25414+ return vdir;
25415+}
25416+
25417+static int reinit_vdir(struct au_vdir *vdir)
25418+{
25419+ int err;
25420+ union au_vdir_deblk_p p, deblk_end;
25421+
25422+ while (vdir->vd_nblk > 1) {
25423+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
25424+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
25425+ vdir->vd_nblk--;
25426+ }
25427+ p.deblk = vdir->vd_deblk[0];
25428+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
25429+ err = set_deblk_end(&p, &deblk_end);
25430+ /* keep vd_dblk_sz */
25431+ vdir->vd_last.ul = 0;
25432+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
25433+ vdir->vd_version = 0;
25434+ vdir->vd_jiffy = 0;
25435+ /* smp_mb(); */
25436+ return err;
25437+}
25438+
25439+/* ---------------------------------------------------------------------- */
25440+
1facf9fc 25441+#define AuFillVdir_CALLED 1
25442+#define AuFillVdir_WHABLE (1 << 1)
dece6358 25443+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 25444+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
25445+#define au_fset_fillvdir(flags, name) \
25446+ do { (flags) |= AuFillVdir_##name; } while (0)
25447+#define au_fclr_fillvdir(flags, name) \
25448+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 25449+
dece6358
AM
25450+#ifndef CONFIG_AUFS_SHWH
25451+#undef AuFillVdir_SHWH
25452+#define AuFillVdir_SHWH 0
25453+#endif
25454+
1facf9fc 25455+struct fillvdir_arg {
25456+ struct file *file;
25457+ struct au_vdir *vdir;
dece6358
AM
25458+ struct au_nhash delist;
25459+ struct au_nhash whlist;
1facf9fc 25460+ aufs_bindex_t bindex;
25461+ unsigned int flags;
25462+ int err;
25463+};
25464+
dece6358 25465+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 25466+ loff_t offset __maybe_unused, u64 h_ino,
25467+ unsigned int d_type)
25468+{
25469+ struct fillvdir_arg *arg = __arg;
25470+ char *name = (void *)__name;
25471+ struct super_block *sb;
1facf9fc 25472+ ino_t ino;
dece6358 25473+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 25474+
1facf9fc 25475+ arg->err = 0;
dece6358 25476+ sb = arg->file->f_dentry->d_sb;
1facf9fc 25477+ au_fset_fillvdir(arg->flags, CALLED);
25478+ /* smp_mb(); */
dece6358 25479+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 25480+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
25481+ if (test_known(&arg->delist, name, nlen)
25482+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
25483+ goto out; /* already exists or whiteouted */
1facf9fc 25484+
25485+ sb = arg->file->f_dentry->d_sb;
dece6358 25486+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
25487+ if (!arg->err) {
25488+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
25489+ d_type = DT_UNKNOWN;
dece6358
AM
25490+ arg->err = append_de(arg->vdir, name, nlen, ino,
25491+ d_type, &arg->delist);
4a4d8108 25492+ }
1facf9fc 25493+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
25494+ name += AUFS_WH_PFX_LEN;
dece6358
AM
25495+ nlen -= AUFS_WH_PFX_LEN;
25496+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
25497+ goto out; /* already whiteouted */
1facf9fc 25498+
dece6358
AM
25499+ if (shwh)
25500+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
25501+ &ino);
4a4d8108
AM
25502+ if (!arg->err) {
25503+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
25504+ d_type = DT_UNKNOWN;
1facf9fc 25505+ arg->err = au_nhash_append_wh
dece6358
AM
25506+ (&arg->whlist, name, nlen, ino, d_type,
25507+ arg->bindex, shwh);
4a4d8108 25508+ }
1facf9fc 25509+ }
25510+
4f0767ce 25511+out:
1facf9fc 25512+ if (!arg->err)
25513+ arg->vdir->vd_jiffy = jiffies;
25514+ /* smp_mb(); */
25515+ AuTraceErr(arg->err);
25516+ return arg->err;
25517+}
25518+
dece6358
AM
25519+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
25520+ struct au_nhash *whlist, struct au_nhash *delist)
25521+{
25522+#ifdef CONFIG_AUFS_SHWH
25523+ int err;
25524+ unsigned int nh, u;
25525+ struct hlist_head *head;
25526+ struct au_vdir_wh *tpos;
25527+ struct hlist_node *pos, *n;
25528+ char *p, *o;
25529+ struct au_vdir_destr *destr;
25530+
25531+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
25532+
25533+ err = -ENOMEM;
4a4d8108 25534+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
25535+ if (unlikely(!p))
25536+ goto out;
25537+
25538+ err = 0;
25539+ nh = whlist->nh_num;
25540+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25541+ p += AUFS_WH_PFX_LEN;
25542+ for (u = 0; u < nh; u++) {
25543+ head = whlist->nh_head + u;
25544+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
25545+ destr = &tpos->wh_str;
25546+ memcpy(p, destr->name, destr->len);
25547+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
25548+ tpos->wh_ino, tpos->wh_type, delist);
25549+ if (unlikely(err))
25550+ break;
25551+ }
25552+ }
25553+
25554+ __putname(o);
25555+
4f0767ce 25556+out:
dece6358
AM
25557+ AuTraceErr(err);
25558+ return err;
25559+#else
25560+ return 0;
25561+#endif
25562+}
25563+
1facf9fc 25564+static int au_do_read_vdir(struct fillvdir_arg *arg)
25565+{
25566+ int err;
dece6358 25567+ unsigned int rdhash;
1facf9fc 25568+ loff_t offset;
dece6358
AM
25569+ aufs_bindex_t bend, bindex, bstart;
25570+ unsigned char shwh;
1facf9fc 25571+ struct file *hf, *file;
25572+ struct super_block *sb;
25573+
1facf9fc 25574+ file = arg->file;
25575+ sb = file->f_dentry->d_sb;
dece6358
AM
25576+ SiMustAnyLock(sb);
25577+
25578+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 25579+ if (!rdhash)
25580+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
25581+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
25582+ if (unlikely(err))
1facf9fc 25583+ goto out;
dece6358
AM
25584+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
25585+ if (unlikely(err))
1facf9fc 25586+ goto out_delist;
25587+
25588+ err = 0;
25589+ arg->flags = 0;
dece6358
AM
25590+ shwh = 0;
25591+ if (au_opt_test(au_mntflags(sb), SHWH)) {
25592+ shwh = 1;
25593+ au_fset_fillvdir(arg->flags, SHWH);
25594+ }
25595+ bstart = au_fbstart(file);
4a4d8108 25596+ bend = au_fbend_dir(file);
dece6358 25597+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 25598+ hf = au_hf_dir(file, bindex);
1facf9fc 25599+ if (!hf)
25600+ continue;
25601+
25602+ offset = vfsub_llseek(hf, 0, SEEK_SET);
25603+ err = offset;
25604+ if (unlikely(offset))
25605+ break;
25606+
25607+ arg->bindex = bindex;
25608+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
25609+ if (shwh
25610+ || (bindex != bend
25611+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 25612+ au_fset_fillvdir(arg->flags, WHABLE);
25613+ do {
25614+ arg->err = 0;
25615+ au_fclr_fillvdir(arg->flags, CALLED);
25616+ /* smp_mb(); */
25617+ err = vfsub_readdir(hf, fillvdir, arg);
25618+ if (err >= 0)
25619+ err = arg->err;
25620+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
25621+ }
dece6358
AM
25622+
25623+ if (!err && shwh)
25624+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
25625+
25626+ au_nhash_wh_free(&arg->whlist);
1facf9fc 25627+
4f0767ce 25628+out_delist:
dece6358 25629+ au_nhash_de_free(&arg->delist);
4f0767ce 25630+out:
1facf9fc 25631+ return err;
25632+}
25633+
25634+static int read_vdir(struct file *file, int may_read)
25635+{
25636+ int err;
25637+ unsigned long expire;
25638+ unsigned char do_read;
25639+ struct fillvdir_arg arg;
25640+ struct inode *inode;
25641+ struct au_vdir *vdir, *allocated;
25642+
25643+ err = 0;
25644+ inode = file->f_dentry->d_inode;
25645+ IMustLock(inode);
dece6358
AM
25646+ SiMustAnyLock(inode->i_sb);
25647+
1facf9fc 25648+ allocated = NULL;
25649+ do_read = 0;
25650+ expire = au_sbi(inode->i_sb)->si_rdcache;
25651+ vdir = au_ivdir(inode);
25652+ if (!vdir) {
25653+ do_read = 1;
1308ab2a 25654+ vdir = alloc_vdir(file);
1facf9fc 25655+ err = PTR_ERR(vdir);
25656+ if (IS_ERR(vdir))
25657+ goto out;
25658+ err = 0;
25659+ allocated = vdir;
25660+ } else if (may_read
25661+ && (inode->i_version != vdir->vd_version
25662+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
25663+ do_read = 1;
25664+ err = reinit_vdir(vdir);
25665+ if (unlikely(err))
25666+ goto out;
25667+ }
25668+
25669+ if (!do_read)
25670+ return 0; /* success */
25671+
25672+ arg.file = file;
25673+ arg.vdir = vdir;
25674+ err = au_do_read_vdir(&arg);
25675+ if (!err) {
25676+ /* file->f_pos = 0; */
25677+ vdir->vd_version = inode->i_version;
25678+ vdir->vd_last.ul = 0;
25679+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
25680+ if (allocated)
25681+ au_set_ivdir(inode, allocated);
25682+ } else if (allocated)
25683+ au_vdir_free(allocated);
25684+
4f0767ce 25685+out:
1facf9fc 25686+ return err;
25687+}
25688+
25689+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
25690+{
25691+ int err, rerr;
25692+ unsigned long ul, n;
25693+ const unsigned int deblk_sz = src->vd_deblk_sz;
25694+
25695+ AuDebugOn(tgt->vd_nblk != 1);
25696+
25697+ err = -ENOMEM;
25698+ if (tgt->vd_nblk < src->vd_nblk) {
25699+ unsigned char **p;
25700+
dece6358
AM
25701+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
25702+ GFP_NOFS);
1facf9fc 25703+ if (unlikely(!p))
25704+ goto out;
25705+ tgt->vd_deblk = p;
25706+ }
25707+
1308ab2a 25708+ if (tgt->vd_deblk_sz != deblk_sz) {
25709+ unsigned char *p;
25710+
25711+ tgt->vd_deblk_sz = deblk_sz;
25712+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
25713+ if (unlikely(!p))
25714+ goto out;
25715+ tgt->vd_deblk[0] = p;
25716+ }
1facf9fc 25717+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 25718+ tgt->vd_version = src->vd_version;
25719+ tgt->vd_jiffy = src->vd_jiffy;
25720+
25721+ n = src->vd_nblk;
25722+ for (ul = 1; ul < n; ul++) {
dece6358
AM
25723+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
25724+ GFP_NOFS);
25725+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 25726+ goto out;
1308ab2a 25727+ tgt->vd_nblk++;
1facf9fc 25728+ }
1308ab2a 25729+ tgt->vd_nblk = n;
25730+ tgt->vd_last.ul = tgt->vd_last.ul;
25731+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
25732+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
25733+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 25734+ /* smp_mb(); */
25735+ return 0; /* success */
25736+
4f0767ce 25737+out:
1facf9fc 25738+ rerr = reinit_vdir(tgt);
25739+ BUG_ON(rerr);
25740+ return err;
25741+}
25742+
25743+int au_vdir_init(struct file *file)
25744+{
25745+ int err;
25746+ struct inode *inode;
25747+ struct au_vdir *vdir_cache, *allocated;
25748+
25749+ err = read_vdir(file, !file->f_pos);
25750+ if (unlikely(err))
25751+ goto out;
25752+
25753+ allocated = NULL;
25754+ vdir_cache = au_fvdir_cache(file);
25755+ if (!vdir_cache) {
1308ab2a 25756+ vdir_cache = alloc_vdir(file);
1facf9fc 25757+ err = PTR_ERR(vdir_cache);
25758+ if (IS_ERR(vdir_cache))
25759+ goto out;
25760+ allocated = vdir_cache;
25761+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
25762+ err = reinit_vdir(vdir_cache);
25763+ if (unlikely(err))
25764+ goto out;
25765+ } else
25766+ return 0; /* success */
25767+
25768+ inode = file->f_dentry->d_inode;
25769+ err = copy_vdir(vdir_cache, au_ivdir(inode));
25770+ if (!err) {
25771+ file->f_version = inode->i_version;
25772+ if (allocated)
25773+ au_set_fvdir_cache(file, allocated);
25774+ } else if (allocated)
25775+ au_vdir_free(allocated);
25776+
4f0767ce 25777+out:
1facf9fc 25778+ return err;
25779+}
25780+
25781+static loff_t calc_offset(struct au_vdir *vdir)
25782+{
25783+ loff_t offset;
25784+ union au_vdir_deblk_p p;
25785+
25786+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
25787+ offset = vdir->vd_last.p.deblk - p.deblk;
25788+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
25789+ return offset;
25790+}
25791+
25792+/* returns true or false */
25793+static int seek_vdir(struct file *file)
25794+{
25795+ int valid;
25796+ unsigned int deblk_sz;
25797+ unsigned long ul, n;
25798+ loff_t offset;
25799+ union au_vdir_deblk_p p, deblk_end;
25800+ struct au_vdir *vdir_cache;
25801+
25802+ valid = 1;
25803+ vdir_cache = au_fvdir_cache(file);
25804+ offset = calc_offset(vdir_cache);
25805+ AuDbg("offset %lld\n", offset);
25806+ if (file->f_pos == offset)
25807+ goto out;
25808+
25809+ vdir_cache->vd_last.ul = 0;
25810+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
25811+ if (!file->f_pos)
25812+ goto out;
25813+
25814+ valid = 0;
25815+ deblk_sz = vdir_cache->vd_deblk_sz;
25816+ ul = div64_u64(file->f_pos, deblk_sz);
25817+ AuDbg("ul %lu\n", ul);
25818+ if (ul >= vdir_cache->vd_nblk)
25819+ goto out;
25820+
25821+ n = vdir_cache->vd_nblk;
25822+ for (; ul < n; ul++) {
25823+ p.deblk = vdir_cache->vd_deblk[ul];
25824+ deblk_end.deblk = p.deblk + deblk_sz;
25825+ offset = ul;
25826+ offset *= deblk_sz;
25827+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
25828+ unsigned int l;
25829+
25830+ l = calc_size(p.de->de_str.len);
25831+ offset += l;
25832+ p.deblk += l;
25833+ }
25834+ if (!is_deblk_end(&p, &deblk_end)) {
25835+ valid = 1;
25836+ vdir_cache->vd_last.ul = ul;
25837+ vdir_cache->vd_last.p = p;
25838+ break;
25839+ }
25840+ }
25841+
4f0767ce 25842+out:
1facf9fc 25843+ /* smp_mb(); */
25844+ AuTraceErr(!valid);
25845+ return valid;
25846+}
25847+
25848+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
25849+{
25850+ int err;
25851+ unsigned int l, deblk_sz;
25852+ union au_vdir_deblk_p deblk_end;
25853+ struct au_vdir *vdir_cache;
25854+ struct au_vdir_de *de;
25855+
25856+ vdir_cache = au_fvdir_cache(file);
25857+ if (!seek_vdir(file))
25858+ return 0;
25859+
25860+ deblk_sz = vdir_cache->vd_deblk_sz;
25861+ while (1) {
25862+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
25863+ deblk_end.deblk += deblk_sz;
25864+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
25865+ de = vdir_cache->vd_last.p.de;
25866+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
25867+ de->de_str.len, de->de_str.name, file->f_pos,
25868+ (unsigned long)de->de_ino, de->de_type);
25869+ err = filldir(dirent, de->de_str.name, de->de_str.len,
25870+ file->f_pos, de->de_ino, de->de_type);
25871+ if (unlikely(err)) {
25872+ AuTraceErr(err);
25873+ /* todo: ignore the error caused by udba? */
25874+ /* return err; */
25875+ return 0;
25876+ }
25877+
25878+ l = calc_size(de->de_str.len);
25879+ vdir_cache->vd_last.p.deblk += l;
25880+ file->f_pos += l;
25881+ }
25882+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
25883+ vdir_cache->vd_last.ul++;
25884+ vdir_cache->vd_last.p.deblk
25885+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
25886+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
25887+ continue;
25888+ }
25889+ break;
25890+ }
25891+
25892+ /* smp_mb(); */
25893+ return 0;
25894+}
7f207e10
AM
25895diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
25896--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 25897+++ linux/fs/aufs/vfsub.c 2012-08-26 08:39:00.763841498 +0200
7eafdf33 25898@@ -0,0 +1,832 @@
1facf9fc 25899+/*
f6c5ef8b 25900+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 25901+ *
25902+ * This program, aufs is free software; you can redistribute it and/or modify
25903+ * it under the terms of the GNU General Public License as published by
25904+ * the Free Software Foundation; either version 2 of the License, or
25905+ * (at your option) any later version.
dece6358
AM
25906+ *
25907+ * This program is distributed in the hope that it will be useful,
25908+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25909+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25910+ * GNU General Public License for more details.
25911+ *
25912+ * You should have received a copy of the GNU General Public License
25913+ * along with this program; if not, write to the Free Software
25914+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25915+ */
25916+
25917+/*
25918+ * sub-routines for VFS
25919+ */
25920+
1308ab2a 25921+#include <linux/ima.h>
dece6358
AM
25922+#include <linux/namei.h>
25923+#include <linux/security.h>
25924+#include <linux/splice.h>
1facf9fc 25925+#include "aufs.h"
25926+
25927+int vfsub_update_h_iattr(struct path *h_path, int *did)
25928+{
25929+ int err;
25930+ struct kstat st;
25931+ struct super_block *h_sb;
25932+
25933+ /* for remote fs, leave work for its getattr or d_revalidate */
25934+ /* for bad i_attr fs, handle them in aufs_getattr() */
25935+ /* still some fs may acquire i_mutex. we need to skip them */
25936+ err = 0;
25937+ if (!did)
25938+ did = &err;
25939+ h_sb = h_path->dentry->d_sb;
25940+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
25941+ if (*did)
25942+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
25943+
25944+ return err;
25945+}
25946+
25947+/* ---------------------------------------------------------------------- */
25948+
4a4d8108 25949+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 25950+{
25951+ struct file *file;
25952+
4a4d8108 25953+ path_get(path);
0c5527e5 25954+ file = dentry_open(path->dentry, path->mnt,
2cbb1c4b 25955+ flags /* | __FMODE_NONOTIFY */,
7f207e10 25956+ current_cred());
2cbb1c4b
JR
25957+ if (!IS_ERR_OR_NULL(file)
25958+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
25959+ i_readcount_inc(path->dentry->d_inode);
4a4d8108 25960+
1308ab2a 25961+ return file;
25962+}
25963+
1facf9fc 25964+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
25965+{
25966+ struct file *file;
25967+
2cbb1c4b 25968+ lockdep_off();
7f207e10 25969+ file = filp_open(path,
2cbb1c4b 25970+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 25971+ mode);
2cbb1c4b 25972+ lockdep_on();
1facf9fc 25973+ if (IS_ERR(file))
25974+ goto out;
25975+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
25976+
4f0767ce 25977+out:
1facf9fc 25978+ return file;
25979+}
25980+
25981+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
25982+{
25983+ int err;
25984+
1facf9fc 25985+ err = kern_path(name, flags, path);
1facf9fc 25986+ if (!err && path->dentry->d_inode)
25987+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
25988+ return err;
25989+}
25990+
25991+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
25992+ int len)
25993+{
25994+ struct path path = {
25995+ .mnt = NULL
25996+ };
25997+
1308ab2a 25998+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 25999+ IMustLock(parent->d_inode);
26000+
26001+ path.dentry = lookup_one_len(name, parent, len);
26002+ if (IS_ERR(path.dentry))
26003+ goto out;
26004+ if (path.dentry->d_inode)
26005+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
26006+
4f0767ce 26007+out:
4a4d8108 26008+ AuTraceErrPtr(path.dentry);
1facf9fc 26009+ return path.dentry;
26010+}
26011+
26012+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
26013+{
26014+ struct path path = {
26015+ .mnt = nd->path.mnt
26016+ };
26017+
26018+ IMustLock(nd->path.dentry->d_inode);
26019+
26020+ path.dentry = lookup_hash(nd);
4a4d8108
AM
26021+ if (IS_ERR(path.dentry))
26022+ goto out;
26023+ if (path.dentry->d_inode)
1facf9fc 26024+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
26025+
4f0767ce 26026+out:
4a4d8108 26027+ AuTraceErrPtr(path.dentry);
1facf9fc 26028+ return path.dentry;
26029+}
26030+
2cbb1c4b
JR
26031+/*
26032+ * this is "VFS:__lookup_one_len()" which was removed and merged into
26033+ * VFS:lookup_one_len() by the commit.
26034+ * 6a96ba5 2011-03-14 kill __lookup_one_len()
26035+ * this function should always be equivalent to the corresponding part in
26036+ * VFS:lookup_one_len().
26037+ */
26038+int vfsub_name_hash(const char *name, struct qstr *this, int len)
26039+{
2cbb1c4b
JR
26040+ unsigned int c;
26041+
26042+ this->name = name;
26043+ this->len = len;
7eafdf33 26044+ this->hash = full_name_hash(name, len);
2cbb1c4b
JR
26045+ if (!len)
26046+ return -EACCES;
26047+
2cbb1c4b
JR
26048+ while (len--) {
26049+ c = *(const unsigned char *)name++;
26050+ if (c == '/' || c == '\0')
26051+ return -EACCES;
2cbb1c4b 26052+ }
2cbb1c4b
JR
26053+ return 0;
26054+}
26055+
1facf9fc 26056+/* ---------------------------------------------------------------------- */
26057+
26058+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
26059+ struct dentry *d2, struct au_hinode *hdir2)
26060+{
26061+ struct dentry *d;
26062+
2cbb1c4b 26063+ lockdep_off();
1facf9fc 26064+ d = lock_rename(d1, d2);
2cbb1c4b 26065+ lockdep_on();
4a4d8108 26066+ au_hn_suspend(hdir1);
1facf9fc 26067+ if (hdir1 != hdir2)
4a4d8108 26068+ au_hn_suspend(hdir2);
1facf9fc 26069+
26070+ return d;
26071+}
26072+
26073+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
26074+ struct dentry *d2, struct au_hinode *hdir2)
26075+{
4a4d8108 26076+ au_hn_resume(hdir1);
1facf9fc 26077+ if (hdir1 != hdir2)
4a4d8108 26078+ au_hn_resume(hdir2);
2cbb1c4b 26079+ lockdep_off();
1facf9fc 26080+ unlock_rename(d1, d2);
2cbb1c4b 26081+ lockdep_on();
1facf9fc 26082+}
26083+
26084+/* ---------------------------------------------------------------------- */
26085+
26086+int vfsub_create(struct inode *dir, struct path *path, int mode)
26087+{
26088+ int err;
26089+ struct dentry *d;
26090+
26091+ IMustLock(dir);
26092+
26093+ d = path->dentry;
26094+ path->dentry = d->d_parent;
b752ccd1 26095+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 26096+ path->dentry = d;
26097+ if (unlikely(err))
26098+ goto out;
26099+
26100+ if (au_test_fs_null_nd(dir->i_sb))
26101+ err = vfs_create(dir, path->dentry, mode, NULL);
26102+ else {
26103+ struct nameidata h_nd;
26104+
26105+ memset(&h_nd, 0, sizeof(h_nd));
26106+ h_nd.flags = LOOKUP_CREATE;
26107+ h_nd.intent.open.flags = O_CREAT
26108+ | vfsub_fmode_to_uint(FMODE_READ);
26109+ h_nd.intent.open.create_mode = mode;
26110+ h_nd.path.dentry = path->dentry->d_parent;
26111+ h_nd.path.mnt = path->mnt;
26112+ path_get(&h_nd.path);
26113+ err = vfs_create(dir, path->dentry, mode, &h_nd);
26114+ path_put(&h_nd.path);
26115+ }
26116+
26117+ if (!err) {
26118+ struct path tmp = *path;
26119+ int did;
26120+
26121+ vfsub_update_h_iattr(&tmp, &did);
26122+ if (did) {
26123+ tmp.dentry = path->dentry->d_parent;
26124+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26125+ }
26126+ /*ignore*/
26127+ }
26128+
4f0767ce 26129+out:
1facf9fc 26130+ return err;
26131+}
26132+
26133+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
26134+{
26135+ int err;
26136+ struct dentry *d;
26137+
26138+ IMustLock(dir);
26139+
26140+ d = path->dentry;
26141+ path->dentry = d->d_parent;
b752ccd1 26142+ err = security_path_symlink(path, d, symname);
1facf9fc 26143+ path->dentry = d;
26144+ if (unlikely(err))
26145+ goto out;
26146+
26147+ err = vfs_symlink(dir, path->dentry, symname);
26148+ if (!err) {
26149+ struct path tmp = *path;
26150+ int did;
26151+
26152+ vfsub_update_h_iattr(&tmp, &did);
26153+ if (did) {
26154+ tmp.dentry = path->dentry->d_parent;
26155+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26156+ }
26157+ /*ignore*/
26158+ }
26159+
4f0767ce 26160+out:
1facf9fc 26161+ return err;
26162+}
26163+
26164+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
26165+{
26166+ int err;
26167+ struct dentry *d;
26168+
26169+ IMustLock(dir);
26170+
26171+ d = path->dentry;
26172+ path->dentry = d->d_parent;
027c5e7a 26173+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 26174+ path->dentry = d;
26175+ if (unlikely(err))
26176+ goto out;
26177+
26178+ err = vfs_mknod(dir, path->dentry, mode, dev);
26179+ if (!err) {
26180+ struct path tmp = *path;
26181+ int did;
26182+
26183+ vfsub_update_h_iattr(&tmp, &did);
26184+ if (did) {
26185+ tmp.dentry = path->dentry->d_parent;
26186+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26187+ }
26188+ /*ignore*/
26189+ }
26190+
4f0767ce 26191+out:
1facf9fc 26192+ return err;
26193+}
26194+
26195+static int au_test_nlink(struct inode *inode)
26196+{
26197+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
26198+
26199+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
26200+ || inode->i_nlink < link_max)
26201+ return 0;
26202+ return -EMLINK;
26203+}
26204+
26205+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
26206+{
26207+ int err;
26208+ struct dentry *d;
26209+
26210+ IMustLock(dir);
26211+
26212+ err = au_test_nlink(src_dentry->d_inode);
26213+ if (unlikely(err))
26214+ return err;
26215+
26216+ d = path->dentry;
26217+ path->dentry = d->d_parent;
b752ccd1 26218+ err = security_path_link(src_dentry, path, d);
1facf9fc 26219+ path->dentry = d;
26220+ if (unlikely(err))
26221+ goto out;
26222+
2cbb1c4b 26223+ lockdep_off();
1facf9fc 26224+ err = vfs_link(src_dentry, dir, path->dentry);
2cbb1c4b 26225+ lockdep_on();
1facf9fc 26226+ if (!err) {
26227+ struct path tmp = *path;
26228+ int did;
26229+
26230+ /* fuse has different memory inode for the same inumber */
26231+ vfsub_update_h_iattr(&tmp, &did);
26232+ if (did) {
26233+ tmp.dentry = path->dentry->d_parent;
26234+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26235+ tmp.dentry = src_dentry;
26236+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26237+ }
26238+ /*ignore*/
26239+ }
26240+
4f0767ce 26241+out:
1facf9fc 26242+ return err;
26243+}
26244+
26245+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
26246+ struct inode *dir, struct path *path)
26247+{
26248+ int err;
26249+ struct path tmp = {
26250+ .mnt = path->mnt
26251+ };
26252+ struct dentry *d;
26253+
26254+ IMustLock(dir);
26255+ IMustLock(src_dir);
26256+
26257+ d = path->dentry;
26258+ path->dentry = d->d_parent;
26259+ tmp.dentry = src_dentry->d_parent;
b752ccd1 26260+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 26261+ path->dentry = d;
26262+ if (unlikely(err))
26263+ goto out;
26264+
2cbb1c4b 26265+ lockdep_off();
1facf9fc 26266+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
2cbb1c4b 26267+ lockdep_on();
1facf9fc 26268+ if (!err) {
26269+ int did;
26270+
26271+ tmp.dentry = d->d_parent;
26272+ vfsub_update_h_iattr(&tmp, &did);
26273+ if (did) {
26274+ tmp.dentry = src_dentry;
26275+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26276+ tmp.dentry = src_dentry->d_parent;
26277+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26278+ }
26279+ /*ignore*/
26280+ }
26281+
4f0767ce 26282+out:
1facf9fc 26283+ return err;
26284+}
26285+
26286+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
26287+{
26288+ int err;
26289+ struct dentry *d;
26290+
26291+ IMustLock(dir);
26292+
26293+ d = path->dentry;
26294+ path->dentry = d->d_parent;
b752ccd1 26295+ err = security_path_mkdir(path, d, mode);
1facf9fc 26296+ path->dentry = d;
26297+ if (unlikely(err))
26298+ goto out;
26299+
26300+ err = vfs_mkdir(dir, path->dentry, mode);
26301+ if (!err) {
26302+ struct path tmp = *path;
26303+ int did;
26304+
26305+ vfsub_update_h_iattr(&tmp, &did);
26306+ if (did) {
26307+ tmp.dentry = path->dentry->d_parent;
26308+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26309+ }
26310+ /*ignore*/
26311+ }
26312+
4f0767ce 26313+out:
1facf9fc 26314+ return err;
26315+}
26316+
26317+int vfsub_rmdir(struct inode *dir, struct path *path)
26318+{
26319+ int err;
26320+ struct dentry *d;
26321+
26322+ IMustLock(dir);
26323+
26324+ d = path->dentry;
26325+ path->dentry = d->d_parent;
b752ccd1 26326+ err = security_path_rmdir(path, d);
1facf9fc 26327+ path->dentry = d;
26328+ if (unlikely(err))
26329+ goto out;
26330+
2cbb1c4b 26331+ lockdep_off();
1facf9fc 26332+ err = vfs_rmdir(dir, path->dentry);
2cbb1c4b 26333+ lockdep_on();
1facf9fc 26334+ if (!err) {
26335+ struct path tmp = {
26336+ .dentry = path->dentry->d_parent,
26337+ .mnt = path->mnt
26338+ };
26339+
26340+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
26341+ }
26342+
4f0767ce 26343+out:
1facf9fc 26344+ return err;
26345+}
26346+
26347+/* ---------------------------------------------------------------------- */
26348+
9dbd164d 26349+/* todo: support mmap_sem? */
1facf9fc 26350+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
26351+ loff_t *ppos)
26352+{
26353+ ssize_t err;
26354+
2cbb1c4b 26355+ lockdep_off();
1facf9fc 26356+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 26357+ lockdep_on();
1facf9fc 26358+ if (err >= 0)
26359+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26360+ return err;
26361+}
26362+
26363+/* todo: kernel_read()? */
26364+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
26365+ loff_t *ppos)
26366+{
26367+ ssize_t err;
26368+ mm_segment_t oldfs;
b752ccd1
AM
26369+ union {
26370+ void *k;
26371+ char __user *u;
26372+ } buf;
1facf9fc 26373+
b752ccd1 26374+ buf.k = kbuf;
1facf9fc 26375+ oldfs = get_fs();
26376+ set_fs(KERNEL_DS);
b752ccd1 26377+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 26378+ set_fs(oldfs);
26379+ return err;
26380+}
26381+
26382+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
26383+ loff_t *ppos)
26384+{
26385+ ssize_t err;
26386+
2cbb1c4b 26387+ lockdep_off();
1facf9fc 26388+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 26389+ lockdep_on();
1facf9fc 26390+ if (err >= 0)
26391+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26392+ return err;
26393+}
26394+
26395+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
26396+{
26397+ ssize_t err;
26398+ mm_segment_t oldfs;
b752ccd1
AM
26399+ union {
26400+ void *k;
26401+ const char __user *u;
26402+ } buf;
1facf9fc 26403+
b752ccd1 26404+ buf.k = kbuf;
1facf9fc 26405+ oldfs = get_fs();
26406+ set_fs(KERNEL_DS);
b752ccd1 26407+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 26408+ set_fs(oldfs);
26409+ return err;
26410+}
26411+
4a4d8108
AM
26412+int vfsub_flush(struct file *file, fl_owner_t id)
26413+{
26414+ int err;
26415+
26416+ err = 0;
26417+ if (file->f_op && file->f_op->flush) {
2cbb1c4b
JR
26418+ if (!au_test_nfs(file->f_dentry->d_sb))
26419+ err = file->f_op->flush(file, id);
26420+ else {
26421+ lockdep_off();
26422+ err = file->f_op->flush(file, id);
26423+ lockdep_on();
26424+ }
4a4d8108
AM
26425+ if (!err)
26426+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
26427+ /*ignore*/
26428+ }
26429+ return err;
26430+}
26431+
1facf9fc 26432+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
26433+{
26434+ int err;
26435+
2cbb1c4b 26436+ lockdep_off();
1facf9fc 26437+ err = vfs_readdir(file, filldir, arg);
2cbb1c4b 26438+ lockdep_on();
1facf9fc 26439+ if (err >= 0)
26440+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26441+ return err;
26442+}
26443+
26444+long vfsub_splice_to(struct file *in, loff_t *ppos,
26445+ struct pipe_inode_info *pipe, size_t len,
26446+ unsigned int flags)
26447+{
26448+ long err;
26449+
2cbb1c4b 26450+ lockdep_off();
0fc653ad 26451+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 26452+ lockdep_on();
4a4d8108 26453+ file_accessed(in);
1facf9fc 26454+ if (err >= 0)
26455+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
26456+ return err;
26457+}
26458+
26459+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
26460+ loff_t *ppos, size_t len, unsigned int flags)
26461+{
26462+ long err;
26463+
2cbb1c4b 26464+ lockdep_off();
0fc653ad 26465+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 26466+ lockdep_on();
1facf9fc 26467+ if (err >= 0)
26468+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
26469+ return err;
26470+}
26471+
53392da6
AM
26472+int vfsub_fsync(struct file *file, struct path *path, int datasync)
26473+{
26474+ int err;
26475+
26476+ /* file can be NULL */
26477+ lockdep_off();
26478+ err = vfs_fsync(file, datasync);
26479+ lockdep_on();
26480+ if (!err) {
26481+ if (!path) {
26482+ AuDebugOn(!file);
26483+ path = &file->f_path;
26484+ }
26485+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
26486+ }
26487+ return err;
26488+}
26489+
1facf9fc 26490+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
26491+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
26492+ struct file *h_file)
26493+{
26494+ int err;
26495+ struct inode *h_inode;
26496+
26497+ h_inode = h_path->dentry->d_inode;
26498+ if (!h_file) {
26499+ err = mnt_want_write(h_path->mnt);
26500+ if (err)
26501+ goto out;
26502+ err = inode_permission(h_inode, MAY_WRITE);
26503+ if (err)
26504+ goto out_mnt;
26505+ err = get_write_access(h_inode);
26506+ if (err)
26507+ goto out_mnt;
4a4d8108 26508+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 26509+ if (err)
26510+ goto out_inode;
26511+ }
26512+
26513+ err = locks_verify_truncate(h_inode, h_file, length);
26514+ if (!err)
953406b4 26515+ err = security_path_truncate(h_path);
2cbb1c4b
JR
26516+ if (!err) {
26517+ lockdep_off();
1facf9fc 26518+ err = do_truncate(h_path->dentry, length, attr, h_file);
2cbb1c4b
JR
26519+ lockdep_on();
26520+ }
1facf9fc 26521+
4f0767ce 26522+out_inode:
1facf9fc 26523+ if (!h_file)
26524+ put_write_access(h_inode);
4f0767ce 26525+out_mnt:
1facf9fc 26526+ if (!h_file)
26527+ mnt_drop_write(h_path->mnt);
4f0767ce 26528+out:
1facf9fc 26529+ return err;
26530+}
26531+
26532+/* ---------------------------------------------------------------------- */
26533+
26534+struct au_vfsub_mkdir_args {
26535+ int *errp;
26536+ struct inode *dir;
26537+ struct path *path;
26538+ int mode;
26539+};
26540+
26541+static void au_call_vfsub_mkdir(void *args)
26542+{
26543+ struct au_vfsub_mkdir_args *a = args;
26544+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
26545+}
26546+
26547+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
26548+{
26549+ int err, do_sio, wkq_err;
26550+
26551+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
26552+ if (!do_sio)
26553+ err = vfsub_mkdir(dir, path, mode);
26554+ else {
26555+ struct au_vfsub_mkdir_args args = {
26556+ .errp = &err,
26557+ .dir = dir,
26558+ .path = path,
26559+ .mode = mode
26560+ };
26561+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
26562+ if (unlikely(wkq_err))
26563+ err = wkq_err;
26564+ }
26565+
26566+ return err;
26567+}
26568+
26569+struct au_vfsub_rmdir_args {
26570+ int *errp;
26571+ struct inode *dir;
26572+ struct path *path;
26573+};
26574+
26575+static void au_call_vfsub_rmdir(void *args)
26576+{
26577+ struct au_vfsub_rmdir_args *a = args;
26578+ *a->errp = vfsub_rmdir(a->dir, a->path);
26579+}
26580+
26581+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
26582+{
26583+ int err, do_sio, wkq_err;
26584+
26585+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
26586+ if (!do_sio)
26587+ err = vfsub_rmdir(dir, path);
26588+ else {
26589+ struct au_vfsub_rmdir_args args = {
26590+ .errp = &err,
26591+ .dir = dir,
26592+ .path = path
26593+ };
26594+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
26595+ if (unlikely(wkq_err))
26596+ err = wkq_err;
26597+ }
26598+
26599+ return err;
26600+}
26601+
26602+/* ---------------------------------------------------------------------- */
26603+
26604+struct notify_change_args {
26605+ int *errp;
26606+ struct path *path;
26607+ struct iattr *ia;
26608+};
26609+
26610+static void call_notify_change(void *args)
26611+{
26612+ struct notify_change_args *a = args;
26613+ struct inode *h_inode;
26614+
26615+ h_inode = a->path->dentry->d_inode;
26616+ IMustLock(h_inode);
26617+
26618+ *a->errp = -EPERM;
26619+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 26620+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 26621+ if (!*a->errp)
26622+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
26623+ }
26624+ AuTraceErr(*a->errp);
26625+}
26626+
26627+int vfsub_notify_change(struct path *path, struct iattr *ia)
26628+{
26629+ int err;
26630+ struct notify_change_args args = {
26631+ .errp = &err,
26632+ .path = path,
26633+ .ia = ia
26634+ };
26635+
26636+ call_notify_change(&args);
26637+
26638+ return err;
26639+}
26640+
26641+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
26642+{
26643+ int err, wkq_err;
26644+ struct notify_change_args args = {
26645+ .errp = &err,
26646+ .path = path,
26647+ .ia = ia
26648+ };
26649+
26650+ wkq_err = au_wkq_wait(call_notify_change, &args);
26651+ if (unlikely(wkq_err))
26652+ err = wkq_err;
26653+
26654+ return err;
26655+}
26656+
26657+/* ---------------------------------------------------------------------- */
26658+
26659+struct unlink_args {
26660+ int *errp;
26661+ struct inode *dir;
26662+ struct path *path;
26663+};
26664+
26665+static void call_unlink(void *args)
26666+{
26667+ struct unlink_args *a = args;
26668+ struct dentry *d = a->path->dentry;
26669+ struct inode *h_inode;
26670+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
027c5e7a 26671+ && d->d_count == 1);
1facf9fc 26672+
26673+ IMustLock(a->dir);
26674+
26675+ a->path->dentry = d->d_parent;
26676+ *a->errp = security_path_unlink(a->path, d);
26677+ a->path->dentry = d;
26678+ if (unlikely(*a->errp))
26679+ return;
26680+
26681+ if (!stop_sillyrename)
26682+ dget(d);
26683+ h_inode = d->d_inode;
26684+ if (h_inode)
027c5e7a 26685+ ihold(h_inode);
1facf9fc 26686+
2cbb1c4b 26687+ lockdep_off();
1facf9fc 26688+ *a->errp = vfs_unlink(a->dir, d);
2cbb1c4b 26689+ lockdep_on();
1facf9fc 26690+ if (!*a->errp) {
26691+ struct path tmp = {
26692+ .dentry = d->d_parent,
26693+ .mnt = a->path->mnt
26694+ };
26695+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
26696+ }
26697+
26698+ if (!stop_sillyrename)
26699+ dput(d);
26700+ if (h_inode)
26701+ iput(h_inode);
26702+
26703+ AuTraceErr(*a->errp);
26704+}
26705+
26706+/*
26707+ * @dir: must be locked.
26708+ * @dentry: target dentry.
26709+ */
26710+int vfsub_unlink(struct inode *dir, struct path *path, int force)
26711+{
26712+ int err;
26713+ struct unlink_args args = {
26714+ .errp = &err,
26715+ .dir = dir,
26716+ .path = path
26717+ };
26718+
26719+ if (!force)
26720+ call_unlink(&args);
26721+ else {
26722+ int wkq_err;
26723+
26724+ wkq_err = au_wkq_wait(call_unlink, &args);
26725+ if (unlikely(wkq_err))
26726+ err = wkq_err;
26727+ }
26728+
26729+ return err;
26730+}
7f207e10
AM
26731diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
26732--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 26733+++ linux/fs/aufs/vfsub.h 2012-08-26 08:39:00.763841498 +0200
0c3ec466 26734@@ -0,0 +1,252 @@
1facf9fc 26735+/*
f6c5ef8b 26736+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 26737+ *
26738+ * This program, aufs is free software; you can redistribute it and/or modify
26739+ * it under the terms of the GNU General Public License as published by
26740+ * the Free Software Foundation; either version 2 of the License, or
26741+ * (at your option) any later version.
dece6358
AM
26742+ *
26743+ * This program is distributed in the hope that it will be useful,
26744+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26745+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26746+ * GNU General Public License for more details.
26747+ *
26748+ * You should have received a copy of the GNU General Public License
26749+ * along with this program; if not, write to the Free Software
26750+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26751+ */
26752+
26753+/*
26754+ * sub-routines for VFS
26755+ */
26756+
26757+#ifndef __AUFS_VFSUB_H__
26758+#define __AUFS_VFSUB_H__
26759+
26760+#ifdef __KERNEL__
26761+
26762+#include <linux/fs.h>
0c5527e5 26763+#include <linux/lglock.h>
7f207e10 26764+#include "debug.h"
1facf9fc 26765+
7f207e10 26766+/* copied from linux/fs/internal.h */
2cbb1c4b 26767+/* todo: BAD approach!! */
0c3ec466 26768+extern struct lglock vfsmount_lock;
0c5527e5 26769+extern void file_sb_list_del(struct file *f);
2cbb1c4b 26770+extern spinlock_t inode_sb_list_lock;
0c5527e5 26771+
7f207e10 26772+/* copied from linux/fs/file_table.c */
0c3ec466 26773+extern struct lglock files_lglock;
0c5527e5
AM
26774+#ifdef CONFIG_SMP
26775+/*
26776+ * These macros iterate all files on all CPUs for a given superblock.
26777+ * files_lglock must be held globally.
26778+ */
26779+#define do_file_list_for_each_entry(__sb, __file) \
26780+{ \
26781+ int i; \
26782+ for_each_possible_cpu(i) { \
26783+ struct list_head *list; \
26784+ list = per_cpu_ptr((__sb)->s_files, i); \
26785+ list_for_each_entry((__file), list, f_u.fu_list)
26786+
26787+#define while_file_list_for_each_entry \
26788+ } \
26789+}
26790+
26791+#else
26792+
26793+#define do_file_list_for_each_entry(__sb, __file) \
26794+{ \
26795+ struct list_head *list; \
26796+ list = &(sb)->s_files; \
26797+ list_for_each_entry((__file), list, f_u.fu_list)
26798+
26799+#define while_file_list_for_each_entry \
26800+}
7f207e10
AM
26801+#endif
26802+
26803+/* ---------------------------------------------------------------------- */
1facf9fc 26804+
26805+/* lock subclass for lower inode */
26806+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
26807+/* reduce? gave up. */
26808+enum {
26809+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
26810+ AuLsc_I_PARENT, /* lower inode, parent first */
26811+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 26812+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 26813+ AuLsc_I_CHILD,
26814+ AuLsc_I_CHILD2,
26815+ AuLsc_I_End
26816+};
26817+
26818+/* to debug easier, do not make them inlined functions */
26819+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
26820+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
26821+
26822+/* ---------------------------------------------------------------------- */
26823+
7f207e10
AM
26824+static inline void vfsub_drop_nlink(struct inode *inode)
26825+{
26826+ AuDebugOn(!inode->i_nlink);
26827+ drop_nlink(inode);
26828+}
26829+
027c5e7a
AM
26830+static inline void vfsub_dead_dir(struct inode *inode)
26831+{
26832+ AuDebugOn(!S_ISDIR(inode->i_mode));
26833+ inode->i_flags |= S_DEAD;
26834+ clear_nlink(inode);
26835+}
26836+
7f207e10
AM
26837+/* ---------------------------------------------------------------------- */
26838+
0c3ec466
AM
26839+/* cf. i_[ug]id_read() in linux/include/fs.h */
26840+static inline uid_t vfsub_ia_uid(struct iattr *ia)
26841+{
26842+ return from_kuid(&init_user_ns, ia->ia_uid);
26843+}
26844+
26845+static inline gid_t vfsub_ia_gid(struct iattr *ia)
26846+{
26847+ return from_kgid(&init_user_ns, ia->ia_gid);
26848+}
26849+
26850+/* ---------------------------------------------------------------------- */
26851+
7f207e10
AM
26852+int vfsub_update_h_iattr(struct path *h_path, int *did);
26853+struct file *vfsub_dentry_open(struct path *path, int flags);
26854+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
1facf9fc 26855+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
26856+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
26857+ int len);
26858+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
2cbb1c4b 26859+int vfsub_name_hash(const char *name, struct qstr *this, int len);
1facf9fc 26860+
26861+/* ---------------------------------------------------------------------- */
26862+
26863+struct au_hinode;
26864+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
26865+ struct dentry *d2, struct au_hinode *hdir2);
26866+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
26867+ struct dentry *d2, struct au_hinode *hdir2);
26868+
26869+int vfsub_create(struct inode *dir, struct path *path, int mode);
26870+int vfsub_symlink(struct inode *dir, struct path *path,
26871+ const char *symname);
26872+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
26873+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
26874+ struct path *path);
26875+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
26876+ struct inode *hdir, struct path *path);
26877+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
26878+int vfsub_rmdir(struct inode *dir, struct path *path);
26879+
26880+/* ---------------------------------------------------------------------- */
26881+
26882+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
26883+ loff_t *ppos);
26884+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
26885+ loff_t *ppos);
26886+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
26887+ loff_t *ppos);
26888+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
26889+ loff_t *ppos);
4a4d8108 26890+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 26891+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
26892+
4a4d8108
AM
26893+static inline unsigned int vfsub_file_flags(struct file *file)
26894+{
26895+ unsigned int flags;
26896+
26897+ spin_lock(&file->f_lock);
26898+ flags = file->f_flags;
26899+ spin_unlock(&file->f_lock);
26900+
26901+ return flags;
26902+}
1308ab2a 26903+
1facf9fc 26904+static inline void vfsub_file_accessed(struct file *h_file)
26905+{
26906+ file_accessed(h_file);
26907+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
26908+}
26909+
26910+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
26911+ struct dentry *h_dentry)
26912+{
26913+ struct path h_path = {
26914+ .dentry = h_dentry,
26915+ .mnt = h_mnt
26916+ };
92d182d2 26917+ touch_atime(&h_path);
1facf9fc 26918+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
26919+}
26920+
0c3ec466
AM
26921+static inline int vfsub_update_time(struct inode *h_inode, struct timespec *ts,
26922+ int flags)
26923+{
26924+ return update_time(h_inode, ts, flags);
26925+ /* no vfsub_update_h_iattr() since we don't have struct path */
26926+}
26927+
4a4d8108
AM
26928+long vfsub_splice_to(struct file *in, loff_t *ppos,
26929+ struct pipe_inode_info *pipe, size_t len,
26930+ unsigned int flags);
26931+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
26932+ loff_t *ppos, size_t len, unsigned int flags);
26933+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
26934+ struct file *h_file);
53392da6 26935+int vfsub_fsync(struct file *file, struct path *path, int datasync);
4a4d8108 26936+
1facf9fc 26937+/* ---------------------------------------------------------------------- */
26938+
26939+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
26940+{
26941+ loff_t err;
26942+
2cbb1c4b 26943+ lockdep_off();
1facf9fc 26944+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 26945+ lockdep_on();
1facf9fc 26946+ return err;
26947+}
26948+
26949+/* ---------------------------------------------------------------------- */
26950+
26951+/* dirty workaround for strict type of fmode_t */
26952+union vfsub_fmu {
26953+ fmode_t fm;
26954+ unsigned int ui;
26955+};
26956+
26957+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
26958+{
26959+ union vfsub_fmu u = {
26960+ .fm = fm
26961+ };
26962+
26963+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
26964+
26965+ return u.ui;
26966+}
26967+
26968+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
26969+{
26970+ union vfsub_fmu u = {
26971+ .ui = ui
26972+ };
26973+
26974+ return u.fm;
26975+}
26976+
4a4d8108
AM
26977+/* ---------------------------------------------------------------------- */
26978+
26979+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
26980+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
26981+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
26982+int vfsub_notify_change(struct path *path, struct iattr *ia);
26983+int vfsub_unlink(struct inode *dir, struct path *path, int force);
26984+
1facf9fc 26985+#endif /* __KERNEL__ */
26986+#endif /* __AUFS_VFSUB_H__ */
7f207e10
AM
26987diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
26988--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 26989+++ linux/fs/aufs/wbr_policy.c 2012-08-26 08:39:00.763841498 +0200
027c5e7a 26990@@ -0,0 +1,700 @@
1facf9fc 26991+/*
f6c5ef8b 26992+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 26993+ *
26994+ * This program, aufs is free software; you can redistribute it and/or modify
26995+ * it under the terms of the GNU General Public License as published by
26996+ * the Free Software Foundation; either version 2 of the License, or
26997+ * (at your option) any later version.
dece6358
AM
26998+ *
26999+ * This program is distributed in the hope that it will be useful,
27000+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27001+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27002+ * GNU General Public License for more details.
27003+ *
27004+ * You should have received a copy of the GNU General Public License
27005+ * along with this program; if not, write to the Free Software
27006+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27007+ */
27008+
27009+/*
27010+ * policies for selecting one among multiple writable branches
27011+ */
27012+
27013+#include <linux/statfs.h>
27014+#include "aufs.h"
27015+
27016+/* subset of cpup_attr() */
27017+static noinline_for_stack
27018+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
27019+{
27020+ int err, sbits;
27021+ struct iattr ia;
27022+ struct inode *h_isrc;
27023+
27024+ h_isrc = h_src->d_inode;
27025+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
27026+ ia.ia_mode = h_isrc->i_mode;
27027+ ia.ia_uid = h_isrc->i_uid;
27028+ ia.ia_gid = h_isrc->i_gid;
27029+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
27030+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
27031+ err = vfsub_sio_notify_change(h_path, &ia);
27032+
27033+ /* is this nfs only? */
27034+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
27035+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
27036+ ia.ia_mode = h_isrc->i_mode;
27037+ err = vfsub_sio_notify_change(h_path, &ia);
27038+ }
27039+
27040+ return err;
27041+}
27042+
27043+#define AuCpdown_PARENT_OPQ 1
27044+#define AuCpdown_WHED (1 << 1)
27045+#define AuCpdown_MADE_DIR (1 << 2)
27046+#define AuCpdown_DIROPQ (1 << 3)
27047+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
27048+#define au_fset_cpdown(flags, name) \
27049+ do { (flags) |= AuCpdown_##name; } while (0)
27050+#define au_fclr_cpdown(flags, name) \
27051+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 27052+
27053+struct au_cpdown_dir_args {
27054+ struct dentry *parent;
27055+ unsigned int flags;
27056+};
27057+
27058+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
27059+ struct au_cpdown_dir_args *a)
27060+{
27061+ int err;
27062+ struct dentry *opq_dentry;
27063+
27064+ opq_dentry = au_diropq_create(dentry, bdst);
27065+ err = PTR_ERR(opq_dentry);
27066+ if (IS_ERR(opq_dentry))
27067+ goto out;
27068+ dput(opq_dentry);
27069+ au_fset_cpdown(a->flags, DIROPQ);
27070+
4f0767ce 27071+out:
1facf9fc 27072+ return err;
27073+}
27074+
27075+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
27076+ struct inode *dir, aufs_bindex_t bdst)
27077+{
27078+ int err;
27079+ struct path h_path;
27080+ struct au_branch *br;
27081+
27082+ br = au_sbr(dentry->d_sb, bdst);
27083+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
27084+ err = PTR_ERR(h_path.dentry);
27085+ if (IS_ERR(h_path.dentry))
27086+ goto out;
27087+
27088+ err = 0;
27089+ if (h_path.dentry->d_inode) {
27090+ h_path.mnt = br->br_mnt;
27091+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
27092+ dentry);
27093+ }
27094+ dput(h_path.dentry);
27095+
4f0767ce 27096+out:
1facf9fc 27097+ return err;
27098+}
27099+
27100+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
27101+ struct dentry *h_parent, void *arg)
27102+{
27103+ int err, rerr;
4a4d8108 27104+ aufs_bindex_t bopq, bstart;
1facf9fc 27105+ struct path h_path;
27106+ struct dentry *parent;
27107+ struct inode *h_dir, *h_inode, *inode, *dir;
27108+ struct au_cpdown_dir_args *args = arg;
27109+
27110+ bstart = au_dbstart(dentry);
27111+ /* dentry is di-locked */
27112+ parent = dget_parent(dentry);
27113+ dir = parent->d_inode;
27114+ h_dir = h_parent->d_inode;
27115+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
27116+ IMustLock(h_dir);
27117+
27118+ err = au_lkup_neg(dentry, bdst);
27119+ if (unlikely(err < 0))
27120+ goto out;
27121+ h_path.dentry = au_h_dptr(dentry, bdst);
27122+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
27123+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
27124+ S_IRWXU | S_IRUGO | S_IXUGO);
27125+ if (unlikely(err))
27126+ goto out_put;
27127+ au_fset_cpdown(args->flags, MADE_DIR);
27128+
1facf9fc 27129+ bopq = au_dbdiropq(dentry);
27130+ au_fclr_cpdown(args->flags, WHED);
27131+ au_fclr_cpdown(args->flags, DIROPQ);
27132+ if (au_dbwh(dentry) == bdst)
27133+ au_fset_cpdown(args->flags, WHED);
27134+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
27135+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 27136+ h_inode = h_path.dentry->d_inode;
27137+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
27138+ if (au_ftest_cpdown(args->flags, WHED)) {
27139+ err = au_cpdown_dir_opq(dentry, bdst, args);
27140+ if (unlikely(err)) {
27141+ mutex_unlock(&h_inode->i_mutex);
27142+ goto out_dir;
27143+ }
27144+ }
27145+
27146+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
27147+ mutex_unlock(&h_inode->i_mutex);
27148+ if (unlikely(err))
27149+ goto out_opq;
27150+
27151+ if (au_ftest_cpdown(args->flags, WHED)) {
27152+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
27153+ if (unlikely(err))
27154+ goto out_opq;
27155+ }
27156+
27157+ inode = dentry->d_inode;
27158+ if (au_ibend(inode) < bdst)
27159+ au_set_ibend(inode, bdst);
27160+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
27161+ au_hi_flags(inode, /*isdir*/1));
27162+ goto out; /* success */
27163+
27164+ /* revert */
4f0767ce 27165+out_opq:
1facf9fc 27166+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
27167+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
27168+ rerr = au_diropq_remove(dentry, bdst);
27169+ mutex_unlock(&h_inode->i_mutex);
27170+ if (unlikely(rerr)) {
27171+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
27172+ AuDLNPair(dentry), bdst, rerr);
27173+ err = -EIO;
27174+ goto out;
27175+ }
27176+ }
4f0767ce 27177+out_dir:
1facf9fc 27178+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
27179+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
27180+ if (unlikely(rerr)) {
27181+ AuIOErr("failed removing %.*s b%d (%d)\n",
27182+ AuDLNPair(dentry), bdst, rerr);
27183+ err = -EIO;
27184+ }
27185+ }
4f0767ce 27186+out_put:
1facf9fc 27187+ au_set_h_dptr(dentry, bdst, NULL);
27188+ if (au_dbend(dentry) == bdst)
27189+ au_update_dbend(dentry);
4f0767ce 27190+out:
1facf9fc 27191+ dput(parent);
27192+ return err;
27193+}
27194+
27195+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
27196+{
27197+ int err;
27198+ struct au_cpdown_dir_args args = {
27199+ .parent = dget_parent(dentry),
27200+ .flags = 0
27201+ };
27202+
27203+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
27204+ dput(args.parent);
27205+
27206+ return err;
27207+}
27208+
27209+/* ---------------------------------------------------------------------- */
27210+
27211+/* policies for create */
27212+
4a4d8108
AM
27213+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
27214+{
27215+ int err, i, j, ndentry;
27216+ aufs_bindex_t bopq;
27217+ struct au_dcsub_pages dpages;
27218+ struct au_dpage *dpage;
27219+ struct dentry **dentries, *parent, *d;
27220+
27221+ err = au_dpages_init(&dpages, GFP_NOFS);
27222+ if (unlikely(err))
27223+ goto out;
27224+ parent = dget_parent(dentry);
027c5e7a 27225+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
27226+ if (unlikely(err))
27227+ goto out_free;
27228+
27229+ err = bindex;
27230+ for (i = 0; i < dpages.ndpage; i++) {
27231+ dpage = dpages.dpages + i;
27232+ dentries = dpage->dentries;
27233+ ndentry = dpage->ndentry;
27234+ for (j = 0; j < ndentry; j++) {
27235+ d = dentries[j];
27236+ di_read_lock_parent2(d, !AuLock_IR);
27237+ bopq = au_dbdiropq(d);
27238+ di_read_unlock(d, !AuLock_IR);
27239+ if (bopq >= 0 && bopq < err)
27240+ err = bopq;
27241+ }
27242+ }
27243+
27244+out_free:
27245+ dput(parent);
27246+ au_dpages_free(&dpages);
27247+out:
27248+ return err;
27249+}
27250+
1facf9fc 27251+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
27252+{
27253+ for (; bindex >= 0; bindex--)
27254+ if (!au_br_rdonly(au_sbr(sb, bindex)))
27255+ return bindex;
27256+ return -EROFS;
27257+}
27258+
27259+/* top down parent */
27260+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
27261+{
27262+ int err;
27263+ aufs_bindex_t bstart, bindex;
27264+ struct super_block *sb;
27265+ struct dentry *parent, *h_parent;
27266+
27267+ sb = dentry->d_sb;
27268+ bstart = au_dbstart(dentry);
27269+ err = bstart;
27270+ if (!au_br_rdonly(au_sbr(sb, bstart)))
27271+ goto out;
27272+
27273+ err = -EROFS;
27274+ parent = dget_parent(dentry);
27275+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
27276+ h_parent = au_h_dptr(parent, bindex);
27277+ if (!h_parent || !h_parent->d_inode)
27278+ continue;
27279+
27280+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
27281+ err = bindex;
27282+ break;
27283+ }
27284+ }
27285+ dput(parent);
27286+
27287+ /* bottom up here */
4a4d8108 27288+ if (unlikely(err < 0)) {
1facf9fc 27289+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
27290+ if (err >= 0)
27291+ err = au_wbr_nonopq(dentry, err);
27292+ }
1facf9fc 27293+
4f0767ce 27294+out:
1facf9fc 27295+ AuDbg("b%d\n", err);
27296+ return err;
27297+}
27298+
27299+/* ---------------------------------------------------------------------- */
27300+
27301+/* an exception for the policy other than tdp */
27302+static int au_wbr_create_exp(struct dentry *dentry)
27303+{
27304+ int err;
27305+ aufs_bindex_t bwh, bdiropq;
27306+ struct dentry *parent;
27307+
27308+ err = -1;
27309+ bwh = au_dbwh(dentry);
27310+ parent = dget_parent(dentry);
27311+ bdiropq = au_dbdiropq(parent);
27312+ if (bwh >= 0) {
27313+ if (bdiropq >= 0)
27314+ err = min(bdiropq, bwh);
27315+ else
27316+ err = bwh;
27317+ AuDbg("%d\n", err);
27318+ } else if (bdiropq >= 0) {
27319+ err = bdiropq;
27320+ AuDbg("%d\n", err);
27321+ }
27322+ dput(parent);
27323+
4a4d8108
AM
27324+ if (err >= 0)
27325+ err = au_wbr_nonopq(dentry, err);
27326+
1facf9fc 27327+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
27328+ err = -1;
27329+
27330+ AuDbg("%d\n", err);
27331+ return err;
27332+}
27333+
27334+/* ---------------------------------------------------------------------- */
27335+
27336+/* round robin */
27337+static int au_wbr_create_init_rr(struct super_block *sb)
27338+{
27339+ int err;
27340+
27341+ err = au_wbr_bu(sb, au_sbend(sb));
27342+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 27343+ /* smp_mb(); */
1facf9fc 27344+
27345+ AuDbg("b%d\n", err);
27346+ return err;
27347+}
27348+
27349+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
27350+{
27351+ int err, nbr;
27352+ unsigned int u;
27353+ aufs_bindex_t bindex, bend;
27354+ struct super_block *sb;
27355+ atomic_t *next;
27356+
27357+ err = au_wbr_create_exp(dentry);
27358+ if (err >= 0)
27359+ goto out;
27360+
27361+ sb = dentry->d_sb;
27362+ next = &au_sbi(sb)->si_wbr_rr_next;
27363+ bend = au_sbend(sb);
27364+ nbr = bend + 1;
27365+ for (bindex = 0; bindex <= bend; bindex++) {
27366+ if (!isdir) {
27367+ err = atomic_dec_return(next) + 1;
27368+ /* modulo for 0 is meaningless */
27369+ if (unlikely(!err))
27370+ err = atomic_dec_return(next) + 1;
27371+ } else
27372+ err = atomic_read(next);
27373+ AuDbg("%d\n", err);
27374+ u = err;
27375+ err = u % nbr;
27376+ AuDbg("%d\n", err);
27377+ if (!au_br_rdonly(au_sbr(sb, err)))
27378+ break;
27379+ err = -EROFS;
27380+ }
27381+
4a4d8108
AM
27382+ if (err >= 0)
27383+ err = au_wbr_nonopq(dentry, err);
27384+
4f0767ce 27385+out:
1facf9fc 27386+ AuDbg("%d\n", err);
27387+ return err;
27388+}
27389+
27390+/* ---------------------------------------------------------------------- */
27391+
27392+/* most free space */
27393+static void au_mfs(struct dentry *dentry)
27394+{
27395+ struct super_block *sb;
27396+ struct au_branch *br;
27397+ struct au_wbr_mfs *mfs;
27398+ aufs_bindex_t bindex, bend;
27399+ int err;
27400+ unsigned long long b, bavail;
7f207e10 27401+ struct path h_path;
1facf9fc 27402+ /* reduce the stack usage */
27403+ struct kstatfs *st;
27404+
27405+ st = kmalloc(sizeof(*st), GFP_NOFS);
27406+ if (unlikely(!st)) {
27407+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
27408+ return;
27409+ }
27410+
27411+ bavail = 0;
27412+ sb = dentry->d_sb;
27413+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 27414+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 27415+ mfs->mfs_bindex = -EROFS;
27416+ mfs->mfsrr_bytes = 0;
27417+ bend = au_sbend(sb);
27418+ for (bindex = 0; bindex <= bend; bindex++) {
27419+ br = au_sbr(sb, bindex);
27420+ if (au_br_rdonly(br))
27421+ continue;
27422+
27423+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
27424+ h_path.mnt = br->br_mnt;
27425+ h_path.dentry = h_path.mnt->mnt_root;
27426+ err = vfs_statfs(&h_path, st);
1facf9fc 27427+ if (unlikely(err)) {
27428+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
27429+ continue;
27430+ }
27431+
27432+ /* when the available size is equal, select the lower one */
27433+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
27434+ || sizeof(b) < sizeof(st->f_bsize));
27435+ b = st->f_bavail * st->f_bsize;
27436+ br->br_wbr->wbr_bytes = b;
27437+ if (b >= bavail) {
27438+ bavail = b;
27439+ mfs->mfs_bindex = bindex;
27440+ mfs->mfs_jiffy = jiffies;
27441+ }
27442+ }
27443+
27444+ mfs->mfsrr_bytes = bavail;
27445+ AuDbg("b%d\n", mfs->mfs_bindex);
27446+ kfree(st);
27447+}
27448+
27449+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
27450+{
27451+ int err;
27452+ struct super_block *sb;
27453+ struct au_wbr_mfs *mfs;
27454+
27455+ err = au_wbr_create_exp(dentry);
27456+ if (err >= 0)
27457+ goto out;
27458+
27459+ sb = dentry->d_sb;
27460+ mfs = &au_sbi(sb)->si_wbr_mfs;
27461+ mutex_lock(&mfs->mfs_lock);
27462+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
27463+ || mfs->mfs_bindex < 0
27464+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
27465+ au_mfs(dentry);
27466+ mutex_unlock(&mfs->mfs_lock);
27467+ err = mfs->mfs_bindex;
27468+
4a4d8108
AM
27469+ if (err >= 0)
27470+ err = au_wbr_nonopq(dentry, err);
27471+
4f0767ce 27472+out:
1facf9fc 27473+ AuDbg("b%d\n", err);
27474+ return err;
27475+}
27476+
27477+static int au_wbr_create_init_mfs(struct super_block *sb)
27478+{
27479+ struct au_wbr_mfs *mfs;
27480+
27481+ mfs = &au_sbi(sb)->si_wbr_mfs;
27482+ mutex_init(&mfs->mfs_lock);
27483+ mfs->mfs_jiffy = 0;
27484+ mfs->mfs_bindex = -EROFS;
27485+
27486+ return 0;
27487+}
27488+
27489+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
27490+{
27491+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
27492+ return 0;
27493+}
27494+
27495+/* ---------------------------------------------------------------------- */
27496+
27497+/* most free space and then round robin */
27498+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
27499+{
27500+ int err;
27501+ struct au_wbr_mfs *mfs;
27502+
27503+ err = au_wbr_create_mfs(dentry, isdir);
27504+ if (err >= 0) {
27505+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 27506+ mutex_lock(&mfs->mfs_lock);
1facf9fc 27507+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
27508+ err = au_wbr_create_rr(dentry, isdir);
dece6358 27509+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 27510+ }
27511+
27512+ AuDbg("b%d\n", err);
27513+ return err;
27514+}
27515+
27516+static int au_wbr_create_init_mfsrr(struct super_block *sb)
27517+{
27518+ int err;
27519+
27520+ au_wbr_create_init_mfs(sb); /* ignore */
27521+ err = au_wbr_create_init_rr(sb);
27522+
27523+ return err;
27524+}
27525+
27526+/* ---------------------------------------------------------------------- */
27527+
27528+/* top down parent and most free space */
27529+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
27530+{
27531+ int err, e2;
27532+ unsigned long long b;
27533+ aufs_bindex_t bindex, bstart, bend;
27534+ struct super_block *sb;
27535+ struct dentry *parent, *h_parent;
27536+ struct au_branch *br;
27537+
27538+ err = au_wbr_create_tdp(dentry, isdir);
27539+ if (unlikely(err < 0))
27540+ goto out;
27541+ parent = dget_parent(dentry);
27542+ bstart = au_dbstart(parent);
27543+ bend = au_dbtaildir(parent);
27544+ if (bstart == bend)
27545+ goto out_parent; /* success */
27546+
27547+ e2 = au_wbr_create_mfs(dentry, isdir);
27548+ if (e2 < 0)
27549+ goto out_parent; /* success */
27550+
27551+ /* when the available size is equal, select upper one */
27552+ sb = dentry->d_sb;
27553+ br = au_sbr(sb, err);
27554+ b = br->br_wbr->wbr_bytes;
27555+ AuDbg("b%d, %llu\n", err, b);
27556+
27557+ for (bindex = bstart; bindex <= bend; bindex++) {
27558+ h_parent = au_h_dptr(parent, bindex);
27559+ if (!h_parent || !h_parent->d_inode)
27560+ continue;
27561+
27562+ br = au_sbr(sb, bindex);
27563+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
27564+ b = br->br_wbr->wbr_bytes;
27565+ err = bindex;
27566+ AuDbg("b%d, %llu\n", err, b);
27567+ }
27568+ }
27569+
4a4d8108
AM
27570+ if (err >= 0)
27571+ err = au_wbr_nonopq(dentry, err);
27572+
4f0767ce 27573+out_parent:
1facf9fc 27574+ dput(parent);
4f0767ce 27575+out:
1facf9fc 27576+ AuDbg("b%d\n", err);
27577+ return err;
27578+}
27579+
27580+/* ---------------------------------------------------------------------- */
27581+
27582+/* policies for copyup */
27583+
27584+/* top down parent */
27585+static int au_wbr_copyup_tdp(struct dentry *dentry)
27586+{
27587+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
27588+}
27589+
27590+/* bottom up parent */
27591+static int au_wbr_copyup_bup(struct dentry *dentry)
27592+{
27593+ int err;
27594+ aufs_bindex_t bindex, bstart;
27595+ struct dentry *parent, *h_parent;
27596+ struct super_block *sb;
27597+
27598+ err = -EROFS;
27599+ sb = dentry->d_sb;
27600+ parent = dget_parent(dentry);
27601+ bstart = au_dbstart(parent);
27602+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
27603+ h_parent = au_h_dptr(parent, bindex);
27604+ if (!h_parent || !h_parent->d_inode)
27605+ continue;
27606+
27607+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
27608+ err = bindex;
27609+ break;
27610+ }
27611+ }
27612+ dput(parent);
27613+
27614+ /* bottom up here */
27615+ if (unlikely(err < 0))
27616+ err = au_wbr_bu(sb, bstart - 1);
27617+
27618+ AuDbg("b%d\n", err);
27619+ return err;
27620+}
27621+
27622+/* bottom up */
27623+static int au_wbr_copyup_bu(struct dentry *dentry)
27624+{
27625+ int err;
4a4d8108 27626+ aufs_bindex_t bstart;
1facf9fc 27627+
4a4d8108
AM
27628+ bstart = au_dbstart(dentry);
27629+ err = au_wbr_bu(dentry->d_sb, bstart);
27630+ AuDbg("b%d\n", err);
27631+ if (err > bstart)
27632+ err = au_wbr_nonopq(dentry, err);
1facf9fc 27633+
27634+ AuDbg("b%d\n", err);
27635+ return err;
27636+}
27637+
27638+/* ---------------------------------------------------------------------- */
27639+
27640+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
27641+ [AuWbrCopyup_TDP] = {
27642+ .copyup = au_wbr_copyup_tdp
27643+ },
27644+ [AuWbrCopyup_BUP] = {
27645+ .copyup = au_wbr_copyup_bup
27646+ },
27647+ [AuWbrCopyup_BU] = {
27648+ .copyup = au_wbr_copyup_bu
27649+ }
27650+};
27651+
27652+struct au_wbr_create_operations au_wbr_create_ops[] = {
27653+ [AuWbrCreate_TDP] = {
27654+ .create = au_wbr_create_tdp
27655+ },
27656+ [AuWbrCreate_RR] = {
27657+ .create = au_wbr_create_rr,
27658+ .init = au_wbr_create_init_rr
27659+ },
27660+ [AuWbrCreate_MFS] = {
27661+ .create = au_wbr_create_mfs,
27662+ .init = au_wbr_create_init_mfs,
27663+ .fin = au_wbr_create_fin_mfs
27664+ },
27665+ [AuWbrCreate_MFSV] = {
27666+ .create = au_wbr_create_mfs,
27667+ .init = au_wbr_create_init_mfs,
27668+ .fin = au_wbr_create_fin_mfs
27669+ },
27670+ [AuWbrCreate_MFSRR] = {
27671+ .create = au_wbr_create_mfsrr,
27672+ .init = au_wbr_create_init_mfsrr,
27673+ .fin = au_wbr_create_fin_mfs
27674+ },
27675+ [AuWbrCreate_MFSRRV] = {
27676+ .create = au_wbr_create_mfsrr,
27677+ .init = au_wbr_create_init_mfsrr,
27678+ .fin = au_wbr_create_fin_mfs
27679+ },
27680+ [AuWbrCreate_PMFS] = {
27681+ .create = au_wbr_create_pmfs,
27682+ .init = au_wbr_create_init_mfs,
27683+ .fin = au_wbr_create_fin_mfs
27684+ },
27685+ [AuWbrCreate_PMFSV] = {
27686+ .create = au_wbr_create_pmfs,
27687+ .init = au_wbr_create_init_mfs,
27688+ .fin = au_wbr_create_fin_mfs
27689+ }
27690+};
7f207e10
AM
27691diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
27692--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 27693+++ linux/fs/aufs/whout.c 2012-08-26 08:39:00.763841498 +0200
0c3ec466 27694@@ -0,0 +1,1041 @@
1facf9fc 27695+/*
f6c5ef8b 27696+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 27697+ *
27698+ * This program, aufs is free software; you can redistribute it and/or modify
27699+ * it under the terms of the GNU General Public License as published by
27700+ * the Free Software Foundation; either version 2 of the License, or
27701+ * (at your option) any later version.
dece6358
AM
27702+ *
27703+ * This program is distributed in the hope that it will be useful,
27704+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27705+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27706+ * GNU General Public License for more details.
27707+ *
27708+ * You should have received a copy of the GNU General Public License
27709+ * along with this program; if not, write to the Free Software
27710+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27711+ */
27712+
27713+/*
27714+ * whiteout for logical deletion and opaque directory
27715+ */
27716+
1facf9fc 27717+#include "aufs.h"
27718+
27719+#define WH_MASK S_IRUGO
27720+
27721+/*
27722+ * If a directory contains this file, then it is opaque. We start with the
27723+ * .wh. flag so that it is blocked by lookup.
27724+ */
0c3ec466
AM
27725+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ,
27726+ sizeof(AUFS_WH_DIROPQ) - 1);
1facf9fc 27727+
27728+/*
27729+ * generate whiteout name, which is NOT terminated by NULL.
27730+ * @name: original d_name.name
27731+ * @len: original d_name.len
27732+ * @wh: whiteout qstr
27733+ * returns zero when succeeds, otherwise error.
27734+ * succeeded value as wh->name should be freed by kfree().
27735+ */
27736+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
27737+{
27738+ char *p;
27739+
27740+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
27741+ return -ENAMETOOLONG;
27742+
27743+ wh->len = name->len + AUFS_WH_PFX_LEN;
27744+ p = kmalloc(wh->len, GFP_NOFS);
27745+ wh->name = p;
27746+ if (p) {
27747+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
27748+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
27749+ /* smp_mb(); */
27750+ return 0;
27751+ }
27752+ return -ENOMEM;
27753+}
27754+
27755+/* ---------------------------------------------------------------------- */
27756+
27757+/*
27758+ * test if the @wh_name exists under @h_parent.
27759+ * @try_sio specifies the necessary of super-io.
27760+ */
27761+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
27762+ struct au_branch *br, int try_sio)
27763+{
27764+ int err;
27765+ struct dentry *wh_dentry;
1facf9fc 27766+
1facf9fc 27767+ if (!try_sio)
27768+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
27769+ else
27770+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
27771+ err = PTR_ERR(wh_dentry);
27772+ if (IS_ERR(wh_dentry))
27773+ goto out;
27774+
27775+ err = 0;
27776+ if (!wh_dentry->d_inode)
27777+ goto out_wh; /* success */
27778+
27779+ err = 1;
27780+ if (S_ISREG(wh_dentry->d_inode->i_mode))
27781+ goto out_wh; /* success */
27782+
27783+ err = -EIO;
27784+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
27785+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
27786+
4f0767ce 27787+out_wh:
1facf9fc 27788+ dput(wh_dentry);
4f0767ce 27789+out:
1facf9fc 27790+ return err;
27791+}
27792+
27793+/*
27794+ * test if the @h_dentry sets opaque or not.
27795+ */
27796+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
27797+{
27798+ int err;
27799+ struct inode *h_dir;
27800+
27801+ h_dir = h_dentry->d_inode;
27802+ err = au_wh_test(h_dentry, &diropq_name, br,
27803+ au_test_h_perm_sio(h_dir, MAY_EXEC));
27804+ return err;
27805+}
27806+
27807+/*
27808+ * returns a negative dentry whose name is unique and temporary.
27809+ */
27810+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
27811+ struct qstr *prefix)
27812+{
1facf9fc 27813+ struct dentry *dentry;
27814+ int i;
027c5e7a 27815+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 27816+ *name, *p;
027c5e7a 27817+ /* strict atomic_t is unnecessary here */
1facf9fc 27818+ static unsigned short cnt;
27819+ struct qstr qs;
27820+
4a4d8108
AM
27821+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
27822+
1facf9fc 27823+ name = defname;
027c5e7a
AM
27824+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
27825+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 27826+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 27827+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 27828+ goto out;
27829+ dentry = ERR_PTR(-ENOMEM);
27830+ name = kmalloc(qs.len + 1, GFP_NOFS);
27831+ if (unlikely(!name))
27832+ goto out;
27833+ }
27834+
27835+ /* doubly whiteout-ed */
27836+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
27837+ p = name + AUFS_WH_PFX_LEN * 2;
27838+ memcpy(p, prefix->name, prefix->len);
27839+ p += prefix->len;
27840+ *p++ = '.';
4a4d8108 27841+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 27842+
27843+ qs.name = name;
27844+ for (i = 0; i < 3; i++) {
b752ccd1 27845+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 27846+ dentry = au_sio_lkup_one(&qs, h_parent, br);
27847+ if (IS_ERR(dentry) || !dentry->d_inode)
27848+ goto out_name;
27849+ dput(dentry);
27850+ }
0c3ec466 27851+ /* pr_warn("could not get random name\n"); */
1facf9fc 27852+ dentry = ERR_PTR(-EEXIST);
27853+ AuDbg("%.*s\n", AuLNPair(&qs));
27854+ BUG();
27855+
4f0767ce 27856+out_name:
1facf9fc 27857+ if (name != defname)
27858+ kfree(name);
4f0767ce 27859+out:
4a4d8108 27860+ AuTraceErrPtr(dentry);
1facf9fc 27861+ return dentry;
1facf9fc 27862+}
27863+
27864+/*
27865+ * rename the @h_dentry on @br to the whiteouted temporary name.
27866+ */
27867+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
27868+{
27869+ int err;
27870+ struct path h_path = {
27871+ .mnt = br->br_mnt
27872+ };
27873+ struct inode *h_dir;
27874+ struct dentry *h_parent;
27875+
27876+ h_parent = h_dentry->d_parent; /* dir inode is locked */
27877+ h_dir = h_parent->d_inode;
27878+ IMustLock(h_dir);
27879+
27880+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
27881+ err = PTR_ERR(h_path.dentry);
27882+ if (IS_ERR(h_path.dentry))
27883+ goto out;
27884+
27885+ /* under the same dir, no need to lock_rename() */
27886+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
27887+ AuTraceErr(err);
27888+ dput(h_path.dentry);
27889+
4f0767ce 27890+out:
4a4d8108 27891+ AuTraceErr(err);
1facf9fc 27892+ return err;
27893+}
27894+
27895+/* ---------------------------------------------------------------------- */
27896+/*
27897+ * functions for removing a whiteout
27898+ */
27899+
27900+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
27901+{
27902+ int force;
27903+
27904+ /*
27905+ * forces superio when the dir has a sticky bit.
27906+ * this may be a violation of unix fs semantics.
27907+ */
27908+ force = (h_dir->i_mode & S_ISVTX)
0c3ec466 27909+ && !uid_eq(current_fsuid(), h_path->dentry->d_inode->i_uid);
1facf9fc 27910+ return vfsub_unlink(h_dir, h_path, force);
27911+}
27912+
27913+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
27914+ struct dentry *dentry)
27915+{
27916+ int err;
27917+
27918+ err = do_unlink_wh(h_dir, h_path);
27919+ if (!err && dentry)
27920+ au_set_dbwh(dentry, -1);
27921+
27922+ return err;
27923+}
27924+
27925+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
27926+ struct au_branch *br)
27927+{
27928+ int err;
27929+ struct path h_path = {
27930+ .mnt = br->br_mnt
27931+ };
27932+
27933+ err = 0;
27934+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
27935+ if (IS_ERR(h_path.dentry))
27936+ err = PTR_ERR(h_path.dentry);
27937+ else {
27938+ if (h_path.dentry->d_inode
27939+ && S_ISREG(h_path.dentry->d_inode->i_mode))
27940+ err = do_unlink_wh(h_parent->d_inode, &h_path);
27941+ dput(h_path.dentry);
27942+ }
27943+
27944+ return err;
27945+}
27946+
27947+/* ---------------------------------------------------------------------- */
27948+/*
27949+ * initialize/clean whiteout for a branch
27950+ */
27951+
27952+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
27953+ const int isdir)
27954+{
27955+ int err;
27956+
27957+ if (!whpath->dentry->d_inode)
27958+ return;
27959+
27960+ err = mnt_want_write(whpath->mnt);
27961+ if (!err) {
27962+ if (isdir)
27963+ err = vfsub_rmdir(h_dir, whpath);
27964+ else
27965+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
27966+ mnt_drop_write(whpath->mnt);
27967+ }
27968+ if (unlikely(err))
0c3ec466
AM
27969+ pr_warn("failed removing %.*s (%d), ignored.\n",
27970+ AuDLNPair(whpath->dentry), err);
1facf9fc 27971+}
27972+
27973+static int test_linkable(struct dentry *h_root)
27974+{
27975+ struct inode *h_dir = h_root->d_inode;
27976+
27977+ if (h_dir->i_op->link)
27978+ return 0;
27979+
4a4d8108
AM
27980+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
27981+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 27982+ return -ENOSYS;
27983+}
27984+
27985+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
27986+static int au_whdir(struct inode *h_dir, struct path *path)
27987+{
27988+ int err;
27989+
27990+ err = -EEXIST;
27991+ if (!path->dentry->d_inode) {
27992+ int mode = S_IRWXU;
27993+
27994+ if (au_test_nfs(path->dentry->d_sb))
27995+ mode |= S_IXUGO;
27996+ err = mnt_want_write(path->mnt);
27997+ if (!err) {
27998+ err = vfsub_mkdir(h_dir, path, mode);
27999+ mnt_drop_write(path->mnt);
28000+ }
28001+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
28002+ err = 0;
28003+ else
4a4d8108 28004+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 28005+
28006+ return err;
28007+}
28008+
28009+struct au_wh_base {
28010+ const struct qstr *name;
28011+ struct dentry *dentry;
28012+};
28013+
28014+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
28015+ struct path *h_path)
28016+{
28017+ h_path->dentry = base[AuBrWh_BASE].dentry;
28018+ au_wh_clean(h_dir, h_path, /*isdir*/0);
28019+ h_path->dentry = base[AuBrWh_PLINK].dentry;
28020+ au_wh_clean(h_dir, h_path, /*isdir*/1);
28021+ h_path->dentry = base[AuBrWh_ORPH].dentry;
28022+ au_wh_clean(h_dir, h_path, /*isdir*/1);
28023+}
28024+
28025+/*
28026+ * returns tri-state,
28027+ * minus: error, caller should print the mesage
28028+ * zero: succuess
28029+ * plus: error, caller should NOT print the mesage
28030+ */
28031+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
28032+ int do_plink, struct au_wh_base base[],
28033+ struct path *h_path)
28034+{
28035+ int err;
28036+ struct inode *h_dir;
28037+
28038+ h_dir = h_root->d_inode;
28039+ h_path->dentry = base[AuBrWh_BASE].dentry;
28040+ au_wh_clean(h_dir, h_path, /*isdir*/0);
28041+ h_path->dentry = base[AuBrWh_PLINK].dentry;
28042+ if (do_plink) {
28043+ err = test_linkable(h_root);
28044+ if (unlikely(err)) {
28045+ err = 1;
28046+ goto out;
28047+ }
28048+
28049+ err = au_whdir(h_dir, h_path);
28050+ if (unlikely(err))
28051+ goto out;
28052+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
28053+ } else
28054+ au_wh_clean(h_dir, h_path, /*isdir*/1);
28055+ h_path->dentry = base[AuBrWh_ORPH].dentry;
28056+ err = au_whdir(h_dir, h_path);
28057+ if (unlikely(err))
28058+ goto out;
28059+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
28060+
4f0767ce 28061+out:
1facf9fc 28062+ return err;
28063+}
28064+
28065+/*
28066+ * for the moment, aufs supports the branch filesystem which does not support
28067+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
28068+ * copyup failed. finally, such filesystem will not be used as the writable
28069+ * branch.
28070+ *
28071+ * returns tri-state, see above.
28072+ */
28073+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
28074+ int do_plink, struct au_wh_base base[],
28075+ struct path *h_path)
28076+{
28077+ int err;
28078+ struct inode *h_dir;
28079+
1308ab2a 28080+ WbrWhMustWriteLock(wbr);
28081+
1facf9fc 28082+ err = test_linkable(h_root);
28083+ if (unlikely(err)) {
28084+ err = 1;
28085+ goto out;
28086+ }
28087+
28088+ /*
28089+ * todo: should this create be done in /sbin/mount.aufs helper?
28090+ */
28091+ err = -EEXIST;
28092+ h_dir = h_root->d_inode;
28093+ if (!base[AuBrWh_BASE].dentry->d_inode) {
28094+ err = mnt_want_write(h_path->mnt);
28095+ if (!err) {
28096+ h_path->dentry = base[AuBrWh_BASE].dentry;
28097+ err = vfsub_create(h_dir, h_path, WH_MASK);
28098+ mnt_drop_write(h_path->mnt);
28099+ }
28100+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
28101+ err = 0;
28102+ else
4a4d8108
AM
28103+ pr_err("unknown %.*s/%.*s exists\n",
28104+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 28105+ if (unlikely(err))
28106+ goto out;
28107+
28108+ h_path->dentry = base[AuBrWh_PLINK].dentry;
28109+ if (do_plink) {
28110+ err = au_whdir(h_dir, h_path);
28111+ if (unlikely(err))
28112+ goto out;
28113+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
28114+ } else
28115+ au_wh_clean(h_dir, h_path, /*isdir*/1);
28116+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
28117+
28118+ h_path->dentry = base[AuBrWh_ORPH].dentry;
28119+ err = au_whdir(h_dir, h_path);
28120+ if (unlikely(err))
28121+ goto out;
28122+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
28123+
4f0767ce 28124+out:
1facf9fc 28125+ return err;
28126+}
28127+
28128+/*
28129+ * initialize the whiteout base file/dir for @br.
28130+ */
28131+int au_wh_init(struct dentry *h_root, struct au_branch *br,
28132+ struct super_block *sb)
28133+{
28134+ int err, i;
28135+ const unsigned char do_plink
28136+ = !!au_opt_test(au_mntflags(sb), PLINK);
28137+ struct path path = {
28138+ .mnt = br->br_mnt
28139+ };
28140+ struct inode *h_dir;
28141+ struct au_wbr *wbr = br->br_wbr;
28142+ static const struct qstr base_name[] = {
0c3ec466
AM
28143+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME,
28144+ sizeof(AUFS_BASE_NAME) - 1),
28145+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME,
28146+ sizeof(AUFS_PLINKDIR_NAME) - 1),
28147+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME,
28148+ sizeof(AUFS_ORPHDIR_NAME) - 1)
1facf9fc 28149+ };
28150+ struct au_wh_base base[] = {
28151+ [AuBrWh_BASE] = {
28152+ .name = base_name + AuBrWh_BASE,
28153+ .dentry = NULL
28154+ },
28155+ [AuBrWh_PLINK] = {
28156+ .name = base_name + AuBrWh_PLINK,
28157+ .dentry = NULL
28158+ },
28159+ [AuBrWh_ORPH] = {
28160+ .name = base_name + AuBrWh_ORPH,
28161+ .dentry = NULL
28162+ }
28163+ };
28164+
1308ab2a 28165+ if (wbr)
28166+ WbrWhMustWriteLock(wbr);
1facf9fc 28167+
1facf9fc 28168+ for (i = 0; i < AuBrWh_Last; i++) {
28169+ /* doubly whiteouted */
28170+ struct dentry *d;
28171+
28172+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
28173+ err = PTR_ERR(d);
28174+ if (IS_ERR(d))
28175+ goto out;
28176+
28177+ base[i].dentry = d;
28178+ AuDebugOn(wbr
28179+ && wbr->wbr_wh[i]
28180+ && wbr->wbr_wh[i] != base[i].dentry);
28181+ }
28182+
28183+ if (wbr)
28184+ for (i = 0; i < AuBrWh_Last; i++) {
28185+ dput(wbr->wbr_wh[i]);
28186+ wbr->wbr_wh[i] = NULL;
28187+ }
28188+
28189+ err = 0;
1e00d052 28190+ if (!au_br_writable(br->br_perm)) {
4a4d8108 28191+ h_dir = h_root->d_inode;
1facf9fc 28192+ au_wh_init_ro(h_dir, base, &path);
1e00d052 28193+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 28194+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
28195+ if (err > 0)
28196+ goto out;
28197+ else if (err)
28198+ goto out_err;
1e00d052 28199+ } else {
1facf9fc 28200+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
28201+ if (err > 0)
28202+ goto out;
28203+ else if (err)
28204+ goto out_err;
1facf9fc 28205+ }
28206+ goto out; /* success */
28207+
4f0767ce 28208+out_err:
4a4d8108
AM
28209+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
28210+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 28211+out:
1facf9fc 28212+ for (i = 0; i < AuBrWh_Last; i++)
28213+ dput(base[i].dentry);
28214+ return err;
28215+}
28216+
28217+/* ---------------------------------------------------------------------- */
28218+/*
28219+ * whiteouts are all hard-linked usually.
28220+ * when its link count reaches a ceiling, we create a new whiteout base
28221+ * asynchronously.
28222+ */
28223+
28224+struct reinit_br_wh {
28225+ struct super_block *sb;
28226+ struct au_branch *br;
28227+};
28228+
28229+static void reinit_br_wh(void *arg)
28230+{
28231+ int err;
28232+ aufs_bindex_t bindex;
28233+ struct path h_path;
28234+ struct reinit_br_wh *a = arg;
28235+ struct au_wbr *wbr;
28236+ struct inode *dir;
28237+ struct dentry *h_root;
28238+ struct au_hinode *hdir;
28239+
28240+ err = 0;
28241+ wbr = a->br->br_wbr;
28242+ /* big aufs lock */
28243+ si_noflush_write_lock(a->sb);
28244+ if (!au_br_writable(a->br->br_perm))
28245+ goto out;
28246+ bindex = au_br_index(a->sb, a->br->br_id);
28247+ if (unlikely(bindex < 0))
28248+ goto out;
28249+
1308ab2a 28250+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 28251+ dir = a->sb->s_root->d_inode;
1facf9fc 28252+ hdir = au_hi(dir, bindex);
28253+ h_root = au_h_dptr(a->sb->s_root, bindex);
28254+
4a4d8108 28255+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 28256+ wbr_wh_write_lock(wbr);
28257+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
28258+ h_root, a->br);
28259+ if (!err) {
28260+ err = mnt_want_write(a->br->br_mnt);
28261+ if (!err) {
28262+ h_path.dentry = wbr->wbr_whbase;
28263+ h_path.mnt = a->br->br_mnt;
28264+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
28265+ mnt_drop_write(a->br->br_mnt);
28266+ }
28267+ } else {
0c3ec466
AM
28268+ pr_warn("%.*s is moved, ignored\n",
28269+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 28270+ err = 0;
28271+ }
28272+ dput(wbr->wbr_whbase);
28273+ wbr->wbr_whbase = NULL;
28274+ if (!err)
28275+ err = au_wh_init(h_root, a->br, a->sb);
28276+ wbr_wh_write_unlock(wbr);
4a4d8108 28277+ au_hn_imtx_unlock(hdir);
1308ab2a 28278+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 28279+
4f0767ce 28280+out:
1facf9fc 28281+ if (wbr)
28282+ atomic_dec(&wbr->wbr_wh_running);
28283+ atomic_dec(&a->br->br_count);
1facf9fc 28284+ si_write_unlock(a->sb);
027c5e7a 28285+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
1facf9fc 28286+ kfree(arg);
28287+ if (unlikely(err))
28288+ AuIOErr("err %d\n", err);
28289+}
28290+
28291+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
28292+{
28293+ int do_dec, wkq_err;
28294+ struct reinit_br_wh *arg;
28295+
28296+ do_dec = 1;
28297+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
28298+ goto out;
28299+
28300+ /* ignore ENOMEM */
28301+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
28302+ if (arg) {
28303+ /*
28304+ * dec(wh_running), kfree(arg) and dec(br_count)
28305+ * in reinit function
28306+ */
28307+ arg->sb = sb;
28308+ arg->br = br;
28309+ atomic_inc(&br->br_count);
53392da6 28310+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0);
1facf9fc 28311+ if (unlikely(wkq_err)) {
28312+ atomic_dec(&br->br_wbr->wbr_wh_running);
28313+ atomic_dec(&br->br_count);
28314+ kfree(arg);
28315+ }
28316+ do_dec = 0;
28317+ }
28318+
4f0767ce 28319+out:
1facf9fc 28320+ if (do_dec)
28321+ atomic_dec(&br->br_wbr->wbr_wh_running);
28322+}
28323+
28324+/* ---------------------------------------------------------------------- */
28325+
28326+/*
28327+ * create the whiteout @wh.
28328+ */
28329+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
28330+ struct dentry *wh)
28331+{
28332+ int err;
28333+ struct path h_path = {
28334+ .dentry = wh
28335+ };
28336+ struct au_branch *br;
28337+ struct au_wbr *wbr;
28338+ struct dentry *h_parent;
28339+ struct inode *h_dir;
28340+
28341+ h_parent = wh->d_parent; /* dir inode is locked */
28342+ h_dir = h_parent->d_inode;
28343+ IMustLock(h_dir);
28344+
28345+ br = au_sbr(sb, bindex);
28346+ h_path.mnt = br->br_mnt;
28347+ wbr = br->br_wbr;
28348+ wbr_wh_read_lock(wbr);
28349+ if (wbr->wbr_whbase) {
28350+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
28351+ if (!err || err != -EMLINK)
28352+ goto out;
28353+
28354+ /* link count full. re-initialize br_whbase. */
28355+ kick_reinit_br_wh(sb, br);
28356+ }
28357+
28358+ /* return this error in this context */
28359+ err = vfsub_create(h_dir, &h_path, WH_MASK);
28360+
4f0767ce 28361+out:
1facf9fc 28362+ wbr_wh_read_unlock(wbr);
28363+ return err;
28364+}
28365+
28366+/* ---------------------------------------------------------------------- */
28367+
28368+/*
28369+ * create or remove the diropq.
28370+ */
28371+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
28372+ unsigned int flags)
28373+{
28374+ struct dentry *opq_dentry, *h_dentry;
28375+ struct super_block *sb;
28376+ struct au_branch *br;
28377+ int err;
28378+
28379+ sb = dentry->d_sb;
28380+ br = au_sbr(sb, bindex);
28381+ h_dentry = au_h_dptr(dentry, bindex);
28382+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
28383+ if (IS_ERR(opq_dentry))
28384+ goto out;
28385+
28386+ if (au_ftest_diropq(flags, CREATE)) {
28387+ err = link_or_create_wh(sb, bindex, opq_dentry);
28388+ if (!err) {
28389+ au_set_dbdiropq(dentry, bindex);
28390+ goto out; /* success */
28391+ }
28392+ } else {
28393+ struct path tmp = {
28394+ .dentry = opq_dentry,
28395+ .mnt = br->br_mnt
28396+ };
28397+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
28398+ if (!err)
28399+ au_set_dbdiropq(dentry, -1);
28400+ }
28401+ dput(opq_dentry);
28402+ opq_dentry = ERR_PTR(err);
28403+
4f0767ce 28404+out:
1facf9fc 28405+ return opq_dentry;
28406+}
28407+
28408+struct do_diropq_args {
28409+ struct dentry **errp;
28410+ struct dentry *dentry;
28411+ aufs_bindex_t bindex;
28412+ unsigned int flags;
28413+};
28414+
28415+static void call_do_diropq(void *args)
28416+{
28417+ struct do_diropq_args *a = args;
28418+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
28419+}
28420+
28421+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
28422+ unsigned int flags)
28423+{
28424+ struct dentry *diropq, *h_dentry;
28425+
28426+ h_dentry = au_h_dptr(dentry, bindex);
28427+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
28428+ diropq = do_diropq(dentry, bindex, flags);
28429+ else {
28430+ int wkq_err;
28431+ struct do_diropq_args args = {
28432+ .errp = &diropq,
28433+ .dentry = dentry,
28434+ .bindex = bindex,
28435+ .flags = flags
28436+ };
28437+
28438+ wkq_err = au_wkq_wait(call_do_diropq, &args);
28439+ if (unlikely(wkq_err))
28440+ diropq = ERR_PTR(wkq_err);
28441+ }
28442+
28443+ return diropq;
28444+}
28445+
28446+/* ---------------------------------------------------------------------- */
28447+
28448+/*
28449+ * lookup whiteout dentry.
28450+ * @h_parent: lower parent dentry which must exist and be locked
28451+ * @base_name: name of dentry which will be whiteouted
28452+ * returns dentry for whiteout.
28453+ */
28454+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
28455+ struct au_branch *br)
28456+{
28457+ int err;
28458+ struct qstr wh_name;
28459+ struct dentry *wh_dentry;
28460+
28461+ err = au_wh_name_alloc(&wh_name, base_name);
28462+ wh_dentry = ERR_PTR(err);
28463+ if (!err) {
28464+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
28465+ kfree(wh_name.name);
28466+ }
28467+ return wh_dentry;
28468+}
28469+
28470+/*
28471+ * link/create a whiteout for @dentry on @bindex.
28472+ */
28473+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
28474+ struct dentry *h_parent)
28475+{
28476+ struct dentry *wh_dentry;
28477+ struct super_block *sb;
28478+ int err;
28479+
28480+ sb = dentry->d_sb;
28481+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
28482+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
28483+ err = link_or_create_wh(sb, bindex, wh_dentry);
28484+ if (!err)
28485+ au_set_dbwh(dentry, bindex);
28486+ else {
28487+ dput(wh_dentry);
28488+ wh_dentry = ERR_PTR(err);
28489+ }
28490+ }
28491+
28492+ return wh_dentry;
28493+}
28494+
28495+/* ---------------------------------------------------------------------- */
28496+
28497+/* Delete all whiteouts in this directory on branch bindex. */
28498+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
28499+ aufs_bindex_t bindex, struct au_branch *br)
28500+{
28501+ int err;
28502+ unsigned long ul, n;
28503+ struct qstr wh_name;
28504+ char *p;
28505+ struct hlist_head *head;
28506+ struct au_vdir_wh *tpos;
28507+ struct hlist_node *pos;
28508+ struct au_vdir_destr *str;
28509+
28510+ err = -ENOMEM;
4a4d8108 28511+ p = __getname_gfp(GFP_NOFS);
1facf9fc 28512+ wh_name.name = p;
28513+ if (unlikely(!wh_name.name))
28514+ goto out;
28515+
28516+ err = 0;
28517+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
28518+ p += AUFS_WH_PFX_LEN;
28519+ n = whlist->nh_num;
28520+ head = whlist->nh_head;
28521+ for (ul = 0; !err && ul < n; ul++, head++) {
28522+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
28523+ if (tpos->wh_bindex != bindex)
28524+ continue;
28525+
28526+ str = &tpos->wh_str;
28527+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
28528+ memcpy(p, str->name, str->len);
28529+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
28530+ err = unlink_wh_name(h_dentry, &wh_name, br);
28531+ if (!err)
28532+ continue;
28533+ break;
28534+ }
28535+ AuIOErr("whiteout name too long %.*s\n",
28536+ str->len, str->name);
28537+ err = -EIO;
28538+ break;
28539+ }
28540+ }
28541+ __putname(wh_name.name);
28542+
4f0767ce 28543+out:
1facf9fc 28544+ return err;
28545+}
28546+
28547+struct del_wh_children_args {
28548+ int *errp;
28549+ struct dentry *h_dentry;
1308ab2a 28550+ struct au_nhash *whlist;
1facf9fc 28551+ aufs_bindex_t bindex;
28552+ struct au_branch *br;
28553+};
28554+
28555+static void call_del_wh_children(void *args)
28556+{
28557+ struct del_wh_children_args *a = args;
1308ab2a 28558+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 28559+}
28560+
28561+/* ---------------------------------------------------------------------- */
28562+
28563+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
28564+{
28565+ struct au_whtmp_rmdir *whtmp;
dece6358 28566+ int err;
1308ab2a 28567+ unsigned int rdhash;
dece6358
AM
28568+
28569+ SiMustAnyLock(sb);
1facf9fc 28570+
28571+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
28572+ if (unlikely(!whtmp)) {
28573+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 28574+ goto out;
dece6358 28575+ }
1facf9fc 28576+
28577+ whtmp->dir = NULL;
027c5e7a 28578+ whtmp->br = NULL;
1facf9fc 28579+ whtmp->wh_dentry = NULL;
1308ab2a 28580+ /* no estimation for dir size */
28581+ rdhash = au_sbi(sb)->si_rdhash;
28582+ if (!rdhash)
28583+ rdhash = AUFS_RDHASH_DEF;
28584+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
28585+ if (unlikely(err)) {
28586+ kfree(whtmp);
28587+ whtmp = ERR_PTR(err);
28588+ }
dece6358 28589+
4f0767ce 28590+out:
dece6358 28591+ return whtmp;
1facf9fc 28592+}
28593+
28594+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
28595+{
027c5e7a
AM
28596+ if (whtmp->br)
28597+ atomic_dec(&whtmp->br->br_count);
1facf9fc 28598+ dput(whtmp->wh_dentry);
28599+ iput(whtmp->dir);
dece6358 28600+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 28601+ kfree(whtmp);
28602+}
28603+
28604+/*
28605+ * rmdir the whiteouted temporary named dir @h_dentry.
28606+ * @whlist: whiteouted children.
28607+ */
28608+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
28609+ struct dentry *wh_dentry, struct au_nhash *whlist)
28610+{
28611+ int err;
28612+ struct path h_tmp;
28613+ struct inode *wh_inode, *h_dir;
28614+ struct au_branch *br;
28615+
28616+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
28617+ IMustLock(h_dir);
28618+
28619+ br = au_sbr(dir->i_sb, bindex);
28620+ wh_inode = wh_dentry->d_inode;
28621+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
28622+
28623+ /*
28624+ * someone else might change some whiteouts while we were sleeping.
28625+ * it means this whlist may have an obsoleted entry.
28626+ */
28627+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
28628+ err = del_wh_children(wh_dentry, whlist, bindex, br);
28629+ else {
28630+ int wkq_err;
28631+ struct del_wh_children_args args = {
28632+ .errp = &err,
28633+ .h_dentry = wh_dentry,
1308ab2a 28634+ .whlist = whlist,
1facf9fc 28635+ .bindex = bindex,
28636+ .br = br
28637+ };
28638+
28639+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
28640+ if (unlikely(wkq_err))
28641+ err = wkq_err;
28642+ }
28643+ mutex_unlock(&wh_inode->i_mutex);
28644+
28645+ if (!err) {
28646+ h_tmp.dentry = wh_dentry;
28647+ h_tmp.mnt = br->br_mnt;
28648+ err = vfsub_rmdir(h_dir, &h_tmp);
1facf9fc 28649+ }
28650+
28651+ if (!err) {
28652+ if (au_ibstart(dir) == bindex) {
7f207e10 28653+ /* todo: dir->i_mutex is necessary */
1facf9fc 28654+ au_cpup_attr_timesizes(dir);
7f207e10 28655+ vfsub_drop_nlink(dir);
1facf9fc 28656+ }
28657+ return 0; /* success */
28658+ }
28659+
0c3ec466
AM
28660+ pr_warn("failed removing %.*s(%d), ignored\n",
28661+ AuDLNPair(wh_dentry), err);
1facf9fc 28662+ return err;
28663+}
28664+
28665+static void call_rmdir_whtmp(void *args)
28666+{
28667+ int err;
e49829fe 28668+ aufs_bindex_t bindex;
1facf9fc 28669+ struct au_whtmp_rmdir *a = args;
28670+ struct super_block *sb;
28671+ struct dentry *h_parent;
28672+ struct inode *h_dir;
1facf9fc 28673+ struct au_hinode *hdir;
28674+
28675+ /* rmdir by nfsd may cause deadlock with this i_mutex */
28676+ /* mutex_lock(&a->dir->i_mutex); */
e49829fe 28677+ err = -EROFS;
1facf9fc 28678+ sb = a->dir->i_sb;
e49829fe
JR
28679+ si_read_lock(sb, !AuLock_FLUSH);
28680+ if (!au_br_writable(a->br->br_perm))
28681+ goto out;
28682+ bindex = au_br_index(sb, a->br->br_id);
28683+ if (unlikely(bindex < 0))
1facf9fc 28684+ goto out;
28685+
28686+ err = -EIO;
1facf9fc 28687+ ii_write_lock_parent(a->dir);
28688+ h_parent = dget_parent(a->wh_dentry);
28689+ h_dir = h_parent->d_inode;
e49829fe 28690+ hdir = au_hi(a->dir, bindex);
4a4d8108 28691+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
28692+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
28693+ a->br);
1facf9fc 28694+ if (!err) {
e49829fe 28695+ err = mnt_want_write(a->br->br_mnt);
1facf9fc 28696+ if (!err) {
e49829fe 28697+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
dece6358 28698+ &a->whlist);
e49829fe 28699+ mnt_drop_write(a->br->br_mnt);
1facf9fc 28700+ }
28701+ }
4a4d8108 28702+ au_hn_imtx_unlock(hdir);
1facf9fc 28703+ dput(h_parent);
28704+ ii_write_unlock(a->dir);
28705+
4f0767ce 28706+out:
1facf9fc 28707+ /* mutex_unlock(&a->dir->i_mutex); */
1facf9fc 28708+ au_whtmp_rmdir_free(a);
027c5e7a
AM
28709+ si_read_unlock(sb);
28710+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 28711+ if (unlikely(err))
28712+ AuIOErr("err %d\n", err);
28713+}
28714+
28715+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
28716+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
28717+{
28718+ int wkq_err;
e49829fe 28719+ struct super_block *sb;
1facf9fc 28720+
28721+ IMustLock(dir);
28722+
28723+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 28724+ sb = dir->i_sb;
1facf9fc 28725+ args->dir = au_igrab(dir);
e49829fe
JR
28726+ args->br = au_sbr(sb, bindex);
28727+ atomic_inc(&args->br->br_count);
1facf9fc 28728+ args->wh_dentry = dget(wh_dentry);
53392da6 28729+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0);
1facf9fc 28730+ if (unlikely(wkq_err)) {
0c3ec466
AM
28731+ pr_warn("rmdir error %.*s (%d), ignored\n",
28732+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 28733+ au_whtmp_rmdir_free(args);
28734+ }
28735+}
7f207e10
AM
28736diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
28737--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 28738+++ linux/fs/aufs/whout.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 28739@@ -0,0 +1,88 @@
1facf9fc 28740+/*
f6c5ef8b 28741+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28742+ *
28743+ * This program, aufs is free software; you can redistribute it and/or modify
28744+ * it under the terms of the GNU General Public License as published by
28745+ * the Free Software Foundation; either version 2 of the License, or
28746+ * (at your option) any later version.
dece6358
AM
28747+ *
28748+ * This program is distributed in the hope that it will be useful,
28749+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28750+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28751+ * GNU General Public License for more details.
28752+ *
28753+ * You should have received a copy of the GNU General Public License
28754+ * along with this program; if not, write to the Free Software
28755+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28756+ */
28757+
28758+/*
28759+ * whiteout for logical deletion and opaque directory
28760+ */
28761+
28762+#ifndef __AUFS_WHOUT_H__
28763+#define __AUFS_WHOUT_H__
28764+
28765+#ifdef __KERNEL__
28766+
1facf9fc 28767+#include "dir.h"
28768+
28769+/* whout.c */
28770+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
28771+struct au_branch;
28772+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
28773+ struct au_branch *br, int try_sio);
28774+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
28775+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
28776+ struct qstr *prefix);
28777+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
28778+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
28779+ struct dentry *dentry);
28780+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
28781+ struct super_block *sb);
28782+
28783+/* diropq flags */
28784+#define AuDiropq_CREATE 1
28785+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
28786+#define au_fset_diropq(flags, name) \
28787+ do { (flags) |= AuDiropq_##name; } while (0)
28788+#define au_fclr_diropq(flags, name) \
28789+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 28790+
28791+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
28792+ unsigned int flags);
28793+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
28794+ struct au_branch *br);
28795+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
28796+ struct dentry *h_parent);
28797+
28798+/* real rmdir for the whiteout-ed dir */
28799+struct au_whtmp_rmdir {
28800+ struct inode *dir;
e49829fe 28801+ struct au_branch *br;
1facf9fc 28802+ struct dentry *wh_dentry;
dece6358 28803+ struct au_nhash whlist;
1facf9fc 28804+};
28805+
28806+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
28807+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
28808+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
28809+ struct dentry *wh_dentry, struct au_nhash *whlist);
28810+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
28811+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
28812+
28813+/* ---------------------------------------------------------------------- */
28814+
28815+static inline struct dentry *au_diropq_create(struct dentry *dentry,
28816+ aufs_bindex_t bindex)
28817+{
28818+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
28819+}
28820+
28821+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
28822+{
28823+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
28824+}
28825+
28826+#endif /* __KERNEL__ */
28827+#endif /* __AUFS_WHOUT_H__ */
7f207e10
AM
28828diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
28829--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 28830+++ linux/fs/aufs/wkq.c 2012-08-26 08:39:00.763841498 +0200
9dbd164d 28831@@ -0,0 +1,214 @@
1facf9fc 28832+/*
f6c5ef8b 28833+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28834+ *
28835+ * This program, aufs is free software; you can redistribute it and/or modify
28836+ * it under the terms of the GNU General Public License as published by
28837+ * the Free Software Foundation; either version 2 of the License, or
28838+ * (at your option) any later version.
dece6358
AM
28839+ *
28840+ * This program is distributed in the hope that it will be useful,
28841+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28842+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28843+ * GNU General Public License for more details.
28844+ *
28845+ * You should have received a copy of the GNU General Public License
28846+ * along with this program; if not, write to the Free Software
28847+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28848+ */
28849+
28850+/*
28851+ * workqueue for asynchronous/super-io operations
28852+ * todo: try new dredential scheme
28853+ */
28854+
dece6358 28855+#include <linux/module.h>
1facf9fc 28856+#include "aufs.h"
28857+
9dbd164d 28858+/* internal workqueue named AUFS_WKQ_NAME */
b752ccd1 28859+
9dbd164d 28860+static struct workqueue_struct *au_wkq;
1facf9fc 28861+
28862+struct au_wkinfo {
28863+ struct work_struct wk;
7f207e10 28864+ struct kobject *kobj;
1facf9fc 28865+
28866+ unsigned int flags; /* see wkq.h */
28867+
28868+ au_wkq_func_t func;
28869+ void *args;
28870+
1facf9fc 28871+ struct completion *comp;
28872+};
28873+
28874+/* ---------------------------------------------------------------------- */
28875+
1facf9fc 28876+static void wkq_func(struct work_struct *wk)
28877+{
28878+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
28879+
2dfbb274 28880+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID));
7f207e10
AM
28881+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
28882+
1facf9fc 28883+ wkinfo->func(wkinfo->args);
1facf9fc 28884+ if (au_ftest_wkq(wkinfo->flags, WAIT))
28885+ complete(wkinfo->comp);
28886+ else {
7f207e10 28887+ kobject_put(wkinfo->kobj);
9dbd164d 28888+ module_put(THIS_MODULE); /* todo: ?? */
1facf9fc 28889+ kfree(wkinfo);
28890+ }
28891+}
28892+
28893+/*
28894+ * Since struct completion is large, try allocating it dynamically.
28895+ */
28896+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
28897+#define AuWkqCompDeclare(name) struct completion *comp = NULL
28898+
28899+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
28900+{
28901+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
28902+ if (*comp) {
28903+ init_completion(*comp);
28904+ wkinfo->comp = *comp;
28905+ return 0;
28906+ }
28907+ return -ENOMEM;
28908+}
28909+
28910+static void au_wkq_comp_free(struct completion *comp)
28911+{
28912+ kfree(comp);
28913+}
28914+
28915+#else
28916+
28917+/* no braces */
28918+#define AuWkqCompDeclare(name) \
28919+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
28920+ struct completion *comp = &_ ## name
28921+
28922+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
28923+{
28924+ wkinfo->comp = *comp;
28925+ return 0;
28926+}
28927+
28928+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
28929+{
28930+ /* empty */
28931+}
28932+#endif /* 4KSTACKS */
28933+
53392da6 28934+static void au_wkq_run(struct au_wkinfo *wkinfo)
1facf9fc 28935+{
53392da6
AM
28936+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
28937+ if (au_wkq_test()) {
28938+ AuWarn1("wkq from wkq, due to a dead dir by UDBA?\n");
28939+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
28940+ }
28941+ } else
28942+ au_dbg_verify_kthread();
28943+
28944+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
a1f66529 28945+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
9dbd164d 28946+ queue_work(au_wkq, &wkinfo->wk);
4a4d8108
AM
28947+ } else {
28948+ INIT_WORK(&wkinfo->wk, wkq_func);
28949+ schedule_work(&wkinfo->wk);
28950+ }
1facf9fc 28951+}
28952+
7f207e10
AM
28953+/*
28954+ * Be careful. It is easy to make deadlock happen.
28955+ * processA: lock, wkq and wait
28956+ * processB: wkq and wait, lock in wkq
28957+ * --> deadlock
28958+ */
b752ccd1 28959+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 28960+{
28961+ int err;
28962+ AuWkqCompDeclare(comp);
28963+ struct au_wkinfo wkinfo = {
b752ccd1 28964+ .flags = flags,
1facf9fc 28965+ .func = func,
28966+ .args = args
28967+ };
28968+
28969+ err = au_wkq_comp_alloc(&wkinfo, &comp);
28970+ if (!err) {
53392da6 28971+ au_wkq_run(&wkinfo);
1facf9fc 28972+ /* no timeout, no interrupt */
28973+ wait_for_completion(wkinfo.comp);
28974+ au_wkq_comp_free(comp);
4a4d8108 28975+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 28976+ }
28977+
28978+ return err;
28979+
28980+}
28981+
027c5e7a
AM
28982+/*
28983+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
28984+ * problem in a concurrent umounting.
28985+ */
53392da6
AM
28986+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
28987+ unsigned int flags)
1facf9fc 28988+{
28989+ int err;
28990+ struct au_wkinfo *wkinfo;
28991+
28992+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
28993+
28994+ /*
28995+ * wkq_func() must free this wkinfo.
28996+ * it highly depends upon the implementation of workqueue.
28997+ */
28998+ err = 0;
28999+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
29000+ if (wkinfo) {
7f207e10 29001+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
53392da6 29002+ wkinfo->flags = flags & ~AuWkq_WAIT;
1facf9fc 29003+ wkinfo->func = func;
29004+ wkinfo->args = args;
29005+ wkinfo->comp = NULL;
7f207e10 29006+ kobject_get(wkinfo->kobj);
9dbd164d 29007+ __module_get(THIS_MODULE); /* todo: ?? */
1facf9fc 29008+
53392da6 29009+ au_wkq_run(wkinfo);
1facf9fc 29010+ } else {
29011+ err = -ENOMEM;
e49829fe 29012+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 29013+ }
29014+
29015+ return err;
29016+}
29017+
29018+/* ---------------------------------------------------------------------- */
29019+
29020+void au_nwt_init(struct au_nowait_tasks *nwt)
29021+{
29022+ atomic_set(&nwt->nw_len, 0);
4a4d8108 29023+ /* smp_mb(); */ /* atomic_set */
1facf9fc 29024+ init_waitqueue_head(&nwt->nw_wq);
29025+}
29026+
29027+void au_wkq_fin(void)
29028+{
9dbd164d 29029+ destroy_workqueue(au_wkq);
1facf9fc 29030+}
29031+
29032+int __init au_wkq_init(void)
29033+{
9dbd164d 29034+ int err;
b752ccd1
AM
29035+
29036+ err = 0;
9dbd164d
AM
29037+ BUILD_BUG_ON(!WQ_RESCUER);
29038+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, !WQ_RESCUER, WQ_DFL_ACTIVE);
29039+ if (IS_ERR(au_wkq))
29040+ err = PTR_ERR(au_wkq);
29041+ else if (!au_wkq)
29042+ err = -ENOMEM;
b752ccd1
AM
29043+
29044+ return err;
1facf9fc 29045+}
7f207e10
AM
29046diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
29047--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 29048+++ linux/fs/aufs/wkq.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 29049@@ -0,0 +1,92 @@
1facf9fc 29050+/*
f6c5ef8b 29051+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 29052+ *
29053+ * This program, aufs is free software; you can redistribute it and/or modify
29054+ * it under the terms of the GNU General Public License as published by
29055+ * the Free Software Foundation; either version 2 of the License, or
29056+ * (at your option) any later version.
dece6358
AM
29057+ *
29058+ * This program is distributed in the hope that it will be useful,
29059+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29060+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29061+ * GNU General Public License for more details.
29062+ *
29063+ * You should have received a copy of the GNU General Public License
29064+ * along with this program; if not, write to the Free Software
29065+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 29066+ */
29067+
29068+/*
29069+ * workqueue for asynchronous/super-io operations
29070+ * todo: try new credentials management scheme
29071+ */
29072+
29073+#ifndef __AUFS_WKQ_H__
29074+#define __AUFS_WKQ_H__
29075+
29076+#ifdef __KERNEL__
29077+
dece6358
AM
29078+struct super_block;
29079+
1facf9fc 29080+/* ---------------------------------------------------------------------- */
29081+
29082+/*
29083+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
29084+ */
29085+struct au_nowait_tasks {
29086+ atomic_t nw_len;
29087+ wait_queue_head_t nw_wq;
29088+};
29089+
29090+/* ---------------------------------------------------------------------- */
29091+
29092+typedef void (*au_wkq_func_t)(void *args);
29093+
29094+/* wkq flags */
29095+#define AuWkq_WAIT 1
9dbd164d 29096+#define AuWkq_NEST (1 << 1)
1facf9fc 29097+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
29098+#define au_fset_wkq(flags, name) \
29099+ do { (flags) |= AuWkq_##name; } while (0)
29100+#define au_fclr_wkq(flags, name) \
29101+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 29102+
9dbd164d
AM
29103+#ifndef CONFIG_AUFS_HNOTIFY
29104+#undef AuWkq_NEST
29105+#define AuWkq_NEST 0
29106+#endif
29107+
1facf9fc 29108+/* wkq.c */
b752ccd1 29109+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
53392da6
AM
29110+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
29111+ unsigned int flags);
1facf9fc 29112+void au_nwt_init(struct au_nowait_tasks *nwt);
29113+int __init au_wkq_init(void);
29114+void au_wkq_fin(void);
29115+
29116+/* ---------------------------------------------------------------------- */
29117+
53392da6
AM
29118+static inline int au_wkq_test(void)
29119+{
29120+ return current->flags & PF_WQ_WORKER;
29121+}
29122+
b752ccd1 29123+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 29124+{
b752ccd1 29125+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 29126+}
29127+
29128+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
29129+{
e49829fe 29130+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 29131+ wake_up_all(&nwt->nw_wq);
29132+}
29133+
29134+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
29135+{
29136+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
29137+ return 0;
29138+}
29139+
29140+#endif /* __KERNEL__ */
29141+#endif /* __AUFS_WKQ_H__ */
7f207e10
AM
29142diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
29143--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 29144+++ linux/fs/aufs/xino.c 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 29145@@ -0,0 +1,1264 @@
1facf9fc 29146+/*
f6c5ef8b 29147+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 29148+ *
29149+ * This program, aufs is free software; you can redistribute it and/or modify
29150+ * it under the terms of the GNU General Public License as published by
29151+ * the Free Software Foundation; either version 2 of the License, or
29152+ * (at your option) any later version.
dece6358
AM
29153+ *
29154+ * This program is distributed in the hope that it will be useful,
29155+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29156+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29157+ * GNU General Public License for more details.
29158+ *
29159+ * You should have received a copy of the GNU General Public License
29160+ * along with this program; if not, write to the Free Software
29161+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 29162+ */
29163+
29164+/*
29165+ * external inode number translation table and bitmap
29166+ */
29167+
29168+#include <linux/seq_file.h>
1facf9fc 29169+#include "aufs.h"
29170+
9dbd164d 29171+/* todo: unnecessary to support mmap_sem since kernel-space? */
b752ccd1 29172+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 29173+ loff_t *pos)
29174+{
29175+ ssize_t err;
29176+ mm_segment_t oldfs;
b752ccd1
AM
29177+ union {
29178+ void *k;
29179+ char __user *u;
29180+ } buf;
1facf9fc 29181+
b752ccd1 29182+ buf.k = kbuf;
1facf9fc 29183+ oldfs = get_fs();
29184+ set_fs(KERNEL_DS);
29185+ do {
29186+ /* todo: signal_pending? */
b752ccd1 29187+ err = func(file, buf.u, size, pos);
1facf9fc 29188+ } while (err == -EAGAIN || err == -EINTR);
29189+ set_fs(oldfs);
29190+
29191+#if 0 /* reserved for future use */
29192+ if (err > 0)
29193+ fsnotify_access(file->f_dentry);
29194+#endif
29195+
29196+ return err;
29197+}
29198+
29199+/* ---------------------------------------------------------------------- */
29200+
b752ccd1 29201+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 29202+ size_t size, loff_t *pos)
29203+{
29204+ ssize_t err;
29205+ mm_segment_t oldfs;
b752ccd1
AM
29206+ union {
29207+ void *k;
29208+ const char __user *u;
29209+ } buf;
1facf9fc 29210+
b752ccd1 29211+ buf.k = kbuf;
1facf9fc 29212+ oldfs = get_fs();
29213+ set_fs(KERNEL_DS);
1facf9fc 29214+ do {
29215+ /* todo: signal_pending? */
b752ccd1 29216+ err = func(file, buf.u, size, pos);
1facf9fc 29217+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 29218+ set_fs(oldfs);
29219+
29220+#if 0 /* reserved for future use */
29221+ if (err > 0)
29222+ fsnotify_modify(file->f_dentry);
29223+#endif
29224+
29225+ return err;
29226+}
29227+
29228+struct do_xino_fwrite_args {
29229+ ssize_t *errp;
29230+ au_writef_t func;
29231+ struct file *file;
29232+ void *buf;
29233+ size_t size;
29234+ loff_t *pos;
29235+};
29236+
29237+static void call_do_xino_fwrite(void *args)
29238+{
29239+ struct do_xino_fwrite_args *a = args;
29240+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
29241+}
29242+
29243+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
29244+ loff_t *pos)
29245+{
29246+ ssize_t err;
29247+
29248+ /* todo: signal block and no wkq? */
b752ccd1
AM
29249+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
29250+ lockdep_off();
29251+ err = do_xino_fwrite(func, file, buf, size, pos);
29252+ lockdep_on();
29253+ } else {
29254+ /*
29255+ * it breaks RLIMIT_FSIZE and normal user's limit,
29256+ * users should care about quota and real 'filesystem full.'
29257+ */
1facf9fc 29258+ int wkq_err;
29259+ struct do_xino_fwrite_args args = {
29260+ .errp = &err,
29261+ .func = func,
29262+ .file = file,
29263+ .buf = buf,
29264+ .size = size,
29265+ .pos = pos
29266+ };
29267+
29268+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
29269+ if (unlikely(wkq_err))
29270+ err = wkq_err;
b752ccd1 29271+ }
1facf9fc 29272+
29273+ return err;
29274+}
29275+
29276+/* ---------------------------------------------------------------------- */
29277+
29278+/*
29279+ * create a new xinofile at the same place/path as @base_file.
29280+ */
29281+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
29282+{
29283+ struct file *file;
4a4d8108 29284+ struct dentry *base, *parent;
1facf9fc 29285+ struct inode *dir;
29286+ struct qstr *name;
1308ab2a 29287+ struct path path;
4a4d8108 29288+ int err;
1facf9fc 29289+
29290+ base = base_file->f_dentry;
29291+ parent = base->d_parent; /* dir inode is locked */
29292+ dir = parent->d_inode;
29293+ IMustLock(dir);
29294+
29295+ file = ERR_PTR(-EINVAL);
29296+ name = &base->d_name;
4a4d8108
AM
29297+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
29298+ if (IS_ERR(path.dentry)) {
29299+ file = (void *)path.dentry;
29300+ pr_err("%.*s lookup err %ld\n",
29301+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 29302+ goto out;
29303+ }
29304+
29305+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 29306+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 29307+ if (unlikely(err)) {
29308+ file = ERR_PTR(err);
4a4d8108 29309+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 29310+ goto out_dput;
29311+ }
29312+
1308ab2a 29313+ path.mnt = base_file->f_vfsmnt;
4a4d8108 29314+ file = vfsub_dentry_open(&path,
7f207e10 29315+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 29316+ /* | __FMODE_NONOTIFY */);
1facf9fc 29317+ if (IS_ERR(file)) {
4a4d8108 29318+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 29319+ goto out_dput;
29320+ }
29321+
29322+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
29323+ if (unlikely(err)) {
4a4d8108 29324+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 29325+ goto out_fput;
29326+ }
29327+
29328+ if (copy_src) {
29329+ /* no one can touch copy_src xino */
29330+ err = au_copy_file(file, copy_src,
29331+ i_size_read(copy_src->f_dentry->d_inode));
29332+ if (unlikely(err)) {
4a4d8108 29333+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 29334+ goto out_fput;
29335+ }
29336+ }
29337+ goto out_dput; /* success */
29338+
4f0767ce 29339+out_fput:
1facf9fc 29340+ fput(file);
29341+ file = ERR_PTR(err);
4f0767ce 29342+out_dput:
4a4d8108 29343+ dput(path.dentry);
4f0767ce 29344+out:
1facf9fc 29345+ return file;
29346+}
29347+
29348+struct au_xino_lock_dir {
29349+ struct au_hinode *hdir;
29350+ struct dentry *parent;
29351+ struct mutex *mtx;
29352+};
29353+
29354+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
29355+ struct au_xino_lock_dir *ldir)
29356+{
29357+ aufs_bindex_t brid, bindex;
29358+
29359+ ldir->hdir = NULL;
29360+ bindex = -1;
29361+ brid = au_xino_brid(sb);
29362+ if (brid >= 0)
29363+ bindex = au_br_index(sb, brid);
29364+ if (bindex >= 0) {
29365+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 29366+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 29367+ } else {
29368+ ldir->parent = dget_parent(xino->f_dentry);
29369+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
29370+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
29371+ }
29372+}
29373+
29374+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
29375+{
29376+ if (ldir->hdir)
4a4d8108 29377+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 29378+ else {
29379+ mutex_unlock(ldir->mtx);
29380+ dput(ldir->parent);
29381+ }
29382+}
29383+
29384+/* ---------------------------------------------------------------------- */
29385+
29386+/* trucate xino files asynchronously */
29387+
29388+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
29389+{
29390+ int err;
29391+ aufs_bindex_t bi, bend;
29392+ struct au_branch *br;
29393+ struct file *new_xino, *file;
29394+ struct super_block *h_sb;
29395+ struct au_xino_lock_dir ldir;
29396+
29397+ err = -EINVAL;
29398+ bend = au_sbend(sb);
29399+ if (unlikely(bindex < 0 || bend < bindex))
29400+ goto out;
29401+ br = au_sbr(sb, bindex);
29402+ file = br->br_xino.xi_file;
29403+ if (!file)
29404+ goto out;
29405+
29406+ au_xino_lock_dir(sb, file, &ldir);
29407+ /* mnt_want_write() is unnecessary here */
29408+ new_xino = au_xino_create2(file, file);
29409+ au_xino_unlock_dir(&ldir);
29410+ err = PTR_ERR(new_xino);
29411+ if (IS_ERR(new_xino))
29412+ goto out;
29413+ err = 0;
29414+ fput(file);
29415+ br->br_xino.xi_file = new_xino;
29416+
29417+ h_sb = br->br_mnt->mnt_sb;
29418+ for (bi = 0; bi <= bend; bi++) {
29419+ if (unlikely(bi == bindex))
29420+ continue;
29421+ br = au_sbr(sb, bi);
29422+ if (br->br_mnt->mnt_sb != h_sb)
29423+ continue;
29424+
29425+ fput(br->br_xino.xi_file);
29426+ br->br_xino.xi_file = new_xino;
29427+ get_file(new_xino);
29428+ }
29429+
4f0767ce 29430+out:
1facf9fc 29431+ return err;
29432+}
29433+
29434+struct xino_do_trunc_args {
29435+ struct super_block *sb;
29436+ struct au_branch *br;
29437+};
29438+
29439+static void xino_do_trunc(void *_args)
29440+{
29441+ struct xino_do_trunc_args *args = _args;
29442+ struct super_block *sb;
29443+ struct au_branch *br;
29444+ struct inode *dir;
29445+ int err;
29446+ aufs_bindex_t bindex;
29447+
29448+ err = 0;
29449+ sb = args->sb;
29450+ dir = sb->s_root->d_inode;
29451+ br = args->br;
29452+
29453+ si_noflush_write_lock(sb);
29454+ ii_read_lock_parent(dir);
29455+ bindex = au_br_index(sb, br->br_id);
29456+ err = au_xino_trunc(sb, bindex);
dece6358
AM
29457+ if (!err
29458+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 29459+ >= br->br_xino_upper)
29460+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
29461+
1facf9fc 29462+ ii_read_unlock(dir);
29463+ if (unlikely(err))
0c3ec466 29464+ pr_warn("err b%d, (%d)\n", bindex, err);
1facf9fc 29465+ atomic_dec(&br->br_xino_running);
29466+ atomic_dec(&br->br_count);
1facf9fc 29467+ si_write_unlock(sb);
027c5e7a 29468+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 29469+ kfree(args);
29470+}
29471+
29472+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
29473+{
29474+ struct xino_do_trunc_args *args;
29475+ int wkq_err;
29476+
29477+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
29478+ < br->br_xino_upper)
29479+ return;
29480+
29481+ if (atomic_inc_return(&br->br_xino_running) > 1)
29482+ goto out;
29483+
29484+ /* lock and kfree() will be called in trunc_xino() */
29485+ args = kmalloc(sizeof(*args), GFP_NOFS);
29486+ if (unlikely(!args)) {
29487+ AuErr1("no memory\n");
29488+ goto out_args;
29489+ }
29490+
e49829fe 29491+ atomic_inc(&br->br_count);
1facf9fc 29492+ args->sb = sb;
29493+ args->br = br;
53392da6 29494+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0);
1facf9fc 29495+ if (!wkq_err)
29496+ return; /* success */
29497+
4a4d8108 29498+ pr_err("wkq %d\n", wkq_err);
e49829fe 29499+ atomic_dec(&br->br_count);
1facf9fc 29500+
4f0767ce 29501+out_args:
1facf9fc 29502+ kfree(args);
4f0767ce 29503+out:
e49829fe 29504+ atomic_dec(&br->br_xino_running);
1facf9fc 29505+}
29506+
29507+/* ---------------------------------------------------------------------- */
29508+
29509+static int au_xino_do_write(au_writef_t write, struct file *file,
29510+ ino_t h_ino, ino_t ino)
29511+{
29512+ loff_t pos;
29513+ ssize_t sz;
29514+
29515+ pos = h_ino;
29516+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
29517+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
29518+ return -EFBIG;
29519+ }
29520+ pos *= sizeof(ino);
29521+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
29522+ if (sz == sizeof(ino))
29523+ return 0; /* success */
29524+
29525+ AuIOErr("write failed (%zd)\n", sz);
29526+ return -EIO;
29527+}
29528+
29529+/*
29530+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
29531+ * at the position of @h_ino.
29532+ * even if @ino is zero, it is written to the xinofile and means no entry.
29533+ * if the size of the xino file on a specific filesystem exceeds the watermark,
29534+ * try truncating it.
29535+ */
29536+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
29537+ ino_t ino)
29538+{
29539+ int err;
29540+ unsigned int mnt_flags;
29541+ struct au_branch *br;
29542+
29543+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
29544+ || ((loff_t)-1) > 0);
dece6358 29545+ SiMustAnyLock(sb);
1facf9fc 29546+
29547+ mnt_flags = au_mntflags(sb);
29548+ if (!au_opt_test(mnt_flags, XINO))
29549+ return 0;
29550+
29551+ br = au_sbr(sb, bindex);
29552+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
29553+ h_ino, ino);
29554+ if (!err) {
29555+ if (au_opt_test(mnt_flags, TRUNC_XINO)
29556+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
29557+ xino_try_trunc(sb, br);
29558+ return 0; /* success */
29559+ }
29560+
29561+ AuIOErr("write failed (%d)\n", err);
29562+ return -EIO;
29563+}
29564+
29565+/* ---------------------------------------------------------------------- */
29566+
29567+/* aufs inode number bitmap */
29568+
29569+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
29570+static ino_t xib_calc_ino(unsigned long pindex, int bit)
29571+{
29572+ ino_t ino;
29573+
29574+ AuDebugOn(bit < 0 || page_bits <= bit);
29575+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
29576+ return ino;
29577+}
29578+
29579+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
29580+{
29581+ AuDebugOn(ino < AUFS_FIRST_INO);
29582+ ino -= AUFS_FIRST_INO;
29583+ *pindex = ino / page_bits;
29584+ *bit = ino % page_bits;
29585+}
29586+
29587+static int xib_pindex(struct super_block *sb, unsigned long pindex)
29588+{
29589+ int err;
29590+ loff_t pos;
29591+ ssize_t sz;
29592+ struct au_sbinfo *sbinfo;
29593+ struct file *xib;
29594+ unsigned long *p;
29595+
29596+ sbinfo = au_sbi(sb);
29597+ MtxMustLock(&sbinfo->si_xib_mtx);
29598+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
29599+ || !au_opt_test(sbinfo->si_mntflags, XINO));
29600+
29601+ if (pindex == sbinfo->si_xib_last_pindex)
29602+ return 0;
29603+
29604+ xib = sbinfo->si_xib;
29605+ p = sbinfo->si_xib_buf;
29606+ pos = sbinfo->si_xib_last_pindex;
29607+ pos *= PAGE_SIZE;
29608+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
29609+ if (unlikely(sz != PAGE_SIZE))
29610+ goto out;
29611+
29612+ pos = pindex;
29613+ pos *= PAGE_SIZE;
29614+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
29615+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
29616+ else {
29617+ memset(p, 0, PAGE_SIZE);
29618+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
29619+ }
29620+ if (sz == PAGE_SIZE) {
29621+ sbinfo->si_xib_last_pindex = pindex;
29622+ return 0; /* success */
29623+ }
29624+
4f0767ce 29625+out:
b752ccd1
AM
29626+ AuIOErr1("write failed (%zd)\n", sz);
29627+ err = sz;
29628+ if (sz >= 0)
29629+ err = -EIO;
29630+ return err;
29631+}
29632+
29633+/* ---------------------------------------------------------------------- */
29634+
29635+static void au_xib_clear_bit(struct inode *inode)
29636+{
29637+ int err, bit;
29638+ unsigned long pindex;
29639+ struct super_block *sb;
29640+ struct au_sbinfo *sbinfo;
29641+
29642+ AuDebugOn(inode->i_nlink);
29643+
29644+ sb = inode->i_sb;
29645+ xib_calc_bit(inode->i_ino, &pindex, &bit);
29646+ AuDebugOn(page_bits <= bit);
29647+ sbinfo = au_sbi(sb);
29648+ mutex_lock(&sbinfo->si_xib_mtx);
29649+ err = xib_pindex(sb, pindex);
29650+ if (!err) {
29651+ clear_bit(bit, sbinfo->si_xib_buf);
29652+ sbinfo->si_xib_next_bit = bit;
29653+ }
29654+ mutex_unlock(&sbinfo->si_xib_mtx);
29655+}
29656+
29657+/* for s_op->delete_inode() */
29658+void au_xino_delete_inode(struct inode *inode, const int unlinked)
29659+{
29660+ int err;
29661+ unsigned int mnt_flags;
29662+ aufs_bindex_t bindex, bend, bi;
29663+ unsigned char try_trunc;
29664+ struct au_iinfo *iinfo;
29665+ struct super_block *sb;
29666+ struct au_hinode *hi;
29667+ struct inode *h_inode;
29668+ struct au_branch *br;
29669+ au_writef_t xwrite;
29670+
29671+ sb = inode->i_sb;
29672+ mnt_flags = au_mntflags(sb);
29673+ if (!au_opt_test(mnt_flags, XINO)
29674+ || inode->i_ino == AUFS_ROOT_INO)
29675+ return;
29676+
29677+ if (unlinked) {
29678+ au_xigen_inc(inode);
29679+ au_xib_clear_bit(inode);
29680+ }
29681+
29682+ iinfo = au_ii(inode);
29683+ if (!iinfo)
29684+ return;
1facf9fc 29685+
b752ccd1
AM
29686+ bindex = iinfo->ii_bstart;
29687+ if (bindex < 0)
29688+ return;
1facf9fc 29689+
b752ccd1
AM
29690+ xwrite = au_sbi(sb)->si_xwrite;
29691+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
29692+ hi = iinfo->ii_hinode + bindex;
29693+ bend = iinfo->ii_bend;
29694+ for (; bindex <= bend; bindex++, hi++) {
29695+ h_inode = hi->hi_inode;
29696+ if (!h_inode
29697+ || (!unlinked && h_inode->i_nlink))
29698+ continue;
1facf9fc 29699+
b752ccd1
AM
29700+ /* inode may not be revalidated */
29701+ bi = au_br_index(sb, hi->hi_id);
29702+ if (bi < 0)
29703+ continue;
1facf9fc 29704+
b752ccd1
AM
29705+ br = au_sbr(sb, bi);
29706+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
29707+ h_inode->i_ino, /*ino*/0);
29708+ if (!err && try_trunc
29709+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
29710+ xino_try_trunc(sb, br);
1facf9fc 29711+ }
1facf9fc 29712+}
29713+
29714+/* get an unused inode number from bitmap */
29715+ino_t au_xino_new_ino(struct super_block *sb)
29716+{
29717+ ino_t ino;
29718+ unsigned long *p, pindex, ul, pend;
29719+ struct au_sbinfo *sbinfo;
29720+ struct file *file;
29721+ int free_bit, err;
29722+
29723+ if (!au_opt_test(au_mntflags(sb), XINO))
29724+ return iunique(sb, AUFS_FIRST_INO);
29725+
29726+ sbinfo = au_sbi(sb);
29727+ mutex_lock(&sbinfo->si_xib_mtx);
29728+ p = sbinfo->si_xib_buf;
29729+ free_bit = sbinfo->si_xib_next_bit;
29730+ if (free_bit < page_bits && !test_bit(free_bit, p))
29731+ goto out; /* success */
29732+ free_bit = find_first_zero_bit(p, page_bits);
29733+ if (free_bit < page_bits)
29734+ goto out; /* success */
29735+
29736+ pindex = sbinfo->si_xib_last_pindex;
29737+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
29738+ err = xib_pindex(sb, ul);
29739+ if (unlikely(err))
29740+ goto out_err;
29741+ free_bit = find_first_zero_bit(p, page_bits);
29742+ if (free_bit < page_bits)
29743+ goto out; /* success */
29744+ }
29745+
29746+ file = sbinfo->si_xib;
29747+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
29748+ for (ul = pindex + 1; ul <= pend; ul++) {
29749+ err = xib_pindex(sb, ul);
29750+ if (unlikely(err))
29751+ goto out_err;
29752+ free_bit = find_first_zero_bit(p, page_bits);
29753+ if (free_bit < page_bits)
29754+ goto out; /* success */
29755+ }
29756+ BUG();
29757+
4f0767ce 29758+out:
1facf9fc 29759+ set_bit(free_bit, p);
7f207e10 29760+ sbinfo->si_xib_next_bit = free_bit + 1;
1facf9fc 29761+ pindex = sbinfo->si_xib_last_pindex;
29762+ mutex_unlock(&sbinfo->si_xib_mtx);
29763+ ino = xib_calc_ino(pindex, free_bit);
29764+ AuDbg("i%lu\n", (unsigned long)ino);
29765+ return ino;
4f0767ce 29766+out_err:
1facf9fc 29767+ mutex_unlock(&sbinfo->si_xib_mtx);
29768+ AuDbg("i0\n");
29769+ return 0;
29770+}
29771+
29772+/*
29773+ * read @ino from xinofile for the specified branch{@sb, @bindex}
29774+ * at the position of @h_ino.
29775+ * if @ino does not exist and @do_new is true, get new one.
29776+ */
29777+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
29778+ ino_t *ino)
29779+{
29780+ int err;
29781+ ssize_t sz;
29782+ loff_t pos;
29783+ struct file *file;
29784+ struct au_sbinfo *sbinfo;
29785+
29786+ *ino = 0;
29787+ if (!au_opt_test(au_mntflags(sb), XINO))
29788+ return 0; /* no xino */
29789+
29790+ err = 0;
29791+ sbinfo = au_sbi(sb);
29792+ pos = h_ino;
29793+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
29794+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
29795+ return -EFBIG;
29796+ }
29797+ pos *= sizeof(*ino);
29798+
29799+ file = au_sbr(sb, bindex)->br_xino.xi_file;
29800+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
29801+ return 0; /* no ino */
29802+
29803+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
29804+ if (sz == sizeof(*ino))
29805+ return 0; /* success */
29806+
29807+ err = sz;
29808+ if (unlikely(sz >= 0)) {
29809+ err = -EIO;
29810+ AuIOErr("xino read error (%zd)\n", sz);
29811+ }
29812+
29813+ return err;
29814+}
29815+
29816+/* ---------------------------------------------------------------------- */
29817+
29818+/* create and set a new xino file */
29819+
29820+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
29821+{
29822+ struct file *file;
29823+ struct dentry *h_parent, *d;
29824+ struct inode *h_dir;
29825+ int err;
29826+
29827+ /*
29828+ * at mount-time, and the xino file is the default path,
4a4d8108 29829+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 29830+ * when a user specified the xino, we cannot get au_hdir to be ignored.
29831+ */
7f207e10 29832+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 29833+ /* | __FMODE_NONOTIFY */,
1facf9fc 29834+ S_IRUGO | S_IWUGO);
29835+ if (IS_ERR(file)) {
29836+ if (!silent)
4a4d8108 29837+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 29838+ return file;
29839+ }
29840+
29841+ /* keep file count */
29842+ h_parent = dget_parent(file->f_dentry);
29843+ h_dir = h_parent->d_inode;
29844+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
29845+ /* mnt_want_write() is unnecessary here */
29846+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
29847+ mutex_unlock(&h_dir->i_mutex);
29848+ dput(h_parent);
29849+ if (unlikely(err)) {
29850+ if (!silent)
4a4d8108 29851+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 29852+ goto out;
29853+ }
29854+
29855+ err = -EINVAL;
29856+ d = file->f_dentry;
29857+ if (unlikely(sb == d->d_sb)) {
29858+ if (!silent)
4a4d8108 29859+ pr_err("%s must be outside\n", fname);
1facf9fc 29860+ goto out;
29861+ }
29862+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
29863+ if (!silent)
4a4d8108
AM
29864+ pr_err("xino doesn't support %s(%s)\n",
29865+ fname, au_sbtype(d->d_sb));
1facf9fc 29866+ goto out;
29867+ }
29868+ return file; /* success */
29869+
4f0767ce 29870+out:
1facf9fc 29871+ fput(file);
29872+ file = ERR_PTR(err);
29873+ return file;
29874+}
29875+
29876+/*
29877+ * find another branch who is on the same filesystem of the specified
29878+ * branch{@btgt}. search until @bend.
29879+ */
29880+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
29881+ aufs_bindex_t bend)
29882+{
29883+ aufs_bindex_t bindex;
29884+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
29885+
29886+ for (bindex = 0; bindex < btgt; bindex++)
29887+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
29888+ return bindex;
29889+ for (bindex++; bindex <= bend; bindex++)
29890+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
29891+ return bindex;
29892+ return -1;
29893+}
29894+
29895+/* ---------------------------------------------------------------------- */
29896+
29897+/*
29898+ * initialize the xinofile for the specified branch @br
29899+ * at the place/path where @base_file indicates.
29900+ * test whether another branch is on the same filesystem or not,
29901+ * if @do_test is true.
29902+ */
29903+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
29904+ struct file *base_file, int do_test)
29905+{
29906+ int err;
29907+ ino_t ino;
29908+ aufs_bindex_t bend, bindex;
29909+ struct au_branch *shared_br, *b;
29910+ struct file *file;
29911+ struct super_block *tgt_sb;
29912+
29913+ shared_br = NULL;
29914+ bend = au_sbend(sb);
29915+ if (do_test) {
29916+ tgt_sb = br->br_mnt->mnt_sb;
29917+ for (bindex = 0; bindex <= bend; bindex++) {
29918+ b = au_sbr(sb, bindex);
29919+ if (tgt_sb == b->br_mnt->mnt_sb) {
29920+ shared_br = b;
29921+ break;
29922+ }
29923+ }
29924+ }
29925+
29926+ if (!shared_br || !shared_br->br_xino.xi_file) {
29927+ struct au_xino_lock_dir ldir;
29928+
29929+ au_xino_lock_dir(sb, base_file, &ldir);
29930+ /* mnt_want_write() is unnecessary here */
29931+ file = au_xino_create2(base_file, NULL);
29932+ au_xino_unlock_dir(&ldir);
29933+ err = PTR_ERR(file);
29934+ if (IS_ERR(file))
29935+ goto out;
29936+ br->br_xino.xi_file = file;
29937+ } else {
29938+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
29939+ get_file(br->br_xino.xi_file);
29940+ }
29941+
29942+ ino = AUFS_ROOT_INO;
29943+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
29944+ h_ino, ino);
b752ccd1
AM
29945+ if (unlikely(err)) {
29946+ fput(br->br_xino.xi_file);
29947+ br->br_xino.xi_file = NULL;
29948+ }
1facf9fc 29949+
4f0767ce 29950+out:
1facf9fc 29951+ return err;
29952+}
29953+
29954+/* ---------------------------------------------------------------------- */
29955+
29956+/* trucate a xino bitmap file */
29957+
29958+/* todo: slow */
29959+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
29960+{
29961+ int err, bit;
29962+ ssize_t sz;
29963+ unsigned long pindex;
29964+ loff_t pos, pend;
29965+ struct au_sbinfo *sbinfo;
29966+ au_readf_t func;
29967+ ino_t *ino;
29968+ unsigned long *p;
29969+
29970+ err = 0;
29971+ sbinfo = au_sbi(sb);
dece6358 29972+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 29973+ p = sbinfo->si_xib_buf;
29974+ func = sbinfo->si_xread;
29975+ pend = i_size_read(file->f_dentry->d_inode);
29976+ pos = 0;
29977+ while (pos < pend) {
29978+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
29979+ err = sz;
29980+ if (unlikely(sz <= 0))
29981+ goto out;
29982+
29983+ err = 0;
29984+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
29985+ if (unlikely(*ino < AUFS_FIRST_INO))
29986+ continue;
29987+
29988+ xib_calc_bit(*ino, &pindex, &bit);
29989+ AuDebugOn(page_bits <= bit);
29990+ err = xib_pindex(sb, pindex);
29991+ if (!err)
29992+ set_bit(bit, p);
29993+ else
29994+ goto out;
29995+ }
29996+ }
29997+
4f0767ce 29998+out:
1facf9fc 29999+ return err;
30000+}
30001+
30002+static int xib_restore(struct super_block *sb)
30003+{
30004+ int err;
30005+ aufs_bindex_t bindex, bend;
30006+ void *page;
30007+
30008+ err = -ENOMEM;
30009+ page = (void *)__get_free_page(GFP_NOFS);
30010+ if (unlikely(!page))
30011+ goto out;
30012+
30013+ err = 0;
30014+ bend = au_sbend(sb);
30015+ for (bindex = 0; !err && bindex <= bend; bindex++)
30016+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
30017+ err = do_xib_restore
30018+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
30019+ else
30020+ AuDbg("b%d\n", bindex);
30021+ free_page((unsigned long)page);
30022+
4f0767ce 30023+out:
1facf9fc 30024+ return err;
30025+}
30026+
30027+int au_xib_trunc(struct super_block *sb)
30028+{
30029+ int err;
30030+ ssize_t sz;
30031+ loff_t pos;
30032+ struct au_xino_lock_dir ldir;
30033+ struct au_sbinfo *sbinfo;
30034+ unsigned long *p;
30035+ struct file *file;
30036+
dece6358
AM
30037+ SiMustWriteLock(sb);
30038+
1facf9fc 30039+ err = 0;
30040+ sbinfo = au_sbi(sb);
30041+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
30042+ goto out;
30043+
30044+ file = sbinfo->si_xib;
30045+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
30046+ goto out;
30047+
30048+ au_xino_lock_dir(sb, file, &ldir);
30049+ /* mnt_want_write() is unnecessary here */
30050+ file = au_xino_create2(sbinfo->si_xib, NULL);
30051+ au_xino_unlock_dir(&ldir);
30052+ err = PTR_ERR(file);
30053+ if (IS_ERR(file))
30054+ goto out;
30055+ fput(sbinfo->si_xib);
30056+ sbinfo->si_xib = file;
30057+
30058+ p = sbinfo->si_xib_buf;
30059+ memset(p, 0, PAGE_SIZE);
30060+ pos = 0;
30061+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
30062+ if (unlikely(sz != PAGE_SIZE)) {
30063+ err = sz;
30064+ AuIOErr("err %d\n", err);
30065+ if (sz >= 0)
30066+ err = -EIO;
30067+ goto out;
30068+ }
30069+
30070+ mutex_lock(&sbinfo->si_xib_mtx);
30071+ /* mnt_want_write() is unnecessary here */
30072+ err = xib_restore(sb);
30073+ mutex_unlock(&sbinfo->si_xib_mtx);
30074+
30075+out:
30076+ return err;
30077+}
30078+
30079+/* ---------------------------------------------------------------------- */
30080+
30081+/*
30082+ * xino mount option handlers
30083+ */
30084+static au_readf_t find_readf(struct file *h_file)
30085+{
30086+ const struct file_operations *fop = h_file->f_op;
30087+
30088+ if (fop) {
30089+ if (fop->read)
30090+ return fop->read;
30091+ if (fop->aio_read)
30092+ return do_sync_read;
30093+ }
30094+ return ERR_PTR(-ENOSYS);
30095+}
30096+
30097+static au_writef_t find_writef(struct file *h_file)
30098+{
30099+ const struct file_operations *fop = h_file->f_op;
30100+
30101+ if (fop) {
30102+ if (fop->write)
30103+ return fop->write;
30104+ if (fop->aio_write)
30105+ return do_sync_write;
30106+ }
30107+ return ERR_PTR(-ENOSYS);
30108+}
30109+
30110+/* xino bitmap */
30111+static void xino_clear_xib(struct super_block *sb)
30112+{
30113+ struct au_sbinfo *sbinfo;
30114+
dece6358
AM
30115+ SiMustWriteLock(sb);
30116+
1facf9fc 30117+ sbinfo = au_sbi(sb);
30118+ sbinfo->si_xread = NULL;
30119+ sbinfo->si_xwrite = NULL;
30120+ if (sbinfo->si_xib)
30121+ fput(sbinfo->si_xib);
30122+ sbinfo->si_xib = NULL;
30123+ free_page((unsigned long)sbinfo->si_xib_buf);
30124+ sbinfo->si_xib_buf = NULL;
30125+}
30126+
30127+static int au_xino_set_xib(struct super_block *sb, struct file *base)
30128+{
30129+ int err;
30130+ loff_t pos;
30131+ struct au_sbinfo *sbinfo;
30132+ struct file *file;
30133+
dece6358
AM
30134+ SiMustWriteLock(sb);
30135+
1facf9fc 30136+ sbinfo = au_sbi(sb);
30137+ file = au_xino_create2(base, sbinfo->si_xib);
30138+ err = PTR_ERR(file);
30139+ if (IS_ERR(file))
30140+ goto out;
30141+ if (sbinfo->si_xib)
30142+ fput(sbinfo->si_xib);
30143+ sbinfo->si_xib = file;
30144+ sbinfo->si_xread = find_readf(file);
30145+ sbinfo->si_xwrite = find_writef(file);
30146+
30147+ err = -ENOMEM;
30148+ if (!sbinfo->si_xib_buf)
30149+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
30150+ if (unlikely(!sbinfo->si_xib_buf))
30151+ goto out_unset;
30152+
30153+ sbinfo->si_xib_last_pindex = 0;
30154+ sbinfo->si_xib_next_bit = 0;
30155+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
30156+ pos = 0;
30157+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
30158+ PAGE_SIZE, &pos);
30159+ if (unlikely(err != PAGE_SIZE))
30160+ goto out_free;
30161+ }
30162+ err = 0;
30163+ goto out; /* success */
30164+
4f0767ce 30165+out_free:
1facf9fc 30166+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
30167+ sbinfo->si_xib_buf = NULL;
30168+ if (err >= 0)
30169+ err = -EIO;
4f0767ce 30170+out_unset:
b752ccd1
AM
30171+ fput(sbinfo->si_xib);
30172+ sbinfo->si_xib = NULL;
30173+ sbinfo->si_xread = NULL;
30174+ sbinfo->si_xwrite = NULL;
4f0767ce 30175+out:
b752ccd1 30176+ return err;
1facf9fc 30177+}
30178+
b752ccd1
AM
30179+/* xino for each branch */
30180+static void xino_clear_br(struct super_block *sb)
30181+{
30182+ aufs_bindex_t bindex, bend;
30183+ struct au_branch *br;
1facf9fc 30184+
b752ccd1
AM
30185+ bend = au_sbend(sb);
30186+ for (bindex = 0; bindex <= bend; bindex++) {
30187+ br = au_sbr(sb, bindex);
30188+ if (!br || !br->br_xino.xi_file)
30189+ continue;
30190+
30191+ fput(br->br_xino.xi_file);
30192+ br->br_xino.xi_file = NULL;
30193+ }
30194+}
30195+
30196+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 30197+{
30198+ int err;
b752ccd1
AM
30199+ ino_t ino;
30200+ aufs_bindex_t bindex, bend, bshared;
30201+ struct {
30202+ struct file *old, *new;
30203+ } *fpair, *p;
30204+ struct au_branch *br;
30205+ struct inode *inode;
30206+ au_writef_t writef;
1facf9fc 30207+
b752ccd1
AM
30208+ SiMustWriteLock(sb);
30209+
30210+ err = -ENOMEM;
30211+ bend = au_sbend(sb);
30212+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
30213+ if (unlikely(!fpair))
1facf9fc 30214+ goto out;
30215+
b752ccd1
AM
30216+ inode = sb->s_root->d_inode;
30217+ ino = AUFS_ROOT_INO;
30218+ writef = au_sbi(sb)->si_xwrite;
30219+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
30220+ br = au_sbr(sb, bindex);
30221+ bshared = is_sb_shared(sb, bindex, bindex - 1);
30222+ if (bshared >= 0) {
30223+ /* shared xino */
30224+ *p = fpair[bshared];
30225+ get_file(p->new);
30226+ }
30227+
30228+ if (!p->new) {
30229+ /* new xino */
30230+ p->old = br->br_xino.xi_file;
30231+ p->new = au_xino_create2(base, br->br_xino.xi_file);
30232+ err = PTR_ERR(p->new);
30233+ if (IS_ERR(p->new)) {
30234+ p->new = NULL;
30235+ goto out_pair;
30236+ }
30237+ }
30238+
30239+ err = au_xino_do_write(writef, p->new,
30240+ au_h_iptr(inode, bindex)->i_ino, ino);
30241+ if (unlikely(err))
30242+ goto out_pair;
30243+ }
30244+
30245+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
30246+ br = au_sbr(sb, bindex);
30247+ if (br->br_xino.xi_file)
30248+ fput(br->br_xino.xi_file);
30249+ get_file(p->new);
30250+ br->br_xino.xi_file = p->new;
30251+ }
1facf9fc 30252+
4f0767ce 30253+out_pair:
b752ccd1
AM
30254+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
30255+ if (p->new)
30256+ fput(p->new);
30257+ else
30258+ break;
30259+ kfree(fpair);
4f0767ce 30260+out:
1facf9fc 30261+ return err;
30262+}
b752ccd1
AM
30263+
30264+void au_xino_clr(struct super_block *sb)
30265+{
30266+ struct au_sbinfo *sbinfo;
30267+
30268+ au_xigen_clr(sb);
30269+ xino_clear_xib(sb);
30270+ xino_clear_br(sb);
30271+ sbinfo = au_sbi(sb);
30272+ /* lvalue, do not call au_mntflags() */
30273+ au_opt_clr(sbinfo->si_mntflags, XINO);
30274+}
30275+
30276+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
30277+{
30278+ int err, skip;
30279+ struct dentry *parent, *cur_parent;
30280+ struct qstr *dname, *cur_name;
30281+ struct file *cur_xino;
30282+ struct inode *dir;
30283+ struct au_sbinfo *sbinfo;
30284+
30285+ SiMustWriteLock(sb);
30286+
30287+ err = 0;
30288+ sbinfo = au_sbi(sb);
30289+ parent = dget_parent(xino->file->f_dentry);
30290+ if (remount) {
30291+ skip = 0;
30292+ dname = &xino->file->f_dentry->d_name;
30293+ cur_xino = sbinfo->si_xib;
30294+ if (cur_xino) {
30295+ cur_parent = dget_parent(cur_xino->f_dentry);
30296+ cur_name = &cur_xino->f_dentry->d_name;
30297+ skip = (cur_parent == parent
30298+ && dname->len == cur_name->len
30299+ && !memcmp(dname->name, cur_name->name,
30300+ dname->len));
30301+ dput(cur_parent);
30302+ }
30303+ if (skip)
30304+ goto out;
30305+ }
30306+
30307+ au_opt_set(sbinfo->si_mntflags, XINO);
30308+ dir = parent->d_inode;
30309+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
30310+ /* mnt_want_write() is unnecessary here */
30311+ err = au_xino_set_xib(sb, xino->file);
30312+ if (!err)
30313+ err = au_xigen_set(sb, xino->file);
30314+ if (!err)
30315+ err = au_xino_set_br(sb, xino->file);
30316+ mutex_unlock(&dir->i_mutex);
30317+ if (!err)
30318+ goto out; /* success */
30319+
30320+ /* reset all */
30321+ AuIOErr("failed creating xino(%d).\n", err);
30322+
4f0767ce 30323+out:
b752ccd1
AM
30324+ dput(parent);
30325+ return err;
30326+}
30327+
30328+/* ---------------------------------------------------------------------- */
30329+
30330+/*
30331+ * create a xinofile at the default place/path.
30332+ */
30333+struct file *au_xino_def(struct super_block *sb)
30334+{
30335+ struct file *file;
30336+ char *page, *p;
30337+ struct au_branch *br;
30338+ struct super_block *h_sb;
30339+ struct path path;
30340+ aufs_bindex_t bend, bindex, bwr;
30341+
30342+ br = NULL;
30343+ bend = au_sbend(sb);
30344+ bwr = -1;
30345+ for (bindex = 0; bindex <= bend; bindex++) {
30346+ br = au_sbr(sb, bindex);
30347+ if (au_br_writable(br->br_perm)
30348+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
30349+ bwr = bindex;
30350+ break;
30351+ }
30352+ }
30353+
7f207e10
AM
30354+ if (bwr >= 0) {
30355+ file = ERR_PTR(-ENOMEM);
30356+ page = __getname_gfp(GFP_NOFS);
30357+ if (unlikely(!page))
30358+ goto out;
30359+ path.mnt = br->br_mnt;
30360+ path.dentry = au_h_dptr(sb->s_root, bwr);
30361+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
30362+ file = (void *)p;
30363+ if (!IS_ERR(p)) {
30364+ strcat(p, "/" AUFS_XINO_FNAME);
30365+ AuDbg("%s\n", p);
30366+ file = au_xino_create(sb, p, /*silent*/0);
30367+ if (!IS_ERR(file))
30368+ au_xino_brid_set(sb, br->br_id);
30369+ }
30370+ __putname(page);
30371+ } else {
30372+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
30373+ if (IS_ERR(file))
30374+ goto out;
30375+ h_sb = file->f_dentry->d_sb;
30376+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
30377+ pr_err("xino doesn't support %s(%s)\n",
30378+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
30379+ fput(file);
30380+ file = ERR_PTR(-EINVAL);
30381+ }
30382+ if (!IS_ERR(file))
30383+ au_xino_brid_set(sb, -1);
30384+ }
0c5527e5 30385+
7f207e10
AM
30386+out:
30387+ return file;
30388+}
30389+
30390+/* ---------------------------------------------------------------------- */
30391+
30392+int au_xino_path(struct seq_file *seq, struct file *file)
30393+{
30394+ int err;
30395+
30396+ err = au_seq_path(seq, &file->f_path);
30397+ if (unlikely(err < 0))
30398+ goto out;
30399+
30400+ err = 0;
30401+#define Deleted "\\040(deleted)"
30402+ seq->count -= sizeof(Deleted) - 1;
30403+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
30404+ sizeof(Deleted) - 1));
30405+#undef Deleted
30406+
30407+out:
30408+ return err;
30409+}
30410diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
30411--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 30412+++ linux/include/linux/aufs_type.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 30413@@ -0,0 +1,233 @@
7f207e10 30414+/*
f6c5ef8b 30415+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
30416+ *
30417+ * This program, aufs is free software; you can redistribute it and/or modify
30418+ * it under the terms of the GNU General Public License as published by
30419+ * the Free Software Foundation; either version 2 of the License, or
30420+ * (at your option) any later version.
30421+ *
30422+ * This program is distributed in the hope that it will be useful,
30423+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30424+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30425+ * GNU General Public License for more details.
30426+ *
30427+ * You should have received a copy of the GNU General Public License
30428+ * along with this program; if not, write to the Free Software
30429+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30430+ */
30431+
30432+#ifndef __AUFS_TYPE_H__
30433+#define __AUFS_TYPE_H__
30434+
f6c5ef8b
AM
30435+#define AUFS_NAME "aufs"
30436+
9dbd164d 30437+#ifdef __KERNEL__
f6c5ef8b
AM
30438+/*
30439+ * define it before including all other headers.
30440+ * sched.h may use pr_* macros before defining "current", so define the
30441+ * no-current version first, and re-define later.
30442+ */
30443+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
30444+#include <linux/sched.h>
30445+#undef pr_fmt
30446+#define pr_fmt(fmt) AUFS_NAME " %s:%d:%s[%d]: " fmt, \
30447+ __func__, __LINE__, current->comm, current->pid
9dbd164d
AM
30448+#else
30449+#include <stdint.h>
30450+#include <sys/types.h>
f6c5ef8b 30451+#endif /* __KERNEL__ */
7f207e10 30452+
f6c5ef8b
AM
30453+#include <linux/limits.h>
30454+
2dfbb274 30455+#define AUFS_VERSION "3.5-20120813"
7f207e10
AM
30456+
30457+/* todo? move this to linux-2.6.19/include/magic.h */
30458+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
30459+
30460+/* ---------------------------------------------------------------------- */
30461+
30462+#ifdef CONFIG_AUFS_BRANCH_MAX_127
9dbd164d 30463+typedef int8_t aufs_bindex_t;
7f207e10
AM
30464+#define AUFS_BRANCH_MAX 127
30465+#else
9dbd164d 30466+typedef int16_t aufs_bindex_t;
7f207e10
AM
30467+#ifdef CONFIG_AUFS_BRANCH_MAX_511
30468+#define AUFS_BRANCH_MAX 511
30469+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
30470+#define AUFS_BRANCH_MAX 1023
30471+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
30472+#define AUFS_BRANCH_MAX 32767
30473+#endif
30474+#endif
30475+
30476+#ifdef __KERNEL__
30477+#ifndef AUFS_BRANCH_MAX
30478+#error unknown CONFIG_AUFS_BRANCH_MAX value
30479+#endif
30480+#endif /* __KERNEL__ */
30481+
30482+/* ---------------------------------------------------------------------- */
30483+
7f207e10
AM
30484+#define AUFS_FSTYPE AUFS_NAME
30485+
30486+#define AUFS_ROOT_INO 2
30487+#define AUFS_FIRST_INO 11
30488+
30489+#define AUFS_WH_PFX ".wh."
30490+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
30491+#define AUFS_WH_TMP_LEN 4
30492+/* a limit for rmdir/rename a dir */
30493+#define AUFS_MAX_NAMELEN (NAME_MAX \
30494+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
30495+ - 1 /* dot */\
30496+ - AUFS_WH_TMP_LEN) /* hex */
30497+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
30498+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
30499+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
30500+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
30501+#define AUFS_DIRWH_DEF 3
30502+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 30503+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
30504+#define AUFS_RDBLK_DEF 512 /* bytes */
30505+#define AUFS_RDHASH_DEF 32
30506+#define AUFS_WKQ_NAME AUFS_NAME "d"
027c5e7a
AM
30507+#define AUFS_MFS_DEF_SEC 30 /* seconds */
30508+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
7f207e10
AM
30509+#define AUFS_PLINK_WARN 100 /* number of plinks */
30510+
30511+/* pseudo-link maintenace under /proc */
30512+#define AUFS_PLINK_MAINT_NAME "plink_maint"
30513+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
30514+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
30515+
30516+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
30517+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
30518+
30519+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
30520+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
30521+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
30522+
30523+/* doubly whiteouted */
30524+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
30525+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
30526+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
30527+
1e00d052 30528+/* branch permissions and attributes */
7f207e10
AM
30529+#define AUFS_BRPERM_RW "rw"
30530+#define AUFS_BRPERM_RO "ro"
30531+#define AUFS_BRPERM_RR "rr"
1e00d052
AM
30532+#define AUFS_BRRATTR_WH "wh"
30533+#define AUFS_BRWATTR_NLWH "nolwh"
7f207e10
AM
30534+
30535+/* ---------------------------------------------------------------------- */
30536+
30537+/* ioctl */
30538+enum {
30539+ /* readdir in userspace */
30540+ AuCtl_RDU,
30541+ AuCtl_RDU_INO,
30542+
30543+ /* pathconf wrapper */
027c5e7a
AM
30544+ AuCtl_WBR_FD,
30545+
30546+ /* busy inode */
30547+ AuCtl_IBUSY
7f207e10
AM
30548+};
30549+
30550+/* borrowed from linux/include/linux/kernel.h */
30551+#ifndef ALIGN
30552+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
30553+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
30554+#endif
30555+
30556+/* borrowed from linux/include/linux/compiler-gcc3.h */
30557+#ifndef __aligned
30558+#define __aligned(x) __attribute__((aligned(x)))
53392da6
AM
30559+#endif
30560+
30561+#ifdef __KERNEL__
30562+#ifndef __packed
7f207e10
AM
30563+#define __packed __attribute__((packed))
30564+#endif
53392da6 30565+#endif
7f207e10
AM
30566+
30567+struct au_rdu_cookie {
9dbd164d
AM
30568+ uint64_t h_pos;
30569+ int16_t bindex;
30570+ uint8_t flags;
30571+ uint8_t pad;
30572+ uint32_t generation;
7f207e10
AM
30573+} __aligned(8);
30574+
30575+struct au_rdu_ent {
9dbd164d
AM
30576+ uint64_t ino;
30577+ int16_t bindex;
30578+ uint8_t type;
30579+ uint8_t nlen;
30580+ uint8_t wh;
7f207e10
AM
30581+ char name[0];
30582+} __aligned(8);
30583+
30584+static inline int au_rdu_len(int nlen)
30585+{
30586+ /* include the terminating NULL */
30587+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
9dbd164d 30588+ sizeof(uint64_t));
7f207e10
AM
30589+}
30590+
30591+union au_rdu_ent_ul {
30592+ struct au_rdu_ent __user *e;
9dbd164d 30593+ uint64_t ul;
7f207e10
AM
30594+};
30595+
30596+enum {
30597+ AufsCtlRduV_SZ,
30598+ AufsCtlRduV_End
30599+};
30600+
30601+struct aufs_rdu {
30602+ /* input */
30603+ union {
9dbd164d
AM
30604+ uint64_t sz; /* AuCtl_RDU */
30605+ uint64_t nent; /* AuCtl_RDU_INO */
7f207e10
AM
30606+ };
30607+ union au_rdu_ent_ul ent;
9dbd164d 30608+ uint16_t verify[AufsCtlRduV_End];
7f207e10
AM
30609+
30610+ /* input/output */
9dbd164d 30611+ uint32_t blk;
7f207e10
AM
30612+
30613+ /* output */
30614+ union au_rdu_ent_ul tail;
30615+ /* number of entries which were added in a single call */
9dbd164d
AM
30616+ uint64_t rent;
30617+ uint8_t full;
30618+ uint8_t shwh;
7f207e10
AM
30619+
30620+ struct au_rdu_cookie cookie;
30621+} __aligned(8);
30622+
1e00d052
AM
30623+/* ---------------------------------------------------------------------- */
30624+
30625+struct aufs_wbr_fd {
9dbd164d
AM
30626+ uint32_t oflags;
30627+ int16_t brid;
1e00d052
AM
30628+} __aligned(8);
30629+
30630+/* ---------------------------------------------------------------------- */
30631+
027c5e7a 30632+struct aufs_ibusy {
9dbd164d
AM
30633+ uint64_t ino, h_ino;
30634+ int16_t bindex;
027c5e7a
AM
30635+} __aligned(8);
30636+
1e00d052
AM
30637+/* ---------------------------------------------------------------------- */
30638+
7f207e10
AM
30639+#define AuCtlType 'A'
30640+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
30641+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
1e00d052
AM
30642+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
30643+ struct aufs_wbr_fd)
027c5e7a 30644+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
7f207e10
AM
30645+
30646+#endif /* __AUFS_TYPE_H__ */
2dfbb274 30647
This page took 5.528994 seconds and 4 git commands to generate.