]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs2.patch
- move vserver configs to kernel-vserver.config; update config
[packages/kernel.git] / kernel-aufs2.patch
CommitLineData
953406b4 1aufs2 kbuild patch for linux-2.6.
b752ccd1
AM
2
3diff --git a/fs/Kconfig b/fs/Kconfig
953406b4 4index 3d18530..8f582e1 100644
b752ccd1
AM
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
953406b4 25index 626b629..a841231 100644
b752ccd1
AM
26--- a/include/linux/Kbuild
27+++ b/include/linux/Kbuild
953406b4 28@@ -60,6 +60,7 @@ header-y += atmppp.h
b752ccd1
AM
29 header-y += atmsap.h
30 header-y += atmsvc.h
953406b4 31 header-y += audit.h
b752ccd1 32+header-y += aufs_type.h
953406b4 33 header-y += auto_fs.h
b752ccd1 34 header-y += auto_fs4.h
953406b4
AM
35 header-y += auxvec.h
36aufs2 base patch for linux-2.6.
b752ccd1
AM
37
38diff --git a/fs/namei.c b/fs/namei.c
953406b4 39index 17ea76b..56e8ece 100644
b752ccd1
AM
40--- a/fs/namei.c
41+++ b/fs/namei.c
953406b4 42@@ -1168,7 +1168,7 @@ out:
b752ccd1
AM
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
953406b4 51@@ -1178,7 +1178,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
b752ccd1
AM
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
953406b4 61index 8f1dfae..278c94f 100644
b752ccd1
AM
62--- a/fs/splice.c
63+++ b/fs/splice.c
953406b4 64@@ -1092,8 +1092,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
b752ccd1
AM
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);
953406b4 75@@ -1120,9 +1120,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
b752ccd1
AM
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);
115+
116 #endif
953406b4 117aufs2 standalone patch for linux-2.6.
b752ccd1
AM
118
119diff --git a/fs/namei.c b/fs/namei.c
953406b4 120index 56e8ece..ba75f28 100644
b752ccd1
AM
121--- a/fs/namei.c
122+++ b/fs/namei.c
953406b4 123@@ -347,6 +347,7 @@ int deny_write_access(struct file * file)
b752ccd1
AM
124
125 return 0;
126 }
127+EXPORT_SYMBOL(deny_write_access);
128
129 /**
130 * path_get - get a reference to a path
953406b4 131@@ -1177,6 +1178,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
b752ccd1
AM
132 return ERR_PTR(err);
133 return __lookup_hash(&nd->last, nd->path.dentry, nd);
134 }
135+EXPORT_SYMBOL(lookup_hash);
136
137 int __lookup_one_len(const char *name, struct qstr *this,
138 struct dentry *base, int len)
953406b4 139@@ -1199,6 +1201,7 @@ int __lookup_one_len(const char *name, struct qstr *this,
b752ccd1
AM
140 this->hash = end_name_hash(hash);
141 return 0;
142 }
143+EXPORT_SYMBOL(__lookup_one_len);
144
145 /**
146 * lookup_one_len - filesystem helper to lookup single pathname component
147diff --git a/fs/namespace.c b/fs/namespace.c
953406b4 148index 2e10cb1..8fa77c4 100644
b752ccd1
AM
149--- a/fs/namespace.c
150+++ b/fs/namespace.c
953406b4 151@@ -1283,6 +1283,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
b752ccd1
AM
152 }
153 return 0;
154 }
155+EXPORT_SYMBOL(iterate_mounts);
156
157 static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
158 {
159diff --git a/fs/notify/group.c b/fs/notify/group.c
953406b4 160index d309f38..f0e9568 100644
b752ccd1
AM
161--- a/fs/notify/group.c
162+++ b/fs/notify/group.c
163@@ -22,6 +22,7 @@
164 #include <linux/srcu.h>
165 #include <linux/rculist.h>
166 #include <linux/wait.h>
167+#include <linux/module.h>
168
169 #include <linux/fsnotify_backend.h>
170 #include "fsnotify.h"
953406b4
AM
171@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
172 if (atomic_dec_and_test(&group->refcnt))
173 fsnotify_destroy_group(group);
b752ccd1
AM
174 }
175+EXPORT_SYMBOL(fsnotify_put_group);
176
177 /*
953406b4
AM
178 * Create a new fsnotify_group and hold a reference for the group returned.
179@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
b752ccd1
AM
180
181 return group;
182 }
953406b4
AM
183+EXPORT_SYMBOL(fsnotify_alloc_group);
184diff --git a/fs/notify/mark.c b/fs/notify/mark.c
185index 325185e..adede09 100644
186--- a/fs/notify/mark.c
187+++ b/fs/notify/mark.c
188@@ -113,6 +113,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
189 if (atomic_dec_and_test(&mark->refcnt))
190 mark->free_mark(mark);
b752ccd1
AM
191 }
192+EXPORT_SYMBOL(fsnotify_put_mark);
193
194 /*
953406b4
AM
195 * Any time a mark is getting freed we end up here.
196@@ -190,6 +191,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
b752ccd1
AM
197 if (unlikely(atomic_dec_and_test(&group->num_marks)))
198 fsnotify_final_destroy_group(group);
199 }
953406b4 200+EXPORT_SYMBOL(fsnotify_destroy_mark);
b752ccd1 201
953406b4
AM
202 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
203 {
204@@ -277,6 +279,7 @@ err:
b752ccd1 205
953406b4 206 return ret;
b752ccd1 207 }
953406b4 208+EXPORT_SYMBOL(fsnotify_add_mark);
b752ccd1
AM
209
210 /*
953406b4
AM
211 * clear any marks in a group in which mark->flags & flags is true
212@@ -332,6 +335,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
213 atomic_set(&mark->refcnt, 1);
214 mark->free_mark = free_mark;
b752ccd1 215 }
953406b4 216+EXPORT_SYMBOL(fsnotify_init_mark);
b752ccd1 217
953406b4
AM
218 static int fsnotify_mark_destroy(void *ignored)
219 {
b752ccd1 220diff --git a/fs/open.c b/fs/open.c
953406b4 221index 630715f..1c864c7 100644
b752ccd1
AM
222--- a/fs/open.c
223+++ b/fs/open.c
953406b4 224@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
b752ccd1
AM
225 mutex_unlock(&dentry->d_inode->i_mutex);
226 return ret;
227 }
228+EXPORT_SYMBOL(do_truncate);
229
230 static long do_sys_truncate(const char __user *pathname, loff_t length)
231 {
232diff --git a/fs/splice.c b/fs/splice.c
953406b4 233index 278c94f..033f7ac 100644
b752ccd1
AM
234--- a/fs/splice.c
235+++ b/fs/splice.c
953406b4 236@@ -1116,6 +1116,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
b752ccd1
AM
237
238 return splice_write(pipe, out, ppos, len, flags);
239 }
240+EXPORT_SYMBOL(do_splice_from);
241
242 /*
243 * Attempt to initiate a splice from a file to a pipe.
953406b4 244@@ -1142,6 +1143,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
b752ccd1
AM
245
246 return splice_read(in, ppos, pipe, len, flags);
247 }
248+EXPORT_SYMBOL(do_splice_to);
249
250 /**
251 * splice_direct_to_actor - splices data directly between two non-pipes
252diff --git a/security/commoncap.c b/security/commoncap.c
253index 4e01599..3611e1b 100644
254--- a/security/commoncap.c
255+++ b/security/commoncap.c
256@@ -951,3 +951,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
257 }
258 return ret;
259 }
260+EXPORT_SYMBOL(cap_file_mmap);
261diff --git a/security/device_cgroup.c b/security/device_cgroup.c
262index 8d9c48f..29108aa 100644
263--- a/security/device_cgroup.c
264+++ b/security/device_cgroup.c
265@@ -515,6 +515,7 @@ found:
266
267 return -EPERM;
268 }
269+EXPORT_SYMBOL(devcgroup_inode_permission);
270
271 int devcgroup_inode_mknod(int mode, dev_t dev)
272 {
273diff --git a/security/security.c b/security/security.c
953406b4 274index c53949f..0ae5b91 100644
b752ccd1
AM
275--- a/security/security.c
276+++ b/security/security.c
277@@ -376,6 +376,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
278 return 0;
279 return security_ops->path_mkdir(dir, dentry, mode);
280 }
281+EXPORT_SYMBOL(security_path_mkdir);
282
283 int security_path_rmdir(struct path *dir, struct dentry *dentry)
284 {
285@@ -383,6 +384,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
286 return 0;
287 return security_ops->path_rmdir(dir, dentry);
288 }
289+EXPORT_SYMBOL(security_path_rmdir);
290
291 int security_path_unlink(struct path *dir, struct dentry *dentry)
292 {
293@@ -390,6 +392,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
294 return 0;
295 return security_ops->path_unlink(dir, dentry);
296 }
297+EXPORT_SYMBOL(security_path_unlink);
298
299 int security_path_symlink(struct path *dir, struct dentry *dentry,
300 const char *old_name)
301@@ -398,6 +401,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
302 return 0;
303 return security_ops->path_symlink(dir, dentry, old_name);
304 }
305+EXPORT_SYMBOL(security_path_symlink);
306
307 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
308 struct dentry *new_dentry)
309@@ -406,6 +410,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
310 return 0;
311 return security_ops->path_link(old_dentry, new_dir, new_dentry);
312 }
313+EXPORT_SYMBOL(security_path_link);
314
315 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
316 struct path *new_dir, struct dentry *new_dentry)
317@@ -416,6 +421,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
318 return security_ops->path_rename(old_dir, old_dentry, new_dir,
319 new_dentry);
320 }
321+EXPORT_SYMBOL(security_path_rename);
322
953406b4
AM
323 int security_path_truncate(struct path *path)
324 {
325@@ -423,6 +429,7 @@ int security_path_truncate(struct path *path)
b752ccd1 326 return 0;
953406b4 327 return security_ops->path_truncate(path);
b752ccd1
AM
328 }
329+EXPORT_SYMBOL(security_path_truncate);
330
331 int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
332 mode_t mode)
953406b4 333@@ -431,6 +438,7 @@ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
b752ccd1
AM
334 return 0;
335 return security_ops->path_chmod(dentry, mnt, mode);
336 }
337+EXPORT_SYMBOL(security_path_chmod);
338
339 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
340 {
953406b4 341@@ -438,6 +446,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
b752ccd1
AM
342 return 0;
343 return security_ops->path_chown(path, uid, gid);
344 }
345+EXPORT_SYMBOL(security_path_chown);
346
347 int security_path_chroot(struct path *path)
348 {
953406b4 349@@ -514,6 +523,7 @@ int security_inode_readlink(struct dentry *dentry)
b752ccd1
AM
350 return 0;
351 return security_ops->inode_readlink(dentry);
352 }
353+EXPORT_SYMBOL(security_inode_readlink);
354
355 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
356 {
953406b4 357@@ -528,6 +538,7 @@ int security_inode_permission(struct inode *inode, int mask)
b752ccd1
AM
358 return 0;
359 return security_ops->inode_permission(inode, mask);
360 }
361+EXPORT_SYMBOL(security_inode_permission);
362
363 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
364 {
953406b4
AM
365@@ -627,6 +638,7 @@ int security_file_permission(struct file *file, int mask)
366
367 return fsnotify_perm(file, mask);
b752ccd1
AM
368 }
369+EXPORT_SYMBOL(security_file_permission);
370
371 int security_file_alloc(struct file *file)
372 {
953406b4 373@@ -654,6 +666,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
b752ccd1
AM
374 return ret;
375 return ima_file_mmap(file, prot);
376 }
377+EXPORT_SYMBOL(security_file_mmap);
378
379 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
380 unsigned long prot)
381diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
382--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
953406b4 383+++ linux/Documentation/ABI/testing/debugfs-aufs 2010-10-21 09:52:43.080290296 +0200
4a4d8108 384@@ -0,0 +1,37 @@
1facf9fc 385+What: /debug/aufs/si_<id>/
386+Date: March 2009
387+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
388+Description:
389+ Under /debug/aufs, a directory named si_<id> is created
390+ per aufs mount, where <id> is a unique id generated
391+ internally.
392+
393+What: /debug/aufs/si_<id>/xib
394+Date: March 2009
395+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
396+Description:
397+ It shows the consumed blocks by xib (External Inode Number
398+ Bitmap), its block size and file size.
399+ When the aufs mount option 'noxino' is specified, it
4a4d8108 400+ will be empty. About XINO files, see the aufs manual.
1facf9fc 401+
402+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
403+Date: March 2009
404+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
405+Description:
406+ It shows the consumed blocks by xino (External Inode Number
407+ Translation Table), its link count, block size and file
408+ size.
409+ When the aufs mount option 'noxino' is specified, it
4a4d8108 410+ will be empty. About XINO files, see the aufs manual.
1facf9fc 411+
412+What: /debug/aufs/si_<id>/xigen
413+Date: March 2009
414+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
415+Description:
416+ It shows the consumed blocks by xigen (External Inode
417+ Generation Table), its block size and file size.
418+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
419+ be created.
420+ When the aufs mount option 'noxino' is specified, it
4a4d8108 421+ will be empty. About XINO files, see the aufs manual.
b752ccd1
AM
422diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
423--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
953406b4 424+++ linux/Documentation/ABI/testing/sysfs-aufs 2010-10-21 09:52:43.080290296 +0200
4a4d8108 425@@ -0,0 +1,24 @@
1facf9fc 426+What: /sys/fs/aufs/si_<id>/
427+Date: March 2009
428+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
429+Description:
430+ Under /sys/fs/aufs, a directory named si_<id> is created
431+ per aufs mount, where <id> is a unique id generated
432+ internally.
433+
434+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
435+Date: March 2009
436+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
437+Description:
438+ It shows the abolute path of a member directory (which
439+ is called branch) in aufs, and its permission.
440+
441+What: /sys/fs/aufs/si_<id>/xi_path
442+Date: March 2009
443+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
444+Description:
445+ It shows the abolute path of XINO (External Inode Number
446+ Bitmap, Translation Table and Generation Table) file
447+ even if it is the default path.
448+ When the aufs mount option 'noxino' is specified, it
4a4d8108 449+ will be empty. About XINO files, see the aufs manual.
b752ccd1
AM
450diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
451--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
953406b4 452+++ linux/fs/aufs/aufs.h 2010-10-21 09:52:43.083624114 +0200
4a4d8108 453@@ -0,0 +1,61 @@
1facf9fc 454+/*
4a4d8108 455+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 456+ *
457+ * This program, aufs is free software; you can redistribute it and/or modify
458+ * it under the terms of the GNU General Public License as published by
459+ * the Free Software Foundation; either version 2 of the License, or
460+ * (at your option) any later version.
dece6358
AM
461+ *
462+ * This program is distributed in the hope that it will be useful,
463+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
464+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
465+ * GNU General Public License for more details.
466+ *
467+ * You should have received a copy of the GNU General Public License
468+ * along with this program; if not, write to the Free Software
469+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 470+ */
471+
472+/*
473+ * all header files
474+ */
475+
476+#ifndef __AUFS_H__
477+#define __AUFS_H__
478+
479+#ifdef __KERNEL__
480+
4a4d8108
AM
481+#define AuStub(type, name, body, ...) \
482+ static inline type name(__VA_ARGS__) { body; }
483+
484+#define AuStubVoid(name, ...) \
485+ AuStub(void, name, , __VA_ARGS__)
486+#define AuStubInt0(name, ...) \
487+ AuStub(int, name, return 0, __VA_ARGS__)
488+
1facf9fc 489+#include "debug.h"
490+
491+#include "branch.h"
492+#include "cpup.h"
493+#include "dcsub.h"
494+#include "dbgaufs.h"
495+#include "dentry.h"
496+#include "dir.h"
4a4d8108 497+#include "dynop.h"
1facf9fc 498+#include "file.h"
499+#include "fstype.h"
500+#include "inode.h"
501+#include "loop.h"
502+#include "module.h"
4a4d8108 503+/* never include ./mtx.h */
1facf9fc 504+#include "opts.h"
505+#include "rwsem.h"
506+#include "spl.h"
507+#include "super.h"
508+#include "sysaufs.h"
509+#include "vfsub.h"
510+#include "whout.h"
511+#include "wkq.h"
512+
513+#endif /* __KERNEL__ */
514+#endif /* __AUFS_H__ */
b752ccd1
AM
515diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
516--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
517+++ linux/fs/aufs/branch.c 2010-10-21 09:52:43.086957936 +0200
518@@ -0,0 +1,1005 @@
1facf9fc 519+/*
4a4d8108 520+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 521+ *
522+ * This program, aufs is free software; you can redistribute it and/or modify
523+ * it under the terms of the GNU General Public License as published by
524+ * the Free Software Foundation; either version 2 of the License, or
525+ * (at your option) any later version.
dece6358
AM
526+ *
527+ * This program is distributed in the hope that it will be useful,
528+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
529+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
530+ * GNU General Public License for more details.
531+ *
532+ * You should have received a copy of the GNU General Public License
533+ * along with this program; if not, write to the Free Software
534+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 535+ */
536+
537+/*
538+ * branch management
539+ */
540+
dece6358 541+#include <linux/file.h>
4a4d8108 542+#include <linux/statfs.h>
1facf9fc 543+#include "aufs.h"
544+
545+/*
546+ * free a single branch
547+ */
548+static void au_br_do_free(struct au_branch *br)
549+{
550+ int i;
551+ struct au_wbr *wbr;
4a4d8108 552+ struct au_dykey **key;
1facf9fc 553+
554+ if (br->br_xino.xi_file)
555+ fput(br->br_xino.xi_file);
556+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
557+
558+ AuDebugOn(atomic_read(&br->br_count));
559+
560+ wbr = br->br_wbr;
561+ if (wbr) {
562+ for (i = 0; i < AuBrWh_Last; i++)
563+ dput(wbr->wbr_wh[i]);
564+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 565+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 566+ }
567+
4a4d8108
AM
568+ key = br->br_dykey;
569+ for (i = 0; i < AuBrDynOp; i++, key++)
570+ if (*key)
571+ au_dy_put(*key);
572+ else
573+ break;
574+
1facf9fc 575+ mntput(br->br_mnt);
1facf9fc 576+ kfree(wbr);
577+ kfree(br);
578+}
579+
580+/*
581+ * frees all branches
582+ */
583+void au_br_free(struct au_sbinfo *sbinfo)
584+{
585+ aufs_bindex_t bmax;
586+ struct au_branch **br;
587+
dece6358
AM
588+ AuRwMustWriteLock(&sbinfo->si_rwsem);
589+
1facf9fc 590+ bmax = sbinfo->si_bend + 1;
591+ br = sbinfo->si_branch;
592+ while (bmax--)
593+ au_br_do_free(*br++);
594+}
595+
596+/*
597+ * find the index of a branch which is specified by @br_id.
598+ */
599+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
600+{
601+ aufs_bindex_t bindex, bend;
602+
603+ bend = au_sbend(sb);
604+ for (bindex = 0; bindex <= bend; bindex++)
605+ if (au_sbr_id(sb, bindex) == br_id)
606+ return bindex;
607+ return -1;
608+}
609+
610+/* ---------------------------------------------------------------------- */
611+
612+/*
613+ * add a branch
614+ */
615+
b752ccd1
AM
616+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
617+ struct dentry *h_root)
1facf9fc 618+{
b752ccd1
AM
619+ if (unlikely(h_adding == h_root
620+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 621+ return 1;
b752ccd1
AM
622+ if (h_adding->d_sb != h_root->d_sb)
623+ return 0;
624+ return au_test_subdir(h_adding, h_root)
625+ || au_test_subdir(h_root, h_adding);
1facf9fc 626+}
627+
628+/*
629+ * returns a newly allocated branch. @new_nbranch is a number of branches
630+ * after adding a branch.
631+ */
632+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
633+ int perm)
634+{
635+ struct au_branch *add_branch;
636+ struct dentry *root;
4a4d8108 637+ int err;
1facf9fc 638+
4a4d8108 639+ err = -ENOMEM;
1facf9fc 640+ root = sb->s_root;
641+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
642+ if (unlikely(!add_branch))
643+ goto out;
644+
645+ add_branch->br_wbr = NULL;
646+ if (au_br_writable(perm)) {
647+ /* may be freed separately at changing the branch permission */
648+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
649+ GFP_NOFS);
650+ if (unlikely(!add_branch->br_wbr))
651+ goto out_br;
652+ }
653+
4a4d8108
AM
654+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
655+ if (!err)
656+ err = au_di_realloc(au_di(root), new_nbranch);
657+ if (!err)
658+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
659+ if (!err)
660+ return add_branch; /* success */
1facf9fc 661+
1facf9fc 662+ kfree(add_branch->br_wbr);
4a4d8108 663+
4f0767ce 664+out_br:
1facf9fc 665+ kfree(add_branch);
4f0767ce 666+out:
4a4d8108 667+ return ERR_PTR(err);
1facf9fc 668+}
669+
670+/*
671+ * test if the branch permission is legal or not.
672+ */
673+static int test_br(struct inode *inode, int brperm, char *path)
674+{
675+ int err;
676+
4a4d8108
AM
677+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
678+ if (!err)
679+ goto out;
1facf9fc 680+
4a4d8108
AM
681+ err = -EINVAL;
682+ pr_err("write permission for readonly mount or inode, %s\n", path);
683+
4f0767ce 684+out:
1facf9fc 685+ return err;
686+}
687+
688+/*
689+ * returns:
690+ * 0: success, the caller will add it
691+ * plus: success, it is already unified, the caller should ignore it
692+ * minus: error
693+ */
694+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
695+{
696+ int err;
697+ aufs_bindex_t bend, bindex;
698+ struct dentry *root;
699+ struct inode *inode, *h_inode;
700+
701+ root = sb->s_root;
702+ bend = au_sbend(sb);
703+ if (unlikely(bend >= 0
704+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
705+ err = 1;
706+ if (!remount) {
707+ err = -EINVAL;
4a4d8108 708+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 709+ }
710+ goto out;
711+ }
712+
713+ err = -ENOSPC; /* -E2BIG; */
714+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
715+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 716+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 717+ goto out;
718+ }
719+
720+ err = -EDOM;
721+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 722+ pr_err("bad index %d\n", add->bindex);
1facf9fc 723+ goto out;
724+ }
725+
726+ inode = add->path.dentry->d_inode;
727+ err = -ENOENT;
728+ if (unlikely(!inode->i_nlink)) {
4a4d8108 729+ pr_err("no existence %s\n", add->pathname);
1facf9fc 730+ goto out;
731+ }
732+
733+ err = -EINVAL;
734+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 735+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 736+ goto out;
737+ }
738+
739+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
740+ pr_err("unsupported filesystem, %s (%s)\n",
741+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 742+ goto out;
743+ }
744+
745+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
746+ if (unlikely(err))
747+ goto out;
748+
749+ if (bend < 0)
750+ return 0; /* success */
751+
752+ err = -EINVAL;
753+ for (bindex = 0; bindex <= bend; bindex++)
754+ if (unlikely(test_overlap(sb, add->path.dentry,
755+ au_h_dptr(root, bindex)))) {
4a4d8108 756+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 757+ goto out;
758+ }
759+
760+ err = 0;
761+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
762+ h_inode = au_h_dptr(root, 0)->d_inode;
763+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
764+ || h_inode->i_uid != inode->i_uid
765+ || h_inode->i_gid != inode->i_gid)
4a4d8108
AM
766+ pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
767+ add->pathname,
768+ inode->i_uid, inode->i_gid,
769+ (inode->i_mode & S_IALLUGO),
770+ h_inode->i_uid, h_inode->i_gid,
771+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 772+ }
773+
4f0767ce 774+out:
1facf9fc 775+ return err;
776+}
777+
778+/*
779+ * initialize or clean the whiteouts for an adding branch
780+ */
781+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
782+ int new_perm, struct dentry *h_root)
783+{
784+ int err, old_perm;
785+ aufs_bindex_t bindex;
786+ struct mutex *h_mtx;
787+ struct au_wbr *wbr;
788+ struct au_hinode *hdir;
789+
790+ wbr = br->br_wbr;
791+ old_perm = br->br_perm;
792+ br->br_perm = new_perm;
793+ hdir = NULL;
794+ h_mtx = NULL;
795+ bindex = au_br_index(sb, br->br_id);
796+ if (0 <= bindex) {
797+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 798+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 799+ } else {
800+ h_mtx = &h_root->d_inode->i_mutex;
801+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
802+ }
803+ if (!wbr)
804+ err = au_wh_init(h_root, br, sb);
805+ else {
806+ wbr_wh_write_lock(wbr);
807+ err = au_wh_init(h_root, br, sb);
808+ wbr_wh_write_unlock(wbr);
809+ }
810+ if (hdir)
4a4d8108 811+ au_hn_imtx_unlock(hdir);
1facf9fc 812+ else
813+ mutex_unlock(h_mtx);
814+ br->br_perm = old_perm;
815+
816+ if (!err && wbr && !au_br_writable(new_perm)) {
817+ kfree(wbr);
818+ br->br_wbr = NULL;
819+ }
820+
821+ return err;
822+}
823+
824+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
825+ int perm, struct path *path)
826+{
827+ int err;
4a4d8108 828+ struct kstatfs kst;
1facf9fc 829+ struct au_wbr *wbr;
4a4d8108 830+ struct dentry *h_dentry;
1facf9fc 831+
832+ wbr = br->br_wbr;
dece6358 833+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 834+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
835+ atomic_set(&wbr->wbr_wh_running, 0);
836+ wbr->wbr_bytes = 0;
837+
4a4d8108
AM
838+ /*
839+ * a limit for rmdir/rename a dir
840+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
841+ */
953406b4 842+ err = vfs_statfs(path, &kst);
4a4d8108
AM
843+ if (unlikely(err))
844+ goto out;
845+ err = -EINVAL;
953406b4 846+ h_dentry = path->dentry;
4a4d8108
AM
847+ if (kst.f_namelen >= NAME_MAX)
848+ err = au_br_init_wh(sb, br, perm, h_dentry);
849+ else
850+ pr_err("%.*s(%s), unsupported namelen %ld\n",
851+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
852+ kst.f_namelen);
1facf9fc 853+
4f0767ce 854+out:
1facf9fc 855+ return err;
856+}
857+
858+/* intialize a new branch */
859+static int au_br_init(struct au_branch *br, struct super_block *sb,
860+ struct au_opt_add *add)
861+{
862+ int err;
863+
864+ err = 0;
865+ memset(&br->br_xino, 0, sizeof(br->br_xino));
866+ mutex_init(&br->br_xino.xi_nondir_mtx);
867+ br->br_perm = add->perm;
868+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
869+ spin_lock_init(&br->br_dykey_lock);
870+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 871+ atomic_set(&br->br_count, 0);
872+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
873+ atomic_set(&br->br_xino_running, 0);
874+ br->br_id = au_new_br_id(sb);
875+
876+ if (au_br_writable(add->perm)) {
877+ err = au_wbr_init(br, sb, add->perm, &add->path);
878+ if (unlikely(err))
b752ccd1 879+ goto out_err;
1facf9fc 880+ }
881+
882+ if (au_opt_test(au_mntflags(sb), XINO)) {
883+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
884+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
885+ if (unlikely(err)) {
886+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 887+ goto out_err;
1facf9fc 888+ }
889+ }
890+
891+ sysaufs_br_init(br);
892+ mntget(add->path.mnt);
b752ccd1 893+ goto out; /* success */
1facf9fc 894+
4f0767ce 895+out_err:
b752ccd1 896+ br->br_mnt = NULL;
4f0767ce 897+out:
1facf9fc 898+ return err;
899+}
900+
901+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
902+ struct au_branch *br, aufs_bindex_t bend,
903+ aufs_bindex_t amount)
904+{
905+ struct au_branch **brp;
906+
dece6358
AM
907+ AuRwMustWriteLock(&sbinfo->si_rwsem);
908+
1facf9fc 909+ brp = sbinfo->si_branch + bindex;
910+ memmove(brp + 1, brp, sizeof(*brp) * amount);
911+ *brp = br;
912+ sbinfo->si_bend++;
913+ if (unlikely(bend < 0))
914+ sbinfo->si_bend = 0;
915+}
916+
917+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
918+ aufs_bindex_t bend, aufs_bindex_t amount)
919+{
920+ struct au_hdentry *hdp;
921+
1308ab2a 922+ AuRwMustWriteLock(&dinfo->di_rwsem);
923+
1facf9fc 924+ hdp = dinfo->di_hdentry + bindex;
925+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
926+ au_h_dentry_init(hdp);
927+ dinfo->di_bend++;
928+ if (unlikely(bend < 0))
929+ dinfo->di_bstart = 0;
930+}
931+
932+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
933+ aufs_bindex_t bend, aufs_bindex_t amount)
934+{
935+ struct au_hinode *hip;
936+
1308ab2a 937+ AuRwMustWriteLock(&iinfo->ii_rwsem);
938+
1facf9fc 939+ hip = iinfo->ii_hinode + bindex;
940+ memmove(hip + 1, hip, sizeof(*hip) * amount);
941+ hip->hi_inode = NULL;
4a4d8108 942+ au_hn_init(hip);
1facf9fc 943+ iinfo->ii_bend++;
944+ if (unlikely(bend < 0))
945+ iinfo->ii_bstart = 0;
946+}
947+
948+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
949+ struct au_branch *br, aufs_bindex_t bindex)
950+{
951+ struct dentry *root;
952+ struct inode *root_inode;
953+ aufs_bindex_t bend, amount;
954+
955+ root = sb->s_root;
956+ root_inode = root->d_inode;
953406b4 957+ au_plink_maint_block(sb);
1facf9fc 958+ bend = au_sbend(sb);
959+ amount = bend + 1 - bindex;
960+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
961+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
962+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
963+ au_set_h_dptr(root, bindex, dget(h_dentry));
964+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
965+ /*flags*/0);
966+}
967+
968+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
969+{
970+ int err;
1facf9fc 971+ aufs_bindex_t bend, add_bindex;
972+ struct dentry *root, *h_dentry;
973+ struct inode *root_inode;
974+ struct au_branch *add_branch;
975+
976+ root = sb->s_root;
977+ root_inode = root->d_inode;
978+ IMustLock(root_inode);
979+ err = test_add(sb, add, remount);
980+ if (unlikely(err < 0))
981+ goto out;
982+ if (err) {
983+ err = 0;
984+ goto out; /* success */
985+ }
986+
987+ bend = au_sbend(sb);
988+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
989+ err = PTR_ERR(add_branch);
990+ if (IS_ERR(add_branch))
991+ goto out;
992+
993+ err = au_br_init(add_branch, sb, add);
994+ if (unlikely(err)) {
995+ au_br_do_free(add_branch);
996+ goto out;
997+ }
998+
999+ add_bindex = add->bindex;
1000+ h_dentry = add->path.dentry;
1001+ if (!remount)
1002+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1003+ else {
1004+ sysaufs_brs_del(sb, add_bindex);
1005+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1006+ sysaufs_brs_add(sb, add_bindex);
1007+ }
1008+
1308ab2a 1009+ if (!add_bindex) {
1facf9fc 1010+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 1011+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
1012+ } else
1facf9fc 1013+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 1014+
1015+ /*
4a4d8108 1016+ * this test/set prevents aufs from handling unnecesary notify events
1facf9fc 1017+ * of xino files, in a case of re-adding a writable branch which was
1018+ * once detached from aufs.
1019+ */
1020+ if (au_xino_brid(sb) < 0
1021+ && au_br_writable(add_branch->br_perm)
1022+ && !au_test_fs_bad_xino(h_dentry->d_sb)
1023+ && add_branch->br_xino.xi_file
1024+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
1025+ au_xino_brid_set(sb, add_branch->br_id);
1026+
4f0767ce 1027+out:
1facf9fc 1028+ return err;
1029+}
1030+
1031+/* ---------------------------------------------------------------------- */
1032+
1033+/*
1034+ * delete a branch
1035+ */
1036+
1037+/* to show the line number, do not make it inlined function */
4a4d8108 1038+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 1039+ if (do_info) \
4a4d8108 1040+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 1041+} while (0)
1042+
1043+/*
1044+ * test if the branch is deletable or not.
1045+ */
1046+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 1047+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1048+{
1049+ int err, i, j, ndentry;
1050+ aufs_bindex_t bstart, bend;
1facf9fc 1051+ struct au_dcsub_pages dpages;
1052+ struct au_dpage *dpage;
1053+ struct dentry *d;
1054+ struct inode *inode;
1055+
1056+ err = au_dpages_init(&dpages, GFP_NOFS);
1057+ if (unlikely(err))
1058+ goto out;
1059+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
1060+ if (unlikely(err))
1061+ goto out_dpages;
1062+
1facf9fc 1063+ for (i = 0; !err && i < dpages.ndpage; i++) {
1064+ dpage = dpages.dpages + i;
1065+ ndentry = dpage->ndentry;
1066+ for (j = 0; !err && j < ndentry; j++) {
1067+ d = dpage->dentries[j];
1068+ AuDebugOn(!atomic_read(&d->d_count));
1069+ inode = d->d_inode;
1070+ if (au_digen(d) == sigen && au_iigen(inode) == sigen)
1071+ di_read_lock_child(d, AuLock_IR);
1072+ else {
1073+ di_write_lock_child(d);
1074+ err = au_reval_dpath(d, sigen);
1075+ if (!err)
1076+ di_downgrade_lock(d, AuLock_IR);
1077+ else {
1078+ di_write_unlock(d);
1079+ break;
1080+ }
1081+ }
1082+
1083+ bstart = au_dbstart(d);
1084+ bend = au_dbend(d);
1085+ if (bstart <= bindex
1086+ && bindex <= bend
1087+ && au_h_dptr(d, bindex)
1088+ && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
1089+ err = -EBUSY;
1090+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
1091+ }
1092+ di_read_unlock(d, AuLock_IR);
1093+ }
1094+ }
1095+
4f0767ce 1096+out_dpages:
1facf9fc 1097+ au_dpages_free(&dpages);
4f0767ce 1098+out:
1facf9fc 1099+ return err;
1100+}
1101+
1102+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 1103+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1104+{
1105+ int err;
1106+ struct inode *i;
1107+ aufs_bindex_t bstart, bend;
1facf9fc 1108+
1109+ err = 0;
1facf9fc 1110+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
1111+ AuDebugOn(!atomic_read(&i->i_count));
1112+ if (!list_empty(&i->i_dentry))
1113+ continue;
1114+
1115+ if (au_iigen(i) == sigen)
1116+ ii_read_lock_child(i);
1117+ else {
1118+ ii_write_lock_child(i);
1119+ err = au_refresh_hinode_self(i, /*do_attr*/1);
1120+ if (!err)
1121+ ii_downgrade_lock(i);
1122+ else {
1123+ ii_write_unlock(i);
1124+ break;
1125+ }
1126+ }
1127+
1128+ bstart = au_ibstart(i);
1129+ bend = au_ibend(i);
1130+ if (bstart <= bindex
1131+ && bindex <= bend
1132+ && au_h_iptr(i, bindex)
1133+ && (!S_ISDIR(i->i_mode) || bstart == bend)) {
1134+ err = -EBUSY;
1135+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
1136+ ii_read_unlock(i);
1137+ break;
1138+ }
1139+ ii_read_unlock(i);
1140+ }
1141+
1142+ return err;
1143+}
1144+
b752ccd1
AM
1145+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
1146+ const unsigned int verbose)
1facf9fc 1147+{
1148+ int err;
1149+ unsigned int sigen;
1150+
1151+ sigen = au_sigen(root->d_sb);
1152+ DiMustNoWaiters(root);
1153+ IiMustNoWaiters(root->d_inode);
1154+ di_write_unlock(root);
b752ccd1 1155+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 1156+ if (!err)
b752ccd1 1157+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 1158+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
1159+
1160+ return err;
1161+}
1162+
1163+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
1164+ const aufs_bindex_t bindex,
1165+ const aufs_bindex_t bend)
1166+{
1167+ struct au_branch **brp, **p;
1168+
dece6358
AM
1169+ AuRwMustWriteLock(&sbinfo->si_rwsem);
1170+
1facf9fc 1171+ brp = sbinfo->si_branch + bindex;
1172+ if (bindex < bend)
1173+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
1174+ sbinfo->si_branch[0 + bend] = NULL;
1175+ sbinfo->si_bend--;
1176+
1177+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
1178+ if (p)
1179+ sbinfo->si_branch = p;
4a4d8108 1180+ /* harmless error */
1facf9fc 1181+}
1182+
1183+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
1184+ const aufs_bindex_t bend)
1185+{
1186+ struct au_hdentry *hdp, *p;
1187+
1308ab2a 1188+ AuRwMustWriteLock(&dinfo->di_rwsem);
1189+
4a4d8108 1190+ hdp = dinfo->di_hdentry;
1facf9fc 1191+ if (bindex < bend)
4a4d8108
AM
1192+ memmove(hdp + bindex, hdp + bindex + 1,
1193+ sizeof(*hdp) * (bend - bindex));
1194+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 1195+ dinfo->di_bend--;
1196+
4a4d8108 1197+ p = krealloc(hdp, sizeof(*p) * bend, GFP_NOFS);
1facf9fc 1198+ if (p)
1199+ dinfo->di_hdentry = p;
4a4d8108 1200+ /* harmless error */
1facf9fc 1201+}
1202+
1203+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
1204+ const aufs_bindex_t bend)
1205+{
1206+ struct au_hinode *hip, *p;
1207+
1308ab2a 1208+ AuRwMustWriteLock(&iinfo->ii_rwsem);
1209+
1facf9fc 1210+ hip = iinfo->ii_hinode + bindex;
1211+ if (bindex < bend)
1212+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
1213+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 1214+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 1215+ iinfo->ii_bend--;
1216+
1217+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
1218+ if (p)
1219+ iinfo->ii_hinode = p;
4a4d8108 1220+ /* harmless error */
1facf9fc 1221+}
1222+
1223+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
1224+ struct au_branch *br)
1225+{
1226+ aufs_bindex_t bend;
1227+ struct au_sbinfo *sbinfo;
1228+ struct dentry *root;
1229+ struct inode *inode;
1230+
dece6358
AM
1231+ SiMustWriteLock(sb);
1232+
1facf9fc 1233+ root = sb->s_root;
1234+ inode = root->d_inode;
953406b4 1235+ au_plink_maint_block(sb);
1facf9fc 1236+ sbinfo = au_sbi(sb);
1237+ bend = sbinfo->si_bend;
1238+
1239+ dput(au_h_dptr(root, bindex));
1240+ au_hiput(au_hi(inode, bindex));
1241+ au_br_do_free(br);
1242+
1243+ au_br_do_del_brp(sbinfo, bindex, bend);
1244+ au_br_do_del_hdp(au_di(root), bindex, bend);
1245+ au_br_do_del_hip(au_ii(inode), bindex, bend);
1246+}
1247+
1248+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
1249+{
1250+ int err, rerr, i;
1251+ unsigned int mnt_flags;
1252+ aufs_bindex_t bindex, bend, br_id;
1253+ unsigned char do_wh, verbose;
1254+ struct au_branch *br;
1255+ struct au_wbr *wbr;
1256+
1257+ err = 0;
1258+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
1259+ if (bindex < 0) {
1260+ if (remount)
1261+ goto out; /* success */
1262+ err = -ENOENT;
4a4d8108 1263+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 1264+ goto out;
1265+ }
1266+ AuDbg("bindex b%d\n", bindex);
1267+
1268+ err = -EBUSY;
1269+ mnt_flags = au_mntflags(sb);
1270+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
1271+ bend = au_sbend(sb);
1272+ if (unlikely(!bend)) {
1273+ AuVerbose(verbose, "no more branches left\n");
1274+ goto out;
1275+ }
1276+ br = au_sbr(sb, bindex);
1277+ i = atomic_read(&br->br_count);
1278+ if (unlikely(i)) {
1279+ AuVerbose(verbose, "%d file(s) opened\n", i);
953406b4
AM
1280+ if (!verbose)
1281+ goto out;
1facf9fc 1282+ }
1283+
1284+ wbr = br->br_wbr;
1285+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
1286+ if (do_wh) {
1308ab2a 1287+ /* instead of WbrWhMustWriteLock(wbr) */
1288+ SiMustWriteLock(sb);
1facf9fc 1289+ for (i = 0; i < AuBrWh_Last; i++) {
1290+ dput(wbr->wbr_wh[i]);
1291+ wbr->wbr_wh[i] = NULL;
1292+ }
1293+ }
1294+
b752ccd1 1295+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 1296+ if (unlikely(err)) {
1297+ if (do_wh)
1298+ goto out_wh;
1299+ goto out;
1300+ }
1301+
1302+ err = 0;
1303+ br_id = br->br_id;
1304+ if (!remount)
1305+ au_br_do_del(sb, bindex, br);
1306+ else {
1307+ sysaufs_brs_del(sb, bindex);
1308+ au_br_do_del(sb, bindex, br);
1309+ sysaufs_brs_add(sb, bindex);
1310+ }
1311+
1308ab2a 1312+ if (!bindex) {
1facf9fc 1313+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 1314+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
1315+ } else
1facf9fc 1316+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
1317+ if (au_opt_test(mnt_flags, PLINK))
1318+ au_plink_half_refresh(sb, br_id);
1319+
b752ccd1 1320+ if (au_xino_brid(sb) == br_id)
1facf9fc 1321+ au_xino_brid_set(sb, -1);
1322+ goto out; /* success */
1323+
4f0767ce 1324+out_wh:
1facf9fc 1325+ /* revert */
1326+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
1327+ if (rerr)
4a4d8108
AM
1328+ pr_warning("failed re-creating base whiteout, %s. (%d)\n",
1329+ del->pathname, rerr);
4f0767ce 1330+out:
1facf9fc 1331+ return err;
1332+}
1333+
1334+/* ---------------------------------------------------------------------- */
1335+
1336+/*
1337+ * change a branch permission
1338+ */
1339+
dece6358
AM
1340+static void au_warn_ima(void)
1341+{
1342+#ifdef CONFIG_IMA
1308ab2a 1343+ /* since it doesn't support mark_files_ro() */
953406b4 1344+ pr_warning("RW -> RO makes IMA to produce wrong message");
dece6358
AM
1345+#endif
1346+}
1347+
1facf9fc 1348+static int do_need_sigen_inc(int a, int b)
1349+{
1350+ return au_br_whable(a) && !au_br_whable(b);
1351+}
1352+
1353+static int need_sigen_inc(int old, int new)
1354+{
1355+ return do_need_sigen_inc(old, new)
1356+ || do_need_sigen_inc(new, old);
1357+}
1358+
1359+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
1360+{
1361+ int err;
1362+ unsigned long n, ul, bytes, files;
953406b4 1363+ aufs_bindex_t bstart;
1facf9fc 1364+ struct file *file, *hf, **a;
1365+ const int step_bytes = 1024, /* memory allocation unit */
1366+ step_files = step_bytes / sizeof(*a);
1367+
1368+ err = -ENOMEM;
1369+ n = 0;
1370+ bytes = step_bytes;
1371+ files = step_files;
1372+ a = kmalloc(bytes, GFP_NOFS);
1373+ if (unlikely(!a))
1374+ goto out;
1375+
1376+ /* no need file_list_lock() since sbinfo is locked? defered? */
1377+ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
1378+ if (special_file(file->f_dentry->d_inode->i_mode))
1379+ continue;
1380+
1381+ AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
1382+ fi_read_lock(file);
1383+ if (unlikely(au_test_mmapped(file))) {
1384+ err = -EBUSY;
1385+ FiMustNoWaiters(file);
1386+ fi_read_unlock(file);
1387+ goto out_free;
1388+ }
1389+
953406b4
AM
1390+ bstart = au_fbstart(file);
1391+ if (!S_ISREG(file->f_dentry->d_inode->i_mode)
1facf9fc 1392+ || !(file->f_mode & FMODE_WRITE)
953406b4 1393+ || bstart != bindex) {
1facf9fc 1394+ FiMustNoWaiters(file);
1395+ fi_read_unlock(file);
1396+ continue;
1397+ }
1398+
953406b4 1399+ hf = au_hf_top(file);
1facf9fc 1400+ FiMustNoWaiters(file);
1401+ fi_read_unlock(file);
1402+
1403+ if (n < files)
1404+ a[n++] = hf;
1405+ else {
1406+ void *p;
1407+
1408+ err = -ENOMEM;
1409+ bytes += step_bytes;
1410+ files += step_files;
1411+ p = krealloc(a, bytes, GFP_NOFS);
1412+ if (p) {
1413+ a = p;
1414+ a[n++] = hf;
1415+ } else
1416+ goto out_free;
1417+ }
1418+ }
1419+
1420+ err = 0;
dece6358
AM
1421+ if (n)
1422+ au_warn_ima();
1facf9fc 1423+ for (ul = 0; ul < n; ul++) {
1424+ /* todo: already flushed? */
1425+ /* cf. fs/super.c:mark_files_ro() */
1426+ hf = a[ul];
1427+ hf->f_mode &= ~FMODE_WRITE;
1428+ if (!file_check_writeable(hf)) {
1429+ file_release_write(hf);
1430+ mnt_drop_write(hf->f_vfsmnt);
1431+ }
1432+ }
1433+
4f0767ce 1434+out_free:
1facf9fc 1435+ kfree(a);
4f0767ce 1436+out:
1facf9fc 1437+ return err;
1438+}
1439+
1440+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1441+ int *do_update)
1442+{
1443+ int err, rerr;
1444+ aufs_bindex_t bindex;
1308ab2a 1445+ struct path path;
1facf9fc 1446+ struct dentry *root;
1447+ struct au_branch *br;
1448+
1449+ root = sb->s_root;
953406b4 1450+ au_plink_maint_block(sb);
1facf9fc 1451+ bindex = au_find_dbindex(root, mod->h_root);
1452+ if (bindex < 0) {
1453+ if (remount)
1454+ return 0; /* success */
1455+ err = -ENOENT;
4a4d8108 1456+ pr_err("%s no such branch\n", mod->path);
1facf9fc 1457+ goto out;
1458+ }
1459+ AuDbg("bindex b%d\n", bindex);
1460+
1461+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
1462+ if (unlikely(err))
1463+ goto out;
1464+
1465+ br = au_sbr(sb, bindex);
1466+ if (br->br_perm == mod->perm)
1467+ return 0; /* success */
1468+
1469+ if (au_br_writable(br->br_perm)) {
1470+ /* remove whiteout base */
1471+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
1472+ if (unlikely(err))
1473+ goto out;
1474+
1475+ if (!au_br_writable(mod->perm)) {
1476+ /* rw --> ro, file might be mmapped */
1477+ DiMustNoWaiters(root);
1478+ IiMustNoWaiters(root->d_inode);
1479+ di_write_unlock(root);
1480+ err = au_br_mod_files_ro(sb, bindex);
1481+ /* aufs_write_lock() calls ..._child() */
1482+ di_write_lock_child(root);
1483+
1484+ if (unlikely(err)) {
1485+ rerr = -ENOMEM;
1486+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
1487+ GFP_NOFS);
1308ab2a 1488+ if (br->br_wbr) {
1489+ path.mnt = br->br_mnt;
1490+ path.dentry = mod->h_root;
1491+ rerr = au_wbr_init(br, sb, br->br_perm,
1492+ &path);
1493+ }
1facf9fc 1494+ if (unlikely(rerr)) {
1495+ AuIOErr("nested error %d (%d)\n",
1496+ rerr, err);
1497+ br->br_perm = mod->perm;
1498+ }
1499+ }
1500+ }
1501+ } else if (au_br_writable(mod->perm)) {
1502+ /* ro --> rw */
1503+ err = -ENOMEM;
1504+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1505+ if (br->br_wbr) {
1308ab2a 1506+ path.mnt = br->br_mnt;
1507+ path.dentry = mod->h_root;
1facf9fc 1508+ err = au_wbr_init(br, sb, mod->perm, &path);
1509+ if (unlikely(err)) {
1510+ kfree(br->br_wbr);
1511+ br->br_wbr = NULL;
1512+ }
1513+ }
1514+ }
1515+
1516+ if (!err) {
1517+ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
1518+ br->br_perm = mod->perm;
1519+ }
1520+
4f0767ce 1521+out:
1facf9fc 1522+ return err;
1523+}
b752ccd1
AM
1524diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
1525--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
953406b4 1526+++ linux/fs/aufs/branch.h 2010-10-21 09:52:43.086957936 +0200
b752ccd1 1527@@ -0,0 +1,224 @@
1facf9fc 1528+/*
4a4d8108 1529+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1530+ *
1531+ * This program, aufs is free software; you can redistribute it and/or modify
1532+ * it under the terms of the GNU General Public License as published by
1533+ * the Free Software Foundation; either version 2 of the License, or
1534+ * (at your option) any later version.
dece6358
AM
1535+ *
1536+ * This program is distributed in the hope that it will be useful,
1537+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1538+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1539+ * GNU General Public License for more details.
1540+ *
1541+ * You should have received a copy of the GNU General Public License
1542+ * along with this program; if not, write to the Free Software
1543+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1544+ */
1545+
1546+/*
1547+ * branch filesystems and xino for them
1548+ */
1549+
1550+#ifndef __AUFS_BRANCH_H__
1551+#define __AUFS_BRANCH_H__
1552+
1553+#ifdef __KERNEL__
1554+
1555+#include <linux/fs.h>
1556+#include <linux/mount.h>
1facf9fc 1557+#include <linux/aufs_type.h>
4a4d8108 1558+#include "dynop.h"
1facf9fc 1559+#include "rwsem.h"
1560+#include "super.h"
1561+
1562+/* ---------------------------------------------------------------------- */
1563+
1564+/* a xino file */
1565+struct au_xino_file {
1566+ struct file *xi_file;
1567+ struct mutex xi_nondir_mtx;
1568+
1569+ /* todo: make xino files an array to support huge inode number */
1570+
1571+#ifdef CONFIG_DEBUG_FS
1572+ struct dentry *xi_dbgaufs;
1573+#endif
1574+};
1575+
1576+/* members for writable branch only */
1577+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
1578+struct au_wbr {
dece6358 1579+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 1580+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 1581+ atomic_t wbr_wh_running;
1facf9fc 1582+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
1583+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
1584+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
1585+
1586+ /* mfs mode */
1587+ unsigned long long wbr_bytes;
1588+};
1589+
4a4d8108
AM
1590+/* ext2 has 3 types of operations at least, ext3 has 4 */
1591+#define AuBrDynOp (AuDyLast * 4)
1592+
1facf9fc 1593+/* protected by superblock rwsem */
1594+struct au_branch {
1595+ struct au_xino_file br_xino;
1596+
1597+ aufs_bindex_t br_id;
1598+
1599+ int br_perm;
1600+ struct vfsmount *br_mnt;
4a4d8108
AM
1601+ spinlock_t br_dykey_lock;
1602+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 1603+ atomic_t br_count;
1604+
1605+ struct au_wbr *br_wbr;
1606+
1607+ /* xino truncation */
1608+ blkcnt_t br_xino_upper; /* watermark in blocks */
1609+ atomic_t br_xino_running;
1610+
1611+#ifdef CONFIG_SYSFS
1612+ /* an entry under sysfs per mount-point */
1613+ char br_name[8];
1614+ struct attribute br_attr;
1615+#endif
1616+};
1617+
1618+/* ---------------------------------------------------------------------- */
1619+
1620+/* branch permission and attribute */
1621+enum {
1622+ AuBrPerm_RW, /* writable, linkable wh */
1623+ AuBrPerm_RO, /* readonly, no wh */
1624+ AuBrPerm_RR, /* natively readonly, no wh */
1625+
1626+ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
1627+
1628+ AuBrPerm_ROWH, /* whiteout-able */
1629+ AuBrPerm_RRWH, /* whiteout-able */
1630+
1631+ AuBrPerm_Last
1632+};
1633+
1634+static inline int au_br_writable(int brperm)
1635+{
1636+ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1637+}
1638+
1639+static inline int au_br_whable(int brperm)
1640+{
1641+ return brperm == AuBrPerm_RW
1642+ || brperm == AuBrPerm_ROWH
1643+ || brperm == AuBrPerm_RRWH;
1644+}
1645+
1646+static inline int au_br_rdonly(struct au_branch *br)
1647+{
1648+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1649+ || !au_br_writable(br->br_perm))
1650+ ? -EROFS : 0;
1651+}
1652+
4a4d8108 1653+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 1654+{
4a4d8108 1655+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 1656+ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1657+#else
1658+ return 0;
1659+#endif
1660+}
1661+
1662+/* ---------------------------------------------------------------------- */
1663+
1664+/* branch.c */
1665+struct au_sbinfo;
1666+void au_br_free(struct au_sbinfo *sinfo);
1667+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1668+struct au_opt_add;
1669+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1670+struct au_opt_del;
1671+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
1672+struct au_opt_mod;
1673+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1674+ int *do_update);
1675+
1676+/* xino.c */
1677+static const loff_t au_loff_max = LLONG_MAX;
1678+
1679+int au_xib_trunc(struct super_block *sb);
1680+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1681+ loff_t *pos);
1682+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1683+ loff_t *pos);
1684+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
1685+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1686+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 1687+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 1688+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1689+ ino_t ino);
1690+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1691+ ino_t *ino);
1692+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1693+ struct file *base_file, int do_test);
1694+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1695+
1696+struct au_opt_xino;
1697+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1698+void au_xino_clr(struct super_block *sb);
1699+struct file *au_xino_def(struct super_block *sb);
1700+int au_xino_path(struct seq_file *seq, struct file *file);
1701+
1702+/* ---------------------------------------------------------------------- */
1703+
1704+/* Superblock to branch */
1705+static inline
1706+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1707+{
1708+ return au_sbr(sb, bindex)->br_id;
1709+}
1710+
1711+static inline
1712+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1713+{
1714+ return au_sbr(sb, bindex)->br_mnt;
1715+}
1716+
1717+static inline
1718+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1719+{
1720+ return au_sbr_mnt(sb, bindex)->mnt_sb;
1721+}
1722+
1723+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1724+{
953406b4 1725+ atomic_dec_return(&au_sbr(sb, bindex)->br_count);
1facf9fc 1726+}
1727+
1728+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1729+{
1730+ return au_sbr(sb, bindex)->br_perm;
1731+}
1732+
1733+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1734+{
1735+ return au_br_whable(au_sbr_perm(sb, bindex));
1736+}
1737+
1738+/* ---------------------------------------------------------------------- */
1739+
1740+/*
1741+ * wbr_wh_read_lock, wbr_wh_write_lock
1742+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
1743+ */
1744+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
1745+
dece6358
AM
1746+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
1747+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
1748+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
1749+
1facf9fc 1750+#endif /* __KERNEL__ */
1751+#endif /* __AUFS_BRANCH_H__ */
b752ccd1
AM
1752diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
1753--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
1754+++ linux/fs/aufs/conf.mk 2010-10-21 09:52:43.086957936 +0200
1755@@ -0,0 +1,36 @@
4a4d8108
AM
1756+
1757+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
1758+
1759+define AuConf
1760+ifdef ${1}
1761+AuConfStr += ${1}=${${1}}
1762+endif
1763+endef
1764+
b752ccd1 1765+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
953406b4 1766+ HNOTIFY HFSNOTIFY \
4a4d8108
AM
1767+ EXPORT INO_T_64 \
1768+ RDU \
1769+ SP_IATTR \
1770+ SHWH \
1771+ BR_RAMFS \
1772+ BR_FUSE POLL \
1773+ BR_HFSPLUS \
1774+ BDEV_LOOP \
b752ccd1
AM
1775+ DEBUG MAGIC_SYSRQ
1776+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
1777+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
1778+
1779+AuConfName = ${obj}/conf.str
1780+${AuConfName}.tmp: FORCE
1781+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
1782+${AuConfName}: ${AuConfName}.tmp
1783+ @diff -q $< $@ > /dev/null 2>&1 || { \
1784+ echo ' GEN ' $@; \
1785+ cp -p $< $@; \
1786+ }
1787+FORCE:
1788+clean-files += ${AuConfName} ${AuConfName}.tmp
1789+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
1790+
1791+-include ${srctree}/${src}/conf_priv.mk
1792diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
1793--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
953406b4 1794+++ linux/fs/aufs/cpup.c 2010-10-21 09:52:43.086957936 +0200
b752ccd1 1795@@ -0,0 +1,1059 @@
1facf9fc 1796+/*
4a4d8108 1797+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1798+ *
1799+ * This program, aufs is free software; you can redistribute it and/or modify
1800+ * it under the terms of the GNU General Public License as published by
1801+ * the Free Software Foundation; either version 2 of the License, or
1802+ * (at your option) any later version.
dece6358
AM
1803+ *
1804+ * This program is distributed in the hope that it will be useful,
1805+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1806+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1807+ * GNU General Public License for more details.
1808+ *
1809+ * You should have received a copy of the GNU General Public License
1810+ * along with this program; if not, write to the Free Software
1811+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1812+ */
1813+
1814+/*
1815+ * copy-up functions, see wbr_policy.c for copy-down
1816+ */
1817+
dece6358 1818+#include <linux/file.h>
1facf9fc 1819+#include <linux/fs_stack.h>
dece6358 1820+#include <linux/mm.h>
1facf9fc 1821+#include <linux/uaccess.h>
1822+#include "aufs.h"
1823+
1824+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
1825+{
1826+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
1827+ | S_NOATIME | S_NOCMTIME;
1828+
1829+ dst->i_flags |= src->i_flags & ~mask;
1830+ if (au_test_fs_notime(dst->i_sb))
1831+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
1832+}
1833+
1834+void au_cpup_attr_timesizes(struct inode *inode)
1835+{
1836+ struct inode *h_inode;
1837+
1838+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1839+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 1840+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 1841+}
1842+
1843+void au_cpup_attr_nlink(struct inode *inode, int force)
1844+{
1845+ struct inode *h_inode;
1846+ struct super_block *sb;
1847+ aufs_bindex_t bindex, bend;
1848+
1849+ sb = inode->i_sb;
1850+ bindex = au_ibstart(inode);
1851+ h_inode = au_h_iptr(inode, bindex);
1852+ if (!force
1853+ && !S_ISDIR(h_inode->i_mode)
1854+ && au_opt_test(au_mntflags(sb), PLINK)
1855+ && au_plink_test(inode))
1856+ return;
1857+
1858+ inode->i_nlink = h_inode->i_nlink;
1859+
1860+ /*
1861+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
1862+ * it may includes whplink directory.
1863+ */
1864+ if (S_ISDIR(h_inode->i_mode)) {
1865+ bend = au_ibend(inode);
1866+ for (bindex++; bindex <= bend; bindex++) {
1867+ h_inode = au_h_iptr(inode, bindex);
1868+ if (h_inode)
1869+ au_add_nlink(inode, h_inode);
1870+ }
1871+ }
1872+}
1873+
1874+void au_cpup_attr_changeable(struct inode *inode)
1875+{
1876+ struct inode *h_inode;
1877+
1878+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1879+ inode->i_mode = h_inode->i_mode;
1880+ inode->i_uid = h_inode->i_uid;
1881+ inode->i_gid = h_inode->i_gid;
1882+ au_cpup_attr_timesizes(inode);
1883+ au_cpup_attr_flags(inode, h_inode);
1884+}
1885+
1886+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
1887+{
1888+ struct au_iinfo *iinfo = au_ii(inode);
1889+
1308ab2a 1890+ IiMustWriteLock(inode);
1891+
1facf9fc 1892+ iinfo->ii_higen = h_inode->i_generation;
1893+ iinfo->ii_hsb1 = h_inode->i_sb;
1894+}
1895+
1896+void au_cpup_attr_all(struct inode *inode, int force)
1897+{
1898+ struct inode *h_inode;
1899+
1900+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1901+ au_cpup_attr_changeable(inode);
1902+ if (inode->i_nlink > 0)
1903+ au_cpup_attr_nlink(inode, force);
1904+ inode->i_rdev = h_inode->i_rdev;
1905+ inode->i_blkbits = h_inode->i_blkbits;
1906+ au_cpup_igen(inode, h_inode);
1907+}
1908+
1909+/* ---------------------------------------------------------------------- */
1910+
1911+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
1912+
1913+/* keep the timestamps of the parent dir when cpup */
1914+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
1915+ struct path *h_path)
1916+{
1917+ struct inode *h_inode;
1918+
1919+ dt->dt_dentry = dentry;
1920+ dt->dt_h_path = *h_path;
1921+ h_inode = h_path->dentry->d_inode;
1922+ dt->dt_atime = h_inode->i_atime;
1923+ dt->dt_mtime = h_inode->i_mtime;
1924+ /* smp_mb(); */
1925+}
1926+
1927+void au_dtime_revert(struct au_dtime *dt)
1928+{
1929+ struct iattr attr;
1930+ int err;
1931+
1932+ attr.ia_atime = dt->dt_atime;
1933+ attr.ia_mtime = dt->dt_mtime;
1934+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
1935+ | ATTR_ATIME | ATTR_ATIME_SET;
1936+
1937+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
1938+ if (unlikely(err))
4a4d8108 1939+ pr_warning("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 1940+}
1941+
1942+/* ---------------------------------------------------------------------- */
1943+
1944+static noinline_for_stack
1945+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
1946+{
1947+ int err, sbits;
1948+ struct iattr ia;
1949+ struct path h_path;
1308ab2a 1950+ struct inode *h_isrc, *h_idst;
1facf9fc 1951+
1952+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 1953+ h_idst = h_path.dentry->d_inode;
1facf9fc 1954+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
1955+ h_isrc = h_src->d_inode;
1308ab2a 1956+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 1957+ | ATTR_ATIME | ATTR_MTIME
1958+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 1959+ ia.ia_uid = h_isrc->i_uid;
1960+ ia.ia_gid = h_isrc->i_gid;
1961+ ia.ia_atime = h_isrc->i_atime;
1962+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 1963+ if (h_idst->i_mode != h_isrc->i_mode
1964+ && !S_ISLNK(h_idst->i_mode)) {
1965+ ia.ia_valid |= ATTR_MODE;
1966+ ia.ia_mode = h_isrc->i_mode;
1967+ }
1968+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
1969+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 1970+ err = vfsub_notify_change(&h_path, &ia);
1971+
1972+ /* is this nfs only? */
1973+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
1974+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
1975+ ia.ia_mode = h_isrc->i_mode;
1976+ err = vfsub_notify_change(&h_path, &ia);
1977+ }
1978+
1979+ return err;
1980+}
1981+
1982+/* ---------------------------------------------------------------------- */
1983+
1984+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
1985+ char *buf, unsigned long blksize)
1986+{
1987+ int err;
1988+ size_t sz, rbytes, wbytes;
1989+ unsigned char all_zero;
1990+ char *p, *zp;
1991+ struct mutex *h_mtx;
1992+ /* reduce stack usage */
1993+ struct iattr *ia;
1994+
1995+ zp = page_address(ZERO_PAGE(0));
1996+ if (unlikely(!zp))
1997+ return -ENOMEM; /* possible? */
1998+
1999+ err = 0;
2000+ all_zero = 0;
2001+ while (len) {
2002+ AuDbg("len %lld\n", len);
2003+ sz = blksize;
2004+ if (len < blksize)
2005+ sz = len;
2006+
2007+ rbytes = 0;
2008+ /* todo: signal_pending? */
2009+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
2010+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
2011+ err = rbytes;
2012+ }
2013+ if (unlikely(err < 0))
2014+ break;
2015+
2016+ all_zero = 0;
2017+ if (len >= rbytes && rbytes == blksize)
2018+ all_zero = !memcmp(buf, zp, rbytes);
2019+ if (!all_zero) {
2020+ wbytes = rbytes;
2021+ p = buf;
2022+ while (wbytes) {
2023+ size_t b;
2024+
2025+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
2026+ err = b;
2027+ /* todo: signal_pending? */
2028+ if (unlikely(err == -EAGAIN || err == -EINTR))
2029+ continue;
2030+ if (unlikely(err < 0))
2031+ break;
2032+ wbytes -= b;
2033+ p += b;
2034+ }
2035+ } else {
2036+ loff_t res;
2037+
2038+ AuLabel(hole);
2039+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
2040+ err = res;
2041+ if (unlikely(res < 0))
2042+ break;
2043+ }
2044+ len -= rbytes;
2045+ err = 0;
2046+ }
2047+
2048+ /* the last block may be a hole */
2049+ if (!err && all_zero) {
2050+ AuLabel(last hole);
2051+
2052+ err = 1;
2053+ if (au_test_nfs(dst->f_dentry->d_sb)) {
2054+ /* nfs requires this step to make last hole */
2055+ /* is this only nfs? */
2056+ do {
2057+ /* todo: signal_pending? */
2058+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
2059+ } while (err == -EAGAIN || err == -EINTR);
2060+ if (err == 1)
2061+ dst->f_pos--;
2062+ }
2063+
2064+ if (err == 1) {
2065+ ia = (void *)buf;
2066+ ia->ia_size = dst->f_pos;
2067+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
2068+ ia->ia_file = dst;
2069+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
2070+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
2071+ err = vfsub_notify_change(&dst->f_path, ia);
2072+ mutex_unlock(h_mtx);
2073+ }
2074+ }
2075+
2076+ return err;
2077+}
2078+
2079+int au_copy_file(struct file *dst, struct file *src, loff_t len)
2080+{
2081+ int err;
2082+ unsigned long blksize;
2083+ unsigned char do_kfree;
2084+ char *buf;
2085+
2086+ err = -ENOMEM;
2087+ blksize = dst->f_dentry->d_sb->s_blocksize;
2088+ if (!blksize || PAGE_SIZE < blksize)
2089+ blksize = PAGE_SIZE;
2090+ AuDbg("blksize %lu\n", blksize);
2091+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
2092+ if (do_kfree)
2093+ buf = kmalloc(blksize, GFP_NOFS);
2094+ else
2095+ buf = (void *)__get_free_page(GFP_NOFS);
2096+ if (unlikely(!buf))
2097+ goto out;
2098+
2099+ if (len > (1 << 22))
2100+ AuDbg("copying a large file %lld\n", (long long)len);
2101+
2102+ src->f_pos = 0;
2103+ dst->f_pos = 0;
2104+ err = au_do_copy_file(dst, src, len, buf, blksize);
2105+ if (do_kfree)
2106+ kfree(buf);
2107+ else
2108+ free_page((unsigned long)buf);
2109+
4f0767ce 2110+out:
1facf9fc 2111+ return err;
2112+}
2113+
2114+/*
2115+ * to support a sparse file which is opened with O_APPEND,
2116+ * we need to close the file.
2117+ */
2118+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 2119+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 2120+{
2121+ int err, i;
2122+ enum { SRC, DST };
2123+ struct {
2124+ aufs_bindex_t bindex;
2125+ unsigned int flags;
2126+ struct dentry *dentry;
2127+ struct file *file;
2128+ void *label, *label_file;
2129+ } *f, file[] = {
2130+ {
2131+ .bindex = bsrc,
2132+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
2133+ .file = NULL,
2134+ .label = &&out,
2135+ .label_file = &&out_src
2136+ },
2137+ {
2138+ .bindex = bdst,
2139+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
2140+ .file = NULL,
2141+ .label = &&out_src,
2142+ .label_file = &&out_dst
2143+ }
2144+ };
2145+ struct super_block *sb;
2146+
2147+ /* bsrc branch can be ro/rw. */
2148+ sb = dentry->d_sb;
2149+ f = file;
2150+ for (i = 0; i < 2; i++, f++) {
2151+ f->dentry = au_h_dptr(dentry, f->bindex);
2152+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
2153+ err = PTR_ERR(f->file);
2154+ if (IS_ERR(f->file))
2155+ goto *f->label;
2156+ err = -EINVAL;
2157+ if (unlikely(!f->file->f_op))
2158+ goto *f->label_file;
2159+ }
2160+
2161+ /* try stopping to update while we copyup */
2162+ IMustLock(file[SRC].dentry->d_inode);
2163+ err = au_copy_file(file[DST].file, file[SRC].file, len);
2164+
4f0767ce 2165+out_dst:
1facf9fc 2166+ fput(file[DST].file);
2167+ au_sbr_put(sb, file[DST].bindex);
4f0767ce 2168+out_src:
1facf9fc 2169+ fput(file[SRC].file);
2170+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 2171+out:
1facf9fc 2172+ return err;
2173+}
2174+
2175+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
2176+ aufs_bindex_t bsrc, loff_t len,
2177+ struct inode *h_dir, struct path *h_path)
2178+{
2179+ int err, rerr;
2180+ loff_t l;
2181+
2182+ err = 0;
2183+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
2184+ if (len == -1 || l < len)
2185+ len = l;
2186+ if (len)
2187+ err = au_cp_regular(dentry, bdst, bsrc, len);
2188+ if (!err)
2189+ goto out; /* success */
2190+
2191+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
2192+ if (rerr) {
2193+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
2194+ AuDLNPair(h_path->dentry), err, rerr);
2195+ err = -EIO;
2196+ }
2197+
4f0767ce 2198+out:
1facf9fc 2199+ return err;
2200+}
2201+
2202+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
2203+ struct inode *h_dir)
2204+{
2205+ int err, symlen;
2206+ mm_segment_t old_fs;
b752ccd1
AM
2207+ union {
2208+ char *k;
2209+ char __user *u;
2210+ } sym;
1facf9fc 2211+
2212+ err = -ENOSYS;
2213+ if (unlikely(!h_src->d_inode->i_op->readlink))
2214+ goto out;
2215+
2216+ err = -ENOMEM;
b752ccd1
AM
2217+ sym.k = __getname_gfp(GFP_NOFS);
2218+ if (unlikely(!sym.k))
1facf9fc 2219+ goto out;
2220+
2221+ old_fs = get_fs();
2222+ set_fs(KERNEL_DS);
b752ccd1 2223+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 2224+ err = symlen;
2225+ set_fs(old_fs);
2226+
2227+ if (symlen > 0) {
b752ccd1
AM
2228+ sym.k[symlen] = 0;
2229+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 2230+ }
b752ccd1 2231+ __putname(sym.k);
1facf9fc 2232+
4f0767ce 2233+out:
1facf9fc 2234+ return err;
2235+}
2236+
2237+/* return with the lower dst inode is locked */
2238+static noinline_for_stack
2239+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
2240+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2241+ struct dentry *dst_parent)
2242+{
2243+ int err;
2244+ umode_t mode;
2245+ unsigned int mnt_flags;
2246+ unsigned char isdir;
2247+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
2248+ struct au_dtime dt;
2249+ struct path h_path;
2250+ struct dentry *h_src, *h_dst, *h_parent;
2251+ struct inode *h_inode, *h_dir;
2252+ struct super_block *sb;
2253+
2254+ /* bsrc branch can be ro/rw. */
2255+ h_src = au_h_dptr(dentry, bsrc);
2256+ h_inode = h_src->d_inode;
2257+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
2258+
2259+ /* try stopping to be referenced while we are creating */
2260+ h_dst = au_h_dptr(dentry, bdst);
2261+ h_parent = h_dst->d_parent; /* dir inode is locked */
2262+ h_dir = h_parent->d_inode;
2263+ IMustLock(h_dir);
2264+ AuDebugOn(h_parent != h_dst->d_parent);
2265+
2266+ sb = dentry->d_sb;
2267+ h_path.mnt = au_sbr_mnt(sb, bdst);
2268+ if (do_dt) {
2269+ h_path.dentry = h_parent;
2270+ au_dtime_store(&dt, dst_parent, &h_path);
2271+ }
2272+ h_path.dentry = h_dst;
2273+
2274+ isdir = 0;
2275+ mode = h_inode->i_mode;
2276+ switch (mode & S_IFMT) {
2277+ case S_IFREG:
2278+ /* try stopping to update while we are referencing */
2279+ IMustLock(h_inode);
2280+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
2281+ if (!err)
2282+ err = au_do_cpup_regular
2283+ (dentry, bdst, bsrc, len,
2284+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
2285+ break;
2286+ case S_IFDIR:
2287+ isdir = 1;
2288+ err = vfsub_mkdir(h_dir, &h_path, mode);
2289+ if (!err) {
2290+ /*
2291+ * strange behaviour from the users view,
2292+ * particularry setattr case
2293+ */
2294+ if (au_ibstart(dst_parent->d_inode) == bdst)
2295+ au_cpup_attr_nlink(dst_parent->d_inode,
2296+ /*force*/1);
2297+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
2298+ }
2299+ break;
2300+ case S_IFLNK:
2301+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
2302+ break;
2303+ case S_IFCHR:
2304+ case S_IFBLK:
2305+ AuDebugOn(!capable(CAP_MKNOD));
2306+ /*FALLTHROUGH*/
2307+ case S_IFIFO:
2308+ case S_IFSOCK:
2309+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
2310+ break;
2311+ default:
2312+ AuIOErr("Unknown inode type 0%o\n", mode);
2313+ err = -EIO;
2314+ }
2315+
2316+ mnt_flags = au_mntflags(sb);
2317+ if (!au_opt_test(mnt_flags, UDBA_NONE)
2318+ && !isdir
2319+ && au_opt_test(mnt_flags, XINO)
2320+ && h_inode->i_nlink == 1
2321+ /* todo: unnecessary? */
2322+ /* && dentry->d_inode->i_nlink == 1 */
2323+ && bdst < bsrc
2324+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 2325+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 2326+ /* ignore this error */
2327+
2328+ if (do_dt)
2329+ au_dtime_revert(&dt);
2330+ return err;
2331+}
2332+
2333+/*
2334+ * copyup the @dentry from @bsrc to @bdst.
2335+ * the caller must set the both of lower dentries.
2336+ * @len is for truncating when it is -1 copyup the entire file.
2337+ * in link/rename cases, @dst_parent may be different from the real one.
2338+ */
2339+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2340+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2341+ struct dentry *dst_parent)
2342+{
2343+ int err, rerr;
2344+ aufs_bindex_t old_ibstart;
2345+ unsigned char isdir, plink;
2346+ struct au_dtime dt;
2347+ struct path h_path;
2348+ struct dentry *h_src, *h_dst, *h_parent;
2349+ struct inode *dst_inode, *h_dir, *inode;
2350+ struct super_block *sb;
2351+
2352+ AuDebugOn(bsrc <= bdst);
2353+
2354+ sb = dentry->d_sb;
2355+ h_path.mnt = au_sbr_mnt(sb, bdst);
2356+ h_dst = au_h_dptr(dentry, bdst);
2357+ h_parent = h_dst->d_parent; /* dir inode is locked */
2358+ h_dir = h_parent->d_inode;
2359+ IMustLock(h_dir);
2360+
2361+ h_src = au_h_dptr(dentry, bsrc);
2362+ inode = dentry->d_inode;
2363+
2364+ if (!dst_parent)
2365+ dst_parent = dget_parent(dentry);
2366+ else
2367+ dget(dst_parent);
2368+
2369+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
2370+ dst_inode = au_h_iptr(inode, bdst);
2371+ if (dst_inode) {
2372+ if (unlikely(!plink)) {
2373+ err = -EIO;
2374+ AuIOErr("i%lu exists on a upper branch "
2375+ "but plink is disabled\n", inode->i_ino);
2376+ goto out;
2377+ }
2378+
2379+ if (dst_inode->i_nlink) {
2380+ const int do_dt = au_ftest_cpup(flags, DTIME);
2381+
2382+ h_src = au_plink_lkup(inode, bdst);
2383+ err = PTR_ERR(h_src);
2384+ if (IS_ERR(h_src))
2385+ goto out;
2386+ if (unlikely(!h_src->d_inode)) {
2387+ err = -EIO;
2388+ AuIOErr("i%lu exists on a upper branch "
2389+ "but plink is broken\n", inode->i_ino);
2390+ dput(h_src);
2391+ goto out;
2392+ }
2393+
2394+ if (do_dt) {
2395+ h_path.dentry = h_parent;
2396+ au_dtime_store(&dt, dst_parent, &h_path);
2397+ }
2398+ h_path.dentry = h_dst;
2399+ err = vfsub_link(h_src, h_dir, &h_path);
2400+ if (do_dt)
2401+ au_dtime_revert(&dt);
2402+ dput(h_src);
2403+ goto out;
2404+ } else
2405+ /* todo: cpup_wh_file? */
2406+ /* udba work */
4a4d8108 2407+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 2408+ }
2409+
2410+ old_ibstart = au_ibstart(inode);
2411+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
2412+ if (unlikely(err))
2413+ goto out;
2414+ dst_inode = h_dst->d_inode;
2415+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
2416+
2417+ err = cpup_iattr(dentry, bdst, h_src);
2418+ isdir = S_ISDIR(dst_inode->i_mode);
2419+ if (!err) {
4a4d8108
AM
2420+ if (bdst < old_ibstart) {
2421+ if (S_ISREG(inode->i_mode)) {
2422+ err = au_dy_iaop(inode, bdst, dst_inode);
2423+ if (unlikely(err))
2424+ goto out_rev;
2425+ }
1facf9fc 2426+ au_set_ibstart(inode, bdst);
4a4d8108 2427+ }
1facf9fc 2428+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
2429+ au_hi_flags(inode, isdir));
2430+ mutex_unlock(&dst_inode->i_mutex);
2431+ if (!isdir
2432+ && h_src->d_inode->i_nlink > 1
2433+ && plink)
2434+ au_plink_append(inode, bdst, h_dst);
2435+ goto out; /* success */
2436+ }
2437+
2438+ /* revert */
4a4d8108 2439+out_rev:
1facf9fc 2440+ h_path.dentry = h_parent;
2441+ mutex_unlock(&dst_inode->i_mutex);
2442+ au_dtime_store(&dt, dst_parent, &h_path);
2443+ h_path.dentry = h_dst;
2444+ if (!isdir)
2445+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
2446+ else
2447+ rerr = vfsub_rmdir(h_dir, &h_path);
2448+ au_dtime_revert(&dt);
2449+ if (rerr) {
2450+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
2451+ err = -EIO;
2452+ }
2453+
4f0767ce 2454+out:
1facf9fc 2455+ dput(dst_parent);
2456+ return err;
2457+}
2458+
2459+struct au_cpup_single_args {
2460+ int *errp;
2461+ struct dentry *dentry;
2462+ aufs_bindex_t bdst, bsrc;
2463+ loff_t len;
2464+ unsigned int flags;
2465+ struct dentry *dst_parent;
2466+};
2467+
2468+static void au_call_cpup_single(void *args)
2469+{
2470+ struct au_cpup_single_args *a = args;
2471+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
2472+ a->flags, a->dst_parent);
2473+}
2474+
2475+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2476+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2477+ struct dentry *dst_parent)
2478+{
2479+ int err, wkq_err;
2480+ umode_t mode;
2481+ struct dentry *h_dentry;
2482+
2483+ h_dentry = au_h_dptr(dentry, bsrc);
2484+ mode = h_dentry->d_inode->i_mode & S_IFMT;
2485+ if ((mode != S_IFCHR && mode != S_IFBLK)
2486+ || capable(CAP_MKNOD))
2487+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2488+ dst_parent);
2489+ else {
2490+ struct au_cpup_single_args args = {
2491+ .errp = &err,
2492+ .dentry = dentry,
2493+ .bdst = bdst,
2494+ .bsrc = bsrc,
2495+ .len = len,
2496+ .flags = flags,
2497+ .dst_parent = dst_parent
2498+ };
2499+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
2500+ if (unlikely(wkq_err))
2501+ err = wkq_err;
2502+ }
2503+
2504+ return err;
2505+}
2506+
2507+/*
2508+ * copyup the @dentry from the first active lower branch to @bdst,
2509+ * using au_cpup_single().
2510+ */
2511+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2512+ unsigned int flags)
2513+{
2514+ int err;
2515+ aufs_bindex_t bsrc, bend;
2516+
2517+ bend = au_dbend(dentry);
2518+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2519+ if (au_h_dptr(dentry, bsrc))
2520+ break;
2521+
2522+ err = au_lkup_neg(dentry, bdst);
2523+ if (!err) {
2524+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
2525+ if (!err)
2526+ return 0; /* success */
2527+
2528+ /* revert */
2529+ au_set_h_dptr(dentry, bdst, NULL);
2530+ au_set_dbstart(dentry, bsrc);
2531+ }
2532+
2533+ return err;
2534+}
2535+
2536+struct au_cpup_simple_args {
2537+ int *errp;
2538+ struct dentry *dentry;
2539+ aufs_bindex_t bdst;
2540+ loff_t len;
2541+ unsigned int flags;
2542+};
2543+
2544+static void au_call_cpup_simple(void *args)
2545+{
2546+ struct au_cpup_simple_args *a = args;
2547+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
2548+}
2549+
2550+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2551+ unsigned int flags)
2552+{
2553+ int err, wkq_err;
2554+ unsigned char do_sio;
2555+ struct dentry *parent;
2556+ struct inode *h_dir;
2557+
2558+ parent = dget_parent(dentry);
2559+ h_dir = au_h_iptr(parent->d_inode, bdst);
2560+ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
2561+ if (!do_sio) {
2562+ /*
2563+ * testing CAP_MKNOD is for generic fs,
2564+ * but CAP_FSETID is for xfs only, currently.
2565+ */
2566+ umode_t mode = dentry->d_inode->i_mode;
2567+ do_sio = (((mode & (S_IFCHR | S_IFBLK))
2568+ && !capable(CAP_MKNOD))
2569+ || ((mode & (S_ISUID | S_ISGID))
2570+ && !capable(CAP_FSETID)));
2571+ }
2572+ if (!do_sio)
2573+ err = au_cpup_simple(dentry, bdst, len, flags);
2574+ else {
2575+ struct au_cpup_simple_args args = {
2576+ .errp = &err,
2577+ .dentry = dentry,
2578+ .bdst = bdst,
2579+ .len = len,
2580+ .flags = flags
2581+ };
2582+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
2583+ if (unlikely(wkq_err))
2584+ err = wkq_err;
2585+ }
2586+
2587+ dput(parent);
2588+ return err;
2589+}
2590+
2591+/* ---------------------------------------------------------------------- */
2592+
2593+/*
2594+ * copyup the deleted file for writing.
2595+ */
2596+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2597+ struct dentry *wh_dentry, struct file *file,
2598+ loff_t len)
2599+{
2600+ int err;
2601+ aufs_bindex_t bstart;
2602+ struct au_dinfo *dinfo;
2603+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 2604+ struct au_hdentry *hdp;
1facf9fc 2605+
2606+ dinfo = au_di(dentry);
1308ab2a 2607+ AuRwMustWriteLock(&dinfo->di_rwsem);
2608+
1facf9fc 2609+ bstart = dinfo->di_bstart;
4a4d8108
AM
2610+ hdp = dinfo->di_hdentry;
2611+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 2612+ dinfo->di_bstart = bdst;
4a4d8108
AM
2613+ hdp[0 + bdst].hd_dentry = wh_dentry;
2614+ h_d_start = hdp[0 + bstart].hd_dentry;
1facf9fc 2615+ if (file)
4a4d8108 2616+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2617+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2618+ /*h_parent*/NULL);
2619+ if (!err && file) {
2620+ err = au_reopen_nondir(file);
4a4d8108 2621+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 2622+ }
4a4d8108 2623+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 2624+ dinfo->di_bstart = bstart;
2625+
2626+ return err;
2627+}
2628+
2629+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2630+ struct file *file)
2631+{
2632+ int err;
2633+ struct au_dtime dt;
2634+ struct dentry *parent, *h_parent, *wh_dentry;
2635+ struct au_branch *br;
2636+ struct path h_path;
2637+
2638+ br = au_sbr(dentry->d_sb, bdst);
2639+ parent = dget_parent(dentry);
2640+ h_parent = au_h_dptr(parent, bdst);
2641+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
2642+ err = PTR_ERR(wh_dentry);
2643+ if (IS_ERR(wh_dentry))
2644+ goto out;
2645+
2646+ h_path.dentry = h_parent;
2647+ h_path.mnt = br->br_mnt;
2648+ au_dtime_store(&dt, parent, &h_path);
2649+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
2650+ if (unlikely(err))
2651+ goto out_wh;
2652+
2653+ dget(wh_dentry);
2654+ h_path.dentry = wh_dentry;
4a4d8108
AM
2655+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
2656+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
2657+ else
2658+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 2659+ if (unlikely(err)) {
2660+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2661+ AuDLNPair(wh_dentry), err);
2662+ err = -EIO;
2663+ }
2664+ au_dtime_revert(&dt);
2665+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2666+
4f0767ce 2667+out_wh:
1facf9fc 2668+ dput(wh_dentry);
4f0767ce 2669+out:
1facf9fc 2670+ dput(parent);
2671+ return err;
2672+}
2673+
2674+struct au_cpup_wh_args {
2675+ int *errp;
2676+ struct dentry *dentry;
2677+ aufs_bindex_t bdst;
2678+ loff_t len;
2679+ struct file *file;
2680+};
2681+
2682+static void au_call_cpup_wh(void *args)
2683+{
2684+ struct au_cpup_wh_args *a = args;
2685+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
2686+}
2687+
2688+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2689+ struct file *file)
2690+{
2691+ int err, wkq_err;
2692+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
2693+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
2694+ struct au_wbr *wbr;
2695+
2696+ parent = dget_parent(dentry);
2697+ dir = parent->d_inode;
2698+ h_orph = NULL;
2699+ h_parent = NULL;
2700+ h_dir = au_igrab(au_h_iptr(dir, bdst));
2701+ h_tmpdir = h_dir;
2702+ if (!h_dir->i_nlink) {
2703+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
2704+ h_orph = wbr->wbr_orph;
2705+
2706+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 2707+ au_set_h_dptr(parent, bdst, dget(h_orph));
2708+ h_tmpdir = h_orph->d_inode;
1facf9fc 2709+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
2710+
2711+ /* this temporary unlock is safe */
2712+ if (file)
4a4d8108 2713+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2714+ else
2715+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
2716+ h_inode = h_dentry->d_inode;
2717+ IMustLock(h_inode);
2718+ mutex_unlock(&h_inode->i_mutex);
dece6358 2719+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 2720+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 2721+ /* todo: au_h_open_pre()? */
1facf9fc 2722+ }
2723+
2724+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
2725+ err = au_cpup_wh(dentry, bdst, len, file);
2726+ else {
2727+ struct au_cpup_wh_args args = {
2728+ .errp = &err,
2729+ .dentry = dentry,
2730+ .bdst = bdst,
2731+ .len = len,
2732+ .file = file
2733+ };
2734+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
2735+ if (unlikely(wkq_err))
2736+ err = wkq_err;
2737+ }
2738+
2739+ if (h_orph) {
2740+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 2741+ /* todo: au_h_open_post()? */
1facf9fc 2742+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 2743+ au_set_h_dptr(parent, bdst, h_parent);
2744+ }
2745+ iput(h_dir);
2746+ dput(parent);
2747+
2748+ return err;
2749+}
2750+
2751+/* ---------------------------------------------------------------------- */
2752+
2753+/*
2754+ * generic routine for both of copy-up and copy-down.
2755+ */
2756+/* cf. revalidate function in file.c */
2757+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2758+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2759+ struct dentry *h_parent, void *arg),
2760+ void *arg)
2761+{
2762+ int err;
2763+ struct au_pin pin;
2764+ struct dentry *d, *parent, *h_parent, *real_parent;
2765+
2766+ err = 0;
2767+ parent = dget_parent(dentry);
2768+ if (IS_ROOT(parent))
2769+ goto out;
2770+
2771+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
2772+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
2773+
2774+ /* do not use au_dpage */
2775+ real_parent = parent;
2776+ while (1) {
2777+ dput(parent);
2778+ parent = dget_parent(dentry);
2779+ h_parent = au_h_dptr(parent, bdst);
2780+ if (h_parent)
2781+ goto out; /* success */
2782+
2783+ /* find top dir which is necessary to cpup */
2784+ do {
2785+ d = parent;
2786+ dput(parent);
2787+ parent = dget_parent(d);
2788+ di_read_lock_parent3(parent, !AuLock_IR);
2789+ h_parent = au_h_dptr(parent, bdst);
2790+ di_read_unlock(parent, !AuLock_IR);
2791+ } while (!h_parent);
2792+
2793+ if (d != real_parent)
2794+ di_write_lock_child3(d);
2795+
2796+ /* somebody else might create while we were sleeping */
2797+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
2798+ if (au_h_dptr(d, bdst))
2799+ au_update_dbstart(d);
2800+
2801+ au_pin_set_dentry(&pin, d);
2802+ err = au_do_pin(&pin);
2803+ if (!err) {
2804+ err = cp(d, bdst, h_parent, arg);
2805+ au_unpin(&pin);
2806+ }
2807+ }
2808+
2809+ if (d != real_parent)
2810+ di_write_unlock(d);
2811+ if (unlikely(err))
2812+ break;
2813+ }
2814+
4f0767ce 2815+out:
1facf9fc 2816+ dput(parent);
2817+ return err;
2818+}
2819+
2820+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
2821+ struct dentry *h_parent __maybe_unused ,
2822+ void *arg __maybe_unused)
2823+{
2824+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
2825+}
2826+
2827+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2828+{
2829+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
2830+}
2831+
2832+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2833+{
2834+ int err;
2835+ struct dentry *parent;
2836+ struct inode *dir;
2837+
2838+ parent = dget_parent(dentry);
2839+ dir = parent->d_inode;
2840+ err = 0;
2841+ if (au_h_iptr(dir, bdst))
2842+ goto out;
2843+
2844+ di_read_unlock(parent, AuLock_IR);
2845+ di_write_lock_parent(parent);
2846+ /* someone else might change our inode while we were sleeping */
2847+ if (!au_h_iptr(dir, bdst))
2848+ err = au_cpup_dirs(dentry, bdst);
2849+ di_downgrade_lock(parent, AuLock_IR);
2850+
4f0767ce 2851+out:
1facf9fc 2852+ dput(parent);
2853+ return err;
2854+}
b752ccd1
AM
2855diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
2856--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
953406b4 2857+++ linux/fs/aufs/cpup.h 2010-10-21 09:52:43.086957936 +0200
dece6358 2858@@ -0,0 +1,81 @@
1facf9fc 2859+/*
4a4d8108 2860+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2861+ *
2862+ * This program, aufs is free software; you can redistribute it and/or modify
2863+ * it under the terms of the GNU General Public License as published by
2864+ * the Free Software Foundation; either version 2 of the License, or
2865+ * (at your option) any later version.
dece6358
AM
2866+ *
2867+ * This program is distributed in the hope that it will be useful,
2868+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2869+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2870+ * GNU General Public License for more details.
2871+ *
2872+ * You should have received a copy of the GNU General Public License
2873+ * along with this program; if not, write to the Free Software
2874+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2875+ */
2876+
2877+/*
2878+ * copy-up/down functions
2879+ */
2880+
2881+#ifndef __AUFS_CPUP_H__
2882+#define __AUFS_CPUP_H__
2883+
2884+#ifdef __KERNEL__
2885+
dece6358
AM
2886+#include <linux/path.h>
2887+#include <linux/time.h>
1facf9fc 2888+#include <linux/aufs_type.h>
2889+
dece6358
AM
2890+struct inode;
2891+struct file;
2892+
1facf9fc 2893+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
2894+void au_cpup_attr_timesizes(struct inode *inode);
2895+void au_cpup_attr_nlink(struct inode *inode, int force);
2896+void au_cpup_attr_changeable(struct inode *inode);
2897+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
2898+void au_cpup_attr_all(struct inode *inode, int force);
2899+
2900+/* ---------------------------------------------------------------------- */
2901+
2902+/* cpup flags */
2903+#define AuCpup_DTIME 1 /* do dtime_store/revert */
2904+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
2905+ for link(2) */
2906+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
2907+#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; }
2908+#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; }
2909+
2910+int au_copy_file(struct file *dst, struct file *src, loff_t len);
2911+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2912+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2913+ struct dentry *dst_parent);
2914+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2915+ unsigned int flags);
2916+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2917+ struct file *file);
2918+
2919+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2920+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2921+ struct dentry *h_parent, void *arg),
2922+ void *arg);
2923+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2924+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2925+
2926+/* ---------------------------------------------------------------------- */
2927+
2928+/* keep timestamps when copyup */
2929+struct au_dtime {
2930+ struct dentry *dt_dentry;
2931+ struct path dt_h_path;
2932+ struct timespec dt_atime, dt_mtime;
2933+};
2934+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
2935+ struct path *h_path);
2936+void au_dtime_revert(struct au_dtime *dt);
2937+
2938+#endif /* __KERNEL__ */
2939+#endif /* __AUFS_CPUP_H__ */
b752ccd1
AM
2940diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
2941--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
953406b4 2942+++ linux/fs/aufs/dbgaufs.c 2010-10-21 09:52:43.086957936 +0200
4a4d8108 2943@@ -0,0 +1,334 @@
1facf9fc 2944+/*
4a4d8108 2945+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2946+ *
2947+ * This program, aufs is free software; you can redistribute it and/or modify
2948+ * it under the terms of the GNU General Public License as published by
2949+ * the Free Software Foundation; either version 2 of the License, or
2950+ * (at your option) any later version.
dece6358
AM
2951+ *
2952+ * This program is distributed in the hope that it will be useful,
2953+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2954+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2955+ * GNU General Public License for more details.
2956+ *
2957+ * You should have received a copy of the GNU General Public License
2958+ * along with this program; if not, write to the Free Software
2959+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2960+ */
2961+
2962+/*
2963+ * debugfs interface
2964+ */
2965+
2966+#include <linux/debugfs.h>
2967+#include "aufs.h"
2968+
2969+#ifndef CONFIG_SYSFS
2970+#error DEBUG_FS depends upon SYSFS
2971+#endif
2972+
2973+static struct dentry *dbgaufs;
2974+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
2975+
2976+/* 20 is max digits length of ulong 64 */
2977+struct dbgaufs_arg {
2978+ int n;
2979+ char a[20 * 4];
2980+};
2981+
2982+/*
2983+ * common function for all XINO files
2984+ */
2985+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
2986+ struct file *file)
2987+{
2988+ kfree(file->private_data);
2989+ return 0;
2990+}
2991+
2992+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
2993+{
2994+ int err;
2995+ struct kstat st;
2996+ struct dbgaufs_arg *p;
2997+
2998+ err = -ENOMEM;
2999+ p = kmalloc(sizeof(*p), GFP_NOFS);
3000+ if (unlikely(!p))
3001+ goto out;
3002+
3003+ err = 0;
3004+ p->n = 0;
3005+ file->private_data = p;
3006+ if (!xf)
3007+ goto out;
3008+
3009+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
3010+ if (!err) {
3011+ if (do_fcnt)
3012+ p->n = snprintf
3013+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
3014+ (long)file_count(xf), st.blocks, st.blksize,
3015+ (long long)st.size);
3016+ else
3017+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
3018+ st.blocks, st.blksize,
3019+ (long long)st.size);
3020+ AuDebugOn(p->n >= sizeof(p->a));
3021+ } else {
3022+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
3023+ err = 0;
3024+ }
3025+
4f0767ce 3026+out:
1facf9fc 3027+ return err;
3028+
3029+}
3030+
3031+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
3032+ size_t count, loff_t *ppos)
3033+{
3034+ struct dbgaufs_arg *p;
3035+
3036+ p = file->private_data;
3037+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
3038+}
3039+
3040+/* ---------------------------------------------------------------------- */
3041+
3042+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
3043+{
3044+ int err;
3045+ struct au_sbinfo *sbinfo;
3046+ struct super_block *sb;
3047+
3048+ sbinfo = inode->i_private;
3049+ sb = sbinfo->si_sb;
3050+ si_noflush_read_lock(sb);
3051+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
3052+ si_read_unlock(sb);
3053+ return err;
3054+}
3055+
3056+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 3057+ .owner = THIS_MODULE,
1facf9fc 3058+ .open = dbgaufs_xib_open,
3059+ .release = dbgaufs_xi_release,
3060+ .read = dbgaufs_xi_read
3061+};
3062+
3063+/* ---------------------------------------------------------------------- */
3064+
3065+#define DbgaufsXi_PREFIX "xi"
3066+
3067+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
3068+{
3069+ int err;
3070+ long l;
3071+ struct au_sbinfo *sbinfo;
3072+ struct super_block *sb;
3073+ struct file *xf;
3074+ struct qstr *name;
3075+
3076+ err = -ENOENT;
3077+ xf = NULL;
3078+ name = &file->f_dentry->d_name;
3079+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
3080+ || memcmp(name->name, DbgaufsXi_PREFIX,
3081+ sizeof(DbgaufsXi_PREFIX) - 1)))
3082+ goto out;
3083+ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
3084+ if (unlikely(err))
3085+ goto out;
3086+
3087+ sbinfo = inode->i_private;
3088+ sb = sbinfo->si_sb;
3089+ si_noflush_read_lock(sb);
3090+ if (l <= au_sbend(sb)) {
3091+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
3092+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
3093+ } else
3094+ err = -ENOENT;
3095+ si_read_unlock(sb);
3096+
4f0767ce 3097+out:
1facf9fc 3098+ return err;
3099+}
3100+
3101+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 3102+ .owner = THIS_MODULE,
1facf9fc 3103+ .open = dbgaufs_xino_open,
3104+ .release = dbgaufs_xi_release,
3105+ .read = dbgaufs_xi_read
3106+};
3107+
3108+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
3109+{
3110+ aufs_bindex_t bend;
3111+ struct au_branch *br;
3112+ struct au_xino_file *xi;
3113+
3114+ if (!au_sbi(sb)->si_dbgaufs)
3115+ return;
3116+
3117+ bend = au_sbend(sb);
3118+ for (; bindex <= bend; bindex++) {
3119+ br = au_sbr(sb, bindex);
3120+ xi = &br->br_xino;
3121+ if (xi->xi_dbgaufs) {
3122+ debugfs_remove(xi->xi_dbgaufs);
3123+ xi->xi_dbgaufs = NULL;
3124+ }
3125+ }
3126+}
3127+
3128+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
3129+{
3130+ struct au_sbinfo *sbinfo;
3131+ struct dentry *parent;
3132+ struct au_branch *br;
3133+ struct au_xino_file *xi;
3134+ aufs_bindex_t bend;
3135+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
3136+
3137+ sbinfo = au_sbi(sb);
3138+ parent = sbinfo->si_dbgaufs;
3139+ if (!parent)
3140+ return;
3141+
3142+ bend = au_sbend(sb);
3143+ for (; bindex <= bend; bindex++) {
3144+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
3145+ br = au_sbr(sb, bindex);
3146+ xi = &br->br_xino;
3147+ AuDebugOn(xi->xi_dbgaufs);
3148+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
3149+ sbinfo, &dbgaufs_xino_fop);
3150+ /* ignore an error */
3151+ if (unlikely(!xi->xi_dbgaufs))
3152+ AuWarn1("failed %s under debugfs\n", name);
3153+ }
3154+}
3155+
3156+/* ---------------------------------------------------------------------- */
3157+
3158+#ifdef CONFIG_AUFS_EXPORT
3159+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
3160+{
3161+ int err;
3162+ struct au_sbinfo *sbinfo;
3163+ struct super_block *sb;
3164+
3165+ sbinfo = inode->i_private;
3166+ sb = sbinfo->si_sb;
3167+ si_noflush_read_lock(sb);
3168+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
3169+ si_read_unlock(sb);
3170+ return err;
3171+}
3172+
3173+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 3174+ .owner = THIS_MODULE,
1facf9fc 3175+ .open = dbgaufs_xigen_open,
3176+ .release = dbgaufs_xi_release,
3177+ .read = dbgaufs_xi_read
3178+};
3179+
3180+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3181+{
3182+ int err;
3183+
dece6358
AM
3184+ /*
3185+ * This function is a dynamic '__init' fucntion actually,
3186+ * so the tiny check for si_rwsem is unnecessary.
3187+ */
3188+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3189+
1facf9fc 3190+ err = -EIO;
3191+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
3192+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3193+ &dbgaufs_xigen_fop);
3194+ if (sbinfo->si_dbgaufs_xigen)
3195+ err = 0;
3196+
3197+ return err;
3198+}
3199+#else
3200+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3201+{
3202+ return 0;
3203+}
3204+#endif /* CONFIG_AUFS_EXPORT */
3205+
3206+/* ---------------------------------------------------------------------- */
3207+
3208+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
3209+{
dece6358
AM
3210+ /*
3211+ * This function is a dynamic '__init' fucntion actually,
3212+ * so the tiny check for si_rwsem is unnecessary.
3213+ */
3214+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3215+
1facf9fc 3216+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
3217+ sbinfo->si_dbgaufs = NULL;
3218+ kobject_put(&sbinfo->si_kobj);
3219+}
3220+
3221+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
3222+{
3223+ int err;
3224+ char name[SysaufsSiNameLen];
3225+
dece6358
AM
3226+ /*
3227+ * This function is a dynamic '__init' fucntion actually,
3228+ * so the tiny check for si_rwsem is unnecessary.
3229+ */
3230+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3231+
1facf9fc 3232+ err = -ENOENT;
3233+ if (!dbgaufs) {
3234+ AuErr1("/debug/aufs is uninitialized\n");
3235+ goto out;
3236+ }
3237+
3238+ err = -EIO;
3239+ sysaufs_name(sbinfo, name);
3240+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
3241+ if (unlikely(!sbinfo->si_dbgaufs))
3242+ goto out;
3243+ kobject_get(&sbinfo->si_kobj);
3244+
3245+ sbinfo->si_dbgaufs_xib = debugfs_create_file
3246+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3247+ &dbgaufs_xib_fop);
3248+ if (unlikely(!sbinfo->si_dbgaufs_xib))
3249+ goto out_dir;
3250+
3251+ err = dbgaufs_xigen_init(sbinfo);
3252+ if (!err)
3253+ goto out; /* success */
3254+
4f0767ce 3255+out_dir:
1facf9fc 3256+ dbgaufs_si_fin(sbinfo);
4f0767ce 3257+out:
1facf9fc 3258+ return err;
3259+}
3260+
3261+/* ---------------------------------------------------------------------- */
3262+
3263+void dbgaufs_fin(void)
3264+{
3265+ debugfs_remove(dbgaufs);
3266+}
3267+
3268+int __init dbgaufs_init(void)
3269+{
3270+ int err;
3271+
3272+ err = -EIO;
3273+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
3274+ if (dbgaufs)
3275+ err = 0;
3276+ return err;
3277+}
b752ccd1
AM
3278diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
3279--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
953406b4 3280+++ linux/fs/aufs/dbgaufs.h 2010-10-21 09:52:43.086957936 +0200
4a4d8108 3281@@ -0,0 +1,52 @@
1facf9fc 3282+/*
4a4d8108 3283+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3284+ *
3285+ * This program, aufs is free software; you can redistribute it and/or modify
3286+ * it under the terms of the GNU General Public License as published by
3287+ * the Free Software Foundation; either version 2 of the License, or
3288+ * (at your option) any later version.
dece6358
AM
3289+ *
3290+ * This program is distributed in the hope that it will be useful,
3291+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3292+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3293+ * GNU General Public License for more details.
3294+ *
3295+ * You should have received a copy of the GNU General Public License
3296+ * along with this program; if not, write to the Free Software
3297+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3298+ */
3299+
3300+/*
3301+ * debugfs interface
3302+ */
3303+
3304+#ifndef __DBGAUFS_H__
3305+#define __DBGAUFS_H__
3306+
3307+#ifdef __KERNEL__
3308+
dece6358 3309+#include <linux/init.h>
1facf9fc 3310+#include <linux/aufs_type.h>
3311+
dece6358 3312+struct super_block;
1facf9fc 3313+struct au_sbinfo;
dece6358 3314+
1facf9fc 3315+#ifdef CONFIG_DEBUG_FS
3316+/* dbgaufs.c */
3317+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
3318+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
3319+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
3320+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
3321+void dbgaufs_fin(void);
3322+int __init dbgaufs_init(void);
1facf9fc 3323+#else
4a4d8108
AM
3324+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
3325+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
3326+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
3327+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
3328+AuStubVoid(dbgaufs_fin, void)
3329+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 3330+#endif /* CONFIG_DEBUG_FS */
3331+
3332+#endif /* __KERNEL__ */
3333+#endif /* __DBGAUFS_H__ */
b752ccd1
AM
3334diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
3335--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
953406b4 3336+++ linux/fs/aufs/dcsub.c 2010-10-21 09:52:43.086957936 +0200
4a4d8108 3337@@ -0,0 +1,200 @@
1facf9fc 3338+/*
4a4d8108 3339+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3340+ *
3341+ * This program, aufs is free software; you can redistribute it and/or modify
3342+ * it under the terms of the GNU General Public License as published by
3343+ * the Free Software Foundation; either version 2 of the License, or
3344+ * (at your option) any later version.
dece6358
AM
3345+ *
3346+ * This program is distributed in the hope that it will be useful,
3347+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3348+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3349+ * GNU General Public License for more details.
3350+ *
3351+ * You should have received a copy of the GNU General Public License
3352+ * along with this program; if not, write to the Free Software
3353+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3354+ */
3355+
3356+/*
3357+ * sub-routines for dentry cache
3358+ */
3359+
3360+#include "aufs.h"
3361+
3362+static void au_dpage_free(struct au_dpage *dpage)
3363+{
3364+ int i;
3365+ struct dentry **p;
3366+
3367+ p = dpage->dentries;
3368+ for (i = 0; i < dpage->ndentry; i++)
3369+ dput(*p++);
3370+ free_page((unsigned long)dpage->dentries);
3371+}
3372+
3373+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
3374+{
3375+ int err;
3376+ void *p;
3377+
3378+ err = -ENOMEM;
3379+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
3380+ if (unlikely(!dpages->dpages))
3381+ goto out;
3382+
3383+ p = (void *)__get_free_page(gfp);
3384+ if (unlikely(!p))
3385+ goto out_dpages;
3386+
3387+ dpages->dpages[0].ndentry = 0;
3388+ dpages->dpages[0].dentries = p;
3389+ dpages->ndpage = 1;
3390+ return 0; /* success */
3391+
4f0767ce 3392+out_dpages:
1facf9fc 3393+ kfree(dpages->dpages);
4f0767ce 3394+out:
1facf9fc 3395+ return err;
3396+}
3397+
3398+void au_dpages_free(struct au_dcsub_pages *dpages)
3399+{
3400+ int i;
3401+ struct au_dpage *p;
3402+
3403+ p = dpages->dpages;
3404+ for (i = 0; i < dpages->ndpage; i++)
3405+ au_dpage_free(p++);
3406+ kfree(dpages->dpages);
3407+}
3408+
3409+static int au_dpages_append(struct au_dcsub_pages *dpages,
3410+ struct dentry *dentry, gfp_t gfp)
3411+{
3412+ int err, sz;
3413+ struct au_dpage *dpage;
3414+ void *p;
3415+
3416+ dpage = dpages->dpages + dpages->ndpage - 1;
3417+ sz = PAGE_SIZE / sizeof(dentry);
3418+ if (unlikely(dpage->ndentry >= sz)) {
3419+ AuLabel(new dpage);
3420+ err = -ENOMEM;
3421+ sz = dpages->ndpage * sizeof(*dpages->dpages);
3422+ p = au_kzrealloc(dpages->dpages, sz,
3423+ sz + sizeof(*dpages->dpages), gfp);
3424+ if (unlikely(!p))
3425+ goto out;
3426+
3427+ dpages->dpages = p;
3428+ dpage = dpages->dpages + dpages->ndpage;
3429+ p = (void *)__get_free_page(gfp);
3430+ if (unlikely(!p))
3431+ goto out;
3432+
3433+ dpage->ndentry = 0;
3434+ dpage->dentries = p;
3435+ dpages->ndpage++;
3436+ }
3437+
3438+ dpage->dentries[dpage->ndentry++] = dget(dentry);
3439+ return 0; /* success */
3440+
4f0767ce 3441+out:
1facf9fc 3442+ return err;
3443+}
3444+
3445+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3446+ au_dpages_test test, void *arg)
3447+{
3448+ int err;
3449+ struct dentry *this_parent = root;
3450+ struct list_head *next;
3451+ struct super_block *sb = root->d_sb;
3452+
3453+ err = 0;
3454+ spin_lock(&dcache_lock);
4f0767ce 3455+repeat:
1facf9fc 3456+ next = this_parent->d_subdirs.next;
4f0767ce 3457+resume:
1facf9fc 3458+ if (this_parent->d_sb == sb
3459+ && !IS_ROOT(this_parent)
3460+ && atomic_read(&this_parent->d_count)
3461+ && this_parent->d_inode
3462+ && (!test || test(this_parent, arg))) {
3463+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3464+ if (unlikely(err))
3465+ goto out;
3466+ }
3467+
3468+ while (next != &this_parent->d_subdirs) {
3469+ struct list_head *tmp = next;
3470+ struct dentry *dentry = list_entry(tmp, struct dentry,
3471+ d_u.d_child);
3472+ next = tmp->next;
3473+ if (/*d_unhashed(dentry) || */!dentry->d_inode)
3474+ continue;
3475+ if (!list_empty(&dentry->d_subdirs)) {
3476+ this_parent = dentry;
3477+ goto repeat;
3478+ }
3479+ if (dentry->d_sb == sb
3480+ && atomic_read(&dentry->d_count)
3481+ && (!test || test(dentry, arg))) {
3482+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3483+ if (unlikely(err))
3484+ goto out;
3485+ }
3486+ }
3487+
3488+ if (this_parent != root) {
3489+ next = this_parent->d_u.d_child.next;
3490+ this_parent = this_parent->d_parent; /* dcache_lock is locked */
3491+ goto resume;
3492+ }
4f0767ce 3493+out:
1facf9fc 3494+ spin_unlock(&dcache_lock);
3495+ return err;
3496+}
3497+
3498+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3499+ int do_include, au_dpages_test test, void *arg)
3500+{
3501+ int err;
3502+
3503+ err = 0;
3504+ spin_lock(&dcache_lock);
3505+ if (do_include && (!test || test(dentry, arg))) {
3506+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3507+ if (unlikely(err))
3508+ goto out;
3509+ }
3510+ while (!IS_ROOT(dentry)) {
3511+ dentry = dentry->d_parent; /* dcache_lock is locked */
3512+ if (!test || test(dentry, arg)) {
3513+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3514+ if (unlikely(err))
3515+ break;
3516+ }
3517+ }
3518+
4f0767ce 3519+out:
1facf9fc 3520+ spin_unlock(&dcache_lock);
3521+
3522+ return err;
3523+}
3524+
4a4d8108 3525+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 3526+{
4a4d8108
AM
3527+ struct path path[2] = {
3528+ {
3529+ .dentry = d1
3530+ },
3531+ {
3532+ .dentry = d2
3533+ }
3534+ };
1facf9fc 3535+
4a4d8108 3536+ return path_is_under(path + 0, path + 1);
1facf9fc 3537+}
b752ccd1
AM
3538diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
3539--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
953406b4 3540+++ linux/fs/aufs/dcsub.h 2010-10-21 09:52:43.086957936 +0200
dece6358 3541@@ -0,0 +1,54 @@
1facf9fc 3542+/*
4a4d8108 3543+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3544+ *
3545+ * This program, aufs is free software; you can redistribute it and/or modify
3546+ * it under the terms of the GNU General Public License as published by
3547+ * the Free Software Foundation; either version 2 of the License, or
3548+ * (at your option) any later version.
dece6358
AM
3549+ *
3550+ * This program is distributed in the hope that it will be useful,
3551+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3552+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3553+ * GNU General Public License for more details.
3554+ *
3555+ * You should have received a copy of the GNU General Public License
3556+ * along with this program; if not, write to the Free Software
3557+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3558+ */
3559+
3560+/*
3561+ * sub-routines for dentry cache
3562+ */
3563+
3564+#ifndef __AUFS_DCSUB_H__
3565+#define __AUFS_DCSUB_H__
3566+
3567+#ifdef __KERNEL__
3568+
dece6358
AM
3569+#include <linux/types.h>
3570+
3571+struct dentry;
1facf9fc 3572+
3573+struct au_dpage {
3574+ int ndentry;
3575+ struct dentry **dentries;
3576+};
3577+
3578+struct au_dcsub_pages {
3579+ int ndpage;
3580+ struct au_dpage *dpages;
3581+};
3582+
3583+/* ---------------------------------------------------------------------- */
3584+
3585+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3586+void au_dpages_free(struct au_dcsub_pages *dpages);
3587+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3588+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3589+ au_dpages_test test, void *arg);
3590+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3591+ int do_include, au_dpages_test test, void *arg);
4a4d8108 3592+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 3593+
3594+#endif /* __KERNEL__ */
3595+#endif /* __AUFS_DCSUB_H__ */
b752ccd1
AM
3596diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
3597--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
3598+++ linux/fs/aufs/debug.c 2010-10-21 09:52:43.086957936 +0200
3599@@ -0,0 +1,426 @@
1facf9fc 3600+/*
4a4d8108 3601+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3602+ *
3603+ * This program, aufs is free software; you can redistribute it and/or modify
3604+ * it under the terms of the GNU General Public License as published by
3605+ * the Free Software Foundation; either version 2 of the License, or
3606+ * (at your option) any later version.
dece6358
AM
3607+ *
3608+ * This program is distributed in the hope that it will be useful,
3609+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3610+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3611+ * GNU General Public License for more details.
3612+ *
3613+ * You should have received a copy of the GNU General Public License
3614+ * along with this program; if not, write to the Free Software
3615+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3616+ */
3617+
3618+/*
3619+ * debug print functions
3620+ */
3621+
dece6358
AM
3622+#include <linux/module.h>
3623+#include <linux/vt_kern.h>
1facf9fc 3624+#include "aufs.h"
3625+
3626+int aufs_debug;
3627+MODULE_PARM_DESC(debug, "debug print");
3628+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
3629+
3630+char *au_plevel = KERN_DEBUG;
953406b4
AM
3631+#define dpri(fmt, ...) do { \
3632+ if (au_debug_test()) \
3633+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 3634+} while (0)
3635+
3636+/* ---------------------------------------------------------------------- */
3637+
3638+void au_dpri_whlist(struct au_nhash *whlist)
3639+{
3640+ unsigned long ul, n;
3641+ struct hlist_head *head;
3642+ struct au_vdir_wh *tpos;
3643+ struct hlist_node *pos;
3644+
3645+ n = whlist->nh_num;
3646+ head = whlist->nh_head;
3647+ for (ul = 0; ul < n; ul++) {
3648+ hlist_for_each_entry(tpos, pos, head, wh_hash)
3649+ dpri("b%d, %.*s, %d\n",
3650+ tpos->wh_bindex,
3651+ tpos->wh_str.len, tpos->wh_str.name,
3652+ tpos->wh_str.len);
3653+ head++;
3654+ }
3655+}
3656+
3657+void au_dpri_vdir(struct au_vdir *vdir)
3658+{
3659+ unsigned long ul;
3660+ union au_vdir_deblk_p p;
3661+ unsigned char *o;
3662+
3663+ if (!vdir || IS_ERR(vdir)) {
3664+ dpri("err %ld\n", PTR_ERR(vdir));
3665+ return;
3666+ }
3667+
3668+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
3669+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
3670+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
3671+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
3672+ p.deblk = vdir->vd_deblk[ul];
3673+ o = p.deblk;
3674+ dpri("[%lu]: %p\n", ul, o);
3675+ }
3676+}
3677+
3678+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3679+ struct dentry *wh)
3680+{
3681+ char *n = NULL;
3682+ int l = 0;
3683+
3684+ if (!inode || IS_ERR(inode)) {
3685+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3686+ return -1;
3687+ }
3688+
3689+ /* the type of i_blocks depends upon CONFIG_LSF */
3690+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3691+ && sizeof(inode->i_blocks) != sizeof(u64));
3692+ if (wh) {
3693+ n = (void *)wh->d_name.name;
3694+ l = wh->d_name.len;
3695+ }
3696+
3697+ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
b752ccd1 3698+ " ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
1facf9fc 3699+ bindex,
3700+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3701+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3702+ i_size_read(inode), (unsigned long long)inode->i_blocks,
3703+ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3704+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
3705+ inode->i_state, inode->i_flags, inode->i_version,
3706+ inode->i_generation,
1facf9fc 3707+ l ? ", wh " : "", l, n);
3708+ return 0;
3709+}
3710+
3711+void au_dpri_inode(struct inode *inode)
3712+{
3713+ struct au_iinfo *iinfo;
3714+ aufs_bindex_t bindex;
3715+ int err;
3716+
3717+ err = do_pri_inode(-1, inode, NULL);
3718+ if (err || !au_test_aufs(inode->i_sb))
3719+ return;
3720+
3721+ iinfo = au_ii(inode);
3722+ if (!iinfo)
3723+ return;
3724+ dpri("i-1: bstart %d, bend %d, gen %d\n",
3725+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
3726+ if (iinfo->ii_bstart < 0)
3727+ return;
3728+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
3729+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
3730+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
3731+}
3732+
3733+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
3734+{
3735+ struct dentry *wh = NULL;
3736+
3737+ if (!dentry || IS_ERR(dentry)) {
3738+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
3739+ return -1;
3740+ }
3741+ /* do not call dget_parent() here */
3742+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
3743+ bindex,
3744+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
3745+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
3746+ atomic_read(&dentry->d_count), dentry->d_flags);
3747+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
3748+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
3749+ if (iinfo)
3750+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
3751+ }
3752+ do_pri_inode(bindex, dentry->d_inode, wh);
3753+ return 0;
3754+}
3755+
3756+void au_dpri_dentry(struct dentry *dentry)
3757+{
3758+ struct au_dinfo *dinfo;
3759+ aufs_bindex_t bindex;
3760+ int err;
4a4d8108 3761+ struct au_hdentry *hdp;
1facf9fc 3762+
3763+ err = do_pri_dentry(-1, dentry);
3764+ if (err || !au_test_aufs(dentry->d_sb))
3765+ return;
3766+
3767+ dinfo = au_di(dentry);
3768+ if (!dinfo)
3769+ return;
3770+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
3771+ dinfo->di_bstart, dinfo->di_bend,
3772+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
3773+ if (dinfo->di_bstart < 0)
3774+ return;
4a4d8108 3775+ hdp = dinfo->di_hdentry;
1facf9fc 3776+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 3777+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 3778+}
3779+
3780+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
3781+{
3782+ char a[32];
3783+
3784+ if (!file || IS_ERR(file)) {
3785+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
3786+ return -1;
3787+ }
3788+ a[0] = 0;
3789+ if (bindex < 0
3790+ && file->f_dentry
3791+ && au_test_aufs(file->f_dentry->d_sb)
3792+ && au_fi(file))
953406b4
AM
3793+ snprintf(a, sizeof(a), ", mmapped %d",
3794+ !!au_fi(file)->fi_hvmop);
b752ccd1 3795+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 3796+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 3797+ file->f_version, file->f_pos, a);
1facf9fc 3798+ if (file->f_dentry)
3799+ do_pri_dentry(bindex, file->f_dentry);
3800+ return 0;
3801+}
3802+
3803+void au_dpri_file(struct file *file)
3804+{
3805+ struct au_finfo *finfo;
4a4d8108
AM
3806+ struct au_fidir *fidir;
3807+ struct au_hfile *hfile;
1facf9fc 3808+ aufs_bindex_t bindex;
3809+ int err;
3810+
3811+ err = do_pri_file(-1, file);
3812+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
3813+ return;
3814+
3815+ finfo = au_fi(file);
3816+ if (!finfo)
3817+ return;
4a4d8108 3818+ if (finfo->fi_btop < 0)
1facf9fc 3819+ return;
4a4d8108
AM
3820+ fidir = finfo->fi_hdir;
3821+ if (!fidir)
3822+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
3823+ else
953406b4 3824+ for (bindex = finfo->fi_btop; bindex <= fidir->fd_bbot;
4a4d8108
AM
3825+ bindex++) {
3826+ hfile = fidir->fd_hfile + bindex;
3827+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
3828+ }
1facf9fc 3829+}
3830+
3831+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
3832+{
3833+ struct vfsmount *mnt;
3834+ struct super_block *sb;
3835+
3836+ if (!br || IS_ERR(br))
3837+ goto out;
3838+ mnt = br->br_mnt;
3839+ if (!mnt || IS_ERR(mnt))
3840+ goto out;
3841+ sb = mnt->mnt_sb;
3842+ if (!sb || IS_ERR(sb))
3843+ goto out;
3844+
3845+ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
b752ccd1 3846+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 3847+ "xino %d\n",
3848+ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
3849+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 3850+ sb->s_flags, sb->s_count,
1facf9fc 3851+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
3852+ return 0;
3853+
4f0767ce 3854+out:
1facf9fc 3855+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
3856+ return -1;
3857+}
3858+
3859+void au_dpri_sb(struct super_block *sb)
3860+{
3861+ struct au_sbinfo *sbinfo;
3862+ aufs_bindex_t bindex;
3863+ int err;
3864+ /* to reuduce stack size */
3865+ struct {
3866+ struct vfsmount mnt;
3867+ struct au_branch fake;
3868+ } *a;
3869+
3870+ /* this function can be called from magic sysrq */
3871+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
3872+ if (unlikely(!a)) {
3873+ dpri("no memory\n");
3874+ return;
3875+ }
3876+
3877+ a->mnt.mnt_sb = sb;
3878+ a->fake.br_perm = 0;
3879+ a->fake.br_mnt = &a->mnt;
3880+ a->fake.br_xino.xi_file = NULL;
3881+ atomic_set(&a->fake.br_count, 0);
3882+ smp_mb(); /* atomic_set */
3883+ err = do_pri_br(-1, &a->fake);
3884+ kfree(a);
3885+ dpri("dev 0x%x\n", sb->s_dev);
3886+ if (err || !au_test_aufs(sb))
3887+ return;
3888+
3889+ sbinfo = au_sbi(sb);
3890+ if (!sbinfo)
3891+ return;
3892+ dpri("nw %d, gen %u, kobj %d\n",
3893+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
3894+ atomic_read(&sbinfo->si_kobj.kref.refcount));
3895+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
3896+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
3897+}
3898+
3899+/* ---------------------------------------------------------------------- */
3900+
3901+void au_dbg_sleep_jiffy(int jiffy)
3902+{
3903+ while (jiffy)
3904+ jiffy = schedule_timeout_uninterruptible(jiffy);
3905+}
3906+
3907+void au_dbg_iattr(struct iattr *ia)
3908+{
3909+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
3910+ dpri(#name "\n")
3911+ AuBit(MODE);
3912+ AuBit(UID);
3913+ AuBit(GID);
3914+ AuBit(SIZE);
3915+ AuBit(ATIME);
3916+ AuBit(MTIME);
3917+ AuBit(CTIME);
3918+ AuBit(ATIME_SET);
3919+ AuBit(MTIME_SET);
3920+ AuBit(FORCE);
3921+ AuBit(ATTR_FLAG);
3922+ AuBit(KILL_SUID);
3923+ AuBit(KILL_SGID);
3924+ AuBit(FILE);
3925+ AuBit(KILL_PRIV);
3926+ AuBit(OPEN);
3927+ AuBit(TIMES_SET);
3928+#undef AuBit
3929+ dpri("ia_file %p\n", ia->ia_file);
3930+}
3931+
3932+/* ---------------------------------------------------------------------- */
3933+
3934+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
3935+{
3936+ struct dentry *parent;
3937+
3938+ parent = dget_parent(dentry);
3939+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
3940+ || IS_ROOT(dentry)
3941+ || au_digen(parent) != sigen);
3942+ dput(parent);
3943+}
3944+
3945+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
3946+{
3947+ struct dentry *parent;
3948+
3949+ parent = dget_parent(dentry);
3950+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
3951+ || au_digen(parent) != sigen);
3952+ dput(parent);
3953+}
3954+
3955+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
3956+{
3957+ int err, i, j;
3958+ struct au_dcsub_pages dpages;
3959+ struct au_dpage *dpage;
3960+ struct dentry **dentries;
3961+
3962+ err = au_dpages_init(&dpages, GFP_NOFS);
3963+ AuDebugOn(err);
3964+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
3965+ AuDebugOn(err);
3966+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
3967+ dpage = dpages.dpages + i;
3968+ dentries = dpage->dentries;
3969+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
3970+ AuDebugOn(au_digen(dentries[j]) != sigen);
3971+ }
3972+ au_dpages_free(&dpages);
3973+}
3974+
1facf9fc 3975+void au_dbg_verify_kthread(void)
3976+{
953406b4 3977+ if (current->flags & PF_WQ_WORKER) {
1facf9fc 3978+ au_dbg_blocked();
953406b4 3979+ WARN_ON(1);
1facf9fc 3980+ }
3981+}
3982+
3983+/* ---------------------------------------------------------------------- */
3984+
3985+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
3986+{
3987+#ifdef AuForceNoPlink
3988+ au_opt_clr(sbinfo->si_mntflags, PLINK);
3989+#endif
3990+#ifdef AuForceNoXino
3991+ au_opt_clr(sbinfo->si_mntflags, XINO);
3992+#endif
3993+#ifdef AuForceNoRefrof
3994+ au_opt_clr(sbinfo->si_mntflags, REFROF);
3995+#endif
4a4d8108
AM
3996+#ifdef AuForceHnotify
3997+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 3998+#endif
1308ab2a 3999+#ifdef AuForceRd0
4000+ sbinfo->si_rdblk = 0;
4001+ sbinfo->si_rdhash = 0;
4002+#endif
1facf9fc 4003+}
4004+
4005+int __init au_debug_init(void)
4006+{
4007+ aufs_bindex_t bindex;
4008+ struct au_vdir_destr destr;
4009+
4010+ bindex = -1;
4011+ AuDebugOn(bindex >= 0);
4012+
4013+ destr.len = -1;
4014+ AuDebugOn(destr.len < NAME_MAX);
4015+
4016+#ifdef CONFIG_4KSTACKS
4a4d8108 4017+ pr_warning("CONFIG_4KSTACKS is defined.\n");
1facf9fc 4018+#endif
4019+
4020+#ifdef AuForceNoBrs
4021+ sysaufs_brs = 0;
4022+#endif
4023+
4024+ return 0;
4025+}
b752ccd1
AM
4026diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
4027--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
4028+++ linux/fs/aufs/debug.h 2010-10-21 09:52:43.086957936 +0200
4029@@ -0,0 +1,243 @@
1facf9fc 4030+/*
4a4d8108 4031+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4032+ *
4033+ * This program, aufs is free software; you can redistribute it and/or modify
4034+ * it under the terms of the GNU General Public License as published by
4035+ * the Free Software Foundation; either version 2 of the License, or
4036+ * (at your option) any later version.
dece6358
AM
4037+ *
4038+ * This program is distributed in the hope that it will be useful,
4039+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4040+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4041+ * GNU General Public License for more details.
4042+ *
4043+ * You should have received a copy of the GNU General Public License
4044+ * along with this program; if not, write to the Free Software
4045+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4046+ */
4047+
4048+/*
4049+ * debug print functions
4050+ */
4051+
4052+#ifndef __AUFS_DEBUG_H__
4053+#define __AUFS_DEBUG_H__
4054+
4055+#ifdef __KERNEL__
4056+
1308ab2a 4057+#include <asm/system.h>
dece6358
AM
4058+#include <linux/bug.h>
4059+/* #include <linux/err.h> */
1308ab2a 4060+#include <linux/init.h>
4a4d8108
AM
4061+#include <linux/module.h>
4062+#include <linux/kallsyms.h>
dece6358 4063+/* #include <linux/kernel.h> */
1facf9fc 4064+#include <linux/delay.h>
dece6358 4065+/* #include <linux/kd.h> */
4f0767ce 4066+#include <linux/vt_kern.h>
1facf9fc 4067+#include <linux/sysrq.h>
4068+#include <linux/aufs_type.h>
4069+
4a4d8108
AM
4070+#include <asm/system.h>
4071+
1facf9fc 4072+#ifdef CONFIG_AUFS_DEBUG
4073+#define AuDebugOn(a) BUG_ON(a)
4074+
4075+/* module parameter */
4076+extern int aufs_debug;
4077+static inline void au_debug(int n)
4078+{
4079+ aufs_debug = n;
4080+ smp_mb();
4081+}
4082+
4083+static inline int au_debug_test(void)
4084+{
4085+ return aufs_debug;
4086+}
4087+#else
4088+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
4089+AuStubVoid(au_debug, int n)
4090+AuStubInt0(au_debug_test, void)
1facf9fc 4091+#endif /* CONFIG_AUFS_DEBUG */
4092+
4093+/* ---------------------------------------------------------------------- */
4094+
4095+/* debug print */
4096+
4a4d8108 4097+#define AuDbg(fmt, ...) do { \
1facf9fc 4098+ if (au_debug_test()) \
4a4d8108 4099+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 4100+} while (0)
4a4d8108
AM
4101+#define AuLabel(l) AuDbg(#l "\n")
4102+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
4103+#define AuWarn1(fmt, ...) do { \
1facf9fc 4104+ static unsigned char _c; \
4105+ if (!_c++) \
4a4d8108 4106+ pr_warning(fmt, ##__VA_ARGS__); \
1facf9fc 4107+} while (0)
4108+
4a4d8108 4109+#define AuErr1(fmt, ...) do { \
1facf9fc 4110+ static unsigned char _c; \
4111+ if (!_c++) \
4a4d8108 4112+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 4113+} while (0)
4114+
4a4d8108 4115+#define AuIOErr1(fmt, ...) do { \
1facf9fc 4116+ static unsigned char _c; \
4117+ if (!_c++) \
4a4d8108 4118+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 4119+} while (0)
4120+
4121+#define AuUnsupportMsg "This operation is not supported." \
4122+ " Please report this application to aufs-users ML."
4a4d8108
AM
4123+#define AuUnsupport(fmt, ...) do { \
4124+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 4125+ dump_stack(); \
4126+} while (0)
4127+
4128+#define AuTraceErr(e) do { \
4129+ if (unlikely((e) < 0)) \
4130+ AuDbg("err %d\n", (int)(e)); \
4131+} while (0)
4132+
4133+#define AuTraceErrPtr(p) do { \
4134+ if (IS_ERR(p)) \
4135+ AuDbg("err %ld\n", PTR_ERR(p)); \
4136+} while (0)
4137+
4138+/* dirty macros for debug print, use with "%.*s" and caution */
4139+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
4140+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
4141+
4142+/* ---------------------------------------------------------------------- */
4143+
4144+struct au_sbinfo;
4145+struct au_finfo;
dece6358 4146+struct dentry;
1facf9fc 4147+#ifdef CONFIG_AUFS_DEBUG
4148+extern char *au_plevel;
4149+struct au_nhash;
4150+void au_dpri_whlist(struct au_nhash *whlist);
4151+struct au_vdir;
4152+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 4153+struct inode;
1facf9fc 4154+void au_dpri_inode(struct inode *inode);
4155+void au_dpri_dentry(struct dentry *dentry);
dece6358 4156+struct file;
1facf9fc 4157+void au_dpri_file(struct file *filp);
dece6358 4158+struct super_block;
1facf9fc 4159+void au_dpri_sb(struct super_block *sb);
4160+
4161+void au_dbg_sleep_jiffy(int jiffy);
dece6358 4162+struct iattr;
1facf9fc 4163+void au_dbg_iattr(struct iattr *ia);
4164+
4165+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
4166+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
4167+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 4168+void au_dbg_verify_kthread(void);
4169+
4170+int __init au_debug_init(void);
4171+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
4172+#define AuDbgWhlist(w) do { \
4173+ AuDbg(#w "\n"); \
4174+ au_dpri_whlist(w); \
4175+} while (0)
4176+
4177+#define AuDbgVdir(v) do { \
4178+ AuDbg(#v "\n"); \
4179+ au_dpri_vdir(v); \
4180+} while (0)
4181+
4182+#define AuDbgInode(i) do { \
4183+ AuDbg(#i "\n"); \
4184+ au_dpri_inode(i); \
4185+} while (0)
4186+
4187+#define AuDbgDentry(d) do { \
4188+ AuDbg(#d "\n"); \
4189+ au_dpri_dentry(d); \
4190+} while (0)
4191+
4192+#define AuDbgFile(f) do { \
4193+ AuDbg(#f "\n"); \
4194+ au_dpri_file(f); \
4195+} while (0)
4196+
4197+#define AuDbgSb(sb) do { \
4198+ AuDbg(#sb "\n"); \
4199+ au_dpri_sb(sb); \
4200+} while (0)
4201+
4202+#define AuDbgSleep(sec) do { \
4203+ AuDbg("sleep %d sec\n", sec); \
4204+ ssleep(sec); \
4205+} while (0)
4206+
4207+#define AuDbgSleepJiffy(jiffy) do { \
4208+ AuDbg("sleep %d jiffies\n", jiffy); \
4209+ au_dbg_sleep_jiffy(jiffy); \
4210+} while (0)
4211+
4212+#define AuDbgIAttr(ia) do { \
4213+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
4214+ au_dbg_iattr(ia); \
4215+} while (0)
4a4d8108
AM
4216+
4217+#define AuDbgSym(addr) do { \
4218+ char sym[KSYM_SYMBOL_LEN]; \
4219+ sprint_symbol(sym, (unsigned long)addr); \
4220+ AuDbg("%s\n", sym); \
4221+} while (0)
4222+
4223+#define AuInfoSym(addr) do { \
4224+ char sym[KSYM_SYMBOL_LEN]; \
4225+ sprint_symbol(sym, (unsigned long)addr); \
4226+ AuInfo("%s\n", sym); \
4227+} while (0)
1facf9fc 4228+#else
4a4d8108
AM
4229+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
4230+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
4231+ unsigned int sigen)
4232+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
4233+AuStubVoid(au_dbg_verify_kthread, void)
4234+AuStubInt0(__init au_debug_init, void)
4235+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 4236+
1facf9fc 4237+#define AuDbgWhlist(w) do {} while (0)
4238+#define AuDbgVdir(v) do {} while (0)
4239+#define AuDbgInode(i) do {} while (0)
4240+#define AuDbgDentry(d) do {} while (0)
4241+#define AuDbgFile(f) do {} while (0)
4242+#define AuDbgSb(sb) do {} while (0)
4243+#define AuDbgSleep(sec) do {} while (0)
4244+#define AuDbgSleepJiffy(jiffy) do {} while (0)
4245+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
4246+#define AuDbgSym(addr) do {} while (0)
4247+#define AuInfoSym(addr) do {} while (0)
1facf9fc 4248+#endif /* CONFIG_AUFS_DEBUG */
4249+
4250+/* ---------------------------------------------------------------------- */
4251+
4252+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
4253+int __init au_sysrq_init(void);
4254+void au_sysrq_fin(void);
4255+
4256+#ifdef CONFIG_HW_CONSOLE
4257+#define au_dbg_blocked() do { \
4258+ WARN_ON(1); \
953406b4 4259+ handle_sysrq('w', vc_cons[fg_console].d->port.tty); \
1facf9fc 4260+} while (0)
4261+#else
4a4d8108 4262+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4263+#endif
4264+
4265+#else
4a4d8108
AM
4266+AuStubInt0(__init au_sysrq_init, void)
4267+AuStubVoid(au_sysrq_fin, void)
4268+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4269+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
4270+
4271+#endif /* __KERNEL__ */
4272+#endif /* __AUFS_DEBUG_H__ */
b752ccd1
AM
4273diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
4274--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
4275+++ linux/fs/aufs/dentry.c 2010-10-21 09:52:43.086957936 +0200
4276@@ -0,0 +1,851 @@
1facf9fc 4277+/*
4a4d8108 4278+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4279+ *
4280+ * This program, aufs is free software; you can redistribute it and/or modify
4281+ * it under the terms of the GNU General Public License as published by
4282+ * the Free Software Foundation; either version 2 of the License, or
4283+ * (at your option) any later version.
dece6358
AM
4284+ *
4285+ * This program is distributed in the hope that it will be useful,
4286+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4287+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4288+ * GNU General Public License for more details.
4289+ *
4290+ * You should have received a copy of the GNU General Public License
4291+ * along with this program; if not, write to the Free Software
4292+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4293+ */
4294+
4295+/*
4296+ * lookup and dentry operations
4297+ */
4298+
dece6358 4299+#include <linux/namei.h>
1facf9fc 4300+#include "aufs.h"
4301+
4302+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
4303+{
4304+ if (nd) {
4305+ *h_nd = *nd;
4306+
4307+ /*
4308+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
4309+ * due to whiteout and branch permission.
4310+ */
4311+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
b752ccd1 4312+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
1facf9fc 4313+ /* unnecessary? */
4314+ h_nd->intent.open.file = NULL;
4315+ } else
4316+ memset(h_nd, 0, sizeof(*h_nd));
4317+}
4318+
4319+struct au_lkup_one_args {
4320+ struct dentry **errp;
4321+ struct qstr *name;
4322+ struct dentry *h_parent;
4323+ struct au_branch *br;
4324+ struct nameidata *nd;
4325+};
4326+
4327+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
4328+ struct au_branch *br, struct nameidata *nd)
4329+{
4330+ struct dentry *h_dentry;
4331+ int err;
4332+ struct nameidata h_nd;
4333+
4334+ if (au_test_fs_null_nd(h_parent->d_sb))
4335+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
4336+
4337+ au_h_nd(&h_nd, nd);
4338+ h_nd.path.dentry = h_parent;
4339+ h_nd.path.mnt = br->br_mnt;
4340+
4341+ err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
4342+ h_dentry = ERR_PTR(err);
4343+ if (!err) {
4344+ path_get(&h_nd.path);
4345+ h_dentry = vfsub_lookup_hash(&h_nd);
4346+ path_put(&h_nd.path);
4347+ }
4348+
4a4d8108 4349+ AuTraceErrPtr(h_dentry);
1facf9fc 4350+ return h_dentry;
4351+}
4352+
4353+static void au_call_lkup_one(void *args)
4354+{
4355+ struct au_lkup_one_args *a = args;
4356+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
4357+}
4358+
4359+#define AuLkup_ALLOW_NEG 1
4360+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
4361+#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; }
4362+#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; }
4363+
4364+struct au_do_lookup_args {
4365+ unsigned int flags;
4366+ mode_t type;
4367+ struct nameidata *nd;
4368+};
4369+
4370+/*
4371+ * returns positive/negative dentry, NULL or an error.
4372+ * NULL means whiteout-ed or not-found.
4373+ */
4374+static struct dentry*
4375+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
4376+ aufs_bindex_t bindex, struct qstr *wh_name,
4377+ struct au_do_lookup_args *args)
4378+{
4379+ struct dentry *h_dentry;
4380+ struct inode *h_inode, *inode;
1facf9fc 4381+ struct au_branch *br;
4382+ int wh_found, opq;
4383+ unsigned char wh_able;
4384+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
4385+
1facf9fc 4386+ wh_found = 0;
4387+ br = au_sbr(dentry->d_sb, bindex);
4388+ wh_able = !!au_br_whable(br->br_perm);
4389+ if (wh_able)
4390+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
4391+ h_dentry = ERR_PTR(wh_found);
4392+ if (!wh_found)
4393+ goto real_lookup;
4394+ if (unlikely(wh_found < 0))
4395+ goto out;
4396+
4397+ /* We found a whiteout */
4398+ /* au_set_dbend(dentry, bindex); */
4399+ au_set_dbwh(dentry, bindex);
4400+ if (!allow_neg)
4401+ return NULL; /* success */
4402+
4f0767ce 4403+real_lookup:
4a4d8108 4404+ h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
1facf9fc 4405+ if (IS_ERR(h_dentry))
4406+ goto out;
4407+
4408+ h_inode = h_dentry->d_inode;
4409+ if (!h_inode) {
4410+ if (!allow_neg)
4411+ goto out_neg;
4412+ } else if (wh_found
4413+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
4414+ goto out_neg;
4415+
4416+ if (au_dbend(dentry) <= bindex)
4417+ au_set_dbend(dentry, bindex);
4418+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4419+ au_set_dbstart(dentry, bindex);
4420+ au_set_h_dptr(dentry, bindex, h_dentry);
4421+
4422+ inode = dentry->d_inode;
4423+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4424+ || (inode && !S_ISDIR(inode->i_mode)))
4425+ goto out; /* success */
4426+
4427+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4428+ opq = au_diropq_test(h_dentry, br);
4429+ mutex_unlock(&h_inode->i_mutex);
4430+ if (opq > 0)
4431+ au_set_dbdiropq(dentry, bindex);
4432+ else if (unlikely(opq < 0)) {
4433+ au_set_h_dptr(dentry, bindex, NULL);
4434+ h_dentry = ERR_PTR(opq);
4435+ }
4436+ goto out;
4437+
4f0767ce 4438+out_neg:
1facf9fc 4439+ dput(h_dentry);
4440+ h_dentry = NULL;
4f0767ce 4441+out:
1facf9fc 4442+ return h_dentry;
4443+}
4444+
dece6358
AM
4445+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
4446+{
4447+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
4448+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
4449+ return -EPERM;
4450+ return 0;
4451+}
4452+
1facf9fc 4453+/*
4454+ * returns the number of lower positive dentries,
4455+ * otherwise an error.
4456+ * can be called at unlinking with @type is zero.
4457+ */
4458+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4459+ struct nameidata *nd)
4460+{
4461+ int npositive, err;
4462+ aufs_bindex_t bindex, btail, bdiropq;
4463+ unsigned char isdir;
4464+ struct qstr whname;
4465+ struct au_do_lookup_args args = {
4466+ .flags = 0,
4467+ .type = type,
4468+ .nd = nd
4469+ };
4470+ const struct qstr *name = &dentry->d_name;
4471+ struct dentry *parent;
4472+ struct inode *inode;
4473+
dece6358
AM
4474+ err = au_test_shwh(dentry->d_sb, name);
4475+ if (unlikely(err))
1facf9fc 4476+ goto out;
4477+
4478+ err = au_wh_name_alloc(&whname, name);
4479+ if (unlikely(err))
4480+ goto out;
4481+
4482+ inode = dentry->d_inode;
4483+ isdir = !!(inode && S_ISDIR(inode->i_mode));
4484+ if (!type)
4485+ au_fset_lkup(args.flags, ALLOW_NEG);
4486+
4487+ npositive = 0;
4a4d8108 4488+ parent = dget_parent(dentry);
1facf9fc 4489+ btail = au_dbtaildir(parent);
4490+ for (bindex = bstart; bindex <= btail; bindex++) {
4491+ struct dentry *h_parent, *h_dentry;
4492+ struct inode *h_inode, *h_dir;
4493+
4494+ h_dentry = au_h_dptr(dentry, bindex);
4495+ if (h_dentry) {
4496+ if (h_dentry->d_inode)
4497+ npositive++;
4498+ if (type != S_IFDIR)
4499+ break;
4500+ continue;
4501+ }
4502+ h_parent = au_h_dptr(parent, bindex);
4503+ if (!h_parent)
4504+ continue;
4505+ h_dir = h_parent->d_inode;
4506+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
4507+ continue;
4508+
4509+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4510+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4511+ &args);
4512+ mutex_unlock(&h_dir->i_mutex);
4513+ err = PTR_ERR(h_dentry);
4514+ if (IS_ERR(h_dentry))
4a4d8108 4515+ goto out_parent;
1facf9fc 4516+ au_fclr_lkup(args.flags, ALLOW_NEG);
4517+
4518+ if (au_dbwh(dentry) >= 0)
4519+ break;
4520+ if (!h_dentry)
4521+ continue;
4522+ h_inode = h_dentry->d_inode;
4523+ if (!h_inode)
4524+ continue;
4525+ npositive++;
4526+ if (!args.type)
4527+ args.type = h_inode->i_mode & S_IFMT;
4528+ if (args.type != S_IFDIR)
4529+ break;
4530+ else if (isdir) {
4531+ /* the type of lower may be different */
4532+ bdiropq = au_dbdiropq(dentry);
4533+ if (bdiropq >= 0 && bdiropq <= bindex)
4534+ break;
4535+ }
4536+ }
4537+
4538+ if (npositive) {
4539+ AuLabel(positive);
4540+ au_update_dbstart(dentry);
4541+ }
4542+ err = npositive;
4543+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
4544+ && au_dbstart(dentry) < 0))
4545+ /* both of real entry and whiteout found */
4546+ err = -EIO;
4547+
4f0767ce 4548+out_parent:
4a4d8108 4549+ dput(parent);
1facf9fc 4550+ kfree(whname.name);
4f0767ce 4551+out:
1facf9fc 4552+ return err;
4553+}
4554+
4555+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4556+ struct au_branch *br)
4557+{
4558+ struct dentry *dentry;
4559+ int wkq_err;
4560+
4561+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
4562+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
4563+ else {
4564+ struct au_lkup_one_args args = {
4565+ .errp = &dentry,
4566+ .name = name,
4567+ .h_parent = parent,
4568+ .br = br,
4569+ .nd = NULL
4570+ };
4571+
4572+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
4573+ if (unlikely(wkq_err))
4574+ dentry = ERR_PTR(wkq_err);
4575+ }
4576+
4577+ return dentry;
4578+}
4579+
4580+/*
4581+ * lookup @dentry on @bindex which should be negative.
4582+ */
4583+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4584+{
4585+ int err;
4586+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 4587+
1facf9fc 4588+ parent = dget_parent(dentry);
4589+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 4590+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 4591+ au_sbr(dentry->d_sb, bindex));
4592+ err = PTR_ERR(h_dentry);
4593+ if (IS_ERR(h_dentry))
4594+ goto out;
4595+ if (unlikely(h_dentry->d_inode)) {
4596+ err = -EIO;
4597+ AuIOErr("b%d %.*s should be negative.\n",
4598+ bindex, AuDLNPair(h_dentry));
4599+ dput(h_dentry);
4600+ goto out;
4601+ }
4602+
4a4d8108 4603+ err = 0;
1facf9fc 4604+ if (bindex < au_dbstart(dentry))
4605+ au_set_dbstart(dentry, bindex);
4606+ if (au_dbend(dentry) < bindex)
4607+ au_set_dbend(dentry, bindex);
4608+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 4609+
4f0767ce 4610+out:
1facf9fc 4611+ dput(parent);
4612+ return err;
4613+}
4614+
4615+/* ---------------------------------------------------------------------- */
4616+
4617+/* subset of struct inode */
4618+struct au_iattr {
4619+ unsigned long i_ino;
4620+ /* unsigned int i_nlink; */
4621+ uid_t i_uid;
4622+ gid_t i_gid;
4623+ u64 i_version;
4624+/*
4625+ loff_t i_size;
4626+ blkcnt_t i_blocks;
4627+*/
4628+ umode_t i_mode;
4629+};
4630+
4631+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
4632+{
4633+ ia->i_ino = h_inode->i_ino;
4634+ /* ia->i_nlink = h_inode->i_nlink; */
4635+ ia->i_uid = h_inode->i_uid;
4636+ ia->i_gid = h_inode->i_gid;
4637+ ia->i_version = h_inode->i_version;
4638+/*
4639+ ia->i_size = h_inode->i_size;
4640+ ia->i_blocks = h_inode->i_blocks;
4641+*/
4642+ ia->i_mode = (h_inode->i_mode & S_IFMT);
4643+}
4644+
4645+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
4646+{
4647+ return ia->i_ino != h_inode->i_ino
4648+ /* || ia->i_nlink != h_inode->i_nlink */
4649+ || ia->i_uid != h_inode->i_uid
4650+ || ia->i_gid != h_inode->i_gid
4651+ || ia->i_version != h_inode->i_version
4652+/*
4653+ || ia->i_size != h_inode->i_size
4654+ || ia->i_blocks != h_inode->i_blocks
4655+*/
4656+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
4657+}
4658+
4659+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
4660+ struct au_branch *br)
4661+{
4662+ int err;
4663+ struct au_iattr ia;
4664+ struct inode *h_inode;
4665+ struct dentry *h_d;
4666+ struct super_block *h_sb;
4667+
4668+ err = 0;
4669+ memset(&ia, -1, sizeof(ia));
4670+ h_sb = h_dentry->d_sb;
4671+ h_inode = h_dentry->d_inode;
4672+ if (h_inode)
4673+ au_iattr_save(&ia, h_inode);
4674+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
4675+ /* nfs d_revalidate may return 0 for negative dentry */
4676+ /* fuse d_revalidate always return 0 for negative dentry */
4677+ goto out;
4678+
4679+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
4680+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
4681+ err = PTR_ERR(h_d);
4682+ if (IS_ERR(h_d))
4683+ goto out;
4684+
4685+ err = 0;
4686+ if (unlikely(h_d != h_dentry
4687+ || h_d->d_inode != h_inode
4688+ || (h_inode && au_iattr_test(&ia, h_inode))))
4689+ err = au_busy_or_stale();
4690+ dput(h_d);
4691+
4f0767ce 4692+out:
1facf9fc 4693+ AuTraceErr(err);
4694+ return err;
4695+}
4696+
4697+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
4698+ struct dentry *h_parent, struct au_branch *br)
4699+{
4700+ int err;
4701+
4702+ err = 0;
4703+ if (udba == AuOpt_UDBA_REVAL) {
4704+ IMustLock(h_dir);
4705+ err = (h_dentry->d_parent->d_inode != h_dir);
4a4d8108 4706+ } else if (udba == AuOpt_UDBA_HNOTIFY)
1facf9fc 4707+ err = au_h_verify_dentry(h_dentry, h_parent, br);
4708+
4709+ return err;
4710+}
4711+
4712+/* ---------------------------------------------------------------------- */
4713+
4714+static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
4715+ struct dentry *parent)
4716+{
4717+ struct dentry *h_d, *h_dp;
4718+ struct au_hdentry tmp, *q;
4719+ struct super_block *sb;
4720+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
4721+
1308ab2a 4722+ AuRwMustWriteLock(&dinfo->di_rwsem);
4723+
1facf9fc 4724+ bend = dinfo->di_bend;
4725+ bwh = dinfo->di_bwh;
4726+ bdiropq = dinfo->di_bdiropq;
4727+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
4728+ h_d = p->hd_dentry;
4729+ if (!h_d)
4730+ continue;
4731+
4732+ h_dp = dget_parent(h_d);
4733+ if (h_dp == au_h_dptr(parent, bindex)) {
4734+ dput(h_dp);
4735+ continue;
4736+ }
4737+
4738+ new_bindex = au_find_dbindex(parent, h_dp);
4739+ dput(h_dp);
4740+ if (dinfo->di_bwh == bindex)
4741+ bwh = new_bindex;
4742+ if (dinfo->di_bdiropq == bindex)
4743+ bdiropq = new_bindex;
4744+ if (new_bindex < 0) {
4745+ au_hdput(p);
4746+ p->hd_dentry = NULL;
4747+ continue;
4748+ }
4749+
4750+ /* swap two lower dentries, and loop again */
4751+ q = dinfo->di_hdentry + new_bindex;
4752+ tmp = *q;
4753+ *q = *p;
4754+ *p = tmp;
4755+ if (tmp.hd_dentry) {
4756+ bindex--;
4757+ p--;
4758+ }
4759+ }
4760+
4761+ sb = parent->d_sb;
4762+ dinfo->di_bwh = -1;
4763+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
4764+ dinfo->di_bwh = bwh;
4765+
4766+ dinfo->di_bdiropq = -1;
4767+ if (bdiropq >= 0
4768+ && bdiropq <= au_sbend(sb)
4769+ && au_sbr_whable(sb, bdiropq))
4770+ dinfo->di_bdiropq = bdiropq;
4771+
4772+ bend = au_dbend(parent);
4773+ p = dinfo->di_hdentry;
4774+ for (bindex = 0; bindex <= bend; bindex++, p++)
4775+ if (p->hd_dentry) {
4776+ dinfo->di_bstart = bindex;
4777+ break;
4778+ }
4779+
4780+ p = dinfo->di_hdentry + bend;
4781+ for (bindex = bend; bindex >= 0; bindex--, p--)
4782+ if (p->hd_dentry) {
4783+ dinfo->di_bend = bindex;
4784+ break;
4785+ }
4786+}
4787+
4788+/*
4789+ * returns the number of found lower positive dentries,
4790+ * otherwise an error.
4791+ */
4792+int au_refresh_hdentry(struct dentry *dentry, mode_t type)
4793+{
4794+ int npositive, err;
4795+ unsigned int sigen;
4796+ aufs_bindex_t bstart;
4797+ struct au_dinfo *dinfo;
4798+ struct super_block *sb;
4799+ struct dentry *parent;
4800+
1308ab2a 4801+ DiMustWriteLock(dentry);
4802+
1facf9fc 4803+ sb = dentry->d_sb;
4804+ AuDebugOn(IS_ROOT(dentry));
4805+ sigen = au_sigen(sb);
4806+ parent = dget_parent(dentry);
4807+ AuDebugOn(au_digen(parent) != sigen
4808+ || au_iigen(parent->d_inode) != sigen);
4809+
4810+ dinfo = au_di(dentry);
4811+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
4812+ npositive = err;
4813+ if (unlikely(err))
4814+ goto out;
4815+ au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
4816+ parent);
4817+
4818+ npositive = 0;
4819+ bstart = au_dbstart(parent);
4820+ if (type != S_IFDIR && dinfo->di_bstart == bstart)
4821+ goto out_dgen; /* success */
4822+
4823+ npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
4824+ if (npositive < 0)
4825+ goto out;
4826+ if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
4827+ d_drop(dentry);
4828+
4f0767ce 4829+out_dgen:
1facf9fc 4830+ au_update_digen(dentry);
4f0767ce 4831+out:
1facf9fc 4832+ dput(parent);
4833+ AuTraceErr(npositive);
4834+ return npositive;
4835+}
4836+
4837+static noinline_for_stack
4838+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
4839+ struct dentry *dentry, aufs_bindex_t bindex)
4840+{
4841+ int err, valid;
4842+ int (*reval)(struct dentry *, struct nameidata *);
4843+
4844+ err = 0;
4845+ reval = NULL;
4846+ if (h_dentry->d_op)
4847+ reval = h_dentry->d_op->d_revalidate;
4848+ if (!reval)
4849+ goto out;
4850+
4851+ AuDbg("b%d\n", bindex);
4852+ if (au_test_fs_null_nd(h_dentry->d_sb))
4853+ /* it may return tri-state */
4854+ valid = reval(h_dentry, NULL);
4855+ else {
4856+ struct nameidata h_nd;
4857+ int locked;
4858+ struct dentry *parent;
4859+
4860+ au_h_nd(&h_nd, nd);
4861+ parent = nd->path.dentry;
4862+ locked = (nd && nd->path.dentry != dentry);
4863+ if (locked)
4864+ di_read_lock_parent(parent, AuLock_IR);
4865+ BUG_ON(bindex > au_dbend(parent));
4866+ h_nd.path.dentry = au_h_dptr(parent, bindex);
4867+ BUG_ON(!h_nd.path.dentry);
4868+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
4869+ path_get(&h_nd.path);
4870+ valid = reval(h_dentry, &h_nd);
4871+ path_put(&h_nd.path);
4872+ if (locked)
4873+ di_read_unlock(parent, AuLock_IR);
4874+ }
4875+
4876+ if (unlikely(valid < 0))
4877+ err = valid;
4878+ else if (!valid)
4879+ err = -EINVAL;
4880+
4f0767ce 4881+out:
1facf9fc 4882+ AuTraceErr(err);
4883+ return err;
4884+}
4885+
4886+/* todo: remove this */
4887+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
4888+ struct nameidata *nd, int do_udba)
4889+{
4890+ int err;
4891+ umode_t mode, h_mode;
4892+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
4893+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 4894+ struct inode *h_inode, *h_cached_inode;
1facf9fc 4895+ struct dentry *h_dentry;
4896+ struct qstr *name, *h_name;
4897+
4898+ err = 0;
4899+ plus = 0;
4900+ mode = 0;
1facf9fc 4901+ ibs = -1;
4902+ ibe = -1;
4903+ unhashed = !!d_unhashed(dentry);
4904+ is_root = !!IS_ROOT(dentry);
4905+ name = &dentry->d_name;
4906+
4907+ /*
953406b4
AM
4908+ * Theoretically, REVAL test should be unnecessary in case of
4909+ * {FS,I}NOTIFY.
4910+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 4911+ * IN_ATTRIB for atime/nlink/pageio
4912+ * IN_DELETE for NFS dentry
4913+ * Let's do REVAL test too.
4914+ */
4915+ if (do_udba && inode) {
4916+ mode = (inode->i_mode & S_IFMT);
4917+ plus = (inode->i_nlink > 0);
1facf9fc 4918+ ibs = au_ibstart(inode);
4919+ ibe = au_ibend(inode);
4920+ }
4921+
4922+ bstart = au_dbstart(dentry);
4923+ btail = bstart;
4924+ if (inode && S_ISDIR(inode->i_mode))
4925+ btail = au_dbtaildir(dentry);
4926+ for (bindex = bstart; bindex <= btail; bindex++) {
4927+ h_dentry = au_h_dptr(dentry, bindex);
4928+ if (!h_dentry)
4929+ continue;
4930+
4931+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
4932+ h_name = &h_dentry->d_name;
4933+ if (unlikely(do_udba
4934+ && !is_root
4935+ && (unhashed != !!d_unhashed(h_dentry)
4936+ || name->len != h_name->len
4937+ || memcmp(name->name, h_name->name, name->len))
4938+ )) {
4939+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
4940+ unhashed, d_unhashed(h_dentry),
4941+ AuDLNPair(dentry), AuDLNPair(h_dentry));
4942+ goto err;
4943+ }
4944+
4945+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
4946+ if (unlikely(err))
4947+ /* do not goto err, to keep the errno */
4948+ break;
4949+
4950+ /* todo: plink too? */
4951+ if (!do_udba)
4952+ continue;
4953+
4954+ /* UDBA tests */
4955+ h_inode = h_dentry->d_inode;
4956+ if (unlikely(!!inode != !!h_inode))
4957+ goto err;
4958+
4959+ h_plus = plus;
4960+ h_mode = mode;
4961+ h_cached_inode = h_inode;
4962+ if (h_inode) {
4963+ h_mode = (h_inode->i_mode & S_IFMT);
4964+ h_plus = (h_inode->i_nlink > 0);
4965+ }
4966+ if (inode && ibs <= bindex && bindex <= ibe)
4967+ h_cached_inode = au_h_iptr(inode, bindex);
4968+
4969+ if (unlikely(plus != h_plus
4970+ || mode != h_mode
4971+ || h_cached_inode != h_inode))
4972+ goto err;
4973+ continue;
4974+
4975+ err:
4976+ err = -EINVAL;
4977+ break;
4978+ }
4979+
4980+ return err;
4981+}
4982+
4983+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
4984+{
4985+ int err;
4986+ struct dentry *parent;
4987+ struct inode *inode;
4988+
4989+ inode = dentry->d_inode;
4990+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
4991+ return 0;
4992+
4993+ parent = dget_parent(dentry);
4994+ di_read_lock_parent(parent, AuLock_IR);
4995+ AuDebugOn(au_digen(parent) != sigen
4996+ || au_iigen(parent->d_inode) != sigen);
4997+ au_dbg_verify_gen(parent, sigen);
4998+
4999+ /* returns a number of positive dentries */
5000+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
5001+ if (err >= 0)
5002+ err = au_refresh_hinode(inode, dentry);
5003+
5004+ di_read_unlock(parent, AuLock_IR);
5005+ dput(parent);
5006+ return err;
5007+}
5008+
5009+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
5010+{
5011+ int err;
5012+ struct dentry *d, *parent;
5013+ struct inode *inode;
5014+
5015+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
5016+ return simple_reval_dpath(dentry, sigen);
5017+
5018+ /* slow loop, keep it simple and stupid */
5019+ /* cf: au_cpup_dirs() */
5020+ err = 0;
5021+ parent = NULL;
5022+ while (au_digen(dentry) != sigen
5023+ || au_iigen(dentry->d_inode) != sigen) {
5024+ d = dentry;
5025+ while (1) {
5026+ dput(parent);
5027+ parent = dget_parent(d);
5028+ if (au_digen(parent) == sigen
5029+ && au_iigen(parent->d_inode) == sigen)
5030+ break;
5031+ d = parent;
5032+ }
5033+
5034+ inode = d->d_inode;
5035+ if (d != dentry)
5036+ di_write_lock_child(d);
5037+
5038+ /* someone might update our dentry while we were sleeping */
5039+ if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
5040+ di_read_lock_parent(parent, AuLock_IR);
5041+ /* returns a number of positive dentries */
5042+ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
5043+ if (err >= 0)
5044+ err = au_refresh_hinode(inode, d);
5045+ di_read_unlock(parent, AuLock_IR);
5046+ }
5047+
5048+ if (d != dentry)
5049+ di_write_unlock(d);
5050+ dput(parent);
5051+ if (unlikely(err))
5052+ break;
5053+ }
5054+
5055+ return err;
5056+}
5057+
5058+/*
5059+ * if valid returns 1, otherwise 0.
5060+ */
5061+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
5062+{
5063+ int valid, err;
5064+ unsigned int sigen;
5065+ unsigned char do_udba;
5066+ struct super_block *sb;
5067+ struct inode *inode;
5068+
953406b4 5069+ err = -EINVAL;
1facf9fc 5070+ sb = dentry->d_sb;
5071+ inode = dentry->d_inode;
953406b4 5072+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
1facf9fc 5073+ sigen = au_sigen(sb);
5074+ if (au_digen(dentry) != sigen) {
5075+ AuDebugOn(IS_ROOT(dentry));
5076+ if (inode)
5077+ err = au_reval_dpath(dentry, sigen);
5078+ if (unlikely(err))
5079+ goto out_dgrade;
1facf9fc 5080+ }
5081+ if (inode && au_iigen(inode) != sigen) {
5082+ AuDebugOn(IS_ROOT(dentry));
5083+ err = au_refresh_hinode(inode, dentry);
5084+ if (unlikely(err))
5085+ goto out_dgrade;
1facf9fc 5086+ }
5087+ di_downgrade_lock(dentry, AuLock_IR);
5088+
1facf9fc 5089+ err = -EINVAL;
5090+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
5091+ if (do_udba && inode) {
5092+ aufs_bindex_t bstart = au_ibstart(inode);
5093+
5094+ if (bstart >= 0
5095+ && au_test_higen(inode, au_h_iptr(inode, bstart)))
953406b4 5096+ goto out;
1facf9fc 5097+ }
5098+
5099+ err = h_d_revalidate(dentry, inode, nd, do_udba);
5100+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
5101+ /* both of real entry and whiteout found */
5102+ err = -EIO;
953406b4 5103+ goto out;
1facf9fc 5104+
4f0767ce 5105+out_dgrade:
1facf9fc 5106+ di_downgrade_lock(dentry, AuLock_IR);
953406b4 5107+out:
1facf9fc 5108+ aufs_read_unlock(dentry, AuLock_IR);
5109+ AuTraceErr(err);
5110+ valid = !err;
5111+ if (!valid)
953406b4 5112+ AuDbg("%.*s invalid\n", AuDLNPair(dentry));
1facf9fc 5113+ return valid;
5114+}
5115+
5116+static void aufs_d_release(struct dentry *dentry)
5117+{
4a4d8108
AM
5118+ if (dentry->d_fsdata) {
5119+ au_di_fin(dentry);
5120+ au_hn_di_reinit(dentry);
1facf9fc 5121+ }
1facf9fc 5122+}
5123+
4a4d8108 5124+const struct dentry_operations aufs_dop = {
1facf9fc 5125+ .d_revalidate = aufs_d_revalidate,
5126+ .d_release = aufs_d_release
5127+};
b752ccd1
AM
5128diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
5129--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
953406b4 5130+++ linux/fs/aufs/dentry.h 2010-10-21 09:52:43.086957936 +0200
1308ab2a 5131@@ -0,0 +1,231 @@
1facf9fc 5132+/*
4a4d8108 5133+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5134+ *
5135+ * This program, aufs is free software; you can redistribute it and/or modify
5136+ * it under the terms of the GNU General Public License as published by
5137+ * the Free Software Foundation; either version 2 of the License, or
5138+ * (at your option) any later version.
dece6358
AM
5139+ *
5140+ * This program is distributed in the hope that it will be useful,
5141+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5142+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5143+ * GNU General Public License for more details.
5144+ *
5145+ * You should have received a copy of the GNU General Public License
5146+ * along with this program; if not, write to the Free Software
5147+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5148+ */
5149+
5150+/*
5151+ * lookup and dentry operations
5152+ */
5153+
5154+#ifndef __AUFS_DENTRY_H__
5155+#define __AUFS_DENTRY_H__
5156+
5157+#ifdef __KERNEL__
5158+
dece6358 5159+#include <linux/dcache.h>
1facf9fc 5160+#include <linux/aufs_type.h>
5161+#include "rwsem.h"
5162+
5163+/* make a single member structure for future use */
5164+/* todo: remove this structure */
5165+struct au_hdentry {
5166+ struct dentry *hd_dentry;
5167+};
5168+
5169+struct au_dinfo {
5170+ atomic_t di_generation;
5171+
dece6358 5172+ struct au_rwsem di_rwsem;
1facf9fc 5173+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
5174+ struct au_hdentry *di_hdentry;
4a4d8108 5175+} ____cacheline_aligned_in_smp;
1facf9fc 5176+
5177+/* ---------------------------------------------------------------------- */
5178+
5179+/* dentry.c */
4a4d8108 5180+extern const struct dentry_operations aufs_dop;
1facf9fc 5181+struct au_branch;
5182+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
5183+ struct au_branch *br, struct nameidata *nd);
5184+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
5185+ struct au_branch *br);
5186+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
5187+ struct dentry *h_parent, struct au_branch *br);
5188+
5189+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
5190+ struct nameidata *nd);
5191+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
5192+int au_refresh_hdentry(struct dentry *dentry, mode_t type);
5193+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
5194+
5195+/* dinfo.c */
4a4d8108
AM
5196+void au_di_init_once(void *_di);
5197+int au_di_init(struct dentry *dentry);
5198+void au_di_fin(struct dentry *dentry);
1facf9fc 5199+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
5200+
5201+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
5202+void di_read_unlock(struct dentry *d, int flags);
5203+void di_downgrade_lock(struct dentry *d, int flags);
5204+void di_write_lock(struct dentry *d, unsigned int lsc);
5205+void di_write_unlock(struct dentry *d);
5206+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
5207+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
5208+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
5209+
5210+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
5211+aufs_bindex_t au_dbtail(struct dentry *dentry);
5212+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
5213+
5214+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5215+ struct dentry *h_dentry);
5216+void au_update_digen(struct dentry *dentry);
5217+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5218+void au_update_dbstart(struct dentry *dentry);
5219+void au_update_dbend(struct dentry *dentry);
5220+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
5221+
5222+/* ---------------------------------------------------------------------- */
5223+
5224+static inline struct au_dinfo *au_di(struct dentry *dentry)
5225+{
5226+ return dentry->d_fsdata;
5227+}
5228+
5229+/* ---------------------------------------------------------------------- */
5230+
5231+/* lock subclass for dinfo */
5232+enum {
5233+ AuLsc_DI_CHILD, /* child first */
4a4d8108 5234+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 5235+ AuLsc_DI_CHILD3, /* copyup dirs */
5236+ AuLsc_DI_PARENT,
5237+ AuLsc_DI_PARENT2,
5238+ AuLsc_DI_PARENT3
5239+};
5240+
5241+/*
5242+ * di_read_lock_child, di_write_lock_child,
5243+ * di_read_lock_child2, di_write_lock_child2,
5244+ * di_read_lock_child3, di_write_lock_child3,
5245+ * di_read_lock_parent, di_write_lock_parent,
5246+ * di_read_lock_parent2, di_write_lock_parent2,
5247+ * di_read_lock_parent3, di_write_lock_parent3,
5248+ */
5249+#define AuReadLockFunc(name, lsc) \
5250+static inline void di_read_lock_##name(struct dentry *d, int flags) \
5251+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
5252+
5253+#define AuWriteLockFunc(name, lsc) \
5254+static inline void di_write_lock_##name(struct dentry *d) \
5255+{ di_write_lock(d, AuLsc_DI_##lsc); }
5256+
5257+#define AuRWLockFuncs(name, lsc) \
5258+ AuReadLockFunc(name, lsc) \
5259+ AuWriteLockFunc(name, lsc)
5260+
5261+AuRWLockFuncs(child, CHILD);
5262+AuRWLockFuncs(child2, CHILD2);
5263+AuRWLockFuncs(child3, CHILD3);
5264+AuRWLockFuncs(parent, PARENT);
5265+AuRWLockFuncs(parent2, PARENT2);
5266+AuRWLockFuncs(parent3, PARENT3);
5267+
5268+#undef AuReadLockFunc
5269+#undef AuWriteLockFunc
5270+#undef AuRWLockFuncs
5271+
5272+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
5273+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
5274+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 5275+
5276+/* ---------------------------------------------------------------------- */
5277+
5278+/* todo: memory barrier? */
5279+static inline unsigned int au_digen(struct dentry *d)
5280+{
5281+ return atomic_read(&au_di(d)->di_generation);
5282+}
5283+
5284+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
5285+{
5286+ hdentry->hd_dentry = NULL;
5287+}
5288+
5289+static inline void au_hdput(struct au_hdentry *hd)
5290+{
4a4d8108
AM
5291+ if (hd)
5292+ dput(hd->hd_dentry);
1facf9fc 5293+}
5294+
5295+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
5296+{
1308ab2a 5297+ DiMustAnyLock(dentry);
1facf9fc 5298+ return au_di(dentry)->di_bstart;
5299+}
5300+
5301+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
5302+{
1308ab2a 5303+ DiMustAnyLock(dentry);
1facf9fc 5304+ return au_di(dentry)->di_bend;
5305+}
5306+
5307+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
5308+{
1308ab2a 5309+ DiMustAnyLock(dentry);
1facf9fc 5310+ return au_di(dentry)->di_bwh;
5311+}
5312+
5313+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
5314+{
1308ab2a 5315+ DiMustAnyLock(dentry);
1facf9fc 5316+ return au_di(dentry)->di_bdiropq;
5317+}
5318+
5319+/* todo: hard/soft set? */
5320+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
5321+{
1308ab2a 5322+ DiMustWriteLock(dentry);
1facf9fc 5323+ au_di(dentry)->di_bstart = bindex;
5324+}
5325+
5326+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
5327+{
1308ab2a 5328+ DiMustWriteLock(dentry);
1facf9fc 5329+ au_di(dentry)->di_bend = bindex;
5330+}
5331+
5332+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
5333+{
1308ab2a 5334+ DiMustWriteLock(dentry);
1facf9fc 5335+ /* dbwh can be outside of bstart - bend range */
5336+ au_di(dentry)->di_bwh = bindex;
5337+}
5338+
5339+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
5340+{
1308ab2a 5341+ DiMustWriteLock(dentry);
1facf9fc 5342+ au_di(dentry)->di_bdiropq = bindex;
5343+}
5344+
5345+/* ---------------------------------------------------------------------- */
5346+
4a4d8108 5347+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 5348+static inline void au_digen_dec(struct dentry *d)
5349+{
953406b4 5350+ atomic_dec_return(&au_di(d)->di_generation);
1facf9fc 5351+}
5352+
4a4d8108 5353+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 5354+{
5355+ dentry->d_fsdata = NULL;
5356+}
5357+#else
4a4d8108
AM
5358+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
5359+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 5360+
5361+#endif /* __KERNEL__ */
5362+#endif /* __AUFS_DENTRY_H__ */
b752ccd1
AM
5363diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
5364--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
5365+++ linux/fs/aufs/dinfo.c 2010-10-21 09:52:43.086957936 +0200
5366@@ -0,0 +1,395 @@
1facf9fc 5367+/*
4a4d8108 5368+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5369+ *
5370+ * This program, aufs is free software; you can redistribute it and/or modify
5371+ * it under the terms of the GNU General Public License as published by
5372+ * the Free Software Foundation; either version 2 of the License, or
5373+ * (at your option) any later version.
dece6358
AM
5374+ *
5375+ * This program is distributed in the hope that it will be useful,
5376+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5377+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5378+ * GNU General Public License for more details.
5379+ *
5380+ * You should have received a copy of the GNU General Public License
5381+ * along with this program; if not, write to the Free Software
5382+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5383+ */
5384+
5385+/*
5386+ * dentry private data
5387+ */
5388+
5389+#include "aufs.h"
5390+
953406b4 5391+void au_di_init_once(void *_di)
4a4d8108 5392+{
953406b4 5393+ struct au_dinfo *di = _di;
4a4d8108 5394+
953406b4 5395+ au_rw_init(&di->di_rwsem);
4a4d8108
AM
5396+}
5397+
5398+int au_di_init(struct dentry *dentry)
1facf9fc 5399+{
5400+ struct au_dinfo *dinfo;
5401+ struct super_block *sb;
5402+ int nbr;
5403+
5404+ dinfo = au_cache_alloc_dinfo();
5405+ if (unlikely(!dinfo))
5406+ goto out;
5407+
5408+ sb = dentry->d_sb;
5409+ nbr = au_sbend(sb) + 1;
5410+ if (nbr <= 0)
5411+ nbr = 1;
5412+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
5413+ if (unlikely(!dinfo->di_hdentry))
5414+ goto out_dinfo;
5415+
5416+ atomic_set(&dinfo->di_generation, au_sigen(sb));
5417+ /* smp_mb(); */ /* atomic_set */
4a4d8108 5418+ au_rw_write_lock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
1facf9fc 5419+ dinfo->di_bstart = -1;
5420+ dinfo->di_bend = -1;
5421+ dinfo->di_bwh = -1;
5422+ dinfo->di_bdiropq = -1;
5423+
5424+ dentry->d_fsdata = dinfo;
5425+ dentry->d_op = &aufs_dop;
5426+ return 0; /* success */
5427+
4f0767ce 5428+out_dinfo:
1facf9fc 5429+ au_cache_free_dinfo(dinfo);
4f0767ce 5430+out:
1facf9fc 5431+ return -ENOMEM;
5432+}
5433+
4a4d8108
AM
5434+void au_di_fin(struct dentry *dentry)
5435+{
5436+ struct au_dinfo *di;
5437+ struct au_hdentry *p;
5438+ aufs_bindex_t bend, bindex;
5439+
5440+ /* dentry may not be revalidated */
5441+ di = dentry->d_fsdata;
5442+ bindex = di->di_bstart;
5443+ if (bindex >= 0) {
5444+ bend = di->di_bend;
5445+ p = di->di_hdentry + bindex;
5446+ while (bindex++ <= bend)
5447+ au_hdput(p++);
5448+ }
5449+ kfree(di->di_hdentry);
5450+ AuRwDestroy(&di->di_rwsem);
5451+ au_cache_free_dinfo(di);
5452+}
5453+
1facf9fc 5454+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
5455+{
5456+ int err, sz;
5457+ struct au_hdentry *hdp;
5458+
1308ab2a 5459+ AuRwMustWriteLock(&dinfo->di_rwsem);
5460+
1facf9fc 5461+ err = -ENOMEM;
5462+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
5463+ if (!sz)
5464+ sz = sizeof(*hdp);
5465+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
5466+ if (hdp) {
5467+ dinfo->di_hdentry = hdp;
5468+ err = 0;
5469+ }
5470+
5471+ return err;
5472+}
5473+
5474+/* ---------------------------------------------------------------------- */
5475+
5476+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
5477+{
5478+ switch (lsc) {
5479+ case AuLsc_DI_CHILD:
5480+ ii_write_lock_child(inode);
5481+ break;
5482+ case AuLsc_DI_CHILD2:
5483+ ii_write_lock_child2(inode);
5484+ break;
5485+ case AuLsc_DI_CHILD3:
5486+ ii_write_lock_child3(inode);
5487+ break;
5488+ case AuLsc_DI_PARENT:
5489+ ii_write_lock_parent(inode);
5490+ break;
5491+ case AuLsc_DI_PARENT2:
5492+ ii_write_lock_parent2(inode);
5493+ break;
5494+ case AuLsc_DI_PARENT3:
5495+ ii_write_lock_parent3(inode);
5496+ break;
5497+ default:
5498+ BUG();
5499+ }
5500+}
5501+
5502+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
5503+{
5504+ switch (lsc) {
5505+ case AuLsc_DI_CHILD:
5506+ ii_read_lock_child(inode);
5507+ break;
5508+ case AuLsc_DI_CHILD2:
5509+ ii_read_lock_child2(inode);
5510+ break;
5511+ case AuLsc_DI_CHILD3:
5512+ ii_read_lock_child3(inode);
5513+ break;
5514+ case AuLsc_DI_PARENT:
5515+ ii_read_lock_parent(inode);
5516+ break;
5517+ case AuLsc_DI_PARENT2:
5518+ ii_read_lock_parent2(inode);
5519+ break;
5520+ case AuLsc_DI_PARENT3:
5521+ ii_read_lock_parent3(inode);
5522+ break;
5523+ default:
5524+ BUG();
5525+ }
5526+}
5527+
5528+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
5529+{
dece6358 5530+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5531+ if (d->d_inode) {
5532+ if (au_ftest_lock(flags, IW))
5533+ do_ii_write_lock(d->d_inode, lsc);
5534+ else if (au_ftest_lock(flags, IR))
5535+ do_ii_read_lock(d->d_inode, lsc);
5536+ }
5537+}
5538+
5539+void di_read_unlock(struct dentry *d, int flags)
5540+{
5541+ if (d->d_inode) {
5542+ if (au_ftest_lock(flags, IW))
5543+ ii_write_unlock(d->d_inode);
5544+ else if (au_ftest_lock(flags, IR))
5545+ ii_read_unlock(d->d_inode);
5546+ }
dece6358 5547+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 5548+}
5549+
5550+void di_downgrade_lock(struct dentry *d, int flags)
5551+{
1facf9fc 5552+ if (d->d_inode && au_ftest_lock(flags, IR))
5553+ ii_downgrade_lock(d->d_inode);
dece6358 5554+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 5555+}
5556+
5557+void di_write_lock(struct dentry *d, unsigned int lsc)
5558+{
dece6358 5559+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5560+ if (d->d_inode)
5561+ do_ii_write_lock(d->d_inode, lsc);
5562+}
5563+
5564+void di_write_unlock(struct dentry *d)
5565+{
5566+ if (d->d_inode)
5567+ ii_write_unlock(d->d_inode);
dece6358 5568+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 5569+}
5570+
5571+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
5572+{
5573+ AuDebugOn(d1 == d2
5574+ || d1->d_inode == d2->d_inode
5575+ || d1->d_sb != d2->d_sb);
5576+
5577+ if (isdir && au_test_subdir(d1, d2)) {
5578+ di_write_lock_child(d1);
5579+ di_write_lock_child2(d2);
5580+ } else {
5581+ /* there should be no races */
5582+ di_write_lock_child(d2);
5583+ di_write_lock_child2(d1);
5584+ }
5585+}
5586+
5587+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
5588+{
5589+ AuDebugOn(d1 == d2
5590+ || d1->d_inode == d2->d_inode
5591+ || d1->d_sb != d2->d_sb);
5592+
5593+ if (isdir && au_test_subdir(d1, d2)) {
5594+ di_write_lock_parent(d1);
5595+ di_write_lock_parent2(d2);
5596+ } else {
5597+ /* there should be no races */
5598+ di_write_lock_parent(d2);
5599+ di_write_lock_parent2(d1);
5600+ }
5601+}
5602+
5603+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
5604+{
5605+ di_write_unlock(d1);
5606+ if (d1->d_inode == d2->d_inode)
dece6358 5607+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 5608+ else
5609+ di_write_unlock(d2);
5610+}
5611+
5612+/* ---------------------------------------------------------------------- */
5613+
5614+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
5615+{
5616+ struct dentry *d;
5617+
1308ab2a 5618+ DiMustAnyLock(dentry);
5619+
1facf9fc 5620+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
5621+ return NULL;
5622+ AuDebugOn(bindex < 0);
5623+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
5624+ AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
5625+ return d;
5626+}
5627+
5628+aufs_bindex_t au_dbtail(struct dentry *dentry)
5629+{
5630+ aufs_bindex_t bend, bwh;
5631+
5632+ bend = au_dbend(dentry);
5633+ if (0 <= bend) {
5634+ bwh = au_dbwh(dentry);
5635+ if (!bwh)
5636+ return bwh;
5637+ if (0 < bwh && bwh < bend)
5638+ return bwh - 1;
5639+ }
5640+ return bend;
5641+}
5642+
5643+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
5644+{
5645+ aufs_bindex_t bend, bopq;
5646+
5647+ bend = au_dbtail(dentry);
5648+ if (0 <= bend) {
5649+ bopq = au_dbdiropq(dentry);
5650+ if (0 <= bopq && bopq < bend)
5651+ bend = bopq;
5652+ }
5653+ return bend;
5654+}
5655+
5656+/* ---------------------------------------------------------------------- */
5657+
5658+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5659+ struct dentry *h_dentry)
5660+{
5661+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
5662+
1308ab2a 5663+ DiMustWriteLock(dentry);
5664+
4a4d8108 5665+ au_hdput(hd);
1facf9fc 5666+ hd->hd_dentry = h_dentry;
5667+}
5668+
5669+void au_update_digen(struct dentry *dentry)
5670+{
5671+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
5672+ /* smp_mb(); */ /* atomic_set */
5673+}
5674+
5675+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
5676+{
5677+ struct au_dinfo *dinfo;
5678+ struct dentry *h_d;
4a4d8108 5679+ struct au_hdentry *hdp;
1facf9fc 5680+
1308ab2a 5681+ DiMustWriteLock(dentry);
5682+
1facf9fc 5683+ dinfo = au_di(dentry);
5684+ if (!dinfo || dinfo->di_bstart < 0)
5685+ return;
5686+
4a4d8108 5687+ hdp = dinfo->di_hdentry;
1facf9fc 5688+ if (do_put_zero) {
5689+ aufs_bindex_t bindex, bend;
5690+
5691+ bend = dinfo->di_bend;
5692+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 5693+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 5694+ if (h_d && !h_d->d_inode)
5695+ au_set_h_dptr(dentry, bindex, NULL);
5696+ }
5697+ }
5698+
5699+ dinfo->di_bstart = -1;
5700+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 5701+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 5702+ break;
5703+ if (dinfo->di_bstart > dinfo->di_bend) {
5704+ dinfo->di_bstart = -1;
5705+ dinfo->di_bend = -1;
5706+ return;
5707+ }
5708+
5709+ dinfo->di_bend++;
5710+ while (0 <= --dinfo->di_bend)
4a4d8108 5711+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 5712+ break;
5713+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
5714+}
5715+
5716+void au_update_dbstart(struct dentry *dentry)
5717+{
5718+ aufs_bindex_t bindex, bend;
5719+ struct dentry *h_dentry;
5720+
5721+ bend = au_dbend(dentry);
5722+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
5723+ h_dentry = au_h_dptr(dentry, bindex);
5724+ if (!h_dentry)
5725+ continue;
5726+ if (h_dentry->d_inode) {
5727+ au_set_dbstart(dentry, bindex);
5728+ return;
5729+ }
5730+ au_set_h_dptr(dentry, bindex, NULL);
5731+ }
5732+}
5733+
5734+void au_update_dbend(struct dentry *dentry)
5735+{
5736+ aufs_bindex_t bindex, bstart;
5737+ struct dentry *h_dentry;
5738+
5739+ bstart = au_dbstart(dentry);
5740+ for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
5741+ h_dentry = au_h_dptr(dentry, bindex);
5742+ if (!h_dentry)
5743+ continue;
5744+ if (h_dentry->d_inode) {
5745+ au_set_dbend(dentry, bindex);
5746+ return;
5747+ }
5748+ au_set_h_dptr(dentry, bindex, NULL);
5749+ }
5750+}
5751+
5752+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
5753+{
5754+ aufs_bindex_t bindex, bend;
5755+
5756+ bend = au_dbend(dentry);
5757+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
5758+ if (au_h_dptr(dentry, bindex) == h_dentry)
5759+ return bindex;
5760+ return -1;
5761+}
b752ccd1
AM
5762diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
5763--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
5764+++ linux/fs/aufs/dir.c 2010-10-21 09:52:43.086957936 +0200
5765@@ -0,0 +1,638 @@
1facf9fc 5766+/*
4a4d8108 5767+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5768+ *
5769+ * This program, aufs is free software; you can redistribute it and/or modify
5770+ * it under the terms of the GNU General Public License as published by
5771+ * the Free Software Foundation; either version 2 of the License, or
5772+ * (at your option) any later version.
dece6358
AM
5773+ *
5774+ * This program is distributed in the hope that it will be useful,
5775+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5776+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5777+ * GNU General Public License for more details.
5778+ *
5779+ * You should have received a copy of the GNU General Public License
5780+ * along with this program; if not, write to the Free Software
5781+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5782+ */
5783+
5784+/*
5785+ * directory operations
5786+ */
5787+
dece6358 5788+#include <linux/file.h>
1facf9fc 5789+#include <linux/fs_stack.h>
5790+#include "aufs.h"
5791+
5792+void au_add_nlink(struct inode *dir, struct inode *h_dir)
5793+{
5794+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5795+
5796+ dir->i_nlink += h_dir->i_nlink - 2;
5797+ if (h_dir->i_nlink < 2)
5798+ dir->i_nlink += 2;
5799+}
5800+
5801+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
5802+{
5803+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5804+
5805+ dir->i_nlink -= h_dir->i_nlink - 2;
5806+ if (h_dir->i_nlink < 2)
5807+ dir->i_nlink -= 2;
5808+}
5809+
1308ab2a 5810+loff_t au_dir_size(struct file *file, struct dentry *dentry)
5811+{
5812+ loff_t sz;
5813+ aufs_bindex_t bindex, bend;
5814+ struct file *h_file;
5815+ struct dentry *h_dentry;
5816+
5817+ sz = 0;
5818+ if (file) {
5819+ AuDebugOn(!file->f_dentry);
5820+ AuDebugOn(!file->f_dentry->d_inode);
5821+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
5822+
4a4d8108 5823+ bend = au_fbend_dir(file);
1308ab2a 5824+ for (bindex = au_fbstart(file);
5825+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5826+ bindex++) {
4a4d8108 5827+ h_file = au_hf_dir(file, bindex);
1308ab2a 5828+ if (h_file
5829+ && h_file->f_dentry
5830+ && h_file->f_dentry->d_inode)
5831+ sz += i_size_read(h_file->f_dentry->d_inode);
5832+ }
5833+ } else {
5834+ AuDebugOn(!dentry);
5835+ AuDebugOn(!dentry->d_inode);
5836+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
5837+
5838+ bend = au_dbtaildir(dentry);
5839+ for (bindex = au_dbstart(dentry);
5840+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5841+ bindex++) {
5842+ h_dentry = au_h_dptr(dentry, bindex);
5843+ if (h_dentry && h_dentry->d_inode)
5844+ sz += i_size_read(h_dentry->d_inode);
5845+ }
5846+ }
5847+ if (sz < KMALLOC_MAX_SIZE)
5848+ sz = roundup_pow_of_two(sz);
5849+ if (sz > KMALLOC_MAX_SIZE)
5850+ sz = KMALLOC_MAX_SIZE;
5851+ else if (sz < NAME_MAX) {
5852+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
5853+ sz = AUFS_RDBLK_DEF;
5854+ }
5855+ return sz;
5856+}
5857+
1facf9fc 5858+/* ---------------------------------------------------------------------- */
5859+
5860+static int reopen_dir(struct file *file)
5861+{
5862+ int err;
5863+ unsigned int flags;
5864+ aufs_bindex_t bindex, btail, bstart;
5865+ struct dentry *dentry, *h_dentry;
5866+ struct file *h_file;
5867+
5868+ /* open all lower dirs */
5869+ dentry = file->f_dentry;
5870+ bstart = au_dbstart(dentry);
5871+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
5872+ au_set_h_fptr(file, bindex, NULL);
5873+ au_set_fbstart(file, bstart);
5874+
5875+ btail = au_dbtaildir(dentry);
4a4d8108 5876+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 5877+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 5878+ au_set_fbend_dir(file, btail);
1facf9fc 5879+
4a4d8108 5880+ flags = vfsub_file_flags(file);
1facf9fc 5881+ for (bindex = bstart; bindex <= btail; bindex++) {
5882+ h_dentry = au_h_dptr(dentry, bindex);
5883+ if (!h_dentry)
5884+ continue;
4a4d8108 5885+ h_file = au_hf_dir(file, bindex);
1facf9fc 5886+ if (h_file)
5887+ continue;
5888+
5889+ h_file = au_h_open(dentry, bindex, flags, file);
5890+ err = PTR_ERR(h_file);
5891+ if (IS_ERR(h_file))
5892+ goto out; /* close all? */
5893+ au_set_h_fptr(file, bindex, h_file);
5894+ }
5895+ au_update_figen(file);
5896+ /* todo: necessary? */
5897+ /* file->f_ra = h_file->f_ra; */
5898+ err = 0;
5899+
4f0767ce 5900+out:
1facf9fc 5901+ return err;
5902+}
5903+
5904+static int do_open_dir(struct file *file, int flags)
5905+{
5906+ int err;
5907+ aufs_bindex_t bindex, btail;
5908+ struct dentry *dentry, *h_dentry;
5909+ struct file *h_file;
5910+
1308ab2a 5911+ FiMustWriteLock(file);
5912+
1facf9fc 5913+ err = 0;
5914+ dentry = file->f_dentry;
1facf9fc 5915+ file->f_version = dentry->d_inode->i_version;
5916+ bindex = au_dbstart(dentry);
5917+ au_set_fbstart(file, bindex);
5918+ btail = au_dbtaildir(dentry);
4a4d8108 5919+ au_set_fbend_dir(file, btail);
1facf9fc 5920+ for (; !err && bindex <= btail; bindex++) {
5921+ h_dentry = au_h_dptr(dentry, bindex);
5922+ if (!h_dentry)
5923+ continue;
5924+
5925+ h_file = au_h_open(dentry, bindex, flags, file);
5926+ if (IS_ERR(h_file)) {
5927+ err = PTR_ERR(h_file);
5928+ break;
5929+ }
5930+ au_set_h_fptr(file, bindex, h_file);
5931+ }
5932+ au_update_figen(file);
5933+ /* todo: necessary? */
5934+ /* file->f_ra = h_file->f_ra; */
5935+ if (!err)
5936+ return 0; /* success */
5937+
5938+ /* close all */
5939+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
5940+ au_set_h_fptr(file, bindex, NULL);
5941+ au_set_fbstart(file, -1);
4a4d8108
AM
5942+ au_set_fbend_dir(file, -1);
5943+
1facf9fc 5944+ return err;
5945+}
5946+
5947+static int aufs_open_dir(struct inode *inode __maybe_unused,
5948+ struct file *file)
5949+{
4a4d8108
AM
5950+ int err;
5951+ struct super_block *sb;
5952+ struct au_fidir *fidir;
5953+
5954+ err = -ENOMEM;
5955+ sb = file->f_dentry->d_sb;
5956+ si_read_lock(sb, AuLock_FLUSH);
953406b4 5957+ fidir = au_fidir_alloc(inode->i_sb);
4a4d8108
AM
5958+ if (fidir) {
5959+ err = au_do_open(file, do_open_dir, fidir);
5960+ if (unlikely(err))
5961+ kfree(fidir);
5962+ }
5963+ si_read_unlock(sb);
5964+ return err;
1facf9fc 5965+}
5966+
5967+static int aufs_release_dir(struct inode *inode __maybe_unused,
5968+ struct file *file)
5969+{
5970+ struct au_vdir *vdir_cache;
5971+ struct super_block *sb;
4a4d8108
AM
5972+ struct au_finfo *finfo;
5973+ struct au_fidir *fidir;
5974+ aufs_bindex_t bindex, bend;
1facf9fc 5975+
953406b4 5976+ au_plink_maint_leave(file);
1facf9fc 5977+ sb = file->f_dentry->d_sb;
4a4d8108
AM
5978+ finfo = au_fi(file);
5979+ fidir = finfo->fi_hdir;
5980+ if (fidir) {
5981+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
5982+ if (vdir_cache)
5983+ au_vdir_free(vdir_cache);
5984+
5985+ bindex = finfo->fi_btop;
5986+ if (bindex >= 0) {
5987+ /*
5988+ * calls fput() instead of filp_close(),
5989+ * since no dnotify or lock for the lower file.
5990+ */
5991+ bend = fidir->fd_bbot;
5992+ for (; bindex <= bend; bindex++)
5993+ au_set_h_fptr(file, bindex, NULL);
5994+ }
5995+ kfree(fidir);
5996+ finfo->fi_hdir = NULL;
1facf9fc 5997+ }
1facf9fc 5998+ au_finfo_fin(file);
1facf9fc 5999+ return 0;
6000+}
6001+
6002+/* ---------------------------------------------------------------------- */
6003+
4a4d8108
AM
6004+static int au_do_flush_dir(struct file *file, fl_owner_t id)
6005+{
6006+ int err;
6007+ aufs_bindex_t bindex, bend;
6008+ struct file *h_file;
6009+
6010+ err = 0;
6011+ bend = au_fbend_dir(file);
6012+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
6013+ h_file = au_hf_dir(file, bindex);
6014+ if (h_file)
6015+ err = vfsub_flush(h_file, id);
6016+ }
6017+ return err;
6018+}
6019+
6020+static int aufs_flush_dir(struct file *file, fl_owner_t id)
6021+{
6022+ return au_do_flush(file, id, au_do_flush_dir);
6023+}
6024+
6025+/* ---------------------------------------------------------------------- */
6026+
1facf9fc 6027+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
6028+{
6029+ int err;
6030+ aufs_bindex_t bend, bindex;
6031+ struct inode *inode;
6032+ struct super_block *sb;
6033+
6034+ err = 0;
6035+ sb = dentry->d_sb;
6036+ inode = dentry->d_inode;
6037+ IMustLock(inode);
6038+ bend = au_dbend(dentry);
6039+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
6040+ struct path h_path;
6041+ struct inode *h_inode;
6042+
6043+ if (au_test_ro(sb, bindex, inode))
6044+ continue;
6045+ h_path.dentry = au_h_dptr(dentry, bindex);
6046+ if (!h_path.dentry)
6047+ continue;
6048+ h_inode = h_path.dentry->d_inode;
6049+ if (!h_inode)
6050+ continue;
6051+
6052+ /* no mnt_want_write() */
6053+ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
6054+ /* todo: inotiry fired? */
6055+ h_path.mnt = au_sbr_mnt(sb, bindex);
6056+ mutex_lock(&h_inode->i_mutex);
6057+ err = filemap_fdatawrite(h_inode->i_mapping);
6058+ AuDebugOn(!h_inode->i_fop);
6059+ if (!err && h_inode->i_fop->fsync)
b752ccd1 6060+ err = h_inode->i_fop->fsync(NULL, datasync);
1facf9fc 6061+ if (!err)
6062+ err = filemap_fdatawrite(h_inode->i_mapping);
6063+ if (!err)
6064+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
6065+ mutex_unlock(&h_inode->i_mutex);
6066+ }
6067+
6068+ return err;
6069+}
6070+
6071+static int au_do_fsync_dir(struct file *file, int datasync)
6072+{
6073+ int err;
6074+ aufs_bindex_t bend, bindex;
6075+ struct file *h_file;
6076+ struct super_block *sb;
6077+ struct inode *inode;
6078+ struct mutex *h_mtx;
6079+
6080+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6081+ if (unlikely(err))
6082+ goto out;
6083+
6084+ sb = file->f_dentry->d_sb;
6085+ inode = file->f_dentry->d_inode;
4a4d8108 6086+ bend = au_fbend_dir(file);
1facf9fc 6087+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 6088+ h_file = au_hf_dir(file, bindex);
1facf9fc 6089+ if (!h_file || au_test_ro(sb, bindex, inode))
6090+ continue;
6091+
b752ccd1 6092+ err = vfs_fsync(h_file, datasync);
1facf9fc 6093+ if (!err) {
6094+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
6095+ mutex_lock(h_mtx);
6096+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
6097+ /*ignore*/
6098+ mutex_unlock(h_mtx);
6099+ }
6100+ }
6101+
4f0767ce 6102+out:
1facf9fc 6103+ return err;
6104+}
6105+
6106+/*
6107+ * @file may be NULL
6108+ */
b752ccd1 6109+static int aufs_fsync_dir(struct file *file, int datasync)
1facf9fc 6110+{
6111+ int err;
b752ccd1 6112+ struct dentry *dentry;
1facf9fc 6113+ struct super_block *sb;
6114+
b752ccd1 6115+ dentry = file->f_dentry;
1facf9fc 6116+ IMustLock(dentry->d_inode);
6117+
6118+ err = 0;
6119+ sb = dentry->d_sb;
6120+ si_noflush_read_lock(sb);
6121+ if (file)
6122+ err = au_do_fsync_dir(file, datasync);
6123+ else {
6124+ di_write_lock_child(dentry);
6125+ err = au_do_fsync_dir_no_file(dentry, datasync);
6126+ }
6127+ au_cpup_attr_timesizes(dentry->d_inode);
6128+ di_write_unlock(dentry);
6129+ if (file)
6130+ fi_write_unlock(file);
6131+
6132+ si_read_unlock(sb);
6133+ return err;
6134+}
6135+
6136+/* ---------------------------------------------------------------------- */
6137+
6138+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
6139+{
6140+ int err;
6141+ struct dentry *dentry;
6142+ struct inode *inode;
6143+ struct super_block *sb;
6144+
6145+ dentry = file->f_dentry;
6146+ inode = dentry->d_inode;
6147+ IMustLock(inode);
6148+
6149+ sb = dentry->d_sb;
6150+ si_read_lock(sb, AuLock_FLUSH);
6151+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6152+ if (unlikely(err))
6153+ goto out;
6154+ err = au_vdir_init(file);
6155+ di_downgrade_lock(dentry, AuLock_IR);
6156+ if (unlikely(err))
6157+ goto out_unlock;
6158+
b752ccd1 6159+ if (!au_test_nfsd()) {
1facf9fc 6160+ err = au_vdir_fill_de(file, dirent, filldir);
6161+ fsstack_copy_attr_atime(inode,
6162+ au_h_iptr(inode, au_ibstart(inode)));
6163+ } else {
6164+ /*
6165+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
6166+ * encode_fh() and others.
6167+ */
6168+ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
6169+
6170+ di_read_unlock(dentry, AuLock_IR);
6171+ si_read_unlock(sb);
1facf9fc 6172+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 6173+ fsstack_copy_attr_atime(inode, h_inode);
6174+ fi_write_unlock(file);
6175+
6176+ AuTraceErr(err);
6177+ return err;
6178+ }
6179+
4f0767ce 6180+out_unlock:
1facf9fc 6181+ di_read_unlock(dentry, AuLock_IR);
6182+ fi_write_unlock(file);
4f0767ce 6183+out:
1facf9fc 6184+ si_read_unlock(sb);
6185+ return err;
6186+}
6187+
6188+/* ---------------------------------------------------------------------- */
6189+
6190+#define AuTestEmpty_WHONLY 1
dece6358
AM
6191+#define AuTestEmpty_CALLED (1 << 1)
6192+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 6193+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
6194+#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
6195+#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
6196+
dece6358
AM
6197+#ifndef CONFIG_AUFS_SHWH
6198+#undef AuTestEmpty_SHWH
6199+#define AuTestEmpty_SHWH 0
6200+#endif
6201+
1facf9fc 6202+struct test_empty_arg {
1308ab2a 6203+ struct au_nhash *whlist;
1facf9fc 6204+ unsigned int flags;
6205+ int err;
6206+ aufs_bindex_t bindex;
6207+};
6208+
6209+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
6210+ loff_t offset __maybe_unused, u64 ino,
6211+ unsigned int d_type)
1facf9fc 6212+{
6213+ struct test_empty_arg *arg = __arg;
6214+ char *name = (void *)__name;
6215+
6216+ arg->err = 0;
6217+ au_fset_testempty(arg->flags, CALLED);
6218+ /* smp_mb(); */
6219+ if (name[0] == '.'
6220+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
6221+ goto out; /* success */
6222+
6223+ if (namelen <= AUFS_WH_PFX_LEN
6224+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
6225+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 6226+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6227+ arg->err = -ENOTEMPTY;
6228+ goto out;
6229+ }
6230+
6231+ name += AUFS_WH_PFX_LEN;
6232+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 6233+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6234+ arg->err = au_nhash_append_wh
1308ab2a 6235+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 6236+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 6237+
4f0767ce 6238+out:
1facf9fc 6239+ /* smp_mb(); */
6240+ AuTraceErr(arg->err);
6241+ return arg->err;
6242+}
6243+
6244+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6245+{
6246+ int err;
6247+ struct file *h_file;
6248+
6249+ h_file = au_h_open(dentry, arg->bindex,
6250+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
6251+ /*file*/NULL);
6252+ err = PTR_ERR(h_file);
6253+ if (IS_ERR(h_file))
6254+ goto out;
6255+
6256+ err = 0;
6257+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
6258+ && !h_file->f_dentry->d_inode->i_nlink)
6259+ goto out_put;
6260+
6261+ do {
6262+ arg->err = 0;
6263+ au_fclr_testempty(arg->flags, CALLED);
6264+ /* smp_mb(); */
6265+ err = vfsub_readdir(h_file, test_empty_cb, arg);
6266+ if (err >= 0)
6267+ err = arg->err;
6268+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
6269+
4f0767ce 6270+out_put:
1facf9fc 6271+ fput(h_file);
6272+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 6273+out:
1facf9fc 6274+ return err;
6275+}
6276+
6277+struct do_test_empty_args {
6278+ int *errp;
6279+ struct dentry *dentry;
6280+ struct test_empty_arg *arg;
6281+};
6282+
6283+static void call_do_test_empty(void *args)
6284+{
6285+ struct do_test_empty_args *a = args;
6286+ *a->errp = do_test_empty(a->dentry, a->arg);
6287+}
6288+
6289+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6290+{
6291+ int err, wkq_err;
6292+ struct dentry *h_dentry;
6293+ struct inode *h_inode;
6294+
6295+ h_dentry = au_h_dptr(dentry, arg->bindex);
6296+ h_inode = h_dentry->d_inode;
6297+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
6298+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
6299+ mutex_unlock(&h_inode->i_mutex);
6300+ if (!err)
6301+ err = do_test_empty(dentry, arg);
6302+ else {
6303+ struct do_test_empty_args args = {
6304+ .errp = &err,
6305+ .dentry = dentry,
6306+ .arg = arg
6307+ };
6308+ unsigned int flags = arg->flags;
6309+
6310+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
6311+ if (unlikely(wkq_err))
6312+ err = wkq_err;
6313+ arg->flags = flags;
6314+ }
6315+
6316+ return err;
6317+}
6318+
6319+int au_test_empty_lower(struct dentry *dentry)
6320+{
6321+ int err;
1308ab2a 6322+ unsigned int rdhash;
1facf9fc 6323+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 6324+ struct au_nhash whlist;
1facf9fc 6325+ struct test_empty_arg arg;
1facf9fc 6326+
dece6358
AM
6327+ SiMustAnyLock(dentry->d_sb);
6328+
1308ab2a 6329+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
6330+ if (!rdhash)
6331+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
6332+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 6333+ if (unlikely(err))
1facf9fc 6334+ goto out;
6335+
1facf9fc 6336+ arg.flags = 0;
1308ab2a 6337+ arg.whlist = &whlist;
6338+ bstart = au_dbstart(dentry);
dece6358
AM
6339+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6340+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 6341+ arg.bindex = bstart;
6342+ err = do_test_empty(dentry, &arg);
6343+ if (unlikely(err))
6344+ goto out_whlist;
6345+
6346+ au_fset_testempty(arg.flags, WHONLY);
6347+ btail = au_dbtaildir(dentry);
6348+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
6349+ struct dentry *h_dentry;
6350+
6351+ h_dentry = au_h_dptr(dentry, bindex);
6352+ if (h_dentry && h_dentry->d_inode) {
6353+ arg.bindex = bindex;
6354+ err = do_test_empty(dentry, &arg);
6355+ }
6356+ }
6357+
4f0767ce 6358+out_whlist:
1308ab2a 6359+ au_nhash_wh_free(&whlist);
4f0767ce 6360+out:
1facf9fc 6361+ return err;
6362+}
6363+
6364+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
6365+{
6366+ int err;
6367+ struct test_empty_arg arg;
6368+ aufs_bindex_t bindex, btail;
6369+
6370+ err = 0;
1308ab2a 6371+ arg.whlist = whlist;
1facf9fc 6372+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
6373+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6374+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 6375+ btail = au_dbtaildir(dentry);
6376+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
6377+ struct dentry *h_dentry;
6378+
6379+ h_dentry = au_h_dptr(dentry, bindex);
6380+ if (h_dentry && h_dentry->d_inode) {
6381+ arg.bindex = bindex;
6382+ err = sio_test_empty(dentry, &arg);
6383+ }
6384+ }
6385+
6386+ return err;
6387+}
6388+
6389+/* ---------------------------------------------------------------------- */
6390+
6391+const struct file_operations aufs_dir_fop = {
4a4d8108 6392+ .owner = THIS_MODULE,
1facf9fc 6393+ .read = generic_read_dir,
6394+ .readdir = aufs_readdir,
6395+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
6396+#ifdef CONFIG_COMPAT
6397+ .compat_ioctl = aufs_compat_ioctl_dir,
6398+#endif
1facf9fc 6399+ .open = aufs_open_dir,
6400+ .release = aufs_release_dir,
4a4d8108 6401+ .flush = aufs_flush_dir,
1facf9fc 6402+ .fsync = aufs_fsync_dir
6403+};
b752ccd1
AM
6404diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
6405--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
953406b4 6406+++ linux/fs/aufs/dir.h 2010-10-21 09:52:43.086957936 +0200
b752ccd1 6407@@ -0,0 +1,138 @@
1facf9fc 6408+/*
4a4d8108 6409+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 6410+ *
6411+ * This program, aufs is free software; you can redistribute it and/or modify
6412+ * it under the terms of the GNU General Public License as published by
6413+ * the Free Software Foundation; either version 2 of the License, or
6414+ * (at your option) any later version.
dece6358
AM
6415+ *
6416+ * This program is distributed in the hope that it will be useful,
6417+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6418+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6419+ * GNU General Public License for more details.
6420+ *
6421+ * You should have received a copy of the GNU General Public License
6422+ * along with this program; if not, write to the Free Software
6423+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6424+ */
6425+
6426+/*
6427+ * directory operations
6428+ */
6429+
6430+#ifndef __AUFS_DIR_H__
6431+#define __AUFS_DIR_H__
6432+
6433+#ifdef __KERNEL__
6434+
6435+#include <linux/fs.h>
6436+#include <linux/aufs_type.h>
6437+
6438+/* ---------------------------------------------------------------------- */
6439+
6440+/* need to be faster and smaller */
6441+
6442+struct au_nhash {
dece6358
AM
6443+ unsigned int nh_num;
6444+ struct hlist_head *nh_head;
1facf9fc 6445+};
6446+
6447+struct au_vdir_destr {
6448+ unsigned char len;
6449+ unsigned char name[0];
6450+} __packed;
6451+
6452+struct au_vdir_dehstr {
6453+ struct hlist_node hash;
6454+ struct au_vdir_destr *str;
4a4d8108 6455+} ____cacheline_aligned_in_smp;
1facf9fc 6456+
6457+struct au_vdir_de {
6458+ ino_t de_ino;
6459+ unsigned char de_type;
6460+ /* caution: packed */
6461+ struct au_vdir_destr de_str;
6462+} __packed;
6463+
6464+struct au_vdir_wh {
6465+ struct hlist_node wh_hash;
dece6358
AM
6466+#ifdef CONFIG_AUFS_SHWH
6467+ ino_t wh_ino;
1facf9fc 6468+ aufs_bindex_t wh_bindex;
dece6358
AM
6469+ unsigned char wh_type;
6470+#else
6471+ aufs_bindex_t wh_bindex;
6472+#endif
6473+ /* caution: packed */
1facf9fc 6474+ struct au_vdir_destr wh_str;
6475+} __packed;
6476+
6477+union au_vdir_deblk_p {
6478+ unsigned char *deblk;
6479+ struct au_vdir_de *de;
6480+};
6481+
6482+struct au_vdir {
6483+ unsigned char **vd_deblk;
6484+ unsigned long vd_nblk;
1facf9fc 6485+ struct {
6486+ unsigned long ul;
6487+ union au_vdir_deblk_p p;
6488+ } vd_last;
6489+
6490+ unsigned long vd_version;
dece6358 6491+ unsigned int vd_deblk_sz;
1facf9fc 6492+ unsigned long vd_jiffy;
4a4d8108 6493+} ____cacheline_aligned_in_smp;
1facf9fc 6494+
6495+/* ---------------------------------------------------------------------- */
6496+
6497+/* dir.c */
6498+extern const struct file_operations aufs_dir_fop;
6499+void au_add_nlink(struct inode *dir, struct inode *h_dir);
6500+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 6501+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 6502+int au_test_empty_lower(struct dentry *dentry);
6503+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
6504+
6505+/* vdir.c */
1308ab2a 6506+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
6507+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
6508+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 6509+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
6510+ int limit);
dece6358
AM
6511+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
6512+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
6513+ unsigned int d_type, aufs_bindex_t bindex,
6514+ unsigned char shwh);
1facf9fc 6515+void au_vdir_free(struct au_vdir *vdir);
6516+int au_vdir_init(struct file *file);
6517+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
6518+
6519+/* ioctl.c */
6520+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
6521+
1308ab2a 6522+#ifdef CONFIG_AUFS_RDU
6523+/* rdu.c */
6524+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
6525+#ifdef CONFIG_COMPAT
6526+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6527+ unsigned long arg);
6528+#endif
1308ab2a 6529+#else
6530+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
6531+ unsigned long arg)
6532+{
6533+ return -EINVAL;
6534+}
b752ccd1
AM
6535+#ifdef CONFIG_COMPAT
6536+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6537+ unsigned long arg)
6538+{
6539+ return -EINVAL;
6540+}
6541+#endif
1308ab2a 6542+#endif
6543+
1facf9fc 6544+#endif /* __KERNEL__ */
6545+#endif /* __AUFS_DIR_H__ */
b752ccd1
AM
6546diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
6547--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
953406b4 6548+++ linux/fs/aufs/dynop.c 2010-10-21 09:52:43.086957936 +0200
b752ccd1 6549@@ -0,0 +1,425 @@
1facf9fc 6550+/*
4a4d8108 6551+ * Copyright (C) 2010 Junjiro R. Okajima
1facf9fc 6552+ *
6553+ * This program, aufs is free software; you can redistribute it and/or modify
6554+ * it under the terms of the GNU General Public License as published by
6555+ * the Free Software Foundation; either version 2 of the License, or
6556+ * (at your option) any later version.
dece6358
AM
6557+ *
6558+ * This program is distributed in the hope that it will be useful,
6559+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6560+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6561+ * GNU General Public License for more details.
6562+ *
6563+ * You should have received a copy of the GNU General Public License
6564+ * along with this program; if not, write to the Free Software
6565+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6566+ */
6567+
6568+/*
4a4d8108 6569+ * dynamically customizable operations for regular files
1facf9fc 6570+ */
6571+
1facf9fc 6572+#include "aufs.h"
6573+
4a4d8108 6574+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 6575+
4a4d8108
AM
6576+/*
6577+ * How large will these lists be?
6578+ * Usually just a few elements, 20-30 at most for each, I guess.
6579+ */
6580+static struct au_splhead dynop[AuDyLast];
6581+
6582+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 6583+{
4a4d8108
AM
6584+ struct au_dykey *key, *tmp;
6585+ struct list_head *head;
1facf9fc 6586+
4a4d8108
AM
6587+ key = NULL;
6588+ head = &spl->head;
6589+ rcu_read_lock();
6590+ list_for_each_entry_rcu(tmp, head, dk_list)
6591+ if (tmp->dk_op.dy_hop == h_op) {
6592+ key = tmp;
6593+ kref_get(&key->dk_kref);
6594+ break;
6595+ }
6596+ rcu_read_unlock();
6597+
6598+ return key;
1facf9fc 6599+}
6600+
4a4d8108 6601+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 6602+{
4a4d8108
AM
6603+ struct au_dykey **k, *found;
6604+ const void *h_op = key->dk_op.dy_hop;
6605+ int i;
1facf9fc 6606+
4a4d8108
AM
6607+ found = NULL;
6608+ k = br->br_dykey;
6609+ for (i = 0; i < AuBrDynOp; i++)
6610+ if (k[i]) {
6611+ if (k[i]->dk_op.dy_hop == h_op) {
6612+ found = k[i];
6613+ break;
6614+ }
6615+ } else
6616+ break;
6617+ if (!found) {
6618+ spin_lock(&br->br_dykey_lock);
6619+ for (; i < AuBrDynOp; i++)
6620+ if (k[i]) {
6621+ if (k[i]->dk_op.dy_hop == h_op) {
6622+ found = k[i];
6623+ break;
6624+ }
6625+ } else {
6626+ k[i] = key;
6627+ break;
6628+ }
6629+ spin_unlock(&br->br_dykey_lock);
6630+ BUG_ON(i == AuBrDynOp); /* expand the array */
6631+ }
6632+
6633+ return found;
1facf9fc 6634+}
6635+
4a4d8108
AM
6636+/* kref_get() if @key is already added */
6637+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
6638+{
6639+ struct au_dykey *tmp, *found;
6640+ struct list_head *head;
6641+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 6642+
4a4d8108
AM
6643+ found = NULL;
6644+ head = &spl->head;
6645+ spin_lock(&spl->spin);
6646+ list_for_each_entry(tmp, head, dk_list)
6647+ if (tmp->dk_op.dy_hop == h_op) {
6648+ kref_get(&tmp->dk_kref);
6649+ found = tmp;
6650+ break;
6651+ }
6652+ if (!found)
6653+ list_add_rcu(&key->dk_list, head);
6654+ spin_unlock(&spl->spin);
1facf9fc 6655+
4a4d8108
AM
6656+ if (!found)
6657+ DyPrSym(key);
6658+ return found;
6659+}
6660+
6661+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 6662+{
4a4d8108
AM
6663+ struct au_dykey *key;
6664+
6665+ key = container_of(rcu, struct au_dykey, dk_rcu);
6666+ DyPrSym(key);
6667+ kfree(key);
1facf9fc 6668+}
6669+
4a4d8108
AM
6670+static void dy_free(struct kref *kref)
6671+{
6672+ struct au_dykey *key;
6673+ struct au_splhead *spl;
1facf9fc 6674+
4a4d8108
AM
6675+ key = container_of(kref, struct au_dykey, dk_kref);
6676+ spl = dynop + key->dk_op.dy_type;
6677+ au_spl_del_rcu(&key->dk_list, spl);
6678+ call_rcu(&key->dk_rcu, dy_free_rcu);
6679+}
6680+
6681+void au_dy_put(struct au_dykey *key)
1facf9fc 6682+{
4a4d8108
AM
6683+ kref_put(&key->dk_kref, dy_free);
6684+}
1facf9fc 6685+
4a4d8108
AM
6686+/* ---------------------------------------------------------------------- */
6687+
6688+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
6689+
6690+#ifdef CONFIG_AUFS_DEBUG
6691+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 6692+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
6693+#else
6694+#define DyDbgDeclare(cnt) do {} while (0)
6695+#define DyDbgInc(cnt) do {} while (0)
6696+#endif
6697+
6698+#define DySet(func, dst, src, h_op, h_sb) do { \
6699+ DyDbgInc(cnt); \
6700+ if (h_op->func) { \
6701+ if (src.func) \
6702+ dst.func = src.func; \
6703+ else \
6704+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
6705+ } \
6706+} while (0)
6707+
6708+#define DySetForce(func, dst, src) do { \
6709+ AuDebugOn(!src.func); \
6710+ DyDbgInc(cnt); \
6711+ dst.func = src.func; \
6712+} while (0)
6713+
6714+#define DySetAop(func) \
6715+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
6716+#define DySetAopForce(func) \
6717+ DySetForce(func, dyaop->da_op, aufs_aop)
6718+
6719+static void dy_aop(struct au_dykey *key, const void *h_op,
6720+ struct super_block *h_sb __maybe_unused)
6721+{
6722+ struct au_dyaop *dyaop = (void *)key;
6723+ const struct address_space_operations *h_aop = h_op;
6724+ DyDbgDeclare(cnt);
6725+
6726+ AuDbg("%s\n", au_sbtype(h_sb));
6727+
6728+ DySetAop(writepage);
6729+ DySetAopForce(readpage); /* force */
6730+ DySetAop(sync_page);
6731+ DySetAop(writepages);
6732+ DySetAop(set_page_dirty);
6733+ DySetAop(readpages);
6734+ DySetAop(write_begin);
6735+ DySetAop(write_end);
6736+ DySetAop(bmap);
6737+ DySetAop(invalidatepage);
6738+ DySetAop(releasepage);
6739+ /* these two will be changed according to an aufs mount option */
6740+ DySetAop(direct_IO);
6741+ DySetAop(get_xip_mem);
6742+ DySetAop(migratepage);
6743+ DySetAop(launder_page);
6744+ DySetAop(is_partially_uptodate);
6745+ DySetAop(error_remove_page);
6746+
6747+ DyDbgSize(cnt, *h_aop);
6748+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
6749+}
6750+
6751+#define DySetVmop(func) \
6752+ DySet(func, dyvmop->dv_op, aufs_vm_ops, h_vmop, h_sb)
6753+#define DySetVmopForce(func) \
6754+ DySetForce(func, dyvmop->dv_op, aufs_vm_ops)
6755+
6756+static void dy_vmop(struct au_dykey *key, const void *h_op,
6757+ struct super_block *h_sb __maybe_unused)
6758+{
6759+ struct au_dyvmop *dyvmop = (void *)key;
6760+ const struct vm_operations_struct *h_vmop = h_op;
6761+ DyDbgDeclare(cnt);
6762+
6763+ AuDbg("%s\n", au_sbtype(h_sb));
6764+
6765+ DySetVmop(open);
6766+ DySetVmop(close);
6767+ DySetVmop(fault);
6768+ DySetVmop(page_mkwrite);
6769+ DySetVmop(access);
6770+#ifdef CONFIG_NUMA
6771+ DySetVmop(set_policy);
6772+ DySetVmop(get_policy);
6773+ DySetVmop(migrate);
6774+#endif
6775+
6776+ DyDbgSize(cnt, *h_vmop);
6777+}
6778+
6779+/* ---------------------------------------------------------------------- */
6780+
6781+static void dy_bug(struct kref *kref)
6782+{
6783+ BUG();
6784+}
6785+
6786+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
6787+{
6788+ struct au_dykey *key, *old;
6789+ struct au_splhead *spl;
b752ccd1 6790+ struct op {
4a4d8108 6791+ unsigned int sz;
b752ccd1
AM
6792+ void (*set)(struct au_dykey *key, const void *h_op,
6793+ struct super_block *h_sb __maybe_unused);
6794+ };
6795+ static const struct op a[] = {
4a4d8108
AM
6796+ [AuDy_AOP] = {
6797+ .sz = sizeof(struct au_dyaop),
b752ccd1 6798+ .set = dy_aop
4a4d8108
AM
6799+ },
6800+ [AuDy_VMOP] = {
6801+ .sz = sizeof(struct au_dyvmop),
b752ccd1 6802+ .set = dy_vmop
4a4d8108 6803+ }
b752ccd1
AM
6804+ };
6805+ const struct op *p;
4a4d8108
AM
6806+
6807+ spl = dynop + op->dy_type;
6808+ key = dy_gfind_get(spl, op->dy_hop);
6809+ if (key)
6810+ goto out_add; /* success */
6811+
6812+ p = a + op->dy_type;
6813+ key = kzalloc(p->sz, GFP_NOFS);
6814+ if (unlikely(!key)) {
6815+ key = ERR_PTR(-ENOMEM);
6816+ goto out;
6817+ }
6818+
6819+ key->dk_op.dy_hop = op->dy_hop;
6820+ kref_init(&key->dk_kref);
b752ccd1 6821+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
6822+ old = dy_gadd(spl, key);
6823+ if (old) {
6824+ kfree(key);
6825+ key = old;
6826+ }
6827+
6828+out_add:
6829+ old = dy_bradd(br, key);
6830+ if (old)
6831+ /* its ref-count should never be zero here */
6832+ kref_put(&key->dk_kref, dy_bug);
6833+out:
6834+ return key;
6835+}
6836+
6837+/* ---------------------------------------------------------------------- */
6838+/*
6839+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
6840+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
6841+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
6842+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
6843+ * See the aufs manual in detail.
6844+ *
6845+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
6846+ * performance of fadvise() and madvise() may be affected.
6847+ */
6848+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
6849+{
6850+ if (!do_dx) {
6851+ dyaop->da_op.direct_IO = NULL;
6852+ dyaop->da_op.get_xip_mem = NULL;
6853+ } else {
6854+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
6855+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
6856+ if (!dyaop->da_get_xip_mem)
6857+ dyaop->da_op.get_xip_mem = NULL;
6858+ }
6859+}
6860+
6861+static struct au_dyaop *dy_aget(struct au_branch *br,
6862+ const struct address_space_operations *h_aop,
6863+ int do_dx)
6864+{
6865+ struct au_dyaop *dyaop;
6866+ struct au_dynop op;
6867+
6868+ op.dy_type = AuDy_AOP;
6869+ op.dy_haop = h_aop;
6870+ dyaop = (void *)dy_get(&op, br);
6871+ if (IS_ERR(dyaop))
6872+ goto out;
6873+ dy_adx(dyaop, do_dx);
6874+
6875+out:
6876+ return dyaop;
6877+}
6878+
6879+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
6880+ struct inode *h_inode)
6881+{
6882+ int err, do_dx;
6883+ struct super_block *sb;
6884+ struct au_branch *br;
6885+ struct au_dyaop *dyaop;
6886+
6887+ AuDebugOn(!S_ISREG(h_inode->i_mode));
6888+ IiMustWriteLock(inode);
6889+
6890+ sb = inode->i_sb;
6891+ br = au_sbr(sb, bindex);
6892+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
6893+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
6894+ err = PTR_ERR(dyaop);
6895+ if (IS_ERR(dyaop))
6896+ /* unnecessary to call dy_fput() */
6897+ goto out;
6898+
6899+ err = 0;
6900+ inode->i_mapping->a_ops = &dyaop->da_op;
6901+
6902+out:
6903+ return err;
6904+}
6905+
b752ccd1
AM
6906+/*
6907+ * Is it safe to replace a_ops during the inode/file is in operation?
6908+ * Yes, I hope so.
6909+ */
6910+int au_dy_irefresh(struct inode *inode)
6911+{
6912+ int err;
6913+ aufs_bindex_t bstart;
6914+ struct inode *h_inode;
6915+
6916+ err = 0;
6917+ if (S_ISREG(inode->i_mode)) {
6918+ bstart = au_ibstart(inode);
6919+ h_inode = au_h_iptr(inode, bstart);
6920+ err = au_dy_iaop(inode, bstart, h_inode);
6921+ }
6922+ return err;
6923+}
6924+
4a4d8108
AM
6925+void au_dy_arefresh(int do_dx)
6926+{
6927+ struct au_splhead *spl;
6928+ struct list_head *head;
6929+ struct au_dykey *key;
6930+
6931+ spl = dynop + AuDy_AOP;
6932+ head = &spl->head;
6933+ spin_lock(&spl->spin);
6934+ list_for_each_entry(key, head, dk_list)
6935+ dy_adx((void *)key, do_dx);
6936+ spin_unlock(&spl->spin);
6937+}
6938+
6939+const struct vm_operations_struct *
6940+au_dy_vmop(struct file *file, struct au_branch *br,
6941+ const struct vm_operations_struct *h_vmop)
6942+{
6943+ struct au_dyvmop *dyvmop;
6944+ struct au_dynop op;
6945+
6946+ op.dy_type = AuDy_VMOP;
6947+ op.dy_hvmop = h_vmop;
6948+ dyvmop = (void *)dy_get(&op, br);
6949+ if (IS_ERR(dyvmop))
6950+ return (void *)dyvmop;
6951+ return &dyvmop->dv_op;
6952+}
6953+
6954+/* ---------------------------------------------------------------------- */
6955+
6956+void __init au_dy_init(void)
6957+{
6958+ int i;
6959+
6960+ /* make sure that 'struct au_dykey *' can be any type */
6961+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
6962+ BUILD_BUG_ON(offsetof(struct au_dyvmop, dv_key));
6963+
6964+ for (i = 0; i < AuDyLast; i++)
6965+ au_spl_init(dynop + i);
6966+}
6967+
6968+void au_dy_fin(void)
6969+{
6970+ int i;
6971+
6972+ for (i = 0; i < AuDyLast; i++)
6973+ WARN_ON(!list_empty(&dynop[i].head));
6974+}
b752ccd1
AM
6975diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
6976--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
953406b4 6977+++ linux/fs/aufs/dynop.h 2010-10-21 09:52:43.086957936 +0200
b752ccd1 6978@@ -0,0 +1,89 @@
4a4d8108
AM
6979+/*
6980+ * Copyright (C) 2010 Junjiro R. Okajima
6981+ *
6982+ * This program, aufs is free software; you can redistribute it and/or modify
6983+ * it under the terms of the GNU General Public License as published by
6984+ * the Free Software Foundation; either version 2 of the License, or
6985+ * (at your option) any later version.
6986+ *
6987+ * This program is distributed in the hope that it will be useful,
6988+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6989+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6990+ * GNU General Public License for more details.
6991+ *
6992+ * You should have received a copy of the GNU General Public License
6993+ * along with this program; if not, write to the Free Software
6994+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6995+ */
6996+
6997+/*
6998+ * dynamically customizable operations (for regular files only)
6999+ */
7000+
7001+#ifndef __AUFS_DYNOP_H__
7002+#define __AUFS_DYNOP_H__
7003+
7004+#ifdef __KERNEL__
7005+
7006+#include <linux/fs.h>
7007+#include <linux/mm.h>
7008+#include <linux/rcupdate.h>
7009+#include <linux/aufs_type.h>
7010+#include "inode.h"
7011+
7012+enum {AuDy_AOP, AuDy_VMOP, AuDyLast};
7013+
7014+struct au_dynop {
7015+ int dy_type;
7016+ union {
7017+ const void *dy_hop;
7018+ const struct address_space_operations *dy_haop;
7019+ const struct vm_operations_struct *dy_hvmop;
7020+ };
7021+};
7022+
7023+struct au_dykey {
7024+ union {
7025+ struct list_head dk_list;
7026+ struct rcu_head dk_rcu;
7027+ };
7028+ struct au_dynop dk_op;
7029+
7030+ /*
7031+ * during I am in the branch local array, kref is gotten. when the
7032+ * branch is removed, kref is put.
7033+ */
7034+ struct kref dk_kref;
7035+};
7036+
7037+/* stop unioning since their sizes are very different from each other */
7038+struct au_dyaop {
7039+ struct au_dykey da_key;
7040+ struct address_space_operations da_op; /* not const */
7041+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
7042+ void **, unsigned long *);
7043+};
7044+
7045+struct au_dyvmop {
7046+ struct au_dykey dv_key;
7047+ struct vm_operations_struct dv_op; /* not const */
7048+};
7049+
7050+/* ---------------------------------------------------------------------- */
7051+
7052+/* dynop.c */
7053+struct au_branch;
7054+void au_dy_put(struct au_dykey *key);
7055+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
7056+ struct inode *h_inode);
b752ccd1 7057+int au_dy_irefresh(struct inode *inode);
4a4d8108
AM
7058+void au_dy_arefresh(int do_dio);
7059+const struct vm_operations_struct *
7060+au_dy_vmop(struct file *file, struct au_branch *br,
7061+ const struct vm_operations_struct *h_vmop);
7062+
7063+void __init au_dy_init(void);
7064+void au_dy_fin(void);
7065+
4a4d8108
AM
7066+#endif /* __KERNEL__ */
7067+#endif /* __AUFS_DYNOP_H__ */
b752ccd1
AM
7068diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
7069--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
953406b4 7070+++ linux/fs/aufs/export.c 2010-10-21 09:52:43.086957936 +0200
b752ccd1 7071@@ -0,0 +1,788 @@
4a4d8108
AM
7072+/*
7073+ * Copyright (C) 2005-2010 Junjiro R. Okajima
7074+ *
7075+ * This program, aufs is free software; you can redistribute it and/or modify
7076+ * it under the terms of the GNU General Public License as published by
7077+ * the Free Software Foundation; either version 2 of the License, or
7078+ * (at your option) any later version.
7079+ *
7080+ * This program is distributed in the hope that it will be useful,
7081+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7082+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7083+ * GNU General Public License for more details.
7084+ *
7085+ * You should have received a copy of the GNU General Public License
7086+ * along with this program; if not, write to the Free Software
7087+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7088+ */
7089+
7090+/*
7091+ * export via nfs
7092+ */
7093+
7094+#include <linux/exportfs.h>
7095+#include <linux/file.h>
7096+#include <linux/mnt_namespace.h>
7097+#include <linux/namei.h>
7098+#include <linux/nsproxy.h>
7099+#include <linux/random.h>
7100+#include <linux/writeback.h>
7101+#include "aufs.h"
7102+
7103+union conv {
7104+#ifdef CONFIG_AUFS_INO_T_64
7105+ __u32 a[2];
7106+#else
7107+ __u32 a[1];
7108+#endif
7109+ ino_t ino;
7110+};
7111+
7112+static ino_t decode_ino(__u32 *a)
7113+{
7114+ union conv u;
7115+
7116+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
7117+ u.a[0] = a[0];
7118+#ifdef CONFIG_AUFS_INO_T_64
7119+ u.a[1] = a[1];
7120+#endif
7121+ return u.ino;
7122+}
7123+
7124+static void encode_ino(__u32 *a, ino_t ino)
7125+{
7126+ union conv u;
7127+
7128+ u.ino = ino;
7129+ a[0] = u.a[0];
7130+#ifdef CONFIG_AUFS_INO_T_64
7131+ a[1] = u.a[1];
7132+#endif
7133+}
7134+
7135+/* NFS file handle */
7136+enum {
7137+ Fh_br_id,
7138+ Fh_sigen,
7139+#ifdef CONFIG_AUFS_INO_T_64
7140+ /* support 64bit inode number */
7141+ Fh_ino1,
7142+ Fh_ino2,
7143+ Fh_dir_ino1,
7144+ Fh_dir_ino2,
7145+#else
7146+ Fh_ino1,
7147+ Fh_dir_ino1,
7148+#endif
7149+ Fh_igen,
7150+ Fh_h_type,
7151+ Fh_tail,
7152+
7153+ Fh_ino = Fh_ino1,
7154+ Fh_dir_ino = Fh_dir_ino1
7155+};
7156+
7157+static int au_test_anon(struct dentry *dentry)
7158+{
7159+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
7160+}
7161+
7162+/* ---------------------------------------------------------------------- */
7163+/* inode generation external table */
7164+
b752ccd1 7165+void au_xigen_inc(struct inode *inode)
4a4d8108 7166+{
4a4d8108
AM
7167+ loff_t pos;
7168+ ssize_t sz;
7169+ __u32 igen;
7170+ struct super_block *sb;
7171+ struct au_sbinfo *sbinfo;
7172+
4a4d8108 7173+ sb = inode->i_sb;
b752ccd1 7174+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 7175+
b752ccd1 7176+ sbinfo = au_sbi(sb);
1facf9fc 7177+ pos = inode->i_ino;
7178+ pos *= sizeof(igen);
7179+ igen = inode->i_generation + 1;
1facf9fc 7180+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
7181+ sizeof(igen), &pos);
7182+ if (sz == sizeof(igen))
b752ccd1 7183+ return; /* success */
1facf9fc 7184+
b752ccd1 7185+ if (unlikely(sz >= 0))
1facf9fc 7186+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 7187+}
7188+
7189+int au_xigen_new(struct inode *inode)
7190+{
7191+ int err;
7192+ loff_t pos;
7193+ ssize_t sz;
7194+ struct super_block *sb;
7195+ struct au_sbinfo *sbinfo;
7196+ struct file *file;
7197+
7198+ err = 0;
7199+ /* todo: dirty, at mount time */
7200+ if (inode->i_ino == AUFS_ROOT_INO)
7201+ goto out;
7202+ sb = inode->i_sb;
dece6358 7203+ SiMustAnyLock(sb);
1facf9fc 7204+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7205+ goto out;
7206+
7207+ err = -EFBIG;
7208+ pos = inode->i_ino;
7209+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
7210+ AuIOErr1("too large i%lld\n", pos);
7211+ goto out;
7212+ }
7213+ pos *= sizeof(inode->i_generation);
7214+
7215+ err = 0;
7216+ sbinfo = au_sbi(sb);
7217+ file = sbinfo->si_xigen;
7218+ BUG_ON(!file);
7219+
7220+ if (i_size_read(file->f_dentry->d_inode)
7221+ < pos + sizeof(inode->i_generation)) {
7222+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
7223+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
7224+ sizeof(inode->i_generation), &pos);
7225+ } else
7226+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
7227+ sizeof(inode->i_generation), &pos);
7228+ if (sz == sizeof(inode->i_generation))
7229+ goto out; /* success */
7230+
7231+ err = sz;
7232+ if (unlikely(sz >= 0)) {
7233+ err = -EIO;
7234+ AuIOErr("xigen error (%zd)\n", sz);
7235+ }
7236+
4f0767ce 7237+out:
1facf9fc 7238+ return err;
7239+}
7240+
7241+int au_xigen_set(struct super_block *sb, struct file *base)
7242+{
7243+ int err;
7244+ struct au_sbinfo *sbinfo;
7245+ struct file *file;
7246+
dece6358
AM
7247+ SiMustWriteLock(sb);
7248+
1facf9fc 7249+ sbinfo = au_sbi(sb);
7250+ file = au_xino_create2(base, sbinfo->si_xigen);
7251+ err = PTR_ERR(file);
7252+ if (IS_ERR(file))
7253+ goto out;
7254+ err = 0;
7255+ if (sbinfo->si_xigen)
7256+ fput(sbinfo->si_xigen);
7257+ sbinfo->si_xigen = file;
7258+
4f0767ce 7259+out:
1facf9fc 7260+ return err;
7261+}
7262+
7263+void au_xigen_clr(struct super_block *sb)
7264+{
7265+ struct au_sbinfo *sbinfo;
7266+
dece6358
AM
7267+ SiMustWriteLock(sb);
7268+
1facf9fc 7269+ sbinfo = au_sbi(sb);
7270+ if (sbinfo->si_xigen) {
7271+ fput(sbinfo->si_xigen);
7272+ sbinfo->si_xigen = NULL;
7273+ }
7274+}
7275+
7276+/* ---------------------------------------------------------------------- */
7277+
7278+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
7279+ ino_t dir_ino)
7280+{
7281+ struct dentry *dentry, *d;
7282+ struct inode *inode;
7283+ unsigned int sigen;
7284+
7285+ dentry = NULL;
7286+ inode = ilookup(sb, ino);
7287+ if (!inode)
7288+ goto out;
7289+
7290+ dentry = ERR_PTR(-ESTALE);
7291+ sigen = au_sigen(sb);
7292+ if (unlikely(is_bad_inode(inode)
7293+ || IS_DEADDIR(inode)
7294+ || sigen != au_iigen(inode)))
7295+ goto out_iput;
7296+
7297+ dentry = NULL;
7298+ if (!dir_ino || S_ISDIR(inode->i_mode))
7299+ dentry = d_find_alias(inode);
7300+ else {
7301+ spin_lock(&dcache_lock);
7302+ list_for_each_entry(d, &inode->i_dentry, d_alias)
7303+ if (!au_test_anon(d)
7304+ && d->d_parent->d_inode->i_ino == dir_ino) {
7305+ dentry = dget_locked(d);
7306+ break;
7307+ }
7308+ spin_unlock(&dcache_lock);
7309+ }
7310+ if (unlikely(dentry && sigen != au_digen(dentry))) {
7311+ dput(dentry);
7312+ dentry = ERR_PTR(-ESTALE);
7313+ }
7314+
4f0767ce 7315+out_iput:
1facf9fc 7316+ iput(inode);
4f0767ce 7317+out:
1facf9fc 7318+ return dentry;
7319+}
7320+
7321+/* ---------------------------------------------------------------------- */
7322+
7323+/* todo: dirty? */
7324+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
7325+
7326+struct au_compare_mnt_args {
7327+ /* input */
7328+ struct super_block *sb;
7329+
7330+ /* output */
7331+ struct vfsmount *mnt;
7332+};
7333+
7334+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
7335+{
7336+ struct au_compare_mnt_args *a = arg;
7337+
7338+ if (mnt->mnt_sb != a->sb)
7339+ return 0;
7340+ a->mnt = mntget(mnt);
7341+ return 1;
7342+}
7343+
1facf9fc 7344+static struct vfsmount *au_mnt_get(struct super_block *sb)
7345+{
4a4d8108
AM
7346+ int err;
7347+ struct au_compare_mnt_args args = {
7348+ .sb = sb
7349+ };
1facf9fc 7350+ struct mnt_namespace *ns;
1facf9fc 7351+
1facf9fc 7352+ /* no get/put ?? */
7353+ AuDebugOn(!current->nsproxy);
7354+ ns = current->nsproxy->mnt_ns;
7355+ AuDebugOn(!ns);
4a4d8108
AM
7356+ err = iterate_mounts(au_compare_mnt, &args, ns->root);
7357+ AuDebugOn(!err);
7358+ AuDebugOn(!args.mnt);
7359+ return args.mnt;
1facf9fc 7360+}
7361+
7362+struct au_nfsd_si_lock {
4a4d8108
AM
7363+ unsigned int sigen;
7364+ aufs_bindex_t br_id;
1facf9fc 7365+ unsigned char force_lock;
7366+};
7367+
7368+static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
7369+ struct au_nfsd_si_lock *nsi_lock)
7370+{
7371+ aufs_bindex_t bindex;
7372+
7373+ si_read_lock(sb, AuLock_FLUSH);
7374+
7375+ /* branch id may be wrapped around */
7376+ bindex = au_br_index(sb, nsi_lock->br_id);
7377+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
7378+ goto out; /* success */
7379+
7380+ if (!nsi_lock->force_lock)
7381+ si_read_unlock(sb);
7382+ bindex = -1;
7383+
4f0767ce 7384+out:
1facf9fc 7385+ return bindex;
7386+}
7387+
7388+struct find_name_by_ino {
7389+ int called, found;
7390+ ino_t ino;
7391+ char *name;
7392+ int namelen;
7393+};
7394+
7395+static int
7396+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
7397+ u64 ino, unsigned int d_type)
7398+{
7399+ struct find_name_by_ino *a = arg;
7400+
7401+ a->called++;
7402+ if (a->ino != ino)
7403+ return 0;
7404+
7405+ memcpy(a->name, name, namelen);
7406+ a->namelen = namelen;
7407+ a->found = 1;
7408+ return 1;
7409+}
7410+
7411+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
7412+ struct au_nfsd_si_lock *nsi_lock)
7413+{
7414+ struct dentry *dentry, *parent;
7415+ struct file *file;
7416+ struct inode *dir;
7417+ struct find_name_by_ino arg;
7418+ int err;
7419+
7420+ parent = path->dentry;
7421+ if (nsi_lock)
7422+ si_read_unlock(parent->d_sb);
4a4d8108 7423+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 7424+ dentry = (void *)file;
7425+ if (IS_ERR(file))
7426+ goto out;
7427+
7428+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 7429+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 7430+ if (unlikely(!arg.name))
7431+ goto out_file;
7432+ arg.ino = ino;
7433+ arg.found = 0;
7434+ do {
7435+ arg.called = 0;
7436+ /* smp_mb(); */
7437+ err = vfsub_readdir(file, find_name_by_ino, &arg);
7438+ } while (!err && !arg.found && arg.called);
7439+ dentry = ERR_PTR(err);
7440+ if (unlikely(err))
7441+ goto out_name;
7442+ dentry = ERR_PTR(-ENOENT);
7443+ if (!arg.found)
7444+ goto out_name;
7445+
7446+ /* do not call au_lkup_one() */
7447+ dir = parent->d_inode;
7448+ mutex_lock(&dir->i_mutex);
7449+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
7450+ mutex_unlock(&dir->i_mutex);
7451+ AuTraceErrPtr(dentry);
7452+ if (IS_ERR(dentry))
7453+ goto out_name;
7454+ AuDebugOn(au_test_anon(dentry));
7455+ if (unlikely(!dentry->d_inode)) {
7456+ dput(dentry);
7457+ dentry = ERR_PTR(-ENOENT);
7458+ }
7459+
4f0767ce 7460+out_name:
1facf9fc 7461+ __putname(arg.name);
4f0767ce 7462+out_file:
1facf9fc 7463+ fput(file);
4f0767ce 7464+out:
1facf9fc 7465+ if (unlikely(nsi_lock
7466+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
7467+ if (!IS_ERR(dentry)) {
7468+ dput(dentry);
7469+ dentry = ERR_PTR(-ESTALE);
7470+ }
7471+ AuTraceErrPtr(dentry);
7472+ return dentry;
7473+}
7474+
7475+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
7476+ ino_t dir_ino,
7477+ struct au_nfsd_si_lock *nsi_lock)
7478+{
7479+ struct dentry *dentry;
7480+ struct path path;
7481+
7482+ if (dir_ino != AUFS_ROOT_INO) {
7483+ path.dentry = decode_by_ino(sb, dir_ino, 0);
7484+ dentry = path.dentry;
7485+ if (!path.dentry || IS_ERR(path.dentry))
7486+ goto out;
7487+ AuDebugOn(au_test_anon(path.dentry));
7488+ } else
7489+ path.dentry = dget(sb->s_root);
7490+
7491+ path.mnt = au_mnt_get(sb);
7492+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
7493+ path_put(&path);
7494+
4f0767ce 7495+out:
1facf9fc 7496+ AuTraceErrPtr(dentry);
7497+ return dentry;
7498+}
7499+
7500+/* ---------------------------------------------------------------------- */
7501+
7502+static int h_acceptable(void *expv, struct dentry *dentry)
7503+{
7504+ return 1;
7505+}
7506+
7507+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
7508+ char *buf, int len, struct super_block *sb)
7509+{
7510+ char *p;
7511+ int n;
7512+ struct path path;
7513+
7514+ p = d_path(h_rootpath, buf, len);
7515+ if (IS_ERR(p))
7516+ goto out;
7517+ n = strlen(p);
7518+
7519+ path.mnt = h_rootpath->mnt;
7520+ path.dentry = h_parent;
7521+ p = d_path(&path, buf, len);
7522+ if (IS_ERR(p))
7523+ goto out;
7524+ if (n != 1)
7525+ p += n;
7526+
7527+ path.mnt = au_mnt_get(sb);
7528+ path.dentry = sb->s_root;
7529+ p = d_path(&path, buf, len - strlen(p));
7530+ mntput(path.mnt);
7531+ if (IS_ERR(p))
7532+ goto out;
7533+ if (n != 1)
7534+ p[strlen(p)] = '/';
7535+
4f0767ce 7536+out:
1facf9fc 7537+ AuTraceErrPtr(p);
7538+ return p;
7539+}
7540+
7541+static
7542+struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
7543+ ino_t ino, __u32 *fh, int fh_len,
7544+ struct au_nfsd_si_lock *nsi_lock)
7545+{
7546+ struct dentry *dentry, *h_parent, *root;
7547+ struct super_block *h_sb;
7548+ char *pathname, *p;
7549+ struct vfsmount *h_mnt;
7550+ struct au_branch *br;
7551+ int err;
7552+ struct path path;
7553+
7554+ br = au_sbr(sb, bindex);
7555+ /* au_br_get(br); */
7556+ h_mnt = br->br_mnt;
7557+ h_sb = h_mnt->mnt_sb;
7558+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
7559+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
7560+ fh_len - Fh_tail, fh[Fh_h_type],
7561+ h_acceptable, /*context*/NULL);
7562+ dentry = h_parent;
7563+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
7564+ AuWarn1("%s decode_fh failed, %ld\n",
7565+ au_sbtype(h_sb), PTR_ERR(h_parent));
7566+ goto out;
7567+ }
7568+ dentry = NULL;
7569+ if (unlikely(au_test_anon(h_parent))) {
7570+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
7571+ au_sbtype(h_sb));
7572+ goto out_h_parent;
7573+ }
7574+
7575+ dentry = ERR_PTR(-ENOMEM);
7576+ pathname = (void *)__get_free_page(GFP_NOFS);
7577+ if (unlikely(!pathname))
7578+ goto out_h_parent;
7579+
7580+ root = sb->s_root;
7581+ path.mnt = h_mnt;
7582+ di_read_lock_parent(root, !AuLock_IR);
7583+ path.dentry = au_h_dptr(root, bindex);
7584+ di_read_unlock(root, !AuLock_IR);
7585+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
7586+ dentry = (void *)p;
7587+ if (IS_ERR(p))
7588+ goto out_pathname;
7589+
7590+ si_read_unlock(sb);
7591+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
7592+ dentry = ERR_PTR(err);
7593+ if (unlikely(err))
7594+ goto out_relock;
7595+
7596+ dentry = ERR_PTR(-ENOENT);
7597+ AuDebugOn(au_test_anon(path.dentry));
7598+ if (unlikely(!path.dentry->d_inode))
7599+ goto out_path;
7600+
7601+ if (ino != path.dentry->d_inode->i_ino)
7602+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
7603+ else
7604+ dentry = dget(path.dentry);
7605+
4f0767ce 7606+out_path:
1facf9fc 7607+ path_put(&path);
4f0767ce 7608+out_relock:
1facf9fc 7609+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
7610+ if (!IS_ERR(dentry)) {
7611+ dput(dentry);
7612+ dentry = ERR_PTR(-ESTALE);
7613+ }
4f0767ce 7614+out_pathname:
1facf9fc 7615+ free_page((unsigned long)pathname);
4f0767ce 7616+out_h_parent:
1facf9fc 7617+ dput(h_parent);
4f0767ce 7618+out:
1facf9fc 7619+ /* au_br_put(br); */
7620+ AuTraceErrPtr(dentry);
7621+ return dentry;
7622+}
7623+
7624+/* ---------------------------------------------------------------------- */
7625+
7626+static struct dentry *
7627+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
7628+ int fh_type)
7629+{
7630+ struct dentry *dentry;
7631+ __u32 *fh = fid->raw;
7632+ ino_t ino, dir_ino;
7633+ aufs_bindex_t bindex;
7634+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 7635+ .force_lock = 0
7636+ };
7637+
1facf9fc 7638+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
7639+ /* it should never happen, but the file handle is unreliable */
7640+ if (unlikely(fh_len < Fh_tail))
7641+ goto out;
7642+ nsi_lock.sigen = fh[Fh_sigen];
7643+ nsi_lock.br_id = fh[Fh_br_id];
7644+
1facf9fc 7645+ /* branch id may be wrapped around */
7646+ bindex = si_nfsd_read_lock(sb, &nsi_lock);
7647+ if (unlikely(bindex < 0))
7648+ goto out;
7649+ nsi_lock.force_lock = 1;
7650+
7651+ /* is this inode still cached? */
7652+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
7653+ /* it should never happen */
7654+ if (unlikely(ino == AUFS_ROOT_INO))
7655+ goto out;
7656+
1facf9fc 7657+ dir_ino = decode_ino(fh + Fh_dir_ino);
7658+ dentry = decode_by_ino(sb, ino, dir_ino);
7659+ if (IS_ERR(dentry))
7660+ goto out_unlock;
7661+ if (dentry)
7662+ goto accept;
7663+
7664+ /* is the parent dir cached? */
7665+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
7666+ if (IS_ERR(dentry))
7667+ goto out_unlock;
7668+ if (dentry)
7669+ goto accept;
7670+
7671+ /* lookup path */
7672+ dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
7673+ if (IS_ERR(dentry))
7674+ goto out_unlock;
7675+ if (unlikely(!dentry))
7676+ /* todo?: make it ESTALE */
7677+ goto out_unlock;
7678+
4f0767ce 7679+accept:
1facf9fc 7680+ if (dentry->d_inode->i_generation == fh[Fh_igen])
7681+ goto out_unlock; /* success */
7682+
7683+ dput(dentry);
7684+ dentry = ERR_PTR(-ESTALE);
4f0767ce 7685+out_unlock:
1facf9fc 7686+ si_read_unlock(sb);
4f0767ce 7687+out:
1facf9fc 7688+ AuTraceErrPtr(dentry);
7689+ return dentry;
7690+}
7691+
7692+#if 0 /* reserved for future use */
7693+/* support subtreecheck option */
7694+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
7695+ int fh_len, int fh_type)
7696+{
7697+ struct dentry *parent;
7698+ __u32 *fh = fid->raw;
7699+ ino_t dir_ino;
7700+
7701+ dir_ino = decode_ino(fh + Fh_dir_ino);
7702+ parent = decode_by_ino(sb, dir_ino, 0);
7703+ if (IS_ERR(parent))
7704+ goto out;
7705+ if (!parent)
7706+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
7707+ dir_ino, fh, fh_len);
7708+
4f0767ce 7709+out:
1facf9fc 7710+ AuTraceErrPtr(parent);
7711+ return parent;
7712+}
7713+#endif
7714+
7715+/* ---------------------------------------------------------------------- */
7716+
7717+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
7718+ int connectable)
7719+{
7720+ int err;
7721+ aufs_bindex_t bindex, bend;
7722+ struct super_block *sb, *h_sb;
7723+ struct inode *inode;
7724+ struct dentry *parent, *h_parent;
7725+ struct au_branch *br;
7726+
7727+ AuDebugOn(au_test_anon(dentry));
7728+
7729+ parent = NULL;
7730+ err = -ENOSPC;
7731+ if (unlikely(*max_len <= Fh_tail)) {
7732+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
7733+ goto out;
7734+ }
7735+
7736+ err = FILEID_ROOT;
7737+ if (IS_ROOT(dentry)) {
7738+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
7739+ goto out;
7740+ }
7741+
7742+ err = -EIO;
7743+ h_parent = NULL;
7744+ sb = dentry->d_sb;
7745+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
7746+ parent = dget_parent(dentry);
7747+ di_read_lock_parent(parent, !AuLock_IR);
7748+ inode = dentry->d_inode;
7749+ AuDebugOn(!inode);
7750+#ifdef CONFIG_AUFS_DEBUG
7751+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7752+ AuWarn1("NFS-exporting requires xino\n");
7753+#endif
7754+
7755+ bend = au_dbtaildir(parent);
7756+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
7757+ h_parent = au_h_dptr(parent, bindex);
7758+ if (h_parent) {
7759+ dget(h_parent);
7760+ break;
7761+ }
7762+ }
7763+ if (unlikely(!h_parent))
7764+ goto out_unlock;
7765+
7766+ err = -EPERM;
7767+ br = au_sbr(sb, bindex);
7768+ h_sb = br->br_mnt->mnt_sb;
7769+ if (unlikely(!h_sb->s_export_op)) {
7770+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
7771+ goto out_dput;
7772+ }
7773+
7774+ fh[Fh_br_id] = br->br_id;
7775+ fh[Fh_sigen] = au_sigen(sb);
7776+ encode_ino(fh + Fh_ino, inode->i_ino);
7777+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
7778+ fh[Fh_igen] = inode->i_generation;
7779+
7780+ *max_len -= Fh_tail;
7781+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
7782+ max_len,
7783+ /*connectable or subtreecheck*/0);
7784+ err = fh[Fh_h_type];
7785+ *max_len += Fh_tail;
7786+ /* todo: macros? */
7787+ if (err != 255)
7788+ err = 99;
7789+ else
7790+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
7791+
4f0767ce 7792+out_dput:
1facf9fc 7793+ dput(h_parent);
4f0767ce 7794+out_unlock:
1facf9fc 7795+ di_read_unlock(parent, !AuLock_IR);
7796+ dput(parent);
7797+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 7798+out:
1facf9fc 7799+ if (unlikely(err < 0))
7800+ err = 255;
7801+ return err;
7802+}
7803+
7804+/* ---------------------------------------------------------------------- */
7805+
4a4d8108
AM
7806+static int aufs_commit_metadata(struct inode *inode)
7807+{
7808+ int err;
7809+ aufs_bindex_t bindex;
7810+ struct super_block *sb;
7811+ struct inode *h_inode;
7812+ int (*f)(struct inode *inode);
7813+
7814+ sb = inode->i_sb;
953406b4 7815+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108
AM
7816+ ii_write_lock_child(inode);
7817+ bindex = au_ibstart(inode);
7818+ AuDebugOn(bindex < 0);
7819+ h_inode = au_h_iptr(inode, bindex);
7820+
7821+ f = h_inode->i_sb->s_export_op->commit_metadata;
7822+ if (f)
7823+ err = f(h_inode);
7824+ else {
7825+ struct writeback_control wbc = {
7826+ .sync_mode = WB_SYNC_ALL,
7827+ .nr_to_write = 0 /* metadata only */
7828+ };
7829+
7830+ err = sync_inode(h_inode, &wbc);
7831+ }
7832+
7833+ au_cpup_attr_timesizes(inode);
7834+ ii_write_unlock(inode);
7835+ si_read_unlock(sb);
7836+ return err;
7837+}
7838+
7839+/* ---------------------------------------------------------------------- */
7840+
1facf9fc 7841+static struct export_operations aufs_export_op = {
4a4d8108 7842+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 7843+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
7844+ .encode_fh = aufs_encode_fh,
7845+ .commit_metadata = aufs_commit_metadata
1facf9fc 7846+};
7847+
7848+void au_export_init(struct super_block *sb)
7849+{
7850+ struct au_sbinfo *sbinfo;
7851+ __u32 u;
7852+
7853+ sb->s_export_op = &aufs_export_op;
7854+ sbinfo = au_sbi(sb);
7855+ sbinfo->si_xigen = NULL;
7856+ get_random_bytes(&u, sizeof(u));
7857+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
7858+ atomic_set(&sbinfo->si_xigen_next, u);
7859+}
b752ccd1
AM
7860diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
7861--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
953406b4 7862+++ linux/fs/aufs/file.c 2010-10-21 09:52:43.090291764 +0200
4a4d8108 7863@@ -0,0 +1,652 @@
1facf9fc 7864+/*
4a4d8108 7865+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 7866+ *
7867+ * This program, aufs is free software; you can redistribute it and/or modify
7868+ * it under the terms of the GNU General Public License as published by
7869+ * the Free Software Foundation; either version 2 of the License, or
7870+ * (at your option) any later version.
dece6358
AM
7871+ *
7872+ * This program is distributed in the hope that it will be useful,
7873+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7874+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7875+ * GNU General Public License for more details.
7876+ *
7877+ * You should have received a copy of the GNU General Public License
7878+ * along with this program; if not, write to the Free Software
7879+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7880+ */
7881+
7882+/*
4a4d8108 7883+ * handling file/dir, and address_space operation
1facf9fc 7884+ */
7885+
dece6358 7886+#include <linux/file.h>
4a4d8108
AM
7887+#include <linux/fsnotify.h>
7888+#include <linux/namei.h>
7889+#include <linux/pagemap.h>
1facf9fc 7890+#include "aufs.h"
7891+
4a4d8108
AM
7892+/* drop flags for writing */
7893+unsigned int au_file_roflags(unsigned int flags)
7894+{
7895+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
7896+ flags |= O_RDONLY | O_NOATIME;
7897+ return flags;
7898+}
7899+
7900+/* common functions to regular file and dir */
7901+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
7902+ struct file *file)
1facf9fc 7903+{
1308ab2a 7904+ struct file *h_file;
4a4d8108
AM
7905+ struct dentry *h_dentry;
7906+ struct inode *h_inode;
7907+ struct super_block *sb;
7908+ struct au_branch *br;
7909+ struct path h_path;
7910+ int err, exec_flag;
1facf9fc 7911+
4a4d8108
AM
7912+ /* a race condition can happen between open and unlink/rmdir */
7913+ h_file = ERR_PTR(-ENOENT);
7914+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 7915+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
7916+ goto out;
7917+ h_inode = h_dentry->d_inode;
b752ccd1 7918+ if (au_test_nfsd() && !h_inode)
4a4d8108
AM
7919+ goto out;
7920+ if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
7921+ || !h_inode))
7922+ goto out;
1facf9fc 7923+
4a4d8108
AM
7924+ sb = dentry->d_sb;
7925+ br = au_sbr(sb, bindex);
7926+ h_file = ERR_PTR(-EACCES);
7927+ exec_flag = flags & vfsub_fmode_to_uint(FMODE_EXEC);
7928+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
7929+ goto out;
1facf9fc 7930+
4a4d8108
AM
7931+ /* drop flags for writing */
7932+ if (au_test_ro(sb, bindex, dentry->d_inode))
7933+ flags = au_file_roflags(flags);
7934+ flags &= ~O_CREAT;
7935+ atomic_inc(&br->br_count);
7936+ h_path.dentry = h_dentry;
7937+ h_path.mnt = br->br_mnt;
7938+ if (!au_special_file(h_inode->i_mode))
7939+ h_file = vfsub_dentry_open(&h_path, flags);
7940+ else {
7941+ /* this block depends upon the configuration */
7942+ di_read_unlock(dentry, AuLock_IR);
7943+ fi_write_unlock(file);
7944+ si_read_unlock(sb);
7945+ h_file = vfsub_dentry_open(&h_path, flags);
7946+ si_noflush_read_lock(sb);
7947+ fi_write_lock(file);
7948+ di_read_lock_child(dentry, AuLock_IR);
dece6358 7949+ }
4a4d8108
AM
7950+ if (IS_ERR(h_file))
7951+ goto out_br;
dece6358 7952+
4a4d8108
AM
7953+ if (exec_flag) {
7954+ err = deny_write_access(h_file);
7955+ if (unlikely(err)) {
7956+ fput(h_file);
7957+ h_file = ERR_PTR(err);
7958+ goto out_br;
7959+ }
7960+ }
953406b4 7961+ fsnotify_open(h_file);
4a4d8108 7962+ goto out; /* success */
1facf9fc 7963+
4f0767ce 7964+out_br:
4a4d8108 7965+ atomic_dec(&br->br_count);
4f0767ce 7966+out:
4a4d8108
AM
7967+ return h_file;
7968+}
1308ab2a 7969+
4a4d8108
AM
7970+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
7971+ struct au_fidir *fidir)
1facf9fc 7972+{
dece6358 7973+ int err;
1facf9fc 7974+ struct dentry *dentry;
1308ab2a 7975+
4a4d8108
AM
7976+ err = au_finfo_init(file, fidir);
7977+ if (unlikely(err))
7978+ goto out;
1facf9fc 7979+
7980+ dentry = file->f_dentry;
4a4d8108
AM
7981+ di_read_lock_child(dentry, AuLock_IR);
7982+ err = open(file, vfsub_file_flags(file));
7983+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 7984+
4a4d8108
AM
7985+ fi_write_unlock(file);
7986+ if (unlikely(err)) {
7987+ au_fi(file)->fi_hdir = NULL;
7988+ au_finfo_fin(file);
1308ab2a 7989+ }
4a4d8108 7990+
4f0767ce 7991+out:
1308ab2a 7992+ return err;
7993+}
dece6358 7994+
4a4d8108 7995+int au_reopen_nondir(struct file *file)
1308ab2a 7996+{
4a4d8108
AM
7997+ int err;
7998+ aufs_bindex_t bstart;
7999+ struct dentry *dentry;
8000+ struct file *h_file, *h_file_tmp;
1308ab2a 8001+
4a4d8108
AM
8002+ dentry = file->f_dentry;
8003+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
8004+ bstart = au_dbstart(dentry);
8005+ h_file_tmp = NULL;
8006+ if (au_fbstart(file) == bstart) {
8007+ h_file = au_hf_top(file);
8008+ if (file->f_mode == h_file->f_mode)
8009+ return 0; /* success */
8010+ h_file_tmp = h_file;
8011+ get_file(h_file_tmp);
8012+ au_set_h_fptr(file, bstart, NULL);
8013+ }
8014+ AuDebugOn(au_fi(file)->fi_hdir);
8015+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 8016+
4a4d8108
AM
8017+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
8018+ file);
8019+ err = PTR_ERR(h_file);
8020+ if (IS_ERR(h_file))
8021+ goto out; /* todo: close all? */
8022+
8023+ err = 0;
8024+ au_set_fbstart(file, bstart);
8025+ au_set_h_fptr(file, bstart, h_file);
8026+ au_update_figen(file);
8027+ /* todo: necessary? */
8028+ /* file->f_ra = h_file->f_ra; */
8029+
4f0767ce 8030+out:
4a4d8108
AM
8031+ if (h_file_tmp)
8032+ fput(h_file_tmp);
8033+ return err;
1facf9fc 8034+}
8035+
1308ab2a 8036+/* ---------------------------------------------------------------------- */
8037+
4a4d8108
AM
8038+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
8039+ struct dentry *hi_wh)
1facf9fc 8040+{
4a4d8108
AM
8041+ int err;
8042+ aufs_bindex_t bstart;
8043+ struct au_dinfo *dinfo;
8044+ struct dentry *h_dentry;
8045+ struct au_hdentry *hdp;
1facf9fc 8046+
4a4d8108
AM
8047+ dinfo = au_di(file->f_dentry);
8048+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 8049+
4a4d8108
AM
8050+ bstart = dinfo->di_bstart;
8051+ dinfo->di_bstart = btgt;
8052+ hdp = dinfo->di_hdentry;
8053+ h_dentry = hdp[0 + btgt].hd_dentry;
8054+ hdp[0 + btgt].hd_dentry = hi_wh;
8055+ err = au_reopen_nondir(file);
8056+ hdp[0 + btgt].hd_dentry = h_dentry;
8057+ dinfo->di_bstart = bstart;
1facf9fc 8058+
1facf9fc 8059+ return err;
8060+}
8061+
4a4d8108
AM
8062+static int au_ready_to_write_wh(struct file *file, loff_t len,
8063+ aufs_bindex_t bcpup)
1facf9fc 8064+{
4a4d8108 8065+ int err;
dece6358 8066+ struct inode *inode;
4a4d8108 8067+ struct dentry *dentry, *hi_wh;
1facf9fc 8068+
dece6358 8069+ dentry = file->f_dentry;
4a4d8108 8070+ au_update_dbstart(dentry);
dece6358 8071+ inode = dentry->d_inode;
4a4d8108
AM
8072+ hi_wh = au_hi_wh(inode, bcpup);
8073+ if (!hi_wh)
8074+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
8075+ else
8076+ /* already copied-up after unlink */
8077+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 8078+
4a4d8108
AM
8079+ if (!err
8080+ && inode->i_nlink > 1
8081+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
8082+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 8083+
dece6358 8084+ return err;
1facf9fc 8085+}
8086+
4a4d8108
AM
8087+/*
8088+ * prepare the @file for writing.
8089+ */
8090+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 8091+{
4a4d8108
AM
8092+ int err;
8093+ aufs_bindex_t bstart, bcpup;
8094+ struct dentry *dentry, *parent, *h_dentry;
8095+ struct inode *h_inode, *inode;
1facf9fc 8096+ struct super_block *sb;
4a4d8108 8097+ struct file *h_file;
1facf9fc 8098+
8099+ dentry = file->f_dentry;
1facf9fc 8100+ sb = dentry->d_sb;
4a4d8108
AM
8101+ inode = dentry->d_inode;
8102+ AuDebugOn(au_special_file(inode->i_mode));
8103+ bstart = au_fbstart(file);
8104+ err = au_test_ro(sb, bstart, inode);
8105+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
8106+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 8107+ goto out;
4a4d8108 8108+ }
1facf9fc 8109+
4a4d8108
AM
8110+ /* need to cpup */
8111+ parent = dget_parent(dentry);
8112+ di_write_lock_parent(parent);
8113+ err = AuWbrCopyup(au_sbi(sb), dentry);
8114+ bcpup = err;
8115+ if (unlikely(err < 0))
8116+ goto out_dgrade;
8117+ err = 0;
8118+
8119+ if (!au_h_dptr(parent, bcpup)) {
8120+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 8121+ if (unlikely(err))
4a4d8108
AM
8122+ goto out_dgrade;
8123+ }
8124+
8125+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
8126+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8127+ if (unlikely(err))
8128+ goto out_dgrade;
8129+
8130+ h_dentry = au_hf_top(file)->f_dentry;
8131+ h_inode = h_dentry->d_inode;
8132+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8133+ h_file = au_h_open_pre(dentry, bstart);
8134+ if (IS_ERR(h_file)) {
8135+ err = PTR_ERR(h_file);
8136+ h_file = NULL;
8137+ } else if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
8138+ /* || !h_inode->i_nlink */) {
8139+ err = au_ready_to_write_wh(file, len, bcpup);
8140+ di_downgrade_lock(parent, AuLock_IR);
8141+ } else {
8142+ di_downgrade_lock(parent, AuLock_IR);
8143+ if (!au_h_dptr(dentry, bcpup))
8144+ err = au_sio_cpup_simple(dentry, bcpup, len,
8145+ AuCpup_DTIME);
8146+ if (!err)
8147+ err = au_reopen_nondir(file);
8148+ }
8149+ mutex_unlock(&h_inode->i_mutex);
8150+ au_h_open_post(dentry, bstart, h_file);
8151+
8152+ if (!err) {
8153+ au_pin_set_parent_lflag(pin, /*lflag*/0);
8154+ goto out_dput; /* success */
8155+ }
8156+ au_unpin(pin);
8157+ goto out_unlock;
1facf9fc 8158+
4f0767ce 8159+out_dgrade:
4a4d8108 8160+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 8161+out_unlock:
4a4d8108 8162+ di_read_unlock(parent, AuLock_IR);
4f0767ce 8163+out_dput:
4a4d8108 8164+ dput(parent);
4f0767ce 8165+out:
1facf9fc 8166+ return err;
8167+}
8168+
4a4d8108
AM
8169+/* ---------------------------------------------------------------------- */
8170+
8171+int au_do_flush(struct file *file, fl_owner_t id,
8172+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 8173+{
4a4d8108 8174+ int err;
1308ab2a 8175+ struct dentry *dentry;
1facf9fc 8176+ struct super_block *sb;
4a4d8108 8177+ struct inode *inode;
1facf9fc 8178+
1facf9fc 8179+ dentry = file->f_dentry;
8180+ sb = dentry->d_sb;
dece6358 8181+ inode = dentry->d_inode;
4a4d8108
AM
8182+ si_noflush_read_lock(sb);
8183+ fi_read_lock(file);
b752ccd1 8184+ ii_read_lock_child(inode);
1facf9fc 8185+
4a4d8108
AM
8186+ err = flush(file, id);
8187+ au_cpup_attr_timesizes(inode);
1facf9fc 8188+
b752ccd1 8189+ ii_read_unlock(inode);
4a4d8108 8190+ fi_read_unlock(file);
1308ab2a 8191+ si_read_unlock(sb);
dece6358 8192+ return err;
1facf9fc 8193+}
8194+
4a4d8108
AM
8195+/* ---------------------------------------------------------------------- */
8196+
8197+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 8198+{
4a4d8108
AM
8199+ int err;
8200+ aufs_bindex_t bstart;
8201+ struct au_pin pin;
8202+ struct au_finfo *finfo;
8203+ struct dentry *dentry, *parent, *hi_wh;
8204+ struct inode *inode;
1facf9fc 8205+ struct super_block *sb;
8206+
4a4d8108
AM
8207+ FiMustWriteLock(file);
8208+
8209+ err = 0;
8210+ finfo = au_fi(file);
1308ab2a 8211+ dentry = file->f_dentry;
8212+ sb = dentry->d_sb;
4a4d8108
AM
8213+ inode = dentry->d_inode;
8214+ bstart = au_ibstart(inode);
8215+ if (bstart == finfo->fi_btop)
1308ab2a 8216+ goto out;
dece6358 8217+
4a4d8108
AM
8218+ parent = dget_parent(dentry);
8219+ if (au_test_ro(sb, bstart, inode)) {
8220+ di_read_lock_parent(parent, !AuLock_IR);
8221+ err = AuWbrCopyup(au_sbi(sb), dentry);
8222+ bstart = err;
8223+ di_read_unlock(parent, !AuLock_IR);
8224+ if (unlikely(err < 0))
8225+ goto out_parent;
8226+ err = 0;
1facf9fc 8227+ }
1facf9fc 8228+
4a4d8108
AM
8229+ di_read_lock_parent(parent, AuLock_IR);
8230+ hi_wh = au_hi_wh(inode, bstart);
8231+ if (au_opt_test(au_mntflags(sb), PLINK)
8232+ && au_plink_test(inode)
8233+ && !d_unhashed(dentry)) {
8234+ err = au_test_and_cpup_dirs(dentry, bstart);
8235+ if (unlikely(err))
8236+ goto out_unlock;
8237+
8238+ /* always superio. */
8239+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
8240+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8241+ if (!err)
8242+ err = au_sio_cpup_simple(dentry, bstart, -1,
8243+ AuCpup_DTIME);
8244+ au_unpin(&pin);
8245+ } else if (hi_wh) {
8246+ /* already copied-up after unlink */
8247+ err = au_reopen_wh(file, bstart, hi_wh);
8248+ *need_reopen = 0;
8249+ }
1facf9fc 8250+
4f0767ce 8251+out_unlock:
4a4d8108 8252+ di_read_unlock(parent, AuLock_IR);
4f0767ce 8253+out_parent:
4a4d8108 8254+ dput(parent);
4f0767ce 8255+out:
1308ab2a 8256+ return err;
dece6358 8257+}
1facf9fc 8258+
4a4d8108 8259+static void au_do_refresh_dir(struct file *file)
dece6358 8260+{
4a4d8108
AM
8261+ aufs_bindex_t bindex, bend, new_bindex, brid;
8262+ struct au_hfile *p, tmp, *q;
8263+ struct au_finfo *finfo;
1308ab2a 8264+ struct super_block *sb;
4a4d8108 8265+ struct au_fidir *fidir;
1facf9fc 8266+
4a4d8108 8267+ FiMustWriteLock(file);
1facf9fc 8268+
4a4d8108
AM
8269+ sb = file->f_dentry->d_sb;
8270+ finfo = au_fi(file);
8271+ fidir = finfo->fi_hdir;
8272+ AuDebugOn(!fidir);
8273+ p = fidir->fd_hfile + finfo->fi_btop;
8274+ brid = p->hf_br->br_id;
8275+ bend = fidir->fd_bbot;
8276+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
8277+ if (!p->hf_file)
8278+ continue;
1308ab2a 8279+
4a4d8108
AM
8280+ new_bindex = au_br_index(sb, p->hf_br->br_id);
8281+ if (new_bindex == bindex)
8282+ continue;
8283+ if (new_bindex < 0) {
8284+ au_set_h_fptr(file, bindex, NULL);
8285+ continue;
8286+ }
1308ab2a 8287+
4a4d8108
AM
8288+ /* swap two lower inode, and loop again */
8289+ q = fidir->fd_hfile + new_bindex;
8290+ tmp = *q;
8291+ *q = *p;
8292+ *p = tmp;
8293+ if (tmp.hf_file) {
8294+ bindex--;
8295+ p--;
8296+ }
8297+ }
1308ab2a 8298+
4a4d8108
AM
8299+ p = fidir->fd_hfile;
8300+ if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
8301+ bend = au_sbend(sb);
8302+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
8303+ finfo->fi_btop++, p++)
8304+ if (p->hf_file) {
8305+ if (p->hf_file->f_dentry
8306+ && p->hf_file->f_dentry->d_inode)
8307+ break;
8308+ else
8309+ au_hfput(p, file);
8310+ }
8311+ } else {
8312+ bend = au_br_index(sb, brid);
8313+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
8314+ finfo->fi_btop++, p++)
8315+ if (p->hf_file)
8316+ au_hfput(p, file);
8317+ bend = au_sbend(sb);
8318+ }
1308ab2a 8319+
4a4d8108
AM
8320+ p = fidir->fd_hfile + bend;
8321+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
8322+ fidir->fd_bbot--, p--)
8323+ if (p->hf_file) {
8324+ if (p->hf_file->f_dentry
8325+ && p->hf_file->f_dentry->d_inode)
8326+ break;
8327+ else
8328+ au_hfput(p, file);
8329+ }
8330+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 8331+}
8332+
4a4d8108
AM
8333+/*
8334+ * after branch manipulating, refresh the file.
8335+ */
8336+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 8337+{
4a4d8108
AM
8338+ int err, need_reopen;
8339+ aufs_bindex_t bend, bindex;
8340+ struct dentry *dentry;
1308ab2a 8341+ struct au_finfo *finfo;
4a4d8108 8342+ struct au_hfile *hfile;
1facf9fc 8343+
4a4d8108 8344+ dentry = file->f_dentry;
1308ab2a 8345+ finfo = au_fi(file);
4a4d8108
AM
8346+ if (!finfo->fi_hdir) {
8347+ hfile = &finfo->fi_htop;
8348+ AuDebugOn(!hfile->hf_file);
8349+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
8350+ AuDebugOn(bindex < 0);
8351+ if (bindex != finfo->fi_btop)
8352+ au_set_fbstart(file, bindex);
8353+ } else {
8354+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
8355+ if (unlikely(err))
8356+ goto out;
8357+ au_do_refresh_dir(file);
8358+ }
1facf9fc 8359+
4a4d8108
AM
8360+ err = 0;
8361+ need_reopen = 1;
8362+ if (!au_test_mmapped(file))
8363+ err = au_file_refresh_by_inode(file, &need_reopen);
8364+ if (!err && need_reopen && !d_unhashed(dentry))
8365+ err = reopen(file);
8366+ if (!err) {
8367+ au_update_figen(file);
8368+ goto out; /* success */
8369+ }
8370+
8371+ /* error, close all lower files */
8372+ if (finfo->fi_hdir) {
8373+ bend = au_fbend_dir(file);
8374+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
8375+ au_set_h_fptr(file, bindex, NULL);
8376+ }
1facf9fc 8377+
4f0767ce 8378+out:
1facf9fc 8379+ return err;
8380+}
8381+
4a4d8108
AM
8382+/* common function to regular file and dir */
8383+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8384+ int wlock)
dece6358 8385+{
1308ab2a 8386+ int err;
4a4d8108
AM
8387+ unsigned int sigen, figen;
8388+ aufs_bindex_t bstart;
8389+ unsigned char pseudo_link;
8390+ struct dentry *dentry;
8391+ struct inode *inode;
1facf9fc 8392+
4a4d8108
AM
8393+ err = 0;
8394+ dentry = file->f_dentry;
8395+ inode = dentry->d_inode;
8396+ AuDebugOn(au_special_file(inode->i_mode));
8397+ sigen = au_sigen(dentry->d_sb);
8398+ fi_write_lock(file);
8399+ figen = au_figen(file);
8400+ di_write_lock_child(dentry);
8401+ bstart = au_dbstart(dentry);
8402+ pseudo_link = (bstart != au_ibstart(inode));
8403+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
8404+ if (!wlock) {
8405+ di_downgrade_lock(dentry, AuLock_IR);
8406+ fi_downgrade_lock(file);
8407+ }
8408+ goto out; /* success */
8409+ }
dece6358 8410+
4a4d8108
AM
8411+ AuDbg("sigen %d, figen %d\n", sigen, figen);
8412+ if (sigen != au_digen(dentry)
8413+ || sigen != au_iigen(inode)) {
8414+ err = au_reval_dpath(dentry, sigen);
8415+ if (unlikely(err < 0))
8416+ goto out;
8417+ AuDebugOn(au_digen(dentry) != sigen
8418+ || au_iigen(inode) != sigen);
8419+ }
dece6358 8420+
4a4d8108
AM
8421+ err = refresh_file(file, reopen);
8422+ if (!err) {
8423+ if (!wlock) {
8424+ di_downgrade_lock(dentry, AuLock_IR);
8425+ fi_downgrade_lock(file);
8426+ }
8427+ } else {
8428+ di_write_unlock(dentry);
8429+ fi_write_unlock(file);
8430+ }
1facf9fc 8431+
4f0767ce 8432+out:
1308ab2a 8433+ return err;
8434+}
1facf9fc 8435+
4a4d8108
AM
8436+/* ---------------------------------------------------------------------- */
8437+
8438+/* cf. aufs_nopage() */
8439+/* for madvise(2) */
8440+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 8441+{
4a4d8108
AM
8442+ unlock_page(page);
8443+ return 0;
8444+}
1facf9fc 8445+
4a4d8108
AM
8446+/* it will never be called, but necessary to support O_DIRECT */
8447+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
8448+ const struct iovec *iov, loff_t offset,
8449+ unsigned long nr_segs)
8450+{ BUG(); return 0; }
1facf9fc 8451+
4a4d8108
AM
8452+/*
8453+ * it will never be called, but madvise and fadvise behaves differently
8454+ * when get_xip_mem is defined
8455+ */
8456+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
8457+ int create, void **kmem, unsigned long *pfn)
8458+{ BUG(); return 0; }
1facf9fc 8459+
4a4d8108
AM
8460+/* they will never be called. */
8461+#ifdef CONFIG_AUFS_DEBUG
8462+static int aufs_write_begin(struct file *file, struct address_space *mapping,
8463+ loff_t pos, unsigned len, unsigned flags,
8464+ struct page **pagep, void **fsdata)
8465+{ AuUnsupport(); return 0; }
8466+static int aufs_write_end(struct file *file, struct address_space *mapping,
8467+ loff_t pos, unsigned len, unsigned copied,
8468+ struct page *page, void *fsdata)
8469+{ AuUnsupport(); return 0; }
8470+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
8471+{ AuUnsupport(); return 0; }
8472+static void aufs_sync_page(struct page *page)
8473+{ AuUnsupport(); }
1308ab2a 8474+
4a4d8108
AM
8475+static int aufs_set_page_dirty(struct page *page)
8476+{ AuUnsupport(); return 0; }
8477+static void aufs_invalidatepage(struct page *page, unsigned long offset)
8478+{ AuUnsupport(); }
8479+static int aufs_releasepage(struct page *page, gfp_t gfp)
8480+{ AuUnsupport(); return 0; }
8481+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
8482+ struct page *page)
8483+{ AuUnsupport(); return 0; }
8484+static int aufs_launder_page(struct page *page)
8485+{ AuUnsupport(); return 0; }
8486+static int aufs_is_partially_uptodate(struct page *page,
8487+ read_descriptor_t *desc,
8488+ unsigned long from)
8489+{ AuUnsupport(); return 0; }
8490+static int aufs_error_remove_page(struct address_space *mapping,
8491+ struct page *page)
8492+{ AuUnsupport(); return 0; }
8493+#endif /* CONFIG_AUFS_DEBUG */
8494+
8495+const struct address_space_operations aufs_aop = {
8496+ .readpage = aufs_readpage,
8497+ .direct_IO = aufs_direct_IO,
8498+ .get_xip_mem = aufs_get_xip_mem,
8499+#ifdef CONFIG_AUFS_DEBUG
8500+ .writepage = aufs_writepage,
8501+ .sync_page = aufs_sync_page,
8502+ /* no writepages, because of writepage */
8503+ .set_page_dirty = aufs_set_page_dirty,
8504+ /* no readpages, because of readpage */
8505+ .write_begin = aufs_write_begin,
8506+ .write_end = aufs_write_end,
8507+ /* no bmap, no block device */
8508+ .invalidatepage = aufs_invalidatepage,
8509+ .releasepage = aufs_releasepage,
8510+ .migratepage = aufs_migratepage,
8511+ .launder_page = aufs_launder_page,
8512+ .is_partially_uptodate = aufs_is_partially_uptodate,
8513+ .error_remove_page = aufs_error_remove_page
8514+#endif /* CONFIG_AUFS_DEBUG */
dece6358 8515+};
b752ccd1
AM
8516diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
8517--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
953406b4 8518+++ linux/fs/aufs/file.h 2010-10-21 09:52:43.090291764 +0200
b752ccd1 8519@@ -0,0 +1,238 @@
4a4d8108
AM
8520+/*
8521+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8522+ *
8523+ * This program, aufs is free software; you can redistribute it and/or modify
8524+ * it under the terms of the GNU General Public License as published by
8525+ * the Free Software Foundation; either version 2 of the License, or
8526+ * (at your option) any later version.
8527+ *
8528+ * This program is distributed in the hope that it will be useful,
8529+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8530+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8531+ * GNU General Public License for more details.
8532+ *
8533+ * You should have received a copy of the GNU General Public License
8534+ * along with this program; if not, write to the Free Software
8535+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8536+ */
1facf9fc 8537+
4a4d8108
AM
8538+/*
8539+ * file operations
8540+ */
1facf9fc 8541+
4a4d8108
AM
8542+#ifndef __AUFS_FILE_H__
8543+#define __AUFS_FILE_H__
1facf9fc 8544+
4a4d8108 8545+#ifdef __KERNEL__
1facf9fc 8546+
4a4d8108
AM
8547+#include <linux/fs.h>
8548+#include <linux/poll.h>
8549+#include <linux/aufs_type.h>
8550+#include "rwsem.h"
1facf9fc 8551+
4a4d8108
AM
8552+struct au_branch;
8553+struct au_hfile {
8554+ struct file *hf_file;
8555+ struct au_branch *hf_br;
8556+};
1facf9fc 8557+
4a4d8108
AM
8558+struct au_vdir;
8559+struct au_fidir {
8560+ aufs_bindex_t fd_bbot;
8561+ aufs_bindex_t fd_nent;
8562+ struct au_vdir *fd_vdir_cache;
8563+ struct au_hfile fd_hfile[];
8564+};
1facf9fc 8565+
4a4d8108 8566+static inline int au_fidir_sz(int nent)
dece6358 8567+{
4f0767ce
JR
8568+ AuDebugOn(nent < 0);
8569+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 8570+}
1facf9fc 8571+
4a4d8108
AM
8572+struct au_finfo {
8573+ atomic_t fi_generation;
dece6358 8574+
4a4d8108
AM
8575+ struct au_rwsem fi_rwsem;
8576+ aufs_bindex_t fi_btop;
8577+
8578+ /* do not union them */
8579+ struct { /* for non-dir */
8580+ struct au_hfile fi_htop;
8581+ struct vm_operations_struct *fi_hvmop;
8582+ struct mutex fi_vm_mtx;
8583+ struct mutex fi_mmap;
8584+ };
8585+ struct au_fidir *fi_hdir; /* for dir only */
8586+} ____cacheline_aligned_in_smp;
1facf9fc 8587+
4a4d8108 8588+/* ---------------------------------------------------------------------- */
1facf9fc 8589+
4a4d8108
AM
8590+/* file.c */
8591+extern const struct address_space_operations aufs_aop;
8592+unsigned int au_file_roflags(unsigned int flags);
8593+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8594+ struct file *file);
8595+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8596+ struct au_fidir *fidir);
8597+int au_reopen_nondir(struct file *file);
8598+struct au_pin;
8599+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
8600+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8601+ int wlock);
8602+int au_do_flush(struct file *file, fl_owner_t id,
8603+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 8604+
4a4d8108
AM
8605+/* poll.c */
8606+#ifdef CONFIG_AUFS_POLL
8607+unsigned int aufs_poll(struct file *file, poll_table *wait);
8608+#endif
1facf9fc 8609+
4a4d8108
AM
8610+#ifdef CONFIG_AUFS_BR_HFSPLUS
8611+/* hfsplus.c */
8612+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
8613+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
8614+ struct file *h_file);
8615+#else
8616+static inline
8617+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 8618+{
4a4d8108
AM
8619+ return NULL;
8620+}
1facf9fc 8621+
4a4d8108
AM
8622+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
8623+ struct file *h_file);
8624+#endif
1facf9fc 8625+
4a4d8108
AM
8626+/* f_op.c */
8627+extern const struct file_operations aufs_file_fop;
8628+extern const struct vm_operations_struct aufs_vm_ops;
8629+int au_do_open_nondir(struct file *file, int flags);
8630+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
8631+
8632+#ifdef CONFIG_AUFS_SP_IATTR
8633+/* f_op_sp.c */
8634+int au_special_file(umode_t mode);
8635+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
8636+#else
8637+AuStubInt0(au_special_file, umode_t mode)
8638+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
8639+ dev_t rdev)
8640+{
8641+ init_special_inode(inode, mode, rdev);
8642+}
8643+#endif
1facf9fc 8644+
4a4d8108
AM
8645+/* finfo.c */
8646+void au_hfput(struct au_hfile *hf, struct file *file);
8647+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
8648+ struct file *h_file);
1facf9fc 8649+
4a4d8108
AM
8650+void au_update_figen(struct file *file);
8651+void au_fi_mmap_lock(struct file *file);
8652+void au_fi_mmap_unlock(struct file *file);
8653+struct au_fidir *au_fidir_alloc(struct super_block *sb);
8654+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 8655+
4a4d8108
AM
8656+void au_fi_init_once(void *_fi);
8657+void au_finfo_fin(struct file *file);
8658+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 8659+
4a4d8108
AM
8660+/* ioctl.c */
8661+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
8662+#ifdef CONFIG_COMPAT
8663+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
8664+ unsigned long arg);
8665+#endif
1facf9fc 8666+
4a4d8108 8667+/* ---------------------------------------------------------------------- */
1facf9fc 8668+
4a4d8108
AM
8669+static inline struct au_finfo *au_fi(struct file *file)
8670+{
8671+ return file->private_data;
8672+}
1facf9fc 8673+
4a4d8108 8674+/* ---------------------------------------------------------------------- */
1facf9fc 8675+
4a4d8108
AM
8676+/*
8677+ * fi_read_lock, fi_write_lock,
8678+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
8679+ */
8680+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 8681+
4a4d8108
AM
8682+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
8683+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
8684+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 8685+
1308ab2a 8686+/* ---------------------------------------------------------------------- */
8687+
4a4d8108
AM
8688+/* todo: hard/soft set? */
8689+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 8690+{
4a4d8108
AM
8691+ FiMustAnyLock(file);
8692+ return au_fi(file)->fi_btop;
8693+}
dece6358 8694+
4a4d8108
AM
8695+static inline aufs_bindex_t au_fbend_dir(struct file *file)
8696+{
8697+ FiMustAnyLock(file);
8698+ AuDebugOn(!au_fi(file)->fi_hdir);
8699+ return au_fi(file)->fi_hdir->fd_bbot;
8700+}
1facf9fc 8701+
4a4d8108
AM
8702+static inline struct au_vdir *au_fvdir_cache(struct file *file)
8703+{
8704+ FiMustAnyLock(file);
8705+ AuDebugOn(!au_fi(file)->fi_hdir);
8706+ return au_fi(file)->fi_hdir->fd_vdir_cache;
8707+}
1facf9fc 8708+
4a4d8108
AM
8709+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
8710+{
8711+ FiMustWriteLock(file);
8712+ au_fi(file)->fi_btop = bindex;
8713+}
1facf9fc 8714+
4a4d8108
AM
8715+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
8716+{
8717+ FiMustWriteLock(file);
8718+ AuDebugOn(!au_fi(file)->fi_hdir);
8719+ au_fi(file)->fi_hdir->fd_bbot = bindex;
8720+}
1308ab2a 8721+
4a4d8108
AM
8722+static inline void au_set_fvdir_cache(struct file *file,
8723+ struct au_vdir *vdir_cache)
8724+{
8725+ FiMustWriteLock(file);
8726+ AuDebugOn(!au_fi(file)->fi_hdir);
8727+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
8728+}
dece6358 8729+
4a4d8108
AM
8730+static inline struct file *au_hf_top(struct file *file)
8731+{
8732+ FiMustAnyLock(file);
8733+ AuDebugOn(au_fi(file)->fi_hdir);
8734+ return au_fi(file)->fi_htop.hf_file;
8735+}
1facf9fc 8736+
4a4d8108
AM
8737+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
8738+{
8739+ FiMustAnyLock(file);
8740+ AuDebugOn(!au_fi(file)->fi_hdir);
8741+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
8742+}
8743+
4a4d8108
AM
8744+/* todo: memory barrier? */
8745+static inline unsigned int au_figen(struct file *f)
dece6358 8746+{
4a4d8108
AM
8747+ return atomic_read(&au_fi(f)->fi_generation);
8748+}
dece6358 8749+
4a4d8108
AM
8750+static inline int au_test_mmapped(struct file *f)
8751+{
8752+ FiMustAnyLock(f);
8753+ return !!(au_fi(f)->fi_hvmop);
8754+}
1308ab2a 8755+
4a4d8108
AM
8756+#endif /* __KERNEL__ */
8757+#endif /* __AUFS_FILE_H__ */
b752ccd1
AM
8758diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
8759--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
8760+++ linux/fs/aufs/finfo.c 2010-10-21 09:52:43.090291764 +0200
8761@@ -0,0 +1,167 @@
4a4d8108
AM
8762+/*
8763+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8764+ *
8765+ * This program, aufs is free software; you can redistribute it and/or modify
8766+ * it under the terms of the GNU General Public License as published by
8767+ * the Free Software Foundation; either version 2 of the License, or
8768+ * (at your option) any later version.
8769+ *
8770+ * This program is distributed in the hope that it will be useful,
8771+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8772+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8773+ * GNU General Public License for more details.
8774+ *
8775+ * You should have received a copy of the GNU General Public License
8776+ * along with this program; if not, write to the Free Software
8777+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8778+ */
1308ab2a 8779+
4a4d8108
AM
8780+/*
8781+ * file private data
8782+ */
1facf9fc 8783+
4a4d8108
AM
8784+#include <linux/file.h>
8785+#include "aufs.h"
1facf9fc 8786+
4a4d8108
AM
8787+void au_hfput(struct au_hfile *hf, struct file *file)
8788+{
8789+ /* todo: direct access f_flags */
8790+ if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC))
8791+ allow_write_access(hf->hf_file);
8792+ fput(hf->hf_file);
8793+ hf->hf_file = NULL;
953406b4 8794+ atomic_dec_return(&hf->hf_br->br_count);
4a4d8108
AM
8795+ hf->hf_br = NULL;
8796+}
1facf9fc 8797+
4a4d8108
AM
8798+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
8799+{
8800+ struct au_finfo *finfo = au_fi(file);
8801+ struct au_hfile *hf;
8802+ struct au_fidir *fidir;
8803+
8804+ fidir = finfo->fi_hdir;
8805+ if (!fidir) {
8806+ AuDebugOn(finfo->fi_btop != bindex);
8807+ hf = &finfo->fi_htop;
8808+ } else
8809+ hf = fidir->fd_hfile + bindex;
8810+
8811+ if (hf && hf->hf_file)
8812+ au_hfput(hf, file);
8813+ if (val) {
8814+ FiMustWriteLock(file);
8815+ hf->hf_file = val;
8816+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 8817+ }
4a4d8108 8818+}
1facf9fc 8819+
4a4d8108
AM
8820+void au_update_figen(struct file *file)
8821+{
8822+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
8823+ /* smp_mb(); */ /* atomic_set */
1facf9fc 8824+}
8825+
4a4d8108
AM
8826+/* ---------------------------------------------------------------------- */
8827+
8828+void au_fi_mmap_lock(struct file *file)
1facf9fc 8829+{
4a4d8108
AM
8830+ FiMustWriteLock(file);
8831+ lockdep_off();
8832+ mutex_lock(&au_fi(file)->fi_mmap);
8833+ lockdep_on();
8834+}
1facf9fc 8835+
4a4d8108
AM
8836+void au_fi_mmap_unlock(struct file *file)
8837+{
8838+ lockdep_off();
8839+ mutex_unlock(&au_fi(file)->fi_mmap);
8840+ lockdep_on();
8841+}
1308ab2a 8842+
4a4d8108 8843+/* ---------------------------------------------------------------------- */
1308ab2a 8844+
4a4d8108
AM
8845+struct au_fidir *au_fidir_alloc(struct super_block *sb)
8846+{
8847+ struct au_fidir *fidir;
8848+ int nbr;
8849+
8850+ nbr = au_sbend(sb) + 1;
8851+ if (nbr < 2)
8852+ nbr = 2; /* initial allocate for 2 branches */
8853+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
8854+ if (fidir) {
8855+ fidir->fd_bbot = -1;
8856+ fidir->fd_nent = nbr;
8857+ fidir->fd_vdir_cache = NULL;
8858+ }
8859+
8860+ return fidir;
8861+}
8862+
8863+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
8864+{
8865+ int err;
8866+ struct au_fidir *fidir, *p;
8867+
8868+ AuRwMustWriteLock(&finfo->fi_rwsem);
8869+ fidir = finfo->fi_hdir;
8870+ AuDebugOn(!fidir);
8871+
8872+ err = -ENOMEM;
8873+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
8874+ GFP_NOFS);
8875+ if (p) {
8876+ p->fd_nent = nbr;
8877+ finfo->fi_hdir = p;
8878+ err = 0;
8879+ }
1facf9fc 8880+
dece6358 8881+ return err;
1facf9fc 8882+}
1308ab2a 8883+
8884+/* ---------------------------------------------------------------------- */
8885+
4a4d8108 8886+void au_finfo_fin(struct file *file)
1308ab2a 8887+{
4a4d8108
AM
8888+ struct au_finfo *finfo;
8889+
8890+ finfo = au_fi(file);
8891+ AuDebugOn(finfo->fi_hdir);
8892+ AuRwDestroy(&finfo->fi_rwsem);
8893+ au_cache_free_finfo(finfo);
1308ab2a 8894+}
1308ab2a 8895+
953406b4 8896+void au_fi_init_once(void *_fi)
4a4d8108 8897+{
953406b4 8898+ struct au_finfo *fi = _fi;
1308ab2a 8899+
953406b4
AM
8900+ au_rw_init(&fi->fi_rwsem);
8901+ mutex_init(&fi->fi_vm_mtx);
8902+ mutex_init(&fi->fi_mmap);
4a4d8108 8903+}
1308ab2a 8904+
4a4d8108
AM
8905+int au_finfo_init(struct file *file, struct au_fidir *fidir)
8906+{
8907+ int err;
8908+ struct au_finfo *finfo;
8909+ struct dentry *dentry;
8910+
8911+ err = -ENOMEM;
8912+ dentry = file->f_dentry;
8913+ finfo = au_cache_alloc_finfo();
8914+ if (unlikely(!finfo))
8915+ goto out;
8916+
8917+ err = 0;
8918+ au_rw_write_lock(&finfo->fi_rwsem);
8919+ finfo->fi_btop = -1;
8920+ finfo->fi_hdir = fidir;
8921+ atomic_set(&finfo->fi_generation, au_digen(dentry));
8922+ /* smp_mb(); */ /* atomic_set */
8923+
8924+ file->private_data = finfo;
8925+
8926+out:
8927+ return err;
8928+}
b752ccd1
AM
8929diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
8930--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
8931+++ linux/fs/aufs/f_op.c 2010-10-21 09:52:43.090291764 +0200
8932@@ -0,0 +1,886 @@
dece6358 8933+/*
4a4d8108 8934+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
8935+ *
8936+ * This program, aufs is free software; you can redistribute it and/or modify
8937+ * it under the terms of the GNU General Public License as published by
8938+ * the Free Software Foundation; either version 2 of the License, or
8939+ * (at your option) any later version.
8940+ *
8941+ * This program is distributed in the hope that it will be useful,
8942+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8943+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8944+ * GNU General Public License for more details.
8945+ *
8946+ * You should have received a copy of the GNU General Public License
8947+ * along with this program; if not, write to the Free Software
8948+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8949+ */
1facf9fc 8950+
8951+/*
4a4d8108 8952+ * file and vm operations
1facf9fc 8953+ */
dece6358
AM
8954+
8955+#include <linux/file.h>
4a4d8108
AM
8956+#include <linux/fs_stack.h>
8957+#include <linux/mman.h>
8958+#include <linux/mm.h>
8959+#include <linux/security.h>
dece6358
AM
8960+#include "aufs.h"
8961+
4a4d8108 8962+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 8963+{
4a4d8108
AM
8964+ int err;
8965+ aufs_bindex_t bindex;
8966+ struct file *h_file;
8967+ struct dentry *dentry;
8968+ struct au_finfo *finfo;
8969+
8970+ FiMustWriteLock(file);
8971+
8972+ err = 0;
8973+ dentry = file->f_dentry;
8974+ finfo = au_fi(file);
8975+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
8976+ finfo->fi_hvmop = NULL;
8977+ bindex = au_dbstart(dentry);
8978+ h_file = au_h_open(dentry, bindex, flags, file);
8979+ if (IS_ERR(h_file))
8980+ err = PTR_ERR(h_file);
8981+ else {
8982+ au_set_fbstart(file, bindex);
8983+ au_set_h_fptr(file, bindex, h_file);
8984+ au_update_figen(file);
8985+ /* todo: necessary? */
8986+ /* file->f_ra = h_file->f_ra; */
8987+ }
8988+ return err;
1facf9fc 8989+}
8990+
4a4d8108
AM
8991+static int aufs_open_nondir(struct inode *inode __maybe_unused,
8992+ struct file *file)
1facf9fc 8993+{
4a4d8108 8994+ int err;
1308ab2a 8995+ struct super_block *sb;
1facf9fc 8996+
4a4d8108
AM
8997+ AuDbg("%.*s, f_ flags 0x%x, f_mode 0x%x\n",
8998+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
8999+ file->f_mode);
1facf9fc 9000+
4a4d8108
AM
9001+ sb = file->f_dentry->d_sb;
9002+ si_read_lock(sb, AuLock_FLUSH);
9003+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
9004+ si_read_unlock(sb);
9005+ return err;
9006+}
1facf9fc 9007+
4a4d8108
AM
9008+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
9009+{
9010+ struct au_finfo *finfo;
9011+ aufs_bindex_t bindex;
1facf9fc 9012+
4a4d8108
AM
9013+ finfo = au_fi(file);
9014+ bindex = finfo->fi_btop;
953406b4 9015+ if (bindex >= 0)
4a4d8108 9016+ au_set_h_fptr(file, bindex, NULL);
dece6358 9017+
4a4d8108
AM
9018+ au_finfo_fin(file);
9019+ return 0;
1facf9fc 9020+}
9021+
4a4d8108
AM
9022+/* ---------------------------------------------------------------------- */
9023+
9024+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 9025+{
1308ab2a 9026+ int err;
4a4d8108
AM
9027+ struct file *h_file;
9028+
9029+ err = 0;
9030+ h_file = au_hf_top(file);
9031+ if (h_file)
9032+ err = vfsub_flush(h_file, id);
9033+ return err;
9034+}
9035+
9036+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
9037+{
9038+ return au_do_flush(file, id, au_do_flush_nondir);
9039+}
9040+
9041+/* ---------------------------------------------------------------------- */
9042+
9043+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
9044+ loff_t *ppos)
9045+{
9046+ ssize_t err;
dece6358 9047+ struct dentry *dentry;
4a4d8108 9048+ struct file *h_file;
dece6358 9049+ struct super_block *sb;
1facf9fc 9050+
dece6358
AM
9051+ dentry = file->f_dentry;
9052+ sb = dentry->d_sb;
953406b4 9053+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108 9054+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
9055+ if (unlikely(err))
9056+ goto out;
1facf9fc 9057+
4a4d8108
AM
9058+ h_file = au_hf_top(file);
9059+ err = vfsub_read_u(h_file, buf, count, ppos);
9060+ /* todo: necessary? */
9061+ /* file->f_ra = h_file->f_ra; */
9062+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1308ab2a 9063+
4a4d8108
AM
9064+ di_read_unlock(dentry, AuLock_IR);
9065+ fi_read_unlock(file);
4f0767ce 9066+out:
dece6358
AM
9067+ si_read_unlock(sb);
9068+ return err;
9069+}
1facf9fc 9070+
4a4d8108
AM
9071+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
9072+ size_t count, loff_t *ppos)
dece6358 9073+{
4a4d8108
AM
9074+ ssize_t err;
9075+ struct au_pin pin;
dece6358 9076+ struct dentry *dentry;
4a4d8108 9077+ struct inode *inode;
953406b4 9078+ struct super_block *sb;
4a4d8108
AM
9079+ struct file *h_file;
9080+ char __user *buf = (char __user *)ubuf;
1facf9fc 9081+
dece6358 9082+ dentry = file->f_dentry;
953406b4 9083+ sb = dentry->d_sb;
4a4d8108 9084+ inode = dentry->d_inode;
953406b4
AM
9085+ mutex_lock(&inode->i_mutex);
9086+ si_read_lock(sb, AuLock_FLUSH);
1facf9fc 9087+
4a4d8108
AM
9088+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9089+ if (unlikely(err))
9090+ goto out;
1facf9fc 9091+
4a4d8108
AM
9092+ err = au_ready_to_write(file, -1, &pin);
9093+ di_downgrade_lock(dentry, AuLock_IR);
9094+ if (unlikely(err))
9095+ goto out_unlock;
1facf9fc 9096+
4a4d8108
AM
9097+ h_file = au_hf_top(file);
9098+ au_unpin(&pin);
9099+ err = vfsub_write_u(h_file, buf, count, ppos);
9100+ au_cpup_attr_timesizes(inode);
9101+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9102+
4f0767ce 9103+out_unlock:
4a4d8108
AM
9104+ di_read_unlock(dentry, AuLock_IR);
9105+ fi_write_unlock(file);
4f0767ce 9106+out:
953406b4 9107+ si_read_unlock(sb);
4a4d8108 9108+ mutex_unlock(&inode->i_mutex);
dece6358
AM
9109+ return err;
9110+}
1facf9fc 9111+
4a4d8108
AM
9112+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
9113+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 9114+{
4a4d8108
AM
9115+ ssize_t err;
9116+ struct file *file;
9117+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
9118+ loff_t);
1facf9fc 9119+
4a4d8108
AM
9120+ err = security_file_permission(h_file, rw);
9121+ if (unlikely(err))
9122+ goto out;
1facf9fc 9123+
4a4d8108
AM
9124+ err = -ENOSYS;
9125+ func = NULL;
9126+ if (rw == MAY_READ)
9127+ func = h_file->f_op->aio_read;
9128+ else if (rw == MAY_WRITE)
9129+ func = h_file->f_op->aio_write;
9130+ if (func) {
9131+ file = kio->ki_filp;
9132+ kio->ki_filp = h_file;
9133+ err = func(kio, iov, nv, pos);
9134+ kio->ki_filp = file;
9135+ } else
9136+ /* currently there is no such fs */
9137+ WARN_ON_ONCE(1);
1facf9fc 9138+
4f0767ce 9139+out:
dece6358
AM
9140+ return err;
9141+}
1facf9fc 9142+
4a4d8108
AM
9143+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
9144+ unsigned long nv, loff_t pos)
1facf9fc 9145+{
4a4d8108
AM
9146+ ssize_t err;
9147+ struct file *file, *h_file;
9148+ struct dentry *dentry;
dece6358 9149+ struct super_block *sb;
1facf9fc 9150+
4a4d8108 9151+ file = kio->ki_filp;
dece6358 9152+ dentry = file->f_dentry;
1308ab2a 9153+ sb = dentry->d_sb;
953406b4 9154+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108
AM
9155+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9156+ if (unlikely(err))
9157+ goto out;
9158+
9159+ h_file = au_hf_top(file);
9160+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
9161+ /* todo: necessary? */
9162+ /* file->f_ra = h_file->f_ra; */
9163+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9164+ di_read_unlock(dentry, AuLock_IR);
9165+ fi_read_unlock(file);
1facf9fc 9166+
4f0767ce 9167+out:
4a4d8108 9168+ si_read_unlock(sb);
1308ab2a 9169+ return err;
9170+}
1facf9fc 9171+
4a4d8108
AM
9172+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
9173+ unsigned long nv, loff_t pos)
1308ab2a 9174+{
4a4d8108
AM
9175+ ssize_t err;
9176+ struct au_pin pin;
9177+ struct dentry *dentry;
9178+ struct inode *inode;
953406b4 9179+ struct super_block *sb;
4a4d8108 9180+ struct file *file, *h_file;
1308ab2a 9181+
4a4d8108 9182+ file = kio->ki_filp;
1308ab2a 9183+ dentry = file->f_dentry;
953406b4 9184+ sb = dentry->d_sb;
1308ab2a 9185+ inode = dentry->d_inode;
953406b4
AM
9186+ mutex_lock(&inode->i_mutex);
9187+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108
AM
9188+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9189+ if (unlikely(err))
1308ab2a 9190+ goto out;
1facf9fc 9191+
4a4d8108
AM
9192+ err = au_ready_to_write(file, -1, &pin);
9193+ di_downgrade_lock(dentry, AuLock_IR);
dece6358 9194+ if (unlikely(err))
4a4d8108 9195+ goto out_unlock;
1facf9fc 9196+
4a4d8108
AM
9197+ au_unpin(&pin);
9198+ h_file = au_hf_top(file);
9199+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
9200+ au_cpup_attr_timesizes(inode);
9201+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9202+
4f0767ce 9203+out_unlock:
4a4d8108
AM
9204+ di_read_unlock(dentry, AuLock_IR);
9205+ fi_write_unlock(file);
4f0767ce 9206+out:
953406b4 9207+ si_read_unlock(sb);
4a4d8108 9208+ mutex_unlock(&inode->i_mutex);
dece6358 9209+ return err;
1facf9fc 9210+}
9211+
4a4d8108
AM
9212+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
9213+ struct pipe_inode_info *pipe, size_t len,
9214+ unsigned int flags)
1facf9fc 9215+{
4a4d8108
AM
9216+ ssize_t err;
9217+ struct file *h_file;
9218+ struct dentry *dentry;
dece6358 9219+ struct super_block *sb;
1facf9fc 9220+
dece6358 9221+ dentry = file->f_dentry;
dece6358 9222+ sb = dentry->d_sb;
953406b4 9223+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108
AM
9224+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9225+ if (unlikely(err))
dece6358 9226+ goto out;
1facf9fc 9227+
4a4d8108
AM
9228+ err = -EINVAL;
9229+ h_file = au_hf_top(file);
9230+ if (au_test_loopback_kthread()) {
9231+ file->f_mapping = h_file->f_mapping;
9232+ smp_mb(); /* unnecessary? */
1308ab2a 9233+ }
4a4d8108
AM
9234+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
9235+ /* todo: necessasry? */
9236+ /* file->f_ra = h_file->f_ra; */
9237+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 9238+
4a4d8108
AM
9239+ di_read_unlock(dentry, AuLock_IR);
9240+ fi_read_unlock(file);
1facf9fc 9241+
4f0767ce 9242+out:
4a4d8108 9243+ si_read_unlock(sb);
dece6358 9244+ return err;
1facf9fc 9245+}
9246+
4a4d8108
AM
9247+static ssize_t
9248+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
9249+ size_t len, unsigned int flags)
1facf9fc 9250+{
4a4d8108
AM
9251+ ssize_t err;
9252+ struct au_pin pin;
9253+ struct dentry *dentry;
9254+ struct inode *inode;
953406b4 9255+ struct super_block *sb;
4a4d8108 9256+ struct file *h_file;
1facf9fc 9257+
4a4d8108
AM
9258+ dentry = file->f_dentry;
9259+ inode = dentry->d_inode;
953406b4
AM
9260+ mutex_lock(&inode->i_mutex);
9261+ sb = dentry->d_sb;
9262+ si_read_lock(sb, AuLock_FLUSH);
9263+
4a4d8108
AM
9264+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9265+ if (unlikely(err))
9266+ goto out;
1facf9fc 9267+
4a4d8108
AM
9268+ err = au_ready_to_write(file, -1, &pin);
9269+ di_downgrade_lock(dentry, AuLock_IR);
9270+ if (unlikely(err))
9271+ goto out_unlock;
1facf9fc 9272+
4a4d8108
AM
9273+ h_file = au_hf_top(file);
9274+ au_unpin(&pin);
9275+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
9276+ au_cpup_attr_timesizes(inode);
9277+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9278+
4f0767ce 9279+out_unlock:
4a4d8108
AM
9280+ di_read_unlock(dentry, AuLock_IR);
9281+ fi_write_unlock(file);
4f0767ce 9282+out:
953406b4 9283+ si_read_unlock(sb);
4a4d8108
AM
9284+ mutex_unlock(&inode->i_mutex);
9285+ return err;
9286+}
1facf9fc 9287+
4a4d8108
AM
9288+/* ---------------------------------------------------------------------- */
9289+
9290+static struct file *au_safe_file(struct vm_area_struct *vma)
9291+{
9292+ struct file *file;
9293+
9294+ file = vma->vm_file;
9295+ if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
9296+ return file;
9297+ return NULL;
1facf9fc 9298+}
9299+
4a4d8108 9300+static void au_reset_file(struct vm_area_struct *vma, struct file *file)
1facf9fc 9301+{
4a4d8108
AM
9302+ vma->vm_file = file;
9303+ /* smp_mb(); */ /* flush vm_file */
9304+}
1facf9fc 9305+
4a4d8108
AM
9306+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
9307+{
9308+ int err;
9309+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9310+ struct file *file, *h_file;
9311+ struct au_finfo *finfo;
1facf9fc 9312+
4a4d8108
AM
9313+ /* todo: non-robr mode, user vm_file as it is? */
9314+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 9315+
4a4d8108
AM
9316+ /* do not revalidate, no si lock */
9317+ finfo = au_fi(file);
9318+ AuDebugOn(finfo->fi_hdir);
9319+ h_file = finfo->fi_htop.hf_file;
9320+ AuDebugOn(!h_file || !finfo->fi_hvmop);
9321+
9322+ mutex_lock(&finfo->fi_vm_mtx);
9323+ vma->vm_file = h_file;
9324+ err = finfo->fi_hvmop->fault(vma, vmf);
9325+ /* todo: necessary? */
9326+ /* file->f_ra = h_file->f_ra; */
9327+ au_reset_file(vma, file);
9328+ mutex_unlock(&finfo->fi_vm_mtx);
9329+#if 0 /* def CONFIG_SMP */
9330+ /* wake_up_nr(&wq, online_cpu - 1); */
9331+ wake_up_all(&wq);
9332+#else
9333+ wake_up(&wq);
9334+#endif
1facf9fc 9335+
dece6358 9336+ return err;
1facf9fc 9337+}
9338+
4a4d8108 9339+static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1facf9fc 9340+{
dece6358 9341+ int err;
4a4d8108
AM
9342+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9343+ struct file *file, *h_file;
9344+ struct au_finfo *finfo;
1facf9fc 9345+
4a4d8108 9346+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 9347+
4a4d8108
AM
9348+ finfo = au_fi(file);
9349+ AuDebugOn(finfo->fi_hdir);
9350+ h_file = finfo->fi_htop.hf_file;
9351+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 9352+
4a4d8108
AM
9353+ mutex_lock(&finfo->fi_vm_mtx);
9354+ vma->vm_file = h_file;
9355+ err = finfo->fi_hvmop->page_mkwrite(vma, vmf);
9356+ au_reset_file(vma, file);
9357+ mutex_unlock(&finfo->fi_vm_mtx);
9358+ wake_up(&wq);
1308ab2a 9359+
dece6358 9360+ return err;
1facf9fc 9361+}
9362+
4a4d8108 9363+static void aufs_vm_close(struct vm_area_struct *vma)
1facf9fc 9364+{
4a4d8108
AM
9365+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9366+ struct file *file, *h_file;
9367+ struct au_finfo *finfo;
dece6358 9368+
4a4d8108 9369+ wait_event(wq, (file = au_safe_file(vma)));
dece6358 9370+
4a4d8108
AM
9371+ finfo = au_fi(file);
9372+ AuDebugOn(finfo->fi_hdir);
9373+ h_file = finfo->fi_htop.hf_file;
9374+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 9375+
4a4d8108
AM
9376+ mutex_lock(&finfo->fi_vm_mtx);
9377+ vma->vm_file = h_file;
9378+ finfo->fi_hvmop->close(vma);
9379+ au_reset_file(vma, file);
9380+ mutex_unlock(&finfo->fi_vm_mtx);
9381+ wake_up(&wq);
9382+}
1facf9fc 9383+
4a4d8108
AM
9384+const struct vm_operations_struct aufs_vm_ops = {
9385+ .close = aufs_vm_close,
9386+ .fault = aufs_fault,
9387+ .page_mkwrite = aufs_page_mkwrite
1308ab2a 9388+};
dece6358 9389+
1308ab2a 9390+/* ---------------------------------------------------------------------- */
1facf9fc 9391+
4a4d8108
AM
9392+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
9393+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
1308ab2a 9394+
4a4d8108 9395+static unsigned long au_arch_prot_conv(unsigned long flags)
dece6358 9396+{
4a4d8108
AM
9397+ /* currently ppc64 only */
9398+#ifdef CONFIG_PPC64
9399+ /* cf. linux/arch/powerpc/include/asm/mman.h */
9400+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
9401+ return AuConv_VM_PROT(flags, SAO);
9402+#else
9403+ AuDebugOn(arch_calc_vm_prot_bits(-1));
9404+ return 0;
9405+#endif
dece6358
AM
9406+}
9407+
4a4d8108 9408+static unsigned long au_prot_conv(unsigned long flags)
dece6358 9409+{
4a4d8108
AM
9410+ return AuConv_VM_PROT(flags, READ)
9411+ | AuConv_VM_PROT(flags, WRITE)
9412+ | AuConv_VM_PROT(flags, EXEC)
9413+ | au_arch_prot_conv(flags);
dece6358
AM
9414+}
9415+
4a4d8108
AM
9416+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
9417+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
dece6358 9418+
4a4d8108 9419+static unsigned long au_flag_conv(unsigned long flags)
dece6358 9420+{
4a4d8108
AM
9421+ return AuConv_VM_MAP(flags, GROWSDOWN)
9422+ | AuConv_VM_MAP(flags, DENYWRITE)
9423+ | AuConv_VM_MAP(flags, EXECUTABLE)
9424+ | AuConv_VM_MAP(flags, LOCKED);
dece6358
AM
9425+}
9426+
4a4d8108
AM
9427+static struct vm_operations_struct *
9428+au_hvmop(struct file *h_file, struct vm_area_struct *vma, unsigned long *flags)
dece6358 9429+{
4a4d8108
AM
9430+ struct vm_operations_struct *h_vmop;
9431+ unsigned long prot;
9432+ int err;
dece6358 9433+
4a4d8108
AM
9434+ h_vmop = ERR_PTR(-ENODEV);
9435+ if (!h_file->f_op || !h_file->f_op->mmap)
9436+ goto out;
dece6358 9437+
4a4d8108
AM
9438+ prot = au_prot_conv(vma->vm_flags);
9439+ err = security_file_mmap(h_file, /*reqprot*/prot, prot,
9440+ au_flag_conv(vma->vm_flags), vma->vm_start, 0);
9441+ h_vmop = ERR_PTR(err);
9442+ if (unlikely(err))
9443+ goto out;
dece6358 9444+
4a4d8108
AM
9445+ err = h_file->f_op->mmap(h_file, vma);
9446+ h_vmop = ERR_PTR(err);
9447+ if (unlikely(err))
9448+ goto out;
dece6358 9449+
4a4d8108
AM
9450+ /* oops, it became 'const' */
9451+ h_vmop = (struct vm_operations_struct *)vma->vm_ops;
9452+ *flags = vma->vm_flags;
9453+ err = do_munmap(current->mm, vma->vm_start,
9454+ vma->vm_end - vma->vm_start);
9455+ if (unlikely(err)) {
9456+ AuIOErr("failed internal unmapping %.*s, %d\n",
9457+ AuDLNPair(h_file->f_dentry), err);
9458+ h_vmop = ERR_PTR(-EIO);
9459+ }
dece6358 9460+
4f0767ce 9461+out:
4a4d8108 9462+ return h_vmop;
dece6358
AM
9463+}
9464+
1308ab2a 9465+/*
4a4d8108
AM
9466+ * This is another ugly approach to keep the lock order, particularly
9467+ * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
9468+ * find it in git-log, if you want.
1308ab2a 9469+ *
4a4d8108
AM
9470+ * native readdir: i_mutex, copy_to_user, mmap_sem
9471+ * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
1308ab2a 9472+ *
4a4d8108
AM
9473+ * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
9474+ * acquire aufs rwsem. It introduces a circular locking dependency.
9475+ * To address this problem, aufs_mmap() delegates the part which requires aufs
9476+ * rwsem to its internal workqueue.
1308ab2a 9477+ */
9478+
4a4d8108
AM
9479+/* very ugly approach */
9480+#include "mtx.h"
1308ab2a 9481+
4a4d8108
AM
9482+struct au_mmap_pre_args {
9483+ /* input */
9484+ struct file *file;
9485+ struct vm_area_struct *vma;
1308ab2a 9486+
4a4d8108
AM
9487+ /* output */
9488+ int *errp;
9489+ struct file *h_file;
9490+ struct au_branch *br;
9491+ int mmapped;
9492+};
dece6358 9493+
4a4d8108
AM
9494+static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
9495+ struct file **h_file, struct au_branch **br,
9496+ int *mmapped)
dece6358 9497+{
4a4d8108
AM
9498+ int err;
9499+ aufs_bindex_t bstart;
9500+ const unsigned char wlock
9501+ = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
9502+ struct dentry *dentry;
9503+ struct super_block *sb;
1308ab2a 9504+
4a4d8108
AM
9505+ dentry = file->f_dentry;
9506+ sb = dentry->d_sb;
953406b4 9507+ si_read_lock(sb, !AuLock_FLUSH);
4a4d8108
AM
9508+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9509+ if (unlikely(err))
9510+ goto out;
9511+
9512+ *mmapped = !!au_test_mmapped(file);
9513+ if (wlock) {
9514+ struct au_pin pin;
9515+
9516+ err = au_ready_to_write(file, -1, &pin);
9517+ di_write_unlock(dentry);
9518+ if (unlikely(err))
9519+ goto out_unlock;
9520+ au_unpin(&pin);
9521+ } else
9522+ di_write_unlock(dentry);
9523+ bstart = au_fbstart(file);
9524+ *br = au_sbr(sb, bstart);
9525+ *h_file = au_hf_top(file);
9526+ get_file(*h_file);
9527+ au_fi_mmap_lock(file);
9528+
9529+out_unlock:
9530+ fi_write_unlock(file);
9531+out:
9532+ si_read_unlock(sb);
9533+ return err;
dece6358
AM
9534+}
9535+
4a4d8108 9536+static void au_call_mmap_pre(void *args)
dece6358 9537+{
4a4d8108
AM
9538+ struct au_mmap_pre_args *a = args;
9539+ *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->br,
9540+ &a->mmapped);
dece6358
AM
9541+}
9542+
4a4d8108 9543+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 9544+{
4a4d8108
AM
9545+ int err, wkq_err;
9546+ unsigned long h_vmflags;
1308ab2a 9547+ struct au_finfo *finfo;
4a4d8108
AM
9548+ struct dentry *h_dentry;
9549+ struct vm_operations_struct *h_vmop, *vmop;
9550+ struct au_mmap_pre_args args = {
9551+ .file = file,
9552+ .vma = vma,
9553+ .errp = &err
9554+ };
9555+
b752ccd1 9556+ wkq_err = au_wkq_wait_pre(au_call_mmap_pre, &args);
4a4d8108
AM
9557+ if (unlikely(wkq_err))
9558+ err = wkq_err;
9559+ if (unlikely(err))
9560+ goto out;
9561+ finfo = au_fi(file);
9562+ mutex_set_owner(&finfo->fi_mmap);
9563+
9564+ h_dentry = args.h_file->f_dentry;
9565+ if (!args.mmapped && au_test_fs_bad_mapping(h_dentry->d_sb)) {
1308ab2a 9566+ /*
4a4d8108
AM
9567+ * by this assignment, f_mapping will differs from aufs inode
9568+ * i_mapping.
9569+ * if someone else mixes the use of f_dentry->d_inode and
9570+ * f_mapping->host, then a problem may arise.
1308ab2a 9571+ */
4a4d8108
AM
9572+ file->f_mapping = args.h_file->f_mapping;
9573+ }
1308ab2a 9574+
4a4d8108
AM
9575+ /* always try this internal mmap to get vma flags */
9576+ h_vmflags = 0; /* gcc warning */
9577+ h_vmop = au_hvmop(args.h_file, vma, &h_vmflags);
9578+ err = PTR_ERR(h_vmop);
9579+ if (IS_ERR(h_vmop))
9580+ goto out_unlock;
9581+ AuDebugOn(args.mmapped && h_vmop != finfo->fi_hvmop);
9582+
9583+ vmop = (void *)au_dy_vmop(file, args.br, h_vmop);
9584+ err = PTR_ERR(vmop);
9585+ if (IS_ERR(vmop))
9586+ goto out_unlock;
9587+
9588+ /*
9589+ * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
9590+ * currently MAP_DENYWRITE from userspace is ignored, but elf loader
9591+ * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
9592+ * both of the aufs file and the lower file is deny_write_access()-ed.
9593+ * finally I hope we can skip handlling MAP_DENYWRITE here.
9594+ */
9595+ err = generic_file_mmap(file, vma);
9596+ if (unlikely(err))
9597+ goto out_unlock;
9598+
9599+ vma->vm_ops = vmop;
9600+ vma->vm_flags = h_vmflags;
9601+ if (!args.mmapped)
9602+ finfo->fi_hvmop = h_vmop;
9603+
9604+ vfsub_file_accessed(args.h_file);
9605+ /* update without lock, I don't think it a problem */
9606+ fsstack_copy_attr_atime(file->f_dentry->d_inode, h_dentry->d_inode);
9607+
4f0767ce 9608+out_unlock:
4a4d8108
AM
9609+ au_fi_mmap_unlock(file);
9610+ fput(args.h_file);
4f0767ce 9611+out:
4a4d8108
AM
9612+ return err;
9613+}
9614+
9615+/* ---------------------------------------------------------------------- */
9616+
b752ccd1 9617+static int aufs_fsync_nondir(struct file *file, int datasync)
4a4d8108
AM
9618+{
9619+ int err;
9620+ struct au_pin pin;
b752ccd1 9621+ struct dentry *dentry;
4a4d8108
AM
9622+ struct inode *inode;
9623+ struct file *h_file;
9624+ struct super_block *sb;
9625+
b752ccd1 9626+ dentry = file->f_dentry;
4a4d8108
AM
9627+ inode = dentry->d_inode;
9628+ IMustLock(file->f_mapping->host);
9629+ if (inode != file->f_mapping->host) {
9630+ mutex_unlock(&file->f_mapping->host->i_mutex);
9631+ mutex_lock(&inode->i_mutex);
9632+ }
9633+ IMustLock(inode);
9634+
9635+ sb = dentry->d_sb;
953406b4 9636+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108
AM
9637+
9638+ err = 0; /* -EBADF; */ /* posix? */
9639+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
953406b4 9640+ goto out;
4a4d8108
AM
9641+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9642+ if (unlikely(err))
953406b4 9643+ goto out;
4a4d8108
AM
9644+
9645+ err = au_ready_to_write(file, -1, &pin);
9646+ di_downgrade_lock(dentry, AuLock_IR);
9647+ if (unlikely(err))
9648+ goto out_unlock;
9649+ au_unpin(&pin);
9650+
9651+ err = -EINVAL;
9652+ h_file = au_hf_top(file);
9653+ if (h_file->f_op && h_file->f_op->fsync) {
4a4d8108
AM
9654+ struct mutex *h_mtx;
9655+
9656+ /*
9657+ * no filemap_fdatawrite() since aufs file has no its own
9658+ * mapping, but dir.
9659+ */
b752ccd1 9660+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
4a4d8108 9661+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
b752ccd1 9662+ err = h_file->f_op->fsync(h_file, datasync);
4a4d8108
AM
9663+ if (!err)
9664+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9665+ /*ignore*/
9666+ au_cpup_attr_timesizes(inode);
9667+ mutex_unlock(h_mtx);
9668+ }
9669+
4f0767ce 9670+out_unlock:
4a4d8108 9671+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 9672+ fi_write_unlock(file);
4f0767ce 9673+out:
953406b4 9674+ si_read_unlock(sb);
4a4d8108
AM
9675+ if (inode != file->f_mapping->host) {
9676+ mutex_unlock(&inode->i_mutex);
9677+ mutex_lock(&file->f_mapping->host->i_mutex);
9678+ }
9679+ return err;
dece6358
AM
9680+}
9681+
4a4d8108
AM
9682+/* no one supports this operation, currently */
9683+#if 0
9684+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 9685+{
4a4d8108
AM
9686+ int err;
9687+ struct au_pin pin;
1308ab2a 9688+ struct dentry *dentry;
4a4d8108
AM
9689+ struct inode *inode;
9690+ struct file *file, *h_file;
953406b4 9691+ struct super_block *sb;
1308ab2a 9692+
4a4d8108 9693+ file = kio->ki_filp;
1308ab2a 9694+ dentry = file->f_dentry;
4a4d8108 9695+ inode = dentry->d_inode;
953406b4
AM
9696+ mutex_lock(&inode->i_mutex);
9697+
9698+ sb = dentry->d_sb;
9699+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108
AM
9700+
9701+ err = 0; /* -EBADF; */ /* posix? */
9702+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
9703+ goto out;
9704+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9705+ if (unlikely(err))
1308ab2a 9706+ goto out;
9707+
4a4d8108
AM
9708+ err = au_ready_to_write(file, -1, &pin);
9709+ di_downgrade_lock(dentry, AuLock_IR);
9710+ if (unlikely(err))
9711+ goto out_unlock;
9712+ au_unpin(&pin);
1308ab2a 9713+
4a4d8108
AM
9714+ err = -ENOSYS;
9715+ h_file = au_hf_top(file);
9716+ if (h_file->f_op && h_file->f_op->aio_fsync) {
9717+ struct dentry *h_d;
9718+ struct mutex *h_mtx;
1308ab2a 9719+
4a4d8108
AM
9720+ h_d = h_file->f_dentry;
9721+ h_mtx = &h_d->d_inode->i_mutex;
9722+ if (!is_sync_kiocb(kio)) {
9723+ get_file(h_file);
9724+ fput(file);
9725+ }
9726+ kio->ki_filp = h_file;
9727+ err = h_file->f_op->aio_fsync(kio, datasync);
9728+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
9729+ if (!err)
9730+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9731+ /*ignore*/
9732+ au_cpup_attr_timesizes(inode);
9733+ mutex_unlock(h_mtx);
9734+ }
1308ab2a 9735+
4f0767ce 9736+out_unlock:
4a4d8108
AM
9737+ di_read_unlock(dentry, AuLock_IR);
9738+ fi_write_unlock(file);
4f0767ce 9739+out:
953406b4 9740+ si_read_unlock(sb);
4a4d8108
AM
9741+ mutex_unlock(&inode->i_mutex);
9742+ return err;
dece6358 9743+}
4a4d8108 9744+#endif
dece6358 9745+
4a4d8108 9746+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 9747+{
4a4d8108
AM
9748+ int err;
9749+ struct file *h_file;
9750+ struct dentry *dentry;
9751+ struct super_block *sb;
1308ab2a 9752+
4a4d8108
AM
9753+ dentry = file->f_dentry;
9754+ sb = dentry->d_sb;
953406b4 9755+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108
AM
9756+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9757+ if (unlikely(err))
9758+ goto out;
9759+
9760+ h_file = au_hf_top(file);
9761+ if (h_file->f_op && h_file->f_op->fasync)
9762+ err = h_file->f_op->fasync(fd, h_file, flag);
9763+
9764+ di_read_unlock(dentry, AuLock_IR);
9765+ fi_read_unlock(file);
1308ab2a 9766+
4f0767ce 9767+out:
4a4d8108 9768+ si_read_unlock(sb);
1308ab2a 9769+ return err;
dece6358 9770+}
4a4d8108
AM
9771+
9772+/* ---------------------------------------------------------------------- */
9773+
9774+/* no one supports this operation, currently */
9775+#if 0
9776+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
9777+ size_t len, loff_t *pos , int more)
9778+{
9779+}
9780+#endif
9781+
9782+/* ---------------------------------------------------------------------- */
9783+
9784+const struct file_operations aufs_file_fop = {
9785+ .owner = THIS_MODULE,
9786+ /*
9787+ * while generic_file_llseek/_unlocked() don't use BKL,
9788+ * don't use it since it operates file->f_mapping->host.
9789+ * in aufs, it may be a real file and may confuse users by UDBA.
9790+ */
9791+ /* .llseek = generic_file_llseek, */
9792+
9793+ .read = aufs_read,
9794+ .write = aufs_write,
9795+ .aio_read = aufs_aio_read,
9796+ .aio_write = aufs_aio_write,
9797+#ifdef CONFIG_AUFS_POLL
9798+ .poll = aufs_poll,
9799+#endif
9800+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
9801+#ifdef CONFIG_COMPAT
9802+ .compat_ioctl = aufs_ioctl_nondir, /* same */
9803+#endif
4a4d8108
AM
9804+ .mmap = aufs_mmap,
9805+ .open = aufs_open_nondir,
9806+ .flush = aufs_flush_nondir,
9807+ .release = aufs_release_nondir,
9808+ .fsync = aufs_fsync_nondir,
9809+ /* .aio_fsync = aufs_aio_fsync_nondir, */
9810+ .fasync = aufs_fasync,
9811+ /* .sendpage = aufs_sendpage, */
9812+ .splice_write = aufs_splice_write,
9813+ .splice_read = aufs_splice_read,
9814+#if 0
9815+ .aio_splice_write = aufs_aio_splice_write,
9816+ .aio_splice_read = aufs_aio_splice_read
9817+#endif
9818+};
b752ccd1
AM
9819diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
9820--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
9821+++ linux/fs/aufs/f_op_sp.c 2010-10-21 09:52:43.090291764 +0200
9822@@ -0,0 +1,301 @@
1308ab2a 9823+/*
4a4d8108 9824+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 9825+ *
9826+ * This program, aufs is free software; you can redistribute it and/or modify
9827+ * it under the terms of the GNU General Public License as published by
9828+ * the Free Software Foundation; either version 2 of the License, or
9829+ * (at your option) any later version.
9830+ *
9831+ * This program is distributed in the hope that it will be useful,
9832+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9833+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9834+ * GNU General Public License for more details.
9835+ *
9836+ * You should have received a copy of the GNU General Public License
9837+ * along with this program; if not, write to the Free Software
9838+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9839+ */
dece6358 9840+
1308ab2a 9841+/*
4a4d8108
AM
9842+ * file operations for special files.
9843+ * while they exist in aufs virtually,
9844+ * their file I/O is handled out of aufs.
1308ab2a 9845+ */
9846+
4a4d8108
AM
9847+#include <linux/fs_stack.h>
9848+#include "aufs.h"
1308ab2a 9849+
4a4d8108
AM
9850+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
9851+ unsigned long nv, loff_t pos)
dece6358 9852+{
4a4d8108
AM
9853+ ssize_t err;
9854+ aufs_bindex_t bstart;
9855+ unsigned char wbr;
9856+ struct file *file, *h_file;
9857+ struct super_block *sb;
1308ab2a 9858+
4a4d8108
AM
9859+ file = kio->ki_filp;
9860+ sb = file->f_dentry->d_sb;
9861+ si_read_lock(sb, AuLock_FLUSH);
9862+ fi_read_lock(file);
9863+ bstart = au_fbstart(file);
9864+ h_file = au_hf_top(file);
9865+ fi_read_unlock(file);
9866+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9867+ si_read_unlock(sb);
9868+
9869+ /* do not change the file in kio */
9870+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
9871+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
9872+ if (err > 0 && wbr)
9873+ file_accessed(h_file);
9874+
9875+ return err;
9876+}
9877+
9878+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
9879+ unsigned long nv, loff_t pos)
9880+{
9881+ ssize_t err;
9882+ aufs_bindex_t bstart;
9883+ unsigned char wbr;
9884+ struct super_block *sb;
9885+ struct file *file, *h_file;
9886+
9887+ file = kio->ki_filp;
9888+ sb = file->f_dentry->d_sb;
9889+ si_read_lock(sb, AuLock_FLUSH);
9890+ fi_read_lock(file);
9891+ bstart = au_fbstart(file);
9892+ h_file = au_hf_top(file);
9893+ fi_read_unlock(file);
9894+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9895+ si_read_unlock(sb);
9896+
9897+ /* do not change the file in kio */
9898+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
9899+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
9900+ if (err > 0 && wbr)
9901+ file_update_time(h_file);
9902+
9903+ return err;
9904+}
9905+
9906+/* ---------------------------------------------------------------------- */
9907+
9908+static int aufs_release_sp(struct inode *inode, struct file *file)
9909+{
9910+ int err;
9911+ struct file *h_file;
9912+
9913+ fi_read_lock(file);
9914+ h_file = au_hf_top(file);
9915+ fi_read_unlock(file);
9916+ /* close this fifo in aufs */
9917+ err = h_file->f_op->release(inode, file); /* ignore */
9918+ aufs_release_nondir(inode, file); /* ignore */
9919+ return err;
9920+}
9921+
9922+/* ---------------------------------------------------------------------- */
9923+
9924+/* currently, support only FIFO */
4f0767ce
JR
9925+enum {
9926+ AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
9927+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
9928+ AuSp_Last
9929+};
4a4d8108
AM
9930+static int aufs_open_sp(struct inode *inode, struct file *file);
9931+static struct au_sp_fop {
9932+ int done;
9933+ struct file_operations fop; /* not 'const' */
9934+ spinlock_t spin;
9935+} au_sp_fop[AuSp_Last] = {
9936+ [AuSp_FIFO] = {
9937+ .fop = {
9938+ .owner = THIS_MODULE,
9939+ .open = aufs_open_sp
9940+ }
9941+ }
9942+};
9943+
9944+static void au_init_fop_sp(struct file *file)
9945+{
9946+ struct au_sp_fop *p;
9947+ int i;
9948+ struct file *h_file;
9949+
9950+ p = au_sp_fop;
9951+ if (unlikely(!p->done)) {
9952+ /* initialize first time only */
9953+ static DEFINE_SPINLOCK(spin);
9954+
9955+ spin_lock(&spin);
9956+ if (!p->done) {
9957+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
9958+ != AuSp_Last);
9959+ for (i = 0; i < AuSp_Last; i++)
9960+ spin_lock_init(&p[i].spin);
9961+ p->done = 1;
9962+ }
9963+ spin_unlock(&spin);
9964+ }
9965+
9966+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
9967+ case FMODE_READ:
9968+ i = AuSp_FIFO_R;
9969+ break;
9970+ case FMODE_WRITE:
9971+ i = AuSp_FIFO_W;
9972+ break;
9973+ case FMODE_READ | FMODE_WRITE:
9974+ i = AuSp_FIFO_RW;
9975+ break;
9976+ default:
9977+ BUG();
9978+ }
9979+
9980+ p += i;
9981+ if (unlikely(!p->done)) {
9982+ /* initialize first time only */
9983+ h_file = au_hf_top(file);
9984+ spin_lock(&p->spin);
9985+ if (!p->done) {
9986+ p->fop = *h_file->f_op;
9987+ p->fop.owner = THIS_MODULE;
9988+ if (p->fop.aio_read)
9989+ p->fop.aio_read = aufs_aio_read_sp;
9990+ if (p->fop.aio_write)
9991+ p->fop.aio_write = aufs_aio_write_sp;
9992+ p->fop.release = aufs_release_sp;
9993+ p->done = 1;
9994+ }
9995+ spin_unlock(&p->spin);
9996+ }
9997+ file->f_op = &p->fop;
9998+}
9999+
10000+static int au_cpup_sp(struct dentry *dentry)
10001+{
10002+ int err;
10003+ aufs_bindex_t bcpup;
10004+ struct au_pin pin;
10005+ struct au_wr_dir_args wr_dir_args = {
10006+ .force_btgt = -1,
10007+ .flags = 0
10008+ };
10009+
10010+ AuDbg("%.*s\n", AuDLNPair(dentry));
10011+
10012+ di_read_unlock(dentry, AuLock_IR);
10013+ di_write_lock_child(dentry);
10014+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
10015+ if (unlikely(err < 0))
10016+ goto out;
10017+ bcpup = err;
10018+ err = 0;
10019+ if (bcpup == au_dbstart(dentry))
10020+ goto out; /* success */
10021+
10022+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
10023+ AuPin_MNT_WRITE);
10024+ if (!err) {
10025+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
10026+ au_unpin(&pin);
10027+ }
10028+
4f0767ce 10029+out:
4a4d8108
AM
10030+ di_downgrade_lock(dentry, AuLock_IR);
10031+ return err;
10032+}
10033+
10034+static int au_do_open_sp(struct file *file, int flags)
10035+{
10036+ int err;
10037+ struct dentry *dentry;
10038+ struct super_block *sb;
10039+ struct file *h_file;
10040+ struct inode *h_inode;
10041+
10042+ dentry = file->f_dentry;
10043+ AuDbg("%.*s\n", AuDLNPair(dentry));
10044+
10045+ /*
10046+ * try copying-up.
10047+ * operate on the ro branch is not an error.
10048+ */
10049+ au_cpup_sp(dentry); /* ignore */
10050+
10051+ /* prepare h_file */
10052+ err = au_do_open_nondir(file, vfsub_file_flags(file));
10053+ if (unlikely(err))
10054+ goto out;
10055+
10056+ sb = dentry->d_sb;
10057+ h_file = au_hf_top(file);
10058+ h_inode = h_file->f_dentry->d_inode;
10059+ di_read_unlock(dentry, AuLock_IR);
10060+ fi_write_unlock(file);
10061+ si_read_unlock(sb);
10062+ /* open this fifo in aufs */
10063+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
10064+ si_noflush_read_lock(sb);
10065+ fi_write_lock(file);
10066+ di_read_lock_child(dentry, AuLock_IR);
10067+ if (!err)
10068+ au_init_fop_sp(file);
953406b4
AM
10069+ else
10070+ au_finfo_fin(file);
4a4d8108 10071+
4f0767ce 10072+out:
4a4d8108
AM
10073+ return err;
10074+}
10075+
10076+static int aufs_open_sp(struct inode *inode, struct file *file)
10077+{
10078+ int err;
10079+ struct super_block *sb;
10080+
10081+ sb = file->f_dentry->d_sb;
10082+ si_read_lock(sb, AuLock_FLUSH);
10083+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
10084+ si_read_unlock(sb);
10085+ return err;
10086+}
10087+
10088+/* ---------------------------------------------------------------------- */
10089+
10090+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
10091+{
10092+ init_special_inode(inode, mode, rdev);
10093+
10094+ switch (mode & S_IFMT) {
10095+ case S_IFIFO:
10096+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
10097+ /*FALLTHROUGH*/
10098+ case S_IFCHR:
10099+ case S_IFBLK:
10100+ case S_IFSOCK:
10101+ break;
10102+ default:
10103+ AuDebugOn(1);
10104+ }
10105+}
10106+
10107+int au_special_file(umode_t mode)
10108+{
10109+ int ret;
10110+
10111+ ret = 0;
10112+ switch (mode & S_IFMT) {
10113+ case S_IFIFO:
10114+#if 0
10115+ case S_IFCHR:
10116+ case S_IFBLK:
10117+ case S_IFSOCK:
10118+#endif
10119+ ret = 1;
10120+ }
10121+
10122+ return ret;
10123+}
b752ccd1
AM
10124diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
10125--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
953406b4 10126+++ linux/fs/aufs/fstype.h 2010-10-21 09:52:43.090291764 +0200
4a4d8108
AM
10127@@ -0,0 +1,497 @@
10128+/*
10129+ * Copyright (C) 2005-2010 Junjiro R. Okajima
10130+ *
10131+ * This program, aufs is free software; you can redistribute it and/or modify
10132+ * it under the terms of the GNU General Public License as published by
10133+ * the Free Software Foundation; either version 2 of the License, or
10134+ * (at your option) any later version.
10135+ *
10136+ * This program is distributed in the hope that it will be useful,
10137+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10138+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10139+ * GNU General Public License for more details.
10140+ *
10141+ * You should have received a copy of the GNU General Public License
10142+ * along with this program; if not, write to the Free Software
10143+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10144+ */
10145+
10146+/*
10147+ * judging filesystem type
10148+ */
10149+
10150+#ifndef __AUFS_FSTYPE_H__
10151+#define __AUFS_FSTYPE_H__
10152+
10153+#ifdef __KERNEL__
10154+
10155+#include <linux/fs.h>
10156+#include <linux/magic.h>
10157+#include <linux/romfs_fs.h>
10158+#include <linux/aufs_type.h>
10159+
10160+static inline int au_test_aufs(struct super_block *sb)
10161+{
10162+ return sb->s_magic == AUFS_SUPER_MAGIC;
10163+}
10164+
10165+static inline const char *au_sbtype(struct super_block *sb)
10166+{
10167+ return sb->s_type->name;
10168+}
1308ab2a 10169+
10170+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
10171+{
10172+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
10173+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
10174+#else
10175+ return 0;
10176+#endif
10177+}
10178+
1308ab2a 10179+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 10180+{
1308ab2a 10181+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
10182+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
10183+#else
10184+ return 0;
10185+#endif
10186+}
10187+
1308ab2a 10188+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 10189+{
1308ab2a 10190+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
10191+ return sb->s_magic == CRAMFS_MAGIC;
10192+#endif
10193+ return 0;
10194+}
10195+
10196+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
10197+{
10198+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
10199+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
10200+#else
10201+ return 0;
10202+#endif
10203+}
10204+
1308ab2a 10205+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 10206+{
1308ab2a 10207+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
10208+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
10209+#else
10210+ return 0;
10211+#endif
10212+}
10213+
1308ab2a 10214+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 10215+{
1308ab2a 10216+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
10217+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
10218+#else
10219+ return 0;
10220+#endif
10221+}
10222+
1308ab2a 10223+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 10224+{
1308ab2a 10225+#ifdef CONFIG_TMPFS
10226+ return sb->s_magic == TMPFS_MAGIC;
10227+#else
10228+ return 0;
dece6358 10229+#endif
dece6358
AM
10230+}
10231+
1308ab2a 10232+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 10233+{
1308ab2a 10234+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
10235+ return !strcmp(au_sbtype(sb), "ecryptfs");
10236+#else
10237+ return 0;
10238+#endif
1facf9fc 10239+}
10240+
1308ab2a 10241+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 10242+{
1308ab2a 10243+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
10244+ return sb->s_magic == SMB_SUPER_MAGIC;
10245+#else
10246+ return 0;
1facf9fc 10247+#endif
1facf9fc 10248+}
10249+
1308ab2a 10250+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 10251+{
1308ab2a 10252+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
10253+ return sb->s_magic == OCFS2_SUPER_MAGIC;
10254+#else
10255+ return 0;
10256+#endif
1facf9fc 10257+}
10258+
1308ab2a 10259+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 10260+{
1308ab2a 10261+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
10262+ return sb->s_magic == DLMFS_MAGIC;
10263+#else
10264+ return 0;
10265+#endif
1facf9fc 10266+}
10267+
1308ab2a 10268+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 10269+{
1308ab2a 10270+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
10271+ return sb->s_magic == CODA_SUPER_MAGIC;
10272+#else
10273+ return 0;
10274+#endif
10275+}
10276+
10277+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
10278+{
10279+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
10280+ return sb->s_magic == V9FS_MAGIC;
10281+#else
10282+ return 0;
10283+#endif
10284+}
10285+
10286+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
10287+{
10288+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
10289+ return sb->s_magic == EXT4_SUPER_MAGIC;
10290+#else
10291+ return 0;
10292+#endif
10293+}
10294+
10295+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
10296+{
10297+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
10298+ return !strcmp(au_sbtype(sb), "sysv");
10299+#else
10300+ return 0;
10301+#endif
10302+}
10303+
10304+static inline int au_test_ramfs(struct super_block *sb)
10305+{
10306+ return sb->s_magic == RAMFS_MAGIC;
10307+}
10308+
10309+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
10310+{
10311+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
10312+ return sb->s_magic == UBIFS_SUPER_MAGIC;
10313+#else
10314+ return 0;
10315+#endif
10316+}
10317+
10318+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
10319+{
10320+#ifdef CONFIG_PROC_FS
10321+ return sb->s_magic == PROC_SUPER_MAGIC;
10322+#else
10323+ return 0;
10324+#endif
10325+}
10326+
10327+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
10328+{
10329+#ifdef CONFIG_SYSFS
10330+ return sb->s_magic == SYSFS_MAGIC;
10331+#else
10332+ return 0;
10333+#endif
10334+}
10335+
10336+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
10337+{
10338+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
10339+ return sb->s_magic == CONFIGFS_MAGIC;
10340+#else
10341+ return 0;
10342+#endif
10343+}
10344+
10345+static inline int au_test_minix(struct super_block *sb __maybe_unused)
10346+{
10347+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
10348+ return sb->s_magic == MINIX3_SUPER_MAGIC
10349+ || sb->s_magic == MINIX2_SUPER_MAGIC
10350+ || sb->s_magic == MINIX2_SUPER_MAGIC2
10351+ || sb->s_magic == MINIX_SUPER_MAGIC
10352+ || sb->s_magic == MINIX_SUPER_MAGIC2;
10353+#else
10354+ return 0;
10355+#endif
10356+}
10357+
10358+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
10359+{
10360+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
10361+ return sb->s_magic == CIFS_MAGIC_NUMBER;
10362+#else
10363+ return 0;
10364+#endif
10365+}
10366+
10367+static inline int au_test_fat(struct super_block *sb __maybe_unused)
10368+{
10369+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
10370+ return sb->s_magic == MSDOS_SUPER_MAGIC;
10371+#else
10372+ return 0;
10373+#endif
10374+}
10375+
10376+static inline int au_test_msdos(struct super_block *sb)
10377+{
10378+ return au_test_fat(sb);
10379+}
10380+
10381+static inline int au_test_vfat(struct super_block *sb)
10382+{
10383+ return au_test_fat(sb);
10384+}
10385+
10386+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
10387+{
10388+#ifdef CONFIG_SECURITYFS
10389+ return sb->s_magic == SECURITYFS_MAGIC;
10390+#else
10391+ return 0;
10392+#endif
10393+}
10394+
10395+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
10396+{
10397+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
10398+ return sb->s_magic == SQUASHFS_MAGIC;
10399+#else
10400+ return 0;
10401+#endif
10402+}
10403+
10404+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
10405+{
10406+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
10407+ return sb->s_magic == BTRFS_SUPER_MAGIC;
10408+#else
10409+ return 0;
10410+#endif
10411+}
10412+
10413+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
10414+{
10415+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
10416+ return sb->s_magic == XENFS_SUPER_MAGIC;
10417+#else
10418+ return 0;
10419+#endif
10420+}
10421+
10422+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
10423+{
10424+#ifdef CONFIG_DEBUG_FS
10425+ return sb->s_magic == DEBUGFS_MAGIC;
10426+#else
10427+ return 0;
10428+#endif
10429+}
10430+
10431+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
10432+{
10433+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
10434+ return sb->s_magic == NILFS_SUPER_MAGIC;
10435+#else
10436+ return 0;
10437+#endif
10438+}
10439+
4a4d8108
AM
10440+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
10441+{
10442+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
10443+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
10444+#else
10445+ return 0;
10446+#endif
10447+}
10448+
1308ab2a 10449+/* ---------------------------------------------------------------------- */
10450+/*
10451+ * they can't be an aufs branch.
10452+ */
10453+static inline int au_test_fs_unsuppoted(struct super_block *sb)
10454+{
10455+ return
10456+#ifndef CONFIG_AUFS_BR_RAMFS
10457+ au_test_ramfs(sb) ||
10458+#endif
10459+ au_test_procfs(sb)
10460+ || au_test_sysfs(sb)
10461+ || au_test_configfs(sb)
10462+ || au_test_debugfs(sb)
10463+ || au_test_securityfs(sb)
10464+ || au_test_xenfs(sb)
10465+ || au_test_ecryptfs(sb)
10466+ /* || !strcmp(au_sbtype(sb), "unionfs") */
10467+ || au_test_aufs(sb); /* will be supported in next version */
10468+}
10469+
10470+/*
10471+ * If the filesystem supports NFS-export, then it has to support NULL as
10472+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
10473+ * We can apply this principle when we handle a lower filesystem.
10474+ */
10475+static inline int au_test_fs_null_nd(struct super_block *sb)
10476+{
10477+ return !!sb->s_export_op;
10478+}
10479+
10480+static inline int au_test_fs_remote(struct super_block *sb)
10481+{
10482+ return !au_test_tmpfs(sb)
10483+#ifdef CONFIG_AUFS_BR_RAMFS
10484+ && !au_test_ramfs(sb)
10485+#endif
10486+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
10487+}
10488+
10489+/* ---------------------------------------------------------------------- */
10490+
10491+/*
10492+ * Note: these functions (below) are created after reading ->getattr() in all
10493+ * filesystems under linux/fs. it means we have to do so in every update...
10494+ */
10495+
10496+/*
10497+ * some filesystems require getattr to refresh the inode attributes before
10498+ * referencing.
10499+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
10500+ * and leave the work for d_revalidate()
10501+ */
10502+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
10503+{
10504+ return au_test_nfs(sb)
10505+ || au_test_fuse(sb)
10506+ /* || au_test_smbfs(sb) */ /* untested */
10507+ /* || au_test_ocfs2(sb) */ /* untested */
10508+ /* || au_test_btrfs(sb) */ /* untested */
10509+ /* || au_test_coda(sb) */ /* untested */
10510+ /* || au_test_v9fs(sb) */ /* untested */
10511+ ;
10512+}
10513+
10514+/*
10515+ * filesystems which don't maintain i_size or i_blocks.
10516+ */
10517+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
10518+{
10519+ return au_test_xfs(sb)
4a4d8108
AM
10520+ || au_test_btrfs(sb)
10521+ || au_test_ubifs(sb)
10522+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 10523+ /* || au_test_ext4(sb) */ /* untested */
10524+ /* || au_test_ocfs2(sb) */ /* untested */
10525+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
10526+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 10527+ /* || au_test_minix(sb) */ /* untested */
10528+ ;
10529+}
10530+
10531+/*
10532+ * filesystems which don't store the correct value in some of their inode
10533+ * attributes.
10534+ */
10535+static inline int au_test_fs_bad_iattr(struct super_block *sb)
10536+{
10537+ return au_test_fs_bad_iattr_size(sb)
10538+ /* || au_test_cifs(sb) */ /* untested */
10539+ || au_test_fat(sb)
10540+ || au_test_msdos(sb)
10541+ || au_test_vfat(sb);
1facf9fc 10542+}
10543+
10544+/* they don't check i_nlink in link(2) */
10545+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
10546+{
10547+ return au_test_tmpfs(sb)
10548+#ifdef CONFIG_AUFS_BR_RAMFS
10549+ || au_test_ramfs(sb)
10550+#endif
4a4d8108
AM
10551+ || au_test_ubifs(sb)
10552+ || au_test_btrfs(sb)
10553+ || au_test_hfsplus(sb);
1facf9fc 10554+}
10555+
10556+/*
10557+ * filesystems which sets S_NOATIME and S_NOCMTIME.
10558+ */
10559+static inline int au_test_fs_notime(struct super_block *sb)
10560+{
10561+ return au_test_nfs(sb)
10562+ || au_test_fuse(sb)
dece6358 10563+ || au_test_ubifs(sb)
1facf9fc 10564+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 10565+ ;
10566+}
10567+
10568+/*
10569+ * filesystems which requires replacing i_mapping.
10570+ */
10571+static inline int au_test_fs_bad_mapping(struct super_block *sb)
10572+{
dece6358
AM
10573+ return au_test_fuse(sb)
10574+ || au_test_ubifs(sb);
1facf9fc 10575+}
10576+
10577+/* temporary support for i#1 in cramfs */
10578+static inline int au_test_fs_unique_ino(struct inode *inode)
10579+{
10580+ if (au_test_cramfs(inode->i_sb))
10581+ return inode->i_ino != 1;
10582+ return 1;
10583+}
10584+
10585+/* ---------------------------------------------------------------------- */
10586+
10587+/*
10588+ * the filesystem where the xino files placed must support i/o after unlink and
10589+ * maintain i_size and i_blocks.
10590+ */
10591+static inline int au_test_fs_bad_xino(struct super_block *sb)
10592+{
10593+ return au_test_fs_remote(sb)
10594+ || au_test_fs_bad_iattr_size(sb)
10595+#ifdef CONFIG_AUFS_BR_RAMFS
10596+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
10597+#else
10598+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
10599+#endif
10600+ /* don't want unnecessary work for xino */
10601+ || au_test_aufs(sb)
1308ab2a 10602+ || au_test_ecryptfs(sb)
10603+ || au_test_nilfs(sb);
1facf9fc 10604+}
10605+
10606+static inline int au_test_fs_trunc_xino(struct super_block *sb)
10607+{
10608+ return au_test_tmpfs(sb)
10609+ || au_test_ramfs(sb);
10610+}
10611+
10612+/*
10613+ * test if the @sb is real-readonly.
10614+ */
10615+static inline int au_test_fs_rr(struct super_block *sb)
10616+{
10617+ return au_test_squashfs(sb)
10618+ || au_test_iso9660(sb)
10619+ || au_test_cramfs(sb)
10620+ || au_test_romfs(sb);
10621+}
10622+
10623+#endif /* __KERNEL__ */
10624+#endif /* __AUFS_FSTYPE_H__ */
b752ccd1
AM
10625diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
10626--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
10627+++ linux/fs/aufs/hfsnotify.c 2010-10-21 09:52:43.090291764 +0200
10628@@ -0,0 +1,216 @@
1facf9fc 10629+/*
4a4d8108 10630+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 10631+ *
10632+ * This program, aufs is free software; you can redistribute it and/or modify
10633+ * it under the terms of the GNU General Public License as published by
10634+ * the Free Software Foundation; either version 2 of the License, or
10635+ * (at your option) any later version.
dece6358
AM
10636+ *
10637+ * This program is distributed in the hope that it will be useful,
10638+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10639+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10640+ * GNU General Public License for more details.
10641+ *
10642+ * You should have received a copy of the GNU General Public License
10643+ * along with this program; if not, write to the Free Software
10644+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 10645+ */
10646+
10647+/*
4a4d8108 10648+ * fsnotify for the lower directories
1facf9fc 10649+ */
10650+
10651+#include "aufs.h"
10652+
4a4d8108
AM
10653+/* FS_IN_IGNORED is unnecessary */
10654+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
10655+ | FS_CREATE | FS_EVENT_ON_CHILD);
10656+static struct fsnotify_group *au_hfsn_group;
953406b4 10657+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
1facf9fc 10658+
953406b4 10659+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 10660+{
953406b4
AM
10661+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
10662+ hn_mark);
4a4d8108 10663+ AuDbg("here\n");
953406b4
AM
10664+ hn->hn_mark_dead = 1;
10665+ smp_mb();
10666+ wake_up_all(&au_hfsn_wq);
4a4d8108 10667+}
1facf9fc 10668+
4a4d8108
AM
10669+static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode)
10670+{
953406b4 10671+ struct fsnotify_mark *mark;
1facf9fc 10672+
953406b4
AM
10673+ hn->hn_mark_dead = 0;
10674+ mark = &hn->hn_mark;
10675+ fsnotify_init_mark(mark, au_hfsn_free_mark);
10676+ mark->mask = AuHfsnMask;
10677+ /*
10678+ * by udba rename or rmdir, aufs assign a new inode to the known
10679+ * h_inode, so specify 1 to allow dups.
10680+ */
10681+ return fsnotify_add_mark(mark, au_hfsn_group, h_inode, /*mnt*/NULL,
10682+ /*allow_dups*/1);
1facf9fc 10683+}
10684+
4a4d8108 10685+static void au_hfsn_free(struct au_hnotify *hn)
1facf9fc 10686+{
953406b4 10687+ struct fsnotify_mark *mark;
1facf9fc 10688+
953406b4
AM
10689+ mark = &hn->hn_mark;
10690+ fsnotify_destroy_mark(mark);
10691+ fsnotify_put_mark(mark);
10692+
10693+ /* TODO: bad approach */
10694+ wait_event(au_hfsn_wq, hn->hn_mark_dead);
1facf9fc 10695+}
10696+
10697+/* ---------------------------------------------------------------------- */
10698+
4a4d8108 10699+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 10700+{
953406b4 10701+ struct fsnotify_mark *mark;
1facf9fc 10702+
953406b4
AM
10703+ mark = &hinode->hi_notify->hn_mark;
10704+ spin_lock(&mark->lock);
1facf9fc 10705+ if (do_set) {
953406b4
AM
10706+ AuDebugOn(mark->mask & AuHfsnMask);
10707+ mark->mask |= AuHfsnMask;
1facf9fc 10708+ } else {
953406b4
AM
10709+ AuDebugOn(!(mark->mask & AuHfsnMask));
10710+ mark->mask &= ~AuHfsnMask;
1facf9fc 10711+ }
953406b4 10712+ spin_unlock(&mark->lock);
4a4d8108 10713+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 10714+}
10715+
4a4d8108 10716+/* ---------------------------------------------------------------------- */
1facf9fc 10717+
4a4d8108
AM
10718+/* #define AuDbgHnotify */
10719+#ifdef AuDbgHnotify
10720+static char *au_hfsn_name(u32 mask)
10721+{
10722+#ifdef CONFIG_AUFS_DEBUG
10723+#define test_ret(flag) if (mask & flag) \
10724+ return #flag;
10725+ test_ret(FS_ACCESS);
10726+ test_ret(FS_MODIFY);
10727+ test_ret(FS_ATTRIB);
10728+ test_ret(FS_CLOSE_WRITE);
10729+ test_ret(FS_CLOSE_NOWRITE);
10730+ test_ret(FS_OPEN);
10731+ test_ret(FS_MOVED_FROM);
10732+ test_ret(FS_MOVED_TO);
10733+ test_ret(FS_CREATE);
10734+ test_ret(FS_DELETE);
10735+ test_ret(FS_DELETE_SELF);
10736+ test_ret(FS_MOVE_SELF);
10737+ test_ret(FS_UNMOUNT);
10738+ test_ret(FS_Q_OVERFLOW);
10739+ test_ret(FS_IN_IGNORED);
10740+ test_ret(FS_IN_ISDIR);
10741+ test_ret(FS_IN_ONESHOT);
10742+ test_ret(FS_EVENT_ON_CHILD);
10743+ return "";
10744+#undef test_ret
10745+#else
10746+ return "??";
10747+#endif
1facf9fc 10748+}
4a4d8108 10749+#endif
1facf9fc 10750+
10751+/* ---------------------------------------------------------------------- */
10752+
4a4d8108 10753+static int au_hfsn_handle_event(struct fsnotify_group *group,
953406b4
AM
10754+ struct fsnotify_mark *inode_mark,
10755+ struct fsnotify_mark *vfsmount_mark,
4a4d8108 10756+ struct fsnotify_event *event)
1facf9fc 10757+{
10758+ int err;
4a4d8108
AM
10759+ struct au_hnotify *hnotify;
10760+ struct inode *h_dir, *h_inode;
10761+ __u32 mask;
4a4d8108
AM
10762+ struct qstr h_child_qstr = {
10763+ .name = event->file_name,
10764+ .len = event->name_len
10765+ };
10766+
10767+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 10768+
10769+ err = 0;
953406b4 10770+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108
AM
10771+ mask = event->mask;
10772+ AuDebugOn(mask & FS_UNMOUNT);
953406b4 10773+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 10774+ goto out;
1facf9fc 10775+
4a4d8108
AM
10776+ h_dir = event->to_tell;
10777+ h_inode = event->inode;
10778+#ifdef AuDbgHnotify
10779+ au_debug(1);
10780+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
10781+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
10782+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
10783+ h_dir->i_ino, mask, au_hfsn_name(mask),
10784+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
10785+ /* WARN_ON(1); */
1facf9fc 10786+ }
4a4d8108 10787+ au_debug(0);
1facf9fc 10788+#endif
4a4d8108 10789+
953406b4
AM
10790+ AuDebugOn(!inode_mark);
10791+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
10792+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
1facf9fc 10793+
4a4d8108
AM
10794+out:
10795+ return err;
10796+}
1facf9fc 10797+
4a4d8108
AM
10798+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
10799+/* it should be exported to modules */
10800+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
953406b4
AM
10801+ struct inode *h_inode,
10802+ struct fsnotify_mark *inode_mark,
10803+ struct fsnotify_mark *vfsmount_mark,
10804+ __u32 mask, void *data, int data_type)
4a4d8108 10805+{
4a4d8108 10806+ mask = (mask & ~FS_EVENT_ON_CHILD);
953406b4 10807+ return inode_mark->mask & mask;
4a4d8108
AM
10808+}
10809+
10810+static struct fsnotify_ops au_hfsn_ops = {
10811+ .should_send_event = au_hfsn_should_send_event,
10812+ .handle_event = au_hfsn_handle_event
10813+};
10814+
10815+/* ---------------------------------------------------------------------- */
10816+
10817+static int __init au_hfsn_init(void)
10818+{
10819+ int err;
1facf9fc 10820+
4a4d8108 10821+ err = 0;
953406b4 10822+ au_hfsn_group = fsnotify_alloc_group(&au_hfsn_ops);
4a4d8108 10823+ if (IS_ERR(au_hfsn_group)) {
4a4d8108 10824+ err = PTR_ERR(au_hfsn_group);
953406b4 10825+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
4a4d8108 10826+ }
1facf9fc 10827+
1facf9fc 10828+ AuTraceErr(err);
10829+ return err;
10830+}
10831+
4a4d8108 10832+static void au_hfsn_fin(void)
1facf9fc 10833+{
4a4d8108
AM
10834+ fsnotify_put_group(au_hfsn_group);
10835+}
1facf9fc 10836+
4a4d8108
AM
10837+const struct au_hnotify_op au_hnotify_op = {
10838+ .ctl = au_hfsn_ctl,
10839+ .alloc = au_hfsn_alloc,
10840+ .free = au_hfsn_free,
1facf9fc 10841+
4a4d8108
AM
10842+ .fin = au_hfsn_fin,
10843+ .init = au_hfsn_init
10844+};
b752ccd1
AM
10845diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
10846--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
953406b4 10847+++ linux/fs/aufs/hfsplus.c 2010-10-21 09:52:43.090291764 +0200
4a4d8108
AM
10848@@ -0,0 +1,58 @@
10849+/*
10850+ * Copyright (C) 2010 Junjiro R. Okajima
10851+ *
10852+ * This program, aufs is free software; you can redistribute it and/or modify
10853+ * it under the terms of the GNU General Public License as published by
10854+ * the Free Software Foundation; either version 2 of the License, or
10855+ * (at your option) any later version.
10856+ *
10857+ * This program is distributed in the hope that it will be useful,
10858+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10859+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10860+ * GNU General Public License for more details.
10861+ *
10862+ * You should have received a copy of the GNU General Public License
10863+ * along with this program; if not, write to the Free Software
10864+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10865+ */
1facf9fc 10866+
4a4d8108
AM
10867+/*
10868+ * special support for filesystems which aqucires an inode mutex
10869+ * at final closing a file, eg, hfsplus.
10870+ *
10871+ * This trick is very simple and stupid, just to open the file before really
10872+ * neceeary open to tell hfsplus that this is not the final closing.
10873+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
10874+ * and au_h_open_post() after releasing it.
10875+ */
1facf9fc 10876+
4a4d8108
AM
10877+#include <linux/file.h>
10878+#include "aufs.h"
1facf9fc 10879+
4a4d8108
AM
10880+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
10881+{
10882+ struct file *h_file;
10883+ struct dentry *h_dentry;
1facf9fc 10884+
4a4d8108
AM
10885+ h_dentry = au_h_dptr(dentry, bindex);
10886+ AuDebugOn(!h_dentry);
10887+ AuDebugOn(!h_dentry->d_inode);
10888+ IMustLock(h_dentry->d_inode);
10889+
10890+ h_file = NULL;
10891+ if (au_test_hfsplus(h_dentry->d_sb)
10892+ && S_ISREG(h_dentry->d_inode->i_mode))
10893+ h_file = au_h_open(dentry, bindex,
10894+ O_RDONLY | O_NOATIME | O_LARGEFILE,
10895+ /*file*/NULL);
10896+ return h_file;
1facf9fc 10897+}
10898+
4a4d8108
AM
10899+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
10900+ struct file *h_file)
10901+{
10902+ if (h_file) {
10903+ fput(h_file);
10904+ au_sbr_put(dentry->d_sb, bindex);
10905+ }
10906+}
b752ccd1
AM
10907diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
10908--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
10909+++ linux/fs/aufs/hnotify.c 2010-10-21 09:52:43.090291764 +0200
10910@@ -0,0 +1,663 @@
1facf9fc 10911+/*
4a4d8108 10912+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 10913+ *
10914+ * This program, aufs is free software; you can redistribute it and/or modify
10915+ * it under the terms of the GNU General Public License as published by
10916+ * the Free Software Foundation; either version 2 of the License, or
10917+ * (at your option) any later version.
dece6358
AM
10918+ *
10919+ * This program is distributed in the hope that it will be useful,
10920+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10921+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10922+ * GNU General Public License for more details.
10923+ *
10924+ * You should have received a copy of the GNU General Public License
10925+ * along with this program; if not, write to the Free Software
10926+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 10927+ */
10928+
10929+/*
4a4d8108 10930+ * abstraction to notify the direct changes on lower directories
1facf9fc 10931+ */
10932+
1308ab2a 10933+#include "aufs.h"
1facf9fc 10934+
4a4d8108
AM
10935+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
10936+ struct inode *h_inode)
dece6358 10937+{
1308ab2a 10938+ int err;
4a4d8108 10939+ struct au_hnotify *hn;
1facf9fc 10940+
4a4d8108
AM
10941+ err = -ENOMEM;
10942+ hn = au_cache_alloc_hnotify();
10943+ if (hn) {
10944+ hn->hn_aufs_inode = inode;
10945+ err = au_hnotify_op.alloc(hn, h_inode);
10946+ if (!err)
10947+ hinode->hi_notify = hn;
10948+ else {
10949+ au_cache_free_hnotify(hn);
10950+ /*
10951+ * The upper dir was removed by udba, but the same named
10952+ * dir left. In this case, aufs assignes a new inode
10953+ * number and set the monitor again.
10954+ * For the lower dir, the old monitnor is still left.
10955+ */
10956+ if (err == -EEXIST)
10957+ err = 0;
10958+ }
1308ab2a 10959+ }
1308ab2a 10960+
1308ab2a 10961+ return err;
dece6358 10962+}
1facf9fc 10963+
4a4d8108 10964+void au_hn_free(struct au_hinode *hinode)
dece6358 10965+{
4a4d8108 10966+ struct au_hnotify *hn;
1facf9fc 10967+
4a4d8108
AM
10968+ hn = hinode->hi_notify;
10969+ if (hn) {
10970+ au_hnotify_op.free(hn);
10971+ au_cache_free_hnotify(hn);
10972+ hinode->hi_notify = NULL;
10973+ }
10974+}
dece6358 10975+
4a4d8108 10976+/* ---------------------------------------------------------------------- */
dece6358 10977+
4a4d8108
AM
10978+void au_hn_ctl(struct au_hinode *hinode, int do_set)
10979+{
10980+ if (hinode->hi_notify)
10981+ au_hnotify_op.ctl(hinode, do_set);
10982+}
10983+
10984+void au_hn_reset(struct inode *inode, unsigned int flags)
10985+{
10986+ aufs_bindex_t bindex, bend;
10987+ struct inode *hi;
10988+ struct dentry *iwhdentry;
1facf9fc 10989+
1308ab2a 10990+ bend = au_ibend(inode);
4a4d8108
AM
10991+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
10992+ hi = au_h_iptr(inode, bindex);
10993+ if (!hi)
10994+ continue;
1308ab2a 10995+
4a4d8108
AM
10996+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
10997+ iwhdentry = au_hi_wh(inode, bindex);
10998+ if (iwhdentry)
10999+ dget(iwhdentry);
11000+ au_igrab(hi);
11001+ au_set_h_iptr(inode, bindex, NULL, 0);
11002+ au_set_h_iptr(inode, bindex, au_igrab(hi),
11003+ flags & ~AuHi_XINO);
11004+ iput(hi);
11005+ dput(iwhdentry);
11006+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 11007+ }
1facf9fc 11008+}
11009+
1308ab2a 11010+/* ---------------------------------------------------------------------- */
1facf9fc 11011+
4a4d8108 11012+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 11013+{
4a4d8108
AM
11014+ int err;
11015+ aufs_bindex_t bindex, bend, bfound, bstart;
11016+ struct inode *h_i;
1facf9fc 11017+
4a4d8108
AM
11018+ err = 0;
11019+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11020+ pr_warning("branch root dir was changed\n");
11021+ goto out;
11022+ }
1facf9fc 11023+
4a4d8108
AM
11024+ bfound = -1;
11025+ bend = au_ibend(inode);
11026+ bstart = au_ibstart(inode);
11027+#if 0 /* reserved for future use */
11028+ if (bindex == bend) {
11029+ /* keep this ino in rename case */
11030+ goto out;
11031+ }
11032+#endif
11033+ for (bindex = bstart; bindex <= bend; bindex++)
11034+ if (au_h_iptr(inode, bindex) == h_inode) {
11035+ bfound = bindex;
11036+ break;
11037+ }
11038+ if (bfound < 0)
1308ab2a 11039+ goto out;
1facf9fc 11040+
4a4d8108
AM
11041+ for (bindex = bstart; bindex <= bend; bindex++) {
11042+ h_i = au_h_iptr(inode, bindex);
11043+ if (!h_i)
11044+ continue;
1facf9fc 11045+
4a4d8108
AM
11046+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
11047+ /* ignore this error */
11048+ /* bad action? */
1facf9fc 11049+ }
1facf9fc 11050+
4a4d8108 11051+ /* children inode number will be broken */
1facf9fc 11052+
4f0767ce 11053+out:
4a4d8108
AM
11054+ AuTraceErr(err);
11055+ return err;
1facf9fc 11056+}
11057+
4a4d8108 11058+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 11059+{
4a4d8108
AM
11060+ int err, i, j, ndentry;
11061+ struct au_dcsub_pages dpages;
11062+ struct au_dpage *dpage;
11063+ struct dentry **dentries;
1facf9fc 11064+
4a4d8108
AM
11065+ err = au_dpages_init(&dpages, GFP_NOFS);
11066+ if (unlikely(err))
11067+ goto out;
11068+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
11069+ if (unlikely(err))
11070+ goto out_dpages;
1facf9fc 11071+
4a4d8108
AM
11072+ for (i = 0; i < dpages.ndpage; i++) {
11073+ dpage = dpages.dpages + i;
11074+ dentries = dpage->dentries;
11075+ ndentry = dpage->ndentry;
11076+ for (j = 0; j < ndentry; j++) {
11077+ struct dentry *d;
11078+
11079+ d = dentries[j];
11080+ if (IS_ROOT(d))
11081+ continue;
11082+
11083+ d_drop(d);
11084+ au_digen_dec(d);
11085+ if (d->d_inode)
11086+ /* todo: reset children xino?
11087+ cached children only? */
11088+ au_iigen_dec(d->d_inode);
1308ab2a 11089+ }
dece6358 11090+ }
1facf9fc 11091+
4f0767ce 11092+out_dpages:
4a4d8108 11093+ au_dpages_free(&dpages);
dece6358 11094+
4a4d8108
AM
11095+ /* discard children */
11096+ dentry_unhash(dentry);
11097+ dput(dentry);
4f0767ce 11098+out:
dece6358
AM
11099+ return err;
11100+}
11101+
1308ab2a 11102+/*
4a4d8108 11103+ * return 0 if processed.
1308ab2a 11104+ */
4a4d8108
AM
11105+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
11106+ const unsigned int isdir)
dece6358 11107+{
1308ab2a 11108+ int err;
4a4d8108
AM
11109+ struct dentry *d;
11110+ struct qstr *dname;
1facf9fc 11111+
4a4d8108
AM
11112+ err = 1;
11113+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11114+ pr_warning("branch root dir was changed\n");
11115+ err = 0;
11116+ goto out;
11117+ }
dece6358 11118+
4a4d8108
AM
11119+ if (!isdir) {
11120+ AuDebugOn(!name);
11121+ au_iigen_dec(inode);
11122+ spin_lock(&dcache_lock);
11123+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
11124+ dname = &d->d_name;
11125+ if (dname->len != nlen
11126+ && memcmp(dname->name, name, nlen))
11127+ continue;
11128+ err = 0;
11129+ spin_lock(&d->d_lock);
11130+ __d_drop(d);
11131+ au_digen_dec(d);
11132+ spin_unlock(&d->d_lock);
11133+ break;
1facf9fc 11134+ }
4a4d8108 11135+ spin_unlock(&dcache_lock);
1308ab2a 11136+ } else {
4a4d8108
AM
11137+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
11138+ d = d_find_alias(inode);
11139+ if (!d) {
11140+ au_iigen_dec(inode);
11141+ goto out;
11142+ }
1facf9fc 11143+
4a4d8108
AM
11144+ dname = &d->d_name;
11145+ if (dname->len == nlen && !memcmp(dname->name, name, nlen))
11146+ err = hn_gen_tree(d);
11147+ dput(d);
11148+ }
1facf9fc 11149+
4f0767ce 11150+out:
4a4d8108 11151+ AuTraceErr(err);
1308ab2a 11152+ return err;
11153+}
dece6358 11154+
4a4d8108 11155+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 11156+{
4a4d8108
AM
11157+ int err;
11158+ struct inode *inode;
1facf9fc 11159+
4a4d8108
AM
11160+ inode = dentry->d_inode;
11161+ if (IS_ROOT(dentry)
11162+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
11163+ ) {
11164+ pr_warning("branch root dir was changed\n");
11165+ return 0;
11166+ }
1308ab2a 11167+
4a4d8108
AM
11168+ err = 0;
11169+ if (!isdir) {
11170+ d_drop(dentry);
11171+ au_digen_dec(dentry);
11172+ if (inode)
11173+ au_iigen_dec(inode);
11174+ } else {
11175+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
11176+ if (inode)
11177+ err = hn_gen_tree(dentry);
11178+ }
11179+
11180+ AuTraceErr(err);
11181+ return err;
1facf9fc 11182+}
11183+
4a4d8108 11184+/* ---------------------------------------------------------------------- */
1facf9fc 11185+
4a4d8108
AM
11186+/* hnotify job flags */
11187+#define AuHnJob_XINO0 1
11188+#define AuHnJob_GEN (1 << 1)
11189+#define AuHnJob_DIRENT (1 << 2)
11190+#define AuHnJob_ISDIR (1 << 3)
11191+#define AuHnJob_TRYXINO0 (1 << 4)
11192+#define AuHnJob_MNTPNT (1 << 5)
11193+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
11194+#define au_fset_hnjob(flags, name) { (flags) |= AuHnJob_##name; }
11195+#define au_fclr_hnjob(flags, name) { (flags) &= ~AuHnJob_##name; }
1facf9fc 11196+
4a4d8108
AM
11197+enum {
11198+ AuHn_CHILD,
11199+ AuHn_PARENT,
11200+ AuHnLast
11201+};
1facf9fc 11202+
4a4d8108
AM
11203+struct au_hnotify_args {
11204+ struct inode *h_dir, *dir, *h_child_inode;
11205+ u32 mask;
11206+ unsigned int flags[AuHnLast];
11207+ unsigned int h_child_nlen;
11208+ char h_child_name[];
11209+};
1facf9fc 11210+
4a4d8108
AM
11211+struct hn_job_args {
11212+ unsigned int flags;
11213+ struct inode *inode, *h_inode, *dir, *h_dir;
11214+ struct dentry *dentry;
11215+ char *h_name;
11216+ int h_nlen;
11217+};
1308ab2a 11218+
4a4d8108
AM
11219+static int hn_job(struct hn_job_args *a)
11220+{
11221+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 11222+
4a4d8108
AM
11223+ /* reset xino */
11224+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
11225+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 11226+
4a4d8108
AM
11227+ if (au_ftest_hnjob(a->flags, TRYXINO0)
11228+ && a->inode
11229+ && a->h_inode) {
11230+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11231+ if (!a->h_inode->i_nlink)
11232+ hn_xino(a->inode, a->h_inode); /* ignore this error */
11233+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 11234+ }
1facf9fc 11235+
4a4d8108
AM
11236+ /* make the generation obsolete */
11237+ if (au_ftest_hnjob(a->flags, GEN)) {
11238+ int err = -1;
11239+ if (a->inode)
11240+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
11241+ isdir);
11242+ if (err && a->dentry)
11243+ hn_gen_by_name(a->dentry, isdir);
11244+ /* ignore this error */
1facf9fc 11245+ }
1facf9fc 11246+
4a4d8108
AM
11247+ /* make dir entries obsolete */
11248+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
11249+ struct au_vdir *vdir;
1facf9fc 11250+
4a4d8108
AM
11251+ vdir = au_ivdir(a->inode);
11252+ if (vdir)
11253+ vdir->vd_jiffy = 0;
11254+ /* IMustLock(a->inode); */
11255+ /* a->inode->i_version++; */
11256+ }
1facf9fc 11257+
4a4d8108
AM
11258+ /* can do nothing but warn */
11259+ if (au_ftest_hnjob(a->flags, MNTPNT)
11260+ && a->dentry
11261+ && d_mountpoint(a->dentry))
11262+ pr_warning("mount-point %.*s is removed or renamed\n",
11263+ AuDLNPair(a->dentry));
1facf9fc 11264+
4a4d8108 11265+ return 0;
1308ab2a 11266+}
1facf9fc 11267+
1308ab2a 11268+/* ---------------------------------------------------------------------- */
1facf9fc 11269+
4a4d8108
AM
11270+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
11271+ struct inode *dir)
1308ab2a 11272+{
4a4d8108
AM
11273+ struct dentry *dentry, *d, *parent;
11274+ struct qstr *dname;
1308ab2a 11275+
4a4d8108
AM
11276+ parent = d_find_alias(dir);
11277+ if (!parent)
11278+ return NULL;
1308ab2a 11279+
4a4d8108
AM
11280+ dentry = NULL;
11281+ spin_lock(&dcache_lock);
11282+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
11283+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
11284+ dname = &d->d_name;
11285+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
11286+ continue;
11287+ if (!atomic_read(&d->d_count) || !d->d_fsdata) {
11288+ spin_lock(&d->d_lock);
11289+ __d_drop(d);
11290+ spin_unlock(&d->d_lock);
11291+ continue;
dece6358 11292+ }
1facf9fc 11293+
4a4d8108
AM
11294+ dentry = dget(d);
11295+ break;
1308ab2a 11296+ }
4a4d8108
AM
11297+ spin_unlock(&dcache_lock);
11298+ dput(parent);
1facf9fc 11299+
4a4d8108
AM
11300+ if (dentry)
11301+ di_write_lock_child(dentry);
1308ab2a 11302+
4a4d8108
AM
11303+ return dentry;
11304+}
dece6358 11305+
4a4d8108
AM
11306+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
11307+ aufs_bindex_t bindex, ino_t h_ino)
11308+{
11309+ struct inode *inode;
11310+ ino_t ino;
11311+ int err;
11312+
11313+ inode = NULL;
11314+ err = au_xino_read(sb, bindex, h_ino, &ino);
11315+ if (!err && ino)
11316+ inode = ilookup(sb, ino);
11317+ if (!inode)
11318+ goto out;
11319+
11320+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11321+ pr_warning("wrong root branch\n");
11322+ iput(inode);
11323+ inode = NULL;
11324+ goto out;
1308ab2a 11325+ }
11326+
4a4d8108 11327+ ii_write_lock_child(inode);
1308ab2a 11328+
4f0767ce 11329+out:
4a4d8108 11330+ return inode;
dece6358
AM
11331+}
11332+
4a4d8108 11333+static void au_hn_bh(void *_args)
1facf9fc 11334+{
4a4d8108
AM
11335+ struct au_hnotify_args *a = _args;
11336+ struct super_block *sb;
11337+ aufs_bindex_t bindex, bend, bfound;
11338+ unsigned char xino, try_iput;
1facf9fc 11339+ int err;
1308ab2a 11340+ struct inode *inode;
4a4d8108
AM
11341+ ino_t h_ino;
11342+ struct hn_job_args args;
11343+ struct dentry *dentry;
11344+ struct au_sbinfo *sbinfo;
1facf9fc 11345+
4a4d8108
AM
11346+ AuDebugOn(!_args);
11347+ AuDebugOn(!a->h_dir);
11348+ AuDebugOn(!a->dir);
11349+ AuDebugOn(!a->mask);
11350+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
11351+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
11352+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 11353+
4a4d8108
AM
11354+ inode = NULL;
11355+ dentry = NULL;
11356+ /*
11357+ * do not lock a->dir->i_mutex here
11358+ * because of d_revalidate() may cause a deadlock.
11359+ */
11360+ sb = a->dir->i_sb;
11361+ AuDebugOn(!sb);
11362+ sbinfo = au_sbi(sb);
11363+ AuDebugOn(!sbinfo);
953406b4
AM
11364+ /* big aufs lock */
11365+ si_noflush_write_lock(sb);
1facf9fc 11366+
4a4d8108
AM
11367+ ii_read_lock_parent(a->dir);
11368+ bfound = -1;
11369+ bend = au_ibend(a->dir);
11370+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
11371+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
11372+ bfound = bindex;
11373+ break;
11374+ }
11375+ ii_read_unlock(a->dir);
11376+ if (unlikely(bfound < 0))
11377+ goto out;
1facf9fc 11378+
4a4d8108
AM
11379+ xino = !!au_opt_test(au_mntflags(sb), XINO);
11380+ h_ino = 0;
11381+ if (a->h_child_inode)
11382+ h_ino = a->h_child_inode->i_ino;
1facf9fc 11383+
4a4d8108
AM
11384+ if (a->h_child_nlen
11385+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
11386+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
11387+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
11388+ a->dir);
11389+ try_iput = 0;
11390+ if (dentry)
11391+ inode = dentry->d_inode;
11392+ if (xino && !inode && h_ino
11393+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
11394+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
11395+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
11396+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
11397+ try_iput = 1;
11398+ }
1facf9fc 11399+
4a4d8108
AM
11400+ args.flags = a->flags[AuHn_CHILD];
11401+ args.dentry = dentry;
11402+ args.inode = inode;
11403+ args.h_inode = a->h_child_inode;
11404+ args.dir = a->dir;
11405+ args.h_dir = a->h_dir;
11406+ args.h_name = a->h_child_name;
11407+ args.h_nlen = a->h_child_nlen;
11408+ err = hn_job(&args);
11409+ if (dentry) {
11410+ if (dentry->d_fsdata)
11411+ di_write_unlock(dentry);
11412+ dput(dentry);
11413+ }
11414+ if (inode && try_iput) {
11415+ ii_write_unlock(inode);
11416+ iput(inode);
11417+ }
1facf9fc 11418+
4a4d8108
AM
11419+ ii_write_lock_parent(a->dir);
11420+ args.flags = a->flags[AuHn_PARENT];
11421+ args.dentry = NULL;
11422+ args.inode = a->dir;
11423+ args.h_inode = a->h_dir;
11424+ args.dir = NULL;
11425+ args.h_dir = NULL;
11426+ args.h_name = NULL;
11427+ args.h_nlen = 0;
11428+ err = hn_job(&args);
11429+ ii_write_unlock(a->dir);
1facf9fc 11430+
4f0767ce 11431+out:
4a4d8108
AM
11432+ au_nwt_done(&sbinfo->si_nowait);
11433+ si_write_unlock(sb);
1308ab2a 11434+
4a4d8108
AM
11435+ iput(a->h_child_inode);
11436+ iput(a->h_dir);
11437+ iput(a->dir);
1308ab2a 11438+ kfree(a);
dece6358 11439+}
1facf9fc 11440+
4a4d8108
AM
11441+/* ---------------------------------------------------------------------- */
11442+
11443+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
11444+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 11445+{
4a4d8108
AM
11446+ int err, len;
11447+ unsigned int flags[AuHnLast];
11448+ unsigned char isdir, isroot, wh;
11449+ struct inode *dir;
11450+ struct au_hnotify_args *args;
11451+ char *p, *h_child_name;
dece6358 11452+
1308ab2a 11453+ err = 0;
4a4d8108
AM
11454+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
11455+ dir = igrab(hnotify->hn_aufs_inode);
11456+ if (!dir)
11457+ goto out;
1facf9fc 11458+
4a4d8108
AM
11459+ isroot = (dir->i_ino == AUFS_ROOT_INO);
11460+ wh = 0;
11461+ h_child_name = (void *)h_child_qstr->name;
11462+ len = h_child_qstr->len;
11463+ if (h_child_name) {
11464+ if (len > AUFS_WH_PFX_LEN
11465+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
11466+ h_child_name += AUFS_WH_PFX_LEN;
11467+ len -= AUFS_WH_PFX_LEN;
11468+ wh = 1;
11469+ }
1facf9fc 11470+ }
dece6358 11471+
4a4d8108
AM
11472+ isdir = 0;
11473+ if (h_child_inode)
11474+ isdir = !!S_ISDIR(h_child_inode->i_mode);
11475+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
11476+ flags[AuHn_CHILD] = 0;
11477+ if (isdir)
11478+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
11479+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
11480+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
11481+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
11482+ case FS_MOVED_FROM:
11483+ case FS_MOVED_TO:
11484+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
11485+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11486+ /*FALLTHROUGH*/
11487+ case FS_CREATE:
11488+ AuDebugOn(!h_child_name || !h_child_inode);
11489+ break;
1facf9fc 11490+
4a4d8108
AM
11491+ case FS_DELETE:
11492+ /*
11493+ * aufs never be able to get this child inode.
11494+ * revalidation should be in d_revalidate()
11495+ * by checking i_nlink, i_generation or d_unhashed().
11496+ */
11497+ AuDebugOn(!h_child_name);
11498+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
11499+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11500+ break;
dece6358 11501+
4a4d8108
AM
11502+ default:
11503+ AuDebugOn(1);
11504+ }
1308ab2a 11505+
4a4d8108
AM
11506+ if (wh)
11507+ h_child_inode = NULL;
1308ab2a 11508+
4a4d8108
AM
11509+ err = -ENOMEM;
11510+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 11511+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
11512+ if (unlikely(!args)) {
11513+ AuErr1("no memory\n");
11514+ iput(dir);
11515+ goto out;
11516+ }
11517+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
11518+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
11519+ args->mask = mask;
11520+ args->dir = dir;
11521+ args->h_dir = igrab(h_dir);
11522+ if (h_child_inode)
11523+ h_child_inode = igrab(h_child_inode); /* can be NULL */
11524+ args->h_child_inode = h_child_inode;
11525+ args->h_child_nlen = len;
11526+ if (len) {
11527+ p = (void *)args;
11528+ p += sizeof(*args);
11529+ memcpy(p, h_child_name, len);
11530+ p[len] = 0;
1308ab2a 11531+ }
1308ab2a 11532+
4a4d8108 11533+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
4a4d8108
AM
11534+ if (unlikely(err)) {
11535+ pr_err("wkq %d\n", err);
11536+ iput(args->h_child_inode);
11537+ iput(args->h_dir);
11538+ iput(args->dir);
11539+ kfree(args);
1facf9fc 11540+ }
1facf9fc 11541+
4a4d8108 11542+out:
1facf9fc 11543+ return err;
11544+}
11545+
4a4d8108
AM
11546+static void au_hn_destroy_cache(void)
11547+{
11548+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
11549+ au_cachep[AuCache_HNOTIFY] = NULL;
11550+}
1308ab2a 11551+
4a4d8108 11552+int __init au_hnotify_init(void)
1facf9fc 11553+{
1308ab2a 11554+ int err;
1308ab2a 11555+
4a4d8108
AM
11556+ err = -ENOMEM;
11557+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
11558+ if (au_cachep[AuCache_HNOTIFY]) {
11559+ err = au_hnotify_op.init();
11560+ if (unlikely(err))
11561+ au_hn_destroy_cache();
1308ab2a 11562+ }
1308ab2a 11563+ AuTraceErr(err);
4a4d8108 11564+ return err;
1308ab2a 11565+}
11566+
4a4d8108 11567+void au_hnotify_fin(void)
1308ab2a 11568+{
4a4d8108
AM
11569+ au_hnotify_op.fin();
11570+ /* cf. au_cache_fin() */
11571+ if (au_cachep[AuCache_HNOTIFY])
11572+ au_hn_destroy_cache();
dece6358 11573+}
b752ccd1
AM
11574diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
11575--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
11576+++ linux/fs/aufs/iinfo.c 2010-10-21 09:52:43.090291764 +0200
11577@@ -0,0 +1,257 @@
dece6358 11578+/*
4a4d8108 11579+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
11580+ *
11581+ * This program, aufs is free software; you can redistribute it and/or modify
11582+ * it under the terms of the GNU General Public License as published by
11583+ * the Free Software Foundation; either version 2 of the License, or
11584+ * (at your option) any later version.
11585+ *
11586+ * This program is distributed in the hope that it will be useful,
11587+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11588+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11589+ * GNU General Public License for more details.
11590+ *
11591+ * You should have received a copy of the GNU General Public License
11592+ * along with this program; if not, write to the Free Software
11593+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11594+ */
1facf9fc 11595+
dece6358 11596+/*
4a4d8108 11597+ * inode private data
dece6358 11598+ */
1facf9fc 11599+
1308ab2a 11600+#include "aufs.h"
1facf9fc 11601+
4a4d8108 11602+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 11603+{
4a4d8108 11604+ struct inode *h_inode;
1facf9fc 11605+
4a4d8108 11606+ IiMustAnyLock(inode);
1facf9fc 11607+
4a4d8108
AM
11608+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
11609+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11610+ return h_inode;
11611+}
1facf9fc 11612+
4a4d8108
AM
11613+/* todo: hard/soft set? */
11614+void au_hiput(struct au_hinode *hinode)
11615+{
11616+ au_hn_free(hinode);
11617+ dput(hinode->hi_whdentry);
11618+ iput(hinode->hi_inode);
11619+}
1facf9fc 11620+
4a4d8108
AM
11621+unsigned int au_hi_flags(struct inode *inode, int isdir)
11622+{
11623+ unsigned int flags;
11624+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 11625+
4a4d8108
AM
11626+ flags = 0;
11627+ if (au_opt_test(mnt_flags, XINO))
11628+ au_fset_hi(flags, XINO);
11629+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
11630+ au_fset_hi(flags, HNOTIFY);
11631+ return flags;
1facf9fc 11632+}
11633+
4a4d8108
AM
11634+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
11635+ struct inode *h_inode, unsigned int flags)
1308ab2a 11636+{
4a4d8108
AM
11637+ struct au_hinode *hinode;
11638+ struct inode *hi;
11639+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 11640+
4a4d8108 11641+ IiMustWriteLock(inode);
dece6358 11642+
4a4d8108
AM
11643+ hinode = iinfo->ii_hinode + bindex;
11644+ hi = hinode->hi_inode;
11645+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11646+
11647+ if (hi)
11648+ au_hiput(hinode);
11649+ hinode->hi_inode = h_inode;
11650+ if (h_inode) {
11651+ int err;
11652+ struct super_block *sb = inode->i_sb;
11653+ struct au_branch *br;
11654+
11655+ if (bindex == iinfo->ii_bstart)
11656+ au_cpup_igen(inode, h_inode);
11657+ br = au_sbr(sb, bindex);
11658+ hinode->hi_id = br->br_id;
11659+ if (au_ftest_hi(flags, XINO)) {
11660+ err = au_xino_write(sb, bindex, h_inode->i_ino,
11661+ inode->i_ino);
11662+ if (unlikely(err))
11663+ AuIOErr1("failed au_xino_write() %d\n", err);
11664+ }
11665+
11666+ if (au_ftest_hi(flags, HNOTIFY)
11667+ && au_br_hnotifyable(br->br_perm)) {
11668+ err = au_hn_alloc(hinode, inode, h_inode);
11669+ if (unlikely(err))
11670+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 11671+ }
11672+ }
4a4d8108 11673+}
dece6358 11674+
4a4d8108
AM
11675+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
11676+ struct dentry *h_wh)
11677+{
11678+ struct au_hinode *hinode;
dece6358 11679+
4a4d8108
AM
11680+ IiMustWriteLock(inode);
11681+
11682+ hinode = au_ii(inode)->ii_hinode + bindex;
11683+ AuDebugOn(hinode->hi_whdentry);
11684+ hinode->hi_whdentry = h_wh;
1facf9fc 11685+}
11686+
4a4d8108 11687+void au_update_iigen(struct inode *inode)
1308ab2a 11688+{
4a4d8108
AM
11689+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
11690+ /* smp_mb(); */ /* atomic_set */
11691+}
1facf9fc 11692+
4a4d8108
AM
11693+/* it may be called at remount time, too */
11694+void au_update_ibrange(struct inode *inode, int do_put_zero)
11695+{
11696+ struct au_iinfo *iinfo;
1facf9fc 11697+
4a4d8108
AM
11698+ iinfo = au_ii(inode);
11699+ if (!iinfo || iinfo->ii_bstart < 0)
11700+ return;
1facf9fc 11701+
4a4d8108 11702+ IiMustWriteLock(inode);
1facf9fc 11703+
4a4d8108
AM
11704+ if (do_put_zero) {
11705+ aufs_bindex_t bindex;
1facf9fc 11706+
4a4d8108
AM
11707+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
11708+ bindex++) {
11709+ struct inode *h_i;
1facf9fc 11710+
4a4d8108
AM
11711+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
11712+ if (h_i && !h_i->i_nlink)
11713+ au_set_h_iptr(inode, bindex, NULL, 0);
11714+ }
11715+ }
1308ab2a 11716+
4a4d8108
AM
11717+ iinfo->ii_bstart = -1;
11718+ while (++iinfo->ii_bstart <= iinfo->ii_bend)
11719+ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
11720+ break;
11721+ if (iinfo->ii_bstart > iinfo->ii_bend) {
11722+ iinfo->ii_bstart = -1;
11723+ iinfo->ii_bend = -1;
11724+ return;
11725+ }
11726+
11727+ iinfo->ii_bend++;
11728+ while (0 <= --iinfo->ii_bend)
11729+ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
11730+ break;
11731+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
1308ab2a 11732+}
1facf9fc 11733+
dece6358 11734+/* ---------------------------------------------------------------------- */
1facf9fc 11735+
4a4d8108 11736+void au_icntnr_init_once(void *_c)
dece6358 11737+{
4a4d8108
AM
11738+ struct au_icntnr *c = _c;
11739+ struct au_iinfo *iinfo = &c->iinfo;
1facf9fc 11740+
4a4d8108
AM
11741+ au_rw_init(&iinfo->ii_rwsem);
11742+ inode_init_once(&c->vfs_inode);
11743+}
1facf9fc 11744+
4a4d8108
AM
11745+int au_iinfo_init(struct inode *inode)
11746+{
11747+ struct au_iinfo *iinfo;
11748+ struct super_block *sb;
11749+ int nbr, i;
1facf9fc 11750+
4a4d8108
AM
11751+ sb = inode->i_sb;
11752+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
11753+ nbr = au_sbend(sb) + 1;
11754+ if (unlikely(nbr <= 0))
11755+ nbr = 1;
11756+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
11757+ if (iinfo->ii_hinode) {
11758+ for (i = 0; i < nbr; i++)
11759+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 11760+
4a4d8108
AM
11761+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
11762+ /* smp_mb(); */ /* atomic_set */
11763+ iinfo->ii_bstart = -1;
11764+ iinfo->ii_bend = -1;
11765+ iinfo->ii_vdir = NULL;
11766+ return 0;
1308ab2a 11767+ }
4a4d8108
AM
11768+ return -ENOMEM;
11769+}
1facf9fc 11770+
4a4d8108
AM
11771+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
11772+{
11773+ int err, sz;
11774+ struct au_hinode *hip;
1facf9fc 11775+
4a4d8108
AM
11776+ AuRwMustWriteLock(&iinfo->ii_rwsem);
11777+
11778+ err = -ENOMEM;
11779+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
11780+ if (!sz)
11781+ sz = sizeof(*hip);
11782+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
11783+ if (hip) {
11784+ iinfo->ii_hinode = hip;
11785+ err = 0;
1308ab2a 11786+ }
4a4d8108 11787+
1308ab2a 11788+ return err;
1facf9fc 11789+}
11790+
4a4d8108 11791+void au_iinfo_fin(struct inode *inode)
1facf9fc 11792+{
4a4d8108
AM
11793+ struct au_iinfo *iinfo;
11794+ struct au_hinode *hi;
11795+ struct super_block *sb;
b752ccd1
AM
11796+ aufs_bindex_t bindex, bend;
11797+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 11798+
4a4d8108
AM
11799+ iinfo = au_ii(inode);
11800+ /* bad_inode case */
11801+ if (!iinfo)
11802+ return;
1308ab2a 11803+
b752ccd1
AM
11804+ sb = inode->i_sb;
11805+ if (si_pid_test(sb))
11806+ au_xino_delete_inode(inode, unlinked);
11807+ else {
11808+ /*
11809+ * it is safe to hide the dependency between sbinfo and
11810+ * sb->s_umount.
11811+ */
11812+ lockdep_off();
11813+ si_noflush_read_lock(sb);
11814+ au_xino_delete_inode(inode, unlinked);
11815+ si_read_unlock(sb);
11816+ lockdep_on();
11817+ }
11818+
4a4d8108
AM
11819+ if (iinfo->ii_vdir)
11820+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 11821+
b752ccd1
AM
11822+ bindex = iinfo->ii_bstart;
11823+ if (bindex >= 0) {
11824+ hi = iinfo->ii_hinode + bindex;
4a4d8108 11825+ bend = iinfo->ii_bend;
b752ccd1
AM
11826+ while (bindex++ <= bend) {
11827+ if (hi->hi_inode)
4a4d8108 11828+ au_hiput(hi);
4a4d8108
AM
11829+ hi++;
11830+ }
11831+ }
4a4d8108
AM
11832+ kfree(iinfo->ii_hinode);
11833+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 11834+}
b752ccd1
AM
11835diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
11836--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
953406b4 11837+++ linux/fs/aufs/inode.c 2010-10-21 09:52:43.090291764 +0200
b752ccd1 11838@@ -0,0 +1,443 @@
4a4d8108
AM
11839+/*
11840+ * Copyright (C) 2005-2010 Junjiro R. Okajima
11841+ *
11842+ * This program, aufs is free software; you can redistribute it and/or modify
11843+ * it under the terms of the GNU General Public License as published by
11844+ * the Free Software Foundation; either version 2 of the License, or
11845+ * (at your option) any later version.
11846+ *
11847+ * This program is distributed in the hope that it will be useful,
11848+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11849+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11850+ * GNU General Public License for more details.
11851+ *
11852+ * You should have received a copy of the GNU General Public License
11853+ * along with this program; if not, write to the Free Software
11854+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11855+ */
1facf9fc 11856+
4a4d8108
AM
11857+/*
11858+ * inode functions
11859+ */
1facf9fc 11860+
4a4d8108 11861+#include "aufs.h"
1308ab2a 11862+
4a4d8108
AM
11863+struct inode *au_igrab(struct inode *inode)
11864+{
11865+ if (inode) {
11866+ AuDebugOn(!atomic_read(&inode->i_count));
953406b4 11867+ atomic_inc_return(&inode->i_count);
1facf9fc 11868+ }
4a4d8108
AM
11869+ return inode;
11870+}
1facf9fc 11871+
4a4d8108
AM
11872+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
11873+{
11874+ au_cpup_attr_all(inode, /*force*/0);
11875+ au_update_iigen(inode);
11876+ if (do_version)
11877+ inode->i_version++;
dece6358 11878+}
1facf9fc 11879+
4a4d8108 11880+int au_refresh_hinode_self(struct inode *inode, int do_attr)
dece6358 11881+{
4a4d8108
AM
11882+ int err, e;
11883+ aufs_bindex_t bindex, new_bindex;
11884+ unsigned char update;
11885+ struct au_hinode *p, *q, tmp;
1308ab2a 11886+ struct super_block *sb;
4a4d8108 11887+ struct au_iinfo *iinfo;
1facf9fc 11888+
4a4d8108 11889+ IiMustWriteLock(inode);
1facf9fc 11890+
4a4d8108
AM
11891+ update = 0;
11892+ sb = inode->i_sb;
11893+ iinfo = au_ii(inode);
11894+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
11895+ if (unlikely(err))
1308ab2a 11896+ goto out;
1facf9fc 11897+
4a4d8108
AM
11898+ p = iinfo->ii_hinode + iinfo->ii_bstart;
11899+ err = 0;
11900+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
11901+ bindex++, p++) {
11902+ if (!p->hi_inode)
11903+ continue;
1facf9fc 11904+
4a4d8108
AM
11905+ new_bindex = au_br_index(sb, p->hi_id);
11906+ if (new_bindex == bindex)
11907+ continue;
1facf9fc 11908+
4a4d8108
AM
11909+ if (new_bindex < 0) {
11910+ update = 1;
11911+ au_hiput(p);
11912+ p->hi_inode = NULL;
11913+ continue;
1308ab2a 11914+ }
4a4d8108
AM
11915+
11916+ if (new_bindex < iinfo->ii_bstart)
11917+ iinfo->ii_bstart = new_bindex;
11918+ if (iinfo->ii_bend < new_bindex)
11919+ iinfo->ii_bend = new_bindex;
11920+ /* swap two lower inode, and loop again */
11921+ q = iinfo->ii_hinode + new_bindex;
11922+ tmp = *q;
11923+ *q = *p;
11924+ *p = tmp;
11925+ if (tmp.hi_inode) {
11926+ bindex--;
11927+ p--;
1308ab2a 11928+ }
11929+ }
4a4d8108
AM
11930+ au_update_ibrange(inode, /*do_put_zero*/0);
11931+ e = au_dy_irefresh(inode);
11932+ if (unlikely(e && !err))
11933+ err = e;
11934+ if (do_attr)
11935+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
1facf9fc 11936+
4f0767ce 11937+out:
4a4d8108
AM
11938+ return err;
11939+}
1facf9fc 11940+
4a4d8108
AM
11941+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
11942+{
11943+ int err, e;
11944+ unsigned int flags;
11945+ aufs_bindex_t bindex, bend;
11946+ unsigned char isdir, update;
11947+ struct au_hinode *p;
11948+ struct au_iinfo *iinfo;
1facf9fc 11949+
4a4d8108
AM
11950+ err = au_refresh_hinode_self(inode, /*do_attr*/0);
11951+ if (unlikely(err))
11952+ goto out;
11953+
11954+ update = 0;
11955+ iinfo = au_ii(inode);
11956+ p = iinfo->ii_hinode + iinfo->ii_bstart;
11957+ isdir = S_ISDIR(inode->i_mode);
11958+ flags = au_hi_flags(inode, isdir);
11959+ bend = au_dbend(dentry);
11960+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
11961+ struct inode *h_i;
11962+ struct dentry *h_d;
11963+
11964+ h_d = au_h_dptr(dentry, bindex);
11965+ if (!h_d || !h_d->d_inode)
11966+ continue;
11967+
11968+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
11969+ h_i = au_h_iptr(inode, bindex);
11970+ if (h_i) {
11971+ if (h_i == h_d->d_inode)
11972+ continue;
11973+ err = -EIO;
11974+ break;
11975+ }
11976+ }
11977+ if (bindex < iinfo->ii_bstart)
11978+ iinfo->ii_bstart = bindex;
11979+ if (iinfo->ii_bend < bindex)
11980+ iinfo->ii_bend = bindex;
11981+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
11982+ update = 1;
1308ab2a 11983+ }
4a4d8108
AM
11984+ au_update_ibrange(inode, /*do_put_zero*/0);
11985+ e = au_dy_irefresh(inode);
11986+ if (unlikely(e && !err))
11987+ err = e;
11988+ au_refresh_hinode_attr(inode, update && isdir);
11989+
4f0767ce 11990+out:
4a4d8108 11991+ AuTraceErr(err);
1308ab2a 11992+ return err;
dece6358
AM
11993+}
11994+
4a4d8108 11995+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 11996+{
4a4d8108
AM
11997+ int err;
11998+ unsigned int flags;
11999+ umode_t mode;
12000+ aufs_bindex_t bindex, bstart, btail;
12001+ unsigned char isdir;
12002+ struct dentry *h_dentry;
12003+ struct inode *h_inode;
12004+ struct au_iinfo *iinfo;
dece6358 12005+
4a4d8108 12006+ IiMustWriteLock(inode);
dece6358 12007+
4a4d8108
AM
12008+ err = 0;
12009+ isdir = 0;
12010+ bstart = au_dbstart(dentry);
12011+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
12012+ mode = h_inode->i_mode;
12013+ switch (mode & S_IFMT) {
12014+ case S_IFREG:
12015+ btail = au_dbtail(dentry);
12016+ inode->i_op = &aufs_iop;
12017+ inode->i_fop = &aufs_file_fop;
12018+ err = au_dy_iaop(inode, bstart, h_inode);
12019+ if (unlikely(err))
12020+ goto out;
12021+ break;
12022+ case S_IFDIR:
12023+ isdir = 1;
12024+ btail = au_dbtaildir(dentry);
12025+ inode->i_op = &aufs_dir_iop;
12026+ inode->i_fop = &aufs_dir_fop;
12027+ break;
12028+ case S_IFLNK:
12029+ btail = au_dbtail(dentry);
12030+ inode->i_op = &aufs_symlink_iop;
12031+ break;
12032+ case S_IFBLK:
12033+ case S_IFCHR:
12034+ case S_IFIFO:
12035+ case S_IFSOCK:
12036+ btail = au_dbtail(dentry);
12037+ inode->i_op = &aufs_iop;
12038+ au_init_special_fop(inode, mode, h_inode->i_rdev);
12039+ break;
12040+ default:
12041+ AuIOErr("Unknown file type 0%o\n", mode);
12042+ err = -EIO;
1308ab2a 12043+ goto out;
4a4d8108 12044+ }
dece6358 12045+
4a4d8108
AM
12046+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
12047+ flags = au_hi_flags(inode, isdir);
12048+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
12049+ && au_ftest_hi(flags, HNOTIFY)
12050+ && dentry->d_name.len > AUFS_WH_PFX_LEN
12051+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
12052+ au_fclr_hi(flags, HNOTIFY);
12053+ iinfo = au_ii(inode);
12054+ iinfo->ii_bstart = bstart;
12055+ iinfo->ii_bend = btail;
12056+ for (bindex = bstart; bindex <= btail; bindex++) {
12057+ h_dentry = au_h_dptr(dentry, bindex);
12058+ if (h_dentry)
12059+ au_set_h_iptr(inode, bindex,
12060+ au_igrab(h_dentry->d_inode), flags);
12061+ }
12062+ au_cpup_attr_all(inode, /*force*/1);
dece6358 12063+
4f0767ce 12064+out:
4a4d8108
AM
12065+ return err;
12066+}
dece6358 12067+
4a4d8108
AM
12068+/* successful returns with iinfo write_locked */
12069+static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
12070+{
12071+ int err;
12072+ aufs_bindex_t bindex, bend;
12073+ struct inode *h_inode, *h_dinode;
dece6358 12074+
4a4d8108 12075+ *matched = 0;
dece6358 12076+
4a4d8108
AM
12077+ /*
12078+ * before this function, if aufs got any iinfo lock, it must be only
12079+ * one, the parent dir.
12080+ * it can happen by UDBA and the obsoleted inode number.
12081+ */
12082+ err = -EIO;
12083+ if (unlikely(inode->i_ino == parent_ino(dentry)))
12084+ goto out;
12085+
12086+ err = 0;
12087+ ii_write_lock_new_child(inode);
12088+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
12089+ bend = au_ibend(inode);
12090+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12091+ h_inode = au_h_iptr(inode, bindex);
12092+ if (h_inode && h_inode == h_dinode) {
12093+ *matched = 1;
12094+ err = 0;
12095+ if (au_iigen(inode) != au_digen(dentry))
12096+ err = au_refresh_hinode(inode, dentry);
12097+ break;
1308ab2a 12098+ }
1facf9fc 12099+ }
dece6358 12100+
4a4d8108
AM
12101+ if (unlikely(err))
12102+ ii_write_unlock(inode);
4f0767ce 12103+out:
1facf9fc 12104+ return err;
12105+}
1facf9fc 12106+
4a4d8108
AM
12107+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12108+ unsigned int d_type, ino_t *ino)
1facf9fc 12109+{
4a4d8108
AM
12110+ int err;
12111+ struct mutex *mtx;
1facf9fc 12112+
b752ccd1 12113+ /* prevent hardlinked inode number from race condition */
4a4d8108 12114+ mtx = NULL;
b752ccd1 12115+ if (d_type != DT_DIR) {
4a4d8108
AM
12116+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
12117+ mutex_lock(mtx);
12118+ }
12119+ err = au_xino_read(sb, bindex, h_ino, ino);
12120+ if (unlikely(err))
12121+ goto out;
1308ab2a 12122+
4a4d8108
AM
12123+ if (!*ino) {
12124+ err = -EIO;
12125+ *ino = au_xino_new_ino(sb);
12126+ if (unlikely(!*ino))
1facf9fc 12127+ goto out;
4a4d8108
AM
12128+ err = au_xino_write(sb, bindex, h_ino, *ino);
12129+ if (unlikely(err))
1308ab2a 12130+ goto out;
1308ab2a 12131+ }
1facf9fc 12132+
4f0767ce 12133+out:
b752ccd1 12134+ if (mtx)
4a4d8108 12135+ mutex_unlock(mtx);
1facf9fc 12136+ return err;
12137+}
12138+
4a4d8108
AM
12139+/* successful returns with iinfo write_locked */
12140+/* todo: return with unlocked? */
12141+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 12142+{
b752ccd1 12143+ struct inode *inode, *h_inode;
4a4d8108
AM
12144+ struct dentry *h_dentry;
12145+ struct super_block *sb;
b752ccd1 12146+ struct mutex *mtx;
4a4d8108
AM
12147+ ino_t h_ino, ino;
12148+ int err, match;
12149+ aufs_bindex_t bstart;
1facf9fc 12150+
4a4d8108
AM
12151+ sb = dentry->d_sb;
12152+ bstart = au_dbstart(dentry);
12153+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
12154+ h_inode = h_dentry->d_inode;
12155+ h_ino = h_inode->i_ino;
12156+
12157+ /*
12158+ * stop 'race'-ing between hardlinks under different
12159+ * parents.
12160+ */
12161+ mtx = NULL;
12162+ if (!S_ISDIR(h_inode->i_mode))
12163+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
12164+
4f0767ce 12165+new_ino:
b752ccd1
AM
12166+ if (mtx)
12167+ mutex_lock(mtx);
4a4d8108
AM
12168+ err = au_xino_read(sb, bstart, h_ino, &ino);
12169+ inode = ERR_PTR(err);
12170+ if (unlikely(err))
12171+ goto out;
b752ccd1 12172+
4a4d8108
AM
12173+ if (!ino) {
12174+ ino = au_xino_new_ino(sb);
12175+ if (unlikely(!ino)) {
12176+ inode = ERR_PTR(-EIO);
dece6358
AM
12177+ goto out;
12178+ }
12179+ }
1facf9fc 12180+
4a4d8108
AM
12181+ AuDbg("i%lu\n", (unsigned long)ino);
12182+ inode = au_iget_locked(sb, ino);
12183+ err = PTR_ERR(inode);
12184+ if (IS_ERR(inode))
1facf9fc 12185+ goto out;
1facf9fc 12186+
4a4d8108
AM
12187+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
12188+ if (inode->i_state & I_NEW) {
12189+ ii_write_lock_new_child(inode);
12190+ err = set_inode(inode, dentry);
12191+ if (!err) {
12192+ unlock_new_inode(inode);
12193+ goto out; /* success */
12194+ }
1308ab2a 12195+
4a4d8108
AM
12196+ ii_write_unlock(inode);
12197+ iget_failed(inode);
12198+ goto out_err;
12199+ } else if (!must_new) {
b752ccd1
AM
12200+ /*
12201+ * horrible race condition between lookup, readdir and copyup
12202+ * (or something).
12203+ */
12204+ if (mtx)
12205+ mutex_unlock(mtx);
4a4d8108 12206+ err = reval_inode(inode, dentry, &match);
b752ccd1
AM
12207+ if (!err) {
12208+ mtx = NULL;
4a4d8108 12209+ goto out; /* success */
b752ccd1
AM
12210+ } else if (match) {
12211+ mtx = NULL;
4a4d8108 12212+ goto out_iput;
b752ccd1
AM
12213+ } else if (mtx)
12214+ mutex_lock(mtx);
4a4d8108
AM
12215+ }
12216+
12217+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
12218+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
12219+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
12220+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
12221+ (unsigned long)h_ino, (unsigned long)ino);
12222+ ino = 0;
12223+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
12224+ if (!err) {
12225+ iput(inode);
b752ccd1
AM
12226+ if (mtx)
12227+ mutex_unlock(mtx);
4a4d8108
AM
12228+ goto new_ino;
12229+ }
1308ab2a 12230+
4f0767ce 12231+out_iput:
4a4d8108 12232+ iput(inode);
4f0767ce 12233+out_err:
4a4d8108 12234+ inode = ERR_PTR(err);
4f0767ce 12235+out:
b752ccd1
AM
12236+ if (mtx)
12237+ mutex_unlock(mtx);
4a4d8108 12238+ return inode;
1facf9fc 12239+}
12240+
4a4d8108 12241+/* ---------------------------------------------------------------------- */
1facf9fc 12242+
4a4d8108
AM
12243+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12244+ struct inode *inode)
12245+{
12246+ int err;
1facf9fc 12247+
4a4d8108 12248+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 12249+
4a4d8108
AM
12250+ /* pseudo-link after flushed may happen out of bounds */
12251+ if (!err
12252+ && inode
12253+ && au_ibstart(inode) <= bindex
12254+ && bindex <= au_ibend(inode)) {
12255+ /*
12256+ * permission check is unnecessary since vfsub routine
12257+ * will be called later
12258+ */
12259+ struct inode *hi = au_h_iptr(inode, bindex);
12260+ if (hi)
12261+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 12262+ }
12263+
4a4d8108
AM
12264+ return err;
12265+}
dece6358 12266+
4a4d8108
AM
12267+int au_test_h_perm(struct inode *h_inode, int mask)
12268+{
12269+ if (!current_fsuid())
12270+ return 0;
12271+ return inode_permission(h_inode, mask);
12272+}
1facf9fc 12273+
4a4d8108
AM
12274+int au_test_h_perm_sio(struct inode *h_inode, int mask)
12275+{
12276+ if (au_test_nfs(h_inode->i_sb)
12277+ && (mask & MAY_WRITE)
12278+ && S_ISDIR(h_inode->i_mode))
12279+ mask |= MAY_READ; /* force permission check */
12280+ return au_test_h_perm(h_inode, mask);
1facf9fc 12281+}
b752ccd1
AM
12282diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
12283--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
12284+++ linux/fs/aufs/inode.h 2010-10-21 09:52:43.090291764 +0200
12285@@ -0,0 +1,498 @@
4a4d8108
AM
12286+/*
12287+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12288+ *
12289+ * This program, aufs is free software; you can redistribute it and/or modify
12290+ * it under the terms of the GNU General Public License as published by
12291+ * the Free Software Foundation; either version 2 of the License, or
12292+ * (at your option) any later version.
12293+ *
12294+ * This program is distributed in the hope that it will be useful,
12295+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12296+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12297+ * GNU General Public License for more details.
12298+ *
12299+ * You should have received a copy of the GNU General Public License
12300+ * along with this program; if not, write to the Free Software
12301+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12302+ */
1facf9fc 12303+
1308ab2a 12304+/*
4a4d8108 12305+ * inode operations
1308ab2a 12306+ */
dece6358 12307+
4a4d8108
AM
12308+#ifndef __AUFS_INODE_H__
12309+#define __AUFS_INODE_H__
dece6358 12310+
4a4d8108 12311+#ifdef __KERNEL__
1308ab2a 12312+
4a4d8108
AM
12313+#include <linux/fs.h>
12314+#include <linux/fsnotify.h>
12315+#include <linux/aufs_type.h>
12316+#include "rwsem.h"
1308ab2a 12317+
4a4d8108 12318+struct vfsmount;
1facf9fc 12319+
4a4d8108
AM
12320+struct au_hnotify {
12321+#ifdef CONFIG_AUFS_HNOTIFY
12322+#ifdef CONFIG_AUFS_HFSNOTIFY
953406b4
AM
12323+ /* never use fsnotify_add_vfsmount_mark() */
12324+ struct fsnotify_mark hn_mark;
12325+ int hn_mark_dead;
4a4d8108
AM
12326+#endif
12327+ struct inode *hn_aufs_inode; /* no get/put */
12328+#endif
12329+} ____cacheline_aligned_in_smp;
1facf9fc 12330+
4a4d8108
AM
12331+struct au_hinode {
12332+ struct inode *hi_inode;
12333+ aufs_bindex_t hi_id;
12334+#ifdef CONFIG_AUFS_HNOTIFY
12335+ struct au_hnotify *hi_notify;
12336+#endif
dece6358 12337+
4a4d8108
AM
12338+ /* reference to the copied-up whiteout with get/put */
12339+ struct dentry *hi_whdentry;
12340+};
dece6358 12341+
4a4d8108
AM
12342+struct au_vdir;
12343+struct au_iinfo {
12344+ atomic_t ii_generation;
12345+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 12346+
4a4d8108
AM
12347+ struct au_rwsem ii_rwsem;
12348+ aufs_bindex_t ii_bstart, ii_bend;
12349+ __u32 ii_higen;
12350+ struct au_hinode *ii_hinode;
12351+ struct au_vdir *ii_vdir;
12352+};
1facf9fc 12353+
4a4d8108
AM
12354+struct au_icntnr {
12355+ struct au_iinfo iinfo;
12356+ struct inode vfs_inode;
12357+} ____cacheline_aligned_in_smp;
1308ab2a 12358+
4a4d8108
AM
12359+/* au_pin flags */
12360+#define AuPin_DI_LOCKED 1
12361+#define AuPin_MNT_WRITE (1 << 1)
12362+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
12363+#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
12364+#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
12365+
12366+struct au_pin {
12367+ /* input */
12368+ struct dentry *dentry;
12369+ unsigned int udba;
12370+ unsigned char lsc_di, lsc_hi, flags;
12371+ aufs_bindex_t bindex;
12372+
12373+ /* output */
12374+ struct dentry *parent;
12375+ struct au_hinode *hdir;
12376+ struct vfsmount *h_mnt;
12377+};
1facf9fc 12378+
1308ab2a 12379+/* ---------------------------------------------------------------------- */
12380+
4a4d8108 12381+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 12382+{
4a4d8108 12383+ struct au_iinfo *iinfo;
1facf9fc 12384+
4a4d8108
AM
12385+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12386+ if (iinfo->ii_hinode)
12387+ return iinfo;
12388+ return NULL; /* debugging bad_inode case */
12389+}
1facf9fc 12390+
4a4d8108 12391+/* ---------------------------------------------------------------------- */
1facf9fc 12392+
4a4d8108
AM
12393+/* inode.c */
12394+struct inode *au_igrab(struct inode *inode);
12395+int au_refresh_hinode_self(struct inode *inode, int do_attr);
12396+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
12397+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12398+ unsigned int d_type, ino_t *ino);
12399+struct inode *au_new_inode(struct dentry *dentry, int must_new);
12400+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12401+ struct inode *inode);
12402+int au_test_h_perm(struct inode *h_inode, int mask);
12403+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 12404+
4a4d8108
AM
12405+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
12406+ ino_t h_ino, unsigned int d_type, ino_t *ino)
12407+{
12408+#ifdef CONFIG_AUFS_SHWH
12409+ return au_ino(sb, bindex, h_ino, d_type, ino);
12410+#else
12411+ return 0;
12412+#endif
12413+}
1facf9fc 12414+
4a4d8108
AM
12415+/* i_op.c */
12416+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 12417+
4a4d8108
AM
12418+/* au_wr_dir flags */
12419+#define AuWrDir_ADD_ENTRY 1
12420+#define AuWrDir_ISDIR (1 << 1)
12421+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
12422+#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
12423+#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
1facf9fc 12424+
4a4d8108
AM
12425+struct au_wr_dir_args {
12426+ aufs_bindex_t force_btgt;
12427+ unsigned char flags;
12428+};
12429+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
12430+ struct au_wr_dir_args *args);
dece6358 12431+
4a4d8108
AM
12432+struct dentry *au_pinned_h_parent(struct au_pin *pin);
12433+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
12434+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
12435+ unsigned int udba, unsigned char flags);
12436+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
12437+ unsigned int udba, unsigned char flags) __must_check;
12438+int au_do_pin(struct au_pin *pin) __must_check;
12439+void au_unpin(struct au_pin *pin);
1facf9fc 12440+
4a4d8108
AM
12441+/* i_op_add.c */
12442+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
12443+ struct dentry *h_parent, int isdir);
12444+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
12445+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
12446+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
12447+ struct nameidata *nd);
12448+int aufs_link(struct dentry *src_dentry, struct inode *dir,
12449+ struct dentry *dentry);
12450+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
1facf9fc 12451+
4a4d8108
AM
12452+/* i_op_del.c */
12453+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
12454+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
12455+ struct dentry *h_parent, int isdir);
12456+int aufs_unlink(struct inode *dir, struct dentry *dentry);
12457+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 12458+
4a4d8108
AM
12459+/* i_op_ren.c */
12460+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
12461+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
12462+ struct inode *dir, struct dentry *dentry);
1facf9fc 12463+
4a4d8108
AM
12464+/* iinfo.c */
12465+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
12466+void au_hiput(struct au_hinode *hinode);
12467+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12468+ struct dentry *h_wh);
12469+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 12470+
4a4d8108
AM
12471+/* hinode flags */
12472+#define AuHi_XINO 1
12473+#define AuHi_HNOTIFY (1 << 1)
12474+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
12475+#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; }
12476+#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; }
1facf9fc 12477+
4a4d8108
AM
12478+#ifndef CONFIG_AUFS_HNOTIFY
12479+#undef AuHi_HNOTIFY
12480+#define AuHi_HNOTIFY 0
12481+#endif
1facf9fc 12482+
4a4d8108
AM
12483+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12484+ struct inode *h_inode, unsigned int flags);
1facf9fc 12485+
4a4d8108
AM
12486+void au_update_iigen(struct inode *inode);
12487+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 12488+
4a4d8108
AM
12489+void au_icntnr_init_once(void *_c);
12490+int au_iinfo_init(struct inode *inode);
12491+void au_iinfo_fin(struct inode *inode);
12492+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 12493+
4a4d8108 12494+/* plink.c */
953406b4
AM
12495+void au_plink_maint_block(struct super_block *sb);
12496+void au_plink_maint_leave(struct file *file);
4a4d8108
AM
12497+#ifdef CONFIG_AUFS_DEBUG
12498+void au_plink_list(struct super_block *sb);
12499+#else
12500+AuStubVoid(au_plink_list, struct super_block *sb)
12501+#endif
12502+int au_plink_test(struct inode *inode);
12503+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
12504+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
12505+ struct dentry *h_dentry);
953406b4 12506+void au_plink_put(struct super_block *sb);
4a4d8108 12507+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
953406b4 12508+long au_plink_ioctl(struct file *file, unsigned int cmd);
1facf9fc 12509+
4a4d8108 12510+/* ---------------------------------------------------------------------- */
1308ab2a 12511+
4a4d8108
AM
12512+/* lock subclass for iinfo */
12513+enum {
12514+ AuLsc_II_CHILD, /* child first */
12515+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
12516+ AuLsc_II_CHILD3, /* copyup dirs */
12517+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
12518+ AuLsc_II_PARENT2,
12519+ AuLsc_II_PARENT3, /* copyup dirs */
12520+ AuLsc_II_NEW_CHILD
12521+};
1308ab2a 12522+
1facf9fc 12523+/*
4a4d8108
AM
12524+ * ii_read_lock_child, ii_write_lock_child,
12525+ * ii_read_lock_child2, ii_write_lock_child2,
12526+ * ii_read_lock_child3, ii_write_lock_child3,
12527+ * ii_read_lock_parent, ii_write_lock_parent,
12528+ * ii_read_lock_parent2, ii_write_lock_parent2,
12529+ * ii_read_lock_parent3, ii_write_lock_parent3,
12530+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 12531+ */
4a4d8108
AM
12532+#define AuReadLockFunc(name, lsc) \
12533+static inline void ii_read_lock_##name(struct inode *i) \
12534+{ \
12535+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12536+}
12537+
12538+#define AuWriteLockFunc(name, lsc) \
12539+static inline void ii_write_lock_##name(struct inode *i) \
12540+{ \
12541+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12542+}
12543+
12544+#define AuRWLockFuncs(name, lsc) \
12545+ AuReadLockFunc(name, lsc) \
12546+ AuWriteLockFunc(name, lsc)
12547+
12548+AuRWLockFuncs(child, CHILD);
12549+AuRWLockFuncs(child2, CHILD2);
12550+AuRWLockFuncs(child3, CHILD3);
12551+AuRWLockFuncs(parent, PARENT);
12552+AuRWLockFuncs(parent2, PARENT2);
12553+AuRWLockFuncs(parent3, PARENT3);
12554+AuRWLockFuncs(new_child, NEW_CHILD);
12555+
12556+#undef AuReadLockFunc
12557+#undef AuWriteLockFunc
12558+#undef AuRWLockFuncs
1facf9fc 12559+
12560+/*
4a4d8108 12561+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 12562+ */
4a4d8108 12563+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 12564+
4a4d8108
AM
12565+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
12566+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
12567+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 12568+
4a4d8108 12569+/* ---------------------------------------------------------------------- */
1308ab2a 12570+
4a4d8108
AM
12571+static inline unsigned int au_iigen(struct inode *inode)
12572+{
12573+ return atomic_read(&au_ii(inode)->ii_generation);
12574+}
1308ab2a 12575+
4a4d8108
AM
12576+/* tiny test for inode number */
12577+/* tmpfs generation is too rough */
12578+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
12579+{
12580+ struct au_iinfo *iinfo;
1308ab2a 12581+
4a4d8108
AM
12582+ iinfo = au_ii(inode);
12583+ AuRwMustAnyLock(&iinfo->ii_rwsem);
12584+ return !(iinfo->ii_hsb1 == h_inode->i_sb
12585+ && iinfo->ii_higen == h_inode->i_generation);
12586+}
1308ab2a 12587+
4a4d8108
AM
12588+static inline void au_iigen_dec(struct inode *inode)
12589+{
12590+#ifdef CONFIG_AUFS_HNOTIFY
953406b4 12591+ atomic_dec_return(&au_ii(inode)->ii_generation);
4a4d8108
AM
12592+#endif
12593+}
1308ab2a 12594+
4a4d8108 12595+/* ---------------------------------------------------------------------- */
1308ab2a 12596+
4a4d8108
AM
12597+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
12598+ aufs_bindex_t bindex)
12599+{
12600+ IiMustAnyLock(inode);
12601+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
12602+}
1308ab2a 12603+
4a4d8108
AM
12604+static inline aufs_bindex_t au_ibstart(struct inode *inode)
12605+{
12606+ IiMustAnyLock(inode);
12607+ return au_ii(inode)->ii_bstart;
12608+}
1308ab2a 12609+
4a4d8108
AM
12610+static inline aufs_bindex_t au_ibend(struct inode *inode)
12611+{
12612+ IiMustAnyLock(inode);
12613+ return au_ii(inode)->ii_bend;
12614+}
1308ab2a 12615+
4a4d8108
AM
12616+static inline struct au_vdir *au_ivdir(struct inode *inode)
12617+{
12618+ IiMustAnyLock(inode);
12619+ return au_ii(inode)->ii_vdir;
12620+}
1308ab2a 12621+
4a4d8108
AM
12622+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
12623+{
12624+ IiMustAnyLock(inode);
12625+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
12626+}
1308ab2a 12627+
4a4d8108 12628+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12629+{
4a4d8108
AM
12630+ IiMustWriteLock(inode);
12631+ au_ii(inode)->ii_bstart = bindex;
12632+}
1308ab2a 12633+
4a4d8108
AM
12634+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
12635+{
12636+ IiMustWriteLock(inode);
12637+ au_ii(inode)->ii_bend = bindex;
1308ab2a 12638+}
12639+
4a4d8108
AM
12640+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
12641+{
12642+ IiMustWriteLock(inode);
12643+ au_ii(inode)->ii_vdir = vdir;
12644+}
1facf9fc 12645+
4a4d8108 12646+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12647+{
4a4d8108
AM
12648+ IiMustAnyLock(inode);
12649+ return au_ii(inode)->ii_hinode + bindex;
12650+}
dece6358 12651+
4a4d8108 12652+/* ---------------------------------------------------------------------- */
1facf9fc 12653+
4a4d8108
AM
12654+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
12655+{
12656+ if (pin)
12657+ return pin->parent;
12658+ return NULL;
1facf9fc 12659+}
12660+
4a4d8108 12661+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 12662+{
4a4d8108
AM
12663+ if (pin && pin->hdir)
12664+ return pin->hdir->hi_inode;
12665+ return NULL;
1308ab2a 12666+}
1facf9fc 12667+
4a4d8108
AM
12668+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
12669+{
12670+ if (pin)
12671+ return pin->hdir;
12672+ return NULL;
12673+}
1facf9fc 12674+
4a4d8108 12675+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 12676+{
4a4d8108
AM
12677+ if (pin)
12678+ pin->dentry = dentry;
12679+}
1308ab2a 12680+
4a4d8108
AM
12681+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
12682+ unsigned char lflag)
12683+{
12684+ if (pin) {
12685+ /* dirty macros require brackets */
12686+ if (lflag) {
12687+ au_fset_pin(pin->flags, DI_LOCKED);
12688+ } else {
12689+ au_fclr_pin(pin->flags, DI_LOCKED);
12690+ }
1308ab2a 12691+ }
4a4d8108
AM
12692+}
12693+
12694+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
12695+{
12696+ if (pin) {
12697+ dput(pin->parent);
12698+ pin->parent = dget(parent);
1facf9fc 12699+ }
4a4d8108 12700+}
1facf9fc 12701+
4a4d8108
AM
12702+/* ---------------------------------------------------------------------- */
12703+
12704+#ifdef CONFIG_AUFS_HNOTIFY
12705+struct au_hnotify_op {
12706+ void (*ctl)(struct au_hinode *hinode, int do_set);
12707+ int (*alloc)(struct au_hnotify *hn, struct inode *h_inode);
12708+ void (*free)(struct au_hnotify *hn);
12709+
12710+ void (*fin)(void);
12711+ int (*init)(void);
12712+};
12713+
12714+/* hnotify.c */
12715+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
12716+ struct inode *h_inode);
12717+void au_hn_free(struct au_hinode *hinode);
12718+void au_hn_ctl(struct au_hinode *hinode, int do_set);
12719+void au_hn_reset(struct inode *inode, unsigned int flags);
12720+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
12721+ struct qstr *h_child_qstr, struct inode *h_child_inode);
12722+int __init au_hnotify_init(void);
12723+void au_hnotify_fin(void);
12724+
953406b4 12725+/* hfsnotify.c */
4a4d8108
AM
12726+extern const struct au_hnotify_op au_hnotify_op;
12727+
12728+static inline
12729+void au_hn_init(struct au_hinode *hinode)
12730+{
12731+ hinode->hi_notify = NULL;
1308ab2a 12732+}
12733+
4a4d8108
AM
12734+#else
12735+static inline
12736+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
12737+ struct inode *inode __maybe_unused,
12738+ struct inode *h_inode __maybe_unused)
1308ab2a 12739+{
4a4d8108
AM
12740+ return -EOPNOTSUPP;
12741+}
1308ab2a 12742+
4a4d8108
AM
12743+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
12744+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
12745+ int do_set __maybe_unused)
12746+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
12747+ unsigned int flags __maybe_unused)
12748+AuStubInt0(__init au_hnotify_init, void)
12749+AuStubVoid(au_hnotify_fin, void)
12750+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
12751+#endif /* CONFIG_AUFS_HNOTIFY */
12752+
12753+static inline void au_hn_suspend(struct au_hinode *hdir)
12754+{
12755+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 12756+}
12757+
4a4d8108 12758+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 12759+{
4a4d8108
AM
12760+ au_hn_ctl(hdir, /*do_set*/1);
12761+}
1308ab2a 12762+
4a4d8108
AM
12763+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
12764+{
12765+ mutex_lock(&hdir->hi_inode->i_mutex);
12766+ au_hn_suspend(hdir);
12767+}
dece6358 12768+
4a4d8108
AM
12769+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
12770+ unsigned int sc __maybe_unused)
12771+{
12772+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
12773+ au_hn_suspend(hdir);
1facf9fc 12774+}
1facf9fc 12775+
4a4d8108
AM
12776+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
12777+{
12778+ au_hn_resume(hdir);
12779+ mutex_unlock(&hdir->hi_inode->i_mutex);
12780+}
12781+
12782+#endif /* __KERNEL__ */
12783+#endif /* __AUFS_INODE_H__ */
b752ccd1
AM
12784diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
12785--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
12786+++ linux/fs/aufs/ioctl.c 2010-10-21 09:52:43.090291764 +0200
12787@@ -0,0 +1,155 @@
4a4d8108
AM
12788+/*
12789+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12790+ *
12791+ * This program, aufs is free software; you can redistribute it and/or modify
12792+ * it under the terms of the GNU General Public License as published by
12793+ * the Free Software Foundation; either version 2 of the License, or
12794+ * (at your option) any later version.
12795+ *
12796+ * This program is distributed in the hope that it will be useful,
12797+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12798+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12799+ * GNU General Public License for more details.
12800+ *
12801+ * You should have received a copy of the GNU General Public License
12802+ * along with this program; if not, write to the Free Software
12803+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12804+ */
12805+
12806+/*
12807+ * ioctl
12808+ * plink-management and readdir in userspace.
12809+ * assist the pathconf(3) wrapper library.
12810+ */
12811+
12812+#include <linux/file.h>
12813+#include "aufs.h"
12814+
12815+static int au_wbr_fd(struct path *path)
12816+{
12817+ int err, fd;
12818+ aufs_bindex_t wbi, bindex, bend;
12819+ struct file *h_file;
12820+ struct super_block *sb;
12821+ struct dentry *root;
12822+ struct au_branch *wbr;
12823+
12824+ err = get_unused_fd();
12825+ if (unlikely(err < 0))
12826+ goto out;
12827+ fd = err;
12828+
12829+ wbi = 0;
12830+ sb = path->dentry->d_sb;
12831+ root = sb->s_root;
12832+ aufs_read_lock(root, AuLock_IR);
12833+ wbr = au_sbr(sb, wbi);
12834+ if (!(path->mnt->mnt_flags & MNT_READONLY)
12835+ && !au_br_writable(wbr->br_perm)) {
12836+ bend = au_sbend(sb);
12837+ for (bindex = 1; bindex <= bend; bindex++) {
12838+ wbr = au_sbr(sb, bindex);
12839+ if (au_br_writable(wbr->br_perm)) {
12840+ wbi = bindex;
12841+ break;
12842+ }
12843+ }
12844+ wbr = au_sbr(sb, wbi);
12845+ }
12846+ AuDbg("wbi %d\n", wbi);
12847+ h_file = au_h_open(root, wbi, O_RDONLY | O_DIRECTORY | O_LARGEFILE,
12848+ NULL);
12849+ aufs_read_unlock(root, AuLock_IR);
12850+ err = PTR_ERR(h_file);
12851+ if (IS_ERR(h_file))
12852+ goto out_fd;
12853+
12854+ atomic_dec(&wbr->br_count); /* cf. au_h_open() */
12855+ fd_install(fd, h_file);
12856+ err = fd;
12857+ goto out; /* success */
12858+
4f0767ce 12859+out_fd:
4a4d8108 12860+ put_unused_fd(fd);
4f0767ce 12861+out:
4a4d8108
AM
12862+ return err;
12863+}
12864+
12865+/* ---------------------------------------------------------------------- */
12866+
12867+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
12868+{
12869+ long err;
12870+
12871+ switch (cmd) {
953406b4
AM
12872+ case AUFS_CTL_PLINK_MAINT:
12873+ case AUFS_CTL_PLINK_CLEAN:
12874+ err = au_plink_ioctl(file, cmd);
12875+ break;
12876+
4a4d8108
AM
12877+ case AUFS_CTL_RDU:
12878+ case AUFS_CTL_RDU_INO:
12879+ err = au_rdu_ioctl(file, cmd, arg);
12880+ break;
12881+
12882+ case AUFS_CTL_WBR_FD:
12883+ err = au_wbr_fd(&file->f_path);
12884+ break;
12885+
12886+ default:
12887+ /* do not call the lower */
12888+ AuDbg("0x%x\n", cmd);
12889+ err = -ENOTTY;
12890+ }
12891+
12892+ AuTraceErr(err);
12893+ return err;
12894+}
12895+
12896+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
12897+{
12898+ long err;
12899+
12900+ switch (cmd) {
12901+ case AUFS_CTL_WBR_FD:
12902+ err = au_wbr_fd(&file->f_path);
12903+ break;
12904+
12905+ default:
12906+ /* do not call the lower */
12907+ AuDbg("0x%x\n", cmd);
12908+ err = -ENOTTY;
12909+ }
12910+
12911+ AuTraceErr(err);
12912+ return err;
12913+}
b752ccd1
AM
12914+
12915+#ifdef CONFIG_COMPAT
12916+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
12917+ unsigned long arg)
12918+{
12919+ long err;
12920+
12921+ switch (cmd) {
12922+ case AUFS_CTL_RDU:
12923+ case AUFS_CTL_RDU_INO:
12924+ err = au_rdu_compat_ioctl(file, cmd, arg);
12925+ break;
12926+
12927+ default:
12928+ err = aufs_ioctl_dir(file, cmd, arg);
12929+ }
12930+
12931+ AuTraceErr(err);
12932+ return err;
12933+}
12934+
12935+#if 0 /* unused yet */
12936+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
12937+ unsigned long arg)
12938+{
12939+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
12940+}
12941+#endif
12942+#endif
12943diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
12944--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
12945+++ linux/fs/aufs/i_op_add.c 2010-10-21 09:52:43.090291764 +0200
12946@@ -0,0 +1,672 @@
4a4d8108
AM
12947+/*
12948+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12949+ *
12950+ * This program, aufs is free software; you can redistribute it and/or modify
12951+ * it under the terms of the GNU General Public License as published by
12952+ * the Free Software Foundation; either version 2 of the License, or
12953+ * (at your option) any later version.
12954+ *
12955+ * This program is distributed in the hope that it will be useful,
12956+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12957+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12958+ * GNU General Public License for more details.
12959+ *
12960+ * You should have received a copy of the GNU General Public License
12961+ * along with this program; if not, write to the Free Software
12962+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12963+ */
12964+
12965+/*
12966+ * inode operations (add entry)
12967+ */
12968+
12969+#include "aufs.h"
12970+
12971+/*
12972+ * final procedure of adding a new entry, except link(2).
12973+ * remove whiteout, instantiate, copyup the parent dir's times and size
12974+ * and update version.
12975+ * if it failed, re-create the removed whiteout.
12976+ */
12977+static int epilog(struct inode *dir, aufs_bindex_t bindex,
12978+ struct dentry *wh_dentry, struct dentry *dentry)
12979+{
12980+ int err, rerr;
12981+ aufs_bindex_t bwh;
12982+ struct path h_path;
12983+ struct inode *inode, *h_dir;
12984+ struct dentry *wh;
12985+
12986+ bwh = -1;
12987+ if (wh_dentry) {
12988+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
12989+ IMustLock(h_dir);
12990+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
12991+ bwh = au_dbwh(dentry);
12992+ h_path.dentry = wh_dentry;
12993+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
12994+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
12995+ dentry);
12996+ if (unlikely(err))
12997+ goto out;
12998+ }
12999+
13000+ inode = au_new_inode(dentry, /*must_new*/1);
13001+ if (!IS_ERR(inode)) {
13002+ d_instantiate(dentry, inode);
13003+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
13004+ IMustLock(dir);
13005+ if (au_ibstart(dir) == au_dbstart(dentry))
13006+ au_cpup_attr_timesizes(dir);
13007+ dir->i_version++;
13008+ return 0; /* success */
13009+ }
13010+
13011+ err = PTR_ERR(inode);
13012+ if (!wh_dentry)
13013+ goto out;
13014+
13015+ /* revert */
13016+ /* dir inode is locked */
13017+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
13018+ rerr = PTR_ERR(wh);
13019+ if (IS_ERR(wh)) {
13020+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
13021+ AuDLNPair(dentry), err, rerr);
13022+ err = -EIO;
13023+ } else
13024+ dput(wh);
13025+
4f0767ce 13026+out:
4a4d8108
AM
13027+ return err;
13028+}
13029+
13030+/*
13031+ * simple tests for the adding inode operations.
13032+ * following the checks in vfs, plus the parent-child relationship.
13033+ */
13034+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13035+ struct dentry *h_parent, int isdir)
13036+{
13037+ int err;
13038+ umode_t h_mode;
13039+ struct dentry *h_dentry;
13040+ struct inode *h_inode;
13041+
13042+ err = -ENAMETOOLONG;
13043+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13044+ goto out;
13045+
13046+ h_dentry = au_h_dptr(dentry, bindex);
13047+ h_inode = h_dentry->d_inode;
13048+ if (!dentry->d_inode) {
13049+ err = -EEXIST;
13050+ if (unlikely(h_inode))
13051+ goto out;
13052+ } else {
13053+ /* rename(2) case */
13054+ err = -EIO;
13055+ if (unlikely(!h_inode || !h_inode->i_nlink))
13056+ goto out;
13057+
13058+ h_mode = h_inode->i_mode;
13059+ if (!isdir) {
13060+ err = -EISDIR;
13061+ if (unlikely(S_ISDIR(h_mode)))
13062+ goto out;
13063+ } else if (unlikely(!S_ISDIR(h_mode))) {
13064+ err = -ENOTDIR;
13065+ goto out;
13066+ }
13067+ }
13068+
13069+ err = 0;
13070+ /* expected parent dir is locked */
13071+ if (unlikely(h_parent != h_dentry->d_parent))
13072+ err = -EIO;
13073+
4f0767ce 13074+out:
4a4d8108
AM
13075+ AuTraceErr(err);
13076+ return err;
13077+}
13078+
13079+/*
13080+ * initial procedure of adding a new entry.
13081+ * prepare writable branch and the parent dir, lock it,
13082+ * and lookup whiteout for the new entry.
13083+ */
13084+static struct dentry*
13085+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
13086+ struct dentry *src_dentry, struct au_pin *pin,
13087+ struct au_wr_dir_args *wr_dir_args)
13088+{
13089+ struct dentry *wh_dentry, *h_parent;
13090+ struct super_block *sb;
13091+ struct au_branch *br;
13092+ int err;
13093+ unsigned int udba;
13094+ aufs_bindex_t bcpup;
13095+
13096+ AuDbg("%.*s\n", AuDLNPair(dentry));
13097+
13098+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
13099+ bcpup = err;
13100+ wh_dentry = ERR_PTR(err);
13101+ if (unlikely(err < 0))
13102+ goto out;
13103+
13104+ sb = dentry->d_sb;
13105+ udba = au_opt_udba(sb);
13106+ err = au_pin(pin, dentry, bcpup, udba,
13107+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13108+ wh_dentry = ERR_PTR(err);
13109+ if (unlikely(err))
13110+ goto out;
13111+
13112+ h_parent = au_pinned_h_parent(pin);
13113+ if (udba != AuOpt_UDBA_NONE
13114+ && au_dbstart(dentry) == bcpup)
13115+ err = au_may_add(dentry, bcpup, h_parent,
13116+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
13117+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13118+ err = -ENAMETOOLONG;
13119+ wh_dentry = ERR_PTR(err);
13120+ if (unlikely(err))
13121+ goto out_unpin;
13122+
13123+ br = au_sbr(sb, bcpup);
13124+ if (dt) {
13125+ struct path tmp = {
13126+ .dentry = h_parent,
13127+ .mnt = br->br_mnt
13128+ };
13129+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
13130+ }
13131+
13132+ wh_dentry = NULL;
13133+ if (bcpup != au_dbwh(dentry))
13134+ goto out; /* success */
13135+
13136+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
13137+
4f0767ce 13138+out_unpin:
4a4d8108
AM
13139+ if (IS_ERR(wh_dentry))
13140+ au_unpin(pin);
4f0767ce 13141+out:
4a4d8108
AM
13142+ return wh_dentry;
13143+}
13144+
13145+/* ---------------------------------------------------------------------- */
13146+
13147+enum { Mknod, Symlink, Creat };
13148+struct simple_arg {
13149+ int type;
13150+ union {
13151+ struct {
13152+ int mode;
13153+ struct nameidata *nd;
13154+ } c;
13155+ struct {
13156+ const char *symname;
13157+ } s;
13158+ struct {
13159+ int mode;
13160+ dev_t dev;
13161+ } m;
13162+ } u;
13163+};
13164+
13165+static int add_simple(struct inode *dir, struct dentry *dentry,
13166+ struct simple_arg *arg)
13167+{
13168+ int err;
13169+ aufs_bindex_t bstart;
13170+ unsigned char created;
13171+ struct au_dtime dt;
13172+ struct au_pin pin;
13173+ struct path h_path;
13174+ struct dentry *wh_dentry, *parent;
13175+ struct inode *h_dir;
13176+ struct au_wr_dir_args wr_dir_args = {
13177+ .force_btgt = -1,
13178+ .flags = AuWrDir_ADD_ENTRY
13179+ };
13180+
13181+ AuDbg("%.*s\n", AuDLNPair(dentry));
13182+ IMustLock(dir);
13183+
13184+ parent = dentry->d_parent; /* dir inode is locked */
13185+ aufs_read_lock(dentry, AuLock_DW);
13186+ di_write_lock_parent(parent);
13187+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
13188+ &wr_dir_args);
13189+ err = PTR_ERR(wh_dentry);
13190+ if (IS_ERR(wh_dentry))
13191+ goto out;
13192+
13193+ bstart = au_dbstart(dentry);
13194+ h_path.dentry = au_h_dptr(dentry, bstart);
13195+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
13196+ h_dir = au_pinned_h_dir(&pin);
13197+ switch (arg->type) {
13198+ case Creat:
13199+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
13200+ break;
13201+ case Symlink:
13202+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
13203+ break;
13204+ case Mknod:
13205+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
13206+ break;
13207+ default:
13208+ BUG();
13209+ }
13210+ created = !err;
13211+ if (!err)
13212+ err = epilog(dir, bstart, wh_dentry, dentry);
13213+
13214+ /* revert */
13215+ if (unlikely(created && err && h_path.dentry->d_inode)) {
13216+ int rerr;
13217+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
13218+ if (rerr) {
13219+ AuIOErr("%.*s revert failure(%d, %d)\n",
13220+ AuDLNPair(dentry), err, rerr);
13221+ err = -EIO;
13222+ }
13223+ au_dtime_revert(&dt);
13224+ d_drop(dentry);
13225+ }
13226+
13227+ au_unpin(&pin);
13228+ dput(wh_dentry);
13229+
4f0767ce 13230+out:
4a4d8108
AM
13231+ if (unlikely(err)) {
13232+ au_update_dbstart(dentry);
13233+ d_drop(dentry);
13234+ }
13235+ di_write_unlock(parent);
13236+ aufs_read_unlock(dentry, AuLock_DW);
13237+ return err;
13238+}
13239+
13240+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
13241+{
13242+ struct simple_arg arg = {
13243+ .type = Mknod,
13244+ .u.m = {
13245+ .mode = mode,
13246+ .dev = dev
13247+ }
13248+ };
13249+ return add_simple(dir, dentry, &arg);
13250+}
13251+
13252+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
13253+{
13254+ struct simple_arg arg = {
13255+ .type = Symlink,
13256+ .u.s.symname = symname
13257+ };
13258+ return add_simple(dir, dentry, &arg);
13259+}
13260+
13261+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13262+ struct nameidata *nd)
13263+{
13264+ struct simple_arg arg = {
13265+ .type = Creat,
13266+ .u.c = {
13267+ .mode = mode,
13268+ .nd = nd
13269+ }
13270+ };
13271+ return add_simple(dir, dentry, &arg);
13272+}
13273+
13274+/* ---------------------------------------------------------------------- */
13275+
13276+struct au_link_args {
13277+ aufs_bindex_t bdst, bsrc;
13278+ struct au_pin pin;
13279+ struct path h_path;
13280+ struct dentry *src_parent, *parent;
13281+};
13282+
13283+static int au_cpup_before_link(struct dentry *src_dentry,
13284+ struct au_link_args *a)
13285+{
13286+ int err;
13287+ struct dentry *h_src_dentry;
13288+ struct mutex *h_mtx;
13289+ struct file *h_file;
13290+
13291+ di_read_lock_parent(a->src_parent, AuLock_IR);
13292+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
13293+ if (unlikely(err))
13294+ goto out;
13295+
13296+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
13297+ h_mtx = &h_src_dentry->d_inode->i_mutex;
13298+ err = au_pin(&a->pin, src_dentry, a->bdst,
13299+ au_opt_udba(src_dentry->d_sb),
13300+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13301+ if (unlikely(err))
13302+ goto out;
13303+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13304+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13305+ if (IS_ERR(h_file)) {
13306+ err = PTR_ERR(h_file);
13307+ h_file = NULL;
13308+ } else
13309+ err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
13310+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
13311+ mutex_unlock(h_mtx);
13312+ au_h_open_post(src_dentry, a->bsrc, h_file);
13313+ au_unpin(&a->pin);
13314+
4f0767ce 13315+out:
4a4d8108
AM
13316+ di_read_unlock(a->src_parent, AuLock_IR);
13317+ return err;
13318+}
13319+
13320+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
13321+{
13322+ int err;
13323+ unsigned char plink;
13324+ struct inode *h_inode, *inode;
13325+ struct dentry *h_src_dentry;
13326+ struct super_block *sb;
13327+ struct file *h_file;
13328+
13329+ plink = 0;
13330+ h_inode = NULL;
13331+ sb = src_dentry->d_sb;
13332+ inode = src_dentry->d_inode;
13333+ if (au_ibstart(inode) <= a->bdst)
13334+ h_inode = au_h_iptr(inode, a->bdst);
13335+ if (!h_inode || !h_inode->i_nlink) {
13336+ /* copyup src_dentry as the name of dentry. */
13337+ au_set_dbstart(src_dentry, a->bdst);
13338+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
13339+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
13340+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
13341+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13342+ if (IS_ERR(h_file)) {
13343+ err = PTR_ERR(h_file);
13344+ h_file = NULL;
13345+ } else
13346+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
13347+ -1, AuCpup_KEEPLINO,
13348+ a->parent);
13349+ mutex_unlock(&h_inode->i_mutex);
13350+ au_h_open_post(src_dentry, a->bsrc, h_file);
13351+ au_set_h_dptr(src_dentry, a->bdst, NULL);
13352+ au_set_dbstart(src_dentry, a->bsrc);
13353+ } else {
13354+ /* the inode of src_dentry already exists on a.bdst branch */
13355+ h_src_dentry = d_find_alias(h_inode);
13356+ if (!h_src_dentry && au_plink_test(inode)) {
13357+ plink = 1;
13358+ h_src_dentry = au_plink_lkup(inode, a->bdst);
13359+ err = PTR_ERR(h_src_dentry);
13360+ if (IS_ERR(h_src_dentry))
13361+ goto out;
13362+
13363+ if (unlikely(!h_src_dentry->d_inode)) {
13364+ dput(h_src_dentry);
13365+ h_src_dentry = NULL;
13366+ }
13367+
13368+ }
13369+ if (h_src_dentry) {
13370+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13371+ &a->h_path);
13372+ dput(h_src_dentry);
13373+ } else {
13374+ AuIOErr("no dentry found for hi%lu on b%d\n",
13375+ h_inode->i_ino, a->bdst);
13376+ err = -EIO;
13377+ }
13378+ }
13379+
13380+ if (!err && !plink)
13381+ au_plink_append(inode, a->bdst, a->h_path.dentry);
13382+
13383+out:
13384+ return err;
13385+}
13386+
13387+int aufs_link(struct dentry *src_dentry, struct inode *dir,
13388+ struct dentry *dentry)
13389+{
13390+ int err, rerr;
13391+ struct au_dtime dt;
13392+ struct au_link_args *a;
13393+ struct dentry *wh_dentry, *h_src_dentry;
13394+ struct inode *inode;
13395+ struct super_block *sb;
13396+ struct au_wr_dir_args wr_dir_args = {
13397+ /* .force_btgt = -1, */
13398+ .flags = AuWrDir_ADD_ENTRY
13399+ };
13400+
13401+ IMustLock(dir);
13402+ inode = src_dentry->d_inode;
13403+ IMustLock(inode);
13404+
13405+ err = -ENOENT;
13406+ if (unlikely(!inode->i_nlink))
13407+ goto out;
13408+
13409+ err = -ENOMEM;
13410+ a = kzalloc(sizeof(*a), GFP_NOFS);
13411+ if (unlikely(!a))
13412+ goto out;
13413+
13414+ a->parent = dentry->d_parent; /* dir inode is locked */
953406b4 13415+ aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
4a4d8108
AM
13416+ a->src_parent = dget_parent(src_dentry);
13417+ wr_dir_args.force_btgt = au_dbstart(src_dentry);
13418+
13419+ di_write_lock_parent(a->parent);
13420+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
13421+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
13422+ &wr_dir_args);
13423+ err = PTR_ERR(wh_dentry);
13424+ if (IS_ERR(wh_dentry))
13425+ goto out_unlock;
13426+
13427+ err = 0;
13428+ sb = dentry->d_sb;
13429+ a->bdst = au_dbstart(dentry);
13430+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
13431+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
13432+ a->bsrc = au_dbstart(src_dentry);
13433+ if (au_opt_test(au_mntflags(sb), PLINK)) {
13434+ if (a->bdst < a->bsrc
13435+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
13436+ err = au_cpup_or_link(src_dentry, a);
13437+ else {
13438+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13439+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13440+ &a->h_path);
13441+ }
13442+ } else {
13443+ /*
13444+ * copyup src_dentry to the branch we process,
13445+ * and then link(2) to it.
13446+ */
13447+ if (a->bdst < a->bsrc
13448+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
13449+ au_unpin(&a->pin);
13450+ di_write_unlock(a->parent);
13451+ err = au_cpup_before_link(src_dentry, a);
13452+ di_write_lock_parent(a->parent);
13453+ if (!err)
13454+ err = au_pin(&a->pin, dentry, a->bdst,
13455+ au_opt_udba(sb),
13456+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13457+ if (unlikely(err))
13458+ goto out_wh;
13459+ }
13460+ if (!err) {
13461+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13462+ err = -ENOENT;
13463+ if (h_src_dentry && h_src_dentry->d_inode)
13464+ err = vfsub_link(h_src_dentry,
13465+ au_pinned_h_dir(&a->pin),
13466+ &a->h_path);
13467+ }
13468+ }
13469+ if (unlikely(err))
13470+ goto out_unpin;
13471+
13472+ if (wh_dentry) {
13473+ a->h_path.dentry = wh_dentry;
13474+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
13475+ dentry);
13476+ if (unlikely(err))
13477+ goto out_revert;
13478+ }
13479+
13480+ dir->i_version++;
13481+ if (au_ibstart(dir) == au_dbstart(dentry))
13482+ au_cpup_attr_timesizes(dir);
13483+ inc_nlink(inode);
13484+ inode->i_ctime = dir->i_ctime;
13485+ if (!d_unhashed(a->h_path.dentry))
13486+ d_instantiate(dentry, au_igrab(inode));
13487+ else
13488+ /* some filesystem calls d_drop() */
13489+ d_drop(dentry);
13490+ goto out_unpin; /* success */
13491+
4f0767ce 13492+out_revert:
4a4d8108
AM
13493+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
13494+ if (!rerr)
13495+ goto out_dt;
13496+ AuIOErr("%.*s reverting failed(%d, %d)\n",
13497+ AuDLNPair(dentry), err, rerr);
13498+ err = -EIO;
4f0767ce 13499+out_dt:
4a4d8108
AM
13500+ d_drop(dentry);
13501+ au_dtime_revert(&dt);
4f0767ce 13502+out_unpin:
4a4d8108 13503+ au_unpin(&a->pin);
4f0767ce 13504+out_wh:
4a4d8108 13505+ dput(wh_dentry);
4f0767ce 13506+out_unlock:
4a4d8108
AM
13507+ if (unlikely(err)) {
13508+ au_update_dbstart(dentry);
13509+ d_drop(dentry);
13510+ }
13511+ di_write_unlock(a->parent);
13512+ dput(a->src_parent);
13513+ aufs_read_and_write_unlock2(dentry, src_dentry);
13514+ kfree(a);
4f0767ce 13515+out:
4a4d8108
AM
13516+ return err;
13517+}
13518+
13519+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
13520+{
13521+ int err, rerr;
13522+ aufs_bindex_t bindex;
13523+ unsigned char diropq;
13524+ struct path h_path;
13525+ struct dentry *wh_dentry, *parent, *opq_dentry;
13526+ struct mutex *h_mtx;
13527+ struct super_block *sb;
13528+ struct {
13529+ struct au_pin pin;
13530+ struct au_dtime dt;
13531+ } *a; /* reduce the stack usage */
13532+ struct au_wr_dir_args wr_dir_args = {
13533+ .force_btgt = -1,
13534+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
13535+ };
13536+
13537+ IMustLock(dir);
13538+
13539+ err = -ENOMEM;
13540+ a = kmalloc(sizeof(*a), GFP_NOFS);
13541+ if (unlikely(!a))
13542+ goto out;
13543+
13544+ aufs_read_lock(dentry, AuLock_DW);
13545+ parent = dentry->d_parent; /* dir inode is locked */
13546+ di_write_lock_parent(parent);
13547+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
13548+ &a->pin, &wr_dir_args);
13549+ err = PTR_ERR(wh_dentry);
13550+ if (IS_ERR(wh_dentry))
13551+ goto out_free;
13552+
13553+ sb = dentry->d_sb;
13554+ bindex = au_dbstart(dentry);
13555+ h_path.dentry = au_h_dptr(dentry, bindex);
13556+ h_path.mnt = au_sbr_mnt(sb, bindex);
13557+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
13558+ if (unlikely(err))
13559+ goto out_unlock;
13560+
13561+ /* make the dir opaque */
13562+ diropq = 0;
13563+ h_mtx = &h_path.dentry->d_inode->i_mutex;
13564+ if (wh_dentry
13565+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
13566+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13567+ opq_dentry = au_diropq_create(dentry, bindex);
13568+ mutex_unlock(h_mtx);
13569+ err = PTR_ERR(opq_dentry);
13570+ if (IS_ERR(opq_dentry))
13571+ goto out_dir;
13572+ dput(opq_dentry);
13573+ diropq = 1;
13574+ }
13575+
13576+ err = epilog(dir, bindex, wh_dentry, dentry);
13577+ if (!err) {
13578+ inc_nlink(dir);
13579+ goto out_unlock; /* success */
13580+ }
13581+
13582+ /* revert */
13583+ if (diropq) {
13584+ AuLabel(revert opq);
13585+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13586+ rerr = au_diropq_remove(dentry, bindex);
13587+ mutex_unlock(h_mtx);
13588+ if (rerr) {
13589+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
13590+ AuDLNPair(dentry), err, rerr);
13591+ err = -EIO;
13592+ }
13593+ }
13594+
4f0767ce 13595+out_dir:
4a4d8108
AM
13596+ AuLabel(revert dir);
13597+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
13598+ if (rerr) {
13599+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
13600+ AuDLNPair(dentry), err, rerr);
13601+ err = -EIO;
13602+ }
13603+ d_drop(dentry);
13604+ au_dtime_revert(&a->dt);
4f0767ce 13605+out_unlock:
4a4d8108
AM
13606+ au_unpin(&a->pin);
13607+ dput(wh_dentry);
4f0767ce 13608+out_free:
4a4d8108
AM
13609+ if (unlikely(err)) {
13610+ au_update_dbstart(dentry);
13611+ d_drop(dentry);
13612+ }
13613+ di_write_unlock(parent);
13614+ aufs_read_unlock(dentry, AuLock_DW);
13615+ kfree(a);
4f0767ce 13616+out:
4a4d8108
AM
13617+ return err;
13618+}
b752ccd1
AM
13619diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
13620--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
13621+++ linux/fs/aufs/i_op.c 2010-10-21 09:52:43.090291764 +0200
13622@@ -0,0 +1,911 @@
4a4d8108
AM
13623+/*
13624+ * Copyright (C) 2005-2010 Junjiro R. Okajima
13625+ *
13626+ * This program, aufs is free software; you can redistribute it and/or modify
13627+ * it under the terms of the GNU General Public License as published by
13628+ * the Free Software Foundation; either version 2 of the License, or
13629+ * (at your option) any later version.
13630+ *
13631+ * This program is distributed in the hope that it will be useful,
13632+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13633+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13634+ * GNU General Public License for more details.
13635+ *
13636+ * You should have received a copy of the GNU General Public License
13637+ * along with this program; if not, write to the Free Software
13638+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13639+ */
1facf9fc 13640+
1308ab2a 13641+/*
4a4d8108 13642+ * inode operations (except add/del/rename)
1308ab2a 13643+ */
4a4d8108
AM
13644+
13645+#include <linux/device_cgroup.h>
13646+#include <linux/fs_stack.h>
13647+#include <linux/mm.h>
13648+#include <linux/namei.h>
13649+#include <linux/security.h>
13650+#include <linux/uaccess.h>
13651+#include "aufs.h"
13652+
13653+static int h_permission(struct inode *h_inode, int mask,
13654+ struct vfsmount *h_mnt, int brperm)
1facf9fc 13655+{
1308ab2a 13656+ int err;
4a4d8108 13657+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 13658+
4a4d8108
AM
13659+ err = -EACCES;
13660+ if ((write_mask && IS_IMMUTABLE(h_inode))
13661+ || ((mask & MAY_EXEC)
13662+ && S_ISREG(h_inode->i_mode)
13663+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
13664+ || !(h_inode->i_mode & S_IXUGO))))
13665+ goto out;
13666+
13667+ /*
13668+ * - skip the lower fs test in the case of write to ro branch.
13669+ * - nfs dir permission write check is optimized, but a policy for
13670+ * link/rename requires a real check.
13671+ */
13672+ if ((write_mask && !au_br_writable(brperm))
13673+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
13674+ && write_mask && !(mask & MAY_READ))
13675+ || !h_inode->i_op->permission) {
13676+ /* AuLabel(generic_permission); */
13677+ err = generic_permission(h_inode, mask,
13678+ h_inode->i_op->check_acl);
1308ab2a 13679+ } else {
4a4d8108
AM
13680+ /* AuLabel(h_inode->permission); */
13681+ err = h_inode->i_op->permission(h_inode, mask);
13682+ AuTraceErr(err);
13683+ }
1facf9fc 13684+
4a4d8108
AM
13685+ if (!err)
13686+ err = devcgroup_inode_permission(h_inode, mask);
953406b4 13687+ if (!err)
4a4d8108 13688+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
13689+
13690+#if 0
13691+ if (!err) {
13692+ /* todo: do we need to call ima_path_check()? */
13693+ struct path h_path = {
13694+ .dentry =
13695+ .mnt = h_mnt
13696+ };
13697+ err = ima_path_check(&h_path,
13698+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
13699+ IMA_COUNT_LEAVE);
1308ab2a 13700+ }
4a4d8108 13701+#endif
dece6358 13702+
4f0767ce 13703+out:
1308ab2a 13704+ return err;
13705+}
dece6358 13706+
4a4d8108 13707+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 13708+{
13709+ int err;
4a4d8108
AM
13710+ aufs_bindex_t bindex, bend;
13711+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
13712+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
13713+ struct inode *h_inode;
13714+ struct super_block *sb;
13715+ struct au_branch *br;
1facf9fc 13716+
4a4d8108
AM
13717+ sb = inode->i_sb;
13718+ si_read_lock(sb, AuLock_FLUSH);
13719+ ii_read_lock_child(inode);
dece6358 13720+
4a4d8108
AM
13721+ if (!isdir || write_mask) {
13722+ err = au_busy_or_stale();
13723+ h_inode = au_h_iptr(inode, au_ibstart(inode));
13724+ if (unlikely(!h_inode
13725+ || (h_inode->i_mode & S_IFMT)
13726+ != (inode->i_mode & S_IFMT)))
13727+ goto out;
1facf9fc 13728+
4a4d8108
AM
13729+ err = 0;
13730+ bindex = au_ibstart(inode);
13731+ br = au_sbr(sb, bindex);
13732+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
13733+ if (write_mask
13734+ && !err
13735+ && !special_file(h_inode->i_mode)) {
13736+ /* test whether the upper writable branch exists */
13737+ err = -EROFS;
13738+ for (; bindex >= 0; bindex--)
13739+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
13740+ err = 0;
13741+ break;
13742+ }
13743+ }
13744+ goto out;
13745+ }
dece6358 13746+
4a4d8108 13747+ /* non-write to dir */
1308ab2a 13748+ err = 0;
4a4d8108
AM
13749+ bend = au_ibend(inode);
13750+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
13751+ h_inode = au_h_iptr(inode, bindex);
13752+ if (h_inode) {
13753+ err = au_busy_or_stale();
13754+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
13755+ break;
13756+
13757+ br = au_sbr(sb, bindex);
13758+ err = h_permission(h_inode, mask, br->br_mnt,
13759+ br->br_perm);
13760+ }
13761+ }
1308ab2a 13762+
4f0767ce 13763+out:
4a4d8108
AM
13764+ ii_read_unlock(inode);
13765+ si_read_unlock(sb);
1308ab2a 13766+ return err;
13767+}
13768+
4a4d8108 13769+/* ---------------------------------------------------------------------- */
1facf9fc 13770+
4a4d8108
AM
13771+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
13772+ struct nameidata *nd)
13773+{
13774+ struct dentry *ret, *parent;
b752ccd1 13775+ struct inode *inode;
4a4d8108
AM
13776+ struct super_block *sb;
13777+ int err, npositive;
dece6358 13778+
4a4d8108 13779+ IMustLock(dir);
1308ab2a 13780+
4a4d8108
AM
13781+ sb = dir->i_sb;
13782+ si_read_lock(sb, AuLock_FLUSH);
13783+ ret = ERR_PTR(-ENAMETOOLONG);
13784+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13785+ goto out;
13786+ err = au_di_init(dentry);
13787+ ret = ERR_PTR(err);
13788+ if (unlikely(err))
13789+ goto out;
1308ab2a 13790+
4a4d8108
AM
13791+ parent = dentry->d_parent; /* dir inode is locked */
13792+ di_read_lock_parent(parent, AuLock_IR);
13793+ npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
13794+ di_read_unlock(parent, AuLock_IR);
13795+ err = npositive;
13796+ ret = ERR_PTR(err);
13797+ if (unlikely(err < 0))
13798+ goto out_unlock;
1308ab2a 13799+
4a4d8108
AM
13800+ inode = NULL;
13801+ if (npositive) {
b752ccd1 13802+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 13803+ ret = (void *)inode;
1facf9fc 13804+ }
4a4d8108
AM
13805+ if (IS_ERR(inode))
13806+ goto out_unlock;
13807+
13808+ ret = d_splice_alias(inode, dentry);
13809+ if (unlikely(IS_ERR(ret) && inode))
13810+ ii_write_unlock(inode);
1facf9fc 13811+
4f0767ce 13812+out_unlock:
4a4d8108 13813+ di_write_unlock(dentry);
4f0767ce 13814+out:
4a4d8108
AM
13815+ si_read_unlock(sb);
13816+ return ret;
13817+}
1facf9fc 13818+
4a4d8108 13819+/* ---------------------------------------------------------------------- */
1facf9fc 13820+
4a4d8108
AM
13821+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
13822+ const unsigned char add_entry, aufs_bindex_t bcpup,
13823+ aufs_bindex_t bstart)
13824+{
13825+ int err;
13826+ struct dentry *h_parent;
13827+ struct inode *h_dir;
1facf9fc 13828+
4a4d8108
AM
13829+ if (add_entry) {
13830+ au_update_dbstart(dentry);
13831+ IMustLock(parent->d_inode);
13832+ } else
13833+ di_write_lock_parent(parent);
13834+
13835+ err = 0;
13836+ if (!au_h_dptr(parent, bcpup)) {
13837+ if (bstart < bcpup)
13838+ err = au_cpdown_dirs(dentry, bcpup);
13839+ else
13840+ err = au_cpup_dirs(dentry, bcpup);
13841+ }
13842+ if (!err && add_entry) {
13843+ h_parent = au_h_dptr(parent, bcpup);
13844+ h_dir = h_parent->d_inode;
13845+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
13846+ err = au_lkup_neg(dentry, bcpup);
13847+ /* todo: no unlock here */
13848+ mutex_unlock(&h_dir->i_mutex);
13849+ if (bstart < bcpup && au_dbstart(dentry) < 0) {
13850+ au_set_dbstart(dentry, 0);
13851+ au_update_dbrange(dentry, /*do_put_zero*/0);
13852+ }
1308ab2a 13853+ }
1facf9fc 13854+
4a4d8108
AM
13855+ if (!add_entry)
13856+ di_write_unlock(parent);
13857+ if (!err)
13858+ err = bcpup; /* success */
1308ab2a 13859+
4a4d8108
AM
13860+ return err;
13861+}
1facf9fc 13862+
4a4d8108
AM
13863+/*
13864+ * decide the branch and the parent dir where we will create a new entry.
13865+ * returns new bindex or an error.
13866+ * copyup the parent dir if needed.
13867+ */
13868+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
13869+ struct au_wr_dir_args *args)
13870+{
13871+ int err;
13872+ aufs_bindex_t bcpup, bstart, src_bstart;
13873+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
13874+ ADD_ENTRY);
13875+ struct super_block *sb;
13876+ struct dentry *parent;
13877+ struct au_sbinfo *sbinfo;
1facf9fc 13878+
4a4d8108
AM
13879+ sb = dentry->d_sb;
13880+ sbinfo = au_sbi(sb);
13881+ parent = dget_parent(dentry);
13882+ bstart = au_dbstart(dentry);
13883+ bcpup = bstart;
13884+ if (args->force_btgt < 0) {
13885+ if (src_dentry) {
13886+ src_bstart = au_dbstart(src_dentry);
13887+ if (src_bstart < bstart)
13888+ bcpup = src_bstart;
13889+ } else if (add_entry) {
13890+ err = AuWbrCreate(sbinfo, dentry,
13891+ au_ftest_wrdir(args->flags, ISDIR));
13892+ bcpup = err;
13893+ }
1facf9fc 13894+
4a4d8108
AM
13895+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
13896+ if (add_entry)
13897+ err = AuWbrCopyup(sbinfo, dentry);
13898+ else {
13899+ if (!IS_ROOT(dentry)) {
13900+ di_read_lock_parent(parent, !AuLock_IR);
13901+ err = AuWbrCopyup(sbinfo, dentry);
13902+ di_read_unlock(parent, !AuLock_IR);
13903+ } else
13904+ err = AuWbrCopyup(sbinfo, dentry);
13905+ }
13906+ bcpup = err;
13907+ if (unlikely(err < 0))
13908+ goto out;
13909+ }
13910+ } else {
13911+ bcpup = args->force_btgt;
13912+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 13913+ }
4a4d8108
AM
13914+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
13915+ err = bcpup;
13916+ if (bcpup == bstart)
13917+ goto out; /* success */
13918+ else if (bstart < bcpup)
13919+ au_update_dbrange(dentry, /*do_put_zero*/1);
13920+
13921+ /* copyup the new parent into the branch we process */
13922+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
13923+
4f0767ce 13924+out:
4a4d8108 13925+ dput(parent);
dece6358
AM
13926+ return err;
13927+}
1facf9fc 13928+
1308ab2a 13929+/* ---------------------------------------------------------------------- */
13930+
4a4d8108 13931+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 13932+{
4a4d8108
AM
13933+ if (pin && pin->parent)
13934+ return au_h_dptr(pin->parent, pin->bindex);
13935+ return NULL;
dece6358 13936+}
1facf9fc 13937+
4a4d8108 13938+void au_unpin(struct au_pin *p)
dece6358 13939+{
953406b4 13940+ if (au_ftest_pin(p->flags, MNT_WRITE))
4a4d8108
AM
13941+ mnt_drop_write(p->h_mnt);
13942+ if (!p->hdir)
13943+ return;
1facf9fc 13944+
4a4d8108
AM
13945+ au_hn_imtx_unlock(p->hdir);
13946+ if (!au_ftest_pin(p->flags, DI_LOCKED))
13947+ di_read_unlock(p->parent, AuLock_IR);
13948+ iput(p->hdir->hi_inode);
13949+ dput(p->parent);
13950+ p->parent = NULL;
13951+ p->hdir = NULL;
13952+ p->h_mnt = NULL;
13953+}
1308ab2a 13954+
4a4d8108
AM
13955+int au_do_pin(struct au_pin *p)
13956+{
13957+ int err;
13958+ struct super_block *sb;
13959+ struct dentry *h_dentry, *h_parent;
13960+ struct au_branch *br;
13961+ struct inode *h_dir;
13962+
13963+ err = 0;
13964+ sb = p->dentry->d_sb;
13965+ br = au_sbr(sb, p->bindex);
13966+ if (IS_ROOT(p->dentry)) {
13967+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
13968+ p->h_mnt = br->br_mnt;
13969+ err = mnt_want_write(p->h_mnt);
13970+ if (unlikely(err)) {
13971+ au_fclr_pin(p->flags, MNT_WRITE);
13972+ goto out_err;
13973+ }
13974+ }
dece6358 13975+ goto out;
1facf9fc 13976+ }
13977+
4a4d8108
AM
13978+ h_dentry = NULL;
13979+ if (p->bindex <= au_dbend(p->dentry))
13980+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 13981+
4a4d8108
AM
13982+ p->parent = dget_parent(p->dentry);
13983+ if (!au_ftest_pin(p->flags, DI_LOCKED))
13984+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 13985+
4a4d8108
AM
13986+ h_dir = NULL;
13987+ h_parent = au_h_dptr(p->parent, p->bindex);
13988+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
13989+ if (p->hdir)
13990+ h_dir = p->hdir->hi_inode;
dece6358 13991+
b752ccd1
AM
13992+ /*
13993+ * udba case, or
13994+ * if DI_LOCKED is not set, then p->parent may be different
13995+ * and h_parent can be NULL.
13996+ */
13997+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
4a4d8108
AM
13998+ if (!au_ftest_pin(p->flags, DI_LOCKED))
13999+ di_read_unlock(p->parent, AuLock_IR);
14000+ dput(p->parent);
14001+ p->parent = NULL;
14002+ goto out_err;
14003+ }
1308ab2a 14004+
4a4d8108
AM
14005+ au_igrab(h_dir);
14006+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 14007+
4a4d8108
AM
14008+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
14009+ err = -EBUSY;
14010+ goto out_unpin;
14011+ }
14012+ if (h_dentry) {
14013+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
14014+ if (unlikely(err)) {
14015+ au_fclr_pin(p->flags, MNT_WRITE);
14016+ goto out_unpin;
14017+ }
1facf9fc 14018+ }
dece6358 14019+
4a4d8108
AM
14020+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14021+ p->h_mnt = br->br_mnt;
14022+ err = mnt_want_write(p->h_mnt);
dece6358 14023+ if (unlikely(err)) {
4a4d8108
AM
14024+ au_fclr_pin(p->flags, MNT_WRITE);
14025+ goto out_unpin;
dece6358
AM
14026+ }
14027+ }
4a4d8108
AM
14028+ goto out; /* success */
14029+
4f0767ce 14030+out_unpin:
4a4d8108 14031+ au_unpin(p);
4f0767ce 14032+out_err:
4a4d8108
AM
14033+ pr_err("err %d\n", err);
14034+ err = au_busy_or_stale();
4f0767ce 14035+out:
1facf9fc 14036+ return err;
14037+}
14038+
4a4d8108
AM
14039+void au_pin_init(struct au_pin *p, struct dentry *dentry,
14040+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14041+ unsigned int udba, unsigned char flags)
14042+{
14043+ p->dentry = dentry;
14044+ p->udba = udba;
14045+ p->lsc_di = lsc_di;
14046+ p->lsc_hi = lsc_hi;
14047+ p->flags = flags;
14048+ p->bindex = bindex;
14049+
14050+ p->parent = NULL;
14051+ p->hdir = NULL;
14052+ p->h_mnt = NULL;
14053+}
14054+
14055+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14056+ unsigned int udba, unsigned char flags)
14057+{
14058+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
14059+ udba, flags);
14060+ return au_do_pin(pin);
14061+}
14062+
dece6358
AM
14063+/* ---------------------------------------------------------------------- */
14064+
1308ab2a 14065+/*
4a4d8108
AM
14066+ * ->setattr() and ->getattr() are called in various cases.
14067+ * chmod, stat: dentry is revalidated.
14068+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
14069+ * unhashed.
14070+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 14071+ */
4a4d8108 14072+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 14073+{
4a4d8108
AM
14074+ int err;
14075+ struct inode *inode;
14076+ struct dentry *parent;
1facf9fc 14077+
1308ab2a 14078+ err = 0;
4a4d8108
AM
14079+ inode = dentry->d_inode;
14080+ if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
14081+ parent = dget_parent(dentry);
14082+ di_read_lock_parent(parent, AuLock_IR);
14083+ /* returns a number of positive dentries */
14084+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
14085+ if (err >= 0)
14086+ err = au_refresh_hinode(inode, dentry);
14087+ di_read_unlock(parent, AuLock_IR);
14088+ dput(parent);
dece6358 14089+ }
1facf9fc 14090+
4a4d8108 14091+ AuTraceErr(err);
1308ab2a 14092+ return err;
14093+}
dece6358 14094+
4a4d8108
AM
14095+#define AuIcpup_DID_CPUP 1
14096+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
14097+#define au_fset_icpup(flags, name) { (flags) |= AuIcpup_##name; }
14098+#define au_fclr_icpup(flags, name) { (flags) &= ~AuIcpup_##name; }
1308ab2a 14099+
4a4d8108
AM
14100+struct au_icpup_args {
14101+ unsigned char flags;
14102+ unsigned char pin_flags;
14103+ aufs_bindex_t btgt;
14104+ unsigned int udba;
14105+ struct au_pin pin;
14106+ struct path h_path;
14107+ struct inode *h_inode;
14108+};
1308ab2a 14109+
4a4d8108
AM
14110+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
14111+ struct au_icpup_args *a)
1308ab2a 14112+{
14113+ int err;
4a4d8108 14114+ loff_t sz;
953406b4 14115+ aufs_bindex_t bstart;
4a4d8108
AM
14116+ struct dentry *hi_wh, *parent;
14117+ struct inode *inode;
14118+ struct file *h_file;
14119+ struct au_wr_dir_args wr_dir_args = {
14120+ .force_btgt = -1,
14121+ .flags = 0
14122+ };
14123+
14124+ bstart = au_dbstart(dentry);
14125+ inode = dentry->d_inode;
14126+ if (S_ISDIR(inode->i_mode))
14127+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
14128+ /* plink or hi_wh() case */
953406b4
AM
14129+ if (bstart != au_ibstart(inode))
14130+ wr_dir_args.force_btgt = au_ibstart(inode);
4a4d8108
AM
14131+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
14132+ if (unlikely(err < 0))
14133+ goto out;
14134+ a->btgt = err;
14135+ if (err != bstart)
14136+ au_fset_icpup(a->flags, DID_CPUP);
14137+
14138+ err = 0;
14139+ a->pin_flags = AuPin_MNT_WRITE;
14140+ parent = NULL;
14141+ if (!IS_ROOT(dentry)) {
14142+ au_fset_pin(a->pin_flags, DI_LOCKED);
14143+ parent = dget_parent(dentry);
14144+ di_write_lock_parent(parent);
14145+ }
14146+
14147+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
14148+ if (unlikely(err))
14149+ goto out_parent;
14150+
14151+ a->h_path.dentry = au_h_dptr(dentry, bstart);
14152+ a->h_inode = a->h_path.dentry->d_inode;
14153+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14154+ sz = -1;
14155+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
14156+ sz = ia->ia_size;
14157+
14158+ h_file = NULL;
14159+ hi_wh = NULL;
14160+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
14161+ hi_wh = au_hi_wh(inode, a->btgt);
14162+ if (!hi_wh) {
14163+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
14164+ if (unlikely(err))
14165+ goto out_unlock;
14166+ hi_wh = au_hi_wh(inode, a->btgt);
14167+ /* todo: revalidate hi_wh? */
14168+ }
14169+ }
14170+
14171+ if (parent) {
14172+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14173+ di_downgrade_lock(parent, AuLock_IR);
14174+ dput(parent);
14175+ parent = NULL;
14176+ }
14177+ if (!au_ftest_icpup(a->flags, DID_CPUP))
14178+ goto out; /* success */
14179+
14180+ if (!d_unhashed(dentry)) {
14181+ h_file = au_h_open_pre(dentry, bstart);
14182+ if (IS_ERR(h_file)) {
14183+ err = PTR_ERR(h_file);
14184+ h_file = NULL;
14185+ } else
14186+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
14187+ AuCpup_DTIME);
14188+ if (!err)
14189+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14190+ } else if (!hi_wh)
14191+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14192+ else
14193+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 14194+
4f0767ce 14195+out_unlock:
4a4d8108
AM
14196+ mutex_unlock(&a->h_inode->i_mutex);
14197+ au_h_open_post(dentry, bstart, h_file);
14198+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 14199+ if (!err) {
4a4d8108 14200+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 14201+ goto out; /* success */
1facf9fc 14202+ }
dece6358 14203+
4a4d8108 14204+ au_unpin(&a->pin);
4f0767ce 14205+out_parent:
4a4d8108
AM
14206+ if (parent) {
14207+ di_write_unlock(parent);
14208+ dput(parent);
14209+ }
4f0767ce 14210+out:
1facf9fc 14211+ return err;
14212+}
14213+
4a4d8108 14214+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 14215+{
4a4d8108
AM
14216+ int err;
14217+ struct inode *inode;
14218+ struct super_block *sb;
14219+ struct file *file;
14220+ struct au_icpup_args *a;
1facf9fc 14221+
4a4d8108
AM
14222+ inode = dentry->d_inode;
14223+ IMustLock(inode);
dece6358 14224+
4a4d8108
AM
14225+ err = -ENOMEM;
14226+ a = kzalloc(sizeof(*a), GFP_NOFS);
14227+ if (unlikely(!a))
14228+ goto out;
1facf9fc 14229+
4a4d8108
AM
14230+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
14231+ ia->ia_valid &= ~ATTR_MODE;
dece6358 14232+
4a4d8108
AM
14233+ file = NULL;
14234+ sb = dentry->d_sb;
953406b4 14235+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108
AM
14236+ if (ia->ia_valid & ATTR_FILE) {
14237+ /* currently ftruncate(2) only */
14238+ AuDebugOn(!S_ISREG(inode->i_mode));
14239+ file = ia->ia_file;
14240+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
14241+ if (unlikely(err))
14242+ goto out_si;
14243+ ia->ia_file = au_hf_top(file);
14244+ a->udba = AuOpt_UDBA_NONE;
14245+ } else {
14246+ /* fchmod() doesn't pass ia_file */
14247+ a->udba = au_opt_udba(sb);
14248+ if (d_unhashed(dentry))
14249+ a->udba = AuOpt_UDBA_NONE;
14250+ di_write_lock_child(dentry);
14251+ if (a->udba != AuOpt_UDBA_NONE) {
14252+ AuDebugOn(IS_ROOT(dentry));
14253+ err = au_reval_for_attr(dentry, au_sigen(sb));
14254+ if (unlikely(err))
14255+ goto out_dentry;
14256+ }
dece6358 14257+ }
dece6358 14258+
4a4d8108
AM
14259+ err = au_pin_and_icpup(dentry, ia, a);
14260+ if (unlikely(err < 0))
14261+ goto out_dentry;
14262+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
14263+ ia->ia_file = NULL;
14264+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 14265+ }
dece6358 14266+
4a4d8108
AM
14267+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
14268+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
14269+ == (ATTR_MODE | ATTR_CTIME)) {
14270+ err = security_path_chmod(a->h_path.dentry, a->h_path.mnt,
14271+ ia->ia_mode);
14272+ if (unlikely(err))
14273+ goto out_unlock;
14274+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
14275+ && (ia->ia_valid & ATTR_CTIME)) {
14276+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
14277+ if (unlikely(err))
14278+ goto out_unlock;
14279+ }
dece6358 14280+
4a4d8108
AM
14281+ if (ia->ia_valid & ATTR_SIZE) {
14282+ struct file *f;
1308ab2a 14283+
953406b4 14284+ if (ia->ia_size < i_size_read(inode))
4a4d8108 14285+ /* unmap only */
953406b4 14286+ truncate_setsize(inode, ia->ia_size);
1308ab2a 14287+
4a4d8108
AM
14288+ f = NULL;
14289+ if (ia->ia_valid & ATTR_FILE)
14290+ f = ia->ia_file;
14291+ mutex_unlock(&a->h_inode->i_mutex);
14292+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
14293+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14294+ } else
14295+ err = vfsub_notify_change(&a->h_path, ia);
14296+ if (!err)
14297+ au_cpup_attr_changeable(inode);
1308ab2a 14298+
4f0767ce 14299+out_unlock:
4a4d8108
AM
14300+ mutex_unlock(&a->h_inode->i_mutex);
14301+ au_unpin(&a->pin);
4f0767ce 14302+out_dentry:
4a4d8108
AM
14303+ di_write_unlock(dentry);
14304+ if (file) {
14305+ fi_write_unlock(file);
14306+ ia->ia_file = file;
14307+ ia->ia_valid |= ATTR_FILE;
14308+ }
4f0767ce 14309+out_si:
4a4d8108
AM
14310+ si_read_unlock(sb);
14311+ kfree(a);
4f0767ce 14312+out:
4a4d8108
AM
14313+ AuTraceErr(err);
14314+ return err;
1facf9fc 14315+}
14316+
4a4d8108
AM
14317+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
14318+ unsigned int nlink)
1facf9fc 14319+{
4a4d8108
AM
14320+ inode->i_mode = st->mode;
14321+ inode->i_uid = st->uid;
14322+ inode->i_gid = st->gid;
14323+ inode->i_atime = st->atime;
14324+ inode->i_mtime = st->mtime;
14325+ inode->i_ctime = st->ctime;
1facf9fc 14326+
4a4d8108
AM
14327+ au_cpup_attr_nlink(inode, /*force*/0);
14328+ if (S_ISDIR(inode->i_mode)) {
14329+ inode->i_nlink -= nlink;
14330+ inode->i_nlink += st->nlink;
14331+ }
1facf9fc 14332+
4a4d8108
AM
14333+ spin_lock(&inode->i_lock);
14334+ inode->i_blocks = st->blocks;
14335+ i_size_write(inode, st->size);
14336+ spin_unlock(&inode->i_lock);
1facf9fc 14337+}
14338+
4a4d8108
AM
14339+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
14340+ struct dentry *dentry, struct kstat *st)
1facf9fc 14341+{
4a4d8108
AM
14342+ int err;
14343+ unsigned int mnt_flags;
14344+ aufs_bindex_t bindex;
14345+ unsigned char udba_none, positive;
14346+ struct super_block *sb, *h_sb;
14347+ struct inode *inode;
14348+ struct vfsmount *h_mnt;
14349+ struct dentry *h_dentry;
1facf9fc 14350+
4a4d8108
AM
14351+ err = 0;
14352+ sb = dentry->d_sb;
14353+ inode = dentry->d_inode;
953406b4 14354+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108
AM
14355+ mnt_flags = au_mntflags(sb);
14356+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 14357+
4a4d8108
AM
14358+ /* support fstat(2) */
14359+ if (!d_unhashed(dentry) && !udba_none) {
14360+ unsigned int sigen = au_sigen(sb);
14361+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
14362+ di_read_lock_child(dentry, AuLock_IR);
14363+ else {
14364+ AuDebugOn(IS_ROOT(dentry));
14365+ di_write_lock_child(dentry);
14366+ err = au_reval_for_attr(dentry, sigen);
14367+ di_downgrade_lock(dentry, AuLock_IR);
14368+ if (unlikely(err))
14369+ goto out;
14370+ }
14371+ } else
14372+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 14373+
4a4d8108
AM
14374+ bindex = au_ibstart(inode);
14375+ h_mnt = au_sbr_mnt(sb, bindex);
14376+ h_sb = h_mnt->mnt_sb;
14377+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
14378+ goto out_fill; /* success */
1facf9fc 14379+
4a4d8108
AM
14380+ h_dentry = NULL;
14381+ if (au_dbstart(dentry) == bindex)
14382+ h_dentry = dget(au_h_dptr(dentry, bindex));
14383+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
14384+ h_dentry = au_plink_lkup(inode, bindex);
14385+ if (IS_ERR(h_dentry))
14386+ goto out_fill; /* pretending success */
14387+ }
14388+ /* illegally overlapped or something */
14389+ if (unlikely(!h_dentry))
14390+ goto out_fill; /* pretending success */
14391+
14392+ positive = !!h_dentry->d_inode;
14393+ if (positive)
14394+ err = vfs_getattr(h_mnt, h_dentry, st);
14395+ dput(h_dentry);
14396+ if (!err) {
14397+ if (positive)
14398+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
14399+ goto out_fill; /* success */
1facf9fc 14400+ }
4a4d8108
AM
14401+ goto out;
14402+
4f0767ce 14403+out_fill:
4a4d8108 14404+ generic_fillattr(inode, st);
4f0767ce 14405+out:
4a4d8108
AM
14406+ di_read_unlock(dentry, AuLock_IR);
14407+ si_read_unlock(sb);
14408+ return err;
1facf9fc 14409+}
14410+
14411+/* ---------------------------------------------------------------------- */
14412+
4a4d8108
AM
14413+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
14414+ int bufsiz)
1facf9fc 14415+{
14416+ int err;
4a4d8108
AM
14417+ struct super_block *sb;
14418+ struct dentry *h_dentry;
1facf9fc 14419+
4a4d8108
AM
14420+ err = -EINVAL;
14421+ h_dentry = au_h_dptr(dentry, bindex);
14422+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
14423+ goto out;
1facf9fc 14424+
4a4d8108
AM
14425+ err = security_inode_readlink(h_dentry);
14426+ if (unlikely(err))
dece6358 14427+ goto out;
1facf9fc 14428+
4a4d8108
AM
14429+ sb = dentry->d_sb;
14430+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
14431+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
14432+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 14433+ }
4a4d8108 14434+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 14435+
4f0767ce 14436+out:
4a4d8108
AM
14437+ return err;
14438+}
1facf9fc 14439+
4a4d8108
AM
14440+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
14441+{
14442+ int err;
1facf9fc 14443+
4a4d8108
AM
14444+ aufs_read_lock(dentry, AuLock_IR);
14445+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
14446+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14447+
4a4d8108
AM
14448+ return err;
14449+}
1facf9fc 14450+
4a4d8108
AM
14451+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
14452+{
14453+ int err;
4a4d8108 14454+ mm_segment_t old_fs;
b752ccd1
AM
14455+ union {
14456+ char *k;
14457+ char __user *u;
14458+ } buf;
1facf9fc 14459+
4a4d8108 14460+ err = -ENOMEM;
b752ccd1
AM
14461+ buf.k = __getname_gfp(GFP_NOFS);
14462+ if (unlikely(!buf.k))
4a4d8108 14463+ goto out;
1facf9fc 14464+
4a4d8108
AM
14465+ aufs_read_lock(dentry, AuLock_IR);
14466+ old_fs = get_fs();
14467+ set_fs(KERNEL_DS);
b752ccd1 14468+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
4a4d8108
AM
14469+ set_fs(old_fs);
14470+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14471+
4a4d8108 14472+ if (err >= 0) {
b752ccd1 14473+ buf.k[err] = 0;
4a4d8108 14474+ /* will be freed by put_link */
b752ccd1 14475+ nd_set_link(nd, buf.k);
4a4d8108 14476+ return NULL; /* success */
1308ab2a 14477+ }
b752ccd1 14478+ __putname(buf.k);
1facf9fc 14479+
4f0767ce 14480+out:
4a4d8108
AM
14481+ path_put(&nd->path);
14482+ AuTraceErr(err);
14483+ return ERR_PTR(err);
14484+}
1facf9fc 14485+
4a4d8108
AM
14486+static void aufs_put_link(struct dentry *dentry __maybe_unused,
14487+ struct nameidata *nd, void *cookie __maybe_unused)
14488+{
14489+ __putname(nd_get_link(nd));
14490+}
1facf9fc 14491+
4a4d8108 14492+/* ---------------------------------------------------------------------- */
1facf9fc 14493+
4a4d8108
AM
14494+static void aufs_truncate_range(struct inode *inode __maybe_unused,
14495+ loff_t start __maybe_unused,
14496+ loff_t end __maybe_unused)
14497+{
14498+ AuUnsupport();
14499+}
1facf9fc 14500+
4a4d8108 14501+/* ---------------------------------------------------------------------- */
1308ab2a 14502+
4a4d8108
AM
14503+struct inode_operations aufs_symlink_iop = {
14504+ .permission = aufs_permission,
14505+ .setattr = aufs_setattr,
14506+ .getattr = aufs_getattr,
14507+ .readlink = aufs_readlink,
14508+ .follow_link = aufs_follow_link,
14509+ .put_link = aufs_put_link
14510+};
14511+
14512+struct inode_operations aufs_dir_iop = {
14513+ .create = aufs_create,
14514+ .lookup = aufs_lookup,
14515+ .link = aufs_link,
14516+ .unlink = aufs_unlink,
14517+ .symlink = aufs_symlink,
14518+ .mkdir = aufs_mkdir,
14519+ .rmdir = aufs_rmdir,
14520+ .mknod = aufs_mknod,
14521+ .rename = aufs_rename,
14522+
14523+ .permission = aufs_permission,
14524+ .setattr = aufs_setattr,
14525+ .getattr = aufs_getattr
14526+};
14527+
14528+struct inode_operations aufs_iop = {
14529+ .permission = aufs_permission,
14530+ .setattr = aufs_setattr,
14531+ .getattr = aufs_getattr,
14532+ .truncate_range = aufs_truncate_range
14533+};
b752ccd1
AM
14534diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
14535--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
953406b4 14536+++ linux/fs/aufs/i_op_del.c 2010-10-21 09:52:43.090291764 +0200
4a4d8108 14537@@ -0,0 +1,472 @@
1facf9fc 14538+/*
4a4d8108 14539+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 14540+ *
14541+ * This program, aufs is free software; you can redistribute it and/or modify
14542+ * it under the terms of the GNU General Public License as published by
14543+ * the Free Software Foundation; either version 2 of the License, or
14544+ * (at your option) any later version.
dece6358
AM
14545+ *
14546+ * This program is distributed in the hope that it will be useful,
14547+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14548+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14549+ * GNU General Public License for more details.
14550+ *
14551+ * You should have received a copy of the GNU General Public License
14552+ * along with this program; if not, write to the Free Software
14553+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14554+ */
14555+
14556+/*
4a4d8108 14557+ * inode operations (del entry)
1308ab2a 14558+ */
dece6358 14559+
1308ab2a 14560+#include "aufs.h"
dece6358 14561+
4a4d8108
AM
14562+/*
14563+ * decide if a new whiteout for @dentry is necessary or not.
14564+ * when it is necessary, prepare the parent dir for the upper branch whose
14565+ * branch index is @bcpup for creation. the actual creation of the whiteout will
14566+ * be done by caller.
14567+ * return value:
14568+ * 0: wh is unnecessary
14569+ * plus: wh is necessary
14570+ * minus: error
14571+ */
14572+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 14573+{
4a4d8108
AM
14574+ int need_wh, err;
14575+ aufs_bindex_t bstart;
14576+ struct super_block *sb;
dece6358 14577+
4a4d8108
AM
14578+ sb = dentry->d_sb;
14579+ bstart = au_dbstart(dentry);
14580+ if (*bcpup < 0) {
14581+ *bcpup = bstart;
14582+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
14583+ err = AuWbrCopyup(au_sbi(sb), dentry);
14584+ *bcpup = err;
14585+ if (unlikely(err < 0))
14586+ goto out;
14587+ }
14588+ } else
14589+ AuDebugOn(bstart < *bcpup
14590+ || au_test_ro(sb, *bcpup, dentry->d_inode));
14591+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 14592+
4a4d8108
AM
14593+ if (*bcpup != bstart) {
14594+ err = au_cpup_dirs(dentry, *bcpup);
14595+ if (unlikely(err))
14596+ goto out;
14597+ need_wh = 1;
14598+ } else {
14599+ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
14600+
14601+ old_bend = au_dbend(dentry);
14602+ if (isdir) {
14603+ bdiropq = au_dbdiropq(dentry);
14604+ au_set_dbdiropq(dentry, -1);
14605+ }
14606+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
14607+ /*nd*/NULL);
14608+ err = need_wh;
14609+ if (isdir)
14610+ au_set_dbdiropq(dentry, bdiropq);
14611+ if (unlikely(err < 0))
14612+ goto out;
14613+ new_bend = au_dbend(dentry);
14614+ if (!need_wh && old_bend != new_bend) {
14615+ au_set_h_dptr(dentry, new_bend, NULL);
14616+ au_set_dbend(dentry, old_bend);
14617+ }
14618+ }
14619+ AuDbg("need_wh %d\n", need_wh);
14620+ err = need_wh;
14621+
4f0767ce 14622+out:
4a4d8108 14623+ return err;
1facf9fc 14624+}
14625+
4a4d8108
AM
14626+/*
14627+ * simple tests for the del-entry operations.
14628+ * following the checks in vfs, plus the parent-child relationship.
14629+ */
14630+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14631+ struct dentry *h_parent, int isdir)
1facf9fc 14632+{
4a4d8108
AM
14633+ int err;
14634+ umode_t h_mode;
14635+ struct dentry *h_dentry, *h_latest;
1308ab2a 14636+ struct inode *h_inode;
1facf9fc 14637+
4a4d8108
AM
14638+ h_dentry = au_h_dptr(dentry, bindex);
14639+ h_inode = h_dentry->d_inode;
14640+ if (dentry->d_inode) {
14641+ err = -ENOENT;
14642+ if (unlikely(!h_inode || !h_inode->i_nlink))
14643+ goto out;
1facf9fc 14644+
4a4d8108
AM
14645+ h_mode = h_inode->i_mode;
14646+ if (!isdir) {
14647+ err = -EISDIR;
14648+ if (unlikely(S_ISDIR(h_mode)))
14649+ goto out;
14650+ } else if (unlikely(!S_ISDIR(h_mode))) {
14651+ err = -ENOTDIR;
14652+ goto out;
14653+ }
14654+ } else {
14655+ /* rename(2) case */
14656+ err = -EIO;
14657+ if (unlikely(h_inode))
14658+ goto out;
14659+ }
1facf9fc 14660+
4a4d8108
AM
14661+ err = -ENOENT;
14662+ /* expected parent dir is locked */
14663+ if (unlikely(h_parent != h_dentry->d_parent))
14664+ goto out;
14665+ err = 0;
14666+
14667+ /*
14668+ * rmdir a dir may break the consistency on some filesystem.
14669+ * let's try heavy test.
14670+ */
14671+ err = -EACCES;
14672+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
14673+ goto out;
14674+
14675+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
14676+ au_sbr(dentry->d_sb, bindex));
14677+ err = -EIO;
14678+ if (IS_ERR(h_latest))
14679+ goto out;
14680+ if (h_latest == h_dentry)
14681+ err = 0;
14682+ dput(h_latest);
14683+
4f0767ce 14684+out:
4a4d8108 14685+ return err;
1308ab2a 14686+}
1facf9fc 14687+
4a4d8108
AM
14688+/*
14689+ * decide the branch where we operate for @dentry. the branch index will be set
14690+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
14691+ * dir for reverting.
14692+ * when a new whiteout is necessary, create it.
14693+ */
14694+static struct dentry*
14695+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
14696+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 14697+{
4a4d8108
AM
14698+ struct dentry *wh_dentry;
14699+ struct super_block *sb;
14700+ struct path h_path;
14701+ int err, need_wh;
14702+ unsigned int udba;
14703+ aufs_bindex_t bcpup;
dece6358 14704+
4a4d8108
AM
14705+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
14706+ wh_dentry = ERR_PTR(need_wh);
14707+ if (unlikely(need_wh < 0))
14708+ goto out;
14709+
14710+ sb = dentry->d_sb;
14711+ udba = au_opt_udba(sb);
14712+ bcpup = *rbcpup;
14713+ err = au_pin(pin, dentry, bcpup, udba,
14714+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14715+ wh_dentry = ERR_PTR(err);
14716+ if (unlikely(err))
14717+ goto out;
14718+
14719+ h_path.dentry = au_pinned_h_parent(pin);
14720+ if (udba != AuOpt_UDBA_NONE
14721+ && au_dbstart(dentry) == bcpup) {
14722+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
14723+ wh_dentry = ERR_PTR(err);
14724+ if (unlikely(err))
14725+ goto out_unpin;
14726+ }
14727+
14728+ h_path.mnt = au_sbr_mnt(sb, bcpup);
14729+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
14730+ wh_dentry = NULL;
14731+ if (!need_wh)
14732+ goto out; /* success, no need to create whiteout */
14733+
14734+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
14735+ if (IS_ERR(wh_dentry))
14736+ goto out_unpin;
14737+
14738+ /* returns with the parent is locked and wh_dentry is dget-ed */
14739+ goto out; /* success */
14740+
4f0767ce 14741+out_unpin:
4a4d8108 14742+ au_unpin(pin);
4f0767ce 14743+out:
4a4d8108 14744+ return wh_dentry;
1facf9fc 14745+}
14746+
4a4d8108
AM
14747+/*
14748+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
14749+ * in order to be revertible and save time for removing many child whiteouts
14750+ * under the dir.
14751+ * returns 1 when there are too many child whiteout and caller should remove
14752+ * them asynchronously. returns 0 when the number of children is enough small to
14753+ * remove now or the branch fs is a remote fs.
14754+ * otherwise return an error.
14755+ */
14756+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
14757+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 14758+{
4a4d8108
AM
14759+ int rmdir_later, err, dirwh;
14760+ struct dentry *h_dentry;
14761+ struct super_block *sb;
14762+
14763+ sb = dentry->d_sb;
14764+ SiMustAnyLock(sb);
14765+ h_dentry = au_h_dptr(dentry, bindex);
14766+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
14767+ if (unlikely(err))
14768+ goto out;
14769+
14770+ /* stop monitoring */
14771+ au_hn_free(au_hi(dentry->d_inode, bindex));
14772+
14773+ if (!au_test_fs_remote(h_dentry->d_sb)) {
14774+ dirwh = au_sbi(sb)->si_dirwh;
14775+ rmdir_later = (dirwh <= 1);
14776+ if (!rmdir_later)
14777+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
14778+ dirwh);
14779+ if (rmdir_later)
14780+ return rmdir_later;
14781+ }
1facf9fc 14782+
4a4d8108
AM
14783+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
14784+ if (unlikely(err)) {
14785+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
14786+ AuDLNPair(h_dentry), bindex, err);
14787+ err = 0;
14788+ }
dece6358 14789+
4f0767ce 14790+out:
4a4d8108
AM
14791+ AuTraceErr(err);
14792+ return err;
14793+}
1308ab2a 14794+
4a4d8108
AM
14795+/*
14796+ * final procedure for deleting a entry.
14797+ * maintain dentry and iattr.
14798+ */
14799+static void epilog(struct inode *dir, struct dentry *dentry,
14800+ aufs_bindex_t bindex)
14801+{
14802+ struct inode *inode;
1308ab2a 14803+
4a4d8108
AM
14804+ inode = dentry->d_inode;
14805+ d_drop(dentry);
14806+ inode->i_ctime = dir->i_ctime;
1308ab2a 14807+
4a4d8108
AM
14808+ if (atomic_read(&dentry->d_count) == 1) {
14809+ au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
14810+ au_update_dbstart(dentry);
dece6358 14811+ }
4a4d8108
AM
14812+ if (au_ibstart(dir) == bindex)
14813+ au_cpup_attr_timesizes(dir);
14814+ dir->i_version++;
1facf9fc 14815+}
14816+
4a4d8108
AM
14817+/*
14818+ * when an error happened, remove the created whiteout and revert everything.
14819+ */
14820+static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
14821+ struct dentry *wh_dentry, struct dentry *dentry,
14822+ struct au_dtime *dt)
1facf9fc 14823+{
4a4d8108
AM
14824+ int rerr;
14825+ struct path h_path = {
14826+ .dentry = wh_dentry,
14827+ .mnt = au_sbr_mnt(dir->i_sb, bwh)
14828+ };
dece6358 14829+
4a4d8108
AM
14830+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
14831+ if (!rerr) {
14832+ au_set_dbwh(dentry, bwh);
14833+ au_dtime_revert(dt);
14834+ return 0;
14835+ }
dece6358 14836+
4a4d8108
AM
14837+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
14838+ AuDLNPair(dentry), err, rerr);
14839+ return -EIO;
1facf9fc 14840+}
14841+
4a4d8108 14842+/* ---------------------------------------------------------------------- */
1facf9fc 14843+
4a4d8108 14844+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 14845+{
4a4d8108
AM
14846+ int err;
14847+ aufs_bindex_t bwh, bindex, bstart;
14848+ struct au_dtime dt;
14849+ struct au_pin pin;
14850+ struct path h_path;
14851+ struct inode *inode, *h_dir;
14852+ struct dentry *parent, *wh_dentry;
1facf9fc 14853+
4a4d8108
AM
14854+ IMustLock(dir);
14855+ inode = dentry->d_inode;
14856+ if (unlikely(!inode))
14857+ return -ENOENT; /* possible? */
14858+ IMustLock(inode);
1facf9fc 14859+
4a4d8108
AM
14860+ aufs_read_lock(dentry, AuLock_DW);
14861+ parent = dentry->d_parent; /* dir inode is locked */
14862+ di_write_lock_parent(parent);
1facf9fc 14863+
4a4d8108
AM
14864+ bstart = au_dbstart(dentry);
14865+ bwh = au_dbwh(dentry);
14866+ bindex = -1;
14867+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
14868+ err = PTR_ERR(wh_dentry);
14869+ if (IS_ERR(wh_dentry))
14870+ goto out;
1facf9fc 14871+
4a4d8108
AM
14872+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
14873+ h_path.dentry = au_h_dptr(dentry, bstart);
14874+ dget(h_path.dentry);
14875+ if (bindex == bstart) {
14876+ h_dir = au_pinned_h_dir(&pin);
14877+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
14878+ } else {
14879+ /* dir inode is locked */
14880+ h_dir = wh_dentry->d_parent->d_inode;
14881+ IMustLock(h_dir);
14882+ err = 0;
14883+ }
dece6358 14884+
4a4d8108
AM
14885+ if (!err) {
14886+ drop_nlink(inode);
14887+ epilog(dir, dentry, bindex);
14888+
14889+ /* update target timestamps */
14890+ if (bindex == bstart) {
14891+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
14892+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
14893+ } else
14894+ /* todo: this timestamp may be reverted later */
14895+ inode->i_ctime = h_dir->i_ctime;
14896+ goto out_unlock; /* success */
1facf9fc 14897+ }
14898+
4a4d8108
AM
14899+ /* revert */
14900+ if (wh_dentry) {
14901+ int rerr;
14902+
14903+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
14904+ if (rerr)
14905+ err = rerr;
dece6358 14906+ }
1facf9fc 14907+
4f0767ce 14908+out_unlock:
4a4d8108
AM
14909+ au_unpin(&pin);
14910+ dput(wh_dentry);
14911+ dput(h_path.dentry);
4f0767ce 14912+out:
4a4d8108
AM
14913+ di_write_unlock(parent);
14914+ aufs_read_unlock(dentry, AuLock_DW);
14915+ return err;
dece6358
AM
14916+}
14917+
4a4d8108 14918+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 14919+{
4a4d8108
AM
14920+ int err, rmdir_later;
14921+ aufs_bindex_t bwh, bindex, bstart;
14922+ struct au_dtime dt;
14923+ struct au_pin pin;
14924+ struct inode *inode;
14925+ struct dentry *parent, *wh_dentry, *h_dentry;
14926+ struct au_whtmp_rmdir *args;
1facf9fc 14927+
4a4d8108
AM
14928+ IMustLock(dir);
14929+ inode = dentry->d_inode;
14930+ err = -ENOENT; /* possible? */
14931+ if (unlikely(!inode))
14932+ goto out;
14933+ IMustLock(inode);
dece6358 14934+
4a4d8108
AM
14935+ aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
14936+ err = -ENOMEM;
14937+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
14938+ if (unlikely(!args))
14939+ goto out_unlock;
dece6358 14940+
4a4d8108
AM
14941+ parent = dentry->d_parent; /* dir inode is locked */
14942+ di_write_lock_parent(parent);
14943+ err = au_test_empty(dentry, &args->whlist);
14944+ if (unlikely(err))
14945+ goto out_args;
1facf9fc 14946+
4a4d8108
AM
14947+ bstart = au_dbstart(dentry);
14948+ bwh = au_dbwh(dentry);
14949+ bindex = -1;
14950+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
14951+ err = PTR_ERR(wh_dentry);
14952+ if (IS_ERR(wh_dentry))
14953+ goto out_args;
1facf9fc 14954+
4a4d8108
AM
14955+ h_dentry = au_h_dptr(dentry, bstart);
14956+ dget(h_dentry);
14957+ rmdir_later = 0;
14958+ if (bindex == bstart) {
14959+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
14960+ if (err > 0) {
14961+ rmdir_later = err;
14962+ err = 0;
14963+ }
14964+ } else {
14965+ /* stop monitoring */
14966+ au_hn_free(au_hi(inode, bstart));
14967+
14968+ /* dir inode is locked */
14969+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 14970+ err = 0;
14971+ }
14972+
4a4d8108
AM
14973+ if (!err) {
14974+ clear_nlink(inode);
14975+ au_set_dbdiropq(dentry, -1);
14976+ epilog(dir, dentry, bindex);
1308ab2a 14977+
4a4d8108
AM
14978+ if (rmdir_later) {
14979+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
14980+ args = NULL;
14981+ }
1308ab2a 14982+
4a4d8108 14983+ goto out_unpin; /* success */
1facf9fc 14984+ }
14985+
4a4d8108
AM
14986+ /* revert */
14987+ AuLabel(revert);
14988+ if (wh_dentry) {
14989+ int rerr;
1308ab2a 14990+
4a4d8108
AM
14991+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
14992+ if (rerr)
14993+ err = rerr;
1facf9fc 14994+ }
14995+
4f0767ce 14996+out_unpin:
4a4d8108
AM
14997+ au_unpin(&pin);
14998+ dput(wh_dentry);
14999+ dput(h_dentry);
4f0767ce 15000+out_args:
4a4d8108
AM
15001+ di_write_unlock(parent);
15002+ if (args)
15003+ au_whtmp_rmdir_free(args);
4f0767ce 15004+out_unlock:
4a4d8108 15005+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 15006+out:
4a4d8108
AM
15007+ AuTraceErr(err);
15008+ return err;
dece6358 15009+}
b752ccd1
AM
15010diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
15011--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
15012+++ linux/fs/aufs/i_op_ren.c 2010-10-21 09:52:43.090291764 +0200
15013@@ -0,0 +1,977 @@
1facf9fc 15014+/*
4a4d8108 15015+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 15016+ *
15017+ * This program, aufs is free software; you can redistribute it and/or modify
15018+ * it under the terms of the GNU General Public License as published by
15019+ * the Free Software Foundation; either version 2 of the License, or
15020+ * (at your option) any later version.
dece6358
AM
15021+ *
15022+ * This program is distributed in the hope that it will be useful,
15023+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15024+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15025+ * GNU General Public License for more details.
15026+ *
15027+ * You should have received a copy of the GNU General Public License
15028+ * along with this program; if not, write to the Free Software
15029+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 15030+ */
15031+
15032+/*
4a4d8108
AM
15033+ * inode operation (rename entry)
15034+ * todo: this is crazy monster
1facf9fc 15035+ */
15036+
15037+#include "aufs.h"
15038+
4a4d8108
AM
15039+enum { AuSRC, AuDST, AuSrcDst };
15040+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 15041+
4a4d8108
AM
15042+#define AuRen_ISDIR 1
15043+#define AuRen_ISSAMEDIR (1 << 1)
15044+#define AuRen_WHSRC (1 << 2)
15045+#define AuRen_WHDST (1 << 3)
15046+#define AuRen_MNT_WRITE (1 << 4)
15047+#define AuRen_DT_DSTDIR (1 << 5)
15048+#define AuRen_DIROPQ (1 << 6)
15049+#define AuRen_CPUP (1 << 7)
15050+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
15051+#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
15052+#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
1facf9fc 15053+
4a4d8108
AM
15054+struct au_ren_args {
15055+ struct {
15056+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
15057+ *wh_dentry;
15058+ struct inode *dir, *inode;
15059+ struct au_hinode *hdir;
15060+ struct au_dtime dt[AuParentChild];
15061+ aufs_bindex_t bstart;
15062+ } sd[AuSrcDst];
1facf9fc 15063+
4a4d8108
AM
15064+#define src_dentry sd[AuSRC].dentry
15065+#define src_dir sd[AuSRC].dir
15066+#define src_inode sd[AuSRC].inode
15067+#define src_h_dentry sd[AuSRC].h_dentry
15068+#define src_parent sd[AuSRC].parent
15069+#define src_h_parent sd[AuSRC].h_parent
15070+#define src_wh_dentry sd[AuSRC].wh_dentry
15071+#define src_hdir sd[AuSRC].hdir
15072+#define src_h_dir sd[AuSRC].hdir->hi_inode
15073+#define src_dt sd[AuSRC].dt
15074+#define src_bstart sd[AuSRC].bstart
1facf9fc 15075+
4a4d8108
AM
15076+#define dst_dentry sd[AuDST].dentry
15077+#define dst_dir sd[AuDST].dir
15078+#define dst_inode sd[AuDST].inode
15079+#define dst_h_dentry sd[AuDST].h_dentry
15080+#define dst_parent sd[AuDST].parent
15081+#define dst_h_parent sd[AuDST].h_parent
15082+#define dst_wh_dentry sd[AuDST].wh_dentry
15083+#define dst_hdir sd[AuDST].hdir
15084+#define dst_h_dir sd[AuDST].hdir->hi_inode
15085+#define dst_dt sd[AuDST].dt
15086+#define dst_bstart sd[AuDST].bstart
15087+
15088+ struct dentry *h_trap;
15089+ struct au_branch *br;
15090+ struct au_hinode *src_hinode;
15091+ struct path h_path;
15092+ struct au_nhash whlist;
15093+ aufs_bindex_t btgt;
1facf9fc 15094+
1308ab2a 15095+ unsigned int flags;
1facf9fc 15096+
4a4d8108
AM
15097+ struct au_whtmp_rmdir *thargs;
15098+ struct dentry *h_dst;
15099+};
1308ab2a 15100+
4a4d8108 15101+/* ---------------------------------------------------------------------- */
1308ab2a 15102+
4a4d8108
AM
15103+/*
15104+ * functions for reverting.
15105+ * when an error happened in a single rename systemcall, we should revert
15106+ * everything as if nothing happend.
15107+ * we don't need to revert the copied-up/down the parent dir since they are
15108+ * harmless.
15109+ */
1facf9fc 15110+
4a4d8108
AM
15111+#define RevertFailure(fmt, ...) do { \
15112+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
15113+ ##__VA_ARGS__, err, rerr); \
15114+ err = -EIO; \
15115+} while (0)
1facf9fc 15116+
4a4d8108 15117+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 15118+{
4a4d8108 15119+ int rerr;
1facf9fc 15120+
4a4d8108
AM
15121+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15122+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
15123+ au_hn_imtx_unlock(a->src_hinode);
15124+ if (rerr)
15125+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
15126+}
1facf9fc 15127+
4a4d8108
AM
15128+static void au_ren_rev_rename(int err, struct au_ren_args *a)
15129+{
15130+ int rerr;
1facf9fc 15131+
4a4d8108
AM
15132+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
15133+ a->br, /*nd*/NULL);
15134+ rerr = PTR_ERR(a->h_path.dentry);
15135+ if (IS_ERR(a->h_path.dentry)) {
15136+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
15137+ return;
1facf9fc 15138+ }
15139+
4a4d8108
AM
15140+ rerr = vfsub_rename(a->dst_h_dir,
15141+ au_h_dptr(a->src_dentry, a->btgt),
15142+ a->src_h_dir, &a->h_path);
15143+ d_drop(a->h_path.dentry);
15144+ dput(a->h_path.dentry);
15145+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
15146+ if (rerr)
15147+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 15148+}
15149+
4a4d8108 15150+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 15151+{
4a4d8108 15152+ int rerr;
1facf9fc 15153+
4a4d8108
AM
15154+ a->h_path.dentry = a->dst_h_dentry;
15155+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
15156+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
15157+ au_set_dbstart(a->src_dentry, a->src_bstart);
15158+ if (rerr)
15159+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 15160+}
15161+
4a4d8108 15162+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 15163+{
4a4d8108 15164+ int rerr;
dece6358 15165+
4a4d8108
AM
15166+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
15167+ a->br, /*nd*/NULL);
15168+ rerr = PTR_ERR(a->h_path.dentry);
15169+ if (IS_ERR(a->h_path.dentry)) {
15170+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
15171+ return;
15172+ }
15173+ if (a->h_path.dentry->d_inode) {
15174+ d_drop(a->h_path.dentry);
15175+ dput(a->h_path.dentry);
15176+ return;
dece6358
AM
15177+ }
15178+
4a4d8108
AM
15179+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
15180+ d_drop(a->h_path.dentry);
15181+ dput(a->h_path.dentry);
15182+ if (!rerr)
15183+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
15184+ else
15185+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
15186+}
1308ab2a 15187+
4a4d8108
AM
15188+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
15189+{
15190+ int rerr;
1308ab2a 15191+
4a4d8108
AM
15192+ a->h_path.dentry = a->src_wh_dentry;
15193+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
15194+ if (rerr)
15195+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
15196+}
1308ab2a 15197+
4a4d8108
AM
15198+static void au_ren_rev_drop(struct au_ren_args *a)
15199+{
15200+ struct dentry *d, *h_d;
15201+ int i;
15202+ aufs_bindex_t bend, bindex;
15203+
15204+ for (i = 0; i < AuSrcDst; i++) {
15205+ d = a->sd[i].dentry;
15206+ d_drop(d);
15207+ bend = au_dbend(d);
15208+ for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
15209+ h_d = au_h_dptr(d, bindex);
15210+ if (h_d)
15211+ d_drop(h_d);
15212+ }
1308ab2a 15213+ }
15214+
4a4d8108
AM
15215+ au_update_dbstart(a->dst_dentry);
15216+ if (a->thargs)
15217+ d_drop(a->h_dst);
1facf9fc 15218+}
4a4d8108 15219+#undef RevertFailure
1facf9fc 15220+
1308ab2a 15221+/* ---------------------------------------------------------------------- */
15222+
4a4d8108
AM
15223+/*
15224+ * when we have to copyup the renaming entry, do it with the rename-target name
15225+ * in order to minimize the cost (the later actual rename is unnecessary).
15226+ * otherwise rename it on the target branch.
15227+ */
15228+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 15229+{
dece6358 15230+ int err;
4a4d8108 15231+ struct dentry *d;
1facf9fc 15232+
4a4d8108
AM
15233+ d = a->src_dentry;
15234+ if (au_dbstart(d) == a->btgt) {
15235+ a->h_path.dentry = a->dst_h_dentry;
15236+ if (au_ftest_ren(a->flags, DIROPQ)
15237+ && au_dbdiropq(d) == a->btgt)
15238+ au_fclr_ren(a->flags, DIROPQ);
15239+ AuDebugOn(au_dbstart(d) != a->btgt);
15240+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
15241+ a->dst_h_dir, &a->h_path);
15242+ } else {
15243+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15244+ struct file *h_file;
1308ab2a 15245+
4a4d8108
AM
15246+ au_fset_ren(a->flags, CPUP);
15247+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15248+ au_set_dbstart(d, a->btgt);
15249+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
15250+ h_file = au_h_open_pre(d, a->src_bstart);
15251+ if (IS_ERR(h_file)) {
15252+ err = PTR_ERR(h_file);
15253+ h_file = NULL;
15254+ } else
15255+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
15256+ !AuCpup_DTIME, a->dst_parent);
15257+ mutex_unlock(h_mtx);
15258+ au_h_open_post(d, a->src_bstart, h_file);
15259+ if (!err) {
15260+ d = a->dst_dentry;
15261+ au_set_h_dptr(d, a->btgt, NULL);
15262+ au_update_dbstart(d);
15263+ } else {
15264+ au_set_h_dptr(d, a->btgt, NULL);
15265+ au_set_dbstart(d, a->src_bstart);
15266+ }
1308ab2a 15267+ }
1facf9fc 15268+
dece6358
AM
15269+ return err;
15270+}
1facf9fc 15271+
4a4d8108
AM
15272+/* cf. aufs_rmdir() */
15273+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 15274+{
4a4d8108
AM
15275+ int err;
15276+ struct inode *dir;
1facf9fc 15277+
4a4d8108
AM
15278+ dir = a->dst_dir;
15279+ SiMustAnyLock(dir->i_sb);
15280+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
15281+ au_sbi(dir->i_sb)->si_dirwh)
15282+ || au_test_fs_remote(a->h_dst->d_sb)) {
15283+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
15284+ if (unlikely(err))
15285+ pr_warning("failed removing whtmp dir %.*s (%d), "
15286+ "ignored.\n", AuDLNPair(a->h_dst), err);
15287+ } else {
15288+ au_nhash_wh_free(&a->thargs->whlist);
15289+ a->thargs->whlist = a->whlist;
15290+ a->whlist.nh_num = 0;
15291+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
15292+ dput(a->h_dst);
15293+ a->thargs = NULL;
15294+ }
15295+
15296+ return 0;
1308ab2a 15297+}
1facf9fc 15298+
4a4d8108
AM
15299+/* make it 'opaque' dir. */
15300+static int au_ren_diropq(struct au_ren_args *a)
15301+{
15302+ int err;
15303+ struct dentry *diropq;
1facf9fc 15304+
4a4d8108
AM
15305+ err = 0;
15306+ a->src_hinode = au_hi(a->src_inode, a->btgt);
15307+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15308+ diropq = au_diropq_create(a->src_dentry, a->btgt);
15309+ au_hn_imtx_unlock(a->src_hinode);
15310+ if (IS_ERR(diropq))
15311+ err = PTR_ERR(diropq);
15312+ dput(diropq);
1facf9fc 15313+
4a4d8108
AM
15314+ return err;
15315+}
1facf9fc 15316+
4a4d8108
AM
15317+static int do_rename(struct au_ren_args *a)
15318+{
15319+ int err;
15320+ struct dentry *d, *h_d;
1facf9fc 15321+
4a4d8108
AM
15322+ /* prepare workqueue args for asynchronous rmdir */
15323+ h_d = a->dst_h_dentry;
15324+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
15325+ err = -ENOMEM;
15326+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
15327+ if (unlikely(!a->thargs))
15328+ goto out;
15329+ a->h_dst = dget(h_d);
15330+ }
1facf9fc 15331+
4a4d8108
AM
15332+ /* create whiteout for src_dentry */
15333+ if (au_ftest_ren(a->flags, WHSRC)) {
15334+ a->src_wh_dentry
15335+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
15336+ err = PTR_ERR(a->src_wh_dentry);
15337+ if (IS_ERR(a->src_wh_dentry))
15338+ goto out_thargs;
15339+ }
1facf9fc 15340+
4a4d8108
AM
15341+ /* lookup whiteout for dentry */
15342+ if (au_ftest_ren(a->flags, WHDST)) {
15343+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
15344+ a->br);
15345+ err = PTR_ERR(h_d);
15346+ if (IS_ERR(h_d))
15347+ goto out_whsrc;
15348+ if (!h_d->d_inode)
15349+ dput(h_d);
15350+ else
15351+ a->dst_wh_dentry = h_d;
15352+ }
1facf9fc 15353+
4a4d8108
AM
15354+ /* rename dentry to tmpwh */
15355+ if (a->thargs) {
15356+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
15357+ if (unlikely(err))
15358+ goto out_whdst;
dece6358 15359+
4a4d8108
AM
15360+ d = a->dst_dentry;
15361+ au_set_h_dptr(d, a->btgt, NULL);
15362+ err = au_lkup_neg(d, a->btgt);
15363+ if (unlikely(err))
15364+ goto out_whtmp;
15365+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
15366+ }
1facf9fc 15367+
4a4d8108
AM
15368+ /* cpup src */
15369+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
15370+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15371+ struct file *h_file;
1facf9fc 15372+
4a4d8108
AM
15373+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15374+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
15375+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
15376+ if (IS_ERR(h_file)) {
15377+ err = PTR_ERR(h_file);
15378+ h_file = NULL;
15379+ } else
15380+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
15381+ !AuCpup_DTIME);
15382+ mutex_unlock(h_mtx);
15383+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
15384+ if (unlikely(err))
15385+ goto out_whtmp;
15386+ }
1facf9fc 15387+
4a4d8108
AM
15388+ /* rename by vfs_rename or cpup */
15389+ d = a->dst_dentry;
15390+ if (au_ftest_ren(a->flags, ISDIR)
15391+ && (a->dst_wh_dentry
15392+ || au_dbdiropq(d) == a->btgt
15393+ /* hide the lower to keep xino */
15394+ || a->btgt < au_dbend(d)
15395+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
15396+ au_fset_ren(a->flags, DIROPQ);
15397+ err = au_ren_or_cpup(a);
15398+ if (unlikely(err))
15399+ /* leave the copied-up one */
15400+ goto out_whtmp;
1308ab2a 15401+
4a4d8108
AM
15402+ /* make dir opaque */
15403+ if (au_ftest_ren(a->flags, DIROPQ)) {
15404+ err = au_ren_diropq(a);
15405+ if (unlikely(err))
15406+ goto out_rename;
15407+ }
1308ab2a 15408+
4a4d8108
AM
15409+ /* update target timestamps */
15410+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
15411+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
15412+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
15413+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 15414+
4a4d8108
AM
15415+ /* remove whiteout for dentry */
15416+ if (a->dst_wh_dentry) {
15417+ a->h_path.dentry = a->dst_wh_dentry;
15418+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
15419+ a->dst_dentry);
15420+ if (unlikely(err))
15421+ goto out_diropq;
15422+ }
1facf9fc 15423+
4a4d8108
AM
15424+ /* remove whtmp */
15425+ if (a->thargs)
15426+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 15427+
4a4d8108
AM
15428+ err = 0;
15429+ goto out_success;
15430+
4f0767ce 15431+out_diropq:
4a4d8108
AM
15432+ if (au_ftest_ren(a->flags, DIROPQ))
15433+ au_ren_rev_diropq(err, a);
4f0767ce 15434+out_rename:
4a4d8108
AM
15435+ if (!au_ftest_ren(a->flags, CPUP))
15436+ au_ren_rev_rename(err, a);
15437+ else
15438+ au_ren_rev_cpup(err, a);
4f0767ce 15439+out_whtmp:
4a4d8108
AM
15440+ if (a->thargs)
15441+ au_ren_rev_whtmp(err, a);
4f0767ce 15442+out_whdst:
4a4d8108
AM
15443+ dput(a->dst_wh_dentry);
15444+ a->dst_wh_dentry = NULL;
4f0767ce 15445+out_whsrc:
4a4d8108
AM
15446+ if (a->src_wh_dentry)
15447+ au_ren_rev_whsrc(err, a);
15448+ au_ren_rev_drop(a);
4f0767ce 15449+out_success:
4a4d8108
AM
15450+ dput(a->src_wh_dentry);
15451+ dput(a->dst_wh_dentry);
4f0767ce 15452+out_thargs:
4a4d8108
AM
15453+ if (a->thargs) {
15454+ dput(a->h_dst);
15455+ au_whtmp_rmdir_free(a->thargs);
15456+ a->thargs = NULL;
15457+ }
4f0767ce 15458+out:
4a4d8108 15459+ return err;
dece6358 15460+}
1facf9fc 15461+
1308ab2a 15462+/* ---------------------------------------------------------------------- */
1facf9fc 15463+
4a4d8108
AM
15464+/*
15465+ * test if @dentry dir can be rename destination or not.
15466+ * success means, it is a logically empty dir.
15467+ */
15468+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 15469+{
4a4d8108 15470+ return au_test_empty(dentry, whlist);
1308ab2a 15471+}
1facf9fc 15472+
4a4d8108
AM
15473+/*
15474+ * test if @dentry dir can be rename source or not.
15475+ * if it can, return 0 and @children is filled.
15476+ * success means,
15477+ * - it is a logically empty dir.
15478+ * - or, it exists on writable branch and has no children including whiteouts
15479+ * on the lower branch.
15480+ */
15481+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
15482+{
15483+ int err;
15484+ unsigned int rdhash;
15485+ aufs_bindex_t bstart;
1facf9fc 15486+
4a4d8108
AM
15487+ bstart = au_dbstart(dentry);
15488+ if (bstart != btgt) {
15489+ struct au_nhash whlist;
dece6358 15490+
4a4d8108
AM
15491+ SiMustAnyLock(dentry->d_sb);
15492+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
15493+ if (!rdhash)
15494+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
15495+ dentry));
15496+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
15497+ if (unlikely(err))
15498+ goto out;
15499+ err = au_test_empty(dentry, &whlist);
15500+ au_nhash_wh_free(&whlist);
15501+ goto out;
15502+ }
dece6358 15503+
4a4d8108
AM
15504+ if (bstart == au_dbtaildir(dentry))
15505+ return 0; /* success */
dece6358 15506+
4a4d8108 15507+ err = au_test_empty_lower(dentry);
1facf9fc 15508+
4f0767ce 15509+out:
4a4d8108
AM
15510+ if (err == -ENOTEMPTY) {
15511+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
15512+ " is not supported\n");
15513+ err = -EXDEV;
15514+ }
15515+ return err;
15516+}
1308ab2a 15517+
4a4d8108
AM
15518+/* side effect: sets whlist and h_dentry */
15519+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 15520+{
4a4d8108
AM
15521+ int err;
15522+ unsigned int rdhash;
15523+ struct dentry *d;
1facf9fc 15524+
4a4d8108
AM
15525+ d = a->dst_dentry;
15526+ SiMustAnyLock(d->d_sb);
1facf9fc 15527+
4a4d8108
AM
15528+ err = 0;
15529+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
15530+ rdhash = au_sbi(d->d_sb)->si_rdhash;
15531+ if (!rdhash)
15532+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
15533+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
15534+ if (unlikely(err))
15535+ goto out;
1308ab2a 15536+
4a4d8108
AM
15537+ au_set_dbstart(d, a->dst_bstart);
15538+ err = may_rename_dstdir(d, &a->whlist);
15539+ au_set_dbstart(d, a->btgt);
15540+ }
15541+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
15542+ if (unlikely(err))
15543+ goto out;
15544+
15545+ d = a->src_dentry;
15546+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
15547+ if (au_ftest_ren(a->flags, ISDIR)) {
15548+ err = may_rename_srcdir(d, a->btgt);
15549+ if (unlikely(err)) {
15550+ au_nhash_wh_free(&a->whlist);
15551+ a->whlist.nh_num = 0;
15552+ }
15553+ }
4f0767ce 15554+out:
4a4d8108 15555+ return err;
1facf9fc 15556+}
15557+
4a4d8108 15558+/* ---------------------------------------------------------------------- */
1facf9fc 15559+
4a4d8108
AM
15560+/*
15561+ * simple tests for rename.
15562+ * following the checks in vfs, plus the parent-child relationship.
15563+ */
15564+static int au_may_ren(struct au_ren_args *a)
15565+{
15566+ int err, isdir;
15567+ struct inode *h_inode;
1facf9fc 15568+
4a4d8108
AM
15569+ if (a->src_bstart == a->btgt) {
15570+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
15571+ au_ftest_ren(a->flags, ISDIR));
15572+ if (unlikely(err))
15573+ goto out;
15574+ err = -EINVAL;
15575+ if (unlikely(a->src_h_dentry == a->h_trap))
15576+ goto out;
15577+ }
1facf9fc 15578+
4a4d8108
AM
15579+ err = 0;
15580+ if (a->dst_bstart != a->btgt)
15581+ goto out;
1facf9fc 15582+
4a4d8108
AM
15583+ err = -EIO;
15584+ h_inode = a->dst_h_dentry->d_inode;
15585+ isdir = !!au_ftest_ren(a->flags, ISDIR);
15586+ if (!a->dst_dentry->d_inode) {
15587+ if (unlikely(h_inode))
15588+ goto out;
15589+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
15590+ isdir);
15591+ } else {
15592+ if (unlikely(!h_inode || !h_inode->i_nlink))
15593+ goto out;
15594+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
15595+ isdir);
15596+ if (unlikely(err))
15597+ goto out;
15598+ err = -ENOTEMPTY;
15599+ if (unlikely(a->dst_h_dentry == a->h_trap))
15600+ goto out;
15601+ err = 0;
15602+ }
1facf9fc 15603+
4f0767ce 15604+out:
4a4d8108
AM
15605+ if (unlikely(err == -ENOENT || err == -EEXIST))
15606+ err = -EIO;
15607+ AuTraceErr(err);
15608+ return err;
15609+}
1facf9fc 15610+
1308ab2a 15611+/* ---------------------------------------------------------------------- */
1facf9fc 15612+
4a4d8108
AM
15613+/*
15614+ * locking order
15615+ * (VFS)
15616+ * - src_dir and dir by lock_rename()
15617+ * - inode if exitsts
15618+ * (aufs)
15619+ * - lock all
15620+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
15621+ * + si_read_lock
15622+ * + di_write_lock2_child()
15623+ * + di_write_lock_child()
15624+ * + ii_write_lock_child()
15625+ * + di_write_lock_child2()
15626+ * + ii_write_lock_child2()
15627+ * + src_parent and parent
15628+ * + di_write_lock_parent()
15629+ * + ii_write_lock_parent()
15630+ * + di_write_lock_parent2()
15631+ * + ii_write_lock_parent2()
15632+ * + lower src_dir and dir by vfsub_lock_rename()
15633+ * + verify the every relationships between child and parent. if any
15634+ * of them failed, unlock all and return -EBUSY.
15635+ */
15636+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 15637+{
4a4d8108
AM
15638+ struct super_block *sb;
15639+
15640+ sb = a->dst_dentry->d_sb;
15641+ if (au_ftest_ren(a->flags, MNT_WRITE))
15642+ mnt_drop_write(a->br->br_mnt);
15643+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
15644+ a->dst_h_parent, a->dst_hdir);
1308ab2a 15645+}
15646+
4a4d8108 15647+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 15648+{
4a4d8108
AM
15649+ int err;
15650+ unsigned int udba;
1308ab2a 15651+
4a4d8108
AM
15652+ err = 0;
15653+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
15654+ a->src_hdir = au_hi(a->src_dir, a->btgt);
15655+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
15656+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
15657+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
15658+ a->dst_h_parent, a->dst_hdir);
15659+ udba = au_opt_udba(a->src_dentry->d_sb);
15660+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
15661+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
15662+ err = au_busy_or_stale();
15663+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
15664+ err = au_h_verify(a->src_h_dentry, udba,
15665+ a->src_h_parent->d_inode, a->src_h_parent,
15666+ a->br);
15667+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
15668+ err = au_h_verify(a->dst_h_dentry, udba,
15669+ a->dst_h_parent->d_inode, a->dst_h_parent,
15670+ a->br);
15671+ if (!err) {
15672+ err = mnt_want_write(a->br->br_mnt);
15673+ if (unlikely(err))
15674+ goto out_unlock;
15675+ au_fset_ren(a->flags, MNT_WRITE);
15676+ goto out; /* success */
15677+ }
15678+
15679+ err = au_busy_or_stale();
15680+
4f0767ce 15681+out_unlock:
4a4d8108 15682+ au_ren_unlock(a);
4f0767ce 15683+out:
4a4d8108 15684+ return err;
1facf9fc 15685+}
15686+
15687+/* ---------------------------------------------------------------------- */
15688+
4a4d8108 15689+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 15690+{
4a4d8108 15691+ struct inode *dir;
dece6358 15692+
4a4d8108
AM
15693+ dir = a->dst_dir;
15694+ dir->i_version++;
15695+ if (au_ftest_ren(a->flags, ISDIR)) {
15696+ /* is this updating defined in POSIX? */
15697+ au_cpup_attr_timesizes(a->src_inode);
15698+ au_cpup_attr_nlink(dir, /*force*/1);
15699+ if (a->dst_inode) {
15700+ clear_nlink(a->dst_inode);
15701+ au_cpup_attr_timesizes(a->dst_inode);
15702+ }
15703+ }
15704+ if (au_ibstart(dir) == a->btgt)
15705+ au_cpup_attr_timesizes(dir);
dece6358 15706+
4a4d8108
AM
15707+ if (au_ftest_ren(a->flags, ISSAMEDIR))
15708+ return;
dece6358 15709+
4a4d8108
AM
15710+ dir = a->src_dir;
15711+ dir->i_version++;
15712+ if (au_ftest_ren(a->flags, ISDIR))
15713+ au_cpup_attr_nlink(dir, /*force*/1);
15714+ if (au_ibstart(dir) == a->btgt)
15715+ au_cpup_attr_timesizes(dir);
1facf9fc 15716+}
15717+
4a4d8108 15718+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 15719+{
4a4d8108
AM
15720+ aufs_bindex_t bend, bindex;
15721+ struct dentry *d, *h_d;
15722+ struct inode *i, *h_i;
15723+ struct super_block *sb;
dece6358 15724+
4a4d8108
AM
15725+ d = a->src_dentry;
15726+ au_set_dbwh(d, -1);
15727+ bend = au_dbend(d);
15728+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
15729+ h_d = au_h_dptr(d, bindex);
15730+ if (h_d)
15731+ au_set_h_dptr(d, bindex, NULL);
15732+ }
15733+ au_set_dbend(d, a->btgt);
15734+
15735+ sb = d->d_sb;
15736+ i = a->src_inode;
15737+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
15738+ return; /* success */
15739+
15740+ bend = au_ibend(i);
15741+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
15742+ h_i = au_h_iptr(i, bindex);
15743+ if (h_i) {
15744+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
15745+ /* ignore this error */
15746+ au_set_h_iptr(i, bindex, NULL, 0);
15747+ }
15748+ }
15749+ au_set_ibend(i, a->btgt);
1308ab2a 15750+}
dece6358 15751+
4a4d8108
AM
15752+/* ---------------------------------------------------------------------- */
15753+
15754+/* mainly for link(2) and rename(2) */
15755+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 15756+{
4a4d8108
AM
15757+ aufs_bindex_t bdiropq, bwh;
15758+ struct dentry *parent;
15759+ struct au_branch *br;
15760+
15761+ parent = dentry->d_parent;
15762+ IMustLock(parent->d_inode); /* dir is locked */
15763+
15764+ bdiropq = au_dbdiropq(parent);
15765+ bwh = au_dbwh(dentry);
15766+ br = au_sbr(dentry->d_sb, btgt);
15767+ if (au_br_rdonly(br)
15768+ || (0 <= bdiropq && bdiropq < btgt)
15769+ || (0 <= bwh && bwh < btgt))
15770+ btgt = -1;
15771+
15772+ AuDbg("btgt %d\n", btgt);
15773+ return btgt;
1facf9fc 15774+}
15775+
4a4d8108
AM
15776+/* sets src_bstart, dst_bstart and btgt */
15777+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 15778+{
4a4d8108
AM
15779+ int err;
15780+ struct au_wr_dir_args wr_dir_args = {
15781+ /* .force_btgt = -1, */
15782+ .flags = AuWrDir_ADD_ENTRY
15783+ };
dece6358 15784+
4a4d8108
AM
15785+ a->src_bstart = au_dbstart(a->src_dentry);
15786+ a->dst_bstart = au_dbstart(a->dst_dentry);
15787+ if (au_ftest_ren(a->flags, ISDIR))
15788+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
15789+ wr_dir_args.force_btgt = a->src_bstart;
15790+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
15791+ wr_dir_args.force_btgt = a->dst_bstart;
15792+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
15793+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
15794+ a->btgt = err;
dece6358 15795+
4a4d8108 15796+ return err;
1facf9fc 15797+}
15798+
4a4d8108 15799+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 15800+{
4a4d8108
AM
15801+ a->h_path.dentry = a->src_h_parent;
15802+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
15803+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
15804+ a->h_path.dentry = a->dst_h_parent;
15805+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
15806+ }
1facf9fc 15807+
4a4d8108
AM
15808+ au_fclr_ren(a->flags, DT_DSTDIR);
15809+ if (!au_ftest_ren(a->flags, ISDIR))
15810+ return;
dece6358 15811+
4a4d8108
AM
15812+ a->h_path.dentry = a->src_h_dentry;
15813+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
15814+ if (a->dst_h_dentry->d_inode) {
15815+ au_fset_ren(a->flags, DT_DSTDIR);
15816+ a->h_path.dentry = a->dst_h_dentry;
15817+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
15818+ }
1308ab2a 15819+}
dece6358 15820+
4a4d8108 15821+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 15822+{
4a4d8108
AM
15823+ struct dentry *h_d;
15824+ struct mutex *h_mtx;
15825+
15826+ au_dtime_revert(a->src_dt + AuPARENT);
15827+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
15828+ au_dtime_revert(a->dst_dt + AuPARENT);
15829+
15830+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
15831+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
15832+ h_mtx = &h_d->d_inode->i_mutex;
15833+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15834+ au_dtime_revert(a->src_dt + AuCHILD);
15835+ mutex_unlock(h_mtx);
15836+
15837+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
15838+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
15839+ h_mtx = &h_d->d_inode->i_mutex;
15840+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15841+ au_dtime_revert(a->dst_dt + AuCHILD);
15842+ mutex_unlock(h_mtx);
1facf9fc 15843+ }
15844+ }
15845+}
15846+
4a4d8108
AM
15847+/* ---------------------------------------------------------------------- */
15848+
15849+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
15850+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 15851+{
953406b4 15852+ int err;
4a4d8108
AM
15853+ /* reduce stack space */
15854+ struct au_ren_args *a;
15855+
15856+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
15857+ IMustLock(_src_dir);
15858+ IMustLock(_dst_dir);
15859+
15860+ err = -ENOMEM;
15861+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
15862+ a = kzalloc(sizeof(*a), GFP_NOFS);
15863+ if (unlikely(!a))
15864+ goto out;
15865+
15866+ a->src_dir = _src_dir;
15867+ a->src_dentry = _src_dentry;
15868+ a->src_inode = a->src_dentry->d_inode;
15869+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
15870+ a->dst_dir = _dst_dir;
15871+ a->dst_dentry = _dst_dentry;
15872+ a->dst_inode = a->dst_dentry->d_inode;
15873+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
15874+ if (a->dst_inode) {
15875+ IMustLock(a->dst_inode);
15876+ au_igrab(a->dst_inode);
1facf9fc 15877+ }
1facf9fc 15878+
4a4d8108
AM
15879+ err = -ENOTDIR;
15880+ if (S_ISDIR(a->src_inode->i_mode)) {
15881+ au_fset_ren(a->flags, ISDIR);
15882+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
15883+ goto out_free;
953406b4
AM
15884+ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
15885+ AuLock_DIR | AuLock_FLUSH);
4a4d8108 15886+ } else
953406b4
AM
15887+ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
15888+ AuLock_FLUSH);
1facf9fc 15889+
4a4d8108
AM
15890+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
15891+ di_write_lock_parent(a->dst_parent);
1facf9fc 15892+
4a4d8108
AM
15893+ /* which branch we process */
15894+ err = au_ren_wbr(a);
15895+ if (unlikely(err < 0))
15896+ goto out_unlock;
15897+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
15898+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 15899+
4a4d8108
AM
15900+ /* are they available to be renamed */
15901+ err = au_ren_may_dir(a);
15902+ if (unlikely(err))
15903+ goto out_children;
1facf9fc 15904+
4a4d8108
AM
15905+ /* prepare the writable parent dir on the same branch */
15906+ if (a->dst_bstart == a->btgt) {
15907+ au_fset_ren(a->flags, WHDST);
15908+ } else {
15909+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
15910+ if (unlikely(err))
15911+ goto out_children;
15912+ }
1facf9fc 15913+
4a4d8108
AM
15914+ if (a->src_dir != a->dst_dir) {
15915+ /*
15916+ * this temporary unlock is safe,
15917+ * because both dir->i_mutex are locked.
15918+ */
15919+ di_write_unlock(a->dst_parent);
15920+ di_write_lock_parent(a->src_parent);
15921+ err = au_wr_dir_need_wh(a->src_dentry,
15922+ au_ftest_ren(a->flags, ISDIR),
15923+ &a->btgt);
15924+ di_write_unlock(a->src_parent);
15925+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
15926+ au_fclr_ren(a->flags, ISSAMEDIR);
15927+ } else
15928+ err = au_wr_dir_need_wh(a->src_dentry,
15929+ au_ftest_ren(a->flags, ISDIR),
15930+ &a->btgt);
15931+ if (unlikely(err < 0))
15932+ goto out_children;
15933+ if (err)
15934+ au_fset_ren(a->flags, WHSRC);
1facf9fc 15935+
4a4d8108
AM
15936+ /* lock them all */
15937+ err = au_ren_lock(a);
15938+ if (unlikely(err))
15939+ goto out_children;
1facf9fc 15940+
4a4d8108
AM
15941+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
15942+ err = au_may_ren(a);
15943+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
15944+ err = -ENAMETOOLONG;
15945+ if (unlikely(err))
15946+ goto out_hdir;
1facf9fc 15947+
4a4d8108
AM
15948+ /* store timestamps to be revertible */
15949+ au_ren_dt(a);
1facf9fc 15950+
4a4d8108
AM
15951+ /* here we go */
15952+ err = do_rename(a);
15953+ if (unlikely(err))
15954+ goto out_dt;
15955+
15956+ /* update dir attributes */
15957+ au_ren_refresh_dir(a);
15958+
15959+ /* dput/iput all lower dentries */
15960+ au_ren_refresh(a);
15961+
15962+ goto out_hdir; /* success */
15963+
4f0767ce 15964+out_dt:
4a4d8108 15965+ au_ren_rev_dt(err, a);
4f0767ce 15966+out_hdir:
4a4d8108 15967+ au_ren_unlock(a);
4f0767ce 15968+out_children:
4a4d8108 15969+ au_nhash_wh_free(&a->whlist);
4f0767ce 15970+out_unlock:
4a4d8108
AM
15971+ if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
15972+ au_update_dbstart(a->dst_dentry);
15973+ d_drop(a->dst_dentry);
15974+ }
15975+ if (!err)
15976+ d_move(a->src_dentry, a->dst_dentry);
15977+ if (au_ftest_ren(a->flags, ISSAMEDIR))
15978+ di_write_unlock(a->dst_parent);
15979+ else
15980+ di_write_unlock2(a->src_parent, a->dst_parent);
15981+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 15982+out_free:
4a4d8108
AM
15983+ iput(a->dst_inode);
15984+ if (a->thargs)
15985+ au_whtmp_rmdir_free(a->thargs);
15986+ kfree(a);
4f0767ce 15987+out:
4a4d8108
AM
15988+ AuTraceErr(err);
15989+ return err;
1308ab2a 15990+}
b752ccd1
AM
15991diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
15992--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
15993+++ linux/fs/aufs/Kconfig 2010-10-21 09:52:43.083624114 +0200
15994@@ -0,0 +1,173 @@
4a4d8108
AM
15995+config AUFS_FS
15996+ tristate "Aufs (Advanced multi layered unification filesystem) support"
15997+ depends on EXPERIMENTAL
15998+ help
15999+ Aufs is a stackable unification filesystem such as Unionfs,
16000+ which unifies several directories and provides a merged single
16001+ directory.
16002+ In the early days, aufs was entirely re-designed and
16003+ re-implemented Unionfs Version 1.x series. Introducing many
16004+ original ideas, approaches and improvements, it becomes totally
16005+ different from Unionfs while keeping the basic features.
1facf9fc 16006+
4a4d8108
AM
16007+if AUFS_FS
16008+choice
16009+ prompt "Maximum number of branches"
16010+ default AUFS_BRANCH_MAX_127
16011+ help
16012+ Specifies the maximum number of branches (or member directories)
16013+ in a single aufs. The larger value consumes more system
16014+ resources and has a minor impact to performance.
16015+config AUFS_BRANCH_MAX_127
16016+ bool "127"
16017+ help
16018+ Specifies the maximum number of branches (or member directories)
16019+ in a single aufs. The larger value consumes more system
16020+ resources and has a minor impact to performance.
16021+config AUFS_BRANCH_MAX_511
16022+ bool "511"
16023+ help
16024+ Specifies the maximum number of branches (or member directories)
16025+ in a single aufs. The larger value consumes more system
16026+ resources and has a minor impact to performance.
16027+config AUFS_BRANCH_MAX_1023
16028+ bool "1023"
16029+ help
16030+ Specifies the maximum number of branches (or member directories)
16031+ in a single aufs. The larger value consumes more system
16032+ resources and has a minor impact to performance.
16033+config AUFS_BRANCH_MAX_32767
16034+ bool "32767"
16035+ help
16036+ Specifies the maximum number of branches (or member directories)
16037+ in a single aufs. The larger value consumes more system
16038+ resources and has a minor impact to performance.
16039+endchoice
1facf9fc 16040+
4a4d8108
AM
16041+config AUFS_HNOTIFY
16042+ bool "Detect direct branch access (bypassing aufs)"
16043+ help
16044+ If you want to modify files on branches directly, eg. bypassing aufs,
16045+ and want aufs to detect the changes of them fully, then enable this
16046+ option and use 'udba=notify' mount option.
953406b4 16047+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
16048+ It will have a negative impact to the performance.
16049+ See detail in aufs.5.
dece6358 16050+
953406b4 16051+
4a4d8108
AM
16052+choice
16053+ prompt "method" if AUFS_HNOTIFY
16054+ default AUFS_HFSNOTIFY
16055+config AUFS_HFSNOTIFY
16056+ bool "fsnotify"
16057+ select FSNOTIFY
4a4d8108 16058+endchoice
1facf9fc 16059+
4a4d8108
AM
16060+config AUFS_EXPORT
16061+ bool "NFS-exportable aufs"
16062+ depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
16063+ help
16064+ If you want to export your mounted aufs via NFS, then enable this
16065+ option. There are several requirements for this configuration.
16066+ See detail in aufs.5.
1facf9fc 16067+
4a4d8108
AM
16068+config AUFS_INO_T_64
16069+ bool
16070+ depends on AUFS_EXPORT
16071+ depends on 64BIT && !(ALPHA || S390)
16072+ default y
16073+ help
16074+ Automatic configuration for internal use.
16075+ /* typedef unsigned long/int __kernel_ino_t */
16076+ /* alpha and s390x are int */
1facf9fc 16077+
4a4d8108
AM
16078+config AUFS_RDU
16079+ bool "Readdir in userspace"
16080+ help
16081+ Aufs has two methods to provide a merged view for a directory,
16082+ by a user-space library and by kernel-space natively. The latter
16083+ is always enabled but sometimes large and slow.
16084+ If you enable this option, install the library in aufs2-util
16085+ package, and set some environment variables for your readdir(3),
16086+ then the work will be handled in user-space which generally
16087+ shows better performance in most cases.
16088+ See detail in aufs.5.
1facf9fc 16089+
4a4d8108
AM
16090+config AUFS_SP_IATTR
16091+ bool "Respect the attributes (mtime/ctime mainly) of special files"
16092+ help
16093+ When you write something to a special file, some attributes of it
16094+ (mtime/ctime mainly) may be updated. Generally such updates are
16095+ less important (actually some device drivers and NFS ignore
16096+ it). But some applications (such like test program) requires
16097+ such updates. If you need these updates, then enable this
16098+ configuration which introduces some overhead.
16099+ Currently this configuration handles FIFO only.
1facf9fc 16100+
4a4d8108
AM
16101+config AUFS_SHWH
16102+ bool "Show whiteouts"
16103+ help
16104+ If you want to make the whiteouts in aufs visible, then enable
16105+ this option and specify 'shwh' mount option. Although it may
16106+ sounds like philosophy or something, but in technically it
16107+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 16108+
4a4d8108
AM
16109+config AUFS_BR_RAMFS
16110+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
16111+ help
16112+ If you want to use ramfs as an aufs branch fs, then enable this
16113+ option. Generally tmpfs is recommended.
16114+ Aufs prohibited them to be a branch fs by default, because
16115+ initramfs becomes unusable after switch_root or something
16116+ generally. If you sets initramfs as an aufs branch and boot your
16117+ system by switch_root, you will meet a problem easily since the
16118+ files in initramfs may be inaccessible.
16119+ Unless you are going to use ramfs as an aufs branch fs without
16120+ switch_root or something, leave it N.
1facf9fc 16121+
4a4d8108
AM
16122+config AUFS_BR_FUSE
16123+ bool "Fuse fs as an aufs branch"
16124+ depends on FUSE_FS
16125+ select AUFS_POLL
16126+ help
16127+ If you want to use fuse-based userspace filesystem as an aufs
16128+ branch fs, then enable this option.
16129+ It implements the internal poll(2) operation which is
16130+ implemented by fuse only (curretnly).
1facf9fc 16131+
4a4d8108
AM
16132+config AUFS_POLL
16133+ bool
16134+ help
16135+ Automatic configuration for internal use.
1facf9fc 16136+
4a4d8108
AM
16137+config AUFS_BR_HFSPLUS
16138+ bool "Hfsplus as an aufs branch"
16139+ depends on HFSPLUS_FS
16140+ default y
16141+ help
16142+ If you want to use hfsplus fs as an aufs branch fs, then enable
16143+ this option. This option introduces a small overhead at
16144+ copying-up a file on hfsplus.
1facf9fc 16145+
4a4d8108
AM
16146+config AUFS_BDEV_LOOP
16147+ bool
16148+ depends on BLK_DEV_LOOP
16149+ default y
16150+ help
16151+ Automatic configuration for internal use.
16152+ Convert =[ym] into =y.
1308ab2a 16153+
4a4d8108
AM
16154+config AUFS_DEBUG
16155+ bool "Debug aufs"
16156+ help
16157+ Enable this to compile aufs internal debug code.
16158+ It will have a negative impact to the performance.
16159+
16160+config AUFS_MAGIC_SYSRQ
16161+ bool
16162+ depends on AUFS_DEBUG && MAGIC_SYSRQ
16163+ default y
16164+ help
16165+ Automatic configuration for internal use.
16166+ When aufs supports Magic SysRq, enabled automatically.
16167+endif
b752ccd1
AM
16168diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
16169--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
953406b4 16170+++ linux/fs/aufs/loop.c 2010-10-21 09:52:43.093625591 +0200
b752ccd1 16171@@ -0,0 +1,63 @@
1facf9fc 16172+/*
4a4d8108 16173+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16174+ *
16175+ * This program, aufs is free software; you can redistribute it and/or modify
16176+ * it under the terms of the GNU General Public License as published by
16177+ * the Free Software Foundation; either version 2 of the License, or
16178+ * (at your option) any later version.
dece6358
AM
16179+ *
16180+ * This program is distributed in the hope that it will be useful,
16181+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16182+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16183+ * GNU General Public License for more details.
16184+ *
16185+ * You should have received a copy of the GNU General Public License
16186+ * along with this program; if not, write to the Free Software
16187+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16188+ */
16189+
16190+/*
16191+ * support for loopback block device as a branch
16192+ */
16193+
16194+#include <linux/loop.h>
16195+#include "aufs.h"
16196+
16197+/*
16198+ * test if two lower dentries have overlapping branches.
16199+ */
b752ccd1 16200+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 16201+{
b752ccd1 16202+ struct super_block *h_sb;
1facf9fc 16203+ struct loop_device *l;
16204+
b752ccd1
AM
16205+ h_sb = h_adding->d_sb;
16206+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 16207+ return 0;
16208+
b752ccd1
AM
16209+ l = h_sb->s_bdev->bd_disk->private_data;
16210+ h_adding = l->lo_backing_file->f_dentry;
16211+ /*
16212+ * h_adding can be local NFS.
16213+ * in this case aufs cannot detect the loop.
16214+ */
16215+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 16216+ return 1;
b752ccd1 16217+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 16218+}
16219+
16220+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
16221+int au_test_loopback_kthread(void)
16222+{
b752ccd1
AM
16223+ int ret;
16224+ struct task_struct *tsk = current;
16225+
16226+ ret = 0;
16227+ if (tsk->flags & PF_KTHREAD) {
16228+ const char c = tsk->comm[4];
16229+ ret = ('0' <= c && c <= '9'
16230+ && !strncmp(tsk->comm, "loop", 4));
16231+ }
1facf9fc 16232+
b752ccd1 16233+ return ret;
1facf9fc 16234+}
b752ccd1
AM
16235diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
16236--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
953406b4 16237+++ linux/fs/aufs/loop.h 2010-10-21 09:52:43.093625591 +0200
b752ccd1 16238@@ -0,0 +1,42 @@
1facf9fc 16239+/*
4a4d8108 16240+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16241+ *
16242+ * This program, aufs is free software; you can redistribute it and/or modify
16243+ * it under the terms of the GNU General Public License as published by
16244+ * the Free Software Foundation; either version 2 of the License, or
16245+ * (at your option) any later version.
dece6358
AM
16246+ *
16247+ * This program is distributed in the hope that it will be useful,
16248+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16249+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16250+ * GNU General Public License for more details.
16251+ *
16252+ * You should have received a copy of the GNU General Public License
16253+ * along with this program; if not, write to the Free Software
16254+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16255+ */
16256+
16257+/*
16258+ * support for loopback mount as a branch
16259+ */
16260+
16261+#ifndef __AUFS_LOOP_H__
16262+#define __AUFS_LOOP_H__
16263+
16264+#ifdef __KERNEL__
16265+
dece6358
AM
16266+struct dentry;
16267+struct super_block;
1facf9fc 16268+
16269+#ifdef CONFIG_AUFS_BDEV_LOOP
16270+/* loop.c */
b752ccd1 16271+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 16272+int au_test_loopback_kthread(void);
16273+#else
4a4d8108 16274+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 16275+ struct dentry *h_adding)
4a4d8108 16276+AuStubInt0(au_test_loopback_kthread, void)
1facf9fc 16277+#endif /* BLK_DEV_LOOP */
16278+
16279+#endif /* __KERNEL__ */
16280+#endif /* __AUFS_LOOP_H__ */
b752ccd1
AM
16281diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
16282--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
953406b4 16283+++ linux/fs/aufs/magic.mk 2010-10-21 09:52:43.093625591 +0200
4a4d8108 16284@@ -0,0 +1,54 @@
1facf9fc 16285+
16286+# defined in ${srctree}/fs/fuse/inode.c
16287+# tristate
16288+ifdef CONFIG_FUSE_FS
16289+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
16290+endif
16291+
16292+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
16293+# tristate
16294+ifdef CONFIG_OCFS2_FS
16295+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
16296+endif
16297+
16298+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
16299+# tristate
16300+ifdef CONFIG_OCFS2_FS_O2CB
16301+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
16302+endif
16303+
1facf9fc 16304+# defined in ${srctree}/fs/cifs/cifsfs.c
16305+# tristate
16306+ifdef CONFIG_CIFS_FS
16307+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
16308+endif
16309+
16310+# defined in ${srctree}/fs/xfs/xfs_sb.h
16311+# tristate
16312+ifdef CONFIG_XFS_FS
16313+ccflags-y += -DXFS_SB_MAGIC=0x58465342
16314+endif
16315+
16316+# defined in ${srctree}/fs/configfs/mount.c
16317+# tristate
16318+ifdef CONFIG_CONFIGFS_FS
16319+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
16320+endif
16321+
16322+# defined in ${srctree}/fs/9p/v9fs.h
16323+# tristate
16324+ifdef CONFIG_9P_FS
16325+ccflags-y += -DV9FS_MAGIC=0x01021997
16326+endif
16327+
16328+# defined in ${srctree}/fs/ubifs/ubifs.h
16329+# tristate
16330+ifdef CONFIG_UBIFS_FS
16331+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
16332+endif
4a4d8108
AM
16333+
16334+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
16335+# tristate
16336+ifdef CONFIG_HFSPLUS_FS
16337+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
16338+endif
b752ccd1
AM
16339diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
16340--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
16341+++ linux/fs/aufs/Makefile 2010-10-21 09:52:43.083624114 +0200
16342@@ -0,0 +1,37 @@
4a4d8108
AM
16343+
16344+include ${src}/magic.mk
16345+ifeq (${CONFIG_AUFS_FS},m)
16346+include ${src}/conf.mk
16347+endif
16348+-include ${src}/priv_def.mk
16349+
16350+# cf. include/linux/kernel.h
16351+# enable pr_debug
16352+ccflags-y += -DDEBUG
16353+ccflags-y += -D'pr_fmt(fmt)="aufs %s:%d:%s[%d]: " fmt, \
16354+ __func__, __LINE__, current->comm, current->pid'
16355+
16356+obj-$(CONFIG_AUFS_FS) += aufs.o
16357+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
16358+ wkq.o vfsub.o dcsub.o \
953406b4 16359+ cpup.o whout.o plink.o wbr_policy.o \
4a4d8108
AM
16360+ dinfo.o dentry.o \
16361+ dynop.o \
16362+ finfo.o file.o f_op.o \
16363+ dir.o vdir.o \
16364+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
16365+ ioctl.o
16366+
16367+# all are boolean
16368+aufs-$(CONFIG_SYSFS) += sysfs.o
16369+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
16370+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
16371+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
16372+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108
AM
16373+aufs-$(CONFIG_AUFS_EXPORT) += export.o
16374+aufs-$(CONFIG_AUFS_POLL) += poll.o
16375+aufs-$(CONFIG_AUFS_RDU) += rdu.o
16376+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
16377+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
16378+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
16379+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
b752ccd1
AM
16380diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
16381--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
16382+++ linux/fs/aufs/module.c 2010-10-21 09:52:43.093625591 +0200
16383@@ -0,0 +1,171 @@
1facf9fc 16384+/*
4a4d8108 16385+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16386+ *
16387+ * This program, aufs is free software; you can redistribute it and/or modify
16388+ * it under the terms of the GNU General Public License as published by
16389+ * the Free Software Foundation; either version 2 of the License, or
16390+ * (at your option) any later version.
dece6358
AM
16391+ *
16392+ * This program is distributed in the hope that it will be useful,
16393+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16394+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16395+ * GNU General Public License for more details.
16396+ *
16397+ * You should have received a copy of the GNU General Public License
16398+ * along with this program; if not, write to the Free Software
16399+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16400+ */
16401+
16402+/*
16403+ * module global variables and operations
16404+ */
16405+
16406+#include <linux/module.h>
16407+#include <linux/seq_file.h>
16408+#include "aufs.h"
16409+
16410+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
16411+{
16412+ if (new_sz <= nused)
16413+ return p;
16414+
16415+ p = krealloc(p, new_sz, gfp);
16416+ if (p)
16417+ memset(p + nused, 0, new_sz - nused);
16418+ return p;
16419+}
16420+
16421+/* ---------------------------------------------------------------------- */
16422+
16423+/*
16424+ * aufs caches
16425+ */
16426+struct kmem_cache *au_cachep[AuCache_Last];
16427+static int __init au_cache_init(void)
16428+{
4a4d8108 16429+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 16430+ if (au_cachep[AuCache_DINFO])
4a4d8108
AM
16431+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
16432+ au_icntnr_init_once);
1facf9fc 16433+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
16434+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
16435+ au_fi_init_once);
1facf9fc 16436+ if (au_cachep[AuCache_FINFO])
16437+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
16438+ if (au_cachep[AuCache_VDIR])
16439+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
16440+ if (au_cachep[AuCache_DEHSTR])
16441+ return 0;
16442+
16443+ return -ENOMEM;
16444+}
16445+
16446+static void au_cache_fin(void)
16447+{
16448+ int i;
4a4d8108
AM
16449+
16450+ /* including AuCache_HNOTIFY */
1facf9fc 16451+ for (i = 0; i < AuCache_Last; i++)
16452+ if (au_cachep[i]) {
16453+ kmem_cache_destroy(au_cachep[i]);
16454+ au_cachep[i] = NULL;
16455+ }
16456+}
16457+
16458+/* ---------------------------------------------------------------------- */
16459+
16460+int au_dir_roflags;
16461+
16462+/*
16463+ * functions for module interface.
16464+ */
16465+MODULE_LICENSE("GPL");
16466+/* MODULE_LICENSE("GPL v2"); */
dece6358 16467+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 16468+MODULE_DESCRIPTION(AUFS_NAME
16469+ " -- Advanced multi layered unification filesystem");
16470+MODULE_VERSION(AUFS_VERSION);
16471+
1facf9fc 16472+/* this module parameter has no meaning when SYSFS is disabled */
16473+int sysaufs_brs = 1;
16474+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
16475+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
16476+
16477+/* ---------------------------------------------------------------------- */
16478+
16479+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
16480+
16481+int au_seq_path(struct seq_file *seq, struct path *path)
16482+{
16483+ return seq_path(seq, path, au_esc_chars);
16484+}
16485+
16486+/* ---------------------------------------------------------------------- */
16487+
16488+static int __init aufs_init(void)
16489+{
16490+ int err, i;
16491+ char *p;
16492+
16493+ p = au_esc_chars;
16494+ for (i = 1; i <= ' '; i++)
16495+ *p++ = i;
16496+ *p++ = '\\';
16497+ *p++ = '\x7f';
16498+ *p = 0;
16499+
16500+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
16501+
16502+ sysaufs_brs_init();
16503+ au_debug_init();
4a4d8108 16504+ au_dy_init();
1facf9fc 16505+ err = sysaufs_init();
16506+ if (unlikely(err))
16507+ goto out;
4f0767ce
JR
16508+ err = au_wkq_init();
16509+ if (unlikely(err))
953406b4 16510+ goto out_sysaufs;
4a4d8108 16511+ err = au_hnotify_init();
1facf9fc 16512+ if (unlikely(err))
16513+ goto out_wkq;
16514+ err = au_sysrq_init();
16515+ if (unlikely(err))
16516+ goto out_hin;
16517+ err = au_cache_init();
16518+ if (unlikely(err))
16519+ goto out_sysrq;
16520+ err = register_filesystem(&aufs_fs_type);
16521+ if (unlikely(err))
16522+ goto out_cache;
4a4d8108
AM
16523+ /* since we define pr_fmt, call printk directly */
16524+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 16525+ goto out; /* success */
16526+
4f0767ce 16527+out_cache:
1facf9fc 16528+ au_cache_fin();
4f0767ce 16529+out_sysrq:
1facf9fc 16530+ au_sysrq_fin();
4f0767ce 16531+out_hin:
4a4d8108 16532+ au_hnotify_fin();
4f0767ce 16533+out_wkq:
1facf9fc 16534+ au_wkq_fin();
4f0767ce 16535+out_sysaufs:
1facf9fc 16536+ sysaufs_fin();
4a4d8108 16537+ au_dy_fin();
4f0767ce 16538+out:
1facf9fc 16539+ return err;
16540+}
16541+
16542+static void __exit aufs_exit(void)
16543+{
16544+ unregister_filesystem(&aufs_fs_type);
16545+ au_cache_fin();
16546+ au_sysrq_fin();
4a4d8108 16547+ au_hnotify_fin();
1facf9fc 16548+ au_wkq_fin();
16549+ sysaufs_fin();
4a4d8108 16550+ au_dy_fin();
1facf9fc 16551+}
16552+
16553+module_init(aufs_init);
16554+module_exit(aufs_exit);
b752ccd1
AM
16555diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
16556--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
16557+++ linux/fs/aufs/module.h 2010-10-21 09:52:43.093625591 +0200
16558@@ -0,0 +1,82 @@
1facf9fc 16559+/*
4a4d8108 16560+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16561+ *
16562+ * This program, aufs is free software; you can redistribute it and/or modify
16563+ * it under the terms of the GNU General Public License as published by
16564+ * the Free Software Foundation; either version 2 of the License, or
16565+ * (at your option) any later version.
dece6358
AM
16566+ *
16567+ * This program is distributed in the hope that it will be useful,
16568+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16569+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16570+ * GNU General Public License for more details.
16571+ *
16572+ * You should have received a copy of the GNU General Public License
16573+ * along with this program; if not, write to the Free Software
16574+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16575+ */
16576+
16577+/*
16578+ * module initialization and module-global
16579+ */
16580+
16581+#ifndef __AUFS_MODULE_H__
16582+#define __AUFS_MODULE_H__
16583+
16584+#ifdef __KERNEL__
16585+
16586+#include <linux/slab.h>
16587+
dece6358
AM
16588+struct path;
16589+struct seq_file;
16590+
1facf9fc 16591+/* module parameters */
1facf9fc 16592+extern int sysaufs_brs;
16593+
16594+/* ---------------------------------------------------------------------- */
16595+
16596+extern int au_dir_roflags;
16597+
16598+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
16599+int au_seq_path(struct seq_file *seq, struct path *path);
16600+
4f0767ce
JR
16601+/* ---------------------------------------------------------------------- */
16602+
16603+/* kmem cache */
1facf9fc 16604+enum {
16605+ AuCache_DINFO,
16606+ AuCache_ICNTNR,
16607+ AuCache_FINFO,
16608+ AuCache_VDIR,
16609+ AuCache_DEHSTR,
4a4d8108
AM
16610+#ifdef CONFIG_AUFS_HNOTIFY
16611+ AuCache_HNOTIFY,
1facf9fc 16612+#endif
16613+ AuCache_Last
16614+};
16615+
4a4d8108
AM
16616+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
16617+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
16618+#define AuCacheCtor(type, ctor) \
16619+ kmem_cache_create(#type, sizeof(struct type), \
16620+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 16621+
16622+extern struct kmem_cache *au_cachep[];
16623+
16624+#define AuCacheFuncs(name, index) \
4a4d8108 16625+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 16626+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 16627+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 16628+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
16629+
16630+AuCacheFuncs(dinfo, DINFO);
16631+AuCacheFuncs(icntnr, ICNTNR);
16632+AuCacheFuncs(finfo, FINFO);
16633+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
16634+AuCacheFuncs(vdir_dehstr, DEHSTR);
16635+#ifdef CONFIG_AUFS_HNOTIFY
16636+AuCacheFuncs(hnotify, HNOTIFY);
16637+#endif
1facf9fc 16638+
4a4d8108
AM
16639+#endif /* __KERNEL__ */
16640+#endif /* __AUFS_MODULE_H__ */
b752ccd1
AM
16641diff -urN /usr/share/empty/fs/aufs/mtx.h linux/fs/aufs/mtx.h
16642--- /usr/share/empty/fs/aufs/mtx.h 1970-01-01 01:00:00.000000000 +0100
953406b4 16643+++ linux/fs/aufs/mtx.h 2010-10-21 09:52:43.093625591 +0200
4a4d8108
AM
16644@@ -0,0 +1,48 @@
16645+/*
16646+ * Copyright (C) 2010 Junjiro R. Okajima
16647+ *
16648+ * This program, aufs is free software; you can redistribute it and/or modify
16649+ * it under the terms of the GNU General Public License as published by
16650+ * the Free Software Foundation; either version 2 of the License, or
16651+ * (at your option) any later version.
16652+ *
16653+ * This program is distributed in the hope that it will be useful,
16654+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16655+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16656+ * GNU General Public License for more details.
16657+ *
16658+ * You should have received a copy of the GNU General Public License
16659+ * along with this program; if not, write to the Free Software
16660+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16661+ */
16662+
16663+/*
16664+ * very ugly approach for aufs_mmap()
16665+ * never include this file from other than f_op.c.
16666+ * see f_op.c in detail.
16667+ */
16668+
16669+#ifndef __AUFS_MTX_H__
16670+#define __AUFS_MTX_H__
16671+
16672+#ifdef __KERNEL__
16673+
16674+/* copied from ../kernel/mutex{,-debug}.h */
16675+struct mutex;
16676+struct thread_info;
16677+#ifdef CONFIG_DEBUG_MUTEXES
16678+static inline void mutex_set_owner(struct mutex *lock)
16679+{
16680+ lock->owner = current_thread_info();
16681+}
16682+#else
16683+static inline void mutex_set_owner(struct mutex *lock)
16684+{
16685+#ifdef CONFIG_SMP
16686+ lock->owner = current_thread_info();
16687+#endif
16688+}
16689+#endif
1facf9fc 16690+
16691+#endif /* __KERNEL__ */
4a4d8108 16692+#endif /* __AUFS_MTX_H__ */
b752ccd1
AM
16693diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
16694--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
16695+++ linux/fs/aufs/opts.c 2010-10-21 09:52:43.093625591 +0200
16696@@ -0,0 +1,1571 @@
1facf9fc 16697+/*
4a4d8108 16698+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16699+ *
16700+ * This program, aufs is free software; you can redistribute it and/or modify
16701+ * it under the terms of the GNU General Public License as published by
16702+ * the Free Software Foundation; either version 2 of the License, or
16703+ * (at your option) any later version.
dece6358
AM
16704+ *
16705+ * This program is distributed in the hope that it will be useful,
16706+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16707+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16708+ * GNU General Public License for more details.
16709+ *
16710+ * You should have received a copy of the GNU General Public License
16711+ * along with this program; if not, write to the Free Software
16712+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16713+ */
16714+
16715+/*
16716+ * mount options/flags
16717+ */
16718+
dece6358
AM
16719+#include <linux/file.h>
16720+#include <linux/namei.h>
1facf9fc 16721+#include <linux/types.h> /* a distribution requires */
16722+#include <linux/parser.h>
16723+#include "aufs.h"
16724+
16725+/* ---------------------------------------------------------------------- */
16726+
16727+enum {
16728+ Opt_br,
16729+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
16730+ Opt_idel, Opt_imod, Opt_ireorder,
16731+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 16732+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 16733+ Opt_xino, Opt_zxino, Opt_noxino,
16734+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
16735+ Opt_trunc_xino_path, Opt_itrunc_xino,
16736+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 16737+ Opt_shwh, Opt_noshwh,
1facf9fc 16738+ Opt_plink, Opt_noplink, Opt_list_plink,
16739+ Opt_udba,
4a4d8108 16740+ Opt_dio, Opt_nodio,
1facf9fc 16741+ /* Opt_lock, Opt_unlock, */
16742+ Opt_cmd, Opt_cmd_args,
16743+ Opt_diropq_a, Opt_diropq_w,
16744+ Opt_warn_perm, Opt_nowarn_perm,
16745+ Opt_wbr_copyup, Opt_wbr_create,
16746+ Opt_refrof, Opt_norefrof,
16747+ Opt_verbose, Opt_noverbose,
16748+ Opt_sum, Opt_nosum, Opt_wsum,
16749+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
16750+};
16751+
16752+static match_table_t options = {
16753+ {Opt_br, "br=%s"},
16754+ {Opt_br, "br:%s"},
16755+
16756+ {Opt_add, "add=%d:%s"},
16757+ {Opt_add, "add:%d:%s"},
16758+ {Opt_add, "ins=%d:%s"},
16759+ {Opt_add, "ins:%d:%s"},
16760+ {Opt_append, "append=%s"},
16761+ {Opt_append, "append:%s"},
16762+ {Opt_prepend, "prepend=%s"},
16763+ {Opt_prepend, "prepend:%s"},
16764+
16765+ {Opt_del, "del=%s"},
16766+ {Opt_del, "del:%s"},
16767+ /* {Opt_idel, "idel:%d"}, */
16768+ {Opt_mod, "mod=%s"},
16769+ {Opt_mod, "mod:%s"},
16770+ /* {Opt_imod, "imod:%d:%s"}, */
16771+
16772+ {Opt_dirwh, "dirwh=%d"},
16773+
16774+ {Opt_xino, "xino=%s"},
16775+ {Opt_noxino, "noxino"},
16776+ {Opt_trunc_xino, "trunc_xino"},
16777+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
16778+ {Opt_notrunc_xino, "notrunc_xino"},
16779+ {Opt_trunc_xino_path, "trunc_xino=%s"},
16780+ {Opt_itrunc_xino, "itrunc_xino=%d"},
16781+ /* {Opt_zxino, "zxino=%s"}, */
16782+ {Opt_trunc_xib, "trunc_xib"},
16783+ {Opt_notrunc_xib, "notrunc_xib"},
16784+
16785+ {Opt_plink, "plink"},
16786+ {Opt_noplink, "noplink"},
16787+#ifdef CONFIG_AUFS_DEBUG
16788+ {Opt_list_plink, "list_plink"},
16789+#endif
16790+
16791+ {Opt_udba, "udba=%s"},
16792+
4a4d8108
AM
16793+ {Opt_dio, "dio"},
16794+ {Opt_nodio, "nodio"},
16795+
1facf9fc 16796+ {Opt_diropq_a, "diropq=always"},
16797+ {Opt_diropq_a, "diropq=a"},
16798+ {Opt_diropq_w, "diropq=whiteouted"},
16799+ {Opt_diropq_w, "diropq=w"},
16800+
16801+ {Opt_warn_perm, "warn_perm"},
16802+ {Opt_nowarn_perm, "nowarn_perm"},
16803+
16804+ /* keep them temporary */
16805+ {Opt_ignore_silent, "coo=%s"},
16806+ {Opt_ignore_silent, "nodlgt"},
16807+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 16808+ {Opt_ignore_silent, "clean_plink"},
16809+
dece6358
AM
16810+#ifdef CONFIG_AUFS_SHWH
16811+ {Opt_shwh, "shwh"},
16812+#endif
16813+ {Opt_noshwh, "noshwh"},
16814+
1facf9fc 16815+ {Opt_rendir, "rendir=%d"},
16816+
16817+ {Opt_refrof, "refrof"},
16818+ {Opt_norefrof, "norefrof"},
16819+
16820+ {Opt_verbose, "verbose"},
16821+ {Opt_verbose, "v"},
16822+ {Opt_noverbose, "noverbose"},
16823+ {Opt_noverbose, "quiet"},
16824+ {Opt_noverbose, "q"},
16825+ {Opt_noverbose, "silent"},
16826+
16827+ {Opt_sum, "sum"},
16828+ {Opt_nosum, "nosum"},
16829+ {Opt_wsum, "wsum"},
16830+
16831+ {Opt_rdcache, "rdcache=%d"},
16832+ {Opt_rdblk, "rdblk=%d"},
dece6358 16833+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 16834+ {Opt_rdhash, "rdhash=%d"},
dece6358 16835+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 16836+
16837+ {Opt_wbr_create, "create=%s"},
16838+ {Opt_wbr_create, "create_policy=%s"},
16839+ {Opt_wbr_copyup, "cpup=%s"},
16840+ {Opt_wbr_copyup, "copyup=%s"},
16841+ {Opt_wbr_copyup, "copyup_policy=%s"},
16842+
16843+ /* internal use for the scripts */
16844+ {Opt_ignore_silent, "si=%s"},
16845+
16846+ {Opt_br, "dirs=%s"},
16847+ {Opt_ignore, "debug=%d"},
16848+ {Opt_ignore, "delete=whiteout"},
16849+ {Opt_ignore, "delete=all"},
16850+ {Opt_ignore, "imap=%s"},
16851+
1308ab2a 16852+ /* temporary workaround, due to old mount(8)? */
16853+ {Opt_ignore_silent, "relatime"},
16854+
1facf9fc 16855+ {Opt_err, NULL}
16856+};
16857+
16858+/* ---------------------------------------------------------------------- */
16859+
16860+static const char *au_parser_pattern(int val, struct match_token *token)
16861+{
16862+ while (token->pattern) {
16863+ if (token->token == val)
16864+ return token->pattern;
16865+ token++;
16866+ }
16867+ BUG();
16868+ return "??";
16869+}
16870+
16871+/* ---------------------------------------------------------------------- */
16872+
16873+static match_table_t brperms = {
16874+ {AuBrPerm_RO, AUFS_BRPERM_RO},
16875+ {AuBrPerm_RR, AUFS_BRPERM_RR},
16876+ {AuBrPerm_RW, AUFS_BRPERM_RW},
16877+
16878+ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
16879+ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
16880+ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
16881+
16882+ {AuBrPerm_ROWH, "nfsro"},
16883+ {AuBrPerm_RO, NULL}
16884+};
16885+
4a4d8108 16886+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 16887+{
16888+ int val;
16889+ substring_t args[MAX_OPT_ARGS];
16890+
16891+ val = match_token(perm, brperms, args);
16892+ return val;
16893+}
16894+
16895+const char *au_optstr_br_perm(int brperm)
16896+{
16897+ return au_parser_pattern(brperm, (void *)brperms);
16898+}
16899+
16900+/* ---------------------------------------------------------------------- */
16901+
16902+static match_table_t udbalevel = {
16903+ {AuOpt_UDBA_REVAL, "reval"},
16904+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
16905+#ifdef CONFIG_AUFS_HNOTIFY
16906+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
16907+#ifdef CONFIG_AUFS_HFSNOTIFY
16908+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 16909+#endif
1facf9fc 16910+#endif
16911+ {-1, NULL}
16912+};
16913+
4a4d8108 16914+static int noinline_for_stack udba_val(char *str)
1facf9fc 16915+{
16916+ substring_t args[MAX_OPT_ARGS];
16917+
953406b4 16918+ return match_token(str, udbalevel, args);
1facf9fc 16919+}
16920+
16921+const char *au_optstr_udba(int udba)
16922+{
16923+ return au_parser_pattern(udba, (void *)udbalevel);
16924+}
16925+
16926+/* ---------------------------------------------------------------------- */
16927+
16928+static match_table_t au_wbr_create_policy = {
16929+ {AuWbrCreate_TDP, "tdp"},
16930+ {AuWbrCreate_TDP, "top-down-parent"},
16931+ {AuWbrCreate_RR, "rr"},
16932+ {AuWbrCreate_RR, "round-robin"},
16933+ {AuWbrCreate_MFS, "mfs"},
16934+ {AuWbrCreate_MFS, "most-free-space"},
16935+ {AuWbrCreate_MFSV, "mfs:%d"},
16936+ {AuWbrCreate_MFSV, "most-free-space:%d"},
16937+
16938+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
16939+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
16940+ {AuWbrCreate_PMFS, "pmfs"},
16941+ {AuWbrCreate_PMFSV, "pmfs:%d"},
16942+
16943+ {-1, NULL}
16944+};
16945+
dece6358
AM
16946+/*
16947+ * cf. linux/lib/parser.c and cmdline.c
16948+ * gave up calling memparse() since it uses simple_strtoull() instead of
16949+ * strict_...().
16950+ */
4a4d8108
AM
16951+static int noinline_for_stack
16952+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 16953+{
16954+ int err;
16955+ unsigned int len;
16956+ char a[32];
16957+
16958+ err = -ERANGE;
16959+ len = s->to - s->from;
16960+ if (len + 1 <= sizeof(a)) {
16961+ memcpy(a, s->from, len);
16962+ a[len] = '\0';
16963+ err = strict_strtoull(a, 0, result);
16964+ }
16965+ return err;
16966+}
16967+
16968+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
16969+ struct au_opt_wbr_create *create)
16970+{
16971+ int err;
16972+ unsigned long long ull;
16973+
16974+ err = 0;
16975+ if (!au_match_ull(arg, &ull))
16976+ create->mfsrr_watermark = ull;
16977+ else {
4a4d8108 16978+ pr_err("bad integer in %s\n", str);
1facf9fc 16979+ err = -EINVAL;
16980+ }
16981+
16982+ return err;
16983+}
16984+
16985+static int au_wbr_mfs_sec(substring_t *arg, char *str,
16986+ struct au_opt_wbr_create *create)
16987+{
16988+ int n, err;
16989+
16990+ err = 0;
953406b4 16991+ if (!match_int(arg, &n) && 0 <= n)
1facf9fc 16992+ create->mfs_second = n;
16993+ else {
4a4d8108 16994+ pr_err("bad integer in %s\n", str);
1facf9fc 16995+ err = -EINVAL;
16996+ }
16997+
16998+ return err;
16999+}
17000+
4a4d8108
AM
17001+static int noinline_for_stack
17002+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 17003+{
17004+ int err, e;
17005+ substring_t args[MAX_OPT_ARGS];
17006+
17007+ err = match_token(str, au_wbr_create_policy, args);
17008+ create->wbr_create = err;
17009+ switch (err) {
17010+ case AuWbrCreate_MFSRRV:
17011+ e = au_wbr_mfs_wmark(&args[0], str, create);
17012+ if (!e)
17013+ e = au_wbr_mfs_sec(&args[1], str, create);
17014+ if (unlikely(e))
17015+ err = e;
17016+ break;
17017+ case AuWbrCreate_MFSRR:
17018+ e = au_wbr_mfs_wmark(&args[0], str, create);
17019+ if (unlikely(e)) {
17020+ err = e;
17021+ break;
17022+ }
17023+ /*FALLTHROUGH*/
17024+ case AuWbrCreate_MFS:
17025+ case AuWbrCreate_PMFS:
17026+ create->mfs_second = AUFS_MFS_SECOND_DEF;
17027+ break;
17028+ case AuWbrCreate_MFSV:
17029+ case AuWbrCreate_PMFSV:
17030+ e = au_wbr_mfs_sec(&args[0], str, create);
17031+ if (unlikely(e))
17032+ err = e;
17033+ break;
17034+ }
17035+
17036+ return err;
17037+}
17038+
17039+const char *au_optstr_wbr_create(int wbr_create)
17040+{
17041+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
17042+}
17043+
17044+static match_table_t au_wbr_copyup_policy = {
17045+ {AuWbrCopyup_TDP, "tdp"},
17046+ {AuWbrCopyup_TDP, "top-down-parent"},
17047+ {AuWbrCopyup_BUP, "bup"},
17048+ {AuWbrCopyup_BUP, "bottom-up-parent"},
17049+ {AuWbrCopyup_BU, "bu"},
17050+ {AuWbrCopyup_BU, "bottom-up"},
17051+ {-1, NULL}
17052+};
17053+
4a4d8108 17054+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 17055+{
17056+ substring_t args[MAX_OPT_ARGS];
17057+
17058+ return match_token(str, au_wbr_copyup_policy, args);
17059+}
17060+
17061+const char *au_optstr_wbr_copyup(int wbr_copyup)
17062+{
17063+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
17064+}
17065+
17066+/* ---------------------------------------------------------------------- */
17067+
17068+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
17069+
17070+static void dump_opts(struct au_opts *opts)
17071+{
17072+#ifdef CONFIG_AUFS_DEBUG
17073+ /* reduce stack space */
17074+ union {
17075+ struct au_opt_add *add;
17076+ struct au_opt_del *del;
17077+ struct au_opt_mod *mod;
17078+ struct au_opt_xino *xino;
17079+ struct au_opt_xino_itrunc *xino_itrunc;
17080+ struct au_opt_wbr_create *create;
17081+ } u;
17082+ struct au_opt *opt;
17083+
17084+ opt = opts->opt;
17085+ while (opt->type != Opt_tail) {
17086+ switch (opt->type) {
17087+ case Opt_add:
17088+ u.add = &opt->add;
17089+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
17090+ u.add->bindex, u.add->pathname, u.add->perm,
17091+ u.add->path.dentry);
17092+ break;
17093+ case Opt_del:
17094+ case Opt_idel:
17095+ u.del = &opt->del;
17096+ AuDbg("del {%s, %p}\n",
17097+ u.del->pathname, u.del->h_path.dentry);
17098+ break;
17099+ case Opt_mod:
17100+ case Opt_imod:
17101+ u.mod = &opt->mod;
17102+ AuDbg("mod {%s, 0x%x, %p}\n",
17103+ u.mod->path, u.mod->perm, u.mod->h_root);
17104+ break;
17105+ case Opt_append:
17106+ u.add = &opt->add;
17107+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
17108+ u.add->bindex, u.add->pathname, u.add->perm,
17109+ u.add->path.dentry);
17110+ break;
17111+ case Opt_prepend:
17112+ u.add = &opt->add;
17113+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
17114+ u.add->bindex, u.add->pathname, u.add->perm,
17115+ u.add->path.dentry);
17116+ break;
17117+ case Opt_dirwh:
17118+ AuDbg("dirwh %d\n", opt->dirwh);
17119+ break;
17120+ case Opt_rdcache:
17121+ AuDbg("rdcache %d\n", opt->rdcache);
17122+ break;
17123+ case Opt_rdblk:
17124+ AuDbg("rdblk %u\n", opt->rdblk);
17125+ break;
dece6358
AM
17126+ case Opt_rdblk_def:
17127+ AuDbg("rdblk_def\n");
17128+ break;
1facf9fc 17129+ case Opt_rdhash:
17130+ AuDbg("rdhash %u\n", opt->rdhash);
17131+ break;
dece6358
AM
17132+ case Opt_rdhash_def:
17133+ AuDbg("rdhash_def\n");
17134+ break;
1facf9fc 17135+ case Opt_xino:
17136+ u.xino = &opt->xino;
17137+ AuDbg("xino {%s %.*s}\n",
17138+ u.xino->path,
17139+ AuDLNPair(u.xino->file->f_dentry));
17140+ break;
17141+ case Opt_trunc_xino:
17142+ AuLabel(trunc_xino);
17143+ break;
17144+ case Opt_notrunc_xino:
17145+ AuLabel(notrunc_xino);
17146+ break;
17147+ case Opt_trunc_xino_path:
17148+ case Opt_itrunc_xino:
17149+ u.xino_itrunc = &opt->xino_itrunc;
17150+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
17151+ break;
17152+
17153+ case Opt_noxino:
17154+ AuLabel(noxino);
17155+ break;
17156+ case Opt_trunc_xib:
17157+ AuLabel(trunc_xib);
17158+ break;
17159+ case Opt_notrunc_xib:
17160+ AuLabel(notrunc_xib);
17161+ break;
dece6358
AM
17162+ case Opt_shwh:
17163+ AuLabel(shwh);
17164+ break;
17165+ case Opt_noshwh:
17166+ AuLabel(noshwh);
17167+ break;
1facf9fc 17168+ case Opt_plink:
17169+ AuLabel(plink);
17170+ break;
17171+ case Opt_noplink:
17172+ AuLabel(noplink);
17173+ break;
17174+ case Opt_list_plink:
17175+ AuLabel(list_plink);
17176+ break;
17177+ case Opt_udba:
17178+ AuDbg("udba %d, %s\n",
17179+ opt->udba, au_optstr_udba(opt->udba));
17180+ break;
4a4d8108
AM
17181+ case Opt_dio:
17182+ AuLabel(dio);
17183+ break;
17184+ case Opt_nodio:
17185+ AuLabel(nodio);
17186+ break;
1facf9fc 17187+ case Opt_diropq_a:
17188+ AuLabel(diropq_a);
17189+ break;
17190+ case Opt_diropq_w:
17191+ AuLabel(diropq_w);
17192+ break;
17193+ case Opt_warn_perm:
17194+ AuLabel(warn_perm);
17195+ break;
17196+ case Opt_nowarn_perm:
17197+ AuLabel(nowarn_perm);
17198+ break;
17199+ case Opt_refrof:
17200+ AuLabel(refrof);
17201+ break;
17202+ case Opt_norefrof:
17203+ AuLabel(norefrof);
17204+ break;
17205+ case Opt_verbose:
17206+ AuLabel(verbose);
17207+ break;
17208+ case Opt_noverbose:
17209+ AuLabel(noverbose);
17210+ break;
17211+ case Opt_sum:
17212+ AuLabel(sum);
17213+ break;
17214+ case Opt_nosum:
17215+ AuLabel(nosum);
17216+ break;
17217+ case Opt_wsum:
17218+ AuLabel(wsum);
17219+ break;
17220+ case Opt_wbr_create:
17221+ u.create = &opt->wbr_create;
17222+ AuDbg("create %d, %s\n", u.create->wbr_create,
17223+ au_optstr_wbr_create(u.create->wbr_create));
17224+ switch (u.create->wbr_create) {
17225+ case AuWbrCreate_MFSV:
17226+ case AuWbrCreate_PMFSV:
17227+ AuDbg("%d sec\n", u.create->mfs_second);
17228+ break;
17229+ case AuWbrCreate_MFSRR:
17230+ AuDbg("%llu watermark\n",
17231+ u.create->mfsrr_watermark);
17232+ break;
17233+ case AuWbrCreate_MFSRRV:
17234+ AuDbg("%llu watermark, %d sec\n",
17235+ u.create->mfsrr_watermark,
17236+ u.create->mfs_second);
17237+ break;
17238+ }
17239+ break;
17240+ case Opt_wbr_copyup:
17241+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
17242+ au_optstr_wbr_copyup(opt->wbr_copyup));
17243+ break;
17244+ default:
17245+ BUG();
17246+ }
17247+ opt++;
17248+ }
17249+#endif
17250+}
17251+
17252+void au_opts_free(struct au_opts *opts)
17253+{
17254+ struct au_opt *opt;
17255+
17256+ opt = opts->opt;
17257+ while (opt->type != Opt_tail) {
17258+ switch (opt->type) {
17259+ case Opt_add:
17260+ case Opt_append:
17261+ case Opt_prepend:
17262+ path_put(&opt->add.path);
17263+ break;
17264+ case Opt_del:
17265+ case Opt_idel:
17266+ path_put(&opt->del.h_path);
17267+ break;
17268+ case Opt_mod:
17269+ case Opt_imod:
17270+ dput(opt->mod.h_root);
17271+ break;
17272+ case Opt_xino:
17273+ fput(opt->xino.file);
17274+ break;
17275+ }
17276+ opt++;
17277+ }
17278+}
17279+
17280+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
17281+ aufs_bindex_t bindex)
17282+{
17283+ int err;
17284+ struct au_opt_add *add = &opt->add;
17285+ char *p;
17286+
17287+ add->bindex = bindex;
17288+ add->perm = AuBrPerm_Last;
17289+ add->pathname = opt_str;
17290+ p = strchr(opt_str, '=');
17291+ if (p) {
17292+ *p++ = 0;
17293+ if (*p)
17294+ add->perm = br_perm_val(p);
17295+ }
17296+
17297+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
17298+ if (!err) {
17299+ if (!p) {
17300+ add->perm = AuBrPerm_RO;
17301+ if (au_test_fs_rr(add->path.dentry->d_sb))
17302+ add->perm = AuBrPerm_RR;
17303+ else if (!bindex && !(sb_flags & MS_RDONLY))
17304+ add->perm = AuBrPerm_RW;
17305+ }
17306+ opt->type = Opt_add;
17307+ goto out;
17308+ }
4a4d8108 17309+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 17310+ err = -EINVAL;
17311+
4f0767ce 17312+out:
1facf9fc 17313+ return err;
17314+}
17315+
17316+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
17317+{
17318+ int err;
17319+
17320+ del->pathname = args[0].from;
17321+ AuDbg("del path %s\n", del->pathname);
17322+
17323+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
17324+ if (unlikely(err))
4a4d8108 17325+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 17326+
17327+ return err;
17328+}
17329+
17330+#if 0 /* reserved for future use */
17331+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
17332+ struct au_opt_del *del, substring_t args[])
17333+{
17334+ int err;
17335+ struct dentry *root;
17336+
17337+ err = -EINVAL;
17338+ root = sb->s_root;
17339+ aufs_read_lock(root, AuLock_FLUSH);
17340+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17341+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17342+ goto out;
17343+ }
17344+
17345+ err = 0;
17346+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
17347+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
17348+
4f0767ce 17349+out:
1facf9fc 17350+ aufs_read_unlock(root, !AuLock_IR);
17351+ return err;
17352+}
17353+#endif
17354+
4a4d8108
AM
17355+static int noinline_for_stack
17356+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 17357+{
17358+ int err;
17359+ struct path path;
17360+ char *p;
17361+
17362+ err = -EINVAL;
17363+ mod->path = args[0].from;
17364+ p = strchr(mod->path, '=');
17365+ if (unlikely(!p)) {
4a4d8108 17366+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 17367+ goto out;
17368+ }
17369+
17370+ *p++ = 0;
17371+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
17372+ if (unlikely(err)) {
4a4d8108 17373+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 17374+ goto out;
17375+ }
17376+
17377+ mod->perm = br_perm_val(p);
17378+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
17379+ mod->h_root = dget(path.dentry);
17380+ path_put(&path);
17381+
4f0767ce 17382+out:
1facf9fc 17383+ return err;
17384+}
17385+
17386+#if 0 /* reserved for future use */
17387+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
17388+ struct au_opt_mod *mod, substring_t args[])
17389+{
17390+ int err;
17391+ struct dentry *root;
17392+
17393+ err = -EINVAL;
17394+ root = sb->s_root;
17395+ aufs_read_lock(root, AuLock_FLUSH);
17396+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17397+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17398+ goto out;
17399+ }
17400+
17401+ err = 0;
17402+ mod->perm = br_perm_val(args[1].from);
17403+ AuDbg("mod path %s, perm 0x%x, %s\n",
17404+ mod->path, mod->perm, args[1].from);
17405+ mod->h_root = dget(au_h_dptr(root, bindex));
17406+
4f0767ce 17407+out:
1facf9fc 17408+ aufs_read_unlock(root, !AuLock_IR);
17409+ return err;
17410+}
17411+#endif
17412+
17413+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
17414+ substring_t args[])
17415+{
17416+ int err;
17417+ struct file *file;
17418+
17419+ file = au_xino_create(sb, args[0].from, /*silent*/0);
17420+ err = PTR_ERR(file);
17421+ if (IS_ERR(file))
17422+ goto out;
17423+
17424+ err = -EINVAL;
17425+ if (unlikely(file->f_dentry->d_sb == sb)) {
17426+ fput(file);
4a4d8108 17427+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 17428+ goto out;
17429+ }
17430+
17431+ err = 0;
17432+ xino->file = file;
17433+ xino->path = args[0].from;
17434+
4f0767ce 17435+out:
1facf9fc 17436+ return err;
17437+}
17438+
4a4d8108
AM
17439+static int noinline_for_stack
17440+au_opts_parse_xino_itrunc_path(struct super_block *sb,
17441+ struct au_opt_xino_itrunc *xino_itrunc,
17442+ substring_t args[])
1facf9fc 17443+{
17444+ int err;
17445+ aufs_bindex_t bend, bindex;
17446+ struct path path;
17447+ struct dentry *root;
17448+
17449+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
17450+ if (unlikely(err)) {
4a4d8108 17451+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 17452+ goto out;
17453+ }
17454+
17455+ xino_itrunc->bindex = -1;
17456+ root = sb->s_root;
17457+ aufs_read_lock(root, AuLock_FLUSH);
17458+ bend = au_sbend(sb);
17459+ for (bindex = 0; bindex <= bend; bindex++) {
17460+ if (au_h_dptr(root, bindex) == path.dentry) {
17461+ xino_itrunc->bindex = bindex;
17462+ break;
17463+ }
17464+ }
17465+ aufs_read_unlock(root, !AuLock_IR);
17466+ path_put(&path);
17467+
17468+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 17469+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 17470+ err = -EINVAL;
17471+ }
17472+
4f0767ce 17473+out:
1facf9fc 17474+ return err;
17475+}
17476+
17477+/* called without aufs lock */
17478+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
17479+{
17480+ int err, n, token;
17481+ aufs_bindex_t bindex;
17482+ unsigned char skipped;
17483+ struct dentry *root;
17484+ struct au_opt *opt, *opt_tail;
17485+ char *opt_str;
17486+ /* reduce the stack space */
17487+ union {
17488+ struct au_opt_xino_itrunc *xino_itrunc;
17489+ struct au_opt_wbr_create *create;
17490+ } u;
17491+ struct {
17492+ substring_t args[MAX_OPT_ARGS];
17493+ } *a;
17494+
17495+ err = -ENOMEM;
17496+ a = kmalloc(sizeof(*a), GFP_NOFS);
17497+ if (unlikely(!a))
17498+ goto out;
17499+
17500+ root = sb->s_root;
17501+ err = 0;
17502+ bindex = 0;
17503+ opt = opts->opt;
17504+ opt_tail = opt + opts->max_opt - 1;
17505+ opt->type = Opt_tail;
17506+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
17507+ err = -EINVAL;
17508+ skipped = 0;
17509+ token = match_token(opt_str, options, a->args);
17510+ switch (token) {
17511+ case Opt_br:
17512+ err = 0;
17513+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
17514+ && *opt_str) {
17515+ err = opt_add(opt, opt_str, opts->sb_flags,
17516+ bindex++);
17517+ if (unlikely(!err && ++opt > opt_tail)) {
17518+ err = -E2BIG;
17519+ break;
17520+ }
17521+ opt->type = Opt_tail;
17522+ skipped = 1;
17523+ }
17524+ break;
17525+ case Opt_add:
17526+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17527+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17528+ break;
17529+ }
17530+ bindex = n;
17531+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
17532+ bindex);
17533+ if (!err)
17534+ opt->type = token;
17535+ break;
17536+ case Opt_append:
17537+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17538+ /*dummy bindex*/1);
17539+ if (!err)
17540+ opt->type = token;
17541+ break;
17542+ case Opt_prepend:
17543+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17544+ /*bindex*/0);
17545+ if (!err)
17546+ opt->type = token;
17547+ break;
17548+ case Opt_del:
17549+ err = au_opts_parse_del(&opt->del, a->args);
17550+ if (!err)
17551+ opt->type = token;
17552+ break;
17553+#if 0 /* reserved for future use */
17554+ case Opt_idel:
17555+ del->pathname = "(indexed)";
17556+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 17557+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17558+ break;
17559+ }
17560+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
17561+ if (!err)
17562+ opt->type = token;
17563+ break;
17564+#endif
17565+ case Opt_mod:
17566+ err = au_opts_parse_mod(&opt->mod, a->args);
17567+ if (!err)
17568+ opt->type = token;
17569+ break;
17570+#ifdef IMOD /* reserved for future use */
17571+ case Opt_imod:
17572+ u.mod->path = "(indexed)";
17573+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17574+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17575+ break;
17576+ }
17577+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
17578+ if (!err)
17579+ opt->type = token;
17580+ break;
17581+#endif
17582+ case Opt_xino:
17583+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
17584+ if (!err)
17585+ opt->type = token;
17586+ break;
17587+
17588+ case Opt_trunc_xino_path:
17589+ err = au_opts_parse_xino_itrunc_path
17590+ (sb, &opt->xino_itrunc, a->args);
17591+ if (!err)
17592+ opt->type = token;
17593+ break;
17594+
17595+ case Opt_itrunc_xino:
17596+ u.xino_itrunc = &opt->xino_itrunc;
17597+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17598+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17599+ break;
17600+ }
17601+ u.xino_itrunc->bindex = n;
17602+ aufs_read_lock(root, AuLock_FLUSH);
17603+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 17604+ pr_err("out of bounds, %d\n", n);
1facf9fc 17605+ aufs_read_unlock(root, !AuLock_IR);
17606+ break;
17607+ }
17608+ aufs_read_unlock(root, !AuLock_IR);
17609+ err = 0;
17610+ opt->type = token;
17611+ break;
17612+
17613+ case Opt_dirwh:
17614+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
17615+ break;
17616+ err = 0;
17617+ opt->type = token;
17618+ break;
17619+
17620+ case Opt_rdcache:
953406b4 17621+ if (unlikely(match_int(&a->args[0], &opt->rdcache)))
1facf9fc 17622+ break;
17623+ err = 0;
17624+ opt->type = token;
17625+ break;
17626+ case Opt_rdblk:
17627+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17628+ || n < 0
1facf9fc 17629+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 17630+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17631+ break;
17632+ }
1308ab2a 17633+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
17634+ pr_err("rdblk must be larger than %d\n",
17635+ NAME_MAX);
1facf9fc 17636+ break;
17637+ }
17638+ opt->rdblk = n;
17639+ err = 0;
17640+ opt->type = token;
17641+ break;
17642+ case Opt_rdhash:
17643+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17644+ || n < 0
1facf9fc 17645+ || n * sizeof(struct hlist_head)
17646+ > KMALLOC_MAX_SIZE)) {
4a4d8108 17647+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17648+ break;
17649+ }
17650+ opt->rdhash = n;
17651+ err = 0;
17652+ opt->type = token;
17653+ break;
17654+
17655+ case Opt_trunc_xino:
17656+ case Opt_notrunc_xino:
17657+ case Opt_noxino:
17658+ case Opt_trunc_xib:
17659+ case Opt_notrunc_xib:
dece6358
AM
17660+ case Opt_shwh:
17661+ case Opt_noshwh:
1facf9fc 17662+ case Opt_plink:
17663+ case Opt_noplink:
17664+ case Opt_list_plink:
4a4d8108
AM
17665+ case Opt_dio:
17666+ case Opt_nodio:
1facf9fc 17667+ case Opt_diropq_a:
17668+ case Opt_diropq_w:
17669+ case Opt_warn_perm:
17670+ case Opt_nowarn_perm:
17671+ case Opt_refrof:
17672+ case Opt_norefrof:
17673+ case Opt_verbose:
17674+ case Opt_noverbose:
17675+ case Opt_sum:
17676+ case Opt_nosum:
17677+ case Opt_wsum:
dece6358
AM
17678+ case Opt_rdblk_def:
17679+ case Opt_rdhash_def:
1facf9fc 17680+ err = 0;
17681+ opt->type = token;
17682+ break;
17683+
17684+ case Opt_udba:
17685+ opt->udba = udba_val(a->args[0].from);
17686+ if (opt->udba >= 0) {
17687+ err = 0;
17688+ opt->type = token;
17689+ } else
4a4d8108 17690+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17691+ break;
17692+
17693+ case Opt_wbr_create:
17694+ u.create = &opt->wbr_create;
17695+ u.create->wbr_create
17696+ = au_wbr_create_val(a->args[0].from, u.create);
17697+ if (u.create->wbr_create >= 0) {
17698+ err = 0;
17699+ opt->type = token;
17700+ } else
4a4d8108 17701+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17702+ break;
17703+ case Opt_wbr_copyup:
17704+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
17705+ if (opt->wbr_copyup >= 0) {
17706+ err = 0;
17707+ opt->type = token;
17708+ } else
4a4d8108 17709+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17710+ break;
17711+
17712+ case Opt_ignore:
4a4d8108 17713+ pr_warning("ignored %s\n", opt_str);
1facf9fc 17714+ /*FALLTHROUGH*/
17715+ case Opt_ignore_silent:
17716+ skipped = 1;
17717+ err = 0;
17718+ break;
17719+ case Opt_err:
4a4d8108 17720+ pr_err("unknown option %s\n", opt_str);
1facf9fc 17721+ break;
17722+ }
17723+
17724+ if (!err && !skipped) {
17725+ if (unlikely(++opt > opt_tail)) {
17726+ err = -E2BIG;
17727+ opt--;
17728+ opt->type = Opt_tail;
17729+ break;
17730+ }
17731+ opt->type = Opt_tail;
17732+ }
17733+ }
17734+
17735+ kfree(a);
17736+ dump_opts(opts);
17737+ if (unlikely(err))
17738+ au_opts_free(opts);
17739+
4f0767ce 17740+out:
1facf9fc 17741+ return err;
17742+}
17743+
17744+static int au_opt_wbr_create(struct super_block *sb,
17745+ struct au_opt_wbr_create *create)
17746+{
17747+ int err;
17748+ struct au_sbinfo *sbinfo;
17749+
dece6358
AM
17750+ SiMustWriteLock(sb);
17751+
1facf9fc 17752+ err = 1; /* handled */
17753+ sbinfo = au_sbi(sb);
17754+ if (sbinfo->si_wbr_create_ops->fin) {
17755+ err = sbinfo->si_wbr_create_ops->fin(sb);
17756+ if (!err)
17757+ err = 1;
17758+ }
17759+
17760+ sbinfo->si_wbr_create = create->wbr_create;
17761+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
17762+ switch (create->wbr_create) {
17763+ case AuWbrCreate_MFSRRV:
17764+ case AuWbrCreate_MFSRR:
17765+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
17766+ /*FALLTHROUGH*/
17767+ case AuWbrCreate_MFS:
17768+ case AuWbrCreate_MFSV:
17769+ case AuWbrCreate_PMFS:
17770+ case AuWbrCreate_PMFSV:
953406b4 17771+ sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
1facf9fc 17772+ break;
17773+ }
17774+
17775+ if (sbinfo->si_wbr_create_ops->init)
17776+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
17777+
17778+ return err;
17779+}
17780+
17781+/*
17782+ * returns,
17783+ * plus: processed without an error
17784+ * zero: unprocessed
17785+ */
17786+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
17787+ struct au_opts *opts)
17788+{
17789+ int err;
17790+ struct au_sbinfo *sbinfo;
17791+
dece6358
AM
17792+ SiMustWriteLock(sb);
17793+
1facf9fc 17794+ err = 1; /* handled */
17795+ sbinfo = au_sbi(sb);
17796+ switch (opt->type) {
17797+ case Opt_udba:
17798+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
17799+ sbinfo->si_mntflags |= opt->udba;
17800+ opts->given_udba |= opt->udba;
17801+ break;
17802+
17803+ case Opt_plink:
17804+ au_opt_set(sbinfo->si_mntflags, PLINK);
17805+ break;
17806+ case Opt_noplink:
17807+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
953406b4 17808+ au_plink_put(sb);
1facf9fc 17809+ au_opt_clr(sbinfo->si_mntflags, PLINK);
17810+ break;
17811+ case Opt_list_plink:
17812+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
17813+ au_plink_list(sb);
17814+ break;
17815+
4a4d8108
AM
17816+ case Opt_dio:
17817+ au_opt_set(sbinfo->si_mntflags, DIO);
17818+ au_fset_opts(opts->flags, REFRESH_DYAOP);
17819+ break;
17820+ case Opt_nodio:
17821+ au_opt_clr(sbinfo->si_mntflags, DIO);
17822+ au_fset_opts(opts->flags, REFRESH_DYAOP);
17823+ break;
17824+
1facf9fc 17825+ case Opt_diropq_a:
17826+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
17827+ break;
17828+ case Opt_diropq_w:
17829+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
17830+ break;
17831+
17832+ case Opt_warn_perm:
17833+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
17834+ break;
17835+ case Opt_nowarn_perm:
17836+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
17837+ break;
17838+
17839+ case Opt_refrof:
17840+ au_opt_set(sbinfo->si_mntflags, REFROF);
17841+ break;
17842+ case Opt_norefrof:
17843+ au_opt_clr(sbinfo->si_mntflags, REFROF);
17844+ break;
17845+
17846+ case Opt_verbose:
17847+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
17848+ break;
17849+ case Opt_noverbose:
17850+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
17851+ break;
17852+
17853+ case Opt_sum:
17854+ au_opt_set(sbinfo->si_mntflags, SUM);
17855+ break;
17856+ case Opt_wsum:
17857+ au_opt_clr(sbinfo->si_mntflags, SUM);
17858+ au_opt_set(sbinfo->si_mntflags, SUM_W);
17859+ case Opt_nosum:
17860+ au_opt_clr(sbinfo->si_mntflags, SUM);
17861+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
17862+ break;
17863+
17864+ case Opt_wbr_create:
17865+ err = au_opt_wbr_create(sb, &opt->wbr_create);
17866+ break;
17867+ case Opt_wbr_copyup:
17868+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
17869+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
17870+ break;
17871+
17872+ case Opt_dirwh:
17873+ sbinfo->si_dirwh = opt->dirwh;
17874+ break;
17875+
17876+ case Opt_rdcache:
953406b4 17877+ sbinfo->si_rdcache = opt->rdcache * HZ;
1facf9fc 17878+ break;
17879+ case Opt_rdblk:
17880+ sbinfo->si_rdblk = opt->rdblk;
17881+ break;
dece6358
AM
17882+ case Opt_rdblk_def:
17883+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
17884+ break;
1facf9fc 17885+ case Opt_rdhash:
17886+ sbinfo->si_rdhash = opt->rdhash;
17887+ break;
dece6358
AM
17888+ case Opt_rdhash_def:
17889+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
17890+ break;
17891+
17892+ case Opt_shwh:
17893+ au_opt_set(sbinfo->si_mntflags, SHWH);
17894+ break;
17895+ case Opt_noshwh:
17896+ au_opt_clr(sbinfo->si_mntflags, SHWH);
17897+ break;
1facf9fc 17898+
17899+ case Opt_trunc_xino:
17900+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
17901+ break;
17902+ case Opt_notrunc_xino:
17903+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
17904+ break;
17905+
17906+ case Opt_trunc_xino_path:
17907+ case Opt_itrunc_xino:
17908+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
17909+ if (!err)
17910+ err = 1;
17911+ break;
17912+
17913+ case Opt_trunc_xib:
17914+ au_fset_opts(opts->flags, TRUNC_XIB);
17915+ break;
17916+ case Opt_notrunc_xib:
17917+ au_fclr_opts(opts->flags, TRUNC_XIB);
17918+ break;
17919+
17920+ default:
17921+ err = 0;
17922+ break;
17923+ }
17924+
17925+ return err;
17926+}
17927+
17928+/*
17929+ * returns tri-state.
17930+ * plus: processed without an error
17931+ * zero: unprocessed
17932+ * minus: error
17933+ */
17934+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
17935+ struct au_opts *opts)
17936+{
17937+ int err, do_refresh;
17938+
17939+ err = 0;
17940+ switch (opt->type) {
17941+ case Opt_append:
17942+ opt->add.bindex = au_sbend(sb) + 1;
17943+ if (opt->add.bindex < 0)
17944+ opt->add.bindex = 0;
17945+ goto add;
17946+ case Opt_prepend:
17947+ opt->add.bindex = 0;
17948+ add:
17949+ case Opt_add:
17950+ err = au_br_add(sb, &opt->add,
17951+ au_ftest_opts(opts->flags, REMOUNT));
17952+ if (!err) {
17953+ err = 1;
17954+ au_fset_opts(opts->flags, REFRESH_DIR);
4a4d8108 17955+ au_fset_opts(opts->flags, REFRESH_NONDIR);
1facf9fc 17956+ }
17957+ break;
17958+
17959+ case Opt_del:
17960+ case Opt_idel:
17961+ err = au_br_del(sb, &opt->del,
17962+ au_ftest_opts(opts->flags, REMOUNT));
17963+ if (!err) {
17964+ err = 1;
17965+ au_fset_opts(opts->flags, TRUNC_XIB);
17966+ au_fset_opts(opts->flags, REFRESH_DIR);
17967+ au_fset_opts(opts->flags, REFRESH_NONDIR);
17968+ }
17969+ break;
17970+
17971+ case Opt_mod:
17972+ case Opt_imod:
17973+ err = au_br_mod(sb, &opt->mod,
17974+ au_ftest_opts(opts->flags, REMOUNT),
17975+ &do_refresh);
17976+ if (!err) {
17977+ err = 1;
17978+ if (do_refresh) {
17979+ au_fset_opts(opts->flags, REFRESH_DIR);
17980+ au_fset_opts(opts->flags, REFRESH_NONDIR);
17981+ }
17982+ }
17983+ break;
17984+ }
17985+
17986+ return err;
17987+}
17988+
17989+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
17990+ struct au_opt_xino **opt_xino,
17991+ struct au_opts *opts)
17992+{
17993+ int err;
17994+ aufs_bindex_t bend, bindex;
17995+ struct dentry *root, *parent, *h_root;
17996+
17997+ err = 0;
17998+ switch (opt->type) {
17999+ case Opt_xino:
18000+ err = au_xino_set(sb, &opt->xino,
18001+ !!au_ftest_opts(opts->flags, REMOUNT));
18002+ if (unlikely(err))
18003+ break;
18004+
18005+ *opt_xino = &opt->xino;
18006+ au_xino_brid_set(sb, -1);
18007+
18008+ /* safe d_parent access */
18009+ parent = opt->xino.file->f_dentry->d_parent;
18010+ root = sb->s_root;
18011+ bend = au_sbend(sb);
18012+ for (bindex = 0; bindex <= bend; bindex++) {
18013+ h_root = au_h_dptr(root, bindex);
18014+ if (h_root == parent) {
18015+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
18016+ break;
18017+ }
18018+ }
18019+ break;
18020+
18021+ case Opt_noxino:
18022+ au_xino_clr(sb);
18023+ au_xino_brid_set(sb, -1);
18024+ *opt_xino = (void *)-1;
18025+ break;
18026+ }
18027+
18028+ return err;
18029+}
18030+
18031+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18032+ unsigned int pending)
18033+{
18034+ int err;
18035+ aufs_bindex_t bindex, bend;
18036+ unsigned char do_plink, skip, do_free;
18037+ struct au_branch *br;
18038+ struct au_wbr *wbr;
18039+ struct dentry *root;
18040+ struct inode *dir, *h_dir;
18041+ struct au_sbinfo *sbinfo;
18042+ struct au_hinode *hdir;
18043+
dece6358
AM
18044+ SiMustAnyLock(sb);
18045+
1facf9fc 18046+ sbinfo = au_sbi(sb);
18047+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
18048+
dece6358
AM
18049+ if (!(sb_flags & MS_RDONLY)) {
18050+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
4a4d8108 18051+ pr_warning("first branch should be rw\n");
dece6358 18052+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
4a4d8108 18053+ pr_warning("shwh should be used with ro\n");
dece6358 18054+ }
1facf9fc 18055+
4a4d8108 18056+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 18057+ && !au_opt_test(sbinfo->si_mntflags, XINO))
4a4d8108 18058+ pr_warning("udba=*notify requires xino\n");
1facf9fc 18059+
18060+ err = 0;
18061+ root = sb->s_root;
4a4d8108 18062+ dir = root->d_inode;
1facf9fc 18063+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
18064+ bend = au_sbend(sb);
18065+ for (bindex = 0; !err && bindex <= bend; bindex++) {
18066+ skip = 0;
18067+ h_dir = au_h_iptr(dir, bindex);
18068+ br = au_sbr(sb, bindex);
18069+ do_free = 0;
18070+
18071+ wbr = br->br_wbr;
18072+ if (wbr)
18073+ wbr_wh_read_lock(wbr);
18074+
18075+ switch (br->br_perm) {
18076+ case AuBrPerm_RO:
18077+ case AuBrPerm_ROWH:
18078+ case AuBrPerm_RR:
18079+ case AuBrPerm_RRWH:
18080+ do_free = !!wbr;
18081+ skip = (!wbr
18082+ || (!wbr->wbr_whbase
18083+ && !wbr->wbr_plink
18084+ && !wbr->wbr_orph));
18085+ break;
18086+
18087+ case AuBrPerm_RWNoLinkWH:
18088+ /* skip = (!br->br_whbase && !br->br_orph); */
18089+ skip = (!wbr || !wbr->wbr_whbase);
18090+ if (skip && wbr) {
18091+ if (do_plink)
18092+ skip = !!wbr->wbr_plink;
18093+ else
18094+ skip = !wbr->wbr_plink;
18095+ }
18096+ break;
18097+
18098+ case AuBrPerm_RW:
18099+ /* skip = (br->br_whbase && br->br_ohph); */
18100+ skip = (wbr && wbr->wbr_whbase);
18101+ if (skip) {
18102+ if (do_plink)
18103+ skip = !!wbr->wbr_plink;
18104+ else
18105+ skip = !wbr->wbr_plink;
18106+ }
18107+ break;
18108+
18109+ default:
18110+ BUG();
18111+ }
18112+ if (wbr)
18113+ wbr_wh_read_unlock(wbr);
18114+
18115+ if (skip)
18116+ continue;
18117+
18118+ hdir = au_hi(dir, bindex);
4a4d8108 18119+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 18120+ if (wbr)
18121+ wbr_wh_write_lock(wbr);
18122+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
18123+ if (wbr)
18124+ wbr_wh_write_unlock(wbr);
4a4d8108 18125+ au_hn_imtx_unlock(hdir);
1facf9fc 18126+
18127+ if (!err && do_free) {
18128+ kfree(wbr);
18129+ br->br_wbr = NULL;
18130+ }
18131+ }
18132+
18133+ return err;
18134+}
18135+
18136+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
18137+{
18138+ int err;
18139+ unsigned int tmp;
18140+ aufs_bindex_t bend;
18141+ struct au_opt *opt;
18142+ struct au_opt_xino *opt_xino, xino;
18143+ struct au_sbinfo *sbinfo;
18144+
dece6358
AM
18145+ SiMustWriteLock(sb);
18146+
1facf9fc 18147+ err = 0;
18148+ opt_xino = NULL;
18149+ opt = opts->opt;
18150+ while (err >= 0 && opt->type != Opt_tail)
18151+ err = au_opt_simple(sb, opt++, opts);
18152+ if (err > 0)
18153+ err = 0;
18154+ else if (unlikely(err < 0))
18155+ goto out;
18156+
18157+ /* disable xino and udba temporary */
18158+ sbinfo = au_sbi(sb);
18159+ tmp = sbinfo->si_mntflags;
18160+ au_opt_clr(sbinfo->si_mntflags, XINO);
18161+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
18162+
18163+ opt = opts->opt;
18164+ while (err >= 0 && opt->type != Opt_tail)
18165+ err = au_opt_br(sb, opt++, opts);
18166+ if (err > 0)
18167+ err = 0;
18168+ else if (unlikely(err < 0))
18169+ goto out;
18170+
18171+ bend = au_sbend(sb);
18172+ if (unlikely(bend < 0)) {
18173+ err = -EINVAL;
4a4d8108 18174+ pr_err("no branches\n");
1facf9fc 18175+ goto out;
18176+ }
18177+
18178+ if (au_opt_test(tmp, XINO))
18179+ au_opt_set(sbinfo->si_mntflags, XINO);
18180+ opt = opts->opt;
18181+ while (!err && opt->type != Opt_tail)
18182+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
18183+ if (unlikely(err))
18184+ goto out;
18185+
18186+ err = au_opts_verify(sb, sb->s_flags, tmp);
18187+ if (unlikely(err))
18188+ goto out;
18189+
18190+ /* restore xino */
18191+ if (au_opt_test(tmp, XINO) && !opt_xino) {
18192+ xino.file = au_xino_def(sb);
18193+ err = PTR_ERR(xino.file);
18194+ if (IS_ERR(xino.file))
18195+ goto out;
18196+
18197+ err = au_xino_set(sb, &xino, /*remount*/0);
18198+ fput(xino.file);
18199+ if (unlikely(err))
18200+ goto out;
18201+ }
18202+
18203+ /* restore udba */
18204+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18205+ sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
4a4d8108 18206+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 18207+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 18208+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 18209+ }
18210+
4f0767ce 18211+out:
1facf9fc 18212+ return err;
18213+}
18214+
18215+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
18216+{
18217+ int err, rerr;
18218+ struct inode *dir;
18219+ struct au_opt_xino *opt_xino;
18220+ struct au_opt *opt;
18221+ struct au_sbinfo *sbinfo;
18222+
dece6358
AM
18223+ SiMustWriteLock(sb);
18224+
1facf9fc 18225+ dir = sb->s_root->d_inode;
18226+ sbinfo = au_sbi(sb);
18227+ err = 0;
18228+ opt_xino = NULL;
18229+ opt = opts->opt;
18230+ while (err >= 0 && opt->type != Opt_tail) {
18231+ err = au_opt_simple(sb, opt, opts);
18232+ if (!err)
18233+ err = au_opt_br(sb, opt, opts);
18234+ if (!err)
18235+ err = au_opt_xino(sb, opt, &opt_xino, opts);
18236+ opt++;
18237+ }
18238+ if (err > 0)
18239+ err = 0;
18240+ AuTraceErr(err);
18241+ /* go on even err */
18242+
18243+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
18244+ if (unlikely(rerr && !err))
18245+ err = rerr;
18246+
18247+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
18248+ rerr = au_xib_trunc(sb);
18249+ if (unlikely(rerr && !err))
18250+ err = rerr;
18251+ }
18252+
18253+ /* will be handled by the caller */
18254+ if (!au_ftest_opts(opts->flags, REFRESH_DIR)
18255+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
18256+ au_fset_opts(opts->flags, REFRESH_DIR);
18257+
18258+ AuDbg("status 0x%x\n", opts->flags);
18259+ return err;
18260+}
18261+
18262+/* ---------------------------------------------------------------------- */
18263+
18264+unsigned int au_opt_udba(struct super_block *sb)
18265+{
18266+ return au_mntflags(sb) & AuOptMask_UDBA;
18267+}
b752ccd1
AM
18268diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
18269--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
18270+++ linux/fs/aufs/opts.h 2010-10-21 09:52:43.093625591 +0200
18271@@ -0,0 +1,198 @@
1facf9fc 18272+/*
4a4d8108 18273+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18274+ *
18275+ * This program, aufs is free software; you can redistribute it and/or modify
18276+ * it under the terms of the GNU General Public License as published by
18277+ * the Free Software Foundation; either version 2 of the License, or
18278+ * (at your option) any later version.
dece6358
AM
18279+ *
18280+ * This program is distributed in the hope that it will be useful,
18281+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18282+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18283+ * GNU General Public License for more details.
18284+ *
18285+ * You should have received a copy of the GNU General Public License
18286+ * along with this program; if not, write to the Free Software
18287+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18288+ */
18289+
18290+/*
18291+ * mount options/flags
18292+ */
18293+
18294+#ifndef __AUFS_OPTS_H__
18295+#define __AUFS_OPTS_H__
18296+
18297+#ifdef __KERNEL__
18298+
dece6358 18299+#include <linux/path.h>
1facf9fc 18300+#include <linux/aufs_type.h>
18301+
dece6358
AM
18302+struct file;
18303+struct super_block;
18304+
1facf9fc 18305+/* ---------------------------------------------------------------------- */
18306+
18307+/* mount flags */
18308+#define AuOpt_XINO 1 /* external inode number bitmap
18309+ and translation table */
18310+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
18311+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
18312+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 18313+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
18314+#define AuOpt_SHWH (1 << 5) /* show whiteout */
18315+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
18316+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
18317+#define AuOpt_REFROF (1 << 8) /* unimplemented */
18318+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
18319+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
18320+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
18321+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
18322+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 18323+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 18324+
4a4d8108
AM
18325+#ifndef CONFIG_AUFS_HNOTIFY
18326+#undef AuOpt_UDBA_HNOTIFY
18327+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 18328+#endif
dece6358
AM
18329+#ifndef CONFIG_AUFS_SHWH
18330+#undef AuOpt_SHWH
18331+#define AuOpt_SHWH 0
18332+#endif
1facf9fc 18333+
18334+#define AuOpt_Def (AuOpt_XINO \
18335+ | AuOpt_UDBA_REVAL \
18336+ | AuOpt_PLINK \
18337+ /* | AuOpt_DIRPERM1 */ \
18338+ | AuOpt_WARN_PERM)
18339+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
18340+ | AuOpt_UDBA_REVAL \
4a4d8108 18341+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 18342+
18343+#define au_opt_test(flags, name) (flags & AuOpt_##name)
18344+#define au_opt_set(flags, name) do { \
18345+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
18346+ ((flags) |= AuOpt_##name); \
18347+} while (0)
18348+#define au_opt_set_udba(flags, name) do { \
18349+ (flags) &= ~AuOptMask_UDBA; \
18350+ ((flags) |= AuOpt_##name); \
18351+} while (0)
18352+#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
18353+
18354+/* ---------------------------------------------------------------------- */
18355+
18356+/* policies to select one among multiple writable branches */
18357+enum {
18358+ AuWbrCreate_TDP, /* top down parent */
18359+ AuWbrCreate_RR, /* round robin */
18360+ AuWbrCreate_MFS, /* most free space */
18361+ AuWbrCreate_MFSV, /* mfs with seconds */
18362+ AuWbrCreate_MFSRR, /* mfs then rr */
18363+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
18364+ AuWbrCreate_PMFS, /* parent and mfs */
18365+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
18366+
18367+ AuWbrCreate_Def = AuWbrCreate_TDP
18368+};
18369+
18370+enum {
18371+ AuWbrCopyup_TDP, /* top down parent */
18372+ AuWbrCopyup_BUP, /* bottom up parent */
18373+ AuWbrCopyup_BU, /* bottom up */
18374+
18375+ AuWbrCopyup_Def = AuWbrCopyup_TDP
18376+};
18377+
18378+/* ---------------------------------------------------------------------- */
18379+
18380+struct au_opt_add {
18381+ aufs_bindex_t bindex;
18382+ char *pathname;
18383+ int perm;
18384+ struct path path;
18385+};
18386+
18387+struct au_opt_del {
18388+ char *pathname;
18389+ struct path h_path;
18390+};
18391+
18392+struct au_opt_mod {
18393+ char *path;
18394+ int perm;
18395+ struct dentry *h_root;
18396+};
18397+
18398+struct au_opt_xino {
18399+ char *path;
18400+ struct file *file;
18401+};
18402+
18403+struct au_opt_xino_itrunc {
18404+ aufs_bindex_t bindex;
18405+};
18406+
18407+struct au_opt_wbr_create {
18408+ int wbr_create;
18409+ int mfs_second;
18410+ unsigned long long mfsrr_watermark;
18411+};
18412+
18413+struct au_opt {
18414+ int type;
18415+ union {
18416+ struct au_opt_xino xino;
18417+ struct au_opt_xino_itrunc xino_itrunc;
18418+ struct au_opt_add add;
18419+ struct au_opt_del del;
18420+ struct au_opt_mod mod;
18421+ int dirwh;
18422+ int rdcache;
18423+ unsigned int rdblk;
18424+ unsigned int rdhash;
18425+ int udba;
18426+ struct au_opt_wbr_create wbr_create;
18427+ int wbr_copyup;
18428+ };
18429+};
18430+
18431+/* opts flags */
18432+#define AuOpts_REMOUNT 1
18433+#define AuOpts_REFRESH_DIR (1 << 1)
18434+#define AuOpts_REFRESH_NONDIR (1 << 2)
18435+#define AuOpts_TRUNC_XIB (1 << 3)
4a4d8108 18436+#define AuOpts_REFRESH_DYAOP (1 << 4)
1facf9fc 18437+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
18438+#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
18439+#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
18440+
18441+struct au_opts {
18442+ struct au_opt *opt;
18443+ int max_opt;
18444+
18445+ unsigned int given_udba;
18446+ unsigned int flags;
18447+ unsigned long sb_flags;
18448+};
18449+
18450+/* ---------------------------------------------------------------------- */
18451+
18452+const char *au_optstr_br_perm(int brperm);
18453+const char *au_optstr_udba(int udba);
18454+const char *au_optstr_wbr_copyup(int wbr_copyup);
18455+const char *au_optstr_wbr_create(int wbr_create);
18456+
18457+void au_opts_free(struct au_opts *opts);
18458+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
18459+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18460+ unsigned int pending);
18461+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
18462+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
18463+
18464+unsigned int au_opt_udba(struct super_block *sb);
18465+
18466+/* ---------------------------------------------------------------------- */
18467+
18468+#endif /* __KERNEL__ */
18469+#endif /* __AUFS_OPTS_H__ */
b752ccd1
AM
18470diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
18471--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
18472+++ linux/fs/aufs/plink.c 2010-10-21 09:52:43.093625591 +0200
18473@@ -0,0 +1,451 @@
1facf9fc 18474+/*
4a4d8108 18475+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18476+ *
18477+ * This program, aufs is free software; you can redistribute it and/or modify
18478+ * it under the terms of the GNU General Public License as published by
18479+ * the Free Software Foundation; either version 2 of the License, or
18480+ * (at your option) any later version.
dece6358
AM
18481+ *
18482+ * This program is distributed in the hope that it will be useful,
18483+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18484+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18485+ * GNU General Public License for more details.
18486+ *
18487+ * You should have received a copy of the GNU General Public License
18488+ * along with this program; if not, write to the Free Software
18489+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18490+ */
18491+
18492+/*
18493+ * pseudo-link
18494+ */
18495+
18496+#include "aufs.h"
18497+
18498+/*
18499+ * during a user process maintains the pseudo-links,
18500+ * prohibit adding a new plink and branch manipulation.
18501+ */
953406b4 18502+void au_plink_maint_block(struct super_block *sb)
1facf9fc 18503+{
953406b4 18504+ struct au_sbinfo *sbi = au_sbi(sb);
dece6358
AM
18505+
18506+ SiMustAnyLock(sb);
18507+
953406b4
AM
18508+ /* gave up wake_up_bit() */
18509+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint);
4a4d8108
AM
18510+}
18511+
953406b4 18512+void au_plink_maint_leave(struct file *file)
4a4d8108 18513+{
953406b4 18514+ struct au_sbinfo *sbinfo;
4a4d8108
AM
18515+ int iam;
18516+
953406b4
AM
18517+ AuDebugOn(atomic_long_read(&file->f_count));
18518+
18519+ sbinfo = au_sbi(file->f_dentry->d_sb);
4a4d8108 18520+ spin_lock(&sbinfo->si_plink_maint_lock);
953406b4 18521+ iam = (sbinfo->si_plink_maint == file);
4a4d8108 18522+ if (iam)
953406b4 18523+ sbinfo->si_plink_maint = NULL;
4a4d8108
AM
18524+ spin_unlock(&sbinfo->si_plink_maint_lock);
18525+ if (iam)
18526+ wake_up_all(&sbinfo->si_plink_wq);
18527+}
18528+
953406b4 18529+static int au_plink_maint_enter(struct file *file)
4a4d8108
AM
18530+{
18531+ int err;
953406b4 18532+ struct super_block *sb;
4a4d8108
AM
18533+ struct au_sbinfo *sbinfo;
18534+
18535+ err = 0;
953406b4 18536+ sb = file->f_dentry->d_sb;
4a4d8108
AM
18537+ sbinfo = au_sbi(sb);
18538+ /* make sure i am the only one in this fs */
953406b4
AM
18539+ si_write_lock(sb);
18540+ /* spin_lock(&sbinfo->si_plink_maint_lock); */
18541+ if (!sbinfo->si_plink_maint)
18542+ sbinfo->si_plink_maint = file;
18543+ else
18544+ err = -EBUSY;
18545+ /* spin_unlock(&sbinfo->si_plink_maint_lock); */
4a4d8108
AM
18546+ si_write_unlock(sb);
18547+
18548+ return err;
1facf9fc 18549+}
18550+
18551+/* ---------------------------------------------------------------------- */
18552+
18553+struct pseudo_link {
4a4d8108
AM
18554+ union {
18555+ struct list_head list;
18556+ struct rcu_head rcu;
18557+ };
1facf9fc 18558+ struct inode *inode;
18559+};
18560+
18561+#ifdef CONFIG_AUFS_DEBUG
18562+void au_plink_list(struct super_block *sb)
18563+{
18564+ struct au_sbinfo *sbinfo;
18565+ struct list_head *plink_list;
18566+ struct pseudo_link *plink;
18567+
dece6358
AM
18568+ SiMustAnyLock(sb);
18569+
1facf9fc 18570+ sbinfo = au_sbi(sb);
18571+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18572+
18573+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18574+ rcu_read_lock();
18575+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 18576+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 18577+ rcu_read_unlock();
1facf9fc 18578+}
18579+#endif
18580+
18581+/* is the inode pseudo-linked? */
18582+int au_plink_test(struct inode *inode)
18583+{
18584+ int found;
18585+ struct au_sbinfo *sbinfo;
18586+ struct list_head *plink_list;
18587+ struct pseudo_link *plink;
18588+
18589+ sbinfo = au_sbi(inode->i_sb);
dece6358 18590+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 18591+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
18592+
18593+ found = 0;
18594+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18595+ rcu_read_lock();
18596+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 18597+ if (plink->inode == inode) {
18598+ found = 1;
18599+ break;
18600+ }
4a4d8108 18601+ rcu_read_unlock();
1facf9fc 18602+ return found;
18603+}
18604+
18605+/* ---------------------------------------------------------------------- */
18606+
18607+/*
18608+ * generate a name for plink.
18609+ * the file will be stored under AUFS_WH_PLINKDIR.
18610+ */
18611+/* 20 is max digits length of ulong 64 */
18612+#define PLINK_NAME_LEN ((20 + 1) * 2)
18613+
18614+static int plink_name(char *name, int len, struct inode *inode,
18615+ aufs_bindex_t bindex)
18616+{
18617+ int rlen;
18618+ struct inode *h_inode;
18619+
18620+ h_inode = au_h_iptr(inode, bindex);
18621+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
18622+ return rlen;
18623+}
18624+
18625+/* lookup the plink-ed @inode under the branch at @bindex */
18626+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
18627+{
18628+ struct dentry *h_dentry, *h_parent;
18629+ struct au_branch *br;
18630+ struct inode *h_dir;
18631+ char a[PLINK_NAME_LEN];
18632+ struct qstr tgtname = {
18633+ .name = a
18634+ };
18635+
18636+ br = au_sbr(inode->i_sb, bindex);
18637+ h_parent = br->br_wbr->wbr_plink;
18638+ h_dir = h_parent->d_inode;
18639+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
18640+
18641+ /* always superio. */
18642+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
18643+ h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
18644+ mutex_unlock(&h_dir->i_mutex);
18645+ return h_dentry;
18646+}
18647+
18648+/* create a pseudo-link */
18649+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
18650+ struct dentry *h_dentry, struct au_branch *br)
18651+{
18652+ int err;
18653+ struct path h_path = {
18654+ .mnt = br->br_mnt
18655+ };
18656+ struct inode *h_dir;
18657+
18658+ h_dir = h_parent->d_inode;
4f0767ce 18659+again:
1facf9fc 18660+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
18661+ err = PTR_ERR(h_path.dentry);
18662+ if (IS_ERR(h_path.dentry))
18663+ goto out;
18664+
18665+ err = 0;
18666+ /* wh.plink dir is not monitored */
18667+ if (h_path.dentry->d_inode
18668+ && h_path.dentry->d_inode != h_dentry->d_inode) {
18669+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
18670+ dput(h_path.dentry);
18671+ h_path.dentry = NULL;
18672+ if (!err)
18673+ goto again;
18674+ }
18675+ if (!err && !h_path.dentry->d_inode)
18676+ err = vfsub_link(h_dentry, h_dir, &h_path);
18677+ dput(h_path.dentry);
18678+
4f0767ce 18679+out:
1facf9fc 18680+ return err;
18681+}
18682+
18683+struct do_whplink_args {
18684+ int *errp;
18685+ struct qstr *tgt;
18686+ struct dentry *h_parent;
18687+ struct dentry *h_dentry;
18688+ struct au_branch *br;
18689+};
18690+
18691+static void call_do_whplink(void *args)
18692+{
18693+ struct do_whplink_args *a = args;
18694+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
18695+}
18696+
18697+static int whplink(struct dentry *h_dentry, struct inode *inode,
18698+ aufs_bindex_t bindex, struct au_branch *br)
18699+{
18700+ int err, wkq_err;
18701+ struct au_wbr *wbr;
18702+ struct dentry *h_parent;
18703+ struct inode *h_dir;
18704+ char a[PLINK_NAME_LEN];
18705+ struct qstr tgtname = {
18706+ .name = a
18707+ };
18708+
18709+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
18710+ h_parent = wbr->wbr_plink;
18711+ h_dir = h_parent->d_inode;
18712+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
18713+
18714+ /* always superio. */
18715+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
b752ccd1 18716+ if (current_fsuid()) {
1facf9fc 18717+ struct do_whplink_args args = {
18718+ .errp = &err,
18719+ .tgt = &tgtname,
18720+ .h_parent = h_parent,
18721+ .h_dentry = h_dentry,
18722+ .br = br
18723+ };
18724+ wkq_err = au_wkq_wait(call_do_whplink, &args);
18725+ if (unlikely(wkq_err))
18726+ err = wkq_err;
18727+ } else
18728+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
18729+ mutex_unlock(&h_dir->i_mutex);
18730+
18731+ return err;
18732+}
18733+
18734+/* free a single plink */
18735+static void do_put_plink(struct pseudo_link *plink, int do_del)
18736+{
1facf9fc 18737+ if (do_del)
18738+ list_del(&plink->list);
4a4d8108
AM
18739+ iput(plink->inode);
18740+ kfree(plink);
18741+}
18742+
18743+static void do_put_plink_rcu(struct rcu_head *rcu)
18744+{
18745+ struct pseudo_link *plink;
18746+
18747+ plink = container_of(rcu, struct pseudo_link, rcu);
18748+ iput(plink->inode);
1facf9fc 18749+ kfree(plink);
18750+}
18751+
18752+/*
18753+ * create a new pseudo-link for @h_dentry on @bindex.
18754+ * the linked inode is held in aufs @inode.
18755+ */
18756+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
18757+ struct dentry *h_dentry)
18758+{
18759+ struct super_block *sb;
18760+ struct au_sbinfo *sbinfo;
18761+ struct list_head *plink_list;
4a4d8108 18762+ struct pseudo_link *plink, *tmp;
1facf9fc 18763+ int found, err, cnt;
18764+
18765+ sb = inode->i_sb;
18766+ sbinfo = au_sbi(sb);
18767+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18768+
1facf9fc 18769+ cnt = 0;
18770+ found = 0;
18771+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18772+ rcu_read_lock();
18773+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 18774+ cnt++;
18775+ if (plink->inode == inode) {
18776+ found = 1;
18777+ break;
18778+ }
18779+ }
4a4d8108
AM
18780+ rcu_read_unlock();
18781+ if (found)
1facf9fc 18782+ return;
4a4d8108
AM
18783+
18784+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
18785+ if (tmp)
18786+ tmp->inode = au_igrab(inode);
18787+ else {
18788+ err = -ENOMEM;
18789+ goto out;
1facf9fc 18790+ }
18791+
4a4d8108
AM
18792+ spin_lock(&sbinfo->si_plink.spin);
18793+ list_for_each_entry(plink, plink_list, list) {
18794+ if (plink->inode == inode) {
18795+ found = 1;
18796+ break;
18797+ }
1facf9fc 18798+ }
4a4d8108
AM
18799+ if (!found)
18800+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 18801+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
18802+ if (!found) {
18803+ cnt++;
18804+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
18805+ "unexpectedly many pseudo links, %d\n", cnt);
953406b4 18806+ au_plink_maint_block(sb);
1facf9fc 18807+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
18808+ } else {
18809+ do_put_plink(tmp, 0);
18810+ return;
1facf9fc 18811+ }
18812+
4a4d8108 18813+out:
1facf9fc 18814+ if (unlikely(err)) {
4a4d8108
AM
18815+ pr_warning("err %d, damaged pseudo link.\n", err);
18816+ if (tmp) {
18817+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
18818+ call_rcu(&tmp->rcu, do_put_plink_rcu);
18819+ }
1facf9fc 18820+ }
18821+}
18822+
18823+/* free all plinks */
953406b4 18824+void au_plink_put(struct super_block *sb)
1facf9fc 18825+{
18826+ struct au_sbinfo *sbinfo;
18827+ struct list_head *plink_list;
18828+ struct pseudo_link *plink, *tmp;
18829+
dece6358
AM
18830+ SiMustWriteLock(sb);
18831+
1facf9fc 18832+ sbinfo = au_sbi(sb);
18833+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18834+
18835+ plink_list = &sbinfo->si_plink.head;
18836+ /* no spin_lock since sbinfo is write-locked */
18837+ list_for_each_entry_safe(plink, tmp, plink_list, list)
18838+ do_put_plink(plink, 0);
18839+ INIT_LIST_HEAD(plink_list);
18840+}
18841+
18842+/* free the plinks on a branch specified by @br_id */
18843+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
18844+{
18845+ struct au_sbinfo *sbinfo;
18846+ struct list_head *plink_list;
18847+ struct pseudo_link *plink, *tmp;
18848+ struct inode *inode;
18849+ aufs_bindex_t bstart, bend, bindex;
18850+ unsigned char do_put;
18851+
dece6358
AM
18852+ SiMustWriteLock(sb);
18853+
1facf9fc 18854+ sbinfo = au_sbi(sb);
18855+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18856+
18857+ plink_list = &sbinfo->si_plink.head;
18858+ /* no spin_lock since sbinfo is write-locked */
18859+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
18860+ do_put = 0;
18861+ inode = au_igrab(plink->inode);
18862+ ii_write_lock_child(inode);
18863+ bstart = au_ibstart(inode);
18864+ bend = au_ibend(inode);
18865+ if (bstart >= 0) {
18866+ for (bindex = bstart; bindex <= bend; bindex++) {
18867+ if (!au_h_iptr(inode, bindex)
18868+ || au_ii_br_id(inode, bindex) != br_id)
18869+ continue;
18870+ au_set_h_iptr(inode, bindex, NULL, 0);
18871+ do_put = 1;
18872+ break;
18873+ }
18874+ } else
18875+ do_put_plink(plink, 1);
18876+
dece6358
AM
18877+ if (do_put) {
18878+ for (bindex = bstart; bindex <= bend; bindex++)
18879+ if (au_h_iptr(inode, bindex)) {
18880+ do_put = 0;
18881+ break;
18882+ }
18883+ if (do_put)
18884+ do_put_plink(plink, 1);
18885+ }
18886+ ii_write_unlock(inode);
18887+ iput(inode);
18888+ }
18889+}
953406b4
AM
18890+
18891+/* ---------------------------------------------------------------------- */
18892+
18893+long au_plink_ioctl(struct file *file, unsigned int cmd)
18894+{
18895+ long err;
18896+ struct super_block *sb;
18897+
18898+ err = -EACCES;
18899+ if (!capable(CAP_SYS_ADMIN))
18900+ goto out;
18901+
18902+ err = 0;
18903+ sb = file->f_dentry->d_sb;
18904+ switch (cmd) {
18905+ case AUFS_CTL_PLINK_MAINT:
18906+ /*
18907+ * pseudo-link maintenance mode,
18908+ * cleared by aufs_release_dir()
18909+ */
18910+ err = au_plink_maint_enter(file);
18911+ break;
18912+ case AUFS_CTL_PLINK_CLEAN:
18913+ aufs_write_lock(sb->s_root);
18914+ if (au_opt_test(au_mntflags(sb), PLINK))
18915+ au_plink_put(sb);
18916+ aufs_write_unlock(sb->s_root);
18917+ break;
18918+ default:
18919+ /* err = -ENOTTY; */
18920+ err = -EINVAL;
18921+ }
18922+out:
18923+ return err;
18924+}
b752ccd1
AM
18925diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
18926--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
953406b4 18927+++ linux/fs/aufs/poll.c 2010-10-21 09:52:43.093625591 +0200
dece6358
AM
18928@@ -0,0 +1,56 @@
18929+/*
4a4d8108 18930+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
18931+ *
18932+ * This program, aufs is free software; you can redistribute it and/or modify
18933+ * it under the terms of the GNU General Public License as published by
18934+ * the Free Software Foundation; either version 2 of the License, or
18935+ * (at your option) any later version.
18936+ *
18937+ * This program is distributed in the hope that it will be useful,
18938+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18939+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18940+ * GNU General Public License for more details.
18941+ *
18942+ * You should have received a copy of the GNU General Public License
18943+ * along with this program; if not, write to the Free Software
18944+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18945+ */
18946+
1308ab2a 18947+/*
18948+ * poll operation
18949+ * There is only one filesystem which implements ->poll operation, currently.
18950+ */
18951+
18952+#include "aufs.h"
18953+
18954+unsigned int aufs_poll(struct file *file, poll_table *wait)
18955+{
18956+ unsigned int mask;
18957+ int err;
18958+ struct file *h_file;
18959+ struct dentry *dentry;
18960+ struct super_block *sb;
18961+
18962+ /* We should pretend an error happened. */
18963+ mask = POLLERR /* | POLLIN | POLLOUT */;
18964+ dentry = file->f_dentry;
18965+ sb = dentry->d_sb;
953406b4 18966+ si_read_lock(sb, AuLock_FLUSH);
1308ab2a 18967+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
18968+ if (unlikely(err))
18969+ goto out;
18970+
18971+ /* it is not an error if h_file has no operation */
18972+ mask = DEFAULT_POLLMASK;
4a4d8108 18973+ h_file = au_hf_top(file);
1308ab2a 18974+ if (h_file->f_op && h_file->f_op->poll)
18975+ mask = h_file->f_op->poll(h_file, wait);
18976+
18977+ di_read_unlock(dentry, AuLock_IR);
18978+ fi_read_unlock(file);
18979+
4f0767ce 18980+out:
1308ab2a 18981+ si_read_unlock(sb);
18982+ AuTraceErr((int)mask);
18983+ return mask;
18984+}
b752ccd1
AM
18985diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
18986--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
18987+++ linux/fs/aufs/rdu.c 2010-10-21 09:52:43.093625591 +0200
18988@@ -0,0 +1,377 @@
1308ab2a 18989+/*
4a4d8108 18990+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 18991+ *
18992+ * This program, aufs is free software; you can redistribute it and/or modify
18993+ * it under the terms of the GNU General Public License as published by
18994+ * the Free Software Foundation; either version 2 of the License, or
18995+ * (at your option) any later version.
18996+ *
18997+ * This program is distributed in the hope that it will be useful,
18998+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18999+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19000+ * GNU General Public License for more details.
19001+ *
19002+ * You should have received a copy of the GNU General Public License
19003+ * along with this program; if not, write to the Free Software
19004+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19005+ */
19006+
19007+/*
19008+ * readdir in userspace.
19009+ */
19010+
b752ccd1 19011+#include <linux/compat.h>
4a4d8108 19012+#include <linux/fs_stack.h>
1308ab2a 19013+#include <linux/security.h>
19014+#include <linux/uaccess.h>
19015+#include <linux/aufs_type.h>
19016+#include "aufs.h"
19017+
19018+/* bits for struct aufs_rdu.flags */
19019+#define AuRdu_CALLED 1
19020+#define AuRdu_CONT (1 << 1)
19021+#define AuRdu_FULL (1 << 2)
19022+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
19023+#define au_fset_rdu(flags, name) { (flags) |= AuRdu_##name; }
19024+#define au_fclr_rdu(flags, name) { (flags) &= ~AuRdu_##name; }
19025+
19026+struct au_rdu_arg {
19027+ struct aufs_rdu *rdu;
19028+ union au_rdu_ent_ul ent;
19029+ unsigned long end;
19030+
19031+ struct super_block *sb;
19032+ int err;
19033+};
19034+
19035+static int au_rdu_fill(void *__arg, const char *name, int nlen,
19036+ loff_t offset, u64 h_ino, unsigned int d_type)
19037+{
19038+ int err, len;
19039+ struct au_rdu_arg *arg = __arg;
19040+ struct aufs_rdu *rdu = arg->rdu;
19041+ struct au_rdu_ent ent;
19042+
19043+ err = 0;
19044+ arg->err = 0;
19045+ au_fset_rdu(rdu->cookie.flags, CALLED);
19046+ len = au_rdu_len(nlen);
19047+ if (arg->ent.ul + len < arg->end) {
19048+ ent.ino = h_ino;
19049+ ent.bindex = rdu->cookie.bindex;
19050+ ent.type = d_type;
19051+ ent.nlen = nlen;
4a4d8108
AM
19052+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
19053+ ent.type = DT_UNKNOWN;
1308ab2a 19054+
19055+ err = -EFAULT;
19056+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
19057+ goto out;
19058+ if (copy_to_user(arg->ent.e->name, name, nlen))
19059+ goto out;
19060+ /* the terminating NULL */
19061+ if (__put_user(0, arg->ent.e->name + nlen))
19062+ goto out;
19063+ err = 0;
19064+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
19065+ arg->ent.ul += len;
19066+ rdu->rent++;
19067+ } else {
19068+ err = -EFAULT;
19069+ au_fset_rdu(rdu->cookie.flags, FULL);
19070+ rdu->full = 1;
19071+ rdu->tail = arg->ent;
19072+ }
19073+
4f0767ce 19074+out:
1308ab2a 19075+ /* AuTraceErr(err); */
19076+ return err;
19077+}
19078+
19079+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
19080+{
19081+ int err;
19082+ loff_t offset;
19083+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
19084+
19085+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
19086+ err = offset;
19087+ if (unlikely(offset != cookie->h_pos))
19088+ goto out;
19089+
19090+ err = 0;
19091+ do {
19092+ arg->err = 0;
19093+ au_fclr_rdu(cookie->flags, CALLED);
19094+ /* smp_mb(); */
19095+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
19096+ if (err >= 0)
19097+ err = arg->err;
19098+ } while (!err
19099+ && au_ftest_rdu(cookie->flags, CALLED)
19100+ && !au_ftest_rdu(cookie->flags, FULL));
19101+ cookie->h_pos = h_file->f_pos;
19102+
4f0767ce 19103+out:
1308ab2a 19104+ AuTraceErr(err);
19105+ return err;
19106+}
19107+
19108+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
19109+{
19110+ int err;
19111+ aufs_bindex_t bend;
19112+ struct au_rdu_arg arg;
19113+ struct dentry *dentry;
19114+ struct inode *inode;
19115+ struct file *h_file;
19116+ struct au_rdu_cookie *cookie = &rdu->cookie;
19117+
19118+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
19119+ if (unlikely(err)) {
19120+ err = -EFAULT;
19121+ AuTraceErr(err);
19122+ goto out;
19123+ }
19124+ rdu->rent = 0;
19125+ rdu->tail = rdu->ent;
19126+ rdu->full = 0;
19127+ arg.rdu = rdu;
19128+ arg.ent = rdu->ent;
19129+ arg.end = arg.ent.ul;
19130+ arg.end += rdu->sz;
19131+
19132+ err = -ENOTDIR;
19133+ if (unlikely(!file->f_op || !file->f_op->readdir))
19134+ goto out;
19135+
19136+ err = security_file_permission(file, MAY_READ);
19137+ AuTraceErr(err);
19138+ if (unlikely(err))
19139+ goto out;
19140+
19141+ dentry = file->f_dentry;
19142+ inode = dentry->d_inode;
19143+#if 1
19144+ mutex_lock(&inode->i_mutex);
19145+#else
19146+ err = mutex_lock_killable(&inode->i_mutex);
19147+ AuTraceErr(err);
19148+ if (unlikely(err))
19149+ goto out;
19150+#endif
19151+ err = -ENOENT;
19152+ if (unlikely(IS_DEADDIR(inode)))
19153+ goto out_mtx;
19154+
19155+ arg.sb = inode->i_sb;
953406b4 19156+ si_read_lock(arg.sb, AuLock_FLUSH);
1308ab2a 19157+ fi_read_lock(file);
19158+
19159+ err = -EAGAIN;
19160+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
19161+ && cookie->generation != au_figen(file)))
19162+ goto out_unlock;
19163+
19164+ err = 0;
19165+ if (!rdu->blk) {
19166+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
19167+ if (!rdu->blk)
19168+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
19169+ }
19170+ bend = au_fbstart(file);
19171+ if (cookie->bindex < bend)
19172+ cookie->bindex = bend;
4a4d8108 19173+ bend = au_fbend_dir(file);
1308ab2a 19174+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
19175+ for (; !err && cookie->bindex <= bend;
19176+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 19177+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 19178+ if (!h_file)
19179+ continue;
19180+
19181+ au_fclr_rdu(cookie->flags, FULL);
19182+ err = au_rdu_do(h_file, &arg);
19183+ AuTraceErr(err);
19184+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
19185+ break;
19186+ }
19187+ AuDbg("rent %llu\n", rdu->rent);
19188+
19189+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
19190+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
19191+ au_fset_rdu(cookie->flags, CONT);
19192+ cookie->generation = au_figen(file);
19193+ }
19194+
19195+ ii_read_lock_child(inode);
19196+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
19197+ ii_read_unlock(inode);
19198+
4f0767ce 19199+out_unlock:
1308ab2a 19200+ fi_read_unlock(file);
19201+ si_read_unlock(arg.sb);
4f0767ce 19202+out_mtx:
1308ab2a 19203+ mutex_unlock(&inode->i_mutex);
4f0767ce 19204+out:
1308ab2a 19205+ AuTraceErr(err);
19206+ return err;
19207+}
19208+
19209+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
19210+{
19211+ int err;
19212+ ino_t ino;
19213+ unsigned long long nent;
19214+ union au_rdu_ent_ul *u;
19215+ struct au_rdu_ent ent;
19216+ struct super_block *sb;
19217+
19218+ err = 0;
19219+ nent = rdu->nent;
19220+ u = &rdu->ent;
19221+ sb = file->f_dentry->d_sb;
19222+ si_read_lock(sb, AuLock_FLUSH);
19223+ while (nent-- > 0) {
1308ab2a 19224+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
19225+ if (!err)
19226+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 19227+ if (unlikely(err)) {
19228+ err = -EFAULT;
19229+ AuTraceErr(err);
19230+ break;
19231+ }
19232+
19233+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
19234+ if (!ent.wh)
19235+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
19236+ else
19237+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
19238+ &ino);
19239+ if (unlikely(err)) {
19240+ AuTraceErr(err);
19241+ break;
19242+ }
19243+
19244+ err = __put_user(ino, &u->e->ino);
19245+ if (unlikely(err)) {
19246+ err = -EFAULT;
19247+ AuTraceErr(err);
19248+ break;
19249+ }
19250+ u->ul += au_rdu_len(ent.nlen);
19251+ }
19252+ si_read_unlock(sb);
19253+
19254+ return err;
19255+}
19256+
19257+/* ---------------------------------------------------------------------- */
19258+
19259+static int au_rdu_verify(struct aufs_rdu *rdu)
19260+{
b752ccd1 19261+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 19262+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 19263+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 19264+ rdu->blk,
19265+ rdu->rent, rdu->shwh, rdu->full,
19266+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
19267+ rdu->cookie.generation);
dece6358 19268+
b752ccd1 19269+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 19270+ return 0;
dece6358 19271+
b752ccd1
AM
19272+ AuDbg("%u:%u\n",
19273+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 19274+ return -EINVAL;
19275+}
19276+
19277+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 19278+{
1308ab2a 19279+ long err, e;
19280+ struct aufs_rdu rdu;
19281+ void __user *p = (void __user *)arg;
dece6358 19282+
1308ab2a 19283+ err = copy_from_user(&rdu, p, sizeof(rdu));
19284+ if (unlikely(err)) {
19285+ err = -EFAULT;
19286+ AuTraceErr(err);
19287+ goto out;
19288+ }
19289+ err = au_rdu_verify(&rdu);
dece6358
AM
19290+ if (unlikely(err))
19291+ goto out;
19292+
1308ab2a 19293+ switch (cmd) {
19294+ case AUFS_CTL_RDU:
19295+ err = au_rdu(file, &rdu);
19296+ if (unlikely(err))
19297+ break;
dece6358 19298+
1308ab2a 19299+ e = copy_to_user(p, &rdu, sizeof(rdu));
19300+ if (unlikely(e)) {
19301+ err = -EFAULT;
19302+ AuTraceErr(err);
19303+ }
19304+ break;
19305+ case AUFS_CTL_RDU_INO:
19306+ err = au_rdu_ino(file, &rdu);
19307+ break;
19308+
19309+ default:
4a4d8108 19310+ /* err = -ENOTTY; */
1308ab2a 19311+ err = -EINVAL;
19312+ }
dece6358 19313+
4f0767ce 19314+out:
1308ab2a 19315+ AuTraceErr(err);
19316+ return err;
1facf9fc 19317+}
b752ccd1
AM
19318+
19319+#ifdef CONFIG_COMPAT
19320+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
19321+{
19322+ long err, e;
19323+ struct aufs_rdu rdu;
19324+ void __user *p = compat_ptr(arg);
19325+
19326+ /* todo: get_user()? */
19327+ err = copy_from_user(&rdu, p, sizeof(rdu));
19328+ if (unlikely(err)) {
19329+ err = -EFAULT;
19330+ AuTraceErr(err);
19331+ goto out;
19332+ }
19333+ rdu.ent.e = compat_ptr(rdu.ent.ul);
19334+ err = au_rdu_verify(&rdu);
19335+ if (unlikely(err))
19336+ goto out;
19337+
19338+ switch (cmd) {
19339+ case AUFS_CTL_RDU:
19340+ err = au_rdu(file, &rdu);
19341+ if (unlikely(err))
19342+ break;
19343+
19344+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
19345+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
19346+ e = copy_to_user(p, &rdu, sizeof(rdu));
19347+ if (unlikely(e)) {
19348+ err = -EFAULT;
19349+ AuTraceErr(err);
19350+ }
19351+ break;
19352+ case AUFS_CTL_RDU_INO:
19353+ err = au_rdu_ino(file, &rdu);
19354+ break;
19355+
19356+ default:
19357+ /* err = -ENOTTY; */
19358+ err = -EINVAL;
19359+ }
19360+
4f0767ce 19361+out:
b752ccd1
AM
19362+ AuTraceErr(err);
19363+ return err;
19364+}
19365+#endif
19366diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
19367--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
19368+++ linux/fs/aufs/rwsem.h 2010-10-21 09:52:43.093625591 +0200
19369@@ -0,0 +1,187 @@
1facf9fc 19370+/*
4a4d8108 19371+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19372+ *
19373+ * This program, aufs is free software; you can redistribute it and/or modify
19374+ * it under the terms of the GNU General Public License as published by
19375+ * the Free Software Foundation; either version 2 of the License, or
19376+ * (at your option) any later version.
dece6358
AM
19377+ *
19378+ * This program is distributed in the hope that it will be useful,
19379+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19380+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19381+ * GNU General Public License for more details.
19382+ *
19383+ * You should have received a copy of the GNU General Public License
19384+ * along with this program; if not, write to the Free Software
19385+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19386+ */
19387+
19388+/*
19389+ * simple read-write semaphore wrappers
19390+ */
19391+
19392+#ifndef __AUFS_RWSEM_H__
19393+#define __AUFS_RWSEM_H__
19394+
19395+#ifdef __KERNEL__
19396+
dece6358 19397+#include <linux/rwsem.h>
4a4d8108 19398+#include "debug.h"
dece6358
AM
19399+
19400+struct au_rwsem {
19401+ struct rw_semaphore rwsem;
19402+#ifdef CONFIG_AUFS_DEBUG
19403+ /* just for debugging, not almighty counter */
19404+ atomic_t rcnt, wcnt;
19405+#endif
19406+};
19407+
19408+#ifdef CONFIG_AUFS_DEBUG
19409+#define AuDbgCntInit(rw) do { \
19410+ atomic_set(&(rw)->rcnt, 0); \
19411+ atomic_set(&(rw)->wcnt, 0); \
19412+ smp_mb(); /* atomic set */ \
19413+} while (0)
19414+
953406b4 19415+#define AuDbgRcntInc(rw) atomic_inc_return(&(rw)->rcnt)
dece6358 19416+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
953406b4 19417+#define AuDbgWcntInc(rw) WARN_ON(atomic_inc_return(&(rw)->wcnt) > 1)
dece6358
AM
19418+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
19419+#else
19420+#define AuDbgCntInit(rw) do {} while (0)
19421+#define AuDbgRcntInc(rw) do {} while (0)
19422+#define AuDbgRcntDec(rw) do {} while (0)
19423+#define AuDbgWcntInc(rw) do {} while (0)
19424+#define AuDbgWcntDec(rw) do {} while (0)
19425+#endif /* CONFIG_AUFS_DEBUG */
19426+
19427+/* to debug easier, do not make them inlined functions */
19428+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
19429+/* rwsem_is_locked() is unusable */
19430+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
19431+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
19432+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
19433+ && atomic_read(&(rw)->wcnt) <= 0)
19434+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
19435+ || atomic_read(&(rw)->wcnt))
19436+
19437+static inline void au_rw_init(struct au_rwsem *rw)
19438+{
19439+ AuDbgCntInit(rw);
19440+ init_rwsem(&rw->rwsem);
19441+}
19442+
19443+static inline void au_rw_init_wlock(struct au_rwsem *rw)
19444+{
19445+ au_rw_init(rw);
19446+ down_write(&rw->rwsem);
19447+ AuDbgWcntInc(rw);
19448+}
19449+
19450+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
19451+ unsigned int lsc)
19452+{
19453+ au_rw_init(rw);
19454+ down_write_nested(&rw->rwsem, lsc);
19455+ AuDbgWcntInc(rw);
19456+}
19457+
19458+static inline void au_rw_read_lock(struct au_rwsem *rw)
19459+{
19460+ down_read(&rw->rwsem);
19461+ AuDbgRcntInc(rw);
19462+}
19463+
19464+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
19465+{
19466+ down_read_nested(&rw->rwsem, lsc);
19467+ AuDbgRcntInc(rw);
19468+}
19469+
19470+static inline void au_rw_read_unlock(struct au_rwsem *rw)
19471+{
19472+ AuRwMustReadLock(rw);
19473+ AuDbgRcntDec(rw);
19474+ up_read(&rw->rwsem);
19475+}
19476+
19477+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
19478+{
19479+ AuRwMustWriteLock(rw);
19480+ AuDbgRcntInc(rw);
19481+ AuDbgWcntDec(rw);
19482+ downgrade_write(&rw->rwsem);
19483+}
19484+
19485+static inline void au_rw_write_lock(struct au_rwsem *rw)
19486+{
19487+ down_write(&rw->rwsem);
19488+ AuDbgWcntInc(rw);
19489+}
19490+
19491+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
19492+ unsigned int lsc)
19493+{
19494+ down_write_nested(&rw->rwsem, lsc);
19495+ AuDbgWcntInc(rw);
19496+}
1facf9fc 19497+
dece6358
AM
19498+static inline void au_rw_write_unlock(struct au_rwsem *rw)
19499+{
19500+ AuRwMustWriteLock(rw);
19501+ AuDbgWcntDec(rw);
19502+ up_write(&rw->rwsem);
19503+}
19504+
19505+/* why is not _nested version defined */
19506+static inline int au_rw_read_trylock(struct au_rwsem *rw)
19507+{
19508+ int ret = down_read_trylock(&rw->rwsem);
19509+ if (ret)
19510+ AuDbgRcntInc(rw);
19511+ return ret;
19512+}
19513+
19514+static inline int au_rw_write_trylock(struct au_rwsem *rw)
19515+{
19516+ int ret = down_write_trylock(&rw->rwsem);
19517+ if (ret)
19518+ AuDbgWcntInc(rw);
19519+ return ret;
19520+}
19521+
19522+#undef AuDbgCntInit
19523+#undef AuDbgRcntInc
19524+#undef AuDbgRcntDec
19525+#undef AuDbgWcntInc
19526+#undef AuDbgWcntDec
1facf9fc 19527+
19528+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
19529+static inline void prefix##_read_lock(param) \
dece6358 19530+{ au_rw_read_lock(rwsem); } \
1facf9fc 19531+static inline void prefix##_write_lock(param) \
dece6358 19532+{ au_rw_write_lock(rwsem); } \
1facf9fc 19533+static inline int prefix##_read_trylock(param) \
dece6358 19534+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 19535+static inline int prefix##_write_trylock(param) \
dece6358 19536+{ return au_rw_write_trylock(rwsem); }
1facf9fc 19537+/* why is not _nested version defined */
19538+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 19539+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 19540+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 19541+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 19542+
19543+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
19544+static inline void prefix##_read_unlock(param) \
dece6358 19545+{ au_rw_read_unlock(rwsem); } \
1facf9fc 19546+static inline void prefix##_write_unlock(param) \
dece6358 19547+{ au_rw_write_unlock(rwsem); } \
1facf9fc 19548+static inline void prefix##_downgrade_lock(param) \
dece6358 19549+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 19550+
19551+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
19552+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
19553+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
19554+
19555+#endif /* __KERNEL__ */
19556+#endif /* __AUFS_RWSEM_H__ */
b752ccd1
AM
19557diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
19558--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
19559+++ linux/fs/aufs/sbinfo.c 2010-10-21 09:52:43.093625591 +0200
19560@@ -0,0 +1,269 @@
1facf9fc 19561+/*
4a4d8108 19562+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19563+ *
19564+ * This program, aufs is free software; you can redistribute it and/or modify
19565+ * it under the terms of the GNU General Public License as published by
19566+ * the Free Software Foundation; either version 2 of the License, or
19567+ * (at your option) any later version.
dece6358
AM
19568+ *
19569+ * This program is distributed in the hope that it will be useful,
19570+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19571+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19572+ * GNU General Public License for more details.
19573+ *
19574+ * You should have received a copy of the GNU General Public License
19575+ * along with this program; if not, write to the Free Software
19576+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19577+ */
19578+
19579+/*
19580+ * superblock private data
19581+ */
19582+
19583+#include "aufs.h"
19584+
19585+/*
19586+ * they are necessary regardless sysfs is disabled.
19587+ */
19588+void au_si_free(struct kobject *kobj)
19589+{
19590+ struct au_sbinfo *sbinfo;
953406b4 19591+ struct super_block *sb;
b752ccd1 19592+ char *locked __maybe_unused; /* debug only */
1facf9fc 19593+
19594+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
19595+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
953406b4 19596+ AuDebugOn(sbinfo->si_plink_maint);
1facf9fc 19597+
953406b4
AM
19598+ sb = sbinfo->si_sb;
19599+ si_write_lock(sb);
19600+ au_xino_clr(sb);
1facf9fc 19601+ au_br_free(sbinfo);
953406b4 19602+ si_write_unlock(sb);
b752ccd1
AM
19603+
19604+ AuDebugOn(radix_tree_gang_lookup
19605+ (&sbinfo->au_si_pid.tree, (void **)&locked,
19606+ /*first_index*/PID_MAX_DEFAULT - 1,
19607+ /*max_items*/sizeof(locked)/sizeof(*locked)));
19608+
1facf9fc 19609+ kfree(sbinfo->si_branch);
b752ccd1 19610+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 19611+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 19612+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 19613+
19614+ kfree(sbinfo);
19615+}
19616+
19617+int au_si_alloc(struct super_block *sb)
19618+{
19619+ int err;
19620+ struct au_sbinfo *sbinfo;
19621+
19622+ err = -ENOMEM;
4a4d8108 19623+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 19624+ if (unlikely(!sbinfo))
19625+ goto out;
19626+
b752ccd1
AM
19627+ BUILD_BUG_ON(sizeof(unsigned long) !=
19628+ sizeof(*sbinfo->au_si_pid.bitmap));
19629+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
19630+ sizeof(*sbinfo->au_si_pid.bitmap),
19631+ GFP_NOFS);
19632+ if (unlikely(!sbinfo->au_si_pid.bitmap))
19633+ goto out_sbinfo;
19634+
1facf9fc 19635+ /* will be reallocated separately */
19636+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
19637+ if (unlikely(!sbinfo->si_branch))
b752ccd1 19638+ goto out_pidmap;
1facf9fc 19639+
1facf9fc 19640+ err = sysaufs_si_init(sbinfo);
19641+ if (unlikely(err))
19642+ goto out_br;
19643+
19644+ au_nwt_init(&sbinfo->si_nowait);
dece6358 19645+ au_rw_init_wlock(&sbinfo->si_rwsem);
b752ccd1
AM
19646+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
19647+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
19648+
1facf9fc 19649+ sbinfo->si_bend = -1;
1facf9fc 19650+
19651+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
19652+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
19653+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
19654+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 19655+
953406b4 19656+ sbinfo->si_mntflags = AuOpt_Def;
1facf9fc 19657+
1facf9fc 19658+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 19659+ sbinfo->si_xino_brid = -1;
19660+ /* leave si_xib_last_pindex and si_xib_next_bit */
19661+
953406b4 19662+ sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
1facf9fc 19663+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
19664+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
19665+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
19666+
19667+ au_spl_init(&sbinfo->si_plink);
19668+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 19669+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 19670+
19671+ /* leave other members for sysaufs and si_mnt. */
19672+ sbinfo->si_sb = sb;
19673+ sb->s_fs_info = sbinfo;
b752ccd1 19674+ si_pid_set(sb);
1facf9fc 19675+ au_debug_sbinfo_init(sbinfo);
19676+ return 0; /* success */
19677+
4f0767ce 19678+out_br:
1facf9fc 19679+ kfree(sbinfo->si_branch);
4f0767ce 19680+out_pidmap:
b752ccd1 19681+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 19682+out_sbinfo:
1facf9fc 19683+ kfree(sbinfo);
4f0767ce 19684+out:
1facf9fc 19685+ return err;
19686+}
19687+
19688+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
19689+{
19690+ int err, sz;
19691+ struct au_branch **brp;
19692+
dece6358
AM
19693+ AuRwMustWriteLock(&sbinfo->si_rwsem);
19694+
1facf9fc 19695+ err = -ENOMEM;
19696+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
19697+ if (unlikely(!sz))
19698+ sz = sizeof(*brp);
19699+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
19700+ if (brp) {
19701+ sbinfo->si_branch = brp;
19702+ err = 0;
19703+ }
19704+
19705+ return err;
19706+}
19707+
19708+/* ---------------------------------------------------------------------- */
19709+
19710+unsigned int au_sigen_inc(struct super_block *sb)
19711+{
19712+ unsigned int gen;
19713+
dece6358
AM
19714+ SiMustWriteLock(sb);
19715+
1facf9fc 19716+ gen = ++au_sbi(sb)->si_generation;
19717+ au_update_digen(sb->s_root);
19718+ au_update_iigen(sb->s_root->d_inode);
19719+ sb->s_root->d_inode->i_version++;
19720+ return gen;
19721+}
19722+
19723+aufs_bindex_t au_new_br_id(struct super_block *sb)
19724+{
19725+ aufs_bindex_t br_id;
19726+ int i;
19727+ struct au_sbinfo *sbinfo;
19728+
dece6358
AM
19729+ SiMustWriteLock(sb);
19730+
1facf9fc 19731+ sbinfo = au_sbi(sb);
19732+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
19733+ br_id = ++sbinfo->si_last_br_id;
19734+ if (br_id && au_br_index(sb, br_id) < 0)
19735+ return br_id;
19736+ }
19737+
19738+ return -1;
19739+}
19740+
19741+/* ---------------------------------------------------------------------- */
19742+
19743+/* dentry and super_block lock. call at entry point */
953406b4 19744+void aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 19745+{
953406b4
AM
19746+ si_read_lock(dentry->d_sb, flags);
19747+ if (au_ftest_lock(flags, DW))
19748+ di_write_lock_child(dentry);
19749+ else
19750+ di_read_lock_child(dentry, flags);
1facf9fc 19751+}
19752+
19753+void aufs_read_unlock(struct dentry *dentry, int flags)
19754+{
19755+ if (au_ftest_lock(flags, DW))
19756+ di_write_unlock(dentry);
19757+ else
19758+ di_read_unlock(dentry, flags);
19759+ si_read_unlock(dentry->d_sb);
19760+}
19761+
19762+void aufs_write_lock(struct dentry *dentry)
19763+{
953406b4 19764+ si_write_lock(dentry->d_sb);
1facf9fc 19765+ di_write_lock_child(dentry);
19766+}
19767+
19768+void aufs_write_unlock(struct dentry *dentry)
19769+{
19770+ di_write_unlock(dentry);
19771+ si_write_unlock(dentry->d_sb);
19772+}
19773+
953406b4 19774+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 19775+{
953406b4
AM
19776+ si_read_lock(d1->d_sb, flags);
19777+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
1facf9fc 19778+}
19779+
19780+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
19781+{
19782+ di_write_unlock2(d1, d2);
19783+ si_read_unlock(d1->d_sb);
19784+}
b752ccd1
AM
19785+
19786+/* ---------------------------------------------------------------------- */
19787+
19788+int si_pid_test_slow(struct super_block *sb)
19789+{
19790+ void *p;
19791+
19792+ rcu_read_lock();
19793+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
19794+ rcu_read_unlock();
19795+
19796+ return (long)p;
19797+}
19798+
19799+void si_pid_set_slow(struct super_block *sb)
19800+{
19801+ int err;
19802+ struct au_sbinfo *sbinfo;
19803+
19804+ AuDebugOn(si_pid_test_slow(sb));
19805+
19806+ sbinfo = au_sbi(sb);
19807+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
19808+ AuDebugOn(err);
19809+ spin_lock(&sbinfo->au_si_pid.tree_lock);
19810+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
19811+ (void *)1);
19812+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
19813+ AuDebugOn(err);
19814+ radix_tree_preload_end();
19815+}
19816+
19817+void si_pid_clr_slow(struct super_block *sb)
19818+{
19819+ void *p;
19820+ struct au_sbinfo *sbinfo;
19821+
19822+ AuDebugOn(!si_pid_test_slow(sb));
19823+
19824+ sbinfo = au_sbi(sb);
19825+ spin_lock(&sbinfo->au_si_pid.tree_lock);
19826+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
19827+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
19828+ AuDebugOn(1 != (long)p);
19829+}
19830diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
19831--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
953406b4 19832+++ linux/fs/aufs/spl.h 2010-10-21 09:52:43.093625591 +0200
4a4d8108 19833@@ -0,0 +1,66 @@
1facf9fc 19834+/*
4a4d8108 19835+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19836+ *
19837+ * This program, aufs is free software; you can redistribute it and/or modify
19838+ * it under the terms of the GNU General Public License as published by
19839+ * the Free Software Foundation; either version 2 of the License, or
19840+ * (at your option) any later version.
dece6358
AM
19841+ *
19842+ * This program is distributed in the hope that it will be useful,
19843+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19844+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19845+ * GNU General Public License for more details.
19846+ *
19847+ * You should have received a copy of the GNU General Public License
19848+ * along with this program; if not, write to the Free Software
19849+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19850+ */
19851+
19852+/*
19853+ * simple list protected by a spinlock
19854+ */
19855+
19856+#ifndef __AUFS_SPL_H__
19857+#define __AUFS_SPL_H__
19858+
19859+#ifdef __KERNEL__
19860+
dece6358
AM
19861+#include <linux/spinlock.h>
19862+#include <linux/list.h>
4a4d8108 19863+#include <linux/rculist.h>
1facf9fc 19864+
19865+struct au_splhead {
19866+ spinlock_t spin;
19867+ struct list_head head;
19868+};
19869+
19870+static inline void au_spl_init(struct au_splhead *spl)
19871+{
19872+ spin_lock_init(&spl->spin);
19873+ INIT_LIST_HEAD(&spl->head);
19874+}
19875+
19876+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
19877+{
19878+ spin_lock(&spl->spin);
19879+ list_add(list, &spl->head);
19880+ spin_unlock(&spl->spin);
19881+}
19882+
19883+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
19884+{
19885+ spin_lock(&spl->spin);
19886+ list_del(list);
19887+ spin_unlock(&spl->spin);
19888+}
19889+
4a4d8108
AM
19890+static inline void au_spl_del_rcu(struct list_head *list,
19891+ struct au_splhead *spl)
19892+{
19893+ spin_lock(&spl->spin);
19894+ list_del_rcu(list);
19895+ spin_unlock(&spl->spin);
19896+}
19897+
1facf9fc 19898+#endif /* __KERNEL__ */
19899+#endif /* __AUFS_SPL_H__ */
b752ccd1
AM
19900diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
19901--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
19902+++ linux/fs/aufs/super.c 2010-10-21 09:52:43.093625591 +0200
19903@@ -0,0 +1,852 @@
1facf9fc 19904+/*
4a4d8108 19905+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19906+ *
19907+ * This program, aufs is free software; you can redistribute it and/or modify
19908+ * it under the terms of the GNU General Public License as published by
19909+ * the Free Software Foundation; either version 2 of the License, or
19910+ * (at your option) any later version.
dece6358
AM
19911+ *
19912+ * This program is distributed in the hope that it will be useful,
19913+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19914+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19915+ * GNU General Public License for more details.
19916+ *
19917+ * You should have received a copy of the GNU General Public License
19918+ * along with this program; if not, write to the Free Software
19919+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19920+ */
19921+
19922+/*
19923+ * mount and super_block operations
19924+ */
19925+
19926+#include <linux/buffer_head.h>
dece6358 19927+#include <linux/module.h>
1facf9fc 19928+#include <linux/seq_file.h>
19929+#include <linux/statfs.h>
19930+#include "aufs.h"
19931+
19932+/*
19933+ * super_operations
19934+ */
19935+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
19936+{
19937+ struct au_icntnr *c;
19938+
19939+ c = au_cache_alloc_icntnr();
19940+ if (c) {
1facf9fc 19941+ c->vfs_inode.i_version = 1; /* sigen(sb); */
19942+ c->iinfo.ii_hinode = NULL;
19943+ return &c->vfs_inode;
19944+ }
19945+ return NULL;
19946+}
19947+
19948+static void aufs_destroy_inode(struct inode *inode)
19949+{
19950+ au_iinfo_fin(inode);
19951+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
19952+}
19953+
19954+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
19955+{
19956+ struct inode *inode;
19957+ int err;
19958+
19959+ inode = iget_locked(sb, ino);
19960+ if (unlikely(!inode)) {
19961+ inode = ERR_PTR(-ENOMEM);
19962+ goto out;
19963+ }
19964+ if (!(inode->i_state & I_NEW))
19965+ goto out;
19966+
19967+ err = au_xigen_new(inode);
19968+ if (!err)
19969+ err = au_iinfo_init(inode);
19970+ if (!err)
19971+ inode->i_version++;
19972+ else {
19973+ iget_failed(inode);
19974+ inode = ERR_PTR(err);
19975+ }
19976+
4f0767ce 19977+out:
1facf9fc 19978+ /* never return NULL */
19979+ AuDebugOn(!inode);
19980+ AuTraceErrPtr(inode);
19981+ return inode;
19982+}
19983+
19984+/* lock free root dinfo */
19985+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
19986+{
19987+ int err;
19988+ aufs_bindex_t bindex, bend;
19989+ struct path path;
4a4d8108 19990+ struct au_hdentry *hdp;
1facf9fc 19991+ struct au_branch *br;
19992+
19993+ err = 0;
19994+ bend = au_sbend(sb);
4a4d8108 19995+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 19996+ for (bindex = 0; !err && bindex <= bend; bindex++) {
19997+ br = au_sbr(sb, bindex);
19998+ path.mnt = br->br_mnt;
4a4d8108 19999+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 20000+ err = au_seq_path(seq, &path);
20001+ if (err > 0)
20002+ err = seq_printf(seq, "=%s",
20003+ au_optstr_br_perm(br->br_perm));
20004+ if (!err && bindex != bend)
20005+ err = seq_putc(seq, ':');
20006+ }
20007+
20008+ return err;
20009+}
20010+
20011+static void au_show_wbr_create(struct seq_file *m, int v,
20012+ struct au_sbinfo *sbinfo)
20013+{
20014+ const char *pat;
20015+
dece6358
AM
20016+ AuRwMustAnyLock(&sbinfo->si_rwsem);
20017+
1facf9fc 20018+ seq_printf(m, ",create=");
20019+ pat = au_optstr_wbr_create(v);
20020+ switch (v) {
20021+ case AuWbrCreate_TDP:
20022+ case AuWbrCreate_RR:
20023+ case AuWbrCreate_MFS:
20024+ case AuWbrCreate_PMFS:
20025+ seq_printf(m, pat);
20026+ break;
20027+ case AuWbrCreate_MFSV:
20028+ seq_printf(m, /*pat*/"mfs:%lu",
953406b4 20029+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
1facf9fc 20030+ break;
20031+ case AuWbrCreate_PMFSV:
20032+ seq_printf(m, /*pat*/"pmfs:%lu",
953406b4 20033+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
1facf9fc 20034+ break;
20035+ case AuWbrCreate_MFSRR:
20036+ seq_printf(m, /*pat*/"mfsrr:%llu",
20037+ sbinfo->si_wbr_mfs.mfsrr_watermark);
20038+ break;
20039+ case AuWbrCreate_MFSRRV:
20040+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
20041+ sbinfo->si_wbr_mfs.mfsrr_watermark,
953406b4 20042+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
1facf9fc 20043+ break;
20044+ }
20045+}
20046+
20047+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
20048+{
20049+#ifdef CONFIG_SYSFS
20050+ return 0;
20051+#else
20052+ int err;
20053+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
20054+ aufs_bindex_t bindex, brid;
20055+ struct super_block *sb;
20056+ struct qstr *name;
20057+ struct file *f;
20058+ struct dentry *d, *h_root;
4a4d8108 20059+ struct au_hdentry *hdp;
1facf9fc 20060+
dece6358
AM
20061+ AuRwMustAnyLock(&sbinfo->si_rwsem);
20062+
1facf9fc 20063+ err = 0;
20064+ sb = mnt->mnt_sb;
20065+ f = au_sbi(sb)->si_xib;
20066+ if (!f)
20067+ goto out;
20068+
20069+ /* stop printing the default xino path on the first writable branch */
20070+ h_root = NULL;
20071+ brid = au_xino_brid(sb);
20072+ if (brid >= 0) {
20073+ bindex = au_br_index(sb, brid);
4a4d8108
AM
20074+ hdp = au_di(sb->s_root)->di_hdentry;
20075+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 20076+ }
20077+ d = f->f_dentry;
20078+ name = &d->d_name;
20079+ /* safe ->d_parent because the file is unlinked */
20080+ if (d->d_parent == h_root
20081+ && name->len == len
20082+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
20083+ goto out;
20084+
20085+ seq_puts(seq, ",xino=");
20086+ err = au_xino_path(seq, f);
20087+
4f0767ce 20088+out:
1facf9fc 20089+ return err;
20090+#endif
20091+}
20092+
20093+/* seq_file will re-call me in case of too long string */
20094+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
20095+{
20096+ int err, n;
20097+ unsigned int mnt_flags, v;
20098+ struct super_block *sb;
20099+ struct au_sbinfo *sbinfo;
20100+
20101+#define AuBool(name, str) do { \
20102+ v = au_opt_test(mnt_flags, name); \
20103+ if (v != au_opt_test(AuOpt_Def, name)) \
20104+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
20105+} while (0)
20106+
20107+#define AuStr(name, str) do { \
20108+ v = mnt_flags & AuOptMask_##name; \
20109+ if (v != (AuOpt_Def & AuOptMask_##name)) \
20110+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
20111+} while (0)
20112+
20113+#define AuUInt(name, str, val) do { \
20114+ if (val != AUFS_##name##_DEF) \
20115+ seq_printf(m, "," #str "=%u", val); \
20116+} while (0)
20117+
20118+ /* lock free root dinfo */
20119+ sb = mnt->mnt_sb;
20120+ si_noflush_read_lock(sb);
20121+ sbinfo = au_sbi(sb);
20122+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
20123+
20124+ mnt_flags = au_mntflags(sb);
20125+ if (au_opt_test(mnt_flags, XINO)) {
20126+ err = au_show_xino(m, mnt);
20127+ if (unlikely(err))
20128+ goto out;
20129+ } else
20130+ seq_puts(m, ",noxino");
20131+
20132+ AuBool(TRUNC_XINO, trunc_xino);
20133+ AuStr(UDBA, udba);
dece6358 20134+ AuBool(SHWH, shwh);
1facf9fc 20135+ AuBool(PLINK, plink);
4a4d8108 20136+ AuBool(DIO, dio);
1facf9fc 20137+ /* AuBool(DIRPERM1, dirperm1); */
20138+ /* AuBool(REFROF, refrof); */
20139+
20140+ v = sbinfo->si_wbr_create;
20141+ if (v != AuWbrCreate_Def)
20142+ au_show_wbr_create(m, v, sbinfo);
20143+
20144+ v = sbinfo->si_wbr_copyup;
20145+ if (v != AuWbrCopyup_Def)
20146+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
20147+
20148+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
20149+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
20150+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
20151+
20152+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
20153+
953406b4 20154+ n = sbinfo->si_rdcache / HZ;
1facf9fc 20155+ AuUInt(RDCACHE, rdcache, n);
20156+
20157+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
20158+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
20159+
20160+ AuBool(SUM, sum);
20161+ /* AuBool(SUM_W, wsum); */
20162+ AuBool(WARN_PERM, warn_perm);
20163+ AuBool(VERBOSE, verbose);
20164+
4f0767ce 20165+out:
1facf9fc 20166+ /* be sure to print "br:" last */
20167+ if (!sysaufs_brs) {
20168+ seq_puts(m, ",br:");
20169+ au_show_brs(m, sb);
20170+ }
20171+ si_read_unlock(sb);
20172+ return 0;
20173+
1facf9fc 20174+#undef AuBool
20175+#undef AuStr
4a4d8108 20176+#undef AuUInt
1facf9fc 20177+}
20178+
20179+/* ---------------------------------------------------------------------- */
20180+
20181+/* sum mode which returns the summation for statfs(2) */
20182+
20183+static u64 au_add_till_max(u64 a, u64 b)
20184+{
20185+ u64 old;
20186+
20187+ old = a;
20188+ a += b;
20189+ if (old < a)
20190+ return a;
20191+ return ULLONG_MAX;
20192+}
20193+
20194+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
20195+{
20196+ int err;
20197+ u64 blocks, bfree, bavail, files, ffree;
20198+ aufs_bindex_t bend, bindex, i;
20199+ unsigned char shared;
953406b4 20200+ struct path h_path;
1facf9fc 20201+ struct super_block *h_sb;
20202+
20203+ blocks = 0;
20204+ bfree = 0;
20205+ bavail = 0;
20206+ files = 0;
20207+ ffree = 0;
20208+
20209+ err = 0;
20210+ bend = au_sbend(sb);
20211+ for (bindex = bend; bindex >= 0; bindex--) {
953406b4
AM
20212+ h_path.mnt = au_sbr_mnt(sb, bindex);
20213+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 20214+ shared = 0;
20215+ for (i = bindex + 1; !shared && i <= bend; i++)
20216+ shared = (au_sbr_sb(sb, i) == h_sb);
20217+ if (shared)
20218+ continue;
20219+
20220+ /* sb->s_root for NFS is unreliable */
953406b4
AM
20221+ h_path.dentry = h_path.mnt->mnt_root;
20222+ err = vfs_statfs(&h_path, buf);
1facf9fc 20223+ if (unlikely(err))
20224+ goto out;
20225+
20226+ blocks = au_add_till_max(blocks, buf->f_blocks);
20227+ bfree = au_add_till_max(bfree, buf->f_bfree);
20228+ bavail = au_add_till_max(bavail, buf->f_bavail);
20229+ files = au_add_till_max(files, buf->f_files);
20230+ ffree = au_add_till_max(ffree, buf->f_ffree);
20231+ }
20232+
20233+ buf->f_blocks = blocks;
20234+ buf->f_bfree = bfree;
20235+ buf->f_bavail = bavail;
20236+ buf->f_files = files;
20237+ buf->f_ffree = ffree;
20238+
4f0767ce 20239+out:
1facf9fc 20240+ return err;
20241+}
20242+
20243+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
20244+{
20245+ int err;
953406b4 20246+ struct path h_path;
1facf9fc 20247+ struct super_block *sb;
20248+
20249+ /* lock free root dinfo */
20250+ sb = dentry->d_sb;
20251+ si_noflush_read_lock(sb);
953406b4 20252+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 20253+ /* sb->s_root for NFS is unreliable */
953406b4
AM
20254+ h_path.mnt = au_sbr_mnt(sb, 0);
20255+ h_path.dentry = h_path.mnt->mnt_root;
20256+ err = vfs_statfs(&h_path, buf);
20257+ } else
1facf9fc 20258+ err = au_statfs_sum(sb, buf);
20259+ si_read_unlock(sb);
20260+
20261+ if (!err) {
20262+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 20263+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 20264+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
20265+ }
20266+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
20267+
20268+ return err;
20269+}
20270+
20271+/* ---------------------------------------------------------------------- */
20272+
953406b4
AM
20273+/*
20274+ * this IS NOT for super_operations.
20275+ * I guess it will be reverted someday.
20276+ */
20277+static void aufs_umount_begin(struct super_block *sb)
20278+{
20279+ struct au_sbinfo *sbinfo;
20280+
20281+ sbinfo = au_sbi(sb);
20282+ if (!sbinfo)
20283+ return;
20284+
20285+ si_write_lock(sb);
20286+ if (au_opt_test(au_mntflags(sb), PLINK))
20287+ au_plink_put(sb);
20288+ if (sbinfo->si_wbr_create_ops->fin)
20289+ sbinfo->si_wbr_create_ops->fin(sb);
20290+ si_write_unlock(sb);
20291+}
20292+
1facf9fc 20293+/* final actions when unmounting a file system */
20294+static void aufs_put_super(struct super_block *sb)
20295+{
20296+ struct au_sbinfo *sbinfo;
20297+
20298+ sbinfo = au_sbi(sb);
20299+ if (!sbinfo)
20300+ return;
20301+
953406b4 20302+ aufs_umount_begin(sb);
1facf9fc 20303+ dbgaufs_si_fin(sbinfo);
20304+ kobject_put(&sbinfo->si_kobj);
20305+}
20306+
20307+/* ---------------------------------------------------------------------- */
20308+
20309+/*
20310+ * refresh dentry and inode at remount time.
20311+ */
20312+static int do_refresh(struct dentry *dentry, mode_t type,
20313+ unsigned int dir_flags)
20314+{
20315+ int err;
20316+ struct dentry *parent;
20317+
20318+ di_write_lock_child(dentry);
20319+ parent = dget_parent(dentry);
20320+ di_read_lock_parent(parent, AuLock_IR);
20321+
20322+ /* returns the number of positive dentries */
20323+ err = au_refresh_hdentry(dentry, type);
20324+ if (err >= 0) {
20325+ struct inode *inode = dentry->d_inode;
20326+ err = au_refresh_hinode(inode, dentry);
20327+ if (!err && type == S_IFDIR)
4a4d8108 20328+ au_hn_reset(inode, dir_flags);
1facf9fc 20329+ }
20330+ if (unlikely(err))
4a4d8108
AM
20331+ pr_err("unrecoverable error %d, %.*s\n",
20332+ err, AuDLNPair(dentry));
1facf9fc 20333+
20334+ di_read_unlock(parent, AuLock_IR);
20335+ dput(parent);
20336+ di_write_unlock(dentry);
20337+
20338+ return err;
20339+}
20340+
20341+static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
20342+{
20343+ return S_ISDIR(dentry->d_inode->i_mode);
20344+}
20345+
20346+/* gave up consolidating with refresh_nondir() */
20347+static int refresh_dir(struct dentry *root, unsigned int sigen)
20348+{
20349+ int err, i, j, ndentry, e;
20350+ struct au_dcsub_pages dpages;
20351+ struct au_dpage *dpage;
20352+ struct dentry **dentries;
20353+ struct inode *inode;
20354+ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
20355+
20356+ err = 0;
20357+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20358+ if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20359+ ii_write_lock_child(inode);
20360+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
20361+ ii_write_unlock(inode);
20362+ if (unlikely(e)) {
20363+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
20364+ if (!err)
20365+ err = e;
20366+ /* go on even if err */
20367+ }
20368+ }
20369+
20370+ e = au_dpages_init(&dpages, GFP_NOFS);
20371+ if (unlikely(e)) {
20372+ if (!err)
20373+ err = e;
20374+ goto out;
20375+ }
20376+ e = au_dcsub_pages(&dpages, root, test_dir, NULL);
20377+ if (unlikely(e)) {
20378+ if (!err)
20379+ err = e;
20380+ goto out_dpages;
20381+ }
20382+
20383+ for (i = 0; !e && i < dpages.ndpage; i++) {
20384+ dpage = dpages.dpages + i;
20385+ dentries = dpage->dentries;
20386+ ndentry = dpage->ndentry;
20387+ for (j = 0; !e && j < ndentry; j++) {
20388+ struct dentry *d;
20389+
20390+ d = dentries[j];
20391+ au_dbg_verify_dir_parent(d, sigen);
20392+ if (au_digen(d) != sigen) {
20393+ e = do_refresh(d, S_IFDIR, flags);
20394+ if (unlikely(e && !err))
20395+ err = e;
20396+ /* break on err */
20397+ }
20398+ }
20399+ }
20400+
4f0767ce 20401+out_dpages:
1facf9fc 20402+ au_dpages_free(&dpages);
4f0767ce 20403+out:
1facf9fc 20404+ return err;
20405+}
20406+
20407+static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
20408+{
20409+ return !S_ISDIR(dentry->d_inode->i_mode);
20410+}
20411+
20412+static int refresh_nondir(struct dentry *root, unsigned int sigen,
20413+ int do_dentry)
20414+{
20415+ int err, i, j, ndentry, e;
20416+ struct au_dcsub_pages dpages;
20417+ struct au_dpage *dpage;
20418+ struct dentry **dentries;
20419+ struct inode *inode;
20420+
20421+ err = 0;
20422+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20423+ if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20424+ ii_write_lock_child(inode);
20425+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
20426+ ii_write_unlock(inode);
20427+ if (unlikely(e)) {
20428+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
20429+ if (!err)
20430+ err = e;
20431+ /* go on even if err */
20432+ }
20433+ }
20434+
20435+ if (!do_dentry)
20436+ goto out;
20437+
20438+ e = au_dpages_init(&dpages, GFP_NOFS);
20439+ if (unlikely(e)) {
20440+ if (!err)
20441+ err = e;
20442+ goto out;
20443+ }
20444+ e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
20445+ if (unlikely(e)) {
20446+ if (!err)
20447+ err = e;
20448+ goto out_dpages;
20449+ }
20450+
20451+ for (i = 0; i < dpages.ndpage; i++) {
20452+ dpage = dpages.dpages + i;
20453+ dentries = dpage->dentries;
20454+ ndentry = dpage->ndentry;
20455+ for (j = 0; j < ndentry; j++) {
20456+ struct dentry *d;
20457+
20458+ d = dentries[j];
20459+ au_dbg_verify_nondir_parent(d, sigen);
20460+ inode = d->d_inode;
20461+ if (inode && au_digen(d) != sigen) {
20462+ e = do_refresh(d, inode->i_mode & S_IFMT,
20463+ /*dir_flags*/0);
20464+ if (unlikely(e && !err))
20465+ err = e;
20466+ /* go on even err */
20467+ }
20468+ }
20469+ }
20470+
4f0767ce 20471+out_dpages:
1facf9fc 20472+ au_dpages_free(&dpages);
4f0767ce 20473+out:
1facf9fc 20474+ return err;
20475+}
20476+
20477+static void au_remount_refresh(struct super_block *sb, unsigned int flags)
20478+{
20479+ int err;
20480+ unsigned int sigen;
20481+ struct au_sbinfo *sbinfo;
20482+ struct dentry *root;
20483+ struct inode *inode;
20484+
20485+ au_sigen_inc(sb);
20486+ sigen = au_sigen(sb);
20487+ sbinfo = au_sbi(sb);
20488+ au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
20489+
20490+ root = sb->s_root;
20491+ DiMustNoWaiters(root);
20492+ inode = root->d_inode;
20493+ IiMustNoWaiters(inode);
4a4d8108 20494+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 20495+ di_write_unlock(root);
20496+
20497+ err = refresh_dir(root, sigen);
20498+ if (unlikely(err)) {
20499+ au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
4a4d8108
AM
20500+ pr_warning("Refreshing directories failed, ignored (%d)\n",
20501+ err);
1facf9fc 20502+ }
20503+
20504+ if (au_ftest_opts(flags, REFRESH_NONDIR)) {
20505+ err = refresh_nondir(root, sigen, !err);
20506+ if (unlikely(err))
4a4d8108
AM
20507+ pr_warning("Refreshing non-directories failed, ignored"
20508+ "(%d)\n", err);
1facf9fc 20509+ }
20510+
20511+ /* aufs_write_lock() calls ..._child() */
20512+ di_write_lock_child(root);
20513+ au_cpup_attr_all(root->d_inode, /*force*/1);
20514+}
20515+
20516+/* stop extra interpretation of errno in mount(8), and strange error messages */
20517+static int cvt_err(int err)
20518+{
20519+ AuTraceErr(err);
20520+
20521+ switch (err) {
20522+ case -ENOENT:
20523+ case -ENOTDIR:
20524+ case -EEXIST:
20525+ case -EIO:
20526+ err = -EINVAL;
20527+ }
20528+ return err;
20529+}
20530+
20531+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
20532+{
4a4d8108
AM
20533+ int err, do_dx;
20534+ unsigned int mntflags;
1facf9fc 20535+ struct au_opts opts;
20536+ struct dentry *root;
20537+ struct inode *inode;
20538+ struct au_sbinfo *sbinfo;
20539+
20540+ err = 0;
20541+ root = sb->s_root;
20542+ if (!data || !*data) {
953406b4
AM
20543+ aufs_write_lock(root);
20544+ err = au_opts_verify(sb, *flags, /*pending*/0);
20545+ aufs_write_unlock(root);
1facf9fc 20546+ goto out;
20547+ }
20548+
20549+ err = -ENOMEM;
20550+ memset(&opts, 0, sizeof(opts));
20551+ opts.opt = (void *)__get_free_page(GFP_NOFS);
20552+ if (unlikely(!opts.opt))
20553+ goto out;
20554+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
20555+ opts.flags = AuOpts_REMOUNT;
20556+ opts.sb_flags = *flags;
20557+
20558+ /* parse it before aufs lock */
20559+ err = au_opts_parse(sb, data, &opts);
20560+ if (unlikely(err))
20561+ goto out_opts;
20562+
20563+ sbinfo = au_sbi(sb);
20564+ inode = root->d_inode;
20565+ mutex_lock(&inode->i_mutex);
953406b4 20566+ aufs_write_lock(root);
1facf9fc 20567+
20568+ /* au_opts_remount() may return an error */
20569+ err = au_opts_remount(sb, &opts);
20570+ au_opts_free(&opts);
20571+
20572+ if (au_ftest_opts(opts.flags, REFRESH_DIR)
20573+ || au_ftest_opts(opts.flags, REFRESH_NONDIR))
20574+ au_remount_refresh(sb, opts.flags);
20575+
4a4d8108
AM
20576+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
20577+ mntflags = au_mntflags(sb);
20578+ do_dx = !!au_opt_test(mntflags, DIO);
20579+ au_dy_arefresh(do_dx);
20580+ }
20581+
1facf9fc 20582+ aufs_write_unlock(root);
4f0767ce 20583+ mutex_unlock(&inode->i_mutex);
953406b4 20584+
4f0767ce 20585+out_opts:
1facf9fc 20586+ free_page((unsigned long)opts.opt);
4f0767ce 20587+out:
1facf9fc 20588+ err = cvt_err(err);
20589+ AuTraceErr(err);
20590+ return err;
20591+}
20592+
4a4d8108 20593+static const struct super_operations aufs_sop = {
1facf9fc 20594+ .alloc_inode = aufs_alloc_inode,
20595+ .destroy_inode = aufs_destroy_inode,
b752ccd1 20596+ /* always deleting, no clearing */
1facf9fc 20597+ .drop_inode = generic_delete_inode,
20598+ .show_options = aufs_show_options,
20599+ .statfs = aufs_statfs,
20600+ .put_super = aufs_put_super,
20601+ .remount_fs = aufs_remount_fs
20602+};
20603+
20604+/* ---------------------------------------------------------------------- */
20605+
20606+static int alloc_root(struct super_block *sb)
20607+{
20608+ int err;
20609+ struct inode *inode;
20610+ struct dentry *root;
20611+
20612+ err = -ENOMEM;
20613+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
20614+ err = PTR_ERR(inode);
20615+ if (IS_ERR(inode))
20616+ goto out;
20617+
20618+ inode->i_op = &aufs_dir_iop;
20619+ inode->i_fop = &aufs_dir_fop;
20620+ inode->i_mode = S_IFDIR;
20621+ inode->i_nlink = 2;
20622+ unlock_new_inode(inode);
20623+
20624+ root = d_alloc_root(inode);
20625+ if (unlikely(!root))
20626+ goto out_iput;
20627+ err = PTR_ERR(root);
20628+ if (IS_ERR(root))
20629+ goto out_iput;
20630+
4a4d8108 20631+ err = au_di_init(root);
1facf9fc 20632+ if (!err) {
20633+ sb->s_root = root;
20634+ return 0; /* success */
20635+ }
20636+ dput(root);
20637+ goto out; /* do not iput */
20638+
4f0767ce 20639+out_iput:
1facf9fc 20640+ iget_failed(inode);
953406b4 20641+ iput(inode);
4f0767ce 20642+out:
1facf9fc 20643+ return err;
20644+
20645+}
20646+
20647+static int aufs_fill_super(struct super_block *sb, void *raw_data,
20648+ int silent __maybe_unused)
20649+{
20650+ int err;
20651+ struct au_opts opts;
20652+ struct dentry *root;
20653+ struct inode *inode;
20654+ char *arg = raw_data;
20655+
20656+ if (unlikely(!arg || !*arg)) {
20657+ err = -EINVAL;
4a4d8108 20658+ pr_err("no arg\n");
1facf9fc 20659+ goto out;
20660+ }
20661+
20662+ err = -ENOMEM;
20663+ memset(&opts, 0, sizeof(opts));
20664+ opts.opt = (void *)__get_free_page(GFP_NOFS);
20665+ if (unlikely(!opts.opt))
20666+ goto out;
20667+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
20668+ opts.sb_flags = sb->s_flags;
20669+
20670+ err = au_si_alloc(sb);
20671+ if (unlikely(err))
20672+ goto out_opts;
20673+
20674+ /* all timestamps always follow the ones on the branch */
20675+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
20676+ sb->s_op = &aufs_sop;
20677+ sb->s_magic = AUFS_SUPER_MAGIC;
20678+ sb->s_maxbytes = 0;
20679+ au_export_init(sb);
20680+
20681+ err = alloc_root(sb);
20682+ if (unlikely(err)) {
20683+ si_write_unlock(sb);
20684+ goto out_info;
20685+ }
20686+ root = sb->s_root;
20687+ inode = root->d_inode;
20688+
20689+ /*
20690+ * actually we can parse options regardless aufs lock here.
20691+ * but at remount time, parsing must be done before aufs lock.
20692+ * so we follow the same rule.
20693+ */
20694+ ii_write_lock_parent(inode);
20695+ aufs_write_unlock(root);
20696+ err = au_opts_parse(sb, arg, &opts);
20697+ if (unlikely(err))
20698+ goto out_root;
20699+
20700+ /* lock vfs_inode first, then aufs. */
20701+ mutex_lock(&inode->i_mutex);
1facf9fc 20702+ aufs_write_lock(root);
20703+ err = au_opts_mount(sb, &opts);
20704+ au_opts_free(&opts);
1facf9fc 20705+ aufs_write_unlock(root);
20706+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
20707+ if (!err)
20708+ goto out_opts; /* success */
1facf9fc 20709+
4f0767ce 20710+out_root:
1facf9fc 20711+ dput(root);
20712+ sb->s_root = NULL;
4f0767ce 20713+out_info:
1facf9fc 20714+ kobject_put(&au_sbi(sb)->si_kobj);
20715+ sb->s_fs_info = NULL;
4f0767ce 20716+out_opts:
1facf9fc 20717+ free_page((unsigned long)opts.opt);
4f0767ce 20718+out:
1facf9fc 20719+ AuTraceErr(err);
20720+ err = cvt_err(err);
20721+ AuTraceErr(err);
20722+ return err;
20723+}
20724+
20725+/* ---------------------------------------------------------------------- */
20726+
20727+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
20728+ const char *dev_name __maybe_unused, void *raw_data,
20729+ struct vfsmount *mnt)
20730+{
20731+ int err;
20732+ struct super_block *sb;
20733+
20734+ /* all timestamps always follow the ones on the branch */
20735+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
20736+ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
20737+ if (!err) {
20738+ sb = mnt->mnt_sb;
953406b4 20739+ si_write_lock(sb);
1facf9fc 20740+ sysaufs_brs_add(sb, 0);
20741+ si_write_unlock(sb);
20742+ }
20743+ return err;
20744+}
20745+
20746+struct file_system_type aufs_fs_type = {
20747+ .name = AUFS_FSTYPE,
20748+ .fs_flags =
20749+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
20750+ | FS_REVAL_DOT, /* for NFS branch and udba */
20751+ .get_sb = aufs_get_sb,
953406b4 20752+ .kill_sb = generic_shutdown_super,
1facf9fc 20753+ /* no need to __module_get() and module_put(). */
20754+ .owner = THIS_MODULE,
20755+};
b752ccd1
AM
20756diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
20757--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
20758+++ linux/fs/aufs/super.h 2010-10-21 09:52:43.093625591 +0200
20759@@ -0,0 +1,465 @@
1facf9fc 20760+/*
4a4d8108 20761+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20762+ *
20763+ * This program, aufs is free software; you can redistribute it and/or modify
20764+ * it under the terms of the GNU General Public License as published by
20765+ * the Free Software Foundation; either version 2 of the License, or
20766+ * (at your option) any later version.
dece6358
AM
20767+ *
20768+ * This program is distributed in the hope that it will be useful,
20769+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20770+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20771+ * GNU General Public License for more details.
20772+ *
20773+ * You should have received a copy of the GNU General Public License
20774+ * along with this program; if not, write to the Free Software
20775+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20776+ */
20777+
20778+/*
20779+ * super_block operations
20780+ */
20781+
20782+#ifndef __AUFS_SUPER_H__
20783+#define __AUFS_SUPER_H__
20784+
20785+#ifdef __KERNEL__
20786+
20787+#include <linux/fs.h>
1facf9fc 20788+#include <linux/aufs_type.h>
20789+#include "rwsem.h"
20790+#include "spl.h"
20791+#include "wkq.h"
20792+
20793+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
20794+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
20795+ loff_t *);
20796+
20797+/* policies to select one among multiple writable branches */
20798+struct au_wbr_copyup_operations {
20799+ int (*copyup)(struct dentry *dentry);
20800+};
20801+
20802+struct au_wbr_create_operations {
20803+ int (*create)(struct dentry *dentry, int isdir);
20804+ int (*init)(struct super_block *sb);
20805+ int (*fin)(struct super_block *sb);
20806+};
20807+
20808+struct au_wbr_mfs {
20809+ struct mutex mfs_lock; /* protect this structure */
20810+ unsigned long mfs_jiffy;
20811+ unsigned long mfs_expire;
20812+ aufs_bindex_t mfs_bindex;
20813+
20814+ unsigned long long mfsrr_bytes;
20815+ unsigned long long mfsrr_watermark;
20816+};
20817+
1facf9fc 20818+struct au_branch;
20819+struct au_sbinfo {
20820+ /* nowait tasks in the system-wide workqueue */
20821+ struct au_nowait_tasks si_nowait;
20822+
b752ccd1
AM
20823+ /*
20824+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
20825+ * rwsem for au_sbinfo is necessary.
20826+ */
dece6358 20827+ struct au_rwsem si_rwsem;
1facf9fc 20828+
b752ccd1
AM
20829+ /* prevent recursive locking in deleting inode */
20830+ struct {
20831+ unsigned long *bitmap;
20832+ spinlock_t tree_lock;
20833+ struct radix_tree_root tree;
20834+ } au_si_pid;
20835+
1facf9fc 20836+ /* branch management */
20837+ unsigned int si_generation;
20838+
20839+ /* see above flags */
20840+ unsigned char au_si_status;
20841+
20842+ aufs_bindex_t si_bend;
20843+ aufs_bindex_t si_last_br_id;
20844+ struct au_branch **si_branch;
20845+
20846+ /* policy to select a writable branch */
20847+ unsigned char si_wbr_copyup;
20848+ unsigned char si_wbr_create;
20849+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
20850+ struct au_wbr_create_operations *si_wbr_create_ops;
20851+
20852+ /* round robin */
20853+ atomic_t si_wbr_rr_next;
20854+
20855+ /* most free space */
20856+ struct au_wbr_mfs si_wbr_mfs;
20857+
20858+ /* mount flags */
20859+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
20860+ unsigned int si_mntflags;
20861+
20862+ /* external inode number (bitmap and translation table) */
20863+ au_readf_t si_xread;
20864+ au_writef_t si_xwrite;
20865+ struct file *si_xib;
20866+ struct mutex si_xib_mtx; /* protect xib members */
20867+ unsigned long *si_xib_buf;
20868+ unsigned long si_xib_last_pindex;
20869+ int si_xib_next_bit;
20870+ aufs_bindex_t si_xino_brid;
20871+ /* reserved for future use */
20872+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
20873+
20874+#ifdef CONFIG_AUFS_EXPORT
20875+ /* i_generation */
20876+ struct file *si_xigen;
20877+ atomic_t si_xigen_next;
20878+#endif
20879+
20880+ /* vdir parameters */
953406b4 20881+ unsigned long si_rdcache; /* max cache time in HZ */
1facf9fc 20882+ unsigned int si_rdblk; /* deblk size */
20883+ unsigned int si_rdhash; /* hash size */
20884+
20885+ /*
20886+ * If the number of whiteouts are larger than si_dirwh, leave all of
20887+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
20888+ * future fsck.aufs or kernel thread will remove them later.
20889+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
20890+ */
20891+ unsigned int si_dirwh;
20892+
20893+ /*
20894+ * rename(2) a directory with all children.
20895+ */
20896+ /* reserved for future use */
20897+ /* int si_rendir; */
20898+
20899+ /* pseudo_link list */
20900+ struct au_splhead si_plink;
20901+ wait_queue_head_t si_plink_wq;
4a4d8108 20902+ spinlock_t si_plink_maint_lock;
953406b4 20903+ struct file *si_plink_maint;
1facf9fc 20904+
20905+ /*
20906+ * sysfs and lifetime management.
20907+ * this is not a small structure and it may be a waste of memory in case
20908+ * of sysfs is disabled, particulary when many aufs-es are mounted.
20909+ * but using sysfs is majority.
20910+ */
20911+ struct kobject si_kobj;
20912+#ifdef CONFIG_DEBUG_FS
20913+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
20914+#ifdef CONFIG_AUFS_EXPORT
20915+ struct dentry *si_dbgaufs_xigen;
20916+#endif
20917+#endif
20918+
20919+ /* dirty, necessary for unmounting, sysfs and sysrq */
20920+ struct super_block *si_sb;
20921+};
20922+
dece6358
AM
20923+/* sbinfo status flags */
20924+/*
20925+ * set true when refresh_dirs() failed at remount time.
20926+ * then try refreshing dirs at access time again.
20927+ * if it is false, refreshing dirs at access time is unnecesary
20928+ */
20929+#define AuSi_FAILED_REFRESH_DIRS 1
dece6358
AM
20930+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
20931+ unsigned int flag)
20932+{
20933+ AuRwMustAnyLock(&sbi->si_rwsem);
20934+ return sbi->au_si_status & flag;
20935+}
20936+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
20937+#define au_fset_si(sbinfo, name) do { \
20938+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
20939+ (sbinfo)->au_si_status |= AuSi_##name; \
20940+} while (0)
20941+#define au_fclr_si(sbinfo, name) do { \
20942+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
20943+ (sbinfo)->au_si_status &= ~AuSi_##name; \
20944+} while (0)
20945+
1facf9fc 20946+/* ---------------------------------------------------------------------- */
20947+
20948+/* policy to select one among writable branches */
4a4d8108
AM
20949+#define AuWbrCopyup(sbinfo, ...) \
20950+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
20951+#define AuWbrCreate(sbinfo, ...) \
20952+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 20953+
20954+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
20955+#define AuLock_DW 1 /* write-lock dentry */
20956+#define AuLock_IR (1 << 1) /* read-lock inode */
20957+#define AuLock_IW (1 << 2) /* write-lock inode */
20958+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
20959+#define AuLock_DIR (1 << 4) /* target is a dir */
20960+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
20961+#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
20962+#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
20963+
20964+/* ---------------------------------------------------------------------- */
20965+
20966+/* super.c */
20967+extern struct file_system_type aufs_fs_type;
20968+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
20969+
20970+/* sbinfo.c */
20971+void au_si_free(struct kobject *kobj);
20972+int au_si_alloc(struct super_block *sb);
20973+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
20974+
20975+unsigned int au_sigen_inc(struct super_block *sb);
20976+aufs_bindex_t au_new_br_id(struct super_block *sb);
20977+
953406b4 20978+void aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 20979+void aufs_read_unlock(struct dentry *dentry, int flags);
20980+void aufs_write_lock(struct dentry *dentry);
20981+void aufs_write_unlock(struct dentry *dentry);
953406b4 20982+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
1facf9fc 20983+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
20984+
b752ccd1
AM
20985+int si_pid_test_slow(struct super_block *sb);
20986+void si_pid_set_slow(struct super_block *sb);
20987+void si_pid_clr_slow(struct super_block *sb);
20988+
1facf9fc 20989+/* wbr_policy.c */
20990+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
20991+extern struct au_wbr_create_operations au_wbr_create_ops[];
20992+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
20993+
20994+/* ---------------------------------------------------------------------- */
20995+
20996+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
20997+{
20998+ return sb->s_fs_info;
20999+}
21000+
21001+/* ---------------------------------------------------------------------- */
21002+
21003+#ifdef CONFIG_AUFS_EXPORT
21004+void au_export_init(struct super_block *sb);
21005+
b752ccd1 21006+static inline int au_test_nfsd(void)
1facf9fc 21007+{
b752ccd1
AM
21008+ struct task_struct *tsk = current;
21009+
21010+ return (tsk->flags & PF_KTHREAD)
21011+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 21012+}
21013+
b752ccd1 21014+void au_xigen_inc(struct inode *inode);
1facf9fc 21015+int au_xigen_new(struct inode *inode);
21016+int au_xigen_set(struct super_block *sb, struct file *base);
21017+void au_xigen_clr(struct super_block *sb);
21018+
21019+static inline int au_busy_or_stale(void)
21020+{
b752ccd1 21021+ if (!au_test_nfsd())
1facf9fc 21022+ return -EBUSY;
21023+ return -ESTALE;
21024+}
21025+#else
4a4d8108 21026+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
21027+AuStubInt0(au_test_nfsd, void)
21028+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
21029+AuStubInt0(au_xigen_new, struct inode *inode)
21030+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
21031+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 21032+static inline int au_busy_or_stale(void)
21033+{
21034+ return -EBUSY;
21035+}
21036+#endif /* CONFIG_AUFS_EXPORT */
21037+
21038+/* ---------------------------------------------------------------------- */
21039+
21040+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
21041+{
dece6358
AM
21042+ /*
21043+ * This function is a dynamic '__init' fucntion actually,
21044+ * so the tiny check for si_rwsem is unnecessary.
21045+ */
21046+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 21047+#ifdef CONFIG_DEBUG_FS
21048+ sbinfo->si_dbgaufs = NULL;
21049+ sbinfo->si_dbgaufs_xib = NULL;
21050+#ifdef CONFIG_AUFS_EXPORT
21051+ sbinfo->si_dbgaufs_xigen = NULL;
21052+#endif
21053+#endif
21054+}
21055+
21056+/* ---------------------------------------------------------------------- */
21057+
b752ccd1
AM
21058+static inline pid_t si_pid_bit(void)
21059+{
21060+ /* the origin of pid is 1, but the bitmap's is 0 */
21061+ return current->pid - 1;
21062+}
21063+
21064+static inline int si_pid_test(struct super_block *sb)
21065+{
21066+ pid_t bit = si_pid_bit();
21067+ if (bit < PID_MAX_DEFAULT)
21068+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21069+ else
21070+ return si_pid_test_slow(sb);
21071+}
21072+
21073+static inline void si_pid_set(struct super_block *sb)
21074+{
21075+ pid_t bit = si_pid_bit();
21076+ if (bit < PID_MAX_DEFAULT) {
21077+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21078+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21079+ /* smp_mb(); */
21080+ } else
21081+ si_pid_set_slow(sb);
21082+}
21083+
21084+static inline void si_pid_clr(struct super_block *sb)
21085+{
21086+ pid_t bit = si_pid_bit();
21087+ if (bit < PID_MAX_DEFAULT) {
21088+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21089+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21090+ /* smp_mb(); */
21091+ } else
21092+ si_pid_clr_slow(sb);
21093+}
21094+
21095+/* ---------------------------------------------------------------------- */
21096+
1facf9fc 21097+/* lock superblock. mainly for entry point functions */
21098+/*
b752ccd1
AM
21099+ * __si_read_lock, __si_write_lock,
21100+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 21101+ */
b752ccd1 21102+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 21103+
dece6358
AM
21104+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
21105+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
21106+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
21107+
b752ccd1
AM
21108+static inline void si_noflush_read_lock(struct super_block *sb)
21109+{
21110+ __si_read_lock(sb);
21111+ si_pid_set(sb);
21112+}
21113+
21114+static inline int si_noflush_read_trylock(struct super_block *sb)
21115+{
21116+ int locked = __si_read_trylock(sb);
21117+ if (locked)
21118+ si_pid_set(sb);
21119+ return locked;
21120+}
21121+
21122+static inline void si_noflush_write_lock(struct super_block *sb)
21123+{
21124+ __si_write_lock(sb);
21125+ si_pid_set(sb);
21126+}
21127+
21128+static inline int si_noflush_write_trylock(struct super_block *sb)
21129+{
21130+ int locked = __si_write_trylock(sb);
21131+ if (locked)
21132+ si_pid_set(sb);
21133+ return locked;
21134+}
21135+
953406b4
AM
21136+static inline void si_read_lock(struct super_block *sb, int flags)
21137+{
21138+ if (au_ftest_lock(flags, FLUSH))
21139+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21140+ si_noflush_read_lock(sb);
21141+}
21142+
1facf9fc 21143+static inline int si_read_trylock(struct super_block *sb, int flags)
21144+{
21145+ if (au_ftest_lock(flags, FLUSH))
21146+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21147+ return si_noflush_read_trylock(sb);
21148+}
21149+
b752ccd1
AM
21150+static inline void si_read_unlock(struct super_block *sb)
21151+{
21152+ si_pid_clr(sb);
21153+ __si_read_unlock(sb);
21154+}
21155+
953406b4
AM
21156+static inline void si_write_lock(struct super_block *sb)
21157+{
21158+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21159+ si_noflush_write_lock(sb);
21160+}
21161+
b752ccd1 21162+#if 0 /* unused */
1facf9fc 21163+static inline int si_write_trylock(struct super_block *sb, int flags)
21164+{
21165+ if (au_ftest_lock(flags, FLUSH))
21166+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21167+ return si_noflush_write_trylock(sb);
21168+}
b752ccd1
AM
21169+#endif
21170+
21171+static inline void si_write_unlock(struct super_block *sb)
21172+{
21173+ si_pid_clr(sb);
21174+ __si_write_unlock(sb);
21175+}
21176+
21177+#if 0 /* unused */
21178+static inline void si_downgrade_lock(struct super_block *sb)
21179+{
21180+ __si_downgrade_lock(sb);
21181+}
21182+#endif
1facf9fc 21183+
21184+/* ---------------------------------------------------------------------- */
21185+
21186+static inline aufs_bindex_t au_sbend(struct super_block *sb)
21187+{
dece6358 21188+ SiMustAnyLock(sb);
1facf9fc 21189+ return au_sbi(sb)->si_bend;
21190+}
21191+
21192+static inline unsigned int au_mntflags(struct super_block *sb)
21193+{
dece6358 21194+ SiMustAnyLock(sb);
1facf9fc 21195+ return au_sbi(sb)->si_mntflags;
21196+}
21197+
21198+static inline unsigned int au_sigen(struct super_block *sb)
21199+{
dece6358 21200+ SiMustAnyLock(sb);
1facf9fc 21201+ return au_sbi(sb)->si_generation;
21202+}
21203+
21204+static inline struct au_branch *au_sbr(struct super_block *sb,
21205+ aufs_bindex_t bindex)
21206+{
dece6358 21207+ SiMustAnyLock(sb);
1facf9fc 21208+ return au_sbi(sb)->si_branch[0 + bindex];
21209+}
21210+
21211+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
21212+{
dece6358 21213+ SiMustWriteLock(sb);
1facf9fc 21214+ au_sbi(sb)->si_xino_brid = brid;
21215+}
21216+
21217+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
21218+{
dece6358 21219+ SiMustAnyLock(sb);
1facf9fc 21220+ return au_sbi(sb)->si_xino_brid;
21221+}
21222+
21223+#endif /* __KERNEL__ */
21224+#endif /* __AUFS_SUPER_H__ */
b752ccd1
AM
21225diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
21226--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
953406b4 21227+++ linux/fs/aufs/sysaufs.c 2010-10-21 09:52:43.093625591 +0200
4a4d8108 21228@@ -0,0 +1,107 @@
1facf9fc 21229+/*
4a4d8108 21230+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21231+ *
21232+ * This program, aufs is free software; you can redistribute it and/or modify
21233+ * it under the terms of the GNU General Public License as published by
21234+ * the Free Software Foundation; either version 2 of the License, or
21235+ * (at your option) any later version.
dece6358
AM
21236+ *
21237+ * This program is distributed in the hope that it will be useful,
21238+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21239+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21240+ * GNU General Public License for more details.
21241+ *
21242+ * You should have received a copy of the GNU General Public License
21243+ * along with this program; if not, write to the Free Software
21244+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21245+ */
21246+
21247+/*
21248+ * sysfs interface and lifetime management
21249+ * they are necessary regardless sysfs is disabled.
21250+ */
21251+
21252+#include <linux/fs.h>
21253+#include <linux/random.h>
21254+#include <linux/sysfs.h>
21255+#include "aufs.h"
21256+
21257+unsigned long sysaufs_si_mask;
953406b4 21258+struct kset *sysaufs_ket;
1facf9fc 21259+
21260+#define AuSiAttr(_name) { \
21261+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
21262+ .show = sysaufs_si_##_name, \
21263+}
21264+
21265+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
21266+struct attribute *sysaufs_si_attrs[] = {
21267+ &sysaufs_si_attr_xi_path.attr,
21268+ NULL,
21269+};
21270+
4a4d8108 21271+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 21272+ .show = sysaufs_si_show
21273+};
21274+
21275+static struct kobj_type au_sbi_ktype = {
21276+ .release = au_si_free,
21277+ .sysfs_ops = &au_sbi_ops,
21278+ .default_attrs = sysaufs_si_attrs
21279+};
21280+
21281+/* ---------------------------------------------------------------------- */
21282+
21283+int sysaufs_si_init(struct au_sbinfo *sbinfo)
21284+{
21285+ int err;
21286+
953406b4 21287+ sbinfo->si_kobj.kset = sysaufs_ket;
1facf9fc 21288+ /* cf. sysaufs_name() */
21289+ err = kobject_init_and_add
953406b4 21290+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->kobj*/NULL,
1facf9fc 21291+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
21292+
21293+ dbgaufs_si_null(sbinfo);
21294+ if (!err) {
21295+ err = dbgaufs_si_init(sbinfo);
21296+ if (unlikely(err))
21297+ kobject_put(&sbinfo->si_kobj);
21298+ }
21299+ return err;
21300+}
21301+
21302+void sysaufs_fin(void)
21303+{
21304+ dbgaufs_fin();
953406b4
AM
21305+ sysfs_remove_group(&sysaufs_ket->kobj, sysaufs_attr_group);
21306+ kset_unregister(sysaufs_ket);
1facf9fc 21307+}
21308+
21309+int __init sysaufs_init(void)
21310+{
21311+ int err;
21312+
21313+ do {
21314+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
21315+ } while (!sysaufs_si_mask);
21316+
4a4d8108 21317+ err = -EINVAL;
953406b4
AM
21318+ sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
21319+ if (unlikely(!sysaufs_ket))
4a4d8108 21320+ goto out;
953406b4
AM
21321+ err = PTR_ERR(sysaufs_ket);
21322+ if (IS_ERR(sysaufs_ket))
1facf9fc 21323+ goto out;
953406b4 21324+ err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
1facf9fc 21325+ if (unlikely(err)) {
953406b4 21326+ kset_unregister(sysaufs_ket);
1facf9fc 21327+ goto out;
21328+ }
21329+
21330+ err = dbgaufs_init();
21331+ if (unlikely(err))
21332+ sysaufs_fin();
4f0767ce 21333+out:
1facf9fc 21334+ return err;
21335+}
b752ccd1
AM
21336diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
21337--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
953406b4 21338+++ linux/fs/aufs/sysaufs.h 2010-10-21 09:52:43.093625591 +0200
4a4d8108 21339@@ -0,0 +1,105 @@
1facf9fc 21340+/*
4a4d8108 21341+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21342+ *
21343+ * This program, aufs is free software; you can redistribute it and/or modify
21344+ * it under the terms of the GNU General Public License as published by
21345+ * the Free Software Foundation; either version 2 of the License, or
21346+ * (at your option) any later version.
dece6358
AM
21347+ *
21348+ * This program is distributed in the hope that it will be useful,
21349+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21350+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21351+ * GNU General Public License for more details.
21352+ *
21353+ * You should have received a copy of the GNU General Public License
21354+ * along with this program; if not, write to the Free Software
21355+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21356+ */
21357+
21358+/*
21359+ * sysfs interface and mount lifetime management
21360+ */
21361+
21362+#ifndef __SYSAUFS_H__
21363+#define __SYSAUFS_H__
21364+
21365+#ifdef __KERNEL__
21366+
1facf9fc 21367+#include <linux/sysfs.h>
21368+#include <linux/aufs_type.h>
21369+#include "module.h"
21370+
dece6358
AM
21371+struct super_block;
21372+struct au_sbinfo;
21373+
1facf9fc 21374+struct sysaufs_si_attr {
21375+ struct attribute attr;
21376+ int (*show)(struct seq_file *seq, struct super_block *sb);
21377+};
21378+
21379+/* ---------------------------------------------------------------------- */
21380+
21381+/* sysaufs.c */
21382+extern unsigned long sysaufs_si_mask;
953406b4 21383+extern struct kset *sysaufs_ket;
1facf9fc 21384+extern struct attribute *sysaufs_si_attrs[];
21385+int sysaufs_si_init(struct au_sbinfo *sbinfo);
21386+int __init sysaufs_init(void);
21387+void sysaufs_fin(void);
21388+
21389+/* ---------------------------------------------------------------------- */
21390+
21391+/* some people doesn't like to show a pointer in kernel */
21392+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
21393+{
21394+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
21395+}
21396+
21397+#define SysaufsSiNamePrefix "si_"
21398+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
21399+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
21400+{
21401+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
21402+ sysaufs_si_id(sbinfo));
21403+}
21404+
21405+struct au_branch;
21406+#ifdef CONFIG_SYSFS
21407+/* sysfs.c */
21408+extern struct attribute_group *sysaufs_attr_group;
21409+
21410+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
21411+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
21412+ char *buf);
21413+
21414+void sysaufs_br_init(struct au_branch *br);
21415+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
21416+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
21417+
21418+#define sysaufs_brs_init() do {} while (0)
21419+
21420+#else
21421+#define sysaufs_attr_group NULL
21422+
4a4d8108 21423+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 21424+
21425+static inline
21426+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
21427+ char *buf)
21428+{
21429+ return 0;
21430+}
21431+
4a4d8108
AM
21432+AuStubVoid(sysaufs_br_init, struct au_branch *br)
21433+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
21434+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 21435+
21436+static inline void sysaufs_brs_init(void)
21437+{
21438+ sysaufs_brs = 0;
21439+}
21440+
21441+#endif /* CONFIG_SYSFS */
21442+
21443+#endif /* __KERNEL__ */
21444+#endif /* __SYSAUFS_H__ */
b752ccd1
AM
21445diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
21446--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
21447+++ linux/fs/aufs/sysfs.c 2010-10-21 09:52:43.093625591 +0200
21448@@ -0,0 +1,250 @@
1facf9fc 21449+/*
4a4d8108 21450+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21451+ *
21452+ * This program, aufs is free software; you can redistribute it and/or modify
21453+ * it under the terms of the GNU General Public License as published by
21454+ * the Free Software Foundation; either version 2 of the License, or
21455+ * (at your option) any later version.
dece6358
AM
21456+ *
21457+ * This program is distributed in the hope that it will be useful,
21458+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21459+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21460+ * GNU General Public License for more details.
21461+ *
21462+ * You should have received a copy of the GNU General Public License
21463+ * along with this program; if not, write to the Free Software
21464+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21465+ */
21466+
21467+/*
21468+ * sysfs interface
21469+ */
21470+
21471+#include <linux/fs.h>
dece6358 21472+#include <linux/module.h>
1facf9fc 21473+#include <linux/seq_file.h>
21474+#include <linux/sysfs.h>
21475+#include "aufs.h"
21476+
4a4d8108
AM
21477+#ifdef CONFIG_AUFS_FS_MODULE
21478+/* this entry violates the "one line per file" policy of sysfs */
21479+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
21480+ char *buf)
21481+{
21482+ ssize_t err;
21483+ static char *conf =
21484+/* this file is generated at compiling */
21485+#include "conf.str"
21486+ ;
21487+
21488+ err = snprintf(buf, PAGE_SIZE, conf);
21489+ if (unlikely(err >= PAGE_SIZE))
21490+ err = -EFBIG;
21491+ return err;
21492+}
21493+
21494+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
21495+#endif
21496+
1facf9fc 21497+static struct attribute *au_attr[] = {
4a4d8108
AM
21498+#ifdef CONFIG_AUFS_FS_MODULE
21499+ &au_config_attr.attr,
21500+#endif
1facf9fc 21501+ NULL, /* need to NULL terminate the list of attributes */
21502+};
21503+
21504+static struct attribute_group sysaufs_attr_group_body = {
21505+ .attrs = au_attr
21506+};
21507+
21508+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
21509+
21510+/* ---------------------------------------------------------------------- */
21511+
21512+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
21513+{
21514+ int err;
21515+
dece6358
AM
21516+ SiMustAnyLock(sb);
21517+
1facf9fc 21518+ err = 0;
21519+ if (au_opt_test(au_mntflags(sb), XINO)) {
21520+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
21521+ seq_putc(seq, '\n');
21522+ }
21523+ return err;
21524+}
21525+
21526+/*
21527+ * the lifetime of branch is independent from the entry under sysfs.
21528+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
21529+ * unlinked.
21530+ */
21531+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
21532+ aufs_bindex_t bindex)
21533+{
21534+ struct path path;
21535+ struct dentry *root;
21536+ struct au_branch *br;
21537+
21538+ AuDbg("b%d\n", bindex);
21539+
21540+ root = sb->s_root;
21541+ di_read_lock_parent(root, !AuLock_IR);
21542+ br = au_sbr(sb, bindex);
21543+ path.mnt = br->br_mnt;
21544+ path.dentry = au_h_dptr(root, bindex);
21545+ au_seq_path(seq, &path);
21546+ di_read_unlock(root, !AuLock_IR);
21547+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
21548+ return 0;
21549+}
21550+
21551+/* ---------------------------------------------------------------------- */
21552+
21553+static struct seq_file *au_seq(char *p, ssize_t len)
21554+{
21555+ struct seq_file *seq;
21556+
21557+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
21558+ if (seq) {
21559+ /* mutex_init(&seq.lock); */
21560+ seq->buf = p;
21561+ seq->size = len;
21562+ return seq; /* success */
21563+ }
21564+
21565+ seq = ERR_PTR(-ENOMEM);
21566+ return seq;
21567+}
21568+
21569+#define SysaufsBr_PREFIX "br"
21570+
21571+/* todo: file size may exceed PAGE_SIZE */
21572+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 21573+ char *buf)
1facf9fc 21574+{
21575+ ssize_t err;
21576+ long l;
21577+ aufs_bindex_t bend;
21578+ struct au_sbinfo *sbinfo;
21579+ struct super_block *sb;
21580+ struct seq_file *seq;
21581+ char *name;
21582+ struct attribute **cattr;
21583+
21584+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
21585+ sb = sbinfo->si_sb;
1308ab2a 21586+
21587+ /*
21588+ * prevent a race condition between sysfs and aufs.
21589+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
21590+ * prohibits maintaining the sysfs entries.
21591+ * hew we acquire read lock after sysfs_get_active_two().
21592+ * on the other hand, the remount process may maintain the sysfs/aufs
21593+ * entries after acquiring write lock.
21594+ * it can cause a deadlock.
21595+ * simply we gave up processing read here.
21596+ */
21597+ err = -EBUSY;
21598+ if (unlikely(!si_noflush_read_trylock(sb)))
21599+ goto out;
1facf9fc 21600+
21601+ seq = au_seq(buf, PAGE_SIZE);
21602+ err = PTR_ERR(seq);
21603+ if (IS_ERR(seq))
1308ab2a 21604+ goto out_unlock;
1facf9fc 21605+
21606+ name = (void *)attr->name;
21607+ cattr = sysaufs_si_attrs;
21608+ while (*cattr) {
21609+ if (!strcmp(name, (*cattr)->name)) {
21610+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
21611+ ->show(seq, sb);
21612+ goto out_seq;
21613+ }
21614+ cattr++;
21615+ }
21616+
21617+ bend = au_sbend(sb);
21618+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
21619+ name += sizeof(SysaufsBr_PREFIX) - 1;
21620+ err = strict_strtol(name, 10, &l);
21621+ if (!err) {
21622+ if (l <= bend)
21623+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
21624+ else
21625+ err = -ENOENT;
21626+ }
21627+ goto out_seq;
21628+ }
21629+ BUG();
21630+
4f0767ce 21631+out_seq:
1facf9fc 21632+ if (!err) {
21633+ err = seq->count;
21634+ /* sysfs limit */
21635+ if (unlikely(err == PAGE_SIZE))
21636+ err = -EFBIG;
21637+ }
21638+ kfree(seq);
4f0767ce 21639+out_unlock:
1facf9fc 21640+ si_read_unlock(sb);
4f0767ce 21641+out:
1facf9fc 21642+ return err;
21643+}
21644+
21645+/* ---------------------------------------------------------------------- */
21646+
21647+void sysaufs_br_init(struct au_branch *br)
21648+{
4a4d8108
AM
21649+ struct attribute *attr = &br->br_attr;
21650+
21651+ sysfs_attr_init(attr);
21652+ attr->name = br->br_name;
21653+ attr->mode = S_IRUGO;
1facf9fc 21654+}
21655+
21656+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
21657+{
21658+ struct au_branch *br;
21659+ struct kobject *kobj;
21660+ aufs_bindex_t bend;
21661+
21662+ dbgaufs_brs_del(sb, bindex);
21663+
21664+ if (!sysaufs_brs)
21665+ return;
21666+
21667+ kobj = &au_sbi(sb)->si_kobj;
21668+ bend = au_sbend(sb);
21669+ for (; bindex <= bend; bindex++) {
21670+ br = au_sbr(sb, bindex);
21671+ sysfs_remove_file(kobj, &br->br_attr);
21672+ }
21673+}
21674+
21675+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
21676+{
21677+ int err;
21678+ aufs_bindex_t bend;
21679+ struct kobject *kobj;
21680+ struct au_branch *br;
21681+
21682+ dbgaufs_brs_add(sb, bindex);
21683+
21684+ if (!sysaufs_brs)
21685+ return;
21686+
21687+ kobj = &au_sbi(sb)->si_kobj;
21688+ bend = au_sbend(sb);
21689+ for (; bindex <= bend; bindex++) {
21690+ br = au_sbr(sb, bindex);
21691+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
21692+ "%d", bindex);
21693+ err = sysfs_create_file(kobj, &br->br_attr);
21694+ if (unlikely(err))
4a4d8108
AM
21695+ pr_warning("failed %s under sysfs(%d)\n",
21696+ br->br_name, err);
1facf9fc 21697+ }
21698+}
b752ccd1
AM
21699diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
21700--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
953406b4 21701+++ linux/fs/aufs/sysrq.c 2010-10-21 09:52:43.093625591 +0200
4a4d8108 21702@@ -0,0 +1,119 @@
1facf9fc 21703+/*
4a4d8108 21704+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21705+ *
21706+ * This program, aufs is free software; you can redistribute it and/or modify
21707+ * it under the terms of the GNU General Public License as published by
21708+ * the Free Software Foundation; either version 2 of the License, or
21709+ * (at your option) any later version.
dece6358
AM
21710+ *
21711+ * This program is distributed in the hope that it will be useful,
21712+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21713+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21714+ * GNU General Public License for more details.
21715+ *
21716+ * You should have received a copy of the GNU General Public License
21717+ * along with this program; if not, write to the Free Software
21718+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21719+ */
21720+
21721+/*
21722+ * magic sysrq hanlder
21723+ */
21724+
21725+#include <linux/fs.h>
21726+#include <linux/module.h>
21727+#include <linux/moduleparam.h>
21728+/* #include <linux/sysrq.h> */
21729+#include "aufs.h"
21730+
21731+/* ---------------------------------------------------------------------- */
21732+
21733+static void sysrq_sb(struct super_block *sb)
21734+{
21735+ char *plevel;
21736+ struct au_sbinfo *sbinfo;
21737+ struct file *file;
21738+
21739+ plevel = au_plevel;
21740+ au_plevel = KERN_WARNING;
953406b4 21741+ au_debug(1);
1facf9fc 21742+
21743+ sbinfo = au_sbi(sb);
4a4d8108
AM
21744+ /* since we define pr_fmt, call printk directly */
21745+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
21746+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 21747+ au_dpri_sb(sb);
4a4d8108 21748+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 21749+ au_dpri_dentry(sb->s_root);
4a4d8108 21750+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 21751+ au_dpri_inode(sb->s_root->d_inode);
21752+#if 0
21753+ struct inode *i;
4a4d8108 21754+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
1facf9fc 21755+ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
21756+ if (list_empty(&i->i_dentry))
21757+ au_dpri_inode(i);
21758+#endif
4a4d8108
AM
21759+ printk(KERN_WARNING AUFS_NAME ": files\n");
21760+ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
21761+ umode_t mode;
21762+ mode = file->f_dentry->d_inode->i_mode;
21763+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 21764+ au_dpri_file(file);
4a4d8108 21765+ }
1facf9fc 21766+
21767+ au_plevel = plevel;
953406b4 21768+ au_debug(0);
1facf9fc 21769+}
21770+
21771+/* ---------------------------------------------------------------------- */
21772+
21773+/* module parameter */
21774+static char *aufs_sysrq_key = "a";
21775+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
21776+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
21777+
21778+static void au_sysrq(int key __maybe_unused,
21779+ struct tty_struct *tty __maybe_unused)
21780+{
953406b4 21781+ struct kobject *kobj;
1facf9fc 21782+ struct au_sbinfo *sbinfo;
21783+
953406b4
AM
21784+ /* spin_lock(&sysaufs_ket->list_lock); */
21785+ list_for_each_entry(kobj, &sysaufs_ket->list, entry) {
21786+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
1facf9fc 21787+ sysrq_sb(sbinfo->si_sb);
953406b4
AM
21788+ }
21789+ /* spin_unlock(&sysaufs_ket->list_lock); */
1facf9fc 21790+}
21791+
21792+static struct sysrq_key_op au_sysrq_op = {
21793+ .handler = au_sysrq,
21794+ .help_msg = "Aufs",
21795+ .action_msg = "Aufs",
21796+ .enable_mask = SYSRQ_ENABLE_DUMP
21797+};
21798+
21799+/* ---------------------------------------------------------------------- */
21800+
21801+int __init au_sysrq_init(void)
21802+{
21803+ int err;
21804+ char key;
21805+
21806+ err = -1;
21807+ key = *aufs_sysrq_key;
21808+ if ('a' <= key && key <= 'z')
21809+ err = register_sysrq_key(key, &au_sysrq_op);
21810+ if (unlikely(err))
4a4d8108 21811+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 21812+ return err;
21813+}
21814+
21815+void au_sysrq_fin(void)
21816+{
21817+ int err;
21818+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
21819+ if (unlikely(err))
4a4d8108 21820+ pr_err("err %d (ignored)\n", err);
1facf9fc 21821+}
b752ccd1
AM
21822diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
21823--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
953406b4 21824+++ linux/fs/aufs/vdir.c 2010-10-21 09:52:43.093625591 +0200
4a4d8108 21825@@ -0,0 +1,884 @@
1facf9fc 21826+/*
4a4d8108 21827+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21828+ *
21829+ * This program, aufs is free software; you can redistribute it and/or modify
21830+ * it under the terms of the GNU General Public License as published by
21831+ * the Free Software Foundation; either version 2 of the License, or
21832+ * (at your option) any later version.
dece6358
AM
21833+ *
21834+ * This program is distributed in the hope that it will be useful,
21835+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21836+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21837+ * GNU General Public License for more details.
21838+ *
21839+ * You should have received a copy of the GNU General Public License
21840+ * along with this program; if not, write to the Free Software
21841+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21842+ */
21843+
21844+/*
21845+ * virtual or vertical directory
21846+ */
21847+
dece6358 21848+#include <linux/hash.h>
1facf9fc 21849+#include "aufs.h"
21850+
dece6358 21851+static unsigned int calc_size(int nlen)
1facf9fc 21852+{
dece6358 21853+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 21854+}
21855+
21856+static int set_deblk_end(union au_vdir_deblk_p *p,
21857+ union au_vdir_deblk_p *deblk_end)
21858+{
21859+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
21860+ p->de->de_str.len = 0;
21861+ /* smp_mb(); */
21862+ return 0;
21863+ }
21864+ return -1; /* error */
21865+}
21866+
21867+/* returns true or false */
21868+static int is_deblk_end(union au_vdir_deblk_p *p,
21869+ union au_vdir_deblk_p *deblk_end)
21870+{
21871+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
21872+ return !p->de->de_str.len;
21873+ return 1;
21874+}
21875+
21876+static unsigned char *last_deblk(struct au_vdir *vdir)
21877+{
21878+ return vdir->vd_deblk[vdir->vd_nblk - 1];
21879+}
21880+
21881+/* ---------------------------------------------------------------------- */
21882+
1308ab2a 21883+/* estimate the apropriate size for name hash table */
21884+unsigned int au_rdhash_est(loff_t sz)
21885+{
21886+ unsigned int n;
21887+
21888+ n = UINT_MAX;
21889+ sz >>= 10;
21890+ if (sz < n)
21891+ n = sz;
21892+ if (sz < AUFS_RDHASH_DEF)
21893+ n = AUFS_RDHASH_DEF;
4a4d8108 21894+ /* pr_info("n %u\n", n); */
1308ab2a 21895+ return n;
21896+}
21897+
1facf9fc 21898+/*
21899+ * the allocated memory has to be freed by
dece6358 21900+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 21901+ */
dece6358 21902+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 21903+{
1facf9fc 21904+ struct hlist_head *head;
dece6358 21905+ unsigned int u;
1facf9fc 21906+
dece6358
AM
21907+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
21908+ if (head) {
21909+ nhash->nh_num = num_hash;
21910+ nhash->nh_head = head;
21911+ for (u = 0; u < num_hash; u++)
1facf9fc 21912+ INIT_HLIST_HEAD(head++);
dece6358 21913+ return 0; /* success */
1facf9fc 21914+ }
1facf9fc 21915+
dece6358 21916+ return -ENOMEM;
1facf9fc 21917+}
21918+
dece6358
AM
21919+static void nhash_count(struct hlist_head *head)
21920+{
21921+#if 0
21922+ unsigned long n;
21923+ struct hlist_node *pos;
21924+
21925+ n = 0;
21926+ hlist_for_each(pos, head)
21927+ n++;
4a4d8108 21928+ pr_info("%lu\n", n);
dece6358
AM
21929+#endif
21930+}
21931+
21932+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 21933+{
1facf9fc 21934+ struct au_vdir_wh *tpos;
21935+ struct hlist_node *pos, *node;
21936+
dece6358
AM
21937+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
21938+ /* hlist_del(pos); */
21939+ kfree(tpos);
1facf9fc 21940+ }
21941+}
21942+
dece6358 21943+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 21944+{
dece6358
AM
21945+ struct au_vdir_dehstr *tpos;
21946+ struct hlist_node *pos, *node;
1facf9fc 21947+
dece6358
AM
21948+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
21949+ /* hlist_del(pos); */
4a4d8108 21950+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 21951+ }
1facf9fc 21952+}
21953+
dece6358
AM
21954+static void au_nhash_do_free(struct au_nhash *nhash,
21955+ void (*free)(struct hlist_head *head))
1facf9fc 21956+{
1308ab2a 21957+ unsigned int n;
1facf9fc 21958+ struct hlist_head *head;
1facf9fc 21959+
dece6358 21960+ n = nhash->nh_num;
1308ab2a 21961+ if (!n)
21962+ return;
21963+
dece6358 21964+ head = nhash->nh_head;
1308ab2a 21965+ while (n-- > 0) {
dece6358
AM
21966+ nhash_count(head);
21967+ free(head++);
1facf9fc 21968+ }
dece6358 21969+ kfree(nhash->nh_head);
1facf9fc 21970+}
21971+
dece6358 21972+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 21973+{
dece6358
AM
21974+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
21975+}
1facf9fc 21976+
dece6358
AM
21977+static void au_nhash_de_free(struct au_nhash *delist)
21978+{
21979+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 21980+}
21981+
21982+/* ---------------------------------------------------------------------- */
21983+
21984+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
21985+ int limit)
21986+{
21987+ int num;
21988+ unsigned int u, n;
21989+ struct hlist_head *head;
21990+ struct au_vdir_wh *tpos;
21991+ struct hlist_node *pos;
21992+
21993+ num = 0;
21994+ n = whlist->nh_num;
21995+ head = whlist->nh_head;
1308ab2a 21996+ for (u = 0; u < n; u++, head++)
1facf9fc 21997+ hlist_for_each_entry(tpos, pos, head, wh_hash)
21998+ if (tpos->wh_bindex == btgt && ++num > limit)
21999+ return 1;
1facf9fc 22000+ return 0;
22001+}
22002+
22003+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 22004+ unsigned char *name,
1facf9fc 22005+ unsigned int len)
22006+{
dece6358
AM
22007+ unsigned int v;
22008+ /* const unsigned int magic_bit = 12; */
22009+
1308ab2a 22010+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
22011+
dece6358
AM
22012+ v = 0;
22013+ while (len--)
22014+ v += *name++;
22015+ /* v = hash_long(v, magic_bit); */
22016+ v %= nhash->nh_num;
22017+ return nhash->nh_head + v;
22018+}
22019+
22020+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
22021+ int nlen)
22022+{
22023+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 22024+}
22025+
22026+/* returns found or not */
dece6358 22027+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 22028+{
22029+ struct hlist_head *head;
22030+ struct au_vdir_wh *tpos;
22031+ struct hlist_node *pos;
22032+ struct au_vdir_destr *str;
22033+
dece6358 22034+ head = au_name_hash(whlist, name, nlen);
1facf9fc 22035+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
22036+ str = &tpos->wh_str;
22037+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
22038+ if (au_nhash_test_name(str, name, nlen))
22039+ return 1;
22040+ }
22041+ return 0;
22042+}
22043+
22044+/* returns found(true) or not */
22045+static int test_known(struct au_nhash *delist, char *name, int nlen)
22046+{
22047+ struct hlist_head *head;
22048+ struct au_vdir_dehstr *tpos;
22049+ struct hlist_node *pos;
22050+ struct au_vdir_destr *str;
22051+
22052+ head = au_name_hash(delist, name, nlen);
22053+ hlist_for_each_entry(tpos, pos, head, hash) {
22054+ str = tpos->str;
22055+ AuDbg("%.*s\n", str->len, str->name);
22056+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 22057+ return 1;
22058+ }
22059+ return 0;
22060+}
22061+
dece6358
AM
22062+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
22063+ unsigned char d_type)
22064+{
22065+#ifdef CONFIG_AUFS_SHWH
22066+ wh->wh_ino = ino;
22067+ wh->wh_type = d_type;
22068+#endif
22069+}
22070+
22071+/* ---------------------------------------------------------------------- */
22072+
22073+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
22074+ unsigned int d_type, aufs_bindex_t bindex,
22075+ unsigned char shwh)
1facf9fc 22076+{
22077+ int err;
22078+ struct au_vdir_destr *str;
22079+ struct au_vdir_wh *wh;
22080+
dece6358 22081+ AuDbg("%.*s\n", nlen, name);
1308ab2a 22082+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
22083+
1facf9fc 22084+ err = -ENOMEM;
dece6358 22085+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 22086+ if (unlikely(!wh))
22087+ goto out;
22088+
22089+ err = 0;
22090+ wh->wh_bindex = bindex;
dece6358
AM
22091+ if (shwh)
22092+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 22093+ str = &wh->wh_str;
dece6358
AM
22094+ str->len = nlen;
22095+ memcpy(str->name, name, nlen);
22096+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 22097+ /* smp_mb(); */
22098+
4f0767ce 22099+out:
1facf9fc 22100+ return err;
22101+}
22102+
1facf9fc 22103+static int append_deblk(struct au_vdir *vdir)
22104+{
22105+ int err;
dece6358 22106+ unsigned long ul;
1facf9fc 22107+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
22108+ union au_vdir_deblk_p p, deblk_end;
22109+ unsigned char **o;
22110+
22111+ err = -ENOMEM;
dece6358
AM
22112+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
22113+ GFP_NOFS);
1facf9fc 22114+ if (unlikely(!o))
22115+ goto out;
22116+
22117+ vdir->vd_deblk = o;
22118+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
22119+ if (p.deblk) {
22120+ ul = vdir->vd_nblk++;
22121+ vdir->vd_deblk[ul] = p.deblk;
22122+ vdir->vd_last.ul = ul;
22123+ vdir->vd_last.p.deblk = p.deblk;
22124+ deblk_end.deblk = p.deblk + deblk_sz;
22125+ err = set_deblk_end(&p, &deblk_end);
22126+ }
22127+
4f0767ce 22128+out:
1facf9fc 22129+ return err;
22130+}
22131+
dece6358
AM
22132+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
22133+ unsigned int d_type, struct au_nhash *delist)
22134+{
22135+ int err;
22136+ unsigned int sz;
22137+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
22138+ union au_vdir_deblk_p p, *room, deblk_end;
22139+ struct au_vdir_dehstr *dehstr;
22140+
22141+ p.deblk = last_deblk(vdir);
22142+ deblk_end.deblk = p.deblk + deblk_sz;
22143+ room = &vdir->vd_last.p;
22144+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
22145+ || !is_deblk_end(room, &deblk_end));
22146+
22147+ sz = calc_size(nlen);
22148+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
22149+ err = append_deblk(vdir);
22150+ if (unlikely(err))
22151+ goto out;
22152+
22153+ p.deblk = last_deblk(vdir);
22154+ deblk_end.deblk = p.deblk + deblk_sz;
22155+ /* smp_mb(); */
22156+ AuDebugOn(room->deblk != p.deblk);
22157+ }
22158+
22159+ err = -ENOMEM;
4a4d8108 22160+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
22161+ if (unlikely(!dehstr))
22162+ goto out;
22163+
22164+ dehstr->str = &room->de->de_str;
22165+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
22166+ room->de->de_ino = ino;
22167+ room->de->de_type = d_type;
22168+ room->de->de_str.len = nlen;
22169+ memcpy(room->de->de_str.name, name, nlen);
22170+
22171+ err = 0;
22172+ room->deblk += sz;
22173+ if (unlikely(set_deblk_end(room, &deblk_end)))
22174+ err = append_deblk(vdir);
22175+ /* smp_mb(); */
22176+
4f0767ce 22177+out:
dece6358
AM
22178+ return err;
22179+}
22180+
22181+/* ---------------------------------------------------------------------- */
22182+
22183+void au_vdir_free(struct au_vdir *vdir)
22184+{
22185+ unsigned char **deblk;
22186+
22187+ deblk = vdir->vd_deblk;
22188+ while (vdir->vd_nblk--)
22189+ kfree(*deblk++);
22190+ kfree(vdir->vd_deblk);
22191+ au_cache_free_vdir(vdir);
22192+}
22193+
1308ab2a 22194+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 22195+{
22196+ struct au_vdir *vdir;
1308ab2a 22197+ struct super_block *sb;
1facf9fc 22198+ int err;
22199+
1308ab2a 22200+ sb = file->f_dentry->d_sb;
dece6358
AM
22201+ SiMustAnyLock(sb);
22202+
1facf9fc 22203+ err = -ENOMEM;
22204+ vdir = au_cache_alloc_vdir();
22205+ if (unlikely(!vdir))
22206+ goto out;
22207+
22208+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
22209+ if (unlikely(!vdir->vd_deblk))
22210+ goto out_free;
22211+
22212+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 22213+ if (!vdir->vd_deblk_sz) {
22214+ /* estimate the apropriate size for deblk */
22215+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 22216+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 22217+ }
1facf9fc 22218+ vdir->vd_nblk = 0;
22219+ vdir->vd_version = 0;
22220+ vdir->vd_jiffy = 0;
22221+ err = append_deblk(vdir);
22222+ if (!err)
22223+ return vdir; /* success */
22224+
22225+ kfree(vdir->vd_deblk);
22226+
4f0767ce 22227+out_free:
1facf9fc 22228+ au_cache_free_vdir(vdir);
4f0767ce 22229+out:
1facf9fc 22230+ vdir = ERR_PTR(err);
22231+ return vdir;
22232+}
22233+
22234+static int reinit_vdir(struct au_vdir *vdir)
22235+{
22236+ int err;
22237+ union au_vdir_deblk_p p, deblk_end;
22238+
22239+ while (vdir->vd_nblk > 1) {
22240+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
22241+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
22242+ vdir->vd_nblk--;
22243+ }
22244+ p.deblk = vdir->vd_deblk[0];
22245+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
22246+ err = set_deblk_end(&p, &deblk_end);
22247+ /* keep vd_dblk_sz */
22248+ vdir->vd_last.ul = 0;
22249+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
22250+ vdir->vd_version = 0;
22251+ vdir->vd_jiffy = 0;
22252+ /* smp_mb(); */
22253+ return err;
22254+}
22255+
22256+/* ---------------------------------------------------------------------- */
22257+
1facf9fc 22258+#define AuFillVdir_CALLED 1
22259+#define AuFillVdir_WHABLE (1 << 1)
dece6358 22260+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 22261+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
22262+#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
22263+#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
22264+
dece6358
AM
22265+#ifndef CONFIG_AUFS_SHWH
22266+#undef AuFillVdir_SHWH
22267+#define AuFillVdir_SHWH 0
22268+#endif
22269+
1facf9fc 22270+struct fillvdir_arg {
22271+ struct file *file;
22272+ struct au_vdir *vdir;
dece6358
AM
22273+ struct au_nhash delist;
22274+ struct au_nhash whlist;
1facf9fc 22275+ aufs_bindex_t bindex;
22276+ unsigned int flags;
22277+ int err;
22278+};
22279+
dece6358 22280+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 22281+ loff_t offset __maybe_unused, u64 h_ino,
22282+ unsigned int d_type)
22283+{
22284+ struct fillvdir_arg *arg = __arg;
22285+ char *name = (void *)__name;
22286+ struct super_block *sb;
1facf9fc 22287+ ino_t ino;
dece6358 22288+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 22289+
1facf9fc 22290+ arg->err = 0;
dece6358 22291+ sb = arg->file->f_dentry->d_sb;
1facf9fc 22292+ au_fset_fillvdir(arg->flags, CALLED);
22293+ /* smp_mb(); */
dece6358 22294+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 22295+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
22296+ if (test_known(&arg->delist, name, nlen)
22297+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
22298+ goto out; /* already exists or whiteouted */
1facf9fc 22299+
22300+ sb = arg->file->f_dentry->d_sb;
dece6358 22301+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
22302+ if (!arg->err) {
22303+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
22304+ d_type = DT_UNKNOWN;
dece6358
AM
22305+ arg->err = append_de(arg->vdir, name, nlen, ino,
22306+ d_type, &arg->delist);
4a4d8108 22307+ }
1facf9fc 22308+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
22309+ name += AUFS_WH_PFX_LEN;
dece6358
AM
22310+ nlen -= AUFS_WH_PFX_LEN;
22311+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
22312+ goto out; /* already whiteouted */
1facf9fc 22313+
dece6358
AM
22314+ if (shwh)
22315+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
22316+ &ino);
4a4d8108
AM
22317+ if (!arg->err) {
22318+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
22319+ d_type = DT_UNKNOWN;
1facf9fc 22320+ arg->err = au_nhash_append_wh
dece6358
AM
22321+ (&arg->whlist, name, nlen, ino, d_type,
22322+ arg->bindex, shwh);
4a4d8108 22323+ }
1facf9fc 22324+ }
22325+
4f0767ce 22326+out:
1facf9fc 22327+ if (!arg->err)
22328+ arg->vdir->vd_jiffy = jiffies;
22329+ /* smp_mb(); */
22330+ AuTraceErr(arg->err);
22331+ return arg->err;
22332+}
22333+
dece6358
AM
22334+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
22335+ struct au_nhash *whlist, struct au_nhash *delist)
22336+{
22337+#ifdef CONFIG_AUFS_SHWH
22338+ int err;
22339+ unsigned int nh, u;
22340+ struct hlist_head *head;
22341+ struct au_vdir_wh *tpos;
22342+ struct hlist_node *pos, *n;
22343+ char *p, *o;
22344+ struct au_vdir_destr *destr;
22345+
22346+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
22347+
22348+ err = -ENOMEM;
4a4d8108 22349+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
22350+ if (unlikely(!p))
22351+ goto out;
22352+
22353+ err = 0;
22354+ nh = whlist->nh_num;
22355+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
22356+ p += AUFS_WH_PFX_LEN;
22357+ for (u = 0; u < nh; u++) {
22358+ head = whlist->nh_head + u;
22359+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
22360+ destr = &tpos->wh_str;
22361+ memcpy(p, destr->name, destr->len);
22362+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
22363+ tpos->wh_ino, tpos->wh_type, delist);
22364+ if (unlikely(err))
22365+ break;
22366+ }
22367+ }
22368+
22369+ __putname(o);
22370+
4f0767ce 22371+out:
dece6358
AM
22372+ AuTraceErr(err);
22373+ return err;
22374+#else
22375+ return 0;
22376+#endif
22377+}
22378+
1facf9fc 22379+static int au_do_read_vdir(struct fillvdir_arg *arg)
22380+{
22381+ int err;
dece6358 22382+ unsigned int rdhash;
1facf9fc 22383+ loff_t offset;
dece6358
AM
22384+ aufs_bindex_t bend, bindex, bstart;
22385+ unsigned char shwh;
1facf9fc 22386+ struct file *hf, *file;
22387+ struct super_block *sb;
22388+
1facf9fc 22389+ file = arg->file;
22390+ sb = file->f_dentry->d_sb;
dece6358
AM
22391+ SiMustAnyLock(sb);
22392+
22393+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 22394+ if (!rdhash)
22395+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
22396+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
22397+ if (unlikely(err))
1facf9fc 22398+ goto out;
dece6358
AM
22399+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
22400+ if (unlikely(err))
1facf9fc 22401+ goto out_delist;
22402+
22403+ err = 0;
22404+ arg->flags = 0;
dece6358
AM
22405+ shwh = 0;
22406+ if (au_opt_test(au_mntflags(sb), SHWH)) {
22407+ shwh = 1;
22408+ au_fset_fillvdir(arg->flags, SHWH);
22409+ }
22410+ bstart = au_fbstart(file);
4a4d8108 22411+ bend = au_fbend_dir(file);
dece6358 22412+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 22413+ hf = au_hf_dir(file, bindex);
1facf9fc 22414+ if (!hf)
22415+ continue;
22416+
22417+ offset = vfsub_llseek(hf, 0, SEEK_SET);
22418+ err = offset;
22419+ if (unlikely(offset))
22420+ break;
22421+
22422+ arg->bindex = bindex;
22423+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
22424+ if (shwh
22425+ || (bindex != bend
22426+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 22427+ au_fset_fillvdir(arg->flags, WHABLE);
22428+ do {
22429+ arg->err = 0;
22430+ au_fclr_fillvdir(arg->flags, CALLED);
22431+ /* smp_mb(); */
22432+ err = vfsub_readdir(hf, fillvdir, arg);
22433+ if (err >= 0)
22434+ err = arg->err;
22435+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
22436+ }
dece6358
AM
22437+
22438+ if (!err && shwh)
22439+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
22440+
22441+ au_nhash_wh_free(&arg->whlist);
1facf9fc 22442+
4f0767ce 22443+out_delist:
dece6358 22444+ au_nhash_de_free(&arg->delist);
4f0767ce 22445+out:
1facf9fc 22446+ return err;
22447+}
22448+
22449+static int read_vdir(struct file *file, int may_read)
22450+{
22451+ int err;
22452+ unsigned long expire;
22453+ unsigned char do_read;
22454+ struct fillvdir_arg arg;
22455+ struct inode *inode;
22456+ struct au_vdir *vdir, *allocated;
22457+
22458+ err = 0;
22459+ inode = file->f_dentry->d_inode;
22460+ IMustLock(inode);
dece6358
AM
22461+ SiMustAnyLock(inode->i_sb);
22462+
1facf9fc 22463+ allocated = NULL;
22464+ do_read = 0;
22465+ expire = au_sbi(inode->i_sb)->si_rdcache;
22466+ vdir = au_ivdir(inode);
22467+ if (!vdir) {
22468+ do_read = 1;
1308ab2a 22469+ vdir = alloc_vdir(file);
1facf9fc 22470+ err = PTR_ERR(vdir);
22471+ if (IS_ERR(vdir))
22472+ goto out;
22473+ err = 0;
22474+ allocated = vdir;
22475+ } else if (may_read
22476+ && (inode->i_version != vdir->vd_version
22477+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
22478+ do_read = 1;
22479+ err = reinit_vdir(vdir);
22480+ if (unlikely(err))
22481+ goto out;
22482+ }
22483+
22484+ if (!do_read)
22485+ return 0; /* success */
22486+
22487+ arg.file = file;
22488+ arg.vdir = vdir;
22489+ err = au_do_read_vdir(&arg);
22490+ if (!err) {
22491+ /* file->f_pos = 0; */
22492+ vdir->vd_version = inode->i_version;
22493+ vdir->vd_last.ul = 0;
22494+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
22495+ if (allocated)
22496+ au_set_ivdir(inode, allocated);
22497+ } else if (allocated)
22498+ au_vdir_free(allocated);
22499+
4f0767ce 22500+out:
1facf9fc 22501+ return err;
22502+}
22503+
22504+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
22505+{
22506+ int err, rerr;
22507+ unsigned long ul, n;
22508+ const unsigned int deblk_sz = src->vd_deblk_sz;
22509+
22510+ AuDebugOn(tgt->vd_nblk != 1);
22511+
22512+ err = -ENOMEM;
22513+ if (tgt->vd_nblk < src->vd_nblk) {
22514+ unsigned char **p;
22515+
dece6358
AM
22516+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
22517+ GFP_NOFS);
1facf9fc 22518+ if (unlikely(!p))
22519+ goto out;
22520+ tgt->vd_deblk = p;
22521+ }
22522+
1308ab2a 22523+ if (tgt->vd_deblk_sz != deblk_sz) {
22524+ unsigned char *p;
22525+
22526+ tgt->vd_deblk_sz = deblk_sz;
22527+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
22528+ if (unlikely(!p))
22529+ goto out;
22530+ tgt->vd_deblk[0] = p;
22531+ }
1facf9fc 22532+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 22533+ tgt->vd_version = src->vd_version;
22534+ tgt->vd_jiffy = src->vd_jiffy;
22535+
22536+ n = src->vd_nblk;
22537+ for (ul = 1; ul < n; ul++) {
dece6358
AM
22538+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
22539+ GFP_NOFS);
22540+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 22541+ goto out;
1308ab2a 22542+ tgt->vd_nblk++;
1facf9fc 22543+ }
1308ab2a 22544+ tgt->vd_nblk = n;
22545+ tgt->vd_last.ul = tgt->vd_last.ul;
22546+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
22547+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
22548+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 22549+ /* smp_mb(); */
22550+ return 0; /* success */
22551+
4f0767ce 22552+out:
1facf9fc 22553+ rerr = reinit_vdir(tgt);
22554+ BUG_ON(rerr);
22555+ return err;
22556+}
22557+
22558+int au_vdir_init(struct file *file)
22559+{
22560+ int err;
22561+ struct inode *inode;
22562+ struct au_vdir *vdir_cache, *allocated;
22563+
22564+ err = read_vdir(file, !file->f_pos);
22565+ if (unlikely(err))
22566+ goto out;
22567+
22568+ allocated = NULL;
22569+ vdir_cache = au_fvdir_cache(file);
22570+ if (!vdir_cache) {
1308ab2a 22571+ vdir_cache = alloc_vdir(file);
1facf9fc 22572+ err = PTR_ERR(vdir_cache);
22573+ if (IS_ERR(vdir_cache))
22574+ goto out;
22575+ allocated = vdir_cache;
22576+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
22577+ err = reinit_vdir(vdir_cache);
22578+ if (unlikely(err))
22579+ goto out;
22580+ } else
22581+ return 0; /* success */
22582+
22583+ inode = file->f_dentry->d_inode;
22584+ err = copy_vdir(vdir_cache, au_ivdir(inode));
22585+ if (!err) {
22586+ file->f_version = inode->i_version;
22587+ if (allocated)
22588+ au_set_fvdir_cache(file, allocated);
22589+ } else if (allocated)
22590+ au_vdir_free(allocated);
22591+
4f0767ce 22592+out:
1facf9fc 22593+ return err;
22594+}
22595+
22596+static loff_t calc_offset(struct au_vdir *vdir)
22597+{
22598+ loff_t offset;
22599+ union au_vdir_deblk_p p;
22600+
22601+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
22602+ offset = vdir->vd_last.p.deblk - p.deblk;
22603+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
22604+ return offset;
22605+}
22606+
22607+/* returns true or false */
22608+static int seek_vdir(struct file *file)
22609+{
22610+ int valid;
22611+ unsigned int deblk_sz;
22612+ unsigned long ul, n;
22613+ loff_t offset;
22614+ union au_vdir_deblk_p p, deblk_end;
22615+ struct au_vdir *vdir_cache;
22616+
22617+ valid = 1;
22618+ vdir_cache = au_fvdir_cache(file);
22619+ offset = calc_offset(vdir_cache);
22620+ AuDbg("offset %lld\n", offset);
22621+ if (file->f_pos == offset)
22622+ goto out;
22623+
22624+ vdir_cache->vd_last.ul = 0;
22625+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
22626+ if (!file->f_pos)
22627+ goto out;
22628+
22629+ valid = 0;
22630+ deblk_sz = vdir_cache->vd_deblk_sz;
22631+ ul = div64_u64(file->f_pos, deblk_sz);
22632+ AuDbg("ul %lu\n", ul);
22633+ if (ul >= vdir_cache->vd_nblk)
22634+ goto out;
22635+
22636+ n = vdir_cache->vd_nblk;
22637+ for (; ul < n; ul++) {
22638+ p.deblk = vdir_cache->vd_deblk[ul];
22639+ deblk_end.deblk = p.deblk + deblk_sz;
22640+ offset = ul;
22641+ offset *= deblk_sz;
22642+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
22643+ unsigned int l;
22644+
22645+ l = calc_size(p.de->de_str.len);
22646+ offset += l;
22647+ p.deblk += l;
22648+ }
22649+ if (!is_deblk_end(&p, &deblk_end)) {
22650+ valid = 1;
22651+ vdir_cache->vd_last.ul = ul;
22652+ vdir_cache->vd_last.p = p;
22653+ break;
22654+ }
22655+ }
22656+
4f0767ce 22657+out:
1facf9fc 22658+ /* smp_mb(); */
22659+ AuTraceErr(!valid);
22660+ return valid;
22661+}
22662+
22663+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
22664+{
22665+ int err;
22666+ unsigned int l, deblk_sz;
22667+ union au_vdir_deblk_p deblk_end;
22668+ struct au_vdir *vdir_cache;
22669+ struct au_vdir_de *de;
22670+
22671+ vdir_cache = au_fvdir_cache(file);
22672+ if (!seek_vdir(file))
22673+ return 0;
22674+
22675+ deblk_sz = vdir_cache->vd_deblk_sz;
22676+ while (1) {
22677+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
22678+ deblk_end.deblk += deblk_sz;
22679+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
22680+ de = vdir_cache->vd_last.p.de;
22681+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
22682+ de->de_str.len, de->de_str.name, file->f_pos,
22683+ (unsigned long)de->de_ino, de->de_type);
22684+ err = filldir(dirent, de->de_str.name, de->de_str.len,
22685+ file->f_pos, de->de_ino, de->de_type);
22686+ if (unlikely(err)) {
22687+ AuTraceErr(err);
22688+ /* todo: ignore the error caused by udba? */
22689+ /* return err; */
22690+ return 0;
22691+ }
22692+
22693+ l = calc_size(de->de_str.len);
22694+ vdir_cache->vd_last.p.deblk += l;
22695+ file->f_pos += l;
22696+ }
22697+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
22698+ vdir_cache->vd_last.ul++;
22699+ vdir_cache->vd_last.p.deblk
22700+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
22701+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
22702+ continue;
22703+ }
22704+ break;
22705+ }
22706+
22707+ /* smp_mb(); */
22708+ return 0;
22709+}
b752ccd1
AM
22710diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
22711--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
953406b4 22712+++ linux/fs/aufs/vfsub.c 2010-10-21 09:52:43.093625591 +0200
b752ccd1 22713@@ -0,0 +1,786 @@
1facf9fc 22714+/*
4a4d8108 22715+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22716+ *
22717+ * This program, aufs is free software; you can redistribute it and/or modify
22718+ * it under the terms of the GNU General Public License as published by
22719+ * the Free Software Foundation; either version 2 of the License, or
22720+ * (at your option) any later version.
dece6358
AM
22721+ *
22722+ * This program is distributed in the hope that it will be useful,
22723+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22724+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22725+ * GNU General Public License for more details.
22726+ *
22727+ * You should have received a copy of the GNU General Public License
22728+ * along with this program; if not, write to the Free Software
22729+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22730+ */
22731+
22732+/*
22733+ * sub-routines for VFS
22734+ */
22735+
4a4d8108 22736+#include <linux/file.h>
1308ab2a 22737+#include <linux/ima.h>
dece6358
AM
22738+#include <linux/namei.h>
22739+#include <linux/security.h>
22740+#include <linux/splice.h>
1facf9fc 22741+#include <linux/uaccess.h>
22742+#include "aufs.h"
22743+
22744+int vfsub_update_h_iattr(struct path *h_path, int *did)
22745+{
22746+ int err;
22747+ struct kstat st;
22748+ struct super_block *h_sb;
22749+
22750+ /* for remote fs, leave work for its getattr or d_revalidate */
22751+ /* for bad i_attr fs, handle them in aufs_getattr() */
22752+ /* still some fs may acquire i_mutex. we need to skip them */
22753+ err = 0;
22754+ if (!did)
22755+ did = &err;
22756+ h_sb = h_path->dentry->d_sb;
22757+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
22758+ if (*did)
22759+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
22760+
22761+ return err;
22762+}
22763+
22764+/* ---------------------------------------------------------------------- */
22765+
4a4d8108
AM
22766+static int au_conv_oflags(int flags)
22767+{
22768+ int mask = 0;
22769+
22770+#ifdef CONFIG_IMA
22771+ fmode_t fmode;
22772+
22773+ /* mask = MAY_OPEN; */
22774+ fmode = OPEN_FMODE(flags);
22775+ if (fmode & FMODE_READ)
22776+ mask |= MAY_READ;
22777+ if ((fmode & FMODE_WRITE)
22778+ || (flags & O_TRUNC))
22779+ mask |= MAY_WRITE;
22780+ /*
22781+ * if (flags & O_APPEND)
22782+ * mask |= MAY_APPEND;
22783+ */
22784+ if (flags & vfsub_fmode_to_uint(FMODE_EXEC))
22785+ mask |= MAY_EXEC;
22786+
22787+ AuDbg("flags 0x%x, mask 0x%x\n", flags, mask);
22788+#endif
22789+
22790+ return mask;
22791+}
22792+
22793+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 22794+{
22795+ struct file *file;
4a4d8108 22796+ int err;
1308ab2a 22797+
4a4d8108
AM
22798+ path_get(path);
22799+ file = dentry_open(path->dentry, path->mnt, flags, current_cred());
1308ab2a 22800+ if (IS_ERR(file))
4a4d8108
AM
22801+ goto out;
22802+
22803+ err = ima_file_check(file, au_conv_oflags(flags));
22804+ if (unlikely(err)) {
22805+ fput(file);
22806+ file = ERR_PTR(err);
22807+ }
22808+out:
1308ab2a 22809+ return file;
22810+}
22811+
1facf9fc 22812+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
22813+{
22814+ struct file *file;
22815+
1facf9fc 22816+ file = filp_open(path, oflags, mode);
1facf9fc 22817+ if (IS_ERR(file))
22818+ goto out;
22819+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
22820+
4f0767ce 22821+out:
1facf9fc 22822+ return file;
22823+}
22824+
22825+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
22826+{
22827+ int err;
22828+
1facf9fc 22829+ err = kern_path(name, flags, path);
1facf9fc 22830+ if (!err && path->dentry->d_inode)
22831+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
22832+ return err;
22833+}
22834+
22835+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
22836+ int len)
22837+{
22838+ struct path path = {
22839+ .mnt = NULL
22840+ };
22841+
1308ab2a 22842+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 22843+ IMustLock(parent->d_inode);
22844+
22845+ path.dentry = lookup_one_len(name, parent, len);
22846+ if (IS_ERR(path.dentry))
22847+ goto out;
22848+ if (path.dentry->d_inode)
22849+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
22850+
4f0767ce 22851+out:
4a4d8108 22852+ AuTraceErrPtr(path.dentry);
1facf9fc 22853+ return path.dentry;
22854+}
22855+
22856+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
22857+{
22858+ struct path path = {
22859+ .mnt = nd->path.mnt
22860+ };
22861+
22862+ IMustLock(nd->path.dentry->d_inode);
22863+
22864+ path.dentry = lookup_hash(nd);
4a4d8108
AM
22865+ if (IS_ERR(path.dentry))
22866+ goto out;
22867+ if (path.dentry->d_inode)
1facf9fc 22868+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
22869+
4f0767ce 22870+out:
4a4d8108 22871+ AuTraceErrPtr(path.dentry);
1facf9fc 22872+ return path.dentry;
22873+}
22874+
22875+/* ---------------------------------------------------------------------- */
22876+
22877+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
22878+ struct dentry *d2, struct au_hinode *hdir2)
22879+{
22880+ struct dentry *d;
22881+
1facf9fc 22882+ d = lock_rename(d1, d2);
4a4d8108 22883+ au_hn_suspend(hdir1);
1facf9fc 22884+ if (hdir1 != hdir2)
4a4d8108 22885+ au_hn_suspend(hdir2);
1facf9fc 22886+
22887+ return d;
22888+}
22889+
22890+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
22891+ struct dentry *d2, struct au_hinode *hdir2)
22892+{
4a4d8108 22893+ au_hn_resume(hdir1);
1facf9fc 22894+ if (hdir1 != hdir2)
4a4d8108 22895+ au_hn_resume(hdir2);
1facf9fc 22896+ unlock_rename(d1, d2);
1facf9fc 22897+}
22898+
22899+/* ---------------------------------------------------------------------- */
22900+
22901+int vfsub_create(struct inode *dir, struct path *path, int mode)
22902+{
22903+ int err;
22904+ struct dentry *d;
22905+
22906+ IMustLock(dir);
22907+
22908+ d = path->dentry;
22909+ path->dentry = d->d_parent;
b752ccd1 22910+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 22911+ path->dentry = d;
22912+ if (unlikely(err))
22913+ goto out;
22914+
22915+ if (au_test_fs_null_nd(dir->i_sb))
22916+ err = vfs_create(dir, path->dentry, mode, NULL);
22917+ else {
22918+ struct nameidata h_nd;
22919+
22920+ memset(&h_nd, 0, sizeof(h_nd));
22921+ h_nd.flags = LOOKUP_CREATE;
22922+ h_nd.intent.open.flags = O_CREAT
22923+ | vfsub_fmode_to_uint(FMODE_READ);
22924+ h_nd.intent.open.create_mode = mode;
22925+ h_nd.path.dentry = path->dentry->d_parent;
22926+ h_nd.path.mnt = path->mnt;
22927+ path_get(&h_nd.path);
22928+ err = vfs_create(dir, path->dentry, mode, &h_nd);
22929+ path_put(&h_nd.path);
22930+ }
22931+
22932+ if (!err) {
22933+ struct path tmp = *path;
22934+ int did;
22935+
22936+ vfsub_update_h_iattr(&tmp, &did);
22937+ if (did) {
22938+ tmp.dentry = path->dentry->d_parent;
22939+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
22940+ }
22941+ /*ignore*/
22942+ }
22943+
4f0767ce 22944+out:
1facf9fc 22945+ return err;
22946+}
22947+
22948+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
22949+{
22950+ int err;
22951+ struct dentry *d;
22952+
22953+ IMustLock(dir);
22954+
22955+ d = path->dentry;
22956+ path->dentry = d->d_parent;
b752ccd1 22957+ err = security_path_symlink(path, d, symname);
1facf9fc 22958+ path->dentry = d;
22959+ if (unlikely(err))
22960+ goto out;
22961+
22962+ err = vfs_symlink(dir, path->dentry, symname);
22963+ if (!err) {
22964+ struct path tmp = *path;
22965+ int did;
22966+
22967+ vfsub_update_h_iattr(&tmp, &did);
22968+ if (did) {
22969+ tmp.dentry = path->dentry->d_parent;
22970+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
22971+ }
22972+ /*ignore*/
22973+ }
22974+
4f0767ce 22975+out:
1facf9fc 22976+ return err;
22977+}
22978+
22979+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
22980+{
22981+ int err;
22982+ struct dentry *d;
22983+
22984+ IMustLock(dir);
22985+
22986+ d = path->dentry;
22987+ path->dentry = d->d_parent;
b752ccd1 22988+ err = security_path_mknod(path, d, mode, dev);
1facf9fc 22989+ path->dentry = d;
22990+ if (unlikely(err))
22991+ goto out;
22992+
22993+ err = vfs_mknod(dir, path->dentry, mode, dev);
22994+ if (!err) {
22995+ struct path tmp = *path;
22996+ int did;
22997+
22998+ vfsub_update_h_iattr(&tmp, &did);
22999+ if (did) {
23000+ tmp.dentry = path->dentry->d_parent;
23001+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23002+ }
23003+ /*ignore*/
23004+ }
23005+
4f0767ce 23006+out:
1facf9fc 23007+ return err;
23008+}
23009+
23010+static int au_test_nlink(struct inode *inode)
23011+{
23012+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
23013+
23014+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
23015+ || inode->i_nlink < link_max)
23016+ return 0;
23017+ return -EMLINK;
23018+}
23019+
23020+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
23021+{
23022+ int err;
23023+ struct dentry *d;
23024+
23025+ IMustLock(dir);
23026+
23027+ err = au_test_nlink(src_dentry->d_inode);
23028+ if (unlikely(err))
23029+ return err;
23030+
23031+ d = path->dentry;
23032+ path->dentry = d->d_parent;
b752ccd1 23033+ err = security_path_link(src_dentry, path, d);
1facf9fc 23034+ path->dentry = d;
23035+ if (unlikely(err))
23036+ goto out;
23037+
1facf9fc 23038+ err = vfs_link(src_dentry, dir, path->dentry);
1facf9fc 23039+ if (!err) {
23040+ struct path tmp = *path;
23041+ int did;
23042+
23043+ /* fuse has different memory inode for the same inumber */
23044+ vfsub_update_h_iattr(&tmp, &did);
23045+ if (did) {
23046+ tmp.dentry = path->dentry->d_parent;
23047+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23048+ tmp.dentry = src_dentry;
23049+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23050+ }
23051+ /*ignore*/
23052+ }
23053+
4f0767ce 23054+out:
1facf9fc 23055+ return err;
23056+}
23057+
23058+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
23059+ struct inode *dir, struct path *path)
23060+{
23061+ int err;
23062+ struct path tmp = {
23063+ .mnt = path->mnt
23064+ };
23065+ struct dentry *d;
23066+
23067+ IMustLock(dir);
23068+ IMustLock(src_dir);
23069+
23070+ d = path->dentry;
23071+ path->dentry = d->d_parent;
23072+ tmp.dentry = src_dentry->d_parent;
b752ccd1 23073+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 23074+ path->dentry = d;
23075+ if (unlikely(err))
23076+ goto out;
23077+
1facf9fc 23078+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
1facf9fc 23079+ if (!err) {
23080+ int did;
23081+
23082+ tmp.dentry = d->d_parent;
23083+ vfsub_update_h_iattr(&tmp, &did);
23084+ if (did) {
23085+ tmp.dentry = src_dentry;
23086+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23087+ tmp.dentry = src_dentry->d_parent;
23088+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23089+ }
23090+ /*ignore*/
23091+ }
23092+
4f0767ce 23093+out:
1facf9fc 23094+ return err;
23095+}
23096+
23097+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
23098+{
23099+ int err;
23100+ struct dentry *d;
23101+
23102+ IMustLock(dir);
23103+
23104+ d = path->dentry;
23105+ path->dentry = d->d_parent;
b752ccd1 23106+ err = security_path_mkdir(path, d, mode);
1facf9fc 23107+ path->dentry = d;
23108+ if (unlikely(err))
23109+ goto out;
23110+
23111+ err = vfs_mkdir(dir, path->dentry, mode);
23112+ if (!err) {
23113+ struct path tmp = *path;
23114+ int did;
23115+
23116+ vfsub_update_h_iattr(&tmp, &did);
23117+ if (did) {
23118+ tmp.dentry = path->dentry->d_parent;
23119+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23120+ }
23121+ /*ignore*/
23122+ }
23123+
4f0767ce 23124+out:
1facf9fc 23125+ return err;
23126+}
23127+
23128+int vfsub_rmdir(struct inode *dir, struct path *path)
23129+{
23130+ int err;
23131+ struct dentry *d;
23132+
23133+ IMustLock(dir);
23134+
23135+ d = path->dentry;
23136+ path->dentry = d->d_parent;
b752ccd1 23137+ err = security_path_rmdir(path, d);
1facf9fc 23138+ path->dentry = d;
23139+ if (unlikely(err))
23140+ goto out;
23141+
1facf9fc 23142+ err = vfs_rmdir(dir, path->dentry);
1facf9fc 23143+ if (!err) {
23144+ struct path tmp = {
23145+ .dentry = path->dentry->d_parent,
23146+ .mnt = path->mnt
23147+ };
23148+
23149+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
23150+ }
23151+
4f0767ce 23152+out:
1facf9fc 23153+ return err;
23154+}
23155+
23156+/* ---------------------------------------------------------------------- */
23157+
23158+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
23159+ loff_t *ppos)
23160+{
23161+ ssize_t err;
23162+
23163+ err = vfs_read(file, ubuf, count, ppos);
23164+ if (err >= 0)
23165+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23166+ return err;
23167+}
23168+
23169+/* todo: kernel_read()? */
23170+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
23171+ loff_t *ppos)
23172+{
23173+ ssize_t err;
23174+ mm_segment_t oldfs;
b752ccd1
AM
23175+ union {
23176+ void *k;
23177+ char __user *u;
23178+ } buf;
1facf9fc 23179+
b752ccd1 23180+ buf.k = kbuf;
1facf9fc 23181+ oldfs = get_fs();
23182+ set_fs(KERNEL_DS);
b752ccd1 23183+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 23184+ set_fs(oldfs);
23185+ return err;
23186+}
23187+
23188+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
23189+ loff_t *ppos)
23190+{
23191+ ssize_t err;
23192+
1facf9fc 23193+ err = vfs_write(file, ubuf, count, ppos);
1facf9fc 23194+ if (err >= 0)
23195+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23196+ return err;
23197+}
23198+
23199+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
23200+{
23201+ ssize_t err;
23202+ mm_segment_t oldfs;
b752ccd1
AM
23203+ union {
23204+ void *k;
23205+ const char __user *u;
23206+ } buf;
1facf9fc 23207+
b752ccd1 23208+ buf.k = kbuf;
1facf9fc 23209+ oldfs = get_fs();
23210+ set_fs(KERNEL_DS);
b752ccd1 23211+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 23212+ set_fs(oldfs);
23213+ return err;
23214+}
23215+
4a4d8108
AM
23216+int vfsub_flush(struct file *file, fl_owner_t id)
23217+{
23218+ int err;
23219+
23220+ err = 0;
23221+ if (file->f_op && file->f_op->flush) {
23222+ err = file->f_op->flush(file, id);
23223+ if (!err)
23224+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
23225+ /*ignore*/
23226+ }
23227+ return err;
23228+}
23229+
1facf9fc 23230+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
23231+{
23232+ int err;
23233+
1facf9fc 23234+ err = vfs_readdir(file, filldir, arg);
1facf9fc 23235+ if (err >= 0)
23236+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23237+ return err;
23238+}
23239+
23240+long vfsub_splice_to(struct file *in, loff_t *ppos,
23241+ struct pipe_inode_info *pipe, size_t len,
23242+ unsigned int flags)
23243+{
23244+ long err;
23245+
0fc653ad 23246+ err = do_splice_to(in, ppos, pipe, len, flags);
4a4d8108 23247+ file_accessed(in);
1facf9fc 23248+ if (err >= 0)
23249+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
23250+ return err;
23251+}
23252+
23253+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
23254+ loff_t *ppos, size_t len, unsigned int flags)
23255+{
23256+ long err;
23257+
0fc653ad 23258+ err = do_splice_from(pipe, out, ppos, len, flags);
1facf9fc 23259+ if (err >= 0)
23260+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
23261+ return err;
23262+}
23263+
23264+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
23265+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
23266+ struct file *h_file)
23267+{
23268+ int err;
23269+ struct inode *h_inode;
23270+
23271+ h_inode = h_path->dentry->d_inode;
23272+ if (!h_file) {
23273+ err = mnt_want_write(h_path->mnt);
23274+ if (err)
23275+ goto out;
23276+ err = inode_permission(h_inode, MAY_WRITE);
23277+ if (err)
23278+ goto out_mnt;
23279+ err = get_write_access(h_inode);
23280+ if (err)
23281+ goto out_mnt;
4a4d8108 23282+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 23283+ if (err)
23284+ goto out_inode;
23285+ }
23286+
23287+ err = locks_verify_truncate(h_inode, h_file, length);
23288+ if (!err)
953406b4 23289+ err = security_path_truncate(h_path);
b752ccd1 23290+ if (!err)
1facf9fc 23291+ err = do_truncate(h_path->dentry, length, attr, h_file);
1facf9fc 23292+
4f0767ce 23293+out_inode:
1facf9fc 23294+ if (!h_file)
23295+ put_write_access(h_inode);
4f0767ce 23296+out_mnt:
1facf9fc 23297+ if (!h_file)
23298+ mnt_drop_write(h_path->mnt);
4f0767ce 23299+out:
1facf9fc 23300+ return err;
23301+}
23302+
23303+/* ---------------------------------------------------------------------- */
23304+
23305+struct au_vfsub_mkdir_args {
23306+ int *errp;
23307+ struct inode *dir;
23308+ struct path *path;
23309+ int mode;
23310+};
23311+
23312+static void au_call_vfsub_mkdir(void *args)
23313+{
23314+ struct au_vfsub_mkdir_args *a = args;
23315+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
23316+}
23317+
23318+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
23319+{
23320+ int err, do_sio, wkq_err;
23321+
23322+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
23323+ if (!do_sio)
23324+ err = vfsub_mkdir(dir, path, mode);
23325+ else {
23326+ struct au_vfsub_mkdir_args args = {
23327+ .errp = &err,
23328+ .dir = dir,
23329+ .path = path,
23330+ .mode = mode
23331+ };
23332+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
23333+ if (unlikely(wkq_err))
23334+ err = wkq_err;
23335+ }
23336+
23337+ return err;
23338+}
23339+
23340+struct au_vfsub_rmdir_args {
23341+ int *errp;
23342+ struct inode *dir;
23343+ struct path *path;
23344+};
23345+
23346+static void au_call_vfsub_rmdir(void *args)
23347+{
23348+ struct au_vfsub_rmdir_args *a = args;
23349+ *a->errp = vfsub_rmdir(a->dir, a->path);
23350+}
23351+
23352+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
23353+{
23354+ int err, do_sio, wkq_err;
23355+
23356+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
23357+ if (!do_sio)
23358+ err = vfsub_rmdir(dir, path);
23359+ else {
23360+ struct au_vfsub_rmdir_args args = {
23361+ .errp = &err,
23362+ .dir = dir,
23363+ .path = path
23364+ };
23365+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
23366+ if (unlikely(wkq_err))
23367+ err = wkq_err;
23368+ }
23369+
23370+ return err;
23371+}
23372+
23373+/* ---------------------------------------------------------------------- */
23374+
23375+struct notify_change_args {
23376+ int *errp;
23377+ struct path *path;
23378+ struct iattr *ia;
23379+};
23380+
23381+static void call_notify_change(void *args)
23382+{
23383+ struct notify_change_args *a = args;
23384+ struct inode *h_inode;
23385+
23386+ h_inode = a->path->dentry->d_inode;
23387+ IMustLock(h_inode);
23388+
23389+ *a->errp = -EPERM;
23390+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 23391+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 23392+ if (!*a->errp)
23393+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
23394+ }
23395+ AuTraceErr(*a->errp);
23396+}
23397+
23398+int vfsub_notify_change(struct path *path, struct iattr *ia)
23399+{
23400+ int err;
23401+ struct notify_change_args args = {
23402+ .errp = &err,
23403+ .path = path,
23404+ .ia = ia
23405+ };
23406+
23407+ call_notify_change(&args);
23408+
23409+ return err;
23410+}
23411+
23412+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
23413+{
23414+ int err, wkq_err;
23415+ struct notify_change_args args = {
23416+ .errp = &err,
23417+ .path = path,
23418+ .ia = ia
23419+ };
23420+
23421+ wkq_err = au_wkq_wait(call_notify_change, &args);
23422+ if (unlikely(wkq_err))
23423+ err = wkq_err;
23424+
23425+ return err;
23426+}
23427+
23428+/* ---------------------------------------------------------------------- */
23429+
23430+struct unlink_args {
23431+ int *errp;
23432+ struct inode *dir;
23433+ struct path *path;
23434+};
23435+
23436+static void call_unlink(void *args)
23437+{
23438+ struct unlink_args *a = args;
23439+ struct dentry *d = a->path->dentry;
23440+ struct inode *h_inode;
23441+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
23442+ && atomic_read(&d->d_count) == 1);
23443+
23444+ IMustLock(a->dir);
23445+
23446+ a->path->dentry = d->d_parent;
23447+ *a->errp = security_path_unlink(a->path, d);
23448+ a->path->dentry = d;
23449+ if (unlikely(*a->errp))
23450+ return;
23451+
23452+ if (!stop_sillyrename)
23453+ dget(d);
23454+ h_inode = d->d_inode;
23455+ if (h_inode)
23456+ atomic_inc(&h_inode->i_count);
23457+
1facf9fc 23458+ *a->errp = vfs_unlink(a->dir, d);
1facf9fc 23459+ if (!*a->errp) {
23460+ struct path tmp = {
23461+ .dentry = d->d_parent,
23462+ .mnt = a->path->mnt
23463+ };
23464+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
23465+ }
23466+
23467+ if (!stop_sillyrename)
23468+ dput(d);
23469+ if (h_inode)
23470+ iput(h_inode);
23471+
23472+ AuTraceErr(*a->errp);
23473+}
23474+
23475+/*
23476+ * @dir: must be locked.
23477+ * @dentry: target dentry.
23478+ */
23479+int vfsub_unlink(struct inode *dir, struct path *path, int force)
23480+{
23481+ int err;
23482+ struct unlink_args args = {
23483+ .errp = &err,
23484+ .dir = dir,
23485+ .path = path
23486+ };
23487+
23488+ if (!force)
23489+ call_unlink(&args);
23490+ else {
23491+ int wkq_err;
23492+
23493+ wkq_err = au_wkq_wait(call_unlink, &args);
23494+ if (unlikely(wkq_err))
23495+ err = wkq_err;
23496+ }
23497+
23498+ return err;
23499+}
b752ccd1
AM
23500diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
23501--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
953406b4 23502+++ linux/fs/aufs/vfsub.h 2010-10-21 09:52:43.093625591 +0200
b752ccd1 23503@@ -0,0 +1,174 @@
1facf9fc 23504+/*
4a4d8108 23505+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 23506+ *
23507+ * This program, aufs is free software; you can redistribute it and/or modify
23508+ * it under the terms of the GNU General Public License as published by
23509+ * the Free Software Foundation; either version 2 of the License, or
23510+ * (at your option) any later version.
dece6358
AM
23511+ *
23512+ * This program is distributed in the hope that it will be useful,
23513+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23514+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23515+ * GNU General Public License for more details.
23516+ *
23517+ * You should have received a copy of the GNU General Public License
23518+ * along with this program; if not, write to the Free Software
23519+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23520+ */
23521+
23522+/*
23523+ * sub-routines for VFS
23524+ */
23525+
23526+#ifndef __AUFS_VFSUB_H__
23527+#define __AUFS_VFSUB_H__
23528+
23529+#ifdef __KERNEL__
23530+
23531+#include <linux/fs.h>
1facf9fc 23532+
23533+/* ---------------------------------------------------------------------- */
23534+
23535+/* lock subclass for lower inode */
23536+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
23537+/* reduce? gave up. */
23538+enum {
23539+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
23540+ AuLsc_I_PARENT, /* lower inode, parent first */
23541+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 23542+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 23543+ AuLsc_I_CHILD,
23544+ AuLsc_I_CHILD2,
23545+ AuLsc_I_End
23546+};
23547+
23548+/* to debug easier, do not make them inlined functions */
23549+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
23550+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
23551+
23552+/* ---------------------------------------------------------------------- */
23553+
1facf9fc 23554+int vfsub_update_h_iattr(struct path *h_path, int *did);
4a4d8108 23555+struct file *vfsub_dentry_open(struct path *path, int flags);
1facf9fc 23556+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
23557+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
23558+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
23559+ int len);
23560+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
23561+
23562+/* ---------------------------------------------------------------------- */
23563+
23564+struct au_hinode;
23565+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
23566+ struct dentry *d2, struct au_hinode *hdir2);
23567+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
23568+ struct dentry *d2, struct au_hinode *hdir2);
23569+
23570+int vfsub_create(struct inode *dir, struct path *path, int mode);
23571+int vfsub_symlink(struct inode *dir, struct path *path,
23572+ const char *symname);
23573+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
23574+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
23575+ struct path *path);
23576+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
23577+ struct inode *hdir, struct path *path);
23578+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
23579+int vfsub_rmdir(struct inode *dir, struct path *path);
23580+
23581+/* ---------------------------------------------------------------------- */
23582+
23583+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
23584+ loff_t *ppos);
23585+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
23586+ loff_t *ppos);
23587+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
23588+ loff_t *ppos);
23589+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
23590+ loff_t *ppos);
4a4d8108 23591+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 23592+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
23593+
4a4d8108
AM
23594+static inline unsigned int vfsub_file_flags(struct file *file)
23595+{
23596+ unsigned int flags;
23597+
23598+ spin_lock(&file->f_lock);
23599+ flags = file->f_flags;
23600+ spin_unlock(&file->f_lock);
23601+
23602+ return flags;
23603+}
1308ab2a 23604+
1facf9fc 23605+static inline void vfsub_file_accessed(struct file *h_file)
23606+{
23607+ file_accessed(h_file);
23608+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
23609+}
23610+
23611+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
23612+ struct dentry *h_dentry)
23613+{
23614+ struct path h_path = {
23615+ .dentry = h_dentry,
23616+ .mnt = h_mnt
23617+ };
23618+ touch_atime(h_mnt, h_dentry);
23619+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
23620+}
23621+
4a4d8108
AM
23622+long vfsub_splice_to(struct file *in, loff_t *ppos,
23623+ struct pipe_inode_info *pipe, size_t len,
23624+ unsigned int flags);
23625+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
23626+ loff_t *ppos, size_t len, unsigned int flags);
23627+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
23628+ struct file *h_file);
23629+
1facf9fc 23630+/* ---------------------------------------------------------------------- */
23631+
23632+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
23633+{
23634+ loff_t err;
23635+
1facf9fc 23636+ err = vfs_llseek(file, offset, origin);
1facf9fc 23637+ return err;
23638+}
23639+
23640+/* ---------------------------------------------------------------------- */
23641+
23642+/* dirty workaround for strict type of fmode_t */
23643+union vfsub_fmu {
23644+ fmode_t fm;
23645+ unsigned int ui;
23646+};
23647+
23648+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
23649+{
23650+ union vfsub_fmu u = {
23651+ .fm = fm
23652+ };
23653+
23654+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
23655+
23656+ return u.ui;
23657+}
23658+
23659+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
23660+{
23661+ union vfsub_fmu u = {
23662+ .ui = ui
23663+ };
23664+
23665+ return u.fm;
23666+}
23667+
4a4d8108
AM
23668+/* ---------------------------------------------------------------------- */
23669+
23670+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
23671+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
23672+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
23673+int vfsub_notify_change(struct path *path, struct iattr *ia);
23674+int vfsub_unlink(struct inode *dir, struct path *path, int force);
23675+
1facf9fc 23676+#endif /* __KERNEL__ */
23677+#endif /* __AUFS_VFSUB_H__ */
b752ccd1
AM
23678diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
23679--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
23680+++ linux/fs/aufs/wbr_policy.c 2010-10-21 09:52:43.096959416 +0200
23681@@ -0,0 +1,699 @@
1facf9fc 23682+/*
4a4d8108 23683+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 23684+ *
23685+ * This program, aufs is free software; you can redistribute it and/or modify
23686+ * it under the terms of the GNU General Public License as published by
23687+ * the Free Software Foundation; either version 2 of the License, or
23688+ * (at your option) any later version.
dece6358
AM
23689+ *
23690+ * This program is distributed in the hope that it will be useful,
23691+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23692+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23693+ * GNU General Public License for more details.
23694+ *
23695+ * You should have received a copy of the GNU General Public License
23696+ * along with this program; if not, write to the Free Software
23697+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23698+ */
23699+
23700+/*
23701+ * policies for selecting one among multiple writable branches
23702+ */
23703+
23704+#include <linux/statfs.h>
23705+#include "aufs.h"
23706+
23707+/* subset of cpup_attr() */
23708+static noinline_for_stack
23709+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
23710+{
23711+ int err, sbits;
23712+ struct iattr ia;
23713+ struct inode *h_isrc;
23714+
23715+ h_isrc = h_src->d_inode;
23716+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
23717+ ia.ia_mode = h_isrc->i_mode;
23718+ ia.ia_uid = h_isrc->i_uid;
23719+ ia.ia_gid = h_isrc->i_gid;
23720+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
23721+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
23722+ err = vfsub_sio_notify_change(h_path, &ia);
23723+
23724+ /* is this nfs only? */
23725+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
23726+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
23727+ ia.ia_mode = h_isrc->i_mode;
23728+ err = vfsub_sio_notify_change(h_path, &ia);
23729+ }
23730+
23731+ return err;
23732+}
23733+
23734+#define AuCpdown_PARENT_OPQ 1
23735+#define AuCpdown_WHED (1 << 1)
23736+#define AuCpdown_MADE_DIR (1 << 2)
23737+#define AuCpdown_DIROPQ (1 << 3)
23738+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
23739+#define au_fset_cpdown(flags, name) { (flags) |= AuCpdown_##name; }
23740+#define au_fclr_cpdown(flags, name) { (flags) &= ~AuCpdown_##name; }
23741+
23742+struct au_cpdown_dir_args {
23743+ struct dentry *parent;
23744+ unsigned int flags;
23745+};
23746+
23747+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
23748+ struct au_cpdown_dir_args *a)
23749+{
23750+ int err;
23751+ struct dentry *opq_dentry;
23752+
23753+ opq_dentry = au_diropq_create(dentry, bdst);
23754+ err = PTR_ERR(opq_dentry);
23755+ if (IS_ERR(opq_dentry))
23756+ goto out;
23757+ dput(opq_dentry);
23758+ au_fset_cpdown(a->flags, DIROPQ);
23759+
4f0767ce 23760+out:
1facf9fc 23761+ return err;
23762+}
23763+
23764+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
23765+ struct inode *dir, aufs_bindex_t bdst)
23766+{
23767+ int err;
23768+ struct path h_path;
23769+ struct au_branch *br;
23770+
23771+ br = au_sbr(dentry->d_sb, bdst);
23772+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
23773+ err = PTR_ERR(h_path.dentry);
23774+ if (IS_ERR(h_path.dentry))
23775+ goto out;
23776+
23777+ err = 0;
23778+ if (h_path.dentry->d_inode) {
23779+ h_path.mnt = br->br_mnt;
23780+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
23781+ dentry);
23782+ }
23783+ dput(h_path.dentry);
23784+
4f0767ce 23785+out:
1facf9fc 23786+ return err;
23787+}
23788+
23789+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
23790+ struct dentry *h_parent, void *arg)
23791+{
23792+ int err, rerr;
4a4d8108 23793+ aufs_bindex_t bopq, bstart;
1facf9fc 23794+ struct path h_path;
23795+ struct dentry *parent;
23796+ struct inode *h_dir, *h_inode, *inode, *dir;
23797+ struct au_cpdown_dir_args *args = arg;
23798+
23799+ bstart = au_dbstart(dentry);
23800+ /* dentry is di-locked */
23801+ parent = dget_parent(dentry);
23802+ dir = parent->d_inode;
23803+ h_dir = h_parent->d_inode;
23804+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
23805+ IMustLock(h_dir);
23806+
23807+ err = au_lkup_neg(dentry, bdst);
23808+ if (unlikely(err < 0))
23809+ goto out;
23810+ h_path.dentry = au_h_dptr(dentry, bdst);
23811+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
23812+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
23813+ S_IRWXU | S_IRUGO | S_IXUGO);
23814+ if (unlikely(err))
23815+ goto out_put;
23816+ au_fset_cpdown(args->flags, MADE_DIR);
23817+
1facf9fc 23818+ bopq = au_dbdiropq(dentry);
23819+ au_fclr_cpdown(args->flags, WHED);
23820+ au_fclr_cpdown(args->flags, DIROPQ);
23821+ if (au_dbwh(dentry) == bdst)
23822+ au_fset_cpdown(args->flags, WHED);
23823+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
23824+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 23825+ h_inode = h_path.dentry->d_inode;
23826+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
23827+ if (au_ftest_cpdown(args->flags, WHED)) {
23828+ err = au_cpdown_dir_opq(dentry, bdst, args);
23829+ if (unlikely(err)) {
23830+ mutex_unlock(&h_inode->i_mutex);
23831+ goto out_dir;
23832+ }
23833+ }
23834+
23835+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
23836+ mutex_unlock(&h_inode->i_mutex);
23837+ if (unlikely(err))
23838+ goto out_opq;
23839+
23840+ if (au_ftest_cpdown(args->flags, WHED)) {
23841+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
23842+ if (unlikely(err))
23843+ goto out_opq;
23844+ }
23845+
23846+ inode = dentry->d_inode;
23847+ if (au_ibend(inode) < bdst)
23848+ au_set_ibend(inode, bdst);
23849+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
23850+ au_hi_flags(inode, /*isdir*/1));
23851+ goto out; /* success */
23852+
23853+ /* revert */
4f0767ce 23854+out_opq:
1facf9fc 23855+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
23856+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
23857+ rerr = au_diropq_remove(dentry, bdst);
23858+ mutex_unlock(&h_inode->i_mutex);
23859+ if (unlikely(rerr)) {
23860+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
23861+ AuDLNPair(dentry), bdst, rerr);
23862+ err = -EIO;
23863+ goto out;
23864+ }
23865+ }
4f0767ce 23866+out_dir:
1facf9fc 23867+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
23868+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
23869+ if (unlikely(rerr)) {
23870+ AuIOErr("failed removing %.*s b%d (%d)\n",
23871+ AuDLNPair(dentry), bdst, rerr);
23872+ err = -EIO;
23873+ }
23874+ }
4f0767ce 23875+out_put:
1facf9fc 23876+ au_set_h_dptr(dentry, bdst, NULL);
23877+ if (au_dbend(dentry) == bdst)
23878+ au_update_dbend(dentry);
4f0767ce 23879+out:
1facf9fc 23880+ dput(parent);
23881+ return err;
23882+}
23883+
23884+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
23885+{
23886+ int err;
23887+ struct au_cpdown_dir_args args = {
23888+ .parent = dget_parent(dentry),
23889+ .flags = 0
23890+ };
23891+
23892+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
23893+ dput(args.parent);
23894+
23895+ return err;
23896+}
23897+
23898+/* ---------------------------------------------------------------------- */
23899+
23900+/* policies for create */
23901+
4a4d8108
AM
23902+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
23903+{
23904+ int err, i, j, ndentry;
23905+ aufs_bindex_t bopq;
23906+ struct au_dcsub_pages dpages;
23907+ struct au_dpage *dpage;
23908+ struct dentry **dentries, *parent, *d;
23909+
23910+ err = au_dpages_init(&dpages, GFP_NOFS);
23911+ if (unlikely(err))
23912+ goto out;
23913+ parent = dget_parent(dentry);
23914+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/0, /*test*/NULL,
23915+ /*arg*/NULL);
23916+ if (unlikely(err))
23917+ goto out_free;
23918+
23919+ err = bindex;
23920+ for (i = 0; i < dpages.ndpage; i++) {
23921+ dpage = dpages.dpages + i;
23922+ dentries = dpage->dentries;
23923+ ndentry = dpage->ndentry;
23924+ for (j = 0; j < ndentry; j++) {
23925+ d = dentries[j];
23926+ di_read_lock_parent2(d, !AuLock_IR);
23927+ bopq = au_dbdiropq(d);
23928+ di_read_unlock(d, !AuLock_IR);
23929+ if (bopq >= 0 && bopq < err)
23930+ err = bopq;
23931+ }
23932+ }
23933+
23934+out_free:
23935+ dput(parent);
23936+ au_dpages_free(&dpages);
23937+out:
23938+ return err;
23939+}
23940+
1facf9fc 23941+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
23942+{
23943+ for (; bindex >= 0; bindex--)
23944+ if (!au_br_rdonly(au_sbr(sb, bindex)))
23945+ return bindex;
23946+ return -EROFS;
23947+}
23948+
23949+/* top down parent */
23950+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
23951+{
23952+ int err;
23953+ aufs_bindex_t bstart, bindex;
23954+ struct super_block *sb;
23955+ struct dentry *parent, *h_parent;
23956+
23957+ sb = dentry->d_sb;
23958+ bstart = au_dbstart(dentry);
23959+ err = bstart;
23960+ if (!au_br_rdonly(au_sbr(sb, bstart)))
23961+ goto out;
23962+
23963+ err = -EROFS;
23964+ parent = dget_parent(dentry);
23965+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
23966+ h_parent = au_h_dptr(parent, bindex);
23967+ if (!h_parent || !h_parent->d_inode)
23968+ continue;
23969+
23970+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
23971+ err = bindex;
23972+ break;
23973+ }
23974+ }
23975+ dput(parent);
23976+
23977+ /* bottom up here */
4a4d8108 23978+ if (unlikely(err < 0)) {
1facf9fc 23979+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
23980+ if (err >= 0)
23981+ err = au_wbr_nonopq(dentry, err);
23982+ }
1facf9fc 23983+
4f0767ce 23984+out:
1facf9fc 23985+ AuDbg("b%d\n", err);
23986+ return err;
23987+}
23988+
23989+/* ---------------------------------------------------------------------- */
23990+
23991+/* an exception for the policy other than tdp */
23992+static int au_wbr_create_exp(struct dentry *dentry)
23993+{
23994+ int err;
23995+ aufs_bindex_t bwh, bdiropq;
23996+ struct dentry *parent;
23997+
23998+ err = -1;
23999+ bwh = au_dbwh(dentry);
24000+ parent = dget_parent(dentry);
24001+ bdiropq = au_dbdiropq(parent);
24002+ if (bwh >= 0) {
24003+ if (bdiropq >= 0)
24004+ err = min(bdiropq, bwh);
24005+ else
24006+ err = bwh;
24007+ AuDbg("%d\n", err);
24008+ } else if (bdiropq >= 0) {
24009+ err = bdiropq;
24010+ AuDbg("%d\n", err);
24011+ }
24012+ dput(parent);
24013+
4a4d8108
AM
24014+ if (err >= 0)
24015+ err = au_wbr_nonopq(dentry, err);
24016+
1facf9fc 24017+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
24018+ err = -1;
24019+
24020+ AuDbg("%d\n", err);
24021+ return err;
24022+}
24023+
24024+/* ---------------------------------------------------------------------- */
24025+
24026+/* round robin */
24027+static int au_wbr_create_init_rr(struct super_block *sb)
24028+{
24029+ int err;
24030+
24031+ err = au_wbr_bu(sb, au_sbend(sb));
24032+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 24033+ /* smp_mb(); */
1facf9fc 24034+
24035+ AuDbg("b%d\n", err);
24036+ return err;
24037+}
24038+
24039+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
24040+{
24041+ int err, nbr;
24042+ unsigned int u;
24043+ aufs_bindex_t bindex, bend;
24044+ struct super_block *sb;
24045+ atomic_t *next;
24046+
24047+ err = au_wbr_create_exp(dentry);
24048+ if (err >= 0)
24049+ goto out;
24050+
24051+ sb = dentry->d_sb;
24052+ next = &au_sbi(sb)->si_wbr_rr_next;
24053+ bend = au_sbend(sb);
24054+ nbr = bend + 1;
24055+ for (bindex = 0; bindex <= bend; bindex++) {
24056+ if (!isdir) {
24057+ err = atomic_dec_return(next) + 1;
24058+ /* modulo for 0 is meaningless */
24059+ if (unlikely(!err))
24060+ err = atomic_dec_return(next) + 1;
24061+ } else
24062+ err = atomic_read(next);
24063+ AuDbg("%d\n", err);
24064+ u = err;
24065+ err = u % nbr;
24066+ AuDbg("%d\n", err);
24067+ if (!au_br_rdonly(au_sbr(sb, err)))
24068+ break;
24069+ err = -EROFS;
24070+ }
24071+
4a4d8108
AM
24072+ if (err >= 0)
24073+ err = au_wbr_nonopq(dentry, err);
24074+
4f0767ce 24075+out:
1facf9fc 24076+ AuDbg("%d\n", err);
24077+ return err;
24078+}
24079+
24080+/* ---------------------------------------------------------------------- */
24081+
24082+/* most free space */
24083+static void au_mfs(struct dentry *dentry)
24084+{
24085+ struct super_block *sb;
24086+ struct au_branch *br;
24087+ struct au_wbr_mfs *mfs;
24088+ aufs_bindex_t bindex, bend;
24089+ int err;
24090+ unsigned long long b, bavail;
953406b4 24091+ struct path h_path;
1facf9fc 24092+ /* reduce the stack usage */
24093+ struct kstatfs *st;
24094+
24095+ st = kmalloc(sizeof(*st), GFP_NOFS);
24096+ if (unlikely(!st)) {
24097+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
24098+ return;
24099+ }
24100+
24101+ bavail = 0;
24102+ sb = dentry->d_sb;
24103+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 24104+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 24105+ mfs->mfs_bindex = -EROFS;
24106+ mfs->mfsrr_bytes = 0;
24107+ bend = au_sbend(sb);
24108+ for (bindex = 0; bindex <= bend; bindex++) {
24109+ br = au_sbr(sb, bindex);
24110+ if (au_br_rdonly(br))
24111+ continue;
24112+
24113+ /* sb->s_root for NFS is unreliable */
953406b4
AM
24114+ h_path.mnt = br->br_mnt;
24115+ h_path.dentry = h_path.mnt->mnt_root;
24116+ err = vfs_statfs(&h_path, st);
1facf9fc 24117+ if (unlikely(err)) {
24118+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
24119+ continue;
24120+ }
24121+
24122+ /* when the available size is equal, select the lower one */
24123+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
24124+ || sizeof(b) < sizeof(st->f_bsize));
24125+ b = st->f_bavail * st->f_bsize;
24126+ br->br_wbr->wbr_bytes = b;
24127+ if (b >= bavail) {
24128+ bavail = b;
24129+ mfs->mfs_bindex = bindex;
24130+ mfs->mfs_jiffy = jiffies;
24131+ }
24132+ }
24133+
24134+ mfs->mfsrr_bytes = bavail;
24135+ AuDbg("b%d\n", mfs->mfs_bindex);
24136+ kfree(st);
24137+}
24138+
24139+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
24140+{
24141+ int err;
24142+ struct super_block *sb;
24143+ struct au_wbr_mfs *mfs;
24144+
24145+ err = au_wbr_create_exp(dentry);
24146+ if (err >= 0)
24147+ goto out;
24148+
24149+ sb = dentry->d_sb;
24150+ mfs = &au_sbi(sb)->si_wbr_mfs;
24151+ mutex_lock(&mfs->mfs_lock);
24152+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
24153+ || mfs->mfs_bindex < 0
24154+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
24155+ au_mfs(dentry);
24156+ mutex_unlock(&mfs->mfs_lock);
24157+ err = mfs->mfs_bindex;
24158+
4a4d8108
AM
24159+ if (err >= 0)
24160+ err = au_wbr_nonopq(dentry, err);
24161+
4f0767ce 24162+out:
1facf9fc 24163+ AuDbg("b%d\n", err);
24164+ return err;
24165+}
24166+
24167+static int au_wbr_create_init_mfs(struct super_block *sb)
24168+{
24169+ struct au_wbr_mfs *mfs;
24170+
24171+ mfs = &au_sbi(sb)->si_wbr_mfs;
24172+ mutex_init(&mfs->mfs_lock);
24173+ mfs->mfs_jiffy = 0;
24174+ mfs->mfs_bindex = -EROFS;
24175+
24176+ return 0;
24177+}
24178+
24179+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
24180+{
24181+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
24182+ return 0;
24183+}
24184+
24185+/* ---------------------------------------------------------------------- */
24186+
24187+/* most free space and then round robin */
24188+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
24189+{
24190+ int err;
24191+ struct au_wbr_mfs *mfs;
24192+
24193+ err = au_wbr_create_mfs(dentry, isdir);
24194+ if (err >= 0) {
24195+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 24196+ mutex_lock(&mfs->mfs_lock);
1facf9fc 24197+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
24198+ err = au_wbr_create_rr(dentry, isdir);
dece6358 24199+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 24200+ }
24201+
24202+ AuDbg("b%d\n", err);
24203+ return err;
24204+}
24205+
24206+static int au_wbr_create_init_mfsrr(struct super_block *sb)
24207+{
24208+ int err;
24209+
24210+ au_wbr_create_init_mfs(sb); /* ignore */
24211+ err = au_wbr_create_init_rr(sb);
24212+
24213+ return err;
24214+}
24215+
24216+/* ---------------------------------------------------------------------- */
24217+
24218+/* top down parent and most free space */
24219+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
24220+{
24221+ int err, e2;
24222+ unsigned long long b;
24223+ aufs_bindex_t bindex, bstart, bend;
24224+ struct super_block *sb;
24225+ struct dentry *parent, *h_parent;
24226+ struct au_branch *br;
24227+
24228+ err = au_wbr_create_tdp(dentry, isdir);
24229+ if (unlikely(err < 0))
24230+ goto out;
24231+ parent = dget_parent(dentry);
24232+ bstart = au_dbstart(parent);
24233+ bend = au_dbtaildir(parent);
24234+ if (bstart == bend)
24235+ goto out_parent; /* success */
24236+
24237+ e2 = au_wbr_create_mfs(dentry, isdir);
24238+ if (e2 < 0)
24239+ goto out_parent; /* success */
24240+
24241+ /* when the available size is equal, select upper one */
24242+ sb = dentry->d_sb;
24243+ br = au_sbr(sb, err);
24244+ b = br->br_wbr->wbr_bytes;
24245+ AuDbg("b%d, %llu\n", err, b);
24246+
24247+ for (bindex = bstart; bindex <= bend; bindex++) {
24248+ h_parent = au_h_dptr(parent, bindex);
24249+ if (!h_parent || !h_parent->d_inode)
24250+ continue;
24251+
24252+ br = au_sbr(sb, bindex);
24253+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
24254+ b = br->br_wbr->wbr_bytes;
24255+ err = bindex;
24256+ AuDbg("b%d, %llu\n", err, b);
24257+ }
24258+ }
24259+
4a4d8108
AM
24260+ if (err >= 0)
24261+ err = au_wbr_nonopq(dentry, err);
24262+
4f0767ce 24263+out_parent:
1facf9fc 24264+ dput(parent);
4f0767ce 24265+out:
1facf9fc 24266+ AuDbg("b%d\n", err);
24267+ return err;
24268+}
24269+
24270+/* ---------------------------------------------------------------------- */
24271+
24272+/* policies for copyup */
24273+
24274+/* top down parent */
24275+static int au_wbr_copyup_tdp(struct dentry *dentry)
24276+{
24277+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
24278+}
24279+
24280+/* bottom up parent */
24281+static int au_wbr_copyup_bup(struct dentry *dentry)
24282+{
24283+ int err;
24284+ aufs_bindex_t bindex, bstart;
24285+ struct dentry *parent, *h_parent;
24286+ struct super_block *sb;
24287+
24288+ err = -EROFS;
24289+ sb = dentry->d_sb;
24290+ parent = dget_parent(dentry);
24291+ bstart = au_dbstart(parent);
24292+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
24293+ h_parent = au_h_dptr(parent, bindex);
24294+ if (!h_parent || !h_parent->d_inode)
24295+ continue;
24296+
24297+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
24298+ err = bindex;
24299+ break;
24300+ }
24301+ }
24302+ dput(parent);
24303+
24304+ /* bottom up here */
24305+ if (unlikely(err < 0))
24306+ err = au_wbr_bu(sb, bstart - 1);
24307+
24308+ AuDbg("b%d\n", err);
24309+ return err;
24310+}
24311+
24312+/* bottom up */
24313+static int au_wbr_copyup_bu(struct dentry *dentry)
24314+{
24315+ int err;
4a4d8108 24316+ aufs_bindex_t bstart;
1facf9fc 24317+
4a4d8108
AM
24318+ bstart = au_dbstart(dentry);
24319+ err = au_wbr_bu(dentry->d_sb, bstart);
24320+ AuDbg("b%d\n", err);
24321+ if (err > bstart)
24322+ err = au_wbr_nonopq(dentry, err);
1facf9fc 24323+
24324+ AuDbg("b%d\n", err);
24325+ return err;
24326+}
24327+
24328+/* ---------------------------------------------------------------------- */
24329+
24330+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
24331+ [AuWbrCopyup_TDP] = {
24332+ .copyup = au_wbr_copyup_tdp
24333+ },
24334+ [AuWbrCopyup_BUP] = {
24335+ .copyup = au_wbr_copyup_bup
24336+ },
24337+ [AuWbrCopyup_BU] = {
24338+ .copyup = au_wbr_copyup_bu
24339+ }
24340+};
24341+
24342+struct au_wbr_create_operations au_wbr_create_ops[] = {
24343+ [AuWbrCreate_TDP] = {
24344+ .create = au_wbr_create_tdp
24345+ },
24346+ [AuWbrCreate_RR] = {
24347+ .create = au_wbr_create_rr,
24348+ .init = au_wbr_create_init_rr
24349+ },
24350+ [AuWbrCreate_MFS] = {
24351+ .create = au_wbr_create_mfs,
24352+ .init = au_wbr_create_init_mfs,
24353+ .fin = au_wbr_create_fin_mfs
24354+ },
24355+ [AuWbrCreate_MFSV] = {
24356+ .create = au_wbr_create_mfs,
24357+ .init = au_wbr_create_init_mfs,
24358+ .fin = au_wbr_create_fin_mfs
24359+ },
24360+ [AuWbrCreate_MFSRR] = {
24361+ .create = au_wbr_create_mfsrr,
24362+ .init = au_wbr_create_init_mfsrr,
24363+ .fin = au_wbr_create_fin_mfs
24364+ },
24365+ [AuWbrCreate_MFSRRV] = {
24366+ .create = au_wbr_create_mfsrr,
24367+ .init = au_wbr_create_init_mfsrr,
24368+ .fin = au_wbr_create_fin_mfs
24369+ },
24370+ [AuWbrCreate_PMFS] = {
24371+ .create = au_wbr_create_pmfs,
24372+ .init = au_wbr_create_init_mfs,
24373+ .fin = au_wbr_create_fin_mfs
24374+ },
24375+ [AuWbrCreate_PMFSV] = {
24376+ .create = au_wbr_create_pmfs,
24377+ .init = au_wbr_create_init_mfs,
24378+ .fin = au_wbr_create_fin_mfs
24379+ }
24380+};
b752ccd1
AM
24381diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
24382--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
24383+++ linux/fs/aufs/whout.c 2010-10-21 09:52:43.096959416 +0200
24384@@ -0,0 +1,1052 @@
1facf9fc 24385+/*
4a4d8108 24386+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 24387+ *
24388+ * This program, aufs is free software; you can redistribute it and/or modify
24389+ * it under the terms of the GNU General Public License as published by
24390+ * the Free Software Foundation; either version 2 of the License, or
24391+ * (at your option) any later version.
dece6358
AM
24392+ *
24393+ * This program is distributed in the hope that it will be useful,
24394+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24395+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24396+ * GNU General Public License for more details.
24397+ *
24398+ * You should have received a copy of the GNU General Public License
24399+ * along with this program; if not, write to the Free Software
24400+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24401+ */
24402+
24403+/*
24404+ * whiteout for logical deletion and opaque directory
24405+ */
24406+
24407+#include <linux/fs.h>
24408+#include "aufs.h"
24409+
24410+#define WH_MASK S_IRUGO
24411+
24412+/*
24413+ * If a directory contains this file, then it is opaque. We start with the
24414+ * .wh. flag so that it is blocked by lookup.
24415+ */
24416+static struct qstr diropq_name = {
24417+ .name = AUFS_WH_DIROPQ,
24418+ .len = sizeof(AUFS_WH_DIROPQ) - 1
24419+};
24420+
24421+/*
24422+ * generate whiteout name, which is NOT terminated by NULL.
24423+ * @name: original d_name.name
24424+ * @len: original d_name.len
24425+ * @wh: whiteout qstr
24426+ * returns zero when succeeds, otherwise error.
24427+ * succeeded value as wh->name should be freed by kfree().
24428+ */
24429+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
24430+{
24431+ char *p;
24432+
24433+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
24434+ return -ENAMETOOLONG;
24435+
24436+ wh->len = name->len + AUFS_WH_PFX_LEN;
24437+ p = kmalloc(wh->len, GFP_NOFS);
24438+ wh->name = p;
24439+ if (p) {
24440+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
24441+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
24442+ /* smp_mb(); */
24443+ return 0;
24444+ }
24445+ return -ENOMEM;
24446+}
24447+
24448+/* ---------------------------------------------------------------------- */
24449+
24450+/*
24451+ * test if the @wh_name exists under @h_parent.
24452+ * @try_sio specifies the necessary of super-io.
24453+ */
24454+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
24455+ struct au_branch *br, int try_sio)
24456+{
24457+ int err;
24458+ struct dentry *wh_dentry;
1facf9fc 24459+
1facf9fc 24460+ if (!try_sio)
24461+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
24462+ else
24463+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
24464+ err = PTR_ERR(wh_dentry);
24465+ if (IS_ERR(wh_dentry))
24466+ goto out;
24467+
24468+ err = 0;
24469+ if (!wh_dentry->d_inode)
24470+ goto out_wh; /* success */
24471+
24472+ err = 1;
24473+ if (S_ISREG(wh_dentry->d_inode->i_mode))
24474+ goto out_wh; /* success */
24475+
24476+ err = -EIO;
24477+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
24478+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
24479+
4f0767ce 24480+out_wh:
1facf9fc 24481+ dput(wh_dentry);
4f0767ce 24482+out:
1facf9fc 24483+ return err;
24484+}
24485+
24486+/*
24487+ * test if the @h_dentry sets opaque or not.
24488+ */
24489+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
24490+{
24491+ int err;
24492+ struct inode *h_dir;
24493+
24494+ h_dir = h_dentry->d_inode;
24495+ err = au_wh_test(h_dentry, &diropq_name, br,
24496+ au_test_h_perm_sio(h_dir, MAY_EXEC));
24497+ return err;
24498+}
24499+
24500+/*
24501+ * returns a negative dentry whose name is unique and temporary.
24502+ */
24503+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
24504+ struct qstr *prefix)
24505+{
1facf9fc 24506+ struct dentry *dentry;
24507+ int i;
4a4d8108
AM
24508+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN_MIN + 1],
24509+ *name, *p;
1facf9fc 24510+ static unsigned short cnt;
24511+ struct qstr qs;
24512+
4a4d8108
AM
24513+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
24514+
1facf9fc 24515+ name = defname;
24516+ qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
24517+ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
24518+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 24519+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 24520+ goto out;
24521+ dentry = ERR_PTR(-ENOMEM);
24522+ name = kmalloc(qs.len + 1, GFP_NOFS);
24523+ if (unlikely(!name))
24524+ goto out;
24525+ }
24526+
24527+ /* doubly whiteout-ed */
24528+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
24529+ p = name + AUFS_WH_PFX_LEN * 2;
24530+ memcpy(p, prefix->name, prefix->len);
24531+ p += prefix->len;
24532+ *p++ = '.';
4a4d8108 24533+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 24534+
24535+ qs.name = name;
24536+ for (i = 0; i < 3; i++) {
b752ccd1 24537+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 24538+ dentry = au_sio_lkup_one(&qs, h_parent, br);
24539+ if (IS_ERR(dentry) || !dentry->d_inode)
24540+ goto out_name;
24541+ dput(dentry);
24542+ }
4a4d8108 24543+ /* pr_warning("could not get random name\n"); */
1facf9fc 24544+ dentry = ERR_PTR(-EEXIST);
24545+ AuDbg("%.*s\n", AuLNPair(&qs));
24546+ BUG();
24547+
4f0767ce 24548+out_name:
1facf9fc 24549+ if (name != defname)
24550+ kfree(name);
4f0767ce 24551+out:
4a4d8108 24552+ AuTraceErrPtr(dentry);
1facf9fc 24553+ return dentry;
1facf9fc 24554+}
24555+
24556+/*
24557+ * rename the @h_dentry on @br to the whiteouted temporary name.
24558+ */
24559+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
24560+{
24561+ int err;
24562+ struct path h_path = {
24563+ .mnt = br->br_mnt
24564+ };
24565+ struct inode *h_dir;
24566+ struct dentry *h_parent;
24567+
24568+ h_parent = h_dentry->d_parent; /* dir inode is locked */
24569+ h_dir = h_parent->d_inode;
24570+ IMustLock(h_dir);
24571+
24572+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
24573+ err = PTR_ERR(h_path.dentry);
24574+ if (IS_ERR(h_path.dentry))
24575+ goto out;
24576+
24577+ /* under the same dir, no need to lock_rename() */
24578+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
24579+ AuTraceErr(err);
24580+ dput(h_path.dentry);
24581+
4f0767ce 24582+out:
4a4d8108 24583+ AuTraceErr(err);
1facf9fc 24584+ return err;
24585+}
24586+
24587+/* ---------------------------------------------------------------------- */
24588+/*
24589+ * functions for removing a whiteout
24590+ */
24591+
24592+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
24593+{
24594+ int force;
24595+
24596+ /*
24597+ * forces superio when the dir has a sticky bit.
24598+ * this may be a violation of unix fs semantics.
24599+ */
24600+ force = (h_dir->i_mode & S_ISVTX)
24601+ && h_path->dentry->d_inode->i_uid != current_fsuid();
24602+ return vfsub_unlink(h_dir, h_path, force);
24603+}
24604+
24605+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
24606+ struct dentry *dentry)
24607+{
24608+ int err;
24609+
24610+ err = do_unlink_wh(h_dir, h_path);
24611+ if (!err && dentry)
24612+ au_set_dbwh(dentry, -1);
24613+
24614+ return err;
24615+}
24616+
24617+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
24618+ struct au_branch *br)
24619+{
24620+ int err;
24621+ struct path h_path = {
24622+ .mnt = br->br_mnt
24623+ };
24624+
24625+ err = 0;
24626+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
24627+ if (IS_ERR(h_path.dentry))
24628+ err = PTR_ERR(h_path.dentry);
24629+ else {
24630+ if (h_path.dentry->d_inode
24631+ && S_ISREG(h_path.dentry->d_inode->i_mode))
24632+ err = do_unlink_wh(h_parent->d_inode, &h_path);
24633+ dput(h_path.dentry);
24634+ }
24635+
24636+ return err;
24637+}
24638+
24639+/* ---------------------------------------------------------------------- */
24640+/*
24641+ * initialize/clean whiteout for a branch
24642+ */
24643+
24644+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
24645+ const int isdir)
24646+{
24647+ int err;
24648+
24649+ if (!whpath->dentry->d_inode)
24650+ return;
24651+
24652+ err = mnt_want_write(whpath->mnt);
24653+ if (!err) {
24654+ if (isdir)
24655+ err = vfsub_rmdir(h_dir, whpath);
24656+ else
24657+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
24658+ mnt_drop_write(whpath->mnt);
24659+ }
24660+ if (unlikely(err))
4a4d8108
AM
24661+ pr_warning("failed removing %.*s (%d), ignored.\n",
24662+ AuDLNPair(whpath->dentry), err);
1facf9fc 24663+}
24664+
24665+static int test_linkable(struct dentry *h_root)
24666+{
24667+ struct inode *h_dir = h_root->d_inode;
24668+
24669+ if (h_dir->i_op->link)
24670+ return 0;
24671+
4a4d8108
AM
24672+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
24673+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 24674+ return -ENOSYS;
24675+}
24676+
24677+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
24678+static int au_whdir(struct inode *h_dir, struct path *path)
24679+{
24680+ int err;
24681+
24682+ err = -EEXIST;
24683+ if (!path->dentry->d_inode) {
24684+ int mode = S_IRWXU;
24685+
24686+ if (au_test_nfs(path->dentry->d_sb))
24687+ mode |= S_IXUGO;
24688+ err = mnt_want_write(path->mnt);
24689+ if (!err) {
24690+ err = vfsub_mkdir(h_dir, path, mode);
24691+ mnt_drop_write(path->mnt);
24692+ }
24693+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
24694+ err = 0;
24695+ else
4a4d8108 24696+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 24697+
24698+ return err;
24699+}
24700+
24701+struct au_wh_base {
24702+ const struct qstr *name;
24703+ struct dentry *dentry;
24704+};
24705+
24706+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
24707+ struct path *h_path)
24708+{
24709+ h_path->dentry = base[AuBrWh_BASE].dentry;
24710+ au_wh_clean(h_dir, h_path, /*isdir*/0);
24711+ h_path->dentry = base[AuBrWh_PLINK].dentry;
24712+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24713+ h_path->dentry = base[AuBrWh_ORPH].dentry;
24714+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24715+}
24716+
24717+/*
24718+ * returns tri-state,
24719+ * minus: error, caller should print the mesage
24720+ * zero: succuess
24721+ * plus: error, caller should NOT print the mesage
24722+ */
24723+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
24724+ int do_plink, struct au_wh_base base[],
24725+ struct path *h_path)
24726+{
24727+ int err;
24728+ struct inode *h_dir;
24729+
24730+ h_dir = h_root->d_inode;
24731+ h_path->dentry = base[AuBrWh_BASE].dentry;
24732+ au_wh_clean(h_dir, h_path, /*isdir*/0);
24733+ h_path->dentry = base[AuBrWh_PLINK].dentry;
24734+ if (do_plink) {
24735+ err = test_linkable(h_root);
24736+ if (unlikely(err)) {
24737+ err = 1;
24738+ goto out;
24739+ }
24740+
24741+ err = au_whdir(h_dir, h_path);
24742+ if (unlikely(err))
24743+ goto out;
24744+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
24745+ } else
24746+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24747+ h_path->dentry = base[AuBrWh_ORPH].dentry;
24748+ err = au_whdir(h_dir, h_path);
24749+ if (unlikely(err))
24750+ goto out;
24751+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
24752+
4f0767ce 24753+out:
1facf9fc 24754+ return err;
24755+}
24756+
24757+/*
24758+ * for the moment, aufs supports the branch filesystem which does not support
24759+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
24760+ * copyup failed. finally, such filesystem will not be used as the writable
24761+ * branch.
24762+ *
24763+ * returns tri-state, see above.
24764+ */
24765+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
24766+ int do_plink, struct au_wh_base base[],
24767+ struct path *h_path)
24768+{
24769+ int err;
24770+ struct inode *h_dir;
24771+
1308ab2a 24772+ WbrWhMustWriteLock(wbr);
24773+
1facf9fc 24774+ err = test_linkable(h_root);
24775+ if (unlikely(err)) {
24776+ err = 1;
24777+ goto out;
24778+ }
24779+
24780+ /*
24781+ * todo: should this create be done in /sbin/mount.aufs helper?
24782+ */
24783+ err = -EEXIST;
24784+ h_dir = h_root->d_inode;
24785+ if (!base[AuBrWh_BASE].dentry->d_inode) {
24786+ err = mnt_want_write(h_path->mnt);
24787+ if (!err) {
24788+ h_path->dentry = base[AuBrWh_BASE].dentry;
24789+ err = vfsub_create(h_dir, h_path, WH_MASK);
24790+ mnt_drop_write(h_path->mnt);
24791+ }
24792+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
24793+ err = 0;
24794+ else
4a4d8108
AM
24795+ pr_err("unknown %.*s/%.*s exists\n",
24796+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 24797+ if (unlikely(err))
24798+ goto out;
24799+
24800+ h_path->dentry = base[AuBrWh_PLINK].dentry;
24801+ if (do_plink) {
24802+ err = au_whdir(h_dir, h_path);
24803+ if (unlikely(err))
24804+ goto out;
24805+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
24806+ } else
24807+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24808+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
24809+
24810+ h_path->dentry = base[AuBrWh_ORPH].dentry;
24811+ err = au_whdir(h_dir, h_path);
24812+ if (unlikely(err))
24813+ goto out;
24814+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
24815+
4f0767ce 24816+out:
1facf9fc 24817+ return err;
24818+}
24819+
24820+/*
24821+ * initialize the whiteout base file/dir for @br.
24822+ */
24823+int au_wh_init(struct dentry *h_root, struct au_branch *br,
24824+ struct super_block *sb)
24825+{
24826+ int err, i;
24827+ const unsigned char do_plink
24828+ = !!au_opt_test(au_mntflags(sb), PLINK);
24829+ struct path path = {
24830+ .mnt = br->br_mnt
24831+ };
24832+ struct inode *h_dir;
24833+ struct au_wbr *wbr = br->br_wbr;
24834+ static const struct qstr base_name[] = {
24835+ [AuBrWh_BASE] = {
24836+ .name = AUFS_BASE_NAME,
24837+ .len = sizeof(AUFS_BASE_NAME) - 1
24838+ },
24839+ [AuBrWh_PLINK] = {
24840+ .name = AUFS_PLINKDIR_NAME,
24841+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
24842+ },
24843+ [AuBrWh_ORPH] = {
24844+ .name = AUFS_ORPHDIR_NAME,
24845+ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
24846+ }
24847+ };
24848+ struct au_wh_base base[] = {
24849+ [AuBrWh_BASE] = {
24850+ .name = base_name + AuBrWh_BASE,
24851+ .dentry = NULL
24852+ },
24853+ [AuBrWh_PLINK] = {
24854+ .name = base_name + AuBrWh_PLINK,
24855+ .dentry = NULL
24856+ },
24857+ [AuBrWh_ORPH] = {
24858+ .name = base_name + AuBrWh_ORPH,
24859+ .dentry = NULL
24860+ }
24861+ };
24862+
1308ab2a 24863+ if (wbr)
24864+ WbrWhMustWriteLock(wbr);
1facf9fc 24865+
1facf9fc 24866+ for (i = 0; i < AuBrWh_Last; i++) {
24867+ /* doubly whiteouted */
24868+ struct dentry *d;
24869+
24870+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
24871+ err = PTR_ERR(d);
24872+ if (IS_ERR(d))
24873+ goto out;
24874+
24875+ base[i].dentry = d;
24876+ AuDebugOn(wbr
24877+ && wbr->wbr_wh[i]
24878+ && wbr->wbr_wh[i] != base[i].dentry);
24879+ }
24880+
24881+ if (wbr)
24882+ for (i = 0; i < AuBrWh_Last; i++) {
24883+ dput(wbr->wbr_wh[i]);
24884+ wbr->wbr_wh[i] = NULL;
24885+ }
24886+
24887+ err = 0;
1facf9fc 24888+ switch (br->br_perm) {
24889+ case AuBrPerm_RO:
24890+ case AuBrPerm_ROWH:
24891+ case AuBrPerm_RR:
24892+ case AuBrPerm_RRWH:
4a4d8108 24893+ h_dir = h_root->d_inode;
1facf9fc 24894+ au_wh_init_ro(h_dir, base, &path);
24895+ break;
24896+
24897+ case AuBrPerm_RWNoLinkWH:
24898+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
24899+ if (err > 0)
24900+ goto out;
24901+ else if (err)
24902+ goto out_err;
24903+ break;
24904+
24905+ case AuBrPerm_RW:
24906+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
24907+ if (err > 0)
24908+ goto out;
24909+ else if (err)
24910+ goto out_err;
24911+ break;
24912+
24913+ default:
24914+ BUG();
24915+ }
24916+ goto out; /* success */
24917+
4f0767ce 24918+out_err:
4a4d8108
AM
24919+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
24920+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 24921+out:
1facf9fc 24922+ for (i = 0; i < AuBrWh_Last; i++)
24923+ dput(base[i].dentry);
24924+ return err;
24925+}
24926+
24927+/* ---------------------------------------------------------------------- */
24928+/*
24929+ * whiteouts are all hard-linked usually.
24930+ * when its link count reaches a ceiling, we create a new whiteout base
24931+ * asynchronously.
24932+ */
24933+
24934+struct reinit_br_wh {
24935+ struct super_block *sb;
24936+ struct au_branch *br;
24937+};
24938+
24939+static void reinit_br_wh(void *arg)
24940+{
24941+ int err;
24942+ aufs_bindex_t bindex;
24943+ struct path h_path;
24944+ struct reinit_br_wh *a = arg;
24945+ struct au_wbr *wbr;
24946+ struct inode *dir;
24947+ struct dentry *h_root;
24948+ struct au_hinode *hdir;
24949+
24950+ err = 0;
24951+ wbr = a->br->br_wbr;
24952+ /* big aufs lock */
24953+ si_noflush_write_lock(a->sb);
24954+ if (!au_br_writable(a->br->br_perm))
24955+ goto out;
24956+ bindex = au_br_index(a->sb, a->br->br_id);
24957+ if (unlikely(bindex < 0))
24958+ goto out;
24959+
1308ab2a 24960+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 24961+ dir = a->sb->s_root->d_inode;
1facf9fc 24962+ hdir = au_hi(dir, bindex);
24963+ h_root = au_h_dptr(a->sb->s_root, bindex);
24964+
4a4d8108 24965+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 24966+ wbr_wh_write_lock(wbr);
24967+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
24968+ h_root, a->br);
24969+ if (!err) {
24970+ err = mnt_want_write(a->br->br_mnt);
24971+ if (!err) {
24972+ h_path.dentry = wbr->wbr_whbase;
24973+ h_path.mnt = a->br->br_mnt;
24974+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
24975+ mnt_drop_write(a->br->br_mnt);
24976+ }
24977+ } else {
4a4d8108
AM
24978+ pr_warning("%.*s is moved, ignored\n",
24979+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 24980+ err = 0;
24981+ }
24982+ dput(wbr->wbr_whbase);
24983+ wbr->wbr_whbase = NULL;
24984+ if (!err)
24985+ err = au_wh_init(h_root, a->br, a->sb);
24986+ wbr_wh_write_unlock(wbr);
4a4d8108 24987+ au_hn_imtx_unlock(hdir);
1308ab2a 24988+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 24989+
4f0767ce 24990+out:
1facf9fc 24991+ if (wbr)
24992+ atomic_dec(&wbr->wbr_wh_running);
24993+ atomic_dec(&a->br->br_count);
24994+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
24995+ si_write_unlock(a->sb);
24996+ kfree(arg);
24997+ if (unlikely(err))
24998+ AuIOErr("err %d\n", err);
24999+}
25000+
25001+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
25002+{
25003+ int do_dec, wkq_err;
25004+ struct reinit_br_wh *arg;
25005+
25006+ do_dec = 1;
25007+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
25008+ goto out;
25009+
25010+ /* ignore ENOMEM */
25011+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
25012+ if (arg) {
25013+ /*
25014+ * dec(wh_running), kfree(arg) and dec(br_count)
25015+ * in reinit function
25016+ */
25017+ arg->sb = sb;
25018+ arg->br = br;
25019+ atomic_inc(&br->br_count);
25020+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
25021+ if (unlikely(wkq_err)) {
25022+ atomic_dec(&br->br_wbr->wbr_wh_running);
25023+ atomic_dec(&br->br_count);
25024+ kfree(arg);
25025+ }
25026+ do_dec = 0;
25027+ }
25028+
4f0767ce 25029+out:
1facf9fc 25030+ if (do_dec)
25031+ atomic_dec(&br->br_wbr->wbr_wh_running);
25032+}
25033+
25034+/* ---------------------------------------------------------------------- */
25035+
25036+/*
25037+ * create the whiteout @wh.
25038+ */
25039+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
25040+ struct dentry *wh)
25041+{
25042+ int err;
25043+ struct path h_path = {
25044+ .dentry = wh
25045+ };
25046+ struct au_branch *br;
25047+ struct au_wbr *wbr;
25048+ struct dentry *h_parent;
25049+ struct inode *h_dir;
25050+
25051+ h_parent = wh->d_parent; /* dir inode is locked */
25052+ h_dir = h_parent->d_inode;
25053+ IMustLock(h_dir);
25054+
25055+ br = au_sbr(sb, bindex);
25056+ h_path.mnt = br->br_mnt;
25057+ wbr = br->br_wbr;
25058+ wbr_wh_read_lock(wbr);
25059+ if (wbr->wbr_whbase) {
25060+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
25061+ if (!err || err != -EMLINK)
25062+ goto out;
25063+
25064+ /* link count full. re-initialize br_whbase. */
25065+ kick_reinit_br_wh(sb, br);
25066+ }
25067+
25068+ /* return this error in this context */
25069+ err = vfsub_create(h_dir, &h_path, WH_MASK);
25070+
4f0767ce 25071+out:
1facf9fc 25072+ wbr_wh_read_unlock(wbr);
25073+ return err;
25074+}
25075+
25076+/* ---------------------------------------------------------------------- */
25077+
25078+/*
25079+ * create or remove the diropq.
25080+ */
25081+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
25082+ unsigned int flags)
25083+{
25084+ struct dentry *opq_dentry, *h_dentry;
25085+ struct super_block *sb;
25086+ struct au_branch *br;
25087+ int err;
25088+
25089+ sb = dentry->d_sb;
25090+ br = au_sbr(sb, bindex);
25091+ h_dentry = au_h_dptr(dentry, bindex);
25092+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
25093+ if (IS_ERR(opq_dentry))
25094+ goto out;
25095+
25096+ if (au_ftest_diropq(flags, CREATE)) {
25097+ err = link_or_create_wh(sb, bindex, opq_dentry);
25098+ if (!err) {
25099+ au_set_dbdiropq(dentry, bindex);
25100+ goto out; /* success */
25101+ }
25102+ } else {
25103+ struct path tmp = {
25104+ .dentry = opq_dentry,
25105+ .mnt = br->br_mnt
25106+ };
25107+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
25108+ if (!err)
25109+ au_set_dbdiropq(dentry, -1);
25110+ }
25111+ dput(opq_dentry);
25112+ opq_dentry = ERR_PTR(err);
25113+
4f0767ce 25114+out:
1facf9fc 25115+ return opq_dentry;
25116+}
25117+
25118+struct do_diropq_args {
25119+ struct dentry **errp;
25120+ struct dentry *dentry;
25121+ aufs_bindex_t bindex;
25122+ unsigned int flags;
25123+};
25124+
25125+static void call_do_diropq(void *args)
25126+{
25127+ struct do_diropq_args *a = args;
25128+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
25129+}
25130+
25131+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
25132+ unsigned int flags)
25133+{
25134+ struct dentry *diropq, *h_dentry;
25135+
25136+ h_dentry = au_h_dptr(dentry, bindex);
25137+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
25138+ diropq = do_diropq(dentry, bindex, flags);
25139+ else {
25140+ int wkq_err;
25141+ struct do_diropq_args args = {
25142+ .errp = &diropq,
25143+ .dentry = dentry,
25144+ .bindex = bindex,
25145+ .flags = flags
25146+ };
25147+
25148+ wkq_err = au_wkq_wait(call_do_diropq, &args);
25149+ if (unlikely(wkq_err))
25150+ diropq = ERR_PTR(wkq_err);
25151+ }
25152+
25153+ return diropq;
25154+}
25155+
25156+/* ---------------------------------------------------------------------- */
25157+
25158+/*
25159+ * lookup whiteout dentry.
25160+ * @h_parent: lower parent dentry which must exist and be locked
25161+ * @base_name: name of dentry which will be whiteouted
25162+ * returns dentry for whiteout.
25163+ */
25164+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
25165+ struct au_branch *br)
25166+{
25167+ int err;
25168+ struct qstr wh_name;
25169+ struct dentry *wh_dentry;
25170+
25171+ err = au_wh_name_alloc(&wh_name, base_name);
25172+ wh_dentry = ERR_PTR(err);
25173+ if (!err) {
25174+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
25175+ kfree(wh_name.name);
25176+ }
25177+ return wh_dentry;
25178+}
25179+
25180+/*
25181+ * link/create a whiteout for @dentry on @bindex.
25182+ */
25183+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
25184+ struct dentry *h_parent)
25185+{
25186+ struct dentry *wh_dentry;
25187+ struct super_block *sb;
25188+ int err;
25189+
25190+ sb = dentry->d_sb;
25191+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
25192+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
25193+ err = link_or_create_wh(sb, bindex, wh_dentry);
25194+ if (!err)
25195+ au_set_dbwh(dentry, bindex);
25196+ else {
25197+ dput(wh_dentry);
25198+ wh_dentry = ERR_PTR(err);
25199+ }
25200+ }
25201+
25202+ return wh_dentry;
25203+}
25204+
25205+/* ---------------------------------------------------------------------- */
25206+
25207+/* Delete all whiteouts in this directory on branch bindex. */
25208+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
25209+ aufs_bindex_t bindex, struct au_branch *br)
25210+{
25211+ int err;
25212+ unsigned long ul, n;
25213+ struct qstr wh_name;
25214+ char *p;
25215+ struct hlist_head *head;
25216+ struct au_vdir_wh *tpos;
25217+ struct hlist_node *pos;
25218+ struct au_vdir_destr *str;
25219+
25220+ err = -ENOMEM;
4a4d8108 25221+ p = __getname_gfp(GFP_NOFS);
1facf9fc 25222+ wh_name.name = p;
25223+ if (unlikely(!wh_name.name))
25224+ goto out;
25225+
25226+ err = 0;
25227+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25228+ p += AUFS_WH_PFX_LEN;
25229+ n = whlist->nh_num;
25230+ head = whlist->nh_head;
25231+ for (ul = 0; !err && ul < n; ul++, head++) {
25232+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
25233+ if (tpos->wh_bindex != bindex)
25234+ continue;
25235+
25236+ str = &tpos->wh_str;
25237+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
25238+ memcpy(p, str->name, str->len);
25239+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
25240+ err = unlink_wh_name(h_dentry, &wh_name, br);
25241+ if (!err)
25242+ continue;
25243+ break;
25244+ }
25245+ AuIOErr("whiteout name too long %.*s\n",
25246+ str->len, str->name);
25247+ err = -EIO;
25248+ break;
25249+ }
25250+ }
25251+ __putname(wh_name.name);
25252+
4f0767ce 25253+out:
1facf9fc 25254+ return err;
25255+}
25256+
25257+struct del_wh_children_args {
25258+ int *errp;
25259+ struct dentry *h_dentry;
1308ab2a 25260+ struct au_nhash *whlist;
1facf9fc 25261+ aufs_bindex_t bindex;
25262+ struct au_branch *br;
25263+};
25264+
25265+static void call_del_wh_children(void *args)
25266+{
25267+ struct del_wh_children_args *a = args;
1308ab2a 25268+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 25269+}
25270+
25271+/* ---------------------------------------------------------------------- */
25272+
25273+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
25274+{
25275+ struct au_whtmp_rmdir *whtmp;
dece6358 25276+ int err;
1308ab2a 25277+ unsigned int rdhash;
dece6358
AM
25278+
25279+ SiMustAnyLock(sb);
1facf9fc 25280+
25281+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
25282+ if (unlikely(!whtmp)) {
25283+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 25284+ goto out;
dece6358 25285+ }
1facf9fc 25286+
25287+ whtmp->dir = NULL;
25288+ whtmp->wh_dentry = NULL;
1308ab2a 25289+ /* no estimation for dir size */
25290+ rdhash = au_sbi(sb)->si_rdhash;
25291+ if (!rdhash)
25292+ rdhash = AUFS_RDHASH_DEF;
25293+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
25294+ if (unlikely(err)) {
25295+ kfree(whtmp);
25296+ whtmp = ERR_PTR(err);
25297+ }
dece6358 25298+
4f0767ce 25299+out:
dece6358 25300+ return whtmp;
1facf9fc 25301+}
25302+
25303+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
25304+{
25305+ dput(whtmp->wh_dentry);
25306+ iput(whtmp->dir);
dece6358 25307+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 25308+ kfree(whtmp);
25309+}
25310+
25311+/*
25312+ * rmdir the whiteouted temporary named dir @h_dentry.
25313+ * @whlist: whiteouted children.
25314+ */
25315+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
25316+ struct dentry *wh_dentry, struct au_nhash *whlist)
25317+{
25318+ int err;
25319+ struct path h_tmp;
25320+ struct inode *wh_inode, *h_dir;
25321+ struct au_branch *br;
25322+
25323+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
25324+ IMustLock(h_dir);
25325+
25326+ br = au_sbr(dir->i_sb, bindex);
25327+ wh_inode = wh_dentry->d_inode;
25328+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
25329+
25330+ /*
25331+ * someone else might change some whiteouts while we were sleeping.
25332+ * it means this whlist may have an obsoleted entry.
25333+ */
25334+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
25335+ err = del_wh_children(wh_dentry, whlist, bindex, br);
25336+ else {
25337+ int wkq_err;
25338+ struct del_wh_children_args args = {
25339+ .errp = &err,
25340+ .h_dentry = wh_dentry,
1308ab2a 25341+ .whlist = whlist,
1facf9fc 25342+ .bindex = bindex,
25343+ .br = br
25344+ };
25345+
25346+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
25347+ if (unlikely(wkq_err))
25348+ err = wkq_err;
25349+ }
25350+ mutex_unlock(&wh_inode->i_mutex);
25351+
25352+ if (!err) {
25353+ h_tmp.dentry = wh_dentry;
25354+ h_tmp.mnt = br->br_mnt;
25355+ err = vfsub_rmdir(h_dir, &h_tmp);
25356+ /* d_drop(h_dentry); */
25357+ }
25358+
25359+ if (!err) {
25360+ if (au_ibstart(dir) == bindex) {
25361+ au_cpup_attr_timesizes(dir);
25362+ drop_nlink(dir);
25363+ }
25364+ return 0; /* success */
25365+ }
25366+
4a4d8108
AM
25367+ pr_warning("failed removing %.*s(%d), ignored\n",
25368+ AuDLNPair(wh_dentry), err);
1facf9fc 25369+ return err;
25370+}
25371+
25372+static void call_rmdir_whtmp(void *args)
25373+{
25374+ int err;
25375+ struct au_whtmp_rmdir *a = args;
25376+ struct super_block *sb;
25377+ struct dentry *h_parent;
25378+ struct inode *h_dir;
953406b4 25379+ struct au_branch *br;
1facf9fc 25380+ struct au_hinode *hdir;
25381+
25382+ /* rmdir by nfsd may cause deadlock with this i_mutex */
25383+ /* mutex_lock(&a->dir->i_mutex); */
25384+ sb = a->dir->i_sb;
953406b4
AM
25385+ si_noflush_read_lock(sb);
25386+ err = au_test_ro(sb, a->bindex, NULL);
25387+ if (unlikely(err))
1facf9fc 25388+ goto out;
25389+
25390+ err = -EIO;
953406b4 25391+ br = au_sbr(sb, a->bindex);
1facf9fc 25392+ ii_write_lock_parent(a->dir);
25393+ h_parent = dget_parent(a->wh_dentry);
25394+ h_dir = h_parent->d_inode;
953406b4 25395+ hdir = au_hi(a->dir, a->bindex);
4a4d8108 25396+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
953406b4 25397+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, br);
1facf9fc 25398+ if (!err) {
953406b4 25399+ err = mnt_want_write(br->br_mnt);
1facf9fc 25400+ if (!err) {
953406b4 25401+ err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
dece6358 25402+ &a->whlist);
953406b4 25403+ mnt_drop_write(br->br_mnt);
1facf9fc 25404+ }
25405+ }
4a4d8108 25406+ au_hn_imtx_unlock(hdir);
1facf9fc 25407+ dput(h_parent);
25408+ ii_write_unlock(a->dir);
25409+
4f0767ce 25410+out:
1facf9fc 25411+ /* mutex_unlock(&a->dir->i_mutex); */
25412+ au_nwt_done(&au_sbi(sb)->si_nowait);
25413+ si_read_unlock(sb);
25414+ au_whtmp_rmdir_free(a);
25415+ if (unlikely(err))
25416+ AuIOErr("err %d\n", err);
25417+}
25418+
25419+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
25420+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
25421+{
25422+ int wkq_err;
25423+
25424+ IMustLock(dir);
25425+
25426+ /* all post-process will be done in do_rmdir_whtmp(). */
25427+ args->dir = au_igrab(dir);
953406b4 25428+ args->bindex = bindex;
1facf9fc 25429+ args->wh_dentry = dget(wh_dentry);
953406b4 25430+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
1facf9fc 25431+ if (unlikely(wkq_err)) {
4a4d8108
AM
25432+ pr_warning("rmdir error %.*s (%d), ignored\n",
25433+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 25434+ au_whtmp_rmdir_free(args);
25435+ }
25436+}
b752ccd1
AM
25437diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
25438--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
953406b4 25439+++ linux/fs/aufs/whout.h 2010-10-21 09:52:43.096959416 +0200
dece6358 25440@@ -0,0 +1,87 @@
1facf9fc 25441+/*
4a4d8108 25442+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25443+ *
25444+ * This program, aufs is free software; you can redistribute it and/or modify
25445+ * it under the terms of the GNU General Public License as published by
25446+ * the Free Software Foundation; either version 2 of the License, or
25447+ * (at your option) any later version.
dece6358
AM
25448+ *
25449+ * This program is distributed in the hope that it will be useful,
25450+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25451+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25452+ * GNU General Public License for more details.
25453+ *
25454+ * You should have received a copy of the GNU General Public License
25455+ * along with this program; if not, write to the Free Software
25456+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25457+ */
25458+
25459+/*
25460+ * whiteout for logical deletion and opaque directory
25461+ */
25462+
25463+#ifndef __AUFS_WHOUT_H__
25464+#define __AUFS_WHOUT_H__
25465+
25466+#ifdef __KERNEL__
25467+
1facf9fc 25468+#include <linux/aufs_type.h>
25469+#include "dir.h"
25470+
25471+/* whout.c */
25472+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
25473+struct au_branch;
25474+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
25475+ struct au_branch *br, int try_sio);
25476+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
25477+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
25478+ struct qstr *prefix);
25479+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
25480+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
25481+ struct dentry *dentry);
25482+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
25483+ struct super_block *sb);
25484+
25485+/* diropq flags */
25486+#define AuDiropq_CREATE 1
25487+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
25488+#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
25489+#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
25490+
25491+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
25492+ unsigned int flags);
25493+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
25494+ struct au_branch *br);
25495+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
25496+ struct dentry *h_parent);
25497+
25498+/* real rmdir for the whiteout-ed dir */
25499+struct au_whtmp_rmdir {
25500+ struct inode *dir;
953406b4 25501+ aufs_bindex_t bindex;
1facf9fc 25502+ struct dentry *wh_dentry;
dece6358 25503+ struct au_nhash whlist;
1facf9fc 25504+};
25505+
25506+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
25507+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
25508+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
25509+ struct dentry *wh_dentry, struct au_nhash *whlist);
25510+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
25511+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
25512+
25513+/* ---------------------------------------------------------------------- */
25514+
25515+static inline struct dentry *au_diropq_create(struct dentry *dentry,
25516+ aufs_bindex_t bindex)
25517+{
25518+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
25519+}
25520+
25521+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
25522+{
25523+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
25524+}
25525+
25526+#endif /* __KERNEL__ */
25527+#endif /* __AUFS_WHOUT_H__ */
b752ccd1
AM
25528diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
25529--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
25530+++ linux/fs/aufs/wkq.c 2010-10-21 09:52:43.096959416 +0200
25531@@ -0,0 +1,226 @@
1facf9fc 25532+/*
4a4d8108 25533+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25534+ *
25535+ * This program, aufs is free software; you can redistribute it and/or modify
25536+ * it under the terms of the GNU General Public License as published by
25537+ * the Free Software Foundation; either version 2 of the License, or
25538+ * (at your option) any later version.
dece6358
AM
25539+ *
25540+ * This program is distributed in the hope that it will be useful,
25541+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25542+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25543+ * GNU General Public License for more details.
25544+ *
25545+ * You should have received a copy of the GNU General Public License
25546+ * along with this program; if not, write to the Free Software
25547+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25548+ */
25549+
25550+/*
25551+ * workqueue for asynchronous/super-io operations
25552+ * todo: try new dredential scheme
25553+ */
25554+
dece6358 25555+#include <linux/module.h>
1facf9fc 25556+#include "aufs.h"
25557+
b752ccd1
AM
25558+/* internal workqueue named AUFS_WKQ_NAME and AUFS_WKQ_PRE_NAME */
25559+enum {
25560+ AuWkq_INORMAL,
25561+ AuWkq_IPRE
25562+};
25563+
25564+static struct {
25565+ char *name;
25566+ struct workqueue_struct *wkq;
25567+} au_wkq[] = {
25568+ [AuWkq_INORMAL] = {
25569+ .name = AUFS_WKQ_NAME
25570+ },
25571+ [AuWkq_IPRE] = {
25572+ .name = AUFS_WKQ_PRE_NAME
25573+ }
25574+};
1facf9fc 25575+
25576+struct au_wkinfo {
25577+ struct work_struct wk;
25578+ struct super_block *sb;
25579+
25580+ unsigned int flags; /* see wkq.h */
25581+
25582+ au_wkq_func_t func;
25583+ void *args;
25584+
1facf9fc 25585+ struct completion *comp;
25586+};
25587+
25588+/* ---------------------------------------------------------------------- */
25589+
1facf9fc 25590+static void wkq_func(struct work_struct *wk)
25591+{
25592+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
25593+
953406b4
AM
25594+ AuDebugOn(current_fsuid());
25595+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
25596+
1facf9fc 25597+ wkinfo->func(wkinfo->args);
1facf9fc 25598+ if (au_ftest_wkq(wkinfo->flags, WAIT))
25599+ complete(wkinfo->comp);
25600+ else {
25601+ kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
25602+ module_put(THIS_MODULE);
25603+ kfree(wkinfo);
25604+ }
25605+}
25606+
25607+/*
25608+ * Since struct completion is large, try allocating it dynamically.
25609+ */
25610+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
25611+#define AuWkqCompDeclare(name) struct completion *comp = NULL
25612+
25613+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
25614+{
25615+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
25616+ if (*comp) {
25617+ init_completion(*comp);
25618+ wkinfo->comp = *comp;
25619+ return 0;
25620+ }
25621+ return -ENOMEM;
25622+}
25623+
25624+static void au_wkq_comp_free(struct completion *comp)
25625+{
25626+ kfree(comp);
25627+}
25628+
25629+#else
25630+
25631+/* no braces */
25632+#define AuWkqCompDeclare(name) \
25633+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
25634+ struct completion *comp = &_ ## name
25635+
25636+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
25637+{
25638+ wkinfo->comp = *comp;
25639+ return 0;
25640+}
25641+
25642+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
25643+{
25644+ /* empty */
25645+}
25646+#endif /* 4KSTACKS */
25647+
b752ccd1 25648+static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags)
1facf9fc 25649+{
b752ccd1
AM
25650+ struct workqueue_struct *wkq;
25651+
1facf9fc 25652+ au_dbg_verify_kthread();
b752ccd1 25653+ if (flags & AuWkq_WAIT) {
4a4d8108 25654+ INIT_WORK_ON_STACK(&wkinfo->wk, wkq_func);
b752ccd1
AM
25655+ wkq = au_wkq[AuWkq_INORMAL].wkq;
25656+ if (flags & AuWkq_PRE)
25657+ wkq = au_wkq[AuWkq_IPRE].wkq;
25658+ queue_work(wkq, &wkinfo->wk);
4a4d8108
AM
25659+ } else {
25660+ INIT_WORK(&wkinfo->wk, wkq_func);
25661+ schedule_work(&wkinfo->wk);
25662+ }
1facf9fc 25663+}
25664+
b752ccd1 25665+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 25666+{
25667+ int err;
25668+ AuWkqCompDeclare(comp);
25669+ struct au_wkinfo wkinfo = {
b752ccd1 25670+ .flags = flags,
1facf9fc 25671+ .func = func,
25672+ .args = args
25673+ };
25674+
25675+ err = au_wkq_comp_alloc(&wkinfo, &comp);
25676+ if (!err) {
b752ccd1 25677+ au_wkq_run(&wkinfo, flags);
1facf9fc 25678+ /* no timeout, no interrupt */
25679+ wait_for_completion(wkinfo.comp);
25680+ au_wkq_comp_free(comp);
4a4d8108 25681+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 25682+ }
25683+
25684+ return err;
25685+
25686+}
25687+
25688+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
25689+{
25690+ int err;
25691+ struct au_wkinfo *wkinfo;
25692+
25693+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
25694+
25695+ /*
25696+ * wkq_func() must free this wkinfo.
25697+ * it highly depends upon the implementation of workqueue.
25698+ */
25699+ err = 0;
25700+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
25701+ if (wkinfo) {
25702+ wkinfo->sb = sb;
25703+ wkinfo->flags = !AuWkq_WAIT;
25704+ wkinfo->func = func;
25705+ wkinfo->args = args;
25706+ wkinfo->comp = NULL;
25707+ kobject_get(&au_sbi(sb)->si_kobj);
25708+ __module_get(THIS_MODULE);
25709+
4a4d8108 25710+ au_wkq_run(wkinfo, !AuWkq_WAIT);
1facf9fc 25711+ } else {
25712+ err = -ENOMEM;
953406b4 25713+ atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
1facf9fc 25714+ }
25715+
25716+ return err;
25717+}
25718+
25719+/* ---------------------------------------------------------------------- */
25720+
25721+void au_nwt_init(struct au_nowait_tasks *nwt)
25722+{
25723+ atomic_set(&nwt->nw_len, 0);
4a4d8108 25724+ /* smp_mb(); */ /* atomic_set */
1facf9fc 25725+ init_waitqueue_head(&nwt->nw_wq);
25726+}
25727+
25728+void au_wkq_fin(void)
25729+{
b752ccd1
AM
25730+ int i;
25731+
25732+ for (i = 0; i < ARRAY_SIZE(au_wkq); i++)
25733+ if (au_wkq[i].wkq)
25734+ destroy_workqueue(au_wkq[i].wkq);
1facf9fc 25735+}
25736+
25737+int __init au_wkq_init(void)
25738+{
b752ccd1
AM
25739+ int err, i;
25740+
25741+ err = 0;
25742+ for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
953406b4
AM
25743+ BUILD_BUG_ON(!WQ_RESCUER);
25744+ au_wkq[i].wkq = alloc_workqueue(au_wkq[i].name, !WQ_RESCUER,
25745+ WQ_DFL_ACTIVE);
b752ccd1
AM
25746+ if (IS_ERR(au_wkq[i].wkq))
25747+ err = PTR_ERR(au_wkq[i].wkq);
25748+ else if (!au_wkq[i].wkq)
25749+ err = -ENOMEM;
25750+ if (unlikely(err))
25751+ au_wkq[i].wkq = NULL;
25752+ }
953406b4 25753+ if (unlikely(err))
b752ccd1
AM
25754+ au_wkq_fin();
25755+
25756+ return err;
1facf9fc 25757+}
b752ccd1
AM
25758diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
25759--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
953406b4 25760+++ linux/fs/aufs/wkq.h 2010-10-21 09:52:43.096959416 +0200
b752ccd1 25761@@ -0,0 +1,88 @@
1facf9fc 25762+/*
4a4d8108 25763+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25764+ *
25765+ * This program, aufs is free software; you can redistribute it and/or modify
25766+ * it under the terms of the GNU General Public License as published by
25767+ * the Free Software Foundation; either version 2 of the License, or
25768+ * (at your option) any later version.
dece6358
AM
25769+ *
25770+ * This program is distributed in the hope that it will be useful,
25771+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25772+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25773+ * GNU General Public License for more details.
25774+ *
25775+ * You should have received a copy of the GNU General Public License
25776+ * along with this program; if not, write to the Free Software
25777+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25778+ */
25779+
25780+/*
25781+ * workqueue for asynchronous/super-io operations
25782+ * todo: try new credentials management scheme
25783+ */
25784+
25785+#ifndef __AUFS_WKQ_H__
25786+#define __AUFS_WKQ_H__
25787+
25788+#ifdef __KERNEL__
25789+
1facf9fc 25790+#include <linux/sched.h>
dece6358 25791+#include <linux/wait.h>
1facf9fc 25792+#include <linux/aufs_type.h>
25793+
dece6358
AM
25794+struct super_block;
25795+
1facf9fc 25796+/* ---------------------------------------------------------------------- */
25797+
25798+/*
25799+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
25800+ */
25801+struct au_nowait_tasks {
25802+ atomic_t nw_len;
25803+ wait_queue_head_t nw_wq;
25804+};
25805+
25806+/* ---------------------------------------------------------------------- */
25807+
25808+typedef void (*au_wkq_func_t)(void *args);
25809+
25810+/* wkq flags */
25811+#define AuWkq_WAIT 1
b752ccd1 25812+#define AuWkq_PRE (1 << 1)
1facf9fc 25813+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
25814+#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
25815+#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
25816+
25817+/* wkq.c */
b752ccd1 25818+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
1facf9fc 25819+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
25820+void au_nwt_init(struct au_nowait_tasks *nwt);
25821+int __init au_wkq_init(void);
25822+void au_wkq_fin(void);
25823+
25824+/* ---------------------------------------------------------------------- */
25825+
b752ccd1
AM
25826+static inline int au_wkq_wait_pre(au_wkq_func_t func, void *args)
25827+{
25828+ return au_wkq_do_wait(AuWkq_WAIT | AuWkq_PRE, func, args);
25829+}
25830+
25831+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 25832+{
b752ccd1 25833+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 25834+}
25835+
25836+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
25837+{
953406b4 25838+ if (!atomic_dec_return(&nwt->nw_len))
1facf9fc 25839+ wake_up_all(&nwt->nw_wq);
25840+}
25841+
25842+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
25843+{
25844+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
25845+ return 0;
25846+}
25847+
25848+#endif /* __KERNEL__ */
25849+#endif /* __AUFS_WKQ_H__ */
b752ccd1
AM
25850diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
25851--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
953406b4 25852+++ linux/fs/aufs/xino.c 2010-10-21 09:52:43.096959416 +0200
b752ccd1 25853@@ -0,0 +1,1263 @@
1facf9fc 25854+/*
4a4d8108 25855+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25856+ *
25857+ * This program, aufs is free software; you can redistribute it and/or modify
25858+ * it under the terms of the GNU General Public License as published by
25859+ * the Free Software Foundation; either version 2 of the License, or
25860+ * (at your option) any later version.
dece6358
AM
25861+ *
25862+ * This program is distributed in the hope that it will be useful,
25863+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25864+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25865+ * GNU General Public License for more details.
25866+ *
25867+ * You should have received a copy of the GNU General Public License
25868+ * along with this program; if not, write to the Free Software
25869+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25870+ */
25871+
25872+/*
25873+ * external inode number translation table and bitmap
25874+ */
25875+
dece6358 25876+#include <linux/file.h>
1facf9fc 25877+#include <linux/seq_file.h>
25878+#include <linux/uaccess.h>
25879+#include "aufs.h"
25880+
b752ccd1 25881+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 25882+ loff_t *pos)
25883+{
25884+ ssize_t err;
25885+ mm_segment_t oldfs;
b752ccd1
AM
25886+ union {
25887+ void *k;
25888+ char __user *u;
25889+ } buf;
1facf9fc 25890+
b752ccd1 25891+ buf.k = kbuf;
1facf9fc 25892+ oldfs = get_fs();
25893+ set_fs(KERNEL_DS);
25894+ do {
25895+ /* todo: signal_pending? */
b752ccd1 25896+ err = func(file, buf.u, size, pos);
1facf9fc 25897+ } while (err == -EAGAIN || err == -EINTR);
25898+ set_fs(oldfs);
25899+
25900+#if 0 /* reserved for future use */
25901+ if (err > 0)
25902+ fsnotify_access(file->f_dentry);
25903+#endif
25904+
25905+ return err;
25906+}
25907+
25908+/* ---------------------------------------------------------------------- */
25909+
b752ccd1 25910+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 25911+ size_t size, loff_t *pos)
25912+{
25913+ ssize_t err;
25914+ mm_segment_t oldfs;
b752ccd1
AM
25915+ union {
25916+ void *k;
25917+ const char __user *u;
25918+ } buf;
1facf9fc 25919+
b752ccd1 25920+ buf.k = kbuf;
1facf9fc 25921+ oldfs = get_fs();
25922+ set_fs(KERNEL_DS);
1facf9fc 25923+ do {
25924+ /* todo: signal_pending? */
b752ccd1 25925+ err = func(file, buf.u, size, pos);
1facf9fc 25926+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 25927+ set_fs(oldfs);
25928+
25929+#if 0 /* reserved for future use */
25930+ if (err > 0)
25931+ fsnotify_modify(file->f_dentry);
25932+#endif
25933+
25934+ return err;
25935+}
25936+
25937+struct do_xino_fwrite_args {
25938+ ssize_t *errp;
25939+ au_writef_t func;
25940+ struct file *file;
25941+ void *buf;
25942+ size_t size;
25943+ loff_t *pos;
25944+};
25945+
25946+static void call_do_xino_fwrite(void *args)
25947+{
25948+ struct do_xino_fwrite_args *a = args;
25949+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
25950+}
25951+
25952+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
25953+ loff_t *pos)
25954+{
25955+ ssize_t err;
25956+
25957+ /* todo: signal block and no wkq? */
b752ccd1
AM
25958+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
25959+ lockdep_off();
25960+ err = do_xino_fwrite(func, file, buf, size, pos);
25961+ lockdep_on();
25962+ } else {
25963+ /*
25964+ * it breaks RLIMIT_FSIZE and normal user's limit,
25965+ * users should care about quota and real 'filesystem full.'
25966+ */
1facf9fc 25967+ int wkq_err;
25968+ struct do_xino_fwrite_args args = {
25969+ .errp = &err,
25970+ .func = func,
25971+ .file = file,
25972+ .buf = buf,
25973+ .size = size,
25974+ .pos = pos
25975+ };
25976+
25977+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
25978+ if (unlikely(wkq_err))
25979+ err = wkq_err;
b752ccd1 25980+ }
1facf9fc 25981+
25982+ return err;
25983+}
25984+
25985+/* ---------------------------------------------------------------------- */
25986+
25987+/*
25988+ * create a new xinofile at the same place/path as @base_file.
25989+ */
25990+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
25991+{
25992+ struct file *file;
4a4d8108 25993+ struct dentry *base, *parent;
1facf9fc 25994+ struct inode *dir;
25995+ struct qstr *name;
1308ab2a 25996+ struct path path;
4a4d8108 25997+ int err;
1facf9fc 25998+
25999+ base = base_file->f_dentry;
26000+ parent = base->d_parent; /* dir inode is locked */
26001+ dir = parent->d_inode;
26002+ IMustLock(dir);
26003+
26004+ file = ERR_PTR(-EINVAL);
26005+ name = &base->d_name;
4a4d8108
AM
26006+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
26007+ if (IS_ERR(path.dentry)) {
26008+ file = (void *)path.dentry;
26009+ pr_err("%.*s lookup err %ld\n",
26010+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 26011+ goto out;
26012+ }
26013+
26014+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 26015+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 26016+ if (unlikely(err)) {
26017+ file = ERR_PTR(err);
4a4d8108 26018+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 26019+ goto out_dput;
26020+ }
26021+
1308ab2a 26022+ path.mnt = base_file->f_vfsmnt;
4a4d8108
AM
26023+ file = vfsub_dentry_open(&path,
26024+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
1facf9fc 26025+ if (IS_ERR(file)) {
4a4d8108 26026+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 26027+ goto out_dput;
26028+ }
26029+
26030+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
26031+ if (unlikely(err)) {
4a4d8108 26032+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 26033+ goto out_fput;
26034+ }
26035+
26036+ if (copy_src) {
26037+ /* no one can touch copy_src xino */
26038+ err = au_copy_file(file, copy_src,
26039+ i_size_read(copy_src->f_dentry->d_inode));
26040+ if (unlikely(err)) {
4a4d8108 26041+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 26042+ goto out_fput;
26043+ }
26044+ }
26045+ goto out_dput; /* success */
26046+
4f0767ce 26047+out_fput:
1facf9fc 26048+ fput(file);
26049+ file = ERR_PTR(err);
4f0767ce 26050+out_dput:
4a4d8108 26051+ dput(path.dentry);
4f0767ce 26052+out:
1facf9fc 26053+ return file;
26054+}
26055+
26056+struct au_xino_lock_dir {
26057+ struct au_hinode *hdir;
26058+ struct dentry *parent;
26059+ struct mutex *mtx;
26060+};
26061+
26062+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
26063+ struct au_xino_lock_dir *ldir)
26064+{
26065+ aufs_bindex_t brid, bindex;
26066+
26067+ ldir->hdir = NULL;
26068+ bindex = -1;
26069+ brid = au_xino_brid(sb);
26070+ if (brid >= 0)
26071+ bindex = au_br_index(sb, brid);
26072+ if (bindex >= 0) {
26073+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 26074+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 26075+ } else {
26076+ ldir->parent = dget_parent(xino->f_dentry);
26077+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
26078+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
26079+ }
26080+}
26081+
26082+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
26083+{
26084+ if (ldir->hdir)
4a4d8108 26085+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 26086+ else {
26087+ mutex_unlock(ldir->mtx);
26088+ dput(ldir->parent);
26089+ }
26090+}
26091+
26092+/* ---------------------------------------------------------------------- */
26093+
26094+/* trucate xino files asynchronously */
26095+
26096+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
26097+{
26098+ int err;
26099+ aufs_bindex_t bi, bend;
26100+ struct au_branch *br;
26101+ struct file *new_xino, *file;
26102+ struct super_block *h_sb;
26103+ struct au_xino_lock_dir ldir;
26104+
26105+ err = -EINVAL;
26106+ bend = au_sbend(sb);
26107+ if (unlikely(bindex < 0 || bend < bindex))
26108+ goto out;
26109+ br = au_sbr(sb, bindex);
26110+ file = br->br_xino.xi_file;
26111+ if (!file)
26112+ goto out;
26113+
26114+ au_xino_lock_dir(sb, file, &ldir);
26115+ /* mnt_want_write() is unnecessary here */
26116+ new_xino = au_xino_create2(file, file);
26117+ au_xino_unlock_dir(&ldir);
26118+ err = PTR_ERR(new_xino);
26119+ if (IS_ERR(new_xino))
26120+ goto out;
26121+ err = 0;
26122+ fput(file);
26123+ br->br_xino.xi_file = new_xino;
26124+
26125+ h_sb = br->br_mnt->mnt_sb;
26126+ for (bi = 0; bi <= bend; bi++) {
26127+ if (unlikely(bi == bindex))
26128+ continue;
26129+ br = au_sbr(sb, bi);
26130+ if (br->br_mnt->mnt_sb != h_sb)
26131+ continue;
26132+
26133+ fput(br->br_xino.xi_file);
26134+ br->br_xino.xi_file = new_xino;
26135+ get_file(new_xino);
26136+ }
26137+
4f0767ce 26138+out:
1facf9fc 26139+ return err;
26140+}
26141+
26142+struct xino_do_trunc_args {
26143+ struct super_block *sb;
26144+ struct au_branch *br;
26145+};
26146+
26147+static void xino_do_trunc(void *_args)
26148+{
26149+ struct xino_do_trunc_args *args = _args;
26150+ struct super_block *sb;
26151+ struct au_branch *br;
26152+ struct inode *dir;
26153+ int err;
26154+ aufs_bindex_t bindex;
26155+
26156+ err = 0;
26157+ sb = args->sb;
26158+ dir = sb->s_root->d_inode;
26159+ br = args->br;
26160+
26161+ si_noflush_write_lock(sb);
26162+ ii_read_lock_parent(dir);
26163+ bindex = au_br_index(sb, br->br_id);
26164+ err = au_xino_trunc(sb, bindex);
dece6358
AM
26165+ if (!err
26166+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 26167+ >= br->br_xino_upper)
26168+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
26169+
1facf9fc 26170+ ii_read_unlock(dir);
26171+ if (unlikely(err))
4a4d8108 26172+ pr_warning("err b%d, (%d)\n", bindex, err);
1facf9fc 26173+ atomic_dec(&br->br_xino_running);
26174+ atomic_dec(&br->br_count);
26175+ au_nwt_done(&au_sbi(sb)->si_nowait);
26176+ si_write_unlock(sb);
26177+ kfree(args);
26178+}
26179+
26180+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
26181+{
26182+ struct xino_do_trunc_args *args;
26183+ int wkq_err;
26184+
26185+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
26186+ < br->br_xino_upper)
26187+ return;
26188+
26189+ if (atomic_inc_return(&br->br_xino_running) > 1)
26190+ goto out;
26191+
26192+ /* lock and kfree() will be called in trunc_xino() */
26193+ args = kmalloc(sizeof(*args), GFP_NOFS);
26194+ if (unlikely(!args)) {
26195+ AuErr1("no memory\n");
26196+ goto out_args;
26197+ }
26198+
953406b4 26199+ atomic_inc_return(&br->br_count);
1facf9fc 26200+ args->sb = sb;
26201+ args->br = br;
26202+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
26203+ if (!wkq_err)
26204+ return; /* success */
26205+
4a4d8108 26206+ pr_err("wkq %d\n", wkq_err);
953406b4 26207+ atomic_dec_return(&br->br_count);
1facf9fc 26208+
4f0767ce 26209+out_args:
1facf9fc 26210+ kfree(args);
4f0767ce 26211+out:
953406b4 26212+ atomic_dec_return(&br->br_xino_running);
1facf9fc 26213+}
26214+
26215+/* ---------------------------------------------------------------------- */
26216+
26217+static int au_xino_do_write(au_writef_t write, struct file *file,
26218+ ino_t h_ino, ino_t ino)
26219+{
26220+ loff_t pos;
26221+ ssize_t sz;
26222+
26223+ pos = h_ino;
26224+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
26225+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
26226+ return -EFBIG;
26227+ }
26228+ pos *= sizeof(ino);
26229+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
26230+ if (sz == sizeof(ino))
26231+ return 0; /* success */
26232+
26233+ AuIOErr("write failed (%zd)\n", sz);
26234+ return -EIO;
26235+}
26236+
26237+/*
26238+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
26239+ * at the position of @h_ino.
26240+ * even if @ino is zero, it is written to the xinofile and means no entry.
26241+ * if the size of the xino file on a specific filesystem exceeds the watermark,
26242+ * try truncating it.
26243+ */
26244+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
26245+ ino_t ino)
26246+{
26247+ int err;
26248+ unsigned int mnt_flags;
26249+ struct au_branch *br;
26250+
26251+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
26252+ || ((loff_t)-1) > 0);
dece6358 26253+ SiMustAnyLock(sb);
1facf9fc 26254+
26255+ mnt_flags = au_mntflags(sb);
26256+ if (!au_opt_test(mnt_flags, XINO))
26257+ return 0;
26258+
26259+ br = au_sbr(sb, bindex);
26260+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
26261+ h_ino, ino);
26262+ if (!err) {
26263+ if (au_opt_test(mnt_flags, TRUNC_XINO)
26264+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
26265+ xino_try_trunc(sb, br);
26266+ return 0; /* success */
26267+ }
26268+
26269+ AuIOErr("write failed (%d)\n", err);
26270+ return -EIO;
26271+}
26272+
26273+/* ---------------------------------------------------------------------- */
26274+
26275+/* aufs inode number bitmap */
26276+
26277+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
26278+static ino_t xib_calc_ino(unsigned long pindex, int bit)
26279+{
26280+ ino_t ino;
26281+
26282+ AuDebugOn(bit < 0 || page_bits <= bit);
26283+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
26284+ return ino;
26285+}
26286+
26287+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
26288+{
26289+ AuDebugOn(ino < AUFS_FIRST_INO);
26290+ ino -= AUFS_FIRST_INO;
26291+ *pindex = ino / page_bits;
26292+ *bit = ino % page_bits;
26293+}
26294+
26295+static int xib_pindex(struct super_block *sb, unsigned long pindex)
26296+{
26297+ int err;
26298+ loff_t pos;
26299+ ssize_t sz;
26300+ struct au_sbinfo *sbinfo;
26301+ struct file *xib;
26302+ unsigned long *p;
26303+
26304+ sbinfo = au_sbi(sb);
26305+ MtxMustLock(&sbinfo->si_xib_mtx);
26306+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
26307+ || !au_opt_test(sbinfo->si_mntflags, XINO));
26308+
26309+ if (pindex == sbinfo->si_xib_last_pindex)
26310+ return 0;
26311+
26312+ xib = sbinfo->si_xib;
26313+ p = sbinfo->si_xib_buf;
26314+ pos = sbinfo->si_xib_last_pindex;
26315+ pos *= PAGE_SIZE;
26316+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
26317+ if (unlikely(sz != PAGE_SIZE))
26318+ goto out;
26319+
26320+ pos = pindex;
26321+ pos *= PAGE_SIZE;
26322+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
26323+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
26324+ else {
26325+ memset(p, 0, PAGE_SIZE);
26326+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
26327+ }
26328+ if (sz == PAGE_SIZE) {
26329+ sbinfo->si_xib_last_pindex = pindex;
26330+ return 0; /* success */
26331+ }
26332+
4f0767ce 26333+out:
b752ccd1
AM
26334+ AuIOErr1("write failed (%zd)\n", sz);
26335+ err = sz;
26336+ if (sz >= 0)
26337+ err = -EIO;
26338+ return err;
26339+}
26340+
26341+/* ---------------------------------------------------------------------- */
26342+
26343+static void au_xib_clear_bit(struct inode *inode)
26344+{
26345+ int err, bit;
26346+ unsigned long pindex;
26347+ struct super_block *sb;
26348+ struct au_sbinfo *sbinfo;
26349+
26350+ AuDebugOn(inode->i_nlink);
26351+
26352+ sb = inode->i_sb;
26353+ xib_calc_bit(inode->i_ino, &pindex, &bit);
26354+ AuDebugOn(page_bits <= bit);
26355+ sbinfo = au_sbi(sb);
26356+ mutex_lock(&sbinfo->si_xib_mtx);
26357+ err = xib_pindex(sb, pindex);
26358+ if (!err) {
26359+ clear_bit(bit, sbinfo->si_xib_buf);
26360+ sbinfo->si_xib_next_bit = bit;
26361+ }
26362+ mutex_unlock(&sbinfo->si_xib_mtx);
26363+}
26364+
26365+/* for s_op->delete_inode() */
26366+void au_xino_delete_inode(struct inode *inode, const int unlinked)
26367+{
26368+ int err;
26369+ unsigned int mnt_flags;
26370+ aufs_bindex_t bindex, bend, bi;
26371+ unsigned char try_trunc;
26372+ struct au_iinfo *iinfo;
26373+ struct super_block *sb;
26374+ struct au_hinode *hi;
26375+ struct inode *h_inode;
26376+ struct au_branch *br;
26377+ au_writef_t xwrite;
26378+
26379+ sb = inode->i_sb;
26380+ mnt_flags = au_mntflags(sb);
26381+ if (!au_opt_test(mnt_flags, XINO)
26382+ || inode->i_ino == AUFS_ROOT_INO)
26383+ return;
26384+
26385+ if (unlinked) {
26386+ au_xigen_inc(inode);
26387+ au_xib_clear_bit(inode);
26388+ }
26389+
26390+ iinfo = au_ii(inode);
26391+ if (!iinfo)
26392+ return;
1facf9fc 26393+
b752ccd1
AM
26394+ bindex = iinfo->ii_bstart;
26395+ if (bindex < 0)
26396+ return;
1facf9fc 26397+
b752ccd1
AM
26398+ xwrite = au_sbi(sb)->si_xwrite;
26399+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
26400+ hi = iinfo->ii_hinode + bindex;
26401+ bend = iinfo->ii_bend;
26402+ for (; bindex <= bend; bindex++, hi++) {
26403+ h_inode = hi->hi_inode;
26404+ if (!h_inode
26405+ || (!unlinked && h_inode->i_nlink))
26406+ continue;
1facf9fc 26407+
b752ccd1
AM
26408+ /* inode may not be revalidated */
26409+ bi = au_br_index(sb, hi->hi_id);
26410+ if (bi < 0)
26411+ continue;
1facf9fc 26412+
b752ccd1
AM
26413+ br = au_sbr(sb, bi);
26414+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
26415+ h_inode->i_ino, /*ino*/0);
26416+ if (!err && try_trunc
26417+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
26418+ xino_try_trunc(sb, br);
1facf9fc 26419+ }
1facf9fc 26420+}
26421+
26422+/* get an unused inode number from bitmap */
26423+ino_t au_xino_new_ino(struct super_block *sb)
26424+{
26425+ ino_t ino;
26426+ unsigned long *p, pindex, ul, pend;
26427+ struct au_sbinfo *sbinfo;
26428+ struct file *file;
26429+ int free_bit, err;
26430+
26431+ if (!au_opt_test(au_mntflags(sb), XINO))
26432+ return iunique(sb, AUFS_FIRST_INO);
26433+
26434+ sbinfo = au_sbi(sb);
26435+ mutex_lock(&sbinfo->si_xib_mtx);
26436+ p = sbinfo->si_xib_buf;
26437+ free_bit = sbinfo->si_xib_next_bit;
26438+ if (free_bit < page_bits && !test_bit(free_bit, p))
26439+ goto out; /* success */
26440+ free_bit = find_first_zero_bit(p, page_bits);
26441+ if (free_bit < page_bits)
26442+ goto out; /* success */
26443+
26444+ pindex = sbinfo->si_xib_last_pindex;
26445+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
26446+ err = xib_pindex(sb, ul);
26447+ if (unlikely(err))
26448+ goto out_err;
26449+ free_bit = find_first_zero_bit(p, page_bits);
26450+ if (free_bit < page_bits)
26451+ goto out; /* success */
26452+ }
26453+
26454+ file = sbinfo->si_xib;
26455+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
26456+ for (ul = pindex + 1; ul <= pend; ul++) {
26457+ err = xib_pindex(sb, ul);
26458+ if (unlikely(err))
26459+ goto out_err;
26460+ free_bit = find_first_zero_bit(p, page_bits);
26461+ if (free_bit < page_bits)
26462+ goto out; /* success */
26463+ }
26464+ BUG();
26465+
4f0767ce 26466+out:
1facf9fc 26467+ set_bit(free_bit, p);
26468+ sbinfo->si_xib_next_bit++;
26469+ pindex = sbinfo->si_xib_last_pindex;
26470+ mutex_unlock(&sbinfo->si_xib_mtx);
26471+ ino = xib_calc_ino(pindex, free_bit);
26472+ AuDbg("i%lu\n", (unsigned long)ino);
26473+ return ino;
4f0767ce 26474+out_err:
1facf9fc 26475+ mutex_unlock(&sbinfo->si_xib_mtx);
26476+ AuDbg("i0\n");
26477+ return 0;
26478+}
26479+
26480+/*
26481+ * read @ino from xinofile for the specified branch{@sb, @bindex}
26482+ * at the position of @h_ino.
26483+ * if @ino does not exist and @do_new is true, get new one.
26484+ */
26485+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
26486+ ino_t *ino)
26487+{
26488+ int err;
26489+ ssize_t sz;
26490+ loff_t pos;
26491+ struct file *file;
26492+ struct au_sbinfo *sbinfo;
26493+
26494+ *ino = 0;
26495+ if (!au_opt_test(au_mntflags(sb), XINO))
26496+ return 0; /* no xino */
26497+
26498+ err = 0;
26499+ sbinfo = au_sbi(sb);
26500+ pos = h_ino;
26501+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
26502+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
26503+ return -EFBIG;
26504+ }
26505+ pos *= sizeof(*ino);
26506+
26507+ file = au_sbr(sb, bindex)->br_xino.xi_file;
26508+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
26509+ return 0; /* no ino */
26510+
26511+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
26512+ if (sz == sizeof(*ino))
26513+ return 0; /* success */
26514+
26515+ err = sz;
26516+ if (unlikely(sz >= 0)) {
26517+ err = -EIO;
26518+ AuIOErr("xino read error (%zd)\n", sz);
26519+ }
26520+
26521+ return err;
26522+}
26523+
26524+/* ---------------------------------------------------------------------- */
26525+
26526+/* create and set a new xino file */
26527+
26528+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
26529+{
26530+ struct file *file;
26531+ struct dentry *h_parent, *d;
26532+ struct inode *h_dir;
26533+ int err;
26534+
26535+ /*
26536+ * at mount-time, and the xino file is the default path,
4a4d8108 26537+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 26538+ * when a user specified the xino, we cannot get au_hdir to be ignored.
26539+ */
26540+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
26541+ S_IRUGO | S_IWUGO);
26542+ if (IS_ERR(file)) {
26543+ if (!silent)
4a4d8108 26544+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 26545+ return file;
26546+ }
26547+
26548+ /* keep file count */
26549+ h_parent = dget_parent(file->f_dentry);
26550+ h_dir = h_parent->d_inode;
26551+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
26552+ /* mnt_want_write() is unnecessary here */
26553+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
26554+ mutex_unlock(&h_dir->i_mutex);
26555+ dput(h_parent);
26556+ if (unlikely(err)) {
26557+ if (!silent)
4a4d8108 26558+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 26559+ goto out;
26560+ }
26561+
26562+ err = -EINVAL;
26563+ d = file->f_dentry;
26564+ if (unlikely(sb == d->d_sb)) {
26565+ if (!silent)
4a4d8108 26566+ pr_err("%s must be outside\n", fname);
1facf9fc 26567+ goto out;
26568+ }
26569+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
26570+ if (!silent)
4a4d8108
AM
26571+ pr_err("xino doesn't support %s(%s)\n",
26572+ fname, au_sbtype(d->d_sb));
1facf9fc 26573+ goto out;
26574+ }
26575+ return file; /* success */
26576+
4f0767ce 26577+out:
1facf9fc 26578+ fput(file);
26579+ file = ERR_PTR(err);
26580+ return file;
26581+}
26582+
26583+/*
26584+ * find another branch who is on the same filesystem of the specified
26585+ * branch{@btgt}. search until @bend.
26586+ */
26587+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
26588+ aufs_bindex_t bend)
26589+{
26590+ aufs_bindex_t bindex;
26591+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
26592+
26593+ for (bindex = 0; bindex < btgt; bindex++)
26594+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
26595+ return bindex;
26596+ for (bindex++; bindex <= bend; bindex++)
26597+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
26598+ return bindex;
26599+ return -1;
26600+}
26601+
26602+/* ---------------------------------------------------------------------- */
26603+
26604+/*
26605+ * initialize the xinofile for the specified branch @br
26606+ * at the place/path where @base_file indicates.
26607+ * test whether another branch is on the same filesystem or not,
26608+ * if @do_test is true.
26609+ */
26610+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
26611+ struct file *base_file, int do_test)
26612+{
26613+ int err;
26614+ ino_t ino;
26615+ aufs_bindex_t bend, bindex;
26616+ struct au_branch *shared_br, *b;
26617+ struct file *file;
26618+ struct super_block *tgt_sb;
26619+
26620+ shared_br = NULL;
26621+ bend = au_sbend(sb);
26622+ if (do_test) {
26623+ tgt_sb = br->br_mnt->mnt_sb;
26624+ for (bindex = 0; bindex <= bend; bindex++) {
26625+ b = au_sbr(sb, bindex);
26626+ if (tgt_sb == b->br_mnt->mnt_sb) {
26627+ shared_br = b;
26628+ break;
26629+ }
26630+ }
26631+ }
26632+
26633+ if (!shared_br || !shared_br->br_xino.xi_file) {
26634+ struct au_xino_lock_dir ldir;
26635+
26636+ au_xino_lock_dir(sb, base_file, &ldir);
26637+ /* mnt_want_write() is unnecessary here */
26638+ file = au_xino_create2(base_file, NULL);
26639+ au_xino_unlock_dir(&ldir);
26640+ err = PTR_ERR(file);
26641+ if (IS_ERR(file))
26642+ goto out;
26643+ br->br_xino.xi_file = file;
26644+ } else {
26645+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
26646+ get_file(br->br_xino.xi_file);
26647+ }
26648+
26649+ ino = AUFS_ROOT_INO;
26650+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
26651+ h_ino, ino);
b752ccd1
AM
26652+ if (unlikely(err)) {
26653+ fput(br->br_xino.xi_file);
26654+ br->br_xino.xi_file = NULL;
26655+ }
1facf9fc 26656+
4f0767ce 26657+out:
1facf9fc 26658+ return err;
26659+}
26660+
26661+/* ---------------------------------------------------------------------- */
26662+
26663+/* trucate a xino bitmap file */
26664+
26665+/* todo: slow */
26666+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
26667+{
26668+ int err, bit;
26669+ ssize_t sz;
26670+ unsigned long pindex;
26671+ loff_t pos, pend;
26672+ struct au_sbinfo *sbinfo;
26673+ au_readf_t func;
26674+ ino_t *ino;
26675+ unsigned long *p;
26676+
26677+ err = 0;
26678+ sbinfo = au_sbi(sb);
dece6358 26679+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 26680+ p = sbinfo->si_xib_buf;
26681+ func = sbinfo->si_xread;
26682+ pend = i_size_read(file->f_dentry->d_inode);
26683+ pos = 0;
26684+ while (pos < pend) {
26685+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
26686+ err = sz;
26687+ if (unlikely(sz <= 0))
26688+ goto out;
26689+
26690+ err = 0;
26691+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
26692+ if (unlikely(*ino < AUFS_FIRST_INO))
26693+ continue;
26694+
26695+ xib_calc_bit(*ino, &pindex, &bit);
26696+ AuDebugOn(page_bits <= bit);
26697+ err = xib_pindex(sb, pindex);
26698+ if (!err)
26699+ set_bit(bit, p);
26700+ else
26701+ goto out;
26702+ }
26703+ }
26704+
4f0767ce 26705+out:
1facf9fc 26706+ return err;
26707+}
26708+
26709+static int xib_restore(struct super_block *sb)
26710+{
26711+ int err;
26712+ aufs_bindex_t bindex, bend;
26713+ void *page;
26714+
26715+ err = -ENOMEM;
26716+ page = (void *)__get_free_page(GFP_NOFS);
26717+ if (unlikely(!page))
26718+ goto out;
26719+
26720+ err = 0;
26721+ bend = au_sbend(sb);
26722+ for (bindex = 0; !err && bindex <= bend; bindex++)
26723+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
26724+ err = do_xib_restore
26725+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
26726+ else
26727+ AuDbg("b%d\n", bindex);
26728+ free_page((unsigned long)page);
26729+
4f0767ce 26730+out:
1facf9fc 26731+ return err;
26732+}
26733+
26734+int au_xib_trunc(struct super_block *sb)
26735+{
26736+ int err;
26737+ ssize_t sz;
26738+ loff_t pos;
26739+ struct au_xino_lock_dir ldir;
26740+ struct au_sbinfo *sbinfo;
26741+ unsigned long *p;
26742+ struct file *file;
26743+
dece6358
AM
26744+ SiMustWriteLock(sb);
26745+
1facf9fc 26746+ err = 0;
26747+ sbinfo = au_sbi(sb);
26748+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
26749+ goto out;
26750+
26751+ file = sbinfo->si_xib;
26752+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
26753+ goto out;
26754+
26755+ au_xino_lock_dir(sb, file, &ldir);
26756+ /* mnt_want_write() is unnecessary here */
26757+ file = au_xino_create2(sbinfo->si_xib, NULL);
26758+ au_xino_unlock_dir(&ldir);
26759+ err = PTR_ERR(file);
26760+ if (IS_ERR(file))
26761+ goto out;
26762+ fput(sbinfo->si_xib);
26763+ sbinfo->si_xib = file;
26764+
26765+ p = sbinfo->si_xib_buf;
26766+ memset(p, 0, PAGE_SIZE);
26767+ pos = 0;
26768+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
26769+ if (unlikely(sz != PAGE_SIZE)) {
26770+ err = sz;
26771+ AuIOErr("err %d\n", err);
26772+ if (sz >= 0)
26773+ err = -EIO;
26774+ goto out;
26775+ }
26776+
26777+ mutex_lock(&sbinfo->si_xib_mtx);
26778+ /* mnt_want_write() is unnecessary here */
26779+ err = xib_restore(sb);
26780+ mutex_unlock(&sbinfo->si_xib_mtx);
26781+
26782+out:
26783+ return err;
26784+}
26785+
26786+/* ---------------------------------------------------------------------- */
26787+
26788+/*
26789+ * xino mount option handlers
26790+ */
26791+static au_readf_t find_readf(struct file *h_file)
26792+{
26793+ const struct file_operations *fop = h_file->f_op;
26794+
26795+ if (fop) {
26796+ if (fop->read)
26797+ return fop->read;
26798+ if (fop->aio_read)
26799+ return do_sync_read;
26800+ }
26801+ return ERR_PTR(-ENOSYS);
26802+}
26803+
26804+static au_writef_t find_writef(struct file *h_file)
26805+{
26806+ const struct file_operations *fop = h_file->f_op;
26807+
26808+ if (fop) {
26809+ if (fop->write)
26810+ return fop->write;
26811+ if (fop->aio_write)
26812+ return do_sync_write;
26813+ }
26814+ return ERR_PTR(-ENOSYS);
26815+}
26816+
26817+/* xino bitmap */
26818+static void xino_clear_xib(struct super_block *sb)
26819+{
26820+ struct au_sbinfo *sbinfo;
26821+
dece6358
AM
26822+ SiMustWriteLock(sb);
26823+
1facf9fc 26824+ sbinfo = au_sbi(sb);
26825+ sbinfo->si_xread = NULL;
26826+ sbinfo->si_xwrite = NULL;
26827+ if (sbinfo->si_xib)
26828+ fput(sbinfo->si_xib);
26829+ sbinfo->si_xib = NULL;
26830+ free_page((unsigned long)sbinfo->si_xib_buf);
26831+ sbinfo->si_xib_buf = NULL;
26832+}
26833+
26834+static int au_xino_set_xib(struct super_block *sb, struct file *base)
26835+{
26836+ int err;
26837+ loff_t pos;
26838+ struct au_sbinfo *sbinfo;
26839+ struct file *file;
26840+
dece6358
AM
26841+ SiMustWriteLock(sb);
26842+
1facf9fc 26843+ sbinfo = au_sbi(sb);
26844+ file = au_xino_create2(base, sbinfo->si_xib);
26845+ err = PTR_ERR(file);
26846+ if (IS_ERR(file))
26847+ goto out;
26848+ if (sbinfo->si_xib)
26849+ fput(sbinfo->si_xib);
26850+ sbinfo->si_xib = file;
26851+ sbinfo->si_xread = find_readf(file);
26852+ sbinfo->si_xwrite = find_writef(file);
26853+
26854+ err = -ENOMEM;
26855+ if (!sbinfo->si_xib_buf)
26856+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
26857+ if (unlikely(!sbinfo->si_xib_buf))
26858+ goto out_unset;
26859+
26860+ sbinfo->si_xib_last_pindex = 0;
26861+ sbinfo->si_xib_next_bit = 0;
26862+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
26863+ pos = 0;
26864+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
26865+ PAGE_SIZE, &pos);
26866+ if (unlikely(err != PAGE_SIZE))
26867+ goto out_free;
26868+ }
26869+ err = 0;
26870+ goto out; /* success */
26871+
4f0767ce 26872+out_free:
1facf9fc 26873+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
26874+ sbinfo->si_xib_buf = NULL;
26875+ if (err >= 0)
26876+ err = -EIO;
4f0767ce 26877+out_unset:
b752ccd1
AM
26878+ fput(sbinfo->si_xib);
26879+ sbinfo->si_xib = NULL;
26880+ sbinfo->si_xread = NULL;
26881+ sbinfo->si_xwrite = NULL;
4f0767ce 26882+out:
b752ccd1 26883+ return err;
1facf9fc 26884+}
26885+
b752ccd1
AM
26886+/* xino for each branch */
26887+static void xino_clear_br(struct super_block *sb)
26888+{
26889+ aufs_bindex_t bindex, bend;
26890+ struct au_branch *br;
1facf9fc 26891+
b752ccd1
AM
26892+ bend = au_sbend(sb);
26893+ for (bindex = 0; bindex <= bend; bindex++) {
26894+ br = au_sbr(sb, bindex);
26895+ if (!br || !br->br_xino.xi_file)
26896+ continue;
26897+
26898+ fput(br->br_xino.xi_file);
26899+ br->br_xino.xi_file = NULL;
26900+ }
26901+}
26902+
26903+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 26904+{
26905+ int err;
b752ccd1
AM
26906+ ino_t ino;
26907+ aufs_bindex_t bindex, bend, bshared;
26908+ struct {
26909+ struct file *old, *new;
26910+ } *fpair, *p;
26911+ struct au_branch *br;
26912+ struct inode *inode;
26913+ au_writef_t writef;
1facf9fc 26914+
b752ccd1
AM
26915+ SiMustWriteLock(sb);
26916+
26917+ err = -ENOMEM;
26918+ bend = au_sbend(sb);
26919+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
26920+ if (unlikely(!fpair))
1facf9fc 26921+ goto out;
26922+
b752ccd1
AM
26923+ inode = sb->s_root->d_inode;
26924+ ino = AUFS_ROOT_INO;
26925+ writef = au_sbi(sb)->si_xwrite;
26926+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
26927+ br = au_sbr(sb, bindex);
26928+ bshared = is_sb_shared(sb, bindex, bindex - 1);
26929+ if (bshared >= 0) {
26930+ /* shared xino */
26931+ *p = fpair[bshared];
26932+ get_file(p->new);
26933+ }
26934+
26935+ if (!p->new) {
26936+ /* new xino */
26937+ p->old = br->br_xino.xi_file;
26938+ p->new = au_xino_create2(base, br->br_xino.xi_file);
26939+ err = PTR_ERR(p->new);
26940+ if (IS_ERR(p->new)) {
26941+ p->new = NULL;
26942+ goto out_pair;
26943+ }
26944+ }
26945+
26946+ err = au_xino_do_write(writef, p->new,
26947+ au_h_iptr(inode, bindex)->i_ino, ino);
26948+ if (unlikely(err))
26949+ goto out_pair;
26950+ }
26951+
26952+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
26953+ br = au_sbr(sb, bindex);
26954+ if (br->br_xino.xi_file)
26955+ fput(br->br_xino.xi_file);
26956+ get_file(p->new);
26957+ br->br_xino.xi_file = p->new;
26958+ }
1facf9fc 26959+
4f0767ce 26960+out_pair:
b752ccd1
AM
26961+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
26962+ if (p->new)
26963+ fput(p->new);
26964+ else
26965+ break;
26966+ kfree(fpair);
4f0767ce 26967+out:
1facf9fc 26968+ return err;
26969+}
b752ccd1
AM
26970+
26971+void au_xino_clr(struct super_block *sb)
26972+{
26973+ struct au_sbinfo *sbinfo;
26974+
26975+ au_xigen_clr(sb);
26976+ xino_clear_xib(sb);
26977+ xino_clear_br(sb);
26978+ sbinfo = au_sbi(sb);
26979+ /* lvalue, do not call au_mntflags() */
26980+ au_opt_clr(sbinfo->si_mntflags, XINO);
26981+}
26982+
26983+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
26984+{
26985+ int err, skip;
26986+ struct dentry *parent, *cur_parent;
26987+ struct qstr *dname, *cur_name;
26988+ struct file *cur_xino;
26989+ struct inode *dir;
26990+ struct au_sbinfo *sbinfo;
26991+
26992+ SiMustWriteLock(sb);
26993+
26994+ err = 0;
26995+ sbinfo = au_sbi(sb);
26996+ parent = dget_parent(xino->file->f_dentry);
26997+ if (remount) {
26998+ skip = 0;
26999+ dname = &xino->file->f_dentry->d_name;
27000+ cur_xino = sbinfo->si_xib;
27001+ if (cur_xino) {
27002+ cur_parent = dget_parent(cur_xino->f_dentry);
27003+ cur_name = &cur_xino->f_dentry->d_name;
27004+ skip = (cur_parent == parent
27005+ && dname->len == cur_name->len
27006+ && !memcmp(dname->name, cur_name->name,
27007+ dname->len));
27008+ dput(cur_parent);
27009+ }
27010+ if (skip)
27011+ goto out;
27012+ }
27013+
27014+ au_opt_set(sbinfo->si_mntflags, XINO);
27015+ dir = parent->d_inode;
27016+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
27017+ /* mnt_want_write() is unnecessary here */
27018+ err = au_xino_set_xib(sb, xino->file);
27019+ if (!err)
27020+ err = au_xigen_set(sb, xino->file);
27021+ if (!err)
27022+ err = au_xino_set_br(sb, xino->file);
27023+ mutex_unlock(&dir->i_mutex);
27024+ if (!err)
27025+ goto out; /* success */
27026+
27027+ /* reset all */
27028+ AuIOErr("failed creating xino(%d).\n", err);
27029+
4f0767ce 27030+out:
b752ccd1
AM
27031+ dput(parent);
27032+ return err;
27033+}
27034+
27035+/* ---------------------------------------------------------------------- */
27036+
27037+/*
27038+ * create a xinofile at the default place/path.
27039+ */
27040+struct file *au_xino_def(struct super_block *sb)
27041+{
27042+ struct file *file;
27043+ char *page, *p;
27044+ struct au_branch *br;
27045+ struct super_block *h_sb;
27046+ struct path path;
27047+ aufs_bindex_t bend, bindex, bwr;
27048+
27049+ br = NULL;
27050+ bend = au_sbend(sb);
27051+ bwr = -1;
27052+ for (bindex = 0; bindex <= bend; bindex++) {
27053+ br = au_sbr(sb, bindex);
27054+ if (au_br_writable(br->br_perm)
27055+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
27056+ bwr = bindex;
27057+ break;
27058+ }
27059+ }
27060+
27061+ if (bwr >= 0) {
27062+ file = ERR_PTR(-ENOMEM);
27063+ page = __getname_gfp(GFP_NOFS);
27064+ if (unlikely(!page))
27065+ goto out;
27066+ path.mnt = br->br_mnt;
27067+ path.dentry = au_h_dptr(sb->s_root, bwr);
27068+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
27069+ file = (void *)p;
27070+ if (!IS_ERR(p)) {
27071+ strcat(p, "/" AUFS_XINO_FNAME);
27072+ AuDbg("%s\n", p);
27073+ file = au_xino_create(sb, p, /*silent*/0);
27074+ if (!IS_ERR(file))
27075+ au_xino_brid_set(sb, br->br_id);
27076+ }
27077+ __putname(page);
27078+ } else {
27079+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
27080+ if (IS_ERR(file))
27081+ goto out;
27082+ h_sb = file->f_dentry->d_sb;
27083+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
27084+ pr_err("xino doesn't support %s(%s)\n",
27085+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
27086+ fput(file);
27087+ file = ERR_PTR(-EINVAL);
27088+ }
27089+ if (!IS_ERR(file))
27090+ au_xino_brid_set(sb, -1);
27091+ }
27092+
4f0767ce 27093+out:
b752ccd1
AM
27094+ return file;
27095+}
27096+
27097+/* ---------------------------------------------------------------------- */
27098+
27099+int au_xino_path(struct seq_file *seq, struct file *file)
27100+{
27101+ int err;
27102+
27103+ err = au_seq_path(seq, &file->f_path);
27104+ if (unlikely(err < 0))
27105+ goto out;
27106+
27107+ err = 0;
27108+#define Deleted "\\040(deleted)"
27109+ seq->count -= sizeof(Deleted) - 1;
27110+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
27111+ sizeof(Deleted) - 1));
27112+#undef Deleted
27113+
4f0767ce 27114+out:
b752ccd1
AM
27115+ return err;
27116+}
27117diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
27118--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
953406b4
AM
27119+++ linux/include/linux/aufs_type.h 2010-10-21 09:52:43.096959416 +0200
27120@@ -0,0 +1,198 @@
1facf9fc 27121+/*
4a4d8108 27122+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 27123+ *
27124+ * This program, aufs is free software; you can redistribute it and/or modify
27125+ * it under the terms of the GNU General Public License as published by
27126+ * the Free Software Foundation; either version 2 of the License, or
27127+ * (at your option) any later version.
dece6358
AM
27128+ *
27129+ * This program is distributed in the hope that it will be useful,
27130+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27131+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27132+ * GNU General Public License for more details.
27133+ *
27134+ * You should have received a copy of the GNU General Public License
27135+ * along with this program; if not, write to the Free Software
27136+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27137+ */
27138+
27139+#ifndef __AUFS_TYPE_H__
27140+#define __AUFS_TYPE_H__
27141+
27142+#include <linux/ioctl.h>
953406b4
AM
27143+/* for those who didn't "make headers_install" */
27144+#ifdef __KERNEL__
4a4d8108 27145+#include <linux/kernel.h>
953406b4 27146+#endif
4a4d8108 27147+#include <linux/limits.h>
1308ab2a 27148+#include <linux/types.h>
1facf9fc 27149+
953406b4 27150+#define AUFS_VERSION "2-standalone.tree-36-rcN-20100823"
1facf9fc 27151+
27152+/* todo? move this to linux-2.6.19/include/magic.h */
27153+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
27154+
27155+/* ---------------------------------------------------------------------- */
27156+
27157+#ifdef CONFIG_AUFS_BRANCH_MAX_127
1308ab2a 27158+typedef __s8 aufs_bindex_t;
1facf9fc 27159+#define AUFS_BRANCH_MAX 127
27160+#else
1308ab2a 27161+typedef __s16 aufs_bindex_t;
1facf9fc 27162+#ifdef CONFIG_AUFS_BRANCH_MAX_511
27163+#define AUFS_BRANCH_MAX 511
27164+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
27165+#define AUFS_BRANCH_MAX 1023
27166+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
27167+#define AUFS_BRANCH_MAX 32767
27168+#endif
27169+#endif
27170+
27171+#ifdef __KERNEL__
27172+#ifndef AUFS_BRANCH_MAX
27173+#error unknown CONFIG_AUFS_BRANCH_MAX value
27174+#endif
27175+#endif /* __KERNEL__ */
27176+
27177+/* ---------------------------------------------------------------------- */
27178+
27179+#define AUFS_NAME "aufs"
27180+#define AUFS_FSTYPE AUFS_NAME
27181+
27182+#define AUFS_ROOT_INO 2
27183+#define AUFS_FIRST_INO 11
27184+
27185+#define AUFS_WH_PFX ".wh."
27186+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
4a4d8108
AM
27187+#define AUFS_WH_TMP_LEN 4
27188+/* a limit for rmdir/rename a dir */
27189+#define AUFS_MAX_NAMELEN (NAME_MAX \
27190+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
27191+ - 1 /* dot */\
27192+ - AUFS_WH_TMP_LEN) /* hex */
1facf9fc 27193+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
27194+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
27195+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
27196+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
27197+#define AUFS_DIRWH_DEF 3
27198+#define AUFS_RDCACHE_DEF 10 /* seconds */
27199+#define AUFS_RDBLK_DEF 512 /* bytes */
27200+#define AUFS_RDHASH_DEF 32
27201+#define AUFS_WKQ_NAME AUFS_NAME "d"
b752ccd1 27202+#define AUFS_WKQ_PRE_NAME AUFS_WKQ_NAME "_pre"
1facf9fc 27203+#define AUFS_MFS_SECOND_DEF 30 /* seconds */
27204+#define AUFS_PLINK_WARN 100 /* number of plinks */
27205+
27206+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
27207+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
27208+
27209+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
27210+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
27211+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
27212+
27213+/* doubly whiteouted */
27214+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
27215+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
27216+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
27217+
27218+/* branch permission */
27219+#define AUFS_BRPERM_RW "rw"
27220+#define AUFS_BRPERM_RO "ro"
27221+#define AUFS_BRPERM_RR "rr"
27222+#define AUFS_BRPERM_WH "wh"
27223+#define AUFS_BRPERM_NLWH "nolwh"
27224+#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
27225+#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
27226+#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
27227+
27228+/* ---------------------------------------------------------------------- */
27229+
27230+/* ioctl */
27231+enum {
953406b4
AM
27232+ AuCtl_PLINK_MAINT,
27233+ AuCtl_PLINK_CLEAN,
27234+
1308ab2a 27235+ /* readdir in userspace */
27236+ AuCtl_RDU,
4a4d8108
AM
27237+ AuCtl_RDU_INO,
27238+
27239+ /* pathconf wrapper */
27240+ AuCtl_WBR_FD
1308ab2a 27241+};
27242+
27243+/* borrowed from linux/include/linux/kernel.h */
27244+#ifndef ALIGN
27245+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
27246+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
27247+#endif
27248+
27249+/* borrowed from linux/include/linux/compiler-gcc3.h */
27250+#ifndef __aligned
27251+#define __aligned(x) __attribute__((aligned(x)))
27252+#define __packed __attribute__((packed))
27253+#endif
27254+
27255+struct au_rdu_cookie {
27256+ __u64 h_pos;
27257+ __s16 bindex;
27258+ __u8 flags;
27259+ __u8 pad;
27260+ __u32 generation;
27261+} __aligned(8);
27262+
27263+struct au_rdu_ent {
27264+ __u64 ino;
27265+ __s16 bindex;
27266+ __u8 type;
27267+ __u8 nlen;
27268+ __u8 wh;
27269+ char name[0];
27270+} __aligned(8);
27271+
27272+static inline int au_rdu_len(int nlen)
27273+{
27274+ /* include the terminating NULL */
27275+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
27276+ sizeof(__u64));
27277+}
27278+
27279+union au_rdu_ent_ul {
27280+ struct au_rdu_ent __user *e;
b752ccd1 27281+ __u64 ul;
1308ab2a 27282+};
27283+
27284+enum {
27285+ AufsCtlRduV_SZ,
1308ab2a 27286+ AufsCtlRduV_End
1facf9fc 27287+};
27288+
1308ab2a 27289+struct aufs_rdu {
27290+ /* input */
27291+ union {
27292+ __u64 sz; /* AuCtl_RDU */
27293+ __u64 nent; /* AuCtl_RDU_INO */
27294+ };
27295+ union au_rdu_ent_ul ent;
27296+ __u16 verify[AufsCtlRduV_End];
27297+
27298+ /* input/output */
27299+ __u32 blk;
27300+
27301+ /* output */
27302+ union au_rdu_ent_ul tail;
27303+ /* number of entries which were added in a single call */
27304+ __u64 rent;
27305+ __u8 full;
27306+ __u8 shwh;
27307+
27308+ struct au_rdu_cookie cookie;
27309+} __aligned(8);
27310+
1facf9fc 27311+#define AuCtlType 'A'
953406b4
AM
27312+#define AUFS_CTL_PLINK_MAINT _IO(AuCtlType, AuCtl_PLINK_MAINT)
27313+#define AUFS_CTL_PLINK_CLEAN _IO(AuCtlType, AuCtl_PLINK_CLEAN)
1308ab2a 27314+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
27315+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
4a4d8108 27316+#define AUFS_CTL_WBR_FD _IO(AuCtlType, AuCtl_WBR_FD)
1facf9fc 27317+
27318+#endif /* __AUFS_TYPE_H__ */
953406b4 27319
This page took 4.148818 seconds and 4 git commands to generate.