]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs2.patch
- up to 2.6.35.7; grsec updated to /grsecurity-2.2.0-2.6.35.6-201009281623.patch
[packages/kernel.git] / kernel-aufs2.patch
CommitLineData
b752ccd1
AM
1aufs2 kbuild patch for linux-2.6.35
2
3diff --git a/fs/Kconfig b/fs/Kconfig
4index 5f85b59..6ee7cf8 100644
5--- a/fs/Kconfig
6+++ b/fs/Kconfig
7@@ -189,6 +189,7 @@ source "fs/romfs/Kconfig"
8 source "fs/sysv/Kconfig"
9 source "fs/ufs/Kconfig"
10 source "fs/exofs/Kconfig"
11+source "fs/aufs/Kconfig"
12
13 endif # MISC_FILESYSTEMS
14
15diff --git a/fs/Makefile b/fs/Makefile
16index e6ec1d3..b0d795a 100644
17--- a/fs/Makefile
18+++ b/fs/Makefile
19@@ -126,3 +126,4 @@ obj-$(CONFIG_BTRFS_FS) += btrfs/
20 obj-$(CONFIG_GFS2_FS) += gfs2/
21 obj-$(CONFIG_EXOFS_FS) += exofs/
22 obj-$(CONFIG_CEPH_FS) += ceph/
23+obj-$(CONFIG_AUFS_FS) += aufs/
24diff --git a/include/linux/Kbuild b/include/linux/Kbuild
25index 2fc8e14..3b766a7 100644
26--- a/include/linux/Kbuild
27+++ b/include/linux/Kbuild
28@@ -34,6 +34,7 @@ header-y += atmppp.h
29 header-y += atmsap.h
30 header-y += atmsvc.h
31 header-y += atm_zatm.h
32+header-y += aufs_type.h
33 header-y += auto_fs4.h
34 header-y += ax25.h
35 header-y += b1lli.h
36aufs2 base patch for linux-2.6.35
37
38diff --git a/fs/namei.c b/fs/namei.c
39index 868d0cb..6e92c81 100644
40--- a/fs/namei.c
41+++ b/fs/namei.c
42@@ -1178,7 +1178,7 @@ out:
43 * needs parent already locked. Doesn't follow mounts.
44 * SMP-safe.
45 */
46-static struct dentry *lookup_hash(struct nameidata *nd)
47+struct dentry *lookup_hash(struct nameidata *nd)
48 {
49 int err;
50
51@@ -1188,7 +1188,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
52 return __lookup_hash(&nd->last, nd->path.dentry, nd);
53 }
54
55-static int __lookup_one_len(const char *name, struct qstr *this,
56+int __lookup_one_len(const char *name, struct qstr *this,
57 struct dentry *base, int len)
58 {
59 unsigned long hash;
60diff --git a/fs/splice.c b/fs/splice.c
61index efdbfec..e01a51e 100644
62--- a/fs/splice.c
63+++ b/fs/splice.c
64@@ -1104,8 +1104,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
65 /*
66 * Attempt to initiate a splice from pipe to file.
67 */
68-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
69- loff_t *ppos, size_t len, unsigned int flags)
70+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
71+ loff_t *ppos, size_t len, unsigned int flags)
72 {
73 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
74 loff_t *, size_t, unsigned int);
75@@ -1132,9 +1132,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
76 /*
77 * Attempt to initiate a splice from a file to a pipe.
78 */
79-static long do_splice_to(struct file *in, loff_t *ppos,
80- struct pipe_inode_info *pipe, size_t len,
81- unsigned int flags)
82+long do_splice_to(struct file *in, loff_t *ppos,
83+ struct pipe_inode_info *pipe, size_t len,
84+ unsigned int flags)
85 {
86 ssize_t (*splice_read)(struct file *, loff_t *,
87 struct pipe_inode_info *, size_t, unsigned int);
88diff --git a/include/linux/namei.h b/include/linux/namei.h
89index 05b441d..91bc74e 100644
90--- a/include/linux/namei.h
91+++ b/include/linux/namei.h
92@@ -73,6 +73,9 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
93 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
94 int (*open)(struct inode *, struct file *));
95
96+extern struct dentry *lookup_hash(struct nameidata *nd);
97+extern int __lookup_one_len(const char *name, struct qstr *this,
98+ struct dentry *base, int len);
99 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
100
101 extern int follow_down(struct path *);
102diff --git a/include/linux/splice.h b/include/linux/splice.h
103index 997c3b4..be9a153 100644
104--- a/include/linux/splice.h
105+++ b/include/linux/splice.h
106@@ -89,4 +89,10 @@ extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *);
107 extern void splice_shrink_spd(struct pipe_inode_info *,
108 struct splice_pipe_desc *);
109
110+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
111+ loff_t *ppos, size_t len, unsigned int flags);
112+extern long do_splice_to(struct file *in, loff_t *ppos,
113+ struct pipe_inode_info *pipe, size_t len,
114+ unsigned int flags);
115+
116 #endif
117aufs2 standalone patch for linux-2.6.35
118
119diff --git a/fs/namei.c b/fs/namei.c
120index 6e92c81..334130e 100644
121--- a/fs/namei.c
122+++ b/fs/namei.c
123@@ -348,6 +348,7 @@ int deny_write_access(struct file * file)
124
125 return 0;
126 }
127+EXPORT_SYMBOL(deny_write_access);
128
129 /**
130 * path_get - get a reference to a path
131@@ -1187,6 +1188,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
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)
139@@ -1209,6 +1211,7 @@ int __lookup_one_len(const char *name, struct qstr *this,
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
148index 88058de..397afcc 100644
149--- a/fs/namespace.c
150+++ b/fs/namespace.c
151@@ -1279,6 +1279,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
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
160index 0e16771..3fab10a 100644
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"
171@@ -169,6 +170,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
172 fsnotify_recalc_global_mask();
173 fsnotify_destroy_group(group);
174 }
175+EXPORT_SYMBOL(fsnotify_put_group);
176
177 /*
178 * Simply run the fsnotify_groups list and find a group which matches
179@@ -252,3 +254,4 @@ struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, __u32 mask,
180
181 return group;
182 }
183+EXPORT_SYMBOL(fsnotify_obtain_group);
184diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
185index 0399bcb..74cdc13 100644
186--- a/fs/notify/inode_mark.c
187+++ b/fs/notify/inode_mark.c
188@@ -105,6 +105,7 @@ void fsnotify_put_mark(struct fsnotify_mark_entry *entry)
189 if (atomic_dec_and_test(&entry->refcnt))
190 entry->free_mark(entry);
191 }
192+EXPORT_SYMBOL(fsnotify_put_mark);
193
194 /*
195 * Recalculate the mask of events relevant to a given inode locked.
196@@ -215,6 +216,7 @@ void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry)
197 if (unlikely(atomic_dec_and_test(&group->num_marks)))
198 fsnotify_final_destroy_group(group);
199 }
200+EXPORT_SYMBOL(fsnotify_destroy_mark_by_entry);
201
202 /*
203 * Given a group, destroy all of the marks associated with that group.
204@@ -281,6 +283,7 @@ struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_group *grou
205 }
206 return NULL;
207 }
208+EXPORT_SYMBOL(fsnotify_find_mark_entry);
209
210 /*
211 * Nothing fancy, just initialize lists and locks and counters.
212@@ -297,6 +300,7 @@ void fsnotify_init_mark(struct fsnotify_mark_entry *entry,
213 entry->inode = NULL;
214 entry->free_mark = free_mark;
215 }
216+EXPORT_SYMBOL(fsnotify_init_mark);
217
218 /*
219 * Attach an initialized mark entry to a given group and inode.
220@@ -352,6 +356,7 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
221
222 return ret;
223 }
224+EXPORT_SYMBOL(fsnotify_add_mark);
225
226 /**
227 * fsnotify_unmount_inodes - an sb is unmounting. handle any watched inodes.
228diff --git a/fs/open.c b/fs/open.c
229index 5463266..d248ead 100644
230--- a/fs/open.c
231+++ b/fs/open.c
232@@ -59,6 +59,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
233 mutex_unlock(&dentry->d_inode->i_mutex);
234 return ret;
235 }
236+EXPORT_SYMBOL(do_truncate);
237
238 static long do_sys_truncate(const char __user *pathname, loff_t length)
239 {
240diff --git a/fs/splice.c b/fs/splice.c
241index e01a51e..4806358 100644
242--- a/fs/splice.c
243+++ b/fs/splice.c
244@@ -1128,6 +1128,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
245
246 return splice_write(pipe, out, ppos, len, flags);
247 }
248+EXPORT_SYMBOL(do_splice_from);
249
250 /*
251 * Attempt to initiate a splice from a file to a pipe.
252@@ -1154,6 +1155,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
253
254 return splice_read(in, ppos, pipe, len, flags);
255 }
256+EXPORT_SYMBOL(do_splice_to);
257
258 /**
259 * splice_direct_to_actor - splices data directly between two non-pipes
260diff --git a/security/commoncap.c b/security/commoncap.c
261index 4e01599..3611e1b 100644
262--- a/security/commoncap.c
263+++ b/security/commoncap.c
264@@ -951,3 +951,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
265 }
266 return ret;
267 }
268+EXPORT_SYMBOL(cap_file_mmap);
269diff --git a/security/device_cgroup.c b/security/device_cgroup.c
270index 8d9c48f..29108aa 100644
271--- a/security/device_cgroup.c
272+++ b/security/device_cgroup.c
273@@ -515,6 +515,7 @@ found:
274
275 return -EPERM;
276 }
277+EXPORT_SYMBOL(devcgroup_inode_permission);
278
279 int devcgroup_inode_mknod(int mode, dev_t dev)
280 {
281diff --git a/security/security.c b/security/security.c
282index 351942a..6ba84a8 100644
283--- a/security/security.c
284+++ b/security/security.c
285@@ -376,6 +376,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
286 return 0;
287 return security_ops->path_mkdir(dir, dentry, mode);
288 }
289+EXPORT_SYMBOL(security_path_mkdir);
290
291 int security_path_rmdir(struct path *dir, struct dentry *dentry)
292 {
293@@ -383,6 +384,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
294 return 0;
295 return security_ops->path_rmdir(dir, dentry);
296 }
297+EXPORT_SYMBOL(security_path_rmdir);
298
299 int security_path_unlink(struct path *dir, struct dentry *dentry)
300 {
301@@ -390,6 +392,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
302 return 0;
303 return security_ops->path_unlink(dir, dentry);
304 }
305+EXPORT_SYMBOL(security_path_unlink);
306
307 int security_path_symlink(struct path *dir, struct dentry *dentry,
308 const char *old_name)
309@@ -398,6 +401,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
310 return 0;
311 return security_ops->path_symlink(dir, dentry, old_name);
312 }
313+EXPORT_SYMBOL(security_path_symlink);
314
315 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
316 struct dentry *new_dentry)
317@@ -406,6 +410,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
318 return 0;
319 return security_ops->path_link(old_dentry, new_dir, new_dentry);
320 }
321+EXPORT_SYMBOL(security_path_link);
322
323 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
324 struct path *new_dir, struct dentry *new_dentry)
325@@ -416,6 +421,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
326 return security_ops->path_rename(old_dir, old_dentry, new_dir,
327 new_dentry);
328 }
329+EXPORT_SYMBOL(security_path_rename);
330
331 int security_path_truncate(struct path *path, loff_t length,
332 unsigned int time_attrs)
333@@ -424,6 +430,7 @@ int security_path_truncate(struct path *path, loff_t length,
334 return 0;
335 return security_ops->path_truncate(path, length, time_attrs);
336 }
337+EXPORT_SYMBOL(security_path_truncate);
338
339 int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
340 mode_t mode)
341@@ -432,6 +439,7 @@ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
342 return 0;
343 return security_ops->path_chmod(dentry, mnt, mode);
344 }
345+EXPORT_SYMBOL(security_path_chmod);
346
347 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
348 {
349@@ -439,6 +447,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
350 return 0;
351 return security_ops->path_chown(path, uid, gid);
352 }
353+EXPORT_SYMBOL(security_path_chown);
354
355 int security_path_chroot(struct path *path)
356 {
357@@ -515,6 +524,7 @@ int security_inode_readlink(struct dentry *dentry)
358 return 0;
359 return security_ops->inode_readlink(dentry);
360 }
361+EXPORT_SYMBOL(security_inode_readlink);
362
363 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
364 {
365@@ -529,6 +539,7 @@ int security_inode_permission(struct inode *inode, int mask)
366 return 0;
367 return security_ops->inode_permission(inode, mask);
368 }
369+EXPORT_SYMBOL(security_inode_permission);
370
371 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
372 {
373@@ -622,6 +633,7 @@ int security_file_permission(struct file *file, int mask)
374 {
375 return security_ops->file_permission(file, mask);
376 }
377+EXPORT_SYMBOL(security_file_permission);
378
379 int security_file_alloc(struct file *file)
380 {
381@@ -649,6 +661,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
382 return ret;
383 return ima_file_mmap(file, prot);
384 }
385+EXPORT_SYMBOL(security_file_mmap);
386
387 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
388 unsigned long prot)
389diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
390--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
391+++ linux/Documentation/ABI/testing/debugfs-aufs 2010-08-21 21:00:02.956499131 +0200
4a4d8108 392@@ -0,0 +1,37 @@
1facf9fc 393+What: /debug/aufs/si_<id>/
394+Date: March 2009
395+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
396+Description:
397+ Under /debug/aufs, a directory named si_<id> is created
398+ per aufs mount, where <id> is a unique id generated
399+ internally.
400+
401+What: /debug/aufs/si_<id>/xib
402+Date: March 2009
403+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
404+Description:
405+ It shows the consumed blocks by xib (External Inode Number
406+ Bitmap), its block size and file size.
407+ When the aufs mount option 'noxino' is specified, it
4a4d8108 408+ will be empty. About XINO files, see the aufs manual.
1facf9fc 409+
410+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
411+Date: March 2009
412+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
413+Description:
414+ It shows the consumed blocks by xino (External Inode Number
415+ Translation Table), its link count, block size and file
416+ size.
417+ When the aufs mount option 'noxino' is specified, it
4a4d8108 418+ will be empty. About XINO files, see the aufs manual.
1facf9fc 419+
420+What: /debug/aufs/si_<id>/xigen
421+Date: March 2009
422+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
423+Description:
424+ It shows the consumed blocks by xigen (External Inode
425+ Generation Table), its block size and file size.
426+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
427+ be created.
428+ When the aufs mount option 'noxino' is specified, it
4a4d8108 429+ will be empty. About XINO files, see the aufs manual.
b752ccd1
AM
430diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
431--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
432+++ linux/Documentation/ABI/testing/sysfs-aufs 2010-08-21 21:00:02.956499131 +0200
4a4d8108 433@@ -0,0 +1,24 @@
1facf9fc 434+What: /sys/fs/aufs/si_<id>/
435+Date: March 2009
436+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
437+Description:
438+ Under /sys/fs/aufs, a directory named si_<id> is created
439+ per aufs mount, where <id> is a unique id generated
440+ internally.
441+
442+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
443+Date: March 2009
444+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
445+Description:
446+ It shows the abolute path of a member directory (which
447+ is called branch) in aufs, and its permission.
448+
449+What: /sys/fs/aufs/si_<id>/xi_path
450+Date: March 2009
451+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
452+Description:
453+ It shows the abolute path of XINO (External Inode Number
454+ Bitmap, Translation Table and Generation Table) file
455+ even if it is the default path.
456+ When the aufs mount option 'noxino' is specified, it
4a4d8108 457+ will be empty. About XINO files, see the aufs manual.
b752ccd1
AM
458diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
459--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
460+++ linux/fs/aufs/aufs.h 2010-08-21 21:00:02.972333781 +0200
4a4d8108 461@@ -0,0 +1,61 @@
1facf9fc 462+/*
4a4d8108 463+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 464+ *
465+ * This program, aufs is free software; you can redistribute it and/or modify
466+ * it under the terms of the GNU General Public License as published by
467+ * the Free Software Foundation; either version 2 of the License, or
468+ * (at your option) any later version.
dece6358
AM
469+ *
470+ * This program is distributed in the hope that it will be useful,
471+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
472+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
473+ * GNU General Public License for more details.
474+ *
475+ * You should have received a copy of the GNU General Public License
476+ * along with this program; if not, write to the Free Software
477+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 478+ */
479+
480+/*
481+ * all header files
482+ */
483+
484+#ifndef __AUFS_H__
485+#define __AUFS_H__
486+
487+#ifdef __KERNEL__
488+
4a4d8108
AM
489+#define AuStub(type, name, body, ...) \
490+ static inline type name(__VA_ARGS__) { body; }
491+
492+#define AuStubVoid(name, ...) \
493+ AuStub(void, name, , __VA_ARGS__)
494+#define AuStubInt0(name, ...) \
495+ AuStub(int, name, return 0, __VA_ARGS__)
496+
1facf9fc 497+#include "debug.h"
498+
499+#include "branch.h"
500+#include "cpup.h"
501+#include "dcsub.h"
502+#include "dbgaufs.h"
503+#include "dentry.h"
504+#include "dir.h"
4a4d8108 505+#include "dynop.h"
1facf9fc 506+#include "file.h"
507+#include "fstype.h"
508+#include "inode.h"
509+#include "loop.h"
510+#include "module.h"
4a4d8108 511+/* never include ./mtx.h */
1facf9fc 512+#include "opts.h"
513+#include "rwsem.h"
514+#include "spl.h"
515+#include "super.h"
516+#include "sysaufs.h"
517+#include "vfsub.h"
518+#include "whout.h"
519+#include "wkq.h"
520+
521+#endif /* __KERNEL__ */
522+#endif /* __AUFS_H__ */
b752ccd1
AM
523diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
524--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
525+++ linux/fs/aufs/branch.c 2010-08-21 21:00:02.972333781 +0200
526@@ -0,0 +1,1005 @@
1facf9fc 527+/*
4a4d8108 528+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 529+ *
530+ * This program, aufs is free software; you can redistribute it and/or modify
531+ * it under the terms of the GNU General Public License as published by
532+ * the Free Software Foundation; either version 2 of the License, or
533+ * (at your option) any later version.
dece6358
AM
534+ *
535+ * This program is distributed in the hope that it will be useful,
536+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
537+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
538+ * GNU General Public License for more details.
539+ *
540+ * You should have received a copy of the GNU General Public License
541+ * along with this program; if not, write to the Free Software
542+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 543+ */
544+
545+/*
546+ * branch management
547+ */
548+
dece6358 549+#include <linux/file.h>
4a4d8108 550+#include <linux/statfs.h>
1facf9fc 551+#include "aufs.h"
552+
553+/*
554+ * free a single branch
555+ */
556+static void au_br_do_free(struct au_branch *br)
557+{
558+ int i;
559+ struct au_wbr *wbr;
4a4d8108 560+ struct au_dykey **key;
1facf9fc 561+
562+ if (br->br_xino.xi_file)
563+ fput(br->br_xino.xi_file);
564+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
565+
566+ AuDebugOn(atomic_read(&br->br_count));
567+
568+ wbr = br->br_wbr;
569+ if (wbr) {
570+ for (i = 0; i < AuBrWh_Last; i++)
571+ dput(wbr->wbr_wh[i]);
572+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 573+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 574+ }
575+
4a4d8108
AM
576+ key = br->br_dykey;
577+ for (i = 0; i < AuBrDynOp; i++, key++)
578+ if (*key)
579+ au_dy_put(*key);
580+ else
581+ break;
582+
1facf9fc 583+ mntput(br->br_mnt);
1facf9fc 584+ kfree(wbr);
585+ kfree(br);
586+}
587+
588+/*
589+ * frees all branches
590+ */
591+void au_br_free(struct au_sbinfo *sbinfo)
592+{
593+ aufs_bindex_t bmax;
594+ struct au_branch **br;
595+
dece6358
AM
596+ AuRwMustWriteLock(&sbinfo->si_rwsem);
597+
1facf9fc 598+ bmax = sbinfo->si_bend + 1;
599+ br = sbinfo->si_branch;
600+ while (bmax--)
601+ au_br_do_free(*br++);
602+}
603+
604+/*
605+ * find the index of a branch which is specified by @br_id.
606+ */
607+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
608+{
609+ aufs_bindex_t bindex, bend;
610+
611+ bend = au_sbend(sb);
612+ for (bindex = 0; bindex <= bend; bindex++)
613+ if (au_sbr_id(sb, bindex) == br_id)
614+ return bindex;
615+ return -1;
616+}
617+
618+/* ---------------------------------------------------------------------- */
619+
620+/*
621+ * add a branch
622+ */
623+
b752ccd1
AM
624+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
625+ struct dentry *h_root)
1facf9fc 626+{
b752ccd1
AM
627+ if (unlikely(h_adding == h_root
628+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 629+ return 1;
b752ccd1
AM
630+ if (h_adding->d_sb != h_root->d_sb)
631+ return 0;
632+ return au_test_subdir(h_adding, h_root)
633+ || au_test_subdir(h_root, h_adding);
1facf9fc 634+}
635+
636+/*
637+ * returns a newly allocated branch. @new_nbranch is a number of branches
638+ * after adding a branch.
639+ */
640+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
641+ int perm)
642+{
643+ struct au_branch *add_branch;
644+ struct dentry *root;
4a4d8108 645+ int err;
1facf9fc 646+
4a4d8108 647+ err = -ENOMEM;
1facf9fc 648+ root = sb->s_root;
649+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
650+ if (unlikely(!add_branch))
651+ goto out;
652+
653+ add_branch->br_wbr = NULL;
654+ if (au_br_writable(perm)) {
655+ /* may be freed separately at changing the branch permission */
656+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
657+ GFP_NOFS);
658+ if (unlikely(!add_branch->br_wbr))
659+ goto out_br;
660+ }
661+
4a4d8108
AM
662+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
663+ if (!err)
664+ err = au_di_realloc(au_di(root), new_nbranch);
665+ if (!err)
666+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
667+ if (!err)
668+ return add_branch; /* success */
1facf9fc 669+
1facf9fc 670+ kfree(add_branch->br_wbr);
4a4d8108 671+
1facf9fc 672+ out_br:
673+ kfree(add_branch);
674+ out:
4a4d8108 675+ return ERR_PTR(err);
1facf9fc 676+}
677+
678+/*
679+ * test if the branch permission is legal or not.
680+ */
681+static int test_br(struct inode *inode, int brperm, char *path)
682+{
683+ int err;
684+
4a4d8108
AM
685+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
686+ if (!err)
687+ goto out;
1facf9fc 688+
4a4d8108
AM
689+ err = -EINVAL;
690+ pr_err("write permission for readonly mount or inode, %s\n", path);
691+
692+ out:
1facf9fc 693+ return err;
694+}
695+
696+/*
697+ * returns:
698+ * 0: success, the caller will add it
699+ * plus: success, it is already unified, the caller should ignore it
700+ * minus: error
701+ */
702+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
703+{
704+ int err;
705+ aufs_bindex_t bend, bindex;
706+ struct dentry *root;
707+ struct inode *inode, *h_inode;
708+
709+ root = sb->s_root;
710+ bend = au_sbend(sb);
711+ if (unlikely(bend >= 0
712+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
713+ err = 1;
714+ if (!remount) {
715+ err = -EINVAL;
4a4d8108 716+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 717+ }
718+ goto out;
719+ }
720+
721+ err = -ENOSPC; /* -E2BIG; */
722+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
723+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 724+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 725+ goto out;
726+ }
727+
728+ err = -EDOM;
729+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 730+ pr_err("bad index %d\n", add->bindex);
1facf9fc 731+ goto out;
732+ }
733+
734+ inode = add->path.dentry->d_inode;
735+ err = -ENOENT;
736+ if (unlikely(!inode->i_nlink)) {
4a4d8108 737+ pr_err("no existence %s\n", add->pathname);
1facf9fc 738+ goto out;
739+ }
740+
741+ err = -EINVAL;
742+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 743+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 744+ goto out;
745+ }
746+
747+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
748+ pr_err("unsupported filesystem, %s (%s)\n",
749+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 750+ goto out;
751+ }
752+
753+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
754+ if (unlikely(err))
755+ goto out;
756+
757+ if (bend < 0)
758+ return 0; /* success */
759+
760+ err = -EINVAL;
761+ for (bindex = 0; bindex <= bend; bindex++)
762+ if (unlikely(test_overlap(sb, add->path.dentry,
763+ au_h_dptr(root, bindex)))) {
4a4d8108 764+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 765+ goto out;
766+ }
767+
768+ err = 0;
769+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
770+ h_inode = au_h_dptr(root, 0)->d_inode;
771+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
772+ || h_inode->i_uid != inode->i_uid
773+ || h_inode->i_gid != inode->i_gid)
4a4d8108
AM
774+ pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
775+ add->pathname,
776+ inode->i_uid, inode->i_gid,
777+ (inode->i_mode & S_IALLUGO),
778+ h_inode->i_uid, h_inode->i_gid,
779+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 780+ }
781+
782+ out:
783+ return err;
784+}
785+
786+/*
787+ * initialize or clean the whiteouts for an adding branch
788+ */
789+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
790+ int new_perm, struct dentry *h_root)
791+{
792+ int err, old_perm;
793+ aufs_bindex_t bindex;
794+ struct mutex *h_mtx;
795+ struct au_wbr *wbr;
796+ struct au_hinode *hdir;
797+
798+ wbr = br->br_wbr;
799+ old_perm = br->br_perm;
800+ br->br_perm = new_perm;
801+ hdir = NULL;
802+ h_mtx = NULL;
803+ bindex = au_br_index(sb, br->br_id);
804+ if (0 <= bindex) {
805+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 806+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 807+ } else {
808+ h_mtx = &h_root->d_inode->i_mutex;
809+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
810+ }
811+ if (!wbr)
812+ err = au_wh_init(h_root, br, sb);
813+ else {
814+ wbr_wh_write_lock(wbr);
815+ err = au_wh_init(h_root, br, sb);
816+ wbr_wh_write_unlock(wbr);
817+ }
818+ if (hdir)
4a4d8108 819+ au_hn_imtx_unlock(hdir);
1facf9fc 820+ else
821+ mutex_unlock(h_mtx);
822+ br->br_perm = old_perm;
823+
824+ if (!err && wbr && !au_br_writable(new_perm)) {
825+ kfree(wbr);
826+ br->br_wbr = NULL;
827+ }
828+
829+ return err;
830+}
831+
832+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
833+ int perm, struct path *path)
834+{
835+ int err;
4a4d8108 836+ struct kstatfs kst;
1facf9fc 837+ struct au_wbr *wbr;
4a4d8108 838+ struct dentry *h_dentry;
1facf9fc 839+
840+ wbr = br->br_wbr;
dece6358 841+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 842+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
843+ atomic_set(&wbr->wbr_wh_running, 0);
844+ wbr->wbr_bytes = 0;
845+
4a4d8108
AM
846+ /*
847+ * a limit for rmdir/rename a dir
848+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
849+ */
850+ h_dentry = path->dentry;
851+ err = vfs_statfs(h_dentry, &kst);
852+ if (unlikely(err))
853+ goto out;
854+ err = -EINVAL;
855+ if (kst.f_namelen >= NAME_MAX)
856+ err = au_br_init_wh(sb, br, perm, h_dentry);
857+ else
858+ pr_err("%.*s(%s), unsupported namelen %ld\n",
859+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
860+ kst.f_namelen);
1facf9fc 861+
4a4d8108 862+ out:
1facf9fc 863+ return err;
864+}
865+
866+/* intialize a new branch */
867+static int au_br_init(struct au_branch *br, struct super_block *sb,
868+ struct au_opt_add *add)
869+{
870+ int err;
871+
872+ err = 0;
873+ memset(&br->br_xino, 0, sizeof(br->br_xino));
874+ mutex_init(&br->br_xino.xi_nondir_mtx);
875+ br->br_perm = add->perm;
876+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
877+ spin_lock_init(&br->br_dykey_lock);
878+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 879+ atomic_set(&br->br_count, 0);
880+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
881+ atomic_set(&br->br_xino_running, 0);
882+ br->br_id = au_new_br_id(sb);
883+
884+ if (au_br_writable(add->perm)) {
885+ err = au_wbr_init(br, sb, add->perm, &add->path);
886+ if (unlikely(err))
b752ccd1 887+ goto out_err;
1facf9fc 888+ }
889+
890+ if (au_opt_test(au_mntflags(sb), XINO)) {
891+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
892+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
893+ if (unlikely(err)) {
894+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 895+ goto out_err;
1facf9fc 896+ }
897+ }
898+
899+ sysaufs_br_init(br);
900+ mntget(add->path.mnt);
b752ccd1 901+ goto out; /* success */
1facf9fc 902+
b752ccd1
AM
903+ out_err:
904+ br->br_mnt = NULL;
1facf9fc 905+ out:
906+ return err;
907+}
908+
909+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
910+ struct au_branch *br, aufs_bindex_t bend,
911+ aufs_bindex_t amount)
912+{
913+ struct au_branch **brp;
914+
dece6358
AM
915+ AuRwMustWriteLock(&sbinfo->si_rwsem);
916+
1facf9fc 917+ brp = sbinfo->si_branch + bindex;
918+ memmove(brp + 1, brp, sizeof(*brp) * amount);
919+ *brp = br;
920+ sbinfo->si_bend++;
921+ if (unlikely(bend < 0))
922+ sbinfo->si_bend = 0;
923+}
924+
925+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
926+ aufs_bindex_t bend, aufs_bindex_t amount)
927+{
928+ struct au_hdentry *hdp;
929+
1308ab2a 930+ AuRwMustWriteLock(&dinfo->di_rwsem);
931+
1facf9fc 932+ hdp = dinfo->di_hdentry + bindex;
933+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
934+ au_h_dentry_init(hdp);
935+ dinfo->di_bend++;
936+ if (unlikely(bend < 0))
937+ dinfo->di_bstart = 0;
938+}
939+
940+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
941+ aufs_bindex_t bend, aufs_bindex_t amount)
942+{
943+ struct au_hinode *hip;
944+
1308ab2a 945+ AuRwMustWriteLock(&iinfo->ii_rwsem);
946+
1facf9fc 947+ hip = iinfo->ii_hinode + bindex;
948+ memmove(hip + 1, hip, sizeof(*hip) * amount);
949+ hip->hi_inode = NULL;
4a4d8108 950+ au_hn_init(hip);
1facf9fc 951+ iinfo->ii_bend++;
952+ if (unlikely(bend < 0))
953+ iinfo->ii_bstart = 0;
954+}
955+
956+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
957+ struct au_branch *br, aufs_bindex_t bindex)
958+{
959+ struct dentry *root;
960+ struct inode *root_inode;
961+ aufs_bindex_t bend, amount;
962+
963+ root = sb->s_root;
964+ root_inode = root->d_inode;
4a4d8108 965+ au_plink_maint_block(sb);
1facf9fc 966+ bend = au_sbend(sb);
967+ amount = bend + 1 - bindex;
968+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
969+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
970+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
971+ au_set_h_dptr(root, bindex, dget(h_dentry));
972+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
973+ /*flags*/0);
974+}
975+
976+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
977+{
978+ int err;
1facf9fc 979+ aufs_bindex_t bend, add_bindex;
980+ struct dentry *root, *h_dentry;
981+ struct inode *root_inode;
982+ struct au_branch *add_branch;
983+
984+ root = sb->s_root;
985+ root_inode = root->d_inode;
986+ IMustLock(root_inode);
987+ err = test_add(sb, add, remount);
988+ if (unlikely(err < 0))
989+ goto out;
990+ if (err) {
991+ err = 0;
992+ goto out; /* success */
993+ }
994+
995+ bend = au_sbend(sb);
996+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
997+ err = PTR_ERR(add_branch);
998+ if (IS_ERR(add_branch))
999+ goto out;
1000+
1001+ err = au_br_init(add_branch, sb, add);
1002+ if (unlikely(err)) {
1003+ au_br_do_free(add_branch);
1004+ goto out;
1005+ }
1006+
1007+ add_bindex = add->bindex;
1008+ h_dentry = add->path.dentry;
1009+ if (!remount)
1010+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1011+ else {
1012+ sysaufs_brs_del(sb, add_bindex);
1013+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1014+ sysaufs_brs_add(sb, add_bindex);
1015+ }
1016+
1308ab2a 1017+ if (!add_bindex) {
1facf9fc 1018+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 1019+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
1020+ } else
1facf9fc 1021+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 1022+
1023+ /*
4a4d8108 1024+ * this test/set prevents aufs from handling unnecesary notify events
1facf9fc 1025+ * of xino files, in a case of re-adding a writable branch which was
1026+ * once detached from aufs.
1027+ */
1028+ if (au_xino_brid(sb) < 0
1029+ && au_br_writable(add_branch->br_perm)
1030+ && !au_test_fs_bad_xino(h_dentry->d_sb)
1031+ && add_branch->br_xino.xi_file
1032+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
1033+ au_xino_brid_set(sb, add_branch->br_id);
1034+
1035+ out:
1036+ return err;
1037+}
1038+
1039+/* ---------------------------------------------------------------------- */
1040+
1041+/*
1042+ * delete a branch
1043+ */
1044+
1045+/* to show the line number, do not make it inlined function */
4a4d8108 1046+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 1047+ if (do_info) \
4a4d8108 1048+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 1049+} while (0)
1050+
1051+/*
1052+ * test if the branch is deletable or not.
1053+ */
1054+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 1055+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1056+{
1057+ int err, i, j, ndentry;
1058+ aufs_bindex_t bstart, bend;
1facf9fc 1059+ struct au_dcsub_pages dpages;
1060+ struct au_dpage *dpage;
1061+ struct dentry *d;
1062+ struct inode *inode;
1063+
1064+ err = au_dpages_init(&dpages, GFP_NOFS);
1065+ if (unlikely(err))
1066+ goto out;
1067+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
1068+ if (unlikely(err))
1069+ goto out_dpages;
1070+
1facf9fc 1071+ for (i = 0; !err && i < dpages.ndpage; i++) {
1072+ dpage = dpages.dpages + i;
1073+ ndentry = dpage->ndentry;
1074+ for (j = 0; !err && j < ndentry; j++) {
1075+ d = dpage->dentries[j];
1076+ AuDebugOn(!atomic_read(&d->d_count));
1077+ inode = d->d_inode;
1078+ if (au_digen(d) == sigen && au_iigen(inode) == sigen)
1079+ di_read_lock_child(d, AuLock_IR);
1080+ else {
1081+ di_write_lock_child(d);
1082+ err = au_reval_dpath(d, sigen);
1083+ if (!err)
1084+ di_downgrade_lock(d, AuLock_IR);
1085+ else {
1086+ di_write_unlock(d);
1087+ break;
1088+ }
1089+ }
1090+
1091+ bstart = au_dbstart(d);
1092+ bend = au_dbend(d);
1093+ if (bstart <= bindex
1094+ && bindex <= bend
1095+ && au_h_dptr(d, bindex)
1096+ && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
1097+ err = -EBUSY;
1098+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
1099+ }
1100+ di_read_unlock(d, AuLock_IR);
1101+ }
1102+ }
1103+
1104+ out_dpages:
1105+ au_dpages_free(&dpages);
1106+ out:
1107+ return err;
1108+}
1109+
1110+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 1111+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1112+{
1113+ int err;
1114+ struct inode *i;
1115+ aufs_bindex_t bstart, bend;
1facf9fc 1116+
1117+ err = 0;
1facf9fc 1118+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
1119+ AuDebugOn(!atomic_read(&i->i_count));
1120+ if (!list_empty(&i->i_dentry))
1121+ continue;
1122+
1123+ if (au_iigen(i) == sigen)
1124+ ii_read_lock_child(i);
1125+ else {
1126+ ii_write_lock_child(i);
1127+ err = au_refresh_hinode_self(i, /*do_attr*/1);
1128+ if (!err)
1129+ ii_downgrade_lock(i);
1130+ else {
1131+ ii_write_unlock(i);
1132+ break;
1133+ }
1134+ }
1135+
1136+ bstart = au_ibstart(i);
1137+ bend = au_ibend(i);
1138+ if (bstart <= bindex
1139+ && bindex <= bend
1140+ && au_h_iptr(i, bindex)
1141+ && (!S_ISDIR(i->i_mode) || bstart == bend)) {
1142+ err = -EBUSY;
1143+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
1144+ ii_read_unlock(i);
1145+ break;
1146+ }
1147+ ii_read_unlock(i);
1148+ }
1149+
1150+ return err;
1151+}
1152+
b752ccd1
AM
1153+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
1154+ const unsigned int verbose)
1facf9fc 1155+{
1156+ int err;
1157+ unsigned int sigen;
1158+
1159+ sigen = au_sigen(root->d_sb);
1160+ DiMustNoWaiters(root);
1161+ IiMustNoWaiters(root->d_inode);
1162+ di_write_unlock(root);
b752ccd1 1163+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 1164+ if (!err)
b752ccd1 1165+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 1166+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
1167+
1168+ return err;
1169+}
1170+
1171+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
1172+ const aufs_bindex_t bindex,
1173+ const aufs_bindex_t bend)
1174+{
1175+ struct au_branch **brp, **p;
1176+
dece6358
AM
1177+ AuRwMustWriteLock(&sbinfo->si_rwsem);
1178+
1facf9fc 1179+ brp = sbinfo->si_branch + bindex;
1180+ if (bindex < bend)
1181+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
1182+ sbinfo->si_branch[0 + bend] = NULL;
1183+ sbinfo->si_bend--;
1184+
1185+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
1186+ if (p)
1187+ sbinfo->si_branch = p;
4a4d8108 1188+ /* harmless error */
1facf9fc 1189+}
1190+
1191+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
1192+ const aufs_bindex_t bend)
1193+{
1194+ struct au_hdentry *hdp, *p;
1195+
1308ab2a 1196+ AuRwMustWriteLock(&dinfo->di_rwsem);
1197+
4a4d8108 1198+ hdp = dinfo->di_hdentry;
1facf9fc 1199+ if (bindex < bend)
4a4d8108
AM
1200+ memmove(hdp + bindex, hdp + bindex + 1,
1201+ sizeof(*hdp) * (bend - bindex));
1202+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 1203+ dinfo->di_bend--;
1204+
4a4d8108 1205+ p = krealloc(hdp, sizeof(*p) * bend, GFP_NOFS);
1facf9fc 1206+ if (p)
1207+ dinfo->di_hdentry = p;
4a4d8108 1208+ /* harmless error */
1facf9fc 1209+}
1210+
1211+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
1212+ const aufs_bindex_t bend)
1213+{
1214+ struct au_hinode *hip, *p;
1215+
1308ab2a 1216+ AuRwMustWriteLock(&iinfo->ii_rwsem);
1217+
1facf9fc 1218+ hip = iinfo->ii_hinode + bindex;
1219+ if (bindex < bend)
1220+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
1221+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 1222+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 1223+ iinfo->ii_bend--;
1224+
1225+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
1226+ if (p)
1227+ iinfo->ii_hinode = p;
4a4d8108 1228+ /* harmless error */
1facf9fc 1229+}
1230+
1231+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
1232+ struct au_branch *br)
1233+{
1234+ aufs_bindex_t bend;
1235+ struct au_sbinfo *sbinfo;
1236+ struct dentry *root;
1237+ struct inode *inode;
1238+
dece6358
AM
1239+ SiMustWriteLock(sb);
1240+
1facf9fc 1241+ root = sb->s_root;
1242+ inode = root->d_inode;
4a4d8108 1243+ au_plink_maint_block(sb);
1facf9fc 1244+ sbinfo = au_sbi(sb);
1245+ bend = sbinfo->si_bend;
1246+
1247+ dput(au_h_dptr(root, bindex));
1248+ au_hiput(au_hi(inode, bindex));
1249+ au_br_do_free(br);
1250+
1251+ au_br_do_del_brp(sbinfo, bindex, bend);
1252+ au_br_do_del_hdp(au_di(root), bindex, bend);
1253+ au_br_do_del_hip(au_ii(inode), bindex, bend);
1254+}
1255+
1256+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
1257+{
1258+ int err, rerr, i;
1259+ unsigned int mnt_flags;
1260+ aufs_bindex_t bindex, bend, br_id;
1261+ unsigned char do_wh, verbose;
1262+ struct au_branch *br;
1263+ struct au_wbr *wbr;
1264+
1265+ err = 0;
1266+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
1267+ if (bindex < 0) {
1268+ if (remount)
1269+ goto out; /* success */
1270+ err = -ENOENT;
4a4d8108 1271+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 1272+ goto out;
1273+ }
1274+ AuDbg("bindex b%d\n", bindex);
1275+
1276+ err = -EBUSY;
1277+ mnt_flags = au_mntflags(sb);
1278+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
1279+ bend = au_sbend(sb);
1280+ if (unlikely(!bend)) {
1281+ AuVerbose(verbose, "no more branches left\n");
1282+ goto out;
1283+ }
1284+ br = au_sbr(sb, bindex);
1285+ i = atomic_read(&br->br_count);
1286+ if (unlikely(i)) {
1287+ AuVerbose(verbose, "%d file(s) opened\n", i);
b752ccd1
AM
1288+ if (!verbose)
1289+ goto out;
1facf9fc 1290+ }
1291+
1292+ wbr = br->br_wbr;
1293+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
1294+ if (do_wh) {
1308ab2a 1295+ /* instead of WbrWhMustWriteLock(wbr) */
1296+ SiMustWriteLock(sb);
1facf9fc 1297+ for (i = 0; i < AuBrWh_Last; i++) {
1298+ dput(wbr->wbr_wh[i]);
1299+ wbr->wbr_wh[i] = NULL;
1300+ }
1301+ }
1302+
b752ccd1 1303+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 1304+ if (unlikely(err)) {
1305+ if (do_wh)
1306+ goto out_wh;
1307+ goto out;
1308+ }
1309+
1310+ err = 0;
1311+ br_id = br->br_id;
1312+ if (!remount)
1313+ au_br_do_del(sb, bindex, br);
1314+ else {
1315+ sysaufs_brs_del(sb, bindex);
1316+ au_br_do_del(sb, bindex, br);
1317+ sysaufs_brs_add(sb, bindex);
1318+ }
1319+
1308ab2a 1320+ if (!bindex) {
1facf9fc 1321+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 1322+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
1323+ } else
1facf9fc 1324+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
1325+ if (au_opt_test(mnt_flags, PLINK))
1326+ au_plink_half_refresh(sb, br_id);
1327+
b752ccd1 1328+ if (au_xino_brid(sb) == br_id)
1facf9fc 1329+ au_xino_brid_set(sb, -1);
1330+ goto out; /* success */
1331+
1332+ out_wh:
1333+ /* revert */
1334+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
1335+ if (rerr)
4a4d8108
AM
1336+ pr_warning("failed re-creating base whiteout, %s. (%d)\n",
1337+ del->pathname, rerr);
1facf9fc 1338+ out:
1339+ return err;
1340+}
1341+
1342+/* ---------------------------------------------------------------------- */
1343+
1344+/*
1345+ * change a branch permission
1346+ */
1347+
dece6358
AM
1348+static void au_warn_ima(void)
1349+{
1350+#ifdef CONFIG_IMA
1308ab2a 1351+ /* since it doesn't support mark_files_ro() */
4a4d8108 1352+ pr_warning("RW -> RO makes IMA to produce wrong message");
dece6358
AM
1353+#endif
1354+}
1355+
1facf9fc 1356+static int do_need_sigen_inc(int a, int b)
1357+{
1358+ return au_br_whable(a) && !au_br_whable(b);
1359+}
1360+
1361+static int need_sigen_inc(int old, int new)
1362+{
1363+ return do_need_sigen_inc(old, new)
1364+ || do_need_sigen_inc(new, old);
1365+}
1366+
1367+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
1368+{
1369+ int err;
1370+ unsigned long n, ul, bytes, files;
1371+ aufs_bindex_t bstart;
1372+ struct file *file, *hf, **a;
1373+ const int step_bytes = 1024, /* memory allocation unit */
1374+ step_files = step_bytes / sizeof(*a);
1375+
1376+ err = -ENOMEM;
1377+ n = 0;
1378+ bytes = step_bytes;
1379+ files = step_files;
1380+ a = kmalloc(bytes, GFP_NOFS);
1381+ if (unlikely(!a))
1382+ goto out;
1383+
1384+ /* no need file_list_lock() since sbinfo is locked? defered? */
1385+ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
1386+ if (special_file(file->f_dentry->d_inode->i_mode))
1387+ continue;
1388+
1389+ AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
1390+ fi_read_lock(file);
1391+ if (unlikely(au_test_mmapped(file))) {
1392+ err = -EBUSY;
1393+ FiMustNoWaiters(file);
1394+ fi_read_unlock(file);
1395+ goto out_free;
1396+ }
1397+
1398+ bstart = au_fbstart(file);
1399+ if (!S_ISREG(file->f_dentry->d_inode->i_mode)
1400+ || !(file->f_mode & FMODE_WRITE)
1401+ || bstart != bindex) {
1402+ FiMustNoWaiters(file);
1403+ fi_read_unlock(file);
1404+ continue;
1405+ }
1406+
4a4d8108 1407+ hf = au_hf_top(file);
1facf9fc 1408+ FiMustNoWaiters(file);
1409+ fi_read_unlock(file);
1410+
1411+ if (n < files)
1412+ a[n++] = hf;
1413+ else {
1414+ void *p;
1415+
1416+ err = -ENOMEM;
1417+ bytes += step_bytes;
1418+ files += step_files;
1419+ p = krealloc(a, bytes, GFP_NOFS);
1420+ if (p) {
1421+ a = p;
1422+ a[n++] = hf;
1423+ } else
1424+ goto out_free;
1425+ }
1426+ }
1427+
1428+ err = 0;
dece6358
AM
1429+ if (n)
1430+ au_warn_ima();
1facf9fc 1431+ for (ul = 0; ul < n; ul++) {
1432+ /* todo: already flushed? */
1433+ /* cf. fs/super.c:mark_files_ro() */
1434+ hf = a[ul];
1435+ hf->f_mode &= ~FMODE_WRITE;
1436+ if (!file_check_writeable(hf)) {
1437+ file_release_write(hf);
1438+ mnt_drop_write(hf->f_vfsmnt);
1439+ }
1440+ }
1441+
1442+ out_free:
1443+ kfree(a);
1444+ out:
1445+ return err;
1446+}
1447+
1448+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1449+ int *do_update)
1450+{
1451+ int err, rerr;
1452+ aufs_bindex_t bindex;
1308ab2a 1453+ struct path path;
1facf9fc 1454+ struct dentry *root;
1455+ struct au_branch *br;
1456+
1457+ root = sb->s_root;
4a4d8108 1458+ au_plink_maint_block(sb);
1facf9fc 1459+ bindex = au_find_dbindex(root, mod->h_root);
1460+ if (bindex < 0) {
1461+ if (remount)
1462+ return 0; /* success */
1463+ err = -ENOENT;
4a4d8108 1464+ pr_err("%s no such branch\n", mod->path);
1facf9fc 1465+ goto out;
1466+ }
1467+ AuDbg("bindex b%d\n", bindex);
1468+
1469+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
1470+ if (unlikely(err))
1471+ goto out;
1472+
1473+ br = au_sbr(sb, bindex);
1474+ if (br->br_perm == mod->perm)
1475+ return 0; /* success */
1476+
1477+ if (au_br_writable(br->br_perm)) {
1478+ /* remove whiteout base */
1479+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
1480+ if (unlikely(err))
1481+ goto out;
1482+
1483+ if (!au_br_writable(mod->perm)) {
1484+ /* rw --> ro, file might be mmapped */
1485+ DiMustNoWaiters(root);
1486+ IiMustNoWaiters(root->d_inode);
1487+ di_write_unlock(root);
1488+ err = au_br_mod_files_ro(sb, bindex);
1489+ /* aufs_write_lock() calls ..._child() */
1490+ di_write_lock_child(root);
1491+
1492+ if (unlikely(err)) {
1493+ rerr = -ENOMEM;
1494+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
1495+ GFP_NOFS);
1308ab2a 1496+ if (br->br_wbr) {
1497+ path.mnt = br->br_mnt;
1498+ path.dentry = mod->h_root;
1499+ rerr = au_wbr_init(br, sb, br->br_perm,
1500+ &path);
1501+ }
1facf9fc 1502+ if (unlikely(rerr)) {
1503+ AuIOErr("nested error %d (%d)\n",
1504+ rerr, err);
1505+ br->br_perm = mod->perm;
1506+ }
1507+ }
1508+ }
1509+ } else if (au_br_writable(mod->perm)) {
1510+ /* ro --> rw */
1511+ err = -ENOMEM;
1512+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1513+ if (br->br_wbr) {
1308ab2a 1514+ path.mnt = br->br_mnt;
1515+ path.dentry = mod->h_root;
1facf9fc 1516+ err = au_wbr_init(br, sb, mod->perm, &path);
1517+ if (unlikely(err)) {
1518+ kfree(br->br_wbr);
1519+ br->br_wbr = NULL;
1520+ }
1521+ }
1522+ }
1523+
1524+ if (!err) {
1525+ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
1526+ br->br_perm = mod->perm;
1527+ }
1528+
1529+ out:
1530+ return err;
1531+}
b752ccd1
AM
1532diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
1533--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
1534+++ linux/fs/aufs/branch.h 2010-08-21 21:00:02.972333781 +0200
1535@@ -0,0 +1,224 @@
1facf9fc 1536+/*
4a4d8108 1537+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1538+ *
1539+ * This program, aufs is free software; you can redistribute it and/or modify
1540+ * it under the terms of the GNU General Public License as published by
1541+ * the Free Software Foundation; either version 2 of the License, or
1542+ * (at your option) any later version.
dece6358
AM
1543+ *
1544+ * This program is distributed in the hope that it will be useful,
1545+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1546+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1547+ * GNU General Public License for more details.
1548+ *
1549+ * You should have received a copy of the GNU General Public License
1550+ * along with this program; if not, write to the Free Software
1551+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1552+ */
1553+
1554+/*
1555+ * branch filesystems and xino for them
1556+ */
1557+
1558+#ifndef __AUFS_BRANCH_H__
1559+#define __AUFS_BRANCH_H__
1560+
1561+#ifdef __KERNEL__
1562+
1563+#include <linux/fs.h>
1564+#include <linux/mount.h>
1facf9fc 1565+#include <linux/aufs_type.h>
4a4d8108 1566+#include "dynop.h"
1facf9fc 1567+#include "rwsem.h"
1568+#include "super.h"
1569+
1570+/* ---------------------------------------------------------------------- */
1571+
1572+/* a xino file */
1573+struct au_xino_file {
1574+ struct file *xi_file;
1575+ struct mutex xi_nondir_mtx;
1576+
1577+ /* todo: make xino files an array to support huge inode number */
1578+
1579+#ifdef CONFIG_DEBUG_FS
1580+ struct dentry *xi_dbgaufs;
1581+#endif
1582+};
1583+
1584+/* members for writable branch only */
1585+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
1586+struct au_wbr {
dece6358 1587+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 1588+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 1589+ atomic_t wbr_wh_running;
1facf9fc 1590+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
1591+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
1592+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
1593+
1594+ /* mfs mode */
1595+ unsigned long long wbr_bytes;
1596+};
1597+
4a4d8108
AM
1598+/* ext2 has 3 types of operations at least, ext3 has 4 */
1599+#define AuBrDynOp (AuDyLast * 4)
1600+
1facf9fc 1601+/* protected by superblock rwsem */
1602+struct au_branch {
1603+ struct au_xino_file br_xino;
1604+
1605+ aufs_bindex_t br_id;
1606+
1607+ int br_perm;
1608+ struct vfsmount *br_mnt;
4a4d8108
AM
1609+ spinlock_t br_dykey_lock;
1610+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 1611+ atomic_t br_count;
1612+
1613+ struct au_wbr *br_wbr;
1614+
1615+ /* xino truncation */
1616+ blkcnt_t br_xino_upper; /* watermark in blocks */
1617+ atomic_t br_xino_running;
1618+
1619+#ifdef CONFIG_SYSFS
1620+ /* an entry under sysfs per mount-point */
1621+ char br_name[8];
1622+ struct attribute br_attr;
1623+#endif
1624+};
1625+
1626+/* ---------------------------------------------------------------------- */
1627+
1628+/* branch permission and attribute */
1629+enum {
1630+ AuBrPerm_RW, /* writable, linkable wh */
1631+ AuBrPerm_RO, /* readonly, no wh */
1632+ AuBrPerm_RR, /* natively readonly, no wh */
1633+
1634+ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
1635+
1636+ AuBrPerm_ROWH, /* whiteout-able */
1637+ AuBrPerm_RRWH, /* whiteout-able */
1638+
1639+ AuBrPerm_Last
1640+};
1641+
1642+static inline int au_br_writable(int brperm)
1643+{
1644+ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1645+}
1646+
1647+static inline int au_br_whable(int brperm)
1648+{
1649+ return brperm == AuBrPerm_RW
1650+ || brperm == AuBrPerm_ROWH
1651+ || brperm == AuBrPerm_RRWH;
1652+}
1653+
1654+static inline int au_br_rdonly(struct au_branch *br)
1655+{
1656+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1657+ || !au_br_writable(br->br_perm))
1658+ ? -EROFS : 0;
1659+}
1660+
4a4d8108 1661+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 1662+{
4a4d8108 1663+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 1664+ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1665+#else
1666+ return 0;
1667+#endif
1668+}
1669+
1670+/* ---------------------------------------------------------------------- */
1671+
1672+/* branch.c */
1673+struct au_sbinfo;
1674+void au_br_free(struct au_sbinfo *sinfo);
1675+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1676+struct au_opt_add;
1677+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1678+struct au_opt_del;
1679+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
1680+struct au_opt_mod;
1681+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1682+ int *do_update);
1683+
1684+/* xino.c */
1685+static const loff_t au_loff_max = LLONG_MAX;
1686+
1687+int au_xib_trunc(struct super_block *sb);
1688+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1689+ loff_t *pos);
1690+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1691+ loff_t *pos);
1692+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
1693+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1694+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 1695+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 1696+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1697+ ino_t ino);
1698+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1699+ ino_t *ino);
1700+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1701+ struct file *base_file, int do_test);
1702+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1703+
1704+struct au_opt_xino;
1705+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1706+void au_xino_clr(struct super_block *sb);
1707+struct file *au_xino_def(struct super_block *sb);
1708+int au_xino_path(struct seq_file *seq, struct file *file);
1709+
1710+/* ---------------------------------------------------------------------- */
1711+
1712+/* Superblock to branch */
1713+static inline
1714+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1715+{
1716+ return au_sbr(sb, bindex)->br_id;
1717+}
1718+
1719+static inline
1720+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1721+{
1722+ return au_sbr(sb, bindex)->br_mnt;
1723+}
1724+
1725+static inline
1726+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1727+{
1728+ return au_sbr_mnt(sb, bindex)->mnt_sb;
1729+}
1730+
1731+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1732+{
dece6358 1733+ atomic_dec_return(&au_sbr(sb, bindex)->br_count);
1facf9fc 1734+}
1735+
1736+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1737+{
1738+ return au_sbr(sb, bindex)->br_perm;
1739+}
1740+
1741+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1742+{
1743+ return au_br_whable(au_sbr_perm(sb, bindex));
1744+}
1745+
1746+/* ---------------------------------------------------------------------- */
1747+
1748+/*
1749+ * wbr_wh_read_lock, wbr_wh_write_lock
1750+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
1751+ */
1752+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
1753+
dece6358
AM
1754+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
1755+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
1756+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
1757+
1facf9fc 1758+#endif /* __KERNEL__ */
1759+#endif /* __AUFS_BRANCH_H__ */
b752ccd1
AM
1760diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
1761--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
1762+++ linux/fs/aufs/conf.mk 2010-08-21 21:00:02.972333781 +0200
1763@@ -0,0 +1,36 @@
4a4d8108
AM
1764+
1765+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
1766+
1767+define AuConf
1768+ifdef ${1}
1769+AuConfStr += ${1}=${${1}}
1770+endif
1771+endef
1772+
b752ccd1 1773+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
4a4d8108
AM
1774+ HNOTIFY HFSNOTIFY HINOTIFY \
1775+ EXPORT INO_T_64 \
1776+ RDU \
1777+ SP_IATTR \
1778+ SHWH \
1779+ BR_RAMFS \
1780+ BR_FUSE POLL \
1781+ BR_HFSPLUS \
1782+ BDEV_LOOP \
b752ccd1
AM
1783+ DEBUG MAGIC_SYSRQ
1784+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
1785+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
1786+
1787+AuConfName = ${obj}/conf.str
1788+${AuConfName}.tmp: FORCE
1789+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
1790+${AuConfName}: ${AuConfName}.tmp
1791+ @diff -q $< $@ > /dev/null 2>&1 || { \
1792+ echo ' GEN ' $@; \
1793+ cp -p $< $@; \
1794+ }
1795+FORCE:
1796+clean-files += ${AuConfName} ${AuConfName}.tmp
1797+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
1798+
1799+-include ${srctree}/${src}/conf_priv.mk
1800diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
1801--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
1802+++ linux/fs/aufs/cpup.c 2010-08-21 21:00:02.972333781 +0200
1803@@ -0,0 +1,1059 @@
1facf9fc 1804+/*
4a4d8108 1805+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1806+ *
1807+ * This program, aufs is free software; you can redistribute it and/or modify
1808+ * it under the terms of the GNU General Public License as published by
1809+ * the Free Software Foundation; either version 2 of the License, or
1810+ * (at your option) any later version.
dece6358
AM
1811+ *
1812+ * This program is distributed in the hope that it will be useful,
1813+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1814+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1815+ * GNU General Public License for more details.
1816+ *
1817+ * You should have received a copy of the GNU General Public License
1818+ * along with this program; if not, write to the Free Software
1819+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1820+ */
1821+
1822+/*
1823+ * copy-up functions, see wbr_policy.c for copy-down
1824+ */
1825+
dece6358 1826+#include <linux/file.h>
1facf9fc 1827+#include <linux/fs_stack.h>
dece6358 1828+#include <linux/mm.h>
1facf9fc 1829+#include <linux/uaccess.h>
1830+#include "aufs.h"
1831+
1832+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
1833+{
1834+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
1835+ | S_NOATIME | S_NOCMTIME;
1836+
1837+ dst->i_flags |= src->i_flags & ~mask;
1838+ if (au_test_fs_notime(dst->i_sb))
1839+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
1840+}
1841+
1842+void au_cpup_attr_timesizes(struct inode *inode)
1843+{
1844+ struct inode *h_inode;
1845+
1846+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1847+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 1848+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 1849+}
1850+
1851+void au_cpup_attr_nlink(struct inode *inode, int force)
1852+{
1853+ struct inode *h_inode;
1854+ struct super_block *sb;
1855+ aufs_bindex_t bindex, bend;
1856+
1857+ sb = inode->i_sb;
1858+ bindex = au_ibstart(inode);
1859+ h_inode = au_h_iptr(inode, bindex);
1860+ if (!force
1861+ && !S_ISDIR(h_inode->i_mode)
1862+ && au_opt_test(au_mntflags(sb), PLINK)
1863+ && au_plink_test(inode))
1864+ return;
1865+
1866+ inode->i_nlink = h_inode->i_nlink;
1867+
1868+ /*
1869+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
1870+ * it may includes whplink directory.
1871+ */
1872+ if (S_ISDIR(h_inode->i_mode)) {
1873+ bend = au_ibend(inode);
1874+ for (bindex++; bindex <= bend; bindex++) {
1875+ h_inode = au_h_iptr(inode, bindex);
1876+ if (h_inode)
1877+ au_add_nlink(inode, h_inode);
1878+ }
1879+ }
1880+}
1881+
1882+void au_cpup_attr_changeable(struct inode *inode)
1883+{
1884+ struct inode *h_inode;
1885+
1886+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1887+ inode->i_mode = h_inode->i_mode;
1888+ inode->i_uid = h_inode->i_uid;
1889+ inode->i_gid = h_inode->i_gid;
1890+ au_cpup_attr_timesizes(inode);
1891+ au_cpup_attr_flags(inode, h_inode);
1892+}
1893+
1894+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
1895+{
1896+ struct au_iinfo *iinfo = au_ii(inode);
1897+
1308ab2a 1898+ IiMustWriteLock(inode);
1899+
1facf9fc 1900+ iinfo->ii_higen = h_inode->i_generation;
1901+ iinfo->ii_hsb1 = h_inode->i_sb;
1902+}
1903+
1904+void au_cpup_attr_all(struct inode *inode, int force)
1905+{
1906+ struct inode *h_inode;
1907+
1908+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1909+ au_cpup_attr_changeable(inode);
1910+ if (inode->i_nlink > 0)
1911+ au_cpup_attr_nlink(inode, force);
1912+ inode->i_rdev = h_inode->i_rdev;
1913+ inode->i_blkbits = h_inode->i_blkbits;
1914+ au_cpup_igen(inode, h_inode);
1915+}
1916+
1917+/* ---------------------------------------------------------------------- */
1918+
1919+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
1920+
1921+/* keep the timestamps of the parent dir when cpup */
1922+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
1923+ struct path *h_path)
1924+{
1925+ struct inode *h_inode;
1926+
1927+ dt->dt_dentry = dentry;
1928+ dt->dt_h_path = *h_path;
1929+ h_inode = h_path->dentry->d_inode;
1930+ dt->dt_atime = h_inode->i_atime;
1931+ dt->dt_mtime = h_inode->i_mtime;
1932+ /* smp_mb(); */
1933+}
1934+
1935+void au_dtime_revert(struct au_dtime *dt)
1936+{
1937+ struct iattr attr;
1938+ int err;
1939+
1940+ attr.ia_atime = dt->dt_atime;
1941+ attr.ia_mtime = dt->dt_mtime;
1942+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
1943+ | ATTR_ATIME | ATTR_ATIME_SET;
1944+
1945+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
1946+ if (unlikely(err))
4a4d8108 1947+ pr_warning("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 1948+}
1949+
1950+/* ---------------------------------------------------------------------- */
1951+
1952+static noinline_for_stack
1953+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
1954+{
1955+ int err, sbits;
1956+ struct iattr ia;
1957+ struct path h_path;
1308ab2a 1958+ struct inode *h_isrc, *h_idst;
1facf9fc 1959+
1960+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 1961+ h_idst = h_path.dentry->d_inode;
1facf9fc 1962+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
1963+ h_isrc = h_src->d_inode;
1308ab2a 1964+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 1965+ | ATTR_ATIME | ATTR_MTIME
1966+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 1967+ ia.ia_uid = h_isrc->i_uid;
1968+ ia.ia_gid = h_isrc->i_gid;
1969+ ia.ia_atime = h_isrc->i_atime;
1970+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 1971+ if (h_idst->i_mode != h_isrc->i_mode
1972+ && !S_ISLNK(h_idst->i_mode)) {
1973+ ia.ia_valid |= ATTR_MODE;
1974+ ia.ia_mode = h_isrc->i_mode;
1975+ }
1976+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
1977+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 1978+ err = vfsub_notify_change(&h_path, &ia);
1979+
1980+ /* is this nfs only? */
1981+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
1982+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
1983+ ia.ia_mode = h_isrc->i_mode;
1984+ err = vfsub_notify_change(&h_path, &ia);
1985+ }
1986+
1987+ return err;
1988+}
1989+
1990+/* ---------------------------------------------------------------------- */
1991+
1992+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
1993+ char *buf, unsigned long blksize)
1994+{
1995+ int err;
1996+ size_t sz, rbytes, wbytes;
1997+ unsigned char all_zero;
1998+ char *p, *zp;
1999+ struct mutex *h_mtx;
2000+ /* reduce stack usage */
2001+ struct iattr *ia;
2002+
2003+ zp = page_address(ZERO_PAGE(0));
2004+ if (unlikely(!zp))
2005+ return -ENOMEM; /* possible? */
2006+
2007+ err = 0;
2008+ all_zero = 0;
2009+ while (len) {
2010+ AuDbg("len %lld\n", len);
2011+ sz = blksize;
2012+ if (len < blksize)
2013+ sz = len;
2014+
2015+ rbytes = 0;
2016+ /* todo: signal_pending? */
2017+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
2018+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
2019+ err = rbytes;
2020+ }
2021+ if (unlikely(err < 0))
2022+ break;
2023+
2024+ all_zero = 0;
2025+ if (len >= rbytes && rbytes == blksize)
2026+ all_zero = !memcmp(buf, zp, rbytes);
2027+ if (!all_zero) {
2028+ wbytes = rbytes;
2029+ p = buf;
2030+ while (wbytes) {
2031+ size_t b;
2032+
2033+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
2034+ err = b;
2035+ /* todo: signal_pending? */
2036+ if (unlikely(err == -EAGAIN || err == -EINTR))
2037+ continue;
2038+ if (unlikely(err < 0))
2039+ break;
2040+ wbytes -= b;
2041+ p += b;
2042+ }
2043+ } else {
2044+ loff_t res;
2045+
2046+ AuLabel(hole);
2047+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
2048+ err = res;
2049+ if (unlikely(res < 0))
2050+ break;
2051+ }
2052+ len -= rbytes;
2053+ err = 0;
2054+ }
2055+
2056+ /* the last block may be a hole */
2057+ if (!err && all_zero) {
2058+ AuLabel(last hole);
2059+
2060+ err = 1;
2061+ if (au_test_nfs(dst->f_dentry->d_sb)) {
2062+ /* nfs requires this step to make last hole */
2063+ /* is this only nfs? */
2064+ do {
2065+ /* todo: signal_pending? */
2066+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
2067+ } while (err == -EAGAIN || err == -EINTR);
2068+ if (err == 1)
2069+ dst->f_pos--;
2070+ }
2071+
2072+ if (err == 1) {
2073+ ia = (void *)buf;
2074+ ia->ia_size = dst->f_pos;
2075+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
2076+ ia->ia_file = dst;
2077+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
2078+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
2079+ err = vfsub_notify_change(&dst->f_path, ia);
2080+ mutex_unlock(h_mtx);
2081+ }
2082+ }
2083+
2084+ return err;
2085+}
2086+
2087+int au_copy_file(struct file *dst, struct file *src, loff_t len)
2088+{
2089+ int err;
2090+ unsigned long blksize;
2091+ unsigned char do_kfree;
2092+ char *buf;
2093+
2094+ err = -ENOMEM;
2095+ blksize = dst->f_dentry->d_sb->s_blocksize;
2096+ if (!blksize || PAGE_SIZE < blksize)
2097+ blksize = PAGE_SIZE;
2098+ AuDbg("blksize %lu\n", blksize);
2099+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
2100+ if (do_kfree)
2101+ buf = kmalloc(blksize, GFP_NOFS);
2102+ else
2103+ buf = (void *)__get_free_page(GFP_NOFS);
2104+ if (unlikely(!buf))
2105+ goto out;
2106+
2107+ if (len > (1 << 22))
2108+ AuDbg("copying a large file %lld\n", (long long)len);
2109+
2110+ src->f_pos = 0;
2111+ dst->f_pos = 0;
2112+ err = au_do_copy_file(dst, src, len, buf, blksize);
2113+ if (do_kfree)
2114+ kfree(buf);
2115+ else
2116+ free_page((unsigned long)buf);
2117+
2118+ out:
2119+ return err;
2120+}
2121+
2122+/*
2123+ * to support a sparse file which is opened with O_APPEND,
2124+ * we need to close the file.
2125+ */
2126+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 2127+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 2128+{
2129+ int err, i;
2130+ enum { SRC, DST };
2131+ struct {
2132+ aufs_bindex_t bindex;
2133+ unsigned int flags;
2134+ struct dentry *dentry;
2135+ struct file *file;
2136+ void *label, *label_file;
2137+ } *f, file[] = {
2138+ {
2139+ .bindex = bsrc,
2140+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
2141+ .file = NULL,
2142+ .label = &&out,
2143+ .label_file = &&out_src
2144+ },
2145+ {
2146+ .bindex = bdst,
2147+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
2148+ .file = NULL,
2149+ .label = &&out_src,
2150+ .label_file = &&out_dst
2151+ }
2152+ };
2153+ struct super_block *sb;
2154+
2155+ /* bsrc branch can be ro/rw. */
2156+ sb = dentry->d_sb;
2157+ f = file;
2158+ for (i = 0; i < 2; i++, f++) {
2159+ f->dentry = au_h_dptr(dentry, f->bindex);
2160+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
2161+ err = PTR_ERR(f->file);
2162+ if (IS_ERR(f->file))
2163+ goto *f->label;
2164+ err = -EINVAL;
2165+ if (unlikely(!f->file->f_op))
2166+ goto *f->label_file;
2167+ }
2168+
2169+ /* try stopping to update while we copyup */
2170+ IMustLock(file[SRC].dentry->d_inode);
2171+ err = au_copy_file(file[DST].file, file[SRC].file, len);
2172+
2173+ out_dst:
2174+ fput(file[DST].file);
2175+ au_sbr_put(sb, file[DST].bindex);
2176+ out_src:
2177+ fput(file[SRC].file);
2178+ au_sbr_put(sb, file[SRC].bindex);
2179+ out:
2180+ return err;
2181+}
2182+
2183+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
2184+ aufs_bindex_t bsrc, loff_t len,
2185+ struct inode *h_dir, struct path *h_path)
2186+{
2187+ int err, rerr;
2188+ loff_t l;
2189+
2190+ err = 0;
2191+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
2192+ if (len == -1 || l < len)
2193+ len = l;
2194+ if (len)
2195+ err = au_cp_regular(dentry, bdst, bsrc, len);
2196+ if (!err)
2197+ goto out; /* success */
2198+
2199+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
2200+ if (rerr) {
2201+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
2202+ AuDLNPair(h_path->dentry), err, rerr);
2203+ err = -EIO;
2204+ }
2205+
2206+ out:
2207+ return err;
2208+}
2209+
2210+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
2211+ struct inode *h_dir)
2212+{
2213+ int err, symlen;
2214+ mm_segment_t old_fs;
b752ccd1
AM
2215+ union {
2216+ char *k;
2217+ char __user *u;
2218+ } sym;
1facf9fc 2219+
2220+ err = -ENOSYS;
2221+ if (unlikely(!h_src->d_inode->i_op->readlink))
2222+ goto out;
2223+
2224+ err = -ENOMEM;
b752ccd1
AM
2225+ sym.k = __getname_gfp(GFP_NOFS);
2226+ if (unlikely(!sym.k))
1facf9fc 2227+ goto out;
2228+
2229+ old_fs = get_fs();
2230+ set_fs(KERNEL_DS);
b752ccd1 2231+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 2232+ err = symlen;
2233+ set_fs(old_fs);
2234+
2235+ if (symlen > 0) {
b752ccd1
AM
2236+ sym.k[symlen] = 0;
2237+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 2238+ }
b752ccd1 2239+ __putname(sym.k);
1facf9fc 2240+
2241+ out:
2242+ return err;
2243+}
2244+
2245+/* return with the lower dst inode is locked */
2246+static noinline_for_stack
2247+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
2248+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2249+ struct dentry *dst_parent)
2250+{
2251+ int err;
2252+ umode_t mode;
2253+ unsigned int mnt_flags;
2254+ unsigned char isdir;
2255+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
2256+ struct au_dtime dt;
2257+ struct path h_path;
2258+ struct dentry *h_src, *h_dst, *h_parent;
2259+ struct inode *h_inode, *h_dir;
2260+ struct super_block *sb;
2261+
2262+ /* bsrc branch can be ro/rw. */
2263+ h_src = au_h_dptr(dentry, bsrc);
2264+ h_inode = h_src->d_inode;
2265+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
2266+
2267+ /* try stopping to be referenced while we are creating */
2268+ h_dst = au_h_dptr(dentry, bdst);
2269+ h_parent = h_dst->d_parent; /* dir inode is locked */
2270+ h_dir = h_parent->d_inode;
2271+ IMustLock(h_dir);
2272+ AuDebugOn(h_parent != h_dst->d_parent);
2273+
2274+ sb = dentry->d_sb;
2275+ h_path.mnt = au_sbr_mnt(sb, bdst);
2276+ if (do_dt) {
2277+ h_path.dentry = h_parent;
2278+ au_dtime_store(&dt, dst_parent, &h_path);
2279+ }
2280+ h_path.dentry = h_dst;
2281+
2282+ isdir = 0;
2283+ mode = h_inode->i_mode;
2284+ switch (mode & S_IFMT) {
2285+ case S_IFREG:
2286+ /* try stopping to update while we are referencing */
2287+ IMustLock(h_inode);
2288+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
2289+ if (!err)
2290+ err = au_do_cpup_regular
2291+ (dentry, bdst, bsrc, len,
2292+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
2293+ break;
2294+ case S_IFDIR:
2295+ isdir = 1;
2296+ err = vfsub_mkdir(h_dir, &h_path, mode);
2297+ if (!err) {
2298+ /*
2299+ * strange behaviour from the users view,
2300+ * particularry setattr case
2301+ */
2302+ if (au_ibstart(dst_parent->d_inode) == bdst)
2303+ au_cpup_attr_nlink(dst_parent->d_inode,
2304+ /*force*/1);
2305+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
2306+ }
2307+ break;
2308+ case S_IFLNK:
2309+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
2310+ break;
2311+ case S_IFCHR:
2312+ case S_IFBLK:
2313+ AuDebugOn(!capable(CAP_MKNOD));
2314+ /*FALLTHROUGH*/
2315+ case S_IFIFO:
2316+ case S_IFSOCK:
2317+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
2318+ break;
2319+ default:
2320+ AuIOErr("Unknown inode type 0%o\n", mode);
2321+ err = -EIO;
2322+ }
2323+
2324+ mnt_flags = au_mntflags(sb);
2325+ if (!au_opt_test(mnt_flags, UDBA_NONE)
2326+ && !isdir
2327+ && au_opt_test(mnt_flags, XINO)
2328+ && h_inode->i_nlink == 1
2329+ /* todo: unnecessary? */
2330+ /* && dentry->d_inode->i_nlink == 1 */
2331+ && bdst < bsrc
2332+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 2333+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 2334+ /* ignore this error */
2335+
2336+ if (do_dt)
2337+ au_dtime_revert(&dt);
2338+ return err;
2339+}
2340+
2341+/*
2342+ * copyup the @dentry from @bsrc to @bdst.
2343+ * the caller must set the both of lower dentries.
2344+ * @len is for truncating when it is -1 copyup the entire file.
2345+ * in link/rename cases, @dst_parent may be different from the real one.
2346+ */
2347+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2348+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2349+ struct dentry *dst_parent)
2350+{
2351+ int err, rerr;
2352+ aufs_bindex_t old_ibstart;
2353+ unsigned char isdir, plink;
2354+ struct au_dtime dt;
2355+ struct path h_path;
2356+ struct dentry *h_src, *h_dst, *h_parent;
2357+ struct inode *dst_inode, *h_dir, *inode;
2358+ struct super_block *sb;
2359+
2360+ AuDebugOn(bsrc <= bdst);
2361+
2362+ sb = dentry->d_sb;
2363+ h_path.mnt = au_sbr_mnt(sb, bdst);
2364+ h_dst = au_h_dptr(dentry, bdst);
2365+ h_parent = h_dst->d_parent; /* dir inode is locked */
2366+ h_dir = h_parent->d_inode;
2367+ IMustLock(h_dir);
2368+
2369+ h_src = au_h_dptr(dentry, bsrc);
2370+ inode = dentry->d_inode;
2371+
2372+ if (!dst_parent)
2373+ dst_parent = dget_parent(dentry);
2374+ else
2375+ dget(dst_parent);
2376+
2377+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
2378+ dst_inode = au_h_iptr(inode, bdst);
2379+ if (dst_inode) {
2380+ if (unlikely(!plink)) {
2381+ err = -EIO;
2382+ AuIOErr("i%lu exists on a upper branch "
2383+ "but plink is disabled\n", inode->i_ino);
2384+ goto out;
2385+ }
2386+
2387+ if (dst_inode->i_nlink) {
2388+ const int do_dt = au_ftest_cpup(flags, DTIME);
2389+
2390+ h_src = au_plink_lkup(inode, bdst);
2391+ err = PTR_ERR(h_src);
2392+ if (IS_ERR(h_src))
2393+ goto out;
2394+ if (unlikely(!h_src->d_inode)) {
2395+ err = -EIO;
2396+ AuIOErr("i%lu exists on a upper branch "
2397+ "but plink is broken\n", inode->i_ino);
2398+ dput(h_src);
2399+ goto out;
2400+ }
2401+
2402+ if (do_dt) {
2403+ h_path.dentry = h_parent;
2404+ au_dtime_store(&dt, dst_parent, &h_path);
2405+ }
2406+ h_path.dentry = h_dst;
2407+ err = vfsub_link(h_src, h_dir, &h_path);
2408+ if (do_dt)
2409+ au_dtime_revert(&dt);
2410+ dput(h_src);
2411+ goto out;
2412+ } else
2413+ /* todo: cpup_wh_file? */
2414+ /* udba work */
4a4d8108 2415+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 2416+ }
2417+
2418+ old_ibstart = au_ibstart(inode);
2419+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
2420+ if (unlikely(err))
2421+ goto out;
2422+ dst_inode = h_dst->d_inode;
2423+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
2424+
2425+ err = cpup_iattr(dentry, bdst, h_src);
2426+ isdir = S_ISDIR(dst_inode->i_mode);
2427+ if (!err) {
4a4d8108
AM
2428+ if (bdst < old_ibstart) {
2429+ if (S_ISREG(inode->i_mode)) {
2430+ err = au_dy_iaop(inode, bdst, dst_inode);
2431+ if (unlikely(err))
2432+ goto out_rev;
2433+ }
1facf9fc 2434+ au_set_ibstart(inode, bdst);
4a4d8108 2435+ }
1facf9fc 2436+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
2437+ au_hi_flags(inode, isdir));
2438+ mutex_unlock(&dst_inode->i_mutex);
2439+ if (!isdir
2440+ && h_src->d_inode->i_nlink > 1
2441+ && plink)
2442+ au_plink_append(inode, bdst, h_dst);
2443+ goto out; /* success */
2444+ }
2445+
2446+ /* revert */
4a4d8108 2447+out_rev:
1facf9fc 2448+ h_path.dentry = h_parent;
2449+ mutex_unlock(&dst_inode->i_mutex);
2450+ au_dtime_store(&dt, dst_parent, &h_path);
2451+ h_path.dentry = h_dst;
2452+ if (!isdir)
2453+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
2454+ else
2455+ rerr = vfsub_rmdir(h_dir, &h_path);
2456+ au_dtime_revert(&dt);
2457+ if (rerr) {
2458+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
2459+ err = -EIO;
2460+ }
2461+
2462+ out:
2463+ dput(dst_parent);
2464+ return err;
2465+}
2466+
2467+struct au_cpup_single_args {
2468+ int *errp;
2469+ struct dentry *dentry;
2470+ aufs_bindex_t bdst, bsrc;
2471+ loff_t len;
2472+ unsigned int flags;
2473+ struct dentry *dst_parent;
2474+};
2475+
2476+static void au_call_cpup_single(void *args)
2477+{
2478+ struct au_cpup_single_args *a = args;
2479+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
2480+ a->flags, a->dst_parent);
2481+}
2482+
2483+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2484+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2485+ struct dentry *dst_parent)
2486+{
2487+ int err, wkq_err;
2488+ umode_t mode;
2489+ struct dentry *h_dentry;
2490+
2491+ h_dentry = au_h_dptr(dentry, bsrc);
2492+ mode = h_dentry->d_inode->i_mode & S_IFMT;
2493+ if ((mode != S_IFCHR && mode != S_IFBLK)
2494+ || capable(CAP_MKNOD))
2495+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2496+ dst_parent);
2497+ else {
2498+ struct au_cpup_single_args args = {
2499+ .errp = &err,
2500+ .dentry = dentry,
2501+ .bdst = bdst,
2502+ .bsrc = bsrc,
2503+ .len = len,
2504+ .flags = flags,
2505+ .dst_parent = dst_parent
2506+ };
2507+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
2508+ if (unlikely(wkq_err))
2509+ err = wkq_err;
2510+ }
2511+
2512+ return err;
2513+}
2514+
2515+/*
2516+ * copyup the @dentry from the first active lower branch to @bdst,
2517+ * using au_cpup_single().
2518+ */
2519+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2520+ unsigned int flags)
2521+{
2522+ int err;
2523+ aufs_bindex_t bsrc, bend;
2524+
2525+ bend = au_dbend(dentry);
2526+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2527+ if (au_h_dptr(dentry, bsrc))
2528+ break;
2529+
2530+ err = au_lkup_neg(dentry, bdst);
2531+ if (!err) {
2532+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
2533+ if (!err)
2534+ return 0; /* success */
2535+
2536+ /* revert */
2537+ au_set_h_dptr(dentry, bdst, NULL);
2538+ au_set_dbstart(dentry, bsrc);
2539+ }
2540+
2541+ return err;
2542+}
2543+
2544+struct au_cpup_simple_args {
2545+ int *errp;
2546+ struct dentry *dentry;
2547+ aufs_bindex_t bdst;
2548+ loff_t len;
2549+ unsigned int flags;
2550+};
2551+
2552+static void au_call_cpup_simple(void *args)
2553+{
2554+ struct au_cpup_simple_args *a = args;
2555+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
2556+}
2557+
2558+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2559+ unsigned int flags)
2560+{
2561+ int err, wkq_err;
2562+ unsigned char do_sio;
2563+ struct dentry *parent;
2564+ struct inode *h_dir;
2565+
2566+ parent = dget_parent(dentry);
2567+ h_dir = au_h_iptr(parent->d_inode, bdst);
2568+ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
2569+ if (!do_sio) {
2570+ /*
2571+ * testing CAP_MKNOD is for generic fs,
2572+ * but CAP_FSETID is for xfs only, currently.
2573+ */
2574+ umode_t mode = dentry->d_inode->i_mode;
2575+ do_sio = (((mode & (S_IFCHR | S_IFBLK))
2576+ && !capable(CAP_MKNOD))
2577+ || ((mode & (S_ISUID | S_ISGID))
2578+ && !capable(CAP_FSETID)));
2579+ }
2580+ if (!do_sio)
2581+ err = au_cpup_simple(dentry, bdst, len, flags);
2582+ else {
2583+ struct au_cpup_simple_args args = {
2584+ .errp = &err,
2585+ .dentry = dentry,
2586+ .bdst = bdst,
2587+ .len = len,
2588+ .flags = flags
2589+ };
2590+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
2591+ if (unlikely(wkq_err))
2592+ err = wkq_err;
2593+ }
2594+
2595+ dput(parent);
2596+ return err;
2597+}
2598+
2599+/* ---------------------------------------------------------------------- */
2600+
2601+/*
2602+ * copyup the deleted file for writing.
2603+ */
2604+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2605+ struct dentry *wh_dentry, struct file *file,
2606+ loff_t len)
2607+{
2608+ int err;
2609+ aufs_bindex_t bstart;
2610+ struct au_dinfo *dinfo;
2611+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 2612+ struct au_hdentry *hdp;
1facf9fc 2613+
2614+ dinfo = au_di(dentry);
1308ab2a 2615+ AuRwMustWriteLock(&dinfo->di_rwsem);
2616+
1facf9fc 2617+ bstart = dinfo->di_bstart;
4a4d8108
AM
2618+ hdp = dinfo->di_hdentry;
2619+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 2620+ dinfo->di_bstart = bdst;
4a4d8108
AM
2621+ hdp[0 + bdst].hd_dentry = wh_dentry;
2622+ h_d_start = hdp[0 + bstart].hd_dentry;
1facf9fc 2623+ if (file)
4a4d8108 2624+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2625+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2626+ /*h_parent*/NULL);
2627+ if (!err && file) {
2628+ err = au_reopen_nondir(file);
4a4d8108 2629+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 2630+ }
4a4d8108 2631+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 2632+ dinfo->di_bstart = bstart;
2633+
2634+ return err;
2635+}
2636+
2637+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2638+ struct file *file)
2639+{
2640+ int err;
2641+ struct au_dtime dt;
2642+ struct dentry *parent, *h_parent, *wh_dentry;
2643+ struct au_branch *br;
2644+ struct path h_path;
2645+
2646+ br = au_sbr(dentry->d_sb, bdst);
2647+ parent = dget_parent(dentry);
2648+ h_parent = au_h_dptr(parent, bdst);
2649+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
2650+ err = PTR_ERR(wh_dentry);
2651+ if (IS_ERR(wh_dentry))
2652+ goto out;
2653+
2654+ h_path.dentry = h_parent;
2655+ h_path.mnt = br->br_mnt;
2656+ au_dtime_store(&dt, parent, &h_path);
2657+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
2658+ if (unlikely(err))
2659+ goto out_wh;
2660+
2661+ dget(wh_dentry);
2662+ h_path.dentry = wh_dentry;
4a4d8108
AM
2663+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
2664+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
2665+ else
2666+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 2667+ if (unlikely(err)) {
2668+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2669+ AuDLNPair(wh_dentry), err);
2670+ err = -EIO;
2671+ }
2672+ au_dtime_revert(&dt);
2673+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2674+
2675+ out_wh:
2676+ dput(wh_dentry);
2677+ out:
2678+ dput(parent);
2679+ return err;
2680+}
2681+
2682+struct au_cpup_wh_args {
2683+ int *errp;
2684+ struct dentry *dentry;
2685+ aufs_bindex_t bdst;
2686+ loff_t len;
2687+ struct file *file;
2688+};
2689+
2690+static void au_call_cpup_wh(void *args)
2691+{
2692+ struct au_cpup_wh_args *a = args;
2693+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
2694+}
2695+
2696+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2697+ struct file *file)
2698+{
2699+ int err, wkq_err;
2700+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
2701+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
2702+ struct au_wbr *wbr;
2703+
2704+ parent = dget_parent(dentry);
2705+ dir = parent->d_inode;
2706+ h_orph = NULL;
2707+ h_parent = NULL;
2708+ h_dir = au_igrab(au_h_iptr(dir, bdst));
2709+ h_tmpdir = h_dir;
2710+ if (!h_dir->i_nlink) {
2711+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
2712+ h_orph = wbr->wbr_orph;
2713+
2714+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 2715+ au_set_h_dptr(parent, bdst, dget(h_orph));
2716+ h_tmpdir = h_orph->d_inode;
1facf9fc 2717+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
2718+
2719+ /* this temporary unlock is safe */
2720+ if (file)
4a4d8108 2721+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2722+ else
2723+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
2724+ h_inode = h_dentry->d_inode;
2725+ IMustLock(h_inode);
2726+ mutex_unlock(&h_inode->i_mutex);
dece6358 2727+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 2728+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 2729+ /* todo: au_h_open_pre()? */
1facf9fc 2730+ }
2731+
2732+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
2733+ err = au_cpup_wh(dentry, bdst, len, file);
2734+ else {
2735+ struct au_cpup_wh_args args = {
2736+ .errp = &err,
2737+ .dentry = dentry,
2738+ .bdst = bdst,
2739+ .len = len,
2740+ .file = file
2741+ };
2742+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
2743+ if (unlikely(wkq_err))
2744+ err = wkq_err;
2745+ }
2746+
2747+ if (h_orph) {
2748+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 2749+ /* todo: au_h_open_post()? */
1facf9fc 2750+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 2751+ au_set_h_dptr(parent, bdst, h_parent);
2752+ }
2753+ iput(h_dir);
2754+ dput(parent);
2755+
2756+ return err;
2757+}
2758+
2759+/* ---------------------------------------------------------------------- */
2760+
2761+/*
2762+ * generic routine for both of copy-up and copy-down.
2763+ */
2764+/* cf. revalidate function in file.c */
2765+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2766+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2767+ struct dentry *h_parent, void *arg),
2768+ void *arg)
2769+{
2770+ int err;
2771+ struct au_pin pin;
2772+ struct dentry *d, *parent, *h_parent, *real_parent;
2773+
2774+ err = 0;
2775+ parent = dget_parent(dentry);
2776+ if (IS_ROOT(parent))
2777+ goto out;
2778+
2779+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
2780+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
2781+
2782+ /* do not use au_dpage */
2783+ real_parent = parent;
2784+ while (1) {
2785+ dput(parent);
2786+ parent = dget_parent(dentry);
2787+ h_parent = au_h_dptr(parent, bdst);
2788+ if (h_parent)
2789+ goto out; /* success */
2790+
2791+ /* find top dir which is necessary to cpup */
2792+ do {
2793+ d = parent;
2794+ dput(parent);
2795+ parent = dget_parent(d);
2796+ di_read_lock_parent3(parent, !AuLock_IR);
2797+ h_parent = au_h_dptr(parent, bdst);
2798+ di_read_unlock(parent, !AuLock_IR);
2799+ } while (!h_parent);
2800+
2801+ if (d != real_parent)
2802+ di_write_lock_child3(d);
2803+
2804+ /* somebody else might create while we were sleeping */
2805+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
2806+ if (au_h_dptr(d, bdst))
2807+ au_update_dbstart(d);
2808+
2809+ au_pin_set_dentry(&pin, d);
2810+ err = au_do_pin(&pin);
2811+ if (!err) {
2812+ err = cp(d, bdst, h_parent, arg);
2813+ au_unpin(&pin);
2814+ }
2815+ }
2816+
2817+ if (d != real_parent)
2818+ di_write_unlock(d);
2819+ if (unlikely(err))
2820+ break;
2821+ }
2822+
2823+ out:
2824+ dput(parent);
2825+ return err;
2826+}
2827+
2828+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
2829+ struct dentry *h_parent __maybe_unused ,
2830+ void *arg __maybe_unused)
2831+{
2832+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
2833+}
2834+
2835+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2836+{
2837+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
2838+}
2839+
2840+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2841+{
2842+ int err;
2843+ struct dentry *parent;
2844+ struct inode *dir;
2845+
2846+ parent = dget_parent(dentry);
2847+ dir = parent->d_inode;
2848+ err = 0;
2849+ if (au_h_iptr(dir, bdst))
2850+ goto out;
2851+
2852+ di_read_unlock(parent, AuLock_IR);
2853+ di_write_lock_parent(parent);
2854+ /* someone else might change our inode while we were sleeping */
2855+ if (!au_h_iptr(dir, bdst))
2856+ err = au_cpup_dirs(dentry, bdst);
2857+ di_downgrade_lock(parent, AuLock_IR);
2858+
2859+ out:
2860+ dput(parent);
2861+ return err;
2862+}
b752ccd1
AM
2863diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
2864--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
2865+++ linux/fs/aufs/cpup.h 2010-08-21 21:00:02.972333781 +0200
dece6358 2866@@ -0,0 +1,81 @@
1facf9fc 2867+/*
4a4d8108 2868+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2869+ *
2870+ * This program, aufs is free software; you can redistribute it and/or modify
2871+ * it under the terms of the GNU General Public License as published by
2872+ * the Free Software Foundation; either version 2 of the License, or
2873+ * (at your option) any later version.
dece6358
AM
2874+ *
2875+ * This program is distributed in the hope that it will be useful,
2876+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2877+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2878+ * GNU General Public License for more details.
2879+ *
2880+ * You should have received a copy of the GNU General Public License
2881+ * along with this program; if not, write to the Free Software
2882+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2883+ */
2884+
2885+/*
2886+ * copy-up/down functions
2887+ */
2888+
2889+#ifndef __AUFS_CPUP_H__
2890+#define __AUFS_CPUP_H__
2891+
2892+#ifdef __KERNEL__
2893+
dece6358
AM
2894+#include <linux/path.h>
2895+#include <linux/time.h>
1facf9fc 2896+#include <linux/aufs_type.h>
2897+
dece6358
AM
2898+struct inode;
2899+struct file;
2900+
1facf9fc 2901+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
2902+void au_cpup_attr_timesizes(struct inode *inode);
2903+void au_cpup_attr_nlink(struct inode *inode, int force);
2904+void au_cpup_attr_changeable(struct inode *inode);
2905+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
2906+void au_cpup_attr_all(struct inode *inode, int force);
2907+
2908+/* ---------------------------------------------------------------------- */
2909+
2910+/* cpup flags */
2911+#define AuCpup_DTIME 1 /* do dtime_store/revert */
2912+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
2913+ for link(2) */
2914+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
2915+#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; }
2916+#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; }
2917+
2918+int au_copy_file(struct file *dst, struct file *src, loff_t len);
2919+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2920+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2921+ struct dentry *dst_parent);
2922+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2923+ unsigned int flags);
2924+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2925+ struct file *file);
2926+
2927+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2928+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2929+ struct dentry *h_parent, void *arg),
2930+ void *arg);
2931+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2932+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2933+
2934+/* ---------------------------------------------------------------------- */
2935+
2936+/* keep timestamps when copyup */
2937+struct au_dtime {
2938+ struct dentry *dt_dentry;
2939+ struct path dt_h_path;
2940+ struct timespec dt_atime, dt_mtime;
2941+};
2942+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
2943+ struct path *h_path);
2944+void au_dtime_revert(struct au_dtime *dt);
2945+
2946+#endif /* __KERNEL__ */
2947+#endif /* __AUFS_CPUP_H__ */
b752ccd1
AM
2948diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
2949--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
2950+++ linux/fs/aufs/dbgaufs.c 2010-08-21 21:00:02.972333781 +0200
4a4d8108 2951@@ -0,0 +1,334 @@
1facf9fc 2952+/*
4a4d8108 2953+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2954+ *
2955+ * This program, aufs is free software; you can redistribute it and/or modify
2956+ * it under the terms of the GNU General Public License as published by
2957+ * the Free Software Foundation; either version 2 of the License, or
2958+ * (at your option) any later version.
dece6358
AM
2959+ *
2960+ * This program is distributed in the hope that it will be useful,
2961+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2962+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2963+ * GNU General Public License for more details.
2964+ *
2965+ * You should have received a copy of the GNU General Public License
2966+ * along with this program; if not, write to the Free Software
2967+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2968+ */
2969+
2970+/*
2971+ * debugfs interface
2972+ */
2973+
2974+#include <linux/debugfs.h>
2975+#include "aufs.h"
2976+
2977+#ifndef CONFIG_SYSFS
2978+#error DEBUG_FS depends upon SYSFS
2979+#endif
2980+
2981+static struct dentry *dbgaufs;
2982+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
2983+
2984+/* 20 is max digits length of ulong 64 */
2985+struct dbgaufs_arg {
2986+ int n;
2987+ char a[20 * 4];
2988+};
2989+
2990+/*
2991+ * common function for all XINO files
2992+ */
2993+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
2994+ struct file *file)
2995+{
2996+ kfree(file->private_data);
2997+ return 0;
2998+}
2999+
3000+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
3001+{
3002+ int err;
3003+ struct kstat st;
3004+ struct dbgaufs_arg *p;
3005+
3006+ err = -ENOMEM;
3007+ p = kmalloc(sizeof(*p), GFP_NOFS);
3008+ if (unlikely(!p))
3009+ goto out;
3010+
3011+ err = 0;
3012+ p->n = 0;
3013+ file->private_data = p;
3014+ if (!xf)
3015+ goto out;
3016+
3017+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
3018+ if (!err) {
3019+ if (do_fcnt)
3020+ p->n = snprintf
3021+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
3022+ (long)file_count(xf), st.blocks, st.blksize,
3023+ (long long)st.size);
3024+ else
3025+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
3026+ st.blocks, st.blksize,
3027+ (long long)st.size);
3028+ AuDebugOn(p->n >= sizeof(p->a));
3029+ } else {
3030+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
3031+ err = 0;
3032+ }
3033+
3034+ out:
3035+ return err;
3036+
3037+}
3038+
3039+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
3040+ size_t count, loff_t *ppos)
3041+{
3042+ struct dbgaufs_arg *p;
3043+
3044+ p = file->private_data;
3045+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
3046+}
3047+
3048+/* ---------------------------------------------------------------------- */
3049+
3050+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
3051+{
3052+ int err;
3053+ struct au_sbinfo *sbinfo;
3054+ struct super_block *sb;
3055+
3056+ sbinfo = inode->i_private;
3057+ sb = sbinfo->si_sb;
3058+ si_noflush_read_lock(sb);
3059+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
3060+ si_read_unlock(sb);
3061+ return err;
3062+}
3063+
3064+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 3065+ .owner = THIS_MODULE,
1facf9fc 3066+ .open = dbgaufs_xib_open,
3067+ .release = dbgaufs_xi_release,
3068+ .read = dbgaufs_xi_read
3069+};
3070+
3071+/* ---------------------------------------------------------------------- */
3072+
3073+#define DbgaufsXi_PREFIX "xi"
3074+
3075+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
3076+{
3077+ int err;
3078+ long l;
3079+ struct au_sbinfo *sbinfo;
3080+ struct super_block *sb;
3081+ struct file *xf;
3082+ struct qstr *name;
3083+
3084+ err = -ENOENT;
3085+ xf = NULL;
3086+ name = &file->f_dentry->d_name;
3087+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
3088+ || memcmp(name->name, DbgaufsXi_PREFIX,
3089+ sizeof(DbgaufsXi_PREFIX) - 1)))
3090+ goto out;
3091+ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
3092+ if (unlikely(err))
3093+ goto out;
3094+
3095+ sbinfo = inode->i_private;
3096+ sb = sbinfo->si_sb;
3097+ si_noflush_read_lock(sb);
3098+ if (l <= au_sbend(sb)) {
3099+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
3100+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
3101+ } else
3102+ err = -ENOENT;
3103+ si_read_unlock(sb);
3104+
3105+ out:
3106+ return err;
3107+}
3108+
3109+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 3110+ .owner = THIS_MODULE,
1facf9fc 3111+ .open = dbgaufs_xino_open,
3112+ .release = dbgaufs_xi_release,
3113+ .read = dbgaufs_xi_read
3114+};
3115+
3116+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
3117+{
3118+ aufs_bindex_t bend;
3119+ struct au_branch *br;
3120+ struct au_xino_file *xi;
3121+
3122+ if (!au_sbi(sb)->si_dbgaufs)
3123+ return;
3124+
3125+ bend = au_sbend(sb);
3126+ for (; bindex <= bend; bindex++) {
3127+ br = au_sbr(sb, bindex);
3128+ xi = &br->br_xino;
3129+ if (xi->xi_dbgaufs) {
3130+ debugfs_remove(xi->xi_dbgaufs);
3131+ xi->xi_dbgaufs = NULL;
3132+ }
3133+ }
3134+}
3135+
3136+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
3137+{
3138+ struct au_sbinfo *sbinfo;
3139+ struct dentry *parent;
3140+ struct au_branch *br;
3141+ struct au_xino_file *xi;
3142+ aufs_bindex_t bend;
3143+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
3144+
3145+ sbinfo = au_sbi(sb);
3146+ parent = sbinfo->si_dbgaufs;
3147+ if (!parent)
3148+ return;
3149+
3150+ bend = au_sbend(sb);
3151+ for (; bindex <= bend; bindex++) {
3152+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
3153+ br = au_sbr(sb, bindex);
3154+ xi = &br->br_xino;
3155+ AuDebugOn(xi->xi_dbgaufs);
3156+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
3157+ sbinfo, &dbgaufs_xino_fop);
3158+ /* ignore an error */
3159+ if (unlikely(!xi->xi_dbgaufs))
3160+ AuWarn1("failed %s under debugfs\n", name);
3161+ }
3162+}
3163+
3164+/* ---------------------------------------------------------------------- */
3165+
3166+#ifdef CONFIG_AUFS_EXPORT
3167+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
3168+{
3169+ int err;
3170+ struct au_sbinfo *sbinfo;
3171+ struct super_block *sb;
3172+
3173+ sbinfo = inode->i_private;
3174+ sb = sbinfo->si_sb;
3175+ si_noflush_read_lock(sb);
3176+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
3177+ si_read_unlock(sb);
3178+ return err;
3179+}
3180+
3181+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 3182+ .owner = THIS_MODULE,
1facf9fc 3183+ .open = dbgaufs_xigen_open,
3184+ .release = dbgaufs_xi_release,
3185+ .read = dbgaufs_xi_read
3186+};
3187+
3188+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3189+{
3190+ int err;
3191+
dece6358
AM
3192+ /*
3193+ * This function is a dynamic '__init' fucntion actually,
3194+ * so the tiny check for si_rwsem is unnecessary.
3195+ */
3196+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3197+
1facf9fc 3198+ err = -EIO;
3199+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
3200+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3201+ &dbgaufs_xigen_fop);
3202+ if (sbinfo->si_dbgaufs_xigen)
3203+ err = 0;
3204+
3205+ return err;
3206+}
3207+#else
3208+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3209+{
3210+ return 0;
3211+}
3212+#endif /* CONFIG_AUFS_EXPORT */
3213+
3214+/* ---------------------------------------------------------------------- */
3215+
3216+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
3217+{
dece6358
AM
3218+ /*
3219+ * This function is a dynamic '__init' fucntion actually,
3220+ * so the tiny check for si_rwsem is unnecessary.
3221+ */
3222+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3223+
1facf9fc 3224+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
3225+ sbinfo->si_dbgaufs = NULL;
3226+ kobject_put(&sbinfo->si_kobj);
3227+}
3228+
3229+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
3230+{
3231+ int err;
3232+ char name[SysaufsSiNameLen];
3233+
dece6358
AM
3234+ /*
3235+ * This function is a dynamic '__init' fucntion actually,
3236+ * so the tiny check for si_rwsem is unnecessary.
3237+ */
3238+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3239+
1facf9fc 3240+ err = -ENOENT;
3241+ if (!dbgaufs) {
3242+ AuErr1("/debug/aufs is uninitialized\n");
3243+ goto out;
3244+ }
3245+
3246+ err = -EIO;
3247+ sysaufs_name(sbinfo, name);
3248+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
3249+ if (unlikely(!sbinfo->si_dbgaufs))
3250+ goto out;
3251+ kobject_get(&sbinfo->si_kobj);
3252+
3253+ sbinfo->si_dbgaufs_xib = debugfs_create_file
3254+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3255+ &dbgaufs_xib_fop);
3256+ if (unlikely(!sbinfo->si_dbgaufs_xib))
3257+ goto out_dir;
3258+
3259+ err = dbgaufs_xigen_init(sbinfo);
3260+ if (!err)
3261+ goto out; /* success */
3262+
3263+ out_dir:
3264+ dbgaufs_si_fin(sbinfo);
3265+ out:
3266+ return err;
3267+}
3268+
3269+/* ---------------------------------------------------------------------- */
3270+
3271+void dbgaufs_fin(void)
3272+{
3273+ debugfs_remove(dbgaufs);
3274+}
3275+
3276+int __init dbgaufs_init(void)
3277+{
3278+ int err;
3279+
3280+ err = -EIO;
3281+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
3282+ if (dbgaufs)
3283+ err = 0;
3284+ return err;
3285+}
b752ccd1
AM
3286diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
3287--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
3288+++ linux/fs/aufs/dbgaufs.h 2010-08-21 21:00:02.972333781 +0200
4a4d8108 3289@@ -0,0 +1,52 @@
1facf9fc 3290+/*
4a4d8108 3291+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3292+ *
3293+ * This program, aufs is free software; you can redistribute it and/or modify
3294+ * it under the terms of the GNU General Public License as published by
3295+ * the Free Software Foundation; either version 2 of the License, or
3296+ * (at your option) any later version.
dece6358
AM
3297+ *
3298+ * This program is distributed in the hope that it will be useful,
3299+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3300+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3301+ * GNU General Public License for more details.
3302+ *
3303+ * You should have received a copy of the GNU General Public License
3304+ * along with this program; if not, write to the Free Software
3305+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3306+ */
3307+
3308+/*
3309+ * debugfs interface
3310+ */
3311+
3312+#ifndef __DBGAUFS_H__
3313+#define __DBGAUFS_H__
3314+
3315+#ifdef __KERNEL__
3316+
dece6358 3317+#include <linux/init.h>
1facf9fc 3318+#include <linux/aufs_type.h>
3319+
dece6358 3320+struct super_block;
1facf9fc 3321+struct au_sbinfo;
dece6358 3322+
1facf9fc 3323+#ifdef CONFIG_DEBUG_FS
3324+/* dbgaufs.c */
3325+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
3326+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
3327+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
3328+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
3329+void dbgaufs_fin(void);
3330+int __init dbgaufs_init(void);
1facf9fc 3331+#else
4a4d8108
AM
3332+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
3333+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
3334+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
3335+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
3336+AuStubVoid(dbgaufs_fin, void)
3337+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 3338+#endif /* CONFIG_DEBUG_FS */
3339+
3340+#endif /* __KERNEL__ */
3341+#endif /* __DBGAUFS_H__ */
b752ccd1
AM
3342diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
3343--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
3344+++ linux/fs/aufs/dcsub.c 2010-08-21 21:00:02.972333781 +0200
4a4d8108 3345@@ -0,0 +1,200 @@
1facf9fc 3346+/*
4a4d8108 3347+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3348+ *
3349+ * This program, aufs is free software; you can redistribute it and/or modify
3350+ * it under the terms of the GNU General Public License as published by
3351+ * the Free Software Foundation; either version 2 of the License, or
3352+ * (at your option) any later version.
dece6358
AM
3353+ *
3354+ * This program is distributed in the hope that it will be useful,
3355+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3356+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3357+ * GNU General Public License for more details.
3358+ *
3359+ * You should have received a copy of the GNU General Public License
3360+ * along with this program; if not, write to the Free Software
3361+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3362+ */
3363+
3364+/*
3365+ * sub-routines for dentry cache
3366+ */
3367+
3368+#include "aufs.h"
3369+
3370+static void au_dpage_free(struct au_dpage *dpage)
3371+{
3372+ int i;
3373+ struct dentry **p;
3374+
3375+ p = dpage->dentries;
3376+ for (i = 0; i < dpage->ndentry; i++)
3377+ dput(*p++);
3378+ free_page((unsigned long)dpage->dentries);
3379+}
3380+
3381+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
3382+{
3383+ int err;
3384+ void *p;
3385+
3386+ err = -ENOMEM;
3387+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
3388+ if (unlikely(!dpages->dpages))
3389+ goto out;
3390+
3391+ p = (void *)__get_free_page(gfp);
3392+ if (unlikely(!p))
3393+ goto out_dpages;
3394+
3395+ dpages->dpages[0].ndentry = 0;
3396+ dpages->dpages[0].dentries = p;
3397+ dpages->ndpage = 1;
3398+ return 0; /* success */
3399+
3400+ out_dpages:
3401+ kfree(dpages->dpages);
3402+ out:
3403+ return err;
3404+}
3405+
3406+void au_dpages_free(struct au_dcsub_pages *dpages)
3407+{
3408+ int i;
3409+ struct au_dpage *p;
3410+
3411+ p = dpages->dpages;
3412+ for (i = 0; i < dpages->ndpage; i++)
3413+ au_dpage_free(p++);
3414+ kfree(dpages->dpages);
3415+}
3416+
3417+static int au_dpages_append(struct au_dcsub_pages *dpages,
3418+ struct dentry *dentry, gfp_t gfp)
3419+{
3420+ int err, sz;
3421+ struct au_dpage *dpage;
3422+ void *p;
3423+
3424+ dpage = dpages->dpages + dpages->ndpage - 1;
3425+ sz = PAGE_SIZE / sizeof(dentry);
3426+ if (unlikely(dpage->ndentry >= sz)) {
3427+ AuLabel(new dpage);
3428+ err = -ENOMEM;
3429+ sz = dpages->ndpage * sizeof(*dpages->dpages);
3430+ p = au_kzrealloc(dpages->dpages, sz,
3431+ sz + sizeof(*dpages->dpages), gfp);
3432+ if (unlikely(!p))
3433+ goto out;
3434+
3435+ dpages->dpages = p;
3436+ dpage = dpages->dpages + dpages->ndpage;
3437+ p = (void *)__get_free_page(gfp);
3438+ if (unlikely(!p))
3439+ goto out;
3440+
3441+ dpage->ndentry = 0;
3442+ dpage->dentries = p;
3443+ dpages->ndpage++;
3444+ }
3445+
3446+ dpage->dentries[dpage->ndentry++] = dget(dentry);
3447+ return 0; /* success */
3448+
3449+ out:
3450+ return err;
3451+}
3452+
3453+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3454+ au_dpages_test test, void *arg)
3455+{
3456+ int err;
3457+ struct dentry *this_parent = root;
3458+ struct list_head *next;
3459+ struct super_block *sb = root->d_sb;
3460+
3461+ err = 0;
3462+ spin_lock(&dcache_lock);
3463+ repeat:
3464+ next = this_parent->d_subdirs.next;
3465+ resume:
3466+ if (this_parent->d_sb == sb
3467+ && !IS_ROOT(this_parent)
3468+ && atomic_read(&this_parent->d_count)
3469+ && this_parent->d_inode
3470+ && (!test || test(this_parent, arg))) {
3471+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3472+ if (unlikely(err))
3473+ goto out;
3474+ }
3475+
3476+ while (next != &this_parent->d_subdirs) {
3477+ struct list_head *tmp = next;
3478+ struct dentry *dentry = list_entry(tmp, struct dentry,
3479+ d_u.d_child);
3480+ next = tmp->next;
3481+ if (/*d_unhashed(dentry) || */!dentry->d_inode)
3482+ continue;
3483+ if (!list_empty(&dentry->d_subdirs)) {
3484+ this_parent = dentry;
3485+ goto repeat;
3486+ }
3487+ if (dentry->d_sb == sb
3488+ && atomic_read(&dentry->d_count)
3489+ && (!test || test(dentry, arg))) {
3490+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3491+ if (unlikely(err))
3492+ goto out;
3493+ }
3494+ }
3495+
3496+ if (this_parent != root) {
3497+ next = this_parent->d_u.d_child.next;
3498+ this_parent = this_parent->d_parent; /* dcache_lock is locked */
3499+ goto resume;
3500+ }
3501+ out:
3502+ spin_unlock(&dcache_lock);
3503+ return err;
3504+}
3505+
3506+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3507+ int do_include, au_dpages_test test, void *arg)
3508+{
3509+ int err;
3510+
3511+ err = 0;
3512+ spin_lock(&dcache_lock);
3513+ if (do_include && (!test || test(dentry, arg))) {
3514+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3515+ if (unlikely(err))
3516+ goto out;
3517+ }
3518+ while (!IS_ROOT(dentry)) {
3519+ dentry = dentry->d_parent; /* dcache_lock is locked */
3520+ if (!test || test(dentry, arg)) {
3521+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3522+ if (unlikely(err))
3523+ break;
3524+ }
3525+ }
3526+
3527+ out:
3528+ spin_unlock(&dcache_lock);
3529+
3530+ return err;
3531+}
3532+
4a4d8108 3533+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 3534+{
4a4d8108
AM
3535+ struct path path[2] = {
3536+ {
3537+ .dentry = d1
3538+ },
3539+ {
3540+ .dentry = d2
3541+ }
3542+ };
1facf9fc 3543+
4a4d8108 3544+ return path_is_under(path + 0, path + 1);
1facf9fc 3545+}
b752ccd1
AM
3546diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
3547--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
3548+++ linux/fs/aufs/dcsub.h 2010-08-21 21:00:02.972333781 +0200
dece6358 3549@@ -0,0 +1,54 @@
1facf9fc 3550+/*
4a4d8108 3551+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3552+ *
3553+ * This program, aufs is free software; you can redistribute it and/or modify
3554+ * it under the terms of the GNU General Public License as published by
3555+ * the Free Software Foundation; either version 2 of the License, or
3556+ * (at your option) any later version.
dece6358
AM
3557+ *
3558+ * This program is distributed in the hope that it will be useful,
3559+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3560+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3561+ * GNU General Public License for more details.
3562+ *
3563+ * You should have received a copy of the GNU General Public License
3564+ * along with this program; if not, write to the Free Software
3565+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3566+ */
3567+
3568+/*
3569+ * sub-routines for dentry cache
3570+ */
3571+
3572+#ifndef __AUFS_DCSUB_H__
3573+#define __AUFS_DCSUB_H__
3574+
3575+#ifdef __KERNEL__
3576+
dece6358
AM
3577+#include <linux/types.h>
3578+
3579+struct dentry;
1facf9fc 3580+
3581+struct au_dpage {
3582+ int ndentry;
3583+ struct dentry **dentries;
3584+};
3585+
3586+struct au_dcsub_pages {
3587+ int ndpage;
3588+ struct au_dpage *dpages;
3589+};
3590+
3591+/* ---------------------------------------------------------------------- */
3592+
3593+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3594+void au_dpages_free(struct au_dcsub_pages *dpages);
3595+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3596+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3597+ au_dpages_test test, void *arg);
3598+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3599+ int do_include, au_dpages_test test, void *arg);
4a4d8108 3600+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 3601+
3602+#endif /* __KERNEL__ */
3603+#endif /* __AUFS_DCSUB_H__ */
b752ccd1
AM
3604diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
3605--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
3606+++ linux/fs/aufs/debug.c 2010-08-21 21:00:02.972333781 +0200
3607@@ -0,0 +1,440 @@
1facf9fc 3608+/*
4a4d8108 3609+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3610+ *
3611+ * This program, aufs is free software; you can redistribute it and/or modify
3612+ * it under the terms of the GNU General Public License as published by
3613+ * the Free Software Foundation; either version 2 of the License, or
3614+ * (at your option) any later version.
dece6358
AM
3615+ *
3616+ * This program is distributed in the hope that it will be useful,
3617+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3618+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3619+ * GNU General Public License for more details.
3620+ *
3621+ * You should have received a copy of the GNU General Public License
3622+ * along with this program; if not, write to the Free Software
3623+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3624+ */
3625+
3626+/*
3627+ * debug print functions
3628+ */
3629+
dece6358
AM
3630+#include <linux/module.h>
3631+#include <linux/vt_kern.h>
1facf9fc 3632+#include "aufs.h"
3633+
3634+int aufs_debug;
3635+MODULE_PARM_DESC(debug, "debug print");
3636+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
3637+
3638+char *au_plevel = KERN_DEBUG;
4a4d8108 3639+#define dpri(fmt, ...) do { \
1facf9fc 3640+ if (au_debug_test()) \
4a4d8108 3641+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 3642+} while (0)
3643+
3644+/* ---------------------------------------------------------------------- */
3645+
3646+void au_dpri_whlist(struct au_nhash *whlist)
3647+{
3648+ unsigned long ul, n;
3649+ struct hlist_head *head;
3650+ struct au_vdir_wh *tpos;
3651+ struct hlist_node *pos;
3652+
3653+ n = whlist->nh_num;
3654+ head = whlist->nh_head;
3655+ for (ul = 0; ul < n; ul++) {
3656+ hlist_for_each_entry(tpos, pos, head, wh_hash)
3657+ dpri("b%d, %.*s, %d\n",
3658+ tpos->wh_bindex,
3659+ tpos->wh_str.len, tpos->wh_str.name,
3660+ tpos->wh_str.len);
3661+ head++;
3662+ }
3663+}
3664+
3665+void au_dpri_vdir(struct au_vdir *vdir)
3666+{
3667+ unsigned long ul;
3668+ union au_vdir_deblk_p p;
3669+ unsigned char *o;
3670+
3671+ if (!vdir || IS_ERR(vdir)) {
3672+ dpri("err %ld\n", PTR_ERR(vdir));
3673+ return;
3674+ }
3675+
3676+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
3677+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
3678+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
3679+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
3680+ p.deblk = vdir->vd_deblk[ul];
3681+ o = p.deblk;
3682+ dpri("[%lu]: %p\n", ul, o);
3683+ }
3684+}
3685+
3686+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3687+ struct dentry *wh)
3688+{
3689+ char *n = NULL;
3690+ int l = 0;
3691+
3692+ if (!inode || IS_ERR(inode)) {
3693+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3694+ return -1;
3695+ }
3696+
3697+ /* the type of i_blocks depends upon CONFIG_LSF */
3698+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3699+ && sizeof(inode->i_blocks) != sizeof(u64));
3700+ if (wh) {
3701+ n = (void *)wh->d_name.name;
3702+ l = wh->d_name.len;
3703+ }
3704+
3705+ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
b752ccd1 3706+ " ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
1facf9fc 3707+ bindex,
3708+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3709+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3710+ i_size_read(inode), (unsigned long long)inode->i_blocks,
3711+ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3712+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
3713+ inode->i_state, inode->i_flags, inode->i_version,
3714+ inode->i_generation,
1facf9fc 3715+ l ? ", wh " : "", l, n);
3716+ return 0;
3717+}
3718+
3719+void au_dpri_inode(struct inode *inode)
3720+{
3721+ struct au_iinfo *iinfo;
3722+ aufs_bindex_t bindex;
3723+ int err;
3724+
3725+ err = do_pri_inode(-1, inode, NULL);
3726+ if (err || !au_test_aufs(inode->i_sb))
3727+ return;
3728+
3729+ iinfo = au_ii(inode);
3730+ if (!iinfo)
3731+ return;
3732+ dpri("i-1: bstart %d, bend %d, gen %d\n",
3733+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
3734+ if (iinfo->ii_bstart < 0)
3735+ return;
3736+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
3737+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
3738+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
3739+}
3740+
3741+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
3742+{
3743+ struct dentry *wh = NULL;
3744+
3745+ if (!dentry || IS_ERR(dentry)) {
3746+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
3747+ return -1;
3748+ }
3749+ /* do not call dget_parent() here */
3750+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
3751+ bindex,
3752+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
3753+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
3754+ atomic_read(&dentry->d_count), dentry->d_flags);
3755+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
3756+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
3757+ if (iinfo)
3758+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
3759+ }
3760+ do_pri_inode(bindex, dentry->d_inode, wh);
3761+ return 0;
3762+}
3763+
3764+void au_dpri_dentry(struct dentry *dentry)
3765+{
3766+ struct au_dinfo *dinfo;
3767+ aufs_bindex_t bindex;
3768+ int err;
4a4d8108 3769+ struct au_hdentry *hdp;
1facf9fc 3770+
3771+ err = do_pri_dentry(-1, dentry);
3772+ if (err || !au_test_aufs(dentry->d_sb))
3773+ return;
3774+
3775+ dinfo = au_di(dentry);
3776+ if (!dinfo)
3777+ return;
3778+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
3779+ dinfo->di_bstart, dinfo->di_bend,
3780+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
3781+ if (dinfo->di_bstart < 0)
3782+ return;
4a4d8108 3783+ hdp = dinfo->di_hdentry;
1facf9fc 3784+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 3785+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 3786+}
3787+
3788+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
3789+{
3790+ char a[32];
3791+
3792+ if (!file || IS_ERR(file)) {
3793+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
3794+ return -1;
3795+ }
3796+ a[0] = 0;
3797+ if (bindex < 0
3798+ && file->f_dentry
3799+ && au_test_aufs(file->f_dentry->d_sb)
3800+ && au_fi(file))
4a4d8108
AM
3801+ snprintf(a, sizeof(a), ", mmapped %d",
3802+ !!au_fi(file)->fi_hvmop);
b752ccd1 3803+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 3804+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 3805+ file->f_version, file->f_pos, a);
1facf9fc 3806+ if (file->f_dentry)
3807+ do_pri_dentry(bindex, file->f_dentry);
3808+ return 0;
3809+}
3810+
3811+void au_dpri_file(struct file *file)
3812+{
3813+ struct au_finfo *finfo;
4a4d8108
AM
3814+ struct au_fidir *fidir;
3815+ struct au_hfile *hfile;
1facf9fc 3816+ aufs_bindex_t bindex;
3817+ int err;
3818+
3819+ err = do_pri_file(-1, file);
3820+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
3821+ return;
3822+
3823+ finfo = au_fi(file);
3824+ if (!finfo)
3825+ return;
4a4d8108 3826+ if (finfo->fi_btop < 0)
1facf9fc 3827+ return;
4a4d8108
AM
3828+ fidir = finfo->fi_hdir;
3829+ if (!fidir)
3830+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
3831+ else
3832+ for (bindex = finfo->fi_btop; bindex <= fidir->fd_bbot;
3833+ bindex++) {
3834+ hfile = fidir->fd_hfile + bindex;
3835+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
3836+ }
1facf9fc 3837+}
3838+
3839+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
3840+{
3841+ struct vfsmount *mnt;
3842+ struct super_block *sb;
3843+
3844+ if (!br || IS_ERR(br))
3845+ goto out;
3846+ mnt = br->br_mnt;
3847+ if (!mnt || IS_ERR(mnt))
3848+ goto out;
3849+ sb = mnt->mnt_sb;
3850+ if (!sb || IS_ERR(sb))
3851+ goto out;
3852+
3853+ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
b752ccd1 3854+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 3855+ "xino %d\n",
3856+ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
3857+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 3858+ sb->s_flags, sb->s_count,
1facf9fc 3859+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
3860+ return 0;
3861+
3862+ out:
3863+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
3864+ return -1;
3865+}
3866+
3867+void au_dpri_sb(struct super_block *sb)
3868+{
3869+ struct au_sbinfo *sbinfo;
3870+ aufs_bindex_t bindex;
3871+ int err;
3872+ /* to reuduce stack size */
3873+ struct {
3874+ struct vfsmount mnt;
3875+ struct au_branch fake;
3876+ } *a;
3877+
3878+ /* this function can be called from magic sysrq */
3879+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
3880+ if (unlikely(!a)) {
3881+ dpri("no memory\n");
3882+ return;
3883+ }
3884+
3885+ a->mnt.mnt_sb = sb;
3886+ a->fake.br_perm = 0;
3887+ a->fake.br_mnt = &a->mnt;
3888+ a->fake.br_xino.xi_file = NULL;
3889+ atomic_set(&a->fake.br_count, 0);
3890+ smp_mb(); /* atomic_set */
3891+ err = do_pri_br(-1, &a->fake);
3892+ kfree(a);
3893+ dpri("dev 0x%x\n", sb->s_dev);
3894+ if (err || !au_test_aufs(sb))
3895+ return;
3896+
3897+ sbinfo = au_sbi(sb);
3898+ if (!sbinfo)
3899+ return;
3900+ dpri("nw %d, gen %u, kobj %d\n",
3901+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
3902+ atomic_read(&sbinfo->si_kobj.kref.refcount));
3903+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
3904+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
3905+}
3906+
3907+/* ---------------------------------------------------------------------- */
3908+
3909+void au_dbg_sleep_jiffy(int jiffy)
3910+{
3911+ while (jiffy)
3912+ jiffy = schedule_timeout_uninterruptible(jiffy);
3913+}
3914+
3915+void au_dbg_iattr(struct iattr *ia)
3916+{
3917+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
3918+ dpri(#name "\n")
3919+ AuBit(MODE);
3920+ AuBit(UID);
3921+ AuBit(GID);
3922+ AuBit(SIZE);
3923+ AuBit(ATIME);
3924+ AuBit(MTIME);
3925+ AuBit(CTIME);
3926+ AuBit(ATIME_SET);
3927+ AuBit(MTIME_SET);
3928+ AuBit(FORCE);
3929+ AuBit(ATTR_FLAG);
3930+ AuBit(KILL_SUID);
3931+ AuBit(KILL_SGID);
3932+ AuBit(FILE);
3933+ AuBit(KILL_PRIV);
3934+ AuBit(OPEN);
3935+ AuBit(TIMES_SET);
3936+#undef AuBit
3937+ dpri("ia_file %p\n", ia->ia_file);
3938+}
3939+
3940+/* ---------------------------------------------------------------------- */
3941+
3942+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
3943+{
3944+ struct dentry *parent;
3945+
3946+ parent = dget_parent(dentry);
3947+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
3948+ || IS_ROOT(dentry)
3949+ || au_digen(parent) != sigen);
3950+ dput(parent);
3951+}
3952+
3953+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
3954+{
3955+ struct dentry *parent;
3956+
3957+ parent = dget_parent(dentry);
3958+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
3959+ || au_digen(parent) != sigen);
3960+ dput(parent);
3961+}
3962+
3963+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
3964+{
3965+ int err, i, j;
3966+ struct au_dcsub_pages dpages;
3967+ struct au_dpage *dpage;
3968+ struct dentry **dentries;
3969+
3970+ err = au_dpages_init(&dpages, GFP_NOFS);
3971+ AuDebugOn(err);
3972+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
3973+ AuDebugOn(err);
3974+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
3975+ dpage = dpages.dpages + i;
3976+ dentries = dpage->dentries;
3977+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
3978+ AuDebugOn(au_digen(dentries[j]) != sigen);
3979+ }
3980+ au_dpages_free(&dpages);
3981+}
3982+
1facf9fc 3983+void au_dbg_verify_kthread(void)
3984+{
b752ccd1
AM
3985+ struct task_struct *tsk = current;
3986+
3987+ if ((tsk->flags & PF_KTHREAD)
3988+ && !strncmp(tsk->comm, AUFS_WKQ_NAME "/", sizeof(AUFS_WKQ_NAME))) {
1facf9fc 3989+ au_dbg_blocked();
3990+ BUG();
3991+ }
3992+}
3993+
b752ccd1
AM
3994+static void au_dbg_do_verify_wkq(void *args)
3995+{
3996+ BUG_ON(current_fsuid());
3997+ BUG_ON(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
3998+}
3999+
4000+void au_dbg_verify_wkq(void)
4001+{
4002+ au_wkq_wait(au_dbg_do_verify_wkq, NULL);
4003+}
4004+
1facf9fc 4005+/* ---------------------------------------------------------------------- */
4006+
4007+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
4008+{
4009+#ifdef AuForceNoPlink
4010+ au_opt_clr(sbinfo->si_mntflags, PLINK);
4011+#endif
4012+#ifdef AuForceNoXino
4013+ au_opt_clr(sbinfo->si_mntflags, XINO);
4014+#endif
4015+#ifdef AuForceNoRefrof
4016+ au_opt_clr(sbinfo->si_mntflags, REFROF);
4017+#endif
4a4d8108
AM
4018+#ifdef AuForceHnotify
4019+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 4020+#endif
1308ab2a 4021+#ifdef AuForceRd0
4022+ sbinfo->si_rdblk = 0;
4023+ sbinfo->si_rdhash = 0;
4024+#endif
1facf9fc 4025+}
4026+
4027+int __init au_debug_init(void)
4028+{
4029+ aufs_bindex_t bindex;
4030+ struct au_vdir_destr destr;
4031+
4032+ bindex = -1;
4033+ AuDebugOn(bindex >= 0);
4034+
4035+ destr.len = -1;
4036+ AuDebugOn(destr.len < NAME_MAX);
4037+
4038+#ifdef CONFIG_4KSTACKS
4a4d8108 4039+ pr_warning("CONFIG_4KSTACKS is defined.\n");
1facf9fc 4040+#endif
4041+
4042+#ifdef AuForceNoBrs
4043+ sysaufs_brs = 0;
4044+#endif
4045+
4046+ return 0;
4047+}
b752ccd1
AM
4048diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
4049--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
4050+++ linux/fs/aufs/debug.h 2010-08-21 21:00:02.972333781 +0200
4051@@ -0,0 +1,245 @@
1facf9fc 4052+/*
4a4d8108 4053+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4054+ *
4055+ * This program, aufs is free software; you can redistribute it and/or modify
4056+ * it under the terms of the GNU General Public License as published by
4057+ * the Free Software Foundation; either version 2 of the License, or
4058+ * (at your option) any later version.
dece6358
AM
4059+ *
4060+ * This program is distributed in the hope that it will be useful,
4061+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4062+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4063+ * GNU General Public License for more details.
4064+ *
4065+ * You should have received a copy of the GNU General Public License
4066+ * along with this program; if not, write to the Free Software
4067+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4068+ */
4069+
4070+/*
4071+ * debug print functions
4072+ */
4073+
4074+#ifndef __AUFS_DEBUG_H__
4075+#define __AUFS_DEBUG_H__
4076+
4077+#ifdef __KERNEL__
4078+
1308ab2a 4079+#include <asm/system.h>
dece6358
AM
4080+#include <linux/bug.h>
4081+/* #include <linux/err.h> */
1308ab2a 4082+#include <linux/init.h>
4a4d8108
AM
4083+#include <linux/module.h>
4084+#include <linux/kallsyms.h>
dece6358 4085+/* #include <linux/kernel.h> */
1facf9fc 4086+#include <linux/delay.h>
dece6358
AM
4087+/* #include <linux/kd.h> */
4088+/* #include <linux/vt_kern.h> */
1facf9fc 4089+#include <linux/sysrq.h>
4090+#include <linux/aufs_type.h>
4091+
4a4d8108
AM
4092+#include <asm/system.h>
4093+
1facf9fc 4094+#ifdef CONFIG_AUFS_DEBUG
4095+#define AuDebugOn(a) BUG_ON(a)
4096+
4097+/* module parameter */
4098+extern int aufs_debug;
4099+static inline void au_debug(int n)
4100+{
4101+ aufs_debug = n;
4102+ smp_mb();
4103+}
4104+
4105+static inline int au_debug_test(void)
4106+{
4107+ return aufs_debug;
4108+}
4109+#else
4110+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
4111+AuStubVoid(au_debug, int n)
4112+AuStubInt0(au_debug_test, void)
1facf9fc 4113+#endif /* CONFIG_AUFS_DEBUG */
4114+
4115+/* ---------------------------------------------------------------------- */
4116+
4117+/* debug print */
4118+
4a4d8108 4119+#define AuDbg(fmt, ...) do { \
1facf9fc 4120+ if (au_debug_test()) \
4a4d8108 4121+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 4122+} while (0)
4a4d8108
AM
4123+#define AuLabel(l) AuDbg(#l "\n")
4124+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
4125+#define AuWarn1(fmt, ...) do { \
1facf9fc 4126+ static unsigned char _c; \
4127+ if (!_c++) \
4a4d8108 4128+ pr_warning(fmt, ##__VA_ARGS__); \
1facf9fc 4129+} while (0)
4130+
4a4d8108 4131+#define AuErr1(fmt, ...) do { \
1facf9fc 4132+ static unsigned char _c; \
4133+ if (!_c++) \
4a4d8108 4134+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 4135+} while (0)
4136+
4a4d8108 4137+#define AuIOErr1(fmt, ...) do { \
1facf9fc 4138+ static unsigned char _c; \
4139+ if (!_c++) \
4a4d8108 4140+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 4141+} while (0)
4142+
4143+#define AuUnsupportMsg "This operation is not supported." \
4144+ " Please report this application to aufs-users ML."
4a4d8108
AM
4145+#define AuUnsupport(fmt, ...) do { \
4146+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 4147+ dump_stack(); \
4148+} while (0)
4149+
4150+#define AuTraceErr(e) do { \
4151+ if (unlikely((e) < 0)) \
4152+ AuDbg("err %d\n", (int)(e)); \
4153+} while (0)
4154+
4155+#define AuTraceErrPtr(p) do { \
4156+ if (IS_ERR(p)) \
4157+ AuDbg("err %ld\n", PTR_ERR(p)); \
4158+} while (0)
4159+
4160+/* dirty macros for debug print, use with "%.*s" and caution */
4161+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
4162+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
4163+
4164+/* ---------------------------------------------------------------------- */
4165+
4166+struct au_sbinfo;
4167+struct au_finfo;
dece6358 4168+struct dentry;
1facf9fc 4169+#ifdef CONFIG_AUFS_DEBUG
4170+extern char *au_plevel;
4171+struct au_nhash;
4172+void au_dpri_whlist(struct au_nhash *whlist);
4173+struct au_vdir;
4174+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 4175+struct inode;
1facf9fc 4176+void au_dpri_inode(struct inode *inode);
4177+void au_dpri_dentry(struct dentry *dentry);
dece6358 4178+struct file;
1facf9fc 4179+void au_dpri_file(struct file *filp);
dece6358 4180+struct super_block;
1facf9fc 4181+void au_dpri_sb(struct super_block *sb);
4182+
4183+void au_dbg_sleep_jiffy(int jiffy);
dece6358 4184+struct iattr;
1facf9fc 4185+void au_dbg_iattr(struct iattr *ia);
4186+
4187+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
4188+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
4189+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 4190+void au_dbg_verify_kthread(void);
b752ccd1 4191+void au_dbg_verify_wkq(void);
1facf9fc 4192+
4193+int __init au_debug_init(void);
4194+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
4195+#define AuDbgWhlist(w) do { \
4196+ AuDbg(#w "\n"); \
4197+ au_dpri_whlist(w); \
4198+} while (0)
4199+
4200+#define AuDbgVdir(v) do { \
4201+ AuDbg(#v "\n"); \
4202+ au_dpri_vdir(v); \
4203+} while (0)
4204+
4205+#define AuDbgInode(i) do { \
4206+ AuDbg(#i "\n"); \
4207+ au_dpri_inode(i); \
4208+} while (0)
4209+
4210+#define AuDbgDentry(d) do { \
4211+ AuDbg(#d "\n"); \
4212+ au_dpri_dentry(d); \
4213+} while (0)
4214+
4215+#define AuDbgFile(f) do { \
4216+ AuDbg(#f "\n"); \
4217+ au_dpri_file(f); \
4218+} while (0)
4219+
4220+#define AuDbgSb(sb) do { \
4221+ AuDbg(#sb "\n"); \
4222+ au_dpri_sb(sb); \
4223+} while (0)
4224+
4225+#define AuDbgSleep(sec) do { \
4226+ AuDbg("sleep %d sec\n", sec); \
4227+ ssleep(sec); \
4228+} while (0)
4229+
4230+#define AuDbgSleepJiffy(jiffy) do { \
4231+ AuDbg("sleep %d jiffies\n", jiffy); \
4232+ au_dbg_sleep_jiffy(jiffy); \
4233+} while (0)
4234+
4235+#define AuDbgIAttr(ia) do { \
4236+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
4237+ au_dbg_iattr(ia); \
4238+} while (0)
4a4d8108
AM
4239+
4240+#define AuDbgSym(addr) do { \
4241+ char sym[KSYM_SYMBOL_LEN]; \
4242+ sprint_symbol(sym, (unsigned long)addr); \
4243+ AuDbg("%s\n", sym); \
4244+} while (0)
4245+
4246+#define AuInfoSym(addr) do { \
4247+ char sym[KSYM_SYMBOL_LEN]; \
4248+ sprint_symbol(sym, (unsigned long)addr); \
4249+ AuInfo("%s\n", sym); \
4250+} while (0)
1facf9fc 4251+#else
4a4d8108
AM
4252+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
4253+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
4254+ unsigned int sigen)
4255+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
4256+AuStubVoid(au_dbg_verify_kthread, void)
b752ccd1 4257+AuStubVoid(au_dbg_verify_wkq, void)
4a4d8108
AM
4258+AuStubInt0(__init au_debug_init, void)
4259+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 4260+
1facf9fc 4261+#define AuDbgWhlist(w) do {} while (0)
4262+#define AuDbgVdir(v) do {} while (0)
4263+#define AuDbgInode(i) do {} while (0)
4264+#define AuDbgDentry(d) do {} while (0)
4265+#define AuDbgFile(f) do {} while (0)
4266+#define AuDbgSb(sb) do {} while (0)
4267+#define AuDbgSleep(sec) do {} while (0)
4268+#define AuDbgSleepJiffy(jiffy) do {} while (0)
4269+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
4270+#define AuDbgSym(addr) do {} while (0)
4271+#define AuInfoSym(addr) do {} while (0)
1facf9fc 4272+#endif /* CONFIG_AUFS_DEBUG */
4273+
4274+/* ---------------------------------------------------------------------- */
4275+
4276+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
4277+int __init au_sysrq_init(void);
4278+void au_sysrq_fin(void);
4279+
4280+#ifdef CONFIG_HW_CONSOLE
4281+#define au_dbg_blocked() do { \
4282+ WARN_ON(1); \
4283+ handle_sysrq('w', vc_cons[fg_console].d->vc_tty); \
4284+} while (0)
4285+#else
4a4d8108 4286+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4287+#endif
4288+
4289+#else
4a4d8108
AM
4290+AuStubInt0(__init au_sysrq_init, void)
4291+AuStubVoid(au_sysrq_fin, void)
4292+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4293+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
4294+
4295+#endif /* __KERNEL__ */
4296+#endif /* __AUFS_DEBUG_H__ */
b752ccd1
AM
4297diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
4298--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
4299+++ linux/fs/aufs/dentry.c 2010-08-21 21:00:02.975972487 +0200
4a4d8108 4300@@ -0,0 +1,850 @@
1facf9fc 4301+/*
4a4d8108 4302+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4303+ *
4304+ * This program, aufs is free software; you can redistribute it and/or modify
4305+ * it under the terms of the GNU General Public License as published by
4306+ * the Free Software Foundation; either version 2 of the License, or
4307+ * (at your option) any later version.
dece6358
AM
4308+ *
4309+ * This program is distributed in the hope that it will be useful,
4310+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4311+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4312+ * GNU General Public License for more details.
4313+ *
4314+ * You should have received a copy of the GNU General Public License
4315+ * along with this program; if not, write to the Free Software
4316+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4317+ */
4318+
4319+/*
4320+ * lookup and dentry operations
4321+ */
4322+
dece6358 4323+#include <linux/namei.h>
1facf9fc 4324+#include "aufs.h"
4325+
4326+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
4327+{
4328+ if (nd) {
4329+ *h_nd = *nd;
4330+
4331+ /*
4332+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
4333+ * due to whiteout and branch permission.
4334+ */
4335+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
b752ccd1 4336+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
1facf9fc 4337+ /* unnecessary? */
4338+ h_nd->intent.open.file = NULL;
4339+ } else
4340+ memset(h_nd, 0, sizeof(*h_nd));
4341+}
4342+
4343+struct au_lkup_one_args {
4344+ struct dentry **errp;
4345+ struct qstr *name;
4346+ struct dentry *h_parent;
4347+ struct au_branch *br;
4348+ struct nameidata *nd;
4349+};
4350+
4351+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
4352+ struct au_branch *br, struct nameidata *nd)
4353+{
4354+ struct dentry *h_dentry;
4355+ int err;
4356+ struct nameidata h_nd;
4357+
4358+ if (au_test_fs_null_nd(h_parent->d_sb))
4359+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
4360+
4361+ au_h_nd(&h_nd, nd);
4362+ h_nd.path.dentry = h_parent;
4363+ h_nd.path.mnt = br->br_mnt;
4364+
4365+ err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
4366+ h_dentry = ERR_PTR(err);
4367+ if (!err) {
4368+ path_get(&h_nd.path);
4369+ h_dentry = vfsub_lookup_hash(&h_nd);
4370+ path_put(&h_nd.path);
4371+ }
4372+
4a4d8108 4373+ AuTraceErrPtr(h_dentry);
1facf9fc 4374+ return h_dentry;
4375+}
4376+
4377+static void au_call_lkup_one(void *args)
4378+{
4379+ struct au_lkup_one_args *a = args;
4380+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
4381+}
4382+
4383+#define AuLkup_ALLOW_NEG 1
4384+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
4385+#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; }
4386+#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; }
4387+
4388+struct au_do_lookup_args {
4389+ unsigned int flags;
4390+ mode_t type;
4391+ struct nameidata *nd;
4392+};
4393+
4394+/*
4395+ * returns positive/negative dentry, NULL or an error.
4396+ * NULL means whiteout-ed or not-found.
4397+ */
4398+static struct dentry*
4399+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
4400+ aufs_bindex_t bindex, struct qstr *wh_name,
4401+ struct au_do_lookup_args *args)
4402+{
4403+ struct dentry *h_dentry;
4404+ struct inode *h_inode, *inode;
1facf9fc 4405+ struct au_branch *br;
4406+ int wh_found, opq;
4407+ unsigned char wh_able;
4408+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
4409+
1facf9fc 4410+ wh_found = 0;
4411+ br = au_sbr(dentry->d_sb, bindex);
4412+ wh_able = !!au_br_whable(br->br_perm);
4413+ if (wh_able)
4414+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
4415+ h_dentry = ERR_PTR(wh_found);
4416+ if (!wh_found)
4417+ goto real_lookup;
4418+ if (unlikely(wh_found < 0))
4419+ goto out;
4420+
4421+ /* We found a whiteout */
4422+ /* au_set_dbend(dentry, bindex); */
4423+ au_set_dbwh(dentry, bindex);
4424+ if (!allow_neg)
4425+ return NULL; /* success */
4426+
4427+ real_lookup:
4a4d8108 4428+ h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
1facf9fc 4429+ if (IS_ERR(h_dentry))
4430+ goto out;
4431+
4432+ h_inode = h_dentry->d_inode;
4433+ if (!h_inode) {
4434+ if (!allow_neg)
4435+ goto out_neg;
4436+ } else if (wh_found
4437+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
4438+ goto out_neg;
4439+
4440+ if (au_dbend(dentry) <= bindex)
4441+ au_set_dbend(dentry, bindex);
4442+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4443+ au_set_dbstart(dentry, bindex);
4444+ au_set_h_dptr(dentry, bindex, h_dentry);
4445+
4446+ inode = dentry->d_inode;
4447+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4448+ || (inode && !S_ISDIR(inode->i_mode)))
4449+ goto out; /* success */
4450+
4451+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4452+ opq = au_diropq_test(h_dentry, br);
4453+ mutex_unlock(&h_inode->i_mutex);
4454+ if (opq > 0)
4455+ au_set_dbdiropq(dentry, bindex);
4456+ else if (unlikely(opq < 0)) {
4457+ au_set_h_dptr(dentry, bindex, NULL);
4458+ h_dentry = ERR_PTR(opq);
4459+ }
4460+ goto out;
4461+
4462+ out_neg:
4463+ dput(h_dentry);
4464+ h_dentry = NULL;
4465+ out:
4466+ return h_dentry;
4467+}
4468+
dece6358
AM
4469+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
4470+{
4471+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
4472+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
4473+ return -EPERM;
4474+ return 0;
4475+}
4476+
1facf9fc 4477+/*
4478+ * returns the number of lower positive dentries,
4479+ * otherwise an error.
4480+ * can be called at unlinking with @type is zero.
4481+ */
4482+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4483+ struct nameidata *nd)
4484+{
4485+ int npositive, err;
4486+ aufs_bindex_t bindex, btail, bdiropq;
4487+ unsigned char isdir;
4488+ struct qstr whname;
4489+ struct au_do_lookup_args args = {
4490+ .flags = 0,
4491+ .type = type,
4492+ .nd = nd
4493+ };
4494+ const struct qstr *name = &dentry->d_name;
4495+ struct dentry *parent;
4496+ struct inode *inode;
4497+
dece6358
AM
4498+ err = au_test_shwh(dentry->d_sb, name);
4499+ if (unlikely(err))
1facf9fc 4500+ goto out;
4501+
4502+ err = au_wh_name_alloc(&whname, name);
4503+ if (unlikely(err))
4504+ goto out;
4505+
4506+ inode = dentry->d_inode;
4507+ isdir = !!(inode && S_ISDIR(inode->i_mode));
4508+ if (!type)
4509+ au_fset_lkup(args.flags, ALLOW_NEG);
4510+
4511+ npositive = 0;
4a4d8108 4512+ parent = dget_parent(dentry);
1facf9fc 4513+ btail = au_dbtaildir(parent);
4514+ for (bindex = bstart; bindex <= btail; bindex++) {
4515+ struct dentry *h_parent, *h_dentry;
4516+ struct inode *h_inode, *h_dir;
4517+
4518+ h_dentry = au_h_dptr(dentry, bindex);
4519+ if (h_dentry) {
4520+ if (h_dentry->d_inode)
4521+ npositive++;
4522+ if (type != S_IFDIR)
4523+ break;
4524+ continue;
4525+ }
4526+ h_parent = au_h_dptr(parent, bindex);
4527+ if (!h_parent)
4528+ continue;
4529+ h_dir = h_parent->d_inode;
4530+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
4531+ continue;
4532+
4533+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4534+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4535+ &args);
4536+ mutex_unlock(&h_dir->i_mutex);
4537+ err = PTR_ERR(h_dentry);
4538+ if (IS_ERR(h_dentry))
4a4d8108 4539+ goto out_parent;
1facf9fc 4540+ au_fclr_lkup(args.flags, ALLOW_NEG);
4541+
4542+ if (au_dbwh(dentry) >= 0)
4543+ break;
4544+ if (!h_dentry)
4545+ continue;
4546+ h_inode = h_dentry->d_inode;
4547+ if (!h_inode)
4548+ continue;
4549+ npositive++;
4550+ if (!args.type)
4551+ args.type = h_inode->i_mode & S_IFMT;
4552+ if (args.type != S_IFDIR)
4553+ break;
4554+ else if (isdir) {
4555+ /* the type of lower may be different */
4556+ bdiropq = au_dbdiropq(dentry);
4557+ if (bdiropq >= 0 && bdiropq <= bindex)
4558+ break;
4559+ }
4560+ }
4561+
4562+ if (npositive) {
4563+ AuLabel(positive);
4564+ au_update_dbstart(dentry);
4565+ }
4566+ err = npositive;
4567+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
4568+ && au_dbstart(dentry) < 0))
4569+ /* both of real entry and whiteout found */
4570+ err = -EIO;
4571+
4a4d8108
AM
4572+ out_parent:
4573+ dput(parent);
1facf9fc 4574+ kfree(whname.name);
4575+ out:
1facf9fc 4576+ return err;
4577+}
4578+
4579+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4580+ struct au_branch *br)
4581+{
4582+ struct dentry *dentry;
4583+ int wkq_err;
4584+
4585+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
4586+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
4587+ else {
4588+ struct au_lkup_one_args args = {
4589+ .errp = &dentry,
4590+ .name = name,
4591+ .h_parent = parent,
4592+ .br = br,
4593+ .nd = NULL
4594+ };
4595+
4596+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
4597+ if (unlikely(wkq_err))
4598+ dentry = ERR_PTR(wkq_err);
4599+ }
4600+
4601+ return dentry;
4602+}
4603+
4604+/*
4605+ * lookup @dentry on @bindex which should be negative.
4606+ */
4607+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4608+{
4609+ int err;
4610+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 4611+
1facf9fc 4612+ parent = dget_parent(dentry);
4613+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 4614+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 4615+ au_sbr(dentry->d_sb, bindex));
4616+ err = PTR_ERR(h_dentry);
4617+ if (IS_ERR(h_dentry))
4618+ goto out;
4619+ if (unlikely(h_dentry->d_inode)) {
4620+ err = -EIO;
4621+ AuIOErr("b%d %.*s should be negative.\n",
4622+ bindex, AuDLNPair(h_dentry));
4623+ dput(h_dentry);
4624+ goto out;
4625+ }
4626+
4a4d8108 4627+ err = 0;
1facf9fc 4628+ if (bindex < au_dbstart(dentry))
4629+ au_set_dbstart(dentry, bindex);
4630+ if (au_dbend(dentry) < bindex)
4631+ au_set_dbend(dentry, bindex);
4632+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 4633+
4634+ out:
4635+ dput(parent);
4636+ return err;
4637+}
4638+
4639+/* ---------------------------------------------------------------------- */
4640+
4641+/* subset of struct inode */
4642+struct au_iattr {
4643+ unsigned long i_ino;
4644+ /* unsigned int i_nlink; */
4645+ uid_t i_uid;
4646+ gid_t i_gid;
4647+ u64 i_version;
4648+/*
4649+ loff_t i_size;
4650+ blkcnt_t i_blocks;
4651+*/
4652+ umode_t i_mode;
4653+};
4654+
4655+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
4656+{
4657+ ia->i_ino = h_inode->i_ino;
4658+ /* ia->i_nlink = h_inode->i_nlink; */
4659+ ia->i_uid = h_inode->i_uid;
4660+ ia->i_gid = h_inode->i_gid;
4661+ ia->i_version = h_inode->i_version;
4662+/*
4663+ ia->i_size = h_inode->i_size;
4664+ ia->i_blocks = h_inode->i_blocks;
4665+*/
4666+ ia->i_mode = (h_inode->i_mode & S_IFMT);
4667+}
4668+
4669+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
4670+{
4671+ return ia->i_ino != h_inode->i_ino
4672+ /* || ia->i_nlink != h_inode->i_nlink */
4673+ || ia->i_uid != h_inode->i_uid
4674+ || ia->i_gid != h_inode->i_gid
4675+ || ia->i_version != h_inode->i_version
4676+/*
4677+ || ia->i_size != h_inode->i_size
4678+ || ia->i_blocks != h_inode->i_blocks
4679+*/
4680+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
4681+}
4682+
4683+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
4684+ struct au_branch *br)
4685+{
4686+ int err;
4687+ struct au_iattr ia;
4688+ struct inode *h_inode;
4689+ struct dentry *h_d;
4690+ struct super_block *h_sb;
4691+
4692+ err = 0;
4693+ memset(&ia, -1, sizeof(ia));
4694+ h_sb = h_dentry->d_sb;
4695+ h_inode = h_dentry->d_inode;
4696+ if (h_inode)
4697+ au_iattr_save(&ia, h_inode);
4698+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
4699+ /* nfs d_revalidate may return 0 for negative dentry */
4700+ /* fuse d_revalidate always return 0 for negative dentry */
4701+ goto out;
4702+
4703+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
4704+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
4705+ err = PTR_ERR(h_d);
4706+ if (IS_ERR(h_d))
4707+ goto out;
4708+
4709+ err = 0;
4710+ if (unlikely(h_d != h_dentry
4711+ || h_d->d_inode != h_inode
4712+ || (h_inode && au_iattr_test(&ia, h_inode))))
4713+ err = au_busy_or_stale();
4714+ dput(h_d);
4715+
4716+ out:
4717+ AuTraceErr(err);
4718+ return err;
4719+}
4720+
4721+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
4722+ struct dentry *h_parent, struct au_branch *br)
4723+{
4724+ int err;
4725+
4726+ err = 0;
4727+ if (udba == AuOpt_UDBA_REVAL) {
4728+ IMustLock(h_dir);
4729+ err = (h_dentry->d_parent->d_inode != h_dir);
4a4d8108 4730+ } else if (udba == AuOpt_UDBA_HNOTIFY)
1facf9fc 4731+ err = au_h_verify_dentry(h_dentry, h_parent, br);
4732+
4733+ return err;
4734+}
4735+
4736+/* ---------------------------------------------------------------------- */
4737+
4738+static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
4739+ struct dentry *parent)
4740+{
4741+ struct dentry *h_d, *h_dp;
4742+ struct au_hdentry tmp, *q;
4743+ struct super_block *sb;
4744+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
4745+
1308ab2a 4746+ AuRwMustWriteLock(&dinfo->di_rwsem);
4747+
1facf9fc 4748+ bend = dinfo->di_bend;
4749+ bwh = dinfo->di_bwh;
4750+ bdiropq = dinfo->di_bdiropq;
4751+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
4752+ h_d = p->hd_dentry;
4753+ if (!h_d)
4754+ continue;
4755+
4756+ h_dp = dget_parent(h_d);
4757+ if (h_dp == au_h_dptr(parent, bindex)) {
4758+ dput(h_dp);
4759+ continue;
4760+ }
4761+
4762+ new_bindex = au_find_dbindex(parent, h_dp);
4763+ dput(h_dp);
4764+ if (dinfo->di_bwh == bindex)
4765+ bwh = new_bindex;
4766+ if (dinfo->di_bdiropq == bindex)
4767+ bdiropq = new_bindex;
4768+ if (new_bindex < 0) {
4769+ au_hdput(p);
4770+ p->hd_dentry = NULL;
4771+ continue;
4772+ }
4773+
4774+ /* swap two lower dentries, and loop again */
4775+ q = dinfo->di_hdentry + new_bindex;
4776+ tmp = *q;
4777+ *q = *p;
4778+ *p = tmp;
4779+ if (tmp.hd_dentry) {
4780+ bindex--;
4781+ p--;
4782+ }
4783+ }
4784+
4785+ sb = parent->d_sb;
4786+ dinfo->di_bwh = -1;
4787+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
4788+ dinfo->di_bwh = bwh;
4789+
4790+ dinfo->di_bdiropq = -1;
4791+ if (bdiropq >= 0
4792+ && bdiropq <= au_sbend(sb)
4793+ && au_sbr_whable(sb, bdiropq))
4794+ dinfo->di_bdiropq = bdiropq;
4795+
4796+ bend = au_dbend(parent);
4797+ p = dinfo->di_hdentry;
4798+ for (bindex = 0; bindex <= bend; bindex++, p++)
4799+ if (p->hd_dentry) {
4800+ dinfo->di_bstart = bindex;
4801+ break;
4802+ }
4803+
4804+ p = dinfo->di_hdentry + bend;
4805+ for (bindex = bend; bindex >= 0; bindex--, p--)
4806+ if (p->hd_dentry) {
4807+ dinfo->di_bend = bindex;
4808+ break;
4809+ }
4810+}
4811+
4812+/*
4813+ * returns the number of found lower positive dentries,
4814+ * otherwise an error.
4815+ */
4816+int au_refresh_hdentry(struct dentry *dentry, mode_t type)
4817+{
4818+ int npositive, err;
4819+ unsigned int sigen;
4820+ aufs_bindex_t bstart;
4821+ struct au_dinfo *dinfo;
4822+ struct super_block *sb;
4823+ struct dentry *parent;
4824+
1308ab2a 4825+ DiMustWriteLock(dentry);
4826+
1facf9fc 4827+ sb = dentry->d_sb;
4828+ AuDebugOn(IS_ROOT(dentry));
4829+ sigen = au_sigen(sb);
4830+ parent = dget_parent(dentry);
4831+ AuDebugOn(au_digen(parent) != sigen
4832+ || au_iigen(parent->d_inode) != sigen);
4833+
4834+ dinfo = au_di(dentry);
4835+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
4836+ npositive = err;
4837+ if (unlikely(err))
4838+ goto out;
4839+ au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
4840+ parent);
4841+
4842+ npositive = 0;
4843+ bstart = au_dbstart(parent);
4844+ if (type != S_IFDIR && dinfo->di_bstart == bstart)
4845+ goto out_dgen; /* success */
4846+
4847+ npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
4848+ if (npositive < 0)
4849+ goto out;
4850+ if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
4851+ d_drop(dentry);
4852+
4853+ out_dgen:
4854+ au_update_digen(dentry);
4855+ out:
4856+ dput(parent);
4857+ AuTraceErr(npositive);
4858+ return npositive;
4859+}
4860+
4861+static noinline_for_stack
4862+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
4863+ struct dentry *dentry, aufs_bindex_t bindex)
4864+{
4865+ int err, valid;
4866+ int (*reval)(struct dentry *, struct nameidata *);
4867+
4868+ err = 0;
4869+ reval = NULL;
4870+ if (h_dentry->d_op)
4871+ reval = h_dentry->d_op->d_revalidate;
4872+ if (!reval)
4873+ goto out;
4874+
4875+ AuDbg("b%d\n", bindex);
4876+ if (au_test_fs_null_nd(h_dentry->d_sb))
4877+ /* it may return tri-state */
4878+ valid = reval(h_dentry, NULL);
4879+ else {
4880+ struct nameidata h_nd;
4881+ int locked;
4882+ struct dentry *parent;
4883+
4884+ au_h_nd(&h_nd, nd);
4885+ parent = nd->path.dentry;
4886+ locked = (nd && nd->path.dentry != dentry);
4887+ if (locked)
4888+ di_read_lock_parent(parent, AuLock_IR);
4889+ BUG_ON(bindex > au_dbend(parent));
4890+ h_nd.path.dentry = au_h_dptr(parent, bindex);
4891+ BUG_ON(!h_nd.path.dentry);
4892+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
4893+ path_get(&h_nd.path);
4894+ valid = reval(h_dentry, &h_nd);
4895+ path_put(&h_nd.path);
4896+ if (locked)
4897+ di_read_unlock(parent, AuLock_IR);
4898+ }
4899+
4900+ if (unlikely(valid < 0))
4901+ err = valid;
4902+ else if (!valid)
4903+ err = -EINVAL;
4904+
4905+ out:
4906+ AuTraceErr(err);
4907+ return err;
4908+}
4909+
4910+/* todo: remove this */
4911+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
4912+ struct nameidata *nd, int do_udba)
4913+{
4914+ int err;
4915+ umode_t mode, h_mode;
4916+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
4917+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 4918+ struct inode *h_inode, *h_cached_inode;
1facf9fc 4919+ struct dentry *h_dentry;
4920+ struct qstr *name, *h_name;
4921+
4922+ err = 0;
4923+ plus = 0;
4924+ mode = 0;
1facf9fc 4925+ ibs = -1;
4926+ ibe = -1;
4927+ unhashed = !!d_unhashed(dentry);
4928+ is_root = !!IS_ROOT(dentry);
4929+ name = &dentry->d_name;
4930+
4931+ /*
4932+ * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
4933+ * But inotify doesn't fire some necessary events,
4934+ * IN_ATTRIB for atime/nlink/pageio
4935+ * IN_DELETE for NFS dentry
4936+ * Let's do REVAL test too.
4937+ */
4938+ if (do_udba && inode) {
4939+ mode = (inode->i_mode & S_IFMT);
4940+ plus = (inode->i_nlink > 0);
1facf9fc 4941+ ibs = au_ibstart(inode);
4942+ ibe = au_ibend(inode);
4943+ }
4944+
4945+ bstart = au_dbstart(dentry);
4946+ btail = bstart;
4947+ if (inode && S_ISDIR(inode->i_mode))
4948+ btail = au_dbtaildir(dentry);
4949+ for (bindex = bstart; bindex <= btail; bindex++) {
4950+ h_dentry = au_h_dptr(dentry, bindex);
4951+ if (!h_dentry)
4952+ continue;
4953+
4954+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
4955+ h_name = &h_dentry->d_name;
4956+ if (unlikely(do_udba
4957+ && !is_root
4958+ && (unhashed != !!d_unhashed(h_dentry)
4959+ || name->len != h_name->len
4960+ || memcmp(name->name, h_name->name, name->len))
4961+ )) {
4962+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
4963+ unhashed, d_unhashed(h_dentry),
4964+ AuDLNPair(dentry), AuDLNPair(h_dentry));
4965+ goto err;
4966+ }
4967+
4968+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
4969+ if (unlikely(err))
4970+ /* do not goto err, to keep the errno */
4971+ break;
4972+
4973+ /* todo: plink too? */
4974+ if (!do_udba)
4975+ continue;
4976+
4977+ /* UDBA tests */
4978+ h_inode = h_dentry->d_inode;
4979+ if (unlikely(!!inode != !!h_inode))
4980+ goto err;
4981+
4982+ h_plus = plus;
4983+ h_mode = mode;
4984+ h_cached_inode = h_inode;
4985+ if (h_inode) {
4986+ h_mode = (h_inode->i_mode & S_IFMT);
4987+ h_plus = (h_inode->i_nlink > 0);
4988+ }
4989+ if (inode && ibs <= bindex && bindex <= ibe)
4990+ h_cached_inode = au_h_iptr(inode, bindex);
4991+
4992+ if (unlikely(plus != h_plus
4993+ || mode != h_mode
4994+ || h_cached_inode != h_inode))
4995+ goto err;
4996+ continue;
4997+
4998+ err:
4999+ err = -EINVAL;
5000+ break;
5001+ }
5002+
5003+ return err;
5004+}
5005+
5006+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
5007+{
5008+ int err;
5009+ struct dentry *parent;
5010+ struct inode *inode;
5011+
5012+ inode = dentry->d_inode;
5013+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
5014+ return 0;
5015+
5016+ parent = dget_parent(dentry);
5017+ di_read_lock_parent(parent, AuLock_IR);
5018+ AuDebugOn(au_digen(parent) != sigen
5019+ || au_iigen(parent->d_inode) != sigen);
5020+ au_dbg_verify_gen(parent, sigen);
5021+
5022+ /* returns a number of positive dentries */
5023+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
5024+ if (err >= 0)
5025+ err = au_refresh_hinode(inode, dentry);
5026+
5027+ di_read_unlock(parent, AuLock_IR);
5028+ dput(parent);
5029+ return err;
5030+}
5031+
5032+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
5033+{
5034+ int err;
5035+ struct dentry *d, *parent;
5036+ struct inode *inode;
5037+
5038+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
5039+ return simple_reval_dpath(dentry, sigen);
5040+
5041+ /* slow loop, keep it simple and stupid */
5042+ /* cf: au_cpup_dirs() */
5043+ err = 0;
5044+ parent = NULL;
5045+ while (au_digen(dentry) != sigen
5046+ || au_iigen(dentry->d_inode) != sigen) {
5047+ d = dentry;
5048+ while (1) {
5049+ dput(parent);
5050+ parent = dget_parent(d);
5051+ if (au_digen(parent) == sigen
5052+ && au_iigen(parent->d_inode) == sigen)
5053+ break;
5054+ d = parent;
5055+ }
5056+
5057+ inode = d->d_inode;
5058+ if (d != dentry)
5059+ di_write_lock_child(d);
5060+
5061+ /* someone might update our dentry while we were sleeping */
5062+ if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
5063+ di_read_lock_parent(parent, AuLock_IR);
5064+ /* returns a number of positive dentries */
5065+ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
5066+ if (err >= 0)
5067+ err = au_refresh_hinode(inode, d);
5068+ di_read_unlock(parent, AuLock_IR);
5069+ }
5070+
5071+ if (d != dentry)
5072+ di_write_unlock(d);
5073+ dput(parent);
5074+ if (unlikely(err))
5075+ break;
5076+ }
5077+
5078+ return err;
5079+}
5080+
5081+/*
5082+ * if valid returns 1, otherwise 0.
5083+ */
5084+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
5085+{
5086+ int valid, err;
5087+ unsigned int sigen;
5088+ unsigned char do_udba;
5089+ struct super_block *sb;
5090+ struct inode *inode;
5091+
5092+ err = -EINVAL;
5093+ sb = dentry->d_sb;
5094+ inode = dentry->d_inode;
5095+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
5096+ sigen = au_sigen(sb);
5097+ if (au_digen(dentry) != sigen) {
5098+ AuDebugOn(IS_ROOT(dentry));
5099+ if (inode)
5100+ err = au_reval_dpath(dentry, sigen);
5101+ if (unlikely(err))
5102+ goto out_dgrade;
1facf9fc 5103+ }
5104+ if (inode && au_iigen(inode) != sigen) {
5105+ AuDebugOn(IS_ROOT(dentry));
5106+ err = au_refresh_hinode(inode, dentry);
5107+ if (unlikely(err))
5108+ goto out_dgrade;
1facf9fc 5109+ }
5110+ di_downgrade_lock(dentry, AuLock_IR);
5111+
1facf9fc 5112+ err = -EINVAL;
5113+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
5114+ if (do_udba && inode) {
5115+ aufs_bindex_t bstart = au_ibstart(inode);
5116+
5117+ if (bstart >= 0
5118+ && au_test_higen(inode, au_h_iptr(inode, bstart)))
5119+ goto out;
5120+ }
5121+
5122+ err = h_d_revalidate(dentry, inode, nd, do_udba);
5123+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
5124+ /* both of real entry and whiteout found */
5125+ err = -EIO;
5126+ goto out;
5127+
5128+ out_dgrade:
5129+ di_downgrade_lock(dentry, AuLock_IR);
5130+ out:
1facf9fc 5131+ aufs_read_unlock(dentry, AuLock_IR);
5132+ AuTraceErr(err);
5133+ valid = !err;
5134+ if (!valid)
5135+ AuDbg("%.*s invalid\n", AuDLNPair(dentry));
5136+ return valid;
5137+}
5138+
5139+static void aufs_d_release(struct dentry *dentry)
5140+{
4a4d8108
AM
5141+ if (dentry->d_fsdata) {
5142+ au_di_fin(dentry);
5143+ au_hn_di_reinit(dentry);
1facf9fc 5144+ }
1facf9fc 5145+}
5146+
4a4d8108 5147+const struct dentry_operations aufs_dop = {
1facf9fc 5148+ .d_revalidate = aufs_d_revalidate,
5149+ .d_release = aufs_d_release
5150+};
b752ccd1
AM
5151diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
5152--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
5153+++ linux/fs/aufs/dentry.h 2010-08-21 21:00:02.975972487 +0200
1308ab2a 5154@@ -0,0 +1,231 @@
1facf9fc 5155+/*
4a4d8108 5156+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5157+ *
5158+ * This program, aufs is free software; you can redistribute it and/or modify
5159+ * it under the terms of the GNU General Public License as published by
5160+ * the Free Software Foundation; either version 2 of the License, or
5161+ * (at your option) any later version.
dece6358
AM
5162+ *
5163+ * This program is distributed in the hope that it will be useful,
5164+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5165+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5166+ * GNU General Public License for more details.
5167+ *
5168+ * You should have received a copy of the GNU General Public License
5169+ * along with this program; if not, write to the Free Software
5170+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5171+ */
5172+
5173+/*
5174+ * lookup and dentry operations
5175+ */
5176+
5177+#ifndef __AUFS_DENTRY_H__
5178+#define __AUFS_DENTRY_H__
5179+
5180+#ifdef __KERNEL__
5181+
dece6358 5182+#include <linux/dcache.h>
1facf9fc 5183+#include <linux/aufs_type.h>
5184+#include "rwsem.h"
5185+
5186+/* make a single member structure for future use */
5187+/* todo: remove this structure */
5188+struct au_hdentry {
5189+ struct dentry *hd_dentry;
5190+};
5191+
5192+struct au_dinfo {
5193+ atomic_t di_generation;
5194+
dece6358 5195+ struct au_rwsem di_rwsem;
1facf9fc 5196+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
5197+ struct au_hdentry *di_hdentry;
4a4d8108 5198+} ____cacheline_aligned_in_smp;
1facf9fc 5199+
5200+/* ---------------------------------------------------------------------- */
5201+
5202+/* dentry.c */
4a4d8108 5203+extern const struct dentry_operations aufs_dop;
1facf9fc 5204+struct au_branch;
5205+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
5206+ struct au_branch *br, struct nameidata *nd);
5207+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
5208+ struct au_branch *br);
5209+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
5210+ struct dentry *h_parent, struct au_branch *br);
5211+
5212+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
5213+ struct nameidata *nd);
5214+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
5215+int au_refresh_hdentry(struct dentry *dentry, mode_t type);
5216+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
5217+
5218+/* dinfo.c */
4a4d8108
AM
5219+void au_di_init_once(void *_di);
5220+int au_di_init(struct dentry *dentry);
5221+void au_di_fin(struct dentry *dentry);
1facf9fc 5222+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
5223+
5224+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
5225+void di_read_unlock(struct dentry *d, int flags);
5226+void di_downgrade_lock(struct dentry *d, int flags);
5227+void di_write_lock(struct dentry *d, unsigned int lsc);
5228+void di_write_unlock(struct dentry *d);
5229+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
5230+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
5231+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
5232+
5233+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
5234+aufs_bindex_t au_dbtail(struct dentry *dentry);
5235+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
5236+
5237+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5238+ struct dentry *h_dentry);
5239+void au_update_digen(struct dentry *dentry);
5240+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5241+void au_update_dbstart(struct dentry *dentry);
5242+void au_update_dbend(struct dentry *dentry);
5243+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
5244+
5245+/* ---------------------------------------------------------------------- */
5246+
5247+static inline struct au_dinfo *au_di(struct dentry *dentry)
5248+{
5249+ return dentry->d_fsdata;
5250+}
5251+
5252+/* ---------------------------------------------------------------------- */
5253+
5254+/* lock subclass for dinfo */
5255+enum {
5256+ AuLsc_DI_CHILD, /* child first */
4a4d8108 5257+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 5258+ AuLsc_DI_CHILD3, /* copyup dirs */
5259+ AuLsc_DI_PARENT,
5260+ AuLsc_DI_PARENT2,
5261+ AuLsc_DI_PARENT3
5262+};
5263+
5264+/*
5265+ * di_read_lock_child, di_write_lock_child,
5266+ * di_read_lock_child2, di_write_lock_child2,
5267+ * di_read_lock_child3, di_write_lock_child3,
5268+ * di_read_lock_parent, di_write_lock_parent,
5269+ * di_read_lock_parent2, di_write_lock_parent2,
5270+ * di_read_lock_parent3, di_write_lock_parent3,
5271+ */
5272+#define AuReadLockFunc(name, lsc) \
5273+static inline void di_read_lock_##name(struct dentry *d, int flags) \
5274+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
5275+
5276+#define AuWriteLockFunc(name, lsc) \
5277+static inline void di_write_lock_##name(struct dentry *d) \
5278+{ di_write_lock(d, AuLsc_DI_##lsc); }
5279+
5280+#define AuRWLockFuncs(name, lsc) \
5281+ AuReadLockFunc(name, lsc) \
5282+ AuWriteLockFunc(name, lsc)
5283+
5284+AuRWLockFuncs(child, CHILD);
5285+AuRWLockFuncs(child2, CHILD2);
5286+AuRWLockFuncs(child3, CHILD3);
5287+AuRWLockFuncs(parent, PARENT);
5288+AuRWLockFuncs(parent2, PARENT2);
5289+AuRWLockFuncs(parent3, PARENT3);
5290+
5291+#undef AuReadLockFunc
5292+#undef AuWriteLockFunc
5293+#undef AuRWLockFuncs
5294+
5295+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
5296+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
5297+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 5298+
5299+/* ---------------------------------------------------------------------- */
5300+
5301+/* todo: memory barrier? */
5302+static inline unsigned int au_digen(struct dentry *d)
5303+{
5304+ return atomic_read(&au_di(d)->di_generation);
5305+}
5306+
5307+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
5308+{
5309+ hdentry->hd_dentry = NULL;
5310+}
5311+
5312+static inline void au_hdput(struct au_hdentry *hd)
5313+{
4a4d8108
AM
5314+ if (hd)
5315+ dput(hd->hd_dentry);
1facf9fc 5316+}
5317+
5318+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
5319+{
1308ab2a 5320+ DiMustAnyLock(dentry);
1facf9fc 5321+ return au_di(dentry)->di_bstart;
5322+}
5323+
5324+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
5325+{
1308ab2a 5326+ DiMustAnyLock(dentry);
1facf9fc 5327+ return au_di(dentry)->di_bend;
5328+}
5329+
5330+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
5331+{
1308ab2a 5332+ DiMustAnyLock(dentry);
1facf9fc 5333+ return au_di(dentry)->di_bwh;
5334+}
5335+
5336+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
5337+{
1308ab2a 5338+ DiMustAnyLock(dentry);
1facf9fc 5339+ return au_di(dentry)->di_bdiropq;
5340+}
5341+
5342+/* todo: hard/soft set? */
5343+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
5344+{
1308ab2a 5345+ DiMustWriteLock(dentry);
1facf9fc 5346+ au_di(dentry)->di_bstart = bindex;
5347+}
5348+
5349+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
5350+{
1308ab2a 5351+ DiMustWriteLock(dentry);
1facf9fc 5352+ au_di(dentry)->di_bend = bindex;
5353+}
5354+
5355+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
5356+{
1308ab2a 5357+ DiMustWriteLock(dentry);
1facf9fc 5358+ /* dbwh can be outside of bstart - bend range */
5359+ au_di(dentry)->di_bwh = bindex;
5360+}
5361+
5362+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
5363+{
1308ab2a 5364+ DiMustWriteLock(dentry);
1facf9fc 5365+ au_di(dentry)->di_bdiropq = bindex;
5366+}
5367+
5368+/* ---------------------------------------------------------------------- */
5369+
4a4d8108 5370+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 5371+static inline void au_digen_dec(struct dentry *d)
5372+{
dece6358 5373+ atomic_dec_return(&au_di(d)->di_generation);
1facf9fc 5374+}
5375+
4a4d8108 5376+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 5377+{
5378+ dentry->d_fsdata = NULL;
5379+}
5380+#else
4a4d8108
AM
5381+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
5382+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 5383+
5384+#endif /* __KERNEL__ */
5385+#endif /* __AUFS_DENTRY_H__ */
b752ccd1
AM
5386diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
5387--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
5388+++ linux/fs/aufs/dinfo.c 2010-08-21 21:00:02.975972487 +0200
4a4d8108 5389@@ -0,0 +1,395 @@
1facf9fc 5390+/*
4a4d8108 5391+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5392+ *
5393+ * This program, aufs is free software; you can redistribute it and/or modify
5394+ * it under the terms of the GNU General Public License as published by
5395+ * the Free Software Foundation; either version 2 of the License, or
5396+ * (at your option) any later version.
dece6358
AM
5397+ *
5398+ * This program is distributed in the hope that it will be useful,
5399+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5400+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5401+ * GNU General Public License for more details.
5402+ *
5403+ * You should have received a copy of the GNU General Public License
5404+ * along with this program; if not, write to the Free Software
5405+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5406+ */
5407+
5408+/*
5409+ * dentry private data
5410+ */
5411+
5412+#include "aufs.h"
5413+
4a4d8108
AM
5414+void au_di_init_once(void *_di)
5415+{
5416+ struct au_dinfo *di = _di;
5417+
5418+ au_rw_init(&di->di_rwsem);
5419+}
5420+
5421+int au_di_init(struct dentry *dentry)
1facf9fc 5422+{
5423+ struct au_dinfo *dinfo;
5424+ struct super_block *sb;
5425+ int nbr;
5426+
5427+ dinfo = au_cache_alloc_dinfo();
5428+ if (unlikely(!dinfo))
5429+ goto out;
5430+
5431+ sb = dentry->d_sb;
5432+ nbr = au_sbend(sb) + 1;
5433+ if (nbr <= 0)
5434+ nbr = 1;
5435+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
5436+ if (unlikely(!dinfo->di_hdentry))
5437+ goto out_dinfo;
5438+
5439+ atomic_set(&dinfo->di_generation, au_sigen(sb));
5440+ /* smp_mb(); */ /* atomic_set */
4a4d8108 5441+ au_rw_write_lock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
1facf9fc 5442+ dinfo->di_bstart = -1;
5443+ dinfo->di_bend = -1;
5444+ dinfo->di_bwh = -1;
5445+ dinfo->di_bdiropq = -1;
5446+
5447+ dentry->d_fsdata = dinfo;
5448+ dentry->d_op = &aufs_dop;
5449+ return 0; /* success */
5450+
5451+ out_dinfo:
5452+ au_cache_free_dinfo(dinfo);
5453+ out:
5454+ return -ENOMEM;
5455+}
5456+
4a4d8108
AM
5457+void au_di_fin(struct dentry *dentry)
5458+{
5459+ struct au_dinfo *di;
5460+ struct au_hdentry *p;
5461+ aufs_bindex_t bend, bindex;
5462+
5463+ /* dentry may not be revalidated */
5464+ di = dentry->d_fsdata;
5465+ bindex = di->di_bstart;
5466+ if (bindex >= 0) {
5467+ bend = di->di_bend;
5468+ p = di->di_hdentry + bindex;
5469+ while (bindex++ <= bend)
5470+ au_hdput(p++);
5471+ }
5472+ kfree(di->di_hdentry);
5473+ AuRwDestroy(&di->di_rwsem);
5474+ au_cache_free_dinfo(di);
5475+}
5476+
1facf9fc 5477+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
5478+{
5479+ int err, sz;
5480+ struct au_hdentry *hdp;
5481+
1308ab2a 5482+ AuRwMustWriteLock(&dinfo->di_rwsem);
5483+
1facf9fc 5484+ err = -ENOMEM;
5485+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
5486+ if (!sz)
5487+ sz = sizeof(*hdp);
5488+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
5489+ if (hdp) {
5490+ dinfo->di_hdentry = hdp;
5491+ err = 0;
5492+ }
5493+
5494+ return err;
5495+}
5496+
5497+/* ---------------------------------------------------------------------- */
5498+
5499+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
5500+{
5501+ switch (lsc) {
5502+ case AuLsc_DI_CHILD:
5503+ ii_write_lock_child(inode);
5504+ break;
5505+ case AuLsc_DI_CHILD2:
5506+ ii_write_lock_child2(inode);
5507+ break;
5508+ case AuLsc_DI_CHILD3:
5509+ ii_write_lock_child3(inode);
5510+ break;
5511+ case AuLsc_DI_PARENT:
5512+ ii_write_lock_parent(inode);
5513+ break;
5514+ case AuLsc_DI_PARENT2:
5515+ ii_write_lock_parent2(inode);
5516+ break;
5517+ case AuLsc_DI_PARENT3:
5518+ ii_write_lock_parent3(inode);
5519+ break;
5520+ default:
5521+ BUG();
5522+ }
5523+}
5524+
5525+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
5526+{
5527+ switch (lsc) {
5528+ case AuLsc_DI_CHILD:
5529+ ii_read_lock_child(inode);
5530+ break;
5531+ case AuLsc_DI_CHILD2:
5532+ ii_read_lock_child2(inode);
5533+ break;
5534+ case AuLsc_DI_CHILD3:
5535+ ii_read_lock_child3(inode);
5536+ break;
5537+ case AuLsc_DI_PARENT:
5538+ ii_read_lock_parent(inode);
5539+ break;
5540+ case AuLsc_DI_PARENT2:
5541+ ii_read_lock_parent2(inode);
5542+ break;
5543+ case AuLsc_DI_PARENT3:
5544+ ii_read_lock_parent3(inode);
5545+ break;
5546+ default:
5547+ BUG();
5548+ }
5549+}
5550+
5551+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
5552+{
dece6358 5553+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5554+ if (d->d_inode) {
5555+ if (au_ftest_lock(flags, IW))
5556+ do_ii_write_lock(d->d_inode, lsc);
5557+ else if (au_ftest_lock(flags, IR))
5558+ do_ii_read_lock(d->d_inode, lsc);
5559+ }
5560+}
5561+
5562+void di_read_unlock(struct dentry *d, int flags)
5563+{
5564+ if (d->d_inode) {
5565+ if (au_ftest_lock(flags, IW))
5566+ ii_write_unlock(d->d_inode);
5567+ else if (au_ftest_lock(flags, IR))
5568+ ii_read_unlock(d->d_inode);
5569+ }
dece6358 5570+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 5571+}
5572+
5573+void di_downgrade_lock(struct dentry *d, int flags)
5574+{
1facf9fc 5575+ if (d->d_inode && au_ftest_lock(flags, IR))
5576+ ii_downgrade_lock(d->d_inode);
dece6358 5577+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 5578+}
5579+
5580+void di_write_lock(struct dentry *d, unsigned int lsc)
5581+{
dece6358 5582+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5583+ if (d->d_inode)
5584+ do_ii_write_lock(d->d_inode, lsc);
5585+}
5586+
5587+void di_write_unlock(struct dentry *d)
5588+{
5589+ if (d->d_inode)
5590+ ii_write_unlock(d->d_inode);
dece6358 5591+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 5592+}
5593+
5594+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
5595+{
5596+ AuDebugOn(d1 == d2
5597+ || d1->d_inode == d2->d_inode
5598+ || d1->d_sb != d2->d_sb);
5599+
5600+ if (isdir && au_test_subdir(d1, d2)) {
5601+ di_write_lock_child(d1);
5602+ di_write_lock_child2(d2);
5603+ } else {
5604+ /* there should be no races */
5605+ di_write_lock_child(d2);
5606+ di_write_lock_child2(d1);
5607+ }
5608+}
5609+
5610+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
5611+{
5612+ AuDebugOn(d1 == d2
5613+ || d1->d_inode == d2->d_inode
5614+ || d1->d_sb != d2->d_sb);
5615+
5616+ if (isdir && au_test_subdir(d1, d2)) {
5617+ di_write_lock_parent(d1);
5618+ di_write_lock_parent2(d2);
5619+ } else {
5620+ /* there should be no races */
5621+ di_write_lock_parent(d2);
5622+ di_write_lock_parent2(d1);
5623+ }
5624+}
5625+
5626+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
5627+{
5628+ di_write_unlock(d1);
5629+ if (d1->d_inode == d2->d_inode)
dece6358 5630+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 5631+ else
5632+ di_write_unlock(d2);
5633+}
5634+
5635+/* ---------------------------------------------------------------------- */
5636+
5637+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
5638+{
5639+ struct dentry *d;
5640+
1308ab2a 5641+ DiMustAnyLock(dentry);
5642+
1facf9fc 5643+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
5644+ return NULL;
5645+ AuDebugOn(bindex < 0);
5646+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
5647+ AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
5648+ return d;
5649+}
5650+
5651+aufs_bindex_t au_dbtail(struct dentry *dentry)
5652+{
5653+ aufs_bindex_t bend, bwh;
5654+
5655+ bend = au_dbend(dentry);
5656+ if (0 <= bend) {
5657+ bwh = au_dbwh(dentry);
5658+ if (!bwh)
5659+ return bwh;
5660+ if (0 < bwh && bwh < bend)
5661+ return bwh - 1;
5662+ }
5663+ return bend;
5664+}
5665+
5666+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
5667+{
5668+ aufs_bindex_t bend, bopq;
5669+
5670+ bend = au_dbtail(dentry);
5671+ if (0 <= bend) {
5672+ bopq = au_dbdiropq(dentry);
5673+ if (0 <= bopq && bopq < bend)
5674+ bend = bopq;
5675+ }
5676+ return bend;
5677+}
5678+
5679+/* ---------------------------------------------------------------------- */
5680+
5681+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5682+ struct dentry *h_dentry)
5683+{
5684+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
5685+
1308ab2a 5686+ DiMustWriteLock(dentry);
5687+
4a4d8108 5688+ au_hdput(hd);
1facf9fc 5689+ hd->hd_dentry = h_dentry;
5690+}
5691+
5692+void au_update_digen(struct dentry *dentry)
5693+{
5694+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
5695+ /* smp_mb(); */ /* atomic_set */
5696+}
5697+
5698+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
5699+{
5700+ struct au_dinfo *dinfo;
5701+ struct dentry *h_d;
4a4d8108 5702+ struct au_hdentry *hdp;
1facf9fc 5703+
1308ab2a 5704+ DiMustWriteLock(dentry);
5705+
1facf9fc 5706+ dinfo = au_di(dentry);
5707+ if (!dinfo || dinfo->di_bstart < 0)
5708+ return;
5709+
4a4d8108 5710+ hdp = dinfo->di_hdentry;
1facf9fc 5711+ if (do_put_zero) {
5712+ aufs_bindex_t bindex, bend;
5713+
5714+ bend = dinfo->di_bend;
5715+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 5716+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 5717+ if (h_d && !h_d->d_inode)
5718+ au_set_h_dptr(dentry, bindex, NULL);
5719+ }
5720+ }
5721+
5722+ dinfo->di_bstart = -1;
5723+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 5724+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 5725+ break;
5726+ if (dinfo->di_bstart > dinfo->di_bend) {
5727+ dinfo->di_bstart = -1;
5728+ dinfo->di_bend = -1;
5729+ return;
5730+ }
5731+
5732+ dinfo->di_bend++;
5733+ while (0 <= --dinfo->di_bend)
4a4d8108 5734+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 5735+ break;
5736+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
5737+}
5738+
5739+void au_update_dbstart(struct dentry *dentry)
5740+{
5741+ aufs_bindex_t bindex, bend;
5742+ struct dentry *h_dentry;
5743+
5744+ bend = au_dbend(dentry);
5745+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
5746+ h_dentry = au_h_dptr(dentry, bindex);
5747+ if (!h_dentry)
5748+ continue;
5749+ if (h_dentry->d_inode) {
5750+ au_set_dbstart(dentry, bindex);
5751+ return;
5752+ }
5753+ au_set_h_dptr(dentry, bindex, NULL);
5754+ }
5755+}
5756+
5757+void au_update_dbend(struct dentry *dentry)
5758+{
5759+ aufs_bindex_t bindex, bstart;
5760+ struct dentry *h_dentry;
5761+
5762+ bstart = au_dbstart(dentry);
5763+ for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
5764+ h_dentry = au_h_dptr(dentry, bindex);
5765+ if (!h_dentry)
5766+ continue;
5767+ if (h_dentry->d_inode) {
5768+ au_set_dbend(dentry, bindex);
5769+ return;
5770+ }
5771+ au_set_h_dptr(dentry, bindex, NULL);
5772+ }
5773+}
5774+
5775+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
5776+{
5777+ aufs_bindex_t bindex, bend;
5778+
5779+ bend = au_dbend(dentry);
5780+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
5781+ if (au_h_dptr(dentry, bindex) == h_dentry)
5782+ return bindex;
5783+ return -1;
5784+}
b752ccd1
AM
5785diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
5786--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
5787+++ linux/fs/aufs/dir.c 2010-08-21 21:00:02.975972487 +0200
5788@@ -0,0 +1,638 @@
1facf9fc 5789+/*
4a4d8108 5790+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5791+ *
5792+ * This program, aufs is free software; you can redistribute it and/or modify
5793+ * it under the terms of the GNU General Public License as published by
5794+ * the Free Software Foundation; either version 2 of the License, or
5795+ * (at your option) any later version.
dece6358
AM
5796+ *
5797+ * This program is distributed in the hope that it will be useful,
5798+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5799+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5800+ * GNU General Public License for more details.
5801+ *
5802+ * You should have received a copy of the GNU General Public License
5803+ * along with this program; if not, write to the Free Software
5804+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5805+ */
5806+
5807+/*
5808+ * directory operations
5809+ */
5810+
dece6358 5811+#include <linux/file.h>
1facf9fc 5812+#include <linux/fs_stack.h>
5813+#include "aufs.h"
5814+
5815+void au_add_nlink(struct inode *dir, struct inode *h_dir)
5816+{
5817+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5818+
5819+ dir->i_nlink += h_dir->i_nlink - 2;
5820+ if (h_dir->i_nlink < 2)
5821+ dir->i_nlink += 2;
5822+}
5823+
5824+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
5825+{
5826+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5827+
5828+ dir->i_nlink -= h_dir->i_nlink - 2;
5829+ if (h_dir->i_nlink < 2)
5830+ dir->i_nlink -= 2;
5831+}
5832+
1308ab2a 5833+loff_t au_dir_size(struct file *file, struct dentry *dentry)
5834+{
5835+ loff_t sz;
5836+ aufs_bindex_t bindex, bend;
5837+ struct file *h_file;
5838+ struct dentry *h_dentry;
5839+
5840+ sz = 0;
5841+ if (file) {
5842+ AuDebugOn(!file->f_dentry);
5843+ AuDebugOn(!file->f_dentry->d_inode);
5844+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
5845+
4a4d8108 5846+ bend = au_fbend_dir(file);
1308ab2a 5847+ for (bindex = au_fbstart(file);
5848+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5849+ bindex++) {
4a4d8108 5850+ h_file = au_hf_dir(file, bindex);
1308ab2a 5851+ if (h_file
5852+ && h_file->f_dentry
5853+ && h_file->f_dentry->d_inode)
5854+ sz += i_size_read(h_file->f_dentry->d_inode);
5855+ }
5856+ } else {
5857+ AuDebugOn(!dentry);
5858+ AuDebugOn(!dentry->d_inode);
5859+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
5860+
5861+ bend = au_dbtaildir(dentry);
5862+ for (bindex = au_dbstart(dentry);
5863+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5864+ bindex++) {
5865+ h_dentry = au_h_dptr(dentry, bindex);
5866+ if (h_dentry && h_dentry->d_inode)
5867+ sz += i_size_read(h_dentry->d_inode);
5868+ }
5869+ }
5870+ if (sz < KMALLOC_MAX_SIZE)
5871+ sz = roundup_pow_of_two(sz);
5872+ if (sz > KMALLOC_MAX_SIZE)
5873+ sz = KMALLOC_MAX_SIZE;
5874+ else if (sz < NAME_MAX) {
5875+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
5876+ sz = AUFS_RDBLK_DEF;
5877+ }
5878+ return sz;
5879+}
5880+
1facf9fc 5881+/* ---------------------------------------------------------------------- */
5882+
5883+static int reopen_dir(struct file *file)
5884+{
5885+ int err;
5886+ unsigned int flags;
5887+ aufs_bindex_t bindex, btail, bstart;
5888+ struct dentry *dentry, *h_dentry;
5889+ struct file *h_file;
5890+
5891+ /* open all lower dirs */
5892+ dentry = file->f_dentry;
5893+ bstart = au_dbstart(dentry);
5894+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
5895+ au_set_h_fptr(file, bindex, NULL);
5896+ au_set_fbstart(file, bstart);
5897+
5898+ btail = au_dbtaildir(dentry);
4a4d8108 5899+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 5900+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 5901+ au_set_fbend_dir(file, btail);
1facf9fc 5902+
4a4d8108 5903+ flags = vfsub_file_flags(file);
1facf9fc 5904+ for (bindex = bstart; bindex <= btail; bindex++) {
5905+ h_dentry = au_h_dptr(dentry, bindex);
5906+ if (!h_dentry)
5907+ continue;
4a4d8108 5908+ h_file = au_hf_dir(file, bindex);
1facf9fc 5909+ if (h_file)
5910+ continue;
5911+
5912+ h_file = au_h_open(dentry, bindex, flags, file);
5913+ err = PTR_ERR(h_file);
5914+ if (IS_ERR(h_file))
5915+ goto out; /* close all? */
5916+ au_set_h_fptr(file, bindex, h_file);
5917+ }
5918+ au_update_figen(file);
5919+ /* todo: necessary? */
5920+ /* file->f_ra = h_file->f_ra; */
5921+ err = 0;
5922+
5923+ out:
5924+ return err;
5925+}
5926+
5927+static int do_open_dir(struct file *file, int flags)
5928+{
5929+ int err;
5930+ aufs_bindex_t bindex, btail;
5931+ struct dentry *dentry, *h_dentry;
5932+ struct file *h_file;
5933+
1308ab2a 5934+ FiMustWriteLock(file);
5935+
1facf9fc 5936+ err = 0;
5937+ dentry = file->f_dentry;
1facf9fc 5938+ file->f_version = dentry->d_inode->i_version;
5939+ bindex = au_dbstart(dentry);
5940+ au_set_fbstart(file, bindex);
5941+ btail = au_dbtaildir(dentry);
4a4d8108 5942+ au_set_fbend_dir(file, btail);
1facf9fc 5943+ for (; !err && bindex <= btail; bindex++) {
5944+ h_dentry = au_h_dptr(dentry, bindex);
5945+ if (!h_dentry)
5946+ continue;
5947+
5948+ h_file = au_h_open(dentry, bindex, flags, file);
5949+ if (IS_ERR(h_file)) {
5950+ err = PTR_ERR(h_file);
5951+ break;
5952+ }
5953+ au_set_h_fptr(file, bindex, h_file);
5954+ }
5955+ au_update_figen(file);
5956+ /* todo: necessary? */
5957+ /* file->f_ra = h_file->f_ra; */
5958+ if (!err)
5959+ return 0; /* success */
5960+
5961+ /* close all */
5962+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
5963+ au_set_h_fptr(file, bindex, NULL);
5964+ au_set_fbstart(file, -1);
4a4d8108
AM
5965+ au_set_fbend_dir(file, -1);
5966+
1facf9fc 5967+ return err;
5968+}
5969+
5970+static int aufs_open_dir(struct inode *inode __maybe_unused,
5971+ struct file *file)
5972+{
4a4d8108
AM
5973+ int err;
5974+ struct super_block *sb;
5975+ struct au_fidir *fidir;
5976+
5977+ err = -ENOMEM;
5978+ sb = file->f_dentry->d_sb;
5979+ si_read_lock(sb, AuLock_FLUSH);
5980+ fidir = au_fidir_alloc(inode->i_sb);
5981+ if (fidir) {
5982+ err = au_do_open(file, do_open_dir, fidir);
5983+ if (unlikely(err))
5984+ kfree(fidir);
5985+ }
5986+ si_read_unlock(sb);
5987+ return err;
1facf9fc 5988+}
5989+
5990+static int aufs_release_dir(struct inode *inode __maybe_unused,
5991+ struct file *file)
5992+{
5993+ struct au_vdir *vdir_cache;
5994+ struct super_block *sb;
4a4d8108
AM
5995+ struct au_finfo *finfo;
5996+ struct au_fidir *fidir;
5997+ aufs_bindex_t bindex, bend;
1facf9fc 5998+
4a4d8108 5999+ au_plink_maint_leave(file);
1facf9fc 6000+ sb = file->f_dentry->d_sb;
4a4d8108
AM
6001+ finfo = au_fi(file);
6002+ fidir = finfo->fi_hdir;
6003+ if (fidir) {
6004+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
6005+ if (vdir_cache)
6006+ au_vdir_free(vdir_cache);
6007+
6008+ bindex = finfo->fi_btop;
6009+ if (bindex >= 0) {
6010+ /*
6011+ * calls fput() instead of filp_close(),
6012+ * since no dnotify or lock for the lower file.
6013+ */
6014+ bend = fidir->fd_bbot;
6015+ for (; bindex <= bend; bindex++)
6016+ au_set_h_fptr(file, bindex, NULL);
6017+ }
6018+ kfree(fidir);
6019+ finfo->fi_hdir = NULL;
1facf9fc 6020+ }
1facf9fc 6021+ au_finfo_fin(file);
1facf9fc 6022+ return 0;
6023+}
6024+
6025+/* ---------------------------------------------------------------------- */
6026+
4a4d8108
AM
6027+static int au_do_flush_dir(struct file *file, fl_owner_t id)
6028+{
6029+ int err;
6030+ aufs_bindex_t bindex, bend;
6031+ struct file *h_file;
6032+
6033+ err = 0;
6034+ bend = au_fbend_dir(file);
6035+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
6036+ h_file = au_hf_dir(file, bindex);
6037+ if (h_file)
6038+ err = vfsub_flush(h_file, id);
6039+ }
6040+ return err;
6041+}
6042+
6043+static int aufs_flush_dir(struct file *file, fl_owner_t id)
6044+{
6045+ return au_do_flush(file, id, au_do_flush_dir);
6046+}
6047+
6048+/* ---------------------------------------------------------------------- */
6049+
1facf9fc 6050+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
6051+{
6052+ int err;
6053+ aufs_bindex_t bend, bindex;
6054+ struct inode *inode;
6055+ struct super_block *sb;
6056+
6057+ err = 0;
6058+ sb = dentry->d_sb;
6059+ inode = dentry->d_inode;
6060+ IMustLock(inode);
6061+ bend = au_dbend(dentry);
6062+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
6063+ struct path h_path;
6064+ struct inode *h_inode;
6065+
6066+ if (au_test_ro(sb, bindex, inode))
6067+ continue;
6068+ h_path.dentry = au_h_dptr(dentry, bindex);
6069+ if (!h_path.dentry)
6070+ continue;
6071+ h_inode = h_path.dentry->d_inode;
6072+ if (!h_inode)
6073+ continue;
6074+
6075+ /* no mnt_want_write() */
6076+ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
6077+ /* todo: inotiry fired? */
6078+ h_path.mnt = au_sbr_mnt(sb, bindex);
6079+ mutex_lock(&h_inode->i_mutex);
6080+ err = filemap_fdatawrite(h_inode->i_mapping);
6081+ AuDebugOn(!h_inode->i_fop);
6082+ if (!err && h_inode->i_fop->fsync)
b752ccd1 6083+ err = h_inode->i_fop->fsync(NULL, datasync);
1facf9fc 6084+ if (!err)
6085+ err = filemap_fdatawrite(h_inode->i_mapping);
6086+ if (!err)
6087+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
6088+ mutex_unlock(&h_inode->i_mutex);
6089+ }
6090+
6091+ return err;
6092+}
6093+
6094+static int au_do_fsync_dir(struct file *file, int datasync)
6095+{
6096+ int err;
6097+ aufs_bindex_t bend, bindex;
6098+ struct file *h_file;
6099+ struct super_block *sb;
6100+ struct inode *inode;
6101+ struct mutex *h_mtx;
6102+
6103+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6104+ if (unlikely(err))
6105+ goto out;
6106+
6107+ sb = file->f_dentry->d_sb;
6108+ inode = file->f_dentry->d_inode;
4a4d8108 6109+ bend = au_fbend_dir(file);
1facf9fc 6110+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 6111+ h_file = au_hf_dir(file, bindex);
1facf9fc 6112+ if (!h_file || au_test_ro(sb, bindex, inode))
6113+ continue;
6114+
b752ccd1 6115+ err = vfs_fsync(h_file, datasync);
1facf9fc 6116+ if (!err) {
6117+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
6118+ mutex_lock(h_mtx);
6119+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
6120+ /*ignore*/
6121+ mutex_unlock(h_mtx);
6122+ }
6123+ }
6124+
6125+ out:
6126+ return err;
6127+}
6128+
6129+/*
6130+ * @file may be NULL
6131+ */
b752ccd1 6132+static int aufs_fsync_dir(struct file *file, int datasync)
1facf9fc 6133+{
6134+ int err;
b752ccd1 6135+ struct dentry *dentry;
1facf9fc 6136+ struct super_block *sb;
6137+
b752ccd1 6138+ dentry = file->f_dentry;
1facf9fc 6139+ IMustLock(dentry->d_inode);
6140+
6141+ err = 0;
6142+ sb = dentry->d_sb;
6143+ si_noflush_read_lock(sb);
6144+ if (file)
6145+ err = au_do_fsync_dir(file, datasync);
6146+ else {
6147+ di_write_lock_child(dentry);
6148+ err = au_do_fsync_dir_no_file(dentry, datasync);
6149+ }
6150+ au_cpup_attr_timesizes(dentry->d_inode);
6151+ di_write_unlock(dentry);
6152+ if (file)
6153+ fi_write_unlock(file);
6154+
6155+ si_read_unlock(sb);
6156+ return err;
6157+}
6158+
6159+/* ---------------------------------------------------------------------- */
6160+
6161+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
6162+{
6163+ int err;
6164+ struct dentry *dentry;
6165+ struct inode *inode;
6166+ struct super_block *sb;
6167+
6168+ dentry = file->f_dentry;
6169+ inode = dentry->d_inode;
6170+ IMustLock(inode);
6171+
6172+ sb = dentry->d_sb;
6173+ si_read_lock(sb, AuLock_FLUSH);
6174+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6175+ if (unlikely(err))
6176+ goto out;
6177+ err = au_vdir_init(file);
6178+ di_downgrade_lock(dentry, AuLock_IR);
6179+ if (unlikely(err))
6180+ goto out_unlock;
6181+
b752ccd1 6182+ if (!au_test_nfsd()) {
1facf9fc 6183+ err = au_vdir_fill_de(file, dirent, filldir);
6184+ fsstack_copy_attr_atime(inode,
6185+ au_h_iptr(inode, au_ibstart(inode)));
6186+ } else {
6187+ /*
6188+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
6189+ * encode_fh() and others.
6190+ */
6191+ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
6192+
6193+ di_read_unlock(dentry, AuLock_IR);
6194+ si_read_unlock(sb);
1facf9fc 6195+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 6196+ fsstack_copy_attr_atime(inode, h_inode);
6197+ fi_write_unlock(file);
6198+
6199+ AuTraceErr(err);
6200+ return err;
6201+ }
6202+
6203+ out_unlock:
6204+ di_read_unlock(dentry, AuLock_IR);
6205+ fi_write_unlock(file);
6206+ out:
6207+ si_read_unlock(sb);
6208+ return err;
6209+}
6210+
6211+/* ---------------------------------------------------------------------- */
6212+
6213+#define AuTestEmpty_WHONLY 1
dece6358
AM
6214+#define AuTestEmpty_CALLED (1 << 1)
6215+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 6216+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
6217+#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
6218+#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
6219+
dece6358
AM
6220+#ifndef CONFIG_AUFS_SHWH
6221+#undef AuTestEmpty_SHWH
6222+#define AuTestEmpty_SHWH 0
6223+#endif
6224+
1facf9fc 6225+struct test_empty_arg {
1308ab2a 6226+ struct au_nhash *whlist;
1facf9fc 6227+ unsigned int flags;
6228+ int err;
6229+ aufs_bindex_t bindex;
6230+};
6231+
6232+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
6233+ loff_t offset __maybe_unused, u64 ino,
6234+ unsigned int d_type)
1facf9fc 6235+{
6236+ struct test_empty_arg *arg = __arg;
6237+ char *name = (void *)__name;
6238+
6239+ arg->err = 0;
6240+ au_fset_testempty(arg->flags, CALLED);
6241+ /* smp_mb(); */
6242+ if (name[0] == '.'
6243+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
6244+ goto out; /* success */
6245+
6246+ if (namelen <= AUFS_WH_PFX_LEN
6247+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
6248+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 6249+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6250+ arg->err = -ENOTEMPTY;
6251+ goto out;
6252+ }
6253+
6254+ name += AUFS_WH_PFX_LEN;
6255+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 6256+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6257+ arg->err = au_nhash_append_wh
1308ab2a 6258+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 6259+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 6260+
6261+ out:
6262+ /* smp_mb(); */
6263+ AuTraceErr(arg->err);
6264+ return arg->err;
6265+}
6266+
6267+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6268+{
6269+ int err;
6270+ struct file *h_file;
6271+
6272+ h_file = au_h_open(dentry, arg->bindex,
6273+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
6274+ /*file*/NULL);
6275+ err = PTR_ERR(h_file);
6276+ if (IS_ERR(h_file))
6277+ goto out;
6278+
6279+ err = 0;
6280+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
6281+ && !h_file->f_dentry->d_inode->i_nlink)
6282+ goto out_put;
6283+
6284+ do {
6285+ arg->err = 0;
6286+ au_fclr_testempty(arg->flags, CALLED);
6287+ /* smp_mb(); */
6288+ err = vfsub_readdir(h_file, test_empty_cb, arg);
6289+ if (err >= 0)
6290+ err = arg->err;
6291+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
6292+
6293+ out_put:
6294+ fput(h_file);
6295+ au_sbr_put(dentry->d_sb, arg->bindex);
6296+ out:
6297+ return err;
6298+}
6299+
6300+struct do_test_empty_args {
6301+ int *errp;
6302+ struct dentry *dentry;
6303+ struct test_empty_arg *arg;
6304+};
6305+
6306+static void call_do_test_empty(void *args)
6307+{
6308+ struct do_test_empty_args *a = args;
6309+ *a->errp = do_test_empty(a->dentry, a->arg);
6310+}
6311+
6312+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6313+{
6314+ int err, wkq_err;
6315+ struct dentry *h_dentry;
6316+ struct inode *h_inode;
6317+
6318+ h_dentry = au_h_dptr(dentry, arg->bindex);
6319+ h_inode = h_dentry->d_inode;
6320+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
6321+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
6322+ mutex_unlock(&h_inode->i_mutex);
6323+ if (!err)
6324+ err = do_test_empty(dentry, arg);
6325+ else {
6326+ struct do_test_empty_args args = {
6327+ .errp = &err,
6328+ .dentry = dentry,
6329+ .arg = arg
6330+ };
6331+ unsigned int flags = arg->flags;
6332+
6333+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
6334+ if (unlikely(wkq_err))
6335+ err = wkq_err;
6336+ arg->flags = flags;
6337+ }
6338+
6339+ return err;
6340+}
6341+
6342+int au_test_empty_lower(struct dentry *dentry)
6343+{
6344+ int err;
1308ab2a 6345+ unsigned int rdhash;
1facf9fc 6346+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 6347+ struct au_nhash whlist;
1facf9fc 6348+ struct test_empty_arg arg;
1facf9fc 6349+
dece6358
AM
6350+ SiMustAnyLock(dentry->d_sb);
6351+
1308ab2a 6352+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
6353+ if (!rdhash)
6354+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
6355+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 6356+ if (unlikely(err))
1facf9fc 6357+ goto out;
6358+
1facf9fc 6359+ arg.flags = 0;
1308ab2a 6360+ arg.whlist = &whlist;
6361+ bstart = au_dbstart(dentry);
dece6358
AM
6362+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6363+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 6364+ arg.bindex = bstart;
6365+ err = do_test_empty(dentry, &arg);
6366+ if (unlikely(err))
6367+ goto out_whlist;
6368+
6369+ au_fset_testempty(arg.flags, WHONLY);
6370+ btail = au_dbtaildir(dentry);
6371+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
6372+ struct dentry *h_dentry;
6373+
6374+ h_dentry = au_h_dptr(dentry, bindex);
6375+ if (h_dentry && h_dentry->d_inode) {
6376+ arg.bindex = bindex;
6377+ err = do_test_empty(dentry, &arg);
6378+ }
6379+ }
6380+
6381+ out_whlist:
1308ab2a 6382+ au_nhash_wh_free(&whlist);
1facf9fc 6383+ out:
6384+ return err;
6385+}
6386+
6387+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
6388+{
6389+ int err;
6390+ struct test_empty_arg arg;
6391+ aufs_bindex_t bindex, btail;
6392+
6393+ err = 0;
1308ab2a 6394+ arg.whlist = whlist;
1facf9fc 6395+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
6396+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6397+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 6398+ btail = au_dbtaildir(dentry);
6399+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
6400+ struct dentry *h_dentry;
6401+
6402+ h_dentry = au_h_dptr(dentry, bindex);
6403+ if (h_dentry && h_dentry->d_inode) {
6404+ arg.bindex = bindex;
6405+ err = sio_test_empty(dentry, &arg);
6406+ }
6407+ }
6408+
6409+ return err;
6410+}
6411+
6412+/* ---------------------------------------------------------------------- */
6413+
6414+const struct file_operations aufs_dir_fop = {
4a4d8108 6415+ .owner = THIS_MODULE,
1facf9fc 6416+ .read = generic_read_dir,
6417+ .readdir = aufs_readdir,
6418+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
6419+#ifdef CONFIG_COMPAT
6420+ .compat_ioctl = aufs_compat_ioctl_dir,
6421+#endif
1facf9fc 6422+ .open = aufs_open_dir,
6423+ .release = aufs_release_dir,
4a4d8108 6424+ .flush = aufs_flush_dir,
1facf9fc 6425+ .fsync = aufs_fsync_dir
6426+};
b752ccd1
AM
6427diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
6428--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
6429+++ linux/fs/aufs/dir.h 2010-08-21 21:00:02.975972487 +0200
6430@@ -0,0 +1,138 @@
1facf9fc 6431+/*
4a4d8108 6432+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 6433+ *
6434+ * This program, aufs is free software; you can redistribute it and/or modify
6435+ * it under the terms of the GNU General Public License as published by
6436+ * the Free Software Foundation; either version 2 of the License, or
6437+ * (at your option) any later version.
dece6358
AM
6438+ *
6439+ * This program is distributed in the hope that it will be useful,
6440+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6441+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6442+ * GNU General Public License for more details.
6443+ *
6444+ * You should have received a copy of the GNU General Public License
6445+ * along with this program; if not, write to the Free Software
6446+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6447+ */
6448+
6449+/*
6450+ * directory operations
6451+ */
6452+
6453+#ifndef __AUFS_DIR_H__
6454+#define __AUFS_DIR_H__
6455+
6456+#ifdef __KERNEL__
6457+
6458+#include <linux/fs.h>
6459+#include <linux/aufs_type.h>
6460+
6461+/* ---------------------------------------------------------------------- */
6462+
6463+/* need to be faster and smaller */
6464+
6465+struct au_nhash {
dece6358
AM
6466+ unsigned int nh_num;
6467+ struct hlist_head *nh_head;
1facf9fc 6468+};
6469+
6470+struct au_vdir_destr {
6471+ unsigned char len;
6472+ unsigned char name[0];
6473+} __packed;
6474+
6475+struct au_vdir_dehstr {
6476+ struct hlist_node hash;
6477+ struct au_vdir_destr *str;
4a4d8108 6478+} ____cacheline_aligned_in_smp;
1facf9fc 6479+
6480+struct au_vdir_de {
6481+ ino_t de_ino;
6482+ unsigned char de_type;
6483+ /* caution: packed */
6484+ struct au_vdir_destr de_str;
6485+} __packed;
6486+
6487+struct au_vdir_wh {
6488+ struct hlist_node wh_hash;
dece6358
AM
6489+#ifdef CONFIG_AUFS_SHWH
6490+ ino_t wh_ino;
1facf9fc 6491+ aufs_bindex_t wh_bindex;
dece6358
AM
6492+ unsigned char wh_type;
6493+#else
6494+ aufs_bindex_t wh_bindex;
6495+#endif
6496+ /* caution: packed */
1facf9fc 6497+ struct au_vdir_destr wh_str;
6498+} __packed;
6499+
6500+union au_vdir_deblk_p {
6501+ unsigned char *deblk;
6502+ struct au_vdir_de *de;
6503+};
6504+
6505+struct au_vdir {
6506+ unsigned char **vd_deblk;
6507+ unsigned long vd_nblk;
1facf9fc 6508+ struct {
6509+ unsigned long ul;
6510+ union au_vdir_deblk_p p;
6511+ } vd_last;
6512+
6513+ unsigned long vd_version;
dece6358 6514+ unsigned int vd_deblk_sz;
1facf9fc 6515+ unsigned long vd_jiffy;
4a4d8108 6516+} ____cacheline_aligned_in_smp;
1facf9fc 6517+
6518+/* ---------------------------------------------------------------------- */
6519+
6520+/* dir.c */
6521+extern const struct file_operations aufs_dir_fop;
6522+void au_add_nlink(struct inode *dir, struct inode *h_dir);
6523+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 6524+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 6525+int au_test_empty_lower(struct dentry *dentry);
6526+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
6527+
6528+/* vdir.c */
1308ab2a 6529+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
6530+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
6531+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 6532+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
6533+ int limit);
dece6358
AM
6534+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
6535+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
6536+ unsigned int d_type, aufs_bindex_t bindex,
6537+ unsigned char shwh);
1facf9fc 6538+void au_vdir_free(struct au_vdir *vdir);
6539+int au_vdir_init(struct file *file);
6540+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
6541+
6542+/* ioctl.c */
6543+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
6544+
1308ab2a 6545+#ifdef CONFIG_AUFS_RDU
6546+/* rdu.c */
6547+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
6548+#ifdef CONFIG_COMPAT
6549+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6550+ unsigned long arg);
6551+#endif
1308ab2a 6552+#else
6553+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
6554+ unsigned long arg)
6555+{
6556+ return -EINVAL;
6557+}
b752ccd1
AM
6558+#ifdef CONFIG_COMPAT
6559+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6560+ unsigned long arg)
6561+{
6562+ return -EINVAL;
6563+}
6564+#endif
1308ab2a 6565+#endif
6566+
1facf9fc 6567+#endif /* __KERNEL__ */
6568+#endif /* __AUFS_DIR_H__ */
b752ccd1
AM
6569diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
6570--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
6571+++ linux/fs/aufs/dynop.c 2010-08-21 21:00:02.975972487 +0200
6572@@ -0,0 +1,425 @@
1facf9fc 6573+/*
4a4d8108 6574+ * Copyright (C) 2010 Junjiro R. Okajima
1facf9fc 6575+ *
6576+ * This program, aufs is free software; you can redistribute it and/or modify
6577+ * it under the terms of the GNU General Public License as published by
6578+ * the Free Software Foundation; either version 2 of the License, or
6579+ * (at your option) any later version.
dece6358
AM
6580+ *
6581+ * This program is distributed in the hope that it will be useful,
6582+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6583+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6584+ * GNU General Public License for more details.
6585+ *
6586+ * You should have received a copy of the GNU General Public License
6587+ * along with this program; if not, write to the Free Software
6588+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6589+ */
6590+
6591+/*
4a4d8108 6592+ * dynamically customizable operations for regular files
1facf9fc 6593+ */
6594+
1facf9fc 6595+#include "aufs.h"
6596+
4a4d8108 6597+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 6598+
4a4d8108
AM
6599+/*
6600+ * How large will these lists be?
6601+ * Usually just a few elements, 20-30 at most for each, I guess.
6602+ */
6603+static struct au_splhead dynop[AuDyLast];
6604+
6605+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 6606+{
4a4d8108
AM
6607+ struct au_dykey *key, *tmp;
6608+ struct list_head *head;
1facf9fc 6609+
4a4d8108
AM
6610+ key = NULL;
6611+ head = &spl->head;
6612+ rcu_read_lock();
6613+ list_for_each_entry_rcu(tmp, head, dk_list)
6614+ if (tmp->dk_op.dy_hop == h_op) {
6615+ key = tmp;
6616+ kref_get(&key->dk_kref);
6617+ break;
6618+ }
6619+ rcu_read_unlock();
6620+
6621+ return key;
1facf9fc 6622+}
6623+
4a4d8108 6624+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 6625+{
4a4d8108
AM
6626+ struct au_dykey **k, *found;
6627+ const void *h_op = key->dk_op.dy_hop;
6628+ int i;
1facf9fc 6629+
4a4d8108
AM
6630+ found = NULL;
6631+ k = br->br_dykey;
6632+ for (i = 0; i < AuBrDynOp; i++)
6633+ if (k[i]) {
6634+ if (k[i]->dk_op.dy_hop == h_op) {
6635+ found = k[i];
6636+ break;
6637+ }
6638+ } else
6639+ break;
6640+ if (!found) {
6641+ spin_lock(&br->br_dykey_lock);
6642+ for (; i < AuBrDynOp; i++)
6643+ if (k[i]) {
6644+ if (k[i]->dk_op.dy_hop == h_op) {
6645+ found = k[i];
6646+ break;
6647+ }
6648+ } else {
6649+ k[i] = key;
6650+ break;
6651+ }
6652+ spin_unlock(&br->br_dykey_lock);
6653+ BUG_ON(i == AuBrDynOp); /* expand the array */
6654+ }
6655+
6656+ return found;
1facf9fc 6657+}
6658+
4a4d8108
AM
6659+/* kref_get() if @key is already added */
6660+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
6661+{
6662+ struct au_dykey *tmp, *found;
6663+ struct list_head *head;
6664+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 6665+
4a4d8108
AM
6666+ found = NULL;
6667+ head = &spl->head;
6668+ spin_lock(&spl->spin);
6669+ list_for_each_entry(tmp, head, dk_list)
6670+ if (tmp->dk_op.dy_hop == h_op) {
6671+ kref_get(&tmp->dk_kref);
6672+ found = tmp;
6673+ break;
6674+ }
6675+ if (!found)
6676+ list_add_rcu(&key->dk_list, head);
6677+ spin_unlock(&spl->spin);
1facf9fc 6678+
4a4d8108
AM
6679+ if (!found)
6680+ DyPrSym(key);
6681+ return found;
6682+}
6683+
6684+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 6685+{
4a4d8108
AM
6686+ struct au_dykey *key;
6687+
6688+ key = container_of(rcu, struct au_dykey, dk_rcu);
6689+ DyPrSym(key);
6690+ kfree(key);
1facf9fc 6691+}
6692+
4a4d8108
AM
6693+static void dy_free(struct kref *kref)
6694+{
6695+ struct au_dykey *key;
6696+ struct au_splhead *spl;
1facf9fc 6697+
4a4d8108
AM
6698+ key = container_of(kref, struct au_dykey, dk_kref);
6699+ spl = dynop + key->dk_op.dy_type;
6700+ au_spl_del_rcu(&key->dk_list, spl);
6701+ call_rcu(&key->dk_rcu, dy_free_rcu);
6702+}
6703+
6704+void au_dy_put(struct au_dykey *key)
1facf9fc 6705+{
4a4d8108
AM
6706+ kref_put(&key->dk_kref, dy_free);
6707+}
1facf9fc 6708+
4a4d8108
AM
6709+/* ---------------------------------------------------------------------- */
6710+
6711+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
6712+
6713+#ifdef CONFIG_AUFS_DEBUG
6714+#define DyDbgDeclare(cnt) unsigned int cnt = 0
6715+#define DyDbgInc(cnt) cnt++
6716+#else
6717+#define DyDbgDeclare(cnt) do {} while (0)
6718+#define DyDbgInc(cnt) do {} while (0)
6719+#endif
6720+
6721+#define DySet(func, dst, src, h_op, h_sb) do { \
6722+ DyDbgInc(cnt); \
6723+ if (h_op->func) { \
6724+ if (src.func) \
6725+ dst.func = src.func; \
6726+ else \
6727+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
6728+ } \
6729+} while (0)
6730+
6731+#define DySetForce(func, dst, src) do { \
6732+ AuDebugOn(!src.func); \
6733+ DyDbgInc(cnt); \
6734+ dst.func = src.func; \
6735+} while (0)
6736+
6737+#define DySetAop(func) \
6738+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
6739+#define DySetAopForce(func) \
6740+ DySetForce(func, dyaop->da_op, aufs_aop)
6741+
6742+static void dy_aop(struct au_dykey *key, const void *h_op,
6743+ struct super_block *h_sb __maybe_unused)
6744+{
6745+ struct au_dyaop *dyaop = (void *)key;
6746+ const struct address_space_operations *h_aop = h_op;
6747+ DyDbgDeclare(cnt);
6748+
6749+ AuDbg("%s\n", au_sbtype(h_sb));
6750+
6751+ DySetAop(writepage);
6752+ DySetAopForce(readpage); /* force */
6753+ DySetAop(sync_page);
6754+ DySetAop(writepages);
6755+ DySetAop(set_page_dirty);
6756+ DySetAop(readpages);
6757+ DySetAop(write_begin);
6758+ DySetAop(write_end);
6759+ DySetAop(bmap);
6760+ DySetAop(invalidatepage);
6761+ DySetAop(releasepage);
6762+ /* these two will be changed according to an aufs mount option */
6763+ DySetAop(direct_IO);
6764+ DySetAop(get_xip_mem);
6765+ DySetAop(migratepage);
6766+ DySetAop(launder_page);
6767+ DySetAop(is_partially_uptodate);
6768+ DySetAop(error_remove_page);
6769+
6770+ DyDbgSize(cnt, *h_aop);
6771+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
6772+}
6773+
6774+#define DySetVmop(func) \
6775+ DySet(func, dyvmop->dv_op, aufs_vm_ops, h_vmop, h_sb)
6776+#define DySetVmopForce(func) \
6777+ DySetForce(func, dyvmop->dv_op, aufs_vm_ops)
6778+
6779+static void dy_vmop(struct au_dykey *key, const void *h_op,
6780+ struct super_block *h_sb __maybe_unused)
6781+{
6782+ struct au_dyvmop *dyvmop = (void *)key;
6783+ const struct vm_operations_struct *h_vmop = h_op;
6784+ DyDbgDeclare(cnt);
6785+
6786+ AuDbg("%s\n", au_sbtype(h_sb));
6787+
6788+ DySetVmop(open);
6789+ DySetVmop(close);
6790+ DySetVmop(fault);
6791+ DySetVmop(page_mkwrite);
6792+ DySetVmop(access);
6793+#ifdef CONFIG_NUMA
6794+ DySetVmop(set_policy);
6795+ DySetVmop(get_policy);
6796+ DySetVmop(migrate);
6797+#endif
6798+
6799+ DyDbgSize(cnt, *h_vmop);
6800+}
6801+
6802+/* ---------------------------------------------------------------------- */
6803+
6804+static void dy_bug(struct kref *kref)
6805+{
6806+ BUG();
6807+}
6808+
6809+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
6810+{
6811+ struct au_dykey *key, *old;
6812+ struct au_splhead *spl;
b752ccd1 6813+ struct op {
4a4d8108 6814+ unsigned int sz;
b752ccd1
AM
6815+ void (*set)(struct au_dykey *key, const void *h_op,
6816+ struct super_block *h_sb __maybe_unused);
6817+ };
6818+ static const struct op a[] = {
4a4d8108
AM
6819+ [AuDy_AOP] = {
6820+ .sz = sizeof(struct au_dyaop),
b752ccd1 6821+ .set = dy_aop
4a4d8108
AM
6822+ },
6823+ [AuDy_VMOP] = {
6824+ .sz = sizeof(struct au_dyvmop),
b752ccd1 6825+ .set = dy_vmop
4a4d8108 6826+ }
b752ccd1
AM
6827+ };
6828+ const struct op *p;
4a4d8108
AM
6829+
6830+ spl = dynop + op->dy_type;
6831+ key = dy_gfind_get(spl, op->dy_hop);
6832+ if (key)
6833+ goto out_add; /* success */
6834+
6835+ p = a + op->dy_type;
6836+ key = kzalloc(p->sz, GFP_NOFS);
6837+ if (unlikely(!key)) {
6838+ key = ERR_PTR(-ENOMEM);
6839+ goto out;
6840+ }
6841+
6842+ key->dk_op.dy_hop = op->dy_hop;
6843+ kref_init(&key->dk_kref);
b752ccd1 6844+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
6845+ old = dy_gadd(spl, key);
6846+ if (old) {
6847+ kfree(key);
6848+ key = old;
6849+ }
6850+
6851+out_add:
6852+ old = dy_bradd(br, key);
6853+ if (old)
6854+ /* its ref-count should never be zero here */
6855+ kref_put(&key->dk_kref, dy_bug);
6856+out:
6857+ return key;
6858+}
6859+
6860+/* ---------------------------------------------------------------------- */
6861+/*
6862+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
6863+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
6864+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
6865+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
6866+ * See the aufs manual in detail.
6867+ *
6868+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
6869+ * performance of fadvise() and madvise() may be affected.
6870+ */
6871+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
6872+{
6873+ if (!do_dx) {
6874+ dyaop->da_op.direct_IO = NULL;
6875+ dyaop->da_op.get_xip_mem = NULL;
6876+ } else {
6877+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
6878+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
6879+ if (!dyaop->da_get_xip_mem)
6880+ dyaop->da_op.get_xip_mem = NULL;
6881+ }
6882+}
6883+
6884+static struct au_dyaop *dy_aget(struct au_branch *br,
6885+ const struct address_space_operations *h_aop,
6886+ int do_dx)
6887+{
6888+ struct au_dyaop *dyaop;
6889+ struct au_dynop op;
6890+
6891+ op.dy_type = AuDy_AOP;
6892+ op.dy_haop = h_aop;
6893+ dyaop = (void *)dy_get(&op, br);
6894+ if (IS_ERR(dyaop))
6895+ goto out;
6896+ dy_adx(dyaop, do_dx);
6897+
6898+out:
6899+ return dyaop;
6900+}
6901+
6902+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
6903+ struct inode *h_inode)
6904+{
6905+ int err, do_dx;
6906+ struct super_block *sb;
6907+ struct au_branch *br;
6908+ struct au_dyaop *dyaop;
6909+
6910+ AuDebugOn(!S_ISREG(h_inode->i_mode));
6911+ IiMustWriteLock(inode);
6912+
6913+ sb = inode->i_sb;
6914+ br = au_sbr(sb, bindex);
6915+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
6916+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
6917+ err = PTR_ERR(dyaop);
6918+ if (IS_ERR(dyaop))
6919+ /* unnecessary to call dy_fput() */
6920+ goto out;
6921+
6922+ err = 0;
6923+ inode->i_mapping->a_ops = &dyaop->da_op;
6924+
6925+out:
6926+ return err;
6927+}
6928+
b752ccd1
AM
6929+/*
6930+ * Is it safe to replace a_ops during the inode/file is in operation?
6931+ * Yes, I hope so.
6932+ */
6933+int au_dy_irefresh(struct inode *inode)
6934+{
6935+ int err;
6936+ aufs_bindex_t bstart;
6937+ struct inode *h_inode;
6938+
6939+ err = 0;
6940+ if (S_ISREG(inode->i_mode)) {
6941+ bstart = au_ibstart(inode);
6942+ h_inode = au_h_iptr(inode, bstart);
6943+ err = au_dy_iaop(inode, bstart, h_inode);
6944+ }
6945+ return err;
6946+}
6947+
4a4d8108
AM
6948+void au_dy_arefresh(int do_dx)
6949+{
6950+ struct au_splhead *spl;
6951+ struct list_head *head;
6952+ struct au_dykey *key;
6953+
6954+ spl = dynop + AuDy_AOP;
6955+ head = &spl->head;
6956+ spin_lock(&spl->spin);
6957+ list_for_each_entry(key, head, dk_list)
6958+ dy_adx((void *)key, do_dx);
6959+ spin_unlock(&spl->spin);
6960+}
6961+
6962+const struct vm_operations_struct *
6963+au_dy_vmop(struct file *file, struct au_branch *br,
6964+ const struct vm_operations_struct *h_vmop)
6965+{
6966+ struct au_dyvmop *dyvmop;
6967+ struct au_dynop op;
6968+
6969+ op.dy_type = AuDy_VMOP;
6970+ op.dy_hvmop = h_vmop;
6971+ dyvmop = (void *)dy_get(&op, br);
6972+ if (IS_ERR(dyvmop))
6973+ return (void *)dyvmop;
6974+ return &dyvmop->dv_op;
6975+}
6976+
6977+/* ---------------------------------------------------------------------- */
6978+
6979+void __init au_dy_init(void)
6980+{
6981+ int i;
6982+
6983+ /* make sure that 'struct au_dykey *' can be any type */
6984+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
6985+ BUILD_BUG_ON(offsetof(struct au_dyvmop, dv_key));
6986+
6987+ for (i = 0; i < AuDyLast; i++)
6988+ au_spl_init(dynop + i);
6989+}
6990+
6991+void au_dy_fin(void)
6992+{
6993+ int i;
6994+
6995+ for (i = 0; i < AuDyLast; i++)
6996+ WARN_ON(!list_empty(&dynop[i].head));
6997+}
b752ccd1
AM
6998diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
6999--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
7000+++ linux/fs/aufs/dynop.h 2010-08-21 21:00:02.975972487 +0200
7001@@ -0,0 +1,89 @@
4a4d8108
AM
7002+/*
7003+ * Copyright (C) 2010 Junjiro R. Okajima
7004+ *
7005+ * This program, aufs is free software; you can redistribute it and/or modify
7006+ * it under the terms of the GNU General Public License as published by
7007+ * the Free Software Foundation; either version 2 of the License, or
7008+ * (at your option) any later version.
7009+ *
7010+ * This program is distributed in the hope that it will be useful,
7011+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7012+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7013+ * GNU General Public License for more details.
7014+ *
7015+ * You should have received a copy of the GNU General Public License
7016+ * along with this program; if not, write to the Free Software
7017+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7018+ */
7019+
7020+/*
7021+ * dynamically customizable operations (for regular files only)
7022+ */
7023+
7024+#ifndef __AUFS_DYNOP_H__
7025+#define __AUFS_DYNOP_H__
7026+
7027+#ifdef __KERNEL__
7028+
7029+#include <linux/fs.h>
7030+#include <linux/mm.h>
7031+#include <linux/rcupdate.h>
7032+#include <linux/aufs_type.h>
7033+#include "inode.h"
7034+
7035+enum {AuDy_AOP, AuDy_VMOP, AuDyLast};
7036+
7037+struct au_dynop {
7038+ int dy_type;
7039+ union {
7040+ const void *dy_hop;
7041+ const struct address_space_operations *dy_haop;
7042+ const struct vm_operations_struct *dy_hvmop;
7043+ };
7044+};
7045+
7046+struct au_dykey {
7047+ union {
7048+ struct list_head dk_list;
7049+ struct rcu_head dk_rcu;
7050+ };
7051+ struct au_dynop dk_op;
7052+
7053+ /*
7054+ * during I am in the branch local array, kref is gotten. when the
7055+ * branch is removed, kref is put.
7056+ */
7057+ struct kref dk_kref;
7058+};
7059+
7060+/* stop unioning since their sizes are very different from each other */
7061+struct au_dyaop {
7062+ struct au_dykey da_key;
7063+ struct address_space_operations da_op; /* not const */
7064+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
7065+ void **, unsigned long *);
7066+};
7067+
7068+struct au_dyvmop {
7069+ struct au_dykey dv_key;
7070+ struct vm_operations_struct dv_op; /* not const */
7071+};
7072+
7073+/* ---------------------------------------------------------------------- */
7074+
7075+/* dynop.c */
7076+struct au_branch;
7077+void au_dy_put(struct au_dykey *key);
7078+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
7079+ struct inode *h_inode);
b752ccd1 7080+int au_dy_irefresh(struct inode *inode);
4a4d8108
AM
7081+void au_dy_arefresh(int do_dio);
7082+const struct vm_operations_struct *
7083+au_dy_vmop(struct file *file, struct au_branch *br,
7084+ const struct vm_operations_struct *h_vmop);
7085+
7086+void __init au_dy_init(void);
7087+void au_dy_fin(void);
7088+
4a4d8108
AM
7089+#endif /* __KERNEL__ */
7090+#endif /* __AUFS_DYNOP_H__ */
b752ccd1
AM
7091diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
7092--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
7093+++ linux/fs/aufs/export.c 2010-08-21 21:00:02.975972487 +0200
7094@@ -0,0 +1,788 @@
4a4d8108
AM
7095+/*
7096+ * Copyright (C) 2005-2010 Junjiro R. Okajima
7097+ *
7098+ * This program, aufs is free software; you can redistribute it and/or modify
7099+ * it under the terms of the GNU General Public License as published by
7100+ * the Free Software Foundation; either version 2 of the License, or
7101+ * (at your option) any later version.
7102+ *
7103+ * This program is distributed in the hope that it will be useful,
7104+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7105+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7106+ * GNU General Public License for more details.
7107+ *
7108+ * You should have received a copy of the GNU General Public License
7109+ * along with this program; if not, write to the Free Software
7110+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7111+ */
7112+
7113+/*
7114+ * export via nfs
7115+ */
7116+
7117+#include <linux/exportfs.h>
7118+#include <linux/file.h>
7119+#include <linux/mnt_namespace.h>
7120+#include <linux/namei.h>
7121+#include <linux/nsproxy.h>
7122+#include <linux/random.h>
7123+#include <linux/writeback.h>
7124+#include "aufs.h"
7125+
7126+union conv {
7127+#ifdef CONFIG_AUFS_INO_T_64
7128+ __u32 a[2];
7129+#else
7130+ __u32 a[1];
7131+#endif
7132+ ino_t ino;
7133+};
7134+
7135+static ino_t decode_ino(__u32 *a)
7136+{
7137+ union conv u;
7138+
7139+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
7140+ u.a[0] = a[0];
7141+#ifdef CONFIG_AUFS_INO_T_64
7142+ u.a[1] = a[1];
7143+#endif
7144+ return u.ino;
7145+}
7146+
7147+static void encode_ino(__u32 *a, ino_t ino)
7148+{
7149+ union conv u;
7150+
7151+ u.ino = ino;
7152+ a[0] = u.a[0];
7153+#ifdef CONFIG_AUFS_INO_T_64
7154+ a[1] = u.a[1];
7155+#endif
7156+}
7157+
7158+/* NFS file handle */
7159+enum {
7160+ Fh_br_id,
7161+ Fh_sigen,
7162+#ifdef CONFIG_AUFS_INO_T_64
7163+ /* support 64bit inode number */
7164+ Fh_ino1,
7165+ Fh_ino2,
7166+ Fh_dir_ino1,
7167+ Fh_dir_ino2,
7168+#else
7169+ Fh_ino1,
7170+ Fh_dir_ino1,
7171+#endif
7172+ Fh_igen,
7173+ Fh_h_type,
7174+ Fh_tail,
7175+
7176+ Fh_ino = Fh_ino1,
7177+ Fh_dir_ino = Fh_dir_ino1
7178+};
7179+
7180+static int au_test_anon(struct dentry *dentry)
7181+{
7182+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
7183+}
7184+
7185+/* ---------------------------------------------------------------------- */
7186+/* inode generation external table */
7187+
b752ccd1 7188+void au_xigen_inc(struct inode *inode)
4a4d8108 7189+{
4a4d8108
AM
7190+ loff_t pos;
7191+ ssize_t sz;
7192+ __u32 igen;
7193+ struct super_block *sb;
7194+ struct au_sbinfo *sbinfo;
7195+
4a4d8108 7196+ sb = inode->i_sb;
b752ccd1 7197+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 7198+
b752ccd1 7199+ sbinfo = au_sbi(sb);
1facf9fc 7200+ pos = inode->i_ino;
7201+ pos *= sizeof(igen);
7202+ igen = inode->i_generation + 1;
1facf9fc 7203+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
7204+ sizeof(igen), &pos);
7205+ if (sz == sizeof(igen))
b752ccd1 7206+ return; /* success */
1facf9fc 7207+
b752ccd1 7208+ if (unlikely(sz >= 0))
1facf9fc 7209+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 7210+}
7211+
7212+int au_xigen_new(struct inode *inode)
7213+{
7214+ int err;
7215+ loff_t pos;
7216+ ssize_t sz;
7217+ struct super_block *sb;
7218+ struct au_sbinfo *sbinfo;
7219+ struct file *file;
7220+
7221+ err = 0;
7222+ /* todo: dirty, at mount time */
7223+ if (inode->i_ino == AUFS_ROOT_INO)
7224+ goto out;
7225+ sb = inode->i_sb;
dece6358 7226+ SiMustAnyLock(sb);
1facf9fc 7227+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7228+ goto out;
7229+
7230+ err = -EFBIG;
7231+ pos = inode->i_ino;
7232+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
7233+ AuIOErr1("too large i%lld\n", pos);
7234+ goto out;
7235+ }
7236+ pos *= sizeof(inode->i_generation);
7237+
7238+ err = 0;
7239+ sbinfo = au_sbi(sb);
7240+ file = sbinfo->si_xigen;
7241+ BUG_ON(!file);
7242+
7243+ if (i_size_read(file->f_dentry->d_inode)
7244+ < pos + sizeof(inode->i_generation)) {
7245+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
7246+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
7247+ sizeof(inode->i_generation), &pos);
7248+ } else
7249+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
7250+ sizeof(inode->i_generation), &pos);
7251+ if (sz == sizeof(inode->i_generation))
7252+ goto out; /* success */
7253+
7254+ err = sz;
7255+ if (unlikely(sz >= 0)) {
7256+ err = -EIO;
7257+ AuIOErr("xigen error (%zd)\n", sz);
7258+ }
7259+
7260+ out:
7261+ return err;
7262+}
7263+
7264+int au_xigen_set(struct super_block *sb, struct file *base)
7265+{
7266+ int err;
7267+ struct au_sbinfo *sbinfo;
7268+ struct file *file;
7269+
dece6358
AM
7270+ SiMustWriteLock(sb);
7271+
1facf9fc 7272+ sbinfo = au_sbi(sb);
7273+ file = au_xino_create2(base, sbinfo->si_xigen);
7274+ err = PTR_ERR(file);
7275+ if (IS_ERR(file))
7276+ goto out;
7277+ err = 0;
7278+ if (sbinfo->si_xigen)
7279+ fput(sbinfo->si_xigen);
7280+ sbinfo->si_xigen = file;
7281+
7282+ out:
7283+ return err;
7284+}
7285+
7286+void au_xigen_clr(struct super_block *sb)
7287+{
7288+ struct au_sbinfo *sbinfo;
7289+
dece6358
AM
7290+ SiMustWriteLock(sb);
7291+
1facf9fc 7292+ sbinfo = au_sbi(sb);
7293+ if (sbinfo->si_xigen) {
7294+ fput(sbinfo->si_xigen);
7295+ sbinfo->si_xigen = NULL;
7296+ }
7297+}
7298+
7299+/* ---------------------------------------------------------------------- */
7300+
7301+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
7302+ ino_t dir_ino)
7303+{
7304+ struct dentry *dentry, *d;
7305+ struct inode *inode;
7306+ unsigned int sigen;
7307+
7308+ dentry = NULL;
7309+ inode = ilookup(sb, ino);
7310+ if (!inode)
7311+ goto out;
7312+
7313+ dentry = ERR_PTR(-ESTALE);
7314+ sigen = au_sigen(sb);
7315+ if (unlikely(is_bad_inode(inode)
7316+ || IS_DEADDIR(inode)
7317+ || sigen != au_iigen(inode)))
7318+ goto out_iput;
7319+
7320+ dentry = NULL;
7321+ if (!dir_ino || S_ISDIR(inode->i_mode))
7322+ dentry = d_find_alias(inode);
7323+ else {
7324+ spin_lock(&dcache_lock);
7325+ list_for_each_entry(d, &inode->i_dentry, d_alias)
7326+ if (!au_test_anon(d)
7327+ && d->d_parent->d_inode->i_ino == dir_ino) {
7328+ dentry = dget_locked(d);
7329+ break;
7330+ }
7331+ spin_unlock(&dcache_lock);
7332+ }
7333+ if (unlikely(dentry && sigen != au_digen(dentry))) {
7334+ dput(dentry);
7335+ dentry = ERR_PTR(-ESTALE);
7336+ }
7337+
7338+ out_iput:
7339+ iput(inode);
7340+ out:
7341+ return dentry;
7342+}
7343+
7344+/* ---------------------------------------------------------------------- */
7345+
7346+/* todo: dirty? */
7347+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
7348+
7349+struct au_compare_mnt_args {
7350+ /* input */
7351+ struct super_block *sb;
7352+
7353+ /* output */
7354+ struct vfsmount *mnt;
7355+};
7356+
7357+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
7358+{
7359+ struct au_compare_mnt_args *a = arg;
7360+
7361+ if (mnt->mnt_sb != a->sb)
7362+ return 0;
7363+ a->mnt = mntget(mnt);
7364+ return 1;
7365+}
7366+
1facf9fc 7367+static struct vfsmount *au_mnt_get(struct super_block *sb)
7368+{
4a4d8108
AM
7369+ int err;
7370+ struct au_compare_mnt_args args = {
7371+ .sb = sb
7372+ };
1facf9fc 7373+ struct mnt_namespace *ns;
1facf9fc 7374+
1facf9fc 7375+ /* no get/put ?? */
7376+ AuDebugOn(!current->nsproxy);
7377+ ns = current->nsproxy->mnt_ns;
7378+ AuDebugOn(!ns);
4a4d8108
AM
7379+ err = iterate_mounts(au_compare_mnt, &args, ns->root);
7380+ AuDebugOn(!err);
7381+ AuDebugOn(!args.mnt);
7382+ return args.mnt;
1facf9fc 7383+}
7384+
7385+struct au_nfsd_si_lock {
4a4d8108
AM
7386+ unsigned int sigen;
7387+ aufs_bindex_t br_id;
1facf9fc 7388+ unsigned char force_lock;
7389+};
7390+
7391+static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
7392+ struct au_nfsd_si_lock *nsi_lock)
7393+{
7394+ aufs_bindex_t bindex;
7395+
7396+ si_read_lock(sb, AuLock_FLUSH);
7397+
7398+ /* branch id may be wrapped around */
7399+ bindex = au_br_index(sb, nsi_lock->br_id);
7400+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
7401+ goto out; /* success */
7402+
7403+ if (!nsi_lock->force_lock)
7404+ si_read_unlock(sb);
7405+ bindex = -1;
7406+
7407+ out:
7408+ return bindex;
7409+}
7410+
7411+struct find_name_by_ino {
7412+ int called, found;
7413+ ino_t ino;
7414+ char *name;
7415+ int namelen;
7416+};
7417+
7418+static int
7419+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
7420+ u64 ino, unsigned int d_type)
7421+{
7422+ struct find_name_by_ino *a = arg;
7423+
7424+ a->called++;
7425+ if (a->ino != ino)
7426+ return 0;
7427+
7428+ memcpy(a->name, name, namelen);
7429+ a->namelen = namelen;
7430+ a->found = 1;
7431+ return 1;
7432+}
7433+
7434+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
7435+ struct au_nfsd_si_lock *nsi_lock)
7436+{
7437+ struct dentry *dentry, *parent;
7438+ struct file *file;
7439+ struct inode *dir;
7440+ struct find_name_by_ino arg;
7441+ int err;
7442+
7443+ parent = path->dentry;
7444+ if (nsi_lock)
7445+ si_read_unlock(parent->d_sb);
4a4d8108 7446+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 7447+ dentry = (void *)file;
7448+ if (IS_ERR(file))
7449+ goto out;
7450+
7451+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 7452+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 7453+ if (unlikely(!arg.name))
7454+ goto out_file;
7455+ arg.ino = ino;
7456+ arg.found = 0;
7457+ do {
7458+ arg.called = 0;
7459+ /* smp_mb(); */
7460+ err = vfsub_readdir(file, find_name_by_ino, &arg);
7461+ } while (!err && !arg.found && arg.called);
7462+ dentry = ERR_PTR(err);
7463+ if (unlikely(err))
7464+ goto out_name;
7465+ dentry = ERR_PTR(-ENOENT);
7466+ if (!arg.found)
7467+ goto out_name;
7468+
7469+ /* do not call au_lkup_one() */
7470+ dir = parent->d_inode;
7471+ mutex_lock(&dir->i_mutex);
7472+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
7473+ mutex_unlock(&dir->i_mutex);
7474+ AuTraceErrPtr(dentry);
7475+ if (IS_ERR(dentry))
7476+ goto out_name;
7477+ AuDebugOn(au_test_anon(dentry));
7478+ if (unlikely(!dentry->d_inode)) {
7479+ dput(dentry);
7480+ dentry = ERR_PTR(-ENOENT);
7481+ }
7482+
7483+ out_name:
7484+ __putname(arg.name);
7485+ out_file:
7486+ fput(file);
7487+ out:
7488+ if (unlikely(nsi_lock
7489+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
7490+ if (!IS_ERR(dentry)) {
7491+ dput(dentry);
7492+ dentry = ERR_PTR(-ESTALE);
7493+ }
7494+ AuTraceErrPtr(dentry);
7495+ return dentry;
7496+}
7497+
7498+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
7499+ ino_t dir_ino,
7500+ struct au_nfsd_si_lock *nsi_lock)
7501+{
7502+ struct dentry *dentry;
7503+ struct path path;
7504+
7505+ if (dir_ino != AUFS_ROOT_INO) {
7506+ path.dentry = decode_by_ino(sb, dir_ino, 0);
7507+ dentry = path.dentry;
7508+ if (!path.dentry || IS_ERR(path.dentry))
7509+ goto out;
7510+ AuDebugOn(au_test_anon(path.dentry));
7511+ } else
7512+ path.dentry = dget(sb->s_root);
7513+
7514+ path.mnt = au_mnt_get(sb);
7515+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
7516+ path_put(&path);
7517+
7518+ out:
7519+ AuTraceErrPtr(dentry);
7520+ return dentry;
7521+}
7522+
7523+/* ---------------------------------------------------------------------- */
7524+
7525+static int h_acceptable(void *expv, struct dentry *dentry)
7526+{
7527+ return 1;
7528+}
7529+
7530+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
7531+ char *buf, int len, struct super_block *sb)
7532+{
7533+ char *p;
7534+ int n;
7535+ struct path path;
7536+
7537+ p = d_path(h_rootpath, buf, len);
7538+ if (IS_ERR(p))
7539+ goto out;
7540+ n = strlen(p);
7541+
7542+ path.mnt = h_rootpath->mnt;
7543+ path.dentry = h_parent;
7544+ p = d_path(&path, buf, len);
7545+ if (IS_ERR(p))
7546+ goto out;
7547+ if (n != 1)
7548+ p += n;
7549+
7550+ path.mnt = au_mnt_get(sb);
7551+ path.dentry = sb->s_root;
7552+ p = d_path(&path, buf, len - strlen(p));
7553+ mntput(path.mnt);
7554+ if (IS_ERR(p))
7555+ goto out;
7556+ if (n != 1)
7557+ p[strlen(p)] = '/';
7558+
7559+ out:
7560+ AuTraceErrPtr(p);
7561+ return p;
7562+}
7563+
7564+static
7565+struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
7566+ ino_t ino, __u32 *fh, int fh_len,
7567+ struct au_nfsd_si_lock *nsi_lock)
7568+{
7569+ struct dentry *dentry, *h_parent, *root;
7570+ struct super_block *h_sb;
7571+ char *pathname, *p;
7572+ struct vfsmount *h_mnt;
7573+ struct au_branch *br;
7574+ int err;
7575+ struct path path;
7576+
7577+ br = au_sbr(sb, bindex);
7578+ /* au_br_get(br); */
7579+ h_mnt = br->br_mnt;
7580+ h_sb = h_mnt->mnt_sb;
7581+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
7582+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
7583+ fh_len - Fh_tail, fh[Fh_h_type],
7584+ h_acceptable, /*context*/NULL);
7585+ dentry = h_parent;
7586+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
7587+ AuWarn1("%s decode_fh failed, %ld\n",
7588+ au_sbtype(h_sb), PTR_ERR(h_parent));
7589+ goto out;
7590+ }
7591+ dentry = NULL;
7592+ if (unlikely(au_test_anon(h_parent))) {
7593+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
7594+ au_sbtype(h_sb));
7595+ goto out_h_parent;
7596+ }
7597+
7598+ dentry = ERR_PTR(-ENOMEM);
7599+ pathname = (void *)__get_free_page(GFP_NOFS);
7600+ if (unlikely(!pathname))
7601+ goto out_h_parent;
7602+
7603+ root = sb->s_root;
7604+ path.mnt = h_mnt;
7605+ di_read_lock_parent(root, !AuLock_IR);
7606+ path.dentry = au_h_dptr(root, bindex);
7607+ di_read_unlock(root, !AuLock_IR);
7608+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
7609+ dentry = (void *)p;
7610+ if (IS_ERR(p))
7611+ goto out_pathname;
7612+
7613+ si_read_unlock(sb);
7614+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
7615+ dentry = ERR_PTR(err);
7616+ if (unlikely(err))
7617+ goto out_relock;
7618+
7619+ dentry = ERR_PTR(-ENOENT);
7620+ AuDebugOn(au_test_anon(path.dentry));
7621+ if (unlikely(!path.dentry->d_inode))
7622+ goto out_path;
7623+
7624+ if (ino != path.dentry->d_inode->i_ino)
7625+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
7626+ else
7627+ dentry = dget(path.dentry);
7628+
7629+ out_path:
7630+ path_put(&path);
7631+ out_relock:
7632+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
7633+ if (!IS_ERR(dentry)) {
7634+ dput(dentry);
7635+ dentry = ERR_PTR(-ESTALE);
7636+ }
7637+ out_pathname:
7638+ free_page((unsigned long)pathname);
7639+ out_h_parent:
7640+ dput(h_parent);
7641+ out:
7642+ /* au_br_put(br); */
7643+ AuTraceErrPtr(dentry);
7644+ return dentry;
7645+}
7646+
7647+/* ---------------------------------------------------------------------- */
7648+
7649+static struct dentry *
7650+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
7651+ int fh_type)
7652+{
7653+ struct dentry *dentry;
7654+ __u32 *fh = fid->raw;
7655+ ino_t ino, dir_ino;
7656+ aufs_bindex_t bindex;
7657+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 7658+ .force_lock = 0
7659+ };
7660+
1facf9fc 7661+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
7662+ /* it should never happen, but the file handle is unreliable */
7663+ if (unlikely(fh_len < Fh_tail))
7664+ goto out;
7665+ nsi_lock.sigen = fh[Fh_sigen];
7666+ nsi_lock.br_id = fh[Fh_br_id];
7667+
1facf9fc 7668+ /* branch id may be wrapped around */
7669+ bindex = si_nfsd_read_lock(sb, &nsi_lock);
7670+ if (unlikely(bindex < 0))
7671+ goto out;
7672+ nsi_lock.force_lock = 1;
7673+
7674+ /* is this inode still cached? */
7675+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
7676+ /* it should never happen */
7677+ if (unlikely(ino == AUFS_ROOT_INO))
7678+ goto out;
7679+
1facf9fc 7680+ dir_ino = decode_ino(fh + Fh_dir_ino);
7681+ dentry = decode_by_ino(sb, ino, dir_ino);
7682+ if (IS_ERR(dentry))
7683+ goto out_unlock;
7684+ if (dentry)
7685+ goto accept;
7686+
7687+ /* is the parent dir cached? */
7688+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
7689+ if (IS_ERR(dentry))
7690+ goto out_unlock;
7691+ if (dentry)
7692+ goto accept;
7693+
7694+ /* lookup path */
7695+ dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
7696+ if (IS_ERR(dentry))
7697+ goto out_unlock;
7698+ if (unlikely(!dentry))
7699+ /* todo?: make it ESTALE */
7700+ goto out_unlock;
7701+
7702+ accept:
7703+ if (dentry->d_inode->i_generation == fh[Fh_igen])
7704+ goto out_unlock; /* success */
7705+
7706+ dput(dentry);
7707+ dentry = ERR_PTR(-ESTALE);
7708+ out_unlock:
7709+ si_read_unlock(sb);
7710+ out:
7711+ AuTraceErrPtr(dentry);
7712+ return dentry;
7713+}
7714+
7715+#if 0 /* reserved for future use */
7716+/* support subtreecheck option */
7717+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
7718+ int fh_len, int fh_type)
7719+{
7720+ struct dentry *parent;
7721+ __u32 *fh = fid->raw;
7722+ ino_t dir_ino;
7723+
7724+ dir_ino = decode_ino(fh + Fh_dir_ino);
7725+ parent = decode_by_ino(sb, dir_ino, 0);
7726+ if (IS_ERR(parent))
7727+ goto out;
7728+ if (!parent)
7729+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
7730+ dir_ino, fh, fh_len);
7731+
7732+ out:
7733+ AuTraceErrPtr(parent);
7734+ return parent;
7735+}
7736+#endif
7737+
7738+/* ---------------------------------------------------------------------- */
7739+
7740+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
7741+ int connectable)
7742+{
7743+ int err;
7744+ aufs_bindex_t bindex, bend;
7745+ struct super_block *sb, *h_sb;
7746+ struct inode *inode;
7747+ struct dentry *parent, *h_parent;
7748+ struct au_branch *br;
7749+
7750+ AuDebugOn(au_test_anon(dentry));
7751+
7752+ parent = NULL;
7753+ err = -ENOSPC;
7754+ if (unlikely(*max_len <= Fh_tail)) {
7755+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
7756+ goto out;
7757+ }
7758+
7759+ err = FILEID_ROOT;
7760+ if (IS_ROOT(dentry)) {
7761+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
7762+ goto out;
7763+ }
7764+
7765+ err = -EIO;
7766+ h_parent = NULL;
7767+ sb = dentry->d_sb;
7768+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
7769+ parent = dget_parent(dentry);
7770+ di_read_lock_parent(parent, !AuLock_IR);
7771+ inode = dentry->d_inode;
7772+ AuDebugOn(!inode);
7773+#ifdef CONFIG_AUFS_DEBUG
7774+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7775+ AuWarn1("NFS-exporting requires xino\n");
7776+#endif
7777+
7778+ bend = au_dbtaildir(parent);
7779+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
7780+ h_parent = au_h_dptr(parent, bindex);
7781+ if (h_parent) {
7782+ dget(h_parent);
7783+ break;
7784+ }
7785+ }
7786+ if (unlikely(!h_parent))
7787+ goto out_unlock;
7788+
7789+ err = -EPERM;
7790+ br = au_sbr(sb, bindex);
7791+ h_sb = br->br_mnt->mnt_sb;
7792+ if (unlikely(!h_sb->s_export_op)) {
7793+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
7794+ goto out_dput;
7795+ }
7796+
7797+ fh[Fh_br_id] = br->br_id;
7798+ fh[Fh_sigen] = au_sigen(sb);
7799+ encode_ino(fh + Fh_ino, inode->i_ino);
7800+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
7801+ fh[Fh_igen] = inode->i_generation;
7802+
7803+ *max_len -= Fh_tail;
7804+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
7805+ max_len,
7806+ /*connectable or subtreecheck*/0);
7807+ err = fh[Fh_h_type];
7808+ *max_len += Fh_tail;
7809+ /* todo: macros? */
7810+ if (err != 255)
7811+ err = 99;
7812+ else
7813+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
7814+
7815+ out_dput:
7816+ dput(h_parent);
7817+ out_unlock:
7818+ di_read_unlock(parent, !AuLock_IR);
7819+ dput(parent);
7820+ aufs_read_unlock(dentry, AuLock_IR);
7821+ out:
7822+ if (unlikely(err < 0))
7823+ err = 255;
7824+ return err;
7825+}
7826+
7827+/* ---------------------------------------------------------------------- */
7828+
4a4d8108
AM
7829+static int aufs_commit_metadata(struct inode *inode)
7830+{
7831+ int err;
7832+ aufs_bindex_t bindex;
7833+ struct super_block *sb;
7834+ struct inode *h_inode;
7835+ int (*f)(struct inode *inode);
7836+
7837+ sb = inode->i_sb;
7838+ si_read_lock(sb, AuLock_FLUSH);
7839+ ii_write_lock_child(inode);
7840+ bindex = au_ibstart(inode);
7841+ AuDebugOn(bindex < 0);
7842+ h_inode = au_h_iptr(inode, bindex);
7843+
7844+ f = h_inode->i_sb->s_export_op->commit_metadata;
7845+ if (f)
7846+ err = f(h_inode);
7847+ else {
7848+ struct writeback_control wbc = {
7849+ .sync_mode = WB_SYNC_ALL,
7850+ .nr_to_write = 0 /* metadata only */
7851+ };
7852+
7853+ err = sync_inode(h_inode, &wbc);
7854+ }
7855+
7856+ au_cpup_attr_timesizes(inode);
7857+ ii_write_unlock(inode);
7858+ si_read_unlock(sb);
7859+ return err;
7860+}
7861+
7862+/* ---------------------------------------------------------------------- */
7863+
1facf9fc 7864+static struct export_operations aufs_export_op = {
4a4d8108 7865+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 7866+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
7867+ .encode_fh = aufs_encode_fh,
7868+ .commit_metadata = aufs_commit_metadata
1facf9fc 7869+};
7870+
7871+void au_export_init(struct super_block *sb)
7872+{
7873+ struct au_sbinfo *sbinfo;
7874+ __u32 u;
7875+
7876+ sb->s_export_op = &aufs_export_op;
7877+ sbinfo = au_sbi(sb);
7878+ sbinfo->si_xigen = NULL;
7879+ get_random_bytes(&u, sizeof(u));
7880+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
7881+ atomic_set(&sbinfo->si_xigen_next, u);
7882+}
b752ccd1
AM
7883diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
7884--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
7885+++ linux/fs/aufs/file.c 2010-08-21 21:00:02.975972487 +0200
4a4d8108 7886@@ -0,0 +1,652 @@
1facf9fc 7887+/*
4a4d8108 7888+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 7889+ *
7890+ * This program, aufs is free software; you can redistribute it and/or modify
7891+ * it under the terms of the GNU General Public License as published by
7892+ * the Free Software Foundation; either version 2 of the License, or
7893+ * (at your option) any later version.
dece6358
AM
7894+ *
7895+ * This program is distributed in the hope that it will be useful,
7896+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7897+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7898+ * GNU General Public License for more details.
7899+ *
7900+ * You should have received a copy of the GNU General Public License
7901+ * along with this program; if not, write to the Free Software
7902+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7903+ */
7904+
7905+/*
4a4d8108 7906+ * handling file/dir, and address_space operation
1facf9fc 7907+ */
7908+
dece6358 7909+#include <linux/file.h>
4a4d8108
AM
7910+#include <linux/fsnotify.h>
7911+#include <linux/namei.h>
7912+#include <linux/pagemap.h>
1facf9fc 7913+#include "aufs.h"
7914+
4a4d8108
AM
7915+/* drop flags for writing */
7916+unsigned int au_file_roflags(unsigned int flags)
7917+{
7918+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
7919+ flags |= O_RDONLY | O_NOATIME;
7920+ return flags;
7921+}
7922+
7923+/* common functions to regular file and dir */
7924+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
7925+ struct file *file)
1facf9fc 7926+{
1308ab2a 7927+ struct file *h_file;
4a4d8108
AM
7928+ struct dentry *h_dentry;
7929+ struct inode *h_inode;
7930+ struct super_block *sb;
7931+ struct au_branch *br;
7932+ struct path h_path;
7933+ int err, exec_flag;
1facf9fc 7934+
4a4d8108
AM
7935+ /* a race condition can happen between open and unlink/rmdir */
7936+ h_file = ERR_PTR(-ENOENT);
7937+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 7938+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
7939+ goto out;
7940+ h_inode = h_dentry->d_inode;
b752ccd1 7941+ if (au_test_nfsd() && !h_inode)
4a4d8108
AM
7942+ goto out;
7943+ if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
7944+ || !h_inode))
7945+ goto out;
1facf9fc 7946+
4a4d8108
AM
7947+ sb = dentry->d_sb;
7948+ br = au_sbr(sb, bindex);
7949+ h_file = ERR_PTR(-EACCES);
7950+ exec_flag = flags & vfsub_fmode_to_uint(FMODE_EXEC);
7951+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
7952+ goto out;
1facf9fc 7953+
4a4d8108
AM
7954+ /* drop flags for writing */
7955+ if (au_test_ro(sb, bindex, dentry->d_inode))
7956+ flags = au_file_roflags(flags);
7957+ flags &= ~O_CREAT;
7958+ atomic_inc(&br->br_count);
7959+ h_path.dentry = h_dentry;
7960+ h_path.mnt = br->br_mnt;
7961+ if (!au_special_file(h_inode->i_mode))
7962+ h_file = vfsub_dentry_open(&h_path, flags);
7963+ else {
7964+ /* this block depends upon the configuration */
7965+ di_read_unlock(dentry, AuLock_IR);
7966+ fi_write_unlock(file);
7967+ si_read_unlock(sb);
7968+ h_file = vfsub_dentry_open(&h_path, flags);
7969+ si_noflush_read_lock(sb);
7970+ fi_write_lock(file);
7971+ di_read_lock_child(dentry, AuLock_IR);
dece6358 7972+ }
4a4d8108
AM
7973+ if (IS_ERR(h_file))
7974+ goto out_br;
dece6358 7975+
4a4d8108
AM
7976+ if (exec_flag) {
7977+ err = deny_write_access(h_file);
7978+ if (unlikely(err)) {
7979+ fput(h_file);
7980+ h_file = ERR_PTR(err);
7981+ goto out_br;
7982+ }
7983+ }
7984+ fsnotify_open(h_dentry);
7985+ goto out; /* success */
1facf9fc 7986+
4a4d8108
AM
7987+ out_br:
7988+ atomic_dec(&br->br_count);
7989+ out:
7990+ return h_file;
7991+}
1308ab2a 7992+
4a4d8108
AM
7993+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
7994+ struct au_fidir *fidir)
1facf9fc 7995+{
dece6358 7996+ int err;
1facf9fc 7997+ struct dentry *dentry;
1308ab2a 7998+
4a4d8108
AM
7999+ err = au_finfo_init(file, fidir);
8000+ if (unlikely(err))
8001+ goto out;
1facf9fc 8002+
8003+ dentry = file->f_dentry;
4a4d8108
AM
8004+ di_read_lock_child(dentry, AuLock_IR);
8005+ err = open(file, vfsub_file_flags(file));
8006+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 8007+
4a4d8108
AM
8008+ fi_write_unlock(file);
8009+ if (unlikely(err)) {
8010+ au_fi(file)->fi_hdir = NULL;
8011+ au_finfo_fin(file);
1308ab2a 8012+ }
4a4d8108
AM
8013+
8014+ out:
1308ab2a 8015+ return err;
8016+}
dece6358 8017+
4a4d8108 8018+int au_reopen_nondir(struct file *file)
1308ab2a 8019+{
4a4d8108
AM
8020+ int err;
8021+ aufs_bindex_t bstart;
8022+ struct dentry *dentry;
8023+ struct file *h_file, *h_file_tmp;
1308ab2a 8024+
4a4d8108
AM
8025+ dentry = file->f_dentry;
8026+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
8027+ bstart = au_dbstart(dentry);
8028+ h_file_tmp = NULL;
8029+ if (au_fbstart(file) == bstart) {
8030+ h_file = au_hf_top(file);
8031+ if (file->f_mode == h_file->f_mode)
8032+ return 0; /* success */
8033+ h_file_tmp = h_file;
8034+ get_file(h_file_tmp);
8035+ au_set_h_fptr(file, bstart, NULL);
8036+ }
8037+ AuDebugOn(au_fi(file)->fi_hdir);
8038+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 8039+
4a4d8108
AM
8040+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
8041+ file);
8042+ err = PTR_ERR(h_file);
8043+ if (IS_ERR(h_file))
8044+ goto out; /* todo: close all? */
8045+
8046+ err = 0;
8047+ au_set_fbstart(file, bstart);
8048+ au_set_h_fptr(file, bstart, h_file);
8049+ au_update_figen(file);
8050+ /* todo: necessary? */
8051+ /* file->f_ra = h_file->f_ra; */
8052+
8053+ out:
8054+ if (h_file_tmp)
8055+ fput(h_file_tmp);
8056+ return err;
1facf9fc 8057+}
8058+
1308ab2a 8059+/* ---------------------------------------------------------------------- */
8060+
4a4d8108
AM
8061+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
8062+ struct dentry *hi_wh)
1facf9fc 8063+{
4a4d8108
AM
8064+ int err;
8065+ aufs_bindex_t bstart;
8066+ struct au_dinfo *dinfo;
8067+ struct dentry *h_dentry;
8068+ struct au_hdentry *hdp;
1facf9fc 8069+
4a4d8108
AM
8070+ dinfo = au_di(file->f_dentry);
8071+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 8072+
4a4d8108
AM
8073+ bstart = dinfo->di_bstart;
8074+ dinfo->di_bstart = btgt;
8075+ hdp = dinfo->di_hdentry;
8076+ h_dentry = hdp[0 + btgt].hd_dentry;
8077+ hdp[0 + btgt].hd_dentry = hi_wh;
8078+ err = au_reopen_nondir(file);
8079+ hdp[0 + btgt].hd_dentry = h_dentry;
8080+ dinfo->di_bstart = bstart;
1facf9fc 8081+
1facf9fc 8082+ return err;
8083+}
8084+
4a4d8108
AM
8085+static int au_ready_to_write_wh(struct file *file, loff_t len,
8086+ aufs_bindex_t bcpup)
1facf9fc 8087+{
4a4d8108 8088+ int err;
dece6358 8089+ struct inode *inode;
4a4d8108 8090+ struct dentry *dentry, *hi_wh;
1facf9fc 8091+
dece6358 8092+ dentry = file->f_dentry;
4a4d8108 8093+ au_update_dbstart(dentry);
dece6358 8094+ inode = dentry->d_inode;
4a4d8108
AM
8095+ hi_wh = au_hi_wh(inode, bcpup);
8096+ if (!hi_wh)
8097+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
8098+ else
8099+ /* already copied-up after unlink */
8100+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 8101+
4a4d8108
AM
8102+ if (!err
8103+ && inode->i_nlink > 1
8104+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
8105+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 8106+
dece6358 8107+ return err;
1facf9fc 8108+}
8109+
4a4d8108
AM
8110+/*
8111+ * prepare the @file for writing.
8112+ */
8113+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 8114+{
4a4d8108
AM
8115+ int err;
8116+ aufs_bindex_t bstart, bcpup;
8117+ struct dentry *dentry, *parent, *h_dentry;
8118+ struct inode *h_inode, *inode;
1facf9fc 8119+ struct super_block *sb;
4a4d8108 8120+ struct file *h_file;
1facf9fc 8121+
8122+ dentry = file->f_dentry;
1facf9fc 8123+ sb = dentry->d_sb;
4a4d8108
AM
8124+ inode = dentry->d_inode;
8125+ AuDebugOn(au_special_file(inode->i_mode));
8126+ bstart = au_fbstart(file);
8127+ err = au_test_ro(sb, bstart, inode);
8128+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
8129+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 8130+ goto out;
4a4d8108 8131+ }
1facf9fc 8132+
4a4d8108
AM
8133+ /* need to cpup */
8134+ parent = dget_parent(dentry);
8135+ di_write_lock_parent(parent);
8136+ err = AuWbrCopyup(au_sbi(sb), dentry);
8137+ bcpup = err;
8138+ if (unlikely(err < 0))
8139+ goto out_dgrade;
8140+ err = 0;
8141+
8142+ if (!au_h_dptr(parent, bcpup)) {
8143+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 8144+ if (unlikely(err))
4a4d8108
AM
8145+ goto out_dgrade;
8146+ }
8147+
8148+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
8149+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8150+ if (unlikely(err))
8151+ goto out_dgrade;
8152+
8153+ h_dentry = au_hf_top(file)->f_dentry;
8154+ h_inode = h_dentry->d_inode;
8155+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8156+ h_file = au_h_open_pre(dentry, bstart);
8157+ if (IS_ERR(h_file)) {
8158+ err = PTR_ERR(h_file);
8159+ h_file = NULL;
8160+ } else if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
8161+ /* || !h_inode->i_nlink */) {
8162+ err = au_ready_to_write_wh(file, len, bcpup);
8163+ di_downgrade_lock(parent, AuLock_IR);
8164+ } else {
8165+ di_downgrade_lock(parent, AuLock_IR);
8166+ if (!au_h_dptr(dentry, bcpup))
8167+ err = au_sio_cpup_simple(dentry, bcpup, len,
8168+ AuCpup_DTIME);
8169+ if (!err)
8170+ err = au_reopen_nondir(file);
8171+ }
8172+ mutex_unlock(&h_inode->i_mutex);
8173+ au_h_open_post(dentry, bstart, h_file);
8174+
8175+ if (!err) {
8176+ au_pin_set_parent_lflag(pin, /*lflag*/0);
8177+ goto out_dput; /* success */
8178+ }
8179+ au_unpin(pin);
8180+ goto out_unlock;
1facf9fc 8181+
4a4d8108
AM
8182+ out_dgrade:
8183+ di_downgrade_lock(parent, AuLock_IR);
1facf9fc 8184+ out_unlock:
4a4d8108
AM
8185+ di_read_unlock(parent, AuLock_IR);
8186+ out_dput:
8187+ dput(parent);
1facf9fc 8188+ out:
1facf9fc 8189+ return err;
8190+}
8191+
4a4d8108
AM
8192+/* ---------------------------------------------------------------------- */
8193+
8194+int au_do_flush(struct file *file, fl_owner_t id,
8195+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 8196+{
4a4d8108 8197+ int err;
1308ab2a 8198+ struct dentry *dentry;
1facf9fc 8199+ struct super_block *sb;
4a4d8108 8200+ struct inode *inode;
1facf9fc 8201+
1facf9fc 8202+ dentry = file->f_dentry;
8203+ sb = dentry->d_sb;
dece6358 8204+ inode = dentry->d_inode;
4a4d8108
AM
8205+ si_noflush_read_lock(sb);
8206+ fi_read_lock(file);
b752ccd1 8207+ ii_read_lock_child(inode);
1facf9fc 8208+
4a4d8108
AM
8209+ err = flush(file, id);
8210+ au_cpup_attr_timesizes(inode);
1facf9fc 8211+
b752ccd1 8212+ ii_read_unlock(inode);
4a4d8108 8213+ fi_read_unlock(file);
1308ab2a 8214+ si_read_unlock(sb);
dece6358 8215+ return err;
1facf9fc 8216+}
8217+
4a4d8108
AM
8218+/* ---------------------------------------------------------------------- */
8219+
8220+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 8221+{
4a4d8108
AM
8222+ int err;
8223+ aufs_bindex_t bstart;
8224+ struct au_pin pin;
8225+ struct au_finfo *finfo;
8226+ struct dentry *dentry, *parent, *hi_wh;
8227+ struct inode *inode;
1facf9fc 8228+ struct super_block *sb;
8229+
4a4d8108
AM
8230+ FiMustWriteLock(file);
8231+
8232+ err = 0;
8233+ finfo = au_fi(file);
1308ab2a 8234+ dentry = file->f_dentry;
8235+ sb = dentry->d_sb;
4a4d8108
AM
8236+ inode = dentry->d_inode;
8237+ bstart = au_ibstart(inode);
8238+ if (bstart == finfo->fi_btop)
1308ab2a 8239+ goto out;
dece6358 8240+
4a4d8108
AM
8241+ parent = dget_parent(dentry);
8242+ if (au_test_ro(sb, bstart, inode)) {
8243+ di_read_lock_parent(parent, !AuLock_IR);
8244+ err = AuWbrCopyup(au_sbi(sb), dentry);
8245+ bstart = err;
8246+ di_read_unlock(parent, !AuLock_IR);
8247+ if (unlikely(err < 0))
8248+ goto out_parent;
8249+ err = 0;
1facf9fc 8250+ }
1facf9fc 8251+
4a4d8108
AM
8252+ di_read_lock_parent(parent, AuLock_IR);
8253+ hi_wh = au_hi_wh(inode, bstart);
8254+ if (au_opt_test(au_mntflags(sb), PLINK)
8255+ && au_plink_test(inode)
8256+ && !d_unhashed(dentry)) {
8257+ err = au_test_and_cpup_dirs(dentry, bstart);
8258+ if (unlikely(err))
8259+ goto out_unlock;
8260+
8261+ /* always superio. */
8262+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
8263+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8264+ if (!err)
8265+ err = au_sio_cpup_simple(dentry, bstart, -1,
8266+ AuCpup_DTIME);
8267+ au_unpin(&pin);
8268+ } else if (hi_wh) {
8269+ /* already copied-up after unlink */
8270+ err = au_reopen_wh(file, bstart, hi_wh);
8271+ *need_reopen = 0;
8272+ }
1facf9fc 8273+
4a4d8108
AM
8274+ out_unlock:
8275+ di_read_unlock(parent, AuLock_IR);
8276+ out_parent:
8277+ dput(parent);
1308ab2a 8278+ out:
1308ab2a 8279+ return err;
dece6358 8280+}
1facf9fc 8281+
4a4d8108 8282+static void au_do_refresh_dir(struct file *file)
dece6358 8283+{
4a4d8108
AM
8284+ aufs_bindex_t bindex, bend, new_bindex, brid;
8285+ struct au_hfile *p, tmp, *q;
8286+ struct au_finfo *finfo;
1308ab2a 8287+ struct super_block *sb;
4a4d8108 8288+ struct au_fidir *fidir;
1facf9fc 8289+
4a4d8108 8290+ FiMustWriteLock(file);
1facf9fc 8291+
4a4d8108
AM
8292+ sb = file->f_dentry->d_sb;
8293+ finfo = au_fi(file);
8294+ fidir = finfo->fi_hdir;
8295+ AuDebugOn(!fidir);
8296+ p = fidir->fd_hfile + finfo->fi_btop;
8297+ brid = p->hf_br->br_id;
8298+ bend = fidir->fd_bbot;
8299+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
8300+ if (!p->hf_file)
8301+ continue;
1308ab2a 8302+
4a4d8108
AM
8303+ new_bindex = au_br_index(sb, p->hf_br->br_id);
8304+ if (new_bindex == bindex)
8305+ continue;
8306+ if (new_bindex < 0) {
8307+ au_set_h_fptr(file, bindex, NULL);
8308+ continue;
8309+ }
1308ab2a 8310+
4a4d8108
AM
8311+ /* swap two lower inode, and loop again */
8312+ q = fidir->fd_hfile + new_bindex;
8313+ tmp = *q;
8314+ *q = *p;
8315+ *p = tmp;
8316+ if (tmp.hf_file) {
8317+ bindex--;
8318+ p--;
8319+ }
8320+ }
1308ab2a 8321+
4a4d8108
AM
8322+ p = fidir->fd_hfile;
8323+ if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
8324+ bend = au_sbend(sb);
8325+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
8326+ finfo->fi_btop++, p++)
8327+ if (p->hf_file) {
8328+ if (p->hf_file->f_dentry
8329+ && p->hf_file->f_dentry->d_inode)
8330+ break;
8331+ else
8332+ au_hfput(p, file);
8333+ }
8334+ } else {
8335+ bend = au_br_index(sb, brid);
8336+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
8337+ finfo->fi_btop++, p++)
8338+ if (p->hf_file)
8339+ au_hfput(p, file);
8340+ bend = au_sbend(sb);
8341+ }
1308ab2a 8342+
4a4d8108
AM
8343+ p = fidir->fd_hfile + bend;
8344+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
8345+ fidir->fd_bbot--, p--)
8346+ if (p->hf_file) {
8347+ if (p->hf_file->f_dentry
8348+ && p->hf_file->f_dentry->d_inode)
8349+ break;
8350+ else
8351+ au_hfput(p, file);
8352+ }
8353+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 8354+}
8355+
4a4d8108
AM
8356+/*
8357+ * after branch manipulating, refresh the file.
8358+ */
8359+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 8360+{
4a4d8108
AM
8361+ int err, need_reopen;
8362+ aufs_bindex_t bend, bindex;
8363+ struct dentry *dentry;
1308ab2a 8364+ struct au_finfo *finfo;
4a4d8108 8365+ struct au_hfile *hfile;
1facf9fc 8366+
4a4d8108 8367+ dentry = file->f_dentry;
1308ab2a 8368+ finfo = au_fi(file);
4a4d8108
AM
8369+ if (!finfo->fi_hdir) {
8370+ hfile = &finfo->fi_htop;
8371+ AuDebugOn(!hfile->hf_file);
8372+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
8373+ AuDebugOn(bindex < 0);
8374+ if (bindex != finfo->fi_btop)
8375+ au_set_fbstart(file, bindex);
8376+ } else {
8377+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
8378+ if (unlikely(err))
8379+ goto out;
8380+ au_do_refresh_dir(file);
8381+ }
1facf9fc 8382+
4a4d8108
AM
8383+ err = 0;
8384+ need_reopen = 1;
8385+ if (!au_test_mmapped(file))
8386+ err = au_file_refresh_by_inode(file, &need_reopen);
8387+ if (!err && need_reopen && !d_unhashed(dentry))
8388+ err = reopen(file);
8389+ if (!err) {
8390+ au_update_figen(file);
8391+ goto out; /* success */
8392+ }
8393+
8394+ /* error, close all lower files */
8395+ if (finfo->fi_hdir) {
8396+ bend = au_fbend_dir(file);
8397+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
8398+ au_set_h_fptr(file, bindex, NULL);
8399+ }
1facf9fc 8400+
4a4d8108 8401+ out:
1facf9fc 8402+ return err;
8403+}
8404+
4a4d8108
AM
8405+/* common function to regular file and dir */
8406+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8407+ int wlock)
dece6358 8408+{
1308ab2a 8409+ int err;
4a4d8108
AM
8410+ unsigned int sigen, figen;
8411+ aufs_bindex_t bstart;
8412+ unsigned char pseudo_link;
8413+ struct dentry *dentry;
8414+ struct inode *inode;
1facf9fc 8415+
4a4d8108
AM
8416+ err = 0;
8417+ dentry = file->f_dentry;
8418+ inode = dentry->d_inode;
8419+ AuDebugOn(au_special_file(inode->i_mode));
8420+ sigen = au_sigen(dentry->d_sb);
8421+ fi_write_lock(file);
8422+ figen = au_figen(file);
8423+ di_write_lock_child(dentry);
8424+ bstart = au_dbstart(dentry);
8425+ pseudo_link = (bstart != au_ibstart(inode));
8426+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
8427+ if (!wlock) {
8428+ di_downgrade_lock(dentry, AuLock_IR);
8429+ fi_downgrade_lock(file);
8430+ }
8431+ goto out; /* success */
8432+ }
dece6358 8433+
4a4d8108
AM
8434+ AuDbg("sigen %d, figen %d\n", sigen, figen);
8435+ if (sigen != au_digen(dentry)
8436+ || sigen != au_iigen(inode)) {
8437+ err = au_reval_dpath(dentry, sigen);
8438+ if (unlikely(err < 0))
8439+ goto out;
8440+ AuDebugOn(au_digen(dentry) != sigen
8441+ || au_iigen(inode) != sigen);
8442+ }
dece6358 8443+
4a4d8108
AM
8444+ err = refresh_file(file, reopen);
8445+ if (!err) {
8446+ if (!wlock) {
8447+ di_downgrade_lock(dentry, AuLock_IR);
8448+ fi_downgrade_lock(file);
8449+ }
8450+ } else {
8451+ di_write_unlock(dentry);
8452+ fi_write_unlock(file);
8453+ }
1facf9fc 8454+
4a4d8108 8455+ out:
1308ab2a 8456+ return err;
8457+}
1facf9fc 8458+
4a4d8108
AM
8459+/* ---------------------------------------------------------------------- */
8460+
8461+/* cf. aufs_nopage() */
8462+/* for madvise(2) */
8463+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 8464+{
4a4d8108
AM
8465+ unlock_page(page);
8466+ return 0;
8467+}
1facf9fc 8468+
4a4d8108
AM
8469+/* it will never be called, but necessary to support O_DIRECT */
8470+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
8471+ const struct iovec *iov, loff_t offset,
8472+ unsigned long nr_segs)
8473+{ BUG(); return 0; }
1facf9fc 8474+
4a4d8108
AM
8475+/*
8476+ * it will never be called, but madvise and fadvise behaves differently
8477+ * when get_xip_mem is defined
8478+ */
8479+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
8480+ int create, void **kmem, unsigned long *pfn)
8481+{ BUG(); return 0; }
1facf9fc 8482+
4a4d8108
AM
8483+/* they will never be called. */
8484+#ifdef CONFIG_AUFS_DEBUG
8485+static int aufs_write_begin(struct file *file, struct address_space *mapping,
8486+ loff_t pos, unsigned len, unsigned flags,
8487+ struct page **pagep, void **fsdata)
8488+{ AuUnsupport(); return 0; }
8489+static int aufs_write_end(struct file *file, struct address_space *mapping,
8490+ loff_t pos, unsigned len, unsigned copied,
8491+ struct page *page, void *fsdata)
8492+{ AuUnsupport(); return 0; }
8493+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
8494+{ AuUnsupport(); return 0; }
8495+static void aufs_sync_page(struct page *page)
8496+{ AuUnsupport(); }
1308ab2a 8497+
4a4d8108
AM
8498+static int aufs_set_page_dirty(struct page *page)
8499+{ AuUnsupport(); return 0; }
8500+static void aufs_invalidatepage(struct page *page, unsigned long offset)
8501+{ AuUnsupport(); }
8502+static int aufs_releasepage(struct page *page, gfp_t gfp)
8503+{ AuUnsupport(); return 0; }
8504+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
8505+ struct page *page)
8506+{ AuUnsupport(); return 0; }
8507+static int aufs_launder_page(struct page *page)
8508+{ AuUnsupport(); return 0; }
8509+static int aufs_is_partially_uptodate(struct page *page,
8510+ read_descriptor_t *desc,
8511+ unsigned long from)
8512+{ AuUnsupport(); return 0; }
8513+static int aufs_error_remove_page(struct address_space *mapping,
8514+ struct page *page)
8515+{ AuUnsupport(); return 0; }
8516+#endif /* CONFIG_AUFS_DEBUG */
8517+
8518+const struct address_space_operations aufs_aop = {
8519+ .readpage = aufs_readpage,
8520+ .direct_IO = aufs_direct_IO,
8521+ .get_xip_mem = aufs_get_xip_mem,
8522+#ifdef CONFIG_AUFS_DEBUG
8523+ .writepage = aufs_writepage,
8524+ .sync_page = aufs_sync_page,
8525+ /* no writepages, because of writepage */
8526+ .set_page_dirty = aufs_set_page_dirty,
8527+ /* no readpages, because of readpage */
8528+ .write_begin = aufs_write_begin,
8529+ .write_end = aufs_write_end,
8530+ /* no bmap, no block device */
8531+ .invalidatepage = aufs_invalidatepage,
8532+ .releasepage = aufs_releasepage,
8533+ .migratepage = aufs_migratepage,
8534+ .launder_page = aufs_launder_page,
8535+ .is_partially_uptodate = aufs_is_partially_uptodate,
8536+ .error_remove_page = aufs_error_remove_page
8537+#endif /* CONFIG_AUFS_DEBUG */
dece6358 8538+};
b752ccd1
AM
8539diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
8540--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
8541+++ linux/fs/aufs/file.h 2010-08-21 21:00:02.975972487 +0200
8542@@ -0,0 +1,238 @@
4a4d8108
AM
8543+/*
8544+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8545+ *
8546+ * This program, aufs is free software; you can redistribute it and/or modify
8547+ * it under the terms of the GNU General Public License as published by
8548+ * the Free Software Foundation; either version 2 of the License, or
8549+ * (at your option) any later version.
8550+ *
8551+ * This program is distributed in the hope that it will be useful,
8552+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8553+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8554+ * GNU General Public License for more details.
8555+ *
8556+ * You should have received a copy of the GNU General Public License
8557+ * along with this program; if not, write to the Free Software
8558+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8559+ */
1facf9fc 8560+
4a4d8108
AM
8561+/*
8562+ * file operations
8563+ */
1facf9fc 8564+
4a4d8108
AM
8565+#ifndef __AUFS_FILE_H__
8566+#define __AUFS_FILE_H__
1facf9fc 8567+
4a4d8108 8568+#ifdef __KERNEL__
1facf9fc 8569+
4a4d8108
AM
8570+#include <linux/fs.h>
8571+#include <linux/poll.h>
8572+#include <linux/aufs_type.h>
8573+#include "rwsem.h"
1facf9fc 8574+
4a4d8108
AM
8575+struct au_branch;
8576+struct au_hfile {
8577+ struct file *hf_file;
8578+ struct au_branch *hf_br;
8579+};
1facf9fc 8580+
4a4d8108
AM
8581+struct au_vdir;
8582+struct au_fidir {
8583+ aufs_bindex_t fd_bbot;
8584+ aufs_bindex_t fd_nent;
8585+ struct au_vdir *fd_vdir_cache;
8586+ struct au_hfile fd_hfile[];
8587+};
1facf9fc 8588+
4a4d8108 8589+static inline int au_fidir_sz(int nent)
dece6358 8590+{
4a4d8108
AM
8591+ AuDebugOn(nent < 0);
8592+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
8593+}
1facf9fc 8594+
4a4d8108
AM
8595+struct au_finfo {
8596+ atomic_t fi_generation;
dece6358 8597+
4a4d8108
AM
8598+ struct au_rwsem fi_rwsem;
8599+ aufs_bindex_t fi_btop;
8600+
8601+ /* do not union them */
8602+ struct { /* for non-dir */
8603+ struct au_hfile fi_htop;
8604+ struct vm_operations_struct *fi_hvmop;
8605+ struct mutex fi_vm_mtx;
8606+ struct mutex fi_mmap;
8607+ };
8608+ struct au_fidir *fi_hdir; /* for dir only */
8609+} ____cacheline_aligned_in_smp;
1facf9fc 8610+
4a4d8108 8611+/* ---------------------------------------------------------------------- */
1facf9fc 8612+
4a4d8108
AM
8613+/* file.c */
8614+extern const struct address_space_operations aufs_aop;
8615+unsigned int au_file_roflags(unsigned int flags);
8616+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8617+ struct file *file);
8618+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8619+ struct au_fidir *fidir);
8620+int au_reopen_nondir(struct file *file);
8621+struct au_pin;
8622+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
8623+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8624+ int wlock);
8625+int au_do_flush(struct file *file, fl_owner_t id,
8626+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 8627+
4a4d8108
AM
8628+/* poll.c */
8629+#ifdef CONFIG_AUFS_POLL
8630+unsigned int aufs_poll(struct file *file, poll_table *wait);
8631+#endif
1facf9fc 8632+
4a4d8108
AM
8633+#ifdef CONFIG_AUFS_BR_HFSPLUS
8634+/* hfsplus.c */
8635+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
8636+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
8637+ struct file *h_file);
8638+#else
8639+static inline
8640+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 8641+{
4a4d8108
AM
8642+ return NULL;
8643+}
1facf9fc 8644+
4a4d8108
AM
8645+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
8646+ struct file *h_file);
8647+#endif
1facf9fc 8648+
4a4d8108
AM
8649+/* f_op.c */
8650+extern const struct file_operations aufs_file_fop;
8651+extern const struct vm_operations_struct aufs_vm_ops;
8652+int au_do_open_nondir(struct file *file, int flags);
8653+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
8654+
8655+#ifdef CONFIG_AUFS_SP_IATTR
8656+/* f_op_sp.c */
8657+int au_special_file(umode_t mode);
8658+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
8659+#else
8660+AuStubInt0(au_special_file, umode_t mode)
8661+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
8662+ dev_t rdev)
8663+{
8664+ init_special_inode(inode, mode, rdev);
8665+}
8666+#endif
1facf9fc 8667+
4a4d8108
AM
8668+/* finfo.c */
8669+void au_hfput(struct au_hfile *hf, struct file *file);
8670+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
8671+ struct file *h_file);
1facf9fc 8672+
4a4d8108
AM
8673+void au_update_figen(struct file *file);
8674+void au_fi_mmap_lock(struct file *file);
8675+void au_fi_mmap_unlock(struct file *file);
8676+struct au_fidir *au_fidir_alloc(struct super_block *sb);
8677+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 8678+
4a4d8108
AM
8679+void au_fi_init_once(void *_fi);
8680+void au_finfo_fin(struct file *file);
8681+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 8682+
4a4d8108
AM
8683+/* ioctl.c */
8684+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
8685+#ifdef CONFIG_COMPAT
8686+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
8687+ unsigned long arg);
8688+#endif
1facf9fc 8689+
4a4d8108 8690+/* ---------------------------------------------------------------------- */
1facf9fc 8691+
4a4d8108
AM
8692+static inline struct au_finfo *au_fi(struct file *file)
8693+{
8694+ return file->private_data;
8695+}
1facf9fc 8696+
4a4d8108 8697+/* ---------------------------------------------------------------------- */
1facf9fc 8698+
4a4d8108
AM
8699+/*
8700+ * fi_read_lock, fi_write_lock,
8701+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
8702+ */
8703+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 8704+
4a4d8108
AM
8705+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
8706+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
8707+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 8708+
1308ab2a 8709+/* ---------------------------------------------------------------------- */
8710+
4a4d8108
AM
8711+/* todo: hard/soft set? */
8712+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 8713+{
4a4d8108
AM
8714+ FiMustAnyLock(file);
8715+ return au_fi(file)->fi_btop;
8716+}
dece6358 8717+
4a4d8108
AM
8718+static inline aufs_bindex_t au_fbend_dir(struct file *file)
8719+{
8720+ FiMustAnyLock(file);
8721+ AuDebugOn(!au_fi(file)->fi_hdir);
8722+ return au_fi(file)->fi_hdir->fd_bbot;
8723+}
1facf9fc 8724+
4a4d8108
AM
8725+static inline struct au_vdir *au_fvdir_cache(struct file *file)
8726+{
8727+ FiMustAnyLock(file);
8728+ AuDebugOn(!au_fi(file)->fi_hdir);
8729+ return au_fi(file)->fi_hdir->fd_vdir_cache;
8730+}
1facf9fc 8731+
4a4d8108
AM
8732+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
8733+{
8734+ FiMustWriteLock(file);
8735+ au_fi(file)->fi_btop = bindex;
8736+}
1facf9fc 8737+
4a4d8108
AM
8738+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
8739+{
8740+ FiMustWriteLock(file);
8741+ AuDebugOn(!au_fi(file)->fi_hdir);
8742+ au_fi(file)->fi_hdir->fd_bbot = bindex;
8743+}
1308ab2a 8744+
4a4d8108
AM
8745+static inline void au_set_fvdir_cache(struct file *file,
8746+ struct au_vdir *vdir_cache)
8747+{
8748+ FiMustWriteLock(file);
8749+ AuDebugOn(!au_fi(file)->fi_hdir);
8750+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
8751+}
dece6358 8752+
4a4d8108
AM
8753+static inline struct file *au_hf_top(struct file *file)
8754+{
8755+ FiMustAnyLock(file);
8756+ AuDebugOn(au_fi(file)->fi_hdir);
8757+ return au_fi(file)->fi_htop.hf_file;
8758+}
1facf9fc 8759+
4a4d8108
AM
8760+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
8761+{
8762+ FiMustAnyLock(file);
8763+ AuDebugOn(!au_fi(file)->fi_hdir);
8764+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
8765+}
8766+
4a4d8108
AM
8767+/* todo: memory barrier? */
8768+static inline unsigned int au_figen(struct file *f)
dece6358 8769+{
4a4d8108
AM
8770+ return atomic_read(&au_fi(f)->fi_generation);
8771+}
dece6358 8772+
4a4d8108
AM
8773+static inline int au_test_mmapped(struct file *f)
8774+{
8775+ FiMustAnyLock(f);
8776+ return !!(au_fi(f)->fi_hvmop);
8777+}
1308ab2a 8778+
4a4d8108
AM
8779+#endif /* __KERNEL__ */
8780+#endif /* __AUFS_FILE_H__ */
b752ccd1
AM
8781diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
8782--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
8783+++ linux/fs/aufs/finfo.c 2010-08-21 21:00:02.975972487 +0200
4a4d8108
AM
8784@@ -0,0 +1,167 @@
8785+/*
8786+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8787+ *
8788+ * This program, aufs is free software; you can redistribute it and/or modify
8789+ * it under the terms of the GNU General Public License as published by
8790+ * the Free Software Foundation; either version 2 of the License, or
8791+ * (at your option) any later version.
8792+ *
8793+ * This program is distributed in the hope that it will be useful,
8794+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8795+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8796+ * GNU General Public License for more details.
8797+ *
8798+ * You should have received a copy of the GNU General Public License
8799+ * along with this program; if not, write to the Free Software
8800+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8801+ */
1308ab2a 8802+
4a4d8108
AM
8803+/*
8804+ * file private data
8805+ */
1facf9fc 8806+
4a4d8108
AM
8807+#include <linux/file.h>
8808+#include "aufs.h"
1facf9fc 8809+
4a4d8108
AM
8810+void au_hfput(struct au_hfile *hf, struct file *file)
8811+{
8812+ /* todo: direct access f_flags */
8813+ if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC))
8814+ allow_write_access(hf->hf_file);
8815+ fput(hf->hf_file);
8816+ hf->hf_file = NULL;
8817+ atomic_dec_return(&hf->hf_br->br_count);
8818+ hf->hf_br = NULL;
8819+}
1facf9fc 8820+
4a4d8108
AM
8821+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
8822+{
8823+ struct au_finfo *finfo = au_fi(file);
8824+ struct au_hfile *hf;
8825+ struct au_fidir *fidir;
8826+
8827+ fidir = finfo->fi_hdir;
8828+ if (!fidir) {
8829+ AuDebugOn(finfo->fi_btop != bindex);
8830+ hf = &finfo->fi_htop;
8831+ } else
8832+ hf = fidir->fd_hfile + bindex;
8833+
8834+ if (hf && hf->hf_file)
8835+ au_hfput(hf, file);
8836+ if (val) {
8837+ FiMustWriteLock(file);
8838+ hf->hf_file = val;
8839+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 8840+ }
4a4d8108 8841+}
1facf9fc 8842+
4a4d8108
AM
8843+void au_update_figen(struct file *file)
8844+{
8845+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
8846+ /* smp_mb(); */ /* atomic_set */
1facf9fc 8847+}
8848+
4a4d8108
AM
8849+/* ---------------------------------------------------------------------- */
8850+
8851+void au_fi_mmap_lock(struct file *file)
1facf9fc 8852+{
4a4d8108
AM
8853+ FiMustWriteLock(file);
8854+ lockdep_off();
8855+ mutex_lock(&au_fi(file)->fi_mmap);
8856+ lockdep_on();
8857+}
1facf9fc 8858+
4a4d8108
AM
8859+void au_fi_mmap_unlock(struct file *file)
8860+{
8861+ lockdep_off();
8862+ mutex_unlock(&au_fi(file)->fi_mmap);
8863+ lockdep_on();
8864+}
1308ab2a 8865+
4a4d8108 8866+/* ---------------------------------------------------------------------- */
1308ab2a 8867+
4a4d8108
AM
8868+struct au_fidir *au_fidir_alloc(struct super_block *sb)
8869+{
8870+ struct au_fidir *fidir;
8871+ int nbr;
8872+
8873+ nbr = au_sbend(sb) + 1;
8874+ if (nbr < 2)
8875+ nbr = 2; /* initial allocate for 2 branches */
8876+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
8877+ if (fidir) {
8878+ fidir->fd_bbot = -1;
8879+ fidir->fd_nent = nbr;
8880+ fidir->fd_vdir_cache = NULL;
8881+ }
8882+
8883+ return fidir;
8884+}
8885+
8886+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
8887+{
8888+ int err;
8889+ struct au_fidir *fidir, *p;
8890+
8891+ AuRwMustWriteLock(&finfo->fi_rwsem);
8892+ fidir = finfo->fi_hdir;
8893+ AuDebugOn(!fidir);
8894+
8895+ err = -ENOMEM;
8896+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
8897+ GFP_NOFS);
8898+ if (p) {
8899+ p->fd_nent = nbr;
8900+ finfo->fi_hdir = p;
8901+ err = 0;
8902+ }
1facf9fc 8903+
dece6358 8904+ return err;
1facf9fc 8905+}
1308ab2a 8906+
8907+/* ---------------------------------------------------------------------- */
8908+
4a4d8108 8909+void au_finfo_fin(struct file *file)
1308ab2a 8910+{
4a4d8108
AM
8911+ struct au_finfo *finfo;
8912+
8913+ finfo = au_fi(file);
8914+ AuDebugOn(finfo->fi_hdir);
8915+ AuRwDestroy(&finfo->fi_rwsem);
8916+ au_cache_free_finfo(finfo);
1308ab2a 8917+}
1308ab2a 8918+
4a4d8108
AM
8919+void au_fi_init_once(void *_fi)
8920+{
8921+ struct au_finfo *fi = _fi;
1308ab2a 8922+
4a4d8108
AM
8923+ au_rw_init(&fi->fi_rwsem);
8924+ mutex_init(&fi->fi_vm_mtx);
8925+ mutex_init(&fi->fi_mmap);
8926+}
1308ab2a 8927+
4a4d8108
AM
8928+int au_finfo_init(struct file *file, struct au_fidir *fidir)
8929+{
8930+ int err;
8931+ struct au_finfo *finfo;
8932+ struct dentry *dentry;
8933+
8934+ err = -ENOMEM;
8935+ dentry = file->f_dentry;
8936+ finfo = au_cache_alloc_finfo();
8937+ if (unlikely(!finfo))
8938+ goto out;
8939+
8940+ err = 0;
8941+ au_rw_write_lock(&finfo->fi_rwsem);
8942+ finfo->fi_btop = -1;
8943+ finfo->fi_hdir = fidir;
8944+ atomic_set(&finfo->fi_generation, au_digen(dentry));
8945+ /* smp_mb(); */ /* atomic_set */
8946+
8947+ file->private_data = finfo;
8948+
8949+out:
8950+ return err;
8951+}
b752ccd1
AM
8952diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
8953--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
8954+++ linux/fs/aufs/f_op.c 2010-08-21 21:00:02.975972487 +0200
8955@@ -0,0 +1,886 @@
dece6358 8956+/*
4a4d8108 8957+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
8958+ *
8959+ * This program, aufs is free software; you can redistribute it and/or modify
8960+ * it under the terms of the GNU General Public License as published by
8961+ * the Free Software Foundation; either version 2 of the License, or
8962+ * (at your option) any later version.
8963+ *
8964+ * This program is distributed in the hope that it will be useful,
8965+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8966+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8967+ * GNU General Public License for more details.
8968+ *
8969+ * You should have received a copy of the GNU General Public License
8970+ * along with this program; if not, write to the Free Software
8971+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8972+ */
1facf9fc 8973+
8974+/*
4a4d8108 8975+ * file and vm operations
1facf9fc 8976+ */
dece6358
AM
8977+
8978+#include <linux/file.h>
4a4d8108
AM
8979+#include <linux/fs_stack.h>
8980+#include <linux/mman.h>
8981+#include <linux/mm.h>
8982+#include <linux/security.h>
dece6358
AM
8983+#include "aufs.h"
8984+
4a4d8108 8985+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 8986+{
4a4d8108
AM
8987+ int err;
8988+ aufs_bindex_t bindex;
8989+ struct file *h_file;
8990+ struct dentry *dentry;
8991+ struct au_finfo *finfo;
8992+
8993+ FiMustWriteLock(file);
8994+
8995+ err = 0;
8996+ dentry = file->f_dentry;
8997+ finfo = au_fi(file);
8998+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
8999+ finfo->fi_hvmop = NULL;
9000+ bindex = au_dbstart(dentry);
9001+ h_file = au_h_open(dentry, bindex, flags, file);
9002+ if (IS_ERR(h_file))
9003+ err = PTR_ERR(h_file);
9004+ else {
9005+ au_set_fbstart(file, bindex);
9006+ au_set_h_fptr(file, bindex, h_file);
9007+ au_update_figen(file);
9008+ /* todo: necessary? */
9009+ /* file->f_ra = h_file->f_ra; */
9010+ }
9011+ return err;
1facf9fc 9012+}
9013+
4a4d8108
AM
9014+static int aufs_open_nondir(struct inode *inode __maybe_unused,
9015+ struct file *file)
1facf9fc 9016+{
4a4d8108 9017+ int err;
1308ab2a 9018+ struct super_block *sb;
1facf9fc 9019+
4a4d8108
AM
9020+ AuDbg("%.*s, f_ flags 0x%x, f_mode 0x%x\n",
9021+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
9022+ file->f_mode);
1facf9fc 9023+
4a4d8108
AM
9024+ sb = file->f_dentry->d_sb;
9025+ si_read_lock(sb, AuLock_FLUSH);
9026+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
9027+ si_read_unlock(sb);
9028+ return err;
9029+}
1facf9fc 9030+
4a4d8108
AM
9031+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
9032+{
9033+ struct au_finfo *finfo;
9034+ aufs_bindex_t bindex;
1facf9fc 9035+
4a4d8108
AM
9036+ finfo = au_fi(file);
9037+ bindex = finfo->fi_btop;
9038+ if (bindex >= 0)
9039+ au_set_h_fptr(file, bindex, NULL);
dece6358 9040+
4a4d8108
AM
9041+ au_finfo_fin(file);
9042+ return 0;
1facf9fc 9043+}
9044+
4a4d8108
AM
9045+/* ---------------------------------------------------------------------- */
9046+
9047+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 9048+{
1308ab2a 9049+ int err;
4a4d8108
AM
9050+ struct file *h_file;
9051+
9052+ err = 0;
9053+ h_file = au_hf_top(file);
9054+ if (h_file)
9055+ err = vfsub_flush(h_file, id);
9056+ return err;
9057+}
9058+
9059+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
9060+{
9061+ return au_do_flush(file, id, au_do_flush_nondir);
9062+}
9063+
9064+/* ---------------------------------------------------------------------- */
9065+
9066+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
9067+ loff_t *ppos)
9068+{
9069+ ssize_t err;
dece6358 9070+ struct dentry *dentry;
4a4d8108 9071+ struct file *h_file;
dece6358 9072+ struct super_block *sb;
1facf9fc 9073+
dece6358
AM
9074+ dentry = file->f_dentry;
9075+ sb = dentry->d_sb;
9076+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108 9077+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
9078+ if (unlikely(err))
9079+ goto out;
1facf9fc 9080+
4a4d8108
AM
9081+ h_file = au_hf_top(file);
9082+ err = vfsub_read_u(h_file, buf, count, ppos);
9083+ /* todo: necessary? */
9084+ /* file->f_ra = h_file->f_ra; */
9085+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1308ab2a 9086+
4a4d8108
AM
9087+ di_read_unlock(dentry, AuLock_IR);
9088+ fi_read_unlock(file);
dece6358
AM
9089+ out:
9090+ si_read_unlock(sb);
9091+ return err;
9092+}
1facf9fc 9093+
4a4d8108
AM
9094+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
9095+ size_t count, loff_t *ppos)
dece6358 9096+{
4a4d8108
AM
9097+ ssize_t err;
9098+ struct au_pin pin;
dece6358 9099+ struct dentry *dentry;
4a4d8108
AM
9100+ struct inode *inode;
9101+ struct super_block *sb;
9102+ struct file *h_file;
9103+ char __user *buf = (char __user *)ubuf;
1facf9fc 9104+
dece6358 9105+ dentry = file->f_dentry;
4a4d8108
AM
9106+ sb = dentry->d_sb;
9107+ inode = dentry->d_inode;
9108+ mutex_lock(&inode->i_mutex);
9109+ si_read_lock(sb, AuLock_FLUSH);
1facf9fc 9110+
4a4d8108
AM
9111+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9112+ if (unlikely(err))
9113+ goto out;
1facf9fc 9114+
4a4d8108
AM
9115+ err = au_ready_to_write(file, -1, &pin);
9116+ di_downgrade_lock(dentry, AuLock_IR);
9117+ if (unlikely(err))
9118+ goto out_unlock;
1facf9fc 9119+
4a4d8108
AM
9120+ h_file = au_hf_top(file);
9121+ au_unpin(&pin);
9122+ err = vfsub_write_u(h_file, buf, count, ppos);
9123+ au_cpup_attr_timesizes(inode);
9124+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9125+
4a4d8108
AM
9126+ out_unlock:
9127+ di_read_unlock(dentry, AuLock_IR);
9128+ fi_write_unlock(file);
dece6358 9129+ out:
4a4d8108
AM
9130+ si_read_unlock(sb);
9131+ mutex_unlock(&inode->i_mutex);
dece6358
AM
9132+ return err;
9133+}
1facf9fc 9134+
4a4d8108
AM
9135+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
9136+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 9137+{
4a4d8108
AM
9138+ ssize_t err;
9139+ struct file *file;
9140+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
9141+ loff_t);
1facf9fc 9142+
4a4d8108
AM
9143+ err = security_file_permission(h_file, rw);
9144+ if (unlikely(err))
9145+ goto out;
1facf9fc 9146+
4a4d8108
AM
9147+ err = -ENOSYS;
9148+ func = NULL;
9149+ if (rw == MAY_READ)
9150+ func = h_file->f_op->aio_read;
9151+ else if (rw == MAY_WRITE)
9152+ func = h_file->f_op->aio_write;
9153+ if (func) {
9154+ file = kio->ki_filp;
9155+ kio->ki_filp = h_file;
9156+ err = func(kio, iov, nv, pos);
9157+ kio->ki_filp = file;
9158+ } else
9159+ /* currently there is no such fs */
9160+ WARN_ON_ONCE(1);
1facf9fc 9161+
4a4d8108 9162+ out:
dece6358
AM
9163+ return err;
9164+}
1facf9fc 9165+
4a4d8108
AM
9166+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
9167+ unsigned long nv, loff_t pos)
1facf9fc 9168+{
4a4d8108
AM
9169+ ssize_t err;
9170+ struct file *file, *h_file;
9171+ struct dentry *dentry;
dece6358 9172+ struct super_block *sb;
1facf9fc 9173+
4a4d8108 9174+ file = kio->ki_filp;
dece6358 9175+ dentry = file->f_dentry;
1308ab2a 9176+ sb = dentry->d_sb;
4a4d8108
AM
9177+ si_read_lock(sb, AuLock_FLUSH);
9178+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9179+ if (unlikely(err))
9180+ goto out;
9181+
9182+ h_file = au_hf_top(file);
9183+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
9184+ /* todo: necessary? */
9185+ /* file->f_ra = h_file->f_ra; */
9186+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9187+ di_read_unlock(dentry, AuLock_IR);
9188+ fi_read_unlock(file);
1facf9fc 9189+
4a4d8108
AM
9190+ out:
9191+ si_read_unlock(sb);
1308ab2a 9192+ return err;
9193+}
1facf9fc 9194+
4a4d8108
AM
9195+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
9196+ unsigned long nv, loff_t pos)
1308ab2a 9197+{
4a4d8108
AM
9198+ ssize_t err;
9199+ struct au_pin pin;
9200+ struct dentry *dentry;
9201+ struct inode *inode;
1308ab2a 9202+ struct super_block *sb;
4a4d8108 9203+ struct file *file, *h_file;
1308ab2a 9204+
4a4d8108 9205+ file = kio->ki_filp;
1308ab2a 9206+ dentry = file->f_dentry;
9207+ sb = dentry->d_sb;
1308ab2a 9208+ inode = dentry->d_inode;
4a4d8108
AM
9209+ mutex_lock(&inode->i_mutex);
9210+ si_read_lock(sb, AuLock_FLUSH);
9211+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9212+ if (unlikely(err))
1308ab2a 9213+ goto out;
1facf9fc 9214+
4a4d8108
AM
9215+ err = au_ready_to_write(file, -1, &pin);
9216+ di_downgrade_lock(dentry, AuLock_IR);
dece6358 9217+ if (unlikely(err))
4a4d8108 9218+ goto out_unlock;
1facf9fc 9219+
4a4d8108
AM
9220+ au_unpin(&pin);
9221+ h_file = au_hf_top(file);
9222+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
9223+ au_cpup_attr_timesizes(inode);
9224+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9225+
1308ab2a 9226+ out_unlock:
4a4d8108
AM
9227+ di_read_unlock(dentry, AuLock_IR);
9228+ fi_write_unlock(file);
dece6358 9229+ out:
4a4d8108
AM
9230+ si_read_unlock(sb);
9231+ mutex_unlock(&inode->i_mutex);
dece6358 9232+ return err;
1facf9fc 9233+}
9234+
4a4d8108
AM
9235+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
9236+ struct pipe_inode_info *pipe, size_t len,
9237+ unsigned int flags)
1facf9fc 9238+{
4a4d8108
AM
9239+ ssize_t err;
9240+ struct file *h_file;
9241+ struct dentry *dentry;
dece6358 9242+ struct super_block *sb;
1facf9fc 9243+
dece6358 9244+ dentry = file->f_dentry;
dece6358 9245+ sb = dentry->d_sb;
4a4d8108
AM
9246+ si_read_lock(sb, AuLock_FLUSH);
9247+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9248+ if (unlikely(err))
dece6358 9249+ goto out;
1facf9fc 9250+
4a4d8108
AM
9251+ err = -EINVAL;
9252+ h_file = au_hf_top(file);
9253+ if (au_test_loopback_kthread()) {
9254+ file->f_mapping = h_file->f_mapping;
9255+ smp_mb(); /* unnecessary? */
1308ab2a 9256+ }
4a4d8108
AM
9257+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
9258+ /* todo: necessasry? */
9259+ /* file->f_ra = h_file->f_ra; */
9260+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 9261+
4a4d8108
AM
9262+ di_read_unlock(dentry, AuLock_IR);
9263+ fi_read_unlock(file);
1facf9fc 9264+
dece6358 9265+ out:
4a4d8108 9266+ si_read_unlock(sb);
dece6358 9267+ return err;
1facf9fc 9268+}
9269+
4a4d8108
AM
9270+static ssize_t
9271+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
9272+ size_t len, unsigned int flags)
1facf9fc 9273+{
4a4d8108
AM
9274+ ssize_t err;
9275+ struct au_pin pin;
9276+ struct dentry *dentry;
9277+ struct inode *inode;
1308ab2a 9278+ struct super_block *sb;
4a4d8108 9279+ struct file *h_file;
1facf9fc 9280+
4a4d8108
AM
9281+ dentry = file->f_dentry;
9282+ inode = dentry->d_inode;
9283+ mutex_lock(&inode->i_mutex);
9284+ sb = dentry->d_sb;
9285+ si_read_lock(sb, AuLock_FLUSH);
1facf9fc 9286+
4a4d8108
AM
9287+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9288+ if (unlikely(err))
9289+ goto out;
1facf9fc 9290+
4a4d8108
AM
9291+ err = au_ready_to_write(file, -1, &pin);
9292+ di_downgrade_lock(dentry, AuLock_IR);
9293+ if (unlikely(err))
9294+ goto out_unlock;
1facf9fc 9295+
4a4d8108
AM
9296+ h_file = au_hf_top(file);
9297+ au_unpin(&pin);
9298+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
9299+ au_cpup_attr_timesizes(inode);
9300+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9301+
4a4d8108
AM
9302+ out_unlock:
9303+ di_read_unlock(dentry, AuLock_IR);
9304+ fi_write_unlock(file);
9305+ out:
9306+ si_read_unlock(sb);
9307+ mutex_unlock(&inode->i_mutex);
9308+ return err;
9309+}
1facf9fc 9310+
4a4d8108
AM
9311+/* ---------------------------------------------------------------------- */
9312+
9313+static struct file *au_safe_file(struct vm_area_struct *vma)
9314+{
9315+ struct file *file;
9316+
9317+ file = vma->vm_file;
9318+ if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
9319+ return file;
9320+ return NULL;
1facf9fc 9321+}
9322+
4a4d8108 9323+static void au_reset_file(struct vm_area_struct *vma, struct file *file)
1facf9fc 9324+{
4a4d8108
AM
9325+ vma->vm_file = file;
9326+ /* smp_mb(); */ /* flush vm_file */
9327+}
1facf9fc 9328+
4a4d8108
AM
9329+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
9330+{
9331+ int err;
9332+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9333+ struct file *file, *h_file;
9334+ struct au_finfo *finfo;
1facf9fc 9335+
4a4d8108
AM
9336+ /* todo: non-robr mode, user vm_file as it is? */
9337+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 9338+
4a4d8108
AM
9339+ /* do not revalidate, no si lock */
9340+ finfo = au_fi(file);
9341+ AuDebugOn(finfo->fi_hdir);
9342+ h_file = finfo->fi_htop.hf_file;
9343+ AuDebugOn(!h_file || !finfo->fi_hvmop);
9344+
9345+ mutex_lock(&finfo->fi_vm_mtx);
9346+ vma->vm_file = h_file;
9347+ err = finfo->fi_hvmop->fault(vma, vmf);
9348+ /* todo: necessary? */
9349+ /* file->f_ra = h_file->f_ra; */
9350+ au_reset_file(vma, file);
9351+ mutex_unlock(&finfo->fi_vm_mtx);
9352+#if 0 /* def CONFIG_SMP */
9353+ /* wake_up_nr(&wq, online_cpu - 1); */
9354+ wake_up_all(&wq);
9355+#else
9356+ wake_up(&wq);
9357+#endif
1facf9fc 9358+
dece6358 9359+ return err;
1facf9fc 9360+}
9361+
4a4d8108 9362+static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1facf9fc 9363+{
dece6358 9364+ int err;
4a4d8108
AM
9365+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9366+ struct file *file, *h_file;
9367+ struct au_finfo *finfo;
1facf9fc 9368+
4a4d8108 9369+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 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+ err = finfo->fi_hvmop->page_mkwrite(vma, vmf);
9379+ au_reset_file(vma, file);
9380+ mutex_unlock(&finfo->fi_vm_mtx);
9381+ wake_up(&wq);
1308ab2a 9382+
dece6358 9383+ return err;
1facf9fc 9384+}
9385+
4a4d8108 9386+static void aufs_vm_close(struct vm_area_struct *vma)
1facf9fc 9387+{
4a4d8108
AM
9388+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9389+ struct file *file, *h_file;
9390+ struct au_finfo *finfo;
dece6358 9391+
4a4d8108 9392+ wait_event(wq, (file = au_safe_file(vma)));
dece6358 9393+
4a4d8108
AM
9394+ finfo = au_fi(file);
9395+ AuDebugOn(finfo->fi_hdir);
9396+ h_file = finfo->fi_htop.hf_file;
9397+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 9398+
4a4d8108
AM
9399+ mutex_lock(&finfo->fi_vm_mtx);
9400+ vma->vm_file = h_file;
9401+ finfo->fi_hvmop->close(vma);
9402+ au_reset_file(vma, file);
9403+ mutex_unlock(&finfo->fi_vm_mtx);
9404+ wake_up(&wq);
9405+}
1facf9fc 9406+
4a4d8108
AM
9407+const struct vm_operations_struct aufs_vm_ops = {
9408+ .close = aufs_vm_close,
9409+ .fault = aufs_fault,
9410+ .page_mkwrite = aufs_page_mkwrite
1308ab2a 9411+};
dece6358 9412+
1308ab2a 9413+/* ---------------------------------------------------------------------- */
1facf9fc 9414+
4a4d8108
AM
9415+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
9416+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
1308ab2a 9417+
4a4d8108 9418+static unsigned long au_arch_prot_conv(unsigned long flags)
dece6358 9419+{
4a4d8108
AM
9420+ /* currently ppc64 only */
9421+#ifdef CONFIG_PPC64
9422+ /* cf. linux/arch/powerpc/include/asm/mman.h */
9423+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
9424+ return AuConv_VM_PROT(flags, SAO);
9425+#else
9426+ AuDebugOn(arch_calc_vm_prot_bits(-1));
9427+ return 0;
9428+#endif
dece6358
AM
9429+}
9430+
4a4d8108 9431+static unsigned long au_prot_conv(unsigned long flags)
dece6358 9432+{
4a4d8108
AM
9433+ return AuConv_VM_PROT(flags, READ)
9434+ | AuConv_VM_PROT(flags, WRITE)
9435+ | AuConv_VM_PROT(flags, EXEC)
9436+ | au_arch_prot_conv(flags);
dece6358
AM
9437+}
9438+
4a4d8108
AM
9439+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
9440+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
dece6358 9441+
4a4d8108 9442+static unsigned long au_flag_conv(unsigned long flags)
dece6358 9443+{
4a4d8108
AM
9444+ return AuConv_VM_MAP(flags, GROWSDOWN)
9445+ | AuConv_VM_MAP(flags, DENYWRITE)
9446+ | AuConv_VM_MAP(flags, EXECUTABLE)
9447+ | AuConv_VM_MAP(flags, LOCKED);
dece6358
AM
9448+}
9449+
4a4d8108
AM
9450+static struct vm_operations_struct *
9451+au_hvmop(struct file *h_file, struct vm_area_struct *vma, unsigned long *flags)
dece6358 9452+{
4a4d8108
AM
9453+ struct vm_operations_struct *h_vmop;
9454+ unsigned long prot;
9455+ int err;
dece6358 9456+
4a4d8108
AM
9457+ h_vmop = ERR_PTR(-ENODEV);
9458+ if (!h_file->f_op || !h_file->f_op->mmap)
9459+ goto out;
dece6358 9460+
4a4d8108
AM
9461+ prot = au_prot_conv(vma->vm_flags);
9462+ err = security_file_mmap(h_file, /*reqprot*/prot, prot,
9463+ au_flag_conv(vma->vm_flags), vma->vm_start, 0);
9464+ h_vmop = ERR_PTR(err);
9465+ if (unlikely(err))
9466+ goto out;
dece6358 9467+
4a4d8108
AM
9468+ err = h_file->f_op->mmap(h_file, vma);
9469+ h_vmop = ERR_PTR(err);
9470+ if (unlikely(err))
9471+ goto out;
dece6358 9472+
4a4d8108
AM
9473+ /* oops, it became 'const' */
9474+ h_vmop = (struct vm_operations_struct *)vma->vm_ops;
9475+ *flags = vma->vm_flags;
9476+ err = do_munmap(current->mm, vma->vm_start,
9477+ vma->vm_end - vma->vm_start);
9478+ if (unlikely(err)) {
9479+ AuIOErr("failed internal unmapping %.*s, %d\n",
9480+ AuDLNPair(h_file->f_dentry), err);
9481+ h_vmop = ERR_PTR(-EIO);
9482+ }
dece6358 9483+
4a4d8108
AM
9484+ out:
9485+ return h_vmop;
dece6358
AM
9486+}
9487+
1308ab2a 9488+/*
4a4d8108
AM
9489+ * This is another ugly approach to keep the lock order, particularly
9490+ * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
9491+ * find it in git-log, if you want.
1308ab2a 9492+ *
4a4d8108
AM
9493+ * native readdir: i_mutex, copy_to_user, mmap_sem
9494+ * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
1308ab2a 9495+ *
4a4d8108
AM
9496+ * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
9497+ * acquire aufs rwsem. It introduces a circular locking dependency.
9498+ * To address this problem, aufs_mmap() delegates the part which requires aufs
9499+ * rwsem to its internal workqueue.
1308ab2a 9500+ */
9501+
4a4d8108
AM
9502+/* very ugly approach */
9503+#include "mtx.h"
1308ab2a 9504+
4a4d8108
AM
9505+struct au_mmap_pre_args {
9506+ /* input */
9507+ struct file *file;
9508+ struct vm_area_struct *vma;
1308ab2a 9509+
4a4d8108
AM
9510+ /* output */
9511+ int *errp;
9512+ struct file *h_file;
9513+ struct au_branch *br;
9514+ int mmapped;
9515+};
dece6358 9516+
4a4d8108
AM
9517+static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
9518+ struct file **h_file, struct au_branch **br,
9519+ int *mmapped)
dece6358 9520+{
4a4d8108
AM
9521+ int err;
9522+ aufs_bindex_t bstart;
9523+ const unsigned char wlock
9524+ = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
9525+ struct dentry *dentry;
9526+ struct super_block *sb;
1308ab2a 9527+
4a4d8108
AM
9528+ dentry = file->f_dentry;
9529+ sb = dentry->d_sb;
9530+ si_read_lock(sb, !AuLock_FLUSH);
9531+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9532+ if (unlikely(err))
9533+ goto out;
9534+
9535+ *mmapped = !!au_test_mmapped(file);
9536+ if (wlock) {
9537+ struct au_pin pin;
9538+
9539+ err = au_ready_to_write(file, -1, &pin);
9540+ di_write_unlock(dentry);
9541+ if (unlikely(err))
9542+ goto out_unlock;
9543+ au_unpin(&pin);
9544+ } else
9545+ di_write_unlock(dentry);
9546+ bstart = au_fbstart(file);
9547+ *br = au_sbr(sb, bstart);
9548+ *h_file = au_hf_top(file);
9549+ get_file(*h_file);
9550+ au_fi_mmap_lock(file);
9551+
9552+out_unlock:
9553+ fi_write_unlock(file);
9554+out:
9555+ si_read_unlock(sb);
9556+ return err;
dece6358
AM
9557+}
9558+
4a4d8108 9559+static void au_call_mmap_pre(void *args)
dece6358 9560+{
4a4d8108
AM
9561+ struct au_mmap_pre_args *a = args;
9562+ *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->br,
9563+ &a->mmapped);
dece6358
AM
9564+}
9565+
4a4d8108 9566+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 9567+{
4a4d8108
AM
9568+ int err, wkq_err;
9569+ unsigned long h_vmflags;
1308ab2a 9570+ struct au_finfo *finfo;
4a4d8108
AM
9571+ struct dentry *h_dentry;
9572+ struct vm_operations_struct *h_vmop, *vmop;
9573+ struct au_mmap_pre_args args = {
9574+ .file = file,
9575+ .vma = vma,
9576+ .errp = &err
9577+ };
9578+
b752ccd1 9579+ wkq_err = au_wkq_wait_pre(au_call_mmap_pre, &args);
4a4d8108
AM
9580+ if (unlikely(wkq_err))
9581+ err = wkq_err;
9582+ if (unlikely(err))
9583+ goto out;
9584+ finfo = au_fi(file);
9585+ mutex_set_owner(&finfo->fi_mmap);
9586+
9587+ h_dentry = args.h_file->f_dentry;
9588+ if (!args.mmapped && au_test_fs_bad_mapping(h_dentry->d_sb)) {
1308ab2a 9589+ /*
4a4d8108
AM
9590+ * by this assignment, f_mapping will differs from aufs inode
9591+ * i_mapping.
9592+ * if someone else mixes the use of f_dentry->d_inode and
9593+ * f_mapping->host, then a problem may arise.
1308ab2a 9594+ */
4a4d8108
AM
9595+ file->f_mapping = args.h_file->f_mapping;
9596+ }
1308ab2a 9597+
4a4d8108
AM
9598+ /* always try this internal mmap to get vma flags */
9599+ h_vmflags = 0; /* gcc warning */
9600+ h_vmop = au_hvmop(args.h_file, vma, &h_vmflags);
9601+ err = PTR_ERR(h_vmop);
9602+ if (IS_ERR(h_vmop))
9603+ goto out_unlock;
9604+ AuDebugOn(args.mmapped && h_vmop != finfo->fi_hvmop);
9605+
9606+ vmop = (void *)au_dy_vmop(file, args.br, h_vmop);
9607+ err = PTR_ERR(vmop);
9608+ if (IS_ERR(vmop))
9609+ goto out_unlock;
9610+
9611+ /*
9612+ * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
9613+ * currently MAP_DENYWRITE from userspace is ignored, but elf loader
9614+ * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
9615+ * both of the aufs file and the lower file is deny_write_access()-ed.
9616+ * finally I hope we can skip handlling MAP_DENYWRITE here.
9617+ */
9618+ err = generic_file_mmap(file, vma);
9619+ if (unlikely(err))
9620+ goto out_unlock;
9621+
9622+ vma->vm_ops = vmop;
9623+ vma->vm_flags = h_vmflags;
9624+ if (!args.mmapped)
9625+ finfo->fi_hvmop = h_vmop;
9626+
9627+ vfsub_file_accessed(args.h_file);
9628+ /* update without lock, I don't think it a problem */
9629+ fsstack_copy_attr_atime(file->f_dentry->d_inode, h_dentry->d_inode);
9630+
9631+ out_unlock:
9632+ au_fi_mmap_unlock(file);
9633+ fput(args.h_file);
9634+ out:
9635+ return err;
9636+}
9637+
9638+/* ---------------------------------------------------------------------- */
9639+
b752ccd1 9640+static int aufs_fsync_nondir(struct file *file, int datasync)
4a4d8108
AM
9641+{
9642+ int err;
9643+ struct au_pin pin;
b752ccd1 9644+ struct dentry *dentry;
4a4d8108
AM
9645+ struct inode *inode;
9646+ struct file *h_file;
9647+ struct super_block *sb;
9648+
b752ccd1 9649+ dentry = file->f_dentry;
4a4d8108
AM
9650+ inode = dentry->d_inode;
9651+ IMustLock(file->f_mapping->host);
9652+ if (inode != file->f_mapping->host) {
9653+ mutex_unlock(&file->f_mapping->host->i_mutex);
9654+ mutex_lock(&inode->i_mutex);
9655+ }
9656+ IMustLock(inode);
9657+
9658+ sb = dentry->d_sb;
9659+ si_read_lock(sb, AuLock_FLUSH);
9660+
9661+ err = 0; /* -EBADF; */ /* posix? */
9662+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
9663+ goto out;
9664+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9665+ if (unlikely(err))
9666+ goto out;
9667+
9668+ err = au_ready_to_write(file, -1, &pin);
9669+ di_downgrade_lock(dentry, AuLock_IR);
9670+ if (unlikely(err))
9671+ goto out_unlock;
9672+ au_unpin(&pin);
9673+
9674+ err = -EINVAL;
9675+ h_file = au_hf_top(file);
9676+ if (h_file->f_op && h_file->f_op->fsync) {
4a4d8108
AM
9677+ struct mutex *h_mtx;
9678+
9679+ /*
9680+ * no filemap_fdatawrite() since aufs file has no its own
9681+ * mapping, but dir.
9682+ */
b752ccd1 9683+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
4a4d8108 9684+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
b752ccd1 9685+ err = h_file->f_op->fsync(h_file, datasync);
4a4d8108
AM
9686+ if (!err)
9687+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9688+ /*ignore*/
9689+ au_cpup_attr_timesizes(inode);
9690+ mutex_unlock(h_mtx);
9691+ }
9692+
9693+ out_unlock:
9694+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 9695+ fi_write_unlock(file);
4a4d8108
AM
9696+ out:
9697+ si_read_unlock(sb);
9698+ if (inode != file->f_mapping->host) {
9699+ mutex_unlock(&inode->i_mutex);
9700+ mutex_lock(&file->f_mapping->host->i_mutex);
9701+ }
9702+ return err;
dece6358
AM
9703+}
9704+
4a4d8108
AM
9705+/* no one supports this operation, currently */
9706+#if 0
9707+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 9708+{
4a4d8108
AM
9709+ int err;
9710+ struct au_pin pin;
1308ab2a 9711+ struct dentry *dentry;
4a4d8108
AM
9712+ struct inode *inode;
9713+ struct file *file, *h_file;
9714+ struct super_block *sb;
1308ab2a 9715+
4a4d8108 9716+ file = kio->ki_filp;
1308ab2a 9717+ dentry = file->f_dentry;
4a4d8108
AM
9718+ inode = dentry->d_inode;
9719+ mutex_lock(&inode->i_mutex);
9720+
9721+ sb = dentry->d_sb;
9722+ si_read_lock(sb, AuLock_FLUSH);
9723+
9724+ err = 0; /* -EBADF; */ /* posix? */
9725+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
9726+ goto out;
9727+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9728+ if (unlikely(err))
1308ab2a 9729+ goto out;
9730+
4a4d8108
AM
9731+ err = au_ready_to_write(file, -1, &pin);
9732+ di_downgrade_lock(dentry, AuLock_IR);
9733+ if (unlikely(err))
9734+ goto out_unlock;
9735+ au_unpin(&pin);
1308ab2a 9736+
4a4d8108
AM
9737+ err = -ENOSYS;
9738+ h_file = au_hf_top(file);
9739+ if (h_file->f_op && h_file->f_op->aio_fsync) {
9740+ struct dentry *h_d;
9741+ struct mutex *h_mtx;
1308ab2a 9742+
4a4d8108
AM
9743+ h_d = h_file->f_dentry;
9744+ h_mtx = &h_d->d_inode->i_mutex;
9745+ if (!is_sync_kiocb(kio)) {
9746+ get_file(h_file);
9747+ fput(file);
9748+ }
9749+ kio->ki_filp = h_file;
9750+ err = h_file->f_op->aio_fsync(kio, datasync);
9751+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
9752+ if (!err)
9753+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9754+ /*ignore*/
9755+ au_cpup_attr_timesizes(inode);
9756+ mutex_unlock(h_mtx);
9757+ }
1308ab2a 9758+
4a4d8108
AM
9759+ out_unlock:
9760+ di_read_unlock(dentry, AuLock_IR);
9761+ fi_write_unlock(file);
1308ab2a 9762+ out:
4a4d8108
AM
9763+ si_read_unlock(sb);
9764+ mutex_unlock(&inode->i_mutex);
9765+ return err;
dece6358 9766+}
4a4d8108 9767+#endif
dece6358 9768+
4a4d8108 9769+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 9770+{
4a4d8108
AM
9771+ int err;
9772+ struct file *h_file;
9773+ struct dentry *dentry;
9774+ struct super_block *sb;
1308ab2a 9775+
4a4d8108
AM
9776+ dentry = file->f_dentry;
9777+ sb = dentry->d_sb;
9778+ si_read_lock(sb, AuLock_FLUSH);
9779+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9780+ if (unlikely(err))
9781+ goto out;
9782+
9783+ h_file = au_hf_top(file);
9784+ if (h_file->f_op && h_file->f_op->fasync)
9785+ err = h_file->f_op->fasync(fd, h_file, flag);
9786+
9787+ di_read_unlock(dentry, AuLock_IR);
9788+ fi_read_unlock(file);
1308ab2a 9789+
4a4d8108
AM
9790+ out:
9791+ si_read_unlock(sb);
1308ab2a 9792+ return err;
dece6358 9793+}
4a4d8108
AM
9794+
9795+/* ---------------------------------------------------------------------- */
9796+
9797+/* no one supports this operation, currently */
9798+#if 0
9799+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
9800+ size_t len, loff_t *pos , int more)
9801+{
9802+}
9803+#endif
9804+
9805+/* ---------------------------------------------------------------------- */
9806+
9807+const struct file_operations aufs_file_fop = {
9808+ .owner = THIS_MODULE,
9809+ /*
9810+ * while generic_file_llseek/_unlocked() don't use BKL,
9811+ * don't use it since it operates file->f_mapping->host.
9812+ * in aufs, it may be a real file and may confuse users by UDBA.
9813+ */
9814+ /* .llseek = generic_file_llseek, */
9815+
9816+ .read = aufs_read,
9817+ .write = aufs_write,
9818+ .aio_read = aufs_aio_read,
9819+ .aio_write = aufs_aio_write,
9820+#ifdef CONFIG_AUFS_POLL
9821+ .poll = aufs_poll,
9822+#endif
9823+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
9824+#ifdef CONFIG_COMPAT
9825+ .compat_ioctl = aufs_ioctl_nondir, /* same */
9826+#endif
4a4d8108
AM
9827+ .mmap = aufs_mmap,
9828+ .open = aufs_open_nondir,
9829+ .flush = aufs_flush_nondir,
9830+ .release = aufs_release_nondir,
9831+ .fsync = aufs_fsync_nondir,
9832+ /* .aio_fsync = aufs_aio_fsync_nondir, */
9833+ .fasync = aufs_fasync,
9834+ /* .sendpage = aufs_sendpage, */
9835+ .splice_write = aufs_splice_write,
9836+ .splice_read = aufs_splice_read,
9837+#if 0
9838+ .aio_splice_write = aufs_aio_splice_write,
9839+ .aio_splice_read = aufs_aio_splice_read
9840+#endif
9841+};
b752ccd1
AM
9842diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
9843--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
9844+++ linux/fs/aufs/f_op_sp.c 2010-08-21 21:00:02.975972487 +0200
4a4d8108 9845@@ -0,0 +1,299 @@
1308ab2a 9846+/*
4a4d8108 9847+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 9848+ *
9849+ * This program, aufs is free software; you can redistribute it and/or modify
9850+ * it under the terms of the GNU General Public License as published by
9851+ * the Free Software Foundation; either version 2 of the License, or
9852+ * (at your option) any later version.
9853+ *
9854+ * This program is distributed in the hope that it will be useful,
9855+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9856+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9857+ * GNU General Public License for more details.
9858+ *
9859+ * You should have received a copy of the GNU General Public License
9860+ * along with this program; if not, write to the Free Software
9861+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9862+ */
dece6358 9863+
1308ab2a 9864+/*
4a4d8108
AM
9865+ * file operations for special files.
9866+ * while they exist in aufs virtually,
9867+ * their file I/O is handled out of aufs.
1308ab2a 9868+ */
9869+
4a4d8108
AM
9870+#include <linux/fs_stack.h>
9871+#include "aufs.h"
1308ab2a 9872+
4a4d8108
AM
9873+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
9874+ unsigned long nv, loff_t pos)
dece6358 9875+{
4a4d8108
AM
9876+ ssize_t err;
9877+ aufs_bindex_t bstart;
9878+ unsigned char wbr;
9879+ struct file *file, *h_file;
9880+ struct super_block *sb;
1308ab2a 9881+
4a4d8108
AM
9882+ file = kio->ki_filp;
9883+ sb = file->f_dentry->d_sb;
9884+ si_read_lock(sb, AuLock_FLUSH);
9885+ fi_read_lock(file);
9886+ bstart = au_fbstart(file);
9887+ h_file = au_hf_top(file);
9888+ fi_read_unlock(file);
9889+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9890+ si_read_unlock(sb);
9891+
9892+ /* do not change the file in kio */
9893+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
9894+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
9895+ if (err > 0 && wbr)
9896+ file_accessed(h_file);
9897+
9898+ return err;
9899+}
9900+
9901+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
9902+ unsigned long nv, loff_t pos)
9903+{
9904+ ssize_t err;
9905+ aufs_bindex_t bstart;
9906+ unsigned char wbr;
9907+ struct super_block *sb;
9908+ struct file *file, *h_file;
9909+
9910+ file = kio->ki_filp;
9911+ sb = file->f_dentry->d_sb;
9912+ si_read_lock(sb, AuLock_FLUSH);
9913+ fi_read_lock(file);
9914+ bstart = au_fbstart(file);
9915+ h_file = au_hf_top(file);
9916+ fi_read_unlock(file);
9917+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9918+ si_read_unlock(sb);
9919+
9920+ /* do not change the file in kio */
9921+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
9922+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
9923+ if (err > 0 && wbr)
9924+ file_update_time(h_file);
9925+
9926+ return err;
9927+}
9928+
9929+/* ---------------------------------------------------------------------- */
9930+
9931+static int aufs_release_sp(struct inode *inode, struct file *file)
9932+{
9933+ int err;
9934+ struct file *h_file;
9935+
9936+ fi_read_lock(file);
9937+ h_file = au_hf_top(file);
9938+ fi_read_unlock(file);
9939+ /* close this fifo in aufs */
9940+ err = h_file->f_op->release(inode, file); /* ignore */
9941+ aufs_release_nondir(inode, file); /* ignore */
9942+ return err;
9943+}
9944+
9945+/* ---------------------------------------------------------------------- */
9946+
9947+/* currently, support only FIFO */
9948+enum {AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
9949+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
9950+ AuSp_Last};
9951+static int aufs_open_sp(struct inode *inode, struct file *file);
9952+static struct au_sp_fop {
9953+ int done;
9954+ struct file_operations fop; /* not 'const' */
9955+ spinlock_t spin;
9956+} au_sp_fop[AuSp_Last] = {
9957+ [AuSp_FIFO] = {
9958+ .fop = {
9959+ .owner = THIS_MODULE,
9960+ .open = aufs_open_sp
9961+ }
9962+ }
9963+};
9964+
9965+static void au_init_fop_sp(struct file *file)
9966+{
9967+ struct au_sp_fop *p;
9968+ int i;
9969+ struct file *h_file;
9970+
9971+ p = au_sp_fop;
9972+ if (unlikely(!p->done)) {
9973+ /* initialize first time only */
9974+ static DEFINE_SPINLOCK(spin);
9975+
9976+ spin_lock(&spin);
9977+ if (!p->done) {
9978+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
9979+ != AuSp_Last);
9980+ for (i = 0; i < AuSp_Last; i++)
9981+ spin_lock_init(&p[i].spin);
9982+ p->done = 1;
9983+ }
9984+ spin_unlock(&spin);
9985+ }
9986+
9987+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
9988+ case FMODE_READ:
9989+ i = AuSp_FIFO_R;
9990+ break;
9991+ case FMODE_WRITE:
9992+ i = AuSp_FIFO_W;
9993+ break;
9994+ case FMODE_READ | FMODE_WRITE:
9995+ i = AuSp_FIFO_RW;
9996+ break;
9997+ default:
9998+ BUG();
9999+ }
10000+
10001+ p += i;
10002+ if (unlikely(!p->done)) {
10003+ /* initialize first time only */
10004+ h_file = au_hf_top(file);
10005+ spin_lock(&p->spin);
10006+ if (!p->done) {
10007+ p->fop = *h_file->f_op;
10008+ p->fop.owner = THIS_MODULE;
10009+ if (p->fop.aio_read)
10010+ p->fop.aio_read = aufs_aio_read_sp;
10011+ if (p->fop.aio_write)
10012+ p->fop.aio_write = aufs_aio_write_sp;
10013+ p->fop.release = aufs_release_sp;
10014+ p->done = 1;
10015+ }
10016+ spin_unlock(&p->spin);
10017+ }
10018+ file->f_op = &p->fop;
10019+}
10020+
10021+static int au_cpup_sp(struct dentry *dentry)
10022+{
10023+ int err;
10024+ aufs_bindex_t bcpup;
10025+ struct au_pin pin;
10026+ struct au_wr_dir_args wr_dir_args = {
10027+ .force_btgt = -1,
10028+ .flags = 0
10029+ };
10030+
10031+ AuDbg("%.*s\n", AuDLNPair(dentry));
10032+
10033+ di_read_unlock(dentry, AuLock_IR);
10034+ di_write_lock_child(dentry);
10035+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
10036+ if (unlikely(err < 0))
10037+ goto out;
10038+ bcpup = err;
10039+ err = 0;
10040+ if (bcpup == au_dbstart(dentry))
10041+ goto out; /* success */
10042+
10043+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
10044+ AuPin_MNT_WRITE);
10045+ if (!err) {
10046+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
10047+ au_unpin(&pin);
10048+ }
10049+
10050+ out:
10051+ di_downgrade_lock(dentry, AuLock_IR);
10052+ return err;
10053+}
10054+
10055+static int au_do_open_sp(struct file *file, int flags)
10056+{
10057+ int err;
10058+ struct dentry *dentry;
10059+ struct super_block *sb;
10060+ struct file *h_file;
10061+ struct inode *h_inode;
10062+
10063+ dentry = file->f_dentry;
10064+ AuDbg("%.*s\n", AuDLNPair(dentry));
10065+
10066+ /*
10067+ * try copying-up.
10068+ * operate on the ro branch is not an error.
10069+ */
10070+ au_cpup_sp(dentry); /* ignore */
10071+
10072+ /* prepare h_file */
10073+ err = au_do_open_nondir(file, vfsub_file_flags(file));
10074+ if (unlikely(err))
10075+ goto out;
10076+
10077+ sb = dentry->d_sb;
10078+ h_file = au_hf_top(file);
10079+ h_inode = h_file->f_dentry->d_inode;
10080+ di_read_unlock(dentry, AuLock_IR);
10081+ fi_write_unlock(file);
10082+ si_read_unlock(sb);
10083+ /* open this fifo in aufs */
10084+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
10085+ si_noflush_read_lock(sb);
10086+ fi_write_lock(file);
10087+ di_read_lock_child(dentry, AuLock_IR);
10088+ if (!err)
10089+ au_init_fop_sp(file);
10090+ else
10091+ au_finfo_fin(file);
10092+
10093+ out:
10094+ return err;
10095+}
10096+
10097+static int aufs_open_sp(struct inode *inode, struct file *file)
10098+{
10099+ int err;
10100+ struct super_block *sb;
10101+
10102+ sb = file->f_dentry->d_sb;
10103+ si_read_lock(sb, AuLock_FLUSH);
10104+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
10105+ si_read_unlock(sb);
10106+ return err;
10107+}
10108+
10109+/* ---------------------------------------------------------------------- */
10110+
10111+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
10112+{
10113+ init_special_inode(inode, mode, rdev);
10114+
10115+ switch (mode & S_IFMT) {
10116+ case S_IFIFO:
10117+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
10118+ /*FALLTHROUGH*/
10119+ case S_IFCHR:
10120+ case S_IFBLK:
10121+ case S_IFSOCK:
10122+ break;
10123+ default:
10124+ AuDebugOn(1);
10125+ }
10126+}
10127+
10128+int au_special_file(umode_t mode)
10129+{
10130+ int ret;
10131+
10132+ ret = 0;
10133+ switch (mode & S_IFMT) {
10134+ case S_IFIFO:
10135+#if 0
10136+ case S_IFCHR:
10137+ case S_IFBLK:
10138+ case S_IFSOCK:
10139+#endif
10140+ ret = 1;
10141+ }
10142+
10143+ return ret;
10144+}
b752ccd1
AM
10145diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
10146--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
10147+++ linux/fs/aufs/fstype.h 2010-08-21 21:00:02.975972487 +0200
4a4d8108
AM
10148@@ -0,0 +1,497 @@
10149+/*
10150+ * Copyright (C) 2005-2010 Junjiro R. Okajima
10151+ *
10152+ * This program, aufs is free software; you can redistribute it and/or modify
10153+ * it under the terms of the GNU General Public License as published by
10154+ * the Free Software Foundation; either version 2 of the License, or
10155+ * (at your option) any later version.
10156+ *
10157+ * This program is distributed in the hope that it will be useful,
10158+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10159+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10160+ * GNU General Public License for more details.
10161+ *
10162+ * You should have received a copy of the GNU General Public License
10163+ * along with this program; if not, write to the Free Software
10164+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10165+ */
10166+
10167+/*
10168+ * judging filesystem type
10169+ */
10170+
10171+#ifndef __AUFS_FSTYPE_H__
10172+#define __AUFS_FSTYPE_H__
10173+
10174+#ifdef __KERNEL__
10175+
10176+#include <linux/fs.h>
10177+#include <linux/magic.h>
10178+#include <linux/romfs_fs.h>
10179+#include <linux/aufs_type.h>
10180+
10181+static inline int au_test_aufs(struct super_block *sb)
10182+{
10183+ return sb->s_magic == AUFS_SUPER_MAGIC;
10184+}
10185+
10186+static inline const char *au_sbtype(struct super_block *sb)
10187+{
10188+ return sb->s_type->name;
10189+}
1308ab2a 10190+
10191+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
10192+{
10193+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
10194+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
10195+#else
10196+ return 0;
10197+#endif
10198+}
10199+
1308ab2a 10200+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 10201+{
1308ab2a 10202+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
10203+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
10204+#else
10205+ return 0;
10206+#endif
10207+}
10208+
1308ab2a 10209+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 10210+{
1308ab2a 10211+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
10212+ return sb->s_magic == CRAMFS_MAGIC;
10213+#endif
10214+ return 0;
10215+}
10216+
10217+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
10218+{
10219+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
10220+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
10221+#else
10222+ return 0;
10223+#endif
10224+}
10225+
1308ab2a 10226+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 10227+{
1308ab2a 10228+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
10229+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
10230+#else
10231+ return 0;
10232+#endif
10233+}
10234+
1308ab2a 10235+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 10236+{
1308ab2a 10237+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
10238+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
10239+#else
10240+ return 0;
10241+#endif
10242+}
10243+
1308ab2a 10244+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 10245+{
1308ab2a 10246+#ifdef CONFIG_TMPFS
10247+ return sb->s_magic == TMPFS_MAGIC;
10248+#else
10249+ return 0;
dece6358 10250+#endif
dece6358
AM
10251+}
10252+
1308ab2a 10253+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 10254+{
1308ab2a 10255+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
10256+ return !strcmp(au_sbtype(sb), "ecryptfs");
10257+#else
10258+ return 0;
10259+#endif
1facf9fc 10260+}
10261+
1308ab2a 10262+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 10263+{
1308ab2a 10264+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
10265+ return sb->s_magic == SMB_SUPER_MAGIC;
10266+#else
10267+ return 0;
1facf9fc 10268+#endif
1facf9fc 10269+}
10270+
1308ab2a 10271+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 10272+{
1308ab2a 10273+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
10274+ return sb->s_magic == OCFS2_SUPER_MAGIC;
10275+#else
10276+ return 0;
10277+#endif
1facf9fc 10278+}
10279+
1308ab2a 10280+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 10281+{
1308ab2a 10282+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
10283+ return sb->s_magic == DLMFS_MAGIC;
10284+#else
10285+ return 0;
10286+#endif
1facf9fc 10287+}
10288+
1308ab2a 10289+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 10290+{
1308ab2a 10291+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
10292+ return sb->s_magic == CODA_SUPER_MAGIC;
10293+#else
10294+ return 0;
10295+#endif
10296+}
10297+
10298+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
10299+{
10300+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
10301+ return sb->s_magic == V9FS_MAGIC;
10302+#else
10303+ return 0;
10304+#endif
10305+}
10306+
10307+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
10308+{
10309+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
10310+ return sb->s_magic == EXT4_SUPER_MAGIC;
10311+#else
10312+ return 0;
10313+#endif
10314+}
10315+
10316+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
10317+{
10318+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
10319+ return !strcmp(au_sbtype(sb), "sysv");
10320+#else
10321+ return 0;
10322+#endif
10323+}
10324+
10325+static inline int au_test_ramfs(struct super_block *sb)
10326+{
10327+ return sb->s_magic == RAMFS_MAGIC;
10328+}
10329+
10330+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
10331+{
10332+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
10333+ return sb->s_magic == UBIFS_SUPER_MAGIC;
10334+#else
10335+ return 0;
10336+#endif
10337+}
10338+
10339+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
10340+{
10341+#ifdef CONFIG_PROC_FS
10342+ return sb->s_magic == PROC_SUPER_MAGIC;
10343+#else
10344+ return 0;
10345+#endif
10346+}
10347+
10348+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
10349+{
10350+#ifdef CONFIG_SYSFS
10351+ return sb->s_magic == SYSFS_MAGIC;
10352+#else
10353+ return 0;
10354+#endif
10355+}
10356+
10357+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
10358+{
10359+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
10360+ return sb->s_magic == CONFIGFS_MAGIC;
10361+#else
10362+ return 0;
10363+#endif
10364+}
10365+
10366+static inline int au_test_minix(struct super_block *sb __maybe_unused)
10367+{
10368+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
10369+ return sb->s_magic == MINIX3_SUPER_MAGIC
10370+ || sb->s_magic == MINIX2_SUPER_MAGIC
10371+ || sb->s_magic == MINIX2_SUPER_MAGIC2
10372+ || sb->s_magic == MINIX_SUPER_MAGIC
10373+ || sb->s_magic == MINIX_SUPER_MAGIC2;
10374+#else
10375+ return 0;
10376+#endif
10377+}
10378+
10379+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
10380+{
10381+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
10382+ return sb->s_magic == CIFS_MAGIC_NUMBER;
10383+#else
10384+ return 0;
10385+#endif
10386+}
10387+
10388+static inline int au_test_fat(struct super_block *sb __maybe_unused)
10389+{
10390+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
10391+ return sb->s_magic == MSDOS_SUPER_MAGIC;
10392+#else
10393+ return 0;
10394+#endif
10395+}
10396+
10397+static inline int au_test_msdos(struct super_block *sb)
10398+{
10399+ return au_test_fat(sb);
10400+}
10401+
10402+static inline int au_test_vfat(struct super_block *sb)
10403+{
10404+ return au_test_fat(sb);
10405+}
10406+
10407+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
10408+{
10409+#ifdef CONFIG_SECURITYFS
10410+ return sb->s_magic == SECURITYFS_MAGIC;
10411+#else
10412+ return 0;
10413+#endif
10414+}
10415+
10416+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
10417+{
10418+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
10419+ return sb->s_magic == SQUASHFS_MAGIC;
10420+#else
10421+ return 0;
10422+#endif
10423+}
10424+
10425+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
10426+{
10427+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
10428+ return sb->s_magic == BTRFS_SUPER_MAGIC;
10429+#else
10430+ return 0;
10431+#endif
10432+}
10433+
10434+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
10435+{
10436+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
10437+ return sb->s_magic == XENFS_SUPER_MAGIC;
10438+#else
10439+ return 0;
10440+#endif
10441+}
10442+
10443+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
10444+{
10445+#ifdef CONFIG_DEBUG_FS
10446+ return sb->s_magic == DEBUGFS_MAGIC;
10447+#else
10448+ return 0;
10449+#endif
10450+}
10451+
10452+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
10453+{
10454+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
10455+ return sb->s_magic == NILFS_SUPER_MAGIC;
10456+#else
10457+ return 0;
10458+#endif
10459+}
10460+
4a4d8108
AM
10461+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
10462+{
10463+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
10464+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
10465+#else
10466+ return 0;
10467+#endif
10468+}
10469+
1308ab2a 10470+/* ---------------------------------------------------------------------- */
10471+/*
10472+ * they can't be an aufs branch.
10473+ */
10474+static inline int au_test_fs_unsuppoted(struct super_block *sb)
10475+{
10476+ return
10477+#ifndef CONFIG_AUFS_BR_RAMFS
10478+ au_test_ramfs(sb) ||
10479+#endif
10480+ au_test_procfs(sb)
10481+ || au_test_sysfs(sb)
10482+ || au_test_configfs(sb)
10483+ || au_test_debugfs(sb)
10484+ || au_test_securityfs(sb)
10485+ || au_test_xenfs(sb)
10486+ || au_test_ecryptfs(sb)
10487+ /* || !strcmp(au_sbtype(sb), "unionfs") */
10488+ || au_test_aufs(sb); /* will be supported in next version */
10489+}
10490+
10491+/*
10492+ * If the filesystem supports NFS-export, then it has to support NULL as
10493+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
10494+ * We can apply this principle when we handle a lower filesystem.
10495+ */
10496+static inline int au_test_fs_null_nd(struct super_block *sb)
10497+{
10498+ return !!sb->s_export_op;
10499+}
10500+
10501+static inline int au_test_fs_remote(struct super_block *sb)
10502+{
10503+ return !au_test_tmpfs(sb)
10504+#ifdef CONFIG_AUFS_BR_RAMFS
10505+ && !au_test_ramfs(sb)
10506+#endif
10507+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
10508+}
10509+
10510+/* ---------------------------------------------------------------------- */
10511+
10512+/*
10513+ * Note: these functions (below) are created after reading ->getattr() in all
10514+ * filesystems under linux/fs. it means we have to do so in every update...
10515+ */
10516+
10517+/*
10518+ * some filesystems require getattr to refresh the inode attributes before
10519+ * referencing.
10520+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
10521+ * and leave the work for d_revalidate()
10522+ */
10523+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
10524+{
10525+ return au_test_nfs(sb)
10526+ || au_test_fuse(sb)
10527+ /* || au_test_smbfs(sb) */ /* untested */
10528+ /* || au_test_ocfs2(sb) */ /* untested */
10529+ /* || au_test_btrfs(sb) */ /* untested */
10530+ /* || au_test_coda(sb) */ /* untested */
10531+ /* || au_test_v9fs(sb) */ /* untested */
10532+ ;
10533+}
10534+
10535+/*
10536+ * filesystems which don't maintain i_size or i_blocks.
10537+ */
10538+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
10539+{
10540+ return au_test_xfs(sb)
4a4d8108
AM
10541+ || au_test_btrfs(sb)
10542+ || au_test_ubifs(sb)
10543+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 10544+ /* || au_test_ext4(sb) */ /* untested */
10545+ /* || au_test_ocfs2(sb) */ /* untested */
10546+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
10547+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 10548+ /* || au_test_minix(sb) */ /* untested */
10549+ ;
10550+}
10551+
10552+/*
10553+ * filesystems which don't store the correct value in some of their inode
10554+ * attributes.
10555+ */
10556+static inline int au_test_fs_bad_iattr(struct super_block *sb)
10557+{
10558+ return au_test_fs_bad_iattr_size(sb)
10559+ /* || au_test_cifs(sb) */ /* untested */
10560+ || au_test_fat(sb)
10561+ || au_test_msdos(sb)
10562+ || au_test_vfat(sb);
1facf9fc 10563+}
10564+
10565+/* they don't check i_nlink in link(2) */
10566+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
10567+{
10568+ return au_test_tmpfs(sb)
10569+#ifdef CONFIG_AUFS_BR_RAMFS
10570+ || au_test_ramfs(sb)
10571+#endif
4a4d8108
AM
10572+ || au_test_ubifs(sb)
10573+ || au_test_btrfs(sb)
10574+ || au_test_hfsplus(sb);
1facf9fc 10575+}
10576+
10577+/*
10578+ * filesystems which sets S_NOATIME and S_NOCMTIME.
10579+ */
10580+static inline int au_test_fs_notime(struct super_block *sb)
10581+{
10582+ return au_test_nfs(sb)
10583+ || au_test_fuse(sb)
dece6358 10584+ || au_test_ubifs(sb)
1facf9fc 10585+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 10586+ ;
10587+}
10588+
10589+/*
10590+ * filesystems which requires replacing i_mapping.
10591+ */
10592+static inline int au_test_fs_bad_mapping(struct super_block *sb)
10593+{
dece6358
AM
10594+ return au_test_fuse(sb)
10595+ || au_test_ubifs(sb);
1facf9fc 10596+}
10597+
10598+/* temporary support for i#1 in cramfs */
10599+static inline int au_test_fs_unique_ino(struct inode *inode)
10600+{
10601+ if (au_test_cramfs(inode->i_sb))
10602+ return inode->i_ino != 1;
10603+ return 1;
10604+}
10605+
10606+/* ---------------------------------------------------------------------- */
10607+
10608+/*
10609+ * the filesystem where the xino files placed must support i/o after unlink and
10610+ * maintain i_size and i_blocks.
10611+ */
10612+static inline int au_test_fs_bad_xino(struct super_block *sb)
10613+{
10614+ return au_test_fs_remote(sb)
10615+ || au_test_fs_bad_iattr_size(sb)
10616+#ifdef CONFIG_AUFS_BR_RAMFS
10617+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
10618+#else
10619+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
10620+#endif
10621+ /* don't want unnecessary work for xino */
10622+ || au_test_aufs(sb)
1308ab2a 10623+ || au_test_ecryptfs(sb)
10624+ || au_test_nilfs(sb);
1facf9fc 10625+}
10626+
10627+static inline int au_test_fs_trunc_xino(struct super_block *sb)
10628+{
10629+ return au_test_tmpfs(sb)
10630+ || au_test_ramfs(sb);
10631+}
10632+
10633+/*
10634+ * test if the @sb is real-readonly.
10635+ */
10636+static inline int au_test_fs_rr(struct super_block *sb)
10637+{
10638+ return au_test_squashfs(sb)
10639+ || au_test_iso9660(sb)
10640+ || au_test_cramfs(sb)
10641+ || au_test_romfs(sb);
10642+}
10643+
10644+#endif /* __KERNEL__ */
10645+#endif /* __AUFS_FSTYPE_H__ */
b752ccd1
AM
10646diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
10647--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
10648+++ linux/fs/aufs/hfsnotify.c 2010-08-21 21:00:02.975972487 +0200
4a4d8108 10649@@ -0,0 +1,230 @@
1facf9fc 10650+/*
4a4d8108 10651+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 10652+ *
10653+ * This program, aufs is free software; you can redistribute it and/or modify
10654+ * it under the terms of the GNU General Public License as published by
10655+ * the Free Software Foundation; either version 2 of the License, or
10656+ * (at your option) any later version.
dece6358
AM
10657+ *
10658+ * This program is distributed in the hope that it will be useful,
10659+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10660+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10661+ * GNU General Public License for more details.
10662+ *
10663+ * You should have received a copy of the GNU General Public License
10664+ * along with this program; if not, write to the Free Software
10665+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 10666+ */
10667+
10668+/*
4a4d8108 10669+ * fsnotify for the lower directories
1facf9fc 10670+ */
10671+
10672+#include "aufs.h"
10673+
4a4d8108
AM
10674+/* FS_IN_IGNORED is unnecessary */
10675+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
10676+ | FS_CREATE | FS_EVENT_ON_CHILD);
10677+static struct fsnotify_group *au_hfsn_group;
1facf9fc 10678+
4a4d8108 10679+static void au_hfsn_free_mark(struct fsnotify_mark_entry *entry)
1facf9fc 10680+{
4a4d8108
AM
10681+#if 0
10682+ struct au_hnotify *hn = container_of(entry, struct au_hnotify,
10683+ hn_entry);
10684+ au_cache_free_hnotify(hn);
10685+#endif
10686+ AuDbg("here\n");
10687+}
1facf9fc 10688+
4a4d8108
AM
10689+static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode)
10690+{
10691+ struct fsnotify_mark_entry *entry;
1facf9fc 10692+
4a4d8108
AM
10693+ entry = &hn->hn_entry;
10694+ fsnotify_init_mark(entry, au_hfsn_free_mark);
10695+ entry->mask = AuHfsnMask;
10696+ return fsnotify_add_mark(entry, au_hfsn_group, h_inode);
1facf9fc 10697+}
10698+
4a4d8108 10699+static void au_hfsn_free(struct au_hnotify *hn)
1facf9fc 10700+{
4a4d8108 10701+ struct fsnotify_mark_entry *entry;
1facf9fc 10702+
4a4d8108
AM
10703+ entry = &hn->hn_entry;
10704+ fsnotify_destroy_mark_by_entry(entry);
10705+ fsnotify_put_mark(entry);
1facf9fc 10706+}
10707+
10708+/* ---------------------------------------------------------------------- */
10709+
4a4d8108 10710+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 10711+{
4a4d8108 10712+ struct fsnotify_mark_entry *entry;
1facf9fc 10713+
4a4d8108
AM
10714+ entry = &hinode->hi_notify->hn_entry;
10715+ spin_lock(&entry->lock);
1facf9fc 10716+ if (do_set) {
4a4d8108
AM
10717+ AuDebugOn(entry->mask & AuHfsnMask);
10718+ entry->mask |= AuHfsnMask;
1facf9fc 10719+ } else {
4a4d8108
AM
10720+ AuDebugOn(!(entry->mask & AuHfsnMask));
10721+ entry->mask &= ~AuHfsnMask;
1facf9fc 10722+ }
4a4d8108
AM
10723+ spin_unlock(&entry->lock);
10724+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 10725+}
10726+
4a4d8108 10727+/* ---------------------------------------------------------------------- */
1facf9fc 10728+
4a4d8108
AM
10729+/* #define AuDbgHnotify */
10730+#ifdef AuDbgHnotify
10731+static char *au_hfsn_name(u32 mask)
10732+{
10733+#ifdef CONFIG_AUFS_DEBUG
10734+#define test_ret(flag) if (mask & flag) \
10735+ return #flag;
10736+ test_ret(FS_ACCESS);
10737+ test_ret(FS_MODIFY);
10738+ test_ret(FS_ATTRIB);
10739+ test_ret(FS_CLOSE_WRITE);
10740+ test_ret(FS_CLOSE_NOWRITE);
10741+ test_ret(FS_OPEN);
10742+ test_ret(FS_MOVED_FROM);
10743+ test_ret(FS_MOVED_TO);
10744+ test_ret(FS_CREATE);
10745+ test_ret(FS_DELETE);
10746+ test_ret(FS_DELETE_SELF);
10747+ test_ret(FS_MOVE_SELF);
10748+ test_ret(FS_UNMOUNT);
10749+ test_ret(FS_Q_OVERFLOW);
10750+ test_ret(FS_IN_IGNORED);
10751+ test_ret(FS_IN_ISDIR);
10752+ test_ret(FS_IN_ONESHOT);
10753+ test_ret(FS_EVENT_ON_CHILD);
10754+ return "";
10755+#undef test_ret
10756+#else
10757+ return "??";
10758+#endif
1facf9fc 10759+}
4a4d8108 10760+#endif
1facf9fc 10761+
10762+/* ---------------------------------------------------------------------- */
10763+
4a4d8108
AM
10764+static int au_hfsn_handle_event(struct fsnotify_group *group,
10765+ struct fsnotify_event *event)
1facf9fc 10766+{
10767+ int err;
4a4d8108
AM
10768+ struct au_hnotify *hnotify;
10769+ struct inode *h_dir, *h_inode;
10770+ __u32 mask;
10771+ struct fsnotify_mark_entry *entry;
10772+ struct qstr h_child_qstr = {
10773+ .name = event->file_name,
10774+ .len = event->name_len
10775+ };
10776+
10777+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 10778+
10779+ err = 0;
4a4d8108
AM
10780+ /* if IN_UNMOUNT happens, there must be another bug */
10781+ mask = event->mask;
10782+ AuDebugOn(mask & FS_UNMOUNT);
10783+ if (mask & (IN_IGNORED | IN_UNMOUNT))
1facf9fc 10784+ goto out;
1facf9fc 10785+
4a4d8108
AM
10786+ h_dir = event->to_tell;
10787+ h_inode = event->inode;
10788+#ifdef AuDbgHnotify
10789+ au_debug(1);
10790+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
10791+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
10792+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
10793+ h_dir->i_ino, mask, au_hfsn_name(mask),
10794+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
10795+ /* WARN_ON(1); */
1facf9fc 10796+ }
4a4d8108 10797+ au_debug(0);
1facf9fc 10798+#endif
4a4d8108
AM
10799+
10800+ spin_lock(&h_dir->i_lock);
10801+ entry = fsnotify_find_mark_entry(group, h_dir);
10802+ spin_unlock(&h_dir->i_lock);
10803+ if (entry) {
10804+ hnotify = container_of(entry, struct au_hnotify, hn_entry);
10805+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
10806+ fsnotify_put_mark(entry);
1facf9fc 10807+ }
1facf9fc 10808+
4a4d8108
AM
10809+out:
10810+ return err;
10811+}
1facf9fc 10812+
4a4d8108
AM
10813+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
10814+/* it should be exported to modules */
10815+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
10816+ struct inode *h_inode, __u32 mask)
10817+{
10818+ struct fsnotify_mark_entry *entry;
10819+ bool send;
10820+
10821+ spin_lock(&h_inode->i_lock);
10822+ entry = fsnotify_find_mark_entry(group, h_inode);
10823+ spin_unlock(&h_inode->i_lock);
10824+ if (!entry)
10825+ return false;
10826+
10827+ mask = (mask & ~FS_EVENT_ON_CHILD);
10828+ send = (entry->mask & mask);
10829+
10830+ /* find took a reference */
10831+ fsnotify_put_mark(entry);
10832+
10833+ return send;
10834+}
10835+
10836+static struct fsnotify_ops au_hfsn_ops = {
10837+ .should_send_event = au_hfsn_should_send_event,
10838+ .handle_event = au_hfsn_handle_event
10839+};
10840+
10841+/* ---------------------------------------------------------------------- */
10842+
10843+static int __init au_hfsn_init(void)
10844+{
10845+ int err;
10846+ unsigned int gn;
10847+ const unsigned int gn_max = 10;
10848+
10849+ gn = 0;
10850+ for (gn = 0; gn < gn_max; gn++) {
10851+ au_hfsn_group = fsnotify_obtain_group(gn, AuHfsnMask,
10852+ &au_hfsn_ops);
10853+ if (au_hfsn_group != ERR_PTR(-EEXIST))
10854+ break;
1facf9fc 10855+ }
10856+
4a4d8108
AM
10857+ err = 0;
10858+ if (IS_ERR(au_hfsn_group)) {
10859+ pr_err("fsnotify_obtain_group() failed %u times\n", gn_max);
10860+ err = PTR_ERR(au_hfsn_group);
10861+ }
1facf9fc 10862+
1facf9fc 10863+ AuTraceErr(err);
10864+ return err;
10865+}
10866+
4a4d8108 10867+static void au_hfsn_fin(void)
1facf9fc 10868+{
4a4d8108
AM
10869+ fsnotify_put_group(au_hfsn_group);
10870+}
1facf9fc 10871+
4a4d8108
AM
10872+const struct au_hnotify_op au_hnotify_op = {
10873+ .ctl = au_hfsn_ctl,
10874+ .alloc = au_hfsn_alloc,
10875+ .free = au_hfsn_free,
1facf9fc 10876+
4a4d8108
AM
10877+ .fin = au_hfsn_fin,
10878+ .init = au_hfsn_init
10879+};
b752ccd1
AM
10880diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
10881--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
10882+++ linux/fs/aufs/hfsplus.c 2010-08-21 21:00:02.975972487 +0200
4a4d8108
AM
10883@@ -0,0 +1,58 @@
10884+/*
10885+ * Copyright (C) 2010 Junjiro R. Okajima
10886+ *
10887+ * This program, aufs is free software; you can redistribute it and/or modify
10888+ * it under the terms of the GNU General Public License as published by
10889+ * the Free Software Foundation; either version 2 of the License, or
10890+ * (at your option) any later version.
10891+ *
10892+ * This program is distributed in the hope that it will be useful,
10893+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10894+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10895+ * GNU General Public License for more details.
10896+ *
10897+ * You should have received a copy of the GNU General Public License
10898+ * along with this program; if not, write to the Free Software
10899+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10900+ */
1facf9fc 10901+
4a4d8108
AM
10902+/*
10903+ * special support for filesystems which aqucires an inode mutex
10904+ * at final closing a file, eg, hfsplus.
10905+ *
10906+ * This trick is very simple and stupid, just to open the file before really
10907+ * neceeary open to tell hfsplus that this is not the final closing.
10908+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
10909+ * and au_h_open_post() after releasing it.
10910+ */
1facf9fc 10911+
4a4d8108
AM
10912+#include <linux/file.h>
10913+#include "aufs.h"
1facf9fc 10914+
4a4d8108
AM
10915+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
10916+{
10917+ struct file *h_file;
10918+ struct dentry *h_dentry;
1facf9fc 10919+
4a4d8108
AM
10920+ h_dentry = au_h_dptr(dentry, bindex);
10921+ AuDebugOn(!h_dentry);
10922+ AuDebugOn(!h_dentry->d_inode);
10923+ IMustLock(h_dentry->d_inode);
10924+
10925+ h_file = NULL;
10926+ if (au_test_hfsplus(h_dentry->d_sb)
10927+ && S_ISREG(h_dentry->d_inode->i_mode))
10928+ h_file = au_h_open(dentry, bindex,
10929+ O_RDONLY | O_NOATIME | O_LARGEFILE,
10930+ /*file*/NULL);
10931+ return h_file;
1facf9fc 10932+}
10933+
4a4d8108
AM
10934+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
10935+ struct file *h_file)
10936+{
10937+ if (h_file) {
10938+ fput(h_file);
10939+ au_sbr_put(dentry->d_sb, bindex);
10940+ }
10941+}
b752ccd1
AM
10942diff -urN /usr/share/empty/fs/aufs/hinotify.c linux/fs/aufs/hinotify.c
10943--- /usr/share/empty/fs/aufs/hinotify.c 1970-01-01 01:00:00.000000000 +0100
10944+++ linux/fs/aufs/hinotify.c 2010-08-21 21:00:02.975972487 +0200
4a4d8108 10945@@ -0,0 +1,227 @@
1facf9fc 10946+/*
4a4d8108
AM
10947+ * Copyright (C) 2005-2010 Junjiro R. Okajima
10948+ *
10949+ * This program, aufs is free software; you can redistribute it and/or modify
10950+ * it under the terms of the GNU General Public License as published by
10951+ * the Free Software Foundation; either version 2 of the License, or
10952+ * (at your option) any later version.
10953+ *
10954+ * This program is distributed in the hope that it will be useful,
10955+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10956+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10957+ * GNU General Public License for more details.
10958+ *
10959+ * You should have received a copy of the GNU General Public License
10960+ * along with this program; if not, write to the Free Software
10961+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10962+ */
10963+
10964+/*
10965+ * inotify for the lower directories (deprecated)
1facf9fc 10966+ */
4a4d8108
AM
10967+
10968+#include "aufs.h"
10969+
10970+static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
10971+static struct inotify_handle *au_hin_handle;
10972+
10973+/* ---------------------------------------------------------------------- */
10974+
10975+static int au_hin_alloc(struct au_hnotify *hn, struct inode *h_inode)
1facf9fc 10976+{
10977+ int err;
4a4d8108
AM
10978+ s32 wd;
10979+ struct inotify_watch *watch;
1facf9fc 10980+
4a4d8108
AM
10981+ err = -EEXIST;
10982+ wd = inotify_find_watch(au_hin_handle, h_inode, &watch);
10983+ if (wd >= 0) {
10984+ put_inotify_watch(watch);
1facf9fc 10985+ goto out;
10986+ }
10987+
4a4d8108
AM
10988+ err = 0;
10989+ inotify_init_watch(&hn->hn_watch);
10990+ wd = inotify_add_watch(au_hin_handle, &hn->hn_watch, h_inode,
10991+ AuHinMask);
10992+ if (unlikely(wd < 0)) {
10993+ err = wd;
10994+ put_inotify_watch(&hn->hn_watch);
1facf9fc 10995+ }
10996+
4a4d8108 10997+out:
1facf9fc 10998+ return err;
10999+}
11000+
4a4d8108 11001+static void au_hin_free(struct au_hnotify *hn)
1facf9fc 11002+{
11003+ int err;
1facf9fc 11004+
11005+ err = 0;
4a4d8108
AM
11006+ if (atomic_read(&hn->hn_watch.count))
11007+ err = inotify_rm_watch(au_hin_handle, &hn->hn_watch);
11008+ if (unlikely(err))
11009+ /* it means the watch is already removed */
11010+ pr_warning("failed inotify_rm_watch() %d\n", err);
1facf9fc 11011+}
11012+
11013+/* ---------------------------------------------------------------------- */
11014+
4a4d8108 11015+static void au_hin_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 11016+{
4a4d8108
AM
11017+ struct inode *h_inode;
11018+ struct inotify_watch *watch;
1facf9fc 11019+
4a4d8108
AM
11020+ h_inode = hinode->hi_inode;
11021+ IMustLock(h_inode);
1facf9fc 11022+
4a4d8108
AM
11023+ /* todo: try inotify_find_update_watch()? */
11024+ watch = &hinode->hi_notify->hn_watch;
11025+ mutex_lock(&h_inode->inotify_mutex);
11026+ /* mutex_lock(&watch->ih->mutex); */
11027+ if (do_set) {
11028+ AuDebugOn(watch->mask & AuHinMask);
11029+ watch->mask |= AuHinMask;
11030+ } else {
11031+ AuDebugOn(!(watch->mask & AuHinMask));
11032+ watch->mask &= ~AuHinMask;
1facf9fc 11033+ }
4a4d8108
AM
11034+ /* mutex_unlock(&watch->ih->mutex); */
11035+ mutex_unlock(&h_inode->inotify_mutex);
1facf9fc 11036+}
11037+
11038+/* ---------------------------------------------------------------------- */
11039+
4a4d8108 11040+#ifdef AuDbgHnotify
1facf9fc 11041+static char *in_name(u32 mask)
11042+{
11043+#ifdef CONFIG_AUFS_DEBUG
11044+#define test_ret(flag) if (mask & flag) \
11045+ return #flag;
11046+ test_ret(IN_ACCESS);
11047+ test_ret(IN_MODIFY);
11048+ test_ret(IN_ATTRIB);
11049+ test_ret(IN_CLOSE_WRITE);
11050+ test_ret(IN_CLOSE_NOWRITE);
11051+ test_ret(IN_OPEN);
11052+ test_ret(IN_MOVED_FROM);
11053+ test_ret(IN_MOVED_TO);
11054+ test_ret(IN_CREATE);
11055+ test_ret(IN_DELETE);
11056+ test_ret(IN_DELETE_SELF);
11057+ test_ret(IN_MOVE_SELF);
11058+ test_ret(IN_UNMOUNT);
11059+ test_ret(IN_Q_OVERFLOW);
11060+ test_ret(IN_IGNORED);
11061+ return "";
11062+#undef test_ret
11063+#else
11064+ return "??";
11065+#endif
11066+}
4a4d8108 11067+#endif
1facf9fc 11068+
4a4d8108
AM
11069+static u32 au_hin_conv_mask(u32 mask)
11070+{
11071+ u32 conv;
11072+
11073+ conv = 0;
11074+#define do_conv(flag) conv |= (mask & IN_ ## flag) ? FS_ ## flag : 0
11075+ do_conv(ACCESS);
11076+ do_conv(MODIFY);
11077+ do_conv(ATTRIB);
11078+ do_conv(CLOSE_WRITE);
11079+ do_conv(CLOSE_NOWRITE);
11080+ do_conv(OPEN);
11081+ do_conv(MOVED_FROM);
11082+ do_conv(MOVED_TO);
11083+ do_conv(CREATE);
11084+ do_conv(DELETE);
11085+ do_conv(DELETE_SELF);
11086+ do_conv(MOVE_SELF);
11087+ do_conv(UNMOUNT);
11088+ do_conv(Q_OVERFLOW);
11089+#undef do_conv
11090+#define do_conv(flag) conv |= (mask & IN_ ## flag) ? FS_IN_ ## flag : 0
11091+ do_conv(IGNORED);
11092+ /* do_conv(ISDIR); */
11093+ /* do_conv(ONESHOT); */
11094+#undef do_conv
11095+
11096+ return conv;
1facf9fc 11097+}
11098+
1facf9fc 11099+static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
11100+ u32 mask, u32 cookie __maybe_unused,
11101+ const char *h_child_name, struct inode *h_child_inode)
11102+{
4a4d8108
AM
11103+ struct au_hnotify *hnotify;
11104+ struct qstr h_child_qstr = {
11105+ .name = h_child_name
11106+ };
1facf9fc 11107+
11108+ /* if IN_UNMOUNT happens, there must be another bug */
11109+ AuDebugOn(mask & IN_UNMOUNT);
11110+ if (mask & (IN_IGNORED | IN_UNMOUNT)) {
11111+ put_inotify_watch(watch);
11112+ return;
11113+ }
4a4d8108
AM
11114+
11115+#ifdef AuDbgHnotify
1facf9fc 11116+ au_debug(1);
11117+ if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
11118+ AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
11119+ " hi%lu\n",
11120+ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
11121+ h_child_name ? h_child_name : "",
11122+ h_child_inode ? h_child_inode->i_ino : 0);
11123+ WARN_ON(1);
11124+ }
11125+ au_debug(0);
11126+#endif
11127+
4a4d8108
AM
11128+ if (h_child_name)
11129+ h_child_qstr.len = strlen(h_child_name);
11130+ hnotify = container_of(watch, struct au_hnotify, hn_watch);
11131+ mask = au_hin_conv_mask(mask);
11132+ au_hnotify(watch->inode, hnotify, mask, &h_child_qstr, h_child_inode);
11133+}
1facf9fc 11134+
4a4d8108
AM
11135+static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
11136+{
11137+ return;
11138+}
1facf9fc 11139+
4a4d8108
AM
11140+static struct inotify_operations aufs_inotify_ops = {
11141+ .handle_event = aufs_inotify,
11142+ .destroy_watch = aufs_inotify_destroy
11143+};
1facf9fc 11144+
4a4d8108 11145+/* ---------------------------------------------------------------------- */
1facf9fc 11146+
4a4d8108
AM
11147+static int __init au_hin_init(void)
11148+{
11149+ int err;
1facf9fc 11150+
4a4d8108
AM
11151+ err = 0;
11152+ au_hin_handle = inotify_init(&aufs_inotify_ops);
11153+ if (IS_ERR(au_hin_handle))
11154+ err = PTR_ERR(au_hin_handle);
1facf9fc 11155+
4a4d8108
AM
11156+ AuTraceErr(err);
11157+ return err;
11158+}
1facf9fc 11159+
4a4d8108 11160+static void au_hin_fin(void)
1facf9fc 11161+{
4a4d8108 11162+ inotify_destroy(au_hin_handle);
1facf9fc 11163+}
11164+
4a4d8108
AM
11165+const struct au_hnotify_op au_hnotify_op = {
11166+ .ctl = au_hin_ctl,
11167+ .alloc = au_hin_alloc,
11168+ .free = au_hin_free,
1facf9fc 11169+
4a4d8108
AM
11170+ .fin = au_hin_fin,
11171+ .init = au_hin_init
11172+};
b752ccd1
AM
11173diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
11174--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
11175+++ linux/fs/aufs/hnotify.c 2010-08-21 21:00:02.975972487 +0200
11176@@ -0,0 +1,663 @@
1facf9fc 11177+/*
4a4d8108 11178+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 11179+ *
11180+ * This program, aufs is free software; you can redistribute it and/or modify
11181+ * it under the terms of the GNU General Public License as published by
11182+ * the Free Software Foundation; either version 2 of the License, or
11183+ * (at your option) any later version.
dece6358
AM
11184+ *
11185+ * This program is distributed in the hope that it will be useful,
11186+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11187+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11188+ * GNU General Public License for more details.
11189+ *
11190+ * You should have received a copy of the GNU General Public License
11191+ * along with this program; if not, write to the Free Software
11192+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 11193+ */
11194+
11195+/*
4a4d8108 11196+ * abstraction to notify the direct changes on lower directories
1facf9fc 11197+ */
11198+
1308ab2a 11199+#include "aufs.h"
1facf9fc 11200+
4a4d8108
AM
11201+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
11202+ struct inode *h_inode)
dece6358 11203+{
1308ab2a 11204+ int err;
4a4d8108 11205+ struct au_hnotify *hn;
1facf9fc 11206+
4a4d8108
AM
11207+ err = -ENOMEM;
11208+ hn = au_cache_alloc_hnotify();
11209+ if (hn) {
11210+ hn->hn_aufs_inode = inode;
11211+ err = au_hnotify_op.alloc(hn, h_inode);
11212+ if (!err)
11213+ hinode->hi_notify = hn;
11214+ else {
11215+ au_cache_free_hnotify(hn);
11216+ /*
11217+ * The upper dir was removed by udba, but the same named
11218+ * dir left. In this case, aufs assignes a new inode
11219+ * number and set the monitor again.
11220+ * For the lower dir, the old monitnor is still left.
11221+ */
11222+ if (err == -EEXIST)
11223+ err = 0;
11224+ }
1308ab2a 11225+ }
1308ab2a 11226+
1308ab2a 11227+ return err;
dece6358 11228+}
1facf9fc 11229+
4a4d8108 11230+void au_hn_free(struct au_hinode *hinode)
dece6358 11231+{
4a4d8108 11232+ struct au_hnotify *hn;
1facf9fc 11233+
4a4d8108
AM
11234+ hn = hinode->hi_notify;
11235+ if (hn) {
11236+ au_hnotify_op.free(hn);
11237+ au_cache_free_hnotify(hn);
11238+ hinode->hi_notify = NULL;
11239+ }
11240+}
dece6358 11241+
4a4d8108 11242+/* ---------------------------------------------------------------------- */
dece6358 11243+
4a4d8108
AM
11244+void au_hn_ctl(struct au_hinode *hinode, int do_set)
11245+{
11246+ if (hinode->hi_notify)
11247+ au_hnotify_op.ctl(hinode, do_set);
11248+}
11249+
11250+void au_hn_reset(struct inode *inode, unsigned int flags)
11251+{
11252+ aufs_bindex_t bindex, bend;
11253+ struct inode *hi;
11254+ struct dentry *iwhdentry;
1facf9fc 11255+
1308ab2a 11256+ bend = au_ibend(inode);
4a4d8108
AM
11257+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
11258+ hi = au_h_iptr(inode, bindex);
11259+ if (!hi)
11260+ continue;
1308ab2a 11261+
4a4d8108
AM
11262+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
11263+ iwhdentry = au_hi_wh(inode, bindex);
11264+ if (iwhdentry)
11265+ dget(iwhdentry);
11266+ au_igrab(hi);
11267+ au_set_h_iptr(inode, bindex, NULL, 0);
11268+ au_set_h_iptr(inode, bindex, au_igrab(hi),
11269+ flags & ~AuHi_XINO);
11270+ iput(hi);
11271+ dput(iwhdentry);
11272+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 11273+ }
1facf9fc 11274+}
11275+
1308ab2a 11276+/* ---------------------------------------------------------------------- */
1facf9fc 11277+
4a4d8108 11278+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 11279+{
4a4d8108
AM
11280+ int err;
11281+ aufs_bindex_t bindex, bend, bfound, bstart;
11282+ struct inode *h_i;
1facf9fc 11283+
4a4d8108
AM
11284+ err = 0;
11285+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11286+ pr_warning("branch root dir was changed\n");
11287+ goto out;
11288+ }
1facf9fc 11289+
4a4d8108
AM
11290+ bfound = -1;
11291+ bend = au_ibend(inode);
11292+ bstart = au_ibstart(inode);
11293+#if 0 /* reserved for future use */
11294+ if (bindex == bend) {
11295+ /* keep this ino in rename case */
11296+ goto out;
11297+ }
11298+#endif
11299+ for (bindex = bstart; bindex <= bend; bindex++)
11300+ if (au_h_iptr(inode, bindex) == h_inode) {
11301+ bfound = bindex;
11302+ break;
11303+ }
11304+ if (bfound < 0)
1308ab2a 11305+ goto out;
1facf9fc 11306+
4a4d8108
AM
11307+ for (bindex = bstart; bindex <= bend; bindex++) {
11308+ h_i = au_h_iptr(inode, bindex);
11309+ if (!h_i)
11310+ continue;
1facf9fc 11311+
4a4d8108
AM
11312+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
11313+ /* ignore this error */
11314+ /* bad action? */
1facf9fc 11315+ }
1facf9fc 11316+
4a4d8108 11317+ /* children inode number will be broken */
1facf9fc 11318+
1308ab2a 11319+ out:
4a4d8108
AM
11320+ AuTraceErr(err);
11321+ return err;
1facf9fc 11322+}
11323+
4a4d8108 11324+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 11325+{
4a4d8108
AM
11326+ int err, i, j, ndentry;
11327+ struct au_dcsub_pages dpages;
11328+ struct au_dpage *dpage;
11329+ struct dentry **dentries;
1facf9fc 11330+
4a4d8108
AM
11331+ err = au_dpages_init(&dpages, GFP_NOFS);
11332+ if (unlikely(err))
11333+ goto out;
11334+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
11335+ if (unlikely(err))
11336+ goto out_dpages;
1facf9fc 11337+
4a4d8108
AM
11338+ for (i = 0; i < dpages.ndpage; i++) {
11339+ dpage = dpages.dpages + i;
11340+ dentries = dpage->dentries;
11341+ ndentry = dpage->ndentry;
11342+ for (j = 0; j < ndentry; j++) {
11343+ struct dentry *d;
11344+
11345+ d = dentries[j];
11346+ if (IS_ROOT(d))
11347+ continue;
11348+
11349+ d_drop(d);
11350+ au_digen_dec(d);
11351+ if (d->d_inode)
11352+ /* todo: reset children xino?
11353+ cached children only? */
11354+ au_iigen_dec(d->d_inode);
1308ab2a 11355+ }
dece6358 11356+ }
1facf9fc 11357+
4a4d8108
AM
11358+ out_dpages:
11359+ au_dpages_free(&dpages);
dece6358 11360+
4a4d8108
AM
11361+ /* discard children */
11362+ dentry_unhash(dentry);
11363+ dput(dentry);
11364+ out:
dece6358
AM
11365+ return err;
11366+}
11367+
1308ab2a 11368+/*
4a4d8108 11369+ * return 0 if processed.
1308ab2a 11370+ */
4a4d8108
AM
11371+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
11372+ const unsigned int isdir)
dece6358 11373+{
1308ab2a 11374+ int err;
4a4d8108
AM
11375+ struct dentry *d;
11376+ struct qstr *dname;
1facf9fc 11377+
4a4d8108
AM
11378+ err = 1;
11379+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11380+ pr_warning("branch root dir was changed\n");
11381+ err = 0;
11382+ goto out;
11383+ }
dece6358 11384+
4a4d8108
AM
11385+ if (!isdir) {
11386+ AuDebugOn(!name);
11387+ au_iigen_dec(inode);
11388+ spin_lock(&dcache_lock);
11389+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
11390+ dname = &d->d_name;
11391+ if (dname->len != nlen
11392+ && memcmp(dname->name, name, nlen))
11393+ continue;
11394+ err = 0;
11395+ spin_lock(&d->d_lock);
11396+ __d_drop(d);
11397+ au_digen_dec(d);
11398+ spin_unlock(&d->d_lock);
11399+ break;
1facf9fc 11400+ }
4a4d8108 11401+ spin_unlock(&dcache_lock);
1308ab2a 11402+ } else {
4a4d8108
AM
11403+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
11404+ d = d_find_alias(inode);
11405+ if (!d) {
11406+ au_iigen_dec(inode);
11407+ goto out;
11408+ }
1facf9fc 11409+
4a4d8108
AM
11410+ dname = &d->d_name;
11411+ if (dname->len == nlen && !memcmp(dname->name, name, nlen))
11412+ err = hn_gen_tree(d);
11413+ dput(d);
11414+ }
1facf9fc 11415+
1308ab2a 11416+ out:
4a4d8108 11417+ AuTraceErr(err);
1308ab2a 11418+ return err;
11419+}
dece6358 11420+
4a4d8108 11421+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 11422+{
4a4d8108
AM
11423+ int err;
11424+ struct inode *inode;
1facf9fc 11425+
4a4d8108
AM
11426+ inode = dentry->d_inode;
11427+ if (IS_ROOT(dentry)
11428+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
11429+ ) {
11430+ pr_warning("branch root dir was changed\n");
11431+ return 0;
11432+ }
1308ab2a 11433+
4a4d8108
AM
11434+ err = 0;
11435+ if (!isdir) {
11436+ d_drop(dentry);
11437+ au_digen_dec(dentry);
11438+ if (inode)
11439+ au_iigen_dec(inode);
11440+ } else {
11441+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
11442+ if (inode)
11443+ err = hn_gen_tree(dentry);
11444+ }
11445+
11446+ AuTraceErr(err);
11447+ return err;
1facf9fc 11448+}
11449+
4a4d8108 11450+/* ---------------------------------------------------------------------- */
1facf9fc 11451+
4a4d8108
AM
11452+/* hnotify job flags */
11453+#define AuHnJob_XINO0 1
11454+#define AuHnJob_GEN (1 << 1)
11455+#define AuHnJob_DIRENT (1 << 2)
11456+#define AuHnJob_ISDIR (1 << 3)
11457+#define AuHnJob_TRYXINO0 (1 << 4)
11458+#define AuHnJob_MNTPNT (1 << 5)
11459+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
11460+#define au_fset_hnjob(flags, name) { (flags) |= AuHnJob_##name; }
11461+#define au_fclr_hnjob(flags, name) { (flags) &= ~AuHnJob_##name; }
1facf9fc 11462+
4a4d8108
AM
11463+enum {
11464+ AuHn_CHILD,
11465+ AuHn_PARENT,
11466+ AuHnLast
11467+};
1facf9fc 11468+
4a4d8108
AM
11469+struct au_hnotify_args {
11470+ struct inode *h_dir, *dir, *h_child_inode;
11471+ u32 mask;
11472+ unsigned int flags[AuHnLast];
11473+ unsigned int h_child_nlen;
11474+ char h_child_name[];
11475+};
1facf9fc 11476+
4a4d8108
AM
11477+struct hn_job_args {
11478+ unsigned int flags;
11479+ struct inode *inode, *h_inode, *dir, *h_dir;
11480+ struct dentry *dentry;
11481+ char *h_name;
11482+ int h_nlen;
11483+};
1308ab2a 11484+
4a4d8108
AM
11485+static int hn_job(struct hn_job_args *a)
11486+{
11487+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 11488+
4a4d8108
AM
11489+ /* reset xino */
11490+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
11491+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 11492+
4a4d8108
AM
11493+ if (au_ftest_hnjob(a->flags, TRYXINO0)
11494+ && a->inode
11495+ && a->h_inode) {
11496+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11497+ if (!a->h_inode->i_nlink)
11498+ hn_xino(a->inode, a->h_inode); /* ignore this error */
11499+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 11500+ }
1facf9fc 11501+
4a4d8108
AM
11502+ /* make the generation obsolete */
11503+ if (au_ftest_hnjob(a->flags, GEN)) {
11504+ int err = -1;
11505+ if (a->inode)
11506+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
11507+ isdir);
11508+ if (err && a->dentry)
11509+ hn_gen_by_name(a->dentry, isdir);
11510+ /* ignore this error */
1facf9fc 11511+ }
1facf9fc 11512+
4a4d8108
AM
11513+ /* make dir entries obsolete */
11514+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
11515+ struct au_vdir *vdir;
1facf9fc 11516+
4a4d8108
AM
11517+ vdir = au_ivdir(a->inode);
11518+ if (vdir)
11519+ vdir->vd_jiffy = 0;
11520+ /* IMustLock(a->inode); */
11521+ /* a->inode->i_version++; */
11522+ }
1facf9fc 11523+
4a4d8108
AM
11524+ /* can do nothing but warn */
11525+ if (au_ftest_hnjob(a->flags, MNTPNT)
11526+ && a->dentry
11527+ && d_mountpoint(a->dentry))
11528+ pr_warning("mount-point %.*s is removed or renamed\n",
11529+ AuDLNPair(a->dentry));
1facf9fc 11530+
4a4d8108 11531+ return 0;
1308ab2a 11532+}
1facf9fc 11533+
1308ab2a 11534+/* ---------------------------------------------------------------------- */
1facf9fc 11535+
4a4d8108
AM
11536+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
11537+ struct inode *dir)
1308ab2a 11538+{
4a4d8108
AM
11539+ struct dentry *dentry, *d, *parent;
11540+ struct qstr *dname;
1308ab2a 11541+
4a4d8108
AM
11542+ parent = d_find_alias(dir);
11543+ if (!parent)
11544+ return NULL;
1308ab2a 11545+
4a4d8108
AM
11546+ dentry = NULL;
11547+ spin_lock(&dcache_lock);
11548+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
11549+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
11550+ dname = &d->d_name;
11551+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
11552+ continue;
11553+ if (!atomic_read(&d->d_count) || !d->d_fsdata) {
11554+ spin_lock(&d->d_lock);
11555+ __d_drop(d);
11556+ spin_unlock(&d->d_lock);
11557+ continue;
dece6358 11558+ }
1facf9fc 11559+
4a4d8108
AM
11560+ dentry = dget(d);
11561+ break;
1308ab2a 11562+ }
4a4d8108
AM
11563+ spin_unlock(&dcache_lock);
11564+ dput(parent);
1facf9fc 11565+
4a4d8108
AM
11566+ if (dentry)
11567+ di_write_lock_child(dentry);
1308ab2a 11568+
4a4d8108
AM
11569+ return dentry;
11570+}
dece6358 11571+
4a4d8108
AM
11572+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
11573+ aufs_bindex_t bindex, ino_t h_ino)
11574+{
11575+ struct inode *inode;
11576+ ino_t ino;
11577+ int err;
11578+
11579+ inode = NULL;
11580+ err = au_xino_read(sb, bindex, h_ino, &ino);
11581+ if (!err && ino)
11582+ inode = ilookup(sb, ino);
11583+ if (!inode)
11584+ goto out;
11585+
11586+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11587+ pr_warning("wrong root branch\n");
11588+ iput(inode);
11589+ inode = NULL;
11590+ goto out;
1308ab2a 11591+ }
11592+
4a4d8108 11593+ ii_write_lock_child(inode);
1308ab2a 11594+
dece6358 11595+ out:
4a4d8108 11596+ return inode;
dece6358
AM
11597+}
11598+
4a4d8108 11599+static void au_hn_bh(void *_args)
1facf9fc 11600+{
4a4d8108
AM
11601+ struct au_hnotify_args *a = _args;
11602+ struct super_block *sb;
11603+ aufs_bindex_t bindex, bend, bfound;
11604+ unsigned char xino, try_iput;
1facf9fc 11605+ int err;
1308ab2a 11606+ struct inode *inode;
4a4d8108
AM
11607+ ino_t h_ino;
11608+ struct hn_job_args args;
11609+ struct dentry *dentry;
11610+ struct au_sbinfo *sbinfo;
1facf9fc 11611+
4a4d8108
AM
11612+ AuDebugOn(!_args);
11613+ AuDebugOn(!a->h_dir);
11614+ AuDebugOn(!a->dir);
11615+ AuDebugOn(!a->mask);
11616+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
11617+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
11618+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 11619+
4a4d8108
AM
11620+ inode = NULL;
11621+ dentry = NULL;
11622+ /*
11623+ * do not lock a->dir->i_mutex here
11624+ * because of d_revalidate() may cause a deadlock.
11625+ */
11626+ sb = a->dir->i_sb;
11627+ AuDebugOn(!sb);
11628+ sbinfo = au_sbi(sb);
11629+ AuDebugOn(!sbinfo);
11630+ /* big aufs lock */
11631+ si_noflush_write_lock(sb);
1facf9fc 11632+
4a4d8108
AM
11633+ ii_read_lock_parent(a->dir);
11634+ bfound = -1;
11635+ bend = au_ibend(a->dir);
11636+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
11637+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
11638+ bfound = bindex;
11639+ break;
11640+ }
11641+ ii_read_unlock(a->dir);
11642+ if (unlikely(bfound < 0))
11643+ goto out;
1facf9fc 11644+
4a4d8108
AM
11645+ xino = !!au_opt_test(au_mntflags(sb), XINO);
11646+ h_ino = 0;
11647+ if (a->h_child_inode)
11648+ h_ino = a->h_child_inode->i_ino;
1facf9fc 11649+
4a4d8108
AM
11650+ if (a->h_child_nlen
11651+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
11652+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
11653+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
11654+ a->dir);
11655+ try_iput = 0;
11656+ if (dentry)
11657+ inode = dentry->d_inode;
11658+ if (xino && !inode && h_ino
11659+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
11660+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
11661+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
11662+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
11663+ try_iput = 1;
11664+ }
1facf9fc 11665+
4a4d8108
AM
11666+ args.flags = a->flags[AuHn_CHILD];
11667+ args.dentry = dentry;
11668+ args.inode = inode;
11669+ args.h_inode = a->h_child_inode;
11670+ args.dir = a->dir;
11671+ args.h_dir = a->h_dir;
11672+ args.h_name = a->h_child_name;
11673+ args.h_nlen = a->h_child_nlen;
11674+ err = hn_job(&args);
11675+ if (dentry) {
11676+ if (dentry->d_fsdata)
11677+ di_write_unlock(dentry);
11678+ dput(dentry);
11679+ }
11680+ if (inode && try_iput) {
11681+ ii_write_unlock(inode);
11682+ iput(inode);
11683+ }
1facf9fc 11684+
4a4d8108
AM
11685+ ii_write_lock_parent(a->dir);
11686+ args.flags = a->flags[AuHn_PARENT];
11687+ args.dentry = NULL;
11688+ args.inode = a->dir;
11689+ args.h_inode = a->h_dir;
11690+ args.dir = NULL;
11691+ args.h_dir = NULL;
11692+ args.h_name = NULL;
11693+ args.h_nlen = 0;
11694+ err = hn_job(&args);
11695+ ii_write_unlock(a->dir);
1facf9fc 11696+
4a4d8108
AM
11697+ out:
11698+ au_nwt_done(&sbinfo->si_nowait);
11699+ si_write_unlock(sb);
1308ab2a 11700+
4a4d8108
AM
11701+ iput(a->h_child_inode);
11702+ iput(a->h_dir);
11703+ iput(a->dir);
1308ab2a 11704+ kfree(a);
dece6358 11705+}
1facf9fc 11706+
4a4d8108
AM
11707+/* ---------------------------------------------------------------------- */
11708+
11709+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
11710+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 11711+{
4a4d8108
AM
11712+ int err, len;
11713+ unsigned int flags[AuHnLast];
11714+ unsigned char isdir, isroot, wh;
11715+ struct inode *dir;
11716+ struct au_hnotify_args *args;
11717+ char *p, *h_child_name;
dece6358 11718+
1308ab2a 11719+ err = 0;
4a4d8108
AM
11720+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
11721+ dir = igrab(hnotify->hn_aufs_inode);
11722+ if (!dir)
11723+ goto out;
1facf9fc 11724+
4a4d8108
AM
11725+ isroot = (dir->i_ino == AUFS_ROOT_INO);
11726+ wh = 0;
11727+ h_child_name = (void *)h_child_qstr->name;
11728+ len = h_child_qstr->len;
11729+ if (h_child_name) {
11730+ if (len > AUFS_WH_PFX_LEN
11731+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
11732+ h_child_name += AUFS_WH_PFX_LEN;
11733+ len -= AUFS_WH_PFX_LEN;
11734+ wh = 1;
11735+ }
1facf9fc 11736+ }
dece6358 11737+
4a4d8108
AM
11738+ isdir = 0;
11739+ if (h_child_inode)
11740+ isdir = !!S_ISDIR(h_child_inode->i_mode);
11741+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
11742+ flags[AuHn_CHILD] = 0;
11743+ if (isdir)
11744+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
11745+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
11746+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
11747+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
11748+ case FS_MOVED_FROM:
11749+ case FS_MOVED_TO:
11750+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
11751+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11752+ /*FALLTHROUGH*/
11753+ case FS_CREATE:
11754+ AuDebugOn(!h_child_name || !h_child_inode);
11755+ break;
1facf9fc 11756+
4a4d8108
AM
11757+ case FS_DELETE:
11758+ /*
11759+ * aufs never be able to get this child inode.
11760+ * revalidation should be in d_revalidate()
11761+ * by checking i_nlink, i_generation or d_unhashed().
11762+ */
11763+ AuDebugOn(!h_child_name);
11764+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
11765+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11766+ break;
dece6358 11767+
4a4d8108
AM
11768+ default:
11769+ AuDebugOn(1);
11770+ }
1308ab2a 11771+
4a4d8108
AM
11772+ if (wh)
11773+ h_child_inode = NULL;
1308ab2a 11774+
4a4d8108
AM
11775+ err = -ENOMEM;
11776+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 11777+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
11778+ if (unlikely(!args)) {
11779+ AuErr1("no memory\n");
11780+ iput(dir);
11781+ goto out;
11782+ }
11783+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
11784+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
11785+ args->mask = mask;
11786+ args->dir = dir;
11787+ args->h_dir = igrab(h_dir);
11788+ if (h_child_inode)
11789+ h_child_inode = igrab(h_child_inode); /* can be NULL */
11790+ args->h_child_inode = h_child_inode;
11791+ args->h_child_nlen = len;
11792+ if (len) {
11793+ p = (void *)args;
11794+ p += sizeof(*args);
11795+ memcpy(p, h_child_name, len);
11796+ p[len] = 0;
1308ab2a 11797+ }
1308ab2a 11798+
4a4d8108 11799+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
4a4d8108
AM
11800+ if (unlikely(err)) {
11801+ pr_err("wkq %d\n", err);
11802+ iput(args->h_child_inode);
11803+ iput(args->h_dir);
11804+ iput(args->dir);
11805+ kfree(args);
1facf9fc 11806+ }
1facf9fc 11807+
4a4d8108 11808+out:
1facf9fc 11809+ return err;
11810+}
11811+
4a4d8108
AM
11812+static void au_hn_destroy_cache(void)
11813+{
11814+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
11815+ au_cachep[AuCache_HNOTIFY] = NULL;
11816+}
1308ab2a 11817+
4a4d8108 11818+int __init au_hnotify_init(void)
1facf9fc 11819+{
1308ab2a 11820+ int err;
1308ab2a 11821+
4a4d8108
AM
11822+ err = -ENOMEM;
11823+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
11824+ if (au_cachep[AuCache_HNOTIFY]) {
11825+ err = au_hnotify_op.init();
11826+ if (unlikely(err))
11827+ au_hn_destroy_cache();
1308ab2a 11828+ }
1308ab2a 11829+ AuTraceErr(err);
4a4d8108 11830+ return err;
1308ab2a 11831+}
11832+
4a4d8108 11833+void au_hnotify_fin(void)
1308ab2a 11834+{
4a4d8108
AM
11835+ au_hnotify_op.fin();
11836+ /* cf. au_cache_fin() */
11837+ if (au_cachep[AuCache_HNOTIFY])
11838+ au_hn_destroy_cache();
dece6358 11839+}
b752ccd1
AM
11840diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
11841--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
11842+++ linux/fs/aufs/iinfo.c 2010-08-21 21:00:02.980020464 +0200
11843@@ -0,0 +1,257 @@
dece6358 11844+/*
4a4d8108 11845+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
11846+ *
11847+ * This program, aufs is free software; you can redistribute it and/or modify
11848+ * it under the terms of the GNU General Public License as published by
11849+ * the Free Software Foundation; either version 2 of the License, or
11850+ * (at your option) any later version.
11851+ *
11852+ * This program is distributed in the hope that it will be useful,
11853+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11854+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11855+ * GNU General Public License for more details.
11856+ *
11857+ * You should have received a copy of the GNU General Public License
11858+ * along with this program; if not, write to the Free Software
11859+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11860+ */
1facf9fc 11861+
dece6358 11862+/*
4a4d8108 11863+ * inode private data
dece6358 11864+ */
1facf9fc 11865+
1308ab2a 11866+#include "aufs.h"
1facf9fc 11867+
4a4d8108 11868+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 11869+{
4a4d8108 11870+ struct inode *h_inode;
1facf9fc 11871+
4a4d8108 11872+ IiMustAnyLock(inode);
1facf9fc 11873+
4a4d8108
AM
11874+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
11875+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11876+ return h_inode;
11877+}
1facf9fc 11878+
4a4d8108
AM
11879+/* todo: hard/soft set? */
11880+void au_hiput(struct au_hinode *hinode)
11881+{
11882+ au_hn_free(hinode);
11883+ dput(hinode->hi_whdentry);
11884+ iput(hinode->hi_inode);
11885+}
1facf9fc 11886+
4a4d8108
AM
11887+unsigned int au_hi_flags(struct inode *inode, int isdir)
11888+{
11889+ unsigned int flags;
11890+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 11891+
4a4d8108
AM
11892+ flags = 0;
11893+ if (au_opt_test(mnt_flags, XINO))
11894+ au_fset_hi(flags, XINO);
11895+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
11896+ au_fset_hi(flags, HNOTIFY);
11897+ return flags;
1facf9fc 11898+}
11899+
4a4d8108
AM
11900+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
11901+ struct inode *h_inode, unsigned int flags)
1308ab2a 11902+{
4a4d8108
AM
11903+ struct au_hinode *hinode;
11904+ struct inode *hi;
11905+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 11906+
4a4d8108 11907+ IiMustWriteLock(inode);
dece6358 11908+
4a4d8108
AM
11909+ hinode = iinfo->ii_hinode + bindex;
11910+ hi = hinode->hi_inode;
11911+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11912+
11913+ if (hi)
11914+ au_hiput(hinode);
11915+ hinode->hi_inode = h_inode;
11916+ if (h_inode) {
11917+ int err;
11918+ struct super_block *sb = inode->i_sb;
11919+ struct au_branch *br;
11920+
11921+ if (bindex == iinfo->ii_bstart)
11922+ au_cpup_igen(inode, h_inode);
11923+ br = au_sbr(sb, bindex);
11924+ hinode->hi_id = br->br_id;
11925+ if (au_ftest_hi(flags, XINO)) {
11926+ err = au_xino_write(sb, bindex, h_inode->i_ino,
11927+ inode->i_ino);
11928+ if (unlikely(err))
11929+ AuIOErr1("failed au_xino_write() %d\n", err);
11930+ }
11931+
11932+ if (au_ftest_hi(flags, HNOTIFY)
11933+ && au_br_hnotifyable(br->br_perm)) {
11934+ err = au_hn_alloc(hinode, inode, h_inode);
11935+ if (unlikely(err))
11936+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 11937+ }
11938+ }
4a4d8108 11939+}
dece6358 11940+
4a4d8108
AM
11941+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
11942+ struct dentry *h_wh)
11943+{
11944+ struct au_hinode *hinode;
dece6358 11945+
4a4d8108
AM
11946+ IiMustWriteLock(inode);
11947+
11948+ hinode = au_ii(inode)->ii_hinode + bindex;
11949+ AuDebugOn(hinode->hi_whdentry);
11950+ hinode->hi_whdentry = h_wh;
1facf9fc 11951+}
11952+
4a4d8108 11953+void au_update_iigen(struct inode *inode)
1308ab2a 11954+{
4a4d8108
AM
11955+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
11956+ /* smp_mb(); */ /* atomic_set */
11957+}
1facf9fc 11958+
4a4d8108
AM
11959+/* it may be called at remount time, too */
11960+void au_update_ibrange(struct inode *inode, int do_put_zero)
11961+{
11962+ struct au_iinfo *iinfo;
1facf9fc 11963+
4a4d8108
AM
11964+ iinfo = au_ii(inode);
11965+ if (!iinfo || iinfo->ii_bstart < 0)
11966+ return;
1facf9fc 11967+
4a4d8108 11968+ IiMustWriteLock(inode);
1facf9fc 11969+
4a4d8108
AM
11970+ if (do_put_zero) {
11971+ aufs_bindex_t bindex;
1facf9fc 11972+
4a4d8108
AM
11973+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
11974+ bindex++) {
11975+ struct inode *h_i;
1facf9fc 11976+
4a4d8108
AM
11977+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
11978+ if (h_i && !h_i->i_nlink)
11979+ au_set_h_iptr(inode, bindex, NULL, 0);
11980+ }
11981+ }
1308ab2a 11982+
4a4d8108
AM
11983+ iinfo->ii_bstart = -1;
11984+ while (++iinfo->ii_bstart <= iinfo->ii_bend)
11985+ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
11986+ break;
11987+ if (iinfo->ii_bstart > iinfo->ii_bend) {
11988+ iinfo->ii_bstart = -1;
11989+ iinfo->ii_bend = -1;
11990+ return;
11991+ }
11992+
11993+ iinfo->ii_bend++;
11994+ while (0 <= --iinfo->ii_bend)
11995+ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
11996+ break;
11997+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
1308ab2a 11998+}
1facf9fc 11999+
dece6358 12000+/* ---------------------------------------------------------------------- */
1facf9fc 12001+
4a4d8108 12002+void au_icntnr_init_once(void *_c)
dece6358 12003+{
4a4d8108
AM
12004+ struct au_icntnr *c = _c;
12005+ struct au_iinfo *iinfo = &c->iinfo;
1facf9fc 12006+
4a4d8108
AM
12007+ au_rw_init(&iinfo->ii_rwsem);
12008+ inode_init_once(&c->vfs_inode);
12009+}
1facf9fc 12010+
4a4d8108
AM
12011+int au_iinfo_init(struct inode *inode)
12012+{
12013+ struct au_iinfo *iinfo;
12014+ struct super_block *sb;
12015+ int nbr, i;
1facf9fc 12016+
4a4d8108
AM
12017+ sb = inode->i_sb;
12018+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12019+ nbr = au_sbend(sb) + 1;
12020+ if (unlikely(nbr <= 0))
12021+ nbr = 1;
12022+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
12023+ if (iinfo->ii_hinode) {
12024+ for (i = 0; i < nbr; i++)
12025+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 12026+
4a4d8108
AM
12027+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
12028+ /* smp_mb(); */ /* atomic_set */
12029+ iinfo->ii_bstart = -1;
12030+ iinfo->ii_bend = -1;
12031+ iinfo->ii_vdir = NULL;
12032+ return 0;
1308ab2a 12033+ }
4a4d8108
AM
12034+ return -ENOMEM;
12035+}
1facf9fc 12036+
4a4d8108
AM
12037+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
12038+{
12039+ int err, sz;
12040+ struct au_hinode *hip;
1facf9fc 12041+
4a4d8108
AM
12042+ AuRwMustWriteLock(&iinfo->ii_rwsem);
12043+
12044+ err = -ENOMEM;
12045+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
12046+ if (!sz)
12047+ sz = sizeof(*hip);
12048+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
12049+ if (hip) {
12050+ iinfo->ii_hinode = hip;
12051+ err = 0;
1308ab2a 12052+ }
4a4d8108 12053+
1308ab2a 12054+ return err;
1facf9fc 12055+}
12056+
4a4d8108 12057+void au_iinfo_fin(struct inode *inode)
1facf9fc 12058+{
4a4d8108
AM
12059+ struct au_iinfo *iinfo;
12060+ struct au_hinode *hi;
12061+ struct super_block *sb;
b752ccd1
AM
12062+ aufs_bindex_t bindex, bend;
12063+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 12064+
4a4d8108
AM
12065+ iinfo = au_ii(inode);
12066+ /* bad_inode case */
12067+ if (!iinfo)
12068+ return;
1308ab2a 12069+
b752ccd1
AM
12070+ sb = inode->i_sb;
12071+ if (si_pid_test(sb))
12072+ au_xino_delete_inode(inode, unlinked);
12073+ else {
12074+ /*
12075+ * it is safe to hide the dependency between sbinfo and
12076+ * sb->s_umount.
12077+ */
12078+ lockdep_off();
12079+ si_noflush_read_lock(sb);
12080+ au_xino_delete_inode(inode, unlinked);
12081+ si_read_unlock(sb);
12082+ lockdep_on();
12083+ }
12084+
4a4d8108
AM
12085+ if (iinfo->ii_vdir)
12086+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 12087+
b752ccd1
AM
12088+ bindex = iinfo->ii_bstart;
12089+ if (bindex >= 0) {
12090+ hi = iinfo->ii_hinode + bindex;
4a4d8108 12091+ bend = iinfo->ii_bend;
b752ccd1
AM
12092+ while (bindex++ <= bend) {
12093+ if (hi->hi_inode)
4a4d8108 12094+ au_hiput(hi);
4a4d8108
AM
12095+ hi++;
12096+ }
12097+ }
4a4d8108
AM
12098+ kfree(iinfo->ii_hinode);
12099+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 12100+}
b752ccd1
AM
12101diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
12102--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
12103+++ linux/fs/aufs/inode.c 2010-08-21 21:00:02.980020464 +0200
12104@@ -0,0 +1,443 @@
4a4d8108
AM
12105+/*
12106+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12107+ *
12108+ * This program, aufs is free software; you can redistribute it and/or modify
12109+ * it under the terms of the GNU General Public License as published by
12110+ * the Free Software Foundation; either version 2 of the License, or
12111+ * (at your option) any later version.
12112+ *
12113+ * This program is distributed in the hope that it will be useful,
12114+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12115+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12116+ * GNU General Public License for more details.
12117+ *
12118+ * You should have received a copy of the GNU General Public License
12119+ * along with this program; if not, write to the Free Software
12120+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12121+ */
1facf9fc 12122+
4a4d8108
AM
12123+/*
12124+ * inode functions
12125+ */
1facf9fc 12126+
4a4d8108 12127+#include "aufs.h"
1308ab2a 12128+
4a4d8108
AM
12129+struct inode *au_igrab(struct inode *inode)
12130+{
12131+ if (inode) {
12132+ AuDebugOn(!atomic_read(&inode->i_count));
12133+ atomic_inc_return(&inode->i_count);
1facf9fc 12134+ }
4a4d8108
AM
12135+ return inode;
12136+}
1facf9fc 12137+
4a4d8108
AM
12138+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
12139+{
12140+ au_cpup_attr_all(inode, /*force*/0);
12141+ au_update_iigen(inode);
12142+ if (do_version)
12143+ inode->i_version++;
dece6358 12144+}
1facf9fc 12145+
4a4d8108 12146+int au_refresh_hinode_self(struct inode *inode, int do_attr)
dece6358 12147+{
4a4d8108
AM
12148+ int err, e;
12149+ aufs_bindex_t bindex, new_bindex;
12150+ unsigned char update;
12151+ struct au_hinode *p, *q, tmp;
1308ab2a 12152+ struct super_block *sb;
4a4d8108 12153+ struct au_iinfo *iinfo;
1facf9fc 12154+
4a4d8108 12155+ IiMustWriteLock(inode);
1facf9fc 12156+
4a4d8108
AM
12157+ update = 0;
12158+ sb = inode->i_sb;
12159+ iinfo = au_ii(inode);
12160+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
12161+ if (unlikely(err))
1308ab2a 12162+ goto out;
1facf9fc 12163+
4a4d8108
AM
12164+ p = iinfo->ii_hinode + iinfo->ii_bstart;
12165+ err = 0;
12166+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12167+ bindex++, p++) {
12168+ if (!p->hi_inode)
12169+ continue;
1facf9fc 12170+
4a4d8108
AM
12171+ new_bindex = au_br_index(sb, p->hi_id);
12172+ if (new_bindex == bindex)
12173+ continue;
1facf9fc 12174+
4a4d8108
AM
12175+ if (new_bindex < 0) {
12176+ update = 1;
12177+ au_hiput(p);
12178+ p->hi_inode = NULL;
12179+ continue;
1308ab2a 12180+ }
4a4d8108
AM
12181+
12182+ if (new_bindex < iinfo->ii_bstart)
12183+ iinfo->ii_bstart = new_bindex;
12184+ if (iinfo->ii_bend < new_bindex)
12185+ iinfo->ii_bend = new_bindex;
12186+ /* swap two lower inode, and loop again */
12187+ q = iinfo->ii_hinode + new_bindex;
12188+ tmp = *q;
12189+ *q = *p;
12190+ *p = tmp;
12191+ if (tmp.hi_inode) {
12192+ bindex--;
12193+ p--;
1308ab2a 12194+ }
12195+ }
4a4d8108
AM
12196+ au_update_ibrange(inode, /*do_put_zero*/0);
12197+ e = au_dy_irefresh(inode);
12198+ if (unlikely(e && !err))
12199+ err = e;
12200+ if (do_attr)
12201+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
1facf9fc 12202+
4a4d8108
AM
12203+ out:
12204+ return err;
12205+}
1facf9fc 12206+
4a4d8108
AM
12207+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
12208+{
12209+ int err, e;
12210+ unsigned int flags;
12211+ aufs_bindex_t bindex, bend;
12212+ unsigned char isdir, update;
12213+ struct au_hinode *p;
12214+ struct au_iinfo *iinfo;
1facf9fc 12215+
4a4d8108
AM
12216+ err = au_refresh_hinode_self(inode, /*do_attr*/0);
12217+ if (unlikely(err))
12218+ goto out;
12219+
12220+ update = 0;
12221+ iinfo = au_ii(inode);
12222+ p = iinfo->ii_hinode + iinfo->ii_bstart;
12223+ isdir = S_ISDIR(inode->i_mode);
12224+ flags = au_hi_flags(inode, isdir);
12225+ bend = au_dbend(dentry);
12226+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
12227+ struct inode *h_i;
12228+ struct dentry *h_d;
12229+
12230+ h_d = au_h_dptr(dentry, bindex);
12231+ if (!h_d || !h_d->d_inode)
12232+ continue;
12233+
12234+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
12235+ h_i = au_h_iptr(inode, bindex);
12236+ if (h_i) {
12237+ if (h_i == h_d->d_inode)
12238+ continue;
12239+ err = -EIO;
12240+ break;
12241+ }
12242+ }
12243+ if (bindex < iinfo->ii_bstart)
12244+ iinfo->ii_bstart = bindex;
12245+ if (iinfo->ii_bend < bindex)
12246+ iinfo->ii_bend = bindex;
12247+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
12248+ update = 1;
1308ab2a 12249+ }
4a4d8108
AM
12250+ au_update_ibrange(inode, /*do_put_zero*/0);
12251+ e = au_dy_irefresh(inode);
12252+ if (unlikely(e && !err))
12253+ err = e;
12254+ au_refresh_hinode_attr(inode, update && isdir);
12255+
1308ab2a 12256+ out:
4a4d8108 12257+ AuTraceErr(err);
1308ab2a 12258+ return err;
dece6358
AM
12259+}
12260+
4a4d8108 12261+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 12262+{
4a4d8108
AM
12263+ int err;
12264+ unsigned int flags;
12265+ umode_t mode;
12266+ aufs_bindex_t bindex, bstart, btail;
12267+ unsigned char isdir;
12268+ struct dentry *h_dentry;
12269+ struct inode *h_inode;
12270+ struct au_iinfo *iinfo;
dece6358 12271+
4a4d8108 12272+ IiMustWriteLock(inode);
dece6358 12273+
4a4d8108
AM
12274+ err = 0;
12275+ isdir = 0;
12276+ bstart = au_dbstart(dentry);
12277+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
12278+ mode = h_inode->i_mode;
12279+ switch (mode & S_IFMT) {
12280+ case S_IFREG:
12281+ btail = au_dbtail(dentry);
12282+ inode->i_op = &aufs_iop;
12283+ inode->i_fop = &aufs_file_fop;
12284+ err = au_dy_iaop(inode, bstart, h_inode);
12285+ if (unlikely(err))
12286+ goto out;
12287+ break;
12288+ case S_IFDIR:
12289+ isdir = 1;
12290+ btail = au_dbtaildir(dentry);
12291+ inode->i_op = &aufs_dir_iop;
12292+ inode->i_fop = &aufs_dir_fop;
12293+ break;
12294+ case S_IFLNK:
12295+ btail = au_dbtail(dentry);
12296+ inode->i_op = &aufs_symlink_iop;
12297+ break;
12298+ case S_IFBLK:
12299+ case S_IFCHR:
12300+ case S_IFIFO:
12301+ case S_IFSOCK:
12302+ btail = au_dbtail(dentry);
12303+ inode->i_op = &aufs_iop;
12304+ au_init_special_fop(inode, mode, h_inode->i_rdev);
12305+ break;
12306+ default:
12307+ AuIOErr("Unknown file type 0%o\n", mode);
12308+ err = -EIO;
1308ab2a 12309+ goto out;
4a4d8108 12310+ }
dece6358 12311+
4a4d8108
AM
12312+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
12313+ flags = au_hi_flags(inode, isdir);
12314+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
12315+ && au_ftest_hi(flags, HNOTIFY)
12316+ && dentry->d_name.len > AUFS_WH_PFX_LEN
12317+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
12318+ au_fclr_hi(flags, HNOTIFY);
12319+ iinfo = au_ii(inode);
12320+ iinfo->ii_bstart = bstart;
12321+ iinfo->ii_bend = btail;
12322+ for (bindex = bstart; bindex <= btail; bindex++) {
12323+ h_dentry = au_h_dptr(dentry, bindex);
12324+ if (h_dentry)
12325+ au_set_h_iptr(inode, bindex,
12326+ au_igrab(h_dentry->d_inode), flags);
12327+ }
12328+ au_cpup_attr_all(inode, /*force*/1);
dece6358 12329+
4a4d8108
AM
12330+ out:
12331+ return err;
12332+}
dece6358 12333+
4a4d8108
AM
12334+/* successful returns with iinfo write_locked */
12335+static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
12336+{
12337+ int err;
12338+ aufs_bindex_t bindex, bend;
12339+ struct inode *h_inode, *h_dinode;
dece6358 12340+
4a4d8108 12341+ *matched = 0;
dece6358 12342+
4a4d8108
AM
12343+ /*
12344+ * before this function, if aufs got any iinfo lock, it must be only
12345+ * one, the parent dir.
12346+ * it can happen by UDBA and the obsoleted inode number.
12347+ */
12348+ err = -EIO;
12349+ if (unlikely(inode->i_ino == parent_ino(dentry)))
12350+ goto out;
12351+
12352+ err = 0;
12353+ ii_write_lock_new_child(inode);
12354+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
12355+ bend = au_ibend(inode);
12356+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12357+ h_inode = au_h_iptr(inode, bindex);
12358+ if (h_inode && h_inode == h_dinode) {
12359+ *matched = 1;
12360+ err = 0;
12361+ if (au_iigen(inode) != au_digen(dentry))
12362+ err = au_refresh_hinode(inode, dentry);
12363+ break;
1308ab2a 12364+ }
1facf9fc 12365+ }
dece6358 12366+
4a4d8108
AM
12367+ if (unlikely(err))
12368+ ii_write_unlock(inode);
1facf9fc 12369+ out:
1facf9fc 12370+ return err;
12371+}
1facf9fc 12372+
4a4d8108
AM
12373+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12374+ unsigned int d_type, ino_t *ino)
1facf9fc 12375+{
4a4d8108
AM
12376+ int err;
12377+ struct mutex *mtx;
1facf9fc 12378+
b752ccd1 12379+ /* prevent hardlinked inode number from race condition */
4a4d8108 12380+ mtx = NULL;
b752ccd1 12381+ if (d_type != DT_DIR) {
4a4d8108
AM
12382+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
12383+ mutex_lock(mtx);
12384+ }
12385+ err = au_xino_read(sb, bindex, h_ino, ino);
12386+ if (unlikely(err))
12387+ goto out;
1308ab2a 12388+
4a4d8108
AM
12389+ if (!*ino) {
12390+ err = -EIO;
12391+ *ino = au_xino_new_ino(sb);
12392+ if (unlikely(!*ino))
1facf9fc 12393+ goto out;
4a4d8108
AM
12394+ err = au_xino_write(sb, bindex, h_ino, *ino);
12395+ if (unlikely(err))
1308ab2a 12396+ goto out;
1308ab2a 12397+ }
1facf9fc 12398+
12399+ out:
b752ccd1 12400+ if (mtx)
4a4d8108 12401+ mutex_unlock(mtx);
1facf9fc 12402+ return err;
12403+}
12404+
4a4d8108
AM
12405+/* successful returns with iinfo write_locked */
12406+/* todo: return with unlocked? */
12407+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 12408+{
b752ccd1 12409+ struct inode *inode, *h_inode;
4a4d8108
AM
12410+ struct dentry *h_dentry;
12411+ struct super_block *sb;
b752ccd1 12412+ struct mutex *mtx;
4a4d8108
AM
12413+ ino_t h_ino, ino;
12414+ int err, match;
12415+ aufs_bindex_t bstart;
1facf9fc 12416+
4a4d8108
AM
12417+ sb = dentry->d_sb;
12418+ bstart = au_dbstart(dentry);
12419+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
12420+ h_inode = h_dentry->d_inode;
12421+ h_ino = h_inode->i_ino;
12422+
12423+ /*
12424+ * stop 'race'-ing between hardlinks under different
12425+ * parents.
12426+ */
12427+ mtx = NULL;
12428+ if (!S_ISDIR(h_inode->i_mode))
12429+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
12430+
12431+ new_ino:
12432+ if (mtx)
12433+ mutex_lock(mtx);
4a4d8108
AM
12434+ err = au_xino_read(sb, bstart, h_ino, &ino);
12435+ inode = ERR_PTR(err);
12436+ if (unlikely(err))
12437+ goto out;
b752ccd1 12438+
4a4d8108
AM
12439+ if (!ino) {
12440+ ino = au_xino_new_ino(sb);
12441+ if (unlikely(!ino)) {
12442+ inode = ERR_PTR(-EIO);
dece6358
AM
12443+ goto out;
12444+ }
12445+ }
1facf9fc 12446+
4a4d8108
AM
12447+ AuDbg("i%lu\n", (unsigned long)ino);
12448+ inode = au_iget_locked(sb, ino);
12449+ err = PTR_ERR(inode);
12450+ if (IS_ERR(inode))
1facf9fc 12451+ goto out;
1facf9fc 12452+
4a4d8108
AM
12453+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
12454+ if (inode->i_state & I_NEW) {
12455+ ii_write_lock_new_child(inode);
12456+ err = set_inode(inode, dentry);
12457+ if (!err) {
12458+ unlock_new_inode(inode);
12459+ goto out; /* success */
12460+ }
1308ab2a 12461+
4a4d8108
AM
12462+ ii_write_unlock(inode);
12463+ iget_failed(inode);
12464+ goto out_err;
12465+ } else if (!must_new) {
b752ccd1
AM
12466+ /*
12467+ * horrible race condition between lookup, readdir and copyup
12468+ * (or something).
12469+ */
12470+ if (mtx)
12471+ mutex_unlock(mtx);
4a4d8108 12472+ err = reval_inode(inode, dentry, &match);
b752ccd1
AM
12473+ if (!err) {
12474+ mtx = NULL;
4a4d8108 12475+ goto out; /* success */
b752ccd1
AM
12476+ } else if (match) {
12477+ mtx = NULL;
4a4d8108 12478+ goto out_iput;
b752ccd1
AM
12479+ } else if (mtx)
12480+ mutex_lock(mtx);
4a4d8108
AM
12481+ }
12482+
12483+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
12484+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
12485+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
12486+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
12487+ (unsigned long)h_ino, (unsigned long)ino);
12488+ ino = 0;
12489+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
12490+ if (!err) {
12491+ iput(inode);
b752ccd1
AM
12492+ if (mtx)
12493+ mutex_unlock(mtx);
4a4d8108
AM
12494+ goto new_ino;
12495+ }
1308ab2a 12496+
4a4d8108
AM
12497+ out_iput:
12498+ iput(inode);
12499+ out_err:
12500+ inode = ERR_PTR(err);
1facf9fc 12501+ out:
b752ccd1
AM
12502+ if (mtx)
12503+ mutex_unlock(mtx);
4a4d8108 12504+ return inode;
1facf9fc 12505+}
12506+
4a4d8108 12507+/* ---------------------------------------------------------------------- */
1facf9fc 12508+
4a4d8108
AM
12509+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12510+ struct inode *inode)
12511+{
12512+ int err;
1facf9fc 12513+
4a4d8108 12514+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 12515+
4a4d8108
AM
12516+ /* pseudo-link after flushed may happen out of bounds */
12517+ if (!err
12518+ && inode
12519+ && au_ibstart(inode) <= bindex
12520+ && bindex <= au_ibend(inode)) {
12521+ /*
12522+ * permission check is unnecessary since vfsub routine
12523+ * will be called later
12524+ */
12525+ struct inode *hi = au_h_iptr(inode, bindex);
12526+ if (hi)
12527+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 12528+ }
12529+
4a4d8108
AM
12530+ return err;
12531+}
dece6358 12532+
4a4d8108
AM
12533+int au_test_h_perm(struct inode *h_inode, int mask)
12534+{
12535+ if (!current_fsuid())
12536+ return 0;
12537+ return inode_permission(h_inode, mask);
12538+}
1facf9fc 12539+
4a4d8108
AM
12540+int au_test_h_perm_sio(struct inode *h_inode, int mask)
12541+{
12542+ if (au_test_nfs(h_inode->i_sb)
12543+ && (mask & MAY_WRITE)
12544+ && S_ISDIR(h_inode->i_mode))
12545+ mask |= MAY_READ; /* force permission check */
12546+ return au_test_h_perm(h_inode, mask);
1facf9fc 12547+}
b752ccd1
AM
12548diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
12549--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
12550+++ linux/fs/aufs/inode.h 2010-08-21 21:00:02.980020464 +0200
4a4d8108
AM
12551@@ -0,0 +1,498 @@
12552+/*
12553+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12554+ *
12555+ * This program, aufs is free software; you can redistribute it and/or modify
12556+ * it under the terms of the GNU General Public License as published by
12557+ * the Free Software Foundation; either version 2 of the License, or
12558+ * (at your option) any later version.
12559+ *
12560+ * This program is distributed in the hope that it will be useful,
12561+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12562+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12563+ * GNU General Public License for more details.
12564+ *
12565+ * You should have received a copy of the GNU General Public License
12566+ * along with this program; if not, write to the Free Software
12567+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12568+ */
1facf9fc 12569+
1308ab2a 12570+/*
4a4d8108 12571+ * inode operations
1308ab2a 12572+ */
dece6358 12573+
4a4d8108
AM
12574+#ifndef __AUFS_INODE_H__
12575+#define __AUFS_INODE_H__
dece6358 12576+
4a4d8108 12577+#ifdef __KERNEL__
1308ab2a 12578+
4a4d8108
AM
12579+#include <linux/fs.h>
12580+#include <linux/fsnotify.h>
12581+#include <linux/aufs_type.h>
12582+#include "rwsem.h"
1308ab2a 12583+
4a4d8108 12584+struct vfsmount;
1facf9fc 12585+
4a4d8108
AM
12586+struct au_hnotify {
12587+#ifdef CONFIG_AUFS_HNOTIFY
12588+#ifdef CONFIG_AUFS_HFSNOTIFY
12589+ struct fsnotify_mark_entry hn_entry;
12590+#else
12591+ struct inotify_watch hn_watch;
12592+#endif
12593+ struct inode *hn_aufs_inode; /* no get/put */
12594+#endif
12595+} ____cacheline_aligned_in_smp;
1facf9fc 12596+
4a4d8108
AM
12597+struct au_hinode {
12598+ struct inode *hi_inode;
12599+ aufs_bindex_t hi_id;
12600+#ifdef CONFIG_AUFS_HNOTIFY
12601+ struct au_hnotify *hi_notify;
12602+#endif
dece6358 12603+
4a4d8108
AM
12604+ /* reference to the copied-up whiteout with get/put */
12605+ struct dentry *hi_whdentry;
12606+};
dece6358 12607+
4a4d8108
AM
12608+struct au_vdir;
12609+struct au_iinfo {
12610+ atomic_t ii_generation;
12611+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 12612+
4a4d8108
AM
12613+ struct au_rwsem ii_rwsem;
12614+ aufs_bindex_t ii_bstart, ii_bend;
12615+ __u32 ii_higen;
12616+ struct au_hinode *ii_hinode;
12617+ struct au_vdir *ii_vdir;
12618+};
1facf9fc 12619+
4a4d8108
AM
12620+struct au_icntnr {
12621+ struct au_iinfo iinfo;
12622+ struct inode vfs_inode;
12623+} ____cacheline_aligned_in_smp;
1308ab2a 12624+
4a4d8108
AM
12625+/* au_pin flags */
12626+#define AuPin_DI_LOCKED 1
12627+#define AuPin_MNT_WRITE (1 << 1)
12628+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
12629+#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
12630+#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
12631+
12632+struct au_pin {
12633+ /* input */
12634+ struct dentry *dentry;
12635+ unsigned int udba;
12636+ unsigned char lsc_di, lsc_hi, flags;
12637+ aufs_bindex_t bindex;
12638+
12639+ /* output */
12640+ struct dentry *parent;
12641+ struct au_hinode *hdir;
12642+ struct vfsmount *h_mnt;
12643+};
1facf9fc 12644+
1308ab2a 12645+/* ---------------------------------------------------------------------- */
12646+
4a4d8108 12647+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 12648+{
4a4d8108 12649+ struct au_iinfo *iinfo;
1facf9fc 12650+
4a4d8108
AM
12651+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12652+ if (iinfo->ii_hinode)
12653+ return iinfo;
12654+ return NULL; /* debugging bad_inode case */
12655+}
1facf9fc 12656+
4a4d8108 12657+/* ---------------------------------------------------------------------- */
1facf9fc 12658+
4a4d8108
AM
12659+/* inode.c */
12660+struct inode *au_igrab(struct inode *inode);
12661+int au_refresh_hinode_self(struct inode *inode, int do_attr);
12662+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
12663+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12664+ unsigned int d_type, ino_t *ino);
12665+struct inode *au_new_inode(struct dentry *dentry, int must_new);
12666+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12667+ struct inode *inode);
12668+int au_test_h_perm(struct inode *h_inode, int mask);
12669+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 12670+
4a4d8108
AM
12671+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
12672+ ino_t h_ino, unsigned int d_type, ino_t *ino)
12673+{
12674+#ifdef CONFIG_AUFS_SHWH
12675+ return au_ino(sb, bindex, h_ino, d_type, ino);
12676+#else
12677+ return 0;
12678+#endif
12679+}
1facf9fc 12680+
4a4d8108
AM
12681+/* i_op.c */
12682+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 12683+
4a4d8108
AM
12684+/* au_wr_dir flags */
12685+#define AuWrDir_ADD_ENTRY 1
12686+#define AuWrDir_ISDIR (1 << 1)
12687+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
12688+#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
12689+#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
1facf9fc 12690+
4a4d8108
AM
12691+struct au_wr_dir_args {
12692+ aufs_bindex_t force_btgt;
12693+ unsigned char flags;
12694+};
12695+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
12696+ struct au_wr_dir_args *args);
dece6358 12697+
4a4d8108
AM
12698+struct dentry *au_pinned_h_parent(struct au_pin *pin);
12699+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
12700+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
12701+ unsigned int udba, unsigned char flags);
12702+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
12703+ unsigned int udba, unsigned char flags) __must_check;
12704+int au_do_pin(struct au_pin *pin) __must_check;
12705+void au_unpin(struct au_pin *pin);
1facf9fc 12706+
4a4d8108
AM
12707+/* i_op_add.c */
12708+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
12709+ struct dentry *h_parent, int isdir);
12710+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
12711+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
12712+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
12713+ struct nameidata *nd);
12714+int aufs_link(struct dentry *src_dentry, struct inode *dir,
12715+ struct dentry *dentry);
12716+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
1facf9fc 12717+
4a4d8108
AM
12718+/* i_op_del.c */
12719+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
12720+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
12721+ struct dentry *h_parent, int isdir);
12722+int aufs_unlink(struct inode *dir, struct dentry *dentry);
12723+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 12724+
4a4d8108
AM
12725+/* i_op_ren.c */
12726+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
12727+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
12728+ struct inode *dir, struct dentry *dentry);
1facf9fc 12729+
4a4d8108
AM
12730+/* iinfo.c */
12731+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
12732+void au_hiput(struct au_hinode *hinode);
12733+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12734+ struct dentry *h_wh);
12735+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 12736+
4a4d8108
AM
12737+/* hinode flags */
12738+#define AuHi_XINO 1
12739+#define AuHi_HNOTIFY (1 << 1)
12740+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
12741+#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; }
12742+#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; }
1facf9fc 12743+
4a4d8108
AM
12744+#ifndef CONFIG_AUFS_HNOTIFY
12745+#undef AuHi_HNOTIFY
12746+#define AuHi_HNOTIFY 0
12747+#endif
1facf9fc 12748+
4a4d8108
AM
12749+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12750+ struct inode *h_inode, unsigned int flags);
1facf9fc 12751+
4a4d8108
AM
12752+void au_update_iigen(struct inode *inode);
12753+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 12754+
4a4d8108
AM
12755+void au_icntnr_init_once(void *_c);
12756+int au_iinfo_init(struct inode *inode);
12757+void au_iinfo_fin(struct inode *inode);
12758+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 12759+
4a4d8108
AM
12760+/* plink.c */
12761+void au_plink_maint_block(struct super_block *sb);
12762+void au_plink_maint_leave(struct file *file);
12763+#ifdef CONFIG_AUFS_DEBUG
12764+void au_plink_list(struct super_block *sb);
12765+#else
12766+AuStubVoid(au_plink_list, struct super_block *sb)
12767+#endif
12768+int au_plink_test(struct inode *inode);
12769+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
12770+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
12771+ struct dentry *h_dentry);
12772+void au_plink_put(struct super_block *sb);
12773+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
12774+long au_plink_ioctl(struct file *file, unsigned int cmd);
1facf9fc 12775+
4a4d8108 12776+/* ---------------------------------------------------------------------- */
1308ab2a 12777+
4a4d8108
AM
12778+/* lock subclass for iinfo */
12779+enum {
12780+ AuLsc_II_CHILD, /* child first */
12781+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
12782+ AuLsc_II_CHILD3, /* copyup dirs */
12783+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
12784+ AuLsc_II_PARENT2,
12785+ AuLsc_II_PARENT3, /* copyup dirs */
12786+ AuLsc_II_NEW_CHILD
12787+};
1308ab2a 12788+
1facf9fc 12789+/*
4a4d8108
AM
12790+ * ii_read_lock_child, ii_write_lock_child,
12791+ * ii_read_lock_child2, ii_write_lock_child2,
12792+ * ii_read_lock_child3, ii_write_lock_child3,
12793+ * ii_read_lock_parent, ii_write_lock_parent,
12794+ * ii_read_lock_parent2, ii_write_lock_parent2,
12795+ * ii_read_lock_parent3, ii_write_lock_parent3,
12796+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 12797+ */
4a4d8108
AM
12798+#define AuReadLockFunc(name, lsc) \
12799+static inline void ii_read_lock_##name(struct inode *i) \
12800+{ \
12801+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12802+}
12803+
12804+#define AuWriteLockFunc(name, lsc) \
12805+static inline void ii_write_lock_##name(struct inode *i) \
12806+{ \
12807+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12808+}
12809+
12810+#define AuRWLockFuncs(name, lsc) \
12811+ AuReadLockFunc(name, lsc) \
12812+ AuWriteLockFunc(name, lsc)
12813+
12814+AuRWLockFuncs(child, CHILD);
12815+AuRWLockFuncs(child2, CHILD2);
12816+AuRWLockFuncs(child3, CHILD3);
12817+AuRWLockFuncs(parent, PARENT);
12818+AuRWLockFuncs(parent2, PARENT2);
12819+AuRWLockFuncs(parent3, PARENT3);
12820+AuRWLockFuncs(new_child, NEW_CHILD);
12821+
12822+#undef AuReadLockFunc
12823+#undef AuWriteLockFunc
12824+#undef AuRWLockFuncs
1facf9fc 12825+
12826+/*
4a4d8108 12827+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 12828+ */
4a4d8108 12829+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 12830+
4a4d8108
AM
12831+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
12832+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
12833+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 12834+
4a4d8108 12835+/* ---------------------------------------------------------------------- */
1308ab2a 12836+
4a4d8108
AM
12837+static inline unsigned int au_iigen(struct inode *inode)
12838+{
12839+ return atomic_read(&au_ii(inode)->ii_generation);
12840+}
1308ab2a 12841+
4a4d8108
AM
12842+/* tiny test for inode number */
12843+/* tmpfs generation is too rough */
12844+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
12845+{
12846+ struct au_iinfo *iinfo;
1308ab2a 12847+
4a4d8108
AM
12848+ iinfo = au_ii(inode);
12849+ AuRwMustAnyLock(&iinfo->ii_rwsem);
12850+ return !(iinfo->ii_hsb1 == h_inode->i_sb
12851+ && iinfo->ii_higen == h_inode->i_generation);
12852+}
1308ab2a 12853+
4a4d8108
AM
12854+static inline void au_iigen_dec(struct inode *inode)
12855+{
12856+#ifdef CONFIG_AUFS_HNOTIFY
12857+ atomic_dec_return(&au_ii(inode)->ii_generation);
12858+#endif
12859+}
1308ab2a 12860+
4a4d8108 12861+/* ---------------------------------------------------------------------- */
1308ab2a 12862+
4a4d8108
AM
12863+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
12864+ aufs_bindex_t bindex)
12865+{
12866+ IiMustAnyLock(inode);
12867+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
12868+}
1308ab2a 12869+
4a4d8108
AM
12870+static inline aufs_bindex_t au_ibstart(struct inode *inode)
12871+{
12872+ IiMustAnyLock(inode);
12873+ return au_ii(inode)->ii_bstart;
12874+}
1308ab2a 12875+
4a4d8108
AM
12876+static inline aufs_bindex_t au_ibend(struct inode *inode)
12877+{
12878+ IiMustAnyLock(inode);
12879+ return au_ii(inode)->ii_bend;
12880+}
1308ab2a 12881+
4a4d8108
AM
12882+static inline struct au_vdir *au_ivdir(struct inode *inode)
12883+{
12884+ IiMustAnyLock(inode);
12885+ return au_ii(inode)->ii_vdir;
12886+}
1308ab2a 12887+
4a4d8108
AM
12888+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
12889+{
12890+ IiMustAnyLock(inode);
12891+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
12892+}
1308ab2a 12893+
4a4d8108 12894+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12895+{
4a4d8108
AM
12896+ IiMustWriteLock(inode);
12897+ au_ii(inode)->ii_bstart = bindex;
12898+}
1308ab2a 12899+
4a4d8108
AM
12900+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
12901+{
12902+ IiMustWriteLock(inode);
12903+ au_ii(inode)->ii_bend = bindex;
1308ab2a 12904+}
12905+
4a4d8108
AM
12906+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
12907+{
12908+ IiMustWriteLock(inode);
12909+ au_ii(inode)->ii_vdir = vdir;
12910+}
1facf9fc 12911+
4a4d8108 12912+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12913+{
4a4d8108
AM
12914+ IiMustAnyLock(inode);
12915+ return au_ii(inode)->ii_hinode + bindex;
12916+}
dece6358 12917+
4a4d8108 12918+/* ---------------------------------------------------------------------- */
1facf9fc 12919+
4a4d8108
AM
12920+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
12921+{
12922+ if (pin)
12923+ return pin->parent;
12924+ return NULL;
1facf9fc 12925+}
12926+
4a4d8108 12927+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 12928+{
4a4d8108
AM
12929+ if (pin && pin->hdir)
12930+ return pin->hdir->hi_inode;
12931+ return NULL;
1308ab2a 12932+}
1facf9fc 12933+
4a4d8108
AM
12934+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
12935+{
12936+ if (pin)
12937+ return pin->hdir;
12938+ return NULL;
12939+}
1facf9fc 12940+
4a4d8108 12941+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 12942+{
4a4d8108
AM
12943+ if (pin)
12944+ pin->dentry = dentry;
12945+}
1308ab2a 12946+
4a4d8108
AM
12947+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
12948+ unsigned char lflag)
12949+{
12950+ if (pin) {
12951+ /* dirty macros require brackets */
12952+ if (lflag) {
12953+ au_fset_pin(pin->flags, DI_LOCKED);
12954+ } else {
12955+ au_fclr_pin(pin->flags, DI_LOCKED);
12956+ }
1308ab2a 12957+ }
4a4d8108
AM
12958+}
12959+
12960+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
12961+{
12962+ if (pin) {
12963+ dput(pin->parent);
12964+ pin->parent = dget(parent);
1facf9fc 12965+ }
4a4d8108 12966+}
1facf9fc 12967+
4a4d8108
AM
12968+/* ---------------------------------------------------------------------- */
12969+
12970+#ifdef CONFIG_AUFS_HNOTIFY
12971+struct au_hnotify_op {
12972+ void (*ctl)(struct au_hinode *hinode, int do_set);
12973+ int (*alloc)(struct au_hnotify *hn, struct inode *h_inode);
12974+ void (*free)(struct au_hnotify *hn);
12975+
12976+ void (*fin)(void);
12977+ int (*init)(void);
12978+};
12979+
12980+/* hnotify.c */
12981+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
12982+ struct inode *h_inode);
12983+void au_hn_free(struct au_hinode *hinode);
12984+void au_hn_ctl(struct au_hinode *hinode, int do_set);
12985+void au_hn_reset(struct inode *inode, unsigned int flags);
12986+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
12987+ struct qstr *h_child_qstr, struct inode *h_child_inode);
12988+int __init au_hnotify_init(void);
12989+void au_hnotify_fin(void);
12990+
12991+/* hinotify.c */
12992+extern const struct au_hnotify_op au_hnotify_op;
12993+
12994+static inline
12995+void au_hn_init(struct au_hinode *hinode)
12996+{
12997+ hinode->hi_notify = NULL;
1308ab2a 12998+}
12999+
4a4d8108
AM
13000+#else
13001+static inline
13002+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
13003+ struct inode *inode __maybe_unused,
13004+ struct inode *h_inode __maybe_unused)
1308ab2a 13005+{
4a4d8108
AM
13006+ return -EOPNOTSUPP;
13007+}
1308ab2a 13008+
4a4d8108
AM
13009+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
13010+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
13011+ int do_set __maybe_unused)
13012+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
13013+ unsigned int flags __maybe_unused)
13014+AuStubInt0(__init au_hnotify_init, void)
13015+AuStubVoid(au_hnotify_fin, void)
13016+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
13017+#endif /* CONFIG_AUFS_HNOTIFY */
13018+
13019+static inline void au_hn_suspend(struct au_hinode *hdir)
13020+{
13021+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 13022+}
13023+
4a4d8108 13024+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 13025+{
4a4d8108
AM
13026+ au_hn_ctl(hdir, /*do_set*/1);
13027+}
1308ab2a 13028+
4a4d8108
AM
13029+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
13030+{
13031+ mutex_lock(&hdir->hi_inode->i_mutex);
13032+ au_hn_suspend(hdir);
13033+}
dece6358 13034+
4a4d8108
AM
13035+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
13036+ unsigned int sc __maybe_unused)
13037+{
13038+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
13039+ au_hn_suspend(hdir);
1facf9fc 13040+}
1facf9fc 13041+
4a4d8108
AM
13042+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
13043+{
13044+ au_hn_resume(hdir);
13045+ mutex_unlock(&hdir->hi_inode->i_mutex);
13046+}
13047+
13048+#endif /* __KERNEL__ */
13049+#endif /* __AUFS_INODE_H__ */
b752ccd1
AM
13050diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
13051--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
13052+++ linux/fs/aufs/ioctl.c 2010-08-21 21:00:02.980020464 +0200
13053@@ -0,0 +1,155 @@
4a4d8108
AM
13054+/*
13055+ * Copyright (C) 2005-2010 Junjiro R. Okajima
13056+ *
13057+ * This program, aufs is free software; you can redistribute it and/or modify
13058+ * it under the terms of the GNU General Public License as published by
13059+ * the Free Software Foundation; either version 2 of the License, or
13060+ * (at your option) any later version.
13061+ *
13062+ * This program is distributed in the hope that it will be useful,
13063+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13064+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13065+ * GNU General Public License for more details.
13066+ *
13067+ * You should have received a copy of the GNU General Public License
13068+ * along with this program; if not, write to the Free Software
13069+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13070+ */
13071+
13072+/*
13073+ * ioctl
13074+ * plink-management and readdir in userspace.
13075+ * assist the pathconf(3) wrapper library.
13076+ */
13077+
13078+#include <linux/file.h>
13079+#include "aufs.h"
13080+
13081+static int au_wbr_fd(struct path *path)
13082+{
13083+ int err, fd;
13084+ aufs_bindex_t wbi, bindex, bend;
13085+ struct file *h_file;
13086+ struct super_block *sb;
13087+ struct dentry *root;
13088+ struct au_branch *wbr;
13089+
13090+ err = get_unused_fd();
13091+ if (unlikely(err < 0))
13092+ goto out;
13093+ fd = err;
13094+
13095+ wbi = 0;
13096+ sb = path->dentry->d_sb;
13097+ root = sb->s_root;
13098+ aufs_read_lock(root, AuLock_IR);
13099+ wbr = au_sbr(sb, wbi);
13100+ if (!(path->mnt->mnt_flags & MNT_READONLY)
13101+ && !au_br_writable(wbr->br_perm)) {
13102+ bend = au_sbend(sb);
13103+ for (bindex = 1; bindex <= bend; bindex++) {
13104+ wbr = au_sbr(sb, bindex);
13105+ if (au_br_writable(wbr->br_perm)) {
13106+ wbi = bindex;
13107+ break;
13108+ }
13109+ }
13110+ wbr = au_sbr(sb, wbi);
13111+ }
13112+ AuDbg("wbi %d\n", wbi);
13113+ h_file = au_h_open(root, wbi, O_RDONLY | O_DIRECTORY | O_LARGEFILE,
13114+ NULL);
13115+ aufs_read_unlock(root, AuLock_IR);
13116+ err = PTR_ERR(h_file);
13117+ if (IS_ERR(h_file))
13118+ goto out_fd;
13119+
13120+ atomic_dec(&wbr->br_count); /* cf. au_h_open() */
13121+ fd_install(fd, h_file);
13122+ err = fd;
13123+ goto out; /* success */
13124+
13125+ out_fd:
13126+ put_unused_fd(fd);
13127+ out:
13128+ return err;
13129+}
13130+
13131+/* ---------------------------------------------------------------------- */
13132+
13133+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
13134+{
13135+ long err;
13136+
13137+ switch (cmd) {
13138+ case AUFS_CTL_PLINK_MAINT:
13139+ case AUFS_CTL_PLINK_CLEAN:
13140+ err = au_plink_ioctl(file, cmd);
13141+ break;
13142+
13143+ case AUFS_CTL_RDU:
13144+ case AUFS_CTL_RDU_INO:
13145+ err = au_rdu_ioctl(file, cmd, arg);
13146+ break;
13147+
13148+ case AUFS_CTL_WBR_FD:
13149+ err = au_wbr_fd(&file->f_path);
13150+ break;
13151+
13152+ default:
13153+ /* do not call the lower */
13154+ AuDbg("0x%x\n", cmd);
13155+ err = -ENOTTY;
13156+ }
13157+
13158+ AuTraceErr(err);
13159+ return err;
13160+}
13161+
13162+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
13163+{
13164+ long err;
13165+
13166+ switch (cmd) {
13167+ case AUFS_CTL_WBR_FD:
13168+ err = au_wbr_fd(&file->f_path);
13169+ break;
13170+
13171+ default:
13172+ /* do not call the lower */
13173+ AuDbg("0x%x\n", cmd);
13174+ err = -ENOTTY;
13175+ }
13176+
13177+ AuTraceErr(err);
13178+ return err;
13179+}
b752ccd1
AM
13180+
13181+#ifdef CONFIG_COMPAT
13182+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
13183+ unsigned long arg)
13184+{
13185+ long err;
13186+
13187+ switch (cmd) {
13188+ case AUFS_CTL_RDU:
13189+ case AUFS_CTL_RDU_INO:
13190+ err = au_rdu_compat_ioctl(file, cmd, arg);
13191+ break;
13192+
13193+ default:
13194+ err = aufs_ioctl_dir(file, cmd, arg);
13195+ }
13196+
13197+ AuTraceErr(err);
13198+ return err;
13199+}
13200+
13201+#if 0 /* unused yet */
13202+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
13203+ unsigned long arg)
13204+{
13205+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
13206+}
13207+#endif
13208+#endif
13209diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
13210--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
13211+++ linux/fs/aufs/i_op_add.c 2010-08-21 21:00:02.975972487 +0200
4a4d8108
AM
13212@@ -0,0 +1,672 @@
13213+/*
13214+ * Copyright (C) 2005-2010 Junjiro R. Okajima
13215+ *
13216+ * This program, aufs is free software; you can redistribute it and/or modify
13217+ * it under the terms of the GNU General Public License as published by
13218+ * the Free Software Foundation; either version 2 of the License, or
13219+ * (at your option) any later version.
13220+ *
13221+ * This program is distributed in the hope that it will be useful,
13222+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13223+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13224+ * GNU General Public License for more details.
13225+ *
13226+ * You should have received a copy of the GNU General Public License
13227+ * along with this program; if not, write to the Free Software
13228+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13229+ */
13230+
13231+/*
13232+ * inode operations (add entry)
13233+ */
13234+
13235+#include "aufs.h"
13236+
13237+/*
13238+ * final procedure of adding a new entry, except link(2).
13239+ * remove whiteout, instantiate, copyup the parent dir's times and size
13240+ * and update version.
13241+ * if it failed, re-create the removed whiteout.
13242+ */
13243+static int epilog(struct inode *dir, aufs_bindex_t bindex,
13244+ struct dentry *wh_dentry, struct dentry *dentry)
13245+{
13246+ int err, rerr;
13247+ aufs_bindex_t bwh;
13248+ struct path h_path;
13249+ struct inode *inode, *h_dir;
13250+ struct dentry *wh;
13251+
13252+ bwh = -1;
13253+ if (wh_dentry) {
13254+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
13255+ IMustLock(h_dir);
13256+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
13257+ bwh = au_dbwh(dentry);
13258+ h_path.dentry = wh_dentry;
13259+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
13260+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
13261+ dentry);
13262+ if (unlikely(err))
13263+ goto out;
13264+ }
13265+
13266+ inode = au_new_inode(dentry, /*must_new*/1);
13267+ if (!IS_ERR(inode)) {
13268+ d_instantiate(dentry, inode);
13269+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
13270+ IMustLock(dir);
13271+ if (au_ibstart(dir) == au_dbstart(dentry))
13272+ au_cpup_attr_timesizes(dir);
13273+ dir->i_version++;
13274+ return 0; /* success */
13275+ }
13276+
13277+ err = PTR_ERR(inode);
13278+ if (!wh_dentry)
13279+ goto out;
13280+
13281+ /* revert */
13282+ /* dir inode is locked */
13283+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
13284+ rerr = PTR_ERR(wh);
13285+ if (IS_ERR(wh)) {
13286+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
13287+ AuDLNPair(dentry), err, rerr);
13288+ err = -EIO;
13289+ } else
13290+ dput(wh);
13291+
13292+ out:
13293+ return err;
13294+}
13295+
13296+/*
13297+ * simple tests for the adding inode operations.
13298+ * following the checks in vfs, plus the parent-child relationship.
13299+ */
13300+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13301+ struct dentry *h_parent, int isdir)
13302+{
13303+ int err;
13304+ umode_t h_mode;
13305+ struct dentry *h_dentry;
13306+ struct inode *h_inode;
13307+
13308+ err = -ENAMETOOLONG;
13309+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13310+ goto out;
13311+
13312+ h_dentry = au_h_dptr(dentry, bindex);
13313+ h_inode = h_dentry->d_inode;
13314+ if (!dentry->d_inode) {
13315+ err = -EEXIST;
13316+ if (unlikely(h_inode))
13317+ goto out;
13318+ } else {
13319+ /* rename(2) case */
13320+ err = -EIO;
13321+ if (unlikely(!h_inode || !h_inode->i_nlink))
13322+ goto out;
13323+
13324+ h_mode = h_inode->i_mode;
13325+ if (!isdir) {
13326+ err = -EISDIR;
13327+ if (unlikely(S_ISDIR(h_mode)))
13328+ goto out;
13329+ } else if (unlikely(!S_ISDIR(h_mode))) {
13330+ err = -ENOTDIR;
13331+ goto out;
13332+ }
13333+ }
13334+
13335+ err = 0;
13336+ /* expected parent dir is locked */
13337+ if (unlikely(h_parent != h_dentry->d_parent))
13338+ err = -EIO;
13339+
13340+ out:
13341+ AuTraceErr(err);
13342+ return err;
13343+}
13344+
13345+/*
13346+ * initial procedure of adding a new entry.
13347+ * prepare writable branch and the parent dir, lock it,
13348+ * and lookup whiteout for the new entry.
13349+ */
13350+static struct dentry*
13351+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
13352+ struct dentry *src_dentry, struct au_pin *pin,
13353+ struct au_wr_dir_args *wr_dir_args)
13354+{
13355+ struct dentry *wh_dentry, *h_parent;
13356+ struct super_block *sb;
13357+ struct au_branch *br;
13358+ int err;
13359+ unsigned int udba;
13360+ aufs_bindex_t bcpup;
13361+
13362+ AuDbg("%.*s\n", AuDLNPair(dentry));
13363+
13364+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
13365+ bcpup = err;
13366+ wh_dentry = ERR_PTR(err);
13367+ if (unlikely(err < 0))
13368+ goto out;
13369+
13370+ sb = dentry->d_sb;
13371+ udba = au_opt_udba(sb);
13372+ err = au_pin(pin, dentry, bcpup, udba,
13373+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13374+ wh_dentry = ERR_PTR(err);
13375+ if (unlikely(err))
13376+ goto out;
13377+
13378+ h_parent = au_pinned_h_parent(pin);
13379+ if (udba != AuOpt_UDBA_NONE
13380+ && au_dbstart(dentry) == bcpup)
13381+ err = au_may_add(dentry, bcpup, h_parent,
13382+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
13383+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13384+ err = -ENAMETOOLONG;
13385+ wh_dentry = ERR_PTR(err);
13386+ if (unlikely(err))
13387+ goto out_unpin;
13388+
13389+ br = au_sbr(sb, bcpup);
13390+ if (dt) {
13391+ struct path tmp = {
13392+ .dentry = h_parent,
13393+ .mnt = br->br_mnt
13394+ };
13395+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
13396+ }
13397+
13398+ wh_dentry = NULL;
13399+ if (bcpup != au_dbwh(dentry))
13400+ goto out; /* success */
13401+
13402+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
13403+
13404+ out_unpin:
13405+ if (IS_ERR(wh_dentry))
13406+ au_unpin(pin);
13407+ out:
13408+ return wh_dentry;
13409+}
13410+
13411+/* ---------------------------------------------------------------------- */
13412+
13413+enum { Mknod, Symlink, Creat };
13414+struct simple_arg {
13415+ int type;
13416+ union {
13417+ struct {
13418+ int mode;
13419+ struct nameidata *nd;
13420+ } c;
13421+ struct {
13422+ const char *symname;
13423+ } s;
13424+ struct {
13425+ int mode;
13426+ dev_t dev;
13427+ } m;
13428+ } u;
13429+};
13430+
13431+static int add_simple(struct inode *dir, struct dentry *dentry,
13432+ struct simple_arg *arg)
13433+{
13434+ int err;
13435+ aufs_bindex_t bstart;
13436+ unsigned char created;
13437+ struct au_dtime dt;
13438+ struct au_pin pin;
13439+ struct path h_path;
13440+ struct dentry *wh_dentry, *parent;
13441+ struct inode *h_dir;
13442+ struct au_wr_dir_args wr_dir_args = {
13443+ .force_btgt = -1,
13444+ .flags = AuWrDir_ADD_ENTRY
13445+ };
13446+
13447+ AuDbg("%.*s\n", AuDLNPair(dentry));
13448+ IMustLock(dir);
13449+
13450+ parent = dentry->d_parent; /* dir inode is locked */
13451+ aufs_read_lock(dentry, AuLock_DW);
13452+ di_write_lock_parent(parent);
13453+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
13454+ &wr_dir_args);
13455+ err = PTR_ERR(wh_dentry);
13456+ if (IS_ERR(wh_dentry))
13457+ goto out;
13458+
13459+ bstart = au_dbstart(dentry);
13460+ h_path.dentry = au_h_dptr(dentry, bstart);
13461+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
13462+ h_dir = au_pinned_h_dir(&pin);
13463+ switch (arg->type) {
13464+ case Creat:
13465+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
13466+ break;
13467+ case Symlink:
13468+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
13469+ break;
13470+ case Mknod:
13471+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
13472+ break;
13473+ default:
13474+ BUG();
13475+ }
13476+ created = !err;
13477+ if (!err)
13478+ err = epilog(dir, bstart, wh_dentry, dentry);
13479+
13480+ /* revert */
13481+ if (unlikely(created && err && h_path.dentry->d_inode)) {
13482+ int rerr;
13483+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
13484+ if (rerr) {
13485+ AuIOErr("%.*s revert failure(%d, %d)\n",
13486+ AuDLNPair(dentry), err, rerr);
13487+ err = -EIO;
13488+ }
13489+ au_dtime_revert(&dt);
13490+ d_drop(dentry);
13491+ }
13492+
13493+ au_unpin(&pin);
13494+ dput(wh_dentry);
13495+
13496+ out:
13497+ if (unlikely(err)) {
13498+ au_update_dbstart(dentry);
13499+ d_drop(dentry);
13500+ }
13501+ di_write_unlock(parent);
13502+ aufs_read_unlock(dentry, AuLock_DW);
13503+ return err;
13504+}
13505+
13506+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
13507+{
13508+ struct simple_arg arg = {
13509+ .type = Mknod,
13510+ .u.m = {
13511+ .mode = mode,
13512+ .dev = dev
13513+ }
13514+ };
13515+ return add_simple(dir, dentry, &arg);
13516+}
13517+
13518+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
13519+{
13520+ struct simple_arg arg = {
13521+ .type = Symlink,
13522+ .u.s.symname = symname
13523+ };
13524+ return add_simple(dir, dentry, &arg);
13525+}
13526+
13527+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13528+ struct nameidata *nd)
13529+{
13530+ struct simple_arg arg = {
13531+ .type = Creat,
13532+ .u.c = {
13533+ .mode = mode,
13534+ .nd = nd
13535+ }
13536+ };
13537+ return add_simple(dir, dentry, &arg);
13538+}
13539+
13540+/* ---------------------------------------------------------------------- */
13541+
13542+struct au_link_args {
13543+ aufs_bindex_t bdst, bsrc;
13544+ struct au_pin pin;
13545+ struct path h_path;
13546+ struct dentry *src_parent, *parent;
13547+};
13548+
13549+static int au_cpup_before_link(struct dentry *src_dentry,
13550+ struct au_link_args *a)
13551+{
13552+ int err;
13553+ struct dentry *h_src_dentry;
13554+ struct mutex *h_mtx;
13555+ struct file *h_file;
13556+
13557+ di_read_lock_parent(a->src_parent, AuLock_IR);
13558+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
13559+ if (unlikely(err))
13560+ goto out;
13561+
13562+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
13563+ h_mtx = &h_src_dentry->d_inode->i_mutex;
13564+ err = au_pin(&a->pin, src_dentry, a->bdst,
13565+ au_opt_udba(src_dentry->d_sb),
13566+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13567+ if (unlikely(err))
13568+ goto out;
13569+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13570+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13571+ if (IS_ERR(h_file)) {
13572+ err = PTR_ERR(h_file);
13573+ h_file = NULL;
13574+ } else
13575+ err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
13576+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
13577+ mutex_unlock(h_mtx);
13578+ au_h_open_post(src_dentry, a->bsrc, h_file);
13579+ au_unpin(&a->pin);
13580+
13581+ out:
13582+ di_read_unlock(a->src_parent, AuLock_IR);
13583+ return err;
13584+}
13585+
13586+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
13587+{
13588+ int err;
13589+ unsigned char plink;
13590+ struct inode *h_inode, *inode;
13591+ struct dentry *h_src_dentry;
13592+ struct super_block *sb;
13593+ struct file *h_file;
13594+
13595+ plink = 0;
13596+ h_inode = NULL;
13597+ sb = src_dentry->d_sb;
13598+ inode = src_dentry->d_inode;
13599+ if (au_ibstart(inode) <= a->bdst)
13600+ h_inode = au_h_iptr(inode, a->bdst);
13601+ if (!h_inode || !h_inode->i_nlink) {
13602+ /* copyup src_dentry as the name of dentry. */
13603+ au_set_dbstart(src_dentry, a->bdst);
13604+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
13605+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
13606+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
13607+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13608+ if (IS_ERR(h_file)) {
13609+ err = PTR_ERR(h_file);
13610+ h_file = NULL;
13611+ } else
13612+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
13613+ -1, AuCpup_KEEPLINO,
13614+ a->parent);
13615+ mutex_unlock(&h_inode->i_mutex);
13616+ au_h_open_post(src_dentry, a->bsrc, h_file);
13617+ au_set_h_dptr(src_dentry, a->bdst, NULL);
13618+ au_set_dbstart(src_dentry, a->bsrc);
13619+ } else {
13620+ /* the inode of src_dentry already exists on a.bdst branch */
13621+ h_src_dentry = d_find_alias(h_inode);
13622+ if (!h_src_dentry && au_plink_test(inode)) {
13623+ plink = 1;
13624+ h_src_dentry = au_plink_lkup(inode, a->bdst);
13625+ err = PTR_ERR(h_src_dentry);
13626+ if (IS_ERR(h_src_dentry))
13627+ goto out;
13628+
13629+ if (unlikely(!h_src_dentry->d_inode)) {
13630+ dput(h_src_dentry);
13631+ h_src_dentry = NULL;
13632+ }
13633+
13634+ }
13635+ if (h_src_dentry) {
13636+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13637+ &a->h_path);
13638+ dput(h_src_dentry);
13639+ } else {
13640+ AuIOErr("no dentry found for hi%lu on b%d\n",
13641+ h_inode->i_ino, a->bdst);
13642+ err = -EIO;
13643+ }
13644+ }
13645+
13646+ if (!err && !plink)
13647+ au_plink_append(inode, a->bdst, a->h_path.dentry);
13648+
13649+out:
13650+ return err;
13651+}
13652+
13653+int aufs_link(struct dentry *src_dentry, struct inode *dir,
13654+ struct dentry *dentry)
13655+{
13656+ int err, rerr;
13657+ struct au_dtime dt;
13658+ struct au_link_args *a;
13659+ struct dentry *wh_dentry, *h_src_dentry;
13660+ struct inode *inode;
13661+ struct super_block *sb;
13662+ struct au_wr_dir_args wr_dir_args = {
13663+ /* .force_btgt = -1, */
13664+ .flags = AuWrDir_ADD_ENTRY
13665+ };
13666+
13667+ IMustLock(dir);
13668+ inode = src_dentry->d_inode;
13669+ IMustLock(inode);
13670+
13671+ err = -ENOENT;
13672+ if (unlikely(!inode->i_nlink))
13673+ goto out;
13674+
13675+ err = -ENOMEM;
13676+ a = kzalloc(sizeof(*a), GFP_NOFS);
13677+ if (unlikely(!a))
13678+ goto out;
13679+
13680+ a->parent = dentry->d_parent; /* dir inode is locked */
13681+ aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
13682+ a->src_parent = dget_parent(src_dentry);
13683+ wr_dir_args.force_btgt = au_dbstart(src_dentry);
13684+
13685+ di_write_lock_parent(a->parent);
13686+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
13687+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
13688+ &wr_dir_args);
13689+ err = PTR_ERR(wh_dentry);
13690+ if (IS_ERR(wh_dentry))
13691+ goto out_unlock;
13692+
13693+ err = 0;
13694+ sb = dentry->d_sb;
13695+ a->bdst = au_dbstart(dentry);
13696+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
13697+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
13698+ a->bsrc = au_dbstart(src_dentry);
13699+ if (au_opt_test(au_mntflags(sb), PLINK)) {
13700+ if (a->bdst < a->bsrc
13701+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
13702+ err = au_cpup_or_link(src_dentry, a);
13703+ else {
13704+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13705+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13706+ &a->h_path);
13707+ }
13708+ } else {
13709+ /*
13710+ * copyup src_dentry to the branch we process,
13711+ * and then link(2) to it.
13712+ */
13713+ if (a->bdst < a->bsrc
13714+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
13715+ au_unpin(&a->pin);
13716+ di_write_unlock(a->parent);
13717+ err = au_cpup_before_link(src_dentry, a);
13718+ di_write_lock_parent(a->parent);
13719+ if (!err)
13720+ err = au_pin(&a->pin, dentry, a->bdst,
13721+ au_opt_udba(sb),
13722+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13723+ if (unlikely(err))
13724+ goto out_wh;
13725+ }
13726+ if (!err) {
13727+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13728+ err = -ENOENT;
13729+ if (h_src_dentry && h_src_dentry->d_inode)
13730+ err = vfsub_link(h_src_dentry,
13731+ au_pinned_h_dir(&a->pin),
13732+ &a->h_path);
13733+ }
13734+ }
13735+ if (unlikely(err))
13736+ goto out_unpin;
13737+
13738+ if (wh_dentry) {
13739+ a->h_path.dentry = wh_dentry;
13740+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
13741+ dentry);
13742+ if (unlikely(err))
13743+ goto out_revert;
13744+ }
13745+
13746+ dir->i_version++;
13747+ if (au_ibstart(dir) == au_dbstart(dentry))
13748+ au_cpup_attr_timesizes(dir);
13749+ inc_nlink(inode);
13750+ inode->i_ctime = dir->i_ctime;
13751+ if (!d_unhashed(a->h_path.dentry))
13752+ d_instantiate(dentry, au_igrab(inode));
13753+ else
13754+ /* some filesystem calls d_drop() */
13755+ d_drop(dentry);
13756+ goto out_unpin; /* success */
13757+
13758+ out_revert:
13759+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
13760+ if (!rerr)
13761+ goto out_dt;
13762+ AuIOErr("%.*s reverting failed(%d, %d)\n",
13763+ AuDLNPair(dentry), err, rerr);
13764+ err = -EIO;
13765+ out_dt:
13766+ d_drop(dentry);
13767+ au_dtime_revert(&dt);
13768+ out_unpin:
13769+ au_unpin(&a->pin);
13770+ out_wh:
13771+ dput(wh_dentry);
13772+ out_unlock:
13773+ if (unlikely(err)) {
13774+ au_update_dbstart(dentry);
13775+ d_drop(dentry);
13776+ }
13777+ di_write_unlock(a->parent);
13778+ dput(a->src_parent);
13779+ aufs_read_and_write_unlock2(dentry, src_dentry);
13780+ kfree(a);
13781+ out:
13782+ return err;
13783+}
13784+
13785+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
13786+{
13787+ int err, rerr;
13788+ aufs_bindex_t bindex;
13789+ unsigned char diropq;
13790+ struct path h_path;
13791+ struct dentry *wh_dentry, *parent, *opq_dentry;
13792+ struct mutex *h_mtx;
13793+ struct super_block *sb;
13794+ struct {
13795+ struct au_pin pin;
13796+ struct au_dtime dt;
13797+ } *a; /* reduce the stack usage */
13798+ struct au_wr_dir_args wr_dir_args = {
13799+ .force_btgt = -1,
13800+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
13801+ };
13802+
13803+ IMustLock(dir);
13804+
13805+ err = -ENOMEM;
13806+ a = kmalloc(sizeof(*a), GFP_NOFS);
13807+ if (unlikely(!a))
13808+ goto out;
13809+
13810+ aufs_read_lock(dentry, AuLock_DW);
13811+ parent = dentry->d_parent; /* dir inode is locked */
13812+ di_write_lock_parent(parent);
13813+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
13814+ &a->pin, &wr_dir_args);
13815+ err = PTR_ERR(wh_dentry);
13816+ if (IS_ERR(wh_dentry))
13817+ goto out_free;
13818+
13819+ sb = dentry->d_sb;
13820+ bindex = au_dbstart(dentry);
13821+ h_path.dentry = au_h_dptr(dentry, bindex);
13822+ h_path.mnt = au_sbr_mnt(sb, bindex);
13823+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
13824+ if (unlikely(err))
13825+ goto out_unlock;
13826+
13827+ /* make the dir opaque */
13828+ diropq = 0;
13829+ h_mtx = &h_path.dentry->d_inode->i_mutex;
13830+ if (wh_dentry
13831+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
13832+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13833+ opq_dentry = au_diropq_create(dentry, bindex);
13834+ mutex_unlock(h_mtx);
13835+ err = PTR_ERR(opq_dentry);
13836+ if (IS_ERR(opq_dentry))
13837+ goto out_dir;
13838+ dput(opq_dentry);
13839+ diropq = 1;
13840+ }
13841+
13842+ err = epilog(dir, bindex, wh_dentry, dentry);
13843+ if (!err) {
13844+ inc_nlink(dir);
13845+ goto out_unlock; /* success */
13846+ }
13847+
13848+ /* revert */
13849+ if (diropq) {
13850+ AuLabel(revert opq);
13851+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13852+ rerr = au_diropq_remove(dentry, bindex);
13853+ mutex_unlock(h_mtx);
13854+ if (rerr) {
13855+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
13856+ AuDLNPair(dentry), err, rerr);
13857+ err = -EIO;
13858+ }
13859+ }
13860+
13861+ out_dir:
13862+ AuLabel(revert dir);
13863+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
13864+ if (rerr) {
13865+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
13866+ AuDLNPair(dentry), err, rerr);
13867+ err = -EIO;
13868+ }
13869+ d_drop(dentry);
13870+ au_dtime_revert(&a->dt);
13871+ out_unlock:
13872+ au_unpin(&a->pin);
13873+ dput(wh_dentry);
13874+ out_free:
13875+ if (unlikely(err)) {
13876+ au_update_dbstart(dentry);
13877+ d_drop(dentry);
13878+ }
13879+ di_write_unlock(parent);
13880+ aufs_read_unlock(dentry, AuLock_DW);
13881+ kfree(a);
13882+ out:
13883+ return err;
13884+}
b752ccd1
AM
13885diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
13886--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
13887+++ linux/fs/aufs/i_op.c 2010-08-21 21:00:02.975972487 +0200
13888@@ -0,0 +1,916 @@
4a4d8108
AM
13889+/*
13890+ * Copyright (C) 2005-2010 Junjiro R. Okajima
13891+ *
13892+ * This program, aufs is free software; you can redistribute it and/or modify
13893+ * it under the terms of the GNU General Public License as published by
13894+ * the Free Software Foundation; either version 2 of the License, or
13895+ * (at your option) any later version.
13896+ *
13897+ * This program is distributed in the hope that it will be useful,
13898+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13899+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13900+ * GNU General Public License for more details.
13901+ *
13902+ * You should have received a copy of the GNU General Public License
13903+ * along with this program; if not, write to the Free Software
13904+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13905+ */
1facf9fc 13906+
1308ab2a 13907+/*
4a4d8108 13908+ * inode operations (except add/del/rename)
1308ab2a 13909+ */
4a4d8108
AM
13910+
13911+#include <linux/device_cgroup.h>
13912+#include <linux/fs_stack.h>
13913+#include <linux/mm.h>
13914+#include <linux/namei.h>
13915+#include <linux/security.h>
13916+#include <linux/uaccess.h>
13917+#include "aufs.h"
13918+
13919+static int h_permission(struct inode *h_inode, int mask,
13920+ struct vfsmount *h_mnt, int brperm)
1facf9fc 13921+{
1308ab2a 13922+ int err;
4a4d8108 13923+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 13924+
4a4d8108
AM
13925+ err = -EACCES;
13926+ if ((write_mask && IS_IMMUTABLE(h_inode))
13927+ || ((mask & MAY_EXEC)
13928+ && S_ISREG(h_inode->i_mode)
13929+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
13930+ || !(h_inode->i_mode & S_IXUGO))))
13931+ goto out;
13932+
13933+ /*
13934+ * - skip the lower fs test in the case of write to ro branch.
13935+ * - nfs dir permission write check is optimized, but a policy for
13936+ * link/rename requires a real check.
13937+ */
13938+ if ((write_mask && !au_br_writable(brperm))
13939+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
13940+ && write_mask && !(mask & MAY_READ))
13941+ || !h_inode->i_op->permission) {
13942+ /* AuLabel(generic_permission); */
13943+ err = generic_permission(h_inode, mask,
13944+ h_inode->i_op->check_acl);
1308ab2a 13945+ } else {
4a4d8108
AM
13946+ /* AuLabel(h_inode->permission); */
13947+ err = h_inode->i_op->permission(h_inode, mask);
13948+ AuTraceErr(err);
13949+ }
1facf9fc 13950+
4a4d8108
AM
13951+ if (!err)
13952+ err = devcgroup_inode_permission(h_inode, mask);
13953+ if (!err) {
13954+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND);
13955+ err = security_inode_permission(h_inode, mask);
13956+ }
13957+
13958+#if 0
13959+ if (!err) {
13960+ /* todo: do we need to call ima_path_check()? */
13961+ struct path h_path = {
13962+ .dentry =
13963+ .mnt = h_mnt
13964+ };
13965+ err = ima_path_check(&h_path,
13966+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
13967+ IMA_COUNT_LEAVE);
1308ab2a 13968+ }
4a4d8108 13969+#endif
dece6358 13970+
4a4d8108 13971+ out:
1308ab2a 13972+ return err;
13973+}
dece6358 13974+
4a4d8108 13975+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 13976+{
13977+ int err;
4a4d8108
AM
13978+ aufs_bindex_t bindex, bend;
13979+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
13980+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
13981+ struct inode *h_inode;
13982+ struct super_block *sb;
13983+ struct au_branch *br;
1facf9fc 13984+
4a4d8108
AM
13985+ sb = inode->i_sb;
13986+ si_read_lock(sb, AuLock_FLUSH);
13987+ ii_read_lock_child(inode);
dece6358 13988+
4a4d8108
AM
13989+ if (!isdir || write_mask) {
13990+ err = au_busy_or_stale();
13991+ h_inode = au_h_iptr(inode, au_ibstart(inode));
13992+ if (unlikely(!h_inode
13993+ || (h_inode->i_mode & S_IFMT)
13994+ != (inode->i_mode & S_IFMT)))
13995+ goto out;
1facf9fc 13996+
4a4d8108
AM
13997+ err = 0;
13998+ bindex = au_ibstart(inode);
13999+ br = au_sbr(sb, bindex);
14000+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
14001+ if (write_mask
14002+ && !err
14003+ && !special_file(h_inode->i_mode)) {
14004+ /* test whether the upper writable branch exists */
14005+ err = -EROFS;
14006+ for (; bindex >= 0; bindex--)
14007+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
14008+ err = 0;
14009+ break;
14010+ }
14011+ }
14012+ goto out;
14013+ }
dece6358 14014+
4a4d8108 14015+ /* non-write to dir */
1308ab2a 14016+ err = 0;
4a4d8108
AM
14017+ bend = au_ibend(inode);
14018+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
14019+ h_inode = au_h_iptr(inode, bindex);
14020+ if (h_inode) {
14021+ err = au_busy_or_stale();
14022+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
14023+ break;
14024+
14025+ br = au_sbr(sb, bindex);
14026+ err = h_permission(h_inode, mask, br->br_mnt,
14027+ br->br_perm);
14028+ }
14029+ }
1308ab2a 14030+
4a4d8108
AM
14031+ out:
14032+ ii_read_unlock(inode);
14033+ si_read_unlock(sb);
1308ab2a 14034+ return err;
14035+}
14036+
4a4d8108 14037+/* ---------------------------------------------------------------------- */
1facf9fc 14038+
4a4d8108
AM
14039+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
14040+ struct nameidata *nd)
14041+{
14042+ struct dentry *ret, *parent;
b752ccd1 14043+ struct inode *inode;
4a4d8108
AM
14044+ struct super_block *sb;
14045+ int err, npositive;
dece6358 14046+
4a4d8108 14047+ IMustLock(dir);
1308ab2a 14048+
4a4d8108
AM
14049+ sb = dir->i_sb;
14050+ si_read_lock(sb, AuLock_FLUSH);
14051+ ret = ERR_PTR(-ENAMETOOLONG);
14052+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
14053+ goto out;
14054+ err = au_di_init(dentry);
14055+ ret = ERR_PTR(err);
14056+ if (unlikely(err))
14057+ goto out;
1308ab2a 14058+
4a4d8108
AM
14059+ parent = dentry->d_parent; /* dir inode is locked */
14060+ di_read_lock_parent(parent, AuLock_IR);
14061+ npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
14062+ di_read_unlock(parent, AuLock_IR);
14063+ err = npositive;
14064+ ret = ERR_PTR(err);
14065+ if (unlikely(err < 0))
14066+ goto out_unlock;
1308ab2a 14067+
4a4d8108
AM
14068+ inode = NULL;
14069+ if (npositive) {
b752ccd1 14070+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 14071+ ret = (void *)inode;
1facf9fc 14072+ }
4a4d8108
AM
14073+ if (IS_ERR(inode))
14074+ goto out_unlock;
14075+
14076+ ret = d_splice_alias(inode, dentry);
14077+ if (unlikely(IS_ERR(ret) && inode))
14078+ ii_write_unlock(inode);
1facf9fc 14079+
4a4d8108
AM
14080+ out_unlock:
14081+ di_write_unlock(dentry);
14082+ out:
14083+ si_read_unlock(sb);
14084+ return ret;
14085+}
1facf9fc 14086+
4a4d8108 14087+/* ---------------------------------------------------------------------- */
1facf9fc 14088+
4a4d8108
AM
14089+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
14090+ const unsigned char add_entry, aufs_bindex_t bcpup,
14091+ aufs_bindex_t bstart)
14092+{
14093+ int err;
14094+ struct dentry *h_parent;
14095+ struct inode *h_dir;
1facf9fc 14096+
4a4d8108
AM
14097+ if (add_entry) {
14098+ au_update_dbstart(dentry);
14099+ IMustLock(parent->d_inode);
14100+ } else
14101+ di_write_lock_parent(parent);
14102+
14103+ err = 0;
14104+ if (!au_h_dptr(parent, bcpup)) {
14105+ if (bstart < bcpup)
14106+ err = au_cpdown_dirs(dentry, bcpup);
14107+ else
14108+ err = au_cpup_dirs(dentry, bcpup);
14109+ }
14110+ if (!err && add_entry) {
14111+ h_parent = au_h_dptr(parent, bcpup);
14112+ h_dir = h_parent->d_inode;
14113+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
14114+ err = au_lkup_neg(dentry, bcpup);
14115+ /* todo: no unlock here */
14116+ mutex_unlock(&h_dir->i_mutex);
14117+ if (bstart < bcpup && au_dbstart(dentry) < 0) {
14118+ au_set_dbstart(dentry, 0);
14119+ au_update_dbrange(dentry, /*do_put_zero*/0);
14120+ }
1308ab2a 14121+ }
1facf9fc 14122+
4a4d8108
AM
14123+ if (!add_entry)
14124+ di_write_unlock(parent);
14125+ if (!err)
14126+ err = bcpup; /* success */
1308ab2a 14127+
4a4d8108
AM
14128+ return err;
14129+}
1facf9fc 14130+
4a4d8108
AM
14131+/*
14132+ * decide the branch and the parent dir where we will create a new entry.
14133+ * returns new bindex or an error.
14134+ * copyup the parent dir if needed.
14135+ */
14136+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14137+ struct au_wr_dir_args *args)
14138+{
14139+ int err;
14140+ aufs_bindex_t bcpup, bstart, src_bstart;
14141+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
14142+ ADD_ENTRY);
14143+ struct super_block *sb;
14144+ struct dentry *parent;
14145+ struct au_sbinfo *sbinfo;
1facf9fc 14146+
4a4d8108
AM
14147+ sb = dentry->d_sb;
14148+ sbinfo = au_sbi(sb);
14149+ parent = dget_parent(dentry);
14150+ bstart = au_dbstart(dentry);
14151+ bcpup = bstart;
14152+ if (args->force_btgt < 0) {
14153+ if (src_dentry) {
14154+ src_bstart = au_dbstart(src_dentry);
14155+ if (src_bstart < bstart)
14156+ bcpup = src_bstart;
14157+ } else if (add_entry) {
14158+ err = AuWbrCreate(sbinfo, dentry,
14159+ au_ftest_wrdir(args->flags, ISDIR));
14160+ bcpup = err;
14161+ }
1facf9fc 14162+
4a4d8108
AM
14163+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
14164+ if (add_entry)
14165+ err = AuWbrCopyup(sbinfo, dentry);
14166+ else {
14167+ if (!IS_ROOT(dentry)) {
14168+ di_read_lock_parent(parent, !AuLock_IR);
14169+ err = AuWbrCopyup(sbinfo, dentry);
14170+ di_read_unlock(parent, !AuLock_IR);
14171+ } else
14172+ err = AuWbrCopyup(sbinfo, dentry);
14173+ }
14174+ bcpup = err;
14175+ if (unlikely(err < 0))
14176+ goto out;
14177+ }
14178+ } else {
14179+ bcpup = args->force_btgt;
14180+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 14181+ }
4a4d8108
AM
14182+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
14183+ err = bcpup;
14184+ if (bcpup == bstart)
14185+ goto out; /* success */
14186+ else if (bstart < bcpup)
14187+ au_update_dbrange(dentry, /*do_put_zero*/1);
14188+
14189+ /* copyup the new parent into the branch we process */
14190+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
14191+
dece6358 14192+ out:
4a4d8108 14193+ dput(parent);
dece6358
AM
14194+ return err;
14195+}
1facf9fc 14196+
1308ab2a 14197+/* ---------------------------------------------------------------------- */
14198+
4a4d8108 14199+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 14200+{
4a4d8108
AM
14201+ if (pin && pin->parent)
14202+ return au_h_dptr(pin->parent, pin->bindex);
14203+ return NULL;
dece6358 14204+}
1facf9fc 14205+
4a4d8108 14206+void au_unpin(struct au_pin *p)
dece6358 14207+{
4a4d8108
AM
14208+ if (au_ftest_pin(p->flags, MNT_WRITE))
14209+ mnt_drop_write(p->h_mnt);
14210+ if (!p->hdir)
14211+ return;
1facf9fc 14212+
4a4d8108
AM
14213+ au_hn_imtx_unlock(p->hdir);
14214+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14215+ di_read_unlock(p->parent, AuLock_IR);
14216+ iput(p->hdir->hi_inode);
14217+ dput(p->parent);
14218+ p->parent = NULL;
14219+ p->hdir = NULL;
14220+ p->h_mnt = NULL;
14221+}
1308ab2a 14222+
4a4d8108
AM
14223+int au_do_pin(struct au_pin *p)
14224+{
14225+ int err;
14226+ struct super_block *sb;
14227+ struct dentry *h_dentry, *h_parent;
14228+ struct au_branch *br;
14229+ struct inode *h_dir;
14230+
14231+ err = 0;
14232+ sb = p->dentry->d_sb;
14233+ br = au_sbr(sb, p->bindex);
14234+ if (IS_ROOT(p->dentry)) {
14235+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14236+ p->h_mnt = br->br_mnt;
14237+ err = mnt_want_write(p->h_mnt);
14238+ if (unlikely(err)) {
14239+ au_fclr_pin(p->flags, MNT_WRITE);
14240+ goto out_err;
14241+ }
14242+ }
dece6358 14243+ goto out;
1facf9fc 14244+ }
14245+
4a4d8108
AM
14246+ h_dentry = NULL;
14247+ if (p->bindex <= au_dbend(p->dentry))
14248+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 14249+
4a4d8108
AM
14250+ p->parent = dget_parent(p->dentry);
14251+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14252+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 14253+
4a4d8108
AM
14254+ h_dir = NULL;
14255+ h_parent = au_h_dptr(p->parent, p->bindex);
14256+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
14257+ if (p->hdir)
14258+ h_dir = p->hdir->hi_inode;
dece6358 14259+
b752ccd1
AM
14260+ /*
14261+ * udba case, or
14262+ * if DI_LOCKED is not set, then p->parent may be different
14263+ * and h_parent can be NULL.
14264+ */
14265+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
4a4d8108
AM
14266+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14267+ di_read_unlock(p->parent, AuLock_IR);
14268+ dput(p->parent);
14269+ p->parent = NULL;
14270+ goto out_err;
14271+ }
1308ab2a 14272+
4a4d8108
AM
14273+ au_igrab(h_dir);
14274+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 14275+
4a4d8108
AM
14276+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
14277+ err = -EBUSY;
14278+ goto out_unpin;
14279+ }
14280+ if (h_dentry) {
14281+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
14282+ if (unlikely(err)) {
14283+ au_fclr_pin(p->flags, MNT_WRITE);
14284+ goto out_unpin;
14285+ }
1facf9fc 14286+ }
dece6358 14287+
4a4d8108
AM
14288+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14289+ p->h_mnt = br->br_mnt;
14290+ err = mnt_want_write(p->h_mnt);
dece6358 14291+ if (unlikely(err)) {
4a4d8108
AM
14292+ au_fclr_pin(p->flags, MNT_WRITE);
14293+ goto out_unpin;
dece6358
AM
14294+ }
14295+ }
4a4d8108
AM
14296+ goto out; /* success */
14297+
14298+ out_unpin:
14299+ au_unpin(p);
14300+ out_err:
14301+ pr_err("err %d\n", err);
14302+ err = au_busy_or_stale();
1facf9fc 14303+ out:
14304+ return err;
14305+}
14306+
4a4d8108
AM
14307+void au_pin_init(struct au_pin *p, struct dentry *dentry,
14308+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14309+ unsigned int udba, unsigned char flags)
14310+{
14311+ p->dentry = dentry;
14312+ p->udba = udba;
14313+ p->lsc_di = lsc_di;
14314+ p->lsc_hi = lsc_hi;
14315+ p->flags = flags;
14316+ p->bindex = bindex;
14317+
14318+ p->parent = NULL;
14319+ p->hdir = NULL;
14320+ p->h_mnt = NULL;
14321+}
14322+
14323+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14324+ unsigned int udba, unsigned char flags)
14325+{
14326+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
14327+ udba, flags);
14328+ return au_do_pin(pin);
14329+}
14330+
dece6358
AM
14331+/* ---------------------------------------------------------------------- */
14332+
1308ab2a 14333+/*
4a4d8108
AM
14334+ * ->setattr() and ->getattr() are called in various cases.
14335+ * chmod, stat: dentry is revalidated.
14336+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
14337+ * unhashed.
14338+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 14339+ */
4a4d8108 14340+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 14341+{
4a4d8108
AM
14342+ int err;
14343+ struct inode *inode;
14344+ struct dentry *parent;
1facf9fc 14345+
1308ab2a 14346+ err = 0;
4a4d8108
AM
14347+ inode = dentry->d_inode;
14348+ if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
14349+ parent = dget_parent(dentry);
14350+ di_read_lock_parent(parent, AuLock_IR);
14351+ /* returns a number of positive dentries */
14352+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
14353+ if (err >= 0)
14354+ err = au_refresh_hinode(inode, dentry);
14355+ di_read_unlock(parent, AuLock_IR);
14356+ dput(parent);
dece6358 14357+ }
1facf9fc 14358+
4a4d8108 14359+ AuTraceErr(err);
1308ab2a 14360+ return err;
14361+}
dece6358 14362+
4a4d8108
AM
14363+#define AuIcpup_DID_CPUP 1
14364+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
14365+#define au_fset_icpup(flags, name) { (flags) |= AuIcpup_##name; }
14366+#define au_fclr_icpup(flags, name) { (flags) &= ~AuIcpup_##name; }
1308ab2a 14367+
4a4d8108
AM
14368+struct au_icpup_args {
14369+ unsigned char flags;
14370+ unsigned char pin_flags;
14371+ aufs_bindex_t btgt;
14372+ unsigned int udba;
14373+ struct au_pin pin;
14374+ struct path h_path;
14375+ struct inode *h_inode;
14376+};
1308ab2a 14377+
4a4d8108
AM
14378+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
14379+ struct au_icpup_args *a)
1308ab2a 14380+{
14381+ int err;
4a4d8108
AM
14382+ loff_t sz;
14383+ aufs_bindex_t bstart;
14384+ struct dentry *hi_wh, *parent;
14385+ struct inode *inode;
14386+ struct file *h_file;
14387+ struct au_wr_dir_args wr_dir_args = {
14388+ .force_btgt = -1,
14389+ .flags = 0
14390+ };
14391+
14392+ bstart = au_dbstart(dentry);
14393+ inode = dentry->d_inode;
14394+ if (S_ISDIR(inode->i_mode))
14395+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
14396+ /* plink or hi_wh() case */
14397+ if (bstart != au_ibstart(inode))
14398+ wr_dir_args.force_btgt = au_ibstart(inode);
14399+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
14400+ if (unlikely(err < 0))
14401+ goto out;
14402+ a->btgt = err;
14403+ if (err != bstart)
14404+ au_fset_icpup(a->flags, DID_CPUP);
14405+
14406+ err = 0;
14407+ a->pin_flags = AuPin_MNT_WRITE;
14408+ parent = NULL;
14409+ if (!IS_ROOT(dentry)) {
14410+ au_fset_pin(a->pin_flags, DI_LOCKED);
14411+ parent = dget_parent(dentry);
14412+ di_write_lock_parent(parent);
14413+ }
14414+
14415+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
14416+ if (unlikely(err))
14417+ goto out_parent;
14418+
14419+ a->h_path.dentry = au_h_dptr(dentry, bstart);
14420+ a->h_inode = a->h_path.dentry->d_inode;
14421+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14422+ sz = -1;
14423+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
14424+ sz = ia->ia_size;
14425+
14426+ h_file = NULL;
14427+ hi_wh = NULL;
14428+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
14429+ hi_wh = au_hi_wh(inode, a->btgt);
14430+ if (!hi_wh) {
14431+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
14432+ if (unlikely(err))
14433+ goto out_unlock;
14434+ hi_wh = au_hi_wh(inode, a->btgt);
14435+ /* todo: revalidate hi_wh? */
14436+ }
14437+ }
14438+
14439+ if (parent) {
14440+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14441+ di_downgrade_lock(parent, AuLock_IR);
14442+ dput(parent);
14443+ parent = NULL;
14444+ }
14445+ if (!au_ftest_icpup(a->flags, DID_CPUP))
14446+ goto out; /* success */
14447+
14448+ if (!d_unhashed(dentry)) {
14449+ h_file = au_h_open_pre(dentry, bstart);
14450+ if (IS_ERR(h_file)) {
14451+ err = PTR_ERR(h_file);
14452+ h_file = NULL;
14453+ } else
14454+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
14455+ AuCpup_DTIME);
14456+ if (!err)
14457+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14458+ } else if (!hi_wh)
14459+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14460+ else
14461+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 14462+
4a4d8108
AM
14463+ out_unlock:
14464+ mutex_unlock(&a->h_inode->i_mutex);
14465+ au_h_open_post(dentry, bstart, h_file);
14466+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 14467+ if (!err) {
4a4d8108 14468+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 14469+ goto out; /* success */
1facf9fc 14470+ }
dece6358 14471+
4a4d8108
AM
14472+ au_unpin(&a->pin);
14473+ out_parent:
14474+ if (parent) {
14475+ di_write_unlock(parent);
14476+ dput(parent);
14477+ }
dece6358 14478+ out:
1facf9fc 14479+ return err;
14480+}
14481+
4a4d8108 14482+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 14483+{
4a4d8108
AM
14484+ int err;
14485+ struct inode *inode;
14486+ struct super_block *sb;
14487+ struct file *file;
14488+ struct au_icpup_args *a;
1facf9fc 14489+
4a4d8108
AM
14490+ inode = dentry->d_inode;
14491+ IMustLock(inode);
dece6358 14492+
4a4d8108
AM
14493+ err = -ENOMEM;
14494+ a = kzalloc(sizeof(*a), GFP_NOFS);
14495+ if (unlikely(!a))
14496+ goto out;
1facf9fc 14497+
4a4d8108
AM
14498+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
14499+ ia->ia_valid &= ~ATTR_MODE;
dece6358 14500+
4a4d8108
AM
14501+ file = NULL;
14502+ sb = dentry->d_sb;
14503+ si_read_lock(sb, AuLock_FLUSH);
14504+ if (ia->ia_valid & ATTR_FILE) {
14505+ /* currently ftruncate(2) only */
14506+ AuDebugOn(!S_ISREG(inode->i_mode));
14507+ file = ia->ia_file;
14508+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
14509+ if (unlikely(err))
14510+ goto out_si;
14511+ ia->ia_file = au_hf_top(file);
14512+ a->udba = AuOpt_UDBA_NONE;
14513+ } else {
14514+ /* fchmod() doesn't pass ia_file */
14515+ a->udba = au_opt_udba(sb);
14516+ if (d_unhashed(dentry))
14517+ a->udba = AuOpt_UDBA_NONE;
14518+ di_write_lock_child(dentry);
14519+ if (a->udba != AuOpt_UDBA_NONE) {
14520+ AuDebugOn(IS_ROOT(dentry));
14521+ err = au_reval_for_attr(dentry, au_sigen(sb));
14522+ if (unlikely(err))
14523+ goto out_dentry;
14524+ }
dece6358 14525+ }
dece6358 14526+
4a4d8108
AM
14527+ err = au_pin_and_icpup(dentry, ia, a);
14528+ if (unlikely(err < 0))
14529+ goto out_dentry;
14530+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
14531+ ia->ia_file = NULL;
14532+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 14533+ }
dece6358 14534+
4a4d8108
AM
14535+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
14536+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
14537+ == (ATTR_MODE | ATTR_CTIME)) {
14538+ err = security_path_chmod(a->h_path.dentry, a->h_path.mnt,
14539+ ia->ia_mode);
14540+ if (unlikely(err))
14541+ goto out_unlock;
14542+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
14543+ && (ia->ia_valid & ATTR_CTIME)) {
14544+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
14545+ if (unlikely(err))
14546+ goto out_unlock;
14547+ }
dece6358 14548+
4a4d8108
AM
14549+ if (ia->ia_valid & ATTR_SIZE) {
14550+ struct file *f;
1308ab2a 14551+
4a4d8108
AM
14552+ if (ia->ia_size < i_size_read(inode)) {
14553+ /* unmap only */
b752ccd1 14554+ err = simple_setsize(inode, ia->ia_size);
4a4d8108
AM
14555+ if (unlikely(err))
14556+ goto out_unlock;
14557+ }
1308ab2a 14558+
4a4d8108
AM
14559+ f = NULL;
14560+ if (ia->ia_valid & ATTR_FILE)
14561+ f = ia->ia_file;
14562+ mutex_unlock(&a->h_inode->i_mutex);
14563+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
14564+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14565+ } else
14566+ err = vfsub_notify_change(&a->h_path, ia);
14567+ if (!err)
14568+ au_cpup_attr_changeable(inode);
1308ab2a 14569+
4a4d8108
AM
14570+ out_unlock:
14571+ mutex_unlock(&a->h_inode->i_mutex);
14572+ au_unpin(&a->pin);
14573+ out_dentry:
14574+ di_write_unlock(dentry);
14575+ if (file) {
14576+ fi_write_unlock(file);
14577+ ia->ia_file = file;
14578+ ia->ia_valid |= ATTR_FILE;
14579+ }
14580+ out_si:
14581+ si_read_unlock(sb);
14582+ kfree(a);
14583+ out:
14584+ AuTraceErr(err);
14585+ return err;
1facf9fc 14586+}
14587+
4a4d8108
AM
14588+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
14589+ unsigned int nlink)
1facf9fc 14590+{
4a4d8108
AM
14591+ inode->i_mode = st->mode;
14592+ inode->i_uid = st->uid;
14593+ inode->i_gid = st->gid;
14594+ inode->i_atime = st->atime;
14595+ inode->i_mtime = st->mtime;
14596+ inode->i_ctime = st->ctime;
1facf9fc 14597+
4a4d8108
AM
14598+ au_cpup_attr_nlink(inode, /*force*/0);
14599+ if (S_ISDIR(inode->i_mode)) {
14600+ inode->i_nlink -= nlink;
14601+ inode->i_nlink += st->nlink;
14602+ }
1facf9fc 14603+
4a4d8108
AM
14604+ spin_lock(&inode->i_lock);
14605+ inode->i_blocks = st->blocks;
14606+ i_size_write(inode, st->size);
14607+ spin_unlock(&inode->i_lock);
1facf9fc 14608+}
14609+
4a4d8108
AM
14610+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
14611+ struct dentry *dentry, struct kstat *st)
1facf9fc 14612+{
4a4d8108
AM
14613+ int err;
14614+ unsigned int mnt_flags;
14615+ aufs_bindex_t bindex;
14616+ unsigned char udba_none, positive;
14617+ struct super_block *sb, *h_sb;
14618+ struct inode *inode;
14619+ struct vfsmount *h_mnt;
14620+ struct dentry *h_dentry;
1facf9fc 14621+
4a4d8108
AM
14622+ err = 0;
14623+ sb = dentry->d_sb;
14624+ inode = dentry->d_inode;
14625+ si_read_lock(sb, AuLock_FLUSH);
14626+ mnt_flags = au_mntflags(sb);
14627+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 14628+
4a4d8108
AM
14629+ /* support fstat(2) */
14630+ if (!d_unhashed(dentry) && !udba_none) {
14631+ unsigned int sigen = au_sigen(sb);
14632+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
14633+ di_read_lock_child(dentry, AuLock_IR);
14634+ else {
14635+ AuDebugOn(IS_ROOT(dentry));
14636+ di_write_lock_child(dentry);
14637+ err = au_reval_for_attr(dentry, sigen);
14638+ di_downgrade_lock(dentry, AuLock_IR);
14639+ if (unlikely(err))
14640+ goto out;
14641+ }
14642+ } else
14643+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 14644+
4a4d8108
AM
14645+ bindex = au_ibstart(inode);
14646+ h_mnt = au_sbr_mnt(sb, bindex);
14647+ h_sb = h_mnt->mnt_sb;
14648+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
14649+ goto out_fill; /* success */
1facf9fc 14650+
4a4d8108
AM
14651+ h_dentry = NULL;
14652+ if (au_dbstart(dentry) == bindex)
14653+ h_dentry = dget(au_h_dptr(dentry, bindex));
14654+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
14655+ h_dentry = au_plink_lkup(inode, bindex);
14656+ if (IS_ERR(h_dentry))
14657+ goto out_fill; /* pretending success */
14658+ }
14659+ /* illegally overlapped or something */
14660+ if (unlikely(!h_dentry))
14661+ goto out_fill; /* pretending success */
14662+
14663+ positive = !!h_dentry->d_inode;
14664+ if (positive)
14665+ err = vfs_getattr(h_mnt, h_dentry, st);
14666+ dput(h_dentry);
14667+ if (!err) {
14668+ if (positive)
14669+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
14670+ goto out_fill; /* success */
1facf9fc 14671+ }
4a4d8108
AM
14672+ goto out;
14673+
14674+ out_fill:
14675+ generic_fillattr(inode, st);
14676+ out:
14677+ di_read_unlock(dentry, AuLock_IR);
14678+ si_read_unlock(sb);
14679+ return err;
1facf9fc 14680+}
14681+
14682+/* ---------------------------------------------------------------------- */
14683+
4a4d8108
AM
14684+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
14685+ int bufsiz)
1facf9fc 14686+{
14687+ int err;
4a4d8108
AM
14688+ struct super_block *sb;
14689+ struct dentry *h_dentry;
1facf9fc 14690+
4a4d8108
AM
14691+ err = -EINVAL;
14692+ h_dentry = au_h_dptr(dentry, bindex);
14693+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
14694+ goto out;
1facf9fc 14695+
4a4d8108
AM
14696+ err = security_inode_readlink(h_dentry);
14697+ if (unlikely(err))
dece6358 14698+ goto out;
1facf9fc 14699+
4a4d8108
AM
14700+ sb = dentry->d_sb;
14701+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
14702+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
14703+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 14704+ }
4a4d8108 14705+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 14706+
4a4d8108
AM
14707+ out:
14708+ return err;
14709+}
1facf9fc 14710+
4a4d8108
AM
14711+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
14712+{
14713+ int err;
1facf9fc 14714+
4a4d8108
AM
14715+ aufs_read_lock(dentry, AuLock_IR);
14716+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
14717+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14718+
4a4d8108
AM
14719+ return err;
14720+}
1facf9fc 14721+
4a4d8108
AM
14722+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
14723+{
14724+ int err;
4a4d8108 14725+ mm_segment_t old_fs;
b752ccd1
AM
14726+ union {
14727+ char *k;
14728+ char __user *u;
14729+ } buf;
1facf9fc 14730+
4a4d8108 14731+ err = -ENOMEM;
b752ccd1
AM
14732+ buf.k = __getname_gfp(GFP_NOFS);
14733+ if (unlikely(!buf.k))
4a4d8108 14734+ goto out;
1facf9fc 14735+
4a4d8108
AM
14736+ aufs_read_lock(dentry, AuLock_IR);
14737+ old_fs = get_fs();
14738+ set_fs(KERNEL_DS);
b752ccd1 14739+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
4a4d8108
AM
14740+ set_fs(old_fs);
14741+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14742+
4a4d8108 14743+ if (err >= 0) {
b752ccd1 14744+ buf.k[err] = 0;
4a4d8108 14745+ /* will be freed by put_link */
b752ccd1 14746+ nd_set_link(nd, buf.k);
4a4d8108 14747+ return NULL; /* success */
1308ab2a 14748+ }
b752ccd1 14749+ __putname(buf.k);
1facf9fc 14750+
4a4d8108
AM
14751+ out:
14752+ path_put(&nd->path);
14753+ AuTraceErr(err);
14754+ return ERR_PTR(err);
14755+}
1facf9fc 14756+
4a4d8108
AM
14757+static void aufs_put_link(struct dentry *dentry __maybe_unused,
14758+ struct nameidata *nd, void *cookie __maybe_unused)
14759+{
14760+ __putname(nd_get_link(nd));
14761+}
1facf9fc 14762+
4a4d8108 14763+/* ---------------------------------------------------------------------- */
1facf9fc 14764+
4a4d8108
AM
14765+static void aufs_truncate_range(struct inode *inode __maybe_unused,
14766+ loff_t start __maybe_unused,
14767+ loff_t end __maybe_unused)
14768+{
14769+ AuUnsupport();
14770+}
1facf9fc 14771+
4a4d8108 14772+/* ---------------------------------------------------------------------- */
1308ab2a 14773+
4a4d8108
AM
14774+struct inode_operations aufs_symlink_iop = {
14775+ .permission = aufs_permission,
14776+ .setattr = aufs_setattr,
14777+ .getattr = aufs_getattr,
14778+ .readlink = aufs_readlink,
14779+ .follow_link = aufs_follow_link,
14780+ .put_link = aufs_put_link
14781+};
14782+
14783+struct inode_operations aufs_dir_iop = {
14784+ .create = aufs_create,
14785+ .lookup = aufs_lookup,
14786+ .link = aufs_link,
14787+ .unlink = aufs_unlink,
14788+ .symlink = aufs_symlink,
14789+ .mkdir = aufs_mkdir,
14790+ .rmdir = aufs_rmdir,
14791+ .mknod = aufs_mknod,
14792+ .rename = aufs_rename,
14793+
14794+ .permission = aufs_permission,
14795+ .setattr = aufs_setattr,
14796+ .getattr = aufs_getattr
14797+};
14798+
14799+struct inode_operations aufs_iop = {
14800+ .permission = aufs_permission,
14801+ .setattr = aufs_setattr,
14802+ .getattr = aufs_getattr,
14803+ .truncate_range = aufs_truncate_range
14804+};
b752ccd1
AM
14805diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
14806--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
14807+++ linux/fs/aufs/i_op_del.c 2010-08-21 21:00:02.975972487 +0200
4a4d8108 14808@@ -0,0 +1,472 @@
1facf9fc 14809+/*
4a4d8108 14810+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 14811+ *
14812+ * This program, aufs is free software; you can redistribute it and/or modify
14813+ * it under the terms of the GNU General Public License as published by
14814+ * the Free Software Foundation; either version 2 of the License, or
14815+ * (at your option) any later version.
dece6358
AM
14816+ *
14817+ * This program is distributed in the hope that it will be useful,
14818+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14819+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14820+ * GNU General Public License for more details.
14821+ *
14822+ * You should have received a copy of the GNU General Public License
14823+ * along with this program; if not, write to the Free Software
14824+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14825+ */
14826+
14827+/*
4a4d8108 14828+ * inode operations (del entry)
1308ab2a 14829+ */
dece6358 14830+
1308ab2a 14831+#include "aufs.h"
dece6358 14832+
4a4d8108
AM
14833+/*
14834+ * decide if a new whiteout for @dentry is necessary or not.
14835+ * when it is necessary, prepare the parent dir for the upper branch whose
14836+ * branch index is @bcpup for creation. the actual creation of the whiteout will
14837+ * be done by caller.
14838+ * return value:
14839+ * 0: wh is unnecessary
14840+ * plus: wh is necessary
14841+ * minus: error
14842+ */
14843+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 14844+{
4a4d8108
AM
14845+ int need_wh, err;
14846+ aufs_bindex_t bstart;
14847+ struct super_block *sb;
dece6358 14848+
4a4d8108
AM
14849+ sb = dentry->d_sb;
14850+ bstart = au_dbstart(dentry);
14851+ if (*bcpup < 0) {
14852+ *bcpup = bstart;
14853+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
14854+ err = AuWbrCopyup(au_sbi(sb), dentry);
14855+ *bcpup = err;
14856+ if (unlikely(err < 0))
14857+ goto out;
14858+ }
14859+ } else
14860+ AuDebugOn(bstart < *bcpup
14861+ || au_test_ro(sb, *bcpup, dentry->d_inode));
14862+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 14863+
4a4d8108
AM
14864+ if (*bcpup != bstart) {
14865+ err = au_cpup_dirs(dentry, *bcpup);
14866+ if (unlikely(err))
14867+ goto out;
14868+ need_wh = 1;
14869+ } else {
14870+ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
14871+
14872+ old_bend = au_dbend(dentry);
14873+ if (isdir) {
14874+ bdiropq = au_dbdiropq(dentry);
14875+ au_set_dbdiropq(dentry, -1);
14876+ }
14877+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
14878+ /*nd*/NULL);
14879+ err = need_wh;
14880+ if (isdir)
14881+ au_set_dbdiropq(dentry, bdiropq);
14882+ if (unlikely(err < 0))
14883+ goto out;
14884+ new_bend = au_dbend(dentry);
14885+ if (!need_wh && old_bend != new_bend) {
14886+ au_set_h_dptr(dentry, new_bend, NULL);
14887+ au_set_dbend(dentry, old_bend);
14888+ }
14889+ }
14890+ AuDbg("need_wh %d\n", need_wh);
14891+ err = need_wh;
14892+
14893+ out:
14894+ return err;
1facf9fc 14895+}
14896+
4a4d8108
AM
14897+/*
14898+ * simple tests for the del-entry operations.
14899+ * following the checks in vfs, plus the parent-child relationship.
14900+ */
14901+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14902+ struct dentry *h_parent, int isdir)
1facf9fc 14903+{
4a4d8108
AM
14904+ int err;
14905+ umode_t h_mode;
14906+ struct dentry *h_dentry, *h_latest;
1308ab2a 14907+ struct inode *h_inode;
1facf9fc 14908+
4a4d8108
AM
14909+ h_dentry = au_h_dptr(dentry, bindex);
14910+ h_inode = h_dentry->d_inode;
14911+ if (dentry->d_inode) {
14912+ err = -ENOENT;
14913+ if (unlikely(!h_inode || !h_inode->i_nlink))
14914+ goto out;
1facf9fc 14915+
4a4d8108
AM
14916+ h_mode = h_inode->i_mode;
14917+ if (!isdir) {
14918+ err = -EISDIR;
14919+ if (unlikely(S_ISDIR(h_mode)))
14920+ goto out;
14921+ } else if (unlikely(!S_ISDIR(h_mode))) {
14922+ err = -ENOTDIR;
14923+ goto out;
14924+ }
14925+ } else {
14926+ /* rename(2) case */
14927+ err = -EIO;
14928+ if (unlikely(h_inode))
14929+ goto out;
14930+ }
1facf9fc 14931+
4a4d8108
AM
14932+ err = -ENOENT;
14933+ /* expected parent dir is locked */
14934+ if (unlikely(h_parent != h_dentry->d_parent))
14935+ goto out;
14936+ err = 0;
14937+
14938+ /*
14939+ * rmdir a dir may break the consistency on some filesystem.
14940+ * let's try heavy test.
14941+ */
14942+ err = -EACCES;
14943+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
14944+ goto out;
14945+
14946+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
14947+ au_sbr(dentry->d_sb, bindex));
14948+ err = -EIO;
14949+ if (IS_ERR(h_latest))
14950+ goto out;
14951+ if (h_latest == h_dentry)
14952+ err = 0;
14953+ dput(h_latest);
14954+
14955+ out:
14956+ return err;
1308ab2a 14957+}
1facf9fc 14958+
4a4d8108
AM
14959+/*
14960+ * decide the branch where we operate for @dentry. the branch index will be set
14961+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
14962+ * dir for reverting.
14963+ * when a new whiteout is necessary, create it.
14964+ */
14965+static struct dentry*
14966+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
14967+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 14968+{
4a4d8108
AM
14969+ struct dentry *wh_dentry;
14970+ struct super_block *sb;
14971+ struct path h_path;
14972+ int err, need_wh;
14973+ unsigned int udba;
14974+ aufs_bindex_t bcpup;
dece6358 14975+
4a4d8108
AM
14976+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
14977+ wh_dentry = ERR_PTR(need_wh);
14978+ if (unlikely(need_wh < 0))
14979+ goto out;
14980+
14981+ sb = dentry->d_sb;
14982+ udba = au_opt_udba(sb);
14983+ bcpup = *rbcpup;
14984+ err = au_pin(pin, dentry, bcpup, udba,
14985+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14986+ wh_dentry = ERR_PTR(err);
14987+ if (unlikely(err))
14988+ goto out;
14989+
14990+ h_path.dentry = au_pinned_h_parent(pin);
14991+ if (udba != AuOpt_UDBA_NONE
14992+ && au_dbstart(dentry) == bcpup) {
14993+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
14994+ wh_dentry = ERR_PTR(err);
14995+ if (unlikely(err))
14996+ goto out_unpin;
14997+ }
14998+
14999+ h_path.mnt = au_sbr_mnt(sb, bcpup);
15000+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
15001+ wh_dentry = NULL;
15002+ if (!need_wh)
15003+ goto out; /* success, no need to create whiteout */
15004+
15005+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
15006+ if (IS_ERR(wh_dentry))
15007+ goto out_unpin;
15008+
15009+ /* returns with the parent is locked and wh_dentry is dget-ed */
15010+ goto out; /* success */
15011+
15012+ out_unpin:
15013+ au_unpin(pin);
15014+ out:
15015+ return wh_dentry;
1facf9fc 15016+}
15017+
4a4d8108
AM
15018+/*
15019+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
15020+ * in order to be revertible and save time for removing many child whiteouts
15021+ * under the dir.
15022+ * returns 1 when there are too many child whiteout and caller should remove
15023+ * them asynchronously. returns 0 when the number of children is enough small to
15024+ * remove now or the branch fs is a remote fs.
15025+ * otherwise return an error.
15026+ */
15027+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
15028+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 15029+{
4a4d8108
AM
15030+ int rmdir_later, err, dirwh;
15031+ struct dentry *h_dentry;
15032+ struct super_block *sb;
15033+
15034+ sb = dentry->d_sb;
15035+ SiMustAnyLock(sb);
15036+ h_dentry = au_h_dptr(dentry, bindex);
15037+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
15038+ if (unlikely(err))
15039+ goto out;
15040+
15041+ /* stop monitoring */
15042+ au_hn_free(au_hi(dentry->d_inode, bindex));
15043+
15044+ if (!au_test_fs_remote(h_dentry->d_sb)) {
15045+ dirwh = au_sbi(sb)->si_dirwh;
15046+ rmdir_later = (dirwh <= 1);
15047+ if (!rmdir_later)
15048+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
15049+ dirwh);
15050+ if (rmdir_later)
15051+ return rmdir_later;
15052+ }
1facf9fc 15053+
4a4d8108
AM
15054+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
15055+ if (unlikely(err)) {
15056+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
15057+ AuDLNPair(h_dentry), bindex, err);
15058+ err = 0;
15059+ }
dece6358 15060+
4a4d8108
AM
15061+ out:
15062+ AuTraceErr(err);
15063+ return err;
15064+}
1308ab2a 15065+
4a4d8108
AM
15066+/*
15067+ * final procedure for deleting a entry.
15068+ * maintain dentry and iattr.
15069+ */
15070+static void epilog(struct inode *dir, struct dentry *dentry,
15071+ aufs_bindex_t bindex)
15072+{
15073+ struct inode *inode;
1308ab2a 15074+
4a4d8108
AM
15075+ inode = dentry->d_inode;
15076+ d_drop(dentry);
15077+ inode->i_ctime = dir->i_ctime;
1308ab2a 15078+
4a4d8108
AM
15079+ if (atomic_read(&dentry->d_count) == 1) {
15080+ au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
15081+ au_update_dbstart(dentry);
dece6358 15082+ }
4a4d8108
AM
15083+ if (au_ibstart(dir) == bindex)
15084+ au_cpup_attr_timesizes(dir);
15085+ dir->i_version++;
1facf9fc 15086+}
15087+
4a4d8108
AM
15088+/*
15089+ * when an error happened, remove the created whiteout and revert everything.
15090+ */
15091+static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
15092+ struct dentry *wh_dentry, struct dentry *dentry,
15093+ struct au_dtime *dt)
1facf9fc 15094+{
4a4d8108
AM
15095+ int rerr;
15096+ struct path h_path = {
15097+ .dentry = wh_dentry,
15098+ .mnt = au_sbr_mnt(dir->i_sb, bwh)
15099+ };
dece6358 15100+
4a4d8108
AM
15101+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
15102+ if (!rerr) {
15103+ au_set_dbwh(dentry, bwh);
15104+ au_dtime_revert(dt);
15105+ return 0;
15106+ }
dece6358 15107+
4a4d8108
AM
15108+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15109+ AuDLNPair(dentry), err, rerr);
15110+ return -EIO;
1facf9fc 15111+}
15112+
4a4d8108 15113+/* ---------------------------------------------------------------------- */
1facf9fc 15114+
4a4d8108 15115+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 15116+{
4a4d8108
AM
15117+ int err;
15118+ aufs_bindex_t bwh, bindex, bstart;
15119+ struct au_dtime dt;
15120+ struct au_pin pin;
15121+ struct path h_path;
15122+ struct inode *inode, *h_dir;
15123+ struct dentry *parent, *wh_dentry;
1facf9fc 15124+
4a4d8108
AM
15125+ IMustLock(dir);
15126+ inode = dentry->d_inode;
15127+ if (unlikely(!inode))
15128+ return -ENOENT; /* possible? */
15129+ IMustLock(inode);
1facf9fc 15130+
4a4d8108
AM
15131+ aufs_read_lock(dentry, AuLock_DW);
15132+ parent = dentry->d_parent; /* dir inode is locked */
15133+ di_write_lock_parent(parent);
1facf9fc 15134+
4a4d8108
AM
15135+ bstart = au_dbstart(dentry);
15136+ bwh = au_dbwh(dentry);
15137+ bindex = -1;
15138+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
15139+ err = PTR_ERR(wh_dentry);
15140+ if (IS_ERR(wh_dentry))
15141+ goto out;
1facf9fc 15142+
4a4d8108
AM
15143+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
15144+ h_path.dentry = au_h_dptr(dentry, bstart);
15145+ dget(h_path.dentry);
15146+ if (bindex == bstart) {
15147+ h_dir = au_pinned_h_dir(&pin);
15148+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
15149+ } else {
15150+ /* dir inode is locked */
15151+ h_dir = wh_dentry->d_parent->d_inode;
15152+ IMustLock(h_dir);
15153+ err = 0;
15154+ }
dece6358 15155+
4a4d8108
AM
15156+ if (!err) {
15157+ drop_nlink(inode);
15158+ epilog(dir, dentry, bindex);
15159+
15160+ /* update target timestamps */
15161+ if (bindex == bstart) {
15162+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
15163+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
15164+ } else
15165+ /* todo: this timestamp may be reverted later */
15166+ inode->i_ctime = h_dir->i_ctime;
15167+ goto out_unlock; /* success */
1facf9fc 15168+ }
15169+
4a4d8108
AM
15170+ /* revert */
15171+ if (wh_dentry) {
15172+ int rerr;
15173+
15174+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
15175+ if (rerr)
15176+ err = rerr;
dece6358 15177+ }
1facf9fc 15178+
4a4d8108
AM
15179+ out_unlock:
15180+ au_unpin(&pin);
15181+ dput(wh_dentry);
15182+ dput(h_path.dentry);
15183+ out:
15184+ di_write_unlock(parent);
15185+ aufs_read_unlock(dentry, AuLock_DW);
15186+ return err;
dece6358
AM
15187+}
15188+
4a4d8108 15189+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 15190+{
4a4d8108
AM
15191+ int err, rmdir_later;
15192+ aufs_bindex_t bwh, bindex, bstart;
15193+ struct au_dtime dt;
15194+ struct au_pin pin;
15195+ struct inode *inode;
15196+ struct dentry *parent, *wh_dentry, *h_dentry;
15197+ struct au_whtmp_rmdir *args;
1facf9fc 15198+
4a4d8108
AM
15199+ IMustLock(dir);
15200+ inode = dentry->d_inode;
15201+ err = -ENOENT; /* possible? */
15202+ if (unlikely(!inode))
15203+ goto out;
15204+ IMustLock(inode);
dece6358 15205+
4a4d8108
AM
15206+ aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
15207+ err = -ENOMEM;
15208+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
15209+ if (unlikely(!args))
15210+ goto out_unlock;
dece6358 15211+
4a4d8108
AM
15212+ parent = dentry->d_parent; /* dir inode is locked */
15213+ di_write_lock_parent(parent);
15214+ err = au_test_empty(dentry, &args->whlist);
15215+ if (unlikely(err))
15216+ goto out_args;
1facf9fc 15217+
4a4d8108
AM
15218+ bstart = au_dbstart(dentry);
15219+ bwh = au_dbwh(dentry);
15220+ bindex = -1;
15221+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
15222+ err = PTR_ERR(wh_dentry);
15223+ if (IS_ERR(wh_dentry))
15224+ goto out_args;
1facf9fc 15225+
4a4d8108
AM
15226+ h_dentry = au_h_dptr(dentry, bstart);
15227+ dget(h_dentry);
15228+ rmdir_later = 0;
15229+ if (bindex == bstart) {
15230+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
15231+ if (err > 0) {
15232+ rmdir_later = err;
15233+ err = 0;
15234+ }
15235+ } else {
15236+ /* stop monitoring */
15237+ au_hn_free(au_hi(inode, bstart));
15238+
15239+ /* dir inode is locked */
15240+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 15241+ err = 0;
15242+ }
15243+
4a4d8108
AM
15244+ if (!err) {
15245+ clear_nlink(inode);
15246+ au_set_dbdiropq(dentry, -1);
15247+ epilog(dir, dentry, bindex);
1308ab2a 15248+
4a4d8108
AM
15249+ if (rmdir_later) {
15250+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
15251+ args = NULL;
15252+ }
1308ab2a 15253+
4a4d8108 15254+ goto out_unpin; /* success */
1facf9fc 15255+ }
15256+
4a4d8108
AM
15257+ /* revert */
15258+ AuLabel(revert);
15259+ if (wh_dentry) {
15260+ int rerr;
1308ab2a 15261+
4a4d8108
AM
15262+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
15263+ if (rerr)
15264+ err = rerr;
1facf9fc 15265+ }
15266+
4a4d8108
AM
15267+ out_unpin:
15268+ au_unpin(&pin);
15269+ dput(wh_dentry);
15270+ dput(h_dentry);
15271+ out_args:
15272+ di_write_unlock(parent);
15273+ if (args)
15274+ au_whtmp_rmdir_free(args);
15275+ out_unlock:
15276+ aufs_read_unlock(dentry, AuLock_DW);
15277+ out:
15278+ AuTraceErr(err);
15279+ return err;
dece6358 15280+}
b752ccd1
AM
15281diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
15282--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
15283+++ linux/fs/aufs/i_op_ren.c 2010-08-21 21:00:02.980020464 +0200
4a4d8108 15284@@ -0,0 +1,977 @@
1facf9fc 15285+/*
4a4d8108 15286+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 15287+ *
15288+ * This program, aufs is free software; you can redistribute it and/or modify
15289+ * it under the terms of the GNU General Public License as published by
15290+ * the Free Software Foundation; either version 2 of the License, or
15291+ * (at your option) any later version.
dece6358
AM
15292+ *
15293+ * This program is distributed in the hope that it will be useful,
15294+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15295+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15296+ * GNU General Public License for more details.
15297+ *
15298+ * You should have received a copy of the GNU General Public License
15299+ * along with this program; if not, write to the Free Software
15300+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 15301+ */
15302+
15303+/*
4a4d8108
AM
15304+ * inode operation (rename entry)
15305+ * todo: this is crazy monster
1facf9fc 15306+ */
15307+
15308+#include "aufs.h"
15309+
4a4d8108
AM
15310+enum { AuSRC, AuDST, AuSrcDst };
15311+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 15312+
4a4d8108
AM
15313+#define AuRen_ISDIR 1
15314+#define AuRen_ISSAMEDIR (1 << 1)
15315+#define AuRen_WHSRC (1 << 2)
15316+#define AuRen_WHDST (1 << 3)
15317+#define AuRen_MNT_WRITE (1 << 4)
15318+#define AuRen_DT_DSTDIR (1 << 5)
15319+#define AuRen_DIROPQ (1 << 6)
15320+#define AuRen_CPUP (1 << 7)
15321+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
15322+#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
15323+#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
1facf9fc 15324+
4a4d8108
AM
15325+struct au_ren_args {
15326+ struct {
15327+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
15328+ *wh_dentry;
15329+ struct inode *dir, *inode;
15330+ struct au_hinode *hdir;
15331+ struct au_dtime dt[AuParentChild];
15332+ aufs_bindex_t bstart;
15333+ } sd[AuSrcDst];
1facf9fc 15334+
4a4d8108
AM
15335+#define src_dentry sd[AuSRC].dentry
15336+#define src_dir sd[AuSRC].dir
15337+#define src_inode sd[AuSRC].inode
15338+#define src_h_dentry sd[AuSRC].h_dentry
15339+#define src_parent sd[AuSRC].parent
15340+#define src_h_parent sd[AuSRC].h_parent
15341+#define src_wh_dentry sd[AuSRC].wh_dentry
15342+#define src_hdir sd[AuSRC].hdir
15343+#define src_h_dir sd[AuSRC].hdir->hi_inode
15344+#define src_dt sd[AuSRC].dt
15345+#define src_bstart sd[AuSRC].bstart
1facf9fc 15346+
4a4d8108
AM
15347+#define dst_dentry sd[AuDST].dentry
15348+#define dst_dir sd[AuDST].dir
15349+#define dst_inode sd[AuDST].inode
15350+#define dst_h_dentry sd[AuDST].h_dentry
15351+#define dst_parent sd[AuDST].parent
15352+#define dst_h_parent sd[AuDST].h_parent
15353+#define dst_wh_dentry sd[AuDST].wh_dentry
15354+#define dst_hdir sd[AuDST].hdir
15355+#define dst_h_dir sd[AuDST].hdir->hi_inode
15356+#define dst_dt sd[AuDST].dt
15357+#define dst_bstart sd[AuDST].bstart
15358+
15359+ struct dentry *h_trap;
15360+ struct au_branch *br;
15361+ struct au_hinode *src_hinode;
15362+ struct path h_path;
15363+ struct au_nhash whlist;
15364+ aufs_bindex_t btgt;
1facf9fc 15365+
1308ab2a 15366+ unsigned int flags;
1facf9fc 15367+
4a4d8108
AM
15368+ struct au_whtmp_rmdir *thargs;
15369+ struct dentry *h_dst;
15370+};
1308ab2a 15371+
4a4d8108 15372+/* ---------------------------------------------------------------------- */
1308ab2a 15373+
4a4d8108
AM
15374+/*
15375+ * functions for reverting.
15376+ * when an error happened in a single rename systemcall, we should revert
15377+ * everything as if nothing happend.
15378+ * we don't need to revert the copied-up/down the parent dir since they are
15379+ * harmless.
15380+ */
1facf9fc 15381+
4a4d8108
AM
15382+#define RevertFailure(fmt, ...) do { \
15383+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
15384+ ##__VA_ARGS__, err, rerr); \
15385+ err = -EIO; \
15386+} while (0)
1facf9fc 15387+
4a4d8108 15388+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 15389+{
4a4d8108 15390+ int rerr;
1facf9fc 15391+
4a4d8108
AM
15392+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15393+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
15394+ au_hn_imtx_unlock(a->src_hinode);
15395+ if (rerr)
15396+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
15397+}
1facf9fc 15398+
4a4d8108
AM
15399+static void au_ren_rev_rename(int err, struct au_ren_args *a)
15400+{
15401+ int rerr;
1facf9fc 15402+
4a4d8108
AM
15403+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
15404+ a->br, /*nd*/NULL);
15405+ rerr = PTR_ERR(a->h_path.dentry);
15406+ if (IS_ERR(a->h_path.dentry)) {
15407+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
15408+ return;
1facf9fc 15409+ }
15410+
4a4d8108
AM
15411+ rerr = vfsub_rename(a->dst_h_dir,
15412+ au_h_dptr(a->src_dentry, a->btgt),
15413+ a->src_h_dir, &a->h_path);
15414+ d_drop(a->h_path.dentry);
15415+ dput(a->h_path.dentry);
15416+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
15417+ if (rerr)
15418+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 15419+}
15420+
4a4d8108 15421+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 15422+{
4a4d8108 15423+ int rerr;
1facf9fc 15424+
4a4d8108
AM
15425+ a->h_path.dentry = a->dst_h_dentry;
15426+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
15427+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
15428+ au_set_dbstart(a->src_dentry, a->src_bstart);
15429+ if (rerr)
15430+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 15431+}
15432+
4a4d8108 15433+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 15434+{
4a4d8108 15435+ int rerr;
dece6358 15436+
4a4d8108
AM
15437+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
15438+ a->br, /*nd*/NULL);
15439+ rerr = PTR_ERR(a->h_path.dentry);
15440+ if (IS_ERR(a->h_path.dentry)) {
15441+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
15442+ return;
15443+ }
15444+ if (a->h_path.dentry->d_inode) {
15445+ d_drop(a->h_path.dentry);
15446+ dput(a->h_path.dentry);
15447+ return;
dece6358
AM
15448+ }
15449+
4a4d8108
AM
15450+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
15451+ d_drop(a->h_path.dentry);
15452+ dput(a->h_path.dentry);
15453+ if (!rerr)
15454+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
15455+ else
15456+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
15457+}
1308ab2a 15458+
4a4d8108
AM
15459+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
15460+{
15461+ int rerr;
1308ab2a 15462+
4a4d8108
AM
15463+ a->h_path.dentry = a->src_wh_dentry;
15464+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
15465+ if (rerr)
15466+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
15467+}
1308ab2a 15468+
4a4d8108
AM
15469+static void au_ren_rev_drop(struct au_ren_args *a)
15470+{
15471+ struct dentry *d, *h_d;
15472+ int i;
15473+ aufs_bindex_t bend, bindex;
15474+
15475+ for (i = 0; i < AuSrcDst; i++) {
15476+ d = a->sd[i].dentry;
15477+ d_drop(d);
15478+ bend = au_dbend(d);
15479+ for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
15480+ h_d = au_h_dptr(d, bindex);
15481+ if (h_d)
15482+ d_drop(h_d);
15483+ }
1308ab2a 15484+ }
15485+
4a4d8108
AM
15486+ au_update_dbstart(a->dst_dentry);
15487+ if (a->thargs)
15488+ d_drop(a->h_dst);
1facf9fc 15489+}
4a4d8108 15490+#undef RevertFailure
1facf9fc 15491+
1308ab2a 15492+/* ---------------------------------------------------------------------- */
15493+
4a4d8108
AM
15494+/*
15495+ * when we have to copyup the renaming entry, do it with the rename-target name
15496+ * in order to minimize the cost (the later actual rename is unnecessary).
15497+ * otherwise rename it on the target branch.
15498+ */
15499+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 15500+{
dece6358 15501+ int err;
4a4d8108 15502+ struct dentry *d;
1facf9fc 15503+
4a4d8108
AM
15504+ d = a->src_dentry;
15505+ if (au_dbstart(d) == a->btgt) {
15506+ a->h_path.dentry = a->dst_h_dentry;
15507+ if (au_ftest_ren(a->flags, DIROPQ)
15508+ && au_dbdiropq(d) == a->btgt)
15509+ au_fclr_ren(a->flags, DIROPQ);
15510+ AuDebugOn(au_dbstart(d) != a->btgt);
15511+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
15512+ a->dst_h_dir, &a->h_path);
15513+ } else {
15514+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15515+ struct file *h_file;
1308ab2a 15516+
4a4d8108
AM
15517+ au_fset_ren(a->flags, CPUP);
15518+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15519+ au_set_dbstart(d, a->btgt);
15520+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
15521+ h_file = au_h_open_pre(d, a->src_bstart);
15522+ if (IS_ERR(h_file)) {
15523+ err = PTR_ERR(h_file);
15524+ h_file = NULL;
15525+ } else
15526+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
15527+ !AuCpup_DTIME, a->dst_parent);
15528+ mutex_unlock(h_mtx);
15529+ au_h_open_post(d, a->src_bstart, h_file);
15530+ if (!err) {
15531+ d = a->dst_dentry;
15532+ au_set_h_dptr(d, a->btgt, NULL);
15533+ au_update_dbstart(d);
15534+ } else {
15535+ au_set_h_dptr(d, a->btgt, NULL);
15536+ au_set_dbstart(d, a->src_bstart);
15537+ }
1308ab2a 15538+ }
1facf9fc 15539+
dece6358
AM
15540+ return err;
15541+}
1facf9fc 15542+
4a4d8108
AM
15543+/* cf. aufs_rmdir() */
15544+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 15545+{
4a4d8108
AM
15546+ int err;
15547+ struct inode *dir;
1facf9fc 15548+
4a4d8108
AM
15549+ dir = a->dst_dir;
15550+ SiMustAnyLock(dir->i_sb);
15551+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
15552+ au_sbi(dir->i_sb)->si_dirwh)
15553+ || au_test_fs_remote(a->h_dst->d_sb)) {
15554+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
15555+ if (unlikely(err))
15556+ pr_warning("failed removing whtmp dir %.*s (%d), "
15557+ "ignored.\n", AuDLNPair(a->h_dst), err);
15558+ } else {
15559+ au_nhash_wh_free(&a->thargs->whlist);
15560+ a->thargs->whlist = a->whlist;
15561+ a->whlist.nh_num = 0;
15562+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
15563+ dput(a->h_dst);
15564+ a->thargs = NULL;
15565+ }
15566+
15567+ return 0;
1308ab2a 15568+}
1facf9fc 15569+
4a4d8108
AM
15570+/* make it 'opaque' dir. */
15571+static int au_ren_diropq(struct au_ren_args *a)
15572+{
15573+ int err;
15574+ struct dentry *diropq;
1facf9fc 15575+
4a4d8108
AM
15576+ err = 0;
15577+ a->src_hinode = au_hi(a->src_inode, a->btgt);
15578+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15579+ diropq = au_diropq_create(a->src_dentry, a->btgt);
15580+ au_hn_imtx_unlock(a->src_hinode);
15581+ if (IS_ERR(diropq))
15582+ err = PTR_ERR(diropq);
15583+ dput(diropq);
1facf9fc 15584+
4a4d8108
AM
15585+ return err;
15586+}
1facf9fc 15587+
4a4d8108
AM
15588+static int do_rename(struct au_ren_args *a)
15589+{
15590+ int err;
15591+ struct dentry *d, *h_d;
1facf9fc 15592+
4a4d8108
AM
15593+ /* prepare workqueue args for asynchronous rmdir */
15594+ h_d = a->dst_h_dentry;
15595+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
15596+ err = -ENOMEM;
15597+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
15598+ if (unlikely(!a->thargs))
15599+ goto out;
15600+ a->h_dst = dget(h_d);
15601+ }
1facf9fc 15602+
4a4d8108
AM
15603+ /* create whiteout for src_dentry */
15604+ if (au_ftest_ren(a->flags, WHSRC)) {
15605+ a->src_wh_dentry
15606+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
15607+ err = PTR_ERR(a->src_wh_dentry);
15608+ if (IS_ERR(a->src_wh_dentry))
15609+ goto out_thargs;
15610+ }
1facf9fc 15611+
4a4d8108
AM
15612+ /* lookup whiteout for dentry */
15613+ if (au_ftest_ren(a->flags, WHDST)) {
15614+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
15615+ a->br);
15616+ err = PTR_ERR(h_d);
15617+ if (IS_ERR(h_d))
15618+ goto out_whsrc;
15619+ if (!h_d->d_inode)
15620+ dput(h_d);
15621+ else
15622+ a->dst_wh_dentry = h_d;
15623+ }
1facf9fc 15624+
4a4d8108
AM
15625+ /* rename dentry to tmpwh */
15626+ if (a->thargs) {
15627+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
15628+ if (unlikely(err))
15629+ goto out_whdst;
dece6358 15630+
4a4d8108
AM
15631+ d = a->dst_dentry;
15632+ au_set_h_dptr(d, a->btgt, NULL);
15633+ err = au_lkup_neg(d, a->btgt);
15634+ if (unlikely(err))
15635+ goto out_whtmp;
15636+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
15637+ }
1facf9fc 15638+
4a4d8108
AM
15639+ /* cpup src */
15640+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
15641+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15642+ struct file *h_file;
1facf9fc 15643+
4a4d8108
AM
15644+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15645+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
15646+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
15647+ if (IS_ERR(h_file)) {
15648+ err = PTR_ERR(h_file);
15649+ h_file = NULL;
15650+ } else
15651+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
15652+ !AuCpup_DTIME);
15653+ mutex_unlock(h_mtx);
15654+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
15655+ if (unlikely(err))
15656+ goto out_whtmp;
15657+ }
1facf9fc 15658+
4a4d8108
AM
15659+ /* rename by vfs_rename or cpup */
15660+ d = a->dst_dentry;
15661+ if (au_ftest_ren(a->flags, ISDIR)
15662+ && (a->dst_wh_dentry
15663+ || au_dbdiropq(d) == a->btgt
15664+ /* hide the lower to keep xino */
15665+ || a->btgt < au_dbend(d)
15666+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
15667+ au_fset_ren(a->flags, DIROPQ);
15668+ err = au_ren_or_cpup(a);
15669+ if (unlikely(err))
15670+ /* leave the copied-up one */
15671+ goto out_whtmp;
1308ab2a 15672+
4a4d8108
AM
15673+ /* make dir opaque */
15674+ if (au_ftest_ren(a->flags, DIROPQ)) {
15675+ err = au_ren_diropq(a);
15676+ if (unlikely(err))
15677+ goto out_rename;
15678+ }
1308ab2a 15679+
4a4d8108
AM
15680+ /* update target timestamps */
15681+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
15682+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
15683+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
15684+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 15685+
4a4d8108
AM
15686+ /* remove whiteout for dentry */
15687+ if (a->dst_wh_dentry) {
15688+ a->h_path.dentry = a->dst_wh_dentry;
15689+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
15690+ a->dst_dentry);
15691+ if (unlikely(err))
15692+ goto out_diropq;
15693+ }
1facf9fc 15694+
4a4d8108
AM
15695+ /* remove whtmp */
15696+ if (a->thargs)
15697+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 15698+
4a4d8108
AM
15699+ err = 0;
15700+ goto out_success;
15701+
15702+ out_diropq:
15703+ if (au_ftest_ren(a->flags, DIROPQ))
15704+ au_ren_rev_diropq(err, a);
15705+ out_rename:
15706+ if (!au_ftest_ren(a->flags, CPUP))
15707+ au_ren_rev_rename(err, a);
15708+ else
15709+ au_ren_rev_cpup(err, a);
15710+ out_whtmp:
15711+ if (a->thargs)
15712+ au_ren_rev_whtmp(err, a);
15713+ out_whdst:
15714+ dput(a->dst_wh_dentry);
15715+ a->dst_wh_dentry = NULL;
15716+ out_whsrc:
15717+ if (a->src_wh_dentry)
15718+ au_ren_rev_whsrc(err, a);
15719+ au_ren_rev_drop(a);
15720+ out_success:
15721+ dput(a->src_wh_dentry);
15722+ dput(a->dst_wh_dentry);
15723+ out_thargs:
15724+ if (a->thargs) {
15725+ dput(a->h_dst);
15726+ au_whtmp_rmdir_free(a->thargs);
15727+ a->thargs = NULL;
15728+ }
15729+ out:
15730+ return err;
dece6358 15731+}
1facf9fc 15732+
1308ab2a 15733+/* ---------------------------------------------------------------------- */
1facf9fc 15734+
4a4d8108
AM
15735+/*
15736+ * test if @dentry dir can be rename destination or not.
15737+ * success means, it is a logically empty dir.
15738+ */
15739+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 15740+{
4a4d8108 15741+ return au_test_empty(dentry, whlist);
1308ab2a 15742+}
1facf9fc 15743+
4a4d8108
AM
15744+/*
15745+ * test if @dentry dir can be rename source or not.
15746+ * if it can, return 0 and @children is filled.
15747+ * success means,
15748+ * - it is a logically empty dir.
15749+ * - or, it exists on writable branch and has no children including whiteouts
15750+ * on the lower branch.
15751+ */
15752+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
15753+{
15754+ int err;
15755+ unsigned int rdhash;
15756+ aufs_bindex_t bstart;
1facf9fc 15757+
4a4d8108
AM
15758+ bstart = au_dbstart(dentry);
15759+ if (bstart != btgt) {
15760+ struct au_nhash whlist;
dece6358 15761+
4a4d8108
AM
15762+ SiMustAnyLock(dentry->d_sb);
15763+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
15764+ if (!rdhash)
15765+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
15766+ dentry));
15767+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
15768+ if (unlikely(err))
15769+ goto out;
15770+ err = au_test_empty(dentry, &whlist);
15771+ au_nhash_wh_free(&whlist);
15772+ goto out;
15773+ }
dece6358 15774+
4a4d8108
AM
15775+ if (bstart == au_dbtaildir(dentry))
15776+ return 0; /* success */
dece6358 15777+
4a4d8108 15778+ err = au_test_empty_lower(dentry);
1facf9fc 15779+
4a4d8108
AM
15780+ out:
15781+ if (err == -ENOTEMPTY) {
15782+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
15783+ " is not supported\n");
15784+ err = -EXDEV;
15785+ }
15786+ return err;
15787+}
1308ab2a 15788+
4a4d8108
AM
15789+/* side effect: sets whlist and h_dentry */
15790+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 15791+{
4a4d8108
AM
15792+ int err;
15793+ unsigned int rdhash;
15794+ struct dentry *d;
1facf9fc 15795+
4a4d8108
AM
15796+ d = a->dst_dentry;
15797+ SiMustAnyLock(d->d_sb);
1facf9fc 15798+
4a4d8108
AM
15799+ err = 0;
15800+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
15801+ rdhash = au_sbi(d->d_sb)->si_rdhash;
15802+ if (!rdhash)
15803+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
15804+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
15805+ if (unlikely(err))
15806+ goto out;
1308ab2a 15807+
4a4d8108
AM
15808+ au_set_dbstart(d, a->dst_bstart);
15809+ err = may_rename_dstdir(d, &a->whlist);
15810+ au_set_dbstart(d, a->btgt);
15811+ }
15812+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
15813+ if (unlikely(err))
15814+ goto out;
15815+
15816+ d = a->src_dentry;
15817+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
15818+ if (au_ftest_ren(a->flags, ISDIR)) {
15819+ err = may_rename_srcdir(d, a->btgt);
15820+ if (unlikely(err)) {
15821+ au_nhash_wh_free(&a->whlist);
15822+ a->whlist.nh_num = 0;
15823+ }
15824+ }
15825+ out:
15826+ return err;
1facf9fc 15827+}
15828+
4a4d8108 15829+/* ---------------------------------------------------------------------- */
1facf9fc 15830+
4a4d8108
AM
15831+/*
15832+ * simple tests for rename.
15833+ * following the checks in vfs, plus the parent-child relationship.
15834+ */
15835+static int au_may_ren(struct au_ren_args *a)
15836+{
15837+ int err, isdir;
15838+ struct inode *h_inode;
1facf9fc 15839+
4a4d8108
AM
15840+ if (a->src_bstart == a->btgt) {
15841+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
15842+ au_ftest_ren(a->flags, ISDIR));
15843+ if (unlikely(err))
15844+ goto out;
15845+ err = -EINVAL;
15846+ if (unlikely(a->src_h_dentry == a->h_trap))
15847+ goto out;
15848+ }
1facf9fc 15849+
4a4d8108
AM
15850+ err = 0;
15851+ if (a->dst_bstart != a->btgt)
15852+ goto out;
1facf9fc 15853+
4a4d8108
AM
15854+ err = -EIO;
15855+ h_inode = a->dst_h_dentry->d_inode;
15856+ isdir = !!au_ftest_ren(a->flags, ISDIR);
15857+ if (!a->dst_dentry->d_inode) {
15858+ if (unlikely(h_inode))
15859+ goto out;
15860+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
15861+ isdir);
15862+ } else {
15863+ if (unlikely(!h_inode || !h_inode->i_nlink))
15864+ goto out;
15865+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
15866+ isdir);
15867+ if (unlikely(err))
15868+ goto out;
15869+ err = -ENOTEMPTY;
15870+ if (unlikely(a->dst_h_dentry == a->h_trap))
15871+ goto out;
15872+ err = 0;
15873+ }
1facf9fc 15874+
4a4d8108
AM
15875+ out:
15876+ if (unlikely(err == -ENOENT || err == -EEXIST))
15877+ err = -EIO;
15878+ AuTraceErr(err);
15879+ return err;
15880+}
1facf9fc 15881+
1308ab2a 15882+/* ---------------------------------------------------------------------- */
1facf9fc 15883+
4a4d8108
AM
15884+/*
15885+ * locking order
15886+ * (VFS)
15887+ * - src_dir and dir by lock_rename()
15888+ * - inode if exitsts
15889+ * (aufs)
15890+ * - lock all
15891+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
15892+ * + si_read_lock
15893+ * + di_write_lock2_child()
15894+ * + di_write_lock_child()
15895+ * + ii_write_lock_child()
15896+ * + di_write_lock_child2()
15897+ * + ii_write_lock_child2()
15898+ * + src_parent and parent
15899+ * + di_write_lock_parent()
15900+ * + ii_write_lock_parent()
15901+ * + di_write_lock_parent2()
15902+ * + ii_write_lock_parent2()
15903+ * + lower src_dir and dir by vfsub_lock_rename()
15904+ * + verify the every relationships between child and parent. if any
15905+ * of them failed, unlock all and return -EBUSY.
15906+ */
15907+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 15908+{
4a4d8108
AM
15909+ struct super_block *sb;
15910+
15911+ sb = a->dst_dentry->d_sb;
15912+ if (au_ftest_ren(a->flags, MNT_WRITE))
15913+ mnt_drop_write(a->br->br_mnt);
15914+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
15915+ a->dst_h_parent, a->dst_hdir);
1308ab2a 15916+}
15917+
4a4d8108 15918+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 15919+{
4a4d8108
AM
15920+ int err;
15921+ unsigned int udba;
1308ab2a 15922+
4a4d8108
AM
15923+ err = 0;
15924+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
15925+ a->src_hdir = au_hi(a->src_dir, a->btgt);
15926+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
15927+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
15928+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
15929+ a->dst_h_parent, a->dst_hdir);
15930+ udba = au_opt_udba(a->src_dentry->d_sb);
15931+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
15932+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
15933+ err = au_busy_or_stale();
15934+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
15935+ err = au_h_verify(a->src_h_dentry, udba,
15936+ a->src_h_parent->d_inode, a->src_h_parent,
15937+ a->br);
15938+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
15939+ err = au_h_verify(a->dst_h_dentry, udba,
15940+ a->dst_h_parent->d_inode, a->dst_h_parent,
15941+ a->br);
15942+ if (!err) {
15943+ err = mnt_want_write(a->br->br_mnt);
15944+ if (unlikely(err))
15945+ goto out_unlock;
15946+ au_fset_ren(a->flags, MNT_WRITE);
15947+ goto out; /* success */
15948+ }
15949+
15950+ err = au_busy_or_stale();
15951+
15952+ out_unlock:
15953+ au_ren_unlock(a);
15954+ out:
15955+ return err;
1facf9fc 15956+}
15957+
15958+/* ---------------------------------------------------------------------- */
15959+
4a4d8108 15960+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 15961+{
4a4d8108 15962+ struct inode *dir;
dece6358 15963+
4a4d8108
AM
15964+ dir = a->dst_dir;
15965+ dir->i_version++;
15966+ if (au_ftest_ren(a->flags, ISDIR)) {
15967+ /* is this updating defined in POSIX? */
15968+ au_cpup_attr_timesizes(a->src_inode);
15969+ au_cpup_attr_nlink(dir, /*force*/1);
15970+ if (a->dst_inode) {
15971+ clear_nlink(a->dst_inode);
15972+ au_cpup_attr_timesizes(a->dst_inode);
15973+ }
15974+ }
15975+ if (au_ibstart(dir) == a->btgt)
15976+ au_cpup_attr_timesizes(dir);
dece6358 15977+
4a4d8108
AM
15978+ if (au_ftest_ren(a->flags, ISSAMEDIR))
15979+ return;
dece6358 15980+
4a4d8108
AM
15981+ dir = a->src_dir;
15982+ dir->i_version++;
15983+ if (au_ftest_ren(a->flags, ISDIR))
15984+ au_cpup_attr_nlink(dir, /*force*/1);
15985+ if (au_ibstart(dir) == a->btgt)
15986+ au_cpup_attr_timesizes(dir);
1facf9fc 15987+}
15988+
4a4d8108 15989+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 15990+{
4a4d8108
AM
15991+ aufs_bindex_t bend, bindex;
15992+ struct dentry *d, *h_d;
15993+ struct inode *i, *h_i;
15994+ struct super_block *sb;
dece6358 15995+
4a4d8108
AM
15996+ d = a->src_dentry;
15997+ au_set_dbwh(d, -1);
15998+ bend = au_dbend(d);
15999+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
16000+ h_d = au_h_dptr(d, bindex);
16001+ if (h_d)
16002+ au_set_h_dptr(d, bindex, NULL);
16003+ }
16004+ au_set_dbend(d, a->btgt);
16005+
16006+ sb = d->d_sb;
16007+ i = a->src_inode;
16008+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
16009+ return; /* success */
16010+
16011+ bend = au_ibend(i);
16012+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
16013+ h_i = au_h_iptr(i, bindex);
16014+ if (h_i) {
16015+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
16016+ /* ignore this error */
16017+ au_set_h_iptr(i, bindex, NULL, 0);
16018+ }
16019+ }
16020+ au_set_ibend(i, a->btgt);
1308ab2a 16021+}
dece6358 16022+
4a4d8108
AM
16023+/* ---------------------------------------------------------------------- */
16024+
16025+/* mainly for link(2) and rename(2) */
16026+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 16027+{
4a4d8108
AM
16028+ aufs_bindex_t bdiropq, bwh;
16029+ struct dentry *parent;
16030+ struct au_branch *br;
16031+
16032+ parent = dentry->d_parent;
16033+ IMustLock(parent->d_inode); /* dir is locked */
16034+
16035+ bdiropq = au_dbdiropq(parent);
16036+ bwh = au_dbwh(dentry);
16037+ br = au_sbr(dentry->d_sb, btgt);
16038+ if (au_br_rdonly(br)
16039+ || (0 <= bdiropq && bdiropq < btgt)
16040+ || (0 <= bwh && bwh < btgt))
16041+ btgt = -1;
16042+
16043+ AuDbg("btgt %d\n", btgt);
16044+ return btgt;
1facf9fc 16045+}
16046+
4a4d8108
AM
16047+/* sets src_bstart, dst_bstart and btgt */
16048+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 16049+{
4a4d8108
AM
16050+ int err;
16051+ struct au_wr_dir_args wr_dir_args = {
16052+ /* .force_btgt = -1, */
16053+ .flags = AuWrDir_ADD_ENTRY
16054+ };
dece6358 16055+
4a4d8108
AM
16056+ a->src_bstart = au_dbstart(a->src_dentry);
16057+ a->dst_bstart = au_dbstart(a->dst_dentry);
16058+ if (au_ftest_ren(a->flags, ISDIR))
16059+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16060+ wr_dir_args.force_btgt = a->src_bstart;
16061+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
16062+ wr_dir_args.force_btgt = a->dst_bstart;
16063+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
16064+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
16065+ a->btgt = err;
dece6358 16066+
4a4d8108 16067+ return err;
1facf9fc 16068+}
16069+
4a4d8108 16070+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 16071+{
4a4d8108
AM
16072+ a->h_path.dentry = a->src_h_parent;
16073+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
16074+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
16075+ a->h_path.dentry = a->dst_h_parent;
16076+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
16077+ }
1facf9fc 16078+
4a4d8108
AM
16079+ au_fclr_ren(a->flags, DT_DSTDIR);
16080+ if (!au_ftest_ren(a->flags, ISDIR))
16081+ return;
dece6358 16082+
4a4d8108
AM
16083+ a->h_path.dentry = a->src_h_dentry;
16084+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
16085+ if (a->dst_h_dentry->d_inode) {
16086+ au_fset_ren(a->flags, DT_DSTDIR);
16087+ a->h_path.dentry = a->dst_h_dentry;
16088+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
16089+ }
1308ab2a 16090+}
dece6358 16091+
4a4d8108 16092+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 16093+{
4a4d8108
AM
16094+ struct dentry *h_d;
16095+ struct mutex *h_mtx;
16096+
16097+ au_dtime_revert(a->src_dt + AuPARENT);
16098+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
16099+ au_dtime_revert(a->dst_dt + AuPARENT);
16100+
16101+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
16102+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
16103+ h_mtx = &h_d->d_inode->i_mutex;
16104+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16105+ au_dtime_revert(a->src_dt + AuCHILD);
16106+ mutex_unlock(h_mtx);
16107+
16108+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
16109+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
16110+ h_mtx = &h_d->d_inode->i_mutex;
16111+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16112+ au_dtime_revert(a->dst_dt + AuCHILD);
16113+ mutex_unlock(h_mtx);
1facf9fc 16114+ }
16115+ }
16116+}
16117+
4a4d8108
AM
16118+/* ---------------------------------------------------------------------- */
16119+
16120+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
16121+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 16122+{
4a4d8108
AM
16123+ int err;
16124+ /* reduce stack space */
16125+ struct au_ren_args *a;
16126+
16127+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
16128+ IMustLock(_src_dir);
16129+ IMustLock(_dst_dir);
16130+
16131+ err = -ENOMEM;
16132+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
16133+ a = kzalloc(sizeof(*a), GFP_NOFS);
16134+ if (unlikely(!a))
16135+ goto out;
16136+
16137+ a->src_dir = _src_dir;
16138+ a->src_dentry = _src_dentry;
16139+ a->src_inode = a->src_dentry->d_inode;
16140+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
16141+ a->dst_dir = _dst_dir;
16142+ a->dst_dentry = _dst_dentry;
16143+ a->dst_inode = a->dst_dentry->d_inode;
16144+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
16145+ if (a->dst_inode) {
16146+ IMustLock(a->dst_inode);
16147+ au_igrab(a->dst_inode);
1facf9fc 16148+ }
1facf9fc 16149+
4a4d8108
AM
16150+ err = -ENOTDIR;
16151+ if (S_ISDIR(a->src_inode->i_mode)) {
16152+ au_fset_ren(a->flags, ISDIR);
16153+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
16154+ goto out_free;
16155+ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16156+ AuLock_DIR | AuLock_FLUSH);
16157+ } else
16158+ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16159+ AuLock_FLUSH);
1facf9fc 16160+
4a4d8108
AM
16161+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
16162+ di_write_lock_parent(a->dst_parent);
1facf9fc 16163+
4a4d8108
AM
16164+ /* which branch we process */
16165+ err = au_ren_wbr(a);
16166+ if (unlikely(err < 0))
16167+ goto out_unlock;
16168+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
16169+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 16170+
4a4d8108
AM
16171+ /* are they available to be renamed */
16172+ err = au_ren_may_dir(a);
16173+ if (unlikely(err))
16174+ goto out_children;
1facf9fc 16175+
4a4d8108
AM
16176+ /* prepare the writable parent dir on the same branch */
16177+ if (a->dst_bstart == a->btgt) {
16178+ au_fset_ren(a->flags, WHDST);
16179+ } else {
16180+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
16181+ if (unlikely(err))
16182+ goto out_children;
16183+ }
1facf9fc 16184+
4a4d8108
AM
16185+ if (a->src_dir != a->dst_dir) {
16186+ /*
16187+ * this temporary unlock is safe,
16188+ * because both dir->i_mutex are locked.
16189+ */
16190+ di_write_unlock(a->dst_parent);
16191+ di_write_lock_parent(a->src_parent);
16192+ err = au_wr_dir_need_wh(a->src_dentry,
16193+ au_ftest_ren(a->flags, ISDIR),
16194+ &a->btgt);
16195+ di_write_unlock(a->src_parent);
16196+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
16197+ au_fclr_ren(a->flags, ISSAMEDIR);
16198+ } else
16199+ err = au_wr_dir_need_wh(a->src_dentry,
16200+ au_ftest_ren(a->flags, ISDIR),
16201+ &a->btgt);
16202+ if (unlikely(err < 0))
16203+ goto out_children;
16204+ if (err)
16205+ au_fset_ren(a->flags, WHSRC);
1facf9fc 16206+
4a4d8108
AM
16207+ /* lock them all */
16208+ err = au_ren_lock(a);
16209+ if (unlikely(err))
16210+ goto out_children;
1facf9fc 16211+
4a4d8108
AM
16212+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
16213+ err = au_may_ren(a);
16214+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
16215+ err = -ENAMETOOLONG;
16216+ if (unlikely(err))
16217+ goto out_hdir;
1facf9fc 16218+
4a4d8108
AM
16219+ /* store timestamps to be revertible */
16220+ au_ren_dt(a);
1facf9fc 16221+
4a4d8108
AM
16222+ /* here we go */
16223+ err = do_rename(a);
16224+ if (unlikely(err))
16225+ goto out_dt;
16226+
16227+ /* update dir attributes */
16228+ au_ren_refresh_dir(a);
16229+
16230+ /* dput/iput all lower dentries */
16231+ au_ren_refresh(a);
16232+
16233+ goto out_hdir; /* success */
16234+
16235+ out_dt:
16236+ au_ren_rev_dt(err, a);
16237+ out_hdir:
16238+ au_ren_unlock(a);
16239+ out_children:
16240+ au_nhash_wh_free(&a->whlist);
16241+ out_unlock:
16242+ if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
16243+ au_update_dbstart(a->dst_dentry);
16244+ d_drop(a->dst_dentry);
16245+ }
16246+ if (!err)
16247+ d_move(a->src_dentry, a->dst_dentry);
16248+ if (au_ftest_ren(a->flags, ISSAMEDIR))
16249+ di_write_unlock(a->dst_parent);
16250+ else
16251+ di_write_unlock2(a->src_parent, a->dst_parent);
16252+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
16253+ out_free:
16254+ iput(a->dst_inode);
16255+ if (a->thargs)
16256+ au_whtmp_rmdir_free(a->thargs);
16257+ kfree(a);
16258+ out:
16259+ AuTraceErr(err);
16260+ return err;
1308ab2a 16261+}
b752ccd1
AM
16262diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
16263--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
16264+++ linux/fs/aufs/Kconfig 2010-08-21 21:00:02.972333781 +0200
4a4d8108
AM
16265@@ -0,0 +1,175 @@
16266+config AUFS_FS
16267+ tristate "Aufs (Advanced multi layered unification filesystem) support"
16268+ depends on EXPERIMENTAL
16269+ help
16270+ Aufs is a stackable unification filesystem such as Unionfs,
16271+ which unifies several directories and provides a merged single
16272+ directory.
16273+ In the early days, aufs was entirely re-designed and
16274+ re-implemented Unionfs Version 1.x series. Introducing many
16275+ original ideas, approaches and improvements, it becomes totally
16276+ different from Unionfs while keeping the basic features.
1facf9fc 16277+
4a4d8108
AM
16278+if AUFS_FS
16279+choice
16280+ prompt "Maximum number of branches"
16281+ default AUFS_BRANCH_MAX_127
16282+ help
16283+ Specifies the maximum number of branches (or member directories)
16284+ in a single aufs. The larger value consumes more system
16285+ resources and has a minor impact to performance.
16286+config AUFS_BRANCH_MAX_127
16287+ bool "127"
16288+ help
16289+ Specifies the maximum number of branches (or member directories)
16290+ in a single aufs. The larger value consumes more system
16291+ resources and has a minor impact to performance.
16292+config AUFS_BRANCH_MAX_511
16293+ bool "511"
16294+ help
16295+ Specifies the maximum number of branches (or member directories)
16296+ in a single aufs. The larger value consumes more system
16297+ resources and has a minor impact to performance.
16298+config AUFS_BRANCH_MAX_1023
16299+ bool "1023"
16300+ help
16301+ Specifies the maximum number of branches (or member directories)
16302+ in a single aufs. The larger value consumes more system
16303+ resources and has a minor impact to performance.
16304+config AUFS_BRANCH_MAX_32767
16305+ bool "32767"
16306+ help
16307+ Specifies the maximum number of branches (or member directories)
16308+ in a single aufs. The larger value consumes more system
16309+ resources and has a minor impact to performance.
16310+endchoice
1facf9fc 16311+
4a4d8108
AM
16312+config AUFS_HNOTIFY
16313+ bool "Detect direct branch access (bypassing aufs)"
16314+ help
16315+ If you want to modify files on branches directly, eg. bypassing aufs,
16316+ and want aufs to detect the changes of them fully, then enable this
16317+ option and use 'udba=notify' mount option.
16318+ It will have a negative impact to the performance.
16319+ See detail in aufs.5.
dece6358 16320+
dece6358 16321+
4a4d8108
AM
16322+choice
16323+ prompt "method" if AUFS_HNOTIFY
16324+ default AUFS_HFSNOTIFY
16325+config AUFS_HFSNOTIFY
16326+ bool "fsnotify"
16327+ select FSNOTIFY
16328+config AUFS_HINOTIFY
16329+ bool "inotify (DEPRECATED)"
16330+ depends on INOTIFY
16331+endchoice
1facf9fc 16332+
4a4d8108
AM
16333+config AUFS_EXPORT
16334+ bool "NFS-exportable aufs"
16335+ depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
16336+ help
16337+ If you want to export your mounted aufs via NFS, then enable this
16338+ option. There are several requirements for this configuration.
16339+ See detail in aufs.5.
1facf9fc 16340+
4a4d8108
AM
16341+config AUFS_INO_T_64
16342+ bool
16343+ depends on AUFS_EXPORT
16344+ depends on 64BIT && !(ALPHA || S390)
16345+ default y
16346+ help
16347+ Automatic configuration for internal use.
16348+ /* typedef unsigned long/int __kernel_ino_t */
16349+ /* alpha and s390x are int */
1facf9fc 16350+
4a4d8108
AM
16351+config AUFS_RDU
16352+ bool "Readdir in userspace"
16353+ help
16354+ Aufs has two methods to provide a merged view for a directory,
16355+ by a user-space library and by kernel-space natively. The latter
16356+ is always enabled but sometimes large and slow.
16357+ If you enable this option, install the library in aufs2-util
16358+ package, and set some environment variables for your readdir(3),
16359+ then the work will be handled in user-space which generally
16360+ shows better performance in most cases.
16361+ See detail in aufs.5.
1facf9fc 16362+
4a4d8108
AM
16363+config AUFS_SP_IATTR
16364+ bool "Respect the attributes (mtime/ctime mainly) of special files"
16365+ help
16366+ When you write something to a special file, some attributes of it
16367+ (mtime/ctime mainly) may be updated. Generally such updates are
16368+ less important (actually some device drivers and NFS ignore
16369+ it). But some applications (such like test program) requires
16370+ such updates. If you need these updates, then enable this
16371+ configuration which introduces some overhead.
16372+ Currently this configuration handles FIFO only.
1facf9fc 16373+
4a4d8108
AM
16374+config AUFS_SHWH
16375+ bool "Show whiteouts"
16376+ help
16377+ If you want to make the whiteouts in aufs visible, then enable
16378+ this option and specify 'shwh' mount option. Although it may
16379+ sounds like philosophy or something, but in technically it
16380+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 16381+
4a4d8108
AM
16382+config AUFS_BR_RAMFS
16383+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
16384+ help
16385+ If you want to use ramfs as an aufs branch fs, then enable this
16386+ option. Generally tmpfs is recommended.
16387+ Aufs prohibited them to be a branch fs by default, because
16388+ initramfs becomes unusable after switch_root or something
16389+ generally. If you sets initramfs as an aufs branch and boot your
16390+ system by switch_root, you will meet a problem easily since the
16391+ files in initramfs may be inaccessible.
16392+ Unless you are going to use ramfs as an aufs branch fs without
16393+ switch_root or something, leave it N.
1facf9fc 16394+
4a4d8108
AM
16395+config AUFS_BR_FUSE
16396+ bool "Fuse fs as an aufs branch"
16397+ depends on FUSE_FS
16398+ select AUFS_POLL
16399+ help
16400+ If you want to use fuse-based userspace filesystem as an aufs
16401+ branch fs, then enable this option.
16402+ It implements the internal poll(2) operation which is
16403+ implemented by fuse only (curretnly).
1facf9fc 16404+
4a4d8108
AM
16405+config AUFS_POLL
16406+ bool
16407+ help
16408+ Automatic configuration for internal use.
1facf9fc 16409+
4a4d8108
AM
16410+config AUFS_BR_HFSPLUS
16411+ bool "Hfsplus as an aufs branch"
16412+ depends on HFSPLUS_FS
16413+ default y
16414+ help
16415+ If you want to use hfsplus fs as an aufs branch fs, then enable
16416+ this option. This option introduces a small overhead at
16417+ copying-up a file on hfsplus.
1facf9fc 16418+
4a4d8108
AM
16419+config AUFS_BDEV_LOOP
16420+ bool
16421+ depends on BLK_DEV_LOOP
16422+ default y
16423+ help
16424+ Automatic configuration for internal use.
16425+ Convert =[ym] into =y.
1308ab2a 16426+
4a4d8108
AM
16427+config AUFS_DEBUG
16428+ bool "Debug aufs"
16429+ help
16430+ Enable this to compile aufs internal debug code.
16431+ It will have a negative impact to the performance.
16432+
16433+config AUFS_MAGIC_SYSRQ
16434+ bool
16435+ depends on AUFS_DEBUG && MAGIC_SYSRQ
16436+ default y
16437+ help
16438+ Automatic configuration for internal use.
16439+ When aufs supports Magic SysRq, enabled automatically.
16440+endif
b752ccd1
AM
16441diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
16442--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
16443+++ linux/fs/aufs/loop.c 2010-08-21 21:00:02.980020464 +0200
16444@@ -0,0 +1,63 @@
1facf9fc 16445+/*
4a4d8108 16446+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16447+ *
16448+ * This program, aufs is free software; you can redistribute it and/or modify
16449+ * it under the terms of the GNU General Public License as published by
16450+ * the Free Software Foundation; either version 2 of the License, or
16451+ * (at your option) any later version.
dece6358
AM
16452+ *
16453+ * This program is distributed in the hope that it will be useful,
16454+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16455+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16456+ * GNU General Public License for more details.
16457+ *
16458+ * You should have received a copy of the GNU General Public License
16459+ * along with this program; if not, write to the Free Software
16460+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16461+ */
16462+
16463+/*
16464+ * support for loopback block device as a branch
16465+ */
16466+
16467+#include <linux/loop.h>
16468+#include "aufs.h"
16469+
16470+/*
16471+ * test if two lower dentries have overlapping branches.
16472+ */
b752ccd1 16473+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 16474+{
b752ccd1 16475+ struct super_block *h_sb;
1facf9fc 16476+ struct loop_device *l;
16477+
b752ccd1
AM
16478+ h_sb = h_adding->d_sb;
16479+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 16480+ return 0;
16481+
b752ccd1
AM
16482+ l = h_sb->s_bdev->bd_disk->private_data;
16483+ h_adding = l->lo_backing_file->f_dentry;
16484+ /*
16485+ * h_adding can be local NFS.
16486+ * in this case aufs cannot detect the loop.
16487+ */
16488+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 16489+ return 1;
b752ccd1 16490+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 16491+}
16492+
16493+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
16494+int au_test_loopback_kthread(void)
16495+{
b752ccd1
AM
16496+ int ret;
16497+ struct task_struct *tsk = current;
16498+
16499+ ret = 0;
16500+ if (tsk->flags & PF_KTHREAD) {
16501+ const char c = tsk->comm[4];
16502+ ret = ('0' <= c && c <= '9'
16503+ && !strncmp(tsk->comm, "loop", 4));
16504+ }
1facf9fc 16505+
b752ccd1 16506+ return ret;
1facf9fc 16507+}
b752ccd1
AM
16508diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
16509--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
16510+++ linux/fs/aufs/loop.h 2010-08-21 21:00:02.980020464 +0200
16511@@ -0,0 +1,42 @@
1facf9fc 16512+/*
4a4d8108 16513+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16514+ *
16515+ * This program, aufs is free software; you can redistribute it and/or modify
16516+ * it under the terms of the GNU General Public License as published by
16517+ * the Free Software Foundation; either version 2 of the License, or
16518+ * (at your option) any later version.
dece6358
AM
16519+ *
16520+ * This program is distributed in the hope that it will be useful,
16521+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16522+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16523+ * GNU General Public License for more details.
16524+ *
16525+ * You should have received a copy of the GNU General Public License
16526+ * along with this program; if not, write to the Free Software
16527+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16528+ */
16529+
16530+/*
16531+ * support for loopback mount as a branch
16532+ */
16533+
16534+#ifndef __AUFS_LOOP_H__
16535+#define __AUFS_LOOP_H__
16536+
16537+#ifdef __KERNEL__
16538+
dece6358
AM
16539+struct dentry;
16540+struct super_block;
1facf9fc 16541+
16542+#ifdef CONFIG_AUFS_BDEV_LOOP
16543+/* loop.c */
b752ccd1 16544+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 16545+int au_test_loopback_kthread(void);
16546+#else
4a4d8108 16547+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 16548+ struct dentry *h_adding)
4a4d8108 16549+AuStubInt0(au_test_loopback_kthread, void)
1facf9fc 16550+#endif /* BLK_DEV_LOOP */
16551+
16552+#endif /* __KERNEL__ */
16553+#endif /* __AUFS_LOOP_H__ */
b752ccd1
AM
16554diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
16555--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
16556+++ linux/fs/aufs/magic.mk 2010-08-21 21:00:02.982333916 +0200
4a4d8108 16557@@ -0,0 +1,54 @@
1facf9fc 16558+
16559+# defined in ${srctree}/fs/fuse/inode.c
16560+# tristate
16561+ifdef CONFIG_FUSE_FS
16562+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
16563+endif
16564+
16565+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
16566+# tristate
16567+ifdef CONFIG_OCFS2_FS
16568+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
16569+endif
16570+
16571+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
16572+# tristate
16573+ifdef CONFIG_OCFS2_FS_O2CB
16574+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
16575+endif
16576+
1facf9fc 16577+# defined in ${srctree}/fs/cifs/cifsfs.c
16578+# tristate
16579+ifdef CONFIG_CIFS_FS
16580+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
16581+endif
16582+
16583+# defined in ${srctree}/fs/xfs/xfs_sb.h
16584+# tristate
16585+ifdef CONFIG_XFS_FS
16586+ccflags-y += -DXFS_SB_MAGIC=0x58465342
16587+endif
16588+
16589+# defined in ${srctree}/fs/configfs/mount.c
16590+# tristate
16591+ifdef CONFIG_CONFIGFS_FS
16592+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
16593+endif
16594+
16595+# defined in ${srctree}/fs/9p/v9fs.h
16596+# tristate
16597+ifdef CONFIG_9P_FS
16598+ccflags-y += -DV9FS_MAGIC=0x01021997
16599+endif
16600+
16601+# defined in ${srctree}/fs/ubifs/ubifs.h
16602+# tristate
16603+ifdef CONFIG_UBIFS_FS
16604+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
16605+endif
4a4d8108
AM
16606+
16607+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
16608+# tristate
16609+ifdef CONFIG_HFSPLUS_FS
16610+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
16611+endif
b752ccd1
AM
16612diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
16613--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
16614+++ linux/fs/aufs/Makefile 2010-08-21 21:00:02.972333781 +0200
4a4d8108
AM
16615@@ -0,0 +1,38 @@
16616+
16617+include ${src}/magic.mk
16618+ifeq (${CONFIG_AUFS_FS},m)
16619+include ${src}/conf.mk
16620+endif
16621+-include ${src}/priv_def.mk
16622+
16623+# cf. include/linux/kernel.h
16624+# enable pr_debug
16625+ccflags-y += -DDEBUG
16626+ccflags-y += -D'pr_fmt(fmt)="aufs %s:%d:%s[%d]: " fmt, \
16627+ __func__, __LINE__, current->comm, current->pid'
16628+
16629+obj-$(CONFIG_AUFS_FS) += aufs.o
16630+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
16631+ wkq.o vfsub.o dcsub.o \
16632+ cpup.o whout.o plink.o wbr_policy.o \
16633+ dinfo.o dentry.o \
16634+ dynop.o \
16635+ finfo.o file.o f_op.o \
16636+ dir.o vdir.o \
16637+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
16638+ ioctl.o
16639+
16640+# all are boolean
16641+aufs-$(CONFIG_SYSFS) += sysfs.o
16642+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
16643+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
16644+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
16645+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
16646+aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
16647+aufs-$(CONFIG_AUFS_EXPORT) += export.o
16648+aufs-$(CONFIG_AUFS_POLL) += poll.o
16649+aufs-$(CONFIG_AUFS_RDU) += rdu.o
16650+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
16651+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
16652+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
16653+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
b752ccd1
AM
16654diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
16655--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
16656+++ linux/fs/aufs/module.c 2010-08-21 21:00:02.982333916 +0200
4a4d8108 16657@@ -0,0 +1,171 @@
1facf9fc 16658+/*
4a4d8108 16659+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16660+ *
16661+ * This program, aufs is free software; you can redistribute it and/or modify
16662+ * it under the terms of the GNU General Public License as published by
16663+ * the Free Software Foundation; either version 2 of the License, or
16664+ * (at your option) any later version.
dece6358
AM
16665+ *
16666+ * This program is distributed in the hope that it will be useful,
16667+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16668+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16669+ * GNU General Public License for more details.
16670+ *
16671+ * You should have received a copy of the GNU General Public License
16672+ * along with this program; if not, write to the Free Software
16673+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16674+ */
16675+
16676+/*
16677+ * module global variables and operations
16678+ */
16679+
16680+#include <linux/module.h>
16681+#include <linux/seq_file.h>
16682+#include "aufs.h"
16683+
16684+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
16685+{
16686+ if (new_sz <= nused)
16687+ return p;
16688+
16689+ p = krealloc(p, new_sz, gfp);
16690+ if (p)
16691+ memset(p + nused, 0, new_sz - nused);
16692+ return p;
16693+}
16694+
16695+/* ---------------------------------------------------------------------- */
16696+
16697+/*
16698+ * aufs caches
16699+ */
16700+struct kmem_cache *au_cachep[AuCache_Last];
16701+static int __init au_cache_init(void)
16702+{
4a4d8108 16703+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 16704+ if (au_cachep[AuCache_DINFO])
4a4d8108
AM
16705+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
16706+ au_icntnr_init_once);
1facf9fc 16707+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
16708+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
16709+ au_fi_init_once);
1facf9fc 16710+ if (au_cachep[AuCache_FINFO])
16711+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
16712+ if (au_cachep[AuCache_VDIR])
16713+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
16714+ if (au_cachep[AuCache_DEHSTR])
16715+ return 0;
16716+
16717+ return -ENOMEM;
16718+}
16719+
16720+static void au_cache_fin(void)
16721+{
16722+ int i;
4a4d8108
AM
16723+
16724+ /* including AuCache_HNOTIFY */
1facf9fc 16725+ for (i = 0; i < AuCache_Last; i++)
16726+ if (au_cachep[i]) {
16727+ kmem_cache_destroy(au_cachep[i]);
16728+ au_cachep[i] = NULL;
16729+ }
16730+}
16731+
16732+/* ---------------------------------------------------------------------- */
16733+
16734+int au_dir_roflags;
16735+
16736+/*
16737+ * functions for module interface.
16738+ */
16739+MODULE_LICENSE("GPL");
16740+/* MODULE_LICENSE("GPL v2"); */
dece6358 16741+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 16742+MODULE_DESCRIPTION(AUFS_NAME
16743+ " -- Advanced multi layered unification filesystem");
16744+MODULE_VERSION(AUFS_VERSION);
16745+
1facf9fc 16746+/* this module parameter has no meaning when SYSFS is disabled */
16747+int sysaufs_brs = 1;
16748+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
16749+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
16750+
16751+/* ---------------------------------------------------------------------- */
16752+
16753+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
16754+
16755+int au_seq_path(struct seq_file *seq, struct path *path)
16756+{
16757+ return seq_path(seq, path, au_esc_chars);
16758+}
16759+
16760+/* ---------------------------------------------------------------------- */
16761+
16762+static int __init aufs_init(void)
16763+{
16764+ int err, i;
16765+ char *p;
16766+
16767+ p = au_esc_chars;
16768+ for (i = 1; i <= ' '; i++)
16769+ *p++ = i;
16770+ *p++ = '\\';
16771+ *p++ = '\x7f';
16772+ *p = 0;
16773+
16774+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
16775+
16776+ sysaufs_brs_init();
16777+ au_debug_init();
4a4d8108 16778+ au_dy_init();
1facf9fc 16779+ err = sysaufs_init();
16780+ if (unlikely(err))
16781+ goto out;
16782+ err = au_wkq_init();
16783+ if (unlikely(err))
16784+ goto out_sysaufs;
4a4d8108 16785+ err = au_hnotify_init();
1facf9fc 16786+ if (unlikely(err))
16787+ goto out_wkq;
16788+ err = au_sysrq_init();
16789+ if (unlikely(err))
16790+ goto out_hin;
16791+ err = au_cache_init();
16792+ if (unlikely(err))
16793+ goto out_sysrq;
16794+ err = register_filesystem(&aufs_fs_type);
16795+ if (unlikely(err))
16796+ goto out_cache;
4a4d8108
AM
16797+ /* since we define pr_fmt, call printk directly */
16798+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 16799+ goto out; /* success */
16800+
16801+ out_cache:
16802+ au_cache_fin();
16803+ out_sysrq:
16804+ au_sysrq_fin();
16805+ out_hin:
4a4d8108 16806+ au_hnotify_fin();
1facf9fc 16807+ out_wkq:
16808+ au_wkq_fin();
16809+ out_sysaufs:
16810+ sysaufs_fin();
4a4d8108 16811+ au_dy_fin();
1facf9fc 16812+ out:
16813+ return err;
16814+}
16815+
16816+static void __exit aufs_exit(void)
16817+{
16818+ unregister_filesystem(&aufs_fs_type);
16819+ au_cache_fin();
16820+ au_sysrq_fin();
4a4d8108 16821+ au_hnotify_fin();
1facf9fc 16822+ au_wkq_fin();
16823+ sysaufs_fin();
4a4d8108 16824+ au_dy_fin();
1facf9fc 16825+}
16826+
16827+module_init(aufs_init);
16828+module_exit(aufs_exit);
b752ccd1
AM
16829diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
16830--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
16831+++ linux/fs/aufs/module.h 2010-08-21 21:00:02.982333916 +0200
4a4d8108 16832@@ -0,0 +1,82 @@
1facf9fc 16833+/*
4a4d8108 16834+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16835+ *
16836+ * This program, aufs is free software; you can redistribute it and/or modify
16837+ * it under the terms of the GNU General Public License as published by
16838+ * the Free Software Foundation; either version 2 of the License, or
16839+ * (at your option) any later version.
dece6358
AM
16840+ *
16841+ * This program is distributed in the hope that it will be useful,
16842+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16843+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16844+ * GNU General Public License for more details.
16845+ *
16846+ * You should have received a copy of the GNU General Public License
16847+ * along with this program; if not, write to the Free Software
16848+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16849+ */
16850+
16851+/*
16852+ * module initialization and module-global
16853+ */
16854+
16855+#ifndef __AUFS_MODULE_H__
16856+#define __AUFS_MODULE_H__
16857+
16858+#ifdef __KERNEL__
16859+
16860+#include <linux/slab.h>
16861+
dece6358
AM
16862+struct path;
16863+struct seq_file;
16864+
1facf9fc 16865+/* module parameters */
1facf9fc 16866+extern int sysaufs_brs;
16867+
16868+/* ---------------------------------------------------------------------- */
16869+
16870+extern int au_dir_roflags;
16871+
16872+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
16873+int au_seq_path(struct seq_file *seq, struct path *path);
16874+
16875+/* ---------------------------------------------------------------------- */
16876+
16877+/* kmem cache */
16878+enum {
16879+ AuCache_DINFO,
16880+ AuCache_ICNTNR,
16881+ AuCache_FINFO,
16882+ AuCache_VDIR,
16883+ AuCache_DEHSTR,
4a4d8108
AM
16884+#ifdef CONFIG_AUFS_HNOTIFY
16885+ AuCache_HNOTIFY,
1facf9fc 16886+#endif
16887+ AuCache_Last
16888+};
16889+
4a4d8108
AM
16890+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
16891+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
16892+#define AuCacheCtor(type, ctor) \
16893+ kmem_cache_create(#type, sizeof(struct type), \
16894+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 16895+
16896+extern struct kmem_cache *au_cachep[];
16897+
16898+#define AuCacheFuncs(name, index) \
4a4d8108 16899+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 16900+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 16901+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 16902+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
16903+
16904+AuCacheFuncs(dinfo, DINFO);
16905+AuCacheFuncs(icntnr, ICNTNR);
16906+AuCacheFuncs(finfo, FINFO);
16907+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
16908+AuCacheFuncs(vdir_dehstr, DEHSTR);
16909+#ifdef CONFIG_AUFS_HNOTIFY
16910+AuCacheFuncs(hnotify, HNOTIFY);
16911+#endif
1facf9fc 16912+
4a4d8108
AM
16913+#endif /* __KERNEL__ */
16914+#endif /* __AUFS_MODULE_H__ */
b752ccd1
AM
16915diff -urN /usr/share/empty/fs/aufs/mtx.h linux/fs/aufs/mtx.h
16916--- /usr/share/empty/fs/aufs/mtx.h 1970-01-01 01:00:00.000000000 +0100
16917+++ linux/fs/aufs/mtx.h 2010-08-21 21:00:02.982333916 +0200
4a4d8108
AM
16918@@ -0,0 +1,48 @@
16919+/*
16920+ * Copyright (C) 2010 Junjiro R. Okajima
16921+ *
16922+ * This program, aufs is free software; you can redistribute it and/or modify
16923+ * it under the terms of the GNU General Public License as published by
16924+ * the Free Software Foundation; either version 2 of the License, or
16925+ * (at your option) any later version.
16926+ *
16927+ * This program is distributed in the hope that it will be useful,
16928+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16929+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16930+ * GNU General Public License for more details.
16931+ *
16932+ * You should have received a copy of the GNU General Public License
16933+ * along with this program; if not, write to the Free Software
16934+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16935+ */
16936+
16937+/*
16938+ * very ugly approach for aufs_mmap()
16939+ * never include this file from other than f_op.c.
16940+ * see f_op.c in detail.
16941+ */
16942+
16943+#ifndef __AUFS_MTX_H__
16944+#define __AUFS_MTX_H__
16945+
16946+#ifdef __KERNEL__
16947+
16948+/* copied from ../kernel/mutex{,-debug}.h */
16949+struct mutex;
16950+struct thread_info;
16951+#ifdef CONFIG_DEBUG_MUTEXES
16952+static inline void mutex_set_owner(struct mutex *lock)
16953+{
16954+ lock->owner = current_thread_info();
16955+}
16956+#else
16957+static inline void mutex_set_owner(struct mutex *lock)
16958+{
16959+#ifdef CONFIG_SMP
16960+ lock->owner = current_thread_info();
16961+#endif
16962+}
16963+#endif
1facf9fc 16964+
16965+#endif /* __KERNEL__ */
4a4d8108 16966+#endif /* __AUFS_MTX_H__ */
b752ccd1
AM
16967diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
16968--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
16969+++ linux/fs/aufs/opts.c 2010-08-21 21:00:02.982333916 +0200
4a4d8108 16970@@ -0,0 +1,1585 @@
1facf9fc 16971+/*
4a4d8108 16972+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16973+ *
16974+ * This program, aufs is free software; you can redistribute it and/or modify
16975+ * it under the terms of the GNU General Public License as published by
16976+ * the Free Software Foundation; either version 2 of the License, or
16977+ * (at your option) any later version.
dece6358
AM
16978+ *
16979+ * This program is distributed in the hope that it will be useful,
16980+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16981+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16982+ * GNU General Public License for more details.
16983+ *
16984+ * You should have received a copy of the GNU General Public License
16985+ * along with this program; if not, write to the Free Software
16986+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16987+ */
16988+
16989+/*
16990+ * mount options/flags
16991+ */
16992+
dece6358
AM
16993+#include <linux/file.h>
16994+#include <linux/namei.h>
1facf9fc 16995+#include <linux/types.h> /* a distribution requires */
16996+#include <linux/parser.h>
16997+#include "aufs.h"
16998+
16999+/* ---------------------------------------------------------------------- */
17000+
17001+enum {
17002+ Opt_br,
17003+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
17004+ Opt_idel, Opt_imod, Opt_ireorder,
17005+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 17006+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 17007+ Opt_xino, Opt_zxino, Opt_noxino,
17008+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
17009+ Opt_trunc_xino_path, Opt_itrunc_xino,
17010+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 17011+ Opt_shwh, Opt_noshwh,
1facf9fc 17012+ Opt_plink, Opt_noplink, Opt_list_plink,
17013+ Opt_udba,
4a4d8108 17014+ Opt_dio, Opt_nodio,
1facf9fc 17015+ /* Opt_lock, Opt_unlock, */
17016+ Opt_cmd, Opt_cmd_args,
17017+ Opt_diropq_a, Opt_diropq_w,
17018+ Opt_warn_perm, Opt_nowarn_perm,
17019+ Opt_wbr_copyup, Opt_wbr_create,
17020+ Opt_refrof, Opt_norefrof,
17021+ Opt_verbose, Opt_noverbose,
17022+ Opt_sum, Opt_nosum, Opt_wsum,
17023+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
17024+};
17025+
17026+static match_table_t options = {
17027+ {Opt_br, "br=%s"},
17028+ {Opt_br, "br:%s"},
17029+
17030+ {Opt_add, "add=%d:%s"},
17031+ {Opt_add, "add:%d:%s"},
17032+ {Opt_add, "ins=%d:%s"},
17033+ {Opt_add, "ins:%d:%s"},
17034+ {Opt_append, "append=%s"},
17035+ {Opt_append, "append:%s"},
17036+ {Opt_prepend, "prepend=%s"},
17037+ {Opt_prepend, "prepend:%s"},
17038+
17039+ {Opt_del, "del=%s"},
17040+ {Opt_del, "del:%s"},
17041+ /* {Opt_idel, "idel:%d"}, */
17042+ {Opt_mod, "mod=%s"},
17043+ {Opt_mod, "mod:%s"},
17044+ /* {Opt_imod, "imod:%d:%s"}, */
17045+
17046+ {Opt_dirwh, "dirwh=%d"},
17047+
17048+ {Opt_xino, "xino=%s"},
17049+ {Opt_noxino, "noxino"},
17050+ {Opt_trunc_xino, "trunc_xino"},
17051+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
17052+ {Opt_notrunc_xino, "notrunc_xino"},
17053+ {Opt_trunc_xino_path, "trunc_xino=%s"},
17054+ {Opt_itrunc_xino, "itrunc_xino=%d"},
17055+ /* {Opt_zxino, "zxino=%s"}, */
17056+ {Opt_trunc_xib, "trunc_xib"},
17057+ {Opt_notrunc_xib, "notrunc_xib"},
17058+
17059+ {Opt_plink, "plink"},
17060+ {Opt_noplink, "noplink"},
17061+#ifdef CONFIG_AUFS_DEBUG
17062+ {Opt_list_plink, "list_plink"},
17063+#endif
17064+
17065+ {Opt_udba, "udba=%s"},
17066+
4a4d8108
AM
17067+ {Opt_dio, "dio"},
17068+ {Opt_nodio, "nodio"},
17069+
1facf9fc 17070+ {Opt_diropq_a, "diropq=always"},
17071+ {Opt_diropq_a, "diropq=a"},
17072+ {Opt_diropq_w, "diropq=whiteouted"},
17073+ {Opt_diropq_w, "diropq=w"},
17074+
17075+ {Opt_warn_perm, "warn_perm"},
17076+ {Opt_nowarn_perm, "nowarn_perm"},
17077+
17078+ /* keep them temporary */
17079+ {Opt_ignore_silent, "coo=%s"},
17080+ {Opt_ignore_silent, "nodlgt"},
17081+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 17082+ {Opt_ignore_silent, "clean_plink"},
17083+
dece6358
AM
17084+#ifdef CONFIG_AUFS_SHWH
17085+ {Opt_shwh, "shwh"},
17086+#endif
17087+ {Opt_noshwh, "noshwh"},
17088+
1facf9fc 17089+ {Opt_rendir, "rendir=%d"},
17090+
17091+ {Opt_refrof, "refrof"},
17092+ {Opt_norefrof, "norefrof"},
17093+
17094+ {Opt_verbose, "verbose"},
17095+ {Opt_verbose, "v"},
17096+ {Opt_noverbose, "noverbose"},
17097+ {Opt_noverbose, "quiet"},
17098+ {Opt_noverbose, "q"},
17099+ {Opt_noverbose, "silent"},
17100+
17101+ {Opt_sum, "sum"},
17102+ {Opt_nosum, "nosum"},
17103+ {Opt_wsum, "wsum"},
17104+
17105+ {Opt_rdcache, "rdcache=%d"},
17106+ {Opt_rdblk, "rdblk=%d"},
dece6358 17107+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 17108+ {Opt_rdhash, "rdhash=%d"},
dece6358 17109+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 17110+
17111+ {Opt_wbr_create, "create=%s"},
17112+ {Opt_wbr_create, "create_policy=%s"},
17113+ {Opt_wbr_copyup, "cpup=%s"},
17114+ {Opt_wbr_copyup, "copyup=%s"},
17115+ {Opt_wbr_copyup, "copyup_policy=%s"},
17116+
17117+ /* internal use for the scripts */
17118+ {Opt_ignore_silent, "si=%s"},
17119+
17120+ {Opt_br, "dirs=%s"},
17121+ {Opt_ignore, "debug=%d"},
17122+ {Opt_ignore, "delete=whiteout"},
17123+ {Opt_ignore, "delete=all"},
17124+ {Opt_ignore, "imap=%s"},
17125+
1308ab2a 17126+ /* temporary workaround, due to old mount(8)? */
17127+ {Opt_ignore_silent, "relatime"},
17128+
1facf9fc 17129+ {Opt_err, NULL}
17130+};
17131+
17132+/* ---------------------------------------------------------------------- */
17133+
17134+static const char *au_parser_pattern(int val, struct match_token *token)
17135+{
17136+ while (token->pattern) {
17137+ if (token->token == val)
17138+ return token->pattern;
17139+ token++;
17140+ }
17141+ BUG();
17142+ return "??";
17143+}
17144+
17145+/* ---------------------------------------------------------------------- */
17146+
17147+static match_table_t brperms = {
17148+ {AuBrPerm_RO, AUFS_BRPERM_RO},
17149+ {AuBrPerm_RR, AUFS_BRPERM_RR},
17150+ {AuBrPerm_RW, AUFS_BRPERM_RW},
17151+
17152+ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
17153+ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
17154+ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
17155+
17156+ {AuBrPerm_ROWH, "nfsro"},
17157+ {AuBrPerm_RO, NULL}
17158+};
17159+
4a4d8108 17160+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 17161+{
17162+ int val;
17163+ substring_t args[MAX_OPT_ARGS];
17164+
17165+ val = match_token(perm, brperms, args);
17166+ return val;
17167+}
17168+
17169+const char *au_optstr_br_perm(int brperm)
17170+{
17171+ return au_parser_pattern(brperm, (void *)brperms);
17172+}
17173+
17174+/* ---------------------------------------------------------------------- */
17175+
17176+static match_table_t udbalevel = {
17177+ {AuOpt_UDBA_REVAL, "reval"},
17178+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
17179+#ifdef CONFIG_AUFS_HNOTIFY
17180+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
17181+#ifdef CONFIG_AUFS_HFSNOTIFY
17182+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
17183+#else
17184+ {AuOpt_UDBA_HNOTIFY, "inotify"},
17185+#endif
1facf9fc 17186+#endif
17187+ {-1, NULL}
17188+};
17189+
4a4d8108
AM
17190+static void au_warn_inotify(int val, char *str)
17191+{
17192+#ifdef CONFIG_AUFS_HINOTIFY
17193+ if (val == AuOpt_UDBA_HNOTIFY
17194+ && !strcmp(str, "inotify"))
17195+ AuWarn1("udba=inotify is deprecated, use udba=notify\n");
17196+#endif
17197+}
17198+
17199+static int noinline_for_stack udba_val(char *str)
1facf9fc 17200+{
4a4d8108 17201+ int val;
1facf9fc 17202+ substring_t args[MAX_OPT_ARGS];
17203+
4a4d8108
AM
17204+ val = match_token(str, udbalevel, args);
17205+ au_warn_inotify(val, str);
17206+ return val;
1facf9fc 17207+}
17208+
17209+const char *au_optstr_udba(int udba)
17210+{
17211+ return au_parser_pattern(udba, (void *)udbalevel);
17212+}
17213+
17214+/* ---------------------------------------------------------------------- */
17215+
17216+static match_table_t au_wbr_create_policy = {
17217+ {AuWbrCreate_TDP, "tdp"},
17218+ {AuWbrCreate_TDP, "top-down-parent"},
17219+ {AuWbrCreate_RR, "rr"},
17220+ {AuWbrCreate_RR, "round-robin"},
17221+ {AuWbrCreate_MFS, "mfs"},
17222+ {AuWbrCreate_MFS, "most-free-space"},
17223+ {AuWbrCreate_MFSV, "mfs:%d"},
17224+ {AuWbrCreate_MFSV, "most-free-space:%d"},
17225+
17226+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
17227+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
17228+ {AuWbrCreate_PMFS, "pmfs"},
17229+ {AuWbrCreate_PMFSV, "pmfs:%d"},
17230+
17231+ {-1, NULL}
17232+};
17233+
dece6358
AM
17234+/*
17235+ * cf. linux/lib/parser.c and cmdline.c
17236+ * gave up calling memparse() since it uses simple_strtoull() instead of
17237+ * strict_...().
17238+ */
4a4d8108
AM
17239+static int noinline_for_stack
17240+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 17241+{
17242+ int err;
17243+ unsigned int len;
17244+ char a[32];
17245+
17246+ err = -ERANGE;
17247+ len = s->to - s->from;
17248+ if (len + 1 <= sizeof(a)) {
17249+ memcpy(a, s->from, len);
17250+ a[len] = '\0';
17251+ err = strict_strtoull(a, 0, result);
17252+ }
17253+ return err;
17254+}
17255+
17256+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
17257+ struct au_opt_wbr_create *create)
17258+{
17259+ int err;
17260+ unsigned long long ull;
17261+
17262+ err = 0;
17263+ if (!au_match_ull(arg, &ull))
17264+ create->mfsrr_watermark = ull;
17265+ else {
4a4d8108 17266+ pr_err("bad integer in %s\n", str);
1facf9fc 17267+ err = -EINVAL;
17268+ }
17269+
17270+ return err;
17271+}
17272+
17273+static int au_wbr_mfs_sec(substring_t *arg, char *str,
17274+ struct au_opt_wbr_create *create)
17275+{
17276+ int n, err;
17277+
17278+ err = 0;
17279+ if (!match_int(arg, &n) && 0 <= n)
17280+ create->mfs_second = n;
17281+ else {
4a4d8108 17282+ pr_err("bad integer in %s\n", str);
1facf9fc 17283+ err = -EINVAL;
17284+ }
17285+
17286+ return err;
17287+}
17288+
4a4d8108
AM
17289+static int noinline_for_stack
17290+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 17291+{
17292+ int err, e;
17293+ substring_t args[MAX_OPT_ARGS];
17294+
17295+ err = match_token(str, au_wbr_create_policy, args);
17296+ create->wbr_create = err;
17297+ switch (err) {
17298+ case AuWbrCreate_MFSRRV:
17299+ e = au_wbr_mfs_wmark(&args[0], str, create);
17300+ if (!e)
17301+ e = au_wbr_mfs_sec(&args[1], str, create);
17302+ if (unlikely(e))
17303+ err = e;
17304+ break;
17305+ case AuWbrCreate_MFSRR:
17306+ e = au_wbr_mfs_wmark(&args[0], str, create);
17307+ if (unlikely(e)) {
17308+ err = e;
17309+ break;
17310+ }
17311+ /*FALLTHROUGH*/
17312+ case AuWbrCreate_MFS:
17313+ case AuWbrCreate_PMFS:
17314+ create->mfs_second = AUFS_MFS_SECOND_DEF;
17315+ break;
17316+ case AuWbrCreate_MFSV:
17317+ case AuWbrCreate_PMFSV:
17318+ e = au_wbr_mfs_sec(&args[0], str, create);
17319+ if (unlikely(e))
17320+ err = e;
17321+ break;
17322+ }
17323+
17324+ return err;
17325+}
17326+
17327+const char *au_optstr_wbr_create(int wbr_create)
17328+{
17329+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
17330+}
17331+
17332+static match_table_t au_wbr_copyup_policy = {
17333+ {AuWbrCopyup_TDP, "tdp"},
17334+ {AuWbrCopyup_TDP, "top-down-parent"},
17335+ {AuWbrCopyup_BUP, "bup"},
17336+ {AuWbrCopyup_BUP, "bottom-up-parent"},
17337+ {AuWbrCopyup_BU, "bu"},
17338+ {AuWbrCopyup_BU, "bottom-up"},
17339+ {-1, NULL}
17340+};
17341+
4a4d8108 17342+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 17343+{
17344+ substring_t args[MAX_OPT_ARGS];
17345+
17346+ return match_token(str, au_wbr_copyup_policy, args);
17347+}
17348+
17349+const char *au_optstr_wbr_copyup(int wbr_copyup)
17350+{
17351+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
17352+}
17353+
17354+/* ---------------------------------------------------------------------- */
17355+
17356+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
17357+
17358+static void dump_opts(struct au_opts *opts)
17359+{
17360+#ifdef CONFIG_AUFS_DEBUG
17361+ /* reduce stack space */
17362+ union {
17363+ struct au_opt_add *add;
17364+ struct au_opt_del *del;
17365+ struct au_opt_mod *mod;
17366+ struct au_opt_xino *xino;
17367+ struct au_opt_xino_itrunc *xino_itrunc;
17368+ struct au_opt_wbr_create *create;
17369+ } u;
17370+ struct au_opt *opt;
17371+
17372+ opt = opts->opt;
17373+ while (opt->type != Opt_tail) {
17374+ switch (opt->type) {
17375+ case Opt_add:
17376+ u.add = &opt->add;
17377+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
17378+ u.add->bindex, u.add->pathname, u.add->perm,
17379+ u.add->path.dentry);
17380+ break;
17381+ case Opt_del:
17382+ case Opt_idel:
17383+ u.del = &opt->del;
17384+ AuDbg("del {%s, %p}\n",
17385+ u.del->pathname, u.del->h_path.dentry);
17386+ break;
17387+ case Opt_mod:
17388+ case Opt_imod:
17389+ u.mod = &opt->mod;
17390+ AuDbg("mod {%s, 0x%x, %p}\n",
17391+ u.mod->path, u.mod->perm, u.mod->h_root);
17392+ break;
17393+ case Opt_append:
17394+ u.add = &opt->add;
17395+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
17396+ u.add->bindex, u.add->pathname, u.add->perm,
17397+ u.add->path.dentry);
17398+ break;
17399+ case Opt_prepend:
17400+ u.add = &opt->add;
17401+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
17402+ u.add->bindex, u.add->pathname, u.add->perm,
17403+ u.add->path.dentry);
17404+ break;
17405+ case Opt_dirwh:
17406+ AuDbg("dirwh %d\n", opt->dirwh);
17407+ break;
17408+ case Opt_rdcache:
17409+ AuDbg("rdcache %d\n", opt->rdcache);
17410+ break;
17411+ case Opt_rdblk:
17412+ AuDbg("rdblk %u\n", opt->rdblk);
17413+ break;
dece6358
AM
17414+ case Opt_rdblk_def:
17415+ AuDbg("rdblk_def\n");
17416+ break;
1facf9fc 17417+ case Opt_rdhash:
17418+ AuDbg("rdhash %u\n", opt->rdhash);
17419+ break;
dece6358
AM
17420+ case Opt_rdhash_def:
17421+ AuDbg("rdhash_def\n");
17422+ break;
1facf9fc 17423+ case Opt_xino:
17424+ u.xino = &opt->xino;
17425+ AuDbg("xino {%s %.*s}\n",
17426+ u.xino->path,
17427+ AuDLNPair(u.xino->file->f_dentry));
17428+ break;
17429+ case Opt_trunc_xino:
17430+ AuLabel(trunc_xino);
17431+ break;
17432+ case Opt_notrunc_xino:
17433+ AuLabel(notrunc_xino);
17434+ break;
17435+ case Opt_trunc_xino_path:
17436+ case Opt_itrunc_xino:
17437+ u.xino_itrunc = &opt->xino_itrunc;
17438+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
17439+ break;
17440+
17441+ case Opt_noxino:
17442+ AuLabel(noxino);
17443+ break;
17444+ case Opt_trunc_xib:
17445+ AuLabel(trunc_xib);
17446+ break;
17447+ case Opt_notrunc_xib:
17448+ AuLabel(notrunc_xib);
17449+ break;
dece6358
AM
17450+ case Opt_shwh:
17451+ AuLabel(shwh);
17452+ break;
17453+ case Opt_noshwh:
17454+ AuLabel(noshwh);
17455+ break;
1facf9fc 17456+ case Opt_plink:
17457+ AuLabel(plink);
17458+ break;
17459+ case Opt_noplink:
17460+ AuLabel(noplink);
17461+ break;
17462+ case Opt_list_plink:
17463+ AuLabel(list_plink);
17464+ break;
17465+ case Opt_udba:
17466+ AuDbg("udba %d, %s\n",
17467+ opt->udba, au_optstr_udba(opt->udba));
17468+ break;
4a4d8108
AM
17469+ case Opt_dio:
17470+ AuLabel(dio);
17471+ break;
17472+ case Opt_nodio:
17473+ AuLabel(nodio);
17474+ break;
1facf9fc 17475+ case Opt_diropq_a:
17476+ AuLabel(diropq_a);
17477+ break;
17478+ case Opt_diropq_w:
17479+ AuLabel(diropq_w);
17480+ break;
17481+ case Opt_warn_perm:
17482+ AuLabel(warn_perm);
17483+ break;
17484+ case Opt_nowarn_perm:
17485+ AuLabel(nowarn_perm);
17486+ break;
17487+ case Opt_refrof:
17488+ AuLabel(refrof);
17489+ break;
17490+ case Opt_norefrof:
17491+ AuLabel(norefrof);
17492+ break;
17493+ case Opt_verbose:
17494+ AuLabel(verbose);
17495+ break;
17496+ case Opt_noverbose:
17497+ AuLabel(noverbose);
17498+ break;
17499+ case Opt_sum:
17500+ AuLabel(sum);
17501+ break;
17502+ case Opt_nosum:
17503+ AuLabel(nosum);
17504+ break;
17505+ case Opt_wsum:
17506+ AuLabel(wsum);
17507+ break;
17508+ case Opt_wbr_create:
17509+ u.create = &opt->wbr_create;
17510+ AuDbg("create %d, %s\n", u.create->wbr_create,
17511+ au_optstr_wbr_create(u.create->wbr_create));
17512+ switch (u.create->wbr_create) {
17513+ case AuWbrCreate_MFSV:
17514+ case AuWbrCreate_PMFSV:
17515+ AuDbg("%d sec\n", u.create->mfs_second);
17516+ break;
17517+ case AuWbrCreate_MFSRR:
17518+ AuDbg("%llu watermark\n",
17519+ u.create->mfsrr_watermark);
17520+ break;
17521+ case AuWbrCreate_MFSRRV:
17522+ AuDbg("%llu watermark, %d sec\n",
17523+ u.create->mfsrr_watermark,
17524+ u.create->mfs_second);
17525+ break;
17526+ }
17527+ break;
17528+ case Opt_wbr_copyup:
17529+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
17530+ au_optstr_wbr_copyup(opt->wbr_copyup));
17531+ break;
17532+ default:
17533+ BUG();
17534+ }
17535+ opt++;
17536+ }
17537+#endif
17538+}
17539+
17540+void au_opts_free(struct au_opts *opts)
17541+{
17542+ struct au_opt *opt;
17543+
17544+ opt = opts->opt;
17545+ while (opt->type != Opt_tail) {
17546+ switch (opt->type) {
17547+ case Opt_add:
17548+ case Opt_append:
17549+ case Opt_prepend:
17550+ path_put(&opt->add.path);
17551+ break;
17552+ case Opt_del:
17553+ case Opt_idel:
17554+ path_put(&opt->del.h_path);
17555+ break;
17556+ case Opt_mod:
17557+ case Opt_imod:
17558+ dput(opt->mod.h_root);
17559+ break;
17560+ case Opt_xino:
17561+ fput(opt->xino.file);
17562+ break;
17563+ }
17564+ opt++;
17565+ }
17566+}
17567+
17568+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
17569+ aufs_bindex_t bindex)
17570+{
17571+ int err;
17572+ struct au_opt_add *add = &opt->add;
17573+ char *p;
17574+
17575+ add->bindex = bindex;
17576+ add->perm = AuBrPerm_Last;
17577+ add->pathname = opt_str;
17578+ p = strchr(opt_str, '=');
17579+ if (p) {
17580+ *p++ = 0;
17581+ if (*p)
17582+ add->perm = br_perm_val(p);
17583+ }
17584+
17585+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
17586+ if (!err) {
17587+ if (!p) {
17588+ add->perm = AuBrPerm_RO;
17589+ if (au_test_fs_rr(add->path.dentry->d_sb))
17590+ add->perm = AuBrPerm_RR;
17591+ else if (!bindex && !(sb_flags & MS_RDONLY))
17592+ add->perm = AuBrPerm_RW;
17593+ }
17594+ opt->type = Opt_add;
17595+ goto out;
17596+ }
4a4d8108 17597+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 17598+ err = -EINVAL;
17599+
17600+ out:
17601+ return err;
17602+}
17603+
17604+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
17605+{
17606+ int err;
17607+
17608+ del->pathname = args[0].from;
17609+ AuDbg("del path %s\n", del->pathname);
17610+
17611+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
17612+ if (unlikely(err))
4a4d8108 17613+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 17614+
17615+ return err;
17616+}
17617+
17618+#if 0 /* reserved for future use */
17619+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
17620+ struct au_opt_del *del, substring_t args[])
17621+{
17622+ int err;
17623+ struct dentry *root;
17624+
17625+ err = -EINVAL;
17626+ root = sb->s_root;
17627+ aufs_read_lock(root, AuLock_FLUSH);
17628+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17629+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17630+ goto out;
17631+ }
17632+
17633+ err = 0;
17634+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
17635+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
17636+
17637+ out:
17638+ aufs_read_unlock(root, !AuLock_IR);
17639+ return err;
17640+}
17641+#endif
17642+
4a4d8108
AM
17643+static int noinline_for_stack
17644+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 17645+{
17646+ int err;
17647+ struct path path;
17648+ char *p;
17649+
17650+ err = -EINVAL;
17651+ mod->path = args[0].from;
17652+ p = strchr(mod->path, '=');
17653+ if (unlikely(!p)) {
4a4d8108 17654+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 17655+ goto out;
17656+ }
17657+
17658+ *p++ = 0;
17659+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
17660+ if (unlikely(err)) {
4a4d8108 17661+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 17662+ goto out;
17663+ }
17664+
17665+ mod->perm = br_perm_val(p);
17666+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
17667+ mod->h_root = dget(path.dentry);
17668+ path_put(&path);
17669+
17670+ out:
17671+ return err;
17672+}
17673+
17674+#if 0 /* reserved for future use */
17675+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
17676+ struct au_opt_mod *mod, substring_t args[])
17677+{
17678+ int err;
17679+ struct dentry *root;
17680+
17681+ err = -EINVAL;
17682+ root = sb->s_root;
17683+ aufs_read_lock(root, AuLock_FLUSH);
17684+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17685+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17686+ goto out;
17687+ }
17688+
17689+ err = 0;
17690+ mod->perm = br_perm_val(args[1].from);
17691+ AuDbg("mod path %s, perm 0x%x, %s\n",
17692+ mod->path, mod->perm, args[1].from);
17693+ mod->h_root = dget(au_h_dptr(root, bindex));
17694+
17695+ out:
17696+ aufs_read_unlock(root, !AuLock_IR);
17697+ return err;
17698+}
17699+#endif
17700+
17701+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
17702+ substring_t args[])
17703+{
17704+ int err;
17705+ struct file *file;
17706+
17707+ file = au_xino_create(sb, args[0].from, /*silent*/0);
17708+ err = PTR_ERR(file);
17709+ if (IS_ERR(file))
17710+ goto out;
17711+
17712+ err = -EINVAL;
17713+ if (unlikely(file->f_dentry->d_sb == sb)) {
17714+ fput(file);
4a4d8108 17715+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 17716+ goto out;
17717+ }
17718+
17719+ err = 0;
17720+ xino->file = file;
17721+ xino->path = args[0].from;
17722+
17723+ out:
17724+ return err;
17725+}
17726+
4a4d8108
AM
17727+static int noinline_for_stack
17728+au_opts_parse_xino_itrunc_path(struct super_block *sb,
17729+ struct au_opt_xino_itrunc *xino_itrunc,
17730+ substring_t args[])
1facf9fc 17731+{
17732+ int err;
17733+ aufs_bindex_t bend, bindex;
17734+ struct path path;
17735+ struct dentry *root;
17736+
17737+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
17738+ if (unlikely(err)) {
4a4d8108 17739+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 17740+ goto out;
17741+ }
17742+
17743+ xino_itrunc->bindex = -1;
17744+ root = sb->s_root;
17745+ aufs_read_lock(root, AuLock_FLUSH);
17746+ bend = au_sbend(sb);
17747+ for (bindex = 0; bindex <= bend; bindex++) {
17748+ if (au_h_dptr(root, bindex) == path.dentry) {
17749+ xino_itrunc->bindex = bindex;
17750+ break;
17751+ }
17752+ }
17753+ aufs_read_unlock(root, !AuLock_IR);
17754+ path_put(&path);
17755+
17756+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 17757+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 17758+ err = -EINVAL;
17759+ }
17760+
17761+ out:
17762+ return err;
17763+}
17764+
17765+/* called without aufs lock */
17766+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
17767+{
17768+ int err, n, token;
17769+ aufs_bindex_t bindex;
17770+ unsigned char skipped;
17771+ struct dentry *root;
17772+ struct au_opt *opt, *opt_tail;
17773+ char *opt_str;
17774+ /* reduce the stack space */
17775+ union {
17776+ struct au_opt_xino_itrunc *xino_itrunc;
17777+ struct au_opt_wbr_create *create;
17778+ } u;
17779+ struct {
17780+ substring_t args[MAX_OPT_ARGS];
17781+ } *a;
17782+
17783+ err = -ENOMEM;
17784+ a = kmalloc(sizeof(*a), GFP_NOFS);
17785+ if (unlikely(!a))
17786+ goto out;
17787+
17788+ root = sb->s_root;
17789+ err = 0;
17790+ bindex = 0;
17791+ opt = opts->opt;
17792+ opt_tail = opt + opts->max_opt - 1;
17793+ opt->type = Opt_tail;
17794+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
17795+ err = -EINVAL;
17796+ skipped = 0;
17797+ token = match_token(opt_str, options, a->args);
17798+ switch (token) {
17799+ case Opt_br:
17800+ err = 0;
17801+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
17802+ && *opt_str) {
17803+ err = opt_add(opt, opt_str, opts->sb_flags,
17804+ bindex++);
17805+ if (unlikely(!err && ++opt > opt_tail)) {
17806+ err = -E2BIG;
17807+ break;
17808+ }
17809+ opt->type = Opt_tail;
17810+ skipped = 1;
17811+ }
17812+ break;
17813+ case Opt_add:
17814+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17815+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17816+ break;
17817+ }
17818+ bindex = n;
17819+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
17820+ bindex);
17821+ if (!err)
17822+ opt->type = token;
17823+ break;
17824+ case Opt_append:
17825+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17826+ /*dummy bindex*/1);
17827+ if (!err)
17828+ opt->type = token;
17829+ break;
17830+ case Opt_prepend:
17831+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17832+ /*bindex*/0);
17833+ if (!err)
17834+ opt->type = token;
17835+ break;
17836+ case Opt_del:
17837+ err = au_opts_parse_del(&opt->del, a->args);
17838+ if (!err)
17839+ opt->type = token;
17840+ break;
17841+#if 0 /* reserved for future use */
17842+ case Opt_idel:
17843+ del->pathname = "(indexed)";
17844+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 17845+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17846+ break;
17847+ }
17848+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
17849+ if (!err)
17850+ opt->type = token;
17851+ break;
17852+#endif
17853+ case Opt_mod:
17854+ err = au_opts_parse_mod(&opt->mod, a->args);
17855+ if (!err)
17856+ opt->type = token;
17857+ break;
17858+#ifdef IMOD /* reserved for future use */
17859+ case Opt_imod:
17860+ u.mod->path = "(indexed)";
17861+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17862+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17863+ break;
17864+ }
17865+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
17866+ if (!err)
17867+ opt->type = token;
17868+ break;
17869+#endif
17870+ case Opt_xino:
17871+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
17872+ if (!err)
17873+ opt->type = token;
17874+ break;
17875+
17876+ case Opt_trunc_xino_path:
17877+ err = au_opts_parse_xino_itrunc_path
17878+ (sb, &opt->xino_itrunc, a->args);
17879+ if (!err)
17880+ opt->type = token;
17881+ break;
17882+
17883+ case Opt_itrunc_xino:
17884+ u.xino_itrunc = &opt->xino_itrunc;
17885+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17886+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17887+ break;
17888+ }
17889+ u.xino_itrunc->bindex = n;
17890+ aufs_read_lock(root, AuLock_FLUSH);
17891+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 17892+ pr_err("out of bounds, %d\n", n);
1facf9fc 17893+ aufs_read_unlock(root, !AuLock_IR);
17894+ break;
17895+ }
17896+ aufs_read_unlock(root, !AuLock_IR);
17897+ err = 0;
17898+ opt->type = token;
17899+ break;
17900+
17901+ case Opt_dirwh:
17902+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
17903+ break;
17904+ err = 0;
17905+ opt->type = token;
17906+ break;
17907+
17908+ case Opt_rdcache:
17909+ if (unlikely(match_int(&a->args[0], &opt->rdcache)))
17910+ break;
17911+ err = 0;
17912+ opt->type = token;
17913+ break;
17914+ case Opt_rdblk:
17915+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17916+ || n < 0
1facf9fc 17917+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 17918+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17919+ break;
17920+ }
1308ab2a 17921+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
17922+ pr_err("rdblk must be larger than %d\n",
17923+ NAME_MAX);
1facf9fc 17924+ break;
17925+ }
17926+ opt->rdblk = n;
17927+ err = 0;
17928+ opt->type = token;
17929+ break;
17930+ case Opt_rdhash:
17931+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17932+ || n < 0
1facf9fc 17933+ || n * sizeof(struct hlist_head)
17934+ > KMALLOC_MAX_SIZE)) {
4a4d8108 17935+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17936+ break;
17937+ }
17938+ opt->rdhash = n;
17939+ err = 0;
17940+ opt->type = token;
17941+ break;
17942+
17943+ case Opt_trunc_xino:
17944+ case Opt_notrunc_xino:
17945+ case Opt_noxino:
17946+ case Opt_trunc_xib:
17947+ case Opt_notrunc_xib:
dece6358
AM
17948+ case Opt_shwh:
17949+ case Opt_noshwh:
1facf9fc 17950+ case Opt_plink:
17951+ case Opt_noplink:
17952+ case Opt_list_plink:
4a4d8108
AM
17953+ case Opt_dio:
17954+ case Opt_nodio:
1facf9fc 17955+ case Opt_diropq_a:
17956+ case Opt_diropq_w:
17957+ case Opt_warn_perm:
17958+ case Opt_nowarn_perm:
17959+ case Opt_refrof:
17960+ case Opt_norefrof:
17961+ case Opt_verbose:
17962+ case Opt_noverbose:
17963+ case Opt_sum:
17964+ case Opt_nosum:
17965+ case Opt_wsum:
dece6358
AM
17966+ case Opt_rdblk_def:
17967+ case Opt_rdhash_def:
1facf9fc 17968+ err = 0;
17969+ opt->type = token;
17970+ break;
17971+
17972+ case Opt_udba:
17973+ opt->udba = udba_val(a->args[0].from);
17974+ if (opt->udba >= 0) {
17975+ err = 0;
17976+ opt->type = token;
17977+ } else
4a4d8108 17978+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17979+ break;
17980+
17981+ case Opt_wbr_create:
17982+ u.create = &opt->wbr_create;
17983+ u.create->wbr_create
17984+ = au_wbr_create_val(a->args[0].from, u.create);
17985+ if (u.create->wbr_create >= 0) {
17986+ err = 0;
17987+ opt->type = token;
17988+ } else
4a4d8108 17989+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17990+ break;
17991+ case Opt_wbr_copyup:
17992+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
17993+ if (opt->wbr_copyup >= 0) {
17994+ err = 0;
17995+ opt->type = token;
17996+ } else
4a4d8108 17997+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17998+ break;
17999+
18000+ case Opt_ignore:
4a4d8108 18001+ pr_warning("ignored %s\n", opt_str);
1facf9fc 18002+ /*FALLTHROUGH*/
18003+ case Opt_ignore_silent:
18004+ skipped = 1;
18005+ err = 0;
18006+ break;
18007+ case Opt_err:
4a4d8108 18008+ pr_err("unknown option %s\n", opt_str);
1facf9fc 18009+ break;
18010+ }
18011+
18012+ if (!err && !skipped) {
18013+ if (unlikely(++opt > opt_tail)) {
18014+ err = -E2BIG;
18015+ opt--;
18016+ opt->type = Opt_tail;
18017+ break;
18018+ }
18019+ opt->type = Opt_tail;
18020+ }
18021+ }
18022+
18023+ kfree(a);
18024+ dump_opts(opts);
18025+ if (unlikely(err))
18026+ au_opts_free(opts);
18027+
18028+ out:
18029+ return err;
18030+}
18031+
18032+static int au_opt_wbr_create(struct super_block *sb,
18033+ struct au_opt_wbr_create *create)
18034+{
18035+ int err;
18036+ struct au_sbinfo *sbinfo;
18037+
dece6358
AM
18038+ SiMustWriteLock(sb);
18039+
1facf9fc 18040+ err = 1; /* handled */
18041+ sbinfo = au_sbi(sb);
18042+ if (sbinfo->si_wbr_create_ops->fin) {
18043+ err = sbinfo->si_wbr_create_ops->fin(sb);
18044+ if (!err)
18045+ err = 1;
18046+ }
18047+
18048+ sbinfo->si_wbr_create = create->wbr_create;
18049+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
18050+ switch (create->wbr_create) {
18051+ case AuWbrCreate_MFSRRV:
18052+ case AuWbrCreate_MFSRR:
18053+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
18054+ /*FALLTHROUGH*/
18055+ case AuWbrCreate_MFS:
18056+ case AuWbrCreate_MFSV:
18057+ case AuWbrCreate_PMFS:
18058+ case AuWbrCreate_PMFSV:
18059+ sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
18060+ break;
18061+ }
18062+
18063+ if (sbinfo->si_wbr_create_ops->init)
18064+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
18065+
18066+ return err;
18067+}
18068+
18069+/*
18070+ * returns,
18071+ * plus: processed without an error
18072+ * zero: unprocessed
18073+ */
18074+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
18075+ struct au_opts *opts)
18076+{
18077+ int err;
18078+ struct au_sbinfo *sbinfo;
18079+
dece6358
AM
18080+ SiMustWriteLock(sb);
18081+
1facf9fc 18082+ err = 1; /* handled */
18083+ sbinfo = au_sbi(sb);
18084+ switch (opt->type) {
18085+ case Opt_udba:
18086+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18087+ sbinfo->si_mntflags |= opt->udba;
18088+ opts->given_udba |= opt->udba;
18089+ break;
18090+
18091+ case Opt_plink:
18092+ au_opt_set(sbinfo->si_mntflags, PLINK);
18093+ break;
18094+ case Opt_noplink:
18095+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
18096+ au_plink_put(sb);
18097+ au_opt_clr(sbinfo->si_mntflags, PLINK);
18098+ break;
18099+ case Opt_list_plink:
18100+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
18101+ au_plink_list(sb);
18102+ break;
18103+
4a4d8108
AM
18104+ case Opt_dio:
18105+ au_opt_set(sbinfo->si_mntflags, DIO);
18106+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18107+ break;
18108+ case Opt_nodio:
18109+ au_opt_clr(sbinfo->si_mntflags, DIO);
18110+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18111+ break;
18112+
1facf9fc 18113+ case Opt_diropq_a:
18114+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18115+ break;
18116+ case Opt_diropq_w:
18117+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18118+ break;
18119+
18120+ case Opt_warn_perm:
18121+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
18122+ break;
18123+ case Opt_nowarn_perm:
18124+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
18125+ break;
18126+
18127+ case Opt_refrof:
18128+ au_opt_set(sbinfo->si_mntflags, REFROF);
18129+ break;
18130+ case Opt_norefrof:
18131+ au_opt_clr(sbinfo->si_mntflags, REFROF);
18132+ break;
18133+
18134+ case Opt_verbose:
18135+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
18136+ break;
18137+ case Opt_noverbose:
18138+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
18139+ break;
18140+
18141+ case Opt_sum:
18142+ au_opt_set(sbinfo->si_mntflags, SUM);
18143+ break;
18144+ case Opt_wsum:
18145+ au_opt_clr(sbinfo->si_mntflags, SUM);
18146+ au_opt_set(sbinfo->si_mntflags, SUM_W);
18147+ case Opt_nosum:
18148+ au_opt_clr(sbinfo->si_mntflags, SUM);
18149+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
18150+ break;
18151+
18152+ case Opt_wbr_create:
18153+ err = au_opt_wbr_create(sb, &opt->wbr_create);
18154+ break;
18155+ case Opt_wbr_copyup:
18156+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
18157+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
18158+ break;
18159+
18160+ case Opt_dirwh:
18161+ sbinfo->si_dirwh = opt->dirwh;
18162+ break;
18163+
18164+ case Opt_rdcache:
18165+ sbinfo->si_rdcache = opt->rdcache * HZ;
18166+ break;
18167+ case Opt_rdblk:
18168+ sbinfo->si_rdblk = opt->rdblk;
18169+ break;
dece6358
AM
18170+ case Opt_rdblk_def:
18171+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
18172+ break;
1facf9fc 18173+ case Opt_rdhash:
18174+ sbinfo->si_rdhash = opt->rdhash;
18175+ break;
dece6358
AM
18176+ case Opt_rdhash_def:
18177+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
18178+ break;
18179+
18180+ case Opt_shwh:
18181+ au_opt_set(sbinfo->si_mntflags, SHWH);
18182+ break;
18183+ case Opt_noshwh:
18184+ au_opt_clr(sbinfo->si_mntflags, SHWH);
18185+ break;
1facf9fc 18186+
18187+ case Opt_trunc_xino:
18188+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
18189+ break;
18190+ case Opt_notrunc_xino:
18191+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
18192+ break;
18193+
18194+ case Opt_trunc_xino_path:
18195+ case Opt_itrunc_xino:
18196+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
18197+ if (!err)
18198+ err = 1;
18199+ break;
18200+
18201+ case Opt_trunc_xib:
18202+ au_fset_opts(opts->flags, TRUNC_XIB);
18203+ break;
18204+ case Opt_notrunc_xib:
18205+ au_fclr_opts(opts->flags, TRUNC_XIB);
18206+ break;
18207+
18208+ default:
18209+ err = 0;
18210+ break;
18211+ }
18212+
18213+ return err;
18214+}
18215+
18216+/*
18217+ * returns tri-state.
18218+ * plus: processed without an error
18219+ * zero: unprocessed
18220+ * minus: error
18221+ */
18222+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
18223+ struct au_opts *opts)
18224+{
18225+ int err, do_refresh;
18226+
18227+ err = 0;
18228+ switch (opt->type) {
18229+ case Opt_append:
18230+ opt->add.bindex = au_sbend(sb) + 1;
18231+ if (opt->add.bindex < 0)
18232+ opt->add.bindex = 0;
18233+ goto add;
18234+ case Opt_prepend:
18235+ opt->add.bindex = 0;
18236+ add:
18237+ case Opt_add:
18238+ err = au_br_add(sb, &opt->add,
18239+ au_ftest_opts(opts->flags, REMOUNT));
18240+ if (!err) {
18241+ err = 1;
18242+ au_fset_opts(opts->flags, REFRESH_DIR);
4a4d8108 18243+ au_fset_opts(opts->flags, REFRESH_NONDIR);
1facf9fc 18244+ }
18245+ break;
18246+
18247+ case Opt_del:
18248+ case Opt_idel:
18249+ err = au_br_del(sb, &opt->del,
18250+ au_ftest_opts(opts->flags, REMOUNT));
18251+ if (!err) {
18252+ err = 1;
18253+ au_fset_opts(opts->flags, TRUNC_XIB);
18254+ au_fset_opts(opts->flags, REFRESH_DIR);
18255+ au_fset_opts(opts->flags, REFRESH_NONDIR);
18256+ }
18257+ break;
18258+
18259+ case Opt_mod:
18260+ case Opt_imod:
18261+ err = au_br_mod(sb, &opt->mod,
18262+ au_ftest_opts(opts->flags, REMOUNT),
18263+ &do_refresh);
18264+ if (!err) {
18265+ err = 1;
18266+ if (do_refresh) {
18267+ au_fset_opts(opts->flags, REFRESH_DIR);
18268+ au_fset_opts(opts->flags, REFRESH_NONDIR);
18269+ }
18270+ }
18271+ break;
18272+ }
18273+
18274+ return err;
18275+}
18276+
18277+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
18278+ struct au_opt_xino **opt_xino,
18279+ struct au_opts *opts)
18280+{
18281+ int err;
18282+ aufs_bindex_t bend, bindex;
18283+ struct dentry *root, *parent, *h_root;
18284+
18285+ err = 0;
18286+ switch (opt->type) {
18287+ case Opt_xino:
18288+ err = au_xino_set(sb, &opt->xino,
18289+ !!au_ftest_opts(opts->flags, REMOUNT));
18290+ if (unlikely(err))
18291+ break;
18292+
18293+ *opt_xino = &opt->xino;
18294+ au_xino_brid_set(sb, -1);
18295+
18296+ /* safe d_parent access */
18297+ parent = opt->xino.file->f_dentry->d_parent;
18298+ root = sb->s_root;
18299+ bend = au_sbend(sb);
18300+ for (bindex = 0; bindex <= bend; bindex++) {
18301+ h_root = au_h_dptr(root, bindex);
18302+ if (h_root == parent) {
18303+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
18304+ break;
18305+ }
18306+ }
18307+ break;
18308+
18309+ case Opt_noxino:
18310+ au_xino_clr(sb);
18311+ au_xino_brid_set(sb, -1);
18312+ *opt_xino = (void *)-1;
18313+ break;
18314+ }
18315+
18316+ return err;
18317+}
18318+
18319+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18320+ unsigned int pending)
18321+{
18322+ int err;
18323+ aufs_bindex_t bindex, bend;
18324+ unsigned char do_plink, skip, do_free;
18325+ struct au_branch *br;
18326+ struct au_wbr *wbr;
18327+ struct dentry *root;
18328+ struct inode *dir, *h_dir;
18329+ struct au_sbinfo *sbinfo;
18330+ struct au_hinode *hdir;
18331+
dece6358
AM
18332+ SiMustAnyLock(sb);
18333+
1facf9fc 18334+ sbinfo = au_sbi(sb);
18335+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
18336+
dece6358
AM
18337+ if (!(sb_flags & MS_RDONLY)) {
18338+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
4a4d8108 18339+ pr_warning("first branch should be rw\n");
dece6358 18340+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
4a4d8108 18341+ pr_warning("shwh should be used with ro\n");
dece6358 18342+ }
1facf9fc 18343+
4a4d8108 18344+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 18345+ && !au_opt_test(sbinfo->si_mntflags, XINO))
4a4d8108 18346+ pr_warning("udba=*notify requires xino\n");
1facf9fc 18347+
18348+ err = 0;
18349+ root = sb->s_root;
4a4d8108 18350+ dir = root->d_inode;
1facf9fc 18351+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
18352+ bend = au_sbend(sb);
18353+ for (bindex = 0; !err && bindex <= bend; bindex++) {
18354+ skip = 0;
18355+ h_dir = au_h_iptr(dir, bindex);
18356+ br = au_sbr(sb, bindex);
18357+ do_free = 0;
18358+
18359+ wbr = br->br_wbr;
18360+ if (wbr)
18361+ wbr_wh_read_lock(wbr);
18362+
18363+ switch (br->br_perm) {
18364+ case AuBrPerm_RO:
18365+ case AuBrPerm_ROWH:
18366+ case AuBrPerm_RR:
18367+ case AuBrPerm_RRWH:
18368+ do_free = !!wbr;
18369+ skip = (!wbr
18370+ || (!wbr->wbr_whbase
18371+ && !wbr->wbr_plink
18372+ && !wbr->wbr_orph));
18373+ break;
18374+
18375+ case AuBrPerm_RWNoLinkWH:
18376+ /* skip = (!br->br_whbase && !br->br_orph); */
18377+ skip = (!wbr || !wbr->wbr_whbase);
18378+ if (skip && wbr) {
18379+ if (do_plink)
18380+ skip = !!wbr->wbr_plink;
18381+ else
18382+ skip = !wbr->wbr_plink;
18383+ }
18384+ break;
18385+
18386+ case AuBrPerm_RW:
18387+ /* skip = (br->br_whbase && br->br_ohph); */
18388+ skip = (wbr && wbr->wbr_whbase);
18389+ if (skip) {
18390+ if (do_plink)
18391+ skip = !!wbr->wbr_plink;
18392+ else
18393+ skip = !wbr->wbr_plink;
18394+ }
18395+ break;
18396+
18397+ default:
18398+ BUG();
18399+ }
18400+ if (wbr)
18401+ wbr_wh_read_unlock(wbr);
18402+
18403+ if (skip)
18404+ continue;
18405+
18406+ hdir = au_hi(dir, bindex);
4a4d8108 18407+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 18408+ if (wbr)
18409+ wbr_wh_write_lock(wbr);
18410+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
18411+ if (wbr)
18412+ wbr_wh_write_unlock(wbr);
4a4d8108 18413+ au_hn_imtx_unlock(hdir);
1facf9fc 18414+
18415+ if (!err && do_free) {
18416+ kfree(wbr);
18417+ br->br_wbr = NULL;
18418+ }
18419+ }
18420+
18421+ return err;
18422+}
18423+
18424+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
18425+{
18426+ int err;
18427+ unsigned int tmp;
18428+ aufs_bindex_t bend;
18429+ struct au_opt *opt;
18430+ struct au_opt_xino *opt_xino, xino;
18431+ struct au_sbinfo *sbinfo;
18432+
dece6358
AM
18433+ SiMustWriteLock(sb);
18434+
1facf9fc 18435+ err = 0;
18436+ opt_xino = NULL;
18437+ opt = opts->opt;
18438+ while (err >= 0 && opt->type != Opt_tail)
18439+ err = au_opt_simple(sb, opt++, opts);
18440+ if (err > 0)
18441+ err = 0;
18442+ else if (unlikely(err < 0))
18443+ goto out;
18444+
18445+ /* disable xino and udba temporary */
18446+ sbinfo = au_sbi(sb);
18447+ tmp = sbinfo->si_mntflags;
18448+ au_opt_clr(sbinfo->si_mntflags, XINO);
18449+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
18450+
18451+ opt = opts->opt;
18452+ while (err >= 0 && opt->type != Opt_tail)
18453+ err = au_opt_br(sb, opt++, opts);
18454+ if (err > 0)
18455+ err = 0;
18456+ else if (unlikely(err < 0))
18457+ goto out;
18458+
18459+ bend = au_sbend(sb);
18460+ if (unlikely(bend < 0)) {
18461+ err = -EINVAL;
4a4d8108 18462+ pr_err("no branches\n");
1facf9fc 18463+ goto out;
18464+ }
18465+
18466+ if (au_opt_test(tmp, XINO))
18467+ au_opt_set(sbinfo->si_mntflags, XINO);
18468+ opt = opts->opt;
18469+ while (!err && opt->type != Opt_tail)
18470+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
18471+ if (unlikely(err))
18472+ goto out;
18473+
18474+ err = au_opts_verify(sb, sb->s_flags, tmp);
18475+ if (unlikely(err))
18476+ goto out;
18477+
18478+ /* restore xino */
18479+ if (au_opt_test(tmp, XINO) && !opt_xino) {
18480+ xino.file = au_xino_def(sb);
18481+ err = PTR_ERR(xino.file);
18482+ if (IS_ERR(xino.file))
18483+ goto out;
18484+
18485+ err = au_xino_set(sb, &xino, /*remount*/0);
18486+ fput(xino.file);
18487+ if (unlikely(err))
18488+ goto out;
18489+ }
18490+
18491+ /* restore udba */
18492+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18493+ sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
4a4d8108 18494+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 18495+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 18496+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 18497+ }
18498+
18499+ out:
18500+ return err;
18501+}
18502+
18503+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
18504+{
18505+ int err, rerr;
18506+ struct inode *dir;
18507+ struct au_opt_xino *opt_xino;
18508+ struct au_opt *opt;
18509+ struct au_sbinfo *sbinfo;
18510+
dece6358
AM
18511+ SiMustWriteLock(sb);
18512+
1facf9fc 18513+ dir = sb->s_root->d_inode;
18514+ sbinfo = au_sbi(sb);
18515+ err = 0;
18516+ opt_xino = NULL;
18517+ opt = opts->opt;
18518+ while (err >= 0 && opt->type != Opt_tail) {
18519+ err = au_opt_simple(sb, opt, opts);
18520+ if (!err)
18521+ err = au_opt_br(sb, opt, opts);
18522+ if (!err)
18523+ err = au_opt_xino(sb, opt, &opt_xino, opts);
18524+ opt++;
18525+ }
18526+ if (err > 0)
18527+ err = 0;
18528+ AuTraceErr(err);
18529+ /* go on even err */
18530+
18531+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
18532+ if (unlikely(rerr && !err))
18533+ err = rerr;
18534+
18535+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
18536+ rerr = au_xib_trunc(sb);
18537+ if (unlikely(rerr && !err))
18538+ err = rerr;
18539+ }
18540+
18541+ /* will be handled by the caller */
18542+ if (!au_ftest_opts(opts->flags, REFRESH_DIR)
18543+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
18544+ au_fset_opts(opts->flags, REFRESH_DIR);
18545+
18546+ AuDbg("status 0x%x\n", opts->flags);
18547+ return err;
18548+}
18549+
18550+/* ---------------------------------------------------------------------- */
18551+
18552+unsigned int au_opt_udba(struct super_block *sb)
18553+{
18554+ return au_mntflags(sb) & AuOptMask_UDBA;
18555+}
b752ccd1
AM
18556diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
18557--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
18558+++ linux/fs/aufs/opts.h 2010-08-21 21:00:02.982333916 +0200
4a4d8108 18559@@ -0,0 +1,198 @@
1facf9fc 18560+/*
4a4d8108 18561+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18562+ *
18563+ * This program, aufs is free software; you can redistribute it and/or modify
18564+ * it under the terms of the GNU General Public License as published by
18565+ * the Free Software Foundation; either version 2 of the License, or
18566+ * (at your option) any later version.
dece6358
AM
18567+ *
18568+ * This program is distributed in the hope that it will be useful,
18569+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18570+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18571+ * GNU General Public License for more details.
18572+ *
18573+ * You should have received a copy of the GNU General Public License
18574+ * along with this program; if not, write to the Free Software
18575+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18576+ */
18577+
18578+/*
18579+ * mount options/flags
18580+ */
18581+
18582+#ifndef __AUFS_OPTS_H__
18583+#define __AUFS_OPTS_H__
18584+
18585+#ifdef __KERNEL__
18586+
dece6358 18587+#include <linux/path.h>
1facf9fc 18588+#include <linux/aufs_type.h>
18589+
dece6358
AM
18590+struct file;
18591+struct super_block;
18592+
1facf9fc 18593+/* ---------------------------------------------------------------------- */
18594+
18595+/* mount flags */
18596+#define AuOpt_XINO 1 /* external inode number bitmap
18597+ and translation table */
18598+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
18599+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
18600+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 18601+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
18602+#define AuOpt_SHWH (1 << 5) /* show whiteout */
18603+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
18604+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
18605+#define AuOpt_REFROF (1 << 8) /* unimplemented */
18606+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
18607+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
18608+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
18609+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
18610+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 18611+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 18612+
4a4d8108
AM
18613+#ifndef CONFIG_AUFS_HNOTIFY
18614+#undef AuOpt_UDBA_HNOTIFY
18615+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 18616+#endif
dece6358
AM
18617+#ifndef CONFIG_AUFS_SHWH
18618+#undef AuOpt_SHWH
18619+#define AuOpt_SHWH 0
18620+#endif
1facf9fc 18621+
18622+#define AuOpt_Def (AuOpt_XINO \
18623+ | AuOpt_UDBA_REVAL \
18624+ | AuOpt_PLINK \
18625+ /* | AuOpt_DIRPERM1 */ \
18626+ | AuOpt_WARN_PERM)
18627+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
18628+ | AuOpt_UDBA_REVAL \
4a4d8108 18629+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 18630+
18631+#define au_opt_test(flags, name) (flags & AuOpt_##name)
18632+#define au_opt_set(flags, name) do { \
18633+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
18634+ ((flags) |= AuOpt_##name); \
18635+} while (0)
18636+#define au_opt_set_udba(flags, name) do { \
18637+ (flags) &= ~AuOptMask_UDBA; \
18638+ ((flags) |= AuOpt_##name); \
18639+} while (0)
18640+#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
18641+
18642+/* ---------------------------------------------------------------------- */
18643+
18644+/* policies to select one among multiple writable branches */
18645+enum {
18646+ AuWbrCreate_TDP, /* top down parent */
18647+ AuWbrCreate_RR, /* round robin */
18648+ AuWbrCreate_MFS, /* most free space */
18649+ AuWbrCreate_MFSV, /* mfs with seconds */
18650+ AuWbrCreate_MFSRR, /* mfs then rr */
18651+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
18652+ AuWbrCreate_PMFS, /* parent and mfs */
18653+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
18654+
18655+ AuWbrCreate_Def = AuWbrCreate_TDP
18656+};
18657+
18658+enum {
18659+ AuWbrCopyup_TDP, /* top down parent */
18660+ AuWbrCopyup_BUP, /* bottom up parent */
18661+ AuWbrCopyup_BU, /* bottom up */
18662+
18663+ AuWbrCopyup_Def = AuWbrCopyup_TDP
18664+};
18665+
18666+/* ---------------------------------------------------------------------- */
18667+
18668+struct au_opt_add {
18669+ aufs_bindex_t bindex;
18670+ char *pathname;
18671+ int perm;
18672+ struct path path;
18673+};
18674+
18675+struct au_opt_del {
18676+ char *pathname;
18677+ struct path h_path;
18678+};
18679+
18680+struct au_opt_mod {
18681+ char *path;
18682+ int perm;
18683+ struct dentry *h_root;
18684+};
18685+
18686+struct au_opt_xino {
18687+ char *path;
18688+ struct file *file;
18689+};
18690+
18691+struct au_opt_xino_itrunc {
18692+ aufs_bindex_t bindex;
18693+};
18694+
18695+struct au_opt_wbr_create {
18696+ int wbr_create;
18697+ int mfs_second;
18698+ unsigned long long mfsrr_watermark;
18699+};
18700+
18701+struct au_opt {
18702+ int type;
18703+ union {
18704+ struct au_opt_xino xino;
18705+ struct au_opt_xino_itrunc xino_itrunc;
18706+ struct au_opt_add add;
18707+ struct au_opt_del del;
18708+ struct au_opt_mod mod;
18709+ int dirwh;
18710+ int rdcache;
18711+ unsigned int rdblk;
18712+ unsigned int rdhash;
18713+ int udba;
18714+ struct au_opt_wbr_create wbr_create;
18715+ int wbr_copyup;
18716+ };
18717+};
18718+
18719+/* opts flags */
18720+#define AuOpts_REMOUNT 1
18721+#define AuOpts_REFRESH_DIR (1 << 1)
18722+#define AuOpts_REFRESH_NONDIR (1 << 2)
18723+#define AuOpts_TRUNC_XIB (1 << 3)
4a4d8108 18724+#define AuOpts_REFRESH_DYAOP (1 << 4)
1facf9fc 18725+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
18726+#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
18727+#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
18728+
18729+struct au_opts {
18730+ struct au_opt *opt;
18731+ int max_opt;
18732+
18733+ unsigned int given_udba;
18734+ unsigned int flags;
18735+ unsigned long sb_flags;
18736+};
18737+
18738+/* ---------------------------------------------------------------------- */
18739+
18740+const char *au_optstr_br_perm(int brperm);
18741+const char *au_optstr_udba(int udba);
18742+const char *au_optstr_wbr_copyup(int wbr_copyup);
18743+const char *au_optstr_wbr_create(int wbr_create);
18744+
18745+void au_opts_free(struct au_opts *opts);
18746+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
18747+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18748+ unsigned int pending);
18749+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
18750+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
18751+
18752+unsigned int au_opt_udba(struct super_block *sb);
18753+
18754+/* ---------------------------------------------------------------------- */
18755+
18756+#endif /* __KERNEL__ */
18757+#endif /* __AUFS_OPTS_H__ */
b752ccd1
AM
18758diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
18759--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
18760+++ linux/fs/aufs/plink.c 2010-08-21 21:00:02.982333916 +0200
18761@@ -0,0 +1,451 @@
1facf9fc 18762+/*
4a4d8108 18763+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18764+ *
18765+ * This program, aufs is free software; you can redistribute it and/or modify
18766+ * it under the terms of the GNU General Public License as published by
18767+ * the Free Software Foundation; either version 2 of the License, or
18768+ * (at your option) any later version.
dece6358
AM
18769+ *
18770+ * This program is distributed in the hope that it will be useful,
18771+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18772+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18773+ * GNU General Public License for more details.
18774+ *
18775+ * You should have received a copy of the GNU General Public License
18776+ * along with this program; if not, write to the Free Software
18777+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18778+ */
18779+
18780+/*
18781+ * pseudo-link
18782+ */
18783+
18784+#include "aufs.h"
18785+
18786+/*
18787+ * during a user process maintains the pseudo-links,
18788+ * prohibit adding a new plink and branch manipulation.
18789+ */
4a4d8108 18790+void au_plink_maint_block(struct super_block *sb)
1facf9fc 18791+{
18792+ struct au_sbinfo *sbi = au_sbi(sb);
dece6358
AM
18793+
18794+ SiMustAnyLock(sb);
18795+
1facf9fc 18796+ /* gave up wake_up_bit() */
4a4d8108
AM
18797+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint);
18798+}
18799+
18800+void au_plink_maint_leave(struct file *file)
18801+{
18802+ struct au_sbinfo *sbinfo;
18803+ int iam;
18804+
18805+ AuDebugOn(atomic_long_read(&file->f_count));
18806+
18807+ sbinfo = au_sbi(file->f_dentry->d_sb);
18808+ spin_lock(&sbinfo->si_plink_maint_lock);
18809+ iam = (sbinfo->si_plink_maint == file);
18810+ if (iam)
18811+ sbinfo->si_plink_maint = NULL;
18812+ spin_unlock(&sbinfo->si_plink_maint_lock);
18813+ if (iam)
18814+ wake_up_all(&sbinfo->si_plink_wq);
18815+}
18816+
18817+static int au_plink_maint_enter(struct file *file)
18818+{
18819+ int err;
18820+ struct super_block *sb;
18821+ struct au_sbinfo *sbinfo;
18822+
18823+ err = 0;
18824+ sb = file->f_dentry->d_sb;
18825+ sbinfo = au_sbi(sb);
18826+ /* make sure i am the only one in this fs */
18827+ si_write_lock(sb);
18828+ /* spin_lock(&sbinfo->si_plink_maint_lock); */
18829+ if (!sbinfo->si_plink_maint)
18830+ sbinfo->si_plink_maint = file;
18831+ else
18832+ err = -EBUSY;
18833+ /* spin_unlock(&sbinfo->si_plink_maint_lock); */
18834+ si_write_unlock(sb);
18835+
18836+ return err;
1facf9fc 18837+}
18838+
18839+/* ---------------------------------------------------------------------- */
18840+
18841+struct pseudo_link {
4a4d8108
AM
18842+ union {
18843+ struct list_head list;
18844+ struct rcu_head rcu;
18845+ };
1facf9fc 18846+ struct inode *inode;
18847+};
18848+
18849+#ifdef CONFIG_AUFS_DEBUG
18850+void au_plink_list(struct super_block *sb)
18851+{
18852+ struct au_sbinfo *sbinfo;
18853+ struct list_head *plink_list;
18854+ struct pseudo_link *plink;
18855+
dece6358
AM
18856+ SiMustAnyLock(sb);
18857+
1facf9fc 18858+ sbinfo = au_sbi(sb);
18859+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18860+
18861+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18862+ rcu_read_lock();
18863+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 18864+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 18865+ rcu_read_unlock();
1facf9fc 18866+}
18867+#endif
18868+
18869+/* is the inode pseudo-linked? */
18870+int au_plink_test(struct inode *inode)
18871+{
18872+ int found;
18873+ struct au_sbinfo *sbinfo;
18874+ struct list_head *plink_list;
18875+ struct pseudo_link *plink;
18876+
18877+ sbinfo = au_sbi(inode->i_sb);
dece6358 18878+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 18879+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
18880+
18881+ found = 0;
18882+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18883+ rcu_read_lock();
18884+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 18885+ if (plink->inode == inode) {
18886+ found = 1;
18887+ break;
18888+ }
4a4d8108 18889+ rcu_read_unlock();
1facf9fc 18890+ return found;
18891+}
18892+
18893+/* ---------------------------------------------------------------------- */
18894+
18895+/*
18896+ * generate a name for plink.
18897+ * the file will be stored under AUFS_WH_PLINKDIR.
18898+ */
18899+/* 20 is max digits length of ulong 64 */
18900+#define PLINK_NAME_LEN ((20 + 1) * 2)
18901+
18902+static int plink_name(char *name, int len, struct inode *inode,
18903+ aufs_bindex_t bindex)
18904+{
18905+ int rlen;
18906+ struct inode *h_inode;
18907+
18908+ h_inode = au_h_iptr(inode, bindex);
18909+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
18910+ return rlen;
18911+}
18912+
18913+/* lookup the plink-ed @inode under the branch at @bindex */
18914+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
18915+{
18916+ struct dentry *h_dentry, *h_parent;
18917+ struct au_branch *br;
18918+ struct inode *h_dir;
18919+ char a[PLINK_NAME_LEN];
18920+ struct qstr tgtname = {
18921+ .name = a
18922+ };
18923+
18924+ br = au_sbr(inode->i_sb, bindex);
18925+ h_parent = br->br_wbr->wbr_plink;
18926+ h_dir = h_parent->d_inode;
18927+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
18928+
18929+ /* always superio. */
18930+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
18931+ h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
18932+ mutex_unlock(&h_dir->i_mutex);
18933+ return h_dentry;
18934+}
18935+
18936+/* create a pseudo-link */
18937+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
18938+ struct dentry *h_dentry, struct au_branch *br)
18939+{
18940+ int err;
18941+ struct path h_path = {
18942+ .mnt = br->br_mnt
18943+ };
18944+ struct inode *h_dir;
18945+
18946+ h_dir = h_parent->d_inode;
18947+ again:
18948+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
18949+ err = PTR_ERR(h_path.dentry);
18950+ if (IS_ERR(h_path.dentry))
18951+ goto out;
18952+
18953+ err = 0;
18954+ /* wh.plink dir is not monitored */
18955+ if (h_path.dentry->d_inode
18956+ && h_path.dentry->d_inode != h_dentry->d_inode) {
18957+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
18958+ dput(h_path.dentry);
18959+ h_path.dentry = NULL;
18960+ if (!err)
18961+ goto again;
18962+ }
18963+ if (!err && !h_path.dentry->d_inode)
18964+ err = vfsub_link(h_dentry, h_dir, &h_path);
18965+ dput(h_path.dentry);
18966+
18967+ out:
18968+ return err;
18969+}
18970+
18971+struct do_whplink_args {
18972+ int *errp;
18973+ struct qstr *tgt;
18974+ struct dentry *h_parent;
18975+ struct dentry *h_dentry;
18976+ struct au_branch *br;
18977+};
18978+
18979+static void call_do_whplink(void *args)
18980+{
18981+ struct do_whplink_args *a = args;
18982+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
18983+}
18984+
18985+static int whplink(struct dentry *h_dentry, struct inode *inode,
18986+ aufs_bindex_t bindex, struct au_branch *br)
18987+{
18988+ int err, wkq_err;
18989+ struct au_wbr *wbr;
18990+ struct dentry *h_parent;
18991+ struct inode *h_dir;
18992+ char a[PLINK_NAME_LEN];
18993+ struct qstr tgtname = {
18994+ .name = a
18995+ };
18996+
18997+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
18998+ h_parent = wbr->wbr_plink;
18999+ h_dir = h_parent->d_inode;
19000+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
19001+
19002+ /* always superio. */
19003+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
b752ccd1 19004+ if (current_fsuid()) {
1facf9fc 19005+ struct do_whplink_args args = {
19006+ .errp = &err,
19007+ .tgt = &tgtname,
19008+ .h_parent = h_parent,
19009+ .h_dentry = h_dentry,
19010+ .br = br
19011+ };
19012+ wkq_err = au_wkq_wait(call_do_whplink, &args);
19013+ if (unlikely(wkq_err))
19014+ err = wkq_err;
19015+ } else
19016+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
19017+ mutex_unlock(&h_dir->i_mutex);
19018+
19019+ return err;
19020+}
19021+
19022+/* free a single plink */
19023+static void do_put_plink(struct pseudo_link *plink, int do_del)
19024+{
1facf9fc 19025+ if (do_del)
19026+ list_del(&plink->list);
4a4d8108
AM
19027+ iput(plink->inode);
19028+ kfree(plink);
19029+}
19030+
19031+static void do_put_plink_rcu(struct rcu_head *rcu)
19032+{
19033+ struct pseudo_link *plink;
19034+
19035+ plink = container_of(rcu, struct pseudo_link, rcu);
19036+ iput(plink->inode);
1facf9fc 19037+ kfree(plink);
19038+}
19039+
19040+/*
19041+ * create a new pseudo-link for @h_dentry on @bindex.
19042+ * the linked inode is held in aufs @inode.
19043+ */
19044+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
19045+ struct dentry *h_dentry)
19046+{
19047+ struct super_block *sb;
19048+ struct au_sbinfo *sbinfo;
19049+ struct list_head *plink_list;
4a4d8108 19050+ struct pseudo_link *plink, *tmp;
1facf9fc 19051+ int found, err, cnt;
19052+
19053+ sb = inode->i_sb;
19054+ sbinfo = au_sbi(sb);
19055+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
19056+
1facf9fc 19057+ cnt = 0;
19058+ found = 0;
19059+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19060+ rcu_read_lock();
19061+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 19062+ cnt++;
19063+ if (plink->inode == inode) {
19064+ found = 1;
19065+ break;
19066+ }
19067+ }
4a4d8108
AM
19068+ rcu_read_unlock();
19069+ if (found)
1facf9fc 19070+ return;
4a4d8108
AM
19071+
19072+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
19073+ if (tmp)
19074+ tmp->inode = au_igrab(inode);
19075+ else {
19076+ err = -ENOMEM;
19077+ goto out;
1facf9fc 19078+ }
19079+
4a4d8108
AM
19080+ spin_lock(&sbinfo->si_plink.spin);
19081+ list_for_each_entry(plink, plink_list, list) {
19082+ if (plink->inode == inode) {
19083+ found = 1;
19084+ break;
19085+ }
1facf9fc 19086+ }
4a4d8108
AM
19087+ if (!found)
19088+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 19089+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
19090+ if (!found) {
19091+ cnt++;
19092+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
19093+ "unexpectedly many pseudo links, %d\n", cnt);
19094+ au_plink_maint_block(sb);
1facf9fc 19095+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
19096+ } else {
19097+ do_put_plink(tmp, 0);
19098+ return;
1facf9fc 19099+ }
19100+
4a4d8108 19101+out:
1facf9fc 19102+ if (unlikely(err)) {
4a4d8108
AM
19103+ pr_warning("err %d, damaged pseudo link.\n", err);
19104+ if (tmp) {
19105+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
19106+ call_rcu(&tmp->rcu, do_put_plink_rcu);
19107+ }
1facf9fc 19108+ }
19109+}
19110+
19111+/* free all plinks */
19112+void au_plink_put(struct super_block *sb)
19113+{
19114+ struct au_sbinfo *sbinfo;
19115+ struct list_head *plink_list;
19116+ struct pseudo_link *plink, *tmp;
19117+
dece6358
AM
19118+ SiMustWriteLock(sb);
19119+
1facf9fc 19120+ sbinfo = au_sbi(sb);
19121+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
19122+
19123+ plink_list = &sbinfo->si_plink.head;
19124+ /* no spin_lock since sbinfo is write-locked */
19125+ list_for_each_entry_safe(plink, tmp, plink_list, list)
19126+ do_put_plink(plink, 0);
19127+ INIT_LIST_HEAD(plink_list);
19128+}
19129+
19130+/* free the plinks on a branch specified by @br_id */
19131+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
19132+{
19133+ struct au_sbinfo *sbinfo;
19134+ struct list_head *plink_list;
19135+ struct pseudo_link *plink, *tmp;
19136+ struct inode *inode;
19137+ aufs_bindex_t bstart, bend, bindex;
19138+ unsigned char do_put;
19139+
dece6358
AM
19140+ SiMustWriteLock(sb);
19141+
1facf9fc 19142+ sbinfo = au_sbi(sb);
19143+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
19144+
19145+ plink_list = &sbinfo->si_plink.head;
19146+ /* no spin_lock since sbinfo is write-locked */
19147+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
19148+ do_put = 0;
19149+ inode = au_igrab(plink->inode);
19150+ ii_write_lock_child(inode);
19151+ bstart = au_ibstart(inode);
19152+ bend = au_ibend(inode);
19153+ if (bstart >= 0) {
19154+ for (bindex = bstart; bindex <= bend; bindex++) {
19155+ if (!au_h_iptr(inode, bindex)
19156+ || au_ii_br_id(inode, bindex) != br_id)
19157+ continue;
19158+ au_set_h_iptr(inode, bindex, NULL, 0);
19159+ do_put = 1;
19160+ break;
19161+ }
19162+ } else
19163+ do_put_plink(plink, 1);
19164+
dece6358
AM
19165+ if (do_put) {
19166+ for (bindex = bstart; bindex <= bend; bindex++)
19167+ if (au_h_iptr(inode, bindex)) {
19168+ do_put = 0;
19169+ break;
19170+ }
19171+ if (do_put)
19172+ do_put_plink(plink, 1);
19173+ }
19174+ ii_write_unlock(inode);
19175+ iput(inode);
19176+ }
19177+}
1308ab2a 19178+
19179+/* ---------------------------------------------------------------------- */
19180+
19181+long au_plink_ioctl(struct file *file, unsigned int cmd)
19182+{
19183+ long err;
19184+ struct super_block *sb;
1308ab2a 19185+
19186+ err = -EACCES;
19187+ if (!capable(CAP_SYS_ADMIN))
19188+ goto out;
19189+
19190+ err = 0;
19191+ sb = file->f_dentry->d_sb;
1308ab2a 19192+ switch (cmd) {
19193+ case AUFS_CTL_PLINK_MAINT:
19194+ /*
19195+ * pseudo-link maintenance mode,
19196+ * cleared by aufs_release_dir()
19197+ */
4a4d8108 19198+ err = au_plink_maint_enter(file);
1308ab2a 19199+ break;
19200+ case AUFS_CTL_PLINK_CLEAN:
19201+ aufs_write_lock(sb->s_root);
b752ccd1 19202+ if (au_opt_test(au_mntflags(sb), PLINK))
1308ab2a 19203+ au_plink_put(sb);
19204+ aufs_write_unlock(sb->s_root);
19205+ break;
19206+ default:
4a4d8108 19207+ /* err = -ENOTTY; */
1308ab2a 19208+ err = -EINVAL;
19209+ }
19210+ out:
19211+ return err;
19212+}
b752ccd1
AM
19213diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
19214--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
19215+++ linux/fs/aufs/poll.c 2010-08-21 21:00:02.982333916 +0200
dece6358
AM
19216@@ -0,0 +1,56 @@
19217+/*
4a4d8108 19218+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
19219+ *
19220+ * This program, aufs is free software; you can redistribute it and/or modify
19221+ * it under the terms of the GNU General Public License as published by
19222+ * the Free Software Foundation; either version 2 of the License, or
19223+ * (at your option) any later version.
19224+ *
19225+ * This program is distributed in the hope that it will be useful,
19226+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19227+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19228+ * GNU General Public License for more details.
19229+ *
19230+ * You should have received a copy of the GNU General Public License
19231+ * along with this program; if not, write to the Free Software
19232+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19233+ */
19234+
1308ab2a 19235+/*
19236+ * poll operation
19237+ * There is only one filesystem which implements ->poll operation, currently.
19238+ */
19239+
19240+#include "aufs.h"
19241+
19242+unsigned int aufs_poll(struct file *file, poll_table *wait)
19243+{
19244+ unsigned int mask;
19245+ int err;
19246+ struct file *h_file;
19247+ struct dentry *dentry;
19248+ struct super_block *sb;
19249+
19250+ /* We should pretend an error happened. */
19251+ mask = POLLERR /* | POLLIN | POLLOUT */;
19252+ dentry = file->f_dentry;
19253+ sb = dentry->d_sb;
19254+ si_read_lock(sb, AuLock_FLUSH);
19255+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
19256+ if (unlikely(err))
19257+ goto out;
19258+
19259+ /* it is not an error if h_file has no operation */
19260+ mask = DEFAULT_POLLMASK;
4a4d8108 19261+ h_file = au_hf_top(file);
1308ab2a 19262+ if (h_file->f_op && h_file->f_op->poll)
19263+ mask = h_file->f_op->poll(h_file, wait);
19264+
19265+ di_read_unlock(dentry, AuLock_IR);
19266+ fi_read_unlock(file);
19267+
19268+ out:
19269+ si_read_unlock(sb);
19270+ AuTraceErr((int)mask);
19271+ return mask;
19272+}
b752ccd1
AM
19273diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
19274--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
19275+++ linux/fs/aufs/rdu.c 2010-08-21 21:00:02.982333916 +0200
19276@@ -0,0 +1,377 @@
1308ab2a 19277+/*
4a4d8108 19278+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 19279+ *
19280+ * This program, aufs is free software; you can redistribute it and/or modify
19281+ * it under the terms of the GNU General Public License as published by
19282+ * the Free Software Foundation; either version 2 of the License, or
19283+ * (at your option) any later version.
19284+ *
19285+ * This program is distributed in the hope that it will be useful,
19286+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19287+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19288+ * GNU General Public License for more details.
19289+ *
19290+ * You should have received a copy of the GNU General Public License
19291+ * along with this program; if not, write to the Free Software
19292+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19293+ */
19294+
19295+/*
19296+ * readdir in userspace.
19297+ */
19298+
b752ccd1 19299+#include <linux/compat.h>
4a4d8108 19300+#include <linux/fs_stack.h>
1308ab2a 19301+#include <linux/security.h>
19302+#include <linux/uaccess.h>
19303+#include <linux/aufs_type.h>
19304+#include "aufs.h"
19305+
19306+/* bits for struct aufs_rdu.flags */
19307+#define AuRdu_CALLED 1
19308+#define AuRdu_CONT (1 << 1)
19309+#define AuRdu_FULL (1 << 2)
19310+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
19311+#define au_fset_rdu(flags, name) { (flags) |= AuRdu_##name; }
19312+#define au_fclr_rdu(flags, name) { (flags) &= ~AuRdu_##name; }
19313+
19314+struct au_rdu_arg {
19315+ struct aufs_rdu *rdu;
19316+ union au_rdu_ent_ul ent;
19317+ unsigned long end;
19318+
19319+ struct super_block *sb;
19320+ int err;
19321+};
19322+
19323+static int au_rdu_fill(void *__arg, const char *name, int nlen,
19324+ loff_t offset, u64 h_ino, unsigned int d_type)
19325+{
19326+ int err, len;
19327+ struct au_rdu_arg *arg = __arg;
19328+ struct aufs_rdu *rdu = arg->rdu;
19329+ struct au_rdu_ent ent;
19330+
19331+ err = 0;
19332+ arg->err = 0;
19333+ au_fset_rdu(rdu->cookie.flags, CALLED);
19334+ len = au_rdu_len(nlen);
19335+ if (arg->ent.ul + len < arg->end) {
19336+ ent.ino = h_ino;
19337+ ent.bindex = rdu->cookie.bindex;
19338+ ent.type = d_type;
19339+ ent.nlen = nlen;
4a4d8108
AM
19340+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
19341+ ent.type = DT_UNKNOWN;
1308ab2a 19342+
19343+ err = -EFAULT;
19344+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
19345+ goto out;
19346+ if (copy_to_user(arg->ent.e->name, name, nlen))
19347+ goto out;
19348+ /* the terminating NULL */
19349+ if (__put_user(0, arg->ent.e->name + nlen))
19350+ goto out;
19351+ err = 0;
19352+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
19353+ arg->ent.ul += len;
19354+ rdu->rent++;
19355+ } else {
19356+ err = -EFAULT;
19357+ au_fset_rdu(rdu->cookie.flags, FULL);
19358+ rdu->full = 1;
19359+ rdu->tail = arg->ent;
19360+ }
19361+
19362+ out:
19363+ /* AuTraceErr(err); */
19364+ return err;
19365+}
19366+
19367+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
19368+{
19369+ int err;
19370+ loff_t offset;
19371+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
19372+
19373+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
19374+ err = offset;
19375+ if (unlikely(offset != cookie->h_pos))
19376+ goto out;
19377+
19378+ err = 0;
19379+ do {
19380+ arg->err = 0;
19381+ au_fclr_rdu(cookie->flags, CALLED);
19382+ /* smp_mb(); */
19383+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
19384+ if (err >= 0)
19385+ err = arg->err;
19386+ } while (!err
19387+ && au_ftest_rdu(cookie->flags, CALLED)
19388+ && !au_ftest_rdu(cookie->flags, FULL));
19389+ cookie->h_pos = h_file->f_pos;
19390+
19391+ out:
19392+ AuTraceErr(err);
19393+ return err;
19394+}
19395+
19396+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
19397+{
19398+ int err;
19399+ aufs_bindex_t bend;
19400+ struct au_rdu_arg arg;
19401+ struct dentry *dentry;
19402+ struct inode *inode;
19403+ struct file *h_file;
19404+ struct au_rdu_cookie *cookie = &rdu->cookie;
19405+
19406+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
19407+ if (unlikely(err)) {
19408+ err = -EFAULT;
19409+ AuTraceErr(err);
19410+ goto out;
19411+ }
19412+ rdu->rent = 0;
19413+ rdu->tail = rdu->ent;
19414+ rdu->full = 0;
19415+ arg.rdu = rdu;
19416+ arg.ent = rdu->ent;
19417+ arg.end = arg.ent.ul;
19418+ arg.end += rdu->sz;
19419+
19420+ err = -ENOTDIR;
19421+ if (unlikely(!file->f_op || !file->f_op->readdir))
19422+ goto out;
19423+
19424+ err = security_file_permission(file, MAY_READ);
19425+ AuTraceErr(err);
19426+ if (unlikely(err))
19427+ goto out;
19428+
19429+ dentry = file->f_dentry;
19430+ inode = dentry->d_inode;
19431+#if 1
19432+ mutex_lock(&inode->i_mutex);
19433+#else
19434+ err = mutex_lock_killable(&inode->i_mutex);
19435+ AuTraceErr(err);
19436+ if (unlikely(err))
19437+ goto out;
19438+#endif
19439+ err = -ENOENT;
19440+ if (unlikely(IS_DEADDIR(inode)))
19441+ goto out_mtx;
19442+
19443+ arg.sb = inode->i_sb;
19444+ si_read_lock(arg.sb, AuLock_FLUSH);
19445+ fi_read_lock(file);
19446+
19447+ err = -EAGAIN;
19448+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
19449+ && cookie->generation != au_figen(file)))
19450+ goto out_unlock;
19451+
19452+ err = 0;
19453+ if (!rdu->blk) {
19454+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
19455+ if (!rdu->blk)
19456+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
19457+ }
19458+ bend = au_fbstart(file);
19459+ if (cookie->bindex < bend)
19460+ cookie->bindex = bend;
4a4d8108 19461+ bend = au_fbend_dir(file);
1308ab2a 19462+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
19463+ for (; !err && cookie->bindex <= bend;
19464+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 19465+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 19466+ if (!h_file)
19467+ continue;
19468+
19469+ au_fclr_rdu(cookie->flags, FULL);
19470+ err = au_rdu_do(h_file, &arg);
19471+ AuTraceErr(err);
19472+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
19473+ break;
19474+ }
19475+ AuDbg("rent %llu\n", rdu->rent);
19476+
19477+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
19478+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
19479+ au_fset_rdu(cookie->flags, CONT);
19480+ cookie->generation = au_figen(file);
19481+ }
19482+
19483+ ii_read_lock_child(inode);
19484+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
19485+ ii_read_unlock(inode);
19486+
19487+ out_unlock:
19488+ fi_read_unlock(file);
19489+ si_read_unlock(arg.sb);
19490+ out_mtx:
19491+ mutex_unlock(&inode->i_mutex);
19492+ out:
19493+ AuTraceErr(err);
19494+ return err;
19495+}
19496+
19497+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
19498+{
19499+ int err;
19500+ ino_t ino;
19501+ unsigned long long nent;
19502+ union au_rdu_ent_ul *u;
19503+ struct au_rdu_ent ent;
19504+ struct super_block *sb;
19505+
19506+ err = 0;
19507+ nent = rdu->nent;
19508+ u = &rdu->ent;
19509+ sb = file->f_dentry->d_sb;
19510+ si_read_lock(sb, AuLock_FLUSH);
19511+ while (nent-- > 0) {
1308ab2a 19512+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
19513+ if (!err)
19514+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 19515+ if (unlikely(err)) {
19516+ err = -EFAULT;
19517+ AuTraceErr(err);
19518+ break;
19519+ }
19520+
19521+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
19522+ if (!ent.wh)
19523+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
19524+ else
19525+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
19526+ &ino);
19527+ if (unlikely(err)) {
19528+ AuTraceErr(err);
19529+ break;
19530+ }
19531+
19532+ err = __put_user(ino, &u->e->ino);
19533+ if (unlikely(err)) {
19534+ err = -EFAULT;
19535+ AuTraceErr(err);
19536+ break;
19537+ }
19538+ u->ul += au_rdu_len(ent.nlen);
19539+ }
19540+ si_read_unlock(sb);
19541+
19542+ return err;
19543+}
19544+
19545+/* ---------------------------------------------------------------------- */
19546+
19547+static int au_rdu_verify(struct aufs_rdu *rdu)
19548+{
b752ccd1 19549+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 19550+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 19551+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 19552+ rdu->blk,
19553+ rdu->rent, rdu->shwh, rdu->full,
19554+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
19555+ rdu->cookie.generation);
dece6358 19556+
b752ccd1 19557+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 19558+ return 0;
dece6358 19559+
b752ccd1
AM
19560+ AuDbg("%u:%u\n",
19561+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 19562+ return -EINVAL;
19563+}
19564+
19565+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 19566+{
1308ab2a 19567+ long err, e;
19568+ struct aufs_rdu rdu;
19569+ void __user *p = (void __user *)arg;
dece6358 19570+
1308ab2a 19571+ err = copy_from_user(&rdu, p, sizeof(rdu));
19572+ if (unlikely(err)) {
19573+ err = -EFAULT;
19574+ AuTraceErr(err);
19575+ goto out;
19576+ }
19577+ err = au_rdu_verify(&rdu);
dece6358
AM
19578+ if (unlikely(err))
19579+ goto out;
19580+
1308ab2a 19581+ switch (cmd) {
19582+ case AUFS_CTL_RDU:
19583+ err = au_rdu(file, &rdu);
19584+ if (unlikely(err))
19585+ break;
dece6358 19586+
1308ab2a 19587+ e = copy_to_user(p, &rdu, sizeof(rdu));
19588+ if (unlikely(e)) {
19589+ err = -EFAULT;
19590+ AuTraceErr(err);
19591+ }
19592+ break;
19593+ case AUFS_CTL_RDU_INO:
19594+ err = au_rdu_ino(file, &rdu);
19595+ break;
19596+
19597+ default:
4a4d8108 19598+ /* err = -ENOTTY; */
1308ab2a 19599+ err = -EINVAL;
19600+ }
dece6358
AM
19601+
19602+ out:
1308ab2a 19603+ AuTraceErr(err);
19604+ return err;
1facf9fc 19605+}
b752ccd1
AM
19606+
19607+#ifdef CONFIG_COMPAT
19608+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
19609+{
19610+ long err, e;
19611+ struct aufs_rdu rdu;
19612+ void __user *p = compat_ptr(arg);
19613+
19614+ /* todo: get_user()? */
19615+ err = copy_from_user(&rdu, p, sizeof(rdu));
19616+ if (unlikely(err)) {
19617+ err = -EFAULT;
19618+ AuTraceErr(err);
19619+ goto out;
19620+ }
19621+ rdu.ent.e = compat_ptr(rdu.ent.ul);
19622+ err = au_rdu_verify(&rdu);
19623+ if (unlikely(err))
19624+ goto out;
19625+
19626+ switch (cmd) {
19627+ case AUFS_CTL_RDU:
19628+ err = au_rdu(file, &rdu);
19629+ if (unlikely(err))
19630+ break;
19631+
19632+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
19633+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
19634+ e = copy_to_user(p, &rdu, sizeof(rdu));
19635+ if (unlikely(e)) {
19636+ err = -EFAULT;
19637+ AuTraceErr(err);
19638+ }
19639+ break;
19640+ case AUFS_CTL_RDU_INO:
19641+ err = au_rdu_ino(file, &rdu);
19642+ break;
19643+
19644+ default:
19645+ /* err = -ENOTTY; */
19646+ err = -EINVAL;
19647+ }
19648+
19649+ out:
19650+ AuTraceErr(err);
19651+ return err;
19652+}
19653+#endif
19654diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
19655--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
19656+++ linux/fs/aufs/rwsem.h 2010-08-21 21:00:02.982333916 +0200
4a4d8108 19657@@ -0,0 +1,187 @@
1facf9fc 19658+/*
4a4d8108 19659+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19660+ *
19661+ * This program, aufs is free software; you can redistribute it and/or modify
19662+ * it under the terms of the GNU General Public License as published by
19663+ * the Free Software Foundation; either version 2 of the License, or
19664+ * (at your option) any later version.
dece6358
AM
19665+ *
19666+ * This program is distributed in the hope that it will be useful,
19667+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19668+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19669+ * GNU General Public License for more details.
19670+ *
19671+ * You should have received a copy of the GNU General Public License
19672+ * along with this program; if not, write to the Free Software
19673+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19674+ */
19675+
19676+/*
19677+ * simple read-write semaphore wrappers
19678+ */
19679+
19680+#ifndef __AUFS_RWSEM_H__
19681+#define __AUFS_RWSEM_H__
19682+
19683+#ifdef __KERNEL__
19684+
dece6358 19685+#include <linux/rwsem.h>
4a4d8108 19686+#include "debug.h"
dece6358
AM
19687+
19688+struct au_rwsem {
19689+ struct rw_semaphore rwsem;
19690+#ifdef CONFIG_AUFS_DEBUG
19691+ /* just for debugging, not almighty counter */
19692+ atomic_t rcnt, wcnt;
19693+#endif
19694+};
19695+
19696+#ifdef CONFIG_AUFS_DEBUG
19697+#define AuDbgCntInit(rw) do { \
19698+ atomic_set(&(rw)->rcnt, 0); \
19699+ atomic_set(&(rw)->wcnt, 0); \
19700+ smp_mb(); /* atomic set */ \
19701+} while (0)
19702+
19703+#define AuDbgRcntInc(rw) atomic_inc_return(&(rw)->rcnt)
19704+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
19705+#define AuDbgWcntInc(rw) WARN_ON(atomic_inc_return(&(rw)->wcnt) > 1)
19706+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
19707+#else
19708+#define AuDbgCntInit(rw) do {} while (0)
19709+#define AuDbgRcntInc(rw) do {} while (0)
19710+#define AuDbgRcntDec(rw) do {} while (0)
19711+#define AuDbgWcntInc(rw) do {} while (0)
19712+#define AuDbgWcntDec(rw) do {} while (0)
19713+#endif /* CONFIG_AUFS_DEBUG */
19714+
19715+/* to debug easier, do not make them inlined functions */
19716+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
19717+/* rwsem_is_locked() is unusable */
19718+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
19719+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
19720+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
19721+ && atomic_read(&(rw)->wcnt) <= 0)
19722+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
19723+ || atomic_read(&(rw)->wcnt))
19724+
19725+static inline void au_rw_init(struct au_rwsem *rw)
19726+{
19727+ AuDbgCntInit(rw);
19728+ init_rwsem(&rw->rwsem);
19729+}
19730+
19731+static inline void au_rw_init_wlock(struct au_rwsem *rw)
19732+{
19733+ au_rw_init(rw);
19734+ down_write(&rw->rwsem);
19735+ AuDbgWcntInc(rw);
19736+}
19737+
19738+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
19739+ unsigned int lsc)
19740+{
19741+ au_rw_init(rw);
19742+ down_write_nested(&rw->rwsem, lsc);
19743+ AuDbgWcntInc(rw);
19744+}
19745+
19746+static inline void au_rw_read_lock(struct au_rwsem *rw)
19747+{
19748+ down_read(&rw->rwsem);
19749+ AuDbgRcntInc(rw);
19750+}
19751+
19752+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
19753+{
19754+ down_read_nested(&rw->rwsem, lsc);
19755+ AuDbgRcntInc(rw);
19756+}
19757+
19758+static inline void au_rw_read_unlock(struct au_rwsem *rw)
19759+{
19760+ AuRwMustReadLock(rw);
19761+ AuDbgRcntDec(rw);
19762+ up_read(&rw->rwsem);
19763+}
19764+
19765+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
19766+{
19767+ AuRwMustWriteLock(rw);
19768+ AuDbgRcntInc(rw);
19769+ AuDbgWcntDec(rw);
19770+ downgrade_write(&rw->rwsem);
19771+}
19772+
19773+static inline void au_rw_write_lock(struct au_rwsem *rw)
19774+{
19775+ down_write(&rw->rwsem);
19776+ AuDbgWcntInc(rw);
19777+}
19778+
19779+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
19780+ unsigned int lsc)
19781+{
19782+ down_write_nested(&rw->rwsem, lsc);
19783+ AuDbgWcntInc(rw);
19784+}
1facf9fc 19785+
dece6358
AM
19786+static inline void au_rw_write_unlock(struct au_rwsem *rw)
19787+{
19788+ AuRwMustWriteLock(rw);
19789+ AuDbgWcntDec(rw);
19790+ up_write(&rw->rwsem);
19791+}
19792+
19793+/* why is not _nested version defined */
19794+static inline int au_rw_read_trylock(struct au_rwsem *rw)
19795+{
19796+ int ret = down_read_trylock(&rw->rwsem);
19797+ if (ret)
19798+ AuDbgRcntInc(rw);
19799+ return ret;
19800+}
19801+
19802+static inline int au_rw_write_trylock(struct au_rwsem *rw)
19803+{
19804+ int ret = down_write_trylock(&rw->rwsem);
19805+ if (ret)
19806+ AuDbgWcntInc(rw);
19807+ return ret;
19808+}
19809+
19810+#undef AuDbgCntInit
19811+#undef AuDbgRcntInc
19812+#undef AuDbgRcntDec
19813+#undef AuDbgWcntInc
19814+#undef AuDbgWcntDec
1facf9fc 19815+
19816+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
19817+static inline void prefix##_read_lock(param) \
dece6358 19818+{ au_rw_read_lock(rwsem); } \
1facf9fc 19819+static inline void prefix##_write_lock(param) \
dece6358 19820+{ au_rw_write_lock(rwsem); } \
1facf9fc 19821+static inline int prefix##_read_trylock(param) \
dece6358 19822+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 19823+static inline int prefix##_write_trylock(param) \
dece6358 19824+{ return au_rw_write_trylock(rwsem); }
1facf9fc 19825+/* why is not _nested version defined */
19826+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 19827+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 19828+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 19829+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 19830+
19831+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
19832+static inline void prefix##_read_unlock(param) \
dece6358 19833+{ au_rw_read_unlock(rwsem); } \
1facf9fc 19834+static inline void prefix##_write_unlock(param) \
dece6358 19835+{ au_rw_write_unlock(rwsem); } \
1facf9fc 19836+static inline void prefix##_downgrade_lock(param) \
dece6358 19837+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 19838+
19839+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
19840+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
19841+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
19842+
19843+#endif /* __KERNEL__ */
19844+#endif /* __AUFS_RWSEM_H__ */
b752ccd1
AM
19845diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
19846--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
19847+++ linux/fs/aufs/sbinfo.c 2010-08-21 21:00:02.982333916 +0200
19848@@ -0,0 +1,269 @@
1facf9fc 19849+/*
4a4d8108 19850+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19851+ *
19852+ * This program, aufs is free software; you can redistribute it and/or modify
19853+ * it under the terms of the GNU General Public License as published by
19854+ * the Free Software Foundation; either version 2 of the License, or
19855+ * (at your option) any later version.
dece6358
AM
19856+ *
19857+ * This program is distributed in the hope that it will be useful,
19858+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19859+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19860+ * GNU General Public License for more details.
19861+ *
19862+ * You should have received a copy of the GNU General Public License
19863+ * along with this program; if not, write to the Free Software
19864+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19865+ */
19866+
19867+/*
19868+ * superblock private data
19869+ */
19870+
19871+#include "aufs.h"
19872+
19873+/*
19874+ * they are necessary regardless sysfs is disabled.
19875+ */
19876+void au_si_free(struct kobject *kobj)
19877+{
19878+ struct au_sbinfo *sbinfo;
19879+ struct super_block *sb;
b752ccd1 19880+ char *locked __maybe_unused; /* debug only */
1facf9fc 19881+
19882+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
19883+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
4a4d8108 19884+ AuDebugOn(sbinfo->si_plink_maint);
1facf9fc 19885+
19886+ sb = sbinfo->si_sb;
19887+ si_write_lock(sb);
19888+ au_xino_clr(sb);
19889+ au_br_free(sbinfo);
b752ccd1
AM
19890+ si_write_unlock(sb);
19891+
19892+ AuDebugOn(radix_tree_gang_lookup
19893+ (&sbinfo->au_si_pid.tree, (void **)&locked,
19894+ /*first_index*/PID_MAX_DEFAULT - 1,
19895+ /*max_items*/sizeof(locked)/sizeof(*locked)));
19896+
1facf9fc 19897+ kfree(sbinfo->si_branch);
b752ccd1 19898+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 19899+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 19900+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 19901+
19902+ kfree(sbinfo);
19903+}
19904+
19905+int au_si_alloc(struct super_block *sb)
19906+{
19907+ int err;
19908+ struct au_sbinfo *sbinfo;
19909+
19910+ err = -ENOMEM;
4a4d8108 19911+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 19912+ if (unlikely(!sbinfo))
19913+ goto out;
19914+
b752ccd1
AM
19915+ BUILD_BUG_ON(sizeof(unsigned long) !=
19916+ sizeof(*sbinfo->au_si_pid.bitmap));
19917+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
19918+ sizeof(*sbinfo->au_si_pid.bitmap),
19919+ GFP_NOFS);
19920+ if (unlikely(!sbinfo->au_si_pid.bitmap))
19921+ goto out_sbinfo;
19922+
1facf9fc 19923+ /* will be reallocated separately */
19924+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
19925+ if (unlikely(!sbinfo->si_branch))
b752ccd1 19926+ goto out_pidmap;
1facf9fc 19927+
1facf9fc 19928+ err = sysaufs_si_init(sbinfo);
19929+ if (unlikely(err))
19930+ goto out_br;
19931+
19932+ au_nwt_init(&sbinfo->si_nowait);
dece6358 19933+ au_rw_init_wlock(&sbinfo->si_rwsem);
b752ccd1
AM
19934+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
19935+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
19936+
1facf9fc 19937+ sbinfo->si_bend = -1;
1facf9fc 19938+
19939+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
19940+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
19941+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
19942+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 19943+
19944+ sbinfo->si_mntflags = AuOpt_Def;
19945+
1facf9fc 19946+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 19947+ sbinfo->si_xino_brid = -1;
19948+ /* leave si_xib_last_pindex and si_xib_next_bit */
19949+
19950+ sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
19951+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
19952+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
19953+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
19954+
19955+ au_spl_init(&sbinfo->si_plink);
19956+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 19957+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 19958+
19959+ /* leave other members for sysaufs and si_mnt. */
19960+ sbinfo->si_sb = sb;
19961+ sb->s_fs_info = sbinfo;
b752ccd1 19962+ si_pid_set(sb);
1facf9fc 19963+ au_debug_sbinfo_init(sbinfo);
19964+ return 0; /* success */
19965+
19966+ out_br:
19967+ kfree(sbinfo->si_branch);
b752ccd1
AM
19968+ out_pidmap:
19969+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 19970+ out_sbinfo:
19971+ kfree(sbinfo);
19972+ out:
19973+ return err;
19974+}
19975+
19976+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
19977+{
19978+ int err, sz;
19979+ struct au_branch **brp;
19980+
dece6358
AM
19981+ AuRwMustWriteLock(&sbinfo->si_rwsem);
19982+
1facf9fc 19983+ err = -ENOMEM;
19984+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
19985+ if (unlikely(!sz))
19986+ sz = sizeof(*brp);
19987+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
19988+ if (brp) {
19989+ sbinfo->si_branch = brp;
19990+ err = 0;
19991+ }
19992+
19993+ return err;
19994+}
19995+
19996+/* ---------------------------------------------------------------------- */
19997+
19998+unsigned int au_sigen_inc(struct super_block *sb)
19999+{
20000+ unsigned int gen;
20001+
dece6358
AM
20002+ SiMustWriteLock(sb);
20003+
1facf9fc 20004+ gen = ++au_sbi(sb)->si_generation;
20005+ au_update_digen(sb->s_root);
20006+ au_update_iigen(sb->s_root->d_inode);
20007+ sb->s_root->d_inode->i_version++;
20008+ return gen;
20009+}
20010+
20011+aufs_bindex_t au_new_br_id(struct super_block *sb)
20012+{
20013+ aufs_bindex_t br_id;
20014+ int i;
20015+ struct au_sbinfo *sbinfo;
20016+
dece6358
AM
20017+ SiMustWriteLock(sb);
20018+
1facf9fc 20019+ sbinfo = au_sbi(sb);
20020+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
20021+ br_id = ++sbinfo->si_last_br_id;
20022+ if (br_id && au_br_index(sb, br_id) < 0)
20023+ return br_id;
20024+ }
20025+
20026+ return -1;
20027+}
20028+
20029+/* ---------------------------------------------------------------------- */
20030+
20031+/* dentry and super_block lock. call at entry point */
20032+void aufs_read_lock(struct dentry *dentry, int flags)
20033+{
20034+ si_read_lock(dentry->d_sb, flags);
20035+ if (au_ftest_lock(flags, DW))
20036+ di_write_lock_child(dentry);
20037+ else
20038+ di_read_lock_child(dentry, flags);
20039+}
20040+
20041+void aufs_read_unlock(struct dentry *dentry, int flags)
20042+{
20043+ if (au_ftest_lock(flags, DW))
20044+ di_write_unlock(dentry);
20045+ else
20046+ di_read_unlock(dentry, flags);
20047+ si_read_unlock(dentry->d_sb);
20048+}
20049+
20050+void aufs_write_lock(struct dentry *dentry)
20051+{
20052+ si_write_lock(dentry->d_sb);
20053+ di_write_lock_child(dentry);
20054+}
20055+
20056+void aufs_write_unlock(struct dentry *dentry)
20057+{
20058+ di_write_unlock(dentry);
20059+ si_write_unlock(dentry->d_sb);
20060+}
20061+
20062+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
20063+{
20064+ si_read_lock(d1->d_sb, flags);
20065+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
20066+}
20067+
20068+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
20069+{
20070+ di_write_unlock2(d1, d2);
20071+ si_read_unlock(d1->d_sb);
20072+}
b752ccd1
AM
20073+
20074+/* ---------------------------------------------------------------------- */
20075+
20076+int si_pid_test_slow(struct super_block *sb)
20077+{
20078+ void *p;
20079+
20080+ rcu_read_lock();
20081+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
20082+ rcu_read_unlock();
20083+
20084+ return (long)p;
20085+}
20086+
20087+void si_pid_set_slow(struct super_block *sb)
20088+{
20089+ int err;
20090+ struct au_sbinfo *sbinfo;
20091+
20092+ AuDebugOn(si_pid_test_slow(sb));
20093+
20094+ sbinfo = au_sbi(sb);
20095+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
20096+ AuDebugOn(err);
20097+ spin_lock(&sbinfo->au_si_pid.tree_lock);
20098+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
20099+ (void *)1);
20100+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
20101+ AuDebugOn(err);
20102+ radix_tree_preload_end();
20103+}
20104+
20105+void si_pid_clr_slow(struct super_block *sb)
20106+{
20107+ void *p;
20108+ struct au_sbinfo *sbinfo;
20109+
20110+ AuDebugOn(!si_pid_test_slow(sb));
20111+
20112+ sbinfo = au_sbi(sb);
20113+ spin_lock(&sbinfo->au_si_pid.tree_lock);
20114+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
20115+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
20116+ AuDebugOn(1 != (long)p);
20117+}
20118diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
20119--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
20120+++ linux/fs/aufs/spl.h 2010-08-21 21:00:02.982333916 +0200
4a4d8108 20121@@ -0,0 +1,66 @@
1facf9fc 20122+/*
4a4d8108 20123+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20124+ *
20125+ * This program, aufs is free software; you can redistribute it and/or modify
20126+ * it under the terms of the GNU General Public License as published by
20127+ * the Free Software Foundation; either version 2 of the License, or
20128+ * (at your option) any later version.
dece6358
AM
20129+ *
20130+ * This program is distributed in the hope that it will be useful,
20131+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20132+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20133+ * GNU General Public License for more details.
20134+ *
20135+ * You should have received a copy of the GNU General Public License
20136+ * along with this program; if not, write to the Free Software
20137+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20138+ */
20139+
20140+/*
20141+ * simple list protected by a spinlock
20142+ */
20143+
20144+#ifndef __AUFS_SPL_H__
20145+#define __AUFS_SPL_H__
20146+
20147+#ifdef __KERNEL__
20148+
dece6358
AM
20149+#include <linux/spinlock.h>
20150+#include <linux/list.h>
4a4d8108 20151+#include <linux/rculist.h>
1facf9fc 20152+
20153+struct au_splhead {
20154+ spinlock_t spin;
20155+ struct list_head head;
20156+};
20157+
20158+static inline void au_spl_init(struct au_splhead *spl)
20159+{
20160+ spin_lock_init(&spl->spin);
20161+ INIT_LIST_HEAD(&spl->head);
20162+}
20163+
20164+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
20165+{
20166+ spin_lock(&spl->spin);
20167+ list_add(list, &spl->head);
20168+ spin_unlock(&spl->spin);
20169+}
20170+
20171+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
20172+{
20173+ spin_lock(&spl->spin);
20174+ list_del(list);
20175+ spin_unlock(&spl->spin);
20176+}
20177+
4a4d8108
AM
20178+static inline void au_spl_del_rcu(struct list_head *list,
20179+ struct au_splhead *spl)
20180+{
20181+ spin_lock(&spl->spin);
20182+ list_del_rcu(list);
20183+ spin_unlock(&spl->spin);
20184+}
20185+
1facf9fc 20186+#endif /* __KERNEL__ */
20187+#endif /* __AUFS_SPL_H__ */
b752ccd1
AM
20188diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
20189--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
20190+++ linux/fs/aufs/super.c 2010-08-21 21:00:02.982333916 +0200
20191@@ -0,0 +1,848 @@
1facf9fc 20192+/*
4a4d8108 20193+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20194+ *
20195+ * This program, aufs is free software; you can redistribute it and/or modify
20196+ * it under the terms of the GNU General Public License as published by
20197+ * the Free Software Foundation; either version 2 of the License, or
20198+ * (at your option) any later version.
dece6358
AM
20199+ *
20200+ * This program is distributed in the hope that it will be useful,
20201+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20202+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20203+ * GNU General Public License for more details.
20204+ *
20205+ * You should have received a copy of the GNU General Public License
20206+ * along with this program; if not, write to the Free Software
20207+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20208+ */
20209+
20210+/*
20211+ * mount and super_block operations
20212+ */
20213+
20214+#include <linux/buffer_head.h>
dece6358 20215+#include <linux/module.h>
1facf9fc 20216+#include <linux/seq_file.h>
20217+#include <linux/statfs.h>
20218+#include "aufs.h"
20219+
20220+/*
20221+ * super_operations
20222+ */
20223+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
20224+{
20225+ struct au_icntnr *c;
20226+
20227+ c = au_cache_alloc_icntnr();
20228+ if (c) {
1facf9fc 20229+ c->vfs_inode.i_version = 1; /* sigen(sb); */
20230+ c->iinfo.ii_hinode = NULL;
20231+ return &c->vfs_inode;
20232+ }
20233+ return NULL;
20234+}
20235+
20236+static void aufs_destroy_inode(struct inode *inode)
20237+{
20238+ au_iinfo_fin(inode);
20239+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
20240+}
20241+
20242+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
20243+{
20244+ struct inode *inode;
20245+ int err;
20246+
20247+ inode = iget_locked(sb, ino);
20248+ if (unlikely(!inode)) {
20249+ inode = ERR_PTR(-ENOMEM);
20250+ goto out;
20251+ }
20252+ if (!(inode->i_state & I_NEW))
20253+ goto out;
20254+
20255+ err = au_xigen_new(inode);
20256+ if (!err)
20257+ err = au_iinfo_init(inode);
20258+ if (!err)
20259+ inode->i_version++;
20260+ else {
20261+ iget_failed(inode);
20262+ inode = ERR_PTR(err);
20263+ }
20264+
20265+ out:
20266+ /* never return NULL */
20267+ AuDebugOn(!inode);
20268+ AuTraceErrPtr(inode);
20269+ return inode;
20270+}
20271+
20272+/* lock free root dinfo */
20273+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
20274+{
20275+ int err;
20276+ aufs_bindex_t bindex, bend;
20277+ struct path path;
4a4d8108 20278+ struct au_hdentry *hdp;
1facf9fc 20279+ struct au_branch *br;
20280+
20281+ err = 0;
20282+ bend = au_sbend(sb);
4a4d8108 20283+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 20284+ for (bindex = 0; !err && bindex <= bend; bindex++) {
20285+ br = au_sbr(sb, bindex);
20286+ path.mnt = br->br_mnt;
4a4d8108 20287+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 20288+ err = au_seq_path(seq, &path);
20289+ if (err > 0)
20290+ err = seq_printf(seq, "=%s",
20291+ au_optstr_br_perm(br->br_perm));
20292+ if (!err && bindex != bend)
20293+ err = seq_putc(seq, ':');
20294+ }
20295+
20296+ return err;
20297+}
20298+
20299+static void au_show_wbr_create(struct seq_file *m, int v,
20300+ struct au_sbinfo *sbinfo)
20301+{
20302+ const char *pat;
20303+
dece6358
AM
20304+ AuRwMustAnyLock(&sbinfo->si_rwsem);
20305+
1facf9fc 20306+ seq_printf(m, ",create=");
20307+ pat = au_optstr_wbr_create(v);
20308+ switch (v) {
20309+ case AuWbrCreate_TDP:
20310+ case AuWbrCreate_RR:
20311+ case AuWbrCreate_MFS:
20312+ case AuWbrCreate_PMFS:
20313+ seq_printf(m, pat);
20314+ break;
20315+ case AuWbrCreate_MFSV:
20316+ seq_printf(m, /*pat*/"mfs:%lu",
20317+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
20318+ break;
20319+ case AuWbrCreate_PMFSV:
20320+ seq_printf(m, /*pat*/"pmfs:%lu",
20321+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
20322+ break;
20323+ case AuWbrCreate_MFSRR:
20324+ seq_printf(m, /*pat*/"mfsrr:%llu",
20325+ sbinfo->si_wbr_mfs.mfsrr_watermark);
20326+ break;
20327+ case AuWbrCreate_MFSRRV:
20328+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
20329+ sbinfo->si_wbr_mfs.mfsrr_watermark,
20330+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
20331+ break;
20332+ }
20333+}
20334+
20335+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
20336+{
20337+#ifdef CONFIG_SYSFS
20338+ return 0;
20339+#else
20340+ int err;
20341+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
20342+ aufs_bindex_t bindex, brid;
20343+ struct super_block *sb;
20344+ struct qstr *name;
20345+ struct file *f;
20346+ struct dentry *d, *h_root;
4a4d8108 20347+ struct au_hdentry *hdp;
1facf9fc 20348+
dece6358
AM
20349+ AuRwMustAnyLock(&sbinfo->si_rwsem);
20350+
1facf9fc 20351+ err = 0;
20352+ sb = mnt->mnt_sb;
20353+ f = au_sbi(sb)->si_xib;
20354+ if (!f)
20355+ goto out;
20356+
20357+ /* stop printing the default xino path on the first writable branch */
20358+ h_root = NULL;
20359+ brid = au_xino_brid(sb);
20360+ if (brid >= 0) {
20361+ bindex = au_br_index(sb, brid);
4a4d8108
AM
20362+ hdp = au_di(sb->s_root)->di_hdentry;
20363+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 20364+ }
20365+ d = f->f_dentry;
20366+ name = &d->d_name;
20367+ /* safe ->d_parent because the file is unlinked */
20368+ if (d->d_parent == h_root
20369+ && name->len == len
20370+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
20371+ goto out;
20372+
20373+ seq_puts(seq, ",xino=");
20374+ err = au_xino_path(seq, f);
20375+
20376+ out:
20377+ return err;
20378+#endif
20379+}
20380+
20381+/* seq_file will re-call me in case of too long string */
20382+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
20383+{
20384+ int err, n;
20385+ unsigned int mnt_flags, v;
20386+ struct super_block *sb;
20387+ struct au_sbinfo *sbinfo;
20388+
20389+#define AuBool(name, str) do { \
20390+ v = au_opt_test(mnt_flags, name); \
20391+ if (v != au_opt_test(AuOpt_Def, name)) \
20392+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
20393+} while (0)
20394+
20395+#define AuStr(name, str) do { \
20396+ v = mnt_flags & AuOptMask_##name; \
20397+ if (v != (AuOpt_Def & AuOptMask_##name)) \
20398+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
20399+} while (0)
20400+
20401+#define AuUInt(name, str, val) do { \
20402+ if (val != AUFS_##name##_DEF) \
20403+ seq_printf(m, "," #str "=%u", val); \
20404+} while (0)
20405+
20406+ /* lock free root dinfo */
20407+ sb = mnt->mnt_sb;
20408+ si_noflush_read_lock(sb);
20409+ sbinfo = au_sbi(sb);
20410+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
20411+
20412+ mnt_flags = au_mntflags(sb);
20413+ if (au_opt_test(mnt_flags, XINO)) {
20414+ err = au_show_xino(m, mnt);
20415+ if (unlikely(err))
20416+ goto out;
20417+ } else
20418+ seq_puts(m, ",noxino");
20419+
20420+ AuBool(TRUNC_XINO, trunc_xino);
20421+ AuStr(UDBA, udba);
dece6358 20422+ AuBool(SHWH, shwh);
1facf9fc 20423+ AuBool(PLINK, plink);
4a4d8108 20424+ AuBool(DIO, dio);
1facf9fc 20425+ /* AuBool(DIRPERM1, dirperm1); */
20426+ /* AuBool(REFROF, refrof); */
20427+
20428+ v = sbinfo->si_wbr_create;
20429+ if (v != AuWbrCreate_Def)
20430+ au_show_wbr_create(m, v, sbinfo);
20431+
20432+ v = sbinfo->si_wbr_copyup;
20433+ if (v != AuWbrCopyup_Def)
20434+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
20435+
20436+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
20437+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
20438+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
20439+
20440+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
20441+
20442+ n = sbinfo->si_rdcache / HZ;
20443+ AuUInt(RDCACHE, rdcache, n);
20444+
20445+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
20446+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
20447+
20448+ AuBool(SUM, sum);
20449+ /* AuBool(SUM_W, wsum); */
20450+ AuBool(WARN_PERM, warn_perm);
20451+ AuBool(VERBOSE, verbose);
20452+
20453+ out:
20454+ /* be sure to print "br:" last */
20455+ if (!sysaufs_brs) {
20456+ seq_puts(m, ",br:");
20457+ au_show_brs(m, sb);
20458+ }
20459+ si_read_unlock(sb);
20460+ return 0;
20461+
1facf9fc 20462+#undef AuBool
20463+#undef AuStr
4a4d8108 20464+#undef AuUInt
1facf9fc 20465+}
20466+
20467+/* ---------------------------------------------------------------------- */
20468+
20469+/* sum mode which returns the summation for statfs(2) */
20470+
20471+static u64 au_add_till_max(u64 a, u64 b)
20472+{
20473+ u64 old;
20474+
20475+ old = a;
20476+ a += b;
20477+ if (old < a)
20478+ return a;
20479+ return ULLONG_MAX;
20480+}
20481+
20482+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
20483+{
20484+ int err;
20485+ u64 blocks, bfree, bavail, files, ffree;
20486+ aufs_bindex_t bend, bindex, i;
20487+ unsigned char shared;
20488+ struct vfsmount *h_mnt;
20489+ struct super_block *h_sb;
20490+
20491+ blocks = 0;
20492+ bfree = 0;
20493+ bavail = 0;
20494+ files = 0;
20495+ ffree = 0;
20496+
20497+ err = 0;
20498+ bend = au_sbend(sb);
20499+ for (bindex = bend; bindex >= 0; bindex--) {
20500+ h_mnt = au_sbr_mnt(sb, bindex);
20501+ h_sb = h_mnt->mnt_sb;
20502+ shared = 0;
20503+ for (i = bindex + 1; !shared && i <= bend; i++)
20504+ shared = (au_sbr_sb(sb, i) == h_sb);
20505+ if (shared)
20506+ continue;
20507+
20508+ /* sb->s_root for NFS is unreliable */
20509+ err = vfs_statfs(h_mnt->mnt_root, buf);
20510+ if (unlikely(err))
20511+ goto out;
20512+
20513+ blocks = au_add_till_max(blocks, buf->f_blocks);
20514+ bfree = au_add_till_max(bfree, buf->f_bfree);
20515+ bavail = au_add_till_max(bavail, buf->f_bavail);
20516+ files = au_add_till_max(files, buf->f_files);
20517+ ffree = au_add_till_max(ffree, buf->f_ffree);
20518+ }
20519+
20520+ buf->f_blocks = blocks;
20521+ buf->f_bfree = bfree;
20522+ buf->f_bavail = bavail;
20523+ buf->f_files = files;
20524+ buf->f_ffree = ffree;
20525+
20526+ out:
20527+ return err;
20528+}
20529+
20530+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
20531+{
20532+ int err;
20533+ struct super_block *sb;
20534+
20535+ /* lock free root dinfo */
20536+ sb = dentry->d_sb;
20537+ si_noflush_read_lock(sb);
20538+ if (!au_opt_test(au_mntflags(sb), SUM))
20539+ /* sb->s_root for NFS is unreliable */
20540+ err = vfs_statfs(au_sbr_mnt(sb, 0)->mnt_root, buf);
20541+ else
20542+ err = au_statfs_sum(sb, buf);
20543+ si_read_unlock(sb);
20544+
20545+ if (!err) {
20546+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 20547+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 20548+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
20549+ }
20550+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
20551+
20552+ return err;
20553+}
20554+
20555+/* ---------------------------------------------------------------------- */
20556+
1facf9fc 20557+/*
20558+ * this IS NOT for super_operations.
20559+ * I guess it will be reverted someday.
20560+ */
20561+static void aufs_umount_begin(struct super_block *sb)
20562+{
20563+ struct au_sbinfo *sbinfo;
20564+
20565+ sbinfo = au_sbi(sb);
20566+ if (!sbinfo)
20567+ return;
20568+
20569+ si_write_lock(sb);
1facf9fc 20570+ if (au_opt_test(au_mntflags(sb), PLINK))
20571+ au_plink_put(sb);
20572+ if (sbinfo->si_wbr_create_ops->fin)
20573+ sbinfo->si_wbr_create_ops->fin(sb);
20574+ si_write_unlock(sb);
20575+}
20576+
20577+/* final actions when unmounting a file system */
20578+static void aufs_put_super(struct super_block *sb)
20579+{
20580+ struct au_sbinfo *sbinfo;
20581+
20582+ sbinfo = au_sbi(sb);
20583+ if (!sbinfo)
20584+ return;
20585+
20586+ aufs_umount_begin(sb);
20587+ dbgaufs_si_fin(sbinfo);
20588+ kobject_put(&sbinfo->si_kobj);
20589+}
20590+
20591+/* ---------------------------------------------------------------------- */
20592+
20593+/*
20594+ * refresh dentry and inode at remount time.
20595+ */
20596+static int do_refresh(struct dentry *dentry, mode_t type,
20597+ unsigned int dir_flags)
20598+{
20599+ int err;
20600+ struct dentry *parent;
20601+
20602+ di_write_lock_child(dentry);
20603+ parent = dget_parent(dentry);
20604+ di_read_lock_parent(parent, AuLock_IR);
20605+
20606+ /* returns the number of positive dentries */
20607+ err = au_refresh_hdentry(dentry, type);
20608+ if (err >= 0) {
20609+ struct inode *inode = dentry->d_inode;
20610+ err = au_refresh_hinode(inode, dentry);
20611+ if (!err && type == S_IFDIR)
4a4d8108 20612+ au_hn_reset(inode, dir_flags);
1facf9fc 20613+ }
20614+ if (unlikely(err))
4a4d8108
AM
20615+ pr_err("unrecoverable error %d, %.*s\n",
20616+ err, AuDLNPair(dentry));
1facf9fc 20617+
20618+ di_read_unlock(parent, AuLock_IR);
20619+ dput(parent);
20620+ di_write_unlock(dentry);
20621+
20622+ return err;
20623+}
20624+
20625+static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
20626+{
20627+ return S_ISDIR(dentry->d_inode->i_mode);
20628+}
20629+
20630+/* gave up consolidating with refresh_nondir() */
20631+static int refresh_dir(struct dentry *root, unsigned int sigen)
20632+{
20633+ int err, i, j, ndentry, e;
20634+ struct au_dcsub_pages dpages;
20635+ struct au_dpage *dpage;
20636+ struct dentry **dentries;
20637+ struct inode *inode;
20638+ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
20639+
20640+ err = 0;
20641+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20642+ if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20643+ ii_write_lock_child(inode);
20644+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
20645+ ii_write_unlock(inode);
20646+ if (unlikely(e)) {
20647+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
20648+ if (!err)
20649+ err = e;
20650+ /* go on even if err */
20651+ }
20652+ }
20653+
20654+ e = au_dpages_init(&dpages, GFP_NOFS);
20655+ if (unlikely(e)) {
20656+ if (!err)
20657+ err = e;
20658+ goto out;
20659+ }
20660+ e = au_dcsub_pages(&dpages, root, test_dir, NULL);
20661+ if (unlikely(e)) {
20662+ if (!err)
20663+ err = e;
20664+ goto out_dpages;
20665+ }
20666+
20667+ for (i = 0; !e && i < dpages.ndpage; i++) {
20668+ dpage = dpages.dpages + i;
20669+ dentries = dpage->dentries;
20670+ ndentry = dpage->ndentry;
20671+ for (j = 0; !e && j < ndentry; j++) {
20672+ struct dentry *d;
20673+
20674+ d = dentries[j];
20675+ au_dbg_verify_dir_parent(d, sigen);
20676+ if (au_digen(d) != sigen) {
20677+ e = do_refresh(d, S_IFDIR, flags);
20678+ if (unlikely(e && !err))
20679+ err = e;
20680+ /* break on err */
20681+ }
20682+ }
20683+ }
20684+
20685+ out_dpages:
20686+ au_dpages_free(&dpages);
20687+ out:
20688+ return err;
20689+}
20690+
20691+static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
20692+{
20693+ return !S_ISDIR(dentry->d_inode->i_mode);
20694+}
20695+
20696+static int refresh_nondir(struct dentry *root, unsigned int sigen,
20697+ int do_dentry)
20698+{
20699+ int err, i, j, ndentry, e;
20700+ struct au_dcsub_pages dpages;
20701+ struct au_dpage *dpage;
20702+ struct dentry **dentries;
20703+ struct inode *inode;
20704+
20705+ err = 0;
20706+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20707+ if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20708+ ii_write_lock_child(inode);
20709+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
20710+ ii_write_unlock(inode);
20711+ if (unlikely(e)) {
20712+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
20713+ if (!err)
20714+ err = e;
20715+ /* go on even if err */
20716+ }
20717+ }
20718+
20719+ if (!do_dentry)
20720+ goto out;
20721+
20722+ e = au_dpages_init(&dpages, GFP_NOFS);
20723+ if (unlikely(e)) {
20724+ if (!err)
20725+ err = e;
20726+ goto out;
20727+ }
20728+ e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
20729+ if (unlikely(e)) {
20730+ if (!err)
20731+ err = e;
20732+ goto out_dpages;
20733+ }
20734+
20735+ for (i = 0; i < dpages.ndpage; i++) {
20736+ dpage = dpages.dpages + i;
20737+ dentries = dpage->dentries;
20738+ ndentry = dpage->ndentry;
20739+ for (j = 0; j < ndentry; j++) {
20740+ struct dentry *d;
20741+
20742+ d = dentries[j];
20743+ au_dbg_verify_nondir_parent(d, sigen);
20744+ inode = d->d_inode;
20745+ if (inode && au_digen(d) != sigen) {
20746+ e = do_refresh(d, inode->i_mode & S_IFMT,
20747+ /*dir_flags*/0);
20748+ if (unlikely(e && !err))
20749+ err = e;
20750+ /* go on even err */
20751+ }
20752+ }
20753+ }
20754+
20755+ out_dpages:
20756+ au_dpages_free(&dpages);
20757+ out:
20758+ return err;
20759+}
20760+
20761+static void au_remount_refresh(struct super_block *sb, unsigned int flags)
20762+{
20763+ int err;
20764+ unsigned int sigen;
20765+ struct au_sbinfo *sbinfo;
20766+ struct dentry *root;
20767+ struct inode *inode;
20768+
20769+ au_sigen_inc(sb);
20770+ sigen = au_sigen(sb);
20771+ sbinfo = au_sbi(sb);
20772+ au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
20773+
20774+ root = sb->s_root;
20775+ DiMustNoWaiters(root);
20776+ inode = root->d_inode;
20777+ IiMustNoWaiters(inode);
4a4d8108 20778+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 20779+ di_write_unlock(root);
20780+
20781+ err = refresh_dir(root, sigen);
20782+ if (unlikely(err)) {
20783+ au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
4a4d8108
AM
20784+ pr_warning("Refreshing directories failed, ignored (%d)\n",
20785+ err);
1facf9fc 20786+ }
20787+
20788+ if (au_ftest_opts(flags, REFRESH_NONDIR)) {
20789+ err = refresh_nondir(root, sigen, !err);
20790+ if (unlikely(err))
4a4d8108
AM
20791+ pr_warning("Refreshing non-directories failed, ignored"
20792+ "(%d)\n", err);
1facf9fc 20793+ }
20794+
20795+ /* aufs_write_lock() calls ..._child() */
20796+ di_write_lock_child(root);
20797+ au_cpup_attr_all(root->d_inode, /*force*/1);
20798+}
20799+
20800+/* stop extra interpretation of errno in mount(8), and strange error messages */
20801+static int cvt_err(int err)
20802+{
20803+ AuTraceErr(err);
20804+
20805+ switch (err) {
20806+ case -ENOENT:
20807+ case -ENOTDIR:
20808+ case -EEXIST:
20809+ case -EIO:
20810+ err = -EINVAL;
20811+ }
20812+ return err;
20813+}
20814+
20815+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
20816+{
4a4d8108
AM
20817+ int err, do_dx;
20818+ unsigned int mntflags;
1facf9fc 20819+ struct au_opts opts;
20820+ struct dentry *root;
20821+ struct inode *inode;
20822+ struct au_sbinfo *sbinfo;
20823+
20824+ err = 0;
20825+ root = sb->s_root;
20826+ if (!data || !*data) {
20827+ aufs_write_lock(root);
20828+ err = au_opts_verify(sb, *flags, /*pending*/0);
1facf9fc 20829+ aufs_write_unlock(root);
20830+ goto out;
20831+ }
20832+
20833+ err = -ENOMEM;
20834+ memset(&opts, 0, sizeof(opts));
20835+ opts.opt = (void *)__get_free_page(GFP_NOFS);
20836+ if (unlikely(!opts.opt))
20837+ goto out;
20838+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
20839+ opts.flags = AuOpts_REMOUNT;
20840+ opts.sb_flags = *flags;
20841+
20842+ /* parse it before aufs lock */
20843+ err = au_opts_parse(sb, data, &opts);
20844+ if (unlikely(err))
20845+ goto out_opts;
20846+
20847+ sbinfo = au_sbi(sb);
20848+ inode = root->d_inode;
20849+ mutex_lock(&inode->i_mutex);
20850+ aufs_write_lock(root);
1facf9fc 20851+
20852+ /* au_opts_remount() may return an error */
20853+ err = au_opts_remount(sb, &opts);
20854+ au_opts_free(&opts);
20855+
20856+ if (au_ftest_opts(opts.flags, REFRESH_DIR)
20857+ || au_ftest_opts(opts.flags, REFRESH_NONDIR))
20858+ au_remount_refresh(sb, opts.flags);
20859+
4a4d8108
AM
20860+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
20861+ mntflags = au_mntflags(sb);
20862+ do_dx = !!au_opt_test(mntflags, DIO);
20863+ au_dy_arefresh(do_dx);
20864+ }
20865+
1facf9fc 20866+ aufs_write_unlock(root);
20867+ mutex_unlock(&inode->i_mutex);
20868+
20869+ out_opts:
20870+ free_page((unsigned long)opts.opt);
20871+ out:
20872+ err = cvt_err(err);
20873+ AuTraceErr(err);
20874+ return err;
20875+}
20876+
4a4d8108 20877+static const struct super_operations aufs_sop = {
1facf9fc 20878+ .alloc_inode = aufs_alloc_inode,
20879+ .destroy_inode = aufs_destroy_inode,
b752ccd1 20880+ /* always deleting, no clearing */
1facf9fc 20881+ .drop_inode = generic_delete_inode,
20882+ .show_options = aufs_show_options,
20883+ .statfs = aufs_statfs,
20884+ .put_super = aufs_put_super,
20885+ .remount_fs = aufs_remount_fs
20886+};
20887+
20888+/* ---------------------------------------------------------------------- */
20889+
20890+static int alloc_root(struct super_block *sb)
20891+{
20892+ int err;
20893+ struct inode *inode;
20894+ struct dentry *root;
20895+
20896+ err = -ENOMEM;
20897+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
20898+ err = PTR_ERR(inode);
20899+ if (IS_ERR(inode))
20900+ goto out;
20901+
20902+ inode->i_op = &aufs_dir_iop;
20903+ inode->i_fop = &aufs_dir_fop;
20904+ inode->i_mode = S_IFDIR;
20905+ inode->i_nlink = 2;
20906+ unlock_new_inode(inode);
20907+
20908+ root = d_alloc_root(inode);
20909+ if (unlikely(!root))
20910+ goto out_iput;
20911+ err = PTR_ERR(root);
20912+ if (IS_ERR(root))
20913+ goto out_iput;
20914+
4a4d8108 20915+ err = au_di_init(root);
1facf9fc 20916+ if (!err) {
20917+ sb->s_root = root;
20918+ return 0; /* success */
20919+ }
20920+ dput(root);
20921+ goto out; /* do not iput */
20922+
20923+ out_iput:
20924+ iget_failed(inode);
20925+ iput(inode);
20926+ out:
20927+ return err;
20928+
20929+}
20930+
20931+static int aufs_fill_super(struct super_block *sb, void *raw_data,
20932+ int silent __maybe_unused)
20933+{
20934+ int err;
20935+ struct au_opts opts;
20936+ struct dentry *root;
20937+ struct inode *inode;
20938+ char *arg = raw_data;
20939+
20940+ if (unlikely(!arg || !*arg)) {
20941+ err = -EINVAL;
4a4d8108 20942+ pr_err("no arg\n");
1facf9fc 20943+ goto out;
20944+ }
20945+
20946+ err = -ENOMEM;
20947+ memset(&opts, 0, sizeof(opts));
20948+ opts.opt = (void *)__get_free_page(GFP_NOFS);
20949+ if (unlikely(!opts.opt))
20950+ goto out;
20951+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
20952+ opts.sb_flags = sb->s_flags;
20953+
20954+ err = au_si_alloc(sb);
20955+ if (unlikely(err))
20956+ goto out_opts;
20957+
20958+ /* all timestamps always follow the ones on the branch */
20959+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
20960+ sb->s_op = &aufs_sop;
20961+ sb->s_magic = AUFS_SUPER_MAGIC;
20962+ sb->s_maxbytes = 0;
20963+ au_export_init(sb);
20964+
20965+ err = alloc_root(sb);
20966+ if (unlikely(err)) {
20967+ si_write_unlock(sb);
20968+ goto out_info;
20969+ }
20970+ root = sb->s_root;
20971+ inode = root->d_inode;
20972+
20973+ /*
20974+ * actually we can parse options regardless aufs lock here.
20975+ * but at remount time, parsing must be done before aufs lock.
20976+ * so we follow the same rule.
20977+ */
20978+ ii_write_lock_parent(inode);
20979+ aufs_write_unlock(root);
20980+ err = au_opts_parse(sb, arg, &opts);
20981+ if (unlikely(err))
20982+ goto out_root;
20983+
20984+ /* lock vfs_inode first, then aufs. */
20985+ mutex_lock(&inode->i_mutex);
1facf9fc 20986+ aufs_write_lock(root);
20987+ err = au_opts_mount(sb, &opts);
20988+ au_opts_free(&opts);
1facf9fc 20989+ aufs_write_unlock(root);
20990+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
20991+ if (!err)
20992+ goto out_opts; /* success */
1facf9fc 20993+
1facf9fc 20994+ out_root:
20995+ dput(root);
20996+ sb->s_root = NULL;
20997+ out_info:
20998+ kobject_put(&au_sbi(sb)->si_kobj);
20999+ sb->s_fs_info = NULL;
21000+ out_opts:
21001+ free_page((unsigned long)opts.opt);
21002+ out:
21003+ AuTraceErr(err);
21004+ err = cvt_err(err);
21005+ AuTraceErr(err);
21006+ return err;
21007+}
21008+
21009+/* ---------------------------------------------------------------------- */
21010+
21011+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
21012+ const char *dev_name __maybe_unused, void *raw_data,
21013+ struct vfsmount *mnt)
21014+{
21015+ int err;
21016+ struct super_block *sb;
21017+
21018+ /* all timestamps always follow the ones on the branch */
21019+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
21020+ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
21021+ if (!err) {
21022+ sb = mnt->mnt_sb;
21023+ si_write_lock(sb);
21024+ sysaufs_brs_add(sb, 0);
21025+ si_write_unlock(sb);
21026+ }
21027+ return err;
21028+}
21029+
21030+struct file_system_type aufs_fs_type = {
21031+ .name = AUFS_FSTYPE,
21032+ .fs_flags =
21033+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
21034+ | FS_REVAL_DOT, /* for NFS branch and udba */
21035+ .get_sb = aufs_get_sb,
21036+ .kill_sb = generic_shutdown_super,
21037+ /* no need to __module_get() and module_put(). */
21038+ .owner = THIS_MODULE,
21039+};
b752ccd1
AM
21040diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
21041--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
21042+++ linux/fs/aufs/super.h 2010-08-21 21:00:02.982333916 +0200
21043@@ -0,0 +1,465 @@
1facf9fc 21044+/*
4a4d8108 21045+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21046+ *
21047+ * This program, aufs is free software; you can redistribute it and/or modify
21048+ * it under the terms of the GNU General Public License as published by
21049+ * the Free Software Foundation; either version 2 of the License, or
21050+ * (at your option) any later version.
dece6358
AM
21051+ *
21052+ * This program is distributed in the hope that it will be useful,
21053+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21054+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21055+ * GNU General Public License for more details.
21056+ *
21057+ * You should have received a copy of the GNU General Public License
21058+ * along with this program; if not, write to the Free Software
21059+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21060+ */
21061+
21062+/*
21063+ * super_block operations
21064+ */
21065+
21066+#ifndef __AUFS_SUPER_H__
21067+#define __AUFS_SUPER_H__
21068+
21069+#ifdef __KERNEL__
21070+
21071+#include <linux/fs.h>
1facf9fc 21072+#include <linux/aufs_type.h>
21073+#include "rwsem.h"
21074+#include "spl.h"
21075+#include "wkq.h"
21076+
21077+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
21078+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
21079+ loff_t *);
21080+
21081+/* policies to select one among multiple writable branches */
21082+struct au_wbr_copyup_operations {
21083+ int (*copyup)(struct dentry *dentry);
21084+};
21085+
21086+struct au_wbr_create_operations {
21087+ int (*create)(struct dentry *dentry, int isdir);
21088+ int (*init)(struct super_block *sb);
21089+ int (*fin)(struct super_block *sb);
21090+};
21091+
21092+struct au_wbr_mfs {
21093+ struct mutex mfs_lock; /* protect this structure */
21094+ unsigned long mfs_jiffy;
21095+ unsigned long mfs_expire;
21096+ aufs_bindex_t mfs_bindex;
21097+
21098+ unsigned long long mfsrr_bytes;
21099+ unsigned long long mfsrr_watermark;
21100+};
21101+
1facf9fc 21102+struct au_branch;
21103+struct au_sbinfo {
21104+ /* nowait tasks in the system-wide workqueue */
21105+ struct au_nowait_tasks si_nowait;
21106+
b752ccd1
AM
21107+ /*
21108+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
21109+ * rwsem for au_sbinfo is necessary.
21110+ */
dece6358 21111+ struct au_rwsem si_rwsem;
1facf9fc 21112+
b752ccd1
AM
21113+ /* prevent recursive locking in deleting inode */
21114+ struct {
21115+ unsigned long *bitmap;
21116+ spinlock_t tree_lock;
21117+ struct radix_tree_root tree;
21118+ } au_si_pid;
21119+
1facf9fc 21120+ /* branch management */
21121+ unsigned int si_generation;
21122+
21123+ /* see above flags */
21124+ unsigned char au_si_status;
21125+
21126+ aufs_bindex_t si_bend;
21127+ aufs_bindex_t si_last_br_id;
21128+ struct au_branch **si_branch;
21129+
21130+ /* policy to select a writable branch */
21131+ unsigned char si_wbr_copyup;
21132+ unsigned char si_wbr_create;
21133+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
21134+ struct au_wbr_create_operations *si_wbr_create_ops;
21135+
21136+ /* round robin */
21137+ atomic_t si_wbr_rr_next;
21138+
21139+ /* most free space */
21140+ struct au_wbr_mfs si_wbr_mfs;
21141+
21142+ /* mount flags */
21143+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
21144+ unsigned int si_mntflags;
21145+
21146+ /* external inode number (bitmap and translation table) */
21147+ au_readf_t si_xread;
21148+ au_writef_t si_xwrite;
21149+ struct file *si_xib;
21150+ struct mutex si_xib_mtx; /* protect xib members */
21151+ unsigned long *si_xib_buf;
21152+ unsigned long si_xib_last_pindex;
21153+ int si_xib_next_bit;
21154+ aufs_bindex_t si_xino_brid;
21155+ /* reserved for future use */
21156+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
21157+
21158+#ifdef CONFIG_AUFS_EXPORT
21159+ /* i_generation */
21160+ struct file *si_xigen;
21161+ atomic_t si_xigen_next;
21162+#endif
21163+
21164+ /* vdir parameters */
21165+ unsigned long si_rdcache; /* max cache time in HZ */
21166+ unsigned int si_rdblk; /* deblk size */
21167+ unsigned int si_rdhash; /* hash size */
21168+
21169+ /*
21170+ * If the number of whiteouts are larger than si_dirwh, leave all of
21171+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
21172+ * future fsck.aufs or kernel thread will remove them later.
21173+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
21174+ */
21175+ unsigned int si_dirwh;
21176+
21177+ /*
21178+ * rename(2) a directory with all children.
21179+ */
21180+ /* reserved for future use */
21181+ /* int si_rendir; */
21182+
21183+ /* pseudo_link list */
21184+ struct au_splhead si_plink;
21185+ wait_queue_head_t si_plink_wq;
4a4d8108
AM
21186+ spinlock_t si_plink_maint_lock;
21187+ struct file *si_plink_maint;
1facf9fc 21188+
21189+ /*
21190+ * sysfs and lifetime management.
21191+ * this is not a small structure and it may be a waste of memory in case
21192+ * of sysfs is disabled, particulary when many aufs-es are mounted.
21193+ * but using sysfs is majority.
21194+ */
21195+ struct kobject si_kobj;
21196+#ifdef CONFIG_DEBUG_FS
21197+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
21198+#ifdef CONFIG_AUFS_EXPORT
21199+ struct dentry *si_dbgaufs_xigen;
21200+#endif
21201+#endif
21202+
21203+ /* dirty, necessary for unmounting, sysfs and sysrq */
21204+ struct super_block *si_sb;
21205+};
21206+
dece6358
AM
21207+/* sbinfo status flags */
21208+/*
21209+ * set true when refresh_dirs() failed at remount time.
21210+ * then try refreshing dirs at access time again.
21211+ * if it is false, refreshing dirs at access time is unnecesary
21212+ */
21213+#define AuSi_FAILED_REFRESH_DIRS 1
dece6358
AM
21214+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
21215+ unsigned int flag)
21216+{
21217+ AuRwMustAnyLock(&sbi->si_rwsem);
21218+ return sbi->au_si_status & flag;
21219+}
21220+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
21221+#define au_fset_si(sbinfo, name) do { \
21222+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
21223+ (sbinfo)->au_si_status |= AuSi_##name; \
21224+} while (0)
21225+#define au_fclr_si(sbinfo, name) do { \
21226+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
21227+ (sbinfo)->au_si_status &= ~AuSi_##name; \
21228+} while (0)
21229+
1facf9fc 21230+/* ---------------------------------------------------------------------- */
21231+
21232+/* policy to select one among writable branches */
4a4d8108
AM
21233+#define AuWbrCopyup(sbinfo, ...) \
21234+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
21235+#define AuWbrCreate(sbinfo, ...) \
21236+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 21237+
21238+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
21239+#define AuLock_DW 1 /* write-lock dentry */
21240+#define AuLock_IR (1 << 1) /* read-lock inode */
21241+#define AuLock_IW (1 << 2) /* write-lock inode */
21242+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
21243+#define AuLock_DIR (1 << 4) /* target is a dir */
21244+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
21245+#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
21246+#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
21247+
21248+/* ---------------------------------------------------------------------- */
21249+
21250+/* super.c */
21251+extern struct file_system_type aufs_fs_type;
21252+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
21253+
21254+/* sbinfo.c */
21255+void au_si_free(struct kobject *kobj);
21256+int au_si_alloc(struct super_block *sb);
21257+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
21258+
21259+unsigned int au_sigen_inc(struct super_block *sb);
21260+aufs_bindex_t au_new_br_id(struct super_block *sb);
21261+
21262+void aufs_read_lock(struct dentry *dentry, int flags);
21263+void aufs_read_unlock(struct dentry *dentry, int flags);
21264+void aufs_write_lock(struct dentry *dentry);
21265+void aufs_write_unlock(struct dentry *dentry);
21266+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
21267+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
21268+
b752ccd1
AM
21269+int si_pid_test_slow(struct super_block *sb);
21270+void si_pid_set_slow(struct super_block *sb);
21271+void si_pid_clr_slow(struct super_block *sb);
21272+
1facf9fc 21273+/* wbr_policy.c */
21274+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
21275+extern struct au_wbr_create_operations au_wbr_create_ops[];
21276+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
21277+
21278+/* ---------------------------------------------------------------------- */
21279+
21280+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
21281+{
21282+ return sb->s_fs_info;
21283+}
21284+
21285+/* ---------------------------------------------------------------------- */
21286+
21287+#ifdef CONFIG_AUFS_EXPORT
21288+void au_export_init(struct super_block *sb);
21289+
b752ccd1 21290+static inline int au_test_nfsd(void)
1facf9fc 21291+{
b752ccd1
AM
21292+ struct task_struct *tsk = current;
21293+
21294+ return (tsk->flags & PF_KTHREAD)
21295+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 21296+}
21297+
b752ccd1 21298+void au_xigen_inc(struct inode *inode);
1facf9fc 21299+int au_xigen_new(struct inode *inode);
21300+int au_xigen_set(struct super_block *sb, struct file *base);
21301+void au_xigen_clr(struct super_block *sb);
21302+
21303+static inline int au_busy_or_stale(void)
21304+{
b752ccd1 21305+ if (!au_test_nfsd())
1facf9fc 21306+ return -EBUSY;
21307+ return -ESTALE;
21308+}
21309+#else
4a4d8108 21310+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
21311+AuStubInt0(au_test_nfsd, void)
21312+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
21313+AuStubInt0(au_xigen_new, struct inode *inode)
21314+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
21315+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 21316+static inline int au_busy_or_stale(void)
21317+{
21318+ return -EBUSY;
21319+}
21320+#endif /* CONFIG_AUFS_EXPORT */
21321+
21322+/* ---------------------------------------------------------------------- */
21323+
21324+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
21325+{
dece6358
AM
21326+ /*
21327+ * This function is a dynamic '__init' fucntion actually,
21328+ * so the tiny check for si_rwsem is unnecessary.
21329+ */
21330+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 21331+#ifdef CONFIG_DEBUG_FS
21332+ sbinfo->si_dbgaufs = NULL;
21333+ sbinfo->si_dbgaufs_xib = NULL;
21334+#ifdef CONFIG_AUFS_EXPORT
21335+ sbinfo->si_dbgaufs_xigen = NULL;
21336+#endif
21337+#endif
21338+}
21339+
21340+/* ---------------------------------------------------------------------- */
21341+
b752ccd1
AM
21342+static inline pid_t si_pid_bit(void)
21343+{
21344+ /* the origin of pid is 1, but the bitmap's is 0 */
21345+ return current->pid - 1;
21346+}
21347+
21348+static inline int si_pid_test(struct super_block *sb)
21349+{
21350+ pid_t bit = si_pid_bit();
21351+ if (bit < PID_MAX_DEFAULT)
21352+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21353+ else
21354+ return si_pid_test_slow(sb);
21355+}
21356+
21357+static inline void si_pid_set(struct super_block *sb)
21358+{
21359+ pid_t bit = si_pid_bit();
21360+ if (bit < PID_MAX_DEFAULT) {
21361+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21362+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21363+ /* smp_mb(); */
21364+ } else
21365+ si_pid_set_slow(sb);
21366+}
21367+
21368+static inline void si_pid_clr(struct super_block *sb)
21369+{
21370+ pid_t bit = si_pid_bit();
21371+ if (bit < PID_MAX_DEFAULT) {
21372+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21373+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21374+ /* smp_mb(); */
21375+ } else
21376+ si_pid_clr_slow(sb);
21377+}
21378+
21379+/* ---------------------------------------------------------------------- */
21380+
1facf9fc 21381+/* lock superblock. mainly for entry point functions */
21382+/*
b752ccd1
AM
21383+ * __si_read_lock, __si_write_lock,
21384+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 21385+ */
b752ccd1 21386+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 21387+
dece6358
AM
21388+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
21389+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
21390+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
21391+
b752ccd1
AM
21392+static inline void si_noflush_read_lock(struct super_block *sb)
21393+{
21394+ __si_read_lock(sb);
21395+ si_pid_set(sb);
21396+}
21397+
21398+static inline int si_noflush_read_trylock(struct super_block *sb)
21399+{
21400+ int locked = __si_read_trylock(sb);
21401+ if (locked)
21402+ si_pid_set(sb);
21403+ return locked;
21404+}
21405+
21406+static inline void si_noflush_write_lock(struct super_block *sb)
21407+{
21408+ __si_write_lock(sb);
21409+ si_pid_set(sb);
21410+}
21411+
21412+static inline int si_noflush_write_trylock(struct super_block *sb)
21413+{
21414+ int locked = __si_write_trylock(sb);
21415+ if (locked)
21416+ si_pid_set(sb);
21417+ return locked;
21418+}
21419+
1facf9fc 21420+static inline void si_read_lock(struct super_block *sb, int flags)
21421+{
21422+ if (au_ftest_lock(flags, FLUSH))
21423+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21424+ si_noflush_read_lock(sb);
21425+}
21426+
1facf9fc 21427+static inline int si_read_trylock(struct super_block *sb, int flags)
21428+{
21429+ if (au_ftest_lock(flags, FLUSH))
21430+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21431+ return si_noflush_read_trylock(sb);
21432+}
21433+
b752ccd1
AM
21434+static inline void si_read_unlock(struct super_block *sb)
21435+{
21436+ si_pid_clr(sb);
21437+ __si_read_unlock(sb);
21438+}
21439+
21440+static inline void si_write_lock(struct super_block *sb)
21441+{
21442+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21443+ si_noflush_write_lock(sb);
21444+}
21445+
21446+#if 0 /* unused */
1facf9fc 21447+static inline int si_write_trylock(struct super_block *sb, int flags)
21448+{
21449+ if (au_ftest_lock(flags, FLUSH))
21450+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21451+ return si_noflush_write_trylock(sb);
21452+}
b752ccd1
AM
21453+#endif
21454+
21455+static inline void si_write_unlock(struct super_block *sb)
21456+{
21457+ si_pid_clr(sb);
21458+ __si_write_unlock(sb);
21459+}
21460+
21461+#if 0 /* unused */
21462+static inline void si_downgrade_lock(struct super_block *sb)
21463+{
21464+ __si_downgrade_lock(sb);
21465+}
21466+#endif
1facf9fc 21467+
21468+/* ---------------------------------------------------------------------- */
21469+
21470+static inline aufs_bindex_t au_sbend(struct super_block *sb)
21471+{
dece6358 21472+ SiMustAnyLock(sb);
1facf9fc 21473+ return au_sbi(sb)->si_bend;
21474+}
21475+
21476+static inline unsigned int au_mntflags(struct super_block *sb)
21477+{
dece6358 21478+ SiMustAnyLock(sb);
1facf9fc 21479+ return au_sbi(sb)->si_mntflags;
21480+}
21481+
21482+static inline unsigned int au_sigen(struct super_block *sb)
21483+{
dece6358 21484+ SiMustAnyLock(sb);
1facf9fc 21485+ return au_sbi(sb)->si_generation;
21486+}
21487+
21488+static inline struct au_branch *au_sbr(struct super_block *sb,
21489+ aufs_bindex_t bindex)
21490+{
dece6358 21491+ SiMustAnyLock(sb);
1facf9fc 21492+ return au_sbi(sb)->si_branch[0 + bindex];
21493+}
21494+
21495+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
21496+{
dece6358 21497+ SiMustWriteLock(sb);
1facf9fc 21498+ au_sbi(sb)->si_xino_brid = brid;
21499+}
21500+
21501+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
21502+{
dece6358 21503+ SiMustAnyLock(sb);
1facf9fc 21504+ return au_sbi(sb)->si_xino_brid;
21505+}
21506+
21507+#endif /* __KERNEL__ */
21508+#endif /* __AUFS_SUPER_H__ */
b752ccd1
AM
21509diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
21510--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
21511+++ linux/fs/aufs/sysaufs.c 2010-08-21 21:00:02.986708041 +0200
4a4d8108 21512@@ -0,0 +1,107 @@
1facf9fc 21513+/*
4a4d8108 21514+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21515+ *
21516+ * This program, aufs is free software; you can redistribute it and/or modify
21517+ * it under the terms of the GNU General Public License as published by
21518+ * the Free Software Foundation; either version 2 of the License, or
21519+ * (at your option) any later version.
dece6358
AM
21520+ *
21521+ * This program is distributed in the hope that it will be useful,
21522+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21523+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21524+ * GNU General Public License for more details.
21525+ *
21526+ * You should have received a copy of the GNU General Public License
21527+ * along with this program; if not, write to the Free Software
21528+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21529+ */
21530+
21531+/*
21532+ * sysfs interface and lifetime management
21533+ * they are necessary regardless sysfs is disabled.
21534+ */
21535+
21536+#include <linux/fs.h>
21537+#include <linux/random.h>
21538+#include <linux/sysfs.h>
21539+#include "aufs.h"
21540+
21541+unsigned long sysaufs_si_mask;
21542+struct kset *sysaufs_ket;
21543+
21544+#define AuSiAttr(_name) { \
21545+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
21546+ .show = sysaufs_si_##_name, \
21547+}
21548+
21549+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
21550+struct attribute *sysaufs_si_attrs[] = {
21551+ &sysaufs_si_attr_xi_path.attr,
21552+ NULL,
21553+};
21554+
4a4d8108 21555+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 21556+ .show = sysaufs_si_show
21557+};
21558+
21559+static struct kobj_type au_sbi_ktype = {
21560+ .release = au_si_free,
21561+ .sysfs_ops = &au_sbi_ops,
21562+ .default_attrs = sysaufs_si_attrs
21563+};
21564+
21565+/* ---------------------------------------------------------------------- */
21566+
21567+int sysaufs_si_init(struct au_sbinfo *sbinfo)
21568+{
21569+ int err;
21570+
21571+ sbinfo->si_kobj.kset = sysaufs_ket;
21572+ /* cf. sysaufs_name() */
21573+ err = kobject_init_and_add
21574+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->kobj*/NULL,
21575+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
21576+
21577+ dbgaufs_si_null(sbinfo);
21578+ if (!err) {
21579+ err = dbgaufs_si_init(sbinfo);
21580+ if (unlikely(err))
21581+ kobject_put(&sbinfo->si_kobj);
21582+ }
21583+ return err;
21584+}
21585+
21586+void sysaufs_fin(void)
21587+{
21588+ dbgaufs_fin();
21589+ sysfs_remove_group(&sysaufs_ket->kobj, sysaufs_attr_group);
21590+ kset_unregister(sysaufs_ket);
21591+}
21592+
21593+int __init sysaufs_init(void)
21594+{
21595+ int err;
21596+
21597+ do {
21598+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
21599+ } while (!sysaufs_si_mask);
21600+
4a4d8108 21601+ err = -EINVAL;
1facf9fc 21602+ sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
4a4d8108
AM
21603+ if (unlikely(!sysaufs_ket))
21604+ goto out;
1facf9fc 21605+ err = PTR_ERR(sysaufs_ket);
21606+ if (IS_ERR(sysaufs_ket))
21607+ goto out;
21608+ err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
21609+ if (unlikely(err)) {
21610+ kset_unregister(sysaufs_ket);
21611+ goto out;
21612+ }
21613+
21614+ err = dbgaufs_init();
21615+ if (unlikely(err))
21616+ sysaufs_fin();
21617+ out:
21618+ return err;
21619+}
b752ccd1
AM
21620diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
21621--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
21622+++ linux/fs/aufs/sysaufs.h 2010-08-21 21:00:02.986708041 +0200
4a4d8108 21623@@ -0,0 +1,105 @@
1facf9fc 21624+/*
4a4d8108 21625+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21626+ *
21627+ * This program, aufs is free software; you can redistribute it and/or modify
21628+ * it under the terms of the GNU General Public License as published by
21629+ * the Free Software Foundation; either version 2 of the License, or
21630+ * (at your option) any later version.
dece6358
AM
21631+ *
21632+ * This program is distributed in the hope that it will be useful,
21633+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21634+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21635+ * GNU General Public License for more details.
21636+ *
21637+ * You should have received a copy of the GNU General Public License
21638+ * along with this program; if not, write to the Free Software
21639+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21640+ */
21641+
21642+/*
21643+ * sysfs interface and mount lifetime management
21644+ */
21645+
21646+#ifndef __SYSAUFS_H__
21647+#define __SYSAUFS_H__
21648+
21649+#ifdef __KERNEL__
21650+
1facf9fc 21651+#include <linux/sysfs.h>
21652+#include <linux/aufs_type.h>
21653+#include "module.h"
21654+
dece6358
AM
21655+struct super_block;
21656+struct au_sbinfo;
21657+
1facf9fc 21658+struct sysaufs_si_attr {
21659+ struct attribute attr;
21660+ int (*show)(struct seq_file *seq, struct super_block *sb);
21661+};
21662+
21663+/* ---------------------------------------------------------------------- */
21664+
21665+/* sysaufs.c */
21666+extern unsigned long sysaufs_si_mask;
21667+extern struct kset *sysaufs_ket;
21668+extern struct attribute *sysaufs_si_attrs[];
21669+int sysaufs_si_init(struct au_sbinfo *sbinfo);
21670+int __init sysaufs_init(void);
21671+void sysaufs_fin(void);
21672+
21673+/* ---------------------------------------------------------------------- */
21674+
21675+/* some people doesn't like to show a pointer in kernel */
21676+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
21677+{
21678+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
21679+}
21680+
21681+#define SysaufsSiNamePrefix "si_"
21682+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
21683+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
21684+{
21685+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
21686+ sysaufs_si_id(sbinfo));
21687+}
21688+
21689+struct au_branch;
21690+#ifdef CONFIG_SYSFS
21691+/* sysfs.c */
21692+extern struct attribute_group *sysaufs_attr_group;
21693+
21694+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
21695+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
21696+ char *buf);
21697+
21698+void sysaufs_br_init(struct au_branch *br);
21699+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
21700+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
21701+
21702+#define sysaufs_brs_init() do {} while (0)
21703+
21704+#else
21705+#define sysaufs_attr_group NULL
21706+
4a4d8108 21707+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 21708+
21709+static inline
21710+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
21711+ char *buf)
21712+{
21713+ return 0;
21714+}
21715+
4a4d8108
AM
21716+AuStubVoid(sysaufs_br_init, struct au_branch *br)
21717+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
21718+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 21719+
21720+static inline void sysaufs_brs_init(void)
21721+{
21722+ sysaufs_brs = 0;
21723+}
21724+
21725+#endif /* CONFIG_SYSFS */
21726+
21727+#endif /* __KERNEL__ */
21728+#endif /* __SYSAUFS_H__ */
b752ccd1
AM
21729diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
21730--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
21731+++ linux/fs/aufs/sysfs.c 2010-08-21 21:00:02.986708041 +0200
4a4d8108 21732@@ -0,0 +1,251 @@
1facf9fc 21733+/*
4a4d8108 21734+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21735+ *
21736+ * This program, aufs is free software; you can redistribute it and/or modify
21737+ * it under the terms of the GNU General Public License as published by
21738+ * the Free Software Foundation; either version 2 of the License, or
21739+ * (at your option) any later version.
dece6358
AM
21740+ *
21741+ * This program is distributed in the hope that it will be useful,
21742+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21743+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21744+ * GNU General Public License for more details.
21745+ *
21746+ * You should have received a copy of the GNU General Public License
21747+ * along with this program; if not, write to the Free Software
21748+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21749+ */
21750+
21751+/*
21752+ * sysfs interface
21753+ */
21754+
21755+#include <linux/fs.h>
dece6358 21756+#include <linux/module.h>
1facf9fc 21757+#include <linux/seq_file.h>
21758+#include <linux/sysfs.h>
21759+#include "aufs.h"
21760+
4a4d8108
AM
21761+#ifdef CONFIG_AUFS_FS_MODULE
21762+/* this entry violates the "one line per file" policy of sysfs */
21763+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
21764+ char *buf)
21765+{
21766+ ssize_t err;
21767+ static char *conf =
21768+/* this file is generated at compiling */
21769+#include "conf.str"
21770+ ;
21771+
21772+ err = snprintf(buf, PAGE_SIZE, conf);
21773+ if (unlikely(err >= PAGE_SIZE))
21774+ err = -EFBIG;
21775+ return err;
21776+}
21777+
21778+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
21779+#endif
21780+
1facf9fc 21781+static struct attribute *au_attr[] = {
4a4d8108
AM
21782+#ifdef CONFIG_AUFS_FS_MODULE
21783+ &au_config_attr.attr,
21784+#endif
1facf9fc 21785+ NULL, /* need to NULL terminate the list of attributes */
21786+};
21787+
21788+static struct attribute_group sysaufs_attr_group_body = {
21789+ .attrs = au_attr
21790+};
21791+
21792+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
21793+
21794+/* ---------------------------------------------------------------------- */
21795+
21796+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
21797+{
21798+ int err;
21799+
dece6358
AM
21800+ SiMustAnyLock(sb);
21801+
1facf9fc 21802+ err = 0;
21803+ if (au_opt_test(au_mntflags(sb), XINO)) {
21804+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
21805+ seq_putc(seq, '\n');
21806+ }
21807+ return err;
21808+}
21809+
21810+/*
21811+ * the lifetime of branch is independent from the entry under sysfs.
21812+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
21813+ * unlinked.
21814+ */
21815+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
21816+ aufs_bindex_t bindex)
21817+{
21818+ struct path path;
21819+ struct dentry *root;
21820+ struct au_branch *br;
21821+
21822+ AuDbg("b%d\n", bindex);
21823+
21824+ root = sb->s_root;
21825+ di_read_lock_parent(root, !AuLock_IR);
21826+ br = au_sbr(sb, bindex);
21827+ path.mnt = br->br_mnt;
21828+ path.dentry = au_h_dptr(root, bindex);
21829+ au_seq_path(seq, &path);
21830+ di_read_unlock(root, !AuLock_IR);
21831+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
21832+ return 0;
21833+}
21834+
21835+/* ---------------------------------------------------------------------- */
21836+
21837+static struct seq_file *au_seq(char *p, ssize_t len)
21838+{
21839+ struct seq_file *seq;
21840+
21841+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
21842+ if (seq) {
21843+ /* mutex_init(&seq.lock); */
21844+ seq->buf = p;
21845+ seq->size = len;
21846+ return seq; /* success */
21847+ }
21848+
21849+ seq = ERR_PTR(-ENOMEM);
21850+ return seq;
21851+}
21852+
21853+#define SysaufsBr_PREFIX "br"
21854+
21855+/* todo: file size may exceed PAGE_SIZE */
21856+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 21857+ char *buf)
1facf9fc 21858+{
21859+ ssize_t err;
21860+ long l;
21861+ aufs_bindex_t bend;
21862+ struct au_sbinfo *sbinfo;
21863+ struct super_block *sb;
21864+ struct seq_file *seq;
21865+ char *name;
21866+ struct attribute **cattr;
21867+
21868+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
21869+ sb = sbinfo->si_sb;
1308ab2a 21870+
21871+ /*
21872+ * prevent a race condition between sysfs and aufs.
21873+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
21874+ * prohibits maintaining the sysfs entries.
21875+ * hew we acquire read lock after sysfs_get_active_two().
21876+ * on the other hand, the remount process may maintain the sysfs/aufs
21877+ * entries after acquiring write lock.
21878+ * it can cause a deadlock.
21879+ * simply we gave up processing read here.
21880+ */
21881+ err = -EBUSY;
21882+ if (unlikely(!si_noflush_read_trylock(sb)))
21883+ goto out;
1facf9fc 21884+
21885+ seq = au_seq(buf, PAGE_SIZE);
21886+ err = PTR_ERR(seq);
21887+ if (IS_ERR(seq))
1308ab2a 21888+ goto out_unlock;
1facf9fc 21889+
21890+ name = (void *)attr->name;
21891+ cattr = sysaufs_si_attrs;
21892+ while (*cattr) {
21893+ if (!strcmp(name, (*cattr)->name)) {
21894+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
21895+ ->show(seq, sb);
21896+ goto out_seq;
21897+ }
21898+ cattr++;
21899+ }
21900+
21901+ bend = au_sbend(sb);
21902+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
21903+ name += sizeof(SysaufsBr_PREFIX) - 1;
21904+ err = strict_strtol(name, 10, &l);
21905+ if (!err) {
21906+ if (l <= bend)
21907+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
21908+ else
21909+ err = -ENOENT;
21910+ }
21911+ goto out_seq;
21912+ }
21913+ BUG();
21914+
21915+ out_seq:
21916+ if (!err) {
21917+ err = seq->count;
21918+ /* sysfs limit */
21919+ if (unlikely(err == PAGE_SIZE))
21920+ err = -EFBIG;
21921+ }
21922+ kfree(seq);
1308ab2a 21923+ out_unlock:
1facf9fc 21924+ si_read_unlock(sb);
1308ab2a 21925+ out:
1facf9fc 21926+ return err;
21927+}
21928+
21929+/* ---------------------------------------------------------------------- */
21930+
21931+void sysaufs_br_init(struct au_branch *br)
21932+{
4a4d8108
AM
21933+ struct attribute *attr = &br->br_attr;
21934+
21935+ sysfs_attr_init(attr);
21936+ attr->name = br->br_name;
21937+ attr->mode = S_IRUGO;
21938+ attr->owner = THIS_MODULE;
1facf9fc 21939+}
21940+
21941+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
21942+{
21943+ struct au_branch *br;
21944+ struct kobject *kobj;
21945+ aufs_bindex_t bend;
21946+
21947+ dbgaufs_brs_del(sb, bindex);
21948+
21949+ if (!sysaufs_brs)
21950+ return;
21951+
21952+ kobj = &au_sbi(sb)->si_kobj;
21953+ bend = au_sbend(sb);
21954+ for (; bindex <= bend; bindex++) {
21955+ br = au_sbr(sb, bindex);
21956+ sysfs_remove_file(kobj, &br->br_attr);
21957+ }
21958+}
21959+
21960+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
21961+{
21962+ int err;
21963+ aufs_bindex_t bend;
21964+ struct kobject *kobj;
21965+ struct au_branch *br;
21966+
21967+ dbgaufs_brs_add(sb, bindex);
21968+
21969+ if (!sysaufs_brs)
21970+ return;
21971+
21972+ kobj = &au_sbi(sb)->si_kobj;
21973+ bend = au_sbend(sb);
21974+ for (; bindex <= bend; bindex++) {
21975+ br = au_sbr(sb, bindex);
21976+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
21977+ "%d", bindex);
21978+ err = sysfs_create_file(kobj, &br->br_attr);
21979+ if (unlikely(err))
4a4d8108
AM
21980+ pr_warning("failed %s under sysfs(%d)\n",
21981+ br->br_name, err);
1facf9fc 21982+ }
21983+}
b752ccd1
AM
21984diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
21985--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
21986+++ linux/fs/aufs/sysrq.c 2010-08-21 21:00:02.986708041 +0200
4a4d8108 21987@@ -0,0 +1,119 @@
1facf9fc 21988+/*
4a4d8108 21989+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21990+ *
21991+ * This program, aufs is free software; you can redistribute it and/or modify
21992+ * it under the terms of the GNU General Public License as published by
21993+ * the Free Software Foundation; either version 2 of the License, or
21994+ * (at your option) any later version.
dece6358
AM
21995+ *
21996+ * This program is distributed in the hope that it will be useful,
21997+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21998+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21999+ * GNU General Public License for more details.
22000+ *
22001+ * You should have received a copy of the GNU General Public License
22002+ * along with this program; if not, write to the Free Software
22003+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22004+ */
22005+
22006+/*
22007+ * magic sysrq hanlder
22008+ */
22009+
22010+#include <linux/fs.h>
22011+#include <linux/module.h>
22012+#include <linux/moduleparam.h>
22013+/* #include <linux/sysrq.h> */
22014+#include "aufs.h"
22015+
22016+/* ---------------------------------------------------------------------- */
22017+
22018+static void sysrq_sb(struct super_block *sb)
22019+{
22020+ char *plevel;
22021+ struct au_sbinfo *sbinfo;
22022+ struct file *file;
22023+
22024+ plevel = au_plevel;
22025+ au_plevel = KERN_WARNING;
22026+ au_debug(1);
22027+
22028+ sbinfo = au_sbi(sb);
4a4d8108
AM
22029+ /* since we define pr_fmt, call printk directly */
22030+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
22031+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 22032+ au_dpri_sb(sb);
4a4d8108 22033+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 22034+ au_dpri_dentry(sb->s_root);
4a4d8108 22035+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 22036+ au_dpri_inode(sb->s_root->d_inode);
22037+#if 0
22038+ struct inode *i;
4a4d8108 22039+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
1facf9fc 22040+ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
22041+ if (list_empty(&i->i_dentry))
22042+ au_dpri_inode(i);
22043+#endif
4a4d8108
AM
22044+ printk(KERN_WARNING AUFS_NAME ": files\n");
22045+ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
22046+ umode_t mode;
22047+ mode = file->f_dentry->d_inode->i_mode;
22048+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 22049+ au_dpri_file(file);
4a4d8108 22050+ }
1facf9fc 22051+
22052+ au_plevel = plevel;
22053+ au_debug(0);
22054+}
22055+
22056+/* ---------------------------------------------------------------------- */
22057+
22058+/* module parameter */
22059+static char *aufs_sysrq_key = "a";
22060+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
22061+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
22062+
22063+static void au_sysrq(int key __maybe_unused,
22064+ struct tty_struct *tty __maybe_unused)
22065+{
22066+ struct kobject *kobj;
22067+ struct au_sbinfo *sbinfo;
22068+
22069+ /* spin_lock(&sysaufs_ket->list_lock); */
22070+ list_for_each_entry(kobj, &sysaufs_ket->list, entry) {
22071+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
22072+ sysrq_sb(sbinfo->si_sb);
22073+ }
22074+ /* spin_unlock(&sysaufs_ket->list_lock); */
22075+}
22076+
22077+static struct sysrq_key_op au_sysrq_op = {
22078+ .handler = au_sysrq,
22079+ .help_msg = "Aufs",
22080+ .action_msg = "Aufs",
22081+ .enable_mask = SYSRQ_ENABLE_DUMP
22082+};
22083+
22084+/* ---------------------------------------------------------------------- */
22085+
22086+int __init au_sysrq_init(void)
22087+{
22088+ int err;
22089+ char key;
22090+
22091+ err = -1;
22092+ key = *aufs_sysrq_key;
22093+ if ('a' <= key && key <= 'z')
22094+ err = register_sysrq_key(key, &au_sysrq_op);
22095+ if (unlikely(err))
4a4d8108 22096+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 22097+ return err;
22098+}
22099+
22100+void au_sysrq_fin(void)
22101+{
22102+ int err;
22103+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
22104+ if (unlikely(err))
4a4d8108 22105+ pr_err("err %d (ignored)\n", err);
1facf9fc 22106+}
b752ccd1
AM
22107diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
22108--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
22109+++ linux/fs/aufs/vdir.c 2010-08-21 21:00:02.986708041 +0200
4a4d8108 22110@@ -0,0 +1,884 @@
1facf9fc 22111+/*
4a4d8108 22112+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22113+ *
22114+ * This program, aufs is free software; you can redistribute it and/or modify
22115+ * it under the terms of the GNU General Public License as published by
22116+ * the Free Software Foundation; either version 2 of the License, or
22117+ * (at your option) any later version.
dece6358
AM
22118+ *
22119+ * This program is distributed in the hope that it will be useful,
22120+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22121+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22122+ * GNU General Public License for more details.
22123+ *
22124+ * You should have received a copy of the GNU General Public License
22125+ * along with this program; if not, write to the Free Software
22126+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22127+ */
22128+
22129+/*
22130+ * virtual or vertical directory
22131+ */
22132+
dece6358 22133+#include <linux/hash.h>
1facf9fc 22134+#include "aufs.h"
22135+
dece6358 22136+static unsigned int calc_size(int nlen)
1facf9fc 22137+{
dece6358 22138+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 22139+}
22140+
22141+static int set_deblk_end(union au_vdir_deblk_p *p,
22142+ union au_vdir_deblk_p *deblk_end)
22143+{
22144+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
22145+ p->de->de_str.len = 0;
22146+ /* smp_mb(); */
22147+ return 0;
22148+ }
22149+ return -1; /* error */
22150+}
22151+
22152+/* returns true or false */
22153+static int is_deblk_end(union au_vdir_deblk_p *p,
22154+ union au_vdir_deblk_p *deblk_end)
22155+{
22156+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
22157+ return !p->de->de_str.len;
22158+ return 1;
22159+}
22160+
22161+static unsigned char *last_deblk(struct au_vdir *vdir)
22162+{
22163+ return vdir->vd_deblk[vdir->vd_nblk - 1];
22164+}
22165+
22166+/* ---------------------------------------------------------------------- */
22167+
1308ab2a 22168+/* estimate the apropriate size for name hash table */
22169+unsigned int au_rdhash_est(loff_t sz)
22170+{
22171+ unsigned int n;
22172+
22173+ n = UINT_MAX;
22174+ sz >>= 10;
22175+ if (sz < n)
22176+ n = sz;
22177+ if (sz < AUFS_RDHASH_DEF)
22178+ n = AUFS_RDHASH_DEF;
4a4d8108 22179+ /* pr_info("n %u\n", n); */
1308ab2a 22180+ return n;
22181+}
22182+
1facf9fc 22183+/*
22184+ * the allocated memory has to be freed by
dece6358 22185+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 22186+ */
dece6358 22187+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 22188+{
1facf9fc 22189+ struct hlist_head *head;
dece6358 22190+ unsigned int u;
1facf9fc 22191+
dece6358
AM
22192+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
22193+ if (head) {
22194+ nhash->nh_num = num_hash;
22195+ nhash->nh_head = head;
22196+ for (u = 0; u < num_hash; u++)
1facf9fc 22197+ INIT_HLIST_HEAD(head++);
dece6358 22198+ return 0; /* success */
1facf9fc 22199+ }
1facf9fc 22200+
dece6358 22201+ return -ENOMEM;
1facf9fc 22202+}
22203+
dece6358
AM
22204+static void nhash_count(struct hlist_head *head)
22205+{
22206+#if 0
22207+ unsigned long n;
22208+ struct hlist_node *pos;
22209+
22210+ n = 0;
22211+ hlist_for_each(pos, head)
22212+ n++;
4a4d8108 22213+ pr_info("%lu\n", n);
dece6358
AM
22214+#endif
22215+}
22216+
22217+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 22218+{
1facf9fc 22219+ struct au_vdir_wh *tpos;
22220+ struct hlist_node *pos, *node;
22221+
dece6358
AM
22222+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
22223+ /* hlist_del(pos); */
22224+ kfree(tpos);
1facf9fc 22225+ }
22226+}
22227+
dece6358 22228+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 22229+{
dece6358
AM
22230+ struct au_vdir_dehstr *tpos;
22231+ struct hlist_node *pos, *node;
1facf9fc 22232+
dece6358
AM
22233+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
22234+ /* hlist_del(pos); */
4a4d8108 22235+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 22236+ }
1facf9fc 22237+}
22238+
dece6358
AM
22239+static void au_nhash_do_free(struct au_nhash *nhash,
22240+ void (*free)(struct hlist_head *head))
1facf9fc 22241+{
1308ab2a 22242+ unsigned int n;
1facf9fc 22243+ struct hlist_head *head;
1facf9fc 22244+
dece6358 22245+ n = nhash->nh_num;
1308ab2a 22246+ if (!n)
22247+ return;
22248+
dece6358 22249+ head = nhash->nh_head;
1308ab2a 22250+ while (n-- > 0) {
dece6358
AM
22251+ nhash_count(head);
22252+ free(head++);
1facf9fc 22253+ }
dece6358 22254+ kfree(nhash->nh_head);
1facf9fc 22255+}
22256+
dece6358 22257+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 22258+{
dece6358
AM
22259+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
22260+}
1facf9fc 22261+
dece6358
AM
22262+static void au_nhash_de_free(struct au_nhash *delist)
22263+{
22264+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 22265+}
22266+
22267+/* ---------------------------------------------------------------------- */
22268+
22269+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
22270+ int limit)
22271+{
22272+ int num;
22273+ unsigned int u, n;
22274+ struct hlist_head *head;
22275+ struct au_vdir_wh *tpos;
22276+ struct hlist_node *pos;
22277+
22278+ num = 0;
22279+ n = whlist->nh_num;
22280+ head = whlist->nh_head;
1308ab2a 22281+ for (u = 0; u < n; u++, head++)
1facf9fc 22282+ hlist_for_each_entry(tpos, pos, head, wh_hash)
22283+ if (tpos->wh_bindex == btgt && ++num > limit)
22284+ return 1;
1facf9fc 22285+ return 0;
22286+}
22287+
22288+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 22289+ unsigned char *name,
1facf9fc 22290+ unsigned int len)
22291+{
dece6358
AM
22292+ unsigned int v;
22293+ /* const unsigned int magic_bit = 12; */
22294+
1308ab2a 22295+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
22296+
dece6358
AM
22297+ v = 0;
22298+ while (len--)
22299+ v += *name++;
22300+ /* v = hash_long(v, magic_bit); */
22301+ v %= nhash->nh_num;
22302+ return nhash->nh_head + v;
22303+}
22304+
22305+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
22306+ int nlen)
22307+{
22308+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 22309+}
22310+
22311+/* returns found or not */
dece6358 22312+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 22313+{
22314+ struct hlist_head *head;
22315+ struct au_vdir_wh *tpos;
22316+ struct hlist_node *pos;
22317+ struct au_vdir_destr *str;
22318+
dece6358 22319+ head = au_name_hash(whlist, name, nlen);
1facf9fc 22320+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
22321+ str = &tpos->wh_str;
22322+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
22323+ if (au_nhash_test_name(str, name, nlen))
22324+ return 1;
22325+ }
22326+ return 0;
22327+}
22328+
22329+/* returns found(true) or not */
22330+static int test_known(struct au_nhash *delist, char *name, int nlen)
22331+{
22332+ struct hlist_head *head;
22333+ struct au_vdir_dehstr *tpos;
22334+ struct hlist_node *pos;
22335+ struct au_vdir_destr *str;
22336+
22337+ head = au_name_hash(delist, name, nlen);
22338+ hlist_for_each_entry(tpos, pos, head, hash) {
22339+ str = tpos->str;
22340+ AuDbg("%.*s\n", str->len, str->name);
22341+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 22342+ return 1;
22343+ }
22344+ return 0;
22345+}
22346+
dece6358
AM
22347+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
22348+ unsigned char d_type)
22349+{
22350+#ifdef CONFIG_AUFS_SHWH
22351+ wh->wh_ino = ino;
22352+ wh->wh_type = d_type;
22353+#endif
22354+}
22355+
22356+/* ---------------------------------------------------------------------- */
22357+
22358+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
22359+ unsigned int d_type, aufs_bindex_t bindex,
22360+ unsigned char shwh)
1facf9fc 22361+{
22362+ int err;
22363+ struct au_vdir_destr *str;
22364+ struct au_vdir_wh *wh;
22365+
dece6358 22366+ AuDbg("%.*s\n", nlen, name);
1308ab2a 22367+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
22368+
1facf9fc 22369+ err = -ENOMEM;
dece6358 22370+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 22371+ if (unlikely(!wh))
22372+ goto out;
22373+
22374+ err = 0;
22375+ wh->wh_bindex = bindex;
dece6358
AM
22376+ if (shwh)
22377+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 22378+ str = &wh->wh_str;
dece6358
AM
22379+ str->len = nlen;
22380+ memcpy(str->name, name, nlen);
22381+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 22382+ /* smp_mb(); */
22383+
22384+ out:
22385+ return err;
22386+}
22387+
1facf9fc 22388+static int append_deblk(struct au_vdir *vdir)
22389+{
22390+ int err;
dece6358 22391+ unsigned long ul;
1facf9fc 22392+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
22393+ union au_vdir_deblk_p p, deblk_end;
22394+ unsigned char **o;
22395+
22396+ err = -ENOMEM;
dece6358
AM
22397+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
22398+ GFP_NOFS);
1facf9fc 22399+ if (unlikely(!o))
22400+ goto out;
22401+
22402+ vdir->vd_deblk = o;
22403+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
22404+ if (p.deblk) {
22405+ ul = vdir->vd_nblk++;
22406+ vdir->vd_deblk[ul] = p.deblk;
22407+ vdir->vd_last.ul = ul;
22408+ vdir->vd_last.p.deblk = p.deblk;
22409+ deblk_end.deblk = p.deblk + deblk_sz;
22410+ err = set_deblk_end(&p, &deblk_end);
22411+ }
22412+
22413+ out:
22414+ return err;
22415+}
22416+
dece6358
AM
22417+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
22418+ unsigned int d_type, struct au_nhash *delist)
22419+{
22420+ int err;
22421+ unsigned int sz;
22422+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
22423+ union au_vdir_deblk_p p, *room, deblk_end;
22424+ struct au_vdir_dehstr *dehstr;
22425+
22426+ p.deblk = last_deblk(vdir);
22427+ deblk_end.deblk = p.deblk + deblk_sz;
22428+ room = &vdir->vd_last.p;
22429+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
22430+ || !is_deblk_end(room, &deblk_end));
22431+
22432+ sz = calc_size(nlen);
22433+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
22434+ err = append_deblk(vdir);
22435+ if (unlikely(err))
22436+ goto out;
22437+
22438+ p.deblk = last_deblk(vdir);
22439+ deblk_end.deblk = p.deblk + deblk_sz;
22440+ /* smp_mb(); */
22441+ AuDebugOn(room->deblk != p.deblk);
22442+ }
22443+
22444+ err = -ENOMEM;
4a4d8108 22445+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
22446+ if (unlikely(!dehstr))
22447+ goto out;
22448+
22449+ dehstr->str = &room->de->de_str;
22450+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
22451+ room->de->de_ino = ino;
22452+ room->de->de_type = d_type;
22453+ room->de->de_str.len = nlen;
22454+ memcpy(room->de->de_str.name, name, nlen);
22455+
22456+ err = 0;
22457+ room->deblk += sz;
22458+ if (unlikely(set_deblk_end(room, &deblk_end)))
22459+ err = append_deblk(vdir);
22460+ /* smp_mb(); */
22461+
22462+ out:
22463+ return err;
22464+}
22465+
22466+/* ---------------------------------------------------------------------- */
22467+
22468+void au_vdir_free(struct au_vdir *vdir)
22469+{
22470+ unsigned char **deblk;
22471+
22472+ deblk = vdir->vd_deblk;
22473+ while (vdir->vd_nblk--)
22474+ kfree(*deblk++);
22475+ kfree(vdir->vd_deblk);
22476+ au_cache_free_vdir(vdir);
22477+}
22478+
1308ab2a 22479+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 22480+{
22481+ struct au_vdir *vdir;
1308ab2a 22482+ struct super_block *sb;
1facf9fc 22483+ int err;
22484+
1308ab2a 22485+ sb = file->f_dentry->d_sb;
dece6358
AM
22486+ SiMustAnyLock(sb);
22487+
1facf9fc 22488+ err = -ENOMEM;
22489+ vdir = au_cache_alloc_vdir();
22490+ if (unlikely(!vdir))
22491+ goto out;
22492+
22493+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
22494+ if (unlikely(!vdir->vd_deblk))
22495+ goto out_free;
22496+
22497+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 22498+ if (!vdir->vd_deblk_sz) {
22499+ /* estimate the apropriate size for deblk */
22500+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 22501+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 22502+ }
1facf9fc 22503+ vdir->vd_nblk = 0;
22504+ vdir->vd_version = 0;
22505+ vdir->vd_jiffy = 0;
22506+ err = append_deblk(vdir);
22507+ if (!err)
22508+ return vdir; /* success */
22509+
22510+ kfree(vdir->vd_deblk);
22511+
22512+ out_free:
22513+ au_cache_free_vdir(vdir);
22514+ out:
22515+ vdir = ERR_PTR(err);
22516+ return vdir;
22517+}
22518+
22519+static int reinit_vdir(struct au_vdir *vdir)
22520+{
22521+ int err;
22522+ union au_vdir_deblk_p p, deblk_end;
22523+
22524+ while (vdir->vd_nblk > 1) {
22525+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
22526+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
22527+ vdir->vd_nblk--;
22528+ }
22529+ p.deblk = vdir->vd_deblk[0];
22530+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
22531+ err = set_deblk_end(&p, &deblk_end);
22532+ /* keep vd_dblk_sz */
22533+ vdir->vd_last.ul = 0;
22534+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
22535+ vdir->vd_version = 0;
22536+ vdir->vd_jiffy = 0;
22537+ /* smp_mb(); */
22538+ return err;
22539+}
22540+
22541+/* ---------------------------------------------------------------------- */
22542+
1facf9fc 22543+#define AuFillVdir_CALLED 1
22544+#define AuFillVdir_WHABLE (1 << 1)
dece6358 22545+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 22546+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
22547+#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
22548+#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
22549+
dece6358
AM
22550+#ifndef CONFIG_AUFS_SHWH
22551+#undef AuFillVdir_SHWH
22552+#define AuFillVdir_SHWH 0
22553+#endif
22554+
1facf9fc 22555+struct fillvdir_arg {
22556+ struct file *file;
22557+ struct au_vdir *vdir;
dece6358
AM
22558+ struct au_nhash delist;
22559+ struct au_nhash whlist;
1facf9fc 22560+ aufs_bindex_t bindex;
22561+ unsigned int flags;
22562+ int err;
22563+};
22564+
dece6358 22565+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 22566+ loff_t offset __maybe_unused, u64 h_ino,
22567+ unsigned int d_type)
22568+{
22569+ struct fillvdir_arg *arg = __arg;
22570+ char *name = (void *)__name;
22571+ struct super_block *sb;
1facf9fc 22572+ ino_t ino;
dece6358 22573+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 22574+
1facf9fc 22575+ arg->err = 0;
dece6358 22576+ sb = arg->file->f_dentry->d_sb;
1facf9fc 22577+ au_fset_fillvdir(arg->flags, CALLED);
22578+ /* smp_mb(); */
dece6358 22579+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 22580+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
22581+ if (test_known(&arg->delist, name, nlen)
22582+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
22583+ goto out; /* already exists or whiteouted */
1facf9fc 22584+
22585+ sb = arg->file->f_dentry->d_sb;
dece6358 22586+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
22587+ if (!arg->err) {
22588+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
22589+ d_type = DT_UNKNOWN;
dece6358
AM
22590+ arg->err = append_de(arg->vdir, name, nlen, ino,
22591+ d_type, &arg->delist);
4a4d8108 22592+ }
1facf9fc 22593+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
22594+ name += AUFS_WH_PFX_LEN;
dece6358
AM
22595+ nlen -= AUFS_WH_PFX_LEN;
22596+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
22597+ goto out; /* already whiteouted */
1facf9fc 22598+
dece6358
AM
22599+ if (shwh)
22600+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
22601+ &ino);
4a4d8108
AM
22602+ if (!arg->err) {
22603+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
22604+ d_type = DT_UNKNOWN;
1facf9fc 22605+ arg->err = au_nhash_append_wh
dece6358
AM
22606+ (&arg->whlist, name, nlen, ino, d_type,
22607+ arg->bindex, shwh);
4a4d8108 22608+ }
1facf9fc 22609+ }
22610+
22611+ out:
22612+ if (!arg->err)
22613+ arg->vdir->vd_jiffy = jiffies;
22614+ /* smp_mb(); */
22615+ AuTraceErr(arg->err);
22616+ return arg->err;
22617+}
22618+
dece6358
AM
22619+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
22620+ struct au_nhash *whlist, struct au_nhash *delist)
22621+{
22622+#ifdef CONFIG_AUFS_SHWH
22623+ int err;
22624+ unsigned int nh, u;
22625+ struct hlist_head *head;
22626+ struct au_vdir_wh *tpos;
22627+ struct hlist_node *pos, *n;
22628+ char *p, *o;
22629+ struct au_vdir_destr *destr;
22630+
22631+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
22632+
22633+ err = -ENOMEM;
4a4d8108 22634+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
22635+ if (unlikely(!p))
22636+ goto out;
22637+
22638+ err = 0;
22639+ nh = whlist->nh_num;
22640+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
22641+ p += AUFS_WH_PFX_LEN;
22642+ for (u = 0; u < nh; u++) {
22643+ head = whlist->nh_head + u;
22644+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
22645+ destr = &tpos->wh_str;
22646+ memcpy(p, destr->name, destr->len);
22647+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
22648+ tpos->wh_ino, tpos->wh_type, delist);
22649+ if (unlikely(err))
22650+ break;
22651+ }
22652+ }
22653+
22654+ __putname(o);
22655+
22656+ out:
22657+ AuTraceErr(err);
22658+ return err;
22659+#else
22660+ return 0;
22661+#endif
22662+}
22663+
1facf9fc 22664+static int au_do_read_vdir(struct fillvdir_arg *arg)
22665+{
22666+ int err;
dece6358 22667+ unsigned int rdhash;
1facf9fc 22668+ loff_t offset;
dece6358
AM
22669+ aufs_bindex_t bend, bindex, bstart;
22670+ unsigned char shwh;
1facf9fc 22671+ struct file *hf, *file;
22672+ struct super_block *sb;
22673+
1facf9fc 22674+ file = arg->file;
22675+ sb = file->f_dentry->d_sb;
dece6358
AM
22676+ SiMustAnyLock(sb);
22677+
22678+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 22679+ if (!rdhash)
22680+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
22681+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
22682+ if (unlikely(err))
1facf9fc 22683+ goto out;
dece6358
AM
22684+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
22685+ if (unlikely(err))
1facf9fc 22686+ goto out_delist;
22687+
22688+ err = 0;
22689+ arg->flags = 0;
dece6358
AM
22690+ shwh = 0;
22691+ if (au_opt_test(au_mntflags(sb), SHWH)) {
22692+ shwh = 1;
22693+ au_fset_fillvdir(arg->flags, SHWH);
22694+ }
22695+ bstart = au_fbstart(file);
4a4d8108 22696+ bend = au_fbend_dir(file);
dece6358 22697+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 22698+ hf = au_hf_dir(file, bindex);
1facf9fc 22699+ if (!hf)
22700+ continue;
22701+
22702+ offset = vfsub_llseek(hf, 0, SEEK_SET);
22703+ err = offset;
22704+ if (unlikely(offset))
22705+ break;
22706+
22707+ arg->bindex = bindex;
22708+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
22709+ if (shwh
22710+ || (bindex != bend
22711+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 22712+ au_fset_fillvdir(arg->flags, WHABLE);
22713+ do {
22714+ arg->err = 0;
22715+ au_fclr_fillvdir(arg->flags, CALLED);
22716+ /* smp_mb(); */
22717+ err = vfsub_readdir(hf, fillvdir, arg);
22718+ if (err >= 0)
22719+ err = arg->err;
22720+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
22721+ }
dece6358
AM
22722+
22723+ if (!err && shwh)
22724+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
22725+
22726+ au_nhash_wh_free(&arg->whlist);
1facf9fc 22727+
22728+ out_delist:
dece6358 22729+ au_nhash_de_free(&arg->delist);
1facf9fc 22730+ out:
22731+ return err;
22732+}
22733+
22734+static int read_vdir(struct file *file, int may_read)
22735+{
22736+ int err;
22737+ unsigned long expire;
22738+ unsigned char do_read;
22739+ struct fillvdir_arg arg;
22740+ struct inode *inode;
22741+ struct au_vdir *vdir, *allocated;
22742+
22743+ err = 0;
22744+ inode = file->f_dentry->d_inode;
22745+ IMustLock(inode);
dece6358
AM
22746+ SiMustAnyLock(inode->i_sb);
22747+
1facf9fc 22748+ allocated = NULL;
22749+ do_read = 0;
22750+ expire = au_sbi(inode->i_sb)->si_rdcache;
22751+ vdir = au_ivdir(inode);
22752+ if (!vdir) {
22753+ do_read = 1;
1308ab2a 22754+ vdir = alloc_vdir(file);
1facf9fc 22755+ err = PTR_ERR(vdir);
22756+ if (IS_ERR(vdir))
22757+ goto out;
22758+ err = 0;
22759+ allocated = vdir;
22760+ } else if (may_read
22761+ && (inode->i_version != vdir->vd_version
22762+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
22763+ do_read = 1;
22764+ err = reinit_vdir(vdir);
22765+ if (unlikely(err))
22766+ goto out;
22767+ }
22768+
22769+ if (!do_read)
22770+ return 0; /* success */
22771+
22772+ arg.file = file;
22773+ arg.vdir = vdir;
22774+ err = au_do_read_vdir(&arg);
22775+ if (!err) {
22776+ /* file->f_pos = 0; */
22777+ vdir->vd_version = inode->i_version;
22778+ vdir->vd_last.ul = 0;
22779+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
22780+ if (allocated)
22781+ au_set_ivdir(inode, allocated);
22782+ } else if (allocated)
22783+ au_vdir_free(allocated);
22784+
22785+ out:
22786+ return err;
22787+}
22788+
22789+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
22790+{
22791+ int err, rerr;
22792+ unsigned long ul, n;
22793+ const unsigned int deblk_sz = src->vd_deblk_sz;
22794+
22795+ AuDebugOn(tgt->vd_nblk != 1);
22796+
22797+ err = -ENOMEM;
22798+ if (tgt->vd_nblk < src->vd_nblk) {
22799+ unsigned char **p;
22800+
dece6358
AM
22801+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
22802+ GFP_NOFS);
1facf9fc 22803+ if (unlikely(!p))
22804+ goto out;
22805+ tgt->vd_deblk = p;
22806+ }
22807+
1308ab2a 22808+ if (tgt->vd_deblk_sz != deblk_sz) {
22809+ unsigned char *p;
22810+
22811+ tgt->vd_deblk_sz = deblk_sz;
22812+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
22813+ if (unlikely(!p))
22814+ goto out;
22815+ tgt->vd_deblk[0] = p;
22816+ }
1facf9fc 22817+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 22818+ tgt->vd_version = src->vd_version;
22819+ tgt->vd_jiffy = src->vd_jiffy;
22820+
22821+ n = src->vd_nblk;
22822+ for (ul = 1; ul < n; ul++) {
dece6358
AM
22823+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
22824+ GFP_NOFS);
22825+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 22826+ goto out;
1308ab2a 22827+ tgt->vd_nblk++;
1facf9fc 22828+ }
1308ab2a 22829+ tgt->vd_nblk = n;
22830+ tgt->vd_last.ul = tgt->vd_last.ul;
22831+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
22832+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
22833+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 22834+ /* smp_mb(); */
22835+ return 0; /* success */
22836+
22837+ out:
22838+ rerr = reinit_vdir(tgt);
22839+ BUG_ON(rerr);
22840+ return err;
22841+}
22842+
22843+int au_vdir_init(struct file *file)
22844+{
22845+ int err;
22846+ struct inode *inode;
22847+ struct au_vdir *vdir_cache, *allocated;
22848+
22849+ err = read_vdir(file, !file->f_pos);
22850+ if (unlikely(err))
22851+ goto out;
22852+
22853+ allocated = NULL;
22854+ vdir_cache = au_fvdir_cache(file);
22855+ if (!vdir_cache) {
1308ab2a 22856+ vdir_cache = alloc_vdir(file);
1facf9fc 22857+ err = PTR_ERR(vdir_cache);
22858+ if (IS_ERR(vdir_cache))
22859+ goto out;
22860+ allocated = vdir_cache;
22861+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
22862+ err = reinit_vdir(vdir_cache);
22863+ if (unlikely(err))
22864+ goto out;
22865+ } else
22866+ return 0; /* success */
22867+
22868+ inode = file->f_dentry->d_inode;
22869+ err = copy_vdir(vdir_cache, au_ivdir(inode));
22870+ if (!err) {
22871+ file->f_version = inode->i_version;
22872+ if (allocated)
22873+ au_set_fvdir_cache(file, allocated);
22874+ } else if (allocated)
22875+ au_vdir_free(allocated);
22876+
22877+ out:
22878+ return err;
22879+}
22880+
22881+static loff_t calc_offset(struct au_vdir *vdir)
22882+{
22883+ loff_t offset;
22884+ union au_vdir_deblk_p p;
22885+
22886+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
22887+ offset = vdir->vd_last.p.deblk - p.deblk;
22888+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
22889+ return offset;
22890+}
22891+
22892+/* returns true or false */
22893+static int seek_vdir(struct file *file)
22894+{
22895+ int valid;
22896+ unsigned int deblk_sz;
22897+ unsigned long ul, n;
22898+ loff_t offset;
22899+ union au_vdir_deblk_p p, deblk_end;
22900+ struct au_vdir *vdir_cache;
22901+
22902+ valid = 1;
22903+ vdir_cache = au_fvdir_cache(file);
22904+ offset = calc_offset(vdir_cache);
22905+ AuDbg("offset %lld\n", offset);
22906+ if (file->f_pos == offset)
22907+ goto out;
22908+
22909+ vdir_cache->vd_last.ul = 0;
22910+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
22911+ if (!file->f_pos)
22912+ goto out;
22913+
22914+ valid = 0;
22915+ deblk_sz = vdir_cache->vd_deblk_sz;
22916+ ul = div64_u64(file->f_pos, deblk_sz);
22917+ AuDbg("ul %lu\n", ul);
22918+ if (ul >= vdir_cache->vd_nblk)
22919+ goto out;
22920+
22921+ n = vdir_cache->vd_nblk;
22922+ for (; ul < n; ul++) {
22923+ p.deblk = vdir_cache->vd_deblk[ul];
22924+ deblk_end.deblk = p.deblk + deblk_sz;
22925+ offset = ul;
22926+ offset *= deblk_sz;
22927+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
22928+ unsigned int l;
22929+
22930+ l = calc_size(p.de->de_str.len);
22931+ offset += l;
22932+ p.deblk += l;
22933+ }
22934+ if (!is_deblk_end(&p, &deblk_end)) {
22935+ valid = 1;
22936+ vdir_cache->vd_last.ul = ul;
22937+ vdir_cache->vd_last.p = p;
22938+ break;
22939+ }
22940+ }
22941+
22942+ out:
22943+ /* smp_mb(); */
22944+ AuTraceErr(!valid);
22945+ return valid;
22946+}
22947+
22948+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
22949+{
22950+ int err;
22951+ unsigned int l, deblk_sz;
22952+ union au_vdir_deblk_p deblk_end;
22953+ struct au_vdir *vdir_cache;
22954+ struct au_vdir_de *de;
22955+
22956+ vdir_cache = au_fvdir_cache(file);
22957+ if (!seek_vdir(file))
22958+ return 0;
22959+
22960+ deblk_sz = vdir_cache->vd_deblk_sz;
22961+ while (1) {
22962+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
22963+ deblk_end.deblk += deblk_sz;
22964+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
22965+ de = vdir_cache->vd_last.p.de;
22966+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
22967+ de->de_str.len, de->de_str.name, file->f_pos,
22968+ (unsigned long)de->de_ino, de->de_type);
22969+ err = filldir(dirent, de->de_str.name, de->de_str.len,
22970+ file->f_pos, de->de_ino, de->de_type);
22971+ if (unlikely(err)) {
22972+ AuTraceErr(err);
22973+ /* todo: ignore the error caused by udba? */
22974+ /* return err; */
22975+ return 0;
22976+ }
22977+
22978+ l = calc_size(de->de_str.len);
22979+ vdir_cache->vd_last.p.deblk += l;
22980+ file->f_pos += l;
22981+ }
22982+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
22983+ vdir_cache->vd_last.ul++;
22984+ vdir_cache->vd_last.p.deblk
22985+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
22986+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
22987+ continue;
22988+ }
22989+ break;
22990+ }
22991+
22992+ /* smp_mb(); */
22993+ return 0;
22994+}
b752ccd1
AM
22995diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
22996--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
22997+++ linux/fs/aufs/vfsub.c 2010-08-21 21:00:02.986708041 +0200
22998@@ -0,0 +1,786 @@
1facf9fc 22999+/*
4a4d8108 23000+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 23001+ *
23002+ * This program, aufs is free software; you can redistribute it and/or modify
23003+ * it under the terms of the GNU General Public License as published by
23004+ * the Free Software Foundation; either version 2 of the License, or
23005+ * (at your option) any later version.
dece6358
AM
23006+ *
23007+ * This program is distributed in the hope that it will be useful,
23008+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23009+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23010+ * GNU General Public License for more details.
23011+ *
23012+ * You should have received a copy of the GNU General Public License
23013+ * along with this program; if not, write to the Free Software
23014+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23015+ */
23016+
23017+/*
23018+ * sub-routines for VFS
23019+ */
23020+
4a4d8108 23021+#include <linux/file.h>
1308ab2a 23022+#include <linux/ima.h>
dece6358
AM
23023+#include <linux/namei.h>
23024+#include <linux/security.h>
23025+#include <linux/splice.h>
1facf9fc 23026+#include <linux/uaccess.h>
23027+#include "aufs.h"
23028+
23029+int vfsub_update_h_iattr(struct path *h_path, int *did)
23030+{
23031+ int err;
23032+ struct kstat st;
23033+ struct super_block *h_sb;
23034+
23035+ /* for remote fs, leave work for its getattr or d_revalidate */
23036+ /* for bad i_attr fs, handle them in aufs_getattr() */
23037+ /* still some fs may acquire i_mutex. we need to skip them */
23038+ err = 0;
23039+ if (!did)
23040+ did = &err;
23041+ h_sb = h_path->dentry->d_sb;
23042+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
23043+ if (*did)
23044+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
23045+
23046+ return err;
23047+}
23048+
23049+/* ---------------------------------------------------------------------- */
23050+
4a4d8108
AM
23051+static int au_conv_oflags(int flags)
23052+{
23053+ int mask = 0;
23054+
23055+#ifdef CONFIG_IMA
23056+ fmode_t fmode;
23057+
23058+ /* mask = MAY_OPEN; */
23059+ fmode = OPEN_FMODE(flags);
23060+ if (fmode & FMODE_READ)
23061+ mask |= MAY_READ;
23062+ if ((fmode & FMODE_WRITE)
23063+ || (flags & O_TRUNC))
23064+ mask |= MAY_WRITE;
23065+ /*
23066+ * if (flags & O_APPEND)
23067+ * mask |= MAY_APPEND;
23068+ */
23069+ if (flags & vfsub_fmode_to_uint(FMODE_EXEC))
23070+ mask |= MAY_EXEC;
23071+
23072+ AuDbg("flags 0x%x, mask 0x%x\n", flags, mask);
23073+#endif
23074+
23075+ return mask;
23076+}
23077+
23078+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 23079+{
23080+ struct file *file;
4a4d8108 23081+ int err;
1308ab2a 23082+
4a4d8108
AM
23083+ path_get(path);
23084+ file = dentry_open(path->dentry, path->mnt, flags, current_cred());
1308ab2a 23085+ if (IS_ERR(file))
4a4d8108
AM
23086+ goto out;
23087+
23088+ err = ima_file_check(file, au_conv_oflags(flags));
23089+ if (unlikely(err)) {
23090+ fput(file);
23091+ file = ERR_PTR(err);
23092+ }
23093+out:
1308ab2a 23094+ return file;
23095+}
23096+
1facf9fc 23097+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
23098+{
23099+ struct file *file;
23100+
1facf9fc 23101+ file = filp_open(path, oflags, mode);
1facf9fc 23102+ if (IS_ERR(file))
23103+ goto out;
23104+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23105+
23106+ out:
23107+ return file;
23108+}
23109+
23110+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
23111+{
23112+ int err;
23113+
1facf9fc 23114+ err = kern_path(name, flags, path);
1facf9fc 23115+ if (!err && path->dentry->d_inode)
23116+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
23117+ return err;
23118+}
23119+
23120+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
23121+ int len)
23122+{
23123+ struct path path = {
23124+ .mnt = NULL
23125+ };
23126+
1308ab2a 23127+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 23128+ IMustLock(parent->d_inode);
23129+
23130+ path.dentry = lookup_one_len(name, parent, len);
23131+ if (IS_ERR(path.dentry))
23132+ goto out;
23133+ if (path.dentry->d_inode)
23134+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
23135+
23136+ out:
4a4d8108 23137+ AuTraceErrPtr(path.dentry);
1facf9fc 23138+ return path.dentry;
23139+}
23140+
23141+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
23142+{
23143+ struct path path = {
23144+ .mnt = nd->path.mnt
23145+ };
23146+
23147+ IMustLock(nd->path.dentry->d_inode);
23148+
23149+ path.dentry = lookup_hash(nd);
4a4d8108
AM
23150+ if (IS_ERR(path.dentry))
23151+ goto out;
23152+ if (path.dentry->d_inode)
1facf9fc 23153+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
23154+
4a4d8108
AM
23155+ out:
23156+ AuTraceErrPtr(path.dentry);
1facf9fc 23157+ return path.dentry;
23158+}
23159+
23160+/* ---------------------------------------------------------------------- */
23161+
23162+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
23163+ struct dentry *d2, struct au_hinode *hdir2)
23164+{
23165+ struct dentry *d;
23166+
1facf9fc 23167+ d = lock_rename(d1, d2);
4a4d8108 23168+ au_hn_suspend(hdir1);
1facf9fc 23169+ if (hdir1 != hdir2)
4a4d8108 23170+ au_hn_suspend(hdir2);
1facf9fc 23171+
23172+ return d;
23173+}
23174+
23175+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
23176+ struct dentry *d2, struct au_hinode *hdir2)
23177+{
4a4d8108 23178+ au_hn_resume(hdir1);
1facf9fc 23179+ if (hdir1 != hdir2)
4a4d8108 23180+ au_hn_resume(hdir2);
1facf9fc 23181+ unlock_rename(d1, d2);
1facf9fc 23182+}
23183+
23184+/* ---------------------------------------------------------------------- */
23185+
23186+int vfsub_create(struct inode *dir, struct path *path, int mode)
23187+{
23188+ int err;
23189+ struct dentry *d;
23190+
23191+ IMustLock(dir);
23192+
23193+ d = path->dentry;
23194+ path->dentry = d->d_parent;
b752ccd1 23195+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 23196+ path->dentry = d;
23197+ if (unlikely(err))
23198+ goto out;
23199+
23200+ if (au_test_fs_null_nd(dir->i_sb))
23201+ err = vfs_create(dir, path->dentry, mode, NULL);
23202+ else {
23203+ struct nameidata h_nd;
23204+
23205+ memset(&h_nd, 0, sizeof(h_nd));
23206+ h_nd.flags = LOOKUP_CREATE;
23207+ h_nd.intent.open.flags = O_CREAT
23208+ | vfsub_fmode_to_uint(FMODE_READ);
23209+ h_nd.intent.open.create_mode = mode;
23210+ h_nd.path.dentry = path->dentry->d_parent;
23211+ h_nd.path.mnt = path->mnt;
23212+ path_get(&h_nd.path);
23213+ err = vfs_create(dir, path->dentry, mode, &h_nd);
23214+ path_put(&h_nd.path);
23215+ }
23216+
23217+ if (!err) {
23218+ struct path tmp = *path;
23219+ int did;
23220+
23221+ vfsub_update_h_iattr(&tmp, &did);
23222+ if (did) {
23223+ tmp.dentry = path->dentry->d_parent;
23224+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23225+ }
23226+ /*ignore*/
23227+ }
23228+
23229+ out:
23230+ return err;
23231+}
23232+
23233+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
23234+{
23235+ int err;
23236+ struct dentry *d;
23237+
23238+ IMustLock(dir);
23239+
23240+ d = path->dentry;
23241+ path->dentry = d->d_parent;
b752ccd1 23242+ err = security_path_symlink(path, d, symname);
1facf9fc 23243+ path->dentry = d;
23244+ if (unlikely(err))
23245+ goto out;
23246+
23247+ err = vfs_symlink(dir, path->dentry, symname);
23248+ if (!err) {
23249+ struct path tmp = *path;
23250+ int did;
23251+
23252+ vfsub_update_h_iattr(&tmp, &did);
23253+ if (did) {
23254+ tmp.dentry = path->dentry->d_parent;
23255+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23256+ }
23257+ /*ignore*/
23258+ }
23259+
23260+ out:
23261+ return err;
23262+}
23263+
23264+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
23265+{
23266+ int err;
23267+ struct dentry *d;
23268+
23269+ IMustLock(dir);
23270+
23271+ d = path->dentry;
23272+ path->dentry = d->d_parent;
b752ccd1 23273+ err = security_path_mknod(path, d, mode, dev);
1facf9fc 23274+ path->dentry = d;
23275+ if (unlikely(err))
23276+ goto out;
23277+
23278+ err = vfs_mknod(dir, path->dentry, mode, dev);
23279+ if (!err) {
23280+ struct path tmp = *path;
23281+ int did;
23282+
23283+ vfsub_update_h_iattr(&tmp, &did);
23284+ if (did) {
23285+ tmp.dentry = path->dentry->d_parent;
23286+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23287+ }
23288+ /*ignore*/
23289+ }
23290+
23291+ out:
23292+ return err;
23293+}
23294+
23295+static int au_test_nlink(struct inode *inode)
23296+{
23297+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
23298+
23299+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
23300+ || inode->i_nlink < link_max)
23301+ return 0;
23302+ return -EMLINK;
23303+}
23304+
23305+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
23306+{
23307+ int err;
23308+ struct dentry *d;
23309+
23310+ IMustLock(dir);
23311+
23312+ err = au_test_nlink(src_dentry->d_inode);
23313+ if (unlikely(err))
23314+ return err;
23315+
23316+ d = path->dentry;
23317+ path->dentry = d->d_parent;
b752ccd1 23318+ err = security_path_link(src_dentry, path, d);
1facf9fc 23319+ path->dentry = d;
23320+ if (unlikely(err))
23321+ goto out;
23322+
1facf9fc 23323+ err = vfs_link(src_dentry, dir, path->dentry);
1facf9fc 23324+ if (!err) {
23325+ struct path tmp = *path;
23326+ int did;
23327+
23328+ /* fuse has different memory inode for the same inumber */
23329+ vfsub_update_h_iattr(&tmp, &did);
23330+ if (did) {
23331+ tmp.dentry = path->dentry->d_parent;
23332+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23333+ tmp.dentry = src_dentry;
23334+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23335+ }
23336+ /*ignore*/
23337+ }
23338+
23339+ out:
23340+ return err;
23341+}
23342+
23343+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
23344+ struct inode *dir, struct path *path)
23345+{
23346+ int err;
23347+ struct path tmp = {
23348+ .mnt = path->mnt
23349+ };
23350+ struct dentry *d;
23351+
23352+ IMustLock(dir);
23353+ IMustLock(src_dir);
23354+
23355+ d = path->dentry;
23356+ path->dentry = d->d_parent;
23357+ tmp.dentry = src_dentry->d_parent;
b752ccd1 23358+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 23359+ path->dentry = d;
23360+ if (unlikely(err))
23361+ goto out;
23362+
1facf9fc 23363+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
1facf9fc 23364+ if (!err) {
23365+ int did;
23366+
23367+ tmp.dentry = d->d_parent;
23368+ vfsub_update_h_iattr(&tmp, &did);
23369+ if (did) {
23370+ tmp.dentry = src_dentry;
23371+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23372+ tmp.dentry = src_dentry->d_parent;
23373+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23374+ }
23375+ /*ignore*/
23376+ }
23377+
23378+ out:
23379+ return err;
23380+}
23381+
23382+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
23383+{
23384+ int err;
23385+ struct dentry *d;
23386+
23387+ IMustLock(dir);
23388+
23389+ d = path->dentry;
23390+ path->dentry = d->d_parent;
b752ccd1 23391+ err = security_path_mkdir(path, d, mode);
1facf9fc 23392+ path->dentry = d;
23393+ if (unlikely(err))
23394+ goto out;
23395+
23396+ err = vfs_mkdir(dir, path->dentry, mode);
23397+ if (!err) {
23398+ struct path tmp = *path;
23399+ int did;
23400+
23401+ vfsub_update_h_iattr(&tmp, &did);
23402+ if (did) {
23403+ tmp.dentry = path->dentry->d_parent;
23404+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23405+ }
23406+ /*ignore*/
23407+ }
23408+
23409+ out:
23410+ return err;
23411+}
23412+
23413+int vfsub_rmdir(struct inode *dir, struct path *path)
23414+{
23415+ int err;
23416+ struct dentry *d;
23417+
23418+ IMustLock(dir);
23419+
23420+ d = path->dentry;
23421+ path->dentry = d->d_parent;
b752ccd1 23422+ err = security_path_rmdir(path, d);
1facf9fc 23423+ path->dentry = d;
23424+ if (unlikely(err))
23425+ goto out;
23426+
1facf9fc 23427+ err = vfs_rmdir(dir, path->dentry);
1facf9fc 23428+ if (!err) {
23429+ struct path tmp = {
23430+ .dentry = path->dentry->d_parent,
23431+ .mnt = path->mnt
23432+ };
23433+
23434+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
23435+ }
23436+
23437+ out:
23438+ return err;
23439+}
23440+
23441+/* ---------------------------------------------------------------------- */
23442+
23443+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
23444+ loff_t *ppos)
23445+{
23446+ ssize_t err;
23447+
23448+ err = vfs_read(file, ubuf, count, ppos);
23449+ if (err >= 0)
23450+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23451+ return err;
23452+}
23453+
23454+/* todo: kernel_read()? */
23455+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
23456+ loff_t *ppos)
23457+{
23458+ ssize_t err;
23459+ mm_segment_t oldfs;
b752ccd1
AM
23460+ union {
23461+ void *k;
23462+ char __user *u;
23463+ } buf;
1facf9fc 23464+
b752ccd1 23465+ buf.k = kbuf;
1facf9fc 23466+ oldfs = get_fs();
23467+ set_fs(KERNEL_DS);
b752ccd1 23468+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 23469+ set_fs(oldfs);
23470+ return err;
23471+}
23472+
23473+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
23474+ loff_t *ppos)
23475+{
23476+ ssize_t err;
23477+
1facf9fc 23478+ err = vfs_write(file, ubuf, count, ppos);
1facf9fc 23479+ if (err >= 0)
23480+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23481+ return err;
23482+}
23483+
23484+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
23485+{
23486+ ssize_t err;
23487+ mm_segment_t oldfs;
b752ccd1
AM
23488+ union {
23489+ void *k;
23490+ const char __user *u;
23491+ } buf;
1facf9fc 23492+
b752ccd1 23493+ buf.k = kbuf;
1facf9fc 23494+ oldfs = get_fs();
23495+ set_fs(KERNEL_DS);
b752ccd1 23496+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 23497+ set_fs(oldfs);
23498+ return err;
23499+}
23500+
4a4d8108
AM
23501+int vfsub_flush(struct file *file, fl_owner_t id)
23502+{
23503+ int err;
23504+
23505+ err = 0;
23506+ if (file->f_op && file->f_op->flush) {
23507+ err = file->f_op->flush(file, id);
23508+ if (!err)
23509+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
23510+ /*ignore*/
23511+ }
23512+ return err;
23513+}
23514+
1facf9fc 23515+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
23516+{
23517+ int err;
23518+
1facf9fc 23519+ err = vfs_readdir(file, filldir, arg);
1facf9fc 23520+ if (err >= 0)
23521+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23522+ return err;
23523+}
23524+
23525+long vfsub_splice_to(struct file *in, loff_t *ppos,
23526+ struct pipe_inode_info *pipe, size_t len,
23527+ unsigned int flags)
23528+{
23529+ long err;
23530+
0fc653ad 23531+ err = do_splice_to(in, ppos, pipe, len, flags);
4a4d8108 23532+ file_accessed(in);
1facf9fc 23533+ if (err >= 0)
23534+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
23535+ return err;
23536+}
23537+
23538+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
23539+ loff_t *ppos, size_t len, unsigned int flags)
23540+{
23541+ long err;
23542+
0fc653ad 23543+ err = do_splice_from(pipe, out, ppos, len, flags);
1facf9fc 23544+ if (err >= 0)
23545+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
23546+ return err;
23547+}
23548+
23549+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
23550+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
23551+ struct file *h_file)
23552+{
23553+ int err;
23554+ struct inode *h_inode;
23555+
23556+ h_inode = h_path->dentry->d_inode;
23557+ if (!h_file) {
23558+ err = mnt_want_write(h_path->mnt);
23559+ if (err)
23560+ goto out;
23561+ err = inode_permission(h_inode, MAY_WRITE);
23562+ if (err)
23563+ goto out_mnt;
23564+ err = get_write_access(h_inode);
23565+ if (err)
23566+ goto out_mnt;
4a4d8108 23567+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 23568+ if (err)
23569+ goto out_inode;
23570+ }
23571+
23572+ err = locks_verify_truncate(h_inode, h_file, length);
23573+ if (!err)
23574+ err = security_path_truncate(h_path, length, attr);
b752ccd1 23575+ if (!err)
1facf9fc 23576+ err = do_truncate(h_path->dentry, length, attr, h_file);
1facf9fc 23577+
23578+ out_inode:
23579+ if (!h_file)
23580+ put_write_access(h_inode);
23581+ out_mnt:
23582+ if (!h_file)
23583+ mnt_drop_write(h_path->mnt);
23584+ out:
23585+ return err;
23586+}
23587+
23588+/* ---------------------------------------------------------------------- */
23589+
23590+struct au_vfsub_mkdir_args {
23591+ int *errp;
23592+ struct inode *dir;
23593+ struct path *path;
23594+ int mode;
23595+};
23596+
23597+static void au_call_vfsub_mkdir(void *args)
23598+{
23599+ struct au_vfsub_mkdir_args *a = args;
23600+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
23601+}
23602+
23603+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
23604+{
23605+ int err, do_sio, wkq_err;
23606+
23607+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
23608+ if (!do_sio)
23609+ err = vfsub_mkdir(dir, path, mode);
23610+ else {
23611+ struct au_vfsub_mkdir_args args = {
23612+ .errp = &err,
23613+ .dir = dir,
23614+ .path = path,
23615+ .mode = mode
23616+ };
23617+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
23618+ if (unlikely(wkq_err))
23619+ err = wkq_err;
23620+ }
23621+
23622+ return err;
23623+}
23624+
23625+struct au_vfsub_rmdir_args {
23626+ int *errp;
23627+ struct inode *dir;
23628+ struct path *path;
23629+};
23630+
23631+static void au_call_vfsub_rmdir(void *args)
23632+{
23633+ struct au_vfsub_rmdir_args *a = args;
23634+ *a->errp = vfsub_rmdir(a->dir, a->path);
23635+}
23636+
23637+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
23638+{
23639+ int err, do_sio, wkq_err;
23640+
23641+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
23642+ if (!do_sio)
23643+ err = vfsub_rmdir(dir, path);
23644+ else {
23645+ struct au_vfsub_rmdir_args args = {
23646+ .errp = &err,
23647+ .dir = dir,
23648+ .path = path
23649+ };
23650+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
23651+ if (unlikely(wkq_err))
23652+ err = wkq_err;
23653+ }
23654+
23655+ return err;
23656+}
23657+
23658+/* ---------------------------------------------------------------------- */
23659+
23660+struct notify_change_args {
23661+ int *errp;
23662+ struct path *path;
23663+ struct iattr *ia;
23664+};
23665+
23666+static void call_notify_change(void *args)
23667+{
23668+ struct notify_change_args *a = args;
23669+ struct inode *h_inode;
23670+
23671+ h_inode = a->path->dentry->d_inode;
23672+ IMustLock(h_inode);
23673+
23674+ *a->errp = -EPERM;
23675+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 23676+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 23677+ if (!*a->errp)
23678+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
23679+ }
23680+ AuTraceErr(*a->errp);
23681+}
23682+
23683+int vfsub_notify_change(struct path *path, struct iattr *ia)
23684+{
23685+ int err;
23686+ struct notify_change_args args = {
23687+ .errp = &err,
23688+ .path = path,
23689+ .ia = ia
23690+ };
23691+
23692+ call_notify_change(&args);
23693+
23694+ return err;
23695+}
23696+
23697+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
23698+{
23699+ int err, wkq_err;
23700+ struct notify_change_args args = {
23701+ .errp = &err,
23702+ .path = path,
23703+ .ia = ia
23704+ };
23705+
23706+ wkq_err = au_wkq_wait(call_notify_change, &args);
23707+ if (unlikely(wkq_err))
23708+ err = wkq_err;
23709+
23710+ return err;
23711+}
23712+
23713+/* ---------------------------------------------------------------------- */
23714+
23715+struct unlink_args {
23716+ int *errp;
23717+ struct inode *dir;
23718+ struct path *path;
23719+};
23720+
23721+static void call_unlink(void *args)
23722+{
23723+ struct unlink_args *a = args;
23724+ struct dentry *d = a->path->dentry;
23725+ struct inode *h_inode;
23726+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
23727+ && atomic_read(&d->d_count) == 1);
23728+
23729+ IMustLock(a->dir);
23730+
23731+ a->path->dentry = d->d_parent;
23732+ *a->errp = security_path_unlink(a->path, d);
23733+ a->path->dentry = d;
23734+ if (unlikely(*a->errp))
23735+ return;
23736+
23737+ if (!stop_sillyrename)
23738+ dget(d);
23739+ h_inode = d->d_inode;
23740+ if (h_inode)
23741+ atomic_inc(&h_inode->i_count);
23742+
1facf9fc 23743+ *a->errp = vfs_unlink(a->dir, d);
1facf9fc 23744+ if (!*a->errp) {
23745+ struct path tmp = {
23746+ .dentry = d->d_parent,
23747+ .mnt = a->path->mnt
23748+ };
23749+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
23750+ }
23751+
23752+ if (!stop_sillyrename)
23753+ dput(d);
23754+ if (h_inode)
23755+ iput(h_inode);
23756+
23757+ AuTraceErr(*a->errp);
23758+}
23759+
23760+/*
23761+ * @dir: must be locked.
23762+ * @dentry: target dentry.
23763+ */
23764+int vfsub_unlink(struct inode *dir, struct path *path, int force)
23765+{
23766+ int err;
23767+ struct unlink_args args = {
23768+ .errp = &err,
23769+ .dir = dir,
23770+ .path = path
23771+ };
23772+
23773+ if (!force)
23774+ call_unlink(&args);
23775+ else {
23776+ int wkq_err;
23777+
23778+ wkq_err = au_wkq_wait(call_unlink, &args);
23779+ if (unlikely(wkq_err))
23780+ err = wkq_err;
23781+ }
23782+
23783+ return err;
23784+}
b752ccd1
AM
23785diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
23786--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
23787+++ linux/fs/aufs/vfsub.h 2010-08-21 21:00:02.986708041 +0200
23788@@ -0,0 +1,174 @@
1facf9fc 23789+/*
4a4d8108 23790+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 23791+ *
23792+ * This program, aufs is free software; you can redistribute it and/or modify
23793+ * it under the terms of the GNU General Public License as published by
23794+ * the Free Software Foundation; either version 2 of the License, or
23795+ * (at your option) any later version.
dece6358
AM
23796+ *
23797+ * This program is distributed in the hope that it will be useful,
23798+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23799+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23800+ * GNU General Public License for more details.
23801+ *
23802+ * You should have received a copy of the GNU General Public License
23803+ * along with this program; if not, write to the Free Software
23804+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23805+ */
23806+
23807+/*
23808+ * sub-routines for VFS
23809+ */
23810+
23811+#ifndef __AUFS_VFSUB_H__
23812+#define __AUFS_VFSUB_H__
23813+
23814+#ifdef __KERNEL__
23815+
23816+#include <linux/fs.h>
1facf9fc 23817+
23818+/* ---------------------------------------------------------------------- */
23819+
23820+/* lock subclass for lower inode */
23821+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
23822+/* reduce? gave up. */
23823+enum {
23824+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
23825+ AuLsc_I_PARENT, /* lower inode, parent first */
23826+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 23827+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 23828+ AuLsc_I_CHILD,
23829+ AuLsc_I_CHILD2,
23830+ AuLsc_I_End
23831+};
23832+
23833+/* to debug easier, do not make them inlined functions */
23834+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
23835+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
23836+
23837+/* ---------------------------------------------------------------------- */
23838+
1facf9fc 23839+int vfsub_update_h_iattr(struct path *h_path, int *did);
4a4d8108 23840+struct file *vfsub_dentry_open(struct path *path, int flags);
1facf9fc 23841+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
23842+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
23843+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
23844+ int len);
23845+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
23846+
23847+/* ---------------------------------------------------------------------- */
23848+
23849+struct au_hinode;
23850+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
23851+ struct dentry *d2, struct au_hinode *hdir2);
23852+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
23853+ struct dentry *d2, struct au_hinode *hdir2);
23854+
23855+int vfsub_create(struct inode *dir, struct path *path, int mode);
23856+int vfsub_symlink(struct inode *dir, struct path *path,
23857+ const char *symname);
23858+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
23859+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
23860+ struct path *path);
23861+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
23862+ struct inode *hdir, struct path *path);
23863+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
23864+int vfsub_rmdir(struct inode *dir, struct path *path);
23865+
23866+/* ---------------------------------------------------------------------- */
23867+
23868+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
23869+ loff_t *ppos);
23870+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
23871+ loff_t *ppos);
23872+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
23873+ loff_t *ppos);
23874+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
23875+ loff_t *ppos);
4a4d8108 23876+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 23877+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
23878+
4a4d8108
AM
23879+static inline unsigned int vfsub_file_flags(struct file *file)
23880+{
23881+ unsigned int flags;
23882+
23883+ spin_lock(&file->f_lock);
23884+ flags = file->f_flags;
23885+ spin_unlock(&file->f_lock);
23886+
23887+ return flags;
23888+}
1308ab2a 23889+
1facf9fc 23890+static inline void vfsub_file_accessed(struct file *h_file)
23891+{
23892+ file_accessed(h_file);
23893+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
23894+}
23895+
23896+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
23897+ struct dentry *h_dentry)
23898+{
23899+ struct path h_path = {
23900+ .dentry = h_dentry,
23901+ .mnt = h_mnt
23902+ };
23903+ touch_atime(h_mnt, h_dentry);
23904+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
23905+}
23906+
4a4d8108
AM
23907+long vfsub_splice_to(struct file *in, loff_t *ppos,
23908+ struct pipe_inode_info *pipe, size_t len,
23909+ unsigned int flags);
23910+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
23911+ loff_t *ppos, size_t len, unsigned int flags);
23912+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
23913+ struct file *h_file);
23914+
1facf9fc 23915+/* ---------------------------------------------------------------------- */
23916+
23917+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
23918+{
23919+ loff_t err;
23920+
1facf9fc 23921+ err = vfs_llseek(file, offset, origin);
1facf9fc 23922+ return err;
23923+}
23924+
23925+/* ---------------------------------------------------------------------- */
23926+
23927+/* dirty workaround for strict type of fmode_t */
23928+union vfsub_fmu {
23929+ fmode_t fm;
23930+ unsigned int ui;
23931+};
23932+
23933+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
23934+{
23935+ union vfsub_fmu u = {
23936+ .fm = fm
23937+ };
23938+
23939+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
23940+
23941+ return u.ui;
23942+}
23943+
23944+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
23945+{
23946+ union vfsub_fmu u = {
23947+ .ui = ui
23948+ };
23949+
23950+ return u.fm;
23951+}
23952+
4a4d8108
AM
23953+/* ---------------------------------------------------------------------- */
23954+
23955+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
23956+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
23957+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
23958+int vfsub_notify_change(struct path *path, struct iattr *ia);
23959+int vfsub_unlink(struct inode *dir, struct path *path, int force);
23960+
1facf9fc 23961+#endif /* __KERNEL__ */
23962+#endif /* __AUFS_VFSUB_H__ */
b752ccd1
AM
23963diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
23964--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
23965+++ linux/fs/aufs/wbr_policy.c 2010-08-21 21:00:02.986708041 +0200
4a4d8108 23966@@ -0,0 +1,696 @@
1facf9fc 23967+/*
4a4d8108 23968+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 23969+ *
23970+ * This program, aufs is free software; you can redistribute it and/or modify
23971+ * it under the terms of the GNU General Public License as published by
23972+ * the Free Software Foundation; either version 2 of the License, or
23973+ * (at your option) any later version.
dece6358
AM
23974+ *
23975+ * This program is distributed in the hope that it will be useful,
23976+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23977+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23978+ * GNU General Public License for more details.
23979+ *
23980+ * You should have received a copy of the GNU General Public License
23981+ * along with this program; if not, write to the Free Software
23982+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23983+ */
23984+
23985+/*
23986+ * policies for selecting one among multiple writable branches
23987+ */
23988+
23989+#include <linux/statfs.h>
23990+#include "aufs.h"
23991+
23992+/* subset of cpup_attr() */
23993+static noinline_for_stack
23994+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
23995+{
23996+ int err, sbits;
23997+ struct iattr ia;
23998+ struct inode *h_isrc;
23999+
24000+ h_isrc = h_src->d_inode;
24001+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
24002+ ia.ia_mode = h_isrc->i_mode;
24003+ ia.ia_uid = h_isrc->i_uid;
24004+ ia.ia_gid = h_isrc->i_gid;
24005+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
24006+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
24007+ err = vfsub_sio_notify_change(h_path, &ia);
24008+
24009+ /* is this nfs only? */
24010+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
24011+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
24012+ ia.ia_mode = h_isrc->i_mode;
24013+ err = vfsub_sio_notify_change(h_path, &ia);
24014+ }
24015+
24016+ return err;
24017+}
24018+
24019+#define AuCpdown_PARENT_OPQ 1
24020+#define AuCpdown_WHED (1 << 1)
24021+#define AuCpdown_MADE_DIR (1 << 2)
24022+#define AuCpdown_DIROPQ (1 << 3)
24023+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
24024+#define au_fset_cpdown(flags, name) { (flags) |= AuCpdown_##name; }
24025+#define au_fclr_cpdown(flags, name) { (flags) &= ~AuCpdown_##name; }
24026+
24027+struct au_cpdown_dir_args {
24028+ struct dentry *parent;
24029+ unsigned int flags;
24030+};
24031+
24032+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
24033+ struct au_cpdown_dir_args *a)
24034+{
24035+ int err;
24036+ struct dentry *opq_dentry;
24037+
24038+ opq_dentry = au_diropq_create(dentry, bdst);
24039+ err = PTR_ERR(opq_dentry);
24040+ if (IS_ERR(opq_dentry))
24041+ goto out;
24042+ dput(opq_dentry);
24043+ au_fset_cpdown(a->flags, DIROPQ);
24044+
24045+ out:
24046+ return err;
24047+}
24048+
24049+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
24050+ struct inode *dir, aufs_bindex_t bdst)
24051+{
24052+ int err;
24053+ struct path h_path;
24054+ struct au_branch *br;
24055+
24056+ br = au_sbr(dentry->d_sb, bdst);
24057+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
24058+ err = PTR_ERR(h_path.dentry);
24059+ if (IS_ERR(h_path.dentry))
24060+ goto out;
24061+
24062+ err = 0;
24063+ if (h_path.dentry->d_inode) {
24064+ h_path.mnt = br->br_mnt;
24065+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
24066+ dentry);
24067+ }
24068+ dput(h_path.dentry);
24069+
24070+ out:
24071+ return err;
24072+}
24073+
24074+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
24075+ struct dentry *h_parent, void *arg)
24076+{
24077+ int err, rerr;
4a4d8108 24078+ aufs_bindex_t bopq, bstart;
1facf9fc 24079+ struct path h_path;
24080+ struct dentry *parent;
24081+ struct inode *h_dir, *h_inode, *inode, *dir;
24082+ struct au_cpdown_dir_args *args = arg;
24083+
24084+ bstart = au_dbstart(dentry);
24085+ /* dentry is di-locked */
24086+ parent = dget_parent(dentry);
24087+ dir = parent->d_inode;
24088+ h_dir = h_parent->d_inode;
24089+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
24090+ IMustLock(h_dir);
24091+
24092+ err = au_lkup_neg(dentry, bdst);
24093+ if (unlikely(err < 0))
24094+ goto out;
24095+ h_path.dentry = au_h_dptr(dentry, bdst);
24096+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
24097+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
24098+ S_IRWXU | S_IRUGO | S_IXUGO);
24099+ if (unlikely(err))
24100+ goto out_put;
24101+ au_fset_cpdown(args->flags, MADE_DIR);
24102+
1facf9fc 24103+ bopq = au_dbdiropq(dentry);
24104+ au_fclr_cpdown(args->flags, WHED);
24105+ au_fclr_cpdown(args->flags, DIROPQ);
24106+ if (au_dbwh(dentry) == bdst)
24107+ au_fset_cpdown(args->flags, WHED);
24108+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
24109+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 24110+ h_inode = h_path.dentry->d_inode;
24111+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
24112+ if (au_ftest_cpdown(args->flags, WHED)) {
24113+ err = au_cpdown_dir_opq(dentry, bdst, args);
24114+ if (unlikely(err)) {
24115+ mutex_unlock(&h_inode->i_mutex);
24116+ goto out_dir;
24117+ }
24118+ }
24119+
24120+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
24121+ mutex_unlock(&h_inode->i_mutex);
24122+ if (unlikely(err))
24123+ goto out_opq;
24124+
24125+ if (au_ftest_cpdown(args->flags, WHED)) {
24126+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
24127+ if (unlikely(err))
24128+ goto out_opq;
24129+ }
24130+
24131+ inode = dentry->d_inode;
24132+ if (au_ibend(inode) < bdst)
24133+ au_set_ibend(inode, bdst);
24134+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
24135+ au_hi_flags(inode, /*isdir*/1));
24136+ goto out; /* success */
24137+
24138+ /* revert */
24139+ out_opq:
24140+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
24141+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
24142+ rerr = au_diropq_remove(dentry, bdst);
24143+ mutex_unlock(&h_inode->i_mutex);
24144+ if (unlikely(rerr)) {
24145+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
24146+ AuDLNPair(dentry), bdst, rerr);
24147+ err = -EIO;
24148+ goto out;
24149+ }
24150+ }
24151+ out_dir:
24152+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
24153+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
24154+ if (unlikely(rerr)) {
24155+ AuIOErr("failed removing %.*s b%d (%d)\n",
24156+ AuDLNPair(dentry), bdst, rerr);
24157+ err = -EIO;
24158+ }
24159+ }
24160+ out_put:
24161+ au_set_h_dptr(dentry, bdst, NULL);
24162+ if (au_dbend(dentry) == bdst)
24163+ au_update_dbend(dentry);
24164+ out:
24165+ dput(parent);
24166+ return err;
24167+}
24168+
24169+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
24170+{
24171+ int err;
24172+ struct au_cpdown_dir_args args = {
24173+ .parent = dget_parent(dentry),
24174+ .flags = 0
24175+ };
24176+
24177+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
24178+ dput(args.parent);
24179+
24180+ return err;
24181+}
24182+
24183+/* ---------------------------------------------------------------------- */
24184+
24185+/* policies for create */
24186+
4a4d8108
AM
24187+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
24188+{
24189+ int err, i, j, ndentry;
24190+ aufs_bindex_t bopq;
24191+ struct au_dcsub_pages dpages;
24192+ struct au_dpage *dpage;
24193+ struct dentry **dentries, *parent, *d;
24194+
24195+ err = au_dpages_init(&dpages, GFP_NOFS);
24196+ if (unlikely(err))
24197+ goto out;
24198+ parent = dget_parent(dentry);
24199+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/0, /*test*/NULL,
24200+ /*arg*/NULL);
24201+ if (unlikely(err))
24202+ goto out_free;
24203+
24204+ err = bindex;
24205+ for (i = 0; i < dpages.ndpage; i++) {
24206+ dpage = dpages.dpages + i;
24207+ dentries = dpage->dentries;
24208+ ndentry = dpage->ndentry;
24209+ for (j = 0; j < ndentry; j++) {
24210+ d = dentries[j];
24211+ di_read_lock_parent2(d, !AuLock_IR);
24212+ bopq = au_dbdiropq(d);
24213+ di_read_unlock(d, !AuLock_IR);
24214+ if (bopq >= 0 && bopq < err)
24215+ err = bopq;
24216+ }
24217+ }
24218+
24219+out_free:
24220+ dput(parent);
24221+ au_dpages_free(&dpages);
24222+out:
24223+ return err;
24224+}
24225+
1facf9fc 24226+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
24227+{
24228+ for (; bindex >= 0; bindex--)
24229+ if (!au_br_rdonly(au_sbr(sb, bindex)))
24230+ return bindex;
24231+ return -EROFS;
24232+}
24233+
24234+/* top down parent */
24235+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
24236+{
24237+ int err;
24238+ aufs_bindex_t bstart, bindex;
24239+ struct super_block *sb;
24240+ struct dentry *parent, *h_parent;
24241+
24242+ sb = dentry->d_sb;
24243+ bstart = au_dbstart(dentry);
24244+ err = bstart;
24245+ if (!au_br_rdonly(au_sbr(sb, bstart)))
24246+ goto out;
24247+
24248+ err = -EROFS;
24249+ parent = dget_parent(dentry);
24250+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
24251+ h_parent = au_h_dptr(parent, bindex);
24252+ if (!h_parent || !h_parent->d_inode)
24253+ continue;
24254+
24255+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
24256+ err = bindex;
24257+ break;
24258+ }
24259+ }
24260+ dput(parent);
24261+
24262+ /* bottom up here */
4a4d8108 24263+ if (unlikely(err < 0)) {
1facf9fc 24264+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
24265+ if (err >= 0)
24266+ err = au_wbr_nonopq(dentry, err);
24267+ }
1facf9fc 24268+
24269+ out:
24270+ AuDbg("b%d\n", err);
24271+ return err;
24272+}
24273+
24274+/* ---------------------------------------------------------------------- */
24275+
24276+/* an exception for the policy other than tdp */
24277+static int au_wbr_create_exp(struct dentry *dentry)
24278+{
24279+ int err;
24280+ aufs_bindex_t bwh, bdiropq;
24281+ struct dentry *parent;
24282+
24283+ err = -1;
24284+ bwh = au_dbwh(dentry);
24285+ parent = dget_parent(dentry);
24286+ bdiropq = au_dbdiropq(parent);
24287+ if (bwh >= 0) {
24288+ if (bdiropq >= 0)
24289+ err = min(bdiropq, bwh);
24290+ else
24291+ err = bwh;
24292+ AuDbg("%d\n", err);
24293+ } else if (bdiropq >= 0) {
24294+ err = bdiropq;
24295+ AuDbg("%d\n", err);
24296+ }
24297+ dput(parent);
24298+
4a4d8108
AM
24299+ if (err >= 0)
24300+ err = au_wbr_nonopq(dentry, err);
24301+
1facf9fc 24302+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
24303+ err = -1;
24304+
24305+ AuDbg("%d\n", err);
24306+ return err;
24307+}
24308+
24309+/* ---------------------------------------------------------------------- */
24310+
24311+/* round robin */
24312+static int au_wbr_create_init_rr(struct super_block *sb)
24313+{
24314+ int err;
24315+
24316+ err = au_wbr_bu(sb, au_sbend(sb));
24317+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 24318+ /* smp_mb(); */
1facf9fc 24319+
24320+ AuDbg("b%d\n", err);
24321+ return err;
24322+}
24323+
24324+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
24325+{
24326+ int err, nbr;
24327+ unsigned int u;
24328+ aufs_bindex_t bindex, bend;
24329+ struct super_block *sb;
24330+ atomic_t *next;
24331+
24332+ err = au_wbr_create_exp(dentry);
24333+ if (err >= 0)
24334+ goto out;
24335+
24336+ sb = dentry->d_sb;
24337+ next = &au_sbi(sb)->si_wbr_rr_next;
24338+ bend = au_sbend(sb);
24339+ nbr = bend + 1;
24340+ for (bindex = 0; bindex <= bend; bindex++) {
24341+ if (!isdir) {
24342+ err = atomic_dec_return(next) + 1;
24343+ /* modulo for 0 is meaningless */
24344+ if (unlikely(!err))
24345+ err = atomic_dec_return(next) + 1;
24346+ } else
24347+ err = atomic_read(next);
24348+ AuDbg("%d\n", err);
24349+ u = err;
24350+ err = u % nbr;
24351+ AuDbg("%d\n", err);
24352+ if (!au_br_rdonly(au_sbr(sb, err)))
24353+ break;
24354+ err = -EROFS;
24355+ }
24356+
4a4d8108
AM
24357+ if (err >= 0)
24358+ err = au_wbr_nonopq(dentry, err);
24359+
1facf9fc 24360+ out:
24361+ AuDbg("%d\n", err);
24362+ return err;
24363+}
24364+
24365+/* ---------------------------------------------------------------------- */
24366+
24367+/* most free space */
24368+static void au_mfs(struct dentry *dentry)
24369+{
24370+ struct super_block *sb;
24371+ struct au_branch *br;
24372+ struct au_wbr_mfs *mfs;
24373+ aufs_bindex_t bindex, bend;
24374+ int err;
24375+ unsigned long long b, bavail;
24376+ /* reduce the stack usage */
24377+ struct kstatfs *st;
24378+
24379+ st = kmalloc(sizeof(*st), GFP_NOFS);
24380+ if (unlikely(!st)) {
24381+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
24382+ return;
24383+ }
24384+
24385+ bavail = 0;
24386+ sb = dentry->d_sb;
24387+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 24388+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 24389+ mfs->mfs_bindex = -EROFS;
24390+ mfs->mfsrr_bytes = 0;
24391+ bend = au_sbend(sb);
24392+ for (bindex = 0; bindex <= bend; bindex++) {
24393+ br = au_sbr(sb, bindex);
24394+ if (au_br_rdonly(br))
24395+ continue;
24396+
24397+ /* sb->s_root for NFS is unreliable */
24398+ err = vfs_statfs(br->br_mnt->mnt_root, st);
24399+ if (unlikely(err)) {
24400+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
24401+ continue;
24402+ }
24403+
24404+ /* when the available size is equal, select the lower one */
24405+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
24406+ || sizeof(b) < sizeof(st->f_bsize));
24407+ b = st->f_bavail * st->f_bsize;
24408+ br->br_wbr->wbr_bytes = b;
24409+ if (b >= bavail) {
24410+ bavail = b;
24411+ mfs->mfs_bindex = bindex;
24412+ mfs->mfs_jiffy = jiffies;
24413+ }
24414+ }
24415+
24416+ mfs->mfsrr_bytes = bavail;
24417+ AuDbg("b%d\n", mfs->mfs_bindex);
24418+ kfree(st);
24419+}
24420+
24421+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
24422+{
24423+ int err;
24424+ struct super_block *sb;
24425+ struct au_wbr_mfs *mfs;
24426+
24427+ err = au_wbr_create_exp(dentry);
24428+ if (err >= 0)
24429+ goto out;
24430+
24431+ sb = dentry->d_sb;
24432+ mfs = &au_sbi(sb)->si_wbr_mfs;
24433+ mutex_lock(&mfs->mfs_lock);
24434+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
24435+ || mfs->mfs_bindex < 0
24436+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
24437+ au_mfs(dentry);
24438+ mutex_unlock(&mfs->mfs_lock);
24439+ err = mfs->mfs_bindex;
24440+
4a4d8108
AM
24441+ if (err >= 0)
24442+ err = au_wbr_nonopq(dentry, err);
24443+
1facf9fc 24444+ out:
24445+ AuDbg("b%d\n", err);
24446+ return err;
24447+}
24448+
24449+static int au_wbr_create_init_mfs(struct super_block *sb)
24450+{
24451+ struct au_wbr_mfs *mfs;
24452+
24453+ mfs = &au_sbi(sb)->si_wbr_mfs;
24454+ mutex_init(&mfs->mfs_lock);
24455+ mfs->mfs_jiffy = 0;
24456+ mfs->mfs_bindex = -EROFS;
24457+
24458+ return 0;
24459+}
24460+
24461+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
24462+{
24463+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
24464+ return 0;
24465+}
24466+
24467+/* ---------------------------------------------------------------------- */
24468+
24469+/* most free space and then round robin */
24470+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
24471+{
24472+ int err;
24473+ struct au_wbr_mfs *mfs;
24474+
24475+ err = au_wbr_create_mfs(dentry, isdir);
24476+ if (err >= 0) {
24477+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 24478+ mutex_lock(&mfs->mfs_lock);
1facf9fc 24479+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
24480+ err = au_wbr_create_rr(dentry, isdir);
dece6358 24481+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 24482+ }
24483+
24484+ AuDbg("b%d\n", err);
24485+ return err;
24486+}
24487+
24488+static int au_wbr_create_init_mfsrr(struct super_block *sb)
24489+{
24490+ int err;
24491+
24492+ au_wbr_create_init_mfs(sb); /* ignore */
24493+ err = au_wbr_create_init_rr(sb);
24494+
24495+ return err;
24496+}
24497+
24498+/* ---------------------------------------------------------------------- */
24499+
24500+/* top down parent and most free space */
24501+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
24502+{
24503+ int err, e2;
24504+ unsigned long long b;
24505+ aufs_bindex_t bindex, bstart, bend;
24506+ struct super_block *sb;
24507+ struct dentry *parent, *h_parent;
24508+ struct au_branch *br;
24509+
24510+ err = au_wbr_create_tdp(dentry, isdir);
24511+ if (unlikely(err < 0))
24512+ goto out;
24513+ parent = dget_parent(dentry);
24514+ bstart = au_dbstart(parent);
24515+ bend = au_dbtaildir(parent);
24516+ if (bstart == bend)
24517+ goto out_parent; /* success */
24518+
24519+ e2 = au_wbr_create_mfs(dentry, isdir);
24520+ if (e2 < 0)
24521+ goto out_parent; /* success */
24522+
24523+ /* when the available size is equal, select upper one */
24524+ sb = dentry->d_sb;
24525+ br = au_sbr(sb, err);
24526+ b = br->br_wbr->wbr_bytes;
24527+ AuDbg("b%d, %llu\n", err, b);
24528+
24529+ for (bindex = bstart; bindex <= bend; bindex++) {
24530+ h_parent = au_h_dptr(parent, bindex);
24531+ if (!h_parent || !h_parent->d_inode)
24532+ continue;
24533+
24534+ br = au_sbr(sb, bindex);
24535+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
24536+ b = br->br_wbr->wbr_bytes;
24537+ err = bindex;
24538+ AuDbg("b%d, %llu\n", err, b);
24539+ }
24540+ }
24541+
4a4d8108
AM
24542+ if (err >= 0)
24543+ err = au_wbr_nonopq(dentry, err);
24544+
1facf9fc 24545+ out_parent:
24546+ dput(parent);
24547+ out:
24548+ AuDbg("b%d\n", err);
24549+ return err;
24550+}
24551+
24552+/* ---------------------------------------------------------------------- */
24553+
24554+/* policies for copyup */
24555+
24556+/* top down parent */
24557+static int au_wbr_copyup_tdp(struct dentry *dentry)
24558+{
24559+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
24560+}
24561+
24562+/* bottom up parent */
24563+static int au_wbr_copyup_bup(struct dentry *dentry)
24564+{
24565+ int err;
24566+ aufs_bindex_t bindex, bstart;
24567+ struct dentry *parent, *h_parent;
24568+ struct super_block *sb;
24569+
24570+ err = -EROFS;
24571+ sb = dentry->d_sb;
24572+ parent = dget_parent(dentry);
24573+ bstart = au_dbstart(parent);
24574+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
24575+ h_parent = au_h_dptr(parent, bindex);
24576+ if (!h_parent || !h_parent->d_inode)
24577+ continue;
24578+
24579+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
24580+ err = bindex;
24581+ break;
24582+ }
24583+ }
24584+ dput(parent);
24585+
24586+ /* bottom up here */
24587+ if (unlikely(err < 0))
24588+ err = au_wbr_bu(sb, bstart - 1);
24589+
24590+ AuDbg("b%d\n", err);
24591+ return err;
24592+}
24593+
24594+/* bottom up */
24595+static int au_wbr_copyup_bu(struct dentry *dentry)
24596+{
24597+ int err;
4a4d8108 24598+ aufs_bindex_t bstart;
1facf9fc 24599+
4a4d8108
AM
24600+ bstart = au_dbstart(dentry);
24601+ err = au_wbr_bu(dentry->d_sb, bstart);
24602+ AuDbg("b%d\n", err);
24603+ if (err > bstart)
24604+ err = au_wbr_nonopq(dentry, err);
1facf9fc 24605+
24606+ AuDbg("b%d\n", err);
24607+ return err;
24608+}
24609+
24610+/* ---------------------------------------------------------------------- */
24611+
24612+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
24613+ [AuWbrCopyup_TDP] = {
24614+ .copyup = au_wbr_copyup_tdp
24615+ },
24616+ [AuWbrCopyup_BUP] = {
24617+ .copyup = au_wbr_copyup_bup
24618+ },
24619+ [AuWbrCopyup_BU] = {
24620+ .copyup = au_wbr_copyup_bu
24621+ }
24622+};
24623+
24624+struct au_wbr_create_operations au_wbr_create_ops[] = {
24625+ [AuWbrCreate_TDP] = {
24626+ .create = au_wbr_create_tdp
24627+ },
24628+ [AuWbrCreate_RR] = {
24629+ .create = au_wbr_create_rr,
24630+ .init = au_wbr_create_init_rr
24631+ },
24632+ [AuWbrCreate_MFS] = {
24633+ .create = au_wbr_create_mfs,
24634+ .init = au_wbr_create_init_mfs,
24635+ .fin = au_wbr_create_fin_mfs
24636+ },
24637+ [AuWbrCreate_MFSV] = {
24638+ .create = au_wbr_create_mfs,
24639+ .init = au_wbr_create_init_mfs,
24640+ .fin = au_wbr_create_fin_mfs
24641+ },
24642+ [AuWbrCreate_MFSRR] = {
24643+ .create = au_wbr_create_mfsrr,
24644+ .init = au_wbr_create_init_mfsrr,
24645+ .fin = au_wbr_create_fin_mfs
24646+ },
24647+ [AuWbrCreate_MFSRRV] = {
24648+ .create = au_wbr_create_mfsrr,
24649+ .init = au_wbr_create_init_mfsrr,
24650+ .fin = au_wbr_create_fin_mfs
24651+ },
24652+ [AuWbrCreate_PMFS] = {
24653+ .create = au_wbr_create_pmfs,
24654+ .init = au_wbr_create_init_mfs,
24655+ .fin = au_wbr_create_fin_mfs
24656+ },
24657+ [AuWbrCreate_PMFSV] = {
24658+ .create = au_wbr_create_pmfs,
24659+ .init = au_wbr_create_init_mfs,
24660+ .fin = au_wbr_create_fin_mfs
24661+ }
24662+};
b752ccd1
AM
24663diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
24664--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
24665+++ linux/fs/aufs/whout.c 2010-08-21 21:00:02.986708041 +0200
1308ab2a 24666@@ -0,0 +1,1052 @@
1facf9fc 24667+/*
4a4d8108 24668+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 24669+ *
24670+ * This program, aufs is free software; you can redistribute it and/or modify
24671+ * it under the terms of the GNU General Public License as published by
24672+ * the Free Software Foundation; either version 2 of the License, or
24673+ * (at your option) any later version.
dece6358
AM
24674+ *
24675+ * This program is distributed in the hope that it will be useful,
24676+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24677+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24678+ * GNU General Public License for more details.
24679+ *
24680+ * You should have received a copy of the GNU General Public License
24681+ * along with this program; if not, write to the Free Software
24682+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24683+ */
24684+
24685+/*
24686+ * whiteout for logical deletion and opaque directory
24687+ */
24688+
24689+#include <linux/fs.h>
24690+#include "aufs.h"
24691+
24692+#define WH_MASK S_IRUGO
24693+
24694+/*
24695+ * If a directory contains this file, then it is opaque. We start with the
24696+ * .wh. flag so that it is blocked by lookup.
24697+ */
24698+static struct qstr diropq_name = {
24699+ .name = AUFS_WH_DIROPQ,
24700+ .len = sizeof(AUFS_WH_DIROPQ) - 1
24701+};
24702+
24703+/*
24704+ * generate whiteout name, which is NOT terminated by NULL.
24705+ * @name: original d_name.name
24706+ * @len: original d_name.len
24707+ * @wh: whiteout qstr
24708+ * returns zero when succeeds, otherwise error.
24709+ * succeeded value as wh->name should be freed by kfree().
24710+ */
24711+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
24712+{
24713+ char *p;
24714+
24715+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
24716+ return -ENAMETOOLONG;
24717+
24718+ wh->len = name->len + AUFS_WH_PFX_LEN;
24719+ p = kmalloc(wh->len, GFP_NOFS);
24720+ wh->name = p;
24721+ if (p) {
24722+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
24723+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
24724+ /* smp_mb(); */
24725+ return 0;
24726+ }
24727+ return -ENOMEM;
24728+}
24729+
24730+/* ---------------------------------------------------------------------- */
24731+
24732+/*
24733+ * test if the @wh_name exists under @h_parent.
24734+ * @try_sio specifies the necessary of super-io.
24735+ */
24736+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
24737+ struct au_branch *br, int try_sio)
24738+{
24739+ int err;
24740+ struct dentry *wh_dentry;
1facf9fc 24741+
1facf9fc 24742+ if (!try_sio)
24743+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
24744+ else
24745+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
24746+ err = PTR_ERR(wh_dentry);
24747+ if (IS_ERR(wh_dentry))
24748+ goto out;
24749+
24750+ err = 0;
24751+ if (!wh_dentry->d_inode)
24752+ goto out_wh; /* success */
24753+
24754+ err = 1;
24755+ if (S_ISREG(wh_dentry->d_inode->i_mode))
24756+ goto out_wh; /* success */
24757+
24758+ err = -EIO;
24759+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
24760+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
24761+
24762+ out_wh:
24763+ dput(wh_dentry);
24764+ out:
24765+ return err;
24766+}
24767+
24768+/*
24769+ * test if the @h_dentry sets opaque or not.
24770+ */
24771+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
24772+{
24773+ int err;
24774+ struct inode *h_dir;
24775+
24776+ h_dir = h_dentry->d_inode;
24777+ err = au_wh_test(h_dentry, &diropq_name, br,
24778+ au_test_h_perm_sio(h_dir, MAY_EXEC));
24779+ return err;
24780+}
24781+
24782+/*
24783+ * returns a negative dentry whose name is unique and temporary.
24784+ */
24785+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
24786+ struct qstr *prefix)
24787+{
1facf9fc 24788+ struct dentry *dentry;
24789+ int i;
4a4d8108
AM
24790+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN_MIN + 1],
24791+ *name, *p;
1facf9fc 24792+ static unsigned short cnt;
24793+ struct qstr qs;
24794+
4a4d8108
AM
24795+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
24796+
1facf9fc 24797+ name = defname;
24798+ qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
24799+ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
24800+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 24801+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 24802+ goto out;
24803+ dentry = ERR_PTR(-ENOMEM);
24804+ name = kmalloc(qs.len + 1, GFP_NOFS);
24805+ if (unlikely(!name))
24806+ goto out;
24807+ }
24808+
24809+ /* doubly whiteout-ed */
24810+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
24811+ p = name + AUFS_WH_PFX_LEN * 2;
24812+ memcpy(p, prefix->name, prefix->len);
24813+ p += prefix->len;
24814+ *p++ = '.';
4a4d8108 24815+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 24816+
24817+ qs.name = name;
24818+ for (i = 0; i < 3; i++) {
b752ccd1 24819+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 24820+ dentry = au_sio_lkup_one(&qs, h_parent, br);
24821+ if (IS_ERR(dentry) || !dentry->d_inode)
24822+ goto out_name;
24823+ dput(dentry);
24824+ }
4a4d8108 24825+ /* pr_warning("could not get random name\n"); */
1facf9fc 24826+ dentry = ERR_PTR(-EEXIST);
24827+ AuDbg("%.*s\n", AuLNPair(&qs));
24828+ BUG();
24829+
24830+ out_name:
24831+ if (name != defname)
24832+ kfree(name);
24833+ out:
4a4d8108 24834+ AuTraceErrPtr(dentry);
1facf9fc 24835+ return dentry;
1facf9fc 24836+}
24837+
24838+/*
24839+ * rename the @h_dentry on @br to the whiteouted temporary name.
24840+ */
24841+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
24842+{
24843+ int err;
24844+ struct path h_path = {
24845+ .mnt = br->br_mnt
24846+ };
24847+ struct inode *h_dir;
24848+ struct dentry *h_parent;
24849+
24850+ h_parent = h_dentry->d_parent; /* dir inode is locked */
24851+ h_dir = h_parent->d_inode;
24852+ IMustLock(h_dir);
24853+
24854+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
24855+ err = PTR_ERR(h_path.dentry);
24856+ if (IS_ERR(h_path.dentry))
24857+ goto out;
24858+
24859+ /* under the same dir, no need to lock_rename() */
24860+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
24861+ AuTraceErr(err);
24862+ dput(h_path.dentry);
24863+
24864+ out:
4a4d8108 24865+ AuTraceErr(err);
1facf9fc 24866+ return err;
24867+}
24868+
24869+/* ---------------------------------------------------------------------- */
24870+/*
24871+ * functions for removing a whiteout
24872+ */
24873+
24874+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
24875+{
24876+ int force;
24877+
24878+ /*
24879+ * forces superio when the dir has a sticky bit.
24880+ * this may be a violation of unix fs semantics.
24881+ */
24882+ force = (h_dir->i_mode & S_ISVTX)
24883+ && h_path->dentry->d_inode->i_uid != current_fsuid();
24884+ return vfsub_unlink(h_dir, h_path, force);
24885+}
24886+
24887+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
24888+ struct dentry *dentry)
24889+{
24890+ int err;
24891+
24892+ err = do_unlink_wh(h_dir, h_path);
24893+ if (!err && dentry)
24894+ au_set_dbwh(dentry, -1);
24895+
24896+ return err;
24897+}
24898+
24899+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
24900+ struct au_branch *br)
24901+{
24902+ int err;
24903+ struct path h_path = {
24904+ .mnt = br->br_mnt
24905+ };
24906+
24907+ err = 0;
24908+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
24909+ if (IS_ERR(h_path.dentry))
24910+ err = PTR_ERR(h_path.dentry);
24911+ else {
24912+ if (h_path.dentry->d_inode
24913+ && S_ISREG(h_path.dentry->d_inode->i_mode))
24914+ err = do_unlink_wh(h_parent->d_inode, &h_path);
24915+ dput(h_path.dentry);
24916+ }
24917+
24918+ return err;
24919+}
24920+
24921+/* ---------------------------------------------------------------------- */
24922+/*
24923+ * initialize/clean whiteout for a branch
24924+ */
24925+
24926+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
24927+ const int isdir)
24928+{
24929+ int err;
24930+
24931+ if (!whpath->dentry->d_inode)
24932+ return;
24933+
24934+ err = mnt_want_write(whpath->mnt);
24935+ if (!err) {
24936+ if (isdir)
24937+ err = vfsub_rmdir(h_dir, whpath);
24938+ else
24939+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
24940+ mnt_drop_write(whpath->mnt);
24941+ }
24942+ if (unlikely(err))
4a4d8108
AM
24943+ pr_warning("failed removing %.*s (%d), ignored.\n",
24944+ AuDLNPair(whpath->dentry), err);
1facf9fc 24945+}
24946+
24947+static int test_linkable(struct dentry *h_root)
24948+{
24949+ struct inode *h_dir = h_root->d_inode;
24950+
24951+ if (h_dir->i_op->link)
24952+ return 0;
24953+
4a4d8108
AM
24954+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
24955+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 24956+ return -ENOSYS;
24957+}
24958+
24959+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
24960+static int au_whdir(struct inode *h_dir, struct path *path)
24961+{
24962+ int err;
24963+
24964+ err = -EEXIST;
24965+ if (!path->dentry->d_inode) {
24966+ int mode = S_IRWXU;
24967+
24968+ if (au_test_nfs(path->dentry->d_sb))
24969+ mode |= S_IXUGO;
24970+ err = mnt_want_write(path->mnt);
24971+ if (!err) {
24972+ err = vfsub_mkdir(h_dir, path, mode);
24973+ mnt_drop_write(path->mnt);
24974+ }
24975+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
24976+ err = 0;
24977+ else
4a4d8108 24978+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 24979+
24980+ return err;
24981+}
24982+
24983+struct au_wh_base {
24984+ const struct qstr *name;
24985+ struct dentry *dentry;
24986+};
24987+
24988+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
24989+ struct path *h_path)
24990+{
24991+ h_path->dentry = base[AuBrWh_BASE].dentry;
24992+ au_wh_clean(h_dir, h_path, /*isdir*/0);
24993+ h_path->dentry = base[AuBrWh_PLINK].dentry;
24994+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24995+ h_path->dentry = base[AuBrWh_ORPH].dentry;
24996+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24997+}
24998+
24999+/*
25000+ * returns tri-state,
25001+ * minus: error, caller should print the mesage
25002+ * zero: succuess
25003+ * plus: error, caller should NOT print the mesage
25004+ */
25005+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
25006+ int do_plink, struct au_wh_base base[],
25007+ struct path *h_path)
25008+{
25009+ int err;
25010+ struct inode *h_dir;
25011+
25012+ h_dir = h_root->d_inode;
25013+ h_path->dentry = base[AuBrWh_BASE].dentry;
25014+ au_wh_clean(h_dir, h_path, /*isdir*/0);
25015+ h_path->dentry = base[AuBrWh_PLINK].dentry;
25016+ if (do_plink) {
25017+ err = test_linkable(h_root);
25018+ if (unlikely(err)) {
25019+ err = 1;
25020+ goto out;
25021+ }
25022+
25023+ err = au_whdir(h_dir, h_path);
25024+ if (unlikely(err))
25025+ goto out;
25026+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
25027+ } else
25028+ au_wh_clean(h_dir, h_path, /*isdir*/1);
25029+ h_path->dentry = base[AuBrWh_ORPH].dentry;
25030+ err = au_whdir(h_dir, h_path);
25031+ if (unlikely(err))
25032+ goto out;
25033+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
25034+
25035+ out:
25036+ return err;
25037+}
25038+
25039+/*
25040+ * for the moment, aufs supports the branch filesystem which does not support
25041+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
25042+ * copyup failed. finally, such filesystem will not be used as the writable
25043+ * branch.
25044+ *
25045+ * returns tri-state, see above.
25046+ */
25047+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
25048+ int do_plink, struct au_wh_base base[],
25049+ struct path *h_path)
25050+{
25051+ int err;
25052+ struct inode *h_dir;
25053+
1308ab2a 25054+ WbrWhMustWriteLock(wbr);
25055+
1facf9fc 25056+ err = test_linkable(h_root);
25057+ if (unlikely(err)) {
25058+ err = 1;
25059+ goto out;
25060+ }
25061+
25062+ /*
25063+ * todo: should this create be done in /sbin/mount.aufs helper?
25064+ */
25065+ err = -EEXIST;
25066+ h_dir = h_root->d_inode;
25067+ if (!base[AuBrWh_BASE].dentry->d_inode) {
25068+ err = mnt_want_write(h_path->mnt);
25069+ if (!err) {
25070+ h_path->dentry = base[AuBrWh_BASE].dentry;
25071+ err = vfsub_create(h_dir, h_path, WH_MASK);
25072+ mnt_drop_write(h_path->mnt);
25073+ }
25074+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
25075+ err = 0;
25076+ else
4a4d8108
AM
25077+ pr_err("unknown %.*s/%.*s exists\n",
25078+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 25079+ if (unlikely(err))
25080+ goto out;
25081+
25082+ h_path->dentry = base[AuBrWh_PLINK].dentry;
25083+ if (do_plink) {
25084+ err = au_whdir(h_dir, h_path);
25085+ if (unlikely(err))
25086+ goto out;
25087+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
25088+ } else
25089+ au_wh_clean(h_dir, h_path, /*isdir*/1);
25090+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
25091+
25092+ h_path->dentry = base[AuBrWh_ORPH].dentry;
25093+ err = au_whdir(h_dir, h_path);
25094+ if (unlikely(err))
25095+ goto out;
25096+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
25097+
25098+ out:
25099+ return err;
25100+}
25101+
25102+/*
25103+ * initialize the whiteout base file/dir for @br.
25104+ */
25105+int au_wh_init(struct dentry *h_root, struct au_branch *br,
25106+ struct super_block *sb)
25107+{
25108+ int err, i;
25109+ const unsigned char do_plink
25110+ = !!au_opt_test(au_mntflags(sb), PLINK);
25111+ struct path path = {
25112+ .mnt = br->br_mnt
25113+ };
25114+ struct inode *h_dir;
25115+ struct au_wbr *wbr = br->br_wbr;
25116+ static const struct qstr base_name[] = {
25117+ [AuBrWh_BASE] = {
25118+ .name = AUFS_BASE_NAME,
25119+ .len = sizeof(AUFS_BASE_NAME) - 1
25120+ },
25121+ [AuBrWh_PLINK] = {
25122+ .name = AUFS_PLINKDIR_NAME,
25123+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
25124+ },
25125+ [AuBrWh_ORPH] = {
25126+ .name = AUFS_ORPHDIR_NAME,
25127+ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
25128+ }
25129+ };
25130+ struct au_wh_base base[] = {
25131+ [AuBrWh_BASE] = {
25132+ .name = base_name + AuBrWh_BASE,
25133+ .dentry = NULL
25134+ },
25135+ [AuBrWh_PLINK] = {
25136+ .name = base_name + AuBrWh_PLINK,
25137+ .dentry = NULL
25138+ },
25139+ [AuBrWh_ORPH] = {
25140+ .name = base_name + AuBrWh_ORPH,
25141+ .dentry = NULL
25142+ }
25143+ };
25144+
1308ab2a 25145+ if (wbr)
25146+ WbrWhMustWriteLock(wbr);
1facf9fc 25147+
1facf9fc 25148+ for (i = 0; i < AuBrWh_Last; i++) {
25149+ /* doubly whiteouted */
25150+ struct dentry *d;
25151+
25152+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
25153+ err = PTR_ERR(d);
25154+ if (IS_ERR(d))
25155+ goto out;
25156+
25157+ base[i].dentry = d;
25158+ AuDebugOn(wbr
25159+ && wbr->wbr_wh[i]
25160+ && wbr->wbr_wh[i] != base[i].dentry);
25161+ }
25162+
25163+ if (wbr)
25164+ for (i = 0; i < AuBrWh_Last; i++) {
25165+ dput(wbr->wbr_wh[i]);
25166+ wbr->wbr_wh[i] = NULL;
25167+ }
25168+
25169+ err = 0;
1facf9fc 25170+ switch (br->br_perm) {
25171+ case AuBrPerm_RO:
25172+ case AuBrPerm_ROWH:
25173+ case AuBrPerm_RR:
25174+ case AuBrPerm_RRWH:
4a4d8108 25175+ h_dir = h_root->d_inode;
1facf9fc 25176+ au_wh_init_ro(h_dir, base, &path);
25177+ break;
25178+
25179+ case AuBrPerm_RWNoLinkWH:
25180+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
25181+ if (err > 0)
25182+ goto out;
25183+ else if (err)
25184+ goto out_err;
25185+ break;
25186+
25187+ case AuBrPerm_RW:
25188+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
25189+ if (err > 0)
25190+ goto out;
25191+ else if (err)
25192+ goto out_err;
25193+ break;
25194+
25195+ default:
25196+ BUG();
25197+ }
25198+ goto out; /* success */
25199+
25200+ out_err:
4a4d8108
AM
25201+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
25202+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 25203+ out:
25204+ for (i = 0; i < AuBrWh_Last; i++)
25205+ dput(base[i].dentry);
25206+ return err;
25207+}
25208+
25209+/* ---------------------------------------------------------------------- */
25210+/*
25211+ * whiteouts are all hard-linked usually.
25212+ * when its link count reaches a ceiling, we create a new whiteout base
25213+ * asynchronously.
25214+ */
25215+
25216+struct reinit_br_wh {
25217+ struct super_block *sb;
25218+ struct au_branch *br;
25219+};
25220+
25221+static void reinit_br_wh(void *arg)
25222+{
25223+ int err;
25224+ aufs_bindex_t bindex;
25225+ struct path h_path;
25226+ struct reinit_br_wh *a = arg;
25227+ struct au_wbr *wbr;
25228+ struct inode *dir;
25229+ struct dentry *h_root;
25230+ struct au_hinode *hdir;
25231+
25232+ err = 0;
25233+ wbr = a->br->br_wbr;
25234+ /* big aufs lock */
25235+ si_noflush_write_lock(a->sb);
25236+ if (!au_br_writable(a->br->br_perm))
25237+ goto out;
25238+ bindex = au_br_index(a->sb, a->br->br_id);
25239+ if (unlikely(bindex < 0))
25240+ goto out;
25241+
1308ab2a 25242+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 25243+ dir = a->sb->s_root->d_inode;
1facf9fc 25244+ hdir = au_hi(dir, bindex);
25245+ h_root = au_h_dptr(a->sb->s_root, bindex);
25246+
4a4d8108 25247+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 25248+ wbr_wh_write_lock(wbr);
25249+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
25250+ h_root, a->br);
25251+ if (!err) {
25252+ err = mnt_want_write(a->br->br_mnt);
25253+ if (!err) {
25254+ h_path.dentry = wbr->wbr_whbase;
25255+ h_path.mnt = a->br->br_mnt;
25256+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
25257+ mnt_drop_write(a->br->br_mnt);
25258+ }
25259+ } else {
4a4d8108
AM
25260+ pr_warning("%.*s is moved, ignored\n",
25261+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 25262+ err = 0;
25263+ }
25264+ dput(wbr->wbr_whbase);
25265+ wbr->wbr_whbase = NULL;
25266+ if (!err)
25267+ err = au_wh_init(h_root, a->br, a->sb);
25268+ wbr_wh_write_unlock(wbr);
4a4d8108 25269+ au_hn_imtx_unlock(hdir);
1308ab2a 25270+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 25271+
25272+ out:
25273+ if (wbr)
25274+ atomic_dec(&wbr->wbr_wh_running);
25275+ atomic_dec(&a->br->br_count);
25276+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
25277+ si_write_unlock(a->sb);
25278+ kfree(arg);
25279+ if (unlikely(err))
25280+ AuIOErr("err %d\n", err);
25281+}
25282+
25283+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
25284+{
25285+ int do_dec, wkq_err;
25286+ struct reinit_br_wh *arg;
25287+
25288+ do_dec = 1;
25289+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
25290+ goto out;
25291+
25292+ /* ignore ENOMEM */
25293+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
25294+ if (arg) {
25295+ /*
25296+ * dec(wh_running), kfree(arg) and dec(br_count)
25297+ * in reinit function
25298+ */
25299+ arg->sb = sb;
25300+ arg->br = br;
25301+ atomic_inc(&br->br_count);
25302+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
25303+ if (unlikely(wkq_err)) {
25304+ atomic_dec(&br->br_wbr->wbr_wh_running);
25305+ atomic_dec(&br->br_count);
25306+ kfree(arg);
25307+ }
25308+ do_dec = 0;
25309+ }
25310+
25311+ out:
25312+ if (do_dec)
25313+ atomic_dec(&br->br_wbr->wbr_wh_running);
25314+}
25315+
25316+/* ---------------------------------------------------------------------- */
25317+
25318+/*
25319+ * create the whiteout @wh.
25320+ */
25321+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
25322+ struct dentry *wh)
25323+{
25324+ int err;
25325+ struct path h_path = {
25326+ .dentry = wh
25327+ };
25328+ struct au_branch *br;
25329+ struct au_wbr *wbr;
25330+ struct dentry *h_parent;
25331+ struct inode *h_dir;
25332+
25333+ h_parent = wh->d_parent; /* dir inode is locked */
25334+ h_dir = h_parent->d_inode;
25335+ IMustLock(h_dir);
25336+
25337+ br = au_sbr(sb, bindex);
25338+ h_path.mnt = br->br_mnt;
25339+ wbr = br->br_wbr;
25340+ wbr_wh_read_lock(wbr);
25341+ if (wbr->wbr_whbase) {
25342+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
25343+ if (!err || err != -EMLINK)
25344+ goto out;
25345+
25346+ /* link count full. re-initialize br_whbase. */
25347+ kick_reinit_br_wh(sb, br);
25348+ }
25349+
25350+ /* return this error in this context */
25351+ err = vfsub_create(h_dir, &h_path, WH_MASK);
25352+
25353+ out:
25354+ wbr_wh_read_unlock(wbr);
25355+ return err;
25356+}
25357+
25358+/* ---------------------------------------------------------------------- */
25359+
25360+/*
25361+ * create or remove the diropq.
25362+ */
25363+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
25364+ unsigned int flags)
25365+{
25366+ struct dentry *opq_dentry, *h_dentry;
25367+ struct super_block *sb;
25368+ struct au_branch *br;
25369+ int err;
25370+
25371+ sb = dentry->d_sb;
25372+ br = au_sbr(sb, bindex);
25373+ h_dentry = au_h_dptr(dentry, bindex);
25374+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
25375+ if (IS_ERR(opq_dentry))
25376+ goto out;
25377+
25378+ if (au_ftest_diropq(flags, CREATE)) {
25379+ err = link_or_create_wh(sb, bindex, opq_dentry);
25380+ if (!err) {
25381+ au_set_dbdiropq(dentry, bindex);
25382+ goto out; /* success */
25383+ }
25384+ } else {
25385+ struct path tmp = {
25386+ .dentry = opq_dentry,
25387+ .mnt = br->br_mnt
25388+ };
25389+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
25390+ if (!err)
25391+ au_set_dbdiropq(dentry, -1);
25392+ }
25393+ dput(opq_dentry);
25394+ opq_dentry = ERR_PTR(err);
25395+
25396+ out:
25397+ return opq_dentry;
25398+}
25399+
25400+struct do_diropq_args {
25401+ struct dentry **errp;
25402+ struct dentry *dentry;
25403+ aufs_bindex_t bindex;
25404+ unsigned int flags;
25405+};
25406+
25407+static void call_do_diropq(void *args)
25408+{
25409+ struct do_diropq_args *a = args;
25410+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
25411+}
25412+
25413+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
25414+ unsigned int flags)
25415+{
25416+ struct dentry *diropq, *h_dentry;
25417+
25418+ h_dentry = au_h_dptr(dentry, bindex);
25419+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
25420+ diropq = do_diropq(dentry, bindex, flags);
25421+ else {
25422+ int wkq_err;
25423+ struct do_diropq_args args = {
25424+ .errp = &diropq,
25425+ .dentry = dentry,
25426+ .bindex = bindex,
25427+ .flags = flags
25428+ };
25429+
25430+ wkq_err = au_wkq_wait(call_do_diropq, &args);
25431+ if (unlikely(wkq_err))
25432+ diropq = ERR_PTR(wkq_err);
25433+ }
25434+
25435+ return diropq;
25436+}
25437+
25438+/* ---------------------------------------------------------------------- */
25439+
25440+/*
25441+ * lookup whiteout dentry.
25442+ * @h_parent: lower parent dentry which must exist and be locked
25443+ * @base_name: name of dentry which will be whiteouted
25444+ * returns dentry for whiteout.
25445+ */
25446+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
25447+ struct au_branch *br)
25448+{
25449+ int err;
25450+ struct qstr wh_name;
25451+ struct dentry *wh_dentry;
25452+
25453+ err = au_wh_name_alloc(&wh_name, base_name);
25454+ wh_dentry = ERR_PTR(err);
25455+ if (!err) {
25456+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
25457+ kfree(wh_name.name);
25458+ }
25459+ return wh_dentry;
25460+}
25461+
25462+/*
25463+ * link/create a whiteout for @dentry on @bindex.
25464+ */
25465+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
25466+ struct dentry *h_parent)
25467+{
25468+ struct dentry *wh_dentry;
25469+ struct super_block *sb;
25470+ int err;
25471+
25472+ sb = dentry->d_sb;
25473+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
25474+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
25475+ err = link_or_create_wh(sb, bindex, wh_dentry);
25476+ if (!err)
25477+ au_set_dbwh(dentry, bindex);
25478+ else {
25479+ dput(wh_dentry);
25480+ wh_dentry = ERR_PTR(err);
25481+ }
25482+ }
25483+
25484+ return wh_dentry;
25485+}
25486+
25487+/* ---------------------------------------------------------------------- */
25488+
25489+/* Delete all whiteouts in this directory on branch bindex. */
25490+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
25491+ aufs_bindex_t bindex, struct au_branch *br)
25492+{
25493+ int err;
25494+ unsigned long ul, n;
25495+ struct qstr wh_name;
25496+ char *p;
25497+ struct hlist_head *head;
25498+ struct au_vdir_wh *tpos;
25499+ struct hlist_node *pos;
25500+ struct au_vdir_destr *str;
25501+
25502+ err = -ENOMEM;
4a4d8108 25503+ p = __getname_gfp(GFP_NOFS);
1facf9fc 25504+ wh_name.name = p;
25505+ if (unlikely(!wh_name.name))
25506+ goto out;
25507+
25508+ err = 0;
25509+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25510+ p += AUFS_WH_PFX_LEN;
25511+ n = whlist->nh_num;
25512+ head = whlist->nh_head;
25513+ for (ul = 0; !err && ul < n; ul++, head++) {
25514+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
25515+ if (tpos->wh_bindex != bindex)
25516+ continue;
25517+
25518+ str = &tpos->wh_str;
25519+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
25520+ memcpy(p, str->name, str->len);
25521+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
25522+ err = unlink_wh_name(h_dentry, &wh_name, br);
25523+ if (!err)
25524+ continue;
25525+ break;
25526+ }
25527+ AuIOErr("whiteout name too long %.*s\n",
25528+ str->len, str->name);
25529+ err = -EIO;
25530+ break;
25531+ }
25532+ }
25533+ __putname(wh_name.name);
25534+
25535+ out:
25536+ return err;
25537+}
25538+
25539+struct del_wh_children_args {
25540+ int *errp;
25541+ struct dentry *h_dentry;
1308ab2a 25542+ struct au_nhash *whlist;
1facf9fc 25543+ aufs_bindex_t bindex;
25544+ struct au_branch *br;
25545+};
25546+
25547+static void call_del_wh_children(void *args)
25548+{
25549+ struct del_wh_children_args *a = args;
1308ab2a 25550+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 25551+}
25552+
25553+/* ---------------------------------------------------------------------- */
25554+
25555+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
25556+{
25557+ struct au_whtmp_rmdir *whtmp;
dece6358 25558+ int err;
1308ab2a 25559+ unsigned int rdhash;
dece6358
AM
25560+
25561+ SiMustAnyLock(sb);
1facf9fc 25562+
25563+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
25564+ if (unlikely(!whtmp)) {
25565+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 25566+ goto out;
dece6358 25567+ }
1facf9fc 25568+
25569+ whtmp->dir = NULL;
25570+ whtmp->wh_dentry = NULL;
1308ab2a 25571+ /* no estimation for dir size */
25572+ rdhash = au_sbi(sb)->si_rdhash;
25573+ if (!rdhash)
25574+ rdhash = AUFS_RDHASH_DEF;
25575+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
25576+ if (unlikely(err)) {
25577+ kfree(whtmp);
25578+ whtmp = ERR_PTR(err);
25579+ }
dece6358 25580+
1facf9fc 25581+ out:
dece6358 25582+ return whtmp;
1facf9fc 25583+}
25584+
25585+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
25586+{
25587+ dput(whtmp->wh_dentry);
25588+ iput(whtmp->dir);
dece6358 25589+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 25590+ kfree(whtmp);
25591+}
25592+
25593+/*
25594+ * rmdir the whiteouted temporary named dir @h_dentry.
25595+ * @whlist: whiteouted children.
25596+ */
25597+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
25598+ struct dentry *wh_dentry, struct au_nhash *whlist)
25599+{
25600+ int err;
25601+ struct path h_tmp;
25602+ struct inode *wh_inode, *h_dir;
25603+ struct au_branch *br;
25604+
25605+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
25606+ IMustLock(h_dir);
25607+
25608+ br = au_sbr(dir->i_sb, bindex);
25609+ wh_inode = wh_dentry->d_inode;
25610+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
25611+
25612+ /*
25613+ * someone else might change some whiteouts while we were sleeping.
25614+ * it means this whlist may have an obsoleted entry.
25615+ */
25616+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
25617+ err = del_wh_children(wh_dentry, whlist, bindex, br);
25618+ else {
25619+ int wkq_err;
25620+ struct del_wh_children_args args = {
25621+ .errp = &err,
25622+ .h_dentry = wh_dentry,
1308ab2a 25623+ .whlist = whlist,
1facf9fc 25624+ .bindex = bindex,
25625+ .br = br
25626+ };
25627+
25628+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
25629+ if (unlikely(wkq_err))
25630+ err = wkq_err;
25631+ }
25632+ mutex_unlock(&wh_inode->i_mutex);
25633+
25634+ if (!err) {
25635+ h_tmp.dentry = wh_dentry;
25636+ h_tmp.mnt = br->br_mnt;
25637+ err = vfsub_rmdir(h_dir, &h_tmp);
25638+ /* d_drop(h_dentry); */
25639+ }
25640+
25641+ if (!err) {
25642+ if (au_ibstart(dir) == bindex) {
25643+ au_cpup_attr_timesizes(dir);
25644+ drop_nlink(dir);
25645+ }
25646+ return 0; /* success */
25647+ }
25648+
4a4d8108
AM
25649+ pr_warning("failed removing %.*s(%d), ignored\n",
25650+ AuDLNPair(wh_dentry), err);
1facf9fc 25651+ return err;
25652+}
25653+
25654+static void call_rmdir_whtmp(void *args)
25655+{
25656+ int err;
25657+ struct au_whtmp_rmdir *a = args;
25658+ struct super_block *sb;
25659+ struct dentry *h_parent;
25660+ struct inode *h_dir;
25661+ struct au_branch *br;
25662+ struct au_hinode *hdir;
25663+
25664+ /* rmdir by nfsd may cause deadlock with this i_mutex */
25665+ /* mutex_lock(&a->dir->i_mutex); */
25666+ sb = a->dir->i_sb;
25667+ si_noflush_read_lock(sb);
25668+ err = au_test_ro(sb, a->bindex, NULL);
25669+ if (unlikely(err))
25670+ goto out;
25671+
25672+ err = -EIO;
25673+ br = au_sbr(sb, a->bindex);
25674+ ii_write_lock_parent(a->dir);
25675+ h_parent = dget_parent(a->wh_dentry);
25676+ h_dir = h_parent->d_inode;
25677+ hdir = au_hi(a->dir, a->bindex);
4a4d8108 25678+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 25679+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, br);
25680+ if (!err) {
25681+ err = mnt_want_write(br->br_mnt);
25682+ if (!err) {
25683+ err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
dece6358 25684+ &a->whlist);
1facf9fc 25685+ mnt_drop_write(br->br_mnt);
25686+ }
25687+ }
4a4d8108 25688+ au_hn_imtx_unlock(hdir);
1facf9fc 25689+ dput(h_parent);
25690+ ii_write_unlock(a->dir);
25691+
25692+ out:
25693+ /* mutex_unlock(&a->dir->i_mutex); */
25694+ au_nwt_done(&au_sbi(sb)->si_nowait);
25695+ si_read_unlock(sb);
25696+ au_whtmp_rmdir_free(a);
25697+ if (unlikely(err))
25698+ AuIOErr("err %d\n", err);
25699+}
25700+
25701+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
25702+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
25703+{
25704+ int wkq_err;
25705+
25706+ IMustLock(dir);
25707+
25708+ /* all post-process will be done in do_rmdir_whtmp(). */
25709+ args->dir = au_igrab(dir);
25710+ args->bindex = bindex;
25711+ args->wh_dentry = dget(wh_dentry);
25712+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
25713+ if (unlikely(wkq_err)) {
4a4d8108
AM
25714+ pr_warning("rmdir error %.*s (%d), ignored\n",
25715+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 25716+ au_whtmp_rmdir_free(args);
25717+ }
25718+}
b752ccd1
AM
25719diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
25720--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
25721+++ linux/fs/aufs/whout.h 2010-08-21 21:00:02.986708041 +0200
dece6358 25722@@ -0,0 +1,87 @@
1facf9fc 25723+/*
4a4d8108 25724+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25725+ *
25726+ * This program, aufs is free software; you can redistribute it and/or modify
25727+ * it under the terms of the GNU General Public License as published by
25728+ * the Free Software Foundation; either version 2 of the License, or
25729+ * (at your option) any later version.
dece6358
AM
25730+ *
25731+ * This program is distributed in the hope that it will be useful,
25732+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25733+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25734+ * GNU General Public License for more details.
25735+ *
25736+ * You should have received a copy of the GNU General Public License
25737+ * along with this program; if not, write to the Free Software
25738+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25739+ */
25740+
25741+/*
25742+ * whiteout for logical deletion and opaque directory
25743+ */
25744+
25745+#ifndef __AUFS_WHOUT_H__
25746+#define __AUFS_WHOUT_H__
25747+
25748+#ifdef __KERNEL__
25749+
1facf9fc 25750+#include <linux/aufs_type.h>
25751+#include "dir.h"
25752+
25753+/* whout.c */
25754+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
25755+struct au_branch;
25756+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
25757+ struct au_branch *br, int try_sio);
25758+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
25759+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
25760+ struct qstr *prefix);
25761+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
25762+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
25763+ struct dentry *dentry);
25764+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
25765+ struct super_block *sb);
25766+
25767+/* diropq flags */
25768+#define AuDiropq_CREATE 1
25769+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
25770+#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
25771+#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
25772+
25773+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
25774+ unsigned int flags);
25775+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
25776+ struct au_branch *br);
25777+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
25778+ struct dentry *h_parent);
25779+
25780+/* real rmdir for the whiteout-ed dir */
25781+struct au_whtmp_rmdir {
25782+ struct inode *dir;
25783+ aufs_bindex_t bindex;
25784+ struct dentry *wh_dentry;
dece6358 25785+ struct au_nhash whlist;
1facf9fc 25786+};
25787+
25788+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
25789+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
25790+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
25791+ struct dentry *wh_dentry, struct au_nhash *whlist);
25792+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
25793+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
25794+
25795+/* ---------------------------------------------------------------------- */
25796+
25797+static inline struct dentry *au_diropq_create(struct dentry *dentry,
25798+ aufs_bindex_t bindex)
25799+{
25800+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
25801+}
25802+
25803+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
25804+{
25805+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
25806+}
25807+
25808+#endif /* __KERNEL__ */
25809+#endif /* __AUFS_WHOUT_H__ */
b752ccd1
AM
25810diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
25811--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
25812+++ linux/fs/aufs/wkq.c 2010-08-21 21:00:02.986708041 +0200
25813@@ -0,0 +1,223 @@
1facf9fc 25814+/*
4a4d8108 25815+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25816+ *
25817+ * This program, aufs is free software; you can redistribute it and/or modify
25818+ * it under the terms of the GNU General Public License as published by
25819+ * the Free Software Foundation; either version 2 of the License, or
25820+ * (at your option) any later version.
dece6358
AM
25821+ *
25822+ * This program is distributed in the hope that it will be useful,
25823+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25824+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25825+ * GNU General Public License for more details.
25826+ *
25827+ * You should have received a copy of the GNU General Public License
25828+ * along with this program; if not, write to the Free Software
25829+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25830+ */
25831+
25832+/*
25833+ * workqueue for asynchronous/super-io operations
25834+ * todo: try new dredential scheme
25835+ */
25836+
dece6358 25837+#include <linux/module.h>
1facf9fc 25838+#include "aufs.h"
25839+
b752ccd1
AM
25840+/* internal workqueue named AUFS_WKQ_NAME and AUFS_WKQ_PRE_NAME */
25841+enum {
25842+ AuWkq_INORMAL,
25843+ AuWkq_IPRE
25844+};
25845+
25846+static struct {
25847+ char *name;
25848+ struct workqueue_struct *wkq;
25849+} au_wkq[] = {
25850+ [AuWkq_INORMAL] = {
25851+ .name = AUFS_WKQ_NAME
25852+ },
25853+ [AuWkq_IPRE] = {
25854+ .name = AUFS_WKQ_PRE_NAME
25855+ }
25856+};
1facf9fc 25857+
25858+struct au_wkinfo {
25859+ struct work_struct wk;
25860+ struct super_block *sb;
25861+
25862+ unsigned int flags; /* see wkq.h */
25863+
25864+ au_wkq_func_t func;
25865+ void *args;
25866+
1facf9fc 25867+ struct completion *comp;
25868+};
25869+
25870+/* ---------------------------------------------------------------------- */
25871+
1facf9fc 25872+static void wkq_func(struct work_struct *wk)
25873+{
25874+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
25875+
25876+ wkinfo->func(wkinfo->args);
1facf9fc 25877+ if (au_ftest_wkq(wkinfo->flags, WAIT))
25878+ complete(wkinfo->comp);
25879+ else {
25880+ kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
25881+ module_put(THIS_MODULE);
25882+ kfree(wkinfo);
25883+ }
25884+}
25885+
25886+/*
25887+ * Since struct completion is large, try allocating it dynamically.
25888+ */
25889+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
25890+#define AuWkqCompDeclare(name) struct completion *comp = NULL
25891+
25892+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
25893+{
25894+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
25895+ if (*comp) {
25896+ init_completion(*comp);
25897+ wkinfo->comp = *comp;
25898+ return 0;
25899+ }
25900+ return -ENOMEM;
25901+}
25902+
25903+static void au_wkq_comp_free(struct completion *comp)
25904+{
25905+ kfree(comp);
25906+}
25907+
25908+#else
25909+
25910+/* no braces */
25911+#define AuWkqCompDeclare(name) \
25912+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
25913+ struct completion *comp = &_ ## name
25914+
25915+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
25916+{
25917+ wkinfo->comp = *comp;
25918+ return 0;
25919+}
25920+
25921+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
25922+{
25923+ /* empty */
25924+}
25925+#endif /* 4KSTACKS */
25926+
b752ccd1 25927+static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags)
1facf9fc 25928+{
b752ccd1
AM
25929+ struct workqueue_struct *wkq;
25930+
1facf9fc 25931+ au_dbg_verify_kthread();
b752ccd1 25932+ if (flags & AuWkq_WAIT) {
4a4d8108 25933+ INIT_WORK_ON_STACK(&wkinfo->wk, wkq_func);
b752ccd1
AM
25934+ wkq = au_wkq[AuWkq_INORMAL].wkq;
25935+ if (flags & AuWkq_PRE)
25936+ wkq = au_wkq[AuWkq_IPRE].wkq;
25937+ queue_work(wkq, &wkinfo->wk);
4a4d8108
AM
25938+ } else {
25939+ INIT_WORK(&wkinfo->wk, wkq_func);
25940+ schedule_work(&wkinfo->wk);
25941+ }
1facf9fc 25942+}
25943+
b752ccd1 25944+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 25945+{
25946+ int err;
25947+ AuWkqCompDeclare(comp);
25948+ struct au_wkinfo wkinfo = {
b752ccd1 25949+ .flags = flags,
1facf9fc 25950+ .func = func,
25951+ .args = args
25952+ };
25953+
25954+ err = au_wkq_comp_alloc(&wkinfo, &comp);
25955+ if (!err) {
b752ccd1 25956+ au_wkq_run(&wkinfo, flags);
1facf9fc 25957+ /* no timeout, no interrupt */
25958+ wait_for_completion(wkinfo.comp);
25959+ au_wkq_comp_free(comp);
4a4d8108 25960+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 25961+ }
25962+
25963+ return err;
25964+
25965+}
25966+
25967+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
25968+{
25969+ int err;
25970+ struct au_wkinfo *wkinfo;
25971+
25972+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
25973+
25974+ /*
25975+ * wkq_func() must free this wkinfo.
25976+ * it highly depends upon the implementation of workqueue.
25977+ */
25978+ err = 0;
25979+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
25980+ if (wkinfo) {
25981+ wkinfo->sb = sb;
25982+ wkinfo->flags = !AuWkq_WAIT;
25983+ wkinfo->func = func;
25984+ wkinfo->args = args;
25985+ wkinfo->comp = NULL;
25986+ kobject_get(&au_sbi(sb)->si_kobj);
25987+ __module_get(THIS_MODULE);
25988+
4a4d8108 25989+ au_wkq_run(wkinfo, !AuWkq_WAIT);
1facf9fc 25990+ } else {
25991+ err = -ENOMEM;
25992+ atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
25993+ }
25994+
25995+ return err;
25996+}
25997+
25998+/* ---------------------------------------------------------------------- */
25999+
26000+void au_nwt_init(struct au_nowait_tasks *nwt)
26001+{
26002+ atomic_set(&nwt->nw_len, 0);
4a4d8108 26003+ /* smp_mb(); */ /* atomic_set */
1facf9fc 26004+ init_waitqueue_head(&nwt->nw_wq);
26005+}
26006+
26007+void au_wkq_fin(void)
26008+{
b752ccd1
AM
26009+ int i;
26010+
26011+ for (i = 0; i < ARRAY_SIZE(au_wkq); i++)
26012+ if (au_wkq[i].wkq)
26013+ destroy_workqueue(au_wkq[i].wkq);
1facf9fc 26014+}
26015+
26016+int __init au_wkq_init(void)
26017+{
b752ccd1
AM
26018+ int err, i;
26019+
26020+ err = 0;
26021+ for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
26022+ au_wkq[i].wkq = create_workqueue(au_wkq[i].name);
26023+ if (IS_ERR(au_wkq[i].wkq))
26024+ err = PTR_ERR(au_wkq[i].wkq);
26025+ else if (!au_wkq[i].wkq)
26026+ err = -ENOMEM;
26027+ if (unlikely(err))
26028+ au_wkq[i].wkq = NULL;
26029+ }
26030+ if (!err)
26031+ au_dbg_verify_wkq();
26032+ else
26033+ au_wkq_fin();
26034+
26035+ return err;
1facf9fc 26036+}
b752ccd1
AM
26037diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
26038--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
26039+++ linux/fs/aufs/wkq.h 2010-08-21 21:00:02.986708041 +0200
26040@@ -0,0 +1,88 @@
1facf9fc 26041+/*
4a4d8108 26042+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26043+ *
26044+ * This program, aufs is free software; you can redistribute it and/or modify
26045+ * it under the terms of the GNU General Public License as published by
26046+ * the Free Software Foundation; either version 2 of the License, or
26047+ * (at your option) any later version.
dece6358
AM
26048+ *
26049+ * This program is distributed in the hope that it will be useful,
26050+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26051+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26052+ * GNU General Public License for more details.
26053+ *
26054+ * You should have received a copy of the GNU General Public License
26055+ * along with this program; if not, write to the Free Software
26056+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26057+ */
26058+
26059+/*
26060+ * workqueue for asynchronous/super-io operations
26061+ * todo: try new credentials management scheme
26062+ */
26063+
26064+#ifndef __AUFS_WKQ_H__
26065+#define __AUFS_WKQ_H__
26066+
26067+#ifdef __KERNEL__
26068+
1facf9fc 26069+#include <linux/sched.h>
dece6358 26070+#include <linux/wait.h>
1facf9fc 26071+#include <linux/aufs_type.h>
26072+
dece6358
AM
26073+struct super_block;
26074+
1facf9fc 26075+/* ---------------------------------------------------------------------- */
26076+
26077+/*
26078+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
26079+ */
26080+struct au_nowait_tasks {
26081+ atomic_t nw_len;
26082+ wait_queue_head_t nw_wq;
26083+};
26084+
26085+/* ---------------------------------------------------------------------- */
26086+
26087+typedef void (*au_wkq_func_t)(void *args);
26088+
26089+/* wkq flags */
26090+#define AuWkq_WAIT 1
b752ccd1 26091+#define AuWkq_PRE (1 << 1)
1facf9fc 26092+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
26093+#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
26094+#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
26095+
26096+/* wkq.c */
b752ccd1 26097+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
1facf9fc 26098+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
26099+void au_nwt_init(struct au_nowait_tasks *nwt);
26100+int __init au_wkq_init(void);
26101+void au_wkq_fin(void);
26102+
26103+/* ---------------------------------------------------------------------- */
26104+
b752ccd1
AM
26105+static inline int au_wkq_wait_pre(au_wkq_func_t func, void *args)
26106+{
26107+ return au_wkq_do_wait(AuWkq_WAIT | AuWkq_PRE, func, args);
26108+}
26109+
26110+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 26111+{
b752ccd1 26112+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 26113+}
26114+
26115+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
26116+{
26117+ if (!atomic_dec_return(&nwt->nw_len))
26118+ wake_up_all(&nwt->nw_wq);
26119+}
26120+
26121+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
26122+{
26123+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
26124+ return 0;
26125+}
26126+
26127+#endif /* __KERNEL__ */
26128+#endif /* __AUFS_WKQ_H__ */
b752ccd1
AM
26129diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
26130--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
26131+++ linux/fs/aufs/xino.c 2010-08-21 21:00:02.986708041 +0200
26132@@ -0,0 +1,1263 @@
1facf9fc 26133+/*
4a4d8108 26134+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26135+ *
26136+ * This program, aufs is free software; you can redistribute it and/or modify
26137+ * it under the terms of the GNU General Public License as published by
26138+ * the Free Software Foundation; either version 2 of the License, or
26139+ * (at your option) any later version.
dece6358
AM
26140+ *
26141+ * This program is distributed in the hope that it will be useful,
26142+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26143+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26144+ * GNU General Public License for more details.
26145+ *
26146+ * You should have received a copy of the GNU General Public License
26147+ * along with this program; if not, write to the Free Software
26148+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26149+ */
26150+
26151+/*
26152+ * external inode number translation table and bitmap
26153+ */
26154+
dece6358 26155+#include <linux/file.h>
1facf9fc 26156+#include <linux/seq_file.h>
26157+#include <linux/uaccess.h>
26158+#include "aufs.h"
26159+
b752ccd1 26160+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 26161+ loff_t *pos)
26162+{
26163+ ssize_t err;
26164+ mm_segment_t oldfs;
b752ccd1
AM
26165+ union {
26166+ void *k;
26167+ char __user *u;
26168+ } buf;
1facf9fc 26169+
b752ccd1 26170+ buf.k = kbuf;
1facf9fc 26171+ oldfs = get_fs();
26172+ set_fs(KERNEL_DS);
26173+ do {
26174+ /* todo: signal_pending? */
b752ccd1 26175+ err = func(file, buf.u, size, pos);
1facf9fc 26176+ } while (err == -EAGAIN || err == -EINTR);
26177+ set_fs(oldfs);
26178+
26179+#if 0 /* reserved for future use */
26180+ if (err > 0)
26181+ fsnotify_access(file->f_dentry);
26182+#endif
26183+
26184+ return err;
26185+}
26186+
26187+/* ---------------------------------------------------------------------- */
26188+
b752ccd1 26189+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 26190+ size_t size, loff_t *pos)
26191+{
26192+ ssize_t err;
26193+ mm_segment_t oldfs;
b752ccd1
AM
26194+ union {
26195+ void *k;
26196+ const char __user *u;
26197+ } buf;
1facf9fc 26198+
b752ccd1 26199+ buf.k = kbuf;
1facf9fc 26200+ oldfs = get_fs();
26201+ set_fs(KERNEL_DS);
1facf9fc 26202+ do {
26203+ /* todo: signal_pending? */
b752ccd1 26204+ err = func(file, buf.u, size, pos);
1facf9fc 26205+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 26206+ set_fs(oldfs);
26207+
26208+#if 0 /* reserved for future use */
26209+ if (err > 0)
26210+ fsnotify_modify(file->f_dentry);
26211+#endif
26212+
26213+ return err;
26214+}
26215+
26216+struct do_xino_fwrite_args {
26217+ ssize_t *errp;
26218+ au_writef_t func;
26219+ struct file *file;
26220+ void *buf;
26221+ size_t size;
26222+ loff_t *pos;
26223+};
26224+
26225+static void call_do_xino_fwrite(void *args)
26226+{
26227+ struct do_xino_fwrite_args *a = args;
26228+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
26229+}
26230+
26231+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
26232+ loff_t *pos)
26233+{
26234+ ssize_t err;
26235+
26236+ /* todo: signal block and no wkq? */
b752ccd1
AM
26237+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
26238+ lockdep_off();
26239+ err = do_xino_fwrite(func, file, buf, size, pos);
26240+ lockdep_on();
26241+ } else {
26242+ /*
26243+ * it breaks RLIMIT_FSIZE and normal user's limit,
26244+ * users should care about quota and real 'filesystem full.'
26245+ */
1facf9fc 26246+ int wkq_err;
26247+ struct do_xino_fwrite_args args = {
26248+ .errp = &err,
26249+ .func = func,
26250+ .file = file,
26251+ .buf = buf,
26252+ .size = size,
26253+ .pos = pos
26254+ };
26255+
26256+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
26257+ if (unlikely(wkq_err))
26258+ err = wkq_err;
b752ccd1 26259+ }
1facf9fc 26260+
26261+ return err;
26262+}
26263+
26264+/* ---------------------------------------------------------------------- */
26265+
26266+/*
26267+ * create a new xinofile at the same place/path as @base_file.
26268+ */
26269+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
26270+{
26271+ struct file *file;
4a4d8108 26272+ struct dentry *base, *parent;
1facf9fc 26273+ struct inode *dir;
26274+ struct qstr *name;
1308ab2a 26275+ struct path path;
4a4d8108 26276+ int err;
1facf9fc 26277+
26278+ base = base_file->f_dentry;
26279+ parent = base->d_parent; /* dir inode is locked */
26280+ dir = parent->d_inode;
26281+ IMustLock(dir);
26282+
26283+ file = ERR_PTR(-EINVAL);
26284+ name = &base->d_name;
4a4d8108
AM
26285+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
26286+ if (IS_ERR(path.dentry)) {
26287+ file = (void *)path.dentry;
26288+ pr_err("%.*s lookup err %ld\n",
26289+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 26290+ goto out;
26291+ }
26292+
26293+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 26294+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 26295+ if (unlikely(err)) {
26296+ file = ERR_PTR(err);
4a4d8108 26297+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 26298+ goto out_dput;
26299+ }
26300+
1308ab2a 26301+ path.mnt = base_file->f_vfsmnt;
4a4d8108
AM
26302+ file = vfsub_dentry_open(&path,
26303+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
1facf9fc 26304+ if (IS_ERR(file)) {
4a4d8108 26305+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 26306+ goto out_dput;
26307+ }
26308+
26309+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
26310+ if (unlikely(err)) {
4a4d8108 26311+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 26312+ goto out_fput;
26313+ }
26314+
26315+ if (copy_src) {
26316+ /* no one can touch copy_src xino */
26317+ err = au_copy_file(file, copy_src,
26318+ i_size_read(copy_src->f_dentry->d_inode));
26319+ if (unlikely(err)) {
4a4d8108 26320+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 26321+ goto out_fput;
26322+ }
26323+ }
26324+ goto out_dput; /* success */
26325+
26326+ out_fput:
26327+ fput(file);
26328+ file = ERR_PTR(err);
26329+ out_dput:
4a4d8108 26330+ dput(path.dentry);
1facf9fc 26331+ out:
26332+ return file;
26333+}
26334+
26335+struct au_xino_lock_dir {
26336+ struct au_hinode *hdir;
26337+ struct dentry *parent;
26338+ struct mutex *mtx;
26339+};
26340+
26341+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
26342+ struct au_xino_lock_dir *ldir)
26343+{
26344+ aufs_bindex_t brid, bindex;
26345+
26346+ ldir->hdir = NULL;
26347+ bindex = -1;
26348+ brid = au_xino_brid(sb);
26349+ if (brid >= 0)
26350+ bindex = au_br_index(sb, brid);
26351+ if (bindex >= 0) {
26352+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 26353+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 26354+ } else {
26355+ ldir->parent = dget_parent(xino->f_dentry);
26356+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
26357+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
26358+ }
26359+}
26360+
26361+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
26362+{
26363+ if (ldir->hdir)
4a4d8108 26364+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 26365+ else {
26366+ mutex_unlock(ldir->mtx);
26367+ dput(ldir->parent);
26368+ }
26369+}
26370+
26371+/* ---------------------------------------------------------------------- */
26372+
26373+/* trucate xino files asynchronously */
26374+
26375+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
26376+{
26377+ int err;
26378+ aufs_bindex_t bi, bend;
26379+ struct au_branch *br;
26380+ struct file *new_xino, *file;
26381+ struct super_block *h_sb;
26382+ struct au_xino_lock_dir ldir;
26383+
26384+ err = -EINVAL;
26385+ bend = au_sbend(sb);
26386+ if (unlikely(bindex < 0 || bend < bindex))
26387+ goto out;
26388+ br = au_sbr(sb, bindex);
26389+ file = br->br_xino.xi_file;
26390+ if (!file)
26391+ goto out;
26392+
26393+ au_xino_lock_dir(sb, file, &ldir);
26394+ /* mnt_want_write() is unnecessary here */
26395+ new_xino = au_xino_create2(file, file);
26396+ au_xino_unlock_dir(&ldir);
26397+ err = PTR_ERR(new_xino);
26398+ if (IS_ERR(new_xino))
26399+ goto out;
26400+ err = 0;
26401+ fput(file);
26402+ br->br_xino.xi_file = new_xino;
26403+
26404+ h_sb = br->br_mnt->mnt_sb;
26405+ for (bi = 0; bi <= bend; bi++) {
26406+ if (unlikely(bi == bindex))
26407+ continue;
26408+ br = au_sbr(sb, bi);
26409+ if (br->br_mnt->mnt_sb != h_sb)
26410+ continue;
26411+
26412+ fput(br->br_xino.xi_file);
26413+ br->br_xino.xi_file = new_xino;
26414+ get_file(new_xino);
26415+ }
26416+
26417+ out:
26418+ return err;
26419+}
26420+
26421+struct xino_do_trunc_args {
26422+ struct super_block *sb;
26423+ struct au_branch *br;
26424+};
26425+
26426+static void xino_do_trunc(void *_args)
26427+{
26428+ struct xino_do_trunc_args *args = _args;
26429+ struct super_block *sb;
26430+ struct au_branch *br;
26431+ struct inode *dir;
26432+ int err;
26433+ aufs_bindex_t bindex;
26434+
26435+ err = 0;
26436+ sb = args->sb;
26437+ dir = sb->s_root->d_inode;
26438+ br = args->br;
26439+
26440+ si_noflush_write_lock(sb);
26441+ ii_read_lock_parent(dir);
26442+ bindex = au_br_index(sb, br->br_id);
26443+ err = au_xino_trunc(sb, bindex);
dece6358
AM
26444+ if (!err
26445+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 26446+ >= br->br_xino_upper)
26447+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
26448+
1facf9fc 26449+ ii_read_unlock(dir);
26450+ if (unlikely(err))
4a4d8108 26451+ pr_warning("err b%d, (%d)\n", bindex, err);
1facf9fc 26452+ atomic_dec(&br->br_xino_running);
26453+ atomic_dec(&br->br_count);
26454+ au_nwt_done(&au_sbi(sb)->si_nowait);
26455+ si_write_unlock(sb);
26456+ kfree(args);
26457+}
26458+
26459+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
26460+{
26461+ struct xino_do_trunc_args *args;
26462+ int wkq_err;
26463+
26464+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
26465+ < br->br_xino_upper)
26466+ return;
26467+
26468+ if (atomic_inc_return(&br->br_xino_running) > 1)
26469+ goto out;
26470+
26471+ /* lock and kfree() will be called in trunc_xino() */
26472+ args = kmalloc(sizeof(*args), GFP_NOFS);
26473+ if (unlikely(!args)) {
26474+ AuErr1("no memory\n");
26475+ goto out_args;
26476+ }
26477+
dece6358 26478+ atomic_inc_return(&br->br_count);
1facf9fc 26479+ args->sb = sb;
26480+ args->br = br;
26481+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
26482+ if (!wkq_err)
26483+ return; /* success */
26484+
4a4d8108 26485+ pr_err("wkq %d\n", wkq_err);
dece6358 26486+ atomic_dec_return(&br->br_count);
1facf9fc 26487+
26488+ out_args:
26489+ kfree(args);
26490+ out:
dece6358 26491+ atomic_dec_return(&br->br_xino_running);
1facf9fc 26492+}
26493+
26494+/* ---------------------------------------------------------------------- */
26495+
26496+static int au_xino_do_write(au_writef_t write, struct file *file,
26497+ ino_t h_ino, ino_t ino)
26498+{
26499+ loff_t pos;
26500+ ssize_t sz;
26501+
26502+ pos = h_ino;
26503+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
26504+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
26505+ return -EFBIG;
26506+ }
26507+ pos *= sizeof(ino);
26508+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
26509+ if (sz == sizeof(ino))
26510+ return 0; /* success */
26511+
26512+ AuIOErr("write failed (%zd)\n", sz);
26513+ return -EIO;
26514+}
26515+
26516+/*
26517+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
26518+ * at the position of @h_ino.
26519+ * even if @ino is zero, it is written to the xinofile and means no entry.
26520+ * if the size of the xino file on a specific filesystem exceeds the watermark,
26521+ * try truncating it.
26522+ */
26523+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
26524+ ino_t ino)
26525+{
26526+ int err;
26527+ unsigned int mnt_flags;
26528+ struct au_branch *br;
26529+
26530+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
26531+ || ((loff_t)-1) > 0);
dece6358 26532+ SiMustAnyLock(sb);
1facf9fc 26533+
26534+ mnt_flags = au_mntflags(sb);
26535+ if (!au_opt_test(mnt_flags, XINO))
26536+ return 0;
26537+
26538+ br = au_sbr(sb, bindex);
26539+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
26540+ h_ino, ino);
26541+ if (!err) {
26542+ if (au_opt_test(mnt_flags, TRUNC_XINO)
26543+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
26544+ xino_try_trunc(sb, br);
26545+ return 0; /* success */
26546+ }
26547+
26548+ AuIOErr("write failed (%d)\n", err);
26549+ return -EIO;
26550+}
26551+
26552+/* ---------------------------------------------------------------------- */
26553+
26554+/* aufs inode number bitmap */
26555+
26556+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
26557+static ino_t xib_calc_ino(unsigned long pindex, int bit)
26558+{
26559+ ino_t ino;
26560+
26561+ AuDebugOn(bit < 0 || page_bits <= bit);
26562+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
26563+ return ino;
26564+}
26565+
26566+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
26567+{
26568+ AuDebugOn(ino < AUFS_FIRST_INO);
26569+ ino -= AUFS_FIRST_INO;
26570+ *pindex = ino / page_bits;
26571+ *bit = ino % page_bits;
26572+}
26573+
26574+static int xib_pindex(struct super_block *sb, unsigned long pindex)
26575+{
26576+ int err;
26577+ loff_t pos;
26578+ ssize_t sz;
26579+ struct au_sbinfo *sbinfo;
26580+ struct file *xib;
26581+ unsigned long *p;
26582+
26583+ sbinfo = au_sbi(sb);
26584+ MtxMustLock(&sbinfo->si_xib_mtx);
26585+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
26586+ || !au_opt_test(sbinfo->si_mntflags, XINO));
26587+
26588+ if (pindex == sbinfo->si_xib_last_pindex)
26589+ return 0;
26590+
26591+ xib = sbinfo->si_xib;
26592+ p = sbinfo->si_xib_buf;
26593+ pos = sbinfo->si_xib_last_pindex;
26594+ pos *= PAGE_SIZE;
26595+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
26596+ if (unlikely(sz != PAGE_SIZE))
26597+ goto out;
26598+
26599+ pos = pindex;
26600+ pos *= PAGE_SIZE;
26601+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
26602+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
26603+ else {
26604+ memset(p, 0, PAGE_SIZE);
26605+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
26606+ }
26607+ if (sz == PAGE_SIZE) {
26608+ sbinfo->si_xib_last_pindex = pindex;
26609+ return 0; /* success */
26610+ }
26611+
b752ccd1
AM
26612+ out:
26613+ AuIOErr1("write failed (%zd)\n", sz);
26614+ err = sz;
26615+ if (sz >= 0)
26616+ err = -EIO;
26617+ return err;
26618+}
26619+
26620+/* ---------------------------------------------------------------------- */
26621+
26622+static void au_xib_clear_bit(struct inode *inode)
26623+{
26624+ int err, bit;
26625+ unsigned long pindex;
26626+ struct super_block *sb;
26627+ struct au_sbinfo *sbinfo;
26628+
26629+ AuDebugOn(inode->i_nlink);
26630+
26631+ sb = inode->i_sb;
26632+ xib_calc_bit(inode->i_ino, &pindex, &bit);
26633+ AuDebugOn(page_bits <= bit);
26634+ sbinfo = au_sbi(sb);
26635+ mutex_lock(&sbinfo->si_xib_mtx);
26636+ err = xib_pindex(sb, pindex);
26637+ if (!err) {
26638+ clear_bit(bit, sbinfo->si_xib_buf);
26639+ sbinfo->si_xib_next_bit = bit;
26640+ }
26641+ mutex_unlock(&sbinfo->si_xib_mtx);
26642+}
26643+
26644+/* for s_op->delete_inode() */
26645+void au_xino_delete_inode(struct inode *inode, const int unlinked)
26646+{
26647+ int err;
26648+ unsigned int mnt_flags;
26649+ aufs_bindex_t bindex, bend, bi;
26650+ unsigned char try_trunc;
26651+ struct au_iinfo *iinfo;
26652+ struct super_block *sb;
26653+ struct au_hinode *hi;
26654+ struct inode *h_inode;
26655+ struct au_branch *br;
26656+ au_writef_t xwrite;
26657+
26658+ sb = inode->i_sb;
26659+ mnt_flags = au_mntflags(sb);
26660+ if (!au_opt_test(mnt_flags, XINO)
26661+ || inode->i_ino == AUFS_ROOT_INO)
26662+ return;
26663+
26664+ if (unlinked) {
26665+ au_xigen_inc(inode);
26666+ au_xib_clear_bit(inode);
26667+ }
26668+
26669+ iinfo = au_ii(inode);
26670+ if (!iinfo)
26671+ return;
1facf9fc 26672+
b752ccd1
AM
26673+ bindex = iinfo->ii_bstart;
26674+ if (bindex < 0)
26675+ return;
1facf9fc 26676+
b752ccd1
AM
26677+ xwrite = au_sbi(sb)->si_xwrite;
26678+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
26679+ hi = iinfo->ii_hinode + bindex;
26680+ bend = iinfo->ii_bend;
26681+ for (; bindex <= bend; bindex++, hi++) {
26682+ h_inode = hi->hi_inode;
26683+ if (!h_inode
26684+ || (!unlinked && h_inode->i_nlink))
26685+ continue;
1facf9fc 26686+
b752ccd1
AM
26687+ /* inode may not be revalidated */
26688+ bi = au_br_index(sb, hi->hi_id);
26689+ if (bi < 0)
26690+ continue;
1facf9fc 26691+
b752ccd1
AM
26692+ br = au_sbr(sb, bi);
26693+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
26694+ h_inode->i_ino, /*ino*/0);
26695+ if (!err && try_trunc
26696+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
26697+ xino_try_trunc(sb, br);
1facf9fc 26698+ }
1facf9fc 26699+}
26700+
26701+/* get an unused inode number from bitmap */
26702+ino_t au_xino_new_ino(struct super_block *sb)
26703+{
26704+ ino_t ino;
26705+ unsigned long *p, pindex, ul, pend;
26706+ struct au_sbinfo *sbinfo;
26707+ struct file *file;
26708+ int free_bit, err;
26709+
26710+ if (!au_opt_test(au_mntflags(sb), XINO))
26711+ return iunique(sb, AUFS_FIRST_INO);
26712+
26713+ sbinfo = au_sbi(sb);
26714+ mutex_lock(&sbinfo->si_xib_mtx);
26715+ p = sbinfo->si_xib_buf;
26716+ free_bit = sbinfo->si_xib_next_bit;
26717+ if (free_bit < page_bits && !test_bit(free_bit, p))
26718+ goto out; /* success */
26719+ free_bit = find_first_zero_bit(p, page_bits);
26720+ if (free_bit < page_bits)
26721+ goto out; /* success */
26722+
26723+ pindex = sbinfo->si_xib_last_pindex;
26724+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
26725+ err = xib_pindex(sb, ul);
26726+ if (unlikely(err))
26727+ goto out_err;
26728+ free_bit = find_first_zero_bit(p, page_bits);
26729+ if (free_bit < page_bits)
26730+ goto out; /* success */
26731+ }
26732+
26733+ file = sbinfo->si_xib;
26734+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
26735+ for (ul = pindex + 1; ul <= pend; ul++) {
26736+ err = xib_pindex(sb, ul);
26737+ if (unlikely(err))
26738+ goto out_err;
26739+ free_bit = find_first_zero_bit(p, page_bits);
26740+ if (free_bit < page_bits)
26741+ goto out; /* success */
26742+ }
26743+ BUG();
26744+
26745+ out:
26746+ set_bit(free_bit, p);
26747+ sbinfo->si_xib_next_bit++;
26748+ pindex = sbinfo->si_xib_last_pindex;
26749+ mutex_unlock(&sbinfo->si_xib_mtx);
26750+ ino = xib_calc_ino(pindex, free_bit);
26751+ AuDbg("i%lu\n", (unsigned long)ino);
26752+ return ino;
26753+ out_err:
26754+ mutex_unlock(&sbinfo->si_xib_mtx);
26755+ AuDbg("i0\n");
26756+ return 0;
26757+}
26758+
26759+/*
26760+ * read @ino from xinofile for the specified branch{@sb, @bindex}
26761+ * at the position of @h_ino.
26762+ * if @ino does not exist and @do_new is true, get new one.
26763+ */
26764+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
26765+ ino_t *ino)
26766+{
26767+ int err;
26768+ ssize_t sz;
26769+ loff_t pos;
26770+ struct file *file;
26771+ struct au_sbinfo *sbinfo;
26772+
26773+ *ino = 0;
26774+ if (!au_opt_test(au_mntflags(sb), XINO))
26775+ return 0; /* no xino */
26776+
26777+ err = 0;
26778+ sbinfo = au_sbi(sb);
26779+ pos = h_ino;
26780+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
26781+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
26782+ return -EFBIG;
26783+ }
26784+ pos *= sizeof(*ino);
26785+
26786+ file = au_sbr(sb, bindex)->br_xino.xi_file;
26787+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
26788+ return 0; /* no ino */
26789+
26790+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
26791+ if (sz == sizeof(*ino))
26792+ return 0; /* success */
26793+
26794+ err = sz;
26795+ if (unlikely(sz >= 0)) {
26796+ err = -EIO;
26797+ AuIOErr("xino read error (%zd)\n", sz);
26798+ }
26799+
26800+ return err;
26801+}
26802+
26803+/* ---------------------------------------------------------------------- */
26804+
26805+/* create and set a new xino file */
26806+
26807+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
26808+{
26809+ struct file *file;
26810+ struct dentry *h_parent, *d;
26811+ struct inode *h_dir;
26812+ int err;
26813+
26814+ /*
26815+ * at mount-time, and the xino file is the default path,
4a4d8108 26816+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 26817+ * when a user specified the xino, we cannot get au_hdir to be ignored.
26818+ */
26819+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
26820+ S_IRUGO | S_IWUGO);
26821+ if (IS_ERR(file)) {
26822+ if (!silent)
4a4d8108 26823+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 26824+ return file;
26825+ }
26826+
26827+ /* keep file count */
26828+ h_parent = dget_parent(file->f_dentry);
26829+ h_dir = h_parent->d_inode;
26830+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
26831+ /* mnt_want_write() is unnecessary here */
26832+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
26833+ mutex_unlock(&h_dir->i_mutex);
26834+ dput(h_parent);
26835+ if (unlikely(err)) {
26836+ if (!silent)
4a4d8108 26837+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 26838+ goto out;
26839+ }
26840+
26841+ err = -EINVAL;
26842+ d = file->f_dentry;
26843+ if (unlikely(sb == d->d_sb)) {
26844+ if (!silent)
4a4d8108 26845+ pr_err("%s must be outside\n", fname);
1facf9fc 26846+ goto out;
26847+ }
26848+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
26849+ if (!silent)
4a4d8108
AM
26850+ pr_err("xino doesn't support %s(%s)\n",
26851+ fname, au_sbtype(d->d_sb));
1facf9fc 26852+ goto out;
26853+ }
26854+ return file; /* success */
26855+
26856+ out:
26857+ fput(file);
26858+ file = ERR_PTR(err);
26859+ return file;
26860+}
26861+
26862+/*
26863+ * find another branch who is on the same filesystem of the specified
26864+ * branch{@btgt}. search until @bend.
26865+ */
26866+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
26867+ aufs_bindex_t bend)
26868+{
26869+ aufs_bindex_t bindex;
26870+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
26871+
26872+ for (bindex = 0; bindex < btgt; bindex++)
26873+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
26874+ return bindex;
26875+ for (bindex++; bindex <= bend; bindex++)
26876+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
26877+ return bindex;
26878+ return -1;
26879+}
26880+
26881+/* ---------------------------------------------------------------------- */
26882+
26883+/*
26884+ * initialize the xinofile for the specified branch @br
26885+ * at the place/path where @base_file indicates.
26886+ * test whether another branch is on the same filesystem or not,
26887+ * if @do_test is true.
26888+ */
26889+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
26890+ struct file *base_file, int do_test)
26891+{
26892+ int err;
26893+ ino_t ino;
26894+ aufs_bindex_t bend, bindex;
26895+ struct au_branch *shared_br, *b;
26896+ struct file *file;
26897+ struct super_block *tgt_sb;
26898+
26899+ shared_br = NULL;
26900+ bend = au_sbend(sb);
26901+ if (do_test) {
26902+ tgt_sb = br->br_mnt->mnt_sb;
26903+ for (bindex = 0; bindex <= bend; bindex++) {
26904+ b = au_sbr(sb, bindex);
26905+ if (tgt_sb == b->br_mnt->mnt_sb) {
26906+ shared_br = b;
26907+ break;
26908+ }
26909+ }
26910+ }
26911+
26912+ if (!shared_br || !shared_br->br_xino.xi_file) {
26913+ struct au_xino_lock_dir ldir;
26914+
26915+ au_xino_lock_dir(sb, base_file, &ldir);
26916+ /* mnt_want_write() is unnecessary here */
26917+ file = au_xino_create2(base_file, NULL);
26918+ au_xino_unlock_dir(&ldir);
26919+ err = PTR_ERR(file);
26920+ if (IS_ERR(file))
26921+ goto out;
26922+ br->br_xino.xi_file = file;
26923+ } else {
26924+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
26925+ get_file(br->br_xino.xi_file);
26926+ }
26927+
26928+ ino = AUFS_ROOT_INO;
26929+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
26930+ h_ino, ino);
b752ccd1
AM
26931+ if (unlikely(err)) {
26932+ fput(br->br_xino.xi_file);
26933+ br->br_xino.xi_file = NULL;
26934+ }
1facf9fc 26935+
26936+ out:
26937+ return err;
26938+}
26939+
26940+/* ---------------------------------------------------------------------- */
26941+
26942+/* trucate a xino bitmap file */
26943+
26944+/* todo: slow */
26945+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
26946+{
26947+ int err, bit;
26948+ ssize_t sz;
26949+ unsigned long pindex;
26950+ loff_t pos, pend;
26951+ struct au_sbinfo *sbinfo;
26952+ au_readf_t func;
26953+ ino_t *ino;
26954+ unsigned long *p;
26955+
26956+ err = 0;
26957+ sbinfo = au_sbi(sb);
dece6358 26958+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 26959+ p = sbinfo->si_xib_buf;
26960+ func = sbinfo->si_xread;
26961+ pend = i_size_read(file->f_dentry->d_inode);
26962+ pos = 0;
26963+ while (pos < pend) {
26964+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
26965+ err = sz;
26966+ if (unlikely(sz <= 0))
26967+ goto out;
26968+
26969+ err = 0;
26970+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
26971+ if (unlikely(*ino < AUFS_FIRST_INO))
26972+ continue;
26973+
26974+ xib_calc_bit(*ino, &pindex, &bit);
26975+ AuDebugOn(page_bits <= bit);
26976+ err = xib_pindex(sb, pindex);
26977+ if (!err)
26978+ set_bit(bit, p);
26979+ else
26980+ goto out;
26981+ }
26982+ }
26983+
26984+ out:
26985+ return err;
26986+}
26987+
26988+static int xib_restore(struct super_block *sb)
26989+{
26990+ int err;
26991+ aufs_bindex_t bindex, bend;
26992+ void *page;
26993+
26994+ err = -ENOMEM;
26995+ page = (void *)__get_free_page(GFP_NOFS);
26996+ if (unlikely(!page))
26997+ goto out;
26998+
26999+ err = 0;
27000+ bend = au_sbend(sb);
27001+ for (bindex = 0; !err && bindex <= bend; bindex++)
27002+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
27003+ err = do_xib_restore
27004+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
27005+ else
27006+ AuDbg("b%d\n", bindex);
27007+ free_page((unsigned long)page);
27008+
27009+ out:
27010+ return err;
27011+}
27012+
27013+int au_xib_trunc(struct super_block *sb)
27014+{
27015+ int err;
27016+ ssize_t sz;
27017+ loff_t pos;
27018+ struct au_xino_lock_dir ldir;
27019+ struct au_sbinfo *sbinfo;
27020+ unsigned long *p;
27021+ struct file *file;
27022+
dece6358
AM
27023+ SiMustWriteLock(sb);
27024+
1facf9fc 27025+ err = 0;
27026+ sbinfo = au_sbi(sb);
27027+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
27028+ goto out;
27029+
27030+ file = sbinfo->si_xib;
27031+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
27032+ goto out;
27033+
27034+ au_xino_lock_dir(sb, file, &ldir);
27035+ /* mnt_want_write() is unnecessary here */
27036+ file = au_xino_create2(sbinfo->si_xib, NULL);
27037+ au_xino_unlock_dir(&ldir);
27038+ err = PTR_ERR(file);
27039+ if (IS_ERR(file))
27040+ goto out;
27041+ fput(sbinfo->si_xib);
27042+ sbinfo->si_xib = file;
27043+
27044+ p = sbinfo->si_xib_buf;
27045+ memset(p, 0, PAGE_SIZE);
27046+ pos = 0;
27047+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
27048+ if (unlikely(sz != PAGE_SIZE)) {
27049+ err = sz;
27050+ AuIOErr("err %d\n", err);
27051+ if (sz >= 0)
27052+ err = -EIO;
27053+ goto out;
27054+ }
27055+
27056+ mutex_lock(&sbinfo->si_xib_mtx);
27057+ /* mnt_want_write() is unnecessary here */
27058+ err = xib_restore(sb);
27059+ mutex_unlock(&sbinfo->si_xib_mtx);
27060+
27061+out:
27062+ return err;
27063+}
27064+
27065+/* ---------------------------------------------------------------------- */
27066+
27067+/*
27068+ * xino mount option handlers
27069+ */
27070+static au_readf_t find_readf(struct file *h_file)
27071+{
27072+ const struct file_operations *fop = h_file->f_op;
27073+
27074+ if (fop) {
27075+ if (fop->read)
27076+ return fop->read;
27077+ if (fop->aio_read)
27078+ return do_sync_read;
27079+ }
27080+ return ERR_PTR(-ENOSYS);
27081+}
27082+
27083+static au_writef_t find_writef(struct file *h_file)
27084+{
27085+ const struct file_operations *fop = h_file->f_op;
27086+
27087+ if (fop) {
27088+ if (fop->write)
27089+ return fop->write;
27090+ if (fop->aio_write)
27091+ return do_sync_write;
27092+ }
27093+ return ERR_PTR(-ENOSYS);
27094+}
27095+
27096+/* xino bitmap */
27097+static void xino_clear_xib(struct super_block *sb)
27098+{
27099+ struct au_sbinfo *sbinfo;
27100+
dece6358
AM
27101+ SiMustWriteLock(sb);
27102+
1facf9fc 27103+ sbinfo = au_sbi(sb);
27104+ sbinfo->si_xread = NULL;
27105+ sbinfo->si_xwrite = NULL;
27106+ if (sbinfo->si_xib)
27107+ fput(sbinfo->si_xib);
27108+ sbinfo->si_xib = NULL;
27109+ free_page((unsigned long)sbinfo->si_xib_buf);
27110+ sbinfo->si_xib_buf = NULL;
27111+}
27112+
27113+static int au_xino_set_xib(struct super_block *sb, struct file *base)
27114+{
27115+ int err;
27116+ loff_t pos;
27117+ struct au_sbinfo *sbinfo;
27118+ struct file *file;
27119+
dece6358
AM
27120+ SiMustWriteLock(sb);
27121+
1facf9fc 27122+ sbinfo = au_sbi(sb);
27123+ file = au_xino_create2(base, sbinfo->si_xib);
27124+ err = PTR_ERR(file);
27125+ if (IS_ERR(file))
27126+ goto out;
27127+ if (sbinfo->si_xib)
27128+ fput(sbinfo->si_xib);
27129+ sbinfo->si_xib = file;
27130+ sbinfo->si_xread = find_readf(file);
27131+ sbinfo->si_xwrite = find_writef(file);
27132+
27133+ err = -ENOMEM;
27134+ if (!sbinfo->si_xib_buf)
27135+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
27136+ if (unlikely(!sbinfo->si_xib_buf))
27137+ goto out_unset;
27138+
27139+ sbinfo->si_xib_last_pindex = 0;
27140+ sbinfo->si_xib_next_bit = 0;
27141+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
27142+ pos = 0;
27143+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
27144+ PAGE_SIZE, &pos);
27145+ if (unlikely(err != PAGE_SIZE))
27146+ goto out_free;
27147+ }
27148+ err = 0;
27149+ goto out; /* success */
27150+
27151+ out_free:
27152+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
27153+ sbinfo->si_xib_buf = NULL;
27154+ if (err >= 0)
27155+ err = -EIO;
27156+ out_unset:
27157+ fput(sbinfo->si_xib);
27158+ sbinfo->si_xib = NULL;
27159+ sbinfo->si_xread = NULL;
27160+ sbinfo->si_xwrite = NULL;
1facf9fc 27161+ out:
b752ccd1 27162+ return err;
1facf9fc 27163+}
27164+
b752ccd1
AM
27165+/* xino for each branch */
27166+static void xino_clear_br(struct super_block *sb)
27167+{
27168+ aufs_bindex_t bindex, bend;
27169+ struct au_branch *br;
1facf9fc 27170+
b752ccd1
AM
27171+ bend = au_sbend(sb);
27172+ for (bindex = 0; bindex <= bend; bindex++) {
27173+ br = au_sbr(sb, bindex);
27174+ if (!br || !br->br_xino.xi_file)
27175+ continue;
27176+
27177+ fput(br->br_xino.xi_file);
27178+ br->br_xino.xi_file = NULL;
27179+ }
27180+}
27181+
27182+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 27183+{
27184+ int err;
b752ccd1
AM
27185+ ino_t ino;
27186+ aufs_bindex_t bindex, bend, bshared;
27187+ struct {
27188+ struct file *old, *new;
27189+ } *fpair, *p;
27190+ struct au_branch *br;
27191+ struct inode *inode;
27192+ au_writef_t writef;
1facf9fc 27193+
b752ccd1
AM
27194+ SiMustWriteLock(sb);
27195+
27196+ err = -ENOMEM;
27197+ bend = au_sbend(sb);
27198+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
27199+ if (unlikely(!fpair))
1facf9fc 27200+ goto out;
27201+
b752ccd1
AM
27202+ inode = sb->s_root->d_inode;
27203+ ino = AUFS_ROOT_INO;
27204+ writef = au_sbi(sb)->si_xwrite;
27205+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
27206+ br = au_sbr(sb, bindex);
27207+ bshared = is_sb_shared(sb, bindex, bindex - 1);
27208+ if (bshared >= 0) {
27209+ /* shared xino */
27210+ *p = fpair[bshared];
27211+ get_file(p->new);
27212+ }
27213+
27214+ if (!p->new) {
27215+ /* new xino */
27216+ p->old = br->br_xino.xi_file;
27217+ p->new = au_xino_create2(base, br->br_xino.xi_file);
27218+ err = PTR_ERR(p->new);
27219+ if (IS_ERR(p->new)) {
27220+ p->new = NULL;
27221+ goto out_pair;
27222+ }
27223+ }
27224+
27225+ err = au_xino_do_write(writef, p->new,
27226+ au_h_iptr(inode, bindex)->i_ino, ino);
27227+ if (unlikely(err))
27228+ goto out_pair;
27229+ }
27230+
27231+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
27232+ br = au_sbr(sb, bindex);
27233+ if (br->br_xino.xi_file)
27234+ fput(br->br_xino.xi_file);
27235+ get_file(p->new);
27236+ br->br_xino.xi_file = p->new;
27237+ }
1facf9fc 27238+
b752ccd1
AM
27239+ out_pair:
27240+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
27241+ if (p->new)
27242+ fput(p->new);
27243+ else
27244+ break;
27245+ kfree(fpair);
1facf9fc 27246+ out:
27247+ return err;
27248+}
b752ccd1
AM
27249+
27250+void au_xino_clr(struct super_block *sb)
27251+{
27252+ struct au_sbinfo *sbinfo;
27253+
27254+ au_xigen_clr(sb);
27255+ xino_clear_xib(sb);
27256+ xino_clear_br(sb);
27257+ sbinfo = au_sbi(sb);
27258+ /* lvalue, do not call au_mntflags() */
27259+ au_opt_clr(sbinfo->si_mntflags, XINO);
27260+}
27261+
27262+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
27263+{
27264+ int err, skip;
27265+ struct dentry *parent, *cur_parent;
27266+ struct qstr *dname, *cur_name;
27267+ struct file *cur_xino;
27268+ struct inode *dir;
27269+ struct au_sbinfo *sbinfo;
27270+
27271+ SiMustWriteLock(sb);
27272+
27273+ err = 0;
27274+ sbinfo = au_sbi(sb);
27275+ parent = dget_parent(xino->file->f_dentry);
27276+ if (remount) {
27277+ skip = 0;
27278+ dname = &xino->file->f_dentry->d_name;
27279+ cur_xino = sbinfo->si_xib;
27280+ if (cur_xino) {
27281+ cur_parent = dget_parent(cur_xino->f_dentry);
27282+ cur_name = &cur_xino->f_dentry->d_name;
27283+ skip = (cur_parent == parent
27284+ && dname->len == cur_name->len
27285+ && !memcmp(dname->name, cur_name->name,
27286+ dname->len));
27287+ dput(cur_parent);
27288+ }
27289+ if (skip)
27290+ goto out;
27291+ }
27292+
27293+ au_opt_set(sbinfo->si_mntflags, XINO);
27294+ dir = parent->d_inode;
27295+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
27296+ /* mnt_want_write() is unnecessary here */
27297+ err = au_xino_set_xib(sb, xino->file);
27298+ if (!err)
27299+ err = au_xigen_set(sb, xino->file);
27300+ if (!err)
27301+ err = au_xino_set_br(sb, xino->file);
27302+ mutex_unlock(&dir->i_mutex);
27303+ if (!err)
27304+ goto out; /* success */
27305+
27306+ /* reset all */
27307+ AuIOErr("failed creating xino(%d).\n", err);
27308+
27309+ out:
27310+ dput(parent);
27311+ return err;
27312+}
27313+
27314+/* ---------------------------------------------------------------------- */
27315+
27316+/*
27317+ * create a xinofile at the default place/path.
27318+ */
27319+struct file *au_xino_def(struct super_block *sb)
27320+{
27321+ struct file *file;
27322+ char *page, *p;
27323+ struct au_branch *br;
27324+ struct super_block *h_sb;
27325+ struct path path;
27326+ aufs_bindex_t bend, bindex, bwr;
27327+
27328+ br = NULL;
27329+ bend = au_sbend(sb);
27330+ bwr = -1;
27331+ for (bindex = 0; bindex <= bend; bindex++) {
27332+ br = au_sbr(sb, bindex);
27333+ if (au_br_writable(br->br_perm)
27334+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
27335+ bwr = bindex;
27336+ break;
27337+ }
27338+ }
27339+
27340+ if (bwr >= 0) {
27341+ file = ERR_PTR(-ENOMEM);
27342+ page = __getname_gfp(GFP_NOFS);
27343+ if (unlikely(!page))
27344+ goto out;
27345+ path.mnt = br->br_mnt;
27346+ path.dentry = au_h_dptr(sb->s_root, bwr);
27347+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
27348+ file = (void *)p;
27349+ if (!IS_ERR(p)) {
27350+ strcat(p, "/" AUFS_XINO_FNAME);
27351+ AuDbg("%s\n", p);
27352+ file = au_xino_create(sb, p, /*silent*/0);
27353+ if (!IS_ERR(file))
27354+ au_xino_brid_set(sb, br->br_id);
27355+ }
27356+ __putname(page);
27357+ } else {
27358+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
27359+ if (IS_ERR(file))
27360+ goto out;
27361+ h_sb = file->f_dentry->d_sb;
27362+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
27363+ pr_err("xino doesn't support %s(%s)\n",
27364+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
27365+ fput(file);
27366+ file = ERR_PTR(-EINVAL);
27367+ }
27368+ if (!IS_ERR(file))
27369+ au_xino_brid_set(sb, -1);
27370+ }
27371+
27372+ out:
27373+ return file;
27374+}
27375+
27376+/* ---------------------------------------------------------------------- */
27377+
27378+int au_xino_path(struct seq_file *seq, struct file *file)
27379+{
27380+ int err;
27381+
27382+ err = au_seq_path(seq, &file->f_path);
27383+ if (unlikely(err < 0))
27384+ goto out;
27385+
27386+ err = 0;
27387+#define Deleted "\\040(deleted)"
27388+ seq->count -= sizeof(Deleted) - 1;
27389+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
27390+ sizeof(Deleted) - 1));
27391+#undef Deleted
27392+
27393+ out:
27394+ return err;
27395+}
27396diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
27397--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
27398+++ linux/include/linux/aufs_type.h 2010-08-21 21:00:02.989917215 +0200
4a4d8108 27399@@ -0,0 +1,198 @@
1facf9fc 27400+/*
4a4d8108 27401+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 27402+ *
27403+ * This program, aufs is free software; you can redistribute it and/or modify
27404+ * it under the terms of the GNU General Public License as published by
27405+ * the Free Software Foundation; either version 2 of the License, or
27406+ * (at your option) any later version.
dece6358
AM
27407+ *
27408+ * This program is distributed in the hope that it will be useful,
27409+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27410+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27411+ * GNU General Public License for more details.
27412+ *
27413+ * You should have received a copy of the GNU General Public License
27414+ * along with this program; if not, write to the Free Software
27415+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27416+ */
27417+
27418+#ifndef __AUFS_TYPE_H__
27419+#define __AUFS_TYPE_H__
27420+
27421+#include <linux/ioctl.h>
4a4d8108
AM
27422+/* for those who didn't "make headers_install" */
27423+#ifdef __KERNEL__
27424+#include <linux/kernel.h>
27425+#endif
27426+#include <linux/limits.h>
1308ab2a 27427+#include <linux/types.h>
1facf9fc 27428+
b752ccd1 27429+#define AUFS_VERSION "2-standalone.tree-35-20100816"
1facf9fc 27430+
27431+/* todo? move this to linux-2.6.19/include/magic.h */
27432+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
27433+
27434+/* ---------------------------------------------------------------------- */
27435+
27436+#ifdef CONFIG_AUFS_BRANCH_MAX_127
1308ab2a 27437+typedef __s8 aufs_bindex_t;
1facf9fc 27438+#define AUFS_BRANCH_MAX 127
27439+#else
1308ab2a 27440+typedef __s16 aufs_bindex_t;
1facf9fc 27441+#ifdef CONFIG_AUFS_BRANCH_MAX_511
27442+#define AUFS_BRANCH_MAX 511
27443+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
27444+#define AUFS_BRANCH_MAX 1023
27445+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
27446+#define AUFS_BRANCH_MAX 32767
27447+#endif
27448+#endif
27449+
27450+#ifdef __KERNEL__
27451+#ifndef AUFS_BRANCH_MAX
27452+#error unknown CONFIG_AUFS_BRANCH_MAX value
27453+#endif
27454+#endif /* __KERNEL__ */
27455+
27456+/* ---------------------------------------------------------------------- */
27457+
27458+#define AUFS_NAME "aufs"
27459+#define AUFS_FSTYPE AUFS_NAME
27460+
27461+#define AUFS_ROOT_INO 2
27462+#define AUFS_FIRST_INO 11
27463+
27464+#define AUFS_WH_PFX ".wh."
27465+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
4a4d8108
AM
27466+#define AUFS_WH_TMP_LEN 4
27467+/* a limit for rmdir/rename a dir */
27468+#define AUFS_MAX_NAMELEN (NAME_MAX \
27469+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
27470+ - 1 /* dot */\
27471+ - AUFS_WH_TMP_LEN) /* hex */
1facf9fc 27472+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
27473+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
27474+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
27475+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
27476+#define AUFS_DIRWH_DEF 3
27477+#define AUFS_RDCACHE_DEF 10 /* seconds */
27478+#define AUFS_RDBLK_DEF 512 /* bytes */
27479+#define AUFS_RDHASH_DEF 32
27480+#define AUFS_WKQ_NAME AUFS_NAME "d"
b752ccd1 27481+#define AUFS_WKQ_PRE_NAME AUFS_WKQ_NAME "_pre"
1facf9fc 27482+#define AUFS_MFS_SECOND_DEF 30 /* seconds */
27483+#define AUFS_PLINK_WARN 100 /* number of plinks */
27484+
27485+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
27486+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
27487+
27488+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
27489+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
27490+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
27491+
27492+/* doubly whiteouted */
27493+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
27494+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
27495+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
27496+
27497+/* branch permission */
27498+#define AUFS_BRPERM_RW "rw"
27499+#define AUFS_BRPERM_RO "ro"
27500+#define AUFS_BRPERM_RR "rr"
27501+#define AUFS_BRPERM_WH "wh"
27502+#define AUFS_BRPERM_NLWH "nolwh"
27503+#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
27504+#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
27505+#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
27506+
27507+/* ---------------------------------------------------------------------- */
27508+
27509+/* ioctl */
27510+enum {
27511+ AuCtl_PLINK_MAINT,
1308ab2a 27512+ AuCtl_PLINK_CLEAN,
27513+
27514+ /* readdir in userspace */
27515+ AuCtl_RDU,
4a4d8108
AM
27516+ AuCtl_RDU_INO,
27517+
27518+ /* pathconf wrapper */
27519+ AuCtl_WBR_FD
1308ab2a 27520+};
27521+
27522+/* borrowed from linux/include/linux/kernel.h */
27523+#ifndef ALIGN
27524+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
27525+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
27526+#endif
27527+
27528+/* borrowed from linux/include/linux/compiler-gcc3.h */
27529+#ifndef __aligned
27530+#define __aligned(x) __attribute__((aligned(x)))
27531+#define __packed __attribute__((packed))
27532+#endif
27533+
27534+struct au_rdu_cookie {
27535+ __u64 h_pos;
27536+ __s16 bindex;
27537+ __u8 flags;
27538+ __u8 pad;
27539+ __u32 generation;
27540+} __aligned(8);
27541+
27542+struct au_rdu_ent {
27543+ __u64 ino;
27544+ __s16 bindex;
27545+ __u8 type;
27546+ __u8 nlen;
27547+ __u8 wh;
27548+ char name[0];
27549+} __aligned(8);
27550+
27551+static inline int au_rdu_len(int nlen)
27552+{
27553+ /* include the terminating NULL */
27554+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
27555+ sizeof(__u64));
27556+}
27557+
27558+union au_rdu_ent_ul {
27559+ struct au_rdu_ent __user *e;
b752ccd1 27560+ __u64 ul;
1308ab2a 27561+};
27562+
27563+enum {
27564+ AufsCtlRduV_SZ,
1308ab2a 27565+ AufsCtlRduV_End
1facf9fc 27566+};
27567+
1308ab2a 27568+struct aufs_rdu {
27569+ /* input */
27570+ union {
27571+ __u64 sz; /* AuCtl_RDU */
27572+ __u64 nent; /* AuCtl_RDU_INO */
27573+ };
27574+ union au_rdu_ent_ul ent;
27575+ __u16 verify[AufsCtlRduV_End];
27576+
27577+ /* input/output */
27578+ __u32 blk;
27579+
27580+ /* output */
27581+ union au_rdu_ent_ul tail;
27582+ /* number of entries which were added in a single call */
27583+ __u64 rent;
27584+ __u8 full;
27585+ __u8 shwh;
27586+
27587+ struct au_rdu_cookie cookie;
27588+} __aligned(8);
27589+
1facf9fc 27590+#define AuCtlType 'A'
27591+#define AUFS_CTL_PLINK_MAINT _IO(AuCtlType, AuCtl_PLINK_MAINT)
27592+#define AUFS_CTL_PLINK_CLEAN _IO(AuCtlType, AuCtl_PLINK_CLEAN)
1308ab2a 27593+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
27594+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
4a4d8108 27595+#define AUFS_CTL_WBR_FD _IO(AuCtlType, AuCtl_WBR_FD)
1facf9fc 27596+
27597+#endif /* __AUFS_TYPE_H__ */
This page took 3.585606 seconds and 4 git commands to generate.