]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs2.patch
- update grsec related patches
[packages/kernel.git] / kernel-aufs2.patch
CommitLineData
7f207e10
AM
1aufs2.1 kbuild patch for linux-2.6.36
2
3diff --git a/fs/Kconfig b/fs/Kconfig
4index 3d18530..8f582e1 100644
5--- a/fs/Kconfig
6+++ b/fs/Kconfig
7@@ -189,6 +189,7 @@ source "fs/romfs/Kconfig"
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
16index e6ec1d3..b0d795a 100644
17--- a/fs/Makefile
18+++ b/fs/Makefile
19@@ -126,3 +126,4 @@ obj-$(CONFIG_BTRFS_FS) += btrfs/
20 obj-$(CONFIG_GFS2_FS) += gfs2/
21 obj-$(CONFIG_EXOFS_FS) += exofs/
22 obj-$(CONFIG_CEPH_FS) += ceph/
23+obj-$(CONFIG_AUFS_FS) += aufs/
24diff --git a/include/linux/Kbuild b/include/linux/Kbuild
25index 4e8ea8c..b8fc201 100644
26--- a/include/linux/Kbuild
27+++ b/include/linux/Kbuild
28@@ -60,6 +60,7 @@ header-y += atmppp.h
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
36aufs2.1 base patch for linux-2.6.36
37
38diff --git a/fs/namei.c b/fs/namei.c
39index 24896e8..19d69c5 100644
40--- a/fs/namei.c
41+++ b/fs/namei.c
42@@ -1159,7 +1159,7 @@ out:
43 * needs parent already locked. Doesn't follow mounts.
44 * SMP-safe.
45 */
46-static struct dentry *lookup_hash(struct nameidata *nd)
47+struct dentry *lookup_hash(struct nameidata *nd)
48 {
49 int err;
50
51@@ -1169,7 +1169,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
52 return __lookup_hash(&nd->last, nd->path.dentry, nd);
53 }
54
55-static int __lookup_one_len(const char *name, struct qstr *this,
56+int __lookup_one_len(const char *name, struct qstr *this,
57 struct dentry *base, int len)
58 {
59 unsigned long hash;
60diff --git a/fs/splice.c b/fs/splice.c
61index 8f1dfae..278c94f 100644
62--- a/fs/splice.c
63+++ b/fs/splice.c
64@@ -1092,8 +1092,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
65 /*
66 * Attempt to initiate a splice from pipe to file.
67 */
68-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
69- loff_t *ppos, size_t len, unsigned int flags)
70+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
71+ loff_t *ppos, size_t len, unsigned int flags)
72 {
73 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
74 loff_t *, size_t, unsigned int);
75@@ -1120,9 +1120,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
76 /*
77 * Attempt to initiate a splice from a file to a pipe.
78 */
79-static long do_splice_to(struct file *in, loff_t *ppos,
80- struct pipe_inode_info *pipe, size_t len,
81- unsigned int flags)
82+long do_splice_to(struct file *in, loff_t *ppos,
83+ struct pipe_inode_info *pipe, size_t len,
84+ unsigned int flags)
85 {
86 ssize_t (*splice_read)(struct file *, loff_t *,
87 struct pipe_inode_info *, size_t, unsigned int);
88diff --git a/include/linux/namei.h b/include/linux/namei.h
89index 05b441d..91bc74e 100644
90--- a/include/linux/namei.h
91+++ b/include/linux/namei.h
92@@ -73,6 +73,9 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
93 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
94 int (*open)(struct inode *, struct file *));
95
96+extern struct dentry *lookup_hash(struct nameidata *nd);
97+extern int __lookup_one_len(const char *name, struct qstr *this,
98+ struct dentry *base, int len);
99 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
100
101 extern int follow_down(struct path *);
102diff --git a/include/linux/splice.h b/include/linux/splice.h
103index 997c3b4..be9a153 100644
104--- a/include/linux/splice.h
105+++ b/include/linux/splice.h
106@@ -89,4 +89,10 @@ extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *);
107 extern void splice_shrink_spd(struct pipe_inode_info *,
108 struct splice_pipe_desc *);
109
110+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
111+ loff_t *ppos, size_t len, unsigned int flags);
112+extern long do_splice_to(struct file *in, loff_t *ppos,
113+ struct pipe_inode_info *pipe, size_t len,
114+ unsigned int flags);
1facf9fc 115+
7f207e10
AM
116 #endif
117aufs2.1 standalone patch for linux-2.6.36
118
119diff --git a/fs/file_table.c b/fs/file_table.c
120index a04bdd8..f51588f 100644
121--- a/fs/file_table.c
122+++ b/fs/file_table.c
123@@ -394,6 +394,8 @@ void file_sb_list_del(struct file *file)
124 }
125 }
126
127+EXPORT_SYMBOL(file_sb_list_del);
1facf9fc 128+
7f207e10
AM
129 #ifdef CONFIG_SMP
130
131 /*
132diff --git a/fs/inode.c b/fs/inode.c
133index 8646433..d84944d 100644
134--- a/fs/inode.c
135+++ b/fs/inode.c
136@@ -83,6 +83,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
137 * the i_state of an inode while it is in use..
138 */
139 DEFINE_SPINLOCK(inode_lock);
140+EXPORT_SYMBOL(inode_lock);
141
142 /*
143 * iprune_sem provides exclusion between the kswapd or try_to_free_pages
144diff --git a/fs/namei.c b/fs/namei.c
145index 19d69c5..944842e 100644
146--- a/fs/namei.c
147+++ b/fs/namei.c
148@@ -347,6 +347,7 @@ int deny_write_access(struct file * file)
149
150 return 0;
151 }
152+EXPORT_SYMBOL(deny_write_access);
153
154 /**
155 * path_get - get a reference to a path
156@@ -1168,6 +1169,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
157 return ERR_PTR(err);
158 return __lookup_hash(&nd->last, nd->path.dentry, nd);
159 }
160+EXPORT_SYMBOL(lookup_hash);
161
162 int __lookup_one_len(const char *name, struct qstr *this,
163 struct dentry *base, int len)
164@@ -1190,6 +1192,7 @@ int __lookup_one_len(const char *name, struct qstr *this,
165 this->hash = end_name_hash(hash);
166 return 0;
167 }
168+EXPORT_SYMBOL(__lookup_one_len);
169
170 /**
171 * lookup_one_len - filesystem helper to lookup single pathname component
172diff --git a/fs/namespace.c b/fs/namespace.c
173index a72eaab..36107eb 100644
174--- a/fs/namespace.c
175+++ b/fs/namespace.c
176@@ -1322,6 +1322,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
177 }
178 return 0;
179 }
180+EXPORT_SYMBOL(iterate_mounts);
181
182 static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
183 {
184diff --git a/fs/notify/group.c b/fs/notify/group.c
185index d309f38..f0e9568 100644
186--- a/fs/notify/group.c
187+++ b/fs/notify/group.c
188@@ -22,6 +22,7 @@
189 #include <linux/srcu.h>
190 #include <linux/rculist.h>
191 #include <linux/wait.h>
192+#include <linux/module.h>
193
194 #include <linux/fsnotify_backend.h>
195 #include "fsnotify.h"
196@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
197 if (atomic_dec_and_test(&group->refcnt))
198 fsnotify_destroy_group(group);
199 }
200+EXPORT_SYMBOL(fsnotify_put_group);
201
202 /*
203 * Create a new fsnotify_group and hold a reference for the group returned.
204@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
205
206 return group;
207 }
208+EXPORT_SYMBOL(fsnotify_alloc_group);
209diff --git a/fs/notify/mark.c b/fs/notify/mark.c
210index 325185e..adede09 100644
211--- a/fs/notify/mark.c
212+++ b/fs/notify/mark.c
213@@ -113,6 +113,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
214 if (atomic_dec_and_test(&mark->refcnt))
215 mark->free_mark(mark);
216 }
217+EXPORT_SYMBOL(fsnotify_put_mark);
218
219 /*
220 * Any time a mark is getting freed we end up here.
221@@ -190,6 +191,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
222 if (unlikely(atomic_dec_and_test(&group->num_marks)))
223 fsnotify_final_destroy_group(group);
224 }
225+EXPORT_SYMBOL(fsnotify_destroy_mark);
226
227 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
228 {
229@@ -277,6 +279,7 @@ err:
230
231 return ret;
232 }
233+EXPORT_SYMBOL(fsnotify_add_mark);
234
235 /*
236 * clear any marks in a group in which mark->flags & flags is true
237@@ -332,6 +335,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
238 atomic_set(&mark->refcnt, 1);
239 mark->free_mark = free_mark;
240 }
241+EXPORT_SYMBOL(fsnotify_init_mark);
242
243 static int fsnotify_mark_destroy(void *ignored)
244 {
245diff --git a/fs/open.c b/fs/open.c
246index d74e198..53ef25e 100644
247--- a/fs/open.c
248+++ b/fs/open.c
249@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
250 mutex_unlock(&dentry->d_inode->i_mutex);
251 return ret;
252 }
253+EXPORT_SYMBOL(do_truncate);
254
255 static long do_sys_truncate(const char __user *pathname, loff_t length)
256 {
257diff --git a/fs/splice.c b/fs/splice.c
258index 278c94f..033f7ac 100644
259--- a/fs/splice.c
260+++ b/fs/splice.c
261@@ -1116,6 +1116,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
262
263 return splice_write(pipe, out, ppos, len, flags);
264 }
265+EXPORT_SYMBOL(do_splice_from);
266
267 /*
268 * Attempt to initiate a splice from a file to a pipe.
269@@ -1142,6 +1143,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
270
271 return splice_read(in, ppos, pipe, len, flags);
272 }
273+EXPORT_SYMBOL(do_splice_to);
274
275 /**
276 * splice_direct_to_actor - splices data directly between two non-pipes
277diff --git a/security/commoncap.c b/security/commoncap.c
278index 9d172e6..8a61084 100644
279--- a/security/commoncap.c
280+++ b/security/commoncap.c
281@@ -951,3 +951,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
282 }
283 return ret;
284 }
285+EXPORT_SYMBOL(cap_file_mmap);
286diff --git a/security/device_cgroup.c b/security/device_cgroup.c
287index 8d9c48f..29108aa 100644
288--- a/security/device_cgroup.c
289+++ b/security/device_cgroup.c
290@@ -515,6 +515,7 @@ found:
291
292 return -EPERM;
293 }
294+EXPORT_SYMBOL(devcgroup_inode_permission);
295
296 int devcgroup_inode_mknod(int mode, dev_t dev)
297 {
298diff --git a/security/security.c b/security/security.c
299index c53949f..0ae5b91 100644
300--- a/security/security.c
301+++ b/security/security.c
302@@ -376,6 +376,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
303 return 0;
304 return security_ops->path_mkdir(dir, dentry, mode);
305 }
306+EXPORT_SYMBOL(security_path_mkdir);
307
308 int security_path_rmdir(struct path *dir, struct dentry *dentry)
309 {
310@@ -383,6 +384,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
311 return 0;
312 return security_ops->path_rmdir(dir, dentry);
313 }
314+EXPORT_SYMBOL(security_path_rmdir);
315
316 int security_path_unlink(struct path *dir, struct dentry *dentry)
317 {
318@@ -390,6 +392,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
319 return 0;
320 return security_ops->path_unlink(dir, dentry);
321 }
322+EXPORT_SYMBOL(security_path_unlink);
323
324 int security_path_symlink(struct path *dir, struct dentry *dentry,
325 const char *old_name)
326@@ -398,6 +401,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
327 return 0;
328 return security_ops->path_symlink(dir, dentry, old_name);
329 }
330+EXPORT_SYMBOL(security_path_symlink);
331
332 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
333 struct dentry *new_dentry)
334@@ -406,6 +410,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
335 return 0;
336 return security_ops->path_link(old_dentry, new_dir, new_dentry);
337 }
338+EXPORT_SYMBOL(security_path_link);
339
340 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
341 struct path *new_dir, struct dentry *new_dentry)
342@@ -416,6 +421,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
343 return security_ops->path_rename(old_dir, old_dentry, new_dir,
344 new_dentry);
345 }
346+EXPORT_SYMBOL(security_path_rename);
347
348 int security_path_truncate(struct path *path)
349 {
350@@ -423,6 +429,7 @@ int security_path_truncate(struct path *path)
351 return 0;
352 return security_ops->path_truncate(path);
353 }
354+EXPORT_SYMBOL(security_path_truncate);
355
356 int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
357 mode_t mode)
358@@ -431,6 +438,7 @@ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
359 return 0;
360 return security_ops->path_chmod(dentry, mnt, mode);
361 }
362+EXPORT_SYMBOL(security_path_chmod);
363
364 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
365 {
366@@ -438,6 +446,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
367 return 0;
368 return security_ops->path_chown(path, uid, gid);
369 }
370+EXPORT_SYMBOL(security_path_chown);
371
372 int security_path_chroot(struct path *path)
373 {
374@@ -514,6 +523,7 @@ int security_inode_readlink(struct dentry *dentry)
375 return 0;
376 return security_ops->inode_readlink(dentry);
377 }
378+EXPORT_SYMBOL(security_inode_readlink);
379
380 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
381 {
382@@ -528,6 +538,7 @@ int security_inode_permission(struct inode *inode, int mask)
383 return 0;
384 return security_ops->inode_permission(inode, mask);
385 }
386+EXPORT_SYMBOL(security_inode_permission);
387
388 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
389 {
390@@ -627,6 +638,7 @@ int security_file_permission(struct file *file, int mask)
391
392 return fsnotify_perm(file, mask);
393 }
394+EXPORT_SYMBOL(security_file_permission);
395
396 int security_file_alloc(struct file *file)
397 {
398@@ -654,6 +666,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
399 return ret;
400 return ima_file_mmap(file, prot);
401 }
402+EXPORT_SYMBOL(security_file_mmap);
403
404 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
405 unsigned long prot)
406diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
407--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
408+++ linux/Documentation/ABI/testing/debugfs-aufs 2010-11-22 11:52:56.970558852 +0100
409@@ -0,0 +1,37 @@
410+What: /debug/aufs/si_<id>/
411+Date: March 2009
412+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
413+Description:
414+ Under /debug/aufs, a directory named si_<id> is created
415+ per aufs mount, where <id> is a unique id generated
416+ internally.
1facf9fc 417+
7f207e10
AM
418+What: /debug/aufs/si_<id>/xib
419+Date: March 2009
420+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
421+Description:
422+ It shows the consumed blocks by xib (External Inode Number
423+ Bitmap), its block size and file size.
424+ When the aufs mount option 'noxino' is specified, it
425+ will be empty. About XINO files, see the aufs manual.
426+
427+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
428+Date: March 2009
429+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
430+Description:
431+ It shows the consumed blocks by xino (External Inode Number
432+ Translation Table), its link count, block size and file
433+ size.
434+ When the aufs mount option 'noxino' is specified, it
435+ will be empty. About XINO files, see the aufs manual.
436+
437+What: /debug/aufs/si_<id>/xigen
438+Date: March 2009
439+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
440+Description:
441+ It shows the consumed blocks by xigen (External Inode
442+ Generation Table), its block size and file size.
443+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
444+ be created.
445+ When the aufs mount option 'noxino' is specified, it
446+ will be empty. About XINO files, see the aufs manual.
447diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
448--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
449+++ linux/Documentation/ABI/testing/sysfs-aufs 2010-11-22 11:52:56.970558852 +0100
450@@ -0,0 +1,24 @@
451+What: /sys/fs/aufs/si_<id>/
452+Date: March 2009
453+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
454+Description:
455+ Under /sys/fs/aufs, a directory named si_<id> is created
456+ per aufs mount, where <id> is a unique id generated
457+ internally.
458+
459+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
460+Date: March 2009
461+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
462+Description:
463+ It shows the abolute path of a member directory (which
464+ is called branch) in aufs, and its permission.
465+
466+What: /sys/fs/aufs/si_<id>/xi_path
467+Date: March 2009
468+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
469+Description:
470+ It shows the abolute path of XINO (External Inode Number
471+ Bitmap, Translation Table and Generation Table) file
472+ even if it is the default path.
473+ When the aufs mount option 'noxino' is specified, it
474+ will be empty. About XINO files, see the aufs manual.
475diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
476--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
477+++ linux/fs/aufs/aufs.h 2010-11-22 11:52:56.983894369 +0100
478@@ -0,0 +1,61 @@
479+/*
480+ * Copyright (C) 2005-2010 Junjiro R. Okajima
481+ *
482+ * This program, aufs is free software; you can redistribute it and/or modify
483+ * it under the terms of the GNU General Public License as published by
484+ * the Free Software Foundation; either version 2 of the License, or
485+ * (at your option) any later version.
486+ *
487+ * This program is distributed in the hope that it will be useful,
488+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
489+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
490+ * GNU General Public License for more details.
491+ *
492+ * You should have received a copy of the GNU General Public License
493+ * along with this program; if not, write to the Free Software
494+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
495+ */
496+
497+/*
498+ * all header files
499+ */
500+
501+#ifndef __AUFS_H__
502+#define __AUFS_H__
503+
504+#ifdef __KERNEL__
505+
506+#define AuStub(type, name, body, ...) \
507+ static inline type name(__VA_ARGS__) { body; }
508+
509+#define AuStubVoid(name, ...) \
510+ AuStub(void, name, , __VA_ARGS__)
511+#define AuStubInt0(name, ...) \
512+ AuStub(int, name, return 0, __VA_ARGS__)
513+
514+#include "debug.h"
515+
516+#include "branch.h"
517+#include "cpup.h"
518+#include "dcsub.h"
519+#include "dbgaufs.h"
520+#include "dentry.h"
521+#include "dir.h"
522+#include "dynop.h"
523+#include "file.h"
524+#include "fstype.h"
525+#include "inode.h"
526+#include "loop.h"
527+#include "module.h"
528+/* never include ./mtx.h */
529+#include "opts.h"
530+#include "rwsem.h"
531+#include "spl.h"
532+#include "super.h"
533+#include "sysaufs.h"
534+#include "vfsub.h"
535+#include "whout.h"
536+#include "wkq.h"
537+
538+#endif /* __KERNEL__ */
539+#endif /* __AUFS_H__ */
540diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
541--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
542+++ linux/fs/aufs/branch.c 2010-11-22 11:52:56.983894369 +0100
543@@ -0,0 +1,1051 @@
544+/*
545+ * Copyright (C) 2005-2010 Junjiro R. Okajima
546+ *
547+ * This program, aufs is free software; you can redistribute it and/or modify
548+ * it under the terms of the GNU General Public License as published by
549+ * the Free Software Foundation; either version 2 of the License, or
550+ * (at your option) any later version.
551+ *
552+ * This program is distributed in the hope that it will be useful,
553+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
554+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
555+ * GNU General Public License for more details.
556+ *
557+ * You should have received a copy of the GNU General Public License
558+ * along with this program; if not, write to the Free Software
559+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
560+ */
561+
562+/*
563+ * branch management
564+ */
565+
566+#include <linux/file.h>
567+#include <linux/statfs.h>
568+#include "aufs.h"
569+
570+/*
571+ * free a single branch
1facf9fc 572+ */
573+static void au_br_do_free(struct au_branch *br)
574+{
575+ int i;
576+ struct au_wbr *wbr;
4a4d8108 577+ struct au_dykey **key;
1facf9fc 578+
579+ if (br->br_xino.xi_file)
580+ fput(br->br_xino.xi_file);
581+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
582+
583+ AuDebugOn(atomic_read(&br->br_count));
584+
585+ wbr = br->br_wbr;
586+ if (wbr) {
587+ for (i = 0; i < AuBrWh_Last; i++)
588+ dput(wbr->wbr_wh[i]);
589+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 590+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 591+ }
592+
4a4d8108
AM
593+ key = br->br_dykey;
594+ for (i = 0; i < AuBrDynOp; i++, key++)
595+ if (*key)
596+ au_dy_put(*key);
597+ else
598+ break;
599+
1facf9fc 600+ mntput(br->br_mnt);
1facf9fc 601+ kfree(wbr);
602+ kfree(br);
603+}
604+
605+/*
606+ * frees all branches
607+ */
608+void au_br_free(struct au_sbinfo *sbinfo)
609+{
610+ aufs_bindex_t bmax;
611+ struct au_branch **br;
612+
dece6358
AM
613+ AuRwMustWriteLock(&sbinfo->si_rwsem);
614+
1facf9fc 615+ bmax = sbinfo->si_bend + 1;
616+ br = sbinfo->si_branch;
617+ while (bmax--)
618+ au_br_do_free(*br++);
619+}
620+
621+/*
622+ * find the index of a branch which is specified by @br_id.
623+ */
624+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
625+{
626+ aufs_bindex_t bindex, bend;
627+
628+ bend = au_sbend(sb);
629+ for (bindex = 0; bindex <= bend; bindex++)
630+ if (au_sbr_id(sb, bindex) == br_id)
631+ return bindex;
632+ return -1;
633+}
634+
635+/* ---------------------------------------------------------------------- */
636+
637+/*
638+ * add a branch
639+ */
640+
b752ccd1
AM
641+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
642+ struct dentry *h_root)
1facf9fc 643+{
b752ccd1
AM
644+ if (unlikely(h_adding == h_root
645+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 646+ return 1;
b752ccd1
AM
647+ if (h_adding->d_sb != h_root->d_sb)
648+ return 0;
649+ return au_test_subdir(h_adding, h_root)
650+ || au_test_subdir(h_root, h_adding);
1facf9fc 651+}
652+
653+/*
654+ * returns a newly allocated branch. @new_nbranch is a number of branches
655+ * after adding a branch.
656+ */
657+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
658+ int perm)
659+{
660+ struct au_branch *add_branch;
661+ struct dentry *root;
4a4d8108 662+ int err;
1facf9fc 663+
4a4d8108 664+ err = -ENOMEM;
1facf9fc 665+ root = sb->s_root;
666+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
667+ if (unlikely(!add_branch))
668+ goto out;
669+
670+ add_branch->br_wbr = NULL;
671+ if (au_br_writable(perm)) {
672+ /* may be freed separately at changing the branch permission */
673+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
674+ GFP_NOFS);
675+ if (unlikely(!add_branch->br_wbr))
676+ goto out_br;
677+ }
678+
4a4d8108
AM
679+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
680+ if (!err)
681+ err = au_di_realloc(au_di(root), new_nbranch);
682+ if (!err)
683+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
684+ if (!err)
685+ return add_branch; /* success */
1facf9fc 686+
1facf9fc 687+ kfree(add_branch->br_wbr);
4a4d8108 688+
4f0767ce 689+out_br:
1facf9fc 690+ kfree(add_branch);
4f0767ce 691+out:
4a4d8108 692+ return ERR_PTR(err);
1facf9fc 693+}
694+
695+/*
696+ * test if the branch permission is legal or not.
697+ */
698+static int test_br(struct inode *inode, int brperm, char *path)
699+{
700+ int err;
701+
4a4d8108
AM
702+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
703+ if (!err)
704+ goto out;
1facf9fc 705+
4a4d8108
AM
706+ err = -EINVAL;
707+ pr_err("write permission for readonly mount or inode, %s\n", path);
708+
4f0767ce 709+out:
1facf9fc 710+ return err;
711+}
712+
713+/*
714+ * returns:
715+ * 0: success, the caller will add it
716+ * plus: success, it is already unified, the caller should ignore it
717+ * minus: error
718+ */
719+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
720+{
721+ int err;
722+ aufs_bindex_t bend, bindex;
723+ struct dentry *root;
724+ struct inode *inode, *h_inode;
725+
726+ root = sb->s_root;
727+ bend = au_sbend(sb);
728+ if (unlikely(bend >= 0
729+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
730+ err = 1;
731+ if (!remount) {
732+ err = -EINVAL;
4a4d8108 733+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 734+ }
735+ goto out;
736+ }
737+
738+ err = -ENOSPC; /* -E2BIG; */
739+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
740+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 741+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 742+ goto out;
743+ }
744+
745+ err = -EDOM;
746+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 747+ pr_err("bad index %d\n", add->bindex);
1facf9fc 748+ goto out;
749+ }
750+
751+ inode = add->path.dentry->d_inode;
752+ err = -ENOENT;
753+ if (unlikely(!inode->i_nlink)) {
4a4d8108 754+ pr_err("no existence %s\n", add->pathname);
1facf9fc 755+ goto out;
756+ }
757+
758+ err = -EINVAL;
759+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 760+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 761+ goto out;
762+ }
763+
764+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
765+ pr_err("unsupported filesystem, %s (%s)\n",
766+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 767+ goto out;
768+ }
769+
770+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
771+ if (unlikely(err))
772+ goto out;
773+
774+ if (bend < 0)
775+ return 0; /* success */
776+
777+ err = -EINVAL;
778+ for (bindex = 0; bindex <= bend; bindex++)
779+ if (unlikely(test_overlap(sb, add->path.dentry,
780+ au_h_dptr(root, bindex)))) {
4a4d8108 781+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 782+ goto out;
783+ }
784+
785+ err = 0;
786+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
787+ h_inode = au_h_dptr(root, 0)->d_inode;
788+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
789+ || h_inode->i_uid != inode->i_uid
790+ || h_inode->i_gid != inode->i_gid)
4a4d8108
AM
791+ pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
792+ add->pathname,
793+ inode->i_uid, inode->i_gid,
794+ (inode->i_mode & S_IALLUGO),
795+ h_inode->i_uid, h_inode->i_gid,
796+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 797+ }
798+
4f0767ce 799+out:
1facf9fc 800+ return err;
801+}
802+
803+/*
804+ * initialize or clean the whiteouts for an adding branch
805+ */
806+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
807+ int new_perm, struct dentry *h_root)
808+{
809+ int err, old_perm;
810+ aufs_bindex_t bindex;
811+ struct mutex *h_mtx;
812+ struct au_wbr *wbr;
813+ struct au_hinode *hdir;
814+
815+ wbr = br->br_wbr;
816+ old_perm = br->br_perm;
817+ br->br_perm = new_perm;
818+ hdir = NULL;
819+ h_mtx = NULL;
820+ bindex = au_br_index(sb, br->br_id);
821+ if (0 <= bindex) {
822+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 823+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 824+ } else {
825+ h_mtx = &h_root->d_inode->i_mutex;
826+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
827+ }
828+ if (!wbr)
829+ err = au_wh_init(h_root, br, sb);
830+ else {
831+ wbr_wh_write_lock(wbr);
832+ err = au_wh_init(h_root, br, sb);
833+ wbr_wh_write_unlock(wbr);
834+ }
835+ if (hdir)
4a4d8108 836+ au_hn_imtx_unlock(hdir);
1facf9fc 837+ else
838+ mutex_unlock(h_mtx);
839+ br->br_perm = old_perm;
840+
841+ if (!err && wbr && !au_br_writable(new_perm)) {
842+ kfree(wbr);
843+ br->br_wbr = NULL;
844+ }
845+
846+ return err;
847+}
848+
849+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
850+ int perm, struct path *path)
851+{
852+ int err;
4a4d8108 853+ struct kstatfs kst;
1facf9fc 854+ struct au_wbr *wbr;
4a4d8108 855+ struct dentry *h_dentry;
1facf9fc 856+
857+ wbr = br->br_wbr;
dece6358 858+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 859+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
860+ atomic_set(&wbr->wbr_wh_running, 0);
861+ wbr->wbr_bytes = 0;
862+
4a4d8108
AM
863+ /*
864+ * a limit for rmdir/rename a dir
865+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
866+ */
7f207e10 867+ err = vfs_statfs(path, &kst);
4a4d8108
AM
868+ if (unlikely(err))
869+ goto out;
870+ err = -EINVAL;
7f207e10 871+ h_dentry = path->dentry;
4a4d8108
AM
872+ if (kst.f_namelen >= NAME_MAX)
873+ err = au_br_init_wh(sb, br, perm, h_dentry);
874+ else
875+ pr_err("%.*s(%s), unsupported namelen %ld\n",
876+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
877+ kst.f_namelen);
1facf9fc 878+
4f0767ce 879+out:
1facf9fc 880+ return err;
881+}
882+
883+/* intialize a new branch */
884+static int au_br_init(struct au_branch *br, struct super_block *sb,
885+ struct au_opt_add *add)
886+{
887+ int err;
888+
889+ err = 0;
890+ memset(&br->br_xino, 0, sizeof(br->br_xino));
891+ mutex_init(&br->br_xino.xi_nondir_mtx);
892+ br->br_perm = add->perm;
893+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
894+ spin_lock_init(&br->br_dykey_lock);
895+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 896+ atomic_set(&br->br_count, 0);
897+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
898+ atomic_set(&br->br_xino_running, 0);
899+ br->br_id = au_new_br_id(sb);
7f207e10 900+ AuDebugOn(br->br_id < 0);
1facf9fc 901+
902+ if (au_br_writable(add->perm)) {
903+ err = au_wbr_init(br, sb, add->perm, &add->path);
904+ if (unlikely(err))
b752ccd1 905+ goto out_err;
1facf9fc 906+ }
907+
908+ if (au_opt_test(au_mntflags(sb), XINO)) {
909+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
910+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
911+ if (unlikely(err)) {
912+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 913+ goto out_err;
1facf9fc 914+ }
915+ }
916+
917+ sysaufs_br_init(br);
918+ mntget(add->path.mnt);
b752ccd1 919+ goto out; /* success */
1facf9fc 920+
4f0767ce 921+out_err:
b752ccd1 922+ br->br_mnt = NULL;
4f0767ce 923+out:
1facf9fc 924+ return err;
925+}
926+
927+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
928+ struct au_branch *br, aufs_bindex_t bend,
929+ aufs_bindex_t amount)
930+{
931+ struct au_branch **brp;
932+
dece6358
AM
933+ AuRwMustWriteLock(&sbinfo->si_rwsem);
934+
1facf9fc 935+ brp = sbinfo->si_branch + bindex;
936+ memmove(brp + 1, brp, sizeof(*brp) * amount);
937+ *brp = br;
938+ sbinfo->si_bend++;
939+ if (unlikely(bend < 0))
940+ sbinfo->si_bend = 0;
941+}
942+
943+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
944+ aufs_bindex_t bend, aufs_bindex_t amount)
945+{
946+ struct au_hdentry *hdp;
947+
1308ab2a 948+ AuRwMustWriteLock(&dinfo->di_rwsem);
949+
1facf9fc 950+ hdp = dinfo->di_hdentry + bindex;
951+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
952+ au_h_dentry_init(hdp);
953+ dinfo->di_bend++;
954+ if (unlikely(bend < 0))
955+ dinfo->di_bstart = 0;
956+}
957+
958+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
959+ aufs_bindex_t bend, aufs_bindex_t amount)
960+{
961+ struct au_hinode *hip;
962+
1308ab2a 963+ AuRwMustWriteLock(&iinfo->ii_rwsem);
964+
1facf9fc 965+ hip = iinfo->ii_hinode + bindex;
966+ memmove(hip + 1, hip, sizeof(*hip) * amount);
967+ hip->hi_inode = NULL;
4a4d8108 968+ au_hn_init(hip);
1facf9fc 969+ iinfo->ii_bend++;
970+ if (unlikely(bend < 0))
971+ iinfo->ii_bstart = 0;
972+}
973+
974+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
975+ struct au_branch *br, aufs_bindex_t bindex)
976+{
977+ struct dentry *root;
978+ struct inode *root_inode;
979+ aufs_bindex_t bend, amount;
980+
981+ root = sb->s_root;
982+ root_inode = root->d_inode;
1facf9fc 983+ bend = au_sbend(sb);
984+ amount = bend + 1 - bindex;
985+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
986+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
987+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
988+ au_set_h_dptr(root, bindex, dget(h_dentry));
989+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
990+ /*flags*/0);
991+}
992+
993+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
994+{
995+ int err;
1facf9fc 996+ aufs_bindex_t bend, add_bindex;
997+ struct dentry *root, *h_dentry;
998+ struct inode *root_inode;
999+ struct au_branch *add_branch;
1000+
1001+ root = sb->s_root;
1002+ root_inode = root->d_inode;
1003+ IMustLock(root_inode);
1004+ err = test_add(sb, add, remount);
1005+ if (unlikely(err < 0))
1006+ goto out;
1007+ if (err) {
1008+ err = 0;
1009+ goto out; /* success */
1010+ }
1011+
1012+ bend = au_sbend(sb);
1013+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
1014+ err = PTR_ERR(add_branch);
1015+ if (IS_ERR(add_branch))
1016+ goto out;
1017+
1018+ err = au_br_init(add_branch, sb, add);
1019+ if (unlikely(err)) {
1020+ au_br_do_free(add_branch);
1021+ goto out;
1022+ }
1023+
1024+ add_bindex = add->bindex;
1025+ h_dentry = add->path.dentry;
1026+ if (!remount)
1027+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1028+ else {
1029+ sysaufs_brs_del(sb, add_bindex);
1030+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1031+ sysaufs_brs_add(sb, add_bindex);
1032+ }
1033+
1308ab2a 1034+ if (!add_bindex) {
1facf9fc 1035+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 1036+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
1037+ } else
1facf9fc 1038+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 1039+
1040+ /*
4a4d8108 1041+ * this test/set prevents aufs from handling unnecesary notify events
1facf9fc 1042+ * of xino files, in a case of re-adding a writable branch which was
1043+ * once detached from aufs.
1044+ */
1045+ if (au_xino_brid(sb) < 0
1046+ && au_br_writable(add_branch->br_perm)
1047+ && !au_test_fs_bad_xino(h_dentry->d_sb)
1048+ && add_branch->br_xino.xi_file
1049+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
1050+ au_xino_brid_set(sb, add_branch->br_id);
1051+
4f0767ce 1052+out:
1facf9fc 1053+ return err;
1054+}
1055+
1056+/* ---------------------------------------------------------------------- */
1057+
1058+/*
1059+ * delete a branch
1060+ */
1061+
1062+/* to show the line number, do not make it inlined function */
4a4d8108 1063+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 1064+ if (do_info) \
4a4d8108 1065+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 1066+} while (0)
1067+
1068+/*
1069+ * test if the branch is deletable or not.
1070+ */
1071+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 1072+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1073+{
1074+ int err, i, j, ndentry;
1075+ aufs_bindex_t bstart, bend;
1facf9fc 1076+ struct au_dcsub_pages dpages;
1077+ struct au_dpage *dpage;
1078+ struct dentry *d;
1079+ struct inode *inode;
1080+
1081+ err = au_dpages_init(&dpages, GFP_NOFS);
1082+ if (unlikely(err))
1083+ goto out;
1084+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
1085+ if (unlikely(err))
1086+ goto out_dpages;
1087+
1facf9fc 1088+ for (i = 0; !err && i < dpages.ndpage; i++) {
1089+ dpage = dpages.dpages + i;
1090+ ndentry = dpage->ndentry;
1091+ for (j = 0; !err && j < ndentry; j++) {
1092+ d = dpage->dentries[j];
1093+ AuDebugOn(!atomic_read(&d->d_count));
1094+ inode = d->d_inode;
1095+ if (au_digen(d) == sigen && au_iigen(inode) == sigen)
1096+ di_read_lock_child(d, AuLock_IR);
1097+ else {
1098+ di_write_lock_child(d);
1099+ err = au_reval_dpath(d, sigen);
1100+ if (!err)
1101+ di_downgrade_lock(d, AuLock_IR);
1102+ else {
1103+ di_write_unlock(d);
1104+ break;
1105+ }
1106+ }
1107+
1108+ bstart = au_dbstart(d);
1109+ bend = au_dbend(d);
1110+ if (bstart <= bindex
1111+ && bindex <= bend
1112+ && au_h_dptr(d, bindex)
1113+ && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
1114+ err = -EBUSY;
1115+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
1116+ }
1117+ di_read_unlock(d, AuLock_IR);
1118+ }
1119+ }
1120+
4f0767ce 1121+out_dpages:
1facf9fc 1122+ au_dpages_free(&dpages);
4f0767ce 1123+out:
1facf9fc 1124+ return err;
1125+}
1126+
1127+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 1128+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1129+{
1130+ int err;
7f207e10
AM
1131+ unsigned long long max, ull;
1132+ struct inode *i, **array;
1facf9fc 1133+ aufs_bindex_t bstart, bend;
1facf9fc 1134+
7f207e10
AM
1135+ array = au_iarray_alloc(sb, &max);
1136+ err = PTR_ERR(array);
1137+ if (IS_ERR(array))
1138+ goto out;
1139+
1facf9fc 1140+ err = 0;
7f207e10
AM
1141+ AuDbg("b%d\n", bindex);
1142+ for (ull = 0; !err && ull < max; ull++) {
1143+ i = array[ull];
1144+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 1145+ continue;
1146+
7f207e10 1147+ /* AuDbgInode(i); */
1facf9fc 1148+ if (au_iigen(i) == sigen)
1149+ ii_read_lock_child(i);
1150+ else {
1151+ ii_write_lock_child(i);
1152+ err = au_refresh_hinode_self(i, /*do_attr*/1);
1153+ if (!err)
1154+ ii_downgrade_lock(i);
1155+ else {
1156+ ii_write_unlock(i);
1157+ break;
1158+ }
1159+ }
1160+
1161+ bstart = au_ibstart(i);
1162+ bend = au_ibend(i);
1163+ if (bstart <= bindex
1164+ && bindex <= bend
1165+ && au_h_iptr(i, bindex)
1166+ && (!S_ISDIR(i->i_mode) || bstart == bend)) {
1167+ err = -EBUSY;
1168+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 1169+ AuDbgInode(i);
1facf9fc 1170+ }
1171+ ii_read_unlock(i);
1172+ }
7f207e10 1173+ au_iarray_free(array, max);
1facf9fc 1174+
7f207e10 1175+out:
1facf9fc 1176+ return err;
1177+}
1178+
b752ccd1
AM
1179+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
1180+ const unsigned int verbose)
1facf9fc 1181+{
1182+ int err;
1183+ unsigned int sigen;
1184+
1185+ sigen = au_sigen(root->d_sb);
1186+ DiMustNoWaiters(root);
1187+ IiMustNoWaiters(root->d_inode);
1188+ di_write_unlock(root);
b752ccd1 1189+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 1190+ if (!err)
b752ccd1 1191+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 1192+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
1193+
1194+ return err;
1195+}
1196+
1197+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
1198+ const aufs_bindex_t bindex,
1199+ const aufs_bindex_t bend)
1200+{
1201+ struct au_branch **brp, **p;
1202+
dece6358
AM
1203+ AuRwMustWriteLock(&sbinfo->si_rwsem);
1204+
1facf9fc 1205+ brp = sbinfo->si_branch + bindex;
1206+ if (bindex < bend)
1207+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
1208+ sbinfo->si_branch[0 + bend] = NULL;
1209+ sbinfo->si_bend--;
1210+
1211+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
1212+ if (p)
1213+ sbinfo->si_branch = p;
4a4d8108 1214+ /* harmless error */
1facf9fc 1215+}
1216+
1217+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
1218+ const aufs_bindex_t bend)
1219+{
1220+ struct au_hdentry *hdp, *p;
1221+
1308ab2a 1222+ AuRwMustWriteLock(&dinfo->di_rwsem);
1223+
4a4d8108 1224+ hdp = dinfo->di_hdentry;
1facf9fc 1225+ if (bindex < bend)
4a4d8108
AM
1226+ memmove(hdp + bindex, hdp + bindex + 1,
1227+ sizeof(*hdp) * (bend - bindex));
1228+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 1229+ dinfo->di_bend--;
1230+
4a4d8108 1231+ p = krealloc(hdp, sizeof(*p) * bend, GFP_NOFS);
1facf9fc 1232+ if (p)
1233+ dinfo->di_hdentry = p;
4a4d8108 1234+ /* harmless error */
1facf9fc 1235+}
1236+
1237+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
1238+ const aufs_bindex_t bend)
1239+{
1240+ struct au_hinode *hip, *p;
1241+
1308ab2a 1242+ AuRwMustWriteLock(&iinfo->ii_rwsem);
1243+
1facf9fc 1244+ hip = iinfo->ii_hinode + bindex;
1245+ if (bindex < bend)
1246+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
1247+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 1248+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 1249+ iinfo->ii_bend--;
1250+
1251+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
1252+ if (p)
1253+ iinfo->ii_hinode = p;
4a4d8108 1254+ /* harmless error */
1facf9fc 1255+}
1256+
1257+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
1258+ struct au_branch *br)
1259+{
1260+ aufs_bindex_t bend;
1261+ struct au_sbinfo *sbinfo;
1262+ struct dentry *root;
1263+ struct inode *inode;
1264+
dece6358
AM
1265+ SiMustWriteLock(sb);
1266+
1facf9fc 1267+ root = sb->s_root;
1268+ inode = root->d_inode;
1facf9fc 1269+ sbinfo = au_sbi(sb);
1270+ bend = sbinfo->si_bend;
1271+
1272+ dput(au_h_dptr(root, bindex));
1273+ au_hiput(au_hi(inode, bindex));
1274+ au_br_do_free(br);
1275+
1276+ au_br_do_del_brp(sbinfo, bindex, bend);
1277+ au_br_do_del_hdp(au_di(root), bindex, bend);
1278+ au_br_do_del_hip(au_ii(inode), bindex, bend);
1279+}
1280+
1281+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
1282+{
1283+ int err, rerr, i;
1284+ unsigned int mnt_flags;
1285+ aufs_bindex_t bindex, bend, br_id;
1286+ unsigned char do_wh, verbose;
1287+ struct au_branch *br;
1288+ struct au_wbr *wbr;
1289+
1290+ err = 0;
1291+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
1292+ if (bindex < 0) {
1293+ if (remount)
1294+ goto out; /* success */
1295+ err = -ENOENT;
4a4d8108 1296+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 1297+ goto out;
1298+ }
1299+ AuDbg("bindex b%d\n", bindex);
1300+
1301+ err = -EBUSY;
1302+ mnt_flags = au_mntflags(sb);
1303+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
1304+ bend = au_sbend(sb);
1305+ if (unlikely(!bend)) {
1306+ AuVerbose(verbose, "no more branches left\n");
1307+ goto out;
1308+ }
1309+ br = au_sbr(sb, bindex);
1310+ i = atomic_read(&br->br_count);
1311+ if (unlikely(i)) {
1312+ AuVerbose(verbose, "%d file(s) opened\n", i);
e49829fe 1313+ goto out;
1facf9fc 1314+ }
1315+
1316+ wbr = br->br_wbr;
1317+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
1318+ if (do_wh) {
1308ab2a 1319+ /* instead of WbrWhMustWriteLock(wbr) */
1320+ SiMustWriteLock(sb);
1facf9fc 1321+ for (i = 0; i < AuBrWh_Last; i++) {
1322+ dput(wbr->wbr_wh[i]);
1323+ wbr->wbr_wh[i] = NULL;
1324+ }
1325+ }
1326+
b752ccd1 1327+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 1328+ if (unlikely(err)) {
1329+ if (do_wh)
1330+ goto out_wh;
1331+ goto out;
1332+ }
1333+
1334+ err = 0;
1335+ br_id = br->br_id;
1336+ if (!remount)
1337+ au_br_do_del(sb, bindex, br);
1338+ else {
1339+ sysaufs_brs_del(sb, bindex);
1340+ au_br_do_del(sb, bindex, br);
1341+ sysaufs_brs_add(sb, bindex);
1342+ }
1343+
1308ab2a 1344+ if (!bindex) {
1facf9fc 1345+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 1346+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
1347+ } else
1facf9fc 1348+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
1349+ if (au_opt_test(mnt_flags, PLINK))
1350+ au_plink_half_refresh(sb, br_id);
1351+
b752ccd1 1352+ if (au_xino_brid(sb) == br_id)
1facf9fc 1353+ au_xino_brid_set(sb, -1);
1354+ goto out; /* success */
1355+
4f0767ce 1356+out_wh:
1facf9fc 1357+ /* revert */
1358+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
1359+ if (rerr)
4a4d8108
AM
1360+ pr_warning("failed re-creating base whiteout, %s. (%d)\n",
1361+ del->pathname, rerr);
4f0767ce 1362+out:
1facf9fc 1363+ return err;
1364+}
1365+
1366+/* ---------------------------------------------------------------------- */
1367+
1368+/*
1369+ * change a branch permission
1370+ */
1371+
dece6358
AM
1372+static void au_warn_ima(void)
1373+{
1374+#ifdef CONFIG_IMA
1308ab2a 1375+ /* since it doesn't support mark_files_ro() */
e49829fe 1376+ AuWarn1("RW -> RO makes IMA to produce wrong message");
dece6358
AM
1377+#endif
1378+}
1379+
1facf9fc 1380+static int do_need_sigen_inc(int a, int b)
1381+{
1382+ return au_br_whable(a) && !au_br_whable(b);
1383+}
1384+
1385+static int need_sigen_inc(int old, int new)
1386+{
1387+ return do_need_sigen_inc(old, new)
1388+ || do_need_sigen_inc(new, old);
1389+}
1390+
7f207e10
AM
1391+static unsigned long long au_farray_cb(void *a,
1392+ unsigned long long max __maybe_unused,
1393+ void *arg)
1394+{
1395+ unsigned long long n;
1396+ struct file **p, *f;
1397+ struct super_block *sb = arg;
1398+
1399+ n = 0;
1400+ p = a;
1401+ lg_global_lock(files_lglock);
1402+ do_file_list_for_each_entry(sb, f) {
1403+ if (au_fi(f)
1404+ && !special_file(f->f_dentry->d_inode->i_mode)) {
1405+ get_file(f);
1406+ *p++ = f;
1407+ n++;
1408+ AuDebugOn(n > max);
1409+ }
1410+ } while_file_list_for_each_entry;
1411+ lg_global_unlock(files_lglock);
1412+
1413+ return n;
1414+}
1415+
1416+static struct file **au_farray_alloc(struct super_block *sb,
1417+ unsigned long long *max)
1418+{
1419+ *max = atomic_long_read(&au_sbi(sb)->si_nfiles);
1420+ return au_array_alloc(max, au_farray_cb, sb);
1421+}
1422+
1423+static void au_farray_free(struct file **a, unsigned long long max)
1424+{
1425+ unsigned long long ull;
1426+
1427+ for (ull = 0; ull < max; ull++)
1428+ if (a[ull])
1429+ fput(a[ull]);
1430+ au_array_free(a);
1431+}
1432+
1facf9fc 1433+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
1434+{
7f207e10
AM
1435+ int err, do_warn;
1436+ unsigned long long ull, max;
e49829fe 1437+ aufs_bindex_t br_id;
7f207e10 1438+ struct file *file, *hf, **array;
e49829fe
JR
1439+ struct dentry *dentry;
1440+ struct inode *inode;
1441+ struct au_hfile *hfile;
1facf9fc 1442+
7f207e10
AM
1443+ array = au_farray_alloc(sb, &max);
1444+ err = PTR_ERR(array);
1445+ if (IS_ERR(array))
1facf9fc 1446+ goto out;
1447+
7f207e10 1448+ do_warn = 0;
e49829fe 1449+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
1450+ for (ull = 0; ull < max; ull++) {
1451+ file = array[ull];
e49829fe
JR
1452+ dentry = file->f_dentry;
1453+ inode = dentry->d_inode;
1facf9fc 1454+
7f207e10 1455+ /* AuDbg("%.*s\n", AuDLNPair(file->f_dentry)); */
1facf9fc 1456+ fi_read_lock(file);
1457+ if (unlikely(au_test_mmapped(file))) {
1458+ err = -EBUSY;
7f207e10 1459+ AuDbgFile(file);
1facf9fc 1460+ FiMustNoWaiters(file);
1461+ fi_read_unlock(file);
7f207e10 1462+ goto out_array;
1facf9fc 1463+ }
1464+
e49829fe
JR
1465+ hfile = &au_fi(file)->fi_htop;
1466+ hf = hfile->hf_file;
1467+ if (!S_ISREG(inode->i_mode)
1facf9fc 1468+ || !(file->f_mode & FMODE_WRITE)
e49829fe 1469+ || hfile->hf_br->br_id != br_id
7f207e10
AM
1470+ || !(hf->f_mode & FMODE_WRITE))
1471+ array[ull] = NULL;
1472+ else {
1473+ do_warn = 1;
1474+ get_file(file);
1facf9fc 1475+ }
1476+
1facf9fc 1477+ FiMustNoWaiters(file);
1478+ fi_read_unlock(file);
7f207e10
AM
1479+ fput(file);
1480+ }
1facf9fc 1481+
1482+ err = 0;
7f207e10 1483+ if (do_warn)
dece6358 1484+ au_warn_ima();
7f207e10
AM
1485+
1486+ for (ull = 0; ull < max; ull++) {
1487+ file = array[ull];
1488+ if (!file)
1489+ continue;
1490+
1facf9fc 1491+ /* todo: already flushed? */
1492+ /* cf. fs/super.c:mark_files_ro() */
7f207e10
AM
1493+ /* fi_read_lock(file); */
1494+ hfile = &au_fi(file)->fi_htop;
1495+ hf = hfile->hf_file;
1496+ /* fi_read_unlock(file); */
1facf9fc 1497+ hf->f_mode &= ~FMODE_WRITE;
1498+ if (!file_check_writeable(hf)) {
1499+ file_release_write(hf);
1500+ mnt_drop_write(hf->f_vfsmnt);
1501+ }
1502+ }
1503+
7f207e10
AM
1504+out_array:
1505+ au_farray_free(array, max);
4f0767ce 1506+out:
7f207e10 1507+ AuTraceErr(err);
1facf9fc 1508+ return err;
1509+}
1510+
1511+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 1512+ int *do_refresh)
1facf9fc 1513+{
1514+ int err, rerr;
1515+ aufs_bindex_t bindex;
1308ab2a 1516+ struct path path;
1facf9fc 1517+ struct dentry *root;
1518+ struct au_branch *br;
1519+
1520+ root = sb->s_root;
1facf9fc 1521+ bindex = au_find_dbindex(root, mod->h_root);
1522+ if (bindex < 0) {
1523+ if (remount)
1524+ return 0; /* success */
1525+ err = -ENOENT;
4a4d8108 1526+ pr_err("%s no such branch\n", mod->path);
1facf9fc 1527+ goto out;
1528+ }
1529+ AuDbg("bindex b%d\n", bindex);
1530+
1531+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
1532+ if (unlikely(err))
1533+ goto out;
1534+
1535+ br = au_sbr(sb, bindex);
1536+ if (br->br_perm == mod->perm)
1537+ return 0; /* success */
1538+
1539+ if (au_br_writable(br->br_perm)) {
1540+ /* remove whiteout base */
1541+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
1542+ if (unlikely(err))
1543+ goto out;
1544+
1545+ if (!au_br_writable(mod->perm)) {
1546+ /* rw --> ro, file might be mmapped */
1547+ DiMustNoWaiters(root);
1548+ IiMustNoWaiters(root->d_inode);
1549+ di_write_unlock(root);
1550+ err = au_br_mod_files_ro(sb, bindex);
1551+ /* aufs_write_lock() calls ..._child() */
1552+ di_write_lock_child(root);
1553+
1554+ if (unlikely(err)) {
1555+ rerr = -ENOMEM;
1556+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
1557+ GFP_NOFS);
1308ab2a 1558+ if (br->br_wbr) {
1559+ path.mnt = br->br_mnt;
1560+ path.dentry = mod->h_root;
1561+ rerr = au_wbr_init(br, sb, br->br_perm,
1562+ &path);
1563+ }
1facf9fc 1564+ if (unlikely(rerr)) {
1565+ AuIOErr("nested error %d (%d)\n",
1566+ rerr, err);
1567+ br->br_perm = mod->perm;
1568+ }
1569+ }
1570+ }
1571+ } else if (au_br_writable(mod->perm)) {
1572+ /* ro --> rw */
1573+ err = -ENOMEM;
1574+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1575+ if (br->br_wbr) {
1308ab2a 1576+ path.mnt = br->br_mnt;
1577+ path.dentry = mod->h_root;
1facf9fc 1578+ err = au_wbr_init(br, sb, mod->perm, &path);
1579+ if (unlikely(err)) {
1580+ kfree(br->br_wbr);
1581+ br->br_wbr = NULL;
1582+ }
1583+ }
1584+ }
1585+
1586+ if (!err) {
7f207e10 1587+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
1facf9fc 1588+ br->br_perm = mod->perm;
1589+ }
1590+
4f0767ce 1591+out:
7f207e10 1592+ AuTraceErr(err);
1facf9fc 1593+ return err;
1594+}
7f207e10
AM
1595diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
1596--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
1597+++ linux/fs/aufs/branch.h 2010-11-22 11:52:56.983894369 +0100
b752ccd1 1598@@ -0,0 +1,224 @@
1facf9fc 1599+/*
4a4d8108 1600+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1601+ *
1602+ * This program, aufs is free software; you can redistribute it and/or modify
1603+ * it under the terms of the GNU General Public License as published by
1604+ * the Free Software Foundation; either version 2 of the License, or
1605+ * (at your option) any later version.
dece6358
AM
1606+ *
1607+ * This program is distributed in the hope that it will be useful,
1608+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1609+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1610+ * GNU General Public License for more details.
1611+ *
1612+ * You should have received a copy of the GNU General Public License
1613+ * along with this program; if not, write to the Free Software
1614+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1615+ */
1616+
1617+/*
1618+ * branch filesystems and xino for them
1619+ */
1620+
1621+#ifndef __AUFS_BRANCH_H__
1622+#define __AUFS_BRANCH_H__
1623+
1624+#ifdef __KERNEL__
1625+
1626+#include <linux/fs.h>
1627+#include <linux/mount.h>
1facf9fc 1628+#include <linux/aufs_type.h>
4a4d8108 1629+#include "dynop.h"
1facf9fc 1630+#include "rwsem.h"
1631+#include "super.h"
1632+
1633+/* ---------------------------------------------------------------------- */
1634+
1635+/* a xino file */
1636+struct au_xino_file {
1637+ struct file *xi_file;
1638+ struct mutex xi_nondir_mtx;
1639+
1640+ /* todo: make xino files an array to support huge inode number */
1641+
1642+#ifdef CONFIG_DEBUG_FS
1643+ struct dentry *xi_dbgaufs;
1644+#endif
1645+};
1646+
1647+/* members for writable branch only */
1648+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
1649+struct au_wbr {
dece6358 1650+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 1651+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 1652+ atomic_t wbr_wh_running;
1facf9fc 1653+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
1654+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
1655+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
1656+
1657+ /* mfs mode */
1658+ unsigned long long wbr_bytes;
1659+};
1660+
4a4d8108
AM
1661+/* ext2 has 3 types of operations at least, ext3 has 4 */
1662+#define AuBrDynOp (AuDyLast * 4)
1663+
1facf9fc 1664+/* protected by superblock rwsem */
1665+struct au_branch {
1666+ struct au_xino_file br_xino;
1667+
1668+ aufs_bindex_t br_id;
1669+
1670+ int br_perm;
1671+ struct vfsmount *br_mnt;
4a4d8108
AM
1672+ spinlock_t br_dykey_lock;
1673+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 1674+ atomic_t br_count;
1675+
1676+ struct au_wbr *br_wbr;
1677+
1678+ /* xino truncation */
1679+ blkcnt_t br_xino_upper; /* watermark in blocks */
1680+ atomic_t br_xino_running;
1681+
1682+#ifdef CONFIG_SYSFS
1683+ /* an entry under sysfs per mount-point */
1684+ char br_name[8];
1685+ struct attribute br_attr;
1686+#endif
1687+};
1688+
1689+/* ---------------------------------------------------------------------- */
1690+
1691+/* branch permission and attribute */
1692+enum {
1693+ AuBrPerm_RW, /* writable, linkable wh */
1694+ AuBrPerm_RO, /* readonly, no wh */
1695+ AuBrPerm_RR, /* natively readonly, no wh */
1696+
1697+ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
1698+
1699+ AuBrPerm_ROWH, /* whiteout-able */
1700+ AuBrPerm_RRWH, /* whiteout-able */
1701+
1702+ AuBrPerm_Last
1703+};
1704+
1705+static inline int au_br_writable(int brperm)
1706+{
1707+ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1708+}
1709+
1710+static inline int au_br_whable(int brperm)
1711+{
1712+ return brperm == AuBrPerm_RW
1713+ || brperm == AuBrPerm_ROWH
1714+ || brperm == AuBrPerm_RRWH;
1715+}
1716+
1717+static inline int au_br_rdonly(struct au_branch *br)
1718+{
1719+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1720+ || !au_br_writable(br->br_perm))
1721+ ? -EROFS : 0;
1722+}
1723+
4a4d8108 1724+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 1725+{
4a4d8108 1726+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 1727+ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1728+#else
1729+ return 0;
1730+#endif
1731+}
1732+
1733+/* ---------------------------------------------------------------------- */
1734+
1735+/* branch.c */
1736+struct au_sbinfo;
1737+void au_br_free(struct au_sbinfo *sinfo);
1738+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1739+struct au_opt_add;
1740+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1741+struct au_opt_del;
1742+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
1743+struct au_opt_mod;
1744+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 1745+ int *do_refresh);
1facf9fc 1746+
1747+/* xino.c */
1748+static const loff_t au_loff_max = LLONG_MAX;
1749+
1750+int au_xib_trunc(struct super_block *sb);
1751+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1752+ loff_t *pos);
1753+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1754+ loff_t *pos);
1755+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
1756+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1757+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 1758+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 1759+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1760+ ino_t ino);
1761+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1762+ ino_t *ino);
1763+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1764+ struct file *base_file, int do_test);
1765+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1766+
1767+struct au_opt_xino;
1768+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1769+void au_xino_clr(struct super_block *sb);
1770+struct file *au_xino_def(struct super_block *sb);
1771+int au_xino_path(struct seq_file *seq, struct file *file);
1772+
1773+/* ---------------------------------------------------------------------- */
1774+
1775+/* Superblock to branch */
1776+static inline
1777+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1778+{
1779+ return au_sbr(sb, bindex)->br_id;
1780+}
1781+
1782+static inline
1783+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1784+{
1785+ return au_sbr(sb, bindex)->br_mnt;
1786+}
1787+
1788+static inline
1789+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1790+{
1791+ return au_sbr_mnt(sb, bindex)->mnt_sb;
1792+}
1793+
1794+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1795+{
e49829fe 1796+ atomic_dec(&au_sbr(sb, bindex)->br_count);
1facf9fc 1797+}
1798+
1799+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1800+{
1801+ return au_sbr(sb, bindex)->br_perm;
1802+}
1803+
1804+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1805+{
1806+ return au_br_whable(au_sbr_perm(sb, bindex));
1807+}
1808+
1809+/* ---------------------------------------------------------------------- */
1810+
1811+/*
1812+ * wbr_wh_read_lock, wbr_wh_write_lock
1813+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
1814+ */
1815+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
1816+
dece6358
AM
1817+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
1818+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
1819+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
1820+
1facf9fc 1821+#endif /* __KERNEL__ */
1822+#endif /* __AUFS_BRANCH_H__ */
7f207e10
AM
1823diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
1824--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
1825+++ linux/fs/aufs/conf.mk 2010-11-22 11:52:56.983894369 +0100
e49829fe 1826@@ -0,0 +1,37 @@
4a4d8108
AM
1827+
1828+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
1829+
1830+define AuConf
1831+ifdef ${1}
1832+AuConfStr += ${1}=${${1}}
1833+endif
1834+endef
1835+
b752ccd1 1836+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 1837+ SBILIST \
7f207e10 1838+ HNOTIFY HFSNOTIFY \
4a4d8108
AM
1839+ EXPORT INO_T_64 \
1840+ RDU \
1841+ SP_IATTR \
1842+ SHWH \
1843+ BR_RAMFS \
1844+ BR_FUSE POLL \
1845+ BR_HFSPLUS \
1846+ BDEV_LOOP \
b752ccd1
AM
1847+ DEBUG MAGIC_SYSRQ
1848+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
1849+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
1850+
1851+AuConfName = ${obj}/conf.str
1852+${AuConfName}.tmp: FORCE
1853+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
1854+${AuConfName}: ${AuConfName}.tmp
1855+ @diff -q $< $@ > /dev/null 2>&1 || { \
1856+ echo ' GEN ' $@; \
1857+ cp -p $< $@; \
1858+ }
1859+FORCE:
1860+clean-files += ${AuConfName} ${AuConfName}.tmp
1861+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
1862+
1863+-include ${srctree}/${src}/conf_priv.mk
7f207e10
AM
1864diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
1865--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
1866+++ linux/fs/aufs/cpup.c 2010-11-22 11:52:56.983894369 +0100
b752ccd1 1867@@ -0,0 +1,1059 @@
1facf9fc 1868+/*
4a4d8108 1869+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1870+ *
1871+ * This program, aufs is free software; you can redistribute it and/or modify
1872+ * it under the terms of the GNU General Public License as published by
1873+ * the Free Software Foundation; either version 2 of the License, or
1874+ * (at your option) any later version.
dece6358
AM
1875+ *
1876+ * This program is distributed in the hope that it will be useful,
1877+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1878+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1879+ * GNU General Public License for more details.
1880+ *
1881+ * You should have received a copy of the GNU General Public License
1882+ * along with this program; if not, write to the Free Software
1883+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1884+ */
1885+
1886+/*
1887+ * copy-up functions, see wbr_policy.c for copy-down
1888+ */
1889+
dece6358 1890+#include <linux/file.h>
1facf9fc 1891+#include <linux/fs_stack.h>
dece6358 1892+#include <linux/mm.h>
1facf9fc 1893+#include <linux/uaccess.h>
1894+#include "aufs.h"
1895+
1896+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
1897+{
1898+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
1899+ | S_NOATIME | S_NOCMTIME;
1900+
1901+ dst->i_flags |= src->i_flags & ~mask;
1902+ if (au_test_fs_notime(dst->i_sb))
1903+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
1904+}
1905+
1906+void au_cpup_attr_timesizes(struct inode *inode)
1907+{
1908+ struct inode *h_inode;
1909+
1910+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1911+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 1912+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 1913+}
1914+
1915+void au_cpup_attr_nlink(struct inode *inode, int force)
1916+{
1917+ struct inode *h_inode;
1918+ struct super_block *sb;
1919+ aufs_bindex_t bindex, bend;
1920+
1921+ sb = inode->i_sb;
1922+ bindex = au_ibstart(inode);
1923+ h_inode = au_h_iptr(inode, bindex);
1924+ if (!force
1925+ && !S_ISDIR(h_inode->i_mode)
1926+ && au_opt_test(au_mntflags(sb), PLINK)
1927+ && au_plink_test(inode))
1928+ return;
1929+
1930+ inode->i_nlink = h_inode->i_nlink;
1931+
1932+ /*
1933+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
1934+ * it may includes whplink directory.
1935+ */
1936+ if (S_ISDIR(h_inode->i_mode)) {
1937+ bend = au_ibend(inode);
1938+ for (bindex++; bindex <= bend; bindex++) {
1939+ h_inode = au_h_iptr(inode, bindex);
1940+ if (h_inode)
1941+ au_add_nlink(inode, h_inode);
1942+ }
1943+ }
1944+}
1945+
1946+void au_cpup_attr_changeable(struct inode *inode)
1947+{
1948+ struct inode *h_inode;
1949+
1950+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1951+ inode->i_mode = h_inode->i_mode;
1952+ inode->i_uid = h_inode->i_uid;
1953+ inode->i_gid = h_inode->i_gid;
1954+ au_cpup_attr_timesizes(inode);
1955+ au_cpup_attr_flags(inode, h_inode);
1956+}
1957+
1958+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
1959+{
1960+ struct au_iinfo *iinfo = au_ii(inode);
1961+
1308ab2a 1962+ IiMustWriteLock(inode);
1963+
1facf9fc 1964+ iinfo->ii_higen = h_inode->i_generation;
1965+ iinfo->ii_hsb1 = h_inode->i_sb;
1966+}
1967+
1968+void au_cpup_attr_all(struct inode *inode, int force)
1969+{
1970+ struct inode *h_inode;
1971+
1972+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1973+ au_cpup_attr_changeable(inode);
1974+ if (inode->i_nlink > 0)
1975+ au_cpup_attr_nlink(inode, force);
1976+ inode->i_rdev = h_inode->i_rdev;
1977+ inode->i_blkbits = h_inode->i_blkbits;
1978+ au_cpup_igen(inode, h_inode);
1979+}
1980+
1981+/* ---------------------------------------------------------------------- */
1982+
1983+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
1984+
1985+/* keep the timestamps of the parent dir when cpup */
1986+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
1987+ struct path *h_path)
1988+{
1989+ struct inode *h_inode;
1990+
1991+ dt->dt_dentry = dentry;
1992+ dt->dt_h_path = *h_path;
1993+ h_inode = h_path->dentry->d_inode;
1994+ dt->dt_atime = h_inode->i_atime;
1995+ dt->dt_mtime = h_inode->i_mtime;
1996+ /* smp_mb(); */
1997+}
1998+
1999+void au_dtime_revert(struct au_dtime *dt)
2000+{
2001+ struct iattr attr;
2002+ int err;
2003+
2004+ attr.ia_atime = dt->dt_atime;
2005+ attr.ia_mtime = dt->dt_mtime;
2006+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
2007+ | ATTR_ATIME | ATTR_ATIME_SET;
2008+
2009+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
2010+ if (unlikely(err))
4a4d8108 2011+ pr_warning("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 2012+}
2013+
2014+/* ---------------------------------------------------------------------- */
2015+
2016+static noinline_for_stack
2017+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
2018+{
2019+ int err, sbits;
2020+ struct iattr ia;
2021+ struct path h_path;
1308ab2a 2022+ struct inode *h_isrc, *h_idst;
1facf9fc 2023+
2024+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 2025+ h_idst = h_path.dentry->d_inode;
1facf9fc 2026+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
2027+ h_isrc = h_src->d_inode;
1308ab2a 2028+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 2029+ | ATTR_ATIME | ATTR_MTIME
2030+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 2031+ ia.ia_uid = h_isrc->i_uid;
2032+ ia.ia_gid = h_isrc->i_gid;
2033+ ia.ia_atime = h_isrc->i_atime;
2034+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 2035+ if (h_idst->i_mode != h_isrc->i_mode
2036+ && !S_ISLNK(h_idst->i_mode)) {
2037+ ia.ia_valid |= ATTR_MODE;
2038+ ia.ia_mode = h_isrc->i_mode;
2039+ }
2040+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
2041+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 2042+ err = vfsub_notify_change(&h_path, &ia);
2043+
2044+ /* is this nfs only? */
2045+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
2046+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
2047+ ia.ia_mode = h_isrc->i_mode;
2048+ err = vfsub_notify_change(&h_path, &ia);
2049+ }
2050+
2051+ return err;
2052+}
2053+
2054+/* ---------------------------------------------------------------------- */
2055+
2056+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
2057+ char *buf, unsigned long blksize)
2058+{
2059+ int err;
2060+ size_t sz, rbytes, wbytes;
2061+ unsigned char all_zero;
2062+ char *p, *zp;
2063+ struct mutex *h_mtx;
2064+ /* reduce stack usage */
2065+ struct iattr *ia;
2066+
2067+ zp = page_address(ZERO_PAGE(0));
2068+ if (unlikely(!zp))
2069+ return -ENOMEM; /* possible? */
2070+
2071+ err = 0;
2072+ all_zero = 0;
2073+ while (len) {
2074+ AuDbg("len %lld\n", len);
2075+ sz = blksize;
2076+ if (len < blksize)
2077+ sz = len;
2078+
2079+ rbytes = 0;
2080+ /* todo: signal_pending? */
2081+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
2082+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
2083+ err = rbytes;
2084+ }
2085+ if (unlikely(err < 0))
2086+ break;
2087+
2088+ all_zero = 0;
2089+ if (len >= rbytes && rbytes == blksize)
2090+ all_zero = !memcmp(buf, zp, rbytes);
2091+ if (!all_zero) {
2092+ wbytes = rbytes;
2093+ p = buf;
2094+ while (wbytes) {
2095+ size_t b;
2096+
2097+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
2098+ err = b;
2099+ /* todo: signal_pending? */
2100+ if (unlikely(err == -EAGAIN || err == -EINTR))
2101+ continue;
2102+ if (unlikely(err < 0))
2103+ break;
2104+ wbytes -= b;
2105+ p += b;
2106+ }
2107+ } else {
2108+ loff_t res;
2109+
2110+ AuLabel(hole);
2111+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
2112+ err = res;
2113+ if (unlikely(res < 0))
2114+ break;
2115+ }
2116+ len -= rbytes;
2117+ err = 0;
2118+ }
2119+
2120+ /* the last block may be a hole */
2121+ if (!err && all_zero) {
2122+ AuLabel(last hole);
2123+
2124+ err = 1;
2125+ if (au_test_nfs(dst->f_dentry->d_sb)) {
2126+ /* nfs requires this step to make last hole */
2127+ /* is this only nfs? */
2128+ do {
2129+ /* todo: signal_pending? */
2130+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
2131+ } while (err == -EAGAIN || err == -EINTR);
2132+ if (err == 1)
2133+ dst->f_pos--;
2134+ }
2135+
2136+ if (err == 1) {
2137+ ia = (void *)buf;
2138+ ia->ia_size = dst->f_pos;
2139+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
2140+ ia->ia_file = dst;
2141+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
2142+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
2143+ err = vfsub_notify_change(&dst->f_path, ia);
2144+ mutex_unlock(h_mtx);
2145+ }
2146+ }
2147+
2148+ return err;
2149+}
2150+
2151+int au_copy_file(struct file *dst, struct file *src, loff_t len)
2152+{
2153+ int err;
2154+ unsigned long blksize;
2155+ unsigned char do_kfree;
2156+ char *buf;
2157+
2158+ err = -ENOMEM;
2159+ blksize = dst->f_dentry->d_sb->s_blocksize;
2160+ if (!blksize || PAGE_SIZE < blksize)
2161+ blksize = PAGE_SIZE;
2162+ AuDbg("blksize %lu\n", blksize);
2163+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
2164+ if (do_kfree)
2165+ buf = kmalloc(blksize, GFP_NOFS);
2166+ else
2167+ buf = (void *)__get_free_page(GFP_NOFS);
2168+ if (unlikely(!buf))
2169+ goto out;
2170+
2171+ if (len > (1 << 22))
2172+ AuDbg("copying a large file %lld\n", (long long)len);
2173+
2174+ src->f_pos = 0;
2175+ dst->f_pos = 0;
2176+ err = au_do_copy_file(dst, src, len, buf, blksize);
2177+ if (do_kfree)
2178+ kfree(buf);
2179+ else
2180+ free_page((unsigned long)buf);
2181+
4f0767ce 2182+out:
1facf9fc 2183+ return err;
2184+}
2185+
2186+/*
2187+ * to support a sparse file which is opened with O_APPEND,
2188+ * we need to close the file.
2189+ */
2190+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 2191+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 2192+{
2193+ int err, i;
2194+ enum { SRC, DST };
2195+ struct {
2196+ aufs_bindex_t bindex;
2197+ unsigned int flags;
2198+ struct dentry *dentry;
2199+ struct file *file;
2200+ void *label, *label_file;
2201+ } *f, file[] = {
2202+ {
2203+ .bindex = bsrc,
2204+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
2205+ .file = NULL,
2206+ .label = &&out,
2207+ .label_file = &&out_src
2208+ },
2209+ {
2210+ .bindex = bdst,
2211+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
2212+ .file = NULL,
2213+ .label = &&out_src,
2214+ .label_file = &&out_dst
2215+ }
2216+ };
2217+ struct super_block *sb;
2218+
2219+ /* bsrc branch can be ro/rw. */
2220+ sb = dentry->d_sb;
2221+ f = file;
2222+ for (i = 0; i < 2; i++, f++) {
2223+ f->dentry = au_h_dptr(dentry, f->bindex);
2224+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
2225+ err = PTR_ERR(f->file);
2226+ if (IS_ERR(f->file))
2227+ goto *f->label;
2228+ err = -EINVAL;
2229+ if (unlikely(!f->file->f_op))
2230+ goto *f->label_file;
2231+ }
2232+
2233+ /* try stopping to update while we copyup */
2234+ IMustLock(file[SRC].dentry->d_inode);
2235+ err = au_copy_file(file[DST].file, file[SRC].file, len);
2236+
4f0767ce 2237+out_dst:
1facf9fc 2238+ fput(file[DST].file);
2239+ au_sbr_put(sb, file[DST].bindex);
4f0767ce 2240+out_src:
1facf9fc 2241+ fput(file[SRC].file);
2242+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 2243+out:
1facf9fc 2244+ return err;
2245+}
2246+
2247+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
2248+ aufs_bindex_t bsrc, loff_t len,
2249+ struct inode *h_dir, struct path *h_path)
2250+{
2251+ int err, rerr;
2252+ loff_t l;
2253+
2254+ err = 0;
2255+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
2256+ if (len == -1 || l < len)
2257+ len = l;
2258+ if (len)
2259+ err = au_cp_regular(dentry, bdst, bsrc, len);
2260+ if (!err)
2261+ goto out; /* success */
2262+
2263+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
2264+ if (rerr) {
2265+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
2266+ AuDLNPair(h_path->dentry), err, rerr);
2267+ err = -EIO;
2268+ }
2269+
4f0767ce 2270+out:
1facf9fc 2271+ return err;
2272+}
2273+
2274+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
2275+ struct inode *h_dir)
2276+{
2277+ int err, symlen;
2278+ mm_segment_t old_fs;
b752ccd1
AM
2279+ union {
2280+ char *k;
2281+ char __user *u;
2282+ } sym;
1facf9fc 2283+
2284+ err = -ENOSYS;
2285+ if (unlikely(!h_src->d_inode->i_op->readlink))
2286+ goto out;
2287+
2288+ err = -ENOMEM;
b752ccd1
AM
2289+ sym.k = __getname_gfp(GFP_NOFS);
2290+ if (unlikely(!sym.k))
1facf9fc 2291+ goto out;
2292+
2293+ old_fs = get_fs();
2294+ set_fs(KERNEL_DS);
b752ccd1 2295+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 2296+ err = symlen;
2297+ set_fs(old_fs);
2298+
2299+ if (symlen > 0) {
b752ccd1
AM
2300+ sym.k[symlen] = 0;
2301+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 2302+ }
b752ccd1 2303+ __putname(sym.k);
1facf9fc 2304+
4f0767ce 2305+out:
1facf9fc 2306+ return err;
2307+}
2308+
2309+/* return with the lower dst inode is locked */
2310+static noinline_for_stack
2311+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
2312+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2313+ struct dentry *dst_parent)
2314+{
2315+ int err;
2316+ umode_t mode;
2317+ unsigned int mnt_flags;
2318+ unsigned char isdir;
2319+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
2320+ struct au_dtime dt;
2321+ struct path h_path;
2322+ struct dentry *h_src, *h_dst, *h_parent;
2323+ struct inode *h_inode, *h_dir;
2324+ struct super_block *sb;
2325+
2326+ /* bsrc branch can be ro/rw. */
2327+ h_src = au_h_dptr(dentry, bsrc);
2328+ h_inode = h_src->d_inode;
2329+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
2330+
2331+ /* try stopping to be referenced while we are creating */
2332+ h_dst = au_h_dptr(dentry, bdst);
2333+ h_parent = h_dst->d_parent; /* dir inode is locked */
2334+ h_dir = h_parent->d_inode;
2335+ IMustLock(h_dir);
2336+ AuDebugOn(h_parent != h_dst->d_parent);
2337+
2338+ sb = dentry->d_sb;
2339+ h_path.mnt = au_sbr_mnt(sb, bdst);
2340+ if (do_dt) {
2341+ h_path.dentry = h_parent;
2342+ au_dtime_store(&dt, dst_parent, &h_path);
2343+ }
2344+ h_path.dentry = h_dst;
2345+
2346+ isdir = 0;
2347+ mode = h_inode->i_mode;
2348+ switch (mode & S_IFMT) {
2349+ case S_IFREG:
2350+ /* try stopping to update while we are referencing */
2351+ IMustLock(h_inode);
2352+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
2353+ if (!err)
2354+ err = au_do_cpup_regular
2355+ (dentry, bdst, bsrc, len,
2356+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
2357+ break;
2358+ case S_IFDIR:
2359+ isdir = 1;
2360+ err = vfsub_mkdir(h_dir, &h_path, mode);
2361+ if (!err) {
2362+ /*
2363+ * strange behaviour from the users view,
2364+ * particularry setattr case
2365+ */
2366+ if (au_ibstart(dst_parent->d_inode) == bdst)
2367+ au_cpup_attr_nlink(dst_parent->d_inode,
2368+ /*force*/1);
2369+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
2370+ }
2371+ break;
2372+ case S_IFLNK:
2373+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
2374+ break;
2375+ case S_IFCHR:
2376+ case S_IFBLK:
2377+ AuDebugOn(!capable(CAP_MKNOD));
2378+ /*FALLTHROUGH*/
2379+ case S_IFIFO:
2380+ case S_IFSOCK:
2381+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
2382+ break;
2383+ default:
2384+ AuIOErr("Unknown inode type 0%o\n", mode);
2385+ err = -EIO;
2386+ }
2387+
2388+ mnt_flags = au_mntflags(sb);
2389+ if (!au_opt_test(mnt_flags, UDBA_NONE)
2390+ && !isdir
2391+ && au_opt_test(mnt_flags, XINO)
2392+ && h_inode->i_nlink == 1
2393+ /* todo: unnecessary? */
2394+ /* && dentry->d_inode->i_nlink == 1 */
2395+ && bdst < bsrc
2396+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 2397+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 2398+ /* ignore this error */
2399+
2400+ if (do_dt)
2401+ au_dtime_revert(&dt);
2402+ return err;
2403+}
2404+
2405+/*
2406+ * copyup the @dentry from @bsrc to @bdst.
2407+ * the caller must set the both of lower dentries.
2408+ * @len is for truncating when it is -1 copyup the entire file.
2409+ * in link/rename cases, @dst_parent may be different from the real one.
2410+ */
2411+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2412+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2413+ struct dentry *dst_parent)
2414+{
2415+ int err, rerr;
2416+ aufs_bindex_t old_ibstart;
2417+ unsigned char isdir, plink;
2418+ struct au_dtime dt;
2419+ struct path h_path;
2420+ struct dentry *h_src, *h_dst, *h_parent;
2421+ struct inode *dst_inode, *h_dir, *inode;
2422+ struct super_block *sb;
2423+
2424+ AuDebugOn(bsrc <= bdst);
2425+
2426+ sb = dentry->d_sb;
2427+ h_path.mnt = au_sbr_mnt(sb, bdst);
2428+ h_dst = au_h_dptr(dentry, bdst);
2429+ h_parent = h_dst->d_parent; /* dir inode is locked */
2430+ h_dir = h_parent->d_inode;
2431+ IMustLock(h_dir);
2432+
2433+ h_src = au_h_dptr(dentry, bsrc);
2434+ inode = dentry->d_inode;
2435+
2436+ if (!dst_parent)
2437+ dst_parent = dget_parent(dentry);
2438+ else
2439+ dget(dst_parent);
2440+
2441+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
2442+ dst_inode = au_h_iptr(inode, bdst);
2443+ if (dst_inode) {
2444+ if (unlikely(!plink)) {
2445+ err = -EIO;
2446+ AuIOErr("i%lu exists on a upper branch "
2447+ "but plink is disabled\n", inode->i_ino);
2448+ goto out;
2449+ }
2450+
2451+ if (dst_inode->i_nlink) {
2452+ const int do_dt = au_ftest_cpup(flags, DTIME);
2453+
2454+ h_src = au_plink_lkup(inode, bdst);
2455+ err = PTR_ERR(h_src);
2456+ if (IS_ERR(h_src))
2457+ goto out;
2458+ if (unlikely(!h_src->d_inode)) {
2459+ err = -EIO;
2460+ AuIOErr("i%lu exists on a upper branch "
2461+ "but plink is broken\n", inode->i_ino);
2462+ dput(h_src);
2463+ goto out;
2464+ }
2465+
2466+ if (do_dt) {
2467+ h_path.dentry = h_parent;
2468+ au_dtime_store(&dt, dst_parent, &h_path);
2469+ }
2470+ h_path.dentry = h_dst;
2471+ err = vfsub_link(h_src, h_dir, &h_path);
2472+ if (do_dt)
2473+ au_dtime_revert(&dt);
2474+ dput(h_src);
2475+ goto out;
2476+ } else
2477+ /* todo: cpup_wh_file? */
2478+ /* udba work */
4a4d8108 2479+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 2480+ }
2481+
2482+ old_ibstart = au_ibstart(inode);
2483+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
2484+ if (unlikely(err))
2485+ goto out;
2486+ dst_inode = h_dst->d_inode;
2487+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
2488+
2489+ err = cpup_iattr(dentry, bdst, h_src);
2490+ isdir = S_ISDIR(dst_inode->i_mode);
2491+ if (!err) {
4a4d8108
AM
2492+ if (bdst < old_ibstart) {
2493+ if (S_ISREG(inode->i_mode)) {
2494+ err = au_dy_iaop(inode, bdst, dst_inode);
2495+ if (unlikely(err))
2496+ goto out_rev;
2497+ }
1facf9fc 2498+ au_set_ibstart(inode, bdst);
4a4d8108 2499+ }
1facf9fc 2500+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
2501+ au_hi_flags(inode, isdir));
2502+ mutex_unlock(&dst_inode->i_mutex);
2503+ if (!isdir
2504+ && h_src->d_inode->i_nlink > 1
2505+ && plink)
2506+ au_plink_append(inode, bdst, h_dst);
2507+ goto out; /* success */
2508+ }
2509+
2510+ /* revert */
4a4d8108 2511+out_rev:
1facf9fc 2512+ h_path.dentry = h_parent;
2513+ mutex_unlock(&dst_inode->i_mutex);
2514+ au_dtime_store(&dt, dst_parent, &h_path);
2515+ h_path.dentry = h_dst;
2516+ if (!isdir)
2517+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
2518+ else
2519+ rerr = vfsub_rmdir(h_dir, &h_path);
2520+ au_dtime_revert(&dt);
2521+ if (rerr) {
2522+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
2523+ err = -EIO;
2524+ }
2525+
4f0767ce 2526+out:
1facf9fc 2527+ dput(dst_parent);
2528+ return err;
2529+}
2530+
2531+struct au_cpup_single_args {
2532+ int *errp;
2533+ struct dentry *dentry;
2534+ aufs_bindex_t bdst, bsrc;
2535+ loff_t len;
2536+ unsigned int flags;
2537+ struct dentry *dst_parent;
2538+};
2539+
2540+static void au_call_cpup_single(void *args)
2541+{
2542+ struct au_cpup_single_args *a = args;
2543+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
2544+ a->flags, a->dst_parent);
2545+}
2546+
2547+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2548+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2549+ struct dentry *dst_parent)
2550+{
2551+ int err, wkq_err;
2552+ umode_t mode;
2553+ struct dentry *h_dentry;
2554+
2555+ h_dentry = au_h_dptr(dentry, bsrc);
2556+ mode = h_dentry->d_inode->i_mode & S_IFMT;
2557+ if ((mode != S_IFCHR && mode != S_IFBLK)
2558+ || capable(CAP_MKNOD))
2559+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2560+ dst_parent);
2561+ else {
2562+ struct au_cpup_single_args args = {
2563+ .errp = &err,
2564+ .dentry = dentry,
2565+ .bdst = bdst,
2566+ .bsrc = bsrc,
2567+ .len = len,
2568+ .flags = flags,
2569+ .dst_parent = dst_parent
2570+ };
2571+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
2572+ if (unlikely(wkq_err))
2573+ err = wkq_err;
2574+ }
2575+
2576+ return err;
2577+}
2578+
2579+/*
2580+ * copyup the @dentry from the first active lower branch to @bdst,
2581+ * using au_cpup_single().
2582+ */
2583+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2584+ unsigned int flags)
2585+{
2586+ int err;
2587+ aufs_bindex_t bsrc, bend;
2588+
2589+ bend = au_dbend(dentry);
2590+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2591+ if (au_h_dptr(dentry, bsrc))
2592+ break;
2593+
2594+ err = au_lkup_neg(dentry, bdst);
2595+ if (!err) {
2596+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
2597+ if (!err)
2598+ return 0; /* success */
2599+
2600+ /* revert */
2601+ au_set_h_dptr(dentry, bdst, NULL);
2602+ au_set_dbstart(dentry, bsrc);
2603+ }
2604+
2605+ return err;
2606+}
2607+
2608+struct au_cpup_simple_args {
2609+ int *errp;
2610+ struct dentry *dentry;
2611+ aufs_bindex_t bdst;
2612+ loff_t len;
2613+ unsigned int flags;
2614+};
2615+
2616+static void au_call_cpup_simple(void *args)
2617+{
2618+ struct au_cpup_simple_args *a = args;
2619+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
2620+}
2621+
2622+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2623+ unsigned int flags)
2624+{
2625+ int err, wkq_err;
2626+ unsigned char do_sio;
2627+ struct dentry *parent;
2628+ struct inode *h_dir;
2629+
2630+ parent = dget_parent(dentry);
2631+ h_dir = au_h_iptr(parent->d_inode, bdst);
2632+ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
2633+ if (!do_sio) {
2634+ /*
2635+ * testing CAP_MKNOD is for generic fs,
2636+ * but CAP_FSETID is for xfs only, currently.
2637+ */
2638+ umode_t mode = dentry->d_inode->i_mode;
2639+ do_sio = (((mode & (S_IFCHR | S_IFBLK))
2640+ && !capable(CAP_MKNOD))
2641+ || ((mode & (S_ISUID | S_ISGID))
2642+ && !capable(CAP_FSETID)));
2643+ }
2644+ if (!do_sio)
2645+ err = au_cpup_simple(dentry, bdst, len, flags);
2646+ else {
2647+ struct au_cpup_simple_args args = {
2648+ .errp = &err,
2649+ .dentry = dentry,
2650+ .bdst = bdst,
2651+ .len = len,
2652+ .flags = flags
2653+ };
2654+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
2655+ if (unlikely(wkq_err))
2656+ err = wkq_err;
2657+ }
2658+
2659+ dput(parent);
2660+ return err;
2661+}
2662+
2663+/* ---------------------------------------------------------------------- */
2664+
2665+/*
2666+ * copyup the deleted file for writing.
2667+ */
2668+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2669+ struct dentry *wh_dentry, struct file *file,
2670+ loff_t len)
2671+{
2672+ int err;
2673+ aufs_bindex_t bstart;
2674+ struct au_dinfo *dinfo;
2675+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 2676+ struct au_hdentry *hdp;
1facf9fc 2677+
2678+ dinfo = au_di(dentry);
1308ab2a 2679+ AuRwMustWriteLock(&dinfo->di_rwsem);
2680+
1facf9fc 2681+ bstart = dinfo->di_bstart;
4a4d8108
AM
2682+ hdp = dinfo->di_hdentry;
2683+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 2684+ dinfo->di_bstart = bdst;
4a4d8108
AM
2685+ hdp[0 + bdst].hd_dentry = wh_dentry;
2686+ h_d_start = hdp[0 + bstart].hd_dentry;
1facf9fc 2687+ if (file)
4a4d8108 2688+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2689+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2690+ /*h_parent*/NULL);
2691+ if (!err && file) {
2692+ err = au_reopen_nondir(file);
4a4d8108 2693+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 2694+ }
4a4d8108 2695+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 2696+ dinfo->di_bstart = bstart;
2697+
2698+ return err;
2699+}
2700+
2701+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2702+ struct file *file)
2703+{
2704+ int err;
2705+ struct au_dtime dt;
2706+ struct dentry *parent, *h_parent, *wh_dentry;
2707+ struct au_branch *br;
2708+ struct path h_path;
2709+
2710+ br = au_sbr(dentry->d_sb, bdst);
2711+ parent = dget_parent(dentry);
2712+ h_parent = au_h_dptr(parent, bdst);
2713+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
2714+ err = PTR_ERR(wh_dentry);
2715+ if (IS_ERR(wh_dentry))
2716+ goto out;
2717+
2718+ h_path.dentry = h_parent;
2719+ h_path.mnt = br->br_mnt;
2720+ au_dtime_store(&dt, parent, &h_path);
2721+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
2722+ if (unlikely(err))
2723+ goto out_wh;
2724+
2725+ dget(wh_dentry);
2726+ h_path.dentry = wh_dentry;
4a4d8108
AM
2727+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
2728+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
2729+ else
2730+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 2731+ if (unlikely(err)) {
2732+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2733+ AuDLNPair(wh_dentry), err);
2734+ err = -EIO;
2735+ }
2736+ au_dtime_revert(&dt);
2737+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2738+
4f0767ce 2739+out_wh:
1facf9fc 2740+ dput(wh_dentry);
4f0767ce 2741+out:
1facf9fc 2742+ dput(parent);
2743+ return err;
2744+}
2745+
2746+struct au_cpup_wh_args {
2747+ int *errp;
2748+ struct dentry *dentry;
2749+ aufs_bindex_t bdst;
2750+ loff_t len;
2751+ struct file *file;
2752+};
2753+
2754+static void au_call_cpup_wh(void *args)
2755+{
2756+ struct au_cpup_wh_args *a = args;
2757+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
2758+}
2759+
2760+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2761+ struct file *file)
2762+{
2763+ int err, wkq_err;
2764+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
2765+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
2766+ struct au_wbr *wbr;
2767+
2768+ parent = dget_parent(dentry);
2769+ dir = parent->d_inode;
2770+ h_orph = NULL;
2771+ h_parent = NULL;
2772+ h_dir = au_igrab(au_h_iptr(dir, bdst));
2773+ h_tmpdir = h_dir;
2774+ if (!h_dir->i_nlink) {
2775+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
2776+ h_orph = wbr->wbr_orph;
2777+
2778+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 2779+ au_set_h_dptr(parent, bdst, dget(h_orph));
2780+ h_tmpdir = h_orph->d_inode;
1facf9fc 2781+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
2782+
2783+ /* this temporary unlock is safe */
2784+ if (file)
4a4d8108 2785+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2786+ else
2787+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
2788+ h_inode = h_dentry->d_inode;
2789+ IMustLock(h_inode);
2790+ mutex_unlock(&h_inode->i_mutex);
dece6358 2791+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 2792+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 2793+ /* todo: au_h_open_pre()? */
1facf9fc 2794+ }
2795+
2796+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
2797+ err = au_cpup_wh(dentry, bdst, len, file);
2798+ else {
2799+ struct au_cpup_wh_args args = {
2800+ .errp = &err,
2801+ .dentry = dentry,
2802+ .bdst = bdst,
2803+ .len = len,
2804+ .file = file
2805+ };
2806+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
2807+ if (unlikely(wkq_err))
2808+ err = wkq_err;
2809+ }
2810+
2811+ if (h_orph) {
2812+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 2813+ /* todo: au_h_open_post()? */
1facf9fc 2814+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 2815+ au_set_h_dptr(parent, bdst, h_parent);
2816+ }
2817+ iput(h_dir);
2818+ dput(parent);
2819+
2820+ return err;
2821+}
2822+
2823+/* ---------------------------------------------------------------------- */
2824+
2825+/*
2826+ * generic routine for both of copy-up and copy-down.
2827+ */
2828+/* cf. revalidate function in file.c */
2829+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2830+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2831+ struct dentry *h_parent, void *arg),
2832+ void *arg)
2833+{
2834+ int err;
2835+ struct au_pin pin;
2836+ struct dentry *d, *parent, *h_parent, *real_parent;
2837+
2838+ err = 0;
2839+ parent = dget_parent(dentry);
2840+ if (IS_ROOT(parent))
2841+ goto out;
2842+
2843+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
2844+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
2845+
2846+ /* do not use au_dpage */
2847+ real_parent = parent;
2848+ while (1) {
2849+ dput(parent);
2850+ parent = dget_parent(dentry);
2851+ h_parent = au_h_dptr(parent, bdst);
2852+ if (h_parent)
2853+ goto out; /* success */
2854+
2855+ /* find top dir which is necessary to cpup */
2856+ do {
2857+ d = parent;
2858+ dput(parent);
2859+ parent = dget_parent(d);
2860+ di_read_lock_parent3(parent, !AuLock_IR);
2861+ h_parent = au_h_dptr(parent, bdst);
2862+ di_read_unlock(parent, !AuLock_IR);
2863+ } while (!h_parent);
2864+
2865+ if (d != real_parent)
2866+ di_write_lock_child3(d);
2867+
2868+ /* somebody else might create while we were sleeping */
2869+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
2870+ if (au_h_dptr(d, bdst))
2871+ au_update_dbstart(d);
2872+
2873+ au_pin_set_dentry(&pin, d);
2874+ err = au_do_pin(&pin);
2875+ if (!err) {
2876+ err = cp(d, bdst, h_parent, arg);
2877+ au_unpin(&pin);
2878+ }
2879+ }
2880+
2881+ if (d != real_parent)
2882+ di_write_unlock(d);
2883+ if (unlikely(err))
2884+ break;
2885+ }
2886+
4f0767ce 2887+out:
1facf9fc 2888+ dput(parent);
2889+ return err;
2890+}
2891+
2892+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
2893+ struct dentry *h_parent __maybe_unused ,
2894+ void *arg __maybe_unused)
2895+{
2896+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
2897+}
2898+
2899+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2900+{
2901+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
2902+}
2903+
2904+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2905+{
2906+ int err;
2907+ struct dentry *parent;
2908+ struct inode *dir;
2909+
2910+ parent = dget_parent(dentry);
2911+ dir = parent->d_inode;
2912+ err = 0;
2913+ if (au_h_iptr(dir, bdst))
2914+ goto out;
2915+
2916+ di_read_unlock(parent, AuLock_IR);
2917+ di_write_lock_parent(parent);
2918+ /* someone else might change our inode while we were sleeping */
2919+ if (!au_h_iptr(dir, bdst))
2920+ err = au_cpup_dirs(dentry, bdst);
2921+ di_downgrade_lock(parent, AuLock_IR);
2922+
4f0767ce 2923+out:
1facf9fc 2924+ dput(parent);
2925+ return err;
2926+}
7f207e10
AM
2927diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
2928--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
2929+++ linux/fs/aufs/cpup.h 2010-11-22 11:52:56.983894369 +0100
2930@@ -0,0 +1,83 @@
1facf9fc 2931+/*
4a4d8108 2932+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2933+ *
2934+ * This program, aufs is free software; you can redistribute it and/or modify
2935+ * it under the terms of the GNU General Public License as published by
2936+ * the Free Software Foundation; either version 2 of the License, or
2937+ * (at your option) any later version.
dece6358
AM
2938+ *
2939+ * This program is distributed in the hope that it will be useful,
2940+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2941+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2942+ * GNU General Public License for more details.
2943+ *
2944+ * You should have received a copy of the GNU General Public License
2945+ * along with this program; if not, write to the Free Software
2946+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2947+ */
2948+
2949+/*
2950+ * copy-up/down functions
2951+ */
2952+
2953+#ifndef __AUFS_CPUP_H__
2954+#define __AUFS_CPUP_H__
2955+
2956+#ifdef __KERNEL__
2957+
dece6358
AM
2958+#include <linux/path.h>
2959+#include <linux/time.h>
1facf9fc 2960+#include <linux/aufs_type.h>
2961+
dece6358
AM
2962+struct inode;
2963+struct file;
2964+
1facf9fc 2965+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
2966+void au_cpup_attr_timesizes(struct inode *inode);
2967+void au_cpup_attr_nlink(struct inode *inode, int force);
2968+void au_cpup_attr_changeable(struct inode *inode);
2969+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
2970+void au_cpup_attr_all(struct inode *inode, int force);
2971+
2972+/* ---------------------------------------------------------------------- */
2973+
2974+/* cpup flags */
2975+#define AuCpup_DTIME 1 /* do dtime_store/revert */
2976+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
2977+ for link(2) */
2978+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
2979+#define au_fset_cpup(flags, name) \
2980+ do { (flags) |= AuCpup_##name; } while (0)
2981+#define au_fclr_cpup(flags, name) \
2982+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 2983+
2984+int au_copy_file(struct file *dst, struct file *src, loff_t len);
2985+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2986+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2987+ struct dentry *dst_parent);
2988+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2989+ unsigned int flags);
2990+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2991+ struct file *file);
2992+
2993+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2994+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2995+ struct dentry *h_parent, void *arg),
2996+ void *arg);
2997+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2998+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2999+
3000+/* ---------------------------------------------------------------------- */
3001+
3002+/* keep timestamps when copyup */
3003+struct au_dtime {
3004+ struct dentry *dt_dentry;
3005+ struct path dt_h_path;
3006+ struct timespec dt_atime, dt_mtime;
3007+};
3008+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
3009+ struct path *h_path);
3010+void au_dtime_revert(struct au_dtime *dt);
3011+
3012+#endif /* __KERNEL__ */
3013+#endif /* __AUFS_CPUP_H__ */
7f207e10
AM
3014diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
3015--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
3016+++ linux/fs/aufs/dbgaufs.c 2010-11-22 11:52:56.983894369 +0100
4a4d8108 3017@@ -0,0 +1,334 @@
1facf9fc 3018+/*
4a4d8108 3019+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3020+ *
3021+ * This program, aufs is free software; you can redistribute it and/or modify
3022+ * it under the terms of the GNU General Public License as published by
3023+ * the Free Software Foundation; either version 2 of the License, or
3024+ * (at your option) any later version.
dece6358
AM
3025+ *
3026+ * This program is distributed in the hope that it will be useful,
3027+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3028+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3029+ * GNU General Public License for more details.
3030+ *
3031+ * You should have received a copy of the GNU General Public License
3032+ * along with this program; if not, write to the Free Software
3033+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3034+ */
3035+
3036+/*
3037+ * debugfs interface
3038+ */
3039+
3040+#include <linux/debugfs.h>
3041+#include "aufs.h"
3042+
3043+#ifndef CONFIG_SYSFS
3044+#error DEBUG_FS depends upon SYSFS
3045+#endif
3046+
3047+static struct dentry *dbgaufs;
3048+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
3049+
3050+/* 20 is max digits length of ulong 64 */
3051+struct dbgaufs_arg {
3052+ int n;
3053+ char a[20 * 4];
3054+};
3055+
3056+/*
3057+ * common function for all XINO files
3058+ */
3059+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
3060+ struct file *file)
3061+{
3062+ kfree(file->private_data);
3063+ return 0;
3064+}
3065+
3066+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
3067+{
3068+ int err;
3069+ struct kstat st;
3070+ struct dbgaufs_arg *p;
3071+
3072+ err = -ENOMEM;
3073+ p = kmalloc(sizeof(*p), GFP_NOFS);
3074+ if (unlikely(!p))
3075+ goto out;
3076+
3077+ err = 0;
3078+ p->n = 0;
3079+ file->private_data = p;
3080+ if (!xf)
3081+ goto out;
3082+
3083+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
3084+ if (!err) {
3085+ if (do_fcnt)
3086+ p->n = snprintf
3087+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
3088+ (long)file_count(xf), st.blocks, st.blksize,
3089+ (long long)st.size);
3090+ else
3091+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
3092+ st.blocks, st.blksize,
3093+ (long long)st.size);
3094+ AuDebugOn(p->n >= sizeof(p->a));
3095+ } else {
3096+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
3097+ err = 0;
3098+ }
3099+
4f0767ce 3100+out:
1facf9fc 3101+ return err;
3102+
3103+}
3104+
3105+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
3106+ size_t count, loff_t *ppos)
3107+{
3108+ struct dbgaufs_arg *p;
3109+
3110+ p = file->private_data;
3111+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
3112+}
3113+
3114+/* ---------------------------------------------------------------------- */
3115+
3116+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
3117+{
3118+ int err;
3119+ struct au_sbinfo *sbinfo;
3120+ struct super_block *sb;
3121+
3122+ sbinfo = inode->i_private;
3123+ sb = sbinfo->si_sb;
3124+ si_noflush_read_lock(sb);
3125+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
3126+ si_read_unlock(sb);
3127+ return err;
3128+}
3129+
3130+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 3131+ .owner = THIS_MODULE,
1facf9fc 3132+ .open = dbgaufs_xib_open,
3133+ .release = dbgaufs_xi_release,
3134+ .read = dbgaufs_xi_read
3135+};
3136+
3137+/* ---------------------------------------------------------------------- */
3138+
3139+#define DbgaufsXi_PREFIX "xi"
3140+
3141+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
3142+{
3143+ int err;
3144+ long l;
3145+ struct au_sbinfo *sbinfo;
3146+ struct super_block *sb;
3147+ struct file *xf;
3148+ struct qstr *name;
3149+
3150+ err = -ENOENT;
3151+ xf = NULL;
3152+ name = &file->f_dentry->d_name;
3153+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
3154+ || memcmp(name->name, DbgaufsXi_PREFIX,
3155+ sizeof(DbgaufsXi_PREFIX) - 1)))
3156+ goto out;
3157+ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
3158+ if (unlikely(err))
3159+ goto out;
3160+
3161+ sbinfo = inode->i_private;
3162+ sb = sbinfo->si_sb;
3163+ si_noflush_read_lock(sb);
3164+ if (l <= au_sbend(sb)) {
3165+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
3166+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
3167+ } else
3168+ err = -ENOENT;
3169+ si_read_unlock(sb);
3170+
4f0767ce 3171+out:
1facf9fc 3172+ return err;
3173+}
3174+
3175+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 3176+ .owner = THIS_MODULE,
1facf9fc 3177+ .open = dbgaufs_xino_open,
3178+ .release = dbgaufs_xi_release,
3179+ .read = dbgaufs_xi_read
3180+};
3181+
3182+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
3183+{
3184+ aufs_bindex_t bend;
3185+ struct au_branch *br;
3186+ struct au_xino_file *xi;
3187+
3188+ if (!au_sbi(sb)->si_dbgaufs)
3189+ return;
3190+
3191+ bend = au_sbend(sb);
3192+ for (; bindex <= bend; bindex++) {
3193+ br = au_sbr(sb, bindex);
3194+ xi = &br->br_xino;
3195+ if (xi->xi_dbgaufs) {
3196+ debugfs_remove(xi->xi_dbgaufs);
3197+ xi->xi_dbgaufs = NULL;
3198+ }
3199+ }
3200+}
3201+
3202+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
3203+{
3204+ struct au_sbinfo *sbinfo;
3205+ struct dentry *parent;
3206+ struct au_branch *br;
3207+ struct au_xino_file *xi;
3208+ aufs_bindex_t bend;
3209+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
3210+
3211+ sbinfo = au_sbi(sb);
3212+ parent = sbinfo->si_dbgaufs;
3213+ if (!parent)
3214+ return;
3215+
3216+ bend = au_sbend(sb);
3217+ for (; bindex <= bend; bindex++) {
3218+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
3219+ br = au_sbr(sb, bindex);
3220+ xi = &br->br_xino;
3221+ AuDebugOn(xi->xi_dbgaufs);
3222+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
3223+ sbinfo, &dbgaufs_xino_fop);
3224+ /* ignore an error */
3225+ if (unlikely(!xi->xi_dbgaufs))
3226+ AuWarn1("failed %s under debugfs\n", name);
3227+ }
3228+}
3229+
3230+/* ---------------------------------------------------------------------- */
3231+
3232+#ifdef CONFIG_AUFS_EXPORT
3233+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
3234+{
3235+ int err;
3236+ struct au_sbinfo *sbinfo;
3237+ struct super_block *sb;
3238+
3239+ sbinfo = inode->i_private;
3240+ sb = sbinfo->si_sb;
3241+ si_noflush_read_lock(sb);
3242+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
3243+ si_read_unlock(sb);
3244+ return err;
3245+}
3246+
3247+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 3248+ .owner = THIS_MODULE,
1facf9fc 3249+ .open = dbgaufs_xigen_open,
3250+ .release = dbgaufs_xi_release,
3251+ .read = dbgaufs_xi_read
3252+};
3253+
3254+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3255+{
3256+ int err;
3257+
dece6358
AM
3258+ /*
3259+ * This function is a dynamic '__init' fucntion actually,
3260+ * so the tiny check for si_rwsem is unnecessary.
3261+ */
3262+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3263+
1facf9fc 3264+ err = -EIO;
3265+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
3266+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3267+ &dbgaufs_xigen_fop);
3268+ if (sbinfo->si_dbgaufs_xigen)
3269+ err = 0;
3270+
3271+ return err;
3272+}
3273+#else
3274+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3275+{
3276+ return 0;
3277+}
3278+#endif /* CONFIG_AUFS_EXPORT */
3279+
3280+/* ---------------------------------------------------------------------- */
3281+
3282+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
3283+{
dece6358
AM
3284+ /*
3285+ * This function is a dynamic '__init' fucntion actually,
3286+ * so the tiny check for si_rwsem is unnecessary.
3287+ */
3288+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3289+
1facf9fc 3290+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
3291+ sbinfo->si_dbgaufs = NULL;
3292+ kobject_put(&sbinfo->si_kobj);
3293+}
3294+
3295+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
3296+{
3297+ int err;
3298+ char name[SysaufsSiNameLen];
3299+
dece6358
AM
3300+ /*
3301+ * This function is a dynamic '__init' fucntion actually,
3302+ * so the tiny check for si_rwsem is unnecessary.
3303+ */
3304+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3305+
1facf9fc 3306+ err = -ENOENT;
3307+ if (!dbgaufs) {
3308+ AuErr1("/debug/aufs is uninitialized\n");
3309+ goto out;
3310+ }
3311+
3312+ err = -EIO;
3313+ sysaufs_name(sbinfo, name);
3314+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
3315+ if (unlikely(!sbinfo->si_dbgaufs))
3316+ goto out;
3317+ kobject_get(&sbinfo->si_kobj);
3318+
3319+ sbinfo->si_dbgaufs_xib = debugfs_create_file
3320+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3321+ &dbgaufs_xib_fop);
3322+ if (unlikely(!sbinfo->si_dbgaufs_xib))
3323+ goto out_dir;
3324+
3325+ err = dbgaufs_xigen_init(sbinfo);
3326+ if (!err)
3327+ goto out; /* success */
3328+
4f0767ce 3329+out_dir:
1facf9fc 3330+ dbgaufs_si_fin(sbinfo);
4f0767ce 3331+out:
1facf9fc 3332+ return err;
3333+}
3334+
3335+/* ---------------------------------------------------------------------- */
3336+
3337+void dbgaufs_fin(void)
3338+{
3339+ debugfs_remove(dbgaufs);
3340+}
3341+
3342+int __init dbgaufs_init(void)
3343+{
3344+ int err;
3345+
3346+ err = -EIO;
3347+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
3348+ if (dbgaufs)
3349+ err = 0;
3350+ return err;
3351+}
7f207e10
AM
3352diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
3353--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
3354+++ linux/fs/aufs/dbgaufs.h 2010-11-22 11:52:56.983894369 +0100
4a4d8108 3355@@ -0,0 +1,52 @@
1facf9fc 3356+/*
4a4d8108 3357+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3358+ *
3359+ * This program, aufs is free software; you can redistribute it and/or modify
3360+ * it under the terms of the GNU General Public License as published by
3361+ * the Free Software Foundation; either version 2 of the License, or
3362+ * (at your option) any later version.
dece6358
AM
3363+ *
3364+ * This program is distributed in the hope that it will be useful,
3365+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3367+ * GNU General Public License for more details.
3368+ *
3369+ * You should have received a copy of the GNU General Public License
3370+ * along with this program; if not, write to the Free Software
3371+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3372+ */
3373+
3374+/*
3375+ * debugfs interface
3376+ */
3377+
3378+#ifndef __DBGAUFS_H__
3379+#define __DBGAUFS_H__
3380+
3381+#ifdef __KERNEL__
3382+
dece6358 3383+#include <linux/init.h>
1facf9fc 3384+#include <linux/aufs_type.h>
3385+
dece6358 3386+struct super_block;
1facf9fc 3387+struct au_sbinfo;
dece6358 3388+
1facf9fc 3389+#ifdef CONFIG_DEBUG_FS
3390+/* dbgaufs.c */
3391+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
3392+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
3393+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
3394+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
3395+void dbgaufs_fin(void);
3396+int __init dbgaufs_init(void);
1facf9fc 3397+#else
4a4d8108
AM
3398+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
3399+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
3400+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
3401+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
3402+AuStubVoid(dbgaufs_fin, void)
3403+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 3404+#endif /* CONFIG_DEBUG_FS */
3405+
3406+#endif /* __KERNEL__ */
3407+#endif /* __DBGAUFS_H__ */
7f207e10
AM
3408diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
3409--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
3410+++ linux/fs/aufs/dcsub.c 2010-11-22 11:52:56.983894369 +0100
4a4d8108 3411@@ -0,0 +1,200 @@
1facf9fc 3412+/*
4a4d8108 3413+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3414+ *
3415+ * This program, aufs is free software; you can redistribute it and/or modify
3416+ * it under the terms of the GNU General Public License as published by
3417+ * the Free Software Foundation; either version 2 of the License, or
3418+ * (at your option) any later version.
dece6358
AM
3419+ *
3420+ * This program is distributed in the hope that it will be useful,
3421+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3422+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3423+ * GNU General Public License for more details.
3424+ *
3425+ * You should have received a copy of the GNU General Public License
3426+ * along with this program; if not, write to the Free Software
3427+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3428+ */
3429+
3430+/*
3431+ * sub-routines for dentry cache
3432+ */
3433+
3434+#include "aufs.h"
3435+
3436+static void au_dpage_free(struct au_dpage *dpage)
3437+{
3438+ int i;
3439+ struct dentry **p;
3440+
3441+ p = dpage->dentries;
3442+ for (i = 0; i < dpage->ndentry; i++)
3443+ dput(*p++);
3444+ free_page((unsigned long)dpage->dentries);
3445+}
3446+
3447+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
3448+{
3449+ int err;
3450+ void *p;
3451+
3452+ err = -ENOMEM;
3453+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
3454+ if (unlikely(!dpages->dpages))
3455+ goto out;
3456+
3457+ p = (void *)__get_free_page(gfp);
3458+ if (unlikely(!p))
3459+ goto out_dpages;
3460+
3461+ dpages->dpages[0].ndentry = 0;
3462+ dpages->dpages[0].dentries = p;
3463+ dpages->ndpage = 1;
3464+ return 0; /* success */
3465+
4f0767ce 3466+out_dpages:
1facf9fc 3467+ kfree(dpages->dpages);
4f0767ce 3468+out:
1facf9fc 3469+ return err;
3470+}
3471+
3472+void au_dpages_free(struct au_dcsub_pages *dpages)
3473+{
3474+ int i;
3475+ struct au_dpage *p;
3476+
3477+ p = dpages->dpages;
3478+ for (i = 0; i < dpages->ndpage; i++)
3479+ au_dpage_free(p++);
3480+ kfree(dpages->dpages);
3481+}
3482+
3483+static int au_dpages_append(struct au_dcsub_pages *dpages,
3484+ struct dentry *dentry, gfp_t gfp)
3485+{
3486+ int err, sz;
3487+ struct au_dpage *dpage;
3488+ void *p;
3489+
3490+ dpage = dpages->dpages + dpages->ndpage - 1;
3491+ sz = PAGE_SIZE / sizeof(dentry);
3492+ if (unlikely(dpage->ndentry >= sz)) {
3493+ AuLabel(new dpage);
3494+ err = -ENOMEM;
3495+ sz = dpages->ndpage * sizeof(*dpages->dpages);
3496+ p = au_kzrealloc(dpages->dpages, sz,
3497+ sz + sizeof(*dpages->dpages), gfp);
3498+ if (unlikely(!p))
3499+ goto out;
3500+
3501+ dpages->dpages = p;
3502+ dpage = dpages->dpages + dpages->ndpage;
3503+ p = (void *)__get_free_page(gfp);
3504+ if (unlikely(!p))
3505+ goto out;
3506+
3507+ dpage->ndentry = 0;
3508+ dpage->dentries = p;
3509+ dpages->ndpage++;
3510+ }
3511+
3512+ dpage->dentries[dpage->ndentry++] = dget(dentry);
3513+ return 0; /* success */
3514+
4f0767ce 3515+out:
1facf9fc 3516+ return err;
3517+}
3518+
3519+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3520+ au_dpages_test test, void *arg)
3521+{
3522+ int err;
3523+ struct dentry *this_parent = root;
3524+ struct list_head *next;
3525+ struct super_block *sb = root->d_sb;
3526+
3527+ err = 0;
3528+ spin_lock(&dcache_lock);
4f0767ce 3529+repeat:
1facf9fc 3530+ next = this_parent->d_subdirs.next;
4f0767ce 3531+resume:
1facf9fc 3532+ if (this_parent->d_sb == sb
3533+ && !IS_ROOT(this_parent)
3534+ && atomic_read(&this_parent->d_count)
3535+ && this_parent->d_inode
3536+ && (!test || test(this_parent, arg))) {
3537+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3538+ if (unlikely(err))
3539+ goto out;
3540+ }
3541+
3542+ while (next != &this_parent->d_subdirs) {
3543+ struct list_head *tmp = next;
3544+ struct dentry *dentry = list_entry(tmp, struct dentry,
3545+ d_u.d_child);
3546+ next = tmp->next;
3547+ if (/*d_unhashed(dentry) || */!dentry->d_inode)
3548+ continue;
3549+ if (!list_empty(&dentry->d_subdirs)) {
3550+ this_parent = dentry;
3551+ goto repeat;
3552+ }
3553+ if (dentry->d_sb == sb
3554+ && atomic_read(&dentry->d_count)
3555+ && (!test || test(dentry, arg))) {
3556+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3557+ if (unlikely(err))
3558+ goto out;
3559+ }
3560+ }
3561+
3562+ if (this_parent != root) {
3563+ next = this_parent->d_u.d_child.next;
3564+ this_parent = this_parent->d_parent; /* dcache_lock is locked */
3565+ goto resume;
3566+ }
4f0767ce 3567+out:
1facf9fc 3568+ spin_unlock(&dcache_lock);
3569+ return err;
3570+}
3571+
3572+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3573+ int do_include, au_dpages_test test, void *arg)
3574+{
3575+ int err;
3576+
3577+ err = 0;
3578+ spin_lock(&dcache_lock);
3579+ if (do_include && (!test || test(dentry, arg))) {
3580+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3581+ if (unlikely(err))
3582+ goto out;
3583+ }
3584+ while (!IS_ROOT(dentry)) {
3585+ dentry = dentry->d_parent; /* dcache_lock is locked */
3586+ if (!test || test(dentry, arg)) {
3587+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3588+ if (unlikely(err))
3589+ break;
3590+ }
3591+ }
3592+
4f0767ce 3593+out:
1facf9fc 3594+ spin_unlock(&dcache_lock);
3595+
3596+ return err;
3597+}
3598+
4a4d8108 3599+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 3600+{
4a4d8108
AM
3601+ struct path path[2] = {
3602+ {
3603+ .dentry = d1
3604+ },
3605+ {
3606+ .dentry = d2
3607+ }
3608+ };
1facf9fc 3609+
4a4d8108 3610+ return path_is_under(path + 0, path + 1);
1facf9fc 3611+}
7f207e10
AM
3612diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
3613--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
3614+++ linux/fs/aufs/dcsub.h 2010-11-22 11:52:56.983894369 +0100
3615@@ -0,0 +1,63 @@
1facf9fc 3616+/*
4a4d8108 3617+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3618+ *
3619+ * This program, aufs is free software; you can redistribute it and/or modify
3620+ * it under the terms of the GNU General Public License as published by
3621+ * the Free Software Foundation; either version 2 of the License, or
3622+ * (at your option) any later version.
dece6358
AM
3623+ *
3624+ * This program is distributed in the hope that it will be useful,
3625+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3626+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3627+ * GNU General Public License for more details.
3628+ *
3629+ * You should have received a copy of the GNU General Public License
3630+ * along with this program; if not, write to the Free Software
3631+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3632+ */
3633+
3634+/*
3635+ * sub-routines for dentry cache
3636+ */
3637+
3638+#ifndef __AUFS_DCSUB_H__
3639+#define __AUFS_DCSUB_H__
3640+
3641+#ifdef __KERNEL__
3642+
7f207e10 3643+#include <linux/dcache.h>
dece6358
AM
3644+#include <linux/types.h>
3645+
3646+struct dentry;
1facf9fc 3647+
3648+struct au_dpage {
3649+ int ndentry;
3650+ struct dentry **dentries;
3651+};
3652+
3653+struct au_dcsub_pages {
3654+ int ndpage;
3655+ struct au_dpage *dpages;
3656+};
3657+
3658+/* ---------------------------------------------------------------------- */
3659+
7f207e10 3660+/* dcsub.c */
1facf9fc 3661+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3662+void au_dpages_free(struct au_dcsub_pages *dpages);
3663+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3664+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3665+ au_dpages_test test, void *arg);
3666+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3667+ int do_include, au_dpages_test test, void *arg);
4a4d8108 3668+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 3669+
7f207e10
AM
3670+/* ---------------------------------------------------------------------- */
3671+
3672+static inline int au_d_removed(struct dentry *d)
3673+{
3674+ return !IS_ROOT(d) && d_unhashed(d);
3675+}
3676+
1facf9fc 3677+#endif /* __KERNEL__ */
3678+#endif /* __AUFS_DCSUB_H__ */
7f207e10
AM
3679diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
3680--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
3681+++ linux/fs/aufs/debug.c 2010-11-22 11:52:56.983894369 +0100
3682@@ -0,0 +1,429 @@
1facf9fc 3683+/*
4a4d8108 3684+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3685+ *
3686+ * This program, aufs is free software; you can redistribute it and/or modify
3687+ * it under the terms of the GNU General Public License as published by
3688+ * the Free Software Foundation; either version 2 of the License, or
3689+ * (at your option) any later version.
dece6358
AM
3690+ *
3691+ * This program is distributed in the hope that it will be useful,
3692+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3693+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3694+ * GNU General Public License for more details.
3695+ *
3696+ * You should have received a copy of the GNU General Public License
3697+ * along with this program; if not, write to the Free Software
3698+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3699+ */
3700+
3701+/*
3702+ * debug print functions
3703+ */
3704+
dece6358 3705+#include <linux/module.h>
7f207e10 3706+#include <linux/vt_kern.h>
1facf9fc 3707+#include "aufs.h"
3708+
3709+int aufs_debug;
3710+MODULE_PARM_DESC(debug, "debug print");
3711+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
3712+
3713+char *au_plevel = KERN_DEBUG;
e49829fe
JR
3714+#define dpri(fmt, ...) do { \
3715+ if ((au_plevel \
3716+ && strcmp(au_plevel, KERN_DEBUG)) \
3717+ || au_debug_test()) \
3718+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 3719+} while (0)
3720+
3721+/* ---------------------------------------------------------------------- */
3722+
3723+void au_dpri_whlist(struct au_nhash *whlist)
3724+{
3725+ unsigned long ul, n;
3726+ struct hlist_head *head;
3727+ struct au_vdir_wh *tpos;
3728+ struct hlist_node *pos;
3729+
3730+ n = whlist->nh_num;
3731+ head = whlist->nh_head;
3732+ for (ul = 0; ul < n; ul++) {
3733+ hlist_for_each_entry(tpos, pos, head, wh_hash)
3734+ dpri("b%d, %.*s, %d\n",
3735+ tpos->wh_bindex,
3736+ tpos->wh_str.len, tpos->wh_str.name,
3737+ tpos->wh_str.len);
3738+ head++;
3739+ }
3740+}
3741+
3742+void au_dpri_vdir(struct au_vdir *vdir)
3743+{
3744+ unsigned long ul;
3745+ union au_vdir_deblk_p p;
3746+ unsigned char *o;
3747+
3748+ if (!vdir || IS_ERR(vdir)) {
3749+ dpri("err %ld\n", PTR_ERR(vdir));
3750+ return;
3751+ }
3752+
3753+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
3754+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
3755+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
3756+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
3757+ p.deblk = vdir->vd_deblk[ul];
3758+ o = p.deblk;
3759+ dpri("[%lu]: %p\n", ul, o);
3760+ }
3761+}
3762+
3763+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3764+ struct dentry *wh)
3765+{
3766+ char *n = NULL;
3767+ int l = 0;
3768+
3769+ if (!inode || IS_ERR(inode)) {
3770+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3771+ return -1;
3772+ }
3773+
3774+ /* the type of i_blocks depends upon CONFIG_LSF */
3775+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3776+ && sizeof(inode->i_blocks) != sizeof(u64));
3777+ if (wh) {
3778+ n = (void *)wh->d_name.name;
3779+ l = wh->d_name.len;
3780+ }
3781+
3782+ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
b752ccd1 3783+ " ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
1facf9fc 3784+ bindex,
3785+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3786+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3787+ i_size_read(inode), (unsigned long long)inode->i_blocks,
3788+ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3789+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
3790+ inode->i_state, inode->i_flags, inode->i_version,
3791+ inode->i_generation,
1facf9fc 3792+ l ? ", wh " : "", l, n);
3793+ return 0;
3794+}
3795+
3796+void au_dpri_inode(struct inode *inode)
3797+{
3798+ struct au_iinfo *iinfo;
3799+ aufs_bindex_t bindex;
3800+ int err;
3801+
3802+ err = do_pri_inode(-1, inode, NULL);
3803+ if (err || !au_test_aufs(inode->i_sb))
3804+ return;
3805+
3806+ iinfo = au_ii(inode);
3807+ if (!iinfo)
3808+ return;
3809+ dpri("i-1: bstart %d, bend %d, gen %d\n",
3810+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
3811+ if (iinfo->ii_bstart < 0)
3812+ return;
3813+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
3814+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
3815+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
3816+}
3817+
3818+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
3819+{
3820+ struct dentry *wh = NULL;
3821+
3822+ if (!dentry || IS_ERR(dentry)) {
3823+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
3824+ return -1;
3825+ }
3826+ /* do not call dget_parent() here */
3827+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
3828+ bindex,
3829+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
3830+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
3831+ atomic_read(&dentry->d_count), dentry->d_flags);
3832+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
3833+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
3834+ if (iinfo)
3835+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
3836+ }
3837+ do_pri_inode(bindex, dentry->d_inode, wh);
3838+ return 0;
3839+}
3840+
3841+void au_dpri_dentry(struct dentry *dentry)
3842+{
3843+ struct au_dinfo *dinfo;
3844+ aufs_bindex_t bindex;
3845+ int err;
4a4d8108 3846+ struct au_hdentry *hdp;
1facf9fc 3847+
3848+ err = do_pri_dentry(-1, dentry);
3849+ if (err || !au_test_aufs(dentry->d_sb))
3850+ return;
3851+
3852+ dinfo = au_di(dentry);
3853+ if (!dinfo)
3854+ return;
3855+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
3856+ dinfo->di_bstart, dinfo->di_bend,
3857+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
3858+ if (dinfo->di_bstart < 0)
3859+ return;
4a4d8108 3860+ hdp = dinfo->di_hdentry;
1facf9fc 3861+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 3862+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 3863+}
3864+
3865+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
3866+{
3867+ char a[32];
3868+
3869+ if (!file || IS_ERR(file)) {
3870+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
3871+ return -1;
3872+ }
3873+ a[0] = 0;
3874+ if (bindex < 0
3875+ && file->f_dentry
3876+ && au_test_aufs(file->f_dentry->d_sb)
3877+ && au_fi(file))
e49829fe
JR
3878+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
3879+ au_figen(file), !!au_fi(file)->fi_hvmop);
b752ccd1 3880+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 3881+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 3882+ file->f_version, file->f_pos, a);
1facf9fc 3883+ if (file->f_dentry)
3884+ do_pri_dentry(bindex, file->f_dentry);
3885+ return 0;
3886+}
3887+
3888+void au_dpri_file(struct file *file)
3889+{
3890+ struct au_finfo *finfo;
4a4d8108
AM
3891+ struct au_fidir *fidir;
3892+ struct au_hfile *hfile;
1facf9fc 3893+ aufs_bindex_t bindex;
3894+ int err;
3895+
3896+ err = do_pri_file(-1, file);
3897+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
3898+ return;
3899+
3900+ finfo = au_fi(file);
3901+ if (!finfo)
3902+ return;
4a4d8108 3903+ if (finfo->fi_btop < 0)
1facf9fc 3904+ return;
4a4d8108
AM
3905+ fidir = finfo->fi_hdir;
3906+ if (!fidir)
3907+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
3908+ else
e49829fe
JR
3909+ for (bindex = finfo->fi_btop;
3910+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
3911+ bindex++) {
3912+ hfile = fidir->fd_hfile + bindex;
3913+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
3914+ }
1facf9fc 3915+}
3916+
3917+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
3918+{
3919+ struct vfsmount *mnt;
3920+ struct super_block *sb;
3921+
3922+ if (!br || IS_ERR(br))
3923+ goto out;
3924+ mnt = br->br_mnt;
3925+ if (!mnt || IS_ERR(mnt))
3926+ goto out;
3927+ sb = mnt->mnt_sb;
3928+ if (!sb || IS_ERR(sb))
3929+ goto out;
3930+
3931+ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
b752ccd1 3932+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 3933+ "xino %d\n",
3934+ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
3935+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 3936+ sb->s_flags, sb->s_count,
1facf9fc 3937+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
3938+ return 0;
3939+
4f0767ce 3940+out:
1facf9fc 3941+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
3942+ return -1;
3943+}
3944+
3945+void au_dpri_sb(struct super_block *sb)
3946+{
3947+ struct au_sbinfo *sbinfo;
3948+ aufs_bindex_t bindex;
3949+ int err;
3950+ /* to reuduce stack size */
3951+ struct {
3952+ struct vfsmount mnt;
3953+ struct au_branch fake;
3954+ } *a;
3955+
3956+ /* this function can be called from magic sysrq */
3957+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
3958+ if (unlikely(!a)) {
3959+ dpri("no memory\n");
3960+ return;
3961+ }
3962+
3963+ a->mnt.mnt_sb = sb;
3964+ a->fake.br_perm = 0;
3965+ a->fake.br_mnt = &a->mnt;
3966+ a->fake.br_xino.xi_file = NULL;
3967+ atomic_set(&a->fake.br_count, 0);
3968+ smp_mb(); /* atomic_set */
3969+ err = do_pri_br(-1, &a->fake);
3970+ kfree(a);
3971+ dpri("dev 0x%x\n", sb->s_dev);
3972+ if (err || !au_test_aufs(sb))
3973+ return;
3974+
3975+ sbinfo = au_sbi(sb);
3976+ if (!sbinfo)
3977+ return;
3978+ dpri("nw %d, gen %u, kobj %d\n",
3979+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
3980+ atomic_read(&sbinfo->si_kobj.kref.refcount));
3981+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
3982+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
3983+}
3984+
3985+/* ---------------------------------------------------------------------- */
3986+
3987+void au_dbg_sleep_jiffy(int jiffy)
3988+{
3989+ while (jiffy)
3990+ jiffy = schedule_timeout_uninterruptible(jiffy);
3991+}
3992+
3993+void au_dbg_iattr(struct iattr *ia)
3994+{
3995+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
3996+ dpri(#name "\n")
3997+ AuBit(MODE);
3998+ AuBit(UID);
3999+ AuBit(GID);
4000+ AuBit(SIZE);
4001+ AuBit(ATIME);
4002+ AuBit(MTIME);
4003+ AuBit(CTIME);
4004+ AuBit(ATIME_SET);
4005+ AuBit(MTIME_SET);
4006+ AuBit(FORCE);
4007+ AuBit(ATTR_FLAG);
4008+ AuBit(KILL_SUID);
4009+ AuBit(KILL_SGID);
4010+ AuBit(FILE);
4011+ AuBit(KILL_PRIV);
4012+ AuBit(OPEN);
4013+ AuBit(TIMES_SET);
4014+#undef AuBit
4015+ dpri("ia_file %p\n", ia->ia_file);
4016+}
4017+
4018+/* ---------------------------------------------------------------------- */
4019+
4020+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
4021+{
4022+ struct dentry *parent;
4023+
4024+ parent = dget_parent(dentry);
4025+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
4026+ || IS_ROOT(dentry)
4027+ || au_digen(parent) != sigen);
4028+ dput(parent);
4029+}
4030+
4031+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
4032+{
4033+ struct dentry *parent;
4034+
4035+ parent = dget_parent(dentry);
4036+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
4037+ || au_digen(parent) != sigen);
4038+ dput(parent);
4039+}
4040+
4041+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
4042+{
4043+ int err, i, j;
4044+ struct au_dcsub_pages dpages;
4045+ struct au_dpage *dpage;
4046+ struct dentry **dentries;
4047+
4048+ err = au_dpages_init(&dpages, GFP_NOFS);
4049+ AuDebugOn(err);
4050+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
4051+ AuDebugOn(err);
4052+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
4053+ dpage = dpages.dpages + i;
4054+ dentries = dpage->dentries;
4055+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
4056+ AuDebugOn(au_digen(dentries[j]) != sigen);
4057+ }
4058+ au_dpages_free(&dpages);
4059+}
4060+
1facf9fc 4061+void au_dbg_verify_kthread(void)
4062+{
7f207e10 4063+ if (current->flags & PF_WQ_WORKER) {
1facf9fc 4064+ au_dbg_blocked();
7f207e10 4065+ WARN_ON(1);
1facf9fc 4066+ }
4067+}
4068+
4069+/* ---------------------------------------------------------------------- */
4070+
4071+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
4072+{
4073+#ifdef AuForceNoPlink
4074+ au_opt_clr(sbinfo->si_mntflags, PLINK);
4075+#endif
4076+#ifdef AuForceNoXino
4077+ au_opt_clr(sbinfo->si_mntflags, XINO);
4078+#endif
4079+#ifdef AuForceNoRefrof
4080+ au_opt_clr(sbinfo->si_mntflags, REFROF);
4081+#endif
4a4d8108
AM
4082+#ifdef AuForceHnotify
4083+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 4084+#endif
1308ab2a 4085+#ifdef AuForceRd0
4086+ sbinfo->si_rdblk = 0;
4087+ sbinfo->si_rdhash = 0;
4088+#endif
1facf9fc 4089+}
4090+
4091+int __init au_debug_init(void)
4092+{
4093+ aufs_bindex_t bindex;
4094+ struct au_vdir_destr destr;
4095+
4096+ bindex = -1;
4097+ AuDebugOn(bindex >= 0);
4098+
4099+ destr.len = -1;
4100+ AuDebugOn(destr.len < NAME_MAX);
4101+
4102+#ifdef CONFIG_4KSTACKS
4a4d8108 4103+ pr_warning("CONFIG_4KSTACKS is defined.\n");
1facf9fc 4104+#endif
4105+
4106+#ifdef AuForceNoBrs
4107+ sysaufs_brs = 0;
4108+#endif
4109+
4110+ return 0;
4111+}
7f207e10
AM
4112diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
4113--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
4114+++ linux/fs/aufs/debug.h 2010-11-22 11:52:56.983894369 +0100
4115@@ -0,0 +1,242 @@
1facf9fc 4116+/*
4a4d8108 4117+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4118+ *
4119+ * This program, aufs is free software; you can redistribute it and/or modify
4120+ * it under the terms of the GNU General Public License as published by
4121+ * the Free Software Foundation; either version 2 of the License, or
4122+ * (at your option) any later version.
dece6358
AM
4123+ *
4124+ * This program is distributed in the hope that it will be useful,
4125+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4126+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4127+ * GNU General Public License for more details.
4128+ *
4129+ * You should have received a copy of the GNU General Public License
4130+ * along with this program; if not, write to the Free Software
4131+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4132+ */
4133+
4134+/*
4135+ * debug print functions
4136+ */
4137+
4138+#ifndef __AUFS_DEBUG_H__
4139+#define __AUFS_DEBUG_H__
4140+
4141+#ifdef __KERNEL__
4142+
1308ab2a 4143+#include <asm/system.h>
dece6358 4144+#include <linux/bug.h>
7f207e10 4145+/* #include <linux/err.h> */
1308ab2a 4146+#include <linux/init.h>
4a4d8108
AM
4147+#include <linux/module.h>
4148+#include <linux/kallsyms.h>
7f207e10 4149+/* #include <linux/kernel.h> */
1facf9fc 4150+#include <linux/delay.h>
7f207e10 4151+/* #include <linux/kd.h> */
1facf9fc 4152+#include <linux/sysrq.h>
4153+#include <linux/aufs_type.h>
4154+
4a4d8108
AM
4155+#include <asm/system.h>
4156+
1facf9fc 4157+#ifdef CONFIG_AUFS_DEBUG
4158+#define AuDebugOn(a) BUG_ON(a)
4159+
4160+/* module parameter */
4161+extern int aufs_debug;
4162+static inline void au_debug(int n)
4163+{
4164+ aufs_debug = n;
4165+ smp_mb();
4166+}
4167+
4168+static inline int au_debug_test(void)
4169+{
4170+ return aufs_debug;
4171+}
4172+#else
4173+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
4174+AuStubVoid(au_debug, int n)
4175+AuStubInt0(au_debug_test, void)
1facf9fc 4176+#endif /* CONFIG_AUFS_DEBUG */
4177+
4178+/* ---------------------------------------------------------------------- */
4179+
4180+/* debug print */
4181+
4a4d8108 4182+#define AuDbg(fmt, ...) do { \
1facf9fc 4183+ if (au_debug_test()) \
4a4d8108 4184+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 4185+} while (0)
4a4d8108
AM
4186+#define AuLabel(l) AuDbg(#l "\n")
4187+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
4188+#define AuWarn1(fmt, ...) do { \
1facf9fc 4189+ static unsigned char _c; \
4190+ if (!_c++) \
4a4d8108 4191+ pr_warning(fmt, ##__VA_ARGS__); \
1facf9fc 4192+} while (0)
4193+
4a4d8108 4194+#define AuErr1(fmt, ...) do { \
1facf9fc 4195+ static unsigned char _c; \
4196+ if (!_c++) \
4a4d8108 4197+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 4198+} while (0)
4199+
4a4d8108 4200+#define AuIOErr1(fmt, ...) do { \
1facf9fc 4201+ static unsigned char _c; \
4202+ if (!_c++) \
4a4d8108 4203+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 4204+} while (0)
4205+
4206+#define AuUnsupportMsg "This operation is not supported." \
4207+ " Please report this application to aufs-users ML."
4a4d8108
AM
4208+#define AuUnsupport(fmt, ...) do { \
4209+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 4210+ dump_stack(); \
4211+} while (0)
4212+
4213+#define AuTraceErr(e) do { \
4214+ if (unlikely((e) < 0)) \
4215+ AuDbg("err %d\n", (int)(e)); \
4216+} while (0)
4217+
4218+#define AuTraceErrPtr(p) do { \
4219+ if (IS_ERR(p)) \
4220+ AuDbg("err %ld\n", PTR_ERR(p)); \
4221+} while (0)
4222+
4223+/* dirty macros for debug print, use with "%.*s" and caution */
4224+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
4225+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
4226+
4227+/* ---------------------------------------------------------------------- */
4228+
4229+struct au_sbinfo;
4230+struct au_finfo;
dece6358 4231+struct dentry;
1facf9fc 4232+#ifdef CONFIG_AUFS_DEBUG
4233+extern char *au_plevel;
4234+struct au_nhash;
4235+void au_dpri_whlist(struct au_nhash *whlist);
4236+struct au_vdir;
4237+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 4238+struct inode;
1facf9fc 4239+void au_dpri_inode(struct inode *inode);
4240+void au_dpri_dentry(struct dentry *dentry);
dece6358 4241+struct file;
1facf9fc 4242+void au_dpri_file(struct file *filp);
dece6358 4243+struct super_block;
1facf9fc 4244+void au_dpri_sb(struct super_block *sb);
4245+
4246+void au_dbg_sleep_jiffy(int jiffy);
dece6358 4247+struct iattr;
1facf9fc 4248+void au_dbg_iattr(struct iattr *ia);
4249+
4250+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
4251+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
4252+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 4253+void au_dbg_verify_kthread(void);
4254+
4255+int __init au_debug_init(void);
4256+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
4257+#define AuDbgWhlist(w) do { \
4258+ AuDbg(#w "\n"); \
4259+ au_dpri_whlist(w); \
4260+} while (0)
4261+
4262+#define AuDbgVdir(v) do { \
4263+ AuDbg(#v "\n"); \
4264+ au_dpri_vdir(v); \
4265+} while (0)
4266+
4267+#define AuDbgInode(i) do { \
4268+ AuDbg(#i "\n"); \
4269+ au_dpri_inode(i); \
4270+} while (0)
4271+
4272+#define AuDbgDentry(d) do { \
4273+ AuDbg(#d "\n"); \
4274+ au_dpri_dentry(d); \
4275+} while (0)
4276+
4277+#define AuDbgFile(f) do { \
4278+ AuDbg(#f "\n"); \
4279+ au_dpri_file(f); \
4280+} while (0)
4281+
4282+#define AuDbgSb(sb) do { \
4283+ AuDbg(#sb "\n"); \
4284+ au_dpri_sb(sb); \
4285+} while (0)
4286+
4287+#define AuDbgSleep(sec) do { \
4288+ AuDbg("sleep %d sec\n", sec); \
4289+ ssleep(sec); \
4290+} while (0)
4291+
4292+#define AuDbgSleepJiffy(jiffy) do { \
4293+ AuDbg("sleep %d jiffies\n", jiffy); \
4294+ au_dbg_sleep_jiffy(jiffy); \
4295+} while (0)
4296+
4297+#define AuDbgIAttr(ia) do { \
4298+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
4299+ au_dbg_iattr(ia); \
4300+} while (0)
4a4d8108
AM
4301+
4302+#define AuDbgSym(addr) do { \
4303+ char sym[KSYM_SYMBOL_LEN]; \
4304+ sprint_symbol(sym, (unsigned long)addr); \
4305+ AuDbg("%s\n", sym); \
4306+} while (0)
4307+
4308+#define AuInfoSym(addr) do { \
4309+ char sym[KSYM_SYMBOL_LEN]; \
4310+ sprint_symbol(sym, (unsigned long)addr); \
4311+ AuInfo("%s\n", sym); \
4312+} while (0)
1facf9fc 4313+#else
4a4d8108
AM
4314+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
4315+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
4316+ unsigned int sigen)
4317+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
4318+AuStubVoid(au_dbg_verify_kthread, void)
4319+AuStubInt0(__init au_debug_init, void)
4320+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 4321+
1facf9fc 4322+#define AuDbgWhlist(w) do {} while (0)
4323+#define AuDbgVdir(v) do {} while (0)
4324+#define AuDbgInode(i) do {} while (0)
4325+#define AuDbgDentry(d) do {} while (0)
4326+#define AuDbgFile(f) do {} while (0)
4327+#define AuDbgSb(sb) do {} while (0)
4328+#define AuDbgSleep(sec) do {} while (0)
4329+#define AuDbgSleepJiffy(jiffy) do {} while (0)
4330+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
4331+#define AuDbgSym(addr) do {} while (0)
4332+#define AuInfoSym(addr) do {} while (0)
1facf9fc 4333+#endif /* CONFIG_AUFS_DEBUG */
4334+
4335+/* ---------------------------------------------------------------------- */
4336+
4337+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
4338+int __init au_sysrq_init(void);
4339+void au_sysrq_fin(void);
4340+
4341+#ifdef CONFIG_HW_CONSOLE
4342+#define au_dbg_blocked() do { \
4343+ WARN_ON(1); \
0c5527e5 4344+ handle_sysrq('w'); \
1facf9fc 4345+} while (0)
4346+#else
4a4d8108 4347+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4348+#endif
4349+
4350+#else
4a4d8108
AM
4351+AuStubInt0(__init au_sysrq_init, void)
4352+AuStubVoid(au_sysrq_fin, void)
4353+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4354+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
4355+
4356+#endif /* __KERNEL__ */
4357+#endif /* __AUFS_DEBUG_H__ */
7f207e10
AM
4358diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
4359--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
4360+++ linux/fs/aufs/dentry.c 2010-11-22 11:52:56.983894369 +0100
4361@@ -0,0 +1,863 @@
1facf9fc 4362+/*
4a4d8108 4363+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4364+ *
4365+ * This program, aufs is free software; you can redistribute it and/or modify
4366+ * it under the terms of the GNU General Public License as published by
4367+ * the Free Software Foundation; either version 2 of the License, or
4368+ * (at your option) any later version.
dece6358
AM
4369+ *
4370+ * This program is distributed in the hope that it will be useful,
4371+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4372+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4373+ * GNU General Public License for more details.
4374+ *
4375+ * You should have received a copy of the GNU General Public License
4376+ * along with this program; if not, write to the Free Software
4377+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4378+ */
4379+
4380+/*
4381+ * lookup and dentry operations
4382+ */
4383+
dece6358 4384+#include <linux/namei.h>
1facf9fc 4385+#include "aufs.h"
4386+
4387+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
4388+{
4389+ if (nd) {
4390+ *h_nd = *nd;
4391+
4392+ /*
4393+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
4394+ * due to whiteout and branch permission.
4395+ */
4396+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
b752ccd1 4397+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
1facf9fc 4398+ /* unnecessary? */
4399+ h_nd->intent.open.file = NULL;
4400+ } else
4401+ memset(h_nd, 0, sizeof(*h_nd));
4402+}
4403+
4404+struct au_lkup_one_args {
4405+ struct dentry **errp;
4406+ struct qstr *name;
4407+ struct dentry *h_parent;
4408+ struct au_branch *br;
4409+ struct nameidata *nd;
4410+};
4411+
4412+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
4413+ struct au_branch *br, struct nameidata *nd)
4414+{
4415+ struct dentry *h_dentry;
4416+ int err;
4417+ struct nameidata h_nd;
4418+
4419+ if (au_test_fs_null_nd(h_parent->d_sb))
4420+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
4421+
4422+ au_h_nd(&h_nd, nd);
4423+ h_nd.path.dentry = h_parent;
4424+ h_nd.path.mnt = br->br_mnt;
4425+
4426+ err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
4427+ h_dentry = ERR_PTR(err);
4428+ if (!err) {
4429+ path_get(&h_nd.path);
4430+ h_dentry = vfsub_lookup_hash(&h_nd);
4431+ path_put(&h_nd.path);
4432+ }
4433+
4a4d8108 4434+ AuTraceErrPtr(h_dentry);
1facf9fc 4435+ return h_dentry;
4436+}
4437+
4438+static void au_call_lkup_one(void *args)
4439+{
4440+ struct au_lkup_one_args *a = args;
4441+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
4442+}
4443+
4444+#define AuLkup_ALLOW_NEG 1
4445+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
7f207e10
AM
4446+#define au_fset_lkup(flags, name) \
4447+ do { (flags) |= AuLkup_##name; } while (0)
4448+#define au_fclr_lkup(flags, name) \
4449+ do { (flags) &= ~AuLkup_##name; } while (0)
1facf9fc 4450+
4451+struct au_do_lookup_args {
4452+ unsigned int flags;
4453+ mode_t type;
4454+ struct nameidata *nd;
4455+};
4456+
4457+/*
4458+ * returns positive/negative dentry, NULL or an error.
4459+ * NULL means whiteout-ed or not-found.
4460+ */
4461+static struct dentry*
4462+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
4463+ aufs_bindex_t bindex, struct qstr *wh_name,
4464+ struct au_do_lookup_args *args)
4465+{
4466+ struct dentry *h_dentry;
4467+ struct inode *h_inode, *inode;
1facf9fc 4468+ struct au_branch *br;
4469+ int wh_found, opq;
4470+ unsigned char wh_able;
4471+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
4472+
1facf9fc 4473+ wh_found = 0;
4474+ br = au_sbr(dentry->d_sb, bindex);
4475+ wh_able = !!au_br_whable(br->br_perm);
4476+ if (wh_able)
4477+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
4478+ h_dentry = ERR_PTR(wh_found);
4479+ if (!wh_found)
4480+ goto real_lookup;
4481+ if (unlikely(wh_found < 0))
4482+ goto out;
4483+
4484+ /* We found a whiteout */
4485+ /* au_set_dbend(dentry, bindex); */
4486+ au_set_dbwh(dentry, bindex);
4487+ if (!allow_neg)
4488+ return NULL; /* success */
4489+
4f0767ce 4490+real_lookup:
4a4d8108 4491+ h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
1facf9fc 4492+ if (IS_ERR(h_dentry))
4493+ goto out;
4494+
4495+ h_inode = h_dentry->d_inode;
4496+ if (!h_inode) {
4497+ if (!allow_neg)
4498+ goto out_neg;
4499+ } else if (wh_found
4500+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
4501+ goto out_neg;
4502+
4503+ if (au_dbend(dentry) <= bindex)
4504+ au_set_dbend(dentry, bindex);
4505+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4506+ au_set_dbstart(dentry, bindex);
4507+ au_set_h_dptr(dentry, bindex, h_dentry);
4508+
4509+ inode = dentry->d_inode;
4510+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4511+ || (inode && !S_ISDIR(inode->i_mode)))
4512+ goto out; /* success */
4513+
4514+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4515+ opq = au_diropq_test(h_dentry, br);
4516+ mutex_unlock(&h_inode->i_mutex);
4517+ if (opq > 0)
4518+ au_set_dbdiropq(dentry, bindex);
4519+ else if (unlikely(opq < 0)) {
4520+ au_set_h_dptr(dentry, bindex, NULL);
4521+ h_dentry = ERR_PTR(opq);
4522+ }
4523+ goto out;
4524+
4f0767ce 4525+out_neg:
1facf9fc 4526+ dput(h_dentry);
4527+ h_dentry = NULL;
4f0767ce 4528+out:
1facf9fc 4529+ return h_dentry;
4530+}
4531+
dece6358
AM
4532+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
4533+{
4534+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
4535+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
4536+ return -EPERM;
4537+ return 0;
4538+}
4539+
1facf9fc 4540+/*
4541+ * returns the number of lower positive dentries,
4542+ * otherwise an error.
4543+ * can be called at unlinking with @type is zero.
4544+ */
4545+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4546+ struct nameidata *nd)
4547+{
4548+ int npositive, err;
4549+ aufs_bindex_t bindex, btail, bdiropq;
4550+ unsigned char isdir;
4551+ struct qstr whname;
4552+ struct au_do_lookup_args args = {
4553+ .flags = 0,
4554+ .type = type,
4555+ .nd = nd
4556+ };
4557+ const struct qstr *name = &dentry->d_name;
4558+ struct dentry *parent;
4559+ struct inode *inode;
4560+
dece6358
AM
4561+ err = au_test_shwh(dentry->d_sb, name);
4562+ if (unlikely(err))
1facf9fc 4563+ goto out;
4564+
4565+ err = au_wh_name_alloc(&whname, name);
4566+ if (unlikely(err))
4567+ goto out;
4568+
4569+ inode = dentry->d_inode;
4570+ isdir = !!(inode && S_ISDIR(inode->i_mode));
4571+ if (!type)
4572+ au_fset_lkup(args.flags, ALLOW_NEG);
4573+
4574+ npositive = 0;
4a4d8108 4575+ parent = dget_parent(dentry);
1facf9fc 4576+ btail = au_dbtaildir(parent);
4577+ for (bindex = bstart; bindex <= btail; bindex++) {
4578+ struct dentry *h_parent, *h_dentry;
4579+ struct inode *h_inode, *h_dir;
4580+
4581+ h_dentry = au_h_dptr(dentry, bindex);
4582+ if (h_dentry) {
4583+ if (h_dentry->d_inode)
4584+ npositive++;
4585+ if (type != S_IFDIR)
4586+ break;
4587+ continue;
4588+ }
4589+ h_parent = au_h_dptr(parent, bindex);
4590+ if (!h_parent)
4591+ continue;
4592+ h_dir = h_parent->d_inode;
4593+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
4594+ continue;
4595+
4596+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4597+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4598+ &args);
4599+ mutex_unlock(&h_dir->i_mutex);
4600+ err = PTR_ERR(h_dentry);
4601+ if (IS_ERR(h_dentry))
4a4d8108 4602+ goto out_parent;
1facf9fc 4603+ au_fclr_lkup(args.flags, ALLOW_NEG);
4604+
4605+ if (au_dbwh(dentry) >= 0)
4606+ break;
4607+ if (!h_dentry)
4608+ continue;
4609+ h_inode = h_dentry->d_inode;
4610+ if (!h_inode)
4611+ continue;
4612+ npositive++;
4613+ if (!args.type)
4614+ args.type = h_inode->i_mode & S_IFMT;
4615+ if (args.type != S_IFDIR)
4616+ break;
4617+ else if (isdir) {
4618+ /* the type of lower may be different */
4619+ bdiropq = au_dbdiropq(dentry);
4620+ if (bdiropq >= 0 && bdiropq <= bindex)
4621+ break;
4622+ }
4623+ }
4624+
4625+ if (npositive) {
4626+ AuLabel(positive);
4627+ au_update_dbstart(dentry);
4628+ }
4629+ err = npositive;
4630+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
4631+ && au_dbstart(dentry) < 0))
4632+ /* both of real entry and whiteout found */
4633+ err = -EIO;
4634+
4f0767ce 4635+out_parent:
4a4d8108 4636+ dput(parent);
1facf9fc 4637+ kfree(whname.name);
4f0767ce 4638+out:
1facf9fc 4639+ return err;
4640+}
4641+
4642+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4643+ struct au_branch *br)
4644+{
4645+ struct dentry *dentry;
4646+ int wkq_err;
4647+
4648+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
4649+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
4650+ else {
4651+ struct au_lkup_one_args args = {
4652+ .errp = &dentry,
4653+ .name = name,
4654+ .h_parent = parent,
4655+ .br = br,
4656+ .nd = NULL
4657+ };
4658+
4659+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
4660+ if (unlikely(wkq_err))
4661+ dentry = ERR_PTR(wkq_err);
4662+ }
4663+
4664+ return dentry;
4665+}
4666+
4667+/*
4668+ * lookup @dentry on @bindex which should be negative.
4669+ */
4670+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4671+{
4672+ int err;
4673+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 4674+
1facf9fc 4675+ parent = dget_parent(dentry);
4676+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 4677+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 4678+ au_sbr(dentry->d_sb, bindex));
4679+ err = PTR_ERR(h_dentry);
4680+ if (IS_ERR(h_dentry))
4681+ goto out;
4682+ if (unlikely(h_dentry->d_inode)) {
4683+ err = -EIO;
4684+ AuIOErr("b%d %.*s should be negative.\n",
4685+ bindex, AuDLNPair(h_dentry));
4686+ dput(h_dentry);
4687+ goto out;
4688+ }
4689+
4a4d8108 4690+ err = 0;
1facf9fc 4691+ if (bindex < au_dbstart(dentry))
4692+ au_set_dbstart(dentry, bindex);
4693+ if (au_dbend(dentry) < bindex)
4694+ au_set_dbend(dentry, bindex);
4695+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 4696+
4f0767ce 4697+out:
1facf9fc 4698+ dput(parent);
4699+ return err;
4700+}
4701+
4702+/* ---------------------------------------------------------------------- */
4703+
4704+/* subset of struct inode */
4705+struct au_iattr {
4706+ unsigned long i_ino;
4707+ /* unsigned int i_nlink; */
4708+ uid_t i_uid;
4709+ gid_t i_gid;
4710+ u64 i_version;
4711+/*
4712+ loff_t i_size;
4713+ blkcnt_t i_blocks;
4714+*/
4715+ umode_t i_mode;
4716+};
4717+
4718+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
4719+{
4720+ ia->i_ino = h_inode->i_ino;
4721+ /* ia->i_nlink = h_inode->i_nlink; */
4722+ ia->i_uid = h_inode->i_uid;
4723+ ia->i_gid = h_inode->i_gid;
4724+ ia->i_version = h_inode->i_version;
4725+/*
4726+ ia->i_size = h_inode->i_size;
4727+ ia->i_blocks = h_inode->i_blocks;
4728+*/
4729+ ia->i_mode = (h_inode->i_mode & S_IFMT);
4730+}
4731+
4732+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
4733+{
4734+ return ia->i_ino != h_inode->i_ino
4735+ /* || ia->i_nlink != h_inode->i_nlink */
4736+ || ia->i_uid != h_inode->i_uid
4737+ || ia->i_gid != h_inode->i_gid
4738+ || ia->i_version != h_inode->i_version
4739+/*
4740+ || ia->i_size != h_inode->i_size
4741+ || ia->i_blocks != h_inode->i_blocks
4742+*/
4743+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
4744+}
4745+
4746+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
4747+ struct au_branch *br)
4748+{
4749+ int err;
4750+ struct au_iattr ia;
4751+ struct inode *h_inode;
4752+ struct dentry *h_d;
4753+ struct super_block *h_sb;
4754+
4755+ err = 0;
4756+ memset(&ia, -1, sizeof(ia));
4757+ h_sb = h_dentry->d_sb;
4758+ h_inode = h_dentry->d_inode;
4759+ if (h_inode)
4760+ au_iattr_save(&ia, h_inode);
4761+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
4762+ /* nfs d_revalidate may return 0 for negative dentry */
4763+ /* fuse d_revalidate always return 0 for negative dentry */
4764+ goto out;
4765+
4766+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
4767+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
4768+ err = PTR_ERR(h_d);
4769+ if (IS_ERR(h_d))
4770+ goto out;
4771+
4772+ err = 0;
4773+ if (unlikely(h_d != h_dentry
4774+ || h_d->d_inode != h_inode
4775+ || (h_inode && au_iattr_test(&ia, h_inode))))
4776+ err = au_busy_or_stale();
4777+ dput(h_d);
4778+
4f0767ce 4779+out:
1facf9fc 4780+ AuTraceErr(err);
4781+ return err;
4782+}
4783+
4784+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
4785+ struct dentry *h_parent, struct au_branch *br)
4786+{
4787+ int err;
4788+
4789+ err = 0;
4790+ if (udba == AuOpt_UDBA_REVAL) {
4791+ IMustLock(h_dir);
4792+ err = (h_dentry->d_parent->d_inode != h_dir);
4a4d8108 4793+ } else if (udba == AuOpt_UDBA_HNOTIFY)
1facf9fc 4794+ err = au_h_verify_dentry(h_dentry, h_parent, br);
4795+
4796+ return err;
4797+}
4798+
4799+/* ---------------------------------------------------------------------- */
4800+
4801+static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
4802+ struct dentry *parent)
4803+{
4804+ struct dentry *h_d, *h_dp;
4805+ struct au_hdentry tmp, *q;
4806+ struct super_block *sb;
4807+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
4808+
1308ab2a 4809+ AuRwMustWriteLock(&dinfo->di_rwsem);
4810+
1facf9fc 4811+ bend = dinfo->di_bend;
4812+ bwh = dinfo->di_bwh;
4813+ bdiropq = dinfo->di_bdiropq;
4814+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
4815+ h_d = p->hd_dentry;
4816+ if (!h_d)
4817+ continue;
4818+
4819+ h_dp = dget_parent(h_d);
4820+ if (h_dp == au_h_dptr(parent, bindex)) {
4821+ dput(h_dp);
4822+ continue;
4823+ }
4824+
4825+ new_bindex = au_find_dbindex(parent, h_dp);
4826+ dput(h_dp);
4827+ if (dinfo->di_bwh == bindex)
4828+ bwh = new_bindex;
4829+ if (dinfo->di_bdiropq == bindex)
4830+ bdiropq = new_bindex;
4831+ if (new_bindex < 0) {
4832+ au_hdput(p);
4833+ p->hd_dentry = NULL;
4834+ continue;
4835+ }
4836+
4837+ /* swap two lower dentries, and loop again */
4838+ q = dinfo->di_hdentry + new_bindex;
4839+ tmp = *q;
4840+ *q = *p;
4841+ *p = tmp;
4842+ if (tmp.hd_dentry) {
4843+ bindex--;
4844+ p--;
4845+ }
4846+ }
4847+
4848+ sb = parent->d_sb;
4849+ dinfo->di_bwh = -1;
4850+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
4851+ dinfo->di_bwh = bwh;
4852+
4853+ dinfo->di_bdiropq = -1;
4854+ if (bdiropq >= 0
4855+ && bdiropq <= au_sbend(sb)
4856+ && au_sbr_whable(sb, bdiropq))
4857+ dinfo->di_bdiropq = bdiropq;
4858+
4859+ bend = au_dbend(parent);
4860+ p = dinfo->di_hdentry;
4861+ for (bindex = 0; bindex <= bend; bindex++, p++)
4862+ if (p->hd_dentry) {
4863+ dinfo->di_bstart = bindex;
4864+ break;
4865+ }
4866+
4867+ p = dinfo->di_hdentry + bend;
4868+ for (bindex = bend; bindex >= 0; bindex--, p--)
4869+ if (p->hd_dentry) {
4870+ dinfo->di_bend = bindex;
4871+ break;
4872+ }
4873+}
4874+
4875+/*
4876+ * returns the number of found lower positive dentries,
4877+ * otherwise an error.
4878+ */
4879+int au_refresh_hdentry(struct dentry *dentry, mode_t type)
4880+{
4881+ int npositive, err;
4882+ unsigned int sigen;
4883+ aufs_bindex_t bstart;
4884+ struct au_dinfo *dinfo;
4885+ struct super_block *sb;
4886+ struct dentry *parent;
4887+
1308ab2a 4888+ DiMustWriteLock(dentry);
4889+
1facf9fc 4890+ sb = dentry->d_sb;
4891+ AuDebugOn(IS_ROOT(dentry));
4892+ sigen = au_sigen(sb);
4893+ parent = dget_parent(dentry);
4894+ AuDebugOn(au_digen(parent) != sigen
4895+ || au_iigen(parent->d_inode) != sigen);
4896+
4897+ dinfo = au_di(dentry);
4898+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
4899+ npositive = err;
4900+ if (unlikely(err))
4901+ goto out;
4902+ au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
4903+ parent);
4904+
4905+ npositive = 0;
4906+ bstart = au_dbstart(parent);
4907+ if (type != S_IFDIR && dinfo->di_bstart == bstart)
4908+ goto out_dgen; /* success */
4909+
4910+ npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
4911+ if (npositive < 0)
4912+ goto out;
4913+ if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
4914+ d_drop(dentry);
4915+
4f0767ce 4916+out_dgen:
1facf9fc 4917+ au_update_digen(dentry);
4f0767ce 4918+out:
1facf9fc 4919+ dput(parent);
4920+ AuTraceErr(npositive);
4921+ return npositive;
4922+}
4923+
4924+static noinline_for_stack
4925+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
4926+ struct dentry *dentry, aufs_bindex_t bindex)
4927+{
4928+ int err, valid;
4929+ int (*reval)(struct dentry *, struct nameidata *);
4930+
4931+ err = 0;
4932+ reval = NULL;
4933+ if (h_dentry->d_op)
4934+ reval = h_dentry->d_op->d_revalidate;
4935+ if (!reval)
4936+ goto out;
4937+
4938+ AuDbg("b%d\n", bindex);
4939+ if (au_test_fs_null_nd(h_dentry->d_sb))
4940+ /* it may return tri-state */
4941+ valid = reval(h_dentry, NULL);
4942+ else {
4943+ struct nameidata h_nd;
4944+ int locked;
4945+ struct dentry *parent;
4946+
4947+ au_h_nd(&h_nd, nd);
4948+ parent = nd->path.dentry;
4949+ locked = (nd && nd->path.dentry != dentry);
4950+ if (locked)
4951+ di_read_lock_parent(parent, AuLock_IR);
4952+ BUG_ON(bindex > au_dbend(parent));
4953+ h_nd.path.dentry = au_h_dptr(parent, bindex);
4954+ BUG_ON(!h_nd.path.dentry);
4955+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
4956+ path_get(&h_nd.path);
4957+ valid = reval(h_dentry, &h_nd);
4958+ path_put(&h_nd.path);
4959+ if (locked)
4960+ di_read_unlock(parent, AuLock_IR);
4961+ }
4962+
4963+ if (unlikely(valid < 0))
4964+ err = valid;
4965+ else if (!valid)
4966+ err = -EINVAL;
4967+
4f0767ce 4968+out:
1facf9fc 4969+ AuTraceErr(err);
4970+ return err;
4971+}
4972+
4973+/* todo: remove this */
4974+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
4975+ struct nameidata *nd, int do_udba)
4976+{
4977+ int err;
4978+ umode_t mode, h_mode;
4979+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
4980+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 4981+ struct inode *h_inode, *h_cached_inode;
1facf9fc 4982+ struct dentry *h_dentry;
4983+ struct qstr *name, *h_name;
4984+
4985+ err = 0;
4986+ plus = 0;
4987+ mode = 0;
1facf9fc 4988+ ibs = -1;
4989+ ibe = -1;
4990+ unhashed = !!d_unhashed(dentry);
4991+ is_root = !!IS_ROOT(dentry);
4992+ name = &dentry->d_name;
4993+
4994+ /*
7f207e10
AM
4995+ * Theoretically, REVAL test should be unnecessary in case of
4996+ * {FS,I}NOTIFY.
4997+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 4998+ * IN_ATTRIB for atime/nlink/pageio
4999+ * IN_DELETE for NFS dentry
5000+ * Let's do REVAL test too.
5001+ */
5002+ if (do_udba && inode) {
5003+ mode = (inode->i_mode & S_IFMT);
5004+ plus = (inode->i_nlink > 0);
1facf9fc 5005+ ibs = au_ibstart(inode);
5006+ ibe = au_ibend(inode);
5007+ }
5008+
5009+ bstart = au_dbstart(dentry);
5010+ btail = bstart;
5011+ if (inode && S_ISDIR(inode->i_mode))
5012+ btail = au_dbtaildir(dentry);
5013+ for (bindex = bstart; bindex <= btail; bindex++) {
5014+ h_dentry = au_h_dptr(dentry, bindex);
5015+ if (!h_dentry)
5016+ continue;
5017+
5018+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
5019+ h_name = &h_dentry->d_name;
5020+ if (unlikely(do_udba
5021+ && !is_root
5022+ && (unhashed != !!d_unhashed(h_dentry)
5023+ || name->len != h_name->len
5024+ || memcmp(name->name, h_name->name, name->len))
5025+ )) {
5026+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
5027+ unhashed, d_unhashed(h_dentry),
5028+ AuDLNPair(dentry), AuDLNPair(h_dentry));
5029+ goto err;
5030+ }
5031+
5032+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
5033+ if (unlikely(err))
5034+ /* do not goto err, to keep the errno */
5035+ break;
5036+
5037+ /* todo: plink too? */
5038+ if (!do_udba)
5039+ continue;
5040+
5041+ /* UDBA tests */
5042+ h_inode = h_dentry->d_inode;
5043+ if (unlikely(!!inode != !!h_inode))
5044+ goto err;
5045+
5046+ h_plus = plus;
5047+ h_mode = mode;
5048+ h_cached_inode = h_inode;
5049+ if (h_inode) {
5050+ h_mode = (h_inode->i_mode & S_IFMT);
5051+ h_plus = (h_inode->i_nlink > 0);
5052+ }
5053+ if (inode && ibs <= bindex && bindex <= ibe)
5054+ h_cached_inode = au_h_iptr(inode, bindex);
5055+
5056+ if (unlikely(plus != h_plus
5057+ || mode != h_mode
5058+ || h_cached_inode != h_inode))
5059+ goto err;
5060+ continue;
5061+
5062+ err:
5063+ err = -EINVAL;
5064+ break;
5065+ }
5066+
5067+ return err;
5068+}
5069+
5070+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
5071+{
5072+ int err;
5073+ struct dentry *parent;
5074+ struct inode *inode;
5075+
5076+ inode = dentry->d_inode;
5077+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
5078+ return 0;
5079+
5080+ parent = dget_parent(dentry);
5081+ di_read_lock_parent(parent, AuLock_IR);
5082+ AuDebugOn(au_digen(parent) != sigen
5083+ || au_iigen(parent->d_inode) != sigen);
5084+ au_dbg_verify_gen(parent, sigen);
5085+
5086+ /* returns a number of positive dentries */
5087+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
5088+ if (err >= 0)
5089+ err = au_refresh_hinode(inode, dentry);
5090+
5091+ di_read_unlock(parent, AuLock_IR);
5092+ dput(parent);
5093+ return err;
5094+}
5095+
5096+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
5097+{
5098+ int err;
5099+ struct dentry *d, *parent;
5100+ struct inode *inode;
5101+
5102+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
5103+ return simple_reval_dpath(dentry, sigen);
5104+
5105+ /* slow loop, keep it simple and stupid */
5106+ /* cf: au_cpup_dirs() */
5107+ err = 0;
5108+ parent = NULL;
5109+ while (au_digen(dentry) != sigen
5110+ || au_iigen(dentry->d_inode) != sigen) {
5111+ d = dentry;
5112+ while (1) {
5113+ dput(parent);
5114+ parent = dget_parent(d);
5115+ if (au_digen(parent) == sigen
5116+ && au_iigen(parent->d_inode) == sigen)
5117+ break;
5118+ d = parent;
5119+ }
5120+
5121+ inode = d->d_inode;
5122+ if (d != dentry)
5123+ di_write_lock_child(d);
5124+
5125+ /* someone might update our dentry while we were sleeping */
5126+ if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
5127+ di_read_lock_parent(parent, AuLock_IR);
5128+ /* returns a number of positive dentries */
5129+ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
5130+ if (err >= 0)
5131+ err = au_refresh_hinode(inode, d);
5132+ di_read_unlock(parent, AuLock_IR);
5133+ }
5134+
5135+ if (d != dentry)
5136+ di_write_unlock(d);
5137+ dput(parent);
5138+ if (unlikely(err))
5139+ break;
5140+ }
5141+
5142+ return err;
5143+}
5144+
5145+/*
5146+ * if valid returns 1, otherwise 0.
5147+ */
5148+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
5149+{
5150+ int valid, err;
5151+ unsigned int sigen;
5152+ unsigned char do_udba;
5153+ struct super_block *sb;
5154+ struct inode *inode;
5155+
e49829fe 5156+ valid = 1;
1facf9fc 5157+ sb = dentry->d_sb;
5158+ inode = dentry->d_inode;
e49829fe
JR
5159+ /*
5160+ * todo: very ugly
5161+ * i_mutex of parent dir may be held,
5162+ * but we should not return 'invalid' due to busy.
5163+ */
5164+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
5165+ if (unlikely(err)) {
5166+ valid = err;
5167+ goto out;
5168+ }
1facf9fc 5169+ sigen = au_sigen(sb);
5170+ if (au_digen(dentry) != sigen) {
5171+ AuDebugOn(IS_ROOT(dentry));
5172+ if (inode)
5173+ err = au_reval_dpath(dentry, sigen);
5174+ if (unlikely(err))
5175+ goto out_dgrade;
1facf9fc 5176+ }
5177+ if (inode && au_iigen(inode) != sigen) {
5178+ AuDebugOn(IS_ROOT(dentry));
5179+ err = au_refresh_hinode(inode, dentry);
5180+ if (unlikely(err))
5181+ goto out_dgrade;
1facf9fc 5182+ }
5183+ di_downgrade_lock(dentry, AuLock_IR);
5184+
1facf9fc 5185+ err = -EINVAL;
5186+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
5187+ if (do_udba && inode) {
5188+ aufs_bindex_t bstart = au_ibstart(inode);
5189+
5190+ if (bstart >= 0
5191+ && au_test_higen(inode, au_h_iptr(inode, bstart)))
e49829fe 5192+ goto out_inval;
1facf9fc 5193+ }
5194+
5195+ err = h_d_revalidate(dentry, inode, nd, do_udba);
5196+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
5197+ /* both of real entry and whiteout found */
5198+ err = -EIO;
e49829fe 5199+ goto out_inval;
1facf9fc 5200+
4f0767ce 5201+out_dgrade:
1facf9fc 5202+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 5203+out_inval:
1facf9fc 5204+ aufs_read_unlock(dentry, AuLock_IR);
5205+ AuTraceErr(err);
5206+ valid = !err;
e49829fe 5207+out:
1facf9fc 5208+ if (!valid)
e49829fe 5209+ AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid);
1facf9fc 5210+ return valid;
5211+}
5212+
5213+static void aufs_d_release(struct dentry *dentry)
5214+{
4a4d8108
AM
5215+ if (dentry->d_fsdata) {
5216+ au_di_fin(dentry);
5217+ au_hn_di_reinit(dentry);
1facf9fc 5218+ }
1facf9fc 5219+}
5220+
4a4d8108 5221+const struct dentry_operations aufs_dop = {
1facf9fc 5222+ .d_revalidate = aufs_d_revalidate,
5223+ .d_release = aufs_d_release
5224+};
7f207e10
AM
5225diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
5226--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
5227+++ linux/fs/aufs/dentry.h 2010-11-22 11:52:56.983894369 +0100
1308ab2a 5228@@ -0,0 +1,231 @@
1facf9fc 5229+/*
4a4d8108 5230+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5231+ *
5232+ * This program, aufs is free software; you can redistribute it and/or modify
5233+ * it under the terms of the GNU General Public License as published by
5234+ * the Free Software Foundation; either version 2 of the License, or
5235+ * (at your option) any later version.
dece6358
AM
5236+ *
5237+ * This program is distributed in the hope that it will be useful,
5238+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5239+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5240+ * GNU General Public License for more details.
5241+ *
5242+ * You should have received a copy of the GNU General Public License
5243+ * along with this program; if not, write to the Free Software
5244+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5245+ */
5246+
5247+/*
5248+ * lookup and dentry operations
5249+ */
5250+
5251+#ifndef __AUFS_DENTRY_H__
5252+#define __AUFS_DENTRY_H__
5253+
5254+#ifdef __KERNEL__
5255+
dece6358 5256+#include <linux/dcache.h>
1facf9fc 5257+#include <linux/aufs_type.h>
5258+#include "rwsem.h"
5259+
5260+/* make a single member structure for future use */
5261+/* todo: remove this structure */
5262+struct au_hdentry {
5263+ struct dentry *hd_dentry;
5264+};
5265+
5266+struct au_dinfo {
5267+ atomic_t di_generation;
5268+
dece6358 5269+ struct au_rwsem di_rwsem;
1facf9fc 5270+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
5271+ struct au_hdentry *di_hdentry;
4a4d8108 5272+} ____cacheline_aligned_in_smp;
1facf9fc 5273+
5274+/* ---------------------------------------------------------------------- */
5275+
5276+/* dentry.c */
4a4d8108 5277+extern const struct dentry_operations aufs_dop;
1facf9fc 5278+struct au_branch;
5279+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
5280+ struct au_branch *br, struct nameidata *nd);
5281+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
5282+ struct au_branch *br);
5283+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
5284+ struct dentry *h_parent, struct au_branch *br);
5285+
5286+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
5287+ struct nameidata *nd);
5288+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
5289+int au_refresh_hdentry(struct dentry *dentry, mode_t type);
5290+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
5291+
5292+/* dinfo.c */
4a4d8108
AM
5293+void au_di_init_once(void *_di);
5294+int au_di_init(struct dentry *dentry);
5295+void au_di_fin(struct dentry *dentry);
1facf9fc 5296+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
5297+
5298+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
5299+void di_read_unlock(struct dentry *d, int flags);
5300+void di_downgrade_lock(struct dentry *d, int flags);
5301+void di_write_lock(struct dentry *d, unsigned int lsc);
5302+void di_write_unlock(struct dentry *d);
5303+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
5304+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
5305+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
5306+
5307+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
5308+aufs_bindex_t au_dbtail(struct dentry *dentry);
5309+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
5310+
5311+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5312+ struct dentry *h_dentry);
5313+void au_update_digen(struct dentry *dentry);
5314+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5315+void au_update_dbstart(struct dentry *dentry);
5316+void au_update_dbend(struct dentry *dentry);
5317+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
5318+
5319+/* ---------------------------------------------------------------------- */
5320+
5321+static inline struct au_dinfo *au_di(struct dentry *dentry)
5322+{
5323+ return dentry->d_fsdata;
5324+}
5325+
5326+/* ---------------------------------------------------------------------- */
5327+
5328+/* lock subclass for dinfo */
5329+enum {
5330+ AuLsc_DI_CHILD, /* child first */
4a4d8108 5331+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 5332+ AuLsc_DI_CHILD3, /* copyup dirs */
5333+ AuLsc_DI_PARENT,
5334+ AuLsc_DI_PARENT2,
5335+ AuLsc_DI_PARENT3
5336+};
5337+
5338+/*
5339+ * di_read_lock_child, di_write_lock_child,
5340+ * di_read_lock_child2, di_write_lock_child2,
5341+ * di_read_lock_child3, di_write_lock_child3,
5342+ * di_read_lock_parent, di_write_lock_parent,
5343+ * di_read_lock_parent2, di_write_lock_parent2,
5344+ * di_read_lock_parent3, di_write_lock_parent3,
5345+ */
5346+#define AuReadLockFunc(name, lsc) \
5347+static inline void di_read_lock_##name(struct dentry *d, int flags) \
5348+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
5349+
5350+#define AuWriteLockFunc(name, lsc) \
5351+static inline void di_write_lock_##name(struct dentry *d) \
5352+{ di_write_lock(d, AuLsc_DI_##lsc); }
5353+
5354+#define AuRWLockFuncs(name, lsc) \
5355+ AuReadLockFunc(name, lsc) \
5356+ AuWriteLockFunc(name, lsc)
5357+
5358+AuRWLockFuncs(child, CHILD);
5359+AuRWLockFuncs(child2, CHILD2);
5360+AuRWLockFuncs(child3, CHILD3);
5361+AuRWLockFuncs(parent, PARENT);
5362+AuRWLockFuncs(parent2, PARENT2);
5363+AuRWLockFuncs(parent3, PARENT3);
5364+
5365+#undef AuReadLockFunc
5366+#undef AuWriteLockFunc
5367+#undef AuRWLockFuncs
5368+
5369+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
5370+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
5371+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 5372+
5373+/* ---------------------------------------------------------------------- */
5374+
5375+/* todo: memory barrier? */
5376+static inline unsigned int au_digen(struct dentry *d)
5377+{
5378+ return atomic_read(&au_di(d)->di_generation);
5379+}
5380+
5381+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
5382+{
5383+ hdentry->hd_dentry = NULL;
5384+}
5385+
5386+static inline void au_hdput(struct au_hdentry *hd)
5387+{
4a4d8108
AM
5388+ if (hd)
5389+ dput(hd->hd_dentry);
1facf9fc 5390+}
5391+
5392+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
5393+{
1308ab2a 5394+ DiMustAnyLock(dentry);
1facf9fc 5395+ return au_di(dentry)->di_bstart;
5396+}
5397+
5398+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
5399+{
1308ab2a 5400+ DiMustAnyLock(dentry);
1facf9fc 5401+ return au_di(dentry)->di_bend;
5402+}
5403+
5404+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
5405+{
1308ab2a 5406+ DiMustAnyLock(dentry);
1facf9fc 5407+ return au_di(dentry)->di_bwh;
5408+}
5409+
5410+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
5411+{
1308ab2a 5412+ DiMustAnyLock(dentry);
1facf9fc 5413+ return au_di(dentry)->di_bdiropq;
5414+}
5415+
5416+/* todo: hard/soft set? */
5417+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
5418+{
1308ab2a 5419+ DiMustWriteLock(dentry);
1facf9fc 5420+ au_di(dentry)->di_bstart = bindex;
5421+}
5422+
5423+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
5424+{
1308ab2a 5425+ DiMustWriteLock(dentry);
1facf9fc 5426+ au_di(dentry)->di_bend = bindex;
5427+}
5428+
5429+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
5430+{
1308ab2a 5431+ DiMustWriteLock(dentry);
1facf9fc 5432+ /* dbwh can be outside of bstart - bend range */
5433+ au_di(dentry)->di_bwh = bindex;
5434+}
5435+
5436+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
5437+{
1308ab2a 5438+ DiMustWriteLock(dentry);
1facf9fc 5439+ au_di(dentry)->di_bdiropq = bindex;
5440+}
5441+
5442+/* ---------------------------------------------------------------------- */
5443+
4a4d8108 5444+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 5445+static inline void au_digen_dec(struct dentry *d)
5446+{
e49829fe 5447+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 5448+}
5449+
4a4d8108 5450+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 5451+{
5452+ dentry->d_fsdata = NULL;
5453+}
5454+#else
4a4d8108
AM
5455+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
5456+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 5457+
5458+#endif /* __KERNEL__ */
5459+#endif /* __AUFS_DENTRY_H__ */
7f207e10
AM
5460diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
5461--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
5462+++ linux/fs/aufs/dinfo.c 2010-11-22 11:52:56.983894369 +0100
e49829fe 5463@@ -0,0 +1,397 @@
1facf9fc 5464+/*
4a4d8108 5465+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5466+ *
5467+ * This program, aufs is free software; you can redistribute it and/or modify
5468+ * it under the terms of the GNU General Public License as published by
5469+ * the Free Software Foundation; either version 2 of the License, or
5470+ * (at your option) any later version.
dece6358
AM
5471+ *
5472+ * This program is distributed in the hope that it will be useful,
5473+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5474+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5475+ * GNU General Public License for more details.
5476+ *
5477+ * You should have received a copy of the GNU General Public License
5478+ * along with this program; if not, write to the Free Software
5479+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5480+ */
5481+
5482+/*
5483+ * dentry private data
5484+ */
5485+
5486+#include "aufs.h"
5487+
e49829fe 5488+void au_di_init_once(void *_dinfo)
4a4d8108 5489+{
e49829fe
JR
5490+ struct au_dinfo *dinfo = _dinfo;
5491+ static struct lock_class_key aufs_di;
4a4d8108 5492+
e49829fe
JR
5493+ au_rw_init(&dinfo->di_rwsem);
5494+ au_rw_class(&dinfo->di_rwsem, &aufs_di);
4a4d8108
AM
5495+}
5496+
5497+int au_di_init(struct dentry *dentry)
1facf9fc 5498+{
5499+ struct au_dinfo *dinfo;
5500+ struct super_block *sb;
5501+ int nbr;
5502+
5503+ dinfo = au_cache_alloc_dinfo();
5504+ if (unlikely(!dinfo))
5505+ goto out;
5506+
5507+ sb = dentry->d_sb;
5508+ nbr = au_sbend(sb) + 1;
5509+ if (nbr <= 0)
5510+ nbr = 1;
5511+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
5512+ if (unlikely(!dinfo->di_hdentry))
5513+ goto out_dinfo;
5514+
5515+ atomic_set(&dinfo->di_generation, au_sigen(sb));
5516+ /* smp_mb(); */ /* atomic_set */
4a4d8108 5517+ au_rw_write_lock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
1facf9fc 5518+ dinfo->di_bstart = -1;
5519+ dinfo->di_bend = -1;
5520+ dinfo->di_bwh = -1;
5521+ dinfo->di_bdiropq = -1;
5522+
5523+ dentry->d_fsdata = dinfo;
5524+ dentry->d_op = &aufs_dop;
5525+ return 0; /* success */
5526+
4f0767ce 5527+out_dinfo:
1facf9fc 5528+ au_cache_free_dinfo(dinfo);
4f0767ce 5529+out:
1facf9fc 5530+ return -ENOMEM;
5531+}
5532+
4a4d8108
AM
5533+void au_di_fin(struct dentry *dentry)
5534+{
5535+ struct au_dinfo *di;
5536+ struct au_hdentry *p;
5537+ aufs_bindex_t bend, bindex;
5538+
5539+ /* dentry may not be revalidated */
5540+ di = dentry->d_fsdata;
5541+ bindex = di->di_bstart;
5542+ if (bindex >= 0) {
5543+ bend = di->di_bend;
5544+ p = di->di_hdentry + bindex;
5545+ while (bindex++ <= bend)
5546+ au_hdput(p++);
5547+ }
5548+ kfree(di->di_hdentry);
5549+ AuRwDestroy(&di->di_rwsem);
5550+ au_cache_free_dinfo(di);
5551+}
5552+
1facf9fc 5553+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
5554+{
5555+ int err, sz;
5556+ struct au_hdentry *hdp;
5557+
1308ab2a 5558+ AuRwMustWriteLock(&dinfo->di_rwsem);
5559+
1facf9fc 5560+ err = -ENOMEM;
5561+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
5562+ if (!sz)
5563+ sz = sizeof(*hdp);
5564+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
5565+ if (hdp) {
5566+ dinfo->di_hdentry = hdp;
5567+ err = 0;
5568+ }
5569+
5570+ return err;
5571+}
5572+
5573+/* ---------------------------------------------------------------------- */
5574+
5575+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
5576+{
5577+ switch (lsc) {
5578+ case AuLsc_DI_CHILD:
5579+ ii_write_lock_child(inode);
5580+ break;
5581+ case AuLsc_DI_CHILD2:
5582+ ii_write_lock_child2(inode);
5583+ break;
5584+ case AuLsc_DI_CHILD3:
5585+ ii_write_lock_child3(inode);
5586+ break;
5587+ case AuLsc_DI_PARENT:
5588+ ii_write_lock_parent(inode);
5589+ break;
5590+ case AuLsc_DI_PARENT2:
5591+ ii_write_lock_parent2(inode);
5592+ break;
5593+ case AuLsc_DI_PARENT3:
5594+ ii_write_lock_parent3(inode);
5595+ break;
5596+ default:
5597+ BUG();
5598+ }
5599+}
5600+
5601+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
5602+{
5603+ switch (lsc) {
5604+ case AuLsc_DI_CHILD:
5605+ ii_read_lock_child(inode);
5606+ break;
5607+ case AuLsc_DI_CHILD2:
5608+ ii_read_lock_child2(inode);
5609+ break;
5610+ case AuLsc_DI_CHILD3:
5611+ ii_read_lock_child3(inode);
5612+ break;
5613+ case AuLsc_DI_PARENT:
5614+ ii_read_lock_parent(inode);
5615+ break;
5616+ case AuLsc_DI_PARENT2:
5617+ ii_read_lock_parent2(inode);
5618+ break;
5619+ case AuLsc_DI_PARENT3:
5620+ ii_read_lock_parent3(inode);
5621+ break;
5622+ default:
5623+ BUG();
5624+ }
5625+}
5626+
5627+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
5628+{
dece6358 5629+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5630+ if (d->d_inode) {
5631+ if (au_ftest_lock(flags, IW))
5632+ do_ii_write_lock(d->d_inode, lsc);
5633+ else if (au_ftest_lock(flags, IR))
5634+ do_ii_read_lock(d->d_inode, lsc);
5635+ }
5636+}
5637+
5638+void di_read_unlock(struct dentry *d, int flags)
5639+{
5640+ if (d->d_inode) {
5641+ if (au_ftest_lock(flags, IW))
5642+ ii_write_unlock(d->d_inode);
5643+ else if (au_ftest_lock(flags, IR))
5644+ ii_read_unlock(d->d_inode);
5645+ }
dece6358 5646+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 5647+}
5648+
5649+void di_downgrade_lock(struct dentry *d, int flags)
5650+{
1facf9fc 5651+ if (d->d_inode && au_ftest_lock(flags, IR))
5652+ ii_downgrade_lock(d->d_inode);
dece6358 5653+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 5654+}
5655+
5656+void di_write_lock(struct dentry *d, unsigned int lsc)
5657+{
dece6358 5658+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5659+ if (d->d_inode)
5660+ do_ii_write_lock(d->d_inode, lsc);
5661+}
5662+
5663+void di_write_unlock(struct dentry *d)
5664+{
5665+ if (d->d_inode)
5666+ ii_write_unlock(d->d_inode);
dece6358 5667+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 5668+}
5669+
5670+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
5671+{
5672+ AuDebugOn(d1 == d2
5673+ || d1->d_inode == d2->d_inode
5674+ || d1->d_sb != d2->d_sb);
5675+
5676+ if (isdir && au_test_subdir(d1, d2)) {
5677+ di_write_lock_child(d1);
5678+ di_write_lock_child2(d2);
5679+ } else {
5680+ /* there should be no races */
5681+ di_write_lock_child(d2);
5682+ di_write_lock_child2(d1);
5683+ }
5684+}
5685+
5686+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
5687+{
5688+ AuDebugOn(d1 == d2
5689+ || d1->d_inode == d2->d_inode
5690+ || d1->d_sb != d2->d_sb);
5691+
5692+ if (isdir && au_test_subdir(d1, d2)) {
5693+ di_write_lock_parent(d1);
5694+ di_write_lock_parent2(d2);
5695+ } else {
5696+ /* there should be no races */
5697+ di_write_lock_parent(d2);
5698+ di_write_lock_parent2(d1);
5699+ }
5700+}
5701+
5702+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
5703+{
5704+ di_write_unlock(d1);
5705+ if (d1->d_inode == d2->d_inode)
dece6358 5706+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 5707+ else
5708+ di_write_unlock(d2);
5709+}
5710+
5711+/* ---------------------------------------------------------------------- */
5712+
5713+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
5714+{
5715+ struct dentry *d;
5716+
1308ab2a 5717+ DiMustAnyLock(dentry);
5718+
1facf9fc 5719+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
5720+ return NULL;
5721+ AuDebugOn(bindex < 0);
5722+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
5723+ AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
5724+ return d;
5725+}
5726+
5727+aufs_bindex_t au_dbtail(struct dentry *dentry)
5728+{
5729+ aufs_bindex_t bend, bwh;
5730+
5731+ bend = au_dbend(dentry);
5732+ if (0 <= bend) {
5733+ bwh = au_dbwh(dentry);
5734+ if (!bwh)
5735+ return bwh;
5736+ if (0 < bwh && bwh < bend)
5737+ return bwh - 1;
5738+ }
5739+ return bend;
5740+}
5741+
5742+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
5743+{
5744+ aufs_bindex_t bend, bopq;
5745+
5746+ bend = au_dbtail(dentry);
5747+ if (0 <= bend) {
5748+ bopq = au_dbdiropq(dentry);
5749+ if (0 <= bopq && bopq < bend)
5750+ bend = bopq;
5751+ }
5752+ return bend;
5753+}
5754+
5755+/* ---------------------------------------------------------------------- */
5756+
5757+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5758+ struct dentry *h_dentry)
5759+{
5760+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
5761+
1308ab2a 5762+ DiMustWriteLock(dentry);
5763+
4a4d8108 5764+ au_hdput(hd);
1facf9fc 5765+ hd->hd_dentry = h_dentry;
5766+}
5767+
5768+void au_update_digen(struct dentry *dentry)
5769+{
5770+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
5771+ /* smp_mb(); */ /* atomic_set */
5772+}
5773+
5774+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
5775+{
5776+ struct au_dinfo *dinfo;
5777+ struct dentry *h_d;
4a4d8108 5778+ struct au_hdentry *hdp;
1facf9fc 5779+
1308ab2a 5780+ DiMustWriteLock(dentry);
5781+
1facf9fc 5782+ dinfo = au_di(dentry);
5783+ if (!dinfo || dinfo->di_bstart < 0)
5784+ return;
5785+
4a4d8108 5786+ hdp = dinfo->di_hdentry;
1facf9fc 5787+ if (do_put_zero) {
5788+ aufs_bindex_t bindex, bend;
5789+
5790+ bend = dinfo->di_bend;
5791+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 5792+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 5793+ if (h_d && !h_d->d_inode)
5794+ au_set_h_dptr(dentry, bindex, NULL);
5795+ }
5796+ }
5797+
5798+ dinfo->di_bstart = -1;
5799+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 5800+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 5801+ break;
5802+ if (dinfo->di_bstart > dinfo->di_bend) {
5803+ dinfo->di_bstart = -1;
5804+ dinfo->di_bend = -1;
5805+ return;
5806+ }
5807+
5808+ dinfo->di_bend++;
5809+ while (0 <= --dinfo->di_bend)
4a4d8108 5810+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 5811+ break;
5812+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
5813+}
5814+
5815+void au_update_dbstart(struct dentry *dentry)
5816+{
5817+ aufs_bindex_t bindex, bend;
5818+ struct dentry *h_dentry;
5819+
5820+ bend = au_dbend(dentry);
5821+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
5822+ h_dentry = au_h_dptr(dentry, bindex);
5823+ if (!h_dentry)
5824+ continue;
5825+ if (h_dentry->d_inode) {
5826+ au_set_dbstart(dentry, bindex);
5827+ return;
5828+ }
5829+ au_set_h_dptr(dentry, bindex, NULL);
5830+ }
5831+}
5832+
5833+void au_update_dbend(struct dentry *dentry)
5834+{
5835+ aufs_bindex_t bindex, bstart;
5836+ struct dentry *h_dentry;
5837+
5838+ bstart = au_dbstart(dentry);
7f207e10 5839+ for (bindex = au_dbend(dentry); bindex >= bstart; bindex--) {
1facf9fc 5840+ h_dentry = au_h_dptr(dentry, bindex);
5841+ if (!h_dentry)
5842+ continue;
5843+ if (h_dentry->d_inode) {
5844+ au_set_dbend(dentry, bindex);
5845+ return;
5846+ }
5847+ au_set_h_dptr(dentry, bindex, NULL);
5848+ }
5849+}
5850+
5851+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
5852+{
5853+ aufs_bindex_t bindex, bend;
5854+
5855+ bend = au_dbend(dentry);
5856+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
5857+ if (au_h_dptr(dentry, bindex) == h_dentry)
5858+ return bindex;
5859+ return -1;
5860+}
7f207e10
AM
5861diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
5862--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
5863+++ linux/fs/aufs/dir.c 2010-11-22 11:52:56.983894369 +0100
5864@@ -0,0 +1,642 @@
1facf9fc 5865+/*
4a4d8108 5866+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5867+ *
5868+ * This program, aufs is free software; you can redistribute it and/or modify
5869+ * it under the terms of the GNU General Public License as published by
5870+ * the Free Software Foundation; either version 2 of the License, or
5871+ * (at your option) any later version.
dece6358
AM
5872+ *
5873+ * This program is distributed in the hope that it will be useful,
5874+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5875+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5876+ * GNU General Public License for more details.
5877+ *
5878+ * You should have received a copy of the GNU General Public License
5879+ * along with this program; if not, write to the Free Software
5880+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5881+ */
5882+
5883+/*
5884+ * directory operations
5885+ */
5886+
dece6358 5887+#include <linux/file.h>
1facf9fc 5888+#include <linux/fs_stack.h>
5889+#include "aufs.h"
5890+
5891+void au_add_nlink(struct inode *dir, struct inode *h_dir)
5892+{
5893+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5894+
5895+ dir->i_nlink += h_dir->i_nlink - 2;
5896+ if (h_dir->i_nlink < 2)
5897+ dir->i_nlink += 2;
5898+}
5899+
5900+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
5901+{
5902+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5903+
5904+ dir->i_nlink -= h_dir->i_nlink - 2;
5905+ if (h_dir->i_nlink < 2)
5906+ dir->i_nlink -= 2;
5907+}
5908+
1308ab2a 5909+loff_t au_dir_size(struct file *file, struct dentry *dentry)
5910+{
5911+ loff_t sz;
5912+ aufs_bindex_t bindex, bend;
5913+ struct file *h_file;
5914+ struct dentry *h_dentry;
5915+
5916+ sz = 0;
5917+ if (file) {
5918+ AuDebugOn(!file->f_dentry);
5919+ AuDebugOn(!file->f_dentry->d_inode);
5920+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
5921+
4a4d8108 5922+ bend = au_fbend_dir(file);
1308ab2a 5923+ for (bindex = au_fbstart(file);
5924+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5925+ bindex++) {
4a4d8108 5926+ h_file = au_hf_dir(file, bindex);
1308ab2a 5927+ if (h_file
5928+ && h_file->f_dentry
5929+ && h_file->f_dentry->d_inode)
5930+ sz += i_size_read(h_file->f_dentry->d_inode);
5931+ }
5932+ } else {
5933+ AuDebugOn(!dentry);
5934+ AuDebugOn(!dentry->d_inode);
5935+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
5936+
5937+ bend = au_dbtaildir(dentry);
5938+ for (bindex = au_dbstart(dentry);
5939+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5940+ bindex++) {
5941+ h_dentry = au_h_dptr(dentry, bindex);
5942+ if (h_dentry && h_dentry->d_inode)
5943+ sz += i_size_read(h_dentry->d_inode);
5944+ }
5945+ }
5946+ if (sz < KMALLOC_MAX_SIZE)
5947+ sz = roundup_pow_of_two(sz);
5948+ if (sz > KMALLOC_MAX_SIZE)
5949+ sz = KMALLOC_MAX_SIZE;
5950+ else if (sz < NAME_MAX) {
5951+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
5952+ sz = AUFS_RDBLK_DEF;
5953+ }
5954+ return sz;
5955+}
5956+
1facf9fc 5957+/* ---------------------------------------------------------------------- */
5958+
5959+static int reopen_dir(struct file *file)
5960+{
5961+ int err;
5962+ unsigned int flags;
5963+ aufs_bindex_t bindex, btail, bstart;
5964+ struct dentry *dentry, *h_dentry;
5965+ struct file *h_file;
5966+
5967+ /* open all lower dirs */
5968+ dentry = file->f_dentry;
5969+ bstart = au_dbstart(dentry);
5970+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
5971+ au_set_h_fptr(file, bindex, NULL);
5972+ au_set_fbstart(file, bstart);
5973+
5974+ btail = au_dbtaildir(dentry);
4a4d8108 5975+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 5976+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 5977+ au_set_fbend_dir(file, btail);
1facf9fc 5978+
4a4d8108 5979+ flags = vfsub_file_flags(file);
1facf9fc 5980+ for (bindex = bstart; bindex <= btail; bindex++) {
5981+ h_dentry = au_h_dptr(dentry, bindex);
5982+ if (!h_dentry)
5983+ continue;
4a4d8108 5984+ h_file = au_hf_dir(file, bindex);
1facf9fc 5985+ if (h_file)
5986+ continue;
5987+
5988+ h_file = au_h_open(dentry, bindex, flags, file);
5989+ err = PTR_ERR(h_file);
5990+ if (IS_ERR(h_file))
5991+ goto out; /* close all? */
5992+ au_set_h_fptr(file, bindex, h_file);
5993+ }
5994+ au_update_figen(file);
5995+ /* todo: necessary? */
5996+ /* file->f_ra = h_file->f_ra; */
5997+ err = 0;
5998+
4f0767ce 5999+out:
1facf9fc 6000+ return err;
6001+}
6002+
6003+static int do_open_dir(struct file *file, int flags)
6004+{
6005+ int err;
6006+ aufs_bindex_t bindex, btail;
6007+ struct dentry *dentry, *h_dentry;
6008+ struct file *h_file;
6009+
1308ab2a 6010+ FiMustWriteLock(file);
6011+
1facf9fc 6012+ err = 0;
6013+ dentry = file->f_dentry;
1facf9fc 6014+ file->f_version = dentry->d_inode->i_version;
6015+ bindex = au_dbstart(dentry);
6016+ au_set_fbstart(file, bindex);
6017+ btail = au_dbtaildir(dentry);
4a4d8108 6018+ au_set_fbend_dir(file, btail);
1facf9fc 6019+ for (; !err && bindex <= btail; bindex++) {
6020+ h_dentry = au_h_dptr(dentry, bindex);
6021+ if (!h_dentry)
6022+ continue;
6023+
6024+ h_file = au_h_open(dentry, bindex, flags, file);
6025+ if (IS_ERR(h_file)) {
6026+ err = PTR_ERR(h_file);
6027+ break;
6028+ }
6029+ au_set_h_fptr(file, bindex, h_file);
6030+ }
6031+ au_update_figen(file);
6032+ /* todo: necessary? */
6033+ /* file->f_ra = h_file->f_ra; */
6034+ if (!err)
6035+ return 0; /* success */
6036+
6037+ /* close all */
6038+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
6039+ au_set_h_fptr(file, bindex, NULL);
6040+ au_set_fbstart(file, -1);
4a4d8108
AM
6041+ au_set_fbend_dir(file, -1);
6042+
1facf9fc 6043+ return err;
6044+}
6045+
6046+static int aufs_open_dir(struct inode *inode __maybe_unused,
6047+ struct file *file)
6048+{
4a4d8108
AM
6049+ int err;
6050+ struct super_block *sb;
6051+ struct au_fidir *fidir;
6052+
6053+ err = -ENOMEM;
6054+ sb = file->f_dentry->d_sb;
6055+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 6056+ fidir = au_fidir_alloc(sb);
4a4d8108
AM
6057+ if (fidir) {
6058+ err = au_do_open(file, do_open_dir, fidir);
6059+ if (unlikely(err))
6060+ kfree(fidir);
6061+ }
6062+ si_read_unlock(sb);
6063+ return err;
1facf9fc 6064+}
6065+
6066+static int aufs_release_dir(struct inode *inode __maybe_unused,
6067+ struct file *file)
6068+{
6069+ struct au_vdir *vdir_cache;
7f207e10 6070+ struct super_block *sb;
4a4d8108
AM
6071+ struct au_finfo *finfo;
6072+ struct au_fidir *fidir;
6073+ aufs_bindex_t bindex, bend;
1facf9fc 6074+
7f207e10 6075+ sb = file->f_dentry->d_sb;
4a4d8108
AM
6076+ finfo = au_fi(file);
6077+ fidir = finfo->fi_hdir;
6078+ if (fidir) {
0c5527e5
AM
6079+ /* remove me from sb->s_files */
6080+ file_sb_list_del(file);
6081+
4a4d8108
AM
6082+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
6083+ if (vdir_cache)
6084+ au_vdir_free(vdir_cache);
6085+
6086+ bindex = finfo->fi_btop;
6087+ if (bindex >= 0) {
6088+ /*
6089+ * calls fput() instead of filp_close(),
6090+ * since no dnotify or lock for the lower file.
6091+ */
6092+ bend = fidir->fd_bbot;
6093+ for (; bindex <= bend; bindex++)
6094+ au_set_h_fptr(file, bindex, NULL);
6095+ }
6096+ kfree(fidir);
6097+ finfo->fi_hdir = NULL;
1facf9fc 6098+ }
1facf9fc 6099+ au_finfo_fin(file);
1facf9fc 6100+ return 0;
6101+}
6102+
6103+/* ---------------------------------------------------------------------- */
6104+
4a4d8108
AM
6105+static int au_do_flush_dir(struct file *file, fl_owner_t id)
6106+{
6107+ int err;
6108+ aufs_bindex_t bindex, bend;
6109+ struct file *h_file;
6110+
6111+ err = 0;
6112+ bend = au_fbend_dir(file);
6113+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
6114+ h_file = au_hf_dir(file, bindex);
6115+ if (h_file)
6116+ err = vfsub_flush(h_file, id);
6117+ }
6118+ return err;
6119+}
6120+
6121+static int aufs_flush_dir(struct file *file, fl_owner_t id)
6122+{
6123+ return au_do_flush(file, id, au_do_flush_dir);
6124+}
6125+
6126+/* ---------------------------------------------------------------------- */
6127+
1facf9fc 6128+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
6129+{
6130+ int err;
6131+ aufs_bindex_t bend, bindex;
6132+ struct inode *inode;
6133+ struct super_block *sb;
6134+
6135+ err = 0;
6136+ sb = dentry->d_sb;
6137+ inode = dentry->d_inode;
6138+ IMustLock(inode);
6139+ bend = au_dbend(dentry);
6140+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
6141+ struct path h_path;
6142+ struct inode *h_inode;
6143+
6144+ if (au_test_ro(sb, bindex, inode))
6145+ continue;
6146+ h_path.dentry = au_h_dptr(dentry, bindex);
6147+ if (!h_path.dentry)
6148+ continue;
6149+ h_inode = h_path.dentry->d_inode;
6150+ if (!h_inode)
6151+ continue;
6152+
6153+ /* no mnt_want_write() */
6154+ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
6155+ /* todo: inotiry fired? */
6156+ h_path.mnt = au_sbr_mnt(sb, bindex);
6157+ mutex_lock(&h_inode->i_mutex);
6158+ err = filemap_fdatawrite(h_inode->i_mapping);
6159+ AuDebugOn(!h_inode->i_fop);
6160+ if (!err && h_inode->i_fop->fsync)
b752ccd1 6161+ err = h_inode->i_fop->fsync(NULL, datasync);
1facf9fc 6162+ if (!err)
6163+ err = filemap_fdatawrite(h_inode->i_mapping);
6164+ if (!err)
6165+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
6166+ mutex_unlock(&h_inode->i_mutex);
6167+ }
6168+
6169+ return err;
6170+}
6171+
6172+static int au_do_fsync_dir(struct file *file, int datasync)
6173+{
6174+ int err;
6175+ aufs_bindex_t bend, bindex;
6176+ struct file *h_file;
6177+ struct super_block *sb;
6178+ struct inode *inode;
6179+ struct mutex *h_mtx;
6180+
6181+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6182+ if (unlikely(err))
6183+ goto out;
6184+
6185+ sb = file->f_dentry->d_sb;
6186+ inode = file->f_dentry->d_inode;
4a4d8108 6187+ bend = au_fbend_dir(file);
1facf9fc 6188+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 6189+ h_file = au_hf_dir(file, bindex);
1facf9fc 6190+ if (!h_file || au_test_ro(sb, bindex, inode))
6191+ continue;
6192+
b752ccd1 6193+ err = vfs_fsync(h_file, datasync);
1facf9fc 6194+ if (!err) {
6195+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
6196+ mutex_lock(h_mtx);
6197+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
6198+ /*ignore*/
6199+ mutex_unlock(h_mtx);
6200+ }
6201+ }
6202+
4f0767ce 6203+out:
1facf9fc 6204+ return err;
6205+}
6206+
6207+/*
6208+ * @file may be NULL
6209+ */
b752ccd1 6210+static int aufs_fsync_dir(struct file *file, int datasync)
1facf9fc 6211+{
6212+ int err;
b752ccd1 6213+ struct dentry *dentry;
1facf9fc 6214+ struct super_block *sb;
6215+
b752ccd1 6216+ dentry = file->f_dentry;
1facf9fc 6217+ IMustLock(dentry->d_inode);
6218+
6219+ err = 0;
6220+ sb = dentry->d_sb;
6221+ si_noflush_read_lock(sb);
6222+ if (file)
6223+ err = au_do_fsync_dir(file, datasync);
6224+ else {
6225+ di_write_lock_child(dentry);
6226+ err = au_do_fsync_dir_no_file(dentry, datasync);
6227+ }
6228+ au_cpup_attr_timesizes(dentry->d_inode);
6229+ di_write_unlock(dentry);
6230+ if (file)
6231+ fi_write_unlock(file);
6232+
6233+ si_read_unlock(sb);
6234+ return err;
6235+}
6236+
6237+/* ---------------------------------------------------------------------- */
6238+
6239+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
6240+{
6241+ int err;
6242+ struct dentry *dentry;
6243+ struct inode *inode;
6244+ struct super_block *sb;
6245+
6246+ dentry = file->f_dentry;
6247+ inode = dentry->d_inode;
6248+ IMustLock(inode);
6249+
6250+ sb = dentry->d_sb;
6251+ si_read_lock(sb, AuLock_FLUSH);
6252+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6253+ if (unlikely(err))
6254+ goto out;
6255+ err = au_vdir_init(file);
6256+ di_downgrade_lock(dentry, AuLock_IR);
6257+ if (unlikely(err))
6258+ goto out_unlock;
6259+
b752ccd1 6260+ if (!au_test_nfsd()) {
1facf9fc 6261+ err = au_vdir_fill_de(file, dirent, filldir);
6262+ fsstack_copy_attr_atime(inode,
6263+ au_h_iptr(inode, au_ibstart(inode)));
6264+ } else {
6265+ /*
6266+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
6267+ * encode_fh() and others.
6268+ */
6269+ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
6270+
6271+ di_read_unlock(dentry, AuLock_IR);
6272+ si_read_unlock(sb);
1facf9fc 6273+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 6274+ fsstack_copy_attr_atime(inode, h_inode);
6275+ fi_write_unlock(file);
6276+
6277+ AuTraceErr(err);
6278+ return err;
6279+ }
6280+
4f0767ce 6281+out_unlock:
1facf9fc 6282+ di_read_unlock(dentry, AuLock_IR);
6283+ fi_write_unlock(file);
4f0767ce 6284+out:
1facf9fc 6285+ si_read_unlock(sb);
6286+ return err;
6287+}
6288+
6289+/* ---------------------------------------------------------------------- */
6290+
6291+#define AuTestEmpty_WHONLY 1
dece6358
AM
6292+#define AuTestEmpty_CALLED (1 << 1)
6293+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 6294+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
6295+#define au_fset_testempty(flags, name) \
6296+ do { (flags) |= AuTestEmpty_##name; } while (0)
6297+#define au_fclr_testempty(flags, name) \
6298+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 6299+
dece6358
AM
6300+#ifndef CONFIG_AUFS_SHWH
6301+#undef AuTestEmpty_SHWH
6302+#define AuTestEmpty_SHWH 0
6303+#endif
6304+
1facf9fc 6305+struct test_empty_arg {
1308ab2a 6306+ struct au_nhash *whlist;
1facf9fc 6307+ unsigned int flags;
6308+ int err;
6309+ aufs_bindex_t bindex;
6310+};
6311+
6312+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
6313+ loff_t offset __maybe_unused, u64 ino,
6314+ unsigned int d_type)
1facf9fc 6315+{
6316+ struct test_empty_arg *arg = __arg;
6317+ char *name = (void *)__name;
6318+
6319+ arg->err = 0;
6320+ au_fset_testempty(arg->flags, CALLED);
6321+ /* smp_mb(); */
6322+ if (name[0] == '.'
6323+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
6324+ goto out; /* success */
6325+
6326+ if (namelen <= AUFS_WH_PFX_LEN
6327+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
6328+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 6329+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6330+ arg->err = -ENOTEMPTY;
6331+ goto out;
6332+ }
6333+
6334+ name += AUFS_WH_PFX_LEN;
6335+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 6336+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6337+ arg->err = au_nhash_append_wh
1308ab2a 6338+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 6339+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 6340+
4f0767ce 6341+out:
1facf9fc 6342+ /* smp_mb(); */
6343+ AuTraceErr(arg->err);
6344+ return arg->err;
6345+}
6346+
6347+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6348+{
6349+ int err;
6350+ struct file *h_file;
6351+
6352+ h_file = au_h_open(dentry, arg->bindex,
6353+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
6354+ /*file*/NULL);
6355+ err = PTR_ERR(h_file);
6356+ if (IS_ERR(h_file))
6357+ goto out;
6358+
6359+ err = 0;
6360+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
6361+ && !h_file->f_dentry->d_inode->i_nlink)
6362+ goto out_put;
6363+
6364+ do {
6365+ arg->err = 0;
6366+ au_fclr_testempty(arg->flags, CALLED);
6367+ /* smp_mb(); */
6368+ err = vfsub_readdir(h_file, test_empty_cb, arg);
6369+ if (err >= 0)
6370+ err = arg->err;
6371+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
6372+
4f0767ce 6373+out_put:
1facf9fc 6374+ fput(h_file);
6375+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 6376+out:
1facf9fc 6377+ return err;
6378+}
6379+
6380+struct do_test_empty_args {
6381+ int *errp;
6382+ struct dentry *dentry;
6383+ struct test_empty_arg *arg;
6384+};
6385+
6386+static void call_do_test_empty(void *args)
6387+{
6388+ struct do_test_empty_args *a = args;
6389+ *a->errp = do_test_empty(a->dentry, a->arg);
6390+}
6391+
6392+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6393+{
6394+ int err, wkq_err;
6395+ struct dentry *h_dentry;
6396+ struct inode *h_inode;
6397+
6398+ h_dentry = au_h_dptr(dentry, arg->bindex);
6399+ h_inode = h_dentry->d_inode;
6400+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
6401+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
6402+ mutex_unlock(&h_inode->i_mutex);
6403+ if (!err)
6404+ err = do_test_empty(dentry, arg);
6405+ else {
6406+ struct do_test_empty_args args = {
6407+ .errp = &err,
6408+ .dentry = dentry,
6409+ .arg = arg
6410+ };
6411+ unsigned int flags = arg->flags;
6412+
6413+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
6414+ if (unlikely(wkq_err))
6415+ err = wkq_err;
6416+ arg->flags = flags;
6417+ }
6418+
6419+ return err;
6420+}
6421+
6422+int au_test_empty_lower(struct dentry *dentry)
6423+{
6424+ int err;
1308ab2a 6425+ unsigned int rdhash;
1facf9fc 6426+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 6427+ struct au_nhash whlist;
1facf9fc 6428+ struct test_empty_arg arg;
1facf9fc 6429+
dece6358
AM
6430+ SiMustAnyLock(dentry->d_sb);
6431+
1308ab2a 6432+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
6433+ if (!rdhash)
6434+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
6435+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 6436+ if (unlikely(err))
1facf9fc 6437+ goto out;
6438+
1facf9fc 6439+ arg.flags = 0;
1308ab2a 6440+ arg.whlist = &whlist;
6441+ bstart = au_dbstart(dentry);
dece6358
AM
6442+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6443+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 6444+ arg.bindex = bstart;
6445+ err = do_test_empty(dentry, &arg);
6446+ if (unlikely(err))
6447+ goto out_whlist;
6448+
6449+ au_fset_testempty(arg.flags, WHONLY);
6450+ btail = au_dbtaildir(dentry);
6451+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
6452+ struct dentry *h_dentry;
6453+
6454+ h_dentry = au_h_dptr(dentry, bindex);
6455+ if (h_dentry && h_dentry->d_inode) {
6456+ arg.bindex = bindex;
6457+ err = do_test_empty(dentry, &arg);
6458+ }
6459+ }
6460+
4f0767ce 6461+out_whlist:
1308ab2a 6462+ au_nhash_wh_free(&whlist);
4f0767ce 6463+out:
1facf9fc 6464+ return err;
6465+}
6466+
6467+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
6468+{
6469+ int err;
6470+ struct test_empty_arg arg;
6471+ aufs_bindex_t bindex, btail;
6472+
6473+ err = 0;
1308ab2a 6474+ arg.whlist = whlist;
1facf9fc 6475+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
6476+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6477+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 6478+ btail = au_dbtaildir(dentry);
6479+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
6480+ struct dentry *h_dentry;
6481+
6482+ h_dentry = au_h_dptr(dentry, bindex);
6483+ if (h_dentry && h_dentry->d_inode) {
6484+ arg.bindex = bindex;
6485+ err = sio_test_empty(dentry, &arg);
6486+ }
6487+ }
6488+
6489+ return err;
6490+}
6491+
6492+/* ---------------------------------------------------------------------- */
6493+
6494+const struct file_operations aufs_dir_fop = {
4a4d8108 6495+ .owner = THIS_MODULE,
1facf9fc 6496+ .read = generic_read_dir,
6497+ .readdir = aufs_readdir,
6498+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
6499+#ifdef CONFIG_COMPAT
6500+ .compat_ioctl = aufs_compat_ioctl_dir,
6501+#endif
1facf9fc 6502+ .open = aufs_open_dir,
6503+ .release = aufs_release_dir,
4a4d8108 6504+ .flush = aufs_flush_dir,
1facf9fc 6505+ .fsync = aufs_fsync_dir
6506+};
7f207e10
AM
6507diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
6508--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
6509+++ linux/fs/aufs/dir.h 2010-11-22 11:52:56.983894369 +0100
b752ccd1 6510@@ -0,0 +1,138 @@
1facf9fc 6511+/*
4a4d8108 6512+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 6513+ *
6514+ * This program, aufs is free software; you can redistribute it and/or modify
6515+ * it under the terms of the GNU General Public License as published by
6516+ * the Free Software Foundation; either version 2 of the License, or
6517+ * (at your option) any later version.
dece6358
AM
6518+ *
6519+ * This program is distributed in the hope that it will be useful,
6520+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6521+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6522+ * GNU General Public License for more details.
6523+ *
6524+ * You should have received a copy of the GNU General Public License
6525+ * along with this program; if not, write to the Free Software
6526+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6527+ */
6528+
6529+/*
6530+ * directory operations
6531+ */
6532+
6533+#ifndef __AUFS_DIR_H__
6534+#define __AUFS_DIR_H__
6535+
6536+#ifdef __KERNEL__
6537+
6538+#include <linux/fs.h>
6539+#include <linux/aufs_type.h>
6540+
6541+/* ---------------------------------------------------------------------- */
6542+
6543+/* need to be faster and smaller */
6544+
6545+struct au_nhash {
dece6358
AM
6546+ unsigned int nh_num;
6547+ struct hlist_head *nh_head;
1facf9fc 6548+};
6549+
6550+struct au_vdir_destr {
6551+ unsigned char len;
6552+ unsigned char name[0];
6553+} __packed;
6554+
6555+struct au_vdir_dehstr {
6556+ struct hlist_node hash;
6557+ struct au_vdir_destr *str;
4a4d8108 6558+} ____cacheline_aligned_in_smp;
1facf9fc 6559+
6560+struct au_vdir_de {
6561+ ino_t de_ino;
6562+ unsigned char de_type;
6563+ /* caution: packed */
6564+ struct au_vdir_destr de_str;
6565+} __packed;
6566+
6567+struct au_vdir_wh {
6568+ struct hlist_node wh_hash;
dece6358
AM
6569+#ifdef CONFIG_AUFS_SHWH
6570+ ino_t wh_ino;
1facf9fc 6571+ aufs_bindex_t wh_bindex;
dece6358
AM
6572+ unsigned char wh_type;
6573+#else
6574+ aufs_bindex_t wh_bindex;
6575+#endif
6576+ /* caution: packed */
1facf9fc 6577+ struct au_vdir_destr wh_str;
6578+} __packed;
6579+
6580+union au_vdir_deblk_p {
6581+ unsigned char *deblk;
6582+ struct au_vdir_de *de;
6583+};
6584+
6585+struct au_vdir {
6586+ unsigned char **vd_deblk;
6587+ unsigned long vd_nblk;
1facf9fc 6588+ struct {
6589+ unsigned long ul;
6590+ union au_vdir_deblk_p p;
6591+ } vd_last;
6592+
6593+ unsigned long vd_version;
dece6358 6594+ unsigned int vd_deblk_sz;
1facf9fc 6595+ unsigned long vd_jiffy;
4a4d8108 6596+} ____cacheline_aligned_in_smp;
1facf9fc 6597+
6598+/* ---------------------------------------------------------------------- */
6599+
6600+/* dir.c */
6601+extern const struct file_operations aufs_dir_fop;
6602+void au_add_nlink(struct inode *dir, struct inode *h_dir);
6603+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 6604+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 6605+int au_test_empty_lower(struct dentry *dentry);
6606+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
6607+
6608+/* vdir.c */
1308ab2a 6609+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
6610+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
6611+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 6612+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
6613+ int limit);
dece6358
AM
6614+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
6615+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
6616+ unsigned int d_type, aufs_bindex_t bindex,
6617+ unsigned char shwh);
1facf9fc 6618+void au_vdir_free(struct au_vdir *vdir);
6619+int au_vdir_init(struct file *file);
6620+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
6621+
6622+/* ioctl.c */
6623+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
6624+
1308ab2a 6625+#ifdef CONFIG_AUFS_RDU
6626+/* rdu.c */
6627+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
6628+#ifdef CONFIG_COMPAT
6629+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6630+ unsigned long arg);
6631+#endif
1308ab2a 6632+#else
6633+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
6634+ unsigned long arg)
6635+{
6636+ return -EINVAL;
6637+}
b752ccd1
AM
6638+#ifdef CONFIG_COMPAT
6639+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6640+ unsigned long arg)
6641+{
6642+ return -EINVAL;
6643+}
6644+#endif
1308ab2a 6645+#endif
6646+
1facf9fc 6647+#endif /* __KERNEL__ */
6648+#endif /* __AUFS_DIR_H__ */
7f207e10
AM
6649diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
6650--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
6651+++ linux/fs/aufs/dynop.c 2010-11-22 11:52:56.983894369 +0100
b752ccd1 6652@@ -0,0 +1,425 @@
1facf9fc 6653+/*
4a4d8108 6654+ * Copyright (C) 2010 Junjiro R. Okajima
1facf9fc 6655+ *
6656+ * This program, aufs is free software; you can redistribute it and/or modify
6657+ * it under the terms of the GNU General Public License as published by
6658+ * the Free Software Foundation; either version 2 of the License, or
6659+ * (at your option) any later version.
dece6358
AM
6660+ *
6661+ * This program is distributed in the hope that it will be useful,
6662+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6663+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6664+ * GNU General Public License for more details.
6665+ *
6666+ * You should have received a copy of the GNU General Public License
6667+ * along with this program; if not, write to the Free Software
6668+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6669+ */
6670+
6671+/*
4a4d8108 6672+ * dynamically customizable operations for regular files
1facf9fc 6673+ */
6674+
1facf9fc 6675+#include "aufs.h"
6676+
4a4d8108 6677+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 6678+
4a4d8108
AM
6679+/*
6680+ * How large will these lists be?
6681+ * Usually just a few elements, 20-30 at most for each, I guess.
6682+ */
6683+static struct au_splhead dynop[AuDyLast];
6684+
6685+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 6686+{
4a4d8108
AM
6687+ struct au_dykey *key, *tmp;
6688+ struct list_head *head;
1facf9fc 6689+
4a4d8108
AM
6690+ key = NULL;
6691+ head = &spl->head;
6692+ rcu_read_lock();
6693+ list_for_each_entry_rcu(tmp, head, dk_list)
6694+ if (tmp->dk_op.dy_hop == h_op) {
6695+ key = tmp;
6696+ kref_get(&key->dk_kref);
6697+ break;
6698+ }
6699+ rcu_read_unlock();
6700+
6701+ return key;
1facf9fc 6702+}
6703+
4a4d8108 6704+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 6705+{
4a4d8108
AM
6706+ struct au_dykey **k, *found;
6707+ const void *h_op = key->dk_op.dy_hop;
6708+ int i;
1facf9fc 6709+
4a4d8108
AM
6710+ found = NULL;
6711+ k = br->br_dykey;
6712+ for (i = 0; i < AuBrDynOp; i++)
6713+ if (k[i]) {
6714+ if (k[i]->dk_op.dy_hop == h_op) {
6715+ found = k[i];
6716+ break;
6717+ }
6718+ } else
6719+ break;
6720+ if (!found) {
6721+ spin_lock(&br->br_dykey_lock);
6722+ for (; i < AuBrDynOp; i++)
6723+ if (k[i]) {
6724+ if (k[i]->dk_op.dy_hop == h_op) {
6725+ found = k[i];
6726+ break;
6727+ }
6728+ } else {
6729+ k[i] = key;
6730+ break;
6731+ }
6732+ spin_unlock(&br->br_dykey_lock);
6733+ BUG_ON(i == AuBrDynOp); /* expand the array */
6734+ }
6735+
6736+ return found;
1facf9fc 6737+}
6738+
4a4d8108
AM
6739+/* kref_get() if @key is already added */
6740+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
6741+{
6742+ struct au_dykey *tmp, *found;
6743+ struct list_head *head;
6744+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 6745+
4a4d8108
AM
6746+ found = NULL;
6747+ head = &spl->head;
6748+ spin_lock(&spl->spin);
6749+ list_for_each_entry(tmp, head, dk_list)
6750+ if (tmp->dk_op.dy_hop == h_op) {
6751+ kref_get(&tmp->dk_kref);
6752+ found = tmp;
6753+ break;
6754+ }
6755+ if (!found)
6756+ list_add_rcu(&key->dk_list, head);
6757+ spin_unlock(&spl->spin);
1facf9fc 6758+
4a4d8108
AM
6759+ if (!found)
6760+ DyPrSym(key);
6761+ return found;
6762+}
6763+
6764+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 6765+{
4a4d8108
AM
6766+ struct au_dykey *key;
6767+
6768+ key = container_of(rcu, struct au_dykey, dk_rcu);
6769+ DyPrSym(key);
6770+ kfree(key);
1facf9fc 6771+}
6772+
4a4d8108
AM
6773+static void dy_free(struct kref *kref)
6774+{
6775+ struct au_dykey *key;
6776+ struct au_splhead *spl;
1facf9fc 6777+
4a4d8108
AM
6778+ key = container_of(kref, struct au_dykey, dk_kref);
6779+ spl = dynop + key->dk_op.dy_type;
6780+ au_spl_del_rcu(&key->dk_list, spl);
6781+ call_rcu(&key->dk_rcu, dy_free_rcu);
6782+}
6783+
6784+void au_dy_put(struct au_dykey *key)
1facf9fc 6785+{
4a4d8108
AM
6786+ kref_put(&key->dk_kref, dy_free);
6787+}
1facf9fc 6788+
4a4d8108
AM
6789+/* ---------------------------------------------------------------------- */
6790+
6791+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
6792+
6793+#ifdef CONFIG_AUFS_DEBUG
6794+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 6795+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
6796+#else
6797+#define DyDbgDeclare(cnt) do {} while (0)
6798+#define DyDbgInc(cnt) do {} while (0)
6799+#endif
6800+
6801+#define DySet(func, dst, src, h_op, h_sb) do { \
6802+ DyDbgInc(cnt); \
6803+ if (h_op->func) { \
6804+ if (src.func) \
6805+ dst.func = src.func; \
6806+ else \
6807+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
6808+ } \
6809+} while (0)
6810+
6811+#define DySetForce(func, dst, src) do { \
6812+ AuDebugOn(!src.func); \
6813+ DyDbgInc(cnt); \
6814+ dst.func = src.func; \
6815+} while (0)
6816+
6817+#define DySetAop(func) \
6818+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
6819+#define DySetAopForce(func) \
6820+ DySetForce(func, dyaop->da_op, aufs_aop)
6821+
6822+static void dy_aop(struct au_dykey *key, const void *h_op,
6823+ struct super_block *h_sb __maybe_unused)
6824+{
6825+ struct au_dyaop *dyaop = (void *)key;
6826+ const struct address_space_operations *h_aop = h_op;
6827+ DyDbgDeclare(cnt);
6828+
6829+ AuDbg("%s\n", au_sbtype(h_sb));
6830+
6831+ DySetAop(writepage);
6832+ DySetAopForce(readpage); /* force */
6833+ DySetAop(sync_page);
6834+ DySetAop(writepages);
6835+ DySetAop(set_page_dirty);
6836+ DySetAop(readpages);
6837+ DySetAop(write_begin);
6838+ DySetAop(write_end);
6839+ DySetAop(bmap);
6840+ DySetAop(invalidatepage);
6841+ DySetAop(releasepage);
6842+ /* these two will be changed according to an aufs mount option */
6843+ DySetAop(direct_IO);
6844+ DySetAop(get_xip_mem);
6845+ DySetAop(migratepage);
6846+ DySetAop(launder_page);
6847+ DySetAop(is_partially_uptodate);
6848+ DySetAop(error_remove_page);
6849+
6850+ DyDbgSize(cnt, *h_aop);
6851+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
6852+}
6853+
6854+#define DySetVmop(func) \
6855+ DySet(func, dyvmop->dv_op, aufs_vm_ops, h_vmop, h_sb)
6856+#define DySetVmopForce(func) \
6857+ DySetForce(func, dyvmop->dv_op, aufs_vm_ops)
6858+
6859+static void dy_vmop(struct au_dykey *key, const void *h_op,
6860+ struct super_block *h_sb __maybe_unused)
6861+{
6862+ struct au_dyvmop *dyvmop = (void *)key;
6863+ const struct vm_operations_struct *h_vmop = h_op;
6864+ DyDbgDeclare(cnt);
6865+
6866+ AuDbg("%s\n", au_sbtype(h_sb));
6867+
6868+ DySetVmop(open);
6869+ DySetVmop(close);
6870+ DySetVmop(fault);
6871+ DySetVmop(page_mkwrite);
6872+ DySetVmop(access);
6873+#ifdef CONFIG_NUMA
6874+ DySetVmop(set_policy);
6875+ DySetVmop(get_policy);
6876+ DySetVmop(migrate);
6877+#endif
6878+
6879+ DyDbgSize(cnt, *h_vmop);
6880+}
6881+
6882+/* ---------------------------------------------------------------------- */
6883+
6884+static void dy_bug(struct kref *kref)
6885+{
6886+ BUG();
6887+}
6888+
6889+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
6890+{
6891+ struct au_dykey *key, *old;
6892+ struct au_splhead *spl;
b752ccd1 6893+ struct op {
4a4d8108 6894+ unsigned int sz;
b752ccd1
AM
6895+ void (*set)(struct au_dykey *key, const void *h_op,
6896+ struct super_block *h_sb __maybe_unused);
6897+ };
6898+ static const struct op a[] = {
4a4d8108
AM
6899+ [AuDy_AOP] = {
6900+ .sz = sizeof(struct au_dyaop),
b752ccd1 6901+ .set = dy_aop
4a4d8108
AM
6902+ },
6903+ [AuDy_VMOP] = {
6904+ .sz = sizeof(struct au_dyvmop),
b752ccd1 6905+ .set = dy_vmop
4a4d8108 6906+ }
b752ccd1
AM
6907+ };
6908+ const struct op *p;
4a4d8108
AM
6909+
6910+ spl = dynop + op->dy_type;
6911+ key = dy_gfind_get(spl, op->dy_hop);
6912+ if (key)
6913+ goto out_add; /* success */
6914+
6915+ p = a + op->dy_type;
6916+ key = kzalloc(p->sz, GFP_NOFS);
6917+ if (unlikely(!key)) {
6918+ key = ERR_PTR(-ENOMEM);
6919+ goto out;
6920+ }
6921+
6922+ key->dk_op.dy_hop = op->dy_hop;
6923+ kref_init(&key->dk_kref);
b752ccd1 6924+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
6925+ old = dy_gadd(spl, key);
6926+ if (old) {
6927+ kfree(key);
6928+ key = old;
6929+ }
6930+
6931+out_add:
6932+ old = dy_bradd(br, key);
6933+ if (old)
6934+ /* its ref-count should never be zero here */
6935+ kref_put(&key->dk_kref, dy_bug);
6936+out:
6937+ return key;
6938+}
6939+
6940+/* ---------------------------------------------------------------------- */
6941+/*
6942+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
6943+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
6944+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
6945+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
6946+ * See the aufs manual in detail.
6947+ *
6948+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
6949+ * performance of fadvise() and madvise() may be affected.
6950+ */
6951+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
6952+{
6953+ if (!do_dx) {
6954+ dyaop->da_op.direct_IO = NULL;
6955+ dyaop->da_op.get_xip_mem = NULL;
6956+ } else {
6957+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
6958+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
6959+ if (!dyaop->da_get_xip_mem)
6960+ dyaop->da_op.get_xip_mem = NULL;
6961+ }
6962+}
6963+
6964+static struct au_dyaop *dy_aget(struct au_branch *br,
6965+ const struct address_space_operations *h_aop,
6966+ int do_dx)
6967+{
6968+ struct au_dyaop *dyaop;
6969+ struct au_dynop op;
6970+
6971+ op.dy_type = AuDy_AOP;
6972+ op.dy_haop = h_aop;
6973+ dyaop = (void *)dy_get(&op, br);
6974+ if (IS_ERR(dyaop))
6975+ goto out;
6976+ dy_adx(dyaop, do_dx);
6977+
6978+out:
6979+ return dyaop;
6980+}
6981+
6982+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
6983+ struct inode *h_inode)
6984+{
6985+ int err, do_dx;
6986+ struct super_block *sb;
6987+ struct au_branch *br;
6988+ struct au_dyaop *dyaop;
6989+
6990+ AuDebugOn(!S_ISREG(h_inode->i_mode));
6991+ IiMustWriteLock(inode);
6992+
6993+ sb = inode->i_sb;
6994+ br = au_sbr(sb, bindex);
6995+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
6996+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
6997+ err = PTR_ERR(dyaop);
6998+ if (IS_ERR(dyaop))
6999+ /* unnecessary to call dy_fput() */
7000+ goto out;
7001+
7002+ err = 0;
7003+ inode->i_mapping->a_ops = &dyaop->da_op;
7004+
7005+out:
7006+ return err;
7007+}
7008+
b752ccd1
AM
7009+/*
7010+ * Is it safe to replace a_ops during the inode/file is in operation?
7011+ * Yes, I hope so.
7012+ */
7013+int au_dy_irefresh(struct inode *inode)
7014+{
7015+ int err;
7016+ aufs_bindex_t bstart;
7017+ struct inode *h_inode;
7018+
7019+ err = 0;
7020+ if (S_ISREG(inode->i_mode)) {
7021+ bstart = au_ibstart(inode);
7022+ h_inode = au_h_iptr(inode, bstart);
7023+ err = au_dy_iaop(inode, bstart, h_inode);
7024+ }
7025+ return err;
7026+}
7027+
4a4d8108
AM
7028+void au_dy_arefresh(int do_dx)
7029+{
7030+ struct au_splhead *spl;
7031+ struct list_head *head;
7032+ struct au_dykey *key;
7033+
7034+ spl = dynop + AuDy_AOP;
7035+ head = &spl->head;
7036+ spin_lock(&spl->spin);
7037+ list_for_each_entry(key, head, dk_list)
7038+ dy_adx((void *)key, do_dx);
7039+ spin_unlock(&spl->spin);
7040+}
7041+
7042+const struct vm_operations_struct *
7043+au_dy_vmop(struct file *file, struct au_branch *br,
7044+ const struct vm_operations_struct *h_vmop)
7045+{
7046+ struct au_dyvmop *dyvmop;
7047+ struct au_dynop op;
7048+
7049+ op.dy_type = AuDy_VMOP;
7050+ op.dy_hvmop = h_vmop;
7051+ dyvmop = (void *)dy_get(&op, br);
7052+ if (IS_ERR(dyvmop))
7053+ return (void *)dyvmop;
7054+ return &dyvmop->dv_op;
7055+}
7056+
7057+/* ---------------------------------------------------------------------- */
7058+
7059+void __init au_dy_init(void)
7060+{
7061+ int i;
7062+
7063+ /* make sure that 'struct au_dykey *' can be any type */
7064+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
7065+ BUILD_BUG_ON(offsetof(struct au_dyvmop, dv_key));
7066+
7067+ for (i = 0; i < AuDyLast; i++)
7068+ au_spl_init(dynop + i);
7069+}
7070+
7071+void au_dy_fin(void)
7072+{
7073+ int i;
7074+
7075+ for (i = 0; i < AuDyLast; i++)
7076+ WARN_ON(!list_empty(&dynop[i].head));
7077+}
7f207e10
AM
7078diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
7079--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
7080+++ linux/fs/aufs/dynop.h 2010-11-22 11:52:56.983894369 +0100
b752ccd1 7081@@ -0,0 +1,89 @@
4a4d8108
AM
7082+/*
7083+ * Copyright (C) 2010 Junjiro R. Okajima
7084+ *
7085+ * This program, aufs is free software; you can redistribute it and/or modify
7086+ * it under the terms of the GNU General Public License as published by
7087+ * the Free Software Foundation; either version 2 of the License, or
7088+ * (at your option) any later version.
7089+ *
7090+ * This program is distributed in the hope that it will be useful,
7091+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7092+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7093+ * GNU General Public License for more details.
7094+ *
7095+ * You should have received a copy of the GNU General Public License
7096+ * along with this program; if not, write to the Free Software
7097+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7098+ */
7099+
7100+/*
7101+ * dynamically customizable operations (for regular files only)
7102+ */
7103+
7104+#ifndef __AUFS_DYNOP_H__
7105+#define __AUFS_DYNOP_H__
7106+
7107+#ifdef __KERNEL__
7108+
7109+#include <linux/fs.h>
7110+#include <linux/mm.h>
7111+#include <linux/rcupdate.h>
7112+#include <linux/aufs_type.h>
7113+#include "inode.h"
7114+
7115+enum {AuDy_AOP, AuDy_VMOP, AuDyLast};
7116+
7117+struct au_dynop {
7118+ int dy_type;
7119+ union {
7120+ const void *dy_hop;
7121+ const struct address_space_operations *dy_haop;
7122+ const struct vm_operations_struct *dy_hvmop;
7123+ };
7124+};
7125+
7126+struct au_dykey {
7127+ union {
7128+ struct list_head dk_list;
7129+ struct rcu_head dk_rcu;
7130+ };
7131+ struct au_dynop dk_op;
7132+
7133+ /*
7134+ * during I am in the branch local array, kref is gotten. when the
7135+ * branch is removed, kref is put.
7136+ */
7137+ struct kref dk_kref;
7138+};
7139+
7140+/* stop unioning since their sizes are very different from each other */
7141+struct au_dyaop {
7142+ struct au_dykey da_key;
7143+ struct address_space_operations da_op; /* not const */
7144+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
7145+ void **, unsigned long *);
7146+};
7147+
7148+struct au_dyvmop {
7149+ struct au_dykey dv_key;
7150+ struct vm_operations_struct dv_op; /* not const */
7151+};
7152+
7153+/* ---------------------------------------------------------------------- */
7154+
7155+/* dynop.c */
7156+struct au_branch;
7157+void au_dy_put(struct au_dykey *key);
7158+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
7159+ struct inode *h_inode);
b752ccd1 7160+int au_dy_irefresh(struct inode *inode);
4a4d8108
AM
7161+void au_dy_arefresh(int do_dio);
7162+const struct vm_operations_struct *
7163+au_dy_vmop(struct file *file, struct au_branch *br,
7164+ const struct vm_operations_struct *h_vmop);
7165+
7166+void __init au_dy_init(void);
7167+void au_dy_fin(void);
7168+
4a4d8108
AM
7169+#endif /* __KERNEL__ */
7170+#endif /* __AUFS_DYNOP_H__ */
7f207e10
AM
7171diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
7172--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
7173+++ linux/fs/aufs/export.c 2010-11-22 11:52:56.987228248 +0100
0c5527e5 7174@@ -0,0 +1,790 @@
4a4d8108
AM
7175+/*
7176+ * Copyright (C) 2005-2010 Junjiro R. Okajima
7177+ *
7178+ * This program, aufs is free software; you can redistribute it and/or modify
7179+ * it under the terms of the GNU General Public License as published by
7180+ * the Free Software Foundation; either version 2 of the License, or
7181+ * (at your option) any later version.
7182+ *
7183+ * This program is distributed in the hope that it will be useful,
7184+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7185+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7186+ * GNU General Public License for more details.
7187+ *
7188+ * You should have received a copy of the GNU General Public License
7189+ * along with this program; if not, write to the Free Software
7190+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7191+ */
7192+
7193+/*
7194+ * export via nfs
7195+ */
7196+
7197+#include <linux/exportfs.h>
7198+#include <linux/file.h>
7199+#include <linux/mnt_namespace.h>
7200+#include <linux/namei.h>
7201+#include <linux/nsproxy.h>
7202+#include <linux/random.h>
7203+#include <linux/writeback.h>
7204+#include "aufs.h"
7205+
7206+union conv {
7207+#ifdef CONFIG_AUFS_INO_T_64
7208+ __u32 a[2];
7209+#else
7210+ __u32 a[1];
7211+#endif
7212+ ino_t ino;
7213+};
7214+
7215+static ino_t decode_ino(__u32 *a)
7216+{
7217+ union conv u;
7218+
7219+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
7220+ u.a[0] = a[0];
7221+#ifdef CONFIG_AUFS_INO_T_64
7222+ u.a[1] = a[1];
7223+#endif
7224+ return u.ino;
7225+}
7226+
7227+static void encode_ino(__u32 *a, ino_t ino)
7228+{
7229+ union conv u;
7230+
7231+ u.ino = ino;
7232+ a[0] = u.a[0];
7233+#ifdef CONFIG_AUFS_INO_T_64
7234+ a[1] = u.a[1];
7235+#endif
7236+}
7237+
7238+/* NFS file handle */
7239+enum {
7240+ Fh_br_id,
7241+ Fh_sigen,
7242+#ifdef CONFIG_AUFS_INO_T_64
7243+ /* support 64bit inode number */
7244+ Fh_ino1,
7245+ Fh_ino2,
7246+ Fh_dir_ino1,
7247+ Fh_dir_ino2,
7248+#else
7249+ Fh_ino1,
7250+ Fh_dir_ino1,
7251+#endif
7252+ Fh_igen,
7253+ Fh_h_type,
7254+ Fh_tail,
7255+
7256+ Fh_ino = Fh_ino1,
7257+ Fh_dir_ino = Fh_dir_ino1
7258+};
7259+
7260+static int au_test_anon(struct dentry *dentry)
7261+{
7262+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
7263+}
7264+
7265+/* ---------------------------------------------------------------------- */
7266+/* inode generation external table */
7267+
b752ccd1 7268+void au_xigen_inc(struct inode *inode)
4a4d8108 7269+{
4a4d8108
AM
7270+ loff_t pos;
7271+ ssize_t sz;
7272+ __u32 igen;
7273+ struct super_block *sb;
7274+ struct au_sbinfo *sbinfo;
7275+
4a4d8108 7276+ sb = inode->i_sb;
b752ccd1 7277+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 7278+
b752ccd1 7279+ sbinfo = au_sbi(sb);
1facf9fc 7280+ pos = inode->i_ino;
7281+ pos *= sizeof(igen);
7282+ igen = inode->i_generation + 1;
1facf9fc 7283+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
7284+ sizeof(igen), &pos);
7285+ if (sz == sizeof(igen))
b752ccd1 7286+ return; /* success */
1facf9fc 7287+
b752ccd1 7288+ if (unlikely(sz >= 0))
1facf9fc 7289+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 7290+}
7291+
7292+int au_xigen_new(struct inode *inode)
7293+{
7294+ int err;
7295+ loff_t pos;
7296+ ssize_t sz;
7297+ struct super_block *sb;
7298+ struct au_sbinfo *sbinfo;
7299+ struct file *file;
7300+
7301+ err = 0;
7302+ /* todo: dirty, at mount time */
7303+ if (inode->i_ino == AUFS_ROOT_INO)
7304+ goto out;
7305+ sb = inode->i_sb;
dece6358 7306+ SiMustAnyLock(sb);
1facf9fc 7307+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7308+ goto out;
7309+
7310+ err = -EFBIG;
7311+ pos = inode->i_ino;
7312+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
7313+ AuIOErr1("too large i%lld\n", pos);
7314+ goto out;
7315+ }
7316+ pos *= sizeof(inode->i_generation);
7317+
7318+ err = 0;
7319+ sbinfo = au_sbi(sb);
7320+ file = sbinfo->si_xigen;
7321+ BUG_ON(!file);
7322+
7323+ if (i_size_read(file->f_dentry->d_inode)
7324+ < pos + sizeof(inode->i_generation)) {
7325+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
7326+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
7327+ sizeof(inode->i_generation), &pos);
7328+ } else
7329+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
7330+ sizeof(inode->i_generation), &pos);
7331+ if (sz == sizeof(inode->i_generation))
7332+ goto out; /* success */
7333+
7334+ err = sz;
7335+ if (unlikely(sz >= 0)) {
7336+ err = -EIO;
7337+ AuIOErr("xigen error (%zd)\n", sz);
7338+ }
7339+
4f0767ce 7340+out:
1facf9fc 7341+ return err;
7342+}
7343+
7344+int au_xigen_set(struct super_block *sb, struct file *base)
7345+{
7346+ int err;
7347+ struct au_sbinfo *sbinfo;
7348+ struct file *file;
7349+
dece6358
AM
7350+ SiMustWriteLock(sb);
7351+
1facf9fc 7352+ sbinfo = au_sbi(sb);
7353+ file = au_xino_create2(base, sbinfo->si_xigen);
7354+ err = PTR_ERR(file);
7355+ if (IS_ERR(file))
7356+ goto out;
7357+ err = 0;
7358+ if (sbinfo->si_xigen)
7359+ fput(sbinfo->si_xigen);
7360+ sbinfo->si_xigen = file;
7361+
4f0767ce 7362+out:
1facf9fc 7363+ return err;
7364+}
7365+
7366+void au_xigen_clr(struct super_block *sb)
7367+{
7368+ struct au_sbinfo *sbinfo;
7369+
dece6358
AM
7370+ SiMustWriteLock(sb);
7371+
1facf9fc 7372+ sbinfo = au_sbi(sb);
7373+ if (sbinfo->si_xigen) {
7374+ fput(sbinfo->si_xigen);
7375+ sbinfo->si_xigen = NULL;
7376+ }
7377+}
7378+
7379+/* ---------------------------------------------------------------------- */
7380+
7381+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
7382+ ino_t dir_ino)
7383+{
7384+ struct dentry *dentry, *d;
7385+ struct inode *inode;
7386+ unsigned int sigen;
7387+
7388+ dentry = NULL;
7389+ inode = ilookup(sb, ino);
7390+ if (!inode)
7391+ goto out;
7392+
7393+ dentry = ERR_PTR(-ESTALE);
7394+ sigen = au_sigen(sb);
7395+ if (unlikely(is_bad_inode(inode)
7396+ || IS_DEADDIR(inode)
7397+ || sigen != au_iigen(inode)))
7398+ goto out_iput;
7399+
7400+ dentry = NULL;
7401+ if (!dir_ino || S_ISDIR(inode->i_mode))
7402+ dentry = d_find_alias(inode);
7403+ else {
7404+ spin_lock(&dcache_lock);
7405+ list_for_each_entry(d, &inode->i_dentry, d_alias)
7406+ if (!au_test_anon(d)
7407+ && d->d_parent->d_inode->i_ino == dir_ino) {
7408+ dentry = dget_locked(d);
7409+ break;
7410+ }
7411+ spin_unlock(&dcache_lock);
7412+ }
7413+ if (unlikely(dentry && sigen != au_digen(dentry))) {
7414+ dput(dentry);
7415+ dentry = ERR_PTR(-ESTALE);
7416+ }
7417+
4f0767ce 7418+out_iput:
1facf9fc 7419+ iput(inode);
4f0767ce 7420+out:
1facf9fc 7421+ return dentry;
7422+}
7423+
7424+/* ---------------------------------------------------------------------- */
7425+
7426+/* todo: dirty? */
7427+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
7428+
7429+struct au_compare_mnt_args {
7430+ /* input */
7431+ struct super_block *sb;
7432+
7433+ /* output */
7434+ struct vfsmount *mnt;
7435+};
7436+
7437+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
7438+{
7439+ struct au_compare_mnt_args *a = arg;
7440+
7441+ if (mnt->mnt_sb != a->sb)
7442+ return 0;
7443+ a->mnt = mntget(mnt);
7444+ return 1;
7445+}
7446+
1facf9fc 7447+static struct vfsmount *au_mnt_get(struct super_block *sb)
7448+{
4a4d8108
AM
7449+ int err;
7450+ struct au_compare_mnt_args args = {
7451+ .sb = sb
7452+ };
1facf9fc 7453+ struct mnt_namespace *ns;
1facf9fc 7454+
0c5527e5 7455+ br_read_lock(vfsmount_lock);
1facf9fc 7456+ /* no get/put ?? */
7457+ AuDebugOn(!current->nsproxy);
7458+ ns = current->nsproxy->mnt_ns;
7459+ AuDebugOn(!ns);
4a4d8108 7460+ err = iterate_mounts(au_compare_mnt, &args, ns->root);
0c5527e5 7461+ br_read_unlock(vfsmount_lock);
4a4d8108
AM
7462+ AuDebugOn(!err);
7463+ AuDebugOn(!args.mnt);
7464+ return args.mnt;
1facf9fc 7465+}
7466+
7467+struct au_nfsd_si_lock {
4a4d8108
AM
7468+ unsigned int sigen;
7469+ aufs_bindex_t br_id;
1facf9fc 7470+ unsigned char force_lock;
7471+};
7472+
7473+static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
7474+ struct au_nfsd_si_lock *nsi_lock)
7475+{
7476+ aufs_bindex_t bindex;
7477+
7478+ si_read_lock(sb, AuLock_FLUSH);
7479+
7480+ /* branch id may be wrapped around */
7481+ bindex = au_br_index(sb, nsi_lock->br_id);
7482+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
7483+ goto out; /* success */
7484+
7485+ if (!nsi_lock->force_lock)
7486+ si_read_unlock(sb);
7487+ bindex = -1;
7488+
4f0767ce 7489+out:
1facf9fc 7490+ return bindex;
7491+}
7492+
7493+struct find_name_by_ino {
7494+ int called, found;
7495+ ino_t ino;
7496+ char *name;
7497+ int namelen;
7498+};
7499+
7500+static int
7501+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
7502+ u64 ino, unsigned int d_type)
7503+{
7504+ struct find_name_by_ino *a = arg;
7505+
7506+ a->called++;
7507+ if (a->ino != ino)
7508+ return 0;
7509+
7510+ memcpy(a->name, name, namelen);
7511+ a->namelen = namelen;
7512+ a->found = 1;
7513+ return 1;
7514+}
7515+
7516+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
7517+ struct au_nfsd_si_lock *nsi_lock)
7518+{
7519+ struct dentry *dentry, *parent;
7520+ struct file *file;
7521+ struct inode *dir;
7522+ struct find_name_by_ino arg;
7523+ int err;
7524+
7525+ parent = path->dentry;
7526+ if (nsi_lock)
7527+ si_read_unlock(parent->d_sb);
4a4d8108 7528+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 7529+ dentry = (void *)file;
7530+ if (IS_ERR(file))
7531+ goto out;
7532+
7533+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 7534+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 7535+ if (unlikely(!arg.name))
7536+ goto out_file;
7537+ arg.ino = ino;
7538+ arg.found = 0;
7539+ do {
7540+ arg.called = 0;
7541+ /* smp_mb(); */
7542+ err = vfsub_readdir(file, find_name_by_ino, &arg);
7543+ } while (!err && !arg.found && arg.called);
7544+ dentry = ERR_PTR(err);
7545+ if (unlikely(err))
7546+ goto out_name;
7547+ dentry = ERR_PTR(-ENOENT);
7548+ if (!arg.found)
7549+ goto out_name;
7550+
7551+ /* do not call au_lkup_one() */
7552+ dir = parent->d_inode;
7553+ mutex_lock(&dir->i_mutex);
7554+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
7555+ mutex_unlock(&dir->i_mutex);
7556+ AuTraceErrPtr(dentry);
7557+ if (IS_ERR(dentry))
7558+ goto out_name;
7559+ AuDebugOn(au_test_anon(dentry));
7560+ if (unlikely(!dentry->d_inode)) {
7561+ dput(dentry);
7562+ dentry = ERR_PTR(-ENOENT);
7563+ }
7564+
4f0767ce 7565+out_name:
1facf9fc 7566+ __putname(arg.name);
4f0767ce 7567+out_file:
1facf9fc 7568+ fput(file);
4f0767ce 7569+out:
1facf9fc 7570+ if (unlikely(nsi_lock
7571+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
7572+ if (!IS_ERR(dentry)) {
7573+ dput(dentry);
7574+ dentry = ERR_PTR(-ESTALE);
7575+ }
7576+ AuTraceErrPtr(dentry);
7577+ return dentry;
7578+}
7579+
7580+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
7581+ ino_t dir_ino,
7582+ struct au_nfsd_si_lock *nsi_lock)
7583+{
7584+ struct dentry *dentry;
7585+ struct path path;
7586+
7587+ if (dir_ino != AUFS_ROOT_INO) {
7588+ path.dentry = decode_by_ino(sb, dir_ino, 0);
7589+ dentry = path.dentry;
7590+ if (!path.dentry || IS_ERR(path.dentry))
7591+ goto out;
7592+ AuDebugOn(au_test_anon(path.dentry));
7593+ } else
7594+ path.dentry = dget(sb->s_root);
7595+
7596+ path.mnt = au_mnt_get(sb);
7597+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
7598+ path_put(&path);
7599+
4f0767ce 7600+out:
1facf9fc 7601+ AuTraceErrPtr(dentry);
7602+ return dentry;
7603+}
7604+
7605+/* ---------------------------------------------------------------------- */
7606+
7607+static int h_acceptable(void *expv, struct dentry *dentry)
7608+{
7609+ return 1;
7610+}
7611+
7612+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
7613+ char *buf, int len, struct super_block *sb)
7614+{
7615+ char *p;
7616+ int n;
7617+ struct path path;
7618+
7619+ p = d_path(h_rootpath, buf, len);
7620+ if (IS_ERR(p))
7621+ goto out;
7622+ n = strlen(p);
7623+
7624+ path.mnt = h_rootpath->mnt;
7625+ path.dentry = h_parent;
7626+ p = d_path(&path, buf, len);
7627+ if (IS_ERR(p))
7628+ goto out;
7629+ if (n != 1)
7630+ p += n;
7631+
7632+ path.mnt = au_mnt_get(sb);
7633+ path.dentry = sb->s_root;
7634+ p = d_path(&path, buf, len - strlen(p));
7635+ mntput(path.mnt);
7636+ if (IS_ERR(p))
7637+ goto out;
7638+ if (n != 1)
7639+ p[strlen(p)] = '/';
7640+
4f0767ce 7641+out:
1facf9fc 7642+ AuTraceErrPtr(p);
7643+ return p;
7644+}
7645+
7646+static
7647+struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
7648+ ino_t ino, __u32 *fh, int fh_len,
7649+ struct au_nfsd_si_lock *nsi_lock)
7650+{
7651+ struct dentry *dentry, *h_parent, *root;
7652+ struct super_block *h_sb;
7653+ char *pathname, *p;
7654+ struct vfsmount *h_mnt;
7655+ struct au_branch *br;
7656+ int err;
7657+ struct path path;
7658+
7659+ br = au_sbr(sb, bindex);
7660+ /* au_br_get(br); */
7661+ h_mnt = br->br_mnt;
7662+ h_sb = h_mnt->mnt_sb;
7663+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
7664+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
7665+ fh_len - Fh_tail, fh[Fh_h_type],
7666+ h_acceptable, /*context*/NULL);
7667+ dentry = h_parent;
7668+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
7669+ AuWarn1("%s decode_fh failed, %ld\n",
7670+ au_sbtype(h_sb), PTR_ERR(h_parent));
7671+ goto out;
7672+ }
7673+ dentry = NULL;
7674+ if (unlikely(au_test_anon(h_parent))) {
7675+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
7676+ au_sbtype(h_sb));
7677+ goto out_h_parent;
7678+ }
7679+
7680+ dentry = ERR_PTR(-ENOMEM);
7681+ pathname = (void *)__get_free_page(GFP_NOFS);
7682+ if (unlikely(!pathname))
7683+ goto out_h_parent;
7684+
7685+ root = sb->s_root;
7686+ path.mnt = h_mnt;
7687+ di_read_lock_parent(root, !AuLock_IR);
7688+ path.dentry = au_h_dptr(root, bindex);
7689+ di_read_unlock(root, !AuLock_IR);
7690+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
7691+ dentry = (void *)p;
7692+ if (IS_ERR(p))
7693+ goto out_pathname;
7694+
7695+ si_read_unlock(sb);
7696+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
7697+ dentry = ERR_PTR(err);
7698+ if (unlikely(err))
7699+ goto out_relock;
7700+
7701+ dentry = ERR_PTR(-ENOENT);
7702+ AuDebugOn(au_test_anon(path.dentry));
7703+ if (unlikely(!path.dentry->d_inode))
7704+ goto out_path;
7705+
7706+ if (ino != path.dentry->d_inode->i_ino)
7707+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
7708+ else
7709+ dentry = dget(path.dentry);
7710+
4f0767ce 7711+out_path:
1facf9fc 7712+ path_put(&path);
4f0767ce 7713+out_relock:
1facf9fc 7714+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
7715+ if (!IS_ERR(dentry)) {
7716+ dput(dentry);
7717+ dentry = ERR_PTR(-ESTALE);
7718+ }
4f0767ce 7719+out_pathname:
1facf9fc 7720+ free_page((unsigned long)pathname);
4f0767ce 7721+out_h_parent:
1facf9fc 7722+ dput(h_parent);
4f0767ce 7723+out:
1facf9fc 7724+ /* au_br_put(br); */
7725+ AuTraceErrPtr(dentry);
7726+ return dentry;
7727+}
7728+
7729+/* ---------------------------------------------------------------------- */
7730+
7731+static struct dentry *
7732+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
7733+ int fh_type)
7734+{
7735+ struct dentry *dentry;
7736+ __u32 *fh = fid->raw;
7737+ ino_t ino, dir_ino;
7738+ aufs_bindex_t bindex;
7739+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 7740+ .force_lock = 0
7741+ };
7742+
1facf9fc 7743+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
7744+ /* it should never happen, but the file handle is unreliable */
7745+ if (unlikely(fh_len < Fh_tail))
7746+ goto out;
7747+ nsi_lock.sigen = fh[Fh_sigen];
7748+ nsi_lock.br_id = fh[Fh_br_id];
7749+
1facf9fc 7750+ /* branch id may be wrapped around */
7751+ bindex = si_nfsd_read_lock(sb, &nsi_lock);
7752+ if (unlikely(bindex < 0))
7753+ goto out;
7754+ nsi_lock.force_lock = 1;
7755+
7756+ /* is this inode still cached? */
7757+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
7758+ /* it should never happen */
7759+ if (unlikely(ino == AUFS_ROOT_INO))
7760+ goto out;
7761+
1facf9fc 7762+ dir_ino = decode_ino(fh + Fh_dir_ino);
7763+ dentry = decode_by_ino(sb, ino, dir_ino);
7764+ if (IS_ERR(dentry))
7765+ goto out_unlock;
7766+ if (dentry)
7767+ goto accept;
7768+
7769+ /* is the parent dir cached? */
7770+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
7771+ if (IS_ERR(dentry))
7772+ goto out_unlock;
7773+ if (dentry)
7774+ goto accept;
7775+
7776+ /* lookup path */
7777+ dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
7778+ if (IS_ERR(dentry))
7779+ goto out_unlock;
7780+ if (unlikely(!dentry))
7781+ /* todo?: make it ESTALE */
7782+ goto out_unlock;
7783+
4f0767ce 7784+accept:
1facf9fc 7785+ if (dentry->d_inode->i_generation == fh[Fh_igen])
7786+ goto out_unlock; /* success */
7787+
7788+ dput(dentry);
7789+ dentry = ERR_PTR(-ESTALE);
4f0767ce 7790+out_unlock:
1facf9fc 7791+ si_read_unlock(sb);
4f0767ce 7792+out:
1facf9fc 7793+ AuTraceErrPtr(dentry);
7794+ return dentry;
7795+}
7796+
7797+#if 0 /* reserved for future use */
7798+/* support subtreecheck option */
7799+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
7800+ int fh_len, int fh_type)
7801+{
7802+ struct dentry *parent;
7803+ __u32 *fh = fid->raw;
7804+ ino_t dir_ino;
7805+
7806+ dir_ino = decode_ino(fh + Fh_dir_ino);
7807+ parent = decode_by_ino(sb, dir_ino, 0);
7808+ if (IS_ERR(parent))
7809+ goto out;
7810+ if (!parent)
7811+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
7812+ dir_ino, fh, fh_len);
7813+
4f0767ce 7814+out:
1facf9fc 7815+ AuTraceErrPtr(parent);
7816+ return parent;
7817+}
7818+#endif
7819+
7820+/* ---------------------------------------------------------------------- */
7821+
7822+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
7823+ int connectable)
7824+{
7825+ int err;
7826+ aufs_bindex_t bindex, bend;
7827+ struct super_block *sb, *h_sb;
7828+ struct inode *inode;
7829+ struct dentry *parent, *h_parent;
7830+ struct au_branch *br;
7831+
7832+ AuDebugOn(au_test_anon(dentry));
7833+
7834+ parent = NULL;
7835+ err = -ENOSPC;
7836+ if (unlikely(*max_len <= Fh_tail)) {
7837+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
7838+ goto out;
7839+ }
7840+
7841+ err = FILEID_ROOT;
7842+ if (IS_ROOT(dentry)) {
7843+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
7844+ goto out;
7845+ }
7846+
7847+ err = -EIO;
7848+ h_parent = NULL;
7849+ sb = dentry->d_sb;
7850+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
7851+ parent = dget_parent(dentry);
7852+ di_read_lock_parent(parent, !AuLock_IR);
7853+ inode = dentry->d_inode;
7854+ AuDebugOn(!inode);
7855+#ifdef CONFIG_AUFS_DEBUG
7856+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7857+ AuWarn1("NFS-exporting requires xino\n");
7858+#endif
7859+
7860+ bend = au_dbtaildir(parent);
7861+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
7862+ h_parent = au_h_dptr(parent, bindex);
7863+ if (h_parent) {
7864+ dget(h_parent);
7865+ break;
7866+ }
7867+ }
7868+ if (unlikely(!h_parent))
7869+ goto out_unlock;
7870+
7871+ err = -EPERM;
7872+ br = au_sbr(sb, bindex);
7873+ h_sb = br->br_mnt->mnt_sb;
7874+ if (unlikely(!h_sb->s_export_op)) {
7875+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
7876+ goto out_dput;
7877+ }
7878+
7879+ fh[Fh_br_id] = br->br_id;
7880+ fh[Fh_sigen] = au_sigen(sb);
7881+ encode_ino(fh + Fh_ino, inode->i_ino);
7882+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
7883+ fh[Fh_igen] = inode->i_generation;
7884+
7885+ *max_len -= Fh_tail;
7886+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
7887+ max_len,
7888+ /*connectable or subtreecheck*/0);
7889+ err = fh[Fh_h_type];
7890+ *max_len += Fh_tail;
7891+ /* todo: macros? */
7892+ if (err != 255)
7893+ err = 99;
7894+ else
7895+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
7896+
4f0767ce 7897+out_dput:
1facf9fc 7898+ dput(h_parent);
4f0767ce 7899+out_unlock:
1facf9fc 7900+ di_read_unlock(parent, !AuLock_IR);
7901+ dput(parent);
7902+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 7903+out:
1facf9fc 7904+ if (unlikely(err < 0))
7905+ err = 255;
7906+ return err;
7907+}
7908+
7909+/* ---------------------------------------------------------------------- */
7910+
4a4d8108
AM
7911+static int aufs_commit_metadata(struct inode *inode)
7912+{
7913+ int err;
7914+ aufs_bindex_t bindex;
7915+ struct super_block *sb;
7916+ struct inode *h_inode;
7917+ int (*f)(struct inode *inode);
7918+
7919+ sb = inode->i_sb;
e49829fe 7920+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
7921+ ii_write_lock_child(inode);
7922+ bindex = au_ibstart(inode);
7923+ AuDebugOn(bindex < 0);
7924+ h_inode = au_h_iptr(inode, bindex);
7925+
7926+ f = h_inode->i_sb->s_export_op->commit_metadata;
7927+ if (f)
7928+ err = f(h_inode);
7929+ else {
7930+ struct writeback_control wbc = {
7931+ .sync_mode = WB_SYNC_ALL,
7932+ .nr_to_write = 0 /* metadata only */
7933+ };
7934+
7935+ err = sync_inode(h_inode, &wbc);
7936+ }
7937+
7938+ au_cpup_attr_timesizes(inode);
7939+ ii_write_unlock(inode);
7940+ si_read_unlock(sb);
7941+ return err;
7942+}
7943+
7944+/* ---------------------------------------------------------------------- */
7945+
1facf9fc 7946+static struct export_operations aufs_export_op = {
4a4d8108 7947+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 7948+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
7949+ .encode_fh = aufs_encode_fh,
7950+ .commit_metadata = aufs_commit_metadata
1facf9fc 7951+};
7952+
7953+void au_export_init(struct super_block *sb)
7954+{
7955+ struct au_sbinfo *sbinfo;
7956+ __u32 u;
7957+
7958+ sb->s_export_op = &aufs_export_op;
7959+ sbinfo = au_sbi(sb);
7960+ sbinfo->si_xigen = NULL;
7961+ get_random_bytes(&u, sizeof(u));
7962+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
7963+ atomic_set(&sbinfo->si_xigen_next, u);
7964+}
7f207e10
AM
7965diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
7966--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
7967+++ linux/fs/aufs/file.c 2010-11-22 11:52:56.987228248 +0100
7968@@ -0,0 +1,655 @@
1facf9fc 7969+/*
4a4d8108 7970+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 7971+ *
7972+ * This program, aufs is free software; you can redistribute it and/or modify
7973+ * it under the terms of the GNU General Public License as published by
7974+ * the Free Software Foundation; either version 2 of the License, or
7975+ * (at your option) any later version.
dece6358
AM
7976+ *
7977+ * This program is distributed in the hope that it will be useful,
7978+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7979+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7980+ * GNU General Public License for more details.
7981+ *
7982+ * You should have received a copy of the GNU General Public License
7983+ * along with this program; if not, write to the Free Software
7984+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7985+ */
7986+
7987+/*
4a4d8108 7988+ * handling file/dir, and address_space operation
1facf9fc 7989+ */
7990+
dece6358 7991+#include <linux/file.h>
4a4d8108
AM
7992+#include <linux/fsnotify.h>
7993+#include <linux/namei.h>
7994+#include <linux/pagemap.h>
1facf9fc 7995+#include "aufs.h"
7996+
4a4d8108
AM
7997+/* drop flags for writing */
7998+unsigned int au_file_roflags(unsigned int flags)
7999+{
8000+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
8001+ flags |= O_RDONLY | O_NOATIME;
8002+ return flags;
8003+}
8004+
8005+/* common functions to regular file and dir */
8006+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8007+ struct file *file)
1facf9fc 8008+{
1308ab2a 8009+ struct file *h_file;
4a4d8108
AM
8010+ struct dentry *h_dentry;
8011+ struct inode *h_inode;
8012+ struct super_block *sb;
8013+ struct au_branch *br;
8014+ struct path h_path;
8015+ int err, exec_flag;
1facf9fc 8016+
4a4d8108
AM
8017+ /* a race condition can happen between open and unlink/rmdir */
8018+ h_file = ERR_PTR(-ENOENT);
8019+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 8020+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
8021+ goto out;
8022+ h_inode = h_dentry->d_inode;
b752ccd1 8023+ if (au_test_nfsd() && !h_inode)
4a4d8108 8024+ goto out;
7f207e10
AM
8025+ if (unlikely((!d_unhashed(dentry) && au_d_removed(h_dentry))
8026+ || !h_inode
8027+ /* || !dentry->d_inode->i_nlink */
8028+ ))
4a4d8108 8029+ goto out;
1facf9fc 8030+
4a4d8108
AM
8031+ sb = dentry->d_sb;
8032+ br = au_sbr(sb, bindex);
8033+ h_file = ERR_PTR(-EACCES);
8034+ exec_flag = flags & vfsub_fmode_to_uint(FMODE_EXEC);
8035+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
8036+ goto out;
1facf9fc 8037+
4a4d8108
AM
8038+ /* drop flags for writing */
8039+ if (au_test_ro(sb, bindex, dentry->d_inode))
8040+ flags = au_file_roflags(flags);
8041+ flags &= ~O_CREAT;
8042+ atomic_inc(&br->br_count);
8043+ h_path.dentry = h_dentry;
8044+ h_path.mnt = br->br_mnt;
8045+ if (!au_special_file(h_inode->i_mode))
8046+ h_file = vfsub_dentry_open(&h_path, flags);
8047+ else {
8048+ /* this block depends upon the configuration */
8049+ di_read_unlock(dentry, AuLock_IR);
8050+ fi_write_unlock(file);
8051+ si_read_unlock(sb);
8052+ h_file = vfsub_dentry_open(&h_path, flags);
8053+ si_noflush_read_lock(sb);
8054+ fi_write_lock(file);
8055+ di_read_lock_child(dentry, AuLock_IR);
dece6358 8056+ }
4a4d8108
AM
8057+ if (IS_ERR(h_file))
8058+ goto out_br;
dece6358 8059+
4a4d8108
AM
8060+ if (exec_flag) {
8061+ err = deny_write_access(h_file);
8062+ if (unlikely(err)) {
8063+ fput(h_file);
8064+ h_file = ERR_PTR(err);
8065+ goto out_br;
8066+ }
8067+ }
953406b4 8068+ fsnotify_open(h_file);
4a4d8108 8069+ goto out; /* success */
1facf9fc 8070+
4f0767ce 8071+out_br:
4a4d8108 8072+ atomic_dec(&br->br_count);
4f0767ce 8073+out:
4a4d8108
AM
8074+ return h_file;
8075+}
1308ab2a 8076+
4a4d8108
AM
8077+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8078+ struct au_fidir *fidir)
1facf9fc 8079+{
dece6358 8080+ int err;
1facf9fc 8081+ struct dentry *dentry;
1308ab2a 8082+
4a4d8108
AM
8083+ err = au_finfo_init(file, fidir);
8084+ if (unlikely(err))
8085+ goto out;
1facf9fc 8086+
8087+ dentry = file->f_dentry;
4a4d8108
AM
8088+ di_read_lock_child(dentry, AuLock_IR);
8089+ err = open(file, vfsub_file_flags(file));
8090+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 8091+
4a4d8108
AM
8092+ fi_write_unlock(file);
8093+ if (unlikely(err)) {
8094+ au_fi(file)->fi_hdir = NULL;
8095+ au_finfo_fin(file);
1308ab2a 8096+ }
4a4d8108 8097+
4f0767ce 8098+out:
1308ab2a 8099+ return err;
8100+}
dece6358 8101+
4a4d8108 8102+int au_reopen_nondir(struct file *file)
1308ab2a 8103+{
4a4d8108
AM
8104+ int err;
8105+ aufs_bindex_t bstart;
8106+ struct dentry *dentry;
8107+ struct file *h_file, *h_file_tmp;
1308ab2a 8108+
4a4d8108
AM
8109+ dentry = file->f_dentry;
8110+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
8111+ bstart = au_dbstart(dentry);
8112+ h_file_tmp = NULL;
8113+ if (au_fbstart(file) == bstart) {
8114+ h_file = au_hf_top(file);
8115+ if (file->f_mode == h_file->f_mode)
8116+ return 0; /* success */
8117+ h_file_tmp = h_file;
8118+ get_file(h_file_tmp);
8119+ au_set_h_fptr(file, bstart, NULL);
8120+ }
8121+ AuDebugOn(au_fi(file)->fi_hdir);
8122+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 8123+
4a4d8108
AM
8124+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
8125+ file);
8126+ err = PTR_ERR(h_file);
8127+ if (IS_ERR(h_file))
8128+ goto out; /* todo: close all? */
8129+
8130+ err = 0;
8131+ au_set_fbstart(file, bstart);
8132+ au_set_h_fptr(file, bstart, h_file);
8133+ au_update_figen(file);
8134+ /* todo: necessary? */
8135+ /* file->f_ra = h_file->f_ra; */
8136+
4f0767ce 8137+out:
4a4d8108
AM
8138+ if (h_file_tmp)
8139+ fput(h_file_tmp);
8140+ return err;
1facf9fc 8141+}
8142+
1308ab2a 8143+/* ---------------------------------------------------------------------- */
8144+
4a4d8108
AM
8145+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
8146+ struct dentry *hi_wh)
1facf9fc 8147+{
4a4d8108
AM
8148+ int err;
8149+ aufs_bindex_t bstart;
8150+ struct au_dinfo *dinfo;
8151+ struct dentry *h_dentry;
8152+ struct au_hdentry *hdp;
1facf9fc 8153+
4a4d8108
AM
8154+ dinfo = au_di(file->f_dentry);
8155+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 8156+
4a4d8108
AM
8157+ bstart = dinfo->di_bstart;
8158+ dinfo->di_bstart = btgt;
8159+ hdp = dinfo->di_hdentry;
8160+ h_dentry = hdp[0 + btgt].hd_dentry;
8161+ hdp[0 + btgt].hd_dentry = hi_wh;
8162+ err = au_reopen_nondir(file);
8163+ hdp[0 + btgt].hd_dentry = h_dentry;
8164+ dinfo->di_bstart = bstart;
1facf9fc 8165+
1facf9fc 8166+ return err;
8167+}
8168+
4a4d8108
AM
8169+static int au_ready_to_write_wh(struct file *file, loff_t len,
8170+ aufs_bindex_t bcpup)
1facf9fc 8171+{
4a4d8108 8172+ int err;
dece6358 8173+ struct inode *inode;
4a4d8108 8174+ struct dentry *dentry, *hi_wh;
1facf9fc 8175+
dece6358 8176+ dentry = file->f_dentry;
4a4d8108 8177+ au_update_dbstart(dentry);
dece6358 8178+ inode = dentry->d_inode;
4a4d8108
AM
8179+ hi_wh = au_hi_wh(inode, bcpup);
8180+ if (!hi_wh)
8181+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
8182+ else
8183+ /* already copied-up after unlink */
8184+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 8185+
4a4d8108
AM
8186+ if (!err
8187+ && inode->i_nlink > 1
8188+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
8189+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 8190+
dece6358 8191+ return err;
1facf9fc 8192+}
8193+
4a4d8108
AM
8194+/*
8195+ * prepare the @file for writing.
8196+ */
8197+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 8198+{
4a4d8108
AM
8199+ int err;
8200+ aufs_bindex_t bstart, bcpup;
8201+ struct dentry *dentry, *parent, *h_dentry;
8202+ struct inode *h_inode, *inode;
1facf9fc 8203+ struct super_block *sb;
4a4d8108 8204+ struct file *h_file;
1facf9fc 8205+
8206+ dentry = file->f_dentry;
1facf9fc 8207+ sb = dentry->d_sb;
4a4d8108
AM
8208+ inode = dentry->d_inode;
8209+ AuDebugOn(au_special_file(inode->i_mode));
8210+ bstart = au_fbstart(file);
8211+ err = au_test_ro(sb, bstart, inode);
8212+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
8213+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 8214+ goto out;
4a4d8108 8215+ }
1facf9fc 8216+
4a4d8108
AM
8217+ /* need to cpup */
8218+ parent = dget_parent(dentry);
8219+ di_write_lock_parent(parent);
8220+ err = AuWbrCopyup(au_sbi(sb), dentry);
8221+ bcpup = err;
8222+ if (unlikely(err < 0))
8223+ goto out_dgrade;
8224+ err = 0;
8225+
8226+ if (!au_h_dptr(parent, bcpup)) {
8227+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 8228+ if (unlikely(err))
4a4d8108
AM
8229+ goto out_dgrade;
8230+ }
8231+
8232+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
8233+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8234+ if (unlikely(err))
8235+ goto out_dgrade;
8236+
8237+ h_dentry = au_hf_top(file)->f_dentry;
8238+ h_inode = h_dentry->d_inode;
8239+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8240+ h_file = au_h_open_pre(dentry, bstart);
8241+ if (IS_ERR(h_file)) {
8242+ err = PTR_ERR(h_file);
8243+ h_file = NULL;
8244+ } else if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
8245+ /* || !h_inode->i_nlink */) {
8246+ err = au_ready_to_write_wh(file, len, bcpup);
8247+ di_downgrade_lock(parent, AuLock_IR);
8248+ } else {
8249+ di_downgrade_lock(parent, AuLock_IR);
8250+ if (!au_h_dptr(dentry, bcpup))
8251+ err = au_sio_cpup_simple(dentry, bcpup, len,
8252+ AuCpup_DTIME);
8253+ if (!err)
8254+ err = au_reopen_nondir(file);
8255+ }
8256+ mutex_unlock(&h_inode->i_mutex);
8257+ au_h_open_post(dentry, bstart, h_file);
8258+
8259+ if (!err) {
8260+ au_pin_set_parent_lflag(pin, /*lflag*/0);
8261+ goto out_dput; /* success */
8262+ }
8263+ au_unpin(pin);
8264+ goto out_unlock;
1facf9fc 8265+
4f0767ce 8266+out_dgrade:
4a4d8108 8267+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 8268+out_unlock:
4a4d8108 8269+ di_read_unlock(parent, AuLock_IR);
4f0767ce 8270+out_dput:
4a4d8108 8271+ dput(parent);
4f0767ce 8272+out:
1facf9fc 8273+ return err;
8274+}
8275+
4a4d8108
AM
8276+/* ---------------------------------------------------------------------- */
8277+
8278+int au_do_flush(struct file *file, fl_owner_t id,
8279+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 8280+{
4a4d8108 8281+ int err;
1308ab2a 8282+ struct dentry *dentry;
1facf9fc 8283+ struct super_block *sb;
4a4d8108 8284+ struct inode *inode;
1facf9fc 8285+
1facf9fc 8286+ dentry = file->f_dentry;
8287+ sb = dentry->d_sb;
dece6358 8288+ inode = dentry->d_inode;
4a4d8108
AM
8289+ si_noflush_read_lock(sb);
8290+ fi_read_lock(file);
b752ccd1 8291+ ii_read_lock_child(inode);
1facf9fc 8292+
4a4d8108
AM
8293+ err = flush(file, id);
8294+ au_cpup_attr_timesizes(inode);
1facf9fc 8295+
b752ccd1 8296+ ii_read_unlock(inode);
4a4d8108 8297+ fi_read_unlock(file);
1308ab2a 8298+ si_read_unlock(sb);
dece6358 8299+ return err;
1facf9fc 8300+}
8301+
4a4d8108
AM
8302+/* ---------------------------------------------------------------------- */
8303+
8304+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 8305+{
4a4d8108
AM
8306+ int err;
8307+ aufs_bindex_t bstart;
8308+ struct au_pin pin;
8309+ struct au_finfo *finfo;
8310+ struct dentry *dentry, *parent, *hi_wh;
8311+ struct inode *inode;
1facf9fc 8312+ struct super_block *sb;
8313+
4a4d8108
AM
8314+ FiMustWriteLock(file);
8315+
8316+ err = 0;
8317+ finfo = au_fi(file);
1308ab2a 8318+ dentry = file->f_dentry;
8319+ sb = dentry->d_sb;
4a4d8108
AM
8320+ inode = dentry->d_inode;
8321+ bstart = au_ibstart(inode);
8322+ if (bstart == finfo->fi_btop)
1308ab2a 8323+ goto out;
dece6358 8324+
4a4d8108
AM
8325+ parent = dget_parent(dentry);
8326+ if (au_test_ro(sb, bstart, inode)) {
8327+ di_read_lock_parent(parent, !AuLock_IR);
8328+ err = AuWbrCopyup(au_sbi(sb), dentry);
8329+ bstart = err;
8330+ di_read_unlock(parent, !AuLock_IR);
8331+ if (unlikely(err < 0))
8332+ goto out_parent;
8333+ err = 0;
1facf9fc 8334+ }
1facf9fc 8335+
4a4d8108
AM
8336+ di_read_lock_parent(parent, AuLock_IR);
8337+ hi_wh = au_hi_wh(inode, bstart);
7f207e10
AM
8338+ if (!S_ISDIR(inode->i_mode)
8339+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108
AM
8340+ && au_plink_test(inode)
8341+ && !d_unhashed(dentry)) {
8342+ err = au_test_and_cpup_dirs(dentry, bstart);
8343+ if (unlikely(err))
8344+ goto out_unlock;
8345+
8346+ /* always superio. */
8347+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
8348+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8349+ if (!err)
8350+ err = au_sio_cpup_simple(dentry, bstart, -1,
8351+ AuCpup_DTIME);
8352+ au_unpin(&pin);
8353+ } else if (hi_wh) {
8354+ /* already copied-up after unlink */
8355+ err = au_reopen_wh(file, bstart, hi_wh);
8356+ *need_reopen = 0;
8357+ }
1facf9fc 8358+
4f0767ce 8359+out_unlock:
4a4d8108 8360+ di_read_unlock(parent, AuLock_IR);
4f0767ce 8361+out_parent:
4a4d8108 8362+ dput(parent);
4f0767ce 8363+out:
1308ab2a 8364+ return err;
dece6358 8365+}
1facf9fc 8366+
4a4d8108 8367+static void au_do_refresh_dir(struct file *file)
dece6358 8368+{
4a4d8108
AM
8369+ aufs_bindex_t bindex, bend, new_bindex, brid;
8370+ struct au_hfile *p, tmp, *q;
8371+ struct au_finfo *finfo;
1308ab2a 8372+ struct super_block *sb;
4a4d8108 8373+ struct au_fidir *fidir;
1facf9fc 8374+
4a4d8108 8375+ FiMustWriteLock(file);
1facf9fc 8376+
4a4d8108
AM
8377+ sb = file->f_dentry->d_sb;
8378+ finfo = au_fi(file);
8379+ fidir = finfo->fi_hdir;
8380+ AuDebugOn(!fidir);
8381+ p = fidir->fd_hfile + finfo->fi_btop;
8382+ brid = p->hf_br->br_id;
8383+ bend = fidir->fd_bbot;
8384+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
8385+ if (!p->hf_file)
8386+ continue;
1308ab2a 8387+
4a4d8108
AM
8388+ new_bindex = au_br_index(sb, p->hf_br->br_id);
8389+ if (new_bindex == bindex)
8390+ continue;
8391+ if (new_bindex < 0) {
8392+ au_set_h_fptr(file, bindex, NULL);
8393+ continue;
8394+ }
1308ab2a 8395+
4a4d8108
AM
8396+ /* swap two lower inode, and loop again */
8397+ q = fidir->fd_hfile + new_bindex;
8398+ tmp = *q;
8399+ *q = *p;
8400+ *p = tmp;
8401+ if (tmp.hf_file) {
8402+ bindex--;
8403+ p--;
8404+ }
8405+ }
1308ab2a 8406+
4a4d8108 8407+ p = fidir->fd_hfile;
7f207e10 8408+ if (!au_test_mmapped(file) && !au_d_removed(file->f_dentry)) {
4a4d8108
AM
8409+ bend = au_sbend(sb);
8410+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
8411+ finfo->fi_btop++, p++)
8412+ if (p->hf_file) {
8413+ if (p->hf_file->f_dentry
8414+ && p->hf_file->f_dentry->d_inode)
8415+ break;
8416+ else
8417+ au_hfput(p, file);
8418+ }
8419+ } else {
8420+ bend = au_br_index(sb, brid);
8421+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
8422+ finfo->fi_btop++, p++)
8423+ if (p->hf_file)
8424+ au_hfput(p, file);
8425+ bend = au_sbend(sb);
8426+ }
1308ab2a 8427+
4a4d8108
AM
8428+ p = fidir->fd_hfile + bend;
8429+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
8430+ fidir->fd_bbot--, p--)
8431+ if (p->hf_file) {
8432+ if (p->hf_file->f_dentry
8433+ && p->hf_file->f_dentry->d_inode)
8434+ break;
8435+ else
8436+ au_hfput(p, file);
8437+ }
8438+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 8439+}
8440+
4a4d8108
AM
8441+/*
8442+ * after branch manipulating, refresh the file.
8443+ */
8444+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 8445+{
4a4d8108
AM
8446+ int err, need_reopen;
8447+ aufs_bindex_t bend, bindex;
8448+ struct dentry *dentry;
1308ab2a 8449+ struct au_finfo *finfo;
4a4d8108 8450+ struct au_hfile *hfile;
1facf9fc 8451+
4a4d8108 8452+ dentry = file->f_dentry;
1308ab2a 8453+ finfo = au_fi(file);
4a4d8108
AM
8454+ if (!finfo->fi_hdir) {
8455+ hfile = &finfo->fi_htop;
8456+ AuDebugOn(!hfile->hf_file);
8457+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
8458+ AuDebugOn(bindex < 0);
8459+ if (bindex != finfo->fi_btop)
8460+ au_set_fbstart(file, bindex);
8461+ } else {
8462+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
8463+ if (unlikely(err))
8464+ goto out;
8465+ au_do_refresh_dir(file);
8466+ }
1facf9fc 8467+
4a4d8108
AM
8468+ err = 0;
8469+ need_reopen = 1;
8470+ if (!au_test_mmapped(file))
8471+ err = au_file_refresh_by_inode(file, &need_reopen);
7f207e10 8472+ if (!err && need_reopen && !au_d_removed(dentry))
4a4d8108
AM
8473+ err = reopen(file);
8474+ if (!err) {
8475+ au_update_figen(file);
8476+ goto out; /* success */
8477+ }
8478+
8479+ /* error, close all lower files */
8480+ if (finfo->fi_hdir) {
8481+ bend = au_fbend_dir(file);
8482+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
8483+ au_set_h_fptr(file, bindex, NULL);
8484+ }
1facf9fc 8485+
4f0767ce 8486+out:
1facf9fc 8487+ return err;
8488+}
8489+
4a4d8108
AM
8490+/* common function to regular file and dir */
8491+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8492+ int wlock)
dece6358 8493+{
1308ab2a 8494+ int err;
4a4d8108
AM
8495+ unsigned int sigen, figen;
8496+ aufs_bindex_t bstart;
8497+ unsigned char pseudo_link;
8498+ struct dentry *dentry;
8499+ struct inode *inode;
1facf9fc 8500+
4a4d8108
AM
8501+ err = 0;
8502+ dentry = file->f_dentry;
8503+ inode = dentry->d_inode;
8504+ AuDebugOn(au_special_file(inode->i_mode));
8505+ sigen = au_sigen(dentry->d_sb);
8506+ fi_write_lock(file);
8507+ figen = au_figen(file);
8508+ di_write_lock_child(dentry);
8509+ bstart = au_dbstart(dentry);
8510+ pseudo_link = (bstart != au_ibstart(inode));
8511+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
8512+ if (!wlock) {
8513+ di_downgrade_lock(dentry, AuLock_IR);
8514+ fi_downgrade_lock(file);
8515+ }
8516+ goto out; /* success */
8517+ }
dece6358 8518+
4a4d8108
AM
8519+ AuDbg("sigen %d, figen %d\n", sigen, figen);
8520+ if (sigen != au_digen(dentry)
8521+ || sigen != au_iigen(inode)) {
8522+ err = au_reval_dpath(dentry, sigen);
8523+ if (unlikely(err < 0))
8524+ goto out;
8525+ AuDebugOn(au_digen(dentry) != sigen
8526+ || au_iigen(inode) != sigen);
8527+ }
dece6358 8528+
4a4d8108
AM
8529+ err = refresh_file(file, reopen);
8530+ if (!err) {
8531+ if (!wlock) {
8532+ di_downgrade_lock(dentry, AuLock_IR);
8533+ fi_downgrade_lock(file);
8534+ }
8535+ } else {
8536+ di_write_unlock(dentry);
8537+ fi_write_unlock(file);
8538+ }
1facf9fc 8539+
4f0767ce 8540+out:
1308ab2a 8541+ return err;
8542+}
1facf9fc 8543+
4a4d8108
AM
8544+/* ---------------------------------------------------------------------- */
8545+
8546+/* cf. aufs_nopage() */
8547+/* for madvise(2) */
8548+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 8549+{
4a4d8108
AM
8550+ unlock_page(page);
8551+ return 0;
8552+}
1facf9fc 8553+
4a4d8108
AM
8554+/* it will never be called, but necessary to support O_DIRECT */
8555+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
8556+ const struct iovec *iov, loff_t offset,
8557+ unsigned long nr_segs)
8558+{ BUG(); return 0; }
1facf9fc 8559+
4a4d8108
AM
8560+/*
8561+ * it will never be called, but madvise and fadvise behaves differently
8562+ * when get_xip_mem is defined
8563+ */
8564+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
8565+ int create, void **kmem, unsigned long *pfn)
8566+{ BUG(); return 0; }
1facf9fc 8567+
4a4d8108
AM
8568+/* they will never be called. */
8569+#ifdef CONFIG_AUFS_DEBUG
8570+static int aufs_write_begin(struct file *file, struct address_space *mapping,
8571+ loff_t pos, unsigned len, unsigned flags,
8572+ struct page **pagep, void **fsdata)
8573+{ AuUnsupport(); return 0; }
8574+static int aufs_write_end(struct file *file, struct address_space *mapping,
8575+ loff_t pos, unsigned len, unsigned copied,
8576+ struct page *page, void *fsdata)
8577+{ AuUnsupport(); return 0; }
8578+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
8579+{ AuUnsupport(); return 0; }
8580+static void aufs_sync_page(struct page *page)
8581+{ AuUnsupport(); }
1308ab2a 8582+
4a4d8108
AM
8583+static int aufs_set_page_dirty(struct page *page)
8584+{ AuUnsupport(); return 0; }
8585+static void aufs_invalidatepage(struct page *page, unsigned long offset)
8586+{ AuUnsupport(); }
8587+static int aufs_releasepage(struct page *page, gfp_t gfp)
8588+{ AuUnsupport(); return 0; }
8589+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
8590+ struct page *page)
8591+{ AuUnsupport(); return 0; }
8592+static int aufs_launder_page(struct page *page)
8593+{ AuUnsupport(); return 0; }
8594+static int aufs_is_partially_uptodate(struct page *page,
8595+ read_descriptor_t *desc,
8596+ unsigned long from)
8597+{ AuUnsupport(); return 0; }
8598+static int aufs_error_remove_page(struct address_space *mapping,
8599+ struct page *page)
8600+{ AuUnsupport(); return 0; }
8601+#endif /* CONFIG_AUFS_DEBUG */
8602+
8603+const struct address_space_operations aufs_aop = {
8604+ .readpage = aufs_readpage,
8605+ .direct_IO = aufs_direct_IO,
8606+ .get_xip_mem = aufs_get_xip_mem,
8607+#ifdef CONFIG_AUFS_DEBUG
8608+ .writepage = aufs_writepage,
8609+ .sync_page = aufs_sync_page,
8610+ /* no writepages, because of writepage */
8611+ .set_page_dirty = aufs_set_page_dirty,
8612+ /* no readpages, because of readpage */
8613+ .write_begin = aufs_write_begin,
8614+ .write_end = aufs_write_end,
8615+ /* no bmap, no block device */
8616+ .invalidatepage = aufs_invalidatepage,
8617+ .releasepage = aufs_releasepage,
8618+ .migratepage = aufs_migratepage,
8619+ .launder_page = aufs_launder_page,
8620+ .is_partially_uptodate = aufs_is_partially_uptodate,
8621+ .error_remove_page = aufs_error_remove_page
8622+#endif /* CONFIG_AUFS_DEBUG */
dece6358 8623+};
7f207e10
AM
8624diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
8625--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
8626+++ linux/fs/aufs/file.h 2010-11-22 11:52:56.987228248 +0100
b752ccd1 8627@@ -0,0 +1,238 @@
4a4d8108
AM
8628+/*
8629+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8630+ *
8631+ * This program, aufs is free software; you can redistribute it and/or modify
8632+ * it under the terms of the GNU General Public License as published by
8633+ * the Free Software Foundation; either version 2 of the License, or
8634+ * (at your option) any later version.
8635+ *
8636+ * This program is distributed in the hope that it will be useful,
8637+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8638+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8639+ * GNU General Public License for more details.
8640+ *
8641+ * You should have received a copy of the GNU General Public License
8642+ * along with this program; if not, write to the Free Software
8643+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8644+ */
1facf9fc 8645+
4a4d8108
AM
8646+/*
8647+ * file operations
8648+ */
1facf9fc 8649+
4a4d8108
AM
8650+#ifndef __AUFS_FILE_H__
8651+#define __AUFS_FILE_H__
1facf9fc 8652+
4a4d8108 8653+#ifdef __KERNEL__
1facf9fc 8654+
4a4d8108
AM
8655+#include <linux/fs.h>
8656+#include <linux/poll.h>
8657+#include <linux/aufs_type.h>
8658+#include "rwsem.h"
1facf9fc 8659+
4a4d8108
AM
8660+struct au_branch;
8661+struct au_hfile {
8662+ struct file *hf_file;
8663+ struct au_branch *hf_br;
8664+};
1facf9fc 8665+
4a4d8108
AM
8666+struct au_vdir;
8667+struct au_fidir {
8668+ aufs_bindex_t fd_bbot;
8669+ aufs_bindex_t fd_nent;
8670+ struct au_vdir *fd_vdir_cache;
8671+ struct au_hfile fd_hfile[];
8672+};
1facf9fc 8673+
4a4d8108 8674+static inline int au_fidir_sz(int nent)
dece6358 8675+{
4f0767ce
JR
8676+ AuDebugOn(nent < 0);
8677+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 8678+}
1facf9fc 8679+
4a4d8108
AM
8680+struct au_finfo {
8681+ atomic_t fi_generation;
dece6358 8682+
4a4d8108
AM
8683+ struct au_rwsem fi_rwsem;
8684+ aufs_bindex_t fi_btop;
8685+
8686+ /* do not union them */
8687+ struct { /* for non-dir */
8688+ struct au_hfile fi_htop;
8689+ struct vm_operations_struct *fi_hvmop;
8690+ struct mutex fi_vm_mtx;
8691+ struct mutex fi_mmap;
8692+ };
8693+ struct au_fidir *fi_hdir; /* for dir only */
8694+} ____cacheline_aligned_in_smp;
1facf9fc 8695+
4a4d8108 8696+/* ---------------------------------------------------------------------- */
1facf9fc 8697+
4a4d8108
AM
8698+/* file.c */
8699+extern const struct address_space_operations aufs_aop;
8700+unsigned int au_file_roflags(unsigned int flags);
8701+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8702+ struct file *file);
8703+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8704+ struct au_fidir *fidir);
8705+int au_reopen_nondir(struct file *file);
8706+struct au_pin;
8707+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
8708+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8709+ int wlock);
8710+int au_do_flush(struct file *file, fl_owner_t id,
8711+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 8712+
4a4d8108
AM
8713+/* poll.c */
8714+#ifdef CONFIG_AUFS_POLL
8715+unsigned int aufs_poll(struct file *file, poll_table *wait);
8716+#endif
1facf9fc 8717+
4a4d8108
AM
8718+#ifdef CONFIG_AUFS_BR_HFSPLUS
8719+/* hfsplus.c */
8720+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
8721+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
8722+ struct file *h_file);
8723+#else
8724+static inline
8725+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 8726+{
4a4d8108
AM
8727+ return NULL;
8728+}
1facf9fc 8729+
4a4d8108
AM
8730+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
8731+ struct file *h_file);
8732+#endif
1facf9fc 8733+
4a4d8108
AM
8734+/* f_op.c */
8735+extern const struct file_operations aufs_file_fop;
8736+extern const struct vm_operations_struct aufs_vm_ops;
8737+int au_do_open_nondir(struct file *file, int flags);
8738+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
8739+
8740+#ifdef CONFIG_AUFS_SP_IATTR
8741+/* f_op_sp.c */
8742+int au_special_file(umode_t mode);
8743+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
8744+#else
8745+AuStubInt0(au_special_file, umode_t mode)
8746+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
8747+ dev_t rdev)
8748+{
8749+ init_special_inode(inode, mode, rdev);
8750+}
8751+#endif
1facf9fc 8752+
4a4d8108
AM
8753+/* finfo.c */
8754+void au_hfput(struct au_hfile *hf, struct file *file);
8755+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
8756+ struct file *h_file);
1facf9fc 8757+
4a4d8108
AM
8758+void au_update_figen(struct file *file);
8759+void au_fi_mmap_lock(struct file *file);
8760+void au_fi_mmap_unlock(struct file *file);
8761+struct au_fidir *au_fidir_alloc(struct super_block *sb);
8762+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 8763+
4a4d8108
AM
8764+void au_fi_init_once(void *_fi);
8765+void au_finfo_fin(struct file *file);
8766+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 8767+
4a4d8108
AM
8768+/* ioctl.c */
8769+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
8770+#ifdef CONFIG_COMPAT
8771+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
8772+ unsigned long arg);
8773+#endif
1facf9fc 8774+
4a4d8108 8775+/* ---------------------------------------------------------------------- */
1facf9fc 8776+
4a4d8108
AM
8777+static inline struct au_finfo *au_fi(struct file *file)
8778+{
8779+ return file->private_data;
8780+}
1facf9fc 8781+
4a4d8108 8782+/* ---------------------------------------------------------------------- */
1facf9fc 8783+
4a4d8108
AM
8784+/*
8785+ * fi_read_lock, fi_write_lock,
8786+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
8787+ */
8788+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 8789+
4a4d8108
AM
8790+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
8791+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
8792+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 8793+
1308ab2a 8794+/* ---------------------------------------------------------------------- */
8795+
4a4d8108
AM
8796+/* todo: hard/soft set? */
8797+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 8798+{
4a4d8108
AM
8799+ FiMustAnyLock(file);
8800+ return au_fi(file)->fi_btop;
8801+}
dece6358 8802+
4a4d8108
AM
8803+static inline aufs_bindex_t au_fbend_dir(struct file *file)
8804+{
8805+ FiMustAnyLock(file);
8806+ AuDebugOn(!au_fi(file)->fi_hdir);
8807+ return au_fi(file)->fi_hdir->fd_bbot;
8808+}
1facf9fc 8809+
4a4d8108
AM
8810+static inline struct au_vdir *au_fvdir_cache(struct file *file)
8811+{
8812+ FiMustAnyLock(file);
8813+ AuDebugOn(!au_fi(file)->fi_hdir);
8814+ return au_fi(file)->fi_hdir->fd_vdir_cache;
8815+}
1facf9fc 8816+
4a4d8108
AM
8817+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
8818+{
8819+ FiMustWriteLock(file);
8820+ au_fi(file)->fi_btop = bindex;
8821+}
1facf9fc 8822+
4a4d8108
AM
8823+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
8824+{
8825+ FiMustWriteLock(file);
8826+ AuDebugOn(!au_fi(file)->fi_hdir);
8827+ au_fi(file)->fi_hdir->fd_bbot = bindex;
8828+}
1308ab2a 8829+
4a4d8108
AM
8830+static inline void au_set_fvdir_cache(struct file *file,
8831+ struct au_vdir *vdir_cache)
8832+{
8833+ FiMustWriteLock(file);
8834+ AuDebugOn(!au_fi(file)->fi_hdir);
8835+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
8836+}
dece6358 8837+
4a4d8108
AM
8838+static inline struct file *au_hf_top(struct file *file)
8839+{
8840+ FiMustAnyLock(file);
8841+ AuDebugOn(au_fi(file)->fi_hdir);
8842+ return au_fi(file)->fi_htop.hf_file;
8843+}
1facf9fc 8844+
4a4d8108
AM
8845+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
8846+{
8847+ FiMustAnyLock(file);
8848+ AuDebugOn(!au_fi(file)->fi_hdir);
8849+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
8850+}
8851+
4a4d8108
AM
8852+/* todo: memory barrier? */
8853+static inline unsigned int au_figen(struct file *f)
dece6358 8854+{
4a4d8108
AM
8855+ return atomic_read(&au_fi(f)->fi_generation);
8856+}
dece6358 8857+
4a4d8108
AM
8858+static inline int au_test_mmapped(struct file *f)
8859+{
8860+ FiMustAnyLock(f);
8861+ return !!(au_fi(f)->fi_hvmop);
8862+}
1308ab2a 8863+
4a4d8108
AM
8864+#endif /* __KERNEL__ */
8865+#endif /* __AUFS_FILE_H__ */
7f207e10
AM
8866diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
8867--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
8868+++ linux/fs/aufs/finfo.c 2010-11-22 11:52:56.987228248 +0100
8869@@ -0,0 +1,174 @@
4a4d8108
AM
8870+/*
8871+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8872+ *
8873+ * This program, aufs is free software; you can redistribute it and/or modify
8874+ * it under the terms of the GNU General Public License as published by
8875+ * the Free Software Foundation; either version 2 of the License, or
8876+ * (at your option) any later version.
8877+ *
8878+ * This program is distributed in the hope that it will be useful,
8879+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8880+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8881+ * GNU General Public License for more details.
8882+ *
8883+ * You should have received a copy of the GNU General Public License
8884+ * along with this program; if not, write to the Free Software
8885+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8886+ */
1308ab2a 8887+
4a4d8108
AM
8888+/*
8889+ * file private data
8890+ */
1facf9fc 8891+
4a4d8108
AM
8892+#include <linux/file.h>
8893+#include "aufs.h"
1facf9fc 8894+
4a4d8108
AM
8895+void au_hfput(struct au_hfile *hf, struct file *file)
8896+{
8897+ /* todo: direct access f_flags */
8898+ if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC))
8899+ allow_write_access(hf->hf_file);
8900+ fput(hf->hf_file);
8901+ hf->hf_file = NULL;
e49829fe 8902+ atomic_dec(&hf->hf_br->br_count);
4a4d8108
AM
8903+ hf->hf_br = NULL;
8904+}
1facf9fc 8905+
4a4d8108
AM
8906+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
8907+{
8908+ struct au_finfo *finfo = au_fi(file);
8909+ struct au_hfile *hf;
8910+ struct au_fidir *fidir;
8911+
8912+ fidir = finfo->fi_hdir;
8913+ if (!fidir) {
8914+ AuDebugOn(finfo->fi_btop != bindex);
8915+ hf = &finfo->fi_htop;
8916+ } else
8917+ hf = fidir->fd_hfile + bindex;
8918+
8919+ if (hf && hf->hf_file)
8920+ au_hfput(hf, file);
8921+ if (val) {
8922+ FiMustWriteLock(file);
8923+ hf->hf_file = val;
8924+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 8925+ }
4a4d8108 8926+}
1facf9fc 8927+
4a4d8108
AM
8928+void au_update_figen(struct file *file)
8929+{
8930+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
8931+ /* smp_mb(); */ /* atomic_set */
1facf9fc 8932+}
8933+
4a4d8108
AM
8934+/* ---------------------------------------------------------------------- */
8935+
8936+void au_fi_mmap_lock(struct file *file)
1facf9fc 8937+{
4a4d8108
AM
8938+ FiMustWriteLock(file);
8939+ lockdep_off();
8940+ mutex_lock(&au_fi(file)->fi_mmap);
8941+ lockdep_on();
8942+}
1facf9fc 8943+
4a4d8108
AM
8944+void au_fi_mmap_unlock(struct file *file)
8945+{
8946+ lockdep_off();
8947+ mutex_unlock(&au_fi(file)->fi_mmap);
8948+ lockdep_on();
8949+}
1308ab2a 8950+
4a4d8108 8951+/* ---------------------------------------------------------------------- */
1308ab2a 8952+
4a4d8108
AM
8953+struct au_fidir *au_fidir_alloc(struct super_block *sb)
8954+{
8955+ struct au_fidir *fidir;
8956+ int nbr;
8957+
8958+ nbr = au_sbend(sb) + 1;
8959+ if (nbr < 2)
8960+ nbr = 2; /* initial allocate for 2 branches */
8961+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
8962+ if (fidir) {
8963+ fidir->fd_bbot = -1;
8964+ fidir->fd_nent = nbr;
8965+ fidir->fd_vdir_cache = NULL;
8966+ }
8967+
8968+ return fidir;
8969+}
8970+
8971+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
8972+{
8973+ int err;
8974+ struct au_fidir *fidir, *p;
8975+
8976+ AuRwMustWriteLock(&finfo->fi_rwsem);
8977+ fidir = finfo->fi_hdir;
8978+ AuDebugOn(!fidir);
8979+
8980+ err = -ENOMEM;
8981+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
8982+ GFP_NOFS);
8983+ if (p) {
8984+ p->fd_nent = nbr;
8985+ finfo->fi_hdir = p;
8986+ err = 0;
8987+ }
1facf9fc 8988+
dece6358 8989+ return err;
1facf9fc 8990+}
1308ab2a 8991+
8992+/* ---------------------------------------------------------------------- */
8993+
4a4d8108 8994+void au_finfo_fin(struct file *file)
1308ab2a 8995+{
4a4d8108
AM
8996+ struct au_finfo *finfo;
8997+
7f207e10
AM
8998+ au_nfiles_dec(file->f_dentry->d_sb);
8999+
4a4d8108
AM
9000+ finfo = au_fi(file);
9001+ AuDebugOn(finfo->fi_hdir);
9002+ AuRwDestroy(&finfo->fi_rwsem);
9003+ au_cache_free_finfo(finfo);
1308ab2a 9004+}
1308ab2a 9005+
e49829fe 9006+void au_fi_init_once(void *_finfo)
4a4d8108 9007+{
e49829fe
JR
9008+ struct au_finfo *finfo = _finfo;
9009+ static struct lock_class_key aufs_fi, aufs_fi_vm, aufs_fi_mmap;
1308ab2a 9010+
e49829fe
JR
9011+ au_rw_init(&finfo->fi_rwsem);
9012+ au_rw_class(&finfo->fi_rwsem, &aufs_fi);
9013+ mutex_init(&finfo->fi_vm_mtx);
9014+ lockdep_set_class(&finfo->fi_vm_mtx, &aufs_fi_vm);
9015+ mutex_init(&finfo->fi_mmap);
9016+ lockdep_set_class(&finfo->fi_mmap, &aufs_fi_mmap);
4a4d8108 9017+}
1308ab2a 9018+
4a4d8108
AM
9019+int au_finfo_init(struct file *file, struct au_fidir *fidir)
9020+{
9021+ int err;
9022+ struct au_finfo *finfo;
9023+ struct dentry *dentry;
9024+
9025+ err = -ENOMEM;
9026+ dentry = file->f_dentry;
9027+ finfo = au_cache_alloc_finfo();
9028+ if (unlikely(!finfo))
9029+ goto out;
9030+
9031+ err = 0;
7f207e10 9032+ au_nfiles_inc(dentry->d_sb);
4a4d8108
AM
9033+ au_rw_write_lock(&finfo->fi_rwsem);
9034+ finfo->fi_btop = -1;
9035+ finfo->fi_hdir = fidir;
9036+ atomic_set(&finfo->fi_generation, au_digen(dentry));
9037+ /* smp_mb(); */ /* atomic_set */
9038+
9039+ file->private_data = finfo;
9040+
9041+out:
9042+ return err;
9043+}
7f207e10
AM
9044diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
9045--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
9046+++ linux/fs/aufs/f_op.c 2010-11-22 11:52:56.987228248 +0100
9047@@ -0,0 +1,901 @@
dece6358 9048+/*
4a4d8108 9049+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
9050+ *
9051+ * This program, aufs is free software; you can redistribute it and/or modify
9052+ * it under the terms of the GNU General Public License as published by
9053+ * the Free Software Foundation; either version 2 of the License, or
9054+ * (at your option) any later version.
9055+ *
9056+ * This program is distributed in the hope that it will be useful,
9057+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9058+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9059+ * GNU General Public License for more details.
9060+ *
9061+ * You should have received a copy of the GNU General Public License
9062+ * along with this program; if not, write to the Free Software
9063+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9064+ */
1facf9fc 9065+
9066+/*
4a4d8108 9067+ * file and vm operations
1facf9fc 9068+ */
dece6358
AM
9069+
9070+#include <linux/file.h>
4a4d8108
AM
9071+#include <linux/fs_stack.h>
9072+#include <linux/mman.h>
9073+#include <linux/mm.h>
9074+#include <linux/security.h>
dece6358
AM
9075+#include "aufs.h"
9076+
4a4d8108 9077+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 9078+{
4a4d8108
AM
9079+ int err;
9080+ aufs_bindex_t bindex;
9081+ struct file *h_file;
9082+ struct dentry *dentry;
9083+ struct au_finfo *finfo;
9084+
9085+ FiMustWriteLock(file);
9086+
9087+ err = 0;
9088+ dentry = file->f_dentry;
9089+ finfo = au_fi(file);
9090+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
9091+ finfo->fi_hvmop = NULL;
9092+ bindex = au_dbstart(dentry);
9093+ h_file = au_h_open(dentry, bindex, flags, file);
9094+ if (IS_ERR(h_file))
9095+ err = PTR_ERR(h_file);
9096+ else {
9097+ au_set_fbstart(file, bindex);
9098+ au_set_h_fptr(file, bindex, h_file);
9099+ au_update_figen(file);
9100+ /* todo: necessary? */
9101+ /* file->f_ra = h_file->f_ra; */
9102+ }
9103+ return err;
1facf9fc 9104+}
9105+
4a4d8108
AM
9106+static int aufs_open_nondir(struct inode *inode __maybe_unused,
9107+ struct file *file)
1facf9fc 9108+{
4a4d8108 9109+ int err;
1308ab2a 9110+ struct super_block *sb;
1facf9fc 9111+
4a4d8108
AM
9112+ AuDbg("%.*s, f_ flags 0x%x, f_mode 0x%x\n",
9113+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
9114+ file->f_mode);
1facf9fc 9115+
4a4d8108
AM
9116+ sb = file->f_dentry->d_sb;
9117+ si_read_lock(sb, AuLock_FLUSH);
9118+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
9119+ si_read_unlock(sb);
9120+ return err;
9121+}
1facf9fc 9122+
4a4d8108
AM
9123+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
9124+{
9125+ struct au_finfo *finfo;
9126+ aufs_bindex_t bindex;
1facf9fc 9127+
4a4d8108
AM
9128+ finfo = au_fi(file);
9129+ bindex = finfo->fi_btop;
0c5527e5
AM
9130+ if (bindex >= 0) {
9131+ /* remove me from sb->s_files */
9132+ file_sb_list_del(file);
4a4d8108 9133+ au_set_h_fptr(file, bindex, NULL);
0c5527e5 9134+ }
7f207e10 9135+
4a4d8108
AM
9136+ au_finfo_fin(file);
9137+ return 0;
1facf9fc 9138+}
9139+
4a4d8108
AM
9140+/* ---------------------------------------------------------------------- */
9141+
9142+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 9143+{
1308ab2a 9144+ int err;
4a4d8108
AM
9145+ struct file *h_file;
9146+
9147+ err = 0;
9148+ h_file = au_hf_top(file);
9149+ if (h_file)
9150+ err = vfsub_flush(h_file, id);
9151+ return err;
9152+}
9153+
9154+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
9155+{
9156+ return au_do_flush(file, id, au_do_flush_nondir);
9157+}
9158+
9159+/* ---------------------------------------------------------------------- */
9160+
9161+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
9162+ loff_t *ppos)
9163+{
9164+ ssize_t err;
dece6358 9165+ struct dentry *dentry;
4a4d8108 9166+ struct file *h_file;
dece6358 9167+ struct super_block *sb;
1facf9fc 9168+
dece6358
AM
9169+ dentry = file->f_dentry;
9170+ sb = dentry->d_sb;
e49829fe 9171+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 9172+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
9173+ if (unlikely(err))
9174+ goto out;
1facf9fc 9175+
4a4d8108
AM
9176+ h_file = au_hf_top(file);
9177+ err = vfsub_read_u(h_file, buf, count, ppos);
9178+ /* todo: necessary? */
9179+ /* file->f_ra = h_file->f_ra; */
9180+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1308ab2a 9181+
4a4d8108
AM
9182+ di_read_unlock(dentry, AuLock_IR);
9183+ fi_read_unlock(file);
4f0767ce 9184+out:
dece6358
AM
9185+ si_read_unlock(sb);
9186+ return err;
9187+}
1facf9fc 9188+
e49829fe
JR
9189+/*
9190+ * todo: very ugly
9191+ * it locks both of i_mutex and si_rwsem for read in safe.
9192+ * if the plink maintenance mode continues forever (that is the problem),
9193+ * may loop forever.
9194+ */
9195+static void au_mtx_and_read_lock(struct inode *inode)
9196+{
9197+ int err;
9198+ struct super_block *sb = inode->i_sb;
9199+
9200+ while (1) {
9201+ mutex_lock(&inode->i_mutex);
9202+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
9203+ if (!err)
9204+ break;
9205+ mutex_unlock(&inode->i_mutex);
9206+ si_read_lock(sb, AuLock_NOPLMW);
9207+ si_read_unlock(sb);
9208+ }
9209+}
9210+
4a4d8108
AM
9211+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
9212+ size_t count, loff_t *ppos)
dece6358 9213+{
4a4d8108
AM
9214+ ssize_t err;
9215+ struct au_pin pin;
dece6358 9216+ struct dentry *dentry;
4a4d8108 9217+ struct inode *inode;
4a4d8108
AM
9218+ struct file *h_file;
9219+ char __user *buf = (char __user *)ubuf;
1facf9fc 9220+
dece6358 9221+ dentry = file->f_dentry;
4a4d8108 9222+ inode = dentry->d_inode;
e49829fe 9223+ au_mtx_and_read_lock(inode);
1facf9fc 9224+
4a4d8108
AM
9225+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9226+ if (unlikely(err))
9227+ goto out;
1facf9fc 9228+
4a4d8108
AM
9229+ err = au_ready_to_write(file, -1, &pin);
9230+ di_downgrade_lock(dentry, AuLock_IR);
9231+ if (unlikely(err))
9232+ goto out_unlock;
1facf9fc 9233+
4a4d8108
AM
9234+ h_file = au_hf_top(file);
9235+ au_unpin(&pin);
9236+ err = vfsub_write_u(h_file, buf, count, ppos);
9237+ au_cpup_attr_timesizes(inode);
9238+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9239+
4f0767ce 9240+out_unlock:
4a4d8108
AM
9241+ di_read_unlock(dentry, AuLock_IR);
9242+ fi_write_unlock(file);
4f0767ce 9243+out:
e49829fe 9244+ si_read_unlock(inode->i_sb);
4a4d8108 9245+ mutex_unlock(&inode->i_mutex);
dece6358
AM
9246+ return err;
9247+}
1facf9fc 9248+
4a4d8108
AM
9249+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
9250+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 9251+{
4a4d8108
AM
9252+ ssize_t err;
9253+ struct file *file;
9254+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
9255+ loff_t);
1facf9fc 9256+
4a4d8108
AM
9257+ err = security_file_permission(h_file, rw);
9258+ if (unlikely(err))
9259+ goto out;
1facf9fc 9260+
4a4d8108
AM
9261+ err = -ENOSYS;
9262+ func = NULL;
9263+ if (rw == MAY_READ)
9264+ func = h_file->f_op->aio_read;
9265+ else if (rw == MAY_WRITE)
9266+ func = h_file->f_op->aio_write;
9267+ if (func) {
9268+ file = kio->ki_filp;
9269+ kio->ki_filp = h_file;
9270+ err = func(kio, iov, nv, pos);
9271+ kio->ki_filp = file;
9272+ } else
9273+ /* currently there is no such fs */
9274+ WARN_ON_ONCE(1);
1facf9fc 9275+
4f0767ce 9276+out:
dece6358
AM
9277+ return err;
9278+}
1facf9fc 9279+
4a4d8108
AM
9280+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
9281+ unsigned long nv, loff_t pos)
1facf9fc 9282+{
4a4d8108
AM
9283+ ssize_t err;
9284+ struct file *file, *h_file;
9285+ struct dentry *dentry;
dece6358 9286+ struct super_block *sb;
1facf9fc 9287+
4a4d8108 9288+ file = kio->ki_filp;
dece6358 9289+ dentry = file->f_dentry;
1308ab2a 9290+ sb = dentry->d_sb;
e49829fe 9291+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9292+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9293+ if (unlikely(err))
9294+ goto out;
9295+
9296+ h_file = au_hf_top(file);
9297+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
9298+ /* todo: necessary? */
9299+ /* file->f_ra = h_file->f_ra; */
9300+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9301+ di_read_unlock(dentry, AuLock_IR);
9302+ fi_read_unlock(file);
1facf9fc 9303+
4f0767ce 9304+out:
4a4d8108 9305+ si_read_unlock(sb);
1308ab2a 9306+ return err;
9307+}
1facf9fc 9308+
4a4d8108
AM
9309+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
9310+ unsigned long nv, loff_t pos)
1308ab2a 9311+{
4a4d8108
AM
9312+ ssize_t err;
9313+ struct au_pin pin;
9314+ struct dentry *dentry;
9315+ struct inode *inode;
4a4d8108 9316+ struct file *file, *h_file;
1308ab2a 9317+
4a4d8108 9318+ file = kio->ki_filp;
1308ab2a 9319+ dentry = file->f_dentry;
1308ab2a 9320+ inode = dentry->d_inode;
e49829fe
JR
9321+ au_mtx_and_read_lock(inode);
9322+
4a4d8108
AM
9323+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9324+ if (unlikely(err))
1308ab2a 9325+ goto out;
1facf9fc 9326+
4a4d8108
AM
9327+ err = au_ready_to_write(file, -1, &pin);
9328+ di_downgrade_lock(dentry, AuLock_IR);
dece6358 9329+ if (unlikely(err))
4a4d8108 9330+ goto out_unlock;
1facf9fc 9331+
4a4d8108
AM
9332+ au_unpin(&pin);
9333+ h_file = au_hf_top(file);
9334+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
9335+ au_cpup_attr_timesizes(inode);
9336+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9337+
4f0767ce 9338+out_unlock:
4a4d8108
AM
9339+ di_read_unlock(dentry, AuLock_IR);
9340+ fi_write_unlock(file);
4f0767ce 9341+out:
e49829fe 9342+ si_read_unlock(inode->i_sb);
4a4d8108 9343+ mutex_unlock(&inode->i_mutex);
dece6358 9344+ return err;
1facf9fc 9345+}
9346+
4a4d8108
AM
9347+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
9348+ struct pipe_inode_info *pipe, size_t len,
9349+ unsigned int flags)
1facf9fc 9350+{
4a4d8108
AM
9351+ ssize_t err;
9352+ struct file *h_file;
9353+ struct dentry *dentry;
dece6358 9354+ struct super_block *sb;
1facf9fc 9355+
dece6358 9356+ dentry = file->f_dentry;
dece6358 9357+ sb = dentry->d_sb;
e49829fe 9358+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9359+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9360+ if (unlikely(err))
dece6358 9361+ goto out;
1facf9fc 9362+
4a4d8108
AM
9363+ err = -EINVAL;
9364+ h_file = au_hf_top(file);
9365+ if (au_test_loopback_kthread()) {
9366+ file->f_mapping = h_file->f_mapping;
9367+ smp_mb(); /* unnecessary? */
1308ab2a 9368+ }
4a4d8108
AM
9369+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
9370+ /* todo: necessasry? */
9371+ /* file->f_ra = h_file->f_ra; */
9372+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 9373+
4a4d8108
AM
9374+ di_read_unlock(dentry, AuLock_IR);
9375+ fi_read_unlock(file);
1facf9fc 9376+
4f0767ce 9377+out:
4a4d8108 9378+ si_read_unlock(sb);
dece6358 9379+ return err;
1facf9fc 9380+}
9381+
4a4d8108
AM
9382+static ssize_t
9383+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
9384+ size_t len, unsigned int flags)
1facf9fc 9385+{
4a4d8108
AM
9386+ ssize_t err;
9387+ struct au_pin pin;
9388+ struct dentry *dentry;
9389+ struct inode *inode;
4a4d8108 9390+ struct file *h_file;
1facf9fc 9391+
4a4d8108
AM
9392+ dentry = file->f_dentry;
9393+ inode = dentry->d_inode;
e49829fe 9394+ au_mtx_and_read_lock(inode);
4a4d8108
AM
9395+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9396+ if (unlikely(err))
9397+ goto out;
1facf9fc 9398+
4a4d8108
AM
9399+ err = au_ready_to_write(file, -1, &pin);
9400+ di_downgrade_lock(dentry, AuLock_IR);
9401+ if (unlikely(err))
9402+ goto out_unlock;
1facf9fc 9403+
4a4d8108
AM
9404+ h_file = au_hf_top(file);
9405+ au_unpin(&pin);
9406+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
9407+ au_cpup_attr_timesizes(inode);
9408+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9409+
4f0767ce 9410+out_unlock:
4a4d8108
AM
9411+ di_read_unlock(dentry, AuLock_IR);
9412+ fi_write_unlock(file);
4f0767ce 9413+out:
e49829fe 9414+ si_read_unlock(inode->i_sb);
4a4d8108
AM
9415+ mutex_unlock(&inode->i_mutex);
9416+ return err;
9417+}
1facf9fc 9418+
4a4d8108
AM
9419+/* ---------------------------------------------------------------------- */
9420+
9421+static struct file *au_safe_file(struct vm_area_struct *vma)
9422+{
9423+ struct file *file;
9424+
9425+ file = vma->vm_file;
9426+ if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
9427+ return file;
9428+ return NULL;
1facf9fc 9429+}
9430+
4a4d8108 9431+static void au_reset_file(struct vm_area_struct *vma, struct file *file)
1facf9fc 9432+{
4a4d8108
AM
9433+ vma->vm_file = file;
9434+ /* smp_mb(); */ /* flush vm_file */
9435+}
1facf9fc 9436+
4a4d8108
AM
9437+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
9438+{
9439+ int err;
9440+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9441+ struct file *file, *h_file;
9442+ struct au_finfo *finfo;
1facf9fc 9443+
4a4d8108
AM
9444+ /* todo: non-robr mode, user vm_file as it is? */
9445+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 9446+
4a4d8108
AM
9447+ /* do not revalidate, no si lock */
9448+ finfo = au_fi(file);
9449+ AuDebugOn(finfo->fi_hdir);
9450+ h_file = finfo->fi_htop.hf_file;
9451+ AuDebugOn(!h_file || !finfo->fi_hvmop);
9452+
9453+ mutex_lock(&finfo->fi_vm_mtx);
9454+ vma->vm_file = h_file;
9455+ err = finfo->fi_hvmop->fault(vma, vmf);
9456+ /* todo: necessary? */
9457+ /* file->f_ra = h_file->f_ra; */
9458+ au_reset_file(vma, file);
9459+ mutex_unlock(&finfo->fi_vm_mtx);
9460+#if 0 /* def CONFIG_SMP */
9461+ /* wake_up_nr(&wq, online_cpu - 1); */
9462+ wake_up_all(&wq);
9463+#else
9464+ wake_up(&wq);
9465+#endif
1facf9fc 9466+
dece6358 9467+ return err;
1facf9fc 9468+}
9469+
4a4d8108 9470+static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1facf9fc 9471+{
dece6358 9472+ int err;
4a4d8108
AM
9473+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9474+ struct file *file, *h_file;
9475+ struct au_finfo *finfo;
1facf9fc 9476+
4a4d8108 9477+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 9478+
4a4d8108
AM
9479+ finfo = au_fi(file);
9480+ AuDebugOn(finfo->fi_hdir);
9481+ h_file = finfo->fi_htop.hf_file;
9482+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 9483+
4a4d8108
AM
9484+ mutex_lock(&finfo->fi_vm_mtx);
9485+ vma->vm_file = h_file;
9486+ err = finfo->fi_hvmop->page_mkwrite(vma, vmf);
9487+ au_reset_file(vma, file);
9488+ mutex_unlock(&finfo->fi_vm_mtx);
9489+ wake_up(&wq);
1308ab2a 9490+
dece6358 9491+ return err;
1facf9fc 9492+}
9493+
4a4d8108 9494+static void aufs_vm_close(struct vm_area_struct *vma)
1facf9fc 9495+{
4a4d8108
AM
9496+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9497+ struct file *file, *h_file;
9498+ struct au_finfo *finfo;
dece6358 9499+
4a4d8108 9500+ wait_event(wq, (file = au_safe_file(vma)));
dece6358 9501+
4a4d8108
AM
9502+ finfo = au_fi(file);
9503+ AuDebugOn(finfo->fi_hdir);
9504+ h_file = finfo->fi_htop.hf_file;
9505+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 9506+
4a4d8108
AM
9507+ mutex_lock(&finfo->fi_vm_mtx);
9508+ vma->vm_file = h_file;
9509+ finfo->fi_hvmop->close(vma);
9510+ au_reset_file(vma, file);
9511+ mutex_unlock(&finfo->fi_vm_mtx);
9512+ wake_up(&wq);
9513+}
1facf9fc 9514+
4a4d8108
AM
9515+const struct vm_operations_struct aufs_vm_ops = {
9516+ .close = aufs_vm_close,
9517+ .fault = aufs_fault,
9518+ .page_mkwrite = aufs_page_mkwrite
1308ab2a 9519+};
dece6358 9520+
1308ab2a 9521+/* ---------------------------------------------------------------------- */
1facf9fc 9522+
4a4d8108
AM
9523+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
9524+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
1308ab2a 9525+
4a4d8108 9526+static unsigned long au_arch_prot_conv(unsigned long flags)
dece6358 9527+{
4a4d8108
AM
9528+ /* currently ppc64 only */
9529+#ifdef CONFIG_PPC64
9530+ /* cf. linux/arch/powerpc/include/asm/mman.h */
9531+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
9532+ return AuConv_VM_PROT(flags, SAO);
9533+#else
9534+ AuDebugOn(arch_calc_vm_prot_bits(-1));
9535+ return 0;
9536+#endif
dece6358
AM
9537+}
9538+
4a4d8108 9539+static unsigned long au_prot_conv(unsigned long flags)
dece6358 9540+{
4a4d8108
AM
9541+ return AuConv_VM_PROT(flags, READ)
9542+ | AuConv_VM_PROT(flags, WRITE)
9543+ | AuConv_VM_PROT(flags, EXEC)
9544+ | au_arch_prot_conv(flags);
dece6358
AM
9545+}
9546+
4a4d8108
AM
9547+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
9548+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
dece6358 9549+
4a4d8108 9550+static unsigned long au_flag_conv(unsigned long flags)
dece6358 9551+{
4a4d8108
AM
9552+ return AuConv_VM_MAP(flags, GROWSDOWN)
9553+ | AuConv_VM_MAP(flags, DENYWRITE)
9554+ | AuConv_VM_MAP(flags, EXECUTABLE)
9555+ | AuConv_VM_MAP(flags, LOCKED);
dece6358
AM
9556+}
9557+
4a4d8108
AM
9558+static struct vm_operations_struct *
9559+au_hvmop(struct file *h_file, struct vm_area_struct *vma, unsigned long *flags)
dece6358 9560+{
4a4d8108
AM
9561+ struct vm_operations_struct *h_vmop;
9562+ unsigned long prot;
9563+ int err;
dece6358 9564+
4a4d8108
AM
9565+ h_vmop = ERR_PTR(-ENODEV);
9566+ if (!h_file->f_op || !h_file->f_op->mmap)
9567+ goto out;
dece6358 9568+
4a4d8108
AM
9569+ prot = au_prot_conv(vma->vm_flags);
9570+ err = security_file_mmap(h_file, /*reqprot*/prot, prot,
9571+ au_flag_conv(vma->vm_flags), vma->vm_start, 0);
9572+ h_vmop = ERR_PTR(err);
9573+ if (unlikely(err))
9574+ goto out;
dece6358 9575+
4a4d8108
AM
9576+ err = h_file->f_op->mmap(h_file, vma);
9577+ h_vmop = ERR_PTR(err);
9578+ if (unlikely(err))
9579+ goto out;
dece6358 9580+
4a4d8108
AM
9581+ /* oops, it became 'const' */
9582+ h_vmop = (struct vm_operations_struct *)vma->vm_ops;
9583+ *flags = vma->vm_flags;
9584+ err = do_munmap(current->mm, vma->vm_start,
9585+ vma->vm_end - vma->vm_start);
9586+ if (unlikely(err)) {
9587+ AuIOErr("failed internal unmapping %.*s, %d\n",
9588+ AuDLNPair(h_file->f_dentry), err);
9589+ h_vmop = ERR_PTR(-EIO);
9590+ }
dece6358 9591+
4f0767ce 9592+out:
4a4d8108 9593+ return h_vmop;
dece6358
AM
9594+}
9595+
1308ab2a 9596+/*
4a4d8108
AM
9597+ * This is another ugly approach to keep the lock order, particularly
9598+ * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
9599+ * find it in git-log, if you want.
1308ab2a 9600+ *
4a4d8108
AM
9601+ * native readdir: i_mutex, copy_to_user, mmap_sem
9602+ * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
1308ab2a 9603+ *
4a4d8108
AM
9604+ * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
9605+ * acquire aufs rwsem. It introduces a circular locking dependency.
9606+ * To address this problem, aufs_mmap() delegates the part which requires aufs
9607+ * rwsem to its internal workqueue.
1308ab2a 9608+ */
9609+
4a4d8108
AM
9610+/* very ugly approach */
9611+#include "mtx.h"
1308ab2a 9612+
4a4d8108
AM
9613+struct au_mmap_pre_args {
9614+ /* input */
9615+ struct file *file;
9616+ struct vm_area_struct *vma;
1308ab2a 9617+
4a4d8108
AM
9618+ /* output */
9619+ int *errp;
9620+ struct file *h_file;
9621+ struct au_branch *br;
9622+ int mmapped;
9623+};
dece6358 9624+
4a4d8108
AM
9625+static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
9626+ struct file **h_file, struct au_branch **br,
9627+ int *mmapped)
dece6358 9628+{
4a4d8108
AM
9629+ int err;
9630+ aufs_bindex_t bstart;
9631+ const unsigned char wlock
9632+ = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
9633+ struct dentry *dentry;
9634+ struct super_block *sb;
1308ab2a 9635+
4a4d8108
AM
9636+ dentry = file->f_dentry;
9637+ sb = dentry->d_sb;
e49829fe 9638+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108
AM
9639+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9640+ if (unlikely(err))
9641+ goto out;
9642+
9643+ *mmapped = !!au_test_mmapped(file);
9644+ if (wlock) {
9645+ struct au_pin pin;
9646+
9647+ err = au_ready_to_write(file, -1, &pin);
9648+ di_write_unlock(dentry);
9649+ if (unlikely(err))
9650+ goto out_unlock;
9651+ au_unpin(&pin);
9652+ } else
9653+ di_write_unlock(dentry);
9654+ bstart = au_fbstart(file);
9655+ *br = au_sbr(sb, bstart);
9656+ *h_file = au_hf_top(file);
9657+ get_file(*h_file);
9658+ au_fi_mmap_lock(file);
9659+
9660+out_unlock:
9661+ fi_write_unlock(file);
9662+out:
9663+ si_read_unlock(sb);
9664+ return err;
dece6358
AM
9665+}
9666+
4a4d8108 9667+static void au_call_mmap_pre(void *args)
dece6358 9668+{
4a4d8108
AM
9669+ struct au_mmap_pre_args *a = args;
9670+ *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->br,
9671+ &a->mmapped);
dece6358
AM
9672+}
9673+
4a4d8108 9674+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 9675+{
4a4d8108
AM
9676+ int err, wkq_err;
9677+ unsigned long h_vmflags;
1308ab2a 9678+ struct au_finfo *finfo;
4a4d8108
AM
9679+ struct dentry *h_dentry;
9680+ struct vm_operations_struct *h_vmop, *vmop;
9681+ struct au_mmap_pre_args args = {
9682+ .file = file,
9683+ .vma = vma,
9684+ .errp = &err
9685+ };
9686+
b752ccd1 9687+ wkq_err = au_wkq_wait_pre(au_call_mmap_pre, &args);
4a4d8108
AM
9688+ if (unlikely(wkq_err))
9689+ err = wkq_err;
9690+ if (unlikely(err))
9691+ goto out;
9692+ finfo = au_fi(file);
9693+ mutex_set_owner(&finfo->fi_mmap);
9694+
9695+ h_dentry = args.h_file->f_dentry;
9696+ if (!args.mmapped && au_test_fs_bad_mapping(h_dentry->d_sb)) {
1308ab2a 9697+ /*
4a4d8108
AM
9698+ * by this assignment, f_mapping will differs from aufs inode
9699+ * i_mapping.
9700+ * if someone else mixes the use of f_dentry->d_inode and
9701+ * f_mapping->host, then a problem may arise.
1308ab2a 9702+ */
4a4d8108
AM
9703+ file->f_mapping = args.h_file->f_mapping;
9704+ }
1308ab2a 9705+
4a4d8108
AM
9706+ /* always try this internal mmap to get vma flags */
9707+ h_vmflags = 0; /* gcc warning */
9708+ h_vmop = au_hvmop(args.h_file, vma, &h_vmflags);
9709+ err = PTR_ERR(h_vmop);
9710+ if (IS_ERR(h_vmop))
9711+ goto out_unlock;
9712+ AuDebugOn(args.mmapped && h_vmop != finfo->fi_hvmop);
9713+
9714+ vmop = (void *)au_dy_vmop(file, args.br, h_vmop);
9715+ err = PTR_ERR(vmop);
9716+ if (IS_ERR(vmop))
9717+ goto out_unlock;
9718+
9719+ /*
9720+ * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
9721+ * currently MAP_DENYWRITE from userspace is ignored, but elf loader
9722+ * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
9723+ * both of the aufs file and the lower file is deny_write_access()-ed.
9724+ * finally I hope we can skip handlling MAP_DENYWRITE here.
9725+ */
9726+ err = generic_file_mmap(file, vma);
9727+ if (unlikely(err))
9728+ goto out_unlock;
9729+
9730+ vma->vm_ops = vmop;
9731+ vma->vm_flags = h_vmflags;
9732+ if (!args.mmapped)
9733+ finfo->fi_hvmop = h_vmop;
9734+
9735+ vfsub_file_accessed(args.h_file);
9736+ /* update without lock, I don't think it a problem */
9737+ fsstack_copy_attr_atime(file->f_dentry->d_inode, h_dentry->d_inode);
9738+
4f0767ce 9739+out_unlock:
4a4d8108
AM
9740+ au_fi_mmap_unlock(file);
9741+ fput(args.h_file);
4f0767ce 9742+out:
4a4d8108
AM
9743+ return err;
9744+}
9745+
9746+/* ---------------------------------------------------------------------- */
9747+
b752ccd1 9748+static int aufs_fsync_nondir(struct file *file, int datasync)
4a4d8108
AM
9749+{
9750+ int err;
9751+ struct au_pin pin;
b752ccd1 9752+ struct dentry *dentry;
4a4d8108
AM
9753+ struct inode *inode;
9754+ struct file *h_file;
9755+ struct super_block *sb;
9756+
b752ccd1 9757+ dentry = file->f_dentry;
4a4d8108
AM
9758+ inode = dentry->d_inode;
9759+ IMustLock(file->f_mapping->host);
9760+ if (inode != file->f_mapping->host) {
9761+ mutex_unlock(&file->f_mapping->host->i_mutex);
9762+ mutex_lock(&inode->i_mutex);
9763+ }
9764+ IMustLock(inode);
9765+
9766+ sb = dentry->d_sb;
e49829fe
JR
9767+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
9768+ if (unlikely(err))
9769+ goto out;
4a4d8108
AM
9770+
9771+ err = 0; /* -EBADF; */ /* posix? */
9772+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
e49829fe 9773+ goto out_si;
4a4d8108
AM
9774+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9775+ if (unlikely(err))
e49829fe 9776+ goto out_si;
4a4d8108
AM
9777+
9778+ err = au_ready_to_write(file, -1, &pin);
9779+ di_downgrade_lock(dentry, AuLock_IR);
9780+ if (unlikely(err))
9781+ goto out_unlock;
9782+ au_unpin(&pin);
9783+
9784+ err = -EINVAL;
9785+ h_file = au_hf_top(file);
9786+ if (h_file->f_op && h_file->f_op->fsync) {
4a4d8108
AM
9787+ struct mutex *h_mtx;
9788+
9789+ /*
9790+ * no filemap_fdatawrite() since aufs file has no its own
9791+ * mapping, but dir.
9792+ */
b752ccd1 9793+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
4a4d8108 9794+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
b752ccd1 9795+ err = h_file->f_op->fsync(h_file, datasync);
4a4d8108
AM
9796+ if (!err)
9797+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9798+ /*ignore*/
9799+ au_cpup_attr_timesizes(inode);
9800+ mutex_unlock(h_mtx);
9801+ }
9802+
4f0767ce 9803+out_unlock:
4a4d8108 9804+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 9805+ fi_write_unlock(file);
e49829fe 9806+out_si:
953406b4 9807+ si_read_unlock(sb);
e49829fe 9808+out:
4a4d8108
AM
9809+ if (inode != file->f_mapping->host) {
9810+ mutex_unlock(&inode->i_mutex);
9811+ mutex_lock(&file->f_mapping->host->i_mutex);
9812+ }
9813+ return err;
dece6358
AM
9814+}
9815+
4a4d8108
AM
9816+/* no one supports this operation, currently */
9817+#if 0
9818+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 9819+{
4a4d8108
AM
9820+ int err;
9821+ struct au_pin pin;
1308ab2a 9822+ struct dentry *dentry;
4a4d8108
AM
9823+ struct inode *inode;
9824+ struct file *file, *h_file;
1308ab2a 9825+
4a4d8108 9826+ file = kio->ki_filp;
1308ab2a 9827+ dentry = file->f_dentry;
4a4d8108 9828+ inode = dentry->d_inode;
e49829fe 9829+ au_mtx_and_read_lock(inode);
4a4d8108
AM
9830+
9831+ err = 0; /* -EBADF; */ /* posix? */
9832+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
9833+ goto out;
9834+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9835+ if (unlikely(err))
1308ab2a 9836+ goto out;
9837+
4a4d8108
AM
9838+ err = au_ready_to_write(file, -1, &pin);
9839+ di_downgrade_lock(dentry, AuLock_IR);
9840+ if (unlikely(err))
9841+ goto out_unlock;
9842+ au_unpin(&pin);
1308ab2a 9843+
4a4d8108
AM
9844+ err = -ENOSYS;
9845+ h_file = au_hf_top(file);
9846+ if (h_file->f_op && h_file->f_op->aio_fsync) {
9847+ struct dentry *h_d;
9848+ struct mutex *h_mtx;
1308ab2a 9849+
4a4d8108
AM
9850+ h_d = h_file->f_dentry;
9851+ h_mtx = &h_d->d_inode->i_mutex;
9852+ if (!is_sync_kiocb(kio)) {
9853+ get_file(h_file);
9854+ fput(file);
9855+ }
9856+ kio->ki_filp = h_file;
9857+ err = h_file->f_op->aio_fsync(kio, datasync);
9858+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
9859+ if (!err)
9860+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9861+ /*ignore*/
9862+ au_cpup_attr_timesizes(inode);
9863+ mutex_unlock(h_mtx);
9864+ }
1308ab2a 9865+
4f0767ce 9866+out_unlock:
4a4d8108
AM
9867+ di_read_unlock(dentry, AuLock_IR);
9868+ fi_write_unlock(file);
4f0767ce 9869+out:
e49829fe 9870+ si_read_unlock(inode->sb);
4a4d8108
AM
9871+ mutex_unlock(&inode->i_mutex);
9872+ return err;
dece6358 9873+}
4a4d8108 9874+#endif
dece6358 9875+
4a4d8108 9876+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 9877+{
4a4d8108
AM
9878+ int err;
9879+ struct file *h_file;
9880+ struct dentry *dentry;
9881+ struct super_block *sb;
1308ab2a 9882+
4a4d8108
AM
9883+ dentry = file->f_dentry;
9884+ sb = dentry->d_sb;
e49829fe 9885+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9886+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9887+ if (unlikely(err))
9888+ goto out;
9889+
9890+ h_file = au_hf_top(file);
9891+ if (h_file->f_op && h_file->f_op->fasync)
9892+ err = h_file->f_op->fasync(fd, h_file, flag);
9893+
9894+ di_read_unlock(dentry, AuLock_IR);
9895+ fi_read_unlock(file);
1308ab2a 9896+
4f0767ce 9897+out:
4a4d8108 9898+ si_read_unlock(sb);
1308ab2a 9899+ return err;
dece6358 9900+}
4a4d8108
AM
9901+
9902+/* ---------------------------------------------------------------------- */
9903+
9904+/* no one supports this operation, currently */
9905+#if 0
9906+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
9907+ size_t len, loff_t *pos , int more)
9908+{
9909+}
9910+#endif
9911+
9912+/* ---------------------------------------------------------------------- */
9913+
9914+const struct file_operations aufs_file_fop = {
9915+ .owner = THIS_MODULE,
9916+ /*
9917+ * while generic_file_llseek/_unlocked() don't use BKL,
9918+ * don't use it since it operates file->f_mapping->host.
9919+ * in aufs, it may be a real file and may confuse users by UDBA.
9920+ */
9921+ /* .llseek = generic_file_llseek, */
9922+
9923+ .read = aufs_read,
9924+ .write = aufs_write,
9925+ .aio_read = aufs_aio_read,
9926+ .aio_write = aufs_aio_write,
9927+#ifdef CONFIG_AUFS_POLL
9928+ .poll = aufs_poll,
9929+#endif
9930+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
9931+#ifdef CONFIG_COMPAT
9932+ .compat_ioctl = aufs_ioctl_nondir, /* same */
9933+#endif
4a4d8108
AM
9934+ .mmap = aufs_mmap,
9935+ .open = aufs_open_nondir,
9936+ .flush = aufs_flush_nondir,
9937+ .release = aufs_release_nondir,
9938+ .fsync = aufs_fsync_nondir,
9939+ /* .aio_fsync = aufs_aio_fsync_nondir, */
9940+ .fasync = aufs_fasync,
9941+ /* .sendpage = aufs_sendpage, */
9942+ .splice_write = aufs_splice_write,
9943+ .splice_read = aufs_splice_read,
9944+#if 0
9945+ .aio_splice_write = aufs_aio_splice_write,
9946+ .aio_splice_read = aufs_aio_splice_read
9947+#endif
9948+};
7f207e10
AM
9949diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
9950--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
9951+++ linux/fs/aufs/f_op_sp.c 2010-11-22 11:52:56.987228248 +0100
e49829fe 9952@@ -0,0 +1,299 @@
1308ab2a 9953+/*
4a4d8108 9954+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 9955+ *
9956+ * This program, aufs is free software; you can redistribute it and/or modify
9957+ * it under the terms of the GNU General Public License as published by
9958+ * the Free Software Foundation; either version 2 of the License, or
9959+ * (at your option) any later version.
9960+ *
9961+ * This program is distributed in the hope that it will be useful,
9962+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9963+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9964+ * GNU General Public License for more details.
9965+ *
9966+ * You should have received a copy of the GNU General Public License
9967+ * along with this program; if not, write to the Free Software
9968+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9969+ */
dece6358 9970+
1308ab2a 9971+/*
4a4d8108
AM
9972+ * file operations for special files.
9973+ * while they exist in aufs virtually,
9974+ * their file I/O is handled out of aufs.
1308ab2a 9975+ */
9976+
4a4d8108
AM
9977+#include <linux/fs_stack.h>
9978+#include "aufs.h"
1308ab2a 9979+
4a4d8108
AM
9980+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
9981+ unsigned long nv, loff_t pos)
dece6358 9982+{
4a4d8108
AM
9983+ ssize_t err;
9984+ aufs_bindex_t bstart;
9985+ unsigned char wbr;
9986+ struct file *file, *h_file;
9987+ struct super_block *sb;
1308ab2a 9988+
4a4d8108
AM
9989+ file = kio->ki_filp;
9990+ sb = file->f_dentry->d_sb;
9991+ si_read_lock(sb, AuLock_FLUSH);
9992+ fi_read_lock(file);
9993+ bstart = au_fbstart(file);
9994+ h_file = au_hf_top(file);
9995+ fi_read_unlock(file);
9996+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9997+ si_read_unlock(sb);
9998+
9999+ /* do not change the file in kio */
10000+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
10001+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
10002+ if (err > 0 && wbr)
10003+ file_accessed(h_file);
10004+
10005+ return err;
10006+}
10007+
10008+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
10009+ unsigned long nv, loff_t pos)
10010+{
10011+ ssize_t err;
10012+ aufs_bindex_t bstart;
10013+ unsigned char wbr;
10014+ struct super_block *sb;
10015+ struct file *file, *h_file;
10016+
10017+ file = kio->ki_filp;
10018+ sb = file->f_dentry->d_sb;
10019+ si_read_lock(sb, AuLock_FLUSH);
10020+ fi_read_lock(file);
10021+ bstart = au_fbstart(file);
10022+ h_file = au_hf_top(file);
10023+ fi_read_unlock(file);
10024+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
10025+ si_read_unlock(sb);
10026+
10027+ /* do not change the file in kio */
10028+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
10029+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
10030+ if (err > 0 && wbr)
10031+ file_update_time(h_file);
10032+
10033+ return err;
10034+}
10035+
10036+/* ---------------------------------------------------------------------- */
10037+
10038+static int aufs_release_sp(struct inode *inode, struct file *file)
10039+{
10040+ int err;
10041+ struct file *h_file;
10042+
10043+ fi_read_lock(file);
10044+ h_file = au_hf_top(file);
10045+ fi_read_unlock(file);
10046+ /* close this fifo in aufs */
10047+ err = h_file->f_op->release(inode, file); /* ignore */
10048+ aufs_release_nondir(inode, file); /* ignore */
10049+ return err;
10050+}
10051+
10052+/* ---------------------------------------------------------------------- */
10053+
10054+/* currently, support only FIFO */
4f0767ce
JR
10055+enum {
10056+ AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
10057+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
10058+ AuSp_Last
10059+};
4a4d8108
AM
10060+static int aufs_open_sp(struct inode *inode, struct file *file);
10061+static struct au_sp_fop {
10062+ int done;
10063+ struct file_operations fop; /* not 'const' */
10064+ spinlock_t spin;
10065+} au_sp_fop[AuSp_Last] = {
10066+ [AuSp_FIFO] = {
10067+ .fop = {
10068+ .owner = THIS_MODULE,
10069+ .open = aufs_open_sp
10070+ }
10071+ }
10072+};
10073+
10074+static void au_init_fop_sp(struct file *file)
10075+{
10076+ struct au_sp_fop *p;
10077+ int i;
10078+ struct file *h_file;
10079+
10080+ p = au_sp_fop;
10081+ if (unlikely(!p->done)) {
10082+ /* initialize first time only */
10083+ static DEFINE_SPINLOCK(spin);
10084+
10085+ spin_lock(&spin);
10086+ if (!p->done) {
10087+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
10088+ != AuSp_Last);
10089+ for (i = 0; i < AuSp_Last; i++)
10090+ spin_lock_init(&p[i].spin);
10091+ p->done = 1;
10092+ }
10093+ spin_unlock(&spin);
10094+ }
10095+
10096+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
10097+ case FMODE_READ:
10098+ i = AuSp_FIFO_R;
10099+ break;
10100+ case FMODE_WRITE:
10101+ i = AuSp_FIFO_W;
10102+ break;
10103+ case FMODE_READ | FMODE_WRITE:
10104+ i = AuSp_FIFO_RW;
10105+ break;
10106+ default:
10107+ BUG();
10108+ }
10109+
10110+ p += i;
10111+ if (unlikely(!p->done)) {
10112+ /* initialize first time only */
10113+ h_file = au_hf_top(file);
10114+ spin_lock(&p->spin);
10115+ if (!p->done) {
10116+ p->fop = *h_file->f_op;
10117+ p->fop.owner = THIS_MODULE;
10118+ if (p->fop.aio_read)
10119+ p->fop.aio_read = aufs_aio_read_sp;
10120+ if (p->fop.aio_write)
10121+ p->fop.aio_write = aufs_aio_write_sp;
10122+ p->fop.release = aufs_release_sp;
10123+ p->done = 1;
10124+ }
10125+ spin_unlock(&p->spin);
10126+ }
10127+ file->f_op = &p->fop;
10128+}
10129+
10130+static int au_cpup_sp(struct dentry *dentry)
10131+{
10132+ int err;
10133+ aufs_bindex_t bcpup;
10134+ struct au_pin pin;
10135+ struct au_wr_dir_args wr_dir_args = {
10136+ .force_btgt = -1,
10137+ .flags = 0
10138+ };
10139+
10140+ AuDbg("%.*s\n", AuDLNPair(dentry));
10141+
10142+ di_read_unlock(dentry, AuLock_IR);
10143+ di_write_lock_child(dentry);
10144+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
10145+ if (unlikely(err < 0))
10146+ goto out;
10147+ bcpup = err;
10148+ err = 0;
10149+ if (bcpup == au_dbstart(dentry))
10150+ goto out; /* success */
10151+
10152+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
10153+ AuPin_MNT_WRITE);
10154+ if (!err) {
10155+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
10156+ au_unpin(&pin);
10157+ }
10158+
4f0767ce 10159+out:
4a4d8108
AM
10160+ di_downgrade_lock(dentry, AuLock_IR);
10161+ return err;
10162+}
10163+
10164+static int au_do_open_sp(struct file *file, int flags)
10165+{
10166+ int err;
10167+ struct dentry *dentry;
10168+ struct super_block *sb;
10169+ struct file *h_file;
10170+ struct inode *h_inode;
10171+
10172+ dentry = file->f_dentry;
10173+ AuDbg("%.*s\n", AuDLNPair(dentry));
10174+
10175+ /*
10176+ * try copying-up.
10177+ * operate on the ro branch is not an error.
10178+ */
10179+ au_cpup_sp(dentry); /* ignore */
10180+
10181+ /* prepare h_file */
10182+ err = au_do_open_nondir(file, vfsub_file_flags(file));
10183+ if (unlikely(err))
10184+ goto out;
10185+
10186+ sb = dentry->d_sb;
10187+ h_file = au_hf_top(file);
10188+ h_inode = h_file->f_dentry->d_inode;
10189+ di_read_unlock(dentry, AuLock_IR);
10190+ fi_write_unlock(file);
10191+ si_read_unlock(sb);
10192+ /* open this fifo in aufs */
10193+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
10194+ si_noflush_read_lock(sb);
10195+ fi_write_lock(file);
10196+ di_read_lock_child(dentry, AuLock_IR);
10197+ if (!err)
10198+ au_init_fop_sp(file);
4a4d8108 10199+
4f0767ce 10200+out:
4a4d8108
AM
10201+ return err;
10202+}
10203+
10204+static int aufs_open_sp(struct inode *inode, struct file *file)
10205+{
10206+ int err;
10207+ struct super_block *sb;
10208+
10209+ sb = file->f_dentry->d_sb;
10210+ si_read_lock(sb, AuLock_FLUSH);
10211+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
10212+ si_read_unlock(sb);
10213+ return err;
10214+}
10215+
10216+/* ---------------------------------------------------------------------- */
10217+
10218+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
10219+{
10220+ init_special_inode(inode, mode, rdev);
10221+
10222+ switch (mode & S_IFMT) {
10223+ case S_IFIFO:
10224+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
10225+ /*FALLTHROUGH*/
10226+ case S_IFCHR:
10227+ case S_IFBLK:
10228+ case S_IFSOCK:
10229+ break;
10230+ default:
10231+ AuDebugOn(1);
10232+ }
10233+}
10234+
10235+int au_special_file(umode_t mode)
10236+{
10237+ int ret;
10238+
10239+ ret = 0;
10240+ switch (mode & S_IFMT) {
10241+ case S_IFIFO:
10242+#if 0
10243+ case S_IFCHR:
10244+ case S_IFBLK:
10245+ case S_IFSOCK:
10246+#endif
10247+ ret = 1;
10248+ }
10249+
10250+ return ret;
10251+}
7f207e10
AM
10252diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
10253--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
10254+++ linux/fs/aufs/fstype.h 2010-11-22 11:52:56.987228248 +0100
4a4d8108
AM
10255@@ -0,0 +1,497 @@
10256+/*
10257+ * Copyright (C) 2005-2010 Junjiro R. Okajima
10258+ *
10259+ * This program, aufs is free software; you can redistribute it and/or modify
10260+ * it under the terms of the GNU General Public License as published by
10261+ * the Free Software Foundation; either version 2 of the License, or
10262+ * (at your option) any later version.
10263+ *
10264+ * This program is distributed in the hope that it will be useful,
10265+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10266+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10267+ * GNU General Public License for more details.
10268+ *
10269+ * You should have received a copy of the GNU General Public License
10270+ * along with this program; if not, write to the Free Software
10271+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10272+ */
10273+
10274+/*
10275+ * judging filesystem type
10276+ */
10277+
10278+#ifndef __AUFS_FSTYPE_H__
10279+#define __AUFS_FSTYPE_H__
10280+
10281+#ifdef __KERNEL__
10282+
10283+#include <linux/fs.h>
10284+#include <linux/magic.h>
10285+#include <linux/romfs_fs.h>
10286+#include <linux/aufs_type.h>
10287+
10288+static inline int au_test_aufs(struct super_block *sb)
10289+{
10290+ return sb->s_magic == AUFS_SUPER_MAGIC;
10291+}
10292+
10293+static inline const char *au_sbtype(struct super_block *sb)
10294+{
10295+ return sb->s_type->name;
10296+}
1308ab2a 10297+
10298+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
10299+{
10300+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
10301+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
10302+#else
10303+ return 0;
10304+#endif
10305+}
10306+
1308ab2a 10307+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 10308+{
1308ab2a 10309+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
10310+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
10311+#else
10312+ return 0;
10313+#endif
10314+}
10315+
1308ab2a 10316+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 10317+{
1308ab2a 10318+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
10319+ return sb->s_magic == CRAMFS_MAGIC;
10320+#endif
10321+ return 0;
10322+}
10323+
10324+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
10325+{
10326+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
10327+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
10328+#else
10329+ return 0;
10330+#endif
10331+}
10332+
1308ab2a 10333+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 10334+{
1308ab2a 10335+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
10336+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
10337+#else
10338+ return 0;
10339+#endif
10340+}
10341+
1308ab2a 10342+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 10343+{
1308ab2a 10344+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
10345+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
10346+#else
10347+ return 0;
10348+#endif
10349+}
10350+
1308ab2a 10351+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 10352+{
1308ab2a 10353+#ifdef CONFIG_TMPFS
10354+ return sb->s_magic == TMPFS_MAGIC;
10355+#else
10356+ return 0;
dece6358 10357+#endif
dece6358
AM
10358+}
10359+
1308ab2a 10360+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 10361+{
1308ab2a 10362+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
10363+ return !strcmp(au_sbtype(sb), "ecryptfs");
10364+#else
10365+ return 0;
10366+#endif
1facf9fc 10367+}
10368+
1308ab2a 10369+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 10370+{
1308ab2a 10371+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
10372+ return sb->s_magic == SMB_SUPER_MAGIC;
10373+#else
10374+ return 0;
1facf9fc 10375+#endif
1facf9fc 10376+}
10377+
1308ab2a 10378+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 10379+{
1308ab2a 10380+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
10381+ return sb->s_magic == OCFS2_SUPER_MAGIC;
10382+#else
10383+ return 0;
10384+#endif
1facf9fc 10385+}
10386+
1308ab2a 10387+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 10388+{
1308ab2a 10389+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
10390+ return sb->s_magic == DLMFS_MAGIC;
10391+#else
10392+ return 0;
10393+#endif
1facf9fc 10394+}
10395+
1308ab2a 10396+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 10397+{
1308ab2a 10398+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
10399+ return sb->s_magic == CODA_SUPER_MAGIC;
10400+#else
10401+ return 0;
10402+#endif
10403+}
10404+
10405+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
10406+{
10407+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
10408+ return sb->s_magic == V9FS_MAGIC;
10409+#else
10410+ return 0;
10411+#endif
10412+}
10413+
10414+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
10415+{
10416+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
10417+ return sb->s_magic == EXT4_SUPER_MAGIC;
10418+#else
10419+ return 0;
10420+#endif
10421+}
10422+
10423+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
10424+{
10425+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
10426+ return !strcmp(au_sbtype(sb), "sysv");
10427+#else
10428+ return 0;
10429+#endif
10430+}
10431+
10432+static inline int au_test_ramfs(struct super_block *sb)
10433+{
10434+ return sb->s_magic == RAMFS_MAGIC;
10435+}
10436+
10437+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
10438+{
10439+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
10440+ return sb->s_magic == UBIFS_SUPER_MAGIC;
10441+#else
10442+ return 0;
10443+#endif
10444+}
10445+
10446+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
10447+{
10448+#ifdef CONFIG_PROC_FS
10449+ return sb->s_magic == PROC_SUPER_MAGIC;
10450+#else
10451+ return 0;
10452+#endif
10453+}
10454+
10455+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
10456+{
10457+#ifdef CONFIG_SYSFS
10458+ return sb->s_magic == SYSFS_MAGIC;
10459+#else
10460+ return 0;
10461+#endif
10462+}
10463+
10464+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
10465+{
10466+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
10467+ return sb->s_magic == CONFIGFS_MAGIC;
10468+#else
10469+ return 0;
10470+#endif
10471+}
10472+
10473+static inline int au_test_minix(struct super_block *sb __maybe_unused)
10474+{
10475+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
10476+ return sb->s_magic == MINIX3_SUPER_MAGIC
10477+ || sb->s_magic == MINIX2_SUPER_MAGIC
10478+ || sb->s_magic == MINIX2_SUPER_MAGIC2
10479+ || sb->s_magic == MINIX_SUPER_MAGIC
10480+ || sb->s_magic == MINIX_SUPER_MAGIC2;
10481+#else
10482+ return 0;
10483+#endif
10484+}
10485+
10486+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
10487+{
10488+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
10489+ return sb->s_magic == CIFS_MAGIC_NUMBER;
10490+#else
10491+ return 0;
10492+#endif
10493+}
10494+
10495+static inline int au_test_fat(struct super_block *sb __maybe_unused)
10496+{
10497+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
10498+ return sb->s_magic == MSDOS_SUPER_MAGIC;
10499+#else
10500+ return 0;
10501+#endif
10502+}
10503+
10504+static inline int au_test_msdos(struct super_block *sb)
10505+{
10506+ return au_test_fat(sb);
10507+}
10508+
10509+static inline int au_test_vfat(struct super_block *sb)
10510+{
10511+ return au_test_fat(sb);
10512+}
10513+
10514+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
10515+{
10516+#ifdef CONFIG_SECURITYFS
10517+ return sb->s_magic == SECURITYFS_MAGIC;
10518+#else
10519+ return 0;
10520+#endif
10521+}
10522+
10523+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
10524+{
10525+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
10526+ return sb->s_magic == SQUASHFS_MAGIC;
10527+#else
10528+ return 0;
10529+#endif
10530+}
10531+
10532+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
10533+{
10534+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
10535+ return sb->s_magic == BTRFS_SUPER_MAGIC;
10536+#else
10537+ return 0;
10538+#endif
10539+}
10540+
10541+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
10542+{
10543+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
10544+ return sb->s_magic == XENFS_SUPER_MAGIC;
10545+#else
10546+ return 0;
10547+#endif
10548+}
10549+
10550+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
10551+{
10552+#ifdef CONFIG_DEBUG_FS
10553+ return sb->s_magic == DEBUGFS_MAGIC;
10554+#else
10555+ return 0;
10556+#endif
10557+}
10558+
10559+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
10560+{
10561+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
10562+ return sb->s_magic == NILFS_SUPER_MAGIC;
10563+#else
10564+ return 0;
10565+#endif
10566+}
10567+
4a4d8108
AM
10568+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
10569+{
10570+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
10571+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
10572+#else
10573+ return 0;
10574+#endif
10575+}
10576+
1308ab2a 10577+/* ---------------------------------------------------------------------- */
10578+/*
10579+ * they can't be an aufs branch.
10580+ */
10581+static inline int au_test_fs_unsuppoted(struct super_block *sb)
10582+{
10583+ return
10584+#ifndef CONFIG_AUFS_BR_RAMFS
10585+ au_test_ramfs(sb) ||
10586+#endif
10587+ au_test_procfs(sb)
10588+ || au_test_sysfs(sb)
10589+ || au_test_configfs(sb)
10590+ || au_test_debugfs(sb)
10591+ || au_test_securityfs(sb)
10592+ || au_test_xenfs(sb)
10593+ || au_test_ecryptfs(sb)
10594+ /* || !strcmp(au_sbtype(sb), "unionfs") */
10595+ || au_test_aufs(sb); /* will be supported in next version */
10596+}
10597+
10598+/*
10599+ * If the filesystem supports NFS-export, then it has to support NULL as
10600+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
10601+ * We can apply this principle when we handle a lower filesystem.
10602+ */
10603+static inline int au_test_fs_null_nd(struct super_block *sb)
10604+{
10605+ return !!sb->s_export_op;
10606+}
10607+
10608+static inline int au_test_fs_remote(struct super_block *sb)
10609+{
10610+ return !au_test_tmpfs(sb)
10611+#ifdef CONFIG_AUFS_BR_RAMFS
10612+ && !au_test_ramfs(sb)
10613+#endif
10614+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
10615+}
10616+
10617+/* ---------------------------------------------------------------------- */
10618+
10619+/*
10620+ * Note: these functions (below) are created after reading ->getattr() in all
10621+ * filesystems under linux/fs. it means we have to do so in every update...
10622+ */
10623+
10624+/*
10625+ * some filesystems require getattr to refresh the inode attributes before
10626+ * referencing.
10627+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
10628+ * and leave the work for d_revalidate()
10629+ */
10630+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
10631+{
10632+ return au_test_nfs(sb)
10633+ || au_test_fuse(sb)
10634+ /* || au_test_smbfs(sb) */ /* untested */
10635+ /* || au_test_ocfs2(sb) */ /* untested */
10636+ /* || au_test_btrfs(sb) */ /* untested */
10637+ /* || au_test_coda(sb) */ /* untested */
10638+ /* || au_test_v9fs(sb) */ /* untested */
10639+ ;
10640+}
10641+
10642+/*
10643+ * filesystems which don't maintain i_size or i_blocks.
10644+ */
10645+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
10646+{
10647+ return au_test_xfs(sb)
4a4d8108
AM
10648+ || au_test_btrfs(sb)
10649+ || au_test_ubifs(sb)
10650+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 10651+ /* || au_test_ext4(sb) */ /* untested */
10652+ /* || au_test_ocfs2(sb) */ /* untested */
10653+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
10654+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 10655+ /* || au_test_minix(sb) */ /* untested */
10656+ ;
10657+}
10658+
10659+/*
10660+ * filesystems which don't store the correct value in some of their inode
10661+ * attributes.
10662+ */
10663+static inline int au_test_fs_bad_iattr(struct super_block *sb)
10664+{
10665+ return au_test_fs_bad_iattr_size(sb)
10666+ /* || au_test_cifs(sb) */ /* untested */
10667+ || au_test_fat(sb)
10668+ || au_test_msdos(sb)
10669+ || au_test_vfat(sb);
1facf9fc 10670+}
10671+
10672+/* they don't check i_nlink in link(2) */
10673+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
10674+{
10675+ return au_test_tmpfs(sb)
10676+#ifdef CONFIG_AUFS_BR_RAMFS
10677+ || au_test_ramfs(sb)
10678+#endif
4a4d8108
AM
10679+ || au_test_ubifs(sb)
10680+ || au_test_btrfs(sb)
10681+ || au_test_hfsplus(sb);
1facf9fc 10682+}
10683+
10684+/*
10685+ * filesystems which sets S_NOATIME and S_NOCMTIME.
10686+ */
10687+static inline int au_test_fs_notime(struct super_block *sb)
10688+{
10689+ return au_test_nfs(sb)
10690+ || au_test_fuse(sb)
dece6358 10691+ || au_test_ubifs(sb)
1facf9fc 10692+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 10693+ ;
10694+}
10695+
10696+/*
10697+ * filesystems which requires replacing i_mapping.
10698+ */
10699+static inline int au_test_fs_bad_mapping(struct super_block *sb)
10700+{
dece6358
AM
10701+ return au_test_fuse(sb)
10702+ || au_test_ubifs(sb);
1facf9fc 10703+}
10704+
10705+/* temporary support for i#1 in cramfs */
10706+static inline int au_test_fs_unique_ino(struct inode *inode)
10707+{
10708+ if (au_test_cramfs(inode->i_sb))
10709+ return inode->i_ino != 1;
10710+ return 1;
10711+}
10712+
10713+/* ---------------------------------------------------------------------- */
10714+
10715+/*
10716+ * the filesystem where the xino files placed must support i/o after unlink and
10717+ * maintain i_size and i_blocks.
10718+ */
10719+static inline int au_test_fs_bad_xino(struct super_block *sb)
10720+{
10721+ return au_test_fs_remote(sb)
10722+ || au_test_fs_bad_iattr_size(sb)
10723+#ifdef CONFIG_AUFS_BR_RAMFS
10724+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
10725+#else
10726+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
10727+#endif
10728+ /* don't want unnecessary work for xino */
10729+ || au_test_aufs(sb)
1308ab2a 10730+ || au_test_ecryptfs(sb)
10731+ || au_test_nilfs(sb);
1facf9fc 10732+}
10733+
10734+static inline int au_test_fs_trunc_xino(struct super_block *sb)
10735+{
10736+ return au_test_tmpfs(sb)
10737+ || au_test_ramfs(sb);
10738+}
10739+
10740+/*
10741+ * test if the @sb is real-readonly.
10742+ */
10743+static inline int au_test_fs_rr(struct super_block *sb)
10744+{
10745+ return au_test_squashfs(sb)
10746+ || au_test_iso9660(sb)
10747+ || au_test_cramfs(sb)
10748+ || au_test_romfs(sb);
10749+}
10750+
10751+#endif /* __KERNEL__ */
10752+#endif /* __AUFS_FSTYPE_H__ */
7f207e10
AM
10753diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
10754--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
10755+++ linux/fs/aufs/hfsnotify.c 2010-11-22 11:52:56.987228248 +0100
10756@@ -0,0 +1,216 @@
1facf9fc 10757+/*
4a4d8108 10758+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 10759+ *
10760+ * This program, aufs is free software; you can redistribute it and/or modify
10761+ * it under the terms of the GNU General Public License as published by
10762+ * the Free Software Foundation; either version 2 of the License, or
10763+ * (at your option) any later version.
dece6358
AM
10764+ *
10765+ * This program is distributed in the hope that it will be useful,
10766+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10767+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10768+ * GNU General Public License for more details.
10769+ *
10770+ * You should have received a copy of the GNU General Public License
10771+ * along with this program; if not, write to the Free Software
10772+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 10773+ */
10774+
10775+/*
4a4d8108 10776+ * fsnotify for the lower directories
1facf9fc 10777+ */
10778+
10779+#include "aufs.h"
10780+
4a4d8108
AM
10781+/* FS_IN_IGNORED is unnecessary */
10782+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
10783+ | FS_CREATE | FS_EVENT_ON_CHILD);
10784+static struct fsnotify_group *au_hfsn_group;
7f207e10 10785+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
1facf9fc 10786+
0c5527e5 10787+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 10788+{
0c5527e5
AM
10789+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
10790+ hn_mark);
4a4d8108 10791+ AuDbg("here\n");
7f207e10
AM
10792+ hn->hn_mark_dead = 1;
10793+ smp_mb();
10794+ wake_up_all(&au_hfsn_wq);
4a4d8108 10795+}
1facf9fc 10796+
4a4d8108
AM
10797+static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode)
10798+{
0c5527e5 10799+ struct fsnotify_mark *mark;
1facf9fc 10800+
7f207e10 10801+ hn->hn_mark_dead = 0;
0c5527e5
AM
10802+ mark = &hn->hn_mark;
10803+ fsnotify_init_mark(mark, au_hfsn_free_mark);
10804+ mark->mask = AuHfsnMask;
7f207e10
AM
10805+ /*
10806+ * by udba rename or rmdir, aufs assign a new inode to the known
10807+ * h_inode, so specify 1 to allow dups.
10808+ */
10809+ return fsnotify_add_mark(mark, au_hfsn_group, h_inode, /*mnt*/NULL,
10810+ /*allow_dups*/1);
1facf9fc 10811+}
10812+
4a4d8108 10813+static void au_hfsn_free(struct au_hnotify *hn)
1facf9fc 10814+{
0c5527e5 10815+ struct fsnotify_mark *mark;
953406b4 10816+
0c5527e5
AM
10817+ mark = &hn->hn_mark;
10818+ fsnotify_destroy_mark(mark);
10819+ fsnotify_put_mark(mark);
7f207e10
AM
10820+
10821+ /* TODO: bad approach */
10822+ wait_event(au_hfsn_wq, hn->hn_mark_dead);
1facf9fc 10823+}
10824+
10825+/* ---------------------------------------------------------------------- */
10826+
4a4d8108 10827+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 10828+{
0c5527e5 10829+ struct fsnotify_mark *mark;
1facf9fc 10830+
0c5527e5
AM
10831+ mark = &hinode->hi_notify->hn_mark;
10832+ spin_lock(&mark->lock);
1facf9fc 10833+ if (do_set) {
0c5527e5
AM
10834+ AuDebugOn(mark->mask & AuHfsnMask);
10835+ mark->mask |= AuHfsnMask;
1facf9fc 10836+ } else {
0c5527e5
AM
10837+ AuDebugOn(!(mark->mask & AuHfsnMask));
10838+ mark->mask &= ~AuHfsnMask;
1facf9fc 10839+ }
0c5527e5 10840+ spin_unlock(&mark->lock);
4a4d8108 10841+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 10842+}
10843+
4a4d8108 10844+/* ---------------------------------------------------------------------- */
1facf9fc 10845+
4a4d8108
AM
10846+/* #define AuDbgHnotify */
10847+#ifdef AuDbgHnotify
10848+static char *au_hfsn_name(u32 mask)
10849+{
10850+#ifdef CONFIG_AUFS_DEBUG
10851+#define test_ret(flag) if (mask & flag) \
10852+ return #flag;
10853+ test_ret(FS_ACCESS);
10854+ test_ret(FS_MODIFY);
10855+ test_ret(FS_ATTRIB);
10856+ test_ret(FS_CLOSE_WRITE);
10857+ test_ret(FS_CLOSE_NOWRITE);
10858+ test_ret(FS_OPEN);
10859+ test_ret(FS_MOVED_FROM);
10860+ test_ret(FS_MOVED_TO);
10861+ test_ret(FS_CREATE);
10862+ test_ret(FS_DELETE);
10863+ test_ret(FS_DELETE_SELF);
10864+ test_ret(FS_MOVE_SELF);
10865+ test_ret(FS_UNMOUNT);
10866+ test_ret(FS_Q_OVERFLOW);
10867+ test_ret(FS_IN_IGNORED);
10868+ test_ret(FS_IN_ISDIR);
10869+ test_ret(FS_IN_ONESHOT);
10870+ test_ret(FS_EVENT_ON_CHILD);
10871+ return "";
10872+#undef test_ret
10873+#else
10874+ return "??";
10875+#endif
1facf9fc 10876+}
4a4d8108 10877+#endif
1facf9fc 10878+
10879+/* ---------------------------------------------------------------------- */
10880+
4a4d8108 10881+static int au_hfsn_handle_event(struct fsnotify_group *group,
0c5527e5
AM
10882+ struct fsnotify_mark *inode_mark,
10883+ struct fsnotify_mark *vfsmount_mark,
4a4d8108 10884+ struct fsnotify_event *event)
1facf9fc 10885+{
10886+ int err;
4a4d8108
AM
10887+ struct au_hnotify *hnotify;
10888+ struct inode *h_dir, *h_inode;
10889+ __u32 mask;
4a4d8108
AM
10890+ struct qstr h_child_qstr = {
10891+ .name = event->file_name,
10892+ .len = event->name_len
10893+ };
10894+
10895+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 10896+
10897+ err = 0;
0c5527e5 10898+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108
AM
10899+ mask = event->mask;
10900+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 10901+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 10902+ goto out;
1facf9fc 10903+
4a4d8108
AM
10904+ h_dir = event->to_tell;
10905+ h_inode = event->inode;
10906+#ifdef AuDbgHnotify
10907+ au_debug(1);
10908+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
10909+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
10910+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
10911+ h_dir->i_ino, mask, au_hfsn_name(mask),
10912+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
10913+ /* WARN_ON(1); */
1facf9fc 10914+ }
4a4d8108 10915+ au_debug(0);
1facf9fc 10916+#endif
4a4d8108 10917+
0c5527e5
AM
10918+ AuDebugOn(!inode_mark);
10919+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
10920+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
1facf9fc 10921+
4a4d8108
AM
10922+out:
10923+ return err;
10924+}
1facf9fc 10925+
7f207e10 10926+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
4a4d8108 10927+/* it should be exported to modules */
7f207e10
AM
10928+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
10929+ struct inode *h_inode,
0c5527e5
AM
10930+ struct fsnotify_mark *inode_mark,
10931+ struct fsnotify_mark *vfsmount_mark,
10932+ __u32 mask, void *data, int data_type)
4a4d8108 10933+{
4a4d8108 10934+ mask = (mask & ~FS_EVENT_ON_CHILD);
7f207e10 10935+ return inode_mark->mask & mask;
4a4d8108
AM
10936+}
10937+
10938+static struct fsnotify_ops au_hfsn_ops = {
10939+ .should_send_event = au_hfsn_should_send_event,
10940+ .handle_event = au_hfsn_handle_event
10941+};
10942+
10943+/* ---------------------------------------------------------------------- */
10944+
10945+static int __init au_hfsn_init(void)
10946+{
10947+ int err;
1facf9fc 10948+
4a4d8108 10949+ err = 0;
0c5527e5 10950+ au_hfsn_group = fsnotify_alloc_group(&au_hfsn_ops);
4a4d8108 10951+ if (IS_ERR(au_hfsn_group)) {
4a4d8108 10952+ err = PTR_ERR(au_hfsn_group);
0c5527e5 10953+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
4a4d8108 10954+ }
1facf9fc 10955+
1facf9fc 10956+ AuTraceErr(err);
10957+ return err;
10958+}
10959+
4a4d8108 10960+static void au_hfsn_fin(void)
1facf9fc 10961+{
4a4d8108
AM
10962+ fsnotify_put_group(au_hfsn_group);
10963+}
1facf9fc 10964+
4a4d8108
AM
10965+const struct au_hnotify_op au_hnotify_op = {
10966+ .ctl = au_hfsn_ctl,
10967+ .alloc = au_hfsn_alloc,
10968+ .free = au_hfsn_free,
1facf9fc 10969+
4a4d8108
AM
10970+ .fin = au_hfsn_fin,
10971+ .init = au_hfsn_init
10972+};
7f207e10
AM
10973diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
10974--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
10975+++ linux/fs/aufs/hfsplus.c 2010-11-22 11:52:56.987228248 +0100
4a4d8108
AM
10976@@ -0,0 +1,58 @@
10977+/*
10978+ * Copyright (C) 2010 Junjiro R. Okajima
10979+ *
10980+ * This program, aufs is free software; you can redistribute it and/or modify
10981+ * it under the terms of the GNU General Public License as published by
10982+ * the Free Software Foundation; either version 2 of the License, or
10983+ * (at your option) any later version.
10984+ *
10985+ * This program is distributed in the hope that it will be useful,
10986+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10987+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10988+ * GNU General Public License for more details.
10989+ *
10990+ * You should have received a copy of the GNU General Public License
10991+ * along with this program; if not, write to the Free Software
10992+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10993+ */
1facf9fc 10994+
4a4d8108
AM
10995+/*
10996+ * special support for filesystems which aqucires an inode mutex
10997+ * at final closing a file, eg, hfsplus.
10998+ *
10999+ * This trick is very simple and stupid, just to open the file before really
11000+ * neceeary open to tell hfsplus that this is not the final closing.
11001+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
11002+ * and au_h_open_post() after releasing it.
11003+ */
1facf9fc 11004+
4a4d8108
AM
11005+#include <linux/file.h>
11006+#include "aufs.h"
1facf9fc 11007+
4a4d8108
AM
11008+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
11009+{
11010+ struct file *h_file;
11011+ struct dentry *h_dentry;
1facf9fc 11012+
4a4d8108
AM
11013+ h_dentry = au_h_dptr(dentry, bindex);
11014+ AuDebugOn(!h_dentry);
11015+ AuDebugOn(!h_dentry->d_inode);
11016+ IMustLock(h_dentry->d_inode);
11017+
11018+ h_file = NULL;
11019+ if (au_test_hfsplus(h_dentry->d_sb)
11020+ && S_ISREG(h_dentry->d_inode->i_mode))
11021+ h_file = au_h_open(dentry, bindex,
11022+ O_RDONLY | O_NOATIME | O_LARGEFILE,
11023+ /*file*/NULL);
11024+ return h_file;
1facf9fc 11025+}
11026+
4a4d8108
AM
11027+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
11028+ struct file *h_file)
11029+{
11030+ if (h_file) {
11031+ fput(h_file);
11032+ au_sbr_put(dentry->d_sb, bindex);
11033+ }
11034+}
7f207e10
AM
11035diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
11036--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
11037+++ linux/fs/aufs/hnotify.c 2010-11-22 11:52:56.987228248 +0100
11038@@ -0,0 +1,664 @@
e49829fe
JR
11039+/*
11040+ * Copyright (C) 2005-2010 Junjiro R. Okajima
11041+ *
11042+ * This program, aufs is free software; you can redistribute it and/or modify
11043+ * it under the terms of the GNU General Public License as published by
11044+ * the Free Software Foundation; either version 2 of the License, or
11045+ * (at your option) any later version.
11046+ *
11047+ * This program is distributed in the hope that it will be useful,
11048+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11049+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11050+ * GNU General Public License for more details.
11051+ *
11052+ * You should have received a copy of the GNU General Public License
11053+ * along with this program; if not, write to the Free Software
11054+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11055+ */
11056+
11057+/*
7f207e10 11058+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
11059+ */
11060+
11061+#include "aufs.h"
11062+
7f207e10
AM
11063+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
11064+ struct inode *h_inode)
e49829fe
JR
11065+{
11066+ int err;
7f207e10 11067+ struct au_hnotify *hn;
1facf9fc 11068+
4a4d8108
AM
11069+ err = -ENOMEM;
11070+ hn = au_cache_alloc_hnotify();
11071+ if (hn) {
11072+ hn->hn_aufs_inode = inode;
11073+ err = au_hnotify_op.alloc(hn, h_inode);
11074+ if (!err)
11075+ hinode->hi_notify = hn;
11076+ else {
11077+ au_cache_free_hnotify(hn);
11078+ /*
11079+ * The upper dir was removed by udba, but the same named
11080+ * dir left. In this case, aufs assignes a new inode
11081+ * number and set the monitor again.
11082+ * For the lower dir, the old monitnor is still left.
11083+ */
11084+ if (err == -EEXIST)
11085+ err = 0;
11086+ }
1308ab2a 11087+ }
1308ab2a 11088+
1308ab2a 11089+ return err;
dece6358 11090+}
1facf9fc 11091+
4a4d8108 11092+void au_hn_free(struct au_hinode *hinode)
dece6358 11093+{
4a4d8108 11094+ struct au_hnotify *hn;
1facf9fc 11095+
4a4d8108
AM
11096+ hn = hinode->hi_notify;
11097+ if (hn) {
11098+ au_hnotify_op.free(hn);
11099+ au_cache_free_hnotify(hn);
11100+ hinode->hi_notify = NULL;
11101+ }
11102+}
dece6358 11103+
4a4d8108 11104+/* ---------------------------------------------------------------------- */
dece6358 11105+
4a4d8108
AM
11106+void au_hn_ctl(struct au_hinode *hinode, int do_set)
11107+{
11108+ if (hinode->hi_notify)
11109+ au_hnotify_op.ctl(hinode, do_set);
11110+}
11111+
11112+void au_hn_reset(struct inode *inode, unsigned int flags)
11113+{
11114+ aufs_bindex_t bindex, bend;
11115+ struct inode *hi;
11116+ struct dentry *iwhdentry;
1facf9fc 11117+
1308ab2a 11118+ bend = au_ibend(inode);
4a4d8108
AM
11119+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
11120+ hi = au_h_iptr(inode, bindex);
11121+ if (!hi)
11122+ continue;
1308ab2a 11123+
4a4d8108
AM
11124+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
11125+ iwhdentry = au_hi_wh(inode, bindex);
11126+ if (iwhdentry)
11127+ dget(iwhdentry);
11128+ au_igrab(hi);
11129+ au_set_h_iptr(inode, bindex, NULL, 0);
11130+ au_set_h_iptr(inode, bindex, au_igrab(hi),
11131+ flags & ~AuHi_XINO);
11132+ iput(hi);
11133+ dput(iwhdentry);
11134+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 11135+ }
1facf9fc 11136+}
11137+
1308ab2a 11138+/* ---------------------------------------------------------------------- */
1facf9fc 11139+
4a4d8108 11140+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 11141+{
4a4d8108
AM
11142+ int err;
11143+ aufs_bindex_t bindex, bend, bfound, bstart;
11144+ struct inode *h_i;
1facf9fc 11145+
4a4d8108
AM
11146+ err = 0;
11147+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11148+ pr_warning("branch root dir was changed\n");
11149+ goto out;
11150+ }
1facf9fc 11151+
4a4d8108
AM
11152+ bfound = -1;
11153+ bend = au_ibend(inode);
11154+ bstart = au_ibstart(inode);
11155+#if 0 /* reserved for future use */
11156+ if (bindex == bend) {
11157+ /* keep this ino in rename case */
11158+ goto out;
11159+ }
11160+#endif
11161+ for (bindex = bstart; bindex <= bend; bindex++)
11162+ if (au_h_iptr(inode, bindex) == h_inode) {
11163+ bfound = bindex;
11164+ break;
11165+ }
11166+ if (bfound < 0)
1308ab2a 11167+ goto out;
1facf9fc 11168+
4a4d8108
AM
11169+ for (bindex = bstart; bindex <= bend; bindex++) {
11170+ h_i = au_h_iptr(inode, bindex);
11171+ if (!h_i)
11172+ continue;
1facf9fc 11173+
4a4d8108
AM
11174+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
11175+ /* ignore this error */
11176+ /* bad action? */
1facf9fc 11177+ }
1facf9fc 11178+
4a4d8108 11179+ /* children inode number will be broken */
1facf9fc 11180+
4f0767ce 11181+out:
4a4d8108
AM
11182+ AuTraceErr(err);
11183+ return err;
1facf9fc 11184+}
11185+
4a4d8108 11186+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 11187+{
4a4d8108
AM
11188+ int err, i, j, ndentry;
11189+ struct au_dcsub_pages dpages;
11190+ struct au_dpage *dpage;
11191+ struct dentry **dentries;
1facf9fc 11192+
4a4d8108
AM
11193+ err = au_dpages_init(&dpages, GFP_NOFS);
11194+ if (unlikely(err))
11195+ goto out;
11196+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
11197+ if (unlikely(err))
11198+ goto out_dpages;
1facf9fc 11199+
4a4d8108
AM
11200+ for (i = 0; i < dpages.ndpage; i++) {
11201+ dpage = dpages.dpages + i;
11202+ dentries = dpage->dentries;
11203+ ndentry = dpage->ndentry;
11204+ for (j = 0; j < ndentry; j++) {
11205+ struct dentry *d;
11206+
11207+ d = dentries[j];
11208+ if (IS_ROOT(d))
11209+ continue;
11210+
11211+ d_drop(d);
11212+ au_digen_dec(d);
11213+ if (d->d_inode)
11214+ /* todo: reset children xino?
11215+ cached children only? */
11216+ au_iigen_dec(d->d_inode);
1308ab2a 11217+ }
dece6358 11218+ }
1facf9fc 11219+
4f0767ce 11220+out_dpages:
4a4d8108 11221+ au_dpages_free(&dpages);
dece6358 11222+
4a4d8108
AM
11223+ /* discard children */
11224+ dentry_unhash(dentry);
11225+ dput(dentry);
4f0767ce 11226+out:
dece6358
AM
11227+ return err;
11228+}
11229+
1308ab2a 11230+/*
4a4d8108 11231+ * return 0 if processed.
1308ab2a 11232+ */
4a4d8108
AM
11233+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
11234+ const unsigned int isdir)
dece6358 11235+{
1308ab2a 11236+ int err;
4a4d8108
AM
11237+ struct dentry *d;
11238+ struct qstr *dname;
1facf9fc 11239+
4a4d8108
AM
11240+ err = 1;
11241+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11242+ pr_warning("branch root dir was changed\n");
11243+ err = 0;
11244+ goto out;
11245+ }
dece6358 11246+
4a4d8108
AM
11247+ if (!isdir) {
11248+ AuDebugOn(!name);
11249+ au_iigen_dec(inode);
11250+ spin_lock(&dcache_lock);
11251+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
11252+ dname = &d->d_name;
11253+ if (dname->len != nlen
11254+ && memcmp(dname->name, name, nlen))
11255+ continue;
11256+ err = 0;
11257+ spin_lock(&d->d_lock);
11258+ __d_drop(d);
11259+ au_digen_dec(d);
11260+ spin_unlock(&d->d_lock);
11261+ break;
1facf9fc 11262+ }
4a4d8108 11263+ spin_unlock(&dcache_lock);
1308ab2a 11264+ } else {
4a4d8108
AM
11265+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
11266+ d = d_find_alias(inode);
11267+ if (!d) {
11268+ au_iigen_dec(inode);
11269+ goto out;
11270+ }
1facf9fc 11271+
4a4d8108
AM
11272+ dname = &d->d_name;
11273+ if (dname->len == nlen && !memcmp(dname->name, name, nlen))
11274+ err = hn_gen_tree(d);
11275+ dput(d);
11276+ }
1facf9fc 11277+
4f0767ce 11278+out:
4a4d8108 11279+ AuTraceErr(err);
1308ab2a 11280+ return err;
11281+}
dece6358 11282+
4a4d8108 11283+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 11284+{
4a4d8108
AM
11285+ int err;
11286+ struct inode *inode;
1facf9fc 11287+
4a4d8108
AM
11288+ inode = dentry->d_inode;
11289+ if (IS_ROOT(dentry)
11290+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
11291+ ) {
11292+ pr_warning("branch root dir was changed\n");
11293+ return 0;
11294+ }
1308ab2a 11295+
4a4d8108
AM
11296+ err = 0;
11297+ if (!isdir) {
11298+ d_drop(dentry);
11299+ au_digen_dec(dentry);
11300+ if (inode)
11301+ au_iigen_dec(inode);
11302+ } else {
11303+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
11304+ if (inode)
11305+ err = hn_gen_tree(dentry);
11306+ }
11307+
11308+ AuTraceErr(err);
11309+ return err;
1facf9fc 11310+}
11311+
4a4d8108 11312+/* ---------------------------------------------------------------------- */
1facf9fc 11313+
4a4d8108
AM
11314+/* hnotify job flags */
11315+#define AuHnJob_XINO0 1
11316+#define AuHnJob_GEN (1 << 1)
11317+#define AuHnJob_DIRENT (1 << 2)
11318+#define AuHnJob_ISDIR (1 << 3)
11319+#define AuHnJob_TRYXINO0 (1 << 4)
11320+#define AuHnJob_MNTPNT (1 << 5)
11321+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
11322+#define au_fset_hnjob(flags, name) \
11323+ do { (flags) |= AuHnJob_##name; } while (0)
11324+#define au_fclr_hnjob(flags, name) \
11325+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 11326+
4a4d8108
AM
11327+enum {
11328+ AuHn_CHILD,
11329+ AuHn_PARENT,
11330+ AuHnLast
11331+};
1facf9fc 11332+
4a4d8108
AM
11333+struct au_hnotify_args {
11334+ struct inode *h_dir, *dir, *h_child_inode;
11335+ u32 mask;
11336+ unsigned int flags[AuHnLast];
11337+ unsigned int h_child_nlen;
11338+ char h_child_name[];
11339+};
1facf9fc 11340+
4a4d8108
AM
11341+struct hn_job_args {
11342+ unsigned int flags;
11343+ struct inode *inode, *h_inode, *dir, *h_dir;
11344+ struct dentry *dentry;
11345+ char *h_name;
11346+ int h_nlen;
11347+};
1308ab2a 11348+
4a4d8108
AM
11349+static int hn_job(struct hn_job_args *a)
11350+{
11351+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 11352+
4a4d8108
AM
11353+ /* reset xino */
11354+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
11355+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 11356+
4a4d8108
AM
11357+ if (au_ftest_hnjob(a->flags, TRYXINO0)
11358+ && a->inode
11359+ && a->h_inode) {
11360+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11361+ if (!a->h_inode->i_nlink)
11362+ hn_xino(a->inode, a->h_inode); /* ignore this error */
11363+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 11364+ }
1facf9fc 11365+
4a4d8108
AM
11366+ /* make the generation obsolete */
11367+ if (au_ftest_hnjob(a->flags, GEN)) {
11368+ int err = -1;
11369+ if (a->inode)
11370+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
11371+ isdir);
11372+ if (err && a->dentry)
11373+ hn_gen_by_name(a->dentry, isdir);
11374+ /* ignore this error */
1facf9fc 11375+ }
1facf9fc 11376+
4a4d8108
AM
11377+ /* make dir entries obsolete */
11378+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
11379+ struct au_vdir *vdir;
1facf9fc 11380+
4a4d8108
AM
11381+ vdir = au_ivdir(a->inode);
11382+ if (vdir)
11383+ vdir->vd_jiffy = 0;
11384+ /* IMustLock(a->inode); */
11385+ /* a->inode->i_version++; */
11386+ }
1facf9fc 11387+
4a4d8108
AM
11388+ /* can do nothing but warn */
11389+ if (au_ftest_hnjob(a->flags, MNTPNT)
11390+ && a->dentry
11391+ && d_mountpoint(a->dentry))
11392+ pr_warning("mount-point %.*s is removed or renamed\n",
11393+ AuDLNPair(a->dentry));
1facf9fc 11394+
4a4d8108 11395+ return 0;
1308ab2a 11396+}
1facf9fc 11397+
1308ab2a 11398+/* ---------------------------------------------------------------------- */
1facf9fc 11399+
4a4d8108
AM
11400+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
11401+ struct inode *dir)
1308ab2a 11402+{
4a4d8108
AM
11403+ struct dentry *dentry, *d, *parent;
11404+ struct qstr *dname;
1308ab2a 11405+
4a4d8108
AM
11406+ parent = d_find_alias(dir);
11407+ if (!parent)
11408+ return NULL;
1308ab2a 11409+
4a4d8108
AM
11410+ dentry = NULL;
11411+ spin_lock(&dcache_lock);
11412+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
11413+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
11414+ dname = &d->d_name;
11415+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
11416+ continue;
11417+ if (!atomic_read(&d->d_count) || !d->d_fsdata) {
11418+ spin_lock(&d->d_lock);
11419+ __d_drop(d);
11420+ spin_unlock(&d->d_lock);
11421+ continue;
dece6358 11422+ }
1facf9fc 11423+
4a4d8108
AM
11424+ dentry = dget(d);
11425+ break;
1308ab2a 11426+ }
4a4d8108
AM
11427+ spin_unlock(&dcache_lock);
11428+ dput(parent);
1facf9fc 11429+
4a4d8108
AM
11430+ if (dentry)
11431+ di_write_lock_child(dentry);
1308ab2a 11432+
4a4d8108
AM
11433+ return dentry;
11434+}
dece6358 11435+
4a4d8108
AM
11436+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
11437+ aufs_bindex_t bindex, ino_t h_ino)
11438+{
11439+ struct inode *inode;
11440+ ino_t ino;
11441+ int err;
11442+
11443+ inode = NULL;
11444+ err = au_xino_read(sb, bindex, h_ino, &ino);
11445+ if (!err && ino)
11446+ inode = ilookup(sb, ino);
11447+ if (!inode)
11448+ goto out;
11449+
11450+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11451+ pr_warning("wrong root branch\n");
11452+ iput(inode);
11453+ inode = NULL;
11454+ goto out;
1308ab2a 11455+ }
11456+
4a4d8108 11457+ ii_write_lock_child(inode);
1308ab2a 11458+
4f0767ce 11459+out:
4a4d8108 11460+ return inode;
dece6358
AM
11461+}
11462+
4a4d8108 11463+static void au_hn_bh(void *_args)
1facf9fc 11464+{
4a4d8108
AM
11465+ struct au_hnotify_args *a = _args;
11466+ struct super_block *sb;
11467+ aufs_bindex_t bindex, bend, bfound;
11468+ unsigned char xino, try_iput;
1facf9fc 11469+ int err;
1308ab2a 11470+ struct inode *inode;
4a4d8108
AM
11471+ ino_t h_ino;
11472+ struct hn_job_args args;
11473+ struct dentry *dentry;
11474+ struct au_sbinfo *sbinfo;
1facf9fc 11475+
4a4d8108
AM
11476+ AuDebugOn(!_args);
11477+ AuDebugOn(!a->h_dir);
11478+ AuDebugOn(!a->dir);
11479+ AuDebugOn(!a->mask);
11480+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
11481+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
11482+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 11483+
4a4d8108
AM
11484+ inode = NULL;
11485+ dentry = NULL;
11486+ /*
11487+ * do not lock a->dir->i_mutex here
11488+ * because of d_revalidate() may cause a deadlock.
11489+ */
11490+ sb = a->dir->i_sb;
11491+ AuDebugOn(!sb);
11492+ sbinfo = au_sbi(sb);
11493+ AuDebugOn(!sbinfo);
7f207e10 11494+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 11495+
4a4d8108
AM
11496+ ii_read_lock_parent(a->dir);
11497+ bfound = -1;
11498+ bend = au_ibend(a->dir);
11499+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
11500+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
11501+ bfound = bindex;
11502+ break;
11503+ }
11504+ ii_read_unlock(a->dir);
11505+ if (unlikely(bfound < 0))
11506+ goto out;
1facf9fc 11507+
4a4d8108
AM
11508+ xino = !!au_opt_test(au_mntflags(sb), XINO);
11509+ h_ino = 0;
11510+ if (a->h_child_inode)
11511+ h_ino = a->h_child_inode->i_ino;
1facf9fc 11512+
4a4d8108
AM
11513+ if (a->h_child_nlen
11514+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
11515+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
11516+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
11517+ a->dir);
11518+ try_iput = 0;
11519+ if (dentry)
11520+ inode = dentry->d_inode;
11521+ if (xino && !inode && h_ino
11522+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
11523+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
11524+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
11525+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
11526+ try_iput = 1;
11527+ }
1facf9fc 11528+
4a4d8108
AM
11529+ args.flags = a->flags[AuHn_CHILD];
11530+ args.dentry = dentry;
11531+ args.inode = inode;
11532+ args.h_inode = a->h_child_inode;
11533+ args.dir = a->dir;
11534+ args.h_dir = a->h_dir;
11535+ args.h_name = a->h_child_name;
11536+ args.h_nlen = a->h_child_nlen;
11537+ err = hn_job(&args);
11538+ if (dentry) {
11539+ if (dentry->d_fsdata)
11540+ di_write_unlock(dentry);
11541+ dput(dentry);
11542+ }
11543+ if (inode && try_iput) {
11544+ ii_write_unlock(inode);
11545+ iput(inode);
11546+ }
1facf9fc 11547+
4a4d8108
AM
11548+ ii_write_lock_parent(a->dir);
11549+ args.flags = a->flags[AuHn_PARENT];
11550+ args.dentry = NULL;
11551+ args.inode = a->dir;
11552+ args.h_inode = a->h_dir;
11553+ args.dir = NULL;
11554+ args.h_dir = NULL;
11555+ args.h_name = NULL;
11556+ args.h_nlen = 0;
11557+ err = hn_job(&args);
11558+ ii_write_unlock(a->dir);
1facf9fc 11559+
4f0767ce 11560+out:
4a4d8108
AM
11561+ au_nwt_done(&sbinfo->si_nowait);
11562+ si_write_unlock(sb);
1308ab2a 11563+
4a4d8108
AM
11564+ iput(a->h_child_inode);
11565+ iput(a->h_dir);
11566+ iput(a->dir);
1308ab2a 11567+ kfree(a);
dece6358 11568+}
1facf9fc 11569+
4a4d8108
AM
11570+/* ---------------------------------------------------------------------- */
11571+
11572+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
11573+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 11574+{
4a4d8108
AM
11575+ int err, len;
11576+ unsigned int flags[AuHnLast];
11577+ unsigned char isdir, isroot, wh;
11578+ struct inode *dir;
11579+ struct au_hnotify_args *args;
11580+ char *p, *h_child_name;
dece6358 11581+
1308ab2a 11582+ err = 0;
4a4d8108
AM
11583+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
11584+ dir = igrab(hnotify->hn_aufs_inode);
11585+ if (!dir)
11586+ goto out;
1facf9fc 11587+
4a4d8108
AM
11588+ isroot = (dir->i_ino == AUFS_ROOT_INO);
11589+ wh = 0;
11590+ h_child_name = (void *)h_child_qstr->name;
11591+ len = h_child_qstr->len;
11592+ if (h_child_name) {
11593+ if (len > AUFS_WH_PFX_LEN
11594+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
11595+ h_child_name += AUFS_WH_PFX_LEN;
11596+ len -= AUFS_WH_PFX_LEN;
11597+ wh = 1;
11598+ }
1facf9fc 11599+ }
dece6358 11600+
4a4d8108
AM
11601+ isdir = 0;
11602+ if (h_child_inode)
11603+ isdir = !!S_ISDIR(h_child_inode->i_mode);
11604+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
11605+ flags[AuHn_CHILD] = 0;
11606+ if (isdir)
11607+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
11608+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
11609+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
11610+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
11611+ case FS_MOVED_FROM:
11612+ case FS_MOVED_TO:
11613+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
11614+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11615+ /*FALLTHROUGH*/
11616+ case FS_CREATE:
11617+ AuDebugOn(!h_child_name || !h_child_inode);
11618+ break;
1facf9fc 11619+
4a4d8108
AM
11620+ case FS_DELETE:
11621+ /*
11622+ * aufs never be able to get this child inode.
11623+ * revalidation should be in d_revalidate()
11624+ * by checking i_nlink, i_generation or d_unhashed().
11625+ */
11626+ AuDebugOn(!h_child_name);
11627+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
11628+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11629+ break;
dece6358 11630+
4a4d8108
AM
11631+ default:
11632+ AuDebugOn(1);
11633+ }
1308ab2a 11634+
4a4d8108
AM
11635+ if (wh)
11636+ h_child_inode = NULL;
1308ab2a 11637+
4a4d8108
AM
11638+ err = -ENOMEM;
11639+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 11640+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
11641+ if (unlikely(!args)) {
11642+ AuErr1("no memory\n");
11643+ iput(dir);
11644+ goto out;
11645+ }
11646+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
11647+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
11648+ args->mask = mask;
11649+ args->dir = dir;
11650+ args->h_dir = igrab(h_dir);
11651+ if (h_child_inode)
11652+ h_child_inode = igrab(h_child_inode); /* can be NULL */
11653+ args->h_child_inode = h_child_inode;
11654+ args->h_child_nlen = len;
11655+ if (len) {
11656+ p = (void *)args;
11657+ p += sizeof(*args);
11658+ memcpy(p, h_child_name, len);
11659+ p[len] = 0;
1308ab2a 11660+ }
1308ab2a 11661+
4a4d8108 11662+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
4a4d8108
AM
11663+ if (unlikely(err)) {
11664+ pr_err("wkq %d\n", err);
11665+ iput(args->h_child_inode);
11666+ iput(args->h_dir);
11667+ iput(args->dir);
11668+ kfree(args);
1facf9fc 11669+ }
1facf9fc 11670+
4a4d8108 11671+out:
1facf9fc 11672+ return err;
11673+}
11674+
4a4d8108
AM
11675+static void au_hn_destroy_cache(void)
11676+{
11677+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
11678+ au_cachep[AuCache_HNOTIFY] = NULL;
11679+}
1308ab2a 11680+
4a4d8108 11681+int __init au_hnotify_init(void)
1facf9fc 11682+{
1308ab2a 11683+ int err;
1308ab2a 11684+
4a4d8108
AM
11685+ err = -ENOMEM;
11686+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
11687+ if (au_cachep[AuCache_HNOTIFY]) {
11688+ err = au_hnotify_op.init();
11689+ if (unlikely(err))
11690+ au_hn_destroy_cache();
1308ab2a 11691+ }
1308ab2a 11692+ AuTraceErr(err);
4a4d8108 11693+ return err;
1308ab2a 11694+}
11695+
4a4d8108 11696+void au_hnotify_fin(void)
1308ab2a 11697+{
4a4d8108
AM
11698+ au_hnotify_op.fin();
11699+ /* cf. au_cache_fin() */
11700+ if (au_cachep[AuCache_HNOTIFY])
11701+ au_hn_destroy_cache();
dece6358 11702+}
7f207e10
AM
11703diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
11704--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
11705+++ linux/fs/aufs/iinfo.c 2010-11-22 11:52:56.987228248 +0100
11706@@ -0,0 +1,261 @@
dece6358 11707+/*
4a4d8108 11708+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
11709+ *
11710+ * This program, aufs is free software; you can redistribute it and/or modify
11711+ * it under the terms of the GNU General Public License as published by
11712+ * the Free Software Foundation; either version 2 of the License, or
11713+ * (at your option) any later version.
11714+ *
11715+ * This program is distributed in the hope that it will be useful,
11716+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11717+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11718+ * GNU General Public License for more details.
11719+ *
11720+ * You should have received a copy of the GNU General Public License
11721+ * along with this program; if not, write to the Free Software
11722+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11723+ */
1facf9fc 11724+
dece6358 11725+/*
4a4d8108 11726+ * inode private data
dece6358 11727+ */
1facf9fc 11728+
1308ab2a 11729+#include "aufs.h"
1facf9fc 11730+
4a4d8108 11731+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 11732+{
4a4d8108 11733+ struct inode *h_inode;
1facf9fc 11734+
4a4d8108 11735+ IiMustAnyLock(inode);
1facf9fc 11736+
4a4d8108
AM
11737+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
11738+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11739+ return h_inode;
11740+}
1facf9fc 11741+
4a4d8108
AM
11742+/* todo: hard/soft set? */
11743+void au_hiput(struct au_hinode *hinode)
11744+{
11745+ au_hn_free(hinode);
11746+ dput(hinode->hi_whdentry);
11747+ iput(hinode->hi_inode);
11748+}
1facf9fc 11749+
4a4d8108
AM
11750+unsigned int au_hi_flags(struct inode *inode, int isdir)
11751+{
11752+ unsigned int flags;
11753+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 11754+
4a4d8108
AM
11755+ flags = 0;
11756+ if (au_opt_test(mnt_flags, XINO))
11757+ au_fset_hi(flags, XINO);
11758+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
11759+ au_fset_hi(flags, HNOTIFY);
11760+ return flags;
1facf9fc 11761+}
11762+
4a4d8108
AM
11763+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
11764+ struct inode *h_inode, unsigned int flags)
1308ab2a 11765+{
4a4d8108
AM
11766+ struct au_hinode *hinode;
11767+ struct inode *hi;
11768+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 11769+
4a4d8108 11770+ IiMustWriteLock(inode);
dece6358 11771+
4a4d8108
AM
11772+ hinode = iinfo->ii_hinode + bindex;
11773+ hi = hinode->hi_inode;
11774+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11775+
11776+ if (hi)
11777+ au_hiput(hinode);
11778+ hinode->hi_inode = h_inode;
11779+ if (h_inode) {
11780+ int err;
11781+ struct super_block *sb = inode->i_sb;
11782+ struct au_branch *br;
11783+
11784+ if (bindex == iinfo->ii_bstart)
11785+ au_cpup_igen(inode, h_inode);
11786+ br = au_sbr(sb, bindex);
11787+ hinode->hi_id = br->br_id;
11788+ if (au_ftest_hi(flags, XINO)) {
11789+ err = au_xino_write(sb, bindex, h_inode->i_ino,
11790+ inode->i_ino);
11791+ if (unlikely(err))
11792+ AuIOErr1("failed au_xino_write() %d\n", err);
11793+ }
11794+
11795+ if (au_ftest_hi(flags, HNOTIFY)
11796+ && au_br_hnotifyable(br->br_perm)) {
11797+ err = au_hn_alloc(hinode, inode, h_inode);
11798+ if (unlikely(err))
11799+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 11800+ }
11801+ }
4a4d8108 11802+}
dece6358 11803+
4a4d8108
AM
11804+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
11805+ struct dentry *h_wh)
11806+{
11807+ struct au_hinode *hinode;
dece6358 11808+
4a4d8108
AM
11809+ IiMustWriteLock(inode);
11810+
11811+ hinode = au_ii(inode)->ii_hinode + bindex;
11812+ AuDebugOn(hinode->hi_whdentry);
11813+ hinode->hi_whdentry = h_wh;
1facf9fc 11814+}
11815+
4a4d8108 11816+void au_update_iigen(struct inode *inode)
1308ab2a 11817+{
4a4d8108
AM
11818+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
11819+ /* smp_mb(); */ /* atomic_set */
11820+}
1facf9fc 11821+
4a4d8108
AM
11822+/* it may be called at remount time, too */
11823+void au_update_ibrange(struct inode *inode, int do_put_zero)
11824+{
11825+ struct au_iinfo *iinfo;
1facf9fc 11826+
4a4d8108
AM
11827+ iinfo = au_ii(inode);
11828+ if (!iinfo || iinfo->ii_bstart < 0)
11829+ return;
1facf9fc 11830+
4a4d8108 11831+ IiMustWriteLock(inode);
1facf9fc 11832+
4a4d8108
AM
11833+ if (do_put_zero) {
11834+ aufs_bindex_t bindex;
1facf9fc 11835+
4a4d8108
AM
11836+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
11837+ bindex++) {
11838+ struct inode *h_i;
1facf9fc 11839+
4a4d8108
AM
11840+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
11841+ if (h_i && !h_i->i_nlink)
11842+ au_set_h_iptr(inode, bindex, NULL, 0);
11843+ }
11844+ }
1308ab2a 11845+
4a4d8108
AM
11846+ iinfo->ii_bstart = -1;
11847+ while (++iinfo->ii_bstart <= iinfo->ii_bend)
11848+ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
11849+ break;
11850+ if (iinfo->ii_bstart > iinfo->ii_bend) {
11851+ iinfo->ii_bstart = -1;
11852+ iinfo->ii_bend = -1;
11853+ return;
11854+ }
11855+
11856+ iinfo->ii_bend++;
11857+ while (0 <= --iinfo->ii_bend)
11858+ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
11859+ break;
11860+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
1308ab2a 11861+}
1facf9fc 11862+
dece6358 11863+/* ---------------------------------------------------------------------- */
1facf9fc 11864+
4a4d8108 11865+void au_icntnr_init_once(void *_c)
dece6358 11866+{
4a4d8108
AM
11867+ struct au_icntnr *c = _c;
11868+ struct au_iinfo *iinfo = &c->iinfo;
e49829fe 11869+ static struct lock_class_key aufs_ii;
1facf9fc 11870+
4a4d8108 11871+ au_rw_init(&iinfo->ii_rwsem);
e49829fe 11872+ au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
4a4d8108
AM
11873+ inode_init_once(&c->vfs_inode);
11874+}
1facf9fc 11875+
4a4d8108
AM
11876+int au_iinfo_init(struct inode *inode)
11877+{
11878+ struct au_iinfo *iinfo;
11879+ struct super_block *sb;
11880+ int nbr, i;
1facf9fc 11881+
4a4d8108
AM
11882+ sb = inode->i_sb;
11883+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
11884+ nbr = au_sbend(sb) + 1;
11885+ if (unlikely(nbr <= 0))
11886+ nbr = 1;
11887+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
11888+ if (iinfo->ii_hinode) {
7f207e10 11889+ au_ninodes_inc(sb);
4a4d8108
AM
11890+ for (i = 0; i < nbr; i++)
11891+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 11892+
4a4d8108
AM
11893+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
11894+ /* smp_mb(); */ /* atomic_set */
11895+ iinfo->ii_bstart = -1;
11896+ iinfo->ii_bend = -1;
11897+ iinfo->ii_vdir = NULL;
11898+ return 0;
1308ab2a 11899+ }
4a4d8108
AM
11900+ return -ENOMEM;
11901+}
1facf9fc 11902+
4a4d8108
AM
11903+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
11904+{
11905+ int err, sz;
11906+ struct au_hinode *hip;
1facf9fc 11907+
4a4d8108
AM
11908+ AuRwMustWriteLock(&iinfo->ii_rwsem);
11909+
11910+ err = -ENOMEM;
11911+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
11912+ if (!sz)
11913+ sz = sizeof(*hip);
11914+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
11915+ if (hip) {
11916+ iinfo->ii_hinode = hip;
11917+ err = 0;
1308ab2a 11918+ }
4a4d8108 11919+
1308ab2a 11920+ return err;
1facf9fc 11921+}
11922+
4a4d8108 11923+void au_iinfo_fin(struct inode *inode)
1facf9fc 11924+{
4a4d8108
AM
11925+ struct au_iinfo *iinfo;
11926+ struct au_hinode *hi;
11927+ struct super_block *sb;
b752ccd1
AM
11928+ aufs_bindex_t bindex, bend;
11929+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 11930+
4a4d8108
AM
11931+ iinfo = au_ii(inode);
11932+ /* bad_inode case */
11933+ if (!iinfo)
11934+ return;
1308ab2a 11935+
b752ccd1 11936+ sb = inode->i_sb;
7f207e10 11937+ au_ninodes_dec(sb);
b752ccd1
AM
11938+ if (si_pid_test(sb))
11939+ au_xino_delete_inode(inode, unlinked);
11940+ else {
11941+ /*
11942+ * it is safe to hide the dependency between sbinfo and
11943+ * sb->s_umount.
11944+ */
11945+ lockdep_off();
11946+ si_noflush_read_lock(sb);
11947+ au_xino_delete_inode(inode, unlinked);
11948+ si_read_unlock(sb);
11949+ lockdep_on();
11950+ }
11951+
4a4d8108
AM
11952+ if (iinfo->ii_vdir)
11953+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 11954+
b752ccd1
AM
11955+ bindex = iinfo->ii_bstart;
11956+ if (bindex >= 0) {
11957+ hi = iinfo->ii_hinode + bindex;
4a4d8108 11958+ bend = iinfo->ii_bend;
b752ccd1
AM
11959+ while (bindex++ <= bend) {
11960+ if (hi->hi_inode)
4a4d8108 11961+ au_hiput(hi);
4a4d8108
AM
11962+ hi++;
11963+ }
11964+ }
4a4d8108
AM
11965+ kfree(iinfo->ii_hinode);
11966+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 11967+}
7f207e10
AM
11968diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
11969--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
11970+++ linux/fs/aufs/inode.c 2010-11-22 11:52:56.987228248 +0100
b752ccd1 11971@@ -0,0 +1,443 @@
4a4d8108
AM
11972+/*
11973+ * Copyright (C) 2005-2010 Junjiro R. Okajima
11974+ *
11975+ * This program, aufs is free software; you can redistribute it and/or modify
11976+ * it under the terms of the GNU General Public License as published by
11977+ * the Free Software Foundation; either version 2 of the License, or
11978+ * (at your option) any later version.
11979+ *
11980+ * This program is distributed in the hope that it will be useful,
11981+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11982+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11983+ * GNU General Public License for more details.
11984+ *
11985+ * You should have received a copy of the GNU General Public License
11986+ * along with this program; if not, write to the Free Software
11987+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11988+ */
1facf9fc 11989+
4a4d8108
AM
11990+/*
11991+ * inode functions
11992+ */
1facf9fc 11993+
4a4d8108 11994+#include "aufs.h"
1308ab2a 11995+
4a4d8108
AM
11996+struct inode *au_igrab(struct inode *inode)
11997+{
11998+ if (inode) {
11999+ AuDebugOn(!atomic_read(&inode->i_count));
e49829fe 12000+ atomic_inc(&inode->i_count);
1facf9fc 12001+ }
4a4d8108
AM
12002+ return inode;
12003+}
1facf9fc 12004+
4a4d8108
AM
12005+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
12006+{
12007+ au_cpup_attr_all(inode, /*force*/0);
12008+ au_update_iigen(inode);
12009+ if (do_version)
12010+ inode->i_version++;
dece6358 12011+}
1facf9fc 12012+
4a4d8108 12013+int au_refresh_hinode_self(struct inode *inode, int do_attr)
dece6358 12014+{
4a4d8108
AM
12015+ int err, e;
12016+ aufs_bindex_t bindex, new_bindex;
12017+ unsigned char update;
12018+ struct au_hinode *p, *q, tmp;
1308ab2a 12019+ struct super_block *sb;
4a4d8108 12020+ struct au_iinfo *iinfo;
1facf9fc 12021+
4a4d8108 12022+ IiMustWriteLock(inode);
1facf9fc 12023+
4a4d8108
AM
12024+ update = 0;
12025+ sb = inode->i_sb;
12026+ iinfo = au_ii(inode);
12027+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
12028+ if (unlikely(err))
1308ab2a 12029+ goto out;
1facf9fc 12030+
4a4d8108
AM
12031+ p = iinfo->ii_hinode + iinfo->ii_bstart;
12032+ err = 0;
12033+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12034+ bindex++, p++) {
12035+ if (!p->hi_inode)
12036+ continue;
1facf9fc 12037+
4a4d8108
AM
12038+ new_bindex = au_br_index(sb, p->hi_id);
12039+ if (new_bindex == bindex)
12040+ continue;
1facf9fc 12041+
4a4d8108
AM
12042+ if (new_bindex < 0) {
12043+ update = 1;
12044+ au_hiput(p);
12045+ p->hi_inode = NULL;
12046+ continue;
1308ab2a 12047+ }
4a4d8108
AM
12048+
12049+ if (new_bindex < iinfo->ii_bstart)
12050+ iinfo->ii_bstart = new_bindex;
12051+ if (iinfo->ii_bend < new_bindex)
12052+ iinfo->ii_bend = new_bindex;
12053+ /* swap two lower inode, and loop again */
12054+ q = iinfo->ii_hinode + new_bindex;
12055+ tmp = *q;
12056+ *q = *p;
12057+ *p = tmp;
12058+ if (tmp.hi_inode) {
12059+ bindex--;
12060+ p--;
1308ab2a 12061+ }
12062+ }
4a4d8108
AM
12063+ au_update_ibrange(inode, /*do_put_zero*/0);
12064+ e = au_dy_irefresh(inode);
12065+ if (unlikely(e && !err))
12066+ err = e;
12067+ if (do_attr)
12068+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
1facf9fc 12069+
4f0767ce 12070+out:
4a4d8108
AM
12071+ return err;
12072+}
1facf9fc 12073+
4a4d8108
AM
12074+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
12075+{
12076+ int err, e;
12077+ unsigned int flags;
12078+ aufs_bindex_t bindex, bend;
12079+ unsigned char isdir, update;
12080+ struct au_hinode *p;
12081+ struct au_iinfo *iinfo;
1facf9fc 12082+
4a4d8108
AM
12083+ err = au_refresh_hinode_self(inode, /*do_attr*/0);
12084+ if (unlikely(err))
12085+ goto out;
12086+
12087+ update = 0;
12088+ iinfo = au_ii(inode);
12089+ p = iinfo->ii_hinode + iinfo->ii_bstart;
12090+ isdir = S_ISDIR(inode->i_mode);
12091+ flags = au_hi_flags(inode, isdir);
12092+ bend = au_dbend(dentry);
12093+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
12094+ struct inode *h_i;
12095+ struct dentry *h_d;
12096+
12097+ h_d = au_h_dptr(dentry, bindex);
12098+ if (!h_d || !h_d->d_inode)
12099+ continue;
12100+
12101+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
12102+ h_i = au_h_iptr(inode, bindex);
12103+ if (h_i) {
12104+ if (h_i == h_d->d_inode)
12105+ continue;
12106+ err = -EIO;
12107+ break;
12108+ }
12109+ }
12110+ if (bindex < iinfo->ii_bstart)
12111+ iinfo->ii_bstart = bindex;
12112+ if (iinfo->ii_bend < bindex)
12113+ iinfo->ii_bend = bindex;
12114+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
12115+ update = 1;
1308ab2a 12116+ }
4a4d8108
AM
12117+ au_update_ibrange(inode, /*do_put_zero*/0);
12118+ e = au_dy_irefresh(inode);
12119+ if (unlikely(e && !err))
12120+ err = e;
12121+ au_refresh_hinode_attr(inode, update && isdir);
12122+
4f0767ce 12123+out:
4a4d8108 12124+ AuTraceErr(err);
1308ab2a 12125+ return err;
dece6358
AM
12126+}
12127+
4a4d8108 12128+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 12129+{
4a4d8108
AM
12130+ int err;
12131+ unsigned int flags;
12132+ umode_t mode;
12133+ aufs_bindex_t bindex, bstart, btail;
12134+ unsigned char isdir;
12135+ struct dentry *h_dentry;
12136+ struct inode *h_inode;
12137+ struct au_iinfo *iinfo;
dece6358 12138+
4a4d8108 12139+ IiMustWriteLock(inode);
dece6358 12140+
4a4d8108
AM
12141+ err = 0;
12142+ isdir = 0;
12143+ bstart = au_dbstart(dentry);
12144+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
12145+ mode = h_inode->i_mode;
12146+ switch (mode & S_IFMT) {
12147+ case S_IFREG:
12148+ btail = au_dbtail(dentry);
12149+ inode->i_op = &aufs_iop;
12150+ inode->i_fop = &aufs_file_fop;
12151+ err = au_dy_iaop(inode, bstart, h_inode);
12152+ if (unlikely(err))
12153+ goto out;
12154+ break;
12155+ case S_IFDIR:
12156+ isdir = 1;
12157+ btail = au_dbtaildir(dentry);
12158+ inode->i_op = &aufs_dir_iop;
12159+ inode->i_fop = &aufs_dir_fop;
12160+ break;
12161+ case S_IFLNK:
12162+ btail = au_dbtail(dentry);
12163+ inode->i_op = &aufs_symlink_iop;
12164+ break;
12165+ case S_IFBLK:
12166+ case S_IFCHR:
12167+ case S_IFIFO:
12168+ case S_IFSOCK:
12169+ btail = au_dbtail(dentry);
12170+ inode->i_op = &aufs_iop;
12171+ au_init_special_fop(inode, mode, h_inode->i_rdev);
12172+ break;
12173+ default:
12174+ AuIOErr("Unknown file type 0%o\n", mode);
12175+ err = -EIO;
1308ab2a 12176+ goto out;
4a4d8108 12177+ }
dece6358 12178+
4a4d8108
AM
12179+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
12180+ flags = au_hi_flags(inode, isdir);
12181+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
12182+ && au_ftest_hi(flags, HNOTIFY)
12183+ && dentry->d_name.len > AUFS_WH_PFX_LEN
12184+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
12185+ au_fclr_hi(flags, HNOTIFY);
12186+ iinfo = au_ii(inode);
12187+ iinfo->ii_bstart = bstart;
12188+ iinfo->ii_bend = btail;
12189+ for (bindex = bstart; bindex <= btail; bindex++) {
12190+ h_dentry = au_h_dptr(dentry, bindex);
12191+ if (h_dentry)
12192+ au_set_h_iptr(inode, bindex,
12193+ au_igrab(h_dentry->d_inode), flags);
12194+ }
12195+ au_cpup_attr_all(inode, /*force*/1);
dece6358 12196+
4f0767ce 12197+out:
4a4d8108
AM
12198+ return err;
12199+}
dece6358 12200+
4a4d8108
AM
12201+/* successful returns with iinfo write_locked */
12202+static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
12203+{
12204+ int err;
12205+ aufs_bindex_t bindex, bend;
12206+ struct inode *h_inode, *h_dinode;
dece6358 12207+
4a4d8108 12208+ *matched = 0;
dece6358 12209+
4a4d8108
AM
12210+ /*
12211+ * before this function, if aufs got any iinfo lock, it must be only
12212+ * one, the parent dir.
12213+ * it can happen by UDBA and the obsoleted inode number.
12214+ */
12215+ err = -EIO;
12216+ if (unlikely(inode->i_ino == parent_ino(dentry)))
12217+ goto out;
12218+
12219+ err = 0;
12220+ ii_write_lock_new_child(inode);
12221+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
12222+ bend = au_ibend(inode);
12223+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12224+ h_inode = au_h_iptr(inode, bindex);
12225+ if (h_inode && h_inode == h_dinode) {
12226+ *matched = 1;
12227+ err = 0;
12228+ if (au_iigen(inode) != au_digen(dentry))
12229+ err = au_refresh_hinode(inode, dentry);
12230+ break;
1308ab2a 12231+ }
1facf9fc 12232+ }
dece6358 12233+
4a4d8108
AM
12234+ if (unlikely(err))
12235+ ii_write_unlock(inode);
4f0767ce 12236+out:
1facf9fc 12237+ return err;
12238+}
1facf9fc 12239+
4a4d8108
AM
12240+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12241+ unsigned int d_type, ino_t *ino)
1facf9fc 12242+{
4a4d8108
AM
12243+ int err;
12244+ struct mutex *mtx;
1facf9fc 12245+
b752ccd1 12246+ /* prevent hardlinked inode number from race condition */
4a4d8108 12247+ mtx = NULL;
b752ccd1 12248+ if (d_type != DT_DIR) {
4a4d8108
AM
12249+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
12250+ mutex_lock(mtx);
12251+ }
12252+ err = au_xino_read(sb, bindex, h_ino, ino);
12253+ if (unlikely(err))
12254+ goto out;
1308ab2a 12255+
4a4d8108
AM
12256+ if (!*ino) {
12257+ err = -EIO;
12258+ *ino = au_xino_new_ino(sb);
12259+ if (unlikely(!*ino))
1facf9fc 12260+ goto out;
4a4d8108
AM
12261+ err = au_xino_write(sb, bindex, h_ino, *ino);
12262+ if (unlikely(err))
1308ab2a 12263+ goto out;
1308ab2a 12264+ }
1facf9fc 12265+
4f0767ce 12266+out:
b752ccd1 12267+ if (mtx)
4a4d8108 12268+ mutex_unlock(mtx);
1facf9fc 12269+ return err;
12270+}
12271+
4a4d8108
AM
12272+/* successful returns with iinfo write_locked */
12273+/* todo: return with unlocked? */
12274+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 12275+{
b752ccd1 12276+ struct inode *inode, *h_inode;
4a4d8108
AM
12277+ struct dentry *h_dentry;
12278+ struct super_block *sb;
b752ccd1 12279+ struct mutex *mtx;
4a4d8108
AM
12280+ ino_t h_ino, ino;
12281+ int err, match;
12282+ aufs_bindex_t bstart;
1facf9fc 12283+
4a4d8108
AM
12284+ sb = dentry->d_sb;
12285+ bstart = au_dbstart(dentry);
12286+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
12287+ h_inode = h_dentry->d_inode;
12288+ h_ino = h_inode->i_ino;
12289+
12290+ /*
12291+ * stop 'race'-ing between hardlinks under different
12292+ * parents.
12293+ */
12294+ mtx = NULL;
12295+ if (!S_ISDIR(h_inode->i_mode))
12296+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
12297+
4f0767ce 12298+new_ino:
b752ccd1
AM
12299+ if (mtx)
12300+ mutex_lock(mtx);
4a4d8108
AM
12301+ err = au_xino_read(sb, bstart, h_ino, &ino);
12302+ inode = ERR_PTR(err);
12303+ if (unlikely(err))
12304+ goto out;
b752ccd1 12305+
4a4d8108
AM
12306+ if (!ino) {
12307+ ino = au_xino_new_ino(sb);
12308+ if (unlikely(!ino)) {
12309+ inode = ERR_PTR(-EIO);
dece6358
AM
12310+ goto out;
12311+ }
12312+ }
1facf9fc 12313+
4a4d8108
AM
12314+ AuDbg("i%lu\n", (unsigned long)ino);
12315+ inode = au_iget_locked(sb, ino);
12316+ err = PTR_ERR(inode);
12317+ if (IS_ERR(inode))
1facf9fc 12318+ goto out;
1facf9fc 12319+
4a4d8108
AM
12320+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
12321+ if (inode->i_state & I_NEW) {
12322+ ii_write_lock_new_child(inode);
12323+ err = set_inode(inode, dentry);
12324+ if (!err) {
12325+ unlock_new_inode(inode);
12326+ goto out; /* success */
12327+ }
1308ab2a 12328+
4a4d8108
AM
12329+ ii_write_unlock(inode);
12330+ iget_failed(inode);
12331+ goto out_err;
12332+ } else if (!must_new) {
b752ccd1
AM
12333+ /*
12334+ * horrible race condition between lookup, readdir and copyup
12335+ * (or something).
12336+ */
12337+ if (mtx)
12338+ mutex_unlock(mtx);
4a4d8108 12339+ err = reval_inode(inode, dentry, &match);
b752ccd1
AM
12340+ if (!err) {
12341+ mtx = NULL;
4a4d8108 12342+ goto out; /* success */
b752ccd1
AM
12343+ } else if (match) {
12344+ mtx = NULL;
4a4d8108 12345+ goto out_iput;
b752ccd1
AM
12346+ } else if (mtx)
12347+ mutex_lock(mtx);
4a4d8108
AM
12348+ }
12349+
12350+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
12351+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
12352+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
12353+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
12354+ (unsigned long)h_ino, (unsigned long)ino);
12355+ ino = 0;
12356+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
12357+ if (!err) {
12358+ iput(inode);
b752ccd1
AM
12359+ if (mtx)
12360+ mutex_unlock(mtx);
4a4d8108
AM
12361+ goto new_ino;
12362+ }
1308ab2a 12363+
4f0767ce 12364+out_iput:
4a4d8108 12365+ iput(inode);
4f0767ce 12366+out_err:
4a4d8108 12367+ inode = ERR_PTR(err);
4f0767ce 12368+out:
b752ccd1
AM
12369+ if (mtx)
12370+ mutex_unlock(mtx);
4a4d8108 12371+ return inode;
1facf9fc 12372+}
12373+
4a4d8108 12374+/* ---------------------------------------------------------------------- */
1facf9fc 12375+
4a4d8108
AM
12376+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12377+ struct inode *inode)
12378+{
12379+ int err;
1facf9fc 12380+
4a4d8108 12381+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 12382+
4a4d8108
AM
12383+ /* pseudo-link after flushed may happen out of bounds */
12384+ if (!err
12385+ && inode
12386+ && au_ibstart(inode) <= bindex
12387+ && bindex <= au_ibend(inode)) {
12388+ /*
12389+ * permission check is unnecessary since vfsub routine
12390+ * will be called later
12391+ */
12392+ struct inode *hi = au_h_iptr(inode, bindex);
12393+ if (hi)
12394+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 12395+ }
12396+
4a4d8108
AM
12397+ return err;
12398+}
dece6358 12399+
4a4d8108
AM
12400+int au_test_h_perm(struct inode *h_inode, int mask)
12401+{
12402+ if (!current_fsuid())
12403+ return 0;
12404+ return inode_permission(h_inode, mask);
12405+}
1facf9fc 12406+
4a4d8108
AM
12407+int au_test_h_perm_sio(struct inode *h_inode, int mask)
12408+{
12409+ if (au_test_nfs(h_inode->i_sb)
12410+ && (mask & MAY_WRITE)
12411+ && S_ISDIR(h_inode->i_mode))
12412+ mask |= MAY_READ; /* force permission check */
12413+ return au_test_h_perm(h_inode, mask);
1facf9fc 12414+}
7f207e10
AM
12415diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
12416--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
12417+++ linux/fs/aufs/inode.h 2010-11-22 11:52:56.987228248 +0100
12418@@ -0,0 +1,518 @@
4a4d8108
AM
12419+/*
12420+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12421+ *
12422+ * This program, aufs is free software; you can redistribute it and/or modify
12423+ * it under the terms of the GNU General Public License as published by
12424+ * the Free Software Foundation; either version 2 of the License, or
12425+ * (at your option) any later version.
12426+ *
12427+ * This program is distributed in the hope that it will be useful,
12428+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12429+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12430+ * GNU General Public License for more details.
12431+ *
12432+ * You should have received a copy of the GNU General Public License
12433+ * along with this program; if not, write to the Free Software
12434+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12435+ */
1facf9fc 12436+
1308ab2a 12437+/*
4a4d8108 12438+ * inode operations
1308ab2a 12439+ */
dece6358 12440+
4a4d8108
AM
12441+#ifndef __AUFS_INODE_H__
12442+#define __AUFS_INODE_H__
dece6358 12443+
4a4d8108 12444+#ifdef __KERNEL__
1308ab2a 12445+
4a4d8108
AM
12446+#include <linux/fs.h>
12447+#include <linux/fsnotify.h>
12448+#include <linux/aufs_type.h>
12449+#include "rwsem.h"
1308ab2a 12450+
4a4d8108 12451+struct vfsmount;
1facf9fc 12452+
4a4d8108
AM
12453+struct au_hnotify {
12454+#ifdef CONFIG_AUFS_HNOTIFY
12455+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 12456+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 12457+ struct fsnotify_mark hn_mark;
7f207e10 12458+ int hn_mark_dead;
4a4d8108 12459+#endif
7f207e10 12460+ struct inode *hn_aufs_inode; /* no get/put */
4a4d8108
AM
12461+#endif
12462+} ____cacheline_aligned_in_smp;
1facf9fc 12463+
4a4d8108
AM
12464+struct au_hinode {
12465+ struct inode *hi_inode;
12466+ aufs_bindex_t hi_id;
12467+#ifdef CONFIG_AUFS_HNOTIFY
12468+ struct au_hnotify *hi_notify;
12469+#endif
dece6358 12470+
4a4d8108
AM
12471+ /* reference to the copied-up whiteout with get/put */
12472+ struct dentry *hi_whdentry;
12473+};
dece6358 12474+
4a4d8108
AM
12475+struct au_vdir;
12476+struct au_iinfo {
12477+ atomic_t ii_generation;
12478+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 12479+
4a4d8108
AM
12480+ struct au_rwsem ii_rwsem;
12481+ aufs_bindex_t ii_bstart, ii_bend;
12482+ __u32 ii_higen;
12483+ struct au_hinode *ii_hinode;
12484+ struct au_vdir *ii_vdir;
12485+};
1facf9fc 12486+
4a4d8108
AM
12487+struct au_icntnr {
12488+ struct au_iinfo iinfo;
12489+ struct inode vfs_inode;
12490+} ____cacheline_aligned_in_smp;
1308ab2a 12491+
4a4d8108
AM
12492+/* au_pin flags */
12493+#define AuPin_DI_LOCKED 1
12494+#define AuPin_MNT_WRITE (1 << 1)
12495+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
12496+#define au_fset_pin(flags, name) \
12497+ do { (flags) |= AuPin_##name; } while (0)
12498+#define au_fclr_pin(flags, name) \
12499+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
12500+
12501+struct au_pin {
12502+ /* input */
12503+ struct dentry *dentry;
12504+ unsigned int udba;
12505+ unsigned char lsc_di, lsc_hi, flags;
12506+ aufs_bindex_t bindex;
12507+
12508+ /* output */
12509+ struct dentry *parent;
12510+ struct au_hinode *hdir;
12511+ struct vfsmount *h_mnt;
12512+};
1facf9fc 12513+
1308ab2a 12514+/* ---------------------------------------------------------------------- */
12515+
4a4d8108 12516+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 12517+{
4a4d8108 12518+ struct au_iinfo *iinfo;
1facf9fc 12519+
4a4d8108
AM
12520+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12521+ if (iinfo->ii_hinode)
12522+ return iinfo;
12523+ return NULL; /* debugging bad_inode case */
12524+}
1facf9fc 12525+
4a4d8108 12526+/* ---------------------------------------------------------------------- */
1facf9fc 12527+
4a4d8108
AM
12528+/* inode.c */
12529+struct inode *au_igrab(struct inode *inode);
12530+int au_refresh_hinode_self(struct inode *inode, int do_attr);
12531+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
12532+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12533+ unsigned int d_type, ino_t *ino);
12534+struct inode *au_new_inode(struct dentry *dentry, int must_new);
12535+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12536+ struct inode *inode);
12537+int au_test_h_perm(struct inode *h_inode, int mask);
12538+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 12539+
4a4d8108
AM
12540+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
12541+ ino_t h_ino, unsigned int d_type, ino_t *ino)
12542+{
12543+#ifdef CONFIG_AUFS_SHWH
12544+ return au_ino(sb, bindex, h_ino, d_type, ino);
12545+#else
12546+ return 0;
12547+#endif
12548+}
1facf9fc 12549+
4a4d8108
AM
12550+/* i_op.c */
12551+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 12552+
4a4d8108
AM
12553+/* au_wr_dir flags */
12554+#define AuWrDir_ADD_ENTRY 1
12555+#define AuWrDir_ISDIR (1 << 1)
12556+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
12557+#define au_fset_wrdir(flags, name) \
12558+ do { (flags) |= AuWrDir_##name; } while (0)
12559+#define au_fclr_wrdir(flags, name) \
12560+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 12561+
4a4d8108
AM
12562+struct au_wr_dir_args {
12563+ aufs_bindex_t force_btgt;
12564+ unsigned char flags;
12565+};
12566+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
12567+ struct au_wr_dir_args *args);
dece6358 12568+
4a4d8108
AM
12569+struct dentry *au_pinned_h_parent(struct au_pin *pin);
12570+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
12571+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
12572+ unsigned int udba, unsigned char flags);
12573+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
12574+ unsigned int udba, unsigned char flags) __must_check;
12575+int au_do_pin(struct au_pin *pin) __must_check;
12576+void au_unpin(struct au_pin *pin);
1facf9fc 12577+
4a4d8108
AM
12578+/* i_op_add.c */
12579+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
12580+ struct dentry *h_parent, int isdir);
12581+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
12582+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
12583+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
12584+ struct nameidata *nd);
12585+int aufs_link(struct dentry *src_dentry, struct inode *dir,
12586+ struct dentry *dentry);
12587+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
1facf9fc 12588+
4a4d8108
AM
12589+/* i_op_del.c */
12590+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
12591+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
12592+ struct dentry *h_parent, int isdir);
12593+int aufs_unlink(struct inode *dir, struct dentry *dentry);
12594+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 12595+
4a4d8108
AM
12596+/* i_op_ren.c */
12597+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
12598+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
12599+ struct inode *dir, struct dentry *dentry);
1facf9fc 12600+
4a4d8108
AM
12601+/* iinfo.c */
12602+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
12603+void au_hiput(struct au_hinode *hinode);
12604+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12605+ struct dentry *h_wh);
12606+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 12607+
4a4d8108
AM
12608+/* hinode flags */
12609+#define AuHi_XINO 1
12610+#define AuHi_HNOTIFY (1 << 1)
12611+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
12612+#define au_fset_hi(flags, name) \
12613+ do { (flags) |= AuHi_##name; } while (0)
12614+#define au_fclr_hi(flags, name) \
12615+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 12616+
4a4d8108
AM
12617+#ifndef CONFIG_AUFS_HNOTIFY
12618+#undef AuHi_HNOTIFY
12619+#define AuHi_HNOTIFY 0
12620+#endif
1facf9fc 12621+
4a4d8108
AM
12622+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12623+ struct inode *h_inode, unsigned int flags);
1facf9fc 12624+
4a4d8108
AM
12625+void au_update_iigen(struct inode *inode);
12626+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 12627+
4a4d8108
AM
12628+void au_icntnr_init_once(void *_c);
12629+int au_iinfo_init(struct inode *inode);
12630+void au_iinfo_fin(struct inode *inode);
12631+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 12632+
e49829fe 12633+#ifdef CONFIG_PROC_FS
4a4d8108 12634+/* plink.c */
e49829fe
JR
12635+int au_plink_maint(struct super_block *sb, int flags);
12636+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
12637+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
12638+#ifdef CONFIG_AUFS_DEBUG
12639+void au_plink_list(struct super_block *sb);
12640+#else
12641+AuStubVoid(au_plink_list, struct super_block *sb)
12642+#endif
12643+int au_plink_test(struct inode *inode);
12644+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
12645+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
12646+ struct dentry *h_dentry);
e49829fe
JR
12647+void au_plink_put(struct super_block *sb, int verbose);
12648+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 12649+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
12650+#else
12651+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
12652+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
12653+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
12654+AuStubVoid(au_plink_list, struct super_block *sb);
12655+AuStubInt0(au_plink_test, struct inode *inode);
12656+AuStub(struct dentry *, au_plink_lkup, return NULL,
12657+ struct inode *inode, aufs_bindex_t bindex);
12658+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
12659+ struct dentry *h_dentry);
12660+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
12661+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
12662+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
12663+#endif /* CONFIG_PROC_FS */
1facf9fc 12664+
4a4d8108 12665+/* ---------------------------------------------------------------------- */
1308ab2a 12666+
4a4d8108
AM
12667+/* lock subclass for iinfo */
12668+enum {
12669+ AuLsc_II_CHILD, /* child first */
12670+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
12671+ AuLsc_II_CHILD3, /* copyup dirs */
12672+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
12673+ AuLsc_II_PARENT2,
12674+ AuLsc_II_PARENT3, /* copyup dirs */
12675+ AuLsc_II_NEW_CHILD
12676+};
1308ab2a 12677+
1facf9fc 12678+/*
4a4d8108
AM
12679+ * ii_read_lock_child, ii_write_lock_child,
12680+ * ii_read_lock_child2, ii_write_lock_child2,
12681+ * ii_read_lock_child3, ii_write_lock_child3,
12682+ * ii_read_lock_parent, ii_write_lock_parent,
12683+ * ii_read_lock_parent2, ii_write_lock_parent2,
12684+ * ii_read_lock_parent3, ii_write_lock_parent3,
12685+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 12686+ */
4a4d8108
AM
12687+#define AuReadLockFunc(name, lsc) \
12688+static inline void ii_read_lock_##name(struct inode *i) \
12689+{ \
12690+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12691+}
12692+
12693+#define AuWriteLockFunc(name, lsc) \
12694+static inline void ii_write_lock_##name(struct inode *i) \
12695+{ \
12696+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12697+}
12698+
12699+#define AuRWLockFuncs(name, lsc) \
12700+ AuReadLockFunc(name, lsc) \
12701+ AuWriteLockFunc(name, lsc)
12702+
12703+AuRWLockFuncs(child, CHILD);
12704+AuRWLockFuncs(child2, CHILD2);
12705+AuRWLockFuncs(child3, CHILD3);
12706+AuRWLockFuncs(parent, PARENT);
12707+AuRWLockFuncs(parent2, PARENT2);
12708+AuRWLockFuncs(parent3, PARENT3);
12709+AuRWLockFuncs(new_child, NEW_CHILD);
12710+
12711+#undef AuReadLockFunc
12712+#undef AuWriteLockFunc
12713+#undef AuRWLockFuncs
1facf9fc 12714+
12715+/*
4a4d8108 12716+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 12717+ */
4a4d8108 12718+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 12719+
4a4d8108
AM
12720+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
12721+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
12722+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 12723+
4a4d8108 12724+/* ---------------------------------------------------------------------- */
1308ab2a 12725+
4a4d8108
AM
12726+static inline unsigned int au_iigen(struct inode *inode)
12727+{
12728+ return atomic_read(&au_ii(inode)->ii_generation);
12729+}
1308ab2a 12730+
4a4d8108
AM
12731+/* tiny test for inode number */
12732+/* tmpfs generation is too rough */
12733+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
12734+{
12735+ struct au_iinfo *iinfo;
1308ab2a 12736+
4a4d8108
AM
12737+ iinfo = au_ii(inode);
12738+ AuRwMustAnyLock(&iinfo->ii_rwsem);
12739+ return !(iinfo->ii_hsb1 == h_inode->i_sb
12740+ && iinfo->ii_higen == h_inode->i_generation);
12741+}
1308ab2a 12742+
4a4d8108
AM
12743+static inline void au_iigen_dec(struct inode *inode)
12744+{
12745+#ifdef CONFIG_AUFS_HNOTIFY
e49829fe 12746+ atomic_dec(&au_ii(inode)->ii_generation);
4a4d8108
AM
12747+#endif
12748+}
1308ab2a 12749+
4a4d8108 12750+/* ---------------------------------------------------------------------- */
1308ab2a 12751+
4a4d8108
AM
12752+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
12753+ aufs_bindex_t bindex)
12754+{
12755+ IiMustAnyLock(inode);
12756+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
12757+}
1308ab2a 12758+
4a4d8108
AM
12759+static inline aufs_bindex_t au_ibstart(struct inode *inode)
12760+{
12761+ IiMustAnyLock(inode);
12762+ return au_ii(inode)->ii_bstart;
12763+}
1308ab2a 12764+
4a4d8108
AM
12765+static inline aufs_bindex_t au_ibend(struct inode *inode)
12766+{
12767+ IiMustAnyLock(inode);
12768+ return au_ii(inode)->ii_bend;
12769+}
1308ab2a 12770+
4a4d8108
AM
12771+static inline struct au_vdir *au_ivdir(struct inode *inode)
12772+{
12773+ IiMustAnyLock(inode);
12774+ return au_ii(inode)->ii_vdir;
12775+}
1308ab2a 12776+
4a4d8108
AM
12777+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
12778+{
12779+ IiMustAnyLock(inode);
12780+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
12781+}
1308ab2a 12782+
4a4d8108 12783+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12784+{
4a4d8108
AM
12785+ IiMustWriteLock(inode);
12786+ au_ii(inode)->ii_bstart = bindex;
12787+}
1308ab2a 12788+
4a4d8108
AM
12789+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
12790+{
12791+ IiMustWriteLock(inode);
12792+ au_ii(inode)->ii_bend = bindex;
1308ab2a 12793+}
12794+
4a4d8108
AM
12795+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
12796+{
12797+ IiMustWriteLock(inode);
12798+ au_ii(inode)->ii_vdir = vdir;
12799+}
1facf9fc 12800+
4a4d8108 12801+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12802+{
4a4d8108
AM
12803+ IiMustAnyLock(inode);
12804+ return au_ii(inode)->ii_hinode + bindex;
12805+}
dece6358 12806+
4a4d8108 12807+/* ---------------------------------------------------------------------- */
1facf9fc 12808+
4a4d8108
AM
12809+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
12810+{
12811+ if (pin)
12812+ return pin->parent;
12813+ return NULL;
1facf9fc 12814+}
12815+
4a4d8108 12816+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 12817+{
4a4d8108
AM
12818+ if (pin && pin->hdir)
12819+ return pin->hdir->hi_inode;
12820+ return NULL;
1308ab2a 12821+}
1facf9fc 12822+
4a4d8108
AM
12823+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
12824+{
12825+ if (pin)
12826+ return pin->hdir;
12827+ return NULL;
12828+}
1facf9fc 12829+
4a4d8108 12830+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 12831+{
4a4d8108
AM
12832+ if (pin)
12833+ pin->dentry = dentry;
12834+}
1308ab2a 12835+
4a4d8108
AM
12836+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
12837+ unsigned char lflag)
12838+{
12839+ if (pin) {
7f207e10 12840+ if (lflag)
4a4d8108 12841+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 12842+ else
4a4d8108 12843+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 12844+ }
4a4d8108
AM
12845+}
12846+
12847+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
12848+{
12849+ if (pin) {
12850+ dput(pin->parent);
12851+ pin->parent = dget(parent);
1facf9fc 12852+ }
4a4d8108 12853+}
1facf9fc 12854+
4a4d8108
AM
12855+/* ---------------------------------------------------------------------- */
12856+
12857+#ifdef CONFIG_AUFS_HNOTIFY
12858+struct au_hnotify_op {
12859+ void (*ctl)(struct au_hinode *hinode, int do_set);
12860+ int (*alloc)(struct au_hnotify *hn, struct inode *h_inode);
12861+ void (*free)(struct au_hnotify *hn);
12862+
12863+ void (*fin)(void);
12864+ int (*init)(void);
12865+};
12866+
12867+/* hnotify.c */
12868+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
12869+ struct inode *h_inode);
12870+void au_hn_free(struct au_hinode *hinode);
12871+void au_hn_ctl(struct au_hinode *hinode, int do_set);
12872+void au_hn_reset(struct inode *inode, unsigned int flags);
12873+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
12874+ struct qstr *h_child_qstr, struct inode *h_child_inode);
12875+int __init au_hnotify_init(void);
12876+void au_hnotify_fin(void);
12877+
7f207e10 12878+/* hfsnotify.c */
4a4d8108
AM
12879+extern const struct au_hnotify_op au_hnotify_op;
12880+
12881+static inline
12882+void au_hn_init(struct au_hinode *hinode)
12883+{
12884+ hinode->hi_notify = NULL;
1308ab2a 12885+}
12886+
4a4d8108
AM
12887+#else
12888+static inline
12889+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
12890+ struct inode *inode __maybe_unused,
12891+ struct inode *h_inode __maybe_unused)
1308ab2a 12892+{
4a4d8108
AM
12893+ return -EOPNOTSUPP;
12894+}
1308ab2a 12895+
4a4d8108
AM
12896+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
12897+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
12898+ int do_set __maybe_unused)
12899+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
12900+ unsigned int flags __maybe_unused)
12901+AuStubInt0(__init au_hnotify_init, void)
12902+AuStubVoid(au_hnotify_fin, void)
12903+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
12904+#endif /* CONFIG_AUFS_HNOTIFY */
12905+
12906+static inline void au_hn_suspend(struct au_hinode *hdir)
12907+{
12908+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 12909+}
12910+
4a4d8108 12911+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 12912+{
4a4d8108
AM
12913+ au_hn_ctl(hdir, /*do_set*/1);
12914+}
1308ab2a 12915+
4a4d8108
AM
12916+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
12917+{
12918+ mutex_lock(&hdir->hi_inode->i_mutex);
12919+ au_hn_suspend(hdir);
12920+}
dece6358 12921+
4a4d8108
AM
12922+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
12923+ unsigned int sc __maybe_unused)
12924+{
12925+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
12926+ au_hn_suspend(hdir);
1facf9fc 12927+}
1facf9fc 12928+
4a4d8108
AM
12929+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
12930+{
12931+ au_hn_resume(hdir);
12932+ mutex_unlock(&hdir->hi_inode->i_mutex);
12933+}
12934+
12935+#endif /* __KERNEL__ */
12936+#endif /* __AUFS_INODE_H__ */
7f207e10
AM
12937diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
12938--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
12939+++ linux/fs/aufs/ioctl.c 2010-11-22 11:52:56.987228248 +0100
e49829fe 12940@@ -0,0 +1,150 @@
4a4d8108
AM
12941+/*
12942+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12943+ *
12944+ * This program, aufs is free software; you can redistribute it and/or modify
12945+ * it under the terms of the GNU General Public License as published by
12946+ * the Free Software Foundation; either version 2 of the License, or
12947+ * (at your option) any later version.
12948+ *
12949+ * This program is distributed in the hope that it will be useful,
12950+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12951+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12952+ * GNU General Public License for more details.
12953+ *
12954+ * You should have received a copy of the GNU General Public License
12955+ * along with this program; if not, write to the Free Software
12956+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12957+ */
12958+
12959+/*
12960+ * ioctl
12961+ * plink-management and readdir in userspace.
12962+ * assist the pathconf(3) wrapper library.
12963+ */
12964+
12965+#include <linux/file.h>
12966+#include "aufs.h"
12967+
12968+static int au_wbr_fd(struct path *path)
12969+{
12970+ int err, fd;
12971+ aufs_bindex_t wbi, bindex, bend;
12972+ struct file *h_file;
12973+ struct super_block *sb;
12974+ struct dentry *root;
12975+ struct au_branch *wbr;
12976+
12977+ err = get_unused_fd();
12978+ if (unlikely(err < 0))
12979+ goto out;
12980+ fd = err;
12981+
12982+ wbi = 0;
12983+ sb = path->dentry->d_sb;
12984+ root = sb->s_root;
12985+ aufs_read_lock(root, AuLock_IR);
12986+ wbr = au_sbr(sb, wbi);
12987+ if (!(path->mnt->mnt_flags & MNT_READONLY)
12988+ && !au_br_writable(wbr->br_perm)) {
12989+ bend = au_sbend(sb);
12990+ for (bindex = 1; bindex <= bend; bindex++) {
12991+ wbr = au_sbr(sb, bindex);
12992+ if (au_br_writable(wbr->br_perm)) {
12993+ wbi = bindex;
12994+ break;
12995+ }
12996+ }
12997+ wbr = au_sbr(sb, wbi);
12998+ }
12999+ AuDbg("wbi %d\n", wbi);
13000+ h_file = au_h_open(root, wbi, O_RDONLY | O_DIRECTORY | O_LARGEFILE,
13001+ NULL);
13002+ aufs_read_unlock(root, AuLock_IR);
13003+ err = PTR_ERR(h_file);
13004+ if (IS_ERR(h_file))
13005+ goto out_fd;
13006+
13007+ atomic_dec(&wbr->br_count); /* cf. au_h_open() */
13008+ fd_install(fd, h_file);
13009+ err = fd;
13010+ goto out; /* success */
13011+
4f0767ce 13012+out_fd:
4a4d8108 13013+ put_unused_fd(fd);
4f0767ce 13014+out:
4a4d8108
AM
13015+ return err;
13016+}
13017+
13018+/* ---------------------------------------------------------------------- */
13019+
13020+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
13021+{
13022+ long err;
13023+
13024+ switch (cmd) {
4a4d8108
AM
13025+ case AUFS_CTL_RDU:
13026+ case AUFS_CTL_RDU_INO:
13027+ err = au_rdu_ioctl(file, cmd, arg);
13028+ break;
13029+
13030+ case AUFS_CTL_WBR_FD:
13031+ err = au_wbr_fd(&file->f_path);
13032+ break;
13033+
13034+ default:
13035+ /* do not call the lower */
13036+ AuDbg("0x%x\n", cmd);
13037+ err = -ENOTTY;
13038+ }
13039+
13040+ AuTraceErr(err);
13041+ return err;
13042+}
13043+
13044+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
13045+{
13046+ long err;
13047+
13048+ switch (cmd) {
13049+ case AUFS_CTL_WBR_FD:
13050+ err = au_wbr_fd(&file->f_path);
13051+ break;
13052+
13053+ default:
13054+ /* do not call the lower */
13055+ AuDbg("0x%x\n", cmd);
13056+ err = -ENOTTY;
13057+ }
13058+
13059+ AuTraceErr(err);
13060+ return err;
13061+}
b752ccd1
AM
13062+
13063+#ifdef CONFIG_COMPAT
13064+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
13065+ unsigned long arg)
13066+{
13067+ long err;
13068+
13069+ switch (cmd) {
13070+ case AUFS_CTL_RDU:
13071+ case AUFS_CTL_RDU_INO:
13072+ err = au_rdu_compat_ioctl(file, cmd, arg);
13073+ break;
13074+
13075+ default:
13076+ err = aufs_ioctl_dir(file, cmd, arg);
13077+ }
13078+
13079+ AuTraceErr(err);
13080+ return err;
13081+}
13082+
13083+#if 0 /* unused yet */
13084+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
13085+ unsigned long arg)
13086+{
13087+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
13088+}
13089+#endif
13090+#endif
7f207e10
AM
13091diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
13092--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
13093+++ linux/fs/aufs/i_op_add.c 2010-11-22 11:52:56.987228248 +0100
e49829fe 13094@@ -0,0 +1,676 @@
4a4d8108
AM
13095+/*
13096+ * Copyright (C) 2005-2010 Junjiro R. Okajima
13097+ *
13098+ * This program, aufs is free software; you can redistribute it and/or modify
13099+ * it under the terms of the GNU General Public License as published by
13100+ * the Free Software Foundation; either version 2 of the License, or
13101+ * (at your option) any later version.
13102+ *
13103+ * This program is distributed in the hope that it will be useful,
13104+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13105+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13106+ * GNU General Public License for more details.
13107+ *
13108+ * You should have received a copy of the GNU General Public License
13109+ * along with this program; if not, write to the Free Software
13110+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13111+ */
13112+
13113+/*
13114+ * inode operations (add entry)
13115+ */
13116+
13117+#include "aufs.h"
13118+
13119+/*
13120+ * final procedure of adding a new entry, except link(2).
13121+ * remove whiteout, instantiate, copyup the parent dir's times and size
13122+ * and update version.
13123+ * if it failed, re-create the removed whiteout.
13124+ */
13125+static int epilog(struct inode *dir, aufs_bindex_t bindex,
13126+ struct dentry *wh_dentry, struct dentry *dentry)
13127+{
13128+ int err, rerr;
13129+ aufs_bindex_t bwh;
13130+ struct path h_path;
13131+ struct inode *inode, *h_dir;
13132+ struct dentry *wh;
13133+
13134+ bwh = -1;
13135+ if (wh_dentry) {
13136+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
13137+ IMustLock(h_dir);
13138+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
13139+ bwh = au_dbwh(dentry);
13140+ h_path.dentry = wh_dentry;
13141+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
13142+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
13143+ dentry);
13144+ if (unlikely(err))
13145+ goto out;
13146+ }
13147+
13148+ inode = au_new_inode(dentry, /*must_new*/1);
13149+ if (!IS_ERR(inode)) {
13150+ d_instantiate(dentry, inode);
13151+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
13152+ IMustLock(dir);
13153+ if (au_ibstart(dir) == au_dbstart(dentry))
13154+ au_cpup_attr_timesizes(dir);
13155+ dir->i_version++;
13156+ return 0; /* success */
13157+ }
13158+
13159+ err = PTR_ERR(inode);
13160+ if (!wh_dentry)
13161+ goto out;
13162+
13163+ /* revert */
13164+ /* dir inode is locked */
13165+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
13166+ rerr = PTR_ERR(wh);
13167+ if (IS_ERR(wh)) {
13168+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
13169+ AuDLNPair(dentry), err, rerr);
13170+ err = -EIO;
13171+ } else
13172+ dput(wh);
13173+
4f0767ce 13174+out:
4a4d8108
AM
13175+ return err;
13176+}
13177+
13178+/*
13179+ * simple tests for the adding inode operations.
13180+ * following the checks in vfs, plus the parent-child relationship.
13181+ */
13182+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13183+ struct dentry *h_parent, int isdir)
13184+{
13185+ int err;
13186+ umode_t h_mode;
13187+ struct dentry *h_dentry;
13188+ struct inode *h_inode;
13189+
13190+ err = -ENAMETOOLONG;
13191+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13192+ goto out;
13193+
13194+ h_dentry = au_h_dptr(dentry, bindex);
13195+ h_inode = h_dentry->d_inode;
13196+ if (!dentry->d_inode) {
13197+ err = -EEXIST;
13198+ if (unlikely(h_inode))
13199+ goto out;
13200+ } else {
13201+ /* rename(2) case */
13202+ err = -EIO;
13203+ if (unlikely(!h_inode || !h_inode->i_nlink))
13204+ goto out;
13205+
13206+ h_mode = h_inode->i_mode;
13207+ if (!isdir) {
13208+ err = -EISDIR;
13209+ if (unlikely(S_ISDIR(h_mode)))
13210+ goto out;
13211+ } else if (unlikely(!S_ISDIR(h_mode))) {
13212+ err = -ENOTDIR;
13213+ goto out;
13214+ }
13215+ }
13216+
13217+ err = 0;
13218+ /* expected parent dir is locked */
13219+ if (unlikely(h_parent != h_dentry->d_parent))
13220+ err = -EIO;
13221+
4f0767ce 13222+out:
4a4d8108
AM
13223+ AuTraceErr(err);
13224+ return err;
13225+}
13226+
13227+/*
13228+ * initial procedure of adding a new entry.
13229+ * prepare writable branch and the parent dir, lock it,
13230+ * and lookup whiteout for the new entry.
13231+ */
13232+static struct dentry*
13233+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
13234+ struct dentry *src_dentry, struct au_pin *pin,
13235+ struct au_wr_dir_args *wr_dir_args)
13236+{
13237+ struct dentry *wh_dentry, *h_parent;
13238+ struct super_block *sb;
13239+ struct au_branch *br;
13240+ int err;
13241+ unsigned int udba;
13242+ aufs_bindex_t bcpup;
13243+
13244+ AuDbg("%.*s\n", AuDLNPair(dentry));
13245+
13246+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
13247+ bcpup = err;
13248+ wh_dentry = ERR_PTR(err);
13249+ if (unlikely(err < 0))
13250+ goto out;
13251+
13252+ sb = dentry->d_sb;
13253+ udba = au_opt_udba(sb);
13254+ err = au_pin(pin, dentry, bcpup, udba,
13255+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13256+ wh_dentry = ERR_PTR(err);
13257+ if (unlikely(err))
13258+ goto out;
13259+
13260+ h_parent = au_pinned_h_parent(pin);
13261+ if (udba != AuOpt_UDBA_NONE
13262+ && au_dbstart(dentry) == bcpup)
13263+ err = au_may_add(dentry, bcpup, h_parent,
13264+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
13265+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13266+ err = -ENAMETOOLONG;
13267+ wh_dentry = ERR_PTR(err);
13268+ if (unlikely(err))
13269+ goto out_unpin;
13270+
13271+ br = au_sbr(sb, bcpup);
13272+ if (dt) {
13273+ struct path tmp = {
13274+ .dentry = h_parent,
13275+ .mnt = br->br_mnt
13276+ };
13277+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
13278+ }
13279+
13280+ wh_dentry = NULL;
13281+ if (bcpup != au_dbwh(dentry))
13282+ goto out; /* success */
13283+
13284+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
13285+
4f0767ce 13286+out_unpin:
4a4d8108
AM
13287+ if (IS_ERR(wh_dentry))
13288+ au_unpin(pin);
4f0767ce 13289+out:
4a4d8108
AM
13290+ return wh_dentry;
13291+}
13292+
13293+/* ---------------------------------------------------------------------- */
13294+
13295+enum { Mknod, Symlink, Creat };
13296+struct simple_arg {
13297+ int type;
13298+ union {
13299+ struct {
13300+ int mode;
13301+ struct nameidata *nd;
13302+ } c;
13303+ struct {
13304+ const char *symname;
13305+ } s;
13306+ struct {
13307+ int mode;
13308+ dev_t dev;
13309+ } m;
13310+ } u;
13311+};
13312+
13313+static int add_simple(struct inode *dir, struct dentry *dentry,
13314+ struct simple_arg *arg)
13315+{
13316+ int err;
13317+ aufs_bindex_t bstart;
13318+ unsigned char created;
13319+ struct au_dtime dt;
13320+ struct au_pin pin;
13321+ struct path h_path;
13322+ struct dentry *wh_dentry, *parent;
13323+ struct inode *h_dir;
13324+ struct au_wr_dir_args wr_dir_args = {
13325+ .force_btgt = -1,
13326+ .flags = AuWrDir_ADD_ENTRY
13327+ };
13328+
13329+ AuDbg("%.*s\n", AuDLNPair(dentry));
13330+ IMustLock(dir);
13331+
13332+ parent = dentry->d_parent; /* dir inode is locked */
13333+ aufs_read_lock(dentry, AuLock_DW);
13334+ di_write_lock_parent(parent);
13335+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
13336+ &wr_dir_args);
13337+ err = PTR_ERR(wh_dentry);
13338+ if (IS_ERR(wh_dentry))
13339+ goto out;
13340+
13341+ bstart = au_dbstart(dentry);
13342+ h_path.dentry = au_h_dptr(dentry, bstart);
13343+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
13344+ h_dir = au_pinned_h_dir(&pin);
13345+ switch (arg->type) {
13346+ case Creat:
13347+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
13348+ break;
13349+ case Symlink:
13350+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
13351+ break;
13352+ case Mknod:
13353+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
13354+ break;
13355+ default:
13356+ BUG();
13357+ }
13358+ created = !err;
13359+ if (!err)
13360+ err = epilog(dir, bstart, wh_dentry, dentry);
13361+
13362+ /* revert */
13363+ if (unlikely(created && err && h_path.dentry->d_inode)) {
13364+ int rerr;
13365+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
13366+ if (rerr) {
13367+ AuIOErr("%.*s revert failure(%d, %d)\n",
13368+ AuDLNPair(dentry), err, rerr);
13369+ err = -EIO;
13370+ }
13371+ au_dtime_revert(&dt);
13372+ d_drop(dentry);
13373+ }
13374+
13375+ au_unpin(&pin);
13376+ dput(wh_dentry);
13377+
4f0767ce 13378+out:
4a4d8108
AM
13379+ if (unlikely(err)) {
13380+ au_update_dbstart(dentry);
13381+ d_drop(dentry);
13382+ }
13383+ di_write_unlock(parent);
13384+ aufs_read_unlock(dentry, AuLock_DW);
13385+ return err;
13386+}
13387+
13388+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
13389+{
13390+ struct simple_arg arg = {
13391+ .type = Mknod,
13392+ .u.m = {
13393+ .mode = mode,
13394+ .dev = dev
13395+ }
13396+ };
13397+ return add_simple(dir, dentry, &arg);
13398+}
13399+
13400+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
13401+{
13402+ struct simple_arg arg = {
13403+ .type = Symlink,
13404+ .u.s.symname = symname
13405+ };
13406+ return add_simple(dir, dentry, &arg);
13407+}
13408+
13409+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13410+ struct nameidata *nd)
13411+{
13412+ struct simple_arg arg = {
13413+ .type = Creat,
13414+ .u.c = {
13415+ .mode = mode,
13416+ .nd = nd
13417+ }
13418+ };
13419+ return add_simple(dir, dentry, &arg);
13420+}
13421+
13422+/* ---------------------------------------------------------------------- */
13423+
13424+struct au_link_args {
13425+ aufs_bindex_t bdst, bsrc;
13426+ struct au_pin pin;
13427+ struct path h_path;
13428+ struct dentry *src_parent, *parent;
13429+};
13430+
13431+static int au_cpup_before_link(struct dentry *src_dentry,
13432+ struct au_link_args *a)
13433+{
13434+ int err;
13435+ struct dentry *h_src_dentry;
13436+ struct mutex *h_mtx;
13437+ struct file *h_file;
13438+
13439+ di_read_lock_parent(a->src_parent, AuLock_IR);
13440+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
13441+ if (unlikely(err))
13442+ goto out;
13443+
13444+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
13445+ h_mtx = &h_src_dentry->d_inode->i_mutex;
13446+ err = au_pin(&a->pin, src_dentry, a->bdst,
13447+ au_opt_udba(src_dentry->d_sb),
13448+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13449+ if (unlikely(err))
13450+ goto out;
13451+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13452+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13453+ if (IS_ERR(h_file)) {
13454+ err = PTR_ERR(h_file);
13455+ h_file = NULL;
13456+ } else
13457+ err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
13458+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
13459+ mutex_unlock(h_mtx);
13460+ au_h_open_post(src_dentry, a->bsrc, h_file);
13461+ au_unpin(&a->pin);
13462+
4f0767ce 13463+out:
4a4d8108
AM
13464+ di_read_unlock(a->src_parent, AuLock_IR);
13465+ return err;
13466+}
13467+
13468+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
13469+{
13470+ int err;
13471+ unsigned char plink;
13472+ struct inode *h_inode, *inode;
13473+ struct dentry *h_src_dentry;
13474+ struct super_block *sb;
13475+ struct file *h_file;
13476+
13477+ plink = 0;
13478+ h_inode = NULL;
13479+ sb = src_dentry->d_sb;
13480+ inode = src_dentry->d_inode;
13481+ if (au_ibstart(inode) <= a->bdst)
13482+ h_inode = au_h_iptr(inode, a->bdst);
13483+ if (!h_inode || !h_inode->i_nlink) {
13484+ /* copyup src_dentry as the name of dentry. */
13485+ au_set_dbstart(src_dentry, a->bdst);
13486+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
13487+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
13488+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
13489+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13490+ if (IS_ERR(h_file)) {
13491+ err = PTR_ERR(h_file);
13492+ h_file = NULL;
13493+ } else
13494+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
13495+ -1, AuCpup_KEEPLINO,
13496+ a->parent);
13497+ mutex_unlock(&h_inode->i_mutex);
13498+ au_h_open_post(src_dentry, a->bsrc, h_file);
13499+ au_set_h_dptr(src_dentry, a->bdst, NULL);
13500+ au_set_dbstart(src_dentry, a->bsrc);
13501+ } else {
13502+ /* the inode of src_dentry already exists on a.bdst branch */
13503+ h_src_dentry = d_find_alias(h_inode);
13504+ if (!h_src_dentry && au_plink_test(inode)) {
13505+ plink = 1;
13506+ h_src_dentry = au_plink_lkup(inode, a->bdst);
13507+ err = PTR_ERR(h_src_dentry);
13508+ if (IS_ERR(h_src_dentry))
13509+ goto out;
13510+
13511+ if (unlikely(!h_src_dentry->d_inode)) {
13512+ dput(h_src_dentry);
13513+ h_src_dentry = NULL;
13514+ }
13515+
13516+ }
13517+ if (h_src_dentry) {
13518+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13519+ &a->h_path);
13520+ dput(h_src_dentry);
13521+ } else {
13522+ AuIOErr("no dentry found for hi%lu on b%d\n",
13523+ h_inode->i_ino, a->bdst);
13524+ err = -EIO;
13525+ }
13526+ }
13527+
13528+ if (!err && !plink)
13529+ au_plink_append(inode, a->bdst, a->h_path.dentry);
13530+
13531+out:
13532+ return err;
13533+}
13534+
13535+int aufs_link(struct dentry *src_dentry, struct inode *dir,
13536+ struct dentry *dentry)
13537+{
13538+ int err, rerr;
13539+ struct au_dtime dt;
13540+ struct au_link_args *a;
13541+ struct dentry *wh_dentry, *h_src_dentry;
13542+ struct inode *inode;
13543+ struct super_block *sb;
13544+ struct au_wr_dir_args wr_dir_args = {
13545+ /* .force_btgt = -1, */
13546+ .flags = AuWrDir_ADD_ENTRY
13547+ };
13548+
13549+ IMustLock(dir);
13550+ inode = src_dentry->d_inode;
13551+ IMustLock(inode);
13552+
13553+ err = -ENOENT;
13554+ if (unlikely(!inode->i_nlink))
13555+ goto out;
13556+
13557+ err = -ENOMEM;
13558+ a = kzalloc(sizeof(*a), GFP_NOFS);
13559+ if (unlikely(!a))
13560+ goto out;
13561+
13562+ a->parent = dentry->d_parent; /* dir inode is locked */
e49829fe
JR
13563+ err = aufs_read_and_write_lock2(dentry, src_dentry, AuLock_NOPLM);
13564+ if (unlikely(err))
13565+ goto out_kfree;
13566+
4a4d8108
AM
13567+ a->src_parent = dget_parent(src_dentry);
13568+ wr_dir_args.force_btgt = au_dbstart(src_dentry);
13569+
13570+ di_write_lock_parent(a->parent);
13571+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
13572+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
13573+ &wr_dir_args);
13574+ err = PTR_ERR(wh_dentry);
13575+ if (IS_ERR(wh_dentry))
13576+ goto out_unlock;
13577+
13578+ err = 0;
13579+ sb = dentry->d_sb;
13580+ a->bdst = au_dbstart(dentry);
13581+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
13582+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
13583+ a->bsrc = au_dbstart(src_dentry);
13584+ if (au_opt_test(au_mntflags(sb), PLINK)) {
13585+ if (a->bdst < a->bsrc
13586+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
13587+ err = au_cpup_or_link(src_dentry, a);
13588+ else {
13589+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13590+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13591+ &a->h_path);
13592+ }
13593+ } else {
13594+ /*
13595+ * copyup src_dentry to the branch we process,
13596+ * and then link(2) to it.
13597+ */
13598+ if (a->bdst < a->bsrc
13599+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
13600+ au_unpin(&a->pin);
13601+ di_write_unlock(a->parent);
13602+ err = au_cpup_before_link(src_dentry, a);
13603+ di_write_lock_parent(a->parent);
13604+ if (!err)
13605+ err = au_pin(&a->pin, dentry, a->bdst,
13606+ au_opt_udba(sb),
13607+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13608+ if (unlikely(err))
13609+ goto out_wh;
13610+ }
13611+ if (!err) {
13612+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13613+ err = -ENOENT;
13614+ if (h_src_dentry && h_src_dentry->d_inode)
13615+ err = vfsub_link(h_src_dentry,
13616+ au_pinned_h_dir(&a->pin),
13617+ &a->h_path);
13618+ }
13619+ }
13620+ if (unlikely(err))
13621+ goto out_unpin;
13622+
13623+ if (wh_dentry) {
13624+ a->h_path.dentry = wh_dentry;
13625+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
13626+ dentry);
13627+ if (unlikely(err))
13628+ goto out_revert;
13629+ }
13630+
13631+ dir->i_version++;
13632+ if (au_ibstart(dir) == au_dbstart(dentry))
13633+ au_cpup_attr_timesizes(dir);
13634+ inc_nlink(inode);
13635+ inode->i_ctime = dir->i_ctime;
13636+ if (!d_unhashed(a->h_path.dentry))
13637+ d_instantiate(dentry, au_igrab(inode));
13638+ else
13639+ /* some filesystem calls d_drop() */
13640+ d_drop(dentry);
13641+ goto out_unpin; /* success */
13642+
4f0767ce 13643+out_revert:
4a4d8108
AM
13644+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
13645+ if (!rerr)
13646+ goto out_dt;
13647+ AuIOErr("%.*s reverting failed(%d, %d)\n",
13648+ AuDLNPair(dentry), err, rerr);
13649+ err = -EIO;
4f0767ce 13650+out_dt:
4a4d8108
AM
13651+ d_drop(dentry);
13652+ au_dtime_revert(&dt);
4f0767ce 13653+out_unpin:
4a4d8108 13654+ au_unpin(&a->pin);
4f0767ce 13655+out_wh:
4a4d8108 13656+ dput(wh_dentry);
4f0767ce 13657+out_unlock:
4a4d8108
AM
13658+ if (unlikely(err)) {
13659+ au_update_dbstart(dentry);
13660+ d_drop(dentry);
13661+ }
13662+ di_write_unlock(a->parent);
13663+ dput(a->src_parent);
13664+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 13665+out_kfree:
4a4d8108 13666+ kfree(a);
4f0767ce 13667+out:
4a4d8108
AM
13668+ return err;
13669+}
13670+
13671+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
13672+{
13673+ int err, rerr;
13674+ aufs_bindex_t bindex;
13675+ unsigned char diropq;
13676+ struct path h_path;
13677+ struct dentry *wh_dentry, *parent, *opq_dentry;
13678+ struct mutex *h_mtx;
13679+ struct super_block *sb;
13680+ struct {
13681+ struct au_pin pin;
13682+ struct au_dtime dt;
13683+ } *a; /* reduce the stack usage */
13684+ struct au_wr_dir_args wr_dir_args = {
13685+ .force_btgt = -1,
13686+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
13687+ };
13688+
13689+ IMustLock(dir);
13690+
13691+ err = -ENOMEM;
13692+ a = kmalloc(sizeof(*a), GFP_NOFS);
13693+ if (unlikely(!a))
13694+ goto out;
13695+
13696+ aufs_read_lock(dentry, AuLock_DW);
13697+ parent = dentry->d_parent; /* dir inode is locked */
13698+ di_write_lock_parent(parent);
13699+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
13700+ &a->pin, &wr_dir_args);
13701+ err = PTR_ERR(wh_dentry);
13702+ if (IS_ERR(wh_dentry))
13703+ goto out_free;
13704+
13705+ sb = dentry->d_sb;
13706+ bindex = au_dbstart(dentry);
13707+ h_path.dentry = au_h_dptr(dentry, bindex);
13708+ h_path.mnt = au_sbr_mnt(sb, bindex);
13709+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
13710+ if (unlikely(err))
13711+ goto out_unlock;
13712+
13713+ /* make the dir opaque */
13714+ diropq = 0;
13715+ h_mtx = &h_path.dentry->d_inode->i_mutex;
13716+ if (wh_dentry
13717+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
13718+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13719+ opq_dentry = au_diropq_create(dentry, bindex);
13720+ mutex_unlock(h_mtx);
13721+ err = PTR_ERR(opq_dentry);
13722+ if (IS_ERR(opq_dentry))
13723+ goto out_dir;
13724+ dput(opq_dentry);
13725+ diropq = 1;
13726+ }
13727+
13728+ err = epilog(dir, bindex, wh_dentry, dentry);
13729+ if (!err) {
13730+ inc_nlink(dir);
13731+ goto out_unlock; /* success */
13732+ }
13733+
13734+ /* revert */
13735+ if (diropq) {
13736+ AuLabel(revert opq);
13737+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13738+ rerr = au_diropq_remove(dentry, bindex);
13739+ mutex_unlock(h_mtx);
13740+ if (rerr) {
13741+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
13742+ AuDLNPair(dentry), err, rerr);
13743+ err = -EIO;
13744+ }
13745+ }
13746+
4f0767ce 13747+out_dir:
4a4d8108
AM
13748+ AuLabel(revert dir);
13749+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
13750+ if (rerr) {
13751+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
13752+ AuDLNPair(dentry), err, rerr);
13753+ err = -EIO;
13754+ }
13755+ d_drop(dentry);
13756+ au_dtime_revert(&a->dt);
4f0767ce 13757+out_unlock:
4a4d8108
AM
13758+ au_unpin(&a->pin);
13759+ dput(wh_dentry);
4f0767ce 13760+out_free:
4a4d8108
AM
13761+ if (unlikely(err)) {
13762+ au_update_dbstart(dentry);
13763+ d_drop(dentry);
13764+ }
13765+ di_write_unlock(parent);
13766+ aufs_read_unlock(dentry, AuLock_DW);
13767+ kfree(a);
4f0767ce 13768+out:
4a4d8108
AM
13769+ return err;
13770+}
7f207e10
AM
13771diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
13772--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
13773+++ linux/fs/aufs/i_op.c 2010-11-22 11:52:56.987228248 +0100
13774@@ -0,0 +1,931 @@
4a4d8108
AM
13775+/*
13776+ * Copyright (C) 2005-2010 Junjiro R. Okajima
13777+ *
13778+ * This program, aufs is free software; you can redistribute it and/or modify
13779+ * it under the terms of the GNU General Public License as published by
13780+ * the Free Software Foundation; either version 2 of the License, or
13781+ * (at your option) any later version.
13782+ *
13783+ * This program is distributed in the hope that it will be useful,
13784+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13785+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13786+ * GNU General Public License for more details.
13787+ *
13788+ * You should have received a copy of the GNU General Public License
13789+ * along with this program; if not, write to the Free Software
13790+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13791+ */
1facf9fc 13792+
1308ab2a 13793+/*
4a4d8108 13794+ * inode operations (except add/del/rename)
1308ab2a 13795+ */
4a4d8108
AM
13796+
13797+#include <linux/device_cgroup.h>
13798+#include <linux/fs_stack.h>
13799+#include <linux/mm.h>
13800+#include <linux/namei.h>
13801+#include <linux/security.h>
13802+#include <linux/uaccess.h>
13803+#include "aufs.h"
13804+
13805+static int h_permission(struct inode *h_inode, int mask,
13806+ struct vfsmount *h_mnt, int brperm)
1facf9fc 13807+{
1308ab2a 13808+ int err;
4a4d8108 13809+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 13810+
4a4d8108
AM
13811+ err = -EACCES;
13812+ if ((write_mask && IS_IMMUTABLE(h_inode))
13813+ || ((mask & MAY_EXEC)
13814+ && S_ISREG(h_inode->i_mode)
13815+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
13816+ || !(h_inode->i_mode & S_IXUGO))))
13817+ goto out;
13818+
13819+ /*
13820+ * - skip the lower fs test in the case of write to ro branch.
13821+ * - nfs dir permission write check is optimized, but a policy for
13822+ * link/rename requires a real check.
13823+ */
13824+ if ((write_mask && !au_br_writable(brperm))
13825+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
13826+ && write_mask && !(mask & MAY_READ))
13827+ || !h_inode->i_op->permission) {
13828+ /* AuLabel(generic_permission); */
13829+ err = generic_permission(h_inode, mask,
13830+ h_inode->i_op->check_acl);
1308ab2a 13831+ } else {
4a4d8108
AM
13832+ /* AuLabel(h_inode->permission); */
13833+ err = h_inode->i_op->permission(h_inode, mask);
13834+ AuTraceErr(err);
13835+ }
1facf9fc 13836+
4a4d8108
AM
13837+ if (!err)
13838+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 13839+ if (!err)
4a4d8108 13840+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
13841+
13842+#if 0
13843+ if (!err) {
13844+ /* todo: do we need to call ima_path_check()? */
13845+ struct path h_path = {
13846+ .dentry =
13847+ .mnt = h_mnt
13848+ };
13849+ err = ima_path_check(&h_path,
13850+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
13851+ IMA_COUNT_LEAVE);
1308ab2a 13852+ }
4a4d8108 13853+#endif
dece6358 13854+
4f0767ce 13855+out:
1308ab2a 13856+ return err;
13857+}
dece6358 13858+
4a4d8108 13859+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 13860+{
13861+ int err;
4a4d8108
AM
13862+ aufs_bindex_t bindex, bend;
13863+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
13864+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
13865+ struct inode *h_inode;
13866+ struct super_block *sb;
13867+ struct au_branch *br;
1facf9fc 13868+
4a4d8108
AM
13869+ sb = inode->i_sb;
13870+ si_read_lock(sb, AuLock_FLUSH);
13871+ ii_read_lock_child(inode);
dece6358 13872+
4a4d8108
AM
13873+ if (!isdir || write_mask) {
13874+ err = au_busy_or_stale();
13875+ h_inode = au_h_iptr(inode, au_ibstart(inode));
13876+ if (unlikely(!h_inode
13877+ || (h_inode->i_mode & S_IFMT)
13878+ != (inode->i_mode & S_IFMT)))
13879+ goto out;
1facf9fc 13880+
4a4d8108
AM
13881+ err = 0;
13882+ bindex = au_ibstart(inode);
13883+ br = au_sbr(sb, bindex);
13884+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
13885+ if (write_mask
13886+ && !err
13887+ && !special_file(h_inode->i_mode)) {
13888+ /* test whether the upper writable branch exists */
13889+ err = -EROFS;
13890+ for (; bindex >= 0; bindex--)
13891+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
13892+ err = 0;
13893+ break;
13894+ }
13895+ }
13896+ goto out;
13897+ }
dece6358 13898+
4a4d8108 13899+ /* non-write to dir */
1308ab2a 13900+ err = 0;
4a4d8108
AM
13901+ bend = au_ibend(inode);
13902+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
13903+ h_inode = au_h_iptr(inode, bindex);
13904+ if (h_inode) {
13905+ err = au_busy_or_stale();
13906+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
13907+ break;
13908+
13909+ br = au_sbr(sb, bindex);
13910+ err = h_permission(h_inode, mask, br->br_mnt,
13911+ br->br_perm);
13912+ }
13913+ }
1308ab2a 13914+
4f0767ce 13915+out:
4a4d8108
AM
13916+ ii_read_unlock(inode);
13917+ si_read_unlock(sb);
1308ab2a 13918+ return err;
13919+}
13920+
4a4d8108 13921+/* ---------------------------------------------------------------------- */
1facf9fc 13922+
4a4d8108
AM
13923+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
13924+ struct nameidata *nd)
13925+{
13926+ struct dentry *ret, *parent;
b752ccd1 13927+ struct inode *inode;
4a4d8108
AM
13928+ struct super_block *sb;
13929+ int err, npositive;
dece6358 13930+
4a4d8108 13931+ IMustLock(dir);
1308ab2a 13932+
4a4d8108 13933+ sb = dir->i_sb;
7f207e10
AM
13934+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
13935+ ret = ERR_PTR(err);
13936+ if (unlikely(err))
13937+ goto out;
13938+
4a4d8108
AM
13939+ ret = ERR_PTR(-ENAMETOOLONG);
13940+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
7f207e10 13941+ goto out_si;
4a4d8108
AM
13942+ err = au_di_init(dentry);
13943+ ret = ERR_PTR(err);
13944+ if (unlikely(err))
7f207e10 13945+ goto out_si;
1308ab2a 13946+
4a4d8108
AM
13947+ parent = dentry->d_parent; /* dir inode is locked */
13948+ di_read_lock_parent(parent, AuLock_IR);
13949+ npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
13950+ di_read_unlock(parent, AuLock_IR);
13951+ err = npositive;
13952+ ret = ERR_PTR(err);
13953+ if (unlikely(err < 0))
13954+ goto out_unlock;
1308ab2a 13955+
4a4d8108
AM
13956+ inode = NULL;
13957+ if (npositive) {
b752ccd1 13958+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 13959+ ret = (void *)inode;
1facf9fc 13960+ }
4a4d8108
AM
13961+ if (IS_ERR(inode))
13962+ goto out_unlock;
13963+
13964+ ret = d_splice_alias(inode, dentry);
7f207e10 13965+ if (unlikely(IS_ERR(ret) && inode)) {
4a4d8108 13966+ ii_write_unlock(inode);
7f207e10
AM
13967+ iput(inode);
13968+ }
1facf9fc 13969+
4f0767ce 13970+out_unlock:
4a4d8108 13971+ di_write_unlock(dentry);
7f207e10 13972+out_si:
4a4d8108 13973+ si_read_unlock(sb);
7f207e10 13974+out:
4a4d8108
AM
13975+ return ret;
13976+}
1facf9fc 13977+
4a4d8108 13978+/* ---------------------------------------------------------------------- */
1facf9fc 13979+
4a4d8108
AM
13980+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
13981+ const unsigned char add_entry, aufs_bindex_t bcpup,
13982+ aufs_bindex_t bstart)
13983+{
13984+ int err;
13985+ struct dentry *h_parent;
13986+ struct inode *h_dir;
1facf9fc 13987+
4a4d8108
AM
13988+ if (add_entry) {
13989+ au_update_dbstart(dentry);
13990+ IMustLock(parent->d_inode);
13991+ } else
13992+ di_write_lock_parent(parent);
13993+
13994+ err = 0;
13995+ if (!au_h_dptr(parent, bcpup)) {
13996+ if (bstart < bcpup)
13997+ err = au_cpdown_dirs(dentry, bcpup);
13998+ else
13999+ err = au_cpup_dirs(dentry, bcpup);
14000+ }
14001+ if (!err && add_entry) {
14002+ h_parent = au_h_dptr(parent, bcpup);
14003+ h_dir = h_parent->d_inode;
14004+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
14005+ err = au_lkup_neg(dentry, bcpup);
14006+ /* todo: no unlock here */
14007+ mutex_unlock(&h_dir->i_mutex);
14008+ if (bstart < bcpup && au_dbstart(dentry) < 0) {
14009+ au_set_dbstart(dentry, 0);
14010+ au_update_dbrange(dentry, /*do_put_zero*/0);
14011+ }
1308ab2a 14012+ }
1facf9fc 14013+
4a4d8108
AM
14014+ if (!add_entry)
14015+ di_write_unlock(parent);
14016+ if (!err)
14017+ err = bcpup; /* success */
1308ab2a 14018+
4a4d8108
AM
14019+ return err;
14020+}
1facf9fc 14021+
4a4d8108
AM
14022+/*
14023+ * decide the branch and the parent dir where we will create a new entry.
14024+ * returns new bindex or an error.
14025+ * copyup the parent dir if needed.
14026+ */
14027+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14028+ struct au_wr_dir_args *args)
14029+{
14030+ int err;
14031+ aufs_bindex_t bcpup, bstart, src_bstart;
14032+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
14033+ ADD_ENTRY);
14034+ struct super_block *sb;
14035+ struct dentry *parent;
14036+ struct au_sbinfo *sbinfo;
1facf9fc 14037+
4a4d8108
AM
14038+ sb = dentry->d_sb;
14039+ sbinfo = au_sbi(sb);
14040+ parent = dget_parent(dentry);
14041+ bstart = au_dbstart(dentry);
14042+ bcpup = bstart;
14043+ if (args->force_btgt < 0) {
14044+ if (src_dentry) {
14045+ src_bstart = au_dbstart(src_dentry);
14046+ if (src_bstart < bstart)
14047+ bcpup = src_bstart;
14048+ } else if (add_entry) {
14049+ err = AuWbrCreate(sbinfo, dentry,
14050+ au_ftest_wrdir(args->flags, ISDIR));
14051+ bcpup = err;
14052+ }
1facf9fc 14053+
4a4d8108
AM
14054+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
14055+ if (add_entry)
14056+ err = AuWbrCopyup(sbinfo, dentry);
14057+ else {
14058+ if (!IS_ROOT(dentry)) {
14059+ di_read_lock_parent(parent, !AuLock_IR);
14060+ err = AuWbrCopyup(sbinfo, dentry);
14061+ di_read_unlock(parent, !AuLock_IR);
14062+ } else
14063+ err = AuWbrCopyup(sbinfo, dentry);
14064+ }
14065+ bcpup = err;
14066+ if (unlikely(err < 0))
14067+ goto out;
14068+ }
14069+ } else {
14070+ bcpup = args->force_btgt;
14071+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 14072+ }
4a4d8108
AM
14073+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
14074+ err = bcpup;
14075+ if (bcpup == bstart)
14076+ goto out; /* success */
14077+ else if (bstart < bcpup)
14078+ au_update_dbrange(dentry, /*do_put_zero*/1);
14079+
14080+ /* copyup the new parent into the branch we process */
14081+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
14082+
4f0767ce 14083+out:
4a4d8108 14084+ dput(parent);
dece6358
AM
14085+ return err;
14086+}
1facf9fc 14087+
1308ab2a 14088+/* ---------------------------------------------------------------------- */
14089+
4a4d8108 14090+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 14091+{
4a4d8108
AM
14092+ if (pin && pin->parent)
14093+ return au_h_dptr(pin->parent, pin->bindex);
14094+ return NULL;
dece6358 14095+}
1facf9fc 14096+
4a4d8108 14097+void au_unpin(struct au_pin *p)
dece6358 14098+{
e49829fe 14099+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
4a4d8108
AM
14100+ mnt_drop_write(p->h_mnt);
14101+ if (!p->hdir)
14102+ return;
1facf9fc 14103+
4a4d8108
AM
14104+ au_hn_imtx_unlock(p->hdir);
14105+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14106+ di_read_unlock(p->parent, AuLock_IR);
14107+ iput(p->hdir->hi_inode);
14108+ dput(p->parent);
14109+ p->parent = NULL;
14110+ p->hdir = NULL;
14111+ p->h_mnt = NULL;
14112+}
1308ab2a 14113+
4a4d8108
AM
14114+int au_do_pin(struct au_pin *p)
14115+{
14116+ int err;
14117+ struct super_block *sb;
14118+ struct dentry *h_dentry, *h_parent;
14119+ struct au_branch *br;
14120+ struct inode *h_dir;
14121+
14122+ err = 0;
14123+ sb = p->dentry->d_sb;
14124+ br = au_sbr(sb, p->bindex);
14125+ if (IS_ROOT(p->dentry)) {
14126+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14127+ p->h_mnt = br->br_mnt;
14128+ err = mnt_want_write(p->h_mnt);
14129+ if (unlikely(err)) {
14130+ au_fclr_pin(p->flags, MNT_WRITE);
14131+ goto out_err;
14132+ }
14133+ }
dece6358 14134+ goto out;
1facf9fc 14135+ }
14136+
4a4d8108
AM
14137+ h_dentry = NULL;
14138+ if (p->bindex <= au_dbend(p->dentry))
14139+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 14140+
4a4d8108
AM
14141+ p->parent = dget_parent(p->dentry);
14142+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14143+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 14144+
4a4d8108
AM
14145+ h_dir = NULL;
14146+ h_parent = au_h_dptr(p->parent, p->bindex);
14147+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
14148+ if (p->hdir)
14149+ h_dir = p->hdir->hi_inode;
dece6358 14150+
b752ccd1
AM
14151+ /*
14152+ * udba case, or
14153+ * if DI_LOCKED is not set, then p->parent may be different
14154+ * and h_parent can be NULL.
14155+ */
14156+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
e49829fe 14157+ err = -EBUSY;
4a4d8108
AM
14158+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14159+ di_read_unlock(p->parent, AuLock_IR);
14160+ dput(p->parent);
14161+ p->parent = NULL;
14162+ goto out_err;
14163+ }
1308ab2a 14164+
4a4d8108
AM
14165+ au_igrab(h_dir);
14166+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 14167+
4a4d8108
AM
14168+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
14169+ err = -EBUSY;
14170+ goto out_unpin;
14171+ }
14172+ if (h_dentry) {
14173+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
14174+ if (unlikely(err)) {
14175+ au_fclr_pin(p->flags, MNT_WRITE);
14176+ goto out_unpin;
14177+ }
1facf9fc 14178+ }
dece6358 14179+
4a4d8108
AM
14180+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14181+ p->h_mnt = br->br_mnt;
14182+ err = mnt_want_write(p->h_mnt);
dece6358 14183+ if (unlikely(err)) {
4a4d8108
AM
14184+ au_fclr_pin(p->flags, MNT_WRITE);
14185+ goto out_unpin;
dece6358
AM
14186+ }
14187+ }
4a4d8108
AM
14188+ goto out; /* success */
14189+
4f0767ce 14190+out_unpin:
4a4d8108 14191+ au_unpin(p);
4f0767ce 14192+out_err:
4a4d8108
AM
14193+ pr_err("err %d\n", err);
14194+ err = au_busy_or_stale();
4f0767ce 14195+out:
1facf9fc 14196+ return err;
14197+}
14198+
4a4d8108
AM
14199+void au_pin_init(struct au_pin *p, struct dentry *dentry,
14200+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14201+ unsigned int udba, unsigned char flags)
14202+{
14203+ p->dentry = dentry;
14204+ p->udba = udba;
14205+ p->lsc_di = lsc_di;
14206+ p->lsc_hi = lsc_hi;
14207+ p->flags = flags;
14208+ p->bindex = bindex;
14209+
14210+ p->parent = NULL;
14211+ p->hdir = NULL;
14212+ p->h_mnt = NULL;
14213+}
14214+
14215+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14216+ unsigned int udba, unsigned char flags)
14217+{
14218+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
14219+ udba, flags);
14220+ return au_do_pin(pin);
14221+}
14222+
dece6358
AM
14223+/* ---------------------------------------------------------------------- */
14224+
1308ab2a 14225+/*
4a4d8108
AM
14226+ * ->setattr() and ->getattr() are called in various cases.
14227+ * chmod, stat: dentry is revalidated.
14228+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
14229+ * unhashed.
14230+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 14231+ */
4a4d8108 14232+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 14233+{
4a4d8108
AM
14234+ int err;
14235+ struct inode *inode;
14236+ struct dentry *parent;
1facf9fc 14237+
1308ab2a 14238+ err = 0;
4a4d8108
AM
14239+ inode = dentry->d_inode;
14240+ if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
14241+ parent = dget_parent(dentry);
14242+ di_read_lock_parent(parent, AuLock_IR);
14243+ /* returns a number of positive dentries */
14244+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
14245+ if (err >= 0)
14246+ err = au_refresh_hinode(inode, dentry);
14247+ di_read_unlock(parent, AuLock_IR);
14248+ dput(parent);
dece6358 14249+ }
1facf9fc 14250+
4a4d8108 14251+ AuTraceErr(err);
1308ab2a 14252+ return err;
14253+}
dece6358 14254+
4a4d8108
AM
14255+#define AuIcpup_DID_CPUP 1
14256+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
7f207e10
AM
14257+#define au_fset_icpup(flags, name) \
14258+ do { (flags) |= AuIcpup_##name; } while (0)
14259+#define au_fclr_icpup(flags, name) \
14260+ do { (flags) &= ~AuIcpup_##name; } while (0)
1308ab2a 14261+
4a4d8108
AM
14262+struct au_icpup_args {
14263+ unsigned char flags;
14264+ unsigned char pin_flags;
14265+ aufs_bindex_t btgt;
14266+ unsigned int udba;
14267+ struct au_pin pin;
14268+ struct path h_path;
14269+ struct inode *h_inode;
14270+};
1308ab2a 14271+
4a4d8108
AM
14272+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
14273+ struct au_icpup_args *a)
1308ab2a 14274+{
14275+ int err;
4a4d8108 14276+ loff_t sz;
e49829fe 14277+ aufs_bindex_t bstart, ibstart;
4a4d8108
AM
14278+ struct dentry *hi_wh, *parent;
14279+ struct inode *inode;
14280+ struct file *h_file;
14281+ struct au_wr_dir_args wr_dir_args = {
14282+ .force_btgt = -1,
14283+ .flags = 0
14284+ };
14285+
14286+ bstart = au_dbstart(dentry);
14287+ inode = dentry->d_inode;
14288+ if (S_ISDIR(inode->i_mode))
14289+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
14290+ /* plink or hi_wh() case */
e49829fe
JR
14291+ ibstart = au_ibstart(inode);
14292+ if (bstart != ibstart)
14293+ wr_dir_args.force_btgt = ibstart;
4a4d8108
AM
14294+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
14295+ if (unlikely(err < 0))
14296+ goto out;
14297+ a->btgt = err;
14298+ if (err != bstart)
14299+ au_fset_icpup(a->flags, DID_CPUP);
14300+
14301+ err = 0;
14302+ a->pin_flags = AuPin_MNT_WRITE;
14303+ parent = NULL;
14304+ if (!IS_ROOT(dentry)) {
14305+ au_fset_pin(a->pin_flags, DI_LOCKED);
14306+ parent = dget_parent(dentry);
14307+ di_write_lock_parent(parent);
14308+ }
14309+
14310+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
14311+ if (unlikely(err))
14312+ goto out_parent;
14313+
14314+ a->h_path.dentry = au_h_dptr(dentry, bstart);
14315+ a->h_inode = a->h_path.dentry->d_inode;
14316+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14317+ sz = -1;
14318+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
14319+ sz = ia->ia_size;
14320+
14321+ h_file = NULL;
14322+ hi_wh = NULL;
7f207e10 14323+ if (au_ftest_icpup(a->flags, DID_CPUP) && au_d_removed(dentry)) {
4a4d8108
AM
14324+ hi_wh = au_hi_wh(inode, a->btgt);
14325+ if (!hi_wh) {
14326+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
14327+ if (unlikely(err))
14328+ goto out_unlock;
14329+ hi_wh = au_hi_wh(inode, a->btgt);
14330+ /* todo: revalidate hi_wh? */
14331+ }
14332+ }
14333+
14334+ if (parent) {
14335+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14336+ di_downgrade_lock(parent, AuLock_IR);
14337+ dput(parent);
14338+ parent = NULL;
14339+ }
14340+ if (!au_ftest_icpup(a->flags, DID_CPUP))
14341+ goto out; /* success */
14342+
14343+ if (!d_unhashed(dentry)) {
14344+ h_file = au_h_open_pre(dentry, bstart);
14345+ if (IS_ERR(h_file)) {
14346+ err = PTR_ERR(h_file);
14347+ h_file = NULL;
14348+ } else
14349+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
14350+ AuCpup_DTIME);
14351+ if (!err)
14352+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14353+ } else if (!hi_wh)
14354+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14355+ else
14356+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 14357+
4f0767ce 14358+out_unlock:
4a4d8108
AM
14359+ mutex_unlock(&a->h_inode->i_mutex);
14360+ au_h_open_post(dentry, bstart, h_file);
14361+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 14362+ if (!err) {
4a4d8108 14363+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 14364+ goto out; /* success */
1facf9fc 14365+ }
dece6358 14366+
4a4d8108 14367+ au_unpin(&a->pin);
4f0767ce 14368+out_parent:
4a4d8108
AM
14369+ if (parent) {
14370+ di_write_unlock(parent);
14371+ dput(parent);
14372+ }
4f0767ce 14373+out:
1facf9fc 14374+ return err;
14375+}
14376+
4a4d8108 14377+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 14378+{
4a4d8108
AM
14379+ int err;
14380+ struct inode *inode;
14381+ struct super_block *sb;
14382+ struct file *file;
14383+ struct au_icpup_args *a;
1facf9fc 14384+
4a4d8108
AM
14385+ inode = dentry->d_inode;
14386+ IMustLock(inode);
dece6358 14387+
4a4d8108
AM
14388+ err = -ENOMEM;
14389+ a = kzalloc(sizeof(*a), GFP_NOFS);
14390+ if (unlikely(!a))
14391+ goto out;
1facf9fc 14392+
4a4d8108
AM
14393+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
14394+ ia->ia_valid &= ~ATTR_MODE;
dece6358 14395+
4a4d8108
AM
14396+ file = NULL;
14397+ sb = dentry->d_sb;
e49829fe
JR
14398+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
14399+ if (unlikely(err))
14400+ goto out_kfree;
14401+
4a4d8108
AM
14402+ if (ia->ia_valid & ATTR_FILE) {
14403+ /* currently ftruncate(2) only */
14404+ AuDebugOn(!S_ISREG(inode->i_mode));
14405+ file = ia->ia_file;
14406+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
14407+ if (unlikely(err))
14408+ goto out_si;
14409+ ia->ia_file = au_hf_top(file);
14410+ a->udba = AuOpt_UDBA_NONE;
14411+ } else {
14412+ /* fchmod() doesn't pass ia_file */
14413+ a->udba = au_opt_udba(sb);
7f207e10 14414+ /* no au_d_removed(), to set UDBA_NONE for root */
4a4d8108
AM
14415+ if (d_unhashed(dentry))
14416+ a->udba = AuOpt_UDBA_NONE;
14417+ di_write_lock_child(dentry);
14418+ if (a->udba != AuOpt_UDBA_NONE) {
14419+ AuDebugOn(IS_ROOT(dentry));
14420+ err = au_reval_for_attr(dentry, au_sigen(sb));
14421+ if (unlikely(err))
14422+ goto out_dentry;
14423+ }
dece6358 14424+ }
dece6358 14425+
4a4d8108
AM
14426+ err = au_pin_and_icpup(dentry, ia, a);
14427+ if (unlikely(err < 0))
14428+ goto out_dentry;
14429+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
14430+ ia->ia_file = NULL;
14431+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 14432+ }
dece6358 14433+
4a4d8108
AM
14434+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
14435+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
14436+ == (ATTR_MODE | ATTR_CTIME)) {
14437+ err = security_path_chmod(a->h_path.dentry, a->h_path.mnt,
14438+ ia->ia_mode);
14439+ if (unlikely(err))
14440+ goto out_unlock;
14441+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
14442+ && (ia->ia_valid & ATTR_CTIME)) {
14443+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
14444+ if (unlikely(err))
14445+ goto out_unlock;
14446+ }
dece6358 14447+
4a4d8108
AM
14448+ if (ia->ia_valid & ATTR_SIZE) {
14449+ struct file *f;
1308ab2a 14450+
953406b4 14451+ if (ia->ia_size < i_size_read(inode))
4a4d8108 14452+ /* unmap only */
953406b4 14453+ truncate_setsize(inode, ia->ia_size);
1308ab2a 14454+
4a4d8108
AM
14455+ f = NULL;
14456+ if (ia->ia_valid & ATTR_FILE)
14457+ f = ia->ia_file;
14458+ mutex_unlock(&a->h_inode->i_mutex);
14459+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
14460+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14461+ } else
14462+ err = vfsub_notify_change(&a->h_path, ia);
14463+ if (!err)
14464+ au_cpup_attr_changeable(inode);
1308ab2a 14465+
4f0767ce 14466+out_unlock:
4a4d8108
AM
14467+ mutex_unlock(&a->h_inode->i_mutex);
14468+ au_unpin(&a->pin);
4f0767ce 14469+out_dentry:
4a4d8108
AM
14470+ di_write_unlock(dentry);
14471+ if (file) {
14472+ fi_write_unlock(file);
14473+ ia->ia_file = file;
14474+ ia->ia_valid |= ATTR_FILE;
14475+ }
4f0767ce 14476+out_si:
4a4d8108 14477+ si_read_unlock(sb);
e49829fe 14478+out_kfree:
4a4d8108 14479+ kfree(a);
4f0767ce 14480+out:
4a4d8108
AM
14481+ AuTraceErr(err);
14482+ return err;
1facf9fc 14483+}
14484+
4a4d8108
AM
14485+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
14486+ unsigned int nlink)
1facf9fc 14487+{
4a4d8108
AM
14488+ inode->i_mode = st->mode;
14489+ inode->i_uid = st->uid;
14490+ inode->i_gid = st->gid;
14491+ inode->i_atime = st->atime;
14492+ inode->i_mtime = st->mtime;
14493+ inode->i_ctime = st->ctime;
1facf9fc 14494+
4a4d8108
AM
14495+ au_cpup_attr_nlink(inode, /*force*/0);
14496+ if (S_ISDIR(inode->i_mode)) {
14497+ inode->i_nlink -= nlink;
14498+ inode->i_nlink += st->nlink;
14499+ }
1facf9fc 14500+
4a4d8108
AM
14501+ spin_lock(&inode->i_lock);
14502+ inode->i_blocks = st->blocks;
14503+ i_size_write(inode, st->size);
14504+ spin_unlock(&inode->i_lock);
1facf9fc 14505+}
14506+
4a4d8108
AM
14507+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
14508+ struct dentry *dentry, struct kstat *st)
1facf9fc 14509+{
4a4d8108
AM
14510+ int err;
14511+ unsigned int mnt_flags;
14512+ aufs_bindex_t bindex;
14513+ unsigned char udba_none, positive;
14514+ struct super_block *sb, *h_sb;
14515+ struct inode *inode;
14516+ struct vfsmount *h_mnt;
14517+ struct dentry *h_dentry;
1facf9fc 14518+
4a4d8108
AM
14519+ sb = dentry->d_sb;
14520+ inode = dentry->d_inode;
7f207e10
AM
14521+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
14522+ if (unlikely(err))
14523+ goto out;
4a4d8108
AM
14524+ mnt_flags = au_mntflags(sb);
14525+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 14526+
4a4d8108 14527+ /* support fstat(2) */
7f207e10 14528+ if (!au_d_removed(dentry) && !udba_none) {
4a4d8108
AM
14529+ unsigned int sigen = au_sigen(sb);
14530+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
14531+ di_read_lock_child(dentry, AuLock_IR);
14532+ else {
14533+ AuDebugOn(IS_ROOT(dentry));
14534+ di_write_lock_child(dentry);
14535+ err = au_reval_for_attr(dentry, sigen);
14536+ di_downgrade_lock(dentry, AuLock_IR);
14537+ if (unlikely(err))
7f207e10 14538+ goto out_unlock;
4a4d8108
AM
14539+ }
14540+ } else
14541+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 14542+
4a4d8108
AM
14543+ bindex = au_ibstart(inode);
14544+ h_mnt = au_sbr_mnt(sb, bindex);
14545+ h_sb = h_mnt->mnt_sb;
14546+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
14547+ goto out_fill; /* success */
1facf9fc 14548+
4a4d8108
AM
14549+ h_dentry = NULL;
14550+ if (au_dbstart(dentry) == bindex)
14551+ h_dentry = dget(au_h_dptr(dentry, bindex));
14552+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
14553+ h_dentry = au_plink_lkup(inode, bindex);
14554+ if (IS_ERR(h_dentry))
14555+ goto out_fill; /* pretending success */
14556+ }
14557+ /* illegally overlapped or something */
14558+ if (unlikely(!h_dentry))
14559+ goto out_fill; /* pretending success */
14560+
14561+ positive = !!h_dentry->d_inode;
14562+ if (positive)
14563+ err = vfs_getattr(h_mnt, h_dentry, st);
14564+ dput(h_dentry);
14565+ if (!err) {
14566+ if (positive)
14567+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
14568+ goto out_fill; /* success */
1facf9fc 14569+ }
7f207e10
AM
14570+ AuTraceErr(err);
14571+ goto out_unlock;
4a4d8108 14572+
4f0767ce 14573+out_fill:
4a4d8108 14574+ generic_fillattr(inode, st);
7f207e10 14575+out_unlock:
4a4d8108
AM
14576+ di_read_unlock(dentry, AuLock_IR);
14577+ si_read_unlock(sb);
7f207e10
AM
14578+out:
14579+ AuTraceErr(err);
4a4d8108 14580+ return err;
1facf9fc 14581+}
14582+
14583+/* ---------------------------------------------------------------------- */
14584+
4a4d8108
AM
14585+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
14586+ int bufsiz)
1facf9fc 14587+{
14588+ int err;
4a4d8108
AM
14589+ struct super_block *sb;
14590+ struct dentry *h_dentry;
1facf9fc 14591+
4a4d8108
AM
14592+ err = -EINVAL;
14593+ h_dentry = au_h_dptr(dentry, bindex);
14594+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
14595+ goto out;
1facf9fc 14596+
4a4d8108
AM
14597+ err = security_inode_readlink(h_dentry);
14598+ if (unlikely(err))
dece6358 14599+ goto out;
1facf9fc 14600+
4a4d8108
AM
14601+ sb = dentry->d_sb;
14602+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
14603+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
14604+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 14605+ }
4a4d8108 14606+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 14607+
4f0767ce 14608+out:
4a4d8108
AM
14609+ return err;
14610+}
1facf9fc 14611+
4a4d8108
AM
14612+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
14613+{
14614+ int err;
1facf9fc 14615+
4a4d8108
AM
14616+ aufs_read_lock(dentry, AuLock_IR);
14617+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
14618+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14619+
4a4d8108
AM
14620+ return err;
14621+}
1facf9fc 14622+
4a4d8108
AM
14623+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
14624+{
14625+ int err;
4a4d8108 14626+ mm_segment_t old_fs;
b752ccd1
AM
14627+ union {
14628+ char *k;
14629+ char __user *u;
14630+ } buf;
1facf9fc 14631+
4a4d8108 14632+ err = -ENOMEM;
b752ccd1
AM
14633+ buf.k = __getname_gfp(GFP_NOFS);
14634+ if (unlikely(!buf.k))
4a4d8108 14635+ goto out;
1facf9fc 14636+
4a4d8108
AM
14637+ aufs_read_lock(dentry, AuLock_IR);
14638+ old_fs = get_fs();
14639+ set_fs(KERNEL_DS);
b752ccd1 14640+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
4a4d8108
AM
14641+ set_fs(old_fs);
14642+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14643+
4a4d8108 14644+ if (err >= 0) {
b752ccd1 14645+ buf.k[err] = 0;
4a4d8108 14646+ /* will be freed by put_link */
b752ccd1 14647+ nd_set_link(nd, buf.k);
4a4d8108 14648+ return NULL; /* success */
1308ab2a 14649+ }
b752ccd1 14650+ __putname(buf.k);
1facf9fc 14651+
4f0767ce 14652+out:
4a4d8108
AM
14653+ path_put(&nd->path);
14654+ AuTraceErr(err);
14655+ return ERR_PTR(err);
14656+}
1facf9fc 14657+
4a4d8108
AM
14658+static void aufs_put_link(struct dentry *dentry __maybe_unused,
14659+ struct nameidata *nd, void *cookie __maybe_unused)
14660+{
14661+ __putname(nd_get_link(nd));
14662+}
1facf9fc 14663+
4a4d8108 14664+/* ---------------------------------------------------------------------- */
1facf9fc 14665+
4a4d8108
AM
14666+static void aufs_truncate_range(struct inode *inode __maybe_unused,
14667+ loff_t start __maybe_unused,
14668+ loff_t end __maybe_unused)
14669+{
14670+ AuUnsupport();
14671+}
1facf9fc 14672+
4a4d8108 14673+/* ---------------------------------------------------------------------- */
1308ab2a 14674+
4a4d8108
AM
14675+struct inode_operations aufs_symlink_iop = {
14676+ .permission = aufs_permission,
14677+ .setattr = aufs_setattr,
14678+ .getattr = aufs_getattr,
14679+ .readlink = aufs_readlink,
14680+ .follow_link = aufs_follow_link,
14681+ .put_link = aufs_put_link
14682+};
14683+
14684+struct inode_operations aufs_dir_iop = {
14685+ .create = aufs_create,
14686+ .lookup = aufs_lookup,
14687+ .link = aufs_link,
14688+ .unlink = aufs_unlink,
14689+ .symlink = aufs_symlink,
14690+ .mkdir = aufs_mkdir,
14691+ .rmdir = aufs_rmdir,
14692+ .mknod = aufs_mknod,
14693+ .rename = aufs_rename,
14694+
14695+ .permission = aufs_permission,
14696+ .setattr = aufs_setattr,
14697+ .getattr = aufs_getattr
14698+};
14699+
14700+struct inode_operations aufs_iop = {
14701+ .permission = aufs_permission,
14702+ .setattr = aufs_setattr,
14703+ .getattr = aufs_getattr,
14704+ .truncate_range = aufs_truncate_range
14705+};
7f207e10
AM
14706diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
14707--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
14708+++ linux/fs/aufs/i_op_del.c 2010-11-22 11:52:56.987228248 +0100
4a4d8108 14709@@ -0,0 +1,472 @@
1facf9fc 14710+/*
4a4d8108 14711+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 14712+ *
14713+ * This program, aufs is free software; you can redistribute it and/or modify
14714+ * it under the terms of the GNU General Public License as published by
14715+ * the Free Software Foundation; either version 2 of the License, or
14716+ * (at your option) any later version.
dece6358
AM
14717+ *
14718+ * This program is distributed in the hope that it will be useful,
14719+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14720+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14721+ * GNU General Public License for more details.
14722+ *
14723+ * You should have received a copy of the GNU General Public License
14724+ * along with this program; if not, write to the Free Software
14725+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14726+ */
14727+
14728+/*
4a4d8108 14729+ * inode operations (del entry)
1308ab2a 14730+ */
dece6358 14731+
1308ab2a 14732+#include "aufs.h"
dece6358 14733+
4a4d8108
AM
14734+/*
14735+ * decide if a new whiteout for @dentry is necessary or not.
14736+ * when it is necessary, prepare the parent dir for the upper branch whose
14737+ * branch index is @bcpup for creation. the actual creation of the whiteout will
14738+ * be done by caller.
14739+ * return value:
14740+ * 0: wh is unnecessary
14741+ * plus: wh is necessary
14742+ * minus: error
14743+ */
14744+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 14745+{
4a4d8108
AM
14746+ int need_wh, err;
14747+ aufs_bindex_t bstart;
14748+ struct super_block *sb;
dece6358 14749+
4a4d8108
AM
14750+ sb = dentry->d_sb;
14751+ bstart = au_dbstart(dentry);
14752+ if (*bcpup < 0) {
14753+ *bcpup = bstart;
14754+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
14755+ err = AuWbrCopyup(au_sbi(sb), dentry);
14756+ *bcpup = err;
14757+ if (unlikely(err < 0))
14758+ goto out;
14759+ }
14760+ } else
14761+ AuDebugOn(bstart < *bcpup
14762+ || au_test_ro(sb, *bcpup, dentry->d_inode));
14763+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 14764+
4a4d8108
AM
14765+ if (*bcpup != bstart) {
14766+ err = au_cpup_dirs(dentry, *bcpup);
14767+ if (unlikely(err))
14768+ goto out;
14769+ need_wh = 1;
14770+ } else {
14771+ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
14772+
14773+ old_bend = au_dbend(dentry);
14774+ if (isdir) {
14775+ bdiropq = au_dbdiropq(dentry);
14776+ au_set_dbdiropq(dentry, -1);
14777+ }
14778+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
14779+ /*nd*/NULL);
14780+ err = need_wh;
14781+ if (isdir)
14782+ au_set_dbdiropq(dentry, bdiropq);
14783+ if (unlikely(err < 0))
14784+ goto out;
14785+ new_bend = au_dbend(dentry);
14786+ if (!need_wh && old_bend != new_bend) {
14787+ au_set_h_dptr(dentry, new_bend, NULL);
14788+ au_set_dbend(dentry, old_bend);
14789+ }
14790+ }
14791+ AuDbg("need_wh %d\n", need_wh);
14792+ err = need_wh;
14793+
4f0767ce 14794+out:
4a4d8108 14795+ return err;
1facf9fc 14796+}
14797+
4a4d8108
AM
14798+/*
14799+ * simple tests for the del-entry operations.
14800+ * following the checks in vfs, plus the parent-child relationship.
14801+ */
14802+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14803+ struct dentry *h_parent, int isdir)
1facf9fc 14804+{
4a4d8108
AM
14805+ int err;
14806+ umode_t h_mode;
14807+ struct dentry *h_dentry, *h_latest;
1308ab2a 14808+ struct inode *h_inode;
1facf9fc 14809+
4a4d8108
AM
14810+ h_dentry = au_h_dptr(dentry, bindex);
14811+ h_inode = h_dentry->d_inode;
14812+ if (dentry->d_inode) {
14813+ err = -ENOENT;
14814+ if (unlikely(!h_inode || !h_inode->i_nlink))
14815+ goto out;
1facf9fc 14816+
4a4d8108
AM
14817+ h_mode = h_inode->i_mode;
14818+ if (!isdir) {
14819+ err = -EISDIR;
14820+ if (unlikely(S_ISDIR(h_mode)))
14821+ goto out;
14822+ } else if (unlikely(!S_ISDIR(h_mode))) {
14823+ err = -ENOTDIR;
14824+ goto out;
14825+ }
14826+ } else {
14827+ /* rename(2) case */
14828+ err = -EIO;
14829+ if (unlikely(h_inode))
14830+ goto out;
14831+ }
1facf9fc 14832+
4a4d8108
AM
14833+ err = -ENOENT;
14834+ /* expected parent dir is locked */
14835+ if (unlikely(h_parent != h_dentry->d_parent))
14836+ goto out;
14837+ err = 0;
14838+
14839+ /*
14840+ * rmdir a dir may break the consistency on some filesystem.
14841+ * let's try heavy test.
14842+ */
14843+ err = -EACCES;
14844+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
14845+ goto out;
14846+
14847+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
14848+ au_sbr(dentry->d_sb, bindex));
14849+ err = -EIO;
14850+ if (IS_ERR(h_latest))
14851+ goto out;
14852+ if (h_latest == h_dentry)
14853+ err = 0;
14854+ dput(h_latest);
14855+
4f0767ce 14856+out:
4a4d8108 14857+ return err;
1308ab2a 14858+}
1facf9fc 14859+
4a4d8108
AM
14860+/*
14861+ * decide the branch where we operate for @dentry. the branch index will be set
14862+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
14863+ * dir for reverting.
14864+ * when a new whiteout is necessary, create it.
14865+ */
14866+static struct dentry*
14867+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
14868+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 14869+{
4a4d8108
AM
14870+ struct dentry *wh_dentry;
14871+ struct super_block *sb;
14872+ struct path h_path;
14873+ int err, need_wh;
14874+ unsigned int udba;
14875+ aufs_bindex_t bcpup;
dece6358 14876+
4a4d8108
AM
14877+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
14878+ wh_dentry = ERR_PTR(need_wh);
14879+ if (unlikely(need_wh < 0))
14880+ goto out;
14881+
14882+ sb = dentry->d_sb;
14883+ udba = au_opt_udba(sb);
14884+ bcpup = *rbcpup;
14885+ err = au_pin(pin, dentry, bcpup, udba,
14886+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14887+ wh_dentry = ERR_PTR(err);
14888+ if (unlikely(err))
14889+ goto out;
14890+
14891+ h_path.dentry = au_pinned_h_parent(pin);
14892+ if (udba != AuOpt_UDBA_NONE
14893+ && au_dbstart(dentry) == bcpup) {
14894+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
14895+ wh_dentry = ERR_PTR(err);
14896+ if (unlikely(err))
14897+ goto out_unpin;
14898+ }
14899+
14900+ h_path.mnt = au_sbr_mnt(sb, bcpup);
14901+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
14902+ wh_dentry = NULL;
14903+ if (!need_wh)
14904+ goto out; /* success, no need to create whiteout */
14905+
14906+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
14907+ if (IS_ERR(wh_dentry))
14908+ goto out_unpin;
14909+
14910+ /* returns with the parent is locked and wh_dentry is dget-ed */
14911+ goto out; /* success */
14912+
4f0767ce 14913+out_unpin:
4a4d8108 14914+ au_unpin(pin);
4f0767ce 14915+out:
4a4d8108 14916+ return wh_dentry;
1facf9fc 14917+}
14918+
4a4d8108
AM
14919+/*
14920+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
14921+ * in order to be revertible and save time for removing many child whiteouts
14922+ * under the dir.
14923+ * returns 1 when there are too many child whiteout and caller should remove
14924+ * them asynchronously. returns 0 when the number of children is enough small to
14925+ * remove now or the branch fs is a remote fs.
14926+ * otherwise return an error.
14927+ */
14928+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
14929+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 14930+{
4a4d8108
AM
14931+ int rmdir_later, err, dirwh;
14932+ struct dentry *h_dentry;
14933+ struct super_block *sb;
14934+
14935+ sb = dentry->d_sb;
14936+ SiMustAnyLock(sb);
14937+ h_dentry = au_h_dptr(dentry, bindex);
14938+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
14939+ if (unlikely(err))
14940+ goto out;
14941+
14942+ /* stop monitoring */
14943+ au_hn_free(au_hi(dentry->d_inode, bindex));
14944+
14945+ if (!au_test_fs_remote(h_dentry->d_sb)) {
14946+ dirwh = au_sbi(sb)->si_dirwh;
14947+ rmdir_later = (dirwh <= 1);
14948+ if (!rmdir_later)
14949+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
14950+ dirwh);
14951+ if (rmdir_later)
14952+ return rmdir_later;
14953+ }
1facf9fc 14954+
4a4d8108
AM
14955+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
14956+ if (unlikely(err)) {
14957+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
14958+ AuDLNPair(h_dentry), bindex, err);
14959+ err = 0;
14960+ }
dece6358 14961+
4f0767ce 14962+out:
4a4d8108
AM
14963+ AuTraceErr(err);
14964+ return err;
14965+}
1308ab2a 14966+
4a4d8108
AM
14967+/*
14968+ * final procedure for deleting a entry.
14969+ * maintain dentry and iattr.
14970+ */
14971+static void epilog(struct inode *dir, struct dentry *dentry,
14972+ aufs_bindex_t bindex)
14973+{
14974+ struct inode *inode;
1308ab2a 14975+
4a4d8108
AM
14976+ inode = dentry->d_inode;
14977+ d_drop(dentry);
14978+ inode->i_ctime = dir->i_ctime;
1308ab2a 14979+
4a4d8108
AM
14980+ if (atomic_read(&dentry->d_count) == 1) {
14981+ au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
14982+ au_update_dbstart(dentry);
dece6358 14983+ }
4a4d8108
AM
14984+ if (au_ibstart(dir) == bindex)
14985+ au_cpup_attr_timesizes(dir);
14986+ dir->i_version++;
1facf9fc 14987+}
14988+
4a4d8108
AM
14989+/*
14990+ * when an error happened, remove the created whiteout and revert everything.
14991+ */
7f207e10
AM
14992+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
14993+ aufs_bindex_t bwh, struct dentry *wh_dentry,
14994+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 14995+{
4a4d8108
AM
14996+ int rerr;
14997+ struct path h_path = {
14998+ .dentry = wh_dentry,
7f207e10 14999+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 15000+ };
dece6358 15001+
7f207e10 15002+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
15003+ if (!rerr) {
15004+ au_set_dbwh(dentry, bwh);
15005+ au_dtime_revert(dt);
15006+ return 0;
15007+ }
dece6358 15008+
4a4d8108
AM
15009+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15010+ AuDLNPair(dentry), err, rerr);
15011+ return -EIO;
1facf9fc 15012+}
15013+
4a4d8108 15014+/* ---------------------------------------------------------------------- */
1facf9fc 15015+
4a4d8108 15016+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 15017+{
4a4d8108
AM
15018+ int err;
15019+ aufs_bindex_t bwh, bindex, bstart;
15020+ struct au_dtime dt;
15021+ struct au_pin pin;
15022+ struct path h_path;
15023+ struct inode *inode, *h_dir;
15024+ struct dentry *parent, *wh_dentry;
1facf9fc 15025+
4a4d8108
AM
15026+ IMustLock(dir);
15027+ inode = dentry->d_inode;
15028+ if (unlikely(!inode))
15029+ return -ENOENT; /* possible? */
15030+ IMustLock(inode);
1facf9fc 15031+
4a4d8108
AM
15032+ aufs_read_lock(dentry, AuLock_DW);
15033+ parent = dentry->d_parent; /* dir inode is locked */
15034+ di_write_lock_parent(parent);
1facf9fc 15035+
4a4d8108
AM
15036+ bstart = au_dbstart(dentry);
15037+ bwh = au_dbwh(dentry);
15038+ bindex = -1;
15039+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
15040+ err = PTR_ERR(wh_dentry);
15041+ if (IS_ERR(wh_dentry))
15042+ goto out;
1facf9fc 15043+
4a4d8108
AM
15044+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
15045+ h_path.dentry = au_h_dptr(dentry, bstart);
15046+ dget(h_path.dentry);
15047+ if (bindex == bstart) {
15048+ h_dir = au_pinned_h_dir(&pin);
15049+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
15050+ } else {
15051+ /* dir inode is locked */
15052+ h_dir = wh_dentry->d_parent->d_inode;
15053+ IMustLock(h_dir);
15054+ err = 0;
15055+ }
dece6358 15056+
4a4d8108 15057+ if (!err) {
7f207e10 15058+ vfsub_drop_nlink(inode);
4a4d8108
AM
15059+ epilog(dir, dentry, bindex);
15060+
15061+ /* update target timestamps */
15062+ if (bindex == bstart) {
15063+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
15064+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
15065+ } else
15066+ /* todo: this timestamp may be reverted later */
15067+ inode->i_ctime = h_dir->i_ctime;
15068+ goto out_unlock; /* success */
1facf9fc 15069+ }
15070+
4a4d8108
AM
15071+ /* revert */
15072+ if (wh_dentry) {
15073+ int rerr;
15074+
7f207e10 15075+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
15076+ if (rerr)
15077+ err = rerr;
dece6358 15078+ }
1facf9fc 15079+
4f0767ce 15080+out_unlock:
4a4d8108
AM
15081+ au_unpin(&pin);
15082+ dput(wh_dentry);
15083+ dput(h_path.dentry);
4f0767ce 15084+out:
4a4d8108
AM
15085+ di_write_unlock(parent);
15086+ aufs_read_unlock(dentry, AuLock_DW);
15087+ return err;
dece6358
AM
15088+}
15089+
4a4d8108 15090+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 15091+{
4a4d8108
AM
15092+ int err, rmdir_later;
15093+ aufs_bindex_t bwh, bindex, bstart;
15094+ struct au_dtime dt;
15095+ struct au_pin pin;
15096+ struct inode *inode;
15097+ struct dentry *parent, *wh_dentry, *h_dentry;
15098+ struct au_whtmp_rmdir *args;
1facf9fc 15099+
4a4d8108
AM
15100+ IMustLock(dir);
15101+ inode = dentry->d_inode;
15102+ err = -ENOENT; /* possible? */
15103+ if (unlikely(!inode))
15104+ goto out;
15105+ IMustLock(inode);
dece6358 15106+
4a4d8108
AM
15107+ aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
15108+ err = -ENOMEM;
15109+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
15110+ if (unlikely(!args))
15111+ goto out_unlock;
dece6358 15112+
4a4d8108
AM
15113+ parent = dentry->d_parent; /* dir inode is locked */
15114+ di_write_lock_parent(parent);
15115+ err = au_test_empty(dentry, &args->whlist);
15116+ if (unlikely(err))
15117+ goto out_args;
1facf9fc 15118+
4a4d8108
AM
15119+ bstart = au_dbstart(dentry);
15120+ bwh = au_dbwh(dentry);
15121+ bindex = -1;
15122+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
15123+ err = PTR_ERR(wh_dentry);
15124+ if (IS_ERR(wh_dentry))
15125+ goto out_args;
1facf9fc 15126+
4a4d8108
AM
15127+ h_dentry = au_h_dptr(dentry, bstart);
15128+ dget(h_dentry);
15129+ rmdir_later = 0;
15130+ if (bindex == bstart) {
15131+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
15132+ if (err > 0) {
15133+ rmdir_later = err;
15134+ err = 0;
15135+ }
15136+ } else {
15137+ /* stop monitoring */
15138+ au_hn_free(au_hi(inode, bstart));
15139+
15140+ /* dir inode is locked */
15141+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 15142+ err = 0;
15143+ }
15144+
4a4d8108
AM
15145+ if (!err) {
15146+ clear_nlink(inode);
15147+ au_set_dbdiropq(dentry, -1);
15148+ epilog(dir, dentry, bindex);
1308ab2a 15149+
4a4d8108
AM
15150+ if (rmdir_later) {
15151+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
15152+ args = NULL;
15153+ }
1308ab2a 15154+
4a4d8108 15155+ goto out_unpin; /* success */
1facf9fc 15156+ }
15157+
4a4d8108
AM
15158+ /* revert */
15159+ AuLabel(revert);
15160+ if (wh_dentry) {
15161+ int rerr;
1308ab2a 15162+
7f207e10 15163+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
15164+ if (rerr)
15165+ err = rerr;
1facf9fc 15166+ }
15167+
4f0767ce 15168+out_unpin:
4a4d8108
AM
15169+ au_unpin(&pin);
15170+ dput(wh_dentry);
15171+ dput(h_dentry);
4f0767ce 15172+out_args:
4a4d8108
AM
15173+ di_write_unlock(parent);
15174+ if (args)
15175+ au_whtmp_rmdir_free(args);
4f0767ce 15176+out_unlock:
4a4d8108 15177+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 15178+out:
4a4d8108
AM
15179+ AuTraceErr(err);
15180+ return err;
dece6358 15181+}
7f207e10
AM
15182diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
15183--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
15184+++ linux/fs/aufs/i_op_ren.c 2010-11-22 11:52:56.987228248 +0100
15185@@ -0,0 +1,982 @@
1facf9fc 15186+/*
4a4d8108 15187+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 15188+ *
15189+ * This program, aufs is free software; you can redistribute it and/or modify
15190+ * it under the terms of the GNU General Public License as published by
15191+ * the Free Software Foundation; either version 2 of the License, or
15192+ * (at your option) any later version.
dece6358
AM
15193+ *
15194+ * This program is distributed in the hope that it will be useful,
15195+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15196+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15197+ * GNU General Public License for more details.
15198+ *
15199+ * You should have received a copy of the GNU General Public License
15200+ * along with this program; if not, write to the Free Software
15201+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 15202+ */
15203+
15204+/*
4a4d8108
AM
15205+ * inode operation (rename entry)
15206+ * todo: this is crazy monster
1facf9fc 15207+ */
15208+
15209+#include "aufs.h"
15210+
4a4d8108
AM
15211+enum { AuSRC, AuDST, AuSrcDst };
15212+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 15213+
4a4d8108
AM
15214+#define AuRen_ISDIR 1
15215+#define AuRen_ISSAMEDIR (1 << 1)
15216+#define AuRen_WHSRC (1 << 2)
15217+#define AuRen_WHDST (1 << 3)
15218+#define AuRen_MNT_WRITE (1 << 4)
15219+#define AuRen_DT_DSTDIR (1 << 5)
15220+#define AuRen_DIROPQ (1 << 6)
15221+#define AuRen_CPUP (1 << 7)
15222+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
15223+#define au_fset_ren(flags, name) \
15224+ do { (flags) |= AuRen_##name; } while (0)
15225+#define au_fclr_ren(flags, name) \
15226+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 15227+
4a4d8108
AM
15228+struct au_ren_args {
15229+ struct {
15230+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
15231+ *wh_dentry;
15232+ struct inode *dir, *inode;
15233+ struct au_hinode *hdir;
15234+ struct au_dtime dt[AuParentChild];
15235+ aufs_bindex_t bstart;
15236+ } sd[AuSrcDst];
1facf9fc 15237+
4a4d8108
AM
15238+#define src_dentry sd[AuSRC].dentry
15239+#define src_dir sd[AuSRC].dir
15240+#define src_inode sd[AuSRC].inode
15241+#define src_h_dentry sd[AuSRC].h_dentry
15242+#define src_parent sd[AuSRC].parent
15243+#define src_h_parent sd[AuSRC].h_parent
15244+#define src_wh_dentry sd[AuSRC].wh_dentry
15245+#define src_hdir sd[AuSRC].hdir
15246+#define src_h_dir sd[AuSRC].hdir->hi_inode
15247+#define src_dt sd[AuSRC].dt
15248+#define src_bstart sd[AuSRC].bstart
1facf9fc 15249+
4a4d8108
AM
15250+#define dst_dentry sd[AuDST].dentry
15251+#define dst_dir sd[AuDST].dir
15252+#define dst_inode sd[AuDST].inode
15253+#define dst_h_dentry sd[AuDST].h_dentry
15254+#define dst_parent sd[AuDST].parent
15255+#define dst_h_parent sd[AuDST].h_parent
15256+#define dst_wh_dentry sd[AuDST].wh_dentry
15257+#define dst_hdir sd[AuDST].hdir
15258+#define dst_h_dir sd[AuDST].hdir->hi_inode
15259+#define dst_dt sd[AuDST].dt
15260+#define dst_bstart sd[AuDST].bstart
15261+
15262+ struct dentry *h_trap;
15263+ struct au_branch *br;
15264+ struct au_hinode *src_hinode;
15265+ struct path h_path;
15266+ struct au_nhash whlist;
15267+ aufs_bindex_t btgt;
1facf9fc 15268+
1308ab2a 15269+ unsigned int flags;
1facf9fc 15270+
4a4d8108
AM
15271+ struct au_whtmp_rmdir *thargs;
15272+ struct dentry *h_dst;
15273+};
1308ab2a 15274+
4a4d8108 15275+/* ---------------------------------------------------------------------- */
1308ab2a 15276+
4a4d8108
AM
15277+/*
15278+ * functions for reverting.
15279+ * when an error happened in a single rename systemcall, we should revert
15280+ * everything as if nothing happend.
15281+ * we don't need to revert the copied-up/down the parent dir since they are
15282+ * harmless.
15283+ */
1facf9fc 15284+
4a4d8108
AM
15285+#define RevertFailure(fmt, ...) do { \
15286+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
15287+ ##__VA_ARGS__, err, rerr); \
15288+ err = -EIO; \
15289+} while (0)
1facf9fc 15290+
4a4d8108 15291+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 15292+{
4a4d8108 15293+ int rerr;
1facf9fc 15294+
4a4d8108
AM
15295+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15296+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
15297+ au_hn_imtx_unlock(a->src_hinode);
15298+ if (rerr)
15299+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
15300+}
1facf9fc 15301+
4a4d8108
AM
15302+static void au_ren_rev_rename(int err, struct au_ren_args *a)
15303+{
15304+ int rerr;
1facf9fc 15305+
4a4d8108
AM
15306+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
15307+ a->br, /*nd*/NULL);
15308+ rerr = PTR_ERR(a->h_path.dentry);
15309+ if (IS_ERR(a->h_path.dentry)) {
15310+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
15311+ return;
1facf9fc 15312+ }
15313+
4a4d8108
AM
15314+ rerr = vfsub_rename(a->dst_h_dir,
15315+ au_h_dptr(a->src_dentry, a->btgt),
15316+ a->src_h_dir, &a->h_path);
15317+ d_drop(a->h_path.dentry);
15318+ dput(a->h_path.dentry);
15319+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
15320+ if (rerr)
15321+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 15322+}
15323+
4a4d8108 15324+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 15325+{
4a4d8108 15326+ int rerr;
1facf9fc 15327+
4a4d8108
AM
15328+ a->h_path.dentry = a->dst_h_dentry;
15329+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
15330+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
15331+ au_set_dbstart(a->src_dentry, a->src_bstart);
15332+ if (rerr)
15333+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 15334+}
15335+
4a4d8108 15336+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 15337+{
4a4d8108 15338+ int rerr;
dece6358 15339+
4a4d8108
AM
15340+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
15341+ a->br, /*nd*/NULL);
15342+ rerr = PTR_ERR(a->h_path.dentry);
15343+ if (IS_ERR(a->h_path.dentry)) {
15344+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
15345+ return;
15346+ }
15347+ if (a->h_path.dentry->d_inode) {
15348+ d_drop(a->h_path.dentry);
15349+ dput(a->h_path.dentry);
15350+ return;
dece6358
AM
15351+ }
15352+
4a4d8108
AM
15353+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
15354+ d_drop(a->h_path.dentry);
15355+ dput(a->h_path.dentry);
15356+ if (!rerr)
15357+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
15358+ else
15359+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
15360+}
1308ab2a 15361+
4a4d8108
AM
15362+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
15363+{
15364+ int rerr;
1308ab2a 15365+
4a4d8108
AM
15366+ a->h_path.dentry = a->src_wh_dentry;
15367+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
15368+ if (rerr)
15369+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
15370+}
1308ab2a 15371+
4a4d8108
AM
15372+static void au_ren_rev_drop(struct au_ren_args *a)
15373+{
15374+ struct dentry *d, *h_d;
15375+ int i;
15376+ aufs_bindex_t bend, bindex;
15377+
15378+ for (i = 0; i < AuSrcDst; i++) {
15379+ d = a->sd[i].dentry;
15380+ d_drop(d);
15381+ bend = au_dbend(d);
15382+ for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
15383+ h_d = au_h_dptr(d, bindex);
15384+ if (h_d)
15385+ d_drop(h_d);
15386+ }
1308ab2a 15387+ }
15388+
4a4d8108
AM
15389+ au_update_dbstart(a->dst_dentry);
15390+ if (a->thargs)
15391+ d_drop(a->h_dst);
1facf9fc 15392+}
4a4d8108 15393+#undef RevertFailure
1facf9fc 15394+
1308ab2a 15395+/* ---------------------------------------------------------------------- */
15396+
4a4d8108
AM
15397+/*
15398+ * when we have to copyup the renaming entry, do it with the rename-target name
15399+ * in order to minimize the cost (the later actual rename is unnecessary).
15400+ * otherwise rename it on the target branch.
15401+ */
15402+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 15403+{
dece6358 15404+ int err;
4a4d8108 15405+ struct dentry *d;
1facf9fc 15406+
4a4d8108
AM
15407+ d = a->src_dentry;
15408+ if (au_dbstart(d) == a->btgt) {
15409+ a->h_path.dentry = a->dst_h_dentry;
15410+ if (au_ftest_ren(a->flags, DIROPQ)
15411+ && au_dbdiropq(d) == a->btgt)
15412+ au_fclr_ren(a->flags, DIROPQ);
15413+ AuDebugOn(au_dbstart(d) != a->btgt);
15414+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
15415+ a->dst_h_dir, &a->h_path);
15416+ } else {
15417+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15418+ struct file *h_file;
1308ab2a 15419+
4a4d8108
AM
15420+ au_fset_ren(a->flags, CPUP);
15421+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15422+ au_set_dbstart(d, a->btgt);
15423+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
15424+ h_file = au_h_open_pre(d, a->src_bstart);
15425+ if (IS_ERR(h_file)) {
15426+ err = PTR_ERR(h_file);
15427+ h_file = NULL;
15428+ } else
15429+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
15430+ !AuCpup_DTIME, a->dst_parent);
15431+ mutex_unlock(h_mtx);
15432+ au_h_open_post(d, a->src_bstart, h_file);
15433+ if (!err) {
15434+ d = a->dst_dentry;
15435+ au_set_h_dptr(d, a->btgt, NULL);
15436+ au_update_dbstart(d);
15437+ } else {
15438+ au_set_h_dptr(d, a->btgt, NULL);
15439+ au_set_dbstart(d, a->src_bstart);
15440+ }
1308ab2a 15441+ }
1facf9fc 15442+
dece6358
AM
15443+ return err;
15444+}
1facf9fc 15445+
4a4d8108
AM
15446+/* cf. aufs_rmdir() */
15447+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 15448+{
4a4d8108
AM
15449+ int err;
15450+ struct inode *dir;
1facf9fc 15451+
4a4d8108
AM
15452+ dir = a->dst_dir;
15453+ SiMustAnyLock(dir->i_sb);
15454+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
15455+ au_sbi(dir->i_sb)->si_dirwh)
15456+ || au_test_fs_remote(a->h_dst->d_sb)) {
15457+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
15458+ if (unlikely(err))
15459+ pr_warning("failed removing whtmp dir %.*s (%d), "
15460+ "ignored.\n", AuDLNPair(a->h_dst), err);
15461+ } else {
15462+ au_nhash_wh_free(&a->thargs->whlist);
15463+ a->thargs->whlist = a->whlist;
15464+ a->whlist.nh_num = 0;
15465+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
15466+ dput(a->h_dst);
15467+ a->thargs = NULL;
15468+ }
15469+
15470+ return 0;
1308ab2a 15471+}
1facf9fc 15472+
4a4d8108
AM
15473+/* make it 'opaque' dir. */
15474+static int au_ren_diropq(struct au_ren_args *a)
15475+{
15476+ int err;
15477+ struct dentry *diropq;
1facf9fc 15478+
4a4d8108
AM
15479+ err = 0;
15480+ a->src_hinode = au_hi(a->src_inode, a->btgt);
15481+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15482+ diropq = au_diropq_create(a->src_dentry, a->btgt);
15483+ au_hn_imtx_unlock(a->src_hinode);
15484+ if (IS_ERR(diropq))
15485+ err = PTR_ERR(diropq);
15486+ dput(diropq);
1facf9fc 15487+
4a4d8108
AM
15488+ return err;
15489+}
1facf9fc 15490+
4a4d8108
AM
15491+static int do_rename(struct au_ren_args *a)
15492+{
15493+ int err;
15494+ struct dentry *d, *h_d;
1facf9fc 15495+
4a4d8108
AM
15496+ /* prepare workqueue args for asynchronous rmdir */
15497+ h_d = a->dst_h_dentry;
15498+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
15499+ err = -ENOMEM;
15500+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
15501+ if (unlikely(!a->thargs))
15502+ goto out;
15503+ a->h_dst = dget(h_d);
15504+ }
1facf9fc 15505+
4a4d8108
AM
15506+ /* create whiteout for src_dentry */
15507+ if (au_ftest_ren(a->flags, WHSRC)) {
15508+ a->src_wh_dentry
15509+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
15510+ err = PTR_ERR(a->src_wh_dentry);
15511+ if (IS_ERR(a->src_wh_dentry))
15512+ goto out_thargs;
15513+ }
1facf9fc 15514+
4a4d8108
AM
15515+ /* lookup whiteout for dentry */
15516+ if (au_ftest_ren(a->flags, WHDST)) {
15517+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
15518+ a->br);
15519+ err = PTR_ERR(h_d);
15520+ if (IS_ERR(h_d))
15521+ goto out_whsrc;
15522+ if (!h_d->d_inode)
15523+ dput(h_d);
15524+ else
15525+ a->dst_wh_dentry = h_d;
15526+ }
1facf9fc 15527+
4a4d8108
AM
15528+ /* rename dentry to tmpwh */
15529+ if (a->thargs) {
15530+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
15531+ if (unlikely(err))
15532+ goto out_whdst;
dece6358 15533+
4a4d8108
AM
15534+ d = a->dst_dentry;
15535+ au_set_h_dptr(d, a->btgt, NULL);
15536+ err = au_lkup_neg(d, a->btgt);
15537+ if (unlikely(err))
15538+ goto out_whtmp;
15539+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
15540+ }
1facf9fc 15541+
4a4d8108
AM
15542+ /* cpup src */
15543+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
15544+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15545+ struct file *h_file;
1facf9fc 15546+
4a4d8108
AM
15547+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15548+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
15549+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
15550+ if (IS_ERR(h_file)) {
15551+ err = PTR_ERR(h_file);
15552+ h_file = NULL;
15553+ } else
15554+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
15555+ !AuCpup_DTIME);
15556+ mutex_unlock(h_mtx);
15557+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
15558+ if (unlikely(err))
15559+ goto out_whtmp;
15560+ }
1facf9fc 15561+
4a4d8108
AM
15562+ /* rename by vfs_rename or cpup */
15563+ d = a->dst_dentry;
15564+ if (au_ftest_ren(a->flags, ISDIR)
15565+ && (a->dst_wh_dentry
15566+ || au_dbdiropq(d) == a->btgt
15567+ /* hide the lower to keep xino */
15568+ || a->btgt < au_dbend(d)
15569+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
15570+ au_fset_ren(a->flags, DIROPQ);
15571+ err = au_ren_or_cpup(a);
15572+ if (unlikely(err))
15573+ /* leave the copied-up one */
15574+ goto out_whtmp;
1308ab2a 15575+
4a4d8108
AM
15576+ /* make dir opaque */
15577+ if (au_ftest_ren(a->flags, DIROPQ)) {
15578+ err = au_ren_diropq(a);
15579+ if (unlikely(err))
15580+ goto out_rename;
15581+ }
1308ab2a 15582+
4a4d8108
AM
15583+ /* update target timestamps */
15584+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
15585+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
15586+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
15587+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 15588+
4a4d8108
AM
15589+ /* remove whiteout for dentry */
15590+ if (a->dst_wh_dentry) {
15591+ a->h_path.dentry = a->dst_wh_dentry;
15592+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
15593+ a->dst_dentry);
15594+ if (unlikely(err))
15595+ goto out_diropq;
15596+ }
1facf9fc 15597+
4a4d8108
AM
15598+ /* remove whtmp */
15599+ if (a->thargs)
15600+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 15601+
4a4d8108
AM
15602+ err = 0;
15603+ goto out_success;
15604+
4f0767ce 15605+out_diropq:
4a4d8108
AM
15606+ if (au_ftest_ren(a->flags, DIROPQ))
15607+ au_ren_rev_diropq(err, a);
4f0767ce 15608+out_rename:
4a4d8108
AM
15609+ if (!au_ftest_ren(a->flags, CPUP))
15610+ au_ren_rev_rename(err, a);
15611+ else
15612+ au_ren_rev_cpup(err, a);
4f0767ce 15613+out_whtmp:
4a4d8108
AM
15614+ if (a->thargs)
15615+ au_ren_rev_whtmp(err, a);
4f0767ce 15616+out_whdst:
4a4d8108
AM
15617+ dput(a->dst_wh_dentry);
15618+ a->dst_wh_dentry = NULL;
4f0767ce 15619+out_whsrc:
4a4d8108
AM
15620+ if (a->src_wh_dentry)
15621+ au_ren_rev_whsrc(err, a);
15622+ au_ren_rev_drop(a);
4f0767ce 15623+out_success:
4a4d8108
AM
15624+ dput(a->src_wh_dentry);
15625+ dput(a->dst_wh_dentry);
4f0767ce 15626+out_thargs:
4a4d8108
AM
15627+ if (a->thargs) {
15628+ dput(a->h_dst);
15629+ au_whtmp_rmdir_free(a->thargs);
15630+ a->thargs = NULL;
15631+ }
4f0767ce 15632+out:
4a4d8108 15633+ return err;
dece6358 15634+}
1facf9fc 15635+
1308ab2a 15636+/* ---------------------------------------------------------------------- */
1facf9fc 15637+
4a4d8108
AM
15638+/*
15639+ * test if @dentry dir can be rename destination or not.
15640+ * success means, it is a logically empty dir.
15641+ */
15642+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 15643+{
4a4d8108 15644+ return au_test_empty(dentry, whlist);
1308ab2a 15645+}
1facf9fc 15646+
4a4d8108
AM
15647+/*
15648+ * test if @dentry dir can be rename source or not.
15649+ * if it can, return 0 and @children is filled.
15650+ * success means,
15651+ * - it is a logically empty dir.
15652+ * - or, it exists on writable branch and has no children including whiteouts
15653+ * on the lower branch.
15654+ */
15655+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
15656+{
15657+ int err;
15658+ unsigned int rdhash;
15659+ aufs_bindex_t bstart;
1facf9fc 15660+
4a4d8108
AM
15661+ bstart = au_dbstart(dentry);
15662+ if (bstart != btgt) {
15663+ struct au_nhash whlist;
dece6358 15664+
4a4d8108
AM
15665+ SiMustAnyLock(dentry->d_sb);
15666+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
15667+ if (!rdhash)
15668+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
15669+ dentry));
15670+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
15671+ if (unlikely(err))
15672+ goto out;
15673+ err = au_test_empty(dentry, &whlist);
15674+ au_nhash_wh_free(&whlist);
15675+ goto out;
15676+ }
dece6358 15677+
4a4d8108
AM
15678+ if (bstart == au_dbtaildir(dentry))
15679+ return 0; /* success */
dece6358 15680+
4a4d8108 15681+ err = au_test_empty_lower(dentry);
1facf9fc 15682+
4f0767ce 15683+out:
4a4d8108
AM
15684+ if (err == -ENOTEMPTY) {
15685+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
15686+ " is not supported\n");
15687+ err = -EXDEV;
15688+ }
15689+ return err;
15690+}
1308ab2a 15691+
4a4d8108
AM
15692+/* side effect: sets whlist and h_dentry */
15693+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 15694+{
4a4d8108
AM
15695+ int err;
15696+ unsigned int rdhash;
15697+ struct dentry *d;
1facf9fc 15698+
4a4d8108
AM
15699+ d = a->dst_dentry;
15700+ SiMustAnyLock(d->d_sb);
1facf9fc 15701+
4a4d8108
AM
15702+ err = 0;
15703+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
15704+ rdhash = au_sbi(d->d_sb)->si_rdhash;
15705+ if (!rdhash)
15706+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
15707+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
15708+ if (unlikely(err))
15709+ goto out;
1308ab2a 15710+
4a4d8108
AM
15711+ au_set_dbstart(d, a->dst_bstart);
15712+ err = may_rename_dstdir(d, &a->whlist);
15713+ au_set_dbstart(d, a->btgt);
15714+ }
15715+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
15716+ if (unlikely(err))
15717+ goto out;
15718+
15719+ d = a->src_dentry;
15720+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
15721+ if (au_ftest_ren(a->flags, ISDIR)) {
15722+ err = may_rename_srcdir(d, a->btgt);
15723+ if (unlikely(err)) {
15724+ au_nhash_wh_free(&a->whlist);
15725+ a->whlist.nh_num = 0;
15726+ }
15727+ }
4f0767ce 15728+out:
4a4d8108 15729+ return err;
1facf9fc 15730+}
15731+
4a4d8108 15732+/* ---------------------------------------------------------------------- */
1facf9fc 15733+
4a4d8108
AM
15734+/*
15735+ * simple tests for rename.
15736+ * following the checks in vfs, plus the parent-child relationship.
15737+ */
15738+static int au_may_ren(struct au_ren_args *a)
15739+{
15740+ int err, isdir;
15741+ struct inode *h_inode;
1facf9fc 15742+
4a4d8108
AM
15743+ if (a->src_bstart == a->btgt) {
15744+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
15745+ au_ftest_ren(a->flags, ISDIR));
15746+ if (unlikely(err))
15747+ goto out;
15748+ err = -EINVAL;
15749+ if (unlikely(a->src_h_dentry == a->h_trap))
15750+ goto out;
15751+ }
1facf9fc 15752+
4a4d8108
AM
15753+ err = 0;
15754+ if (a->dst_bstart != a->btgt)
15755+ goto out;
1facf9fc 15756+
4a4d8108
AM
15757+ err = -EIO;
15758+ h_inode = a->dst_h_dentry->d_inode;
15759+ isdir = !!au_ftest_ren(a->flags, ISDIR);
15760+ if (!a->dst_dentry->d_inode) {
15761+ if (unlikely(h_inode))
15762+ goto out;
15763+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
15764+ isdir);
15765+ } else {
15766+ if (unlikely(!h_inode || !h_inode->i_nlink))
15767+ goto out;
15768+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
15769+ isdir);
15770+ if (unlikely(err))
15771+ goto out;
15772+ err = -ENOTEMPTY;
15773+ if (unlikely(a->dst_h_dentry == a->h_trap))
15774+ goto out;
15775+ err = 0;
15776+ }
1facf9fc 15777+
4f0767ce 15778+out:
4a4d8108
AM
15779+ if (unlikely(err == -ENOENT || err == -EEXIST))
15780+ err = -EIO;
15781+ AuTraceErr(err);
15782+ return err;
15783+}
1facf9fc 15784+
1308ab2a 15785+/* ---------------------------------------------------------------------- */
1facf9fc 15786+
4a4d8108
AM
15787+/*
15788+ * locking order
15789+ * (VFS)
15790+ * - src_dir and dir by lock_rename()
15791+ * - inode if exitsts
15792+ * (aufs)
15793+ * - lock all
15794+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
15795+ * + si_read_lock
15796+ * + di_write_lock2_child()
15797+ * + di_write_lock_child()
15798+ * + ii_write_lock_child()
15799+ * + di_write_lock_child2()
15800+ * + ii_write_lock_child2()
15801+ * + src_parent and parent
15802+ * + di_write_lock_parent()
15803+ * + ii_write_lock_parent()
15804+ * + di_write_lock_parent2()
15805+ * + ii_write_lock_parent2()
15806+ * + lower src_dir and dir by vfsub_lock_rename()
15807+ * + verify the every relationships between child and parent. if any
15808+ * of them failed, unlock all and return -EBUSY.
15809+ */
15810+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 15811+{
4a4d8108
AM
15812+ struct super_block *sb;
15813+
15814+ sb = a->dst_dentry->d_sb;
15815+ if (au_ftest_ren(a->flags, MNT_WRITE))
15816+ mnt_drop_write(a->br->br_mnt);
15817+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
15818+ a->dst_h_parent, a->dst_hdir);
1308ab2a 15819+}
15820+
4a4d8108 15821+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 15822+{
4a4d8108
AM
15823+ int err;
15824+ unsigned int udba;
1308ab2a 15825+
4a4d8108
AM
15826+ err = 0;
15827+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
15828+ a->src_hdir = au_hi(a->src_dir, a->btgt);
15829+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
15830+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
15831+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
15832+ a->dst_h_parent, a->dst_hdir);
15833+ udba = au_opt_udba(a->src_dentry->d_sb);
15834+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
15835+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
15836+ err = au_busy_or_stale();
15837+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
15838+ err = au_h_verify(a->src_h_dentry, udba,
15839+ a->src_h_parent->d_inode, a->src_h_parent,
15840+ a->br);
15841+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
15842+ err = au_h_verify(a->dst_h_dentry, udba,
15843+ a->dst_h_parent->d_inode, a->dst_h_parent,
15844+ a->br);
15845+ if (!err) {
15846+ err = mnt_want_write(a->br->br_mnt);
15847+ if (unlikely(err))
15848+ goto out_unlock;
15849+ au_fset_ren(a->flags, MNT_WRITE);
15850+ goto out; /* success */
15851+ }
15852+
15853+ err = au_busy_or_stale();
15854+
4f0767ce 15855+out_unlock:
4a4d8108 15856+ au_ren_unlock(a);
4f0767ce 15857+out:
4a4d8108 15858+ return err;
1facf9fc 15859+}
15860+
15861+/* ---------------------------------------------------------------------- */
15862+
4a4d8108 15863+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 15864+{
4a4d8108 15865+ struct inode *dir;
dece6358 15866+
4a4d8108
AM
15867+ dir = a->dst_dir;
15868+ dir->i_version++;
15869+ if (au_ftest_ren(a->flags, ISDIR)) {
15870+ /* is this updating defined in POSIX? */
15871+ au_cpup_attr_timesizes(a->src_inode);
15872+ au_cpup_attr_nlink(dir, /*force*/1);
15873+ if (a->dst_inode) {
15874+ clear_nlink(a->dst_inode);
15875+ au_cpup_attr_timesizes(a->dst_inode);
15876+ }
15877+ }
15878+ if (au_ibstart(dir) == a->btgt)
15879+ au_cpup_attr_timesizes(dir);
dece6358 15880+
4a4d8108
AM
15881+ if (au_ftest_ren(a->flags, ISSAMEDIR))
15882+ return;
dece6358 15883+
4a4d8108
AM
15884+ dir = a->src_dir;
15885+ dir->i_version++;
15886+ if (au_ftest_ren(a->flags, ISDIR))
15887+ au_cpup_attr_nlink(dir, /*force*/1);
15888+ if (au_ibstart(dir) == a->btgt)
15889+ au_cpup_attr_timesizes(dir);
1facf9fc 15890+}
15891+
4a4d8108 15892+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 15893+{
4a4d8108
AM
15894+ aufs_bindex_t bend, bindex;
15895+ struct dentry *d, *h_d;
15896+ struct inode *i, *h_i;
15897+ struct super_block *sb;
dece6358 15898+
4a4d8108
AM
15899+ d = a->src_dentry;
15900+ au_set_dbwh(d, -1);
15901+ bend = au_dbend(d);
15902+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
15903+ h_d = au_h_dptr(d, bindex);
15904+ if (h_d)
15905+ au_set_h_dptr(d, bindex, NULL);
15906+ }
15907+ au_set_dbend(d, a->btgt);
15908+
15909+ sb = d->d_sb;
15910+ i = a->src_inode;
15911+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
15912+ return; /* success */
15913+
15914+ bend = au_ibend(i);
15915+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
15916+ h_i = au_h_iptr(i, bindex);
15917+ if (h_i) {
15918+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
15919+ /* ignore this error */
15920+ au_set_h_iptr(i, bindex, NULL, 0);
15921+ }
15922+ }
15923+ au_set_ibend(i, a->btgt);
1308ab2a 15924+}
dece6358 15925+
4a4d8108
AM
15926+/* ---------------------------------------------------------------------- */
15927+
15928+/* mainly for link(2) and rename(2) */
15929+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 15930+{
4a4d8108
AM
15931+ aufs_bindex_t bdiropq, bwh;
15932+ struct dentry *parent;
15933+ struct au_branch *br;
15934+
15935+ parent = dentry->d_parent;
15936+ IMustLock(parent->d_inode); /* dir is locked */
15937+
15938+ bdiropq = au_dbdiropq(parent);
15939+ bwh = au_dbwh(dentry);
15940+ br = au_sbr(dentry->d_sb, btgt);
15941+ if (au_br_rdonly(br)
15942+ || (0 <= bdiropq && bdiropq < btgt)
15943+ || (0 <= bwh && bwh < btgt))
15944+ btgt = -1;
15945+
15946+ AuDbg("btgt %d\n", btgt);
15947+ return btgt;
1facf9fc 15948+}
15949+
4a4d8108
AM
15950+/* sets src_bstart, dst_bstart and btgt */
15951+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 15952+{
4a4d8108
AM
15953+ int err;
15954+ struct au_wr_dir_args wr_dir_args = {
15955+ /* .force_btgt = -1, */
15956+ .flags = AuWrDir_ADD_ENTRY
15957+ };
dece6358 15958+
4a4d8108
AM
15959+ a->src_bstart = au_dbstart(a->src_dentry);
15960+ a->dst_bstart = au_dbstart(a->dst_dentry);
15961+ if (au_ftest_ren(a->flags, ISDIR))
15962+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
15963+ wr_dir_args.force_btgt = a->src_bstart;
15964+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
15965+ wr_dir_args.force_btgt = a->dst_bstart;
15966+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
15967+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
15968+ a->btgt = err;
dece6358 15969+
4a4d8108 15970+ return err;
1facf9fc 15971+}
15972+
4a4d8108 15973+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 15974+{
4a4d8108
AM
15975+ a->h_path.dentry = a->src_h_parent;
15976+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
15977+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
15978+ a->h_path.dentry = a->dst_h_parent;
15979+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
15980+ }
1facf9fc 15981+
4a4d8108
AM
15982+ au_fclr_ren(a->flags, DT_DSTDIR);
15983+ if (!au_ftest_ren(a->flags, ISDIR))
15984+ return;
dece6358 15985+
4a4d8108
AM
15986+ a->h_path.dentry = a->src_h_dentry;
15987+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
15988+ if (a->dst_h_dentry->d_inode) {
15989+ au_fset_ren(a->flags, DT_DSTDIR);
15990+ a->h_path.dentry = a->dst_h_dentry;
15991+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
15992+ }
1308ab2a 15993+}
dece6358 15994+
4a4d8108 15995+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 15996+{
4a4d8108
AM
15997+ struct dentry *h_d;
15998+ struct mutex *h_mtx;
15999+
16000+ au_dtime_revert(a->src_dt + AuPARENT);
16001+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
16002+ au_dtime_revert(a->dst_dt + AuPARENT);
16003+
16004+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
16005+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
16006+ h_mtx = &h_d->d_inode->i_mutex;
16007+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16008+ au_dtime_revert(a->src_dt + AuCHILD);
16009+ mutex_unlock(h_mtx);
16010+
16011+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
16012+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
16013+ h_mtx = &h_d->d_inode->i_mutex;
16014+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16015+ au_dtime_revert(a->dst_dt + AuCHILD);
16016+ mutex_unlock(h_mtx);
1facf9fc 16017+ }
16018+ }
16019+}
16020+
4a4d8108
AM
16021+/* ---------------------------------------------------------------------- */
16022+
16023+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
16024+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 16025+{
e49829fe 16026+ int err, flags;
4a4d8108
AM
16027+ /* reduce stack space */
16028+ struct au_ren_args *a;
16029+
16030+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
16031+ IMustLock(_src_dir);
16032+ IMustLock(_dst_dir);
16033+
16034+ err = -ENOMEM;
16035+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
16036+ a = kzalloc(sizeof(*a), GFP_NOFS);
16037+ if (unlikely(!a))
16038+ goto out;
16039+
16040+ a->src_dir = _src_dir;
16041+ a->src_dentry = _src_dentry;
16042+ a->src_inode = a->src_dentry->d_inode;
16043+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
16044+ a->dst_dir = _dst_dir;
16045+ a->dst_dentry = _dst_dentry;
16046+ a->dst_inode = a->dst_dentry->d_inode;
16047+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
16048+ if (a->dst_inode) {
16049+ IMustLock(a->dst_inode);
16050+ au_igrab(a->dst_inode);
1facf9fc 16051+ }
1facf9fc 16052+
4a4d8108 16053+ err = -ENOTDIR;
e49829fe 16054+ flags = AuLock_FLUSH | AuLock_NOPLM;
4a4d8108
AM
16055+ if (S_ISDIR(a->src_inode->i_mode)) {
16056+ au_fset_ren(a->flags, ISDIR);
16057+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
16058+ goto out_free;
e49829fe
JR
16059+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16060+ AuLock_DIR | flags);
4a4d8108 16061+ } else
e49829fe
JR
16062+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16063+ flags);
16064+ if (unlikely(err))
16065+ goto out_free;
1facf9fc 16066+
4a4d8108
AM
16067+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
16068+ di_write_lock_parent(a->dst_parent);
1facf9fc 16069+
4a4d8108
AM
16070+ /* which branch we process */
16071+ err = au_ren_wbr(a);
16072+ if (unlikely(err < 0))
16073+ goto out_unlock;
16074+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
16075+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 16076+
4a4d8108
AM
16077+ /* are they available to be renamed */
16078+ err = au_ren_may_dir(a);
16079+ if (unlikely(err))
16080+ goto out_children;
1facf9fc 16081+
4a4d8108
AM
16082+ /* prepare the writable parent dir on the same branch */
16083+ if (a->dst_bstart == a->btgt) {
16084+ au_fset_ren(a->flags, WHDST);
16085+ } else {
16086+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
16087+ if (unlikely(err))
16088+ goto out_children;
16089+ }
1facf9fc 16090+
4a4d8108
AM
16091+ if (a->src_dir != a->dst_dir) {
16092+ /*
16093+ * this temporary unlock is safe,
16094+ * because both dir->i_mutex are locked.
16095+ */
16096+ di_write_unlock(a->dst_parent);
16097+ di_write_lock_parent(a->src_parent);
16098+ err = au_wr_dir_need_wh(a->src_dentry,
16099+ au_ftest_ren(a->flags, ISDIR),
16100+ &a->btgt);
16101+ di_write_unlock(a->src_parent);
16102+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
16103+ au_fclr_ren(a->flags, ISSAMEDIR);
16104+ } else
16105+ err = au_wr_dir_need_wh(a->src_dentry,
16106+ au_ftest_ren(a->flags, ISDIR),
16107+ &a->btgt);
16108+ if (unlikely(err < 0))
16109+ goto out_children;
16110+ if (err)
16111+ au_fset_ren(a->flags, WHSRC);
1facf9fc 16112+
4a4d8108
AM
16113+ /* lock them all */
16114+ err = au_ren_lock(a);
16115+ if (unlikely(err))
16116+ goto out_children;
1facf9fc 16117+
4a4d8108
AM
16118+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
16119+ err = au_may_ren(a);
16120+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
16121+ err = -ENAMETOOLONG;
16122+ if (unlikely(err))
16123+ goto out_hdir;
1facf9fc 16124+
4a4d8108
AM
16125+ /* store timestamps to be revertible */
16126+ au_ren_dt(a);
1facf9fc 16127+
4a4d8108
AM
16128+ /* here we go */
16129+ err = do_rename(a);
16130+ if (unlikely(err))
16131+ goto out_dt;
16132+
16133+ /* update dir attributes */
16134+ au_ren_refresh_dir(a);
16135+
16136+ /* dput/iput all lower dentries */
16137+ au_ren_refresh(a);
16138+
16139+ goto out_hdir; /* success */
16140+
4f0767ce 16141+out_dt:
4a4d8108 16142+ au_ren_rev_dt(err, a);
4f0767ce 16143+out_hdir:
4a4d8108 16144+ au_ren_unlock(a);
4f0767ce 16145+out_children:
4a4d8108 16146+ au_nhash_wh_free(&a->whlist);
4f0767ce 16147+out_unlock:
4a4d8108
AM
16148+ if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
16149+ au_update_dbstart(a->dst_dentry);
16150+ d_drop(a->dst_dentry);
16151+ }
16152+ if (!err)
16153+ d_move(a->src_dentry, a->dst_dentry);
16154+ if (au_ftest_ren(a->flags, ISSAMEDIR))
16155+ di_write_unlock(a->dst_parent);
16156+ else
16157+ di_write_unlock2(a->src_parent, a->dst_parent);
16158+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 16159+out_free:
4a4d8108
AM
16160+ iput(a->dst_inode);
16161+ if (a->thargs)
16162+ au_whtmp_rmdir_free(a->thargs);
16163+ kfree(a);
4f0767ce 16164+out:
4a4d8108
AM
16165+ AuTraceErr(err);
16166+ return err;
1308ab2a 16167+}
7f207e10
AM
16168diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
16169--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
16170+++ linux/fs/aufs/Kconfig 2010-11-22 11:52:56.983894369 +0100
16171@@ -0,0 +1,180 @@
4a4d8108
AM
16172+config AUFS_FS
16173+ tristate "Aufs (Advanced multi layered unification filesystem) support"
16174+ depends on EXPERIMENTAL
16175+ help
16176+ Aufs is a stackable unification filesystem such as Unionfs,
16177+ which unifies several directories and provides a merged single
16178+ directory.
16179+ In the early days, aufs was entirely re-designed and
16180+ re-implemented Unionfs Version 1.x series. Introducing many
16181+ original ideas, approaches and improvements, it becomes totally
16182+ different from Unionfs while keeping the basic features.
1facf9fc 16183+
4a4d8108
AM
16184+if AUFS_FS
16185+choice
16186+ prompt "Maximum number of branches"
16187+ default AUFS_BRANCH_MAX_127
16188+ help
16189+ Specifies the maximum number of branches (or member directories)
16190+ in a single aufs. The larger value consumes more system
16191+ resources and has a minor impact to performance.
16192+config AUFS_BRANCH_MAX_127
16193+ bool "127"
16194+ help
16195+ Specifies the maximum number of branches (or member directories)
16196+ in a single aufs. The larger value consumes more system
16197+ resources and has a minor impact to performance.
16198+config AUFS_BRANCH_MAX_511
16199+ bool "511"
16200+ help
16201+ Specifies the maximum number of branches (or member directories)
16202+ in a single aufs. The larger value consumes more system
16203+ resources and has a minor impact to performance.
16204+config AUFS_BRANCH_MAX_1023
16205+ bool "1023"
16206+ help
16207+ Specifies the maximum number of branches (or member directories)
16208+ in a single aufs. The larger value consumes more system
16209+ resources and has a minor impact to performance.
16210+config AUFS_BRANCH_MAX_32767
16211+ bool "32767"
16212+ help
16213+ Specifies the maximum number of branches (or member directories)
16214+ in a single aufs. The larger value consumes more system
16215+ resources and has a minor impact to performance.
16216+endchoice
1facf9fc 16217+
e49829fe
JR
16218+config AUFS_SBILIST
16219+ bool
16220+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
16221+ default y
16222+ help
16223+ Automatic configuration for internal use.
16224+ When aufs supports Magic SysRq or /proc, enabled automatically.
16225+
4a4d8108
AM
16226+config AUFS_HNOTIFY
16227+ bool "Detect direct branch access (bypassing aufs)"
16228+ help
16229+ If you want to modify files on branches directly, eg. bypassing aufs,
16230+ and want aufs to detect the changes of them fully, then enable this
16231+ option and use 'udba=notify' mount option.
7f207e10 16232+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
16233+ It will have a negative impact to the performance.
16234+ See detail in aufs.5.
dece6358 16235+
4a4d8108
AM
16236+choice
16237+ prompt "method" if AUFS_HNOTIFY
16238+ default AUFS_HFSNOTIFY
16239+config AUFS_HFSNOTIFY
16240+ bool "fsnotify"
16241+ select FSNOTIFY
4a4d8108 16242+endchoice
1facf9fc 16243+
4a4d8108
AM
16244+config AUFS_EXPORT
16245+ bool "NFS-exportable aufs"
16246+ depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
16247+ help
16248+ If you want to export your mounted aufs via NFS, then enable this
16249+ option. There are several requirements for this configuration.
16250+ See detail in aufs.5.
1facf9fc 16251+
4a4d8108
AM
16252+config AUFS_INO_T_64
16253+ bool
16254+ depends on AUFS_EXPORT
16255+ depends on 64BIT && !(ALPHA || S390)
16256+ default y
16257+ help
16258+ Automatic configuration for internal use.
16259+ /* typedef unsigned long/int __kernel_ino_t */
16260+ /* alpha and s390x are int */
1facf9fc 16261+
4a4d8108
AM
16262+config AUFS_RDU
16263+ bool "Readdir in userspace"
16264+ help
16265+ Aufs has two methods to provide a merged view for a directory,
16266+ by a user-space library and by kernel-space natively. The latter
16267+ is always enabled but sometimes large and slow.
16268+ If you enable this option, install the library in aufs2-util
16269+ package, and set some environment variables for your readdir(3),
16270+ then the work will be handled in user-space which generally
16271+ shows better performance in most cases.
16272+ See detail in aufs.5.
1facf9fc 16273+
4a4d8108
AM
16274+config AUFS_SP_IATTR
16275+ bool "Respect the attributes (mtime/ctime mainly) of special files"
16276+ help
16277+ When you write something to a special file, some attributes of it
16278+ (mtime/ctime mainly) may be updated. Generally such updates are
16279+ less important (actually some device drivers and NFS ignore
16280+ it). But some applications (such like test program) requires
16281+ such updates. If you need these updates, then enable this
16282+ configuration which introduces some overhead.
16283+ Currently this configuration handles FIFO only.
1facf9fc 16284+
4a4d8108
AM
16285+config AUFS_SHWH
16286+ bool "Show whiteouts"
16287+ help
16288+ If you want to make the whiteouts in aufs visible, then enable
16289+ this option and specify 'shwh' mount option. Although it may
16290+ sounds like philosophy or something, but in technically it
16291+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 16292+
4a4d8108
AM
16293+config AUFS_BR_RAMFS
16294+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
16295+ help
16296+ If you want to use ramfs as an aufs branch fs, then enable this
16297+ option. Generally tmpfs is recommended.
16298+ Aufs prohibited them to be a branch fs by default, because
16299+ initramfs becomes unusable after switch_root or something
16300+ generally. If you sets initramfs as an aufs branch and boot your
16301+ system by switch_root, you will meet a problem easily since the
16302+ files in initramfs may be inaccessible.
16303+ Unless you are going to use ramfs as an aufs branch fs without
16304+ switch_root or something, leave it N.
1facf9fc 16305+
4a4d8108
AM
16306+config AUFS_BR_FUSE
16307+ bool "Fuse fs as an aufs branch"
16308+ depends on FUSE_FS
16309+ select AUFS_POLL
16310+ help
16311+ If you want to use fuse-based userspace filesystem as an aufs
16312+ branch fs, then enable this option.
16313+ It implements the internal poll(2) operation which is
16314+ implemented by fuse only (curretnly).
1facf9fc 16315+
4a4d8108
AM
16316+config AUFS_POLL
16317+ bool
16318+ help
16319+ Automatic configuration for internal use.
1facf9fc 16320+
4a4d8108
AM
16321+config AUFS_BR_HFSPLUS
16322+ bool "Hfsplus as an aufs branch"
16323+ depends on HFSPLUS_FS
16324+ default y
16325+ help
16326+ If you want to use hfsplus fs as an aufs branch fs, then enable
16327+ this option. This option introduces a small overhead at
16328+ copying-up a file on hfsplus.
1facf9fc 16329+
4a4d8108
AM
16330+config AUFS_BDEV_LOOP
16331+ bool
16332+ depends on BLK_DEV_LOOP
16333+ default y
16334+ help
16335+ Automatic configuration for internal use.
16336+ Convert =[ym] into =y.
1308ab2a 16337+
4a4d8108
AM
16338+config AUFS_DEBUG
16339+ bool "Debug aufs"
16340+ help
16341+ Enable this to compile aufs internal debug code.
16342+ It will have a negative impact to the performance.
16343+
16344+config AUFS_MAGIC_SYSRQ
16345+ bool
16346+ depends on AUFS_DEBUG && MAGIC_SYSRQ
16347+ default y
16348+ help
16349+ Automatic configuration for internal use.
16350+ When aufs supports Magic SysRq, enabled automatically.
16351+endif
7f207e10
AM
16352diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
16353--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
16354+++ linux/fs/aufs/loop.c 2010-11-22 11:52:56.990562128 +0100
b752ccd1 16355@@ -0,0 +1,63 @@
1facf9fc 16356+/*
4a4d8108 16357+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16358+ *
16359+ * This program, aufs is free software; you can redistribute it and/or modify
16360+ * it under the terms of the GNU General Public License as published by
16361+ * the Free Software Foundation; either version 2 of the License, or
16362+ * (at your option) any later version.
dece6358
AM
16363+ *
16364+ * This program is distributed in the hope that it will be useful,
16365+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16367+ * GNU General Public License for more details.
16368+ *
16369+ * You should have received a copy of the GNU General Public License
16370+ * along with this program; if not, write to the Free Software
16371+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16372+ */
16373+
16374+/*
16375+ * support for loopback block device as a branch
16376+ */
16377+
16378+#include <linux/loop.h>
16379+#include "aufs.h"
16380+
16381+/*
16382+ * test if two lower dentries have overlapping branches.
16383+ */
b752ccd1 16384+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 16385+{
b752ccd1 16386+ struct super_block *h_sb;
1facf9fc 16387+ struct loop_device *l;
16388+
b752ccd1
AM
16389+ h_sb = h_adding->d_sb;
16390+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 16391+ return 0;
16392+
b752ccd1
AM
16393+ l = h_sb->s_bdev->bd_disk->private_data;
16394+ h_adding = l->lo_backing_file->f_dentry;
16395+ /*
16396+ * h_adding can be local NFS.
16397+ * in this case aufs cannot detect the loop.
16398+ */
16399+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 16400+ return 1;
b752ccd1 16401+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 16402+}
16403+
16404+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
16405+int au_test_loopback_kthread(void)
16406+{
b752ccd1
AM
16407+ int ret;
16408+ struct task_struct *tsk = current;
16409+
16410+ ret = 0;
16411+ if (tsk->flags & PF_KTHREAD) {
16412+ const char c = tsk->comm[4];
16413+ ret = ('0' <= c && c <= '9'
16414+ && !strncmp(tsk->comm, "loop", 4));
16415+ }
1facf9fc 16416+
b752ccd1 16417+ return ret;
1facf9fc 16418+}
7f207e10
AM
16419diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
16420--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
16421+++ linux/fs/aufs/loop.h 2010-11-22 11:52:56.990562128 +0100
b752ccd1 16422@@ -0,0 +1,42 @@
1facf9fc 16423+/*
4a4d8108 16424+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16425+ *
16426+ * This program, aufs is free software; you can redistribute it and/or modify
16427+ * it under the terms of the GNU General Public License as published by
16428+ * the Free Software Foundation; either version 2 of the License, or
16429+ * (at your option) any later version.
dece6358
AM
16430+ *
16431+ * This program is distributed in the hope that it will be useful,
16432+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16433+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16434+ * GNU General Public License for more details.
16435+ *
16436+ * You should have received a copy of the GNU General Public License
16437+ * along with this program; if not, write to the Free Software
16438+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16439+ */
16440+
16441+/*
16442+ * support for loopback mount as a branch
16443+ */
16444+
16445+#ifndef __AUFS_LOOP_H__
16446+#define __AUFS_LOOP_H__
16447+
16448+#ifdef __KERNEL__
16449+
dece6358
AM
16450+struct dentry;
16451+struct super_block;
1facf9fc 16452+
16453+#ifdef CONFIG_AUFS_BDEV_LOOP
16454+/* loop.c */
b752ccd1 16455+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 16456+int au_test_loopback_kthread(void);
16457+#else
4a4d8108 16458+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 16459+ struct dentry *h_adding)
4a4d8108 16460+AuStubInt0(au_test_loopback_kthread, void)
1facf9fc 16461+#endif /* BLK_DEV_LOOP */
16462+
16463+#endif /* __KERNEL__ */
16464+#endif /* __AUFS_LOOP_H__ */
7f207e10
AM
16465diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
16466--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
16467+++ linux/fs/aufs/magic.mk 2010-11-22 11:52:56.990562128 +0100
4a4d8108 16468@@ -0,0 +1,54 @@
1facf9fc 16469+
16470+# defined in ${srctree}/fs/fuse/inode.c
16471+# tristate
16472+ifdef CONFIG_FUSE_FS
16473+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
16474+endif
16475+
16476+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
16477+# tristate
16478+ifdef CONFIG_OCFS2_FS
16479+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
16480+endif
16481+
16482+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
16483+# tristate
16484+ifdef CONFIG_OCFS2_FS_O2CB
16485+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
16486+endif
16487+
1facf9fc 16488+# defined in ${srctree}/fs/cifs/cifsfs.c
16489+# tristate
16490+ifdef CONFIG_CIFS_FS
16491+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
16492+endif
16493+
16494+# defined in ${srctree}/fs/xfs/xfs_sb.h
16495+# tristate
16496+ifdef CONFIG_XFS_FS
16497+ccflags-y += -DXFS_SB_MAGIC=0x58465342
16498+endif
16499+
16500+# defined in ${srctree}/fs/configfs/mount.c
16501+# tristate
16502+ifdef CONFIG_CONFIGFS_FS
16503+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
16504+endif
16505+
16506+# defined in ${srctree}/fs/9p/v9fs.h
16507+# tristate
16508+ifdef CONFIG_9P_FS
16509+ccflags-y += -DV9FS_MAGIC=0x01021997
16510+endif
16511+
16512+# defined in ${srctree}/fs/ubifs/ubifs.h
16513+# tristate
16514+ifdef CONFIG_UBIFS_FS
16515+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
16516+endif
4a4d8108
AM
16517+
16518+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
16519+# tristate
16520+ifdef CONFIG_HFSPLUS_FS
16521+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
16522+endif
7f207e10
AM
16523diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
16524--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
16525+++ linux/fs/aufs/Makefile 2010-11-22 11:52:56.983894369 +0100
16526@@ -0,0 +1,38 @@
4a4d8108
AM
16527+
16528+include ${src}/magic.mk
16529+ifeq (${CONFIG_AUFS_FS},m)
16530+include ${src}/conf.mk
16531+endif
16532+-include ${src}/priv_def.mk
16533+
16534+# cf. include/linux/kernel.h
16535+# enable pr_debug
16536+ccflags-y += -DDEBUG
7f207e10
AM
16537+# sparse doesn't allow spaces
16538+ccflags-y += -D'pr_fmt(fmt)=AUFS_NAME"\040%s:%d:%s[%d]:\040"fmt,__func__,__LINE__,current->comm,current->pid'
4a4d8108
AM
16539+
16540+obj-$(CONFIG_AUFS_FS) += aufs.o
16541+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
16542+ wkq.o vfsub.o dcsub.o \
e49829fe 16543+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
16544+ dinfo.o dentry.o \
16545+ dynop.o \
16546+ finfo.o file.o f_op.o \
16547+ dir.o vdir.o \
16548+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
16549+ ioctl.o
16550+
16551+# all are boolean
e49829fe 16552+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
16553+aufs-$(CONFIG_SYSFS) += sysfs.o
16554+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
16555+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
16556+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
16557+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108
AM
16558+aufs-$(CONFIG_AUFS_EXPORT) += export.o
16559+aufs-$(CONFIG_AUFS_POLL) += poll.o
16560+aufs-$(CONFIG_AUFS_RDU) += rdu.o
16561+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
16562+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
16563+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
16564+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10
AM
16565diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
16566--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
16567+++ linux/fs/aufs/module.c 2010-11-22 11:52:56.990562128 +0100
e49829fe 16568@@ -0,0 +1,182 @@
1facf9fc 16569+/*
4a4d8108 16570+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16571+ *
16572+ * This program, aufs is free software; you can redistribute it and/or modify
16573+ * it under the terms of the GNU General Public License as published by
16574+ * the Free Software Foundation; either version 2 of the License, or
16575+ * (at your option) any later version.
dece6358
AM
16576+ *
16577+ * This program is distributed in the hope that it will be useful,
16578+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16579+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16580+ * GNU General Public License for more details.
16581+ *
16582+ * You should have received a copy of the GNU General Public License
16583+ * along with this program; if not, write to the Free Software
16584+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16585+ */
16586+
16587+/*
16588+ * module global variables and operations
16589+ */
16590+
16591+#include <linux/module.h>
16592+#include <linux/seq_file.h>
16593+#include "aufs.h"
16594+
16595+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
16596+{
16597+ if (new_sz <= nused)
16598+ return p;
16599+
16600+ p = krealloc(p, new_sz, gfp);
16601+ if (p)
16602+ memset(p + nused, 0, new_sz - nused);
16603+ return p;
16604+}
16605+
16606+/* ---------------------------------------------------------------------- */
16607+
16608+/*
16609+ * aufs caches
16610+ */
16611+struct kmem_cache *au_cachep[AuCache_Last];
16612+static int __init au_cache_init(void)
16613+{
4a4d8108 16614+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 16615+ if (au_cachep[AuCache_DINFO])
4a4d8108
AM
16616+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
16617+ au_icntnr_init_once);
1facf9fc 16618+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
16619+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
16620+ au_fi_init_once);
1facf9fc 16621+ if (au_cachep[AuCache_FINFO])
16622+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
16623+ if (au_cachep[AuCache_VDIR])
16624+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
16625+ if (au_cachep[AuCache_DEHSTR])
16626+ return 0;
16627+
16628+ return -ENOMEM;
16629+}
16630+
16631+static void au_cache_fin(void)
16632+{
16633+ int i;
4a4d8108
AM
16634+
16635+ /* including AuCache_HNOTIFY */
1facf9fc 16636+ for (i = 0; i < AuCache_Last; i++)
16637+ if (au_cachep[i]) {
16638+ kmem_cache_destroy(au_cachep[i]);
16639+ au_cachep[i] = NULL;
16640+ }
16641+}
16642+
16643+/* ---------------------------------------------------------------------- */
16644+
16645+int au_dir_roflags;
16646+
e49829fe
JR
16647+#ifdef CONFIG_AUFS_SBILIST
16648+struct au_splhead au_sbilist;
16649+#endif
16650+
1facf9fc 16651+/*
16652+ * functions for module interface.
16653+ */
16654+MODULE_LICENSE("GPL");
16655+/* MODULE_LICENSE("GPL v2"); */
dece6358 16656+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 16657+MODULE_DESCRIPTION(AUFS_NAME
16658+ " -- Advanced multi layered unification filesystem");
16659+MODULE_VERSION(AUFS_VERSION);
16660+
1facf9fc 16661+/* this module parameter has no meaning when SYSFS is disabled */
16662+int sysaufs_brs = 1;
16663+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
16664+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
16665+
16666+/* ---------------------------------------------------------------------- */
16667+
16668+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
16669+
16670+int au_seq_path(struct seq_file *seq, struct path *path)
16671+{
16672+ return seq_path(seq, path, au_esc_chars);
16673+}
16674+
16675+/* ---------------------------------------------------------------------- */
16676+
16677+static int __init aufs_init(void)
16678+{
16679+ int err, i;
16680+ char *p;
16681+
16682+ p = au_esc_chars;
16683+ for (i = 1; i <= ' '; i++)
16684+ *p++ = i;
16685+ *p++ = '\\';
16686+ *p++ = '\x7f';
16687+ *p = 0;
16688+
16689+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
16690+
e49829fe 16691+ au_sbilist_init();
1facf9fc 16692+ sysaufs_brs_init();
16693+ au_debug_init();
4a4d8108 16694+ au_dy_init();
1facf9fc 16695+ err = sysaufs_init();
16696+ if (unlikely(err))
16697+ goto out;
e49829fe 16698+ err = au_procfs_init();
4f0767ce 16699+ if (unlikely(err))
953406b4 16700+ goto out_sysaufs;
e49829fe
JR
16701+ err = au_wkq_init();
16702+ if (unlikely(err))
16703+ goto out_procfs;
4a4d8108 16704+ err = au_hnotify_init();
1facf9fc 16705+ if (unlikely(err))
16706+ goto out_wkq;
16707+ err = au_sysrq_init();
16708+ if (unlikely(err))
16709+ goto out_hin;
16710+ err = au_cache_init();
16711+ if (unlikely(err))
16712+ goto out_sysrq;
16713+ err = register_filesystem(&aufs_fs_type);
16714+ if (unlikely(err))
16715+ goto out_cache;
4a4d8108
AM
16716+ /* since we define pr_fmt, call printk directly */
16717+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 16718+ goto out; /* success */
16719+
4f0767ce 16720+out_cache:
1facf9fc 16721+ au_cache_fin();
4f0767ce 16722+out_sysrq:
1facf9fc 16723+ au_sysrq_fin();
4f0767ce 16724+out_hin:
4a4d8108 16725+ au_hnotify_fin();
4f0767ce 16726+out_wkq:
1facf9fc 16727+ au_wkq_fin();
e49829fe
JR
16728+out_procfs:
16729+ au_procfs_fin();
4f0767ce 16730+out_sysaufs:
1facf9fc 16731+ sysaufs_fin();
4a4d8108 16732+ au_dy_fin();
4f0767ce 16733+out:
1facf9fc 16734+ return err;
16735+}
16736+
16737+static void __exit aufs_exit(void)
16738+{
16739+ unregister_filesystem(&aufs_fs_type);
16740+ au_cache_fin();
16741+ au_sysrq_fin();
4a4d8108 16742+ au_hnotify_fin();
1facf9fc 16743+ au_wkq_fin();
e49829fe 16744+ au_procfs_fin();
1facf9fc 16745+ sysaufs_fin();
4a4d8108 16746+ au_dy_fin();
1facf9fc 16747+}
16748+
16749+module_init(aufs_init);
16750+module_exit(aufs_exit);
7f207e10
AM
16751diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
16752--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
16753+++ linux/fs/aufs/module.h 2010-11-22 11:52:56.990562128 +0100
e49829fe 16754@@ -0,0 +1,91 @@
1facf9fc 16755+/*
4a4d8108 16756+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16757+ *
16758+ * This program, aufs is free software; you can redistribute it and/or modify
16759+ * it under the terms of the GNU General Public License as published by
16760+ * the Free Software Foundation; either version 2 of the License, or
16761+ * (at your option) any later version.
dece6358
AM
16762+ *
16763+ * This program is distributed in the hope that it will be useful,
16764+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16765+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16766+ * GNU General Public License for more details.
16767+ *
16768+ * You should have received a copy of the GNU General Public License
16769+ * along with this program; if not, write to the Free Software
16770+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16771+ */
16772+
16773+/*
16774+ * module initialization and module-global
16775+ */
16776+
16777+#ifndef __AUFS_MODULE_H__
16778+#define __AUFS_MODULE_H__
16779+
16780+#ifdef __KERNEL__
16781+
16782+#include <linux/slab.h>
16783+
dece6358
AM
16784+struct path;
16785+struct seq_file;
16786+
1facf9fc 16787+/* module parameters */
1facf9fc 16788+extern int sysaufs_brs;
16789+
16790+/* ---------------------------------------------------------------------- */
16791+
16792+extern int au_dir_roflags;
16793+
16794+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
16795+int au_seq_path(struct seq_file *seq, struct path *path);
16796+
e49829fe
JR
16797+#ifdef CONFIG_PROC_FS
16798+/* procfs.c */
16799+int __init au_procfs_init(void);
16800+void au_procfs_fin(void);
16801+#else
16802+AuStubInt0(au_procfs_init, void);
16803+AuStubVoid(au_procfs_fin, void);
16804+#endif
16805+
4f0767ce
JR
16806+/* ---------------------------------------------------------------------- */
16807+
16808+/* kmem cache */
1facf9fc 16809+enum {
16810+ AuCache_DINFO,
16811+ AuCache_ICNTNR,
16812+ AuCache_FINFO,
16813+ AuCache_VDIR,
16814+ AuCache_DEHSTR,
4a4d8108
AM
16815+#ifdef CONFIG_AUFS_HNOTIFY
16816+ AuCache_HNOTIFY,
1facf9fc 16817+#endif
16818+ AuCache_Last
16819+};
16820+
4a4d8108
AM
16821+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
16822+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
16823+#define AuCacheCtor(type, ctor) \
16824+ kmem_cache_create(#type, sizeof(struct type), \
16825+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 16826+
16827+extern struct kmem_cache *au_cachep[];
16828+
16829+#define AuCacheFuncs(name, index) \
4a4d8108 16830+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 16831+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 16832+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 16833+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
16834+
16835+AuCacheFuncs(dinfo, DINFO);
16836+AuCacheFuncs(icntnr, ICNTNR);
16837+AuCacheFuncs(finfo, FINFO);
16838+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
16839+AuCacheFuncs(vdir_dehstr, DEHSTR);
16840+#ifdef CONFIG_AUFS_HNOTIFY
16841+AuCacheFuncs(hnotify, HNOTIFY);
16842+#endif
1facf9fc 16843+
4a4d8108
AM
16844+#endif /* __KERNEL__ */
16845+#endif /* __AUFS_MODULE_H__ */
7f207e10
AM
16846diff -urN /usr/share/empty/fs/aufs/mtx.h linux/fs/aufs/mtx.h
16847--- /usr/share/empty/fs/aufs/mtx.h 1970-01-01 01:00:00.000000000 +0100
16848+++ linux/fs/aufs/mtx.h 2010-11-22 11:52:56.990562128 +0100
4a4d8108
AM
16849@@ -0,0 +1,48 @@
16850+/*
16851+ * Copyright (C) 2010 Junjiro R. Okajima
16852+ *
16853+ * This program, aufs is free software; you can redistribute it and/or modify
16854+ * it under the terms of the GNU General Public License as published by
16855+ * the Free Software Foundation; either version 2 of the License, or
16856+ * (at your option) any later version.
16857+ *
16858+ * This program is distributed in the hope that it will be useful,
16859+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16860+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16861+ * GNU General Public License for more details.
16862+ *
16863+ * You should have received a copy of the GNU General Public License
16864+ * along with this program; if not, write to the Free Software
16865+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16866+ */
16867+
16868+/*
16869+ * very ugly approach for aufs_mmap()
16870+ * never include this file from other than f_op.c.
16871+ * see f_op.c in detail.
16872+ */
16873+
16874+#ifndef __AUFS_MTX_H__
16875+#define __AUFS_MTX_H__
16876+
16877+#ifdef __KERNEL__
16878+
16879+/* copied from ../kernel/mutex{,-debug}.h */
16880+struct mutex;
16881+struct thread_info;
16882+#ifdef CONFIG_DEBUG_MUTEXES
16883+static inline void mutex_set_owner(struct mutex *lock)
16884+{
16885+ lock->owner = current_thread_info();
16886+}
16887+#else
16888+static inline void mutex_set_owner(struct mutex *lock)
16889+{
16890+#ifdef CONFIG_SMP
16891+ lock->owner = current_thread_info();
16892+#endif
16893+}
16894+#endif
1facf9fc 16895+
16896+#endif /* __KERNEL__ */
4a4d8108 16897+#endif /* __AUFS_MTX_H__ */
7f207e10
AM
16898diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
16899--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
16900+++ linux/fs/aufs/opts.c 2010-11-22 11:52:56.990562128 +0100
16901@@ -0,0 +1,1581 @@
1facf9fc 16902+/*
4a4d8108 16903+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16904+ *
16905+ * This program, aufs is free software; you can redistribute it and/or modify
16906+ * it under the terms of the GNU General Public License as published by
16907+ * the Free Software Foundation; either version 2 of the License, or
16908+ * (at your option) any later version.
dece6358
AM
16909+ *
16910+ * This program is distributed in the hope that it will be useful,
16911+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16912+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16913+ * GNU General Public License for more details.
16914+ *
16915+ * You should have received a copy of the GNU General Public License
16916+ * along with this program; if not, write to the Free Software
16917+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16918+ */
16919+
16920+/*
16921+ * mount options/flags
16922+ */
16923+
dece6358 16924+#include <linux/file.h>
e49829fe 16925+#include <linux/jiffies.h>
dece6358 16926+#include <linux/namei.h>
1facf9fc 16927+#include <linux/types.h> /* a distribution requires */
16928+#include <linux/parser.h>
16929+#include "aufs.h"
16930+
16931+/* ---------------------------------------------------------------------- */
16932+
16933+enum {
16934+ Opt_br,
16935+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
16936+ Opt_idel, Opt_imod, Opt_ireorder,
16937+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 16938+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 16939+ Opt_xino, Opt_zxino, Opt_noxino,
16940+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
16941+ Opt_trunc_xino_path, Opt_itrunc_xino,
16942+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 16943+ Opt_shwh, Opt_noshwh,
1facf9fc 16944+ Opt_plink, Opt_noplink, Opt_list_plink,
16945+ Opt_udba,
4a4d8108 16946+ Opt_dio, Opt_nodio,
1facf9fc 16947+ /* Opt_lock, Opt_unlock, */
16948+ Opt_cmd, Opt_cmd_args,
16949+ Opt_diropq_a, Opt_diropq_w,
16950+ Opt_warn_perm, Opt_nowarn_perm,
16951+ Opt_wbr_copyup, Opt_wbr_create,
16952+ Opt_refrof, Opt_norefrof,
16953+ Opt_verbose, Opt_noverbose,
16954+ Opt_sum, Opt_nosum, Opt_wsum,
16955+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
16956+};
16957+
16958+static match_table_t options = {
16959+ {Opt_br, "br=%s"},
16960+ {Opt_br, "br:%s"},
16961+
16962+ {Opt_add, "add=%d:%s"},
16963+ {Opt_add, "add:%d:%s"},
16964+ {Opt_add, "ins=%d:%s"},
16965+ {Opt_add, "ins:%d:%s"},
16966+ {Opt_append, "append=%s"},
16967+ {Opt_append, "append:%s"},
16968+ {Opt_prepend, "prepend=%s"},
16969+ {Opt_prepend, "prepend:%s"},
16970+
16971+ {Opt_del, "del=%s"},
16972+ {Opt_del, "del:%s"},
16973+ /* {Opt_idel, "idel:%d"}, */
16974+ {Opt_mod, "mod=%s"},
16975+ {Opt_mod, "mod:%s"},
16976+ /* {Opt_imod, "imod:%d:%s"}, */
16977+
16978+ {Opt_dirwh, "dirwh=%d"},
16979+
16980+ {Opt_xino, "xino=%s"},
16981+ {Opt_noxino, "noxino"},
16982+ {Opt_trunc_xino, "trunc_xino"},
16983+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
16984+ {Opt_notrunc_xino, "notrunc_xino"},
16985+ {Opt_trunc_xino_path, "trunc_xino=%s"},
16986+ {Opt_itrunc_xino, "itrunc_xino=%d"},
16987+ /* {Opt_zxino, "zxino=%s"}, */
16988+ {Opt_trunc_xib, "trunc_xib"},
16989+ {Opt_notrunc_xib, "notrunc_xib"},
16990+
e49829fe 16991+#ifdef CONFIG_PROC_FS
1facf9fc 16992+ {Opt_plink, "plink"},
e49829fe
JR
16993+#else
16994+ {Opt_ignore_silent, "plink"},
16995+#endif
16996+
1facf9fc 16997+ {Opt_noplink, "noplink"},
e49829fe 16998+
1facf9fc 16999+#ifdef CONFIG_AUFS_DEBUG
17000+ {Opt_list_plink, "list_plink"},
17001+#endif
17002+
17003+ {Opt_udba, "udba=%s"},
17004+
4a4d8108
AM
17005+ {Opt_dio, "dio"},
17006+ {Opt_nodio, "nodio"},
17007+
1facf9fc 17008+ {Opt_diropq_a, "diropq=always"},
17009+ {Opt_diropq_a, "diropq=a"},
17010+ {Opt_diropq_w, "diropq=whiteouted"},
17011+ {Opt_diropq_w, "diropq=w"},
17012+
17013+ {Opt_warn_perm, "warn_perm"},
17014+ {Opt_nowarn_perm, "nowarn_perm"},
17015+
17016+ /* keep them temporary */
17017+ {Opt_ignore_silent, "coo=%s"},
17018+ {Opt_ignore_silent, "nodlgt"},
17019+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 17020+ {Opt_ignore_silent, "clean_plink"},
17021+
dece6358
AM
17022+#ifdef CONFIG_AUFS_SHWH
17023+ {Opt_shwh, "shwh"},
17024+#endif
17025+ {Opt_noshwh, "noshwh"},
17026+
1facf9fc 17027+ {Opt_rendir, "rendir=%d"},
17028+
17029+ {Opt_refrof, "refrof"},
17030+ {Opt_norefrof, "norefrof"},
17031+
17032+ {Opt_verbose, "verbose"},
17033+ {Opt_verbose, "v"},
17034+ {Opt_noverbose, "noverbose"},
17035+ {Opt_noverbose, "quiet"},
17036+ {Opt_noverbose, "q"},
17037+ {Opt_noverbose, "silent"},
17038+
17039+ {Opt_sum, "sum"},
17040+ {Opt_nosum, "nosum"},
17041+ {Opt_wsum, "wsum"},
17042+
17043+ {Opt_rdcache, "rdcache=%d"},
17044+ {Opt_rdblk, "rdblk=%d"},
dece6358 17045+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 17046+ {Opt_rdhash, "rdhash=%d"},
dece6358 17047+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 17048+
17049+ {Opt_wbr_create, "create=%s"},
17050+ {Opt_wbr_create, "create_policy=%s"},
17051+ {Opt_wbr_copyup, "cpup=%s"},
17052+ {Opt_wbr_copyup, "copyup=%s"},
17053+ {Opt_wbr_copyup, "copyup_policy=%s"},
17054+
17055+ /* internal use for the scripts */
17056+ {Opt_ignore_silent, "si=%s"},
17057+
17058+ {Opt_br, "dirs=%s"},
17059+ {Opt_ignore, "debug=%d"},
17060+ {Opt_ignore, "delete=whiteout"},
17061+ {Opt_ignore, "delete=all"},
17062+ {Opt_ignore, "imap=%s"},
17063+
1308ab2a 17064+ /* temporary workaround, due to old mount(8)? */
17065+ {Opt_ignore_silent, "relatime"},
17066+
1facf9fc 17067+ {Opt_err, NULL}
17068+};
17069+
17070+/* ---------------------------------------------------------------------- */
17071+
17072+static const char *au_parser_pattern(int val, struct match_token *token)
17073+{
17074+ while (token->pattern) {
17075+ if (token->token == val)
17076+ return token->pattern;
17077+ token++;
17078+ }
17079+ BUG();
17080+ return "??";
17081+}
17082+
17083+/* ---------------------------------------------------------------------- */
17084+
17085+static match_table_t brperms = {
17086+ {AuBrPerm_RO, AUFS_BRPERM_RO},
17087+ {AuBrPerm_RR, AUFS_BRPERM_RR},
17088+ {AuBrPerm_RW, AUFS_BRPERM_RW},
17089+
17090+ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
17091+ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
17092+ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
17093+
17094+ {AuBrPerm_ROWH, "nfsro"},
17095+ {AuBrPerm_RO, NULL}
17096+};
17097+
4a4d8108 17098+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 17099+{
17100+ int val;
17101+ substring_t args[MAX_OPT_ARGS];
17102+
17103+ val = match_token(perm, brperms, args);
17104+ return val;
17105+}
17106+
17107+const char *au_optstr_br_perm(int brperm)
17108+{
17109+ return au_parser_pattern(brperm, (void *)brperms);
17110+}
17111+
17112+/* ---------------------------------------------------------------------- */
17113+
17114+static match_table_t udbalevel = {
17115+ {AuOpt_UDBA_REVAL, "reval"},
17116+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
17117+#ifdef CONFIG_AUFS_HNOTIFY
17118+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
17119+#ifdef CONFIG_AUFS_HFSNOTIFY
17120+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 17121+#endif
1facf9fc 17122+#endif
17123+ {-1, NULL}
17124+};
17125+
4a4d8108 17126+static int noinline_for_stack udba_val(char *str)
1facf9fc 17127+{
17128+ substring_t args[MAX_OPT_ARGS];
17129+
7f207e10 17130+ return match_token(str, udbalevel, args);
1facf9fc 17131+}
17132+
17133+const char *au_optstr_udba(int udba)
17134+{
17135+ return au_parser_pattern(udba, (void *)udbalevel);
17136+}
17137+
17138+/* ---------------------------------------------------------------------- */
17139+
17140+static match_table_t au_wbr_create_policy = {
17141+ {AuWbrCreate_TDP, "tdp"},
17142+ {AuWbrCreate_TDP, "top-down-parent"},
17143+ {AuWbrCreate_RR, "rr"},
17144+ {AuWbrCreate_RR, "round-robin"},
17145+ {AuWbrCreate_MFS, "mfs"},
17146+ {AuWbrCreate_MFS, "most-free-space"},
17147+ {AuWbrCreate_MFSV, "mfs:%d"},
17148+ {AuWbrCreate_MFSV, "most-free-space:%d"},
17149+
17150+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
17151+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
17152+ {AuWbrCreate_PMFS, "pmfs"},
17153+ {AuWbrCreate_PMFSV, "pmfs:%d"},
17154+
17155+ {-1, NULL}
17156+};
17157+
dece6358
AM
17158+/*
17159+ * cf. linux/lib/parser.c and cmdline.c
17160+ * gave up calling memparse() since it uses simple_strtoull() instead of
17161+ * strict_...().
17162+ */
4a4d8108
AM
17163+static int noinline_for_stack
17164+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 17165+{
17166+ int err;
17167+ unsigned int len;
17168+ char a[32];
17169+
17170+ err = -ERANGE;
17171+ len = s->to - s->from;
17172+ if (len + 1 <= sizeof(a)) {
17173+ memcpy(a, s->from, len);
17174+ a[len] = '\0';
17175+ err = strict_strtoull(a, 0, result);
17176+ }
17177+ return err;
17178+}
17179+
17180+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
17181+ struct au_opt_wbr_create *create)
17182+{
17183+ int err;
17184+ unsigned long long ull;
17185+
17186+ err = 0;
17187+ if (!au_match_ull(arg, &ull))
17188+ create->mfsrr_watermark = ull;
17189+ else {
4a4d8108 17190+ pr_err("bad integer in %s\n", str);
1facf9fc 17191+ err = -EINVAL;
17192+ }
17193+
17194+ return err;
17195+}
17196+
17197+static int au_wbr_mfs_sec(substring_t *arg, char *str,
17198+ struct au_opt_wbr_create *create)
17199+{
17200+ int n, err;
17201+
17202+ err = 0;
e49829fe 17203+ if (!match_int(arg, &n) && 0 <= n && n <= MAX_SEC_IN_JIFFIES)
1facf9fc 17204+ create->mfs_second = n;
17205+ else {
4a4d8108 17206+ pr_err("bad integer in %s\n", str);
1facf9fc 17207+ err = -EINVAL;
17208+ }
17209+
17210+ return err;
17211+}
17212+
4a4d8108
AM
17213+static int noinline_for_stack
17214+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 17215+{
17216+ int err, e;
17217+ substring_t args[MAX_OPT_ARGS];
17218+
17219+ err = match_token(str, au_wbr_create_policy, args);
17220+ create->wbr_create = err;
17221+ switch (err) {
17222+ case AuWbrCreate_MFSRRV:
17223+ e = au_wbr_mfs_wmark(&args[0], str, create);
17224+ if (!e)
17225+ e = au_wbr_mfs_sec(&args[1], str, create);
17226+ if (unlikely(e))
17227+ err = e;
17228+ break;
17229+ case AuWbrCreate_MFSRR:
17230+ e = au_wbr_mfs_wmark(&args[0], str, create);
17231+ if (unlikely(e)) {
17232+ err = e;
17233+ break;
17234+ }
17235+ /*FALLTHROUGH*/
17236+ case AuWbrCreate_MFS:
17237+ case AuWbrCreate_PMFS:
17238+ create->mfs_second = AUFS_MFS_SECOND_DEF;
17239+ break;
17240+ case AuWbrCreate_MFSV:
17241+ case AuWbrCreate_PMFSV:
17242+ e = au_wbr_mfs_sec(&args[0], str, create);
17243+ if (unlikely(e))
17244+ err = e;
17245+ break;
17246+ }
17247+
17248+ return err;
17249+}
17250+
17251+const char *au_optstr_wbr_create(int wbr_create)
17252+{
17253+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
17254+}
17255+
17256+static match_table_t au_wbr_copyup_policy = {
17257+ {AuWbrCopyup_TDP, "tdp"},
17258+ {AuWbrCopyup_TDP, "top-down-parent"},
17259+ {AuWbrCopyup_BUP, "bup"},
17260+ {AuWbrCopyup_BUP, "bottom-up-parent"},
17261+ {AuWbrCopyup_BU, "bu"},
17262+ {AuWbrCopyup_BU, "bottom-up"},
17263+ {-1, NULL}
17264+};
17265+
4a4d8108 17266+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 17267+{
17268+ substring_t args[MAX_OPT_ARGS];
17269+
17270+ return match_token(str, au_wbr_copyup_policy, args);
17271+}
17272+
17273+const char *au_optstr_wbr_copyup(int wbr_copyup)
17274+{
17275+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
17276+}
17277+
17278+/* ---------------------------------------------------------------------- */
17279+
17280+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
17281+
17282+static void dump_opts(struct au_opts *opts)
17283+{
17284+#ifdef CONFIG_AUFS_DEBUG
17285+ /* reduce stack space */
17286+ union {
17287+ struct au_opt_add *add;
17288+ struct au_opt_del *del;
17289+ struct au_opt_mod *mod;
17290+ struct au_opt_xino *xino;
17291+ struct au_opt_xino_itrunc *xino_itrunc;
17292+ struct au_opt_wbr_create *create;
17293+ } u;
17294+ struct au_opt *opt;
17295+
17296+ opt = opts->opt;
17297+ while (opt->type != Opt_tail) {
17298+ switch (opt->type) {
17299+ case Opt_add:
17300+ u.add = &opt->add;
17301+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
17302+ u.add->bindex, u.add->pathname, u.add->perm,
17303+ u.add->path.dentry);
17304+ break;
17305+ case Opt_del:
17306+ case Opt_idel:
17307+ u.del = &opt->del;
17308+ AuDbg("del {%s, %p}\n",
17309+ u.del->pathname, u.del->h_path.dentry);
17310+ break;
17311+ case Opt_mod:
17312+ case Opt_imod:
17313+ u.mod = &opt->mod;
17314+ AuDbg("mod {%s, 0x%x, %p}\n",
17315+ u.mod->path, u.mod->perm, u.mod->h_root);
17316+ break;
17317+ case Opt_append:
17318+ u.add = &opt->add;
17319+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
17320+ u.add->bindex, u.add->pathname, u.add->perm,
17321+ u.add->path.dentry);
17322+ break;
17323+ case Opt_prepend:
17324+ u.add = &opt->add;
17325+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
17326+ u.add->bindex, u.add->pathname, u.add->perm,
17327+ u.add->path.dentry);
17328+ break;
17329+ case Opt_dirwh:
17330+ AuDbg("dirwh %d\n", opt->dirwh);
17331+ break;
17332+ case Opt_rdcache:
17333+ AuDbg("rdcache %d\n", opt->rdcache);
17334+ break;
17335+ case Opt_rdblk:
17336+ AuDbg("rdblk %u\n", opt->rdblk);
17337+ break;
dece6358
AM
17338+ case Opt_rdblk_def:
17339+ AuDbg("rdblk_def\n");
17340+ break;
1facf9fc 17341+ case Opt_rdhash:
17342+ AuDbg("rdhash %u\n", opt->rdhash);
17343+ break;
dece6358
AM
17344+ case Opt_rdhash_def:
17345+ AuDbg("rdhash_def\n");
17346+ break;
1facf9fc 17347+ case Opt_xino:
17348+ u.xino = &opt->xino;
17349+ AuDbg("xino {%s %.*s}\n",
17350+ u.xino->path,
17351+ AuDLNPair(u.xino->file->f_dentry));
17352+ break;
17353+ case Opt_trunc_xino:
17354+ AuLabel(trunc_xino);
17355+ break;
17356+ case Opt_notrunc_xino:
17357+ AuLabel(notrunc_xino);
17358+ break;
17359+ case Opt_trunc_xino_path:
17360+ case Opt_itrunc_xino:
17361+ u.xino_itrunc = &opt->xino_itrunc;
17362+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
17363+ break;
17364+
17365+ case Opt_noxino:
17366+ AuLabel(noxino);
17367+ break;
17368+ case Opt_trunc_xib:
17369+ AuLabel(trunc_xib);
17370+ break;
17371+ case Opt_notrunc_xib:
17372+ AuLabel(notrunc_xib);
17373+ break;
dece6358
AM
17374+ case Opt_shwh:
17375+ AuLabel(shwh);
17376+ break;
17377+ case Opt_noshwh:
17378+ AuLabel(noshwh);
17379+ break;
1facf9fc 17380+ case Opt_plink:
17381+ AuLabel(plink);
17382+ break;
17383+ case Opt_noplink:
17384+ AuLabel(noplink);
17385+ break;
17386+ case Opt_list_plink:
17387+ AuLabel(list_plink);
17388+ break;
17389+ case Opt_udba:
17390+ AuDbg("udba %d, %s\n",
17391+ opt->udba, au_optstr_udba(opt->udba));
17392+ break;
4a4d8108
AM
17393+ case Opt_dio:
17394+ AuLabel(dio);
17395+ break;
17396+ case Opt_nodio:
17397+ AuLabel(nodio);
17398+ break;
1facf9fc 17399+ case Opt_diropq_a:
17400+ AuLabel(diropq_a);
17401+ break;
17402+ case Opt_diropq_w:
17403+ AuLabel(diropq_w);
17404+ break;
17405+ case Opt_warn_perm:
17406+ AuLabel(warn_perm);
17407+ break;
17408+ case Opt_nowarn_perm:
17409+ AuLabel(nowarn_perm);
17410+ break;
17411+ case Opt_refrof:
17412+ AuLabel(refrof);
17413+ break;
17414+ case Opt_norefrof:
17415+ AuLabel(norefrof);
17416+ break;
17417+ case Opt_verbose:
17418+ AuLabel(verbose);
17419+ break;
17420+ case Opt_noverbose:
17421+ AuLabel(noverbose);
17422+ break;
17423+ case Opt_sum:
17424+ AuLabel(sum);
17425+ break;
17426+ case Opt_nosum:
17427+ AuLabel(nosum);
17428+ break;
17429+ case Opt_wsum:
17430+ AuLabel(wsum);
17431+ break;
17432+ case Opt_wbr_create:
17433+ u.create = &opt->wbr_create;
17434+ AuDbg("create %d, %s\n", u.create->wbr_create,
17435+ au_optstr_wbr_create(u.create->wbr_create));
17436+ switch (u.create->wbr_create) {
17437+ case AuWbrCreate_MFSV:
17438+ case AuWbrCreate_PMFSV:
17439+ AuDbg("%d sec\n", u.create->mfs_second);
17440+ break;
17441+ case AuWbrCreate_MFSRR:
17442+ AuDbg("%llu watermark\n",
17443+ u.create->mfsrr_watermark);
17444+ break;
17445+ case AuWbrCreate_MFSRRV:
17446+ AuDbg("%llu watermark, %d sec\n",
17447+ u.create->mfsrr_watermark,
17448+ u.create->mfs_second);
17449+ break;
17450+ }
17451+ break;
17452+ case Opt_wbr_copyup:
17453+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
17454+ au_optstr_wbr_copyup(opt->wbr_copyup));
17455+ break;
17456+ default:
17457+ BUG();
17458+ }
17459+ opt++;
17460+ }
17461+#endif
17462+}
17463+
17464+void au_opts_free(struct au_opts *opts)
17465+{
17466+ struct au_opt *opt;
17467+
17468+ opt = opts->opt;
17469+ while (opt->type != Opt_tail) {
17470+ switch (opt->type) {
17471+ case Opt_add:
17472+ case Opt_append:
17473+ case Opt_prepend:
17474+ path_put(&opt->add.path);
17475+ break;
17476+ case Opt_del:
17477+ case Opt_idel:
17478+ path_put(&opt->del.h_path);
17479+ break;
17480+ case Opt_mod:
17481+ case Opt_imod:
17482+ dput(opt->mod.h_root);
17483+ break;
17484+ case Opt_xino:
17485+ fput(opt->xino.file);
17486+ break;
17487+ }
17488+ opt++;
17489+ }
17490+}
17491+
17492+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
17493+ aufs_bindex_t bindex)
17494+{
17495+ int err;
17496+ struct au_opt_add *add = &opt->add;
17497+ char *p;
17498+
17499+ add->bindex = bindex;
17500+ add->perm = AuBrPerm_Last;
17501+ add->pathname = opt_str;
17502+ p = strchr(opt_str, '=');
17503+ if (p) {
17504+ *p++ = 0;
17505+ if (*p)
17506+ add->perm = br_perm_val(p);
17507+ }
17508+
17509+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
17510+ if (!err) {
17511+ if (!p) {
17512+ add->perm = AuBrPerm_RO;
17513+ if (au_test_fs_rr(add->path.dentry->d_sb))
17514+ add->perm = AuBrPerm_RR;
17515+ else if (!bindex && !(sb_flags & MS_RDONLY))
17516+ add->perm = AuBrPerm_RW;
17517+ }
17518+ opt->type = Opt_add;
17519+ goto out;
17520+ }
4a4d8108 17521+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 17522+ err = -EINVAL;
17523+
4f0767ce 17524+out:
1facf9fc 17525+ return err;
17526+}
17527+
17528+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
17529+{
17530+ int err;
17531+
17532+ del->pathname = args[0].from;
17533+ AuDbg("del path %s\n", del->pathname);
17534+
17535+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
17536+ if (unlikely(err))
4a4d8108 17537+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 17538+
17539+ return err;
17540+}
17541+
17542+#if 0 /* reserved for future use */
17543+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
17544+ struct au_opt_del *del, substring_t args[])
17545+{
17546+ int err;
17547+ struct dentry *root;
17548+
17549+ err = -EINVAL;
17550+ root = sb->s_root;
17551+ aufs_read_lock(root, AuLock_FLUSH);
17552+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17553+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17554+ goto out;
17555+ }
17556+
17557+ err = 0;
17558+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
17559+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
17560+
4f0767ce 17561+out:
1facf9fc 17562+ aufs_read_unlock(root, !AuLock_IR);
17563+ return err;
17564+}
17565+#endif
17566+
4a4d8108
AM
17567+static int noinline_for_stack
17568+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 17569+{
17570+ int err;
17571+ struct path path;
17572+ char *p;
17573+
17574+ err = -EINVAL;
17575+ mod->path = args[0].from;
17576+ p = strchr(mod->path, '=');
17577+ if (unlikely(!p)) {
4a4d8108 17578+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 17579+ goto out;
17580+ }
17581+
17582+ *p++ = 0;
17583+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
17584+ if (unlikely(err)) {
4a4d8108 17585+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 17586+ goto out;
17587+ }
17588+
17589+ mod->perm = br_perm_val(p);
17590+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
17591+ mod->h_root = dget(path.dentry);
17592+ path_put(&path);
17593+
4f0767ce 17594+out:
1facf9fc 17595+ return err;
17596+}
17597+
17598+#if 0 /* reserved for future use */
17599+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
17600+ struct au_opt_mod *mod, substring_t args[])
17601+{
17602+ int err;
17603+ struct dentry *root;
17604+
17605+ err = -EINVAL;
17606+ root = sb->s_root;
17607+ aufs_read_lock(root, AuLock_FLUSH);
17608+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17609+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17610+ goto out;
17611+ }
17612+
17613+ err = 0;
17614+ mod->perm = br_perm_val(args[1].from);
17615+ AuDbg("mod path %s, perm 0x%x, %s\n",
17616+ mod->path, mod->perm, args[1].from);
17617+ mod->h_root = dget(au_h_dptr(root, bindex));
17618+
4f0767ce 17619+out:
1facf9fc 17620+ aufs_read_unlock(root, !AuLock_IR);
17621+ return err;
17622+}
17623+#endif
17624+
17625+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
17626+ substring_t args[])
17627+{
17628+ int err;
17629+ struct file *file;
17630+
17631+ file = au_xino_create(sb, args[0].from, /*silent*/0);
17632+ err = PTR_ERR(file);
17633+ if (IS_ERR(file))
17634+ goto out;
17635+
17636+ err = -EINVAL;
17637+ if (unlikely(file->f_dentry->d_sb == sb)) {
17638+ fput(file);
4a4d8108 17639+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 17640+ goto out;
17641+ }
17642+
17643+ err = 0;
17644+ xino->file = file;
17645+ xino->path = args[0].from;
17646+
4f0767ce 17647+out:
1facf9fc 17648+ return err;
17649+}
17650+
4a4d8108
AM
17651+static int noinline_for_stack
17652+au_opts_parse_xino_itrunc_path(struct super_block *sb,
17653+ struct au_opt_xino_itrunc *xino_itrunc,
17654+ substring_t args[])
1facf9fc 17655+{
17656+ int err;
17657+ aufs_bindex_t bend, bindex;
17658+ struct path path;
17659+ struct dentry *root;
17660+
17661+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
17662+ if (unlikely(err)) {
4a4d8108 17663+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 17664+ goto out;
17665+ }
17666+
17667+ xino_itrunc->bindex = -1;
17668+ root = sb->s_root;
17669+ aufs_read_lock(root, AuLock_FLUSH);
17670+ bend = au_sbend(sb);
17671+ for (bindex = 0; bindex <= bend; bindex++) {
17672+ if (au_h_dptr(root, bindex) == path.dentry) {
17673+ xino_itrunc->bindex = bindex;
17674+ break;
17675+ }
17676+ }
17677+ aufs_read_unlock(root, !AuLock_IR);
17678+ path_put(&path);
17679+
17680+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 17681+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 17682+ err = -EINVAL;
17683+ }
17684+
4f0767ce 17685+out:
1facf9fc 17686+ return err;
17687+}
17688+
17689+/* called without aufs lock */
17690+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
17691+{
17692+ int err, n, token;
17693+ aufs_bindex_t bindex;
17694+ unsigned char skipped;
17695+ struct dentry *root;
17696+ struct au_opt *opt, *opt_tail;
17697+ char *opt_str;
17698+ /* reduce the stack space */
17699+ union {
17700+ struct au_opt_xino_itrunc *xino_itrunc;
17701+ struct au_opt_wbr_create *create;
17702+ } u;
17703+ struct {
17704+ substring_t args[MAX_OPT_ARGS];
17705+ } *a;
17706+
17707+ err = -ENOMEM;
17708+ a = kmalloc(sizeof(*a), GFP_NOFS);
17709+ if (unlikely(!a))
17710+ goto out;
17711+
17712+ root = sb->s_root;
17713+ err = 0;
17714+ bindex = 0;
17715+ opt = opts->opt;
17716+ opt_tail = opt + opts->max_opt - 1;
17717+ opt->type = Opt_tail;
17718+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
17719+ err = -EINVAL;
17720+ skipped = 0;
17721+ token = match_token(opt_str, options, a->args);
17722+ switch (token) {
17723+ case Opt_br:
17724+ err = 0;
17725+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
17726+ && *opt_str) {
17727+ err = opt_add(opt, opt_str, opts->sb_flags,
17728+ bindex++);
17729+ if (unlikely(!err && ++opt > opt_tail)) {
17730+ err = -E2BIG;
17731+ break;
17732+ }
17733+ opt->type = Opt_tail;
17734+ skipped = 1;
17735+ }
17736+ break;
17737+ case Opt_add:
17738+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17739+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17740+ break;
17741+ }
17742+ bindex = n;
17743+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
17744+ bindex);
17745+ if (!err)
17746+ opt->type = token;
17747+ break;
17748+ case Opt_append:
17749+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17750+ /*dummy bindex*/1);
17751+ if (!err)
17752+ opt->type = token;
17753+ break;
17754+ case Opt_prepend:
17755+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17756+ /*bindex*/0);
17757+ if (!err)
17758+ opt->type = token;
17759+ break;
17760+ case Opt_del:
17761+ err = au_opts_parse_del(&opt->del, a->args);
17762+ if (!err)
17763+ opt->type = token;
17764+ break;
17765+#if 0 /* reserved for future use */
17766+ case Opt_idel:
17767+ del->pathname = "(indexed)";
17768+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 17769+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17770+ break;
17771+ }
17772+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
17773+ if (!err)
17774+ opt->type = token;
17775+ break;
17776+#endif
17777+ case Opt_mod:
17778+ err = au_opts_parse_mod(&opt->mod, a->args);
17779+ if (!err)
17780+ opt->type = token;
17781+ break;
17782+#ifdef IMOD /* reserved for future use */
17783+ case Opt_imod:
17784+ u.mod->path = "(indexed)";
17785+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17786+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17787+ break;
17788+ }
17789+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
17790+ if (!err)
17791+ opt->type = token;
17792+ break;
17793+#endif
17794+ case Opt_xino:
17795+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
17796+ if (!err)
17797+ opt->type = token;
17798+ break;
17799+
17800+ case Opt_trunc_xino_path:
17801+ err = au_opts_parse_xino_itrunc_path
17802+ (sb, &opt->xino_itrunc, a->args);
17803+ if (!err)
17804+ opt->type = token;
17805+ break;
17806+
17807+ case Opt_itrunc_xino:
17808+ u.xino_itrunc = &opt->xino_itrunc;
17809+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17810+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17811+ break;
17812+ }
17813+ u.xino_itrunc->bindex = n;
17814+ aufs_read_lock(root, AuLock_FLUSH);
17815+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 17816+ pr_err("out of bounds, %d\n", n);
1facf9fc 17817+ aufs_read_unlock(root, !AuLock_IR);
17818+ break;
17819+ }
17820+ aufs_read_unlock(root, !AuLock_IR);
17821+ err = 0;
17822+ opt->type = token;
17823+ break;
17824+
17825+ case Opt_dirwh:
17826+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
17827+ break;
17828+ err = 0;
17829+ opt->type = token;
17830+ break;
17831+
17832+ case Opt_rdcache:
e49829fe
JR
17833+ if (unlikely(match_int(&a->args[0], &opt->rdcache)
17834+ || opt->rdcache > MAX_SEC_IN_JIFFIES))
1facf9fc 17835+ break;
17836+ err = 0;
17837+ opt->type = token;
17838+ break;
17839+ case Opt_rdblk:
17840+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17841+ || n < 0
1facf9fc 17842+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 17843+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17844+ break;
17845+ }
1308ab2a 17846+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
17847+ pr_err("rdblk must be larger than %d\n",
17848+ NAME_MAX);
1facf9fc 17849+ break;
17850+ }
17851+ opt->rdblk = n;
17852+ err = 0;
17853+ opt->type = token;
17854+ break;
17855+ case Opt_rdhash:
17856+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17857+ || n < 0
1facf9fc 17858+ || n * sizeof(struct hlist_head)
17859+ > KMALLOC_MAX_SIZE)) {
4a4d8108 17860+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17861+ break;
17862+ }
17863+ opt->rdhash = n;
17864+ err = 0;
17865+ opt->type = token;
17866+ break;
17867+
17868+ case Opt_trunc_xino:
17869+ case Opt_notrunc_xino:
17870+ case Opt_noxino:
17871+ case Opt_trunc_xib:
17872+ case Opt_notrunc_xib:
dece6358
AM
17873+ case Opt_shwh:
17874+ case Opt_noshwh:
1facf9fc 17875+ case Opt_plink:
17876+ case Opt_noplink:
17877+ case Opt_list_plink:
4a4d8108
AM
17878+ case Opt_dio:
17879+ case Opt_nodio:
1facf9fc 17880+ case Opt_diropq_a:
17881+ case Opt_diropq_w:
17882+ case Opt_warn_perm:
17883+ case Opt_nowarn_perm:
17884+ case Opt_refrof:
17885+ case Opt_norefrof:
17886+ case Opt_verbose:
17887+ case Opt_noverbose:
17888+ case Opt_sum:
17889+ case Opt_nosum:
17890+ case Opt_wsum:
dece6358
AM
17891+ case Opt_rdblk_def:
17892+ case Opt_rdhash_def:
1facf9fc 17893+ err = 0;
17894+ opt->type = token;
17895+ break;
17896+
17897+ case Opt_udba:
17898+ opt->udba = udba_val(a->args[0].from);
17899+ if (opt->udba >= 0) {
17900+ err = 0;
17901+ opt->type = token;
17902+ } else
4a4d8108 17903+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17904+ break;
17905+
17906+ case Opt_wbr_create:
17907+ u.create = &opt->wbr_create;
17908+ u.create->wbr_create
17909+ = au_wbr_create_val(a->args[0].from, u.create);
17910+ if (u.create->wbr_create >= 0) {
17911+ err = 0;
17912+ opt->type = token;
17913+ } else
4a4d8108 17914+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17915+ break;
17916+ case Opt_wbr_copyup:
17917+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
17918+ if (opt->wbr_copyup >= 0) {
17919+ err = 0;
17920+ opt->type = token;
17921+ } else
4a4d8108 17922+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17923+ break;
17924+
17925+ case Opt_ignore:
4a4d8108 17926+ pr_warning("ignored %s\n", opt_str);
1facf9fc 17927+ /*FALLTHROUGH*/
17928+ case Opt_ignore_silent:
17929+ skipped = 1;
17930+ err = 0;
17931+ break;
17932+ case Opt_err:
4a4d8108 17933+ pr_err("unknown option %s\n", opt_str);
1facf9fc 17934+ break;
17935+ }
17936+
17937+ if (!err && !skipped) {
17938+ if (unlikely(++opt > opt_tail)) {
17939+ err = -E2BIG;
17940+ opt--;
17941+ opt->type = Opt_tail;
17942+ break;
17943+ }
17944+ opt->type = Opt_tail;
17945+ }
17946+ }
17947+
17948+ kfree(a);
17949+ dump_opts(opts);
17950+ if (unlikely(err))
17951+ au_opts_free(opts);
17952+
4f0767ce 17953+out:
1facf9fc 17954+ return err;
17955+}
17956+
17957+static int au_opt_wbr_create(struct super_block *sb,
17958+ struct au_opt_wbr_create *create)
17959+{
17960+ int err;
17961+ struct au_sbinfo *sbinfo;
17962+
dece6358
AM
17963+ SiMustWriteLock(sb);
17964+
1facf9fc 17965+ err = 1; /* handled */
17966+ sbinfo = au_sbi(sb);
17967+ if (sbinfo->si_wbr_create_ops->fin) {
17968+ err = sbinfo->si_wbr_create_ops->fin(sb);
17969+ if (!err)
17970+ err = 1;
17971+ }
17972+
17973+ sbinfo->si_wbr_create = create->wbr_create;
17974+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
17975+ switch (create->wbr_create) {
17976+ case AuWbrCreate_MFSRRV:
17977+ case AuWbrCreate_MFSRR:
17978+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
17979+ /*FALLTHROUGH*/
17980+ case AuWbrCreate_MFS:
17981+ case AuWbrCreate_MFSV:
17982+ case AuWbrCreate_PMFS:
17983+ case AuWbrCreate_PMFSV:
e49829fe
JR
17984+ sbinfo->si_wbr_mfs.mfs_expire
17985+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 17986+ break;
17987+ }
17988+
17989+ if (sbinfo->si_wbr_create_ops->init)
17990+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
17991+
17992+ return err;
17993+}
17994+
17995+/*
17996+ * returns,
17997+ * plus: processed without an error
17998+ * zero: unprocessed
17999+ */
18000+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
18001+ struct au_opts *opts)
18002+{
18003+ int err;
18004+ struct au_sbinfo *sbinfo;
18005+
dece6358
AM
18006+ SiMustWriteLock(sb);
18007+
1facf9fc 18008+ err = 1; /* handled */
18009+ sbinfo = au_sbi(sb);
18010+ switch (opt->type) {
18011+ case Opt_udba:
18012+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18013+ sbinfo->si_mntflags |= opt->udba;
18014+ opts->given_udba |= opt->udba;
18015+ break;
18016+
18017+ case Opt_plink:
18018+ au_opt_set(sbinfo->si_mntflags, PLINK);
18019+ break;
18020+ case Opt_noplink:
18021+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 18022+ au_plink_put(sb, /*verbose*/1);
1facf9fc 18023+ au_opt_clr(sbinfo->si_mntflags, PLINK);
18024+ break;
18025+ case Opt_list_plink:
18026+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
18027+ au_plink_list(sb);
18028+ break;
18029+
4a4d8108
AM
18030+ case Opt_dio:
18031+ au_opt_set(sbinfo->si_mntflags, DIO);
18032+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18033+ break;
18034+ case Opt_nodio:
18035+ au_opt_clr(sbinfo->si_mntflags, DIO);
18036+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18037+ break;
18038+
1facf9fc 18039+ case Opt_diropq_a:
18040+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18041+ break;
18042+ case Opt_diropq_w:
18043+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18044+ break;
18045+
18046+ case Opt_warn_perm:
18047+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
18048+ break;
18049+ case Opt_nowarn_perm:
18050+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
18051+ break;
18052+
18053+ case Opt_refrof:
18054+ au_opt_set(sbinfo->si_mntflags, REFROF);
18055+ break;
18056+ case Opt_norefrof:
18057+ au_opt_clr(sbinfo->si_mntflags, REFROF);
18058+ break;
18059+
18060+ case Opt_verbose:
18061+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
18062+ break;
18063+ case Opt_noverbose:
18064+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
18065+ break;
18066+
18067+ case Opt_sum:
18068+ au_opt_set(sbinfo->si_mntflags, SUM);
18069+ break;
18070+ case Opt_wsum:
18071+ au_opt_clr(sbinfo->si_mntflags, SUM);
18072+ au_opt_set(sbinfo->si_mntflags, SUM_W);
18073+ case Opt_nosum:
18074+ au_opt_clr(sbinfo->si_mntflags, SUM);
18075+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
18076+ break;
18077+
18078+ case Opt_wbr_create:
18079+ err = au_opt_wbr_create(sb, &opt->wbr_create);
18080+ break;
18081+ case Opt_wbr_copyup:
18082+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
18083+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
18084+ break;
18085+
18086+ case Opt_dirwh:
18087+ sbinfo->si_dirwh = opt->dirwh;
18088+ break;
18089+
18090+ case Opt_rdcache:
e49829fe
JR
18091+ sbinfo->si_rdcache
18092+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 18093+ break;
18094+ case Opt_rdblk:
18095+ sbinfo->si_rdblk = opt->rdblk;
18096+ break;
dece6358
AM
18097+ case Opt_rdblk_def:
18098+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
18099+ break;
1facf9fc 18100+ case Opt_rdhash:
18101+ sbinfo->si_rdhash = opt->rdhash;
18102+ break;
dece6358
AM
18103+ case Opt_rdhash_def:
18104+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
18105+ break;
18106+
18107+ case Opt_shwh:
18108+ au_opt_set(sbinfo->si_mntflags, SHWH);
18109+ break;
18110+ case Opt_noshwh:
18111+ au_opt_clr(sbinfo->si_mntflags, SHWH);
18112+ break;
1facf9fc 18113+
18114+ case Opt_trunc_xino:
18115+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
18116+ break;
18117+ case Opt_notrunc_xino:
18118+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
18119+ break;
18120+
18121+ case Opt_trunc_xino_path:
18122+ case Opt_itrunc_xino:
18123+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
18124+ if (!err)
18125+ err = 1;
18126+ break;
18127+
18128+ case Opt_trunc_xib:
18129+ au_fset_opts(opts->flags, TRUNC_XIB);
18130+ break;
18131+ case Opt_notrunc_xib:
18132+ au_fclr_opts(opts->flags, TRUNC_XIB);
18133+ break;
18134+
18135+ default:
18136+ err = 0;
18137+ break;
18138+ }
18139+
18140+ return err;
18141+}
18142+
18143+/*
18144+ * returns tri-state.
18145+ * plus: processed without an error
18146+ * zero: unprocessed
18147+ * minus: error
18148+ */
18149+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
18150+ struct au_opts *opts)
18151+{
18152+ int err, do_refresh;
18153+
18154+ err = 0;
18155+ switch (opt->type) {
18156+ case Opt_append:
18157+ opt->add.bindex = au_sbend(sb) + 1;
18158+ if (opt->add.bindex < 0)
18159+ opt->add.bindex = 0;
18160+ goto add;
18161+ case Opt_prepend:
18162+ opt->add.bindex = 0;
18163+ add:
18164+ case Opt_add:
18165+ err = au_br_add(sb, &opt->add,
18166+ au_ftest_opts(opts->flags, REMOUNT));
18167+ if (!err) {
18168+ err = 1;
18169+ au_fset_opts(opts->flags, REFRESH_DIR);
4a4d8108 18170+ au_fset_opts(opts->flags, REFRESH_NONDIR);
1facf9fc 18171+ }
18172+ break;
18173+
18174+ case Opt_del:
18175+ case Opt_idel:
18176+ err = au_br_del(sb, &opt->del,
18177+ au_ftest_opts(opts->flags, REMOUNT));
18178+ if (!err) {
18179+ err = 1;
18180+ au_fset_opts(opts->flags, TRUNC_XIB);
18181+ au_fset_opts(opts->flags, REFRESH_DIR);
18182+ au_fset_opts(opts->flags, REFRESH_NONDIR);
18183+ }
18184+ break;
18185+
18186+ case Opt_mod:
18187+ case Opt_imod:
18188+ err = au_br_mod(sb, &opt->mod,
18189+ au_ftest_opts(opts->flags, REMOUNT),
18190+ &do_refresh);
18191+ if (!err) {
18192+ err = 1;
18193+ if (do_refresh) {
18194+ au_fset_opts(opts->flags, REFRESH_DIR);
18195+ au_fset_opts(opts->flags, REFRESH_NONDIR);
18196+ }
18197+ }
18198+ break;
18199+ }
18200+
18201+ return err;
18202+}
18203+
18204+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
18205+ struct au_opt_xino **opt_xino,
18206+ struct au_opts *opts)
18207+{
18208+ int err;
18209+ aufs_bindex_t bend, bindex;
18210+ struct dentry *root, *parent, *h_root;
18211+
18212+ err = 0;
18213+ switch (opt->type) {
18214+ case Opt_xino:
18215+ err = au_xino_set(sb, &opt->xino,
18216+ !!au_ftest_opts(opts->flags, REMOUNT));
18217+ if (unlikely(err))
18218+ break;
18219+
18220+ *opt_xino = &opt->xino;
18221+ au_xino_brid_set(sb, -1);
18222+
18223+ /* safe d_parent access */
18224+ parent = opt->xino.file->f_dentry->d_parent;
18225+ root = sb->s_root;
18226+ bend = au_sbend(sb);
18227+ for (bindex = 0; bindex <= bend; bindex++) {
18228+ h_root = au_h_dptr(root, bindex);
18229+ if (h_root == parent) {
18230+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
18231+ break;
18232+ }
18233+ }
18234+ break;
18235+
18236+ case Opt_noxino:
18237+ au_xino_clr(sb);
18238+ au_xino_brid_set(sb, -1);
18239+ *opt_xino = (void *)-1;
18240+ break;
18241+ }
18242+
18243+ return err;
18244+}
18245+
18246+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18247+ unsigned int pending)
18248+{
18249+ int err;
18250+ aufs_bindex_t bindex, bend;
18251+ unsigned char do_plink, skip, do_free;
18252+ struct au_branch *br;
18253+ struct au_wbr *wbr;
18254+ struct dentry *root;
18255+ struct inode *dir, *h_dir;
18256+ struct au_sbinfo *sbinfo;
18257+ struct au_hinode *hdir;
18258+
dece6358
AM
18259+ SiMustAnyLock(sb);
18260+
1facf9fc 18261+ sbinfo = au_sbi(sb);
18262+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
18263+
dece6358
AM
18264+ if (!(sb_flags & MS_RDONLY)) {
18265+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
4a4d8108 18266+ pr_warning("first branch should be rw\n");
dece6358 18267+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
4a4d8108 18268+ pr_warning("shwh should be used with ro\n");
dece6358 18269+ }
1facf9fc 18270+
4a4d8108 18271+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 18272+ && !au_opt_test(sbinfo->si_mntflags, XINO))
4a4d8108 18273+ pr_warning("udba=*notify requires xino\n");
1facf9fc 18274+
18275+ err = 0;
18276+ root = sb->s_root;
4a4d8108 18277+ dir = root->d_inode;
1facf9fc 18278+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
18279+ bend = au_sbend(sb);
18280+ for (bindex = 0; !err && bindex <= bend; bindex++) {
18281+ skip = 0;
18282+ h_dir = au_h_iptr(dir, bindex);
18283+ br = au_sbr(sb, bindex);
18284+ do_free = 0;
18285+
18286+ wbr = br->br_wbr;
18287+ if (wbr)
18288+ wbr_wh_read_lock(wbr);
18289+
18290+ switch (br->br_perm) {
18291+ case AuBrPerm_RO:
18292+ case AuBrPerm_ROWH:
18293+ case AuBrPerm_RR:
18294+ case AuBrPerm_RRWH:
18295+ do_free = !!wbr;
18296+ skip = (!wbr
18297+ || (!wbr->wbr_whbase
18298+ && !wbr->wbr_plink
18299+ && !wbr->wbr_orph));
18300+ break;
18301+
18302+ case AuBrPerm_RWNoLinkWH:
18303+ /* skip = (!br->br_whbase && !br->br_orph); */
18304+ skip = (!wbr || !wbr->wbr_whbase);
18305+ if (skip && wbr) {
18306+ if (do_plink)
18307+ skip = !!wbr->wbr_plink;
18308+ else
18309+ skip = !wbr->wbr_plink;
18310+ }
18311+ break;
18312+
18313+ case AuBrPerm_RW:
18314+ /* skip = (br->br_whbase && br->br_ohph); */
18315+ skip = (wbr && wbr->wbr_whbase);
18316+ if (skip) {
18317+ if (do_plink)
18318+ skip = !!wbr->wbr_plink;
18319+ else
18320+ skip = !wbr->wbr_plink;
18321+ }
18322+ break;
18323+
18324+ default:
18325+ BUG();
18326+ }
18327+ if (wbr)
18328+ wbr_wh_read_unlock(wbr);
18329+
18330+ if (skip)
18331+ continue;
18332+
18333+ hdir = au_hi(dir, bindex);
4a4d8108 18334+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 18335+ if (wbr)
18336+ wbr_wh_write_lock(wbr);
18337+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
18338+ if (wbr)
18339+ wbr_wh_write_unlock(wbr);
4a4d8108 18340+ au_hn_imtx_unlock(hdir);
1facf9fc 18341+
18342+ if (!err && do_free) {
18343+ kfree(wbr);
18344+ br->br_wbr = NULL;
18345+ }
18346+ }
18347+
18348+ return err;
18349+}
18350+
18351+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
18352+{
18353+ int err;
18354+ unsigned int tmp;
18355+ aufs_bindex_t bend;
18356+ struct au_opt *opt;
18357+ struct au_opt_xino *opt_xino, xino;
18358+ struct au_sbinfo *sbinfo;
18359+
dece6358
AM
18360+ SiMustWriteLock(sb);
18361+
1facf9fc 18362+ err = 0;
18363+ opt_xino = NULL;
18364+ opt = opts->opt;
18365+ while (err >= 0 && opt->type != Opt_tail)
18366+ err = au_opt_simple(sb, opt++, opts);
18367+ if (err > 0)
18368+ err = 0;
18369+ else if (unlikely(err < 0))
18370+ goto out;
18371+
18372+ /* disable xino and udba temporary */
18373+ sbinfo = au_sbi(sb);
18374+ tmp = sbinfo->si_mntflags;
18375+ au_opt_clr(sbinfo->si_mntflags, XINO);
18376+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
18377+
18378+ opt = opts->opt;
18379+ while (err >= 0 && opt->type != Opt_tail)
18380+ err = au_opt_br(sb, opt++, opts);
18381+ if (err > 0)
18382+ err = 0;
18383+ else if (unlikely(err < 0))
18384+ goto out;
18385+
18386+ bend = au_sbend(sb);
18387+ if (unlikely(bend < 0)) {
18388+ err = -EINVAL;
4a4d8108 18389+ pr_err("no branches\n");
1facf9fc 18390+ goto out;
18391+ }
18392+
18393+ if (au_opt_test(tmp, XINO))
18394+ au_opt_set(sbinfo->si_mntflags, XINO);
18395+ opt = opts->opt;
18396+ while (!err && opt->type != Opt_tail)
18397+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
18398+ if (unlikely(err))
18399+ goto out;
18400+
18401+ err = au_opts_verify(sb, sb->s_flags, tmp);
18402+ if (unlikely(err))
18403+ goto out;
18404+
18405+ /* restore xino */
18406+ if (au_opt_test(tmp, XINO) && !opt_xino) {
18407+ xino.file = au_xino_def(sb);
18408+ err = PTR_ERR(xino.file);
18409+ if (IS_ERR(xino.file))
18410+ goto out;
18411+
18412+ err = au_xino_set(sb, &xino, /*remount*/0);
18413+ fput(xino.file);
18414+ if (unlikely(err))
18415+ goto out;
18416+ }
18417+
18418+ /* restore udba */
18419+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18420+ sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
4a4d8108 18421+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 18422+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 18423+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 18424+ }
18425+
4f0767ce 18426+out:
1facf9fc 18427+ return err;
18428+}
18429+
18430+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
18431+{
18432+ int err, rerr;
18433+ struct inode *dir;
18434+ struct au_opt_xino *opt_xino;
18435+ struct au_opt *opt;
18436+ struct au_sbinfo *sbinfo;
18437+
dece6358
AM
18438+ SiMustWriteLock(sb);
18439+
1facf9fc 18440+ dir = sb->s_root->d_inode;
18441+ sbinfo = au_sbi(sb);
18442+ err = 0;
18443+ opt_xino = NULL;
18444+ opt = opts->opt;
18445+ while (err >= 0 && opt->type != Opt_tail) {
18446+ err = au_opt_simple(sb, opt, opts);
18447+ if (!err)
18448+ err = au_opt_br(sb, opt, opts);
18449+ if (!err)
18450+ err = au_opt_xino(sb, opt, &opt_xino, opts);
18451+ opt++;
18452+ }
18453+ if (err > 0)
18454+ err = 0;
18455+ AuTraceErr(err);
18456+ /* go on even err */
18457+
18458+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
18459+ if (unlikely(rerr && !err))
18460+ err = rerr;
18461+
18462+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
18463+ rerr = au_xib_trunc(sb);
18464+ if (unlikely(rerr && !err))
18465+ err = rerr;
18466+ }
18467+
18468+ /* will be handled by the caller */
18469+ if (!au_ftest_opts(opts->flags, REFRESH_DIR)
18470+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
18471+ au_fset_opts(opts->flags, REFRESH_DIR);
18472+
18473+ AuDbg("status 0x%x\n", opts->flags);
18474+ return err;
18475+}
18476+
18477+/* ---------------------------------------------------------------------- */
18478+
18479+unsigned int au_opt_udba(struct super_block *sb)
18480+{
18481+ return au_mntflags(sb) & AuOptMask_UDBA;
18482+}
7f207e10
AM
18483diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
18484--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
18485+++ linux/fs/aufs/opts.h 2010-11-22 11:52:56.990562128 +0100
18486@@ -0,0 +1,211 @@
1facf9fc 18487+/*
4a4d8108 18488+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18489+ *
18490+ * This program, aufs is free software; you can redistribute it and/or modify
18491+ * it under the terms of the GNU General Public License as published by
18492+ * the Free Software Foundation; either version 2 of the License, or
18493+ * (at your option) any later version.
dece6358
AM
18494+ *
18495+ * This program is distributed in the hope that it will be useful,
18496+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18497+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18498+ * GNU General Public License for more details.
18499+ *
18500+ * You should have received a copy of the GNU General Public License
18501+ * along with this program; if not, write to the Free Software
18502+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18503+ */
18504+
18505+/*
18506+ * mount options/flags
18507+ */
18508+
18509+#ifndef __AUFS_OPTS_H__
18510+#define __AUFS_OPTS_H__
18511+
18512+#ifdef __KERNEL__
18513+
dece6358 18514+#include <linux/path.h>
1facf9fc 18515+#include <linux/aufs_type.h>
18516+
dece6358
AM
18517+struct file;
18518+struct super_block;
18519+
1facf9fc 18520+/* ---------------------------------------------------------------------- */
18521+
18522+/* mount flags */
18523+#define AuOpt_XINO 1 /* external inode number bitmap
18524+ and translation table */
18525+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
18526+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
18527+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 18528+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
18529+#define AuOpt_SHWH (1 << 5) /* show whiteout */
18530+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
18531+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
18532+#define AuOpt_REFROF (1 << 8) /* unimplemented */
18533+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
18534+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
18535+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
18536+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
18537+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 18538+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 18539+
4a4d8108
AM
18540+#ifndef CONFIG_AUFS_HNOTIFY
18541+#undef AuOpt_UDBA_HNOTIFY
18542+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 18543+#endif
dece6358
AM
18544+#ifndef CONFIG_AUFS_SHWH
18545+#undef AuOpt_SHWH
18546+#define AuOpt_SHWH 0
18547+#endif
1facf9fc 18548+
18549+#define AuOpt_Def (AuOpt_XINO \
18550+ | AuOpt_UDBA_REVAL \
18551+ | AuOpt_PLINK \
18552+ /* | AuOpt_DIRPERM1 */ \
18553+ | AuOpt_WARN_PERM)
18554+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
18555+ | AuOpt_UDBA_REVAL \
4a4d8108 18556+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 18557+
18558+#define au_opt_test(flags, name) (flags & AuOpt_##name)
18559+#define au_opt_set(flags, name) do { \
18560+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
18561+ ((flags) |= AuOpt_##name); \
18562+} while (0)
18563+#define au_opt_set_udba(flags, name) do { \
18564+ (flags) &= ~AuOptMask_UDBA; \
18565+ ((flags) |= AuOpt_##name); \
18566+} while (0)
7f207e10
AM
18567+#define au_opt_clr(flags, name) do { \
18568+ ((flags) &= ~AuOpt_##name); \
18569+} while (0)
1facf9fc 18570+
e49829fe
JR
18571+static inline unsigned int au_opts_plink(unsigned int mntflags)
18572+{
18573+#ifdef CONFIG_PROC_FS
18574+ return mntflags;
18575+#else
18576+ return mntflags & ~AuOpt_PLINK;
18577+#endif
18578+}
18579+
1facf9fc 18580+/* ---------------------------------------------------------------------- */
18581+
18582+/* policies to select one among multiple writable branches */
18583+enum {
18584+ AuWbrCreate_TDP, /* top down parent */
18585+ AuWbrCreate_RR, /* round robin */
18586+ AuWbrCreate_MFS, /* most free space */
18587+ AuWbrCreate_MFSV, /* mfs with seconds */
18588+ AuWbrCreate_MFSRR, /* mfs then rr */
18589+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
18590+ AuWbrCreate_PMFS, /* parent and mfs */
18591+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
18592+
18593+ AuWbrCreate_Def = AuWbrCreate_TDP
18594+};
18595+
18596+enum {
18597+ AuWbrCopyup_TDP, /* top down parent */
18598+ AuWbrCopyup_BUP, /* bottom up parent */
18599+ AuWbrCopyup_BU, /* bottom up */
18600+
18601+ AuWbrCopyup_Def = AuWbrCopyup_TDP
18602+};
18603+
18604+/* ---------------------------------------------------------------------- */
18605+
18606+struct au_opt_add {
18607+ aufs_bindex_t bindex;
18608+ char *pathname;
18609+ int perm;
18610+ struct path path;
18611+};
18612+
18613+struct au_opt_del {
18614+ char *pathname;
18615+ struct path h_path;
18616+};
18617+
18618+struct au_opt_mod {
18619+ char *path;
18620+ int perm;
18621+ struct dentry *h_root;
18622+};
18623+
18624+struct au_opt_xino {
18625+ char *path;
18626+ struct file *file;
18627+};
18628+
18629+struct au_opt_xino_itrunc {
18630+ aufs_bindex_t bindex;
18631+};
18632+
18633+struct au_opt_wbr_create {
18634+ int wbr_create;
18635+ int mfs_second;
18636+ unsigned long long mfsrr_watermark;
18637+};
18638+
18639+struct au_opt {
18640+ int type;
18641+ union {
18642+ struct au_opt_xino xino;
18643+ struct au_opt_xino_itrunc xino_itrunc;
18644+ struct au_opt_add add;
18645+ struct au_opt_del del;
18646+ struct au_opt_mod mod;
18647+ int dirwh;
18648+ int rdcache;
18649+ unsigned int rdblk;
18650+ unsigned int rdhash;
18651+ int udba;
18652+ struct au_opt_wbr_create wbr_create;
18653+ int wbr_copyup;
18654+ };
18655+};
18656+
18657+/* opts flags */
18658+#define AuOpts_REMOUNT 1
18659+#define AuOpts_REFRESH_DIR (1 << 1)
18660+#define AuOpts_REFRESH_NONDIR (1 << 2)
18661+#define AuOpts_TRUNC_XIB (1 << 3)
4a4d8108 18662+#define AuOpts_REFRESH_DYAOP (1 << 4)
1facf9fc 18663+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
18664+#define au_fset_opts(flags, name) \
18665+ do { (flags) |= AuOpts_##name; } while (0)
18666+#define au_fclr_opts(flags, name) \
18667+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 18668+
18669+struct au_opts {
18670+ struct au_opt *opt;
18671+ int max_opt;
18672+
18673+ unsigned int given_udba;
18674+ unsigned int flags;
18675+ unsigned long sb_flags;
18676+};
18677+
18678+/* ---------------------------------------------------------------------- */
18679+
18680+const char *au_optstr_br_perm(int brperm);
18681+const char *au_optstr_udba(int udba);
18682+const char *au_optstr_wbr_copyup(int wbr_copyup);
18683+const char *au_optstr_wbr_create(int wbr_create);
18684+
18685+void au_opts_free(struct au_opts *opts);
18686+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
18687+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18688+ unsigned int pending);
18689+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
18690+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
18691+
18692+unsigned int au_opt_udba(struct super_block *sb);
18693+
18694+/* ---------------------------------------------------------------------- */
18695+
18696+#endif /* __KERNEL__ */
18697+#endif /* __AUFS_OPTS_H__ */
7f207e10
AM
18698diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
18699--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
18700+++ linux/fs/aufs/plink.c 2010-11-22 11:52:56.990562128 +0100
18701@@ -0,0 +1,522 @@
1facf9fc 18702+/*
4a4d8108 18703+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18704+ *
18705+ * This program, aufs is free software; you can redistribute it and/or modify
18706+ * it under the terms of the GNU General Public License as published by
18707+ * the Free Software Foundation; either version 2 of the License, or
18708+ * (at your option) any later version.
dece6358
AM
18709+ *
18710+ * This program is distributed in the hope that it will be useful,
18711+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18712+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18713+ * GNU General Public License for more details.
18714+ *
18715+ * You should have received a copy of the GNU General Public License
18716+ * along with this program; if not, write to the Free Software
18717+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18718+ */
18719+
18720+/*
18721+ * pseudo-link
18722+ */
18723+
18724+#include "aufs.h"
18725+
18726+/*
e49829fe 18727+ * the pseudo-link maintenance mode.
1facf9fc 18728+ * during a user process maintains the pseudo-links,
18729+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
18730+ *
18731+ * Flags
18732+ * NOPLM:
18733+ * For entry functions which will handle plink, and i_mutex is already held
18734+ * in VFS.
18735+ * They cannot wait and should return an error at once.
18736+ * Callers has to check the error.
18737+ * NOPLMW:
18738+ * For entry functions which will handle plink, but i_mutex is not held
18739+ * in VFS.
18740+ * They can wait the plink maintenance mode to finish.
18741+ *
18742+ * They behave like F_SETLK and F_SETLKW.
18743+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 18744+ */
e49829fe
JR
18745+
18746+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 18747+{
e49829fe
JR
18748+ int err;
18749+ pid_t pid, ppid;
18750+ struct au_sbinfo *sbi;
dece6358
AM
18751+
18752+ SiMustAnyLock(sb);
18753+
e49829fe
JR
18754+ err = 0;
18755+ if (!au_opt_test(au_mntflags(sb), PLINK))
18756+ goto out;
18757+
18758+ sbi = au_sbi(sb);
18759+ pid = sbi->si_plink_maint_pid;
18760+ if (!pid || pid == current->pid)
18761+ goto out;
18762+
18763+ /* todo: it highly depends upon /sbin/mount.aufs */
18764+ rcu_read_lock();
18765+ ppid = task_pid_vnr(rcu_dereference(current->real_parent));
18766+ rcu_read_unlock();
18767+ if (pid == ppid)
18768+ goto out;
18769+
18770+ if (au_ftest_lock(flags, NOPLMW)) {
18771+ /*
18772+ * todo: debug by lockdep, if there is no i_mutex lock in VFS,
18773+ * we don't need to wait.
18774+ */
18775+ while (sbi->si_plink_maint_pid) {
18776+ si_read_unlock(sb);
18777+ /* gave up wake_up_bit() */
18778+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
18779+
18780+ if (au_ftest_lock(flags, FLUSH))
18781+ au_nwt_flush(&sbi->si_nowait);
18782+ si_noflush_read_lock(sb);
18783+ }
18784+ } else if (au_ftest_lock(flags, NOPLM)) {
18785+ AuDbg("ppid %d, pid %d\n", ppid, pid);
18786+ err = -EAGAIN;
18787+ }
18788+
18789+out:
18790+ return err;
4a4d8108
AM
18791+}
18792+
e49829fe 18793+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 18794+{
4a4d8108
AM
18795+ int iam;
18796+
4a4d8108 18797+ spin_lock(&sbinfo->si_plink_maint_lock);
e49829fe 18798+ iam = (sbinfo->si_plink_maint_pid == current->pid);
4a4d8108 18799+ if (iam)
e49829fe 18800+ sbinfo->si_plink_maint_pid = 0;
4a4d8108
AM
18801+ spin_unlock(&sbinfo->si_plink_maint_lock);
18802+ if (iam)
18803+ wake_up_all(&sbinfo->si_plink_wq);
18804+}
18805+
e49829fe 18806+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
18807+{
18808+ int err;
4a4d8108
AM
18809+ struct au_sbinfo *sbinfo;
18810+
18811+ err = 0;
4a4d8108
AM
18812+ sbinfo = au_sbi(sb);
18813+ /* make sure i am the only one in this fs */
e49829fe
JR
18814+ si_write_lock(sb, AuLock_FLUSH);
18815+ if (au_opt_test(au_mntflags(sb), PLINK)) {
18816+ spin_lock(&sbinfo->si_plink_maint_lock);
18817+ if (!sbinfo->si_plink_maint_pid)
18818+ sbinfo->si_plink_maint_pid = current->pid;
18819+ else
18820+ err = -EBUSY;
18821+ spin_unlock(&sbinfo->si_plink_maint_lock);
18822+ }
4a4d8108
AM
18823+ si_write_unlock(sb);
18824+
18825+ return err;
1facf9fc 18826+}
18827+
18828+/* ---------------------------------------------------------------------- */
18829+
18830+struct pseudo_link {
4a4d8108
AM
18831+ union {
18832+ struct list_head list;
18833+ struct rcu_head rcu;
18834+ };
1facf9fc 18835+ struct inode *inode;
18836+};
18837+
18838+#ifdef CONFIG_AUFS_DEBUG
18839+void au_plink_list(struct super_block *sb)
18840+{
18841+ struct au_sbinfo *sbinfo;
18842+ struct list_head *plink_list;
18843+ struct pseudo_link *plink;
18844+
dece6358
AM
18845+ SiMustAnyLock(sb);
18846+
1facf9fc 18847+ sbinfo = au_sbi(sb);
18848+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 18849+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 18850+
18851+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18852+ rcu_read_lock();
18853+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 18854+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 18855+ rcu_read_unlock();
1facf9fc 18856+}
18857+#endif
18858+
18859+/* is the inode pseudo-linked? */
18860+int au_plink_test(struct inode *inode)
18861+{
18862+ int found;
18863+ struct au_sbinfo *sbinfo;
18864+ struct list_head *plink_list;
18865+ struct pseudo_link *plink;
18866+
18867+ sbinfo = au_sbi(inode->i_sb);
dece6358 18868+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 18869+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 18870+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 18871+
18872+ found = 0;
18873+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18874+ rcu_read_lock();
18875+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 18876+ if (plink->inode == inode) {
18877+ found = 1;
18878+ break;
18879+ }
4a4d8108 18880+ rcu_read_unlock();
1facf9fc 18881+ return found;
18882+}
18883+
18884+/* ---------------------------------------------------------------------- */
18885+
18886+/*
18887+ * generate a name for plink.
18888+ * the file will be stored under AUFS_WH_PLINKDIR.
18889+ */
18890+/* 20 is max digits length of ulong 64 */
18891+#define PLINK_NAME_LEN ((20 + 1) * 2)
18892+
18893+static int plink_name(char *name, int len, struct inode *inode,
18894+ aufs_bindex_t bindex)
18895+{
18896+ int rlen;
18897+ struct inode *h_inode;
18898+
18899+ h_inode = au_h_iptr(inode, bindex);
18900+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
18901+ return rlen;
18902+}
18903+
7f207e10
AM
18904+struct au_do_plink_lkup_args {
18905+ struct dentry **errp;
18906+ struct qstr *tgtname;
18907+ struct dentry *h_parent;
18908+ struct au_branch *br;
18909+};
18910+
18911+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
18912+ struct dentry *h_parent,
18913+ struct au_branch *br)
18914+{
18915+ struct dentry *h_dentry;
18916+ struct mutex *h_mtx;
18917+
18918+ h_mtx = &h_parent->d_inode->i_mutex;
18919+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
18920+ h_dentry = au_lkup_one(tgtname, h_parent, br, /*nd*/NULL);
18921+ mutex_unlock(h_mtx);
18922+ return h_dentry;
18923+}
18924+
18925+static void au_call_do_plink_lkup(void *args)
18926+{
18927+ struct au_do_plink_lkup_args *a = args;
18928+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
18929+}
18930+
1facf9fc 18931+/* lookup the plink-ed @inode under the branch at @bindex */
18932+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
18933+{
18934+ struct dentry *h_dentry, *h_parent;
18935+ struct au_branch *br;
18936+ struct inode *h_dir;
7f207e10 18937+ int wkq_err;
1facf9fc 18938+ char a[PLINK_NAME_LEN];
18939+ struct qstr tgtname = {
18940+ .name = a
18941+ };
18942+
e49829fe
JR
18943+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
18944+
1facf9fc 18945+ br = au_sbr(inode->i_sb, bindex);
18946+ h_parent = br->br_wbr->wbr_plink;
18947+ h_dir = h_parent->d_inode;
18948+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
18949+
7f207e10
AM
18950+ if (current_fsuid()) {
18951+ struct au_do_plink_lkup_args args = {
18952+ .errp = &h_dentry,
18953+ .tgtname = &tgtname,
18954+ .h_parent = h_parent,
18955+ .br = br
18956+ };
18957+
18958+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
18959+ if (unlikely(wkq_err))
18960+ h_dentry = ERR_PTR(wkq_err);
18961+ } else
18962+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
18963+
1facf9fc 18964+ return h_dentry;
18965+}
18966+
18967+/* create a pseudo-link */
18968+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
18969+ struct dentry *h_dentry, struct au_branch *br)
18970+{
18971+ int err;
18972+ struct path h_path = {
18973+ .mnt = br->br_mnt
18974+ };
18975+ struct inode *h_dir;
18976+
18977+ h_dir = h_parent->d_inode;
7f207e10 18978+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
4f0767ce 18979+again:
1facf9fc 18980+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
18981+ err = PTR_ERR(h_path.dentry);
18982+ if (IS_ERR(h_path.dentry))
18983+ goto out;
18984+
18985+ err = 0;
18986+ /* wh.plink dir is not monitored */
7f207e10 18987+ /* todo: is it really safe? */
1facf9fc 18988+ if (h_path.dentry->d_inode
18989+ && h_path.dentry->d_inode != h_dentry->d_inode) {
18990+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
18991+ dput(h_path.dentry);
18992+ h_path.dentry = NULL;
18993+ if (!err)
18994+ goto again;
18995+ }
18996+ if (!err && !h_path.dentry->d_inode)
18997+ err = vfsub_link(h_dentry, h_dir, &h_path);
18998+ dput(h_path.dentry);
18999+
4f0767ce 19000+out:
7f207e10 19001+ mutex_unlock(&h_dir->i_mutex);
1facf9fc 19002+ return err;
19003+}
19004+
19005+struct do_whplink_args {
19006+ int *errp;
19007+ struct qstr *tgt;
19008+ struct dentry *h_parent;
19009+ struct dentry *h_dentry;
19010+ struct au_branch *br;
19011+};
19012+
19013+static void call_do_whplink(void *args)
19014+{
19015+ struct do_whplink_args *a = args;
19016+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
19017+}
19018+
19019+static int whplink(struct dentry *h_dentry, struct inode *inode,
19020+ aufs_bindex_t bindex, struct au_branch *br)
19021+{
19022+ int err, wkq_err;
19023+ struct au_wbr *wbr;
19024+ struct dentry *h_parent;
19025+ struct inode *h_dir;
19026+ char a[PLINK_NAME_LEN];
19027+ struct qstr tgtname = {
19028+ .name = a
19029+ };
19030+
19031+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
19032+ h_parent = wbr->wbr_plink;
19033+ h_dir = h_parent->d_inode;
19034+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
19035+
19036+ /* always superio. */
b752ccd1 19037+ if (current_fsuid()) {
1facf9fc 19038+ struct do_whplink_args args = {
19039+ .errp = &err,
19040+ .tgt = &tgtname,
19041+ .h_parent = h_parent,
19042+ .h_dentry = h_dentry,
19043+ .br = br
19044+ };
19045+ wkq_err = au_wkq_wait(call_do_whplink, &args);
19046+ if (unlikely(wkq_err))
19047+ err = wkq_err;
19048+ } else
19049+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 19050+
19051+ return err;
19052+}
19053+
19054+/* free a single plink */
19055+static void do_put_plink(struct pseudo_link *plink, int do_del)
19056+{
1facf9fc 19057+ if (do_del)
19058+ list_del(&plink->list);
4a4d8108
AM
19059+ iput(plink->inode);
19060+ kfree(plink);
19061+}
19062+
19063+static void do_put_plink_rcu(struct rcu_head *rcu)
19064+{
19065+ struct pseudo_link *plink;
19066+
19067+ plink = container_of(rcu, struct pseudo_link, rcu);
19068+ iput(plink->inode);
1facf9fc 19069+ kfree(plink);
19070+}
19071+
19072+/*
19073+ * create a new pseudo-link for @h_dentry on @bindex.
19074+ * the linked inode is held in aufs @inode.
19075+ */
19076+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
19077+ struct dentry *h_dentry)
19078+{
19079+ struct super_block *sb;
19080+ struct au_sbinfo *sbinfo;
19081+ struct list_head *plink_list;
4a4d8108 19082+ struct pseudo_link *plink, *tmp;
1facf9fc 19083+ int found, err, cnt;
19084+
19085+ sb = inode->i_sb;
19086+ sbinfo = au_sbi(sb);
19087+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19088+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19089+
1facf9fc 19090+ cnt = 0;
19091+ found = 0;
19092+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19093+ rcu_read_lock();
19094+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 19095+ cnt++;
19096+ if (plink->inode == inode) {
19097+ found = 1;
19098+ break;
19099+ }
19100+ }
4a4d8108
AM
19101+ rcu_read_unlock();
19102+ if (found)
1facf9fc 19103+ return;
4a4d8108
AM
19104+
19105+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
19106+ if (tmp)
19107+ tmp->inode = au_igrab(inode);
19108+ else {
19109+ err = -ENOMEM;
19110+ goto out;
1facf9fc 19111+ }
19112+
4a4d8108
AM
19113+ spin_lock(&sbinfo->si_plink.spin);
19114+ list_for_each_entry(plink, plink_list, list) {
19115+ if (plink->inode == inode) {
19116+ found = 1;
19117+ break;
19118+ }
1facf9fc 19119+ }
4a4d8108
AM
19120+ if (!found)
19121+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 19122+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
19123+ if (!found) {
19124+ cnt++;
19125+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
19126+ "unexpectedly many pseudo links, %d\n", cnt);
1facf9fc 19127+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
19128+ } else {
19129+ do_put_plink(tmp, 0);
19130+ return;
1facf9fc 19131+ }
19132+
4a4d8108 19133+out:
1facf9fc 19134+ if (unlikely(err)) {
4a4d8108
AM
19135+ pr_warning("err %d, damaged pseudo link.\n", err);
19136+ if (tmp) {
19137+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
19138+ call_rcu(&tmp->rcu, do_put_plink_rcu);
19139+ }
1facf9fc 19140+ }
19141+}
19142+
19143+/* free all plinks */
e49829fe 19144+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 19145+{
19146+ struct au_sbinfo *sbinfo;
19147+ struct list_head *plink_list;
19148+ struct pseudo_link *plink, *tmp;
19149+
dece6358
AM
19150+ SiMustWriteLock(sb);
19151+
1facf9fc 19152+ sbinfo = au_sbi(sb);
19153+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19154+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19155+
19156+ plink_list = &sbinfo->si_plink.head;
19157+ /* no spin_lock since sbinfo is write-locked */
e49829fe 19158+ WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
1facf9fc 19159+ list_for_each_entry_safe(plink, tmp, plink_list, list)
19160+ do_put_plink(plink, 0);
19161+ INIT_LIST_HEAD(plink_list);
19162+}
19163+
e49829fe
JR
19164+void au_plink_clean(struct super_block *sb, int verbose)
19165+{
19166+ struct dentry *root;
19167+
19168+ root = sb->s_root;
19169+ aufs_write_lock(root);
19170+ if (au_opt_test(au_mntflags(sb), PLINK))
19171+ au_plink_put(sb, verbose);
19172+ aufs_write_unlock(root);
19173+}
19174+
1facf9fc 19175+/* free the plinks on a branch specified by @br_id */
19176+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
19177+{
19178+ struct au_sbinfo *sbinfo;
19179+ struct list_head *plink_list;
19180+ struct pseudo_link *plink, *tmp;
19181+ struct inode *inode;
19182+ aufs_bindex_t bstart, bend, bindex;
19183+ unsigned char do_put;
19184+
dece6358
AM
19185+ SiMustWriteLock(sb);
19186+
1facf9fc 19187+ sbinfo = au_sbi(sb);
19188+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19189+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19190+
19191+ plink_list = &sbinfo->si_plink.head;
19192+ /* no spin_lock since sbinfo is write-locked */
19193+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
19194+ do_put = 0;
19195+ inode = au_igrab(plink->inode);
19196+ ii_write_lock_child(inode);
19197+ bstart = au_ibstart(inode);
19198+ bend = au_ibend(inode);
19199+ if (bstart >= 0) {
19200+ for (bindex = bstart; bindex <= bend; bindex++) {
19201+ if (!au_h_iptr(inode, bindex)
19202+ || au_ii_br_id(inode, bindex) != br_id)
19203+ continue;
19204+ au_set_h_iptr(inode, bindex, NULL, 0);
19205+ do_put = 1;
19206+ break;
19207+ }
19208+ } else
19209+ do_put_plink(plink, 1);
19210+
dece6358
AM
19211+ if (do_put) {
19212+ for (bindex = bstart; bindex <= bend; bindex++)
19213+ if (au_h_iptr(inode, bindex)) {
19214+ do_put = 0;
19215+ break;
19216+ }
19217+ if (do_put)
19218+ do_put_plink(plink, 1);
19219+ }
19220+ ii_write_unlock(inode);
19221+ iput(inode);
19222+ }
19223+}
7f207e10
AM
19224diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
19225--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
19226+++ linux/fs/aufs/poll.c 2010-11-22 11:52:56.990562128 +0100
dece6358
AM
19227@@ -0,0 +1,56 @@
19228+/*
4a4d8108 19229+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
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.
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
19244+ */
19245+
1308ab2a 19246+/*
19247+ * poll operation
19248+ * There is only one filesystem which implements ->poll operation, currently.
19249+ */
19250+
19251+#include "aufs.h"
19252+
19253+unsigned int aufs_poll(struct file *file, poll_table *wait)
19254+{
19255+ unsigned int mask;
19256+ int err;
19257+ struct file *h_file;
19258+ struct dentry *dentry;
19259+ struct super_block *sb;
19260+
19261+ /* We should pretend an error happened. */
19262+ mask = POLLERR /* | POLLIN | POLLOUT */;
19263+ dentry = file->f_dentry;
19264+ sb = dentry->d_sb;
e49829fe 19265+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 19266+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
19267+ if (unlikely(err))
19268+ goto out;
19269+
19270+ /* it is not an error if h_file has no operation */
19271+ mask = DEFAULT_POLLMASK;
4a4d8108 19272+ h_file = au_hf_top(file);
1308ab2a 19273+ if (h_file->f_op && h_file->f_op->poll)
19274+ mask = h_file->f_op->poll(h_file, wait);
19275+
19276+ di_read_unlock(dentry, AuLock_IR);
19277+ fi_read_unlock(file);
19278+
4f0767ce 19279+out:
1308ab2a 19280+ si_read_unlock(sb);
19281+ AuTraceErr((int)mask);
19282+ return mask;
19283+}
7f207e10
AM
19284diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
19285--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
19286+++ linux/fs/aufs/procfs.c 2010-11-22 11:52:56.990562128 +0100
e49829fe
JR
19287@@ -0,0 +1,169 @@
19288+/*
19289+ * Copyright (C) 2010 Junjiro R. Okajima
19290+ *
19291+ * This program, aufs is free software; you can redistribute it and/or modify
19292+ * it under the terms of the GNU General Public License as published by
19293+ * the Free Software Foundation; either version 2 of the License, or
19294+ * (at your option) any later version.
19295+ *
19296+ * This program is distributed in the hope that it will be useful,
19297+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19298+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19299+ * GNU General Public License for more details.
19300+ *
19301+ * You should have received a copy of the GNU General Public License
19302+ * along with this program; if not, write to the Free Software
19303+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19304+ */
19305+
19306+/*
19307+ * procfs interfaces
19308+ */
19309+
19310+#include <linux/proc_fs.h>
19311+#include "aufs.h"
19312+
19313+static int au_procfs_plm_release(struct inode *inode, struct file *file)
19314+{
19315+ struct au_sbinfo *sbinfo;
19316+
19317+ sbinfo = file->private_data;
19318+ if (sbinfo) {
19319+ au_plink_maint_leave(sbinfo);
19320+ kobject_put(&sbinfo->si_kobj);
19321+ }
19322+
19323+ return 0;
19324+}
19325+
19326+static void au_procfs_plm_write_clean(struct file *file)
19327+{
19328+ struct au_sbinfo *sbinfo;
19329+
19330+ sbinfo = file->private_data;
19331+ if (sbinfo)
19332+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
19333+}
19334+
19335+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
19336+{
19337+ int err;
19338+ struct super_block *sb;
19339+ struct au_sbinfo *sbinfo;
19340+
19341+ err = -EBUSY;
19342+ if (unlikely(file->private_data))
19343+ goto out;
19344+
19345+ sb = NULL;
19346+ spin_lock(&au_sbilist.spin);
19347+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
19348+ if (id == sysaufs_si_id(sbinfo)) {
19349+ kobject_get(&sbinfo->si_kobj);
19350+ sb = sbinfo->si_sb;
19351+ break;
19352+ }
19353+ spin_unlock(&au_sbilist.spin);
19354+
19355+ err = -EINVAL;
19356+ if (unlikely(!sb))
19357+ goto out;
19358+
19359+ err = au_plink_maint_enter(sb);
19360+ if (!err)
19361+ /* keep kobject_get() */
19362+ file->private_data = sbinfo;
19363+ else
19364+ kobject_put(&sbinfo->si_kobj);
19365+out:
19366+ return err;
19367+}
19368+
19369+/*
19370+ * Accept a valid "si=xxxx" only.
19371+ * Once it is accepted successfully, accept "clean" too.
19372+ */
19373+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
19374+ size_t count, loff_t *ppos)
19375+{
19376+ ssize_t err;
19377+ unsigned long id;
19378+ /* last newline is allowed */
19379+ char buf[3 + sizeof(unsigned long) * 2 + 1];
19380+
19381+ err = -EACCES;
19382+ if (unlikely(!capable(CAP_SYS_ADMIN)))
19383+ goto out;
19384+
19385+ err = -EINVAL;
19386+ if (unlikely(count > sizeof(buf)))
19387+ goto out;
19388+
19389+ err = copy_from_user(buf, ubuf, count);
19390+ if (unlikely(err)) {
19391+ err = -EFAULT;
19392+ goto out;
19393+ }
19394+ buf[count] = 0;
19395+
19396+ err = -EINVAL;
19397+ if (!strcmp("clean", buf)) {
19398+ au_procfs_plm_write_clean(file);
19399+ goto out_success;
19400+ } else if (unlikely(strncmp("si=", buf, 3)))
19401+ goto out;
19402+
19403+ err = strict_strtoul(buf + 3, 16, &id);
19404+ if (unlikely(err))
19405+ goto out;
19406+
19407+ err = au_procfs_plm_write_si(file, id);
19408+ if (unlikely(err))
19409+ goto out;
19410+
19411+out_success:
19412+ err = count; /* success */
19413+out:
19414+ return err;
19415+}
19416+
19417+static const struct file_operations au_procfs_plm_fop = {
19418+ .write = au_procfs_plm_write,
19419+ .release = au_procfs_plm_release,
19420+ .owner = THIS_MODULE
19421+};
19422+
19423+/* ---------------------------------------------------------------------- */
19424+
19425+static struct proc_dir_entry *au_procfs_dir;
19426+
19427+void au_procfs_fin(void)
19428+{
19429+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
19430+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
19431+}
19432+
19433+int __init au_procfs_init(void)
19434+{
19435+ int err;
19436+ struct proc_dir_entry *entry;
19437+
19438+ err = -ENOMEM;
19439+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
19440+ if (unlikely(!au_procfs_dir))
19441+ goto out;
19442+
19443+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
19444+ au_procfs_dir, &au_procfs_plm_fop);
19445+ if (unlikely(!entry))
19446+ goto out_dir;
19447+
19448+ err = 0;
19449+ goto out; /* success */
19450+
19451+
19452+out_dir:
19453+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
19454+out:
19455+ return err;
19456+}
7f207e10
AM
19457diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
19458--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
19459+++ linux/fs/aufs/rdu.c 2010-11-22 11:52:56.990562128 +0100
19460@@ -0,0 +1,382 @@
1308ab2a 19461+/*
4a4d8108 19462+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 19463+ *
19464+ * This program, aufs is free software; you can redistribute it and/or modify
19465+ * it under the terms of the GNU General Public License as published by
19466+ * the Free Software Foundation; either version 2 of the License, or
19467+ * (at your option) any later version.
19468+ *
19469+ * This program is distributed in the hope that it will be useful,
19470+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19471+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19472+ * GNU General Public License for more details.
19473+ *
19474+ * You should have received a copy of the GNU General Public License
19475+ * along with this program; if not, write to the Free Software
19476+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19477+ */
19478+
19479+/*
19480+ * readdir in userspace.
19481+ */
19482+
b752ccd1 19483+#include <linux/compat.h>
4a4d8108 19484+#include <linux/fs_stack.h>
1308ab2a 19485+#include <linux/security.h>
19486+#include <linux/uaccess.h>
19487+#include <linux/aufs_type.h>
19488+#include "aufs.h"
19489+
19490+/* bits for struct aufs_rdu.flags */
19491+#define AuRdu_CALLED 1
19492+#define AuRdu_CONT (1 << 1)
19493+#define AuRdu_FULL (1 << 2)
19494+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
19495+#define au_fset_rdu(flags, name) \
19496+ do { (flags) |= AuRdu_##name; } while (0)
19497+#define au_fclr_rdu(flags, name) \
19498+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 19499+
19500+struct au_rdu_arg {
19501+ struct aufs_rdu *rdu;
19502+ union au_rdu_ent_ul ent;
19503+ unsigned long end;
19504+
19505+ struct super_block *sb;
19506+ int err;
19507+};
19508+
19509+static int au_rdu_fill(void *__arg, const char *name, int nlen,
19510+ loff_t offset, u64 h_ino, unsigned int d_type)
19511+{
19512+ int err, len;
19513+ struct au_rdu_arg *arg = __arg;
19514+ struct aufs_rdu *rdu = arg->rdu;
19515+ struct au_rdu_ent ent;
19516+
19517+ err = 0;
19518+ arg->err = 0;
19519+ au_fset_rdu(rdu->cookie.flags, CALLED);
19520+ len = au_rdu_len(nlen);
19521+ if (arg->ent.ul + len < arg->end) {
19522+ ent.ino = h_ino;
19523+ ent.bindex = rdu->cookie.bindex;
19524+ ent.type = d_type;
19525+ ent.nlen = nlen;
4a4d8108
AM
19526+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
19527+ ent.type = DT_UNKNOWN;
1308ab2a 19528+
19529+ err = -EFAULT;
19530+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
19531+ goto out;
19532+ if (copy_to_user(arg->ent.e->name, name, nlen))
19533+ goto out;
19534+ /* the terminating NULL */
19535+ if (__put_user(0, arg->ent.e->name + nlen))
19536+ goto out;
19537+ err = 0;
19538+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
19539+ arg->ent.ul += len;
19540+ rdu->rent++;
19541+ } else {
19542+ err = -EFAULT;
19543+ au_fset_rdu(rdu->cookie.flags, FULL);
19544+ rdu->full = 1;
19545+ rdu->tail = arg->ent;
19546+ }
19547+
4f0767ce 19548+out:
1308ab2a 19549+ /* AuTraceErr(err); */
19550+ return err;
19551+}
19552+
19553+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
19554+{
19555+ int err;
19556+ loff_t offset;
19557+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
19558+
19559+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
19560+ err = offset;
19561+ if (unlikely(offset != cookie->h_pos))
19562+ goto out;
19563+
19564+ err = 0;
19565+ do {
19566+ arg->err = 0;
19567+ au_fclr_rdu(cookie->flags, CALLED);
19568+ /* smp_mb(); */
19569+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
19570+ if (err >= 0)
19571+ err = arg->err;
19572+ } while (!err
19573+ && au_ftest_rdu(cookie->flags, CALLED)
19574+ && !au_ftest_rdu(cookie->flags, FULL));
19575+ cookie->h_pos = h_file->f_pos;
19576+
4f0767ce 19577+out:
1308ab2a 19578+ AuTraceErr(err);
19579+ return err;
19580+}
19581+
19582+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
19583+{
19584+ int err;
19585+ aufs_bindex_t bend;
19586+ struct au_rdu_arg arg;
19587+ struct dentry *dentry;
19588+ struct inode *inode;
19589+ struct file *h_file;
19590+ struct au_rdu_cookie *cookie = &rdu->cookie;
19591+
19592+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
19593+ if (unlikely(err)) {
19594+ err = -EFAULT;
19595+ AuTraceErr(err);
19596+ goto out;
19597+ }
19598+ rdu->rent = 0;
19599+ rdu->tail = rdu->ent;
19600+ rdu->full = 0;
19601+ arg.rdu = rdu;
19602+ arg.ent = rdu->ent;
19603+ arg.end = arg.ent.ul;
19604+ arg.end += rdu->sz;
19605+
19606+ err = -ENOTDIR;
19607+ if (unlikely(!file->f_op || !file->f_op->readdir))
19608+ goto out;
19609+
19610+ err = security_file_permission(file, MAY_READ);
19611+ AuTraceErr(err);
19612+ if (unlikely(err))
19613+ goto out;
19614+
19615+ dentry = file->f_dentry;
19616+ inode = dentry->d_inode;
19617+#if 1
19618+ mutex_lock(&inode->i_mutex);
19619+#else
19620+ err = mutex_lock_killable(&inode->i_mutex);
19621+ AuTraceErr(err);
19622+ if (unlikely(err))
19623+ goto out;
19624+#endif
19625+ err = -ENOENT;
19626+ if (unlikely(IS_DEADDIR(inode)))
19627+ goto out_mtx;
19628+
19629+ arg.sb = inode->i_sb;
e49829fe
JR
19630+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
19631+ if (unlikely(err))
19632+ goto out_mtx;
19633+ /* todo: reval? */
1308ab2a 19634+ fi_read_lock(file);
19635+
19636+ err = -EAGAIN;
19637+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
19638+ && cookie->generation != au_figen(file)))
19639+ goto out_unlock;
19640+
19641+ err = 0;
19642+ if (!rdu->blk) {
19643+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
19644+ if (!rdu->blk)
19645+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
19646+ }
19647+ bend = au_fbstart(file);
19648+ if (cookie->bindex < bend)
19649+ cookie->bindex = bend;
4a4d8108 19650+ bend = au_fbend_dir(file);
1308ab2a 19651+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
19652+ for (; !err && cookie->bindex <= bend;
19653+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 19654+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 19655+ if (!h_file)
19656+ continue;
19657+
19658+ au_fclr_rdu(cookie->flags, FULL);
19659+ err = au_rdu_do(h_file, &arg);
19660+ AuTraceErr(err);
19661+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
19662+ break;
19663+ }
19664+ AuDbg("rent %llu\n", rdu->rent);
19665+
19666+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
19667+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
19668+ au_fset_rdu(cookie->flags, CONT);
19669+ cookie->generation = au_figen(file);
19670+ }
19671+
19672+ ii_read_lock_child(inode);
19673+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
19674+ ii_read_unlock(inode);
19675+
4f0767ce 19676+out_unlock:
1308ab2a 19677+ fi_read_unlock(file);
19678+ si_read_unlock(arg.sb);
4f0767ce 19679+out_mtx:
1308ab2a 19680+ mutex_unlock(&inode->i_mutex);
4f0767ce 19681+out:
1308ab2a 19682+ AuTraceErr(err);
19683+ return err;
19684+}
19685+
19686+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
19687+{
19688+ int err;
19689+ ino_t ino;
19690+ unsigned long long nent;
19691+ union au_rdu_ent_ul *u;
19692+ struct au_rdu_ent ent;
19693+ struct super_block *sb;
19694+
19695+ err = 0;
19696+ nent = rdu->nent;
19697+ u = &rdu->ent;
19698+ sb = file->f_dentry->d_sb;
19699+ si_read_lock(sb, AuLock_FLUSH);
19700+ while (nent-- > 0) {
1308ab2a 19701+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
19702+ if (!err)
19703+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 19704+ if (unlikely(err)) {
19705+ err = -EFAULT;
19706+ AuTraceErr(err);
19707+ break;
19708+ }
19709+
19710+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
19711+ if (!ent.wh)
19712+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
19713+ else
19714+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
19715+ &ino);
19716+ if (unlikely(err)) {
19717+ AuTraceErr(err);
19718+ break;
19719+ }
19720+
19721+ err = __put_user(ino, &u->e->ino);
19722+ if (unlikely(err)) {
19723+ err = -EFAULT;
19724+ AuTraceErr(err);
19725+ break;
19726+ }
19727+ u->ul += au_rdu_len(ent.nlen);
19728+ }
19729+ si_read_unlock(sb);
19730+
19731+ return err;
19732+}
19733+
19734+/* ---------------------------------------------------------------------- */
19735+
19736+static int au_rdu_verify(struct aufs_rdu *rdu)
19737+{
b752ccd1 19738+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 19739+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 19740+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 19741+ rdu->blk,
19742+ rdu->rent, rdu->shwh, rdu->full,
19743+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
19744+ rdu->cookie.generation);
dece6358 19745+
b752ccd1 19746+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 19747+ return 0;
dece6358 19748+
b752ccd1
AM
19749+ AuDbg("%u:%u\n",
19750+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 19751+ return -EINVAL;
19752+}
19753+
19754+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 19755+{
1308ab2a 19756+ long err, e;
19757+ struct aufs_rdu rdu;
19758+ void __user *p = (void __user *)arg;
dece6358 19759+
1308ab2a 19760+ err = copy_from_user(&rdu, p, sizeof(rdu));
19761+ if (unlikely(err)) {
19762+ err = -EFAULT;
19763+ AuTraceErr(err);
19764+ goto out;
19765+ }
19766+ err = au_rdu_verify(&rdu);
dece6358
AM
19767+ if (unlikely(err))
19768+ goto out;
19769+
1308ab2a 19770+ switch (cmd) {
19771+ case AUFS_CTL_RDU:
19772+ err = au_rdu(file, &rdu);
19773+ if (unlikely(err))
19774+ break;
dece6358 19775+
1308ab2a 19776+ e = copy_to_user(p, &rdu, sizeof(rdu));
19777+ if (unlikely(e)) {
19778+ err = -EFAULT;
19779+ AuTraceErr(err);
19780+ }
19781+ break;
19782+ case AUFS_CTL_RDU_INO:
19783+ err = au_rdu_ino(file, &rdu);
19784+ break;
19785+
19786+ default:
4a4d8108 19787+ /* err = -ENOTTY; */
1308ab2a 19788+ err = -EINVAL;
19789+ }
dece6358 19790+
4f0767ce 19791+out:
1308ab2a 19792+ AuTraceErr(err);
19793+ return err;
1facf9fc 19794+}
b752ccd1
AM
19795+
19796+#ifdef CONFIG_COMPAT
19797+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
19798+{
19799+ long err, e;
19800+ struct aufs_rdu rdu;
19801+ void __user *p = compat_ptr(arg);
19802+
19803+ /* todo: get_user()? */
19804+ err = copy_from_user(&rdu, p, sizeof(rdu));
19805+ if (unlikely(err)) {
19806+ err = -EFAULT;
19807+ AuTraceErr(err);
19808+ goto out;
19809+ }
19810+ rdu.ent.e = compat_ptr(rdu.ent.ul);
19811+ err = au_rdu_verify(&rdu);
19812+ if (unlikely(err))
19813+ goto out;
19814+
19815+ switch (cmd) {
19816+ case AUFS_CTL_RDU:
19817+ err = au_rdu(file, &rdu);
19818+ if (unlikely(err))
19819+ break;
19820+
19821+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
19822+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
19823+ e = copy_to_user(p, &rdu, sizeof(rdu));
19824+ if (unlikely(e)) {
19825+ err = -EFAULT;
19826+ AuTraceErr(err);
19827+ }
19828+ break;
19829+ case AUFS_CTL_RDU_INO:
19830+ err = au_rdu_ino(file, &rdu);
19831+ break;
19832+
19833+ default:
19834+ /* err = -ENOTTY; */
19835+ err = -EINVAL;
19836+ }
19837+
4f0767ce 19838+out:
b752ccd1
AM
19839+ AuTraceErr(err);
19840+ return err;
19841+}
19842+#endif
7f207e10
AM
19843diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
19844--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
19845+++ linux/fs/aufs/rwsem.h 2010-11-22 11:52:56.993896008 +0100
e49829fe 19846@@ -0,0 +1,189 @@
1facf9fc 19847+/*
4a4d8108 19848+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19849+ *
19850+ * This program, aufs is free software; you can redistribute it and/or modify
19851+ * it under the terms of the GNU General Public License as published by
19852+ * the Free Software Foundation; either version 2 of the License, or
19853+ * (at your option) any later version.
dece6358
AM
19854+ *
19855+ * This program is distributed in the hope that it will be useful,
19856+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19857+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19858+ * GNU General Public License for more details.
19859+ *
19860+ * You should have received a copy of the GNU General Public License
19861+ * along with this program; if not, write to the Free Software
19862+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19863+ */
19864+
19865+/*
19866+ * simple read-write semaphore wrappers
19867+ */
19868+
19869+#ifndef __AUFS_RWSEM_H__
19870+#define __AUFS_RWSEM_H__
19871+
19872+#ifdef __KERNEL__
19873+
dece6358 19874+#include <linux/rwsem.h>
4a4d8108 19875+#include "debug.h"
dece6358
AM
19876+
19877+struct au_rwsem {
19878+ struct rw_semaphore rwsem;
19879+#ifdef CONFIG_AUFS_DEBUG
19880+ /* just for debugging, not almighty counter */
19881+ atomic_t rcnt, wcnt;
19882+#endif
19883+};
19884+
19885+#ifdef CONFIG_AUFS_DEBUG
19886+#define AuDbgCntInit(rw) do { \
19887+ atomic_set(&(rw)->rcnt, 0); \
19888+ atomic_set(&(rw)->wcnt, 0); \
19889+ smp_mb(); /* atomic set */ \
19890+} while (0)
19891+
e49829fe 19892+#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
dece6358 19893+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
e49829fe 19894+#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
dece6358
AM
19895+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
19896+#else
19897+#define AuDbgCntInit(rw) do {} while (0)
19898+#define AuDbgRcntInc(rw) do {} while (0)
19899+#define AuDbgRcntDec(rw) do {} while (0)
19900+#define AuDbgWcntInc(rw) do {} while (0)
19901+#define AuDbgWcntDec(rw) do {} while (0)
19902+#endif /* CONFIG_AUFS_DEBUG */
19903+
19904+/* to debug easier, do not make them inlined functions */
19905+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
19906+/* rwsem_is_locked() is unusable */
19907+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
19908+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
19909+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
19910+ && atomic_read(&(rw)->wcnt) <= 0)
19911+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
19912+ || atomic_read(&(rw)->wcnt))
19913+
e49829fe
JR
19914+#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
19915+
dece6358
AM
19916+static inline void au_rw_init(struct au_rwsem *rw)
19917+{
19918+ AuDbgCntInit(rw);
19919+ init_rwsem(&rw->rwsem);
19920+}
19921+
19922+static inline void au_rw_init_wlock(struct au_rwsem *rw)
19923+{
19924+ au_rw_init(rw);
19925+ down_write(&rw->rwsem);
19926+ AuDbgWcntInc(rw);
19927+}
19928+
19929+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
19930+ unsigned int lsc)
19931+{
19932+ au_rw_init(rw);
19933+ down_write_nested(&rw->rwsem, lsc);
19934+ AuDbgWcntInc(rw);
19935+}
19936+
19937+static inline void au_rw_read_lock(struct au_rwsem *rw)
19938+{
19939+ down_read(&rw->rwsem);
19940+ AuDbgRcntInc(rw);
19941+}
19942+
19943+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
19944+{
19945+ down_read_nested(&rw->rwsem, lsc);
19946+ AuDbgRcntInc(rw);
19947+}
19948+
19949+static inline void au_rw_read_unlock(struct au_rwsem *rw)
19950+{
19951+ AuRwMustReadLock(rw);
19952+ AuDbgRcntDec(rw);
19953+ up_read(&rw->rwsem);
19954+}
19955+
19956+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
19957+{
19958+ AuRwMustWriteLock(rw);
19959+ AuDbgRcntInc(rw);
19960+ AuDbgWcntDec(rw);
19961+ downgrade_write(&rw->rwsem);
19962+}
19963+
19964+static inline void au_rw_write_lock(struct au_rwsem *rw)
19965+{
19966+ down_write(&rw->rwsem);
19967+ AuDbgWcntInc(rw);
19968+}
19969+
19970+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
19971+ unsigned int lsc)
19972+{
19973+ down_write_nested(&rw->rwsem, lsc);
19974+ AuDbgWcntInc(rw);
19975+}
1facf9fc 19976+
dece6358
AM
19977+static inline void au_rw_write_unlock(struct au_rwsem *rw)
19978+{
19979+ AuRwMustWriteLock(rw);
19980+ AuDbgWcntDec(rw);
19981+ up_write(&rw->rwsem);
19982+}
19983+
19984+/* why is not _nested version defined */
19985+static inline int au_rw_read_trylock(struct au_rwsem *rw)
19986+{
19987+ int ret = down_read_trylock(&rw->rwsem);
19988+ if (ret)
19989+ AuDbgRcntInc(rw);
19990+ return ret;
19991+}
19992+
19993+static inline int au_rw_write_trylock(struct au_rwsem *rw)
19994+{
19995+ int ret = down_write_trylock(&rw->rwsem);
19996+ if (ret)
19997+ AuDbgWcntInc(rw);
19998+ return ret;
19999+}
20000+
20001+#undef AuDbgCntInit
20002+#undef AuDbgRcntInc
20003+#undef AuDbgRcntDec
20004+#undef AuDbgWcntInc
20005+#undef AuDbgWcntDec
1facf9fc 20006+
20007+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
20008+static inline void prefix##_read_lock(param) \
dece6358 20009+{ au_rw_read_lock(rwsem); } \
1facf9fc 20010+static inline void prefix##_write_lock(param) \
dece6358 20011+{ au_rw_write_lock(rwsem); } \
1facf9fc 20012+static inline int prefix##_read_trylock(param) \
dece6358 20013+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 20014+static inline int prefix##_write_trylock(param) \
dece6358 20015+{ return au_rw_write_trylock(rwsem); }
1facf9fc 20016+/* why is not _nested version defined */
20017+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 20018+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 20019+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 20020+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 20021+
20022+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
20023+static inline void prefix##_read_unlock(param) \
dece6358 20024+{ au_rw_read_unlock(rwsem); } \
1facf9fc 20025+static inline void prefix##_write_unlock(param) \
dece6358 20026+{ au_rw_write_unlock(rwsem); } \
1facf9fc 20027+static inline void prefix##_downgrade_lock(param) \
dece6358 20028+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 20029+
20030+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
20031+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
20032+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
20033+
20034+#endif /* __KERNEL__ */
20035+#endif /* __AUFS_RWSEM_H__ */
7f207e10
AM
20036diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
20037--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
20038+++ linux/fs/aufs/sbinfo.c 2010-11-22 11:52:56.993896008 +0100
20039@@ -0,0 +1,316 @@
1facf9fc 20040+/*
4a4d8108 20041+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20042+ *
20043+ * This program, aufs is free software; you can redistribute it and/or modify
20044+ * it under the terms of the GNU General Public License as published by
20045+ * the Free Software Foundation; either version 2 of the License, or
20046+ * (at your option) any later version.
dece6358
AM
20047+ *
20048+ * This program is distributed in the hope that it will be useful,
20049+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20050+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20051+ * GNU General Public License for more details.
20052+ *
20053+ * You should have received a copy of the GNU General Public License
20054+ * along with this program; if not, write to the Free Software
20055+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20056+ */
20057+
20058+/*
20059+ * superblock private data
20060+ */
20061+
e49829fe 20062+#include <linux/jiffies.h>
1facf9fc 20063+#include "aufs.h"
20064+
20065+/*
20066+ * they are necessary regardless sysfs is disabled.
20067+ */
20068+void au_si_free(struct kobject *kobj)
20069+{
20070+ struct au_sbinfo *sbinfo;
b752ccd1 20071+ char *locked __maybe_unused; /* debug only */
1facf9fc 20072+
20073+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
20074+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
e49829fe 20075+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
1facf9fc 20076+
e49829fe 20077+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 20078+ au_br_free(sbinfo);
e49829fe 20079+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1
AM
20080+
20081+ AuDebugOn(radix_tree_gang_lookup
20082+ (&sbinfo->au_si_pid.tree, (void **)&locked,
20083+ /*first_index*/PID_MAX_DEFAULT - 1,
20084+ /*max_items*/sizeof(locked)/sizeof(*locked)));
20085+
1facf9fc 20086+ kfree(sbinfo->si_branch);
b752ccd1 20087+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 20088+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 20089+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 20090+
20091+ kfree(sbinfo);
20092+}
20093+
20094+int au_si_alloc(struct super_block *sb)
20095+{
20096+ int err;
20097+ struct au_sbinfo *sbinfo;
e49829fe 20098+ static struct lock_class_key aufs_si;
1facf9fc 20099+
20100+ err = -ENOMEM;
4a4d8108 20101+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 20102+ if (unlikely(!sbinfo))
20103+ goto out;
20104+
b752ccd1
AM
20105+ BUILD_BUG_ON(sizeof(unsigned long) !=
20106+ sizeof(*sbinfo->au_si_pid.bitmap));
20107+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
20108+ sizeof(*sbinfo->au_si_pid.bitmap),
20109+ GFP_NOFS);
20110+ if (unlikely(!sbinfo->au_si_pid.bitmap))
20111+ goto out_sbinfo;
20112+
1facf9fc 20113+ /* will be reallocated separately */
20114+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
20115+ if (unlikely(!sbinfo->si_branch))
b752ccd1 20116+ goto out_pidmap;
1facf9fc 20117+
1facf9fc 20118+ err = sysaufs_si_init(sbinfo);
20119+ if (unlikely(err))
20120+ goto out_br;
20121+
20122+ au_nwt_init(&sbinfo->si_nowait);
dece6358 20123+ au_rw_init_wlock(&sbinfo->si_rwsem);
e49829fe 20124+ au_rw_class(&sbinfo->si_rwsem, &aufs_si);
b752ccd1
AM
20125+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
20126+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
20127+
7f207e10
AM
20128+ atomic_long_set(&sbinfo->si_ninodes, 0);
20129+
20130+ atomic_long_set(&sbinfo->si_nfiles, 0);
20131+
1facf9fc 20132+ sbinfo->si_bend = -1;
1facf9fc 20133+
20134+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
20135+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
20136+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
20137+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 20138+
e49829fe 20139+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 20140+
1facf9fc 20141+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 20142+ sbinfo->si_xino_brid = -1;
20143+ /* leave si_xib_last_pindex and si_xib_next_bit */
20144+
e49829fe 20145+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 20146+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
20147+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
20148+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
20149+
20150+ au_spl_init(&sbinfo->si_plink);
20151+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 20152+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 20153+
20154+ /* leave other members for sysaufs and si_mnt. */
20155+ sbinfo->si_sb = sb;
20156+ sb->s_fs_info = sbinfo;
b752ccd1 20157+ si_pid_set(sb);
1facf9fc 20158+ au_debug_sbinfo_init(sbinfo);
20159+ return 0; /* success */
20160+
4f0767ce 20161+out_br:
1facf9fc 20162+ kfree(sbinfo->si_branch);
4f0767ce 20163+out_pidmap:
b752ccd1 20164+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 20165+out_sbinfo:
1facf9fc 20166+ kfree(sbinfo);
4f0767ce 20167+out:
1facf9fc 20168+ return err;
20169+}
20170+
20171+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
20172+{
20173+ int err, sz;
20174+ struct au_branch **brp;
20175+
dece6358
AM
20176+ AuRwMustWriteLock(&sbinfo->si_rwsem);
20177+
1facf9fc 20178+ err = -ENOMEM;
20179+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
20180+ if (unlikely(!sz))
20181+ sz = sizeof(*brp);
20182+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
20183+ if (brp) {
20184+ sbinfo->si_branch = brp;
20185+ err = 0;
20186+ }
20187+
20188+ return err;
20189+}
20190+
20191+/* ---------------------------------------------------------------------- */
20192+
20193+unsigned int au_sigen_inc(struct super_block *sb)
20194+{
20195+ unsigned int gen;
20196+
dece6358
AM
20197+ SiMustWriteLock(sb);
20198+
1facf9fc 20199+ gen = ++au_sbi(sb)->si_generation;
20200+ au_update_digen(sb->s_root);
20201+ au_update_iigen(sb->s_root->d_inode);
20202+ sb->s_root->d_inode->i_version++;
20203+ return gen;
20204+}
20205+
20206+aufs_bindex_t au_new_br_id(struct super_block *sb)
20207+{
20208+ aufs_bindex_t br_id;
20209+ int i;
20210+ struct au_sbinfo *sbinfo;
20211+
dece6358
AM
20212+ SiMustWriteLock(sb);
20213+
1facf9fc 20214+ sbinfo = au_sbi(sb);
20215+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
20216+ br_id = ++sbinfo->si_last_br_id;
7f207e10 20217+ AuDebugOn(br_id < 0);
1facf9fc 20218+ if (br_id && au_br_index(sb, br_id) < 0)
20219+ return br_id;
20220+ }
20221+
20222+ return -1;
20223+}
20224+
20225+/* ---------------------------------------------------------------------- */
20226+
e49829fe
JR
20227+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
20228+int si_read_lock(struct super_block *sb, int flags)
20229+{
20230+ int err;
20231+
20232+ err = 0;
20233+ if (au_ftest_lock(flags, FLUSH))
20234+ au_nwt_flush(&au_sbi(sb)->si_nowait);
20235+
20236+ si_noflush_read_lock(sb);
20237+ err = au_plink_maint(sb, flags);
20238+ if (unlikely(err))
20239+ si_read_unlock(sb);
20240+
20241+ return err;
20242+}
20243+
20244+int si_write_lock(struct super_block *sb, int flags)
20245+{
20246+ int err;
20247+
20248+ if (au_ftest_lock(flags, FLUSH))
20249+ au_nwt_flush(&au_sbi(sb)->si_nowait);
20250+
20251+ si_noflush_write_lock(sb);
20252+ err = au_plink_maint(sb, flags);
20253+ if (unlikely(err))
20254+ si_write_unlock(sb);
20255+
20256+ return err;
20257+}
20258+
1facf9fc 20259+/* dentry and super_block lock. call at entry point */
e49829fe 20260+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 20261+{
e49829fe
JR
20262+ int err;
20263+
20264+ err = si_read_lock(dentry->d_sb, flags);
20265+ if (!err) {
20266+ if (au_ftest_lock(flags, DW))
20267+ di_write_lock_child(dentry);
20268+ else
20269+ di_read_lock_child(dentry, flags);
20270+ }
20271+
20272+ return err;
1facf9fc 20273+}
20274+
20275+void aufs_read_unlock(struct dentry *dentry, int flags)
20276+{
20277+ if (au_ftest_lock(flags, DW))
20278+ di_write_unlock(dentry);
20279+ else
20280+ di_read_unlock(dentry, flags);
20281+ si_read_unlock(dentry->d_sb);
20282+}
20283+
20284+void aufs_write_lock(struct dentry *dentry)
20285+{
e49829fe 20286+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 20287+ di_write_lock_child(dentry);
20288+}
20289+
20290+void aufs_write_unlock(struct dentry *dentry)
20291+{
20292+ di_write_unlock(dentry);
20293+ si_write_unlock(dentry->d_sb);
20294+}
20295+
e49829fe 20296+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 20297+{
e49829fe
JR
20298+ int err;
20299+
20300+ err = si_read_lock(d1->d_sb, flags);
20301+ if (!err)
20302+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
20303+ return err;
1facf9fc 20304+}
20305+
20306+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
20307+{
20308+ di_write_unlock2(d1, d2);
20309+ si_read_unlock(d1->d_sb);
20310+}
b752ccd1
AM
20311+
20312+/* ---------------------------------------------------------------------- */
20313+
20314+int si_pid_test_slow(struct super_block *sb)
20315+{
20316+ void *p;
20317+
20318+ rcu_read_lock();
20319+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
20320+ rcu_read_unlock();
20321+
20322+ return (long)p;
20323+}
20324+
20325+void si_pid_set_slow(struct super_block *sb)
20326+{
20327+ int err;
20328+ struct au_sbinfo *sbinfo;
20329+
20330+ AuDebugOn(si_pid_test_slow(sb));
20331+
20332+ sbinfo = au_sbi(sb);
20333+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
20334+ AuDebugOn(err);
20335+ spin_lock(&sbinfo->au_si_pid.tree_lock);
20336+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
20337+ (void *)1);
20338+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
20339+ AuDebugOn(err);
20340+ radix_tree_preload_end();
20341+}
20342+
20343+void si_pid_clr_slow(struct super_block *sb)
20344+{
20345+ void *p;
20346+ struct au_sbinfo *sbinfo;
20347+
20348+ AuDebugOn(!si_pid_test_slow(sb));
20349+
20350+ sbinfo = au_sbi(sb);
20351+ spin_lock(&sbinfo->au_si_pid.tree_lock);
20352+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
20353+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
20354+ AuDebugOn(1 != (long)p);
20355+}
7f207e10
AM
20356diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
20357--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
20358+++ linux/fs/aufs/spl.h 2010-11-22 11:52:56.997229888 +0100
4a4d8108 20359@@ -0,0 +1,66 @@
1facf9fc 20360+/*
4a4d8108 20361+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20362+ *
20363+ * This program, aufs is free software; you can redistribute it and/or modify
20364+ * it under the terms of the GNU General Public License as published by
20365+ * the Free Software Foundation; either version 2 of the License, or
20366+ * (at your option) any later version.
dece6358
AM
20367+ *
20368+ * This program is distributed in the hope that it will be useful,
20369+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20370+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20371+ * GNU General Public License for more details.
20372+ *
20373+ * You should have received a copy of the GNU General Public License
20374+ * along with this program; if not, write to the Free Software
20375+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20376+ */
20377+
20378+/*
20379+ * simple list protected by a spinlock
20380+ */
20381+
20382+#ifndef __AUFS_SPL_H__
20383+#define __AUFS_SPL_H__
20384+
20385+#ifdef __KERNEL__
20386+
dece6358
AM
20387+#include <linux/spinlock.h>
20388+#include <linux/list.h>
4a4d8108 20389+#include <linux/rculist.h>
1facf9fc 20390+
20391+struct au_splhead {
20392+ spinlock_t spin;
20393+ struct list_head head;
20394+};
20395+
20396+static inline void au_spl_init(struct au_splhead *spl)
20397+{
20398+ spin_lock_init(&spl->spin);
20399+ INIT_LIST_HEAD(&spl->head);
20400+}
20401+
20402+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
20403+{
20404+ spin_lock(&spl->spin);
20405+ list_add(list, &spl->head);
20406+ spin_unlock(&spl->spin);
20407+}
20408+
20409+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
20410+{
20411+ spin_lock(&spl->spin);
20412+ list_del(list);
20413+ spin_unlock(&spl->spin);
20414+}
20415+
4a4d8108
AM
20416+static inline void au_spl_del_rcu(struct list_head *list,
20417+ struct au_splhead *spl)
20418+{
20419+ spin_lock(&spl->spin);
20420+ list_del_rcu(list);
20421+ spin_unlock(&spl->spin);
20422+}
20423+
1facf9fc 20424+#endif /* __KERNEL__ */
20425+#endif /* __AUFS_SPL_H__ */
7f207e10
AM
20426diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
20427--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
20428+++ linux/fs/aufs/super.c 2010-11-22 11:52:56.997229888 +0100
20429@@ -0,0 +1,954 @@
1facf9fc 20430+/*
4a4d8108 20431+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20432+ *
20433+ * This program, aufs is free software; you can redistribute it and/or modify
20434+ * it under the terms of the GNU General Public License as published by
20435+ * the Free Software Foundation; either version 2 of the License, or
20436+ * (at your option) any later version.
dece6358
AM
20437+ *
20438+ * This program is distributed in the hope that it will be useful,
20439+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20440+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20441+ * GNU General Public License for more details.
20442+ *
20443+ * You should have received a copy of the GNU General Public License
20444+ * along with this program; if not, write to the Free Software
20445+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20446+ */
20447+
20448+/*
20449+ * mount and super_block operations
20450+ */
20451+
20452+#include <linux/buffer_head.h>
e49829fe 20453+#include <linux/jiffies.h>
dece6358 20454+#include <linux/module.h>
1facf9fc 20455+#include <linux/seq_file.h>
20456+#include <linux/statfs.h>
7f207e10
AM
20457+#include <linux/vmalloc.h>
20458+#include <linux/writeback.h>
1facf9fc 20459+#include "aufs.h"
20460+
20461+/*
20462+ * super_operations
20463+ */
20464+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
20465+{
20466+ struct au_icntnr *c;
20467+
20468+ c = au_cache_alloc_icntnr();
20469+ if (c) {
1facf9fc 20470+ c->vfs_inode.i_version = 1; /* sigen(sb); */
20471+ c->iinfo.ii_hinode = NULL;
20472+ return &c->vfs_inode;
20473+ }
20474+ return NULL;
20475+}
20476+
20477+static void aufs_destroy_inode(struct inode *inode)
20478+{
20479+ au_iinfo_fin(inode);
20480+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
20481+}
20482+
20483+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
20484+{
20485+ struct inode *inode;
20486+ int err;
20487+
20488+ inode = iget_locked(sb, ino);
20489+ if (unlikely(!inode)) {
20490+ inode = ERR_PTR(-ENOMEM);
20491+ goto out;
20492+ }
20493+ if (!(inode->i_state & I_NEW))
20494+ goto out;
20495+
20496+ err = au_xigen_new(inode);
20497+ if (!err)
20498+ err = au_iinfo_init(inode);
20499+ if (!err)
20500+ inode->i_version++;
20501+ else {
20502+ iget_failed(inode);
20503+ inode = ERR_PTR(err);
20504+ }
20505+
4f0767ce 20506+out:
1facf9fc 20507+ /* never return NULL */
20508+ AuDebugOn(!inode);
20509+ AuTraceErrPtr(inode);
20510+ return inode;
20511+}
20512+
20513+/* lock free root dinfo */
20514+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
20515+{
20516+ int err;
20517+ aufs_bindex_t bindex, bend;
20518+ struct path path;
4a4d8108 20519+ struct au_hdentry *hdp;
1facf9fc 20520+ struct au_branch *br;
20521+
20522+ err = 0;
20523+ bend = au_sbend(sb);
4a4d8108 20524+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 20525+ for (bindex = 0; !err && bindex <= bend; bindex++) {
20526+ br = au_sbr(sb, bindex);
20527+ path.mnt = br->br_mnt;
4a4d8108 20528+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 20529+ err = au_seq_path(seq, &path);
20530+ if (err > 0)
20531+ err = seq_printf(seq, "=%s",
20532+ au_optstr_br_perm(br->br_perm));
20533+ if (!err && bindex != bend)
20534+ err = seq_putc(seq, ':');
20535+ }
20536+
20537+ return err;
20538+}
20539+
20540+static void au_show_wbr_create(struct seq_file *m, int v,
20541+ struct au_sbinfo *sbinfo)
20542+{
20543+ const char *pat;
20544+
dece6358
AM
20545+ AuRwMustAnyLock(&sbinfo->si_rwsem);
20546+
1facf9fc 20547+ seq_printf(m, ",create=");
20548+ pat = au_optstr_wbr_create(v);
20549+ switch (v) {
20550+ case AuWbrCreate_TDP:
20551+ case AuWbrCreate_RR:
20552+ case AuWbrCreate_MFS:
20553+ case AuWbrCreate_PMFS:
20554+ seq_printf(m, pat);
20555+ break;
20556+ case AuWbrCreate_MFSV:
20557+ seq_printf(m, /*pat*/"mfs:%lu",
e49829fe
JR
20558+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
20559+ / MSEC_PER_SEC);
1facf9fc 20560+ break;
20561+ case AuWbrCreate_PMFSV:
20562+ seq_printf(m, /*pat*/"pmfs:%lu",
e49829fe
JR
20563+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
20564+ / MSEC_PER_SEC);
1facf9fc 20565+ break;
20566+ case AuWbrCreate_MFSRR:
20567+ seq_printf(m, /*pat*/"mfsrr:%llu",
20568+ sbinfo->si_wbr_mfs.mfsrr_watermark);
20569+ break;
20570+ case AuWbrCreate_MFSRRV:
20571+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
20572+ sbinfo->si_wbr_mfs.mfsrr_watermark,
e49829fe
JR
20573+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
20574+ / MSEC_PER_SEC);
1facf9fc 20575+ break;
20576+ }
20577+}
20578+
20579+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
20580+{
20581+#ifdef CONFIG_SYSFS
20582+ return 0;
20583+#else
20584+ int err;
20585+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
20586+ aufs_bindex_t bindex, brid;
20587+ struct super_block *sb;
20588+ struct qstr *name;
20589+ struct file *f;
20590+ struct dentry *d, *h_root;
4a4d8108 20591+ struct au_hdentry *hdp;
1facf9fc 20592+
dece6358
AM
20593+ AuRwMustAnyLock(&sbinfo->si_rwsem);
20594+
1facf9fc 20595+ err = 0;
20596+ sb = mnt->mnt_sb;
20597+ f = au_sbi(sb)->si_xib;
20598+ if (!f)
20599+ goto out;
20600+
20601+ /* stop printing the default xino path on the first writable branch */
20602+ h_root = NULL;
20603+ brid = au_xino_brid(sb);
20604+ if (brid >= 0) {
20605+ bindex = au_br_index(sb, brid);
4a4d8108
AM
20606+ hdp = au_di(sb->s_root)->di_hdentry;
20607+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 20608+ }
20609+ d = f->f_dentry;
20610+ name = &d->d_name;
20611+ /* safe ->d_parent because the file is unlinked */
20612+ if (d->d_parent == h_root
20613+ && name->len == len
20614+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
20615+ goto out;
20616+
20617+ seq_puts(seq, ",xino=");
20618+ err = au_xino_path(seq, f);
20619+
4f0767ce 20620+out:
1facf9fc 20621+ return err;
20622+#endif
20623+}
20624+
20625+/* seq_file will re-call me in case of too long string */
20626+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
20627+{
20628+ int err, n;
20629+ unsigned int mnt_flags, v;
20630+ struct super_block *sb;
20631+ struct au_sbinfo *sbinfo;
20632+
20633+#define AuBool(name, str) do { \
20634+ v = au_opt_test(mnt_flags, name); \
20635+ if (v != au_opt_test(AuOpt_Def, name)) \
20636+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
20637+} while (0)
20638+
20639+#define AuStr(name, str) do { \
20640+ v = mnt_flags & AuOptMask_##name; \
20641+ if (v != (AuOpt_Def & AuOptMask_##name)) \
20642+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
20643+} while (0)
20644+
20645+#define AuUInt(name, str, val) do { \
20646+ if (val != AUFS_##name##_DEF) \
20647+ seq_printf(m, "," #str "=%u", val); \
20648+} while (0)
20649+
20650+ /* lock free root dinfo */
20651+ sb = mnt->mnt_sb;
20652+ si_noflush_read_lock(sb);
20653+ sbinfo = au_sbi(sb);
20654+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
20655+
20656+ mnt_flags = au_mntflags(sb);
20657+ if (au_opt_test(mnt_flags, XINO)) {
20658+ err = au_show_xino(m, mnt);
20659+ if (unlikely(err))
20660+ goto out;
20661+ } else
20662+ seq_puts(m, ",noxino");
20663+
20664+ AuBool(TRUNC_XINO, trunc_xino);
20665+ AuStr(UDBA, udba);
dece6358 20666+ AuBool(SHWH, shwh);
1facf9fc 20667+ AuBool(PLINK, plink);
4a4d8108 20668+ AuBool(DIO, dio);
1facf9fc 20669+ /* AuBool(DIRPERM1, dirperm1); */
20670+ /* AuBool(REFROF, refrof); */
20671+
20672+ v = sbinfo->si_wbr_create;
20673+ if (v != AuWbrCreate_Def)
20674+ au_show_wbr_create(m, v, sbinfo);
20675+
20676+ v = sbinfo->si_wbr_copyup;
20677+ if (v != AuWbrCopyup_Def)
20678+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
20679+
20680+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
20681+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
20682+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
20683+
20684+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
20685+
e49829fe 20686+ n = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
1facf9fc 20687+ AuUInt(RDCACHE, rdcache, n);
20688+
20689+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
20690+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
20691+
20692+ AuBool(SUM, sum);
20693+ /* AuBool(SUM_W, wsum); */
20694+ AuBool(WARN_PERM, warn_perm);
20695+ AuBool(VERBOSE, verbose);
20696+
4f0767ce 20697+out:
1facf9fc 20698+ /* be sure to print "br:" last */
20699+ if (!sysaufs_brs) {
20700+ seq_puts(m, ",br:");
20701+ au_show_brs(m, sb);
20702+ }
20703+ si_read_unlock(sb);
20704+ return 0;
20705+
1facf9fc 20706+#undef AuBool
20707+#undef AuStr
4a4d8108 20708+#undef AuUInt
1facf9fc 20709+}
20710+
20711+/* ---------------------------------------------------------------------- */
20712+
20713+/* sum mode which returns the summation for statfs(2) */
20714+
20715+static u64 au_add_till_max(u64 a, u64 b)
20716+{
20717+ u64 old;
20718+
20719+ old = a;
20720+ a += b;
20721+ if (old < a)
20722+ return a;
20723+ return ULLONG_MAX;
20724+}
20725+
20726+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
20727+{
20728+ int err;
20729+ u64 blocks, bfree, bavail, files, ffree;
20730+ aufs_bindex_t bend, bindex, i;
20731+ unsigned char shared;
7f207e10 20732+ struct path h_path;
1facf9fc 20733+ struct super_block *h_sb;
20734+
20735+ blocks = 0;
20736+ bfree = 0;
20737+ bavail = 0;
20738+ files = 0;
20739+ ffree = 0;
20740+
20741+ err = 0;
20742+ bend = au_sbend(sb);
20743+ for (bindex = bend; bindex >= 0; bindex--) {
7f207e10
AM
20744+ h_path.mnt = au_sbr_mnt(sb, bindex);
20745+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 20746+ shared = 0;
20747+ for (i = bindex + 1; !shared && i <= bend; i++)
20748+ shared = (au_sbr_sb(sb, i) == h_sb);
20749+ if (shared)
20750+ continue;
20751+
20752+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
20753+ h_path.dentry = h_path.mnt->mnt_root;
20754+ err = vfs_statfs(&h_path, buf);
1facf9fc 20755+ if (unlikely(err))
20756+ goto out;
20757+
20758+ blocks = au_add_till_max(blocks, buf->f_blocks);
20759+ bfree = au_add_till_max(bfree, buf->f_bfree);
20760+ bavail = au_add_till_max(bavail, buf->f_bavail);
20761+ files = au_add_till_max(files, buf->f_files);
20762+ ffree = au_add_till_max(ffree, buf->f_ffree);
20763+ }
20764+
20765+ buf->f_blocks = blocks;
20766+ buf->f_bfree = bfree;
20767+ buf->f_bavail = bavail;
20768+ buf->f_files = files;
20769+ buf->f_ffree = ffree;
20770+
4f0767ce 20771+out:
1facf9fc 20772+ return err;
20773+}
20774+
20775+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
20776+{
20777+ int err;
7f207e10 20778+ struct path h_path;
1facf9fc 20779+ struct super_block *sb;
20780+
20781+ /* lock free root dinfo */
20782+ sb = dentry->d_sb;
20783+ si_noflush_read_lock(sb);
7f207e10 20784+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 20785+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
20786+ h_path.mnt = au_sbr_mnt(sb, 0);
20787+ h_path.dentry = h_path.mnt->mnt_root;
20788+ err = vfs_statfs(&h_path, buf);
20789+ } else
1facf9fc 20790+ err = au_statfs_sum(sb, buf);
20791+ si_read_unlock(sb);
20792+
20793+ if (!err) {
20794+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 20795+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 20796+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
20797+ }
20798+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
20799+
20800+ return err;
20801+}
20802+
20803+/* ---------------------------------------------------------------------- */
20804+
1facf9fc 20805+/* final actions when unmounting a file system */
20806+static void aufs_put_super(struct super_block *sb)
20807+{
20808+ struct au_sbinfo *sbinfo;
20809+
20810+ sbinfo = au_sbi(sb);
20811+ if (!sbinfo)
20812+ return;
20813+
1facf9fc 20814+ dbgaufs_si_fin(sbinfo);
20815+ kobject_put(&sbinfo->si_kobj);
20816+}
20817+
20818+/* ---------------------------------------------------------------------- */
20819+
7f207e10
AM
20820+void au_array_free(void *array)
20821+{
20822+ if (array) {
20823+ if (!is_vmalloc_addr(array))
20824+ kfree(array);
20825+ else
20826+ vfree(array);
20827+ }
20828+}
20829+
20830+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
20831+{
20832+ void *array;
20833+ unsigned long long n;
20834+
20835+ array = NULL;
20836+ n = 0;
20837+ if (!*hint)
20838+ goto out;
20839+
20840+ if (*hint > ULLONG_MAX / sizeof(array)) {
20841+ array = ERR_PTR(-EMFILE);
20842+ pr_err("hint %llu\n", *hint);
20843+ goto out;
20844+ }
20845+
20846+ array = kmalloc(sizeof(array) * *hint, GFP_NOFS);
20847+ if (unlikely(!array))
20848+ array = vmalloc(sizeof(array) * *hint);
20849+ if (unlikely(!array)) {
20850+ array = ERR_PTR(-ENOMEM);
20851+ goto out;
20852+ }
20853+
20854+ n = cb(array, *hint, arg);
20855+ AuDebugOn(n > *hint);
20856+
20857+out:
20858+ *hint = n;
20859+ return array;
20860+}
20861+
20862+static unsigned long long au_iarray_cb(void *a,
20863+ unsigned long long max __maybe_unused,
20864+ void *arg)
20865+{
20866+ unsigned long long n;
20867+ struct inode **p, *inode;
20868+ struct list_head *head;
20869+
20870+ n = 0;
20871+ p = a;
20872+ head = arg;
20873+ spin_lock(&inode_lock);
20874+ list_for_each_entry(inode, head, i_sb_list) {
20875+ if (!is_bad_inode(inode)
20876+ && au_ii(inode)->ii_bstart >= 0) {
20877+ au_igrab(inode);
20878+ *p++ = inode;
20879+ n++;
20880+ AuDebugOn(n > max);
20881+ }
20882+ }
20883+ spin_unlock(&inode_lock);
20884+
20885+ return n;
20886+}
20887+
20888+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
20889+{
20890+ *max = atomic_long_read(&au_sbi(sb)->si_ninodes);
20891+ return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
20892+}
20893+
20894+void au_iarray_free(struct inode **a, unsigned long long max)
20895+{
20896+ unsigned long long ull;
20897+
20898+ for (ull = 0; ull < max; ull++)
20899+ iput(a[ull]);
20900+ au_array_free(a);
20901+}
20902+
20903+/* ---------------------------------------------------------------------- */
20904+
1facf9fc 20905+/*
20906+ * refresh dentry and inode at remount time.
20907+ */
20908+static int do_refresh(struct dentry *dentry, mode_t type,
20909+ unsigned int dir_flags)
20910+{
20911+ int err;
20912+ struct dentry *parent;
20913+
20914+ di_write_lock_child(dentry);
20915+ parent = dget_parent(dentry);
20916+ di_read_lock_parent(parent, AuLock_IR);
20917+
20918+ /* returns the number of positive dentries */
20919+ err = au_refresh_hdentry(dentry, type);
20920+ if (err >= 0) {
20921+ struct inode *inode = dentry->d_inode;
20922+ err = au_refresh_hinode(inode, dentry);
20923+ if (!err && type == S_IFDIR)
4a4d8108 20924+ au_hn_reset(inode, dir_flags);
1facf9fc 20925+ }
20926+ if (unlikely(err))
4a4d8108
AM
20927+ pr_err("unrecoverable error %d, %.*s\n",
20928+ err, AuDLNPair(dentry));
1facf9fc 20929+
20930+ di_read_unlock(parent, AuLock_IR);
20931+ dput(parent);
20932+ di_write_unlock(dentry);
20933+
20934+ return err;
20935+}
20936+
20937+static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
20938+{
20939+ return S_ISDIR(dentry->d_inode->i_mode);
20940+}
20941+
20942+/* gave up consolidating with refresh_nondir() */
20943+static int refresh_dir(struct dentry *root, unsigned int sigen)
20944+{
20945+ int err, i, j, ndentry, e;
20946+ struct au_dcsub_pages dpages;
20947+ struct au_dpage *dpage;
20948+ struct dentry **dentries;
20949+ struct inode *inode;
20950+ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
20951+
20952+ err = 0;
20953+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20954+ if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20955+ ii_write_lock_child(inode);
20956+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
20957+ ii_write_unlock(inode);
20958+ if (unlikely(e)) {
20959+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
20960+ if (!err)
20961+ err = e;
20962+ /* go on even if err */
20963+ }
20964+ }
20965+
20966+ e = au_dpages_init(&dpages, GFP_NOFS);
20967+ if (unlikely(e)) {
20968+ if (!err)
20969+ err = e;
20970+ goto out;
20971+ }
20972+ e = au_dcsub_pages(&dpages, root, test_dir, NULL);
20973+ if (unlikely(e)) {
20974+ if (!err)
20975+ err = e;
20976+ goto out_dpages;
20977+ }
20978+
20979+ for (i = 0; !e && i < dpages.ndpage; i++) {
20980+ dpage = dpages.dpages + i;
20981+ dentries = dpage->dentries;
20982+ ndentry = dpage->ndentry;
20983+ for (j = 0; !e && j < ndentry; j++) {
20984+ struct dentry *d;
20985+
20986+ d = dentries[j];
20987+ au_dbg_verify_dir_parent(d, sigen);
20988+ if (au_digen(d) != sigen) {
20989+ e = do_refresh(d, S_IFDIR, flags);
20990+ if (unlikely(e && !err))
20991+ err = e;
20992+ /* break on err */
20993+ }
20994+ }
20995+ }
20996+
4f0767ce 20997+out_dpages:
1facf9fc 20998+ au_dpages_free(&dpages);
4f0767ce 20999+out:
1facf9fc 21000+ return err;
21001+}
21002+
21003+static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
21004+{
21005+ return !S_ISDIR(dentry->d_inode->i_mode);
21006+}
21007+
21008+static int refresh_nondir(struct dentry *root, unsigned int sigen,
21009+ int do_dentry)
21010+{
21011+ int err, i, j, ndentry, e;
21012+ struct au_dcsub_pages dpages;
21013+ struct au_dpage *dpage;
21014+ struct dentry **dentries;
21015+ struct inode *inode;
21016+
21017+ err = 0;
21018+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
21019+ if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
21020+ ii_write_lock_child(inode);
21021+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
21022+ ii_write_unlock(inode);
21023+ if (unlikely(e)) {
21024+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
21025+ if (!err)
21026+ err = e;
21027+ /* go on even if err */
21028+ }
21029+ }
21030+
21031+ if (!do_dentry)
21032+ goto out;
21033+
21034+ e = au_dpages_init(&dpages, GFP_NOFS);
21035+ if (unlikely(e)) {
21036+ if (!err)
21037+ err = e;
21038+ goto out;
21039+ }
21040+ e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
21041+ if (unlikely(e)) {
21042+ if (!err)
21043+ err = e;
21044+ goto out_dpages;
21045+ }
21046+
21047+ for (i = 0; i < dpages.ndpage; i++) {
21048+ dpage = dpages.dpages + i;
21049+ dentries = dpage->dentries;
21050+ ndentry = dpage->ndentry;
21051+ for (j = 0; j < ndentry; j++) {
21052+ struct dentry *d;
21053+
21054+ d = dentries[j];
21055+ au_dbg_verify_nondir_parent(d, sigen);
21056+ inode = d->d_inode;
21057+ if (inode && au_digen(d) != sigen) {
21058+ e = do_refresh(d, inode->i_mode & S_IFMT,
21059+ /*dir_flags*/0);
21060+ if (unlikely(e && !err))
21061+ err = e;
21062+ /* go on even err */
21063+ }
21064+ }
21065+ }
21066+
4f0767ce 21067+out_dpages:
1facf9fc 21068+ au_dpages_free(&dpages);
4f0767ce 21069+out:
1facf9fc 21070+ return err;
21071+}
21072+
21073+static void au_remount_refresh(struct super_block *sb, unsigned int flags)
21074+{
21075+ int err;
21076+ unsigned int sigen;
21077+ struct au_sbinfo *sbinfo;
21078+ struct dentry *root;
21079+ struct inode *inode;
21080+
21081+ au_sigen_inc(sb);
21082+ sigen = au_sigen(sb);
21083+ sbinfo = au_sbi(sb);
21084+ au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
21085+
21086+ root = sb->s_root;
21087+ DiMustNoWaiters(root);
21088+ inode = root->d_inode;
21089+ IiMustNoWaiters(inode);
4a4d8108 21090+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 21091+ di_write_unlock(root);
21092+
21093+ err = refresh_dir(root, sigen);
21094+ if (unlikely(err)) {
21095+ au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
4a4d8108
AM
21096+ pr_warning("Refreshing directories failed, ignored (%d)\n",
21097+ err);
1facf9fc 21098+ }
21099+
21100+ if (au_ftest_opts(flags, REFRESH_NONDIR)) {
21101+ err = refresh_nondir(root, sigen, !err);
21102+ if (unlikely(err))
4a4d8108
AM
21103+ pr_warning("Refreshing non-directories failed, ignored"
21104+ "(%d)\n", err);
1facf9fc 21105+ }
21106+
21107+ /* aufs_write_lock() calls ..._child() */
21108+ di_write_lock_child(root);
21109+ au_cpup_attr_all(root->d_inode, /*force*/1);
21110+}
21111+
21112+/* stop extra interpretation of errno in mount(8), and strange error messages */
21113+static int cvt_err(int err)
21114+{
21115+ AuTraceErr(err);
21116+
21117+ switch (err) {
21118+ case -ENOENT:
21119+ case -ENOTDIR:
21120+ case -EEXIST:
21121+ case -EIO:
21122+ err = -EINVAL;
21123+ }
21124+ return err;
21125+}
21126+
21127+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
21128+{
4a4d8108
AM
21129+ int err, do_dx;
21130+ unsigned int mntflags;
1facf9fc 21131+ struct au_opts opts;
21132+ struct dentry *root;
21133+ struct inode *inode;
21134+ struct au_sbinfo *sbinfo;
21135+
21136+ err = 0;
21137+ root = sb->s_root;
21138+ if (!data || !*data) {
e49829fe
JR
21139+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21140+ if (!err) {
21141+ di_write_lock_child(root);
21142+ err = au_opts_verify(sb, *flags, /*pending*/0);
21143+ aufs_write_unlock(root);
21144+ }
1facf9fc 21145+ goto out;
21146+ }
21147+
21148+ err = -ENOMEM;
21149+ memset(&opts, 0, sizeof(opts));
21150+ opts.opt = (void *)__get_free_page(GFP_NOFS);
21151+ if (unlikely(!opts.opt))
21152+ goto out;
21153+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
21154+ opts.flags = AuOpts_REMOUNT;
21155+ opts.sb_flags = *flags;
21156+
21157+ /* parse it before aufs lock */
21158+ err = au_opts_parse(sb, data, &opts);
21159+ if (unlikely(err))
21160+ goto out_opts;
21161+
21162+ sbinfo = au_sbi(sb);
21163+ inode = root->d_inode;
21164+ mutex_lock(&inode->i_mutex);
e49829fe
JR
21165+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21166+ if (unlikely(err))
21167+ goto out_mtx;
21168+ di_write_lock_child(root);
1facf9fc 21169+
21170+ /* au_opts_remount() may return an error */
21171+ err = au_opts_remount(sb, &opts);
21172+ au_opts_free(&opts);
21173+
21174+ if (au_ftest_opts(opts.flags, REFRESH_DIR)
21175+ || au_ftest_opts(opts.flags, REFRESH_NONDIR))
21176+ au_remount_refresh(sb, opts.flags);
21177+
4a4d8108
AM
21178+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
21179+ mntflags = au_mntflags(sb);
21180+ do_dx = !!au_opt_test(mntflags, DIO);
21181+ au_dy_arefresh(do_dx);
21182+ }
21183+
1facf9fc 21184+ aufs_write_unlock(root);
953406b4 21185+
e49829fe
JR
21186+out_mtx:
21187+ mutex_unlock(&inode->i_mutex);
4f0767ce 21188+out_opts:
1facf9fc 21189+ free_page((unsigned long)opts.opt);
4f0767ce 21190+out:
1facf9fc 21191+ err = cvt_err(err);
21192+ AuTraceErr(err);
21193+ return err;
21194+}
21195+
4a4d8108 21196+static const struct super_operations aufs_sop = {
1facf9fc 21197+ .alloc_inode = aufs_alloc_inode,
21198+ .destroy_inode = aufs_destroy_inode,
b752ccd1 21199+ /* always deleting, no clearing */
1facf9fc 21200+ .drop_inode = generic_delete_inode,
21201+ .show_options = aufs_show_options,
21202+ .statfs = aufs_statfs,
21203+ .put_super = aufs_put_super,
21204+ .remount_fs = aufs_remount_fs
21205+};
21206+
21207+/* ---------------------------------------------------------------------- */
21208+
21209+static int alloc_root(struct super_block *sb)
21210+{
21211+ int err;
21212+ struct inode *inode;
21213+ struct dentry *root;
21214+
21215+ err = -ENOMEM;
21216+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
21217+ err = PTR_ERR(inode);
21218+ if (IS_ERR(inode))
21219+ goto out;
21220+
21221+ inode->i_op = &aufs_dir_iop;
21222+ inode->i_fop = &aufs_dir_fop;
21223+ inode->i_mode = S_IFDIR;
21224+ inode->i_nlink = 2;
21225+ unlock_new_inode(inode);
21226+
21227+ root = d_alloc_root(inode);
21228+ if (unlikely(!root))
21229+ goto out_iput;
21230+ err = PTR_ERR(root);
21231+ if (IS_ERR(root))
21232+ goto out_iput;
21233+
4a4d8108 21234+ err = au_di_init(root);
1facf9fc 21235+ if (!err) {
21236+ sb->s_root = root;
21237+ return 0; /* success */
21238+ }
21239+ dput(root);
21240+ goto out; /* do not iput */
21241+
4f0767ce 21242+out_iput:
1facf9fc 21243+ iget_failed(inode);
4f0767ce 21244+out:
1facf9fc 21245+ return err;
21246+
21247+}
21248+
21249+static int aufs_fill_super(struct super_block *sb, void *raw_data,
21250+ int silent __maybe_unused)
21251+{
21252+ int err;
21253+ struct au_opts opts;
21254+ struct dentry *root;
21255+ struct inode *inode;
21256+ char *arg = raw_data;
21257+
21258+ if (unlikely(!arg || !*arg)) {
21259+ err = -EINVAL;
4a4d8108 21260+ pr_err("no arg\n");
1facf9fc 21261+ goto out;
21262+ }
21263+
21264+ err = -ENOMEM;
21265+ memset(&opts, 0, sizeof(opts));
21266+ opts.opt = (void *)__get_free_page(GFP_NOFS);
21267+ if (unlikely(!opts.opt))
21268+ goto out;
21269+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
21270+ opts.sb_flags = sb->s_flags;
21271+
21272+ err = au_si_alloc(sb);
21273+ if (unlikely(err))
21274+ goto out_opts;
21275+
21276+ /* all timestamps always follow the ones on the branch */
21277+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
21278+ sb->s_op = &aufs_sop;
21279+ sb->s_magic = AUFS_SUPER_MAGIC;
21280+ sb->s_maxbytes = 0;
21281+ au_export_init(sb);
21282+
21283+ err = alloc_root(sb);
21284+ if (unlikely(err)) {
21285+ si_write_unlock(sb);
21286+ goto out_info;
21287+ }
21288+ root = sb->s_root;
21289+ inode = root->d_inode;
21290+
21291+ /*
21292+ * actually we can parse options regardless aufs lock here.
21293+ * but at remount time, parsing must be done before aufs lock.
21294+ * so we follow the same rule.
21295+ */
21296+ ii_write_lock_parent(inode);
21297+ aufs_write_unlock(root);
21298+ err = au_opts_parse(sb, arg, &opts);
21299+ if (unlikely(err))
21300+ goto out_root;
21301+
21302+ /* lock vfs_inode first, then aufs. */
21303+ mutex_lock(&inode->i_mutex);
1facf9fc 21304+ aufs_write_lock(root);
21305+ err = au_opts_mount(sb, &opts);
21306+ au_opts_free(&opts);
1facf9fc 21307+ aufs_write_unlock(root);
21308+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
21309+ if (!err)
21310+ goto out_opts; /* success */
1facf9fc 21311+
4f0767ce 21312+out_root:
1facf9fc 21313+ dput(root);
21314+ sb->s_root = NULL;
4f0767ce 21315+out_info:
1facf9fc 21316+ kobject_put(&au_sbi(sb)->si_kobj);
21317+ sb->s_fs_info = NULL;
4f0767ce 21318+out_opts:
1facf9fc 21319+ free_page((unsigned long)opts.opt);
4f0767ce 21320+out:
1facf9fc 21321+ AuTraceErr(err);
21322+ err = cvt_err(err);
21323+ AuTraceErr(err);
21324+ return err;
21325+}
21326+
21327+/* ---------------------------------------------------------------------- */
21328+
21329+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
21330+ const char *dev_name __maybe_unused, void *raw_data,
21331+ struct vfsmount *mnt)
21332+{
21333+ int err;
21334+ struct super_block *sb;
21335+
21336+ /* all timestamps always follow the ones on the branch */
21337+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
21338+ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
21339+ if (!err) {
21340+ sb = mnt->mnt_sb;
e49829fe 21341+ si_write_lock(sb, !AuLock_FLUSH);
1facf9fc 21342+ sysaufs_brs_add(sb, 0);
21343+ si_write_unlock(sb);
e49829fe 21344+ au_sbilist_add(sb);
1facf9fc 21345+ }
21346+ return err;
21347+}
21348+
e49829fe
JR
21349+static void aufs_kill_sb(struct super_block *sb)
21350+{
21351+ struct au_sbinfo *sbinfo;
21352+
21353+ sbinfo = au_sbi(sb);
21354+ if (sbinfo) {
21355+ au_sbilist_del(sb);
21356+ aufs_write_lock(sb->s_root);
21357+ if (sbinfo->si_wbr_create_ops->fin)
21358+ sbinfo->si_wbr_create_ops->fin(sb);
21359+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
21360+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
21361+ au_remount_refresh(sb, /*flags*/0);
21362+ }
21363+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
21364+ au_plink_put(sb, /*verbose*/1);
21365+ au_xino_clr(sb);
21366+ aufs_write_unlock(sb->s_root);
21367+
21368+ au_plink_maint_leave(sbinfo);
21369+ au_nwt_flush(&sbinfo->si_nowait);
21370+ }
21371+ generic_shutdown_super(sb);
21372+}
21373+
1facf9fc 21374+struct file_system_type aufs_fs_type = {
21375+ .name = AUFS_FSTYPE,
21376+ .fs_flags =
21377+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
21378+ | FS_REVAL_DOT, /* for NFS branch and udba */
21379+ .get_sb = aufs_get_sb,
e49829fe 21380+ .kill_sb = aufs_kill_sb,
1facf9fc 21381+ /* no need to __module_get() and module_put(). */
21382+ .owner = THIS_MODULE,
21383+};
7f207e10
AM
21384diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
21385--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
21386+++ linux/fs/aufs/super.h 2010-11-22 11:52:57.000563767 +0100
21387@@ -0,0 +1,526 @@
1facf9fc 21388+/*
4a4d8108 21389+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21390+ *
21391+ * This program, aufs is free software; you can redistribute it and/or modify
21392+ * it under the terms of the GNU General Public License as published by
21393+ * the Free Software Foundation; either version 2 of the License, or
21394+ * (at your option) any later version.
dece6358
AM
21395+ *
21396+ * This program is distributed in the hope that it will be useful,
21397+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21398+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21399+ * GNU General Public License for more details.
21400+ *
21401+ * You should have received a copy of the GNU General Public License
21402+ * along with this program; if not, write to the Free Software
21403+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21404+ */
21405+
21406+/*
21407+ * super_block operations
21408+ */
21409+
21410+#ifndef __AUFS_SUPER_H__
21411+#define __AUFS_SUPER_H__
21412+
21413+#ifdef __KERNEL__
21414+
21415+#include <linux/fs.h>
1facf9fc 21416+#include <linux/aufs_type.h>
21417+#include "rwsem.h"
21418+#include "spl.h"
21419+#include "wkq.h"
21420+
21421+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
21422+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
21423+ loff_t *);
21424+
21425+/* policies to select one among multiple writable branches */
21426+struct au_wbr_copyup_operations {
21427+ int (*copyup)(struct dentry *dentry);
21428+};
21429+
21430+struct au_wbr_create_operations {
21431+ int (*create)(struct dentry *dentry, int isdir);
21432+ int (*init)(struct super_block *sb);
21433+ int (*fin)(struct super_block *sb);
21434+};
21435+
21436+struct au_wbr_mfs {
21437+ struct mutex mfs_lock; /* protect this structure */
21438+ unsigned long mfs_jiffy;
21439+ unsigned long mfs_expire;
21440+ aufs_bindex_t mfs_bindex;
21441+
21442+ unsigned long long mfsrr_bytes;
21443+ unsigned long long mfsrr_watermark;
21444+};
21445+
1facf9fc 21446+struct au_branch;
21447+struct au_sbinfo {
21448+ /* nowait tasks in the system-wide workqueue */
21449+ struct au_nowait_tasks si_nowait;
21450+
b752ccd1
AM
21451+ /*
21452+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
21453+ * rwsem for au_sbinfo is necessary.
21454+ */
dece6358 21455+ struct au_rwsem si_rwsem;
1facf9fc 21456+
b752ccd1
AM
21457+ /* prevent recursive locking in deleting inode */
21458+ struct {
21459+ unsigned long *bitmap;
21460+ spinlock_t tree_lock;
21461+ struct radix_tree_root tree;
21462+ } au_si_pid;
21463+
7f207e10
AM
21464+ /*
21465+ * dirty approach to protect sb->sb_inodes and ->s_files from remount.
21466+ */
21467+ atomic_long_t si_ninodes, si_nfiles;
21468+
1facf9fc 21469+ /* branch management */
21470+ unsigned int si_generation;
21471+
21472+ /* see above flags */
21473+ unsigned char au_si_status;
21474+
21475+ aufs_bindex_t si_bend;
7f207e10
AM
21476+
21477+ /* dirty trick to keep br_id plus */
21478+ unsigned int si_last_br_id :
21479+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 21480+ struct au_branch **si_branch;
21481+
21482+ /* policy to select a writable branch */
21483+ unsigned char si_wbr_copyup;
21484+ unsigned char si_wbr_create;
21485+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
21486+ struct au_wbr_create_operations *si_wbr_create_ops;
21487+
21488+ /* round robin */
21489+ atomic_t si_wbr_rr_next;
21490+
21491+ /* most free space */
21492+ struct au_wbr_mfs si_wbr_mfs;
21493+
21494+ /* mount flags */
21495+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
21496+ unsigned int si_mntflags;
21497+
21498+ /* external inode number (bitmap and translation table) */
21499+ au_readf_t si_xread;
21500+ au_writef_t si_xwrite;
21501+ struct file *si_xib;
21502+ struct mutex si_xib_mtx; /* protect xib members */
21503+ unsigned long *si_xib_buf;
21504+ unsigned long si_xib_last_pindex;
21505+ int si_xib_next_bit;
21506+ aufs_bindex_t si_xino_brid;
21507+ /* reserved for future use */
21508+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
21509+
21510+#ifdef CONFIG_AUFS_EXPORT
21511+ /* i_generation */
21512+ struct file *si_xigen;
21513+ atomic_t si_xigen_next;
21514+#endif
21515+
21516+ /* vdir parameters */
e49829fe 21517+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 21518+ unsigned int si_rdblk; /* deblk size */
21519+ unsigned int si_rdhash; /* hash size */
21520+
21521+ /*
21522+ * If the number of whiteouts are larger than si_dirwh, leave all of
21523+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
21524+ * future fsck.aufs or kernel thread will remove them later.
21525+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
21526+ */
21527+ unsigned int si_dirwh;
21528+
21529+ /*
21530+ * rename(2) a directory with all children.
21531+ */
21532+ /* reserved for future use */
21533+ /* int si_rendir; */
21534+
21535+ /* pseudo_link list */
21536+ struct au_splhead si_plink;
21537+ wait_queue_head_t si_plink_wq;
4a4d8108 21538+ spinlock_t si_plink_maint_lock;
e49829fe 21539+ pid_t si_plink_maint_pid;
1facf9fc 21540+
21541+ /*
21542+ * sysfs and lifetime management.
21543+ * this is not a small structure and it may be a waste of memory in case
21544+ * of sysfs is disabled, particulary when many aufs-es are mounted.
21545+ * but using sysfs is majority.
21546+ */
21547+ struct kobject si_kobj;
21548+#ifdef CONFIG_DEBUG_FS
21549+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
21550+#ifdef CONFIG_AUFS_EXPORT
21551+ struct dentry *si_dbgaufs_xigen;
21552+#endif
21553+#endif
21554+
e49829fe
JR
21555+#ifdef CONFIG_AUFS_SBILIST
21556+ struct list_head si_list;
21557+#endif
21558+
1facf9fc 21559+ /* dirty, necessary for unmounting, sysfs and sysrq */
21560+ struct super_block *si_sb;
21561+};
21562+
dece6358
AM
21563+/* sbinfo status flags */
21564+/*
21565+ * set true when refresh_dirs() failed at remount time.
21566+ * then try refreshing dirs at access time again.
21567+ * if it is false, refreshing dirs at access time is unnecesary
21568+ */
21569+#define AuSi_FAILED_REFRESH_DIRS 1
dece6358
AM
21570+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
21571+ unsigned int flag)
21572+{
21573+ AuRwMustAnyLock(&sbi->si_rwsem);
21574+ return sbi->au_si_status & flag;
21575+}
21576+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
21577+#define au_fset_si(sbinfo, name) do { \
21578+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
21579+ (sbinfo)->au_si_status |= AuSi_##name; \
21580+} while (0)
21581+#define au_fclr_si(sbinfo, name) do { \
21582+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
21583+ (sbinfo)->au_si_status &= ~AuSi_##name; \
21584+} while (0)
21585+
1facf9fc 21586+/* ---------------------------------------------------------------------- */
21587+
21588+/* policy to select one among writable branches */
4a4d8108
AM
21589+#define AuWbrCopyup(sbinfo, ...) \
21590+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
21591+#define AuWbrCreate(sbinfo, ...) \
21592+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 21593+
21594+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
21595+#define AuLock_DW 1 /* write-lock dentry */
21596+#define AuLock_IR (1 << 1) /* read-lock inode */
21597+#define AuLock_IW (1 << 2) /* write-lock inode */
21598+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
21599+#define AuLock_DIR (1 << 4) /* target is a dir */
e49829fe
JR
21600+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
21601+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
1facf9fc 21602+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
21603+#define au_fset_lock(flags, name) \
21604+ do { (flags) |= AuLock_##name; } while (0)
21605+#define au_fclr_lock(flags, name) \
21606+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 21607+
21608+/* ---------------------------------------------------------------------- */
21609+
21610+/* super.c */
21611+extern struct file_system_type aufs_fs_type;
21612+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
7f207e10
AM
21613+typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max,
21614+ void *arg);
21615+void au_array_free(void *array);
21616+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg);
21617+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
21618+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 21619+
21620+/* sbinfo.c */
21621+void au_si_free(struct kobject *kobj);
21622+int au_si_alloc(struct super_block *sb);
21623+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
21624+
21625+unsigned int au_sigen_inc(struct super_block *sb);
21626+aufs_bindex_t au_new_br_id(struct super_block *sb);
21627+
e49829fe
JR
21628+int si_read_lock(struct super_block *sb, int flags);
21629+int si_write_lock(struct super_block *sb, int flags);
21630+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 21631+void aufs_read_unlock(struct dentry *dentry, int flags);
21632+void aufs_write_lock(struct dentry *dentry);
21633+void aufs_write_unlock(struct dentry *dentry);
e49829fe 21634+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 21635+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
21636+
b752ccd1
AM
21637+int si_pid_test_slow(struct super_block *sb);
21638+void si_pid_set_slow(struct super_block *sb);
21639+void si_pid_clr_slow(struct super_block *sb);
21640+
1facf9fc 21641+/* wbr_policy.c */
21642+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
21643+extern struct au_wbr_create_operations au_wbr_create_ops[];
21644+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
21645+
21646+/* ---------------------------------------------------------------------- */
21647+
21648+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
21649+{
21650+ return sb->s_fs_info;
21651+}
21652+
21653+/* ---------------------------------------------------------------------- */
21654+
21655+#ifdef CONFIG_AUFS_EXPORT
21656+void au_export_init(struct super_block *sb);
21657+
b752ccd1 21658+static inline int au_test_nfsd(void)
1facf9fc 21659+{
b752ccd1
AM
21660+ struct task_struct *tsk = current;
21661+
21662+ return (tsk->flags & PF_KTHREAD)
21663+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 21664+}
21665+
b752ccd1 21666+void au_xigen_inc(struct inode *inode);
1facf9fc 21667+int au_xigen_new(struct inode *inode);
21668+int au_xigen_set(struct super_block *sb, struct file *base);
21669+void au_xigen_clr(struct super_block *sb);
21670+
21671+static inline int au_busy_or_stale(void)
21672+{
b752ccd1 21673+ if (!au_test_nfsd())
1facf9fc 21674+ return -EBUSY;
21675+ return -ESTALE;
21676+}
21677+#else
4a4d8108 21678+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
21679+AuStubInt0(au_test_nfsd, void)
21680+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
21681+AuStubInt0(au_xigen_new, struct inode *inode)
21682+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
21683+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 21684+static inline int au_busy_or_stale(void)
21685+{
21686+ return -EBUSY;
21687+}
21688+#endif /* CONFIG_AUFS_EXPORT */
21689+
21690+/* ---------------------------------------------------------------------- */
21691+
e49829fe
JR
21692+#ifdef CONFIG_AUFS_SBILIST
21693+/* module.c */
21694+extern struct au_splhead au_sbilist;
21695+
21696+static inline void au_sbilist_init(void)
21697+{
21698+ au_spl_init(&au_sbilist);
21699+}
21700+
21701+static inline void au_sbilist_add(struct super_block *sb)
21702+{
21703+ au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
21704+}
21705+
21706+static inline void au_sbilist_del(struct super_block *sb)
21707+{
21708+ au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
21709+}
21710+#else
21711+AuStubVoid(au_sbilist_init, void)
21712+AuStubVoid(au_sbilist_add, struct super_block*)
21713+AuStubVoid(au_sbilist_del, struct super_block*)
21714+#endif
21715+
21716+/* ---------------------------------------------------------------------- */
21717+
1facf9fc 21718+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
21719+{
dece6358
AM
21720+ /*
21721+ * This function is a dynamic '__init' fucntion actually,
21722+ * so the tiny check for si_rwsem is unnecessary.
21723+ */
21724+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 21725+#ifdef CONFIG_DEBUG_FS
21726+ sbinfo->si_dbgaufs = NULL;
21727+ sbinfo->si_dbgaufs_xib = NULL;
21728+#ifdef CONFIG_AUFS_EXPORT
21729+ sbinfo->si_dbgaufs_xigen = NULL;
21730+#endif
21731+#endif
21732+}
21733+
21734+/* ---------------------------------------------------------------------- */
21735+
b752ccd1
AM
21736+static inline pid_t si_pid_bit(void)
21737+{
21738+ /* the origin of pid is 1, but the bitmap's is 0 */
21739+ return current->pid - 1;
21740+}
21741+
21742+static inline int si_pid_test(struct super_block *sb)
21743+{
21744+ pid_t bit = si_pid_bit();
21745+ if (bit < PID_MAX_DEFAULT)
21746+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21747+ else
21748+ return si_pid_test_slow(sb);
21749+}
21750+
21751+static inline void si_pid_set(struct super_block *sb)
21752+{
21753+ pid_t bit = si_pid_bit();
21754+ if (bit < PID_MAX_DEFAULT) {
21755+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21756+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21757+ /* smp_mb(); */
21758+ } else
21759+ si_pid_set_slow(sb);
21760+}
21761+
21762+static inline void si_pid_clr(struct super_block *sb)
21763+{
21764+ pid_t bit = si_pid_bit();
21765+ if (bit < PID_MAX_DEFAULT) {
21766+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21767+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21768+ /* smp_mb(); */
21769+ } else
21770+ si_pid_clr_slow(sb);
21771+}
21772+
21773+/* ---------------------------------------------------------------------- */
21774+
1facf9fc 21775+/* lock superblock. mainly for entry point functions */
21776+/*
b752ccd1
AM
21777+ * __si_read_lock, __si_write_lock,
21778+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 21779+ */
b752ccd1 21780+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 21781+
dece6358
AM
21782+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
21783+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
21784+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
21785+
b752ccd1
AM
21786+static inline void si_noflush_read_lock(struct super_block *sb)
21787+{
21788+ __si_read_lock(sb);
21789+ si_pid_set(sb);
21790+}
21791+
21792+static inline int si_noflush_read_trylock(struct super_block *sb)
21793+{
21794+ int locked = __si_read_trylock(sb);
21795+ if (locked)
21796+ si_pid_set(sb);
21797+ return locked;
21798+}
21799+
21800+static inline void si_noflush_write_lock(struct super_block *sb)
21801+{
21802+ __si_write_lock(sb);
21803+ si_pid_set(sb);
21804+}
21805+
21806+static inline int si_noflush_write_trylock(struct super_block *sb)
21807+{
21808+ int locked = __si_write_trylock(sb);
21809+ if (locked)
21810+ si_pid_set(sb);
21811+ return locked;
21812+}
21813+
e49829fe 21814+#if 0 /* unused */
1facf9fc 21815+static inline int si_read_trylock(struct super_block *sb, int flags)
21816+{
21817+ if (au_ftest_lock(flags, FLUSH))
21818+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21819+ return si_noflush_read_trylock(sb);
21820+}
e49829fe 21821+#endif
1facf9fc 21822+
b752ccd1
AM
21823+static inline void si_read_unlock(struct super_block *sb)
21824+{
21825+ si_pid_clr(sb);
21826+ __si_read_unlock(sb);
21827+}
21828+
b752ccd1 21829+#if 0 /* unused */
1facf9fc 21830+static inline int si_write_trylock(struct super_block *sb, int flags)
21831+{
21832+ if (au_ftest_lock(flags, FLUSH))
21833+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21834+ return si_noflush_write_trylock(sb);
21835+}
b752ccd1
AM
21836+#endif
21837+
21838+static inline void si_write_unlock(struct super_block *sb)
21839+{
21840+ si_pid_clr(sb);
21841+ __si_write_unlock(sb);
21842+}
21843+
21844+#if 0 /* unused */
21845+static inline void si_downgrade_lock(struct super_block *sb)
21846+{
21847+ __si_downgrade_lock(sb);
21848+}
21849+#endif
1facf9fc 21850+
21851+/* ---------------------------------------------------------------------- */
21852+
21853+static inline aufs_bindex_t au_sbend(struct super_block *sb)
21854+{
dece6358 21855+ SiMustAnyLock(sb);
1facf9fc 21856+ return au_sbi(sb)->si_bend;
21857+}
21858+
21859+static inline unsigned int au_mntflags(struct super_block *sb)
21860+{
dece6358 21861+ SiMustAnyLock(sb);
1facf9fc 21862+ return au_sbi(sb)->si_mntflags;
21863+}
21864+
21865+static inline unsigned int au_sigen(struct super_block *sb)
21866+{
dece6358 21867+ SiMustAnyLock(sb);
1facf9fc 21868+ return au_sbi(sb)->si_generation;
21869+}
21870+
7f207e10
AM
21871+static inline void au_ninodes_inc(struct super_block *sb)
21872+{
21873+ atomic_long_inc(&au_sbi(sb)->si_ninodes);
21874+}
21875+
21876+static inline void au_ninodes_dec(struct super_block *sb)
21877+{
21878+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes));
21879+ atomic_long_dec(&au_sbi(sb)->si_ninodes);
21880+}
21881+
21882+static inline void au_nfiles_inc(struct super_block *sb)
21883+{
21884+ atomic_long_inc(&au_sbi(sb)->si_nfiles);
21885+}
21886+
21887+static inline void au_nfiles_dec(struct super_block *sb)
21888+{
21889+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles));
21890+ atomic_long_dec(&au_sbi(sb)->si_nfiles);
21891+}
21892+
1facf9fc 21893+static inline struct au_branch *au_sbr(struct super_block *sb,
21894+ aufs_bindex_t bindex)
21895+{
dece6358 21896+ SiMustAnyLock(sb);
1facf9fc 21897+ return au_sbi(sb)->si_branch[0 + bindex];
21898+}
21899+
21900+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
21901+{
dece6358 21902+ SiMustWriteLock(sb);
1facf9fc 21903+ au_sbi(sb)->si_xino_brid = brid;
21904+}
21905+
21906+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
21907+{
dece6358 21908+ SiMustAnyLock(sb);
1facf9fc 21909+ return au_sbi(sb)->si_xino_brid;
21910+}
21911+
21912+#endif /* __KERNEL__ */
21913+#endif /* __AUFS_SUPER_H__ */
7f207e10
AM
21914diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
21915--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
21916+++ linux/fs/aufs/sysaufs.c 2010-11-22 11:52:57.000563767 +0100
4a4d8108 21917@@ -0,0 +1,107 @@
1facf9fc 21918+/*
4a4d8108 21919+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21920+ *
21921+ * This program, aufs is free software; you can redistribute it and/or modify
21922+ * it under the terms of the GNU General Public License as published by
21923+ * the Free Software Foundation; either version 2 of the License, or
21924+ * (at your option) any later version.
dece6358
AM
21925+ *
21926+ * This program is distributed in the hope that it will be useful,
21927+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21928+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21929+ * GNU General Public License for more details.
21930+ *
21931+ * You should have received a copy of the GNU General Public License
21932+ * along with this program; if not, write to the Free Software
21933+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21934+ */
21935+
21936+/*
21937+ * sysfs interface and lifetime management
21938+ * they are necessary regardless sysfs is disabled.
21939+ */
21940+
21941+#include <linux/fs.h>
21942+#include <linux/random.h>
21943+#include <linux/sysfs.h>
21944+#include "aufs.h"
21945+
21946+unsigned long sysaufs_si_mask;
e49829fe 21947+struct kset *sysaufs_kset;
1facf9fc 21948+
21949+#define AuSiAttr(_name) { \
21950+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
21951+ .show = sysaufs_si_##_name, \
21952+}
21953+
21954+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
21955+struct attribute *sysaufs_si_attrs[] = {
21956+ &sysaufs_si_attr_xi_path.attr,
21957+ NULL,
21958+};
21959+
4a4d8108 21960+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 21961+ .show = sysaufs_si_show
21962+};
21963+
21964+static struct kobj_type au_sbi_ktype = {
21965+ .release = au_si_free,
21966+ .sysfs_ops = &au_sbi_ops,
21967+ .default_attrs = sysaufs_si_attrs
21968+};
21969+
21970+/* ---------------------------------------------------------------------- */
21971+
21972+int sysaufs_si_init(struct au_sbinfo *sbinfo)
21973+{
21974+ int err;
21975+
e49829fe 21976+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 21977+ /* cf. sysaufs_name() */
21978+ err = kobject_init_and_add
e49829fe 21979+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 21980+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
21981+
21982+ dbgaufs_si_null(sbinfo);
21983+ if (!err) {
21984+ err = dbgaufs_si_init(sbinfo);
21985+ if (unlikely(err))
21986+ kobject_put(&sbinfo->si_kobj);
21987+ }
21988+ return err;
21989+}
21990+
21991+void sysaufs_fin(void)
21992+{
21993+ dbgaufs_fin();
e49829fe
JR
21994+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
21995+ kset_unregister(sysaufs_kset);
1facf9fc 21996+}
21997+
21998+int __init sysaufs_init(void)
21999+{
22000+ int err;
22001+
22002+ do {
22003+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
22004+ } while (!sysaufs_si_mask);
22005+
4a4d8108 22006+ err = -EINVAL;
e49829fe
JR
22007+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
22008+ if (unlikely(!sysaufs_kset))
4a4d8108 22009+ goto out;
e49829fe
JR
22010+ err = PTR_ERR(sysaufs_kset);
22011+ if (IS_ERR(sysaufs_kset))
1facf9fc 22012+ goto out;
e49829fe 22013+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 22014+ if (unlikely(err)) {
e49829fe 22015+ kset_unregister(sysaufs_kset);
1facf9fc 22016+ goto out;
22017+ }
22018+
22019+ err = dbgaufs_init();
22020+ if (unlikely(err))
22021+ sysaufs_fin();
4f0767ce 22022+out:
1facf9fc 22023+ return err;
22024+}
7f207e10
AM
22025diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
22026--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
22027+++ linux/fs/aufs/sysaufs.h 2010-11-22 11:52:57.000563767 +0100
4a4d8108 22028@@ -0,0 +1,105 @@
1facf9fc 22029+/*
4a4d8108 22030+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22031+ *
22032+ * This program, aufs is free software; you can redistribute it and/or modify
22033+ * it under the terms of the GNU General Public License as published by
22034+ * the Free Software Foundation; either version 2 of the License, or
22035+ * (at your option) any later version.
dece6358
AM
22036+ *
22037+ * This program is distributed in the hope that it will be useful,
22038+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22039+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22040+ * GNU General Public License for more details.
22041+ *
22042+ * You should have received a copy of the GNU General Public License
22043+ * along with this program; if not, write to the Free Software
22044+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22045+ */
22046+
22047+/*
22048+ * sysfs interface and mount lifetime management
22049+ */
22050+
22051+#ifndef __SYSAUFS_H__
22052+#define __SYSAUFS_H__
22053+
22054+#ifdef __KERNEL__
22055+
1facf9fc 22056+#include <linux/sysfs.h>
22057+#include <linux/aufs_type.h>
22058+#include "module.h"
22059+
dece6358
AM
22060+struct super_block;
22061+struct au_sbinfo;
22062+
1facf9fc 22063+struct sysaufs_si_attr {
22064+ struct attribute attr;
22065+ int (*show)(struct seq_file *seq, struct super_block *sb);
22066+};
22067+
22068+/* ---------------------------------------------------------------------- */
22069+
22070+/* sysaufs.c */
22071+extern unsigned long sysaufs_si_mask;
e49829fe 22072+extern struct kset *sysaufs_kset;
1facf9fc 22073+extern struct attribute *sysaufs_si_attrs[];
22074+int sysaufs_si_init(struct au_sbinfo *sbinfo);
22075+int __init sysaufs_init(void);
22076+void sysaufs_fin(void);
22077+
22078+/* ---------------------------------------------------------------------- */
22079+
22080+/* some people doesn't like to show a pointer in kernel */
22081+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
22082+{
22083+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
22084+}
22085+
22086+#define SysaufsSiNamePrefix "si_"
22087+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
22088+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
22089+{
22090+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
22091+ sysaufs_si_id(sbinfo));
22092+}
22093+
22094+struct au_branch;
22095+#ifdef CONFIG_SYSFS
22096+/* sysfs.c */
22097+extern struct attribute_group *sysaufs_attr_group;
22098+
22099+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
22100+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
22101+ char *buf);
22102+
22103+void sysaufs_br_init(struct au_branch *br);
22104+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
22105+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
22106+
22107+#define sysaufs_brs_init() do {} while (0)
22108+
22109+#else
22110+#define sysaufs_attr_group NULL
22111+
4a4d8108 22112+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 22113+
22114+static inline
22115+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
22116+ char *buf)
22117+{
22118+ return 0;
22119+}
22120+
4a4d8108
AM
22121+AuStubVoid(sysaufs_br_init, struct au_branch *br)
22122+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
22123+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 22124+
22125+static inline void sysaufs_brs_init(void)
22126+{
22127+ sysaufs_brs = 0;
22128+}
22129+
22130+#endif /* CONFIG_SYSFS */
22131+
22132+#endif /* __KERNEL__ */
22133+#endif /* __SYSAUFS_H__ */
7f207e10
AM
22134diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
22135--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
22136+++ linux/fs/aufs/sysfs.c 2010-11-22 11:52:57.000563767 +0100
953406b4 22137@@ -0,0 +1,250 @@
1facf9fc 22138+/*
4a4d8108 22139+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22140+ *
22141+ * This program, aufs is free software; you can redistribute it and/or modify
22142+ * it under the terms of the GNU General Public License as published by
22143+ * the Free Software Foundation; either version 2 of the License, or
22144+ * (at your option) any later version.
dece6358
AM
22145+ *
22146+ * This program is distributed in the hope that it will be useful,
22147+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22148+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22149+ * GNU General Public License for more details.
22150+ *
22151+ * You should have received a copy of the GNU General Public License
22152+ * along with this program; if not, write to the Free Software
22153+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22154+ */
22155+
22156+/*
22157+ * sysfs interface
22158+ */
22159+
22160+#include <linux/fs.h>
dece6358 22161+#include <linux/module.h>
1facf9fc 22162+#include <linux/seq_file.h>
22163+#include <linux/sysfs.h>
22164+#include "aufs.h"
22165+
4a4d8108
AM
22166+#ifdef CONFIG_AUFS_FS_MODULE
22167+/* this entry violates the "one line per file" policy of sysfs */
22168+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
22169+ char *buf)
22170+{
22171+ ssize_t err;
22172+ static char *conf =
22173+/* this file is generated at compiling */
22174+#include "conf.str"
22175+ ;
22176+
22177+ err = snprintf(buf, PAGE_SIZE, conf);
22178+ if (unlikely(err >= PAGE_SIZE))
22179+ err = -EFBIG;
22180+ return err;
22181+}
22182+
22183+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
22184+#endif
22185+
1facf9fc 22186+static struct attribute *au_attr[] = {
4a4d8108
AM
22187+#ifdef CONFIG_AUFS_FS_MODULE
22188+ &au_config_attr.attr,
22189+#endif
1facf9fc 22190+ NULL, /* need to NULL terminate the list of attributes */
22191+};
22192+
22193+static struct attribute_group sysaufs_attr_group_body = {
22194+ .attrs = au_attr
22195+};
22196+
22197+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
22198+
22199+/* ---------------------------------------------------------------------- */
22200+
22201+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
22202+{
22203+ int err;
22204+
dece6358
AM
22205+ SiMustAnyLock(sb);
22206+
1facf9fc 22207+ err = 0;
22208+ if (au_opt_test(au_mntflags(sb), XINO)) {
22209+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
22210+ seq_putc(seq, '\n');
22211+ }
22212+ return err;
22213+}
22214+
22215+/*
22216+ * the lifetime of branch is independent from the entry under sysfs.
22217+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
22218+ * unlinked.
22219+ */
22220+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
22221+ aufs_bindex_t bindex)
22222+{
22223+ struct path path;
22224+ struct dentry *root;
22225+ struct au_branch *br;
22226+
22227+ AuDbg("b%d\n", bindex);
22228+
22229+ root = sb->s_root;
22230+ di_read_lock_parent(root, !AuLock_IR);
22231+ br = au_sbr(sb, bindex);
22232+ path.mnt = br->br_mnt;
22233+ path.dentry = au_h_dptr(root, bindex);
22234+ au_seq_path(seq, &path);
22235+ di_read_unlock(root, !AuLock_IR);
22236+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
22237+ return 0;
22238+}
22239+
22240+/* ---------------------------------------------------------------------- */
22241+
22242+static struct seq_file *au_seq(char *p, ssize_t len)
22243+{
22244+ struct seq_file *seq;
22245+
22246+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
22247+ if (seq) {
22248+ /* mutex_init(&seq.lock); */
22249+ seq->buf = p;
22250+ seq->size = len;
22251+ return seq; /* success */
22252+ }
22253+
22254+ seq = ERR_PTR(-ENOMEM);
22255+ return seq;
22256+}
22257+
22258+#define SysaufsBr_PREFIX "br"
22259+
22260+/* todo: file size may exceed PAGE_SIZE */
22261+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 22262+ char *buf)
1facf9fc 22263+{
22264+ ssize_t err;
22265+ long l;
22266+ aufs_bindex_t bend;
22267+ struct au_sbinfo *sbinfo;
22268+ struct super_block *sb;
22269+ struct seq_file *seq;
22270+ char *name;
22271+ struct attribute **cattr;
22272+
22273+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
22274+ sb = sbinfo->si_sb;
1308ab2a 22275+
22276+ /*
22277+ * prevent a race condition between sysfs and aufs.
22278+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
22279+ * prohibits maintaining the sysfs entries.
22280+ * hew we acquire read lock after sysfs_get_active_two().
22281+ * on the other hand, the remount process may maintain the sysfs/aufs
22282+ * entries after acquiring write lock.
22283+ * it can cause a deadlock.
22284+ * simply we gave up processing read here.
22285+ */
22286+ err = -EBUSY;
22287+ if (unlikely(!si_noflush_read_trylock(sb)))
22288+ goto out;
1facf9fc 22289+
22290+ seq = au_seq(buf, PAGE_SIZE);
22291+ err = PTR_ERR(seq);
22292+ if (IS_ERR(seq))
1308ab2a 22293+ goto out_unlock;
1facf9fc 22294+
22295+ name = (void *)attr->name;
22296+ cattr = sysaufs_si_attrs;
22297+ while (*cattr) {
22298+ if (!strcmp(name, (*cattr)->name)) {
22299+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
22300+ ->show(seq, sb);
22301+ goto out_seq;
22302+ }
22303+ cattr++;
22304+ }
22305+
22306+ bend = au_sbend(sb);
22307+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
22308+ name += sizeof(SysaufsBr_PREFIX) - 1;
22309+ err = strict_strtol(name, 10, &l);
22310+ if (!err) {
22311+ if (l <= bend)
22312+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
22313+ else
22314+ err = -ENOENT;
22315+ }
22316+ goto out_seq;
22317+ }
22318+ BUG();
22319+
4f0767ce 22320+out_seq:
1facf9fc 22321+ if (!err) {
22322+ err = seq->count;
22323+ /* sysfs limit */
22324+ if (unlikely(err == PAGE_SIZE))
22325+ err = -EFBIG;
22326+ }
22327+ kfree(seq);
4f0767ce 22328+out_unlock:
1facf9fc 22329+ si_read_unlock(sb);
4f0767ce 22330+out:
1facf9fc 22331+ return err;
22332+}
22333+
22334+/* ---------------------------------------------------------------------- */
22335+
22336+void sysaufs_br_init(struct au_branch *br)
22337+{
4a4d8108
AM
22338+ struct attribute *attr = &br->br_attr;
22339+
22340+ sysfs_attr_init(attr);
22341+ attr->name = br->br_name;
22342+ attr->mode = S_IRUGO;
1facf9fc 22343+}
22344+
22345+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
22346+{
22347+ struct au_branch *br;
22348+ struct kobject *kobj;
22349+ aufs_bindex_t bend;
22350+
22351+ dbgaufs_brs_del(sb, bindex);
22352+
22353+ if (!sysaufs_brs)
22354+ return;
22355+
22356+ kobj = &au_sbi(sb)->si_kobj;
22357+ bend = au_sbend(sb);
22358+ for (; bindex <= bend; bindex++) {
22359+ br = au_sbr(sb, bindex);
22360+ sysfs_remove_file(kobj, &br->br_attr);
22361+ }
22362+}
22363+
22364+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
22365+{
22366+ int err;
22367+ aufs_bindex_t bend;
22368+ struct kobject *kobj;
22369+ struct au_branch *br;
22370+
22371+ dbgaufs_brs_add(sb, bindex);
22372+
22373+ if (!sysaufs_brs)
22374+ return;
22375+
22376+ kobj = &au_sbi(sb)->si_kobj;
22377+ bend = au_sbend(sb);
22378+ for (; bindex <= bend; bindex++) {
22379+ br = au_sbr(sb, bindex);
22380+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
22381+ "%d", bindex);
22382+ err = sysfs_create_file(kobj, &br->br_attr);
22383+ if (unlikely(err))
4a4d8108
AM
22384+ pr_warning("failed %s under sysfs(%d)\n",
22385+ br->br_name, err);
1facf9fc 22386+ }
22387+}
7f207e10
AM
22388diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
22389--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
22390+++ linux/fs/aufs/sysrq.c 2010-11-22 11:52:57.000563767 +0100
0c5527e5 22391@@ -0,0 +1,118 @@
1facf9fc 22392+/*
4a4d8108 22393+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22394+ *
22395+ * This program, aufs is free software; you can redistribute it and/or modify
22396+ * it under the terms of the GNU General Public License as published by
22397+ * the Free Software Foundation; either version 2 of the License, or
22398+ * (at your option) any later version.
dece6358
AM
22399+ *
22400+ * This program is distributed in the hope that it will be useful,
22401+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22402+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22403+ * GNU General Public License for more details.
22404+ *
22405+ * You should have received a copy of the GNU General Public License
22406+ * along with this program; if not, write to the Free Software
22407+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22408+ */
22409+
22410+/*
22411+ * magic sysrq hanlder
22412+ */
22413+
22414+#include <linux/fs.h>
22415+#include <linux/module.h>
22416+#include <linux/moduleparam.h>
22417+/* #include <linux/sysrq.h> */
22418+#include "aufs.h"
22419+
22420+/* ---------------------------------------------------------------------- */
22421+
22422+static void sysrq_sb(struct super_block *sb)
22423+{
22424+ char *plevel;
22425+ struct au_sbinfo *sbinfo;
22426+ struct file *file;
22427+
22428+ plevel = au_plevel;
22429+ au_plevel = KERN_WARNING;
1facf9fc 22430+
22431+ sbinfo = au_sbi(sb);
4a4d8108
AM
22432+ /* since we define pr_fmt, call printk directly */
22433+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
22434+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 22435+ au_dpri_sb(sb);
4a4d8108 22436+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 22437+ au_dpri_dentry(sb->s_root);
4a4d8108 22438+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 22439+ au_dpri_inode(sb->s_root->d_inode);
22440+#if 0
22441+ struct inode *i;
4a4d8108 22442+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
e49829fe 22443+ spin_lock(&inode_lock);
1facf9fc 22444+ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
22445+ if (list_empty(&i->i_dentry))
22446+ au_dpri_inode(i);
e49829fe 22447+ spin_unlock(&inode_lock);
1facf9fc 22448+#endif
4a4d8108 22449+ printk(KERN_WARNING AUFS_NAME ": files\n");
0c5527e5
AM
22450+ lg_global_lock(files_lglock);
22451+ do_file_list_for_each_entry(sb, file) {
4a4d8108
AM
22452+ umode_t mode;
22453+ mode = file->f_dentry->d_inode->i_mode;
22454+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 22455+ au_dpri_file(file);
0c5527e5
AM
22456+ } while_file_list_for_each_entry;
22457+ lg_global_unlock(files_lglock);
e49829fe 22458+ printk(KERN_WARNING AUFS_NAME ": done\n");
1facf9fc 22459+
22460+ au_plevel = plevel;
1facf9fc 22461+}
22462+
22463+/* ---------------------------------------------------------------------- */
22464+
22465+/* module parameter */
22466+static char *aufs_sysrq_key = "a";
22467+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
22468+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
22469+
0c5527e5 22470+static void au_sysrq(int key __maybe_unused)
1facf9fc 22471+{
1facf9fc 22472+ struct au_sbinfo *sbinfo;
22473+
e49829fe
JR
22474+ spin_lock(&au_sbilist.spin);
22475+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
1facf9fc 22476+ sysrq_sb(sbinfo->si_sb);
e49829fe 22477+ spin_unlock(&au_sbilist.spin);
1facf9fc 22478+}
22479+
22480+static struct sysrq_key_op au_sysrq_op = {
22481+ .handler = au_sysrq,
22482+ .help_msg = "Aufs",
22483+ .action_msg = "Aufs",
22484+ .enable_mask = SYSRQ_ENABLE_DUMP
22485+};
22486+
22487+/* ---------------------------------------------------------------------- */
22488+
22489+int __init au_sysrq_init(void)
22490+{
22491+ int err;
22492+ char key;
22493+
22494+ err = -1;
22495+ key = *aufs_sysrq_key;
22496+ if ('a' <= key && key <= 'z')
22497+ err = register_sysrq_key(key, &au_sysrq_op);
22498+ if (unlikely(err))
4a4d8108 22499+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 22500+ return err;
22501+}
22502+
22503+void au_sysrq_fin(void)
22504+{
22505+ int err;
22506+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
22507+ if (unlikely(err))
4a4d8108 22508+ pr_err("err %d (ignored)\n", err);
1facf9fc 22509+}
7f207e10
AM
22510diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
22511--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
22512+++ linux/fs/aufs/vdir.c 2010-11-22 11:52:57.000563767 +0100
22513@@ -0,0 +1,886 @@
1facf9fc 22514+/*
4a4d8108 22515+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22516+ *
22517+ * This program, aufs is free software; you can redistribute it and/or modify
22518+ * it under the terms of the GNU General Public License as published by
22519+ * the Free Software Foundation; either version 2 of the License, or
22520+ * (at your option) any later version.
dece6358
AM
22521+ *
22522+ * This program is distributed in the hope that it will be useful,
22523+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22524+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22525+ * GNU General Public License for more details.
22526+ *
22527+ * You should have received a copy of the GNU General Public License
22528+ * along with this program; if not, write to the Free Software
22529+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22530+ */
22531+
22532+/*
22533+ * virtual or vertical directory
22534+ */
22535+
dece6358 22536+#include <linux/hash.h>
1facf9fc 22537+#include "aufs.h"
22538+
dece6358 22539+static unsigned int calc_size(int nlen)
1facf9fc 22540+{
dece6358 22541+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 22542+}
22543+
22544+static int set_deblk_end(union au_vdir_deblk_p *p,
22545+ union au_vdir_deblk_p *deblk_end)
22546+{
22547+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
22548+ p->de->de_str.len = 0;
22549+ /* smp_mb(); */
22550+ return 0;
22551+ }
22552+ return -1; /* error */
22553+}
22554+
22555+/* returns true or false */
22556+static int is_deblk_end(union au_vdir_deblk_p *p,
22557+ union au_vdir_deblk_p *deblk_end)
22558+{
22559+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
22560+ return !p->de->de_str.len;
22561+ return 1;
22562+}
22563+
22564+static unsigned char *last_deblk(struct au_vdir *vdir)
22565+{
22566+ return vdir->vd_deblk[vdir->vd_nblk - 1];
22567+}
22568+
22569+/* ---------------------------------------------------------------------- */
22570+
1308ab2a 22571+/* estimate the apropriate size for name hash table */
22572+unsigned int au_rdhash_est(loff_t sz)
22573+{
22574+ unsigned int n;
22575+
22576+ n = UINT_MAX;
22577+ sz >>= 10;
22578+ if (sz < n)
22579+ n = sz;
22580+ if (sz < AUFS_RDHASH_DEF)
22581+ n = AUFS_RDHASH_DEF;
4a4d8108 22582+ /* pr_info("n %u\n", n); */
1308ab2a 22583+ return n;
22584+}
22585+
1facf9fc 22586+/*
22587+ * the allocated memory has to be freed by
dece6358 22588+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 22589+ */
dece6358 22590+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 22591+{
1facf9fc 22592+ struct hlist_head *head;
dece6358 22593+ unsigned int u;
1facf9fc 22594+
dece6358
AM
22595+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
22596+ if (head) {
22597+ nhash->nh_num = num_hash;
22598+ nhash->nh_head = head;
22599+ for (u = 0; u < num_hash; u++)
1facf9fc 22600+ INIT_HLIST_HEAD(head++);
dece6358 22601+ return 0; /* success */
1facf9fc 22602+ }
1facf9fc 22603+
dece6358 22604+ return -ENOMEM;
1facf9fc 22605+}
22606+
dece6358
AM
22607+static void nhash_count(struct hlist_head *head)
22608+{
22609+#if 0
22610+ unsigned long n;
22611+ struct hlist_node *pos;
22612+
22613+ n = 0;
22614+ hlist_for_each(pos, head)
22615+ n++;
4a4d8108 22616+ pr_info("%lu\n", n);
dece6358
AM
22617+#endif
22618+}
22619+
22620+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 22621+{
1facf9fc 22622+ struct au_vdir_wh *tpos;
22623+ struct hlist_node *pos, *node;
22624+
dece6358
AM
22625+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
22626+ /* hlist_del(pos); */
22627+ kfree(tpos);
1facf9fc 22628+ }
22629+}
22630+
dece6358 22631+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 22632+{
dece6358
AM
22633+ struct au_vdir_dehstr *tpos;
22634+ struct hlist_node *pos, *node;
1facf9fc 22635+
dece6358
AM
22636+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
22637+ /* hlist_del(pos); */
4a4d8108 22638+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 22639+ }
1facf9fc 22640+}
22641+
dece6358
AM
22642+static void au_nhash_do_free(struct au_nhash *nhash,
22643+ void (*free)(struct hlist_head *head))
1facf9fc 22644+{
1308ab2a 22645+ unsigned int n;
1facf9fc 22646+ struct hlist_head *head;
1facf9fc 22647+
dece6358 22648+ n = nhash->nh_num;
1308ab2a 22649+ if (!n)
22650+ return;
22651+
dece6358 22652+ head = nhash->nh_head;
1308ab2a 22653+ while (n-- > 0) {
dece6358
AM
22654+ nhash_count(head);
22655+ free(head++);
1facf9fc 22656+ }
dece6358 22657+ kfree(nhash->nh_head);
1facf9fc 22658+}
22659+
dece6358 22660+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 22661+{
dece6358
AM
22662+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
22663+}
1facf9fc 22664+
dece6358
AM
22665+static void au_nhash_de_free(struct au_nhash *delist)
22666+{
22667+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 22668+}
22669+
22670+/* ---------------------------------------------------------------------- */
22671+
22672+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
22673+ int limit)
22674+{
22675+ int num;
22676+ unsigned int u, n;
22677+ struct hlist_head *head;
22678+ struct au_vdir_wh *tpos;
22679+ struct hlist_node *pos;
22680+
22681+ num = 0;
22682+ n = whlist->nh_num;
22683+ head = whlist->nh_head;
1308ab2a 22684+ for (u = 0; u < n; u++, head++)
1facf9fc 22685+ hlist_for_each_entry(tpos, pos, head, wh_hash)
22686+ if (tpos->wh_bindex == btgt && ++num > limit)
22687+ return 1;
1facf9fc 22688+ return 0;
22689+}
22690+
22691+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 22692+ unsigned char *name,
1facf9fc 22693+ unsigned int len)
22694+{
dece6358
AM
22695+ unsigned int v;
22696+ /* const unsigned int magic_bit = 12; */
22697+
1308ab2a 22698+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
22699+
dece6358
AM
22700+ v = 0;
22701+ while (len--)
22702+ v += *name++;
22703+ /* v = hash_long(v, magic_bit); */
22704+ v %= nhash->nh_num;
22705+ return nhash->nh_head + v;
22706+}
22707+
22708+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
22709+ int nlen)
22710+{
22711+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 22712+}
22713+
22714+/* returns found or not */
dece6358 22715+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 22716+{
22717+ struct hlist_head *head;
22718+ struct au_vdir_wh *tpos;
22719+ struct hlist_node *pos;
22720+ struct au_vdir_destr *str;
22721+
dece6358 22722+ head = au_name_hash(whlist, name, nlen);
1facf9fc 22723+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
22724+ str = &tpos->wh_str;
22725+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
22726+ if (au_nhash_test_name(str, name, nlen))
22727+ return 1;
22728+ }
22729+ return 0;
22730+}
22731+
22732+/* returns found(true) or not */
22733+static int test_known(struct au_nhash *delist, char *name, int nlen)
22734+{
22735+ struct hlist_head *head;
22736+ struct au_vdir_dehstr *tpos;
22737+ struct hlist_node *pos;
22738+ struct au_vdir_destr *str;
22739+
22740+ head = au_name_hash(delist, name, nlen);
22741+ hlist_for_each_entry(tpos, pos, head, hash) {
22742+ str = tpos->str;
22743+ AuDbg("%.*s\n", str->len, str->name);
22744+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 22745+ return 1;
22746+ }
22747+ return 0;
22748+}
22749+
dece6358
AM
22750+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
22751+ unsigned char d_type)
22752+{
22753+#ifdef CONFIG_AUFS_SHWH
22754+ wh->wh_ino = ino;
22755+ wh->wh_type = d_type;
22756+#endif
22757+}
22758+
22759+/* ---------------------------------------------------------------------- */
22760+
22761+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
22762+ unsigned int d_type, aufs_bindex_t bindex,
22763+ unsigned char shwh)
1facf9fc 22764+{
22765+ int err;
22766+ struct au_vdir_destr *str;
22767+ struct au_vdir_wh *wh;
22768+
dece6358 22769+ AuDbg("%.*s\n", nlen, name);
1308ab2a 22770+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
22771+
1facf9fc 22772+ err = -ENOMEM;
dece6358 22773+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 22774+ if (unlikely(!wh))
22775+ goto out;
22776+
22777+ err = 0;
22778+ wh->wh_bindex = bindex;
dece6358
AM
22779+ if (shwh)
22780+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 22781+ str = &wh->wh_str;
dece6358
AM
22782+ str->len = nlen;
22783+ memcpy(str->name, name, nlen);
22784+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 22785+ /* smp_mb(); */
22786+
4f0767ce 22787+out:
1facf9fc 22788+ return err;
22789+}
22790+
1facf9fc 22791+static int append_deblk(struct au_vdir *vdir)
22792+{
22793+ int err;
dece6358 22794+ unsigned long ul;
1facf9fc 22795+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
22796+ union au_vdir_deblk_p p, deblk_end;
22797+ unsigned char **o;
22798+
22799+ err = -ENOMEM;
dece6358
AM
22800+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
22801+ GFP_NOFS);
1facf9fc 22802+ if (unlikely(!o))
22803+ goto out;
22804+
22805+ vdir->vd_deblk = o;
22806+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
22807+ if (p.deblk) {
22808+ ul = vdir->vd_nblk++;
22809+ vdir->vd_deblk[ul] = p.deblk;
22810+ vdir->vd_last.ul = ul;
22811+ vdir->vd_last.p.deblk = p.deblk;
22812+ deblk_end.deblk = p.deblk + deblk_sz;
22813+ err = set_deblk_end(&p, &deblk_end);
22814+ }
22815+
4f0767ce 22816+out:
1facf9fc 22817+ return err;
22818+}
22819+
dece6358
AM
22820+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
22821+ unsigned int d_type, struct au_nhash *delist)
22822+{
22823+ int err;
22824+ unsigned int sz;
22825+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
22826+ union au_vdir_deblk_p p, *room, deblk_end;
22827+ struct au_vdir_dehstr *dehstr;
22828+
22829+ p.deblk = last_deblk(vdir);
22830+ deblk_end.deblk = p.deblk + deblk_sz;
22831+ room = &vdir->vd_last.p;
22832+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
22833+ || !is_deblk_end(room, &deblk_end));
22834+
22835+ sz = calc_size(nlen);
22836+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
22837+ err = append_deblk(vdir);
22838+ if (unlikely(err))
22839+ goto out;
22840+
22841+ p.deblk = last_deblk(vdir);
22842+ deblk_end.deblk = p.deblk + deblk_sz;
22843+ /* smp_mb(); */
22844+ AuDebugOn(room->deblk != p.deblk);
22845+ }
22846+
22847+ err = -ENOMEM;
4a4d8108 22848+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
22849+ if (unlikely(!dehstr))
22850+ goto out;
22851+
22852+ dehstr->str = &room->de->de_str;
22853+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
22854+ room->de->de_ino = ino;
22855+ room->de->de_type = d_type;
22856+ room->de->de_str.len = nlen;
22857+ memcpy(room->de->de_str.name, name, nlen);
22858+
22859+ err = 0;
22860+ room->deblk += sz;
22861+ if (unlikely(set_deblk_end(room, &deblk_end)))
22862+ err = append_deblk(vdir);
22863+ /* smp_mb(); */
22864+
4f0767ce 22865+out:
dece6358
AM
22866+ return err;
22867+}
22868+
22869+/* ---------------------------------------------------------------------- */
22870+
22871+void au_vdir_free(struct au_vdir *vdir)
22872+{
22873+ unsigned char **deblk;
22874+
22875+ deblk = vdir->vd_deblk;
22876+ while (vdir->vd_nblk--)
22877+ kfree(*deblk++);
22878+ kfree(vdir->vd_deblk);
22879+ au_cache_free_vdir(vdir);
22880+}
22881+
1308ab2a 22882+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 22883+{
22884+ struct au_vdir *vdir;
1308ab2a 22885+ struct super_block *sb;
1facf9fc 22886+ int err;
22887+
1308ab2a 22888+ sb = file->f_dentry->d_sb;
dece6358
AM
22889+ SiMustAnyLock(sb);
22890+
1facf9fc 22891+ err = -ENOMEM;
22892+ vdir = au_cache_alloc_vdir();
22893+ if (unlikely(!vdir))
22894+ goto out;
22895+
22896+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
22897+ if (unlikely(!vdir->vd_deblk))
22898+ goto out_free;
22899+
22900+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 22901+ if (!vdir->vd_deblk_sz) {
22902+ /* estimate the apropriate size for deblk */
22903+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 22904+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 22905+ }
1facf9fc 22906+ vdir->vd_nblk = 0;
22907+ vdir->vd_version = 0;
22908+ vdir->vd_jiffy = 0;
22909+ err = append_deblk(vdir);
22910+ if (!err)
22911+ return vdir; /* success */
22912+
22913+ kfree(vdir->vd_deblk);
22914+
4f0767ce 22915+out_free:
1facf9fc 22916+ au_cache_free_vdir(vdir);
4f0767ce 22917+out:
1facf9fc 22918+ vdir = ERR_PTR(err);
22919+ return vdir;
22920+}
22921+
22922+static int reinit_vdir(struct au_vdir *vdir)
22923+{
22924+ int err;
22925+ union au_vdir_deblk_p p, deblk_end;
22926+
22927+ while (vdir->vd_nblk > 1) {
22928+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
22929+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
22930+ vdir->vd_nblk--;
22931+ }
22932+ p.deblk = vdir->vd_deblk[0];
22933+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
22934+ err = set_deblk_end(&p, &deblk_end);
22935+ /* keep vd_dblk_sz */
22936+ vdir->vd_last.ul = 0;
22937+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
22938+ vdir->vd_version = 0;
22939+ vdir->vd_jiffy = 0;
22940+ /* smp_mb(); */
22941+ return err;
22942+}
22943+
22944+/* ---------------------------------------------------------------------- */
22945+
1facf9fc 22946+#define AuFillVdir_CALLED 1
22947+#define AuFillVdir_WHABLE (1 << 1)
dece6358 22948+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 22949+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
22950+#define au_fset_fillvdir(flags, name) \
22951+ do { (flags) |= AuFillVdir_##name; } while (0)
22952+#define au_fclr_fillvdir(flags, name) \
22953+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 22954+
dece6358
AM
22955+#ifndef CONFIG_AUFS_SHWH
22956+#undef AuFillVdir_SHWH
22957+#define AuFillVdir_SHWH 0
22958+#endif
22959+
1facf9fc 22960+struct fillvdir_arg {
22961+ struct file *file;
22962+ struct au_vdir *vdir;
dece6358
AM
22963+ struct au_nhash delist;
22964+ struct au_nhash whlist;
1facf9fc 22965+ aufs_bindex_t bindex;
22966+ unsigned int flags;
22967+ int err;
22968+};
22969+
dece6358 22970+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 22971+ loff_t offset __maybe_unused, u64 h_ino,
22972+ unsigned int d_type)
22973+{
22974+ struct fillvdir_arg *arg = __arg;
22975+ char *name = (void *)__name;
22976+ struct super_block *sb;
1facf9fc 22977+ ino_t ino;
dece6358 22978+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 22979+
1facf9fc 22980+ arg->err = 0;
dece6358 22981+ sb = arg->file->f_dentry->d_sb;
1facf9fc 22982+ au_fset_fillvdir(arg->flags, CALLED);
22983+ /* smp_mb(); */
dece6358 22984+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 22985+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
22986+ if (test_known(&arg->delist, name, nlen)
22987+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
22988+ goto out; /* already exists or whiteouted */
1facf9fc 22989+
22990+ sb = arg->file->f_dentry->d_sb;
dece6358 22991+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
22992+ if (!arg->err) {
22993+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
22994+ d_type = DT_UNKNOWN;
dece6358
AM
22995+ arg->err = append_de(arg->vdir, name, nlen, ino,
22996+ d_type, &arg->delist);
4a4d8108 22997+ }
1facf9fc 22998+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
22999+ name += AUFS_WH_PFX_LEN;
dece6358
AM
23000+ nlen -= AUFS_WH_PFX_LEN;
23001+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
23002+ goto out; /* already whiteouted */
1facf9fc 23003+
dece6358
AM
23004+ if (shwh)
23005+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
23006+ &ino);
4a4d8108
AM
23007+ if (!arg->err) {
23008+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
23009+ d_type = DT_UNKNOWN;
1facf9fc 23010+ arg->err = au_nhash_append_wh
dece6358
AM
23011+ (&arg->whlist, name, nlen, ino, d_type,
23012+ arg->bindex, shwh);
4a4d8108 23013+ }
1facf9fc 23014+ }
23015+
4f0767ce 23016+out:
1facf9fc 23017+ if (!arg->err)
23018+ arg->vdir->vd_jiffy = jiffies;
23019+ /* smp_mb(); */
23020+ AuTraceErr(arg->err);
23021+ return arg->err;
23022+}
23023+
dece6358
AM
23024+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
23025+ struct au_nhash *whlist, struct au_nhash *delist)
23026+{
23027+#ifdef CONFIG_AUFS_SHWH
23028+ int err;
23029+ unsigned int nh, u;
23030+ struct hlist_head *head;
23031+ struct au_vdir_wh *tpos;
23032+ struct hlist_node *pos, *n;
23033+ char *p, *o;
23034+ struct au_vdir_destr *destr;
23035+
23036+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
23037+
23038+ err = -ENOMEM;
4a4d8108 23039+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
23040+ if (unlikely(!p))
23041+ goto out;
23042+
23043+ err = 0;
23044+ nh = whlist->nh_num;
23045+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
23046+ p += AUFS_WH_PFX_LEN;
23047+ for (u = 0; u < nh; u++) {
23048+ head = whlist->nh_head + u;
23049+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
23050+ destr = &tpos->wh_str;
23051+ memcpy(p, destr->name, destr->len);
23052+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
23053+ tpos->wh_ino, tpos->wh_type, delist);
23054+ if (unlikely(err))
23055+ break;
23056+ }
23057+ }
23058+
23059+ __putname(o);
23060+
4f0767ce 23061+out:
dece6358
AM
23062+ AuTraceErr(err);
23063+ return err;
23064+#else
23065+ return 0;
23066+#endif
23067+}
23068+
1facf9fc 23069+static int au_do_read_vdir(struct fillvdir_arg *arg)
23070+{
23071+ int err;
dece6358 23072+ unsigned int rdhash;
1facf9fc 23073+ loff_t offset;
dece6358
AM
23074+ aufs_bindex_t bend, bindex, bstart;
23075+ unsigned char shwh;
1facf9fc 23076+ struct file *hf, *file;
23077+ struct super_block *sb;
23078+
1facf9fc 23079+ file = arg->file;
23080+ sb = file->f_dentry->d_sb;
dece6358
AM
23081+ SiMustAnyLock(sb);
23082+
23083+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 23084+ if (!rdhash)
23085+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
23086+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
23087+ if (unlikely(err))
1facf9fc 23088+ goto out;
dece6358
AM
23089+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
23090+ if (unlikely(err))
1facf9fc 23091+ goto out_delist;
23092+
23093+ err = 0;
23094+ arg->flags = 0;
dece6358
AM
23095+ shwh = 0;
23096+ if (au_opt_test(au_mntflags(sb), SHWH)) {
23097+ shwh = 1;
23098+ au_fset_fillvdir(arg->flags, SHWH);
23099+ }
23100+ bstart = au_fbstart(file);
4a4d8108 23101+ bend = au_fbend_dir(file);
dece6358 23102+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 23103+ hf = au_hf_dir(file, bindex);
1facf9fc 23104+ if (!hf)
23105+ continue;
23106+
23107+ offset = vfsub_llseek(hf, 0, SEEK_SET);
23108+ err = offset;
23109+ if (unlikely(offset))
23110+ break;
23111+
23112+ arg->bindex = bindex;
23113+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
23114+ if (shwh
23115+ || (bindex != bend
23116+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 23117+ au_fset_fillvdir(arg->flags, WHABLE);
23118+ do {
23119+ arg->err = 0;
23120+ au_fclr_fillvdir(arg->flags, CALLED);
23121+ /* smp_mb(); */
23122+ err = vfsub_readdir(hf, fillvdir, arg);
23123+ if (err >= 0)
23124+ err = arg->err;
23125+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
23126+ }
dece6358
AM
23127+
23128+ if (!err && shwh)
23129+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
23130+
23131+ au_nhash_wh_free(&arg->whlist);
1facf9fc 23132+
4f0767ce 23133+out_delist:
dece6358 23134+ au_nhash_de_free(&arg->delist);
4f0767ce 23135+out:
1facf9fc 23136+ return err;
23137+}
23138+
23139+static int read_vdir(struct file *file, int may_read)
23140+{
23141+ int err;
23142+ unsigned long expire;
23143+ unsigned char do_read;
23144+ struct fillvdir_arg arg;
23145+ struct inode *inode;
23146+ struct au_vdir *vdir, *allocated;
23147+
23148+ err = 0;
23149+ inode = file->f_dentry->d_inode;
23150+ IMustLock(inode);
dece6358
AM
23151+ SiMustAnyLock(inode->i_sb);
23152+
1facf9fc 23153+ allocated = NULL;
23154+ do_read = 0;
23155+ expire = au_sbi(inode->i_sb)->si_rdcache;
23156+ vdir = au_ivdir(inode);
23157+ if (!vdir) {
23158+ do_read = 1;
1308ab2a 23159+ vdir = alloc_vdir(file);
1facf9fc 23160+ err = PTR_ERR(vdir);
23161+ if (IS_ERR(vdir))
23162+ goto out;
23163+ err = 0;
23164+ allocated = vdir;
23165+ } else if (may_read
23166+ && (inode->i_version != vdir->vd_version
23167+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
23168+ do_read = 1;
23169+ err = reinit_vdir(vdir);
23170+ if (unlikely(err))
23171+ goto out;
23172+ }
23173+
23174+ if (!do_read)
23175+ return 0; /* success */
23176+
23177+ arg.file = file;
23178+ arg.vdir = vdir;
23179+ err = au_do_read_vdir(&arg);
23180+ if (!err) {
23181+ /* file->f_pos = 0; */
23182+ vdir->vd_version = inode->i_version;
23183+ vdir->vd_last.ul = 0;
23184+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
23185+ if (allocated)
23186+ au_set_ivdir(inode, allocated);
23187+ } else if (allocated)
23188+ au_vdir_free(allocated);
23189+
4f0767ce 23190+out:
1facf9fc 23191+ return err;
23192+}
23193+
23194+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
23195+{
23196+ int err, rerr;
23197+ unsigned long ul, n;
23198+ const unsigned int deblk_sz = src->vd_deblk_sz;
23199+
23200+ AuDebugOn(tgt->vd_nblk != 1);
23201+
23202+ err = -ENOMEM;
23203+ if (tgt->vd_nblk < src->vd_nblk) {
23204+ unsigned char **p;
23205+
dece6358
AM
23206+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
23207+ GFP_NOFS);
1facf9fc 23208+ if (unlikely(!p))
23209+ goto out;
23210+ tgt->vd_deblk = p;
23211+ }
23212+
1308ab2a 23213+ if (tgt->vd_deblk_sz != deblk_sz) {
23214+ unsigned char *p;
23215+
23216+ tgt->vd_deblk_sz = deblk_sz;
23217+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
23218+ if (unlikely(!p))
23219+ goto out;
23220+ tgt->vd_deblk[0] = p;
23221+ }
1facf9fc 23222+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 23223+ tgt->vd_version = src->vd_version;
23224+ tgt->vd_jiffy = src->vd_jiffy;
23225+
23226+ n = src->vd_nblk;
23227+ for (ul = 1; ul < n; ul++) {
dece6358
AM
23228+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
23229+ GFP_NOFS);
23230+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 23231+ goto out;
1308ab2a 23232+ tgt->vd_nblk++;
1facf9fc 23233+ }
1308ab2a 23234+ tgt->vd_nblk = n;
23235+ tgt->vd_last.ul = tgt->vd_last.ul;
23236+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
23237+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
23238+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 23239+ /* smp_mb(); */
23240+ return 0; /* success */
23241+
4f0767ce 23242+out:
1facf9fc 23243+ rerr = reinit_vdir(tgt);
23244+ BUG_ON(rerr);
23245+ return err;
23246+}
23247+
23248+int au_vdir_init(struct file *file)
23249+{
23250+ int err;
23251+ struct inode *inode;
23252+ struct au_vdir *vdir_cache, *allocated;
23253+
23254+ err = read_vdir(file, !file->f_pos);
23255+ if (unlikely(err))
23256+ goto out;
23257+
23258+ allocated = NULL;
23259+ vdir_cache = au_fvdir_cache(file);
23260+ if (!vdir_cache) {
1308ab2a 23261+ vdir_cache = alloc_vdir(file);
1facf9fc 23262+ err = PTR_ERR(vdir_cache);
23263+ if (IS_ERR(vdir_cache))
23264+ goto out;
23265+ allocated = vdir_cache;
23266+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
23267+ err = reinit_vdir(vdir_cache);
23268+ if (unlikely(err))
23269+ goto out;
23270+ } else
23271+ return 0; /* success */
23272+
23273+ inode = file->f_dentry->d_inode;
23274+ err = copy_vdir(vdir_cache, au_ivdir(inode));
23275+ if (!err) {
23276+ file->f_version = inode->i_version;
23277+ if (allocated)
23278+ au_set_fvdir_cache(file, allocated);
23279+ } else if (allocated)
23280+ au_vdir_free(allocated);
23281+
4f0767ce 23282+out:
1facf9fc 23283+ return err;
23284+}
23285+
23286+static loff_t calc_offset(struct au_vdir *vdir)
23287+{
23288+ loff_t offset;
23289+ union au_vdir_deblk_p p;
23290+
23291+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
23292+ offset = vdir->vd_last.p.deblk - p.deblk;
23293+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
23294+ return offset;
23295+}
23296+
23297+/* returns true or false */
23298+static int seek_vdir(struct file *file)
23299+{
23300+ int valid;
23301+ unsigned int deblk_sz;
23302+ unsigned long ul, n;
23303+ loff_t offset;
23304+ union au_vdir_deblk_p p, deblk_end;
23305+ struct au_vdir *vdir_cache;
23306+
23307+ valid = 1;
23308+ vdir_cache = au_fvdir_cache(file);
23309+ offset = calc_offset(vdir_cache);
23310+ AuDbg("offset %lld\n", offset);
23311+ if (file->f_pos == offset)
23312+ goto out;
23313+
23314+ vdir_cache->vd_last.ul = 0;
23315+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
23316+ if (!file->f_pos)
23317+ goto out;
23318+
23319+ valid = 0;
23320+ deblk_sz = vdir_cache->vd_deblk_sz;
23321+ ul = div64_u64(file->f_pos, deblk_sz);
23322+ AuDbg("ul %lu\n", ul);
23323+ if (ul >= vdir_cache->vd_nblk)
23324+ goto out;
23325+
23326+ n = vdir_cache->vd_nblk;
23327+ for (; ul < n; ul++) {
23328+ p.deblk = vdir_cache->vd_deblk[ul];
23329+ deblk_end.deblk = p.deblk + deblk_sz;
23330+ offset = ul;
23331+ offset *= deblk_sz;
23332+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
23333+ unsigned int l;
23334+
23335+ l = calc_size(p.de->de_str.len);
23336+ offset += l;
23337+ p.deblk += l;
23338+ }
23339+ if (!is_deblk_end(&p, &deblk_end)) {
23340+ valid = 1;
23341+ vdir_cache->vd_last.ul = ul;
23342+ vdir_cache->vd_last.p = p;
23343+ break;
23344+ }
23345+ }
23346+
4f0767ce 23347+out:
1facf9fc 23348+ /* smp_mb(); */
23349+ AuTraceErr(!valid);
23350+ return valid;
23351+}
23352+
23353+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
23354+{
23355+ int err;
23356+ unsigned int l, deblk_sz;
23357+ union au_vdir_deblk_p deblk_end;
23358+ struct au_vdir *vdir_cache;
23359+ struct au_vdir_de *de;
23360+
23361+ vdir_cache = au_fvdir_cache(file);
23362+ if (!seek_vdir(file))
23363+ return 0;
23364+
23365+ deblk_sz = vdir_cache->vd_deblk_sz;
23366+ while (1) {
23367+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
23368+ deblk_end.deblk += deblk_sz;
23369+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
23370+ de = vdir_cache->vd_last.p.de;
23371+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
23372+ de->de_str.len, de->de_str.name, file->f_pos,
23373+ (unsigned long)de->de_ino, de->de_type);
23374+ err = filldir(dirent, de->de_str.name, de->de_str.len,
23375+ file->f_pos, de->de_ino, de->de_type);
23376+ if (unlikely(err)) {
23377+ AuTraceErr(err);
23378+ /* todo: ignore the error caused by udba? */
23379+ /* return err; */
23380+ return 0;
23381+ }
23382+
23383+ l = calc_size(de->de_str.len);
23384+ vdir_cache->vd_last.p.deblk += l;
23385+ file->f_pos += l;
23386+ }
23387+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
23388+ vdir_cache->vd_last.ul++;
23389+ vdir_cache->vd_last.p.deblk
23390+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
23391+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
23392+ continue;
23393+ }
23394+ break;
23395+ }
23396+
23397+ /* smp_mb(); */
23398+ return 0;
23399+}
7f207e10
AM
23400diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
23401--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
23402+++ linux/fs/aufs/vfsub.c 2010-11-22 11:52:57.000563767 +0100
23403@@ -0,0 +1,790 @@
1facf9fc 23404+/*
4a4d8108 23405+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 23406+ *
23407+ * This program, aufs is free software; you can redistribute it and/or modify
23408+ * it under the terms of the GNU General Public License as published by
23409+ * the Free Software Foundation; either version 2 of the License, or
23410+ * (at your option) any later version.
dece6358
AM
23411+ *
23412+ * This program is distributed in the hope that it will be useful,
23413+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23414+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23415+ * GNU General Public License for more details.
23416+ *
23417+ * You should have received a copy of the GNU General Public License
23418+ * along with this program; if not, write to the Free Software
23419+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23420+ */
23421+
23422+/*
23423+ * sub-routines for VFS
23424+ */
23425+
4a4d8108 23426+#include <linux/file.h>
1308ab2a 23427+#include <linux/ima.h>
dece6358
AM
23428+#include <linux/namei.h>
23429+#include <linux/security.h>
23430+#include <linux/splice.h>
1facf9fc 23431+#include <linux/uaccess.h>
23432+#include "aufs.h"
23433+
23434+int vfsub_update_h_iattr(struct path *h_path, int *did)
23435+{
23436+ int err;
23437+ struct kstat st;
23438+ struct super_block *h_sb;
23439+
23440+ /* for remote fs, leave work for its getattr or d_revalidate */
23441+ /* for bad i_attr fs, handle them in aufs_getattr() */
23442+ /* still some fs may acquire i_mutex. we need to skip them */
23443+ err = 0;
23444+ if (!did)
23445+ did = &err;
23446+ h_sb = h_path->dentry->d_sb;
23447+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
23448+ if (*did)
23449+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
23450+
23451+ return err;
23452+}
23453+
23454+/* ---------------------------------------------------------------------- */
23455+
4a4d8108
AM
23456+static int au_conv_oflags(int flags)
23457+{
23458+ int mask = 0;
23459+
23460+#ifdef CONFIG_IMA
23461+ fmode_t fmode;
23462+
23463+ /* mask = MAY_OPEN; */
23464+ fmode = OPEN_FMODE(flags);
23465+ if (fmode & FMODE_READ)
23466+ mask |= MAY_READ;
23467+ if ((fmode & FMODE_WRITE)
23468+ || (flags & O_TRUNC))
23469+ mask |= MAY_WRITE;
23470+ /*
23471+ * if (flags & O_APPEND)
23472+ * mask |= MAY_APPEND;
23473+ */
23474+ if (flags & vfsub_fmode_to_uint(FMODE_EXEC))
23475+ mask |= MAY_EXEC;
23476+
23477+ AuDbg("flags 0x%x, mask 0x%x\n", flags, mask);
23478+#endif
23479+
23480+ return mask;
23481+}
23482+
23483+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 23484+{
23485+ struct file *file;
4a4d8108 23486+ int err;
1308ab2a 23487+
4a4d8108 23488+ path_get(path);
0c5527e5 23489+ file = dentry_open(path->dentry, path->mnt,
7f207e10
AM
23490+ flags /* | vfsub_fmode_to_uint(FMODE_NONOTIFY) */,
23491+ current_cred());
1308ab2a 23492+ if (IS_ERR(file))
4a4d8108
AM
23493+ goto out;
23494+
23495+ err = ima_file_check(file, au_conv_oflags(flags));
23496+ if (unlikely(err)) {
23497+ fput(file);
23498+ file = ERR_PTR(err);
23499+ }
23500+out:
1308ab2a 23501+ return file;
23502+}
23503+
1facf9fc 23504+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
23505+{
23506+ struct file *file;
23507+
7f207e10
AM
23508+ file = filp_open(path,
23509+ oflags /* | vfsub_fmode_to_uint(FMODE_NONOTIFY) */,
23510+ mode);
1facf9fc 23511+ if (IS_ERR(file))
23512+ goto out;
23513+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23514+
4f0767ce 23515+out:
1facf9fc 23516+ return file;
23517+}
23518+
23519+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
23520+{
23521+ int err;
23522+
1facf9fc 23523+ err = kern_path(name, flags, path);
1facf9fc 23524+ if (!err && path->dentry->d_inode)
23525+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
23526+ return err;
23527+}
23528+
23529+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
23530+ int len)
23531+{
23532+ struct path path = {
23533+ .mnt = NULL
23534+ };
23535+
1308ab2a 23536+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 23537+ IMustLock(parent->d_inode);
23538+
23539+ path.dentry = lookup_one_len(name, parent, len);
23540+ if (IS_ERR(path.dentry))
23541+ goto out;
23542+ if (path.dentry->d_inode)
23543+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
23544+
4f0767ce 23545+out:
4a4d8108 23546+ AuTraceErrPtr(path.dentry);
1facf9fc 23547+ return path.dentry;
23548+}
23549+
23550+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
23551+{
23552+ struct path path = {
23553+ .mnt = nd->path.mnt
23554+ };
23555+
23556+ IMustLock(nd->path.dentry->d_inode);
23557+
23558+ path.dentry = lookup_hash(nd);
4a4d8108
AM
23559+ if (IS_ERR(path.dentry))
23560+ goto out;
23561+ if (path.dentry->d_inode)
1facf9fc 23562+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
23563+
4f0767ce 23564+out:
4a4d8108 23565+ AuTraceErrPtr(path.dentry);
1facf9fc 23566+ return path.dentry;
23567+}
23568+
23569+/* ---------------------------------------------------------------------- */
23570+
23571+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
23572+ struct dentry *d2, struct au_hinode *hdir2)
23573+{
23574+ struct dentry *d;
23575+
1facf9fc 23576+ d = lock_rename(d1, d2);
4a4d8108 23577+ au_hn_suspend(hdir1);
1facf9fc 23578+ if (hdir1 != hdir2)
4a4d8108 23579+ au_hn_suspend(hdir2);
1facf9fc 23580+
23581+ return d;
23582+}
23583+
23584+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
23585+ struct dentry *d2, struct au_hinode *hdir2)
23586+{
4a4d8108 23587+ au_hn_resume(hdir1);
1facf9fc 23588+ if (hdir1 != hdir2)
4a4d8108 23589+ au_hn_resume(hdir2);
1facf9fc 23590+ unlock_rename(d1, d2);
1facf9fc 23591+}
23592+
23593+/* ---------------------------------------------------------------------- */
23594+
23595+int vfsub_create(struct inode *dir, struct path *path, int mode)
23596+{
23597+ int err;
23598+ struct dentry *d;
23599+
23600+ IMustLock(dir);
23601+
23602+ d = path->dentry;
23603+ path->dentry = d->d_parent;
b752ccd1 23604+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 23605+ path->dentry = d;
23606+ if (unlikely(err))
23607+ goto out;
23608+
23609+ if (au_test_fs_null_nd(dir->i_sb))
23610+ err = vfs_create(dir, path->dentry, mode, NULL);
23611+ else {
23612+ struct nameidata h_nd;
23613+
23614+ memset(&h_nd, 0, sizeof(h_nd));
23615+ h_nd.flags = LOOKUP_CREATE;
23616+ h_nd.intent.open.flags = O_CREAT
23617+ | vfsub_fmode_to_uint(FMODE_READ);
23618+ h_nd.intent.open.create_mode = mode;
23619+ h_nd.path.dentry = path->dentry->d_parent;
23620+ h_nd.path.mnt = path->mnt;
23621+ path_get(&h_nd.path);
23622+ err = vfs_create(dir, path->dentry, mode, &h_nd);
23623+ path_put(&h_nd.path);
23624+ }
23625+
23626+ if (!err) {
23627+ struct path tmp = *path;
23628+ int did;
23629+
23630+ vfsub_update_h_iattr(&tmp, &did);
23631+ if (did) {
23632+ tmp.dentry = path->dentry->d_parent;
23633+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23634+ }
23635+ /*ignore*/
23636+ }
23637+
4f0767ce 23638+out:
1facf9fc 23639+ return err;
23640+}
23641+
23642+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
23643+{
23644+ int err;
23645+ struct dentry *d;
23646+
23647+ IMustLock(dir);
23648+
23649+ d = path->dentry;
23650+ path->dentry = d->d_parent;
b752ccd1 23651+ err = security_path_symlink(path, d, symname);
1facf9fc 23652+ path->dentry = d;
23653+ if (unlikely(err))
23654+ goto out;
23655+
23656+ err = vfs_symlink(dir, path->dentry, symname);
23657+ if (!err) {
23658+ struct path tmp = *path;
23659+ int did;
23660+
23661+ vfsub_update_h_iattr(&tmp, &did);
23662+ if (did) {
23663+ tmp.dentry = path->dentry->d_parent;
23664+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23665+ }
23666+ /*ignore*/
23667+ }
23668+
4f0767ce 23669+out:
1facf9fc 23670+ return err;
23671+}
23672+
23673+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
23674+{
23675+ int err;
23676+ struct dentry *d;
23677+
23678+ IMustLock(dir);
23679+
23680+ d = path->dentry;
23681+ path->dentry = d->d_parent;
b752ccd1 23682+ err = security_path_mknod(path, d, mode, dev);
1facf9fc 23683+ path->dentry = d;
23684+ if (unlikely(err))
23685+ goto out;
23686+
23687+ err = vfs_mknod(dir, path->dentry, mode, dev);
23688+ if (!err) {
23689+ struct path tmp = *path;
23690+ int did;
23691+
23692+ vfsub_update_h_iattr(&tmp, &did);
23693+ if (did) {
23694+ tmp.dentry = path->dentry->d_parent;
23695+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23696+ }
23697+ /*ignore*/
23698+ }
23699+
4f0767ce 23700+out:
1facf9fc 23701+ return err;
23702+}
23703+
23704+static int au_test_nlink(struct inode *inode)
23705+{
23706+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
23707+
23708+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
23709+ || inode->i_nlink < link_max)
23710+ return 0;
23711+ return -EMLINK;
23712+}
23713+
23714+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
23715+{
23716+ int err;
23717+ struct dentry *d;
23718+
23719+ IMustLock(dir);
23720+
23721+ err = au_test_nlink(src_dentry->d_inode);
23722+ if (unlikely(err))
23723+ return err;
23724+
23725+ d = path->dentry;
23726+ path->dentry = d->d_parent;
b752ccd1 23727+ err = security_path_link(src_dentry, path, d);
1facf9fc 23728+ path->dentry = d;
23729+ if (unlikely(err))
23730+ goto out;
23731+
1facf9fc 23732+ err = vfs_link(src_dentry, dir, path->dentry);
1facf9fc 23733+ if (!err) {
23734+ struct path tmp = *path;
23735+ int did;
23736+
23737+ /* fuse has different memory inode for the same inumber */
23738+ vfsub_update_h_iattr(&tmp, &did);
23739+ if (did) {
23740+ tmp.dentry = path->dentry->d_parent;
23741+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23742+ tmp.dentry = src_dentry;
23743+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23744+ }
23745+ /*ignore*/
23746+ }
23747+
4f0767ce 23748+out:
1facf9fc 23749+ return err;
23750+}
23751+
23752+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
23753+ struct inode *dir, struct path *path)
23754+{
23755+ int err;
23756+ struct path tmp = {
23757+ .mnt = path->mnt
23758+ };
23759+ struct dentry *d;
23760+
23761+ IMustLock(dir);
23762+ IMustLock(src_dir);
23763+
23764+ d = path->dentry;
23765+ path->dentry = d->d_parent;
23766+ tmp.dentry = src_dentry->d_parent;
b752ccd1 23767+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 23768+ path->dentry = d;
23769+ if (unlikely(err))
23770+ goto out;
23771+
1facf9fc 23772+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
1facf9fc 23773+ if (!err) {
23774+ int did;
23775+
23776+ tmp.dentry = d->d_parent;
23777+ vfsub_update_h_iattr(&tmp, &did);
23778+ if (did) {
23779+ tmp.dentry = src_dentry;
23780+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23781+ tmp.dentry = src_dentry->d_parent;
23782+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23783+ }
23784+ /*ignore*/
23785+ }
23786+
4f0767ce 23787+out:
1facf9fc 23788+ return err;
23789+}
23790+
23791+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
23792+{
23793+ int err;
23794+ struct dentry *d;
23795+
23796+ IMustLock(dir);
23797+
23798+ d = path->dentry;
23799+ path->dentry = d->d_parent;
b752ccd1 23800+ err = security_path_mkdir(path, d, mode);
1facf9fc 23801+ path->dentry = d;
23802+ if (unlikely(err))
23803+ goto out;
23804+
23805+ err = vfs_mkdir(dir, path->dentry, mode);
23806+ if (!err) {
23807+ struct path tmp = *path;
23808+ int did;
23809+
23810+ vfsub_update_h_iattr(&tmp, &did);
23811+ if (did) {
23812+ tmp.dentry = path->dentry->d_parent;
23813+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23814+ }
23815+ /*ignore*/
23816+ }
23817+
4f0767ce 23818+out:
1facf9fc 23819+ return err;
23820+}
23821+
23822+int vfsub_rmdir(struct inode *dir, struct path *path)
23823+{
23824+ int err;
23825+ struct dentry *d;
23826+
23827+ IMustLock(dir);
23828+
23829+ d = path->dentry;
23830+ path->dentry = d->d_parent;
b752ccd1 23831+ err = security_path_rmdir(path, d);
1facf9fc 23832+ path->dentry = d;
23833+ if (unlikely(err))
23834+ goto out;
23835+
1facf9fc 23836+ err = vfs_rmdir(dir, path->dentry);
1facf9fc 23837+ if (!err) {
23838+ struct path tmp = {
23839+ .dentry = path->dentry->d_parent,
23840+ .mnt = path->mnt
23841+ };
23842+
23843+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
23844+ }
23845+
4f0767ce 23846+out:
1facf9fc 23847+ return err;
23848+}
23849+
23850+/* ---------------------------------------------------------------------- */
23851+
23852+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
23853+ loff_t *ppos)
23854+{
23855+ ssize_t err;
23856+
23857+ err = vfs_read(file, ubuf, count, ppos);
23858+ if (err >= 0)
23859+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23860+ return err;
23861+}
23862+
23863+/* todo: kernel_read()? */
23864+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
23865+ loff_t *ppos)
23866+{
23867+ ssize_t err;
23868+ mm_segment_t oldfs;
b752ccd1
AM
23869+ union {
23870+ void *k;
23871+ char __user *u;
23872+ } buf;
1facf9fc 23873+
b752ccd1 23874+ buf.k = kbuf;
1facf9fc 23875+ oldfs = get_fs();
23876+ set_fs(KERNEL_DS);
b752ccd1 23877+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 23878+ set_fs(oldfs);
23879+ return err;
23880+}
23881+
23882+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
23883+ loff_t *ppos)
23884+{
23885+ ssize_t err;
23886+
1facf9fc 23887+ err = vfs_write(file, ubuf, count, ppos);
1facf9fc 23888+ if (err >= 0)
23889+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23890+ return err;
23891+}
23892+
23893+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
23894+{
23895+ ssize_t err;
23896+ mm_segment_t oldfs;
b752ccd1
AM
23897+ union {
23898+ void *k;
23899+ const char __user *u;
23900+ } buf;
1facf9fc 23901+
b752ccd1 23902+ buf.k = kbuf;
1facf9fc 23903+ oldfs = get_fs();
23904+ set_fs(KERNEL_DS);
b752ccd1 23905+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 23906+ set_fs(oldfs);
23907+ return err;
23908+}
23909+
4a4d8108
AM
23910+int vfsub_flush(struct file *file, fl_owner_t id)
23911+{
23912+ int err;
23913+
23914+ err = 0;
23915+ if (file->f_op && file->f_op->flush) {
23916+ err = file->f_op->flush(file, id);
23917+ if (!err)
23918+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
23919+ /*ignore*/
23920+ }
23921+ return err;
23922+}
23923+
1facf9fc 23924+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
23925+{
23926+ int err;
23927+
1facf9fc 23928+ err = vfs_readdir(file, filldir, arg);
1facf9fc 23929+ if (err >= 0)
23930+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23931+ return err;
23932+}
23933+
23934+long vfsub_splice_to(struct file *in, loff_t *ppos,
23935+ struct pipe_inode_info *pipe, size_t len,
23936+ unsigned int flags)
23937+{
23938+ long err;
23939+
0fc653ad 23940+ err = do_splice_to(in, ppos, pipe, len, flags);
4a4d8108 23941+ file_accessed(in);
1facf9fc 23942+ if (err >= 0)
23943+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
23944+ return err;
23945+}
23946+
23947+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
23948+ loff_t *ppos, size_t len, unsigned int flags)
23949+{
23950+ long err;
23951+
0fc653ad 23952+ err = do_splice_from(pipe, out, ppos, len, flags);
1facf9fc 23953+ if (err >= 0)
23954+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
23955+ return err;
23956+}
23957+
23958+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
23959+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
23960+ struct file *h_file)
23961+{
23962+ int err;
23963+ struct inode *h_inode;
23964+
23965+ h_inode = h_path->dentry->d_inode;
23966+ if (!h_file) {
23967+ err = mnt_want_write(h_path->mnt);
23968+ if (err)
23969+ goto out;
23970+ err = inode_permission(h_inode, MAY_WRITE);
23971+ if (err)
23972+ goto out_mnt;
23973+ err = get_write_access(h_inode);
23974+ if (err)
23975+ goto out_mnt;
4a4d8108 23976+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 23977+ if (err)
23978+ goto out_inode;
23979+ }
23980+
23981+ err = locks_verify_truncate(h_inode, h_file, length);
23982+ if (!err)
953406b4 23983+ err = security_path_truncate(h_path);
b752ccd1 23984+ if (!err)
1facf9fc 23985+ err = do_truncate(h_path->dentry, length, attr, h_file);
1facf9fc 23986+
4f0767ce 23987+out_inode:
1facf9fc 23988+ if (!h_file)
23989+ put_write_access(h_inode);
4f0767ce 23990+out_mnt:
1facf9fc 23991+ if (!h_file)
23992+ mnt_drop_write(h_path->mnt);
4f0767ce 23993+out:
1facf9fc 23994+ return err;
23995+}
23996+
23997+/* ---------------------------------------------------------------------- */
23998+
23999+struct au_vfsub_mkdir_args {
24000+ int *errp;
24001+ struct inode *dir;
24002+ struct path *path;
24003+ int mode;
24004+};
24005+
24006+static void au_call_vfsub_mkdir(void *args)
24007+{
24008+ struct au_vfsub_mkdir_args *a = args;
24009+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
24010+}
24011+
24012+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
24013+{
24014+ int err, do_sio, wkq_err;
24015+
24016+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
24017+ if (!do_sio)
24018+ err = vfsub_mkdir(dir, path, mode);
24019+ else {
24020+ struct au_vfsub_mkdir_args args = {
24021+ .errp = &err,
24022+ .dir = dir,
24023+ .path = path,
24024+ .mode = mode
24025+ };
24026+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
24027+ if (unlikely(wkq_err))
24028+ err = wkq_err;
24029+ }
24030+
24031+ return err;
24032+}
24033+
24034+struct au_vfsub_rmdir_args {
24035+ int *errp;
24036+ struct inode *dir;
24037+ struct path *path;
24038+};
24039+
24040+static void au_call_vfsub_rmdir(void *args)
24041+{
24042+ struct au_vfsub_rmdir_args *a = args;
24043+ *a->errp = vfsub_rmdir(a->dir, a->path);
24044+}
24045+
24046+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
24047+{
24048+ int err, do_sio, wkq_err;
24049+
24050+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
24051+ if (!do_sio)
24052+ err = vfsub_rmdir(dir, path);
24053+ else {
24054+ struct au_vfsub_rmdir_args args = {
24055+ .errp = &err,
24056+ .dir = dir,
24057+ .path = path
24058+ };
24059+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
24060+ if (unlikely(wkq_err))
24061+ err = wkq_err;
24062+ }
24063+
24064+ return err;
24065+}
24066+
24067+/* ---------------------------------------------------------------------- */
24068+
24069+struct notify_change_args {
24070+ int *errp;
24071+ struct path *path;
24072+ struct iattr *ia;
24073+};
24074+
24075+static void call_notify_change(void *args)
24076+{
24077+ struct notify_change_args *a = args;
24078+ struct inode *h_inode;
24079+
24080+ h_inode = a->path->dentry->d_inode;
24081+ IMustLock(h_inode);
24082+
24083+ *a->errp = -EPERM;
24084+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 24085+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 24086+ if (!*a->errp)
24087+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
24088+ }
24089+ AuTraceErr(*a->errp);
24090+}
24091+
24092+int vfsub_notify_change(struct path *path, struct iattr *ia)
24093+{
24094+ int err;
24095+ struct notify_change_args args = {
24096+ .errp = &err,
24097+ .path = path,
24098+ .ia = ia
24099+ };
24100+
24101+ call_notify_change(&args);
24102+
24103+ return err;
24104+}
24105+
24106+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
24107+{
24108+ int err, wkq_err;
24109+ struct notify_change_args args = {
24110+ .errp = &err,
24111+ .path = path,
24112+ .ia = ia
24113+ };
24114+
24115+ wkq_err = au_wkq_wait(call_notify_change, &args);
24116+ if (unlikely(wkq_err))
24117+ err = wkq_err;
24118+
24119+ return err;
24120+}
24121+
24122+/* ---------------------------------------------------------------------- */
24123+
24124+struct unlink_args {
24125+ int *errp;
24126+ struct inode *dir;
24127+ struct path *path;
24128+};
24129+
24130+static void call_unlink(void *args)
24131+{
24132+ struct unlink_args *a = args;
24133+ struct dentry *d = a->path->dentry;
24134+ struct inode *h_inode;
24135+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
24136+ && atomic_read(&d->d_count) == 1);
24137+
24138+ IMustLock(a->dir);
24139+
24140+ a->path->dentry = d->d_parent;
24141+ *a->errp = security_path_unlink(a->path, d);
24142+ a->path->dentry = d;
24143+ if (unlikely(*a->errp))
24144+ return;
24145+
24146+ if (!stop_sillyrename)
24147+ dget(d);
24148+ h_inode = d->d_inode;
24149+ if (h_inode)
24150+ atomic_inc(&h_inode->i_count);
24151+
1facf9fc 24152+ *a->errp = vfs_unlink(a->dir, d);
1facf9fc 24153+ if (!*a->errp) {
24154+ struct path tmp = {
24155+ .dentry = d->d_parent,
24156+ .mnt = a->path->mnt
24157+ };
24158+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
24159+ }
24160+
24161+ if (!stop_sillyrename)
24162+ dput(d);
24163+ if (h_inode)
24164+ iput(h_inode);
24165+
24166+ AuTraceErr(*a->errp);
24167+}
24168+
24169+/*
24170+ * @dir: must be locked.
24171+ * @dentry: target dentry.
24172+ */
24173+int vfsub_unlink(struct inode *dir, struct path *path, int force)
24174+{
24175+ int err;
24176+ struct unlink_args args = {
24177+ .errp = &err,
24178+ .dir = dir,
24179+ .path = path
24180+ };
24181+
24182+ if (!force)
24183+ call_unlink(&args);
24184+ else {
24185+ int wkq_err;
24186+
24187+ wkq_err = au_wkq_wait(call_unlink, &args);
24188+ if (unlikely(wkq_err))
24189+ err = wkq_err;
24190+ }
24191+
24192+ return err;
24193+}
7f207e10
AM
24194diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
24195--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
24196+++ linux/fs/aufs/vfsub.h 2010-11-22 11:52:57.000563767 +0100
24197@@ -0,0 +1,219 @@
1facf9fc 24198+/*
4a4d8108 24199+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 24200+ *
24201+ * This program, aufs is free software; you can redistribute it and/or modify
24202+ * it under the terms of the GNU General Public License as published by
24203+ * the Free Software Foundation; either version 2 of the License, or
24204+ * (at your option) any later version.
dece6358
AM
24205+ *
24206+ * This program is distributed in the hope that it will be useful,
24207+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24208+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24209+ * GNU General Public License for more details.
24210+ *
24211+ * You should have received a copy of the GNU General Public License
24212+ * along with this program; if not, write to the Free Software
24213+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24214+ */
24215+
24216+/*
24217+ * sub-routines for VFS
24218+ */
24219+
24220+#ifndef __AUFS_VFSUB_H__
24221+#define __AUFS_VFSUB_H__
24222+
24223+#ifdef __KERNEL__
24224+
24225+#include <linux/fs.h>
0c5527e5 24226+#include <linux/lglock.h>
7f207e10 24227+#include "debug.h"
1facf9fc 24228+
7f207e10 24229+/* copied from linux/fs/internal.h */
0c5527e5 24230+DECLARE_BRLOCK(vfsmount_lock);
0c5527e5
AM
24231+extern void file_sb_list_del(struct file *f);
24232+
7f207e10
AM
24233+/* copied from linux/fs/file_table.c */
24234+DECLARE_LGLOCK(files_lglock);
0c5527e5
AM
24235+#ifdef CONFIG_SMP
24236+/*
24237+ * These macros iterate all files on all CPUs for a given superblock.
24238+ * files_lglock must be held globally.
24239+ */
24240+#define do_file_list_for_each_entry(__sb, __file) \
24241+{ \
24242+ int i; \
24243+ for_each_possible_cpu(i) { \
24244+ struct list_head *list; \
24245+ list = per_cpu_ptr((__sb)->s_files, i); \
24246+ list_for_each_entry((__file), list, f_u.fu_list)
24247+
24248+#define while_file_list_for_each_entry \
24249+ } \
24250+}
24251+
24252+#else
24253+
24254+#define do_file_list_for_each_entry(__sb, __file) \
24255+{ \
24256+ struct list_head *list; \
24257+ list = &(sb)->s_files; \
24258+ list_for_each_entry((__file), list, f_u.fu_list)
24259+
24260+#define while_file_list_for_each_entry \
24261+}
7f207e10
AM
24262+#endif
24263+
24264+/* ---------------------------------------------------------------------- */
1facf9fc 24265+
24266+/* lock subclass for lower inode */
24267+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
24268+/* reduce? gave up. */
24269+enum {
24270+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
24271+ AuLsc_I_PARENT, /* lower inode, parent first */
24272+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 24273+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 24274+ AuLsc_I_CHILD,
24275+ AuLsc_I_CHILD2,
24276+ AuLsc_I_End
24277+};
24278+
24279+/* to debug easier, do not make them inlined functions */
24280+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
24281+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
24282+
24283+/* ---------------------------------------------------------------------- */
24284+
7f207e10
AM
24285+static inline void vfsub_drop_nlink(struct inode *inode)
24286+{
24287+ AuDebugOn(!inode->i_nlink);
24288+ drop_nlink(inode);
24289+}
24290+
24291+/* ---------------------------------------------------------------------- */
24292+
24293+int vfsub_update_h_iattr(struct path *h_path, int *did);
24294+struct file *vfsub_dentry_open(struct path *path, int flags);
24295+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
1facf9fc 24296+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
24297+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
24298+ int len);
24299+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
24300+
24301+/* ---------------------------------------------------------------------- */
24302+
24303+struct au_hinode;
24304+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
24305+ struct dentry *d2, struct au_hinode *hdir2);
24306+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
24307+ struct dentry *d2, struct au_hinode *hdir2);
24308+
24309+int vfsub_create(struct inode *dir, struct path *path, int mode);
24310+int vfsub_symlink(struct inode *dir, struct path *path,
24311+ const char *symname);
24312+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
24313+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
24314+ struct path *path);
24315+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
24316+ struct inode *hdir, struct path *path);
24317+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
24318+int vfsub_rmdir(struct inode *dir, struct path *path);
24319+
24320+/* ---------------------------------------------------------------------- */
24321+
24322+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
24323+ loff_t *ppos);
24324+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
24325+ loff_t *ppos);
24326+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
24327+ loff_t *ppos);
24328+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
24329+ loff_t *ppos);
4a4d8108 24330+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 24331+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
24332+
4a4d8108
AM
24333+static inline unsigned int vfsub_file_flags(struct file *file)
24334+{
24335+ unsigned int flags;
24336+
24337+ spin_lock(&file->f_lock);
24338+ flags = file->f_flags;
24339+ spin_unlock(&file->f_lock);
24340+
24341+ return flags;
24342+}
1308ab2a 24343+
1facf9fc 24344+static inline void vfsub_file_accessed(struct file *h_file)
24345+{
24346+ file_accessed(h_file);
24347+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
24348+}
24349+
24350+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
24351+ struct dentry *h_dentry)
24352+{
24353+ struct path h_path = {
24354+ .dentry = h_dentry,
24355+ .mnt = h_mnt
24356+ };
24357+ touch_atime(h_mnt, h_dentry);
24358+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
24359+}
24360+
4a4d8108
AM
24361+long vfsub_splice_to(struct file *in, loff_t *ppos,
24362+ struct pipe_inode_info *pipe, size_t len,
24363+ unsigned int flags);
24364+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
24365+ loff_t *ppos, size_t len, unsigned int flags);
24366+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
24367+ struct file *h_file);
24368+
1facf9fc 24369+/* ---------------------------------------------------------------------- */
24370+
24371+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
24372+{
24373+ loff_t err;
24374+
1facf9fc 24375+ err = vfs_llseek(file, offset, origin);
1facf9fc 24376+ return err;
24377+}
24378+
24379+/* ---------------------------------------------------------------------- */
24380+
24381+/* dirty workaround for strict type of fmode_t */
24382+union vfsub_fmu {
24383+ fmode_t fm;
24384+ unsigned int ui;
24385+};
24386+
24387+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
24388+{
24389+ union vfsub_fmu u = {
24390+ .fm = fm
24391+ };
24392+
24393+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
24394+
24395+ return u.ui;
24396+}
24397+
24398+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
24399+{
24400+ union vfsub_fmu u = {
24401+ .ui = ui
24402+ };
24403+
24404+ return u.fm;
24405+}
24406+
4a4d8108
AM
24407+/* ---------------------------------------------------------------------- */
24408+
24409+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
24410+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
24411+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
24412+int vfsub_notify_change(struct path *path, struct iattr *ia);
24413+int vfsub_unlink(struct inode *dir, struct path *path, int force);
24414+
1facf9fc 24415+#endif /* __KERNEL__ */
24416+#endif /* __AUFS_VFSUB_H__ */
7f207e10
AM
24417diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
24418--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
24419+++ linux/fs/aufs/wbr_policy.c 2010-11-22 11:52:57.000563767 +0100
24420@@ -0,0 +1,701 @@
1facf9fc 24421+/*
4a4d8108 24422+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 24423+ *
24424+ * This program, aufs is free software; you can redistribute it and/or modify
24425+ * it under the terms of the GNU General Public License as published by
24426+ * the Free Software Foundation; either version 2 of the License, or
24427+ * (at your option) any later version.
dece6358
AM
24428+ *
24429+ * This program is distributed in the hope that it will be useful,
24430+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24431+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24432+ * GNU General Public License for more details.
24433+ *
24434+ * You should have received a copy of the GNU General Public License
24435+ * along with this program; if not, write to the Free Software
24436+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24437+ */
24438+
24439+/*
24440+ * policies for selecting one among multiple writable branches
24441+ */
24442+
24443+#include <linux/statfs.h>
24444+#include "aufs.h"
24445+
24446+/* subset of cpup_attr() */
24447+static noinline_for_stack
24448+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
24449+{
24450+ int err, sbits;
24451+ struct iattr ia;
24452+ struct inode *h_isrc;
24453+
24454+ h_isrc = h_src->d_inode;
24455+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
24456+ ia.ia_mode = h_isrc->i_mode;
24457+ ia.ia_uid = h_isrc->i_uid;
24458+ ia.ia_gid = h_isrc->i_gid;
24459+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
24460+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
24461+ err = vfsub_sio_notify_change(h_path, &ia);
24462+
24463+ /* is this nfs only? */
24464+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
24465+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
24466+ ia.ia_mode = h_isrc->i_mode;
24467+ err = vfsub_sio_notify_change(h_path, &ia);
24468+ }
24469+
24470+ return err;
24471+}
24472+
24473+#define AuCpdown_PARENT_OPQ 1
24474+#define AuCpdown_WHED (1 << 1)
24475+#define AuCpdown_MADE_DIR (1 << 2)
24476+#define AuCpdown_DIROPQ (1 << 3)
24477+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
24478+#define au_fset_cpdown(flags, name) \
24479+ do { (flags) |= AuCpdown_##name; } while (0)
24480+#define au_fclr_cpdown(flags, name) \
24481+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 24482+
24483+struct au_cpdown_dir_args {
24484+ struct dentry *parent;
24485+ unsigned int flags;
24486+};
24487+
24488+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
24489+ struct au_cpdown_dir_args *a)
24490+{
24491+ int err;
24492+ struct dentry *opq_dentry;
24493+
24494+ opq_dentry = au_diropq_create(dentry, bdst);
24495+ err = PTR_ERR(opq_dentry);
24496+ if (IS_ERR(opq_dentry))
24497+ goto out;
24498+ dput(opq_dentry);
24499+ au_fset_cpdown(a->flags, DIROPQ);
24500+
4f0767ce 24501+out:
1facf9fc 24502+ return err;
24503+}
24504+
24505+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
24506+ struct inode *dir, aufs_bindex_t bdst)
24507+{
24508+ int err;
24509+ struct path h_path;
24510+ struct au_branch *br;
24511+
24512+ br = au_sbr(dentry->d_sb, bdst);
24513+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
24514+ err = PTR_ERR(h_path.dentry);
24515+ if (IS_ERR(h_path.dentry))
24516+ goto out;
24517+
24518+ err = 0;
24519+ if (h_path.dentry->d_inode) {
24520+ h_path.mnt = br->br_mnt;
24521+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
24522+ dentry);
24523+ }
24524+ dput(h_path.dentry);
24525+
4f0767ce 24526+out:
1facf9fc 24527+ return err;
24528+}
24529+
24530+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
24531+ struct dentry *h_parent, void *arg)
24532+{
24533+ int err, rerr;
4a4d8108 24534+ aufs_bindex_t bopq, bstart;
1facf9fc 24535+ struct path h_path;
24536+ struct dentry *parent;
24537+ struct inode *h_dir, *h_inode, *inode, *dir;
24538+ struct au_cpdown_dir_args *args = arg;
24539+
24540+ bstart = au_dbstart(dentry);
24541+ /* dentry is di-locked */
24542+ parent = dget_parent(dentry);
24543+ dir = parent->d_inode;
24544+ h_dir = h_parent->d_inode;
24545+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
24546+ IMustLock(h_dir);
24547+
24548+ err = au_lkup_neg(dentry, bdst);
24549+ if (unlikely(err < 0))
24550+ goto out;
24551+ h_path.dentry = au_h_dptr(dentry, bdst);
24552+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
24553+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
24554+ S_IRWXU | S_IRUGO | S_IXUGO);
24555+ if (unlikely(err))
24556+ goto out_put;
24557+ au_fset_cpdown(args->flags, MADE_DIR);
24558+
1facf9fc 24559+ bopq = au_dbdiropq(dentry);
24560+ au_fclr_cpdown(args->flags, WHED);
24561+ au_fclr_cpdown(args->flags, DIROPQ);
24562+ if (au_dbwh(dentry) == bdst)
24563+ au_fset_cpdown(args->flags, WHED);
24564+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
24565+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 24566+ h_inode = h_path.dentry->d_inode;
24567+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
24568+ if (au_ftest_cpdown(args->flags, WHED)) {
24569+ err = au_cpdown_dir_opq(dentry, bdst, args);
24570+ if (unlikely(err)) {
24571+ mutex_unlock(&h_inode->i_mutex);
24572+ goto out_dir;
24573+ }
24574+ }
24575+
24576+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
24577+ mutex_unlock(&h_inode->i_mutex);
24578+ if (unlikely(err))
24579+ goto out_opq;
24580+
24581+ if (au_ftest_cpdown(args->flags, WHED)) {
24582+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
24583+ if (unlikely(err))
24584+ goto out_opq;
24585+ }
24586+
24587+ inode = dentry->d_inode;
24588+ if (au_ibend(inode) < bdst)
24589+ au_set_ibend(inode, bdst);
24590+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
24591+ au_hi_flags(inode, /*isdir*/1));
24592+ goto out; /* success */
24593+
24594+ /* revert */
4f0767ce 24595+out_opq:
1facf9fc 24596+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
24597+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
24598+ rerr = au_diropq_remove(dentry, bdst);
24599+ mutex_unlock(&h_inode->i_mutex);
24600+ if (unlikely(rerr)) {
24601+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
24602+ AuDLNPair(dentry), bdst, rerr);
24603+ err = -EIO;
24604+ goto out;
24605+ }
24606+ }
4f0767ce 24607+out_dir:
1facf9fc 24608+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
24609+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
24610+ if (unlikely(rerr)) {
24611+ AuIOErr("failed removing %.*s b%d (%d)\n",
24612+ AuDLNPair(dentry), bdst, rerr);
24613+ err = -EIO;
24614+ }
24615+ }
4f0767ce 24616+out_put:
1facf9fc 24617+ au_set_h_dptr(dentry, bdst, NULL);
24618+ if (au_dbend(dentry) == bdst)
24619+ au_update_dbend(dentry);
4f0767ce 24620+out:
1facf9fc 24621+ dput(parent);
24622+ return err;
24623+}
24624+
24625+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
24626+{
24627+ int err;
24628+ struct au_cpdown_dir_args args = {
24629+ .parent = dget_parent(dentry),
24630+ .flags = 0
24631+ };
24632+
24633+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
24634+ dput(args.parent);
24635+
24636+ return err;
24637+}
24638+
24639+/* ---------------------------------------------------------------------- */
24640+
24641+/* policies for create */
24642+
4a4d8108
AM
24643+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
24644+{
24645+ int err, i, j, ndentry;
24646+ aufs_bindex_t bopq;
24647+ struct au_dcsub_pages dpages;
24648+ struct au_dpage *dpage;
24649+ struct dentry **dentries, *parent, *d;
24650+
24651+ err = au_dpages_init(&dpages, GFP_NOFS);
24652+ if (unlikely(err))
24653+ goto out;
24654+ parent = dget_parent(dentry);
24655+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/0, /*test*/NULL,
24656+ /*arg*/NULL);
24657+ if (unlikely(err))
24658+ goto out_free;
24659+
24660+ err = bindex;
24661+ for (i = 0; i < dpages.ndpage; i++) {
24662+ dpage = dpages.dpages + i;
24663+ dentries = dpage->dentries;
24664+ ndentry = dpage->ndentry;
24665+ for (j = 0; j < ndentry; j++) {
24666+ d = dentries[j];
24667+ di_read_lock_parent2(d, !AuLock_IR);
24668+ bopq = au_dbdiropq(d);
24669+ di_read_unlock(d, !AuLock_IR);
24670+ if (bopq >= 0 && bopq < err)
24671+ err = bopq;
24672+ }
24673+ }
24674+
24675+out_free:
24676+ dput(parent);
24677+ au_dpages_free(&dpages);
24678+out:
24679+ return err;
24680+}
24681+
1facf9fc 24682+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
24683+{
24684+ for (; bindex >= 0; bindex--)
24685+ if (!au_br_rdonly(au_sbr(sb, bindex)))
24686+ return bindex;
24687+ return -EROFS;
24688+}
24689+
24690+/* top down parent */
24691+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
24692+{
24693+ int err;
24694+ aufs_bindex_t bstart, bindex;
24695+ struct super_block *sb;
24696+ struct dentry *parent, *h_parent;
24697+
24698+ sb = dentry->d_sb;
24699+ bstart = au_dbstart(dentry);
24700+ err = bstart;
24701+ if (!au_br_rdonly(au_sbr(sb, bstart)))
24702+ goto out;
24703+
24704+ err = -EROFS;
24705+ parent = dget_parent(dentry);
24706+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
24707+ h_parent = au_h_dptr(parent, bindex);
24708+ if (!h_parent || !h_parent->d_inode)
24709+ continue;
24710+
24711+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
24712+ err = bindex;
24713+ break;
24714+ }
24715+ }
24716+ dput(parent);
24717+
24718+ /* bottom up here */
4a4d8108 24719+ if (unlikely(err < 0)) {
1facf9fc 24720+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
24721+ if (err >= 0)
24722+ err = au_wbr_nonopq(dentry, err);
24723+ }
1facf9fc 24724+
4f0767ce 24725+out:
1facf9fc 24726+ AuDbg("b%d\n", err);
24727+ return err;
24728+}
24729+
24730+/* ---------------------------------------------------------------------- */
24731+
24732+/* an exception for the policy other than tdp */
24733+static int au_wbr_create_exp(struct dentry *dentry)
24734+{
24735+ int err;
24736+ aufs_bindex_t bwh, bdiropq;
24737+ struct dentry *parent;
24738+
24739+ err = -1;
24740+ bwh = au_dbwh(dentry);
24741+ parent = dget_parent(dentry);
24742+ bdiropq = au_dbdiropq(parent);
24743+ if (bwh >= 0) {
24744+ if (bdiropq >= 0)
24745+ err = min(bdiropq, bwh);
24746+ else
24747+ err = bwh;
24748+ AuDbg("%d\n", err);
24749+ } else if (bdiropq >= 0) {
24750+ err = bdiropq;
24751+ AuDbg("%d\n", err);
24752+ }
24753+ dput(parent);
24754+
4a4d8108
AM
24755+ if (err >= 0)
24756+ err = au_wbr_nonopq(dentry, err);
24757+
1facf9fc 24758+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
24759+ err = -1;
24760+
24761+ AuDbg("%d\n", err);
24762+ return err;
24763+}
24764+
24765+/* ---------------------------------------------------------------------- */
24766+
24767+/* round robin */
24768+static int au_wbr_create_init_rr(struct super_block *sb)
24769+{
24770+ int err;
24771+
24772+ err = au_wbr_bu(sb, au_sbend(sb));
24773+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 24774+ /* smp_mb(); */
1facf9fc 24775+
24776+ AuDbg("b%d\n", err);
24777+ return err;
24778+}
24779+
24780+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
24781+{
24782+ int err, nbr;
24783+ unsigned int u;
24784+ aufs_bindex_t bindex, bend;
24785+ struct super_block *sb;
24786+ atomic_t *next;
24787+
24788+ err = au_wbr_create_exp(dentry);
24789+ if (err >= 0)
24790+ goto out;
24791+
24792+ sb = dentry->d_sb;
24793+ next = &au_sbi(sb)->si_wbr_rr_next;
24794+ bend = au_sbend(sb);
24795+ nbr = bend + 1;
24796+ for (bindex = 0; bindex <= bend; bindex++) {
24797+ if (!isdir) {
24798+ err = atomic_dec_return(next) + 1;
24799+ /* modulo for 0 is meaningless */
24800+ if (unlikely(!err))
24801+ err = atomic_dec_return(next) + 1;
24802+ } else
24803+ err = atomic_read(next);
24804+ AuDbg("%d\n", err);
24805+ u = err;
24806+ err = u % nbr;
24807+ AuDbg("%d\n", err);
24808+ if (!au_br_rdonly(au_sbr(sb, err)))
24809+ break;
24810+ err = -EROFS;
24811+ }
24812+
4a4d8108
AM
24813+ if (err >= 0)
24814+ err = au_wbr_nonopq(dentry, err);
24815+
4f0767ce 24816+out:
1facf9fc 24817+ AuDbg("%d\n", err);
24818+ return err;
24819+}
24820+
24821+/* ---------------------------------------------------------------------- */
24822+
24823+/* most free space */
24824+static void au_mfs(struct dentry *dentry)
24825+{
24826+ struct super_block *sb;
24827+ struct au_branch *br;
24828+ struct au_wbr_mfs *mfs;
24829+ aufs_bindex_t bindex, bend;
24830+ int err;
24831+ unsigned long long b, bavail;
7f207e10 24832+ struct path h_path;
1facf9fc 24833+ /* reduce the stack usage */
24834+ struct kstatfs *st;
24835+
24836+ st = kmalloc(sizeof(*st), GFP_NOFS);
24837+ if (unlikely(!st)) {
24838+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
24839+ return;
24840+ }
24841+
24842+ bavail = 0;
24843+ sb = dentry->d_sb;
24844+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 24845+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 24846+ mfs->mfs_bindex = -EROFS;
24847+ mfs->mfsrr_bytes = 0;
24848+ bend = au_sbend(sb);
24849+ for (bindex = 0; bindex <= bend; bindex++) {
24850+ br = au_sbr(sb, bindex);
24851+ if (au_br_rdonly(br))
24852+ continue;
24853+
24854+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
24855+ h_path.mnt = br->br_mnt;
24856+ h_path.dentry = h_path.mnt->mnt_root;
24857+ err = vfs_statfs(&h_path, st);
1facf9fc 24858+ if (unlikely(err)) {
24859+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
24860+ continue;
24861+ }
24862+
24863+ /* when the available size is equal, select the lower one */
24864+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
24865+ || sizeof(b) < sizeof(st->f_bsize));
24866+ b = st->f_bavail * st->f_bsize;
24867+ br->br_wbr->wbr_bytes = b;
24868+ if (b >= bavail) {
24869+ bavail = b;
24870+ mfs->mfs_bindex = bindex;
24871+ mfs->mfs_jiffy = jiffies;
24872+ }
24873+ }
24874+
24875+ mfs->mfsrr_bytes = bavail;
24876+ AuDbg("b%d\n", mfs->mfs_bindex);
24877+ kfree(st);
24878+}
24879+
24880+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
24881+{
24882+ int err;
24883+ struct super_block *sb;
24884+ struct au_wbr_mfs *mfs;
24885+
24886+ err = au_wbr_create_exp(dentry);
24887+ if (err >= 0)
24888+ goto out;
24889+
24890+ sb = dentry->d_sb;
24891+ mfs = &au_sbi(sb)->si_wbr_mfs;
24892+ mutex_lock(&mfs->mfs_lock);
24893+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
24894+ || mfs->mfs_bindex < 0
24895+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
24896+ au_mfs(dentry);
24897+ mutex_unlock(&mfs->mfs_lock);
24898+ err = mfs->mfs_bindex;
24899+
4a4d8108
AM
24900+ if (err >= 0)
24901+ err = au_wbr_nonopq(dentry, err);
24902+
4f0767ce 24903+out:
1facf9fc 24904+ AuDbg("b%d\n", err);
24905+ return err;
24906+}
24907+
24908+static int au_wbr_create_init_mfs(struct super_block *sb)
24909+{
24910+ struct au_wbr_mfs *mfs;
24911+
24912+ mfs = &au_sbi(sb)->si_wbr_mfs;
24913+ mutex_init(&mfs->mfs_lock);
24914+ mfs->mfs_jiffy = 0;
24915+ mfs->mfs_bindex = -EROFS;
24916+
24917+ return 0;
24918+}
24919+
24920+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
24921+{
24922+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
24923+ return 0;
24924+}
24925+
24926+/* ---------------------------------------------------------------------- */
24927+
24928+/* most free space and then round robin */
24929+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
24930+{
24931+ int err;
24932+ struct au_wbr_mfs *mfs;
24933+
24934+ err = au_wbr_create_mfs(dentry, isdir);
24935+ if (err >= 0) {
24936+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 24937+ mutex_lock(&mfs->mfs_lock);
1facf9fc 24938+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
24939+ err = au_wbr_create_rr(dentry, isdir);
dece6358 24940+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 24941+ }
24942+
24943+ AuDbg("b%d\n", err);
24944+ return err;
24945+}
24946+
24947+static int au_wbr_create_init_mfsrr(struct super_block *sb)
24948+{
24949+ int err;
24950+
24951+ au_wbr_create_init_mfs(sb); /* ignore */
24952+ err = au_wbr_create_init_rr(sb);
24953+
24954+ return err;
24955+}
24956+
24957+/* ---------------------------------------------------------------------- */
24958+
24959+/* top down parent and most free space */
24960+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
24961+{
24962+ int err, e2;
24963+ unsigned long long b;
24964+ aufs_bindex_t bindex, bstart, bend;
24965+ struct super_block *sb;
24966+ struct dentry *parent, *h_parent;
24967+ struct au_branch *br;
24968+
24969+ err = au_wbr_create_tdp(dentry, isdir);
24970+ if (unlikely(err < 0))
24971+ goto out;
24972+ parent = dget_parent(dentry);
24973+ bstart = au_dbstart(parent);
24974+ bend = au_dbtaildir(parent);
24975+ if (bstart == bend)
24976+ goto out_parent; /* success */
24977+
24978+ e2 = au_wbr_create_mfs(dentry, isdir);
24979+ if (e2 < 0)
24980+ goto out_parent; /* success */
24981+
24982+ /* when the available size is equal, select upper one */
24983+ sb = dentry->d_sb;
24984+ br = au_sbr(sb, err);
24985+ b = br->br_wbr->wbr_bytes;
24986+ AuDbg("b%d, %llu\n", err, b);
24987+
24988+ for (bindex = bstart; bindex <= bend; bindex++) {
24989+ h_parent = au_h_dptr(parent, bindex);
24990+ if (!h_parent || !h_parent->d_inode)
24991+ continue;
24992+
24993+ br = au_sbr(sb, bindex);
24994+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
24995+ b = br->br_wbr->wbr_bytes;
24996+ err = bindex;
24997+ AuDbg("b%d, %llu\n", err, b);
24998+ }
24999+ }
25000+
4a4d8108
AM
25001+ if (err >= 0)
25002+ err = au_wbr_nonopq(dentry, err);
25003+
4f0767ce 25004+out_parent:
1facf9fc 25005+ dput(parent);
4f0767ce 25006+out:
1facf9fc 25007+ AuDbg("b%d\n", err);
25008+ return err;
25009+}
25010+
25011+/* ---------------------------------------------------------------------- */
25012+
25013+/* policies for copyup */
25014+
25015+/* top down parent */
25016+static int au_wbr_copyup_tdp(struct dentry *dentry)
25017+{
25018+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
25019+}
25020+
25021+/* bottom up parent */
25022+static int au_wbr_copyup_bup(struct dentry *dentry)
25023+{
25024+ int err;
25025+ aufs_bindex_t bindex, bstart;
25026+ struct dentry *parent, *h_parent;
25027+ struct super_block *sb;
25028+
25029+ err = -EROFS;
25030+ sb = dentry->d_sb;
25031+ parent = dget_parent(dentry);
25032+ bstart = au_dbstart(parent);
25033+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
25034+ h_parent = au_h_dptr(parent, bindex);
25035+ if (!h_parent || !h_parent->d_inode)
25036+ continue;
25037+
25038+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
25039+ err = bindex;
25040+ break;
25041+ }
25042+ }
25043+ dput(parent);
25044+
25045+ /* bottom up here */
25046+ if (unlikely(err < 0))
25047+ err = au_wbr_bu(sb, bstart - 1);
25048+
25049+ AuDbg("b%d\n", err);
25050+ return err;
25051+}
25052+
25053+/* bottom up */
25054+static int au_wbr_copyup_bu(struct dentry *dentry)
25055+{
25056+ int err;
4a4d8108 25057+ aufs_bindex_t bstart;
1facf9fc 25058+
4a4d8108
AM
25059+ bstart = au_dbstart(dentry);
25060+ err = au_wbr_bu(dentry->d_sb, bstart);
25061+ AuDbg("b%d\n", err);
25062+ if (err > bstart)
25063+ err = au_wbr_nonopq(dentry, err);
1facf9fc 25064+
25065+ AuDbg("b%d\n", err);
25066+ return err;
25067+}
25068+
25069+/* ---------------------------------------------------------------------- */
25070+
25071+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
25072+ [AuWbrCopyup_TDP] = {
25073+ .copyup = au_wbr_copyup_tdp
25074+ },
25075+ [AuWbrCopyup_BUP] = {
25076+ .copyup = au_wbr_copyup_bup
25077+ },
25078+ [AuWbrCopyup_BU] = {
25079+ .copyup = au_wbr_copyup_bu
25080+ }
25081+};
25082+
25083+struct au_wbr_create_operations au_wbr_create_ops[] = {
25084+ [AuWbrCreate_TDP] = {
25085+ .create = au_wbr_create_tdp
25086+ },
25087+ [AuWbrCreate_RR] = {
25088+ .create = au_wbr_create_rr,
25089+ .init = au_wbr_create_init_rr
25090+ },
25091+ [AuWbrCreate_MFS] = {
25092+ .create = au_wbr_create_mfs,
25093+ .init = au_wbr_create_init_mfs,
25094+ .fin = au_wbr_create_fin_mfs
25095+ },
25096+ [AuWbrCreate_MFSV] = {
25097+ .create = au_wbr_create_mfs,
25098+ .init = au_wbr_create_init_mfs,
25099+ .fin = au_wbr_create_fin_mfs
25100+ },
25101+ [AuWbrCreate_MFSRR] = {
25102+ .create = au_wbr_create_mfsrr,
25103+ .init = au_wbr_create_init_mfsrr,
25104+ .fin = au_wbr_create_fin_mfs
25105+ },
25106+ [AuWbrCreate_MFSRRV] = {
25107+ .create = au_wbr_create_mfsrr,
25108+ .init = au_wbr_create_init_mfsrr,
25109+ .fin = au_wbr_create_fin_mfs
25110+ },
25111+ [AuWbrCreate_PMFS] = {
25112+ .create = au_wbr_create_pmfs,
25113+ .init = au_wbr_create_init_mfs,
25114+ .fin = au_wbr_create_fin_mfs
25115+ },
25116+ [AuWbrCreate_PMFSV] = {
25117+ .create = au_wbr_create_pmfs,
25118+ .init = au_wbr_create_init_mfs,
25119+ .fin = au_wbr_create_fin_mfs
25120+ }
25121+};
7f207e10
AM
25122diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
25123--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
25124+++ linux/fs/aufs/whout.c 2010-11-22 11:52:57.000563767 +0100
25125@@ -0,0 +1,1060 @@
1facf9fc 25126+/*
4a4d8108 25127+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25128+ *
25129+ * This program, aufs is free software; you can redistribute it and/or modify
25130+ * it under the terms of the GNU General Public License as published by
25131+ * the Free Software Foundation; either version 2 of the License, or
25132+ * (at your option) any later version.
dece6358
AM
25133+ *
25134+ * This program is distributed in the hope that it will be useful,
25135+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25136+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25137+ * GNU General Public License for more details.
25138+ *
25139+ * You should have received a copy of the GNU General Public License
25140+ * along with this program; if not, write to the Free Software
25141+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25142+ */
25143+
25144+/*
25145+ * whiteout for logical deletion and opaque directory
25146+ */
25147+
25148+#include <linux/fs.h>
25149+#include "aufs.h"
25150+
25151+#define WH_MASK S_IRUGO
25152+
25153+/*
25154+ * If a directory contains this file, then it is opaque. We start with the
25155+ * .wh. flag so that it is blocked by lookup.
25156+ */
25157+static struct qstr diropq_name = {
25158+ .name = AUFS_WH_DIROPQ,
25159+ .len = sizeof(AUFS_WH_DIROPQ) - 1
25160+};
25161+
25162+/*
25163+ * generate whiteout name, which is NOT terminated by NULL.
25164+ * @name: original d_name.name
25165+ * @len: original d_name.len
25166+ * @wh: whiteout qstr
25167+ * returns zero when succeeds, otherwise error.
25168+ * succeeded value as wh->name should be freed by kfree().
25169+ */
25170+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
25171+{
25172+ char *p;
25173+
25174+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
25175+ return -ENAMETOOLONG;
25176+
25177+ wh->len = name->len + AUFS_WH_PFX_LEN;
25178+ p = kmalloc(wh->len, GFP_NOFS);
25179+ wh->name = p;
25180+ if (p) {
25181+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25182+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
25183+ /* smp_mb(); */
25184+ return 0;
25185+ }
25186+ return -ENOMEM;
25187+}
25188+
25189+/* ---------------------------------------------------------------------- */
25190+
25191+/*
25192+ * test if the @wh_name exists under @h_parent.
25193+ * @try_sio specifies the necessary of super-io.
25194+ */
25195+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
25196+ struct au_branch *br, int try_sio)
25197+{
25198+ int err;
25199+ struct dentry *wh_dentry;
1facf9fc 25200+
1facf9fc 25201+ if (!try_sio)
25202+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
25203+ else
25204+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
25205+ err = PTR_ERR(wh_dentry);
25206+ if (IS_ERR(wh_dentry))
25207+ goto out;
25208+
25209+ err = 0;
25210+ if (!wh_dentry->d_inode)
25211+ goto out_wh; /* success */
25212+
25213+ err = 1;
25214+ if (S_ISREG(wh_dentry->d_inode->i_mode))
25215+ goto out_wh; /* success */
25216+
25217+ err = -EIO;
25218+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
25219+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
25220+
4f0767ce 25221+out_wh:
1facf9fc 25222+ dput(wh_dentry);
4f0767ce 25223+out:
1facf9fc 25224+ return err;
25225+}
25226+
25227+/*
25228+ * test if the @h_dentry sets opaque or not.
25229+ */
25230+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
25231+{
25232+ int err;
25233+ struct inode *h_dir;
25234+
25235+ h_dir = h_dentry->d_inode;
25236+ err = au_wh_test(h_dentry, &diropq_name, br,
25237+ au_test_h_perm_sio(h_dir, MAY_EXEC));
25238+ return err;
25239+}
25240+
25241+/*
25242+ * returns a negative dentry whose name is unique and temporary.
25243+ */
25244+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
25245+ struct qstr *prefix)
25246+{
1facf9fc 25247+ struct dentry *dentry;
25248+ int i;
4a4d8108
AM
25249+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN_MIN + 1],
25250+ *name, *p;
1facf9fc 25251+ static unsigned short cnt;
25252+ struct qstr qs;
25253+
4a4d8108
AM
25254+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
25255+
1facf9fc 25256+ name = defname;
25257+ qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
25258+ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
25259+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 25260+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 25261+ goto out;
25262+ dentry = ERR_PTR(-ENOMEM);
25263+ name = kmalloc(qs.len + 1, GFP_NOFS);
25264+ if (unlikely(!name))
25265+ goto out;
25266+ }
25267+
25268+ /* doubly whiteout-ed */
25269+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
25270+ p = name + AUFS_WH_PFX_LEN * 2;
25271+ memcpy(p, prefix->name, prefix->len);
25272+ p += prefix->len;
25273+ *p++ = '.';
4a4d8108 25274+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 25275+
25276+ qs.name = name;
25277+ for (i = 0; i < 3; i++) {
b752ccd1 25278+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 25279+ dentry = au_sio_lkup_one(&qs, h_parent, br);
25280+ if (IS_ERR(dentry) || !dentry->d_inode)
25281+ goto out_name;
25282+ dput(dentry);
25283+ }
4a4d8108 25284+ /* pr_warning("could not get random name\n"); */
1facf9fc 25285+ dentry = ERR_PTR(-EEXIST);
25286+ AuDbg("%.*s\n", AuLNPair(&qs));
25287+ BUG();
25288+
4f0767ce 25289+out_name:
1facf9fc 25290+ if (name != defname)
25291+ kfree(name);
4f0767ce 25292+out:
4a4d8108 25293+ AuTraceErrPtr(dentry);
1facf9fc 25294+ return dentry;
1facf9fc 25295+}
25296+
25297+/*
25298+ * rename the @h_dentry on @br to the whiteouted temporary name.
25299+ */
25300+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
25301+{
25302+ int err;
25303+ struct path h_path = {
25304+ .mnt = br->br_mnt
25305+ };
25306+ struct inode *h_dir;
25307+ struct dentry *h_parent;
25308+
25309+ h_parent = h_dentry->d_parent; /* dir inode is locked */
25310+ h_dir = h_parent->d_inode;
25311+ IMustLock(h_dir);
25312+
25313+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
25314+ err = PTR_ERR(h_path.dentry);
25315+ if (IS_ERR(h_path.dentry))
25316+ goto out;
25317+
25318+ /* under the same dir, no need to lock_rename() */
25319+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
25320+ AuTraceErr(err);
25321+ dput(h_path.dentry);
25322+
4f0767ce 25323+out:
4a4d8108 25324+ AuTraceErr(err);
1facf9fc 25325+ return err;
25326+}
25327+
25328+/* ---------------------------------------------------------------------- */
25329+/*
25330+ * functions for removing a whiteout
25331+ */
25332+
25333+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
25334+{
25335+ int force;
25336+
25337+ /*
25338+ * forces superio when the dir has a sticky bit.
25339+ * this may be a violation of unix fs semantics.
25340+ */
25341+ force = (h_dir->i_mode & S_ISVTX)
25342+ && h_path->dentry->d_inode->i_uid != current_fsuid();
25343+ return vfsub_unlink(h_dir, h_path, force);
25344+}
25345+
25346+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
25347+ struct dentry *dentry)
25348+{
25349+ int err;
25350+
25351+ err = do_unlink_wh(h_dir, h_path);
25352+ if (!err && dentry)
25353+ au_set_dbwh(dentry, -1);
25354+
25355+ return err;
25356+}
25357+
25358+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
25359+ struct au_branch *br)
25360+{
25361+ int err;
25362+ struct path h_path = {
25363+ .mnt = br->br_mnt
25364+ };
25365+
25366+ err = 0;
25367+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
25368+ if (IS_ERR(h_path.dentry))
25369+ err = PTR_ERR(h_path.dentry);
25370+ else {
25371+ if (h_path.dentry->d_inode
25372+ && S_ISREG(h_path.dentry->d_inode->i_mode))
25373+ err = do_unlink_wh(h_parent->d_inode, &h_path);
25374+ dput(h_path.dentry);
25375+ }
25376+
25377+ return err;
25378+}
25379+
25380+/* ---------------------------------------------------------------------- */
25381+/*
25382+ * initialize/clean whiteout for a branch
25383+ */
25384+
25385+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
25386+ const int isdir)
25387+{
25388+ int err;
25389+
25390+ if (!whpath->dentry->d_inode)
25391+ return;
25392+
25393+ err = mnt_want_write(whpath->mnt);
25394+ if (!err) {
25395+ if (isdir)
25396+ err = vfsub_rmdir(h_dir, whpath);
25397+ else
25398+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
25399+ mnt_drop_write(whpath->mnt);
25400+ }
25401+ if (unlikely(err))
4a4d8108
AM
25402+ pr_warning("failed removing %.*s (%d), ignored.\n",
25403+ AuDLNPair(whpath->dentry), err);
1facf9fc 25404+}
25405+
25406+static int test_linkable(struct dentry *h_root)
25407+{
25408+ struct inode *h_dir = h_root->d_inode;
25409+
25410+ if (h_dir->i_op->link)
25411+ return 0;
25412+
4a4d8108
AM
25413+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
25414+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 25415+ return -ENOSYS;
25416+}
25417+
25418+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
25419+static int au_whdir(struct inode *h_dir, struct path *path)
25420+{
25421+ int err;
25422+
25423+ err = -EEXIST;
25424+ if (!path->dentry->d_inode) {
25425+ int mode = S_IRWXU;
25426+
25427+ if (au_test_nfs(path->dentry->d_sb))
25428+ mode |= S_IXUGO;
25429+ err = mnt_want_write(path->mnt);
25430+ if (!err) {
25431+ err = vfsub_mkdir(h_dir, path, mode);
25432+ mnt_drop_write(path->mnt);
25433+ }
25434+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
25435+ err = 0;
25436+ else
4a4d8108 25437+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 25438+
25439+ return err;
25440+}
25441+
25442+struct au_wh_base {
25443+ const struct qstr *name;
25444+ struct dentry *dentry;
25445+};
25446+
25447+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
25448+ struct path *h_path)
25449+{
25450+ h_path->dentry = base[AuBrWh_BASE].dentry;
25451+ au_wh_clean(h_dir, h_path, /*isdir*/0);
25452+ h_path->dentry = base[AuBrWh_PLINK].dentry;
25453+ au_wh_clean(h_dir, h_path, /*isdir*/1);
25454+ h_path->dentry = base[AuBrWh_ORPH].dentry;
25455+ au_wh_clean(h_dir, h_path, /*isdir*/1);
25456+}
25457+
25458+/*
25459+ * returns tri-state,
25460+ * minus: error, caller should print the mesage
25461+ * zero: succuess
25462+ * plus: error, caller should NOT print the mesage
25463+ */
25464+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
25465+ int do_plink, struct au_wh_base base[],
25466+ struct path *h_path)
25467+{
25468+ int err;
25469+ struct inode *h_dir;
25470+
25471+ h_dir = h_root->d_inode;
25472+ h_path->dentry = base[AuBrWh_BASE].dentry;
25473+ au_wh_clean(h_dir, h_path, /*isdir*/0);
25474+ h_path->dentry = base[AuBrWh_PLINK].dentry;
25475+ if (do_plink) {
25476+ err = test_linkable(h_root);
25477+ if (unlikely(err)) {
25478+ err = 1;
25479+ goto out;
25480+ }
25481+
25482+ err = au_whdir(h_dir, h_path);
25483+ if (unlikely(err))
25484+ goto out;
25485+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
25486+ } else
25487+ au_wh_clean(h_dir, h_path, /*isdir*/1);
25488+ h_path->dentry = base[AuBrWh_ORPH].dentry;
25489+ err = au_whdir(h_dir, h_path);
25490+ if (unlikely(err))
25491+ goto out;
25492+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
25493+
4f0767ce 25494+out:
1facf9fc 25495+ return err;
25496+}
25497+
25498+/*
25499+ * for the moment, aufs supports the branch filesystem which does not support
25500+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
25501+ * copyup failed. finally, such filesystem will not be used as the writable
25502+ * branch.
25503+ *
25504+ * returns tri-state, see above.
25505+ */
25506+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
25507+ int do_plink, struct au_wh_base base[],
25508+ struct path *h_path)
25509+{
25510+ int err;
25511+ struct inode *h_dir;
25512+
1308ab2a 25513+ WbrWhMustWriteLock(wbr);
25514+
1facf9fc 25515+ err = test_linkable(h_root);
25516+ if (unlikely(err)) {
25517+ err = 1;
25518+ goto out;
25519+ }
25520+
25521+ /*
25522+ * todo: should this create be done in /sbin/mount.aufs helper?
25523+ */
25524+ err = -EEXIST;
25525+ h_dir = h_root->d_inode;
25526+ if (!base[AuBrWh_BASE].dentry->d_inode) {
25527+ err = mnt_want_write(h_path->mnt);
25528+ if (!err) {
25529+ h_path->dentry = base[AuBrWh_BASE].dentry;
25530+ err = vfsub_create(h_dir, h_path, WH_MASK);
25531+ mnt_drop_write(h_path->mnt);
25532+ }
25533+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
25534+ err = 0;
25535+ else
4a4d8108
AM
25536+ pr_err("unknown %.*s/%.*s exists\n",
25537+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 25538+ if (unlikely(err))
25539+ goto out;
25540+
25541+ h_path->dentry = base[AuBrWh_PLINK].dentry;
25542+ if (do_plink) {
25543+ err = au_whdir(h_dir, h_path);
25544+ if (unlikely(err))
25545+ goto out;
25546+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
25547+ } else
25548+ au_wh_clean(h_dir, h_path, /*isdir*/1);
25549+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
25550+
25551+ h_path->dentry = base[AuBrWh_ORPH].dentry;
25552+ err = au_whdir(h_dir, h_path);
25553+ if (unlikely(err))
25554+ goto out;
25555+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
25556+
4f0767ce 25557+out:
1facf9fc 25558+ return err;
25559+}
25560+
25561+/*
25562+ * initialize the whiteout base file/dir for @br.
25563+ */
25564+int au_wh_init(struct dentry *h_root, struct au_branch *br,
25565+ struct super_block *sb)
25566+{
25567+ int err, i;
25568+ const unsigned char do_plink
25569+ = !!au_opt_test(au_mntflags(sb), PLINK);
25570+ struct path path = {
25571+ .mnt = br->br_mnt
25572+ };
25573+ struct inode *h_dir;
25574+ struct au_wbr *wbr = br->br_wbr;
25575+ static const struct qstr base_name[] = {
25576+ [AuBrWh_BASE] = {
25577+ .name = AUFS_BASE_NAME,
25578+ .len = sizeof(AUFS_BASE_NAME) - 1
25579+ },
25580+ [AuBrWh_PLINK] = {
25581+ .name = AUFS_PLINKDIR_NAME,
25582+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
25583+ },
25584+ [AuBrWh_ORPH] = {
25585+ .name = AUFS_ORPHDIR_NAME,
25586+ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
25587+ }
25588+ };
25589+ struct au_wh_base base[] = {
25590+ [AuBrWh_BASE] = {
25591+ .name = base_name + AuBrWh_BASE,
25592+ .dentry = NULL
25593+ },
25594+ [AuBrWh_PLINK] = {
25595+ .name = base_name + AuBrWh_PLINK,
25596+ .dentry = NULL
25597+ },
25598+ [AuBrWh_ORPH] = {
25599+ .name = base_name + AuBrWh_ORPH,
25600+ .dentry = NULL
25601+ }
25602+ };
25603+
1308ab2a 25604+ if (wbr)
25605+ WbrWhMustWriteLock(wbr);
1facf9fc 25606+
1facf9fc 25607+ for (i = 0; i < AuBrWh_Last; i++) {
25608+ /* doubly whiteouted */
25609+ struct dentry *d;
25610+
25611+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
25612+ err = PTR_ERR(d);
25613+ if (IS_ERR(d))
25614+ goto out;
25615+
25616+ base[i].dentry = d;
25617+ AuDebugOn(wbr
25618+ && wbr->wbr_wh[i]
25619+ && wbr->wbr_wh[i] != base[i].dentry);
25620+ }
25621+
25622+ if (wbr)
25623+ for (i = 0; i < AuBrWh_Last; i++) {
25624+ dput(wbr->wbr_wh[i]);
25625+ wbr->wbr_wh[i] = NULL;
25626+ }
25627+
25628+ err = 0;
1facf9fc 25629+ switch (br->br_perm) {
25630+ case AuBrPerm_RO:
25631+ case AuBrPerm_ROWH:
25632+ case AuBrPerm_RR:
25633+ case AuBrPerm_RRWH:
4a4d8108 25634+ h_dir = h_root->d_inode;
1facf9fc 25635+ au_wh_init_ro(h_dir, base, &path);
25636+ break;
25637+
25638+ case AuBrPerm_RWNoLinkWH:
25639+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
25640+ if (err > 0)
25641+ goto out;
25642+ else if (err)
25643+ goto out_err;
25644+ break;
25645+
25646+ case AuBrPerm_RW:
25647+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
25648+ if (err > 0)
25649+ goto out;
25650+ else if (err)
25651+ goto out_err;
25652+ break;
25653+
25654+ default:
25655+ BUG();
25656+ }
25657+ goto out; /* success */
25658+
4f0767ce 25659+out_err:
4a4d8108
AM
25660+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
25661+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 25662+out:
1facf9fc 25663+ for (i = 0; i < AuBrWh_Last; i++)
25664+ dput(base[i].dentry);
25665+ return err;
25666+}
25667+
25668+/* ---------------------------------------------------------------------- */
25669+/*
25670+ * whiteouts are all hard-linked usually.
25671+ * when its link count reaches a ceiling, we create a new whiteout base
25672+ * asynchronously.
25673+ */
25674+
25675+struct reinit_br_wh {
25676+ struct super_block *sb;
25677+ struct au_branch *br;
25678+};
25679+
25680+static void reinit_br_wh(void *arg)
25681+{
25682+ int err;
25683+ aufs_bindex_t bindex;
25684+ struct path h_path;
25685+ struct reinit_br_wh *a = arg;
25686+ struct au_wbr *wbr;
25687+ struct inode *dir;
25688+ struct dentry *h_root;
25689+ struct au_hinode *hdir;
25690+
25691+ err = 0;
25692+ wbr = a->br->br_wbr;
25693+ /* big aufs lock */
25694+ si_noflush_write_lock(a->sb);
25695+ if (!au_br_writable(a->br->br_perm))
25696+ goto out;
25697+ bindex = au_br_index(a->sb, a->br->br_id);
25698+ if (unlikely(bindex < 0))
25699+ goto out;
25700+
1308ab2a 25701+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 25702+ dir = a->sb->s_root->d_inode;
1facf9fc 25703+ hdir = au_hi(dir, bindex);
25704+ h_root = au_h_dptr(a->sb->s_root, bindex);
25705+
4a4d8108 25706+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 25707+ wbr_wh_write_lock(wbr);
25708+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
25709+ h_root, a->br);
25710+ if (!err) {
25711+ err = mnt_want_write(a->br->br_mnt);
25712+ if (!err) {
25713+ h_path.dentry = wbr->wbr_whbase;
25714+ h_path.mnt = a->br->br_mnt;
25715+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
25716+ mnt_drop_write(a->br->br_mnt);
25717+ }
25718+ } else {
4a4d8108
AM
25719+ pr_warning("%.*s is moved, ignored\n",
25720+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 25721+ err = 0;
25722+ }
25723+ dput(wbr->wbr_whbase);
25724+ wbr->wbr_whbase = NULL;
25725+ if (!err)
25726+ err = au_wh_init(h_root, a->br, a->sb);
25727+ wbr_wh_write_unlock(wbr);
4a4d8108 25728+ au_hn_imtx_unlock(hdir);
1308ab2a 25729+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 25730+
4f0767ce 25731+out:
1facf9fc 25732+ if (wbr)
25733+ atomic_dec(&wbr->wbr_wh_running);
25734+ atomic_dec(&a->br->br_count);
25735+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
25736+ si_write_unlock(a->sb);
25737+ kfree(arg);
25738+ if (unlikely(err))
25739+ AuIOErr("err %d\n", err);
25740+}
25741+
25742+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
25743+{
25744+ int do_dec, wkq_err;
25745+ struct reinit_br_wh *arg;
25746+
25747+ do_dec = 1;
25748+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
25749+ goto out;
25750+
25751+ /* ignore ENOMEM */
25752+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
25753+ if (arg) {
25754+ /*
25755+ * dec(wh_running), kfree(arg) and dec(br_count)
25756+ * in reinit function
25757+ */
25758+ arg->sb = sb;
25759+ arg->br = br;
25760+ atomic_inc(&br->br_count);
25761+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
25762+ if (unlikely(wkq_err)) {
25763+ atomic_dec(&br->br_wbr->wbr_wh_running);
25764+ atomic_dec(&br->br_count);
25765+ kfree(arg);
25766+ }
25767+ do_dec = 0;
25768+ }
25769+
4f0767ce 25770+out:
1facf9fc 25771+ if (do_dec)
25772+ atomic_dec(&br->br_wbr->wbr_wh_running);
25773+}
25774+
25775+/* ---------------------------------------------------------------------- */
25776+
25777+/*
25778+ * create the whiteout @wh.
25779+ */
25780+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
25781+ struct dentry *wh)
25782+{
25783+ int err;
25784+ struct path h_path = {
25785+ .dentry = wh
25786+ };
25787+ struct au_branch *br;
25788+ struct au_wbr *wbr;
25789+ struct dentry *h_parent;
25790+ struct inode *h_dir;
25791+
25792+ h_parent = wh->d_parent; /* dir inode is locked */
25793+ h_dir = h_parent->d_inode;
25794+ IMustLock(h_dir);
25795+
25796+ br = au_sbr(sb, bindex);
25797+ h_path.mnt = br->br_mnt;
25798+ wbr = br->br_wbr;
25799+ wbr_wh_read_lock(wbr);
25800+ if (wbr->wbr_whbase) {
25801+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
25802+ if (!err || err != -EMLINK)
25803+ goto out;
25804+
25805+ /* link count full. re-initialize br_whbase. */
25806+ kick_reinit_br_wh(sb, br);
25807+ }
25808+
25809+ /* return this error in this context */
25810+ err = vfsub_create(h_dir, &h_path, WH_MASK);
25811+
4f0767ce 25812+out:
1facf9fc 25813+ wbr_wh_read_unlock(wbr);
25814+ return err;
25815+}
25816+
25817+/* ---------------------------------------------------------------------- */
25818+
25819+/*
25820+ * create or remove the diropq.
25821+ */
25822+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
25823+ unsigned int flags)
25824+{
25825+ struct dentry *opq_dentry, *h_dentry;
25826+ struct super_block *sb;
25827+ struct au_branch *br;
25828+ int err;
25829+
25830+ sb = dentry->d_sb;
25831+ br = au_sbr(sb, bindex);
25832+ h_dentry = au_h_dptr(dentry, bindex);
25833+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
25834+ if (IS_ERR(opq_dentry))
25835+ goto out;
25836+
25837+ if (au_ftest_diropq(flags, CREATE)) {
25838+ err = link_or_create_wh(sb, bindex, opq_dentry);
25839+ if (!err) {
25840+ au_set_dbdiropq(dentry, bindex);
25841+ goto out; /* success */
25842+ }
25843+ } else {
25844+ struct path tmp = {
25845+ .dentry = opq_dentry,
25846+ .mnt = br->br_mnt
25847+ };
25848+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
25849+ if (!err)
25850+ au_set_dbdiropq(dentry, -1);
25851+ }
25852+ dput(opq_dentry);
25853+ opq_dentry = ERR_PTR(err);
25854+
4f0767ce 25855+out:
1facf9fc 25856+ return opq_dentry;
25857+}
25858+
25859+struct do_diropq_args {
25860+ struct dentry **errp;
25861+ struct dentry *dentry;
25862+ aufs_bindex_t bindex;
25863+ unsigned int flags;
25864+};
25865+
25866+static void call_do_diropq(void *args)
25867+{
25868+ struct do_diropq_args *a = args;
25869+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
25870+}
25871+
25872+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
25873+ unsigned int flags)
25874+{
25875+ struct dentry *diropq, *h_dentry;
25876+
25877+ h_dentry = au_h_dptr(dentry, bindex);
25878+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
25879+ diropq = do_diropq(dentry, bindex, flags);
25880+ else {
25881+ int wkq_err;
25882+ struct do_diropq_args args = {
25883+ .errp = &diropq,
25884+ .dentry = dentry,
25885+ .bindex = bindex,
25886+ .flags = flags
25887+ };
25888+
25889+ wkq_err = au_wkq_wait(call_do_diropq, &args);
25890+ if (unlikely(wkq_err))
25891+ diropq = ERR_PTR(wkq_err);
25892+ }
25893+
25894+ return diropq;
25895+}
25896+
25897+/* ---------------------------------------------------------------------- */
25898+
25899+/*
25900+ * lookup whiteout dentry.
25901+ * @h_parent: lower parent dentry which must exist and be locked
25902+ * @base_name: name of dentry which will be whiteouted
25903+ * returns dentry for whiteout.
25904+ */
25905+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
25906+ struct au_branch *br)
25907+{
25908+ int err;
25909+ struct qstr wh_name;
25910+ struct dentry *wh_dentry;
25911+
25912+ err = au_wh_name_alloc(&wh_name, base_name);
25913+ wh_dentry = ERR_PTR(err);
25914+ if (!err) {
25915+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
25916+ kfree(wh_name.name);
25917+ }
25918+ return wh_dentry;
25919+}
25920+
25921+/*
25922+ * link/create a whiteout for @dentry on @bindex.
25923+ */
25924+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
25925+ struct dentry *h_parent)
25926+{
25927+ struct dentry *wh_dentry;
25928+ struct super_block *sb;
25929+ int err;
25930+
25931+ sb = dentry->d_sb;
25932+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
25933+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
25934+ err = link_or_create_wh(sb, bindex, wh_dentry);
25935+ if (!err)
25936+ au_set_dbwh(dentry, bindex);
25937+ else {
25938+ dput(wh_dentry);
25939+ wh_dentry = ERR_PTR(err);
25940+ }
25941+ }
25942+
25943+ return wh_dentry;
25944+}
25945+
25946+/* ---------------------------------------------------------------------- */
25947+
25948+/* Delete all whiteouts in this directory on branch bindex. */
25949+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
25950+ aufs_bindex_t bindex, struct au_branch *br)
25951+{
25952+ int err;
25953+ unsigned long ul, n;
25954+ struct qstr wh_name;
25955+ char *p;
25956+ struct hlist_head *head;
25957+ struct au_vdir_wh *tpos;
25958+ struct hlist_node *pos;
25959+ struct au_vdir_destr *str;
25960+
25961+ err = -ENOMEM;
4a4d8108 25962+ p = __getname_gfp(GFP_NOFS);
1facf9fc 25963+ wh_name.name = p;
25964+ if (unlikely(!wh_name.name))
25965+ goto out;
25966+
25967+ err = 0;
25968+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25969+ p += AUFS_WH_PFX_LEN;
25970+ n = whlist->nh_num;
25971+ head = whlist->nh_head;
25972+ for (ul = 0; !err && ul < n; ul++, head++) {
25973+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
25974+ if (tpos->wh_bindex != bindex)
25975+ continue;
25976+
25977+ str = &tpos->wh_str;
25978+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
25979+ memcpy(p, str->name, str->len);
25980+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
25981+ err = unlink_wh_name(h_dentry, &wh_name, br);
25982+ if (!err)
25983+ continue;
25984+ break;
25985+ }
25986+ AuIOErr("whiteout name too long %.*s\n",
25987+ str->len, str->name);
25988+ err = -EIO;
25989+ break;
25990+ }
25991+ }
25992+ __putname(wh_name.name);
25993+
4f0767ce 25994+out:
1facf9fc 25995+ return err;
25996+}
25997+
25998+struct del_wh_children_args {
25999+ int *errp;
26000+ struct dentry *h_dentry;
1308ab2a 26001+ struct au_nhash *whlist;
1facf9fc 26002+ aufs_bindex_t bindex;
26003+ struct au_branch *br;
26004+};
26005+
26006+static void call_del_wh_children(void *args)
26007+{
26008+ struct del_wh_children_args *a = args;
1308ab2a 26009+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 26010+}
26011+
26012+/* ---------------------------------------------------------------------- */
26013+
26014+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
26015+{
26016+ struct au_whtmp_rmdir *whtmp;
dece6358 26017+ int err;
1308ab2a 26018+ unsigned int rdhash;
dece6358
AM
26019+
26020+ SiMustAnyLock(sb);
1facf9fc 26021+
26022+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
26023+ if (unlikely(!whtmp)) {
26024+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 26025+ goto out;
dece6358 26026+ }
1facf9fc 26027+
26028+ whtmp->dir = NULL;
26029+ whtmp->wh_dentry = NULL;
1308ab2a 26030+ /* no estimation for dir size */
26031+ rdhash = au_sbi(sb)->si_rdhash;
26032+ if (!rdhash)
26033+ rdhash = AUFS_RDHASH_DEF;
26034+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
26035+ if (unlikely(err)) {
26036+ kfree(whtmp);
26037+ whtmp = ERR_PTR(err);
26038+ }
dece6358 26039+
4f0767ce 26040+out:
dece6358 26041+ return whtmp;
1facf9fc 26042+}
26043+
26044+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
26045+{
26046+ dput(whtmp->wh_dentry);
26047+ iput(whtmp->dir);
dece6358 26048+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 26049+ kfree(whtmp);
26050+}
26051+
26052+/*
26053+ * rmdir the whiteouted temporary named dir @h_dentry.
26054+ * @whlist: whiteouted children.
26055+ */
26056+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
26057+ struct dentry *wh_dentry, struct au_nhash *whlist)
26058+{
26059+ int err;
26060+ struct path h_tmp;
26061+ struct inode *wh_inode, *h_dir;
26062+ struct au_branch *br;
26063+
26064+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
26065+ IMustLock(h_dir);
26066+
26067+ br = au_sbr(dir->i_sb, bindex);
26068+ wh_inode = wh_dentry->d_inode;
26069+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
26070+
26071+ /*
26072+ * someone else might change some whiteouts while we were sleeping.
26073+ * it means this whlist may have an obsoleted entry.
26074+ */
26075+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
26076+ err = del_wh_children(wh_dentry, whlist, bindex, br);
26077+ else {
26078+ int wkq_err;
26079+ struct del_wh_children_args args = {
26080+ .errp = &err,
26081+ .h_dentry = wh_dentry,
1308ab2a 26082+ .whlist = whlist,
1facf9fc 26083+ .bindex = bindex,
26084+ .br = br
26085+ };
26086+
26087+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
26088+ if (unlikely(wkq_err))
26089+ err = wkq_err;
26090+ }
26091+ mutex_unlock(&wh_inode->i_mutex);
26092+
26093+ if (!err) {
26094+ h_tmp.dentry = wh_dentry;
26095+ h_tmp.mnt = br->br_mnt;
26096+ err = vfsub_rmdir(h_dir, &h_tmp);
26097+ /* d_drop(h_dentry); */
26098+ }
26099+
26100+ if (!err) {
26101+ if (au_ibstart(dir) == bindex) {
7f207e10 26102+ /* todo: dir->i_mutex is necessary */
1facf9fc 26103+ au_cpup_attr_timesizes(dir);
7f207e10 26104+ vfsub_drop_nlink(dir);
1facf9fc 26105+ }
26106+ return 0; /* success */
26107+ }
26108+
4a4d8108
AM
26109+ pr_warning("failed removing %.*s(%d), ignored\n",
26110+ AuDLNPair(wh_dentry), err);
1facf9fc 26111+ return err;
26112+}
26113+
26114+static void call_rmdir_whtmp(void *args)
26115+{
26116+ int err;
e49829fe 26117+ aufs_bindex_t bindex;
1facf9fc 26118+ struct au_whtmp_rmdir *a = args;
26119+ struct super_block *sb;
26120+ struct dentry *h_parent;
26121+ struct inode *h_dir;
1facf9fc 26122+ struct au_hinode *hdir;
26123+
26124+ /* rmdir by nfsd may cause deadlock with this i_mutex */
26125+ /* mutex_lock(&a->dir->i_mutex); */
e49829fe 26126+ err = -EROFS;
1facf9fc 26127+ sb = a->dir->i_sb;
e49829fe
JR
26128+ si_read_lock(sb, !AuLock_FLUSH);
26129+ if (!au_br_writable(a->br->br_perm))
26130+ goto out;
26131+ bindex = au_br_index(sb, a->br->br_id);
26132+ if (unlikely(bindex < 0))
1facf9fc 26133+ goto out;
26134+
26135+ err = -EIO;
1facf9fc 26136+ ii_write_lock_parent(a->dir);
26137+ h_parent = dget_parent(a->wh_dentry);
26138+ h_dir = h_parent->d_inode;
e49829fe 26139+ hdir = au_hi(a->dir, bindex);
4a4d8108 26140+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
26141+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
26142+ a->br);
1facf9fc 26143+ if (!err) {
e49829fe 26144+ err = mnt_want_write(a->br->br_mnt);
1facf9fc 26145+ if (!err) {
e49829fe 26146+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
dece6358 26147+ &a->whlist);
e49829fe 26148+ mnt_drop_write(a->br->br_mnt);
1facf9fc 26149+ }
26150+ }
4a4d8108 26151+ au_hn_imtx_unlock(hdir);
1facf9fc 26152+ dput(h_parent);
26153+ ii_write_unlock(a->dir);
26154+
4f0767ce 26155+out:
1facf9fc 26156+ /* mutex_unlock(&a->dir->i_mutex); */
e49829fe 26157+ atomic_dec(&a->br->br_count);
1facf9fc 26158+ au_nwt_done(&au_sbi(sb)->si_nowait);
26159+ si_read_unlock(sb);
26160+ au_whtmp_rmdir_free(a);
26161+ if (unlikely(err))
26162+ AuIOErr("err %d\n", err);
26163+}
26164+
26165+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
26166+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
26167+{
26168+ int wkq_err;
e49829fe 26169+ struct super_block *sb;
1facf9fc 26170+
26171+ IMustLock(dir);
26172+
26173+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 26174+ sb = dir->i_sb;
1facf9fc 26175+ args->dir = au_igrab(dir);
e49829fe
JR
26176+ args->br = au_sbr(sb, bindex);
26177+ atomic_inc(&args->br->br_count);
1facf9fc 26178+ args->wh_dentry = dget(wh_dentry);
e49829fe 26179+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb);
1facf9fc 26180+ if (unlikely(wkq_err)) {
4a4d8108
AM
26181+ pr_warning("rmdir error %.*s (%d), ignored\n",
26182+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 26183+ au_whtmp_rmdir_free(args);
26184+ }
26185+}
7f207e10
AM
26186diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
26187--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
26188+++ linux/fs/aufs/whout.h 2010-11-22 11:52:57.000563767 +0100
26189@@ -0,0 +1,89 @@
1facf9fc 26190+/*
4a4d8108 26191+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26192+ *
26193+ * This program, aufs is free software; you can redistribute it and/or modify
26194+ * it under the terms of the GNU General Public License as published by
26195+ * the Free Software Foundation; either version 2 of the License, or
26196+ * (at your option) any later version.
dece6358
AM
26197+ *
26198+ * This program is distributed in the hope that it will be useful,
26199+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26200+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26201+ * GNU General Public License for more details.
26202+ *
26203+ * You should have received a copy of the GNU General Public License
26204+ * along with this program; if not, write to the Free Software
26205+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26206+ */
26207+
26208+/*
26209+ * whiteout for logical deletion and opaque directory
26210+ */
26211+
26212+#ifndef __AUFS_WHOUT_H__
26213+#define __AUFS_WHOUT_H__
26214+
26215+#ifdef __KERNEL__
26216+
1facf9fc 26217+#include <linux/aufs_type.h>
26218+#include "dir.h"
26219+
26220+/* whout.c */
26221+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
26222+struct au_branch;
26223+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
26224+ struct au_branch *br, int try_sio);
26225+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
26226+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
26227+ struct qstr *prefix);
26228+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
26229+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
26230+ struct dentry *dentry);
26231+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
26232+ struct super_block *sb);
26233+
26234+/* diropq flags */
26235+#define AuDiropq_CREATE 1
26236+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
26237+#define au_fset_diropq(flags, name) \
26238+ do { (flags) |= AuDiropq_##name; } while (0)
26239+#define au_fclr_diropq(flags, name) \
26240+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 26241+
26242+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
26243+ unsigned int flags);
26244+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
26245+ struct au_branch *br);
26246+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
26247+ struct dentry *h_parent);
26248+
26249+/* real rmdir for the whiteout-ed dir */
26250+struct au_whtmp_rmdir {
26251+ struct inode *dir;
e49829fe 26252+ struct au_branch *br;
1facf9fc 26253+ struct dentry *wh_dentry;
dece6358 26254+ struct au_nhash whlist;
1facf9fc 26255+};
26256+
26257+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
26258+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
26259+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
26260+ struct dentry *wh_dentry, struct au_nhash *whlist);
26261+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
26262+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
26263+
26264+/* ---------------------------------------------------------------------- */
26265+
26266+static inline struct dentry *au_diropq_create(struct dentry *dentry,
26267+ aufs_bindex_t bindex)
26268+{
26269+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
26270+}
26271+
26272+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
26273+{
26274+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
26275+}
26276+
26277+#endif /* __KERNEL__ */
26278+#endif /* __AUFS_WHOUT_H__ */
7f207e10
AM
26279diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
26280--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
26281+++ linux/fs/aufs/wkq.c 2010-11-22 11:52:57.000563767 +0100
26282@@ -0,0 +1,232 @@
1facf9fc 26283+/*
4a4d8108 26284+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26285+ *
26286+ * This program, aufs is free software; you can redistribute it and/or modify
26287+ * it under the terms of the GNU General Public License as published by
26288+ * the Free Software Foundation; either version 2 of the License, or
26289+ * (at your option) any later version.
dece6358
AM
26290+ *
26291+ * This program is distributed in the hope that it will be useful,
26292+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26293+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26294+ * GNU General Public License for more details.
26295+ *
26296+ * You should have received a copy of the GNU General Public License
26297+ * along with this program; if not, write to the Free Software
26298+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26299+ */
26300+
26301+/*
26302+ * workqueue for asynchronous/super-io operations
26303+ * todo: try new dredential scheme
26304+ */
26305+
dece6358 26306+#include <linux/module.h>
1facf9fc 26307+#include "aufs.h"
26308+
b752ccd1
AM
26309+/* internal workqueue named AUFS_WKQ_NAME and AUFS_WKQ_PRE_NAME */
26310+enum {
26311+ AuWkq_INORMAL,
26312+ AuWkq_IPRE
26313+};
26314+
26315+static struct {
26316+ char *name;
26317+ struct workqueue_struct *wkq;
26318+} au_wkq[] = {
26319+ [AuWkq_INORMAL] = {
26320+ .name = AUFS_WKQ_NAME
26321+ },
26322+ [AuWkq_IPRE] = {
26323+ .name = AUFS_WKQ_PRE_NAME
26324+ }
26325+};
1facf9fc 26326+
26327+struct au_wkinfo {
26328+ struct work_struct wk;
7f207e10 26329+ struct kobject *kobj;
1facf9fc 26330+
26331+ unsigned int flags; /* see wkq.h */
26332+
26333+ au_wkq_func_t func;
26334+ void *args;
26335+
1facf9fc 26336+ struct completion *comp;
26337+};
26338+
26339+/* ---------------------------------------------------------------------- */
26340+
1facf9fc 26341+static void wkq_func(struct work_struct *wk)
26342+{
26343+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
26344+
7f207e10
AM
26345+ AuDebugOn(current_fsuid());
26346+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
26347+
1facf9fc 26348+ wkinfo->func(wkinfo->args);
1facf9fc 26349+ if (au_ftest_wkq(wkinfo->flags, WAIT))
26350+ complete(wkinfo->comp);
26351+ else {
7f207e10 26352+ kobject_put(wkinfo->kobj);
1facf9fc 26353+ module_put(THIS_MODULE);
26354+ kfree(wkinfo);
26355+ }
26356+}
26357+
26358+/*
26359+ * Since struct completion is large, try allocating it dynamically.
26360+ */
26361+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
26362+#define AuWkqCompDeclare(name) struct completion *comp = NULL
26363+
26364+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
26365+{
26366+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
26367+ if (*comp) {
26368+ init_completion(*comp);
26369+ wkinfo->comp = *comp;
26370+ return 0;
26371+ }
26372+ return -ENOMEM;
26373+}
26374+
26375+static void au_wkq_comp_free(struct completion *comp)
26376+{
26377+ kfree(comp);
26378+}
26379+
26380+#else
26381+
26382+/* no braces */
26383+#define AuWkqCompDeclare(name) \
26384+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
26385+ struct completion *comp = &_ ## name
26386+
26387+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
26388+{
26389+ wkinfo->comp = *comp;
26390+ return 0;
26391+}
26392+
26393+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
26394+{
26395+ /* empty */
26396+}
26397+#endif /* 4KSTACKS */
26398+
b752ccd1 26399+static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags)
1facf9fc 26400+{
b752ccd1
AM
26401+ struct workqueue_struct *wkq;
26402+
1facf9fc 26403+ au_dbg_verify_kthread();
b752ccd1 26404+ if (flags & AuWkq_WAIT) {
a1f66529 26405+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
b752ccd1
AM
26406+ wkq = au_wkq[AuWkq_INORMAL].wkq;
26407+ if (flags & AuWkq_PRE)
26408+ wkq = au_wkq[AuWkq_IPRE].wkq;
26409+ queue_work(wkq, &wkinfo->wk);
4a4d8108
AM
26410+ } else {
26411+ INIT_WORK(&wkinfo->wk, wkq_func);
26412+ schedule_work(&wkinfo->wk);
26413+ }
1facf9fc 26414+}
26415+
7f207e10
AM
26416+/*
26417+ * Be careful. It is easy to make deadlock happen.
26418+ * processA: lock, wkq and wait
26419+ * processB: wkq and wait, lock in wkq
26420+ * --> deadlock
26421+ */
b752ccd1 26422+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 26423+{
26424+ int err;
26425+ AuWkqCompDeclare(comp);
26426+ struct au_wkinfo wkinfo = {
b752ccd1 26427+ .flags = flags,
1facf9fc 26428+ .func = func,
26429+ .args = args
26430+ };
26431+
26432+ err = au_wkq_comp_alloc(&wkinfo, &comp);
26433+ if (!err) {
b752ccd1 26434+ au_wkq_run(&wkinfo, flags);
1facf9fc 26435+ /* no timeout, no interrupt */
26436+ wait_for_completion(wkinfo.comp);
26437+ au_wkq_comp_free(comp);
4a4d8108 26438+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 26439+ }
26440+
26441+ return err;
26442+
26443+}
26444+
26445+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
26446+{
26447+ int err;
26448+ struct au_wkinfo *wkinfo;
26449+
26450+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
26451+
26452+ /*
26453+ * wkq_func() must free this wkinfo.
26454+ * it highly depends upon the implementation of workqueue.
26455+ */
26456+ err = 0;
26457+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
26458+ if (wkinfo) {
7f207e10 26459+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
1facf9fc 26460+ wkinfo->flags = !AuWkq_WAIT;
26461+ wkinfo->func = func;
26462+ wkinfo->args = args;
26463+ wkinfo->comp = NULL;
7f207e10 26464+ kobject_get(wkinfo->kobj);
1facf9fc 26465+ __module_get(THIS_MODULE);
26466+
4a4d8108 26467+ au_wkq_run(wkinfo, !AuWkq_WAIT);
1facf9fc 26468+ } else {
26469+ err = -ENOMEM;
e49829fe 26470+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 26471+ }
26472+
26473+ return err;
26474+}
26475+
26476+/* ---------------------------------------------------------------------- */
26477+
26478+void au_nwt_init(struct au_nowait_tasks *nwt)
26479+{
26480+ atomic_set(&nwt->nw_len, 0);
4a4d8108 26481+ /* smp_mb(); */ /* atomic_set */
1facf9fc 26482+ init_waitqueue_head(&nwt->nw_wq);
26483+}
26484+
26485+void au_wkq_fin(void)
26486+{
b752ccd1
AM
26487+ int i;
26488+
26489+ for (i = 0; i < ARRAY_SIZE(au_wkq); i++)
26490+ if (au_wkq[i].wkq)
26491+ destroy_workqueue(au_wkq[i].wkq);
1facf9fc 26492+}
26493+
26494+int __init au_wkq_init(void)
26495+{
b752ccd1
AM
26496+ int err, i;
26497+
26498+ err = 0;
26499+ for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
7f207e10
AM
26500+ BUILD_BUG_ON(!WQ_RESCUER);
26501+ au_wkq[i].wkq = alloc_workqueue(au_wkq[i].name, !WQ_RESCUER,
26502+ WQ_DFL_ACTIVE);
b752ccd1
AM
26503+ if (IS_ERR(au_wkq[i].wkq))
26504+ err = PTR_ERR(au_wkq[i].wkq);
26505+ else if (!au_wkq[i].wkq)
26506+ err = -ENOMEM;
26507+ if (unlikely(err))
26508+ au_wkq[i].wkq = NULL;
26509+ }
7f207e10 26510+ if (unlikely(err))
b752ccd1
AM
26511+ au_wkq_fin();
26512+
26513+ return err;
1facf9fc 26514+}
7f207e10
AM
26515diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
26516--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
26517+++ linux/fs/aufs/wkq.h 2010-11-22 11:52:57.003897646 +0100
26518@@ -0,0 +1,90 @@
1facf9fc 26519+/*
4a4d8108 26520+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26521+ *
26522+ * This program, aufs is free software; you can redistribute it and/or modify
26523+ * it under the terms of the GNU General Public License as published by
26524+ * the Free Software Foundation; either version 2 of the License, or
26525+ * (at your option) any later version.
dece6358
AM
26526+ *
26527+ * This program is distributed in the hope that it will be useful,
26528+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26529+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26530+ * GNU General Public License for more details.
26531+ *
26532+ * You should have received a copy of the GNU General Public License
26533+ * along with this program; if not, write to the Free Software
26534+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26535+ */
26536+
26537+/*
26538+ * workqueue for asynchronous/super-io operations
26539+ * todo: try new credentials management scheme
26540+ */
26541+
26542+#ifndef __AUFS_WKQ_H__
26543+#define __AUFS_WKQ_H__
26544+
26545+#ifdef __KERNEL__
26546+
1facf9fc 26547+#include <linux/sched.h>
dece6358 26548+#include <linux/wait.h>
1facf9fc 26549+#include <linux/aufs_type.h>
26550+
dece6358
AM
26551+struct super_block;
26552+
1facf9fc 26553+/* ---------------------------------------------------------------------- */
26554+
26555+/*
26556+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
26557+ */
26558+struct au_nowait_tasks {
26559+ atomic_t nw_len;
26560+ wait_queue_head_t nw_wq;
26561+};
26562+
26563+/* ---------------------------------------------------------------------- */
26564+
26565+typedef void (*au_wkq_func_t)(void *args);
26566+
26567+/* wkq flags */
26568+#define AuWkq_WAIT 1
b752ccd1 26569+#define AuWkq_PRE (1 << 1)
1facf9fc 26570+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
26571+#define au_fset_wkq(flags, name) \
26572+ do { (flags) |= AuWkq_##name; } while (0)
26573+#define au_fclr_wkq(flags, name) \
26574+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 26575+
26576+/* wkq.c */
b752ccd1 26577+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
1facf9fc 26578+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
26579+void au_nwt_init(struct au_nowait_tasks *nwt);
26580+int __init au_wkq_init(void);
26581+void au_wkq_fin(void);
26582+
26583+/* ---------------------------------------------------------------------- */
26584+
b752ccd1
AM
26585+static inline int au_wkq_wait_pre(au_wkq_func_t func, void *args)
26586+{
26587+ return au_wkq_do_wait(AuWkq_WAIT | AuWkq_PRE, func, args);
26588+}
26589+
26590+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 26591+{
b752ccd1 26592+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 26593+}
26594+
26595+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
26596+{
e49829fe 26597+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 26598+ wake_up_all(&nwt->nw_wq);
26599+}
26600+
26601+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
26602+{
26603+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
26604+ return 0;
26605+}
26606+
26607+#endif /* __KERNEL__ */
26608+#endif /* __AUFS_WKQ_H__ */
7f207e10
AM
26609diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
26610--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
26611+++ linux/fs/aufs/xino.c 2010-11-22 11:52:57.003897646 +0100
26612@@ -0,0 +1,1265 @@
1facf9fc 26613+/*
4a4d8108 26614+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26615+ *
26616+ * This program, aufs is free software; you can redistribute it and/or modify
26617+ * it under the terms of the GNU General Public License as published by
26618+ * the Free Software Foundation; either version 2 of the License, or
26619+ * (at your option) any later version.
dece6358
AM
26620+ *
26621+ * This program is distributed in the hope that it will be useful,
26622+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26623+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26624+ * GNU General Public License for more details.
26625+ *
26626+ * You should have received a copy of the GNU General Public License
26627+ * along with this program; if not, write to the Free Software
26628+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26629+ */
26630+
26631+/*
26632+ * external inode number translation table and bitmap
26633+ */
26634+
dece6358 26635+#include <linux/file.h>
1facf9fc 26636+#include <linux/seq_file.h>
26637+#include <linux/uaccess.h>
26638+#include "aufs.h"
26639+
b752ccd1 26640+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 26641+ loff_t *pos)
26642+{
26643+ ssize_t err;
26644+ mm_segment_t oldfs;
b752ccd1
AM
26645+ union {
26646+ void *k;
26647+ char __user *u;
26648+ } buf;
1facf9fc 26649+
b752ccd1 26650+ buf.k = kbuf;
1facf9fc 26651+ oldfs = get_fs();
26652+ set_fs(KERNEL_DS);
26653+ do {
26654+ /* todo: signal_pending? */
b752ccd1 26655+ err = func(file, buf.u, size, pos);
1facf9fc 26656+ } while (err == -EAGAIN || err == -EINTR);
26657+ set_fs(oldfs);
26658+
26659+#if 0 /* reserved for future use */
26660+ if (err > 0)
26661+ fsnotify_access(file->f_dentry);
26662+#endif
26663+
26664+ return err;
26665+}
26666+
26667+/* ---------------------------------------------------------------------- */
26668+
b752ccd1 26669+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 26670+ size_t size, loff_t *pos)
26671+{
26672+ ssize_t err;
26673+ mm_segment_t oldfs;
b752ccd1
AM
26674+ union {
26675+ void *k;
26676+ const char __user *u;
26677+ } buf;
1facf9fc 26678+
b752ccd1 26679+ buf.k = kbuf;
1facf9fc 26680+ oldfs = get_fs();
26681+ set_fs(KERNEL_DS);
1facf9fc 26682+ do {
26683+ /* todo: signal_pending? */
b752ccd1 26684+ err = func(file, buf.u, size, pos);
1facf9fc 26685+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 26686+ set_fs(oldfs);
26687+
26688+#if 0 /* reserved for future use */
26689+ if (err > 0)
26690+ fsnotify_modify(file->f_dentry);
26691+#endif
26692+
26693+ return err;
26694+}
26695+
26696+struct do_xino_fwrite_args {
26697+ ssize_t *errp;
26698+ au_writef_t func;
26699+ struct file *file;
26700+ void *buf;
26701+ size_t size;
26702+ loff_t *pos;
26703+};
26704+
26705+static void call_do_xino_fwrite(void *args)
26706+{
26707+ struct do_xino_fwrite_args *a = args;
26708+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
26709+}
26710+
26711+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
26712+ loff_t *pos)
26713+{
26714+ ssize_t err;
26715+
26716+ /* todo: signal block and no wkq? */
b752ccd1
AM
26717+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
26718+ lockdep_off();
26719+ err = do_xino_fwrite(func, file, buf, size, pos);
26720+ lockdep_on();
26721+ } else {
26722+ /*
26723+ * it breaks RLIMIT_FSIZE and normal user's limit,
26724+ * users should care about quota and real 'filesystem full.'
26725+ */
1facf9fc 26726+ int wkq_err;
26727+ struct do_xino_fwrite_args args = {
26728+ .errp = &err,
26729+ .func = func,
26730+ .file = file,
26731+ .buf = buf,
26732+ .size = size,
26733+ .pos = pos
26734+ };
26735+
26736+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
26737+ if (unlikely(wkq_err))
26738+ err = wkq_err;
b752ccd1 26739+ }
1facf9fc 26740+
26741+ return err;
26742+}
26743+
26744+/* ---------------------------------------------------------------------- */
26745+
26746+/*
26747+ * create a new xinofile at the same place/path as @base_file.
26748+ */
26749+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
26750+{
26751+ struct file *file;
4a4d8108 26752+ struct dentry *base, *parent;
1facf9fc 26753+ struct inode *dir;
26754+ struct qstr *name;
1308ab2a 26755+ struct path path;
4a4d8108 26756+ int err;
1facf9fc 26757+
26758+ base = base_file->f_dentry;
26759+ parent = base->d_parent; /* dir inode is locked */
26760+ dir = parent->d_inode;
26761+ IMustLock(dir);
26762+
26763+ file = ERR_PTR(-EINVAL);
26764+ name = &base->d_name;
4a4d8108
AM
26765+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
26766+ if (IS_ERR(path.dentry)) {
26767+ file = (void *)path.dentry;
26768+ pr_err("%.*s lookup err %ld\n",
26769+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 26770+ goto out;
26771+ }
26772+
26773+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 26774+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 26775+ if (unlikely(err)) {
26776+ file = ERR_PTR(err);
4a4d8108 26777+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 26778+ goto out_dput;
26779+ }
26780+
1308ab2a 26781+ path.mnt = base_file->f_vfsmnt;
4a4d8108 26782+ file = vfsub_dentry_open(&path,
7f207e10
AM
26783+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
26784+ /* | FMODE_NONOTIFY */);
1facf9fc 26785+ if (IS_ERR(file)) {
4a4d8108 26786+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 26787+ goto out_dput;
26788+ }
26789+
26790+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
26791+ if (unlikely(err)) {
4a4d8108 26792+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 26793+ goto out_fput;
26794+ }
26795+
26796+ if (copy_src) {
26797+ /* no one can touch copy_src xino */
26798+ err = au_copy_file(file, copy_src,
26799+ i_size_read(copy_src->f_dentry->d_inode));
26800+ if (unlikely(err)) {
4a4d8108 26801+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 26802+ goto out_fput;
26803+ }
26804+ }
26805+ goto out_dput; /* success */
26806+
4f0767ce 26807+out_fput:
1facf9fc 26808+ fput(file);
26809+ file = ERR_PTR(err);
4f0767ce 26810+out_dput:
4a4d8108 26811+ dput(path.dentry);
4f0767ce 26812+out:
1facf9fc 26813+ return file;
26814+}
26815+
26816+struct au_xino_lock_dir {
26817+ struct au_hinode *hdir;
26818+ struct dentry *parent;
26819+ struct mutex *mtx;
26820+};
26821+
26822+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
26823+ struct au_xino_lock_dir *ldir)
26824+{
26825+ aufs_bindex_t brid, bindex;
26826+
26827+ ldir->hdir = NULL;
26828+ bindex = -1;
26829+ brid = au_xino_brid(sb);
26830+ if (brid >= 0)
26831+ bindex = au_br_index(sb, brid);
26832+ if (bindex >= 0) {
26833+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 26834+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 26835+ } else {
26836+ ldir->parent = dget_parent(xino->f_dentry);
26837+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
26838+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
26839+ }
26840+}
26841+
26842+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
26843+{
26844+ if (ldir->hdir)
4a4d8108 26845+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 26846+ else {
26847+ mutex_unlock(ldir->mtx);
26848+ dput(ldir->parent);
26849+ }
26850+}
26851+
26852+/* ---------------------------------------------------------------------- */
26853+
26854+/* trucate xino files asynchronously */
26855+
26856+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
26857+{
26858+ int err;
26859+ aufs_bindex_t bi, bend;
26860+ struct au_branch *br;
26861+ struct file *new_xino, *file;
26862+ struct super_block *h_sb;
26863+ struct au_xino_lock_dir ldir;
26864+
26865+ err = -EINVAL;
26866+ bend = au_sbend(sb);
26867+ if (unlikely(bindex < 0 || bend < bindex))
26868+ goto out;
26869+ br = au_sbr(sb, bindex);
26870+ file = br->br_xino.xi_file;
26871+ if (!file)
26872+ goto out;
26873+
26874+ au_xino_lock_dir(sb, file, &ldir);
26875+ /* mnt_want_write() is unnecessary here */
26876+ new_xino = au_xino_create2(file, file);
26877+ au_xino_unlock_dir(&ldir);
26878+ err = PTR_ERR(new_xino);
26879+ if (IS_ERR(new_xino))
26880+ goto out;
26881+ err = 0;
26882+ fput(file);
26883+ br->br_xino.xi_file = new_xino;
26884+
26885+ h_sb = br->br_mnt->mnt_sb;
26886+ for (bi = 0; bi <= bend; bi++) {
26887+ if (unlikely(bi == bindex))
26888+ continue;
26889+ br = au_sbr(sb, bi);
26890+ if (br->br_mnt->mnt_sb != h_sb)
26891+ continue;
26892+
26893+ fput(br->br_xino.xi_file);
26894+ br->br_xino.xi_file = new_xino;
26895+ get_file(new_xino);
26896+ }
26897+
4f0767ce 26898+out:
1facf9fc 26899+ return err;
26900+}
26901+
26902+struct xino_do_trunc_args {
26903+ struct super_block *sb;
26904+ struct au_branch *br;
26905+};
26906+
26907+static void xino_do_trunc(void *_args)
26908+{
26909+ struct xino_do_trunc_args *args = _args;
26910+ struct super_block *sb;
26911+ struct au_branch *br;
26912+ struct inode *dir;
26913+ int err;
26914+ aufs_bindex_t bindex;
26915+
26916+ err = 0;
26917+ sb = args->sb;
26918+ dir = sb->s_root->d_inode;
26919+ br = args->br;
26920+
26921+ si_noflush_write_lock(sb);
26922+ ii_read_lock_parent(dir);
26923+ bindex = au_br_index(sb, br->br_id);
26924+ err = au_xino_trunc(sb, bindex);
dece6358
AM
26925+ if (!err
26926+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 26927+ >= br->br_xino_upper)
26928+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
26929+
1facf9fc 26930+ ii_read_unlock(dir);
26931+ if (unlikely(err))
4a4d8108 26932+ pr_warning("err b%d, (%d)\n", bindex, err);
1facf9fc 26933+ atomic_dec(&br->br_xino_running);
26934+ atomic_dec(&br->br_count);
26935+ au_nwt_done(&au_sbi(sb)->si_nowait);
26936+ si_write_unlock(sb);
26937+ kfree(args);
26938+}
26939+
26940+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
26941+{
26942+ struct xino_do_trunc_args *args;
26943+ int wkq_err;
26944+
26945+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
26946+ < br->br_xino_upper)
26947+ return;
26948+
26949+ if (atomic_inc_return(&br->br_xino_running) > 1)
26950+ goto out;
26951+
26952+ /* lock and kfree() will be called in trunc_xino() */
26953+ args = kmalloc(sizeof(*args), GFP_NOFS);
26954+ if (unlikely(!args)) {
26955+ AuErr1("no memory\n");
26956+ goto out_args;
26957+ }
26958+
e49829fe 26959+ atomic_inc(&br->br_count);
1facf9fc 26960+ args->sb = sb;
26961+ args->br = br;
26962+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
26963+ if (!wkq_err)
26964+ return; /* success */
26965+
4a4d8108 26966+ pr_err("wkq %d\n", wkq_err);
e49829fe 26967+ atomic_dec(&br->br_count);
1facf9fc 26968+
4f0767ce 26969+out_args:
1facf9fc 26970+ kfree(args);
4f0767ce 26971+out:
e49829fe 26972+ atomic_dec(&br->br_xino_running);
1facf9fc 26973+}
26974+
26975+/* ---------------------------------------------------------------------- */
26976+
26977+static int au_xino_do_write(au_writef_t write, struct file *file,
26978+ ino_t h_ino, ino_t ino)
26979+{
26980+ loff_t pos;
26981+ ssize_t sz;
26982+
26983+ pos = h_ino;
26984+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
26985+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
26986+ return -EFBIG;
26987+ }
26988+ pos *= sizeof(ino);
26989+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
26990+ if (sz == sizeof(ino))
26991+ return 0; /* success */
26992+
26993+ AuIOErr("write failed (%zd)\n", sz);
26994+ return -EIO;
26995+}
26996+
26997+/*
26998+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
26999+ * at the position of @h_ino.
27000+ * even if @ino is zero, it is written to the xinofile and means no entry.
27001+ * if the size of the xino file on a specific filesystem exceeds the watermark,
27002+ * try truncating it.
27003+ */
27004+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
27005+ ino_t ino)
27006+{
27007+ int err;
27008+ unsigned int mnt_flags;
27009+ struct au_branch *br;
27010+
27011+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
27012+ || ((loff_t)-1) > 0);
dece6358 27013+ SiMustAnyLock(sb);
1facf9fc 27014+
27015+ mnt_flags = au_mntflags(sb);
27016+ if (!au_opt_test(mnt_flags, XINO))
27017+ return 0;
27018+
27019+ br = au_sbr(sb, bindex);
27020+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
27021+ h_ino, ino);
27022+ if (!err) {
27023+ if (au_opt_test(mnt_flags, TRUNC_XINO)
27024+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
27025+ xino_try_trunc(sb, br);
27026+ return 0; /* success */
27027+ }
27028+
27029+ AuIOErr("write failed (%d)\n", err);
27030+ return -EIO;
27031+}
27032+
27033+/* ---------------------------------------------------------------------- */
27034+
27035+/* aufs inode number bitmap */
27036+
27037+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
27038+static ino_t xib_calc_ino(unsigned long pindex, int bit)
27039+{
27040+ ino_t ino;
27041+
27042+ AuDebugOn(bit < 0 || page_bits <= bit);
27043+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
27044+ return ino;
27045+}
27046+
27047+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
27048+{
27049+ AuDebugOn(ino < AUFS_FIRST_INO);
27050+ ino -= AUFS_FIRST_INO;
27051+ *pindex = ino / page_bits;
27052+ *bit = ino % page_bits;
27053+}
27054+
27055+static int xib_pindex(struct super_block *sb, unsigned long pindex)
27056+{
27057+ int err;
27058+ loff_t pos;
27059+ ssize_t sz;
27060+ struct au_sbinfo *sbinfo;
27061+ struct file *xib;
27062+ unsigned long *p;
27063+
27064+ sbinfo = au_sbi(sb);
27065+ MtxMustLock(&sbinfo->si_xib_mtx);
27066+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
27067+ || !au_opt_test(sbinfo->si_mntflags, XINO));
27068+
27069+ if (pindex == sbinfo->si_xib_last_pindex)
27070+ return 0;
27071+
27072+ xib = sbinfo->si_xib;
27073+ p = sbinfo->si_xib_buf;
27074+ pos = sbinfo->si_xib_last_pindex;
27075+ pos *= PAGE_SIZE;
27076+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
27077+ if (unlikely(sz != PAGE_SIZE))
27078+ goto out;
27079+
27080+ pos = pindex;
27081+ pos *= PAGE_SIZE;
27082+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
27083+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
27084+ else {
27085+ memset(p, 0, PAGE_SIZE);
27086+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
27087+ }
27088+ if (sz == PAGE_SIZE) {
27089+ sbinfo->si_xib_last_pindex = pindex;
27090+ return 0; /* success */
27091+ }
27092+
4f0767ce 27093+out:
b752ccd1
AM
27094+ AuIOErr1("write failed (%zd)\n", sz);
27095+ err = sz;
27096+ if (sz >= 0)
27097+ err = -EIO;
27098+ return err;
27099+}
27100+
27101+/* ---------------------------------------------------------------------- */
27102+
27103+static void au_xib_clear_bit(struct inode *inode)
27104+{
27105+ int err, bit;
27106+ unsigned long pindex;
27107+ struct super_block *sb;
27108+ struct au_sbinfo *sbinfo;
27109+
27110+ AuDebugOn(inode->i_nlink);
27111+
27112+ sb = inode->i_sb;
27113+ xib_calc_bit(inode->i_ino, &pindex, &bit);
27114+ AuDebugOn(page_bits <= bit);
27115+ sbinfo = au_sbi(sb);
27116+ mutex_lock(&sbinfo->si_xib_mtx);
27117+ err = xib_pindex(sb, pindex);
27118+ if (!err) {
27119+ clear_bit(bit, sbinfo->si_xib_buf);
27120+ sbinfo->si_xib_next_bit = bit;
27121+ }
27122+ mutex_unlock(&sbinfo->si_xib_mtx);
27123+}
27124+
27125+/* for s_op->delete_inode() */
27126+void au_xino_delete_inode(struct inode *inode, const int unlinked)
27127+{
27128+ int err;
27129+ unsigned int mnt_flags;
27130+ aufs_bindex_t bindex, bend, bi;
27131+ unsigned char try_trunc;
27132+ struct au_iinfo *iinfo;
27133+ struct super_block *sb;
27134+ struct au_hinode *hi;
27135+ struct inode *h_inode;
27136+ struct au_branch *br;
27137+ au_writef_t xwrite;
27138+
27139+ sb = inode->i_sb;
27140+ mnt_flags = au_mntflags(sb);
27141+ if (!au_opt_test(mnt_flags, XINO)
27142+ || inode->i_ino == AUFS_ROOT_INO)
27143+ return;
27144+
27145+ if (unlinked) {
27146+ au_xigen_inc(inode);
27147+ au_xib_clear_bit(inode);
27148+ }
27149+
27150+ iinfo = au_ii(inode);
27151+ if (!iinfo)
27152+ return;
1facf9fc 27153+
b752ccd1
AM
27154+ bindex = iinfo->ii_bstart;
27155+ if (bindex < 0)
27156+ return;
1facf9fc 27157+
b752ccd1
AM
27158+ xwrite = au_sbi(sb)->si_xwrite;
27159+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
27160+ hi = iinfo->ii_hinode + bindex;
27161+ bend = iinfo->ii_bend;
27162+ for (; bindex <= bend; bindex++, hi++) {
27163+ h_inode = hi->hi_inode;
27164+ if (!h_inode
27165+ || (!unlinked && h_inode->i_nlink))
27166+ continue;
1facf9fc 27167+
b752ccd1
AM
27168+ /* inode may not be revalidated */
27169+ bi = au_br_index(sb, hi->hi_id);
27170+ if (bi < 0)
27171+ continue;
1facf9fc 27172+
b752ccd1
AM
27173+ br = au_sbr(sb, bi);
27174+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
27175+ h_inode->i_ino, /*ino*/0);
27176+ if (!err && try_trunc
27177+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
27178+ xino_try_trunc(sb, br);
1facf9fc 27179+ }
1facf9fc 27180+}
27181+
27182+/* get an unused inode number from bitmap */
27183+ino_t au_xino_new_ino(struct super_block *sb)
27184+{
27185+ ino_t ino;
27186+ unsigned long *p, pindex, ul, pend;
27187+ struct au_sbinfo *sbinfo;
27188+ struct file *file;
27189+ int free_bit, err;
27190+
27191+ if (!au_opt_test(au_mntflags(sb), XINO))
27192+ return iunique(sb, AUFS_FIRST_INO);
27193+
27194+ sbinfo = au_sbi(sb);
27195+ mutex_lock(&sbinfo->si_xib_mtx);
27196+ p = sbinfo->si_xib_buf;
27197+ free_bit = sbinfo->si_xib_next_bit;
27198+ if (free_bit < page_bits && !test_bit(free_bit, p))
27199+ goto out; /* success */
27200+ free_bit = find_first_zero_bit(p, page_bits);
27201+ if (free_bit < page_bits)
27202+ goto out; /* success */
27203+
27204+ pindex = sbinfo->si_xib_last_pindex;
27205+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
27206+ err = xib_pindex(sb, ul);
27207+ if (unlikely(err))
27208+ goto out_err;
27209+ free_bit = find_first_zero_bit(p, page_bits);
27210+ if (free_bit < page_bits)
27211+ goto out; /* success */
27212+ }
27213+
27214+ file = sbinfo->si_xib;
27215+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
27216+ for (ul = pindex + 1; ul <= pend; ul++) {
27217+ err = xib_pindex(sb, ul);
27218+ if (unlikely(err))
27219+ goto out_err;
27220+ free_bit = find_first_zero_bit(p, page_bits);
27221+ if (free_bit < page_bits)
27222+ goto out; /* success */
27223+ }
27224+ BUG();
27225+
4f0767ce 27226+out:
1facf9fc 27227+ set_bit(free_bit, p);
7f207e10 27228+ sbinfo->si_xib_next_bit = free_bit + 1;
1facf9fc 27229+ pindex = sbinfo->si_xib_last_pindex;
27230+ mutex_unlock(&sbinfo->si_xib_mtx);
27231+ ino = xib_calc_ino(pindex, free_bit);
27232+ AuDbg("i%lu\n", (unsigned long)ino);
27233+ return ino;
4f0767ce 27234+out_err:
1facf9fc 27235+ mutex_unlock(&sbinfo->si_xib_mtx);
27236+ AuDbg("i0\n");
27237+ return 0;
27238+}
27239+
27240+/*
27241+ * read @ino from xinofile for the specified branch{@sb, @bindex}
27242+ * at the position of @h_ino.
27243+ * if @ino does not exist and @do_new is true, get new one.
27244+ */
27245+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
27246+ ino_t *ino)
27247+{
27248+ int err;
27249+ ssize_t sz;
27250+ loff_t pos;
27251+ struct file *file;
27252+ struct au_sbinfo *sbinfo;
27253+
27254+ *ino = 0;
27255+ if (!au_opt_test(au_mntflags(sb), XINO))
27256+ return 0; /* no xino */
27257+
27258+ err = 0;
27259+ sbinfo = au_sbi(sb);
27260+ pos = h_ino;
27261+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
27262+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
27263+ return -EFBIG;
27264+ }
27265+ pos *= sizeof(*ino);
27266+
27267+ file = au_sbr(sb, bindex)->br_xino.xi_file;
27268+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
27269+ return 0; /* no ino */
27270+
27271+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
27272+ if (sz == sizeof(*ino))
27273+ return 0; /* success */
27274+
27275+ err = sz;
27276+ if (unlikely(sz >= 0)) {
27277+ err = -EIO;
27278+ AuIOErr("xino read error (%zd)\n", sz);
27279+ }
27280+
27281+ return err;
27282+}
27283+
27284+/* ---------------------------------------------------------------------- */
27285+
27286+/* create and set a new xino file */
27287+
27288+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
27289+{
27290+ struct file *file;
27291+ struct dentry *h_parent, *d;
27292+ struct inode *h_dir;
27293+ int err;
27294+
27295+ /*
27296+ * at mount-time, and the xino file is the default path,
4a4d8108 27297+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 27298+ * when a user specified the xino, we cannot get au_hdir to be ignored.
27299+ */
7f207e10
AM
27300+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
27301+ /* | FMODE_NONOTIFY */,
1facf9fc 27302+ S_IRUGO | S_IWUGO);
27303+ if (IS_ERR(file)) {
27304+ if (!silent)
4a4d8108 27305+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 27306+ return file;
27307+ }
27308+
27309+ /* keep file count */
27310+ h_parent = dget_parent(file->f_dentry);
27311+ h_dir = h_parent->d_inode;
27312+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
27313+ /* mnt_want_write() is unnecessary here */
27314+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
27315+ mutex_unlock(&h_dir->i_mutex);
27316+ dput(h_parent);
27317+ if (unlikely(err)) {
27318+ if (!silent)
4a4d8108 27319+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 27320+ goto out;
27321+ }
27322+
27323+ err = -EINVAL;
27324+ d = file->f_dentry;
27325+ if (unlikely(sb == d->d_sb)) {
27326+ if (!silent)
4a4d8108 27327+ pr_err("%s must be outside\n", fname);
1facf9fc 27328+ goto out;
27329+ }
27330+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
27331+ if (!silent)
4a4d8108
AM
27332+ pr_err("xino doesn't support %s(%s)\n",
27333+ fname, au_sbtype(d->d_sb));
1facf9fc 27334+ goto out;
27335+ }
27336+ return file; /* success */
27337+
4f0767ce 27338+out:
1facf9fc 27339+ fput(file);
27340+ file = ERR_PTR(err);
27341+ return file;
27342+}
27343+
27344+/*
27345+ * find another branch who is on the same filesystem of the specified
27346+ * branch{@btgt}. search until @bend.
27347+ */
27348+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
27349+ aufs_bindex_t bend)
27350+{
27351+ aufs_bindex_t bindex;
27352+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
27353+
27354+ for (bindex = 0; bindex < btgt; bindex++)
27355+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
27356+ return bindex;
27357+ for (bindex++; bindex <= bend; bindex++)
27358+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
27359+ return bindex;
27360+ return -1;
27361+}
27362+
27363+/* ---------------------------------------------------------------------- */
27364+
27365+/*
27366+ * initialize the xinofile for the specified branch @br
27367+ * at the place/path where @base_file indicates.
27368+ * test whether another branch is on the same filesystem or not,
27369+ * if @do_test is true.
27370+ */
27371+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
27372+ struct file *base_file, int do_test)
27373+{
27374+ int err;
27375+ ino_t ino;
27376+ aufs_bindex_t bend, bindex;
27377+ struct au_branch *shared_br, *b;
27378+ struct file *file;
27379+ struct super_block *tgt_sb;
27380+
27381+ shared_br = NULL;
27382+ bend = au_sbend(sb);
27383+ if (do_test) {
27384+ tgt_sb = br->br_mnt->mnt_sb;
27385+ for (bindex = 0; bindex <= bend; bindex++) {
27386+ b = au_sbr(sb, bindex);
27387+ if (tgt_sb == b->br_mnt->mnt_sb) {
27388+ shared_br = b;
27389+ break;
27390+ }
27391+ }
27392+ }
27393+
27394+ if (!shared_br || !shared_br->br_xino.xi_file) {
27395+ struct au_xino_lock_dir ldir;
27396+
27397+ au_xino_lock_dir(sb, base_file, &ldir);
27398+ /* mnt_want_write() is unnecessary here */
27399+ file = au_xino_create2(base_file, NULL);
27400+ au_xino_unlock_dir(&ldir);
27401+ err = PTR_ERR(file);
27402+ if (IS_ERR(file))
27403+ goto out;
27404+ br->br_xino.xi_file = file;
27405+ } else {
27406+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
27407+ get_file(br->br_xino.xi_file);
27408+ }
27409+
27410+ ino = AUFS_ROOT_INO;
27411+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
27412+ h_ino, ino);
b752ccd1
AM
27413+ if (unlikely(err)) {
27414+ fput(br->br_xino.xi_file);
27415+ br->br_xino.xi_file = NULL;
27416+ }
1facf9fc 27417+
4f0767ce 27418+out:
1facf9fc 27419+ return err;
27420+}
27421+
27422+/* ---------------------------------------------------------------------- */
27423+
27424+/* trucate a xino bitmap file */
27425+
27426+/* todo: slow */
27427+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
27428+{
27429+ int err, bit;
27430+ ssize_t sz;
27431+ unsigned long pindex;
27432+ loff_t pos, pend;
27433+ struct au_sbinfo *sbinfo;
27434+ au_readf_t func;
27435+ ino_t *ino;
27436+ unsigned long *p;
27437+
27438+ err = 0;
27439+ sbinfo = au_sbi(sb);
dece6358 27440+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 27441+ p = sbinfo->si_xib_buf;
27442+ func = sbinfo->si_xread;
27443+ pend = i_size_read(file->f_dentry->d_inode);
27444+ pos = 0;
27445+ while (pos < pend) {
27446+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
27447+ err = sz;
27448+ if (unlikely(sz <= 0))
27449+ goto out;
27450+
27451+ err = 0;
27452+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
27453+ if (unlikely(*ino < AUFS_FIRST_INO))
27454+ continue;
27455+
27456+ xib_calc_bit(*ino, &pindex, &bit);
27457+ AuDebugOn(page_bits <= bit);
27458+ err = xib_pindex(sb, pindex);
27459+ if (!err)
27460+ set_bit(bit, p);
27461+ else
27462+ goto out;
27463+ }
27464+ }
27465+
4f0767ce 27466+out:
1facf9fc 27467+ return err;
27468+}
27469+
27470+static int xib_restore(struct super_block *sb)
27471+{
27472+ int err;
27473+ aufs_bindex_t bindex, bend;
27474+ void *page;
27475+
27476+ err = -ENOMEM;
27477+ page = (void *)__get_free_page(GFP_NOFS);
27478+ if (unlikely(!page))
27479+ goto out;
27480+
27481+ err = 0;
27482+ bend = au_sbend(sb);
27483+ for (bindex = 0; !err && bindex <= bend; bindex++)
27484+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
27485+ err = do_xib_restore
27486+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
27487+ else
27488+ AuDbg("b%d\n", bindex);
27489+ free_page((unsigned long)page);
27490+
4f0767ce 27491+out:
1facf9fc 27492+ return err;
27493+}
27494+
27495+int au_xib_trunc(struct super_block *sb)
27496+{
27497+ int err;
27498+ ssize_t sz;
27499+ loff_t pos;
27500+ struct au_xino_lock_dir ldir;
27501+ struct au_sbinfo *sbinfo;
27502+ unsigned long *p;
27503+ struct file *file;
27504+
dece6358
AM
27505+ SiMustWriteLock(sb);
27506+
1facf9fc 27507+ err = 0;
27508+ sbinfo = au_sbi(sb);
27509+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
27510+ goto out;
27511+
27512+ file = sbinfo->si_xib;
27513+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
27514+ goto out;
27515+
27516+ au_xino_lock_dir(sb, file, &ldir);
27517+ /* mnt_want_write() is unnecessary here */
27518+ file = au_xino_create2(sbinfo->si_xib, NULL);
27519+ au_xino_unlock_dir(&ldir);
27520+ err = PTR_ERR(file);
27521+ if (IS_ERR(file))
27522+ goto out;
27523+ fput(sbinfo->si_xib);
27524+ sbinfo->si_xib = file;
27525+
27526+ p = sbinfo->si_xib_buf;
27527+ memset(p, 0, PAGE_SIZE);
27528+ pos = 0;
27529+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
27530+ if (unlikely(sz != PAGE_SIZE)) {
27531+ err = sz;
27532+ AuIOErr("err %d\n", err);
27533+ if (sz >= 0)
27534+ err = -EIO;
27535+ goto out;
27536+ }
27537+
27538+ mutex_lock(&sbinfo->si_xib_mtx);
27539+ /* mnt_want_write() is unnecessary here */
27540+ err = xib_restore(sb);
27541+ mutex_unlock(&sbinfo->si_xib_mtx);
27542+
27543+out:
27544+ return err;
27545+}
27546+
27547+/* ---------------------------------------------------------------------- */
27548+
27549+/*
27550+ * xino mount option handlers
27551+ */
27552+static au_readf_t find_readf(struct file *h_file)
27553+{
27554+ const struct file_operations *fop = h_file->f_op;
27555+
27556+ if (fop) {
27557+ if (fop->read)
27558+ return fop->read;
27559+ if (fop->aio_read)
27560+ return do_sync_read;
27561+ }
27562+ return ERR_PTR(-ENOSYS);
27563+}
27564+
27565+static au_writef_t find_writef(struct file *h_file)
27566+{
27567+ const struct file_operations *fop = h_file->f_op;
27568+
27569+ if (fop) {
27570+ if (fop->write)
27571+ return fop->write;
27572+ if (fop->aio_write)
27573+ return do_sync_write;
27574+ }
27575+ return ERR_PTR(-ENOSYS);
27576+}
27577+
27578+/* xino bitmap */
27579+static void xino_clear_xib(struct super_block *sb)
27580+{
27581+ struct au_sbinfo *sbinfo;
27582+
dece6358
AM
27583+ SiMustWriteLock(sb);
27584+
1facf9fc 27585+ sbinfo = au_sbi(sb);
27586+ sbinfo->si_xread = NULL;
27587+ sbinfo->si_xwrite = NULL;
27588+ if (sbinfo->si_xib)
27589+ fput(sbinfo->si_xib);
27590+ sbinfo->si_xib = NULL;
27591+ free_page((unsigned long)sbinfo->si_xib_buf);
27592+ sbinfo->si_xib_buf = NULL;
27593+}
27594+
27595+static int au_xino_set_xib(struct super_block *sb, struct file *base)
27596+{
27597+ int err;
27598+ loff_t pos;
27599+ struct au_sbinfo *sbinfo;
27600+ struct file *file;
27601+
dece6358
AM
27602+ SiMustWriteLock(sb);
27603+
1facf9fc 27604+ sbinfo = au_sbi(sb);
27605+ file = au_xino_create2(base, sbinfo->si_xib);
27606+ err = PTR_ERR(file);
27607+ if (IS_ERR(file))
27608+ goto out;
27609+ if (sbinfo->si_xib)
27610+ fput(sbinfo->si_xib);
27611+ sbinfo->si_xib = file;
27612+ sbinfo->si_xread = find_readf(file);
27613+ sbinfo->si_xwrite = find_writef(file);
27614+
27615+ err = -ENOMEM;
27616+ if (!sbinfo->si_xib_buf)
27617+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
27618+ if (unlikely(!sbinfo->si_xib_buf))
27619+ goto out_unset;
27620+
27621+ sbinfo->si_xib_last_pindex = 0;
27622+ sbinfo->si_xib_next_bit = 0;
27623+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
27624+ pos = 0;
27625+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
27626+ PAGE_SIZE, &pos);
27627+ if (unlikely(err != PAGE_SIZE))
27628+ goto out_free;
27629+ }
27630+ err = 0;
27631+ goto out; /* success */
27632+
4f0767ce 27633+out_free:
1facf9fc 27634+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
27635+ sbinfo->si_xib_buf = NULL;
27636+ if (err >= 0)
27637+ err = -EIO;
4f0767ce 27638+out_unset:
b752ccd1
AM
27639+ fput(sbinfo->si_xib);
27640+ sbinfo->si_xib = NULL;
27641+ sbinfo->si_xread = NULL;
27642+ sbinfo->si_xwrite = NULL;
4f0767ce 27643+out:
b752ccd1 27644+ return err;
1facf9fc 27645+}
27646+
b752ccd1
AM
27647+/* xino for each branch */
27648+static void xino_clear_br(struct super_block *sb)
27649+{
27650+ aufs_bindex_t bindex, bend;
27651+ struct au_branch *br;
1facf9fc 27652+
b752ccd1
AM
27653+ bend = au_sbend(sb);
27654+ for (bindex = 0; bindex <= bend; bindex++) {
27655+ br = au_sbr(sb, bindex);
27656+ if (!br || !br->br_xino.xi_file)
27657+ continue;
27658+
27659+ fput(br->br_xino.xi_file);
27660+ br->br_xino.xi_file = NULL;
27661+ }
27662+}
27663+
27664+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 27665+{
27666+ int err;
b752ccd1
AM
27667+ ino_t ino;
27668+ aufs_bindex_t bindex, bend, bshared;
27669+ struct {
27670+ struct file *old, *new;
27671+ } *fpair, *p;
27672+ struct au_branch *br;
27673+ struct inode *inode;
27674+ au_writef_t writef;
1facf9fc 27675+
b752ccd1
AM
27676+ SiMustWriteLock(sb);
27677+
27678+ err = -ENOMEM;
27679+ bend = au_sbend(sb);
27680+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
27681+ if (unlikely(!fpair))
1facf9fc 27682+ goto out;
27683+
b752ccd1
AM
27684+ inode = sb->s_root->d_inode;
27685+ ino = AUFS_ROOT_INO;
27686+ writef = au_sbi(sb)->si_xwrite;
27687+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
27688+ br = au_sbr(sb, bindex);
27689+ bshared = is_sb_shared(sb, bindex, bindex - 1);
27690+ if (bshared >= 0) {
27691+ /* shared xino */
27692+ *p = fpair[bshared];
27693+ get_file(p->new);
27694+ }
27695+
27696+ if (!p->new) {
27697+ /* new xino */
27698+ p->old = br->br_xino.xi_file;
27699+ p->new = au_xino_create2(base, br->br_xino.xi_file);
27700+ err = PTR_ERR(p->new);
27701+ if (IS_ERR(p->new)) {
27702+ p->new = NULL;
27703+ goto out_pair;
27704+ }
27705+ }
27706+
27707+ err = au_xino_do_write(writef, p->new,
27708+ au_h_iptr(inode, bindex)->i_ino, ino);
27709+ if (unlikely(err))
27710+ goto out_pair;
27711+ }
27712+
27713+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
27714+ br = au_sbr(sb, bindex);
27715+ if (br->br_xino.xi_file)
27716+ fput(br->br_xino.xi_file);
27717+ get_file(p->new);
27718+ br->br_xino.xi_file = p->new;
27719+ }
1facf9fc 27720+
4f0767ce 27721+out_pair:
b752ccd1
AM
27722+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
27723+ if (p->new)
27724+ fput(p->new);
27725+ else
27726+ break;
27727+ kfree(fpair);
4f0767ce 27728+out:
1facf9fc 27729+ return err;
27730+}
b752ccd1
AM
27731+
27732+void au_xino_clr(struct super_block *sb)
27733+{
27734+ struct au_sbinfo *sbinfo;
27735+
27736+ au_xigen_clr(sb);
27737+ xino_clear_xib(sb);
27738+ xino_clear_br(sb);
27739+ sbinfo = au_sbi(sb);
27740+ /* lvalue, do not call au_mntflags() */
27741+ au_opt_clr(sbinfo->si_mntflags, XINO);
27742+}
27743+
27744+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
27745+{
27746+ int err, skip;
27747+ struct dentry *parent, *cur_parent;
27748+ struct qstr *dname, *cur_name;
27749+ struct file *cur_xino;
27750+ struct inode *dir;
27751+ struct au_sbinfo *sbinfo;
27752+
27753+ SiMustWriteLock(sb);
27754+
27755+ err = 0;
27756+ sbinfo = au_sbi(sb);
27757+ parent = dget_parent(xino->file->f_dentry);
27758+ if (remount) {
27759+ skip = 0;
27760+ dname = &xino->file->f_dentry->d_name;
27761+ cur_xino = sbinfo->si_xib;
27762+ if (cur_xino) {
27763+ cur_parent = dget_parent(cur_xino->f_dentry);
27764+ cur_name = &cur_xino->f_dentry->d_name;
27765+ skip = (cur_parent == parent
27766+ && dname->len == cur_name->len
27767+ && !memcmp(dname->name, cur_name->name,
27768+ dname->len));
27769+ dput(cur_parent);
27770+ }
27771+ if (skip)
27772+ goto out;
27773+ }
27774+
27775+ au_opt_set(sbinfo->si_mntflags, XINO);
27776+ dir = parent->d_inode;
27777+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
27778+ /* mnt_want_write() is unnecessary here */
27779+ err = au_xino_set_xib(sb, xino->file);
27780+ if (!err)
27781+ err = au_xigen_set(sb, xino->file);
27782+ if (!err)
27783+ err = au_xino_set_br(sb, xino->file);
27784+ mutex_unlock(&dir->i_mutex);
27785+ if (!err)
27786+ goto out; /* success */
27787+
27788+ /* reset all */
27789+ AuIOErr("failed creating xino(%d).\n", err);
27790+
4f0767ce 27791+out:
b752ccd1
AM
27792+ dput(parent);
27793+ return err;
27794+}
27795+
27796+/* ---------------------------------------------------------------------- */
27797+
27798+/*
27799+ * create a xinofile at the default place/path.
27800+ */
27801+struct file *au_xino_def(struct super_block *sb)
27802+{
27803+ struct file *file;
27804+ char *page, *p;
27805+ struct au_branch *br;
27806+ struct super_block *h_sb;
27807+ struct path path;
27808+ aufs_bindex_t bend, bindex, bwr;
27809+
27810+ br = NULL;
27811+ bend = au_sbend(sb);
27812+ bwr = -1;
27813+ for (bindex = 0; bindex <= bend; bindex++) {
27814+ br = au_sbr(sb, bindex);
27815+ if (au_br_writable(br->br_perm)
27816+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
27817+ bwr = bindex;
27818+ break;
27819+ }
27820+ }
27821+
7f207e10
AM
27822+ if (bwr >= 0) {
27823+ file = ERR_PTR(-ENOMEM);
27824+ page = __getname_gfp(GFP_NOFS);
27825+ if (unlikely(!page))
27826+ goto out;
27827+ path.mnt = br->br_mnt;
27828+ path.dentry = au_h_dptr(sb->s_root, bwr);
27829+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
27830+ file = (void *)p;
27831+ if (!IS_ERR(p)) {
27832+ strcat(p, "/" AUFS_XINO_FNAME);
27833+ AuDbg("%s\n", p);
27834+ file = au_xino_create(sb, p, /*silent*/0);
27835+ if (!IS_ERR(file))
27836+ au_xino_brid_set(sb, br->br_id);
27837+ }
27838+ __putname(page);
27839+ } else {
27840+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
27841+ if (IS_ERR(file))
27842+ goto out;
27843+ h_sb = file->f_dentry->d_sb;
27844+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
27845+ pr_err("xino doesn't support %s(%s)\n",
27846+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
27847+ fput(file);
27848+ file = ERR_PTR(-EINVAL);
27849+ }
27850+ if (!IS_ERR(file))
27851+ au_xino_brid_set(sb, -1);
27852+ }
0c5527e5 27853+
7f207e10
AM
27854+out:
27855+ return file;
27856+}
27857+
27858+/* ---------------------------------------------------------------------- */
27859+
27860+int au_xino_path(struct seq_file *seq, struct file *file)
27861+{
27862+ int err;
27863+
27864+ err = au_seq_path(seq, &file->f_path);
27865+ if (unlikely(err < 0))
27866+ goto out;
27867+
27868+ err = 0;
27869+#define Deleted "\\040(deleted)"
27870+ seq->count -= sizeof(Deleted) - 1;
27871+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
27872+ sizeof(Deleted) - 1));
27873+#undef Deleted
27874+
27875+out:
27876+ return err;
27877+}
27878diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
27879--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
27880+++ linux/include/linux/aufs_type.h 2010-11-22 11:52:57.003897646 +0100
27881@@ -0,0 +1,195 @@
27882+/*
27883+ * Copyright (C) 2005-2010 Junjiro R. Okajima
27884+ *
27885+ * This program, aufs is free software; you can redistribute it and/or modify
27886+ * it under the terms of the GNU General Public License as published by
27887+ * the Free Software Foundation; either version 2 of the License, or
27888+ * (at your option) any later version.
27889+ *
27890+ * This program is distributed in the hope that it will be useful,
27891+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27892+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27893+ * GNU General Public License for more details.
27894+ *
27895+ * You should have received a copy of the GNU General Public License
27896+ * along with this program; if not, write to the Free Software
27897+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27898+ */
27899+
27900+#ifndef __AUFS_TYPE_H__
27901+#define __AUFS_TYPE_H__
27902+
27903+#include <linux/ioctl.h>
27904+#include <linux/kernel.h>
27905+#include <linux/limits.h>
27906+#include <linux/types.h>
27907+
27908+#define AUFS_VERSION "2.1-standalone.tree-36-20101122"
27909+
27910+/* todo? move this to linux-2.6.19/include/magic.h */
27911+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
27912+
27913+/* ---------------------------------------------------------------------- */
27914+
27915+#ifdef CONFIG_AUFS_BRANCH_MAX_127
27916+typedef __s8 aufs_bindex_t;
27917+#define AUFS_BRANCH_MAX 127
27918+#else
27919+typedef __s16 aufs_bindex_t;
27920+#ifdef CONFIG_AUFS_BRANCH_MAX_511
27921+#define AUFS_BRANCH_MAX 511
27922+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
27923+#define AUFS_BRANCH_MAX 1023
27924+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
27925+#define AUFS_BRANCH_MAX 32767
27926+#endif
27927+#endif
27928+
27929+#ifdef __KERNEL__
27930+#ifndef AUFS_BRANCH_MAX
27931+#error unknown CONFIG_AUFS_BRANCH_MAX value
27932+#endif
27933+#endif /* __KERNEL__ */
27934+
27935+/* ---------------------------------------------------------------------- */
27936+
27937+#define AUFS_NAME "aufs"
27938+#define AUFS_FSTYPE AUFS_NAME
27939+
27940+#define AUFS_ROOT_INO 2
27941+#define AUFS_FIRST_INO 11
27942+
27943+#define AUFS_WH_PFX ".wh."
27944+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
27945+#define AUFS_WH_TMP_LEN 4
27946+/* a limit for rmdir/rename a dir */
27947+#define AUFS_MAX_NAMELEN (NAME_MAX \
27948+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
27949+ - 1 /* dot */\
27950+ - AUFS_WH_TMP_LEN) /* hex */
27951+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
27952+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
27953+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
27954+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
27955+#define AUFS_DIRWH_DEF 3
27956+#define AUFS_RDCACHE_DEF 10 /* seconds */
27957+#define AUFS_RDBLK_DEF 512 /* bytes */
27958+#define AUFS_RDHASH_DEF 32
27959+#define AUFS_WKQ_NAME AUFS_NAME "d"
27960+#define AUFS_WKQ_PRE_NAME AUFS_WKQ_NAME "_pre"
27961+#define AUFS_MFS_SECOND_DEF 30 /* seconds */
27962+#define AUFS_PLINK_WARN 100 /* number of plinks */
27963+
27964+/* pseudo-link maintenace under /proc */
27965+#define AUFS_PLINK_MAINT_NAME "plink_maint"
27966+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
27967+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
27968+
27969+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
27970+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
27971+
27972+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
27973+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
27974+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
27975+
27976+/* doubly whiteouted */
27977+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
27978+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
27979+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
27980+
27981+/* branch permission */
27982+#define AUFS_BRPERM_RW "rw"
27983+#define AUFS_BRPERM_RO "ro"
27984+#define AUFS_BRPERM_RR "rr"
27985+#define AUFS_BRPERM_WH "wh"
27986+#define AUFS_BRPERM_NLWH "nolwh"
27987+#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
27988+#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
27989+#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
27990+
27991+/* ---------------------------------------------------------------------- */
27992+
27993+/* ioctl */
27994+enum {
27995+ /* readdir in userspace */
27996+ AuCtl_RDU,
27997+ AuCtl_RDU_INO,
27998+
27999+ /* pathconf wrapper */
28000+ AuCtl_WBR_FD
28001+};
28002+
28003+/* borrowed from linux/include/linux/kernel.h */
28004+#ifndef ALIGN
28005+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
28006+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
28007+#endif
28008+
28009+/* borrowed from linux/include/linux/compiler-gcc3.h */
28010+#ifndef __aligned
28011+#define __aligned(x) __attribute__((aligned(x)))
28012+#define __packed __attribute__((packed))
28013+#endif
28014+
28015+struct au_rdu_cookie {
28016+ __u64 h_pos;
28017+ __s16 bindex;
28018+ __u8 flags;
28019+ __u8 pad;
28020+ __u32 generation;
28021+} __aligned(8);
28022+
28023+struct au_rdu_ent {
28024+ __u64 ino;
28025+ __s16 bindex;
28026+ __u8 type;
28027+ __u8 nlen;
28028+ __u8 wh;
28029+ char name[0];
28030+} __aligned(8);
28031+
28032+static inline int au_rdu_len(int nlen)
28033+{
28034+ /* include the terminating NULL */
28035+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
28036+ sizeof(__u64));
28037+}
28038+
28039+union au_rdu_ent_ul {
28040+ struct au_rdu_ent __user *e;
28041+ __u64 ul;
28042+};
28043+
28044+enum {
28045+ AufsCtlRduV_SZ,
28046+ AufsCtlRduV_End
28047+};
28048+
28049+struct aufs_rdu {
28050+ /* input */
28051+ union {
28052+ __u64 sz; /* AuCtl_RDU */
28053+ __u64 nent; /* AuCtl_RDU_INO */
28054+ };
28055+ union au_rdu_ent_ul ent;
28056+ __u16 verify[AufsCtlRduV_End];
28057+
28058+ /* input/output */
28059+ __u32 blk;
28060+
28061+ /* output */
28062+ union au_rdu_ent_ul tail;
28063+ /* number of entries which were added in a single call */
28064+ __u64 rent;
28065+ __u8 full;
28066+ __u8 shwh;
28067+
28068+ struct au_rdu_cookie cookie;
28069+} __aligned(8);
28070+
28071+#define AuCtlType 'A'
28072+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
28073+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
28074+#define AUFS_CTL_WBR_FD _IO(AuCtlType, AuCtl_WBR_FD)
28075+
28076+#endif /* __AUFS_TYPE_H__ */
28077
96b982d4
AM
28078diff --git linux/fs/aufs/f_op.c linux/fs/aufs/f_op.c
28079index ff918db..67f2a5b 100644
28080--- linux/fs/aufs/f_op.c
28081+++ linux/fs/aufs/f_op.c
28082@@ -871,6 +871,7 @@ const struct file_operations aufs_file_fop = {
28083 * in aufs, it may be a real file and may confuse users by UDBA.
28084 */
28085 /* .llseek = generic_file_llseek, */
28086+ .llseek = default_llseek,
28087
28088 .read = aufs_read,
28089 .write = aufs_write,
This page took 4.616727 seconds and 4 git commands to generate.