]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs2.patch
- grsec updated to grsecurity-2.2.0-2.6.36-201011062054.patch, vserver to patch-2...
[packages/kernel.git] / kernel-aufs2.patch
CommitLineData
e49829fe 1aufs2.1 kbuild patch for linux-2.6.36
b752ccd1
AM
2
3diff --git a/fs/Kconfig b/fs/Kconfig
953406b4 4index 3d18530..8f582e1 100644
b752ccd1
AM
5--- a/fs/Kconfig
6+++ b/fs/Kconfig
7@@ -189,6 +189,7 @@ source "fs/romfs/Kconfig"
8 source "fs/sysv/Kconfig"
9 source "fs/ufs/Kconfig"
10 source "fs/exofs/Kconfig"
11+source "fs/aufs/Kconfig"
12
13 endif # MISC_FILESYSTEMS
14
15diff --git a/fs/Makefile b/fs/Makefile
16index e6ec1d3..b0d795a 100644
17--- a/fs/Makefile
18+++ b/fs/Makefile
19@@ -126,3 +126,4 @@ obj-$(CONFIG_BTRFS_FS) += btrfs/
20 obj-$(CONFIG_GFS2_FS) += gfs2/
21 obj-$(CONFIG_EXOFS_FS) += exofs/
22 obj-$(CONFIG_CEPH_FS) += ceph/
23+obj-$(CONFIG_AUFS_FS) += aufs/
24diff --git a/include/linux/Kbuild b/include/linux/Kbuild
953406b4 25index 626b629..a841231 100644
b752ccd1
AM
26--- a/include/linux/Kbuild
27+++ b/include/linux/Kbuild
953406b4 28@@ -60,6 +60,7 @@ header-y += atmppp.h
b752ccd1
AM
29 header-y += atmsap.h
30 header-y += atmsvc.h
953406b4 31 header-y += audit.h
b752ccd1 32+header-y += aufs_type.h
953406b4 33 header-y += auto_fs.h
b752ccd1 34 header-y += auto_fs4.h
953406b4 35 header-y += auxvec.h
e49829fe 36aufs2.1 base patch for linux-2.6.35
b752ccd1
AM
37
38diff --git a/fs/namei.c b/fs/namei.c
e49829fe 39index 868d0cb..6e92c81 100644
b752ccd1
AM
40--- a/fs/namei.c
41+++ b/fs/namei.c
e49829fe 42@@ -1178,7 +1178,7 @@ out:
b752ccd1
AM
43 * needs parent already locked. Doesn't follow mounts.
44 * SMP-safe.
45 */
46-static struct dentry *lookup_hash(struct nameidata *nd)
47+struct dentry *lookup_hash(struct nameidata *nd)
48 {
49 int err;
50
e49829fe 51@@ -1188,7 +1188,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
b752ccd1
AM
52 return __lookup_hash(&nd->last, nd->path.dentry, nd);
53 }
54
55-static int __lookup_one_len(const char *name, struct qstr *this,
56+int __lookup_one_len(const char *name, struct qstr *this,
57 struct dentry *base, int len)
58 {
59 unsigned long hash;
60diff --git a/fs/splice.c b/fs/splice.c
e49829fe 61index efdbfec..e01a51e 100644
b752ccd1
AM
62--- a/fs/splice.c
63+++ b/fs/splice.c
e49829fe 64@@ -1104,8 +1104,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
b752ccd1
AM
65 /*
66 * Attempt to initiate a splice from pipe to file.
67 */
68-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
69- loff_t *ppos, size_t len, unsigned int flags)
70+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
71+ loff_t *ppos, size_t len, unsigned int flags)
72 {
73 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
74 loff_t *, size_t, unsigned int);
e49829fe 75@@ -1132,9 +1132,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
b752ccd1
AM
76 /*
77 * Attempt to initiate a splice from a file to a pipe.
78 */
79-static long do_splice_to(struct file *in, loff_t *ppos,
80- struct pipe_inode_info *pipe, size_t len,
81- unsigned int flags)
82+long do_splice_to(struct file *in, loff_t *ppos,
83+ struct pipe_inode_info *pipe, size_t len,
84+ unsigned int flags)
85 {
86 ssize_t (*splice_read)(struct file *, loff_t *,
87 struct pipe_inode_info *, size_t, unsigned int);
88diff --git a/include/linux/namei.h b/include/linux/namei.h
89index 05b441d..91bc74e 100644
90--- a/include/linux/namei.h
91+++ b/include/linux/namei.h
92@@ -73,6 +73,9 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
93 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
94 int (*open)(struct inode *, struct file *));
95
96+extern struct dentry *lookup_hash(struct nameidata *nd);
97+extern int __lookup_one_len(const char *name, struct qstr *this,
98+ struct dentry *base, int len);
99 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
100
101 extern int follow_down(struct path *);
102diff --git a/include/linux/splice.h b/include/linux/splice.h
103index 997c3b4..be9a153 100644
104--- a/include/linux/splice.h
105+++ b/include/linux/splice.h
106@@ -89,4 +89,10 @@ extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *);
107 extern void splice_shrink_spd(struct pipe_inode_info *,
108 struct splice_pipe_desc *);
109
110+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
111+ loff_t *ppos, size_t len, unsigned int flags);
112+extern long do_splice_to(struct file *in, loff_t *ppos,
113+ struct pipe_inode_info *pipe, size_t len,
114+ unsigned int flags);
115+
116 #endif
e49829fe 117aufs2.1 standalone patch for linux-2.6.36
b752ccd1 118
e49829fe
JR
119diff --git a/fs/inode.c b/fs/inode.c
120index 722860b..bfb0698 100644
121--- a/fs/inode.c
122+++ b/fs/inode.c
123@@ -84,6 +84,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
124 * the i_state of an inode while it is in use..
125 */
126 DEFINE_SPINLOCK(inode_lock);
127+EXPORT_SYMBOL(inode_lock);
128
129 /*
130 * iprune_sem provides exclusion between the kswapd or try_to_free_pages
b752ccd1 131diff --git a/fs/namei.c b/fs/namei.c
953406b4 132index 56e8ece..ba75f28 100644
b752ccd1
AM
133--- a/fs/namei.c
134+++ b/fs/namei.c
953406b4 135@@ -347,6 +347,7 @@ int deny_write_access(struct file * file)
b752ccd1
AM
136
137 return 0;
138 }
139+EXPORT_SYMBOL(deny_write_access);
140
141 /**
142 * path_get - get a reference to a path
953406b4 143@@ -1177,6 +1178,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
b752ccd1
AM
144 return ERR_PTR(err);
145 return __lookup_hash(&nd->last, nd->path.dentry, nd);
146 }
147+EXPORT_SYMBOL(lookup_hash);
148
149 int __lookup_one_len(const char *name, struct qstr *this,
150 struct dentry *base, int len)
953406b4 151@@ -1199,6 +1201,7 @@ int __lookup_one_len(const char *name, struct qstr *this,
b752ccd1
AM
152 this->hash = end_name_hash(hash);
153 return 0;
154 }
155+EXPORT_SYMBOL(__lookup_one_len);
156
157 /**
158 * lookup_one_len - filesystem helper to lookup single pathname component
159diff --git a/fs/namespace.c b/fs/namespace.c
953406b4 160index 2e10cb1..8fa77c4 100644
b752ccd1
AM
161--- a/fs/namespace.c
162+++ b/fs/namespace.c
953406b4 163@@ -1283,6 +1283,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
b752ccd1
AM
164 }
165 return 0;
166 }
167+EXPORT_SYMBOL(iterate_mounts);
168
169 static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
170 {
171diff --git a/fs/notify/group.c b/fs/notify/group.c
953406b4 172index d309f38..f0e9568 100644
b752ccd1
AM
173--- a/fs/notify/group.c
174+++ b/fs/notify/group.c
175@@ -22,6 +22,7 @@
176 #include <linux/srcu.h>
177 #include <linux/rculist.h>
178 #include <linux/wait.h>
179+#include <linux/module.h>
180
181 #include <linux/fsnotify_backend.h>
182 #include "fsnotify.h"
953406b4
AM
183@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
184 if (atomic_dec_and_test(&group->refcnt))
185 fsnotify_destroy_group(group);
b752ccd1
AM
186 }
187+EXPORT_SYMBOL(fsnotify_put_group);
188
189 /*
953406b4
AM
190 * Create a new fsnotify_group and hold a reference for the group returned.
191@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
b752ccd1
AM
192
193 return group;
194 }
953406b4
AM
195+EXPORT_SYMBOL(fsnotify_alloc_group);
196diff --git a/fs/notify/mark.c b/fs/notify/mark.c
197index 325185e..adede09 100644
198--- a/fs/notify/mark.c
199+++ b/fs/notify/mark.c
200@@ -113,6 +113,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
201 if (atomic_dec_and_test(&mark->refcnt))
202 mark->free_mark(mark);
b752ccd1
AM
203 }
204+EXPORT_SYMBOL(fsnotify_put_mark);
205
206 /*
953406b4
AM
207 * Any time a mark is getting freed we end up here.
208@@ -190,6 +191,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
b752ccd1
AM
209 if (unlikely(atomic_dec_and_test(&group->num_marks)))
210 fsnotify_final_destroy_group(group);
211 }
953406b4 212+EXPORT_SYMBOL(fsnotify_destroy_mark);
b752ccd1 213
953406b4
AM
214 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
215 {
216@@ -277,6 +279,7 @@ err:
b752ccd1 217
953406b4 218 return ret;
b752ccd1 219 }
953406b4 220+EXPORT_SYMBOL(fsnotify_add_mark);
b752ccd1
AM
221
222 /*
953406b4
AM
223 * clear any marks in a group in which mark->flags & flags is true
224@@ -332,6 +335,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
225 atomic_set(&mark->refcnt, 1);
226 mark->free_mark = free_mark;
b752ccd1 227 }
953406b4 228+EXPORT_SYMBOL(fsnotify_init_mark);
b752ccd1 229
953406b4
AM
230 static int fsnotify_mark_destroy(void *ignored)
231 {
b752ccd1 232diff --git a/fs/open.c b/fs/open.c
953406b4 233index 630715f..1c864c7 100644
b752ccd1
AM
234--- a/fs/open.c
235+++ b/fs/open.c
953406b4 236@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
b752ccd1
AM
237 mutex_unlock(&dentry->d_inode->i_mutex);
238 return ret;
239 }
240+EXPORT_SYMBOL(do_truncate);
241
242 static long do_sys_truncate(const char __user *pathname, loff_t length)
243 {
244diff --git a/fs/splice.c b/fs/splice.c
953406b4 245index 278c94f..033f7ac 100644
b752ccd1
AM
246--- a/fs/splice.c
247+++ b/fs/splice.c
953406b4 248@@ -1116,6 +1116,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
b752ccd1
AM
249
250 return splice_write(pipe, out, ppos, len, flags);
251 }
252+EXPORT_SYMBOL(do_splice_from);
253
254 /*
255 * Attempt to initiate a splice from a file to a pipe.
953406b4 256@@ -1142,6 +1143,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
b752ccd1
AM
257
258 return splice_read(in, ppos, pipe, len, flags);
259 }
260+EXPORT_SYMBOL(do_splice_to);
261
262 /**
263 * splice_direct_to_actor - splices data directly between two non-pipes
264diff --git a/security/commoncap.c b/security/commoncap.c
265index 4e01599..3611e1b 100644
266--- a/security/commoncap.c
267+++ b/security/commoncap.c
268@@ -951,3 +951,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
269 }
270 return ret;
271 }
272+EXPORT_SYMBOL(cap_file_mmap);
273diff --git a/security/device_cgroup.c b/security/device_cgroup.c
274index 8d9c48f..29108aa 100644
275--- a/security/device_cgroup.c
276+++ b/security/device_cgroup.c
277@@ -515,6 +515,7 @@ found:
278
279 return -EPERM;
280 }
281+EXPORT_SYMBOL(devcgroup_inode_permission);
282
283 int devcgroup_inode_mknod(int mode, dev_t dev)
284 {
285diff --git a/security/security.c b/security/security.c
953406b4 286index c53949f..0ae5b91 100644
b752ccd1
AM
287--- a/security/security.c
288+++ b/security/security.c
289@@ -376,6 +376,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
290 return 0;
291 return security_ops->path_mkdir(dir, dentry, mode);
292 }
293+EXPORT_SYMBOL(security_path_mkdir);
294
295 int security_path_rmdir(struct path *dir, struct dentry *dentry)
296 {
297@@ -383,6 +384,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
298 return 0;
299 return security_ops->path_rmdir(dir, dentry);
300 }
301+EXPORT_SYMBOL(security_path_rmdir);
302
303 int security_path_unlink(struct path *dir, struct dentry *dentry)
304 {
305@@ -390,6 +392,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
306 return 0;
307 return security_ops->path_unlink(dir, dentry);
308 }
309+EXPORT_SYMBOL(security_path_unlink);
310
311 int security_path_symlink(struct path *dir, struct dentry *dentry,
312 const char *old_name)
313@@ -398,6 +401,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
314 return 0;
315 return security_ops->path_symlink(dir, dentry, old_name);
316 }
317+EXPORT_SYMBOL(security_path_symlink);
318
319 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
320 struct dentry *new_dentry)
321@@ -406,6 +410,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
322 return 0;
323 return security_ops->path_link(old_dentry, new_dir, new_dentry);
324 }
325+EXPORT_SYMBOL(security_path_link);
326
327 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
328 struct path *new_dir, struct dentry *new_dentry)
329@@ -416,6 +421,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
330 return security_ops->path_rename(old_dir, old_dentry, new_dir,
331 new_dentry);
332 }
333+EXPORT_SYMBOL(security_path_rename);
334
953406b4
AM
335 int security_path_truncate(struct path *path)
336 {
337@@ -423,6 +429,7 @@ int security_path_truncate(struct path *path)
b752ccd1 338 return 0;
953406b4 339 return security_ops->path_truncate(path);
b752ccd1
AM
340 }
341+EXPORT_SYMBOL(security_path_truncate);
342
343 int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
344 mode_t mode)
953406b4 345@@ -431,6 +438,7 @@ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
b752ccd1
AM
346 return 0;
347 return security_ops->path_chmod(dentry, mnt, mode);
348 }
349+EXPORT_SYMBOL(security_path_chmod);
350
351 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
352 {
953406b4 353@@ -438,6 +446,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
b752ccd1
AM
354 return 0;
355 return security_ops->path_chown(path, uid, gid);
356 }
357+EXPORT_SYMBOL(security_path_chown);
358
359 int security_path_chroot(struct path *path)
360 {
953406b4 361@@ -514,6 +523,7 @@ int security_inode_readlink(struct dentry *dentry)
b752ccd1
AM
362 return 0;
363 return security_ops->inode_readlink(dentry);
364 }
365+EXPORT_SYMBOL(security_inode_readlink);
366
367 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
368 {
953406b4 369@@ -528,6 +538,7 @@ int security_inode_permission(struct inode *inode, int mask)
b752ccd1
AM
370 return 0;
371 return security_ops->inode_permission(inode, mask);
372 }
373+EXPORT_SYMBOL(security_inode_permission);
374
375 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
376 {
953406b4
AM
377@@ -627,6 +638,7 @@ int security_file_permission(struct file *file, int mask)
378
379 return fsnotify_perm(file, mask);
b752ccd1
AM
380 }
381+EXPORT_SYMBOL(security_file_permission);
382
383 int security_file_alloc(struct file *file)
384 {
953406b4 385@@ -654,6 +666,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
b752ccd1
AM
386 return ret;
387 return ima_file_mmap(file, prot);
388 }
389+EXPORT_SYMBOL(security_file_mmap);
390
391 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
392 unsigned long prot)
e49829fe
JR
393--- /dev/null
394+++ linux-2.6/Documentation/ABI/testing/debugfs-aufs 2010-10-24 11:11:14.000000000 +0200
4a4d8108 395@@ -0,0 +1,37 @@
1facf9fc 396+What: /debug/aufs/si_<id>/
397+Date: March 2009
398+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
399+Description:
400+ Under /debug/aufs, a directory named si_<id> is created
401+ per aufs mount, where <id> is a unique id generated
402+ internally.
403+
404+What: /debug/aufs/si_<id>/xib
405+Date: March 2009
406+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
407+Description:
408+ It shows the consumed blocks by xib (External Inode Number
409+ Bitmap), its block size and file size.
410+ When the aufs mount option 'noxino' is specified, it
4a4d8108 411+ will be empty. About XINO files, see the aufs manual.
1facf9fc 412+
413+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
414+Date: March 2009
415+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
416+Description:
417+ It shows the consumed blocks by xino (External Inode Number
418+ Translation Table), its link count, block size and file
419+ size.
420+ When the aufs mount option 'noxino' is specified, it
4a4d8108 421+ will be empty. About XINO files, see the aufs manual.
1facf9fc 422+
423+What: /debug/aufs/si_<id>/xigen
424+Date: March 2009
425+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
426+Description:
427+ It shows the consumed blocks by xigen (External Inode
428+ Generation Table), its block size and file size.
429+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
430+ be created.
431+ When the aufs mount option 'noxino' is specified, it
4a4d8108 432+ will be empty. About XINO files, see the aufs manual.
e49829fe
JR
433--- /dev/null
434+++ linux-2.6/Documentation/ABI/testing/sysfs-aufs 2010-10-24 11:11:14.000000000 +0200
4a4d8108 435@@ -0,0 +1,24 @@
1facf9fc 436+What: /sys/fs/aufs/si_<id>/
437+Date: March 2009
438+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
439+Description:
440+ Under /sys/fs/aufs, a directory named si_<id> is created
441+ per aufs mount, where <id> is a unique id generated
442+ internally.
443+
444+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
445+Date: March 2009
446+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
447+Description:
448+ It shows the abolute path of a member directory (which
449+ is called branch) in aufs, and its permission.
450+
451+What: /sys/fs/aufs/si_<id>/xi_path
452+Date: March 2009
453+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
454+Description:
455+ It shows the abolute path of XINO (External Inode Number
456+ Bitmap, Translation Table and Generation Table) file
457+ even if it is the default path.
458+ When the aufs mount option 'noxino' is specified, it
4a4d8108 459+ will be empty. About XINO files, see the aufs manual.
e49829fe
JR
460--- /dev/null
461+++ linux-2.6/fs/aufs/aufs.h 2010-10-24 11:19:23.000000000 +0200
4a4d8108 462@@ -0,0 +1,61 @@
1facf9fc 463+/*
4a4d8108 464+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 465+ *
466+ * This program, aufs is free software; you can redistribute it and/or modify
467+ * it under the terms of the GNU General Public License as published by
468+ * the Free Software Foundation; either version 2 of the License, or
469+ * (at your option) any later version.
dece6358
AM
470+ *
471+ * This program is distributed in the hope that it will be useful,
472+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
473+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
474+ * GNU General Public License for more details.
475+ *
476+ * You should have received a copy of the GNU General Public License
477+ * along with this program; if not, write to the Free Software
478+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 479+ */
480+
481+/*
482+ * all header files
483+ */
484+
485+#ifndef __AUFS_H__
486+#define __AUFS_H__
487+
488+#ifdef __KERNEL__
489+
4a4d8108
AM
490+#define AuStub(type, name, body, ...) \
491+ static inline type name(__VA_ARGS__) { body; }
492+
493+#define AuStubVoid(name, ...) \
494+ AuStub(void, name, , __VA_ARGS__)
495+#define AuStubInt0(name, ...) \
496+ AuStub(int, name, return 0, __VA_ARGS__)
497+
1facf9fc 498+#include "debug.h"
499+
500+#include "branch.h"
501+#include "cpup.h"
502+#include "dcsub.h"
503+#include "dbgaufs.h"
504+#include "dentry.h"
505+#include "dir.h"
4a4d8108 506+#include "dynop.h"
1facf9fc 507+#include "file.h"
508+#include "fstype.h"
509+#include "inode.h"
510+#include "loop.h"
511+#include "module.h"
4a4d8108 512+/* never include ./mtx.h */
1facf9fc 513+#include "opts.h"
514+#include "rwsem.h"
515+#include "spl.h"
516+#include "super.h"
517+#include "sysaufs.h"
518+#include "vfsub.h"
519+#include "whout.h"
520+#include "wkq.h"
521+
522+#endif /* __KERNEL__ */
523+#endif /* __AUFS_H__ */
e49829fe
JR
524--- /dev/null
525+++ linux-2.6/fs/aufs/branch.c 2010-10-24 16:28:53.000000000 +0200
526@@ -0,0 +1,1020 @@
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+
4f0767ce 672+out_br:
1facf9fc 673+ kfree(add_branch);
4f0767ce 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+
4f0767ce 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+
4f0767ce 782+out:
1facf9fc 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+ */
e49829fe 850+ h_dentry = path->dentry;
953406b4 851+ err = vfs_statfs(path, &kst);
4a4d8108
AM
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+
4f0767ce 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+
4f0767ce 903+out_err:
b752ccd1 904+ br->br_mnt = NULL;
4f0767ce 905+out:
1facf9fc 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;
1facf9fc 965+ bend = au_sbend(sb);
966+ amount = bend + 1 - bindex;
967+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
968+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
969+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
970+ au_set_h_dptr(root, bindex, dget(h_dentry));
971+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
972+ /*flags*/0);
973+}
974+
975+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
976+{
977+ int err;
1facf9fc 978+ aufs_bindex_t bend, add_bindex;
979+ struct dentry *root, *h_dentry;
980+ struct inode *root_inode;
981+ struct au_branch *add_branch;
982+
983+ root = sb->s_root;
984+ root_inode = root->d_inode;
985+ IMustLock(root_inode);
986+ err = test_add(sb, add, remount);
987+ if (unlikely(err < 0))
988+ goto out;
989+ if (err) {
990+ err = 0;
991+ goto out; /* success */
992+ }
993+
994+ bend = au_sbend(sb);
995+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
996+ err = PTR_ERR(add_branch);
997+ if (IS_ERR(add_branch))
998+ goto out;
999+
1000+ err = au_br_init(add_branch, sb, add);
1001+ if (unlikely(err)) {
1002+ au_br_do_free(add_branch);
1003+ goto out;
1004+ }
1005+
1006+ add_bindex = add->bindex;
1007+ h_dentry = add->path.dentry;
1008+ if (!remount)
1009+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1010+ else {
1011+ sysaufs_brs_del(sb, add_bindex);
1012+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1013+ sysaufs_brs_add(sb, add_bindex);
1014+ }
1015+
1308ab2a 1016+ if (!add_bindex) {
1facf9fc 1017+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 1018+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
1019+ } else
1facf9fc 1020+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 1021+
1022+ /*
4a4d8108 1023+ * this test/set prevents aufs from handling unnecesary notify events
1facf9fc 1024+ * of xino files, in a case of re-adding a writable branch which was
1025+ * once detached from aufs.
1026+ */
1027+ if (au_xino_brid(sb) < 0
1028+ && au_br_writable(add_branch->br_perm)
1029+ && !au_test_fs_bad_xino(h_dentry->d_sb)
1030+ && add_branch->br_xino.xi_file
1031+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
1032+ au_xino_brid_set(sb, add_branch->br_id);
1033+
4f0767ce 1034+out:
1facf9fc 1035+ return err;
1036+}
1037+
1038+/* ---------------------------------------------------------------------- */
1039+
1040+/*
1041+ * delete a branch
1042+ */
1043+
1044+/* to show the line number, do not make it inlined function */
4a4d8108 1045+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 1046+ if (do_info) \
4a4d8108 1047+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 1048+} while (0)
1049+
1050+/*
1051+ * test if the branch is deletable or not.
1052+ */
1053+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 1054+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1055+{
1056+ int err, i, j, ndentry;
1057+ aufs_bindex_t bstart, bend;
1facf9fc 1058+ struct au_dcsub_pages dpages;
1059+ struct au_dpage *dpage;
1060+ struct dentry *d;
1061+ struct inode *inode;
1062+
1063+ err = au_dpages_init(&dpages, GFP_NOFS);
1064+ if (unlikely(err))
1065+ goto out;
1066+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
1067+ if (unlikely(err))
1068+ goto out_dpages;
1069+
1facf9fc 1070+ for (i = 0; !err && i < dpages.ndpage; i++) {
1071+ dpage = dpages.dpages + i;
1072+ ndentry = dpage->ndentry;
1073+ for (j = 0; !err && j < ndentry; j++) {
1074+ d = dpage->dentries[j];
1075+ AuDebugOn(!atomic_read(&d->d_count));
1076+ inode = d->d_inode;
1077+ if (au_digen(d) == sigen && au_iigen(inode) == sigen)
1078+ di_read_lock_child(d, AuLock_IR);
1079+ else {
1080+ di_write_lock_child(d);
1081+ err = au_reval_dpath(d, sigen);
1082+ if (!err)
1083+ di_downgrade_lock(d, AuLock_IR);
1084+ else {
1085+ di_write_unlock(d);
1086+ break;
1087+ }
1088+ }
1089+
1090+ bstart = au_dbstart(d);
1091+ bend = au_dbend(d);
1092+ if (bstart <= bindex
1093+ && bindex <= bend
1094+ && au_h_dptr(d, bindex)
1095+ && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
1096+ err = -EBUSY;
1097+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
1098+ }
1099+ di_read_unlock(d, AuLock_IR);
1100+ }
1101+ }
1102+
4f0767ce 1103+out_dpages:
1facf9fc 1104+ au_dpages_free(&dpages);
4f0767ce 1105+out:
1facf9fc 1106+ return err;
1107+}
1108+
1109+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 1110+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1111+{
1112+ int err;
1113+ struct inode *i;
1114+ aufs_bindex_t bstart, bend;
1facf9fc 1115+
1116+ err = 0;
1facf9fc 1117+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
1118+ AuDebugOn(!atomic_read(&i->i_count));
1119+ if (!list_empty(&i->i_dentry))
1120+ continue;
1121+
1122+ if (au_iigen(i) == sigen)
1123+ ii_read_lock_child(i);
1124+ else {
1125+ ii_write_lock_child(i);
1126+ err = au_refresh_hinode_self(i, /*do_attr*/1);
1127+ if (!err)
1128+ ii_downgrade_lock(i);
1129+ else {
1130+ ii_write_unlock(i);
1131+ break;
1132+ }
1133+ }
1134+
1135+ bstart = au_ibstart(i);
1136+ bend = au_ibend(i);
1137+ if (bstart <= bindex
1138+ && bindex <= bend
1139+ && au_h_iptr(i, bindex)
1140+ && (!S_ISDIR(i->i_mode) || bstart == bend)) {
1141+ err = -EBUSY;
1142+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
1143+ ii_read_unlock(i);
1144+ break;
1145+ }
1146+ ii_read_unlock(i);
1147+ }
1148+
1149+ return err;
1150+}
1151+
b752ccd1
AM
1152+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
1153+ const unsigned int verbose)
1facf9fc 1154+{
1155+ int err;
1156+ unsigned int sigen;
1157+
1158+ sigen = au_sigen(root->d_sb);
1159+ DiMustNoWaiters(root);
1160+ IiMustNoWaiters(root->d_inode);
1161+ di_write_unlock(root);
b752ccd1 1162+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 1163+ if (!err)
b752ccd1 1164+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 1165+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
1166+
1167+ return err;
1168+}
1169+
1170+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
1171+ const aufs_bindex_t bindex,
1172+ const aufs_bindex_t bend)
1173+{
1174+ struct au_branch **brp, **p;
1175+
dece6358
AM
1176+ AuRwMustWriteLock(&sbinfo->si_rwsem);
1177+
1facf9fc 1178+ brp = sbinfo->si_branch + bindex;
1179+ if (bindex < bend)
1180+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
1181+ sbinfo->si_branch[0 + bend] = NULL;
1182+ sbinfo->si_bend--;
1183+
1184+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
1185+ if (p)
1186+ sbinfo->si_branch = p;
4a4d8108 1187+ /* harmless error */
1facf9fc 1188+}
1189+
1190+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
1191+ const aufs_bindex_t bend)
1192+{
1193+ struct au_hdentry *hdp, *p;
1194+
1308ab2a 1195+ AuRwMustWriteLock(&dinfo->di_rwsem);
1196+
4a4d8108 1197+ hdp = dinfo->di_hdentry;
1facf9fc 1198+ if (bindex < bend)
4a4d8108
AM
1199+ memmove(hdp + bindex, hdp + bindex + 1,
1200+ sizeof(*hdp) * (bend - bindex));
1201+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 1202+ dinfo->di_bend--;
1203+
4a4d8108 1204+ p = krealloc(hdp, sizeof(*p) * bend, GFP_NOFS);
1facf9fc 1205+ if (p)
1206+ dinfo->di_hdentry = p;
4a4d8108 1207+ /* harmless error */
1facf9fc 1208+}
1209+
1210+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
1211+ const aufs_bindex_t bend)
1212+{
1213+ struct au_hinode *hip, *p;
1214+
1308ab2a 1215+ AuRwMustWriteLock(&iinfo->ii_rwsem);
1216+
1facf9fc 1217+ hip = iinfo->ii_hinode + bindex;
1218+ if (bindex < bend)
1219+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
1220+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 1221+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 1222+ iinfo->ii_bend--;
1223+
1224+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
1225+ if (p)
1226+ iinfo->ii_hinode = p;
4a4d8108 1227+ /* harmless error */
1facf9fc 1228+}
1229+
1230+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
1231+ struct au_branch *br)
1232+{
1233+ aufs_bindex_t bend;
1234+ struct au_sbinfo *sbinfo;
1235+ struct dentry *root;
1236+ struct inode *inode;
1237+
dece6358
AM
1238+ SiMustWriteLock(sb);
1239+
1facf9fc 1240+ root = sb->s_root;
1241+ inode = root->d_inode;
1facf9fc 1242+ sbinfo = au_sbi(sb);
1243+ bend = sbinfo->si_bend;
1244+
1245+ dput(au_h_dptr(root, bindex));
1246+ au_hiput(au_hi(inode, bindex));
1247+ au_br_do_free(br);
1248+
1249+ au_br_do_del_brp(sbinfo, bindex, bend);
1250+ au_br_do_del_hdp(au_di(root), bindex, bend);
1251+ au_br_do_del_hip(au_ii(inode), bindex, bend);
1252+}
1253+
1254+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
1255+{
1256+ int err, rerr, i;
1257+ unsigned int mnt_flags;
1258+ aufs_bindex_t bindex, bend, br_id;
1259+ unsigned char do_wh, verbose;
1260+ struct au_branch *br;
1261+ struct au_wbr *wbr;
1262+
1263+ err = 0;
1264+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
1265+ if (bindex < 0) {
1266+ if (remount)
1267+ goto out; /* success */
1268+ err = -ENOENT;
4a4d8108 1269+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 1270+ goto out;
1271+ }
1272+ AuDbg("bindex b%d\n", bindex);
1273+
1274+ err = -EBUSY;
1275+ mnt_flags = au_mntflags(sb);
1276+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
1277+ bend = au_sbend(sb);
1278+ if (unlikely(!bend)) {
1279+ AuVerbose(verbose, "no more branches left\n");
1280+ goto out;
1281+ }
1282+ br = au_sbr(sb, bindex);
1283+ i = atomic_read(&br->br_count);
1284+ if (unlikely(i)) {
1285+ AuVerbose(verbose, "%d file(s) opened\n", i);
e49829fe 1286+ goto out;
1facf9fc 1287+ }
1288+
1289+ wbr = br->br_wbr;
1290+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
1291+ if (do_wh) {
1308ab2a 1292+ /* instead of WbrWhMustWriteLock(wbr) */
1293+ SiMustWriteLock(sb);
1facf9fc 1294+ for (i = 0; i < AuBrWh_Last; i++) {
1295+ dput(wbr->wbr_wh[i]);
1296+ wbr->wbr_wh[i] = NULL;
1297+ }
1298+ }
1299+
b752ccd1 1300+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 1301+ if (unlikely(err)) {
1302+ if (do_wh)
1303+ goto out_wh;
1304+ goto out;
1305+ }
1306+
1307+ err = 0;
1308+ br_id = br->br_id;
1309+ if (!remount)
1310+ au_br_do_del(sb, bindex, br);
1311+ else {
1312+ sysaufs_brs_del(sb, bindex);
1313+ au_br_do_del(sb, bindex, br);
1314+ sysaufs_brs_add(sb, bindex);
1315+ }
1316+
1308ab2a 1317+ if (!bindex) {
1facf9fc 1318+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 1319+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
1320+ } else
1facf9fc 1321+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
1322+ if (au_opt_test(mnt_flags, PLINK))
1323+ au_plink_half_refresh(sb, br_id);
1324+
b752ccd1 1325+ if (au_xino_brid(sb) == br_id)
1facf9fc 1326+ au_xino_brid_set(sb, -1);
1327+ goto out; /* success */
1328+
4f0767ce 1329+out_wh:
1facf9fc 1330+ /* revert */
1331+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
1332+ if (rerr)
4a4d8108
AM
1333+ pr_warning("failed re-creating base whiteout, %s. (%d)\n",
1334+ del->pathname, rerr);
4f0767ce 1335+out:
1facf9fc 1336+ return err;
1337+}
1338+
1339+/* ---------------------------------------------------------------------- */
1340+
1341+/*
1342+ * change a branch permission
1343+ */
1344+
dece6358
AM
1345+static void au_warn_ima(void)
1346+{
1347+#ifdef CONFIG_IMA
1308ab2a 1348+ /* since it doesn't support mark_files_ro() */
e49829fe 1349+ AuWarn1("RW -> RO makes IMA to produce wrong message");
dece6358
AM
1350+#endif
1351+}
1352+
1facf9fc 1353+static int do_need_sigen_inc(int a, int b)
1354+{
1355+ return au_br_whable(a) && !au_br_whable(b);
1356+}
1357+
1358+static int need_sigen_inc(int old, int new)
1359+{
1360+ return do_need_sigen_inc(old, new)
1361+ || do_need_sigen_inc(new, old);
1362+}
1363+
1364+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
1365+{
1366+ int err;
1367+ unsigned long n, ul, bytes, files;
e49829fe 1368+ aufs_bindex_t br_id;
1facf9fc 1369+ struct file *file, *hf, **a;
e49829fe
JR
1370+ struct dentry *dentry;
1371+ struct inode *inode;
1372+ struct au_hfile *hfile;
1373+ struct list_head *list;
1374+#ifdef CONFIG_SMP
1375+ int cpu;
1376+#endif
1facf9fc 1377+ const int step_bytes = 1024, /* memory allocation unit */
1378+ step_files = step_bytes / sizeof(*a);
1379+
1380+ err = -ENOMEM;
1381+ n = 0;
1382+ bytes = step_bytes;
1383+ files = step_files;
1384+ a = kmalloc(bytes, GFP_NOFS);
1385+ if (unlikely(!a))
1386+ goto out;
1387+
e49829fe
JR
1388+#ifdef CONFIG_SMP
1389+ cpu = smp_processor_id();
1390+ file->f_sb_list_cpu = cpu;
1391+ list = per_cpu_ptr(sb->s_files, cpu);
1392+#else
1393+ list = &sb->s_files;
1394+#endif
1395+
1facf9fc 1396+ /* no need file_list_lock() since sbinfo is locked? defered? */
e49829fe
JR
1397+ br_id = au_sbr_id(sb, bindex);
1398+ list_for_each_entry(file, list, f_u.fu_list) {
1facf9fc 1399+ if (special_file(file->f_dentry->d_inode->i_mode))
1400+ continue;
e49829fe
JR
1401+ dentry = file->f_dentry;
1402+ inode = dentry->d_inode;
1facf9fc 1403+
1404+ AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
1405+ fi_read_lock(file);
1406+ if (unlikely(au_test_mmapped(file))) {
1407+ err = -EBUSY;
1408+ FiMustNoWaiters(file);
1409+ fi_read_unlock(file);
1410+ goto out_free;
1411+ }
1412+
e49829fe
JR
1413+ hfile = &au_fi(file)->fi_htop;
1414+ hf = hfile->hf_file;
1415+ if (!S_ISREG(inode->i_mode)
1facf9fc 1416+ || !(file->f_mode & FMODE_WRITE)
e49829fe
JR
1417+ || hfile->hf_br->br_id != br_id
1418+ || !(hf->f_mode & FMODE_WRITE)) {
1facf9fc 1419+ FiMustNoWaiters(file);
1420+ fi_read_unlock(file);
1421+ continue;
1422+ }
1423+
1facf9fc 1424+ FiMustNoWaiters(file);
1425+ fi_read_unlock(file);
1426+
1427+ if (n < files)
1428+ a[n++] = hf;
1429+ else {
1430+ void *p;
1431+
1432+ err = -ENOMEM;
1433+ bytes += step_bytes;
1434+ files += step_files;
1435+ p = krealloc(a, bytes, GFP_NOFS);
1436+ if (p) {
1437+ a = p;
1438+ a[n++] = hf;
1439+ } else
1440+ goto out_free;
1441+ }
1442+ }
1443+
1444+ err = 0;
dece6358
AM
1445+ if (n)
1446+ au_warn_ima();
1facf9fc 1447+ for (ul = 0; ul < n; ul++) {
1448+ /* todo: already flushed? */
1449+ /* cf. fs/super.c:mark_files_ro() */
1450+ hf = a[ul];
1451+ hf->f_mode &= ~FMODE_WRITE;
1452+ if (!file_check_writeable(hf)) {
1453+ file_release_write(hf);
1454+ mnt_drop_write(hf->f_vfsmnt);
1455+ }
1456+ }
1457+
4f0767ce 1458+out_free:
1facf9fc 1459+ kfree(a);
4f0767ce 1460+out:
1facf9fc 1461+ return err;
1462+}
1463+
1464+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1465+ int *do_update)
1466+{
1467+ int err, rerr;
1468+ aufs_bindex_t bindex;
1308ab2a 1469+ struct path path;
1facf9fc 1470+ struct dentry *root;
1471+ struct au_branch *br;
1472+
1473+ root = sb->s_root;
1facf9fc 1474+ bindex = au_find_dbindex(root, mod->h_root);
1475+ if (bindex < 0) {
1476+ if (remount)
1477+ return 0; /* success */
1478+ err = -ENOENT;
4a4d8108 1479+ pr_err("%s no such branch\n", mod->path);
1facf9fc 1480+ goto out;
1481+ }
1482+ AuDbg("bindex b%d\n", bindex);
1483+
1484+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
1485+ if (unlikely(err))
1486+ goto out;
1487+
1488+ br = au_sbr(sb, bindex);
1489+ if (br->br_perm == mod->perm)
1490+ return 0; /* success */
1491+
1492+ if (au_br_writable(br->br_perm)) {
1493+ /* remove whiteout base */
1494+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
1495+ if (unlikely(err))
1496+ goto out;
1497+
1498+ if (!au_br_writable(mod->perm)) {
1499+ /* rw --> ro, file might be mmapped */
1500+ DiMustNoWaiters(root);
1501+ IiMustNoWaiters(root->d_inode);
1502+ di_write_unlock(root);
1503+ err = au_br_mod_files_ro(sb, bindex);
1504+ /* aufs_write_lock() calls ..._child() */
1505+ di_write_lock_child(root);
1506+
1507+ if (unlikely(err)) {
1508+ rerr = -ENOMEM;
1509+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
1510+ GFP_NOFS);
1308ab2a 1511+ if (br->br_wbr) {
1512+ path.mnt = br->br_mnt;
1513+ path.dentry = mod->h_root;
1514+ rerr = au_wbr_init(br, sb, br->br_perm,
1515+ &path);
1516+ }
1facf9fc 1517+ if (unlikely(rerr)) {
1518+ AuIOErr("nested error %d (%d)\n",
1519+ rerr, err);
1520+ br->br_perm = mod->perm;
1521+ }
1522+ }
1523+ }
1524+ } else if (au_br_writable(mod->perm)) {
1525+ /* ro --> rw */
1526+ err = -ENOMEM;
1527+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1528+ if (br->br_wbr) {
1308ab2a 1529+ path.mnt = br->br_mnt;
1530+ path.dentry = mod->h_root;
1facf9fc 1531+ err = au_wbr_init(br, sb, mod->perm, &path);
1532+ if (unlikely(err)) {
1533+ kfree(br->br_wbr);
1534+ br->br_wbr = NULL;
1535+ }
1536+ }
1537+ }
1538+
1539+ if (!err) {
1540+ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
1541+ br->br_perm = mod->perm;
1542+ }
1543+
4f0767ce 1544+out:
1facf9fc 1545+ return err;
1546+}
e49829fe
JR
1547--- /dev/null
1548+++ linux-2.6/fs/aufs/branch.h 2010-10-24 11:30:39.000000000 +0200
b752ccd1 1549@@ -0,0 +1,224 @@
1facf9fc 1550+/*
4a4d8108 1551+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1552+ *
1553+ * This program, aufs is free software; you can redistribute it and/or modify
1554+ * it under the terms of the GNU General Public License as published by
1555+ * the Free Software Foundation; either version 2 of the License, or
1556+ * (at your option) any later version.
dece6358
AM
1557+ *
1558+ * This program is distributed in the hope that it will be useful,
1559+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1560+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1561+ * GNU General Public License for more details.
1562+ *
1563+ * You should have received a copy of the GNU General Public License
1564+ * along with this program; if not, write to the Free Software
1565+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1566+ */
1567+
1568+/*
1569+ * branch filesystems and xino for them
1570+ */
1571+
1572+#ifndef __AUFS_BRANCH_H__
1573+#define __AUFS_BRANCH_H__
1574+
1575+#ifdef __KERNEL__
1576+
1577+#include <linux/fs.h>
1578+#include <linux/mount.h>
1facf9fc 1579+#include <linux/aufs_type.h>
4a4d8108 1580+#include "dynop.h"
1facf9fc 1581+#include "rwsem.h"
1582+#include "super.h"
1583+
1584+/* ---------------------------------------------------------------------- */
1585+
1586+/* a xino file */
1587+struct au_xino_file {
1588+ struct file *xi_file;
1589+ struct mutex xi_nondir_mtx;
1590+
1591+ /* todo: make xino files an array to support huge inode number */
1592+
1593+#ifdef CONFIG_DEBUG_FS
1594+ struct dentry *xi_dbgaufs;
1595+#endif
1596+};
1597+
1598+/* members for writable branch only */
1599+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
1600+struct au_wbr {
dece6358 1601+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 1602+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 1603+ atomic_t wbr_wh_running;
1facf9fc 1604+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
1605+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
1606+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
1607+
1608+ /* mfs mode */
1609+ unsigned long long wbr_bytes;
1610+};
1611+
4a4d8108
AM
1612+/* ext2 has 3 types of operations at least, ext3 has 4 */
1613+#define AuBrDynOp (AuDyLast * 4)
1614+
1facf9fc 1615+/* protected by superblock rwsem */
1616+struct au_branch {
1617+ struct au_xino_file br_xino;
1618+
1619+ aufs_bindex_t br_id;
1620+
1621+ int br_perm;
1622+ struct vfsmount *br_mnt;
4a4d8108
AM
1623+ spinlock_t br_dykey_lock;
1624+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 1625+ atomic_t br_count;
1626+
1627+ struct au_wbr *br_wbr;
1628+
1629+ /* xino truncation */
1630+ blkcnt_t br_xino_upper; /* watermark in blocks */
1631+ atomic_t br_xino_running;
1632+
1633+#ifdef CONFIG_SYSFS
1634+ /* an entry under sysfs per mount-point */
1635+ char br_name[8];
1636+ struct attribute br_attr;
1637+#endif
1638+};
1639+
1640+/* ---------------------------------------------------------------------- */
1641+
1642+/* branch permission and attribute */
1643+enum {
1644+ AuBrPerm_RW, /* writable, linkable wh */
1645+ AuBrPerm_RO, /* readonly, no wh */
1646+ AuBrPerm_RR, /* natively readonly, no wh */
1647+
1648+ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
1649+
1650+ AuBrPerm_ROWH, /* whiteout-able */
1651+ AuBrPerm_RRWH, /* whiteout-able */
1652+
1653+ AuBrPerm_Last
1654+};
1655+
1656+static inline int au_br_writable(int brperm)
1657+{
1658+ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1659+}
1660+
1661+static inline int au_br_whable(int brperm)
1662+{
1663+ return brperm == AuBrPerm_RW
1664+ || brperm == AuBrPerm_ROWH
1665+ || brperm == AuBrPerm_RRWH;
1666+}
1667+
1668+static inline int au_br_rdonly(struct au_branch *br)
1669+{
1670+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1671+ || !au_br_writable(br->br_perm))
1672+ ? -EROFS : 0;
1673+}
1674+
4a4d8108 1675+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 1676+{
4a4d8108 1677+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 1678+ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1679+#else
1680+ return 0;
1681+#endif
1682+}
1683+
1684+/* ---------------------------------------------------------------------- */
1685+
1686+/* branch.c */
1687+struct au_sbinfo;
1688+void au_br_free(struct au_sbinfo *sinfo);
1689+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1690+struct au_opt_add;
1691+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1692+struct au_opt_del;
1693+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
1694+struct au_opt_mod;
1695+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1696+ int *do_update);
1697+
1698+/* xino.c */
1699+static const loff_t au_loff_max = LLONG_MAX;
1700+
1701+int au_xib_trunc(struct super_block *sb);
1702+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1703+ loff_t *pos);
1704+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1705+ loff_t *pos);
1706+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
1707+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1708+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 1709+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 1710+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1711+ ino_t ino);
1712+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1713+ ino_t *ino);
1714+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1715+ struct file *base_file, int do_test);
1716+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1717+
1718+struct au_opt_xino;
1719+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1720+void au_xino_clr(struct super_block *sb);
1721+struct file *au_xino_def(struct super_block *sb);
1722+int au_xino_path(struct seq_file *seq, struct file *file);
1723+
1724+/* ---------------------------------------------------------------------- */
1725+
1726+/* Superblock to branch */
1727+static inline
1728+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1729+{
1730+ return au_sbr(sb, bindex)->br_id;
1731+}
1732+
1733+static inline
1734+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1735+{
1736+ return au_sbr(sb, bindex)->br_mnt;
1737+}
1738+
1739+static inline
1740+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1741+{
1742+ return au_sbr_mnt(sb, bindex)->mnt_sb;
1743+}
1744+
1745+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1746+{
e49829fe 1747+ atomic_dec(&au_sbr(sb, bindex)->br_count);
1facf9fc 1748+}
1749+
1750+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1751+{
1752+ return au_sbr(sb, bindex)->br_perm;
1753+}
1754+
1755+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1756+{
1757+ return au_br_whable(au_sbr_perm(sb, bindex));
1758+}
1759+
1760+/* ---------------------------------------------------------------------- */
1761+
1762+/*
1763+ * wbr_wh_read_lock, wbr_wh_write_lock
1764+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
1765+ */
1766+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
1767+
dece6358
AM
1768+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
1769+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
1770+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
1771+
1facf9fc 1772+#endif /* __KERNEL__ */
1773+#endif /* __AUFS_BRANCH_H__ */
e49829fe
JR
1774--- /dev/null
1775+++ linux-2.6/fs/aufs/conf.mk 2010-10-24 11:31:04.000000000 +0200
1776@@ -0,0 +1,37 @@
4a4d8108
AM
1777+
1778+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
1779+
1780+define AuConf
1781+ifdef ${1}
1782+AuConfStr += ${1}=${${1}}
1783+endif
1784+endef
1785+
b752ccd1 1786+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe
JR
1787+ SBILIST \
1788+ HNOTIFY HFSNOTIFY HINOTIFY \
4a4d8108
AM
1789+ EXPORT INO_T_64 \
1790+ RDU \
1791+ SP_IATTR \
1792+ SHWH \
1793+ BR_RAMFS \
1794+ BR_FUSE POLL \
1795+ BR_HFSPLUS \
1796+ BDEV_LOOP \
b752ccd1
AM
1797+ DEBUG MAGIC_SYSRQ
1798+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
1799+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
1800+
1801+AuConfName = ${obj}/conf.str
1802+${AuConfName}.tmp: FORCE
1803+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
1804+${AuConfName}: ${AuConfName}.tmp
1805+ @diff -q $< $@ > /dev/null 2>&1 || { \
1806+ echo ' GEN ' $@; \
1807+ cp -p $< $@; \
1808+ }
1809+FORCE:
1810+clean-files += ${AuConfName} ${AuConfName}.tmp
1811+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
1812+
1813+-include ${srctree}/${src}/conf_priv.mk
e49829fe
JR
1814--- /dev/null
1815+++ linux-2.6/fs/aufs/cpup.c 2010-10-24 11:19:23.000000000 +0200
b752ccd1 1816@@ -0,0 +1,1059 @@
1facf9fc 1817+/*
4a4d8108 1818+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1819+ *
1820+ * This program, aufs is free software; you can redistribute it and/or modify
1821+ * it under the terms of the GNU General Public License as published by
1822+ * the Free Software Foundation; either version 2 of the License, or
1823+ * (at your option) any later version.
dece6358
AM
1824+ *
1825+ * This program is distributed in the hope that it will be useful,
1826+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1827+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1828+ * GNU General Public License for more details.
1829+ *
1830+ * You should have received a copy of the GNU General Public License
1831+ * along with this program; if not, write to the Free Software
1832+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1833+ */
1834+
1835+/*
1836+ * copy-up functions, see wbr_policy.c for copy-down
1837+ */
1838+
dece6358 1839+#include <linux/file.h>
1facf9fc 1840+#include <linux/fs_stack.h>
dece6358 1841+#include <linux/mm.h>
1facf9fc 1842+#include <linux/uaccess.h>
1843+#include "aufs.h"
1844+
1845+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
1846+{
1847+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
1848+ | S_NOATIME | S_NOCMTIME;
1849+
1850+ dst->i_flags |= src->i_flags & ~mask;
1851+ if (au_test_fs_notime(dst->i_sb))
1852+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
1853+}
1854+
1855+void au_cpup_attr_timesizes(struct inode *inode)
1856+{
1857+ struct inode *h_inode;
1858+
1859+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1860+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 1861+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 1862+}
1863+
1864+void au_cpup_attr_nlink(struct inode *inode, int force)
1865+{
1866+ struct inode *h_inode;
1867+ struct super_block *sb;
1868+ aufs_bindex_t bindex, bend;
1869+
1870+ sb = inode->i_sb;
1871+ bindex = au_ibstart(inode);
1872+ h_inode = au_h_iptr(inode, bindex);
1873+ if (!force
1874+ && !S_ISDIR(h_inode->i_mode)
1875+ && au_opt_test(au_mntflags(sb), PLINK)
1876+ && au_plink_test(inode))
1877+ return;
1878+
1879+ inode->i_nlink = h_inode->i_nlink;
1880+
1881+ /*
1882+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
1883+ * it may includes whplink directory.
1884+ */
1885+ if (S_ISDIR(h_inode->i_mode)) {
1886+ bend = au_ibend(inode);
1887+ for (bindex++; bindex <= bend; bindex++) {
1888+ h_inode = au_h_iptr(inode, bindex);
1889+ if (h_inode)
1890+ au_add_nlink(inode, h_inode);
1891+ }
1892+ }
1893+}
1894+
1895+void au_cpup_attr_changeable(struct inode *inode)
1896+{
1897+ struct inode *h_inode;
1898+
1899+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1900+ inode->i_mode = h_inode->i_mode;
1901+ inode->i_uid = h_inode->i_uid;
1902+ inode->i_gid = h_inode->i_gid;
1903+ au_cpup_attr_timesizes(inode);
1904+ au_cpup_attr_flags(inode, h_inode);
1905+}
1906+
1907+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
1908+{
1909+ struct au_iinfo *iinfo = au_ii(inode);
1910+
1308ab2a 1911+ IiMustWriteLock(inode);
1912+
1facf9fc 1913+ iinfo->ii_higen = h_inode->i_generation;
1914+ iinfo->ii_hsb1 = h_inode->i_sb;
1915+}
1916+
1917+void au_cpup_attr_all(struct inode *inode, int force)
1918+{
1919+ struct inode *h_inode;
1920+
1921+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1922+ au_cpup_attr_changeable(inode);
1923+ if (inode->i_nlink > 0)
1924+ au_cpup_attr_nlink(inode, force);
1925+ inode->i_rdev = h_inode->i_rdev;
1926+ inode->i_blkbits = h_inode->i_blkbits;
1927+ au_cpup_igen(inode, h_inode);
1928+}
1929+
1930+/* ---------------------------------------------------------------------- */
1931+
1932+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
1933+
1934+/* keep the timestamps of the parent dir when cpup */
1935+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
1936+ struct path *h_path)
1937+{
1938+ struct inode *h_inode;
1939+
1940+ dt->dt_dentry = dentry;
1941+ dt->dt_h_path = *h_path;
1942+ h_inode = h_path->dentry->d_inode;
1943+ dt->dt_atime = h_inode->i_atime;
1944+ dt->dt_mtime = h_inode->i_mtime;
1945+ /* smp_mb(); */
1946+}
1947+
1948+void au_dtime_revert(struct au_dtime *dt)
1949+{
1950+ struct iattr attr;
1951+ int err;
1952+
1953+ attr.ia_atime = dt->dt_atime;
1954+ attr.ia_mtime = dt->dt_mtime;
1955+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
1956+ | ATTR_ATIME | ATTR_ATIME_SET;
1957+
1958+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
1959+ if (unlikely(err))
4a4d8108 1960+ pr_warning("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 1961+}
1962+
1963+/* ---------------------------------------------------------------------- */
1964+
1965+static noinline_for_stack
1966+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
1967+{
1968+ int err, sbits;
1969+ struct iattr ia;
1970+ struct path h_path;
1308ab2a 1971+ struct inode *h_isrc, *h_idst;
1facf9fc 1972+
1973+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 1974+ h_idst = h_path.dentry->d_inode;
1facf9fc 1975+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
1976+ h_isrc = h_src->d_inode;
1308ab2a 1977+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 1978+ | ATTR_ATIME | ATTR_MTIME
1979+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 1980+ ia.ia_uid = h_isrc->i_uid;
1981+ ia.ia_gid = h_isrc->i_gid;
1982+ ia.ia_atime = h_isrc->i_atime;
1983+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 1984+ if (h_idst->i_mode != h_isrc->i_mode
1985+ && !S_ISLNK(h_idst->i_mode)) {
1986+ ia.ia_valid |= ATTR_MODE;
1987+ ia.ia_mode = h_isrc->i_mode;
1988+ }
1989+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
1990+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 1991+ err = vfsub_notify_change(&h_path, &ia);
1992+
1993+ /* is this nfs only? */
1994+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
1995+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
1996+ ia.ia_mode = h_isrc->i_mode;
1997+ err = vfsub_notify_change(&h_path, &ia);
1998+ }
1999+
2000+ return err;
2001+}
2002+
2003+/* ---------------------------------------------------------------------- */
2004+
2005+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
2006+ char *buf, unsigned long blksize)
2007+{
2008+ int err;
2009+ size_t sz, rbytes, wbytes;
2010+ unsigned char all_zero;
2011+ char *p, *zp;
2012+ struct mutex *h_mtx;
2013+ /* reduce stack usage */
2014+ struct iattr *ia;
2015+
2016+ zp = page_address(ZERO_PAGE(0));
2017+ if (unlikely(!zp))
2018+ return -ENOMEM; /* possible? */
2019+
2020+ err = 0;
2021+ all_zero = 0;
2022+ while (len) {
2023+ AuDbg("len %lld\n", len);
2024+ sz = blksize;
2025+ if (len < blksize)
2026+ sz = len;
2027+
2028+ rbytes = 0;
2029+ /* todo: signal_pending? */
2030+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
2031+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
2032+ err = rbytes;
2033+ }
2034+ if (unlikely(err < 0))
2035+ break;
2036+
2037+ all_zero = 0;
2038+ if (len >= rbytes && rbytes == blksize)
2039+ all_zero = !memcmp(buf, zp, rbytes);
2040+ if (!all_zero) {
2041+ wbytes = rbytes;
2042+ p = buf;
2043+ while (wbytes) {
2044+ size_t b;
2045+
2046+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
2047+ err = b;
2048+ /* todo: signal_pending? */
2049+ if (unlikely(err == -EAGAIN || err == -EINTR))
2050+ continue;
2051+ if (unlikely(err < 0))
2052+ break;
2053+ wbytes -= b;
2054+ p += b;
2055+ }
2056+ } else {
2057+ loff_t res;
2058+
2059+ AuLabel(hole);
2060+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
2061+ err = res;
2062+ if (unlikely(res < 0))
2063+ break;
2064+ }
2065+ len -= rbytes;
2066+ err = 0;
2067+ }
2068+
2069+ /* the last block may be a hole */
2070+ if (!err && all_zero) {
2071+ AuLabel(last hole);
2072+
2073+ err = 1;
2074+ if (au_test_nfs(dst->f_dentry->d_sb)) {
2075+ /* nfs requires this step to make last hole */
2076+ /* is this only nfs? */
2077+ do {
2078+ /* todo: signal_pending? */
2079+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
2080+ } while (err == -EAGAIN || err == -EINTR);
2081+ if (err == 1)
2082+ dst->f_pos--;
2083+ }
2084+
2085+ if (err == 1) {
2086+ ia = (void *)buf;
2087+ ia->ia_size = dst->f_pos;
2088+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
2089+ ia->ia_file = dst;
2090+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
2091+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
2092+ err = vfsub_notify_change(&dst->f_path, ia);
2093+ mutex_unlock(h_mtx);
2094+ }
2095+ }
2096+
2097+ return err;
2098+}
2099+
2100+int au_copy_file(struct file *dst, struct file *src, loff_t len)
2101+{
2102+ int err;
2103+ unsigned long blksize;
2104+ unsigned char do_kfree;
2105+ char *buf;
2106+
2107+ err = -ENOMEM;
2108+ blksize = dst->f_dentry->d_sb->s_blocksize;
2109+ if (!blksize || PAGE_SIZE < blksize)
2110+ blksize = PAGE_SIZE;
2111+ AuDbg("blksize %lu\n", blksize);
2112+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
2113+ if (do_kfree)
2114+ buf = kmalloc(blksize, GFP_NOFS);
2115+ else
2116+ buf = (void *)__get_free_page(GFP_NOFS);
2117+ if (unlikely(!buf))
2118+ goto out;
2119+
2120+ if (len > (1 << 22))
2121+ AuDbg("copying a large file %lld\n", (long long)len);
2122+
2123+ src->f_pos = 0;
2124+ dst->f_pos = 0;
2125+ err = au_do_copy_file(dst, src, len, buf, blksize);
2126+ if (do_kfree)
2127+ kfree(buf);
2128+ else
2129+ free_page((unsigned long)buf);
2130+
4f0767ce 2131+out:
1facf9fc 2132+ return err;
2133+}
2134+
2135+/*
2136+ * to support a sparse file which is opened with O_APPEND,
2137+ * we need to close the file.
2138+ */
2139+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 2140+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 2141+{
2142+ int err, i;
2143+ enum { SRC, DST };
2144+ struct {
2145+ aufs_bindex_t bindex;
2146+ unsigned int flags;
2147+ struct dentry *dentry;
2148+ struct file *file;
2149+ void *label, *label_file;
2150+ } *f, file[] = {
2151+ {
2152+ .bindex = bsrc,
2153+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
2154+ .file = NULL,
2155+ .label = &&out,
2156+ .label_file = &&out_src
2157+ },
2158+ {
2159+ .bindex = bdst,
2160+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
2161+ .file = NULL,
2162+ .label = &&out_src,
2163+ .label_file = &&out_dst
2164+ }
2165+ };
2166+ struct super_block *sb;
2167+
2168+ /* bsrc branch can be ro/rw. */
2169+ sb = dentry->d_sb;
2170+ f = file;
2171+ for (i = 0; i < 2; i++, f++) {
2172+ f->dentry = au_h_dptr(dentry, f->bindex);
2173+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
2174+ err = PTR_ERR(f->file);
2175+ if (IS_ERR(f->file))
2176+ goto *f->label;
2177+ err = -EINVAL;
2178+ if (unlikely(!f->file->f_op))
2179+ goto *f->label_file;
2180+ }
2181+
2182+ /* try stopping to update while we copyup */
2183+ IMustLock(file[SRC].dentry->d_inode);
2184+ err = au_copy_file(file[DST].file, file[SRC].file, len);
2185+
4f0767ce 2186+out_dst:
1facf9fc 2187+ fput(file[DST].file);
2188+ au_sbr_put(sb, file[DST].bindex);
4f0767ce 2189+out_src:
1facf9fc 2190+ fput(file[SRC].file);
2191+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 2192+out:
1facf9fc 2193+ return err;
2194+}
2195+
2196+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
2197+ aufs_bindex_t bsrc, loff_t len,
2198+ struct inode *h_dir, struct path *h_path)
2199+{
2200+ int err, rerr;
2201+ loff_t l;
2202+
2203+ err = 0;
2204+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
2205+ if (len == -1 || l < len)
2206+ len = l;
2207+ if (len)
2208+ err = au_cp_regular(dentry, bdst, bsrc, len);
2209+ if (!err)
2210+ goto out; /* success */
2211+
2212+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
2213+ if (rerr) {
2214+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
2215+ AuDLNPair(h_path->dentry), err, rerr);
2216+ err = -EIO;
2217+ }
2218+
4f0767ce 2219+out:
1facf9fc 2220+ return err;
2221+}
2222+
2223+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
2224+ struct inode *h_dir)
2225+{
2226+ int err, symlen;
2227+ mm_segment_t old_fs;
b752ccd1
AM
2228+ union {
2229+ char *k;
2230+ char __user *u;
2231+ } sym;
1facf9fc 2232+
2233+ err = -ENOSYS;
2234+ if (unlikely(!h_src->d_inode->i_op->readlink))
2235+ goto out;
2236+
2237+ err = -ENOMEM;
b752ccd1
AM
2238+ sym.k = __getname_gfp(GFP_NOFS);
2239+ if (unlikely(!sym.k))
1facf9fc 2240+ goto out;
2241+
2242+ old_fs = get_fs();
2243+ set_fs(KERNEL_DS);
b752ccd1 2244+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 2245+ err = symlen;
2246+ set_fs(old_fs);
2247+
2248+ if (symlen > 0) {
b752ccd1
AM
2249+ sym.k[symlen] = 0;
2250+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 2251+ }
b752ccd1 2252+ __putname(sym.k);
1facf9fc 2253+
4f0767ce 2254+out:
1facf9fc 2255+ return err;
2256+}
2257+
2258+/* return with the lower dst inode is locked */
2259+static noinline_for_stack
2260+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
2261+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2262+ struct dentry *dst_parent)
2263+{
2264+ int err;
2265+ umode_t mode;
2266+ unsigned int mnt_flags;
2267+ unsigned char isdir;
2268+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
2269+ struct au_dtime dt;
2270+ struct path h_path;
2271+ struct dentry *h_src, *h_dst, *h_parent;
2272+ struct inode *h_inode, *h_dir;
2273+ struct super_block *sb;
2274+
2275+ /* bsrc branch can be ro/rw. */
2276+ h_src = au_h_dptr(dentry, bsrc);
2277+ h_inode = h_src->d_inode;
2278+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
2279+
2280+ /* try stopping to be referenced while we are creating */
2281+ h_dst = au_h_dptr(dentry, bdst);
2282+ h_parent = h_dst->d_parent; /* dir inode is locked */
2283+ h_dir = h_parent->d_inode;
2284+ IMustLock(h_dir);
2285+ AuDebugOn(h_parent != h_dst->d_parent);
2286+
2287+ sb = dentry->d_sb;
2288+ h_path.mnt = au_sbr_mnt(sb, bdst);
2289+ if (do_dt) {
2290+ h_path.dentry = h_parent;
2291+ au_dtime_store(&dt, dst_parent, &h_path);
2292+ }
2293+ h_path.dentry = h_dst;
2294+
2295+ isdir = 0;
2296+ mode = h_inode->i_mode;
2297+ switch (mode & S_IFMT) {
2298+ case S_IFREG:
2299+ /* try stopping to update while we are referencing */
2300+ IMustLock(h_inode);
2301+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
2302+ if (!err)
2303+ err = au_do_cpup_regular
2304+ (dentry, bdst, bsrc, len,
2305+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
2306+ break;
2307+ case S_IFDIR:
2308+ isdir = 1;
2309+ err = vfsub_mkdir(h_dir, &h_path, mode);
2310+ if (!err) {
2311+ /*
2312+ * strange behaviour from the users view,
2313+ * particularry setattr case
2314+ */
2315+ if (au_ibstart(dst_parent->d_inode) == bdst)
2316+ au_cpup_attr_nlink(dst_parent->d_inode,
2317+ /*force*/1);
2318+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
2319+ }
2320+ break;
2321+ case S_IFLNK:
2322+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
2323+ break;
2324+ case S_IFCHR:
2325+ case S_IFBLK:
2326+ AuDebugOn(!capable(CAP_MKNOD));
2327+ /*FALLTHROUGH*/
2328+ case S_IFIFO:
2329+ case S_IFSOCK:
2330+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
2331+ break;
2332+ default:
2333+ AuIOErr("Unknown inode type 0%o\n", mode);
2334+ err = -EIO;
2335+ }
2336+
2337+ mnt_flags = au_mntflags(sb);
2338+ if (!au_opt_test(mnt_flags, UDBA_NONE)
2339+ && !isdir
2340+ && au_opt_test(mnt_flags, XINO)
2341+ && h_inode->i_nlink == 1
2342+ /* todo: unnecessary? */
2343+ /* && dentry->d_inode->i_nlink == 1 */
2344+ && bdst < bsrc
2345+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 2346+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 2347+ /* ignore this error */
2348+
2349+ if (do_dt)
2350+ au_dtime_revert(&dt);
2351+ return err;
2352+}
2353+
2354+/*
2355+ * copyup the @dentry from @bsrc to @bdst.
2356+ * the caller must set the both of lower dentries.
2357+ * @len is for truncating when it is -1 copyup the entire file.
2358+ * in link/rename cases, @dst_parent may be different from the real one.
2359+ */
2360+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2361+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2362+ struct dentry *dst_parent)
2363+{
2364+ int err, rerr;
2365+ aufs_bindex_t old_ibstart;
2366+ unsigned char isdir, plink;
2367+ struct au_dtime dt;
2368+ struct path h_path;
2369+ struct dentry *h_src, *h_dst, *h_parent;
2370+ struct inode *dst_inode, *h_dir, *inode;
2371+ struct super_block *sb;
2372+
2373+ AuDebugOn(bsrc <= bdst);
2374+
2375+ sb = dentry->d_sb;
2376+ h_path.mnt = au_sbr_mnt(sb, bdst);
2377+ h_dst = au_h_dptr(dentry, bdst);
2378+ h_parent = h_dst->d_parent; /* dir inode is locked */
2379+ h_dir = h_parent->d_inode;
2380+ IMustLock(h_dir);
2381+
2382+ h_src = au_h_dptr(dentry, bsrc);
2383+ inode = dentry->d_inode;
2384+
2385+ if (!dst_parent)
2386+ dst_parent = dget_parent(dentry);
2387+ else
2388+ dget(dst_parent);
2389+
2390+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
2391+ dst_inode = au_h_iptr(inode, bdst);
2392+ if (dst_inode) {
2393+ if (unlikely(!plink)) {
2394+ err = -EIO;
2395+ AuIOErr("i%lu exists on a upper branch "
2396+ "but plink is disabled\n", inode->i_ino);
2397+ goto out;
2398+ }
2399+
2400+ if (dst_inode->i_nlink) {
2401+ const int do_dt = au_ftest_cpup(flags, DTIME);
2402+
2403+ h_src = au_plink_lkup(inode, bdst);
2404+ err = PTR_ERR(h_src);
2405+ if (IS_ERR(h_src))
2406+ goto out;
2407+ if (unlikely(!h_src->d_inode)) {
2408+ err = -EIO;
2409+ AuIOErr("i%lu exists on a upper branch "
2410+ "but plink is broken\n", inode->i_ino);
2411+ dput(h_src);
2412+ goto out;
2413+ }
2414+
2415+ if (do_dt) {
2416+ h_path.dentry = h_parent;
2417+ au_dtime_store(&dt, dst_parent, &h_path);
2418+ }
2419+ h_path.dentry = h_dst;
2420+ err = vfsub_link(h_src, h_dir, &h_path);
2421+ if (do_dt)
2422+ au_dtime_revert(&dt);
2423+ dput(h_src);
2424+ goto out;
2425+ } else
2426+ /* todo: cpup_wh_file? */
2427+ /* udba work */
4a4d8108 2428+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 2429+ }
2430+
2431+ old_ibstart = au_ibstart(inode);
2432+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
2433+ if (unlikely(err))
2434+ goto out;
2435+ dst_inode = h_dst->d_inode;
2436+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
2437+
2438+ err = cpup_iattr(dentry, bdst, h_src);
2439+ isdir = S_ISDIR(dst_inode->i_mode);
2440+ if (!err) {
4a4d8108
AM
2441+ if (bdst < old_ibstart) {
2442+ if (S_ISREG(inode->i_mode)) {
2443+ err = au_dy_iaop(inode, bdst, dst_inode);
2444+ if (unlikely(err))
2445+ goto out_rev;
2446+ }
1facf9fc 2447+ au_set_ibstart(inode, bdst);
4a4d8108 2448+ }
1facf9fc 2449+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
2450+ au_hi_flags(inode, isdir));
2451+ mutex_unlock(&dst_inode->i_mutex);
2452+ if (!isdir
2453+ && h_src->d_inode->i_nlink > 1
2454+ && plink)
2455+ au_plink_append(inode, bdst, h_dst);
2456+ goto out; /* success */
2457+ }
2458+
2459+ /* revert */
4a4d8108 2460+out_rev:
1facf9fc 2461+ h_path.dentry = h_parent;
2462+ mutex_unlock(&dst_inode->i_mutex);
2463+ au_dtime_store(&dt, dst_parent, &h_path);
2464+ h_path.dentry = h_dst;
2465+ if (!isdir)
2466+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
2467+ else
2468+ rerr = vfsub_rmdir(h_dir, &h_path);
2469+ au_dtime_revert(&dt);
2470+ if (rerr) {
2471+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
2472+ err = -EIO;
2473+ }
2474+
4f0767ce 2475+out:
1facf9fc 2476+ dput(dst_parent);
2477+ return err;
2478+}
2479+
2480+struct au_cpup_single_args {
2481+ int *errp;
2482+ struct dentry *dentry;
2483+ aufs_bindex_t bdst, bsrc;
2484+ loff_t len;
2485+ unsigned int flags;
2486+ struct dentry *dst_parent;
2487+};
2488+
2489+static void au_call_cpup_single(void *args)
2490+{
2491+ struct au_cpup_single_args *a = args;
2492+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
2493+ a->flags, a->dst_parent);
2494+}
2495+
2496+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2497+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2498+ struct dentry *dst_parent)
2499+{
2500+ int err, wkq_err;
2501+ umode_t mode;
2502+ struct dentry *h_dentry;
2503+
2504+ h_dentry = au_h_dptr(dentry, bsrc);
2505+ mode = h_dentry->d_inode->i_mode & S_IFMT;
2506+ if ((mode != S_IFCHR && mode != S_IFBLK)
2507+ || capable(CAP_MKNOD))
2508+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2509+ dst_parent);
2510+ else {
2511+ struct au_cpup_single_args args = {
2512+ .errp = &err,
2513+ .dentry = dentry,
2514+ .bdst = bdst,
2515+ .bsrc = bsrc,
2516+ .len = len,
2517+ .flags = flags,
2518+ .dst_parent = dst_parent
2519+ };
2520+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
2521+ if (unlikely(wkq_err))
2522+ err = wkq_err;
2523+ }
2524+
2525+ return err;
2526+}
2527+
2528+/*
2529+ * copyup the @dentry from the first active lower branch to @bdst,
2530+ * using au_cpup_single().
2531+ */
2532+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2533+ unsigned int flags)
2534+{
2535+ int err;
2536+ aufs_bindex_t bsrc, bend;
2537+
2538+ bend = au_dbend(dentry);
2539+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2540+ if (au_h_dptr(dentry, bsrc))
2541+ break;
2542+
2543+ err = au_lkup_neg(dentry, bdst);
2544+ if (!err) {
2545+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
2546+ if (!err)
2547+ return 0; /* success */
2548+
2549+ /* revert */
2550+ au_set_h_dptr(dentry, bdst, NULL);
2551+ au_set_dbstart(dentry, bsrc);
2552+ }
2553+
2554+ return err;
2555+}
2556+
2557+struct au_cpup_simple_args {
2558+ int *errp;
2559+ struct dentry *dentry;
2560+ aufs_bindex_t bdst;
2561+ loff_t len;
2562+ unsigned int flags;
2563+};
2564+
2565+static void au_call_cpup_simple(void *args)
2566+{
2567+ struct au_cpup_simple_args *a = args;
2568+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
2569+}
2570+
2571+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2572+ unsigned int flags)
2573+{
2574+ int err, wkq_err;
2575+ unsigned char do_sio;
2576+ struct dentry *parent;
2577+ struct inode *h_dir;
2578+
2579+ parent = dget_parent(dentry);
2580+ h_dir = au_h_iptr(parent->d_inode, bdst);
2581+ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
2582+ if (!do_sio) {
2583+ /*
2584+ * testing CAP_MKNOD is for generic fs,
2585+ * but CAP_FSETID is for xfs only, currently.
2586+ */
2587+ umode_t mode = dentry->d_inode->i_mode;
2588+ do_sio = (((mode & (S_IFCHR | S_IFBLK))
2589+ && !capable(CAP_MKNOD))
2590+ || ((mode & (S_ISUID | S_ISGID))
2591+ && !capable(CAP_FSETID)));
2592+ }
2593+ if (!do_sio)
2594+ err = au_cpup_simple(dentry, bdst, len, flags);
2595+ else {
2596+ struct au_cpup_simple_args args = {
2597+ .errp = &err,
2598+ .dentry = dentry,
2599+ .bdst = bdst,
2600+ .len = len,
2601+ .flags = flags
2602+ };
2603+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
2604+ if (unlikely(wkq_err))
2605+ err = wkq_err;
2606+ }
2607+
2608+ dput(parent);
2609+ return err;
2610+}
2611+
2612+/* ---------------------------------------------------------------------- */
2613+
2614+/*
2615+ * copyup the deleted file for writing.
2616+ */
2617+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2618+ struct dentry *wh_dentry, struct file *file,
2619+ loff_t len)
2620+{
2621+ int err;
2622+ aufs_bindex_t bstart;
2623+ struct au_dinfo *dinfo;
2624+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 2625+ struct au_hdentry *hdp;
1facf9fc 2626+
2627+ dinfo = au_di(dentry);
1308ab2a 2628+ AuRwMustWriteLock(&dinfo->di_rwsem);
2629+
1facf9fc 2630+ bstart = dinfo->di_bstart;
4a4d8108
AM
2631+ hdp = dinfo->di_hdentry;
2632+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 2633+ dinfo->di_bstart = bdst;
4a4d8108
AM
2634+ hdp[0 + bdst].hd_dentry = wh_dentry;
2635+ h_d_start = hdp[0 + bstart].hd_dentry;
1facf9fc 2636+ if (file)
4a4d8108 2637+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2638+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2639+ /*h_parent*/NULL);
2640+ if (!err && file) {
2641+ err = au_reopen_nondir(file);
4a4d8108 2642+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 2643+ }
4a4d8108 2644+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 2645+ dinfo->di_bstart = bstart;
2646+
2647+ return err;
2648+}
2649+
2650+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2651+ struct file *file)
2652+{
2653+ int err;
2654+ struct au_dtime dt;
2655+ struct dentry *parent, *h_parent, *wh_dentry;
2656+ struct au_branch *br;
2657+ struct path h_path;
2658+
2659+ br = au_sbr(dentry->d_sb, bdst);
2660+ parent = dget_parent(dentry);
2661+ h_parent = au_h_dptr(parent, bdst);
2662+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
2663+ err = PTR_ERR(wh_dentry);
2664+ if (IS_ERR(wh_dentry))
2665+ goto out;
2666+
2667+ h_path.dentry = h_parent;
2668+ h_path.mnt = br->br_mnt;
2669+ au_dtime_store(&dt, parent, &h_path);
2670+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
2671+ if (unlikely(err))
2672+ goto out_wh;
2673+
2674+ dget(wh_dentry);
2675+ h_path.dentry = wh_dentry;
4a4d8108
AM
2676+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
2677+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
2678+ else
2679+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 2680+ if (unlikely(err)) {
2681+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2682+ AuDLNPair(wh_dentry), err);
2683+ err = -EIO;
2684+ }
2685+ au_dtime_revert(&dt);
2686+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2687+
4f0767ce 2688+out_wh:
1facf9fc 2689+ dput(wh_dentry);
4f0767ce 2690+out:
1facf9fc 2691+ dput(parent);
2692+ return err;
2693+}
2694+
2695+struct au_cpup_wh_args {
2696+ int *errp;
2697+ struct dentry *dentry;
2698+ aufs_bindex_t bdst;
2699+ loff_t len;
2700+ struct file *file;
2701+};
2702+
2703+static void au_call_cpup_wh(void *args)
2704+{
2705+ struct au_cpup_wh_args *a = args;
2706+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
2707+}
2708+
2709+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2710+ struct file *file)
2711+{
2712+ int err, wkq_err;
2713+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
2714+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
2715+ struct au_wbr *wbr;
2716+
2717+ parent = dget_parent(dentry);
2718+ dir = parent->d_inode;
2719+ h_orph = NULL;
2720+ h_parent = NULL;
2721+ h_dir = au_igrab(au_h_iptr(dir, bdst));
2722+ h_tmpdir = h_dir;
2723+ if (!h_dir->i_nlink) {
2724+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
2725+ h_orph = wbr->wbr_orph;
2726+
2727+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 2728+ au_set_h_dptr(parent, bdst, dget(h_orph));
2729+ h_tmpdir = h_orph->d_inode;
1facf9fc 2730+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
2731+
2732+ /* this temporary unlock is safe */
2733+ if (file)
4a4d8108 2734+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2735+ else
2736+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
2737+ h_inode = h_dentry->d_inode;
2738+ IMustLock(h_inode);
2739+ mutex_unlock(&h_inode->i_mutex);
dece6358 2740+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 2741+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 2742+ /* todo: au_h_open_pre()? */
1facf9fc 2743+ }
2744+
2745+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
2746+ err = au_cpup_wh(dentry, bdst, len, file);
2747+ else {
2748+ struct au_cpup_wh_args args = {
2749+ .errp = &err,
2750+ .dentry = dentry,
2751+ .bdst = bdst,
2752+ .len = len,
2753+ .file = file
2754+ };
2755+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
2756+ if (unlikely(wkq_err))
2757+ err = wkq_err;
2758+ }
2759+
2760+ if (h_orph) {
2761+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 2762+ /* todo: au_h_open_post()? */
1facf9fc 2763+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 2764+ au_set_h_dptr(parent, bdst, h_parent);
2765+ }
2766+ iput(h_dir);
2767+ dput(parent);
2768+
2769+ return err;
2770+}
2771+
2772+/* ---------------------------------------------------------------------- */
2773+
2774+/*
2775+ * generic routine for both of copy-up and copy-down.
2776+ */
2777+/* cf. revalidate function in file.c */
2778+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2779+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2780+ struct dentry *h_parent, void *arg),
2781+ void *arg)
2782+{
2783+ int err;
2784+ struct au_pin pin;
2785+ struct dentry *d, *parent, *h_parent, *real_parent;
2786+
2787+ err = 0;
2788+ parent = dget_parent(dentry);
2789+ if (IS_ROOT(parent))
2790+ goto out;
2791+
2792+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
2793+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
2794+
2795+ /* do not use au_dpage */
2796+ real_parent = parent;
2797+ while (1) {
2798+ dput(parent);
2799+ parent = dget_parent(dentry);
2800+ h_parent = au_h_dptr(parent, bdst);
2801+ if (h_parent)
2802+ goto out; /* success */
2803+
2804+ /* find top dir which is necessary to cpup */
2805+ do {
2806+ d = parent;
2807+ dput(parent);
2808+ parent = dget_parent(d);
2809+ di_read_lock_parent3(parent, !AuLock_IR);
2810+ h_parent = au_h_dptr(parent, bdst);
2811+ di_read_unlock(parent, !AuLock_IR);
2812+ } while (!h_parent);
2813+
2814+ if (d != real_parent)
2815+ di_write_lock_child3(d);
2816+
2817+ /* somebody else might create while we were sleeping */
2818+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
2819+ if (au_h_dptr(d, bdst))
2820+ au_update_dbstart(d);
2821+
2822+ au_pin_set_dentry(&pin, d);
2823+ err = au_do_pin(&pin);
2824+ if (!err) {
2825+ err = cp(d, bdst, h_parent, arg);
2826+ au_unpin(&pin);
2827+ }
2828+ }
2829+
2830+ if (d != real_parent)
2831+ di_write_unlock(d);
2832+ if (unlikely(err))
2833+ break;
2834+ }
2835+
4f0767ce 2836+out:
1facf9fc 2837+ dput(parent);
2838+ return err;
2839+}
2840+
2841+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
2842+ struct dentry *h_parent __maybe_unused ,
2843+ void *arg __maybe_unused)
2844+{
2845+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
2846+}
2847+
2848+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2849+{
2850+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
2851+}
2852+
2853+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2854+{
2855+ int err;
2856+ struct dentry *parent;
2857+ struct inode *dir;
2858+
2859+ parent = dget_parent(dentry);
2860+ dir = parent->d_inode;
2861+ err = 0;
2862+ if (au_h_iptr(dir, bdst))
2863+ goto out;
2864+
2865+ di_read_unlock(parent, AuLock_IR);
2866+ di_write_lock_parent(parent);
2867+ /* someone else might change our inode while we were sleeping */
2868+ if (!au_h_iptr(dir, bdst))
2869+ err = au_cpup_dirs(dentry, bdst);
2870+ di_downgrade_lock(parent, AuLock_IR);
2871+
4f0767ce 2872+out:
1facf9fc 2873+ dput(parent);
2874+ return err;
2875+}
e49829fe
JR
2876--- /dev/null
2877+++ linux-2.6/fs/aufs/cpup.h 2010-10-24 11:19:23.000000000 +0200
dece6358 2878@@ -0,0 +1,81 @@
1facf9fc 2879+/*
4a4d8108 2880+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2881+ *
2882+ * This program, aufs is free software; you can redistribute it and/or modify
2883+ * it under the terms of the GNU General Public License as published by
2884+ * the Free Software Foundation; either version 2 of the License, or
2885+ * (at your option) any later version.
dece6358
AM
2886+ *
2887+ * This program is distributed in the hope that it will be useful,
2888+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2889+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2890+ * GNU General Public License for more details.
2891+ *
2892+ * You should have received a copy of the GNU General Public License
2893+ * along with this program; if not, write to the Free Software
2894+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2895+ */
2896+
2897+/*
2898+ * copy-up/down functions
2899+ */
2900+
2901+#ifndef __AUFS_CPUP_H__
2902+#define __AUFS_CPUP_H__
2903+
2904+#ifdef __KERNEL__
2905+
dece6358
AM
2906+#include <linux/path.h>
2907+#include <linux/time.h>
1facf9fc 2908+#include <linux/aufs_type.h>
2909+
dece6358
AM
2910+struct inode;
2911+struct file;
2912+
1facf9fc 2913+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
2914+void au_cpup_attr_timesizes(struct inode *inode);
2915+void au_cpup_attr_nlink(struct inode *inode, int force);
2916+void au_cpup_attr_changeable(struct inode *inode);
2917+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
2918+void au_cpup_attr_all(struct inode *inode, int force);
2919+
2920+/* ---------------------------------------------------------------------- */
2921+
2922+/* cpup flags */
2923+#define AuCpup_DTIME 1 /* do dtime_store/revert */
2924+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
2925+ for link(2) */
2926+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
2927+#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; }
2928+#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; }
2929+
2930+int au_copy_file(struct file *dst, struct file *src, loff_t len);
2931+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2932+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2933+ struct dentry *dst_parent);
2934+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2935+ unsigned int flags);
2936+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2937+ struct file *file);
2938+
2939+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2940+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2941+ struct dentry *h_parent, void *arg),
2942+ void *arg);
2943+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2944+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2945+
2946+/* ---------------------------------------------------------------------- */
2947+
2948+/* keep timestamps when copyup */
2949+struct au_dtime {
2950+ struct dentry *dt_dentry;
2951+ struct path dt_h_path;
2952+ struct timespec dt_atime, dt_mtime;
2953+};
2954+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
2955+ struct path *h_path);
2956+void au_dtime_revert(struct au_dtime *dt);
2957+
2958+#endif /* __KERNEL__ */
2959+#endif /* __AUFS_CPUP_H__ */
e49829fe
JR
2960--- /dev/null
2961+++ linux-2.6/fs/aufs/dbgaufs.c 2010-10-24 11:19:23.000000000 +0200
4a4d8108 2962@@ -0,0 +1,334 @@
1facf9fc 2963+/*
4a4d8108 2964+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2965+ *
2966+ * This program, aufs is free software; you can redistribute it and/or modify
2967+ * it under the terms of the GNU General Public License as published by
2968+ * the Free Software Foundation; either version 2 of the License, or
2969+ * (at your option) any later version.
dece6358
AM
2970+ *
2971+ * This program is distributed in the hope that it will be useful,
2972+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2973+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2974+ * GNU General Public License for more details.
2975+ *
2976+ * You should have received a copy of the GNU General Public License
2977+ * along with this program; if not, write to the Free Software
2978+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2979+ */
2980+
2981+/*
2982+ * debugfs interface
2983+ */
2984+
2985+#include <linux/debugfs.h>
2986+#include "aufs.h"
2987+
2988+#ifndef CONFIG_SYSFS
2989+#error DEBUG_FS depends upon SYSFS
2990+#endif
2991+
2992+static struct dentry *dbgaufs;
2993+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
2994+
2995+/* 20 is max digits length of ulong 64 */
2996+struct dbgaufs_arg {
2997+ int n;
2998+ char a[20 * 4];
2999+};
3000+
3001+/*
3002+ * common function for all XINO files
3003+ */
3004+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
3005+ struct file *file)
3006+{
3007+ kfree(file->private_data);
3008+ return 0;
3009+}
3010+
3011+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
3012+{
3013+ int err;
3014+ struct kstat st;
3015+ struct dbgaufs_arg *p;
3016+
3017+ err = -ENOMEM;
3018+ p = kmalloc(sizeof(*p), GFP_NOFS);
3019+ if (unlikely(!p))
3020+ goto out;
3021+
3022+ err = 0;
3023+ p->n = 0;
3024+ file->private_data = p;
3025+ if (!xf)
3026+ goto out;
3027+
3028+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
3029+ if (!err) {
3030+ if (do_fcnt)
3031+ p->n = snprintf
3032+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
3033+ (long)file_count(xf), st.blocks, st.blksize,
3034+ (long long)st.size);
3035+ else
3036+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
3037+ st.blocks, st.blksize,
3038+ (long long)st.size);
3039+ AuDebugOn(p->n >= sizeof(p->a));
3040+ } else {
3041+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
3042+ err = 0;
3043+ }
3044+
4f0767ce 3045+out:
1facf9fc 3046+ return err;
3047+
3048+}
3049+
3050+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
3051+ size_t count, loff_t *ppos)
3052+{
3053+ struct dbgaufs_arg *p;
3054+
3055+ p = file->private_data;
3056+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
3057+}
3058+
3059+/* ---------------------------------------------------------------------- */
3060+
3061+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
3062+{
3063+ int err;
3064+ struct au_sbinfo *sbinfo;
3065+ struct super_block *sb;
3066+
3067+ sbinfo = inode->i_private;
3068+ sb = sbinfo->si_sb;
3069+ si_noflush_read_lock(sb);
3070+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
3071+ si_read_unlock(sb);
3072+ return err;
3073+}
3074+
3075+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 3076+ .owner = THIS_MODULE,
1facf9fc 3077+ .open = dbgaufs_xib_open,
3078+ .release = dbgaufs_xi_release,
3079+ .read = dbgaufs_xi_read
3080+};
3081+
3082+/* ---------------------------------------------------------------------- */
3083+
3084+#define DbgaufsXi_PREFIX "xi"
3085+
3086+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
3087+{
3088+ int err;
3089+ long l;
3090+ struct au_sbinfo *sbinfo;
3091+ struct super_block *sb;
3092+ struct file *xf;
3093+ struct qstr *name;
3094+
3095+ err = -ENOENT;
3096+ xf = NULL;
3097+ name = &file->f_dentry->d_name;
3098+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
3099+ || memcmp(name->name, DbgaufsXi_PREFIX,
3100+ sizeof(DbgaufsXi_PREFIX) - 1)))
3101+ goto out;
3102+ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
3103+ if (unlikely(err))
3104+ goto out;
3105+
3106+ sbinfo = inode->i_private;
3107+ sb = sbinfo->si_sb;
3108+ si_noflush_read_lock(sb);
3109+ if (l <= au_sbend(sb)) {
3110+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
3111+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
3112+ } else
3113+ err = -ENOENT;
3114+ si_read_unlock(sb);
3115+
4f0767ce 3116+out:
1facf9fc 3117+ return err;
3118+}
3119+
3120+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 3121+ .owner = THIS_MODULE,
1facf9fc 3122+ .open = dbgaufs_xino_open,
3123+ .release = dbgaufs_xi_release,
3124+ .read = dbgaufs_xi_read
3125+};
3126+
3127+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
3128+{
3129+ aufs_bindex_t bend;
3130+ struct au_branch *br;
3131+ struct au_xino_file *xi;
3132+
3133+ if (!au_sbi(sb)->si_dbgaufs)
3134+ return;
3135+
3136+ bend = au_sbend(sb);
3137+ for (; bindex <= bend; bindex++) {
3138+ br = au_sbr(sb, bindex);
3139+ xi = &br->br_xino;
3140+ if (xi->xi_dbgaufs) {
3141+ debugfs_remove(xi->xi_dbgaufs);
3142+ xi->xi_dbgaufs = NULL;
3143+ }
3144+ }
3145+}
3146+
3147+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
3148+{
3149+ struct au_sbinfo *sbinfo;
3150+ struct dentry *parent;
3151+ struct au_branch *br;
3152+ struct au_xino_file *xi;
3153+ aufs_bindex_t bend;
3154+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
3155+
3156+ sbinfo = au_sbi(sb);
3157+ parent = sbinfo->si_dbgaufs;
3158+ if (!parent)
3159+ return;
3160+
3161+ bend = au_sbend(sb);
3162+ for (; bindex <= bend; bindex++) {
3163+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
3164+ br = au_sbr(sb, bindex);
3165+ xi = &br->br_xino;
3166+ AuDebugOn(xi->xi_dbgaufs);
3167+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
3168+ sbinfo, &dbgaufs_xino_fop);
3169+ /* ignore an error */
3170+ if (unlikely(!xi->xi_dbgaufs))
3171+ AuWarn1("failed %s under debugfs\n", name);
3172+ }
3173+}
3174+
3175+/* ---------------------------------------------------------------------- */
3176+
3177+#ifdef CONFIG_AUFS_EXPORT
3178+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
3179+{
3180+ int err;
3181+ struct au_sbinfo *sbinfo;
3182+ struct super_block *sb;
3183+
3184+ sbinfo = inode->i_private;
3185+ sb = sbinfo->si_sb;
3186+ si_noflush_read_lock(sb);
3187+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
3188+ si_read_unlock(sb);
3189+ return err;
3190+}
3191+
3192+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 3193+ .owner = THIS_MODULE,
1facf9fc 3194+ .open = dbgaufs_xigen_open,
3195+ .release = dbgaufs_xi_release,
3196+ .read = dbgaufs_xi_read
3197+};
3198+
3199+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3200+{
3201+ int err;
3202+
dece6358
AM
3203+ /*
3204+ * This function is a dynamic '__init' fucntion actually,
3205+ * so the tiny check for si_rwsem is unnecessary.
3206+ */
3207+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3208+
1facf9fc 3209+ err = -EIO;
3210+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
3211+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3212+ &dbgaufs_xigen_fop);
3213+ if (sbinfo->si_dbgaufs_xigen)
3214+ err = 0;
3215+
3216+ return err;
3217+}
3218+#else
3219+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3220+{
3221+ return 0;
3222+}
3223+#endif /* CONFIG_AUFS_EXPORT */
3224+
3225+/* ---------------------------------------------------------------------- */
3226+
3227+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
3228+{
dece6358
AM
3229+ /*
3230+ * This function is a dynamic '__init' fucntion actually,
3231+ * so the tiny check for si_rwsem is unnecessary.
3232+ */
3233+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3234+
1facf9fc 3235+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
3236+ sbinfo->si_dbgaufs = NULL;
3237+ kobject_put(&sbinfo->si_kobj);
3238+}
3239+
3240+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
3241+{
3242+ int err;
3243+ char name[SysaufsSiNameLen];
3244+
dece6358
AM
3245+ /*
3246+ * This function is a dynamic '__init' fucntion actually,
3247+ * so the tiny check for si_rwsem is unnecessary.
3248+ */
3249+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3250+
1facf9fc 3251+ err = -ENOENT;
3252+ if (!dbgaufs) {
3253+ AuErr1("/debug/aufs is uninitialized\n");
3254+ goto out;
3255+ }
3256+
3257+ err = -EIO;
3258+ sysaufs_name(sbinfo, name);
3259+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
3260+ if (unlikely(!sbinfo->si_dbgaufs))
3261+ goto out;
3262+ kobject_get(&sbinfo->si_kobj);
3263+
3264+ sbinfo->si_dbgaufs_xib = debugfs_create_file
3265+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3266+ &dbgaufs_xib_fop);
3267+ if (unlikely(!sbinfo->si_dbgaufs_xib))
3268+ goto out_dir;
3269+
3270+ err = dbgaufs_xigen_init(sbinfo);
3271+ if (!err)
3272+ goto out; /* success */
3273+
4f0767ce 3274+out_dir:
1facf9fc 3275+ dbgaufs_si_fin(sbinfo);
4f0767ce 3276+out:
1facf9fc 3277+ return err;
3278+}
3279+
3280+/* ---------------------------------------------------------------------- */
3281+
3282+void dbgaufs_fin(void)
3283+{
3284+ debugfs_remove(dbgaufs);
3285+}
3286+
3287+int __init dbgaufs_init(void)
3288+{
3289+ int err;
3290+
3291+ err = -EIO;
3292+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
3293+ if (dbgaufs)
3294+ err = 0;
3295+ return err;
3296+}
e49829fe
JR
3297--- /dev/null
3298+++ linux-2.6/fs/aufs/dbgaufs.h 2010-10-24 11:19:23.000000000 +0200
4a4d8108 3299@@ -0,0 +1,52 @@
1facf9fc 3300+/*
4a4d8108 3301+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3302+ *
3303+ * This program, aufs is free software; you can redistribute it and/or modify
3304+ * it under the terms of the GNU General Public License as published by
3305+ * the Free Software Foundation; either version 2 of the License, or
3306+ * (at your option) any later version.
dece6358
AM
3307+ *
3308+ * This program is distributed in the hope that it will be useful,
3309+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3310+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3311+ * GNU General Public License for more details.
3312+ *
3313+ * You should have received a copy of the GNU General Public License
3314+ * along with this program; if not, write to the Free Software
3315+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3316+ */
3317+
3318+/*
3319+ * debugfs interface
3320+ */
3321+
3322+#ifndef __DBGAUFS_H__
3323+#define __DBGAUFS_H__
3324+
3325+#ifdef __KERNEL__
3326+
dece6358 3327+#include <linux/init.h>
1facf9fc 3328+#include <linux/aufs_type.h>
3329+
dece6358 3330+struct super_block;
1facf9fc 3331+struct au_sbinfo;
dece6358 3332+
1facf9fc 3333+#ifdef CONFIG_DEBUG_FS
3334+/* dbgaufs.c */
3335+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
3336+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
3337+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
3338+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
3339+void dbgaufs_fin(void);
3340+int __init dbgaufs_init(void);
1facf9fc 3341+#else
4a4d8108
AM
3342+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
3343+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
3344+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
3345+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
3346+AuStubVoid(dbgaufs_fin, void)
3347+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 3348+#endif /* CONFIG_DEBUG_FS */
3349+
3350+#endif /* __KERNEL__ */
3351+#endif /* __DBGAUFS_H__ */
e49829fe
JR
3352--- /dev/null
3353+++ linux-2.6/fs/aufs/dcsub.c 2010-10-24 11:19:23.000000000 +0200
4a4d8108 3354@@ -0,0 +1,200 @@
1facf9fc 3355+/*
4a4d8108 3356+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3357+ *
3358+ * This program, aufs is free software; you can redistribute it and/or modify
3359+ * it under the terms of the GNU General Public License as published by
3360+ * the Free Software Foundation; either version 2 of the License, or
3361+ * (at your option) any later version.
dece6358
AM
3362+ *
3363+ * This program is distributed in the hope that it will be useful,
3364+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3365+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3366+ * GNU General Public License for more details.
3367+ *
3368+ * You should have received a copy of the GNU General Public License
3369+ * along with this program; if not, write to the Free Software
3370+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3371+ */
3372+
3373+/*
3374+ * sub-routines for dentry cache
3375+ */
3376+
3377+#include "aufs.h"
3378+
3379+static void au_dpage_free(struct au_dpage *dpage)
3380+{
3381+ int i;
3382+ struct dentry **p;
3383+
3384+ p = dpage->dentries;
3385+ for (i = 0; i < dpage->ndentry; i++)
3386+ dput(*p++);
3387+ free_page((unsigned long)dpage->dentries);
3388+}
3389+
3390+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
3391+{
3392+ int err;
3393+ void *p;
3394+
3395+ err = -ENOMEM;
3396+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
3397+ if (unlikely(!dpages->dpages))
3398+ goto out;
3399+
3400+ p = (void *)__get_free_page(gfp);
3401+ if (unlikely(!p))
3402+ goto out_dpages;
3403+
3404+ dpages->dpages[0].ndentry = 0;
3405+ dpages->dpages[0].dentries = p;
3406+ dpages->ndpage = 1;
3407+ return 0; /* success */
3408+
4f0767ce 3409+out_dpages:
1facf9fc 3410+ kfree(dpages->dpages);
4f0767ce 3411+out:
1facf9fc 3412+ return err;
3413+}
3414+
3415+void au_dpages_free(struct au_dcsub_pages *dpages)
3416+{
3417+ int i;
3418+ struct au_dpage *p;
3419+
3420+ p = dpages->dpages;
3421+ for (i = 0; i < dpages->ndpage; i++)
3422+ au_dpage_free(p++);
3423+ kfree(dpages->dpages);
3424+}
3425+
3426+static int au_dpages_append(struct au_dcsub_pages *dpages,
3427+ struct dentry *dentry, gfp_t gfp)
3428+{
3429+ int err, sz;
3430+ struct au_dpage *dpage;
3431+ void *p;
3432+
3433+ dpage = dpages->dpages + dpages->ndpage - 1;
3434+ sz = PAGE_SIZE / sizeof(dentry);
3435+ if (unlikely(dpage->ndentry >= sz)) {
3436+ AuLabel(new dpage);
3437+ err = -ENOMEM;
3438+ sz = dpages->ndpage * sizeof(*dpages->dpages);
3439+ p = au_kzrealloc(dpages->dpages, sz,
3440+ sz + sizeof(*dpages->dpages), gfp);
3441+ if (unlikely(!p))
3442+ goto out;
3443+
3444+ dpages->dpages = p;
3445+ dpage = dpages->dpages + dpages->ndpage;
3446+ p = (void *)__get_free_page(gfp);
3447+ if (unlikely(!p))
3448+ goto out;
3449+
3450+ dpage->ndentry = 0;
3451+ dpage->dentries = p;
3452+ dpages->ndpage++;
3453+ }
3454+
3455+ dpage->dentries[dpage->ndentry++] = dget(dentry);
3456+ return 0; /* success */
3457+
4f0767ce 3458+out:
1facf9fc 3459+ return err;
3460+}
3461+
3462+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3463+ au_dpages_test test, void *arg)
3464+{
3465+ int err;
3466+ struct dentry *this_parent = root;
3467+ struct list_head *next;
3468+ struct super_block *sb = root->d_sb;
3469+
3470+ err = 0;
3471+ spin_lock(&dcache_lock);
4f0767ce 3472+repeat:
1facf9fc 3473+ next = this_parent->d_subdirs.next;
4f0767ce 3474+resume:
1facf9fc 3475+ if (this_parent->d_sb == sb
3476+ && !IS_ROOT(this_parent)
3477+ && atomic_read(&this_parent->d_count)
3478+ && this_parent->d_inode
3479+ && (!test || test(this_parent, arg))) {
3480+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3481+ if (unlikely(err))
3482+ goto out;
3483+ }
3484+
3485+ while (next != &this_parent->d_subdirs) {
3486+ struct list_head *tmp = next;
3487+ struct dentry *dentry = list_entry(tmp, struct dentry,
3488+ d_u.d_child);
3489+ next = tmp->next;
3490+ if (/*d_unhashed(dentry) || */!dentry->d_inode)
3491+ continue;
3492+ if (!list_empty(&dentry->d_subdirs)) {
3493+ this_parent = dentry;
3494+ goto repeat;
3495+ }
3496+ if (dentry->d_sb == sb
3497+ && atomic_read(&dentry->d_count)
3498+ && (!test || test(dentry, arg))) {
3499+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3500+ if (unlikely(err))
3501+ goto out;
3502+ }
3503+ }
3504+
3505+ if (this_parent != root) {
3506+ next = this_parent->d_u.d_child.next;
3507+ this_parent = this_parent->d_parent; /* dcache_lock is locked */
3508+ goto resume;
3509+ }
4f0767ce 3510+out:
1facf9fc 3511+ spin_unlock(&dcache_lock);
3512+ return err;
3513+}
3514+
3515+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3516+ int do_include, au_dpages_test test, void *arg)
3517+{
3518+ int err;
3519+
3520+ err = 0;
3521+ spin_lock(&dcache_lock);
3522+ if (do_include && (!test || test(dentry, arg))) {
3523+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3524+ if (unlikely(err))
3525+ goto out;
3526+ }
3527+ while (!IS_ROOT(dentry)) {
3528+ dentry = dentry->d_parent; /* dcache_lock is locked */
3529+ if (!test || test(dentry, arg)) {
3530+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3531+ if (unlikely(err))
3532+ break;
3533+ }
3534+ }
3535+
4f0767ce 3536+out:
1facf9fc 3537+ spin_unlock(&dcache_lock);
3538+
3539+ return err;
3540+}
3541+
4a4d8108 3542+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 3543+{
4a4d8108
AM
3544+ struct path path[2] = {
3545+ {
3546+ .dentry = d1
3547+ },
3548+ {
3549+ .dentry = d2
3550+ }
3551+ };
1facf9fc 3552+
4a4d8108 3553+ return path_is_under(path + 0, path + 1);
1facf9fc 3554+}
e49829fe
JR
3555--- /dev/null
3556+++ linux-2.6/fs/aufs/dcsub.h 2010-10-24 11:19:23.000000000 +0200
dece6358 3557@@ -0,0 +1,54 @@
1facf9fc 3558+/*
4a4d8108 3559+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3560+ *
3561+ * This program, aufs is free software; you can redistribute it and/or modify
3562+ * it under the terms of the GNU General Public License as published by
3563+ * the Free Software Foundation; either version 2 of the License, or
3564+ * (at your option) any later version.
dece6358
AM
3565+ *
3566+ * This program is distributed in the hope that it will be useful,
3567+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3568+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3569+ * GNU General Public License for more details.
3570+ *
3571+ * You should have received a copy of the GNU General Public License
3572+ * along with this program; if not, write to the Free Software
3573+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3574+ */
3575+
3576+/*
3577+ * sub-routines for dentry cache
3578+ */
3579+
3580+#ifndef __AUFS_DCSUB_H__
3581+#define __AUFS_DCSUB_H__
3582+
3583+#ifdef __KERNEL__
3584+
dece6358
AM
3585+#include <linux/types.h>
3586+
3587+struct dentry;
1facf9fc 3588+
3589+struct au_dpage {
3590+ int ndentry;
3591+ struct dentry **dentries;
3592+};
3593+
3594+struct au_dcsub_pages {
3595+ int ndpage;
3596+ struct au_dpage *dpages;
3597+};
3598+
3599+/* ---------------------------------------------------------------------- */
3600+
3601+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3602+void au_dpages_free(struct au_dcsub_pages *dpages);
3603+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3604+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3605+ au_dpages_test test, void *arg);
3606+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3607+ int do_include, au_dpages_test test, void *arg);
4a4d8108 3608+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 3609+
3610+#endif /* __KERNEL__ */
3611+#endif /* __AUFS_DCSUB_H__ */
e49829fe
JR
3612--- /dev/null
3613+++ linux-2.6/fs/aufs/debug.c 2010-10-24 11:31:58.000000000 +0200
3614@@ -0,0 +1,443 @@
1facf9fc 3615+/*
4a4d8108 3616+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3617+ *
3618+ * This program, aufs is free software; you can redistribute it and/or modify
3619+ * it under the terms of the GNU General Public License as published by
3620+ * the Free Software Foundation; either version 2 of the License, or
3621+ * (at your option) any later version.
dece6358
AM
3622+ *
3623+ * This program is distributed in the hope that it will be useful,
3624+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3625+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3626+ * GNU General Public License for more details.
3627+ *
3628+ * You should have received a copy of the GNU General Public License
3629+ * along with this program; if not, write to the Free Software
3630+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3631+ */
3632+
3633+/*
3634+ * debug print functions
3635+ */
3636+
dece6358
AM
3637+#include <linux/module.h>
3638+#include <linux/vt_kern.h>
1facf9fc 3639+#include "aufs.h"
3640+
3641+int aufs_debug;
3642+MODULE_PARM_DESC(debug, "debug print");
3643+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
3644+
3645+char *au_plevel = KERN_DEBUG;
e49829fe
JR
3646+#define dpri(fmt, ...) do { \
3647+ if ((au_plevel \
3648+ && strcmp(au_plevel, KERN_DEBUG)) \
3649+ || au_debug_test()) \
3650+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 3651+} while (0)
3652+
3653+/* ---------------------------------------------------------------------- */
3654+
3655+void au_dpri_whlist(struct au_nhash *whlist)
3656+{
3657+ unsigned long ul, n;
3658+ struct hlist_head *head;
3659+ struct au_vdir_wh *tpos;
3660+ struct hlist_node *pos;
3661+
3662+ n = whlist->nh_num;
3663+ head = whlist->nh_head;
3664+ for (ul = 0; ul < n; ul++) {
3665+ hlist_for_each_entry(tpos, pos, head, wh_hash)
3666+ dpri("b%d, %.*s, %d\n",
3667+ tpos->wh_bindex,
3668+ tpos->wh_str.len, tpos->wh_str.name,
3669+ tpos->wh_str.len);
3670+ head++;
3671+ }
3672+}
3673+
3674+void au_dpri_vdir(struct au_vdir *vdir)
3675+{
3676+ unsigned long ul;
3677+ union au_vdir_deblk_p p;
3678+ unsigned char *o;
3679+
3680+ if (!vdir || IS_ERR(vdir)) {
3681+ dpri("err %ld\n", PTR_ERR(vdir));
3682+ return;
3683+ }
3684+
3685+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
3686+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
3687+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
3688+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
3689+ p.deblk = vdir->vd_deblk[ul];
3690+ o = p.deblk;
3691+ dpri("[%lu]: %p\n", ul, o);
3692+ }
3693+}
3694+
3695+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3696+ struct dentry *wh)
3697+{
3698+ char *n = NULL;
3699+ int l = 0;
3700+
3701+ if (!inode || IS_ERR(inode)) {
3702+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3703+ return -1;
3704+ }
3705+
3706+ /* the type of i_blocks depends upon CONFIG_LSF */
3707+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3708+ && sizeof(inode->i_blocks) != sizeof(u64));
3709+ if (wh) {
3710+ n = (void *)wh->d_name.name;
3711+ l = wh->d_name.len;
3712+ }
3713+
3714+ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
b752ccd1 3715+ " ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
1facf9fc 3716+ bindex,
3717+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3718+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3719+ i_size_read(inode), (unsigned long long)inode->i_blocks,
3720+ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3721+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
3722+ inode->i_state, inode->i_flags, inode->i_version,
3723+ inode->i_generation,
1facf9fc 3724+ l ? ", wh " : "", l, n);
3725+ return 0;
3726+}
3727+
3728+void au_dpri_inode(struct inode *inode)
3729+{
3730+ struct au_iinfo *iinfo;
3731+ aufs_bindex_t bindex;
3732+ int err;
3733+
3734+ err = do_pri_inode(-1, inode, NULL);
3735+ if (err || !au_test_aufs(inode->i_sb))
3736+ return;
3737+
3738+ iinfo = au_ii(inode);
3739+ if (!iinfo)
3740+ return;
3741+ dpri("i-1: bstart %d, bend %d, gen %d\n",
3742+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
3743+ if (iinfo->ii_bstart < 0)
3744+ return;
3745+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
3746+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
3747+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
3748+}
3749+
3750+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
3751+{
3752+ struct dentry *wh = NULL;
3753+
3754+ if (!dentry || IS_ERR(dentry)) {
3755+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
3756+ return -1;
3757+ }
3758+ /* do not call dget_parent() here */
3759+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
3760+ bindex,
3761+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
3762+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
3763+ atomic_read(&dentry->d_count), dentry->d_flags);
3764+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
3765+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
3766+ if (iinfo)
3767+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
3768+ }
3769+ do_pri_inode(bindex, dentry->d_inode, wh);
3770+ return 0;
3771+}
3772+
3773+void au_dpri_dentry(struct dentry *dentry)
3774+{
3775+ struct au_dinfo *dinfo;
3776+ aufs_bindex_t bindex;
3777+ int err;
4a4d8108 3778+ struct au_hdentry *hdp;
1facf9fc 3779+
3780+ err = do_pri_dentry(-1, dentry);
3781+ if (err || !au_test_aufs(dentry->d_sb))
3782+ return;
3783+
3784+ dinfo = au_di(dentry);
3785+ if (!dinfo)
3786+ return;
3787+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
3788+ dinfo->di_bstart, dinfo->di_bend,
3789+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
3790+ if (dinfo->di_bstart < 0)
3791+ return;
4a4d8108 3792+ hdp = dinfo->di_hdentry;
1facf9fc 3793+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 3794+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 3795+}
3796+
3797+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
3798+{
3799+ char a[32];
3800+
3801+ if (!file || IS_ERR(file)) {
3802+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
3803+ return -1;
3804+ }
3805+ a[0] = 0;
3806+ if (bindex < 0
3807+ && file->f_dentry
3808+ && au_test_aufs(file->f_dentry->d_sb)
3809+ && au_fi(file))
e49829fe
JR
3810+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
3811+ au_figen(file), !!au_fi(file)->fi_hvmop);
b752ccd1 3812+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 3813+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 3814+ file->f_version, file->f_pos, a);
1facf9fc 3815+ if (file->f_dentry)
3816+ do_pri_dentry(bindex, file->f_dentry);
3817+ return 0;
3818+}
3819+
3820+void au_dpri_file(struct file *file)
3821+{
3822+ struct au_finfo *finfo;
4a4d8108
AM
3823+ struct au_fidir *fidir;
3824+ struct au_hfile *hfile;
1facf9fc 3825+ aufs_bindex_t bindex;
3826+ int err;
3827+
3828+ err = do_pri_file(-1, file);
3829+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
3830+ return;
3831+
3832+ finfo = au_fi(file);
3833+ if (!finfo)
3834+ return;
4a4d8108 3835+ if (finfo->fi_btop < 0)
1facf9fc 3836+ return;
4a4d8108
AM
3837+ fidir = finfo->fi_hdir;
3838+ if (!fidir)
3839+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
3840+ else
e49829fe
JR
3841+ for (bindex = finfo->fi_btop;
3842+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
3843+ bindex++) {
3844+ hfile = fidir->fd_hfile + bindex;
3845+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
3846+ }
1facf9fc 3847+}
3848+
3849+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
3850+{
3851+ struct vfsmount *mnt;
3852+ struct super_block *sb;
3853+
3854+ if (!br || IS_ERR(br))
3855+ goto out;
3856+ mnt = br->br_mnt;
3857+ if (!mnt || IS_ERR(mnt))
3858+ goto out;
3859+ sb = mnt->mnt_sb;
3860+ if (!sb || IS_ERR(sb))
3861+ goto out;
3862+
3863+ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
b752ccd1 3864+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 3865+ "xino %d\n",
3866+ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
3867+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 3868+ sb->s_flags, sb->s_count,
1facf9fc 3869+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
3870+ return 0;
3871+
4f0767ce 3872+out:
1facf9fc 3873+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
3874+ return -1;
3875+}
3876+
3877+void au_dpri_sb(struct super_block *sb)
3878+{
3879+ struct au_sbinfo *sbinfo;
3880+ aufs_bindex_t bindex;
3881+ int err;
3882+ /* to reuduce stack size */
3883+ struct {
3884+ struct vfsmount mnt;
3885+ struct au_branch fake;
3886+ } *a;
3887+
3888+ /* this function can be called from magic sysrq */
3889+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
3890+ if (unlikely(!a)) {
3891+ dpri("no memory\n");
3892+ return;
3893+ }
3894+
3895+ a->mnt.mnt_sb = sb;
3896+ a->fake.br_perm = 0;
3897+ a->fake.br_mnt = &a->mnt;
3898+ a->fake.br_xino.xi_file = NULL;
3899+ atomic_set(&a->fake.br_count, 0);
3900+ smp_mb(); /* atomic_set */
3901+ err = do_pri_br(-1, &a->fake);
3902+ kfree(a);
3903+ dpri("dev 0x%x\n", sb->s_dev);
3904+ if (err || !au_test_aufs(sb))
3905+ return;
3906+
3907+ sbinfo = au_sbi(sb);
3908+ if (!sbinfo)
3909+ return;
3910+ dpri("nw %d, gen %u, kobj %d\n",
3911+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
3912+ atomic_read(&sbinfo->si_kobj.kref.refcount));
3913+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
3914+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
3915+}
3916+
3917+/* ---------------------------------------------------------------------- */
3918+
3919+void au_dbg_sleep_jiffy(int jiffy)
3920+{
3921+ while (jiffy)
3922+ jiffy = schedule_timeout_uninterruptible(jiffy);
3923+}
3924+
3925+void au_dbg_iattr(struct iattr *ia)
3926+{
3927+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
3928+ dpri(#name "\n")
3929+ AuBit(MODE);
3930+ AuBit(UID);
3931+ AuBit(GID);
3932+ AuBit(SIZE);
3933+ AuBit(ATIME);
3934+ AuBit(MTIME);
3935+ AuBit(CTIME);
3936+ AuBit(ATIME_SET);
3937+ AuBit(MTIME_SET);
3938+ AuBit(FORCE);
3939+ AuBit(ATTR_FLAG);
3940+ AuBit(KILL_SUID);
3941+ AuBit(KILL_SGID);
3942+ AuBit(FILE);
3943+ AuBit(KILL_PRIV);
3944+ AuBit(OPEN);
3945+ AuBit(TIMES_SET);
3946+#undef AuBit
3947+ dpri("ia_file %p\n", ia->ia_file);
3948+}
3949+
3950+/* ---------------------------------------------------------------------- */
3951+
3952+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
3953+{
3954+ struct dentry *parent;
3955+
3956+ parent = dget_parent(dentry);
3957+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
3958+ || IS_ROOT(dentry)
3959+ || au_digen(parent) != sigen);
3960+ dput(parent);
3961+}
3962+
3963+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
3964+{
3965+ struct dentry *parent;
3966+
3967+ parent = dget_parent(dentry);
3968+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
3969+ || au_digen(parent) != sigen);
3970+ dput(parent);
3971+}
3972+
3973+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
3974+{
3975+ int err, i, j;
3976+ struct au_dcsub_pages dpages;
3977+ struct au_dpage *dpage;
3978+ struct dentry **dentries;
3979+
3980+ err = au_dpages_init(&dpages, GFP_NOFS);
3981+ AuDebugOn(err);
3982+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
3983+ AuDebugOn(err);
3984+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
3985+ dpage = dpages.dpages + i;
3986+ dentries = dpage->dentries;
3987+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
3988+ AuDebugOn(au_digen(dentries[j]) != sigen);
3989+ }
3990+ au_dpages_free(&dpages);
3991+}
3992+
1facf9fc 3993+void au_dbg_verify_kthread(void)
3994+{
e49829fe
JR
3995+ struct task_struct *tsk = current;
3996+
3997+ if ((tsk->flags & PF_KTHREAD)
3998+ && !strncmp(tsk->comm, AUFS_WKQ_NAME "/", sizeof(AUFS_WKQ_NAME))) {
1facf9fc 3999+ au_dbg_blocked();
e49829fe 4000+ BUG();
1facf9fc 4001+ }
4002+}
4003+
e49829fe
JR
4004+static void au_dbg_do_verify_wkq(void *args)
4005+{
4006+ BUG_ON(current_fsuid());
4007+ BUG_ON(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
4008+}
4009+
4010+void au_dbg_verify_wkq(void)
4011+{
4012+ au_wkq_wait(au_dbg_do_verify_wkq, NULL);
4013+}
4014+
1facf9fc 4015+/* ---------------------------------------------------------------------- */
4016+
4017+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
4018+{
4019+#ifdef AuForceNoPlink
4020+ au_opt_clr(sbinfo->si_mntflags, PLINK);
4021+#endif
4022+#ifdef AuForceNoXino
4023+ au_opt_clr(sbinfo->si_mntflags, XINO);
4024+#endif
4025+#ifdef AuForceNoRefrof
4026+ au_opt_clr(sbinfo->si_mntflags, REFROF);
4027+#endif
4a4d8108
AM
4028+#ifdef AuForceHnotify
4029+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 4030+#endif
1308ab2a 4031+#ifdef AuForceRd0
4032+ sbinfo->si_rdblk = 0;
4033+ sbinfo->si_rdhash = 0;
4034+#endif
1facf9fc 4035+}
4036+
4037+int __init au_debug_init(void)
4038+{
4039+ aufs_bindex_t bindex;
4040+ struct au_vdir_destr destr;
4041+
4042+ bindex = -1;
4043+ AuDebugOn(bindex >= 0);
4044+
4045+ destr.len = -1;
4046+ AuDebugOn(destr.len < NAME_MAX);
4047+
4048+#ifdef CONFIG_4KSTACKS
4a4d8108 4049+ pr_warning("CONFIG_4KSTACKS is defined.\n");
1facf9fc 4050+#endif
4051+
4052+#ifdef AuForceNoBrs
4053+ sysaufs_brs = 0;
4054+#endif
4055+
4056+ return 0;
4057+}
e49829fe
JR
4058--- /dev/null
4059+++ linux-2.6/fs/aufs/debug.h 2010-10-24 11:32:22.000000000 +0200
4060@@ -0,0 +1,245 @@
1facf9fc 4061+/*
4a4d8108 4062+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4063+ *
4064+ * This program, aufs is free software; you can redistribute it and/or modify
4065+ * it under the terms of the GNU General Public License as published by
4066+ * the Free Software Foundation; either version 2 of the License, or
4067+ * (at your option) any later version.
dece6358
AM
4068+ *
4069+ * This program is distributed in the hope that it will be useful,
4070+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4071+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4072+ * GNU General Public License for more details.
4073+ *
4074+ * You should have received a copy of the GNU General Public License
4075+ * along with this program; if not, write to the Free Software
4076+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4077+ */
4078+
4079+/*
4080+ * debug print functions
4081+ */
4082+
4083+#ifndef __AUFS_DEBUG_H__
4084+#define __AUFS_DEBUG_H__
4085+
4086+#ifdef __KERNEL__
4087+
1308ab2a 4088+#include <asm/system.h>
dece6358
AM
4089+#include <linux/bug.h>
4090+/* #include <linux/err.h> */
1308ab2a 4091+#include <linux/init.h>
4a4d8108
AM
4092+#include <linux/module.h>
4093+#include <linux/kallsyms.h>
dece6358 4094+/* #include <linux/kernel.h> */
1facf9fc 4095+#include <linux/delay.h>
dece6358 4096+/* #include <linux/kd.h> */
4f0767ce 4097+#include <linux/vt_kern.h>
1facf9fc 4098+#include <linux/sysrq.h>
4099+#include <linux/aufs_type.h>
4100+
4a4d8108
AM
4101+#include <asm/system.h>
4102+
1facf9fc 4103+#ifdef CONFIG_AUFS_DEBUG
4104+#define AuDebugOn(a) BUG_ON(a)
4105+
4106+/* module parameter */
4107+extern int aufs_debug;
4108+static inline void au_debug(int n)
4109+{
4110+ aufs_debug = n;
4111+ smp_mb();
4112+}
4113+
4114+static inline int au_debug_test(void)
4115+{
4116+ return aufs_debug;
4117+}
4118+#else
4119+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
4120+AuStubVoid(au_debug, int n)
4121+AuStubInt0(au_debug_test, void)
1facf9fc 4122+#endif /* CONFIG_AUFS_DEBUG */
4123+
4124+/* ---------------------------------------------------------------------- */
4125+
4126+/* debug print */
4127+
4a4d8108 4128+#define AuDbg(fmt, ...) do { \
1facf9fc 4129+ if (au_debug_test()) \
4a4d8108 4130+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 4131+} while (0)
4a4d8108
AM
4132+#define AuLabel(l) AuDbg(#l "\n")
4133+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
4134+#define AuWarn1(fmt, ...) do { \
1facf9fc 4135+ static unsigned char _c; \
4136+ if (!_c++) \
4a4d8108 4137+ pr_warning(fmt, ##__VA_ARGS__); \
1facf9fc 4138+} while (0)
4139+
4a4d8108 4140+#define AuErr1(fmt, ...) do { \
1facf9fc 4141+ static unsigned char _c; \
4142+ if (!_c++) \
4a4d8108 4143+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 4144+} while (0)
4145+
4a4d8108 4146+#define AuIOErr1(fmt, ...) do { \
1facf9fc 4147+ static unsigned char _c; \
4148+ if (!_c++) \
4a4d8108 4149+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 4150+} while (0)
4151+
4152+#define AuUnsupportMsg "This operation is not supported." \
4153+ " Please report this application to aufs-users ML."
4a4d8108
AM
4154+#define AuUnsupport(fmt, ...) do { \
4155+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 4156+ dump_stack(); \
4157+} while (0)
4158+
4159+#define AuTraceErr(e) do { \
4160+ if (unlikely((e) < 0)) \
4161+ AuDbg("err %d\n", (int)(e)); \
4162+} while (0)
4163+
4164+#define AuTraceErrPtr(p) do { \
4165+ if (IS_ERR(p)) \
4166+ AuDbg("err %ld\n", PTR_ERR(p)); \
4167+} while (0)
4168+
4169+/* dirty macros for debug print, use with "%.*s" and caution */
4170+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
4171+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
4172+
4173+/* ---------------------------------------------------------------------- */
4174+
4175+struct au_sbinfo;
4176+struct au_finfo;
dece6358 4177+struct dentry;
1facf9fc 4178+#ifdef CONFIG_AUFS_DEBUG
4179+extern char *au_plevel;
4180+struct au_nhash;
4181+void au_dpri_whlist(struct au_nhash *whlist);
4182+struct au_vdir;
4183+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 4184+struct inode;
1facf9fc 4185+void au_dpri_inode(struct inode *inode);
4186+void au_dpri_dentry(struct dentry *dentry);
dece6358 4187+struct file;
1facf9fc 4188+void au_dpri_file(struct file *filp);
dece6358 4189+struct super_block;
1facf9fc 4190+void au_dpri_sb(struct super_block *sb);
4191+
4192+void au_dbg_sleep_jiffy(int jiffy);
dece6358 4193+struct iattr;
1facf9fc 4194+void au_dbg_iattr(struct iattr *ia);
4195+
4196+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
4197+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
4198+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 4199+void au_dbg_verify_kthread(void);
e49829fe 4200+void au_dbg_verify_wkq(void);
1facf9fc 4201+
4202+int __init au_debug_init(void);
4203+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
4204+#define AuDbgWhlist(w) do { \
4205+ AuDbg(#w "\n"); \
4206+ au_dpri_whlist(w); \
4207+} while (0)
4208+
4209+#define AuDbgVdir(v) do { \
4210+ AuDbg(#v "\n"); \
4211+ au_dpri_vdir(v); \
4212+} while (0)
4213+
4214+#define AuDbgInode(i) do { \
4215+ AuDbg(#i "\n"); \
4216+ au_dpri_inode(i); \
4217+} while (0)
4218+
4219+#define AuDbgDentry(d) do { \
4220+ AuDbg(#d "\n"); \
4221+ au_dpri_dentry(d); \
4222+} while (0)
4223+
4224+#define AuDbgFile(f) do { \
4225+ AuDbg(#f "\n"); \
4226+ au_dpri_file(f); \
4227+} while (0)
4228+
4229+#define AuDbgSb(sb) do { \
4230+ AuDbg(#sb "\n"); \
4231+ au_dpri_sb(sb); \
4232+} while (0)
4233+
4234+#define AuDbgSleep(sec) do { \
4235+ AuDbg("sleep %d sec\n", sec); \
4236+ ssleep(sec); \
4237+} while (0)
4238+
4239+#define AuDbgSleepJiffy(jiffy) do { \
4240+ AuDbg("sleep %d jiffies\n", jiffy); \
4241+ au_dbg_sleep_jiffy(jiffy); \
4242+} while (0)
4243+
4244+#define AuDbgIAttr(ia) do { \
4245+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
4246+ au_dbg_iattr(ia); \
4247+} while (0)
4a4d8108
AM
4248+
4249+#define AuDbgSym(addr) do { \
4250+ char sym[KSYM_SYMBOL_LEN]; \
4251+ sprint_symbol(sym, (unsigned long)addr); \
4252+ AuDbg("%s\n", sym); \
4253+} while (0)
4254+
4255+#define AuInfoSym(addr) do { \
4256+ char sym[KSYM_SYMBOL_LEN]; \
4257+ sprint_symbol(sym, (unsigned long)addr); \
4258+ AuInfo("%s\n", sym); \
4259+} while (0)
1facf9fc 4260+#else
4a4d8108
AM
4261+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
4262+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
4263+ unsigned int sigen)
4264+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
4265+AuStubVoid(au_dbg_verify_kthread, void)
e49829fe 4266+AuStubVoid(au_dbg_verify_wkq, void)
4a4d8108
AM
4267+AuStubInt0(__init au_debug_init, void)
4268+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 4269+
1facf9fc 4270+#define AuDbgWhlist(w) do {} while (0)
4271+#define AuDbgVdir(v) do {} while (0)
4272+#define AuDbgInode(i) do {} while (0)
4273+#define AuDbgDentry(d) do {} while (0)
4274+#define AuDbgFile(f) do {} while (0)
4275+#define AuDbgSb(sb) do {} while (0)
4276+#define AuDbgSleep(sec) do {} while (0)
4277+#define AuDbgSleepJiffy(jiffy) do {} while (0)
4278+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
4279+#define AuDbgSym(addr) do {} while (0)
4280+#define AuInfoSym(addr) do {} while (0)
1facf9fc 4281+#endif /* CONFIG_AUFS_DEBUG */
4282+
4283+/* ---------------------------------------------------------------------- */
4284+
4285+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
4286+int __init au_sysrq_init(void);
4287+void au_sysrq_fin(void);
4288+
4289+#ifdef CONFIG_HW_CONSOLE
4290+#define au_dbg_blocked() do { \
4291+ WARN_ON(1); \
e49829fe 4292+ handle_sysrq('w', vc_cons[fg_console].d->vc_tty); \
1facf9fc 4293+} while (0)
4294+#else
4a4d8108 4295+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4296+#endif
4297+
4298+#else
4a4d8108
AM
4299+AuStubInt0(__init au_sysrq_init, void)
4300+AuStubVoid(au_sysrq_fin, void)
4301+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4302+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
4303+
4304+#endif /* __KERNEL__ */
4305+#endif /* __AUFS_DEBUG_H__ */
e49829fe
JR
4306--- /dev/null
4307+++ linux-2.6/fs/aufs/dentry.c 2010-10-24 11:32:50.000000000 +0200
4308@@ -0,0 +1,860 @@
1facf9fc 4309+/*
4a4d8108 4310+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4311+ *
4312+ * This program, aufs is free software; you can redistribute it and/or modify
4313+ * it under the terms of the GNU General Public License as published by
4314+ * the Free Software Foundation; either version 2 of the License, or
4315+ * (at your option) any later version.
dece6358
AM
4316+ *
4317+ * This program is distributed in the hope that it will be useful,
4318+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4319+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4320+ * GNU General Public License for more details.
4321+ *
4322+ * You should have received a copy of the GNU General Public License
4323+ * along with this program; if not, write to the Free Software
4324+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4325+ */
4326+
4327+/*
4328+ * lookup and dentry operations
4329+ */
4330+
dece6358 4331+#include <linux/namei.h>
1facf9fc 4332+#include "aufs.h"
4333+
4334+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
4335+{
4336+ if (nd) {
4337+ *h_nd = *nd;
4338+
4339+ /*
4340+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
4341+ * due to whiteout and branch permission.
4342+ */
4343+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
b752ccd1 4344+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
1facf9fc 4345+ /* unnecessary? */
4346+ h_nd->intent.open.file = NULL;
4347+ } else
4348+ memset(h_nd, 0, sizeof(*h_nd));
4349+}
4350+
4351+struct au_lkup_one_args {
4352+ struct dentry **errp;
4353+ struct qstr *name;
4354+ struct dentry *h_parent;
4355+ struct au_branch *br;
4356+ struct nameidata *nd;
4357+};
4358+
4359+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
4360+ struct au_branch *br, struct nameidata *nd)
4361+{
4362+ struct dentry *h_dentry;
4363+ int err;
4364+ struct nameidata h_nd;
4365+
4366+ if (au_test_fs_null_nd(h_parent->d_sb))
4367+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
4368+
4369+ au_h_nd(&h_nd, nd);
4370+ h_nd.path.dentry = h_parent;
4371+ h_nd.path.mnt = br->br_mnt;
4372+
4373+ err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
4374+ h_dentry = ERR_PTR(err);
4375+ if (!err) {
4376+ path_get(&h_nd.path);
4377+ h_dentry = vfsub_lookup_hash(&h_nd);
4378+ path_put(&h_nd.path);
4379+ }
4380+
4a4d8108 4381+ AuTraceErrPtr(h_dentry);
1facf9fc 4382+ return h_dentry;
4383+}
4384+
4385+static void au_call_lkup_one(void *args)
4386+{
4387+ struct au_lkup_one_args *a = args;
4388+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
4389+}
4390+
4391+#define AuLkup_ALLOW_NEG 1
4392+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
4393+#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; }
4394+#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; }
4395+
4396+struct au_do_lookup_args {
4397+ unsigned int flags;
4398+ mode_t type;
4399+ struct nameidata *nd;
4400+};
4401+
4402+/*
4403+ * returns positive/negative dentry, NULL or an error.
4404+ * NULL means whiteout-ed or not-found.
4405+ */
4406+static struct dentry*
4407+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
4408+ aufs_bindex_t bindex, struct qstr *wh_name,
4409+ struct au_do_lookup_args *args)
4410+{
4411+ struct dentry *h_dentry;
4412+ struct inode *h_inode, *inode;
1facf9fc 4413+ struct au_branch *br;
4414+ int wh_found, opq;
4415+ unsigned char wh_able;
4416+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
4417+
1facf9fc 4418+ wh_found = 0;
4419+ br = au_sbr(dentry->d_sb, bindex);
4420+ wh_able = !!au_br_whable(br->br_perm);
4421+ if (wh_able)
4422+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
4423+ h_dentry = ERR_PTR(wh_found);
4424+ if (!wh_found)
4425+ goto real_lookup;
4426+ if (unlikely(wh_found < 0))
4427+ goto out;
4428+
4429+ /* We found a whiteout */
4430+ /* au_set_dbend(dentry, bindex); */
4431+ au_set_dbwh(dentry, bindex);
4432+ if (!allow_neg)
4433+ return NULL; /* success */
4434+
4f0767ce 4435+real_lookup:
4a4d8108 4436+ h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
1facf9fc 4437+ if (IS_ERR(h_dentry))
4438+ goto out;
4439+
4440+ h_inode = h_dentry->d_inode;
4441+ if (!h_inode) {
4442+ if (!allow_neg)
4443+ goto out_neg;
4444+ } else if (wh_found
4445+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
4446+ goto out_neg;
4447+
4448+ if (au_dbend(dentry) <= bindex)
4449+ au_set_dbend(dentry, bindex);
4450+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4451+ au_set_dbstart(dentry, bindex);
4452+ au_set_h_dptr(dentry, bindex, h_dentry);
4453+
4454+ inode = dentry->d_inode;
4455+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4456+ || (inode && !S_ISDIR(inode->i_mode)))
4457+ goto out; /* success */
4458+
4459+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4460+ opq = au_diropq_test(h_dentry, br);
4461+ mutex_unlock(&h_inode->i_mutex);
4462+ if (opq > 0)
4463+ au_set_dbdiropq(dentry, bindex);
4464+ else if (unlikely(opq < 0)) {
4465+ au_set_h_dptr(dentry, bindex, NULL);
4466+ h_dentry = ERR_PTR(opq);
4467+ }
4468+ goto out;
4469+
4f0767ce 4470+out_neg:
1facf9fc 4471+ dput(h_dentry);
4472+ h_dentry = NULL;
4f0767ce 4473+out:
1facf9fc 4474+ return h_dentry;
4475+}
4476+
dece6358
AM
4477+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
4478+{
4479+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
4480+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
4481+ return -EPERM;
4482+ return 0;
4483+}
4484+
1facf9fc 4485+/*
4486+ * returns the number of lower positive dentries,
4487+ * otherwise an error.
4488+ * can be called at unlinking with @type is zero.
4489+ */
4490+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4491+ struct nameidata *nd)
4492+{
4493+ int npositive, err;
4494+ aufs_bindex_t bindex, btail, bdiropq;
4495+ unsigned char isdir;
4496+ struct qstr whname;
4497+ struct au_do_lookup_args args = {
4498+ .flags = 0,
4499+ .type = type,
4500+ .nd = nd
4501+ };
4502+ const struct qstr *name = &dentry->d_name;
4503+ struct dentry *parent;
4504+ struct inode *inode;
4505+
dece6358
AM
4506+ err = au_test_shwh(dentry->d_sb, name);
4507+ if (unlikely(err))
1facf9fc 4508+ goto out;
4509+
4510+ err = au_wh_name_alloc(&whname, name);
4511+ if (unlikely(err))
4512+ goto out;
4513+
4514+ inode = dentry->d_inode;
4515+ isdir = !!(inode && S_ISDIR(inode->i_mode));
4516+ if (!type)
4517+ au_fset_lkup(args.flags, ALLOW_NEG);
4518+
4519+ npositive = 0;
4a4d8108 4520+ parent = dget_parent(dentry);
1facf9fc 4521+ btail = au_dbtaildir(parent);
4522+ for (bindex = bstart; bindex <= btail; bindex++) {
4523+ struct dentry *h_parent, *h_dentry;
4524+ struct inode *h_inode, *h_dir;
4525+
4526+ h_dentry = au_h_dptr(dentry, bindex);
4527+ if (h_dentry) {
4528+ if (h_dentry->d_inode)
4529+ npositive++;
4530+ if (type != S_IFDIR)
4531+ break;
4532+ continue;
4533+ }
4534+ h_parent = au_h_dptr(parent, bindex);
4535+ if (!h_parent)
4536+ continue;
4537+ h_dir = h_parent->d_inode;
4538+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
4539+ continue;
4540+
4541+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4542+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4543+ &args);
4544+ mutex_unlock(&h_dir->i_mutex);
4545+ err = PTR_ERR(h_dentry);
4546+ if (IS_ERR(h_dentry))
4a4d8108 4547+ goto out_parent;
1facf9fc 4548+ au_fclr_lkup(args.flags, ALLOW_NEG);
4549+
4550+ if (au_dbwh(dentry) >= 0)
4551+ break;
4552+ if (!h_dentry)
4553+ continue;
4554+ h_inode = h_dentry->d_inode;
4555+ if (!h_inode)
4556+ continue;
4557+ npositive++;
4558+ if (!args.type)
4559+ args.type = h_inode->i_mode & S_IFMT;
4560+ if (args.type != S_IFDIR)
4561+ break;
4562+ else if (isdir) {
4563+ /* the type of lower may be different */
4564+ bdiropq = au_dbdiropq(dentry);
4565+ if (bdiropq >= 0 && bdiropq <= bindex)
4566+ break;
4567+ }
4568+ }
4569+
4570+ if (npositive) {
4571+ AuLabel(positive);
4572+ au_update_dbstart(dentry);
4573+ }
4574+ err = npositive;
4575+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
4576+ && au_dbstart(dentry) < 0))
4577+ /* both of real entry and whiteout found */
4578+ err = -EIO;
4579+
4f0767ce 4580+out_parent:
4a4d8108 4581+ dput(parent);
1facf9fc 4582+ kfree(whname.name);
4f0767ce 4583+out:
1facf9fc 4584+ return err;
4585+}
4586+
4587+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4588+ struct au_branch *br)
4589+{
4590+ struct dentry *dentry;
4591+ int wkq_err;
4592+
4593+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
4594+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
4595+ else {
4596+ struct au_lkup_one_args args = {
4597+ .errp = &dentry,
4598+ .name = name,
4599+ .h_parent = parent,
4600+ .br = br,
4601+ .nd = NULL
4602+ };
4603+
4604+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
4605+ if (unlikely(wkq_err))
4606+ dentry = ERR_PTR(wkq_err);
4607+ }
4608+
4609+ return dentry;
4610+}
4611+
4612+/*
4613+ * lookup @dentry on @bindex which should be negative.
4614+ */
4615+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4616+{
4617+ int err;
4618+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 4619+
1facf9fc 4620+ parent = dget_parent(dentry);
4621+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 4622+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 4623+ au_sbr(dentry->d_sb, bindex));
4624+ err = PTR_ERR(h_dentry);
4625+ if (IS_ERR(h_dentry))
4626+ goto out;
4627+ if (unlikely(h_dentry->d_inode)) {
4628+ err = -EIO;
4629+ AuIOErr("b%d %.*s should be negative.\n",
4630+ bindex, AuDLNPair(h_dentry));
4631+ dput(h_dentry);
4632+ goto out;
4633+ }
4634+
4a4d8108 4635+ err = 0;
1facf9fc 4636+ if (bindex < au_dbstart(dentry))
4637+ au_set_dbstart(dentry, bindex);
4638+ if (au_dbend(dentry) < bindex)
4639+ au_set_dbend(dentry, bindex);
4640+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 4641+
4f0767ce 4642+out:
1facf9fc 4643+ dput(parent);
4644+ return err;
4645+}
4646+
4647+/* ---------------------------------------------------------------------- */
4648+
4649+/* subset of struct inode */
4650+struct au_iattr {
4651+ unsigned long i_ino;
4652+ /* unsigned int i_nlink; */
4653+ uid_t i_uid;
4654+ gid_t i_gid;
4655+ u64 i_version;
4656+/*
4657+ loff_t i_size;
4658+ blkcnt_t i_blocks;
4659+*/
4660+ umode_t i_mode;
4661+};
4662+
4663+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
4664+{
4665+ ia->i_ino = h_inode->i_ino;
4666+ /* ia->i_nlink = h_inode->i_nlink; */
4667+ ia->i_uid = h_inode->i_uid;
4668+ ia->i_gid = h_inode->i_gid;
4669+ ia->i_version = h_inode->i_version;
4670+/*
4671+ ia->i_size = h_inode->i_size;
4672+ ia->i_blocks = h_inode->i_blocks;
4673+*/
4674+ ia->i_mode = (h_inode->i_mode & S_IFMT);
4675+}
4676+
4677+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
4678+{
4679+ return ia->i_ino != h_inode->i_ino
4680+ /* || ia->i_nlink != h_inode->i_nlink */
4681+ || ia->i_uid != h_inode->i_uid
4682+ || ia->i_gid != h_inode->i_gid
4683+ || ia->i_version != h_inode->i_version
4684+/*
4685+ || ia->i_size != h_inode->i_size
4686+ || ia->i_blocks != h_inode->i_blocks
4687+*/
4688+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
4689+}
4690+
4691+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
4692+ struct au_branch *br)
4693+{
4694+ int err;
4695+ struct au_iattr ia;
4696+ struct inode *h_inode;
4697+ struct dentry *h_d;
4698+ struct super_block *h_sb;
4699+
4700+ err = 0;
4701+ memset(&ia, -1, sizeof(ia));
4702+ h_sb = h_dentry->d_sb;
4703+ h_inode = h_dentry->d_inode;
4704+ if (h_inode)
4705+ au_iattr_save(&ia, h_inode);
4706+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
4707+ /* nfs d_revalidate may return 0 for negative dentry */
4708+ /* fuse d_revalidate always return 0 for negative dentry */
4709+ goto out;
4710+
4711+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
4712+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
4713+ err = PTR_ERR(h_d);
4714+ if (IS_ERR(h_d))
4715+ goto out;
4716+
4717+ err = 0;
4718+ if (unlikely(h_d != h_dentry
4719+ || h_d->d_inode != h_inode
4720+ || (h_inode && au_iattr_test(&ia, h_inode))))
4721+ err = au_busy_or_stale();
4722+ dput(h_d);
4723+
4f0767ce 4724+out:
1facf9fc 4725+ AuTraceErr(err);
4726+ return err;
4727+}
4728+
4729+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
4730+ struct dentry *h_parent, struct au_branch *br)
4731+{
4732+ int err;
4733+
4734+ err = 0;
4735+ if (udba == AuOpt_UDBA_REVAL) {
4736+ IMustLock(h_dir);
4737+ err = (h_dentry->d_parent->d_inode != h_dir);
4a4d8108 4738+ } else if (udba == AuOpt_UDBA_HNOTIFY)
1facf9fc 4739+ err = au_h_verify_dentry(h_dentry, h_parent, br);
4740+
4741+ return err;
4742+}
4743+
4744+/* ---------------------------------------------------------------------- */
4745+
4746+static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
4747+ struct dentry *parent)
4748+{
4749+ struct dentry *h_d, *h_dp;
4750+ struct au_hdentry tmp, *q;
4751+ struct super_block *sb;
4752+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
4753+
1308ab2a 4754+ AuRwMustWriteLock(&dinfo->di_rwsem);
4755+
1facf9fc 4756+ bend = dinfo->di_bend;
4757+ bwh = dinfo->di_bwh;
4758+ bdiropq = dinfo->di_bdiropq;
4759+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
4760+ h_d = p->hd_dentry;
4761+ if (!h_d)
4762+ continue;
4763+
4764+ h_dp = dget_parent(h_d);
4765+ if (h_dp == au_h_dptr(parent, bindex)) {
4766+ dput(h_dp);
4767+ continue;
4768+ }
4769+
4770+ new_bindex = au_find_dbindex(parent, h_dp);
4771+ dput(h_dp);
4772+ if (dinfo->di_bwh == bindex)
4773+ bwh = new_bindex;
4774+ if (dinfo->di_bdiropq == bindex)
4775+ bdiropq = new_bindex;
4776+ if (new_bindex < 0) {
4777+ au_hdput(p);
4778+ p->hd_dentry = NULL;
4779+ continue;
4780+ }
4781+
4782+ /* swap two lower dentries, and loop again */
4783+ q = dinfo->di_hdentry + new_bindex;
4784+ tmp = *q;
4785+ *q = *p;
4786+ *p = tmp;
4787+ if (tmp.hd_dentry) {
4788+ bindex--;
4789+ p--;
4790+ }
4791+ }
4792+
4793+ sb = parent->d_sb;
4794+ dinfo->di_bwh = -1;
4795+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
4796+ dinfo->di_bwh = bwh;
4797+
4798+ dinfo->di_bdiropq = -1;
4799+ if (bdiropq >= 0
4800+ && bdiropq <= au_sbend(sb)
4801+ && au_sbr_whable(sb, bdiropq))
4802+ dinfo->di_bdiropq = bdiropq;
4803+
4804+ bend = au_dbend(parent);
4805+ p = dinfo->di_hdentry;
4806+ for (bindex = 0; bindex <= bend; bindex++, p++)
4807+ if (p->hd_dentry) {
4808+ dinfo->di_bstart = bindex;
4809+ break;
4810+ }
4811+
4812+ p = dinfo->di_hdentry + bend;
4813+ for (bindex = bend; bindex >= 0; bindex--, p--)
4814+ if (p->hd_dentry) {
4815+ dinfo->di_bend = bindex;
4816+ break;
4817+ }
4818+}
4819+
4820+/*
4821+ * returns the number of found lower positive dentries,
4822+ * otherwise an error.
4823+ */
4824+int au_refresh_hdentry(struct dentry *dentry, mode_t type)
4825+{
4826+ int npositive, err;
4827+ unsigned int sigen;
4828+ aufs_bindex_t bstart;
4829+ struct au_dinfo *dinfo;
4830+ struct super_block *sb;
4831+ struct dentry *parent;
4832+
1308ab2a 4833+ DiMustWriteLock(dentry);
4834+
1facf9fc 4835+ sb = dentry->d_sb;
4836+ AuDebugOn(IS_ROOT(dentry));
4837+ sigen = au_sigen(sb);
4838+ parent = dget_parent(dentry);
4839+ AuDebugOn(au_digen(parent) != sigen
4840+ || au_iigen(parent->d_inode) != sigen);
4841+
4842+ dinfo = au_di(dentry);
4843+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
4844+ npositive = err;
4845+ if (unlikely(err))
4846+ goto out;
4847+ au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
4848+ parent);
4849+
4850+ npositive = 0;
4851+ bstart = au_dbstart(parent);
4852+ if (type != S_IFDIR && dinfo->di_bstart == bstart)
4853+ goto out_dgen; /* success */
4854+
4855+ npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
4856+ if (npositive < 0)
4857+ goto out;
4858+ if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
4859+ d_drop(dentry);
4860+
4f0767ce 4861+out_dgen:
1facf9fc 4862+ au_update_digen(dentry);
4f0767ce 4863+out:
1facf9fc 4864+ dput(parent);
4865+ AuTraceErr(npositive);
4866+ return npositive;
4867+}
4868+
4869+static noinline_for_stack
4870+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
4871+ struct dentry *dentry, aufs_bindex_t bindex)
4872+{
4873+ int err, valid;
4874+ int (*reval)(struct dentry *, struct nameidata *);
4875+
4876+ err = 0;
4877+ reval = NULL;
4878+ if (h_dentry->d_op)
4879+ reval = h_dentry->d_op->d_revalidate;
4880+ if (!reval)
4881+ goto out;
4882+
4883+ AuDbg("b%d\n", bindex);
4884+ if (au_test_fs_null_nd(h_dentry->d_sb))
4885+ /* it may return tri-state */
4886+ valid = reval(h_dentry, NULL);
4887+ else {
4888+ struct nameidata h_nd;
4889+ int locked;
4890+ struct dentry *parent;
4891+
4892+ au_h_nd(&h_nd, nd);
4893+ parent = nd->path.dentry;
4894+ locked = (nd && nd->path.dentry != dentry);
4895+ if (locked)
4896+ di_read_lock_parent(parent, AuLock_IR);
4897+ BUG_ON(bindex > au_dbend(parent));
4898+ h_nd.path.dentry = au_h_dptr(parent, bindex);
4899+ BUG_ON(!h_nd.path.dentry);
4900+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
4901+ path_get(&h_nd.path);
4902+ valid = reval(h_dentry, &h_nd);
4903+ path_put(&h_nd.path);
4904+ if (locked)
4905+ di_read_unlock(parent, AuLock_IR);
4906+ }
4907+
4908+ if (unlikely(valid < 0))
4909+ err = valid;
4910+ else if (!valid)
4911+ err = -EINVAL;
4912+
4f0767ce 4913+out:
1facf9fc 4914+ AuTraceErr(err);
4915+ return err;
4916+}
4917+
4918+/* todo: remove this */
4919+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
4920+ struct nameidata *nd, int do_udba)
4921+{
4922+ int err;
4923+ umode_t mode, h_mode;
4924+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
4925+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 4926+ struct inode *h_inode, *h_cached_inode;
1facf9fc 4927+ struct dentry *h_dentry;
4928+ struct qstr *name, *h_name;
4929+
4930+ err = 0;
4931+ plus = 0;
4932+ mode = 0;
1facf9fc 4933+ ibs = -1;
4934+ ibe = -1;
4935+ unhashed = !!d_unhashed(dentry);
4936+ is_root = !!IS_ROOT(dentry);
4937+ name = &dentry->d_name;
4938+
4939+ /*
e49829fe
JR
4940+ * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
4941+ * But inotify doesn't fire some necessary events,
1facf9fc 4942+ * IN_ATTRIB for atime/nlink/pageio
4943+ * IN_DELETE for NFS dentry
4944+ * Let's do REVAL test too.
4945+ */
4946+ if (do_udba && inode) {
4947+ mode = (inode->i_mode & S_IFMT);
4948+ plus = (inode->i_nlink > 0);
1facf9fc 4949+ ibs = au_ibstart(inode);
4950+ ibe = au_ibend(inode);
4951+ }
4952+
4953+ bstart = au_dbstart(dentry);
4954+ btail = bstart;
4955+ if (inode && S_ISDIR(inode->i_mode))
4956+ btail = au_dbtaildir(dentry);
4957+ for (bindex = bstart; bindex <= btail; bindex++) {
4958+ h_dentry = au_h_dptr(dentry, bindex);
4959+ if (!h_dentry)
4960+ continue;
4961+
4962+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
4963+ h_name = &h_dentry->d_name;
4964+ if (unlikely(do_udba
4965+ && !is_root
4966+ && (unhashed != !!d_unhashed(h_dentry)
4967+ || name->len != h_name->len
4968+ || memcmp(name->name, h_name->name, name->len))
4969+ )) {
4970+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
4971+ unhashed, d_unhashed(h_dentry),
4972+ AuDLNPair(dentry), AuDLNPair(h_dentry));
4973+ goto err;
4974+ }
4975+
4976+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
4977+ if (unlikely(err))
4978+ /* do not goto err, to keep the errno */
4979+ break;
4980+
4981+ /* todo: plink too? */
4982+ if (!do_udba)
4983+ continue;
4984+
4985+ /* UDBA tests */
4986+ h_inode = h_dentry->d_inode;
4987+ if (unlikely(!!inode != !!h_inode))
4988+ goto err;
4989+
4990+ h_plus = plus;
4991+ h_mode = mode;
4992+ h_cached_inode = h_inode;
4993+ if (h_inode) {
4994+ h_mode = (h_inode->i_mode & S_IFMT);
4995+ h_plus = (h_inode->i_nlink > 0);
4996+ }
4997+ if (inode && ibs <= bindex && bindex <= ibe)
4998+ h_cached_inode = au_h_iptr(inode, bindex);
4999+
5000+ if (unlikely(plus != h_plus
5001+ || mode != h_mode
5002+ || h_cached_inode != h_inode))
5003+ goto err;
5004+ continue;
5005+
5006+ err:
5007+ err = -EINVAL;
5008+ break;
5009+ }
5010+
5011+ return err;
5012+}
5013+
5014+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
5015+{
5016+ int err;
5017+ struct dentry *parent;
5018+ struct inode *inode;
5019+
5020+ inode = dentry->d_inode;
5021+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
5022+ return 0;
5023+
5024+ parent = dget_parent(dentry);
5025+ di_read_lock_parent(parent, AuLock_IR);
5026+ AuDebugOn(au_digen(parent) != sigen
5027+ || au_iigen(parent->d_inode) != sigen);
5028+ au_dbg_verify_gen(parent, sigen);
5029+
5030+ /* returns a number of positive dentries */
5031+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
5032+ if (err >= 0)
5033+ err = au_refresh_hinode(inode, dentry);
5034+
5035+ di_read_unlock(parent, AuLock_IR);
5036+ dput(parent);
5037+ return err;
5038+}
5039+
5040+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
5041+{
5042+ int err;
5043+ struct dentry *d, *parent;
5044+ struct inode *inode;
5045+
5046+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
5047+ return simple_reval_dpath(dentry, sigen);
5048+
5049+ /* slow loop, keep it simple and stupid */
5050+ /* cf: au_cpup_dirs() */
5051+ err = 0;
5052+ parent = NULL;
5053+ while (au_digen(dentry) != sigen
5054+ || au_iigen(dentry->d_inode) != sigen) {
5055+ d = dentry;
5056+ while (1) {
5057+ dput(parent);
5058+ parent = dget_parent(d);
5059+ if (au_digen(parent) == sigen
5060+ && au_iigen(parent->d_inode) == sigen)
5061+ break;
5062+ d = parent;
5063+ }
5064+
5065+ inode = d->d_inode;
5066+ if (d != dentry)
5067+ di_write_lock_child(d);
5068+
5069+ /* someone might update our dentry while we were sleeping */
5070+ if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
5071+ di_read_lock_parent(parent, AuLock_IR);
5072+ /* returns a number of positive dentries */
5073+ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
5074+ if (err >= 0)
5075+ err = au_refresh_hinode(inode, d);
5076+ di_read_unlock(parent, AuLock_IR);
5077+ }
5078+
5079+ if (d != dentry)
5080+ di_write_unlock(d);
5081+ dput(parent);
5082+ if (unlikely(err))
5083+ break;
5084+ }
5085+
5086+ return err;
5087+}
5088+
5089+/*
5090+ * if valid returns 1, otherwise 0.
5091+ */
5092+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
5093+{
5094+ int valid, err;
5095+ unsigned int sigen;
5096+ unsigned char do_udba;
5097+ struct super_block *sb;
5098+ struct inode *inode;
5099+
e49829fe 5100+ valid = 1;
1facf9fc 5101+ sb = dentry->d_sb;
5102+ inode = dentry->d_inode;
e49829fe
JR
5103+ /*
5104+ * todo: very ugly
5105+ * i_mutex of parent dir may be held,
5106+ * but we should not return 'invalid' due to busy.
5107+ */
5108+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
5109+ if (unlikely(err)) {
5110+ valid = err;
5111+ goto out;
5112+ }
1facf9fc 5113+ sigen = au_sigen(sb);
5114+ if (au_digen(dentry) != sigen) {
5115+ AuDebugOn(IS_ROOT(dentry));
5116+ if (inode)
5117+ err = au_reval_dpath(dentry, sigen);
5118+ if (unlikely(err))
5119+ goto out_dgrade;
1facf9fc 5120+ }
5121+ if (inode && au_iigen(inode) != sigen) {
5122+ AuDebugOn(IS_ROOT(dentry));
5123+ err = au_refresh_hinode(inode, dentry);
5124+ if (unlikely(err))
5125+ goto out_dgrade;
1facf9fc 5126+ }
5127+ di_downgrade_lock(dentry, AuLock_IR);
5128+
1facf9fc 5129+ err = -EINVAL;
5130+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
5131+ if (do_udba && inode) {
5132+ aufs_bindex_t bstart = au_ibstart(inode);
5133+
5134+ if (bstart >= 0
5135+ && au_test_higen(inode, au_h_iptr(inode, bstart)))
e49829fe 5136+ goto out_inval;
1facf9fc 5137+ }
5138+
5139+ err = h_d_revalidate(dentry, inode, nd, do_udba);
5140+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
5141+ /* both of real entry and whiteout found */
5142+ err = -EIO;
e49829fe 5143+ goto out_inval;
1facf9fc 5144+
4f0767ce 5145+out_dgrade:
1facf9fc 5146+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 5147+out_inval:
1facf9fc 5148+ aufs_read_unlock(dentry, AuLock_IR);
5149+ AuTraceErr(err);
5150+ valid = !err;
e49829fe 5151+out:
1facf9fc 5152+ if (!valid)
e49829fe 5153+ AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid);
1facf9fc 5154+ return valid;
5155+}
5156+
5157+static void aufs_d_release(struct dentry *dentry)
5158+{
4a4d8108
AM
5159+ if (dentry->d_fsdata) {
5160+ au_di_fin(dentry);
5161+ au_hn_di_reinit(dentry);
1facf9fc 5162+ }
1facf9fc 5163+}
5164+
4a4d8108 5165+const struct dentry_operations aufs_dop = {
1facf9fc 5166+ .d_revalidate = aufs_d_revalidate,
5167+ .d_release = aufs_d_release
5168+};
e49829fe
JR
5169--- /dev/null
5170+++ linux-2.6/fs/aufs/dentry.h 2010-10-24 11:33:02.000000000 +0200
1308ab2a 5171@@ -0,0 +1,231 @@
1facf9fc 5172+/*
4a4d8108 5173+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5174+ *
5175+ * This program, aufs is free software; you can redistribute it and/or modify
5176+ * it under the terms of the GNU General Public License as published by
5177+ * the Free Software Foundation; either version 2 of the License, or
5178+ * (at your option) any later version.
dece6358
AM
5179+ *
5180+ * This program is distributed in the hope that it will be useful,
5181+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5182+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5183+ * GNU General Public License for more details.
5184+ *
5185+ * You should have received a copy of the GNU General Public License
5186+ * along with this program; if not, write to the Free Software
5187+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5188+ */
5189+
5190+/*
5191+ * lookup and dentry operations
5192+ */
5193+
5194+#ifndef __AUFS_DENTRY_H__
5195+#define __AUFS_DENTRY_H__
5196+
5197+#ifdef __KERNEL__
5198+
dece6358 5199+#include <linux/dcache.h>
1facf9fc 5200+#include <linux/aufs_type.h>
5201+#include "rwsem.h"
5202+
5203+/* make a single member structure for future use */
5204+/* todo: remove this structure */
5205+struct au_hdentry {
5206+ struct dentry *hd_dentry;
5207+};
5208+
5209+struct au_dinfo {
5210+ atomic_t di_generation;
5211+
dece6358 5212+ struct au_rwsem di_rwsem;
1facf9fc 5213+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
5214+ struct au_hdentry *di_hdentry;
4a4d8108 5215+} ____cacheline_aligned_in_smp;
1facf9fc 5216+
5217+/* ---------------------------------------------------------------------- */
5218+
5219+/* dentry.c */
4a4d8108 5220+extern const struct dentry_operations aufs_dop;
1facf9fc 5221+struct au_branch;
5222+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
5223+ struct au_branch *br, struct nameidata *nd);
5224+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
5225+ struct au_branch *br);
5226+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
5227+ struct dentry *h_parent, struct au_branch *br);
5228+
5229+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
5230+ struct nameidata *nd);
5231+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
5232+int au_refresh_hdentry(struct dentry *dentry, mode_t type);
5233+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
5234+
5235+/* dinfo.c */
4a4d8108
AM
5236+void au_di_init_once(void *_di);
5237+int au_di_init(struct dentry *dentry);
5238+void au_di_fin(struct dentry *dentry);
1facf9fc 5239+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
5240+
5241+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
5242+void di_read_unlock(struct dentry *d, int flags);
5243+void di_downgrade_lock(struct dentry *d, int flags);
5244+void di_write_lock(struct dentry *d, unsigned int lsc);
5245+void di_write_unlock(struct dentry *d);
5246+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
5247+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
5248+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
5249+
5250+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
5251+aufs_bindex_t au_dbtail(struct dentry *dentry);
5252+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
5253+
5254+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5255+ struct dentry *h_dentry);
5256+void au_update_digen(struct dentry *dentry);
5257+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5258+void au_update_dbstart(struct dentry *dentry);
5259+void au_update_dbend(struct dentry *dentry);
5260+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
5261+
5262+/* ---------------------------------------------------------------------- */
5263+
5264+static inline struct au_dinfo *au_di(struct dentry *dentry)
5265+{
5266+ return dentry->d_fsdata;
5267+}
5268+
5269+/* ---------------------------------------------------------------------- */
5270+
5271+/* lock subclass for dinfo */
5272+enum {
5273+ AuLsc_DI_CHILD, /* child first */
4a4d8108 5274+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 5275+ AuLsc_DI_CHILD3, /* copyup dirs */
5276+ AuLsc_DI_PARENT,
5277+ AuLsc_DI_PARENT2,
5278+ AuLsc_DI_PARENT3
5279+};
5280+
5281+/*
5282+ * di_read_lock_child, di_write_lock_child,
5283+ * di_read_lock_child2, di_write_lock_child2,
5284+ * di_read_lock_child3, di_write_lock_child3,
5285+ * di_read_lock_parent, di_write_lock_parent,
5286+ * di_read_lock_parent2, di_write_lock_parent2,
5287+ * di_read_lock_parent3, di_write_lock_parent3,
5288+ */
5289+#define AuReadLockFunc(name, lsc) \
5290+static inline void di_read_lock_##name(struct dentry *d, int flags) \
5291+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
5292+
5293+#define AuWriteLockFunc(name, lsc) \
5294+static inline void di_write_lock_##name(struct dentry *d) \
5295+{ di_write_lock(d, AuLsc_DI_##lsc); }
5296+
5297+#define AuRWLockFuncs(name, lsc) \
5298+ AuReadLockFunc(name, lsc) \
5299+ AuWriteLockFunc(name, lsc)
5300+
5301+AuRWLockFuncs(child, CHILD);
5302+AuRWLockFuncs(child2, CHILD2);
5303+AuRWLockFuncs(child3, CHILD3);
5304+AuRWLockFuncs(parent, PARENT);
5305+AuRWLockFuncs(parent2, PARENT2);
5306+AuRWLockFuncs(parent3, PARENT3);
5307+
5308+#undef AuReadLockFunc
5309+#undef AuWriteLockFunc
5310+#undef AuRWLockFuncs
5311+
5312+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
5313+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
5314+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 5315+
5316+/* ---------------------------------------------------------------------- */
5317+
5318+/* todo: memory barrier? */
5319+static inline unsigned int au_digen(struct dentry *d)
5320+{
5321+ return atomic_read(&au_di(d)->di_generation);
5322+}
5323+
5324+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
5325+{
5326+ hdentry->hd_dentry = NULL;
5327+}
5328+
5329+static inline void au_hdput(struct au_hdentry *hd)
5330+{
4a4d8108
AM
5331+ if (hd)
5332+ dput(hd->hd_dentry);
1facf9fc 5333+}
5334+
5335+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
5336+{
1308ab2a 5337+ DiMustAnyLock(dentry);
1facf9fc 5338+ return au_di(dentry)->di_bstart;
5339+}
5340+
5341+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
5342+{
1308ab2a 5343+ DiMustAnyLock(dentry);
1facf9fc 5344+ return au_di(dentry)->di_bend;
5345+}
5346+
5347+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
5348+{
1308ab2a 5349+ DiMustAnyLock(dentry);
1facf9fc 5350+ return au_di(dentry)->di_bwh;
5351+}
5352+
5353+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
5354+{
1308ab2a 5355+ DiMustAnyLock(dentry);
1facf9fc 5356+ return au_di(dentry)->di_bdiropq;
5357+}
5358+
5359+/* todo: hard/soft set? */
5360+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
5361+{
1308ab2a 5362+ DiMustWriteLock(dentry);
1facf9fc 5363+ au_di(dentry)->di_bstart = bindex;
5364+}
5365+
5366+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
5367+{
1308ab2a 5368+ DiMustWriteLock(dentry);
1facf9fc 5369+ au_di(dentry)->di_bend = bindex;
5370+}
5371+
5372+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
5373+{
1308ab2a 5374+ DiMustWriteLock(dentry);
1facf9fc 5375+ /* dbwh can be outside of bstart - bend range */
5376+ au_di(dentry)->di_bwh = bindex;
5377+}
5378+
5379+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
5380+{
1308ab2a 5381+ DiMustWriteLock(dentry);
1facf9fc 5382+ au_di(dentry)->di_bdiropq = bindex;
5383+}
5384+
5385+/* ---------------------------------------------------------------------- */
5386+
4a4d8108 5387+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 5388+static inline void au_digen_dec(struct dentry *d)
5389+{
e49829fe 5390+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 5391+}
5392+
4a4d8108 5393+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 5394+{
5395+ dentry->d_fsdata = NULL;
5396+}
5397+#else
4a4d8108
AM
5398+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
5399+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 5400+
5401+#endif /* __KERNEL__ */
5402+#endif /* __AUFS_DENTRY_H__ */
e49829fe
JR
5403--- /dev/null
5404+++ linux-2.6/fs/aufs/dinfo.c 2010-10-24 11:33:24.000000000 +0200
5405@@ -0,0 +1,397 @@
1facf9fc 5406+/*
4a4d8108 5407+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5408+ *
5409+ * This program, aufs is free software; you can redistribute it and/or modify
5410+ * it under the terms of the GNU General Public License as published by
5411+ * the Free Software Foundation; either version 2 of the License, or
5412+ * (at your option) any later version.
dece6358
AM
5413+ *
5414+ * This program is distributed in the hope that it will be useful,
5415+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5416+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5417+ * GNU General Public License for more details.
5418+ *
5419+ * You should have received a copy of the GNU General Public License
5420+ * along with this program; if not, write to the Free Software
5421+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5422+ */
5423+
5424+/*
5425+ * dentry private data
5426+ */
5427+
5428+#include "aufs.h"
5429+
e49829fe 5430+void au_di_init_once(void *_dinfo)
4a4d8108 5431+{
e49829fe
JR
5432+ struct au_dinfo *dinfo = _dinfo;
5433+ static struct lock_class_key aufs_di;
4a4d8108 5434+
e49829fe
JR
5435+ au_rw_init(&dinfo->di_rwsem);
5436+ au_rw_class(&dinfo->di_rwsem, &aufs_di);
4a4d8108
AM
5437+}
5438+
5439+int au_di_init(struct dentry *dentry)
1facf9fc 5440+{
5441+ struct au_dinfo *dinfo;
5442+ struct super_block *sb;
5443+ int nbr;
5444+
5445+ dinfo = au_cache_alloc_dinfo();
5446+ if (unlikely(!dinfo))
5447+ goto out;
5448+
5449+ sb = dentry->d_sb;
5450+ nbr = au_sbend(sb) + 1;
5451+ if (nbr <= 0)
5452+ nbr = 1;
5453+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
5454+ if (unlikely(!dinfo->di_hdentry))
5455+ goto out_dinfo;
5456+
5457+ atomic_set(&dinfo->di_generation, au_sigen(sb));
5458+ /* smp_mb(); */ /* atomic_set */
4a4d8108 5459+ au_rw_write_lock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
1facf9fc 5460+ dinfo->di_bstart = -1;
5461+ dinfo->di_bend = -1;
5462+ dinfo->di_bwh = -1;
5463+ dinfo->di_bdiropq = -1;
5464+
5465+ dentry->d_fsdata = dinfo;
5466+ dentry->d_op = &aufs_dop;
5467+ return 0; /* success */
5468+
4f0767ce 5469+out_dinfo:
1facf9fc 5470+ au_cache_free_dinfo(dinfo);
4f0767ce 5471+out:
1facf9fc 5472+ return -ENOMEM;
5473+}
5474+
4a4d8108
AM
5475+void au_di_fin(struct dentry *dentry)
5476+{
5477+ struct au_dinfo *di;
5478+ struct au_hdentry *p;
5479+ aufs_bindex_t bend, bindex;
5480+
5481+ /* dentry may not be revalidated */
5482+ di = dentry->d_fsdata;
5483+ bindex = di->di_bstart;
5484+ if (bindex >= 0) {
5485+ bend = di->di_bend;
5486+ p = di->di_hdentry + bindex;
5487+ while (bindex++ <= bend)
5488+ au_hdput(p++);
5489+ }
5490+ kfree(di->di_hdentry);
5491+ AuRwDestroy(&di->di_rwsem);
5492+ au_cache_free_dinfo(di);
5493+}
5494+
1facf9fc 5495+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
5496+{
5497+ int err, sz;
5498+ struct au_hdentry *hdp;
5499+
1308ab2a 5500+ AuRwMustWriteLock(&dinfo->di_rwsem);
5501+
1facf9fc 5502+ err = -ENOMEM;
5503+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
5504+ if (!sz)
5505+ sz = sizeof(*hdp);
5506+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
5507+ if (hdp) {
5508+ dinfo->di_hdentry = hdp;
5509+ err = 0;
5510+ }
5511+
5512+ return err;
5513+}
5514+
5515+/* ---------------------------------------------------------------------- */
5516+
5517+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
5518+{
5519+ switch (lsc) {
5520+ case AuLsc_DI_CHILD:
5521+ ii_write_lock_child(inode);
5522+ break;
5523+ case AuLsc_DI_CHILD2:
5524+ ii_write_lock_child2(inode);
5525+ break;
5526+ case AuLsc_DI_CHILD3:
5527+ ii_write_lock_child3(inode);
5528+ break;
5529+ case AuLsc_DI_PARENT:
5530+ ii_write_lock_parent(inode);
5531+ break;
5532+ case AuLsc_DI_PARENT2:
5533+ ii_write_lock_parent2(inode);
5534+ break;
5535+ case AuLsc_DI_PARENT3:
5536+ ii_write_lock_parent3(inode);
5537+ break;
5538+ default:
5539+ BUG();
5540+ }
5541+}
5542+
5543+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
5544+{
5545+ switch (lsc) {
5546+ case AuLsc_DI_CHILD:
5547+ ii_read_lock_child(inode);
5548+ break;
5549+ case AuLsc_DI_CHILD2:
5550+ ii_read_lock_child2(inode);
5551+ break;
5552+ case AuLsc_DI_CHILD3:
5553+ ii_read_lock_child3(inode);
5554+ break;
5555+ case AuLsc_DI_PARENT:
5556+ ii_read_lock_parent(inode);
5557+ break;
5558+ case AuLsc_DI_PARENT2:
5559+ ii_read_lock_parent2(inode);
5560+ break;
5561+ case AuLsc_DI_PARENT3:
5562+ ii_read_lock_parent3(inode);
5563+ break;
5564+ default:
5565+ BUG();
5566+ }
5567+}
5568+
5569+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
5570+{
dece6358 5571+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5572+ if (d->d_inode) {
5573+ if (au_ftest_lock(flags, IW))
5574+ do_ii_write_lock(d->d_inode, lsc);
5575+ else if (au_ftest_lock(flags, IR))
5576+ do_ii_read_lock(d->d_inode, lsc);
5577+ }
5578+}
5579+
5580+void di_read_unlock(struct dentry *d, int flags)
5581+{
5582+ if (d->d_inode) {
5583+ if (au_ftest_lock(flags, IW))
5584+ ii_write_unlock(d->d_inode);
5585+ else if (au_ftest_lock(flags, IR))
5586+ ii_read_unlock(d->d_inode);
5587+ }
dece6358 5588+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 5589+}
5590+
5591+void di_downgrade_lock(struct dentry *d, int flags)
5592+{
1facf9fc 5593+ if (d->d_inode && au_ftest_lock(flags, IR))
5594+ ii_downgrade_lock(d->d_inode);
dece6358 5595+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 5596+}
5597+
5598+void di_write_lock(struct dentry *d, unsigned int lsc)
5599+{
dece6358 5600+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5601+ if (d->d_inode)
5602+ do_ii_write_lock(d->d_inode, lsc);
5603+}
5604+
5605+void di_write_unlock(struct dentry *d)
5606+{
5607+ if (d->d_inode)
5608+ ii_write_unlock(d->d_inode);
dece6358 5609+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 5610+}
5611+
5612+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
5613+{
5614+ AuDebugOn(d1 == d2
5615+ || d1->d_inode == d2->d_inode
5616+ || d1->d_sb != d2->d_sb);
5617+
5618+ if (isdir && au_test_subdir(d1, d2)) {
5619+ di_write_lock_child(d1);
5620+ di_write_lock_child2(d2);
5621+ } else {
5622+ /* there should be no races */
5623+ di_write_lock_child(d2);
5624+ di_write_lock_child2(d1);
5625+ }
5626+}
5627+
5628+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
5629+{
5630+ AuDebugOn(d1 == d2
5631+ || d1->d_inode == d2->d_inode
5632+ || d1->d_sb != d2->d_sb);
5633+
5634+ if (isdir && au_test_subdir(d1, d2)) {
5635+ di_write_lock_parent(d1);
5636+ di_write_lock_parent2(d2);
5637+ } else {
5638+ /* there should be no races */
5639+ di_write_lock_parent(d2);
5640+ di_write_lock_parent2(d1);
5641+ }
5642+}
5643+
5644+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
5645+{
5646+ di_write_unlock(d1);
5647+ if (d1->d_inode == d2->d_inode)
dece6358 5648+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 5649+ else
5650+ di_write_unlock(d2);
5651+}
5652+
5653+/* ---------------------------------------------------------------------- */
5654+
5655+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
5656+{
5657+ struct dentry *d;
5658+
1308ab2a 5659+ DiMustAnyLock(dentry);
5660+
1facf9fc 5661+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
5662+ return NULL;
5663+ AuDebugOn(bindex < 0);
5664+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
5665+ AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
5666+ return d;
5667+}
5668+
5669+aufs_bindex_t au_dbtail(struct dentry *dentry)
5670+{
5671+ aufs_bindex_t bend, bwh;
5672+
5673+ bend = au_dbend(dentry);
5674+ if (0 <= bend) {
5675+ bwh = au_dbwh(dentry);
5676+ if (!bwh)
5677+ return bwh;
5678+ if (0 < bwh && bwh < bend)
5679+ return bwh - 1;
5680+ }
5681+ return bend;
5682+}
5683+
5684+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
5685+{
5686+ aufs_bindex_t bend, bopq;
5687+
5688+ bend = au_dbtail(dentry);
5689+ if (0 <= bend) {
5690+ bopq = au_dbdiropq(dentry);
5691+ if (0 <= bopq && bopq < bend)
5692+ bend = bopq;
5693+ }
5694+ return bend;
5695+}
5696+
5697+/* ---------------------------------------------------------------------- */
5698+
5699+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5700+ struct dentry *h_dentry)
5701+{
5702+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
5703+
1308ab2a 5704+ DiMustWriteLock(dentry);
5705+
4a4d8108 5706+ au_hdput(hd);
1facf9fc 5707+ hd->hd_dentry = h_dentry;
5708+}
5709+
5710+void au_update_digen(struct dentry *dentry)
5711+{
5712+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
5713+ /* smp_mb(); */ /* atomic_set */
5714+}
5715+
5716+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
5717+{
5718+ struct au_dinfo *dinfo;
5719+ struct dentry *h_d;
4a4d8108 5720+ struct au_hdentry *hdp;
1facf9fc 5721+
1308ab2a 5722+ DiMustWriteLock(dentry);
5723+
1facf9fc 5724+ dinfo = au_di(dentry);
5725+ if (!dinfo || dinfo->di_bstart < 0)
5726+ return;
5727+
4a4d8108 5728+ hdp = dinfo->di_hdentry;
1facf9fc 5729+ if (do_put_zero) {
5730+ aufs_bindex_t bindex, bend;
5731+
5732+ bend = dinfo->di_bend;
5733+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 5734+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 5735+ if (h_d && !h_d->d_inode)
5736+ au_set_h_dptr(dentry, bindex, NULL);
5737+ }
5738+ }
5739+
5740+ dinfo->di_bstart = -1;
5741+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 5742+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 5743+ break;
5744+ if (dinfo->di_bstart > dinfo->di_bend) {
5745+ dinfo->di_bstart = -1;
5746+ dinfo->di_bend = -1;
5747+ return;
5748+ }
5749+
5750+ dinfo->di_bend++;
5751+ while (0 <= --dinfo->di_bend)
4a4d8108 5752+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 5753+ break;
5754+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
5755+}
5756+
5757+void au_update_dbstart(struct dentry *dentry)
5758+{
5759+ aufs_bindex_t bindex, bend;
5760+ struct dentry *h_dentry;
5761+
5762+ bend = au_dbend(dentry);
5763+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
5764+ h_dentry = au_h_dptr(dentry, bindex);
5765+ if (!h_dentry)
5766+ continue;
5767+ if (h_dentry->d_inode) {
5768+ au_set_dbstart(dentry, bindex);
5769+ return;
5770+ }
5771+ au_set_h_dptr(dentry, bindex, NULL);
5772+ }
5773+}
5774+
5775+void au_update_dbend(struct dentry *dentry)
5776+{
5777+ aufs_bindex_t bindex, bstart;
5778+ struct dentry *h_dentry;
5779+
5780+ bstart = au_dbstart(dentry);
5781+ for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
5782+ h_dentry = au_h_dptr(dentry, bindex);
5783+ if (!h_dentry)
5784+ continue;
5785+ if (h_dentry->d_inode) {
5786+ au_set_dbend(dentry, bindex);
5787+ return;
5788+ }
5789+ au_set_h_dptr(dentry, bindex, NULL);
5790+ }
5791+}
5792+
5793+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
5794+{
5795+ aufs_bindex_t bindex, bend;
5796+
5797+ bend = au_dbend(dentry);
5798+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
5799+ if (au_h_dptr(dentry, bindex) == h_dentry)
5800+ return bindex;
5801+ return -1;
5802+}
e49829fe
JR
5803--- /dev/null
5804+++ linux-2.6/fs/aufs/dir.c 2010-10-24 15:03:11.000000000 +0200
953406b4 5805@@ -0,0 +1,638 @@
1facf9fc 5806+/*
4a4d8108 5807+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5808+ *
5809+ * This program, aufs is free software; you can redistribute it and/or modify
5810+ * it under the terms of the GNU General Public License as published by
5811+ * the Free Software Foundation; either version 2 of the License, or
5812+ * (at your option) any later version.
dece6358
AM
5813+ *
5814+ * This program is distributed in the hope that it will be useful,
5815+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5816+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5817+ * GNU General Public License for more details.
5818+ *
5819+ * You should have received a copy of the GNU General Public License
5820+ * along with this program; if not, write to the Free Software
5821+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5822+ */
5823+
5824+/*
5825+ * directory operations
5826+ */
5827+
dece6358 5828+#include <linux/file.h>
1facf9fc 5829+#include <linux/fs_stack.h>
5830+#include "aufs.h"
5831+
5832+void au_add_nlink(struct inode *dir, struct inode *h_dir)
5833+{
5834+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5835+
5836+ dir->i_nlink += h_dir->i_nlink - 2;
5837+ if (h_dir->i_nlink < 2)
5838+ dir->i_nlink += 2;
5839+}
5840+
5841+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
5842+{
5843+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5844+
5845+ dir->i_nlink -= h_dir->i_nlink - 2;
5846+ if (h_dir->i_nlink < 2)
5847+ dir->i_nlink -= 2;
5848+}
5849+
1308ab2a 5850+loff_t au_dir_size(struct file *file, struct dentry *dentry)
5851+{
5852+ loff_t sz;
5853+ aufs_bindex_t bindex, bend;
5854+ struct file *h_file;
5855+ struct dentry *h_dentry;
5856+
5857+ sz = 0;
5858+ if (file) {
5859+ AuDebugOn(!file->f_dentry);
5860+ AuDebugOn(!file->f_dentry->d_inode);
5861+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
5862+
4a4d8108 5863+ bend = au_fbend_dir(file);
1308ab2a 5864+ for (bindex = au_fbstart(file);
5865+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5866+ bindex++) {
4a4d8108 5867+ h_file = au_hf_dir(file, bindex);
1308ab2a 5868+ if (h_file
5869+ && h_file->f_dentry
5870+ && h_file->f_dentry->d_inode)
5871+ sz += i_size_read(h_file->f_dentry->d_inode);
5872+ }
5873+ } else {
5874+ AuDebugOn(!dentry);
5875+ AuDebugOn(!dentry->d_inode);
5876+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
5877+
5878+ bend = au_dbtaildir(dentry);
5879+ for (bindex = au_dbstart(dentry);
5880+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5881+ bindex++) {
5882+ h_dentry = au_h_dptr(dentry, bindex);
5883+ if (h_dentry && h_dentry->d_inode)
5884+ sz += i_size_read(h_dentry->d_inode);
5885+ }
5886+ }
5887+ if (sz < KMALLOC_MAX_SIZE)
5888+ sz = roundup_pow_of_two(sz);
5889+ if (sz > KMALLOC_MAX_SIZE)
5890+ sz = KMALLOC_MAX_SIZE;
5891+ else if (sz < NAME_MAX) {
5892+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
5893+ sz = AUFS_RDBLK_DEF;
5894+ }
5895+ return sz;
5896+}
5897+
1facf9fc 5898+/* ---------------------------------------------------------------------- */
5899+
5900+static int reopen_dir(struct file *file)
5901+{
5902+ int err;
5903+ unsigned int flags;
5904+ aufs_bindex_t bindex, btail, bstart;
5905+ struct dentry *dentry, *h_dentry;
5906+ struct file *h_file;
5907+
5908+ /* open all lower dirs */
5909+ dentry = file->f_dentry;
5910+ bstart = au_dbstart(dentry);
5911+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
5912+ au_set_h_fptr(file, bindex, NULL);
5913+ au_set_fbstart(file, bstart);
5914+
5915+ btail = au_dbtaildir(dentry);
4a4d8108 5916+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 5917+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 5918+ au_set_fbend_dir(file, btail);
1facf9fc 5919+
4a4d8108 5920+ flags = vfsub_file_flags(file);
1facf9fc 5921+ for (bindex = bstart; bindex <= btail; bindex++) {
5922+ h_dentry = au_h_dptr(dentry, bindex);
5923+ if (!h_dentry)
5924+ continue;
4a4d8108 5925+ h_file = au_hf_dir(file, bindex);
1facf9fc 5926+ if (h_file)
5927+ continue;
5928+
5929+ h_file = au_h_open(dentry, bindex, flags, file);
5930+ err = PTR_ERR(h_file);
5931+ if (IS_ERR(h_file))
5932+ goto out; /* close all? */
5933+ au_set_h_fptr(file, bindex, h_file);
5934+ }
5935+ au_update_figen(file);
5936+ /* todo: necessary? */
5937+ /* file->f_ra = h_file->f_ra; */
5938+ err = 0;
5939+
4f0767ce 5940+out:
1facf9fc 5941+ return err;
5942+}
5943+
5944+static int do_open_dir(struct file *file, int flags)
5945+{
5946+ int err;
5947+ aufs_bindex_t bindex, btail;
5948+ struct dentry *dentry, *h_dentry;
5949+ struct file *h_file;
5950+
1308ab2a 5951+ FiMustWriteLock(file);
5952+
1facf9fc 5953+ err = 0;
5954+ dentry = file->f_dentry;
1facf9fc 5955+ file->f_version = dentry->d_inode->i_version;
5956+ bindex = au_dbstart(dentry);
5957+ au_set_fbstart(file, bindex);
5958+ btail = au_dbtaildir(dentry);
4a4d8108 5959+ au_set_fbend_dir(file, btail);
1facf9fc 5960+ for (; !err && bindex <= btail; bindex++) {
5961+ h_dentry = au_h_dptr(dentry, bindex);
5962+ if (!h_dentry)
5963+ continue;
5964+
5965+ h_file = au_h_open(dentry, bindex, flags, file);
5966+ if (IS_ERR(h_file)) {
5967+ err = PTR_ERR(h_file);
5968+ break;
5969+ }
5970+ au_set_h_fptr(file, bindex, h_file);
5971+ }
5972+ au_update_figen(file);
5973+ /* todo: necessary? */
5974+ /* file->f_ra = h_file->f_ra; */
5975+ if (!err)
5976+ return 0; /* success */
5977+
5978+ /* close all */
5979+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
5980+ au_set_h_fptr(file, bindex, NULL);
5981+ au_set_fbstart(file, -1);
4a4d8108
AM
5982+ au_set_fbend_dir(file, -1);
5983+
1facf9fc 5984+ return err;
5985+}
5986+
5987+static int aufs_open_dir(struct inode *inode __maybe_unused,
5988+ struct file *file)
5989+{
4a4d8108
AM
5990+ int err;
5991+ struct super_block *sb;
5992+ struct au_fidir *fidir;
5993+
5994+ err = -ENOMEM;
5995+ sb = file->f_dentry->d_sb;
5996+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 5997+ fidir = au_fidir_alloc(sb);
4a4d8108
AM
5998+ if (fidir) {
5999+ err = au_do_open(file, do_open_dir, fidir);
6000+ if (unlikely(err))
6001+ kfree(fidir);
6002+ }
6003+ si_read_unlock(sb);
6004+ return err;
1facf9fc 6005+}
6006+
6007+static int aufs_release_dir(struct inode *inode __maybe_unused,
6008+ struct file *file)
6009+{
6010+ struct au_vdir *vdir_cache;
6011+ struct super_block *sb;
4a4d8108
AM
6012+ struct au_finfo *finfo;
6013+ struct au_fidir *fidir;
6014+ aufs_bindex_t bindex, bend;
1facf9fc 6015+
6016+ sb = file->f_dentry->d_sb;
e49829fe 6017+ au_plink_maint_leave(au_sbi(sb));
4a4d8108
AM
6018+ finfo = au_fi(file);
6019+ fidir = finfo->fi_hdir;
6020+ if (fidir) {
6021+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
6022+ if (vdir_cache)
6023+ au_vdir_free(vdir_cache);
6024+
6025+ bindex = finfo->fi_btop;
6026+ if (bindex >= 0) {
6027+ /*
6028+ * calls fput() instead of filp_close(),
6029+ * since no dnotify or lock for the lower file.
6030+ */
6031+ bend = fidir->fd_bbot;
6032+ for (; bindex <= bend; bindex++)
6033+ au_set_h_fptr(file, bindex, NULL);
6034+ }
6035+ kfree(fidir);
6036+ finfo->fi_hdir = NULL;
1facf9fc 6037+ }
1facf9fc 6038+ au_finfo_fin(file);
1facf9fc 6039+ return 0;
6040+}
6041+
6042+/* ---------------------------------------------------------------------- */
6043+
4a4d8108
AM
6044+static int au_do_flush_dir(struct file *file, fl_owner_t id)
6045+{
6046+ int err;
6047+ aufs_bindex_t bindex, bend;
6048+ struct file *h_file;
6049+
6050+ err = 0;
6051+ bend = au_fbend_dir(file);
6052+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
6053+ h_file = au_hf_dir(file, bindex);
6054+ if (h_file)
6055+ err = vfsub_flush(h_file, id);
6056+ }
6057+ return err;
6058+}
6059+
6060+static int aufs_flush_dir(struct file *file, fl_owner_t id)
6061+{
6062+ return au_do_flush(file, id, au_do_flush_dir);
6063+}
6064+
6065+/* ---------------------------------------------------------------------- */
6066+
1facf9fc 6067+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
6068+{
6069+ int err;
6070+ aufs_bindex_t bend, bindex;
6071+ struct inode *inode;
6072+ struct super_block *sb;
6073+
6074+ err = 0;
6075+ sb = dentry->d_sb;
6076+ inode = dentry->d_inode;
6077+ IMustLock(inode);
6078+ bend = au_dbend(dentry);
6079+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
6080+ struct path h_path;
6081+ struct inode *h_inode;
6082+
6083+ if (au_test_ro(sb, bindex, inode))
6084+ continue;
6085+ h_path.dentry = au_h_dptr(dentry, bindex);
6086+ if (!h_path.dentry)
6087+ continue;
6088+ h_inode = h_path.dentry->d_inode;
6089+ if (!h_inode)
6090+ continue;
6091+
6092+ /* no mnt_want_write() */
6093+ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
6094+ /* todo: inotiry fired? */
6095+ h_path.mnt = au_sbr_mnt(sb, bindex);
6096+ mutex_lock(&h_inode->i_mutex);
6097+ err = filemap_fdatawrite(h_inode->i_mapping);
6098+ AuDebugOn(!h_inode->i_fop);
6099+ if (!err && h_inode->i_fop->fsync)
b752ccd1 6100+ err = h_inode->i_fop->fsync(NULL, datasync);
1facf9fc 6101+ if (!err)
6102+ err = filemap_fdatawrite(h_inode->i_mapping);
6103+ if (!err)
6104+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
6105+ mutex_unlock(&h_inode->i_mutex);
6106+ }
6107+
6108+ return err;
6109+}
6110+
6111+static int au_do_fsync_dir(struct file *file, int datasync)
6112+{
6113+ int err;
6114+ aufs_bindex_t bend, bindex;
6115+ struct file *h_file;
6116+ struct super_block *sb;
6117+ struct inode *inode;
6118+ struct mutex *h_mtx;
6119+
6120+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6121+ if (unlikely(err))
6122+ goto out;
6123+
6124+ sb = file->f_dentry->d_sb;
6125+ inode = file->f_dentry->d_inode;
4a4d8108 6126+ bend = au_fbend_dir(file);
1facf9fc 6127+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 6128+ h_file = au_hf_dir(file, bindex);
1facf9fc 6129+ if (!h_file || au_test_ro(sb, bindex, inode))
6130+ continue;
6131+
b752ccd1 6132+ err = vfs_fsync(h_file, datasync);
1facf9fc 6133+ if (!err) {
6134+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
6135+ mutex_lock(h_mtx);
6136+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
6137+ /*ignore*/
6138+ mutex_unlock(h_mtx);
6139+ }
6140+ }
6141+
4f0767ce 6142+out:
1facf9fc 6143+ return err;
6144+}
6145+
6146+/*
6147+ * @file may be NULL
6148+ */
b752ccd1 6149+static int aufs_fsync_dir(struct file *file, int datasync)
1facf9fc 6150+{
6151+ int err;
b752ccd1 6152+ struct dentry *dentry;
1facf9fc 6153+ struct super_block *sb;
6154+
b752ccd1 6155+ dentry = file->f_dentry;
1facf9fc 6156+ IMustLock(dentry->d_inode);
6157+
6158+ err = 0;
6159+ sb = dentry->d_sb;
6160+ si_noflush_read_lock(sb);
6161+ if (file)
6162+ err = au_do_fsync_dir(file, datasync);
6163+ else {
6164+ di_write_lock_child(dentry);
6165+ err = au_do_fsync_dir_no_file(dentry, datasync);
6166+ }
6167+ au_cpup_attr_timesizes(dentry->d_inode);
6168+ di_write_unlock(dentry);
6169+ if (file)
6170+ fi_write_unlock(file);
6171+
6172+ si_read_unlock(sb);
6173+ return err;
6174+}
6175+
6176+/* ---------------------------------------------------------------------- */
6177+
6178+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
6179+{
6180+ int err;
6181+ struct dentry *dentry;
6182+ struct inode *inode;
6183+ struct super_block *sb;
6184+
6185+ dentry = file->f_dentry;
6186+ inode = dentry->d_inode;
6187+ IMustLock(inode);
6188+
6189+ sb = dentry->d_sb;
6190+ si_read_lock(sb, AuLock_FLUSH);
6191+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6192+ if (unlikely(err))
6193+ goto out;
6194+ err = au_vdir_init(file);
6195+ di_downgrade_lock(dentry, AuLock_IR);
6196+ if (unlikely(err))
6197+ goto out_unlock;
6198+
b752ccd1 6199+ if (!au_test_nfsd()) {
1facf9fc 6200+ err = au_vdir_fill_de(file, dirent, filldir);
6201+ fsstack_copy_attr_atime(inode,
6202+ au_h_iptr(inode, au_ibstart(inode)));
6203+ } else {
6204+ /*
6205+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
6206+ * encode_fh() and others.
6207+ */
6208+ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
6209+
6210+ di_read_unlock(dentry, AuLock_IR);
6211+ si_read_unlock(sb);
1facf9fc 6212+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 6213+ fsstack_copy_attr_atime(inode, h_inode);
6214+ fi_write_unlock(file);
6215+
6216+ AuTraceErr(err);
6217+ return err;
6218+ }
6219+
4f0767ce 6220+out_unlock:
1facf9fc 6221+ di_read_unlock(dentry, AuLock_IR);
6222+ fi_write_unlock(file);
4f0767ce 6223+out:
1facf9fc 6224+ si_read_unlock(sb);
6225+ return err;
6226+}
6227+
6228+/* ---------------------------------------------------------------------- */
6229+
6230+#define AuTestEmpty_WHONLY 1
dece6358
AM
6231+#define AuTestEmpty_CALLED (1 << 1)
6232+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 6233+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
6234+#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
6235+#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
6236+
dece6358
AM
6237+#ifndef CONFIG_AUFS_SHWH
6238+#undef AuTestEmpty_SHWH
6239+#define AuTestEmpty_SHWH 0
6240+#endif
6241+
1facf9fc 6242+struct test_empty_arg {
1308ab2a 6243+ struct au_nhash *whlist;
1facf9fc 6244+ unsigned int flags;
6245+ int err;
6246+ aufs_bindex_t bindex;
6247+};
6248+
6249+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
6250+ loff_t offset __maybe_unused, u64 ino,
6251+ unsigned int d_type)
1facf9fc 6252+{
6253+ struct test_empty_arg *arg = __arg;
6254+ char *name = (void *)__name;
6255+
6256+ arg->err = 0;
6257+ au_fset_testempty(arg->flags, CALLED);
6258+ /* smp_mb(); */
6259+ if (name[0] == '.'
6260+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
6261+ goto out; /* success */
6262+
6263+ if (namelen <= AUFS_WH_PFX_LEN
6264+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
6265+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 6266+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6267+ arg->err = -ENOTEMPTY;
6268+ goto out;
6269+ }
6270+
6271+ name += AUFS_WH_PFX_LEN;
6272+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 6273+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6274+ arg->err = au_nhash_append_wh
1308ab2a 6275+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 6276+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 6277+
4f0767ce 6278+out:
1facf9fc 6279+ /* smp_mb(); */
6280+ AuTraceErr(arg->err);
6281+ return arg->err;
6282+}
6283+
6284+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6285+{
6286+ int err;
6287+ struct file *h_file;
6288+
6289+ h_file = au_h_open(dentry, arg->bindex,
6290+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
6291+ /*file*/NULL);
6292+ err = PTR_ERR(h_file);
6293+ if (IS_ERR(h_file))
6294+ goto out;
6295+
6296+ err = 0;
6297+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
6298+ && !h_file->f_dentry->d_inode->i_nlink)
6299+ goto out_put;
6300+
6301+ do {
6302+ arg->err = 0;
6303+ au_fclr_testempty(arg->flags, CALLED);
6304+ /* smp_mb(); */
6305+ err = vfsub_readdir(h_file, test_empty_cb, arg);
6306+ if (err >= 0)
6307+ err = arg->err;
6308+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
6309+
4f0767ce 6310+out_put:
1facf9fc 6311+ fput(h_file);
6312+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 6313+out:
1facf9fc 6314+ return err;
6315+}
6316+
6317+struct do_test_empty_args {
6318+ int *errp;
6319+ struct dentry *dentry;
6320+ struct test_empty_arg *arg;
6321+};
6322+
6323+static void call_do_test_empty(void *args)
6324+{
6325+ struct do_test_empty_args *a = args;
6326+ *a->errp = do_test_empty(a->dentry, a->arg);
6327+}
6328+
6329+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6330+{
6331+ int err, wkq_err;
6332+ struct dentry *h_dentry;
6333+ struct inode *h_inode;
6334+
6335+ h_dentry = au_h_dptr(dentry, arg->bindex);
6336+ h_inode = h_dentry->d_inode;
6337+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
6338+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
6339+ mutex_unlock(&h_inode->i_mutex);
6340+ if (!err)
6341+ err = do_test_empty(dentry, arg);
6342+ else {
6343+ struct do_test_empty_args args = {
6344+ .errp = &err,
6345+ .dentry = dentry,
6346+ .arg = arg
6347+ };
6348+ unsigned int flags = arg->flags;
6349+
6350+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
6351+ if (unlikely(wkq_err))
6352+ err = wkq_err;
6353+ arg->flags = flags;
6354+ }
6355+
6356+ return err;
6357+}
6358+
6359+int au_test_empty_lower(struct dentry *dentry)
6360+{
6361+ int err;
1308ab2a 6362+ unsigned int rdhash;
1facf9fc 6363+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 6364+ struct au_nhash whlist;
1facf9fc 6365+ struct test_empty_arg arg;
1facf9fc 6366+
dece6358
AM
6367+ SiMustAnyLock(dentry->d_sb);
6368+
1308ab2a 6369+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
6370+ if (!rdhash)
6371+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
6372+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 6373+ if (unlikely(err))
1facf9fc 6374+ goto out;
6375+
1facf9fc 6376+ arg.flags = 0;
1308ab2a 6377+ arg.whlist = &whlist;
6378+ bstart = au_dbstart(dentry);
dece6358
AM
6379+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6380+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 6381+ arg.bindex = bstart;
6382+ err = do_test_empty(dentry, &arg);
6383+ if (unlikely(err))
6384+ goto out_whlist;
6385+
6386+ au_fset_testempty(arg.flags, WHONLY);
6387+ btail = au_dbtaildir(dentry);
6388+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
6389+ struct dentry *h_dentry;
6390+
6391+ h_dentry = au_h_dptr(dentry, bindex);
6392+ if (h_dentry && h_dentry->d_inode) {
6393+ arg.bindex = bindex;
6394+ err = do_test_empty(dentry, &arg);
6395+ }
6396+ }
6397+
4f0767ce 6398+out_whlist:
1308ab2a 6399+ au_nhash_wh_free(&whlist);
4f0767ce 6400+out:
1facf9fc 6401+ return err;
6402+}
6403+
6404+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
6405+{
6406+ int err;
6407+ struct test_empty_arg arg;
6408+ aufs_bindex_t bindex, btail;
6409+
6410+ err = 0;
1308ab2a 6411+ arg.whlist = whlist;
1facf9fc 6412+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
6413+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6414+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 6415+ btail = au_dbtaildir(dentry);
6416+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
6417+ struct dentry *h_dentry;
6418+
6419+ h_dentry = au_h_dptr(dentry, bindex);
6420+ if (h_dentry && h_dentry->d_inode) {
6421+ arg.bindex = bindex;
6422+ err = sio_test_empty(dentry, &arg);
6423+ }
6424+ }
6425+
6426+ return err;
6427+}
6428+
6429+/* ---------------------------------------------------------------------- */
6430+
6431+const struct file_operations aufs_dir_fop = {
4a4d8108 6432+ .owner = THIS_MODULE,
1facf9fc 6433+ .read = generic_read_dir,
6434+ .readdir = aufs_readdir,
6435+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
6436+#ifdef CONFIG_COMPAT
6437+ .compat_ioctl = aufs_compat_ioctl_dir,
6438+#endif
1facf9fc 6439+ .open = aufs_open_dir,
6440+ .release = aufs_release_dir,
4a4d8108 6441+ .flush = aufs_flush_dir,
1facf9fc 6442+ .fsync = aufs_fsync_dir
6443+};
e49829fe
JR
6444--- /dev/null
6445+++ linux-2.6/fs/aufs/dir.h 2010-10-24 11:19:23.000000000 +0200
b752ccd1 6446@@ -0,0 +1,138 @@
1facf9fc 6447+/*
4a4d8108 6448+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 6449+ *
6450+ * This program, aufs is free software; you can redistribute it and/or modify
6451+ * it under the terms of the GNU General Public License as published by
6452+ * the Free Software Foundation; either version 2 of the License, or
6453+ * (at your option) any later version.
dece6358
AM
6454+ *
6455+ * This program is distributed in the hope that it will be useful,
6456+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6457+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6458+ * GNU General Public License for more details.
6459+ *
6460+ * You should have received a copy of the GNU General Public License
6461+ * along with this program; if not, write to the Free Software
6462+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6463+ */
6464+
6465+/*
6466+ * directory operations
6467+ */
6468+
6469+#ifndef __AUFS_DIR_H__
6470+#define __AUFS_DIR_H__
6471+
6472+#ifdef __KERNEL__
6473+
6474+#include <linux/fs.h>
6475+#include <linux/aufs_type.h>
6476+
6477+/* ---------------------------------------------------------------------- */
6478+
6479+/* need to be faster and smaller */
6480+
6481+struct au_nhash {
dece6358
AM
6482+ unsigned int nh_num;
6483+ struct hlist_head *nh_head;
1facf9fc 6484+};
6485+
6486+struct au_vdir_destr {
6487+ unsigned char len;
6488+ unsigned char name[0];
6489+} __packed;
6490+
6491+struct au_vdir_dehstr {
6492+ struct hlist_node hash;
6493+ struct au_vdir_destr *str;
4a4d8108 6494+} ____cacheline_aligned_in_smp;
1facf9fc 6495+
6496+struct au_vdir_de {
6497+ ino_t de_ino;
6498+ unsigned char de_type;
6499+ /* caution: packed */
6500+ struct au_vdir_destr de_str;
6501+} __packed;
6502+
6503+struct au_vdir_wh {
6504+ struct hlist_node wh_hash;
dece6358
AM
6505+#ifdef CONFIG_AUFS_SHWH
6506+ ino_t wh_ino;
1facf9fc 6507+ aufs_bindex_t wh_bindex;
dece6358
AM
6508+ unsigned char wh_type;
6509+#else
6510+ aufs_bindex_t wh_bindex;
6511+#endif
6512+ /* caution: packed */
1facf9fc 6513+ struct au_vdir_destr wh_str;
6514+} __packed;
6515+
6516+union au_vdir_deblk_p {
6517+ unsigned char *deblk;
6518+ struct au_vdir_de *de;
6519+};
6520+
6521+struct au_vdir {
6522+ unsigned char **vd_deblk;
6523+ unsigned long vd_nblk;
1facf9fc 6524+ struct {
6525+ unsigned long ul;
6526+ union au_vdir_deblk_p p;
6527+ } vd_last;
6528+
6529+ unsigned long vd_version;
dece6358 6530+ unsigned int vd_deblk_sz;
1facf9fc 6531+ unsigned long vd_jiffy;
4a4d8108 6532+} ____cacheline_aligned_in_smp;
1facf9fc 6533+
6534+/* ---------------------------------------------------------------------- */
6535+
6536+/* dir.c */
6537+extern const struct file_operations aufs_dir_fop;
6538+void au_add_nlink(struct inode *dir, struct inode *h_dir);
6539+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 6540+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 6541+int au_test_empty_lower(struct dentry *dentry);
6542+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
6543+
6544+/* vdir.c */
1308ab2a 6545+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
6546+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
6547+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 6548+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
6549+ int limit);
dece6358
AM
6550+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
6551+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
6552+ unsigned int d_type, aufs_bindex_t bindex,
6553+ unsigned char shwh);
1facf9fc 6554+void au_vdir_free(struct au_vdir *vdir);
6555+int au_vdir_init(struct file *file);
6556+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
6557+
6558+/* ioctl.c */
6559+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
6560+
1308ab2a 6561+#ifdef CONFIG_AUFS_RDU
6562+/* rdu.c */
6563+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
6564+#ifdef CONFIG_COMPAT
6565+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6566+ unsigned long arg);
6567+#endif
1308ab2a 6568+#else
6569+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
6570+ unsigned long arg)
6571+{
6572+ return -EINVAL;
6573+}
b752ccd1
AM
6574+#ifdef CONFIG_COMPAT
6575+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6576+ unsigned long arg)
6577+{
6578+ return -EINVAL;
6579+}
6580+#endif
1308ab2a 6581+#endif
6582+
1facf9fc 6583+#endif /* __KERNEL__ */
6584+#endif /* __AUFS_DIR_H__ */
e49829fe
JR
6585--- /dev/null
6586+++ linux-2.6/fs/aufs/dynop.c 2010-10-24 11:19:23.000000000 +0200
b752ccd1 6587@@ -0,0 +1,425 @@
1facf9fc 6588+/*
4a4d8108 6589+ * Copyright (C) 2010 Junjiro R. Okajima
1facf9fc 6590+ *
6591+ * This program, aufs is free software; you can redistribute it and/or modify
6592+ * it under the terms of the GNU General Public License as published by
6593+ * the Free Software Foundation; either version 2 of the License, or
6594+ * (at your option) any later version.
dece6358
AM
6595+ *
6596+ * This program is distributed in the hope that it will be useful,
6597+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6598+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6599+ * GNU General Public License for more details.
6600+ *
6601+ * You should have received a copy of the GNU General Public License
6602+ * along with this program; if not, write to the Free Software
6603+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6604+ */
6605+
6606+/*
4a4d8108 6607+ * dynamically customizable operations for regular files
1facf9fc 6608+ */
6609+
1facf9fc 6610+#include "aufs.h"
6611+
4a4d8108 6612+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 6613+
4a4d8108
AM
6614+/*
6615+ * How large will these lists be?
6616+ * Usually just a few elements, 20-30 at most for each, I guess.
6617+ */
6618+static struct au_splhead dynop[AuDyLast];
6619+
6620+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 6621+{
4a4d8108
AM
6622+ struct au_dykey *key, *tmp;
6623+ struct list_head *head;
1facf9fc 6624+
4a4d8108
AM
6625+ key = NULL;
6626+ head = &spl->head;
6627+ rcu_read_lock();
6628+ list_for_each_entry_rcu(tmp, head, dk_list)
6629+ if (tmp->dk_op.dy_hop == h_op) {
6630+ key = tmp;
6631+ kref_get(&key->dk_kref);
6632+ break;
6633+ }
6634+ rcu_read_unlock();
6635+
6636+ return key;
1facf9fc 6637+}
6638+
4a4d8108 6639+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 6640+{
4a4d8108
AM
6641+ struct au_dykey **k, *found;
6642+ const void *h_op = key->dk_op.dy_hop;
6643+ int i;
1facf9fc 6644+
4a4d8108
AM
6645+ found = NULL;
6646+ k = br->br_dykey;
6647+ for (i = 0; i < AuBrDynOp; i++)
6648+ if (k[i]) {
6649+ if (k[i]->dk_op.dy_hop == h_op) {
6650+ found = k[i];
6651+ break;
6652+ }
6653+ } else
6654+ break;
6655+ if (!found) {
6656+ spin_lock(&br->br_dykey_lock);
6657+ for (; i < AuBrDynOp; i++)
6658+ if (k[i]) {
6659+ if (k[i]->dk_op.dy_hop == h_op) {
6660+ found = k[i];
6661+ break;
6662+ }
6663+ } else {
6664+ k[i] = key;
6665+ break;
6666+ }
6667+ spin_unlock(&br->br_dykey_lock);
6668+ BUG_ON(i == AuBrDynOp); /* expand the array */
6669+ }
6670+
6671+ return found;
1facf9fc 6672+}
6673+
4a4d8108
AM
6674+/* kref_get() if @key is already added */
6675+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
6676+{
6677+ struct au_dykey *tmp, *found;
6678+ struct list_head *head;
6679+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 6680+
4a4d8108
AM
6681+ found = NULL;
6682+ head = &spl->head;
6683+ spin_lock(&spl->spin);
6684+ list_for_each_entry(tmp, head, dk_list)
6685+ if (tmp->dk_op.dy_hop == h_op) {
6686+ kref_get(&tmp->dk_kref);
6687+ found = tmp;
6688+ break;
6689+ }
6690+ if (!found)
6691+ list_add_rcu(&key->dk_list, head);
6692+ spin_unlock(&spl->spin);
1facf9fc 6693+
4a4d8108
AM
6694+ if (!found)
6695+ DyPrSym(key);
6696+ return found;
6697+}
6698+
6699+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 6700+{
4a4d8108
AM
6701+ struct au_dykey *key;
6702+
6703+ key = container_of(rcu, struct au_dykey, dk_rcu);
6704+ DyPrSym(key);
6705+ kfree(key);
1facf9fc 6706+}
6707+
4a4d8108
AM
6708+static void dy_free(struct kref *kref)
6709+{
6710+ struct au_dykey *key;
6711+ struct au_splhead *spl;
1facf9fc 6712+
4a4d8108
AM
6713+ key = container_of(kref, struct au_dykey, dk_kref);
6714+ spl = dynop + key->dk_op.dy_type;
6715+ au_spl_del_rcu(&key->dk_list, spl);
6716+ call_rcu(&key->dk_rcu, dy_free_rcu);
6717+}
6718+
6719+void au_dy_put(struct au_dykey *key)
1facf9fc 6720+{
4a4d8108
AM
6721+ kref_put(&key->dk_kref, dy_free);
6722+}
1facf9fc 6723+
4a4d8108
AM
6724+/* ---------------------------------------------------------------------- */
6725+
6726+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
6727+
6728+#ifdef CONFIG_AUFS_DEBUG
6729+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 6730+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
6731+#else
6732+#define DyDbgDeclare(cnt) do {} while (0)
6733+#define DyDbgInc(cnt) do {} while (0)
6734+#endif
6735+
6736+#define DySet(func, dst, src, h_op, h_sb) do { \
6737+ DyDbgInc(cnt); \
6738+ if (h_op->func) { \
6739+ if (src.func) \
6740+ dst.func = src.func; \
6741+ else \
6742+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
6743+ } \
6744+} while (0)
6745+
6746+#define DySetForce(func, dst, src) do { \
6747+ AuDebugOn(!src.func); \
6748+ DyDbgInc(cnt); \
6749+ dst.func = src.func; \
6750+} while (0)
6751+
6752+#define DySetAop(func) \
6753+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
6754+#define DySetAopForce(func) \
6755+ DySetForce(func, dyaop->da_op, aufs_aop)
6756+
6757+static void dy_aop(struct au_dykey *key, const void *h_op,
6758+ struct super_block *h_sb __maybe_unused)
6759+{
6760+ struct au_dyaop *dyaop = (void *)key;
6761+ const struct address_space_operations *h_aop = h_op;
6762+ DyDbgDeclare(cnt);
6763+
6764+ AuDbg("%s\n", au_sbtype(h_sb));
6765+
6766+ DySetAop(writepage);
6767+ DySetAopForce(readpage); /* force */
6768+ DySetAop(sync_page);
6769+ DySetAop(writepages);
6770+ DySetAop(set_page_dirty);
6771+ DySetAop(readpages);
6772+ DySetAop(write_begin);
6773+ DySetAop(write_end);
6774+ DySetAop(bmap);
6775+ DySetAop(invalidatepage);
6776+ DySetAop(releasepage);
6777+ /* these two will be changed according to an aufs mount option */
6778+ DySetAop(direct_IO);
6779+ DySetAop(get_xip_mem);
6780+ DySetAop(migratepage);
6781+ DySetAop(launder_page);
6782+ DySetAop(is_partially_uptodate);
6783+ DySetAop(error_remove_page);
6784+
6785+ DyDbgSize(cnt, *h_aop);
6786+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
6787+}
6788+
6789+#define DySetVmop(func) \
6790+ DySet(func, dyvmop->dv_op, aufs_vm_ops, h_vmop, h_sb)
6791+#define DySetVmopForce(func) \
6792+ DySetForce(func, dyvmop->dv_op, aufs_vm_ops)
6793+
6794+static void dy_vmop(struct au_dykey *key, const void *h_op,
6795+ struct super_block *h_sb __maybe_unused)
6796+{
6797+ struct au_dyvmop *dyvmop = (void *)key;
6798+ const struct vm_operations_struct *h_vmop = h_op;
6799+ DyDbgDeclare(cnt);
6800+
6801+ AuDbg("%s\n", au_sbtype(h_sb));
6802+
6803+ DySetVmop(open);
6804+ DySetVmop(close);
6805+ DySetVmop(fault);
6806+ DySetVmop(page_mkwrite);
6807+ DySetVmop(access);
6808+#ifdef CONFIG_NUMA
6809+ DySetVmop(set_policy);
6810+ DySetVmop(get_policy);
6811+ DySetVmop(migrate);
6812+#endif
6813+
6814+ DyDbgSize(cnt, *h_vmop);
6815+}
6816+
6817+/* ---------------------------------------------------------------------- */
6818+
6819+static void dy_bug(struct kref *kref)
6820+{
6821+ BUG();
6822+}
6823+
6824+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
6825+{
6826+ struct au_dykey *key, *old;
6827+ struct au_splhead *spl;
b752ccd1 6828+ struct op {
4a4d8108 6829+ unsigned int sz;
b752ccd1
AM
6830+ void (*set)(struct au_dykey *key, const void *h_op,
6831+ struct super_block *h_sb __maybe_unused);
6832+ };
6833+ static const struct op a[] = {
4a4d8108
AM
6834+ [AuDy_AOP] = {
6835+ .sz = sizeof(struct au_dyaop),
b752ccd1 6836+ .set = dy_aop
4a4d8108
AM
6837+ },
6838+ [AuDy_VMOP] = {
6839+ .sz = sizeof(struct au_dyvmop),
b752ccd1 6840+ .set = dy_vmop
4a4d8108 6841+ }
b752ccd1
AM
6842+ };
6843+ const struct op *p;
4a4d8108
AM
6844+
6845+ spl = dynop + op->dy_type;
6846+ key = dy_gfind_get(spl, op->dy_hop);
6847+ if (key)
6848+ goto out_add; /* success */
6849+
6850+ p = a + op->dy_type;
6851+ key = kzalloc(p->sz, GFP_NOFS);
6852+ if (unlikely(!key)) {
6853+ key = ERR_PTR(-ENOMEM);
6854+ goto out;
6855+ }
6856+
6857+ key->dk_op.dy_hop = op->dy_hop;
6858+ kref_init(&key->dk_kref);
b752ccd1 6859+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
6860+ old = dy_gadd(spl, key);
6861+ if (old) {
6862+ kfree(key);
6863+ key = old;
6864+ }
6865+
6866+out_add:
6867+ old = dy_bradd(br, key);
6868+ if (old)
6869+ /* its ref-count should never be zero here */
6870+ kref_put(&key->dk_kref, dy_bug);
6871+out:
6872+ return key;
6873+}
6874+
6875+/* ---------------------------------------------------------------------- */
6876+/*
6877+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
6878+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
6879+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
6880+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
6881+ * See the aufs manual in detail.
6882+ *
6883+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
6884+ * performance of fadvise() and madvise() may be affected.
6885+ */
6886+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
6887+{
6888+ if (!do_dx) {
6889+ dyaop->da_op.direct_IO = NULL;
6890+ dyaop->da_op.get_xip_mem = NULL;
6891+ } else {
6892+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
6893+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
6894+ if (!dyaop->da_get_xip_mem)
6895+ dyaop->da_op.get_xip_mem = NULL;
6896+ }
6897+}
6898+
6899+static struct au_dyaop *dy_aget(struct au_branch *br,
6900+ const struct address_space_operations *h_aop,
6901+ int do_dx)
6902+{
6903+ struct au_dyaop *dyaop;
6904+ struct au_dynop op;
6905+
6906+ op.dy_type = AuDy_AOP;
6907+ op.dy_haop = h_aop;
6908+ dyaop = (void *)dy_get(&op, br);
6909+ if (IS_ERR(dyaop))
6910+ goto out;
6911+ dy_adx(dyaop, do_dx);
6912+
6913+out:
6914+ return dyaop;
6915+}
6916+
6917+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
6918+ struct inode *h_inode)
6919+{
6920+ int err, do_dx;
6921+ struct super_block *sb;
6922+ struct au_branch *br;
6923+ struct au_dyaop *dyaop;
6924+
6925+ AuDebugOn(!S_ISREG(h_inode->i_mode));
6926+ IiMustWriteLock(inode);
6927+
6928+ sb = inode->i_sb;
6929+ br = au_sbr(sb, bindex);
6930+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
6931+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
6932+ err = PTR_ERR(dyaop);
6933+ if (IS_ERR(dyaop))
6934+ /* unnecessary to call dy_fput() */
6935+ goto out;
6936+
6937+ err = 0;
6938+ inode->i_mapping->a_ops = &dyaop->da_op;
6939+
6940+out:
6941+ return err;
6942+}
6943+
b752ccd1
AM
6944+/*
6945+ * Is it safe to replace a_ops during the inode/file is in operation?
6946+ * Yes, I hope so.
6947+ */
6948+int au_dy_irefresh(struct inode *inode)
6949+{
6950+ int err;
6951+ aufs_bindex_t bstart;
6952+ struct inode *h_inode;
6953+
6954+ err = 0;
6955+ if (S_ISREG(inode->i_mode)) {
6956+ bstart = au_ibstart(inode);
6957+ h_inode = au_h_iptr(inode, bstart);
6958+ err = au_dy_iaop(inode, bstart, h_inode);
6959+ }
6960+ return err;
6961+}
6962+
4a4d8108
AM
6963+void au_dy_arefresh(int do_dx)
6964+{
6965+ struct au_splhead *spl;
6966+ struct list_head *head;
6967+ struct au_dykey *key;
6968+
6969+ spl = dynop + AuDy_AOP;
6970+ head = &spl->head;
6971+ spin_lock(&spl->spin);
6972+ list_for_each_entry(key, head, dk_list)
6973+ dy_adx((void *)key, do_dx);
6974+ spin_unlock(&spl->spin);
6975+}
6976+
6977+const struct vm_operations_struct *
6978+au_dy_vmop(struct file *file, struct au_branch *br,
6979+ const struct vm_operations_struct *h_vmop)
6980+{
6981+ struct au_dyvmop *dyvmop;
6982+ struct au_dynop op;
6983+
6984+ op.dy_type = AuDy_VMOP;
6985+ op.dy_hvmop = h_vmop;
6986+ dyvmop = (void *)dy_get(&op, br);
6987+ if (IS_ERR(dyvmop))
6988+ return (void *)dyvmop;
6989+ return &dyvmop->dv_op;
6990+}
6991+
6992+/* ---------------------------------------------------------------------- */
6993+
6994+void __init au_dy_init(void)
6995+{
6996+ int i;
6997+
6998+ /* make sure that 'struct au_dykey *' can be any type */
6999+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
7000+ BUILD_BUG_ON(offsetof(struct au_dyvmop, dv_key));
7001+
7002+ for (i = 0; i < AuDyLast; i++)
7003+ au_spl_init(dynop + i);
7004+}
7005+
7006+void au_dy_fin(void)
7007+{
7008+ int i;
7009+
7010+ for (i = 0; i < AuDyLast; i++)
7011+ WARN_ON(!list_empty(&dynop[i].head));
7012+}
e49829fe
JR
7013--- /dev/null
7014+++ linux-2.6/fs/aufs/dynop.h 2010-10-24 11:19:23.000000000 +0200
b752ccd1 7015@@ -0,0 +1,89 @@
4a4d8108
AM
7016+/*
7017+ * Copyright (C) 2010 Junjiro R. Okajima
7018+ *
7019+ * This program, aufs is free software; you can redistribute it and/or modify
7020+ * it under the terms of the GNU General Public License as published by
7021+ * the Free Software Foundation; either version 2 of the License, or
7022+ * (at your option) any later version.
7023+ *
7024+ * This program is distributed in the hope that it will be useful,
7025+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7026+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7027+ * GNU General Public License for more details.
7028+ *
7029+ * You should have received a copy of the GNU General Public License
7030+ * along with this program; if not, write to the Free Software
7031+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7032+ */
7033+
7034+/*
7035+ * dynamically customizable operations (for regular files only)
7036+ */
7037+
7038+#ifndef __AUFS_DYNOP_H__
7039+#define __AUFS_DYNOP_H__
7040+
7041+#ifdef __KERNEL__
7042+
7043+#include <linux/fs.h>
7044+#include <linux/mm.h>
7045+#include <linux/rcupdate.h>
7046+#include <linux/aufs_type.h>
7047+#include "inode.h"
7048+
7049+enum {AuDy_AOP, AuDy_VMOP, AuDyLast};
7050+
7051+struct au_dynop {
7052+ int dy_type;
7053+ union {
7054+ const void *dy_hop;
7055+ const struct address_space_operations *dy_haop;
7056+ const struct vm_operations_struct *dy_hvmop;
7057+ };
7058+};
7059+
7060+struct au_dykey {
7061+ union {
7062+ struct list_head dk_list;
7063+ struct rcu_head dk_rcu;
7064+ };
7065+ struct au_dynop dk_op;
7066+
7067+ /*
7068+ * during I am in the branch local array, kref is gotten. when the
7069+ * branch is removed, kref is put.
7070+ */
7071+ struct kref dk_kref;
7072+};
7073+
7074+/* stop unioning since their sizes are very different from each other */
7075+struct au_dyaop {
7076+ struct au_dykey da_key;
7077+ struct address_space_operations da_op; /* not const */
7078+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
7079+ void **, unsigned long *);
7080+};
7081+
7082+struct au_dyvmop {
7083+ struct au_dykey dv_key;
7084+ struct vm_operations_struct dv_op; /* not const */
7085+};
7086+
7087+/* ---------------------------------------------------------------------- */
7088+
7089+/* dynop.c */
7090+struct au_branch;
7091+void au_dy_put(struct au_dykey *key);
7092+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
7093+ struct inode *h_inode);
b752ccd1 7094+int au_dy_irefresh(struct inode *inode);
4a4d8108
AM
7095+void au_dy_arefresh(int do_dio);
7096+const struct vm_operations_struct *
7097+au_dy_vmop(struct file *file, struct au_branch *br,
7098+ const struct vm_operations_struct *h_vmop);
7099+
7100+void __init au_dy_init(void);
7101+void au_dy_fin(void);
7102+
4a4d8108
AM
7103+#endif /* __KERNEL__ */
7104+#endif /* __AUFS_DYNOP_H__ */
e49829fe
JR
7105--- /dev/null
7106+++ linux-2.6/fs/aufs/export.c 2010-10-24 11:34:10.000000000 +0200
b752ccd1 7107@@ -0,0 +1,788 @@
4a4d8108
AM
7108+/*
7109+ * Copyright (C) 2005-2010 Junjiro R. Okajima
7110+ *
7111+ * This program, aufs is free software; you can redistribute it and/or modify
7112+ * it under the terms of the GNU General Public License as published by
7113+ * the Free Software Foundation; either version 2 of the License, or
7114+ * (at your option) any later version.
7115+ *
7116+ * This program is distributed in the hope that it will be useful,
7117+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7118+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7119+ * GNU General Public License for more details.
7120+ *
7121+ * You should have received a copy of the GNU General Public License
7122+ * along with this program; if not, write to the Free Software
7123+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7124+ */
7125+
7126+/*
7127+ * export via nfs
7128+ */
7129+
7130+#include <linux/exportfs.h>
7131+#include <linux/file.h>
7132+#include <linux/mnt_namespace.h>
7133+#include <linux/namei.h>
7134+#include <linux/nsproxy.h>
7135+#include <linux/random.h>
7136+#include <linux/writeback.h>
7137+#include "aufs.h"
7138+
7139+union conv {
7140+#ifdef CONFIG_AUFS_INO_T_64
7141+ __u32 a[2];
7142+#else
7143+ __u32 a[1];
7144+#endif
7145+ ino_t ino;
7146+};
7147+
7148+static ino_t decode_ino(__u32 *a)
7149+{
7150+ union conv u;
7151+
7152+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
7153+ u.a[0] = a[0];
7154+#ifdef CONFIG_AUFS_INO_T_64
7155+ u.a[1] = a[1];
7156+#endif
7157+ return u.ino;
7158+}
7159+
7160+static void encode_ino(__u32 *a, ino_t ino)
7161+{
7162+ union conv u;
7163+
7164+ u.ino = ino;
7165+ a[0] = u.a[0];
7166+#ifdef CONFIG_AUFS_INO_T_64
7167+ a[1] = u.a[1];
7168+#endif
7169+}
7170+
7171+/* NFS file handle */
7172+enum {
7173+ Fh_br_id,
7174+ Fh_sigen,
7175+#ifdef CONFIG_AUFS_INO_T_64
7176+ /* support 64bit inode number */
7177+ Fh_ino1,
7178+ Fh_ino2,
7179+ Fh_dir_ino1,
7180+ Fh_dir_ino2,
7181+#else
7182+ Fh_ino1,
7183+ Fh_dir_ino1,
7184+#endif
7185+ Fh_igen,
7186+ Fh_h_type,
7187+ Fh_tail,
7188+
7189+ Fh_ino = Fh_ino1,
7190+ Fh_dir_ino = Fh_dir_ino1
7191+};
7192+
7193+static int au_test_anon(struct dentry *dentry)
7194+{
7195+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
7196+}
7197+
7198+/* ---------------------------------------------------------------------- */
7199+/* inode generation external table */
7200+
b752ccd1 7201+void au_xigen_inc(struct inode *inode)
4a4d8108 7202+{
4a4d8108
AM
7203+ loff_t pos;
7204+ ssize_t sz;
7205+ __u32 igen;
7206+ struct super_block *sb;
7207+ struct au_sbinfo *sbinfo;
7208+
4a4d8108 7209+ sb = inode->i_sb;
b752ccd1 7210+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 7211+
b752ccd1 7212+ sbinfo = au_sbi(sb);
1facf9fc 7213+ pos = inode->i_ino;
7214+ pos *= sizeof(igen);
7215+ igen = inode->i_generation + 1;
1facf9fc 7216+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
7217+ sizeof(igen), &pos);
7218+ if (sz == sizeof(igen))
b752ccd1 7219+ return; /* success */
1facf9fc 7220+
b752ccd1 7221+ if (unlikely(sz >= 0))
1facf9fc 7222+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 7223+}
7224+
7225+int au_xigen_new(struct inode *inode)
7226+{
7227+ int err;
7228+ loff_t pos;
7229+ ssize_t sz;
7230+ struct super_block *sb;
7231+ struct au_sbinfo *sbinfo;
7232+ struct file *file;
7233+
7234+ err = 0;
7235+ /* todo: dirty, at mount time */
7236+ if (inode->i_ino == AUFS_ROOT_INO)
7237+ goto out;
7238+ sb = inode->i_sb;
dece6358 7239+ SiMustAnyLock(sb);
1facf9fc 7240+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7241+ goto out;
7242+
7243+ err = -EFBIG;
7244+ pos = inode->i_ino;
7245+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
7246+ AuIOErr1("too large i%lld\n", pos);
7247+ goto out;
7248+ }
7249+ pos *= sizeof(inode->i_generation);
7250+
7251+ err = 0;
7252+ sbinfo = au_sbi(sb);
7253+ file = sbinfo->si_xigen;
7254+ BUG_ON(!file);
7255+
7256+ if (i_size_read(file->f_dentry->d_inode)
7257+ < pos + sizeof(inode->i_generation)) {
7258+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
7259+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
7260+ sizeof(inode->i_generation), &pos);
7261+ } else
7262+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
7263+ sizeof(inode->i_generation), &pos);
7264+ if (sz == sizeof(inode->i_generation))
7265+ goto out; /* success */
7266+
7267+ err = sz;
7268+ if (unlikely(sz >= 0)) {
7269+ err = -EIO;
7270+ AuIOErr("xigen error (%zd)\n", sz);
7271+ }
7272+
4f0767ce 7273+out:
1facf9fc 7274+ return err;
7275+}
7276+
7277+int au_xigen_set(struct super_block *sb, struct file *base)
7278+{
7279+ int err;
7280+ struct au_sbinfo *sbinfo;
7281+ struct file *file;
7282+
dece6358
AM
7283+ SiMustWriteLock(sb);
7284+
1facf9fc 7285+ sbinfo = au_sbi(sb);
7286+ file = au_xino_create2(base, sbinfo->si_xigen);
7287+ err = PTR_ERR(file);
7288+ if (IS_ERR(file))
7289+ goto out;
7290+ err = 0;
7291+ if (sbinfo->si_xigen)
7292+ fput(sbinfo->si_xigen);
7293+ sbinfo->si_xigen = file;
7294+
4f0767ce 7295+out:
1facf9fc 7296+ return err;
7297+}
7298+
7299+void au_xigen_clr(struct super_block *sb)
7300+{
7301+ struct au_sbinfo *sbinfo;
7302+
dece6358
AM
7303+ SiMustWriteLock(sb);
7304+
1facf9fc 7305+ sbinfo = au_sbi(sb);
7306+ if (sbinfo->si_xigen) {
7307+ fput(sbinfo->si_xigen);
7308+ sbinfo->si_xigen = NULL;
7309+ }
7310+}
7311+
7312+/* ---------------------------------------------------------------------- */
7313+
7314+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
7315+ ino_t dir_ino)
7316+{
7317+ struct dentry *dentry, *d;
7318+ struct inode *inode;
7319+ unsigned int sigen;
7320+
7321+ dentry = NULL;
7322+ inode = ilookup(sb, ino);
7323+ if (!inode)
7324+ goto out;
7325+
7326+ dentry = ERR_PTR(-ESTALE);
7327+ sigen = au_sigen(sb);
7328+ if (unlikely(is_bad_inode(inode)
7329+ || IS_DEADDIR(inode)
7330+ || sigen != au_iigen(inode)))
7331+ goto out_iput;
7332+
7333+ dentry = NULL;
7334+ if (!dir_ino || S_ISDIR(inode->i_mode))
7335+ dentry = d_find_alias(inode);
7336+ else {
7337+ spin_lock(&dcache_lock);
7338+ list_for_each_entry(d, &inode->i_dentry, d_alias)
7339+ if (!au_test_anon(d)
7340+ && d->d_parent->d_inode->i_ino == dir_ino) {
7341+ dentry = dget_locked(d);
7342+ break;
7343+ }
7344+ spin_unlock(&dcache_lock);
7345+ }
7346+ if (unlikely(dentry && sigen != au_digen(dentry))) {
7347+ dput(dentry);
7348+ dentry = ERR_PTR(-ESTALE);
7349+ }
7350+
4f0767ce 7351+out_iput:
1facf9fc 7352+ iput(inode);
4f0767ce 7353+out:
1facf9fc 7354+ return dentry;
7355+}
7356+
7357+/* ---------------------------------------------------------------------- */
7358+
7359+/* todo: dirty? */
7360+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
7361+
7362+struct au_compare_mnt_args {
7363+ /* input */
7364+ struct super_block *sb;
7365+
7366+ /* output */
7367+ struct vfsmount *mnt;
7368+};
7369+
7370+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
7371+{
7372+ struct au_compare_mnt_args *a = arg;
7373+
7374+ if (mnt->mnt_sb != a->sb)
7375+ return 0;
7376+ a->mnt = mntget(mnt);
7377+ return 1;
7378+}
7379+
1facf9fc 7380+static struct vfsmount *au_mnt_get(struct super_block *sb)
7381+{
4a4d8108
AM
7382+ int err;
7383+ struct au_compare_mnt_args args = {
7384+ .sb = sb
7385+ };
1facf9fc 7386+ struct mnt_namespace *ns;
1facf9fc 7387+
1facf9fc 7388+ /* no get/put ?? */
7389+ AuDebugOn(!current->nsproxy);
7390+ ns = current->nsproxy->mnt_ns;
7391+ AuDebugOn(!ns);
4a4d8108
AM
7392+ err = iterate_mounts(au_compare_mnt, &args, ns->root);
7393+ AuDebugOn(!err);
7394+ AuDebugOn(!args.mnt);
7395+ return args.mnt;
1facf9fc 7396+}
7397+
7398+struct au_nfsd_si_lock {
4a4d8108
AM
7399+ unsigned int sigen;
7400+ aufs_bindex_t br_id;
1facf9fc 7401+ unsigned char force_lock;
7402+};
7403+
7404+static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
7405+ struct au_nfsd_si_lock *nsi_lock)
7406+{
7407+ aufs_bindex_t bindex;
7408+
7409+ si_read_lock(sb, AuLock_FLUSH);
7410+
7411+ /* branch id may be wrapped around */
7412+ bindex = au_br_index(sb, nsi_lock->br_id);
7413+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
7414+ goto out; /* success */
7415+
7416+ if (!nsi_lock->force_lock)
7417+ si_read_unlock(sb);
7418+ bindex = -1;
7419+
4f0767ce 7420+out:
1facf9fc 7421+ return bindex;
7422+}
7423+
7424+struct find_name_by_ino {
7425+ int called, found;
7426+ ino_t ino;
7427+ char *name;
7428+ int namelen;
7429+};
7430+
7431+static int
7432+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
7433+ u64 ino, unsigned int d_type)
7434+{
7435+ struct find_name_by_ino *a = arg;
7436+
7437+ a->called++;
7438+ if (a->ino != ino)
7439+ return 0;
7440+
7441+ memcpy(a->name, name, namelen);
7442+ a->namelen = namelen;
7443+ a->found = 1;
7444+ return 1;
7445+}
7446+
7447+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
7448+ struct au_nfsd_si_lock *nsi_lock)
7449+{
7450+ struct dentry *dentry, *parent;
7451+ struct file *file;
7452+ struct inode *dir;
7453+ struct find_name_by_ino arg;
7454+ int err;
7455+
7456+ parent = path->dentry;
7457+ if (nsi_lock)
7458+ si_read_unlock(parent->d_sb);
4a4d8108 7459+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 7460+ dentry = (void *)file;
7461+ if (IS_ERR(file))
7462+ goto out;
7463+
7464+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 7465+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 7466+ if (unlikely(!arg.name))
7467+ goto out_file;
7468+ arg.ino = ino;
7469+ arg.found = 0;
7470+ do {
7471+ arg.called = 0;
7472+ /* smp_mb(); */
7473+ err = vfsub_readdir(file, find_name_by_ino, &arg);
7474+ } while (!err && !arg.found && arg.called);
7475+ dentry = ERR_PTR(err);
7476+ if (unlikely(err))
7477+ goto out_name;
7478+ dentry = ERR_PTR(-ENOENT);
7479+ if (!arg.found)
7480+ goto out_name;
7481+
7482+ /* do not call au_lkup_one() */
7483+ dir = parent->d_inode;
7484+ mutex_lock(&dir->i_mutex);
7485+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
7486+ mutex_unlock(&dir->i_mutex);
7487+ AuTraceErrPtr(dentry);
7488+ if (IS_ERR(dentry))
7489+ goto out_name;
7490+ AuDebugOn(au_test_anon(dentry));
7491+ if (unlikely(!dentry->d_inode)) {
7492+ dput(dentry);
7493+ dentry = ERR_PTR(-ENOENT);
7494+ }
7495+
4f0767ce 7496+out_name:
1facf9fc 7497+ __putname(arg.name);
4f0767ce 7498+out_file:
1facf9fc 7499+ fput(file);
4f0767ce 7500+out:
1facf9fc 7501+ if (unlikely(nsi_lock
7502+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
7503+ if (!IS_ERR(dentry)) {
7504+ dput(dentry);
7505+ dentry = ERR_PTR(-ESTALE);
7506+ }
7507+ AuTraceErrPtr(dentry);
7508+ return dentry;
7509+}
7510+
7511+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
7512+ ino_t dir_ino,
7513+ struct au_nfsd_si_lock *nsi_lock)
7514+{
7515+ struct dentry *dentry;
7516+ struct path path;
7517+
7518+ if (dir_ino != AUFS_ROOT_INO) {
7519+ path.dentry = decode_by_ino(sb, dir_ino, 0);
7520+ dentry = path.dentry;
7521+ if (!path.dentry || IS_ERR(path.dentry))
7522+ goto out;
7523+ AuDebugOn(au_test_anon(path.dentry));
7524+ } else
7525+ path.dentry = dget(sb->s_root);
7526+
7527+ path.mnt = au_mnt_get(sb);
7528+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
7529+ path_put(&path);
7530+
4f0767ce 7531+out:
1facf9fc 7532+ AuTraceErrPtr(dentry);
7533+ return dentry;
7534+}
7535+
7536+/* ---------------------------------------------------------------------- */
7537+
7538+static int h_acceptable(void *expv, struct dentry *dentry)
7539+{
7540+ return 1;
7541+}
7542+
7543+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
7544+ char *buf, int len, struct super_block *sb)
7545+{
7546+ char *p;
7547+ int n;
7548+ struct path path;
7549+
7550+ p = d_path(h_rootpath, buf, len);
7551+ if (IS_ERR(p))
7552+ goto out;
7553+ n = strlen(p);
7554+
7555+ path.mnt = h_rootpath->mnt;
7556+ path.dentry = h_parent;
7557+ p = d_path(&path, buf, len);
7558+ if (IS_ERR(p))
7559+ goto out;
7560+ if (n != 1)
7561+ p += n;
7562+
7563+ path.mnt = au_mnt_get(sb);
7564+ path.dentry = sb->s_root;
7565+ p = d_path(&path, buf, len - strlen(p));
7566+ mntput(path.mnt);
7567+ if (IS_ERR(p))
7568+ goto out;
7569+ if (n != 1)
7570+ p[strlen(p)] = '/';
7571+
4f0767ce 7572+out:
1facf9fc 7573+ AuTraceErrPtr(p);
7574+ return p;
7575+}
7576+
7577+static
7578+struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
7579+ ino_t ino, __u32 *fh, int fh_len,
7580+ struct au_nfsd_si_lock *nsi_lock)
7581+{
7582+ struct dentry *dentry, *h_parent, *root;
7583+ struct super_block *h_sb;
7584+ char *pathname, *p;
7585+ struct vfsmount *h_mnt;
7586+ struct au_branch *br;
7587+ int err;
7588+ struct path path;
7589+
7590+ br = au_sbr(sb, bindex);
7591+ /* au_br_get(br); */
7592+ h_mnt = br->br_mnt;
7593+ h_sb = h_mnt->mnt_sb;
7594+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
7595+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
7596+ fh_len - Fh_tail, fh[Fh_h_type],
7597+ h_acceptable, /*context*/NULL);
7598+ dentry = h_parent;
7599+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
7600+ AuWarn1("%s decode_fh failed, %ld\n",
7601+ au_sbtype(h_sb), PTR_ERR(h_parent));
7602+ goto out;
7603+ }
7604+ dentry = NULL;
7605+ if (unlikely(au_test_anon(h_parent))) {
7606+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
7607+ au_sbtype(h_sb));
7608+ goto out_h_parent;
7609+ }
7610+
7611+ dentry = ERR_PTR(-ENOMEM);
7612+ pathname = (void *)__get_free_page(GFP_NOFS);
7613+ if (unlikely(!pathname))
7614+ goto out_h_parent;
7615+
7616+ root = sb->s_root;
7617+ path.mnt = h_mnt;
7618+ di_read_lock_parent(root, !AuLock_IR);
7619+ path.dentry = au_h_dptr(root, bindex);
7620+ di_read_unlock(root, !AuLock_IR);
7621+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
7622+ dentry = (void *)p;
7623+ if (IS_ERR(p))
7624+ goto out_pathname;
7625+
7626+ si_read_unlock(sb);
7627+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
7628+ dentry = ERR_PTR(err);
7629+ if (unlikely(err))
7630+ goto out_relock;
7631+
7632+ dentry = ERR_PTR(-ENOENT);
7633+ AuDebugOn(au_test_anon(path.dentry));
7634+ if (unlikely(!path.dentry->d_inode))
7635+ goto out_path;
7636+
7637+ if (ino != path.dentry->d_inode->i_ino)
7638+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
7639+ else
7640+ dentry = dget(path.dentry);
7641+
4f0767ce 7642+out_path:
1facf9fc 7643+ path_put(&path);
4f0767ce 7644+out_relock:
1facf9fc 7645+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
7646+ if (!IS_ERR(dentry)) {
7647+ dput(dentry);
7648+ dentry = ERR_PTR(-ESTALE);
7649+ }
4f0767ce 7650+out_pathname:
1facf9fc 7651+ free_page((unsigned long)pathname);
4f0767ce 7652+out_h_parent:
1facf9fc 7653+ dput(h_parent);
4f0767ce 7654+out:
1facf9fc 7655+ /* au_br_put(br); */
7656+ AuTraceErrPtr(dentry);
7657+ return dentry;
7658+}
7659+
7660+/* ---------------------------------------------------------------------- */
7661+
7662+static struct dentry *
7663+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
7664+ int fh_type)
7665+{
7666+ struct dentry *dentry;
7667+ __u32 *fh = fid->raw;
7668+ ino_t ino, dir_ino;
7669+ aufs_bindex_t bindex;
7670+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 7671+ .force_lock = 0
7672+ };
7673+
1facf9fc 7674+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
7675+ /* it should never happen, but the file handle is unreliable */
7676+ if (unlikely(fh_len < Fh_tail))
7677+ goto out;
7678+ nsi_lock.sigen = fh[Fh_sigen];
7679+ nsi_lock.br_id = fh[Fh_br_id];
7680+
1facf9fc 7681+ /* branch id may be wrapped around */
7682+ bindex = si_nfsd_read_lock(sb, &nsi_lock);
7683+ if (unlikely(bindex < 0))
7684+ goto out;
7685+ nsi_lock.force_lock = 1;
7686+
7687+ /* is this inode still cached? */
7688+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
7689+ /* it should never happen */
7690+ if (unlikely(ino == AUFS_ROOT_INO))
7691+ goto out;
7692+
1facf9fc 7693+ dir_ino = decode_ino(fh + Fh_dir_ino);
7694+ dentry = decode_by_ino(sb, ino, dir_ino);
7695+ if (IS_ERR(dentry))
7696+ goto out_unlock;
7697+ if (dentry)
7698+ goto accept;
7699+
7700+ /* is the parent dir cached? */
7701+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
7702+ if (IS_ERR(dentry))
7703+ goto out_unlock;
7704+ if (dentry)
7705+ goto accept;
7706+
7707+ /* lookup path */
7708+ dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
7709+ if (IS_ERR(dentry))
7710+ goto out_unlock;
7711+ if (unlikely(!dentry))
7712+ /* todo?: make it ESTALE */
7713+ goto out_unlock;
7714+
4f0767ce 7715+accept:
1facf9fc 7716+ if (dentry->d_inode->i_generation == fh[Fh_igen])
7717+ goto out_unlock; /* success */
7718+
7719+ dput(dentry);
7720+ dentry = ERR_PTR(-ESTALE);
4f0767ce 7721+out_unlock:
1facf9fc 7722+ si_read_unlock(sb);
4f0767ce 7723+out:
1facf9fc 7724+ AuTraceErrPtr(dentry);
7725+ return dentry;
7726+}
7727+
7728+#if 0 /* reserved for future use */
7729+/* support subtreecheck option */
7730+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
7731+ int fh_len, int fh_type)
7732+{
7733+ struct dentry *parent;
7734+ __u32 *fh = fid->raw;
7735+ ino_t dir_ino;
7736+
7737+ dir_ino = decode_ino(fh + Fh_dir_ino);
7738+ parent = decode_by_ino(sb, dir_ino, 0);
7739+ if (IS_ERR(parent))
7740+ goto out;
7741+ if (!parent)
7742+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
7743+ dir_ino, fh, fh_len);
7744+
4f0767ce 7745+out:
1facf9fc 7746+ AuTraceErrPtr(parent);
7747+ return parent;
7748+}
7749+#endif
7750+
7751+/* ---------------------------------------------------------------------- */
7752+
7753+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
7754+ int connectable)
7755+{
7756+ int err;
7757+ aufs_bindex_t bindex, bend;
7758+ struct super_block *sb, *h_sb;
7759+ struct inode *inode;
7760+ struct dentry *parent, *h_parent;
7761+ struct au_branch *br;
7762+
7763+ AuDebugOn(au_test_anon(dentry));
7764+
7765+ parent = NULL;
7766+ err = -ENOSPC;
7767+ if (unlikely(*max_len <= Fh_tail)) {
7768+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
7769+ goto out;
7770+ }
7771+
7772+ err = FILEID_ROOT;
7773+ if (IS_ROOT(dentry)) {
7774+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
7775+ goto out;
7776+ }
7777+
7778+ err = -EIO;
7779+ h_parent = NULL;
7780+ sb = dentry->d_sb;
7781+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
7782+ parent = dget_parent(dentry);
7783+ di_read_lock_parent(parent, !AuLock_IR);
7784+ inode = dentry->d_inode;
7785+ AuDebugOn(!inode);
7786+#ifdef CONFIG_AUFS_DEBUG
7787+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7788+ AuWarn1("NFS-exporting requires xino\n");
7789+#endif
7790+
7791+ bend = au_dbtaildir(parent);
7792+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
7793+ h_parent = au_h_dptr(parent, bindex);
7794+ if (h_parent) {
7795+ dget(h_parent);
7796+ break;
7797+ }
7798+ }
7799+ if (unlikely(!h_parent))
7800+ goto out_unlock;
7801+
7802+ err = -EPERM;
7803+ br = au_sbr(sb, bindex);
7804+ h_sb = br->br_mnt->mnt_sb;
7805+ if (unlikely(!h_sb->s_export_op)) {
7806+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
7807+ goto out_dput;
7808+ }
7809+
7810+ fh[Fh_br_id] = br->br_id;
7811+ fh[Fh_sigen] = au_sigen(sb);
7812+ encode_ino(fh + Fh_ino, inode->i_ino);
7813+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
7814+ fh[Fh_igen] = inode->i_generation;
7815+
7816+ *max_len -= Fh_tail;
7817+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
7818+ max_len,
7819+ /*connectable or subtreecheck*/0);
7820+ err = fh[Fh_h_type];
7821+ *max_len += Fh_tail;
7822+ /* todo: macros? */
7823+ if (err != 255)
7824+ err = 99;
7825+ else
7826+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
7827+
4f0767ce 7828+out_dput:
1facf9fc 7829+ dput(h_parent);
4f0767ce 7830+out_unlock:
1facf9fc 7831+ di_read_unlock(parent, !AuLock_IR);
7832+ dput(parent);
7833+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 7834+out:
1facf9fc 7835+ if (unlikely(err < 0))
7836+ err = 255;
7837+ return err;
7838+}
7839+
7840+/* ---------------------------------------------------------------------- */
7841+
4a4d8108
AM
7842+static int aufs_commit_metadata(struct inode *inode)
7843+{
7844+ int err;
7845+ aufs_bindex_t bindex;
7846+ struct super_block *sb;
7847+ struct inode *h_inode;
7848+ int (*f)(struct inode *inode);
7849+
7850+ sb = inode->i_sb;
e49829fe 7851+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
7852+ ii_write_lock_child(inode);
7853+ bindex = au_ibstart(inode);
7854+ AuDebugOn(bindex < 0);
7855+ h_inode = au_h_iptr(inode, bindex);
7856+
7857+ f = h_inode->i_sb->s_export_op->commit_metadata;
7858+ if (f)
7859+ err = f(h_inode);
7860+ else {
7861+ struct writeback_control wbc = {
7862+ .sync_mode = WB_SYNC_ALL,
7863+ .nr_to_write = 0 /* metadata only */
7864+ };
7865+
7866+ err = sync_inode(h_inode, &wbc);
7867+ }
7868+
7869+ au_cpup_attr_timesizes(inode);
7870+ ii_write_unlock(inode);
7871+ si_read_unlock(sb);
7872+ return err;
7873+}
7874+
7875+/* ---------------------------------------------------------------------- */
7876+
1facf9fc 7877+static struct export_operations aufs_export_op = {
4a4d8108 7878+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 7879+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
7880+ .encode_fh = aufs_encode_fh,
7881+ .commit_metadata = aufs_commit_metadata
1facf9fc 7882+};
7883+
7884+void au_export_init(struct super_block *sb)
7885+{
7886+ struct au_sbinfo *sbinfo;
7887+ __u32 u;
7888+
7889+ sb->s_export_op = &aufs_export_op;
7890+ sbinfo = au_sbi(sb);
7891+ sbinfo->si_xigen = NULL;
7892+ get_random_bytes(&u, sizeof(u));
7893+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
7894+ atomic_set(&sbinfo->si_xigen_next, u);
7895+}
e49829fe
JR
7896--- /dev/null
7897+++ linux-2.6/fs/aufs/file.c 2010-10-24 14:50:09.000000000 +0200
4a4d8108 7898@@ -0,0 +1,652 @@
1facf9fc 7899+/*
4a4d8108 7900+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 7901+ *
7902+ * This program, aufs is free software; you can redistribute it and/or modify
7903+ * it under the terms of the GNU General Public License as published by
7904+ * the Free Software Foundation; either version 2 of the License, or
7905+ * (at your option) any later version.
dece6358
AM
7906+ *
7907+ * This program is distributed in the hope that it will be useful,
7908+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7909+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7910+ * GNU General Public License for more details.
7911+ *
7912+ * You should have received a copy of the GNU General Public License
7913+ * along with this program; if not, write to the Free Software
7914+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7915+ */
7916+
7917+/*
4a4d8108 7918+ * handling file/dir, and address_space operation
1facf9fc 7919+ */
7920+
dece6358 7921+#include <linux/file.h>
4a4d8108
AM
7922+#include <linux/fsnotify.h>
7923+#include <linux/namei.h>
7924+#include <linux/pagemap.h>
1facf9fc 7925+#include "aufs.h"
7926+
4a4d8108
AM
7927+/* drop flags for writing */
7928+unsigned int au_file_roflags(unsigned int flags)
7929+{
7930+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
7931+ flags |= O_RDONLY | O_NOATIME;
7932+ return flags;
7933+}
7934+
7935+/* common functions to regular file and dir */
7936+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
7937+ struct file *file)
1facf9fc 7938+{
1308ab2a 7939+ struct file *h_file;
4a4d8108
AM
7940+ struct dentry *h_dentry;
7941+ struct inode *h_inode;
7942+ struct super_block *sb;
7943+ struct au_branch *br;
7944+ struct path h_path;
7945+ int err, exec_flag;
1facf9fc 7946+
4a4d8108
AM
7947+ /* a race condition can happen between open and unlink/rmdir */
7948+ h_file = ERR_PTR(-ENOENT);
7949+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 7950+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
7951+ goto out;
7952+ h_inode = h_dentry->d_inode;
b752ccd1 7953+ if (au_test_nfsd() && !h_inode)
4a4d8108
AM
7954+ goto out;
7955+ if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
7956+ || !h_inode))
7957+ goto out;
1facf9fc 7958+
4a4d8108
AM
7959+ sb = dentry->d_sb;
7960+ br = au_sbr(sb, bindex);
7961+ h_file = ERR_PTR(-EACCES);
7962+ exec_flag = flags & vfsub_fmode_to_uint(FMODE_EXEC);
7963+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
7964+ goto out;
1facf9fc 7965+
4a4d8108
AM
7966+ /* drop flags for writing */
7967+ if (au_test_ro(sb, bindex, dentry->d_inode))
7968+ flags = au_file_roflags(flags);
7969+ flags &= ~O_CREAT;
7970+ atomic_inc(&br->br_count);
7971+ h_path.dentry = h_dentry;
7972+ h_path.mnt = br->br_mnt;
7973+ if (!au_special_file(h_inode->i_mode))
7974+ h_file = vfsub_dentry_open(&h_path, flags);
7975+ else {
7976+ /* this block depends upon the configuration */
7977+ di_read_unlock(dentry, AuLock_IR);
7978+ fi_write_unlock(file);
7979+ si_read_unlock(sb);
7980+ h_file = vfsub_dentry_open(&h_path, flags);
7981+ si_noflush_read_lock(sb);
7982+ fi_write_lock(file);
7983+ di_read_lock_child(dentry, AuLock_IR);
dece6358 7984+ }
4a4d8108
AM
7985+ if (IS_ERR(h_file))
7986+ goto out_br;
dece6358 7987+
4a4d8108
AM
7988+ if (exec_flag) {
7989+ err = deny_write_access(h_file);
7990+ if (unlikely(err)) {
7991+ fput(h_file);
7992+ h_file = ERR_PTR(err);
7993+ goto out_br;
7994+ }
7995+ }
953406b4 7996+ fsnotify_open(h_file);
4a4d8108 7997+ goto out; /* success */
1facf9fc 7998+
4f0767ce 7999+out_br:
4a4d8108 8000+ atomic_dec(&br->br_count);
4f0767ce 8001+out:
4a4d8108
AM
8002+ return h_file;
8003+}
1308ab2a 8004+
4a4d8108
AM
8005+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8006+ struct au_fidir *fidir)
1facf9fc 8007+{
dece6358 8008+ int err;
1facf9fc 8009+ struct dentry *dentry;
1308ab2a 8010+
4a4d8108
AM
8011+ err = au_finfo_init(file, fidir);
8012+ if (unlikely(err))
8013+ goto out;
1facf9fc 8014+
8015+ dentry = file->f_dentry;
4a4d8108
AM
8016+ di_read_lock_child(dentry, AuLock_IR);
8017+ err = open(file, vfsub_file_flags(file));
8018+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 8019+
4a4d8108
AM
8020+ fi_write_unlock(file);
8021+ if (unlikely(err)) {
8022+ au_fi(file)->fi_hdir = NULL;
8023+ au_finfo_fin(file);
1308ab2a 8024+ }
4a4d8108 8025+
4f0767ce 8026+out:
1308ab2a 8027+ return err;
8028+}
dece6358 8029+
4a4d8108 8030+int au_reopen_nondir(struct file *file)
1308ab2a 8031+{
4a4d8108
AM
8032+ int err;
8033+ aufs_bindex_t bstart;
8034+ struct dentry *dentry;
8035+ struct file *h_file, *h_file_tmp;
1308ab2a 8036+
4a4d8108
AM
8037+ dentry = file->f_dentry;
8038+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
8039+ bstart = au_dbstart(dentry);
8040+ h_file_tmp = NULL;
8041+ if (au_fbstart(file) == bstart) {
8042+ h_file = au_hf_top(file);
8043+ if (file->f_mode == h_file->f_mode)
8044+ return 0; /* success */
8045+ h_file_tmp = h_file;
8046+ get_file(h_file_tmp);
8047+ au_set_h_fptr(file, bstart, NULL);
8048+ }
8049+ AuDebugOn(au_fi(file)->fi_hdir);
8050+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 8051+
4a4d8108
AM
8052+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
8053+ file);
8054+ err = PTR_ERR(h_file);
8055+ if (IS_ERR(h_file))
8056+ goto out; /* todo: close all? */
8057+
8058+ err = 0;
8059+ au_set_fbstart(file, bstart);
8060+ au_set_h_fptr(file, bstart, h_file);
8061+ au_update_figen(file);
8062+ /* todo: necessary? */
8063+ /* file->f_ra = h_file->f_ra; */
8064+
4f0767ce 8065+out:
4a4d8108
AM
8066+ if (h_file_tmp)
8067+ fput(h_file_tmp);
8068+ return err;
1facf9fc 8069+}
8070+
1308ab2a 8071+/* ---------------------------------------------------------------------- */
8072+
4a4d8108
AM
8073+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
8074+ struct dentry *hi_wh)
1facf9fc 8075+{
4a4d8108
AM
8076+ int err;
8077+ aufs_bindex_t bstart;
8078+ struct au_dinfo *dinfo;
8079+ struct dentry *h_dentry;
8080+ struct au_hdentry *hdp;
1facf9fc 8081+
4a4d8108
AM
8082+ dinfo = au_di(file->f_dentry);
8083+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 8084+
4a4d8108
AM
8085+ bstart = dinfo->di_bstart;
8086+ dinfo->di_bstart = btgt;
8087+ hdp = dinfo->di_hdentry;
8088+ h_dentry = hdp[0 + btgt].hd_dentry;
8089+ hdp[0 + btgt].hd_dentry = hi_wh;
8090+ err = au_reopen_nondir(file);
8091+ hdp[0 + btgt].hd_dentry = h_dentry;
8092+ dinfo->di_bstart = bstart;
1facf9fc 8093+
1facf9fc 8094+ return err;
8095+}
8096+
4a4d8108
AM
8097+static int au_ready_to_write_wh(struct file *file, loff_t len,
8098+ aufs_bindex_t bcpup)
1facf9fc 8099+{
4a4d8108 8100+ int err;
dece6358 8101+ struct inode *inode;
4a4d8108 8102+ struct dentry *dentry, *hi_wh;
1facf9fc 8103+
dece6358 8104+ dentry = file->f_dentry;
4a4d8108 8105+ au_update_dbstart(dentry);
dece6358 8106+ inode = dentry->d_inode;
4a4d8108
AM
8107+ hi_wh = au_hi_wh(inode, bcpup);
8108+ if (!hi_wh)
8109+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
8110+ else
8111+ /* already copied-up after unlink */
8112+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 8113+
4a4d8108
AM
8114+ if (!err
8115+ && inode->i_nlink > 1
8116+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
8117+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 8118+
dece6358 8119+ return err;
1facf9fc 8120+}
8121+
4a4d8108
AM
8122+/*
8123+ * prepare the @file for writing.
8124+ */
8125+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 8126+{
4a4d8108
AM
8127+ int err;
8128+ aufs_bindex_t bstart, bcpup;
8129+ struct dentry *dentry, *parent, *h_dentry;
8130+ struct inode *h_inode, *inode;
1facf9fc 8131+ struct super_block *sb;
4a4d8108 8132+ struct file *h_file;
1facf9fc 8133+
8134+ dentry = file->f_dentry;
1facf9fc 8135+ sb = dentry->d_sb;
4a4d8108
AM
8136+ inode = dentry->d_inode;
8137+ AuDebugOn(au_special_file(inode->i_mode));
8138+ bstart = au_fbstart(file);
8139+ err = au_test_ro(sb, bstart, inode);
8140+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
8141+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 8142+ goto out;
4a4d8108 8143+ }
1facf9fc 8144+
4a4d8108
AM
8145+ /* need to cpup */
8146+ parent = dget_parent(dentry);
8147+ di_write_lock_parent(parent);
8148+ err = AuWbrCopyup(au_sbi(sb), dentry);
8149+ bcpup = err;
8150+ if (unlikely(err < 0))
8151+ goto out_dgrade;
8152+ err = 0;
8153+
8154+ if (!au_h_dptr(parent, bcpup)) {
8155+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 8156+ if (unlikely(err))
4a4d8108
AM
8157+ goto out_dgrade;
8158+ }
8159+
8160+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
8161+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8162+ if (unlikely(err))
8163+ goto out_dgrade;
8164+
8165+ h_dentry = au_hf_top(file)->f_dentry;
8166+ h_inode = h_dentry->d_inode;
8167+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8168+ h_file = au_h_open_pre(dentry, bstart);
8169+ if (IS_ERR(h_file)) {
8170+ err = PTR_ERR(h_file);
8171+ h_file = NULL;
8172+ } else if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
8173+ /* || !h_inode->i_nlink */) {
8174+ err = au_ready_to_write_wh(file, len, bcpup);
8175+ di_downgrade_lock(parent, AuLock_IR);
8176+ } else {
8177+ di_downgrade_lock(parent, AuLock_IR);
8178+ if (!au_h_dptr(dentry, bcpup))
8179+ err = au_sio_cpup_simple(dentry, bcpup, len,
8180+ AuCpup_DTIME);
8181+ if (!err)
8182+ err = au_reopen_nondir(file);
8183+ }
8184+ mutex_unlock(&h_inode->i_mutex);
8185+ au_h_open_post(dentry, bstart, h_file);
8186+
8187+ if (!err) {
8188+ au_pin_set_parent_lflag(pin, /*lflag*/0);
8189+ goto out_dput; /* success */
8190+ }
8191+ au_unpin(pin);
8192+ goto out_unlock;
1facf9fc 8193+
4f0767ce 8194+out_dgrade:
4a4d8108 8195+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 8196+out_unlock:
4a4d8108 8197+ di_read_unlock(parent, AuLock_IR);
4f0767ce 8198+out_dput:
4a4d8108 8199+ dput(parent);
4f0767ce 8200+out:
1facf9fc 8201+ return err;
8202+}
8203+
4a4d8108
AM
8204+/* ---------------------------------------------------------------------- */
8205+
8206+int au_do_flush(struct file *file, fl_owner_t id,
8207+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 8208+{
4a4d8108 8209+ int err;
1308ab2a 8210+ struct dentry *dentry;
1facf9fc 8211+ struct super_block *sb;
4a4d8108 8212+ struct inode *inode;
1facf9fc 8213+
1facf9fc 8214+ dentry = file->f_dentry;
8215+ sb = dentry->d_sb;
dece6358 8216+ inode = dentry->d_inode;
4a4d8108
AM
8217+ si_noflush_read_lock(sb);
8218+ fi_read_lock(file);
b752ccd1 8219+ ii_read_lock_child(inode);
1facf9fc 8220+
4a4d8108
AM
8221+ err = flush(file, id);
8222+ au_cpup_attr_timesizes(inode);
1facf9fc 8223+
b752ccd1 8224+ ii_read_unlock(inode);
4a4d8108 8225+ fi_read_unlock(file);
1308ab2a 8226+ si_read_unlock(sb);
dece6358 8227+ return err;
1facf9fc 8228+}
8229+
4a4d8108
AM
8230+/* ---------------------------------------------------------------------- */
8231+
8232+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 8233+{
4a4d8108
AM
8234+ int err;
8235+ aufs_bindex_t bstart;
8236+ struct au_pin pin;
8237+ struct au_finfo *finfo;
8238+ struct dentry *dentry, *parent, *hi_wh;
8239+ struct inode *inode;
1facf9fc 8240+ struct super_block *sb;
8241+
4a4d8108
AM
8242+ FiMustWriteLock(file);
8243+
8244+ err = 0;
8245+ finfo = au_fi(file);
1308ab2a 8246+ dentry = file->f_dentry;
8247+ sb = dentry->d_sb;
4a4d8108
AM
8248+ inode = dentry->d_inode;
8249+ bstart = au_ibstart(inode);
8250+ if (bstart == finfo->fi_btop)
1308ab2a 8251+ goto out;
dece6358 8252+
4a4d8108
AM
8253+ parent = dget_parent(dentry);
8254+ if (au_test_ro(sb, bstart, inode)) {
8255+ di_read_lock_parent(parent, !AuLock_IR);
8256+ err = AuWbrCopyup(au_sbi(sb), dentry);
8257+ bstart = err;
8258+ di_read_unlock(parent, !AuLock_IR);
8259+ if (unlikely(err < 0))
8260+ goto out_parent;
8261+ err = 0;
1facf9fc 8262+ }
1facf9fc 8263+
4a4d8108
AM
8264+ di_read_lock_parent(parent, AuLock_IR);
8265+ hi_wh = au_hi_wh(inode, bstart);
8266+ if (au_opt_test(au_mntflags(sb), PLINK)
8267+ && au_plink_test(inode)
8268+ && !d_unhashed(dentry)) {
8269+ err = au_test_and_cpup_dirs(dentry, bstart);
8270+ if (unlikely(err))
8271+ goto out_unlock;
8272+
8273+ /* always superio. */
8274+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
8275+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8276+ if (!err)
8277+ err = au_sio_cpup_simple(dentry, bstart, -1,
8278+ AuCpup_DTIME);
8279+ au_unpin(&pin);
8280+ } else if (hi_wh) {
8281+ /* already copied-up after unlink */
8282+ err = au_reopen_wh(file, bstart, hi_wh);
8283+ *need_reopen = 0;
8284+ }
1facf9fc 8285+
4f0767ce 8286+out_unlock:
4a4d8108 8287+ di_read_unlock(parent, AuLock_IR);
4f0767ce 8288+out_parent:
4a4d8108 8289+ dput(parent);
4f0767ce 8290+out:
1308ab2a 8291+ return err;
dece6358 8292+}
1facf9fc 8293+
4a4d8108 8294+static void au_do_refresh_dir(struct file *file)
dece6358 8295+{
4a4d8108
AM
8296+ aufs_bindex_t bindex, bend, new_bindex, brid;
8297+ struct au_hfile *p, tmp, *q;
8298+ struct au_finfo *finfo;
1308ab2a 8299+ struct super_block *sb;
4a4d8108 8300+ struct au_fidir *fidir;
1facf9fc 8301+
4a4d8108 8302+ FiMustWriteLock(file);
1facf9fc 8303+
4a4d8108
AM
8304+ sb = file->f_dentry->d_sb;
8305+ finfo = au_fi(file);
8306+ fidir = finfo->fi_hdir;
8307+ AuDebugOn(!fidir);
8308+ p = fidir->fd_hfile + finfo->fi_btop;
8309+ brid = p->hf_br->br_id;
8310+ bend = fidir->fd_bbot;
8311+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
8312+ if (!p->hf_file)
8313+ continue;
1308ab2a 8314+
4a4d8108
AM
8315+ new_bindex = au_br_index(sb, p->hf_br->br_id);
8316+ if (new_bindex == bindex)
8317+ continue;
8318+ if (new_bindex < 0) {
8319+ au_set_h_fptr(file, bindex, NULL);
8320+ continue;
8321+ }
1308ab2a 8322+
4a4d8108
AM
8323+ /* swap two lower inode, and loop again */
8324+ q = fidir->fd_hfile + new_bindex;
8325+ tmp = *q;
8326+ *q = *p;
8327+ *p = tmp;
8328+ if (tmp.hf_file) {
8329+ bindex--;
8330+ p--;
8331+ }
8332+ }
1308ab2a 8333+
4a4d8108
AM
8334+ p = fidir->fd_hfile;
8335+ if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
8336+ bend = au_sbend(sb);
8337+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
8338+ finfo->fi_btop++, p++)
8339+ if (p->hf_file) {
8340+ if (p->hf_file->f_dentry
8341+ && p->hf_file->f_dentry->d_inode)
8342+ break;
8343+ else
8344+ au_hfput(p, file);
8345+ }
8346+ } else {
8347+ bend = au_br_index(sb, brid);
8348+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
8349+ finfo->fi_btop++, p++)
8350+ if (p->hf_file)
8351+ au_hfput(p, file);
8352+ bend = au_sbend(sb);
8353+ }
1308ab2a 8354+
4a4d8108
AM
8355+ p = fidir->fd_hfile + bend;
8356+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
8357+ fidir->fd_bbot--, p--)
8358+ if (p->hf_file) {
8359+ if (p->hf_file->f_dentry
8360+ && p->hf_file->f_dentry->d_inode)
8361+ break;
8362+ else
8363+ au_hfput(p, file);
8364+ }
8365+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 8366+}
8367+
4a4d8108
AM
8368+/*
8369+ * after branch manipulating, refresh the file.
8370+ */
8371+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 8372+{
4a4d8108
AM
8373+ int err, need_reopen;
8374+ aufs_bindex_t bend, bindex;
8375+ struct dentry *dentry;
1308ab2a 8376+ struct au_finfo *finfo;
4a4d8108 8377+ struct au_hfile *hfile;
1facf9fc 8378+
4a4d8108 8379+ dentry = file->f_dentry;
1308ab2a 8380+ finfo = au_fi(file);
4a4d8108
AM
8381+ if (!finfo->fi_hdir) {
8382+ hfile = &finfo->fi_htop;
8383+ AuDebugOn(!hfile->hf_file);
8384+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
8385+ AuDebugOn(bindex < 0);
8386+ if (bindex != finfo->fi_btop)
8387+ au_set_fbstart(file, bindex);
8388+ } else {
8389+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
8390+ if (unlikely(err))
8391+ goto out;
8392+ au_do_refresh_dir(file);
8393+ }
1facf9fc 8394+
4a4d8108
AM
8395+ err = 0;
8396+ need_reopen = 1;
8397+ if (!au_test_mmapped(file))
8398+ err = au_file_refresh_by_inode(file, &need_reopen);
8399+ if (!err && need_reopen && !d_unhashed(dentry))
8400+ err = reopen(file);
8401+ if (!err) {
8402+ au_update_figen(file);
8403+ goto out; /* success */
8404+ }
8405+
8406+ /* error, close all lower files */
8407+ if (finfo->fi_hdir) {
8408+ bend = au_fbend_dir(file);
8409+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
8410+ au_set_h_fptr(file, bindex, NULL);
8411+ }
1facf9fc 8412+
4f0767ce 8413+out:
1facf9fc 8414+ return err;
8415+}
8416+
4a4d8108
AM
8417+/* common function to regular file and dir */
8418+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8419+ int wlock)
dece6358 8420+{
1308ab2a 8421+ int err;
4a4d8108
AM
8422+ unsigned int sigen, figen;
8423+ aufs_bindex_t bstart;
8424+ unsigned char pseudo_link;
8425+ struct dentry *dentry;
8426+ struct inode *inode;
1facf9fc 8427+
4a4d8108
AM
8428+ err = 0;
8429+ dentry = file->f_dentry;
8430+ inode = dentry->d_inode;
8431+ AuDebugOn(au_special_file(inode->i_mode));
8432+ sigen = au_sigen(dentry->d_sb);
8433+ fi_write_lock(file);
8434+ figen = au_figen(file);
8435+ di_write_lock_child(dentry);
8436+ bstart = au_dbstart(dentry);
8437+ pseudo_link = (bstart != au_ibstart(inode));
8438+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
8439+ if (!wlock) {
8440+ di_downgrade_lock(dentry, AuLock_IR);
8441+ fi_downgrade_lock(file);
8442+ }
8443+ goto out; /* success */
8444+ }
dece6358 8445+
4a4d8108
AM
8446+ AuDbg("sigen %d, figen %d\n", sigen, figen);
8447+ if (sigen != au_digen(dentry)
8448+ || sigen != au_iigen(inode)) {
8449+ err = au_reval_dpath(dentry, sigen);
8450+ if (unlikely(err < 0))
8451+ goto out;
8452+ AuDebugOn(au_digen(dentry) != sigen
8453+ || au_iigen(inode) != sigen);
8454+ }
dece6358 8455+
4a4d8108
AM
8456+ err = refresh_file(file, reopen);
8457+ if (!err) {
8458+ if (!wlock) {
8459+ di_downgrade_lock(dentry, AuLock_IR);
8460+ fi_downgrade_lock(file);
8461+ }
8462+ } else {
8463+ di_write_unlock(dentry);
8464+ fi_write_unlock(file);
8465+ }
1facf9fc 8466+
4f0767ce 8467+out:
1308ab2a 8468+ return err;
8469+}
1facf9fc 8470+
4a4d8108
AM
8471+/* ---------------------------------------------------------------------- */
8472+
8473+/* cf. aufs_nopage() */
8474+/* for madvise(2) */
8475+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 8476+{
4a4d8108
AM
8477+ unlock_page(page);
8478+ return 0;
8479+}
1facf9fc 8480+
4a4d8108
AM
8481+/* it will never be called, but necessary to support O_DIRECT */
8482+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
8483+ const struct iovec *iov, loff_t offset,
8484+ unsigned long nr_segs)
8485+{ BUG(); return 0; }
1facf9fc 8486+
4a4d8108
AM
8487+/*
8488+ * it will never be called, but madvise and fadvise behaves differently
8489+ * when get_xip_mem is defined
8490+ */
8491+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
8492+ int create, void **kmem, unsigned long *pfn)
8493+{ BUG(); return 0; }
1facf9fc 8494+
4a4d8108
AM
8495+/* they will never be called. */
8496+#ifdef CONFIG_AUFS_DEBUG
8497+static int aufs_write_begin(struct file *file, struct address_space *mapping,
8498+ loff_t pos, unsigned len, unsigned flags,
8499+ struct page **pagep, void **fsdata)
8500+{ AuUnsupport(); return 0; }
8501+static int aufs_write_end(struct file *file, struct address_space *mapping,
8502+ loff_t pos, unsigned len, unsigned copied,
8503+ struct page *page, void *fsdata)
8504+{ AuUnsupport(); return 0; }
8505+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
8506+{ AuUnsupport(); return 0; }
8507+static void aufs_sync_page(struct page *page)
8508+{ AuUnsupport(); }
1308ab2a 8509+
4a4d8108
AM
8510+static int aufs_set_page_dirty(struct page *page)
8511+{ AuUnsupport(); return 0; }
8512+static void aufs_invalidatepage(struct page *page, unsigned long offset)
8513+{ AuUnsupport(); }
8514+static int aufs_releasepage(struct page *page, gfp_t gfp)
8515+{ AuUnsupport(); return 0; }
8516+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
8517+ struct page *page)
8518+{ AuUnsupport(); return 0; }
8519+static int aufs_launder_page(struct page *page)
8520+{ AuUnsupport(); return 0; }
8521+static int aufs_is_partially_uptodate(struct page *page,
8522+ read_descriptor_t *desc,
8523+ unsigned long from)
8524+{ AuUnsupport(); return 0; }
8525+static int aufs_error_remove_page(struct address_space *mapping,
8526+ struct page *page)
8527+{ AuUnsupport(); return 0; }
8528+#endif /* CONFIG_AUFS_DEBUG */
8529+
8530+const struct address_space_operations aufs_aop = {
8531+ .readpage = aufs_readpage,
8532+ .direct_IO = aufs_direct_IO,
8533+ .get_xip_mem = aufs_get_xip_mem,
8534+#ifdef CONFIG_AUFS_DEBUG
8535+ .writepage = aufs_writepage,
8536+ .sync_page = aufs_sync_page,
8537+ /* no writepages, because of writepage */
8538+ .set_page_dirty = aufs_set_page_dirty,
8539+ /* no readpages, because of readpage */
8540+ .write_begin = aufs_write_begin,
8541+ .write_end = aufs_write_end,
8542+ /* no bmap, no block device */
8543+ .invalidatepage = aufs_invalidatepage,
8544+ .releasepage = aufs_releasepage,
8545+ .migratepage = aufs_migratepage,
8546+ .launder_page = aufs_launder_page,
8547+ .is_partially_uptodate = aufs_is_partially_uptodate,
8548+ .error_remove_page = aufs_error_remove_page
8549+#endif /* CONFIG_AUFS_DEBUG */
dece6358 8550+};
e49829fe
JR
8551--- /dev/null
8552+++ linux-2.6/fs/aufs/file.h 2010-10-24 11:19:23.000000000 +0200
b752ccd1 8553@@ -0,0 +1,238 @@
4a4d8108
AM
8554+/*
8555+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8556+ *
8557+ * This program, aufs is free software; you can redistribute it and/or modify
8558+ * it under the terms of the GNU General Public License as published by
8559+ * the Free Software Foundation; either version 2 of the License, or
8560+ * (at your option) any later version.
8561+ *
8562+ * This program is distributed in the hope that it will be useful,
8563+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8564+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8565+ * GNU General Public License for more details.
8566+ *
8567+ * You should have received a copy of the GNU General Public License
8568+ * along with this program; if not, write to the Free Software
8569+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8570+ */
1facf9fc 8571+
4a4d8108
AM
8572+/*
8573+ * file operations
8574+ */
1facf9fc 8575+
4a4d8108
AM
8576+#ifndef __AUFS_FILE_H__
8577+#define __AUFS_FILE_H__
1facf9fc 8578+
4a4d8108 8579+#ifdef __KERNEL__
1facf9fc 8580+
4a4d8108
AM
8581+#include <linux/fs.h>
8582+#include <linux/poll.h>
8583+#include <linux/aufs_type.h>
8584+#include "rwsem.h"
1facf9fc 8585+
4a4d8108
AM
8586+struct au_branch;
8587+struct au_hfile {
8588+ struct file *hf_file;
8589+ struct au_branch *hf_br;
8590+};
1facf9fc 8591+
4a4d8108
AM
8592+struct au_vdir;
8593+struct au_fidir {
8594+ aufs_bindex_t fd_bbot;
8595+ aufs_bindex_t fd_nent;
8596+ struct au_vdir *fd_vdir_cache;
8597+ struct au_hfile fd_hfile[];
8598+};
1facf9fc 8599+
4a4d8108 8600+static inline int au_fidir_sz(int nent)
dece6358 8601+{
4f0767ce
JR
8602+ AuDebugOn(nent < 0);
8603+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 8604+}
1facf9fc 8605+
4a4d8108
AM
8606+struct au_finfo {
8607+ atomic_t fi_generation;
dece6358 8608+
4a4d8108
AM
8609+ struct au_rwsem fi_rwsem;
8610+ aufs_bindex_t fi_btop;
8611+
8612+ /* do not union them */
8613+ struct { /* for non-dir */
8614+ struct au_hfile fi_htop;
8615+ struct vm_operations_struct *fi_hvmop;
8616+ struct mutex fi_vm_mtx;
8617+ struct mutex fi_mmap;
8618+ };
8619+ struct au_fidir *fi_hdir; /* for dir only */
8620+} ____cacheline_aligned_in_smp;
1facf9fc 8621+
4a4d8108 8622+/* ---------------------------------------------------------------------- */
1facf9fc 8623+
4a4d8108
AM
8624+/* file.c */
8625+extern const struct address_space_operations aufs_aop;
8626+unsigned int au_file_roflags(unsigned int flags);
8627+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8628+ struct file *file);
8629+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8630+ struct au_fidir *fidir);
8631+int au_reopen_nondir(struct file *file);
8632+struct au_pin;
8633+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
8634+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8635+ int wlock);
8636+int au_do_flush(struct file *file, fl_owner_t id,
8637+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 8638+
4a4d8108
AM
8639+/* poll.c */
8640+#ifdef CONFIG_AUFS_POLL
8641+unsigned int aufs_poll(struct file *file, poll_table *wait);
8642+#endif
1facf9fc 8643+
4a4d8108
AM
8644+#ifdef CONFIG_AUFS_BR_HFSPLUS
8645+/* hfsplus.c */
8646+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
8647+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
8648+ struct file *h_file);
8649+#else
8650+static inline
8651+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 8652+{
4a4d8108
AM
8653+ return NULL;
8654+}
1facf9fc 8655+
4a4d8108
AM
8656+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
8657+ struct file *h_file);
8658+#endif
1facf9fc 8659+
4a4d8108
AM
8660+/* f_op.c */
8661+extern const struct file_operations aufs_file_fop;
8662+extern const struct vm_operations_struct aufs_vm_ops;
8663+int au_do_open_nondir(struct file *file, int flags);
8664+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
8665+
8666+#ifdef CONFIG_AUFS_SP_IATTR
8667+/* f_op_sp.c */
8668+int au_special_file(umode_t mode);
8669+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
8670+#else
8671+AuStubInt0(au_special_file, umode_t mode)
8672+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
8673+ dev_t rdev)
8674+{
8675+ init_special_inode(inode, mode, rdev);
8676+}
8677+#endif
1facf9fc 8678+
4a4d8108
AM
8679+/* finfo.c */
8680+void au_hfput(struct au_hfile *hf, struct file *file);
8681+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
8682+ struct file *h_file);
1facf9fc 8683+
4a4d8108
AM
8684+void au_update_figen(struct file *file);
8685+void au_fi_mmap_lock(struct file *file);
8686+void au_fi_mmap_unlock(struct file *file);
8687+struct au_fidir *au_fidir_alloc(struct super_block *sb);
8688+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 8689+
4a4d8108
AM
8690+void au_fi_init_once(void *_fi);
8691+void au_finfo_fin(struct file *file);
8692+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 8693+
4a4d8108
AM
8694+/* ioctl.c */
8695+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
8696+#ifdef CONFIG_COMPAT
8697+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
8698+ unsigned long arg);
8699+#endif
1facf9fc 8700+
4a4d8108 8701+/* ---------------------------------------------------------------------- */
1facf9fc 8702+
4a4d8108
AM
8703+static inline struct au_finfo *au_fi(struct file *file)
8704+{
8705+ return file->private_data;
8706+}
1facf9fc 8707+
4a4d8108 8708+/* ---------------------------------------------------------------------- */
1facf9fc 8709+
4a4d8108
AM
8710+/*
8711+ * fi_read_lock, fi_write_lock,
8712+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
8713+ */
8714+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 8715+
4a4d8108
AM
8716+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
8717+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
8718+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 8719+
1308ab2a 8720+/* ---------------------------------------------------------------------- */
8721+
4a4d8108
AM
8722+/* todo: hard/soft set? */
8723+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 8724+{
4a4d8108
AM
8725+ FiMustAnyLock(file);
8726+ return au_fi(file)->fi_btop;
8727+}
dece6358 8728+
4a4d8108
AM
8729+static inline aufs_bindex_t au_fbend_dir(struct file *file)
8730+{
8731+ FiMustAnyLock(file);
8732+ AuDebugOn(!au_fi(file)->fi_hdir);
8733+ return au_fi(file)->fi_hdir->fd_bbot;
8734+}
1facf9fc 8735+
4a4d8108
AM
8736+static inline struct au_vdir *au_fvdir_cache(struct file *file)
8737+{
8738+ FiMustAnyLock(file);
8739+ AuDebugOn(!au_fi(file)->fi_hdir);
8740+ return au_fi(file)->fi_hdir->fd_vdir_cache;
8741+}
1facf9fc 8742+
4a4d8108
AM
8743+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
8744+{
8745+ FiMustWriteLock(file);
8746+ au_fi(file)->fi_btop = bindex;
8747+}
1facf9fc 8748+
4a4d8108
AM
8749+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
8750+{
8751+ FiMustWriteLock(file);
8752+ AuDebugOn(!au_fi(file)->fi_hdir);
8753+ au_fi(file)->fi_hdir->fd_bbot = bindex;
8754+}
1308ab2a 8755+
4a4d8108
AM
8756+static inline void au_set_fvdir_cache(struct file *file,
8757+ struct au_vdir *vdir_cache)
8758+{
8759+ FiMustWriteLock(file);
8760+ AuDebugOn(!au_fi(file)->fi_hdir);
8761+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
8762+}
dece6358 8763+
4a4d8108
AM
8764+static inline struct file *au_hf_top(struct file *file)
8765+{
8766+ FiMustAnyLock(file);
8767+ AuDebugOn(au_fi(file)->fi_hdir);
8768+ return au_fi(file)->fi_htop.hf_file;
8769+}
1facf9fc 8770+
4a4d8108
AM
8771+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
8772+{
8773+ FiMustAnyLock(file);
8774+ AuDebugOn(!au_fi(file)->fi_hdir);
8775+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
8776+}
8777+
4a4d8108
AM
8778+/* todo: memory barrier? */
8779+static inline unsigned int au_figen(struct file *f)
dece6358 8780+{
4a4d8108
AM
8781+ return atomic_read(&au_fi(f)->fi_generation);
8782+}
dece6358 8783+
4a4d8108
AM
8784+static inline int au_test_mmapped(struct file *f)
8785+{
8786+ FiMustAnyLock(f);
8787+ return !!(au_fi(f)->fi_hvmop);
8788+}
1308ab2a 8789+
4a4d8108
AM
8790+#endif /* __KERNEL__ */
8791+#endif /* __AUFS_FILE_H__ */
e49829fe
JR
8792--- /dev/null
8793+++ linux-2.6/fs/aufs/finfo.c 2010-10-24 11:36:29.000000000 +0200
8794@@ -0,0 +1,171 @@
4a4d8108
AM
8795+/*
8796+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8797+ *
8798+ * This program, aufs is free software; you can redistribute it and/or modify
8799+ * it under the terms of the GNU General Public License as published by
8800+ * the Free Software Foundation; either version 2 of the License, or
8801+ * (at your option) any later version.
8802+ *
8803+ * This program is distributed in the hope that it will be useful,
8804+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8805+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8806+ * GNU General Public License for more details.
8807+ *
8808+ * You should have received a copy of the GNU General Public License
8809+ * along with this program; if not, write to the Free Software
8810+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8811+ */
1308ab2a 8812+
4a4d8108
AM
8813+/*
8814+ * file private data
8815+ */
1facf9fc 8816+
4a4d8108
AM
8817+#include <linux/file.h>
8818+#include "aufs.h"
1facf9fc 8819+
4a4d8108
AM
8820+void au_hfput(struct au_hfile *hf, struct file *file)
8821+{
8822+ /* todo: direct access f_flags */
8823+ if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC))
8824+ allow_write_access(hf->hf_file);
8825+ fput(hf->hf_file);
8826+ hf->hf_file = NULL;
e49829fe 8827+ atomic_dec(&hf->hf_br->br_count);
4a4d8108
AM
8828+ hf->hf_br = NULL;
8829+}
1facf9fc 8830+
4a4d8108
AM
8831+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
8832+{
8833+ struct au_finfo *finfo = au_fi(file);
8834+ struct au_hfile *hf;
8835+ struct au_fidir *fidir;
8836+
8837+ fidir = finfo->fi_hdir;
8838+ if (!fidir) {
8839+ AuDebugOn(finfo->fi_btop != bindex);
8840+ hf = &finfo->fi_htop;
8841+ } else
8842+ hf = fidir->fd_hfile + bindex;
8843+
8844+ if (hf && hf->hf_file)
8845+ au_hfput(hf, file);
8846+ if (val) {
8847+ FiMustWriteLock(file);
8848+ hf->hf_file = val;
8849+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 8850+ }
4a4d8108 8851+}
1facf9fc 8852+
4a4d8108
AM
8853+void au_update_figen(struct file *file)
8854+{
8855+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
8856+ /* smp_mb(); */ /* atomic_set */
1facf9fc 8857+}
8858+
4a4d8108
AM
8859+/* ---------------------------------------------------------------------- */
8860+
8861+void au_fi_mmap_lock(struct file *file)
1facf9fc 8862+{
4a4d8108
AM
8863+ FiMustWriteLock(file);
8864+ lockdep_off();
8865+ mutex_lock(&au_fi(file)->fi_mmap);
8866+ lockdep_on();
8867+}
1facf9fc 8868+
4a4d8108
AM
8869+void au_fi_mmap_unlock(struct file *file)
8870+{
8871+ lockdep_off();
8872+ mutex_unlock(&au_fi(file)->fi_mmap);
8873+ lockdep_on();
8874+}
1308ab2a 8875+
4a4d8108 8876+/* ---------------------------------------------------------------------- */
1308ab2a 8877+
4a4d8108
AM
8878+struct au_fidir *au_fidir_alloc(struct super_block *sb)
8879+{
8880+ struct au_fidir *fidir;
8881+ int nbr;
8882+
8883+ nbr = au_sbend(sb) + 1;
8884+ if (nbr < 2)
8885+ nbr = 2; /* initial allocate for 2 branches */
8886+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
8887+ if (fidir) {
8888+ fidir->fd_bbot = -1;
8889+ fidir->fd_nent = nbr;
8890+ fidir->fd_vdir_cache = NULL;
8891+ }
8892+
8893+ return fidir;
8894+}
8895+
8896+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
8897+{
8898+ int err;
8899+ struct au_fidir *fidir, *p;
8900+
8901+ AuRwMustWriteLock(&finfo->fi_rwsem);
8902+ fidir = finfo->fi_hdir;
8903+ AuDebugOn(!fidir);
8904+
8905+ err = -ENOMEM;
8906+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
8907+ GFP_NOFS);
8908+ if (p) {
8909+ p->fd_nent = nbr;
8910+ finfo->fi_hdir = p;
8911+ err = 0;
8912+ }
1facf9fc 8913+
dece6358 8914+ return err;
1facf9fc 8915+}
1308ab2a 8916+
8917+/* ---------------------------------------------------------------------- */
8918+
4a4d8108 8919+void au_finfo_fin(struct file *file)
1308ab2a 8920+{
4a4d8108
AM
8921+ struct au_finfo *finfo;
8922+
8923+ finfo = au_fi(file);
8924+ AuDebugOn(finfo->fi_hdir);
8925+ AuRwDestroy(&finfo->fi_rwsem);
8926+ au_cache_free_finfo(finfo);
1308ab2a 8927+}
1308ab2a 8928+
e49829fe 8929+void au_fi_init_once(void *_finfo)
4a4d8108 8930+{
e49829fe
JR
8931+ struct au_finfo *finfo = _finfo;
8932+ static struct lock_class_key aufs_fi, aufs_fi_vm, aufs_fi_mmap;
1308ab2a 8933+
e49829fe
JR
8934+ au_rw_init(&finfo->fi_rwsem);
8935+ au_rw_class(&finfo->fi_rwsem, &aufs_fi);
8936+ mutex_init(&finfo->fi_vm_mtx);
8937+ lockdep_set_class(&finfo->fi_vm_mtx, &aufs_fi_vm);
8938+ mutex_init(&finfo->fi_mmap);
8939+ lockdep_set_class(&finfo->fi_mmap, &aufs_fi_mmap);
4a4d8108 8940+}
1308ab2a 8941+
4a4d8108
AM
8942+int au_finfo_init(struct file *file, struct au_fidir *fidir)
8943+{
8944+ int err;
8945+ struct au_finfo *finfo;
8946+ struct dentry *dentry;
8947+
8948+ err = -ENOMEM;
8949+ dentry = file->f_dentry;
8950+ finfo = au_cache_alloc_finfo();
8951+ if (unlikely(!finfo))
8952+ goto out;
8953+
8954+ err = 0;
8955+ au_rw_write_lock(&finfo->fi_rwsem);
8956+ finfo->fi_btop = -1;
8957+ finfo->fi_hdir = fidir;
8958+ atomic_set(&finfo->fi_generation, au_digen(dentry));
8959+ /* smp_mb(); */ /* atomic_set */
8960+
8961+ file->private_data = finfo;
8962+
8963+out:
8964+ return err;
8965+}
e49829fe
JR
8966--- /dev/null
8967+++ linux-2.6/fs/aufs/f_op.c 2010-10-24 15:02:31.000000000 +0200
8968@@ -0,0 +1,899 @@
dece6358 8969+/*
4a4d8108 8970+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
8971+ *
8972+ * This program, aufs is free software; you can redistribute it and/or modify
8973+ * it under the terms of the GNU General Public License as published by
8974+ * the Free Software Foundation; either version 2 of the License, or
8975+ * (at your option) any later version.
8976+ *
8977+ * This program is distributed in the hope that it will be useful,
8978+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8979+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8980+ * GNU General Public License for more details.
8981+ *
8982+ * You should have received a copy of the GNU General Public License
8983+ * along with this program; if not, write to the Free Software
8984+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8985+ */
1facf9fc 8986+
8987+/*
4a4d8108 8988+ * file and vm operations
1facf9fc 8989+ */
dece6358
AM
8990+
8991+#include <linux/file.h>
4a4d8108
AM
8992+#include <linux/fs_stack.h>
8993+#include <linux/mman.h>
8994+#include <linux/mm.h>
8995+#include <linux/security.h>
dece6358
AM
8996+#include "aufs.h"
8997+
4a4d8108 8998+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 8999+{
4a4d8108
AM
9000+ int err;
9001+ aufs_bindex_t bindex;
9002+ struct file *h_file;
9003+ struct dentry *dentry;
9004+ struct au_finfo *finfo;
9005+
9006+ FiMustWriteLock(file);
9007+
9008+ err = 0;
9009+ dentry = file->f_dentry;
9010+ finfo = au_fi(file);
9011+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
9012+ finfo->fi_hvmop = NULL;
9013+ bindex = au_dbstart(dentry);
9014+ h_file = au_h_open(dentry, bindex, flags, file);
9015+ if (IS_ERR(h_file))
9016+ err = PTR_ERR(h_file);
9017+ else {
9018+ au_set_fbstart(file, bindex);
9019+ au_set_h_fptr(file, bindex, h_file);
9020+ au_update_figen(file);
9021+ /* todo: necessary? */
9022+ /* file->f_ra = h_file->f_ra; */
9023+ }
9024+ return err;
1facf9fc 9025+}
9026+
4a4d8108
AM
9027+static int aufs_open_nondir(struct inode *inode __maybe_unused,
9028+ struct file *file)
1facf9fc 9029+{
4a4d8108 9030+ int err;
1308ab2a 9031+ struct super_block *sb;
1facf9fc 9032+
4a4d8108
AM
9033+ AuDbg("%.*s, f_ flags 0x%x, f_mode 0x%x\n",
9034+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
9035+ file->f_mode);
1facf9fc 9036+
4a4d8108
AM
9037+ sb = file->f_dentry->d_sb;
9038+ si_read_lock(sb, AuLock_FLUSH);
9039+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
9040+ si_read_unlock(sb);
9041+ return err;
9042+}
1facf9fc 9043+
4a4d8108
AM
9044+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
9045+{
9046+ struct au_finfo *finfo;
9047+ aufs_bindex_t bindex;
1facf9fc 9048+
e49829fe 9049+ au_plink_maint_leave(au_sbi(file->f_dentry->d_sb));
4a4d8108
AM
9050+ finfo = au_fi(file);
9051+ bindex = finfo->fi_btop;
953406b4 9052+ if (bindex >= 0)
4a4d8108 9053+ au_set_h_fptr(file, bindex, NULL);
dece6358 9054+
4a4d8108
AM
9055+ au_finfo_fin(file);
9056+ return 0;
1facf9fc 9057+}
9058+
4a4d8108
AM
9059+/* ---------------------------------------------------------------------- */
9060+
9061+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 9062+{
1308ab2a 9063+ int err;
4a4d8108
AM
9064+ struct file *h_file;
9065+
9066+ err = 0;
9067+ h_file = au_hf_top(file);
9068+ if (h_file)
9069+ err = vfsub_flush(h_file, id);
9070+ return err;
9071+}
9072+
9073+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
9074+{
9075+ return au_do_flush(file, id, au_do_flush_nondir);
9076+}
9077+
9078+/* ---------------------------------------------------------------------- */
9079+
9080+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
9081+ loff_t *ppos)
9082+{
9083+ ssize_t err;
dece6358 9084+ struct dentry *dentry;
4a4d8108 9085+ struct file *h_file;
dece6358 9086+ struct super_block *sb;
1facf9fc 9087+
dece6358
AM
9088+ dentry = file->f_dentry;
9089+ sb = dentry->d_sb;
e49829fe 9090+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 9091+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
9092+ if (unlikely(err))
9093+ goto out;
1facf9fc 9094+
4a4d8108
AM
9095+ h_file = au_hf_top(file);
9096+ err = vfsub_read_u(h_file, buf, count, ppos);
9097+ /* todo: necessary? */
9098+ /* file->f_ra = h_file->f_ra; */
9099+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1308ab2a 9100+
4a4d8108
AM
9101+ di_read_unlock(dentry, AuLock_IR);
9102+ fi_read_unlock(file);
4f0767ce 9103+out:
dece6358
AM
9104+ si_read_unlock(sb);
9105+ return err;
9106+}
1facf9fc 9107+
e49829fe
JR
9108+/*
9109+ * todo: very ugly
9110+ * it locks both of i_mutex and si_rwsem for read in safe.
9111+ * if the plink maintenance mode continues forever (that is the problem),
9112+ * may loop forever.
9113+ */
9114+static void au_mtx_and_read_lock(struct inode *inode)
9115+{
9116+ int err;
9117+ struct super_block *sb = inode->i_sb;
9118+
9119+ while (1) {
9120+ mutex_lock(&inode->i_mutex);
9121+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
9122+ if (!err)
9123+ break;
9124+ mutex_unlock(&inode->i_mutex);
9125+ si_read_lock(sb, AuLock_NOPLMW);
9126+ si_read_unlock(sb);
9127+ }
9128+}
9129+
4a4d8108
AM
9130+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
9131+ size_t count, loff_t *ppos)
dece6358 9132+{
4a4d8108
AM
9133+ ssize_t err;
9134+ struct au_pin pin;
dece6358 9135+ struct dentry *dentry;
4a4d8108 9136+ struct inode *inode;
4a4d8108
AM
9137+ struct file *h_file;
9138+ char __user *buf = (char __user *)ubuf;
1facf9fc 9139+
dece6358 9140+ dentry = file->f_dentry;
4a4d8108 9141+ inode = dentry->d_inode;
e49829fe 9142+ au_mtx_and_read_lock(inode);
1facf9fc 9143+
4a4d8108
AM
9144+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9145+ if (unlikely(err))
9146+ goto out;
1facf9fc 9147+
4a4d8108
AM
9148+ err = au_ready_to_write(file, -1, &pin);
9149+ di_downgrade_lock(dentry, AuLock_IR);
9150+ if (unlikely(err))
9151+ goto out_unlock;
1facf9fc 9152+
4a4d8108
AM
9153+ h_file = au_hf_top(file);
9154+ au_unpin(&pin);
9155+ err = vfsub_write_u(h_file, buf, count, ppos);
9156+ au_cpup_attr_timesizes(inode);
9157+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9158+
4f0767ce 9159+out_unlock:
4a4d8108
AM
9160+ di_read_unlock(dentry, AuLock_IR);
9161+ fi_write_unlock(file);
4f0767ce 9162+out:
e49829fe 9163+ si_read_unlock(inode->i_sb);
4a4d8108 9164+ mutex_unlock(&inode->i_mutex);
dece6358
AM
9165+ return err;
9166+}
1facf9fc 9167+
4a4d8108
AM
9168+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
9169+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 9170+{
4a4d8108
AM
9171+ ssize_t err;
9172+ struct file *file;
9173+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
9174+ loff_t);
1facf9fc 9175+
4a4d8108
AM
9176+ err = security_file_permission(h_file, rw);
9177+ if (unlikely(err))
9178+ goto out;
1facf9fc 9179+
4a4d8108
AM
9180+ err = -ENOSYS;
9181+ func = NULL;
9182+ if (rw == MAY_READ)
9183+ func = h_file->f_op->aio_read;
9184+ else if (rw == MAY_WRITE)
9185+ func = h_file->f_op->aio_write;
9186+ if (func) {
9187+ file = kio->ki_filp;
9188+ kio->ki_filp = h_file;
9189+ err = func(kio, iov, nv, pos);
9190+ kio->ki_filp = file;
9191+ } else
9192+ /* currently there is no such fs */
9193+ WARN_ON_ONCE(1);
1facf9fc 9194+
4f0767ce 9195+out:
dece6358
AM
9196+ return err;
9197+}
1facf9fc 9198+
4a4d8108
AM
9199+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
9200+ unsigned long nv, loff_t pos)
1facf9fc 9201+{
4a4d8108
AM
9202+ ssize_t err;
9203+ struct file *file, *h_file;
9204+ struct dentry *dentry;
dece6358 9205+ struct super_block *sb;
1facf9fc 9206+
4a4d8108 9207+ file = kio->ki_filp;
dece6358 9208+ dentry = file->f_dentry;
1308ab2a 9209+ sb = dentry->d_sb;
e49829fe 9210+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9211+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9212+ if (unlikely(err))
9213+ goto out;
9214+
9215+ h_file = au_hf_top(file);
9216+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
9217+ /* todo: necessary? */
9218+ /* file->f_ra = h_file->f_ra; */
9219+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9220+ di_read_unlock(dentry, AuLock_IR);
9221+ fi_read_unlock(file);
1facf9fc 9222+
4f0767ce 9223+out:
4a4d8108 9224+ si_read_unlock(sb);
1308ab2a 9225+ return err;
9226+}
1facf9fc 9227+
4a4d8108
AM
9228+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
9229+ unsigned long nv, loff_t pos)
1308ab2a 9230+{
4a4d8108
AM
9231+ ssize_t err;
9232+ struct au_pin pin;
9233+ struct dentry *dentry;
9234+ struct inode *inode;
4a4d8108 9235+ struct file *file, *h_file;
1308ab2a 9236+
4a4d8108 9237+ file = kio->ki_filp;
1308ab2a 9238+ dentry = file->f_dentry;
1308ab2a 9239+ inode = dentry->d_inode;
e49829fe
JR
9240+ au_mtx_and_read_lock(inode);
9241+
4a4d8108
AM
9242+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9243+ if (unlikely(err))
1308ab2a 9244+ goto out;
1facf9fc 9245+
4a4d8108
AM
9246+ err = au_ready_to_write(file, -1, &pin);
9247+ di_downgrade_lock(dentry, AuLock_IR);
dece6358 9248+ if (unlikely(err))
4a4d8108 9249+ goto out_unlock;
1facf9fc 9250+
4a4d8108
AM
9251+ au_unpin(&pin);
9252+ h_file = au_hf_top(file);
9253+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
9254+ au_cpup_attr_timesizes(inode);
9255+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9256+
4f0767ce 9257+out_unlock:
4a4d8108
AM
9258+ di_read_unlock(dentry, AuLock_IR);
9259+ fi_write_unlock(file);
4f0767ce 9260+out:
e49829fe 9261+ si_read_unlock(inode->i_sb);
4a4d8108 9262+ mutex_unlock(&inode->i_mutex);
dece6358 9263+ return err;
1facf9fc 9264+}
9265+
4a4d8108
AM
9266+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
9267+ struct pipe_inode_info *pipe, size_t len,
9268+ unsigned int flags)
1facf9fc 9269+{
4a4d8108
AM
9270+ ssize_t err;
9271+ struct file *h_file;
9272+ struct dentry *dentry;
dece6358 9273+ struct super_block *sb;
1facf9fc 9274+
dece6358 9275+ dentry = file->f_dentry;
dece6358 9276+ sb = dentry->d_sb;
e49829fe 9277+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9278+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9279+ if (unlikely(err))
dece6358 9280+ goto out;
1facf9fc 9281+
4a4d8108
AM
9282+ err = -EINVAL;
9283+ h_file = au_hf_top(file);
9284+ if (au_test_loopback_kthread()) {
9285+ file->f_mapping = h_file->f_mapping;
9286+ smp_mb(); /* unnecessary? */
1308ab2a 9287+ }
4a4d8108
AM
9288+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
9289+ /* todo: necessasry? */
9290+ /* file->f_ra = h_file->f_ra; */
9291+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 9292+
4a4d8108
AM
9293+ di_read_unlock(dentry, AuLock_IR);
9294+ fi_read_unlock(file);
1facf9fc 9295+
4f0767ce 9296+out:
4a4d8108 9297+ si_read_unlock(sb);
dece6358 9298+ return err;
1facf9fc 9299+}
9300+
4a4d8108
AM
9301+static ssize_t
9302+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
9303+ size_t len, unsigned int flags)
1facf9fc 9304+{
4a4d8108
AM
9305+ ssize_t err;
9306+ struct au_pin pin;
9307+ struct dentry *dentry;
9308+ struct inode *inode;
4a4d8108 9309+ struct file *h_file;
1facf9fc 9310+
4a4d8108
AM
9311+ dentry = file->f_dentry;
9312+ inode = dentry->d_inode;
e49829fe 9313+ au_mtx_and_read_lock(inode);
4a4d8108
AM
9314+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9315+ if (unlikely(err))
9316+ goto out;
1facf9fc 9317+
4a4d8108
AM
9318+ err = au_ready_to_write(file, -1, &pin);
9319+ di_downgrade_lock(dentry, AuLock_IR);
9320+ if (unlikely(err))
9321+ goto out_unlock;
1facf9fc 9322+
4a4d8108
AM
9323+ h_file = au_hf_top(file);
9324+ au_unpin(&pin);
9325+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
9326+ au_cpup_attr_timesizes(inode);
9327+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9328+
4f0767ce 9329+out_unlock:
4a4d8108
AM
9330+ di_read_unlock(dentry, AuLock_IR);
9331+ fi_write_unlock(file);
4f0767ce 9332+out:
e49829fe 9333+ si_read_unlock(inode->i_sb);
4a4d8108
AM
9334+ mutex_unlock(&inode->i_mutex);
9335+ return err;
9336+}
1facf9fc 9337+
4a4d8108
AM
9338+/* ---------------------------------------------------------------------- */
9339+
9340+static struct file *au_safe_file(struct vm_area_struct *vma)
9341+{
9342+ struct file *file;
9343+
9344+ file = vma->vm_file;
9345+ if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
9346+ return file;
9347+ return NULL;
1facf9fc 9348+}
9349+
4a4d8108 9350+static void au_reset_file(struct vm_area_struct *vma, struct file *file)
1facf9fc 9351+{
4a4d8108
AM
9352+ vma->vm_file = file;
9353+ /* smp_mb(); */ /* flush vm_file */
9354+}
1facf9fc 9355+
4a4d8108
AM
9356+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
9357+{
9358+ int err;
9359+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9360+ struct file *file, *h_file;
9361+ struct au_finfo *finfo;
1facf9fc 9362+
4a4d8108
AM
9363+ /* todo: non-robr mode, user vm_file as it is? */
9364+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 9365+
4a4d8108
AM
9366+ /* do not revalidate, no si lock */
9367+ finfo = au_fi(file);
9368+ AuDebugOn(finfo->fi_hdir);
9369+ h_file = finfo->fi_htop.hf_file;
9370+ AuDebugOn(!h_file || !finfo->fi_hvmop);
9371+
9372+ mutex_lock(&finfo->fi_vm_mtx);
9373+ vma->vm_file = h_file;
9374+ err = finfo->fi_hvmop->fault(vma, vmf);
9375+ /* todo: necessary? */
9376+ /* file->f_ra = h_file->f_ra; */
9377+ au_reset_file(vma, file);
9378+ mutex_unlock(&finfo->fi_vm_mtx);
9379+#if 0 /* def CONFIG_SMP */
9380+ /* wake_up_nr(&wq, online_cpu - 1); */
9381+ wake_up_all(&wq);
9382+#else
9383+ wake_up(&wq);
9384+#endif
1facf9fc 9385+
dece6358 9386+ return err;
1facf9fc 9387+}
9388+
4a4d8108 9389+static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1facf9fc 9390+{
dece6358 9391+ int err;
4a4d8108
AM
9392+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9393+ struct file *file, *h_file;
9394+ struct au_finfo *finfo;
1facf9fc 9395+
4a4d8108 9396+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 9397+
4a4d8108
AM
9398+ finfo = au_fi(file);
9399+ AuDebugOn(finfo->fi_hdir);
9400+ h_file = finfo->fi_htop.hf_file;
9401+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 9402+
4a4d8108
AM
9403+ mutex_lock(&finfo->fi_vm_mtx);
9404+ vma->vm_file = h_file;
9405+ err = finfo->fi_hvmop->page_mkwrite(vma, vmf);
9406+ au_reset_file(vma, file);
9407+ mutex_unlock(&finfo->fi_vm_mtx);
9408+ wake_up(&wq);
1308ab2a 9409+
dece6358 9410+ return err;
1facf9fc 9411+}
9412+
4a4d8108 9413+static void aufs_vm_close(struct vm_area_struct *vma)
1facf9fc 9414+{
4a4d8108
AM
9415+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9416+ struct file *file, *h_file;
9417+ struct au_finfo *finfo;
dece6358 9418+
4a4d8108 9419+ wait_event(wq, (file = au_safe_file(vma)));
dece6358 9420+
4a4d8108
AM
9421+ finfo = au_fi(file);
9422+ AuDebugOn(finfo->fi_hdir);
9423+ h_file = finfo->fi_htop.hf_file;
9424+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 9425+
4a4d8108
AM
9426+ mutex_lock(&finfo->fi_vm_mtx);
9427+ vma->vm_file = h_file;
9428+ finfo->fi_hvmop->close(vma);
9429+ au_reset_file(vma, file);
9430+ mutex_unlock(&finfo->fi_vm_mtx);
9431+ wake_up(&wq);
9432+}
1facf9fc 9433+
4a4d8108
AM
9434+const struct vm_operations_struct aufs_vm_ops = {
9435+ .close = aufs_vm_close,
9436+ .fault = aufs_fault,
9437+ .page_mkwrite = aufs_page_mkwrite
1308ab2a 9438+};
dece6358 9439+
1308ab2a 9440+/* ---------------------------------------------------------------------- */
1facf9fc 9441+
4a4d8108
AM
9442+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
9443+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
1308ab2a 9444+
4a4d8108 9445+static unsigned long au_arch_prot_conv(unsigned long flags)
dece6358 9446+{
4a4d8108
AM
9447+ /* currently ppc64 only */
9448+#ifdef CONFIG_PPC64
9449+ /* cf. linux/arch/powerpc/include/asm/mman.h */
9450+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
9451+ return AuConv_VM_PROT(flags, SAO);
9452+#else
9453+ AuDebugOn(arch_calc_vm_prot_bits(-1));
9454+ return 0;
9455+#endif
dece6358
AM
9456+}
9457+
4a4d8108 9458+static unsigned long au_prot_conv(unsigned long flags)
dece6358 9459+{
4a4d8108
AM
9460+ return AuConv_VM_PROT(flags, READ)
9461+ | AuConv_VM_PROT(flags, WRITE)
9462+ | AuConv_VM_PROT(flags, EXEC)
9463+ | au_arch_prot_conv(flags);
dece6358
AM
9464+}
9465+
4a4d8108
AM
9466+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
9467+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
dece6358 9468+
4a4d8108 9469+static unsigned long au_flag_conv(unsigned long flags)
dece6358 9470+{
4a4d8108
AM
9471+ return AuConv_VM_MAP(flags, GROWSDOWN)
9472+ | AuConv_VM_MAP(flags, DENYWRITE)
9473+ | AuConv_VM_MAP(flags, EXECUTABLE)
9474+ | AuConv_VM_MAP(flags, LOCKED);
dece6358
AM
9475+}
9476+
4a4d8108
AM
9477+static struct vm_operations_struct *
9478+au_hvmop(struct file *h_file, struct vm_area_struct *vma, unsigned long *flags)
dece6358 9479+{
4a4d8108
AM
9480+ struct vm_operations_struct *h_vmop;
9481+ unsigned long prot;
9482+ int err;
dece6358 9483+
4a4d8108
AM
9484+ h_vmop = ERR_PTR(-ENODEV);
9485+ if (!h_file->f_op || !h_file->f_op->mmap)
9486+ goto out;
dece6358 9487+
4a4d8108
AM
9488+ prot = au_prot_conv(vma->vm_flags);
9489+ err = security_file_mmap(h_file, /*reqprot*/prot, prot,
9490+ au_flag_conv(vma->vm_flags), vma->vm_start, 0);
9491+ h_vmop = ERR_PTR(err);
9492+ if (unlikely(err))
9493+ goto out;
dece6358 9494+
4a4d8108
AM
9495+ err = h_file->f_op->mmap(h_file, vma);
9496+ h_vmop = ERR_PTR(err);
9497+ if (unlikely(err))
9498+ goto out;
dece6358 9499+
4a4d8108
AM
9500+ /* oops, it became 'const' */
9501+ h_vmop = (struct vm_operations_struct *)vma->vm_ops;
9502+ *flags = vma->vm_flags;
9503+ err = do_munmap(current->mm, vma->vm_start,
9504+ vma->vm_end - vma->vm_start);
9505+ if (unlikely(err)) {
9506+ AuIOErr("failed internal unmapping %.*s, %d\n",
9507+ AuDLNPair(h_file->f_dentry), err);
9508+ h_vmop = ERR_PTR(-EIO);
9509+ }
dece6358 9510+
4f0767ce 9511+out:
4a4d8108 9512+ return h_vmop;
dece6358
AM
9513+}
9514+
1308ab2a 9515+/*
4a4d8108
AM
9516+ * This is another ugly approach to keep the lock order, particularly
9517+ * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
9518+ * find it in git-log, if you want.
1308ab2a 9519+ *
4a4d8108
AM
9520+ * native readdir: i_mutex, copy_to_user, mmap_sem
9521+ * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
1308ab2a 9522+ *
4a4d8108
AM
9523+ * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
9524+ * acquire aufs rwsem. It introduces a circular locking dependency.
9525+ * To address this problem, aufs_mmap() delegates the part which requires aufs
9526+ * rwsem to its internal workqueue.
1308ab2a 9527+ */
9528+
4a4d8108
AM
9529+/* very ugly approach */
9530+#include "mtx.h"
1308ab2a 9531+
4a4d8108
AM
9532+struct au_mmap_pre_args {
9533+ /* input */
9534+ struct file *file;
9535+ struct vm_area_struct *vma;
1308ab2a 9536+
4a4d8108
AM
9537+ /* output */
9538+ int *errp;
9539+ struct file *h_file;
9540+ struct au_branch *br;
9541+ int mmapped;
9542+};
dece6358 9543+
4a4d8108
AM
9544+static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
9545+ struct file **h_file, struct au_branch **br,
9546+ int *mmapped)
dece6358 9547+{
4a4d8108
AM
9548+ int err;
9549+ aufs_bindex_t bstart;
9550+ const unsigned char wlock
9551+ = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
9552+ struct dentry *dentry;
9553+ struct super_block *sb;
1308ab2a 9554+
4a4d8108
AM
9555+ dentry = file->f_dentry;
9556+ sb = dentry->d_sb;
e49829fe 9557+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108
AM
9558+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9559+ if (unlikely(err))
9560+ goto out;
9561+
9562+ *mmapped = !!au_test_mmapped(file);
9563+ if (wlock) {
9564+ struct au_pin pin;
9565+
9566+ err = au_ready_to_write(file, -1, &pin);
9567+ di_write_unlock(dentry);
9568+ if (unlikely(err))
9569+ goto out_unlock;
9570+ au_unpin(&pin);
9571+ } else
9572+ di_write_unlock(dentry);
9573+ bstart = au_fbstart(file);
9574+ *br = au_sbr(sb, bstart);
9575+ *h_file = au_hf_top(file);
9576+ get_file(*h_file);
9577+ au_fi_mmap_lock(file);
9578+
9579+out_unlock:
9580+ fi_write_unlock(file);
9581+out:
9582+ si_read_unlock(sb);
9583+ return err;
dece6358
AM
9584+}
9585+
4a4d8108 9586+static void au_call_mmap_pre(void *args)
dece6358 9587+{
4a4d8108
AM
9588+ struct au_mmap_pre_args *a = args;
9589+ *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->br,
9590+ &a->mmapped);
dece6358
AM
9591+}
9592+
4a4d8108 9593+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 9594+{
4a4d8108
AM
9595+ int err, wkq_err;
9596+ unsigned long h_vmflags;
1308ab2a 9597+ struct au_finfo *finfo;
4a4d8108
AM
9598+ struct dentry *h_dentry;
9599+ struct vm_operations_struct *h_vmop, *vmop;
9600+ struct au_mmap_pre_args args = {
9601+ .file = file,
9602+ .vma = vma,
9603+ .errp = &err
9604+ };
9605+
b752ccd1 9606+ wkq_err = au_wkq_wait_pre(au_call_mmap_pre, &args);
4a4d8108
AM
9607+ if (unlikely(wkq_err))
9608+ err = wkq_err;
9609+ if (unlikely(err))
9610+ goto out;
9611+ finfo = au_fi(file);
9612+ mutex_set_owner(&finfo->fi_mmap);
9613+
9614+ h_dentry = args.h_file->f_dentry;
9615+ if (!args.mmapped && au_test_fs_bad_mapping(h_dentry->d_sb)) {
1308ab2a 9616+ /*
4a4d8108
AM
9617+ * by this assignment, f_mapping will differs from aufs inode
9618+ * i_mapping.
9619+ * if someone else mixes the use of f_dentry->d_inode and
9620+ * f_mapping->host, then a problem may arise.
1308ab2a 9621+ */
4a4d8108
AM
9622+ file->f_mapping = args.h_file->f_mapping;
9623+ }
1308ab2a 9624+
4a4d8108
AM
9625+ /* always try this internal mmap to get vma flags */
9626+ h_vmflags = 0; /* gcc warning */
9627+ h_vmop = au_hvmop(args.h_file, vma, &h_vmflags);
9628+ err = PTR_ERR(h_vmop);
9629+ if (IS_ERR(h_vmop))
9630+ goto out_unlock;
9631+ AuDebugOn(args.mmapped && h_vmop != finfo->fi_hvmop);
9632+
9633+ vmop = (void *)au_dy_vmop(file, args.br, h_vmop);
9634+ err = PTR_ERR(vmop);
9635+ if (IS_ERR(vmop))
9636+ goto out_unlock;
9637+
9638+ /*
9639+ * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
9640+ * currently MAP_DENYWRITE from userspace is ignored, but elf loader
9641+ * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
9642+ * both of the aufs file and the lower file is deny_write_access()-ed.
9643+ * finally I hope we can skip handlling MAP_DENYWRITE here.
9644+ */
9645+ err = generic_file_mmap(file, vma);
9646+ if (unlikely(err))
9647+ goto out_unlock;
9648+
9649+ vma->vm_ops = vmop;
9650+ vma->vm_flags = h_vmflags;
9651+ if (!args.mmapped)
9652+ finfo->fi_hvmop = h_vmop;
9653+
9654+ vfsub_file_accessed(args.h_file);
9655+ /* update without lock, I don't think it a problem */
9656+ fsstack_copy_attr_atime(file->f_dentry->d_inode, h_dentry->d_inode);
9657+
4f0767ce 9658+out_unlock:
4a4d8108
AM
9659+ au_fi_mmap_unlock(file);
9660+ fput(args.h_file);
4f0767ce 9661+out:
4a4d8108
AM
9662+ return err;
9663+}
9664+
9665+/* ---------------------------------------------------------------------- */
9666+
b752ccd1 9667+static int aufs_fsync_nondir(struct file *file, int datasync)
4a4d8108
AM
9668+{
9669+ int err;
9670+ struct au_pin pin;
b752ccd1 9671+ struct dentry *dentry;
4a4d8108
AM
9672+ struct inode *inode;
9673+ struct file *h_file;
9674+ struct super_block *sb;
9675+
b752ccd1 9676+ dentry = file->f_dentry;
4a4d8108
AM
9677+ inode = dentry->d_inode;
9678+ IMustLock(file->f_mapping->host);
9679+ if (inode != file->f_mapping->host) {
9680+ mutex_unlock(&file->f_mapping->host->i_mutex);
9681+ mutex_lock(&inode->i_mutex);
9682+ }
9683+ IMustLock(inode);
9684+
9685+ sb = dentry->d_sb;
e49829fe
JR
9686+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
9687+ if (unlikely(err))
9688+ goto out;
4a4d8108
AM
9689+
9690+ err = 0; /* -EBADF; */ /* posix? */
9691+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
e49829fe 9692+ goto out_si;
4a4d8108
AM
9693+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9694+ if (unlikely(err))
e49829fe 9695+ goto out_si;
4a4d8108
AM
9696+
9697+ err = au_ready_to_write(file, -1, &pin);
9698+ di_downgrade_lock(dentry, AuLock_IR);
9699+ if (unlikely(err))
9700+ goto out_unlock;
9701+ au_unpin(&pin);
9702+
9703+ err = -EINVAL;
9704+ h_file = au_hf_top(file);
9705+ if (h_file->f_op && h_file->f_op->fsync) {
4a4d8108
AM
9706+ struct mutex *h_mtx;
9707+
9708+ /*
9709+ * no filemap_fdatawrite() since aufs file has no its own
9710+ * mapping, but dir.
9711+ */
b752ccd1 9712+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
4a4d8108 9713+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
b752ccd1 9714+ err = h_file->f_op->fsync(h_file, datasync);
4a4d8108
AM
9715+ if (!err)
9716+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9717+ /*ignore*/
9718+ au_cpup_attr_timesizes(inode);
9719+ mutex_unlock(h_mtx);
9720+ }
9721+
4f0767ce 9722+out_unlock:
4a4d8108 9723+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 9724+ fi_write_unlock(file);
e49829fe 9725+out_si:
953406b4 9726+ si_read_unlock(sb);
e49829fe 9727+out:
4a4d8108
AM
9728+ if (inode != file->f_mapping->host) {
9729+ mutex_unlock(&inode->i_mutex);
9730+ mutex_lock(&file->f_mapping->host->i_mutex);
9731+ }
9732+ return err;
dece6358
AM
9733+}
9734+
4a4d8108
AM
9735+/* no one supports this operation, currently */
9736+#if 0
9737+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 9738+{
4a4d8108
AM
9739+ int err;
9740+ struct au_pin pin;
1308ab2a 9741+ struct dentry *dentry;
4a4d8108
AM
9742+ struct inode *inode;
9743+ struct file *file, *h_file;
1308ab2a 9744+
4a4d8108 9745+ file = kio->ki_filp;
1308ab2a 9746+ dentry = file->f_dentry;
4a4d8108 9747+ inode = dentry->d_inode;
e49829fe 9748+ au_mtx_and_read_lock(inode);
4a4d8108
AM
9749+
9750+ err = 0; /* -EBADF; */ /* posix? */
9751+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
9752+ goto out;
9753+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9754+ if (unlikely(err))
1308ab2a 9755+ goto out;
9756+
4a4d8108
AM
9757+ err = au_ready_to_write(file, -1, &pin);
9758+ di_downgrade_lock(dentry, AuLock_IR);
9759+ if (unlikely(err))
9760+ goto out_unlock;
9761+ au_unpin(&pin);
1308ab2a 9762+
4a4d8108
AM
9763+ err = -ENOSYS;
9764+ h_file = au_hf_top(file);
9765+ if (h_file->f_op && h_file->f_op->aio_fsync) {
9766+ struct dentry *h_d;
9767+ struct mutex *h_mtx;
1308ab2a 9768+
4a4d8108
AM
9769+ h_d = h_file->f_dentry;
9770+ h_mtx = &h_d->d_inode->i_mutex;
9771+ if (!is_sync_kiocb(kio)) {
9772+ get_file(h_file);
9773+ fput(file);
9774+ }
9775+ kio->ki_filp = h_file;
9776+ err = h_file->f_op->aio_fsync(kio, datasync);
9777+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
9778+ if (!err)
9779+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9780+ /*ignore*/
9781+ au_cpup_attr_timesizes(inode);
9782+ mutex_unlock(h_mtx);
9783+ }
1308ab2a 9784+
4f0767ce 9785+out_unlock:
4a4d8108
AM
9786+ di_read_unlock(dentry, AuLock_IR);
9787+ fi_write_unlock(file);
4f0767ce 9788+out:
e49829fe 9789+ si_read_unlock(inode->sb);
4a4d8108
AM
9790+ mutex_unlock(&inode->i_mutex);
9791+ return err;
dece6358 9792+}
4a4d8108 9793+#endif
dece6358 9794+
4a4d8108 9795+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 9796+{
4a4d8108
AM
9797+ int err;
9798+ struct file *h_file;
9799+ struct dentry *dentry;
9800+ struct super_block *sb;
1308ab2a 9801+
4a4d8108
AM
9802+ dentry = file->f_dentry;
9803+ sb = dentry->d_sb;
e49829fe 9804+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9805+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9806+ if (unlikely(err))
9807+ goto out;
9808+
9809+ h_file = au_hf_top(file);
9810+ if (h_file->f_op && h_file->f_op->fasync)
9811+ err = h_file->f_op->fasync(fd, h_file, flag);
9812+
9813+ di_read_unlock(dentry, AuLock_IR);
9814+ fi_read_unlock(file);
1308ab2a 9815+
4f0767ce 9816+out:
4a4d8108 9817+ si_read_unlock(sb);
1308ab2a 9818+ return err;
dece6358 9819+}
4a4d8108
AM
9820+
9821+/* ---------------------------------------------------------------------- */
9822+
9823+/* no one supports this operation, currently */
9824+#if 0
9825+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
9826+ size_t len, loff_t *pos , int more)
9827+{
9828+}
9829+#endif
9830+
9831+/* ---------------------------------------------------------------------- */
9832+
9833+const struct file_operations aufs_file_fop = {
9834+ .owner = THIS_MODULE,
9835+ /*
9836+ * while generic_file_llseek/_unlocked() don't use BKL,
9837+ * don't use it since it operates file->f_mapping->host.
9838+ * in aufs, it may be a real file and may confuse users by UDBA.
9839+ */
9840+ /* .llseek = generic_file_llseek, */
9841+
9842+ .read = aufs_read,
9843+ .write = aufs_write,
9844+ .aio_read = aufs_aio_read,
9845+ .aio_write = aufs_aio_write,
9846+#ifdef CONFIG_AUFS_POLL
9847+ .poll = aufs_poll,
9848+#endif
9849+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
9850+#ifdef CONFIG_COMPAT
9851+ .compat_ioctl = aufs_ioctl_nondir, /* same */
9852+#endif
4a4d8108
AM
9853+ .mmap = aufs_mmap,
9854+ .open = aufs_open_nondir,
9855+ .flush = aufs_flush_nondir,
9856+ .release = aufs_release_nondir,
9857+ .fsync = aufs_fsync_nondir,
9858+ /* .aio_fsync = aufs_aio_fsync_nondir, */
9859+ .fasync = aufs_fasync,
9860+ /* .sendpage = aufs_sendpage, */
9861+ .splice_write = aufs_splice_write,
9862+ .splice_read = aufs_splice_read,
9863+#if 0
9864+ .aio_splice_write = aufs_aio_splice_write,
9865+ .aio_splice_read = aufs_aio_splice_read
9866+#endif
9867+};
e49829fe
JR
9868--- /dev/null
9869+++ linux-2.6/fs/aufs/f_op_sp.c 2010-10-24 11:35:52.000000000 +0200
9870@@ -0,0 +1,299 @@
1308ab2a 9871+/*
4a4d8108 9872+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 9873+ *
9874+ * This program, aufs is free software; you can redistribute it and/or modify
9875+ * it under the terms of the GNU General Public License as published by
9876+ * the Free Software Foundation; either version 2 of the License, or
9877+ * (at your option) any later version.
9878+ *
9879+ * This program is distributed in the hope that it will be useful,
9880+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9881+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9882+ * GNU General Public License for more details.
9883+ *
9884+ * You should have received a copy of the GNU General Public License
9885+ * along with this program; if not, write to the Free Software
9886+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9887+ */
dece6358 9888+
1308ab2a 9889+/*
4a4d8108
AM
9890+ * file operations for special files.
9891+ * while they exist in aufs virtually,
9892+ * their file I/O is handled out of aufs.
1308ab2a 9893+ */
9894+
4a4d8108
AM
9895+#include <linux/fs_stack.h>
9896+#include "aufs.h"
1308ab2a 9897+
4a4d8108
AM
9898+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
9899+ unsigned long nv, loff_t pos)
dece6358 9900+{
4a4d8108
AM
9901+ ssize_t err;
9902+ aufs_bindex_t bstart;
9903+ unsigned char wbr;
9904+ struct file *file, *h_file;
9905+ struct super_block *sb;
1308ab2a 9906+
4a4d8108
AM
9907+ file = kio->ki_filp;
9908+ sb = file->f_dentry->d_sb;
9909+ si_read_lock(sb, AuLock_FLUSH);
9910+ fi_read_lock(file);
9911+ bstart = au_fbstart(file);
9912+ h_file = au_hf_top(file);
9913+ fi_read_unlock(file);
9914+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9915+ si_read_unlock(sb);
9916+
9917+ /* do not change the file in kio */
9918+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
9919+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
9920+ if (err > 0 && wbr)
9921+ file_accessed(h_file);
9922+
9923+ return err;
9924+}
9925+
9926+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
9927+ unsigned long nv, loff_t pos)
9928+{
9929+ ssize_t err;
9930+ aufs_bindex_t bstart;
9931+ unsigned char wbr;
9932+ struct super_block *sb;
9933+ struct file *file, *h_file;
9934+
9935+ file = kio->ki_filp;
9936+ sb = file->f_dentry->d_sb;
9937+ si_read_lock(sb, AuLock_FLUSH);
9938+ fi_read_lock(file);
9939+ bstart = au_fbstart(file);
9940+ h_file = au_hf_top(file);
9941+ fi_read_unlock(file);
9942+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9943+ si_read_unlock(sb);
9944+
9945+ /* do not change the file in kio */
9946+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
9947+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
9948+ if (err > 0 && wbr)
9949+ file_update_time(h_file);
9950+
9951+ return err;
9952+}
9953+
9954+/* ---------------------------------------------------------------------- */
9955+
9956+static int aufs_release_sp(struct inode *inode, struct file *file)
9957+{
9958+ int err;
9959+ struct file *h_file;
9960+
9961+ fi_read_lock(file);
9962+ h_file = au_hf_top(file);
9963+ fi_read_unlock(file);
9964+ /* close this fifo in aufs */
9965+ err = h_file->f_op->release(inode, file); /* ignore */
9966+ aufs_release_nondir(inode, file); /* ignore */
9967+ return err;
9968+}
9969+
9970+/* ---------------------------------------------------------------------- */
9971+
9972+/* currently, support only FIFO */
4f0767ce
JR
9973+enum {
9974+ AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
9975+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
9976+ AuSp_Last
9977+};
4a4d8108
AM
9978+static int aufs_open_sp(struct inode *inode, struct file *file);
9979+static struct au_sp_fop {
9980+ int done;
9981+ struct file_operations fop; /* not 'const' */
9982+ spinlock_t spin;
9983+} au_sp_fop[AuSp_Last] = {
9984+ [AuSp_FIFO] = {
9985+ .fop = {
9986+ .owner = THIS_MODULE,
9987+ .open = aufs_open_sp
9988+ }
9989+ }
9990+};
9991+
9992+static void au_init_fop_sp(struct file *file)
9993+{
9994+ struct au_sp_fop *p;
9995+ int i;
9996+ struct file *h_file;
9997+
9998+ p = au_sp_fop;
9999+ if (unlikely(!p->done)) {
10000+ /* initialize first time only */
10001+ static DEFINE_SPINLOCK(spin);
10002+
10003+ spin_lock(&spin);
10004+ if (!p->done) {
10005+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
10006+ != AuSp_Last);
10007+ for (i = 0; i < AuSp_Last; i++)
10008+ spin_lock_init(&p[i].spin);
10009+ p->done = 1;
10010+ }
10011+ spin_unlock(&spin);
10012+ }
10013+
10014+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
10015+ case FMODE_READ:
10016+ i = AuSp_FIFO_R;
10017+ break;
10018+ case FMODE_WRITE:
10019+ i = AuSp_FIFO_W;
10020+ break;
10021+ case FMODE_READ | FMODE_WRITE:
10022+ i = AuSp_FIFO_RW;
10023+ break;
10024+ default:
10025+ BUG();
10026+ }
10027+
10028+ p += i;
10029+ if (unlikely(!p->done)) {
10030+ /* initialize first time only */
10031+ h_file = au_hf_top(file);
10032+ spin_lock(&p->spin);
10033+ if (!p->done) {
10034+ p->fop = *h_file->f_op;
10035+ p->fop.owner = THIS_MODULE;
10036+ if (p->fop.aio_read)
10037+ p->fop.aio_read = aufs_aio_read_sp;
10038+ if (p->fop.aio_write)
10039+ p->fop.aio_write = aufs_aio_write_sp;
10040+ p->fop.release = aufs_release_sp;
10041+ p->done = 1;
10042+ }
10043+ spin_unlock(&p->spin);
10044+ }
10045+ file->f_op = &p->fop;
10046+}
10047+
10048+static int au_cpup_sp(struct dentry *dentry)
10049+{
10050+ int err;
10051+ aufs_bindex_t bcpup;
10052+ struct au_pin pin;
10053+ struct au_wr_dir_args wr_dir_args = {
10054+ .force_btgt = -1,
10055+ .flags = 0
10056+ };
10057+
10058+ AuDbg("%.*s\n", AuDLNPair(dentry));
10059+
10060+ di_read_unlock(dentry, AuLock_IR);
10061+ di_write_lock_child(dentry);
10062+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
10063+ if (unlikely(err < 0))
10064+ goto out;
10065+ bcpup = err;
10066+ err = 0;
10067+ if (bcpup == au_dbstart(dentry))
10068+ goto out; /* success */
10069+
10070+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
10071+ AuPin_MNT_WRITE);
10072+ if (!err) {
10073+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
10074+ au_unpin(&pin);
10075+ }
10076+
4f0767ce 10077+out:
4a4d8108
AM
10078+ di_downgrade_lock(dentry, AuLock_IR);
10079+ return err;
10080+}
10081+
10082+static int au_do_open_sp(struct file *file, int flags)
10083+{
10084+ int err;
10085+ struct dentry *dentry;
10086+ struct super_block *sb;
10087+ struct file *h_file;
10088+ struct inode *h_inode;
10089+
10090+ dentry = file->f_dentry;
10091+ AuDbg("%.*s\n", AuDLNPair(dentry));
10092+
10093+ /*
10094+ * try copying-up.
10095+ * operate on the ro branch is not an error.
10096+ */
10097+ au_cpup_sp(dentry); /* ignore */
10098+
10099+ /* prepare h_file */
10100+ err = au_do_open_nondir(file, vfsub_file_flags(file));
10101+ if (unlikely(err))
10102+ goto out;
10103+
10104+ sb = dentry->d_sb;
10105+ h_file = au_hf_top(file);
10106+ h_inode = h_file->f_dentry->d_inode;
10107+ di_read_unlock(dentry, AuLock_IR);
10108+ fi_write_unlock(file);
10109+ si_read_unlock(sb);
10110+ /* open this fifo in aufs */
10111+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
10112+ si_noflush_read_lock(sb);
10113+ fi_write_lock(file);
10114+ di_read_lock_child(dentry, AuLock_IR);
10115+ if (!err)
10116+ au_init_fop_sp(file);
4a4d8108 10117+
4f0767ce 10118+out:
4a4d8108
AM
10119+ return err;
10120+}
10121+
10122+static int aufs_open_sp(struct inode *inode, struct file *file)
10123+{
10124+ int err;
10125+ struct super_block *sb;
10126+
10127+ sb = file->f_dentry->d_sb;
10128+ si_read_lock(sb, AuLock_FLUSH);
10129+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
10130+ si_read_unlock(sb);
10131+ return err;
10132+}
10133+
10134+/* ---------------------------------------------------------------------- */
10135+
10136+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
10137+{
10138+ init_special_inode(inode, mode, rdev);
10139+
10140+ switch (mode & S_IFMT) {
10141+ case S_IFIFO:
10142+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
10143+ /*FALLTHROUGH*/
10144+ case S_IFCHR:
10145+ case S_IFBLK:
10146+ case S_IFSOCK:
10147+ break;
10148+ default:
10149+ AuDebugOn(1);
10150+ }
10151+}
10152+
10153+int au_special_file(umode_t mode)
10154+{
10155+ int ret;
10156+
10157+ ret = 0;
10158+ switch (mode & S_IFMT) {
10159+ case S_IFIFO:
10160+#if 0
10161+ case S_IFCHR:
10162+ case S_IFBLK:
10163+ case S_IFSOCK:
10164+#endif
10165+ ret = 1;
10166+ }
10167+
10168+ return ret;
10169+}
e49829fe
JR
10170--- /dev/null
10171+++ linux-2.6/fs/aufs/fstype.h 2010-10-24 11:19:23.000000000 +0200
4a4d8108
AM
10172@@ -0,0 +1,497 @@
10173+/*
10174+ * Copyright (C) 2005-2010 Junjiro R. Okajima
10175+ *
10176+ * This program, aufs is free software; you can redistribute it and/or modify
10177+ * it under the terms of the GNU General Public License as published by
10178+ * the Free Software Foundation; either version 2 of the License, or
10179+ * (at your option) any later version.
10180+ *
10181+ * This program is distributed in the hope that it will be useful,
10182+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10183+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10184+ * GNU General Public License for more details.
10185+ *
10186+ * You should have received a copy of the GNU General Public License
10187+ * along with this program; if not, write to the Free Software
10188+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10189+ */
10190+
10191+/*
10192+ * judging filesystem type
10193+ */
10194+
10195+#ifndef __AUFS_FSTYPE_H__
10196+#define __AUFS_FSTYPE_H__
10197+
10198+#ifdef __KERNEL__
10199+
10200+#include <linux/fs.h>
10201+#include <linux/magic.h>
10202+#include <linux/romfs_fs.h>
10203+#include <linux/aufs_type.h>
10204+
10205+static inline int au_test_aufs(struct super_block *sb)
10206+{
10207+ return sb->s_magic == AUFS_SUPER_MAGIC;
10208+}
10209+
10210+static inline const char *au_sbtype(struct super_block *sb)
10211+{
10212+ return sb->s_type->name;
10213+}
1308ab2a 10214+
10215+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
10216+{
10217+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
10218+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
10219+#else
10220+ return 0;
10221+#endif
10222+}
10223+
1308ab2a 10224+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 10225+{
1308ab2a 10226+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
10227+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
10228+#else
10229+ return 0;
10230+#endif
10231+}
10232+
1308ab2a 10233+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 10234+{
1308ab2a 10235+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
10236+ return sb->s_magic == CRAMFS_MAGIC;
10237+#endif
10238+ return 0;
10239+}
10240+
10241+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
10242+{
10243+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
10244+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
10245+#else
10246+ return 0;
10247+#endif
10248+}
10249+
1308ab2a 10250+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 10251+{
1308ab2a 10252+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
10253+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
10254+#else
10255+ return 0;
10256+#endif
10257+}
10258+
1308ab2a 10259+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 10260+{
1308ab2a 10261+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
10262+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
10263+#else
10264+ return 0;
10265+#endif
10266+}
10267+
1308ab2a 10268+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 10269+{
1308ab2a 10270+#ifdef CONFIG_TMPFS
10271+ return sb->s_magic == TMPFS_MAGIC;
10272+#else
10273+ return 0;
dece6358 10274+#endif
dece6358
AM
10275+}
10276+
1308ab2a 10277+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 10278+{
1308ab2a 10279+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
10280+ return !strcmp(au_sbtype(sb), "ecryptfs");
10281+#else
10282+ return 0;
10283+#endif
1facf9fc 10284+}
10285+
1308ab2a 10286+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 10287+{
1308ab2a 10288+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
10289+ return sb->s_magic == SMB_SUPER_MAGIC;
10290+#else
10291+ return 0;
1facf9fc 10292+#endif
1facf9fc 10293+}
10294+
1308ab2a 10295+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 10296+{
1308ab2a 10297+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
10298+ return sb->s_magic == OCFS2_SUPER_MAGIC;
10299+#else
10300+ return 0;
10301+#endif
1facf9fc 10302+}
10303+
1308ab2a 10304+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 10305+{
1308ab2a 10306+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
10307+ return sb->s_magic == DLMFS_MAGIC;
10308+#else
10309+ return 0;
10310+#endif
1facf9fc 10311+}
10312+
1308ab2a 10313+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 10314+{
1308ab2a 10315+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
10316+ return sb->s_magic == CODA_SUPER_MAGIC;
10317+#else
10318+ return 0;
10319+#endif
10320+}
10321+
10322+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
10323+{
10324+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
10325+ return sb->s_magic == V9FS_MAGIC;
10326+#else
10327+ return 0;
10328+#endif
10329+}
10330+
10331+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
10332+{
10333+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
10334+ return sb->s_magic == EXT4_SUPER_MAGIC;
10335+#else
10336+ return 0;
10337+#endif
10338+}
10339+
10340+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
10341+{
10342+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
10343+ return !strcmp(au_sbtype(sb), "sysv");
10344+#else
10345+ return 0;
10346+#endif
10347+}
10348+
10349+static inline int au_test_ramfs(struct super_block *sb)
10350+{
10351+ return sb->s_magic == RAMFS_MAGIC;
10352+}
10353+
10354+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
10355+{
10356+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
10357+ return sb->s_magic == UBIFS_SUPER_MAGIC;
10358+#else
10359+ return 0;
10360+#endif
10361+}
10362+
10363+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
10364+{
10365+#ifdef CONFIG_PROC_FS
10366+ return sb->s_magic == PROC_SUPER_MAGIC;
10367+#else
10368+ return 0;
10369+#endif
10370+}
10371+
10372+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
10373+{
10374+#ifdef CONFIG_SYSFS
10375+ return sb->s_magic == SYSFS_MAGIC;
10376+#else
10377+ return 0;
10378+#endif
10379+}
10380+
10381+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
10382+{
10383+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
10384+ return sb->s_magic == CONFIGFS_MAGIC;
10385+#else
10386+ return 0;
10387+#endif
10388+}
10389+
10390+static inline int au_test_minix(struct super_block *sb __maybe_unused)
10391+{
10392+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
10393+ return sb->s_magic == MINIX3_SUPER_MAGIC
10394+ || sb->s_magic == MINIX2_SUPER_MAGIC
10395+ || sb->s_magic == MINIX2_SUPER_MAGIC2
10396+ || sb->s_magic == MINIX_SUPER_MAGIC
10397+ || sb->s_magic == MINIX_SUPER_MAGIC2;
10398+#else
10399+ return 0;
10400+#endif
10401+}
10402+
10403+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
10404+{
10405+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
10406+ return sb->s_magic == CIFS_MAGIC_NUMBER;
10407+#else
10408+ return 0;
10409+#endif
10410+}
10411+
10412+static inline int au_test_fat(struct super_block *sb __maybe_unused)
10413+{
10414+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
10415+ return sb->s_magic == MSDOS_SUPER_MAGIC;
10416+#else
10417+ return 0;
10418+#endif
10419+}
10420+
10421+static inline int au_test_msdos(struct super_block *sb)
10422+{
10423+ return au_test_fat(sb);
10424+}
10425+
10426+static inline int au_test_vfat(struct super_block *sb)
10427+{
10428+ return au_test_fat(sb);
10429+}
10430+
10431+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
10432+{
10433+#ifdef CONFIG_SECURITYFS
10434+ return sb->s_magic == SECURITYFS_MAGIC;
10435+#else
10436+ return 0;
10437+#endif
10438+}
10439+
10440+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
10441+{
10442+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
10443+ return sb->s_magic == SQUASHFS_MAGIC;
10444+#else
10445+ return 0;
10446+#endif
10447+}
10448+
10449+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
10450+{
10451+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
10452+ return sb->s_magic == BTRFS_SUPER_MAGIC;
10453+#else
10454+ return 0;
10455+#endif
10456+}
10457+
10458+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
10459+{
10460+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
10461+ return sb->s_magic == XENFS_SUPER_MAGIC;
10462+#else
10463+ return 0;
10464+#endif
10465+}
10466+
10467+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
10468+{
10469+#ifdef CONFIG_DEBUG_FS
10470+ return sb->s_magic == DEBUGFS_MAGIC;
10471+#else
10472+ return 0;
10473+#endif
10474+}
10475+
10476+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
10477+{
10478+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
10479+ return sb->s_magic == NILFS_SUPER_MAGIC;
10480+#else
10481+ return 0;
10482+#endif
10483+}
10484+
4a4d8108
AM
10485+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
10486+{
10487+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
10488+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
10489+#else
10490+ return 0;
10491+#endif
10492+}
10493+
1308ab2a 10494+/* ---------------------------------------------------------------------- */
10495+/*
10496+ * they can't be an aufs branch.
10497+ */
10498+static inline int au_test_fs_unsuppoted(struct super_block *sb)
10499+{
10500+ return
10501+#ifndef CONFIG_AUFS_BR_RAMFS
10502+ au_test_ramfs(sb) ||
10503+#endif
10504+ au_test_procfs(sb)
10505+ || au_test_sysfs(sb)
10506+ || au_test_configfs(sb)
10507+ || au_test_debugfs(sb)
10508+ || au_test_securityfs(sb)
10509+ || au_test_xenfs(sb)
10510+ || au_test_ecryptfs(sb)
10511+ /* || !strcmp(au_sbtype(sb), "unionfs") */
10512+ || au_test_aufs(sb); /* will be supported in next version */
10513+}
10514+
10515+/*
10516+ * If the filesystem supports NFS-export, then it has to support NULL as
10517+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
10518+ * We can apply this principle when we handle a lower filesystem.
10519+ */
10520+static inline int au_test_fs_null_nd(struct super_block *sb)
10521+{
10522+ return !!sb->s_export_op;
10523+}
10524+
10525+static inline int au_test_fs_remote(struct super_block *sb)
10526+{
10527+ return !au_test_tmpfs(sb)
10528+#ifdef CONFIG_AUFS_BR_RAMFS
10529+ && !au_test_ramfs(sb)
10530+#endif
10531+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
10532+}
10533+
10534+/* ---------------------------------------------------------------------- */
10535+
10536+/*
10537+ * Note: these functions (below) are created after reading ->getattr() in all
10538+ * filesystems under linux/fs. it means we have to do so in every update...
10539+ */
10540+
10541+/*
10542+ * some filesystems require getattr to refresh the inode attributes before
10543+ * referencing.
10544+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
10545+ * and leave the work for d_revalidate()
10546+ */
10547+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
10548+{
10549+ return au_test_nfs(sb)
10550+ || au_test_fuse(sb)
10551+ /* || au_test_smbfs(sb) */ /* untested */
10552+ /* || au_test_ocfs2(sb) */ /* untested */
10553+ /* || au_test_btrfs(sb) */ /* untested */
10554+ /* || au_test_coda(sb) */ /* untested */
10555+ /* || au_test_v9fs(sb) */ /* untested */
10556+ ;
10557+}
10558+
10559+/*
10560+ * filesystems which don't maintain i_size or i_blocks.
10561+ */
10562+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
10563+{
10564+ return au_test_xfs(sb)
4a4d8108
AM
10565+ || au_test_btrfs(sb)
10566+ || au_test_ubifs(sb)
10567+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 10568+ /* || au_test_ext4(sb) */ /* untested */
10569+ /* || au_test_ocfs2(sb) */ /* untested */
10570+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
10571+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 10572+ /* || au_test_minix(sb) */ /* untested */
10573+ ;
10574+}
10575+
10576+/*
10577+ * filesystems which don't store the correct value in some of their inode
10578+ * attributes.
10579+ */
10580+static inline int au_test_fs_bad_iattr(struct super_block *sb)
10581+{
10582+ return au_test_fs_bad_iattr_size(sb)
10583+ /* || au_test_cifs(sb) */ /* untested */
10584+ || au_test_fat(sb)
10585+ || au_test_msdos(sb)
10586+ || au_test_vfat(sb);
1facf9fc 10587+}
10588+
10589+/* they don't check i_nlink in link(2) */
10590+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
10591+{
10592+ return au_test_tmpfs(sb)
10593+#ifdef CONFIG_AUFS_BR_RAMFS
10594+ || au_test_ramfs(sb)
10595+#endif
4a4d8108
AM
10596+ || au_test_ubifs(sb)
10597+ || au_test_btrfs(sb)
10598+ || au_test_hfsplus(sb);
1facf9fc 10599+}
10600+
10601+/*
10602+ * filesystems which sets S_NOATIME and S_NOCMTIME.
10603+ */
10604+static inline int au_test_fs_notime(struct super_block *sb)
10605+{
10606+ return au_test_nfs(sb)
10607+ || au_test_fuse(sb)
dece6358 10608+ || au_test_ubifs(sb)
1facf9fc 10609+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 10610+ ;
10611+}
10612+
10613+/*
10614+ * filesystems which requires replacing i_mapping.
10615+ */
10616+static inline int au_test_fs_bad_mapping(struct super_block *sb)
10617+{
dece6358
AM
10618+ return au_test_fuse(sb)
10619+ || au_test_ubifs(sb);
1facf9fc 10620+}
10621+
10622+/* temporary support for i#1 in cramfs */
10623+static inline int au_test_fs_unique_ino(struct inode *inode)
10624+{
10625+ if (au_test_cramfs(inode->i_sb))
10626+ return inode->i_ino != 1;
10627+ return 1;
10628+}
10629+
10630+/* ---------------------------------------------------------------------- */
10631+
10632+/*
10633+ * the filesystem where the xino files placed must support i/o after unlink and
10634+ * maintain i_size and i_blocks.
10635+ */
10636+static inline int au_test_fs_bad_xino(struct super_block *sb)
10637+{
10638+ return au_test_fs_remote(sb)
10639+ || au_test_fs_bad_iattr_size(sb)
10640+#ifdef CONFIG_AUFS_BR_RAMFS
10641+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
10642+#else
10643+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
10644+#endif
10645+ /* don't want unnecessary work for xino */
10646+ || au_test_aufs(sb)
1308ab2a 10647+ || au_test_ecryptfs(sb)
10648+ || au_test_nilfs(sb);
1facf9fc 10649+}
10650+
10651+static inline int au_test_fs_trunc_xino(struct super_block *sb)
10652+{
10653+ return au_test_tmpfs(sb)
10654+ || au_test_ramfs(sb);
10655+}
10656+
10657+/*
10658+ * test if the @sb is real-readonly.
10659+ */
10660+static inline int au_test_fs_rr(struct super_block *sb)
10661+{
10662+ return au_test_squashfs(sb)
10663+ || au_test_iso9660(sb)
10664+ || au_test_cramfs(sb)
10665+ || au_test_romfs(sb);
10666+}
10667+
10668+#endif /* __KERNEL__ */
10669+#endif /* __AUFS_FSTYPE_H__ */
e49829fe
JR
10670--- /dev/null
10671+++ linux-2.6/fs/aufs/hfsnotify.c 2010-10-24 11:37:18.000000000 +0200
d498916e 10672@@ -0,0 +1,226 @@
1facf9fc 10673+/*
4a4d8108 10674+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 10675+ *
10676+ * This program, aufs is free software; you can redistribute it and/or modify
10677+ * it under the terms of the GNU General Public License as published by
10678+ * the Free Software Foundation; either version 2 of the License, or
10679+ * (at your option) any later version.
dece6358
AM
10680+ *
10681+ * This program is distributed in the hope that it will be useful,
10682+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10683+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10684+ * GNU General Public License for more details.
10685+ *
10686+ * You should have received a copy of the GNU General Public License
10687+ * along with this program; if not, write to the Free Software
10688+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 10689+ */
10690+
10691+/*
4a4d8108 10692+ * fsnotify for the lower directories
1facf9fc 10693+ */
10694+
10695+#include "aufs.h"
10696+
4a4d8108
AM
10697+/* FS_IN_IGNORED is unnecessary */
10698+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
10699+ | FS_CREATE | FS_EVENT_ON_CHILD);
10700+static struct fsnotify_group *au_hfsn_group;
1facf9fc 10701+
2bf81694 10702+static void au_hfsn_free_mark(struct fsnotify_mark *entry)
1facf9fc 10703+{
e49829fe
JR
10704+#if 0
10705+ struct au_hnotify *hn = container_of(entry, struct au_hnotify,
10706+ hn_entry);
10707+ au_cache_free_hnotify(hn);
10708+#endif
4a4d8108
AM
10709+ AuDbg("here\n");
10710+}
1facf9fc 10711+
4a4d8108
AM
10712+static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode)
10713+{
2bf81694 10714+ struct fsnotify_mark *entry;
1facf9fc 10715+
e49829fe
JR
10716+ entry = &hn->hn_entry;
10717+ fsnotify_init_mark(entry, au_hfsn_free_mark);
10718+ entry->mask = AuHfsnMask;
d498916e 10719+ return fsnotify_add_mark(entry, au_hfsn_group, h_inode, NULL, 0);
1facf9fc 10720+}
10721+
4a4d8108 10722+static void au_hfsn_free(struct au_hnotify *hn)
1facf9fc 10723+{
2bf81694 10724+ struct fsnotify_mark *entry;
953406b4 10725+
e49829fe 10726+ entry = &hn->hn_entry;
d498916e 10727+ fsnotify_destroy_mark(entry);
e49829fe 10728+ fsnotify_put_mark(entry);
1facf9fc 10729+}
10730+
10731+/* ---------------------------------------------------------------------- */
10732+
4a4d8108 10733+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 10734+{
2bf81694 10735+ struct fsnotify_mark *entry;
1facf9fc 10736+
e49829fe
JR
10737+ entry = &hinode->hi_notify->hn_entry;
10738+ spin_lock(&entry->lock);
1facf9fc 10739+ if (do_set) {
e49829fe
JR
10740+ AuDebugOn(entry->mask & AuHfsnMask);
10741+ entry->mask |= AuHfsnMask;
1facf9fc 10742+ } else {
e49829fe
JR
10743+ AuDebugOn(!(entry->mask & AuHfsnMask));
10744+ entry->mask &= ~AuHfsnMask;
1facf9fc 10745+ }
e49829fe 10746+ spin_unlock(&entry->lock);
4a4d8108 10747+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 10748+}
10749+
4a4d8108 10750+/* ---------------------------------------------------------------------- */
1facf9fc 10751+
4a4d8108
AM
10752+/* #define AuDbgHnotify */
10753+#ifdef AuDbgHnotify
10754+static char *au_hfsn_name(u32 mask)
10755+{
10756+#ifdef CONFIG_AUFS_DEBUG
10757+#define test_ret(flag) if (mask & flag) \
10758+ return #flag;
10759+ test_ret(FS_ACCESS);
10760+ test_ret(FS_MODIFY);
10761+ test_ret(FS_ATTRIB);
10762+ test_ret(FS_CLOSE_WRITE);
10763+ test_ret(FS_CLOSE_NOWRITE);
10764+ test_ret(FS_OPEN);
10765+ test_ret(FS_MOVED_FROM);
10766+ test_ret(FS_MOVED_TO);
10767+ test_ret(FS_CREATE);
10768+ test_ret(FS_DELETE);
10769+ test_ret(FS_DELETE_SELF);
10770+ test_ret(FS_MOVE_SELF);
10771+ test_ret(FS_UNMOUNT);
10772+ test_ret(FS_Q_OVERFLOW);
10773+ test_ret(FS_IN_IGNORED);
10774+ test_ret(FS_IN_ISDIR);
10775+ test_ret(FS_IN_ONESHOT);
10776+ test_ret(FS_EVENT_ON_CHILD);
10777+ return "";
10778+#undef test_ret
10779+#else
10780+ return "??";
10781+#endif
1facf9fc 10782+}
4a4d8108 10783+#endif
1facf9fc 10784+
10785+/* ---------------------------------------------------------------------- */
10786+
4a4d8108
AM
10787+static int au_hfsn_handle_event(struct fsnotify_group *group,
10788+ struct fsnotify_event *event)
1facf9fc 10789+{
10790+ int err;
4a4d8108
AM
10791+ struct au_hnotify *hnotify;
10792+ struct inode *h_dir, *h_inode;
10793+ __u32 mask;
2bf81694 10794+ struct fsnotify_mark *entry;
4a4d8108
AM
10795+ struct qstr h_child_qstr = {
10796+ .name = event->file_name,
10797+ .len = event->name_len
10798+ };
10799+
10800+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 10801+
10802+ err = 0;
e49829fe 10803+ /* if IN_UNMOUNT happens, there must be another bug */
4a4d8108
AM
10804+ mask = event->mask;
10805+ AuDebugOn(mask & FS_UNMOUNT);
e49829fe 10806+ if (mask & (IN_IGNORED | IN_UNMOUNT))
1facf9fc 10807+ goto out;
1facf9fc 10808+
4a4d8108
AM
10809+ h_dir = event->to_tell;
10810+ h_inode = event->inode;
10811+#ifdef AuDbgHnotify
10812+ au_debug(1);
10813+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
10814+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
10815+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
10816+ h_dir->i_ino, mask, au_hfsn_name(mask),
10817+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
10818+ /* WARN_ON(1); */
1facf9fc 10819+ }
4a4d8108 10820+ au_debug(0);
1facf9fc 10821+#endif
4a4d8108 10822+
d498916e 10823+ entry = fsnotify_find_inode_mark(group, h_dir);
e49829fe
JR
10824+ if (entry) {
10825+ hnotify = container_of(entry, struct au_hnotify, hn_entry);
10826+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
10827+ fsnotify_put_mark(entry);
10828+ }
1facf9fc 10829+
4a4d8108
AM
10830+out:
10831+ return err;
10832+}
1facf9fc 10833+
4a4d8108
AM
10834+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
10835+/* it should be exported to modules */
10836+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
e49829fe 10837+ struct inode *h_inode, __u32 mask)
4a4d8108 10838+{
2bf81694 10839+ struct fsnotify_mark *entry;
e49829fe
JR
10840+ bool send;
10841+
d498916e 10842+ entry = fsnotify_find_inode_mark(group, h_inode);
e49829fe
JR
10843+ if (!entry)
10844+ return false;
10845+
4a4d8108 10846+ mask = (mask & ~FS_EVENT_ON_CHILD);
e49829fe
JR
10847+ send = (entry->mask & mask);
10848+
10849+ /* find took a reference */
10850+ fsnotify_put_mark(entry);
10851+
10852+ return send;
4a4d8108
AM
10853+}
10854+
10855+static struct fsnotify_ops au_hfsn_ops = {
10856+ .should_send_event = au_hfsn_should_send_event,
10857+ .handle_event = au_hfsn_handle_event
10858+};
10859+
10860+/* ---------------------------------------------------------------------- */
10861+
10862+static int __init au_hfsn_init(void)
10863+{
10864+ int err;
e49829fe
JR
10865+ unsigned int gn;
10866+ const unsigned int gn_max = 10;
10867+
10868+ gn = 0;
10869+ for (gn = 0; gn < gn_max; gn++) {
10870+ au_hfsn_group = fsnotify_obtain_group(gn, AuHfsnMask,
10871+ &au_hfsn_ops);
10872+ if (au_hfsn_group != ERR_PTR(-EEXIST))
10873+ break;
10874+ }
1facf9fc 10875+
4a4d8108
AM
10876+ err = 0;
10877+ if (IS_ERR(au_hfsn_group)) {
e49829fe 10878+ pr_err("fsnotify_obtain_group() failed %u times\n", gn_max);
4a4d8108
AM
10879+ err = PTR_ERR(au_hfsn_group);
10880+ }
1facf9fc 10881+
1facf9fc 10882+ AuTraceErr(err);
10883+ return err;
10884+}
10885+
4a4d8108 10886+static void au_hfsn_fin(void)
1facf9fc 10887+{
4a4d8108
AM
10888+ fsnotify_put_group(au_hfsn_group);
10889+}
1facf9fc 10890+
4a4d8108
AM
10891+const struct au_hnotify_op au_hnotify_op = {
10892+ .ctl = au_hfsn_ctl,
10893+ .alloc = au_hfsn_alloc,
10894+ .free = au_hfsn_free,
1facf9fc 10895+
4a4d8108
AM
10896+ .fin = au_hfsn_fin,
10897+ .init = au_hfsn_init
10898+};
e49829fe
JR
10899--- /dev/null
10900+++ linux-2.6/fs/aufs/hfsplus.c 2010-10-24 11:19:23.000000000 +0200
4a4d8108
AM
10901@@ -0,0 +1,58 @@
10902+/*
10903+ * Copyright (C) 2010 Junjiro R. Okajima
10904+ *
10905+ * This program, aufs is free software; you can redistribute it and/or modify
10906+ * it under the terms of the GNU General Public License as published by
10907+ * the Free Software Foundation; either version 2 of the License, or
10908+ * (at your option) any later version.
10909+ *
10910+ * This program is distributed in the hope that it will be useful,
10911+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10912+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10913+ * GNU General Public License for more details.
10914+ *
10915+ * You should have received a copy of the GNU General Public License
10916+ * along with this program; if not, write to the Free Software
10917+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10918+ */
1facf9fc 10919+
4a4d8108
AM
10920+/*
10921+ * special support for filesystems which aqucires an inode mutex
10922+ * at final closing a file, eg, hfsplus.
10923+ *
10924+ * This trick is very simple and stupid, just to open the file before really
10925+ * neceeary open to tell hfsplus that this is not the final closing.
10926+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
10927+ * and au_h_open_post() after releasing it.
10928+ */
1facf9fc 10929+
4a4d8108
AM
10930+#include <linux/file.h>
10931+#include "aufs.h"
1facf9fc 10932+
4a4d8108
AM
10933+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
10934+{
10935+ struct file *h_file;
10936+ struct dentry *h_dentry;
1facf9fc 10937+
4a4d8108
AM
10938+ h_dentry = au_h_dptr(dentry, bindex);
10939+ AuDebugOn(!h_dentry);
10940+ AuDebugOn(!h_dentry->d_inode);
10941+ IMustLock(h_dentry->d_inode);
10942+
10943+ h_file = NULL;
10944+ if (au_test_hfsplus(h_dentry->d_sb)
10945+ && S_ISREG(h_dentry->d_inode->i_mode))
10946+ h_file = au_h_open(dentry, bindex,
10947+ O_RDONLY | O_NOATIME | O_LARGEFILE,
10948+ /*file*/NULL);
10949+ return h_file;
1facf9fc 10950+}
10951+
4a4d8108
AM
10952+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
10953+ struct file *h_file)
10954+{
10955+ if (h_file) {
10956+ fput(h_file);
10957+ au_sbr_put(dentry->d_sb, bindex);
10958+ }
10959+}
e49829fe
JR
10960--- /dev/null
10961+++ linux-2.6/fs/aufs/hinotify.c 2010-10-24 11:11:14.000000000 +0200
10962@@ -0,0 +1,231 @@
10963+/*
10964+ * Copyright (C) 2005-2010 Junjiro R. Okajima
10965+ *
10966+ * This program, aufs is free software; you can redistribute it and/or modify
10967+ * it under the terms of the GNU General Public License as published by
10968+ * the Free Software Foundation; either version 2 of the License, or
10969+ * (at your option) any later version.
10970+ *
10971+ * This program is distributed in the hope that it will be useful,
10972+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10973+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10974+ * GNU General Public License for more details.
10975+ *
10976+ * You should have received a copy of the GNU General Public License
10977+ * along with this program; if not, write to the Free Software
10978+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10979+ */
10980+
10981+/*
10982+ * inotify for the lower directories (deprecated)
10983+ */
10984+
10985+#include "aufs.h"
10986+
10987+static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
10988+static struct inotify_handle *au_hin_handle;
10989+
10990+/* ---------------------------------------------------------------------- */
10991+
10992+static int au_hin_alloc(struct au_hnotify *hn, struct inode *h_inode)
10993+{
10994+ int err;
10995+ s32 wd;
10996+ struct inotify_watch *watch;
10997+
10998+ err = -EEXIST;
10999+ wd = inotify_find_watch(au_hin_handle, h_inode, &watch);
11000+ if (wd >= 0) {
11001+ put_inotify_watch(watch);
11002+ goto out;
11003+ }
11004+
11005+ err = 0;
11006+ inotify_init_watch(&hn->hn_watch);
11007+ wd = inotify_add_watch(au_hin_handle, &hn->hn_watch, h_inode,
11008+ AuHinMask);
11009+ if (unlikely(wd < 0)) {
11010+ err = wd;
11011+ put_inotify_watch(&hn->hn_watch);
11012+ }
11013+
11014+out:
11015+ return err;
11016+}
11017+
11018+static void au_hin_free(struct au_hnotify *hn)
11019+{
11020+ int err;
11021+
11022+ err = 0;
11023+ if (atomic_read(&hn->hn_watch.count))
11024+ err = inotify_rm_watch(au_hin_handle, &hn->hn_watch);
11025+ if (unlikely(err))
11026+ /* it means the watch is already removed */
11027+ pr_warning("failed inotify_rm_watch() %d\n", err);
11028+}
11029+
11030+/* ---------------------------------------------------------------------- */
11031+
11032+static void au_hin_ctl(struct au_hinode *hinode, int do_set)
11033+{
11034+ struct inode *h_inode;
11035+ struct inotify_watch *watch;
11036+
11037+ h_inode = hinode->hi_inode;
11038+ IMustLock(h_inode);
11039+
11040+ /* todo: try inotify_find_update_watch()? */
11041+ watch = &hinode->hi_notify->hn_watch;
11042+ mutex_lock(&h_inode->inotify_mutex);
11043+ /* mutex_lock(&watch->ih->mutex); */
11044+ if (do_set) {
11045+ AuDebugOn(watch->mask & AuHinMask);
11046+ watch->mask |= AuHinMask;
11047+ } else {
11048+ AuDebugOn(!(watch->mask & AuHinMask));
11049+ watch->mask &= ~AuHinMask;
11050+ }
11051+ /* mutex_unlock(&watch->ih->mutex); */
11052+ mutex_unlock(&h_inode->inotify_mutex);
11053+}
11054+
11055+/* ---------------------------------------------------------------------- */
11056+
11057+#ifdef AuDbgHnotify
11058+static char *in_name(u32 mask)
11059+{
11060+#ifdef CONFIG_AUFS_DEBUG
11061+#define test_ret(flag) if (mask & flag) \
11062+ return #flag;
11063+ test_ret(IN_ACCESS);
11064+ test_ret(IN_MODIFY);
11065+ test_ret(IN_ATTRIB);
11066+ test_ret(IN_CLOSE_WRITE);
11067+ test_ret(IN_CLOSE_NOWRITE);
11068+ test_ret(IN_OPEN);
11069+ test_ret(IN_MOVED_FROM);
11070+ test_ret(IN_MOVED_TO);
11071+ test_ret(IN_CREATE);
11072+ test_ret(IN_DELETE);
11073+ test_ret(IN_DELETE_SELF);
11074+ test_ret(IN_MOVE_SELF);
11075+ test_ret(IN_UNMOUNT);
11076+ test_ret(IN_Q_OVERFLOW);
11077+ test_ret(IN_IGNORED);
11078+ return "";
11079+#undef test_ret
11080+#else
11081+ return "??";
11082+#endif
11083+}
11084+#endif
11085+
11086+static u32 au_hin_conv_mask(u32 mask)
11087+{
11088+ u32 conv;
11089+
11090+ conv = 0;
11091+#define do_conv(flag) do { \
11092+ conv |= (mask & IN_ ## flag) ? FS_ ## flag : 0; \
11093+ } while (0)
11094+ do_conv(ACCESS);
11095+ do_conv(MODIFY);
11096+ do_conv(ATTRIB);
11097+ do_conv(CLOSE_WRITE);
11098+ do_conv(CLOSE_NOWRITE);
11099+ do_conv(OPEN);
11100+ do_conv(MOVED_FROM);
11101+ do_conv(MOVED_TO);
11102+ do_conv(CREATE);
11103+ do_conv(DELETE);
11104+ do_conv(DELETE_SELF);
11105+ do_conv(MOVE_SELF);
11106+ do_conv(UNMOUNT);
11107+ do_conv(Q_OVERFLOW);
11108+#undef do_conv
11109+#define do_conv(flag) do { \
11110+ conv |= (mask & IN_ ## flag) ? FS_IN_ ## flag : 0; \
11111+ } while (0)
11112+ do_conv(IGNORED);
11113+ /* do_conv(ISDIR); */
11114+ /* do_conv(ONESHOT); */
11115+#undef do_conv
11116+
11117+ return conv;
11118+}
11119+
11120+static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
11121+ u32 mask, u32 cookie __maybe_unused,
11122+ const char *h_child_name, struct inode *h_child_inode)
11123+{
11124+ struct au_hnotify *hnotify;
11125+ struct qstr h_child_qstr = {
11126+ .name = h_child_name
11127+ };
11128+
11129+ /* if IN_UNMOUNT happens, there must be another bug */
11130+ AuDebugOn(mask & IN_UNMOUNT);
11131+ if (mask & (IN_IGNORED | IN_UNMOUNT)) {
11132+ put_inotify_watch(watch);
11133+ return;
11134+ }
11135+
11136+#ifdef AuDbgHnotify
11137+ au_debug(1);
11138+ if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
11139+ AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
11140+ " hi%lu\n",
11141+ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
11142+ h_child_name ? h_child_name : "",
11143+ h_child_inode ? h_child_inode->i_ino : 0);
11144+ WARN_ON(1);
11145+ }
11146+ au_debug(0);
11147+#endif
11148+
11149+ if (h_child_name)
11150+ h_child_qstr.len = strlen(h_child_name);
11151+ hnotify = container_of(watch, struct au_hnotify, hn_watch);
11152+ mask = au_hin_conv_mask(mask);
11153+ au_hnotify(watch->inode, hnotify, mask, &h_child_qstr, h_child_inode);
11154+}
11155+
11156+static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
11157+{
11158+ return;
11159+}
11160+
11161+static struct inotify_operations aufs_inotify_ops = {
11162+ .handle_event = aufs_inotify,
11163+ .destroy_watch = aufs_inotify_destroy
11164+};
11165+
11166+/* ---------------------------------------------------------------------- */
11167+
11168+static int __init au_hin_init(void)
11169+{
11170+ int err;
11171+
11172+ err = 0;
11173+ au_hin_handle = inotify_init(&aufs_inotify_ops);
11174+ if (IS_ERR(au_hin_handle))
11175+ err = PTR_ERR(au_hin_handle);
11176+
11177+ AuTraceErr(err);
11178+ return err;
11179+}
11180+
11181+static void au_hin_fin(void)
11182+{
11183+ inotify_destroy(au_hin_handle);
11184+}
11185+
11186+const struct au_hnotify_op au_hnotify_op = {
11187+ .ctl = au_hin_ctl,
11188+ .alloc = au_hin_alloc,
11189+ .free = au_hin_free,
11190+
11191+ .fin = au_hin_fin,
11192+ .init = au_hin_init
11193+};
11194--- /dev/null
11195+++ linux-2.6/fs/aufs/hnotify.c 2010-10-24 11:37:32.000000000 +0200
11196@@ -0,0 +1,662 @@
1facf9fc 11197+/*
4a4d8108 11198+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 11199+ *
11200+ * This program, aufs is free software; you can redistribute it and/or modify
11201+ * it under the terms of the GNU General Public License as published by
11202+ * the Free Software Foundation; either version 2 of the License, or
11203+ * (at your option) any later version.
dece6358
AM
11204+ *
11205+ * This program is distributed in the hope that it will be useful,
11206+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11207+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11208+ * GNU General Public License for more details.
11209+ *
11210+ * You should have received a copy of the GNU General Public License
11211+ * along with this program; if not, write to the Free Software
11212+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 11213+ */
11214+
11215+/*
4a4d8108 11216+ * abstraction to notify the direct changes on lower directories
1facf9fc 11217+ */
11218+
1308ab2a 11219+#include "aufs.h"
1facf9fc 11220+
4a4d8108
AM
11221+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
11222+ struct inode *h_inode)
dece6358 11223+{
1308ab2a 11224+ int err;
4a4d8108 11225+ struct au_hnotify *hn;
1facf9fc 11226+
4a4d8108
AM
11227+ err = -ENOMEM;
11228+ hn = au_cache_alloc_hnotify();
11229+ if (hn) {
11230+ hn->hn_aufs_inode = inode;
11231+ err = au_hnotify_op.alloc(hn, h_inode);
11232+ if (!err)
11233+ hinode->hi_notify = hn;
11234+ else {
11235+ au_cache_free_hnotify(hn);
11236+ /*
11237+ * The upper dir was removed by udba, but the same named
11238+ * dir left. In this case, aufs assignes a new inode
11239+ * number and set the monitor again.
11240+ * For the lower dir, the old monitnor is still left.
11241+ */
11242+ if (err == -EEXIST)
11243+ err = 0;
11244+ }
1308ab2a 11245+ }
1308ab2a 11246+
1308ab2a 11247+ return err;
dece6358 11248+}
1facf9fc 11249+
4a4d8108 11250+void au_hn_free(struct au_hinode *hinode)
dece6358 11251+{
4a4d8108 11252+ struct au_hnotify *hn;
1facf9fc 11253+
4a4d8108
AM
11254+ hn = hinode->hi_notify;
11255+ if (hn) {
11256+ au_hnotify_op.free(hn);
11257+ au_cache_free_hnotify(hn);
11258+ hinode->hi_notify = NULL;
11259+ }
11260+}
dece6358 11261+
4a4d8108 11262+/* ---------------------------------------------------------------------- */
dece6358 11263+
4a4d8108
AM
11264+void au_hn_ctl(struct au_hinode *hinode, int do_set)
11265+{
11266+ if (hinode->hi_notify)
11267+ au_hnotify_op.ctl(hinode, do_set);
11268+}
11269+
11270+void au_hn_reset(struct inode *inode, unsigned int flags)
11271+{
11272+ aufs_bindex_t bindex, bend;
11273+ struct inode *hi;
11274+ struct dentry *iwhdentry;
1facf9fc 11275+
1308ab2a 11276+ bend = au_ibend(inode);
4a4d8108
AM
11277+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
11278+ hi = au_h_iptr(inode, bindex);
11279+ if (!hi)
11280+ continue;
1308ab2a 11281+
4a4d8108
AM
11282+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
11283+ iwhdentry = au_hi_wh(inode, bindex);
11284+ if (iwhdentry)
11285+ dget(iwhdentry);
11286+ au_igrab(hi);
11287+ au_set_h_iptr(inode, bindex, NULL, 0);
11288+ au_set_h_iptr(inode, bindex, au_igrab(hi),
11289+ flags & ~AuHi_XINO);
11290+ iput(hi);
11291+ dput(iwhdentry);
11292+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 11293+ }
1facf9fc 11294+}
11295+
1308ab2a 11296+/* ---------------------------------------------------------------------- */
1facf9fc 11297+
4a4d8108 11298+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 11299+{
4a4d8108
AM
11300+ int err;
11301+ aufs_bindex_t bindex, bend, bfound, bstart;
11302+ struct inode *h_i;
1facf9fc 11303+
4a4d8108
AM
11304+ err = 0;
11305+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11306+ pr_warning("branch root dir was changed\n");
11307+ goto out;
11308+ }
1facf9fc 11309+
4a4d8108
AM
11310+ bfound = -1;
11311+ bend = au_ibend(inode);
11312+ bstart = au_ibstart(inode);
11313+#if 0 /* reserved for future use */
11314+ if (bindex == bend) {
11315+ /* keep this ino in rename case */
11316+ goto out;
11317+ }
11318+#endif
11319+ for (bindex = bstart; bindex <= bend; bindex++)
11320+ if (au_h_iptr(inode, bindex) == h_inode) {
11321+ bfound = bindex;
11322+ break;
11323+ }
11324+ if (bfound < 0)
1308ab2a 11325+ goto out;
1facf9fc 11326+
4a4d8108
AM
11327+ for (bindex = bstart; bindex <= bend; bindex++) {
11328+ h_i = au_h_iptr(inode, bindex);
11329+ if (!h_i)
11330+ continue;
1facf9fc 11331+
4a4d8108
AM
11332+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
11333+ /* ignore this error */
11334+ /* bad action? */
1facf9fc 11335+ }
1facf9fc 11336+
4a4d8108 11337+ /* children inode number will be broken */
1facf9fc 11338+
4f0767ce 11339+out:
4a4d8108
AM
11340+ AuTraceErr(err);
11341+ return err;
1facf9fc 11342+}
11343+
4a4d8108 11344+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 11345+{
4a4d8108
AM
11346+ int err, i, j, ndentry;
11347+ struct au_dcsub_pages dpages;
11348+ struct au_dpage *dpage;
11349+ struct dentry **dentries;
1facf9fc 11350+
4a4d8108
AM
11351+ err = au_dpages_init(&dpages, GFP_NOFS);
11352+ if (unlikely(err))
11353+ goto out;
11354+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
11355+ if (unlikely(err))
11356+ goto out_dpages;
1facf9fc 11357+
4a4d8108
AM
11358+ for (i = 0; i < dpages.ndpage; i++) {
11359+ dpage = dpages.dpages + i;
11360+ dentries = dpage->dentries;
11361+ ndentry = dpage->ndentry;
11362+ for (j = 0; j < ndentry; j++) {
11363+ struct dentry *d;
11364+
11365+ d = dentries[j];
11366+ if (IS_ROOT(d))
11367+ continue;
11368+
11369+ d_drop(d);
11370+ au_digen_dec(d);
11371+ if (d->d_inode)
11372+ /* todo: reset children xino?
11373+ cached children only? */
11374+ au_iigen_dec(d->d_inode);
1308ab2a 11375+ }
dece6358 11376+ }
1facf9fc 11377+
4f0767ce 11378+out_dpages:
4a4d8108 11379+ au_dpages_free(&dpages);
dece6358 11380+
4a4d8108
AM
11381+ /* discard children */
11382+ dentry_unhash(dentry);
11383+ dput(dentry);
4f0767ce 11384+out:
dece6358
AM
11385+ return err;
11386+}
11387+
1308ab2a 11388+/*
4a4d8108 11389+ * return 0 if processed.
1308ab2a 11390+ */
4a4d8108
AM
11391+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
11392+ const unsigned int isdir)
dece6358 11393+{
1308ab2a 11394+ int err;
4a4d8108
AM
11395+ struct dentry *d;
11396+ struct qstr *dname;
1facf9fc 11397+
4a4d8108
AM
11398+ err = 1;
11399+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11400+ pr_warning("branch root dir was changed\n");
11401+ err = 0;
11402+ goto out;
11403+ }
dece6358 11404+
4a4d8108
AM
11405+ if (!isdir) {
11406+ AuDebugOn(!name);
11407+ au_iigen_dec(inode);
11408+ spin_lock(&dcache_lock);
11409+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
11410+ dname = &d->d_name;
11411+ if (dname->len != nlen
11412+ && memcmp(dname->name, name, nlen))
11413+ continue;
11414+ err = 0;
11415+ spin_lock(&d->d_lock);
11416+ __d_drop(d);
11417+ au_digen_dec(d);
11418+ spin_unlock(&d->d_lock);
11419+ break;
1facf9fc 11420+ }
4a4d8108 11421+ spin_unlock(&dcache_lock);
1308ab2a 11422+ } else {
4a4d8108
AM
11423+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
11424+ d = d_find_alias(inode);
11425+ if (!d) {
11426+ au_iigen_dec(inode);
11427+ goto out;
11428+ }
1facf9fc 11429+
4a4d8108
AM
11430+ dname = &d->d_name;
11431+ if (dname->len == nlen && !memcmp(dname->name, name, nlen))
11432+ err = hn_gen_tree(d);
11433+ dput(d);
11434+ }
1facf9fc 11435+
4f0767ce 11436+out:
4a4d8108 11437+ AuTraceErr(err);
1308ab2a 11438+ return err;
11439+}
dece6358 11440+
4a4d8108 11441+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 11442+{
4a4d8108
AM
11443+ int err;
11444+ struct inode *inode;
1facf9fc 11445+
4a4d8108
AM
11446+ inode = dentry->d_inode;
11447+ if (IS_ROOT(dentry)
11448+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
11449+ ) {
11450+ pr_warning("branch root dir was changed\n");
11451+ return 0;
11452+ }
1308ab2a 11453+
4a4d8108
AM
11454+ err = 0;
11455+ if (!isdir) {
11456+ d_drop(dentry);
11457+ au_digen_dec(dentry);
11458+ if (inode)
11459+ au_iigen_dec(inode);
11460+ } else {
11461+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
11462+ if (inode)
11463+ err = hn_gen_tree(dentry);
11464+ }
11465+
11466+ AuTraceErr(err);
11467+ return err;
1facf9fc 11468+}
11469+
4a4d8108 11470+/* ---------------------------------------------------------------------- */
1facf9fc 11471+
4a4d8108
AM
11472+/* hnotify job flags */
11473+#define AuHnJob_XINO0 1
11474+#define AuHnJob_GEN (1 << 1)
11475+#define AuHnJob_DIRENT (1 << 2)
11476+#define AuHnJob_ISDIR (1 << 3)
11477+#define AuHnJob_TRYXINO0 (1 << 4)
11478+#define AuHnJob_MNTPNT (1 << 5)
11479+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
11480+#define au_fset_hnjob(flags, name) { (flags) |= AuHnJob_##name; }
11481+#define au_fclr_hnjob(flags, name) { (flags) &= ~AuHnJob_##name; }
1facf9fc 11482+
4a4d8108
AM
11483+enum {
11484+ AuHn_CHILD,
11485+ AuHn_PARENT,
11486+ AuHnLast
11487+};
1facf9fc 11488+
4a4d8108
AM
11489+struct au_hnotify_args {
11490+ struct inode *h_dir, *dir, *h_child_inode;
11491+ u32 mask;
11492+ unsigned int flags[AuHnLast];
11493+ unsigned int h_child_nlen;
11494+ char h_child_name[];
11495+};
1facf9fc 11496+
4a4d8108
AM
11497+struct hn_job_args {
11498+ unsigned int flags;
11499+ struct inode *inode, *h_inode, *dir, *h_dir;
11500+ struct dentry *dentry;
11501+ char *h_name;
11502+ int h_nlen;
11503+};
1308ab2a 11504+
4a4d8108
AM
11505+static int hn_job(struct hn_job_args *a)
11506+{
11507+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 11508+
4a4d8108
AM
11509+ /* reset xino */
11510+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
11511+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 11512+
4a4d8108
AM
11513+ if (au_ftest_hnjob(a->flags, TRYXINO0)
11514+ && a->inode
11515+ && a->h_inode) {
11516+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11517+ if (!a->h_inode->i_nlink)
11518+ hn_xino(a->inode, a->h_inode); /* ignore this error */
11519+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 11520+ }
1facf9fc 11521+
4a4d8108
AM
11522+ /* make the generation obsolete */
11523+ if (au_ftest_hnjob(a->flags, GEN)) {
11524+ int err = -1;
11525+ if (a->inode)
11526+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
11527+ isdir);
11528+ if (err && a->dentry)
11529+ hn_gen_by_name(a->dentry, isdir);
11530+ /* ignore this error */
1facf9fc 11531+ }
1facf9fc 11532+
4a4d8108
AM
11533+ /* make dir entries obsolete */
11534+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
11535+ struct au_vdir *vdir;
1facf9fc 11536+
4a4d8108
AM
11537+ vdir = au_ivdir(a->inode);
11538+ if (vdir)
11539+ vdir->vd_jiffy = 0;
11540+ /* IMustLock(a->inode); */
11541+ /* a->inode->i_version++; */
11542+ }
1facf9fc 11543+
4a4d8108
AM
11544+ /* can do nothing but warn */
11545+ if (au_ftest_hnjob(a->flags, MNTPNT)
11546+ && a->dentry
11547+ && d_mountpoint(a->dentry))
11548+ pr_warning("mount-point %.*s is removed or renamed\n",
11549+ AuDLNPair(a->dentry));
1facf9fc 11550+
4a4d8108 11551+ return 0;
1308ab2a 11552+}
1facf9fc 11553+
1308ab2a 11554+/* ---------------------------------------------------------------------- */
1facf9fc 11555+
4a4d8108
AM
11556+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
11557+ struct inode *dir)
1308ab2a 11558+{
4a4d8108
AM
11559+ struct dentry *dentry, *d, *parent;
11560+ struct qstr *dname;
1308ab2a 11561+
4a4d8108
AM
11562+ parent = d_find_alias(dir);
11563+ if (!parent)
11564+ return NULL;
1308ab2a 11565+
4a4d8108
AM
11566+ dentry = NULL;
11567+ spin_lock(&dcache_lock);
11568+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
11569+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
11570+ dname = &d->d_name;
11571+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
11572+ continue;
11573+ if (!atomic_read(&d->d_count) || !d->d_fsdata) {
11574+ spin_lock(&d->d_lock);
11575+ __d_drop(d);
11576+ spin_unlock(&d->d_lock);
11577+ continue;
dece6358 11578+ }
1facf9fc 11579+
4a4d8108
AM
11580+ dentry = dget(d);
11581+ break;
1308ab2a 11582+ }
4a4d8108
AM
11583+ spin_unlock(&dcache_lock);
11584+ dput(parent);
1facf9fc 11585+
4a4d8108
AM
11586+ if (dentry)
11587+ di_write_lock_child(dentry);
1308ab2a 11588+
4a4d8108
AM
11589+ return dentry;
11590+}
dece6358 11591+
4a4d8108
AM
11592+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
11593+ aufs_bindex_t bindex, ino_t h_ino)
11594+{
11595+ struct inode *inode;
11596+ ino_t ino;
11597+ int err;
11598+
11599+ inode = NULL;
11600+ err = au_xino_read(sb, bindex, h_ino, &ino);
11601+ if (!err && ino)
11602+ inode = ilookup(sb, ino);
11603+ if (!inode)
11604+ goto out;
11605+
11606+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11607+ pr_warning("wrong root branch\n");
11608+ iput(inode);
11609+ inode = NULL;
11610+ goto out;
1308ab2a 11611+ }
11612+
4a4d8108 11613+ ii_write_lock_child(inode);
1308ab2a 11614+
4f0767ce 11615+out:
4a4d8108 11616+ return inode;
dece6358
AM
11617+}
11618+
4a4d8108 11619+static void au_hn_bh(void *_args)
1facf9fc 11620+{
4a4d8108
AM
11621+ struct au_hnotify_args *a = _args;
11622+ struct super_block *sb;
11623+ aufs_bindex_t bindex, bend, bfound;
11624+ unsigned char xino, try_iput;
1facf9fc 11625+ int err;
1308ab2a 11626+ struct inode *inode;
4a4d8108
AM
11627+ ino_t h_ino;
11628+ struct hn_job_args args;
11629+ struct dentry *dentry;
11630+ struct au_sbinfo *sbinfo;
1facf9fc 11631+
4a4d8108
AM
11632+ AuDebugOn(!_args);
11633+ AuDebugOn(!a->h_dir);
11634+ AuDebugOn(!a->dir);
11635+ AuDebugOn(!a->mask);
11636+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
11637+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
11638+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 11639+
4a4d8108
AM
11640+ inode = NULL;
11641+ dentry = NULL;
11642+ /*
11643+ * do not lock a->dir->i_mutex here
11644+ * because of d_revalidate() may cause a deadlock.
11645+ */
11646+ sb = a->dir->i_sb;
11647+ AuDebugOn(!sb);
11648+ sbinfo = au_sbi(sb);
11649+ AuDebugOn(!sbinfo);
e49829fe 11650+ si_write_lock(sb, !AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 11651+
4a4d8108
AM
11652+ ii_read_lock_parent(a->dir);
11653+ bfound = -1;
11654+ bend = au_ibend(a->dir);
11655+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
11656+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
11657+ bfound = bindex;
11658+ break;
11659+ }
11660+ ii_read_unlock(a->dir);
11661+ if (unlikely(bfound < 0))
11662+ goto out;
1facf9fc 11663+
4a4d8108
AM
11664+ xino = !!au_opt_test(au_mntflags(sb), XINO);
11665+ h_ino = 0;
11666+ if (a->h_child_inode)
11667+ h_ino = a->h_child_inode->i_ino;
1facf9fc 11668+
4a4d8108
AM
11669+ if (a->h_child_nlen
11670+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
11671+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
11672+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
11673+ a->dir);
11674+ try_iput = 0;
11675+ if (dentry)
11676+ inode = dentry->d_inode;
11677+ if (xino && !inode && h_ino
11678+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
11679+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
11680+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
11681+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
11682+ try_iput = 1;
11683+ }
1facf9fc 11684+
4a4d8108
AM
11685+ args.flags = a->flags[AuHn_CHILD];
11686+ args.dentry = dentry;
11687+ args.inode = inode;
11688+ args.h_inode = a->h_child_inode;
11689+ args.dir = a->dir;
11690+ args.h_dir = a->h_dir;
11691+ args.h_name = a->h_child_name;
11692+ args.h_nlen = a->h_child_nlen;
11693+ err = hn_job(&args);
11694+ if (dentry) {
11695+ if (dentry->d_fsdata)
11696+ di_write_unlock(dentry);
11697+ dput(dentry);
11698+ }
11699+ if (inode && try_iput) {
11700+ ii_write_unlock(inode);
11701+ iput(inode);
11702+ }
1facf9fc 11703+
4a4d8108
AM
11704+ ii_write_lock_parent(a->dir);
11705+ args.flags = a->flags[AuHn_PARENT];
11706+ args.dentry = NULL;
11707+ args.inode = a->dir;
11708+ args.h_inode = a->h_dir;
11709+ args.dir = NULL;
11710+ args.h_dir = NULL;
11711+ args.h_name = NULL;
11712+ args.h_nlen = 0;
11713+ err = hn_job(&args);
11714+ ii_write_unlock(a->dir);
1facf9fc 11715+
4f0767ce 11716+out:
4a4d8108
AM
11717+ au_nwt_done(&sbinfo->si_nowait);
11718+ si_write_unlock(sb);
1308ab2a 11719+
4a4d8108
AM
11720+ iput(a->h_child_inode);
11721+ iput(a->h_dir);
11722+ iput(a->dir);
1308ab2a 11723+ kfree(a);
dece6358 11724+}
1facf9fc 11725+
4a4d8108
AM
11726+/* ---------------------------------------------------------------------- */
11727+
11728+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
11729+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 11730+{
4a4d8108
AM
11731+ int err, len;
11732+ unsigned int flags[AuHnLast];
11733+ unsigned char isdir, isroot, wh;
11734+ struct inode *dir;
11735+ struct au_hnotify_args *args;
11736+ char *p, *h_child_name;
dece6358 11737+
1308ab2a 11738+ err = 0;
4a4d8108
AM
11739+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
11740+ dir = igrab(hnotify->hn_aufs_inode);
11741+ if (!dir)
11742+ goto out;
1facf9fc 11743+
4a4d8108
AM
11744+ isroot = (dir->i_ino == AUFS_ROOT_INO);
11745+ wh = 0;
11746+ h_child_name = (void *)h_child_qstr->name;
11747+ len = h_child_qstr->len;
11748+ if (h_child_name) {
11749+ if (len > AUFS_WH_PFX_LEN
11750+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
11751+ h_child_name += AUFS_WH_PFX_LEN;
11752+ len -= AUFS_WH_PFX_LEN;
11753+ wh = 1;
11754+ }
1facf9fc 11755+ }
dece6358 11756+
4a4d8108
AM
11757+ isdir = 0;
11758+ if (h_child_inode)
11759+ isdir = !!S_ISDIR(h_child_inode->i_mode);
11760+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
11761+ flags[AuHn_CHILD] = 0;
11762+ if (isdir)
11763+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
11764+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
11765+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
11766+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
11767+ case FS_MOVED_FROM:
11768+ case FS_MOVED_TO:
11769+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
11770+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11771+ /*FALLTHROUGH*/
11772+ case FS_CREATE:
11773+ AuDebugOn(!h_child_name || !h_child_inode);
11774+ break;
1facf9fc 11775+
4a4d8108
AM
11776+ case FS_DELETE:
11777+ /*
11778+ * aufs never be able to get this child inode.
11779+ * revalidation should be in d_revalidate()
11780+ * by checking i_nlink, i_generation or d_unhashed().
11781+ */
11782+ AuDebugOn(!h_child_name);
11783+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
11784+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11785+ break;
dece6358 11786+
4a4d8108
AM
11787+ default:
11788+ AuDebugOn(1);
11789+ }
1308ab2a 11790+
4a4d8108
AM
11791+ if (wh)
11792+ h_child_inode = NULL;
1308ab2a 11793+
4a4d8108
AM
11794+ err = -ENOMEM;
11795+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 11796+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
11797+ if (unlikely(!args)) {
11798+ AuErr1("no memory\n");
11799+ iput(dir);
11800+ goto out;
11801+ }
11802+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
11803+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
11804+ args->mask = mask;
11805+ args->dir = dir;
11806+ args->h_dir = igrab(h_dir);
11807+ if (h_child_inode)
11808+ h_child_inode = igrab(h_child_inode); /* can be NULL */
11809+ args->h_child_inode = h_child_inode;
11810+ args->h_child_nlen = len;
11811+ if (len) {
11812+ p = (void *)args;
11813+ p += sizeof(*args);
11814+ memcpy(p, h_child_name, len);
11815+ p[len] = 0;
1308ab2a 11816+ }
1308ab2a 11817+
4a4d8108 11818+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
4a4d8108
AM
11819+ if (unlikely(err)) {
11820+ pr_err("wkq %d\n", err);
11821+ iput(args->h_child_inode);
11822+ iput(args->h_dir);
11823+ iput(args->dir);
11824+ kfree(args);
1facf9fc 11825+ }
1facf9fc 11826+
4a4d8108 11827+out:
1facf9fc 11828+ return err;
11829+}
11830+
4a4d8108
AM
11831+static void au_hn_destroy_cache(void)
11832+{
11833+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
11834+ au_cachep[AuCache_HNOTIFY] = NULL;
11835+}
1308ab2a 11836+
4a4d8108 11837+int __init au_hnotify_init(void)
1facf9fc 11838+{
1308ab2a 11839+ int err;
1308ab2a 11840+
4a4d8108
AM
11841+ err = -ENOMEM;
11842+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
11843+ if (au_cachep[AuCache_HNOTIFY]) {
11844+ err = au_hnotify_op.init();
11845+ if (unlikely(err))
11846+ au_hn_destroy_cache();
1308ab2a 11847+ }
1308ab2a 11848+ AuTraceErr(err);
4a4d8108 11849+ return err;
1308ab2a 11850+}
11851+
4a4d8108 11852+void au_hnotify_fin(void)
1308ab2a 11853+{
4a4d8108
AM
11854+ au_hnotify_op.fin();
11855+ /* cf. au_cache_fin() */
11856+ if (au_cachep[AuCache_HNOTIFY])
11857+ au_hn_destroy_cache();
dece6358 11858+}
e49829fe
JR
11859--- /dev/null
11860+++ linux-2.6/fs/aufs/iinfo.c 2010-10-24 11:38:41.000000000 +0200
11861@@ -0,0 +1,259 @@
dece6358 11862+/*
4a4d8108 11863+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
11864+ *
11865+ * This program, aufs is free software; you can redistribute it and/or modify
11866+ * it under the terms of the GNU General Public License as published by
11867+ * the Free Software Foundation; either version 2 of the License, or
11868+ * (at your option) any later version.
11869+ *
11870+ * This program is distributed in the hope that it will be useful,
11871+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11872+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11873+ * GNU General Public License for more details.
11874+ *
11875+ * You should have received a copy of the GNU General Public License
11876+ * along with this program; if not, write to the Free Software
11877+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11878+ */
1facf9fc 11879+
dece6358 11880+/*
4a4d8108 11881+ * inode private data
dece6358 11882+ */
1facf9fc 11883+
1308ab2a 11884+#include "aufs.h"
1facf9fc 11885+
4a4d8108 11886+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 11887+{
4a4d8108 11888+ struct inode *h_inode;
1facf9fc 11889+
4a4d8108 11890+ IiMustAnyLock(inode);
1facf9fc 11891+
4a4d8108
AM
11892+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
11893+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11894+ return h_inode;
11895+}
1facf9fc 11896+
4a4d8108
AM
11897+/* todo: hard/soft set? */
11898+void au_hiput(struct au_hinode *hinode)
11899+{
11900+ au_hn_free(hinode);
11901+ dput(hinode->hi_whdentry);
11902+ iput(hinode->hi_inode);
11903+}
1facf9fc 11904+
4a4d8108
AM
11905+unsigned int au_hi_flags(struct inode *inode, int isdir)
11906+{
11907+ unsigned int flags;
11908+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 11909+
4a4d8108
AM
11910+ flags = 0;
11911+ if (au_opt_test(mnt_flags, XINO))
11912+ au_fset_hi(flags, XINO);
11913+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
11914+ au_fset_hi(flags, HNOTIFY);
11915+ return flags;
1facf9fc 11916+}
11917+
4a4d8108
AM
11918+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
11919+ struct inode *h_inode, unsigned int flags)
1308ab2a 11920+{
4a4d8108
AM
11921+ struct au_hinode *hinode;
11922+ struct inode *hi;
11923+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 11924+
4a4d8108 11925+ IiMustWriteLock(inode);
dece6358 11926+
4a4d8108
AM
11927+ hinode = iinfo->ii_hinode + bindex;
11928+ hi = hinode->hi_inode;
11929+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11930+
11931+ if (hi)
11932+ au_hiput(hinode);
11933+ hinode->hi_inode = h_inode;
11934+ if (h_inode) {
11935+ int err;
11936+ struct super_block *sb = inode->i_sb;
11937+ struct au_branch *br;
11938+
11939+ if (bindex == iinfo->ii_bstart)
11940+ au_cpup_igen(inode, h_inode);
11941+ br = au_sbr(sb, bindex);
11942+ hinode->hi_id = br->br_id;
11943+ if (au_ftest_hi(flags, XINO)) {
11944+ err = au_xino_write(sb, bindex, h_inode->i_ino,
11945+ inode->i_ino);
11946+ if (unlikely(err))
11947+ AuIOErr1("failed au_xino_write() %d\n", err);
11948+ }
11949+
11950+ if (au_ftest_hi(flags, HNOTIFY)
11951+ && au_br_hnotifyable(br->br_perm)) {
11952+ err = au_hn_alloc(hinode, inode, h_inode);
11953+ if (unlikely(err))
11954+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 11955+ }
11956+ }
4a4d8108 11957+}
dece6358 11958+
4a4d8108
AM
11959+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
11960+ struct dentry *h_wh)
11961+{
11962+ struct au_hinode *hinode;
dece6358 11963+
4a4d8108
AM
11964+ IiMustWriteLock(inode);
11965+
11966+ hinode = au_ii(inode)->ii_hinode + bindex;
11967+ AuDebugOn(hinode->hi_whdentry);
11968+ hinode->hi_whdentry = h_wh;
1facf9fc 11969+}
11970+
4a4d8108 11971+void au_update_iigen(struct inode *inode)
1308ab2a 11972+{
4a4d8108
AM
11973+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
11974+ /* smp_mb(); */ /* atomic_set */
11975+}
1facf9fc 11976+
4a4d8108
AM
11977+/* it may be called at remount time, too */
11978+void au_update_ibrange(struct inode *inode, int do_put_zero)
11979+{
11980+ struct au_iinfo *iinfo;
1facf9fc 11981+
4a4d8108
AM
11982+ iinfo = au_ii(inode);
11983+ if (!iinfo || iinfo->ii_bstart < 0)
11984+ return;
1facf9fc 11985+
4a4d8108 11986+ IiMustWriteLock(inode);
1facf9fc 11987+
4a4d8108
AM
11988+ if (do_put_zero) {
11989+ aufs_bindex_t bindex;
1facf9fc 11990+
4a4d8108
AM
11991+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
11992+ bindex++) {
11993+ struct inode *h_i;
1facf9fc 11994+
4a4d8108
AM
11995+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
11996+ if (h_i && !h_i->i_nlink)
11997+ au_set_h_iptr(inode, bindex, NULL, 0);
11998+ }
11999+ }
1308ab2a 12000+
4a4d8108
AM
12001+ iinfo->ii_bstart = -1;
12002+ while (++iinfo->ii_bstart <= iinfo->ii_bend)
12003+ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
12004+ break;
12005+ if (iinfo->ii_bstart > iinfo->ii_bend) {
12006+ iinfo->ii_bstart = -1;
12007+ iinfo->ii_bend = -1;
12008+ return;
12009+ }
12010+
12011+ iinfo->ii_bend++;
12012+ while (0 <= --iinfo->ii_bend)
12013+ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
12014+ break;
12015+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
1308ab2a 12016+}
1facf9fc 12017+
dece6358 12018+/* ---------------------------------------------------------------------- */
1facf9fc 12019+
4a4d8108 12020+void au_icntnr_init_once(void *_c)
dece6358 12021+{
4a4d8108
AM
12022+ struct au_icntnr *c = _c;
12023+ struct au_iinfo *iinfo = &c->iinfo;
e49829fe 12024+ static struct lock_class_key aufs_ii;
1facf9fc 12025+
4a4d8108 12026+ au_rw_init(&iinfo->ii_rwsem);
e49829fe 12027+ au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
4a4d8108
AM
12028+ inode_init_once(&c->vfs_inode);
12029+}
1facf9fc 12030+
4a4d8108
AM
12031+int au_iinfo_init(struct inode *inode)
12032+{
12033+ struct au_iinfo *iinfo;
12034+ struct super_block *sb;
12035+ int nbr, i;
1facf9fc 12036+
4a4d8108
AM
12037+ sb = inode->i_sb;
12038+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12039+ nbr = au_sbend(sb) + 1;
12040+ if (unlikely(nbr <= 0))
12041+ nbr = 1;
12042+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
12043+ if (iinfo->ii_hinode) {
12044+ for (i = 0; i < nbr; i++)
12045+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 12046+
4a4d8108
AM
12047+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
12048+ /* smp_mb(); */ /* atomic_set */
12049+ iinfo->ii_bstart = -1;
12050+ iinfo->ii_bend = -1;
12051+ iinfo->ii_vdir = NULL;
12052+ return 0;
1308ab2a 12053+ }
4a4d8108
AM
12054+ return -ENOMEM;
12055+}
1facf9fc 12056+
4a4d8108
AM
12057+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
12058+{
12059+ int err, sz;
12060+ struct au_hinode *hip;
1facf9fc 12061+
4a4d8108
AM
12062+ AuRwMustWriteLock(&iinfo->ii_rwsem);
12063+
12064+ err = -ENOMEM;
12065+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
12066+ if (!sz)
12067+ sz = sizeof(*hip);
12068+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
12069+ if (hip) {
12070+ iinfo->ii_hinode = hip;
12071+ err = 0;
1308ab2a 12072+ }
4a4d8108 12073+
1308ab2a 12074+ return err;
1facf9fc 12075+}
12076+
4a4d8108 12077+void au_iinfo_fin(struct inode *inode)
1facf9fc 12078+{
4a4d8108
AM
12079+ struct au_iinfo *iinfo;
12080+ struct au_hinode *hi;
12081+ struct super_block *sb;
b752ccd1
AM
12082+ aufs_bindex_t bindex, bend;
12083+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 12084+
4a4d8108
AM
12085+ iinfo = au_ii(inode);
12086+ /* bad_inode case */
12087+ if (!iinfo)
12088+ return;
1308ab2a 12089+
b752ccd1
AM
12090+ sb = inode->i_sb;
12091+ if (si_pid_test(sb))
12092+ au_xino_delete_inode(inode, unlinked);
12093+ else {
12094+ /*
12095+ * it is safe to hide the dependency between sbinfo and
12096+ * sb->s_umount.
12097+ */
12098+ lockdep_off();
12099+ si_noflush_read_lock(sb);
12100+ au_xino_delete_inode(inode, unlinked);
12101+ si_read_unlock(sb);
12102+ lockdep_on();
12103+ }
12104+
4a4d8108
AM
12105+ if (iinfo->ii_vdir)
12106+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 12107+
b752ccd1
AM
12108+ bindex = iinfo->ii_bstart;
12109+ if (bindex >= 0) {
12110+ hi = iinfo->ii_hinode + bindex;
4a4d8108 12111+ bend = iinfo->ii_bend;
b752ccd1
AM
12112+ while (bindex++ <= bend) {
12113+ if (hi->hi_inode)
4a4d8108 12114+ au_hiput(hi);
4a4d8108
AM
12115+ hi++;
12116+ }
12117+ }
4a4d8108
AM
12118+ kfree(iinfo->ii_hinode);
12119+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 12120+}
e49829fe
JR
12121--- /dev/null
12122+++ linux-2.6/fs/aufs/inode.c 2010-10-24 11:38:51.000000000 +0200
b752ccd1 12123@@ -0,0 +1,443 @@
4a4d8108
AM
12124+/*
12125+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12126+ *
12127+ * This program, aufs is free software; you can redistribute it and/or modify
12128+ * it under the terms of the GNU General Public License as published by
12129+ * the Free Software Foundation; either version 2 of the License, or
12130+ * (at your option) any later version.
12131+ *
12132+ * This program is distributed in the hope that it will be useful,
12133+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12134+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12135+ * GNU General Public License for more details.
12136+ *
12137+ * You should have received a copy of the GNU General Public License
12138+ * along with this program; if not, write to the Free Software
12139+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12140+ */
1facf9fc 12141+
4a4d8108
AM
12142+/*
12143+ * inode functions
12144+ */
1facf9fc 12145+
4a4d8108 12146+#include "aufs.h"
1308ab2a 12147+
4a4d8108
AM
12148+struct inode *au_igrab(struct inode *inode)
12149+{
12150+ if (inode) {
12151+ AuDebugOn(!atomic_read(&inode->i_count));
e49829fe 12152+ atomic_inc(&inode->i_count);
1facf9fc 12153+ }
4a4d8108
AM
12154+ return inode;
12155+}
1facf9fc 12156+
4a4d8108
AM
12157+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
12158+{
12159+ au_cpup_attr_all(inode, /*force*/0);
12160+ au_update_iigen(inode);
12161+ if (do_version)
12162+ inode->i_version++;
dece6358 12163+}
1facf9fc 12164+
4a4d8108 12165+int au_refresh_hinode_self(struct inode *inode, int do_attr)
dece6358 12166+{
4a4d8108
AM
12167+ int err, e;
12168+ aufs_bindex_t bindex, new_bindex;
12169+ unsigned char update;
12170+ struct au_hinode *p, *q, tmp;
1308ab2a 12171+ struct super_block *sb;
4a4d8108 12172+ struct au_iinfo *iinfo;
1facf9fc 12173+
4a4d8108 12174+ IiMustWriteLock(inode);
1facf9fc 12175+
4a4d8108
AM
12176+ update = 0;
12177+ sb = inode->i_sb;
12178+ iinfo = au_ii(inode);
12179+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
12180+ if (unlikely(err))
1308ab2a 12181+ goto out;
1facf9fc 12182+
4a4d8108
AM
12183+ p = iinfo->ii_hinode + iinfo->ii_bstart;
12184+ err = 0;
12185+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12186+ bindex++, p++) {
12187+ if (!p->hi_inode)
12188+ continue;
1facf9fc 12189+
4a4d8108
AM
12190+ new_bindex = au_br_index(sb, p->hi_id);
12191+ if (new_bindex == bindex)
12192+ continue;
1facf9fc 12193+
4a4d8108
AM
12194+ if (new_bindex < 0) {
12195+ update = 1;
12196+ au_hiput(p);
12197+ p->hi_inode = NULL;
12198+ continue;
1308ab2a 12199+ }
4a4d8108
AM
12200+
12201+ if (new_bindex < iinfo->ii_bstart)
12202+ iinfo->ii_bstart = new_bindex;
12203+ if (iinfo->ii_bend < new_bindex)
12204+ iinfo->ii_bend = new_bindex;
12205+ /* swap two lower inode, and loop again */
12206+ q = iinfo->ii_hinode + new_bindex;
12207+ tmp = *q;
12208+ *q = *p;
12209+ *p = tmp;
12210+ if (tmp.hi_inode) {
12211+ bindex--;
12212+ p--;
1308ab2a 12213+ }
12214+ }
4a4d8108
AM
12215+ au_update_ibrange(inode, /*do_put_zero*/0);
12216+ e = au_dy_irefresh(inode);
12217+ if (unlikely(e && !err))
12218+ err = e;
12219+ if (do_attr)
12220+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
1facf9fc 12221+
4f0767ce 12222+out:
4a4d8108
AM
12223+ return err;
12224+}
1facf9fc 12225+
4a4d8108
AM
12226+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
12227+{
12228+ int err, e;
12229+ unsigned int flags;
12230+ aufs_bindex_t bindex, bend;
12231+ unsigned char isdir, update;
12232+ struct au_hinode *p;
12233+ struct au_iinfo *iinfo;
1facf9fc 12234+
4a4d8108
AM
12235+ err = au_refresh_hinode_self(inode, /*do_attr*/0);
12236+ if (unlikely(err))
12237+ goto out;
12238+
12239+ update = 0;
12240+ iinfo = au_ii(inode);
12241+ p = iinfo->ii_hinode + iinfo->ii_bstart;
12242+ isdir = S_ISDIR(inode->i_mode);
12243+ flags = au_hi_flags(inode, isdir);
12244+ bend = au_dbend(dentry);
12245+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
12246+ struct inode *h_i;
12247+ struct dentry *h_d;
12248+
12249+ h_d = au_h_dptr(dentry, bindex);
12250+ if (!h_d || !h_d->d_inode)
12251+ continue;
12252+
12253+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
12254+ h_i = au_h_iptr(inode, bindex);
12255+ if (h_i) {
12256+ if (h_i == h_d->d_inode)
12257+ continue;
12258+ err = -EIO;
12259+ break;
12260+ }
12261+ }
12262+ if (bindex < iinfo->ii_bstart)
12263+ iinfo->ii_bstart = bindex;
12264+ if (iinfo->ii_bend < bindex)
12265+ iinfo->ii_bend = bindex;
12266+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
12267+ update = 1;
1308ab2a 12268+ }
4a4d8108
AM
12269+ au_update_ibrange(inode, /*do_put_zero*/0);
12270+ e = au_dy_irefresh(inode);
12271+ if (unlikely(e && !err))
12272+ err = e;
12273+ au_refresh_hinode_attr(inode, update && isdir);
12274+
4f0767ce 12275+out:
4a4d8108 12276+ AuTraceErr(err);
1308ab2a 12277+ return err;
dece6358
AM
12278+}
12279+
4a4d8108 12280+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 12281+{
4a4d8108
AM
12282+ int err;
12283+ unsigned int flags;
12284+ umode_t mode;
12285+ aufs_bindex_t bindex, bstart, btail;
12286+ unsigned char isdir;
12287+ struct dentry *h_dentry;
12288+ struct inode *h_inode;
12289+ struct au_iinfo *iinfo;
dece6358 12290+
4a4d8108 12291+ IiMustWriteLock(inode);
dece6358 12292+
4a4d8108
AM
12293+ err = 0;
12294+ isdir = 0;
12295+ bstart = au_dbstart(dentry);
12296+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
12297+ mode = h_inode->i_mode;
12298+ switch (mode & S_IFMT) {
12299+ case S_IFREG:
12300+ btail = au_dbtail(dentry);
12301+ inode->i_op = &aufs_iop;
12302+ inode->i_fop = &aufs_file_fop;
12303+ err = au_dy_iaop(inode, bstart, h_inode);
12304+ if (unlikely(err))
12305+ goto out;
12306+ break;
12307+ case S_IFDIR:
12308+ isdir = 1;
12309+ btail = au_dbtaildir(dentry);
12310+ inode->i_op = &aufs_dir_iop;
12311+ inode->i_fop = &aufs_dir_fop;
12312+ break;
12313+ case S_IFLNK:
12314+ btail = au_dbtail(dentry);
12315+ inode->i_op = &aufs_symlink_iop;
12316+ break;
12317+ case S_IFBLK:
12318+ case S_IFCHR:
12319+ case S_IFIFO:
12320+ case S_IFSOCK:
12321+ btail = au_dbtail(dentry);
12322+ inode->i_op = &aufs_iop;
12323+ au_init_special_fop(inode, mode, h_inode->i_rdev);
12324+ break;
12325+ default:
12326+ AuIOErr("Unknown file type 0%o\n", mode);
12327+ err = -EIO;
1308ab2a 12328+ goto out;
4a4d8108 12329+ }
dece6358 12330+
4a4d8108
AM
12331+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
12332+ flags = au_hi_flags(inode, isdir);
12333+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
12334+ && au_ftest_hi(flags, HNOTIFY)
12335+ && dentry->d_name.len > AUFS_WH_PFX_LEN
12336+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
12337+ au_fclr_hi(flags, HNOTIFY);
12338+ iinfo = au_ii(inode);
12339+ iinfo->ii_bstart = bstart;
12340+ iinfo->ii_bend = btail;
12341+ for (bindex = bstart; bindex <= btail; bindex++) {
12342+ h_dentry = au_h_dptr(dentry, bindex);
12343+ if (h_dentry)
12344+ au_set_h_iptr(inode, bindex,
12345+ au_igrab(h_dentry->d_inode), flags);
12346+ }
12347+ au_cpup_attr_all(inode, /*force*/1);
dece6358 12348+
4f0767ce 12349+out:
4a4d8108
AM
12350+ return err;
12351+}
dece6358 12352+
4a4d8108
AM
12353+/* successful returns with iinfo write_locked */
12354+static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
12355+{
12356+ int err;
12357+ aufs_bindex_t bindex, bend;
12358+ struct inode *h_inode, *h_dinode;
dece6358 12359+
4a4d8108 12360+ *matched = 0;
dece6358 12361+
4a4d8108
AM
12362+ /*
12363+ * before this function, if aufs got any iinfo lock, it must be only
12364+ * one, the parent dir.
12365+ * it can happen by UDBA and the obsoleted inode number.
12366+ */
12367+ err = -EIO;
12368+ if (unlikely(inode->i_ino == parent_ino(dentry)))
12369+ goto out;
12370+
12371+ err = 0;
12372+ ii_write_lock_new_child(inode);
12373+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
12374+ bend = au_ibend(inode);
12375+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12376+ h_inode = au_h_iptr(inode, bindex);
12377+ if (h_inode && h_inode == h_dinode) {
12378+ *matched = 1;
12379+ err = 0;
12380+ if (au_iigen(inode) != au_digen(dentry))
12381+ err = au_refresh_hinode(inode, dentry);
12382+ break;
1308ab2a 12383+ }
1facf9fc 12384+ }
dece6358 12385+
4a4d8108
AM
12386+ if (unlikely(err))
12387+ ii_write_unlock(inode);
4f0767ce 12388+out:
1facf9fc 12389+ return err;
12390+}
1facf9fc 12391+
4a4d8108
AM
12392+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12393+ unsigned int d_type, ino_t *ino)
1facf9fc 12394+{
4a4d8108
AM
12395+ int err;
12396+ struct mutex *mtx;
1facf9fc 12397+
b752ccd1 12398+ /* prevent hardlinked inode number from race condition */
4a4d8108 12399+ mtx = NULL;
b752ccd1 12400+ if (d_type != DT_DIR) {
4a4d8108
AM
12401+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
12402+ mutex_lock(mtx);
12403+ }
12404+ err = au_xino_read(sb, bindex, h_ino, ino);
12405+ if (unlikely(err))
12406+ goto out;
1308ab2a 12407+
4a4d8108
AM
12408+ if (!*ino) {
12409+ err = -EIO;
12410+ *ino = au_xino_new_ino(sb);
12411+ if (unlikely(!*ino))
1facf9fc 12412+ goto out;
4a4d8108
AM
12413+ err = au_xino_write(sb, bindex, h_ino, *ino);
12414+ if (unlikely(err))
1308ab2a 12415+ goto out;
1308ab2a 12416+ }
1facf9fc 12417+
4f0767ce 12418+out:
b752ccd1 12419+ if (mtx)
4a4d8108 12420+ mutex_unlock(mtx);
1facf9fc 12421+ return err;
12422+}
12423+
4a4d8108
AM
12424+/* successful returns with iinfo write_locked */
12425+/* todo: return with unlocked? */
12426+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 12427+{
b752ccd1 12428+ struct inode *inode, *h_inode;
4a4d8108
AM
12429+ struct dentry *h_dentry;
12430+ struct super_block *sb;
b752ccd1 12431+ struct mutex *mtx;
4a4d8108
AM
12432+ ino_t h_ino, ino;
12433+ int err, match;
12434+ aufs_bindex_t bstart;
1facf9fc 12435+
4a4d8108
AM
12436+ sb = dentry->d_sb;
12437+ bstart = au_dbstart(dentry);
12438+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
12439+ h_inode = h_dentry->d_inode;
12440+ h_ino = h_inode->i_ino;
12441+
12442+ /*
12443+ * stop 'race'-ing between hardlinks under different
12444+ * parents.
12445+ */
12446+ mtx = NULL;
12447+ if (!S_ISDIR(h_inode->i_mode))
12448+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
12449+
4f0767ce 12450+new_ino:
b752ccd1
AM
12451+ if (mtx)
12452+ mutex_lock(mtx);
4a4d8108
AM
12453+ err = au_xino_read(sb, bstart, h_ino, &ino);
12454+ inode = ERR_PTR(err);
12455+ if (unlikely(err))
12456+ goto out;
b752ccd1 12457+
4a4d8108
AM
12458+ if (!ino) {
12459+ ino = au_xino_new_ino(sb);
12460+ if (unlikely(!ino)) {
12461+ inode = ERR_PTR(-EIO);
dece6358
AM
12462+ goto out;
12463+ }
12464+ }
1facf9fc 12465+
4a4d8108
AM
12466+ AuDbg("i%lu\n", (unsigned long)ino);
12467+ inode = au_iget_locked(sb, ino);
12468+ err = PTR_ERR(inode);
12469+ if (IS_ERR(inode))
1facf9fc 12470+ goto out;
1facf9fc 12471+
4a4d8108
AM
12472+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
12473+ if (inode->i_state & I_NEW) {
12474+ ii_write_lock_new_child(inode);
12475+ err = set_inode(inode, dentry);
12476+ if (!err) {
12477+ unlock_new_inode(inode);
12478+ goto out; /* success */
12479+ }
1308ab2a 12480+
4a4d8108
AM
12481+ ii_write_unlock(inode);
12482+ iget_failed(inode);
12483+ goto out_err;
12484+ } else if (!must_new) {
b752ccd1
AM
12485+ /*
12486+ * horrible race condition between lookup, readdir and copyup
12487+ * (or something).
12488+ */
12489+ if (mtx)
12490+ mutex_unlock(mtx);
4a4d8108 12491+ err = reval_inode(inode, dentry, &match);
b752ccd1
AM
12492+ if (!err) {
12493+ mtx = NULL;
4a4d8108 12494+ goto out; /* success */
b752ccd1
AM
12495+ } else if (match) {
12496+ mtx = NULL;
4a4d8108 12497+ goto out_iput;
b752ccd1
AM
12498+ } else if (mtx)
12499+ mutex_lock(mtx);
4a4d8108
AM
12500+ }
12501+
12502+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
12503+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
12504+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
12505+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
12506+ (unsigned long)h_ino, (unsigned long)ino);
12507+ ino = 0;
12508+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
12509+ if (!err) {
12510+ iput(inode);
b752ccd1
AM
12511+ if (mtx)
12512+ mutex_unlock(mtx);
4a4d8108
AM
12513+ goto new_ino;
12514+ }
1308ab2a 12515+
4f0767ce 12516+out_iput:
4a4d8108 12517+ iput(inode);
4f0767ce 12518+out_err:
4a4d8108 12519+ inode = ERR_PTR(err);
4f0767ce 12520+out:
b752ccd1
AM
12521+ if (mtx)
12522+ mutex_unlock(mtx);
4a4d8108 12523+ return inode;
1facf9fc 12524+}
12525+
4a4d8108 12526+/* ---------------------------------------------------------------------- */
1facf9fc 12527+
4a4d8108
AM
12528+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12529+ struct inode *inode)
12530+{
12531+ int err;
1facf9fc 12532+
4a4d8108 12533+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 12534+
4a4d8108
AM
12535+ /* pseudo-link after flushed may happen out of bounds */
12536+ if (!err
12537+ && inode
12538+ && au_ibstart(inode) <= bindex
12539+ && bindex <= au_ibend(inode)) {
12540+ /*
12541+ * permission check is unnecessary since vfsub routine
12542+ * will be called later
12543+ */
12544+ struct inode *hi = au_h_iptr(inode, bindex);
12545+ if (hi)
12546+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 12547+ }
12548+
4a4d8108
AM
12549+ return err;
12550+}
dece6358 12551+
4a4d8108
AM
12552+int au_test_h_perm(struct inode *h_inode, int mask)
12553+{
12554+ if (!current_fsuid())
12555+ return 0;
12556+ return inode_permission(h_inode, mask);
12557+}
1facf9fc 12558+
4a4d8108
AM
12559+int au_test_h_perm_sio(struct inode *h_inode, int mask)
12560+{
12561+ if (au_test_nfs(h_inode->i_sb)
12562+ && (mask & MAY_WRITE)
12563+ && S_ISDIR(h_inode->i_mode))
12564+ mask |= MAY_READ; /* force permission check */
12565+ return au_test_h_perm(h_inode, mask);
1facf9fc 12566+}
e49829fe
JR
12567--- /dev/null
12568+++ linux-2.6/fs/aufs/inode.h 2010-10-24 15:01:53.000000000 +0200
12569@@ -0,0 +1,514 @@
4a4d8108
AM
12570+/*
12571+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12572+ *
12573+ * This program, aufs is free software; you can redistribute it and/or modify
12574+ * it under the terms of the GNU General Public License as published by
12575+ * the Free Software Foundation; either version 2 of the License, or
12576+ * (at your option) any later version.
12577+ *
12578+ * This program is distributed in the hope that it will be useful,
12579+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12580+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12581+ * GNU General Public License for more details.
12582+ *
12583+ * You should have received a copy of the GNU General Public License
12584+ * along with this program; if not, write to the Free Software
12585+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12586+ */
1facf9fc 12587+
1308ab2a 12588+/*
4a4d8108 12589+ * inode operations
1308ab2a 12590+ */
dece6358 12591+
4a4d8108
AM
12592+#ifndef __AUFS_INODE_H__
12593+#define __AUFS_INODE_H__
dece6358 12594+
4a4d8108 12595+#ifdef __KERNEL__
1308ab2a 12596+
4a4d8108
AM
12597+#include <linux/fs.h>
12598+#include <linux/fsnotify.h>
12599+#include <linux/aufs_type.h>
12600+#include "rwsem.h"
1308ab2a 12601+
4a4d8108 12602+struct vfsmount;
1facf9fc 12603+
4a4d8108
AM
12604+struct au_hnotify {
12605+#ifdef CONFIG_AUFS_HNOTIFY
12606+#ifdef CONFIG_AUFS_HFSNOTIFY
2bf81694 12607+ struct fsnotify_mark hn_entry;
e49829fe
JR
12608+#else
12609+ struct inotify_watch hn_watch;
4a4d8108
AM
12610+#endif
12611+ struct inode *hn_aufs_inode; /* no get/put */
12612+#endif
12613+} ____cacheline_aligned_in_smp;
1facf9fc 12614+
4a4d8108
AM
12615+struct au_hinode {
12616+ struct inode *hi_inode;
12617+ aufs_bindex_t hi_id;
12618+#ifdef CONFIG_AUFS_HNOTIFY
12619+ struct au_hnotify *hi_notify;
12620+#endif
dece6358 12621+
4a4d8108
AM
12622+ /* reference to the copied-up whiteout with get/put */
12623+ struct dentry *hi_whdentry;
12624+};
dece6358 12625+
4a4d8108
AM
12626+struct au_vdir;
12627+struct au_iinfo {
12628+ atomic_t ii_generation;
12629+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 12630+
4a4d8108
AM
12631+ struct au_rwsem ii_rwsem;
12632+ aufs_bindex_t ii_bstart, ii_bend;
12633+ __u32 ii_higen;
12634+ struct au_hinode *ii_hinode;
12635+ struct au_vdir *ii_vdir;
12636+};
1facf9fc 12637+
4a4d8108
AM
12638+struct au_icntnr {
12639+ struct au_iinfo iinfo;
12640+ struct inode vfs_inode;
12641+} ____cacheline_aligned_in_smp;
1308ab2a 12642+
4a4d8108
AM
12643+/* au_pin flags */
12644+#define AuPin_DI_LOCKED 1
12645+#define AuPin_MNT_WRITE (1 << 1)
12646+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
12647+#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
12648+#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
12649+
12650+struct au_pin {
12651+ /* input */
12652+ struct dentry *dentry;
12653+ unsigned int udba;
12654+ unsigned char lsc_di, lsc_hi, flags;
12655+ aufs_bindex_t bindex;
12656+
12657+ /* output */
12658+ struct dentry *parent;
12659+ struct au_hinode *hdir;
12660+ struct vfsmount *h_mnt;
12661+};
1facf9fc 12662+
1308ab2a 12663+/* ---------------------------------------------------------------------- */
12664+
4a4d8108 12665+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 12666+{
4a4d8108 12667+ struct au_iinfo *iinfo;
1facf9fc 12668+
4a4d8108
AM
12669+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12670+ if (iinfo->ii_hinode)
12671+ return iinfo;
12672+ return NULL; /* debugging bad_inode case */
12673+}
1facf9fc 12674+
4a4d8108 12675+/* ---------------------------------------------------------------------- */
1facf9fc 12676+
4a4d8108
AM
12677+/* inode.c */
12678+struct inode *au_igrab(struct inode *inode);
12679+int au_refresh_hinode_self(struct inode *inode, int do_attr);
12680+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
12681+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12682+ unsigned int d_type, ino_t *ino);
12683+struct inode *au_new_inode(struct dentry *dentry, int must_new);
12684+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12685+ struct inode *inode);
12686+int au_test_h_perm(struct inode *h_inode, int mask);
12687+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 12688+
4a4d8108
AM
12689+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
12690+ ino_t h_ino, unsigned int d_type, ino_t *ino)
12691+{
12692+#ifdef CONFIG_AUFS_SHWH
12693+ return au_ino(sb, bindex, h_ino, d_type, ino);
12694+#else
12695+ return 0;
12696+#endif
12697+}
1facf9fc 12698+
4a4d8108
AM
12699+/* i_op.c */
12700+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 12701+
4a4d8108
AM
12702+/* au_wr_dir flags */
12703+#define AuWrDir_ADD_ENTRY 1
12704+#define AuWrDir_ISDIR (1 << 1)
12705+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
12706+#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
12707+#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
1facf9fc 12708+
4a4d8108
AM
12709+struct au_wr_dir_args {
12710+ aufs_bindex_t force_btgt;
12711+ unsigned char flags;
12712+};
12713+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
12714+ struct au_wr_dir_args *args);
dece6358 12715+
4a4d8108
AM
12716+struct dentry *au_pinned_h_parent(struct au_pin *pin);
12717+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
12718+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
12719+ unsigned int udba, unsigned char flags);
12720+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
12721+ unsigned int udba, unsigned char flags) __must_check;
12722+int au_do_pin(struct au_pin *pin) __must_check;
12723+void au_unpin(struct au_pin *pin);
1facf9fc 12724+
4a4d8108
AM
12725+/* i_op_add.c */
12726+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
12727+ struct dentry *h_parent, int isdir);
12728+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
12729+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
12730+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
12731+ struct nameidata *nd);
12732+int aufs_link(struct dentry *src_dentry, struct inode *dir,
12733+ struct dentry *dentry);
12734+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
1facf9fc 12735+
4a4d8108
AM
12736+/* i_op_del.c */
12737+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
12738+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
12739+ struct dentry *h_parent, int isdir);
12740+int aufs_unlink(struct inode *dir, struct dentry *dentry);
12741+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 12742+
4a4d8108
AM
12743+/* i_op_ren.c */
12744+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
12745+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
12746+ struct inode *dir, struct dentry *dentry);
1facf9fc 12747+
4a4d8108
AM
12748+/* iinfo.c */
12749+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
12750+void au_hiput(struct au_hinode *hinode);
12751+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12752+ struct dentry *h_wh);
12753+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 12754+
4a4d8108
AM
12755+/* hinode flags */
12756+#define AuHi_XINO 1
12757+#define AuHi_HNOTIFY (1 << 1)
12758+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
12759+#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; }
12760+#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; }
1facf9fc 12761+
4a4d8108
AM
12762+#ifndef CONFIG_AUFS_HNOTIFY
12763+#undef AuHi_HNOTIFY
12764+#define AuHi_HNOTIFY 0
12765+#endif
1facf9fc 12766+
4a4d8108
AM
12767+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12768+ struct inode *h_inode, unsigned int flags);
1facf9fc 12769+
4a4d8108
AM
12770+void au_update_iigen(struct inode *inode);
12771+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 12772+
4a4d8108
AM
12773+void au_icntnr_init_once(void *_c);
12774+int au_iinfo_init(struct inode *inode);
12775+void au_iinfo_fin(struct inode *inode);
12776+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 12777+
e49829fe 12778+#ifdef CONFIG_PROC_FS
4a4d8108 12779+/* plink.c */
e49829fe
JR
12780+int au_plink_maint(struct super_block *sb, int flags);
12781+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
12782+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
12783+#ifdef CONFIG_AUFS_DEBUG
12784+void au_plink_list(struct super_block *sb);
12785+#else
12786+AuStubVoid(au_plink_list, struct super_block *sb)
12787+#endif
12788+int au_plink_test(struct inode *inode);
12789+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
12790+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
12791+ struct dentry *h_dentry);
e49829fe
JR
12792+void au_plink_put(struct super_block *sb, int verbose);
12793+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 12794+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
12795+#else
12796+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
12797+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
12798+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
12799+AuStubVoid(au_plink_list, struct super_block *sb);
12800+AuStubInt0(au_plink_test, struct inode *inode);
12801+AuStub(struct dentry *, au_plink_lkup, return NULL,
12802+ struct inode *inode, aufs_bindex_t bindex);
12803+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
12804+ struct dentry *h_dentry);
12805+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
12806+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
12807+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
12808+#endif /* CONFIG_PROC_FS */
1facf9fc 12809+
4a4d8108 12810+/* ---------------------------------------------------------------------- */
1308ab2a 12811+
4a4d8108
AM
12812+/* lock subclass for iinfo */
12813+enum {
12814+ AuLsc_II_CHILD, /* child first */
12815+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
12816+ AuLsc_II_CHILD3, /* copyup dirs */
12817+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
12818+ AuLsc_II_PARENT2,
12819+ AuLsc_II_PARENT3, /* copyup dirs */
12820+ AuLsc_II_NEW_CHILD
12821+};
1308ab2a 12822+
1facf9fc 12823+/*
4a4d8108
AM
12824+ * ii_read_lock_child, ii_write_lock_child,
12825+ * ii_read_lock_child2, ii_write_lock_child2,
12826+ * ii_read_lock_child3, ii_write_lock_child3,
12827+ * ii_read_lock_parent, ii_write_lock_parent,
12828+ * ii_read_lock_parent2, ii_write_lock_parent2,
12829+ * ii_read_lock_parent3, ii_write_lock_parent3,
12830+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 12831+ */
4a4d8108
AM
12832+#define AuReadLockFunc(name, lsc) \
12833+static inline void ii_read_lock_##name(struct inode *i) \
12834+{ \
12835+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12836+}
12837+
12838+#define AuWriteLockFunc(name, lsc) \
12839+static inline void ii_write_lock_##name(struct inode *i) \
12840+{ \
12841+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12842+}
12843+
12844+#define AuRWLockFuncs(name, lsc) \
12845+ AuReadLockFunc(name, lsc) \
12846+ AuWriteLockFunc(name, lsc)
12847+
12848+AuRWLockFuncs(child, CHILD);
12849+AuRWLockFuncs(child2, CHILD2);
12850+AuRWLockFuncs(child3, CHILD3);
12851+AuRWLockFuncs(parent, PARENT);
12852+AuRWLockFuncs(parent2, PARENT2);
12853+AuRWLockFuncs(parent3, PARENT3);
12854+AuRWLockFuncs(new_child, NEW_CHILD);
12855+
12856+#undef AuReadLockFunc
12857+#undef AuWriteLockFunc
12858+#undef AuRWLockFuncs
1facf9fc 12859+
12860+/*
4a4d8108 12861+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 12862+ */
4a4d8108 12863+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 12864+
4a4d8108
AM
12865+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
12866+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
12867+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 12868+
4a4d8108 12869+/* ---------------------------------------------------------------------- */
1308ab2a 12870+
4a4d8108
AM
12871+static inline unsigned int au_iigen(struct inode *inode)
12872+{
12873+ return atomic_read(&au_ii(inode)->ii_generation);
12874+}
1308ab2a 12875+
4a4d8108
AM
12876+/* tiny test for inode number */
12877+/* tmpfs generation is too rough */
12878+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
12879+{
12880+ struct au_iinfo *iinfo;
1308ab2a 12881+
4a4d8108
AM
12882+ iinfo = au_ii(inode);
12883+ AuRwMustAnyLock(&iinfo->ii_rwsem);
12884+ return !(iinfo->ii_hsb1 == h_inode->i_sb
12885+ && iinfo->ii_higen == h_inode->i_generation);
12886+}
1308ab2a 12887+
4a4d8108
AM
12888+static inline void au_iigen_dec(struct inode *inode)
12889+{
12890+#ifdef CONFIG_AUFS_HNOTIFY
e49829fe 12891+ atomic_dec(&au_ii(inode)->ii_generation);
4a4d8108
AM
12892+#endif
12893+}
1308ab2a 12894+
4a4d8108 12895+/* ---------------------------------------------------------------------- */
1308ab2a 12896+
4a4d8108
AM
12897+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
12898+ aufs_bindex_t bindex)
12899+{
12900+ IiMustAnyLock(inode);
12901+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
12902+}
1308ab2a 12903+
4a4d8108
AM
12904+static inline aufs_bindex_t au_ibstart(struct inode *inode)
12905+{
12906+ IiMustAnyLock(inode);
12907+ return au_ii(inode)->ii_bstart;
12908+}
1308ab2a 12909+
4a4d8108
AM
12910+static inline aufs_bindex_t au_ibend(struct inode *inode)
12911+{
12912+ IiMustAnyLock(inode);
12913+ return au_ii(inode)->ii_bend;
12914+}
1308ab2a 12915+
4a4d8108
AM
12916+static inline struct au_vdir *au_ivdir(struct inode *inode)
12917+{
12918+ IiMustAnyLock(inode);
12919+ return au_ii(inode)->ii_vdir;
12920+}
1308ab2a 12921+
4a4d8108
AM
12922+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
12923+{
12924+ IiMustAnyLock(inode);
12925+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
12926+}
1308ab2a 12927+
4a4d8108 12928+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12929+{
4a4d8108
AM
12930+ IiMustWriteLock(inode);
12931+ au_ii(inode)->ii_bstart = bindex;
12932+}
1308ab2a 12933+
4a4d8108
AM
12934+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
12935+{
12936+ IiMustWriteLock(inode);
12937+ au_ii(inode)->ii_bend = bindex;
1308ab2a 12938+}
12939+
4a4d8108
AM
12940+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
12941+{
12942+ IiMustWriteLock(inode);
12943+ au_ii(inode)->ii_vdir = vdir;
12944+}
1facf9fc 12945+
4a4d8108 12946+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12947+{
4a4d8108
AM
12948+ IiMustAnyLock(inode);
12949+ return au_ii(inode)->ii_hinode + bindex;
12950+}
dece6358 12951+
4a4d8108 12952+/* ---------------------------------------------------------------------- */
1facf9fc 12953+
4a4d8108
AM
12954+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
12955+{
12956+ if (pin)
12957+ return pin->parent;
12958+ return NULL;
1facf9fc 12959+}
12960+
4a4d8108 12961+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 12962+{
4a4d8108
AM
12963+ if (pin && pin->hdir)
12964+ return pin->hdir->hi_inode;
12965+ return NULL;
1308ab2a 12966+}
1facf9fc 12967+
4a4d8108
AM
12968+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
12969+{
12970+ if (pin)
12971+ return pin->hdir;
12972+ return NULL;
12973+}
1facf9fc 12974+
4a4d8108 12975+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 12976+{
4a4d8108
AM
12977+ if (pin)
12978+ pin->dentry = dentry;
12979+}
1308ab2a 12980+
4a4d8108
AM
12981+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
12982+ unsigned char lflag)
12983+{
12984+ if (pin) {
12985+ /* dirty macros require brackets */
12986+ if (lflag) {
12987+ au_fset_pin(pin->flags, DI_LOCKED);
12988+ } else {
12989+ au_fclr_pin(pin->flags, DI_LOCKED);
12990+ }
1308ab2a 12991+ }
4a4d8108
AM
12992+}
12993+
12994+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
12995+{
12996+ if (pin) {
12997+ dput(pin->parent);
12998+ pin->parent = dget(parent);
1facf9fc 12999+ }
4a4d8108 13000+}
1facf9fc 13001+
4a4d8108
AM
13002+/* ---------------------------------------------------------------------- */
13003+
13004+#ifdef CONFIG_AUFS_HNOTIFY
13005+struct au_hnotify_op {
13006+ void (*ctl)(struct au_hinode *hinode, int do_set);
13007+ int (*alloc)(struct au_hnotify *hn, struct inode *h_inode);
13008+ void (*free)(struct au_hnotify *hn);
13009+
13010+ void (*fin)(void);
13011+ int (*init)(void);
13012+};
13013+
13014+/* hnotify.c */
13015+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
13016+ struct inode *h_inode);
13017+void au_hn_free(struct au_hinode *hinode);
13018+void au_hn_ctl(struct au_hinode *hinode, int do_set);
13019+void au_hn_reset(struct inode *inode, unsigned int flags);
13020+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
13021+ struct qstr *h_child_qstr, struct inode *h_child_inode);
13022+int __init au_hnotify_init(void);
13023+void au_hnotify_fin(void);
13024+
e49829fe 13025+/* hinotify.c */
4a4d8108
AM
13026+extern const struct au_hnotify_op au_hnotify_op;
13027+
13028+static inline
13029+void au_hn_init(struct au_hinode *hinode)
13030+{
13031+ hinode->hi_notify = NULL;
1308ab2a 13032+}
13033+
4a4d8108
AM
13034+#else
13035+static inline
13036+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
13037+ struct inode *inode __maybe_unused,
13038+ struct inode *h_inode __maybe_unused)
1308ab2a 13039+{
4a4d8108
AM
13040+ return -EOPNOTSUPP;
13041+}
1308ab2a 13042+
4a4d8108
AM
13043+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
13044+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
13045+ int do_set __maybe_unused)
13046+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
13047+ unsigned int flags __maybe_unused)
13048+AuStubInt0(__init au_hnotify_init, void)
13049+AuStubVoid(au_hnotify_fin, void)
13050+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
13051+#endif /* CONFIG_AUFS_HNOTIFY */
13052+
13053+static inline void au_hn_suspend(struct au_hinode *hdir)
13054+{
13055+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 13056+}
13057+
4a4d8108 13058+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 13059+{
4a4d8108
AM
13060+ au_hn_ctl(hdir, /*do_set*/1);
13061+}
1308ab2a 13062+
4a4d8108
AM
13063+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
13064+{
13065+ mutex_lock(&hdir->hi_inode->i_mutex);
13066+ au_hn_suspend(hdir);
13067+}
dece6358 13068+
4a4d8108
AM
13069+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
13070+ unsigned int sc __maybe_unused)
13071+{
13072+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
13073+ au_hn_suspend(hdir);
1facf9fc 13074+}
1facf9fc 13075+
4a4d8108
AM
13076+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
13077+{
13078+ au_hn_resume(hdir);
13079+ mutex_unlock(&hdir->hi_inode->i_mutex);
13080+}
13081+
13082+#endif /* __KERNEL__ */
13083+#endif /* __AUFS_INODE_H__ */
e49829fe
JR
13084--- /dev/null
13085+++ linux-2.6/fs/aufs/ioctl.c 2010-10-24 11:39:20.000000000 +0200
13086@@ -0,0 +1,150 @@
4a4d8108
AM
13087+/*
13088+ * Copyright (C) 2005-2010 Junjiro R. Okajima
13089+ *
13090+ * This program, aufs is free software; you can redistribute it and/or modify
13091+ * it under the terms of the GNU General Public License as published by
13092+ * the Free Software Foundation; either version 2 of the License, or
13093+ * (at your option) any later version.
13094+ *
13095+ * This program is distributed in the hope that it will be useful,
13096+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13097+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13098+ * GNU General Public License for more details.
13099+ *
13100+ * You should have received a copy of the GNU General Public License
13101+ * along with this program; if not, write to the Free Software
13102+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13103+ */
13104+
13105+/*
13106+ * ioctl
13107+ * plink-management and readdir in userspace.
13108+ * assist the pathconf(3) wrapper library.
13109+ */
13110+
13111+#include <linux/file.h>
13112+#include "aufs.h"
13113+
13114+static int au_wbr_fd(struct path *path)
13115+{
13116+ int err, fd;
13117+ aufs_bindex_t wbi, bindex, bend;
13118+ struct file *h_file;
13119+ struct super_block *sb;
13120+ struct dentry *root;
13121+ struct au_branch *wbr;
13122+
13123+ err = get_unused_fd();
13124+ if (unlikely(err < 0))
13125+ goto out;
13126+ fd = err;
13127+
13128+ wbi = 0;
13129+ sb = path->dentry->d_sb;
13130+ root = sb->s_root;
13131+ aufs_read_lock(root, AuLock_IR);
13132+ wbr = au_sbr(sb, wbi);
13133+ if (!(path->mnt->mnt_flags & MNT_READONLY)
13134+ && !au_br_writable(wbr->br_perm)) {
13135+ bend = au_sbend(sb);
13136+ for (bindex = 1; bindex <= bend; bindex++) {
13137+ wbr = au_sbr(sb, bindex);
13138+ if (au_br_writable(wbr->br_perm)) {
13139+ wbi = bindex;
13140+ break;
13141+ }
13142+ }
13143+ wbr = au_sbr(sb, wbi);
13144+ }
13145+ AuDbg("wbi %d\n", wbi);
13146+ h_file = au_h_open(root, wbi, O_RDONLY | O_DIRECTORY | O_LARGEFILE,
13147+ NULL);
13148+ aufs_read_unlock(root, AuLock_IR);
13149+ err = PTR_ERR(h_file);
13150+ if (IS_ERR(h_file))
13151+ goto out_fd;
13152+
13153+ atomic_dec(&wbr->br_count); /* cf. au_h_open() */
13154+ fd_install(fd, h_file);
13155+ err = fd;
13156+ goto out; /* success */
13157+
4f0767ce 13158+out_fd:
4a4d8108 13159+ put_unused_fd(fd);
4f0767ce 13160+out:
4a4d8108
AM
13161+ return err;
13162+}
13163+
13164+/* ---------------------------------------------------------------------- */
13165+
13166+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
13167+{
13168+ long err;
13169+
13170+ switch (cmd) {
4a4d8108
AM
13171+ case AUFS_CTL_RDU:
13172+ case AUFS_CTL_RDU_INO:
13173+ err = au_rdu_ioctl(file, cmd, arg);
13174+ break;
13175+
13176+ case AUFS_CTL_WBR_FD:
13177+ err = au_wbr_fd(&file->f_path);
13178+ break;
13179+
13180+ default:
13181+ /* do not call the lower */
13182+ AuDbg("0x%x\n", cmd);
13183+ err = -ENOTTY;
13184+ }
13185+
13186+ AuTraceErr(err);
13187+ return err;
13188+}
13189+
13190+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
13191+{
13192+ long err;
13193+
13194+ switch (cmd) {
13195+ case AUFS_CTL_WBR_FD:
13196+ err = au_wbr_fd(&file->f_path);
13197+ break;
13198+
13199+ default:
13200+ /* do not call the lower */
13201+ AuDbg("0x%x\n", cmd);
13202+ err = -ENOTTY;
13203+ }
13204+
13205+ AuTraceErr(err);
13206+ return err;
13207+}
b752ccd1
AM
13208+
13209+#ifdef CONFIG_COMPAT
13210+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
13211+ unsigned long arg)
13212+{
13213+ long err;
13214+
13215+ switch (cmd) {
13216+ case AUFS_CTL_RDU:
13217+ case AUFS_CTL_RDU_INO:
13218+ err = au_rdu_compat_ioctl(file, cmd, arg);
13219+ break;
13220+
13221+ default:
13222+ err = aufs_ioctl_dir(file, cmd, arg);
13223+ }
13224+
13225+ AuTraceErr(err);
13226+ return err;
13227+}
13228+
13229+#if 0 /* unused yet */
13230+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
13231+ unsigned long arg)
13232+{
13233+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
13234+}
13235+#endif
13236+#endif
e49829fe
JR
13237--- /dev/null
13238+++ linux-2.6/fs/aufs/i_op_add.c 2010-10-24 11:38:14.000000000 +0200
13239@@ -0,0 +1,676 @@
4a4d8108
AM
13240+/*
13241+ * Copyright (C) 2005-2010 Junjiro R. Okajima
13242+ *
13243+ * This program, aufs is free software; you can redistribute it and/or modify
13244+ * it under the terms of the GNU General Public License as published by
13245+ * the Free Software Foundation; either version 2 of the License, or
13246+ * (at your option) any later version.
13247+ *
13248+ * This program is distributed in the hope that it will be useful,
13249+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13250+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13251+ * GNU General Public License for more details.
13252+ *
13253+ * You should have received a copy of the GNU General Public License
13254+ * along with this program; if not, write to the Free Software
13255+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13256+ */
13257+
13258+/*
13259+ * inode operations (add entry)
13260+ */
13261+
13262+#include "aufs.h"
13263+
13264+/*
13265+ * final procedure of adding a new entry, except link(2).
13266+ * remove whiteout, instantiate, copyup the parent dir's times and size
13267+ * and update version.
13268+ * if it failed, re-create the removed whiteout.
13269+ */
13270+static int epilog(struct inode *dir, aufs_bindex_t bindex,
13271+ struct dentry *wh_dentry, struct dentry *dentry)
13272+{
13273+ int err, rerr;
13274+ aufs_bindex_t bwh;
13275+ struct path h_path;
13276+ struct inode *inode, *h_dir;
13277+ struct dentry *wh;
13278+
13279+ bwh = -1;
13280+ if (wh_dentry) {
13281+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
13282+ IMustLock(h_dir);
13283+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
13284+ bwh = au_dbwh(dentry);
13285+ h_path.dentry = wh_dentry;
13286+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
13287+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
13288+ dentry);
13289+ if (unlikely(err))
13290+ goto out;
13291+ }
13292+
13293+ inode = au_new_inode(dentry, /*must_new*/1);
13294+ if (!IS_ERR(inode)) {
13295+ d_instantiate(dentry, inode);
13296+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
13297+ IMustLock(dir);
13298+ if (au_ibstart(dir) == au_dbstart(dentry))
13299+ au_cpup_attr_timesizes(dir);
13300+ dir->i_version++;
13301+ return 0; /* success */
13302+ }
13303+
13304+ err = PTR_ERR(inode);
13305+ if (!wh_dentry)
13306+ goto out;
13307+
13308+ /* revert */
13309+ /* dir inode is locked */
13310+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
13311+ rerr = PTR_ERR(wh);
13312+ if (IS_ERR(wh)) {
13313+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
13314+ AuDLNPair(dentry), err, rerr);
13315+ err = -EIO;
13316+ } else
13317+ dput(wh);
13318+
4f0767ce 13319+out:
4a4d8108
AM
13320+ return err;
13321+}
13322+
13323+/*
13324+ * simple tests for the adding inode operations.
13325+ * following the checks in vfs, plus the parent-child relationship.
13326+ */
13327+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13328+ struct dentry *h_parent, int isdir)
13329+{
13330+ int err;
13331+ umode_t h_mode;
13332+ struct dentry *h_dentry;
13333+ struct inode *h_inode;
13334+
13335+ err = -ENAMETOOLONG;
13336+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13337+ goto out;
13338+
13339+ h_dentry = au_h_dptr(dentry, bindex);
13340+ h_inode = h_dentry->d_inode;
13341+ if (!dentry->d_inode) {
13342+ err = -EEXIST;
13343+ if (unlikely(h_inode))
13344+ goto out;
13345+ } else {
13346+ /* rename(2) case */
13347+ err = -EIO;
13348+ if (unlikely(!h_inode || !h_inode->i_nlink))
13349+ goto out;
13350+
13351+ h_mode = h_inode->i_mode;
13352+ if (!isdir) {
13353+ err = -EISDIR;
13354+ if (unlikely(S_ISDIR(h_mode)))
13355+ goto out;
13356+ } else if (unlikely(!S_ISDIR(h_mode))) {
13357+ err = -ENOTDIR;
13358+ goto out;
13359+ }
13360+ }
13361+
13362+ err = 0;
13363+ /* expected parent dir is locked */
13364+ if (unlikely(h_parent != h_dentry->d_parent))
13365+ err = -EIO;
13366+
4f0767ce 13367+out:
4a4d8108
AM
13368+ AuTraceErr(err);
13369+ return err;
13370+}
13371+
13372+/*
13373+ * initial procedure of adding a new entry.
13374+ * prepare writable branch and the parent dir, lock it,
13375+ * and lookup whiteout for the new entry.
13376+ */
13377+static struct dentry*
13378+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
13379+ struct dentry *src_dentry, struct au_pin *pin,
13380+ struct au_wr_dir_args *wr_dir_args)
13381+{
13382+ struct dentry *wh_dentry, *h_parent;
13383+ struct super_block *sb;
13384+ struct au_branch *br;
13385+ int err;
13386+ unsigned int udba;
13387+ aufs_bindex_t bcpup;
13388+
13389+ AuDbg("%.*s\n", AuDLNPair(dentry));
13390+
13391+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
13392+ bcpup = err;
13393+ wh_dentry = ERR_PTR(err);
13394+ if (unlikely(err < 0))
13395+ goto out;
13396+
13397+ sb = dentry->d_sb;
13398+ udba = au_opt_udba(sb);
13399+ err = au_pin(pin, dentry, bcpup, udba,
13400+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13401+ wh_dentry = ERR_PTR(err);
13402+ if (unlikely(err))
13403+ goto out;
13404+
13405+ h_parent = au_pinned_h_parent(pin);
13406+ if (udba != AuOpt_UDBA_NONE
13407+ && au_dbstart(dentry) == bcpup)
13408+ err = au_may_add(dentry, bcpup, h_parent,
13409+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
13410+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13411+ err = -ENAMETOOLONG;
13412+ wh_dentry = ERR_PTR(err);
13413+ if (unlikely(err))
13414+ goto out_unpin;
13415+
13416+ br = au_sbr(sb, bcpup);
13417+ if (dt) {
13418+ struct path tmp = {
13419+ .dentry = h_parent,
13420+ .mnt = br->br_mnt
13421+ };
13422+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
13423+ }
13424+
13425+ wh_dentry = NULL;
13426+ if (bcpup != au_dbwh(dentry))
13427+ goto out; /* success */
13428+
13429+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
13430+
4f0767ce 13431+out_unpin:
4a4d8108
AM
13432+ if (IS_ERR(wh_dentry))
13433+ au_unpin(pin);
4f0767ce 13434+out:
4a4d8108
AM
13435+ return wh_dentry;
13436+}
13437+
13438+/* ---------------------------------------------------------------------- */
13439+
13440+enum { Mknod, Symlink, Creat };
13441+struct simple_arg {
13442+ int type;
13443+ union {
13444+ struct {
13445+ int mode;
13446+ struct nameidata *nd;
13447+ } c;
13448+ struct {
13449+ const char *symname;
13450+ } s;
13451+ struct {
13452+ int mode;
13453+ dev_t dev;
13454+ } m;
13455+ } u;
13456+};
13457+
13458+static int add_simple(struct inode *dir, struct dentry *dentry,
13459+ struct simple_arg *arg)
13460+{
13461+ int err;
13462+ aufs_bindex_t bstart;
13463+ unsigned char created;
13464+ struct au_dtime dt;
13465+ struct au_pin pin;
13466+ struct path h_path;
13467+ struct dentry *wh_dentry, *parent;
13468+ struct inode *h_dir;
13469+ struct au_wr_dir_args wr_dir_args = {
13470+ .force_btgt = -1,
13471+ .flags = AuWrDir_ADD_ENTRY
13472+ };
13473+
13474+ AuDbg("%.*s\n", AuDLNPair(dentry));
13475+ IMustLock(dir);
13476+
13477+ parent = dentry->d_parent; /* dir inode is locked */
13478+ aufs_read_lock(dentry, AuLock_DW);
13479+ di_write_lock_parent(parent);
13480+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
13481+ &wr_dir_args);
13482+ err = PTR_ERR(wh_dentry);
13483+ if (IS_ERR(wh_dentry))
13484+ goto out;
13485+
13486+ bstart = au_dbstart(dentry);
13487+ h_path.dentry = au_h_dptr(dentry, bstart);
13488+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
13489+ h_dir = au_pinned_h_dir(&pin);
13490+ switch (arg->type) {
13491+ case Creat:
13492+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
13493+ break;
13494+ case Symlink:
13495+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
13496+ break;
13497+ case Mknod:
13498+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
13499+ break;
13500+ default:
13501+ BUG();
13502+ }
13503+ created = !err;
13504+ if (!err)
13505+ err = epilog(dir, bstart, wh_dentry, dentry);
13506+
13507+ /* revert */
13508+ if (unlikely(created && err && h_path.dentry->d_inode)) {
13509+ int rerr;
13510+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
13511+ if (rerr) {
13512+ AuIOErr("%.*s revert failure(%d, %d)\n",
13513+ AuDLNPair(dentry), err, rerr);
13514+ err = -EIO;
13515+ }
13516+ au_dtime_revert(&dt);
13517+ d_drop(dentry);
13518+ }
13519+
13520+ au_unpin(&pin);
13521+ dput(wh_dentry);
13522+
4f0767ce 13523+out:
4a4d8108
AM
13524+ if (unlikely(err)) {
13525+ au_update_dbstart(dentry);
13526+ d_drop(dentry);
13527+ }
13528+ di_write_unlock(parent);
13529+ aufs_read_unlock(dentry, AuLock_DW);
13530+ return err;
13531+}
13532+
13533+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
13534+{
13535+ struct simple_arg arg = {
13536+ .type = Mknod,
13537+ .u.m = {
13538+ .mode = mode,
13539+ .dev = dev
13540+ }
13541+ };
13542+ return add_simple(dir, dentry, &arg);
13543+}
13544+
13545+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
13546+{
13547+ struct simple_arg arg = {
13548+ .type = Symlink,
13549+ .u.s.symname = symname
13550+ };
13551+ return add_simple(dir, dentry, &arg);
13552+}
13553+
13554+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13555+ struct nameidata *nd)
13556+{
13557+ struct simple_arg arg = {
13558+ .type = Creat,
13559+ .u.c = {
13560+ .mode = mode,
13561+ .nd = nd
13562+ }
13563+ };
13564+ return add_simple(dir, dentry, &arg);
13565+}
13566+
13567+/* ---------------------------------------------------------------------- */
13568+
13569+struct au_link_args {
13570+ aufs_bindex_t bdst, bsrc;
13571+ struct au_pin pin;
13572+ struct path h_path;
13573+ struct dentry *src_parent, *parent;
13574+};
13575+
13576+static int au_cpup_before_link(struct dentry *src_dentry,
13577+ struct au_link_args *a)
13578+{
13579+ int err;
13580+ struct dentry *h_src_dentry;
13581+ struct mutex *h_mtx;
13582+ struct file *h_file;
13583+
13584+ di_read_lock_parent(a->src_parent, AuLock_IR);
13585+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
13586+ if (unlikely(err))
13587+ goto out;
13588+
13589+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
13590+ h_mtx = &h_src_dentry->d_inode->i_mutex;
13591+ err = au_pin(&a->pin, src_dentry, a->bdst,
13592+ au_opt_udba(src_dentry->d_sb),
13593+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13594+ if (unlikely(err))
13595+ goto out;
13596+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13597+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13598+ if (IS_ERR(h_file)) {
13599+ err = PTR_ERR(h_file);
13600+ h_file = NULL;
13601+ } else
13602+ err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
13603+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
13604+ mutex_unlock(h_mtx);
13605+ au_h_open_post(src_dentry, a->bsrc, h_file);
13606+ au_unpin(&a->pin);
13607+
4f0767ce 13608+out:
4a4d8108
AM
13609+ di_read_unlock(a->src_parent, AuLock_IR);
13610+ return err;
13611+}
13612+
13613+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
13614+{
13615+ int err;
13616+ unsigned char plink;
13617+ struct inode *h_inode, *inode;
13618+ struct dentry *h_src_dentry;
13619+ struct super_block *sb;
13620+ struct file *h_file;
13621+
13622+ plink = 0;
13623+ h_inode = NULL;
13624+ sb = src_dentry->d_sb;
13625+ inode = src_dentry->d_inode;
13626+ if (au_ibstart(inode) <= a->bdst)
13627+ h_inode = au_h_iptr(inode, a->bdst);
13628+ if (!h_inode || !h_inode->i_nlink) {
13629+ /* copyup src_dentry as the name of dentry. */
13630+ au_set_dbstart(src_dentry, a->bdst);
13631+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
13632+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
13633+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
13634+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13635+ if (IS_ERR(h_file)) {
13636+ err = PTR_ERR(h_file);
13637+ h_file = NULL;
13638+ } else
13639+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
13640+ -1, AuCpup_KEEPLINO,
13641+ a->parent);
13642+ mutex_unlock(&h_inode->i_mutex);
13643+ au_h_open_post(src_dentry, a->bsrc, h_file);
13644+ au_set_h_dptr(src_dentry, a->bdst, NULL);
13645+ au_set_dbstart(src_dentry, a->bsrc);
13646+ } else {
13647+ /* the inode of src_dentry already exists on a.bdst branch */
13648+ h_src_dentry = d_find_alias(h_inode);
13649+ if (!h_src_dentry && au_plink_test(inode)) {
13650+ plink = 1;
13651+ h_src_dentry = au_plink_lkup(inode, a->bdst);
13652+ err = PTR_ERR(h_src_dentry);
13653+ if (IS_ERR(h_src_dentry))
13654+ goto out;
13655+
13656+ if (unlikely(!h_src_dentry->d_inode)) {
13657+ dput(h_src_dentry);
13658+ h_src_dentry = NULL;
13659+ }
13660+
13661+ }
13662+ if (h_src_dentry) {
13663+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13664+ &a->h_path);
13665+ dput(h_src_dentry);
13666+ } else {
13667+ AuIOErr("no dentry found for hi%lu on b%d\n",
13668+ h_inode->i_ino, a->bdst);
13669+ err = -EIO;
13670+ }
13671+ }
13672+
13673+ if (!err && !plink)
13674+ au_plink_append(inode, a->bdst, a->h_path.dentry);
13675+
13676+out:
13677+ return err;
13678+}
13679+
13680+int aufs_link(struct dentry *src_dentry, struct inode *dir,
13681+ struct dentry *dentry)
13682+{
13683+ int err, rerr;
13684+ struct au_dtime dt;
13685+ struct au_link_args *a;
13686+ struct dentry *wh_dentry, *h_src_dentry;
13687+ struct inode *inode;
13688+ struct super_block *sb;
13689+ struct au_wr_dir_args wr_dir_args = {
13690+ /* .force_btgt = -1, */
13691+ .flags = AuWrDir_ADD_ENTRY
13692+ };
13693+
13694+ IMustLock(dir);
13695+ inode = src_dentry->d_inode;
13696+ IMustLock(inode);
13697+
13698+ err = -ENOENT;
13699+ if (unlikely(!inode->i_nlink))
13700+ goto out;
13701+
13702+ err = -ENOMEM;
13703+ a = kzalloc(sizeof(*a), GFP_NOFS);
13704+ if (unlikely(!a))
13705+ goto out;
13706+
13707+ a->parent = dentry->d_parent; /* dir inode is locked */
e49829fe
JR
13708+ err = aufs_read_and_write_lock2(dentry, src_dentry, AuLock_NOPLM);
13709+ if (unlikely(err))
13710+ goto out_kfree;
13711+
4a4d8108
AM
13712+ a->src_parent = dget_parent(src_dentry);
13713+ wr_dir_args.force_btgt = au_dbstart(src_dentry);
13714+
13715+ di_write_lock_parent(a->parent);
13716+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
13717+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
13718+ &wr_dir_args);
13719+ err = PTR_ERR(wh_dentry);
13720+ if (IS_ERR(wh_dentry))
13721+ goto out_unlock;
13722+
13723+ err = 0;
13724+ sb = dentry->d_sb;
13725+ a->bdst = au_dbstart(dentry);
13726+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
13727+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
13728+ a->bsrc = au_dbstart(src_dentry);
13729+ if (au_opt_test(au_mntflags(sb), PLINK)) {
13730+ if (a->bdst < a->bsrc
13731+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
13732+ err = au_cpup_or_link(src_dentry, a);
13733+ else {
13734+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13735+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13736+ &a->h_path);
13737+ }
13738+ } else {
13739+ /*
13740+ * copyup src_dentry to the branch we process,
13741+ * and then link(2) to it.
13742+ */
13743+ if (a->bdst < a->bsrc
13744+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
13745+ au_unpin(&a->pin);
13746+ di_write_unlock(a->parent);
13747+ err = au_cpup_before_link(src_dentry, a);
13748+ di_write_lock_parent(a->parent);
13749+ if (!err)
13750+ err = au_pin(&a->pin, dentry, a->bdst,
13751+ au_opt_udba(sb),
13752+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13753+ if (unlikely(err))
13754+ goto out_wh;
13755+ }
13756+ if (!err) {
13757+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13758+ err = -ENOENT;
13759+ if (h_src_dentry && h_src_dentry->d_inode)
13760+ err = vfsub_link(h_src_dentry,
13761+ au_pinned_h_dir(&a->pin),
13762+ &a->h_path);
13763+ }
13764+ }
13765+ if (unlikely(err))
13766+ goto out_unpin;
13767+
13768+ if (wh_dentry) {
13769+ a->h_path.dentry = wh_dentry;
13770+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
13771+ dentry);
13772+ if (unlikely(err))
13773+ goto out_revert;
13774+ }
13775+
13776+ dir->i_version++;
13777+ if (au_ibstart(dir) == au_dbstart(dentry))
13778+ au_cpup_attr_timesizes(dir);
13779+ inc_nlink(inode);
13780+ inode->i_ctime = dir->i_ctime;
13781+ if (!d_unhashed(a->h_path.dentry))
13782+ d_instantiate(dentry, au_igrab(inode));
13783+ else
13784+ /* some filesystem calls d_drop() */
13785+ d_drop(dentry);
13786+ goto out_unpin; /* success */
13787+
4f0767ce 13788+out_revert:
4a4d8108
AM
13789+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
13790+ if (!rerr)
13791+ goto out_dt;
13792+ AuIOErr("%.*s reverting failed(%d, %d)\n",
13793+ AuDLNPair(dentry), err, rerr);
13794+ err = -EIO;
4f0767ce 13795+out_dt:
4a4d8108
AM
13796+ d_drop(dentry);
13797+ au_dtime_revert(&dt);
4f0767ce 13798+out_unpin:
4a4d8108 13799+ au_unpin(&a->pin);
4f0767ce 13800+out_wh:
4a4d8108 13801+ dput(wh_dentry);
4f0767ce 13802+out_unlock:
4a4d8108
AM
13803+ if (unlikely(err)) {
13804+ au_update_dbstart(dentry);
13805+ d_drop(dentry);
13806+ }
13807+ di_write_unlock(a->parent);
13808+ dput(a->src_parent);
13809+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 13810+out_kfree:
4a4d8108 13811+ kfree(a);
4f0767ce 13812+out:
4a4d8108
AM
13813+ return err;
13814+}
13815+
13816+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
13817+{
13818+ int err, rerr;
13819+ aufs_bindex_t bindex;
13820+ unsigned char diropq;
13821+ struct path h_path;
13822+ struct dentry *wh_dentry, *parent, *opq_dentry;
13823+ struct mutex *h_mtx;
13824+ struct super_block *sb;
13825+ struct {
13826+ struct au_pin pin;
13827+ struct au_dtime dt;
13828+ } *a; /* reduce the stack usage */
13829+ struct au_wr_dir_args wr_dir_args = {
13830+ .force_btgt = -1,
13831+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
13832+ };
13833+
13834+ IMustLock(dir);
13835+
13836+ err = -ENOMEM;
13837+ a = kmalloc(sizeof(*a), GFP_NOFS);
13838+ if (unlikely(!a))
13839+ goto out;
13840+
13841+ aufs_read_lock(dentry, AuLock_DW);
13842+ parent = dentry->d_parent; /* dir inode is locked */
13843+ di_write_lock_parent(parent);
13844+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
13845+ &a->pin, &wr_dir_args);
13846+ err = PTR_ERR(wh_dentry);
13847+ if (IS_ERR(wh_dentry))
13848+ goto out_free;
13849+
13850+ sb = dentry->d_sb;
13851+ bindex = au_dbstart(dentry);
13852+ h_path.dentry = au_h_dptr(dentry, bindex);
13853+ h_path.mnt = au_sbr_mnt(sb, bindex);
13854+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
13855+ if (unlikely(err))
13856+ goto out_unlock;
13857+
13858+ /* make the dir opaque */
13859+ diropq = 0;
13860+ h_mtx = &h_path.dentry->d_inode->i_mutex;
13861+ if (wh_dentry
13862+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
13863+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13864+ opq_dentry = au_diropq_create(dentry, bindex);
13865+ mutex_unlock(h_mtx);
13866+ err = PTR_ERR(opq_dentry);
13867+ if (IS_ERR(opq_dentry))
13868+ goto out_dir;
13869+ dput(opq_dentry);
13870+ diropq = 1;
13871+ }
13872+
13873+ err = epilog(dir, bindex, wh_dentry, dentry);
13874+ if (!err) {
13875+ inc_nlink(dir);
13876+ goto out_unlock; /* success */
13877+ }
13878+
13879+ /* revert */
13880+ if (diropq) {
13881+ AuLabel(revert opq);
13882+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13883+ rerr = au_diropq_remove(dentry, bindex);
13884+ mutex_unlock(h_mtx);
13885+ if (rerr) {
13886+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
13887+ AuDLNPair(dentry), err, rerr);
13888+ err = -EIO;
13889+ }
13890+ }
13891+
4f0767ce 13892+out_dir:
4a4d8108
AM
13893+ AuLabel(revert dir);
13894+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
13895+ if (rerr) {
13896+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
13897+ AuDLNPair(dentry), err, rerr);
13898+ err = -EIO;
13899+ }
13900+ d_drop(dentry);
13901+ au_dtime_revert(&a->dt);
4f0767ce 13902+out_unlock:
4a4d8108
AM
13903+ au_unpin(&a->pin);
13904+ dput(wh_dentry);
4f0767ce 13905+out_free:
4a4d8108
AM
13906+ if (unlikely(err)) {
13907+ au_update_dbstart(dentry);
13908+ d_drop(dentry);
13909+ }
13910+ di_write_unlock(parent);
13911+ aufs_read_unlock(dentry, AuLock_DW);
13912+ kfree(a);
4f0767ce 13913+out:
4a4d8108
AM
13914+ return err;
13915+}
e49829fe
JR
13916--- /dev/null
13917+++ linux-2.6/fs/aufs/i_op.c 2010-10-24 13:50:56.000000000 +0200
13918@@ -0,0 +1,919 @@
4a4d8108
AM
13919+/*
13920+ * Copyright (C) 2005-2010 Junjiro R. Okajima
13921+ *
13922+ * This program, aufs is free software; you can redistribute it and/or modify
13923+ * it under the terms of the GNU General Public License as published by
13924+ * the Free Software Foundation; either version 2 of the License, or
13925+ * (at your option) any later version.
13926+ *
13927+ * This program is distributed in the hope that it will be useful,
13928+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13929+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13930+ * GNU General Public License for more details.
13931+ *
13932+ * You should have received a copy of the GNU General Public License
13933+ * along with this program; if not, write to the Free Software
13934+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13935+ */
1facf9fc 13936+
1308ab2a 13937+/*
4a4d8108 13938+ * inode operations (except add/del/rename)
1308ab2a 13939+ */
4a4d8108
AM
13940+
13941+#include <linux/device_cgroup.h>
13942+#include <linux/fs_stack.h>
13943+#include <linux/mm.h>
13944+#include <linux/namei.h>
13945+#include <linux/security.h>
13946+#include <linux/uaccess.h>
13947+#include "aufs.h"
13948+
13949+static int h_permission(struct inode *h_inode, int mask,
13950+ struct vfsmount *h_mnt, int brperm)
1facf9fc 13951+{
1308ab2a 13952+ int err;
4a4d8108 13953+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 13954+
4a4d8108
AM
13955+ err = -EACCES;
13956+ if ((write_mask && IS_IMMUTABLE(h_inode))
13957+ || ((mask & MAY_EXEC)
13958+ && S_ISREG(h_inode->i_mode)
13959+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
13960+ || !(h_inode->i_mode & S_IXUGO))))
13961+ goto out;
13962+
13963+ /*
13964+ * - skip the lower fs test in the case of write to ro branch.
13965+ * - nfs dir permission write check is optimized, but a policy for
13966+ * link/rename requires a real check.
13967+ */
13968+ if ((write_mask && !au_br_writable(brperm))
13969+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
13970+ && write_mask && !(mask & MAY_READ))
13971+ || !h_inode->i_op->permission) {
13972+ /* AuLabel(generic_permission); */
13973+ err = generic_permission(h_inode, mask,
13974+ h_inode->i_op->check_acl);
1308ab2a 13975+ } else {
4a4d8108
AM
13976+ /* AuLabel(h_inode->permission); */
13977+ err = h_inode->i_op->permission(h_inode, mask);
13978+ AuTraceErr(err);
13979+ }
1facf9fc 13980+
4a4d8108
AM
13981+ if (!err)
13982+ err = devcgroup_inode_permission(h_inode, mask);
e49829fe
JR
13983+ if (!err) {
13984+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND);
4a4d8108 13985+ err = security_inode_permission(h_inode, mask);
e49829fe 13986+ }
4a4d8108
AM
13987+
13988+#if 0
13989+ if (!err) {
13990+ /* todo: do we need to call ima_path_check()? */
13991+ struct path h_path = {
13992+ .dentry =
13993+ .mnt = h_mnt
13994+ };
13995+ err = ima_path_check(&h_path,
13996+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
13997+ IMA_COUNT_LEAVE);
1308ab2a 13998+ }
4a4d8108 13999+#endif
dece6358 14000+
4f0767ce 14001+out:
1308ab2a 14002+ return err;
14003+}
dece6358 14004+
4a4d8108 14005+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 14006+{
14007+ int err;
4a4d8108
AM
14008+ aufs_bindex_t bindex, bend;
14009+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
14010+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
14011+ struct inode *h_inode;
14012+ struct super_block *sb;
14013+ struct au_branch *br;
1facf9fc 14014+
4a4d8108
AM
14015+ sb = inode->i_sb;
14016+ si_read_lock(sb, AuLock_FLUSH);
14017+ ii_read_lock_child(inode);
dece6358 14018+
4a4d8108
AM
14019+ if (!isdir || write_mask) {
14020+ err = au_busy_or_stale();
14021+ h_inode = au_h_iptr(inode, au_ibstart(inode));
14022+ if (unlikely(!h_inode
14023+ || (h_inode->i_mode & S_IFMT)
14024+ != (inode->i_mode & S_IFMT)))
14025+ goto out;
1facf9fc 14026+
4a4d8108
AM
14027+ err = 0;
14028+ bindex = au_ibstart(inode);
14029+ br = au_sbr(sb, bindex);
14030+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
14031+ if (write_mask
14032+ && !err
14033+ && !special_file(h_inode->i_mode)) {
14034+ /* test whether the upper writable branch exists */
14035+ err = -EROFS;
14036+ for (; bindex >= 0; bindex--)
14037+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
14038+ err = 0;
14039+ break;
14040+ }
14041+ }
14042+ goto out;
14043+ }
dece6358 14044+
4a4d8108 14045+ /* non-write to dir */
1308ab2a 14046+ err = 0;
4a4d8108
AM
14047+ bend = au_ibend(inode);
14048+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
14049+ h_inode = au_h_iptr(inode, bindex);
14050+ if (h_inode) {
14051+ err = au_busy_or_stale();
14052+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
14053+ break;
14054+
14055+ br = au_sbr(sb, bindex);
14056+ err = h_permission(h_inode, mask, br->br_mnt,
14057+ br->br_perm);
14058+ }
14059+ }
1308ab2a 14060+
4f0767ce 14061+out:
4a4d8108
AM
14062+ ii_read_unlock(inode);
14063+ si_read_unlock(sb);
1308ab2a 14064+ return err;
14065+}
14066+
4a4d8108 14067+/* ---------------------------------------------------------------------- */
1facf9fc 14068+
4a4d8108
AM
14069+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
14070+ struct nameidata *nd)
14071+{
14072+ struct dentry *ret, *parent;
b752ccd1 14073+ struct inode *inode;
4a4d8108
AM
14074+ struct super_block *sb;
14075+ int err, npositive;
dece6358 14076+
4a4d8108 14077+ IMustLock(dir);
1308ab2a 14078+
4a4d8108
AM
14079+ sb = dir->i_sb;
14080+ si_read_lock(sb, AuLock_FLUSH);
14081+ ret = ERR_PTR(-ENAMETOOLONG);
14082+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
14083+ goto out;
14084+ err = au_di_init(dentry);
14085+ ret = ERR_PTR(err);
14086+ if (unlikely(err))
14087+ goto out;
1308ab2a 14088+
4a4d8108
AM
14089+ parent = dentry->d_parent; /* dir inode is locked */
14090+ di_read_lock_parent(parent, AuLock_IR);
14091+ npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
14092+ di_read_unlock(parent, AuLock_IR);
14093+ err = npositive;
14094+ ret = ERR_PTR(err);
14095+ if (unlikely(err < 0))
14096+ goto out_unlock;
1308ab2a 14097+
4a4d8108
AM
14098+ inode = NULL;
14099+ if (npositive) {
b752ccd1 14100+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 14101+ ret = (void *)inode;
1facf9fc 14102+ }
4a4d8108
AM
14103+ if (IS_ERR(inode))
14104+ goto out_unlock;
14105+
14106+ ret = d_splice_alias(inode, dentry);
14107+ if (unlikely(IS_ERR(ret) && inode))
14108+ ii_write_unlock(inode);
1facf9fc 14109+
4f0767ce 14110+out_unlock:
4a4d8108 14111+ di_write_unlock(dentry);
4f0767ce 14112+out:
4a4d8108
AM
14113+ si_read_unlock(sb);
14114+ return ret;
14115+}
1facf9fc 14116+
4a4d8108 14117+/* ---------------------------------------------------------------------- */
1facf9fc 14118+
4a4d8108
AM
14119+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
14120+ const unsigned char add_entry, aufs_bindex_t bcpup,
14121+ aufs_bindex_t bstart)
14122+{
14123+ int err;
14124+ struct dentry *h_parent;
14125+ struct inode *h_dir;
1facf9fc 14126+
4a4d8108
AM
14127+ if (add_entry) {
14128+ au_update_dbstart(dentry);
14129+ IMustLock(parent->d_inode);
14130+ } else
14131+ di_write_lock_parent(parent);
14132+
14133+ err = 0;
14134+ if (!au_h_dptr(parent, bcpup)) {
14135+ if (bstart < bcpup)
14136+ err = au_cpdown_dirs(dentry, bcpup);
14137+ else
14138+ err = au_cpup_dirs(dentry, bcpup);
14139+ }
14140+ if (!err && add_entry) {
14141+ h_parent = au_h_dptr(parent, bcpup);
14142+ h_dir = h_parent->d_inode;
14143+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
14144+ err = au_lkup_neg(dentry, bcpup);
14145+ /* todo: no unlock here */
14146+ mutex_unlock(&h_dir->i_mutex);
14147+ if (bstart < bcpup && au_dbstart(dentry) < 0) {
14148+ au_set_dbstart(dentry, 0);
14149+ au_update_dbrange(dentry, /*do_put_zero*/0);
14150+ }
1308ab2a 14151+ }
1facf9fc 14152+
4a4d8108
AM
14153+ if (!add_entry)
14154+ di_write_unlock(parent);
14155+ if (!err)
14156+ err = bcpup; /* success */
1308ab2a 14157+
4a4d8108
AM
14158+ return err;
14159+}
1facf9fc 14160+
4a4d8108
AM
14161+/*
14162+ * decide the branch and the parent dir where we will create a new entry.
14163+ * returns new bindex or an error.
14164+ * copyup the parent dir if needed.
14165+ */
14166+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14167+ struct au_wr_dir_args *args)
14168+{
14169+ int err;
14170+ aufs_bindex_t bcpup, bstart, src_bstart;
14171+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
14172+ ADD_ENTRY);
14173+ struct super_block *sb;
14174+ struct dentry *parent;
14175+ struct au_sbinfo *sbinfo;
1facf9fc 14176+
4a4d8108
AM
14177+ sb = dentry->d_sb;
14178+ sbinfo = au_sbi(sb);
14179+ parent = dget_parent(dentry);
14180+ bstart = au_dbstart(dentry);
14181+ bcpup = bstart;
14182+ if (args->force_btgt < 0) {
14183+ if (src_dentry) {
14184+ src_bstart = au_dbstart(src_dentry);
14185+ if (src_bstart < bstart)
14186+ bcpup = src_bstart;
14187+ } else if (add_entry) {
14188+ err = AuWbrCreate(sbinfo, dentry,
14189+ au_ftest_wrdir(args->flags, ISDIR));
14190+ bcpup = err;
14191+ }
1facf9fc 14192+
4a4d8108
AM
14193+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
14194+ if (add_entry)
14195+ err = AuWbrCopyup(sbinfo, dentry);
14196+ else {
14197+ if (!IS_ROOT(dentry)) {
14198+ di_read_lock_parent(parent, !AuLock_IR);
14199+ err = AuWbrCopyup(sbinfo, dentry);
14200+ di_read_unlock(parent, !AuLock_IR);
14201+ } else
14202+ err = AuWbrCopyup(sbinfo, dentry);
14203+ }
14204+ bcpup = err;
14205+ if (unlikely(err < 0))
14206+ goto out;
14207+ }
14208+ } else {
14209+ bcpup = args->force_btgt;
14210+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 14211+ }
4a4d8108
AM
14212+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
14213+ err = bcpup;
14214+ if (bcpup == bstart)
14215+ goto out; /* success */
14216+ else if (bstart < bcpup)
14217+ au_update_dbrange(dentry, /*do_put_zero*/1);
14218+
14219+ /* copyup the new parent into the branch we process */
14220+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
14221+
4f0767ce 14222+out:
4a4d8108 14223+ dput(parent);
dece6358
AM
14224+ return err;
14225+}
1facf9fc 14226+
1308ab2a 14227+/* ---------------------------------------------------------------------- */
14228+
4a4d8108 14229+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 14230+{
4a4d8108
AM
14231+ if (pin && pin->parent)
14232+ return au_h_dptr(pin->parent, pin->bindex);
14233+ return NULL;
dece6358 14234+}
1facf9fc 14235+
4a4d8108 14236+void au_unpin(struct au_pin *p)
dece6358 14237+{
e49829fe 14238+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
4a4d8108
AM
14239+ mnt_drop_write(p->h_mnt);
14240+ if (!p->hdir)
14241+ return;
1facf9fc 14242+
4a4d8108
AM
14243+ au_hn_imtx_unlock(p->hdir);
14244+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14245+ di_read_unlock(p->parent, AuLock_IR);
14246+ iput(p->hdir->hi_inode);
14247+ dput(p->parent);
14248+ p->parent = NULL;
14249+ p->hdir = NULL;
14250+ p->h_mnt = NULL;
14251+}
1308ab2a 14252+
4a4d8108
AM
14253+int au_do_pin(struct au_pin *p)
14254+{
14255+ int err;
14256+ struct super_block *sb;
14257+ struct dentry *h_dentry, *h_parent;
14258+ struct au_branch *br;
14259+ struct inode *h_dir;
14260+
14261+ err = 0;
14262+ sb = p->dentry->d_sb;
14263+ br = au_sbr(sb, p->bindex);
14264+ if (IS_ROOT(p->dentry)) {
14265+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14266+ p->h_mnt = br->br_mnt;
14267+ err = mnt_want_write(p->h_mnt);
14268+ if (unlikely(err)) {
14269+ au_fclr_pin(p->flags, MNT_WRITE);
14270+ goto out_err;
14271+ }
14272+ }
dece6358 14273+ goto out;
1facf9fc 14274+ }
14275+
4a4d8108
AM
14276+ h_dentry = NULL;
14277+ if (p->bindex <= au_dbend(p->dentry))
14278+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 14279+
4a4d8108
AM
14280+ p->parent = dget_parent(p->dentry);
14281+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14282+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 14283+
4a4d8108
AM
14284+ h_dir = NULL;
14285+ h_parent = au_h_dptr(p->parent, p->bindex);
14286+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
14287+ if (p->hdir)
14288+ h_dir = p->hdir->hi_inode;
dece6358 14289+
b752ccd1
AM
14290+ /*
14291+ * udba case, or
14292+ * if DI_LOCKED is not set, then p->parent may be different
14293+ * and h_parent can be NULL.
14294+ */
14295+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
e49829fe 14296+ err = -EBUSY;
4a4d8108
AM
14297+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14298+ di_read_unlock(p->parent, AuLock_IR);
14299+ dput(p->parent);
14300+ p->parent = NULL;
14301+ goto out_err;
14302+ }
1308ab2a 14303+
4a4d8108
AM
14304+ au_igrab(h_dir);
14305+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 14306+
4a4d8108
AM
14307+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
14308+ err = -EBUSY;
14309+ goto out_unpin;
14310+ }
14311+ if (h_dentry) {
14312+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
14313+ if (unlikely(err)) {
14314+ au_fclr_pin(p->flags, MNT_WRITE);
14315+ goto out_unpin;
14316+ }
1facf9fc 14317+ }
dece6358 14318+
4a4d8108
AM
14319+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14320+ p->h_mnt = br->br_mnt;
14321+ err = mnt_want_write(p->h_mnt);
dece6358 14322+ if (unlikely(err)) {
4a4d8108
AM
14323+ au_fclr_pin(p->flags, MNT_WRITE);
14324+ goto out_unpin;
dece6358
AM
14325+ }
14326+ }
4a4d8108
AM
14327+ goto out; /* success */
14328+
4f0767ce 14329+out_unpin:
4a4d8108 14330+ au_unpin(p);
4f0767ce 14331+out_err:
4a4d8108
AM
14332+ pr_err("err %d\n", err);
14333+ err = au_busy_or_stale();
4f0767ce 14334+out:
1facf9fc 14335+ return err;
14336+}
14337+
4a4d8108
AM
14338+void au_pin_init(struct au_pin *p, struct dentry *dentry,
14339+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14340+ unsigned int udba, unsigned char flags)
14341+{
14342+ p->dentry = dentry;
14343+ p->udba = udba;
14344+ p->lsc_di = lsc_di;
14345+ p->lsc_hi = lsc_hi;
14346+ p->flags = flags;
14347+ p->bindex = bindex;
14348+
14349+ p->parent = NULL;
14350+ p->hdir = NULL;
14351+ p->h_mnt = NULL;
14352+}
14353+
14354+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14355+ unsigned int udba, unsigned char flags)
14356+{
14357+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
14358+ udba, flags);
14359+ return au_do_pin(pin);
14360+}
14361+
dece6358
AM
14362+/* ---------------------------------------------------------------------- */
14363+
1308ab2a 14364+/*
4a4d8108
AM
14365+ * ->setattr() and ->getattr() are called in various cases.
14366+ * chmod, stat: dentry is revalidated.
14367+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
14368+ * unhashed.
14369+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 14370+ */
4a4d8108 14371+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 14372+{
4a4d8108
AM
14373+ int err;
14374+ struct inode *inode;
14375+ struct dentry *parent;
1facf9fc 14376+
1308ab2a 14377+ err = 0;
4a4d8108
AM
14378+ inode = dentry->d_inode;
14379+ if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
14380+ parent = dget_parent(dentry);
14381+ di_read_lock_parent(parent, AuLock_IR);
14382+ /* returns a number of positive dentries */
14383+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
14384+ if (err >= 0)
14385+ err = au_refresh_hinode(inode, dentry);
14386+ di_read_unlock(parent, AuLock_IR);
14387+ dput(parent);
dece6358 14388+ }
1facf9fc 14389+
4a4d8108 14390+ AuTraceErr(err);
1308ab2a 14391+ return err;
14392+}
dece6358 14393+
4a4d8108
AM
14394+#define AuIcpup_DID_CPUP 1
14395+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
14396+#define au_fset_icpup(flags, name) { (flags) |= AuIcpup_##name; }
14397+#define au_fclr_icpup(flags, name) { (flags) &= ~AuIcpup_##name; }
1308ab2a 14398+
4a4d8108
AM
14399+struct au_icpup_args {
14400+ unsigned char flags;
14401+ unsigned char pin_flags;
14402+ aufs_bindex_t btgt;
14403+ unsigned int udba;
14404+ struct au_pin pin;
14405+ struct path h_path;
14406+ struct inode *h_inode;
14407+};
1308ab2a 14408+
4a4d8108
AM
14409+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
14410+ struct au_icpup_args *a)
1308ab2a 14411+{
14412+ int err;
4a4d8108 14413+ loff_t sz;
e49829fe 14414+ aufs_bindex_t bstart, ibstart;
4a4d8108
AM
14415+ struct dentry *hi_wh, *parent;
14416+ struct inode *inode;
14417+ struct file *h_file;
14418+ struct au_wr_dir_args wr_dir_args = {
14419+ .force_btgt = -1,
14420+ .flags = 0
14421+ };
14422+
14423+ bstart = au_dbstart(dentry);
14424+ inode = dentry->d_inode;
14425+ if (S_ISDIR(inode->i_mode))
14426+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
14427+ /* plink or hi_wh() case */
e49829fe
JR
14428+ ibstart = au_ibstart(inode);
14429+ if (bstart != ibstart)
14430+ wr_dir_args.force_btgt = ibstart;
4a4d8108
AM
14431+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
14432+ if (unlikely(err < 0))
14433+ goto out;
14434+ a->btgt = err;
14435+ if (err != bstart)
14436+ au_fset_icpup(a->flags, DID_CPUP);
14437+
14438+ err = 0;
14439+ a->pin_flags = AuPin_MNT_WRITE;
14440+ parent = NULL;
14441+ if (!IS_ROOT(dentry)) {
14442+ au_fset_pin(a->pin_flags, DI_LOCKED);
14443+ parent = dget_parent(dentry);
14444+ di_write_lock_parent(parent);
14445+ }
14446+
14447+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
14448+ if (unlikely(err))
14449+ goto out_parent;
14450+
14451+ a->h_path.dentry = au_h_dptr(dentry, bstart);
14452+ a->h_inode = a->h_path.dentry->d_inode;
14453+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14454+ sz = -1;
14455+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
14456+ sz = ia->ia_size;
14457+
14458+ h_file = NULL;
14459+ hi_wh = NULL;
14460+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
14461+ hi_wh = au_hi_wh(inode, a->btgt);
14462+ if (!hi_wh) {
14463+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
14464+ if (unlikely(err))
14465+ goto out_unlock;
14466+ hi_wh = au_hi_wh(inode, a->btgt);
14467+ /* todo: revalidate hi_wh? */
14468+ }
14469+ }
14470+
14471+ if (parent) {
14472+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14473+ di_downgrade_lock(parent, AuLock_IR);
14474+ dput(parent);
14475+ parent = NULL;
14476+ }
14477+ if (!au_ftest_icpup(a->flags, DID_CPUP))
14478+ goto out; /* success */
14479+
14480+ if (!d_unhashed(dentry)) {
14481+ h_file = au_h_open_pre(dentry, bstart);
14482+ if (IS_ERR(h_file)) {
14483+ err = PTR_ERR(h_file);
14484+ h_file = NULL;
14485+ } else
14486+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
14487+ AuCpup_DTIME);
14488+ if (!err)
14489+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14490+ } else if (!hi_wh)
14491+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14492+ else
14493+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 14494+
4f0767ce 14495+out_unlock:
4a4d8108
AM
14496+ mutex_unlock(&a->h_inode->i_mutex);
14497+ au_h_open_post(dentry, bstart, h_file);
14498+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 14499+ if (!err) {
4a4d8108 14500+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 14501+ goto out; /* success */
1facf9fc 14502+ }
dece6358 14503+
4a4d8108 14504+ au_unpin(&a->pin);
4f0767ce 14505+out_parent:
4a4d8108
AM
14506+ if (parent) {
14507+ di_write_unlock(parent);
14508+ dput(parent);
14509+ }
4f0767ce 14510+out:
1facf9fc 14511+ return err;
14512+}
14513+
4a4d8108 14514+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 14515+{
4a4d8108
AM
14516+ int err;
14517+ struct inode *inode;
14518+ struct super_block *sb;
14519+ struct file *file;
14520+ struct au_icpup_args *a;
1facf9fc 14521+
4a4d8108
AM
14522+ inode = dentry->d_inode;
14523+ IMustLock(inode);
dece6358 14524+
4a4d8108
AM
14525+ err = -ENOMEM;
14526+ a = kzalloc(sizeof(*a), GFP_NOFS);
14527+ if (unlikely(!a))
14528+ goto out;
1facf9fc 14529+
4a4d8108
AM
14530+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
14531+ ia->ia_valid &= ~ATTR_MODE;
dece6358 14532+
4a4d8108
AM
14533+ file = NULL;
14534+ sb = dentry->d_sb;
e49829fe
JR
14535+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
14536+ if (unlikely(err))
14537+ goto out_kfree;
14538+
4a4d8108
AM
14539+ if (ia->ia_valid & ATTR_FILE) {
14540+ /* currently ftruncate(2) only */
14541+ AuDebugOn(!S_ISREG(inode->i_mode));
14542+ file = ia->ia_file;
14543+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
14544+ if (unlikely(err))
14545+ goto out_si;
14546+ ia->ia_file = au_hf_top(file);
14547+ a->udba = AuOpt_UDBA_NONE;
14548+ } else {
14549+ /* fchmod() doesn't pass ia_file */
14550+ a->udba = au_opt_udba(sb);
14551+ if (d_unhashed(dentry))
14552+ a->udba = AuOpt_UDBA_NONE;
14553+ di_write_lock_child(dentry);
14554+ if (a->udba != AuOpt_UDBA_NONE) {
14555+ AuDebugOn(IS_ROOT(dentry));
14556+ err = au_reval_for_attr(dentry, au_sigen(sb));
14557+ if (unlikely(err))
14558+ goto out_dentry;
14559+ }
dece6358 14560+ }
dece6358 14561+
4a4d8108
AM
14562+ err = au_pin_and_icpup(dentry, ia, a);
14563+ if (unlikely(err < 0))
14564+ goto out_dentry;
14565+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
14566+ ia->ia_file = NULL;
14567+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 14568+ }
dece6358 14569+
4a4d8108
AM
14570+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
14571+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
14572+ == (ATTR_MODE | ATTR_CTIME)) {
14573+ err = security_path_chmod(a->h_path.dentry, a->h_path.mnt,
14574+ ia->ia_mode);
14575+ if (unlikely(err))
14576+ goto out_unlock;
14577+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
14578+ && (ia->ia_valid & ATTR_CTIME)) {
14579+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
14580+ if (unlikely(err))
14581+ goto out_unlock;
14582+ }
dece6358 14583+
4a4d8108
AM
14584+ if (ia->ia_valid & ATTR_SIZE) {
14585+ struct file *f;
1308ab2a 14586+
953406b4 14587+ if (ia->ia_size < i_size_read(inode))
4a4d8108 14588+ /* unmap only */
953406b4 14589+ truncate_setsize(inode, ia->ia_size);
1308ab2a 14590+
4a4d8108
AM
14591+ f = NULL;
14592+ if (ia->ia_valid & ATTR_FILE)
14593+ f = ia->ia_file;
14594+ mutex_unlock(&a->h_inode->i_mutex);
14595+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
14596+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14597+ } else
14598+ err = vfsub_notify_change(&a->h_path, ia);
14599+ if (!err)
14600+ au_cpup_attr_changeable(inode);
1308ab2a 14601+
4f0767ce 14602+out_unlock:
4a4d8108
AM
14603+ mutex_unlock(&a->h_inode->i_mutex);
14604+ au_unpin(&a->pin);
4f0767ce 14605+out_dentry:
4a4d8108
AM
14606+ di_write_unlock(dentry);
14607+ if (file) {
14608+ fi_write_unlock(file);
14609+ ia->ia_file = file;
14610+ ia->ia_valid |= ATTR_FILE;
14611+ }
4f0767ce 14612+out_si:
4a4d8108 14613+ si_read_unlock(sb);
e49829fe 14614+out_kfree:
4a4d8108 14615+ kfree(a);
4f0767ce 14616+out:
4a4d8108
AM
14617+ AuTraceErr(err);
14618+ return err;
1facf9fc 14619+}
14620+
4a4d8108
AM
14621+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
14622+ unsigned int nlink)
1facf9fc 14623+{
4a4d8108
AM
14624+ inode->i_mode = st->mode;
14625+ inode->i_uid = st->uid;
14626+ inode->i_gid = st->gid;
14627+ inode->i_atime = st->atime;
14628+ inode->i_mtime = st->mtime;
14629+ inode->i_ctime = st->ctime;
1facf9fc 14630+
4a4d8108
AM
14631+ au_cpup_attr_nlink(inode, /*force*/0);
14632+ if (S_ISDIR(inode->i_mode)) {
14633+ inode->i_nlink -= nlink;
14634+ inode->i_nlink += st->nlink;
14635+ }
1facf9fc 14636+
4a4d8108
AM
14637+ spin_lock(&inode->i_lock);
14638+ inode->i_blocks = st->blocks;
14639+ i_size_write(inode, st->size);
14640+ spin_unlock(&inode->i_lock);
1facf9fc 14641+}
14642+
4a4d8108
AM
14643+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
14644+ struct dentry *dentry, struct kstat *st)
1facf9fc 14645+{
4a4d8108
AM
14646+ int err;
14647+ unsigned int mnt_flags;
14648+ aufs_bindex_t bindex;
14649+ unsigned char udba_none, positive;
14650+ struct super_block *sb, *h_sb;
14651+ struct inode *inode;
14652+ struct vfsmount *h_mnt;
14653+ struct dentry *h_dentry;
1facf9fc 14654+
4a4d8108
AM
14655+ err = 0;
14656+ sb = dentry->d_sb;
14657+ inode = dentry->d_inode;
e49829fe 14658+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
14659+ mnt_flags = au_mntflags(sb);
14660+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 14661+
4a4d8108
AM
14662+ /* support fstat(2) */
14663+ if (!d_unhashed(dentry) && !udba_none) {
14664+ unsigned int sigen = au_sigen(sb);
14665+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
14666+ di_read_lock_child(dentry, AuLock_IR);
14667+ else {
14668+ AuDebugOn(IS_ROOT(dentry));
14669+ di_write_lock_child(dentry);
14670+ err = au_reval_for_attr(dentry, sigen);
14671+ di_downgrade_lock(dentry, AuLock_IR);
14672+ if (unlikely(err))
14673+ goto out;
14674+ }
14675+ } else
14676+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 14677+
4a4d8108
AM
14678+ bindex = au_ibstart(inode);
14679+ h_mnt = au_sbr_mnt(sb, bindex);
14680+ h_sb = h_mnt->mnt_sb;
14681+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
14682+ goto out_fill; /* success */
1facf9fc 14683+
4a4d8108
AM
14684+ h_dentry = NULL;
14685+ if (au_dbstart(dentry) == bindex)
14686+ h_dentry = dget(au_h_dptr(dentry, bindex));
14687+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
14688+ h_dentry = au_plink_lkup(inode, bindex);
14689+ if (IS_ERR(h_dentry))
14690+ goto out_fill; /* pretending success */
14691+ }
14692+ /* illegally overlapped or something */
14693+ if (unlikely(!h_dentry))
14694+ goto out_fill; /* pretending success */
14695+
14696+ positive = !!h_dentry->d_inode;
14697+ if (positive)
14698+ err = vfs_getattr(h_mnt, h_dentry, st);
14699+ dput(h_dentry);
14700+ if (!err) {
14701+ if (positive)
14702+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
14703+ goto out_fill; /* success */
1facf9fc 14704+ }
4a4d8108
AM
14705+ goto out;
14706+
4f0767ce 14707+out_fill:
4a4d8108 14708+ generic_fillattr(inode, st);
4f0767ce 14709+out:
4a4d8108
AM
14710+ di_read_unlock(dentry, AuLock_IR);
14711+ si_read_unlock(sb);
14712+ return err;
1facf9fc 14713+}
14714+
14715+/* ---------------------------------------------------------------------- */
14716+
4a4d8108
AM
14717+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
14718+ int bufsiz)
1facf9fc 14719+{
14720+ int err;
4a4d8108
AM
14721+ struct super_block *sb;
14722+ struct dentry *h_dentry;
1facf9fc 14723+
4a4d8108
AM
14724+ err = -EINVAL;
14725+ h_dentry = au_h_dptr(dentry, bindex);
14726+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
14727+ goto out;
1facf9fc 14728+
4a4d8108
AM
14729+ err = security_inode_readlink(h_dentry);
14730+ if (unlikely(err))
dece6358 14731+ goto out;
1facf9fc 14732+
4a4d8108
AM
14733+ sb = dentry->d_sb;
14734+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
14735+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
14736+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 14737+ }
4a4d8108 14738+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 14739+
4f0767ce 14740+out:
4a4d8108
AM
14741+ return err;
14742+}
1facf9fc 14743+
4a4d8108
AM
14744+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
14745+{
14746+ int err;
1facf9fc 14747+
4a4d8108
AM
14748+ aufs_read_lock(dentry, AuLock_IR);
14749+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
14750+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14751+
4a4d8108
AM
14752+ return err;
14753+}
1facf9fc 14754+
4a4d8108
AM
14755+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
14756+{
14757+ int err;
4a4d8108 14758+ mm_segment_t old_fs;
b752ccd1
AM
14759+ union {
14760+ char *k;
14761+ char __user *u;
14762+ } buf;
1facf9fc 14763+
4a4d8108 14764+ err = -ENOMEM;
b752ccd1
AM
14765+ buf.k = __getname_gfp(GFP_NOFS);
14766+ if (unlikely(!buf.k))
4a4d8108 14767+ goto out;
1facf9fc 14768+
4a4d8108
AM
14769+ aufs_read_lock(dentry, AuLock_IR);
14770+ old_fs = get_fs();
14771+ set_fs(KERNEL_DS);
b752ccd1 14772+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
4a4d8108
AM
14773+ set_fs(old_fs);
14774+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14775+
4a4d8108 14776+ if (err >= 0) {
b752ccd1 14777+ buf.k[err] = 0;
4a4d8108 14778+ /* will be freed by put_link */
b752ccd1 14779+ nd_set_link(nd, buf.k);
4a4d8108 14780+ return NULL; /* success */
1308ab2a 14781+ }
b752ccd1 14782+ __putname(buf.k);
1facf9fc 14783+
4f0767ce 14784+out:
4a4d8108
AM
14785+ path_put(&nd->path);
14786+ AuTraceErr(err);
14787+ return ERR_PTR(err);
14788+}
1facf9fc 14789+
4a4d8108
AM
14790+static void aufs_put_link(struct dentry *dentry __maybe_unused,
14791+ struct nameidata *nd, void *cookie __maybe_unused)
14792+{
14793+ __putname(nd_get_link(nd));
14794+}
1facf9fc 14795+
4a4d8108 14796+/* ---------------------------------------------------------------------- */
1facf9fc 14797+
4a4d8108
AM
14798+static void aufs_truncate_range(struct inode *inode __maybe_unused,
14799+ loff_t start __maybe_unused,
14800+ loff_t end __maybe_unused)
14801+{
14802+ AuUnsupport();
14803+}
1facf9fc 14804+
4a4d8108 14805+/* ---------------------------------------------------------------------- */
1308ab2a 14806+
4a4d8108
AM
14807+struct inode_operations aufs_symlink_iop = {
14808+ .permission = aufs_permission,
14809+ .setattr = aufs_setattr,
14810+ .getattr = aufs_getattr,
14811+ .readlink = aufs_readlink,
14812+ .follow_link = aufs_follow_link,
14813+ .put_link = aufs_put_link
14814+};
14815+
14816+struct inode_operations aufs_dir_iop = {
14817+ .create = aufs_create,
14818+ .lookup = aufs_lookup,
14819+ .link = aufs_link,
14820+ .unlink = aufs_unlink,
14821+ .symlink = aufs_symlink,
14822+ .mkdir = aufs_mkdir,
14823+ .rmdir = aufs_rmdir,
14824+ .mknod = aufs_mknod,
14825+ .rename = aufs_rename,
14826+
14827+ .permission = aufs_permission,
14828+ .setattr = aufs_setattr,
14829+ .getattr = aufs_getattr
14830+};
14831+
14832+struct inode_operations aufs_iop = {
14833+ .permission = aufs_permission,
14834+ .setattr = aufs_setattr,
14835+ .getattr = aufs_getattr,
14836+ .truncate_range = aufs_truncate_range
14837+};
e49829fe
JR
14838--- /dev/null
14839+++ linux-2.6/fs/aufs/i_op_del.c 2010-10-24 11:19:23.000000000 +0200
4a4d8108 14840@@ -0,0 +1,472 @@
1facf9fc 14841+/*
4a4d8108 14842+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 14843+ *
14844+ * This program, aufs is free software; you can redistribute it and/or modify
14845+ * it under the terms of the GNU General Public License as published by
14846+ * the Free Software Foundation; either version 2 of the License, or
14847+ * (at your option) any later version.
dece6358
AM
14848+ *
14849+ * This program is distributed in the hope that it will be useful,
14850+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14851+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14852+ * GNU General Public License for more details.
14853+ *
14854+ * You should have received a copy of the GNU General Public License
14855+ * along with this program; if not, write to the Free Software
14856+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14857+ */
14858+
14859+/*
4a4d8108 14860+ * inode operations (del entry)
1308ab2a 14861+ */
dece6358 14862+
1308ab2a 14863+#include "aufs.h"
dece6358 14864+
4a4d8108
AM
14865+/*
14866+ * decide if a new whiteout for @dentry is necessary or not.
14867+ * when it is necessary, prepare the parent dir for the upper branch whose
14868+ * branch index is @bcpup for creation. the actual creation of the whiteout will
14869+ * be done by caller.
14870+ * return value:
14871+ * 0: wh is unnecessary
14872+ * plus: wh is necessary
14873+ * minus: error
14874+ */
14875+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 14876+{
4a4d8108
AM
14877+ int need_wh, err;
14878+ aufs_bindex_t bstart;
14879+ struct super_block *sb;
dece6358 14880+
4a4d8108
AM
14881+ sb = dentry->d_sb;
14882+ bstart = au_dbstart(dentry);
14883+ if (*bcpup < 0) {
14884+ *bcpup = bstart;
14885+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
14886+ err = AuWbrCopyup(au_sbi(sb), dentry);
14887+ *bcpup = err;
14888+ if (unlikely(err < 0))
14889+ goto out;
14890+ }
14891+ } else
14892+ AuDebugOn(bstart < *bcpup
14893+ || au_test_ro(sb, *bcpup, dentry->d_inode));
14894+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 14895+
4a4d8108
AM
14896+ if (*bcpup != bstart) {
14897+ err = au_cpup_dirs(dentry, *bcpup);
14898+ if (unlikely(err))
14899+ goto out;
14900+ need_wh = 1;
14901+ } else {
14902+ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
14903+
14904+ old_bend = au_dbend(dentry);
14905+ if (isdir) {
14906+ bdiropq = au_dbdiropq(dentry);
14907+ au_set_dbdiropq(dentry, -1);
14908+ }
14909+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
14910+ /*nd*/NULL);
14911+ err = need_wh;
14912+ if (isdir)
14913+ au_set_dbdiropq(dentry, bdiropq);
14914+ if (unlikely(err < 0))
14915+ goto out;
14916+ new_bend = au_dbend(dentry);
14917+ if (!need_wh && old_bend != new_bend) {
14918+ au_set_h_dptr(dentry, new_bend, NULL);
14919+ au_set_dbend(dentry, old_bend);
14920+ }
14921+ }
14922+ AuDbg("need_wh %d\n", need_wh);
14923+ err = need_wh;
14924+
4f0767ce 14925+out:
4a4d8108 14926+ return err;
1facf9fc 14927+}
14928+
4a4d8108
AM
14929+/*
14930+ * simple tests for the del-entry operations.
14931+ * following the checks in vfs, plus the parent-child relationship.
14932+ */
14933+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14934+ struct dentry *h_parent, int isdir)
1facf9fc 14935+{
4a4d8108
AM
14936+ int err;
14937+ umode_t h_mode;
14938+ struct dentry *h_dentry, *h_latest;
1308ab2a 14939+ struct inode *h_inode;
1facf9fc 14940+
4a4d8108
AM
14941+ h_dentry = au_h_dptr(dentry, bindex);
14942+ h_inode = h_dentry->d_inode;
14943+ if (dentry->d_inode) {
14944+ err = -ENOENT;
14945+ if (unlikely(!h_inode || !h_inode->i_nlink))
14946+ goto out;
1facf9fc 14947+
4a4d8108
AM
14948+ h_mode = h_inode->i_mode;
14949+ if (!isdir) {
14950+ err = -EISDIR;
14951+ if (unlikely(S_ISDIR(h_mode)))
14952+ goto out;
14953+ } else if (unlikely(!S_ISDIR(h_mode))) {
14954+ err = -ENOTDIR;
14955+ goto out;
14956+ }
14957+ } else {
14958+ /* rename(2) case */
14959+ err = -EIO;
14960+ if (unlikely(h_inode))
14961+ goto out;
14962+ }
1facf9fc 14963+
4a4d8108
AM
14964+ err = -ENOENT;
14965+ /* expected parent dir is locked */
14966+ if (unlikely(h_parent != h_dentry->d_parent))
14967+ goto out;
14968+ err = 0;
14969+
14970+ /*
14971+ * rmdir a dir may break the consistency on some filesystem.
14972+ * let's try heavy test.
14973+ */
14974+ err = -EACCES;
14975+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
14976+ goto out;
14977+
14978+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
14979+ au_sbr(dentry->d_sb, bindex));
14980+ err = -EIO;
14981+ if (IS_ERR(h_latest))
14982+ goto out;
14983+ if (h_latest == h_dentry)
14984+ err = 0;
14985+ dput(h_latest);
14986+
4f0767ce 14987+out:
4a4d8108 14988+ return err;
1308ab2a 14989+}
1facf9fc 14990+
4a4d8108
AM
14991+/*
14992+ * decide the branch where we operate for @dentry. the branch index will be set
14993+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
14994+ * dir for reverting.
14995+ * when a new whiteout is necessary, create it.
14996+ */
14997+static struct dentry*
14998+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
14999+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 15000+{
4a4d8108
AM
15001+ struct dentry *wh_dentry;
15002+ struct super_block *sb;
15003+ struct path h_path;
15004+ int err, need_wh;
15005+ unsigned int udba;
15006+ aufs_bindex_t bcpup;
dece6358 15007+
4a4d8108
AM
15008+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
15009+ wh_dentry = ERR_PTR(need_wh);
15010+ if (unlikely(need_wh < 0))
15011+ goto out;
15012+
15013+ sb = dentry->d_sb;
15014+ udba = au_opt_udba(sb);
15015+ bcpup = *rbcpup;
15016+ err = au_pin(pin, dentry, bcpup, udba,
15017+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15018+ wh_dentry = ERR_PTR(err);
15019+ if (unlikely(err))
15020+ goto out;
15021+
15022+ h_path.dentry = au_pinned_h_parent(pin);
15023+ if (udba != AuOpt_UDBA_NONE
15024+ && au_dbstart(dentry) == bcpup) {
15025+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
15026+ wh_dentry = ERR_PTR(err);
15027+ if (unlikely(err))
15028+ goto out_unpin;
15029+ }
15030+
15031+ h_path.mnt = au_sbr_mnt(sb, bcpup);
15032+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
15033+ wh_dentry = NULL;
15034+ if (!need_wh)
15035+ goto out; /* success, no need to create whiteout */
15036+
15037+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
15038+ if (IS_ERR(wh_dentry))
15039+ goto out_unpin;
15040+
15041+ /* returns with the parent is locked and wh_dentry is dget-ed */
15042+ goto out; /* success */
15043+
4f0767ce 15044+out_unpin:
4a4d8108 15045+ au_unpin(pin);
4f0767ce 15046+out:
4a4d8108 15047+ return wh_dentry;
1facf9fc 15048+}
15049+
4a4d8108
AM
15050+/*
15051+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
15052+ * in order to be revertible and save time for removing many child whiteouts
15053+ * under the dir.
15054+ * returns 1 when there are too many child whiteout and caller should remove
15055+ * them asynchronously. returns 0 when the number of children is enough small to
15056+ * remove now or the branch fs is a remote fs.
15057+ * otherwise return an error.
15058+ */
15059+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
15060+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 15061+{
4a4d8108
AM
15062+ int rmdir_later, err, dirwh;
15063+ struct dentry *h_dentry;
15064+ struct super_block *sb;
15065+
15066+ sb = dentry->d_sb;
15067+ SiMustAnyLock(sb);
15068+ h_dentry = au_h_dptr(dentry, bindex);
15069+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
15070+ if (unlikely(err))
15071+ goto out;
15072+
15073+ /* stop monitoring */
15074+ au_hn_free(au_hi(dentry->d_inode, bindex));
15075+
15076+ if (!au_test_fs_remote(h_dentry->d_sb)) {
15077+ dirwh = au_sbi(sb)->si_dirwh;
15078+ rmdir_later = (dirwh <= 1);
15079+ if (!rmdir_later)
15080+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
15081+ dirwh);
15082+ if (rmdir_later)
15083+ return rmdir_later;
15084+ }
1facf9fc 15085+
4a4d8108
AM
15086+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
15087+ if (unlikely(err)) {
15088+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
15089+ AuDLNPair(h_dentry), bindex, err);
15090+ err = 0;
15091+ }
dece6358 15092+
4f0767ce 15093+out:
4a4d8108
AM
15094+ AuTraceErr(err);
15095+ return err;
15096+}
1308ab2a 15097+
4a4d8108
AM
15098+/*
15099+ * final procedure for deleting a entry.
15100+ * maintain dentry and iattr.
15101+ */
15102+static void epilog(struct inode *dir, struct dentry *dentry,
15103+ aufs_bindex_t bindex)
15104+{
15105+ struct inode *inode;
1308ab2a 15106+
4a4d8108
AM
15107+ inode = dentry->d_inode;
15108+ d_drop(dentry);
15109+ inode->i_ctime = dir->i_ctime;
1308ab2a 15110+
4a4d8108
AM
15111+ if (atomic_read(&dentry->d_count) == 1) {
15112+ au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
15113+ au_update_dbstart(dentry);
dece6358 15114+ }
4a4d8108
AM
15115+ if (au_ibstart(dir) == bindex)
15116+ au_cpup_attr_timesizes(dir);
15117+ dir->i_version++;
1facf9fc 15118+}
15119+
4a4d8108
AM
15120+/*
15121+ * when an error happened, remove the created whiteout and revert everything.
15122+ */
15123+static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
15124+ struct dentry *wh_dentry, struct dentry *dentry,
15125+ struct au_dtime *dt)
1facf9fc 15126+{
4a4d8108
AM
15127+ int rerr;
15128+ struct path h_path = {
15129+ .dentry = wh_dentry,
15130+ .mnt = au_sbr_mnt(dir->i_sb, bwh)
15131+ };
dece6358 15132+
4a4d8108
AM
15133+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
15134+ if (!rerr) {
15135+ au_set_dbwh(dentry, bwh);
15136+ au_dtime_revert(dt);
15137+ return 0;
15138+ }
dece6358 15139+
4a4d8108
AM
15140+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15141+ AuDLNPair(dentry), err, rerr);
15142+ return -EIO;
1facf9fc 15143+}
15144+
4a4d8108 15145+/* ---------------------------------------------------------------------- */
1facf9fc 15146+
4a4d8108 15147+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 15148+{
4a4d8108
AM
15149+ int err;
15150+ aufs_bindex_t bwh, bindex, bstart;
15151+ struct au_dtime dt;
15152+ struct au_pin pin;
15153+ struct path h_path;
15154+ struct inode *inode, *h_dir;
15155+ struct dentry *parent, *wh_dentry;
1facf9fc 15156+
4a4d8108
AM
15157+ IMustLock(dir);
15158+ inode = dentry->d_inode;
15159+ if (unlikely(!inode))
15160+ return -ENOENT; /* possible? */
15161+ IMustLock(inode);
1facf9fc 15162+
4a4d8108
AM
15163+ aufs_read_lock(dentry, AuLock_DW);
15164+ parent = dentry->d_parent; /* dir inode is locked */
15165+ di_write_lock_parent(parent);
1facf9fc 15166+
4a4d8108
AM
15167+ bstart = au_dbstart(dentry);
15168+ bwh = au_dbwh(dentry);
15169+ bindex = -1;
15170+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
15171+ err = PTR_ERR(wh_dentry);
15172+ if (IS_ERR(wh_dentry))
15173+ goto out;
1facf9fc 15174+
4a4d8108
AM
15175+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
15176+ h_path.dentry = au_h_dptr(dentry, bstart);
15177+ dget(h_path.dentry);
15178+ if (bindex == bstart) {
15179+ h_dir = au_pinned_h_dir(&pin);
15180+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
15181+ } else {
15182+ /* dir inode is locked */
15183+ h_dir = wh_dentry->d_parent->d_inode;
15184+ IMustLock(h_dir);
15185+ err = 0;
15186+ }
dece6358 15187+
4a4d8108
AM
15188+ if (!err) {
15189+ drop_nlink(inode);
15190+ epilog(dir, dentry, bindex);
15191+
15192+ /* update target timestamps */
15193+ if (bindex == bstart) {
15194+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
15195+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
15196+ } else
15197+ /* todo: this timestamp may be reverted later */
15198+ inode->i_ctime = h_dir->i_ctime;
15199+ goto out_unlock; /* success */
1facf9fc 15200+ }
15201+
4a4d8108
AM
15202+ /* revert */
15203+ if (wh_dentry) {
15204+ int rerr;
15205+
15206+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
15207+ if (rerr)
15208+ err = rerr;
dece6358 15209+ }
1facf9fc 15210+
4f0767ce 15211+out_unlock:
4a4d8108
AM
15212+ au_unpin(&pin);
15213+ dput(wh_dentry);
15214+ dput(h_path.dentry);
4f0767ce 15215+out:
4a4d8108
AM
15216+ di_write_unlock(parent);
15217+ aufs_read_unlock(dentry, AuLock_DW);
15218+ return err;
dece6358
AM
15219+}
15220+
4a4d8108 15221+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 15222+{
4a4d8108
AM
15223+ int err, rmdir_later;
15224+ aufs_bindex_t bwh, bindex, bstart;
15225+ struct au_dtime dt;
15226+ struct au_pin pin;
15227+ struct inode *inode;
15228+ struct dentry *parent, *wh_dentry, *h_dentry;
15229+ struct au_whtmp_rmdir *args;
1facf9fc 15230+
4a4d8108
AM
15231+ IMustLock(dir);
15232+ inode = dentry->d_inode;
15233+ err = -ENOENT; /* possible? */
15234+ if (unlikely(!inode))
15235+ goto out;
15236+ IMustLock(inode);
dece6358 15237+
4a4d8108
AM
15238+ aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
15239+ err = -ENOMEM;
15240+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
15241+ if (unlikely(!args))
15242+ goto out_unlock;
dece6358 15243+
4a4d8108
AM
15244+ parent = dentry->d_parent; /* dir inode is locked */
15245+ di_write_lock_parent(parent);
15246+ err = au_test_empty(dentry, &args->whlist);
15247+ if (unlikely(err))
15248+ goto out_args;
1facf9fc 15249+
4a4d8108
AM
15250+ bstart = au_dbstart(dentry);
15251+ bwh = au_dbwh(dentry);
15252+ bindex = -1;
15253+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
15254+ err = PTR_ERR(wh_dentry);
15255+ if (IS_ERR(wh_dentry))
15256+ goto out_args;
1facf9fc 15257+
4a4d8108
AM
15258+ h_dentry = au_h_dptr(dentry, bstart);
15259+ dget(h_dentry);
15260+ rmdir_later = 0;
15261+ if (bindex == bstart) {
15262+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
15263+ if (err > 0) {
15264+ rmdir_later = err;
15265+ err = 0;
15266+ }
15267+ } else {
15268+ /* stop monitoring */
15269+ au_hn_free(au_hi(inode, bstart));
15270+
15271+ /* dir inode is locked */
15272+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 15273+ err = 0;
15274+ }
15275+
4a4d8108
AM
15276+ if (!err) {
15277+ clear_nlink(inode);
15278+ au_set_dbdiropq(dentry, -1);
15279+ epilog(dir, dentry, bindex);
1308ab2a 15280+
4a4d8108
AM
15281+ if (rmdir_later) {
15282+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
15283+ args = NULL;
15284+ }
1308ab2a 15285+
4a4d8108 15286+ goto out_unpin; /* success */
1facf9fc 15287+ }
15288+
4a4d8108
AM
15289+ /* revert */
15290+ AuLabel(revert);
15291+ if (wh_dentry) {
15292+ int rerr;
1308ab2a 15293+
4a4d8108
AM
15294+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
15295+ if (rerr)
15296+ err = rerr;
1facf9fc 15297+ }
15298+
4f0767ce 15299+out_unpin:
4a4d8108
AM
15300+ au_unpin(&pin);
15301+ dput(wh_dentry);
15302+ dput(h_dentry);
4f0767ce 15303+out_args:
4a4d8108
AM
15304+ di_write_unlock(parent);
15305+ if (args)
15306+ au_whtmp_rmdir_free(args);
4f0767ce 15307+out_unlock:
4a4d8108 15308+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 15309+out:
4a4d8108
AM
15310+ AuTraceErr(err);
15311+ return err;
dece6358 15312+}
e49829fe
JR
15313--- /dev/null
15314+++ linux-2.6/fs/aufs/i_op_ren.c 2010-10-24 11:38:32.000000000 +0200
15315@@ -0,0 +1,980 @@
1facf9fc 15316+/*
4a4d8108 15317+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 15318+ *
15319+ * This program, aufs is free software; you can redistribute it and/or modify
15320+ * it under the terms of the GNU General Public License as published by
15321+ * the Free Software Foundation; either version 2 of the License, or
15322+ * (at your option) any later version.
dece6358
AM
15323+ *
15324+ * This program is distributed in the hope that it will be useful,
15325+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15326+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15327+ * GNU General Public License for more details.
15328+ *
15329+ * You should have received a copy of the GNU General Public License
15330+ * along with this program; if not, write to the Free Software
15331+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 15332+ */
15333+
15334+/*
4a4d8108
AM
15335+ * inode operation (rename entry)
15336+ * todo: this is crazy monster
1facf9fc 15337+ */
15338+
15339+#include "aufs.h"
15340+
4a4d8108
AM
15341+enum { AuSRC, AuDST, AuSrcDst };
15342+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 15343+
4a4d8108
AM
15344+#define AuRen_ISDIR 1
15345+#define AuRen_ISSAMEDIR (1 << 1)
15346+#define AuRen_WHSRC (1 << 2)
15347+#define AuRen_WHDST (1 << 3)
15348+#define AuRen_MNT_WRITE (1 << 4)
15349+#define AuRen_DT_DSTDIR (1 << 5)
15350+#define AuRen_DIROPQ (1 << 6)
15351+#define AuRen_CPUP (1 << 7)
15352+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
15353+#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
15354+#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
1facf9fc 15355+
4a4d8108
AM
15356+struct au_ren_args {
15357+ struct {
15358+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
15359+ *wh_dentry;
15360+ struct inode *dir, *inode;
15361+ struct au_hinode *hdir;
15362+ struct au_dtime dt[AuParentChild];
15363+ aufs_bindex_t bstart;
15364+ } sd[AuSrcDst];
1facf9fc 15365+
4a4d8108
AM
15366+#define src_dentry sd[AuSRC].dentry
15367+#define src_dir sd[AuSRC].dir
15368+#define src_inode sd[AuSRC].inode
15369+#define src_h_dentry sd[AuSRC].h_dentry
15370+#define src_parent sd[AuSRC].parent
15371+#define src_h_parent sd[AuSRC].h_parent
15372+#define src_wh_dentry sd[AuSRC].wh_dentry
15373+#define src_hdir sd[AuSRC].hdir
15374+#define src_h_dir sd[AuSRC].hdir->hi_inode
15375+#define src_dt sd[AuSRC].dt
15376+#define src_bstart sd[AuSRC].bstart
1facf9fc 15377+
4a4d8108
AM
15378+#define dst_dentry sd[AuDST].dentry
15379+#define dst_dir sd[AuDST].dir
15380+#define dst_inode sd[AuDST].inode
15381+#define dst_h_dentry sd[AuDST].h_dentry
15382+#define dst_parent sd[AuDST].parent
15383+#define dst_h_parent sd[AuDST].h_parent
15384+#define dst_wh_dentry sd[AuDST].wh_dentry
15385+#define dst_hdir sd[AuDST].hdir
15386+#define dst_h_dir sd[AuDST].hdir->hi_inode
15387+#define dst_dt sd[AuDST].dt
15388+#define dst_bstart sd[AuDST].bstart
15389+
15390+ struct dentry *h_trap;
15391+ struct au_branch *br;
15392+ struct au_hinode *src_hinode;
15393+ struct path h_path;
15394+ struct au_nhash whlist;
15395+ aufs_bindex_t btgt;
1facf9fc 15396+
1308ab2a 15397+ unsigned int flags;
1facf9fc 15398+
4a4d8108
AM
15399+ struct au_whtmp_rmdir *thargs;
15400+ struct dentry *h_dst;
15401+};
1308ab2a 15402+
4a4d8108 15403+/* ---------------------------------------------------------------------- */
1308ab2a 15404+
4a4d8108
AM
15405+/*
15406+ * functions for reverting.
15407+ * when an error happened in a single rename systemcall, we should revert
15408+ * everything as if nothing happend.
15409+ * we don't need to revert the copied-up/down the parent dir since they are
15410+ * harmless.
15411+ */
1facf9fc 15412+
4a4d8108
AM
15413+#define RevertFailure(fmt, ...) do { \
15414+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
15415+ ##__VA_ARGS__, err, rerr); \
15416+ err = -EIO; \
15417+} while (0)
1facf9fc 15418+
4a4d8108 15419+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 15420+{
4a4d8108 15421+ int rerr;
1facf9fc 15422+
4a4d8108
AM
15423+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15424+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
15425+ au_hn_imtx_unlock(a->src_hinode);
15426+ if (rerr)
15427+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
15428+}
1facf9fc 15429+
4a4d8108
AM
15430+static void au_ren_rev_rename(int err, struct au_ren_args *a)
15431+{
15432+ int rerr;
1facf9fc 15433+
4a4d8108
AM
15434+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
15435+ a->br, /*nd*/NULL);
15436+ rerr = PTR_ERR(a->h_path.dentry);
15437+ if (IS_ERR(a->h_path.dentry)) {
15438+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
15439+ return;
1facf9fc 15440+ }
15441+
4a4d8108
AM
15442+ rerr = vfsub_rename(a->dst_h_dir,
15443+ au_h_dptr(a->src_dentry, a->btgt),
15444+ a->src_h_dir, &a->h_path);
15445+ d_drop(a->h_path.dentry);
15446+ dput(a->h_path.dentry);
15447+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
15448+ if (rerr)
15449+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 15450+}
15451+
4a4d8108 15452+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 15453+{
4a4d8108 15454+ int rerr;
1facf9fc 15455+
4a4d8108
AM
15456+ a->h_path.dentry = a->dst_h_dentry;
15457+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
15458+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
15459+ au_set_dbstart(a->src_dentry, a->src_bstart);
15460+ if (rerr)
15461+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 15462+}
15463+
4a4d8108 15464+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 15465+{
4a4d8108 15466+ int rerr;
dece6358 15467+
4a4d8108
AM
15468+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
15469+ a->br, /*nd*/NULL);
15470+ rerr = PTR_ERR(a->h_path.dentry);
15471+ if (IS_ERR(a->h_path.dentry)) {
15472+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
15473+ return;
15474+ }
15475+ if (a->h_path.dentry->d_inode) {
15476+ d_drop(a->h_path.dentry);
15477+ dput(a->h_path.dentry);
15478+ return;
dece6358
AM
15479+ }
15480+
4a4d8108
AM
15481+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
15482+ d_drop(a->h_path.dentry);
15483+ dput(a->h_path.dentry);
15484+ if (!rerr)
15485+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
15486+ else
15487+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
15488+}
1308ab2a 15489+
4a4d8108
AM
15490+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
15491+{
15492+ int rerr;
1308ab2a 15493+
4a4d8108
AM
15494+ a->h_path.dentry = a->src_wh_dentry;
15495+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
15496+ if (rerr)
15497+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
15498+}
1308ab2a 15499+
4a4d8108
AM
15500+static void au_ren_rev_drop(struct au_ren_args *a)
15501+{
15502+ struct dentry *d, *h_d;
15503+ int i;
15504+ aufs_bindex_t bend, bindex;
15505+
15506+ for (i = 0; i < AuSrcDst; i++) {
15507+ d = a->sd[i].dentry;
15508+ d_drop(d);
15509+ bend = au_dbend(d);
15510+ for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
15511+ h_d = au_h_dptr(d, bindex);
15512+ if (h_d)
15513+ d_drop(h_d);
15514+ }
1308ab2a 15515+ }
15516+
4a4d8108
AM
15517+ au_update_dbstart(a->dst_dentry);
15518+ if (a->thargs)
15519+ d_drop(a->h_dst);
1facf9fc 15520+}
4a4d8108 15521+#undef RevertFailure
1facf9fc 15522+
1308ab2a 15523+/* ---------------------------------------------------------------------- */
15524+
4a4d8108
AM
15525+/*
15526+ * when we have to copyup the renaming entry, do it with the rename-target name
15527+ * in order to minimize the cost (the later actual rename is unnecessary).
15528+ * otherwise rename it on the target branch.
15529+ */
15530+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 15531+{
dece6358 15532+ int err;
4a4d8108 15533+ struct dentry *d;
1facf9fc 15534+
4a4d8108
AM
15535+ d = a->src_dentry;
15536+ if (au_dbstart(d) == a->btgt) {
15537+ a->h_path.dentry = a->dst_h_dentry;
15538+ if (au_ftest_ren(a->flags, DIROPQ)
15539+ && au_dbdiropq(d) == a->btgt)
15540+ au_fclr_ren(a->flags, DIROPQ);
15541+ AuDebugOn(au_dbstart(d) != a->btgt);
15542+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
15543+ a->dst_h_dir, &a->h_path);
15544+ } else {
15545+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15546+ struct file *h_file;
1308ab2a 15547+
4a4d8108
AM
15548+ au_fset_ren(a->flags, CPUP);
15549+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15550+ au_set_dbstart(d, a->btgt);
15551+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
15552+ h_file = au_h_open_pre(d, a->src_bstart);
15553+ if (IS_ERR(h_file)) {
15554+ err = PTR_ERR(h_file);
15555+ h_file = NULL;
15556+ } else
15557+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
15558+ !AuCpup_DTIME, a->dst_parent);
15559+ mutex_unlock(h_mtx);
15560+ au_h_open_post(d, a->src_bstart, h_file);
15561+ if (!err) {
15562+ d = a->dst_dentry;
15563+ au_set_h_dptr(d, a->btgt, NULL);
15564+ au_update_dbstart(d);
15565+ } else {
15566+ au_set_h_dptr(d, a->btgt, NULL);
15567+ au_set_dbstart(d, a->src_bstart);
15568+ }
1308ab2a 15569+ }
1facf9fc 15570+
dece6358
AM
15571+ return err;
15572+}
1facf9fc 15573+
4a4d8108
AM
15574+/* cf. aufs_rmdir() */
15575+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 15576+{
4a4d8108
AM
15577+ int err;
15578+ struct inode *dir;
1facf9fc 15579+
4a4d8108
AM
15580+ dir = a->dst_dir;
15581+ SiMustAnyLock(dir->i_sb);
15582+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
15583+ au_sbi(dir->i_sb)->si_dirwh)
15584+ || au_test_fs_remote(a->h_dst->d_sb)) {
15585+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
15586+ if (unlikely(err))
15587+ pr_warning("failed removing whtmp dir %.*s (%d), "
15588+ "ignored.\n", AuDLNPair(a->h_dst), err);
15589+ } else {
15590+ au_nhash_wh_free(&a->thargs->whlist);
15591+ a->thargs->whlist = a->whlist;
15592+ a->whlist.nh_num = 0;
15593+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
15594+ dput(a->h_dst);
15595+ a->thargs = NULL;
15596+ }
15597+
15598+ return 0;
1308ab2a 15599+}
1facf9fc 15600+
4a4d8108
AM
15601+/* make it 'opaque' dir. */
15602+static int au_ren_diropq(struct au_ren_args *a)
15603+{
15604+ int err;
15605+ struct dentry *diropq;
1facf9fc 15606+
4a4d8108
AM
15607+ err = 0;
15608+ a->src_hinode = au_hi(a->src_inode, a->btgt);
15609+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15610+ diropq = au_diropq_create(a->src_dentry, a->btgt);
15611+ au_hn_imtx_unlock(a->src_hinode);
15612+ if (IS_ERR(diropq))
15613+ err = PTR_ERR(diropq);
15614+ dput(diropq);
1facf9fc 15615+
4a4d8108
AM
15616+ return err;
15617+}
1facf9fc 15618+
4a4d8108
AM
15619+static int do_rename(struct au_ren_args *a)
15620+{
15621+ int err;
15622+ struct dentry *d, *h_d;
1facf9fc 15623+
4a4d8108
AM
15624+ /* prepare workqueue args for asynchronous rmdir */
15625+ h_d = a->dst_h_dentry;
15626+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
15627+ err = -ENOMEM;
15628+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
15629+ if (unlikely(!a->thargs))
15630+ goto out;
15631+ a->h_dst = dget(h_d);
15632+ }
1facf9fc 15633+
4a4d8108
AM
15634+ /* create whiteout for src_dentry */
15635+ if (au_ftest_ren(a->flags, WHSRC)) {
15636+ a->src_wh_dentry
15637+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
15638+ err = PTR_ERR(a->src_wh_dentry);
15639+ if (IS_ERR(a->src_wh_dentry))
15640+ goto out_thargs;
15641+ }
1facf9fc 15642+
4a4d8108
AM
15643+ /* lookup whiteout for dentry */
15644+ if (au_ftest_ren(a->flags, WHDST)) {
15645+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
15646+ a->br);
15647+ err = PTR_ERR(h_d);
15648+ if (IS_ERR(h_d))
15649+ goto out_whsrc;
15650+ if (!h_d->d_inode)
15651+ dput(h_d);
15652+ else
15653+ a->dst_wh_dentry = h_d;
15654+ }
1facf9fc 15655+
4a4d8108
AM
15656+ /* rename dentry to tmpwh */
15657+ if (a->thargs) {
15658+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
15659+ if (unlikely(err))
15660+ goto out_whdst;
dece6358 15661+
4a4d8108
AM
15662+ d = a->dst_dentry;
15663+ au_set_h_dptr(d, a->btgt, NULL);
15664+ err = au_lkup_neg(d, a->btgt);
15665+ if (unlikely(err))
15666+ goto out_whtmp;
15667+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
15668+ }
1facf9fc 15669+
4a4d8108
AM
15670+ /* cpup src */
15671+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
15672+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15673+ struct file *h_file;
1facf9fc 15674+
4a4d8108
AM
15675+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15676+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
15677+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
15678+ if (IS_ERR(h_file)) {
15679+ err = PTR_ERR(h_file);
15680+ h_file = NULL;
15681+ } else
15682+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
15683+ !AuCpup_DTIME);
15684+ mutex_unlock(h_mtx);
15685+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
15686+ if (unlikely(err))
15687+ goto out_whtmp;
15688+ }
1facf9fc 15689+
4a4d8108
AM
15690+ /* rename by vfs_rename or cpup */
15691+ d = a->dst_dentry;
15692+ if (au_ftest_ren(a->flags, ISDIR)
15693+ && (a->dst_wh_dentry
15694+ || au_dbdiropq(d) == a->btgt
15695+ /* hide the lower to keep xino */
15696+ || a->btgt < au_dbend(d)
15697+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
15698+ au_fset_ren(a->flags, DIROPQ);
15699+ err = au_ren_or_cpup(a);
15700+ if (unlikely(err))
15701+ /* leave the copied-up one */
15702+ goto out_whtmp;
1308ab2a 15703+
4a4d8108
AM
15704+ /* make dir opaque */
15705+ if (au_ftest_ren(a->flags, DIROPQ)) {
15706+ err = au_ren_diropq(a);
15707+ if (unlikely(err))
15708+ goto out_rename;
15709+ }
1308ab2a 15710+
4a4d8108
AM
15711+ /* update target timestamps */
15712+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
15713+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
15714+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
15715+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 15716+
4a4d8108
AM
15717+ /* remove whiteout for dentry */
15718+ if (a->dst_wh_dentry) {
15719+ a->h_path.dentry = a->dst_wh_dentry;
15720+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
15721+ a->dst_dentry);
15722+ if (unlikely(err))
15723+ goto out_diropq;
15724+ }
1facf9fc 15725+
4a4d8108
AM
15726+ /* remove whtmp */
15727+ if (a->thargs)
15728+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 15729+
4a4d8108
AM
15730+ err = 0;
15731+ goto out_success;
15732+
4f0767ce 15733+out_diropq:
4a4d8108
AM
15734+ if (au_ftest_ren(a->flags, DIROPQ))
15735+ au_ren_rev_diropq(err, a);
4f0767ce 15736+out_rename:
4a4d8108
AM
15737+ if (!au_ftest_ren(a->flags, CPUP))
15738+ au_ren_rev_rename(err, a);
15739+ else
15740+ au_ren_rev_cpup(err, a);
4f0767ce 15741+out_whtmp:
4a4d8108
AM
15742+ if (a->thargs)
15743+ au_ren_rev_whtmp(err, a);
4f0767ce 15744+out_whdst:
4a4d8108
AM
15745+ dput(a->dst_wh_dentry);
15746+ a->dst_wh_dentry = NULL;
4f0767ce 15747+out_whsrc:
4a4d8108
AM
15748+ if (a->src_wh_dentry)
15749+ au_ren_rev_whsrc(err, a);
15750+ au_ren_rev_drop(a);
4f0767ce 15751+out_success:
4a4d8108
AM
15752+ dput(a->src_wh_dentry);
15753+ dput(a->dst_wh_dentry);
4f0767ce 15754+out_thargs:
4a4d8108
AM
15755+ if (a->thargs) {
15756+ dput(a->h_dst);
15757+ au_whtmp_rmdir_free(a->thargs);
15758+ a->thargs = NULL;
15759+ }
4f0767ce 15760+out:
4a4d8108 15761+ return err;
dece6358 15762+}
1facf9fc 15763+
1308ab2a 15764+/* ---------------------------------------------------------------------- */
1facf9fc 15765+
4a4d8108
AM
15766+/*
15767+ * test if @dentry dir can be rename destination or not.
15768+ * success means, it is a logically empty dir.
15769+ */
15770+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 15771+{
4a4d8108 15772+ return au_test_empty(dentry, whlist);
1308ab2a 15773+}
1facf9fc 15774+
4a4d8108
AM
15775+/*
15776+ * test if @dentry dir can be rename source or not.
15777+ * if it can, return 0 and @children is filled.
15778+ * success means,
15779+ * - it is a logically empty dir.
15780+ * - or, it exists on writable branch and has no children including whiteouts
15781+ * on the lower branch.
15782+ */
15783+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
15784+{
15785+ int err;
15786+ unsigned int rdhash;
15787+ aufs_bindex_t bstart;
1facf9fc 15788+
4a4d8108
AM
15789+ bstart = au_dbstart(dentry);
15790+ if (bstart != btgt) {
15791+ struct au_nhash whlist;
dece6358 15792+
4a4d8108
AM
15793+ SiMustAnyLock(dentry->d_sb);
15794+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
15795+ if (!rdhash)
15796+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
15797+ dentry));
15798+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
15799+ if (unlikely(err))
15800+ goto out;
15801+ err = au_test_empty(dentry, &whlist);
15802+ au_nhash_wh_free(&whlist);
15803+ goto out;
15804+ }
dece6358 15805+
4a4d8108
AM
15806+ if (bstart == au_dbtaildir(dentry))
15807+ return 0; /* success */
dece6358 15808+
4a4d8108 15809+ err = au_test_empty_lower(dentry);
1facf9fc 15810+
4f0767ce 15811+out:
4a4d8108
AM
15812+ if (err == -ENOTEMPTY) {
15813+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
15814+ " is not supported\n");
15815+ err = -EXDEV;
15816+ }
15817+ return err;
15818+}
1308ab2a 15819+
4a4d8108
AM
15820+/* side effect: sets whlist and h_dentry */
15821+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 15822+{
4a4d8108
AM
15823+ int err;
15824+ unsigned int rdhash;
15825+ struct dentry *d;
1facf9fc 15826+
4a4d8108
AM
15827+ d = a->dst_dentry;
15828+ SiMustAnyLock(d->d_sb);
1facf9fc 15829+
4a4d8108
AM
15830+ err = 0;
15831+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
15832+ rdhash = au_sbi(d->d_sb)->si_rdhash;
15833+ if (!rdhash)
15834+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
15835+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
15836+ if (unlikely(err))
15837+ goto out;
1308ab2a 15838+
4a4d8108
AM
15839+ au_set_dbstart(d, a->dst_bstart);
15840+ err = may_rename_dstdir(d, &a->whlist);
15841+ au_set_dbstart(d, a->btgt);
15842+ }
15843+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
15844+ if (unlikely(err))
15845+ goto out;
15846+
15847+ d = a->src_dentry;
15848+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
15849+ if (au_ftest_ren(a->flags, ISDIR)) {
15850+ err = may_rename_srcdir(d, a->btgt);
15851+ if (unlikely(err)) {
15852+ au_nhash_wh_free(&a->whlist);
15853+ a->whlist.nh_num = 0;
15854+ }
15855+ }
4f0767ce 15856+out:
4a4d8108 15857+ return err;
1facf9fc 15858+}
15859+
4a4d8108 15860+/* ---------------------------------------------------------------------- */
1facf9fc 15861+
4a4d8108
AM
15862+/*
15863+ * simple tests for rename.
15864+ * following the checks in vfs, plus the parent-child relationship.
15865+ */
15866+static int au_may_ren(struct au_ren_args *a)
15867+{
15868+ int err, isdir;
15869+ struct inode *h_inode;
1facf9fc 15870+
4a4d8108
AM
15871+ if (a->src_bstart == a->btgt) {
15872+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
15873+ au_ftest_ren(a->flags, ISDIR));
15874+ if (unlikely(err))
15875+ goto out;
15876+ err = -EINVAL;
15877+ if (unlikely(a->src_h_dentry == a->h_trap))
15878+ goto out;
15879+ }
1facf9fc 15880+
4a4d8108
AM
15881+ err = 0;
15882+ if (a->dst_bstart != a->btgt)
15883+ goto out;
1facf9fc 15884+
4a4d8108
AM
15885+ err = -EIO;
15886+ h_inode = a->dst_h_dentry->d_inode;
15887+ isdir = !!au_ftest_ren(a->flags, ISDIR);
15888+ if (!a->dst_dentry->d_inode) {
15889+ if (unlikely(h_inode))
15890+ goto out;
15891+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
15892+ isdir);
15893+ } else {
15894+ if (unlikely(!h_inode || !h_inode->i_nlink))
15895+ goto out;
15896+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
15897+ isdir);
15898+ if (unlikely(err))
15899+ goto out;
15900+ err = -ENOTEMPTY;
15901+ if (unlikely(a->dst_h_dentry == a->h_trap))
15902+ goto out;
15903+ err = 0;
15904+ }
1facf9fc 15905+
4f0767ce 15906+out:
4a4d8108
AM
15907+ if (unlikely(err == -ENOENT || err == -EEXIST))
15908+ err = -EIO;
15909+ AuTraceErr(err);
15910+ return err;
15911+}
1facf9fc 15912+
1308ab2a 15913+/* ---------------------------------------------------------------------- */
1facf9fc 15914+
4a4d8108
AM
15915+/*
15916+ * locking order
15917+ * (VFS)
15918+ * - src_dir and dir by lock_rename()
15919+ * - inode if exitsts
15920+ * (aufs)
15921+ * - lock all
15922+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
15923+ * + si_read_lock
15924+ * + di_write_lock2_child()
15925+ * + di_write_lock_child()
15926+ * + ii_write_lock_child()
15927+ * + di_write_lock_child2()
15928+ * + ii_write_lock_child2()
15929+ * + src_parent and parent
15930+ * + di_write_lock_parent()
15931+ * + ii_write_lock_parent()
15932+ * + di_write_lock_parent2()
15933+ * + ii_write_lock_parent2()
15934+ * + lower src_dir and dir by vfsub_lock_rename()
15935+ * + verify the every relationships between child and parent. if any
15936+ * of them failed, unlock all and return -EBUSY.
15937+ */
15938+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 15939+{
4a4d8108
AM
15940+ struct super_block *sb;
15941+
15942+ sb = a->dst_dentry->d_sb;
15943+ if (au_ftest_ren(a->flags, MNT_WRITE))
15944+ mnt_drop_write(a->br->br_mnt);
15945+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
15946+ a->dst_h_parent, a->dst_hdir);
1308ab2a 15947+}
15948+
4a4d8108 15949+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 15950+{
4a4d8108
AM
15951+ int err;
15952+ unsigned int udba;
1308ab2a 15953+
4a4d8108
AM
15954+ err = 0;
15955+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
15956+ a->src_hdir = au_hi(a->src_dir, a->btgt);
15957+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
15958+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
15959+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
15960+ a->dst_h_parent, a->dst_hdir);
15961+ udba = au_opt_udba(a->src_dentry->d_sb);
15962+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
15963+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
15964+ err = au_busy_or_stale();
15965+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
15966+ err = au_h_verify(a->src_h_dentry, udba,
15967+ a->src_h_parent->d_inode, a->src_h_parent,
15968+ a->br);
15969+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
15970+ err = au_h_verify(a->dst_h_dentry, udba,
15971+ a->dst_h_parent->d_inode, a->dst_h_parent,
15972+ a->br);
15973+ if (!err) {
15974+ err = mnt_want_write(a->br->br_mnt);
15975+ if (unlikely(err))
15976+ goto out_unlock;
15977+ au_fset_ren(a->flags, MNT_WRITE);
15978+ goto out; /* success */
15979+ }
15980+
15981+ err = au_busy_or_stale();
15982+
4f0767ce 15983+out_unlock:
4a4d8108 15984+ au_ren_unlock(a);
4f0767ce 15985+out:
4a4d8108 15986+ return err;
1facf9fc 15987+}
15988+
15989+/* ---------------------------------------------------------------------- */
15990+
4a4d8108 15991+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 15992+{
4a4d8108 15993+ struct inode *dir;
dece6358 15994+
4a4d8108
AM
15995+ dir = a->dst_dir;
15996+ dir->i_version++;
15997+ if (au_ftest_ren(a->flags, ISDIR)) {
15998+ /* is this updating defined in POSIX? */
15999+ au_cpup_attr_timesizes(a->src_inode);
16000+ au_cpup_attr_nlink(dir, /*force*/1);
16001+ if (a->dst_inode) {
16002+ clear_nlink(a->dst_inode);
16003+ au_cpup_attr_timesizes(a->dst_inode);
16004+ }
16005+ }
16006+ if (au_ibstart(dir) == a->btgt)
16007+ au_cpup_attr_timesizes(dir);
dece6358 16008+
4a4d8108
AM
16009+ if (au_ftest_ren(a->flags, ISSAMEDIR))
16010+ return;
dece6358 16011+
4a4d8108
AM
16012+ dir = a->src_dir;
16013+ dir->i_version++;
16014+ if (au_ftest_ren(a->flags, ISDIR))
16015+ au_cpup_attr_nlink(dir, /*force*/1);
16016+ if (au_ibstart(dir) == a->btgt)
16017+ au_cpup_attr_timesizes(dir);
1facf9fc 16018+}
16019+
4a4d8108 16020+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 16021+{
4a4d8108
AM
16022+ aufs_bindex_t bend, bindex;
16023+ struct dentry *d, *h_d;
16024+ struct inode *i, *h_i;
16025+ struct super_block *sb;
dece6358 16026+
4a4d8108
AM
16027+ d = a->src_dentry;
16028+ au_set_dbwh(d, -1);
16029+ bend = au_dbend(d);
16030+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
16031+ h_d = au_h_dptr(d, bindex);
16032+ if (h_d)
16033+ au_set_h_dptr(d, bindex, NULL);
16034+ }
16035+ au_set_dbend(d, a->btgt);
16036+
16037+ sb = d->d_sb;
16038+ i = a->src_inode;
16039+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
16040+ return; /* success */
16041+
16042+ bend = au_ibend(i);
16043+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
16044+ h_i = au_h_iptr(i, bindex);
16045+ if (h_i) {
16046+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
16047+ /* ignore this error */
16048+ au_set_h_iptr(i, bindex, NULL, 0);
16049+ }
16050+ }
16051+ au_set_ibend(i, a->btgt);
1308ab2a 16052+}
dece6358 16053+
4a4d8108
AM
16054+/* ---------------------------------------------------------------------- */
16055+
16056+/* mainly for link(2) and rename(2) */
16057+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 16058+{
4a4d8108
AM
16059+ aufs_bindex_t bdiropq, bwh;
16060+ struct dentry *parent;
16061+ struct au_branch *br;
16062+
16063+ parent = dentry->d_parent;
16064+ IMustLock(parent->d_inode); /* dir is locked */
16065+
16066+ bdiropq = au_dbdiropq(parent);
16067+ bwh = au_dbwh(dentry);
16068+ br = au_sbr(dentry->d_sb, btgt);
16069+ if (au_br_rdonly(br)
16070+ || (0 <= bdiropq && bdiropq < btgt)
16071+ || (0 <= bwh && bwh < btgt))
16072+ btgt = -1;
16073+
16074+ AuDbg("btgt %d\n", btgt);
16075+ return btgt;
1facf9fc 16076+}
16077+
4a4d8108
AM
16078+/* sets src_bstart, dst_bstart and btgt */
16079+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 16080+{
4a4d8108
AM
16081+ int err;
16082+ struct au_wr_dir_args wr_dir_args = {
16083+ /* .force_btgt = -1, */
16084+ .flags = AuWrDir_ADD_ENTRY
16085+ };
dece6358 16086+
4a4d8108
AM
16087+ a->src_bstart = au_dbstart(a->src_dentry);
16088+ a->dst_bstart = au_dbstart(a->dst_dentry);
16089+ if (au_ftest_ren(a->flags, ISDIR))
16090+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16091+ wr_dir_args.force_btgt = a->src_bstart;
16092+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
16093+ wr_dir_args.force_btgt = a->dst_bstart;
16094+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
16095+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
16096+ a->btgt = err;
dece6358 16097+
4a4d8108 16098+ return err;
1facf9fc 16099+}
16100+
4a4d8108 16101+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 16102+{
4a4d8108
AM
16103+ a->h_path.dentry = a->src_h_parent;
16104+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
16105+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
16106+ a->h_path.dentry = a->dst_h_parent;
16107+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
16108+ }
1facf9fc 16109+
4a4d8108
AM
16110+ au_fclr_ren(a->flags, DT_DSTDIR);
16111+ if (!au_ftest_ren(a->flags, ISDIR))
16112+ return;
dece6358 16113+
4a4d8108
AM
16114+ a->h_path.dentry = a->src_h_dentry;
16115+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
16116+ if (a->dst_h_dentry->d_inode) {
16117+ au_fset_ren(a->flags, DT_DSTDIR);
16118+ a->h_path.dentry = a->dst_h_dentry;
16119+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
16120+ }
1308ab2a 16121+}
dece6358 16122+
4a4d8108 16123+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 16124+{
4a4d8108
AM
16125+ struct dentry *h_d;
16126+ struct mutex *h_mtx;
16127+
16128+ au_dtime_revert(a->src_dt + AuPARENT);
16129+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
16130+ au_dtime_revert(a->dst_dt + AuPARENT);
16131+
16132+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
16133+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
16134+ h_mtx = &h_d->d_inode->i_mutex;
16135+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16136+ au_dtime_revert(a->src_dt + AuCHILD);
16137+ mutex_unlock(h_mtx);
16138+
16139+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
16140+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
16141+ h_mtx = &h_d->d_inode->i_mutex;
16142+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16143+ au_dtime_revert(a->dst_dt + AuCHILD);
16144+ mutex_unlock(h_mtx);
1facf9fc 16145+ }
16146+ }
16147+}
16148+
4a4d8108
AM
16149+/* ---------------------------------------------------------------------- */
16150+
16151+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
16152+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 16153+{
e49829fe 16154+ int err, flags;
4a4d8108
AM
16155+ /* reduce stack space */
16156+ struct au_ren_args *a;
16157+
16158+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
16159+ IMustLock(_src_dir);
16160+ IMustLock(_dst_dir);
16161+
16162+ err = -ENOMEM;
16163+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
16164+ a = kzalloc(sizeof(*a), GFP_NOFS);
16165+ if (unlikely(!a))
16166+ goto out;
16167+
16168+ a->src_dir = _src_dir;
16169+ a->src_dentry = _src_dentry;
16170+ a->src_inode = a->src_dentry->d_inode;
16171+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
16172+ a->dst_dir = _dst_dir;
16173+ a->dst_dentry = _dst_dentry;
16174+ a->dst_inode = a->dst_dentry->d_inode;
16175+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
16176+ if (a->dst_inode) {
16177+ IMustLock(a->dst_inode);
16178+ au_igrab(a->dst_inode);
1facf9fc 16179+ }
1facf9fc 16180+
4a4d8108 16181+ err = -ENOTDIR;
e49829fe 16182+ flags = AuLock_FLUSH | AuLock_NOPLM;
4a4d8108
AM
16183+ if (S_ISDIR(a->src_inode->i_mode)) {
16184+ au_fset_ren(a->flags, ISDIR);
16185+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
16186+ goto out_free;
e49829fe
JR
16187+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16188+ AuLock_DIR | flags);
4a4d8108 16189+ } else
e49829fe
JR
16190+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16191+ flags);
16192+ if (unlikely(err))
16193+ goto out_free;
1facf9fc 16194+
4a4d8108
AM
16195+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
16196+ di_write_lock_parent(a->dst_parent);
1facf9fc 16197+
4a4d8108
AM
16198+ /* which branch we process */
16199+ err = au_ren_wbr(a);
16200+ if (unlikely(err < 0))
16201+ goto out_unlock;
16202+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
16203+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 16204+
4a4d8108
AM
16205+ /* are they available to be renamed */
16206+ err = au_ren_may_dir(a);
16207+ if (unlikely(err))
16208+ goto out_children;
1facf9fc 16209+
4a4d8108
AM
16210+ /* prepare the writable parent dir on the same branch */
16211+ if (a->dst_bstart == a->btgt) {
16212+ au_fset_ren(a->flags, WHDST);
16213+ } else {
16214+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
16215+ if (unlikely(err))
16216+ goto out_children;
16217+ }
1facf9fc 16218+
4a4d8108
AM
16219+ if (a->src_dir != a->dst_dir) {
16220+ /*
16221+ * this temporary unlock is safe,
16222+ * because both dir->i_mutex are locked.
16223+ */
16224+ di_write_unlock(a->dst_parent);
16225+ di_write_lock_parent(a->src_parent);
16226+ err = au_wr_dir_need_wh(a->src_dentry,
16227+ au_ftest_ren(a->flags, ISDIR),
16228+ &a->btgt);
16229+ di_write_unlock(a->src_parent);
16230+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
16231+ au_fclr_ren(a->flags, ISSAMEDIR);
16232+ } else
16233+ err = au_wr_dir_need_wh(a->src_dentry,
16234+ au_ftest_ren(a->flags, ISDIR),
16235+ &a->btgt);
16236+ if (unlikely(err < 0))
16237+ goto out_children;
16238+ if (err)
16239+ au_fset_ren(a->flags, WHSRC);
1facf9fc 16240+
4a4d8108
AM
16241+ /* lock them all */
16242+ err = au_ren_lock(a);
16243+ if (unlikely(err))
16244+ goto out_children;
1facf9fc 16245+
4a4d8108
AM
16246+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
16247+ err = au_may_ren(a);
16248+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
16249+ err = -ENAMETOOLONG;
16250+ if (unlikely(err))
16251+ goto out_hdir;
1facf9fc 16252+
4a4d8108
AM
16253+ /* store timestamps to be revertible */
16254+ au_ren_dt(a);
1facf9fc 16255+
4a4d8108
AM
16256+ /* here we go */
16257+ err = do_rename(a);
16258+ if (unlikely(err))
16259+ goto out_dt;
16260+
16261+ /* update dir attributes */
16262+ au_ren_refresh_dir(a);
16263+
16264+ /* dput/iput all lower dentries */
16265+ au_ren_refresh(a);
16266+
16267+ goto out_hdir; /* success */
16268+
4f0767ce 16269+out_dt:
4a4d8108 16270+ au_ren_rev_dt(err, a);
4f0767ce 16271+out_hdir:
4a4d8108 16272+ au_ren_unlock(a);
4f0767ce 16273+out_children:
4a4d8108 16274+ au_nhash_wh_free(&a->whlist);
4f0767ce 16275+out_unlock:
4a4d8108
AM
16276+ if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
16277+ au_update_dbstart(a->dst_dentry);
16278+ d_drop(a->dst_dentry);
16279+ }
16280+ if (!err)
16281+ d_move(a->src_dentry, a->dst_dentry);
16282+ if (au_ftest_ren(a->flags, ISSAMEDIR))
16283+ di_write_unlock(a->dst_parent);
16284+ else
16285+ di_write_unlock2(a->src_parent, a->dst_parent);
16286+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 16287+out_free:
4a4d8108
AM
16288+ iput(a->dst_inode);
16289+ if (a->thargs)
16290+ au_whtmp_rmdir_free(a->thargs);
16291+ kfree(a);
4f0767ce 16292+out:
4a4d8108
AM
16293+ AuTraceErr(err);
16294+ return err;
1308ab2a 16295+}
e49829fe
JR
16296--- /dev/null
16297+++ linux-2.6/fs/aufs/Kconfig 2010-10-24 11:39:57.000000000 +0200
16298@@ -0,0 +1,182 @@
4a4d8108
AM
16299+config AUFS_FS
16300+ tristate "Aufs (Advanced multi layered unification filesystem) support"
16301+ depends on EXPERIMENTAL
16302+ help
16303+ Aufs is a stackable unification filesystem such as Unionfs,
16304+ which unifies several directories and provides a merged single
16305+ directory.
16306+ In the early days, aufs was entirely re-designed and
16307+ re-implemented Unionfs Version 1.x series. Introducing many
16308+ original ideas, approaches and improvements, it becomes totally
16309+ different from Unionfs while keeping the basic features.
1facf9fc 16310+
4a4d8108
AM
16311+if AUFS_FS
16312+choice
16313+ prompt "Maximum number of branches"
16314+ default AUFS_BRANCH_MAX_127
16315+ help
16316+ Specifies the maximum number of branches (or member directories)
16317+ in a single aufs. The larger value consumes more system
16318+ resources and has a minor impact to performance.
16319+config AUFS_BRANCH_MAX_127
16320+ bool "127"
16321+ help
16322+ Specifies the maximum number of branches (or member directories)
16323+ in a single aufs. The larger value consumes more system
16324+ resources and has a minor impact to performance.
16325+config AUFS_BRANCH_MAX_511
16326+ bool "511"
16327+ help
16328+ Specifies the maximum number of branches (or member directories)
16329+ in a single aufs. The larger value consumes more system
16330+ resources and has a minor impact to performance.
16331+config AUFS_BRANCH_MAX_1023
16332+ bool "1023"
16333+ help
16334+ Specifies the maximum number of branches (or member directories)
16335+ in a single aufs. The larger value consumes more system
16336+ resources and has a minor impact to performance.
16337+config AUFS_BRANCH_MAX_32767
16338+ bool "32767"
16339+ help
16340+ Specifies the maximum number of branches (or member directories)
16341+ in a single aufs. The larger value consumes more system
16342+ resources and has a minor impact to performance.
16343+endchoice
1facf9fc 16344+
e49829fe
JR
16345+config AUFS_SBILIST
16346+ bool
16347+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
16348+ default y
16349+ help
16350+ Automatic configuration for internal use.
16351+ When aufs supports Magic SysRq or /proc, enabled automatically.
16352+
4a4d8108
AM
16353+config AUFS_HNOTIFY
16354+ bool "Detect direct branch access (bypassing aufs)"
16355+ help
16356+ If you want to modify files on branches directly, eg. bypassing aufs,
16357+ and want aufs to detect the changes of them fully, then enable this
16358+ option and use 'udba=notify' mount option.
16359+ It will have a negative impact to the performance.
16360+ See detail in aufs.5.
dece6358 16361+
4a4d8108
AM
16362+choice
16363+ prompt "method" if AUFS_HNOTIFY
16364+ default AUFS_HFSNOTIFY
16365+config AUFS_HFSNOTIFY
16366+ bool "fsnotify"
16367+ select FSNOTIFY
e49829fe
JR
16368+config AUFS_HINOTIFY
16369+ bool "inotify (DEPRECATED)"
16370+ depends on INOTIFY
4a4d8108 16371+endchoice
1facf9fc 16372+
4a4d8108
AM
16373+config AUFS_EXPORT
16374+ bool "NFS-exportable aufs"
16375+ depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
16376+ help
16377+ If you want to export your mounted aufs via NFS, then enable this
16378+ option. There are several requirements for this configuration.
16379+ See detail in aufs.5.
1facf9fc 16380+
4a4d8108
AM
16381+config AUFS_INO_T_64
16382+ bool
16383+ depends on AUFS_EXPORT
16384+ depends on 64BIT && !(ALPHA || S390)
16385+ default y
16386+ help
16387+ Automatic configuration for internal use.
16388+ /* typedef unsigned long/int __kernel_ino_t */
16389+ /* alpha and s390x are int */
1facf9fc 16390+
4a4d8108
AM
16391+config AUFS_RDU
16392+ bool "Readdir in userspace"
16393+ help
16394+ Aufs has two methods to provide a merged view for a directory,
16395+ by a user-space library and by kernel-space natively. The latter
16396+ is always enabled but sometimes large and slow.
16397+ If you enable this option, install the library in aufs2-util
16398+ package, and set some environment variables for your readdir(3),
16399+ then the work will be handled in user-space which generally
16400+ shows better performance in most cases.
16401+ See detail in aufs.5.
1facf9fc 16402+
4a4d8108
AM
16403+config AUFS_SP_IATTR
16404+ bool "Respect the attributes (mtime/ctime mainly) of special files"
16405+ help
16406+ When you write something to a special file, some attributes of it
16407+ (mtime/ctime mainly) may be updated. Generally such updates are
16408+ less important (actually some device drivers and NFS ignore
16409+ it). But some applications (such like test program) requires
16410+ such updates. If you need these updates, then enable this
16411+ configuration which introduces some overhead.
16412+ Currently this configuration handles FIFO only.
1facf9fc 16413+
4a4d8108
AM
16414+config AUFS_SHWH
16415+ bool "Show whiteouts"
16416+ help
16417+ If you want to make the whiteouts in aufs visible, then enable
16418+ this option and specify 'shwh' mount option. Although it may
16419+ sounds like philosophy or something, but in technically it
16420+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 16421+
4a4d8108
AM
16422+config AUFS_BR_RAMFS
16423+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
16424+ help
16425+ If you want to use ramfs as an aufs branch fs, then enable this
16426+ option. Generally tmpfs is recommended.
16427+ Aufs prohibited them to be a branch fs by default, because
16428+ initramfs becomes unusable after switch_root or something
16429+ generally. If you sets initramfs as an aufs branch and boot your
16430+ system by switch_root, you will meet a problem easily since the
16431+ files in initramfs may be inaccessible.
16432+ Unless you are going to use ramfs as an aufs branch fs without
16433+ switch_root or something, leave it N.
1facf9fc 16434+
4a4d8108
AM
16435+config AUFS_BR_FUSE
16436+ bool "Fuse fs as an aufs branch"
16437+ depends on FUSE_FS
16438+ select AUFS_POLL
16439+ help
16440+ If you want to use fuse-based userspace filesystem as an aufs
16441+ branch fs, then enable this option.
16442+ It implements the internal poll(2) operation which is
16443+ implemented by fuse only (curretnly).
1facf9fc 16444+
4a4d8108
AM
16445+config AUFS_POLL
16446+ bool
16447+ help
16448+ Automatic configuration for internal use.
1facf9fc 16449+
4a4d8108
AM
16450+config AUFS_BR_HFSPLUS
16451+ bool "Hfsplus as an aufs branch"
16452+ depends on HFSPLUS_FS
16453+ default y
16454+ help
16455+ If you want to use hfsplus fs as an aufs branch fs, then enable
16456+ this option. This option introduces a small overhead at
16457+ copying-up a file on hfsplus.
1facf9fc 16458+
4a4d8108
AM
16459+config AUFS_BDEV_LOOP
16460+ bool
16461+ depends on BLK_DEV_LOOP
16462+ default y
16463+ help
16464+ Automatic configuration for internal use.
16465+ Convert =[ym] into =y.
1308ab2a 16466+
4a4d8108
AM
16467+config AUFS_DEBUG
16468+ bool "Debug aufs"
16469+ help
16470+ Enable this to compile aufs internal debug code.
16471+ It will have a negative impact to the performance.
16472+
16473+config AUFS_MAGIC_SYSRQ
16474+ bool
16475+ depends on AUFS_DEBUG && MAGIC_SYSRQ
16476+ default y
16477+ help
16478+ Automatic configuration for internal use.
16479+ When aufs supports Magic SysRq, enabled automatically.
16480+endif
e49829fe
JR
16481--- /dev/null
16482+++ linux-2.6/fs/aufs/loop.c 2010-10-24 11:19:23.000000000 +0200
b752ccd1 16483@@ -0,0 +1,63 @@
1facf9fc 16484+/*
4a4d8108 16485+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16486+ *
16487+ * This program, aufs is free software; you can redistribute it and/or modify
16488+ * it under the terms of the GNU General Public License as published by
16489+ * the Free Software Foundation; either version 2 of the License, or
16490+ * (at your option) any later version.
dece6358
AM
16491+ *
16492+ * This program is distributed in the hope that it will be useful,
16493+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16494+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16495+ * GNU General Public License for more details.
16496+ *
16497+ * You should have received a copy of the GNU General Public License
16498+ * along with this program; if not, write to the Free Software
16499+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16500+ */
16501+
16502+/*
16503+ * support for loopback block device as a branch
16504+ */
16505+
16506+#include <linux/loop.h>
16507+#include "aufs.h"
16508+
16509+/*
16510+ * test if two lower dentries have overlapping branches.
16511+ */
b752ccd1 16512+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 16513+{
b752ccd1 16514+ struct super_block *h_sb;
1facf9fc 16515+ struct loop_device *l;
16516+
b752ccd1
AM
16517+ h_sb = h_adding->d_sb;
16518+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 16519+ return 0;
16520+
b752ccd1
AM
16521+ l = h_sb->s_bdev->bd_disk->private_data;
16522+ h_adding = l->lo_backing_file->f_dentry;
16523+ /*
16524+ * h_adding can be local NFS.
16525+ * in this case aufs cannot detect the loop.
16526+ */
16527+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 16528+ return 1;
b752ccd1 16529+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 16530+}
16531+
16532+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
16533+int au_test_loopback_kthread(void)
16534+{
b752ccd1
AM
16535+ int ret;
16536+ struct task_struct *tsk = current;
16537+
16538+ ret = 0;
16539+ if (tsk->flags & PF_KTHREAD) {
16540+ const char c = tsk->comm[4];
16541+ ret = ('0' <= c && c <= '9'
16542+ && !strncmp(tsk->comm, "loop", 4));
16543+ }
1facf9fc 16544+
b752ccd1 16545+ return ret;
1facf9fc 16546+}
e49829fe
JR
16547--- /dev/null
16548+++ linux-2.6/fs/aufs/loop.h 2010-10-24 11:19:23.000000000 +0200
b752ccd1 16549@@ -0,0 +1,42 @@
1facf9fc 16550+/*
4a4d8108 16551+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16552+ *
16553+ * This program, aufs is free software; you can redistribute it and/or modify
16554+ * it under the terms of the GNU General Public License as published by
16555+ * the Free Software Foundation; either version 2 of the License, or
16556+ * (at your option) any later version.
dece6358
AM
16557+ *
16558+ * This program is distributed in the hope that it will be useful,
16559+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16560+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16561+ * GNU General Public License for more details.
16562+ *
16563+ * You should have received a copy of the GNU General Public License
16564+ * along with this program; if not, write to the Free Software
16565+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16566+ */
16567+
16568+/*
16569+ * support for loopback mount as a branch
16570+ */
16571+
16572+#ifndef __AUFS_LOOP_H__
16573+#define __AUFS_LOOP_H__
16574+
16575+#ifdef __KERNEL__
16576+
dece6358
AM
16577+struct dentry;
16578+struct super_block;
1facf9fc 16579+
16580+#ifdef CONFIG_AUFS_BDEV_LOOP
16581+/* loop.c */
b752ccd1 16582+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 16583+int au_test_loopback_kthread(void);
16584+#else
4a4d8108 16585+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 16586+ struct dentry *h_adding)
4a4d8108 16587+AuStubInt0(au_test_loopback_kthread, void)
1facf9fc 16588+#endif /* BLK_DEV_LOOP */
16589+
16590+#endif /* __KERNEL__ */
16591+#endif /* __AUFS_LOOP_H__ */
e49829fe
JR
16592--- /dev/null
16593+++ linux-2.6/fs/aufs/magic.mk 2010-10-24 11:19:23.000000000 +0200
4a4d8108 16594@@ -0,0 +1,54 @@
1facf9fc 16595+
16596+# defined in ${srctree}/fs/fuse/inode.c
16597+# tristate
16598+ifdef CONFIG_FUSE_FS
16599+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
16600+endif
16601+
16602+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
16603+# tristate
16604+ifdef CONFIG_OCFS2_FS
16605+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
16606+endif
16607+
16608+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
16609+# tristate
16610+ifdef CONFIG_OCFS2_FS_O2CB
16611+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
16612+endif
16613+
1facf9fc 16614+# defined in ${srctree}/fs/cifs/cifsfs.c
16615+# tristate
16616+ifdef CONFIG_CIFS_FS
16617+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
16618+endif
16619+
16620+# defined in ${srctree}/fs/xfs/xfs_sb.h
16621+# tristate
16622+ifdef CONFIG_XFS_FS
16623+ccflags-y += -DXFS_SB_MAGIC=0x58465342
16624+endif
16625+
16626+# defined in ${srctree}/fs/configfs/mount.c
16627+# tristate
16628+ifdef CONFIG_CONFIGFS_FS
16629+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
16630+endif
16631+
16632+# defined in ${srctree}/fs/9p/v9fs.h
16633+# tristate
16634+ifdef CONFIG_9P_FS
16635+ccflags-y += -DV9FS_MAGIC=0x01021997
16636+endif
16637+
16638+# defined in ${srctree}/fs/ubifs/ubifs.h
16639+# tristate
16640+ifdef CONFIG_UBIFS_FS
16641+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
16642+endif
4a4d8108
AM
16643+
16644+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
16645+# tristate
16646+ifdef CONFIG_HFSPLUS_FS
16647+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
16648+endif
e49829fe
JR
16649--- /dev/null
16650+++ linux-2.6/fs/aufs/Makefile 2010-10-24 11:40:16.000000000 +0200
16651@@ -0,0 +1,39 @@
4a4d8108
AM
16652+
16653+include ${src}/magic.mk
16654+ifeq (${CONFIG_AUFS_FS},m)
16655+include ${src}/conf.mk
16656+endif
16657+-include ${src}/priv_def.mk
16658+
16659+# cf. include/linux/kernel.h
16660+# enable pr_debug
16661+ccflags-y += -DDEBUG
16662+ccflags-y += -D'pr_fmt(fmt)="aufs %s:%d:%s[%d]: " fmt, \
16663+ __func__, __LINE__, current->comm, current->pid'
16664+
16665+obj-$(CONFIG_AUFS_FS) += aufs.o
16666+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
16667+ wkq.o vfsub.o dcsub.o \
e49829fe 16668+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
16669+ dinfo.o dentry.o \
16670+ dynop.o \
16671+ finfo.o file.o f_op.o \
16672+ dir.o vdir.o \
16673+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
16674+ ioctl.o
16675+
16676+# all are boolean
e49829fe 16677+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
16678+aufs-$(CONFIG_SYSFS) += sysfs.o
16679+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
16680+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
16681+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
16682+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
e49829fe 16683+aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
4a4d8108
AM
16684+aufs-$(CONFIG_AUFS_EXPORT) += export.o
16685+aufs-$(CONFIG_AUFS_POLL) += poll.o
16686+aufs-$(CONFIG_AUFS_RDU) += rdu.o
16687+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
16688+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
16689+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
16690+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
e49829fe
JR
16691--- /dev/null
16692+++ linux-2.6/fs/aufs/module.c 2010-10-24 11:40:26.000000000 +0200
16693@@ -0,0 +1,182 @@
1facf9fc 16694+/*
4a4d8108 16695+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16696+ *
16697+ * This program, aufs is free software; you can redistribute it and/or modify
16698+ * it under the terms of the GNU General Public License as published by
16699+ * the Free Software Foundation; either version 2 of the License, or
16700+ * (at your option) any later version.
dece6358
AM
16701+ *
16702+ * This program is distributed in the hope that it will be useful,
16703+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16704+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16705+ * GNU General Public License for more details.
16706+ *
16707+ * You should have received a copy of the GNU General Public License
16708+ * along with this program; if not, write to the Free Software
16709+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16710+ */
16711+
16712+/*
16713+ * module global variables and operations
16714+ */
16715+
16716+#include <linux/module.h>
16717+#include <linux/seq_file.h>
16718+#include "aufs.h"
16719+
16720+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
16721+{
16722+ if (new_sz <= nused)
16723+ return p;
16724+
16725+ p = krealloc(p, new_sz, gfp);
16726+ if (p)
16727+ memset(p + nused, 0, new_sz - nused);
16728+ return p;
16729+}
16730+
16731+/* ---------------------------------------------------------------------- */
16732+
16733+/*
16734+ * aufs caches
16735+ */
16736+struct kmem_cache *au_cachep[AuCache_Last];
16737+static int __init au_cache_init(void)
16738+{
4a4d8108 16739+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 16740+ if (au_cachep[AuCache_DINFO])
4a4d8108
AM
16741+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
16742+ au_icntnr_init_once);
1facf9fc 16743+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
16744+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
16745+ au_fi_init_once);
1facf9fc 16746+ if (au_cachep[AuCache_FINFO])
16747+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
16748+ if (au_cachep[AuCache_VDIR])
16749+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
16750+ if (au_cachep[AuCache_DEHSTR])
16751+ return 0;
16752+
16753+ return -ENOMEM;
16754+}
16755+
16756+static void au_cache_fin(void)
16757+{
16758+ int i;
4a4d8108
AM
16759+
16760+ /* including AuCache_HNOTIFY */
1facf9fc 16761+ for (i = 0; i < AuCache_Last; i++)
16762+ if (au_cachep[i]) {
16763+ kmem_cache_destroy(au_cachep[i]);
16764+ au_cachep[i] = NULL;
16765+ }
16766+}
16767+
16768+/* ---------------------------------------------------------------------- */
16769+
16770+int au_dir_roflags;
16771+
e49829fe
JR
16772+#ifdef CONFIG_AUFS_SBILIST
16773+struct au_splhead au_sbilist;
16774+#endif
16775+
1facf9fc 16776+/*
16777+ * functions for module interface.
16778+ */
16779+MODULE_LICENSE("GPL");
16780+/* MODULE_LICENSE("GPL v2"); */
dece6358 16781+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 16782+MODULE_DESCRIPTION(AUFS_NAME
16783+ " -- Advanced multi layered unification filesystem");
16784+MODULE_VERSION(AUFS_VERSION);
16785+
1facf9fc 16786+/* this module parameter has no meaning when SYSFS is disabled */
16787+int sysaufs_brs = 1;
16788+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
16789+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
16790+
16791+/* ---------------------------------------------------------------------- */
16792+
16793+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
16794+
16795+int au_seq_path(struct seq_file *seq, struct path *path)
16796+{
16797+ return seq_path(seq, path, au_esc_chars);
16798+}
16799+
16800+/* ---------------------------------------------------------------------- */
16801+
16802+static int __init aufs_init(void)
16803+{
16804+ int err, i;
16805+ char *p;
16806+
16807+ p = au_esc_chars;
16808+ for (i = 1; i <= ' '; i++)
16809+ *p++ = i;
16810+ *p++ = '\\';
16811+ *p++ = '\x7f';
16812+ *p = 0;
16813+
16814+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
16815+
e49829fe 16816+ au_sbilist_init();
1facf9fc 16817+ sysaufs_brs_init();
16818+ au_debug_init();
4a4d8108 16819+ au_dy_init();
1facf9fc 16820+ err = sysaufs_init();
16821+ if (unlikely(err))
16822+ goto out;
e49829fe 16823+ err = au_procfs_init();
4f0767ce 16824+ if (unlikely(err))
953406b4 16825+ goto out_sysaufs;
e49829fe
JR
16826+ err = au_wkq_init();
16827+ if (unlikely(err))
16828+ goto out_procfs;
4a4d8108 16829+ err = au_hnotify_init();
1facf9fc 16830+ if (unlikely(err))
16831+ goto out_wkq;
16832+ err = au_sysrq_init();
16833+ if (unlikely(err))
16834+ goto out_hin;
16835+ err = au_cache_init();
16836+ if (unlikely(err))
16837+ goto out_sysrq;
16838+ err = register_filesystem(&aufs_fs_type);
16839+ if (unlikely(err))
16840+ goto out_cache;
4a4d8108
AM
16841+ /* since we define pr_fmt, call printk directly */
16842+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 16843+ goto out; /* success */
16844+
4f0767ce 16845+out_cache:
1facf9fc 16846+ au_cache_fin();
4f0767ce 16847+out_sysrq:
1facf9fc 16848+ au_sysrq_fin();
4f0767ce 16849+out_hin:
4a4d8108 16850+ au_hnotify_fin();
4f0767ce 16851+out_wkq:
1facf9fc 16852+ au_wkq_fin();
e49829fe
JR
16853+out_procfs:
16854+ au_procfs_fin();
4f0767ce 16855+out_sysaufs:
1facf9fc 16856+ sysaufs_fin();
4a4d8108 16857+ au_dy_fin();
4f0767ce 16858+out:
1facf9fc 16859+ return err;
16860+}
16861+
16862+static void __exit aufs_exit(void)
16863+{
16864+ unregister_filesystem(&aufs_fs_type);
16865+ au_cache_fin();
16866+ au_sysrq_fin();
4a4d8108 16867+ au_hnotify_fin();
1facf9fc 16868+ au_wkq_fin();
e49829fe 16869+ au_procfs_fin();
1facf9fc 16870+ sysaufs_fin();
4a4d8108 16871+ au_dy_fin();
1facf9fc 16872+}
16873+
16874+module_init(aufs_init);
16875+module_exit(aufs_exit);
e49829fe
JR
16876--- /dev/null
16877+++ linux-2.6/fs/aufs/module.h 2010-10-24 11:40:35.000000000 +0200
16878@@ -0,0 +1,91 @@
1facf9fc 16879+/*
4a4d8108 16880+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16881+ *
16882+ * This program, aufs is free software; you can redistribute it and/or modify
16883+ * it under the terms of the GNU General Public License as published by
16884+ * the Free Software Foundation; either version 2 of the License, or
16885+ * (at your option) any later version.
dece6358
AM
16886+ *
16887+ * This program is distributed in the hope that it will be useful,
16888+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16889+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16890+ * GNU General Public License for more details.
16891+ *
16892+ * You should have received a copy of the GNU General Public License
16893+ * along with this program; if not, write to the Free Software
16894+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16895+ */
16896+
16897+/*
16898+ * module initialization and module-global
16899+ */
16900+
16901+#ifndef __AUFS_MODULE_H__
16902+#define __AUFS_MODULE_H__
16903+
16904+#ifdef __KERNEL__
16905+
16906+#include <linux/slab.h>
16907+
dece6358
AM
16908+struct path;
16909+struct seq_file;
16910+
1facf9fc 16911+/* module parameters */
1facf9fc 16912+extern int sysaufs_brs;
16913+
16914+/* ---------------------------------------------------------------------- */
16915+
16916+extern int au_dir_roflags;
16917+
16918+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
16919+int au_seq_path(struct seq_file *seq, struct path *path);
16920+
e49829fe
JR
16921+#ifdef CONFIG_PROC_FS
16922+/* procfs.c */
16923+int __init au_procfs_init(void);
16924+void au_procfs_fin(void);
16925+#else
16926+AuStubInt0(au_procfs_init, void);
16927+AuStubVoid(au_procfs_fin, void);
16928+#endif
16929+
4f0767ce
JR
16930+/* ---------------------------------------------------------------------- */
16931+
16932+/* kmem cache */
1facf9fc 16933+enum {
16934+ AuCache_DINFO,
16935+ AuCache_ICNTNR,
16936+ AuCache_FINFO,
16937+ AuCache_VDIR,
16938+ AuCache_DEHSTR,
4a4d8108
AM
16939+#ifdef CONFIG_AUFS_HNOTIFY
16940+ AuCache_HNOTIFY,
1facf9fc 16941+#endif
16942+ AuCache_Last
16943+};
16944+
4a4d8108
AM
16945+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
16946+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
16947+#define AuCacheCtor(type, ctor) \
16948+ kmem_cache_create(#type, sizeof(struct type), \
16949+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 16950+
16951+extern struct kmem_cache *au_cachep[];
16952+
16953+#define AuCacheFuncs(name, index) \
4a4d8108 16954+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 16955+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 16956+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 16957+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
16958+
16959+AuCacheFuncs(dinfo, DINFO);
16960+AuCacheFuncs(icntnr, ICNTNR);
16961+AuCacheFuncs(finfo, FINFO);
16962+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
16963+AuCacheFuncs(vdir_dehstr, DEHSTR);
16964+#ifdef CONFIG_AUFS_HNOTIFY
16965+AuCacheFuncs(hnotify, HNOTIFY);
16966+#endif
1facf9fc 16967+
4a4d8108
AM
16968+#endif /* __KERNEL__ */
16969+#endif /* __AUFS_MODULE_H__ */
e49829fe
JR
16970--- /dev/null
16971+++ linux-2.6/fs/aufs/mtx.h 2010-10-24 11:19:23.000000000 +0200
4a4d8108
AM
16972@@ -0,0 +1,48 @@
16973+/*
16974+ * Copyright (C) 2010 Junjiro R. Okajima
16975+ *
16976+ * This program, aufs is free software; you can redistribute it and/or modify
16977+ * it under the terms of the GNU General Public License as published by
16978+ * the Free Software Foundation; either version 2 of the License, or
16979+ * (at your option) any later version.
16980+ *
16981+ * This program is distributed in the hope that it will be useful,
16982+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16983+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16984+ * GNU General Public License for more details.
16985+ *
16986+ * You should have received a copy of the GNU General Public License
16987+ * along with this program; if not, write to the Free Software
16988+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16989+ */
16990+
16991+/*
16992+ * very ugly approach for aufs_mmap()
16993+ * never include this file from other than f_op.c.
16994+ * see f_op.c in detail.
16995+ */
16996+
16997+#ifndef __AUFS_MTX_H__
16998+#define __AUFS_MTX_H__
16999+
17000+#ifdef __KERNEL__
17001+
17002+/* copied from ../kernel/mutex{,-debug}.h */
17003+struct mutex;
17004+struct thread_info;
17005+#ifdef CONFIG_DEBUG_MUTEXES
17006+static inline void mutex_set_owner(struct mutex *lock)
17007+{
17008+ lock->owner = current_thread_info();
17009+}
17010+#else
17011+static inline void mutex_set_owner(struct mutex *lock)
17012+{
17013+#ifdef CONFIG_SMP
17014+ lock->owner = current_thread_info();
17015+#endif
17016+}
17017+#endif
1facf9fc 17018+
17019+#endif /* __KERNEL__ */
4a4d8108 17020+#endif /* __AUFS_MTX_H__ */
e49829fe
JR
17021--- /dev/null
17022+++ linux-2.6/fs/aufs/opts.c 2010-10-24 11:40:51.000000000 +0200
17023@@ -0,0 +1,1595 @@
1facf9fc 17024+/*
4a4d8108 17025+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 17026+ *
17027+ * This program, aufs is free software; you can redistribute it and/or modify
17028+ * it under the terms of the GNU General Public License as published by
17029+ * the Free Software Foundation; either version 2 of the License, or
17030+ * (at your option) any later version.
dece6358
AM
17031+ *
17032+ * This program is distributed in the hope that it will be useful,
17033+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17034+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17035+ * GNU General Public License for more details.
17036+ *
17037+ * You should have received a copy of the GNU General Public License
17038+ * along with this program; if not, write to the Free Software
17039+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17040+ */
17041+
17042+/*
17043+ * mount options/flags
17044+ */
17045+
dece6358 17046+#include <linux/file.h>
e49829fe 17047+#include <linux/jiffies.h>
dece6358 17048+#include <linux/namei.h>
1facf9fc 17049+#include <linux/types.h> /* a distribution requires */
17050+#include <linux/parser.h>
17051+#include "aufs.h"
17052+
17053+/* ---------------------------------------------------------------------- */
17054+
17055+enum {
17056+ Opt_br,
17057+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
17058+ Opt_idel, Opt_imod, Opt_ireorder,
17059+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 17060+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 17061+ Opt_xino, Opt_zxino, Opt_noxino,
17062+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
17063+ Opt_trunc_xino_path, Opt_itrunc_xino,
17064+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 17065+ Opt_shwh, Opt_noshwh,
1facf9fc 17066+ Opt_plink, Opt_noplink, Opt_list_plink,
17067+ Opt_udba,
4a4d8108 17068+ Opt_dio, Opt_nodio,
1facf9fc 17069+ /* Opt_lock, Opt_unlock, */
17070+ Opt_cmd, Opt_cmd_args,
17071+ Opt_diropq_a, Opt_diropq_w,
17072+ Opt_warn_perm, Opt_nowarn_perm,
17073+ Opt_wbr_copyup, Opt_wbr_create,
17074+ Opt_refrof, Opt_norefrof,
17075+ Opt_verbose, Opt_noverbose,
17076+ Opt_sum, Opt_nosum, Opt_wsum,
17077+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
17078+};
17079+
17080+static match_table_t options = {
17081+ {Opt_br, "br=%s"},
17082+ {Opt_br, "br:%s"},
17083+
17084+ {Opt_add, "add=%d:%s"},
17085+ {Opt_add, "add:%d:%s"},
17086+ {Opt_add, "ins=%d:%s"},
17087+ {Opt_add, "ins:%d:%s"},
17088+ {Opt_append, "append=%s"},
17089+ {Opt_append, "append:%s"},
17090+ {Opt_prepend, "prepend=%s"},
17091+ {Opt_prepend, "prepend:%s"},
17092+
17093+ {Opt_del, "del=%s"},
17094+ {Opt_del, "del:%s"},
17095+ /* {Opt_idel, "idel:%d"}, */
17096+ {Opt_mod, "mod=%s"},
17097+ {Opt_mod, "mod:%s"},
17098+ /* {Opt_imod, "imod:%d:%s"}, */
17099+
17100+ {Opt_dirwh, "dirwh=%d"},
17101+
17102+ {Opt_xino, "xino=%s"},
17103+ {Opt_noxino, "noxino"},
17104+ {Opt_trunc_xino, "trunc_xino"},
17105+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
17106+ {Opt_notrunc_xino, "notrunc_xino"},
17107+ {Opt_trunc_xino_path, "trunc_xino=%s"},
17108+ {Opt_itrunc_xino, "itrunc_xino=%d"},
17109+ /* {Opt_zxino, "zxino=%s"}, */
17110+ {Opt_trunc_xib, "trunc_xib"},
17111+ {Opt_notrunc_xib, "notrunc_xib"},
17112+
e49829fe 17113+#ifdef CONFIG_PROC_FS
1facf9fc 17114+ {Opt_plink, "plink"},
e49829fe
JR
17115+#else
17116+ {Opt_ignore_silent, "plink"},
17117+#endif
17118+
1facf9fc 17119+ {Opt_noplink, "noplink"},
e49829fe 17120+
1facf9fc 17121+#ifdef CONFIG_AUFS_DEBUG
17122+ {Opt_list_plink, "list_plink"},
17123+#endif
17124+
17125+ {Opt_udba, "udba=%s"},
17126+
4a4d8108
AM
17127+ {Opt_dio, "dio"},
17128+ {Opt_nodio, "nodio"},
17129+
1facf9fc 17130+ {Opt_diropq_a, "diropq=always"},
17131+ {Opt_diropq_a, "diropq=a"},
17132+ {Opt_diropq_w, "diropq=whiteouted"},
17133+ {Opt_diropq_w, "diropq=w"},
17134+
17135+ {Opt_warn_perm, "warn_perm"},
17136+ {Opt_nowarn_perm, "nowarn_perm"},
17137+
17138+ /* keep them temporary */
17139+ {Opt_ignore_silent, "coo=%s"},
17140+ {Opt_ignore_silent, "nodlgt"},
17141+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 17142+ {Opt_ignore_silent, "clean_plink"},
17143+
dece6358
AM
17144+#ifdef CONFIG_AUFS_SHWH
17145+ {Opt_shwh, "shwh"},
17146+#endif
17147+ {Opt_noshwh, "noshwh"},
17148+
1facf9fc 17149+ {Opt_rendir, "rendir=%d"},
17150+
17151+ {Opt_refrof, "refrof"},
17152+ {Opt_norefrof, "norefrof"},
17153+
17154+ {Opt_verbose, "verbose"},
17155+ {Opt_verbose, "v"},
17156+ {Opt_noverbose, "noverbose"},
17157+ {Opt_noverbose, "quiet"},
17158+ {Opt_noverbose, "q"},
17159+ {Opt_noverbose, "silent"},
17160+
17161+ {Opt_sum, "sum"},
17162+ {Opt_nosum, "nosum"},
17163+ {Opt_wsum, "wsum"},
17164+
17165+ {Opt_rdcache, "rdcache=%d"},
17166+ {Opt_rdblk, "rdblk=%d"},
dece6358 17167+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 17168+ {Opt_rdhash, "rdhash=%d"},
dece6358 17169+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 17170+
17171+ {Opt_wbr_create, "create=%s"},
17172+ {Opt_wbr_create, "create_policy=%s"},
17173+ {Opt_wbr_copyup, "cpup=%s"},
17174+ {Opt_wbr_copyup, "copyup=%s"},
17175+ {Opt_wbr_copyup, "copyup_policy=%s"},
17176+
17177+ /* internal use for the scripts */
17178+ {Opt_ignore_silent, "si=%s"},
17179+
17180+ {Opt_br, "dirs=%s"},
17181+ {Opt_ignore, "debug=%d"},
17182+ {Opt_ignore, "delete=whiteout"},
17183+ {Opt_ignore, "delete=all"},
17184+ {Opt_ignore, "imap=%s"},
17185+
1308ab2a 17186+ /* temporary workaround, due to old mount(8)? */
17187+ {Opt_ignore_silent, "relatime"},
17188+
1facf9fc 17189+ {Opt_err, NULL}
17190+};
17191+
17192+/* ---------------------------------------------------------------------- */
17193+
17194+static const char *au_parser_pattern(int val, struct match_token *token)
17195+{
17196+ while (token->pattern) {
17197+ if (token->token == val)
17198+ return token->pattern;
17199+ token++;
17200+ }
17201+ BUG();
17202+ return "??";
17203+}
17204+
17205+/* ---------------------------------------------------------------------- */
17206+
17207+static match_table_t brperms = {
17208+ {AuBrPerm_RO, AUFS_BRPERM_RO},
17209+ {AuBrPerm_RR, AUFS_BRPERM_RR},
17210+ {AuBrPerm_RW, AUFS_BRPERM_RW},
17211+
17212+ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
17213+ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
17214+ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
17215+
17216+ {AuBrPerm_ROWH, "nfsro"},
17217+ {AuBrPerm_RO, NULL}
17218+};
17219+
4a4d8108 17220+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 17221+{
17222+ int val;
17223+ substring_t args[MAX_OPT_ARGS];
17224+
17225+ val = match_token(perm, brperms, args);
17226+ return val;
17227+}
17228+
17229+const char *au_optstr_br_perm(int brperm)
17230+{
17231+ return au_parser_pattern(brperm, (void *)brperms);
17232+}
17233+
17234+/* ---------------------------------------------------------------------- */
17235+
17236+static match_table_t udbalevel = {
17237+ {AuOpt_UDBA_REVAL, "reval"},
17238+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
17239+#ifdef CONFIG_AUFS_HNOTIFY
17240+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
17241+#ifdef CONFIG_AUFS_HFSNOTIFY
17242+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
e49829fe
JR
17243+#else
17244+ {AuOpt_UDBA_HNOTIFY, "inotify"},
4a4d8108 17245+#endif
1facf9fc 17246+#endif
17247+ {-1, NULL}
17248+};
17249+
e49829fe
JR
17250+static void au_warn_inotify(int val, char *str)
17251+{
17252+#ifdef CONFIG_AUFS_HINOTIFY
17253+ if (val == AuOpt_UDBA_HNOTIFY
17254+ && !strcmp(str, "inotify"))
17255+ AuWarn1("udba=inotify is deprecated, use udba=notify\n");
17256+#endif
17257+}
17258+
4a4d8108 17259+static int noinline_for_stack udba_val(char *str)
1facf9fc 17260+{
e49829fe 17261+ int val;
1facf9fc 17262+ substring_t args[MAX_OPT_ARGS];
17263+
e49829fe
JR
17264+ val = match_token(str, udbalevel, args);
17265+ au_warn_inotify(val, str);
17266+ return val;
1facf9fc 17267+}
17268+
17269+const char *au_optstr_udba(int udba)
17270+{
17271+ return au_parser_pattern(udba, (void *)udbalevel);
17272+}
17273+
17274+/* ---------------------------------------------------------------------- */
17275+
17276+static match_table_t au_wbr_create_policy = {
17277+ {AuWbrCreate_TDP, "tdp"},
17278+ {AuWbrCreate_TDP, "top-down-parent"},
17279+ {AuWbrCreate_RR, "rr"},
17280+ {AuWbrCreate_RR, "round-robin"},
17281+ {AuWbrCreate_MFS, "mfs"},
17282+ {AuWbrCreate_MFS, "most-free-space"},
17283+ {AuWbrCreate_MFSV, "mfs:%d"},
17284+ {AuWbrCreate_MFSV, "most-free-space:%d"},
17285+
17286+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
17287+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
17288+ {AuWbrCreate_PMFS, "pmfs"},
17289+ {AuWbrCreate_PMFSV, "pmfs:%d"},
17290+
17291+ {-1, NULL}
17292+};
17293+
dece6358
AM
17294+/*
17295+ * cf. linux/lib/parser.c and cmdline.c
17296+ * gave up calling memparse() since it uses simple_strtoull() instead of
17297+ * strict_...().
17298+ */
4a4d8108
AM
17299+static int noinline_for_stack
17300+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 17301+{
17302+ int err;
17303+ unsigned int len;
17304+ char a[32];
17305+
17306+ err = -ERANGE;
17307+ len = s->to - s->from;
17308+ if (len + 1 <= sizeof(a)) {
17309+ memcpy(a, s->from, len);
17310+ a[len] = '\0';
17311+ err = strict_strtoull(a, 0, result);
17312+ }
17313+ return err;
17314+}
17315+
17316+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
17317+ struct au_opt_wbr_create *create)
17318+{
17319+ int err;
17320+ unsigned long long ull;
17321+
17322+ err = 0;
17323+ if (!au_match_ull(arg, &ull))
17324+ create->mfsrr_watermark = ull;
17325+ else {
4a4d8108 17326+ pr_err("bad integer in %s\n", str);
1facf9fc 17327+ err = -EINVAL;
17328+ }
17329+
17330+ return err;
17331+}
17332+
17333+static int au_wbr_mfs_sec(substring_t *arg, char *str,
17334+ struct au_opt_wbr_create *create)
17335+{
17336+ int n, err;
17337+
17338+ err = 0;
e49829fe 17339+ if (!match_int(arg, &n) && 0 <= n && n <= MAX_SEC_IN_JIFFIES)
1facf9fc 17340+ create->mfs_second = n;
17341+ else {
4a4d8108 17342+ pr_err("bad integer in %s\n", str);
1facf9fc 17343+ err = -EINVAL;
17344+ }
17345+
17346+ return err;
17347+}
17348+
4a4d8108
AM
17349+static int noinline_for_stack
17350+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 17351+{
17352+ int err, e;
17353+ substring_t args[MAX_OPT_ARGS];
17354+
17355+ err = match_token(str, au_wbr_create_policy, args);
17356+ create->wbr_create = err;
17357+ switch (err) {
17358+ case AuWbrCreate_MFSRRV:
17359+ e = au_wbr_mfs_wmark(&args[0], str, create);
17360+ if (!e)
17361+ e = au_wbr_mfs_sec(&args[1], str, create);
17362+ if (unlikely(e))
17363+ err = e;
17364+ break;
17365+ case AuWbrCreate_MFSRR:
17366+ e = au_wbr_mfs_wmark(&args[0], str, create);
17367+ if (unlikely(e)) {
17368+ err = e;
17369+ break;
17370+ }
17371+ /*FALLTHROUGH*/
17372+ case AuWbrCreate_MFS:
17373+ case AuWbrCreate_PMFS:
17374+ create->mfs_second = AUFS_MFS_SECOND_DEF;
17375+ break;
17376+ case AuWbrCreate_MFSV:
17377+ case AuWbrCreate_PMFSV:
17378+ e = au_wbr_mfs_sec(&args[0], str, create);
17379+ if (unlikely(e))
17380+ err = e;
17381+ break;
17382+ }
17383+
17384+ return err;
17385+}
17386+
17387+const char *au_optstr_wbr_create(int wbr_create)
17388+{
17389+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
17390+}
17391+
17392+static match_table_t au_wbr_copyup_policy = {
17393+ {AuWbrCopyup_TDP, "tdp"},
17394+ {AuWbrCopyup_TDP, "top-down-parent"},
17395+ {AuWbrCopyup_BUP, "bup"},
17396+ {AuWbrCopyup_BUP, "bottom-up-parent"},
17397+ {AuWbrCopyup_BU, "bu"},
17398+ {AuWbrCopyup_BU, "bottom-up"},
17399+ {-1, NULL}
17400+};
17401+
4a4d8108 17402+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 17403+{
17404+ substring_t args[MAX_OPT_ARGS];
17405+
17406+ return match_token(str, au_wbr_copyup_policy, args);
17407+}
17408+
17409+const char *au_optstr_wbr_copyup(int wbr_copyup)
17410+{
17411+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
17412+}
17413+
17414+/* ---------------------------------------------------------------------- */
17415+
17416+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
17417+
17418+static void dump_opts(struct au_opts *opts)
17419+{
17420+#ifdef CONFIG_AUFS_DEBUG
17421+ /* reduce stack space */
17422+ union {
17423+ struct au_opt_add *add;
17424+ struct au_opt_del *del;
17425+ struct au_opt_mod *mod;
17426+ struct au_opt_xino *xino;
17427+ struct au_opt_xino_itrunc *xino_itrunc;
17428+ struct au_opt_wbr_create *create;
17429+ } u;
17430+ struct au_opt *opt;
17431+
17432+ opt = opts->opt;
17433+ while (opt->type != Opt_tail) {
17434+ switch (opt->type) {
17435+ case Opt_add:
17436+ u.add = &opt->add;
17437+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
17438+ u.add->bindex, u.add->pathname, u.add->perm,
17439+ u.add->path.dentry);
17440+ break;
17441+ case Opt_del:
17442+ case Opt_idel:
17443+ u.del = &opt->del;
17444+ AuDbg("del {%s, %p}\n",
17445+ u.del->pathname, u.del->h_path.dentry);
17446+ break;
17447+ case Opt_mod:
17448+ case Opt_imod:
17449+ u.mod = &opt->mod;
17450+ AuDbg("mod {%s, 0x%x, %p}\n",
17451+ u.mod->path, u.mod->perm, u.mod->h_root);
17452+ break;
17453+ case Opt_append:
17454+ u.add = &opt->add;
17455+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
17456+ u.add->bindex, u.add->pathname, u.add->perm,
17457+ u.add->path.dentry);
17458+ break;
17459+ case Opt_prepend:
17460+ u.add = &opt->add;
17461+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
17462+ u.add->bindex, u.add->pathname, u.add->perm,
17463+ u.add->path.dentry);
17464+ break;
17465+ case Opt_dirwh:
17466+ AuDbg("dirwh %d\n", opt->dirwh);
17467+ break;
17468+ case Opt_rdcache:
17469+ AuDbg("rdcache %d\n", opt->rdcache);
17470+ break;
17471+ case Opt_rdblk:
17472+ AuDbg("rdblk %u\n", opt->rdblk);
17473+ break;
dece6358
AM
17474+ case Opt_rdblk_def:
17475+ AuDbg("rdblk_def\n");
17476+ break;
1facf9fc 17477+ case Opt_rdhash:
17478+ AuDbg("rdhash %u\n", opt->rdhash);
17479+ break;
dece6358
AM
17480+ case Opt_rdhash_def:
17481+ AuDbg("rdhash_def\n");
17482+ break;
1facf9fc 17483+ case Opt_xino:
17484+ u.xino = &opt->xino;
17485+ AuDbg("xino {%s %.*s}\n",
17486+ u.xino->path,
17487+ AuDLNPair(u.xino->file->f_dentry));
17488+ break;
17489+ case Opt_trunc_xino:
17490+ AuLabel(trunc_xino);
17491+ break;
17492+ case Opt_notrunc_xino:
17493+ AuLabel(notrunc_xino);
17494+ break;
17495+ case Opt_trunc_xino_path:
17496+ case Opt_itrunc_xino:
17497+ u.xino_itrunc = &opt->xino_itrunc;
17498+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
17499+ break;
17500+
17501+ case Opt_noxino:
17502+ AuLabel(noxino);
17503+ break;
17504+ case Opt_trunc_xib:
17505+ AuLabel(trunc_xib);
17506+ break;
17507+ case Opt_notrunc_xib:
17508+ AuLabel(notrunc_xib);
17509+ break;
dece6358
AM
17510+ case Opt_shwh:
17511+ AuLabel(shwh);
17512+ break;
17513+ case Opt_noshwh:
17514+ AuLabel(noshwh);
17515+ break;
1facf9fc 17516+ case Opt_plink:
17517+ AuLabel(plink);
17518+ break;
17519+ case Opt_noplink:
17520+ AuLabel(noplink);
17521+ break;
17522+ case Opt_list_plink:
17523+ AuLabel(list_plink);
17524+ break;
17525+ case Opt_udba:
17526+ AuDbg("udba %d, %s\n",
17527+ opt->udba, au_optstr_udba(opt->udba));
17528+ break;
4a4d8108
AM
17529+ case Opt_dio:
17530+ AuLabel(dio);
17531+ break;
17532+ case Opt_nodio:
17533+ AuLabel(nodio);
17534+ break;
1facf9fc 17535+ case Opt_diropq_a:
17536+ AuLabel(diropq_a);
17537+ break;
17538+ case Opt_diropq_w:
17539+ AuLabel(diropq_w);
17540+ break;
17541+ case Opt_warn_perm:
17542+ AuLabel(warn_perm);
17543+ break;
17544+ case Opt_nowarn_perm:
17545+ AuLabel(nowarn_perm);
17546+ break;
17547+ case Opt_refrof:
17548+ AuLabel(refrof);
17549+ break;
17550+ case Opt_norefrof:
17551+ AuLabel(norefrof);
17552+ break;
17553+ case Opt_verbose:
17554+ AuLabel(verbose);
17555+ break;
17556+ case Opt_noverbose:
17557+ AuLabel(noverbose);
17558+ break;
17559+ case Opt_sum:
17560+ AuLabel(sum);
17561+ break;
17562+ case Opt_nosum:
17563+ AuLabel(nosum);
17564+ break;
17565+ case Opt_wsum:
17566+ AuLabel(wsum);
17567+ break;
17568+ case Opt_wbr_create:
17569+ u.create = &opt->wbr_create;
17570+ AuDbg("create %d, %s\n", u.create->wbr_create,
17571+ au_optstr_wbr_create(u.create->wbr_create));
17572+ switch (u.create->wbr_create) {
17573+ case AuWbrCreate_MFSV:
17574+ case AuWbrCreate_PMFSV:
17575+ AuDbg("%d sec\n", u.create->mfs_second);
17576+ break;
17577+ case AuWbrCreate_MFSRR:
17578+ AuDbg("%llu watermark\n",
17579+ u.create->mfsrr_watermark);
17580+ break;
17581+ case AuWbrCreate_MFSRRV:
17582+ AuDbg("%llu watermark, %d sec\n",
17583+ u.create->mfsrr_watermark,
17584+ u.create->mfs_second);
17585+ break;
17586+ }
17587+ break;
17588+ case Opt_wbr_copyup:
17589+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
17590+ au_optstr_wbr_copyup(opt->wbr_copyup));
17591+ break;
17592+ default:
17593+ BUG();
17594+ }
17595+ opt++;
17596+ }
17597+#endif
17598+}
17599+
17600+void au_opts_free(struct au_opts *opts)
17601+{
17602+ struct au_opt *opt;
17603+
17604+ opt = opts->opt;
17605+ while (opt->type != Opt_tail) {
17606+ switch (opt->type) {
17607+ case Opt_add:
17608+ case Opt_append:
17609+ case Opt_prepend:
17610+ path_put(&opt->add.path);
17611+ break;
17612+ case Opt_del:
17613+ case Opt_idel:
17614+ path_put(&opt->del.h_path);
17615+ break;
17616+ case Opt_mod:
17617+ case Opt_imod:
17618+ dput(opt->mod.h_root);
17619+ break;
17620+ case Opt_xino:
17621+ fput(opt->xino.file);
17622+ break;
17623+ }
17624+ opt++;
17625+ }
17626+}
17627+
17628+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
17629+ aufs_bindex_t bindex)
17630+{
17631+ int err;
17632+ struct au_opt_add *add = &opt->add;
17633+ char *p;
17634+
17635+ add->bindex = bindex;
17636+ add->perm = AuBrPerm_Last;
17637+ add->pathname = opt_str;
17638+ p = strchr(opt_str, '=');
17639+ if (p) {
17640+ *p++ = 0;
17641+ if (*p)
17642+ add->perm = br_perm_val(p);
17643+ }
17644+
17645+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
17646+ if (!err) {
17647+ if (!p) {
17648+ add->perm = AuBrPerm_RO;
17649+ if (au_test_fs_rr(add->path.dentry->d_sb))
17650+ add->perm = AuBrPerm_RR;
17651+ else if (!bindex && !(sb_flags & MS_RDONLY))
17652+ add->perm = AuBrPerm_RW;
17653+ }
17654+ opt->type = Opt_add;
17655+ goto out;
17656+ }
4a4d8108 17657+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 17658+ err = -EINVAL;
17659+
4f0767ce 17660+out:
1facf9fc 17661+ return err;
17662+}
17663+
17664+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
17665+{
17666+ int err;
17667+
17668+ del->pathname = args[0].from;
17669+ AuDbg("del path %s\n", del->pathname);
17670+
17671+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
17672+ if (unlikely(err))
4a4d8108 17673+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 17674+
17675+ return err;
17676+}
17677+
17678+#if 0 /* reserved for future use */
17679+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
17680+ struct au_opt_del *del, substring_t args[])
17681+{
17682+ int err;
17683+ struct dentry *root;
17684+
17685+ err = -EINVAL;
17686+ root = sb->s_root;
17687+ aufs_read_lock(root, AuLock_FLUSH);
17688+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17689+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17690+ goto out;
17691+ }
17692+
17693+ err = 0;
17694+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
17695+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
17696+
4f0767ce 17697+out:
1facf9fc 17698+ aufs_read_unlock(root, !AuLock_IR);
17699+ return err;
17700+}
17701+#endif
17702+
4a4d8108
AM
17703+static int noinline_for_stack
17704+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 17705+{
17706+ int err;
17707+ struct path path;
17708+ char *p;
17709+
17710+ err = -EINVAL;
17711+ mod->path = args[0].from;
17712+ p = strchr(mod->path, '=');
17713+ if (unlikely(!p)) {
4a4d8108 17714+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 17715+ goto out;
17716+ }
17717+
17718+ *p++ = 0;
17719+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
17720+ if (unlikely(err)) {
4a4d8108 17721+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 17722+ goto out;
17723+ }
17724+
17725+ mod->perm = br_perm_val(p);
17726+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
17727+ mod->h_root = dget(path.dentry);
17728+ path_put(&path);
17729+
4f0767ce 17730+out:
1facf9fc 17731+ return err;
17732+}
17733+
17734+#if 0 /* reserved for future use */
17735+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
17736+ struct au_opt_mod *mod, substring_t args[])
17737+{
17738+ int err;
17739+ struct dentry *root;
17740+
17741+ err = -EINVAL;
17742+ root = sb->s_root;
17743+ aufs_read_lock(root, AuLock_FLUSH);
17744+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17745+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17746+ goto out;
17747+ }
17748+
17749+ err = 0;
17750+ mod->perm = br_perm_val(args[1].from);
17751+ AuDbg("mod path %s, perm 0x%x, %s\n",
17752+ mod->path, mod->perm, args[1].from);
17753+ mod->h_root = dget(au_h_dptr(root, bindex));
17754+
4f0767ce 17755+out:
1facf9fc 17756+ aufs_read_unlock(root, !AuLock_IR);
17757+ return err;
17758+}
17759+#endif
17760+
17761+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
17762+ substring_t args[])
17763+{
17764+ int err;
17765+ struct file *file;
17766+
17767+ file = au_xino_create(sb, args[0].from, /*silent*/0);
17768+ err = PTR_ERR(file);
17769+ if (IS_ERR(file))
17770+ goto out;
17771+
17772+ err = -EINVAL;
17773+ if (unlikely(file->f_dentry->d_sb == sb)) {
17774+ fput(file);
4a4d8108 17775+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 17776+ goto out;
17777+ }
17778+
17779+ err = 0;
17780+ xino->file = file;
17781+ xino->path = args[0].from;
17782+
4f0767ce 17783+out:
1facf9fc 17784+ return err;
17785+}
17786+
4a4d8108
AM
17787+static int noinline_for_stack
17788+au_opts_parse_xino_itrunc_path(struct super_block *sb,
17789+ struct au_opt_xino_itrunc *xino_itrunc,
17790+ substring_t args[])
1facf9fc 17791+{
17792+ int err;
17793+ aufs_bindex_t bend, bindex;
17794+ struct path path;
17795+ struct dentry *root;
17796+
17797+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
17798+ if (unlikely(err)) {
4a4d8108 17799+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 17800+ goto out;
17801+ }
17802+
17803+ xino_itrunc->bindex = -1;
17804+ root = sb->s_root;
17805+ aufs_read_lock(root, AuLock_FLUSH);
17806+ bend = au_sbend(sb);
17807+ for (bindex = 0; bindex <= bend; bindex++) {
17808+ if (au_h_dptr(root, bindex) == path.dentry) {
17809+ xino_itrunc->bindex = bindex;
17810+ break;
17811+ }
17812+ }
17813+ aufs_read_unlock(root, !AuLock_IR);
17814+ path_put(&path);
17815+
17816+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 17817+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 17818+ err = -EINVAL;
17819+ }
17820+
4f0767ce 17821+out:
1facf9fc 17822+ return err;
17823+}
17824+
17825+/* called without aufs lock */
17826+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
17827+{
17828+ int err, n, token;
17829+ aufs_bindex_t bindex;
17830+ unsigned char skipped;
17831+ struct dentry *root;
17832+ struct au_opt *opt, *opt_tail;
17833+ char *opt_str;
17834+ /* reduce the stack space */
17835+ union {
17836+ struct au_opt_xino_itrunc *xino_itrunc;
17837+ struct au_opt_wbr_create *create;
17838+ } u;
17839+ struct {
17840+ substring_t args[MAX_OPT_ARGS];
17841+ } *a;
17842+
17843+ err = -ENOMEM;
17844+ a = kmalloc(sizeof(*a), GFP_NOFS);
17845+ if (unlikely(!a))
17846+ goto out;
17847+
17848+ root = sb->s_root;
17849+ err = 0;
17850+ bindex = 0;
17851+ opt = opts->opt;
17852+ opt_tail = opt + opts->max_opt - 1;
17853+ opt->type = Opt_tail;
17854+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
17855+ err = -EINVAL;
17856+ skipped = 0;
17857+ token = match_token(opt_str, options, a->args);
17858+ switch (token) {
17859+ case Opt_br:
17860+ err = 0;
17861+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
17862+ && *opt_str) {
17863+ err = opt_add(opt, opt_str, opts->sb_flags,
17864+ bindex++);
17865+ if (unlikely(!err && ++opt > opt_tail)) {
17866+ err = -E2BIG;
17867+ break;
17868+ }
17869+ opt->type = Opt_tail;
17870+ skipped = 1;
17871+ }
17872+ break;
17873+ case Opt_add:
17874+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17875+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17876+ break;
17877+ }
17878+ bindex = n;
17879+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
17880+ bindex);
17881+ if (!err)
17882+ opt->type = token;
17883+ break;
17884+ case Opt_append:
17885+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17886+ /*dummy bindex*/1);
17887+ if (!err)
17888+ opt->type = token;
17889+ break;
17890+ case Opt_prepend:
17891+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17892+ /*bindex*/0);
17893+ if (!err)
17894+ opt->type = token;
17895+ break;
17896+ case Opt_del:
17897+ err = au_opts_parse_del(&opt->del, a->args);
17898+ if (!err)
17899+ opt->type = token;
17900+ break;
17901+#if 0 /* reserved for future use */
17902+ case Opt_idel:
17903+ del->pathname = "(indexed)";
17904+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 17905+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17906+ break;
17907+ }
17908+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
17909+ if (!err)
17910+ opt->type = token;
17911+ break;
17912+#endif
17913+ case Opt_mod:
17914+ err = au_opts_parse_mod(&opt->mod, a->args);
17915+ if (!err)
17916+ opt->type = token;
17917+ break;
17918+#ifdef IMOD /* reserved for future use */
17919+ case Opt_imod:
17920+ u.mod->path = "(indexed)";
17921+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17922+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17923+ break;
17924+ }
17925+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
17926+ if (!err)
17927+ opt->type = token;
17928+ break;
17929+#endif
17930+ case Opt_xino:
17931+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
17932+ if (!err)
17933+ opt->type = token;
17934+ break;
17935+
17936+ case Opt_trunc_xino_path:
17937+ err = au_opts_parse_xino_itrunc_path
17938+ (sb, &opt->xino_itrunc, a->args);
17939+ if (!err)
17940+ opt->type = token;
17941+ break;
17942+
17943+ case Opt_itrunc_xino:
17944+ u.xino_itrunc = &opt->xino_itrunc;
17945+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17946+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17947+ break;
17948+ }
17949+ u.xino_itrunc->bindex = n;
17950+ aufs_read_lock(root, AuLock_FLUSH);
17951+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 17952+ pr_err("out of bounds, %d\n", n);
1facf9fc 17953+ aufs_read_unlock(root, !AuLock_IR);
17954+ break;
17955+ }
17956+ aufs_read_unlock(root, !AuLock_IR);
17957+ err = 0;
17958+ opt->type = token;
17959+ break;
17960+
17961+ case Opt_dirwh:
17962+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
17963+ break;
17964+ err = 0;
17965+ opt->type = token;
17966+ break;
17967+
17968+ case Opt_rdcache:
e49829fe
JR
17969+ if (unlikely(match_int(&a->args[0], &opt->rdcache)
17970+ || opt->rdcache > MAX_SEC_IN_JIFFIES))
1facf9fc 17971+ break;
17972+ err = 0;
17973+ opt->type = token;
17974+ break;
17975+ case Opt_rdblk:
17976+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17977+ || n < 0
1facf9fc 17978+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 17979+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17980+ break;
17981+ }
1308ab2a 17982+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
17983+ pr_err("rdblk must be larger than %d\n",
17984+ NAME_MAX);
1facf9fc 17985+ break;
17986+ }
17987+ opt->rdblk = n;
17988+ err = 0;
17989+ opt->type = token;
17990+ break;
17991+ case Opt_rdhash:
17992+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17993+ || n < 0
1facf9fc 17994+ || n * sizeof(struct hlist_head)
17995+ > KMALLOC_MAX_SIZE)) {
4a4d8108 17996+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17997+ break;
17998+ }
17999+ opt->rdhash = n;
18000+ err = 0;
18001+ opt->type = token;
18002+ break;
18003+
18004+ case Opt_trunc_xino:
18005+ case Opt_notrunc_xino:
18006+ case Opt_noxino:
18007+ case Opt_trunc_xib:
18008+ case Opt_notrunc_xib:
dece6358
AM
18009+ case Opt_shwh:
18010+ case Opt_noshwh:
1facf9fc 18011+ case Opt_plink:
18012+ case Opt_noplink:
18013+ case Opt_list_plink:
4a4d8108
AM
18014+ case Opt_dio:
18015+ case Opt_nodio:
1facf9fc 18016+ case Opt_diropq_a:
18017+ case Opt_diropq_w:
18018+ case Opt_warn_perm:
18019+ case Opt_nowarn_perm:
18020+ case Opt_refrof:
18021+ case Opt_norefrof:
18022+ case Opt_verbose:
18023+ case Opt_noverbose:
18024+ case Opt_sum:
18025+ case Opt_nosum:
18026+ case Opt_wsum:
dece6358
AM
18027+ case Opt_rdblk_def:
18028+ case Opt_rdhash_def:
1facf9fc 18029+ err = 0;
18030+ opt->type = token;
18031+ break;
18032+
18033+ case Opt_udba:
18034+ opt->udba = udba_val(a->args[0].from);
18035+ if (opt->udba >= 0) {
18036+ err = 0;
18037+ opt->type = token;
18038+ } else
4a4d8108 18039+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18040+ break;
18041+
18042+ case Opt_wbr_create:
18043+ u.create = &opt->wbr_create;
18044+ u.create->wbr_create
18045+ = au_wbr_create_val(a->args[0].from, u.create);
18046+ if (u.create->wbr_create >= 0) {
18047+ err = 0;
18048+ opt->type = token;
18049+ } else
4a4d8108 18050+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18051+ break;
18052+ case Opt_wbr_copyup:
18053+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
18054+ if (opt->wbr_copyup >= 0) {
18055+ err = 0;
18056+ opt->type = token;
18057+ } else
4a4d8108 18058+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18059+ break;
18060+
18061+ case Opt_ignore:
4a4d8108 18062+ pr_warning("ignored %s\n", opt_str);
1facf9fc 18063+ /*FALLTHROUGH*/
18064+ case Opt_ignore_silent:
18065+ skipped = 1;
18066+ err = 0;
18067+ break;
18068+ case Opt_err:
4a4d8108 18069+ pr_err("unknown option %s\n", opt_str);
1facf9fc 18070+ break;
18071+ }
18072+
18073+ if (!err && !skipped) {
18074+ if (unlikely(++opt > opt_tail)) {
18075+ err = -E2BIG;
18076+ opt--;
18077+ opt->type = Opt_tail;
18078+ break;
18079+ }
18080+ opt->type = Opt_tail;
18081+ }
18082+ }
18083+
18084+ kfree(a);
18085+ dump_opts(opts);
18086+ if (unlikely(err))
18087+ au_opts_free(opts);
18088+
4f0767ce 18089+out:
1facf9fc 18090+ return err;
18091+}
18092+
18093+static int au_opt_wbr_create(struct super_block *sb,
18094+ struct au_opt_wbr_create *create)
18095+{
18096+ int err;
18097+ struct au_sbinfo *sbinfo;
18098+
dece6358
AM
18099+ SiMustWriteLock(sb);
18100+
1facf9fc 18101+ err = 1; /* handled */
18102+ sbinfo = au_sbi(sb);
18103+ if (sbinfo->si_wbr_create_ops->fin) {
18104+ err = sbinfo->si_wbr_create_ops->fin(sb);
18105+ if (!err)
18106+ err = 1;
18107+ }
18108+
18109+ sbinfo->si_wbr_create = create->wbr_create;
18110+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
18111+ switch (create->wbr_create) {
18112+ case AuWbrCreate_MFSRRV:
18113+ case AuWbrCreate_MFSRR:
18114+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
18115+ /*FALLTHROUGH*/
18116+ case AuWbrCreate_MFS:
18117+ case AuWbrCreate_MFSV:
18118+ case AuWbrCreate_PMFS:
18119+ case AuWbrCreate_PMFSV:
e49829fe
JR
18120+ sbinfo->si_wbr_mfs.mfs_expire
18121+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 18122+ break;
18123+ }
18124+
18125+ if (sbinfo->si_wbr_create_ops->init)
18126+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
18127+
18128+ return err;
18129+}
18130+
18131+/*
18132+ * returns,
18133+ * plus: processed without an error
18134+ * zero: unprocessed
18135+ */
18136+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
18137+ struct au_opts *opts)
18138+{
18139+ int err;
18140+ struct au_sbinfo *sbinfo;
18141+
dece6358
AM
18142+ SiMustWriteLock(sb);
18143+
1facf9fc 18144+ err = 1; /* handled */
18145+ sbinfo = au_sbi(sb);
18146+ switch (opt->type) {
18147+ case Opt_udba:
18148+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18149+ sbinfo->si_mntflags |= opt->udba;
18150+ opts->given_udba |= opt->udba;
18151+ break;
18152+
18153+ case Opt_plink:
18154+ au_opt_set(sbinfo->si_mntflags, PLINK);
18155+ break;
18156+ case Opt_noplink:
18157+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 18158+ au_plink_put(sb, /*verbose*/1);
1facf9fc 18159+ au_opt_clr(sbinfo->si_mntflags, PLINK);
18160+ break;
18161+ case Opt_list_plink:
18162+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
18163+ au_plink_list(sb);
18164+ break;
18165+
4a4d8108
AM
18166+ case Opt_dio:
18167+ au_opt_set(sbinfo->si_mntflags, DIO);
18168+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18169+ break;
18170+ case Opt_nodio:
18171+ au_opt_clr(sbinfo->si_mntflags, DIO);
18172+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18173+ break;
18174+
1facf9fc 18175+ case Opt_diropq_a:
18176+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18177+ break;
18178+ case Opt_diropq_w:
18179+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18180+ break;
18181+
18182+ case Opt_warn_perm:
18183+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
18184+ break;
18185+ case Opt_nowarn_perm:
18186+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
18187+ break;
18188+
18189+ case Opt_refrof:
18190+ au_opt_set(sbinfo->si_mntflags, REFROF);
18191+ break;
18192+ case Opt_norefrof:
18193+ au_opt_clr(sbinfo->si_mntflags, REFROF);
18194+ break;
18195+
18196+ case Opt_verbose:
18197+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
18198+ break;
18199+ case Opt_noverbose:
18200+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
18201+ break;
18202+
18203+ case Opt_sum:
18204+ au_opt_set(sbinfo->si_mntflags, SUM);
18205+ break;
18206+ case Opt_wsum:
18207+ au_opt_clr(sbinfo->si_mntflags, SUM);
18208+ au_opt_set(sbinfo->si_mntflags, SUM_W);
18209+ case Opt_nosum:
18210+ au_opt_clr(sbinfo->si_mntflags, SUM);
18211+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
18212+ break;
18213+
18214+ case Opt_wbr_create:
18215+ err = au_opt_wbr_create(sb, &opt->wbr_create);
18216+ break;
18217+ case Opt_wbr_copyup:
18218+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
18219+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
18220+ break;
18221+
18222+ case Opt_dirwh:
18223+ sbinfo->si_dirwh = opt->dirwh;
18224+ break;
18225+
18226+ case Opt_rdcache:
e49829fe
JR
18227+ sbinfo->si_rdcache
18228+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 18229+ break;
18230+ case Opt_rdblk:
18231+ sbinfo->si_rdblk = opt->rdblk;
18232+ break;
dece6358
AM
18233+ case Opt_rdblk_def:
18234+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
18235+ break;
1facf9fc 18236+ case Opt_rdhash:
18237+ sbinfo->si_rdhash = opt->rdhash;
18238+ break;
dece6358
AM
18239+ case Opt_rdhash_def:
18240+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
18241+ break;
18242+
18243+ case Opt_shwh:
18244+ au_opt_set(sbinfo->si_mntflags, SHWH);
18245+ break;
18246+ case Opt_noshwh:
18247+ au_opt_clr(sbinfo->si_mntflags, SHWH);
18248+ break;
1facf9fc 18249+
18250+ case Opt_trunc_xino:
18251+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
18252+ break;
18253+ case Opt_notrunc_xino:
18254+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
18255+ break;
18256+
18257+ case Opt_trunc_xino_path:
18258+ case Opt_itrunc_xino:
18259+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
18260+ if (!err)
18261+ err = 1;
18262+ break;
18263+
18264+ case Opt_trunc_xib:
18265+ au_fset_opts(opts->flags, TRUNC_XIB);
18266+ break;
18267+ case Opt_notrunc_xib:
18268+ au_fclr_opts(opts->flags, TRUNC_XIB);
18269+ break;
18270+
18271+ default:
18272+ err = 0;
18273+ break;
18274+ }
18275+
18276+ return err;
18277+}
18278+
18279+/*
18280+ * returns tri-state.
18281+ * plus: processed without an error
18282+ * zero: unprocessed
18283+ * minus: error
18284+ */
18285+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
18286+ struct au_opts *opts)
18287+{
18288+ int err, do_refresh;
18289+
18290+ err = 0;
18291+ switch (opt->type) {
18292+ case Opt_append:
18293+ opt->add.bindex = au_sbend(sb) + 1;
18294+ if (opt->add.bindex < 0)
18295+ opt->add.bindex = 0;
18296+ goto add;
18297+ case Opt_prepend:
18298+ opt->add.bindex = 0;
18299+ add:
18300+ case Opt_add:
18301+ err = au_br_add(sb, &opt->add,
18302+ au_ftest_opts(opts->flags, REMOUNT));
18303+ if (!err) {
18304+ err = 1;
18305+ au_fset_opts(opts->flags, REFRESH_DIR);
4a4d8108 18306+ au_fset_opts(opts->flags, REFRESH_NONDIR);
1facf9fc 18307+ }
18308+ break;
18309+
18310+ case Opt_del:
18311+ case Opt_idel:
18312+ err = au_br_del(sb, &opt->del,
18313+ au_ftest_opts(opts->flags, REMOUNT));
18314+ if (!err) {
18315+ err = 1;
18316+ au_fset_opts(opts->flags, TRUNC_XIB);
18317+ au_fset_opts(opts->flags, REFRESH_DIR);
18318+ au_fset_opts(opts->flags, REFRESH_NONDIR);
18319+ }
18320+ break;
18321+
18322+ case Opt_mod:
18323+ case Opt_imod:
18324+ err = au_br_mod(sb, &opt->mod,
18325+ au_ftest_opts(opts->flags, REMOUNT),
18326+ &do_refresh);
18327+ if (!err) {
18328+ err = 1;
18329+ if (do_refresh) {
18330+ au_fset_opts(opts->flags, REFRESH_DIR);
18331+ au_fset_opts(opts->flags, REFRESH_NONDIR);
18332+ }
18333+ }
18334+ break;
18335+ }
18336+
18337+ return err;
18338+}
18339+
18340+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
18341+ struct au_opt_xino **opt_xino,
18342+ struct au_opts *opts)
18343+{
18344+ int err;
18345+ aufs_bindex_t bend, bindex;
18346+ struct dentry *root, *parent, *h_root;
18347+
18348+ err = 0;
18349+ switch (opt->type) {
18350+ case Opt_xino:
18351+ err = au_xino_set(sb, &opt->xino,
18352+ !!au_ftest_opts(opts->flags, REMOUNT));
18353+ if (unlikely(err))
18354+ break;
18355+
18356+ *opt_xino = &opt->xino;
18357+ au_xino_brid_set(sb, -1);
18358+
18359+ /* safe d_parent access */
18360+ parent = opt->xino.file->f_dentry->d_parent;
18361+ root = sb->s_root;
18362+ bend = au_sbend(sb);
18363+ for (bindex = 0; bindex <= bend; bindex++) {
18364+ h_root = au_h_dptr(root, bindex);
18365+ if (h_root == parent) {
18366+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
18367+ break;
18368+ }
18369+ }
18370+ break;
18371+
18372+ case Opt_noxino:
18373+ au_xino_clr(sb);
18374+ au_xino_brid_set(sb, -1);
18375+ *opt_xino = (void *)-1;
18376+ break;
18377+ }
18378+
18379+ return err;
18380+}
18381+
18382+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18383+ unsigned int pending)
18384+{
18385+ int err;
18386+ aufs_bindex_t bindex, bend;
18387+ unsigned char do_plink, skip, do_free;
18388+ struct au_branch *br;
18389+ struct au_wbr *wbr;
18390+ struct dentry *root;
18391+ struct inode *dir, *h_dir;
18392+ struct au_sbinfo *sbinfo;
18393+ struct au_hinode *hdir;
18394+
dece6358
AM
18395+ SiMustAnyLock(sb);
18396+
1facf9fc 18397+ sbinfo = au_sbi(sb);
18398+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
18399+
dece6358
AM
18400+ if (!(sb_flags & MS_RDONLY)) {
18401+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
4a4d8108 18402+ pr_warning("first branch should be rw\n");
dece6358 18403+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
4a4d8108 18404+ pr_warning("shwh should be used with ro\n");
dece6358 18405+ }
1facf9fc 18406+
4a4d8108 18407+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 18408+ && !au_opt_test(sbinfo->si_mntflags, XINO))
4a4d8108 18409+ pr_warning("udba=*notify requires xino\n");
1facf9fc 18410+
18411+ err = 0;
18412+ root = sb->s_root;
4a4d8108 18413+ dir = root->d_inode;
1facf9fc 18414+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
18415+ bend = au_sbend(sb);
18416+ for (bindex = 0; !err && bindex <= bend; bindex++) {
18417+ skip = 0;
18418+ h_dir = au_h_iptr(dir, bindex);
18419+ br = au_sbr(sb, bindex);
18420+ do_free = 0;
18421+
18422+ wbr = br->br_wbr;
18423+ if (wbr)
18424+ wbr_wh_read_lock(wbr);
18425+
18426+ switch (br->br_perm) {
18427+ case AuBrPerm_RO:
18428+ case AuBrPerm_ROWH:
18429+ case AuBrPerm_RR:
18430+ case AuBrPerm_RRWH:
18431+ do_free = !!wbr;
18432+ skip = (!wbr
18433+ || (!wbr->wbr_whbase
18434+ && !wbr->wbr_plink
18435+ && !wbr->wbr_orph));
18436+ break;
18437+
18438+ case AuBrPerm_RWNoLinkWH:
18439+ /* skip = (!br->br_whbase && !br->br_orph); */
18440+ skip = (!wbr || !wbr->wbr_whbase);
18441+ if (skip && wbr) {
18442+ if (do_plink)
18443+ skip = !!wbr->wbr_plink;
18444+ else
18445+ skip = !wbr->wbr_plink;
18446+ }
18447+ break;
18448+
18449+ case AuBrPerm_RW:
18450+ /* skip = (br->br_whbase && br->br_ohph); */
18451+ skip = (wbr && wbr->wbr_whbase);
18452+ if (skip) {
18453+ if (do_plink)
18454+ skip = !!wbr->wbr_plink;
18455+ else
18456+ skip = !wbr->wbr_plink;
18457+ }
18458+ break;
18459+
18460+ default:
18461+ BUG();
18462+ }
18463+ if (wbr)
18464+ wbr_wh_read_unlock(wbr);
18465+
18466+ if (skip)
18467+ continue;
18468+
18469+ hdir = au_hi(dir, bindex);
4a4d8108 18470+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 18471+ if (wbr)
18472+ wbr_wh_write_lock(wbr);
18473+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
18474+ if (wbr)
18475+ wbr_wh_write_unlock(wbr);
4a4d8108 18476+ au_hn_imtx_unlock(hdir);
1facf9fc 18477+
18478+ if (!err && do_free) {
18479+ kfree(wbr);
18480+ br->br_wbr = NULL;
18481+ }
18482+ }
18483+
18484+ return err;
18485+}
18486+
18487+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
18488+{
18489+ int err;
18490+ unsigned int tmp;
18491+ aufs_bindex_t bend;
18492+ struct au_opt *opt;
18493+ struct au_opt_xino *opt_xino, xino;
18494+ struct au_sbinfo *sbinfo;
18495+
dece6358
AM
18496+ SiMustWriteLock(sb);
18497+
1facf9fc 18498+ err = 0;
18499+ opt_xino = NULL;
18500+ opt = opts->opt;
18501+ while (err >= 0 && opt->type != Opt_tail)
18502+ err = au_opt_simple(sb, opt++, opts);
18503+ if (err > 0)
18504+ err = 0;
18505+ else if (unlikely(err < 0))
18506+ goto out;
18507+
18508+ /* disable xino and udba temporary */
18509+ sbinfo = au_sbi(sb);
18510+ tmp = sbinfo->si_mntflags;
18511+ au_opt_clr(sbinfo->si_mntflags, XINO);
18512+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
18513+
18514+ opt = opts->opt;
18515+ while (err >= 0 && opt->type != Opt_tail)
18516+ err = au_opt_br(sb, opt++, opts);
18517+ if (err > 0)
18518+ err = 0;
18519+ else if (unlikely(err < 0))
18520+ goto out;
18521+
18522+ bend = au_sbend(sb);
18523+ if (unlikely(bend < 0)) {
18524+ err = -EINVAL;
4a4d8108 18525+ pr_err("no branches\n");
1facf9fc 18526+ goto out;
18527+ }
18528+
18529+ if (au_opt_test(tmp, XINO))
18530+ au_opt_set(sbinfo->si_mntflags, XINO);
18531+ opt = opts->opt;
18532+ while (!err && opt->type != Opt_tail)
18533+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
18534+ if (unlikely(err))
18535+ goto out;
18536+
18537+ err = au_opts_verify(sb, sb->s_flags, tmp);
18538+ if (unlikely(err))
18539+ goto out;
18540+
18541+ /* restore xino */
18542+ if (au_opt_test(tmp, XINO) && !opt_xino) {
18543+ xino.file = au_xino_def(sb);
18544+ err = PTR_ERR(xino.file);
18545+ if (IS_ERR(xino.file))
18546+ goto out;
18547+
18548+ err = au_xino_set(sb, &xino, /*remount*/0);
18549+ fput(xino.file);
18550+ if (unlikely(err))
18551+ goto out;
18552+ }
18553+
18554+ /* restore udba */
18555+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18556+ sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
4a4d8108 18557+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 18558+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 18559+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 18560+ }
18561+
4f0767ce 18562+out:
1facf9fc 18563+ return err;
18564+}
18565+
18566+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
18567+{
18568+ int err, rerr;
18569+ struct inode *dir;
18570+ struct au_opt_xino *opt_xino;
18571+ struct au_opt *opt;
18572+ struct au_sbinfo *sbinfo;
18573+
dece6358
AM
18574+ SiMustWriteLock(sb);
18575+
1facf9fc 18576+ dir = sb->s_root->d_inode;
18577+ sbinfo = au_sbi(sb);
18578+ err = 0;
18579+ opt_xino = NULL;
18580+ opt = opts->opt;
18581+ while (err >= 0 && opt->type != Opt_tail) {
18582+ err = au_opt_simple(sb, opt, opts);
18583+ if (!err)
18584+ err = au_opt_br(sb, opt, opts);
18585+ if (!err)
18586+ err = au_opt_xino(sb, opt, &opt_xino, opts);
18587+ opt++;
18588+ }
18589+ if (err > 0)
18590+ err = 0;
18591+ AuTraceErr(err);
18592+ /* go on even err */
18593+
18594+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
18595+ if (unlikely(rerr && !err))
18596+ err = rerr;
18597+
18598+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
18599+ rerr = au_xib_trunc(sb);
18600+ if (unlikely(rerr && !err))
18601+ err = rerr;
18602+ }
18603+
18604+ /* will be handled by the caller */
18605+ if (!au_ftest_opts(opts->flags, REFRESH_DIR)
18606+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
18607+ au_fset_opts(opts->flags, REFRESH_DIR);
18608+
18609+ AuDbg("status 0x%x\n", opts->flags);
18610+ return err;
18611+}
18612+
18613+/* ---------------------------------------------------------------------- */
18614+
18615+unsigned int au_opt_udba(struct super_block *sb)
18616+{
18617+ return au_mntflags(sb) & AuOptMask_UDBA;
18618+}
e49829fe
JR
18619--- /dev/null
18620+++ linux-2.6/fs/aufs/opts.h 2010-10-24 11:41:02.000000000 +0200
18621@@ -0,0 +1,207 @@
1facf9fc 18622+/*
4a4d8108 18623+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18624+ *
18625+ * This program, aufs is free software; you can redistribute it and/or modify
18626+ * it under the terms of the GNU General Public License as published by
18627+ * the Free Software Foundation; either version 2 of the License, or
18628+ * (at your option) any later version.
dece6358
AM
18629+ *
18630+ * This program is distributed in the hope that it will be useful,
18631+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18632+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18633+ * GNU General Public License for more details.
18634+ *
18635+ * You should have received a copy of the GNU General Public License
18636+ * along with this program; if not, write to the Free Software
18637+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18638+ */
18639+
18640+/*
18641+ * mount options/flags
18642+ */
18643+
18644+#ifndef __AUFS_OPTS_H__
18645+#define __AUFS_OPTS_H__
18646+
18647+#ifdef __KERNEL__
18648+
dece6358 18649+#include <linux/path.h>
1facf9fc 18650+#include <linux/aufs_type.h>
18651+
dece6358
AM
18652+struct file;
18653+struct super_block;
18654+
1facf9fc 18655+/* ---------------------------------------------------------------------- */
18656+
18657+/* mount flags */
18658+#define AuOpt_XINO 1 /* external inode number bitmap
18659+ and translation table */
18660+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
18661+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
18662+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 18663+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
18664+#define AuOpt_SHWH (1 << 5) /* show whiteout */
18665+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
18666+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
18667+#define AuOpt_REFROF (1 << 8) /* unimplemented */
18668+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
18669+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
18670+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
18671+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
18672+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 18673+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 18674+
4a4d8108
AM
18675+#ifndef CONFIG_AUFS_HNOTIFY
18676+#undef AuOpt_UDBA_HNOTIFY
18677+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 18678+#endif
dece6358
AM
18679+#ifndef CONFIG_AUFS_SHWH
18680+#undef AuOpt_SHWH
18681+#define AuOpt_SHWH 0
18682+#endif
1facf9fc 18683+
18684+#define AuOpt_Def (AuOpt_XINO \
18685+ | AuOpt_UDBA_REVAL \
18686+ | AuOpt_PLINK \
18687+ /* | AuOpt_DIRPERM1 */ \
18688+ | AuOpt_WARN_PERM)
18689+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
18690+ | AuOpt_UDBA_REVAL \
4a4d8108 18691+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 18692+
18693+#define au_opt_test(flags, name) (flags & AuOpt_##name)
18694+#define au_opt_set(flags, name) do { \
18695+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
18696+ ((flags) |= AuOpt_##name); \
18697+} while (0)
18698+#define au_opt_set_udba(flags, name) do { \
18699+ (flags) &= ~AuOptMask_UDBA; \
18700+ ((flags) |= AuOpt_##name); \
18701+} while (0)
18702+#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
18703+
e49829fe
JR
18704+static inline unsigned int au_opts_plink(unsigned int mntflags)
18705+{
18706+#ifdef CONFIG_PROC_FS
18707+ return mntflags;
18708+#else
18709+ return mntflags & ~AuOpt_PLINK;
18710+#endif
18711+}
18712+
1facf9fc 18713+/* ---------------------------------------------------------------------- */
18714+
18715+/* policies to select one among multiple writable branches */
18716+enum {
18717+ AuWbrCreate_TDP, /* top down parent */
18718+ AuWbrCreate_RR, /* round robin */
18719+ AuWbrCreate_MFS, /* most free space */
18720+ AuWbrCreate_MFSV, /* mfs with seconds */
18721+ AuWbrCreate_MFSRR, /* mfs then rr */
18722+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
18723+ AuWbrCreate_PMFS, /* parent and mfs */
18724+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
18725+
18726+ AuWbrCreate_Def = AuWbrCreate_TDP
18727+};
18728+
18729+enum {
18730+ AuWbrCopyup_TDP, /* top down parent */
18731+ AuWbrCopyup_BUP, /* bottom up parent */
18732+ AuWbrCopyup_BU, /* bottom up */
18733+
18734+ AuWbrCopyup_Def = AuWbrCopyup_TDP
18735+};
18736+
18737+/* ---------------------------------------------------------------------- */
18738+
18739+struct au_opt_add {
18740+ aufs_bindex_t bindex;
18741+ char *pathname;
18742+ int perm;
18743+ struct path path;
18744+};
18745+
18746+struct au_opt_del {
18747+ char *pathname;
18748+ struct path h_path;
18749+};
18750+
18751+struct au_opt_mod {
18752+ char *path;
18753+ int perm;
18754+ struct dentry *h_root;
18755+};
18756+
18757+struct au_opt_xino {
18758+ char *path;
18759+ struct file *file;
18760+};
18761+
18762+struct au_opt_xino_itrunc {
18763+ aufs_bindex_t bindex;
18764+};
18765+
18766+struct au_opt_wbr_create {
18767+ int wbr_create;
18768+ int mfs_second;
18769+ unsigned long long mfsrr_watermark;
18770+};
18771+
18772+struct au_opt {
18773+ int type;
18774+ union {
18775+ struct au_opt_xino xino;
18776+ struct au_opt_xino_itrunc xino_itrunc;
18777+ struct au_opt_add add;
18778+ struct au_opt_del del;
18779+ struct au_opt_mod mod;
18780+ int dirwh;
18781+ int rdcache;
18782+ unsigned int rdblk;
18783+ unsigned int rdhash;
18784+ int udba;
18785+ struct au_opt_wbr_create wbr_create;
18786+ int wbr_copyup;
18787+ };
18788+};
18789+
18790+/* opts flags */
18791+#define AuOpts_REMOUNT 1
18792+#define AuOpts_REFRESH_DIR (1 << 1)
18793+#define AuOpts_REFRESH_NONDIR (1 << 2)
18794+#define AuOpts_TRUNC_XIB (1 << 3)
4a4d8108 18795+#define AuOpts_REFRESH_DYAOP (1 << 4)
1facf9fc 18796+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
18797+#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
18798+#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
18799+
18800+struct au_opts {
18801+ struct au_opt *opt;
18802+ int max_opt;
18803+
18804+ unsigned int given_udba;
18805+ unsigned int flags;
18806+ unsigned long sb_flags;
18807+};
18808+
18809+/* ---------------------------------------------------------------------- */
18810+
18811+const char *au_optstr_br_perm(int brperm);
18812+const char *au_optstr_udba(int udba);
18813+const char *au_optstr_wbr_copyup(int wbr_copyup);
18814+const char *au_optstr_wbr_create(int wbr_create);
18815+
18816+void au_opts_free(struct au_opts *opts);
18817+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
18818+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18819+ unsigned int pending);
18820+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
18821+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
18822+
18823+unsigned int au_opt_udba(struct super_block *sb);
18824+
18825+/* ---------------------------------------------------------------------- */
18826+
18827+#endif /* __KERNEL__ */
18828+#endif /* __AUFS_OPTS_H__ */
e49829fe
JR
18829--- /dev/null
18830+++ linux-2.6/fs/aufs/plink.c 2010-10-24 15:01:46.000000000 +0200
18831@@ -0,0 +1,483 @@
1facf9fc 18832+/*
4a4d8108 18833+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18834+ *
18835+ * This program, aufs is free software; you can redistribute it and/or modify
18836+ * it under the terms of the GNU General Public License as published by
18837+ * the Free Software Foundation; either version 2 of the License, or
18838+ * (at your option) any later version.
dece6358
AM
18839+ *
18840+ * This program is distributed in the hope that it will be useful,
18841+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18842+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18843+ * GNU General Public License for more details.
18844+ *
18845+ * You should have received a copy of the GNU General Public License
18846+ * along with this program; if not, write to the Free Software
18847+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18848+ */
18849+
18850+/*
18851+ * pseudo-link
18852+ */
18853+
18854+#include "aufs.h"
18855+
18856+/*
e49829fe 18857+ * the pseudo-link maintenance mode.
1facf9fc 18858+ * during a user process maintains the pseudo-links,
18859+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
18860+ *
18861+ * Flags
18862+ * NOPLM:
18863+ * For entry functions which will handle plink, and i_mutex is already held
18864+ * in VFS.
18865+ * They cannot wait and should return an error at once.
18866+ * Callers has to check the error.
18867+ * NOPLMW:
18868+ * For entry functions which will handle plink, but i_mutex is not held
18869+ * in VFS.
18870+ * They can wait the plink maintenance mode to finish.
18871+ *
18872+ * They behave like F_SETLK and F_SETLKW.
18873+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 18874+ */
e49829fe
JR
18875+
18876+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 18877+{
e49829fe
JR
18878+ int err;
18879+ pid_t pid, ppid;
18880+ struct au_sbinfo *sbi;
dece6358
AM
18881+
18882+ SiMustAnyLock(sb);
18883+
e49829fe
JR
18884+ err = 0;
18885+ if (!au_opt_test(au_mntflags(sb), PLINK))
18886+ goto out;
18887+
18888+ sbi = au_sbi(sb);
18889+ pid = sbi->si_plink_maint_pid;
18890+ if (!pid || pid == current->pid)
18891+ goto out;
18892+
18893+ /* todo: it highly depends upon /sbin/mount.aufs */
18894+ rcu_read_lock();
18895+ ppid = task_pid_vnr(rcu_dereference(current->real_parent));
18896+ rcu_read_unlock();
18897+ if (pid == ppid)
18898+ goto out;
18899+
18900+ if (au_ftest_lock(flags, NOPLMW)) {
18901+ /*
18902+ * todo: debug by lockdep, if there is no i_mutex lock in VFS,
18903+ * we don't need to wait.
18904+ */
18905+ while (sbi->si_plink_maint_pid) {
18906+ si_read_unlock(sb);
18907+ /* gave up wake_up_bit() */
18908+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
18909+
18910+ if (au_ftest_lock(flags, FLUSH))
18911+ au_nwt_flush(&sbi->si_nowait);
18912+ si_noflush_read_lock(sb);
18913+ }
18914+ } else if (au_ftest_lock(flags, NOPLM)) {
18915+ AuDbg("ppid %d, pid %d\n", ppid, pid);
18916+ err = -EAGAIN;
18917+ }
18918+
18919+out:
18920+ return err;
4a4d8108
AM
18921+}
18922+
e49829fe 18923+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 18924+{
4a4d8108
AM
18925+ int iam;
18926+
4a4d8108 18927+ spin_lock(&sbinfo->si_plink_maint_lock);
e49829fe 18928+ iam = (sbinfo->si_plink_maint_pid == current->pid);
4a4d8108 18929+ if (iam)
e49829fe 18930+ sbinfo->si_plink_maint_pid = 0;
4a4d8108
AM
18931+ spin_unlock(&sbinfo->si_plink_maint_lock);
18932+ if (iam)
18933+ wake_up_all(&sbinfo->si_plink_wq);
18934+}
18935+
e49829fe 18936+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
18937+{
18938+ int err;
4a4d8108
AM
18939+ struct au_sbinfo *sbinfo;
18940+
18941+ err = 0;
4a4d8108
AM
18942+ sbinfo = au_sbi(sb);
18943+ /* make sure i am the only one in this fs */
e49829fe
JR
18944+ si_write_lock(sb, AuLock_FLUSH);
18945+ if (au_opt_test(au_mntflags(sb), PLINK)) {
18946+ spin_lock(&sbinfo->si_plink_maint_lock);
18947+ if (!sbinfo->si_plink_maint_pid)
18948+ sbinfo->si_plink_maint_pid = current->pid;
18949+ else
18950+ err = -EBUSY;
18951+ spin_unlock(&sbinfo->si_plink_maint_lock);
18952+ }
4a4d8108
AM
18953+ si_write_unlock(sb);
18954+
18955+ return err;
1facf9fc 18956+}
18957+
18958+/* ---------------------------------------------------------------------- */
18959+
18960+struct pseudo_link {
4a4d8108
AM
18961+ union {
18962+ struct list_head list;
18963+ struct rcu_head rcu;
18964+ };
1facf9fc 18965+ struct inode *inode;
18966+};
18967+
18968+#ifdef CONFIG_AUFS_DEBUG
18969+void au_plink_list(struct super_block *sb)
18970+{
18971+ struct au_sbinfo *sbinfo;
18972+ struct list_head *plink_list;
18973+ struct pseudo_link *plink;
18974+
dece6358
AM
18975+ SiMustAnyLock(sb);
18976+
1facf9fc 18977+ sbinfo = au_sbi(sb);
18978+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 18979+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 18980+
18981+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18982+ rcu_read_lock();
18983+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 18984+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 18985+ rcu_read_unlock();
1facf9fc 18986+}
18987+#endif
18988+
18989+/* is the inode pseudo-linked? */
18990+int au_plink_test(struct inode *inode)
18991+{
18992+ int found;
18993+ struct au_sbinfo *sbinfo;
18994+ struct list_head *plink_list;
18995+ struct pseudo_link *plink;
18996+
18997+ sbinfo = au_sbi(inode->i_sb);
dece6358 18998+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 18999+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 19000+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 19001+
19002+ found = 0;
19003+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19004+ rcu_read_lock();
19005+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 19006+ if (plink->inode == inode) {
19007+ found = 1;
19008+ break;
19009+ }
4a4d8108 19010+ rcu_read_unlock();
1facf9fc 19011+ return found;
19012+}
19013+
19014+/* ---------------------------------------------------------------------- */
19015+
19016+/*
19017+ * generate a name for plink.
19018+ * the file will be stored under AUFS_WH_PLINKDIR.
19019+ */
19020+/* 20 is max digits length of ulong 64 */
19021+#define PLINK_NAME_LEN ((20 + 1) * 2)
19022+
19023+static int plink_name(char *name, int len, struct inode *inode,
19024+ aufs_bindex_t bindex)
19025+{
19026+ int rlen;
19027+ struct inode *h_inode;
19028+
19029+ h_inode = au_h_iptr(inode, bindex);
19030+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
19031+ return rlen;
19032+}
19033+
19034+/* lookup the plink-ed @inode under the branch at @bindex */
19035+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
19036+{
19037+ struct dentry *h_dentry, *h_parent;
19038+ struct au_branch *br;
19039+ struct inode *h_dir;
19040+ char a[PLINK_NAME_LEN];
19041+ struct qstr tgtname = {
19042+ .name = a
19043+ };
19044+
e49829fe
JR
19045+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
19046+
1facf9fc 19047+ br = au_sbr(inode->i_sb, bindex);
19048+ h_parent = br->br_wbr->wbr_plink;
19049+ h_dir = h_parent->d_inode;
19050+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
19051+
19052+ /* always superio. */
19053+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
19054+ h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
19055+ mutex_unlock(&h_dir->i_mutex);
19056+ return h_dentry;
19057+}
19058+
19059+/* create a pseudo-link */
19060+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
19061+ struct dentry *h_dentry, struct au_branch *br)
19062+{
19063+ int err;
19064+ struct path h_path = {
19065+ .mnt = br->br_mnt
19066+ };
19067+ struct inode *h_dir;
19068+
19069+ h_dir = h_parent->d_inode;
4f0767ce 19070+again:
1facf9fc 19071+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
19072+ err = PTR_ERR(h_path.dentry);
19073+ if (IS_ERR(h_path.dentry))
19074+ goto out;
19075+
19076+ err = 0;
19077+ /* wh.plink dir is not monitored */
19078+ if (h_path.dentry->d_inode
19079+ && h_path.dentry->d_inode != h_dentry->d_inode) {
19080+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
19081+ dput(h_path.dentry);
19082+ h_path.dentry = NULL;
19083+ if (!err)
19084+ goto again;
19085+ }
19086+ if (!err && !h_path.dentry->d_inode)
19087+ err = vfsub_link(h_dentry, h_dir, &h_path);
19088+ dput(h_path.dentry);
19089+
4f0767ce 19090+out:
1facf9fc 19091+ return err;
19092+}
19093+
19094+struct do_whplink_args {
19095+ int *errp;
19096+ struct qstr *tgt;
19097+ struct dentry *h_parent;
19098+ struct dentry *h_dentry;
19099+ struct au_branch *br;
19100+};
19101+
19102+static void call_do_whplink(void *args)
19103+{
19104+ struct do_whplink_args *a = args;
19105+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
19106+}
19107+
19108+static int whplink(struct dentry *h_dentry, struct inode *inode,
19109+ aufs_bindex_t bindex, struct au_branch *br)
19110+{
19111+ int err, wkq_err;
19112+ struct au_wbr *wbr;
19113+ struct dentry *h_parent;
19114+ struct inode *h_dir;
19115+ char a[PLINK_NAME_LEN];
19116+ struct qstr tgtname = {
19117+ .name = a
19118+ };
19119+
19120+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
19121+ h_parent = wbr->wbr_plink;
19122+ h_dir = h_parent->d_inode;
19123+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
19124+
19125+ /* always superio. */
19126+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
b752ccd1 19127+ if (current_fsuid()) {
1facf9fc 19128+ struct do_whplink_args args = {
19129+ .errp = &err,
19130+ .tgt = &tgtname,
19131+ .h_parent = h_parent,
19132+ .h_dentry = h_dentry,
19133+ .br = br
19134+ };
19135+ wkq_err = au_wkq_wait(call_do_whplink, &args);
19136+ if (unlikely(wkq_err))
19137+ err = wkq_err;
19138+ } else
19139+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
19140+ mutex_unlock(&h_dir->i_mutex);
19141+
19142+ return err;
19143+}
19144+
19145+/* free a single plink */
19146+static void do_put_plink(struct pseudo_link *plink, int do_del)
19147+{
1facf9fc 19148+ if (do_del)
19149+ list_del(&plink->list);
4a4d8108
AM
19150+ iput(plink->inode);
19151+ kfree(plink);
19152+}
19153+
19154+static void do_put_plink_rcu(struct rcu_head *rcu)
19155+{
19156+ struct pseudo_link *plink;
19157+
19158+ plink = container_of(rcu, struct pseudo_link, rcu);
19159+ iput(plink->inode);
1facf9fc 19160+ kfree(plink);
19161+}
19162+
19163+/*
19164+ * create a new pseudo-link for @h_dentry on @bindex.
19165+ * the linked inode is held in aufs @inode.
19166+ */
19167+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
19168+ struct dentry *h_dentry)
19169+{
19170+ struct super_block *sb;
19171+ struct au_sbinfo *sbinfo;
19172+ struct list_head *plink_list;
4a4d8108 19173+ struct pseudo_link *plink, *tmp;
1facf9fc 19174+ int found, err, cnt;
19175+
19176+ sb = inode->i_sb;
19177+ sbinfo = au_sbi(sb);
19178+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19179+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19180+
1facf9fc 19181+ cnt = 0;
19182+ found = 0;
19183+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19184+ rcu_read_lock();
19185+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 19186+ cnt++;
19187+ if (plink->inode == inode) {
19188+ found = 1;
19189+ break;
19190+ }
19191+ }
4a4d8108
AM
19192+ rcu_read_unlock();
19193+ if (found)
1facf9fc 19194+ return;
4a4d8108
AM
19195+
19196+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
19197+ if (tmp)
19198+ tmp->inode = au_igrab(inode);
19199+ else {
19200+ err = -ENOMEM;
19201+ goto out;
1facf9fc 19202+ }
19203+
4a4d8108
AM
19204+ spin_lock(&sbinfo->si_plink.spin);
19205+ list_for_each_entry(plink, plink_list, list) {
19206+ if (plink->inode == inode) {
19207+ found = 1;
19208+ break;
19209+ }
1facf9fc 19210+ }
4a4d8108
AM
19211+ if (!found)
19212+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 19213+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
19214+ if (!found) {
19215+ cnt++;
19216+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
19217+ "unexpectedly many pseudo links, %d\n", cnt);
1facf9fc 19218+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
19219+ } else {
19220+ do_put_plink(tmp, 0);
19221+ return;
1facf9fc 19222+ }
19223+
4a4d8108 19224+out:
1facf9fc 19225+ if (unlikely(err)) {
4a4d8108
AM
19226+ pr_warning("err %d, damaged pseudo link.\n", err);
19227+ if (tmp) {
19228+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
19229+ call_rcu(&tmp->rcu, do_put_plink_rcu);
19230+ }
1facf9fc 19231+ }
19232+}
19233+
19234+/* free all plinks */
e49829fe 19235+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 19236+{
19237+ struct au_sbinfo *sbinfo;
19238+ struct list_head *plink_list;
19239+ struct pseudo_link *plink, *tmp;
19240+
dece6358
AM
19241+ SiMustWriteLock(sb);
19242+
1facf9fc 19243+ sbinfo = au_sbi(sb);
19244+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19245+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19246+
19247+ plink_list = &sbinfo->si_plink.head;
19248+ /* no spin_lock since sbinfo is write-locked */
e49829fe 19249+ WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
1facf9fc 19250+ list_for_each_entry_safe(plink, tmp, plink_list, list)
19251+ do_put_plink(plink, 0);
19252+ INIT_LIST_HEAD(plink_list);
19253+}
19254+
e49829fe
JR
19255+void au_plink_clean(struct super_block *sb, int verbose)
19256+{
19257+ struct dentry *root;
19258+
19259+ root = sb->s_root;
19260+ aufs_write_lock(root);
19261+ if (au_opt_test(au_mntflags(sb), PLINK))
19262+ au_plink_put(sb, verbose);
19263+ aufs_write_unlock(root);
19264+}
19265+
1facf9fc 19266+/* free the plinks on a branch specified by @br_id */
19267+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
19268+{
19269+ struct au_sbinfo *sbinfo;
19270+ struct list_head *plink_list;
19271+ struct pseudo_link *plink, *tmp;
19272+ struct inode *inode;
19273+ aufs_bindex_t bstart, bend, bindex;
19274+ unsigned char do_put;
19275+
dece6358
AM
19276+ SiMustWriteLock(sb);
19277+
1facf9fc 19278+ sbinfo = au_sbi(sb);
19279+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19280+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19281+
19282+ plink_list = &sbinfo->si_plink.head;
19283+ /* no spin_lock since sbinfo is write-locked */
19284+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
19285+ do_put = 0;
19286+ inode = au_igrab(plink->inode);
19287+ ii_write_lock_child(inode);
19288+ bstart = au_ibstart(inode);
19289+ bend = au_ibend(inode);
19290+ if (bstart >= 0) {
19291+ for (bindex = bstart; bindex <= bend; bindex++) {
19292+ if (!au_h_iptr(inode, bindex)
19293+ || au_ii_br_id(inode, bindex) != br_id)
19294+ continue;
19295+ au_set_h_iptr(inode, bindex, NULL, 0);
19296+ do_put = 1;
19297+ break;
19298+ }
19299+ } else
19300+ do_put_plink(plink, 1);
19301+
dece6358
AM
19302+ if (do_put) {
19303+ for (bindex = bstart; bindex <= bend; bindex++)
19304+ if (au_h_iptr(inode, bindex)) {
19305+ do_put = 0;
19306+ break;
19307+ }
19308+ if (do_put)
19309+ do_put_plink(plink, 1);
19310+ }
19311+ ii_write_unlock(inode);
19312+ iput(inode);
19313+ }
19314+}
e49829fe
JR
19315--- /dev/null
19316+++ linux-2.6/fs/aufs/poll.c 2010-10-24 11:41:22.000000000 +0200
dece6358
AM
19317@@ -0,0 +1,56 @@
19318+/*
4a4d8108 19319+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
19320+ *
19321+ * This program, aufs is free software; you can redistribute it and/or modify
19322+ * it under the terms of the GNU General Public License as published by
19323+ * the Free Software Foundation; either version 2 of the License, or
19324+ * (at your option) any later version.
19325+ *
19326+ * This program is distributed in the hope that it will be useful,
19327+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19328+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19329+ * GNU General Public License for more details.
19330+ *
19331+ * You should have received a copy of the GNU General Public License
19332+ * along with this program; if not, write to the Free Software
19333+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19334+ */
19335+
1308ab2a 19336+/*
19337+ * poll operation
19338+ * There is only one filesystem which implements ->poll operation, currently.
19339+ */
19340+
19341+#include "aufs.h"
19342+
19343+unsigned int aufs_poll(struct file *file, poll_table *wait)
19344+{
19345+ unsigned int mask;
19346+ int err;
19347+ struct file *h_file;
19348+ struct dentry *dentry;
19349+ struct super_block *sb;
19350+
19351+ /* We should pretend an error happened. */
19352+ mask = POLLERR /* | POLLIN | POLLOUT */;
19353+ dentry = file->f_dentry;
19354+ sb = dentry->d_sb;
e49829fe 19355+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 19356+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
19357+ if (unlikely(err))
19358+ goto out;
19359+
19360+ /* it is not an error if h_file has no operation */
19361+ mask = DEFAULT_POLLMASK;
4a4d8108 19362+ h_file = au_hf_top(file);
1308ab2a 19363+ if (h_file->f_op && h_file->f_op->poll)
19364+ mask = h_file->f_op->poll(h_file, wait);
19365+
19366+ di_read_unlock(dentry, AuLock_IR);
19367+ fi_read_unlock(file);
19368+
4f0767ce 19369+out:
1308ab2a 19370+ si_read_unlock(sb);
19371+ AuTraceErr((int)mask);
19372+ return mask;
19373+}
e49829fe
JR
19374--- /dev/null
19375+++ linux-2.6/fs/aufs/procfs.c 2010-10-24 11:11:14.000000000 +0200
19376@@ -0,0 +1,169 @@
19377+/*
19378+ * Copyright (C) 2010 Junjiro R. Okajima
19379+ *
19380+ * This program, aufs is free software; you can redistribute it and/or modify
19381+ * it under the terms of the GNU General Public License as published by
19382+ * the Free Software Foundation; either version 2 of the License, or
19383+ * (at your option) any later version.
19384+ *
19385+ * This program is distributed in the hope that it will be useful,
19386+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19387+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19388+ * GNU General Public License for more details.
19389+ *
19390+ * You should have received a copy of the GNU General Public License
19391+ * along with this program; if not, write to the Free Software
19392+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19393+ */
19394+
19395+/*
19396+ * procfs interfaces
19397+ */
19398+
19399+#include <linux/proc_fs.h>
19400+#include "aufs.h"
19401+
19402+static int au_procfs_plm_release(struct inode *inode, struct file *file)
19403+{
19404+ struct au_sbinfo *sbinfo;
19405+
19406+ sbinfo = file->private_data;
19407+ if (sbinfo) {
19408+ au_plink_maint_leave(sbinfo);
19409+ kobject_put(&sbinfo->si_kobj);
19410+ }
19411+
19412+ return 0;
19413+}
19414+
19415+static void au_procfs_plm_write_clean(struct file *file)
19416+{
19417+ struct au_sbinfo *sbinfo;
19418+
19419+ sbinfo = file->private_data;
19420+ if (sbinfo)
19421+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
19422+}
19423+
19424+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
19425+{
19426+ int err;
19427+ struct super_block *sb;
19428+ struct au_sbinfo *sbinfo;
19429+
19430+ err = -EBUSY;
19431+ if (unlikely(file->private_data))
19432+ goto out;
19433+
19434+ sb = NULL;
19435+ spin_lock(&au_sbilist.spin);
19436+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
19437+ if (id == sysaufs_si_id(sbinfo)) {
19438+ kobject_get(&sbinfo->si_kobj);
19439+ sb = sbinfo->si_sb;
19440+ break;
19441+ }
19442+ spin_unlock(&au_sbilist.spin);
19443+
19444+ err = -EINVAL;
19445+ if (unlikely(!sb))
19446+ goto out;
19447+
19448+ err = au_plink_maint_enter(sb);
19449+ if (!err)
19450+ /* keep kobject_get() */
19451+ file->private_data = sbinfo;
19452+ else
19453+ kobject_put(&sbinfo->si_kobj);
19454+out:
19455+ return err;
19456+}
19457+
19458+/*
19459+ * Accept a valid "si=xxxx" only.
19460+ * Once it is accepted successfully, accept "clean" too.
19461+ */
19462+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
19463+ size_t count, loff_t *ppos)
19464+{
19465+ ssize_t err;
19466+ unsigned long id;
19467+ /* last newline is allowed */
19468+ char buf[3 + sizeof(unsigned long) * 2 + 1];
19469+
19470+ err = -EACCES;
19471+ if (unlikely(!capable(CAP_SYS_ADMIN)))
19472+ goto out;
19473+
19474+ err = -EINVAL;
19475+ if (unlikely(count > sizeof(buf)))
19476+ goto out;
19477+
19478+ err = copy_from_user(buf, ubuf, count);
19479+ if (unlikely(err)) {
19480+ err = -EFAULT;
19481+ goto out;
19482+ }
19483+ buf[count] = 0;
19484+
19485+ err = -EINVAL;
19486+ if (!strcmp("clean", buf)) {
19487+ au_procfs_plm_write_clean(file);
19488+ goto out_success;
19489+ } else if (unlikely(strncmp("si=", buf, 3)))
19490+ goto out;
19491+
19492+ err = strict_strtoul(buf + 3, 16, &id);
19493+ if (unlikely(err))
19494+ goto out;
19495+
19496+ err = au_procfs_plm_write_si(file, id);
19497+ if (unlikely(err))
19498+ goto out;
19499+
19500+out_success:
19501+ err = count; /* success */
19502+out:
19503+ return err;
19504+}
19505+
19506+static const struct file_operations au_procfs_plm_fop = {
19507+ .write = au_procfs_plm_write,
19508+ .release = au_procfs_plm_release,
19509+ .owner = THIS_MODULE
19510+};
19511+
19512+/* ---------------------------------------------------------------------- */
19513+
19514+static struct proc_dir_entry *au_procfs_dir;
19515+
19516+void au_procfs_fin(void)
19517+{
19518+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
19519+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
19520+}
19521+
19522+int __init au_procfs_init(void)
19523+{
19524+ int err;
19525+ struct proc_dir_entry *entry;
19526+
19527+ err = -ENOMEM;
19528+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
19529+ if (unlikely(!au_procfs_dir))
19530+ goto out;
19531+
19532+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
19533+ au_procfs_dir, &au_procfs_plm_fop);
19534+ if (unlikely(!entry))
19535+ goto out_dir;
19536+
19537+ err = 0;
19538+ goto out; /* success */
19539+
19540+
19541+out_dir:
19542+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
19543+out:
19544+ return err;
19545+}
19546--- /dev/null
19547+++ linux-2.6/fs/aufs/rdu.c 2010-10-24 11:42:00.000000000 +0200
19548@@ -0,0 +1,380 @@
1308ab2a 19549+/*
4a4d8108 19550+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 19551+ *
19552+ * This program, aufs is free software; you can redistribute it and/or modify
19553+ * it under the terms of the GNU General Public License as published by
19554+ * the Free Software Foundation; either version 2 of the License, or
19555+ * (at your option) any later version.
19556+ *
19557+ * This program is distributed in the hope that it will be useful,
19558+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19559+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19560+ * GNU General Public License for more details.
19561+ *
19562+ * You should have received a copy of the GNU General Public License
19563+ * along with this program; if not, write to the Free Software
19564+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19565+ */
19566+
19567+/*
19568+ * readdir in userspace.
19569+ */
19570+
b752ccd1 19571+#include <linux/compat.h>
4a4d8108 19572+#include <linux/fs_stack.h>
1308ab2a 19573+#include <linux/security.h>
19574+#include <linux/uaccess.h>
19575+#include <linux/aufs_type.h>
19576+#include "aufs.h"
19577+
19578+/* bits for struct aufs_rdu.flags */
19579+#define AuRdu_CALLED 1
19580+#define AuRdu_CONT (1 << 1)
19581+#define AuRdu_FULL (1 << 2)
19582+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
19583+#define au_fset_rdu(flags, name) { (flags) |= AuRdu_##name; }
19584+#define au_fclr_rdu(flags, name) { (flags) &= ~AuRdu_##name; }
19585+
19586+struct au_rdu_arg {
19587+ struct aufs_rdu *rdu;
19588+ union au_rdu_ent_ul ent;
19589+ unsigned long end;
19590+
19591+ struct super_block *sb;
19592+ int err;
19593+};
19594+
19595+static int au_rdu_fill(void *__arg, const char *name, int nlen,
19596+ loff_t offset, u64 h_ino, unsigned int d_type)
19597+{
19598+ int err, len;
19599+ struct au_rdu_arg *arg = __arg;
19600+ struct aufs_rdu *rdu = arg->rdu;
19601+ struct au_rdu_ent ent;
19602+
19603+ err = 0;
19604+ arg->err = 0;
19605+ au_fset_rdu(rdu->cookie.flags, CALLED);
19606+ len = au_rdu_len(nlen);
19607+ if (arg->ent.ul + len < arg->end) {
19608+ ent.ino = h_ino;
19609+ ent.bindex = rdu->cookie.bindex;
19610+ ent.type = d_type;
19611+ ent.nlen = nlen;
4a4d8108
AM
19612+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
19613+ ent.type = DT_UNKNOWN;
1308ab2a 19614+
19615+ err = -EFAULT;
19616+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
19617+ goto out;
19618+ if (copy_to_user(arg->ent.e->name, name, nlen))
19619+ goto out;
19620+ /* the terminating NULL */
19621+ if (__put_user(0, arg->ent.e->name + nlen))
19622+ goto out;
19623+ err = 0;
19624+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
19625+ arg->ent.ul += len;
19626+ rdu->rent++;
19627+ } else {
19628+ err = -EFAULT;
19629+ au_fset_rdu(rdu->cookie.flags, FULL);
19630+ rdu->full = 1;
19631+ rdu->tail = arg->ent;
19632+ }
19633+
4f0767ce 19634+out:
1308ab2a 19635+ /* AuTraceErr(err); */
19636+ return err;
19637+}
19638+
19639+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
19640+{
19641+ int err;
19642+ loff_t offset;
19643+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
19644+
19645+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
19646+ err = offset;
19647+ if (unlikely(offset != cookie->h_pos))
19648+ goto out;
19649+
19650+ err = 0;
19651+ do {
19652+ arg->err = 0;
19653+ au_fclr_rdu(cookie->flags, CALLED);
19654+ /* smp_mb(); */
19655+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
19656+ if (err >= 0)
19657+ err = arg->err;
19658+ } while (!err
19659+ && au_ftest_rdu(cookie->flags, CALLED)
19660+ && !au_ftest_rdu(cookie->flags, FULL));
19661+ cookie->h_pos = h_file->f_pos;
19662+
4f0767ce 19663+out:
1308ab2a 19664+ AuTraceErr(err);
19665+ return err;
19666+}
19667+
19668+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
19669+{
19670+ int err;
19671+ aufs_bindex_t bend;
19672+ struct au_rdu_arg arg;
19673+ struct dentry *dentry;
19674+ struct inode *inode;
19675+ struct file *h_file;
19676+ struct au_rdu_cookie *cookie = &rdu->cookie;
19677+
19678+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
19679+ if (unlikely(err)) {
19680+ err = -EFAULT;
19681+ AuTraceErr(err);
19682+ goto out;
19683+ }
19684+ rdu->rent = 0;
19685+ rdu->tail = rdu->ent;
19686+ rdu->full = 0;
19687+ arg.rdu = rdu;
19688+ arg.ent = rdu->ent;
19689+ arg.end = arg.ent.ul;
19690+ arg.end += rdu->sz;
19691+
19692+ err = -ENOTDIR;
19693+ if (unlikely(!file->f_op || !file->f_op->readdir))
19694+ goto out;
19695+
19696+ err = security_file_permission(file, MAY_READ);
19697+ AuTraceErr(err);
19698+ if (unlikely(err))
19699+ goto out;
19700+
19701+ dentry = file->f_dentry;
19702+ inode = dentry->d_inode;
19703+#if 1
19704+ mutex_lock(&inode->i_mutex);
19705+#else
19706+ err = mutex_lock_killable(&inode->i_mutex);
19707+ AuTraceErr(err);
19708+ if (unlikely(err))
19709+ goto out;
19710+#endif
19711+ err = -ENOENT;
19712+ if (unlikely(IS_DEADDIR(inode)))
19713+ goto out_mtx;
19714+
19715+ arg.sb = inode->i_sb;
e49829fe
JR
19716+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
19717+ if (unlikely(err))
19718+ goto out_mtx;
19719+ /* todo: reval? */
1308ab2a 19720+ fi_read_lock(file);
19721+
19722+ err = -EAGAIN;
19723+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
19724+ && cookie->generation != au_figen(file)))
19725+ goto out_unlock;
19726+
19727+ err = 0;
19728+ if (!rdu->blk) {
19729+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
19730+ if (!rdu->blk)
19731+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
19732+ }
19733+ bend = au_fbstart(file);
19734+ if (cookie->bindex < bend)
19735+ cookie->bindex = bend;
4a4d8108 19736+ bend = au_fbend_dir(file);
1308ab2a 19737+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
19738+ for (; !err && cookie->bindex <= bend;
19739+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 19740+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 19741+ if (!h_file)
19742+ continue;
19743+
19744+ au_fclr_rdu(cookie->flags, FULL);
19745+ err = au_rdu_do(h_file, &arg);
19746+ AuTraceErr(err);
19747+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
19748+ break;
19749+ }
19750+ AuDbg("rent %llu\n", rdu->rent);
19751+
19752+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
19753+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
19754+ au_fset_rdu(cookie->flags, CONT);
19755+ cookie->generation = au_figen(file);
19756+ }
19757+
19758+ ii_read_lock_child(inode);
19759+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
19760+ ii_read_unlock(inode);
19761+
4f0767ce 19762+out_unlock:
1308ab2a 19763+ fi_read_unlock(file);
19764+ si_read_unlock(arg.sb);
4f0767ce 19765+out_mtx:
1308ab2a 19766+ mutex_unlock(&inode->i_mutex);
4f0767ce 19767+out:
1308ab2a 19768+ AuTraceErr(err);
19769+ return err;
19770+}
19771+
19772+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
19773+{
19774+ int err;
19775+ ino_t ino;
19776+ unsigned long long nent;
19777+ union au_rdu_ent_ul *u;
19778+ struct au_rdu_ent ent;
19779+ struct super_block *sb;
19780+
19781+ err = 0;
19782+ nent = rdu->nent;
19783+ u = &rdu->ent;
19784+ sb = file->f_dentry->d_sb;
19785+ si_read_lock(sb, AuLock_FLUSH);
19786+ while (nent-- > 0) {
1308ab2a 19787+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
19788+ if (!err)
19789+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 19790+ if (unlikely(err)) {
19791+ err = -EFAULT;
19792+ AuTraceErr(err);
19793+ break;
19794+ }
19795+
19796+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
19797+ if (!ent.wh)
19798+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
19799+ else
19800+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
19801+ &ino);
19802+ if (unlikely(err)) {
19803+ AuTraceErr(err);
19804+ break;
19805+ }
19806+
19807+ err = __put_user(ino, &u->e->ino);
19808+ if (unlikely(err)) {
19809+ err = -EFAULT;
19810+ AuTraceErr(err);
19811+ break;
19812+ }
19813+ u->ul += au_rdu_len(ent.nlen);
19814+ }
19815+ si_read_unlock(sb);
19816+
19817+ return err;
19818+}
19819+
19820+/* ---------------------------------------------------------------------- */
19821+
19822+static int au_rdu_verify(struct aufs_rdu *rdu)
19823+{
b752ccd1 19824+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 19825+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 19826+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 19827+ rdu->blk,
19828+ rdu->rent, rdu->shwh, rdu->full,
19829+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
19830+ rdu->cookie.generation);
dece6358 19831+
b752ccd1 19832+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 19833+ return 0;
dece6358 19834+
b752ccd1
AM
19835+ AuDbg("%u:%u\n",
19836+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 19837+ return -EINVAL;
19838+}
19839+
19840+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 19841+{
1308ab2a 19842+ long err, e;
19843+ struct aufs_rdu rdu;
19844+ void __user *p = (void __user *)arg;
dece6358 19845+
1308ab2a 19846+ err = copy_from_user(&rdu, p, sizeof(rdu));
19847+ if (unlikely(err)) {
19848+ err = -EFAULT;
19849+ AuTraceErr(err);
19850+ goto out;
19851+ }
19852+ err = au_rdu_verify(&rdu);
dece6358
AM
19853+ if (unlikely(err))
19854+ goto out;
19855+
1308ab2a 19856+ switch (cmd) {
19857+ case AUFS_CTL_RDU:
19858+ err = au_rdu(file, &rdu);
19859+ if (unlikely(err))
19860+ break;
dece6358 19861+
1308ab2a 19862+ e = copy_to_user(p, &rdu, sizeof(rdu));
19863+ if (unlikely(e)) {
19864+ err = -EFAULT;
19865+ AuTraceErr(err);
19866+ }
19867+ break;
19868+ case AUFS_CTL_RDU_INO:
19869+ err = au_rdu_ino(file, &rdu);
19870+ break;
19871+
19872+ default:
4a4d8108 19873+ /* err = -ENOTTY; */
1308ab2a 19874+ err = -EINVAL;
19875+ }
dece6358 19876+
4f0767ce 19877+out:
1308ab2a 19878+ AuTraceErr(err);
19879+ return err;
1facf9fc 19880+}
b752ccd1
AM
19881+
19882+#ifdef CONFIG_COMPAT
19883+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
19884+{
19885+ long err, e;
19886+ struct aufs_rdu rdu;
19887+ void __user *p = compat_ptr(arg);
19888+
19889+ /* todo: get_user()? */
19890+ err = copy_from_user(&rdu, p, sizeof(rdu));
19891+ if (unlikely(err)) {
19892+ err = -EFAULT;
19893+ AuTraceErr(err);
19894+ goto out;
19895+ }
19896+ rdu.ent.e = compat_ptr(rdu.ent.ul);
19897+ err = au_rdu_verify(&rdu);
19898+ if (unlikely(err))
19899+ goto out;
19900+
19901+ switch (cmd) {
19902+ case AUFS_CTL_RDU:
19903+ err = au_rdu(file, &rdu);
19904+ if (unlikely(err))
19905+ break;
19906+
19907+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
19908+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
19909+ e = copy_to_user(p, &rdu, sizeof(rdu));
19910+ if (unlikely(e)) {
19911+ err = -EFAULT;
19912+ AuTraceErr(err);
19913+ }
19914+ break;
19915+ case AUFS_CTL_RDU_INO:
19916+ err = au_rdu_ino(file, &rdu);
19917+ break;
19918+
19919+ default:
19920+ /* err = -ENOTTY; */
19921+ err = -EINVAL;
19922+ }
19923+
4f0767ce 19924+out:
b752ccd1
AM
19925+ AuTraceErr(err);
19926+ return err;
19927+}
19928+#endif
e49829fe
JR
19929--- /dev/null
19930+++ linux-2.6/fs/aufs/rwsem.h 2010-10-24 11:42:11.000000000 +0200
19931@@ -0,0 +1,189 @@
1facf9fc 19932+/*
4a4d8108 19933+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19934+ *
19935+ * This program, aufs is free software; you can redistribute it and/or modify
19936+ * it under the terms of the GNU General Public License as published by
19937+ * the Free Software Foundation; either version 2 of the License, or
19938+ * (at your option) any later version.
dece6358
AM
19939+ *
19940+ * This program is distributed in the hope that it will be useful,
19941+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19942+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19943+ * GNU General Public License for more details.
19944+ *
19945+ * You should have received a copy of the GNU General Public License
19946+ * along with this program; if not, write to the Free Software
19947+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19948+ */
19949+
19950+/*
19951+ * simple read-write semaphore wrappers
19952+ */
19953+
19954+#ifndef __AUFS_RWSEM_H__
19955+#define __AUFS_RWSEM_H__
19956+
19957+#ifdef __KERNEL__
19958+
dece6358 19959+#include <linux/rwsem.h>
4a4d8108 19960+#include "debug.h"
dece6358
AM
19961+
19962+struct au_rwsem {
19963+ struct rw_semaphore rwsem;
19964+#ifdef CONFIG_AUFS_DEBUG
19965+ /* just for debugging, not almighty counter */
19966+ atomic_t rcnt, wcnt;
19967+#endif
19968+};
19969+
19970+#ifdef CONFIG_AUFS_DEBUG
19971+#define AuDbgCntInit(rw) do { \
19972+ atomic_set(&(rw)->rcnt, 0); \
19973+ atomic_set(&(rw)->wcnt, 0); \
19974+ smp_mb(); /* atomic set */ \
19975+} while (0)
19976+
e49829fe 19977+#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
dece6358 19978+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
e49829fe 19979+#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
dece6358
AM
19980+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
19981+#else
19982+#define AuDbgCntInit(rw) do {} while (0)
19983+#define AuDbgRcntInc(rw) do {} while (0)
19984+#define AuDbgRcntDec(rw) do {} while (0)
19985+#define AuDbgWcntInc(rw) do {} while (0)
19986+#define AuDbgWcntDec(rw) do {} while (0)
19987+#endif /* CONFIG_AUFS_DEBUG */
19988+
19989+/* to debug easier, do not make them inlined functions */
19990+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
19991+/* rwsem_is_locked() is unusable */
19992+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
19993+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
19994+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
19995+ && atomic_read(&(rw)->wcnt) <= 0)
19996+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
19997+ || atomic_read(&(rw)->wcnt))
19998+
e49829fe
JR
19999+#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
20000+
dece6358
AM
20001+static inline void au_rw_init(struct au_rwsem *rw)
20002+{
20003+ AuDbgCntInit(rw);
20004+ init_rwsem(&rw->rwsem);
20005+}
20006+
20007+static inline void au_rw_init_wlock(struct au_rwsem *rw)
20008+{
20009+ au_rw_init(rw);
20010+ down_write(&rw->rwsem);
20011+ AuDbgWcntInc(rw);
20012+}
20013+
20014+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
20015+ unsigned int lsc)
20016+{
20017+ au_rw_init(rw);
20018+ down_write_nested(&rw->rwsem, lsc);
20019+ AuDbgWcntInc(rw);
20020+}
20021+
20022+static inline void au_rw_read_lock(struct au_rwsem *rw)
20023+{
20024+ down_read(&rw->rwsem);
20025+ AuDbgRcntInc(rw);
20026+}
20027+
20028+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
20029+{
20030+ down_read_nested(&rw->rwsem, lsc);
20031+ AuDbgRcntInc(rw);
20032+}
20033+
20034+static inline void au_rw_read_unlock(struct au_rwsem *rw)
20035+{
20036+ AuRwMustReadLock(rw);
20037+ AuDbgRcntDec(rw);
20038+ up_read(&rw->rwsem);
20039+}
20040+
20041+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
20042+{
20043+ AuRwMustWriteLock(rw);
20044+ AuDbgRcntInc(rw);
20045+ AuDbgWcntDec(rw);
20046+ downgrade_write(&rw->rwsem);
20047+}
20048+
20049+static inline void au_rw_write_lock(struct au_rwsem *rw)
20050+{
20051+ down_write(&rw->rwsem);
20052+ AuDbgWcntInc(rw);
20053+}
20054+
20055+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
20056+ unsigned int lsc)
20057+{
20058+ down_write_nested(&rw->rwsem, lsc);
20059+ AuDbgWcntInc(rw);
20060+}
1facf9fc 20061+
dece6358
AM
20062+static inline void au_rw_write_unlock(struct au_rwsem *rw)
20063+{
20064+ AuRwMustWriteLock(rw);
20065+ AuDbgWcntDec(rw);
20066+ up_write(&rw->rwsem);
20067+}
20068+
20069+/* why is not _nested version defined */
20070+static inline int au_rw_read_trylock(struct au_rwsem *rw)
20071+{
20072+ int ret = down_read_trylock(&rw->rwsem);
20073+ if (ret)
20074+ AuDbgRcntInc(rw);
20075+ return ret;
20076+}
20077+
20078+static inline int au_rw_write_trylock(struct au_rwsem *rw)
20079+{
20080+ int ret = down_write_trylock(&rw->rwsem);
20081+ if (ret)
20082+ AuDbgWcntInc(rw);
20083+ return ret;
20084+}
20085+
20086+#undef AuDbgCntInit
20087+#undef AuDbgRcntInc
20088+#undef AuDbgRcntDec
20089+#undef AuDbgWcntInc
20090+#undef AuDbgWcntDec
1facf9fc 20091+
20092+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
20093+static inline void prefix##_read_lock(param) \
dece6358 20094+{ au_rw_read_lock(rwsem); } \
1facf9fc 20095+static inline void prefix##_write_lock(param) \
dece6358 20096+{ au_rw_write_lock(rwsem); } \
1facf9fc 20097+static inline int prefix##_read_trylock(param) \
dece6358 20098+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 20099+static inline int prefix##_write_trylock(param) \
dece6358 20100+{ return au_rw_write_trylock(rwsem); }
1facf9fc 20101+/* why is not _nested version defined */
20102+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 20103+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 20104+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 20105+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 20106+
20107+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
20108+static inline void prefix##_read_unlock(param) \
dece6358 20109+{ au_rw_read_unlock(rwsem); } \
1facf9fc 20110+static inline void prefix##_write_unlock(param) \
dece6358 20111+{ au_rw_write_unlock(rwsem); } \
1facf9fc 20112+static inline void prefix##_downgrade_lock(param) \
dece6358 20113+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 20114+
20115+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
20116+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
20117+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
20118+
20119+#endif /* __KERNEL__ */
20120+#endif /* __AUFS_RWSEM_H__ */
e49829fe
JR
20121--- /dev/null
20122+++ linux-2.6/fs/aufs/sbinfo.c 2010-10-24 11:42:17.000000000 +0200
20123@@ -0,0 +1,311 @@
1facf9fc 20124+/*
4a4d8108 20125+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20126+ *
20127+ * This program, aufs is free software; you can redistribute it and/or modify
20128+ * it under the terms of the GNU General Public License as published by
20129+ * the Free Software Foundation; either version 2 of the License, or
20130+ * (at your option) any later version.
dece6358
AM
20131+ *
20132+ * This program is distributed in the hope that it will be useful,
20133+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20134+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20135+ * GNU General Public License for more details.
20136+ *
20137+ * You should have received a copy of the GNU General Public License
20138+ * along with this program; if not, write to the Free Software
20139+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20140+ */
20141+
20142+/*
20143+ * superblock private data
20144+ */
20145+
e49829fe 20146+#include <linux/jiffies.h>
1facf9fc 20147+#include "aufs.h"
20148+
20149+/*
20150+ * they are necessary regardless sysfs is disabled.
20151+ */
20152+void au_si_free(struct kobject *kobj)
20153+{
20154+ struct au_sbinfo *sbinfo;
b752ccd1 20155+ char *locked __maybe_unused; /* debug only */
1facf9fc 20156+
20157+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
20158+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
e49829fe 20159+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
1facf9fc 20160+
e49829fe 20161+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 20162+ au_br_free(sbinfo);
e49829fe 20163+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1
AM
20164+
20165+ AuDebugOn(radix_tree_gang_lookup
20166+ (&sbinfo->au_si_pid.tree, (void **)&locked,
20167+ /*first_index*/PID_MAX_DEFAULT - 1,
20168+ /*max_items*/sizeof(locked)/sizeof(*locked)));
20169+
1facf9fc 20170+ kfree(sbinfo->si_branch);
b752ccd1 20171+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 20172+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 20173+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 20174+
20175+ kfree(sbinfo);
20176+}
20177+
20178+int au_si_alloc(struct super_block *sb)
20179+{
20180+ int err;
20181+ struct au_sbinfo *sbinfo;
e49829fe 20182+ static struct lock_class_key aufs_si;
1facf9fc 20183+
20184+ err = -ENOMEM;
4a4d8108 20185+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 20186+ if (unlikely(!sbinfo))
20187+ goto out;
20188+
b752ccd1
AM
20189+ BUILD_BUG_ON(sizeof(unsigned long) !=
20190+ sizeof(*sbinfo->au_si_pid.bitmap));
20191+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
20192+ sizeof(*sbinfo->au_si_pid.bitmap),
20193+ GFP_NOFS);
20194+ if (unlikely(!sbinfo->au_si_pid.bitmap))
20195+ goto out_sbinfo;
20196+
1facf9fc 20197+ /* will be reallocated separately */
20198+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
20199+ if (unlikely(!sbinfo->si_branch))
b752ccd1 20200+ goto out_pidmap;
1facf9fc 20201+
1facf9fc 20202+ err = sysaufs_si_init(sbinfo);
20203+ if (unlikely(err))
20204+ goto out_br;
20205+
20206+ au_nwt_init(&sbinfo->si_nowait);
dece6358 20207+ au_rw_init_wlock(&sbinfo->si_rwsem);
e49829fe 20208+ au_rw_class(&sbinfo->si_rwsem, &aufs_si);
b752ccd1
AM
20209+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
20210+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
20211+
1facf9fc 20212+ sbinfo->si_bend = -1;
1facf9fc 20213+
20214+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
20215+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
20216+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
20217+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 20218+
e49829fe 20219+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 20220+
1facf9fc 20221+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 20222+ sbinfo->si_xino_brid = -1;
20223+ /* leave si_xib_last_pindex and si_xib_next_bit */
20224+
e49829fe 20225+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 20226+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
20227+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
20228+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
20229+
20230+ au_spl_init(&sbinfo->si_plink);
20231+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 20232+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 20233+
20234+ /* leave other members for sysaufs and si_mnt. */
20235+ sbinfo->si_sb = sb;
20236+ sb->s_fs_info = sbinfo;
b752ccd1 20237+ si_pid_set(sb);
1facf9fc 20238+ au_debug_sbinfo_init(sbinfo);
20239+ return 0; /* success */
20240+
4f0767ce 20241+out_br:
1facf9fc 20242+ kfree(sbinfo->si_branch);
4f0767ce 20243+out_pidmap:
b752ccd1 20244+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 20245+out_sbinfo:
1facf9fc 20246+ kfree(sbinfo);
4f0767ce 20247+out:
1facf9fc 20248+ return err;
20249+}
20250+
20251+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
20252+{
20253+ int err, sz;
20254+ struct au_branch **brp;
20255+
dece6358
AM
20256+ AuRwMustWriteLock(&sbinfo->si_rwsem);
20257+
1facf9fc 20258+ err = -ENOMEM;
20259+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
20260+ if (unlikely(!sz))
20261+ sz = sizeof(*brp);
20262+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
20263+ if (brp) {
20264+ sbinfo->si_branch = brp;
20265+ err = 0;
20266+ }
20267+
20268+ return err;
20269+}
20270+
20271+/* ---------------------------------------------------------------------- */
20272+
20273+unsigned int au_sigen_inc(struct super_block *sb)
20274+{
20275+ unsigned int gen;
20276+
dece6358
AM
20277+ SiMustWriteLock(sb);
20278+
1facf9fc 20279+ gen = ++au_sbi(sb)->si_generation;
20280+ au_update_digen(sb->s_root);
20281+ au_update_iigen(sb->s_root->d_inode);
20282+ sb->s_root->d_inode->i_version++;
20283+ return gen;
20284+}
20285+
20286+aufs_bindex_t au_new_br_id(struct super_block *sb)
20287+{
20288+ aufs_bindex_t br_id;
20289+ int i;
20290+ struct au_sbinfo *sbinfo;
20291+
dece6358
AM
20292+ SiMustWriteLock(sb);
20293+
1facf9fc 20294+ sbinfo = au_sbi(sb);
20295+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
20296+ br_id = ++sbinfo->si_last_br_id;
20297+ if (br_id && au_br_index(sb, br_id) < 0)
20298+ return br_id;
20299+ }
20300+
20301+ return -1;
20302+}
20303+
20304+/* ---------------------------------------------------------------------- */
20305+
e49829fe
JR
20306+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
20307+int si_read_lock(struct super_block *sb, int flags)
20308+{
20309+ int err;
20310+
20311+ err = 0;
20312+ if (au_ftest_lock(flags, FLUSH))
20313+ au_nwt_flush(&au_sbi(sb)->si_nowait);
20314+
20315+ si_noflush_read_lock(sb);
20316+ err = au_plink_maint(sb, flags);
20317+ if (unlikely(err))
20318+ si_read_unlock(sb);
20319+
20320+ return err;
20321+}
20322+
20323+int si_write_lock(struct super_block *sb, int flags)
20324+{
20325+ int err;
20326+
20327+ if (au_ftest_lock(flags, FLUSH))
20328+ au_nwt_flush(&au_sbi(sb)->si_nowait);
20329+
20330+ si_noflush_write_lock(sb);
20331+ err = au_plink_maint(sb, flags);
20332+ if (unlikely(err))
20333+ si_write_unlock(sb);
20334+
20335+ return err;
20336+}
20337+
1facf9fc 20338+/* dentry and super_block lock. call at entry point */
e49829fe 20339+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 20340+{
e49829fe
JR
20341+ int err;
20342+
20343+ err = si_read_lock(dentry->d_sb, flags);
20344+ if (!err) {
20345+ if (au_ftest_lock(flags, DW))
20346+ di_write_lock_child(dentry);
20347+ else
20348+ di_read_lock_child(dentry, flags);
20349+ }
20350+
20351+ return err;
1facf9fc 20352+}
20353+
20354+void aufs_read_unlock(struct dentry *dentry, int flags)
20355+{
20356+ if (au_ftest_lock(flags, DW))
20357+ di_write_unlock(dentry);
20358+ else
20359+ di_read_unlock(dentry, flags);
20360+ si_read_unlock(dentry->d_sb);
20361+}
20362+
20363+void aufs_write_lock(struct dentry *dentry)
20364+{
e49829fe 20365+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 20366+ di_write_lock_child(dentry);
20367+}
20368+
20369+void aufs_write_unlock(struct dentry *dentry)
20370+{
20371+ di_write_unlock(dentry);
20372+ si_write_unlock(dentry->d_sb);
20373+}
20374+
e49829fe 20375+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 20376+{
e49829fe
JR
20377+ int err;
20378+
20379+ err = si_read_lock(d1->d_sb, flags);
20380+ if (!err)
20381+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
20382+ return err;
1facf9fc 20383+}
20384+
20385+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
20386+{
20387+ di_write_unlock2(d1, d2);
20388+ si_read_unlock(d1->d_sb);
20389+}
b752ccd1
AM
20390+
20391+/* ---------------------------------------------------------------------- */
20392+
20393+int si_pid_test_slow(struct super_block *sb)
20394+{
20395+ void *p;
20396+
20397+ rcu_read_lock();
20398+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
20399+ rcu_read_unlock();
20400+
20401+ return (long)p;
20402+}
20403+
20404+void si_pid_set_slow(struct super_block *sb)
20405+{
20406+ int err;
20407+ struct au_sbinfo *sbinfo;
20408+
20409+ AuDebugOn(si_pid_test_slow(sb));
20410+
20411+ sbinfo = au_sbi(sb);
20412+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
20413+ AuDebugOn(err);
20414+ spin_lock(&sbinfo->au_si_pid.tree_lock);
20415+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
20416+ (void *)1);
20417+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
20418+ AuDebugOn(err);
20419+ radix_tree_preload_end();
20420+}
20421+
20422+void si_pid_clr_slow(struct super_block *sb)
20423+{
20424+ void *p;
20425+ struct au_sbinfo *sbinfo;
20426+
20427+ AuDebugOn(!si_pid_test_slow(sb));
20428+
20429+ sbinfo = au_sbi(sb);
20430+ spin_lock(&sbinfo->au_si_pid.tree_lock);
20431+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
20432+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
20433+ AuDebugOn(1 != (long)p);
20434+}
e49829fe
JR
20435--- /dev/null
20436+++ linux-2.6/fs/aufs/spl.h 2010-10-24 11:19:23.000000000 +0200
4a4d8108 20437@@ -0,0 +1,66 @@
1facf9fc 20438+/*
4a4d8108 20439+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20440+ *
20441+ * This program, aufs is free software; you can redistribute it and/or modify
20442+ * it under the terms of the GNU General Public License as published by
20443+ * the Free Software Foundation; either version 2 of the License, or
20444+ * (at your option) any later version.
dece6358
AM
20445+ *
20446+ * This program is distributed in the hope that it will be useful,
20447+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20448+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20449+ * GNU General Public License for more details.
20450+ *
20451+ * You should have received a copy of the GNU General Public License
20452+ * along with this program; if not, write to the Free Software
20453+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20454+ */
20455+
20456+/*
20457+ * simple list protected by a spinlock
20458+ */
20459+
20460+#ifndef __AUFS_SPL_H__
20461+#define __AUFS_SPL_H__
20462+
20463+#ifdef __KERNEL__
20464+
dece6358
AM
20465+#include <linux/spinlock.h>
20466+#include <linux/list.h>
4a4d8108 20467+#include <linux/rculist.h>
1facf9fc 20468+
20469+struct au_splhead {
20470+ spinlock_t spin;
20471+ struct list_head head;
20472+};
20473+
20474+static inline void au_spl_init(struct au_splhead *spl)
20475+{
20476+ spin_lock_init(&spl->spin);
20477+ INIT_LIST_HEAD(&spl->head);
20478+}
20479+
20480+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
20481+{
20482+ spin_lock(&spl->spin);
20483+ list_add(list, &spl->head);
20484+ spin_unlock(&spl->spin);
20485+}
20486+
20487+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
20488+{
20489+ spin_lock(&spl->spin);
20490+ list_del(list);
20491+ spin_unlock(&spl->spin);
20492+}
20493+
4a4d8108
AM
20494+static inline void au_spl_del_rcu(struct list_head *list,
20495+ struct au_splhead *spl)
20496+{
20497+ spin_lock(&spl->spin);
20498+ list_del_rcu(list);
20499+ spin_unlock(&spl->spin);
20500+}
20501+
1facf9fc 20502+#endif /* __KERNEL__ */
20503+#endif /* __AUFS_SPL_H__ */
e49829fe
JR
20504--- /dev/null
20505+++ linux-2.6/fs/aufs/super.c 2010-10-24 13:42:19.000000000 +0200
20506@@ -0,0 +1,867 @@
1facf9fc 20507+/*
4a4d8108 20508+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20509+ *
20510+ * This program, aufs is free software; you can redistribute it and/or modify
20511+ * it under the terms of the GNU General Public License as published by
20512+ * the Free Software Foundation; either version 2 of the License, or
20513+ * (at your option) any later version.
dece6358
AM
20514+ *
20515+ * This program is distributed in the hope that it will be useful,
20516+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20517+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20518+ * GNU General Public License for more details.
20519+ *
20520+ * You should have received a copy of the GNU General Public License
20521+ * along with this program; if not, write to the Free Software
20522+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20523+ */
20524+
20525+/*
20526+ * mount and super_block operations
20527+ */
20528+
20529+#include <linux/buffer_head.h>
e49829fe 20530+#include <linux/jiffies.h>
dece6358 20531+#include <linux/module.h>
1facf9fc 20532+#include <linux/seq_file.h>
20533+#include <linux/statfs.h>
20534+#include "aufs.h"
20535+
20536+/*
20537+ * super_operations
20538+ */
20539+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
20540+{
20541+ struct au_icntnr *c;
20542+
20543+ c = au_cache_alloc_icntnr();
20544+ if (c) {
1facf9fc 20545+ c->vfs_inode.i_version = 1; /* sigen(sb); */
20546+ c->iinfo.ii_hinode = NULL;
20547+ return &c->vfs_inode;
20548+ }
20549+ return NULL;
20550+}
20551+
20552+static void aufs_destroy_inode(struct inode *inode)
20553+{
20554+ au_iinfo_fin(inode);
20555+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
20556+}
20557+
20558+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
20559+{
20560+ struct inode *inode;
20561+ int err;
20562+
20563+ inode = iget_locked(sb, ino);
20564+ if (unlikely(!inode)) {
20565+ inode = ERR_PTR(-ENOMEM);
20566+ goto out;
20567+ }
20568+ if (!(inode->i_state & I_NEW))
20569+ goto out;
20570+
20571+ err = au_xigen_new(inode);
20572+ if (!err)
20573+ err = au_iinfo_init(inode);
20574+ if (!err)
20575+ inode->i_version++;
20576+ else {
20577+ iget_failed(inode);
20578+ inode = ERR_PTR(err);
20579+ }
20580+
4f0767ce 20581+out:
1facf9fc 20582+ /* never return NULL */
20583+ AuDebugOn(!inode);
20584+ AuTraceErrPtr(inode);
20585+ return inode;
20586+}
20587+
20588+/* lock free root dinfo */
20589+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
20590+{
20591+ int err;
20592+ aufs_bindex_t bindex, bend;
20593+ struct path path;
4a4d8108 20594+ struct au_hdentry *hdp;
1facf9fc 20595+ struct au_branch *br;
20596+
20597+ err = 0;
20598+ bend = au_sbend(sb);
4a4d8108 20599+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 20600+ for (bindex = 0; !err && bindex <= bend; bindex++) {
20601+ br = au_sbr(sb, bindex);
20602+ path.mnt = br->br_mnt;
4a4d8108 20603+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 20604+ err = au_seq_path(seq, &path);
20605+ if (err > 0)
20606+ err = seq_printf(seq, "=%s",
20607+ au_optstr_br_perm(br->br_perm));
20608+ if (!err && bindex != bend)
20609+ err = seq_putc(seq, ':');
20610+ }
20611+
20612+ return err;
20613+}
20614+
20615+static void au_show_wbr_create(struct seq_file *m, int v,
20616+ struct au_sbinfo *sbinfo)
20617+{
20618+ const char *pat;
20619+
dece6358
AM
20620+ AuRwMustAnyLock(&sbinfo->si_rwsem);
20621+
1facf9fc 20622+ seq_printf(m, ",create=");
20623+ pat = au_optstr_wbr_create(v);
20624+ switch (v) {
20625+ case AuWbrCreate_TDP:
20626+ case AuWbrCreate_RR:
20627+ case AuWbrCreate_MFS:
20628+ case AuWbrCreate_PMFS:
20629+ seq_printf(m, pat);
20630+ break;
20631+ case AuWbrCreate_MFSV:
20632+ seq_printf(m, /*pat*/"mfs:%lu",
e49829fe
JR
20633+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
20634+ / MSEC_PER_SEC);
1facf9fc 20635+ break;
20636+ case AuWbrCreate_PMFSV:
20637+ seq_printf(m, /*pat*/"pmfs:%lu",
e49829fe
JR
20638+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
20639+ / MSEC_PER_SEC);
1facf9fc 20640+ break;
20641+ case AuWbrCreate_MFSRR:
20642+ seq_printf(m, /*pat*/"mfsrr:%llu",
20643+ sbinfo->si_wbr_mfs.mfsrr_watermark);
20644+ break;
20645+ case AuWbrCreate_MFSRRV:
20646+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
20647+ sbinfo->si_wbr_mfs.mfsrr_watermark,
e49829fe
JR
20648+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
20649+ / MSEC_PER_SEC);
1facf9fc 20650+ break;
20651+ }
20652+}
20653+
20654+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
20655+{
20656+#ifdef CONFIG_SYSFS
20657+ return 0;
20658+#else
20659+ int err;
20660+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
20661+ aufs_bindex_t bindex, brid;
20662+ struct super_block *sb;
20663+ struct qstr *name;
20664+ struct file *f;
20665+ struct dentry *d, *h_root;
4a4d8108 20666+ struct au_hdentry *hdp;
1facf9fc 20667+
dece6358
AM
20668+ AuRwMustAnyLock(&sbinfo->si_rwsem);
20669+
1facf9fc 20670+ err = 0;
20671+ sb = mnt->mnt_sb;
20672+ f = au_sbi(sb)->si_xib;
20673+ if (!f)
20674+ goto out;
20675+
20676+ /* stop printing the default xino path on the first writable branch */
20677+ h_root = NULL;
20678+ brid = au_xino_brid(sb);
20679+ if (brid >= 0) {
20680+ bindex = au_br_index(sb, brid);
4a4d8108
AM
20681+ hdp = au_di(sb->s_root)->di_hdentry;
20682+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 20683+ }
20684+ d = f->f_dentry;
20685+ name = &d->d_name;
20686+ /* safe ->d_parent because the file is unlinked */
20687+ if (d->d_parent == h_root
20688+ && name->len == len
20689+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
20690+ goto out;
20691+
20692+ seq_puts(seq, ",xino=");
20693+ err = au_xino_path(seq, f);
20694+
4f0767ce 20695+out:
1facf9fc 20696+ return err;
20697+#endif
20698+}
20699+
20700+/* seq_file will re-call me in case of too long string */
20701+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
20702+{
20703+ int err, n;
20704+ unsigned int mnt_flags, v;
20705+ struct super_block *sb;
20706+ struct au_sbinfo *sbinfo;
20707+
20708+#define AuBool(name, str) do { \
20709+ v = au_opt_test(mnt_flags, name); \
20710+ if (v != au_opt_test(AuOpt_Def, name)) \
20711+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
20712+} while (0)
20713+
20714+#define AuStr(name, str) do { \
20715+ v = mnt_flags & AuOptMask_##name; \
20716+ if (v != (AuOpt_Def & AuOptMask_##name)) \
20717+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
20718+} while (0)
20719+
20720+#define AuUInt(name, str, val) do { \
20721+ if (val != AUFS_##name##_DEF) \
20722+ seq_printf(m, "," #str "=%u", val); \
20723+} while (0)
20724+
20725+ /* lock free root dinfo */
20726+ sb = mnt->mnt_sb;
20727+ si_noflush_read_lock(sb);
20728+ sbinfo = au_sbi(sb);
20729+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
20730+
20731+ mnt_flags = au_mntflags(sb);
20732+ if (au_opt_test(mnt_flags, XINO)) {
20733+ err = au_show_xino(m, mnt);
20734+ if (unlikely(err))
20735+ goto out;
20736+ } else
20737+ seq_puts(m, ",noxino");
20738+
20739+ AuBool(TRUNC_XINO, trunc_xino);
20740+ AuStr(UDBA, udba);
dece6358 20741+ AuBool(SHWH, shwh);
1facf9fc 20742+ AuBool(PLINK, plink);
4a4d8108 20743+ AuBool(DIO, dio);
1facf9fc 20744+ /* AuBool(DIRPERM1, dirperm1); */
20745+ /* AuBool(REFROF, refrof); */
20746+
20747+ v = sbinfo->si_wbr_create;
20748+ if (v != AuWbrCreate_Def)
20749+ au_show_wbr_create(m, v, sbinfo);
20750+
20751+ v = sbinfo->si_wbr_copyup;
20752+ if (v != AuWbrCopyup_Def)
20753+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
20754+
20755+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
20756+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
20757+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
20758+
20759+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
20760+
e49829fe 20761+ n = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
1facf9fc 20762+ AuUInt(RDCACHE, rdcache, n);
20763+
20764+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
20765+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
20766+
20767+ AuBool(SUM, sum);
20768+ /* AuBool(SUM_W, wsum); */
20769+ AuBool(WARN_PERM, warn_perm);
20770+ AuBool(VERBOSE, verbose);
20771+
4f0767ce 20772+out:
1facf9fc 20773+ /* be sure to print "br:" last */
20774+ if (!sysaufs_brs) {
20775+ seq_puts(m, ",br:");
20776+ au_show_brs(m, sb);
20777+ }
20778+ si_read_unlock(sb);
20779+ return 0;
20780+
1facf9fc 20781+#undef AuBool
20782+#undef AuStr
4a4d8108 20783+#undef AuUInt
1facf9fc 20784+}
20785+
20786+/* ---------------------------------------------------------------------- */
20787+
20788+/* sum mode which returns the summation for statfs(2) */
20789+
20790+static u64 au_add_till_max(u64 a, u64 b)
20791+{
20792+ u64 old;
20793+
20794+ old = a;
20795+ a += b;
20796+ if (old < a)
20797+ return a;
20798+ return ULLONG_MAX;
20799+}
20800+
20801+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
20802+{
20803+ int err;
20804+ u64 blocks, bfree, bavail, files, ffree;
20805+ aufs_bindex_t bend, bindex, i;
20806+ unsigned char shared;
953406b4 20807+ struct path h_path;
1facf9fc 20808+ struct super_block *h_sb;
20809+
20810+ blocks = 0;
20811+ bfree = 0;
20812+ bavail = 0;
20813+ files = 0;
20814+ ffree = 0;
20815+
20816+ err = 0;
20817+ bend = au_sbend(sb);
20818+ for (bindex = bend; bindex >= 0; bindex--) {
953406b4
AM
20819+ h_path.mnt = au_sbr_mnt(sb, bindex);
20820+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 20821+ shared = 0;
20822+ for (i = bindex + 1; !shared && i <= bend; i++)
20823+ shared = (au_sbr_sb(sb, i) == h_sb);
20824+ if (shared)
20825+ continue;
20826+
20827+ /* sb->s_root for NFS is unreliable */
953406b4
AM
20828+ h_path.dentry = h_path.mnt->mnt_root;
20829+ err = vfs_statfs(&h_path, buf);
1facf9fc 20830+ if (unlikely(err))
20831+ goto out;
20832+
20833+ blocks = au_add_till_max(blocks, buf->f_blocks);
20834+ bfree = au_add_till_max(bfree, buf->f_bfree);
20835+ bavail = au_add_till_max(bavail, buf->f_bavail);
20836+ files = au_add_till_max(files, buf->f_files);
20837+ ffree = au_add_till_max(ffree, buf->f_ffree);
20838+ }
20839+
20840+ buf->f_blocks = blocks;
20841+ buf->f_bfree = bfree;
20842+ buf->f_bavail = bavail;
20843+ buf->f_files = files;
20844+ buf->f_ffree = ffree;
20845+
4f0767ce 20846+out:
1facf9fc 20847+ return err;
20848+}
20849+
20850+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
20851+{
20852+ int err;
953406b4 20853+ struct path h_path;
1facf9fc 20854+ struct super_block *sb;
20855+
20856+ /* lock free root dinfo */
20857+ sb = dentry->d_sb;
20858+ si_noflush_read_lock(sb);
953406b4 20859+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 20860+ /* sb->s_root for NFS is unreliable */
953406b4
AM
20861+ h_path.mnt = au_sbr_mnt(sb, 0);
20862+ h_path.dentry = h_path.mnt->mnt_root;
20863+ err = vfs_statfs(&h_path, buf);
20864+ } else
1facf9fc 20865+ err = au_statfs_sum(sb, buf);
20866+ si_read_unlock(sb);
20867+
20868+ if (!err) {
20869+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 20870+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 20871+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
20872+ }
20873+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
20874+
20875+ return err;
20876+}
20877+
20878+/* ---------------------------------------------------------------------- */
20879+
1facf9fc 20880+/* final actions when unmounting a file system */
20881+static void aufs_put_super(struct super_block *sb)
20882+{
20883+ struct au_sbinfo *sbinfo;
20884+
20885+ sbinfo = au_sbi(sb);
20886+ if (!sbinfo)
20887+ return;
20888+
1facf9fc 20889+ dbgaufs_si_fin(sbinfo);
20890+ kobject_put(&sbinfo->si_kobj);
20891+}
20892+
20893+/* ---------------------------------------------------------------------- */
20894+
20895+/*
20896+ * refresh dentry and inode at remount time.
20897+ */
20898+static int do_refresh(struct dentry *dentry, mode_t type,
20899+ unsigned int dir_flags)
20900+{
20901+ int err;
20902+ struct dentry *parent;
20903+
20904+ di_write_lock_child(dentry);
20905+ parent = dget_parent(dentry);
20906+ di_read_lock_parent(parent, AuLock_IR);
20907+
20908+ /* returns the number of positive dentries */
20909+ err = au_refresh_hdentry(dentry, type);
20910+ if (err >= 0) {
20911+ struct inode *inode = dentry->d_inode;
20912+ err = au_refresh_hinode(inode, dentry);
20913+ if (!err && type == S_IFDIR)
4a4d8108 20914+ au_hn_reset(inode, dir_flags);
1facf9fc 20915+ }
20916+ if (unlikely(err))
4a4d8108
AM
20917+ pr_err("unrecoverable error %d, %.*s\n",
20918+ err, AuDLNPair(dentry));
1facf9fc 20919+
20920+ di_read_unlock(parent, AuLock_IR);
20921+ dput(parent);
20922+ di_write_unlock(dentry);
20923+
20924+ return err;
20925+}
20926+
20927+static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
20928+{
20929+ return S_ISDIR(dentry->d_inode->i_mode);
20930+}
20931+
20932+/* gave up consolidating with refresh_nondir() */
20933+static int refresh_dir(struct dentry *root, unsigned int sigen)
20934+{
20935+ int err, i, j, ndentry, e;
20936+ struct au_dcsub_pages dpages;
20937+ struct au_dpage *dpage;
20938+ struct dentry **dentries;
20939+ struct inode *inode;
20940+ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
20941+
20942+ err = 0;
20943+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20944+ if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20945+ ii_write_lock_child(inode);
20946+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
20947+ ii_write_unlock(inode);
20948+ if (unlikely(e)) {
20949+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
20950+ if (!err)
20951+ err = e;
20952+ /* go on even if err */
20953+ }
20954+ }
20955+
20956+ e = au_dpages_init(&dpages, GFP_NOFS);
20957+ if (unlikely(e)) {
20958+ if (!err)
20959+ err = e;
20960+ goto out;
20961+ }
20962+ e = au_dcsub_pages(&dpages, root, test_dir, NULL);
20963+ if (unlikely(e)) {
20964+ if (!err)
20965+ err = e;
20966+ goto out_dpages;
20967+ }
20968+
20969+ for (i = 0; !e && i < dpages.ndpage; i++) {
20970+ dpage = dpages.dpages + i;
20971+ dentries = dpage->dentries;
20972+ ndentry = dpage->ndentry;
20973+ for (j = 0; !e && j < ndentry; j++) {
20974+ struct dentry *d;
20975+
20976+ d = dentries[j];
20977+ au_dbg_verify_dir_parent(d, sigen);
20978+ if (au_digen(d) != sigen) {
20979+ e = do_refresh(d, S_IFDIR, flags);
20980+ if (unlikely(e && !err))
20981+ err = e;
20982+ /* break on err */
20983+ }
20984+ }
20985+ }
20986+
4f0767ce 20987+out_dpages:
1facf9fc 20988+ au_dpages_free(&dpages);
4f0767ce 20989+out:
1facf9fc 20990+ return err;
20991+}
20992+
20993+static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
20994+{
20995+ return !S_ISDIR(dentry->d_inode->i_mode);
20996+}
20997+
20998+static int refresh_nondir(struct dentry *root, unsigned int sigen,
20999+ int do_dentry)
21000+{
21001+ int err, i, j, ndentry, e;
21002+ struct au_dcsub_pages dpages;
21003+ struct au_dpage *dpage;
21004+ struct dentry **dentries;
21005+ struct inode *inode;
21006+
21007+ err = 0;
21008+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
21009+ if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
21010+ ii_write_lock_child(inode);
21011+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
21012+ ii_write_unlock(inode);
21013+ if (unlikely(e)) {
21014+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
21015+ if (!err)
21016+ err = e;
21017+ /* go on even if err */
21018+ }
21019+ }
21020+
21021+ if (!do_dentry)
21022+ goto out;
21023+
21024+ e = au_dpages_init(&dpages, GFP_NOFS);
21025+ if (unlikely(e)) {
21026+ if (!err)
21027+ err = e;
21028+ goto out;
21029+ }
21030+ e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
21031+ if (unlikely(e)) {
21032+ if (!err)
21033+ err = e;
21034+ goto out_dpages;
21035+ }
21036+
21037+ for (i = 0; i < dpages.ndpage; i++) {
21038+ dpage = dpages.dpages + i;
21039+ dentries = dpage->dentries;
21040+ ndentry = dpage->ndentry;
21041+ for (j = 0; j < ndentry; j++) {
21042+ struct dentry *d;
21043+
21044+ d = dentries[j];
21045+ au_dbg_verify_nondir_parent(d, sigen);
21046+ inode = d->d_inode;
21047+ if (inode && au_digen(d) != sigen) {
21048+ e = do_refresh(d, inode->i_mode & S_IFMT,
21049+ /*dir_flags*/0);
21050+ if (unlikely(e && !err))
21051+ err = e;
21052+ /* go on even err */
21053+ }
21054+ }
21055+ }
21056+
4f0767ce 21057+out_dpages:
1facf9fc 21058+ au_dpages_free(&dpages);
4f0767ce 21059+out:
1facf9fc 21060+ return err;
21061+}
21062+
21063+static void au_remount_refresh(struct super_block *sb, unsigned int flags)
21064+{
21065+ int err;
21066+ unsigned int sigen;
21067+ struct au_sbinfo *sbinfo;
21068+ struct dentry *root;
21069+ struct inode *inode;
21070+
21071+ au_sigen_inc(sb);
21072+ sigen = au_sigen(sb);
21073+ sbinfo = au_sbi(sb);
21074+ au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
21075+
21076+ root = sb->s_root;
21077+ DiMustNoWaiters(root);
21078+ inode = root->d_inode;
21079+ IiMustNoWaiters(inode);
4a4d8108 21080+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 21081+ di_write_unlock(root);
21082+
21083+ err = refresh_dir(root, sigen);
21084+ if (unlikely(err)) {
21085+ au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
4a4d8108
AM
21086+ pr_warning("Refreshing directories failed, ignored (%d)\n",
21087+ err);
1facf9fc 21088+ }
21089+
21090+ if (au_ftest_opts(flags, REFRESH_NONDIR)) {
21091+ err = refresh_nondir(root, sigen, !err);
21092+ if (unlikely(err))
4a4d8108
AM
21093+ pr_warning("Refreshing non-directories failed, ignored"
21094+ "(%d)\n", err);
1facf9fc 21095+ }
21096+
21097+ /* aufs_write_lock() calls ..._child() */
21098+ di_write_lock_child(root);
21099+ au_cpup_attr_all(root->d_inode, /*force*/1);
21100+}
21101+
21102+/* stop extra interpretation of errno in mount(8), and strange error messages */
21103+static int cvt_err(int err)
21104+{
21105+ AuTraceErr(err);
21106+
21107+ switch (err) {
21108+ case -ENOENT:
21109+ case -ENOTDIR:
21110+ case -EEXIST:
21111+ case -EIO:
21112+ err = -EINVAL;
21113+ }
21114+ return err;
21115+}
21116+
21117+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
21118+{
4a4d8108
AM
21119+ int err, do_dx;
21120+ unsigned int mntflags;
1facf9fc 21121+ struct au_opts opts;
21122+ struct dentry *root;
21123+ struct inode *inode;
21124+ struct au_sbinfo *sbinfo;
21125+
21126+ err = 0;
21127+ root = sb->s_root;
21128+ if (!data || !*data) {
e49829fe
JR
21129+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21130+ if (!err) {
21131+ di_write_lock_child(root);
21132+ err = au_opts_verify(sb, *flags, /*pending*/0);
21133+ aufs_write_unlock(root);
21134+ }
1facf9fc 21135+ goto out;
21136+ }
21137+
21138+ err = -ENOMEM;
21139+ memset(&opts, 0, sizeof(opts));
21140+ opts.opt = (void *)__get_free_page(GFP_NOFS);
21141+ if (unlikely(!opts.opt))
21142+ goto out;
21143+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
21144+ opts.flags = AuOpts_REMOUNT;
21145+ opts.sb_flags = *flags;
21146+
21147+ /* parse it before aufs lock */
21148+ err = au_opts_parse(sb, data, &opts);
21149+ if (unlikely(err))
21150+ goto out_opts;
21151+
21152+ sbinfo = au_sbi(sb);
21153+ inode = root->d_inode;
21154+ mutex_lock(&inode->i_mutex);
e49829fe
JR
21155+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21156+ if (unlikely(err))
21157+ goto out_mtx;
21158+ di_write_lock_child(root);
1facf9fc 21159+
21160+ /* au_opts_remount() may return an error */
21161+ err = au_opts_remount(sb, &opts);
21162+ au_opts_free(&opts);
21163+
21164+ if (au_ftest_opts(opts.flags, REFRESH_DIR)
21165+ || au_ftest_opts(opts.flags, REFRESH_NONDIR))
21166+ au_remount_refresh(sb, opts.flags);
21167+
4a4d8108
AM
21168+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
21169+ mntflags = au_mntflags(sb);
21170+ do_dx = !!au_opt_test(mntflags, DIO);
21171+ au_dy_arefresh(do_dx);
21172+ }
21173+
1facf9fc 21174+ aufs_write_unlock(root);
953406b4 21175+
e49829fe
JR
21176+out_mtx:
21177+ mutex_unlock(&inode->i_mutex);
4f0767ce 21178+out_opts:
1facf9fc 21179+ free_page((unsigned long)opts.opt);
4f0767ce 21180+out:
1facf9fc 21181+ err = cvt_err(err);
21182+ AuTraceErr(err);
21183+ return err;
21184+}
21185+
4a4d8108 21186+static const struct super_operations aufs_sop = {
1facf9fc 21187+ .alloc_inode = aufs_alloc_inode,
21188+ .destroy_inode = aufs_destroy_inode,
b752ccd1 21189+ /* always deleting, no clearing */
1facf9fc 21190+ .drop_inode = generic_delete_inode,
21191+ .show_options = aufs_show_options,
21192+ .statfs = aufs_statfs,
21193+ .put_super = aufs_put_super,
21194+ .remount_fs = aufs_remount_fs
21195+};
21196+
21197+/* ---------------------------------------------------------------------- */
21198+
21199+static int alloc_root(struct super_block *sb)
21200+{
21201+ int err;
21202+ struct inode *inode;
21203+ struct dentry *root;
21204+
21205+ err = -ENOMEM;
21206+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
21207+ err = PTR_ERR(inode);
21208+ if (IS_ERR(inode))
21209+ goto out;
21210+
21211+ inode->i_op = &aufs_dir_iop;
21212+ inode->i_fop = &aufs_dir_fop;
21213+ inode->i_mode = S_IFDIR;
21214+ inode->i_nlink = 2;
21215+ unlock_new_inode(inode);
21216+
21217+ root = d_alloc_root(inode);
21218+ if (unlikely(!root))
21219+ goto out_iput;
21220+ err = PTR_ERR(root);
21221+ if (IS_ERR(root))
21222+ goto out_iput;
21223+
4a4d8108 21224+ err = au_di_init(root);
1facf9fc 21225+ if (!err) {
21226+ sb->s_root = root;
21227+ return 0; /* success */
21228+ }
21229+ dput(root);
21230+ goto out; /* do not iput */
21231+
4f0767ce 21232+out_iput:
1facf9fc 21233+ iget_failed(inode);
4f0767ce 21234+out:
1facf9fc 21235+ return err;
21236+
21237+}
21238+
21239+static int aufs_fill_super(struct super_block *sb, void *raw_data,
21240+ int silent __maybe_unused)
21241+{
21242+ int err;
21243+ struct au_opts opts;
21244+ struct dentry *root;
21245+ struct inode *inode;
21246+ char *arg = raw_data;
21247+
21248+ if (unlikely(!arg || !*arg)) {
21249+ err = -EINVAL;
4a4d8108 21250+ pr_err("no arg\n");
1facf9fc 21251+ goto out;
21252+ }
21253+
21254+ err = -ENOMEM;
21255+ memset(&opts, 0, sizeof(opts));
21256+ opts.opt = (void *)__get_free_page(GFP_NOFS);
21257+ if (unlikely(!opts.opt))
21258+ goto out;
21259+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
21260+ opts.sb_flags = sb->s_flags;
21261+
21262+ err = au_si_alloc(sb);
21263+ if (unlikely(err))
21264+ goto out_opts;
21265+
21266+ /* all timestamps always follow the ones on the branch */
21267+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
21268+ sb->s_op = &aufs_sop;
21269+ sb->s_magic = AUFS_SUPER_MAGIC;
21270+ sb->s_maxbytes = 0;
21271+ au_export_init(sb);
21272+
21273+ err = alloc_root(sb);
21274+ if (unlikely(err)) {
21275+ si_write_unlock(sb);
21276+ goto out_info;
21277+ }
21278+ root = sb->s_root;
21279+ inode = root->d_inode;
21280+
21281+ /*
21282+ * actually we can parse options regardless aufs lock here.
21283+ * but at remount time, parsing must be done before aufs lock.
21284+ * so we follow the same rule.
21285+ */
21286+ ii_write_lock_parent(inode);
21287+ aufs_write_unlock(root);
21288+ err = au_opts_parse(sb, arg, &opts);
21289+ if (unlikely(err))
21290+ goto out_root;
21291+
21292+ /* lock vfs_inode first, then aufs. */
21293+ mutex_lock(&inode->i_mutex);
1facf9fc 21294+ aufs_write_lock(root);
21295+ err = au_opts_mount(sb, &opts);
21296+ au_opts_free(&opts);
1facf9fc 21297+ aufs_write_unlock(root);
21298+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
21299+ if (!err)
21300+ goto out_opts; /* success */
1facf9fc 21301+
4f0767ce 21302+out_root:
1facf9fc 21303+ dput(root);
21304+ sb->s_root = NULL;
4f0767ce 21305+out_info:
1facf9fc 21306+ kobject_put(&au_sbi(sb)->si_kobj);
21307+ sb->s_fs_info = NULL;
4f0767ce 21308+out_opts:
1facf9fc 21309+ free_page((unsigned long)opts.opt);
4f0767ce 21310+out:
1facf9fc 21311+ AuTraceErr(err);
21312+ err = cvt_err(err);
21313+ AuTraceErr(err);
21314+ return err;
21315+}
21316+
21317+/* ---------------------------------------------------------------------- */
21318+
21319+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
21320+ const char *dev_name __maybe_unused, void *raw_data,
21321+ struct vfsmount *mnt)
21322+{
21323+ int err;
21324+ struct super_block *sb;
21325+
21326+ /* all timestamps always follow the ones on the branch */
21327+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
21328+ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
21329+ if (!err) {
21330+ sb = mnt->mnt_sb;
e49829fe 21331+ si_write_lock(sb, !AuLock_FLUSH);
1facf9fc 21332+ sysaufs_brs_add(sb, 0);
21333+ si_write_unlock(sb);
e49829fe 21334+ au_sbilist_add(sb);
1facf9fc 21335+ }
21336+ return err;
21337+}
21338+
e49829fe
JR
21339+static void aufs_kill_sb(struct super_block *sb)
21340+{
21341+ struct au_sbinfo *sbinfo;
21342+
21343+ sbinfo = au_sbi(sb);
21344+ if (sbinfo) {
21345+ au_sbilist_del(sb);
21346+ aufs_write_lock(sb->s_root);
21347+ if (sbinfo->si_wbr_create_ops->fin)
21348+ sbinfo->si_wbr_create_ops->fin(sb);
21349+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
21350+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
21351+ au_remount_refresh(sb, /*flags*/0);
21352+ }
21353+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
21354+ au_plink_put(sb, /*verbose*/1);
21355+ au_xino_clr(sb);
21356+ aufs_write_unlock(sb->s_root);
21357+
21358+ au_plink_maint_leave(sbinfo);
21359+ au_nwt_flush(&sbinfo->si_nowait);
21360+ }
21361+ generic_shutdown_super(sb);
21362+}
21363+
1facf9fc 21364+struct file_system_type aufs_fs_type = {
21365+ .name = AUFS_FSTYPE,
21366+ .fs_flags =
21367+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
21368+ | FS_REVAL_DOT, /* for NFS branch and udba */
21369+ .get_sb = aufs_get_sb,
e49829fe 21370+ .kill_sb = aufs_kill_sb,
1facf9fc 21371+ /* no need to __module_get() and module_put(). */
21372+ .owner = THIS_MODULE,
21373+};
e49829fe
JR
21374--- /dev/null
21375+++ linux-2.6/fs/aufs/super.h 2010-10-24 11:42:36.000000000 +0200
21376@@ -0,0 +1,488 @@
1facf9fc 21377+/*
4a4d8108 21378+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21379+ *
21380+ * This program, aufs is free software; you can redistribute it and/or modify
21381+ * it under the terms of the GNU General Public License as published by
21382+ * the Free Software Foundation; either version 2 of the License, or
21383+ * (at your option) any later version.
dece6358
AM
21384+ *
21385+ * This program is distributed in the hope that it will be useful,
21386+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21387+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21388+ * GNU General Public License for more details.
21389+ *
21390+ * You should have received a copy of the GNU General Public License
21391+ * along with this program; if not, write to the Free Software
21392+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21393+ */
21394+
21395+/*
21396+ * super_block operations
21397+ */
21398+
21399+#ifndef __AUFS_SUPER_H__
21400+#define __AUFS_SUPER_H__
21401+
21402+#ifdef __KERNEL__
21403+
21404+#include <linux/fs.h>
1facf9fc 21405+#include <linux/aufs_type.h>
21406+#include "rwsem.h"
21407+#include "spl.h"
21408+#include "wkq.h"
21409+
21410+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
21411+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
21412+ loff_t *);
21413+
21414+/* policies to select one among multiple writable branches */
21415+struct au_wbr_copyup_operations {
21416+ int (*copyup)(struct dentry *dentry);
21417+};
21418+
21419+struct au_wbr_create_operations {
21420+ int (*create)(struct dentry *dentry, int isdir);
21421+ int (*init)(struct super_block *sb);
21422+ int (*fin)(struct super_block *sb);
21423+};
21424+
21425+struct au_wbr_mfs {
21426+ struct mutex mfs_lock; /* protect this structure */
21427+ unsigned long mfs_jiffy;
21428+ unsigned long mfs_expire;
21429+ aufs_bindex_t mfs_bindex;
21430+
21431+ unsigned long long mfsrr_bytes;
21432+ unsigned long long mfsrr_watermark;
21433+};
21434+
1facf9fc 21435+struct au_branch;
21436+struct au_sbinfo {
21437+ /* nowait tasks in the system-wide workqueue */
21438+ struct au_nowait_tasks si_nowait;
21439+
b752ccd1
AM
21440+ /*
21441+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
21442+ * rwsem for au_sbinfo is necessary.
21443+ */
dece6358 21444+ struct au_rwsem si_rwsem;
1facf9fc 21445+
b752ccd1
AM
21446+ /* prevent recursive locking in deleting inode */
21447+ struct {
21448+ unsigned long *bitmap;
21449+ spinlock_t tree_lock;
21450+ struct radix_tree_root tree;
21451+ } au_si_pid;
21452+
1facf9fc 21453+ /* branch management */
21454+ unsigned int si_generation;
21455+
21456+ /* see above flags */
21457+ unsigned char au_si_status;
21458+
21459+ aufs_bindex_t si_bend;
21460+ aufs_bindex_t si_last_br_id;
21461+ struct au_branch **si_branch;
21462+
21463+ /* policy to select a writable branch */
21464+ unsigned char si_wbr_copyup;
21465+ unsigned char si_wbr_create;
21466+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
21467+ struct au_wbr_create_operations *si_wbr_create_ops;
21468+
21469+ /* round robin */
21470+ atomic_t si_wbr_rr_next;
21471+
21472+ /* most free space */
21473+ struct au_wbr_mfs si_wbr_mfs;
21474+
21475+ /* mount flags */
21476+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
21477+ unsigned int si_mntflags;
21478+
21479+ /* external inode number (bitmap and translation table) */
21480+ au_readf_t si_xread;
21481+ au_writef_t si_xwrite;
21482+ struct file *si_xib;
21483+ struct mutex si_xib_mtx; /* protect xib members */
21484+ unsigned long *si_xib_buf;
21485+ unsigned long si_xib_last_pindex;
21486+ int si_xib_next_bit;
21487+ aufs_bindex_t si_xino_brid;
21488+ /* reserved for future use */
21489+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
21490+
21491+#ifdef CONFIG_AUFS_EXPORT
21492+ /* i_generation */
21493+ struct file *si_xigen;
21494+ atomic_t si_xigen_next;
21495+#endif
21496+
21497+ /* vdir parameters */
e49829fe 21498+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 21499+ unsigned int si_rdblk; /* deblk size */
21500+ unsigned int si_rdhash; /* hash size */
21501+
21502+ /*
21503+ * If the number of whiteouts are larger than si_dirwh, leave all of
21504+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
21505+ * future fsck.aufs or kernel thread will remove them later.
21506+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
21507+ */
21508+ unsigned int si_dirwh;
21509+
21510+ /*
21511+ * rename(2) a directory with all children.
21512+ */
21513+ /* reserved for future use */
21514+ /* int si_rendir; */
21515+
21516+ /* pseudo_link list */
21517+ struct au_splhead si_plink;
21518+ wait_queue_head_t si_plink_wq;
4a4d8108 21519+ spinlock_t si_plink_maint_lock;
e49829fe 21520+ pid_t si_plink_maint_pid;
1facf9fc 21521+
21522+ /*
21523+ * sysfs and lifetime management.
21524+ * this is not a small structure and it may be a waste of memory in case
21525+ * of sysfs is disabled, particulary when many aufs-es are mounted.
21526+ * but using sysfs is majority.
21527+ */
21528+ struct kobject si_kobj;
21529+#ifdef CONFIG_DEBUG_FS
21530+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
21531+#ifdef CONFIG_AUFS_EXPORT
21532+ struct dentry *si_dbgaufs_xigen;
21533+#endif
21534+#endif
21535+
e49829fe
JR
21536+#ifdef CONFIG_AUFS_SBILIST
21537+ struct list_head si_list;
21538+#endif
21539+
1facf9fc 21540+ /* dirty, necessary for unmounting, sysfs and sysrq */
21541+ struct super_block *si_sb;
21542+};
21543+
dece6358
AM
21544+/* sbinfo status flags */
21545+/*
21546+ * set true when refresh_dirs() failed at remount time.
21547+ * then try refreshing dirs at access time again.
21548+ * if it is false, refreshing dirs at access time is unnecesary
21549+ */
21550+#define AuSi_FAILED_REFRESH_DIRS 1
dece6358
AM
21551+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
21552+ unsigned int flag)
21553+{
21554+ AuRwMustAnyLock(&sbi->si_rwsem);
21555+ return sbi->au_si_status & flag;
21556+}
21557+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
21558+#define au_fset_si(sbinfo, name) do { \
21559+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
21560+ (sbinfo)->au_si_status |= AuSi_##name; \
21561+} while (0)
21562+#define au_fclr_si(sbinfo, name) do { \
21563+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
21564+ (sbinfo)->au_si_status &= ~AuSi_##name; \
21565+} while (0)
21566+
1facf9fc 21567+/* ---------------------------------------------------------------------- */
21568+
21569+/* policy to select one among writable branches */
4a4d8108
AM
21570+#define AuWbrCopyup(sbinfo, ...) \
21571+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
21572+#define AuWbrCreate(sbinfo, ...) \
21573+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 21574+
21575+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
21576+#define AuLock_DW 1 /* write-lock dentry */
21577+#define AuLock_IR (1 << 1) /* read-lock inode */
21578+#define AuLock_IW (1 << 2) /* write-lock inode */
21579+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
21580+#define AuLock_DIR (1 << 4) /* target is a dir */
e49829fe
JR
21581+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
21582+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
1facf9fc 21583+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
21584+#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
21585+#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
21586+
21587+/* ---------------------------------------------------------------------- */
21588+
21589+/* super.c */
21590+extern struct file_system_type aufs_fs_type;
21591+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
21592+
21593+/* sbinfo.c */
21594+void au_si_free(struct kobject *kobj);
21595+int au_si_alloc(struct super_block *sb);
21596+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
21597+
21598+unsigned int au_sigen_inc(struct super_block *sb);
21599+aufs_bindex_t au_new_br_id(struct super_block *sb);
21600+
e49829fe
JR
21601+int si_read_lock(struct super_block *sb, int flags);
21602+int si_write_lock(struct super_block *sb, int flags);
21603+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 21604+void aufs_read_unlock(struct dentry *dentry, int flags);
21605+void aufs_write_lock(struct dentry *dentry);
21606+void aufs_write_unlock(struct dentry *dentry);
e49829fe 21607+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 21608+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
21609+
b752ccd1
AM
21610+int si_pid_test_slow(struct super_block *sb);
21611+void si_pid_set_slow(struct super_block *sb);
21612+void si_pid_clr_slow(struct super_block *sb);
21613+
1facf9fc 21614+/* wbr_policy.c */
21615+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
21616+extern struct au_wbr_create_operations au_wbr_create_ops[];
21617+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
21618+
21619+/* ---------------------------------------------------------------------- */
21620+
21621+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
21622+{
21623+ return sb->s_fs_info;
21624+}
21625+
21626+/* ---------------------------------------------------------------------- */
21627+
21628+#ifdef CONFIG_AUFS_EXPORT
21629+void au_export_init(struct super_block *sb);
21630+
b752ccd1 21631+static inline int au_test_nfsd(void)
1facf9fc 21632+{
b752ccd1
AM
21633+ struct task_struct *tsk = current;
21634+
21635+ return (tsk->flags & PF_KTHREAD)
21636+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 21637+}
21638+
b752ccd1 21639+void au_xigen_inc(struct inode *inode);
1facf9fc 21640+int au_xigen_new(struct inode *inode);
21641+int au_xigen_set(struct super_block *sb, struct file *base);
21642+void au_xigen_clr(struct super_block *sb);
21643+
21644+static inline int au_busy_or_stale(void)
21645+{
b752ccd1 21646+ if (!au_test_nfsd())
1facf9fc 21647+ return -EBUSY;
21648+ return -ESTALE;
21649+}
21650+#else
4a4d8108 21651+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
21652+AuStubInt0(au_test_nfsd, void)
21653+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
21654+AuStubInt0(au_xigen_new, struct inode *inode)
21655+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
21656+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 21657+static inline int au_busy_or_stale(void)
21658+{
21659+ return -EBUSY;
21660+}
21661+#endif /* CONFIG_AUFS_EXPORT */
21662+
21663+/* ---------------------------------------------------------------------- */
21664+
e49829fe
JR
21665+#ifdef CONFIG_AUFS_SBILIST
21666+/* module.c */
21667+extern struct au_splhead au_sbilist;
21668+
21669+static inline void au_sbilist_init(void)
21670+{
21671+ au_spl_init(&au_sbilist);
21672+}
21673+
21674+static inline void au_sbilist_add(struct super_block *sb)
21675+{
21676+ au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
21677+}
21678+
21679+static inline void au_sbilist_del(struct super_block *sb)
21680+{
21681+ au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
21682+}
21683+#else
21684+AuStubVoid(au_sbilist_init, void)
21685+AuStubVoid(au_sbilist_add, struct super_block*)
21686+AuStubVoid(au_sbilist_del, struct super_block*)
21687+#endif
21688+
21689+/* ---------------------------------------------------------------------- */
21690+
1facf9fc 21691+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
21692+{
dece6358
AM
21693+ /*
21694+ * This function is a dynamic '__init' fucntion actually,
21695+ * so the tiny check for si_rwsem is unnecessary.
21696+ */
21697+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 21698+#ifdef CONFIG_DEBUG_FS
21699+ sbinfo->si_dbgaufs = NULL;
21700+ sbinfo->si_dbgaufs_xib = NULL;
21701+#ifdef CONFIG_AUFS_EXPORT
21702+ sbinfo->si_dbgaufs_xigen = NULL;
21703+#endif
21704+#endif
21705+}
21706+
21707+/* ---------------------------------------------------------------------- */
21708+
b752ccd1
AM
21709+static inline pid_t si_pid_bit(void)
21710+{
21711+ /* the origin of pid is 1, but the bitmap's is 0 */
21712+ return current->pid - 1;
21713+}
21714+
21715+static inline int si_pid_test(struct super_block *sb)
21716+{
21717+ pid_t bit = si_pid_bit();
21718+ if (bit < PID_MAX_DEFAULT)
21719+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21720+ else
21721+ return si_pid_test_slow(sb);
21722+}
21723+
21724+static inline void si_pid_set(struct super_block *sb)
21725+{
21726+ pid_t bit = si_pid_bit();
21727+ if (bit < PID_MAX_DEFAULT) {
21728+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21729+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21730+ /* smp_mb(); */
21731+ } else
21732+ si_pid_set_slow(sb);
21733+}
21734+
21735+static inline void si_pid_clr(struct super_block *sb)
21736+{
21737+ pid_t bit = si_pid_bit();
21738+ if (bit < PID_MAX_DEFAULT) {
21739+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21740+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21741+ /* smp_mb(); */
21742+ } else
21743+ si_pid_clr_slow(sb);
21744+}
21745+
21746+/* ---------------------------------------------------------------------- */
21747+
1facf9fc 21748+/* lock superblock. mainly for entry point functions */
21749+/*
b752ccd1
AM
21750+ * __si_read_lock, __si_write_lock,
21751+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 21752+ */
b752ccd1 21753+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 21754+
dece6358
AM
21755+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
21756+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
21757+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
21758+
b752ccd1
AM
21759+static inline void si_noflush_read_lock(struct super_block *sb)
21760+{
21761+ __si_read_lock(sb);
21762+ si_pid_set(sb);
21763+}
21764+
21765+static inline int si_noflush_read_trylock(struct super_block *sb)
21766+{
21767+ int locked = __si_read_trylock(sb);
21768+ if (locked)
21769+ si_pid_set(sb);
21770+ return locked;
21771+}
21772+
21773+static inline void si_noflush_write_lock(struct super_block *sb)
21774+{
21775+ __si_write_lock(sb);
21776+ si_pid_set(sb);
21777+}
21778+
21779+static inline int si_noflush_write_trylock(struct super_block *sb)
21780+{
21781+ int locked = __si_write_trylock(sb);
21782+ if (locked)
21783+ si_pid_set(sb);
21784+ return locked;
21785+}
21786+
e49829fe 21787+#if 0 /* unused */
1facf9fc 21788+static inline int si_read_trylock(struct super_block *sb, int flags)
21789+{
21790+ if (au_ftest_lock(flags, FLUSH))
21791+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21792+ return si_noflush_read_trylock(sb);
21793+}
e49829fe 21794+#endif
1facf9fc 21795+
b752ccd1
AM
21796+static inline void si_read_unlock(struct super_block *sb)
21797+{
21798+ si_pid_clr(sb);
21799+ __si_read_unlock(sb);
21800+}
21801+
b752ccd1 21802+#if 0 /* unused */
1facf9fc 21803+static inline int si_write_trylock(struct super_block *sb, int flags)
21804+{
21805+ if (au_ftest_lock(flags, FLUSH))
21806+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21807+ return si_noflush_write_trylock(sb);
21808+}
b752ccd1
AM
21809+#endif
21810+
21811+static inline void si_write_unlock(struct super_block *sb)
21812+{
21813+ si_pid_clr(sb);
21814+ __si_write_unlock(sb);
21815+}
21816+
21817+#if 0 /* unused */
21818+static inline void si_downgrade_lock(struct super_block *sb)
21819+{
21820+ __si_downgrade_lock(sb);
21821+}
21822+#endif
1facf9fc 21823+
21824+/* ---------------------------------------------------------------------- */
21825+
21826+static inline aufs_bindex_t au_sbend(struct super_block *sb)
21827+{
dece6358 21828+ SiMustAnyLock(sb);
1facf9fc 21829+ return au_sbi(sb)->si_bend;
21830+}
21831+
21832+static inline unsigned int au_mntflags(struct super_block *sb)
21833+{
dece6358 21834+ SiMustAnyLock(sb);
1facf9fc 21835+ return au_sbi(sb)->si_mntflags;
21836+}
21837+
21838+static inline unsigned int au_sigen(struct super_block *sb)
21839+{
dece6358 21840+ SiMustAnyLock(sb);
1facf9fc 21841+ return au_sbi(sb)->si_generation;
21842+}
21843+
21844+static inline struct au_branch *au_sbr(struct super_block *sb,
21845+ aufs_bindex_t bindex)
21846+{
dece6358 21847+ SiMustAnyLock(sb);
1facf9fc 21848+ return au_sbi(sb)->si_branch[0 + bindex];
21849+}
21850+
21851+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
21852+{
dece6358 21853+ SiMustWriteLock(sb);
1facf9fc 21854+ au_sbi(sb)->si_xino_brid = brid;
21855+}
21856+
21857+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
21858+{
dece6358 21859+ SiMustAnyLock(sb);
1facf9fc 21860+ return au_sbi(sb)->si_xino_brid;
21861+}
21862+
21863+#endif /* __KERNEL__ */
21864+#endif /* __AUFS_SUPER_H__ */
e49829fe
JR
21865--- /dev/null
21866+++ linux-2.6/fs/aufs/sysaufs.c 2010-10-24 11:42:49.000000000 +0200
4a4d8108 21867@@ -0,0 +1,107 @@
1facf9fc 21868+/*
4a4d8108 21869+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21870+ *
21871+ * This program, aufs is free software; you can redistribute it and/or modify
21872+ * it under the terms of the GNU General Public License as published by
21873+ * the Free Software Foundation; either version 2 of the License, or
21874+ * (at your option) any later version.
dece6358
AM
21875+ *
21876+ * This program is distributed in the hope that it will be useful,
21877+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21878+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21879+ * GNU General Public License for more details.
21880+ *
21881+ * You should have received a copy of the GNU General Public License
21882+ * along with this program; if not, write to the Free Software
21883+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21884+ */
21885+
21886+/*
21887+ * sysfs interface and lifetime management
21888+ * they are necessary regardless sysfs is disabled.
21889+ */
21890+
21891+#include <linux/fs.h>
21892+#include <linux/random.h>
21893+#include <linux/sysfs.h>
21894+#include "aufs.h"
21895+
21896+unsigned long sysaufs_si_mask;
e49829fe 21897+struct kset *sysaufs_kset;
1facf9fc 21898+
21899+#define AuSiAttr(_name) { \
21900+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
21901+ .show = sysaufs_si_##_name, \
21902+}
21903+
21904+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
21905+struct attribute *sysaufs_si_attrs[] = {
21906+ &sysaufs_si_attr_xi_path.attr,
21907+ NULL,
21908+};
21909+
4a4d8108 21910+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 21911+ .show = sysaufs_si_show
21912+};
21913+
21914+static struct kobj_type au_sbi_ktype = {
21915+ .release = au_si_free,
21916+ .sysfs_ops = &au_sbi_ops,
21917+ .default_attrs = sysaufs_si_attrs
21918+};
21919+
21920+/* ---------------------------------------------------------------------- */
21921+
21922+int sysaufs_si_init(struct au_sbinfo *sbinfo)
21923+{
21924+ int err;
21925+
e49829fe 21926+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 21927+ /* cf. sysaufs_name() */
21928+ err = kobject_init_and_add
e49829fe 21929+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 21930+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
21931+
21932+ dbgaufs_si_null(sbinfo);
21933+ if (!err) {
21934+ err = dbgaufs_si_init(sbinfo);
21935+ if (unlikely(err))
21936+ kobject_put(&sbinfo->si_kobj);
21937+ }
21938+ return err;
21939+}
21940+
21941+void sysaufs_fin(void)
21942+{
21943+ dbgaufs_fin();
e49829fe
JR
21944+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
21945+ kset_unregister(sysaufs_kset);
1facf9fc 21946+}
21947+
21948+int __init sysaufs_init(void)
21949+{
21950+ int err;
21951+
21952+ do {
21953+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
21954+ } while (!sysaufs_si_mask);
21955+
4a4d8108 21956+ err = -EINVAL;
e49829fe
JR
21957+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
21958+ if (unlikely(!sysaufs_kset))
4a4d8108 21959+ goto out;
e49829fe
JR
21960+ err = PTR_ERR(sysaufs_kset);
21961+ if (IS_ERR(sysaufs_kset))
1facf9fc 21962+ goto out;
e49829fe 21963+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 21964+ if (unlikely(err)) {
e49829fe 21965+ kset_unregister(sysaufs_kset);
1facf9fc 21966+ goto out;
21967+ }
21968+
21969+ err = dbgaufs_init();
21970+ if (unlikely(err))
21971+ sysaufs_fin();
4f0767ce 21972+out:
1facf9fc 21973+ return err;
21974+}
e49829fe
JR
21975--- /dev/null
21976+++ linux-2.6/fs/aufs/sysaufs.h 2010-10-24 11:43:00.000000000 +0200
4a4d8108 21977@@ -0,0 +1,105 @@
1facf9fc 21978+/*
4a4d8108 21979+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21980+ *
21981+ * This program, aufs is free software; you can redistribute it and/or modify
21982+ * it under the terms of the GNU General Public License as published by
21983+ * the Free Software Foundation; either version 2 of the License, or
21984+ * (at your option) any later version.
dece6358
AM
21985+ *
21986+ * This program is distributed in the hope that it will be useful,
21987+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21988+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21989+ * GNU General Public License for more details.
21990+ *
21991+ * You should have received a copy of the GNU General Public License
21992+ * along with this program; if not, write to the Free Software
21993+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21994+ */
21995+
21996+/*
21997+ * sysfs interface and mount lifetime management
21998+ */
21999+
22000+#ifndef __SYSAUFS_H__
22001+#define __SYSAUFS_H__
22002+
22003+#ifdef __KERNEL__
22004+
1facf9fc 22005+#include <linux/sysfs.h>
22006+#include <linux/aufs_type.h>
22007+#include "module.h"
22008+
dece6358
AM
22009+struct super_block;
22010+struct au_sbinfo;
22011+
1facf9fc 22012+struct sysaufs_si_attr {
22013+ struct attribute attr;
22014+ int (*show)(struct seq_file *seq, struct super_block *sb);
22015+};
22016+
22017+/* ---------------------------------------------------------------------- */
22018+
22019+/* sysaufs.c */
22020+extern unsigned long sysaufs_si_mask;
e49829fe 22021+extern struct kset *sysaufs_kset;
1facf9fc 22022+extern struct attribute *sysaufs_si_attrs[];
22023+int sysaufs_si_init(struct au_sbinfo *sbinfo);
22024+int __init sysaufs_init(void);
22025+void sysaufs_fin(void);
22026+
22027+/* ---------------------------------------------------------------------- */
22028+
22029+/* some people doesn't like to show a pointer in kernel */
22030+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
22031+{
22032+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
22033+}
22034+
22035+#define SysaufsSiNamePrefix "si_"
22036+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
22037+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
22038+{
22039+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
22040+ sysaufs_si_id(sbinfo));
22041+}
22042+
22043+struct au_branch;
22044+#ifdef CONFIG_SYSFS
22045+/* sysfs.c */
22046+extern struct attribute_group *sysaufs_attr_group;
22047+
22048+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
22049+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
22050+ char *buf);
22051+
22052+void sysaufs_br_init(struct au_branch *br);
22053+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
22054+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
22055+
22056+#define sysaufs_brs_init() do {} while (0)
22057+
22058+#else
22059+#define sysaufs_attr_group NULL
22060+
4a4d8108 22061+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 22062+
22063+static inline
22064+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
22065+ char *buf)
22066+{
22067+ return 0;
22068+}
22069+
4a4d8108
AM
22070+AuStubVoid(sysaufs_br_init, struct au_branch *br)
22071+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
22072+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 22073+
22074+static inline void sysaufs_brs_init(void)
22075+{
22076+ sysaufs_brs = 0;
22077+}
22078+
22079+#endif /* CONFIG_SYSFS */
22080+
22081+#endif /* __KERNEL__ */
22082+#endif /* __SYSAUFS_H__ */
e49829fe
JR
22083--- /dev/null
22084+++ linux-2.6/fs/aufs/sysfs.c 2010-10-24 15:24:09.000000000 +0200
953406b4 22085@@ -0,0 +1,250 @@
1facf9fc 22086+/*
4a4d8108 22087+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22088+ *
22089+ * This program, aufs is free software; you can redistribute it and/or modify
22090+ * it under the terms of the GNU General Public License as published by
22091+ * the Free Software Foundation; either version 2 of the License, or
22092+ * (at your option) any later version.
dece6358
AM
22093+ *
22094+ * This program is distributed in the hope that it will be useful,
22095+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22096+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22097+ * GNU General Public License for more details.
22098+ *
22099+ * You should have received a copy of the GNU General Public License
22100+ * along with this program; if not, write to the Free Software
22101+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22102+ */
22103+
22104+/*
22105+ * sysfs interface
22106+ */
22107+
22108+#include <linux/fs.h>
dece6358 22109+#include <linux/module.h>
1facf9fc 22110+#include <linux/seq_file.h>
22111+#include <linux/sysfs.h>
22112+#include "aufs.h"
22113+
4a4d8108
AM
22114+#ifdef CONFIG_AUFS_FS_MODULE
22115+/* this entry violates the "one line per file" policy of sysfs */
22116+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
22117+ char *buf)
22118+{
22119+ ssize_t err;
22120+ static char *conf =
22121+/* this file is generated at compiling */
22122+#include "conf.str"
22123+ ;
22124+
22125+ err = snprintf(buf, PAGE_SIZE, conf);
22126+ if (unlikely(err >= PAGE_SIZE))
22127+ err = -EFBIG;
22128+ return err;
22129+}
22130+
22131+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
22132+#endif
22133+
1facf9fc 22134+static struct attribute *au_attr[] = {
4a4d8108
AM
22135+#ifdef CONFIG_AUFS_FS_MODULE
22136+ &au_config_attr.attr,
22137+#endif
1facf9fc 22138+ NULL, /* need to NULL terminate the list of attributes */
22139+};
22140+
22141+static struct attribute_group sysaufs_attr_group_body = {
22142+ .attrs = au_attr
22143+};
22144+
22145+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
22146+
22147+/* ---------------------------------------------------------------------- */
22148+
22149+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
22150+{
22151+ int err;
22152+
dece6358
AM
22153+ SiMustAnyLock(sb);
22154+
1facf9fc 22155+ err = 0;
22156+ if (au_opt_test(au_mntflags(sb), XINO)) {
22157+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
22158+ seq_putc(seq, '\n');
22159+ }
22160+ return err;
22161+}
22162+
22163+/*
22164+ * the lifetime of branch is independent from the entry under sysfs.
22165+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
22166+ * unlinked.
22167+ */
22168+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
22169+ aufs_bindex_t bindex)
22170+{
22171+ struct path path;
22172+ struct dentry *root;
22173+ struct au_branch *br;
22174+
22175+ AuDbg("b%d\n", bindex);
22176+
22177+ root = sb->s_root;
22178+ di_read_lock_parent(root, !AuLock_IR);
22179+ br = au_sbr(sb, bindex);
22180+ path.mnt = br->br_mnt;
22181+ path.dentry = au_h_dptr(root, bindex);
22182+ au_seq_path(seq, &path);
22183+ di_read_unlock(root, !AuLock_IR);
22184+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
22185+ return 0;
22186+}
22187+
22188+/* ---------------------------------------------------------------------- */
22189+
22190+static struct seq_file *au_seq(char *p, ssize_t len)
22191+{
22192+ struct seq_file *seq;
22193+
22194+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
22195+ if (seq) {
22196+ /* mutex_init(&seq.lock); */
22197+ seq->buf = p;
22198+ seq->size = len;
22199+ return seq; /* success */
22200+ }
22201+
22202+ seq = ERR_PTR(-ENOMEM);
22203+ return seq;
22204+}
22205+
22206+#define SysaufsBr_PREFIX "br"
22207+
22208+/* todo: file size may exceed PAGE_SIZE */
22209+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 22210+ char *buf)
1facf9fc 22211+{
22212+ ssize_t err;
22213+ long l;
22214+ aufs_bindex_t bend;
22215+ struct au_sbinfo *sbinfo;
22216+ struct super_block *sb;
22217+ struct seq_file *seq;
22218+ char *name;
22219+ struct attribute **cattr;
22220+
22221+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
22222+ sb = sbinfo->si_sb;
1308ab2a 22223+
22224+ /*
22225+ * prevent a race condition between sysfs and aufs.
22226+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
22227+ * prohibits maintaining the sysfs entries.
22228+ * hew we acquire read lock after sysfs_get_active_two().
22229+ * on the other hand, the remount process may maintain the sysfs/aufs
22230+ * entries after acquiring write lock.
22231+ * it can cause a deadlock.
22232+ * simply we gave up processing read here.
22233+ */
22234+ err = -EBUSY;
22235+ if (unlikely(!si_noflush_read_trylock(sb)))
22236+ goto out;
1facf9fc 22237+
22238+ seq = au_seq(buf, PAGE_SIZE);
22239+ err = PTR_ERR(seq);
22240+ if (IS_ERR(seq))
1308ab2a 22241+ goto out_unlock;
1facf9fc 22242+
22243+ name = (void *)attr->name;
22244+ cattr = sysaufs_si_attrs;
22245+ while (*cattr) {
22246+ if (!strcmp(name, (*cattr)->name)) {
22247+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
22248+ ->show(seq, sb);
22249+ goto out_seq;
22250+ }
22251+ cattr++;
22252+ }
22253+
22254+ bend = au_sbend(sb);
22255+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
22256+ name += sizeof(SysaufsBr_PREFIX) - 1;
22257+ err = strict_strtol(name, 10, &l);
22258+ if (!err) {
22259+ if (l <= bend)
22260+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
22261+ else
22262+ err = -ENOENT;
22263+ }
22264+ goto out_seq;
22265+ }
22266+ BUG();
22267+
4f0767ce 22268+out_seq:
1facf9fc 22269+ if (!err) {
22270+ err = seq->count;
22271+ /* sysfs limit */
22272+ if (unlikely(err == PAGE_SIZE))
22273+ err = -EFBIG;
22274+ }
22275+ kfree(seq);
4f0767ce 22276+out_unlock:
1facf9fc 22277+ si_read_unlock(sb);
4f0767ce 22278+out:
1facf9fc 22279+ return err;
22280+}
22281+
22282+/* ---------------------------------------------------------------------- */
22283+
22284+void sysaufs_br_init(struct au_branch *br)
22285+{
4a4d8108
AM
22286+ struct attribute *attr = &br->br_attr;
22287+
22288+ sysfs_attr_init(attr);
22289+ attr->name = br->br_name;
22290+ attr->mode = S_IRUGO;
1facf9fc 22291+}
22292+
22293+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
22294+{
22295+ struct au_branch *br;
22296+ struct kobject *kobj;
22297+ aufs_bindex_t bend;
22298+
22299+ dbgaufs_brs_del(sb, bindex);
22300+
22301+ if (!sysaufs_brs)
22302+ return;
22303+
22304+ kobj = &au_sbi(sb)->si_kobj;
22305+ bend = au_sbend(sb);
22306+ for (; bindex <= bend; bindex++) {
22307+ br = au_sbr(sb, bindex);
22308+ sysfs_remove_file(kobj, &br->br_attr);
22309+ }
22310+}
22311+
22312+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
22313+{
22314+ int err;
22315+ aufs_bindex_t bend;
22316+ struct kobject *kobj;
22317+ struct au_branch *br;
22318+
22319+ dbgaufs_brs_add(sb, bindex);
22320+
22321+ if (!sysaufs_brs)
22322+ return;
22323+
22324+ kobj = &au_sbi(sb)->si_kobj;
22325+ bend = au_sbend(sb);
22326+ for (; bindex <= bend; bindex++) {
22327+ br = au_sbr(sb, bindex);
22328+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
22329+ "%d", bindex);
22330+ err = sysfs_create_file(kobj, &br->br_attr);
22331+ if (unlikely(err))
4a4d8108
AM
22332+ pr_warning("failed %s under sysfs(%d)\n",
22333+ br->br_name, err);
1facf9fc 22334+ }
22335+}
e49829fe
JR
22336--- /dev/null
22337+++ linux-2.6/fs/aufs/sysrq.c 2010-10-24 11:43:18.000000000 +0200
4a4d8108 22338@@ -0,0 +1,119 @@
1facf9fc 22339+/*
4a4d8108 22340+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22341+ *
22342+ * This program, aufs is free software; you can redistribute it and/or modify
22343+ * it under the terms of the GNU General Public License as published by
22344+ * the Free Software Foundation; either version 2 of the License, or
22345+ * (at your option) any later version.
dece6358
AM
22346+ *
22347+ * This program is distributed in the hope that it will be useful,
22348+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22349+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22350+ * GNU General Public License for more details.
22351+ *
22352+ * You should have received a copy of the GNU General Public License
22353+ * along with this program; if not, write to the Free Software
22354+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22355+ */
22356+
22357+/*
22358+ * magic sysrq hanlder
22359+ */
22360+
22361+#include <linux/fs.h>
22362+#include <linux/module.h>
22363+#include <linux/moduleparam.h>
22364+/* #include <linux/sysrq.h> */
22365+#include "aufs.h"
22366+
22367+/* ---------------------------------------------------------------------- */
22368+
22369+static void sysrq_sb(struct super_block *sb)
22370+{
22371+ char *plevel;
22372+ struct au_sbinfo *sbinfo;
22373+ struct file *file;
22374+
22375+ plevel = au_plevel;
22376+ au_plevel = KERN_WARNING;
1facf9fc 22377+
22378+ sbinfo = au_sbi(sb);
4a4d8108
AM
22379+ /* since we define pr_fmt, call printk directly */
22380+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
22381+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 22382+ au_dpri_sb(sb);
4a4d8108 22383+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 22384+ au_dpri_dentry(sb->s_root);
4a4d8108 22385+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 22386+ au_dpri_inode(sb->s_root->d_inode);
22387+#if 0
22388+ struct inode *i;
4a4d8108 22389+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
e49829fe 22390+ spin_lock(&inode_lock);
1facf9fc 22391+ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
22392+ if (list_empty(&i->i_dentry))
22393+ au_dpri_inode(i);
e49829fe 22394+ spin_unlock(&inode_lock);
1facf9fc 22395+#endif
4a4d8108 22396+ printk(KERN_WARNING AUFS_NAME ": files\n");
e49829fe 22397+ file_list_lock();
4a4d8108
AM
22398+ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
22399+ umode_t mode;
22400+ mode = file->f_dentry->d_inode->i_mode;
22401+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 22402+ au_dpri_file(file);
4a4d8108 22403+ }
e49829fe
JR
22404+ file_list_unlock();
22405+ printk(KERN_WARNING AUFS_NAME ": done\n");
1facf9fc 22406+
22407+ au_plevel = plevel;
1facf9fc 22408+}
22409+
22410+/* ---------------------------------------------------------------------- */
22411+
22412+/* module parameter */
22413+static char *aufs_sysrq_key = "a";
22414+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
22415+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
22416+
22417+static void au_sysrq(int key __maybe_unused,
22418+ struct tty_struct *tty __maybe_unused)
22419+{
1facf9fc 22420+ struct au_sbinfo *sbinfo;
22421+
e49829fe
JR
22422+ spin_lock(&au_sbilist.spin);
22423+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
1facf9fc 22424+ sysrq_sb(sbinfo->si_sb);
e49829fe 22425+ spin_unlock(&au_sbilist.spin);
1facf9fc 22426+}
22427+
22428+static struct sysrq_key_op au_sysrq_op = {
22429+ .handler = au_sysrq,
22430+ .help_msg = "Aufs",
22431+ .action_msg = "Aufs",
22432+ .enable_mask = SYSRQ_ENABLE_DUMP
22433+};
22434+
22435+/* ---------------------------------------------------------------------- */
22436+
22437+int __init au_sysrq_init(void)
22438+{
22439+ int err;
22440+ char key;
22441+
22442+ err = -1;
22443+ key = *aufs_sysrq_key;
22444+ if ('a' <= key && key <= 'z')
22445+ err = register_sysrq_key(key, &au_sysrq_op);
22446+ if (unlikely(err))
4a4d8108 22447+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 22448+ return err;
22449+}
22450+
22451+void au_sysrq_fin(void)
22452+{
22453+ int err;
22454+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
22455+ if (unlikely(err))
4a4d8108 22456+ pr_err("err %d (ignored)\n", err);
1facf9fc 22457+}
e49829fe
JR
22458--- /dev/null
22459+++ linux-2.6/fs/aufs/vdir.c 2010-10-24 11:19:23.000000000 +0200
4a4d8108 22460@@ -0,0 +1,884 @@
1facf9fc 22461+/*
4a4d8108 22462+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22463+ *
22464+ * This program, aufs is free software; you can redistribute it and/or modify
22465+ * it under the terms of the GNU General Public License as published by
22466+ * the Free Software Foundation; either version 2 of the License, or
22467+ * (at your option) any later version.
dece6358
AM
22468+ *
22469+ * This program is distributed in the hope that it will be useful,
22470+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22471+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22472+ * GNU General Public License for more details.
22473+ *
22474+ * You should have received a copy of the GNU General Public License
22475+ * along with this program; if not, write to the Free Software
22476+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22477+ */
22478+
22479+/*
22480+ * virtual or vertical directory
22481+ */
22482+
dece6358 22483+#include <linux/hash.h>
1facf9fc 22484+#include "aufs.h"
22485+
dece6358 22486+static unsigned int calc_size(int nlen)
1facf9fc 22487+{
dece6358 22488+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 22489+}
22490+
22491+static int set_deblk_end(union au_vdir_deblk_p *p,
22492+ union au_vdir_deblk_p *deblk_end)
22493+{
22494+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
22495+ p->de->de_str.len = 0;
22496+ /* smp_mb(); */
22497+ return 0;
22498+ }
22499+ return -1; /* error */
22500+}
22501+
22502+/* returns true or false */
22503+static int is_deblk_end(union au_vdir_deblk_p *p,
22504+ union au_vdir_deblk_p *deblk_end)
22505+{
22506+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
22507+ return !p->de->de_str.len;
22508+ return 1;
22509+}
22510+
22511+static unsigned char *last_deblk(struct au_vdir *vdir)
22512+{
22513+ return vdir->vd_deblk[vdir->vd_nblk - 1];
22514+}
22515+
22516+/* ---------------------------------------------------------------------- */
22517+
1308ab2a 22518+/* estimate the apropriate size for name hash table */
22519+unsigned int au_rdhash_est(loff_t sz)
22520+{
22521+ unsigned int n;
22522+
22523+ n = UINT_MAX;
22524+ sz >>= 10;
22525+ if (sz < n)
22526+ n = sz;
22527+ if (sz < AUFS_RDHASH_DEF)
22528+ n = AUFS_RDHASH_DEF;
4a4d8108 22529+ /* pr_info("n %u\n", n); */
1308ab2a 22530+ return n;
22531+}
22532+
1facf9fc 22533+/*
22534+ * the allocated memory has to be freed by
dece6358 22535+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 22536+ */
dece6358 22537+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 22538+{
1facf9fc 22539+ struct hlist_head *head;
dece6358 22540+ unsigned int u;
1facf9fc 22541+
dece6358
AM
22542+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
22543+ if (head) {
22544+ nhash->nh_num = num_hash;
22545+ nhash->nh_head = head;
22546+ for (u = 0; u < num_hash; u++)
1facf9fc 22547+ INIT_HLIST_HEAD(head++);
dece6358 22548+ return 0; /* success */
1facf9fc 22549+ }
1facf9fc 22550+
dece6358 22551+ return -ENOMEM;
1facf9fc 22552+}
22553+
dece6358
AM
22554+static void nhash_count(struct hlist_head *head)
22555+{
22556+#if 0
22557+ unsigned long n;
22558+ struct hlist_node *pos;
22559+
22560+ n = 0;
22561+ hlist_for_each(pos, head)
22562+ n++;
4a4d8108 22563+ pr_info("%lu\n", n);
dece6358
AM
22564+#endif
22565+}
22566+
22567+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 22568+{
1facf9fc 22569+ struct au_vdir_wh *tpos;
22570+ struct hlist_node *pos, *node;
22571+
dece6358
AM
22572+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
22573+ /* hlist_del(pos); */
22574+ kfree(tpos);
1facf9fc 22575+ }
22576+}
22577+
dece6358 22578+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 22579+{
dece6358
AM
22580+ struct au_vdir_dehstr *tpos;
22581+ struct hlist_node *pos, *node;
1facf9fc 22582+
dece6358
AM
22583+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
22584+ /* hlist_del(pos); */
4a4d8108 22585+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 22586+ }
1facf9fc 22587+}
22588+
dece6358
AM
22589+static void au_nhash_do_free(struct au_nhash *nhash,
22590+ void (*free)(struct hlist_head *head))
1facf9fc 22591+{
1308ab2a 22592+ unsigned int n;
1facf9fc 22593+ struct hlist_head *head;
1facf9fc 22594+
dece6358 22595+ n = nhash->nh_num;
1308ab2a 22596+ if (!n)
22597+ return;
22598+
dece6358 22599+ head = nhash->nh_head;
1308ab2a 22600+ while (n-- > 0) {
dece6358
AM
22601+ nhash_count(head);
22602+ free(head++);
1facf9fc 22603+ }
dece6358 22604+ kfree(nhash->nh_head);
1facf9fc 22605+}
22606+
dece6358 22607+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 22608+{
dece6358
AM
22609+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
22610+}
1facf9fc 22611+
dece6358
AM
22612+static void au_nhash_de_free(struct au_nhash *delist)
22613+{
22614+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 22615+}
22616+
22617+/* ---------------------------------------------------------------------- */
22618+
22619+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
22620+ int limit)
22621+{
22622+ int num;
22623+ unsigned int u, n;
22624+ struct hlist_head *head;
22625+ struct au_vdir_wh *tpos;
22626+ struct hlist_node *pos;
22627+
22628+ num = 0;
22629+ n = whlist->nh_num;
22630+ head = whlist->nh_head;
1308ab2a 22631+ for (u = 0; u < n; u++, head++)
1facf9fc 22632+ hlist_for_each_entry(tpos, pos, head, wh_hash)
22633+ if (tpos->wh_bindex == btgt && ++num > limit)
22634+ return 1;
1facf9fc 22635+ return 0;
22636+}
22637+
22638+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 22639+ unsigned char *name,
1facf9fc 22640+ unsigned int len)
22641+{
dece6358
AM
22642+ unsigned int v;
22643+ /* const unsigned int magic_bit = 12; */
22644+
1308ab2a 22645+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
22646+
dece6358
AM
22647+ v = 0;
22648+ while (len--)
22649+ v += *name++;
22650+ /* v = hash_long(v, magic_bit); */
22651+ v %= nhash->nh_num;
22652+ return nhash->nh_head + v;
22653+}
22654+
22655+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
22656+ int nlen)
22657+{
22658+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 22659+}
22660+
22661+/* returns found or not */
dece6358 22662+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 22663+{
22664+ struct hlist_head *head;
22665+ struct au_vdir_wh *tpos;
22666+ struct hlist_node *pos;
22667+ struct au_vdir_destr *str;
22668+
dece6358 22669+ head = au_name_hash(whlist, name, nlen);
1facf9fc 22670+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
22671+ str = &tpos->wh_str;
22672+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
22673+ if (au_nhash_test_name(str, name, nlen))
22674+ return 1;
22675+ }
22676+ return 0;
22677+}
22678+
22679+/* returns found(true) or not */
22680+static int test_known(struct au_nhash *delist, char *name, int nlen)
22681+{
22682+ struct hlist_head *head;
22683+ struct au_vdir_dehstr *tpos;
22684+ struct hlist_node *pos;
22685+ struct au_vdir_destr *str;
22686+
22687+ head = au_name_hash(delist, name, nlen);
22688+ hlist_for_each_entry(tpos, pos, head, hash) {
22689+ str = tpos->str;
22690+ AuDbg("%.*s\n", str->len, str->name);
22691+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 22692+ return 1;
22693+ }
22694+ return 0;
22695+}
22696+
dece6358
AM
22697+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
22698+ unsigned char d_type)
22699+{
22700+#ifdef CONFIG_AUFS_SHWH
22701+ wh->wh_ino = ino;
22702+ wh->wh_type = d_type;
22703+#endif
22704+}
22705+
22706+/* ---------------------------------------------------------------------- */
22707+
22708+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
22709+ unsigned int d_type, aufs_bindex_t bindex,
22710+ unsigned char shwh)
1facf9fc 22711+{
22712+ int err;
22713+ struct au_vdir_destr *str;
22714+ struct au_vdir_wh *wh;
22715+
dece6358 22716+ AuDbg("%.*s\n", nlen, name);
1308ab2a 22717+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
22718+
1facf9fc 22719+ err = -ENOMEM;
dece6358 22720+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 22721+ if (unlikely(!wh))
22722+ goto out;
22723+
22724+ err = 0;
22725+ wh->wh_bindex = bindex;
dece6358
AM
22726+ if (shwh)
22727+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 22728+ str = &wh->wh_str;
dece6358
AM
22729+ str->len = nlen;
22730+ memcpy(str->name, name, nlen);
22731+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 22732+ /* smp_mb(); */
22733+
4f0767ce 22734+out:
1facf9fc 22735+ return err;
22736+}
22737+
1facf9fc 22738+static int append_deblk(struct au_vdir *vdir)
22739+{
22740+ int err;
dece6358 22741+ unsigned long ul;
1facf9fc 22742+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
22743+ union au_vdir_deblk_p p, deblk_end;
22744+ unsigned char **o;
22745+
22746+ err = -ENOMEM;
dece6358
AM
22747+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
22748+ GFP_NOFS);
1facf9fc 22749+ if (unlikely(!o))
22750+ goto out;
22751+
22752+ vdir->vd_deblk = o;
22753+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
22754+ if (p.deblk) {
22755+ ul = vdir->vd_nblk++;
22756+ vdir->vd_deblk[ul] = p.deblk;
22757+ vdir->vd_last.ul = ul;
22758+ vdir->vd_last.p.deblk = p.deblk;
22759+ deblk_end.deblk = p.deblk + deblk_sz;
22760+ err = set_deblk_end(&p, &deblk_end);
22761+ }
22762+
4f0767ce 22763+out:
1facf9fc 22764+ return err;
22765+}
22766+
dece6358
AM
22767+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
22768+ unsigned int d_type, struct au_nhash *delist)
22769+{
22770+ int err;
22771+ unsigned int sz;
22772+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
22773+ union au_vdir_deblk_p p, *room, deblk_end;
22774+ struct au_vdir_dehstr *dehstr;
22775+
22776+ p.deblk = last_deblk(vdir);
22777+ deblk_end.deblk = p.deblk + deblk_sz;
22778+ room = &vdir->vd_last.p;
22779+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
22780+ || !is_deblk_end(room, &deblk_end));
22781+
22782+ sz = calc_size(nlen);
22783+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
22784+ err = append_deblk(vdir);
22785+ if (unlikely(err))
22786+ goto out;
22787+
22788+ p.deblk = last_deblk(vdir);
22789+ deblk_end.deblk = p.deblk + deblk_sz;
22790+ /* smp_mb(); */
22791+ AuDebugOn(room->deblk != p.deblk);
22792+ }
22793+
22794+ err = -ENOMEM;
4a4d8108 22795+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
22796+ if (unlikely(!dehstr))
22797+ goto out;
22798+
22799+ dehstr->str = &room->de->de_str;
22800+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
22801+ room->de->de_ino = ino;
22802+ room->de->de_type = d_type;
22803+ room->de->de_str.len = nlen;
22804+ memcpy(room->de->de_str.name, name, nlen);
22805+
22806+ err = 0;
22807+ room->deblk += sz;
22808+ if (unlikely(set_deblk_end(room, &deblk_end)))
22809+ err = append_deblk(vdir);
22810+ /* smp_mb(); */
22811+
4f0767ce 22812+out:
dece6358
AM
22813+ return err;
22814+}
22815+
22816+/* ---------------------------------------------------------------------- */
22817+
22818+void au_vdir_free(struct au_vdir *vdir)
22819+{
22820+ unsigned char **deblk;
22821+
22822+ deblk = vdir->vd_deblk;
22823+ while (vdir->vd_nblk--)
22824+ kfree(*deblk++);
22825+ kfree(vdir->vd_deblk);
22826+ au_cache_free_vdir(vdir);
22827+}
22828+
1308ab2a 22829+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 22830+{
22831+ struct au_vdir *vdir;
1308ab2a 22832+ struct super_block *sb;
1facf9fc 22833+ int err;
22834+
1308ab2a 22835+ sb = file->f_dentry->d_sb;
dece6358
AM
22836+ SiMustAnyLock(sb);
22837+
1facf9fc 22838+ err = -ENOMEM;
22839+ vdir = au_cache_alloc_vdir();
22840+ if (unlikely(!vdir))
22841+ goto out;
22842+
22843+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
22844+ if (unlikely(!vdir->vd_deblk))
22845+ goto out_free;
22846+
22847+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 22848+ if (!vdir->vd_deblk_sz) {
22849+ /* estimate the apropriate size for deblk */
22850+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 22851+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 22852+ }
1facf9fc 22853+ vdir->vd_nblk = 0;
22854+ vdir->vd_version = 0;
22855+ vdir->vd_jiffy = 0;
22856+ err = append_deblk(vdir);
22857+ if (!err)
22858+ return vdir; /* success */
22859+
22860+ kfree(vdir->vd_deblk);
22861+
4f0767ce 22862+out_free:
1facf9fc 22863+ au_cache_free_vdir(vdir);
4f0767ce 22864+out:
1facf9fc 22865+ vdir = ERR_PTR(err);
22866+ return vdir;
22867+}
22868+
22869+static int reinit_vdir(struct au_vdir *vdir)
22870+{
22871+ int err;
22872+ union au_vdir_deblk_p p, deblk_end;
22873+
22874+ while (vdir->vd_nblk > 1) {
22875+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
22876+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
22877+ vdir->vd_nblk--;
22878+ }
22879+ p.deblk = vdir->vd_deblk[0];
22880+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
22881+ err = set_deblk_end(&p, &deblk_end);
22882+ /* keep vd_dblk_sz */
22883+ vdir->vd_last.ul = 0;
22884+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
22885+ vdir->vd_version = 0;
22886+ vdir->vd_jiffy = 0;
22887+ /* smp_mb(); */
22888+ return err;
22889+}
22890+
22891+/* ---------------------------------------------------------------------- */
22892+
1facf9fc 22893+#define AuFillVdir_CALLED 1
22894+#define AuFillVdir_WHABLE (1 << 1)
dece6358 22895+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 22896+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
22897+#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
22898+#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
22899+
dece6358
AM
22900+#ifndef CONFIG_AUFS_SHWH
22901+#undef AuFillVdir_SHWH
22902+#define AuFillVdir_SHWH 0
22903+#endif
22904+
1facf9fc 22905+struct fillvdir_arg {
22906+ struct file *file;
22907+ struct au_vdir *vdir;
dece6358
AM
22908+ struct au_nhash delist;
22909+ struct au_nhash whlist;
1facf9fc 22910+ aufs_bindex_t bindex;
22911+ unsigned int flags;
22912+ int err;
22913+};
22914+
dece6358 22915+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 22916+ loff_t offset __maybe_unused, u64 h_ino,
22917+ unsigned int d_type)
22918+{
22919+ struct fillvdir_arg *arg = __arg;
22920+ char *name = (void *)__name;
22921+ struct super_block *sb;
1facf9fc 22922+ ino_t ino;
dece6358 22923+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 22924+
1facf9fc 22925+ arg->err = 0;
dece6358 22926+ sb = arg->file->f_dentry->d_sb;
1facf9fc 22927+ au_fset_fillvdir(arg->flags, CALLED);
22928+ /* smp_mb(); */
dece6358 22929+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 22930+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
22931+ if (test_known(&arg->delist, name, nlen)
22932+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
22933+ goto out; /* already exists or whiteouted */
1facf9fc 22934+
22935+ sb = arg->file->f_dentry->d_sb;
dece6358 22936+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
22937+ if (!arg->err) {
22938+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
22939+ d_type = DT_UNKNOWN;
dece6358
AM
22940+ arg->err = append_de(arg->vdir, name, nlen, ino,
22941+ d_type, &arg->delist);
4a4d8108 22942+ }
1facf9fc 22943+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
22944+ name += AUFS_WH_PFX_LEN;
dece6358
AM
22945+ nlen -= AUFS_WH_PFX_LEN;
22946+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
22947+ goto out; /* already whiteouted */
1facf9fc 22948+
dece6358
AM
22949+ if (shwh)
22950+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
22951+ &ino);
4a4d8108
AM
22952+ if (!arg->err) {
22953+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
22954+ d_type = DT_UNKNOWN;
1facf9fc 22955+ arg->err = au_nhash_append_wh
dece6358
AM
22956+ (&arg->whlist, name, nlen, ino, d_type,
22957+ arg->bindex, shwh);
4a4d8108 22958+ }
1facf9fc 22959+ }
22960+
4f0767ce 22961+out:
1facf9fc 22962+ if (!arg->err)
22963+ arg->vdir->vd_jiffy = jiffies;
22964+ /* smp_mb(); */
22965+ AuTraceErr(arg->err);
22966+ return arg->err;
22967+}
22968+
dece6358
AM
22969+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
22970+ struct au_nhash *whlist, struct au_nhash *delist)
22971+{
22972+#ifdef CONFIG_AUFS_SHWH
22973+ int err;
22974+ unsigned int nh, u;
22975+ struct hlist_head *head;
22976+ struct au_vdir_wh *tpos;
22977+ struct hlist_node *pos, *n;
22978+ char *p, *o;
22979+ struct au_vdir_destr *destr;
22980+
22981+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
22982+
22983+ err = -ENOMEM;
4a4d8108 22984+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
22985+ if (unlikely(!p))
22986+ goto out;
22987+
22988+ err = 0;
22989+ nh = whlist->nh_num;
22990+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
22991+ p += AUFS_WH_PFX_LEN;
22992+ for (u = 0; u < nh; u++) {
22993+ head = whlist->nh_head + u;
22994+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
22995+ destr = &tpos->wh_str;
22996+ memcpy(p, destr->name, destr->len);
22997+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
22998+ tpos->wh_ino, tpos->wh_type, delist);
22999+ if (unlikely(err))
23000+ break;
23001+ }
23002+ }
23003+
23004+ __putname(o);
23005+
4f0767ce 23006+out:
dece6358
AM
23007+ AuTraceErr(err);
23008+ return err;
23009+#else
23010+ return 0;
23011+#endif
23012+}
23013+
1facf9fc 23014+static int au_do_read_vdir(struct fillvdir_arg *arg)
23015+{
23016+ int err;
dece6358 23017+ unsigned int rdhash;
1facf9fc 23018+ loff_t offset;
dece6358
AM
23019+ aufs_bindex_t bend, bindex, bstart;
23020+ unsigned char shwh;
1facf9fc 23021+ struct file *hf, *file;
23022+ struct super_block *sb;
23023+
1facf9fc 23024+ file = arg->file;
23025+ sb = file->f_dentry->d_sb;
dece6358
AM
23026+ SiMustAnyLock(sb);
23027+
23028+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 23029+ if (!rdhash)
23030+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
23031+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
23032+ if (unlikely(err))
1facf9fc 23033+ goto out;
dece6358
AM
23034+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
23035+ if (unlikely(err))
1facf9fc 23036+ goto out_delist;
23037+
23038+ err = 0;
23039+ arg->flags = 0;
dece6358
AM
23040+ shwh = 0;
23041+ if (au_opt_test(au_mntflags(sb), SHWH)) {
23042+ shwh = 1;
23043+ au_fset_fillvdir(arg->flags, SHWH);
23044+ }
23045+ bstart = au_fbstart(file);
4a4d8108 23046+ bend = au_fbend_dir(file);
dece6358 23047+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 23048+ hf = au_hf_dir(file, bindex);
1facf9fc 23049+ if (!hf)
23050+ continue;
23051+
23052+ offset = vfsub_llseek(hf, 0, SEEK_SET);
23053+ err = offset;
23054+ if (unlikely(offset))
23055+ break;
23056+
23057+ arg->bindex = bindex;
23058+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
23059+ if (shwh
23060+ || (bindex != bend
23061+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 23062+ au_fset_fillvdir(arg->flags, WHABLE);
23063+ do {
23064+ arg->err = 0;
23065+ au_fclr_fillvdir(arg->flags, CALLED);
23066+ /* smp_mb(); */
23067+ err = vfsub_readdir(hf, fillvdir, arg);
23068+ if (err >= 0)
23069+ err = arg->err;
23070+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
23071+ }
dece6358
AM
23072+
23073+ if (!err && shwh)
23074+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
23075+
23076+ au_nhash_wh_free(&arg->whlist);
1facf9fc 23077+
4f0767ce 23078+out_delist:
dece6358 23079+ au_nhash_de_free(&arg->delist);
4f0767ce 23080+out:
1facf9fc 23081+ return err;
23082+}
23083+
23084+static int read_vdir(struct file *file, int may_read)
23085+{
23086+ int err;
23087+ unsigned long expire;
23088+ unsigned char do_read;
23089+ struct fillvdir_arg arg;
23090+ struct inode *inode;
23091+ struct au_vdir *vdir, *allocated;
23092+
23093+ err = 0;
23094+ inode = file->f_dentry->d_inode;
23095+ IMustLock(inode);
dece6358
AM
23096+ SiMustAnyLock(inode->i_sb);
23097+
1facf9fc 23098+ allocated = NULL;
23099+ do_read = 0;
23100+ expire = au_sbi(inode->i_sb)->si_rdcache;
23101+ vdir = au_ivdir(inode);
23102+ if (!vdir) {
23103+ do_read = 1;
1308ab2a 23104+ vdir = alloc_vdir(file);
1facf9fc 23105+ err = PTR_ERR(vdir);
23106+ if (IS_ERR(vdir))
23107+ goto out;
23108+ err = 0;
23109+ allocated = vdir;
23110+ } else if (may_read
23111+ && (inode->i_version != vdir->vd_version
23112+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
23113+ do_read = 1;
23114+ err = reinit_vdir(vdir);
23115+ if (unlikely(err))
23116+ goto out;
23117+ }
23118+
23119+ if (!do_read)
23120+ return 0; /* success */
23121+
23122+ arg.file = file;
23123+ arg.vdir = vdir;
23124+ err = au_do_read_vdir(&arg);
23125+ if (!err) {
23126+ /* file->f_pos = 0; */
23127+ vdir->vd_version = inode->i_version;
23128+ vdir->vd_last.ul = 0;
23129+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
23130+ if (allocated)
23131+ au_set_ivdir(inode, allocated);
23132+ } else if (allocated)
23133+ au_vdir_free(allocated);
23134+
4f0767ce 23135+out:
1facf9fc 23136+ return err;
23137+}
23138+
23139+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
23140+{
23141+ int err, rerr;
23142+ unsigned long ul, n;
23143+ const unsigned int deblk_sz = src->vd_deblk_sz;
23144+
23145+ AuDebugOn(tgt->vd_nblk != 1);
23146+
23147+ err = -ENOMEM;
23148+ if (tgt->vd_nblk < src->vd_nblk) {
23149+ unsigned char **p;
23150+
dece6358
AM
23151+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
23152+ GFP_NOFS);
1facf9fc 23153+ if (unlikely(!p))
23154+ goto out;
23155+ tgt->vd_deblk = p;
23156+ }
23157+
1308ab2a 23158+ if (tgt->vd_deblk_sz != deblk_sz) {
23159+ unsigned char *p;
23160+
23161+ tgt->vd_deblk_sz = deblk_sz;
23162+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
23163+ if (unlikely(!p))
23164+ goto out;
23165+ tgt->vd_deblk[0] = p;
23166+ }
1facf9fc 23167+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 23168+ tgt->vd_version = src->vd_version;
23169+ tgt->vd_jiffy = src->vd_jiffy;
23170+
23171+ n = src->vd_nblk;
23172+ for (ul = 1; ul < n; ul++) {
dece6358
AM
23173+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
23174+ GFP_NOFS);
23175+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 23176+ goto out;
1308ab2a 23177+ tgt->vd_nblk++;
1facf9fc 23178+ }
1308ab2a 23179+ tgt->vd_nblk = n;
23180+ tgt->vd_last.ul = tgt->vd_last.ul;
23181+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
23182+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
23183+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 23184+ /* smp_mb(); */
23185+ return 0; /* success */
23186+
4f0767ce 23187+out:
1facf9fc 23188+ rerr = reinit_vdir(tgt);
23189+ BUG_ON(rerr);
23190+ return err;
23191+}
23192+
23193+int au_vdir_init(struct file *file)
23194+{
23195+ int err;
23196+ struct inode *inode;
23197+ struct au_vdir *vdir_cache, *allocated;
23198+
23199+ err = read_vdir(file, !file->f_pos);
23200+ if (unlikely(err))
23201+ goto out;
23202+
23203+ allocated = NULL;
23204+ vdir_cache = au_fvdir_cache(file);
23205+ if (!vdir_cache) {
1308ab2a 23206+ vdir_cache = alloc_vdir(file);
1facf9fc 23207+ err = PTR_ERR(vdir_cache);
23208+ if (IS_ERR(vdir_cache))
23209+ goto out;
23210+ allocated = vdir_cache;
23211+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
23212+ err = reinit_vdir(vdir_cache);
23213+ if (unlikely(err))
23214+ goto out;
23215+ } else
23216+ return 0; /* success */
23217+
23218+ inode = file->f_dentry->d_inode;
23219+ err = copy_vdir(vdir_cache, au_ivdir(inode));
23220+ if (!err) {
23221+ file->f_version = inode->i_version;
23222+ if (allocated)
23223+ au_set_fvdir_cache(file, allocated);
23224+ } else if (allocated)
23225+ au_vdir_free(allocated);
23226+
4f0767ce 23227+out:
1facf9fc 23228+ return err;
23229+}
23230+
23231+static loff_t calc_offset(struct au_vdir *vdir)
23232+{
23233+ loff_t offset;
23234+ union au_vdir_deblk_p p;
23235+
23236+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
23237+ offset = vdir->vd_last.p.deblk - p.deblk;
23238+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
23239+ return offset;
23240+}
23241+
23242+/* returns true or false */
23243+static int seek_vdir(struct file *file)
23244+{
23245+ int valid;
23246+ unsigned int deblk_sz;
23247+ unsigned long ul, n;
23248+ loff_t offset;
23249+ union au_vdir_deblk_p p, deblk_end;
23250+ struct au_vdir *vdir_cache;
23251+
23252+ valid = 1;
23253+ vdir_cache = au_fvdir_cache(file);
23254+ offset = calc_offset(vdir_cache);
23255+ AuDbg("offset %lld\n", offset);
23256+ if (file->f_pos == offset)
23257+ goto out;
23258+
23259+ vdir_cache->vd_last.ul = 0;
23260+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
23261+ if (!file->f_pos)
23262+ goto out;
23263+
23264+ valid = 0;
23265+ deblk_sz = vdir_cache->vd_deblk_sz;
23266+ ul = div64_u64(file->f_pos, deblk_sz);
23267+ AuDbg("ul %lu\n", ul);
23268+ if (ul >= vdir_cache->vd_nblk)
23269+ goto out;
23270+
23271+ n = vdir_cache->vd_nblk;
23272+ for (; ul < n; ul++) {
23273+ p.deblk = vdir_cache->vd_deblk[ul];
23274+ deblk_end.deblk = p.deblk + deblk_sz;
23275+ offset = ul;
23276+ offset *= deblk_sz;
23277+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
23278+ unsigned int l;
23279+
23280+ l = calc_size(p.de->de_str.len);
23281+ offset += l;
23282+ p.deblk += l;
23283+ }
23284+ if (!is_deblk_end(&p, &deblk_end)) {
23285+ valid = 1;
23286+ vdir_cache->vd_last.ul = ul;
23287+ vdir_cache->vd_last.p = p;
23288+ break;
23289+ }
23290+ }
23291+
4f0767ce 23292+out:
1facf9fc 23293+ /* smp_mb(); */
23294+ AuTraceErr(!valid);
23295+ return valid;
23296+}
23297+
23298+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
23299+{
23300+ int err;
23301+ unsigned int l, deblk_sz;
23302+ union au_vdir_deblk_p deblk_end;
23303+ struct au_vdir *vdir_cache;
23304+ struct au_vdir_de *de;
23305+
23306+ vdir_cache = au_fvdir_cache(file);
23307+ if (!seek_vdir(file))
23308+ return 0;
23309+
23310+ deblk_sz = vdir_cache->vd_deblk_sz;
23311+ while (1) {
23312+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
23313+ deblk_end.deblk += deblk_sz;
23314+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
23315+ de = vdir_cache->vd_last.p.de;
23316+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
23317+ de->de_str.len, de->de_str.name, file->f_pos,
23318+ (unsigned long)de->de_ino, de->de_type);
23319+ err = filldir(dirent, de->de_str.name, de->de_str.len,
23320+ file->f_pos, de->de_ino, de->de_type);
23321+ if (unlikely(err)) {
23322+ AuTraceErr(err);
23323+ /* todo: ignore the error caused by udba? */
23324+ /* return err; */
23325+ return 0;
23326+ }
23327+
23328+ l = calc_size(de->de_str.len);
23329+ vdir_cache->vd_last.p.deblk += l;
23330+ file->f_pos += l;
23331+ }
23332+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
23333+ vdir_cache->vd_last.ul++;
23334+ vdir_cache->vd_last.p.deblk
23335+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
23336+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
23337+ continue;
23338+ }
23339+ break;
23340+ }
23341+
23342+ /* smp_mb(); */
23343+ return 0;
23344+}
e49829fe
JR
23345--- /dev/null
23346+++ linux-2.6/fs/aufs/vfsub.c 2010-10-24 12:39:12.000000000 +0200
b752ccd1 23347@@ -0,0 +1,786 @@
1facf9fc 23348+/*
4a4d8108 23349+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 23350+ *
23351+ * This program, aufs is free software; you can redistribute it and/or modify
23352+ * it under the terms of the GNU General Public License as published by
23353+ * the Free Software Foundation; either version 2 of the License, or
23354+ * (at your option) any later version.
dece6358
AM
23355+ *
23356+ * This program is distributed in the hope that it will be useful,
23357+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23358+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23359+ * GNU General Public License for more details.
23360+ *
23361+ * You should have received a copy of the GNU General Public License
23362+ * along with this program; if not, write to the Free Software
23363+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23364+ */
23365+
23366+/*
23367+ * sub-routines for VFS
23368+ */
23369+
4a4d8108 23370+#include <linux/file.h>
1308ab2a 23371+#include <linux/ima.h>
dece6358
AM
23372+#include <linux/namei.h>
23373+#include <linux/security.h>
23374+#include <linux/splice.h>
1facf9fc 23375+#include <linux/uaccess.h>
23376+#include "aufs.h"
23377+
23378+int vfsub_update_h_iattr(struct path *h_path, int *did)
23379+{
23380+ int err;
23381+ struct kstat st;
23382+ struct super_block *h_sb;
23383+
23384+ /* for remote fs, leave work for its getattr or d_revalidate */
23385+ /* for bad i_attr fs, handle them in aufs_getattr() */
23386+ /* still some fs may acquire i_mutex. we need to skip them */
23387+ err = 0;
23388+ if (!did)
23389+ did = &err;
23390+ h_sb = h_path->dentry->d_sb;
23391+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
23392+ if (*did)
23393+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
23394+
23395+ return err;
23396+}
23397+
23398+/* ---------------------------------------------------------------------- */
23399+
4a4d8108
AM
23400+static int au_conv_oflags(int flags)
23401+{
23402+ int mask = 0;
23403+
23404+#ifdef CONFIG_IMA
23405+ fmode_t fmode;
23406+
23407+ /* mask = MAY_OPEN; */
23408+ fmode = OPEN_FMODE(flags);
23409+ if (fmode & FMODE_READ)
23410+ mask |= MAY_READ;
23411+ if ((fmode & FMODE_WRITE)
23412+ || (flags & O_TRUNC))
23413+ mask |= MAY_WRITE;
23414+ /*
23415+ * if (flags & O_APPEND)
23416+ * mask |= MAY_APPEND;
23417+ */
23418+ if (flags & vfsub_fmode_to_uint(FMODE_EXEC))
23419+ mask |= MAY_EXEC;
23420+
23421+ AuDbg("flags 0x%x, mask 0x%x\n", flags, mask);
23422+#endif
23423+
23424+ return mask;
23425+}
23426+
23427+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 23428+{
23429+ struct file *file;
4a4d8108 23430+ int err;
1308ab2a 23431+
4a4d8108
AM
23432+ path_get(path);
23433+ file = dentry_open(path->dentry, path->mnt, flags, current_cred());
1308ab2a 23434+ if (IS_ERR(file))
4a4d8108
AM
23435+ goto out;
23436+
23437+ err = ima_file_check(file, au_conv_oflags(flags));
23438+ if (unlikely(err)) {
23439+ fput(file);
23440+ file = ERR_PTR(err);
23441+ }
23442+out:
1308ab2a 23443+ return file;
23444+}
23445+
1facf9fc 23446+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
23447+{
23448+ struct file *file;
23449+
1facf9fc 23450+ file = filp_open(path, oflags, mode);
1facf9fc 23451+ if (IS_ERR(file))
23452+ goto out;
23453+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23454+
4f0767ce 23455+out:
1facf9fc 23456+ return file;
23457+}
23458+
23459+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
23460+{
23461+ int err;
23462+
1facf9fc 23463+ err = kern_path(name, flags, path);
1facf9fc 23464+ if (!err && path->dentry->d_inode)
23465+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
23466+ return err;
23467+}
23468+
23469+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
23470+ int len)
23471+{
23472+ struct path path = {
23473+ .mnt = NULL
23474+ };
23475+
1308ab2a 23476+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 23477+ IMustLock(parent->d_inode);
23478+
23479+ path.dentry = lookup_one_len(name, parent, len);
23480+ if (IS_ERR(path.dentry))
23481+ goto out;
23482+ if (path.dentry->d_inode)
23483+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
23484+
4f0767ce 23485+out:
4a4d8108 23486+ AuTraceErrPtr(path.dentry);
1facf9fc 23487+ return path.dentry;
23488+}
23489+
23490+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
23491+{
23492+ struct path path = {
23493+ .mnt = nd->path.mnt
23494+ };
23495+
23496+ IMustLock(nd->path.dentry->d_inode);
23497+
23498+ path.dentry = lookup_hash(nd);
4a4d8108
AM
23499+ if (IS_ERR(path.dentry))
23500+ goto out;
23501+ if (path.dentry->d_inode)
1facf9fc 23502+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
23503+
4f0767ce 23504+out:
4a4d8108 23505+ AuTraceErrPtr(path.dentry);
1facf9fc 23506+ return path.dentry;
23507+}
23508+
23509+/* ---------------------------------------------------------------------- */
23510+
23511+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
23512+ struct dentry *d2, struct au_hinode *hdir2)
23513+{
23514+ struct dentry *d;
23515+
1facf9fc 23516+ d = lock_rename(d1, d2);
4a4d8108 23517+ au_hn_suspend(hdir1);
1facf9fc 23518+ if (hdir1 != hdir2)
4a4d8108 23519+ au_hn_suspend(hdir2);
1facf9fc 23520+
23521+ return d;
23522+}
23523+
23524+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
23525+ struct dentry *d2, struct au_hinode *hdir2)
23526+{
4a4d8108 23527+ au_hn_resume(hdir1);
1facf9fc 23528+ if (hdir1 != hdir2)
4a4d8108 23529+ au_hn_resume(hdir2);
1facf9fc 23530+ unlock_rename(d1, d2);
1facf9fc 23531+}
23532+
23533+/* ---------------------------------------------------------------------- */
23534+
23535+int vfsub_create(struct inode *dir, struct path *path, int mode)
23536+{
23537+ int err;
23538+ struct dentry *d;
23539+
23540+ IMustLock(dir);
23541+
23542+ d = path->dentry;
23543+ path->dentry = d->d_parent;
b752ccd1 23544+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 23545+ path->dentry = d;
23546+ if (unlikely(err))
23547+ goto out;
23548+
23549+ if (au_test_fs_null_nd(dir->i_sb))
23550+ err = vfs_create(dir, path->dentry, mode, NULL);
23551+ else {
23552+ struct nameidata h_nd;
23553+
23554+ memset(&h_nd, 0, sizeof(h_nd));
23555+ h_nd.flags = LOOKUP_CREATE;
23556+ h_nd.intent.open.flags = O_CREAT
23557+ | vfsub_fmode_to_uint(FMODE_READ);
23558+ h_nd.intent.open.create_mode = mode;
23559+ h_nd.path.dentry = path->dentry->d_parent;
23560+ h_nd.path.mnt = path->mnt;
23561+ path_get(&h_nd.path);
23562+ err = vfs_create(dir, path->dentry, mode, &h_nd);
23563+ path_put(&h_nd.path);
23564+ }
23565+
23566+ if (!err) {
23567+ struct path tmp = *path;
23568+ int did;
23569+
23570+ vfsub_update_h_iattr(&tmp, &did);
23571+ if (did) {
23572+ tmp.dentry = path->dentry->d_parent;
23573+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23574+ }
23575+ /*ignore*/
23576+ }
23577+
4f0767ce 23578+out:
1facf9fc 23579+ return err;
23580+}
23581+
23582+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
23583+{
23584+ int err;
23585+ struct dentry *d;
23586+
23587+ IMustLock(dir);
23588+
23589+ d = path->dentry;
23590+ path->dentry = d->d_parent;
b752ccd1 23591+ err = security_path_symlink(path, d, symname);
1facf9fc 23592+ path->dentry = d;
23593+ if (unlikely(err))
23594+ goto out;
23595+
23596+ err = vfs_symlink(dir, path->dentry, symname);
23597+ if (!err) {
23598+ struct path tmp = *path;
23599+ int did;
23600+
23601+ vfsub_update_h_iattr(&tmp, &did);
23602+ if (did) {
23603+ tmp.dentry = path->dentry->d_parent;
23604+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23605+ }
23606+ /*ignore*/
23607+ }
23608+
4f0767ce 23609+out:
1facf9fc 23610+ return err;
23611+}
23612+
23613+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
23614+{
23615+ int err;
23616+ struct dentry *d;
23617+
23618+ IMustLock(dir);
23619+
23620+ d = path->dentry;
23621+ path->dentry = d->d_parent;
b752ccd1 23622+ err = security_path_mknod(path, d, mode, dev);
1facf9fc 23623+ path->dentry = d;
23624+ if (unlikely(err))
23625+ goto out;
23626+
23627+ err = vfs_mknod(dir, path->dentry, mode, dev);
23628+ if (!err) {
23629+ struct path tmp = *path;
23630+ int did;
23631+
23632+ vfsub_update_h_iattr(&tmp, &did);
23633+ if (did) {
23634+ tmp.dentry = path->dentry->d_parent;
23635+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23636+ }
23637+ /*ignore*/
23638+ }
23639+
4f0767ce 23640+out:
1facf9fc 23641+ return err;
23642+}
23643+
23644+static int au_test_nlink(struct inode *inode)
23645+{
23646+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
23647+
23648+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
23649+ || inode->i_nlink < link_max)
23650+ return 0;
23651+ return -EMLINK;
23652+}
23653+
23654+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
23655+{
23656+ int err;
23657+ struct dentry *d;
23658+
23659+ IMustLock(dir);
23660+
23661+ err = au_test_nlink(src_dentry->d_inode);
23662+ if (unlikely(err))
23663+ return err;
23664+
23665+ d = path->dentry;
23666+ path->dentry = d->d_parent;
b752ccd1 23667+ err = security_path_link(src_dentry, path, d);
1facf9fc 23668+ path->dentry = d;
23669+ if (unlikely(err))
23670+ goto out;
23671+
1facf9fc 23672+ err = vfs_link(src_dentry, dir, path->dentry);
1facf9fc 23673+ if (!err) {
23674+ struct path tmp = *path;
23675+ int did;
23676+
23677+ /* fuse has different memory inode for the same inumber */
23678+ vfsub_update_h_iattr(&tmp, &did);
23679+ if (did) {
23680+ tmp.dentry = path->dentry->d_parent;
23681+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23682+ tmp.dentry = src_dentry;
23683+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23684+ }
23685+ /*ignore*/
23686+ }
23687+
4f0767ce 23688+out:
1facf9fc 23689+ return err;
23690+}
23691+
23692+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
23693+ struct inode *dir, struct path *path)
23694+{
23695+ int err;
23696+ struct path tmp = {
23697+ .mnt = path->mnt
23698+ };
23699+ struct dentry *d;
23700+
23701+ IMustLock(dir);
23702+ IMustLock(src_dir);
23703+
23704+ d = path->dentry;
23705+ path->dentry = d->d_parent;
23706+ tmp.dentry = src_dentry->d_parent;
b752ccd1 23707+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 23708+ path->dentry = d;
23709+ if (unlikely(err))
23710+ goto out;
23711+
1facf9fc 23712+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
1facf9fc 23713+ if (!err) {
23714+ int did;
23715+
23716+ tmp.dentry = d->d_parent;
23717+ vfsub_update_h_iattr(&tmp, &did);
23718+ if (did) {
23719+ tmp.dentry = src_dentry;
23720+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23721+ tmp.dentry = src_dentry->d_parent;
23722+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23723+ }
23724+ /*ignore*/
23725+ }
23726+
4f0767ce 23727+out:
1facf9fc 23728+ return err;
23729+}
23730+
23731+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
23732+{
23733+ int err;
23734+ struct dentry *d;
23735+
23736+ IMustLock(dir);
23737+
23738+ d = path->dentry;
23739+ path->dentry = d->d_parent;
b752ccd1 23740+ err = security_path_mkdir(path, d, mode);
1facf9fc 23741+ path->dentry = d;
23742+ if (unlikely(err))
23743+ goto out;
23744+
23745+ err = vfs_mkdir(dir, path->dentry, mode);
23746+ if (!err) {
23747+ struct path tmp = *path;
23748+ int did;
23749+
23750+ vfsub_update_h_iattr(&tmp, &did);
23751+ if (did) {
23752+ tmp.dentry = path->dentry->d_parent;
23753+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23754+ }
23755+ /*ignore*/
23756+ }
23757+
4f0767ce 23758+out:
1facf9fc 23759+ return err;
23760+}
23761+
23762+int vfsub_rmdir(struct inode *dir, struct path *path)
23763+{
23764+ int err;
23765+ struct dentry *d;
23766+
23767+ IMustLock(dir);
23768+
23769+ d = path->dentry;
23770+ path->dentry = d->d_parent;
b752ccd1 23771+ err = security_path_rmdir(path, d);
1facf9fc 23772+ path->dentry = d;
23773+ if (unlikely(err))
23774+ goto out;
23775+
1facf9fc 23776+ err = vfs_rmdir(dir, path->dentry);
1facf9fc 23777+ if (!err) {
23778+ struct path tmp = {
23779+ .dentry = path->dentry->d_parent,
23780+ .mnt = path->mnt
23781+ };
23782+
23783+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
23784+ }
23785+
4f0767ce 23786+out:
1facf9fc 23787+ return err;
23788+}
23789+
23790+/* ---------------------------------------------------------------------- */
23791+
23792+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
23793+ loff_t *ppos)
23794+{
23795+ ssize_t err;
23796+
23797+ err = vfs_read(file, ubuf, count, ppos);
23798+ if (err >= 0)
23799+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23800+ return err;
23801+}
23802+
23803+/* todo: kernel_read()? */
23804+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
23805+ loff_t *ppos)
23806+{
23807+ ssize_t err;
23808+ mm_segment_t oldfs;
b752ccd1
AM
23809+ union {
23810+ void *k;
23811+ char __user *u;
23812+ } buf;
1facf9fc 23813+
b752ccd1 23814+ buf.k = kbuf;
1facf9fc 23815+ oldfs = get_fs();
23816+ set_fs(KERNEL_DS);
b752ccd1 23817+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 23818+ set_fs(oldfs);
23819+ return err;
23820+}
23821+
23822+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
23823+ loff_t *ppos)
23824+{
23825+ ssize_t err;
23826+
1facf9fc 23827+ err = vfs_write(file, ubuf, count, ppos);
1facf9fc 23828+ if (err >= 0)
23829+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23830+ return err;
23831+}
23832+
23833+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
23834+{
23835+ ssize_t err;
23836+ mm_segment_t oldfs;
b752ccd1
AM
23837+ union {
23838+ void *k;
23839+ const char __user *u;
23840+ } buf;
1facf9fc 23841+
b752ccd1 23842+ buf.k = kbuf;
1facf9fc 23843+ oldfs = get_fs();
23844+ set_fs(KERNEL_DS);
b752ccd1 23845+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 23846+ set_fs(oldfs);
23847+ return err;
23848+}
23849+
4a4d8108
AM
23850+int vfsub_flush(struct file *file, fl_owner_t id)
23851+{
23852+ int err;
23853+
23854+ err = 0;
23855+ if (file->f_op && file->f_op->flush) {
23856+ err = file->f_op->flush(file, id);
23857+ if (!err)
23858+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
23859+ /*ignore*/
23860+ }
23861+ return err;
23862+}
23863+
1facf9fc 23864+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
23865+{
23866+ int err;
23867+
1facf9fc 23868+ err = vfs_readdir(file, filldir, arg);
1facf9fc 23869+ if (err >= 0)
23870+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23871+ return err;
23872+}
23873+
23874+long vfsub_splice_to(struct file *in, loff_t *ppos,
23875+ struct pipe_inode_info *pipe, size_t len,
23876+ unsigned int flags)
23877+{
23878+ long err;
23879+
0fc653ad 23880+ err = do_splice_to(in, ppos, pipe, len, flags);
4a4d8108 23881+ file_accessed(in);
1facf9fc 23882+ if (err >= 0)
23883+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
23884+ return err;
23885+}
23886+
23887+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
23888+ loff_t *ppos, size_t len, unsigned int flags)
23889+{
23890+ long err;
23891+
0fc653ad 23892+ err = do_splice_from(pipe, out, ppos, len, flags);
1facf9fc 23893+ if (err >= 0)
23894+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
23895+ return err;
23896+}
23897+
23898+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
23899+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
23900+ struct file *h_file)
23901+{
23902+ int err;
23903+ struct inode *h_inode;
23904+
23905+ h_inode = h_path->dentry->d_inode;
23906+ if (!h_file) {
23907+ err = mnt_want_write(h_path->mnt);
23908+ if (err)
23909+ goto out;
23910+ err = inode_permission(h_inode, MAY_WRITE);
23911+ if (err)
23912+ goto out_mnt;
23913+ err = get_write_access(h_inode);
23914+ if (err)
23915+ goto out_mnt;
4a4d8108 23916+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 23917+ if (err)
23918+ goto out_inode;
23919+ }
23920+
23921+ err = locks_verify_truncate(h_inode, h_file, length);
23922+ if (!err)
953406b4 23923+ err = security_path_truncate(h_path);
b752ccd1 23924+ if (!err)
1facf9fc 23925+ err = do_truncate(h_path->dentry, length, attr, h_file);
1facf9fc 23926+
4f0767ce 23927+out_inode:
1facf9fc 23928+ if (!h_file)
23929+ put_write_access(h_inode);
4f0767ce 23930+out_mnt:
1facf9fc 23931+ if (!h_file)
23932+ mnt_drop_write(h_path->mnt);
4f0767ce 23933+out:
1facf9fc 23934+ return err;
23935+}
23936+
23937+/* ---------------------------------------------------------------------- */
23938+
23939+struct au_vfsub_mkdir_args {
23940+ int *errp;
23941+ struct inode *dir;
23942+ struct path *path;
23943+ int mode;
23944+};
23945+
23946+static void au_call_vfsub_mkdir(void *args)
23947+{
23948+ struct au_vfsub_mkdir_args *a = args;
23949+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
23950+}
23951+
23952+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
23953+{
23954+ int err, do_sio, wkq_err;
23955+
23956+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
23957+ if (!do_sio)
23958+ err = vfsub_mkdir(dir, path, mode);
23959+ else {
23960+ struct au_vfsub_mkdir_args args = {
23961+ .errp = &err,
23962+ .dir = dir,
23963+ .path = path,
23964+ .mode = mode
23965+ };
23966+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
23967+ if (unlikely(wkq_err))
23968+ err = wkq_err;
23969+ }
23970+
23971+ return err;
23972+}
23973+
23974+struct au_vfsub_rmdir_args {
23975+ int *errp;
23976+ struct inode *dir;
23977+ struct path *path;
23978+};
23979+
23980+static void au_call_vfsub_rmdir(void *args)
23981+{
23982+ struct au_vfsub_rmdir_args *a = args;
23983+ *a->errp = vfsub_rmdir(a->dir, a->path);
23984+}
23985+
23986+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
23987+{
23988+ int err, do_sio, wkq_err;
23989+
23990+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
23991+ if (!do_sio)
23992+ err = vfsub_rmdir(dir, path);
23993+ else {
23994+ struct au_vfsub_rmdir_args args = {
23995+ .errp = &err,
23996+ .dir = dir,
23997+ .path = path
23998+ };
23999+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
24000+ if (unlikely(wkq_err))
24001+ err = wkq_err;
24002+ }
24003+
24004+ return err;
24005+}
24006+
24007+/* ---------------------------------------------------------------------- */
24008+
24009+struct notify_change_args {
24010+ int *errp;
24011+ struct path *path;
24012+ struct iattr *ia;
24013+};
24014+
24015+static void call_notify_change(void *args)
24016+{
24017+ struct notify_change_args *a = args;
24018+ struct inode *h_inode;
24019+
24020+ h_inode = a->path->dentry->d_inode;
24021+ IMustLock(h_inode);
24022+
24023+ *a->errp = -EPERM;
24024+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 24025+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 24026+ if (!*a->errp)
24027+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
24028+ }
24029+ AuTraceErr(*a->errp);
24030+}
24031+
24032+int vfsub_notify_change(struct path *path, struct iattr *ia)
24033+{
24034+ int err;
24035+ struct notify_change_args args = {
24036+ .errp = &err,
24037+ .path = path,
24038+ .ia = ia
24039+ };
24040+
24041+ call_notify_change(&args);
24042+
24043+ return err;
24044+}
24045+
24046+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
24047+{
24048+ int err, wkq_err;
24049+ struct notify_change_args args = {
24050+ .errp = &err,
24051+ .path = path,
24052+ .ia = ia
24053+ };
24054+
24055+ wkq_err = au_wkq_wait(call_notify_change, &args);
24056+ if (unlikely(wkq_err))
24057+ err = wkq_err;
24058+
24059+ return err;
24060+}
24061+
24062+/* ---------------------------------------------------------------------- */
24063+
24064+struct unlink_args {
24065+ int *errp;
24066+ struct inode *dir;
24067+ struct path *path;
24068+};
24069+
24070+static void call_unlink(void *args)
24071+{
24072+ struct unlink_args *a = args;
24073+ struct dentry *d = a->path->dentry;
24074+ struct inode *h_inode;
24075+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
24076+ && atomic_read(&d->d_count) == 1);
24077+
24078+ IMustLock(a->dir);
24079+
24080+ a->path->dentry = d->d_parent;
24081+ *a->errp = security_path_unlink(a->path, d);
24082+ a->path->dentry = d;
24083+ if (unlikely(*a->errp))
24084+ return;
24085+
24086+ if (!stop_sillyrename)
24087+ dget(d);
24088+ h_inode = d->d_inode;
24089+ if (h_inode)
24090+ atomic_inc(&h_inode->i_count);
24091+
1facf9fc 24092+ *a->errp = vfs_unlink(a->dir, d);
1facf9fc 24093+ if (!*a->errp) {
24094+ struct path tmp = {
24095+ .dentry = d->d_parent,
24096+ .mnt = a->path->mnt
24097+ };
24098+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
24099+ }
24100+
24101+ if (!stop_sillyrename)
24102+ dput(d);
24103+ if (h_inode)
24104+ iput(h_inode);
24105+
24106+ AuTraceErr(*a->errp);
24107+}
24108+
24109+/*
24110+ * @dir: must be locked.
24111+ * @dentry: target dentry.
24112+ */
24113+int vfsub_unlink(struct inode *dir, struct path *path, int force)
24114+{
24115+ int err;
24116+ struct unlink_args args = {
24117+ .errp = &err,
24118+ .dir = dir,
24119+ .path = path
24120+ };
24121+
24122+ if (!force)
24123+ call_unlink(&args);
24124+ else {
24125+ int wkq_err;
24126+
24127+ wkq_err = au_wkq_wait(call_unlink, &args);
24128+ if (unlikely(wkq_err))
24129+ err = wkq_err;
24130+ }
24131+
24132+ return err;
24133+}
e49829fe
JR
24134--- /dev/null
24135+++ linux-2.6/fs/aufs/vfsub.h 2010-10-24 11:19:23.000000000 +0200
b752ccd1 24136@@ -0,0 +1,174 @@
1facf9fc 24137+/*
4a4d8108 24138+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 24139+ *
24140+ * This program, aufs is free software; you can redistribute it and/or modify
24141+ * it under the terms of the GNU General Public License as published by
24142+ * the Free Software Foundation; either version 2 of the License, or
24143+ * (at your option) any later version.
dece6358
AM
24144+ *
24145+ * This program is distributed in the hope that it will be useful,
24146+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24147+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24148+ * GNU General Public License for more details.
24149+ *
24150+ * You should have received a copy of the GNU General Public License
24151+ * along with this program; if not, write to the Free Software
24152+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24153+ */
24154+
24155+/*
24156+ * sub-routines for VFS
24157+ */
24158+
24159+#ifndef __AUFS_VFSUB_H__
24160+#define __AUFS_VFSUB_H__
24161+
24162+#ifdef __KERNEL__
24163+
24164+#include <linux/fs.h>
1facf9fc 24165+
24166+/* ---------------------------------------------------------------------- */
24167+
24168+/* lock subclass for lower inode */
24169+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
24170+/* reduce? gave up. */
24171+enum {
24172+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
24173+ AuLsc_I_PARENT, /* lower inode, parent first */
24174+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 24175+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 24176+ AuLsc_I_CHILD,
24177+ AuLsc_I_CHILD2,
24178+ AuLsc_I_End
24179+};
24180+
24181+/* to debug easier, do not make them inlined functions */
24182+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
24183+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
24184+
24185+/* ---------------------------------------------------------------------- */
24186+
1facf9fc 24187+int vfsub_update_h_iattr(struct path *h_path, int *did);
4a4d8108 24188+struct file *vfsub_dentry_open(struct path *path, int flags);
1facf9fc 24189+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
24190+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
24191+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
24192+ int len);
24193+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
24194+
24195+/* ---------------------------------------------------------------------- */
24196+
24197+struct au_hinode;
24198+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
24199+ struct dentry *d2, struct au_hinode *hdir2);
24200+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
24201+ struct dentry *d2, struct au_hinode *hdir2);
24202+
24203+int vfsub_create(struct inode *dir, struct path *path, int mode);
24204+int vfsub_symlink(struct inode *dir, struct path *path,
24205+ const char *symname);
24206+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
24207+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
24208+ struct path *path);
24209+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
24210+ struct inode *hdir, struct path *path);
24211+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
24212+int vfsub_rmdir(struct inode *dir, struct path *path);
24213+
24214+/* ---------------------------------------------------------------------- */
24215+
24216+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
24217+ loff_t *ppos);
24218+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
24219+ loff_t *ppos);
24220+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
24221+ loff_t *ppos);
24222+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
24223+ loff_t *ppos);
4a4d8108 24224+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 24225+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
24226+
4a4d8108
AM
24227+static inline unsigned int vfsub_file_flags(struct file *file)
24228+{
24229+ unsigned int flags;
24230+
24231+ spin_lock(&file->f_lock);
24232+ flags = file->f_flags;
24233+ spin_unlock(&file->f_lock);
24234+
24235+ return flags;
24236+}
1308ab2a 24237+
1facf9fc 24238+static inline void vfsub_file_accessed(struct file *h_file)
24239+{
24240+ file_accessed(h_file);
24241+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
24242+}
24243+
24244+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
24245+ struct dentry *h_dentry)
24246+{
24247+ struct path h_path = {
24248+ .dentry = h_dentry,
24249+ .mnt = h_mnt
24250+ };
24251+ touch_atime(h_mnt, h_dentry);
24252+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
24253+}
24254+
4a4d8108
AM
24255+long vfsub_splice_to(struct file *in, loff_t *ppos,
24256+ struct pipe_inode_info *pipe, size_t len,
24257+ unsigned int flags);
24258+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
24259+ loff_t *ppos, size_t len, unsigned int flags);
24260+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
24261+ struct file *h_file);
24262+
1facf9fc 24263+/* ---------------------------------------------------------------------- */
24264+
24265+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
24266+{
24267+ loff_t err;
24268+
1facf9fc 24269+ err = vfs_llseek(file, offset, origin);
1facf9fc 24270+ return err;
24271+}
24272+
24273+/* ---------------------------------------------------------------------- */
24274+
24275+/* dirty workaround for strict type of fmode_t */
24276+union vfsub_fmu {
24277+ fmode_t fm;
24278+ unsigned int ui;
24279+};
24280+
24281+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
24282+{
24283+ union vfsub_fmu u = {
24284+ .fm = fm
24285+ };
24286+
24287+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
24288+
24289+ return u.ui;
24290+}
24291+
24292+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
24293+{
24294+ union vfsub_fmu u = {
24295+ .ui = ui
24296+ };
24297+
24298+ return u.fm;
24299+}
24300+
4a4d8108
AM
24301+/* ---------------------------------------------------------------------- */
24302+
24303+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
24304+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
24305+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
24306+int vfsub_notify_change(struct path *path, struct iattr *ia);
24307+int vfsub_unlink(struct inode *dir, struct path *path, int force);
24308+
1facf9fc 24309+#endif /* __KERNEL__ */
24310+#endif /* __AUFS_VFSUB_H__ */
e49829fe
JR
24311--- /dev/null
24312+++ linux-2.6/fs/aufs/wbr_policy.c 2010-10-24 14:48:12.000000000 +0200
953406b4 24313@@ -0,0 +1,699 @@
1facf9fc 24314+/*
4a4d8108 24315+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 24316+ *
24317+ * This program, aufs is free software; you can redistribute it and/or modify
24318+ * it under the terms of the GNU General Public License as published by
24319+ * the Free Software Foundation; either version 2 of the License, or
24320+ * (at your option) any later version.
dece6358
AM
24321+ *
24322+ * This program is distributed in the hope that it will be useful,
24323+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24324+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24325+ * GNU General Public License for more details.
24326+ *
24327+ * You should have received a copy of the GNU General Public License
24328+ * along with this program; if not, write to the Free Software
24329+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24330+ */
24331+
24332+/*
24333+ * policies for selecting one among multiple writable branches
24334+ */
24335+
24336+#include <linux/statfs.h>
24337+#include "aufs.h"
24338+
24339+/* subset of cpup_attr() */
24340+static noinline_for_stack
24341+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
24342+{
24343+ int err, sbits;
24344+ struct iattr ia;
24345+ struct inode *h_isrc;
24346+
24347+ h_isrc = h_src->d_inode;
24348+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
24349+ ia.ia_mode = h_isrc->i_mode;
24350+ ia.ia_uid = h_isrc->i_uid;
24351+ ia.ia_gid = h_isrc->i_gid;
24352+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
24353+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
24354+ err = vfsub_sio_notify_change(h_path, &ia);
24355+
24356+ /* is this nfs only? */
24357+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
24358+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
24359+ ia.ia_mode = h_isrc->i_mode;
24360+ err = vfsub_sio_notify_change(h_path, &ia);
24361+ }
24362+
24363+ return err;
24364+}
24365+
24366+#define AuCpdown_PARENT_OPQ 1
24367+#define AuCpdown_WHED (1 << 1)
24368+#define AuCpdown_MADE_DIR (1 << 2)
24369+#define AuCpdown_DIROPQ (1 << 3)
24370+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
24371+#define au_fset_cpdown(flags, name) { (flags) |= AuCpdown_##name; }
24372+#define au_fclr_cpdown(flags, name) { (flags) &= ~AuCpdown_##name; }
24373+
24374+struct au_cpdown_dir_args {
24375+ struct dentry *parent;
24376+ unsigned int flags;
24377+};
24378+
24379+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
24380+ struct au_cpdown_dir_args *a)
24381+{
24382+ int err;
24383+ struct dentry *opq_dentry;
24384+
24385+ opq_dentry = au_diropq_create(dentry, bdst);
24386+ err = PTR_ERR(opq_dentry);
24387+ if (IS_ERR(opq_dentry))
24388+ goto out;
24389+ dput(opq_dentry);
24390+ au_fset_cpdown(a->flags, DIROPQ);
24391+
4f0767ce 24392+out:
1facf9fc 24393+ return err;
24394+}
24395+
24396+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
24397+ struct inode *dir, aufs_bindex_t bdst)
24398+{
24399+ int err;
24400+ struct path h_path;
24401+ struct au_branch *br;
24402+
24403+ br = au_sbr(dentry->d_sb, bdst);
24404+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
24405+ err = PTR_ERR(h_path.dentry);
24406+ if (IS_ERR(h_path.dentry))
24407+ goto out;
24408+
24409+ err = 0;
24410+ if (h_path.dentry->d_inode) {
24411+ h_path.mnt = br->br_mnt;
24412+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
24413+ dentry);
24414+ }
24415+ dput(h_path.dentry);
24416+
4f0767ce 24417+out:
1facf9fc 24418+ return err;
24419+}
24420+
24421+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
24422+ struct dentry *h_parent, void *arg)
24423+{
24424+ int err, rerr;
4a4d8108 24425+ aufs_bindex_t bopq, bstart;
1facf9fc 24426+ struct path h_path;
24427+ struct dentry *parent;
24428+ struct inode *h_dir, *h_inode, *inode, *dir;
24429+ struct au_cpdown_dir_args *args = arg;
24430+
24431+ bstart = au_dbstart(dentry);
24432+ /* dentry is di-locked */
24433+ parent = dget_parent(dentry);
24434+ dir = parent->d_inode;
24435+ h_dir = h_parent->d_inode;
24436+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
24437+ IMustLock(h_dir);
24438+
24439+ err = au_lkup_neg(dentry, bdst);
24440+ if (unlikely(err < 0))
24441+ goto out;
24442+ h_path.dentry = au_h_dptr(dentry, bdst);
24443+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
24444+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
24445+ S_IRWXU | S_IRUGO | S_IXUGO);
24446+ if (unlikely(err))
24447+ goto out_put;
24448+ au_fset_cpdown(args->flags, MADE_DIR);
24449+
1facf9fc 24450+ bopq = au_dbdiropq(dentry);
24451+ au_fclr_cpdown(args->flags, WHED);
24452+ au_fclr_cpdown(args->flags, DIROPQ);
24453+ if (au_dbwh(dentry) == bdst)
24454+ au_fset_cpdown(args->flags, WHED);
24455+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
24456+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 24457+ h_inode = h_path.dentry->d_inode;
24458+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
24459+ if (au_ftest_cpdown(args->flags, WHED)) {
24460+ err = au_cpdown_dir_opq(dentry, bdst, args);
24461+ if (unlikely(err)) {
24462+ mutex_unlock(&h_inode->i_mutex);
24463+ goto out_dir;
24464+ }
24465+ }
24466+
24467+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
24468+ mutex_unlock(&h_inode->i_mutex);
24469+ if (unlikely(err))
24470+ goto out_opq;
24471+
24472+ if (au_ftest_cpdown(args->flags, WHED)) {
24473+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
24474+ if (unlikely(err))
24475+ goto out_opq;
24476+ }
24477+
24478+ inode = dentry->d_inode;
24479+ if (au_ibend(inode) < bdst)
24480+ au_set_ibend(inode, bdst);
24481+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
24482+ au_hi_flags(inode, /*isdir*/1));
24483+ goto out; /* success */
24484+
24485+ /* revert */
4f0767ce 24486+out_opq:
1facf9fc 24487+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
24488+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
24489+ rerr = au_diropq_remove(dentry, bdst);
24490+ mutex_unlock(&h_inode->i_mutex);
24491+ if (unlikely(rerr)) {
24492+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
24493+ AuDLNPair(dentry), bdst, rerr);
24494+ err = -EIO;
24495+ goto out;
24496+ }
24497+ }
4f0767ce 24498+out_dir:
1facf9fc 24499+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
24500+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
24501+ if (unlikely(rerr)) {
24502+ AuIOErr("failed removing %.*s b%d (%d)\n",
24503+ AuDLNPair(dentry), bdst, rerr);
24504+ err = -EIO;
24505+ }
24506+ }
4f0767ce 24507+out_put:
1facf9fc 24508+ au_set_h_dptr(dentry, bdst, NULL);
24509+ if (au_dbend(dentry) == bdst)
24510+ au_update_dbend(dentry);
4f0767ce 24511+out:
1facf9fc 24512+ dput(parent);
24513+ return err;
24514+}
24515+
24516+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
24517+{
24518+ int err;
24519+ struct au_cpdown_dir_args args = {
24520+ .parent = dget_parent(dentry),
24521+ .flags = 0
24522+ };
24523+
24524+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
24525+ dput(args.parent);
24526+
24527+ return err;
24528+}
24529+
24530+/* ---------------------------------------------------------------------- */
24531+
24532+/* policies for create */
24533+
4a4d8108
AM
24534+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
24535+{
24536+ int err, i, j, ndentry;
24537+ aufs_bindex_t bopq;
24538+ struct au_dcsub_pages dpages;
24539+ struct au_dpage *dpage;
24540+ struct dentry **dentries, *parent, *d;
24541+
24542+ err = au_dpages_init(&dpages, GFP_NOFS);
24543+ if (unlikely(err))
24544+ goto out;
24545+ parent = dget_parent(dentry);
24546+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/0, /*test*/NULL,
24547+ /*arg*/NULL);
24548+ if (unlikely(err))
24549+ goto out_free;
24550+
24551+ err = bindex;
24552+ for (i = 0; i < dpages.ndpage; i++) {
24553+ dpage = dpages.dpages + i;
24554+ dentries = dpage->dentries;
24555+ ndentry = dpage->ndentry;
24556+ for (j = 0; j < ndentry; j++) {
24557+ d = dentries[j];
24558+ di_read_lock_parent2(d, !AuLock_IR);
24559+ bopq = au_dbdiropq(d);
24560+ di_read_unlock(d, !AuLock_IR);
24561+ if (bopq >= 0 && bopq < err)
24562+ err = bopq;
24563+ }
24564+ }
24565+
24566+out_free:
24567+ dput(parent);
24568+ au_dpages_free(&dpages);
24569+out:
24570+ return err;
24571+}
24572+
1facf9fc 24573+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
24574+{
24575+ for (; bindex >= 0; bindex--)
24576+ if (!au_br_rdonly(au_sbr(sb, bindex)))
24577+ return bindex;
24578+ return -EROFS;
24579+}
24580+
24581+/* top down parent */
24582+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
24583+{
24584+ int err;
24585+ aufs_bindex_t bstart, bindex;
24586+ struct super_block *sb;
24587+ struct dentry *parent, *h_parent;
24588+
24589+ sb = dentry->d_sb;
24590+ bstart = au_dbstart(dentry);
24591+ err = bstart;
24592+ if (!au_br_rdonly(au_sbr(sb, bstart)))
24593+ goto out;
24594+
24595+ err = -EROFS;
24596+ parent = dget_parent(dentry);
24597+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
24598+ h_parent = au_h_dptr(parent, bindex);
24599+ if (!h_parent || !h_parent->d_inode)
24600+ continue;
24601+
24602+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
24603+ err = bindex;
24604+ break;
24605+ }
24606+ }
24607+ dput(parent);
24608+
24609+ /* bottom up here */
4a4d8108 24610+ if (unlikely(err < 0)) {
1facf9fc 24611+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
24612+ if (err >= 0)
24613+ err = au_wbr_nonopq(dentry, err);
24614+ }
1facf9fc 24615+
4f0767ce 24616+out:
1facf9fc 24617+ AuDbg("b%d\n", err);
24618+ return err;
24619+}
24620+
24621+/* ---------------------------------------------------------------------- */
24622+
24623+/* an exception for the policy other than tdp */
24624+static int au_wbr_create_exp(struct dentry *dentry)
24625+{
24626+ int err;
24627+ aufs_bindex_t bwh, bdiropq;
24628+ struct dentry *parent;
24629+
24630+ err = -1;
24631+ bwh = au_dbwh(dentry);
24632+ parent = dget_parent(dentry);
24633+ bdiropq = au_dbdiropq(parent);
24634+ if (bwh >= 0) {
24635+ if (bdiropq >= 0)
24636+ err = min(bdiropq, bwh);
24637+ else
24638+ err = bwh;
24639+ AuDbg("%d\n", err);
24640+ } else if (bdiropq >= 0) {
24641+ err = bdiropq;
24642+ AuDbg("%d\n", err);
24643+ }
24644+ dput(parent);
24645+
4a4d8108
AM
24646+ if (err >= 0)
24647+ err = au_wbr_nonopq(dentry, err);
24648+
1facf9fc 24649+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
24650+ err = -1;
24651+
24652+ AuDbg("%d\n", err);
24653+ return err;
24654+}
24655+
24656+/* ---------------------------------------------------------------------- */
24657+
24658+/* round robin */
24659+static int au_wbr_create_init_rr(struct super_block *sb)
24660+{
24661+ int err;
24662+
24663+ err = au_wbr_bu(sb, au_sbend(sb));
24664+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 24665+ /* smp_mb(); */
1facf9fc 24666+
24667+ AuDbg("b%d\n", err);
24668+ return err;
24669+}
24670+
24671+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
24672+{
24673+ int err, nbr;
24674+ unsigned int u;
24675+ aufs_bindex_t bindex, bend;
24676+ struct super_block *sb;
24677+ atomic_t *next;
24678+
24679+ err = au_wbr_create_exp(dentry);
24680+ if (err >= 0)
24681+ goto out;
24682+
24683+ sb = dentry->d_sb;
24684+ next = &au_sbi(sb)->si_wbr_rr_next;
24685+ bend = au_sbend(sb);
24686+ nbr = bend + 1;
24687+ for (bindex = 0; bindex <= bend; bindex++) {
24688+ if (!isdir) {
24689+ err = atomic_dec_return(next) + 1;
24690+ /* modulo for 0 is meaningless */
24691+ if (unlikely(!err))
24692+ err = atomic_dec_return(next) + 1;
24693+ } else
24694+ err = atomic_read(next);
24695+ AuDbg("%d\n", err);
24696+ u = err;
24697+ err = u % nbr;
24698+ AuDbg("%d\n", err);
24699+ if (!au_br_rdonly(au_sbr(sb, err)))
24700+ break;
24701+ err = -EROFS;
24702+ }
24703+
4a4d8108
AM
24704+ if (err >= 0)
24705+ err = au_wbr_nonopq(dentry, err);
24706+
4f0767ce 24707+out:
1facf9fc 24708+ AuDbg("%d\n", err);
24709+ return err;
24710+}
24711+
24712+/* ---------------------------------------------------------------------- */
24713+
24714+/* most free space */
24715+static void au_mfs(struct dentry *dentry)
24716+{
24717+ struct super_block *sb;
24718+ struct au_branch *br;
24719+ struct au_wbr_mfs *mfs;
24720+ aufs_bindex_t bindex, bend;
24721+ int err;
24722+ unsigned long long b, bavail;
953406b4 24723+ struct path h_path;
1facf9fc 24724+ /* reduce the stack usage */
24725+ struct kstatfs *st;
24726+
24727+ st = kmalloc(sizeof(*st), GFP_NOFS);
24728+ if (unlikely(!st)) {
24729+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
24730+ return;
24731+ }
24732+
24733+ bavail = 0;
24734+ sb = dentry->d_sb;
24735+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 24736+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 24737+ mfs->mfs_bindex = -EROFS;
24738+ mfs->mfsrr_bytes = 0;
24739+ bend = au_sbend(sb);
24740+ for (bindex = 0; bindex <= bend; bindex++) {
24741+ br = au_sbr(sb, bindex);
24742+ if (au_br_rdonly(br))
24743+ continue;
24744+
24745+ /* sb->s_root for NFS is unreliable */
953406b4
AM
24746+ h_path.mnt = br->br_mnt;
24747+ h_path.dentry = h_path.mnt->mnt_root;
24748+ err = vfs_statfs(&h_path, st);
1facf9fc 24749+ if (unlikely(err)) {
24750+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
24751+ continue;
24752+ }
24753+
24754+ /* when the available size is equal, select the lower one */
24755+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
24756+ || sizeof(b) < sizeof(st->f_bsize));
24757+ b = st->f_bavail * st->f_bsize;
24758+ br->br_wbr->wbr_bytes = b;
24759+ if (b >= bavail) {
24760+ bavail = b;
24761+ mfs->mfs_bindex = bindex;
24762+ mfs->mfs_jiffy = jiffies;
24763+ }
24764+ }
24765+
24766+ mfs->mfsrr_bytes = bavail;
24767+ AuDbg("b%d\n", mfs->mfs_bindex);
24768+ kfree(st);
24769+}
24770+
24771+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
24772+{
24773+ int err;
24774+ struct super_block *sb;
24775+ struct au_wbr_mfs *mfs;
24776+
24777+ err = au_wbr_create_exp(dentry);
24778+ if (err >= 0)
24779+ goto out;
24780+
24781+ sb = dentry->d_sb;
24782+ mfs = &au_sbi(sb)->si_wbr_mfs;
24783+ mutex_lock(&mfs->mfs_lock);
24784+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
24785+ || mfs->mfs_bindex < 0
24786+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
24787+ au_mfs(dentry);
24788+ mutex_unlock(&mfs->mfs_lock);
24789+ err = mfs->mfs_bindex;
24790+
4a4d8108
AM
24791+ if (err >= 0)
24792+ err = au_wbr_nonopq(dentry, err);
24793+
4f0767ce 24794+out:
1facf9fc 24795+ AuDbg("b%d\n", err);
24796+ return err;
24797+}
24798+
24799+static int au_wbr_create_init_mfs(struct super_block *sb)
24800+{
24801+ struct au_wbr_mfs *mfs;
24802+
24803+ mfs = &au_sbi(sb)->si_wbr_mfs;
24804+ mutex_init(&mfs->mfs_lock);
24805+ mfs->mfs_jiffy = 0;
24806+ mfs->mfs_bindex = -EROFS;
24807+
24808+ return 0;
24809+}
24810+
24811+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
24812+{
24813+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
24814+ return 0;
24815+}
24816+
24817+/* ---------------------------------------------------------------------- */
24818+
24819+/* most free space and then round robin */
24820+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
24821+{
24822+ int err;
24823+ struct au_wbr_mfs *mfs;
24824+
24825+ err = au_wbr_create_mfs(dentry, isdir);
24826+ if (err >= 0) {
24827+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 24828+ mutex_lock(&mfs->mfs_lock);
1facf9fc 24829+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
24830+ err = au_wbr_create_rr(dentry, isdir);
dece6358 24831+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 24832+ }
24833+
24834+ AuDbg("b%d\n", err);
24835+ return err;
24836+}
24837+
24838+static int au_wbr_create_init_mfsrr(struct super_block *sb)
24839+{
24840+ int err;
24841+
24842+ au_wbr_create_init_mfs(sb); /* ignore */
24843+ err = au_wbr_create_init_rr(sb);
24844+
24845+ return err;
24846+}
24847+
24848+/* ---------------------------------------------------------------------- */
24849+
24850+/* top down parent and most free space */
24851+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
24852+{
24853+ int err, e2;
24854+ unsigned long long b;
24855+ aufs_bindex_t bindex, bstart, bend;
24856+ struct super_block *sb;
24857+ struct dentry *parent, *h_parent;
24858+ struct au_branch *br;
24859+
24860+ err = au_wbr_create_tdp(dentry, isdir);
24861+ if (unlikely(err < 0))
24862+ goto out;
24863+ parent = dget_parent(dentry);
24864+ bstart = au_dbstart(parent);
24865+ bend = au_dbtaildir(parent);
24866+ if (bstart == bend)
24867+ goto out_parent; /* success */
24868+
24869+ e2 = au_wbr_create_mfs(dentry, isdir);
24870+ if (e2 < 0)
24871+ goto out_parent; /* success */
24872+
24873+ /* when the available size is equal, select upper one */
24874+ sb = dentry->d_sb;
24875+ br = au_sbr(sb, err);
24876+ b = br->br_wbr->wbr_bytes;
24877+ AuDbg("b%d, %llu\n", err, b);
24878+
24879+ for (bindex = bstart; bindex <= bend; bindex++) {
24880+ h_parent = au_h_dptr(parent, bindex);
24881+ if (!h_parent || !h_parent->d_inode)
24882+ continue;
24883+
24884+ br = au_sbr(sb, bindex);
24885+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
24886+ b = br->br_wbr->wbr_bytes;
24887+ err = bindex;
24888+ AuDbg("b%d, %llu\n", err, b);
24889+ }
24890+ }
24891+
4a4d8108
AM
24892+ if (err >= 0)
24893+ err = au_wbr_nonopq(dentry, err);
24894+
4f0767ce 24895+out_parent:
1facf9fc 24896+ dput(parent);
4f0767ce 24897+out:
1facf9fc 24898+ AuDbg("b%d\n", err);
24899+ return err;
24900+}
24901+
24902+/* ---------------------------------------------------------------------- */
24903+
24904+/* policies for copyup */
24905+
24906+/* top down parent */
24907+static int au_wbr_copyup_tdp(struct dentry *dentry)
24908+{
24909+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
24910+}
24911+
24912+/* bottom up parent */
24913+static int au_wbr_copyup_bup(struct dentry *dentry)
24914+{
24915+ int err;
24916+ aufs_bindex_t bindex, bstart;
24917+ struct dentry *parent, *h_parent;
24918+ struct super_block *sb;
24919+
24920+ err = -EROFS;
24921+ sb = dentry->d_sb;
24922+ parent = dget_parent(dentry);
24923+ bstart = au_dbstart(parent);
24924+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
24925+ h_parent = au_h_dptr(parent, bindex);
24926+ if (!h_parent || !h_parent->d_inode)
24927+ continue;
24928+
24929+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
24930+ err = bindex;
24931+ break;
24932+ }
24933+ }
24934+ dput(parent);
24935+
24936+ /* bottom up here */
24937+ if (unlikely(err < 0))
24938+ err = au_wbr_bu(sb, bstart - 1);
24939+
24940+ AuDbg("b%d\n", err);
24941+ return err;
24942+}
24943+
24944+/* bottom up */
24945+static int au_wbr_copyup_bu(struct dentry *dentry)
24946+{
24947+ int err;
4a4d8108 24948+ aufs_bindex_t bstart;
1facf9fc 24949+
4a4d8108
AM
24950+ bstart = au_dbstart(dentry);
24951+ err = au_wbr_bu(dentry->d_sb, bstart);
24952+ AuDbg("b%d\n", err);
24953+ if (err > bstart)
24954+ err = au_wbr_nonopq(dentry, err);
1facf9fc 24955+
24956+ AuDbg("b%d\n", err);
24957+ return err;
24958+}
24959+
24960+/* ---------------------------------------------------------------------- */
24961+
24962+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
24963+ [AuWbrCopyup_TDP] = {
24964+ .copyup = au_wbr_copyup_tdp
24965+ },
24966+ [AuWbrCopyup_BUP] = {
24967+ .copyup = au_wbr_copyup_bup
24968+ },
24969+ [AuWbrCopyup_BU] = {
24970+ .copyup = au_wbr_copyup_bu
24971+ }
24972+};
24973+
24974+struct au_wbr_create_operations au_wbr_create_ops[] = {
24975+ [AuWbrCreate_TDP] = {
24976+ .create = au_wbr_create_tdp
24977+ },
24978+ [AuWbrCreate_RR] = {
24979+ .create = au_wbr_create_rr,
24980+ .init = au_wbr_create_init_rr
24981+ },
24982+ [AuWbrCreate_MFS] = {
24983+ .create = au_wbr_create_mfs,
24984+ .init = au_wbr_create_init_mfs,
24985+ .fin = au_wbr_create_fin_mfs
24986+ },
24987+ [AuWbrCreate_MFSV] = {
24988+ .create = au_wbr_create_mfs,
24989+ .init = au_wbr_create_init_mfs,
24990+ .fin = au_wbr_create_fin_mfs
24991+ },
24992+ [AuWbrCreate_MFSRR] = {
24993+ .create = au_wbr_create_mfsrr,
24994+ .init = au_wbr_create_init_mfsrr,
24995+ .fin = au_wbr_create_fin_mfs
24996+ },
24997+ [AuWbrCreate_MFSRRV] = {
24998+ .create = au_wbr_create_mfsrr,
24999+ .init = au_wbr_create_init_mfsrr,
25000+ .fin = au_wbr_create_fin_mfs
25001+ },
25002+ [AuWbrCreate_PMFS] = {
25003+ .create = au_wbr_create_pmfs,
25004+ .init = au_wbr_create_init_mfs,
25005+ .fin = au_wbr_create_fin_mfs
25006+ },
25007+ [AuWbrCreate_PMFSV] = {
25008+ .create = au_wbr_create_pmfs,
25009+ .init = au_wbr_create_init_mfs,
25010+ .fin = au_wbr_create_fin_mfs
25011+ }
25012+};
e49829fe
JR
25013--- /dev/null
25014+++ linux-2.6/fs/aufs/whout.c 2010-10-24 11:43:45.000000000 +0200
25015@@ -0,0 +1,1059 @@
1facf9fc 25016+/*
4a4d8108 25017+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25018+ *
25019+ * This program, aufs is free software; you can redistribute it and/or modify
25020+ * it under the terms of the GNU General Public License as published by
25021+ * the Free Software Foundation; either version 2 of the License, or
25022+ * (at your option) any later version.
dece6358
AM
25023+ *
25024+ * This program is distributed in the hope that it will be useful,
25025+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25026+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25027+ * GNU General Public License for more details.
25028+ *
25029+ * You should have received a copy of the GNU General Public License
25030+ * along with this program; if not, write to the Free Software
25031+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25032+ */
25033+
25034+/*
25035+ * whiteout for logical deletion and opaque directory
25036+ */
25037+
25038+#include <linux/fs.h>
25039+#include "aufs.h"
25040+
25041+#define WH_MASK S_IRUGO
25042+
25043+/*
25044+ * If a directory contains this file, then it is opaque. We start with the
25045+ * .wh. flag so that it is blocked by lookup.
25046+ */
25047+static struct qstr diropq_name = {
25048+ .name = AUFS_WH_DIROPQ,
25049+ .len = sizeof(AUFS_WH_DIROPQ) - 1
25050+};
25051+
25052+/*
25053+ * generate whiteout name, which is NOT terminated by NULL.
25054+ * @name: original d_name.name
25055+ * @len: original d_name.len
25056+ * @wh: whiteout qstr
25057+ * returns zero when succeeds, otherwise error.
25058+ * succeeded value as wh->name should be freed by kfree().
25059+ */
25060+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
25061+{
25062+ char *p;
25063+
25064+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
25065+ return -ENAMETOOLONG;
25066+
25067+ wh->len = name->len + AUFS_WH_PFX_LEN;
25068+ p = kmalloc(wh->len, GFP_NOFS);
25069+ wh->name = p;
25070+ if (p) {
25071+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25072+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
25073+ /* smp_mb(); */
25074+ return 0;
25075+ }
25076+ return -ENOMEM;
25077+}
25078+
25079+/* ---------------------------------------------------------------------- */
25080+
25081+/*
25082+ * test if the @wh_name exists under @h_parent.
25083+ * @try_sio specifies the necessary of super-io.
25084+ */
25085+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
25086+ struct au_branch *br, int try_sio)
25087+{
25088+ int err;
25089+ struct dentry *wh_dentry;
1facf9fc 25090+
1facf9fc 25091+ if (!try_sio)
25092+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
25093+ else
25094+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
25095+ err = PTR_ERR(wh_dentry);
25096+ if (IS_ERR(wh_dentry))
25097+ goto out;
25098+
25099+ err = 0;
25100+ if (!wh_dentry->d_inode)
25101+ goto out_wh; /* success */
25102+
25103+ err = 1;
25104+ if (S_ISREG(wh_dentry->d_inode->i_mode))
25105+ goto out_wh; /* success */
25106+
25107+ err = -EIO;
25108+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
25109+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
25110+
4f0767ce 25111+out_wh:
1facf9fc 25112+ dput(wh_dentry);
4f0767ce 25113+out:
1facf9fc 25114+ return err;
25115+}
25116+
25117+/*
25118+ * test if the @h_dentry sets opaque or not.
25119+ */
25120+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
25121+{
25122+ int err;
25123+ struct inode *h_dir;
25124+
25125+ h_dir = h_dentry->d_inode;
25126+ err = au_wh_test(h_dentry, &diropq_name, br,
25127+ au_test_h_perm_sio(h_dir, MAY_EXEC));
25128+ return err;
25129+}
25130+
25131+/*
25132+ * returns a negative dentry whose name is unique and temporary.
25133+ */
25134+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
25135+ struct qstr *prefix)
25136+{
1facf9fc 25137+ struct dentry *dentry;
25138+ int i;
4a4d8108
AM
25139+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN_MIN + 1],
25140+ *name, *p;
1facf9fc 25141+ static unsigned short cnt;
25142+ struct qstr qs;
25143+
4a4d8108
AM
25144+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
25145+
1facf9fc 25146+ name = defname;
25147+ qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
25148+ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
25149+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 25150+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 25151+ goto out;
25152+ dentry = ERR_PTR(-ENOMEM);
25153+ name = kmalloc(qs.len + 1, GFP_NOFS);
25154+ if (unlikely(!name))
25155+ goto out;
25156+ }
25157+
25158+ /* doubly whiteout-ed */
25159+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
25160+ p = name + AUFS_WH_PFX_LEN * 2;
25161+ memcpy(p, prefix->name, prefix->len);
25162+ p += prefix->len;
25163+ *p++ = '.';
4a4d8108 25164+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 25165+
25166+ qs.name = name;
25167+ for (i = 0; i < 3; i++) {
b752ccd1 25168+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 25169+ dentry = au_sio_lkup_one(&qs, h_parent, br);
25170+ if (IS_ERR(dentry) || !dentry->d_inode)
25171+ goto out_name;
25172+ dput(dentry);
25173+ }
4a4d8108 25174+ /* pr_warning("could not get random name\n"); */
1facf9fc 25175+ dentry = ERR_PTR(-EEXIST);
25176+ AuDbg("%.*s\n", AuLNPair(&qs));
25177+ BUG();
25178+
4f0767ce 25179+out_name:
1facf9fc 25180+ if (name != defname)
25181+ kfree(name);
4f0767ce 25182+out:
4a4d8108 25183+ AuTraceErrPtr(dentry);
1facf9fc 25184+ return dentry;
1facf9fc 25185+}
25186+
25187+/*
25188+ * rename the @h_dentry on @br to the whiteouted temporary name.
25189+ */
25190+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
25191+{
25192+ int err;
25193+ struct path h_path = {
25194+ .mnt = br->br_mnt
25195+ };
25196+ struct inode *h_dir;
25197+ struct dentry *h_parent;
25198+
25199+ h_parent = h_dentry->d_parent; /* dir inode is locked */
25200+ h_dir = h_parent->d_inode;
25201+ IMustLock(h_dir);
25202+
25203+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
25204+ err = PTR_ERR(h_path.dentry);
25205+ if (IS_ERR(h_path.dentry))
25206+ goto out;
25207+
25208+ /* under the same dir, no need to lock_rename() */
25209+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
25210+ AuTraceErr(err);
25211+ dput(h_path.dentry);
25212+
4f0767ce 25213+out:
4a4d8108 25214+ AuTraceErr(err);
1facf9fc 25215+ return err;
25216+}
25217+
25218+/* ---------------------------------------------------------------------- */
25219+/*
25220+ * functions for removing a whiteout
25221+ */
25222+
25223+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
25224+{
25225+ int force;
25226+
25227+ /*
25228+ * forces superio when the dir has a sticky bit.
25229+ * this may be a violation of unix fs semantics.
25230+ */
25231+ force = (h_dir->i_mode & S_ISVTX)
25232+ && h_path->dentry->d_inode->i_uid != current_fsuid();
25233+ return vfsub_unlink(h_dir, h_path, force);
25234+}
25235+
25236+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
25237+ struct dentry *dentry)
25238+{
25239+ int err;
25240+
25241+ err = do_unlink_wh(h_dir, h_path);
25242+ if (!err && dentry)
25243+ au_set_dbwh(dentry, -1);
25244+
25245+ return err;
25246+}
25247+
25248+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
25249+ struct au_branch *br)
25250+{
25251+ int err;
25252+ struct path h_path = {
25253+ .mnt = br->br_mnt
25254+ };
25255+
25256+ err = 0;
25257+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
25258+ if (IS_ERR(h_path.dentry))
25259+ err = PTR_ERR(h_path.dentry);
25260+ else {
25261+ if (h_path.dentry->d_inode
25262+ && S_ISREG(h_path.dentry->d_inode->i_mode))
25263+ err = do_unlink_wh(h_parent->d_inode, &h_path);
25264+ dput(h_path.dentry);
25265+ }
25266+
25267+ return err;
25268+}
25269+
25270+/* ---------------------------------------------------------------------- */
25271+/*
25272+ * initialize/clean whiteout for a branch
25273+ */
25274+
25275+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
25276+ const int isdir)
25277+{
25278+ int err;
25279+
25280+ if (!whpath->dentry->d_inode)
25281+ return;
25282+
25283+ err = mnt_want_write(whpath->mnt);
25284+ if (!err) {
25285+ if (isdir)
25286+ err = vfsub_rmdir(h_dir, whpath);
25287+ else
25288+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
25289+ mnt_drop_write(whpath->mnt);
25290+ }
25291+ if (unlikely(err))
4a4d8108
AM
25292+ pr_warning("failed removing %.*s (%d), ignored.\n",
25293+ AuDLNPair(whpath->dentry), err);
1facf9fc 25294+}
25295+
25296+static int test_linkable(struct dentry *h_root)
25297+{
25298+ struct inode *h_dir = h_root->d_inode;
25299+
25300+ if (h_dir->i_op->link)
25301+ return 0;
25302+
4a4d8108
AM
25303+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
25304+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 25305+ return -ENOSYS;
25306+}
25307+
25308+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
25309+static int au_whdir(struct inode *h_dir, struct path *path)
25310+{
25311+ int err;
25312+
25313+ err = -EEXIST;
25314+ if (!path->dentry->d_inode) {
25315+ int mode = S_IRWXU;
25316+
25317+ if (au_test_nfs(path->dentry->d_sb))
25318+ mode |= S_IXUGO;
25319+ err = mnt_want_write(path->mnt);
25320+ if (!err) {
25321+ err = vfsub_mkdir(h_dir, path, mode);
25322+ mnt_drop_write(path->mnt);
25323+ }
25324+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
25325+ err = 0;
25326+ else
4a4d8108 25327+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 25328+
25329+ return err;
25330+}
25331+
25332+struct au_wh_base {
25333+ const struct qstr *name;
25334+ struct dentry *dentry;
25335+};
25336+
25337+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
25338+ struct path *h_path)
25339+{
25340+ h_path->dentry = base[AuBrWh_BASE].dentry;
25341+ au_wh_clean(h_dir, h_path, /*isdir*/0);
25342+ h_path->dentry = base[AuBrWh_PLINK].dentry;
25343+ au_wh_clean(h_dir, h_path, /*isdir*/1);
25344+ h_path->dentry = base[AuBrWh_ORPH].dentry;
25345+ au_wh_clean(h_dir, h_path, /*isdir*/1);
25346+}
25347+
25348+/*
25349+ * returns tri-state,
25350+ * minus: error, caller should print the mesage
25351+ * zero: succuess
25352+ * plus: error, caller should NOT print the mesage
25353+ */
25354+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
25355+ int do_plink, struct au_wh_base base[],
25356+ struct path *h_path)
25357+{
25358+ int err;
25359+ struct inode *h_dir;
25360+
25361+ h_dir = h_root->d_inode;
25362+ h_path->dentry = base[AuBrWh_BASE].dentry;
25363+ au_wh_clean(h_dir, h_path, /*isdir*/0);
25364+ h_path->dentry = base[AuBrWh_PLINK].dentry;
25365+ if (do_plink) {
25366+ err = test_linkable(h_root);
25367+ if (unlikely(err)) {
25368+ err = 1;
25369+ goto out;
25370+ }
25371+
25372+ err = au_whdir(h_dir, h_path);
25373+ if (unlikely(err))
25374+ goto out;
25375+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
25376+ } else
25377+ au_wh_clean(h_dir, h_path, /*isdir*/1);
25378+ h_path->dentry = base[AuBrWh_ORPH].dentry;
25379+ err = au_whdir(h_dir, h_path);
25380+ if (unlikely(err))
25381+ goto out;
25382+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
25383+
4f0767ce 25384+out:
1facf9fc 25385+ return err;
25386+}
25387+
25388+/*
25389+ * for the moment, aufs supports the branch filesystem which does not support
25390+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
25391+ * copyup failed. finally, such filesystem will not be used as the writable
25392+ * branch.
25393+ *
25394+ * returns tri-state, see above.
25395+ */
25396+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
25397+ int do_plink, struct au_wh_base base[],
25398+ struct path *h_path)
25399+{
25400+ int err;
25401+ struct inode *h_dir;
25402+
1308ab2a 25403+ WbrWhMustWriteLock(wbr);
25404+
1facf9fc 25405+ err = test_linkable(h_root);
25406+ if (unlikely(err)) {
25407+ err = 1;
25408+ goto out;
25409+ }
25410+
25411+ /*
25412+ * todo: should this create be done in /sbin/mount.aufs helper?
25413+ */
25414+ err = -EEXIST;
25415+ h_dir = h_root->d_inode;
25416+ if (!base[AuBrWh_BASE].dentry->d_inode) {
25417+ err = mnt_want_write(h_path->mnt);
25418+ if (!err) {
25419+ h_path->dentry = base[AuBrWh_BASE].dentry;
25420+ err = vfsub_create(h_dir, h_path, WH_MASK);
25421+ mnt_drop_write(h_path->mnt);
25422+ }
25423+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
25424+ err = 0;
25425+ else
4a4d8108
AM
25426+ pr_err("unknown %.*s/%.*s exists\n",
25427+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 25428+ if (unlikely(err))
25429+ goto out;
25430+
25431+ h_path->dentry = base[AuBrWh_PLINK].dentry;
25432+ if (do_plink) {
25433+ err = au_whdir(h_dir, h_path);
25434+ if (unlikely(err))
25435+ goto out;
25436+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
25437+ } else
25438+ au_wh_clean(h_dir, h_path, /*isdir*/1);
25439+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
25440+
25441+ h_path->dentry = base[AuBrWh_ORPH].dentry;
25442+ err = au_whdir(h_dir, h_path);
25443+ if (unlikely(err))
25444+ goto out;
25445+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
25446+
4f0767ce 25447+out:
1facf9fc 25448+ return err;
25449+}
25450+
25451+/*
25452+ * initialize the whiteout base file/dir for @br.
25453+ */
25454+int au_wh_init(struct dentry *h_root, struct au_branch *br,
25455+ struct super_block *sb)
25456+{
25457+ int err, i;
25458+ const unsigned char do_plink
25459+ = !!au_opt_test(au_mntflags(sb), PLINK);
25460+ struct path path = {
25461+ .mnt = br->br_mnt
25462+ };
25463+ struct inode *h_dir;
25464+ struct au_wbr *wbr = br->br_wbr;
25465+ static const struct qstr base_name[] = {
25466+ [AuBrWh_BASE] = {
25467+ .name = AUFS_BASE_NAME,
25468+ .len = sizeof(AUFS_BASE_NAME) - 1
25469+ },
25470+ [AuBrWh_PLINK] = {
25471+ .name = AUFS_PLINKDIR_NAME,
25472+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
25473+ },
25474+ [AuBrWh_ORPH] = {
25475+ .name = AUFS_ORPHDIR_NAME,
25476+ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
25477+ }
25478+ };
25479+ struct au_wh_base base[] = {
25480+ [AuBrWh_BASE] = {
25481+ .name = base_name + AuBrWh_BASE,
25482+ .dentry = NULL
25483+ },
25484+ [AuBrWh_PLINK] = {
25485+ .name = base_name + AuBrWh_PLINK,
25486+ .dentry = NULL
25487+ },
25488+ [AuBrWh_ORPH] = {
25489+ .name = base_name + AuBrWh_ORPH,
25490+ .dentry = NULL
25491+ }
25492+ };
25493+
1308ab2a 25494+ if (wbr)
25495+ WbrWhMustWriteLock(wbr);
1facf9fc 25496+
1facf9fc 25497+ for (i = 0; i < AuBrWh_Last; i++) {
25498+ /* doubly whiteouted */
25499+ struct dentry *d;
25500+
25501+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
25502+ err = PTR_ERR(d);
25503+ if (IS_ERR(d))
25504+ goto out;
25505+
25506+ base[i].dentry = d;
25507+ AuDebugOn(wbr
25508+ && wbr->wbr_wh[i]
25509+ && wbr->wbr_wh[i] != base[i].dentry);
25510+ }
25511+
25512+ if (wbr)
25513+ for (i = 0; i < AuBrWh_Last; i++) {
25514+ dput(wbr->wbr_wh[i]);
25515+ wbr->wbr_wh[i] = NULL;
25516+ }
25517+
25518+ err = 0;
1facf9fc 25519+ switch (br->br_perm) {
25520+ case AuBrPerm_RO:
25521+ case AuBrPerm_ROWH:
25522+ case AuBrPerm_RR:
25523+ case AuBrPerm_RRWH:
4a4d8108 25524+ h_dir = h_root->d_inode;
1facf9fc 25525+ au_wh_init_ro(h_dir, base, &path);
25526+ break;
25527+
25528+ case AuBrPerm_RWNoLinkWH:
25529+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
25530+ if (err > 0)
25531+ goto out;
25532+ else if (err)
25533+ goto out_err;
25534+ break;
25535+
25536+ case AuBrPerm_RW:
25537+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
25538+ if (err > 0)
25539+ goto out;
25540+ else if (err)
25541+ goto out_err;
25542+ break;
25543+
25544+ default:
25545+ BUG();
25546+ }
25547+ goto out; /* success */
25548+
4f0767ce 25549+out_err:
4a4d8108
AM
25550+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
25551+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 25552+out:
1facf9fc 25553+ for (i = 0; i < AuBrWh_Last; i++)
25554+ dput(base[i].dentry);
25555+ return err;
25556+}
25557+
25558+/* ---------------------------------------------------------------------- */
25559+/*
25560+ * whiteouts are all hard-linked usually.
25561+ * when its link count reaches a ceiling, we create a new whiteout base
25562+ * asynchronously.
25563+ */
25564+
25565+struct reinit_br_wh {
25566+ struct super_block *sb;
25567+ struct au_branch *br;
25568+};
25569+
25570+static void reinit_br_wh(void *arg)
25571+{
25572+ int err;
25573+ aufs_bindex_t bindex;
25574+ struct path h_path;
25575+ struct reinit_br_wh *a = arg;
25576+ struct au_wbr *wbr;
25577+ struct inode *dir;
25578+ struct dentry *h_root;
25579+ struct au_hinode *hdir;
25580+
25581+ err = 0;
25582+ wbr = a->br->br_wbr;
25583+ /* big aufs lock */
25584+ si_noflush_write_lock(a->sb);
25585+ if (!au_br_writable(a->br->br_perm))
25586+ goto out;
25587+ bindex = au_br_index(a->sb, a->br->br_id);
25588+ if (unlikely(bindex < 0))
25589+ goto out;
25590+
1308ab2a 25591+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 25592+ dir = a->sb->s_root->d_inode;
1facf9fc 25593+ hdir = au_hi(dir, bindex);
25594+ h_root = au_h_dptr(a->sb->s_root, bindex);
25595+
4a4d8108 25596+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 25597+ wbr_wh_write_lock(wbr);
25598+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
25599+ h_root, a->br);
25600+ if (!err) {
25601+ err = mnt_want_write(a->br->br_mnt);
25602+ if (!err) {
25603+ h_path.dentry = wbr->wbr_whbase;
25604+ h_path.mnt = a->br->br_mnt;
25605+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
25606+ mnt_drop_write(a->br->br_mnt);
25607+ }
25608+ } else {
4a4d8108
AM
25609+ pr_warning("%.*s is moved, ignored\n",
25610+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 25611+ err = 0;
25612+ }
25613+ dput(wbr->wbr_whbase);
25614+ wbr->wbr_whbase = NULL;
25615+ if (!err)
25616+ err = au_wh_init(h_root, a->br, a->sb);
25617+ wbr_wh_write_unlock(wbr);
4a4d8108 25618+ au_hn_imtx_unlock(hdir);
1308ab2a 25619+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 25620+
4f0767ce 25621+out:
1facf9fc 25622+ if (wbr)
25623+ atomic_dec(&wbr->wbr_wh_running);
25624+ atomic_dec(&a->br->br_count);
25625+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
25626+ si_write_unlock(a->sb);
25627+ kfree(arg);
25628+ if (unlikely(err))
25629+ AuIOErr("err %d\n", err);
25630+}
25631+
25632+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
25633+{
25634+ int do_dec, wkq_err;
25635+ struct reinit_br_wh *arg;
25636+
25637+ do_dec = 1;
25638+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
25639+ goto out;
25640+
25641+ /* ignore ENOMEM */
25642+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
25643+ if (arg) {
25644+ /*
25645+ * dec(wh_running), kfree(arg) and dec(br_count)
25646+ * in reinit function
25647+ */
25648+ arg->sb = sb;
25649+ arg->br = br;
25650+ atomic_inc(&br->br_count);
25651+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
25652+ if (unlikely(wkq_err)) {
25653+ atomic_dec(&br->br_wbr->wbr_wh_running);
25654+ atomic_dec(&br->br_count);
25655+ kfree(arg);
25656+ }
25657+ do_dec = 0;
25658+ }
25659+
4f0767ce 25660+out:
1facf9fc 25661+ if (do_dec)
25662+ atomic_dec(&br->br_wbr->wbr_wh_running);
25663+}
25664+
25665+/* ---------------------------------------------------------------------- */
25666+
25667+/*
25668+ * create the whiteout @wh.
25669+ */
25670+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
25671+ struct dentry *wh)
25672+{
25673+ int err;
25674+ struct path h_path = {
25675+ .dentry = wh
25676+ };
25677+ struct au_branch *br;
25678+ struct au_wbr *wbr;
25679+ struct dentry *h_parent;
25680+ struct inode *h_dir;
25681+
25682+ h_parent = wh->d_parent; /* dir inode is locked */
25683+ h_dir = h_parent->d_inode;
25684+ IMustLock(h_dir);
25685+
25686+ br = au_sbr(sb, bindex);
25687+ h_path.mnt = br->br_mnt;
25688+ wbr = br->br_wbr;
25689+ wbr_wh_read_lock(wbr);
25690+ if (wbr->wbr_whbase) {
25691+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
25692+ if (!err || err != -EMLINK)
25693+ goto out;
25694+
25695+ /* link count full. re-initialize br_whbase. */
25696+ kick_reinit_br_wh(sb, br);
25697+ }
25698+
25699+ /* return this error in this context */
25700+ err = vfsub_create(h_dir, &h_path, WH_MASK);
25701+
4f0767ce 25702+out:
1facf9fc 25703+ wbr_wh_read_unlock(wbr);
25704+ return err;
25705+}
25706+
25707+/* ---------------------------------------------------------------------- */
25708+
25709+/*
25710+ * create or remove the diropq.
25711+ */
25712+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
25713+ unsigned int flags)
25714+{
25715+ struct dentry *opq_dentry, *h_dentry;
25716+ struct super_block *sb;
25717+ struct au_branch *br;
25718+ int err;
25719+
25720+ sb = dentry->d_sb;
25721+ br = au_sbr(sb, bindex);
25722+ h_dentry = au_h_dptr(dentry, bindex);
25723+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
25724+ if (IS_ERR(opq_dentry))
25725+ goto out;
25726+
25727+ if (au_ftest_diropq(flags, CREATE)) {
25728+ err = link_or_create_wh(sb, bindex, opq_dentry);
25729+ if (!err) {
25730+ au_set_dbdiropq(dentry, bindex);
25731+ goto out; /* success */
25732+ }
25733+ } else {
25734+ struct path tmp = {
25735+ .dentry = opq_dentry,
25736+ .mnt = br->br_mnt
25737+ };
25738+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
25739+ if (!err)
25740+ au_set_dbdiropq(dentry, -1);
25741+ }
25742+ dput(opq_dentry);
25743+ opq_dentry = ERR_PTR(err);
25744+
4f0767ce 25745+out:
1facf9fc 25746+ return opq_dentry;
25747+}
25748+
25749+struct do_diropq_args {
25750+ struct dentry **errp;
25751+ struct dentry *dentry;
25752+ aufs_bindex_t bindex;
25753+ unsigned int flags;
25754+};
25755+
25756+static void call_do_diropq(void *args)
25757+{
25758+ struct do_diropq_args *a = args;
25759+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
25760+}
25761+
25762+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
25763+ unsigned int flags)
25764+{
25765+ struct dentry *diropq, *h_dentry;
25766+
25767+ h_dentry = au_h_dptr(dentry, bindex);
25768+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
25769+ diropq = do_diropq(dentry, bindex, flags);
25770+ else {
25771+ int wkq_err;
25772+ struct do_diropq_args args = {
25773+ .errp = &diropq,
25774+ .dentry = dentry,
25775+ .bindex = bindex,
25776+ .flags = flags
25777+ };
25778+
25779+ wkq_err = au_wkq_wait(call_do_diropq, &args);
25780+ if (unlikely(wkq_err))
25781+ diropq = ERR_PTR(wkq_err);
25782+ }
25783+
25784+ return diropq;
25785+}
25786+
25787+/* ---------------------------------------------------------------------- */
25788+
25789+/*
25790+ * lookup whiteout dentry.
25791+ * @h_parent: lower parent dentry which must exist and be locked
25792+ * @base_name: name of dentry which will be whiteouted
25793+ * returns dentry for whiteout.
25794+ */
25795+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
25796+ struct au_branch *br)
25797+{
25798+ int err;
25799+ struct qstr wh_name;
25800+ struct dentry *wh_dentry;
25801+
25802+ err = au_wh_name_alloc(&wh_name, base_name);
25803+ wh_dentry = ERR_PTR(err);
25804+ if (!err) {
25805+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
25806+ kfree(wh_name.name);
25807+ }
25808+ return wh_dentry;
25809+}
25810+
25811+/*
25812+ * link/create a whiteout for @dentry on @bindex.
25813+ */
25814+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
25815+ struct dentry *h_parent)
25816+{
25817+ struct dentry *wh_dentry;
25818+ struct super_block *sb;
25819+ int err;
25820+
25821+ sb = dentry->d_sb;
25822+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
25823+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
25824+ err = link_or_create_wh(sb, bindex, wh_dentry);
25825+ if (!err)
25826+ au_set_dbwh(dentry, bindex);
25827+ else {
25828+ dput(wh_dentry);
25829+ wh_dentry = ERR_PTR(err);
25830+ }
25831+ }
25832+
25833+ return wh_dentry;
25834+}
25835+
25836+/* ---------------------------------------------------------------------- */
25837+
25838+/* Delete all whiteouts in this directory on branch bindex. */
25839+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
25840+ aufs_bindex_t bindex, struct au_branch *br)
25841+{
25842+ int err;
25843+ unsigned long ul, n;
25844+ struct qstr wh_name;
25845+ char *p;
25846+ struct hlist_head *head;
25847+ struct au_vdir_wh *tpos;
25848+ struct hlist_node *pos;
25849+ struct au_vdir_destr *str;
25850+
25851+ err = -ENOMEM;
4a4d8108 25852+ p = __getname_gfp(GFP_NOFS);
1facf9fc 25853+ wh_name.name = p;
25854+ if (unlikely(!wh_name.name))
25855+ goto out;
25856+
25857+ err = 0;
25858+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25859+ p += AUFS_WH_PFX_LEN;
25860+ n = whlist->nh_num;
25861+ head = whlist->nh_head;
25862+ for (ul = 0; !err && ul < n; ul++, head++) {
25863+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
25864+ if (tpos->wh_bindex != bindex)
25865+ continue;
25866+
25867+ str = &tpos->wh_str;
25868+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
25869+ memcpy(p, str->name, str->len);
25870+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
25871+ err = unlink_wh_name(h_dentry, &wh_name, br);
25872+ if (!err)
25873+ continue;
25874+ break;
25875+ }
25876+ AuIOErr("whiteout name too long %.*s\n",
25877+ str->len, str->name);
25878+ err = -EIO;
25879+ break;
25880+ }
25881+ }
25882+ __putname(wh_name.name);
25883+
4f0767ce 25884+out:
1facf9fc 25885+ return err;
25886+}
25887+
25888+struct del_wh_children_args {
25889+ int *errp;
25890+ struct dentry *h_dentry;
1308ab2a 25891+ struct au_nhash *whlist;
1facf9fc 25892+ aufs_bindex_t bindex;
25893+ struct au_branch *br;
25894+};
25895+
25896+static void call_del_wh_children(void *args)
25897+{
25898+ struct del_wh_children_args *a = args;
1308ab2a 25899+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 25900+}
25901+
25902+/* ---------------------------------------------------------------------- */
25903+
25904+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
25905+{
25906+ struct au_whtmp_rmdir *whtmp;
dece6358 25907+ int err;
1308ab2a 25908+ unsigned int rdhash;
dece6358
AM
25909+
25910+ SiMustAnyLock(sb);
1facf9fc 25911+
25912+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
25913+ if (unlikely(!whtmp)) {
25914+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 25915+ goto out;
dece6358 25916+ }
1facf9fc 25917+
25918+ whtmp->dir = NULL;
25919+ whtmp->wh_dentry = NULL;
1308ab2a 25920+ /* no estimation for dir size */
25921+ rdhash = au_sbi(sb)->si_rdhash;
25922+ if (!rdhash)
25923+ rdhash = AUFS_RDHASH_DEF;
25924+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
25925+ if (unlikely(err)) {
25926+ kfree(whtmp);
25927+ whtmp = ERR_PTR(err);
25928+ }
dece6358 25929+
4f0767ce 25930+out:
dece6358 25931+ return whtmp;
1facf9fc 25932+}
25933+
25934+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
25935+{
25936+ dput(whtmp->wh_dentry);
25937+ iput(whtmp->dir);
dece6358 25938+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 25939+ kfree(whtmp);
25940+}
25941+
25942+/*
25943+ * rmdir the whiteouted temporary named dir @h_dentry.
25944+ * @whlist: whiteouted children.
25945+ */
25946+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
25947+ struct dentry *wh_dentry, struct au_nhash *whlist)
25948+{
25949+ int err;
25950+ struct path h_tmp;
25951+ struct inode *wh_inode, *h_dir;
25952+ struct au_branch *br;
25953+
25954+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
25955+ IMustLock(h_dir);
25956+
25957+ br = au_sbr(dir->i_sb, bindex);
25958+ wh_inode = wh_dentry->d_inode;
25959+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
25960+
25961+ /*
25962+ * someone else might change some whiteouts while we were sleeping.
25963+ * it means this whlist may have an obsoleted entry.
25964+ */
25965+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
25966+ err = del_wh_children(wh_dentry, whlist, bindex, br);
25967+ else {
25968+ int wkq_err;
25969+ struct del_wh_children_args args = {
25970+ .errp = &err,
25971+ .h_dentry = wh_dentry,
1308ab2a 25972+ .whlist = whlist,
1facf9fc 25973+ .bindex = bindex,
25974+ .br = br
25975+ };
25976+
25977+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
25978+ if (unlikely(wkq_err))
25979+ err = wkq_err;
25980+ }
25981+ mutex_unlock(&wh_inode->i_mutex);
25982+
25983+ if (!err) {
25984+ h_tmp.dentry = wh_dentry;
25985+ h_tmp.mnt = br->br_mnt;
25986+ err = vfsub_rmdir(h_dir, &h_tmp);
25987+ /* d_drop(h_dentry); */
25988+ }
25989+
25990+ if (!err) {
25991+ if (au_ibstart(dir) == bindex) {
25992+ au_cpup_attr_timesizes(dir);
25993+ drop_nlink(dir);
25994+ }
25995+ return 0; /* success */
25996+ }
25997+
4a4d8108
AM
25998+ pr_warning("failed removing %.*s(%d), ignored\n",
25999+ AuDLNPair(wh_dentry), err);
1facf9fc 26000+ return err;
26001+}
26002+
26003+static void call_rmdir_whtmp(void *args)
26004+{
26005+ int err;
e49829fe 26006+ aufs_bindex_t bindex;
1facf9fc 26007+ struct au_whtmp_rmdir *a = args;
26008+ struct super_block *sb;
26009+ struct dentry *h_parent;
26010+ struct inode *h_dir;
1facf9fc 26011+ struct au_hinode *hdir;
26012+
26013+ /* rmdir by nfsd may cause deadlock with this i_mutex */
26014+ /* mutex_lock(&a->dir->i_mutex); */
e49829fe 26015+ err = -EROFS;
1facf9fc 26016+ sb = a->dir->i_sb;
e49829fe
JR
26017+ si_read_lock(sb, !AuLock_FLUSH);
26018+ if (!au_br_writable(a->br->br_perm))
26019+ goto out;
26020+ bindex = au_br_index(sb, a->br->br_id);
26021+ if (unlikely(bindex < 0))
1facf9fc 26022+ goto out;
26023+
26024+ err = -EIO;
1facf9fc 26025+ ii_write_lock_parent(a->dir);
26026+ h_parent = dget_parent(a->wh_dentry);
26027+ h_dir = h_parent->d_inode;
e49829fe 26028+ hdir = au_hi(a->dir, bindex);
4a4d8108 26029+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
26030+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
26031+ a->br);
1facf9fc 26032+ if (!err) {
e49829fe 26033+ err = mnt_want_write(a->br->br_mnt);
1facf9fc 26034+ if (!err) {
e49829fe 26035+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
dece6358 26036+ &a->whlist);
e49829fe 26037+ mnt_drop_write(a->br->br_mnt);
1facf9fc 26038+ }
26039+ }
4a4d8108 26040+ au_hn_imtx_unlock(hdir);
1facf9fc 26041+ dput(h_parent);
26042+ ii_write_unlock(a->dir);
26043+
4f0767ce 26044+out:
1facf9fc 26045+ /* mutex_unlock(&a->dir->i_mutex); */
e49829fe 26046+ atomic_dec(&a->br->br_count);
1facf9fc 26047+ au_nwt_done(&au_sbi(sb)->si_nowait);
26048+ si_read_unlock(sb);
26049+ au_whtmp_rmdir_free(a);
26050+ if (unlikely(err))
26051+ AuIOErr("err %d\n", err);
26052+}
26053+
26054+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
26055+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
26056+{
26057+ int wkq_err;
e49829fe 26058+ struct super_block *sb;
1facf9fc 26059+
26060+ IMustLock(dir);
26061+
26062+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 26063+ sb = dir->i_sb;
1facf9fc 26064+ args->dir = au_igrab(dir);
e49829fe
JR
26065+ args->br = au_sbr(sb, bindex);
26066+ atomic_inc(&args->br->br_count);
1facf9fc 26067+ args->wh_dentry = dget(wh_dentry);
e49829fe 26068+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb);
1facf9fc 26069+ if (unlikely(wkq_err)) {
4a4d8108
AM
26070+ pr_warning("rmdir error %.*s (%d), ignored\n",
26071+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 26072+ au_whtmp_rmdir_free(args);
26073+ }
26074+}
e49829fe
JR
26075--- /dev/null
26076+++ linux-2.6/fs/aufs/whout.h 2010-10-24 11:43:55.000000000 +0200
dece6358 26077@@ -0,0 +1,87 @@
1facf9fc 26078+/*
4a4d8108 26079+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26080+ *
26081+ * This program, aufs is free software; you can redistribute it and/or modify
26082+ * it under the terms of the GNU General Public License as published by
26083+ * the Free Software Foundation; either version 2 of the License, or
26084+ * (at your option) any later version.
dece6358
AM
26085+ *
26086+ * This program is distributed in the hope that it will be useful,
26087+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26088+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26089+ * GNU General Public License for more details.
26090+ *
26091+ * You should have received a copy of the GNU General Public License
26092+ * along with this program; if not, write to the Free Software
26093+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26094+ */
26095+
26096+/*
26097+ * whiteout for logical deletion and opaque directory
26098+ */
26099+
26100+#ifndef __AUFS_WHOUT_H__
26101+#define __AUFS_WHOUT_H__
26102+
26103+#ifdef __KERNEL__
26104+
1facf9fc 26105+#include <linux/aufs_type.h>
26106+#include "dir.h"
26107+
26108+/* whout.c */
26109+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
26110+struct au_branch;
26111+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
26112+ struct au_branch *br, int try_sio);
26113+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
26114+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
26115+ struct qstr *prefix);
26116+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
26117+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
26118+ struct dentry *dentry);
26119+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
26120+ struct super_block *sb);
26121+
26122+/* diropq flags */
26123+#define AuDiropq_CREATE 1
26124+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
26125+#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
26126+#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
26127+
26128+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
26129+ unsigned int flags);
26130+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
26131+ struct au_branch *br);
26132+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
26133+ struct dentry *h_parent);
26134+
26135+/* real rmdir for the whiteout-ed dir */
26136+struct au_whtmp_rmdir {
26137+ struct inode *dir;
e49829fe 26138+ struct au_branch *br;
1facf9fc 26139+ struct dentry *wh_dentry;
dece6358 26140+ struct au_nhash whlist;
1facf9fc 26141+};
26142+
26143+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
26144+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
26145+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
26146+ struct dentry *wh_dentry, struct au_nhash *whlist);
26147+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
26148+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
26149+
26150+/* ---------------------------------------------------------------------- */
26151+
26152+static inline struct dentry *au_diropq_create(struct dentry *dentry,
26153+ aufs_bindex_t bindex)
26154+{
26155+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
26156+}
26157+
26158+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
26159+{
26160+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
26161+}
26162+
26163+#endif /* __KERNEL__ */
26164+#endif /* __AUFS_WHOUT_H__ */
e49829fe
JR
26165--- /dev/null
26166+++ linux-2.6/fs/aufs/wkq.c 2010-10-24 11:44:06.000000000 +0200
26167@@ -0,0 +1,223 @@
1facf9fc 26168+/*
4a4d8108 26169+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26170+ *
26171+ * This program, aufs is free software; you can redistribute it and/or modify
26172+ * it under the terms of the GNU General Public License as published by
26173+ * the Free Software Foundation; either version 2 of the License, or
26174+ * (at your option) any later version.
dece6358
AM
26175+ *
26176+ * This program is distributed in the hope that it will be useful,
26177+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26178+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26179+ * GNU General Public License for more details.
26180+ *
26181+ * You should have received a copy of the GNU General Public License
26182+ * along with this program; if not, write to the Free Software
26183+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26184+ */
26185+
26186+/*
26187+ * workqueue for asynchronous/super-io operations
26188+ * todo: try new dredential scheme
26189+ */
26190+
dece6358 26191+#include <linux/module.h>
1facf9fc 26192+#include "aufs.h"
26193+
b752ccd1
AM
26194+/* internal workqueue named AUFS_WKQ_NAME and AUFS_WKQ_PRE_NAME */
26195+enum {
26196+ AuWkq_INORMAL,
26197+ AuWkq_IPRE
26198+};
26199+
26200+static struct {
26201+ char *name;
26202+ struct workqueue_struct *wkq;
26203+} au_wkq[] = {
26204+ [AuWkq_INORMAL] = {
26205+ .name = AUFS_WKQ_NAME
26206+ },
26207+ [AuWkq_IPRE] = {
26208+ .name = AUFS_WKQ_PRE_NAME
26209+ }
26210+};
1facf9fc 26211+
26212+struct au_wkinfo {
26213+ struct work_struct wk;
26214+ struct super_block *sb;
26215+
26216+ unsigned int flags; /* see wkq.h */
26217+
26218+ au_wkq_func_t func;
26219+ void *args;
26220+
1facf9fc 26221+ struct completion *comp;
26222+};
26223+
26224+/* ---------------------------------------------------------------------- */
26225+
1facf9fc 26226+static void wkq_func(struct work_struct *wk)
26227+{
26228+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
26229+
26230+ wkinfo->func(wkinfo->args);
1facf9fc 26231+ if (au_ftest_wkq(wkinfo->flags, WAIT))
26232+ complete(wkinfo->comp);
26233+ else {
26234+ kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
26235+ module_put(THIS_MODULE);
26236+ kfree(wkinfo);
26237+ }
26238+}
26239+
26240+/*
26241+ * Since struct completion is large, try allocating it dynamically.
26242+ */
26243+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
26244+#define AuWkqCompDeclare(name) struct completion *comp = NULL
26245+
26246+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
26247+{
26248+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
26249+ if (*comp) {
26250+ init_completion(*comp);
26251+ wkinfo->comp = *comp;
26252+ return 0;
26253+ }
26254+ return -ENOMEM;
26255+}
26256+
26257+static void au_wkq_comp_free(struct completion *comp)
26258+{
26259+ kfree(comp);
26260+}
26261+
26262+#else
26263+
26264+/* no braces */
26265+#define AuWkqCompDeclare(name) \
26266+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
26267+ struct completion *comp = &_ ## name
26268+
26269+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
26270+{
26271+ wkinfo->comp = *comp;
26272+ return 0;
26273+}
26274+
26275+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
26276+{
26277+ /* empty */
26278+}
26279+#endif /* 4KSTACKS */
26280+
b752ccd1 26281+static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags)
1facf9fc 26282+{
b752ccd1
AM
26283+ struct workqueue_struct *wkq;
26284+
1facf9fc 26285+ au_dbg_verify_kthread();
b752ccd1 26286+ if (flags & AuWkq_WAIT) {
4a4d8108 26287+ INIT_WORK_ON_STACK(&wkinfo->wk, wkq_func);
b752ccd1
AM
26288+ wkq = au_wkq[AuWkq_INORMAL].wkq;
26289+ if (flags & AuWkq_PRE)
26290+ wkq = au_wkq[AuWkq_IPRE].wkq;
26291+ queue_work(wkq, &wkinfo->wk);
4a4d8108
AM
26292+ } else {
26293+ INIT_WORK(&wkinfo->wk, wkq_func);
26294+ schedule_work(&wkinfo->wk);
26295+ }
1facf9fc 26296+}
26297+
b752ccd1 26298+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 26299+{
26300+ int err;
26301+ AuWkqCompDeclare(comp);
26302+ struct au_wkinfo wkinfo = {
b752ccd1 26303+ .flags = flags,
1facf9fc 26304+ .func = func,
26305+ .args = args
26306+ };
26307+
26308+ err = au_wkq_comp_alloc(&wkinfo, &comp);
26309+ if (!err) {
b752ccd1 26310+ au_wkq_run(&wkinfo, flags);
1facf9fc 26311+ /* no timeout, no interrupt */
26312+ wait_for_completion(wkinfo.comp);
26313+ au_wkq_comp_free(comp);
4a4d8108 26314+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 26315+ }
26316+
26317+ return err;
26318+
26319+}
26320+
26321+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
26322+{
26323+ int err;
26324+ struct au_wkinfo *wkinfo;
26325+
26326+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
26327+
26328+ /*
26329+ * wkq_func() must free this wkinfo.
26330+ * it highly depends upon the implementation of workqueue.
26331+ */
26332+ err = 0;
26333+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
26334+ if (wkinfo) {
26335+ wkinfo->sb = sb;
26336+ wkinfo->flags = !AuWkq_WAIT;
26337+ wkinfo->func = func;
26338+ wkinfo->args = args;
26339+ wkinfo->comp = NULL;
26340+ kobject_get(&au_sbi(sb)->si_kobj);
26341+ __module_get(THIS_MODULE);
26342+
4a4d8108 26343+ au_wkq_run(wkinfo, !AuWkq_WAIT);
1facf9fc 26344+ } else {
26345+ err = -ENOMEM;
e49829fe 26346+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 26347+ }
26348+
26349+ return err;
26350+}
26351+
26352+/* ---------------------------------------------------------------------- */
26353+
26354+void au_nwt_init(struct au_nowait_tasks *nwt)
26355+{
26356+ atomic_set(&nwt->nw_len, 0);
4a4d8108 26357+ /* smp_mb(); */ /* atomic_set */
1facf9fc 26358+ init_waitqueue_head(&nwt->nw_wq);
26359+}
26360+
26361+void au_wkq_fin(void)
26362+{
b752ccd1
AM
26363+ int i;
26364+
26365+ for (i = 0; i < ARRAY_SIZE(au_wkq); i++)
26366+ if (au_wkq[i].wkq)
26367+ destroy_workqueue(au_wkq[i].wkq);
1facf9fc 26368+}
26369+
26370+int __init au_wkq_init(void)
26371+{
b752ccd1
AM
26372+ int err, i;
26373+
26374+ err = 0;
26375+ for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
e49829fe 26376+ au_wkq[i].wkq = create_workqueue(au_wkq[i].name);
b752ccd1
AM
26377+ if (IS_ERR(au_wkq[i].wkq))
26378+ err = PTR_ERR(au_wkq[i].wkq);
26379+ else if (!au_wkq[i].wkq)
26380+ err = -ENOMEM;
26381+ if (unlikely(err))
26382+ au_wkq[i].wkq = NULL;
26383+ }
e49829fe
JR
26384+ if (!err)
26385+ au_dbg_verify_wkq();
26386+ else
b752ccd1
AM
26387+ au_wkq_fin();
26388+
26389+ return err;
1facf9fc 26390+}
e49829fe
JR
26391--- /dev/null
26392+++ linux-2.6/fs/aufs/wkq.h 2010-10-24 11:44:14.000000000 +0200
b752ccd1 26393@@ -0,0 +1,88 @@
1facf9fc 26394+/*
4a4d8108 26395+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26396+ *
26397+ * This program, aufs is free software; you can redistribute it and/or modify
26398+ * it under the terms of the GNU General Public License as published by
26399+ * the Free Software Foundation; either version 2 of the License, or
26400+ * (at your option) any later version.
dece6358
AM
26401+ *
26402+ * This program is distributed in the hope that it will be useful,
26403+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26404+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26405+ * GNU General Public License for more details.
26406+ *
26407+ * You should have received a copy of the GNU General Public License
26408+ * along with this program; if not, write to the Free Software
26409+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26410+ */
26411+
26412+/*
26413+ * workqueue for asynchronous/super-io operations
26414+ * todo: try new credentials management scheme
26415+ */
26416+
26417+#ifndef __AUFS_WKQ_H__
26418+#define __AUFS_WKQ_H__
26419+
26420+#ifdef __KERNEL__
26421+
1facf9fc 26422+#include <linux/sched.h>
dece6358 26423+#include <linux/wait.h>
1facf9fc 26424+#include <linux/aufs_type.h>
26425+
dece6358
AM
26426+struct super_block;
26427+
1facf9fc 26428+/* ---------------------------------------------------------------------- */
26429+
26430+/*
26431+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
26432+ */
26433+struct au_nowait_tasks {
26434+ atomic_t nw_len;
26435+ wait_queue_head_t nw_wq;
26436+};
26437+
26438+/* ---------------------------------------------------------------------- */
26439+
26440+typedef void (*au_wkq_func_t)(void *args);
26441+
26442+/* wkq flags */
26443+#define AuWkq_WAIT 1
b752ccd1 26444+#define AuWkq_PRE (1 << 1)
1facf9fc 26445+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
26446+#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
26447+#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
26448+
26449+/* wkq.c */
b752ccd1 26450+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
1facf9fc 26451+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
26452+void au_nwt_init(struct au_nowait_tasks *nwt);
26453+int __init au_wkq_init(void);
26454+void au_wkq_fin(void);
26455+
26456+/* ---------------------------------------------------------------------- */
26457+
b752ccd1
AM
26458+static inline int au_wkq_wait_pre(au_wkq_func_t func, void *args)
26459+{
26460+ return au_wkq_do_wait(AuWkq_WAIT | AuWkq_PRE, func, args);
26461+}
26462+
26463+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 26464+{
b752ccd1 26465+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 26466+}
26467+
26468+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
26469+{
e49829fe 26470+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 26471+ wake_up_all(&nwt->nw_wq);
26472+}
26473+
26474+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
26475+{
26476+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
26477+ return 0;
26478+}
26479+
26480+#endif /* __KERNEL__ */
26481+#endif /* __AUFS_WKQ_H__ */
e49829fe
JR
26482--- /dev/null
26483+++ linux-2.6/fs/aufs/xino.c 2010-10-24 11:44:28.000000000 +0200
b752ccd1 26484@@ -0,0 +1,1263 @@
1facf9fc 26485+/*
4a4d8108 26486+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26487+ *
26488+ * This program, aufs is free software; you can redistribute it and/or modify
26489+ * it under the terms of the GNU General Public License as published by
26490+ * the Free Software Foundation; either version 2 of the License, or
26491+ * (at your option) any later version.
dece6358
AM
26492+ *
26493+ * This program is distributed in the hope that it will be useful,
26494+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26495+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26496+ * GNU General Public License for more details.
26497+ *
26498+ * You should have received a copy of the GNU General Public License
26499+ * along with this program; if not, write to the Free Software
26500+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26501+ */
26502+
26503+/*
26504+ * external inode number translation table and bitmap
26505+ */
26506+
dece6358 26507+#include <linux/file.h>
1facf9fc 26508+#include <linux/seq_file.h>
26509+#include <linux/uaccess.h>
26510+#include "aufs.h"
26511+
b752ccd1 26512+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 26513+ loff_t *pos)
26514+{
26515+ ssize_t err;
26516+ mm_segment_t oldfs;
b752ccd1
AM
26517+ union {
26518+ void *k;
26519+ char __user *u;
26520+ } buf;
1facf9fc 26521+
b752ccd1 26522+ buf.k = kbuf;
1facf9fc 26523+ oldfs = get_fs();
26524+ set_fs(KERNEL_DS);
26525+ do {
26526+ /* todo: signal_pending? */
b752ccd1 26527+ err = func(file, buf.u, size, pos);
1facf9fc 26528+ } while (err == -EAGAIN || err == -EINTR);
26529+ set_fs(oldfs);
26530+
26531+#if 0 /* reserved for future use */
26532+ if (err > 0)
26533+ fsnotify_access(file->f_dentry);
26534+#endif
26535+
26536+ return err;
26537+}
26538+
26539+/* ---------------------------------------------------------------------- */
26540+
b752ccd1 26541+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 26542+ size_t size, loff_t *pos)
26543+{
26544+ ssize_t err;
26545+ mm_segment_t oldfs;
b752ccd1
AM
26546+ union {
26547+ void *k;
26548+ const char __user *u;
26549+ } buf;
1facf9fc 26550+
b752ccd1 26551+ buf.k = kbuf;
1facf9fc 26552+ oldfs = get_fs();
26553+ set_fs(KERNEL_DS);
1facf9fc 26554+ do {
26555+ /* todo: signal_pending? */
b752ccd1 26556+ err = func(file, buf.u, size, pos);
1facf9fc 26557+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 26558+ set_fs(oldfs);
26559+
26560+#if 0 /* reserved for future use */
26561+ if (err > 0)
26562+ fsnotify_modify(file->f_dentry);
26563+#endif
26564+
26565+ return err;
26566+}
26567+
26568+struct do_xino_fwrite_args {
26569+ ssize_t *errp;
26570+ au_writef_t func;
26571+ struct file *file;
26572+ void *buf;
26573+ size_t size;
26574+ loff_t *pos;
26575+};
26576+
26577+static void call_do_xino_fwrite(void *args)
26578+{
26579+ struct do_xino_fwrite_args *a = args;
26580+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
26581+}
26582+
26583+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
26584+ loff_t *pos)
26585+{
26586+ ssize_t err;
26587+
26588+ /* todo: signal block and no wkq? */
b752ccd1
AM
26589+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
26590+ lockdep_off();
26591+ err = do_xino_fwrite(func, file, buf, size, pos);
26592+ lockdep_on();
26593+ } else {
26594+ /*
26595+ * it breaks RLIMIT_FSIZE and normal user's limit,
26596+ * users should care about quota and real 'filesystem full.'
26597+ */
1facf9fc 26598+ int wkq_err;
26599+ struct do_xino_fwrite_args args = {
26600+ .errp = &err,
26601+ .func = func,
26602+ .file = file,
26603+ .buf = buf,
26604+ .size = size,
26605+ .pos = pos
26606+ };
26607+
26608+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
26609+ if (unlikely(wkq_err))
26610+ err = wkq_err;
b752ccd1 26611+ }
1facf9fc 26612+
26613+ return err;
26614+}
26615+
26616+/* ---------------------------------------------------------------------- */
26617+
26618+/*
26619+ * create a new xinofile at the same place/path as @base_file.
26620+ */
26621+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
26622+{
26623+ struct file *file;
4a4d8108 26624+ struct dentry *base, *parent;
1facf9fc 26625+ struct inode *dir;
26626+ struct qstr *name;
1308ab2a 26627+ struct path path;
4a4d8108 26628+ int err;
1facf9fc 26629+
26630+ base = base_file->f_dentry;
26631+ parent = base->d_parent; /* dir inode is locked */
26632+ dir = parent->d_inode;
26633+ IMustLock(dir);
26634+
26635+ file = ERR_PTR(-EINVAL);
26636+ name = &base->d_name;
4a4d8108
AM
26637+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
26638+ if (IS_ERR(path.dentry)) {
26639+ file = (void *)path.dentry;
26640+ pr_err("%.*s lookup err %ld\n",
26641+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 26642+ goto out;
26643+ }
26644+
26645+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 26646+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 26647+ if (unlikely(err)) {
26648+ file = ERR_PTR(err);
4a4d8108 26649+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 26650+ goto out_dput;
26651+ }
26652+
1308ab2a 26653+ path.mnt = base_file->f_vfsmnt;
4a4d8108
AM
26654+ file = vfsub_dentry_open(&path,
26655+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
1facf9fc 26656+ if (IS_ERR(file)) {
4a4d8108 26657+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 26658+ goto out_dput;
26659+ }
26660+
26661+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
26662+ if (unlikely(err)) {
4a4d8108 26663+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 26664+ goto out_fput;
26665+ }
26666+
26667+ if (copy_src) {
26668+ /* no one can touch copy_src xino */
26669+ err = au_copy_file(file, copy_src,
26670+ i_size_read(copy_src->f_dentry->d_inode));
26671+ if (unlikely(err)) {
4a4d8108 26672+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 26673+ goto out_fput;
26674+ }
26675+ }
26676+ goto out_dput; /* success */
26677+
4f0767ce 26678+out_fput:
1facf9fc 26679+ fput(file);
26680+ file = ERR_PTR(err);
4f0767ce 26681+out_dput:
4a4d8108 26682+ dput(path.dentry);
4f0767ce 26683+out:
1facf9fc 26684+ return file;
26685+}
26686+
26687+struct au_xino_lock_dir {
26688+ struct au_hinode *hdir;
26689+ struct dentry *parent;
26690+ struct mutex *mtx;
26691+};
26692+
26693+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
26694+ struct au_xino_lock_dir *ldir)
26695+{
26696+ aufs_bindex_t brid, bindex;
26697+
26698+ ldir->hdir = NULL;
26699+ bindex = -1;
26700+ brid = au_xino_brid(sb);
26701+ if (brid >= 0)
26702+ bindex = au_br_index(sb, brid);
26703+ if (bindex >= 0) {
26704+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 26705+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 26706+ } else {
26707+ ldir->parent = dget_parent(xino->f_dentry);
26708+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
26709+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
26710+ }
26711+}
26712+
26713+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
26714+{
26715+ if (ldir->hdir)
4a4d8108 26716+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 26717+ else {
26718+ mutex_unlock(ldir->mtx);
26719+ dput(ldir->parent);
26720+ }
26721+}
26722+
26723+/* ---------------------------------------------------------------------- */
26724+
26725+/* trucate xino files asynchronously */
26726+
26727+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
26728+{
26729+ int err;
26730+ aufs_bindex_t bi, bend;
26731+ struct au_branch *br;
26732+ struct file *new_xino, *file;
26733+ struct super_block *h_sb;
26734+ struct au_xino_lock_dir ldir;
26735+
26736+ err = -EINVAL;
26737+ bend = au_sbend(sb);
26738+ if (unlikely(bindex < 0 || bend < bindex))
26739+ goto out;
26740+ br = au_sbr(sb, bindex);
26741+ file = br->br_xino.xi_file;
26742+ if (!file)
26743+ goto out;
26744+
26745+ au_xino_lock_dir(sb, file, &ldir);
26746+ /* mnt_want_write() is unnecessary here */
26747+ new_xino = au_xino_create2(file, file);
26748+ au_xino_unlock_dir(&ldir);
26749+ err = PTR_ERR(new_xino);
26750+ if (IS_ERR(new_xino))
26751+ goto out;
26752+ err = 0;
26753+ fput(file);
26754+ br->br_xino.xi_file = new_xino;
26755+
26756+ h_sb = br->br_mnt->mnt_sb;
26757+ for (bi = 0; bi <= bend; bi++) {
26758+ if (unlikely(bi == bindex))
26759+ continue;
26760+ br = au_sbr(sb, bi);
26761+ if (br->br_mnt->mnt_sb != h_sb)
26762+ continue;
26763+
26764+ fput(br->br_xino.xi_file);
26765+ br->br_xino.xi_file = new_xino;
26766+ get_file(new_xino);
26767+ }
26768+
4f0767ce 26769+out:
1facf9fc 26770+ return err;
26771+}
26772+
26773+struct xino_do_trunc_args {
26774+ struct super_block *sb;
26775+ struct au_branch *br;
26776+};
26777+
26778+static void xino_do_trunc(void *_args)
26779+{
26780+ struct xino_do_trunc_args *args = _args;
26781+ struct super_block *sb;
26782+ struct au_branch *br;
26783+ struct inode *dir;
26784+ int err;
26785+ aufs_bindex_t bindex;
26786+
26787+ err = 0;
26788+ sb = args->sb;
26789+ dir = sb->s_root->d_inode;
26790+ br = args->br;
26791+
26792+ si_noflush_write_lock(sb);
26793+ ii_read_lock_parent(dir);
26794+ bindex = au_br_index(sb, br->br_id);
26795+ err = au_xino_trunc(sb, bindex);
dece6358
AM
26796+ if (!err
26797+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 26798+ >= br->br_xino_upper)
26799+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
26800+
1facf9fc 26801+ ii_read_unlock(dir);
26802+ if (unlikely(err))
4a4d8108 26803+ pr_warning("err b%d, (%d)\n", bindex, err);
1facf9fc 26804+ atomic_dec(&br->br_xino_running);
26805+ atomic_dec(&br->br_count);
26806+ au_nwt_done(&au_sbi(sb)->si_nowait);
26807+ si_write_unlock(sb);
26808+ kfree(args);
26809+}
26810+
26811+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
26812+{
26813+ struct xino_do_trunc_args *args;
26814+ int wkq_err;
26815+
26816+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
26817+ < br->br_xino_upper)
26818+ return;
26819+
26820+ if (atomic_inc_return(&br->br_xino_running) > 1)
26821+ goto out;
26822+
26823+ /* lock and kfree() will be called in trunc_xino() */
26824+ args = kmalloc(sizeof(*args), GFP_NOFS);
26825+ if (unlikely(!args)) {
26826+ AuErr1("no memory\n");
26827+ goto out_args;
26828+ }
26829+
e49829fe 26830+ atomic_inc(&br->br_count);
1facf9fc 26831+ args->sb = sb;
26832+ args->br = br;
26833+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
26834+ if (!wkq_err)
26835+ return; /* success */
26836+
4a4d8108 26837+ pr_err("wkq %d\n", wkq_err);
e49829fe 26838+ atomic_dec(&br->br_count);
1facf9fc 26839+
4f0767ce 26840+out_args:
1facf9fc 26841+ kfree(args);
4f0767ce 26842+out:
e49829fe 26843+ atomic_dec(&br->br_xino_running);
1facf9fc 26844+}
26845+
26846+/* ---------------------------------------------------------------------- */
26847+
26848+static int au_xino_do_write(au_writef_t write, struct file *file,
26849+ ino_t h_ino, ino_t ino)
26850+{
26851+ loff_t pos;
26852+ ssize_t sz;
26853+
26854+ pos = h_ino;
26855+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
26856+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
26857+ return -EFBIG;
26858+ }
26859+ pos *= sizeof(ino);
26860+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
26861+ if (sz == sizeof(ino))
26862+ return 0; /* success */
26863+
26864+ AuIOErr("write failed (%zd)\n", sz);
26865+ return -EIO;
26866+}
26867+
26868+/*
26869+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
26870+ * at the position of @h_ino.
26871+ * even if @ino is zero, it is written to the xinofile and means no entry.
26872+ * if the size of the xino file on a specific filesystem exceeds the watermark,
26873+ * try truncating it.
26874+ */
26875+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
26876+ ino_t ino)
26877+{
26878+ int err;
26879+ unsigned int mnt_flags;
26880+ struct au_branch *br;
26881+
26882+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
26883+ || ((loff_t)-1) > 0);
dece6358 26884+ SiMustAnyLock(sb);
1facf9fc 26885+
26886+ mnt_flags = au_mntflags(sb);
26887+ if (!au_opt_test(mnt_flags, XINO))
26888+ return 0;
26889+
26890+ br = au_sbr(sb, bindex);
26891+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
26892+ h_ino, ino);
26893+ if (!err) {
26894+ if (au_opt_test(mnt_flags, TRUNC_XINO)
26895+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
26896+ xino_try_trunc(sb, br);
26897+ return 0; /* success */
26898+ }
26899+
26900+ AuIOErr("write failed (%d)\n", err);
26901+ return -EIO;
26902+}
26903+
26904+/* ---------------------------------------------------------------------- */
26905+
26906+/* aufs inode number bitmap */
26907+
26908+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
26909+static ino_t xib_calc_ino(unsigned long pindex, int bit)
26910+{
26911+ ino_t ino;
26912+
26913+ AuDebugOn(bit < 0 || page_bits <= bit);
26914+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
26915+ return ino;
26916+}
26917+
26918+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
26919+{
26920+ AuDebugOn(ino < AUFS_FIRST_INO);
26921+ ino -= AUFS_FIRST_INO;
26922+ *pindex = ino / page_bits;
26923+ *bit = ino % page_bits;
26924+}
26925+
26926+static int xib_pindex(struct super_block *sb, unsigned long pindex)
26927+{
26928+ int err;
26929+ loff_t pos;
26930+ ssize_t sz;
26931+ struct au_sbinfo *sbinfo;
26932+ struct file *xib;
26933+ unsigned long *p;
26934+
26935+ sbinfo = au_sbi(sb);
26936+ MtxMustLock(&sbinfo->si_xib_mtx);
26937+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
26938+ || !au_opt_test(sbinfo->si_mntflags, XINO));
26939+
26940+ if (pindex == sbinfo->si_xib_last_pindex)
26941+ return 0;
26942+
26943+ xib = sbinfo->si_xib;
26944+ p = sbinfo->si_xib_buf;
26945+ pos = sbinfo->si_xib_last_pindex;
26946+ pos *= PAGE_SIZE;
26947+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
26948+ if (unlikely(sz != PAGE_SIZE))
26949+ goto out;
26950+
26951+ pos = pindex;
26952+ pos *= PAGE_SIZE;
26953+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
26954+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
26955+ else {
26956+ memset(p, 0, PAGE_SIZE);
26957+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
26958+ }
26959+ if (sz == PAGE_SIZE) {
26960+ sbinfo->si_xib_last_pindex = pindex;
26961+ return 0; /* success */
26962+ }
26963+
4f0767ce 26964+out:
b752ccd1
AM
26965+ AuIOErr1("write failed (%zd)\n", sz);
26966+ err = sz;
26967+ if (sz >= 0)
26968+ err = -EIO;
26969+ return err;
26970+}
26971+
26972+/* ---------------------------------------------------------------------- */
26973+
26974+static void au_xib_clear_bit(struct inode *inode)
26975+{
26976+ int err, bit;
26977+ unsigned long pindex;
26978+ struct super_block *sb;
26979+ struct au_sbinfo *sbinfo;
26980+
26981+ AuDebugOn(inode->i_nlink);
26982+
26983+ sb = inode->i_sb;
26984+ xib_calc_bit(inode->i_ino, &pindex, &bit);
26985+ AuDebugOn(page_bits <= bit);
26986+ sbinfo = au_sbi(sb);
26987+ mutex_lock(&sbinfo->si_xib_mtx);
26988+ err = xib_pindex(sb, pindex);
26989+ if (!err) {
26990+ clear_bit(bit, sbinfo->si_xib_buf);
26991+ sbinfo->si_xib_next_bit = bit;
26992+ }
26993+ mutex_unlock(&sbinfo->si_xib_mtx);
26994+}
26995+
26996+/* for s_op->delete_inode() */
26997+void au_xino_delete_inode(struct inode *inode, const int unlinked)
26998+{
26999+ int err;
27000+ unsigned int mnt_flags;
27001+ aufs_bindex_t bindex, bend, bi;
27002+ unsigned char try_trunc;
27003+ struct au_iinfo *iinfo;
27004+ struct super_block *sb;
27005+ struct au_hinode *hi;
27006+ struct inode *h_inode;
27007+ struct au_branch *br;
27008+ au_writef_t xwrite;
27009+
27010+ sb = inode->i_sb;
27011+ mnt_flags = au_mntflags(sb);
27012+ if (!au_opt_test(mnt_flags, XINO)
27013+ || inode->i_ino == AUFS_ROOT_INO)
27014+ return;
27015+
27016+ if (unlinked) {
27017+ au_xigen_inc(inode);
27018+ au_xib_clear_bit(inode);
27019+ }
27020+
27021+ iinfo = au_ii(inode);
27022+ if (!iinfo)
27023+ return;
1facf9fc 27024+
b752ccd1
AM
27025+ bindex = iinfo->ii_bstart;
27026+ if (bindex < 0)
27027+ return;
1facf9fc 27028+
b752ccd1
AM
27029+ xwrite = au_sbi(sb)->si_xwrite;
27030+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
27031+ hi = iinfo->ii_hinode + bindex;
27032+ bend = iinfo->ii_bend;
27033+ for (; bindex <= bend; bindex++, hi++) {
27034+ h_inode = hi->hi_inode;
27035+ if (!h_inode
27036+ || (!unlinked && h_inode->i_nlink))
27037+ continue;
1facf9fc 27038+
b752ccd1
AM
27039+ /* inode may not be revalidated */
27040+ bi = au_br_index(sb, hi->hi_id);
27041+ if (bi < 0)
27042+ continue;
1facf9fc 27043+
b752ccd1
AM
27044+ br = au_sbr(sb, bi);
27045+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
27046+ h_inode->i_ino, /*ino*/0);
27047+ if (!err && try_trunc
27048+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
27049+ xino_try_trunc(sb, br);
1facf9fc 27050+ }
1facf9fc 27051+}
27052+
27053+/* get an unused inode number from bitmap */
27054+ino_t au_xino_new_ino(struct super_block *sb)
27055+{
27056+ ino_t ino;
27057+ unsigned long *p, pindex, ul, pend;
27058+ struct au_sbinfo *sbinfo;
27059+ struct file *file;
27060+ int free_bit, err;
27061+
27062+ if (!au_opt_test(au_mntflags(sb), XINO))
27063+ return iunique(sb, AUFS_FIRST_INO);
27064+
27065+ sbinfo = au_sbi(sb);
27066+ mutex_lock(&sbinfo->si_xib_mtx);
27067+ p = sbinfo->si_xib_buf;
27068+ free_bit = sbinfo->si_xib_next_bit;
27069+ if (free_bit < page_bits && !test_bit(free_bit, p))
27070+ goto out; /* success */
27071+ free_bit = find_first_zero_bit(p, page_bits);
27072+ if (free_bit < page_bits)
27073+ goto out; /* success */
27074+
27075+ pindex = sbinfo->si_xib_last_pindex;
27076+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
27077+ err = xib_pindex(sb, ul);
27078+ if (unlikely(err))
27079+ goto out_err;
27080+ free_bit = find_first_zero_bit(p, page_bits);
27081+ if (free_bit < page_bits)
27082+ goto out; /* success */
27083+ }
27084+
27085+ file = sbinfo->si_xib;
27086+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
27087+ for (ul = pindex + 1; ul <= pend; ul++) {
27088+ err = xib_pindex(sb, ul);
27089+ if (unlikely(err))
27090+ goto out_err;
27091+ free_bit = find_first_zero_bit(p, page_bits);
27092+ if (free_bit < page_bits)
27093+ goto out; /* success */
27094+ }
27095+ BUG();
27096+
4f0767ce 27097+out:
1facf9fc 27098+ set_bit(free_bit, p);
27099+ sbinfo->si_xib_next_bit++;
27100+ pindex = sbinfo->si_xib_last_pindex;
27101+ mutex_unlock(&sbinfo->si_xib_mtx);
27102+ ino = xib_calc_ino(pindex, free_bit);
27103+ AuDbg("i%lu\n", (unsigned long)ino);
27104+ return ino;
4f0767ce 27105+out_err:
1facf9fc 27106+ mutex_unlock(&sbinfo->si_xib_mtx);
27107+ AuDbg("i0\n");
27108+ return 0;
27109+}
27110+
27111+/*
27112+ * read @ino from xinofile for the specified branch{@sb, @bindex}
27113+ * at the position of @h_ino.
27114+ * if @ino does not exist and @do_new is true, get new one.
27115+ */
27116+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
27117+ ino_t *ino)
27118+{
27119+ int err;
27120+ ssize_t sz;
27121+ loff_t pos;
27122+ struct file *file;
27123+ struct au_sbinfo *sbinfo;
27124+
27125+ *ino = 0;
27126+ if (!au_opt_test(au_mntflags(sb), XINO))
27127+ return 0; /* no xino */
27128+
27129+ err = 0;
27130+ sbinfo = au_sbi(sb);
27131+ pos = h_ino;
27132+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
27133+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
27134+ return -EFBIG;
27135+ }
27136+ pos *= sizeof(*ino);
27137+
27138+ file = au_sbr(sb, bindex)->br_xino.xi_file;
27139+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
27140+ return 0; /* no ino */
27141+
27142+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
27143+ if (sz == sizeof(*ino))
27144+ return 0; /* success */
27145+
27146+ err = sz;
27147+ if (unlikely(sz >= 0)) {
27148+ err = -EIO;
27149+ AuIOErr("xino read error (%zd)\n", sz);
27150+ }
27151+
27152+ return err;
27153+}
27154+
27155+/* ---------------------------------------------------------------------- */
27156+
27157+/* create and set a new xino file */
27158+
27159+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
27160+{
27161+ struct file *file;
27162+ struct dentry *h_parent, *d;
27163+ struct inode *h_dir;
27164+ int err;
27165+
27166+ /*
27167+ * at mount-time, and the xino file is the default path,
4a4d8108 27168+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 27169+ * when a user specified the xino, we cannot get au_hdir to be ignored.
27170+ */
27171+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
27172+ S_IRUGO | S_IWUGO);
27173+ if (IS_ERR(file)) {
27174+ if (!silent)
4a4d8108 27175+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 27176+ return file;
27177+ }
27178+
27179+ /* keep file count */
27180+ h_parent = dget_parent(file->f_dentry);
27181+ h_dir = h_parent->d_inode;
27182+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
27183+ /* mnt_want_write() is unnecessary here */
27184+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
27185+ mutex_unlock(&h_dir->i_mutex);
27186+ dput(h_parent);
27187+ if (unlikely(err)) {
27188+ if (!silent)
4a4d8108 27189+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 27190+ goto out;
27191+ }
27192+
27193+ err = -EINVAL;
27194+ d = file->f_dentry;
27195+ if (unlikely(sb == d->d_sb)) {
27196+ if (!silent)
4a4d8108 27197+ pr_err("%s must be outside\n", fname);
1facf9fc 27198+ goto out;
27199+ }
27200+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
27201+ if (!silent)
4a4d8108
AM
27202+ pr_err("xino doesn't support %s(%s)\n",
27203+ fname, au_sbtype(d->d_sb));
1facf9fc 27204+ goto out;
27205+ }
27206+ return file; /* success */
27207+
4f0767ce 27208+out:
1facf9fc 27209+ fput(file);
27210+ file = ERR_PTR(err);
27211+ return file;
27212+}
27213+
27214+/*
27215+ * find another branch who is on the same filesystem of the specified
27216+ * branch{@btgt}. search until @bend.
27217+ */
27218+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
27219+ aufs_bindex_t bend)
27220+{
27221+ aufs_bindex_t bindex;
27222+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
27223+
27224+ for (bindex = 0; bindex < btgt; bindex++)
27225+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
27226+ return bindex;
27227+ for (bindex++; bindex <= bend; bindex++)
27228+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
27229+ return bindex;
27230+ return -1;
27231+}
27232+
27233+/* ---------------------------------------------------------------------- */
27234+
27235+/*
27236+ * initialize the xinofile for the specified branch @br
27237+ * at the place/path where @base_file indicates.
27238+ * test whether another branch is on the same filesystem or not,
27239+ * if @do_test is true.
27240+ */
27241+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
27242+ struct file *base_file, int do_test)
27243+{
27244+ int err;
27245+ ino_t ino;
27246+ aufs_bindex_t bend, bindex;
27247+ struct au_branch *shared_br, *b;
27248+ struct file *file;
27249+ struct super_block *tgt_sb;
27250+
27251+ shared_br = NULL;
27252+ bend = au_sbend(sb);
27253+ if (do_test) {
27254+ tgt_sb = br->br_mnt->mnt_sb;
27255+ for (bindex = 0; bindex <= bend; bindex++) {
27256+ b = au_sbr(sb, bindex);
27257+ if (tgt_sb == b->br_mnt->mnt_sb) {
27258+ shared_br = b;
27259+ break;
27260+ }
27261+ }
27262+ }
27263+
27264+ if (!shared_br || !shared_br->br_xino.xi_file) {
27265+ struct au_xino_lock_dir ldir;
27266+
27267+ au_xino_lock_dir(sb, base_file, &ldir);
27268+ /* mnt_want_write() is unnecessary here */
27269+ file = au_xino_create2(base_file, NULL);
27270+ au_xino_unlock_dir(&ldir);
27271+ err = PTR_ERR(file);
27272+ if (IS_ERR(file))
27273+ goto out;
27274+ br->br_xino.xi_file = file;
27275+ } else {
27276+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
27277+ get_file(br->br_xino.xi_file);
27278+ }
27279+
27280+ ino = AUFS_ROOT_INO;
27281+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
27282+ h_ino, ino);
b752ccd1
AM
27283+ if (unlikely(err)) {
27284+ fput(br->br_xino.xi_file);
27285+ br->br_xino.xi_file = NULL;
27286+ }
1facf9fc 27287+
4f0767ce 27288+out:
1facf9fc 27289+ return err;
27290+}
27291+
27292+/* ---------------------------------------------------------------------- */
27293+
27294+/* trucate a xino bitmap file */
27295+
27296+/* todo: slow */
27297+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
27298+{
27299+ int err, bit;
27300+ ssize_t sz;
27301+ unsigned long pindex;
27302+ loff_t pos, pend;
27303+ struct au_sbinfo *sbinfo;
27304+ au_readf_t func;
27305+ ino_t *ino;
27306+ unsigned long *p;
27307+
27308+ err = 0;
27309+ sbinfo = au_sbi(sb);
dece6358 27310+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 27311+ p = sbinfo->si_xib_buf;
27312+ func = sbinfo->si_xread;
27313+ pend = i_size_read(file->f_dentry->d_inode);
27314+ pos = 0;
27315+ while (pos < pend) {
27316+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
27317+ err = sz;
27318+ if (unlikely(sz <= 0))
27319+ goto out;
27320+
27321+ err = 0;
27322+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
27323+ if (unlikely(*ino < AUFS_FIRST_INO))
27324+ continue;
27325+
27326+ xib_calc_bit(*ino, &pindex, &bit);
27327+ AuDebugOn(page_bits <= bit);
27328+ err = xib_pindex(sb, pindex);
27329+ if (!err)
27330+ set_bit(bit, p);
27331+ else
27332+ goto out;
27333+ }
27334+ }
27335+
4f0767ce 27336+out:
1facf9fc 27337+ return err;
27338+}
27339+
27340+static int xib_restore(struct super_block *sb)
27341+{
27342+ int err;
27343+ aufs_bindex_t bindex, bend;
27344+ void *page;
27345+
27346+ err = -ENOMEM;
27347+ page = (void *)__get_free_page(GFP_NOFS);
27348+ if (unlikely(!page))
27349+ goto out;
27350+
27351+ err = 0;
27352+ bend = au_sbend(sb);
27353+ for (bindex = 0; !err && bindex <= bend; bindex++)
27354+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
27355+ err = do_xib_restore
27356+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
27357+ else
27358+ AuDbg("b%d\n", bindex);
27359+ free_page((unsigned long)page);
27360+
4f0767ce 27361+out:
1facf9fc 27362+ return err;
27363+}
27364+
27365+int au_xib_trunc(struct super_block *sb)
27366+{
27367+ int err;
27368+ ssize_t sz;
27369+ loff_t pos;
27370+ struct au_xino_lock_dir ldir;
27371+ struct au_sbinfo *sbinfo;
27372+ unsigned long *p;
27373+ struct file *file;
27374+
dece6358
AM
27375+ SiMustWriteLock(sb);
27376+
1facf9fc 27377+ err = 0;
27378+ sbinfo = au_sbi(sb);
27379+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
27380+ goto out;
27381+
27382+ file = sbinfo->si_xib;
27383+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
27384+ goto out;
27385+
27386+ au_xino_lock_dir(sb, file, &ldir);
27387+ /* mnt_want_write() is unnecessary here */
27388+ file = au_xino_create2(sbinfo->si_xib, NULL);
27389+ au_xino_unlock_dir(&ldir);
27390+ err = PTR_ERR(file);
27391+ if (IS_ERR(file))
27392+ goto out;
27393+ fput(sbinfo->si_xib);
27394+ sbinfo->si_xib = file;
27395+
27396+ p = sbinfo->si_xib_buf;
27397+ memset(p, 0, PAGE_SIZE);
27398+ pos = 0;
27399+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
27400+ if (unlikely(sz != PAGE_SIZE)) {
27401+ err = sz;
27402+ AuIOErr("err %d\n", err);
27403+ if (sz >= 0)
27404+ err = -EIO;
27405+ goto out;
27406+ }
27407+
27408+ mutex_lock(&sbinfo->si_xib_mtx);
27409+ /* mnt_want_write() is unnecessary here */
27410+ err = xib_restore(sb);
27411+ mutex_unlock(&sbinfo->si_xib_mtx);
27412+
27413+out:
27414+ return err;
27415+}
27416+
27417+/* ---------------------------------------------------------------------- */
27418+
27419+/*
27420+ * xino mount option handlers
27421+ */
27422+static au_readf_t find_readf(struct file *h_file)
27423+{
27424+ const struct file_operations *fop = h_file->f_op;
27425+
27426+ if (fop) {
27427+ if (fop->read)
27428+ return fop->read;
27429+ if (fop->aio_read)
27430+ return do_sync_read;
27431+ }
27432+ return ERR_PTR(-ENOSYS);
27433+}
27434+
27435+static au_writef_t find_writef(struct file *h_file)
27436+{
27437+ const struct file_operations *fop = h_file->f_op;
27438+
27439+ if (fop) {
27440+ if (fop->write)
27441+ return fop->write;
27442+ if (fop->aio_write)
27443+ return do_sync_write;
27444+ }
27445+ return ERR_PTR(-ENOSYS);
27446+}
27447+
27448+/* xino bitmap */
27449+static void xino_clear_xib(struct super_block *sb)
27450+{
27451+ struct au_sbinfo *sbinfo;
27452+
dece6358
AM
27453+ SiMustWriteLock(sb);
27454+
1facf9fc 27455+ sbinfo = au_sbi(sb);
27456+ sbinfo->si_xread = NULL;
27457+ sbinfo->si_xwrite = NULL;
27458+ if (sbinfo->si_xib)
27459+ fput(sbinfo->si_xib);
27460+ sbinfo->si_xib = NULL;
27461+ free_page((unsigned long)sbinfo->si_xib_buf);
27462+ sbinfo->si_xib_buf = NULL;
27463+}
27464+
27465+static int au_xino_set_xib(struct super_block *sb, struct file *base)
27466+{
27467+ int err;
27468+ loff_t pos;
27469+ struct au_sbinfo *sbinfo;
27470+ struct file *file;
27471+
dece6358
AM
27472+ SiMustWriteLock(sb);
27473+
1facf9fc 27474+ sbinfo = au_sbi(sb);
27475+ file = au_xino_create2(base, sbinfo->si_xib);
27476+ err = PTR_ERR(file);
27477+ if (IS_ERR(file))
27478+ goto out;
27479+ if (sbinfo->si_xib)
27480+ fput(sbinfo->si_xib);
27481+ sbinfo->si_xib = file;
27482+ sbinfo->si_xread = find_readf(file);
27483+ sbinfo->si_xwrite = find_writef(file);
27484+
27485+ err = -ENOMEM;
27486+ if (!sbinfo->si_xib_buf)
27487+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
27488+ if (unlikely(!sbinfo->si_xib_buf))
27489+ goto out_unset;
27490+
27491+ sbinfo->si_xib_last_pindex = 0;
27492+ sbinfo->si_xib_next_bit = 0;
27493+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
27494+ pos = 0;
27495+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
27496+ PAGE_SIZE, &pos);
27497+ if (unlikely(err != PAGE_SIZE))
27498+ goto out_free;
27499+ }
27500+ err = 0;
27501+ goto out; /* success */
27502+
4f0767ce 27503+out_free:
1facf9fc 27504+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
27505+ sbinfo->si_xib_buf = NULL;
27506+ if (err >= 0)
27507+ err = -EIO;
4f0767ce 27508+out_unset:
b752ccd1
AM
27509+ fput(sbinfo->si_xib);
27510+ sbinfo->si_xib = NULL;
27511+ sbinfo->si_xread = NULL;
27512+ sbinfo->si_xwrite = NULL;
4f0767ce 27513+out:
b752ccd1 27514+ return err;
1facf9fc 27515+}
27516+
b752ccd1
AM
27517+/* xino for each branch */
27518+static void xino_clear_br(struct super_block *sb)
27519+{
27520+ aufs_bindex_t bindex, bend;
27521+ struct au_branch *br;
1facf9fc 27522+
b752ccd1
AM
27523+ bend = au_sbend(sb);
27524+ for (bindex = 0; bindex <= bend; bindex++) {
27525+ br = au_sbr(sb, bindex);
27526+ if (!br || !br->br_xino.xi_file)
27527+ continue;
27528+
27529+ fput(br->br_xino.xi_file);
27530+ br->br_xino.xi_file = NULL;
27531+ }
27532+}
27533+
27534+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 27535+{
27536+ int err;
b752ccd1
AM
27537+ ino_t ino;
27538+ aufs_bindex_t bindex, bend, bshared;
27539+ struct {
27540+ struct file *old, *new;
27541+ } *fpair, *p;
27542+ struct au_branch *br;
27543+ struct inode *inode;
27544+ au_writef_t writef;
1facf9fc 27545+
b752ccd1
AM
27546+ SiMustWriteLock(sb);
27547+
27548+ err = -ENOMEM;
27549+ bend = au_sbend(sb);
27550+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
27551+ if (unlikely(!fpair))
1facf9fc 27552+ goto out;
27553+
b752ccd1
AM
27554+ inode = sb->s_root->d_inode;
27555+ ino = AUFS_ROOT_INO;
27556+ writef = au_sbi(sb)->si_xwrite;
27557+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
27558+ br = au_sbr(sb, bindex);
27559+ bshared = is_sb_shared(sb, bindex, bindex - 1);
27560+ if (bshared >= 0) {
27561+ /* shared xino */
27562+ *p = fpair[bshared];
27563+ get_file(p->new);
27564+ }
27565+
27566+ if (!p->new) {
27567+ /* new xino */
27568+ p->old = br->br_xino.xi_file;
27569+ p->new = au_xino_create2(base, br->br_xino.xi_file);
27570+ err = PTR_ERR(p->new);
27571+ if (IS_ERR(p->new)) {
27572+ p->new = NULL;
27573+ goto out_pair;
27574+ }
27575+ }
27576+
27577+ err = au_xino_do_write(writef, p->new,
27578+ au_h_iptr(inode, bindex)->i_ino, ino);
27579+ if (unlikely(err))
27580+ goto out_pair;
27581+ }
27582+
27583+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
27584+ br = au_sbr(sb, bindex);
27585+ if (br->br_xino.xi_file)
27586+ fput(br->br_xino.xi_file);
27587+ get_file(p->new);
27588+ br->br_xino.xi_file = p->new;
27589+ }
1facf9fc 27590+
4f0767ce 27591+out_pair:
b752ccd1
AM
27592+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
27593+ if (p->new)
27594+ fput(p->new);
27595+ else
27596+ break;
27597+ kfree(fpair);
4f0767ce 27598+out:
1facf9fc 27599+ return err;
27600+}
b752ccd1
AM
27601+
27602+void au_xino_clr(struct super_block *sb)
27603+{
27604+ struct au_sbinfo *sbinfo;
27605+
27606+ au_xigen_clr(sb);
27607+ xino_clear_xib(sb);
27608+ xino_clear_br(sb);
27609+ sbinfo = au_sbi(sb);
27610+ /* lvalue, do not call au_mntflags() */
27611+ au_opt_clr(sbinfo->si_mntflags, XINO);
27612+}
27613+
27614+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
27615+{
27616+ int err, skip;
27617+ struct dentry *parent, *cur_parent;
27618+ struct qstr *dname, *cur_name;
27619+ struct file *cur_xino;
27620+ struct inode *dir;
27621+ struct au_sbinfo *sbinfo;
27622+
27623+ SiMustWriteLock(sb);
27624+
27625+ err = 0;
27626+ sbinfo = au_sbi(sb);
27627+ parent = dget_parent(xino->file->f_dentry);
27628+ if (remount) {
27629+ skip = 0;
27630+ dname = &xino->file->f_dentry->d_name;
27631+ cur_xino = sbinfo->si_xib;
27632+ if (cur_xino) {
27633+ cur_parent = dget_parent(cur_xino->f_dentry);
27634+ cur_name = &cur_xino->f_dentry->d_name;
27635+ skip = (cur_parent == parent
27636+ && dname->len == cur_name->len
27637+ && !memcmp(dname->name, cur_name->name,
27638+ dname->len));
27639+ dput(cur_parent);
27640+ }
27641+ if (skip)
27642+ goto out;
27643+ }
27644+
27645+ au_opt_set(sbinfo->si_mntflags, XINO);
27646+ dir = parent->d_inode;
27647+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
27648+ /* mnt_want_write() is unnecessary here */
27649+ err = au_xino_set_xib(sb, xino->file);
27650+ if (!err)
27651+ err = au_xigen_set(sb, xino->file);
27652+ if (!err)
27653+ err = au_xino_set_br(sb, xino->file);
27654+ mutex_unlock(&dir->i_mutex);
27655+ if (!err)
27656+ goto out; /* success */
27657+
27658+ /* reset all */
27659+ AuIOErr("failed creating xino(%d).\n", err);
27660+
4f0767ce 27661+out:
b752ccd1
AM
27662+ dput(parent);
27663+ return err;
27664+}
27665+
27666+/* ---------------------------------------------------------------------- */
27667+
27668+/*
27669+ * create a xinofile at the default place/path.
27670+ */
27671+struct file *au_xino_def(struct super_block *sb)
27672+{
27673+ struct file *file;
27674+ char *page, *p;
27675+ struct au_branch *br;
27676+ struct super_block *h_sb;
27677+ struct path path;
27678+ aufs_bindex_t bend, bindex, bwr;
27679+
27680+ br = NULL;
27681+ bend = au_sbend(sb);
27682+ bwr = -1;
27683+ for (bindex = 0; bindex <= bend; bindex++) {
27684+ br = au_sbr(sb, bindex);
27685+ if (au_br_writable(br->br_perm)
27686+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
27687+ bwr = bindex;
27688+ break;
27689+ }
27690+ }
27691+
27692+ if (bwr >= 0) {
27693+ file = ERR_PTR(-ENOMEM);
27694+ page = __getname_gfp(GFP_NOFS);
27695+ if (unlikely(!page))
27696+ goto out;
27697+ path.mnt = br->br_mnt;
27698+ path.dentry = au_h_dptr(sb->s_root, bwr);
27699+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
27700+ file = (void *)p;
27701+ if (!IS_ERR(p)) {
27702+ strcat(p, "/" AUFS_XINO_FNAME);
27703+ AuDbg("%s\n", p);
27704+ file = au_xino_create(sb, p, /*silent*/0);
27705+ if (!IS_ERR(file))
27706+ au_xino_brid_set(sb, br->br_id);
27707+ }
27708+ __putname(page);
27709+ } else {
27710+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
27711+ if (IS_ERR(file))
27712+ goto out;
27713+ h_sb = file->f_dentry->d_sb;
27714+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
27715+ pr_err("xino doesn't support %s(%s)\n",
27716+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
27717+ fput(file);
27718+ file = ERR_PTR(-EINVAL);
27719+ }
27720+ if (!IS_ERR(file))
27721+ au_xino_brid_set(sb, -1);
27722+ }
27723+
4f0767ce 27724+out:
b752ccd1
AM
27725+ return file;
27726+}
27727+
27728+/* ---------------------------------------------------------------------- */
27729+
27730+int au_xino_path(struct seq_file *seq, struct file *file)
27731+{
27732+ int err;
27733+
27734+ err = au_seq_path(seq, &file->f_path);
27735+ if (unlikely(err < 0))
27736+ goto out;
27737+
27738+ err = 0;
27739+#define Deleted "\\040(deleted)"
27740+ seq->count -= sizeof(Deleted) - 1;
27741+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
27742+ sizeof(Deleted) - 1));
27743+#undef Deleted
27744+
4f0767ce 27745+out:
b752ccd1
AM
27746+ return err;
27747+}
e49829fe
JR
27748--- /dev/null
27749+++ linux-2.6/include/linux/aufs_type.h 2010-10-24 15:14:43.000000000 +0200
953406b4 27750@@ -0,0 +1,198 @@
1facf9fc 27751+/*
4a4d8108 27752+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 27753+ *
27754+ * This program, aufs is free software; you can redistribute it and/or modify
27755+ * it under the terms of the GNU General Public License as published by
27756+ * the Free Software Foundation; either version 2 of the License, or
27757+ * (at your option) any later version.
dece6358
AM
27758+ *
27759+ * This program is distributed in the hope that it will be useful,
27760+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27761+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27762+ * GNU General Public License for more details.
27763+ *
27764+ * You should have received a copy of the GNU General Public License
27765+ * along with this program; if not, write to the Free Software
27766+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27767+ */
27768+
27769+#ifndef __AUFS_TYPE_H__
27770+#define __AUFS_TYPE_H__
27771+
27772+#include <linux/ioctl.h>
953406b4
AM
27773+/* for those who didn't "make headers_install" */
27774+#ifdef __KERNEL__
4a4d8108 27775+#include <linux/kernel.h>
953406b4 27776+#endif
4a4d8108 27777+#include <linux/limits.h>
1308ab2a 27778+#include <linux/types.h>
1facf9fc 27779+
e49829fe 27780+#define AUFS_VERSION "2.1-standalone.tree-36-UNRELEASED-20101024"
1facf9fc 27781+
27782+/* todo? move this to linux-2.6.19/include/magic.h */
27783+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
27784+
27785+/* ---------------------------------------------------------------------- */
27786+
27787+#ifdef CONFIG_AUFS_BRANCH_MAX_127
1308ab2a 27788+typedef __s8 aufs_bindex_t;
1facf9fc 27789+#define AUFS_BRANCH_MAX 127
27790+#else
1308ab2a 27791+typedef __s16 aufs_bindex_t;
1facf9fc 27792+#ifdef CONFIG_AUFS_BRANCH_MAX_511
27793+#define AUFS_BRANCH_MAX 511
27794+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
27795+#define AUFS_BRANCH_MAX 1023
27796+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
27797+#define AUFS_BRANCH_MAX 32767
27798+#endif
27799+#endif
27800+
27801+#ifdef __KERNEL__
27802+#ifndef AUFS_BRANCH_MAX
27803+#error unknown CONFIG_AUFS_BRANCH_MAX value
27804+#endif
27805+#endif /* __KERNEL__ */
27806+
27807+/* ---------------------------------------------------------------------- */
27808+
27809+#define AUFS_NAME "aufs"
27810+#define AUFS_FSTYPE AUFS_NAME
27811+
27812+#define AUFS_ROOT_INO 2
27813+#define AUFS_FIRST_INO 11
27814+
27815+#define AUFS_WH_PFX ".wh."
27816+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
4a4d8108
AM
27817+#define AUFS_WH_TMP_LEN 4
27818+/* a limit for rmdir/rename a dir */
27819+#define AUFS_MAX_NAMELEN (NAME_MAX \
27820+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
27821+ - 1 /* dot */\
27822+ - AUFS_WH_TMP_LEN) /* hex */
1facf9fc 27823+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
27824+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
27825+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
27826+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
27827+#define AUFS_DIRWH_DEF 3
27828+#define AUFS_RDCACHE_DEF 10 /* seconds */
27829+#define AUFS_RDBLK_DEF 512 /* bytes */
27830+#define AUFS_RDHASH_DEF 32
27831+#define AUFS_WKQ_NAME AUFS_NAME "d"
b752ccd1 27832+#define AUFS_WKQ_PRE_NAME AUFS_WKQ_NAME "_pre"
1facf9fc 27833+#define AUFS_MFS_SECOND_DEF 30 /* seconds */
27834+#define AUFS_PLINK_WARN 100 /* number of plinks */
27835+
e49829fe
JR
27836+/* pseudo-link maintenace under /proc */
27837+#define AUFS_PLINK_MAINT_NAME "plink_maint"
27838+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
27839+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
27840+
1facf9fc 27841+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
27842+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
27843+
27844+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
27845+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
27846+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
27847+
27848+/* doubly whiteouted */
27849+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
27850+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
27851+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
27852+
27853+/* branch permission */
27854+#define AUFS_BRPERM_RW "rw"
27855+#define AUFS_BRPERM_RO "ro"
27856+#define AUFS_BRPERM_RR "rr"
27857+#define AUFS_BRPERM_WH "wh"
27858+#define AUFS_BRPERM_NLWH "nolwh"
27859+#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
27860+#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
27861+#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
27862+
27863+/* ---------------------------------------------------------------------- */
27864+
27865+/* ioctl */
27866+enum {
1308ab2a 27867+ /* readdir in userspace */
27868+ AuCtl_RDU,
4a4d8108
AM
27869+ AuCtl_RDU_INO,
27870+
27871+ /* pathconf wrapper */
27872+ AuCtl_WBR_FD
1308ab2a 27873+};
27874+
27875+/* borrowed from linux/include/linux/kernel.h */
27876+#ifndef ALIGN
27877+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
27878+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
27879+#endif
27880+
27881+/* borrowed from linux/include/linux/compiler-gcc3.h */
27882+#ifndef __aligned
27883+#define __aligned(x) __attribute__((aligned(x)))
27884+#define __packed __attribute__((packed))
27885+#endif
27886+
27887+struct au_rdu_cookie {
27888+ __u64 h_pos;
27889+ __s16 bindex;
27890+ __u8 flags;
27891+ __u8 pad;
27892+ __u32 generation;
27893+} __aligned(8);
27894+
27895+struct au_rdu_ent {
27896+ __u64 ino;
27897+ __s16 bindex;
27898+ __u8 type;
27899+ __u8 nlen;
27900+ __u8 wh;
27901+ char name[0];
27902+} __aligned(8);
27903+
27904+static inline int au_rdu_len(int nlen)
27905+{
27906+ /* include the terminating NULL */
27907+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
27908+ sizeof(__u64));
27909+}
27910+
27911+union au_rdu_ent_ul {
27912+ struct au_rdu_ent __user *e;
b752ccd1 27913+ __u64 ul;
1308ab2a 27914+};
27915+
27916+enum {
27917+ AufsCtlRduV_SZ,
1308ab2a 27918+ AufsCtlRduV_End
1facf9fc 27919+};
27920+
1308ab2a 27921+struct aufs_rdu {
27922+ /* input */
27923+ union {
27924+ __u64 sz; /* AuCtl_RDU */
27925+ __u64 nent; /* AuCtl_RDU_INO */
27926+ };
27927+ union au_rdu_ent_ul ent;
27928+ __u16 verify[AufsCtlRduV_End];
27929+
27930+ /* input/output */
27931+ __u32 blk;
27932+
27933+ /* output */
27934+ union au_rdu_ent_ul tail;
27935+ /* number of entries which were added in a single call */
27936+ __u64 rent;
27937+ __u8 full;
27938+ __u8 shwh;
27939+
27940+ struct au_rdu_cookie cookie;
27941+} __aligned(8);
27942+
1facf9fc 27943+#define AuCtlType 'A'
1308ab2a 27944+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
27945+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
4a4d8108 27946+#define AUFS_CTL_WBR_FD _IO(AuCtlType, AuCtl_WBR_FD)
1facf9fc 27947+
27948+#endif /* __AUFS_TYPE_H__ */
This page took 3.78789 seconds and 4 git commands to generate.