]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs2.patch
- removed hunks applied in 3.0-rc6
[packages/kernel.git] / kernel-aufs2.patch
CommitLineData
027c5e7a 1aufs2.1 kbuild patch for linux-2.6.
7f207e10
AM
2
3diff --git a/fs/Kconfig b/fs/Kconfig
027c5e7a 4index 3db9caa..c9e1f11 100644
7f207e10
AM
5--- a/fs/Kconfig
6+++ b/fs/Kconfig
027c5e7a 7@@ -190,6 +190,7 @@ source "fs/romfs/Kconfig"
7f207e10
AM
8 source "fs/sysv/Kconfig"
9 source "fs/ufs/Kconfig"
10 source "fs/exofs/Kconfig"
11+source "fs/aufs/Kconfig"
12
13 endif # MISC_FILESYSTEMS
14
15diff --git a/fs/Makefile b/fs/Makefile
027c5e7a 16index a7f7cef..95dd4d3 100644
7f207e10
AM
17--- a/fs/Makefile
18+++ b/fs/Makefile
bf0370f2 19@@ -122,3 +122,4 @@ obj-$(CONFIG_GFS2_FS) += gfs2/
7f207e10
AM
20 obj-$(CONFIG_EXOFS_FS) += exofs/
21 obj-$(CONFIG_CEPH_FS) += ceph/
bf0370f2 22 obj-$(CONFIG_PSTORE) += pstore/
db4eec2d 23+obj-$(CONFIG_AUFS_FS) += aufs/
7f207e10 24diff --git a/include/linux/Kbuild b/include/linux/Kbuild
027c5e7a 25index b0ada6f..5cb5837 100644
7f207e10
AM
26--- a/include/linux/Kbuild
27+++ b/include/linux/Kbuild
027c5e7a 28@@ -64,6 +64,7 @@ header-y += atmppp.h
7f207e10
AM
29 header-y += atmsap.h
30 header-y += atmsvc.h
31 header-y += audit.h
32+header-y += aufs_type.h
33 header-y += auto_fs.h
34 header-y += auto_fs4.h
35 header-y += auxvec.h
027c5e7a 36aufs2.1 base patch for linux-2.6.
7f207e10
AM
37
38diff --git a/fs/namei.c b/fs/namei.c
027c5e7a 39index 0087cf9..cd39cdf 100644
7f207e10
AM
40--- a/fs/namei.c
41+++ b/fs/namei.c
027c5e7a 42@@ -1841,12 +1841,12 @@ out:
7f207e10
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 {
7f207e10
AM
49 return __lookup_hash(&nd->last, nd->path.dentry, nd);
50 }
51
52-static int __lookup_one_len(const char *name, struct qstr *this,
53+int __lookup_one_len(const char *name, struct qstr *this,
54 struct dentry *base, int len)
55 {
56 unsigned long hash;
57diff --git a/fs/splice.c b/fs/splice.c
027c5e7a 58index 50a5d97..886e942 100644
7f207e10
AM
59--- a/fs/splice.c
60+++ b/fs/splice.c
027c5e7a 61@@ -1081,8 +1081,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
7f207e10
AM
62 /*
63 * Attempt to initiate a splice from pipe to file.
64 */
65-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
66- loff_t *ppos, size_t len, unsigned int flags)
67+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
68+ loff_t *ppos, size_t len, unsigned int flags)
69 {
70 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
71 loff_t *, size_t, unsigned int);
027c5e7a 72@@ -1109,9 +1109,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
73 /*
74 * Attempt to initiate a splice from a file to a pipe.
75 */
76-static long do_splice_to(struct file *in, loff_t *ppos,
77- struct pipe_inode_info *pipe, size_t len,
78- unsigned int flags)
79+long do_splice_to(struct file *in, loff_t *ppos,
80+ struct pipe_inode_info *pipe, size_t len,
81+ unsigned int flags)
82 {
83 ssize_t (*splice_read)(struct file *, loff_t *,
84 struct pipe_inode_info *, size_t, unsigned int);
85diff --git a/include/linux/namei.h b/include/linux/namei.h
027c5e7a 86index f276d4f..4eb5fcb 100644
7f207e10
AM
87--- a/include/linux/namei.h
88+++ b/include/linux/namei.h
027c5e7a 89@@ -79,6 +79,9 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
7f207e10
AM
90 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
91 int (*open)(struct inode *, struct file *));
92
93+extern struct dentry *lookup_hash(struct nameidata *nd);
94+extern int __lookup_one_len(const char *name, struct qstr *this,
95+ struct dentry *base, int len);
96 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
97
027c5e7a 98 extern int follow_down_one(struct path *);
7f207e10
AM
99diff --git a/include/linux/splice.h b/include/linux/splice.h
100index 997c3b4..be9a153 100644
101--- a/include/linux/splice.h
102+++ b/include/linux/splice.h
103@@ -89,4 +89,10 @@ extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *);
104 extern void splice_shrink_spd(struct pipe_inode_info *,
105 struct splice_pipe_desc *);
106
107+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
108+ loff_t *ppos, size_t len, unsigned int flags);
109+extern long do_splice_to(struct file *in, loff_t *ppos,
110+ struct pipe_inode_info *pipe, size_t len,
111+ unsigned int flags);
1facf9fc 112+
7f207e10 113 #endif
027c5e7a 114aufs2.1 standalone patch for linux-2.6.
7f207e10
AM
115
116diff --git a/fs/file_table.c b/fs/file_table.c
027c5e7a 117index eb36b6b..12f2809 100644
7f207e10
AM
118--- a/fs/file_table.c
119+++ b/fs/file_table.c
027c5e7a 120@@ -393,6 +393,8 @@ void file_sb_list_del(struct file *file)
7f207e10
AM
121 }
122 }
123
124+EXPORT_SYMBOL(file_sb_list_del);
1facf9fc 125+
7f207e10
AM
126 #ifdef CONFIG_SMP
127
128 /*
129diff --git a/fs/inode.c b/fs/inode.c
027c5e7a 130index 0647d80..294b8ad 100644
7f207e10
AM
131--- a/fs/inode.c
132+++ b/fs/inode.c
027c5e7a 133@@ -82,6 +82,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
7f207e10
AM
134 * the i_state of an inode while it is in use..
135 */
136 DEFINE_SPINLOCK(inode_lock);
137+EXPORT_SYMBOL(inode_lock);
138
139 /*
140 * iprune_sem provides exclusion between the kswapd or try_to_free_pages
141diff --git a/fs/namei.c b/fs/namei.c
027c5e7a 142index cd39cdf..db4290c 100644
7f207e10
AM
143--- a/fs/namei.c
144+++ b/fs/namei.c
027c5e7a 145@@ -353,6 +353,7 @@ int deny_write_access(struct file * file)
7f207e10
AM
146
147 return 0;
148 }
149+EXPORT_SYMBOL(deny_write_access);
150
151 /**
152 * path_get - get a reference to a path
027c5e7a
AM
153@@ -1845,6 +1846,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
154 {
7f207e10
AM
155 return __lookup_hash(&nd->last, nd->path.dentry, nd);
156 }
157+EXPORT_SYMBOL(lookup_hash);
158
159 int __lookup_one_len(const char *name, struct qstr *this,
160 struct dentry *base, int len)
027c5e7a 161@@ -1867,6 +1869,7 @@ int __lookup_one_len(const char *name, struct qstr *this,
7f207e10
AM
162 this->hash = end_name_hash(hash);
163 return 0;
164 }
165+EXPORT_SYMBOL(__lookup_one_len);
166
167 /**
168 * lookup_one_len - filesystem helper to lookup single pathname component
169diff --git a/fs/namespace.c b/fs/namespace.c
027c5e7a 170index d1edf26..44ca259 100644
7f207e10
AM
171--- a/fs/namespace.c
172+++ b/fs/namespace.c
027c5e7a 173@@ -1465,6 +1465,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
7f207e10
AM
174 }
175 return 0;
176 }
177+EXPORT_SYMBOL(iterate_mounts);
178
179 static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
180 {
181diff --git a/fs/notify/group.c b/fs/notify/group.c
182index d309f38..f0e9568 100644
183--- a/fs/notify/group.c
184+++ b/fs/notify/group.c
185@@ -22,6 +22,7 @@
186 #include <linux/srcu.h>
187 #include <linux/rculist.h>
188 #include <linux/wait.h>
189+#include <linux/module.h>
190
191 #include <linux/fsnotify_backend.h>
192 #include "fsnotify.h"
193@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
194 if (atomic_dec_and_test(&group->refcnt))
195 fsnotify_destroy_group(group);
196 }
197+EXPORT_SYMBOL(fsnotify_put_group);
198
199 /*
200 * Create a new fsnotify_group and hold a reference for the group returned.
201@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
202
203 return group;
204 }
205+EXPORT_SYMBOL(fsnotify_alloc_group);
206diff --git a/fs/notify/mark.c b/fs/notify/mark.c
207index 325185e..adede09 100644
208--- a/fs/notify/mark.c
209+++ b/fs/notify/mark.c
210@@ -113,6 +113,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
211 if (atomic_dec_and_test(&mark->refcnt))
212 mark->free_mark(mark);
213 }
214+EXPORT_SYMBOL(fsnotify_put_mark);
215
216 /*
217 * Any time a mark is getting freed we end up here.
218@@ -190,6 +191,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
219 if (unlikely(atomic_dec_and_test(&group->num_marks)))
220 fsnotify_final_destroy_group(group);
221 }
222+EXPORT_SYMBOL(fsnotify_destroy_mark);
223
224 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
225 {
226@@ -277,6 +279,7 @@ err:
227
228 return ret;
229 }
230+EXPORT_SYMBOL(fsnotify_add_mark);
231
232 /*
233 * clear any marks in a group in which mark->flags & flags is true
234@@ -332,6 +335,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
235 atomic_set(&mark->refcnt, 1);
236 mark->free_mark = free_mark;
237 }
238+EXPORT_SYMBOL(fsnotify_init_mark);
239
240 static int fsnotify_mark_destroy(void *ignored)
241 {
242diff --git a/fs/open.c b/fs/open.c
027c5e7a 243index 5a2c6eb..f0fa5b2 100644
7f207e10
AM
244--- a/fs/open.c
245+++ b/fs/open.c
246@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
247 mutex_unlock(&dentry->d_inode->i_mutex);
248 return ret;
249 }
250+EXPORT_SYMBOL(do_truncate);
251
252 static long do_sys_truncate(const char __user *pathname, loff_t length)
253 {
254diff --git a/fs/splice.c b/fs/splice.c
027c5e7a 255index 886e942..9a77a3e 100644
7f207e10
AM
256--- a/fs/splice.c
257+++ b/fs/splice.c
027c5e7a 258@@ -1105,6 +1105,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
259
260 return splice_write(pipe, out, ppos, len, flags);
261 }
262+EXPORT_SYMBOL(do_splice_from);
263
264 /*
265 * Attempt to initiate a splice from a file to a pipe.
027c5e7a 266@@ -1131,6 +1132,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
7f207e10
AM
267
268 return splice_read(in, ppos, pipe, len, flags);
269 }
270+EXPORT_SYMBOL(do_splice_to);
271
272 /**
273 * splice_direct_to_actor - splices data directly between two non-pipes
274diff --git a/security/commoncap.c b/security/commoncap.c
027c5e7a 275index 64c2ed9..e58b5d8 100644
7f207e10
AM
276--- a/security/commoncap.c
277+++ b/security/commoncap.c
027c5e7a 278@@ -929,3 +929,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
7f207e10
AM
279 }
280 return ret;
281 }
282+EXPORT_SYMBOL(cap_file_mmap);
283diff --git a/security/device_cgroup.c b/security/device_cgroup.c
284index 8d9c48f..29108aa 100644
285--- a/security/device_cgroup.c
286+++ b/security/device_cgroup.c
287@@ -515,6 +515,7 @@ found:
288
289 return -EPERM;
290 }
291+EXPORT_SYMBOL(devcgroup_inode_permission);
292
293 int devcgroup_inode_mknod(int mode, dev_t dev)
294 {
295diff --git a/security/security.c b/security/security.c
027c5e7a 296index 7b7308a..140afc7 100644
7f207e10
AM
297--- a/security/security.c
298+++ b/security/security.c
027c5e7a 299@@ -359,6 +359,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
7f207e10
AM
300 return 0;
301 return security_ops->path_mkdir(dir, dentry, mode);
302 }
303+EXPORT_SYMBOL(security_path_mkdir);
304
305 int security_path_rmdir(struct path *dir, struct dentry *dentry)
306 {
027c5e7a 307@@ -366,6 +367,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
7f207e10
AM
308 return 0;
309 return security_ops->path_rmdir(dir, dentry);
310 }
311+EXPORT_SYMBOL(security_path_rmdir);
312
313 int security_path_unlink(struct path *dir, struct dentry *dentry)
314 {
027c5e7a 315@@ -373,6 +375,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
7f207e10
AM
316 return 0;
317 return security_ops->path_unlink(dir, dentry);
318 }
319+EXPORT_SYMBOL(security_path_unlink);
320
321 int security_path_symlink(struct path *dir, struct dentry *dentry,
322 const char *old_name)
027c5e7a 323@@ -381,6 +384,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
7f207e10
AM
324 return 0;
325 return security_ops->path_symlink(dir, dentry, old_name);
326 }
327+EXPORT_SYMBOL(security_path_symlink);
328
329 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
330 struct dentry *new_dentry)
027c5e7a 331@@ -389,6 +393,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
7f207e10
AM
332 return 0;
333 return security_ops->path_link(old_dentry, new_dir, new_dentry);
334 }
335+EXPORT_SYMBOL(security_path_link);
336
337 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
338 struct path *new_dir, struct dentry *new_dentry)
027c5e7a 339@@ -399,6 +404,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
7f207e10
AM
340 return security_ops->path_rename(old_dir, old_dentry, new_dir,
341 new_dentry);
342 }
343+EXPORT_SYMBOL(security_path_rename);
344
345 int security_path_truncate(struct path *path)
346 {
027c5e7a 347@@ -406,6 +412,7 @@ int security_path_truncate(struct path *path)
7f207e10
AM
348 return 0;
349 return security_ops->path_truncate(path);
350 }
351+EXPORT_SYMBOL(security_path_truncate);
352
353 int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
354 mode_t mode)
027c5e7a 355@@ -414,6 +421,7 @@ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
7f207e10
AM
356 return 0;
357 return security_ops->path_chmod(dentry, mnt, mode);
358 }
359+EXPORT_SYMBOL(security_path_chmod);
360
361 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
362 {
027c5e7a 363@@ -421,6 +429,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
7f207e10
AM
364 return 0;
365 return security_ops->path_chown(path, uid, gid);
366 }
367+EXPORT_SYMBOL(security_path_chown);
368
369 int security_path_chroot(struct path *path)
370 {
027c5e7a 371@@ -497,6 +506,7 @@ int security_inode_readlink(struct dentry *dentry)
7f207e10
AM
372 return 0;
373 return security_ops->inode_readlink(dentry);
374 }
375+EXPORT_SYMBOL(security_inode_readlink);
376
377 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
378 {
027c5e7a 379@@ -511,6 +521,7 @@ int security_inode_permission(struct inode *inode, int mask)
7f207e10
AM
380 return 0;
381 return security_ops->inode_permission(inode, mask);
382 }
383+EXPORT_SYMBOL(security_inode_permission);
384
027c5e7a 385 int security_inode_exec_permission(struct inode *inode, unsigned int flags)
7f207e10 386 {
027c5e7a 387@@ -619,6 +630,7 @@ int security_file_permission(struct file *file, int mask)
7f207e10
AM
388
389 return fsnotify_perm(file, mask);
390 }
391+EXPORT_SYMBOL(security_file_permission);
392
393 int security_file_alloc(struct file *file)
394 {
027c5e7a 395@@ -646,6 +658,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
7f207e10
AM
396 return ret;
397 return ima_file_mmap(file, prot);
398 }
399+EXPORT_SYMBOL(security_file_mmap);
400
401 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
402 unsigned long prot)
403diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
404--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
027c5e7a 405+++ linux/Documentation/ABI/testing/debugfs-aufs 2011-03-21 20:22:06.833934512 +0100
7f207e10
AM
406@@ -0,0 +1,37 @@
407+What: /debug/aufs/si_<id>/
408+Date: March 2009
409+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
410+Description:
411+ Under /debug/aufs, a directory named si_<id> is created
412+ per aufs mount, where <id> is a unique id generated
413+ internally.
1facf9fc 414+
7f207e10
AM
415+What: /debug/aufs/si_<id>/xib
416+Date: March 2009
417+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
418+Description:
419+ It shows the consumed blocks by xib (External Inode Number
420+ Bitmap), its block size and file size.
421+ When the aufs mount option 'noxino' is specified, it
422+ will be empty. About XINO files, see the aufs manual.
423+
424+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
425+Date: March 2009
426+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
427+Description:
428+ It shows the consumed blocks by xino (External Inode Number
429+ Translation Table), its link count, block size and file
430+ size.
431+ When the aufs mount option 'noxino' is specified, it
432+ will be empty. About XINO files, see the aufs manual.
433+
434+What: /debug/aufs/si_<id>/xigen
435+Date: March 2009
436+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
437+Description:
438+ It shows the consumed blocks by xigen (External Inode
439+ Generation Table), its block size and file size.
440+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
441+ be created.
442+ When the aufs mount option 'noxino' is specified, it
443+ will be empty. About XINO files, see the aufs manual.
444diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
445--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
027c5e7a 446+++ linux/Documentation/ABI/testing/sysfs-aufs 2011-03-21 20:22:06.833934512 +0100
7f207e10
AM
447@@ -0,0 +1,24 @@
448+What: /sys/fs/aufs/si_<id>/
449+Date: March 2009
450+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
451+Description:
452+ Under /sys/fs/aufs, a directory named si_<id> is created
453+ per aufs mount, where <id> is a unique id generated
454+ internally.
455+
456+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
457+Date: March 2009
458+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
459+Description:
460+ It shows the abolute path of a member directory (which
461+ is called branch) in aufs, and its permission.
462+
463+What: /sys/fs/aufs/si_<id>/xi_path
464+Date: March 2009
465+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
466+Description:
467+ It shows the abolute path of XINO (External Inode Number
468+ Bitmap, Translation Table and Generation Table) file
469+ even if it is the default path.
470+ When the aufs mount option 'noxino' is specified, it
471+ will be empty. About XINO files, see the aufs manual.
472diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
473--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 474+++ linux/fs/aufs/aufs.h 2011-03-21 20:22:06.850601942 +0100
7f207e10
AM
475@@ -0,0 +1,61 @@
476+/*
027c5e7a 477+ * Copyright (C) 2005-2011 Junjiro R. Okajima
7f207e10
AM
478+ *
479+ * This program, aufs is free software; you can redistribute it and/or modify
480+ * it under the terms of the GNU General Public License as published by
481+ * the Free Software Foundation; either version 2 of the License, or
482+ * (at your option) any later version.
483+ *
484+ * This program is distributed in the hope that it will be useful,
485+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
486+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
487+ * GNU General Public License for more details.
488+ *
489+ * You should have received a copy of the GNU General Public License
490+ * along with this program; if not, write to the Free Software
491+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
492+ */
493+
494+/*
495+ * all header files
496+ */
497+
498+#ifndef __AUFS_H__
499+#define __AUFS_H__
500+
501+#ifdef __KERNEL__
502+
503+#define AuStub(type, name, body, ...) \
504+ static inline type name(__VA_ARGS__) { body; }
505+
506+#define AuStubVoid(name, ...) \
507+ AuStub(void, name, , __VA_ARGS__)
508+#define AuStubInt0(name, ...) \
509+ AuStub(int, name, return 0, __VA_ARGS__)
510+
511+#include "debug.h"
512+
513+#include "branch.h"
514+#include "cpup.h"
515+#include "dcsub.h"
516+#include "dbgaufs.h"
517+#include "dentry.h"
518+#include "dir.h"
519+#include "dynop.h"
520+#include "file.h"
521+#include "fstype.h"
522+#include "inode.h"
523+#include "loop.h"
524+#include "module.h"
525+/* never include ./mtx.h */
526+#include "opts.h"
527+#include "rwsem.h"
528+#include "spl.h"
529+#include "super.h"
530+#include "sysaufs.h"
531+#include "vfsub.h"
532+#include "whout.h"
533+#include "wkq.h"
534+
535+#endif /* __KERNEL__ */
536+#endif /* __AUFS_H__ */
537diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
538--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
539+++ linux/fs/aufs/branch.c 2011-03-21 20:22:06.850601942 +0100
540@@ -0,0 +1,1160 @@
7f207e10 541+/*
027c5e7a 542+ * Copyright (C) 2005-2011 Junjiro R. Okajima
7f207e10
AM
543+ *
544+ * This program, aufs is free software; you can redistribute it and/or modify
545+ * it under the terms of the GNU General Public License as published by
546+ * the Free Software Foundation; either version 2 of the License, or
547+ * (at your option) any later version.
548+ *
549+ * This program is distributed in the hope that it will be useful,
550+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
551+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
552+ * GNU General Public License for more details.
553+ *
554+ * You should have received a copy of the GNU General Public License
555+ * along with this program; if not, write to the Free Software
556+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
557+ */
558+
559+/*
560+ * branch management
561+ */
562+
027c5e7a 563+#include <linux/compat.h>
7f207e10
AM
564+#include <linux/file.h>
565+#include <linux/statfs.h>
566+#include "aufs.h"
567+
568+/*
569+ * free a single branch
1facf9fc 570+ */
571+static void au_br_do_free(struct au_branch *br)
572+{
573+ int i;
574+ struct au_wbr *wbr;
4a4d8108 575+ struct au_dykey **key;
1facf9fc 576+
027c5e7a
AM
577+ au_hnotify_fin_br(br);
578+
1facf9fc 579+ if (br->br_xino.xi_file)
580+ fput(br->br_xino.xi_file);
581+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
582+
583+ AuDebugOn(atomic_read(&br->br_count));
584+
585+ wbr = br->br_wbr;
586+ if (wbr) {
587+ for (i = 0; i < AuBrWh_Last; i++)
588+ dput(wbr->wbr_wh[i]);
589+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 590+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 591+ }
592+
4a4d8108
AM
593+ key = br->br_dykey;
594+ for (i = 0; i < AuBrDynOp; i++, key++)
595+ if (*key)
596+ au_dy_put(*key);
597+ else
598+ break;
599+
1facf9fc 600+ mntput(br->br_mnt);
1facf9fc 601+ kfree(wbr);
602+ kfree(br);
603+}
604+
605+/*
606+ * frees all branches
607+ */
608+void au_br_free(struct au_sbinfo *sbinfo)
609+{
610+ aufs_bindex_t bmax;
611+ struct au_branch **br;
612+
dece6358
AM
613+ AuRwMustWriteLock(&sbinfo->si_rwsem);
614+
1facf9fc 615+ bmax = sbinfo->si_bend + 1;
616+ br = sbinfo->si_branch;
617+ while (bmax--)
618+ au_br_do_free(*br++);
619+}
620+
621+/*
622+ * find the index of a branch which is specified by @br_id.
623+ */
624+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
625+{
626+ aufs_bindex_t bindex, bend;
627+
628+ bend = au_sbend(sb);
629+ for (bindex = 0; bindex <= bend; bindex++)
630+ if (au_sbr_id(sb, bindex) == br_id)
631+ return bindex;
632+ return -1;
633+}
634+
635+/* ---------------------------------------------------------------------- */
636+
637+/*
638+ * add a branch
639+ */
640+
b752ccd1
AM
641+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
642+ struct dentry *h_root)
1facf9fc 643+{
b752ccd1
AM
644+ if (unlikely(h_adding == h_root
645+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 646+ return 1;
b752ccd1
AM
647+ if (h_adding->d_sb != h_root->d_sb)
648+ return 0;
649+ return au_test_subdir(h_adding, h_root)
650+ || au_test_subdir(h_root, h_adding);
1facf9fc 651+}
652+
653+/*
654+ * returns a newly allocated branch. @new_nbranch is a number of branches
655+ * after adding a branch.
656+ */
657+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
658+ int perm)
659+{
660+ struct au_branch *add_branch;
661+ struct dentry *root;
4a4d8108 662+ int err;
1facf9fc 663+
4a4d8108 664+ err = -ENOMEM;
1facf9fc 665+ root = sb->s_root;
666+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
667+ if (unlikely(!add_branch))
668+ goto out;
669+
027c5e7a
AM
670+ err = au_hnotify_init_br(add_branch, perm);
671+ if (unlikely(err))
672+ goto out_br;
673+
1facf9fc 674+ add_branch->br_wbr = NULL;
675+ if (au_br_writable(perm)) {
676+ /* may be freed separately at changing the branch permission */
677+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
678+ GFP_NOFS);
679+ if (unlikely(!add_branch->br_wbr))
027c5e7a 680+ goto out_hnotify;
1facf9fc 681+ }
682+
4a4d8108
AM
683+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
684+ if (!err)
685+ err = au_di_realloc(au_di(root), new_nbranch);
686+ if (!err)
687+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
688+ if (!err)
689+ return add_branch; /* success */
1facf9fc 690+
1facf9fc 691+ kfree(add_branch->br_wbr);
4a4d8108 692+
027c5e7a
AM
693+out_hnotify:
694+ au_hnotify_fin_br(add_branch);
4f0767ce 695+out_br:
1facf9fc 696+ kfree(add_branch);
4f0767ce 697+out:
4a4d8108 698+ return ERR_PTR(err);
1facf9fc 699+}
700+
701+/*
702+ * test if the branch permission is legal or not.
703+ */
704+static int test_br(struct inode *inode, int brperm, char *path)
705+{
706+ int err;
707+
4a4d8108
AM
708+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
709+ if (!err)
710+ goto out;
1facf9fc 711+
4a4d8108
AM
712+ err = -EINVAL;
713+ pr_err("write permission for readonly mount or inode, %s\n", path);
714+
4f0767ce 715+out:
1facf9fc 716+ return err;
717+}
718+
719+/*
720+ * returns:
721+ * 0: success, the caller will add it
722+ * plus: success, it is already unified, the caller should ignore it
723+ * minus: error
724+ */
725+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
726+{
727+ int err;
728+ aufs_bindex_t bend, bindex;
729+ struct dentry *root;
730+ struct inode *inode, *h_inode;
731+
732+ root = sb->s_root;
733+ bend = au_sbend(sb);
734+ if (unlikely(bend >= 0
735+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
736+ err = 1;
737+ if (!remount) {
738+ err = -EINVAL;
4a4d8108 739+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 740+ }
741+ goto out;
742+ }
743+
744+ err = -ENOSPC; /* -E2BIG; */
745+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
746+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 747+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 748+ goto out;
749+ }
750+
751+ err = -EDOM;
752+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 753+ pr_err("bad index %d\n", add->bindex);
1facf9fc 754+ goto out;
755+ }
756+
757+ inode = add->path.dentry->d_inode;
758+ err = -ENOENT;
759+ if (unlikely(!inode->i_nlink)) {
4a4d8108 760+ pr_err("no existence %s\n", add->pathname);
1facf9fc 761+ goto out;
762+ }
763+
764+ err = -EINVAL;
765+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 766+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 767+ goto out;
768+ }
769+
770+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
771+ pr_err("unsupported filesystem, %s (%s)\n",
772+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 773+ goto out;
774+ }
775+
776+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
777+ if (unlikely(err))
778+ goto out;
779+
780+ if (bend < 0)
781+ return 0; /* success */
782+
783+ err = -EINVAL;
784+ for (bindex = 0; bindex <= bend; bindex++)
785+ if (unlikely(test_overlap(sb, add->path.dentry,
786+ au_h_dptr(root, bindex)))) {
4a4d8108 787+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 788+ goto out;
789+ }
790+
791+ err = 0;
792+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
793+ h_inode = au_h_dptr(root, 0)->d_inode;
794+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
795+ || h_inode->i_uid != inode->i_uid
796+ || h_inode->i_gid != inode->i_gid)
4a4d8108
AM
797+ pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
798+ add->pathname,
799+ inode->i_uid, inode->i_gid,
800+ (inode->i_mode & S_IALLUGO),
801+ h_inode->i_uid, h_inode->i_gid,
802+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 803+ }
804+
4f0767ce 805+out:
1facf9fc 806+ return err;
807+}
808+
809+/*
810+ * initialize or clean the whiteouts for an adding branch
811+ */
812+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
813+ int new_perm, struct dentry *h_root)
814+{
815+ int err, old_perm;
816+ aufs_bindex_t bindex;
817+ struct mutex *h_mtx;
818+ struct au_wbr *wbr;
819+ struct au_hinode *hdir;
820+
821+ wbr = br->br_wbr;
822+ old_perm = br->br_perm;
823+ br->br_perm = new_perm;
824+ hdir = NULL;
825+ h_mtx = NULL;
826+ bindex = au_br_index(sb, br->br_id);
827+ if (0 <= bindex) {
828+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 829+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 830+ } else {
831+ h_mtx = &h_root->d_inode->i_mutex;
832+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
833+ }
834+ if (!wbr)
835+ err = au_wh_init(h_root, br, sb);
836+ else {
837+ wbr_wh_write_lock(wbr);
838+ err = au_wh_init(h_root, br, sb);
839+ wbr_wh_write_unlock(wbr);
840+ }
841+ if (hdir)
4a4d8108 842+ au_hn_imtx_unlock(hdir);
1facf9fc 843+ else
844+ mutex_unlock(h_mtx);
845+ br->br_perm = old_perm;
846+
847+ if (!err && wbr && !au_br_writable(new_perm)) {
848+ kfree(wbr);
849+ br->br_wbr = NULL;
850+ }
851+
852+ return err;
853+}
854+
855+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
856+ int perm, struct path *path)
857+{
858+ int err;
4a4d8108 859+ struct kstatfs kst;
1facf9fc 860+ struct au_wbr *wbr;
4a4d8108 861+ struct dentry *h_dentry;
1facf9fc 862+
863+ wbr = br->br_wbr;
dece6358 864+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 865+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
866+ atomic_set(&wbr->wbr_wh_running, 0);
867+ wbr->wbr_bytes = 0;
868+
4a4d8108
AM
869+ /*
870+ * a limit for rmdir/rename a dir
871+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
872+ */
7f207e10 873+ err = vfs_statfs(path, &kst);
4a4d8108
AM
874+ if (unlikely(err))
875+ goto out;
876+ err = -EINVAL;
7f207e10 877+ h_dentry = path->dentry;
4a4d8108
AM
878+ if (kst.f_namelen >= NAME_MAX)
879+ err = au_br_init_wh(sb, br, perm, h_dentry);
880+ else
881+ pr_err("%.*s(%s), unsupported namelen %ld\n",
882+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
883+ kst.f_namelen);
1facf9fc 884+
4f0767ce 885+out:
1facf9fc 886+ return err;
887+}
888+
889+/* intialize a new branch */
890+static int au_br_init(struct au_branch *br, struct super_block *sb,
891+ struct au_opt_add *add)
892+{
893+ int err;
894+
895+ err = 0;
896+ memset(&br->br_xino, 0, sizeof(br->br_xino));
897+ mutex_init(&br->br_xino.xi_nondir_mtx);
898+ br->br_perm = add->perm;
899+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
900+ spin_lock_init(&br->br_dykey_lock);
901+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 902+ atomic_set(&br->br_count, 0);
903+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
904+ atomic_set(&br->br_xino_running, 0);
905+ br->br_id = au_new_br_id(sb);
7f207e10 906+ AuDebugOn(br->br_id < 0);
1facf9fc 907+
908+ if (au_br_writable(add->perm)) {
909+ err = au_wbr_init(br, sb, add->perm, &add->path);
910+ if (unlikely(err))
b752ccd1 911+ goto out_err;
1facf9fc 912+ }
913+
914+ if (au_opt_test(au_mntflags(sb), XINO)) {
915+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
916+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
917+ if (unlikely(err)) {
918+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 919+ goto out_err;
1facf9fc 920+ }
921+ }
922+
923+ sysaufs_br_init(br);
924+ mntget(add->path.mnt);
b752ccd1 925+ goto out; /* success */
1facf9fc 926+
4f0767ce 927+out_err:
b752ccd1 928+ br->br_mnt = NULL;
4f0767ce 929+out:
1facf9fc 930+ return err;
931+}
932+
933+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
934+ struct au_branch *br, aufs_bindex_t bend,
935+ aufs_bindex_t amount)
936+{
937+ struct au_branch **brp;
938+
dece6358
AM
939+ AuRwMustWriteLock(&sbinfo->si_rwsem);
940+
1facf9fc 941+ brp = sbinfo->si_branch + bindex;
942+ memmove(brp + 1, brp, sizeof(*brp) * amount);
943+ *brp = br;
944+ sbinfo->si_bend++;
945+ if (unlikely(bend < 0))
946+ sbinfo->si_bend = 0;
947+}
948+
949+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
950+ aufs_bindex_t bend, aufs_bindex_t amount)
951+{
952+ struct au_hdentry *hdp;
953+
1308ab2a 954+ AuRwMustWriteLock(&dinfo->di_rwsem);
955+
1facf9fc 956+ hdp = dinfo->di_hdentry + bindex;
957+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
958+ au_h_dentry_init(hdp);
959+ dinfo->di_bend++;
960+ if (unlikely(bend < 0))
961+ dinfo->di_bstart = 0;
962+}
963+
964+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
965+ aufs_bindex_t bend, aufs_bindex_t amount)
966+{
967+ struct au_hinode *hip;
968+
1308ab2a 969+ AuRwMustWriteLock(&iinfo->ii_rwsem);
970+
1facf9fc 971+ hip = iinfo->ii_hinode + bindex;
972+ memmove(hip + 1, hip, sizeof(*hip) * amount);
973+ hip->hi_inode = NULL;
4a4d8108 974+ au_hn_init(hip);
1facf9fc 975+ iinfo->ii_bend++;
976+ if (unlikely(bend < 0))
977+ iinfo->ii_bstart = 0;
978+}
979+
980+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
981+ struct au_branch *br, aufs_bindex_t bindex)
982+{
983+ struct dentry *root;
984+ struct inode *root_inode;
985+ aufs_bindex_t bend, amount;
986+
987+ root = sb->s_root;
988+ root_inode = root->d_inode;
1facf9fc 989+ bend = au_sbend(sb);
990+ amount = bend + 1 - bindex;
991+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
992+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
993+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
994+ au_set_h_dptr(root, bindex, dget(h_dentry));
995+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
996+ /*flags*/0);
997+}
998+
999+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
1000+{
1001+ int err;
1facf9fc 1002+ aufs_bindex_t bend, add_bindex;
1003+ struct dentry *root, *h_dentry;
1004+ struct inode *root_inode;
1005+ struct au_branch *add_branch;
1006+
1007+ root = sb->s_root;
1008+ root_inode = root->d_inode;
1009+ IMustLock(root_inode);
1010+ err = test_add(sb, add, remount);
1011+ if (unlikely(err < 0))
1012+ goto out;
1013+ if (err) {
1014+ err = 0;
1015+ goto out; /* success */
1016+ }
1017+
1018+ bend = au_sbend(sb);
1019+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
1020+ err = PTR_ERR(add_branch);
1021+ if (IS_ERR(add_branch))
1022+ goto out;
1023+
1024+ err = au_br_init(add_branch, sb, add);
1025+ if (unlikely(err)) {
1026+ au_br_do_free(add_branch);
1027+ goto out;
1028+ }
1029+
1030+ add_bindex = add->bindex;
1031+ h_dentry = add->path.dentry;
1032+ if (!remount)
1033+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1034+ else {
1035+ sysaufs_brs_del(sb, add_bindex);
1036+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1037+ sysaufs_brs_add(sb, add_bindex);
1038+ }
1039+
1308ab2a 1040+ if (!add_bindex) {
1facf9fc 1041+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 1042+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
1043+ } else
1facf9fc 1044+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 1045+
1046+ /*
4a4d8108 1047+ * this test/set prevents aufs from handling unnecesary notify events
027c5e7a 1048+ * of xino files, in case of re-adding a writable branch which was
1facf9fc 1049+ * once detached from aufs.
1050+ */
1051+ if (au_xino_brid(sb) < 0
1052+ && au_br_writable(add_branch->br_perm)
1053+ && !au_test_fs_bad_xino(h_dentry->d_sb)
1054+ && add_branch->br_xino.xi_file
1055+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
1056+ au_xino_brid_set(sb, add_branch->br_id);
1057+
4f0767ce 1058+out:
1facf9fc 1059+ return err;
1060+}
1061+
1062+/* ---------------------------------------------------------------------- */
1063+
1064+/*
1065+ * delete a branch
1066+ */
1067+
1068+/* to show the line number, do not make it inlined function */
4a4d8108 1069+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 1070+ if (do_info) \
4a4d8108 1071+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 1072+} while (0)
1073+
027c5e7a
AM
1074+static int au_test_ibusy(struct inode *inode, aufs_bindex_t bstart,
1075+ aufs_bindex_t bend)
1076+{
1077+ return (inode && !S_ISDIR(inode->i_mode)) || bstart == bend;
1078+}
1079+
1080+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t bstart,
1081+ aufs_bindex_t bend)
1082+{
1083+ return au_test_ibusy(dentry->d_inode, bstart, bend);
1084+}
1085+
1facf9fc 1086+/*
1087+ * test if the branch is deletable or not.
1088+ */
1089+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 1090+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1091+{
1092+ int err, i, j, ndentry;
1093+ aufs_bindex_t bstart, bend;
1facf9fc 1094+ struct au_dcsub_pages dpages;
1095+ struct au_dpage *dpage;
1096+ struct dentry *d;
1facf9fc 1097+
1098+ err = au_dpages_init(&dpages, GFP_NOFS);
1099+ if (unlikely(err))
1100+ goto out;
1101+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
1102+ if (unlikely(err))
1103+ goto out_dpages;
1104+
1facf9fc 1105+ for (i = 0; !err && i < dpages.ndpage; i++) {
1106+ dpage = dpages.dpages + i;
1107+ ndentry = dpage->ndentry;
1108+ for (j = 0; !err && j < ndentry; j++) {
1109+ d = dpage->dentries[j];
027c5e7a
AM
1110+ AuDebugOn(!d->d_count);
1111+ if (!au_digen_test(d, sigen)) {
1facf9fc 1112+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
1113+ if (unlikely(au_dbrange_test(d))) {
1114+ di_read_unlock(d, AuLock_IR);
1115+ continue;
1116+ }
1117+ } else {
1facf9fc 1118+ di_write_lock_child(d);
027c5e7a
AM
1119+ if (unlikely(au_dbrange_test(d))) {
1120+ di_write_unlock(d);
1121+ continue;
1122+ }
1facf9fc 1123+ err = au_reval_dpath(d, sigen);
1124+ if (!err)
1125+ di_downgrade_lock(d, AuLock_IR);
1126+ else {
1127+ di_write_unlock(d);
1128+ break;
1129+ }
1130+ }
1131+
027c5e7a 1132+ /* AuDbgDentry(d); */
1facf9fc 1133+ bstart = au_dbstart(d);
1134+ bend = au_dbend(d);
1135+ if (bstart <= bindex
1136+ && bindex <= bend
1137+ && au_h_dptr(d, bindex)
027c5e7a 1138+ && au_test_dbusy(d, bstart, bend)) {
1facf9fc 1139+ err = -EBUSY;
1140+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
027c5e7a 1141+ AuDbgDentry(d);
1facf9fc 1142+ }
1143+ di_read_unlock(d, AuLock_IR);
1144+ }
1145+ }
1146+
4f0767ce 1147+out_dpages:
1facf9fc 1148+ au_dpages_free(&dpages);
4f0767ce 1149+out:
1facf9fc 1150+ return err;
1151+}
1152+
1153+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 1154+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1155+{
1156+ int err;
7f207e10
AM
1157+ unsigned long long max, ull;
1158+ struct inode *i, **array;
1facf9fc 1159+ aufs_bindex_t bstart, bend;
1facf9fc 1160+
7f207e10
AM
1161+ array = au_iarray_alloc(sb, &max);
1162+ err = PTR_ERR(array);
1163+ if (IS_ERR(array))
1164+ goto out;
1165+
1facf9fc 1166+ err = 0;
7f207e10
AM
1167+ AuDbg("b%d\n", bindex);
1168+ for (ull = 0; !err && ull < max; ull++) {
1169+ i = array[ull];
1170+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 1171+ continue;
1172+
7f207e10 1173+ /* AuDbgInode(i); */
1facf9fc 1174+ if (au_iigen(i) == sigen)
1175+ ii_read_lock_child(i);
1176+ else {
1177+ ii_write_lock_child(i);
027c5e7a
AM
1178+ err = au_refresh_hinode_self(i);
1179+ au_iigen_dec(i);
1facf9fc 1180+ if (!err)
1181+ ii_downgrade_lock(i);
1182+ else {
1183+ ii_write_unlock(i);
1184+ break;
1185+ }
1186+ }
1187+
1188+ bstart = au_ibstart(i);
1189+ bend = au_ibend(i);
1190+ if (bstart <= bindex
1191+ && bindex <= bend
1192+ && au_h_iptr(i, bindex)
027c5e7a 1193+ && au_test_ibusy(i, bstart, bend)) {
1facf9fc 1194+ err = -EBUSY;
1195+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 1196+ AuDbgInode(i);
1facf9fc 1197+ }
1198+ ii_read_unlock(i);
1199+ }
7f207e10 1200+ au_iarray_free(array, max);
1facf9fc 1201+
7f207e10 1202+out:
1facf9fc 1203+ return err;
1204+}
1205+
b752ccd1
AM
1206+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
1207+ const unsigned int verbose)
1facf9fc 1208+{
1209+ int err;
1210+ unsigned int sigen;
1211+
1212+ sigen = au_sigen(root->d_sb);
1213+ DiMustNoWaiters(root);
1214+ IiMustNoWaiters(root->d_inode);
1215+ di_write_unlock(root);
b752ccd1 1216+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 1217+ if (!err)
b752ccd1 1218+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 1219+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
1220+
1221+ return err;
1222+}
1223+
1224+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
1225+ const aufs_bindex_t bindex,
1226+ const aufs_bindex_t bend)
1227+{
1228+ struct au_branch **brp, **p;
1229+
dece6358
AM
1230+ AuRwMustWriteLock(&sbinfo->si_rwsem);
1231+
1facf9fc 1232+ brp = sbinfo->si_branch + bindex;
1233+ if (bindex < bend)
1234+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
1235+ sbinfo->si_branch[0 + bend] = NULL;
1236+ sbinfo->si_bend--;
1237+
1238+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
1239+ if (p)
1240+ sbinfo->si_branch = p;
4a4d8108 1241+ /* harmless error */
1facf9fc 1242+}
1243+
1244+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
1245+ const aufs_bindex_t bend)
1246+{
1247+ struct au_hdentry *hdp, *p;
1248+
1308ab2a 1249+ AuRwMustWriteLock(&dinfo->di_rwsem);
1250+
4a4d8108 1251+ hdp = dinfo->di_hdentry;
1facf9fc 1252+ if (bindex < bend)
4a4d8108
AM
1253+ memmove(hdp + bindex, hdp + bindex + 1,
1254+ sizeof(*hdp) * (bend - bindex));
1255+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 1256+ dinfo->di_bend--;
1257+
4a4d8108 1258+ p = krealloc(hdp, sizeof(*p) * bend, GFP_NOFS);
1facf9fc 1259+ if (p)
1260+ dinfo->di_hdentry = p;
4a4d8108 1261+ /* harmless error */
1facf9fc 1262+}
1263+
1264+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
1265+ const aufs_bindex_t bend)
1266+{
1267+ struct au_hinode *hip, *p;
1268+
1308ab2a 1269+ AuRwMustWriteLock(&iinfo->ii_rwsem);
1270+
1facf9fc 1271+ hip = iinfo->ii_hinode + bindex;
1272+ if (bindex < bend)
1273+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
1274+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 1275+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 1276+ iinfo->ii_bend--;
1277+
1278+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
1279+ if (p)
1280+ iinfo->ii_hinode = p;
4a4d8108 1281+ /* harmless error */
1facf9fc 1282+}
1283+
1284+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
1285+ struct au_branch *br)
1286+{
1287+ aufs_bindex_t bend;
1288+ struct au_sbinfo *sbinfo;
1289+ struct dentry *root;
1290+ struct inode *inode;
1291+
dece6358
AM
1292+ SiMustWriteLock(sb);
1293+
1facf9fc 1294+ root = sb->s_root;
1295+ inode = root->d_inode;
1facf9fc 1296+ sbinfo = au_sbi(sb);
1297+ bend = sbinfo->si_bend;
1298+
1299+ dput(au_h_dptr(root, bindex));
1300+ au_hiput(au_hi(inode, bindex));
1301+ au_br_do_free(br);
1302+
1303+ au_br_do_del_brp(sbinfo, bindex, bend);
1304+ au_br_do_del_hdp(au_di(root), bindex, bend);
1305+ au_br_do_del_hip(au_ii(inode), bindex, bend);
1306+}
1307+
1308+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
1309+{
1310+ int err, rerr, i;
1311+ unsigned int mnt_flags;
1312+ aufs_bindex_t bindex, bend, br_id;
1313+ unsigned char do_wh, verbose;
1314+ struct au_branch *br;
1315+ struct au_wbr *wbr;
1316+
1317+ err = 0;
1318+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
1319+ if (bindex < 0) {
1320+ if (remount)
1321+ goto out; /* success */
1322+ err = -ENOENT;
4a4d8108 1323+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 1324+ goto out;
1325+ }
1326+ AuDbg("bindex b%d\n", bindex);
1327+
1328+ err = -EBUSY;
1329+ mnt_flags = au_mntflags(sb);
1330+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
1331+ bend = au_sbend(sb);
1332+ if (unlikely(!bend)) {
1333+ AuVerbose(verbose, "no more branches left\n");
1334+ goto out;
1335+ }
1336+ br = au_sbr(sb, bindex);
1337+ i = atomic_read(&br->br_count);
1338+ if (unlikely(i)) {
1339+ AuVerbose(verbose, "%d file(s) opened\n", i);
e49829fe 1340+ goto out;
1facf9fc 1341+ }
1342+
1343+ wbr = br->br_wbr;
1344+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
1345+ if (do_wh) {
1308ab2a 1346+ /* instead of WbrWhMustWriteLock(wbr) */
1347+ SiMustWriteLock(sb);
1facf9fc 1348+ for (i = 0; i < AuBrWh_Last; i++) {
1349+ dput(wbr->wbr_wh[i]);
1350+ wbr->wbr_wh[i] = NULL;
1351+ }
1352+ }
1353+
b752ccd1 1354+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 1355+ if (unlikely(err)) {
1356+ if (do_wh)
1357+ goto out_wh;
1358+ goto out;
1359+ }
1360+
1361+ err = 0;
1362+ br_id = br->br_id;
1363+ if (!remount)
1364+ au_br_do_del(sb, bindex, br);
1365+ else {
1366+ sysaufs_brs_del(sb, bindex);
1367+ au_br_do_del(sb, bindex, br);
1368+ sysaufs_brs_add(sb, bindex);
1369+ }
1370+
1308ab2a 1371+ if (!bindex) {
1facf9fc 1372+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 1373+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
1374+ } else
1facf9fc 1375+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
1376+ if (au_opt_test(mnt_flags, PLINK))
1377+ au_plink_half_refresh(sb, br_id);
1378+
b752ccd1 1379+ if (au_xino_brid(sb) == br_id)
1facf9fc 1380+ au_xino_brid_set(sb, -1);
1381+ goto out; /* success */
1382+
4f0767ce 1383+out_wh:
1facf9fc 1384+ /* revert */
1385+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
1386+ if (rerr)
4a4d8108
AM
1387+ pr_warning("failed re-creating base whiteout, %s. (%d)\n",
1388+ del->pathname, rerr);
4f0767ce 1389+out:
1facf9fc 1390+ return err;
1391+}
1392+
1393+/* ---------------------------------------------------------------------- */
1394+
027c5e7a
AM
1395+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
1396+{
1397+ int err;
1398+ aufs_bindex_t bstart, bend;
1399+ struct aufs_ibusy ibusy;
1400+ struct inode *inode, *h_inode;
1401+
1402+ err = -EPERM;
1403+ if (unlikely(!capable(CAP_SYS_ADMIN)))
1404+ goto out;
1405+
1406+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
1407+ if (!err)
1408+ err = !access_ok(VERIFY_WRITE, &arg->h_ino, sizeof(arg->h_ino));
1409+ if (unlikely(err)) {
1410+ err = -EFAULT;
1411+ AuTraceErr(err);
1412+ goto out;
1413+ }
1414+
1415+ err = -EINVAL;
1416+ si_read_lock(sb, AuLock_FLUSH);
1417+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbend(sb)))
1418+ goto out_unlock;
1419+
1420+ err = 0;
1421+ ibusy.h_ino = 0; /* invalid */
1422+ inode = ilookup(sb, ibusy.ino);
1423+ if (!inode
1424+ || inode->i_ino == AUFS_ROOT_INO
1425+ || is_bad_inode(inode))
1426+ goto out_unlock;
1427+
1428+ ii_read_lock_child(inode);
1429+ bstart = au_ibstart(inode);
1430+ bend = au_ibend(inode);
1431+ if (bstart <= ibusy.bindex && ibusy.bindex <= bend) {
1432+ h_inode = au_h_iptr(inode, ibusy.bindex);
1433+ if (h_inode && au_test_ibusy(inode, bstart, bend))
1434+ ibusy.h_ino = h_inode->i_ino;
1435+ }
1436+ ii_read_unlock(inode);
1437+ iput(inode);
1438+
1439+out_unlock:
1440+ si_read_unlock(sb);
1441+ if (!err) {
1442+ err = __put_user(ibusy.h_ino, &arg->h_ino);
1443+ if (unlikely(err)) {
1444+ err = -EFAULT;
1445+ AuTraceErr(err);
1446+ }
1447+ }
1448+out:
1449+ return err;
1450+}
1451+
1452+long au_ibusy_ioctl(struct file *file, unsigned long arg)
1453+{
1454+ return au_ibusy(file->f_dentry->d_sb, (void __user *)arg);
1455+}
1456+
1457+#ifdef CONFIG_COMPAT
1458+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
1459+{
1460+ return au_ibusy(file->f_dentry->d_sb, compat_ptr(arg));
1461+}
1462+#endif
1463+
1464+/* ---------------------------------------------------------------------- */
1465+
1facf9fc 1466+/*
1467+ * change a branch permission
1468+ */
1469+
dece6358
AM
1470+static void au_warn_ima(void)
1471+{
1472+#ifdef CONFIG_IMA
1308ab2a 1473+ /* since it doesn't support mark_files_ro() */
027c5e7a 1474+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
1475+#endif
1476+}
1477+
1facf9fc 1478+static int do_need_sigen_inc(int a, int b)
1479+{
1480+ return au_br_whable(a) && !au_br_whable(b);
1481+}
1482+
1483+static int need_sigen_inc(int old, int new)
1484+{
1485+ return do_need_sigen_inc(old, new)
1486+ || do_need_sigen_inc(new, old);
1487+}
1488+
7f207e10
AM
1489+static unsigned long long au_farray_cb(void *a,
1490+ unsigned long long max __maybe_unused,
1491+ void *arg)
1492+{
1493+ unsigned long long n;
1494+ struct file **p, *f;
1495+ struct super_block *sb = arg;
1496+
1497+ n = 0;
1498+ p = a;
1499+ lg_global_lock(files_lglock);
1500+ do_file_list_for_each_entry(sb, f) {
1501+ if (au_fi(f)
027c5e7a 1502+ && file_count(f)
7f207e10
AM
1503+ && !special_file(f->f_dentry->d_inode->i_mode)) {
1504+ get_file(f);
1505+ *p++ = f;
1506+ n++;
1507+ AuDebugOn(n > max);
1508+ }
1509+ } while_file_list_for_each_entry;
1510+ lg_global_unlock(files_lglock);
1511+
1512+ return n;
1513+}
1514+
1515+static struct file **au_farray_alloc(struct super_block *sb,
1516+ unsigned long long *max)
1517+{
1518+ *max = atomic_long_read(&au_sbi(sb)->si_nfiles);
1519+ return au_array_alloc(max, au_farray_cb, sb);
1520+}
1521+
1522+static void au_farray_free(struct file **a, unsigned long long max)
1523+{
1524+ unsigned long long ull;
1525+
1526+ for (ull = 0; ull < max; ull++)
1527+ if (a[ull])
1528+ fput(a[ull]);
1529+ au_array_free(a);
1530+}
1531+
1facf9fc 1532+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
1533+{
7f207e10 1534+ int err, do_warn;
027c5e7a 1535+ unsigned int mnt_flags;
7f207e10 1536+ unsigned long long ull, max;
e49829fe 1537+ aufs_bindex_t br_id;
027c5e7a 1538+ unsigned char verbose;
7f207e10 1539+ struct file *file, *hf, **array;
e49829fe
JR
1540+ struct inode *inode;
1541+ struct au_hfile *hfile;
1facf9fc 1542+
027c5e7a
AM
1543+ mnt_flags = au_mntflags(sb);
1544+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
1545+
7f207e10
AM
1546+ array = au_farray_alloc(sb, &max);
1547+ err = PTR_ERR(array);
1548+ if (IS_ERR(array))
1facf9fc 1549+ goto out;
1550+
7f207e10 1551+ do_warn = 0;
e49829fe 1552+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
1553+ for (ull = 0; ull < max; ull++) {
1554+ file = array[ull];
1facf9fc 1555+
7f207e10 1556+ /* AuDbg("%.*s\n", AuDLNPair(file->f_dentry)); */
1facf9fc 1557+ fi_read_lock(file);
1558+ if (unlikely(au_test_mmapped(file))) {
1559+ err = -EBUSY;
027c5e7a
AM
1560+ AuVerbose(verbose, "mmapped %.*s\n",
1561+ AuDLNPair(file->f_dentry));
7f207e10 1562+ AuDbgFile(file);
1facf9fc 1563+ FiMustNoWaiters(file);
1564+ fi_read_unlock(file);
7f207e10 1565+ goto out_array;
1facf9fc 1566+ }
1567+
027c5e7a 1568+ inode = file->f_dentry->d_inode;
e49829fe
JR
1569+ hfile = &au_fi(file)->fi_htop;
1570+ hf = hfile->hf_file;
1571+ if (!S_ISREG(inode->i_mode)
1facf9fc 1572+ || !(file->f_mode & FMODE_WRITE)
e49829fe 1573+ || hfile->hf_br->br_id != br_id
7f207e10
AM
1574+ || !(hf->f_mode & FMODE_WRITE))
1575+ array[ull] = NULL;
1576+ else {
1577+ do_warn = 1;
1578+ get_file(file);
1facf9fc 1579+ }
1580+
1facf9fc 1581+ FiMustNoWaiters(file);
1582+ fi_read_unlock(file);
7f207e10
AM
1583+ fput(file);
1584+ }
1facf9fc 1585+
1586+ err = 0;
7f207e10 1587+ if (do_warn)
dece6358 1588+ au_warn_ima();
7f207e10
AM
1589+
1590+ for (ull = 0; ull < max; ull++) {
1591+ file = array[ull];
1592+ if (!file)
1593+ continue;
1594+
1facf9fc 1595+ /* todo: already flushed? */
1596+ /* cf. fs/super.c:mark_files_ro() */
7f207e10
AM
1597+ /* fi_read_lock(file); */
1598+ hfile = &au_fi(file)->fi_htop;
1599+ hf = hfile->hf_file;
1600+ /* fi_read_unlock(file); */
027c5e7a 1601+ spin_lock(&hf->f_lock);
1facf9fc 1602+ hf->f_mode &= ~FMODE_WRITE;
027c5e7a 1603+ spin_unlock(&hf->f_lock);
1facf9fc 1604+ if (!file_check_writeable(hf)) {
1605+ file_release_write(hf);
1606+ mnt_drop_write(hf->f_vfsmnt);
1607+ }
1608+ }
1609+
7f207e10
AM
1610+out_array:
1611+ au_farray_free(array, max);
4f0767ce 1612+out:
7f207e10 1613+ AuTraceErr(err);
1facf9fc 1614+ return err;
1615+}
1616+
1617+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 1618+ int *do_refresh)
1facf9fc 1619+{
1620+ int err, rerr;
1621+ aufs_bindex_t bindex;
1308ab2a 1622+ struct path path;
1facf9fc 1623+ struct dentry *root;
1624+ struct au_branch *br;
1625+
1626+ root = sb->s_root;
1facf9fc 1627+ bindex = au_find_dbindex(root, mod->h_root);
1628+ if (bindex < 0) {
1629+ if (remount)
1630+ return 0; /* success */
1631+ err = -ENOENT;
4a4d8108 1632+ pr_err("%s no such branch\n", mod->path);
1facf9fc 1633+ goto out;
1634+ }
1635+ AuDbg("bindex b%d\n", bindex);
1636+
1637+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
1638+ if (unlikely(err))
1639+ goto out;
1640+
1641+ br = au_sbr(sb, bindex);
1642+ if (br->br_perm == mod->perm)
1643+ return 0; /* success */
1644+
1645+ if (au_br_writable(br->br_perm)) {
1646+ /* remove whiteout base */
1647+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
1648+ if (unlikely(err))
1649+ goto out;
1650+
1651+ if (!au_br_writable(mod->perm)) {
1652+ /* rw --> ro, file might be mmapped */
1653+ DiMustNoWaiters(root);
1654+ IiMustNoWaiters(root->d_inode);
1655+ di_write_unlock(root);
1656+ err = au_br_mod_files_ro(sb, bindex);
1657+ /* aufs_write_lock() calls ..._child() */
1658+ di_write_lock_child(root);
1659+
1660+ if (unlikely(err)) {
1661+ rerr = -ENOMEM;
1662+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
1663+ GFP_NOFS);
1308ab2a 1664+ if (br->br_wbr) {
1665+ path.mnt = br->br_mnt;
1666+ path.dentry = mod->h_root;
1667+ rerr = au_wbr_init(br, sb, br->br_perm,
1668+ &path);
1669+ }
1facf9fc 1670+ if (unlikely(rerr)) {
1671+ AuIOErr("nested error %d (%d)\n",
1672+ rerr, err);
1673+ br->br_perm = mod->perm;
1674+ }
1675+ }
1676+ }
1677+ } else if (au_br_writable(mod->perm)) {
1678+ /* ro --> rw */
1679+ err = -ENOMEM;
1680+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1681+ if (br->br_wbr) {
1308ab2a 1682+ path.mnt = br->br_mnt;
1683+ path.dentry = mod->h_root;
1facf9fc 1684+ err = au_wbr_init(br, sb, mod->perm, &path);
1685+ if (unlikely(err)) {
1686+ kfree(br->br_wbr);
1687+ br->br_wbr = NULL;
1688+ }
1689+ }
1690+ }
1691+
1692+ if (!err) {
7f207e10 1693+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
1facf9fc 1694+ br->br_perm = mod->perm;
1695+ }
1696+
4f0767ce 1697+out:
7f207e10 1698+ AuTraceErr(err);
1facf9fc 1699+ return err;
1700+}
7f207e10
AM
1701diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
1702--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
1703+++ linux/fs/aufs/branch.h 2011-03-21 20:22:06.850601942 +0100
1704@@ -0,0 +1,233 @@
1facf9fc 1705+/*
027c5e7a 1706+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 1707+ *
1708+ * This program, aufs is free software; you can redistribute it and/or modify
1709+ * it under the terms of the GNU General Public License as published by
1710+ * the Free Software Foundation; either version 2 of the License, or
1711+ * (at your option) any later version.
dece6358
AM
1712+ *
1713+ * This program is distributed in the hope that it will be useful,
1714+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1715+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1716+ * GNU General Public License for more details.
1717+ *
1718+ * You should have received a copy of the GNU General Public License
1719+ * along with this program; if not, write to the Free Software
1720+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1721+ */
1722+
1723+/*
1724+ * branch filesystems and xino for them
1725+ */
1726+
1727+#ifndef __AUFS_BRANCH_H__
1728+#define __AUFS_BRANCH_H__
1729+
1730+#ifdef __KERNEL__
1731+
1732+#include <linux/fs.h>
1733+#include <linux/mount.h>
1facf9fc 1734+#include <linux/aufs_type.h>
4a4d8108 1735+#include "dynop.h"
1facf9fc 1736+#include "rwsem.h"
1737+#include "super.h"
1738+
1739+/* ---------------------------------------------------------------------- */
1740+
1741+/* a xino file */
1742+struct au_xino_file {
1743+ struct file *xi_file;
1744+ struct mutex xi_nondir_mtx;
1745+
1746+ /* todo: make xino files an array to support huge inode number */
1747+
1748+#ifdef CONFIG_DEBUG_FS
1749+ struct dentry *xi_dbgaufs;
1750+#endif
1751+};
1752+
1753+/* members for writable branch only */
1754+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
1755+struct au_wbr {
dece6358 1756+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 1757+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 1758+ atomic_t wbr_wh_running;
1facf9fc 1759+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
1760+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
1761+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
1762+
1763+ /* mfs mode */
1764+ unsigned long long wbr_bytes;
1765+};
1766+
4a4d8108
AM
1767+/* ext2 has 3 types of operations at least, ext3 has 4 */
1768+#define AuBrDynOp (AuDyLast * 4)
1769+
1facf9fc 1770+/* protected by superblock rwsem */
1771+struct au_branch {
1772+ struct au_xino_file br_xino;
1773+
1774+ aufs_bindex_t br_id;
1775+
1776+ int br_perm;
1777+ struct vfsmount *br_mnt;
4a4d8108
AM
1778+ spinlock_t br_dykey_lock;
1779+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 1780+ atomic_t br_count;
1781+
1782+ struct au_wbr *br_wbr;
1783+
1784+ /* xino truncation */
1785+ blkcnt_t br_xino_upper; /* watermark in blocks */
1786+ atomic_t br_xino_running;
1787+
027c5e7a
AM
1788+#ifdef CONFIG_AUFS_HFSNOTIFY
1789+ struct fsnotify_group *br_hfsn_group;
1790+ struct fsnotify_ops br_hfsn_ops;
1791+#endif
1792+
1facf9fc 1793+#ifdef CONFIG_SYSFS
1794+ /* an entry under sysfs per mount-point */
1795+ char br_name[8];
1796+ struct attribute br_attr;
1797+#endif
1798+};
1799+
1800+/* ---------------------------------------------------------------------- */
1801+
1802+/* branch permission and attribute */
1803+enum {
1804+ AuBrPerm_RW, /* writable, linkable wh */
1805+ AuBrPerm_RO, /* readonly, no wh */
1806+ AuBrPerm_RR, /* natively readonly, no wh */
1807+
1808+ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
1809+
1810+ AuBrPerm_ROWH, /* whiteout-able */
1811+ AuBrPerm_RRWH, /* whiteout-able */
1812+
1813+ AuBrPerm_Last
1814+};
1815+
1816+static inline int au_br_writable(int brperm)
1817+{
1818+ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1819+}
1820+
1821+static inline int au_br_whable(int brperm)
1822+{
1823+ return brperm == AuBrPerm_RW
1824+ || brperm == AuBrPerm_ROWH
1825+ || brperm == AuBrPerm_RRWH;
1826+}
1827+
1828+static inline int au_br_rdonly(struct au_branch *br)
1829+{
1830+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1831+ || !au_br_writable(br->br_perm))
1832+ ? -EROFS : 0;
1833+}
1834+
4a4d8108 1835+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 1836+{
4a4d8108 1837+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 1838+ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1839+#else
1840+ return 0;
1841+#endif
1842+}
1843+
1844+/* ---------------------------------------------------------------------- */
1845+
1846+/* branch.c */
1847+struct au_sbinfo;
1848+void au_br_free(struct au_sbinfo *sinfo);
1849+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1850+struct au_opt_add;
1851+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1852+struct au_opt_del;
1853+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
1854+long au_ibusy_ioctl(struct file *file, unsigned long arg);
1855+#ifdef CONFIG_COMPAT
1856+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
1857+#endif
1facf9fc 1858+struct au_opt_mod;
1859+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 1860+ int *do_refresh);
1facf9fc 1861+
1862+/* xino.c */
1863+static const loff_t au_loff_max = LLONG_MAX;
1864+
1865+int au_xib_trunc(struct super_block *sb);
1866+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1867+ loff_t *pos);
1868+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1869+ loff_t *pos);
1870+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
1871+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1872+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 1873+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 1874+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1875+ ino_t ino);
1876+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1877+ ino_t *ino);
1878+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1879+ struct file *base_file, int do_test);
1880+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1881+
1882+struct au_opt_xino;
1883+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1884+void au_xino_clr(struct super_block *sb);
1885+struct file *au_xino_def(struct super_block *sb);
1886+int au_xino_path(struct seq_file *seq, struct file *file);
1887+
1888+/* ---------------------------------------------------------------------- */
1889+
1890+/* Superblock to branch */
1891+static inline
1892+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1893+{
1894+ return au_sbr(sb, bindex)->br_id;
1895+}
1896+
1897+static inline
1898+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1899+{
1900+ return au_sbr(sb, bindex)->br_mnt;
1901+}
1902+
1903+static inline
1904+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1905+{
1906+ return au_sbr_mnt(sb, bindex)->mnt_sb;
1907+}
1908+
1909+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1910+{
e49829fe 1911+ atomic_dec(&au_sbr(sb, bindex)->br_count);
1facf9fc 1912+}
1913+
1914+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1915+{
1916+ return au_sbr(sb, bindex)->br_perm;
1917+}
1918+
1919+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1920+{
1921+ return au_br_whable(au_sbr_perm(sb, bindex));
1922+}
1923+
1924+/* ---------------------------------------------------------------------- */
1925+
1926+/*
1927+ * wbr_wh_read_lock, wbr_wh_write_lock
1928+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
1929+ */
1930+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
1931+
dece6358
AM
1932+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
1933+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
1934+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
1935+
1facf9fc 1936+#endif /* __KERNEL__ */
1937+#endif /* __AUFS_BRANCH_H__ */
7f207e10
AM
1938diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
1939--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
027c5e7a 1940+++ linux/fs/aufs/conf.mk 2011-03-21 20:22:06.850601942 +0100
e49829fe 1941@@ -0,0 +1,37 @@
4a4d8108
AM
1942+
1943+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
1944+
1945+define AuConf
1946+ifdef ${1}
1947+AuConfStr += ${1}=${${1}}
1948+endif
1949+endef
1950+
b752ccd1 1951+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 1952+ SBILIST \
7f207e10 1953+ HNOTIFY HFSNOTIFY \
4a4d8108
AM
1954+ EXPORT INO_T_64 \
1955+ RDU \
1956+ SP_IATTR \
1957+ SHWH \
1958+ BR_RAMFS \
1959+ BR_FUSE POLL \
1960+ BR_HFSPLUS \
1961+ BDEV_LOOP \
b752ccd1
AM
1962+ DEBUG MAGIC_SYSRQ
1963+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
1964+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
1965+
1966+AuConfName = ${obj}/conf.str
1967+${AuConfName}.tmp: FORCE
1968+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
1969+${AuConfName}: ${AuConfName}.tmp
1970+ @diff -q $< $@ > /dev/null 2>&1 || { \
1971+ echo ' GEN ' $@; \
1972+ cp -p $< $@; \
1973+ }
1974+FORCE:
1975+clean-files += ${AuConfName} ${AuConfName}.tmp
1976+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
1977+
1978+-include ${srctree}/${src}/conf_priv.mk
7f207e10
AM
1979diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
1980--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
1981+++ linux/fs/aufs/cpup.c 2011-03-21 20:22:06.850601942 +0100
1982@@ -0,0 +1,1063 @@
1facf9fc 1983+/*
027c5e7a 1984+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 1985+ *
1986+ * This program, aufs is free software; you can redistribute it and/or modify
1987+ * it under the terms of the GNU General Public License as published by
1988+ * the Free Software Foundation; either version 2 of the License, or
1989+ * (at your option) any later version.
dece6358
AM
1990+ *
1991+ * This program is distributed in the hope that it will be useful,
1992+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1993+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1994+ * GNU General Public License for more details.
1995+ *
1996+ * You should have received a copy of the GNU General Public License
1997+ * along with this program; if not, write to the Free Software
1998+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1999+ */
2000+
2001+/*
2002+ * copy-up functions, see wbr_policy.c for copy-down
2003+ */
2004+
dece6358 2005+#include <linux/file.h>
1facf9fc 2006+#include <linux/fs_stack.h>
dece6358 2007+#include <linux/mm.h>
1facf9fc 2008+#include <linux/uaccess.h>
2009+#include "aufs.h"
2010+
2011+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
2012+{
2013+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
2014+ | S_NOATIME | S_NOCMTIME;
2015+
2016+ dst->i_flags |= src->i_flags & ~mask;
2017+ if (au_test_fs_notime(dst->i_sb))
2018+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
2019+}
2020+
2021+void au_cpup_attr_timesizes(struct inode *inode)
2022+{
2023+ struct inode *h_inode;
2024+
2025+ h_inode = au_h_iptr(inode, au_ibstart(inode));
2026+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 2027+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 2028+}
2029+
2030+void au_cpup_attr_nlink(struct inode *inode, int force)
2031+{
2032+ struct inode *h_inode;
2033+ struct super_block *sb;
2034+ aufs_bindex_t bindex, bend;
2035+
2036+ sb = inode->i_sb;
2037+ bindex = au_ibstart(inode);
2038+ h_inode = au_h_iptr(inode, bindex);
2039+ if (!force
2040+ && !S_ISDIR(h_inode->i_mode)
2041+ && au_opt_test(au_mntflags(sb), PLINK)
2042+ && au_plink_test(inode))
2043+ return;
2044+
2045+ inode->i_nlink = h_inode->i_nlink;
2046+
2047+ /*
2048+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
2049+ * it may includes whplink directory.
2050+ */
2051+ if (S_ISDIR(h_inode->i_mode)) {
2052+ bend = au_ibend(inode);
2053+ for (bindex++; bindex <= bend; bindex++) {
2054+ h_inode = au_h_iptr(inode, bindex);
2055+ if (h_inode)
2056+ au_add_nlink(inode, h_inode);
2057+ }
2058+ }
2059+}
2060+
2061+void au_cpup_attr_changeable(struct inode *inode)
2062+{
2063+ struct inode *h_inode;
2064+
2065+ h_inode = au_h_iptr(inode, au_ibstart(inode));
2066+ inode->i_mode = h_inode->i_mode;
2067+ inode->i_uid = h_inode->i_uid;
2068+ inode->i_gid = h_inode->i_gid;
2069+ au_cpup_attr_timesizes(inode);
2070+ au_cpup_attr_flags(inode, h_inode);
2071+}
2072+
2073+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
2074+{
2075+ struct au_iinfo *iinfo = au_ii(inode);
2076+
1308ab2a 2077+ IiMustWriteLock(inode);
2078+
1facf9fc 2079+ iinfo->ii_higen = h_inode->i_generation;
2080+ iinfo->ii_hsb1 = h_inode->i_sb;
2081+}
2082+
2083+void au_cpup_attr_all(struct inode *inode, int force)
2084+{
2085+ struct inode *h_inode;
2086+
2087+ h_inode = au_h_iptr(inode, au_ibstart(inode));
2088+ au_cpup_attr_changeable(inode);
2089+ if (inode->i_nlink > 0)
2090+ au_cpup_attr_nlink(inode, force);
2091+ inode->i_rdev = h_inode->i_rdev;
2092+ inode->i_blkbits = h_inode->i_blkbits;
2093+ au_cpup_igen(inode, h_inode);
2094+}
2095+
2096+/* ---------------------------------------------------------------------- */
2097+
2098+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
2099+
2100+/* keep the timestamps of the parent dir when cpup */
2101+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
2102+ struct path *h_path)
2103+{
2104+ struct inode *h_inode;
2105+
2106+ dt->dt_dentry = dentry;
2107+ dt->dt_h_path = *h_path;
2108+ h_inode = h_path->dentry->d_inode;
2109+ dt->dt_atime = h_inode->i_atime;
2110+ dt->dt_mtime = h_inode->i_mtime;
2111+ /* smp_mb(); */
2112+}
2113+
2114+void au_dtime_revert(struct au_dtime *dt)
2115+{
2116+ struct iattr attr;
2117+ int err;
2118+
2119+ attr.ia_atime = dt->dt_atime;
2120+ attr.ia_mtime = dt->dt_mtime;
2121+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
2122+ | ATTR_ATIME | ATTR_ATIME_SET;
2123+
2124+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
2125+ if (unlikely(err))
4a4d8108 2126+ pr_warning("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 2127+}
2128+
2129+/* ---------------------------------------------------------------------- */
2130+
2131+static noinline_for_stack
2132+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
2133+{
2134+ int err, sbits;
2135+ struct iattr ia;
2136+ struct path h_path;
1308ab2a 2137+ struct inode *h_isrc, *h_idst;
1facf9fc 2138+
2139+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 2140+ h_idst = h_path.dentry->d_inode;
1facf9fc 2141+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
2142+ h_isrc = h_src->d_inode;
1308ab2a 2143+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 2144+ | ATTR_ATIME | ATTR_MTIME
2145+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 2146+ ia.ia_uid = h_isrc->i_uid;
2147+ ia.ia_gid = h_isrc->i_gid;
2148+ ia.ia_atime = h_isrc->i_atime;
2149+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 2150+ if (h_idst->i_mode != h_isrc->i_mode
2151+ && !S_ISLNK(h_idst->i_mode)) {
2152+ ia.ia_valid |= ATTR_MODE;
2153+ ia.ia_mode = h_isrc->i_mode;
2154+ }
2155+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
2156+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 2157+ err = vfsub_notify_change(&h_path, &ia);
2158+
2159+ /* is this nfs only? */
2160+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
2161+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
2162+ ia.ia_mode = h_isrc->i_mode;
2163+ err = vfsub_notify_change(&h_path, &ia);
2164+ }
2165+
2166+ return err;
2167+}
2168+
2169+/* ---------------------------------------------------------------------- */
2170+
2171+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
2172+ char *buf, unsigned long blksize)
2173+{
2174+ int err;
2175+ size_t sz, rbytes, wbytes;
2176+ unsigned char all_zero;
2177+ char *p, *zp;
2178+ struct mutex *h_mtx;
2179+ /* reduce stack usage */
2180+ struct iattr *ia;
2181+
2182+ zp = page_address(ZERO_PAGE(0));
2183+ if (unlikely(!zp))
2184+ return -ENOMEM; /* possible? */
2185+
2186+ err = 0;
2187+ all_zero = 0;
2188+ while (len) {
2189+ AuDbg("len %lld\n", len);
2190+ sz = blksize;
2191+ if (len < blksize)
2192+ sz = len;
2193+
2194+ rbytes = 0;
2195+ /* todo: signal_pending? */
2196+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
2197+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
2198+ err = rbytes;
2199+ }
2200+ if (unlikely(err < 0))
2201+ break;
2202+
2203+ all_zero = 0;
2204+ if (len >= rbytes && rbytes == blksize)
2205+ all_zero = !memcmp(buf, zp, rbytes);
2206+ if (!all_zero) {
2207+ wbytes = rbytes;
2208+ p = buf;
2209+ while (wbytes) {
2210+ size_t b;
2211+
2212+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
2213+ err = b;
2214+ /* todo: signal_pending? */
2215+ if (unlikely(err == -EAGAIN || err == -EINTR))
2216+ continue;
2217+ if (unlikely(err < 0))
2218+ break;
2219+ wbytes -= b;
2220+ p += b;
2221+ }
2222+ } else {
2223+ loff_t res;
2224+
2225+ AuLabel(hole);
2226+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
2227+ err = res;
2228+ if (unlikely(res < 0))
2229+ break;
2230+ }
2231+ len -= rbytes;
2232+ err = 0;
2233+ }
2234+
2235+ /* the last block may be a hole */
2236+ if (!err && all_zero) {
2237+ AuLabel(last hole);
2238+
2239+ err = 1;
2240+ if (au_test_nfs(dst->f_dentry->d_sb)) {
2241+ /* nfs requires this step to make last hole */
2242+ /* is this only nfs? */
2243+ do {
2244+ /* todo: signal_pending? */
2245+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
2246+ } while (err == -EAGAIN || err == -EINTR);
2247+ if (err == 1)
2248+ dst->f_pos--;
2249+ }
2250+
2251+ if (err == 1) {
2252+ ia = (void *)buf;
2253+ ia->ia_size = dst->f_pos;
2254+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
2255+ ia->ia_file = dst;
2256+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
2257+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
2258+ err = vfsub_notify_change(&dst->f_path, ia);
2259+ mutex_unlock(h_mtx);
2260+ }
2261+ }
2262+
2263+ return err;
2264+}
2265+
2266+int au_copy_file(struct file *dst, struct file *src, loff_t len)
2267+{
2268+ int err;
2269+ unsigned long blksize;
2270+ unsigned char do_kfree;
2271+ char *buf;
2272+
2273+ err = -ENOMEM;
2274+ blksize = dst->f_dentry->d_sb->s_blocksize;
2275+ if (!blksize || PAGE_SIZE < blksize)
2276+ blksize = PAGE_SIZE;
2277+ AuDbg("blksize %lu\n", blksize);
2278+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
2279+ if (do_kfree)
2280+ buf = kmalloc(blksize, GFP_NOFS);
2281+ else
2282+ buf = (void *)__get_free_page(GFP_NOFS);
2283+ if (unlikely(!buf))
2284+ goto out;
2285+
2286+ if (len > (1 << 22))
2287+ AuDbg("copying a large file %lld\n", (long long)len);
2288+
2289+ src->f_pos = 0;
2290+ dst->f_pos = 0;
2291+ err = au_do_copy_file(dst, src, len, buf, blksize);
2292+ if (do_kfree)
2293+ kfree(buf);
2294+ else
2295+ free_page((unsigned long)buf);
2296+
4f0767ce 2297+out:
1facf9fc 2298+ return err;
2299+}
2300+
2301+/*
2302+ * to support a sparse file which is opened with O_APPEND,
2303+ * we need to close the file.
2304+ */
2305+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 2306+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 2307+{
2308+ int err, i;
2309+ enum { SRC, DST };
2310+ struct {
2311+ aufs_bindex_t bindex;
2312+ unsigned int flags;
2313+ struct dentry *dentry;
2314+ struct file *file;
2315+ void *label, *label_file;
2316+ } *f, file[] = {
2317+ {
2318+ .bindex = bsrc,
2319+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
2320+ .file = NULL,
2321+ .label = &&out,
2322+ .label_file = &&out_src
2323+ },
2324+ {
2325+ .bindex = bdst,
2326+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
2327+ .file = NULL,
2328+ .label = &&out_src,
2329+ .label_file = &&out_dst
2330+ }
2331+ };
2332+ struct super_block *sb;
2333+
2334+ /* bsrc branch can be ro/rw. */
2335+ sb = dentry->d_sb;
2336+ f = file;
2337+ for (i = 0; i < 2; i++, f++) {
2338+ f->dentry = au_h_dptr(dentry, f->bindex);
2339+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
2340+ err = PTR_ERR(f->file);
2341+ if (IS_ERR(f->file))
2342+ goto *f->label;
2343+ err = -EINVAL;
2344+ if (unlikely(!f->file->f_op))
2345+ goto *f->label_file;
2346+ }
2347+
2348+ /* try stopping to update while we copyup */
2349+ IMustLock(file[SRC].dentry->d_inode);
2350+ err = au_copy_file(file[DST].file, file[SRC].file, len);
2351+
4f0767ce 2352+out_dst:
1facf9fc 2353+ fput(file[DST].file);
2354+ au_sbr_put(sb, file[DST].bindex);
4f0767ce 2355+out_src:
1facf9fc 2356+ fput(file[SRC].file);
2357+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 2358+out:
1facf9fc 2359+ return err;
2360+}
2361+
2362+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
2363+ aufs_bindex_t bsrc, loff_t len,
2364+ struct inode *h_dir, struct path *h_path)
2365+{
2366+ int err, rerr;
2367+ loff_t l;
2368+
2369+ err = 0;
2370+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
2371+ if (len == -1 || l < len)
2372+ len = l;
2373+ if (len)
2374+ err = au_cp_regular(dentry, bdst, bsrc, len);
2375+ if (!err)
2376+ goto out; /* success */
2377+
2378+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
2379+ if (rerr) {
2380+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
2381+ AuDLNPair(h_path->dentry), err, rerr);
2382+ err = -EIO;
2383+ }
2384+
4f0767ce 2385+out:
1facf9fc 2386+ return err;
2387+}
2388+
2389+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
2390+ struct inode *h_dir)
2391+{
2392+ int err, symlen;
2393+ mm_segment_t old_fs;
b752ccd1
AM
2394+ union {
2395+ char *k;
2396+ char __user *u;
2397+ } sym;
1facf9fc 2398+
2399+ err = -ENOSYS;
2400+ if (unlikely(!h_src->d_inode->i_op->readlink))
2401+ goto out;
2402+
2403+ err = -ENOMEM;
b752ccd1
AM
2404+ sym.k = __getname_gfp(GFP_NOFS);
2405+ if (unlikely(!sym.k))
1facf9fc 2406+ goto out;
2407+
2408+ old_fs = get_fs();
2409+ set_fs(KERNEL_DS);
b752ccd1 2410+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 2411+ err = symlen;
2412+ set_fs(old_fs);
2413+
2414+ if (symlen > 0) {
b752ccd1
AM
2415+ sym.k[symlen] = 0;
2416+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 2417+ }
b752ccd1 2418+ __putname(sym.k);
1facf9fc 2419+
4f0767ce 2420+out:
1facf9fc 2421+ return err;
2422+}
2423+
2424+/* return with the lower dst inode is locked */
2425+static noinline_for_stack
2426+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
2427+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2428+ struct dentry *dst_parent)
2429+{
2430+ int err;
2431+ umode_t mode;
2432+ unsigned int mnt_flags;
2433+ unsigned char isdir;
2434+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
2435+ struct au_dtime dt;
2436+ struct path h_path;
2437+ struct dentry *h_src, *h_dst, *h_parent;
2438+ struct inode *h_inode, *h_dir;
2439+ struct super_block *sb;
2440+
2441+ /* bsrc branch can be ro/rw. */
2442+ h_src = au_h_dptr(dentry, bsrc);
2443+ h_inode = h_src->d_inode;
2444+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
2445+
2446+ /* try stopping to be referenced while we are creating */
2447+ h_dst = au_h_dptr(dentry, bdst);
2448+ h_parent = h_dst->d_parent; /* dir inode is locked */
2449+ h_dir = h_parent->d_inode;
2450+ IMustLock(h_dir);
2451+ AuDebugOn(h_parent != h_dst->d_parent);
2452+
2453+ sb = dentry->d_sb;
2454+ h_path.mnt = au_sbr_mnt(sb, bdst);
2455+ if (do_dt) {
2456+ h_path.dentry = h_parent;
2457+ au_dtime_store(&dt, dst_parent, &h_path);
2458+ }
2459+ h_path.dentry = h_dst;
2460+
2461+ isdir = 0;
2462+ mode = h_inode->i_mode;
2463+ switch (mode & S_IFMT) {
2464+ case S_IFREG:
2465+ /* try stopping to update while we are referencing */
2466+ IMustLock(h_inode);
2467+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
2468+ if (!err)
2469+ err = au_do_cpup_regular
2470+ (dentry, bdst, bsrc, len,
2471+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
2472+ break;
2473+ case S_IFDIR:
2474+ isdir = 1;
2475+ err = vfsub_mkdir(h_dir, &h_path, mode);
2476+ if (!err) {
2477+ /*
2478+ * strange behaviour from the users view,
2479+ * particularry setattr case
2480+ */
2481+ if (au_ibstart(dst_parent->d_inode) == bdst)
2482+ au_cpup_attr_nlink(dst_parent->d_inode,
2483+ /*force*/1);
2484+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
2485+ }
2486+ break;
2487+ case S_IFLNK:
2488+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
2489+ break;
2490+ case S_IFCHR:
2491+ case S_IFBLK:
2492+ AuDebugOn(!capable(CAP_MKNOD));
2493+ /*FALLTHROUGH*/
2494+ case S_IFIFO:
2495+ case S_IFSOCK:
2496+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
2497+ break;
2498+ default:
2499+ AuIOErr("Unknown inode type 0%o\n", mode);
2500+ err = -EIO;
2501+ }
2502+
2503+ mnt_flags = au_mntflags(sb);
2504+ if (!au_opt_test(mnt_flags, UDBA_NONE)
2505+ && !isdir
2506+ && au_opt_test(mnt_flags, XINO)
2507+ && h_inode->i_nlink == 1
2508+ /* todo: unnecessary? */
2509+ /* && dentry->d_inode->i_nlink == 1 */
2510+ && bdst < bsrc
2511+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 2512+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 2513+ /* ignore this error */
2514+
2515+ if (do_dt)
2516+ au_dtime_revert(&dt);
2517+ return err;
2518+}
2519+
2520+/*
2521+ * copyup the @dentry from @bsrc to @bdst.
2522+ * the caller must set the both of lower dentries.
2523+ * @len is for truncating when it is -1 copyup the entire file.
2524+ * in link/rename cases, @dst_parent may be different from the real one.
2525+ */
2526+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2527+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2528+ struct dentry *dst_parent)
2529+{
2530+ int err, rerr;
2531+ aufs_bindex_t old_ibstart;
2532+ unsigned char isdir, plink;
2533+ struct au_dtime dt;
2534+ struct path h_path;
2535+ struct dentry *h_src, *h_dst, *h_parent;
2536+ struct inode *dst_inode, *h_dir, *inode;
2537+ struct super_block *sb;
2538+
2539+ AuDebugOn(bsrc <= bdst);
2540+
2541+ sb = dentry->d_sb;
2542+ h_path.mnt = au_sbr_mnt(sb, bdst);
2543+ h_dst = au_h_dptr(dentry, bdst);
2544+ h_parent = h_dst->d_parent; /* dir inode is locked */
2545+ h_dir = h_parent->d_inode;
2546+ IMustLock(h_dir);
2547+
2548+ h_src = au_h_dptr(dentry, bsrc);
2549+ inode = dentry->d_inode;
2550+
2551+ if (!dst_parent)
2552+ dst_parent = dget_parent(dentry);
2553+ else
2554+ dget(dst_parent);
2555+
2556+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
2557+ dst_inode = au_h_iptr(inode, bdst);
2558+ if (dst_inode) {
2559+ if (unlikely(!plink)) {
2560+ err = -EIO;
027c5e7a
AM
2561+ AuIOErr("hi%lu(i%lu) exists on b%d "
2562+ "but plink is disabled\n",
2563+ dst_inode->i_ino, inode->i_ino, bdst);
1facf9fc 2564+ goto out;
2565+ }
2566+
2567+ if (dst_inode->i_nlink) {
2568+ const int do_dt = au_ftest_cpup(flags, DTIME);
2569+
2570+ h_src = au_plink_lkup(inode, bdst);
2571+ err = PTR_ERR(h_src);
2572+ if (IS_ERR(h_src))
2573+ goto out;
2574+ if (unlikely(!h_src->d_inode)) {
2575+ err = -EIO;
2576+ AuIOErr("i%lu exists on a upper branch "
027c5e7a
AM
2577+ "but not pseudo-linked\n",
2578+ inode->i_ino);
1facf9fc 2579+ dput(h_src);
2580+ goto out;
2581+ }
2582+
2583+ if (do_dt) {
2584+ h_path.dentry = h_parent;
2585+ au_dtime_store(&dt, dst_parent, &h_path);
2586+ }
2587+ h_path.dentry = h_dst;
2588+ err = vfsub_link(h_src, h_dir, &h_path);
2589+ if (do_dt)
2590+ au_dtime_revert(&dt);
2591+ dput(h_src);
2592+ goto out;
2593+ } else
2594+ /* todo: cpup_wh_file? */
2595+ /* udba work */
4a4d8108 2596+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 2597+ }
2598+
2599+ old_ibstart = au_ibstart(inode);
2600+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
2601+ if (unlikely(err))
2602+ goto out;
2603+ dst_inode = h_dst->d_inode;
2604+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
2605+
2606+ err = cpup_iattr(dentry, bdst, h_src);
2607+ isdir = S_ISDIR(dst_inode->i_mode);
2608+ if (!err) {
4a4d8108
AM
2609+ if (bdst < old_ibstart) {
2610+ if (S_ISREG(inode->i_mode)) {
2611+ err = au_dy_iaop(inode, bdst, dst_inode);
2612+ if (unlikely(err))
2613+ goto out_rev;
2614+ }
1facf9fc 2615+ au_set_ibstart(inode, bdst);
4a4d8108 2616+ }
1facf9fc 2617+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
2618+ au_hi_flags(inode, isdir));
2619+ mutex_unlock(&dst_inode->i_mutex);
2620+ if (!isdir
2621+ && h_src->d_inode->i_nlink > 1
2622+ && plink)
2623+ au_plink_append(inode, bdst, h_dst);
2624+ goto out; /* success */
2625+ }
2626+
2627+ /* revert */
4a4d8108 2628+out_rev:
1facf9fc 2629+ h_path.dentry = h_parent;
2630+ mutex_unlock(&dst_inode->i_mutex);
2631+ au_dtime_store(&dt, dst_parent, &h_path);
2632+ h_path.dentry = h_dst;
2633+ if (!isdir)
2634+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
2635+ else
2636+ rerr = vfsub_rmdir(h_dir, &h_path);
2637+ au_dtime_revert(&dt);
2638+ if (rerr) {
2639+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
2640+ err = -EIO;
2641+ }
2642+
4f0767ce 2643+out:
1facf9fc 2644+ dput(dst_parent);
2645+ return err;
2646+}
2647+
2648+struct au_cpup_single_args {
2649+ int *errp;
2650+ struct dentry *dentry;
2651+ aufs_bindex_t bdst, bsrc;
2652+ loff_t len;
2653+ unsigned int flags;
2654+ struct dentry *dst_parent;
2655+};
2656+
2657+static void au_call_cpup_single(void *args)
2658+{
2659+ struct au_cpup_single_args *a = args;
2660+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
2661+ a->flags, a->dst_parent);
2662+}
2663+
2664+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2665+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2666+ struct dentry *dst_parent)
2667+{
2668+ int err, wkq_err;
2669+ umode_t mode;
2670+ struct dentry *h_dentry;
2671+
2672+ h_dentry = au_h_dptr(dentry, bsrc);
2673+ mode = h_dentry->d_inode->i_mode & S_IFMT;
2674+ if ((mode != S_IFCHR && mode != S_IFBLK)
2675+ || capable(CAP_MKNOD))
2676+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2677+ dst_parent);
2678+ else {
2679+ struct au_cpup_single_args args = {
2680+ .errp = &err,
2681+ .dentry = dentry,
2682+ .bdst = bdst,
2683+ .bsrc = bsrc,
2684+ .len = len,
2685+ .flags = flags,
2686+ .dst_parent = dst_parent
2687+ };
2688+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
2689+ if (unlikely(wkq_err))
2690+ err = wkq_err;
2691+ }
2692+
2693+ return err;
2694+}
2695+
2696+/*
2697+ * copyup the @dentry from the first active lower branch to @bdst,
2698+ * using au_cpup_single().
2699+ */
2700+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2701+ unsigned int flags)
2702+{
2703+ int err;
2704+ aufs_bindex_t bsrc, bend;
2705+
2706+ bend = au_dbend(dentry);
2707+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2708+ if (au_h_dptr(dentry, bsrc))
2709+ break;
2710+
2711+ err = au_lkup_neg(dentry, bdst);
2712+ if (!err) {
2713+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
2714+ if (!err)
2715+ return 0; /* success */
2716+
2717+ /* revert */
2718+ au_set_h_dptr(dentry, bdst, NULL);
2719+ au_set_dbstart(dentry, bsrc);
2720+ }
2721+
2722+ return err;
2723+}
2724+
2725+struct au_cpup_simple_args {
2726+ int *errp;
2727+ struct dentry *dentry;
2728+ aufs_bindex_t bdst;
2729+ loff_t len;
2730+ unsigned int flags;
2731+};
2732+
2733+static void au_call_cpup_simple(void *args)
2734+{
2735+ struct au_cpup_simple_args *a = args;
2736+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
2737+}
2738+
2739+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2740+ unsigned int flags)
2741+{
2742+ int err, wkq_err;
2743+ unsigned char do_sio;
2744+ struct dentry *parent;
2745+ struct inode *h_dir;
2746+
2747+ parent = dget_parent(dentry);
2748+ h_dir = au_h_iptr(parent->d_inode, bdst);
2749+ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
2750+ if (!do_sio) {
2751+ /*
2752+ * testing CAP_MKNOD is for generic fs,
2753+ * but CAP_FSETID is for xfs only, currently.
2754+ */
2755+ umode_t mode = dentry->d_inode->i_mode;
2756+ do_sio = (((mode & (S_IFCHR | S_IFBLK))
2757+ && !capable(CAP_MKNOD))
2758+ || ((mode & (S_ISUID | S_ISGID))
2759+ && !capable(CAP_FSETID)));
2760+ }
2761+ if (!do_sio)
2762+ err = au_cpup_simple(dentry, bdst, len, flags);
2763+ else {
2764+ struct au_cpup_simple_args args = {
2765+ .errp = &err,
2766+ .dentry = dentry,
2767+ .bdst = bdst,
2768+ .len = len,
2769+ .flags = flags
2770+ };
2771+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
2772+ if (unlikely(wkq_err))
2773+ err = wkq_err;
2774+ }
2775+
2776+ dput(parent);
2777+ return err;
2778+}
2779+
2780+/* ---------------------------------------------------------------------- */
2781+
2782+/*
2783+ * copyup the deleted file for writing.
2784+ */
2785+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2786+ struct dentry *wh_dentry, struct file *file,
2787+ loff_t len)
2788+{
2789+ int err;
2790+ aufs_bindex_t bstart;
2791+ struct au_dinfo *dinfo;
2792+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 2793+ struct au_hdentry *hdp;
1facf9fc 2794+
2795+ dinfo = au_di(dentry);
1308ab2a 2796+ AuRwMustWriteLock(&dinfo->di_rwsem);
2797+
1facf9fc 2798+ bstart = dinfo->di_bstart;
4a4d8108
AM
2799+ hdp = dinfo->di_hdentry;
2800+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 2801+ dinfo->di_bstart = bdst;
4a4d8108 2802+ hdp[0 + bdst].hd_dentry = wh_dentry;
027c5e7a
AM
2803+ if (file) {
2804+ h_d_start = hdp[0 + bstart].hd_dentry;
4a4d8108 2805+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
027c5e7a 2806+ }
1facf9fc 2807+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2808+ /*h_parent*/NULL);
027c5e7a
AM
2809+ if (file) {
2810+ if (!err)
2811+ err = au_reopen_nondir(file);
4a4d8108 2812+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 2813+ }
4a4d8108 2814+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 2815+ dinfo->di_bstart = bstart;
2816+
2817+ return err;
2818+}
2819+
2820+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2821+ struct file *file)
2822+{
2823+ int err;
2824+ struct au_dtime dt;
2825+ struct dentry *parent, *h_parent, *wh_dentry;
2826+ struct au_branch *br;
2827+ struct path h_path;
2828+
2829+ br = au_sbr(dentry->d_sb, bdst);
2830+ parent = dget_parent(dentry);
2831+ h_parent = au_h_dptr(parent, bdst);
2832+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
2833+ err = PTR_ERR(wh_dentry);
2834+ if (IS_ERR(wh_dentry))
2835+ goto out;
2836+
2837+ h_path.dentry = h_parent;
2838+ h_path.mnt = br->br_mnt;
2839+ au_dtime_store(&dt, parent, &h_path);
2840+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
2841+ if (unlikely(err))
2842+ goto out_wh;
2843+
2844+ dget(wh_dentry);
2845+ h_path.dentry = wh_dentry;
4a4d8108
AM
2846+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
2847+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
2848+ else
2849+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 2850+ if (unlikely(err)) {
2851+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2852+ AuDLNPair(wh_dentry), err);
2853+ err = -EIO;
2854+ }
2855+ au_dtime_revert(&dt);
2856+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2857+
4f0767ce 2858+out_wh:
1facf9fc 2859+ dput(wh_dentry);
4f0767ce 2860+out:
1facf9fc 2861+ dput(parent);
2862+ return err;
2863+}
2864+
2865+struct au_cpup_wh_args {
2866+ int *errp;
2867+ struct dentry *dentry;
2868+ aufs_bindex_t bdst;
2869+ loff_t len;
2870+ struct file *file;
2871+};
2872+
2873+static void au_call_cpup_wh(void *args)
2874+{
2875+ struct au_cpup_wh_args *a = args;
2876+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
2877+}
2878+
2879+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2880+ struct file *file)
2881+{
2882+ int err, wkq_err;
2883+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
2884+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
2885+ struct au_wbr *wbr;
2886+
2887+ parent = dget_parent(dentry);
2888+ dir = parent->d_inode;
2889+ h_orph = NULL;
2890+ h_parent = NULL;
2891+ h_dir = au_igrab(au_h_iptr(dir, bdst));
2892+ h_tmpdir = h_dir;
2893+ if (!h_dir->i_nlink) {
2894+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
2895+ h_orph = wbr->wbr_orph;
2896+
2897+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 2898+ au_set_h_dptr(parent, bdst, dget(h_orph));
2899+ h_tmpdir = h_orph->d_inode;
1facf9fc 2900+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
2901+
2902+ /* this temporary unlock is safe */
2903+ if (file)
4a4d8108 2904+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2905+ else
2906+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
2907+ h_inode = h_dentry->d_inode;
2908+ IMustLock(h_inode);
2909+ mutex_unlock(&h_inode->i_mutex);
dece6358 2910+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 2911+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 2912+ /* todo: au_h_open_pre()? */
1facf9fc 2913+ }
2914+
2915+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
2916+ err = au_cpup_wh(dentry, bdst, len, file);
2917+ else {
2918+ struct au_cpup_wh_args args = {
2919+ .errp = &err,
2920+ .dentry = dentry,
2921+ .bdst = bdst,
2922+ .len = len,
2923+ .file = file
2924+ };
2925+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
2926+ if (unlikely(wkq_err))
2927+ err = wkq_err;
2928+ }
2929+
2930+ if (h_orph) {
2931+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 2932+ /* todo: au_h_open_post()? */
1facf9fc 2933+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 2934+ au_set_h_dptr(parent, bdst, h_parent);
2935+ }
2936+ iput(h_dir);
2937+ dput(parent);
2938+
2939+ return err;
2940+}
2941+
2942+/* ---------------------------------------------------------------------- */
2943+
2944+/*
2945+ * generic routine for both of copy-up and copy-down.
2946+ */
2947+/* cf. revalidate function in file.c */
2948+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2949+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2950+ struct dentry *h_parent, void *arg),
2951+ void *arg)
2952+{
2953+ int err;
2954+ struct au_pin pin;
2955+ struct dentry *d, *parent, *h_parent, *real_parent;
2956+
2957+ err = 0;
2958+ parent = dget_parent(dentry);
2959+ if (IS_ROOT(parent))
2960+ goto out;
2961+
2962+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
2963+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
2964+
2965+ /* do not use au_dpage */
2966+ real_parent = parent;
2967+ while (1) {
2968+ dput(parent);
2969+ parent = dget_parent(dentry);
2970+ h_parent = au_h_dptr(parent, bdst);
2971+ if (h_parent)
2972+ goto out; /* success */
2973+
2974+ /* find top dir which is necessary to cpup */
2975+ do {
2976+ d = parent;
2977+ dput(parent);
2978+ parent = dget_parent(d);
2979+ di_read_lock_parent3(parent, !AuLock_IR);
2980+ h_parent = au_h_dptr(parent, bdst);
2981+ di_read_unlock(parent, !AuLock_IR);
2982+ } while (!h_parent);
2983+
2984+ if (d != real_parent)
2985+ di_write_lock_child3(d);
2986+
2987+ /* somebody else might create while we were sleeping */
2988+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
2989+ if (au_h_dptr(d, bdst))
2990+ au_update_dbstart(d);
2991+
2992+ au_pin_set_dentry(&pin, d);
2993+ err = au_do_pin(&pin);
2994+ if (!err) {
2995+ err = cp(d, bdst, h_parent, arg);
2996+ au_unpin(&pin);
2997+ }
2998+ }
2999+
3000+ if (d != real_parent)
3001+ di_write_unlock(d);
3002+ if (unlikely(err))
3003+ break;
3004+ }
3005+
4f0767ce 3006+out:
1facf9fc 3007+ dput(parent);
3008+ return err;
3009+}
3010+
3011+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
3012+ struct dentry *h_parent __maybe_unused ,
3013+ void *arg __maybe_unused)
3014+{
3015+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
3016+}
3017+
3018+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
3019+{
3020+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
3021+}
3022+
3023+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
3024+{
3025+ int err;
3026+ struct dentry *parent;
3027+ struct inode *dir;
3028+
3029+ parent = dget_parent(dentry);
3030+ dir = parent->d_inode;
3031+ err = 0;
3032+ if (au_h_iptr(dir, bdst))
3033+ goto out;
3034+
3035+ di_read_unlock(parent, AuLock_IR);
3036+ di_write_lock_parent(parent);
3037+ /* someone else might change our inode while we were sleeping */
3038+ if (!au_h_iptr(dir, bdst))
3039+ err = au_cpup_dirs(dentry, bdst);
3040+ di_downgrade_lock(parent, AuLock_IR);
3041+
4f0767ce 3042+out:
1facf9fc 3043+ dput(parent);
3044+ return err;
3045+}
7f207e10
AM
3046diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
3047--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 3048+++ linux/fs/aufs/cpup.h 2011-03-21 20:22:06.850601942 +0100
7f207e10 3049@@ -0,0 +1,83 @@
1facf9fc 3050+/*
027c5e7a 3051+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3052+ *
3053+ * This program, aufs is free software; you can redistribute it and/or modify
3054+ * it under the terms of the GNU General Public License as published by
3055+ * the Free Software Foundation; either version 2 of the License, or
3056+ * (at your option) any later version.
dece6358
AM
3057+ *
3058+ * This program is distributed in the hope that it will be useful,
3059+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3060+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3061+ * GNU General Public License for more details.
3062+ *
3063+ * You should have received a copy of the GNU General Public License
3064+ * along with this program; if not, write to the Free Software
3065+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3066+ */
3067+
3068+/*
3069+ * copy-up/down functions
3070+ */
3071+
3072+#ifndef __AUFS_CPUP_H__
3073+#define __AUFS_CPUP_H__
3074+
3075+#ifdef __KERNEL__
3076+
dece6358
AM
3077+#include <linux/path.h>
3078+#include <linux/time.h>
1facf9fc 3079+#include <linux/aufs_type.h>
3080+
dece6358
AM
3081+struct inode;
3082+struct file;
3083+
1facf9fc 3084+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
3085+void au_cpup_attr_timesizes(struct inode *inode);
3086+void au_cpup_attr_nlink(struct inode *inode, int force);
3087+void au_cpup_attr_changeable(struct inode *inode);
3088+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
3089+void au_cpup_attr_all(struct inode *inode, int force);
3090+
3091+/* ---------------------------------------------------------------------- */
3092+
3093+/* cpup flags */
3094+#define AuCpup_DTIME 1 /* do dtime_store/revert */
3095+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
3096+ for link(2) */
3097+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
3098+#define au_fset_cpup(flags, name) \
3099+ do { (flags) |= AuCpup_##name; } while (0)
3100+#define au_fclr_cpup(flags, name) \
3101+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 3102+
3103+int au_copy_file(struct file *dst, struct file *src, loff_t len);
3104+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
3105+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3106+ struct dentry *dst_parent);
3107+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
3108+ unsigned int flags);
3109+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
3110+ struct file *file);
3111+
3112+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
3113+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
3114+ struct dentry *h_parent, void *arg),
3115+ void *arg);
3116+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
3117+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
3118+
3119+/* ---------------------------------------------------------------------- */
3120+
3121+/* keep timestamps when copyup */
3122+struct au_dtime {
3123+ struct dentry *dt_dentry;
3124+ struct path dt_h_path;
3125+ struct timespec dt_atime, dt_mtime;
3126+};
3127+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
3128+ struct path *h_path);
3129+void au_dtime_revert(struct au_dtime *dt);
3130+
3131+#endif /* __KERNEL__ */
3132+#endif /* __AUFS_CPUP_H__ */
7f207e10
AM
3133diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
3134--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a 3135+++ linux/fs/aufs/dbgaufs.c 2011-03-21 20:22:06.850601942 +0100
4a4d8108 3136@@ -0,0 +1,334 @@
1facf9fc 3137+/*
027c5e7a 3138+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3139+ *
3140+ * This program, aufs is free software; you can redistribute it and/or modify
3141+ * it under the terms of the GNU General Public License as published by
3142+ * the Free Software Foundation; either version 2 of the License, or
3143+ * (at your option) any later version.
dece6358
AM
3144+ *
3145+ * This program is distributed in the hope that it will be useful,
3146+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3147+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3148+ * GNU General Public License for more details.
3149+ *
3150+ * You should have received a copy of the GNU General Public License
3151+ * along with this program; if not, write to the Free Software
3152+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3153+ */
3154+
3155+/*
3156+ * debugfs interface
3157+ */
3158+
3159+#include <linux/debugfs.h>
3160+#include "aufs.h"
3161+
3162+#ifndef CONFIG_SYSFS
3163+#error DEBUG_FS depends upon SYSFS
3164+#endif
3165+
3166+static struct dentry *dbgaufs;
3167+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
3168+
3169+/* 20 is max digits length of ulong 64 */
3170+struct dbgaufs_arg {
3171+ int n;
3172+ char a[20 * 4];
3173+};
3174+
3175+/*
3176+ * common function for all XINO files
3177+ */
3178+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
3179+ struct file *file)
3180+{
3181+ kfree(file->private_data);
3182+ return 0;
3183+}
3184+
3185+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
3186+{
3187+ int err;
3188+ struct kstat st;
3189+ struct dbgaufs_arg *p;
3190+
3191+ err = -ENOMEM;
3192+ p = kmalloc(sizeof(*p), GFP_NOFS);
3193+ if (unlikely(!p))
3194+ goto out;
3195+
3196+ err = 0;
3197+ p->n = 0;
3198+ file->private_data = p;
3199+ if (!xf)
3200+ goto out;
3201+
3202+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
3203+ if (!err) {
3204+ if (do_fcnt)
3205+ p->n = snprintf
3206+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
3207+ (long)file_count(xf), st.blocks, st.blksize,
3208+ (long long)st.size);
3209+ else
3210+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
3211+ st.blocks, st.blksize,
3212+ (long long)st.size);
3213+ AuDebugOn(p->n >= sizeof(p->a));
3214+ } else {
3215+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
3216+ err = 0;
3217+ }
3218+
4f0767ce 3219+out:
1facf9fc 3220+ return err;
3221+
3222+}
3223+
3224+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
3225+ size_t count, loff_t *ppos)
3226+{
3227+ struct dbgaufs_arg *p;
3228+
3229+ p = file->private_data;
3230+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
3231+}
3232+
3233+/* ---------------------------------------------------------------------- */
3234+
3235+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
3236+{
3237+ int err;
3238+ struct au_sbinfo *sbinfo;
3239+ struct super_block *sb;
3240+
3241+ sbinfo = inode->i_private;
3242+ sb = sbinfo->si_sb;
3243+ si_noflush_read_lock(sb);
3244+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
3245+ si_read_unlock(sb);
3246+ return err;
3247+}
3248+
3249+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 3250+ .owner = THIS_MODULE,
1facf9fc 3251+ .open = dbgaufs_xib_open,
3252+ .release = dbgaufs_xi_release,
3253+ .read = dbgaufs_xi_read
3254+};
3255+
3256+/* ---------------------------------------------------------------------- */
3257+
3258+#define DbgaufsXi_PREFIX "xi"
3259+
3260+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
3261+{
3262+ int err;
3263+ long l;
3264+ struct au_sbinfo *sbinfo;
3265+ struct super_block *sb;
3266+ struct file *xf;
3267+ struct qstr *name;
3268+
3269+ err = -ENOENT;
3270+ xf = NULL;
3271+ name = &file->f_dentry->d_name;
3272+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
3273+ || memcmp(name->name, DbgaufsXi_PREFIX,
3274+ sizeof(DbgaufsXi_PREFIX) - 1)))
3275+ goto out;
3276+ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
3277+ if (unlikely(err))
3278+ goto out;
3279+
3280+ sbinfo = inode->i_private;
3281+ sb = sbinfo->si_sb;
3282+ si_noflush_read_lock(sb);
3283+ if (l <= au_sbend(sb)) {
3284+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
3285+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
3286+ } else
3287+ err = -ENOENT;
3288+ si_read_unlock(sb);
3289+
4f0767ce 3290+out:
1facf9fc 3291+ return err;
3292+}
3293+
3294+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 3295+ .owner = THIS_MODULE,
1facf9fc 3296+ .open = dbgaufs_xino_open,
3297+ .release = dbgaufs_xi_release,
3298+ .read = dbgaufs_xi_read
3299+};
3300+
3301+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
3302+{
3303+ aufs_bindex_t bend;
3304+ struct au_branch *br;
3305+ struct au_xino_file *xi;
3306+
3307+ if (!au_sbi(sb)->si_dbgaufs)
3308+ return;
3309+
3310+ bend = au_sbend(sb);
3311+ for (; bindex <= bend; bindex++) {
3312+ br = au_sbr(sb, bindex);
3313+ xi = &br->br_xino;
3314+ if (xi->xi_dbgaufs) {
3315+ debugfs_remove(xi->xi_dbgaufs);
3316+ xi->xi_dbgaufs = NULL;
3317+ }
3318+ }
3319+}
3320+
3321+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
3322+{
3323+ struct au_sbinfo *sbinfo;
3324+ struct dentry *parent;
3325+ struct au_branch *br;
3326+ struct au_xino_file *xi;
3327+ aufs_bindex_t bend;
3328+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
3329+
3330+ sbinfo = au_sbi(sb);
3331+ parent = sbinfo->si_dbgaufs;
3332+ if (!parent)
3333+ return;
3334+
3335+ bend = au_sbend(sb);
3336+ for (; bindex <= bend; bindex++) {
3337+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
3338+ br = au_sbr(sb, bindex);
3339+ xi = &br->br_xino;
3340+ AuDebugOn(xi->xi_dbgaufs);
3341+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
3342+ sbinfo, &dbgaufs_xino_fop);
3343+ /* ignore an error */
3344+ if (unlikely(!xi->xi_dbgaufs))
3345+ AuWarn1("failed %s under debugfs\n", name);
3346+ }
3347+}
3348+
3349+/* ---------------------------------------------------------------------- */
3350+
3351+#ifdef CONFIG_AUFS_EXPORT
3352+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
3353+{
3354+ int err;
3355+ struct au_sbinfo *sbinfo;
3356+ struct super_block *sb;
3357+
3358+ sbinfo = inode->i_private;
3359+ sb = sbinfo->si_sb;
3360+ si_noflush_read_lock(sb);
3361+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
3362+ si_read_unlock(sb);
3363+ return err;
3364+}
3365+
3366+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 3367+ .owner = THIS_MODULE,
1facf9fc 3368+ .open = dbgaufs_xigen_open,
3369+ .release = dbgaufs_xi_release,
3370+ .read = dbgaufs_xi_read
3371+};
3372+
3373+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3374+{
3375+ int err;
3376+
dece6358
AM
3377+ /*
3378+ * This function is a dynamic '__init' fucntion actually,
3379+ * so the tiny check for si_rwsem is unnecessary.
3380+ */
3381+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3382+
1facf9fc 3383+ err = -EIO;
3384+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
3385+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3386+ &dbgaufs_xigen_fop);
3387+ if (sbinfo->si_dbgaufs_xigen)
3388+ err = 0;
3389+
3390+ return err;
3391+}
3392+#else
3393+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3394+{
3395+ return 0;
3396+}
3397+#endif /* CONFIG_AUFS_EXPORT */
3398+
3399+/* ---------------------------------------------------------------------- */
3400+
3401+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
3402+{
dece6358
AM
3403+ /*
3404+ * This function is a dynamic '__init' fucntion actually,
3405+ * so the tiny check for si_rwsem is unnecessary.
3406+ */
3407+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3408+
1facf9fc 3409+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
3410+ sbinfo->si_dbgaufs = NULL;
3411+ kobject_put(&sbinfo->si_kobj);
3412+}
3413+
3414+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
3415+{
3416+ int err;
3417+ char name[SysaufsSiNameLen];
3418+
dece6358
AM
3419+ /*
3420+ * This function is a dynamic '__init' fucntion actually,
3421+ * so the tiny check for si_rwsem is unnecessary.
3422+ */
3423+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3424+
1facf9fc 3425+ err = -ENOENT;
3426+ if (!dbgaufs) {
3427+ AuErr1("/debug/aufs is uninitialized\n");
3428+ goto out;
3429+ }
3430+
3431+ err = -EIO;
3432+ sysaufs_name(sbinfo, name);
3433+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
3434+ if (unlikely(!sbinfo->si_dbgaufs))
3435+ goto out;
3436+ kobject_get(&sbinfo->si_kobj);
3437+
3438+ sbinfo->si_dbgaufs_xib = debugfs_create_file
3439+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3440+ &dbgaufs_xib_fop);
3441+ if (unlikely(!sbinfo->si_dbgaufs_xib))
3442+ goto out_dir;
3443+
3444+ err = dbgaufs_xigen_init(sbinfo);
3445+ if (!err)
3446+ goto out; /* success */
3447+
4f0767ce 3448+out_dir:
1facf9fc 3449+ dbgaufs_si_fin(sbinfo);
4f0767ce 3450+out:
1facf9fc 3451+ return err;
3452+}
3453+
3454+/* ---------------------------------------------------------------------- */
3455+
3456+void dbgaufs_fin(void)
3457+{
3458+ debugfs_remove(dbgaufs);
3459+}
3460+
3461+int __init dbgaufs_init(void)
3462+{
3463+ int err;
3464+
3465+ err = -EIO;
3466+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
3467+ if (dbgaufs)
3468+ err = 0;
3469+ return err;
3470+}
7f207e10
AM
3471diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
3472--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 3473+++ linux/fs/aufs/dbgaufs.h 2011-03-21 20:22:06.850601942 +0100
4a4d8108 3474@@ -0,0 +1,52 @@
1facf9fc 3475+/*
027c5e7a 3476+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3477+ *
3478+ * This program, aufs is free software; you can redistribute it and/or modify
3479+ * it under the terms of the GNU General Public License as published by
3480+ * the Free Software Foundation; either version 2 of the License, or
3481+ * (at your option) any later version.
dece6358
AM
3482+ *
3483+ * This program is distributed in the hope that it will be useful,
3484+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3485+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3486+ * GNU General Public License for more details.
3487+ *
3488+ * You should have received a copy of the GNU General Public License
3489+ * along with this program; if not, write to the Free Software
3490+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3491+ */
3492+
3493+/*
3494+ * debugfs interface
3495+ */
3496+
3497+#ifndef __DBGAUFS_H__
3498+#define __DBGAUFS_H__
3499+
3500+#ifdef __KERNEL__
3501+
dece6358 3502+#include <linux/init.h>
1facf9fc 3503+#include <linux/aufs_type.h>
3504+
dece6358 3505+struct super_block;
1facf9fc 3506+struct au_sbinfo;
dece6358 3507+
1facf9fc 3508+#ifdef CONFIG_DEBUG_FS
3509+/* dbgaufs.c */
3510+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
3511+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
3512+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
3513+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
3514+void dbgaufs_fin(void);
3515+int __init dbgaufs_init(void);
1facf9fc 3516+#else
4a4d8108
AM
3517+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
3518+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
3519+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
3520+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
3521+AuStubVoid(dbgaufs_fin, void)
3522+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 3523+#endif /* CONFIG_DEBUG_FS */
3524+
3525+#endif /* __KERNEL__ */
3526+#endif /* __DBGAUFS_H__ */
7f207e10
AM
3527diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
3528--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
3529+++ linux/fs/aufs/dcsub.c 2011-03-21 20:22:06.850601942 +0100
3530@@ -0,0 +1,243 @@
1facf9fc 3531+/*
027c5e7a 3532+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3533+ *
3534+ * This program, aufs is free software; you can redistribute it and/or modify
3535+ * it under the terms of the GNU General Public License as published by
3536+ * the Free Software Foundation; either version 2 of the License, or
3537+ * (at your option) any later version.
dece6358
AM
3538+ *
3539+ * This program is distributed in the hope that it will be useful,
3540+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3541+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3542+ * GNU General Public License for more details.
3543+ *
3544+ * You should have received a copy of the GNU General Public License
3545+ * along with this program; if not, write to the Free Software
3546+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3547+ */
3548+
3549+/*
3550+ * sub-routines for dentry cache
3551+ */
3552+
3553+#include "aufs.h"
3554+
3555+static void au_dpage_free(struct au_dpage *dpage)
3556+{
3557+ int i;
3558+ struct dentry **p;
3559+
3560+ p = dpage->dentries;
3561+ for (i = 0; i < dpage->ndentry; i++)
3562+ dput(*p++);
3563+ free_page((unsigned long)dpage->dentries);
3564+}
3565+
3566+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
3567+{
3568+ int err;
3569+ void *p;
3570+
3571+ err = -ENOMEM;
3572+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
3573+ if (unlikely(!dpages->dpages))
3574+ goto out;
3575+
3576+ p = (void *)__get_free_page(gfp);
3577+ if (unlikely(!p))
3578+ goto out_dpages;
3579+
3580+ dpages->dpages[0].ndentry = 0;
3581+ dpages->dpages[0].dentries = p;
3582+ dpages->ndpage = 1;
3583+ return 0; /* success */
3584+
4f0767ce 3585+out_dpages:
1facf9fc 3586+ kfree(dpages->dpages);
4f0767ce 3587+out:
1facf9fc 3588+ return err;
3589+}
3590+
3591+void au_dpages_free(struct au_dcsub_pages *dpages)
3592+{
3593+ int i;
3594+ struct au_dpage *p;
3595+
3596+ p = dpages->dpages;
3597+ for (i = 0; i < dpages->ndpage; i++)
3598+ au_dpage_free(p++);
3599+ kfree(dpages->dpages);
3600+}
3601+
3602+static int au_dpages_append(struct au_dcsub_pages *dpages,
3603+ struct dentry *dentry, gfp_t gfp)
3604+{
3605+ int err, sz;
3606+ struct au_dpage *dpage;
3607+ void *p;
3608+
3609+ dpage = dpages->dpages + dpages->ndpage - 1;
3610+ sz = PAGE_SIZE / sizeof(dentry);
3611+ if (unlikely(dpage->ndentry >= sz)) {
3612+ AuLabel(new dpage);
3613+ err = -ENOMEM;
3614+ sz = dpages->ndpage * sizeof(*dpages->dpages);
3615+ p = au_kzrealloc(dpages->dpages, sz,
3616+ sz + sizeof(*dpages->dpages), gfp);
3617+ if (unlikely(!p))
3618+ goto out;
3619+
3620+ dpages->dpages = p;
3621+ dpage = dpages->dpages + dpages->ndpage;
3622+ p = (void *)__get_free_page(gfp);
3623+ if (unlikely(!p))
3624+ goto out;
3625+
3626+ dpage->ndentry = 0;
3627+ dpage->dentries = p;
3628+ dpages->ndpage++;
3629+ }
3630+
027c5e7a
AM
3631+ AuDebugOn(!dentry->d_count);
3632+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 3633+ return 0; /* success */
3634+
4f0767ce 3635+out:
1facf9fc 3636+ return err;
3637+}
3638+
3639+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3640+ au_dpages_test test, void *arg)
3641+{
3642+ int err;
027c5e7a 3643+ struct dentry *this_parent;
1facf9fc 3644+ struct list_head *next;
3645+ struct super_block *sb = root->d_sb;
3646+
3647+ err = 0;
027c5e7a
AM
3648+ write_seqlock(&rename_lock);
3649+ this_parent = root;
3650+ spin_lock(&this_parent->d_lock);
4f0767ce 3651+repeat:
1facf9fc 3652+ next = this_parent->d_subdirs.next;
4f0767ce 3653+resume:
1facf9fc 3654+ if (this_parent->d_sb == sb
3655+ && !IS_ROOT(this_parent)
027c5e7a
AM
3656+ && au_di(this_parent)
3657+ && this_parent->d_count
1facf9fc 3658+ && (!test || test(this_parent, arg))) {
3659+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3660+ if (unlikely(err))
3661+ goto out;
3662+ }
3663+
3664+ while (next != &this_parent->d_subdirs) {
3665+ struct list_head *tmp = next;
3666+ struct dentry *dentry = list_entry(tmp, struct dentry,
3667+ d_u.d_child);
027c5e7a 3668+
1facf9fc 3669+ next = tmp->next;
027c5e7a
AM
3670+ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
3671+ if (dentry->d_count) {
3672+ if (!list_empty(&dentry->d_subdirs)) {
3673+ spin_unlock(&this_parent->d_lock);
3674+ spin_release(&dentry->d_lock.dep_map, 1,
3675+ _RET_IP_);
3676+ this_parent = dentry;
3677+ spin_acquire(&this_parent->d_lock.dep_map, 0, 1,
3678+ _RET_IP_);
3679+ goto repeat;
3680+ }
3681+ if (dentry->d_sb == sb
3682+ && au_di(dentry)
3683+ && (!test || test(dentry, arg)))
3684+ err = au_dpages_append(dpages, dentry,
3685+ GFP_ATOMIC);
1facf9fc 3686+ }
027c5e7a
AM
3687+ spin_unlock(&dentry->d_lock);
3688+ if (unlikely(err))
3689+ goto out;
1facf9fc 3690+ }
3691+
3692+ if (this_parent != root) {
027c5e7a
AM
3693+ struct dentry *tmp;
3694+ struct dentry *child;
3695+
3696+ tmp = this_parent->d_parent;
3697+ rcu_read_lock();
3698+ spin_unlock(&this_parent->d_lock);
3699+ child = this_parent;
3700+ this_parent = tmp;
3701+ spin_lock(&this_parent->d_lock);
3702+ rcu_read_unlock();
3703+ next = child->d_u.d_child.next;
1facf9fc 3704+ goto resume;
3705+ }
027c5e7a 3706+
4f0767ce 3707+out:
027c5e7a
AM
3708+ spin_unlock(&this_parent->d_lock);
3709+ write_sequnlock(&rename_lock);
1facf9fc 3710+ return err;
3711+}
3712+
3713+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3714+ int do_include, au_dpages_test test, void *arg)
3715+{
3716+ int err;
3717+
3718+ err = 0;
027c5e7a
AM
3719+ write_seqlock(&rename_lock);
3720+ spin_lock(&dentry->d_lock);
3721+ if (do_include
3722+ && dentry->d_count
3723+ && (!test || test(dentry, arg)))
1facf9fc 3724+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
3725+ spin_unlock(&dentry->d_lock);
3726+ if (unlikely(err))
3727+ goto out;
3728+
3729+ /*
3730+ * vfsmount_lock is unnecessary since this is a traverse in a single
3731+ * mount
3732+ */
1facf9fc 3733+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
3734+ dentry = dentry->d_parent; /* rename_lock is locked */
3735+ spin_lock(&dentry->d_lock);
3736+ if (dentry->d_count
3737+ && (!test || test(dentry, arg)))
1facf9fc 3738+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
3739+ spin_unlock(&dentry->d_lock);
3740+ if (unlikely(err))
3741+ break;
1facf9fc 3742+ }
3743+
4f0767ce 3744+out:
027c5e7a 3745+ write_sequnlock(&rename_lock);
1facf9fc 3746+ return err;
3747+}
3748+
027c5e7a
AM
3749+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
3750+{
3751+ return au_di(dentry) && dentry->d_sb == arg;
3752+}
3753+
3754+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
3755+ struct dentry *dentry, int do_include)
3756+{
3757+ return au_dcsub_pages_rev(dpages, dentry, do_include,
3758+ au_dcsub_dpages_aufs, dentry->d_sb);
3759+}
3760+
4a4d8108 3761+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 3762+{
4a4d8108
AM
3763+ struct path path[2] = {
3764+ {
3765+ .dentry = d1
3766+ },
3767+ {
3768+ .dentry = d2
3769+ }
3770+ };
1facf9fc 3771+
4a4d8108 3772+ return path_is_under(path + 0, path + 1);
1facf9fc 3773+}
7f207e10
AM
3774diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
3775--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
3776+++ linux/fs/aufs/dcsub.h 2011-03-21 20:22:06.853935428 +0100
3777@@ -0,0 +1,95 @@
1facf9fc 3778+/*
027c5e7a 3779+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3780+ *
3781+ * This program, aufs is free software; you can redistribute it and/or modify
3782+ * it under the terms of the GNU General Public License as published by
3783+ * the Free Software Foundation; either version 2 of the License, or
3784+ * (at your option) any later version.
dece6358
AM
3785+ *
3786+ * This program is distributed in the hope that it will be useful,
3787+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3788+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3789+ * GNU General Public License for more details.
3790+ *
3791+ * You should have received a copy of the GNU General Public License
3792+ * along with this program; if not, write to the Free Software
3793+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3794+ */
3795+
3796+/*
3797+ * sub-routines for dentry cache
3798+ */
3799+
3800+#ifndef __AUFS_DCSUB_H__
3801+#define __AUFS_DCSUB_H__
3802+
3803+#ifdef __KERNEL__
3804+
7f207e10 3805+#include <linux/dcache.h>
027c5e7a 3806+#include <linux/fs.h>
dece6358
AM
3807+#include <linux/types.h>
3808+
3809+struct dentry;
1facf9fc 3810+
3811+struct au_dpage {
3812+ int ndentry;
3813+ struct dentry **dentries;
3814+};
3815+
3816+struct au_dcsub_pages {
3817+ int ndpage;
3818+ struct au_dpage *dpages;
3819+};
3820+
3821+/* ---------------------------------------------------------------------- */
3822+
7f207e10 3823+/* dcsub.c */
1facf9fc 3824+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3825+void au_dpages_free(struct au_dcsub_pages *dpages);
3826+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3827+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3828+ au_dpages_test test, void *arg);
3829+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3830+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
3831+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
3832+ struct dentry *dentry, int do_include);
4a4d8108 3833+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 3834+
7f207e10
AM
3835+/* ---------------------------------------------------------------------- */
3836+
027c5e7a
AM
3837+static inline int au_d_hashed_positive(struct dentry *d)
3838+{
3839+ int err;
3840+ struct inode *inode = d->d_inode;
3841+ err = 0;
3842+ if (unlikely(d_unhashed(d) || !inode || !inode->i_nlink))
3843+ err = -ENOENT;
3844+ return err;
3845+}
3846+
3847+static inline int au_d_alive(struct dentry *d)
3848+{
3849+ int err;
3850+ struct inode *inode;
3851+ err = 0;
3852+ if (!IS_ROOT(d))
3853+ err = au_d_hashed_positive(d);
3854+ else {
3855+ inode = d->d_inode;
3856+ if (unlikely(d_unlinked(d) || !inode || !inode->i_nlink))
3857+ err = -ENOENT;
3858+ }
3859+ return err;
3860+}
3861+
3862+static inline int au_alive_dir(struct dentry *d)
7f207e10 3863+{
027c5e7a
AM
3864+ int err;
3865+ err = au_d_alive(d);
3866+ if (unlikely(err || IS_DEADDIR(d->d_inode)))
3867+ err = -ENOENT;
3868+ return err;
7f207e10
AM
3869+}
3870+
1facf9fc 3871+#endif /* __KERNEL__ */
3872+#endif /* __AUFS_DCSUB_H__ */
7f207e10
AM
3873diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
3874--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
3875+++ linux/fs/aufs/debug.c 2011-03-21 20:22:06.853935428 +0100
3876@@ -0,0 +1,469 @@
1facf9fc 3877+/*
027c5e7a 3878+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3879+ *
3880+ * This program, aufs is free software; you can redistribute it and/or modify
3881+ * it under the terms of the GNU General Public License as published by
3882+ * the Free Software Foundation; either version 2 of the License, or
3883+ * (at your option) any later version.
dece6358
AM
3884+ *
3885+ * This program is distributed in the hope that it will be useful,
3886+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3887+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3888+ * GNU General Public License for more details.
3889+ *
3890+ * You should have received a copy of the GNU General Public License
3891+ * along with this program; if not, write to the Free Software
3892+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3893+ */
3894+
3895+/*
3896+ * debug print functions
3897+ */
3898+
dece6358 3899+#include <linux/module.h>
7f207e10 3900+#include <linux/vt_kern.h>
1facf9fc 3901+#include "aufs.h"
3902+
3903+int aufs_debug;
3904+MODULE_PARM_DESC(debug, "debug print");
3905+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
3906+
3907+char *au_plevel = KERN_DEBUG;
e49829fe
JR
3908+#define dpri(fmt, ...) do { \
3909+ if ((au_plevel \
3910+ && strcmp(au_plevel, KERN_DEBUG)) \
3911+ || au_debug_test()) \
3912+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 3913+} while (0)
3914+
3915+/* ---------------------------------------------------------------------- */
3916+
3917+void au_dpri_whlist(struct au_nhash *whlist)
3918+{
3919+ unsigned long ul, n;
3920+ struct hlist_head *head;
3921+ struct au_vdir_wh *tpos;
3922+ struct hlist_node *pos;
3923+
3924+ n = whlist->nh_num;
3925+ head = whlist->nh_head;
3926+ for (ul = 0; ul < n; ul++) {
3927+ hlist_for_each_entry(tpos, pos, head, wh_hash)
3928+ dpri("b%d, %.*s, %d\n",
3929+ tpos->wh_bindex,
3930+ tpos->wh_str.len, tpos->wh_str.name,
3931+ tpos->wh_str.len);
3932+ head++;
3933+ }
3934+}
3935+
3936+void au_dpri_vdir(struct au_vdir *vdir)
3937+{
3938+ unsigned long ul;
3939+ union au_vdir_deblk_p p;
3940+ unsigned char *o;
3941+
3942+ if (!vdir || IS_ERR(vdir)) {
3943+ dpri("err %ld\n", PTR_ERR(vdir));
3944+ return;
3945+ }
3946+
3947+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
3948+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
3949+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
3950+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
3951+ p.deblk = vdir->vd_deblk[ul];
3952+ o = p.deblk;
3953+ dpri("[%lu]: %p\n", ul, o);
3954+ }
3955+}
3956+
3957+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3958+ struct dentry *wh)
3959+{
3960+ char *n = NULL;
3961+ int l = 0;
3962+
3963+ if (!inode || IS_ERR(inode)) {
3964+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3965+ return -1;
3966+ }
3967+
3968+ /* the type of i_blocks depends upon CONFIG_LSF */
3969+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3970+ && sizeof(inode->i_blocks) != sizeof(u64));
3971+ if (wh) {
3972+ n = (void *)wh->d_name.name;
3973+ l = wh->d_name.len;
3974+ }
3975+
3976+ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
b752ccd1 3977+ " ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
1facf9fc 3978+ bindex,
3979+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3980+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3981+ i_size_read(inode), (unsigned long long)inode->i_blocks,
3982+ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3983+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
3984+ inode->i_state, inode->i_flags, inode->i_version,
3985+ inode->i_generation,
1facf9fc 3986+ l ? ", wh " : "", l, n);
3987+ return 0;
3988+}
3989+
3990+void au_dpri_inode(struct inode *inode)
3991+{
3992+ struct au_iinfo *iinfo;
3993+ aufs_bindex_t bindex;
3994+ int err;
3995+
3996+ err = do_pri_inode(-1, inode, NULL);
3997+ if (err || !au_test_aufs(inode->i_sb))
3998+ return;
3999+
4000+ iinfo = au_ii(inode);
4001+ if (!iinfo)
4002+ return;
4003+ dpri("i-1: bstart %d, bend %d, gen %d\n",
4004+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
4005+ if (iinfo->ii_bstart < 0)
4006+ return;
4007+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
4008+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
4009+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
4010+}
4011+
4012+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
4013+{
4014+ struct dentry *wh = NULL;
4015+
4016+ if (!dentry || IS_ERR(dentry)) {
4017+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
4018+ return -1;
4019+ }
4020+ /* do not call dget_parent() here */
027c5e7a 4021+ /* note: access d_xxx without d_lock */
1facf9fc 4022+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
4023+ bindex,
4024+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
4025+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
027c5e7a 4026+ dentry->d_count, dentry->d_flags);
1facf9fc 4027+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
4028+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
4029+ if (iinfo)
4030+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
4031+ }
4032+ do_pri_inode(bindex, dentry->d_inode, wh);
4033+ return 0;
4034+}
4035+
4036+void au_dpri_dentry(struct dentry *dentry)
4037+{
4038+ struct au_dinfo *dinfo;
4039+ aufs_bindex_t bindex;
4040+ int err;
4a4d8108 4041+ struct au_hdentry *hdp;
1facf9fc 4042+
4043+ err = do_pri_dentry(-1, dentry);
4044+ if (err || !au_test_aufs(dentry->d_sb))
4045+ return;
4046+
4047+ dinfo = au_di(dentry);
4048+ if (!dinfo)
4049+ return;
4050+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
4051+ dinfo->di_bstart, dinfo->di_bend,
4052+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
4053+ if (dinfo->di_bstart < 0)
4054+ return;
4a4d8108 4055+ hdp = dinfo->di_hdentry;
1facf9fc 4056+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 4057+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 4058+}
4059+
4060+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
4061+{
4062+ char a[32];
4063+
4064+ if (!file || IS_ERR(file)) {
4065+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
4066+ return -1;
4067+ }
4068+ a[0] = 0;
4069+ if (bindex < 0
4070+ && file->f_dentry
4071+ && au_test_aufs(file->f_dentry->d_sb)
4072+ && au_fi(file))
e49829fe
JR
4073+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
4074+ au_figen(file), !!au_fi(file)->fi_hvmop);
b752ccd1 4075+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 4076+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 4077+ file->f_version, file->f_pos, a);
1facf9fc 4078+ if (file->f_dentry)
4079+ do_pri_dentry(bindex, file->f_dentry);
4080+ return 0;
4081+}
4082+
4083+void au_dpri_file(struct file *file)
4084+{
4085+ struct au_finfo *finfo;
4a4d8108
AM
4086+ struct au_fidir *fidir;
4087+ struct au_hfile *hfile;
1facf9fc 4088+ aufs_bindex_t bindex;
4089+ int err;
4090+
4091+ err = do_pri_file(-1, file);
4092+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
4093+ return;
4094+
4095+ finfo = au_fi(file);
4096+ if (!finfo)
4097+ return;
4a4d8108 4098+ if (finfo->fi_btop < 0)
1facf9fc 4099+ return;
4a4d8108
AM
4100+ fidir = finfo->fi_hdir;
4101+ if (!fidir)
4102+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
4103+ else
e49829fe
JR
4104+ for (bindex = finfo->fi_btop;
4105+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
4106+ bindex++) {
4107+ hfile = fidir->fd_hfile + bindex;
4108+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
4109+ }
1facf9fc 4110+}
4111+
4112+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
4113+{
4114+ struct vfsmount *mnt;
4115+ struct super_block *sb;
4116+
4117+ if (!br || IS_ERR(br))
4118+ goto out;
4119+ mnt = br->br_mnt;
4120+ if (!mnt || IS_ERR(mnt))
4121+ goto out;
4122+ sb = mnt->mnt_sb;
4123+ if (!sb || IS_ERR(sb))
4124+ goto out;
4125+
4126+ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
b752ccd1 4127+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 4128+ "xino %d\n",
4129+ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
4130+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 4131+ sb->s_flags, sb->s_count,
1facf9fc 4132+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
4133+ return 0;
4134+
4f0767ce 4135+out:
1facf9fc 4136+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
4137+ return -1;
4138+}
4139+
4140+void au_dpri_sb(struct super_block *sb)
4141+{
4142+ struct au_sbinfo *sbinfo;
4143+ aufs_bindex_t bindex;
4144+ int err;
4145+ /* to reuduce stack size */
4146+ struct {
4147+ struct vfsmount mnt;
4148+ struct au_branch fake;
4149+ } *a;
4150+
4151+ /* this function can be called from magic sysrq */
4152+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
4153+ if (unlikely(!a)) {
4154+ dpri("no memory\n");
4155+ return;
4156+ }
4157+
4158+ a->mnt.mnt_sb = sb;
4159+ a->fake.br_perm = 0;
4160+ a->fake.br_mnt = &a->mnt;
4161+ a->fake.br_xino.xi_file = NULL;
4162+ atomic_set(&a->fake.br_count, 0);
4163+ smp_mb(); /* atomic_set */
4164+ err = do_pri_br(-1, &a->fake);
4165+ kfree(a);
4166+ dpri("dev 0x%x\n", sb->s_dev);
4167+ if (err || !au_test_aufs(sb))
4168+ return;
4169+
4170+ sbinfo = au_sbi(sb);
4171+ if (!sbinfo)
4172+ return;
4173+ dpri("nw %d, gen %u, kobj %d\n",
4174+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
4175+ atomic_read(&sbinfo->si_kobj.kref.refcount));
4176+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
4177+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
4178+}
4179+
4180+/* ---------------------------------------------------------------------- */
4181+
4182+void au_dbg_sleep_jiffy(int jiffy)
4183+{
4184+ while (jiffy)
4185+ jiffy = schedule_timeout_uninterruptible(jiffy);
4186+}
4187+
4188+void au_dbg_iattr(struct iattr *ia)
4189+{
4190+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
4191+ dpri(#name "\n")
4192+ AuBit(MODE);
4193+ AuBit(UID);
4194+ AuBit(GID);
4195+ AuBit(SIZE);
4196+ AuBit(ATIME);
4197+ AuBit(MTIME);
4198+ AuBit(CTIME);
4199+ AuBit(ATIME_SET);
4200+ AuBit(MTIME_SET);
4201+ AuBit(FORCE);
4202+ AuBit(ATTR_FLAG);
4203+ AuBit(KILL_SUID);
4204+ AuBit(KILL_SGID);
4205+ AuBit(FILE);
4206+ AuBit(KILL_PRIV);
4207+ AuBit(OPEN);
4208+ AuBit(TIMES_SET);
4209+#undef AuBit
4210+ dpri("ia_file %p\n", ia->ia_file);
4211+}
4212+
4213+/* ---------------------------------------------------------------------- */
4214+
027c5e7a
AM
4215+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
4216+{
4217+ struct inode *h_inode, *inode = dentry->d_inode;
4218+ struct dentry *h_dentry;
4219+ aufs_bindex_t bindex, bend, bi;
4220+
4221+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
4222+ return;
4223+
4224+ bend = au_dbend(dentry);
4225+ bi = au_ibend(inode);
4226+ if (bi < bend)
4227+ bend = bi;
4228+ bindex = au_dbstart(dentry);
4229+ bi = au_ibstart(inode);
4230+ if (bi > bindex)
4231+ bindex = bi;
4232+
4233+ for (; bindex <= bend; bindex++) {
4234+ h_dentry = au_h_dptr(dentry, bindex);
4235+ if (!h_dentry)
4236+ continue;
4237+ h_inode = au_h_iptr(inode, bindex);
4238+ if (unlikely(h_inode != h_dentry->d_inode)) {
4239+ int old = au_debug_test();
4240+ if (!old)
4241+ au_debug(1);
4242+ AuDbg("b%d, %s:%d\n", bindex, func, line);
4243+ AuDbgDentry(dentry);
4244+ AuDbgInode(inode);
4245+ if (!old)
4246+ au_debug(0);
4247+ BUG();
4248+ }
4249+ }
4250+}
4251+
1facf9fc 4252+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
4253+{
4254+ struct dentry *parent;
4255+
4256+ parent = dget_parent(dentry);
027c5e7a
AM
4257+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
4258+ AuDebugOn(IS_ROOT(dentry));
4259+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 4260+ dput(parent);
4261+}
4262+
4263+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
4264+{
4265+ struct dentry *parent;
027c5e7a 4266+ struct inode *inode;
1facf9fc 4267+
4268+ parent = dget_parent(dentry);
027c5e7a
AM
4269+ inode = dentry->d_inode;
4270+ AuDebugOn(inode && S_ISDIR(dentry->d_inode->i_mode));
4271+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 4272+ dput(parent);
4273+}
4274+
4275+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
4276+{
4277+ int err, i, j;
4278+ struct au_dcsub_pages dpages;
4279+ struct au_dpage *dpage;
4280+ struct dentry **dentries;
4281+
4282+ err = au_dpages_init(&dpages, GFP_NOFS);
4283+ AuDebugOn(err);
027c5e7a 4284+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 4285+ AuDebugOn(err);
4286+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
4287+ dpage = dpages.dpages + i;
4288+ dentries = dpage->dentries;
4289+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 4290+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 4291+ }
4292+ au_dpages_free(&dpages);
4293+}
4294+
1facf9fc 4295+void au_dbg_verify_kthread(void)
4296+{
7f207e10 4297+ if (current->flags & PF_WQ_WORKER) {
1facf9fc 4298+ au_dbg_blocked();
7f207e10 4299+ WARN_ON(1);
1facf9fc 4300+ }
4301+}
4302+
4303+/* ---------------------------------------------------------------------- */
4304+
4305+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
4306+{
4307+#ifdef AuForceNoPlink
4308+ au_opt_clr(sbinfo->si_mntflags, PLINK);
4309+#endif
4310+#ifdef AuForceNoXino
4311+ au_opt_clr(sbinfo->si_mntflags, XINO);
4312+#endif
4313+#ifdef AuForceNoRefrof
4314+ au_opt_clr(sbinfo->si_mntflags, REFROF);
4315+#endif
4a4d8108
AM
4316+#ifdef AuForceHnotify
4317+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 4318+#endif
1308ab2a 4319+#ifdef AuForceRd0
4320+ sbinfo->si_rdblk = 0;
4321+ sbinfo->si_rdhash = 0;
4322+#endif
1facf9fc 4323+}
4324+
4325+int __init au_debug_init(void)
4326+{
4327+ aufs_bindex_t bindex;
4328+ struct au_vdir_destr destr;
4329+
4330+ bindex = -1;
4331+ AuDebugOn(bindex >= 0);
4332+
4333+ destr.len = -1;
4334+ AuDebugOn(destr.len < NAME_MAX);
4335+
4336+#ifdef CONFIG_4KSTACKS
4a4d8108 4337+ pr_warning("CONFIG_4KSTACKS is defined.\n");
1facf9fc 4338+#endif
4339+
4340+#ifdef AuForceNoBrs
4341+ sysaufs_brs = 0;
4342+#endif
4343+
4344+ return 0;
4345+}
7f207e10
AM
4346diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
4347--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
4348+++ linux/fs/aufs/debug.h 2011-03-21 20:22:06.853935428 +0100
4349@@ -0,0 +1,245 @@
1facf9fc 4350+/*
027c5e7a 4351+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 4352+ *
4353+ * This program, aufs is free software; you can redistribute it and/or modify
4354+ * it under the terms of the GNU General Public License as published by
4355+ * the Free Software Foundation; either version 2 of the License, or
4356+ * (at your option) any later version.
dece6358
AM
4357+ *
4358+ * This program is distributed in the hope that it will be useful,
4359+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4360+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4361+ * GNU General Public License for more details.
4362+ *
4363+ * You should have received a copy of the GNU General Public License
4364+ * along with this program; if not, write to the Free Software
4365+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4366+ */
4367+
4368+/*
4369+ * debug print functions
4370+ */
4371+
4372+#ifndef __AUFS_DEBUG_H__
4373+#define __AUFS_DEBUG_H__
4374+
4375+#ifdef __KERNEL__
4376+
1308ab2a 4377+#include <asm/system.h>
dece6358 4378+#include <linux/bug.h>
7f207e10 4379+/* #include <linux/err.h> */
1308ab2a 4380+#include <linux/init.h>
4a4d8108
AM
4381+#include <linux/module.h>
4382+#include <linux/kallsyms.h>
7f207e10 4383+/* #include <linux/kernel.h> */
1facf9fc 4384+#include <linux/delay.h>
7f207e10 4385+/* #include <linux/kd.h> */
1facf9fc 4386+#include <linux/sysrq.h>
4387+#include <linux/aufs_type.h>
4388+
4a4d8108
AM
4389+#include <asm/system.h>
4390+
1facf9fc 4391+#ifdef CONFIG_AUFS_DEBUG
4392+#define AuDebugOn(a) BUG_ON(a)
4393+
4394+/* module parameter */
4395+extern int aufs_debug;
4396+static inline void au_debug(int n)
4397+{
4398+ aufs_debug = n;
4399+ smp_mb();
4400+}
4401+
4402+static inline int au_debug_test(void)
4403+{
4404+ return aufs_debug;
4405+}
4406+#else
4407+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
4408+AuStubVoid(au_debug, int n)
4409+AuStubInt0(au_debug_test, void)
1facf9fc 4410+#endif /* CONFIG_AUFS_DEBUG */
4411+
4412+/* ---------------------------------------------------------------------- */
4413+
4414+/* debug print */
4415+
4a4d8108 4416+#define AuDbg(fmt, ...) do { \
1facf9fc 4417+ if (au_debug_test()) \
4a4d8108 4418+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 4419+} while (0)
4a4d8108
AM
4420+#define AuLabel(l) AuDbg(#l "\n")
4421+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
4422+#define AuWarn1(fmt, ...) do { \
1facf9fc 4423+ static unsigned char _c; \
4424+ if (!_c++) \
4a4d8108 4425+ pr_warning(fmt, ##__VA_ARGS__); \
1facf9fc 4426+} while (0)
4427+
4a4d8108 4428+#define AuErr1(fmt, ...) do { \
1facf9fc 4429+ static unsigned char _c; \
4430+ if (!_c++) \
4a4d8108 4431+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 4432+} while (0)
4433+
4a4d8108 4434+#define AuIOErr1(fmt, ...) do { \
1facf9fc 4435+ static unsigned char _c; \
4436+ if (!_c++) \
4a4d8108 4437+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 4438+} while (0)
4439+
4440+#define AuUnsupportMsg "This operation is not supported." \
4441+ " Please report this application to aufs-users ML."
4a4d8108
AM
4442+#define AuUnsupport(fmt, ...) do { \
4443+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 4444+ dump_stack(); \
4445+} while (0)
4446+
4447+#define AuTraceErr(e) do { \
4448+ if (unlikely((e) < 0)) \
4449+ AuDbg("err %d\n", (int)(e)); \
4450+} while (0)
4451+
4452+#define AuTraceErrPtr(p) do { \
4453+ if (IS_ERR(p)) \
4454+ AuDbg("err %ld\n", PTR_ERR(p)); \
4455+} while (0)
4456+
4457+/* dirty macros for debug print, use with "%.*s" and caution */
4458+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
4459+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
4460+
4461+/* ---------------------------------------------------------------------- */
4462+
4463+struct au_sbinfo;
4464+struct au_finfo;
dece6358 4465+struct dentry;
1facf9fc 4466+#ifdef CONFIG_AUFS_DEBUG
4467+extern char *au_plevel;
4468+struct au_nhash;
4469+void au_dpri_whlist(struct au_nhash *whlist);
4470+struct au_vdir;
4471+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 4472+struct inode;
1facf9fc 4473+void au_dpri_inode(struct inode *inode);
4474+void au_dpri_dentry(struct dentry *dentry);
dece6358 4475+struct file;
1facf9fc 4476+void au_dpri_file(struct file *filp);
dece6358 4477+struct super_block;
1facf9fc 4478+void au_dpri_sb(struct super_block *sb);
4479+
4480+void au_dbg_sleep_jiffy(int jiffy);
dece6358 4481+struct iattr;
1facf9fc 4482+void au_dbg_iattr(struct iattr *ia);
4483+
027c5e7a
AM
4484+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
4485+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 4486+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
4487+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
4488+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 4489+void au_dbg_verify_kthread(void);
4490+
4491+int __init au_debug_init(void);
4492+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
4493+#define AuDbgWhlist(w) do { \
4494+ AuDbg(#w "\n"); \
4495+ au_dpri_whlist(w); \
4496+} while (0)
4497+
4498+#define AuDbgVdir(v) do { \
4499+ AuDbg(#v "\n"); \
4500+ au_dpri_vdir(v); \
4501+} while (0)
4502+
4503+#define AuDbgInode(i) do { \
4504+ AuDbg(#i "\n"); \
4505+ au_dpri_inode(i); \
4506+} while (0)
4507+
4508+#define AuDbgDentry(d) do { \
4509+ AuDbg(#d "\n"); \
4510+ au_dpri_dentry(d); \
4511+} while (0)
4512+
4513+#define AuDbgFile(f) do { \
4514+ AuDbg(#f "\n"); \
4515+ au_dpri_file(f); \
4516+} while (0)
4517+
4518+#define AuDbgSb(sb) do { \
4519+ AuDbg(#sb "\n"); \
4520+ au_dpri_sb(sb); \
4521+} while (0)
4522+
4523+#define AuDbgSleep(sec) do { \
4524+ AuDbg("sleep %d sec\n", sec); \
4525+ ssleep(sec); \
4526+} while (0)
4527+
4528+#define AuDbgSleepJiffy(jiffy) do { \
4529+ AuDbg("sleep %d jiffies\n", jiffy); \
4530+ au_dbg_sleep_jiffy(jiffy); \
4531+} while (0)
4532+
4533+#define AuDbgIAttr(ia) do { \
4534+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
4535+ au_dbg_iattr(ia); \
4536+} while (0)
4a4d8108
AM
4537+
4538+#define AuDbgSym(addr) do { \
4539+ char sym[KSYM_SYMBOL_LEN]; \
4540+ sprint_symbol(sym, (unsigned long)addr); \
4541+ AuDbg("%s\n", sym); \
4542+} while (0)
4543+
4544+#define AuInfoSym(addr) do { \
4545+ char sym[KSYM_SYMBOL_LEN]; \
4546+ sprint_symbol(sym, (unsigned long)addr); \
4547+ AuInfo("%s\n", sym); \
4548+} while (0)
1facf9fc 4549+#else
027c5e7a 4550+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
4551+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
4552+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
4553+ unsigned int sigen)
4554+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
4555+AuStubVoid(au_dbg_verify_kthread, void)
4556+AuStubInt0(__init au_debug_init, void)
4557+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 4558+
1facf9fc 4559+#define AuDbgWhlist(w) do {} while (0)
4560+#define AuDbgVdir(v) do {} while (0)
4561+#define AuDbgInode(i) do {} while (0)
4562+#define AuDbgDentry(d) do {} while (0)
4563+#define AuDbgFile(f) do {} while (0)
4564+#define AuDbgSb(sb) do {} while (0)
4565+#define AuDbgSleep(sec) do {} while (0)
4566+#define AuDbgSleepJiffy(jiffy) do {} while (0)
4567+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
4568+#define AuDbgSym(addr) do {} while (0)
4569+#define AuInfoSym(addr) do {} while (0)
1facf9fc 4570+#endif /* CONFIG_AUFS_DEBUG */
4571+
4572+/* ---------------------------------------------------------------------- */
4573+
4574+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
4575+int __init au_sysrq_init(void);
4576+void au_sysrq_fin(void);
4577+
4578+#ifdef CONFIG_HW_CONSOLE
4579+#define au_dbg_blocked() do { \
4580+ WARN_ON(1); \
0c5527e5 4581+ handle_sysrq('w'); \
1facf9fc 4582+} while (0)
4583+#else
4a4d8108 4584+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4585+#endif
4586+
4587+#else
4a4d8108
AM
4588+AuStubInt0(__init au_sysrq_init, void)
4589+AuStubVoid(au_sysrq_fin, void)
4590+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4591+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
4592+
4593+#endif /* __KERNEL__ */
4594+#endif /* __AUFS_DEBUG_H__ */
7f207e10
AM
4595diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
4596--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
4597+++ linux/fs/aufs/dentry.c 2011-03-21 20:22:06.853935428 +0100
4598@@ -0,0 +1,1140 @@
1facf9fc 4599+/*
027c5e7a 4600+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 4601+ *
4602+ * This program, aufs is free software; you can redistribute it and/or modify
4603+ * it under the terms of the GNU General Public License as published by
4604+ * the Free Software Foundation; either version 2 of the License, or
4605+ * (at your option) any later version.
dece6358
AM
4606+ *
4607+ * This program is distributed in the hope that it will be useful,
4608+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4609+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4610+ * GNU General Public License for more details.
4611+ *
4612+ * You should have received a copy of the GNU General Public License
4613+ * along with this program; if not, write to the Free Software
4614+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4615+ */
4616+
4617+/*
4618+ * lookup and dentry operations
4619+ */
4620+
dece6358 4621+#include <linux/namei.h>
1facf9fc 4622+#include "aufs.h"
4623+
4624+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
4625+{
4626+ if (nd) {
4627+ *h_nd = *nd;
4628+
4629+ /*
4630+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
4631+ * due to whiteout and branch permission.
4632+ */
4633+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
b752ccd1 4634+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
1facf9fc 4635+ /* unnecessary? */
4636+ h_nd->intent.open.file = NULL;
4637+ } else
4638+ memset(h_nd, 0, sizeof(*h_nd));
4639+}
4640+
4641+struct au_lkup_one_args {
4642+ struct dentry **errp;
4643+ struct qstr *name;
4644+ struct dentry *h_parent;
4645+ struct au_branch *br;
4646+ struct nameidata *nd;
4647+};
4648+
4649+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
4650+ struct au_branch *br, struct nameidata *nd)
4651+{
4652+ struct dentry *h_dentry;
4653+ int err;
4654+ struct nameidata h_nd;
4655+
4656+ if (au_test_fs_null_nd(h_parent->d_sb))
4657+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
4658+
4659+ au_h_nd(&h_nd, nd);
4660+ h_nd.path.dentry = h_parent;
4661+ h_nd.path.mnt = br->br_mnt;
4662+
4663+ err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
4664+ h_dentry = ERR_PTR(err);
4665+ if (!err) {
4666+ path_get(&h_nd.path);
4667+ h_dentry = vfsub_lookup_hash(&h_nd);
4668+ path_put(&h_nd.path);
4669+ }
4670+
4a4d8108 4671+ AuTraceErrPtr(h_dentry);
1facf9fc 4672+ return h_dentry;
4673+}
4674+
4675+static void au_call_lkup_one(void *args)
4676+{
4677+ struct au_lkup_one_args *a = args;
4678+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
4679+}
4680+
4681+#define AuLkup_ALLOW_NEG 1
4682+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
7f207e10
AM
4683+#define au_fset_lkup(flags, name) \
4684+ do { (flags) |= AuLkup_##name; } while (0)
4685+#define au_fclr_lkup(flags, name) \
4686+ do { (flags) &= ~AuLkup_##name; } while (0)
1facf9fc 4687+
4688+struct au_do_lookup_args {
4689+ unsigned int flags;
4690+ mode_t type;
4691+ struct nameidata *nd;
4692+};
4693+
4694+/*
4695+ * returns positive/negative dentry, NULL or an error.
4696+ * NULL means whiteout-ed or not-found.
4697+ */
4698+static struct dentry*
4699+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
4700+ aufs_bindex_t bindex, struct qstr *wh_name,
4701+ struct au_do_lookup_args *args)
4702+{
4703+ struct dentry *h_dentry;
4704+ struct inode *h_inode, *inode;
1facf9fc 4705+ struct au_branch *br;
4706+ int wh_found, opq;
4707+ unsigned char wh_able;
4708+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
4709+
1facf9fc 4710+ wh_found = 0;
4711+ br = au_sbr(dentry->d_sb, bindex);
4712+ wh_able = !!au_br_whable(br->br_perm);
4713+ if (wh_able)
4714+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
4715+ h_dentry = ERR_PTR(wh_found);
4716+ if (!wh_found)
4717+ goto real_lookup;
4718+ if (unlikely(wh_found < 0))
4719+ goto out;
4720+
4721+ /* We found a whiteout */
4722+ /* au_set_dbend(dentry, bindex); */
4723+ au_set_dbwh(dentry, bindex);
4724+ if (!allow_neg)
4725+ return NULL; /* success */
4726+
4f0767ce 4727+real_lookup:
4a4d8108 4728+ h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
1facf9fc 4729+ if (IS_ERR(h_dentry))
4730+ goto out;
4731+
4732+ h_inode = h_dentry->d_inode;
4733+ if (!h_inode) {
4734+ if (!allow_neg)
4735+ goto out_neg;
4736+ } else if (wh_found
4737+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
4738+ goto out_neg;
4739+
4740+ if (au_dbend(dentry) <= bindex)
4741+ au_set_dbend(dentry, bindex);
4742+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4743+ au_set_dbstart(dentry, bindex);
4744+ au_set_h_dptr(dentry, bindex, h_dentry);
4745+
4746+ inode = dentry->d_inode;
4747+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4748+ || (inode && !S_ISDIR(inode->i_mode)))
4749+ goto out; /* success */
4750+
4751+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4752+ opq = au_diropq_test(h_dentry, br);
4753+ mutex_unlock(&h_inode->i_mutex);
4754+ if (opq > 0)
4755+ au_set_dbdiropq(dentry, bindex);
4756+ else if (unlikely(opq < 0)) {
4757+ au_set_h_dptr(dentry, bindex, NULL);
4758+ h_dentry = ERR_PTR(opq);
4759+ }
4760+ goto out;
4761+
4f0767ce 4762+out_neg:
1facf9fc 4763+ dput(h_dentry);
4764+ h_dentry = NULL;
4f0767ce 4765+out:
1facf9fc 4766+ return h_dentry;
4767+}
4768+
dece6358
AM
4769+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
4770+{
4771+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
4772+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
4773+ return -EPERM;
4774+ return 0;
4775+}
4776+
1facf9fc 4777+/*
4778+ * returns the number of lower positive dentries,
4779+ * otherwise an error.
4780+ * can be called at unlinking with @type is zero.
4781+ */
4782+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4783+ struct nameidata *nd)
4784+{
4785+ int npositive, err;
4786+ aufs_bindex_t bindex, btail, bdiropq;
4787+ unsigned char isdir;
4788+ struct qstr whname;
4789+ struct au_do_lookup_args args = {
4790+ .flags = 0,
4791+ .type = type,
4792+ .nd = nd
4793+ };
4794+ const struct qstr *name = &dentry->d_name;
4795+ struct dentry *parent;
4796+ struct inode *inode;
4797+
dece6358
AM
4798+ err = au_test_shwh(dentry->d_sb, name);
4799+ if (unlikely(err))
1facf9fc 4800+ goto out;
4801+
4802+ err = au_wh_name_alloc(&whname, name);
4803+ if (unlikely(err))
4804+ goto out;
4805+
4806+ inode = dentry->d_inode;
4807+ isdir = !!(inode && S_ISDIR(inode->i_mode));
4808+ if (!type)
4809+ au_fset_lkup(args.flags, ALLOW_NEG);
4810+
4811+ npositive = 0;
4a4d8108 4812+ parent = dget_parent(dentry);
1facf9fc 4813+ btail = au_dbtaildir(parent);
4814+ for (bindex = bstart; bindex <= btail; bindex++) {
4815+ struct dentry *h_parent, *h_dentry;
4816+ struct inode *h_inode, *h_dir;
4817+
4818+ h_dentry = au_h_dptr(dentry, bindex);
4819+ if (h_dentry) {
4820+ if (h_dentry->d_inode)
4821+ npositive++;
4822+ if (type != S_IFDIR)
4823+ break;
4824+ continue;
4825+ }
4826+ h_parent = au_h_dptr(parent, bindex);
4827+ if (!h_parent)
4828+ continue;
4829+ h_dir = h_parent->d_inode;
4830+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
4831+ continue;
4832+
4833+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4834+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4835+ &args);
4836+ mutex_unlock(&h_dir->i_mutex);
4837+ err = PTR_ERR(h_dentry);
4838+ if (IS_ERR(h_dentry))
4a4d8108 4839+ goto out_parent;
1facf9fc 4840+ au_fclr_lkup(args.flags, ALLOW_NEG);
4841+
4842+ if (au_dbwh(dentry) >= 0)
4843+ break;
4844+ if (!h_dentry)
4845+ continue;
4846+ h_inode = h_dentry->d_inode;
4847+ if (!h_inode)
4848+ continue;
4849+ npositive++;
4850+ if (!args.type)
4851+ args.type = h_inode->i_mode & S_IFMT;
4852+ if (args.type != S_IFDIR)
4853+ break;
4854+ else if (isdir) {
4855+ /* the type of lower may be different */
4856+ bdiropq = au_dbdiropq(dentry);
4857+ if (bdiropq >= 0 && bdiropq <= bindex)
4858+ break;
4859+ }
4860+ }
4861+
4862+ if (npositive) {
4863+ AuLabel(positive);
4864+ au_update_dbstart(dentry);
4865+ }
4866+ err = npositive;
4867+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
027c5e7a 4868+ && au_dbstart(dentry) < 0)) {
1facf9fc 4869+ err = -EIO;
027c5e7a
AM
4870+ AuIOErr("both of real entry and whiteout found, %.*s, err %d\n",
4871+ AuDLNPair(dentry), err);
4872+ }
1facf9fc 4873+
4f0767ce 4874+out_parent:
4a4d8108 4875+ dput(parent);
1facf9fc 4876+ kfree(whname.name);
4f0767ce 4877+out:
1facf9fc 4878+ return err;
4879+}
4880+
4881+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4882+ struct au_branch *br)
4883+{
4884+ struct dentry *dentry;
4885+ int wkq_err;
4886+
4887+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
4888+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
4889+ else {
4890+ struct au_lkup_one_args args = {
4891+ .errp = &dentry,
4892+ .name = name,
4893+ .h_parent = parent,
4894+ .br = br,
4895+ .nd = NULL
4896+ };
4897+
4898+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
4899+ if (unlikely(wkq_err))
4900+ dentry = ERR_PTR(wkq_err);
4901+ }
4902+
4903+ return dentry;
4904+}
4905+
4906+/*
4907+ * lookup @dentry on @bindex which should be negative.
4908+ */
4909+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4910+{
4911+ int err;
4912+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 4913+
1facf9fc 4914+ parent = dget_parent(dentry);
4915+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 4916+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 4917+ au_sbr(dentry->d_sb, bindex));
4918+ err = PTR_ERR(h_dentry);
4919+ if (IS_ERR(h_dentry))
4920+ goto out;
4921+ if (unlikely(h_dentry->d_inode)) {
4922+ err = -EIO;
027c5e7a
AM
4923+ AuIOErr("%.*s should be negative on b%d.\n",
4924+ AuDLNPair(h_dentry), bindex);
1facf9fc 4925+ dput(h_dentry);
4926+ goto out;
4927+ }
4928+
4a4d8108 4929+ err = 0;
1facf9fc 4930+ if (bindex < au_dbstart(dentry))
4931+ au_set_dbstart(dentry, bindex);
4932+ if (au_dbend(dentry) < bindex)
4933+ au_set_dbend(dentry, bindex);
4934+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 4935+
4f0767ce 4936+out:
1facf9fc 4937+ dput(parent);
4938+ return err;
4939+}
4940+
4941+/* ---------------------------------------------------------------------- */
4942+
4943+/* subset of struct inode */
4944+struct au_iattr {
4945+ unsigned long i_ino;
4946+ /* unsigned int i_nlink; */
4947+ uid_t i_uid;
4948+ gid_t i_gid;
4949+ u64 i_version;
4950+/*
4951+ loff_t i_size;
4952+ blkcnt_t i_blocks;
4953+*/
4954+ umode_t i_mode;
4955+};
4956+
4957+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
4958+{
4959+ ia->i_ino = h_inode->i_ino;
4960+ /* ia->i_nlink = h_inode->i_nlink; */
4961+ ia->i_uid = h_inode->i_uid;
4962+ ia->i_gid = h_inode->i_gid;
4963+ ia->i_version = h_inode->i_version;
4964+/*
4965+ ia->i_size = h_inode->i_size;
4966+ ia->i_blocks = h_inode->i_blocks;
4967+*/
4968+ ia->i_mode = (h_inode->i_mode & S_IFMT);
4969+}
4970+
4971+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
4972+{
4973+ return ia->i_ino != h_inode->i_ino
4974+ /* || ia->i_nlink != h_inode->i_nlink */
4975+ || ia->i_uid != h_inode->i_uid
4976+ || ia->i_gid != h_inode->i_gid
4977+ || ia->i_version != h_inode->i_version
4978+/*
4979+ || ia->i_size != h_inode->i_size
4980+ || ia->i_blocks != h_inode->i_blocks
4981+*/
4982+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
4983+}
4984+
4985+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
4986+ struct au_branch *br)
4987+{
4988+ int err;
4989+ struct au_iattr ia;
4990+ struct inode *h_inode;
4991+ struct dentry *h_d;
4992+ struct super_block *h_sb;
4993+
4994+ err = 0;
4995+ memset(&ia, -1, sizeof(ia));
4996+ h_sb = h_dentry->d_sb;
4997+ h_inode = h_dentry->d_inode;
4998+ if (h_inode)
4999+ au_iattr_save(&ia, h_inode);
5000+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
5001+ /* nfs d_revalidate may return 0 for negative dentry */
5002+ /* fuse d_revalidate always return 0 for negative dentry */
5003+ goto out;
5004+
5005+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
5006+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
5007+ err = PTR_ERR(h_d);
5008+ if (IS_ERR(h_d))
5009+ goto out;
5010+
5011+ err = 0;
5012+ if (unlikely(h_d != h_dentry
5013+ || h_d->d_inode != h_inode
5014+ || (h_inode && au_iattr_test(&ia, h_inode))))
5015+ err = au_busy_or_stale();
5016+ dput(h_d);
5017+
4f0767ce 5018+out:
1facf9fc 5019+ AuTraceErr(err);
5020+ return err;
5021+}
5022+
5023+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
5024+ struct dentry *h_parent, struct au_branch *br)
5025+{
5026+ int err;
5027+
5028+ err = 0;
027c5e7a
AM
5029+ if (udba == AuOpt_UDBA_REVAL
5030+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 5031+ IMustLock(h_dir);
5032+ err = (h_dentry->d_parent->d_inode != h_dir);
027c5e7a 5033+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 5034+ err = au_h_verify_dentry(h_dentry, h_parent, br);
5035+
5036+ return err;
5037+}
5038+
5039+/* ---------------------------------------------------------------------- */
5040+
027c5e7a 5041+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 5042+{
027c5e7a 5043+ int err;
1facf9fc 5044+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
027c5e7a
AM
5045+ struct au_hdentry tmp, *p, *q;
5046+ struct au_dinfo *dinfo;
5047+ struct super_block *sb;
1facf9fc 5048+
027c5e7a 5049+ DiMustWriteLock(dentry);
1308ab2a 5050+
027c5e7a
AM
5051+ sb = dentry->d_sb;
5052+ dinfo = au_di(dentry);
1facf9fc 5053+ bend = dinfo->di_bend;
5054+ bwh = dinfo->di_bwh;
5055+ bdiropq = dinfo->di_bdiropq;
027c5e7a 5056+ p = dinfo->di_hdentry + dinfo->di_bstart;
1facf9fc 5057+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
027c5e7a 5058+ if (!p->hd_dentry)
1facf9fc 5059+ continue;
5060+
027c5e7a
AM
5061+ new_bindex = au_br_index(sb, p->hd_id);
5062+ if (new_bindex == bindex)
1facf9fc 5063+ continue;
1facf9fc 5064+
1facf9fc 5065+ if (dinfo->di_bwh == bindex)
5066+ bwh = new_bindex;
5067+ if (dinfo->di_bdiropq == bindex)
5068+ bdiropq = new_bindex;
5069+ if (new_bindex < 0) {
5070+ au_hdput(p);
5071+ p->hd_dentry = NULL;
5072+ continue;
5073+ }
5074+
5075+ /* swap two lower dentries, and loop again */
5076+ q = dinfo->di_hdentry + new_bindex;
5077+ tmp = *q;
5078+ *q = *p;
5079+ *p = tmp;
5080+ if (tmp.hd_dentry) {
5081+ bindex--;
5082+ p--;
5083+ }
5084+ }
5085+
1facf9fc 5086+ dinfo->di_bwh = -1;
5087+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
5088+ dinfo->di_bwh = bwh;
5089+
5090+ dinfo->di_bdiropq = -1;
5091+ if (bdiropq >= 0
5092+ && bdiropq <= au_sbend(sb)
5093+ && au_sbr_whable(sb, bdiropq))
5094+ dinfo->di_bdiropq = bdiropq;
5095+
027c5e7a
AM
5096+ err = -EIO;
5097+ dinfo->di_bstart = -1;
5098+ dinfo->di_bend = -1;
1facf9fc 5099+ bend = au_dbend(parent);
5100+ p = dinfo->di_hdentry;
5101+ for (bindex = 0; bindex <= bend; bindex++, p++)
5102+ if (p->hd_dentry) {
5103+ dinfo->di_bstart = bindex;
5104+ break;
5105+ }
5106+
027c5e7a
AM
5107+ if (dinfo->di_bstart >= 0) {
5108+ p = dinfo->di_hdentry + bend;
5109+ for (bindex = bend; bindex >= 0; bindex--, p--)
5110+ if (p->hd_dentry) {
5111+ dinfo->di_bend = bindex;
5112+ err = 0;
5113+ break;
5114+ }
5115+ }
5116+
5117+ return err;
1facf9fc 5118+}
5119+
027c5e7a 5120+static void au_do_hide(struct dentry *dentry)
1facf9fc 5121+{
027c5e7a 5122+ struct inode *inode;
1facf9fc 5123+
027c5e7a
AM
5124+ inode = dentry->d_inode;
5125+ if (inode) {
5126+ if (!S_ISDIR(inode->i_mode)) {
5127+ if (inode->i_nlink && !d_unhashed(dentry))
5128+ drop_nlink(inode);
5129+ } else {
5130+ clear_nlink(inode);
5131+ /* stop next lookup */
5132+ inode->i_flags |= S_DEAD;
5133+ }
5134+ smp_mb(); /* necessary? */
5135+ }
5136+ d_drop(dentry);
5137+}
1308ab2a 5138+
027c5e7a
AM
5139+static int au_hide_children(struct dentry *parent)
5140+{
5141+ int err, i, j, ndentry;
5142+ struct au_dcsub_pages dpages;
5143+ struct au_dpage *dpage;
5144+ struct dentry *dentry;
1facf9fc 5145+
027c5e7a 5146+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 5147+ if (unlikely(err))
5148+ goto out;
027c5e7a
AM
5149+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
5150+ if (unlikely(err))
5151+ goto out_dpages;
1facf9fc 5152+
027c5e7a
AM
5153+ /* in reverse order */
5154+ for (i = dpages.ndpage - 1; i >= 0; i--) {
5155+ dpage = dpages.dpages + i;
5156+ ndentry = dpage->ndentry;
5157+ for (j = ndentry - 1; j >= 0; j--) {
5158+ dentry = dpage->dentries[j];
5159+ if (dentry != parent)
5160+ au_do_hide(dentry);
5161+ }
5162+ }
1facf9fc 5163+
027c5e7a
AM
5164+out_dpages:
5165+ au_dpages_free(&dpages);
4f0767ce 5166+out:
027c5e7a 5167+ return err;
1facf9fc 5168+}
5169+
027c5e7a 5170+static void au_hide(struct dentry *dentry)
1facf9fc 5171+{
027c5e7a
AM
5172+ int err;
5173+ struct inode *inode;
1facf9fc 5174+
027c5e7a
AM
5175+ AuDbgDentry(dentry);
5176+ inode = dentry->d_inode;
5177+ if (inode && S_ISDIR(inode->i_mode)) {
5178+ /* shrink_dcache_parent(dentry); */
5179+ err = au_hide_children(dentry);
5180+ if (unlikely(err))
5181+ AuIOErr("%.*s, failed hiding children, ignored %d\n",
5182+ AuDLNPair(dentry), err);
5183+ }
5184+ au_do_hide(dentry);
5185+}
1facf9fc 5186+
027c5e7a
AM
5187+/*
5188+ * By adding a dirty branch, a cached dentry may be affected in various ways.
5189+ *
5190+ * a dirty branch is added
5191+ * - on the top of layers
5192+ * - in the middle of layers
5193+ * - to the bottom of layers
5194+ *
5195+ * on the added branch there exists
5196+ * - a whiteout
5197+ * - a diropq
5198+ * - a same named entry
5199+ * + exist
5200+ * * negative --> positive
5201+ * * positive --> positive
5202+ * - type is unchanged
5203+ * - type is changed
5204+ * + doesn't exist
5205+ * * negative --> negative
5206+ * * positive --> negative (rejected by au_br_del() for non-dir case)
5207+ * - none
5208+ */
5209+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
5210+ struct au_dinfo *tmp)
5211+{
5212+ int err;
5213+ aufs_bindex_t bindex, bend;
5214+ struct {
5215+ struct dentry *dentry;
5216+ struct inode *inode;
5217+ mode_t mode;
5218+ } orig_h, tmp_h;
5219+ struct au_hdentry *hd;
5220+ struct inode *inode, *h_inode;
5221+ struct dentry *h_dentry;
5222+
5223+ err = 0;
5224+ AuDebugOn(dinfo->di_bstart < 0);
5225+ orig_h.dentry = dinfo->di_hdentry[dinfo->di_bstart].hd_dentry;
5226+ orig_h.inode = orig_h.dentry->d_inode;
5227+ orig_h.mode = 0;
5228+ if (orig_h.inode)
5229+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
5230+ memset(&tmp_h, 0, sizeof(tmp_h));
5231+ if (tmp->di_bstart >= 0) {
5232+ tmp_h.dentry = tmp->di_hdentry[tmp->di_bstart].hd_dentry;
5233+ tmp_h.inode = tmp_h.dentry->d_inode;
5234+ if (tmp_h.inode)
5235+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
5236+ }
5237+
5238+ inode = dentry->d_inode;
5239+ if (!orig_h.inode) {
5240+ AuDbg("nagative originally\n");
5241+ if (inode) {
5242+ au_hide(dentry);
5243+ goto out;
5244+ }
5245+ AuDebugOn(inode);
5246+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
5247+ AuDebugOn(dinfo->di_bdiropq != -1);
5248+
5249+ if (!tmp_h.inode) {
5250+ AuDbg("negative --> negative\n");
5251+ /* should have only one negative lower */
5252+ if (tmp->di_bstart >= 0
5253+ && tmp->di_bstart < dinfo->di_bstart) {
5254+ AuDebugOn(tmp->di_bstart != tmp->di_bend);
5255+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
5256+ au_set_h_dptr(dentry, dinfo->di_bstart, NULL);
5257+ au_di_cp(dinfo, tmp);
5258+ hd = tmp->di_hdentry + tmp->di_bstart;
5259+ au_set_h_dptr(dentry, tmp->di_bstart,
5260+ dget(hd->hd_dentry));
5261+ }
5262+ au_dbg_verify_dinode(dentry);
5263+ } else {
5264+ AuDbg("negative --> positive\n");
5265+ /*
5266+ * similar to the behaviour of creating with bypassing
5267+ * aufs.
5268+ * unhash it in order to force an error in the
5269+ * succeeding create operation.
5270+ * we should not set S_DEAD here.
5271+ */
5272+ d_drop(dentry);
5273+ /* au_di_swap(tmp, dinfo); */
5274+ au_dbg_verify_dinode(dentry);
5275+ }
5276+ } else {
5277+ AuDbg("positive originally\n");
5278+ /* inode may be NULL */
5279+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
5280+ if (!tmp_h.inode) {
5281+ AuDbg("positive --> negative\n");
5282+ /* or bypassing aufs */
5283+ au_hide(dentry);
5284+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_bstart)
5285+ dinfo->di_bwh = tmp->di_bwh;
5286+ if (inode)
5287+ err = au_refresh_hinode_self(inode);
5288+ au_dbg_verify_dinode(dentry);
5289+ } else if (orig_h.mode == tmp_h.mode) {
5290+ AuDbg("positive --> positive, same type\n");
5291+ if (!S_ISDIR(orig_h.mode)
5292+ && dinfo->di_bstart > tmp->di_bstart) {
5293+ /*
5294+ * similar to the behaviour of removing and
5295+ * creating.
5296+ */
5297+ au_hide(dentry);
5298+ if (inode)
5299+ err = au_refresh_hinode_self(inode);
5300+ au_dbg_verify_dinode(dentry);
5301+ } else {
5302+ /* fill empty slots */
5303+ if (dinfo->di_bstart > tmp->di_bstart)
5304+ dinfo->di_bstart = tmp->di_bstart;
5305+ if (dinfo->di_bend < tmp->di_bend)
5306+ dinfo->di_bend = tmp->di_bend;
5307+ dinfo->di_bwh = tmp->di_bwh;
5308+ dinfo->di_bdiropq = tmp->di_bdiropq;
5309+ hd = tmp->di_hdentry;
5310+ bend = dinfo->di_bend;
5311+ for (bindex = tmp->di_bstart; bindex <= bend;
5312+ bindex++) {
5313+ if (au_h_dptr(dentry, bindex))
5314+ continue;
5315+ h_dentry = hd[bindex].hd_dentry;
5316+ if (!h_dentry)
5317+ continue;
5318+ h_inode = h_dentry->d_inode;
5319+ AuDebugOn(!h_inode);
5320+ AuDebugOn(orig_h.mode
5321+ != (h_inode->i_mode
5322+ & S_IFMT));
5323+ au_set_h_dptr(dentry, bindex,
5324+ dget(h_dentry));
5325+ }
5326+ err = au_refresh_hinode(inode, dentry);
5327+ au_dbg_verify_dinode(dentry);
5328+ }
5329+ } else {
5330+ AuDbg("positive --> positive, different type\n");
5331+ /* similar to the behaviour of removing and creating */
5332+ au_hide(dentry);
5333+ if (inode)
5334+ err = au_refresh_hinode_self(inode);
5335+ au_dbg_verify_dinode(dentry);
5336+ }
5337+ }
5338+
5339+out:
5340+ return err;
5341+}
5342+
5343+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
5344+{
5345+ int err, ebrange;
5346+ unsigned int sigen;
5347+ struct au_dinfo *dinfo, *tmp;
5348+ struct super_block *sb;
5349+ struct inode *inode;
5350+
5351+ DiMustWriteLock(dentry);
5352+ AuDebugOn(IS_ROOT(dentry));
5353+ AuDebugOn(!parent->d_inode);
5354+
5355+ sb = dentry->d_sb;
5356+ inode = dentry->d_inode;
5357+ sigen = au_sigen(sb);
5358+ err = au_digen_test(parent, sigen);
5359+ if (unlikely(err))
5360+ goto out;
5361+
5362+ dinfo = au_di(dentry);
5363+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
5364+ if (unlikely(err))
5365+ goto out;
5366+ ebrange = au_dbrange_test(dentry);
5367+ if (!ebrange)
5368+ ebrange = au_do_refresh_hdentry(dentry, parent);
5369+
5370+ if (d_unhashed(dentry) || ebrange) {
5371+ AuDebugOn(au_dbstart(dentry) < 0 && au_dbend(dentry) >= 0);
5372+ if (inode)
5373+ err = au_refresh_hinode_self(inode);
5374+ au_dbg_verify_dinode(dentry);
5375+ if (!err)
5376+ goto out_dgen; /* success */
5377+ goto out;
5378+ }
5379+
5380+ /* temporary dinfo */
5381+ AuDbgDentry(dentry);
5382+ err = -ENOMEM;
5383+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
5384+ if (unlikely(!tmp))
5385+ goto out;
5386+ au_di_swap(tmp, dinfo);
5387+ /* returns the number of positive dentries */
5388+ /*
5389+ * if current working dir is removed, it returns an error.
5390+ * but the dentry is legal.
5391+ */
5392+ err = au_lkup_dentry(dentry, /*bstart*/0, /*type*/0, /*nd*/NULL);
5393+ AuDbgDentry(dentry);
5394+ au_di_swap(tmp, dinfo);
5395+ if (err == -ENOENT)
5396+ err = 0;
5397+ if (err >= 0) {
5398+ /* compare/refresh by dinfo */
5399+ AuDbgDentry(dentry);
5400+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
5401+ au_dbg_verify_dinode(dentry);
5402+ AuTraceErr(err);
5403+ }
5404+ au_rw_write_unlock(&tmp->di_rwsem);
5405+ au_di_free(tmp);
5406+ if (unlikely(err))
5407+ goto out;
5408+
5409+out_dgen:
5410+ au_update_digen(dentry);
5411+out:
5412+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
5413+ AuIOErr("failed refreshing %.*s, %d\n",
5414+ AuDLNPair(dentry), err);
5415+ AuDbgDentry(dentry);
5416+ }
5417+ AuTraceErr(err);
5418+ return err;
5419+}
5420+
5421+static noinline_for_stack
5422+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
5423+ struct dentry *dentry, aufs_bindex_t bindex)
5424+{
5425+ int err, valid;
5426+ int (*reval)(struct dentry *, struct nameidata *);
5427+
5428+ err = 0;
5429+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
5430+ goto out;
5431+ reval = h_dentry->d_op->d_revalidate;
5432+
5433+ AuDbg("b%d\n", bindex);
5434+ if (au_test_fs_null_nd(h_dentry->d_sb))
5435+ /* it may return tri-state */
5436+ valid = reval(h_dentry, NULL);
5437+ else {
5438+ struct nameidata h_nd;
5439+ int locked;
1facf9fc 5440+ struct dentry *parent;
5441+
5442+ au_h_nd(&h_nd, nd);
5443+ parent = nd->path.dentry;
5444+ locked = (nd && nd->path.dentry != dentry);
5445+ if (locked)
5446+ di_read_lock_parent(parent, AuLock_IR);
5447+ BUG_ON(bindex > au_dbend(parent));
5448+ h_nd.path.dentry = au_h_dptr(parent, bindex);
5449+ BUG_ON(!h_nd.path.dentry);
5450+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
5451+ path_get(&h_nd.path);
5452+ valid = reval(h_dentry, &h_nd);
5453+ path_put(&h_nd.path);
5454+ if (locked)
5455+ di_read_unlock(parent, AuLock_IR);
5456+ }
5457+
5458+ if (unlikely(valid < 0))
5459+ err = valid;
5460+ else if (!valid)
5461+ err = -EINVAL;
5462+
4f0767ce 5463+out:
1facf9fc 5464+ AuTraceErr(err);
5465+ return err;
5466+}
5467+
5468+/* todo: remove this */
5469+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
5470+ struct nameidata *nd, int do_udba)
5471+{
5472+ int err;
5473+ umode_t mode, h_mode;
5474+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
5475+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 5476+ struct inode *h_inode, *h_cached_inode;
1facf9fc 5477+ struct dentry *h_dentry;
5478+ struct qstr *name, *h_name;
5479+
5480+ err = 0;
5481+ plus = 0;
5482+ mode = 0;
1facf9fc 5483+ ibs = -1;
5484+ ibe = -1;
5485+ unhashed = !!d_unhashed(dentry);
5486+ is_root = !!IS_ROOT(dentry);
5487+ name = &dentry->d_name;
5488+
5489+ /*
7f207e10
AM
5490+ * Theoretically, REVAL test should be unnecessary in case of
5491+ * {FS,I}NOTIFY.
5492+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 5493+ * IN_ATTRIB for atime/nlink/pageio
5494+ * IN_DELETE for NFS dentry
5495+ * Let's do REVAL test too.
5496+ */
5497+ if (do_udba && inode) {
5498+ mode = (inode->i_mode & S_IFMT);
5499+ plus = (inode->i_nlink > 0);
1facf9fc 5500+ ibs = au_ibstart(inode);
5501+ ibe = au_ibend(inode);
5502+ }
5503+
5504+ bstart = au_dbstart(dentry);
5505+ btail = bstart;
5506+ if (inode && S_ISDIR(inode->i_mode))
5507+ btail = au_dbtaildir(dentry);
5508+ for (bindex = bstart; bindex <= btail; bindex++) {
5509+ h_dentry = au_h_dptr(dentry, bindex);
5510+ if (!h_dentry)
5511+ continue;
5512+
5513+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
027c5e7a 5514+ spin_lock(&h_dentry->d_lock);
1facf9fc 5515+ h_name = &h_dentry->d_name;
5516+ if (unlikely(do_udba
5517+ && !is_root
5518+ && (unhashed != !!d_unhashed(h_dentry)
5519+ || name->len != h_name->len
5520+ || memcmp(name->name, h_name->name, name->len))
5521+ )) {
5522+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
5523+ unhashed, d_unhashed(h_dentry),
5524+ AuDLNPair(dentry), AuDLNPair(h_dentry));
027c5e7a 5525+ spin_unlock(&h_dentry->d_lock);
1facf9fc 5526+ goto err;
5527+ }
027c5e7a 5528+ spin_unlock(&h_dentry->d_lock);
1facf9fc 5529+
5530+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
5531+ if (unlikely(err))
5532+ /* do not goto err, to keep the errno */
5533+ break;
5534+
5535+ /* todo: plink too? */
5536+ if (!do_udba)
5537+ continue;
5538+
5539+ /* UDBA tests */
5540+ h_inode = h_dentry->d_inode;
5541+ if (unlikely(!!inode != !!h_inode))
5542+ goto err;
5543+
5544+ h_plus = plus;
5545+ h_mode = mode;
5546+ h_cached_inode = h_inode;
5547+ if (h_inode) {
5548+ h_mode = (h_inode->i_mode & S_IFMT);
5549+ h_plus = (h_inode->i_nlink > 0);
5550+ }
5551+ if (inode && ibs <= bindex && bindex <= ibe)
5552+ h_cached_inode = au_h_iptr(inode, bindex);
5553+
5554+ if (unlikely(plus != h_plus
5555+ || mode != h_mode
5556+ || h_cached_inode != h_inode))
5557+ goto err;
5558+ continue;
5559+
5560+ err:
5561+ err = -EINVAL;
5562+ break;
5563+ }
5564+
5565+ return err;
5566+}
5567+
027c5e7a 5568+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 5569+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
5570+{
5571+ int err;
5572+ struct dentry *parent;
1facf9fc 5573+
027c5e7a 5574+ if (!au_digen_test(dentry, sigen))
1facf9fc 5575+ return 0;
5576+
5577+ parent = dget_parent(dentry);
5578+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 5579+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 5580+ au_dbg_verify_gen(parent, sigen);
027c5e7a 5581+ err = au_refresh_dentry(dentry, parent);
1facf9fc 5582+ di_read_unlock(parent, AuLock_IR);
5583+ dput(parent);
027c5e7a 5584+ AuTraceErr(err);
1facf9fc 5585+ return err;
5586+}
5587+
5588+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
5589+{
5590+ int err;
5591+ struct dentry *d, *parent;
5592+ struct inode *inode;
5593+
027c5e7a 5594+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 5595+ return simple_reval_dpath(dentry, sigen);
5596+
5597+ /* slow loop, keep it simple and stupid */
5598+ /* cf: au_cpup_dirs() */
5599+ err = 0;
5600+ parent = NULL;
027c5e7a 5601+ while (au_digen_test(dentry, sigen)) {
1facf9fc 5602+ d = dentry;
5603+ while (1) {
5604+ dput(parent);
5605+ parent = dget_parent(d);
027c5e7a 5606+ if (!au_digen_test(parent, sigen))
1facf9fc 5607+ break;
5608+ d = parent;
5609+ }
5610+
5611+ inode = d->d_inode;
5612+ if (d != dentry)
027c5e7a 5613+ di_write_lock_child2(d);
1facf9fc 5614+
5615+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
5616+ if (au_digen_test(d, sigen)) {
5617+ /*
5618+ * todo: consolidate with simple_reval_dpath(),
5619+ * do_refresh() and au_reval_for_attr().
5620+ */
1facf9fc 5621+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 5622+ err = au_refresh_dentry(d, parent);
1facf9fc 5623+ di_read_unlock(parent, AuLock_IR);
5624+ }
5625+
5626+ if (d != dentry)
5627+ di_write_unlock(d);
5628+ dput(parent);
5629+ if (unlikely(err))
5630+ break;
5631+ }
5632+
5633+ return err;
5634+}
5635+
5636+/*
5637+ * if valid returns 1, otherwise 0.
5638+ */
5639+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
5640+{
5641+ int valid, err;
5642+ unsigned int sigen;
5643+ unsigned char do_udba;
5644+ struct super_block *sb;
5645+ struct inode *inode;
5646+
027c5e7a
AM
5647+ /* todo: support rcu-walk? */
5648+ if (nd && (nd->flags & LOOKUP_RCU))
5649+ return -ECHILD;
5650+
5651+ valid = 0;
5652+ if (unlikely(!au_di(dentry)))
5653+ goto out;
5654+
5655+ inode = dentry->d_inode;
5656+ if (inode && is_bad_inode(inode))
5657+ goto out;
5658+
e49829fe 5659+ valid = 1;
1facf9fc 5660+ sb = dentry->d_sb;
e49829fe
JR
5661+ /*
5662+ * todo: very ugly
5663+ * i_mutex of parent dir may be held,
5664+ * but we should not return 'invalid' due to busy.
5665+ */
5666+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
5667+ if (unlikely(err)) {
5668+ valid = err;
027c5e7a 5669+ AuTraceErr(err);
e49829fe
JR
5670+ goto out;
5671+ }
027c5e7a
AM
5672+ if (unlikely(au_dbrange_test(dentry))) {
5673+ err = -EINVAL;
5674+ AuTraceErr(err);
5675+ goto out_dgrade;
1facf9fc 5676+ }
027c5e7a
AM
5677+
5678+ sigen = au_sigen(sb);
5679+ if (au_digen_test(dentry, sigen)) {
1facf9fc 5680+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
5681+ err = au_reval_dpath(dentry, sigen);
5682+ if (unlikely(err)) {
5683+ AuTraceErr(err);
1facf9fc 5684+ goto out_dgrade;
027c5e7a 5685+ }
1facf9fc 5686+ }
5687+ di_downgrade_lock(dentry, AuLock_IR);
5688+
1facf9fc 5689+ err = -EINVAL;
027c5e7a
AM
5690+ if (inode && (IS_DEADDIR(inode) || !inode->i_nlink))
5691+ goto out_inval;
5692+
1facf9fc 5693+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
5694+ if (do_udba && inode) {
5695+ aufs_bindex_t bstart = au_ibstart(inode);
027c5e7a 5696+ struct inode *h_inode;
1facf9fc 5697+
027c5e7a
AM
5698+ if (bstart >= 0) {
5699+ h_inode = au_h_iptr(inode, bstart);
5700+ if (h_inode && au_test_higen(inode, h_inode))
5701+ goto out_inval;
5702+ }
1facf9fc 5703+ }
5704+
5705+ err = h_d_revalidate(dentry, inode, nd, do_udba);
027c5e7a 5706+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0)) {
1facf9fc 5707+ err = -EIO;
027c5e7a
AM
5708+ AuDbg("both of real entry and whiteout found, %.*s, err %d\n",
5709+ AuDLNPair(dentry), err);
5710+ }
e49829fe 5711+ goto out_inval;
1facf9fc 5712+
4f0767ce 5713+out_dgrade:
1facf9fc 5714+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 5715+out_inval:
1facf9fc 5716+ aufs_read_unlock(dentry, AuLock_IR);
5717+ AuTraceErr(err);
5718+ valid = !err;
e49829fe 5719+out:
027c5e7a 5720+ if (!valid) {
e49829fe 5721+ AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid);
027c5e7a
AM
5722+ d_drop(dentry);
5723+ }
1facf9fc 5724+ return valid;
5725+}
5726+
5727+static void aufs_d_release(struct dentry *dentry)
5728+{
027c5e7a 5729+ if (au_di(dentry)) {
4a4d8108
AM
5730+ au_di_fin(dentry);
5731+ au_hn_di_reinit(dentry);
1facf9fc 5732+ }
1facf9fc 5733+}
5734+
4a4d8108 5735+const struct dentry_operations aufs_dop = {
1facf9fc 5736+ .d_revalidate = aufs_d_revalidate,
5737+ .d_release = aufs_d_release
5738+};
7f207e10
AM
5739diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
5740--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
5741+++ linux/fs/aufs/dentry.h 2011-03-21 20:22:06.853935428 +0100
5742@@ -0,0 +1,237 @@
1facf9fc 5743+/*
027c5e7a 5744+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 5745+ *
5746+ * This program, aufs is free software; you can redistribute it and/or modify
5747+ * it under the terms of the GNU General Public License as published by
5748+ * the Free Software Foundation; either version 2 of the License, or
5749+ * (at your option) any later version.
dece6358
AM
5750+ *
5751+ * This program is distributed in the hope that it will be useful,
5752+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5753+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5754+ * GNU General Public License for more details.
5755+ *
5756+ * You should have received a copy of the GNU General Public License
5757+ * along with this program; if not, write to the Free Software
5758+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5759+ */
5760+
5761+/*
5762+ * lookup and dentry operations
5763+ */
5764+
5765+#ifndef __AUFS_DENTRY_H__
5766+#define __AUFS_DENTRY_H__
5767+
5768+#ifdef __KERNEL__
5769+
dece6358 5770+#include <linux/dcache.h>
1facf9fc 5771+#include <linux/aufs_type.h>
5772+#include "rwsem.h"
5773+
1facf9fc 5774+struct au_hdentry {
5775+ struct dentry *hd_dentry;
027c5e7a 5776+ aufs_bindex_t hd_id;
1facf9fc 5777+};
5778+
5779+struct au_dinfo {
5780+ atomic_t di_generation;
5781+
dece6358 5782+ struct au_rwsem di_rwsem;
1facf9fc 5783+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
5784+ struct au_hdentry *di_hdentry;
4a4d8108 5785+} ____cacheline_aligned_in_smp;
1facf9fc 5786+
5787+/* ---------------------------------------------------------------------- */
5788+
5789+/* dentry.c */
4a4d8108 5790+extern const struct dentry_operations aufs_dop;
1facf9fc 5791+struct au_branch;
5792+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
5793+ struct au_branch *br, struct nameidata *nd);
5794+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
5795+ struct au_branch *br);
5796+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
5797+ struct dentry *h_parent, struct au_branch *br);
5798+
5799+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
5800+ struct nameidata *nd);
5801+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
027c5e7a 5802+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 5803+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
5804+
5805+/* dinfo.c */
4a4d8108 5806+void au_di_init_once(void *_di);
027c5e7a
AM
5807+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
5808+void au_di_free(struct au_dinfo *dinfo);
5809+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
5810+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
5811+int au_di_init(struct dentry *dentry);
5812+void au_di_fin(struct dentry *dentry);
1facf9fc 5813+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
5814+
5815+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
5816+void di_read_unlock(struct dentry *d, int flags);
5817+void di_downgrade_lock(struct dentry *d, int flags);
5818+void di_write_lock(struct dentry *d, unsigned int lsc);
5819+void di_write_unlock(struct dentry *d);
5820+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
5821+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
5822+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
5823+
5824+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
5825+aufs_bindex_t au_dbtail(struct dentry *dentry);
5826+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
5827+
5828+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5829+ struct dentry *h_dentry);
027c5e7a
AM
5830+int au_digen_test(struct dentry *dentry, unsigned int sigen);
5831+int au_dbrange_test(struct dentry *dentry);
1facf9fc 5832+void au_update_digen(struct dentry *dentry);
5833+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5834+void au_update_dbstart(struct dentry *dentry);
5835+void au_update_dbend(struct dentry *dentry);
5836+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
5837+
5838+/* ---------------------------------------------------------------------- */
5839+
5840+static inline struct au_dinfo *au_di(struct dentry *dentry)
5841+{
5842+ return dentry->d_fsdata;
5843+}
5844+
5845+/* ---------------------------------------------------------------------- */
5846+
5847+/* lock subclass for dinfo */
5848+enum {
5849+ AuLsc_DI_CHILD, /* child first */
4a4d8108 5850+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 5851+ AuLsc_DI_CHILD3, /* copyup dirs */
5852+ AuLsc_DI_PARENT,
5853+ AuLsc_DI_PARENT2,
027c5e7a
AM
5854+ AuLsc_DI_PARENT3,
5855+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 5856+};
5857+
5858+/*
5859+ * di_read_lock_child, di_write_lock_child,
5860+ * di_read_lock_child2, di_write_lock_child2,
5861+ * di_read_lock_child3, di_write_lock_child3,
5862+ * di_read_lock_parent, di_write_lock_parent,
5863+ * di_read_lock_parent2, di_write_lock_parent2,
5864+ * di_read_lock_parent3, di_write_lock_parent3,
5865+ */
5866+#define AuReadLockFunc(name, lsc) \
5867+static inline void di_read_lock_##name(struct dentry *d, int flags) \
5868+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
5869+
5870+#define AuWriteLockFunc(name, lsc) \
5871+static inline void di_write_lock_##name(struct dentry *d) \
5872+{ di_write_lock(d, AuLsc_DI_##lsc); }
5873+
5874+#define AuRWLockFuncs(name, lsc) \
5875+ AuReadLockFunc(name, lsc) \
5876+ AuWriteLockFunc(name, lsc)
5877+
5878+AuRWLockFuncs(child, CHILD);
5879+AuRWLockFuncs(child2, CHILD2);
5880+AuRWLockFuncs(child3, CHILD3);
5881+AuRWLockFuncs(parent, PARENT);
5882+AuRWLockFuncs(parent2, PARENT2);
5883+AuRWLockFuncs(parent3, PARENT3);
5884+
5885+#undef AuReadLockFunc
5886+#undef AuWriteLockFunc
5887+#undef AuRWLockFuncs
5888+
5889+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
5890+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
5891+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 5892+
5893+/* ---------------------------------------------------------------------- */
5894+
5895+/* todo: memory barrier? */
5896+static inline unsigned int au_digen(struct dentry *d)
5897+{
5898+ return atomic_read(&au_di(d)->di_generation);
5899+}
5900+
5901+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
5902+{
5903+ hdentry->hd_dentry = NULL;
5904+}
5905+
5906+static inline void au_hdput(struct au_hdentry *hd)
5907+{
4a4d8108
AM
5908+ if (hd)
5909+ dput(hd->hd_dentry);
1facf9fc 5910+}
5911+
5912+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
5913+{
1308ab2a 5914+ DiMustAnyLock(dentry);
1facf9fc 5915+ return au_di(dentry)->di_bstart;
5916+}
5917+
5918+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
5919+{
1308ab2a 5920+ DiMustAnyLock(dentry);
1facf9fc 5921+ return au_di(dentry)->di_bend;
5922+}
5923+
5924+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
5925+{
1308ab2a 5926+ DiMustAnyLock(dentry);
1facf9fc 5927+ return au_di(dentry)->di_bwh;
5928+}
5929+
5930+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
5931+{
1308ab2a 5932+ DiMustAnyLock(dentry);
1facf9fc 5933+ return au_di(dentry)->di_bdiropq;
5934+}
5935+
5936+/* todo: hard/soft set? */
5937+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
5938+{
1308ab2a 5939+ DiMustWriteLock(dentry);
1facf9fc 5940+ au_di(dentry)->di_bstart = bindex;
5941+}
5942+
5943+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
5944+{
1308ab2a 5945+ DiMustWriteLock(dentry);
1facf9fc 5946+ au_di(dentry)->di_bend = bindex;
5947+}
5948+
5949+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
5950+{
1308ab2a 5951+ DiMustWriteLock(dentry);
1facf9fc 5952+ /* dbwh can be outside of bstart - bend range */
5953+ au_di(dentry)->di_bwh = bindex;
5954+}
5955+
5956+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
5957+{
1308ab2a 5958+ DiMustWriteLock(dentry);
1facf9fc 5959+ au_di(dentry)->di_bdiropq = bindex;
5960+}
5961+
5962+/* ---------------------------------------------------------------------- */
5963+
4a4d8108 5964+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 5965+static inline void au_digen_dec(struct dentry *d)
5966+{
e49829fe 5967+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 5968+}
5969+
4a4d8108 5970+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 5971+{
5972+ dentry->d_fsdata = NULL;
5973+}
5974+#else
4a4d8108
AM
5975+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
5976+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 5977+
5978+#endif /* __KERNEL__ */
5979+#endif /* __AUFS_DENTRY_H__ */
7f207e10
AM
5980diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
5981--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
5982+++ linux/fs/aufs/dinfo.c 2011-03-21 20:22:06.853935428 +0100
5983@@ -0,0 +1,493 @@
1facf9fc 5984+/*
027c5e7a 5985+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 5986+ *
5987+ * This program, aufs is free software; you can redistribute it and/or modify
5988+ * it under the terms of the GNU General Public License as published by
5989+ * the Free Software Foundation; either version 2 of the License, or
5990+ * (at your option) any later version.
dece6358
AM
5991+ *
5992+ * This program is distributed in the hope that it will be useful,
5993+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5994+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5995+ * GNU General Public License for more details.
5996+ *
5997+ * You should have received a copy of the GNU General Public License
5998+ * along with this program; if not, write to the Free Software
5999+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6000+ */
6001+
6002+/*
6003+ * dentry private data
6004+ */
6005+
6006+#include "aufs.h"
6007+
e49829fe 6008+void au_di_init_once(void *_dinfo)
4a4d8108 6009+{
e49829fe
JR
6010+ struct au_dinfo *dinfo = _dinfo;
6011+ static struct lock_class_key aufs_di;
4a4d8108 6012+
e49829fe
JR
6013+ au_rw_init(&dinfo->di_rwsem);
6014+ au_rw_class(&dinfo->di_rwsem, &aufs_di);
4a4d8108
AM
6015+}
6016+
027c5e7a 6017+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 6018+{
6019+ struct au_dinfo *dinfo;
027c5e7a 6020+ int nbr, i;
1facf9fc 6021+
6022+ dinfo = au_cache_alloc_dinfo();
6023+ if (unlikely(!dinfo))
6024+ goto out;
6025+
1facf9fc 6026+ nbr = au_sbend(sb) + 1;
6027+ if (nbr <= 0)
6028+ nbr = 1;
6029+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
6030+ if (dinfo->di_hdentry) {
6031+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
6032+ dinfo->di_bstart = -1;
6033+ dinfo->di_bend = -1;
6034+ dinfo->di_bwh = -1;
6035+ dinfo->di_bdiropq = -1;
6036+ for (i = 0; i < nbr; i++)
6037+ dinfo->di_hdentry[i].hd_id = -1;
6038+ goto out;
6039+ }
1facf9fc 6040+
1facf9fc 6041+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
6042+ dinfo = NULL;
6043+
4f0767ce 6044+out:
027c5e7a 6045+ return dinfo;
1facf9fc 6046+}
6047+
027c5e7a 6048+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 6049+{
4a4d8108
AM
6050+ struct au_hdentry *p;
6051+ aufs_bindex_t bend, bindex;
6052+
6053+ /* dentry may not be revalidated */
027c5e7a 6054+ bindex = dinfo->di_bstart;
4a4d8108 6055+ if (bindex >= 0) {
027c5e7a
AM
6056+ bend = dinfo->di_bend;
6057+ p = dinfo->di_hdentry + bindex;
4a4d8108
AM
6058+ while (bindex++ <= bend)
6059+ au_hdput(p++);
6060+ }
027c5e7a
AM
6061+ kfree(dinfo->di_hdentry);
6062+ au_cache_free_dinfo(dinfo);
6063+}
6064+
6065+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
6066+{
6067+ struct au_hdentry *p;
6068+ aufs_bindex_t bi;
6069+
6070+ AuRwMustWriteLock(&a->di_rwsem);
6071+ AuRwMustWriteLock(&b->di_rwsem);
6072+
6073+#define DiSwap(v, name) \
6074+ do { \
6075+ v = a->di_##name; \
6076+ a->di_##name = b->di_##name; \
6077+ b->di_##name = v; \
6078+ } while (0)
6079+
6080+ DiSwap(p, hdentry);
6081+ DiSwap(bi, bstart);
6082+ DiSwap(bi, bend);
6083+ DiSwap(bi, bwh);
6084+ DiSwap(bi, bdiropq);
6085+ /* smp_mb(); */
6086+
6087+#undef DiSwap
6088+}
6089+
6090+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
6091+{
6092+ AuRwMustWriteLock(&dst->di_rwsem);
6093+ AuRwMustWriteLock(&src->di_rwsem);
6094+
6095+ dst->di_bstart = src->di_bstart;
6096+ dst->di_bend = src->di_bend;
6097+ dst->di_bwh = src->di_bwh;
6098+ dst->di_bdiropq = src->di_bdiropq;
6099+ /* smp_mb(); */
6100+}
6101+
6102+int au_di_init(struct dentry *dentry)
6103+{
6104+ int err;
6105+ struct super_block *sb;
6106+ struct au_dinfo *dinfo;
6107+
6108+ err = 0;
6109+ sb = dentry->d_sb;
6110+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
6111+ if (dinfo) {
6112+ atomic_set(&dinfo->di_generation, au_sigen(sb));
6113+ /* smp_mb(); */ /* atomic_set */
6114+ dentry->d_fsdata = dinfo;
6115+ } else
6116+ err = -ENOMEM;
6117+
6118+ return err;
6119+}
6120+
6121+void au_di_fin(struct dentry *dentry)
6122+{
6123+ struct au_dinfo *dinfo;
6124+
6125+ dinfo = au_di(dentry);
6126+ AuRwDestroy(&dinfo->di_rwsem);
6127+ au_di_free(dinfo);
4a4d8108
AM
6128+}
6129+
1facf9fc 6130+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
6131+{
6132+ int err, sz;
6133+ struct au_hdentry *hdp;
6134+
1308ab2a 6135+ AuRwMustWriteLock(&dinfo->di_rwsem);
6136+
1facf9fc 6137+ err = -ENOMEM;
6138+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
6139+ if (!sz)
6140+ sz = sizeof(*hdp);
6141+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
6142+ if (hdp) {
6143+ dinfo->di_hdentry = hdp;
6144+ err = 0;
6145+ }
6146+
6147+ return err;
6148+}
6149+
6150+/* ---------------------------------------------------------------------- */
6151+
6152+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
6153+{
6154+ switch (lsc) {
6155+ case AuLsc_DI_CHILD:
6156+ ii_write_lock_child(inode);
6157+ break;
6158+ case AuLsc_DI_CHILD2:
6159+ ii_write_lock_child2(inode);
6160+ break;
6161+ case AuLsc_DI_CHILD3:
6162+ ii_write_lock_child3(inode);
6163+ break;
6164+ case AuLsc_DI_PARENT:
6165+ ii_write_lock_parent(inode);
6166+ break;
6167+ case AuLsc_DI_PARENT2:
6168+ ii_write_lock_parent2(inode);
6169+ break;
6170+ case AuLsc_DI_PARENT3:
6171+ ii_write_lock_parent3(inode);
6172+ break;
6173+ default:
6174+ BUG();
6175+ }
6176+}
6177+
6178+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
6179+{
6180+ switch (lsc) {
6181+ case AuLsc_DI_CHILD:
6182+ ii_read_lock_child(inode);
6183+ break;
6184+ case AuLsc_DI_CHILD2:
6185+ ii_read_lock_child2(inode);
6186+ break;
6187+ case AuLsc_DI_CHILD3:
6188+ ii_read_lock_child3(inode);
6189+ break;
6190+ case AuLsc_DI_PARENT:
6191+ ii_read_lock_parent(inode);
6192+ break;
6193+ case AuLsc_DI_PARENT2:
6194+ ii_read_lock_parent2(inode);
6195+ break;
6196+ case AuLsc_DI_PARENT3:
6197+ ii_read_lock_parent3(inode);
6198+ break;
6199+ default:
6200+ BUG();
6201+ }
6202+}
6203+
6204+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
6205+{
dece6358 6206+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 6207+ if (d->d_inode) {
6208+ if (au_ftest_lock(flags, IW))
6209+ do_ii_write_lock(d->d_inode, lsc);
6210+ else if (au_ftest_lock(flags, IR))
6211+ do_ii_read_lock(d->d_inode, lsc);
6212+ }
6213+}
6214+
6215+void di_read_unlock(struct dentry *d, int flags)
6216+{
6217+ if (d->d_inode) {
027c5e7a
AM
6218+ if (au_ftest_lock(flags, IW)) {
6219+ au_dbg_verify_dinode(d);
1facf9fc 6220+ ii_write_unlock(d->d_inode);
027c5e7a
AM
6221+ } else if (au_ftest_lock(flags, IR)) {
6222+ au_dbg_verify_dinode(d);
1facf9fc 6223+ ii_read_unlock(d->d_inode);
027c5e7a 6224+ }
1facf9fc 6225+ }
dece6358 6226+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 6227+}
6228+
6229+void di_downgrade_lock(struct dentry *d, int flags)
6230+{
1facf9fc 6231+ if (d->d_inode && au_ftest_lock(flags, IR))
6232+ ii_downgrade_lock(d->d_inode);
dece6358 6233+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 6234+}
6235+
6236+void di_write_lock(struct dentry *d, unsigned int lsc)
6237+{
dece6358 6238+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 6239+ if (d->d_inode)
6240+ do_ii_write_lock(d->d_inode, lsc);
6241+}
6242+
6243+void di_write_unlock(struct dentry *d)
6244+{
027c5e7a 6245+ au_dbg_verify_dinode(d);
1facf9fc 6246+ if (d->d_inode)
6247+ ii_write_unlock(d->d_inode);
dece6358 6248+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 6249+}
6250+
6251+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
6252+{
6253+ AuDebugOn(d1 == d2
6254+ || d1->d_inode == d2->d_inode
6255+ || d1->d_sb != d2->d_sb);
6256+
6257+ if (isdir && au_test_subdir(d1, d2)) {
6258+ di_write_lock_child(d1);
6259+ di_write_lock_child2(d2);
6260+ } else {
6261+ /* there should be no races */
6262+ di_write_lock_child(d2);
6263+ di_write_lock_child2(d1);
6264+ }
6265+}
6266+
6267+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
6268+{
6269+ AuDebugOn(d1 == d2
6270+ || d1->d_inode == d2->d_inode
6271+ || d1->d_sb != d2->d_sb);
6272+
6273+ if (isdir && au_test_subdir(d1, d2)) {
6274+ di_write_lock_parent(d1);
6275+ di_write_lock_parent2(d2);
6276+ } else {
6277+ /* there should be no races */
6278+ di_write_lock_parent(d2);
6279+ di_write_lock_parent2(d1);
6280+ }
6281+}
6282+
6283+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
6284+{
6285+ di_write_unlock(d1);
6286+ if (d1->d_inode == d2->d_inode)
dece6358 6287+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 6288+ else
6289+ di_write_unlock(d2);
6290+}
6291+
6292+/* ---------------------------------------------------------------------- */
6293+
6294+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
6295+{
6296+ struct dentry *d;
6297+
1308ab2a 6298+ DiMustAnyLock(dentry);
6299+
1facf9fc 6300+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
6301+ return NULL;
6302+ AuDebugOn(bindex < 0);
6303+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
027c5e7a 6304+ AuDebugOn(d && d->d_count <= 0);
1facf9fc 6305+ return d;
6306+}
6307+
6308+aufs_bindex_t au_dbtail(struct dentry *dentry)
6309+{
6310+ aufs_bindex_t bend, bwh;
6311+
6312+ bend = au_dbend(dentry);
6313+ if (0 <= bend) {
6314+ bwh = au_dbwh(dentry);
6315+ if (!bwh)
6316+ return bwh;
6317+ if (0 < bwh && bwh < bend)
6318+ return bwh - 1;
6319+ }
6320+ return bend;
6321+}
6322+
6323+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
6324+{
6325+ aufs_bindex_t bend, bopq;
6326+
6327+ bend = au_dbtail(dentry);
6328+ if (0 <= bend) {
6329+ bopq = au_dbdiropq(dentry);
6330+ if (0 <= bopq && bopq < bend)
6331+ bend = bopq;
6332+ }
6333+ return bend;
6334+}
6335+
6336+/* ---------------------------------------------------------------------- */
6337+
6338+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
6339+ struct dentry *h_dentry)
6340+{
6341+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
027c5e7a 6342+ struct au_branch *br;
1facf9fc 6343+
1308ab2a 6344+ DiMustWriteLock(dentry);
6345+
4a4d8108 6346+ au_hdput(hd);
1facf9fc 6347+ hd->hd_dentry = h_dentry;
027c5e7a
AM
6348+ if (h_dentry) {
6349+ br = au_sbr(dentry->d_sb, bindex);
6350+ hd->hd_id = br->br_id;
6351+ }
6352+}
6353+
6354+int au_dbrange_test(struct dentry *dentry)
6355+{
6356+ int err;
6357+ aufs_bindex_t bstart, bend;
6358+
6359+ err = 0;
6360+ bstart = au_dbstart(dentry);
6361+ bend = au_dbend(dentry);
6362+ if (bstart >= 0)
6363+ AuDebugOn(bend < 0 && bstart > bend);
6364+ else {
6365+ err = -EIO;
6366+ AuDebugOn(bend >= 0);
6367+ }
6368+
6369+ return err;
6370+}
6371+
6372+int au_digen_test(struct dentry *dentry, unsigned int sigen)
6373+{
6374+ int err;
6375+
6376+ err = 0;
6377+ if (unlikely(au_digen(dentry) != sigen
6378+ || au_iigen_test(dentry->d_inode, sigen)))
6379+ err = -EIO;
6380+
6381+ return err;
1facf9fc 6382+}
6383+
6384+void au_update_digen(struct dentry *dentry)
6385+{
6386+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
6387+ /* smp_mb(); */ /* atomic_set */
6388+}
6389+
6390+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
6391+{
6392+ struct au_dinfo *dinfo;
6393+ struct dentry *h_d;
4a4d8108 6394+ struct au_hdentry *hdp;
1facf9fc 6395+
1308ab2a 6396+ DiMustWriteLock(dentry);
6397+
1facf9fc 6398+ dinfo = au_di(dentry);
6399+ if (!dinfo || dinfo->di_bstart < 0)
6400+ return;
6401+
4a4d8108 6402+ hdp = dinfo->di_hdentry;
1facf9fc 6403+ if (do_put_zero) {
6404+ aufs_bindex_t bindex, bend;
6405+
6406+ bend = dinfo->di_bend;
6407+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 6408+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 6409+ if (h_d && !h_d->d_inode)
6410+ au_set_h_dptr(dentry, bindex, NULL);
6411+ }
6412+ }
6413+
6414+ dinfo->di_bstart = -1;
6415+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 6416+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 6417+ break;
6418+ if (dinfo->di_bstart > dinfo->di_bend) {
6419+ dinfo->di_bstart = -1;
6420+ dinfo->di_bend = -1;
6421+ return;
6422+ }
6423+
6424+ dinfo->di_bend++;
6425+ while (0 <= --dinfo->di_bend)
4a4d8108 6426+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 6427+ break;
6428+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
6429+}
6430+
6431+void au_update_dbstart(struct dentry *dentry)
6432+{
6433+ aufs_bindex_t bindex, bend;
6434+ struct dentry *h_dentry;
6435+
6436+ bend = au_dbend(dentry);
6437+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
6438+ h_dentry = au_h_dptr(dentry, bindex);
6439+ if (!h_dentry)
6440+ continue;
6441+ if (h_dentry->d_inode) {
6442+ au_set_dbstart(dentry, bindex);
6443+ return;
6444+ }
6445+ au_set_h_dptr(dentry, bindex, NULL);
6446+ }
6447+}
6448+
6449+void au_update_dbend(struct dentry *dentry)
6450+{
6451+ aufs_bindex_t bindex, bstart;
6452+ struct dentry *h_dentry;
6453+
6454+ bstart = au_dbstart(dentry);
7f207e10 6455+ for (bindex = au_dbend(dentry); bindex >= bstart; bindex--) {
1facf9fc 6456+ h_dentry = au_h_dptr(dentry, bindex);
6457+ if (!h_dentry)
6458+ continue;
6459+ if (h_dentry->d_inode) {
6460+ au_set_dbend(dentry, bindex);
6461+ return;
6462+ }
6463+ au_set_h_dptr(dentry, bindex, NULL);
6464+ }
6465+}
6466+
6467+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
6468+{
6469+ aufs_bindex_t bindex, bend;
6470+
6471+ bend = au_dbend(dentry);
6472+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
6473+ if (au_h_dptr(dentry, bindex) == h_dentry)
6474+ return bindex;
6475+ return -1;
6476+}
7f207e10
AM
6477diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
6478--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
6479+++ linux/fs/aufs/dir.c 2011-03-21 20:22:06.853935428 +0100
6480@@ -0,0 +1,647 @@
1facf9fc 6481+/*
027c5e7a 6482+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 6483+ *
6484+ * This program, aufs is free software; you can redistribute it and/or modify
6485+ * it under the terms of the GNU General Public License as published by
6486+ * the Free Software Foundation; either version 2 of the License, or
6487+ * (at your option) any later version.
dece6358
AM
6488+ *
6489+ * This program is distributed in the hope that it will be useful,
6490+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6491+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6492+ * GNU General Public License for more details.
6493+ *
6494+ * You should have received a copy of the GNU General Public License
6495+ * along with this program; if not, write to the Free Software
6496+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6497+ */
6498+
6499+/*
6500+ * directory operations
6501+ */
6502+
dece6358 6503+#include <linux/file.h>
1facf9fc 6504+#include <linux/fs_stack.h>
6505+#include "aufs.h"
6506+
6507+void au_add_nlink(struct inode *dir, struct inode *h_dir)
6508+{
6509+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
6510+
6511+ dir->i_nlink += h_dir->i_nlink - 2;
6512+ if (h_dir->i_nlink < 2)
6513+ dir->i_nlink += 2;
6514+}
6515+
6516+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
6517+{
6518+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
6519+
6520+ dir->i_nlink -= h_dir->i_nlink - 2;
6521+ if (h_dir->i_nlink < 2)
6522+ dir->i_nlink -= 2;
6523+}
6524+
1308ab2a 6525+loff_t au_dir_size(struct file *file, struct dentry *dentry)
6526+{
6527+ loff_t sz;
6528+ aufs_bindex_t bindex, bend;
6529+ struct file *h_file;
6530+ struct dentry *h_dentry;
6531+
6532+ sz = 0;
6533+ if (file) {
6534+ AuDebugOn(!file->f_dentry);
6535+ AuDebugOn(!file->f_dentry->d_inode);
6536+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
6537+
4a4d8108 6538+ bend = au_fbend_dir(file);
1308ab2a 6539+ for (bindex = au_fbstart(file);
6540+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
6541+ bindex++) {
4a4d8108 6542+ h_file = au_hf_dir(file, bindex);
1308ab2a 6543+ if (h_file
6544+ && h_file->f_dentry
6545+ && h_file->f_dentry->d_inode)
6546+ sz += i_size_read(h_file->f_dentry->d_inode);
6547+ }
6548+ } else {
6549+ AuDebugOn(!dentry);
6550+ AuDebugOn(!dentry->d_inode);
6551+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
6552+
6553+ bend = au_dbtaildir(dentry);
6554+ for (bindex = au_dbstart(dentry);
6555+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
6556+ bindex++) {
6557+ h_dentry = au_h_dptr(dentry, bindex);
6558+ if (h_dentry && h_dentry->d_inode)
6559+ sz += i_size_read(h_dentry->d_inode);
6560+ }
6561+ }
6562+ if (sz < KMALLOC_MAX_SIZE)
6563+ sz = roundup_pow_of_two(sz);
6564+ if (sz > KMALLOC_MAX_SIZE)
6565+ sz = KMALLOC_MAX_SIZE;
6566+ else if (sz < NAME_MAX) {
6567+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
6568+ sz = AUFS_RDBLK_DEF;
6569+ }
6570+ return sz;
6571+}
6572+
1facf9fc 6573+/* ---------------------------------------------------------------------- */
6574+
6575+static int reopen_dir(struct file *file)
6576+{
6577+ int err;
6578+ unsigned int flags;
6579+ aufs_bindex_t bindex, btail, bstart;
6580+ struct dentry *dentry, *h_dentry;
6581+ struct file *h_file;
6582+
6583+ /* open all lower dirs */
6584+ dentry = file->f_dentry;
6585+ bstart = au_dbstart(dentry);
6586+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
6587+ au_set_h_fptr(file, bindex, NULL);
6588+ au_set_fbstart(file, bstart);
6589+
6590+ btail = au_dbtaildir(dentry);
4a4d8108 6591+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 6592+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 6593+ au_set_fbend_dir(file, btail);
1facf9fc 6594+
4a4d8108 6595+ flags = vfsub_file_flags(file);
1facf9fc 6596+ for (bindex = bstart; bindex <= btail; bindex++) {
6597+ h_dentry = au_h_dptr(dentry, bindex);
6598+ if (!h_dentry)
6599+ continue;
4a4d8108 6600+ h_file = au_hf_dir(file, bindex);
1facf9fc 6601+ if (h_file)
6602+ continue;
6603+
6604+ h_file = au_h_open(dentry, bindex, flags, file);
6605+ err = PTR_ERR(h_file);
6606+ if (IS_ERR(h_file))
6607+ goto out; /* close all? */
6608+ au_set_h_fptr(file, bindex, h_file);
6609+ }
6610+ au_update_figen(file);
6611+ /* todo: necessary? */
6612+ /* file->f_ra = h_file->f_ra; */
6613+ err = 0;
6614+
4f0767ce 6615+out:
1facf9fc 6616+ return err;
6617+}
6618+
6619+static int do_open_dir(struct file *file, int flags)
6620+{
6621+ int err;
6622+ aufs_bindex_t bindex, btail;
6623+ struct dentry *dentry, *h_dentry;
6624+ struct file *h_file;
6625+
1308ab2a 6626+ FiMustWriteLock(file);
6627+
1facf9fc 6628+ dentry = file->f_dentry;
027c5e7a
AM
6629+ err = au_alive_dir(dentry);
6630+ if (unlikely(err))
6631+ goto out;
6632+
1facf9fc 6633+ file->f_version = dentry->d_inode->i_version;
6634+ bindex = au_dbstart(dentry);
6635+ au_set_fbstart(file, bindex);
6636+ btail = au_dbtaildir(dentry);
4a4d8108 6637+ au_set_fbend_dir(file, btail);
1facf9fc 6638+ for (; !err && bindex <= btail; bindex++) {
6639+ h_dentry = au_h_dptr(dentry, bindex);
6640+ if (!h_dentry)
6641+ continue;
6642+
6643+ h_file = au_h_open(dentry, bindex, flags, file);
6644+ if (IS_ERR(h_file)) {
6645+ err = PTR_ERR(h_file);
6646+ break;
6647+ }
6648+ au_set_h_fptr(file, bindex, h_file);
6649+ }
6650+ au_update_figen(file);
6651+ /* todo: necessary? */
6652+ /* file->f_ra = h_file->f_ra; */
6653+ if (!err)
6654+ return 0; /* success */
6655+
6656+ /* close all */
6657+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
6658+ au_set_h_fptr(file, bindex, NULL);
6659+ au_set_fbstart(file, -1);
4a4d8108
AM
6660+ au_set_fbend_dir(file, -1);
6661+
027c5e7a 6662+out:
1facf9fc 6663+ return err;
6664+}
6665+
6666+static int aufs_open_dir(struct inode *inode __maybe_unused,
6667+ struct file *file)
6668+{
4a4d8108
AM
6669+ int err;
6670+ struct super_block *sb;
6671+ struct au_fidir *fidir;
6672+
6673+ err = -ENOMEM;
6674+ sb = file->f_dentry->d_sb;
6675+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 6676+ fidir = au_fidir_alloc(sb);
4a4d8108
AM
6677+ if (fidir) {
6678+ err = au_do_open(file, do_open_dir, fidir);
6679+ if (unlikely(err))
6680+ kfree(fidir);
6681+ }
6682+ si_read_unlock(sb);
6683+ return err;
1facf9fc 6684+}
6685+
6686+static int aufs_release_dir(struct inode *inode __maybe_unused,
6687+ struct file *file)
6688+{
6689+ struct au_vdir *vdir_cache;
4a4d8108
AM
6690+ struct au_finfo *finfo;
6691+ struct au_fidir *fidir;
6692+ aufs_bindex_t bindex, bend;
1facf9fc 6693+
4a4d8108
AM
6694+ finfo = au_fi(file);
6695+ fidir = finfo->fi_hdir;
6696+ if (fidir) {
0c5527e5
AM
6697+ /* remove me from sb->s_files */
6698+ file_sb_list_del(file);
6699+
4a4d8108
AM
6700+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
6701+ if (vdir_cache)
6702+ au_vdir_free(vdir_cache);
6703+
6704+ bindex = finfo->fi_btop;
6705+ if (bindex >= 0) {
6706+ /*
6707+ * calls fput() instead of filp_close(),
6708+ * since no dnotify or lock for the lower file.
6709+ */
6710+ bend = fidir->fd_bbot;
6711+ for (; bindex <= bend; bindex++)
6712+ au_set_h_fptr(file, bindex, NULL);
6713+ }
6714+ kfree(fidir);
6715+ finfo->fi_hdir = NULL;
1facf9fc 6716+ }
1facf9fc 6717+ au_finfo_fin(file);
1facf9fc 6718+ return 0;
6719+}
6720+
6721+/* ---------------------------------------------------------------------- */
6722+
4a4d8108
AM
6723+static int au_do_flush_dir(struct file *file, fl_owner_t id)
6724+{
6725+ int err;
6726+ aufs_bindex_t bindex, bend;
6727+ struct file *h_file;
6728+
6729+ err = 0;
6730+ bend = au_fbend_dir(file);
6731+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
6732+ h_file = au_hf_dir(file, bindex);
6733+ if (h_file)
6734+ err = vfsub_flush(h_file, id);
6735+ }
6736+ return err;
6737+}
6738+
6739+static int aufs_flush_dir(struct file *file, fl_owner_t id)
6740+{
6741+ return au_do_flush(file, id, au_do_flush_dir);
6742+}
6743+
6744+/* ---------------------------------------------------------------------- */
6745+
1facf9fc 6746+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
6747+{
6748+ int err;
6749+ aufs_bindex_t bend, bindex;
6750+ struct inode *inode;
6751+ struct super_block *sb;
6752+
6753+ err = 0;
6754+ sb = dentry->d_sb;
6755+ inode = dentry->d_inode;
6756+ IMustLock(inode);
6757+ bend = au_dbend(dentry);
6758+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
6759+ struct path h_path;
6760+ struct inode *h_inode;
6761+
6762+ if (au_test_ro(sb, bindex, inode))
6763+ continue;
6764+ h_path.dentry = au_h_dptr(dentry, bindex);
6765+ if (!h_path.dentry)
6766+ continue;
6767+ h_inode = h_path.dentry->d_inode;
6768+ if (!h_inode)
6769+ continue;
6770+
6771+ /* no mnt_want_write() */
6772+ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
6773+ /* todo: inotiry fired? */
6774+ h_path.mnt = au_sbr_mnt(sb, bindex);
6775+ mutex_lock(&h_inode->i_mutex);
6776+ err = filemap_fdatawrite(h_inode->i_mapping);
6777+ AuDebugOn(!h_inode->i_fop);
6778+ if (!err && h_inode->i_fop->fsync)
b752ccd1 6779+ err = h_inode->i_fop->fsync(NULL, datasync);
1facf9fc 6780+ if (!err)
6781+ err = filemap_fdatawrite(h_inode->i_mapping);
6782+ if (!err)
6783+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
6784+ mutex_unlock(&h_inode->i_mutex);
6785+ }
6786+
6787+ return err;
6788+}
6789+
6790+static int au_do_fsync_dir(struct file *file, int datasync)
6791+{
6792+ int err;
6793+ aufs_bindex_t bend, bindex;
6794+ struct file *h_file;
6795+ struct super_block *sb;
6796+ struct inode *inode;
6797+ struct mutex *h_mtx;
6798+
6799+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6800+ if (unlikely(err))
6801+ goto out;
6802+
6803+ sb = file->f_dentry->d_sb;
6804+ inode = file->f_dentry->d_inode;
4a4d8108 6805+ bend = au_fbend_dir(file);
1facf9fc 6806+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 6807+ h_file = au_hf_dir(file, bindex);
1facf9fc 6808+ if (!h_file || au_test_ro(sb, bindex, inode))
6809+ continue;
6810+
b752ccd1 6811+ err = vfs_fsync(h_file, datasync);
1facf9fc 6812+ if (!err) {
6813+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
6814+ mutex_lock(h_mtx);
6815+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
6816+ /*ignore*/
6817+ mutex_unlock(h_mtx);
6818+ }
6819+ }
6820+
4f0767ce 6821+out:
1facf9fc 6822+ return err;
6823+}
6824+
6825+/*
6826+ * @file may be NULL
6827+ */
b752ccd1 6828+static int aufs_fsync_dir(struct file *file, int datasync)
1facf9fc 6829+{
6830+ int err;
b752ccd1 6831+ struct dentry *dentry;
1facf9fc 6832+ struct super_block *sb;
6833+
b752ccd1 6834+ dentry = file->f_dentry;
1facf9fc 6835+ IMustLock(dentry->d_inode);
6836+
6837+ err = 0;
6838+ sb = dentry->d_sb;
6839+ si_noflush_read_lock(sb);
6840+ if (file)
6841+ err = au_do_fsync_dir(file, datasync);
6842+ else {
6843+ di_write_lock_child(dentry);
6844+ err = au_do_fsync_dir_no_file(dentry, datasync);
6845+ }
6846+ au_cpup_attr_timesizes(dentry->d_inode);
6847+ di_write_unlock(dentry);
6848+ if (file)
6849+ fi_write_unlock(file);
6850+
6851+ si_read_unlock(sb);
6852+ return err;
6853+}
6854+
6855+/* ---------------------------------------------------------------------- */
6856+
6857+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
6858+{
6859+ int err;
6860+ struct dentry *dentry;
6861+ struct inode *inode;
6862+ struct super_block *sb;
6863+
6864+ dentry = file->f_dentry;
6865+ inode = dentry->d_inode;
6866+ IMustLock(inode);
6867+
6868+ sb = dentry->d_sb;
6869+ si_read_lock(sb, AuLock_FLUSH);
6870+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6871+ if (unlikely(err))
6872+ goto out;
027c5e7a
AM
6873+ err = au_alive_dir(dentry);
6874+ if (!err)
6875+ err = au_vdir_init(file);
1facf9fc 6876+ di_downgrade_lock(dentry, AuLock_IR);
6877+ if (unlikely(err))
6878+ goto out_unlock;
6879+
b752ccd1 6880+ if (!au_test_nfsd()) {
1facf9fc 6881+ err = au_vdir_fill_de(file, dirent, filldir);
6882+ fsstack_copy_attr_atime(inode,
6883+ au_h_iptr(inode, au_ibstart(inode)));
6884+ } else {
6885+ /*
6886+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
6887+ * encode_fh() and others.
6888+ */
6889+ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
6890+
6891+ di_read_unlock(dentry, AuLock_IR);
6892+ si_read_unlock(sb);
1facf9fc 6893+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 6894+ fsstack_copy_attr_atime(inode, h_inode);
6895+ fi_write_unlock(file);
6896+
6897+ AuTraceErr(err);
6898+ return err;
6899+ }
6900+
4f0767ce 6901+out_unlock:
1facf9fc 6902+ di_read_unlock(dentry, AuLock_IR);
6903+ fi_write_unlock(file);
4f0767ce 6904+out:
1facf9fc 6905+ si_read_unlock(sb);
6906+ return err;
6907+}
6908+
6909+/* ---------------------------------------------------------------------- */
6910+
6911+#define AuTestEmpty_WHONLY 1
dece6358
AM
6912+#define AuTestEmpty_CALLED (1 << 1)
6913+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 6914+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
6915+#define au_fset_testempty(flags, name) \
6916+ do { (flags) |= AuTestEmpty_##name; } while (0)
6917+#define au_fclr_testempty(flags, name) \
6918+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 6919+
dece6358
AM
6920+#ifndef CONFIG_AUFS_SHWH
6921+#undef AuTestEmpty_SHWH
6922+#define AuTestEmpty_SHWH 0
6923+#endif
6924+
1facf9fc 6925+struct test_empty_arg {
1308ab2a 6926+ struct au_nhash *whlist;
1facf9fc 6927+ unsigned int flags;
6928+ int err;
6929+ aufs_bindex_t bindex;
6930+};
6931+
6932+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
6933+ loff_t offset __maybe_unused, u64 ino,
6934+ unsigned int d_type)
1facf9fc 6935+{
6936+ struct test_empty_arg *arg = __arg;
6937+ char *name = (void *)__name;
6938+
6939+ arg->err = 0;
6940+ au_fset_testempty(arg->flags, CALLED);
6941+ /* smp_mb(); */
6942+ if (name[0] == '.'
6943+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
6944+ goto out; /* success */
6945+
6946+ if (namelen <= AUFS_WH_PFX_LEN
6947+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
6948+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 6949+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6950+ arg->err = -ENOTEMPTY;
6951+ goto out;
6952+ }
6953+
6954+ name += AUFS_WH_PFX_LEN;
6955+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 6956+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6957+ arg->err = au_nhash_append_wh
1308ab2a 6958+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 6959+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 6960+
4f0767ce 6961+out:
1facf9fc 6962+ /* smp_mb(); */
6963+ AuTraceErr(arg->err);
6964+ return arg->err;
6965+}
6966+
6967+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6968+{
6969+ int err;
6970+ struct file *h_file;
6971+
6972+ h_file = au_h_open(dentry, arg->bindex,
6973+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
6974+ /*file*/NULL);
6975+ err = PTR_ERR(h_file);
6976+ if (IS_ERR(h_file))
6977+ goto out;
6978+
6979+ err = 0;
6980+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
6981+ && !h_file->f_dentry->d_inode->i_nlink)
6982+ goto out_put;
6983+
6984+ do {
6985+ arg->err = 0;
6986+ au_fclr_testempty(arg->flags, CALLED);
6987+ /* smp_mb(); */
6988+ err = vfsub_readdir(h_file, test_empty_cb, arg);
6989+ if (err >= 0)
6990+ err = arg->err;
6991+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
6992+
4f0767ce 6993+out_put:
1facf9fc 6994+ fput(h_file);
6995+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 6996+out:
1facf9fc 6997+ return err;
6998+}
6999+
7000+struct do_test_empty_args {
7001+ int *errp;
7002+ struct dentry *dentry;
7003+ struct test_empty_arg *arg;
7004+};
7005+
7006+static void call_do_test_empty(void *args)
7007+{
7008+ struct do_test_empty_args *a = args;
7009+ *a->errp = do_test_empty(a->dentry, a->arg);
7010+}
7011+
7012+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
7013+{
7014+ int err, wkq_err;
7015+ struct dentry *h_dentry;
7016+ struct inode *h_inode;
7017+
7018+ h_dentry = au_h_dptr(dentry, arg->bindex);
7019+ h_inode = h_dentry->d_inode;
7020+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
7021+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
7022+ mutex_unlock(&h_inode->i_mutex);
7023+ if (!err)
7024+ err = do_test_empty(dentry, arg);
7025+ else {
7026+ struct do_test_empty_args args = {
7027+ .errp = &err,
7028+ .dentry = dentry,
7029+ .arg = arg
7030+ };
7031+ unsigned int flags = arg->flags;
7032+
7033+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
7034+ if (unlikely(wkq_err))
7035+ err = wkq_err;
7036+ arg->flags = flags;
7037+ }
7038+
7039+ return err;
7040+}
7041+
7042+int au_test_empty_lower(struct dentry *dentry)
7043+{
7044+ int err;
1308ab2a 7045+ unsigned int rdhash;
1facf9fc 7046+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 7047+ struct au_nhash whlist;
1facf9fc 7048+ struct test_empty_arg arg;
1facf9fc 7049+
dece6358
AM
7050+ SiMustAnyLock(dentry->d_sb);
7051+
1308ab2a 7052+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
7053+ if (!rdhash)
7054+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
7055+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 7056+ if (unlikely(err))
1facf9fc 7057+ goto out;
7058+
1facf9fc 7059+ arg.flags = 0;
1308ab2a 7060+ arg.whlist = &whlist;
7061+ bstart = au_dbstart(dentry);
dece6358
AM
7062+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
7063+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 7064+ arg.bindex = bstart;
7065+ err = do_test_empty(dentry, &arg);
7066+ if (unlikely(err))
7067+ goto out_whlist;
7068+
7069+ au_fset_testempty(arg.flags, WHONLY);
7070+ btail = au_dbtaildir(dentry);
7071+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
7072+ struct dentry *h_dentry;
7073+
7074+ h_dentry = au_h_dptr(dentry, bindex);
7075+ if (h_dentry && h_dentry->d_inode) {
7076+ arg.bindex = bindex;
7077+ err = do_test_empty(dentry, &arg);
7078+ }
7079+ }
7080+
4f0767ce 7081+out_whlist:
1308ab2a 7082+ au_nhash_wh_free(&whlist);
4f0767ce 7083+out:
1facf9fc 7084+ return err;
7085+}
7086+
7087+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
7088+{
7089+ int err;
7090+ struct test_empty_arg arg;
7091+ aufs_bindex_t bindex, btail;
7092+
7093+ err = 0;
1308ab2a 7094+ arg.whlist = whlist;
1facf9fc 7095+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
7096+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
7097+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 7098+ btail = au_dbtaildir(dentry);
7099+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
7100+ struct dentry *h_dentry;
7101+
7102+ h_dentry = au_h_dptr(dentry, bindex);
7103+ if (h_dentry && h_dentry->d_inode) {
7104+ arg.bindex = bindex;
7105+ err = sio_test_empty(dentry, &arg);
7106+ }
7107+ }
7108+
7109+ return err;
7110+}
7111+
7112+/* ---------------------------------------------------------------------- */
7113+
7114+const struct file_operations aufs_dir_fop = {
4a4d8108 7115+ .owner = THIS_MODULE,
027c5e7a 7116+ .llseek = default_llseek,
1facf9fc 7117+ .read = generic_read_dir,
7118+ .readdir = aufs_readdir,
7119+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
7120+#ifdef CONFIG_COMPAT
7121+ .compat_ioctl = aufs_compat_ioctl_dir,
7122+#endif
1facf9fc 7123+ .open = aufs_open_dir,
7124+ .release = aufs_release_dir,
4a4d8108 7125+ .flush = aufs_flush_dir,
1facf9fc 7126+ .fsync = aufs_fsync_dir
7127+};
7f207e10
AM
7128diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
7129--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 7130+++ linux/fs/aufs/dir.h 2011-03-21 20:22:06.853935428 +0100
b752ccd1 7131@@ -0,0 +1,138 @@
1facf9fc 7132+/*
027c5e7a 7133+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 7134+ *
7135+ * This program, aufs is free software; you can redistribute it and/or modify
7136+ * it under the terms of the GNU General Public License as published by
7137+ * the Free Software Foundation; either version 2 of the License, or
7138+ * (at your option) any later version.
dece6358
AM
7139+ *
7140+ * This program is distributed in the hope that it will be useful,
7141+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7142+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7143+ * GNU General Public License for more details.
7144+ *
7145+ * You should have received a copy of the GNU General Public License
7146+ * along with this program; if not, write to the Free Software
7147+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7148+ */
7149+
7150+/*
7151+ * directory operations
7152+ */
7153+
7154+#ifndef __AUFS_DIR_H__
7155+#define __AUFS_DIR_H__
7156+
7157+#ifdef __KERNEL__
7158+
7159+#include <linux/fs.h>
7160+#include <linux/aufs_type.h>
7161+
7162+/* ---------------------------------------------------------------------- */
7163+
7164+/* need to be faster and smaller */
7165+
7166+struct au_nhash {
dece6358
AM
7167+ unsigned int nh_num;
7168+ struct hlist_head *nh_head;
1facf9fc 7169+};
7170+
7171+struct au_vdir_destr {
7172+ unsigned char len;
7173+ unsigned char name[0];
7174+} __packed;
7175+
7176+struct au_vdir_dehstr {
7177+ struct hlist_node hash;
7178+ struct au_vdir_destr *str;
4a4d8108 7179+} ____cacheline_aligned_in_smp;
1facf9fc 7180+
7181+struct au_vdir_de {
7182+ ino_t de_ino;
7183+ unsigned char de_type;
7184+ /* caution: packed */
7185+ struct au_vdir_destr de_str;
7186+} __packed;
7187+
7188+struct au_vdir_wh {
7189+ struct hlist_node wh_hash;
dece6358
AM
7190+#ifdef CONFIG_AUFS_SHWH
7191+ ino_t wh_ino;
1facf9fc 7192+ aufs_bindex_t wh_bindex;
dece6358
AM
7193+ unsigned char wh_type;
7194+#else
7195+ aufs_bindex_t wh_bindex;
7196+#endif
7197+ /* caution: packed */
1facf9fc 7198+ struct au_vdir_destr wh_str;
7199+} __packed;
7200+
7201+union au_vdir_deblk_p {
7202+ unsigned char *deblk;
7203+ struct au_vdir_de *de;
7204+};
7205+
7206+struct au_vdir {
7207+ unsigned char **vd_deblk;
7208+ unsigned long vd_nblk;
1facf9fc 7209+ struct {
7210+ unsigned long ul;
7211+ union au_vdir_deblk_p p;
7212+ } vd_last;
7213+
7214+ unsigned long vd_version;
dece6358 7215+ unsigned int vd_deblk_sz;
1facf9fc 7216+ unsigned long vd_jiffy;
4a4d8108 7217+} ____cacheline_aligned_in_smp;
1facf9fc 7218+
7219+/* ---------------------------------------------------------------------- */
7220+
7221+/* dir.c */
7222+extern const struct file_operations aufs_dir_fop;
7223+void au_add_nlink(struct inode *dir, struct inode *h_dir);
7224+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 7225+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 7226+int au_test_empty_lower(struct dentry *dentry);
7227+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
7228+
7229+/* vdir.c */
1308ab2a 7230+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
7231+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
7232+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 7233+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
7234+ int limit);
dece6358
AM
7235+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
7236+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
7237+ unsigned int d_type, aufs_bindex_t bindex,
7238+ unsigned char shwh);
1facf9fc 7239+void au_vdir_free(struct au_vdir *vdir);
7240+int au_vdir_init(struct file *file);
7241+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
7242+
7243+/* ioctl.c */
7244+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
7245+
1308ab2a 7246+#ifdef CONFIG_AUFS_RDU
7247+/* rdu.c */
7248+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
7249+#ifdef CONFIG_COMPAT
7250+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
7251+ unsigned long arg);
7252+#endif
1308ab2a 7253+#else
7254+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
7255+ unsigned long arg)
7256+{
7257+ return -EINVAL;
7258+}
b752ccd1
AM
7259+#ifdef CONFIG_COMPAT
7260+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
7261+ unsigned long arg)
7262+{
7263+ return -EINVAL;
7264+}
7265+#endif
1308ab2a 7266+#endif
7267+
1facf9fc 7268+#endif /* __KERNEL__ */
7269+#endif /* __AUFS_DIR_H__ */
7f207e10
AM
7270diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
7271--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
7272+++ linux/fs/aufs/dynop.c 2011-03-21 20:22:06.853935428 +0100
7273@@ -0,0 +1,426 @@
1facf9fc 7274+/*
027c5e7a 7275+ * Copyright (C) 2010-2011 Junjiro R. Okajima
1facf9fc 7276+ *
7277+ * This program, aufs is free software; you can redistribute it and/or modify
7278+ * it under the terms of the GNU General Public License as published by
7279+ * the Free Software Foundation; either version 2 of the License, or
7280+ * (at your option) any later version.
dece6358
AM
7281+ *
7282+ * This program is distributed in the hope that it will be useful,
7283+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7284+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7285+ * GNU General Public License for more details.
7286+ *
7287+ * You should have received a copy of the GNU General Public License
7288+ * along with this program; if not, write to the Free Software
7289+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7290+ */
7291+
7292+/*
4a4d8108 7293+ * dynamically customizable operations for regular files
1facf9fc 7294+ */
7295+
1facf9fc 7296+#include "aufs.h"
7297+
4a4d8108 7298+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 7299+
4a4d8108
AM
7300+/*
7301+ * How large will these lists be?
7302+ * Usually just a few elements, 20-30 at most for each, I guess.
7303+ */
7304+static struct au_splhead dynop[AuDyLast];
7305+
7306+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 7307+{
4a4d8108
AM
7308+ struct au_dykey *key, *tmp;
7309+ struct list_head *head;
1facf9fc 7310+
4a4d8108
AM
7311+ key = NULL;
7312+ head = &spl->head;
7313+ rcu_read_lock();
7314+ list_for_each_entry_rcu(tmp, head, dk_list)
7315+ if (tmp->dk_op.dy_hop == h_op) {
7316+ key = tmp;
7317+ kref_get(&key->dk_kref);
7318+ break;
7319+ }
7320+ rcu_read_unlock();
7321+
7322+ return key;
1facf9fc 7323+}
7324+
4a4d8108 7325+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 7326+{
4a4d8108
AM
7327+ struct au_dykey **k, *found;
7328+ const void *h_op = key->dk_op.dy_hop;
7329+ int i;
1facf9fc 7330+
4a4d8108
AM
7331+ found = NULL;
7332+ k = br->br_dykey;
7333+ for (i = 0; i < AuBrDynOp; i++)
7334+ if (k[i]) {
7335+ if (k[i]->dk_op.dy_hop == h_op) {
7336+ found = k[i];
7337+ break;
7338+ }
7339+ } else
7340+ break;
7341+ if (!found) {
7342+ spin_lock(&br->br_dykey_lock);
7343+ for (; i < AuBrDynOp; i++)
7344+ if (k[i]) {
7345+ if (k[i]->dk_op.dy_hop == h_op) {
7346+ found = k[i];
7347+ break;
7348+ }
7349+ } else {
7350+ k[i] = key;
7351+ break;
7352+ }
7353+ spin_unlock(&br->br_dykey_lock);
7354+ BUG_ON(i == AuBrDynOp); /* expand the array */
7355+ }
7356+
7357+ return found;
1facf9fc 7358+}
7359+
4a4d8108
AM
7360+/* kref_get() if @key is already added */
7361+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
7362+{
7363+ struct au_dykey *tmp, *found;
7364+ struct list_head *head;
7365+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 7366+
4a4d8108
AM
7367+ found = NULL;
7368+ head = &spl->head;
7369+ spin_lock(&spl->spin);
7370+ list_for_each_entry(tmp, head, dk_list)
7371+ if (tmp->dk_op.dy_hop == h_op) {
7372+ kref_get(&tmp->dk_kref);
7373+ found = tmp;
7374+ break;
7375+ }
7376+ if (!found)
7377+ list_add_rcu(&key->dk_list, head);
7378+ spin_unlock(&spl->spin);
1facf9fc 7379+
4a4d8108
AM
7380+ if (!found)
7381+ DyPrSym(key);
7382+ return found;
7383+}
7384+
7385+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 7386+{
4a4d8108
AM
7387+ struct au_dykey *key;
7388+
7389+ key = container_of(rcu, struct au_dykey, dk_rcu);
7390+ DyPrSym(key);
7391+ kfree(key);
1facf9fc 7392+}
7393+
4a4d8108
AM
7394+static void dy_free(struct kref *kref)
7395+{
7396+ struct au_dykey *key;
7397+ struct au_splhead *spl;
1facf9fc 7398+
4a4d8108
AM
7399+ key = container_of(kref, struct au_dykey, dk_kref);
7400+ spl = dynop + key->dk_op.dy_type;
7401+ au_spl_del_rcu(&key->dk_list, spl);
7402+ call_rcu(&key->dk_rcu, dy_free_rcu);
7403+}
7404+
7405+void au_dy_put(struct au_dykey *key)
1facf9fc 7406+{
4a4d8108
AM
7407+ kref_put(&key->dk_kref, dy_free);
7408+}
1facf9fc 7409+
4a4d8108
AM
7410+/* ---------------------------------------------------------------------- */
7411+
7412+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
7413+
7414+#ifdef CONFIG_AUFS_DEBUG
7415+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 7416+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
7417+#else
7418+#define DyDbgDeclare(cnt) do {} while (0)
7419+#define DyDbgInc(cnt) do {} while (0)
7420+#endif
7421+
7422+#define DySet(func, dst, src, h_op, h_sb) do { \
7423+ DyDbgInc(cnt); \
7424+ if (h_op->func) { \
7425+ if (src.func) \
7426+ dst.func = src.func; \
7427+ else \
7428+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
7429+ } \
7430+} while (0)
7431+
7432+#define DySetForce(func, dst, src) do { \
7433+ AuDebugOn(!src.func); \
7434+ DyDbgInc(cnt); \
7435+ dst.func = src.func; \
7436+} while (0)
7437+
7438+#define DySetAop(func) \
7439+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
7440+#define DySetAopForce(func) \
7441+ DySetForce(func, dyaop->da_op, aufs_aop)
7442+
7443+static void dy_aop(struct au_dykey *key, const void *h_op,
7444+ struct super_block *h_sb __maybe_unused)
7445+{
7446+ struct au_dyaop *dyaop = (void *)key;
7447+ const struct address_space_operations *h_aop = h_op;
7448+ DyDbgDeclare(cnt);
7449+
7450+ AuDbg("%s\n", au_sbtype(h_sb));
7451+
7452+ DySetAop(writepage);
7453+ DySetAopForce(readpage); /* force */
7454+ DySetAop(sync_page);
7455+ DySetAop(writepages);
7456+ DySetAop(set_page_dirty);
7457+ DySetAop(readpages);
7458+ DySetAop(write_begin);
7459+ DySetAop(write_end);
7460+ DySetAop(bmap);
7461+ DySetAop(invalidatepage);
7462+ DySetAop(releasepage);
027c5e7a 7463+ DySetAop(freepage);
4a4d8108
AM
7464+ /* these two will be changed according to an aufs mount option */
7465+ DySetAop(direct_IO);
7466+ DySetAop(get_xip_mem);
7467+ DySetAop(migratepage);
7468+ DySetAop(launder_page);
7469+ DySetAop(is_partially_uptodate);
7470+ DySetAop(error_remove_page);
7471+
7472+ DyDbgSize(cnt, *h_aop);
7473+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
7474+}
7475+
7476+#define DySetVmop(func) \
7477+ DySet(func, dyvmop->dv_op, aufs_vm_ops, h_vmop, h_sb)
7478+#define DySetVmopForce(func) \
7479+ DySetForce(func, dyvmop->dv_op, aufs_vm_ops)
7480+
7481+static void dy_vmop(struct au_dykey *key, const void *h_op,
7482+ struct super_block *h_sb __maybe_unused)
7483+{
7484+ struct au_dyvmop *dyvmop = (void *)key;
7485+ const struct vm_operations_struct *h_vmop = h_op;
7486+ DyDbgDeclare(cnt);
7487+
7488+ AuDbg("%s\n", au_sbtype(h_sb));
7489+
7490+ DySetVmop(open);
7491+ DySetVmop(close);
7492+ DySetVmop(fault);
7493+ DySetVmop(page_mkwrite);
7494+ DySetVmop(access);
7495+#ifdef CONFIG_NUMA
7496+ DySetVmop(set_policy);
7497+ DySetVmop(get_policy);
7498+ DySetVmop(migrate);
7499+#endif
7500+
7501+ DyDbgSize(cnt, *h_vmop);
7502+}
7503+
7504+/* ---------------------------------------------------------------------- */
7505+
7506+static void dy_bug(struct kref *kref)
7507+{
7508+ BUG();
7509+}
7510+
7511+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
7512+{
7513+ struct au_dykey *key, *old;
7514+ struct au_splhead *spl;
b752ccd1 7515+ struct op {
4a4d8108 7516+ unsigned int sz;
b752ccd1
AM
7517+ void (*set)(struct au_dykey *key, const void *h_op,
7518+ struct super_block *h_sb __maybe_unused);
7519+ };
7520+ static const struct op a[] = {
4a4d8108
AM
7521+ [AuDy_AOP] = {
7522+ .sz = sizeof(struct au_dyaop),
b752ccd1 7523+ .set = dy_aop
4a4d8108
AM
7524+ },
7525+ [AuDy_VMOP] = {
7526+ .sz = sizeof(struct au_dyvmop),
b752ccd1 7527+ .set = dy_vmop
4a4d8108 7528+ }
b752ccd1
AM
7529+ };
7530+ const struct op *p;
4a4d8108
AM
7531+
7532+ spl = dynop + op->dy_type;
7533+ key = dy_gfind_get(spl, op->dy_hop);
7534+ if (key)
7535+ goto out_add; /* success */
7536+
7537+ p = a + op->dy_type;
7538+ key = kzalloc(p->sz, GFP_NOFS);
7539+ if (unlikely(!key)) {
7540+ key = ERR_PTR(-ENOMEM);
7541+ goto out;
7542+ }
7543+
7544+ key->dk_op.dy_hop = op->dy_hop;
7545+ kref_init(&key->dk_kref);
b752ccd1 7546+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
7547+ old = dy_gadd(spl, key);
7548+ if (old) {
7549+ kfree(key);
7550+ key = old;
7551+ }
7552+
7553+out_add:
7554+ old = dy_bradd(br, key);
7555+ if (old)
7556+ /* its ref-count should never be zero here */
7557+ kref_put(&key->dk_kref, dy_bug);
7558+out:
7559+ return key;
7560+}
7561+
7562+/* ---------------------------------------------------------------------- */
7563+/*
7564+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
7565+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
7566+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
7567+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
7568+ * See the aufs manual in detail.
7569+ *
7570+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
7571+ * performance of fadvise() and madvise() may be affected.
7572+ */
7573+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
7574+{
7575+ if (!do_dx) {
7576+ dyaop->da_op.direct_IO = NULL;
7577+ dyaop->da_op.get_xip_mem = NULL;
7578+ } else {
7579+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
7580+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
7581+ if (!dyaop->da_get_xip_mem)
7582+ dyaop->da_op.get_xip_mem = NULL;
7583+ }
7584+}
7585+
7586+static struct au_dyaop *dy_aget(struct au_branch *br,
7587+ const struct address_space_operations *h_aop,
7588+ int do_dx)
7589+{
7590+ struct au_dyaop *dyaop;
7591+ struct au_dynop op;
7592+
7593+ op.dy_type = AuDy_AOP;
7594+ op.dy_haop = h_aop;
7595+ dyaop = (void *)dy_get(&op, br);
7596+ if (IS_ERR(dyaop))
7597+ goto out;
7598+ dy_adx(dyaop, do_dx);
7599+
7600+out:
7601+ return dyaop;
7602+}
7603+
7604+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
7605+ struct inode *h_inode)
7606+{
7607+ int err, do_dx;
7608+ struct super_block *sb;
7609+ struct au_branch *br;
7610+ struct au_dyaop *dyaop;
7611+
7612+ AuDebugOn(!S_ISREG(h_inode->i_mode));
7613+ IiMustWriteLock(inode);
7614+
7615+ sb = inode->i_sb;
7616+ br = au_sbr(sb, bindex);
7617+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
7618+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
7619+ err = PTR_ERR(dyaop);
7620+ if (IS_ERR(dyaop))
7621+ /* unnecessary to call dy_fput() */
7622+ goto out;
7623+
7624+ err = 0;
7625+ inode->i_mapping->a_ops = &dyaop->da_op;
7626+
7627+out:
7628+ return err;
7629+}
7630+
b752ccd1
AM
7631+/*
7632+ * Is it safe to replace a_ops during the inode/file is in operation?
7633+ * Yes, I hope so.
7634+ */
7635+int au_dy_irefresh(struct inode *inode)
7636+{
7637+ int err;
7638+ aufs_bindex_t bstart;
7639+ struct inode *h_inode;
7640+
7641+ err = 0;
7642+ if (S_ISREG(inode->i_mode)) {
7643+ bstart = au_ibstart(inode);
7644+ h_inode = au_h_iptr(inode, bstart);
7645+ err = au_dy_iaop(inode, bstart, h_inode);
7646+ }
7647+ return err;
7648+}
7649+
4a4d8108
AM
7650+void au_dy_arefresh(int do_dx)
7651+{
7652+ struct au_splhead *spl;
7653+ struct list_head *head;
7654+ struct au_dykey *key;
7655+
7656+ spl = dynop + AuDy_AOP;
7657+ head = &spl->head;
7658+ spin_lock(&spl->spin);
7659+ list_for_each_entry(key, head, dk_list)
7660+ dy_adx((void *)key, do_dx);
7661+ spin_unlock(&spl->spin);
7662+}
7663+
7664+const struct vm_operations_struct *
7665+au_dy_vmop(struct file *file, struct au_branch *br,
7666+ const struct vm_operations_struct *h_vmop)
7667+{
7668+ struct au_dyvmop *dyvmop;
7669+ struct au_dynop op;
7670+
7671+ op.dy_type = AuDy_VMOP;
7672+ op.dy_hvmop = h_vmop;
7673+ dyvmop = (void *)dy_get(&op, br);
7674+ if (IS_ERR(dyvmop))
7675+ return (void *)dyvmop;
7676+ return &dyvmop->dv_op;
7677+}
7678+
7679+/* ---------------------------------------------------------------------- */
7680+
7681+void __init au_dy_init(void)
7682+{
7683+ int i;
7684+
7685+ /* make sure that 'struct au_dykey *' can be any type */
7686+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
7687+ BUILD_BUG_ON(offsetof(struct au_dyvmop, dv_key));
7688+
7689+ for (i = 0; i < AuDyLast; i++)
7690+ au_spl_init(dynop + i);
7691+}
7692+
7693+void au_dy_fin(void)
7694+{
7695+ int i;
7696+
7697+ for (i = 0; i < AuDyLast; i++)
7698+ WARN_ON(!list_empty(&dynop[i].head));
7699+}
7f207e10
AM
7700diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
7701--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 7702+++ linux/fs/aufs/dynop.h 2011-03-21 20:22:06.853935428 +0100
b752ccd1 7703@@ -0,0 +1,89 @@
4a4d8108 7704+/*
027c5e7a 7705+ * Copyright (C) 2010-2011 Junjiro R. Okajima
4a4d8108
AM
7706+ *
7707+ * This program, aufs is free software; you can redistribute it and/or modify
7708+ * it under the terms of the GNU General Public License as published by
7709+ * the Free Software Foundation; either version 2 of the License, or
7710+ * (at your option) any later version.
7711+ *
7712+ * This program is distributed in the hope that it will be useful,
7713+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7714+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7715+ * GNU General Public License for more details.
7716+ *
7717+ * You should have received a copy of the GNU General Public License
7718+ * along with this program; if not, write to the Free Software
7719+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7720+ */
7721+
7722+/*
7723+ * dynamically customizable operations (for regular files only)
7724+ */
7725+
7726+#ifndef __AUFS_DYNOP_H__
7727+#define __AUFS_DYNOP_H__
7728+
7729+#ifdef __KERNEL__
7730+
7731+#include <linux/fs.h>
7732+#include <linux/mm.h>
7733+#include <linux/rcupdate.h>
7734+#include <linux/aufs_type.h>
7735+#include "inode.h"
7736+
7737+enum {AuDy_AOP, AuDy_VMOP, AuDyLast};
7738+
7739+struct au_dynop {
7740+ int dy_type;
7741+ union {
7742+ const void *dy_hop;
7743+ const struct address_space_operations *dy_haop;
7744+ const struct vm_operations_struct *dy_hvmop;
7745+ };
7746+};
7747+
7748+struct au_dykey {
7749+ union {
7750+ struct list_head dk_list;
7751+ struct rcu_head dk_rcu;
7752+ };
7753+ struct au_dynop dk_op;
7754+
7755+ /*
7756+ * during I am in the branch local array, kref is gotten. when the
7757+ * branch is removed, kref is put.
7758+ */
7759+ struct kref dk_kref;
7760+};
7761+
7762+/* stop unioning since their sizes are very different from each other */
7763+struct au_dyaop {
7764+ struct au_dykey da_key;
7765+ struct address_space_operations da_op; /* not const */
7766+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
7767+ void **, unsigned long *);
7768+};
7769+
7770+struct au_dyvmop {
7771+ struct au_dykey dv_key;
7772+ struct vm_operations_struct dv_op; /* not const */
7773+};
7774+
7775+/* ---------------------------------------------------------------------- */
7776+
7777+/* dynop.c */
7778+struct au_branch;
7779+void au_dy_put(struct au_dykey *key);
7780+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
7781+ struct inode *h_inode);
b752ccd1 7782+int au_dy_irefresh(struct inode *inode);
4a4d8108
AM
7783+void au_dy_arefresh(int do_dio);
7784+const struct vm_operations_struct *
7785+au_dy_vmop(struct file *file, struct au_branch *br,
7786+ const struct vm_operations_struct *h_vmop);
7787+
7788+void __init au_dy_init(void);
7789+void au_dy_fin(void);
7790+
4a4d8108
AM
7791+#endif /* __KERNEL__ */
7792+#endif /* __AUFS_DYNOP_H__ */
7f207e10
AM
7793diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
7794--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
7795+++ linux/fs/aufs/export.c 2011-03-21 20:22:06.853935428 +0100
7796@@ -0,0 +1,803 @@
4a4d8108 7797+/*
027c5e7a 7798+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
7799+ *
7800+ * This program, aufs is free software; you can redistribute it and/or modify
7801+ * it under the terms of the GNU General Public License as published by
7802+ * the Free Software Foundation; either version 2 of the License, or
7803+ * (at your option) any later version.
7804+ *
7805+ * This program is distributed in the hope that it will be useful,
7806+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7807+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7808+ * GNU General Public License for more details.
7809+ *
7810+ * You should have received a copy of the GNU General Public License
7811+ * along with this program; if not, write to the Free Software
7812+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7813+ */
7814+
7815+/*
7816+ * export via nfs
7817+ */
7818+
7819+#include <linux/exportfs.h>
7820+#include <linux/file.h>
7821+#include <linux/mnt_namespace.h>
7822+#include <linux/namei.h>
7823+#include <linux/nsproxy.h>
7824+#include <linux/random.h>
7825+#include <linux/writeback.h>
7826+#include "aufs.h"
7827+
7828+union conv {
7829+#ifdef CONFIG_AUFS_INO_T_64
7830+ __u32 a[2];
7831+#else
7832+ __u32 a[1];
7833+#endif
7834+ ino_t ino;
7835+};
7836+
7837+static ino_t decode_ino(__u32 *a)
7838+{
7839+ union conv u;
7840+
7841+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
7842+ u.a[0] = a[0];
7843+#ifdef CONFIG_AUFS_INO_T_64
7844+ u.a[1] = a[1];
7845+#endif
7846+ return u.ino;
7847+}
7848+
7849+static void encode_ino(__u32 *a, ino_t ino)
7850+{
7851+ union conv u;
7852+
7853+ u.ino = ino;
7854+ a[0] = u.a[0];
7855+#ifdef CONFIG_AUFS_INO_T_64
7856+ a[1] = u.a[1];
7857+#endif
7858+}
7859+
7860+/* NFS file handle */
7861+enum {
7862+ Fh_br_id,
7863+ Fh_sigen,
7864+#ifdef CONFIG_AUFS_INO_T_64
7865+ /* support 64bit inode number */
7866+ Fh_ino1,
7867+ Fh_ino2,
7868+ Fh_dir_ino1,
7869+ Fh_dir_ino2,
7870+#else
7871+ Fh_ino1,
7872+ Fh_dir_ino1,
7873+#endif
7874+ Fh_igen,
7875+ Fh_h_type,
7876+ Fh_tail,
7877+
7878+ Fh_ino = Fh_ino1,
7879+ Fh_dir_ino = Fh_dir_ino1
7880+};
7881+
7882+static int au_test_anon(struct dentry *dentry)
7883+{
027c5e7a 7884+ /* note: read d_flags without d_lock */
4a4d8108
AM
7885+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
7886+}
7887+
7888+/* ---------------------------------------------------------------------- */
7889+/* inode generation external table */
7890+
b752ccd1 7891+void au_xigen_inc(struct inode *inode)
4a4d8108 7892+{
4a4d8108
AM
7893+ loff_t pos;
7894+ ssize_t sz;
7895+ __u32 igen;
7896+ struct super_block *sb;
7897+ struct au_sbinfo *sbinfo;
7898+
4a4d8108 7899+ sb = inode->i_sb;
b752ccd1 7900+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 7901+
b752ccd1 7902+ sbinfo = au_sbi(sb);
1facf9fc 7903+ pos = inode->i_ino;
7904+ pos *= sizeof(igen);
7905+ igen = inode->i_generation + 1;
1facf9fc 7906+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
7907+ sizeof(igen), &pos);
7908+ if (sz == sizeof(igen))
b752ccd1 7909+ return; /* success */
1facf9fc 7910+
b752ccd1 7911+ if (unlikely(sz >= 0))
1facf9fc 7912+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 7913+}
7914+
7915+int au_xigen_new(struct inode *inode)
7916+{
7917+ int err;
7918+ loff_t pos;
7919+ ssize_t sz;
7920+ struct super_block *sb;
7921+ struct au_sbinfo *sbinfo;
7922+ struct file *file;
7923+
7924+ err = 0;
7925+ /* todo: dirty, at mount time */
7926+ if (inode->i_ino == AUFS_ROOT_INO)
7927+ goto out;
7928+ sb = inode->i_sb;
dece6358 7929+ SiMustAnyLock(sb);
1facf9fc 7930+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7931+ goto out;
7932+
7933+ err = -EFBIG;
7934+ pos = inode->i_ino;
7935+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
7936+ AuIOErr1("too large i%lld\n", pos);
7937+ goto out;
7938+ }
7939+ pos *= sizeof(inode->i_generation);
7940+
7941+ err = 0;
7942+ sbinfo = au_sbi(sb);
7943+ file = sbinfo->si_xigen;
7944+ BUG_ON(!file);
7945+
7946+ if (i_size_read(file->f_dentry->d_inode)
7947+ < pos + sizeof(inode->i_generation)) {
7948+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
7949+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
7950+ sizeof(inode->i_generation), &pos);
7951+ } else
7952+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
7953+ sizeof(inode->i_generation), &pos);
7954+ if (sz == sizeof(inode->i_generation))
7955+ goto out; /* success */
7956+
7957+ err = sz;
7958+ if (unlikely(sz >= 0)) {
7959+ err = -EIO;
7960+ AuIOErr("xigen error (%zd)\n", sz);
7961+ }
7962+
4f0767ce 7963+out:
1facf9fc 7964+ return err;
7965+}
7966+
7967+int au_xigen_set(struct super_block *sb, struct file *base)
7968+{
7969+ int err;
7970+ struct au_sbinfo *sbinfo;
7971+ struct file *file;
7972+
dece6358
AM
7973+ SiMustWriteLock(sb);
7974+
1facf9fc 7975+ sbinfo = au_sbi(sb);
7976+ file = au_xino_create2(base, sbinfo->si_xigen);
7977+ err = PTR_ERR(file);
7978+ if (IS_ERR(file))
7979+ goto out;
7980+ err = 0;
7981+ if (sbinfo->si_xigen)
7982+ fput(sbinfo->si_xigen);
7983+ sbinfo->si_xigen = file;
7984+
4f0767ce 7985+out:
1facf9fc 7986+ return err;
7987+}
7988+
7989+void au_xigen_clr(struct super_block *sb)
7990+{
7991+ struct au_sbinfo *sbinfo;
7992+
dece6358
AM
7993+ SiMustWriteLock(sb);
7994+
1facf9fc 7995+ sbinfo = au_sbi(sb);
7996+ if (sbinfo->si_xigen) {
7997+ fput(sbinfo->si_xigen);
7998+ sbinfo->si_xigen = NULL;
7999+ }
8000+}
8001+
8002+/* ---------------------------------------------------------------------- */
8003+
8004+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
8005+ ino_t dir_ino)
8006+{
8007+ struct dentry *dentry, *d;
8008+ struct inode *inode;
8009+ unsigned int sigen;
8010+
8011+ dentry = NULL;
8012+ inode = ilookup(sb, ino);
8013+ if (!inode)
8014+ goto out;
8015+
8016+ dentry = ERR_PTR(-ESTALE);
8017+ sigen = au_sigen(sb);
8018+ if (unlikely(is_bad_inode(inode)
8019+ || IS_DEADDIR(inode)
8020+ || sigen != au_iigen(inode)))
8021+ goto out_iput;
8022+
8023+ dentry = NULL;
8024+ if (!dir_ino || S_ISDIR(inode->i_mode))
8025+ dentry = d_find_alias(inode);
8026+ else {
027c5e7a
AM
8027+ spin_lock(&inode->i_lock);
8028+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
8029+ spin_lock(&d->d_lock);
1facf9fc 8030+ if (!au_test_anon(d)
8031+ && d->d_parent->d_inode->i_ino == dir_ino) {
027c5e7a
AM
8032+ dentry = dget_dlock(d);
8033+ spin_unlock(&d->d_lock);
1facf9fc 8034+ break;
8035+ }
027c5e7a
AM
8036+ spin_unlock(&d->d_lock);
8037+ }
8038+ spin_unlock(&inode->i_lock);
1facf9fc 8039+ }
027c5e7a 8040+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
1facf9fc 8041+ dput(dentry);
8042+ dentry = ERR_PTR(-ESTALE);
8043+ }
8044+
4f0767ce 8045+out_iput:
1facf9fc 8046+ iput(inode);
4f0767ce 8047+out:
1facf9fc 8048+ return dentry;
8049+}
8050+
8051+/* ---------------------------------------------------------------------- */
8052+
8053+/* todo: dirty? */
8054+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
8055+
8056+struct au_compare_mnt_args {
8057+ /* input */
8058+ struct super_block *sb;
8059+
8060+ /* output */
8061+ struct vfsmount *mnt;
8062+};
8063+
8064+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
8065+{
8066+ struct au_compare_mnt_args *a = arg;
8067+
8068+ if (mnt->mnt_sb != a->sb)
8069+ return 0;
8070+ a->mnt = mntget(mnt);
8071+ return 1;
8072+}
8073+
1facf9fc 8074+static struct vfsmount *au_mnt_get(struct super_block *sb)
8075+{
4a4d8108
AM
8076+ int err;
8077+ struct au_compare_mnt_args args = {
8078+ .sb = sb
8079+ };
1facf9fc 8080+ struct mnt_namespace *ns;
1facf9fc 8081+
0c5527e5 8082+ br_read_lock(vfsmount_lock);
1facf9fc 8083+ /* no get/put ?? */
8084+ AuDebugOn(!current->nsproxy);
8085+ ns = current->nsproxy->mnt_ns;
8086+ AuDebugOn(!ns);
4a4d8108 8087+ err = iterate_mounts(au_compare_mnt, &args, ns->root);
0c5527e5 8088+ br_read_unlock(vfsmount_lock);
4a4d8108
AM
8089+ AuDebugOn(!err);
8090+ AuDebugOn(!args.mnt);
8091+ return args.mnt;
1facf9fc 8092+}
8093+
8094+struct au_nfsd_si_lock {
4a4d8108 8095+ unsigned int sigen;
027c5e7a 8096+ aufs_bindex_t bindex, br_id;
1facf9fc 8097+ unsigned char force_lock;
8098+};
8099+
027c5e7a
AM
8100+static int si_nfsd_read_lock(struct super_block *sb,
8101+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 8102+{
027c5e7a 8103+ int err;
1facf9fc 8104+ aufs_bindex_t bindex;
8105+
8106+ si_read_lock(sb, AuLock_FLUSH);
8107+
8108+ /* branch id may be wrapped around */
027c5e7a 8109+ err = 0;
1facf9fc 8110+ bindex = au_br_index(sb, nsi_lock->br_id);
8111+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
8112+ goto out; /* success */
8113+
027c5e7a
AM
8114+ err = -ESTALE;
8115+ bindex = -1;
1facf9fc 8116+ if (!nsi_lock->force_lock)
8117+ si_read_unlock(sb);
1facf9fc 8118+
4f0767ce 8119+out:
027c5e7a
AM
8120+ nsi_lock->bindex = bindex;
8121+ return err;
1facf9fc 8122+}
8123+
8124+struct find_name_by_ino {
8125+ int called, found;
8126+ ino_t ino;
8127+ char *name;
8128+ int namelen;
8129+};
8130+
8131+static int
8132+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
8133+ u64 ino, unsigned int d_type)
8134+{
8135+ struct find_name_by_ino *a = arg;
8136+
8137+ a->called++;
8138+ if (a->ino != ino)
8139+ return 0;
8140+
8141+ memcpy(a->name, name, namelen);
8142+ a->namelen = namelen;
8143+ a->found = 1;
8144+ return 1;
8145+}
8146+
8147+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
8148+ struct au_nfsd_si_lock *nsi_lock)
8149+{
8150+ struct dentry *dentry, *parent;
8151+ struct file *file;
8152+ struct inode *dir;
8153+ struct find_name_by_ino arg;
8154+ int err;
8155+
8156+ parent = path->dentry;
8157+ if (nsi_lock)
8158+ si_read_unlock(parent->d_sb);
4a4d8108 8159+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 8160+ dentry = (void *)file;
8161+ if (IS_ERR(file))
8162+ goto out;
8163+
8164+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 8165+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 8166+ if (unlikely(!arg.name))
8167+ goto out_file;
8168+ arg.ino = ino;
8169+ arg.found = 0;
8170+ do {
8171+ arg.called = 0;
8172+ /* smp_mb(); */
8173+ err = vfsub_readdir(file, find_name_by_ino, &arg);
8174+ } while (!err && !arg.found && arg.called);
8175+ dentry = ERR_PTR(err);
8176+ if (unlikely(err))
8177+ goto out_name;
8178+ dentry = ERR_PTR(-ENOENT);
8179+ if (!arg.found)
8180+ goto out_name;
8181+
8182+ /* do not call au_lkup_one() */
8183+ dir = parent->d_inode;
8184+ mutex_lock(&dir->i_mutex);
8185+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
8186+ mutex_unlock(&dir->i_mutex);
8187+ AuTraceErrPtr(dentry);
8188+ if (IS_ERR(dentry))
8189+ goto out_name;
8190+ AuDebugOn(au_test_anon(dentry));
8191+ if (unlikely(!dentry->d_inode)) {
8192+ dput(dentry);
8193+ dentry = ERR_PTR(-ENOENT);
8194+ }
8195+
4f0767ce 8196+out_name:
1facf9fc 8197+ __putname(arg.name);
4f0767ce 8198+out_file:
1facf9fc 8199+ fput(file);
4f0767ce 8200+out:
1facf9fc 8201+ if (unlikely(nsi_lock
8202+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
8203+ if (!IS_ERR(dentry)) {
8204+ dput(dentry);
8205+ dentry = ERR_PTR(-ESTALE);
8206+ }
8207+ AuTraceErrPtr(dentry);
8208+ return dentry;
8209+}
8210+
8211+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
8212+ ino_t dir_ino,
8213+ struct au_nfsd_si_lock *nsi_lock)
8214+{
8215+ struct dentry *dentry;
8216+ struct path path;
8217+
8218+ if (dir_ino != AUFS_ROOT_INO) {
8219+ path.dentry = decode_by_ino(sb, dir_ino, 0);
8220+ dentry = path.dentry;
8221+ if (!path.dentry || IS_ERR(path.dentry))
8222+ goto out;
8223+ AuDebugOn(au_test_anon(path.dentry));
8224+ } else
8225+ path.dentry = dget(sb->s_root);
8226+
8227+ path.mnt = au_mnt_get(sb);
8228+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
8229+ path_put(&path);
8230+
4f0767ce 8231+out:
1facf9fc 8232+ AuTraceErrPtr(dentry);
8233+ return dentry;
8234+}
8235+
8236+/* ---------------------------------------------------------------------- */
8237+
8238+static int h_acceptable(void *expv, struct dentry *dentry)
8239+{
8240+ return 1;
8241+}
8242+
8243+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
8244+ char *buf, int len, struct super_block *sb)
8245+{
8246+ char *p;
8247+ int n;
8248+ struct path path;
8249+
8250+ p = d_path(h_rootpath, buf, len);
8251+ if (IS_ERR(p))
8252+ goto out;
8253+ n = strlen(p);
8254+
8255+ path.mnt = h_rootpath->mnt;
8256+ path.dentry = h_parent;
8257+ p = d_path(&path, buf, len);
8258+ if (IS_ERR(p))
8259+ goto out;
8260+ if (n != 1)
8261+ p += n;
8262+
8263+ path.mnt = au_mnt_get(sb);
8264+ path.dentry = sb->s_root;
8265+ p = d_path(&path, buf, len - strlen(p));
8266+ mntput(path.mnt);
8267+ if (IS_ERR(p))
8268+ goto out;
8269+ if (n != 1)
8270+ p[strlen(p)] = '/';
8271+
4f0767ce 8272+out:
1facf9fc 8273+ AuTraceErrPtr(p);
8274+ return p;
8275+}
8276+
8277+static
027c5e7a
AM
8278+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
8279+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 8280+{
8281+ struct dentry *dentry, *h_parent, *root;
8282+ struct super_block *h_sb;
8283+ char *pathname, *p;
8284+ struct vfsmount *h_mnt;
8285+ struct au_branch *br;
8286+ int err;
8287+ struct path path;
8288+
027c5e7a 8289+ br = au_sbr(sb, nsi_lock->bindex);
1facf9fc 8290+ h_mnt = br->br_mnt;
8291+ h_sb = h_mnt->mnt_sb;
8292+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
8293+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
8294+ fh_len - Fh_tail, fh[Fh_h_type],
8295+ h_acceptable, /*context*/NULL);
8296+ dentry = h_parent;
8297+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
8298+ AuWarn1("%s decode_fh failed, %ld\n",
8299+ au_sbtype(h_sb), PTR_ERR(h_parent));
8300+ goto out;
8301+ }
8302+ dentry = NULL;
8303+ if (unlikely(au_test_anon(h_parent))) {
8304+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
8305+ au_sbtype(h_sb));
8306+ goto out_h_parent;
8307+ }
8308+
8309+ dentry = ERR_PTR(-ENOMEM);
8310+ pathname = (void *)__get_free_page(GFP_NOFS);
8311+ if (unlikely(!pathname))
8312+ goto out_h_parent;
8313+
8314+ root = sb->s_root;
8315+ path.mnt = h_mnt;
8316+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 8317+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 8318+ di_read_unlock(root, !AuLock_IR);
8319+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
8320+ dentry = (void *)p;
8321+ if (IS_ERR(p))
8322+ goto out_pathname;
8323+
8324+ si_read_unlock(sb);
8325+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
8326+ dentry = ERR_PTR(err);
8327+ if (unlikely(err))
8328+ goto out_relock;
8329+
8330+ dentry = ERR_PTR(-ENOENT);
8331+ AuDebugOn(au_test_anon(path.dentry));
8332+ if (unlikely(!path.dentry->d_inode))
8333+ goto out_path;
8334+
8335+ if (ino != path.dentry->d_inode->i_ino)
8336+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
8337+ else
8338+ dentry = dget(path.dentry);
8339+
4f0767ce 8340+out_path:
1facf9fc 8341+ path_put(&path);
4f0767ce 8342+out_relock:
1facf9fc 8343+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
8344+ if (!IS_ERR(dentry)) {
8345+ dput(dentry);
8346+ dentry = ERR_PTR(-ESTALE);
8347+ }
4f0767ce 8348+out_pathname:
1facf9fc 8349+ free_page((unsigned long)pathname);
4f0767ce 8350+out_h_parent:
1facf9fc 8351+ dput(h_parent);
4f0767ce 8352+out:
1facf9fc 8353+ AuTraceErrPtr(dentry);
8354+ return dentry;
8355+}
8356+
8357+/* ---------------------------------------------------------------------- */
8358+
8359+static struct dentry *
8360+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
8361+ int fh_type)
8362+{
8363+ struct dentry *dentry;
8364+ __u32 *fh = fid->raw;
027c5e7a 8365+ struct au_branch *br;
1facf9fc 8366+ ino_t ino, dir_ino;
1facf9fc 8367+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 8368+ .force_lock = 0
8369+ };
8370+
1facf9fc 8371+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
8372+ /* it should never happen, but the file handle is unreliable */
8373+ if (unlikely(fh_len < Fh_tail))
8374+ goto out;
8375+ nsi_lock.sigen = fh[Fh_sigen];
8376+ nsi_lock.br_id = fh[Fh_br_id];
8377+
1facf9fc 8378+ /* branch id may be wrapped around */
027c5e7a
AM
8379+ br = NULL;
8380+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 8381+ goto out;
8382+ nsi_lock.force_lock = 1;
8383+
8384+ /* is this inode still cached? */
8385+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
8386+ /* it should never happen */
8387+ if (unlikely(ino == AUFS_ROOT_INO))
8388+ goto out;
8389+
1facf9fc 8390+ dir_ino = decode_ino(fh + Fh_dir_ino);
8391+ dentry = decode_by_ino(sb, ino, dir_ino);
8392+ if (IS_ERR(dentry))
8393+ goto out_unlock;
8394+ if (dentry)
8395+ goto accept;
8396+
8397+ /* is the parent dir cached? */
027c5e7a
AM
8398+ br = au_sbr(sb, nsi_lock.bindex);
8399+ atomic_inc(&br->br_count);
1facf9fc 8400+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
8401+ if (IS_ERR(dentry))
8402+ goto out_unlock;
8403+ if (dentry)
8404+ goto accept;
8405+
8406+ /* lookup path */
027c5e7a 8407+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 8408+ if (IS_ERR(dentry))
8409+ goto out_unlock;
8410+ if (unlikely(!dentry))
8411+ /* todo?: make it ESTALE */
8412+ goto out_unlock;
8413+
4f0767ce 8414+accept:
027c5e7a
AM
8415+ if (!au_digen_test(dentry, au_sigen(sb))
8416+ && dentry->d_inode->i_generation == fh[Fh_igen])
1facf9fc 8417+ goto out_unlock; /* success */
8418+
8419+ dput(dentry);
8420+ dentry = ERR_PTR(-ESTALE);
4f0767ce 8421+out_unlock:
027c5e7a
AM
8422+ if (br)
8423+ atomic_dec(&br->br_count);
1facf9fc 8424+ si_read_unlock(sb);
4f0767ce 8425+out:
1facf9fc 8426+ AuTraceErrPtr(dentry);
8427+ return dentry;
8428+}
8429+
8430+#if 0 /* reserved for future use */
8431+/* support subtreecheck option */
8432+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
8433+ int fh_len, int fh_type)
8434+{
8435+ struct dentry *parent;
8436+ __u32 *fh = fid->raw;
8437+ ino_t dir_ino;
8438+
8439+ dir_ino = decode_ino(fh + Fh_dir_ino);
8440+ parent = decode_by_ino(sb, dir_ino, 0);
8441+ if (IS_ERR(parent))
8442+ goto out;
8443+ if (!parent)
8444+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
8445+ dir_ino, fh, fh_len);
8446+
4f0767ce 8447+out:
1facf9fc 8448+ AuTraceErrPtr(parent);
8449+ return parent;
8450+}
8451+#endif
8452+
8453+/* ---------------------------------------------------------------------- */
8454+
8455+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
8456+ int connectable)
8457+{
8458+ int err;
8459+ aufs_bindex_t bindex, bend;
8460+ struct super_block *sb, *h_sb;
8461+ struct inode *inode;
8462+ struct dentry *parent, *h_parent;
8463+ struct au_branch *br;
8464+
8465+ AuDebugOn(au_test_anon(dentry));
8466+
8467+ parent = NULL;
8468+ err = -ENOSPC;
8469+ if (unlikely(*max_len <= Fh_tail)) {
8470+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
8471+ goto out;
8472+ }
8473+
8474+ err = FILEID_ROOT;
8475+ if (IS_ROOT(dentry)) {
8476+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
8477+ goto out;
8478+ }
8479+
1facf9fc 8480+ h_parent = NULL;
027c5e7a
AM
8481+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR | AuLock_GEN);
8482+ if (unlikely(err))
8483+ goto out;
8484+
1facf9fc 8485+ inode = dentry->d_inode;
8486+ AuDebugOn(!inode);
027c5e7a 8487+ sb = dentry->d_sb;
1facf9fc 8488+#ifdef CONFIG_AUFS_DEBUG
8489+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
8490+ AuWarn1("NFS-exporting requires xino\n");
8491+#endif
027c5e7a
AM
8492+ err = -EIO;
8493+ parent = dget_parent(dentry);
8494+ di_read_lock_parent(parent, !AuLock_IR);
1facf9fc 8495+ bend = au_dbtaildir(parent);
8496+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
8497+ h_parent = au_h_dptr(parent, bindex);
8498+ if (h_parent) {
8499+ dget(h_parent);
8500+ break;
8501+ }
8502+ }
8503+ if (unlikely(!h_parent))
8504+ goto out_unlock;
8505+
8506+ err = -EPERM;
8507+ br = au_sbr(sb, bindex);
8508+ h_sb = br->br_mnt->mnt_sb;
8509+ if (unlikely(!h_sb->s_export_op)) {
8510+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
8511+ goto out_dput;
8512+ }
8513+
8514+ fh[Fh_br_id] = br->br_id;
8515+ fh[Fh_sigen] = au_sigen(sb);
8516+ encode_ino(fh + Fh_ino, inode->i_ino);
8517+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
8518+ fh[Fh_igen] = inode->i_generation;
8519+
8520+ *max_len -= Fh_tail;
8521+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
8522+ max_len,
8523+ /*connectable or subtreecheck*/0);
8524+ err = fh[Fh_h_type];
8525+ *max_len += Fh_tail;
8526+ /* todo: macros? */
8527+ if (err != 255)
8528+ err = 99;
8529+ else
8530+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
8531+
4f0767ce 8532+out_dput:
1facf9fc 8533+ dput(h_parent);
4f0767ce 8534+out_unlock:
1facf9fc 8535+ di_read_unlock(parent, !AuLock_IR);
8536+ dput(parent);
8537+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 8538+out:
1facf9fc 8539+ if (unlikely(err < 0))
8540+ err = 255;
8541+ return err;
8542+}
8543+
8544+/* ---------------------------------------------------------------------- */
8545+
4a4d8108
AM
8546+static int aufs_commit_metadata(struct inode *inode)
8547+{
8548+ int err;
8549+ aufs_bindex_t bindex;
8550+ struct super_block *sb;
8551+ struct inode *h_inode;
8552+ int (*f)(struct inode *inode);
8553+
8554+ sb = inode->i_sb;
e49829fe 8555+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
8556+ ii_write_lock_child(inode);
8557+ bindex = au_ibstart(inode);
8558+ AuDebugOn(bindex < 0);
8559+ h_inode = au_h_iptr(inode, bindex);
8560+
8561+ f = h_inode->i_sb->s_export_op->commit_metadata;
8562+ if (f)
8563+ err = f(h_inode);
8564+ else {
8565+ struct writeback_control wbc = {
8566+ .sync_mode = WB_SYNC_ALL,
8567+ .nr_to_write = 0 /* metadata only */
8568+ };
8569+
8570+ err = sync_inode(h_inode, &wbc);
8571+ }
8572+
8573+ au_cpup_attr_timesizes(inode);
8574+ ii_write_unlock(inode);
8575+ si_read_unlock(sb);
8576+ return err;
8577+}
8578+
8579+/* ---------------------------------------------------------------------- */
8580+
1facf9fc 8581+static struct export_operations aufs_export_op = {
4a4d8108 8582+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 8583+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
8584+ .encode_fh = aufs_encode_fh,
8585+ .commit_metadata = aufs_commit_metadata
1facf9fc 8586+};
8587+
8588+void au_export_init(struct super_block *sb)
8589+{
8590+ struct au_sbinfo *sbinfo;
8591+ __u32 u;
8592+
8593+ sb->s_export_op = &aufs_export_op;
8594+ sbinfo = au_sbi(sb);
8595+ sbinfo->si_xigen = NULL;
8596+ get_random_bytes(&u, sizeof(u));
8597+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
8598+ atomic_set(&sbinfo->si_xigen_next, u);
8599+}
7f207e10
AM
8600diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
8601--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
8602+++ linux/fs/aufs/file.c 2011-03-21 20:22:06.853935428 +0100
8603@@ -0,0 +1,679 @@
1facf9fc 8604+/*
027c5e7a 8605+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 8606+ *
8607+ * This program, aufs is free software; you can redistribute it and/or modify
8608+ * it under the terms of the GNU General Public License as published by
8609+ * the Free Software Foundation; either version 2 of the License, or
8610+ * (at your option) any later version.
dece6358
AM
8611+ *
8612+ * This program is distributed in the hope that it will be useful,
8613+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8614+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8615+ * GNU General Public License for more details.
8616+ *
8617+ * You should have received a copy of the GNU General Public License
8618+ * along with this program; if not, write to the Free Software
8619+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8620+ */
8621+
8622+/*
4a4d8108 8623+ * handling file/dir, and address_space operation
1facf9fc 8624+ */
8625+
dece6358 8626+#include <linux/file.h>
4a4d8108
AM
8627+#include <linux/fsnotify.h>
8628+#include <linux/namei.h>
8629+#include <linux/pagemap.h>
1facf9fc 8630+#include "aufs.h"
8631+
4a4d8108
AM
8632+/* drop flags for writing */
8633+unsigned int au_file_roflags(unsigned int flags)
8634+{
8635+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
8636+ flags |= O_RDONLY | O_NOATIME;
8637+ return flags;
8638+}
8639+
8640+/* common functions to regular file and dir */
8641+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8642+ struct file *file)
1facf9fc 8643+{
1308ab2a 8644+ struct file *h_file;
4a4d8108
AM
8645+ struct dentry *h_dentry;
8646+ struct inode *h_inode;
8647+ struct super_block *sb;
8648+ struct au_branch *br;
8649+ struct path h_path;
8650+ int err, exec_flag;
1facf9fc 8651+
4a4d8108
AM
8652+ /* a race condition can happen between open and unlink/rmdir */
8653+ h_file = ERR_PTR(-ENOENT);
8654+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 8655+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
8656+ goto out;
8657+ h_inode = h_dentry->d_inode;
b752ccd1 8658+ if (au_test_nfsd() && !h_inode)
4a4d8108 8659+ goto out;
027c5e7a
AM
8660+ spin_lock(&h_dentry->d_lock);
8661+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
8662+ || !h_inode
8663+ /* || !dentry->d_inode->i_nlink */
8664+ ;
8665+ spin_unlock(&h_dentry->d_lock);
8666+ if (unlikely(err))
4a4d8108 8667+ goto out;
1facf9fc 8668+
4a4d8108
AM
8669+ sb = dentry->d_sb;
8670+ br = au_sbr(sb, bindex);
8671+ h_file = ERR_PTR(-EACCES);
8672+ exec_flag = flags & vfsub_fmode_to_uint(FMODE_EXEC);
8673+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
027c5e7a 8674+ goto out;
1facf9fc 8675+
4a4d8108
AM
8676+ /* drop flags for writing */
8677+ if (au_test_ro(sb, bindex, dentry->d_inode))
8678+ flags = au_file_roflags(flags);
8679+ flags &= ~O_CREAT;
8680+ atomic_inc(&br->br_count);
8681+ h_path.dentry = h_dentry;
8682+ h_path.mnt = br->br_mnt;
8683+ if (!au_special_file(h_inode->i_mode))
8684+ h_file = vfsub_dentry_open(&h_path, flags);
8685+ else {
8686+ /* this block depends upon the configuration */
8687+ di_read_unlock(dentry, AuLock_IR);
8688+ fi_write_unlock(file);
8689+ si_read_unlock(sb);
8690+ h_file = vfsub_dentry_open(&h_path, flags);
8691+ si_noflush_read_lock(sb);
8692+ fi_write_lock(file);
8693+ di_read_lock_child(dentry, AuLock_IR);
dece6358 8694+ }
4a4d8108
AM
8695+ if (IS_ERR(h_file))
8696+ goto out_br;
dece6358 8697+
4a4d8108
AM
8698+ if (exec_flag) {
8699+ err = deny_write_access(h_file);
8700+ if (unlikely(err)) {
8701+ fput(h_file);
8702+ h_file = ERR_PTR(err);
8703+ goto out_br;
8704+ }
8705+ }
953406b4 8706+ fsnotify_open(h_file);
4a4d8108 8707+ goto out; /* success */
1facf9fc 8708+
4f0767ce 8709+out_br:
4a4d8108 8710+ atomic_dec(&br->br_count);
4f0767ce 8711+out:
4a4d8108
AM
8712+ return h_file;
8713+}
1308ab2a 8714+
4a4d8108
AM
8715+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8716+ struct au_fidir *fidir)
1facf9fc 8717+{
dece6358 8718+ int err;
1facf9fc 8719+ struct dentry *dentry;
1308ab2a 8720+
4a4d8108
AM
8721+ err = au_finfo_init(file, fidir);
8722+ if (unlikely(err))
8723+ goto out;
1facf9fc 8724+
8725+ dentry = file->f_dentry;
4a4d8108
AM
8726+ di_read_lock_child(dentry, AuLock_IR);
8727+ err = open(file, vfsub_file_flags(file));
8728+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 8729+
4a4d8108
AM
8730+ fi_write_unlock(file);
8731+ if (unlikely(err)) {
8732+ au_fi(file)->fi_hdir = NULL;
8733+ au_finfo_fin(file);
1308ab2a 8734+ }
4a4d8108 8735+
4f0767ce 8736+out:
1308ab2a 8737+ return err;
8738+}
dece6358 8739+
4a4d8108 8740+int au_reopen_nondir(struct file *file)
1308ab2a 8741+{
4a4d8108
AM
8742+ int err;
8743+ aufs_bindex_t bstart;
8744+ struct dentry *dentry;
8745+ struct file *h_file, *h_file_tmp;
1308ab2a 8746+
4a4d8108
AM
8747+ dentry = file->f_dentry;
8748+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
8749+ bstart = au_dbstart(dentry);
8750+ h_file_tmp = NULL;
8751+ if (au_fbstart(file) == bstart) {
8752+ h_file = au_hf_top(file);
8753+ if (file->f_mode == h_file->f_mode)
8754+ return 0; /* success */
8755+ h_file_tmp = h_file;
8756+ get_file(h_file_tmp);
8757+ au_set_h_fptr(file, bstart, NULL);
8758+ }
8759+ AuDebugOn(au_fi(file)->fi_hdir);
8760+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 8761+
4a4d8108
AM
8762+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
8763+ file);
8764+ err = PTR_ERR(h_file);
8765+ if (IS_ERR(h_file))
8766+ goto out; /* todo: close all? */
8767+
8768+ err = 0;
8769+ au_set_fbstart(file, bstart);
8770+ au_set_h_fptr(file, bstart, h_file);
8771+ au_update_figen(file);
8772+ /* todo: necessary? */
8773+ /* file->f_ra = h_file->f_ra; */
8774+
4f0767ce 8775+out:
4a4d8108
AM
8776+ if (h_file_tmp)
8777+ fput(h_file_tmp);
8778+ return err;
1facf9fc 8779+}
8780+
1308ab2a 8781+/* ---------------------------------------------------------------------- */
8782+
4a4d8108
AM
8783+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
8784+ struct dentry *hi_wh)
1facf9fc 8785+{
4a4d8108
AM
8786+ int err;
8787+ aufs_bindex_t bstart;
8788+ struct au_dinfo *dinfo;
8789+ struct dentry *h_dentry;
8790+ struct au_hdentry *hdp;
1facf9fc 8791+
4a4d8108
AM
8792+ dinfo = au_di(file->f_dentry);
8793+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 8794+
4a4d8108
AM
8795+ bstart = dinfo->di_bstart;
8796+ dinfo->di_bstart = btgt;
8797+ hdp = dinfo->di_hdentry;
8798+ h_dentry = hdp[0 + btgt].hd_dentry;
8799+ hdp[0 + btgt].hd_dentry = hi_wh;
8800+ err = au_reopen_nondir(file);
8801+ hdp[0 + btgt].hd_dentry = h_dentry;
8802+ dinfo->di_bstart = bstart;
1facf9fc 8803+
1facf9fc 8804+ return err;
8805+}
8806+
4a4d8108
AM
8807+static int au_ready_to_write_wh(struct file *file, loff_t len,
8808+ aufs_bindex_t bcpup)
1facf9fc 8809+{
4a4d8108 8810+ int err;
027c5e7a
AM
8811+ struct inode *inode, *h_inode;
8812+ struct dentry *dentry, *h_dentry, *hi_wh;
1facf9fc 8813+
dece6358 8814+ dentry = file->f_dentry;
4a4d8108 8815+ au_update_dbstart(dentry);
dece6358 8816+ inode = dentry->d_inode;
027c5e7a
AM
8817+ h_inode = NULL;
8818+ if (au_dbstart(dentry) <= bcpup && au_dbend(dentry) >= bcpup) {
8819+ h_dentry = au_h_dptr(dentry, bcpup);
8820+ if (h_dentry)
8821+ h_inode = h_dentry->d_inode;
8822+ }
4a4d8108 8823+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 8824+ if (!hi_wh && !h_inode)
4a4d8108
AM
8825+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
8826+ else
8827+ /* already copied-up after unlink */
8828+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 8829+
4a4d8108
AM
8830+ if (!err
8831+ && inode->i_nlink > 1
8832+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
8833+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 8834+
dece6358 8835+ return err;
1facf9fc 8836+}
8837+
4a4d8108
AM
8838+/*
8839+ * prepare the @file for writing.
8840+ */
8841+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 8842+{
4a4d8108 8843+ int err;
027c5e7a 8844+ aufs_bindex_t bstart, bcpup, dbstart;
4a4d8108
AM
8845+ struct dentry *dentry, *parent, *h_dentry;
8846+ struct inode *h_inode, *inode;
1facf9fc 8847+ struct super_block *sb;
4a4d8108 8848+ struct file *h_file;
1facf9fc 8849+
8850+ dentry = file->f_dentry;
1facf9fc 8851+ sb = dentry->d_sb;
4a4d8108
AM
8852+ inode = dentry->d_inode;
8853+ AuDebugOn(au_special_file(inode->i_mode));
8854+ bstart = au_fbstart(file);
8855+ err = au_test_ro(sb, bstart, inode);
8856+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
8857+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 8858+ goto out;
4a4d8108 8859+ }
1facf9fc 8860+
027c5e7a 8861+ /* need to cpup or reopen */
4a4d8108
AM
8862+ parent = dget_parent(dentry);
8863+ di_write_lock_parent(parent);
8864+ err = AuWbrCopyup(au_sbi(sb), dentry);
8865+ bcpup = err;
8866+ if (unlikely(err < 0))
8867+ goto out_dgrade;
8868+ err = 0;
8869+
027c5e7a 8870+ if (!d_unhashed(dentry) && !au_h_dptr(parent, bcpup)) {
4a4d8108 8871+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 8872+ if (unlikely(err))
4a4d8108
AM
8873+ goto out_dgrade;
8874+ }
8875+
8876+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
8877+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8878+ if (unlikely(err))
8879+ goto out_dgrade;
8880+
8881+ h_dentry = au_hf_top(file)->f_dentry;
8882+ h_inode = h_dentry->d_inode;
027c5e7a
AM
8883+ dbstart = au_dbstart(dentry);
8884+ if (dbstart <= bcpup) {
8885+ h_dentry = au_h_dptr(dentry, bcpup);
8886+ AuDebugOn(!h_dentry);
8887+ h_inode = h_dentry->d_inode;
8888+ AuDebugOn(!h_inode);
8889+ bstart = bcpup;
8890+ }
8891+
8892+ if (dbstart <= bcpup /* just reopen */
8893+ || !d_unhashed(dentry) /* copyup and reopen */
8894+ ) {
8895+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8896+ h_file = au_h_open_pre(dentry, bstart);
8897+ if (IS_ERR(h_file)) {
8898+ err = PTR_ERR(h_file);
8899+ h_file = NULL;
8900+ } else {
8901+ di_downgrade_lock(parent, AuLock_IR);
8902+ if (dbstart > bcpup)
8903+ err = au_sio_cpup_simple(dentry, bcpup, len,
8904+ AuCpup_DTIME);
8905+ if (!err)
8906+ err = au_reopen_nondir(file);
8907+ }
8908+ mutex_unlock(&h_inode->i_mutex);
8909+ au_h_open_post(dentry, bstart, h_file);
8910+ } else { /* copyup as wh and reopen */
8911+ /*
8912+ * since writable hfsplus branch is not supported,
8913+ * h_open_pre/post() are unnecessary.
8914+ */
8915+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108
AM
8916+ err = au_ready_to_write_wh(file, len, bcpup);
8917+ di_downgrade_lock(parent, AuLock_IR);
027c5e7a 8918+ mutex_unlock(&h_inode->i_mutex);
4a4d8108 8919+ }
4a4d8108
AM
8920+
8921+ if (!err) {
8922+ au_pin_set_parent_lflag(pin, /*lflag*/0);
8923+ goto out_dput; /* success */
8924+ }
8925+ au_unpin(pin);
8926+ goto out_unlock;
1facf9fc 8927+
4f0767ce 8928+out_dgrade:
4a4d8108 8929+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 8930+out_unlock:
4a4d8108 8931+ di_read_unlock(parent, AuLock_IR);
4f0767ce 8932+out_dput:
4a4d8108 8933+ dput(parent);
4f0767ce 8934+out:
1facf9fc 8935+ return err;
8936+}
8937+
4a4d8108
AM
8938+/* ---------------------------------------------------------------------- */
8939+
8940+int au_do_flush(struct file *file, fl_owner_t id,
8941+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 8942+{
4a4d8108 8943+ int err;
1308ab2a 8944+ struct dentry *dentry;
1facf9fc 8945+ struct super_block *sb;
4a4d8108 8946+ struct inode *inode;
1facf9fc 8947+
1facf9fc 8948+ dentry = file->f_dentry;
8949+ sb = dentry->d_sb;
dece6358 8950+ inode = dentry->d_inode;
4a4d8108
AM
8951+ si_noflush_read_lock(sb);
8952+ fi_read_lock(file);
b752ccd1 8953+ ii_read_lock_child(inode);
1facf9fc 8954+
4a4d8108
AM
8955+ err = flush(file, id);
8956+ au_cpup_attr_timesizes(inode);
1facf9fc 8957+
b752ccd1 8958+ ii_read_unlock(inode);
4a4d8108 8959+ fi_read_unlock(file);
1308ab2a 8960+ si_read_unlock(sb);
dece6358 8961+ return err;
1facf9fc 8962+}
8963+
4a4d8108
AM
8964+/* ---------------------------------------------------------------------- */
8965+
8966+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 8967+{
4a4d8108
AM
8968+ int err;
8969+ aufs_bindex_t bstart;
8970+ struct au_pin pin;
8971+ struct au_finfo *finfo;
8972+ struct dentry *dentry, *parent, *hi_wh;
8973+ struct inode *inode;
1facf9fc 8974+ struct super_block *sb;
8975+
4a4d8108
AM
8976+ FiMustWriteLock(file);
8977+
8978+ err = 0;
8979+ finfo = au_fi(file);
1308ab2a 8980+ dentry = file->f_dentry;
8981+ sb = dentry->d_sb;
4a4d8108
AM
8982+ inode = dentry->d_inode;
8983+ bstart = au_ibstart(inode);
027c5e7a 8984+ if (bstart == finfo->fi_btop || IS_ROOT(dentry))
1308ab2a 8985+ goto out;
dece6358 8986+
4a4d8108
AM
8987+ parent = dget_parent(dentry);
8988+ if (au_test_ro(sb, bstart, inode)) {
8989+ di_read_lock_parent(parent, !AuLock_IR);
8990+ err = AuWbrCopyup(au_sbi(sb), dentry);
8991+ bstart = err;
8992+ di_read_unlock(parent, !AuLock_IR);
8993+ if (unlikely(err < 0))
8994+ goto out_parent;
8995+ err = 0;
1facf9fc 8996+ }
1facf9fc 8997+
4a4d8108
AM
8998+ di_read_lock_parent(parent, AuLock_IR);
8999+ hi_wh = au_hi_wh(inode, bstart);
7f207e10
AM
9000+ if (!S_ISDIR(inode->i_mode)
9001+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108
AM
9002+ && au_plink_test(inode)
9003+ && !d_unhashed(dentry)) {
9004+ err = au_test_and_cpup_dirs(dentry, bstart);
9005+ if (unlikely(err))
9006+ goto out_unlock;
9007+
9008+ /* always superio. */
9009+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
9010+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
9011+ if (!err)
9012+ err = au_sio_cpup_simple(dentry, bstart, -1,
9013+ AuCpup_DTIME);
9014+ au_unpin(&pin);
9015+ } else if (hi_wh) {
9016+ /* already copied-up after unlink */
9017+ err = au_reopen_wh(file, bstart, hi_wh);
9018+ *need_reopen = 0;
9019+ }
1facf9fc 9020+
4f0767ce 9021+out_unlock:
4a4d8108 9022+ di_read_unlock(parent, AuLock_IR);
4f0767ce 9023+out_parent:
4a4d8108 9024+ dput(parent);
4f0767ce 9025+out:
1308ab2a 9026+ return err;
dece6358 9027+}
1facf9fc 9028+
4a4d8108 9029+static void au_do_refresh_dir(struct file *file)
dece6358 9030+{
4a4d8108
AM
9031+ aufs_bindex_t bindex, bend, new_bindex, brid;
9032+ struct au_hfile *p, tmp, *q;
9033+ struct au_finfo *finfo;
1308ab2a 9034+ struct super_block *sb;
4a4d8108 9035+ struct au_fidir *fidir;
1facf9fc 9036+
4a4d8108 9037+ FiMustWriteLock(file);
1facf9fc 9038+
4a4d8108
AM
9039+ sb = file->f_dentry->d_sb;
9040+ finfo = au_fi(file);
9041+ fidir = finfo->fi_hdir;
9042+ AuDebugOn(!fidir);
9043+ p = fidir->fd_hfile + finfo->fi_btop;
9044+ brid = p->hf_br->br_id;
9045+ bend = fidir->fd_bbot;
9046+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
9047+ if (!p->hf_file)
9048+ continue;
1308ab2a 9049+
4a4d8108
AM
9050+ new_bindex = au_br_index(sb, p->hf_br->br_id);
9051+ if (new_bindex == bindex)
9052+ continue;
9053+ if (new_bindex < 0) {
9054+ au_set_h_fptr(file, bindex, NULL);
9055+ continue;
9056+ }
1308ab2a 9057+
4a4d8108
AM
9058+ /* swap two lower inode, and loop again */
9059+ q = fidir->fd_hfile + new_bindex;
9060+ tmp = *q;
9061+ *q = *p;
9062+ *p = tmp;
9063+ if (tmp.hf_file) {
9064+ bindex--;
9065+ p--;
9066+ }
9067+ }
1308ab2a 9068+
4a4d8108 9069+ p = fidir->fd_hfile;
027c5e7a 9070+ if (!au_test_mmapped(file) && !d_unlinked(file->f_dentry)) {
4a4d8108
AM
9071+ bend = au_sbend(sb);
9072+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
9073+ finfo->fi_btop++, p++)
9074+ if (p->hf_file) {
9075+ if (p->hf_file->f_dentry
9076+ && p->hf_file->f_dentry->d_inode)
9077+ break;
9078+ else
9079+ au_hfput(p, file);
9080+ }
9081+ } else {
9082+ bend = au_br_index(sb, brid);
9083+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
9084+ finfo->fi_btop++, p++)
9085+ if (p->hf_file)
9086+ au_hfput(p, file);
9087+ bend = au_sbend(sb);
9088+ }
1308ab2a 9089+
4a4d8108
AM
9090+ p = fidir->fd_hfile + bend;
9091+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
9092+ fidir->fd_bbot--, p--)
9093+ if (p->hf_file) {
9094+ if (p->hf_file->f_dentry
9095+ && p->hf_file->f_dentry->d_inode)
9096+ break;
9097+ else
9098+ au_hfput(p, file);
9099+ }
9100+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 9101+}
9102+
4a4d8108
AM
9103+/*
9104+ * after branch manipulating, refresh the file.
9105+ */
9106+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 9107+{
4a4d8108
AM
9108+ int err, need_reopen;
9109+ aufs_bindex_t bend, bindex;
9110+ struct dentry *dentry;
1308ab2a 9111+ struct au_finfo *finfo;
4a4d8108 9112+ struct au_hfile *hfile;
1facf9fc 9113+
4a4d8108 9114+ dentry = file->f_dentry;
1308ab2a 9115+ finfo = au_fi(file);
4a4d8108
AM
9116+ if (!finfo->fi_hdir) {
9117+ hfile = &finfo->fi_htop;
9118+ AuDebugOn(!hfile->hf_file);
9119+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
9120+ AuDebugOn(bindex < 0);
9121+ if (bindex != finfo->fi_btop)
9122+ au_set_fbstart(file, bindex);
9123+ } else {
9124+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
9125+ if (unlikely(err))
9126+ goto out;
9127+ au_do_refresh_dir(file);
9128+ }
1facf9fc 9129+
4a4d8108
AM
9130+ err = 0;
9131+ need_reopen = 1;
9132+ if (!au_test_mmapped(file))
9133+ err = au_file_refresh_by_inode(file, &need_reopen);
027c5e7a 9134+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
9135+ err = reopen(file);
9136+ if (!err) {
9137+ au_update_figen(file);
9138+ goto out; /* success */
9139+ }
9140+
9141+ /* error, close all lower files */
9142+ if (finfo->fi_hdir) {
9143+ bend = au_fbend_dir(file);
9144+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
9145+ au_set_h_fptr(file, bindex, NULL);
9146+ }
1facf9fc 9147+
4f0767ce 9148+out:
1facf9fc 9149+ return err;
9150+}
9151+
4a4d8108
AM
9152+/* common function to regular file and dir */
9153+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
9154+ int wlock)
dece6358 9155+{
1308ab2a 9156+ int err;
4a4d8108
AM
9157+ unsigned int sigen, figen;
9158+ aufs_bindex_t bstart;
9159+ unsigned char pseudo_link;
9160+ struct dentry *dentry;
9161+ struct inode *inode;
1facf9fc 9162+
4a4d8108
AM
9163+ err = 0;
9164+ dentry = file->f_dentry;
9165+ inode = dentry->d_inode;
9166+ AuDebugOn(au_special_file(inode->i_mode));
9167+ sigen = au_sigen(dentry->d_sb);
9168+ fi_write_lock(file);
9169+ figen = au_figen(file);
9170+ di_write_lock_child(dentry);
9171+ bstart = au_dbstart(dentry);
9172+ pseudo_link = (bstart != au_ibstart(inode));
9173+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
9174+ if (!wlock) {
9175+ di_downgrade_lock(dentry, AuLock_IR);
9176+ fi_downgrade_lock(file);
9177+ }
9178+ goto out; /* success */
9179+ }
dece6358 9180+
4a4d8108 9181+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 9182+ if (au_digen_test(dentry, sigen)) {
4a4d8108 9183+ err = au_reval_dpath(dentry, sigen);
027c5e7a 9184+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 9185+ }
dece6358 9186+
027c5e7a
AM
9187+ if (!err)
9188+ err = refresh_file(file, reopen);
4a4d8108
AM
9189+ if (!err) {
9190+ if (!wlock) {
9191+ di_downgrade_lock(dentry, AuLock_IR);
9192+ fi_downgrade_lock(file);
9193+ }
9194+ } else {
9195+ di_write_unlock(dentry);
9196+ fi_write_unlock(file);
9197+ }
1facf9fc 9198+
4f0767ce 9199+out:
1308ab2a 9200+ return err;
9201+}
1facf9fc 9202+
4a4d8108
AM
9203+/* ---------------------------------------------------------------------- */
9204+
9205+/* cf. aufs_nopage() */
9206+/* for madvise(2) */
9207+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 9208+{
4a4d8108
AM
9209+ unlock_page(page);
9210+ return 0;
9211+}
1facf9fc 9212+
4a4d8108
AM
9213+/* it will never be called, but necessary to support O_DIRECT */
9214+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
9215+ const struct iovec *iov, loff_t offset,
9216+ unsigned long nr_segs)
9217+{ BUG(); return 0; }
1facf9fc 9218+
4a4d8108
AM
9219+/*
9220+ * it will never be called, but madvise and fadvise behaves differently
9221+ * when get_xip_mem is defined
9222+ */
9223+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
9224+ int create, void **kmem, unsigned long *pfn)
9225+{ BUG(); return 0; }
1facf9fc 9226+
4a4d8108
AM
9227+/* they will never be called. */
9228+#ifdef CONFIG_AUFS_DEBUG
9229+static int aufs_write_begin(struct file *file, struct address_space *mapping,
9230+ loff_t pos, unsigned len, unsigned flags,
9231+ struct page **pagep, void **fsdata)
9232+{ AuUnsupport(); return 0; }
9233+static int aufs_write_end(struct file *file, struct address_space *mapping,
9234+ loff_t pos, unsigned len, unsigned copied,
9235+ struct page *page, void *fsdata)
9236+{ AuUnsupport(); return 0; }
9237+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
9238+{ AuUnsupport(); return 0; }
9239+static void aufs_sync_page(struct page *page)
9240+{ AuUnsupport(); }
1308ab2a 9241+
4a4d8108
AM
9242+static int aufs_set_page_dirty(struct page *page)
9243+{ AuUnsupport(); return 0; }
9244+static void aufs_invalidatepage(struct page *page, unsigned long offset)
9245+{ AuUnsupport(); }
9246+static int aufs_releasepage(struct page *page, gfp_t gfp)
9247+{ AuUnsupport(); return 0; }
9248+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
9249+ struct page *page)
9250+{ AuUnsupport(); return 0; }
9251+static int aufs_launder_page(struct page *page)
9252+{ AuUnsupport(); return 0; }
9253+static int aufs_is_partially_uptodate(struct page *page,
9254+ read_descriptor_t *desc,
9255+ unsigned long from)
9256+{ AuUnsupport(); return 0; }
9257+static int aufs_error_remove_page(struct address_space *mapping,
9258+ struct page *page)
9259+{ AuUnsupport(); return 0; }
9260+#endif /* CONFIG_AUFS_DEBUG */
9261+
9262+const struct address_space_operations aufs_aop = {
9263+ .readpage = aufs_readpage,
9264+ .direct_IO = aufs_direct_IO,
9265+ .get_xip_mem = aufs_get_xip_mem,
9266+#ifdef CONFIG_AUFS_DEBUG
9267+ .writepage = aufs_writepage,
9268+ .sync_page = aufs_sync_page,
9269+ /* no writepages, because of writepage */
9270+ .set_page_dirty = aufs_set_page_dirty,
9271+ /* no readpages, because of readpage */
9272+ .write_begin = aufs_write_begin,
9273+ .write_end = aufs_write_end,
9274+ /* no bmap, no block device */
9275+ .invalidatepage = aufs_invalidatepage,
9276+ .releasepage = aufs_releasepage,
9277+ .migratepage = aufs_migratepage,
9278+ .launder_page = aufs_launder_page,
9279+ .is_partially_uptodate = aufs_is_partially_uptodate,
9280+ .error_remove_page = aufs_error_remove_page
9281+#endif /* CONFIG_AUFS_DEBUG */
dece6358 9282+};
7f207e10
AM
9283diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
9284--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
9285+++ linux/fs/aufs/file.h 2011-03-21 20:22:06.853935428 +0100
9286@@ -0,0 +1,236 @@
4a4d8108 9287+/*
027c5e7a 9288+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
9289+ *
9290+ * This program, aufs is free software; you can redistribute it and/or modify
9291+ * it under the terms of the GNU General Public License as published by
9292+ * the Free Software Foundation; either version 2 of the License, or
9293+ * (at your option) any later version.
9294+ *
9295+ * This program is distributed in the hope that it will be useful,
9296+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9297+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9298+ * GNU General Public License for more details.
9299+ *
9300+ * You should have received a copy of the GNU General Public License
9301+ * along with this program; if not, write to the Free Software
9302+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9303+ */
1facf9fc 9304+
4a4d8108
AM
9305+/*
9306+ * file operations
9307+ */
1facf9fc 9308+
4a4d8108
AM
9309+#ifndef __AUFS_FILE_H__
9310+#define __AUFS_FILE_H__
1facf9fc 9311+
4a4d8108 9312+#ifdef __KERNEL__
1facf9fc 9313+
4a4d8108
AM
9314+#include <linux/fs.h>
9315+#include <linux/poll.h>
9316+#include <linux/aufs_type.h>
9317+#include "rwsem.h"
1facf9fc 9318+
4a4d8108
AM
9319+struct au_branch;
9320+struct au_hfile {
9321+ struct file *hf_file;
9322+ struct au_branch *hf_br;
9323+};
1facf9fc 9324+
4a4d8108
AM
9325+struct au_vdir;
9326+struct au_fidir {
9327+ aufs_bindex_t fd_bbot;
9328+ aufs_bindex_t fd_nent;
9329+ struct au_vdir *fd_vdir_cache;
9330+ struct au_hfile fd_hfile[];
9331+};
1facf9fc 9332+
4a4d8108 9333+static inline int au_fidir_sz(int nent)
dece6358 9334+{
4f0767ce
JR
9335+ AuDebugOn(nent < 0);
9336+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 9337+}
1facf9fc 9338+
4a4d8108
AM
9339+struct au_finfo {
9340+ atomic_t fi_generation;
dece6358 9341+
4a4d8108
AM
9342+ struct au_rwsem fi_rwsem;
9343+ aufs_bindex_t fi_btop;
9344+
9345+ /* do not union them */
9346+ struct { /* for non-dir */
9347+ struct au_hfile fi_htop;
9348+ struct vm_operations_struct *fi_hvmop;
9349+ struct mutex fi_vm_mtx;
9350+ struct mutex fi_mmap;
9351+ };
9352+ struct au_fidir *fi_hdir; /* for dir only */
9353+} ____cacheline_aligned_in_smp;
1facf9fc 9354+
4a4d8108 9355+/* ---------------------------------------------------------------------- */
1facf9fc 9356+
4a4d8108
AM
9357+/* file.c */
9358+extern const struct address_space_operations aufs_aop;
9359+unsigned int au_file_roflags(unsigned int flags);
9360+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
9361+ struct file *file);
9362+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
9363+ struct au_fidir *fidir);
9364+int au_reopen_nondir(struct file *file);
9365+struct au_pin;
9366+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
9367+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
9368+ int wlock);
9369+int au_do_flush(struct file *file, fl_owner_t id,
9370+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 9371+
4a4d8108
AM
9372+/* poll.c */
9373+#ifdef CONFIG_AUFS_POLL
9374+unsigned int aufs_poll(struct file *file, poll_table *wait);
9375+#endif
1facf9fc 9376+
4a4d8108
AM
9377+#ifdef CONFIG_AUFS_BR_HFSPLUS
9378+/* hfsplus.c */
9379+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
9380+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
9381+ struct file *h_file);
9382+#else
9383+static inline
9384+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 9385+{
4a4d8108
AM
9386+ return NULL;
9387+}
1facf9fc 9388+
4a4d8108
AM
9389+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
9390+ struct file *h_file);
9391+#endif
1facf9fc 9392+
4a4d8108
AM
9393+/* f_op.c */
9394+extern const struct file_operations aufs_file_fop;
9395+extern const struct vm_operations_struct aufs_vm_ops;
9396+int au_do_open_nondir(struct file *file, int flags);
9397+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
9398+
9399+#ifdef CONFIG_AUFS_SP_IATTR
9400+/* f_op_sp.c */
9401+int au_special_file(umode_t mode);
9402+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
9403+#else
9404+AuStubInt0(au_special_file, umode_t mode)
9405+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
9406+ dev_t rdev)
9407+{
9408+ init_special_inode(inode, mode, rdev);
9409+}
9410+#endif
1facf9fc 9411+
4a4d8108
AM
9412+/* finfo.c */
9413+void au_hfput(struct au_hfile *hf, struct file *file);
9414+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
9415+ struct file *h_file);
1facf9fc 9416+
4a4d8108 9417+void au_update_figen(struct file *file);
4a4d8108
AM
9418+struct au_fidir *au_fidir_alloc(struct super_block *sb);
9419+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 9420+
4a4d8108
AM
9421+void au_fi_init_once(void *_fi);
9422+void au_finfo_fin(struct file *file);
9423+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 9424+
4a4d8108
AM
9425+/* ioctl.c */
9426+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
9427+#ifdef CONFIG_COMPAT
9428+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
9429+ unsigned long arg);
9430+#endif
1facf9fc 9431+
4a4d8108 9432+/* ---------------------------------------------------------------------- */
1facf9fc 9433+
4a4d8108
AM
9434+static inline struct au_finfo *au_fi(struct file *file)
9435+{
9436+ return file->private_data;
9437+}
1facf9fc 9438+
4a4d8108 9439+/* ---------------------------------------------------------------------- */
1facf9fc 9440+
4a4d8108
AM
9441+/*
9442+ * fi_read_lock, fi_write_lock,
9443+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
9444+ */
9445+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 9446+
4a4d8108
AM
9447+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
9448+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
9449+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 9450+
1308ab2a 9451+/* ---------------------------------------------------------------------- */
9452+
4a4d8108
AM
9453+/* todo: hard/soft set? */
9454+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 9455+{
4a4d8108
AM
9456+ FiMustAnyLock(file);
9457+ return au_fi(file)->fi_btop;
9458+}
dece6358 9459+
4a4d8108
AM
9460+static inline aufs_bindex_t au_fbend_dir(struct file *file)
9461+{
9462+ FiMustAnyLock(file);
9463+ AuDebugOn(!au_fi(file)->fi_hdir);
9464+ return au_fi(file)->fi_hdir->fd_bbot;
9465+}
1facf9fc 9466+
4a4d8108
AM
9467+static inline struct au_vdir *au_fvdir_cache(struct file *file)
9468+{
9469+ FiMustAnyLock(file);
9470+ AuDebugOn(!au_fi(file)->fi_hdir);
9471+ return au_fi(file)->fi_hdir->fd_vdir_cache;
9472+}
1facf9fc 9473+
4a4d8108
AM
9474+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
9475+{
9476+ FiMustWriteLock(file);
9477+ au_fi(file)->fi_btop = bindex;
9478+}
1facf9fc 9479+
4a4d8108
AM
9480+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
9481+{
9482+ FiMustWriteLock(file);
9483+ AuDebugOn(!au_fi(file)->fi_hdir);
9484+ au_fi(file)->fi_hdir->fd_bbot = bindex;
9485+}
1308ab2a 9486+
4a4d8108
AM
9487+static inline void au_set_fvdir_cache(struct file *file,
9488+ struct au_vdir *vdir_cache)
9489+{
9490+ FiMustWriteLock(file);
9491+ AuDebugOn(!au_fi(file)->fi_hdir);
9492+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
9493+}
dece6358 9494+
4a4d8108
AM
9495+static inline struct file *au_hf_top(struct file *file)
9496+{
9497+ FiMustAnyLock(file);
9498+ AuDebugOn(au_fi(file)->fi_hdir);
9499+ return au_fi(file)->fi_htop.hf_file;
9500+}
1facf9fc 9501+
4a4d8108
AM
9502+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
9503+{
9504+ FiMustAnyLock(file);
9505+ AuDebugOn(!au_fi(file)->fi_hdir);
9506+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
9507+}
9508+
4a4d8108
AM
9509+/* todo: memory barrier? */
9510+static inline unsigned int au_figen(struct file *f)
dece6358 9511+{
4a4d8108
AM
9512+ return atomic_read(&au_fi(f)->fi_generation);
9513+}
dece6358 9514+
4a4d8108
AM
9515+static inline int au_test_mmapped(struct file *f)
9516+{
9517+ FiMustAnyLock(f);
9518+ return !!(au_fi(f)->fi_hvmop);
9519+}
1308ab2a 9520+
4a4d8108
AM
9521+#endif /* __KERNEL__ */
9522+#endif /* __AUFS_FILE_H__ */
7f207e10
AM
9523diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
9524--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
9525+++ linux/fs/aufs/finfo.c 2011-03-21 20:22:06.853935428 +0100
9526@@ -0,0 +1,157 @@
4a4d8108 9527+/*
027c5e7a 9528+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
9529+ *
9530+ * This program, aufs is free software; you can redistribute it and/or modify
9531+ * it under the terms of the GNU General Public License as published by
9532+ * the Free Software Foundation; either version 2 of the License, or
9533+ * (at your option) any later version.
9534+ *
9535+ * This program is distributed in the hope that it will be useful,
9536+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9537+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9538+ * GNU General Public License for more details.
9539+ *
9540+ * You should have received a copy of the GNU General Public License
9541+ * along with this program; if not, write to the Free Software
9542+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9543+ */
1308ab2a 9544+
4a4d8108
AM
9545+/*
9546+ * file private data
9547+ */
1facf9fc 9548+
4a4d8108
AM
9549+#include <linux/file.h>
9550+#include "aufs.h"
1facf9fc 9551+
4a4d8108
AM
9552+void au_hfput(struct au_hfile *hf, struct file *file)
9553+{
9554+ /* todo: direct access f_flags */
9555+ if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC))
9556+ allow_write_access(hf->hf_file);
9557+ fput(hf->hf_file);
9558+ hf->hf_file = NULL;
e49829fe 9559+ atomic_dec(&hf->hf_br->br_count);
4a4d8108
AM
9560+ hf->hf_br = NULL;
9561+}
1facf9fc 9562+
4a4d8108
AM
9563+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
9564+{
9565+ struct au_finfo *finfo = au_fi(file);
9566+ struct au_hfile *hf;
9567+ struct au_fidir *fidir;
9568+
9569+ fidir = finfo->fi_hdir;
9570+ if (!fidir) {
9571+ AuDebugOn(finfo->fi_btop != bindex);
9572+ hf = &finfo->fi_htop;
9573+ } else
9574+ hf = fidir->fd_hfile + bindex;
9575+
9576+ if (hf && hf->hf_file)
9577+ au_hfput(hf, file);
9578+ if (val) {
9579+ FiMustWriteLock(file);
9580+ hf->hf_file = val;
9581+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 9582+ }
4a4d8108 9583+}
1facf9fc 9584+
4a4d8108
AM
9585+void au_update_figen(struct file *file)
9586+{
9587+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
9588+ /* smp_mb(); */ /* atomic_set */
1facf9fc 9589+}
9590+
4a4d8108
AM
9591+/* ---------------------------------------------------------------------- */
9592+
4a4d8108
AM
9593+struct au_fidir *au_fidir_alloc(struct super_block *sb)
9594+{
9595+ struct au_fidir *fidir;
9596+ int nbr;
9597+
9598+ nbr = au_sbend(sb) + 1;
9599+ if (nbr < 2)
9600+ nbr = 2; /* initial allocate for 2 branches */
9601+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
9602+ if (fidir) {
9603+ fidir->fd_bbot = -1;
9604+ fidir->fd_nent = nbr;
9605+ fidir->fd_vdir_cache = NULL;
9606+ }
9607+
9608+ return fidir;
9609+}
9610+
9611+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
9612+{
9613+ int err;
9614+ struct au_fidir *fidir, *p;
9615+
9616+ AuRwMustWriteLock(&finfo->fi_rwsem);
9617+ fidir = finfo->fi_hdir;
9618+ AuDebugOn(!fidir);
9619+
9620+ err = -ENOMEM;
9621+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
9622+ GFP_NOFS);
9623+ if (p) {
9624+ p->fd_nent = nbr;
9625+ finfo->fi_hdir = p;
9626+ err = 0;
9627+ }
1facf9fc 9628+
dece6358 9629+ return err;
1facf9fc 9630+}
1308ab2a 9631+
9632+/* ---------------------------------------------------------------------- */
9633+
4a4d8108 9634+void au_finfo_fin(struct file *file)
1308ab2a 9635+{
4a4d8108
AM
9636+ struct au_finfo *finfo;
9637+
7f207e10
AM
9638+ au_nfiles_dec(file->f_dentry->d_sb);
9639+
4a4d8108
AM
9640+ finfo = au_fi(file);
9641+ AuDebugOn(finfo->fi_hdir);
9642+ AuRwDestroy(&finfo->fi_rwsem);
9643+ au_cache_free_finfo(finfo);
1308ab2a 9644+}
1308ab2a 9645+
e49829fe 9646+void au_fi_init_once(void *_finfo)
4a4d8108 9647+{
e49829fe
JR
9648+ struct au_finfo *finfo = _finfo;
9649+ static struct lock_class_key aufs_fi, aufs_fi_vm, aufs_fi_mmap;
1308ab2a 9650+
e49829fe
JR
9651+ au_rw_init(&finfo->fi_rwsem);
9652+ au_rw_class(&finfo->fi_rwsem, &aufs_fi);
9653+ mutex_init(&finfo->fi_vm_mtx);
9654+ lockdep_set_class(&finfo->fi_vm_mtx, &aufs_fi_vm);
9655+ mutex_init(&finfo->fi_mmap);
9656+ lockdep_set_class(&finfo->fi_mmap, &aufs_fi_mmap);
4a4d8108 9657+}
1308ab2a 9658+
4a4d8108
AM
9659+int au_finfo_init(struct file *file, struct au_fidir *fidir)
9660+{
9661+ int err;
9662+ struct au_finfo *finfo;
9663+ struct dentry *dentry;
9664+
9665+ err = -ENOMEM;
9666+ dentry = file->f_dentry;
9667+ finfo = au_cache_alloc_finfo();
9668+ if (unlikely(!finfo))
9669+ goto out;
9670+
9671+ err = 0;
7f207e10 9672+ au_nfiles_inc(dentry->d_sb);
4a4d8108
AM
9673+ au_rw_write_lock(&finfo->fi_rwsem);
9674+ finfo->fi_btop = -1;
9675+ finfo->fi_hdir = fidir;
9676+ atomic_set(&finfo->fi_generation, au_digen(dentry));
9677+ /* smp_mb(); */ /* atomic_set */
9678+
9679+ file->private_data = finfo;
9680+
9681+out:
9682+ return err;
9683+}
7f207e10
AM
9684diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
9685--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
9686+++ linux/fs/aufs/f_op.c 2011-03-21 20:22:06.853935428 +0100
9687@@ -0,0 +1,937 @@
dece6358 9688+/*
027c5e7a 9689+ * Copyright (C) 2005-2011 Junjiro R. Okajima
dece6358
AM
9690+ *
9691+ * This program, aufs is free software; you can redistribute it and/or modify
9692+ * it under the terms of the GNU General Public License as published by
9693+ * the Free Software Foundation; either version 2 of the License, or
9694+ * (at your option) any later version.
9695+ *
9696+ * This program is distributed in the hope that it will be useful,
9697+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9698+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9699+ * GNU General Public License for more details.
9700+ *
9701+ * You should have received a copy of the GNU General Public License
9702+ * along with this program; if not, write to the Free Software
9703+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9704+ */
1facf9fc 9705+
9706+/*
4a4d8108 9707+ * file and vm operations
1facf9fc 9708+ */
dece6358
AM
9709+
9710+#include <linux/file.h>
4a4d8108
AM
9711+#include <linux/fs_stack.h>
9712+#include <linux/mman.h>
9713+#include <linux/mm.h>
9714+#include <linux/security.h>
dece6358
AM
9715+#include "aufs.h"
9716+
4a4d8108 9717+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 9718+{
4a4d8108
AM
9719+ int err;
9720+ aufs_bindex_t bindex;
9721+ struct file *h_file;
9722+ struct dentry *dentry;
9723+ struct au_finfo *finfo;
9724+
9725+ FiMustWriteLock(file);
9726+
4a4d8108 9727+ dentry = file->f_dentry;
027c5e7a
AM
9728+ err = au_d_alive(dentry);
9729+ if (unlikely(err))
9730+ goto out;
9731+
4a4d8108
AM
9732+ finfo = au_fi(file);
9733+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
9734+ finfo->fi_hvmop = NULL;
9735+ bindex = au_dbstart(dentry);
9736+ h_file = au_h_open(dentry, bindex, flags, file);
9737+ if (IS_ERR(h_file))
9738+ err = PTR_ERR(h_file);
9739+ else {
9740+ au_set_fbstart(file, bindex);
9741+ au_set_h_fptr(file, bindex, h_file);
9742+ au_update_figen(file);
9743+ /* todo: necessary? */
9744+ /* file->f_ra = h_file->f_ra; */
9745+ }
027c5e7a
AM
9746+
9747+out:
4a4d8108 9748+ return err;
1facf9fc 9749+}
9750+
4a4d8108
AM
9751+static int aufs_open_nondir(struct inode *inode __maybe_unused,
9752+ struct file *file)
1facf9fc 9753+{
4a4d8108 9754+ int err;
1308ab2a 9755+ struct super_block *sb;
1facf9fc 9756+
4a4d8108
AM
9757+ AuDbg("%.*s, f_ flags 0x%x, f_mode 0x%x\n",
9758+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
9759+ file->f_mode);
1facf9fc 9760+
4a4d8108
AM
9761+ sb = file->f_dentry->d_sb;
9762+ si_read_lock(sb, AuLock_FLUSH);
9763+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
9764+ si_read_unlock(sb);
9765+ return err;
9766+}
1facf9fc 9767+
4a4d8108
AM
9768+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
9769+{
9770+ struct au_finfo *finfo;
9771+ aufs_bindex_t bindex;
1facf9fc 9772+
4a4d8108
AM
9773+ finfo = au_fi(file);
9774+ bindex = finfo->fi_btop;
0c5527e5
AM
9775+ if (bindex >= 0) {
9776+ /* remove me from sb->s_files */
9777+ file_sb_list_del(file);
4a4d8108 9778+ au_set_h_fptr(file, bindex, NULL);
0c5527e5 9779+ }
7f207e10 9780+
4a4d8108
AM
9781+ au_finfo_fin(file);
9782+ return 0;
1facf9fc 9783+}
9784+
4a4d8108
AM
9785+/* ---------------------------------------------------------------------- */
9786+
9787+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 9788+{
1308ab2a 9789+ int err;
4a4d8108
AM
9790+ struct file *h_file;
9791+
9792+ err = 0;
9793+ h_file = au_hf_top(file);
9794+ if (h_file)
9795+ err = vfsub_flush(h_file, id);
9796+ return err;
9797+}
9798+
9799+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
9800+{
9801+ return au_do_flush(file, id, au_do_flush_nondir);
9802+}
9803+
9804+/* ---------------------------------------------------------------------- */
9805+
9806+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
9807+ loff_t *ppos)
9808+{
9809+ ssize_t err;
dece6358 9810+ struct dentry *dentry;
4a4d8108 9811+ struct file *h_file;
dece6358 9812+ struct super_block *sb;
1facf9fc 9813+
dece6358
AM
9814+ dentry = file->f_dentry;
9815+ sb = dentry->d_sb;
e49829fe 9816+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 9817+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
9818+ if (unlikely(err))
9819+ goto out;
1facf9fc 9820+
4a4d8108
AM
9821+ h_file = au_hf_top(file);
9822+ err = vfsub_read_u(h_file, buf, count, ppos);
9823+ /* todo: necessary? */
9824+ /* file->f_ra = h_file->f_ra; */
9825+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1308ab2a 9826+
4a4d8108
AM
9827+ di_read_unlock(dentry, AuLock_IR);
9828+ fi_read_unlock(file);
4f0767ce 9829+out:
dece6358
AM
9830+ si_read_unlock(sb);
9831+ return err;
9832+}
1facf9fc 9833+
e49829fe
JR
9834+/*
9835+ * todo: very ugly
9836+ * it locks both of i_mutex and si_rwsem for read in safe.
9837+ * if the plink maintenance mode continues forever (that is the problem),
9838+ * may loop forever.
9839+ */
9840+static void au_mtx_and_read_lock(struct inode *inode)
9841+{
9842+ int err;
9843+ struct super_block *sb = inode->i_sb;
9844+
9845+ while (1) {
9846+ mutex_lock(&inode->i_mutex);
9847+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
9848+ if (!err)
9849+ break;
9850+ mutex_unlock(&inode->i_mutex);
9851+ si_read_lock(sb, AuLock_NOPLMW);
9852+ si_read_unlock(sb);
9853+ }
9854+}
9855+
4a4d8108
AM
9856+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
9857+ size_t count, loff_t *ppos)
dece6358 9858+{
4a4d8108
AM
9859+ ssize_t err;
9860+ struct au_pin pin;
dece6358 9861+ struct dentry *dentry;
4a4d8108 9862+ struct inode *inode;
4a4d8108
AM
9863+ struct file *h_file;
9864+ char __user *buf = (char __user *)ubuf;
1facf9fc 9865+
dece6358 9866+ dentry = file->f_dentry;
4a4d8108 9867+ inode = dentry->d_inode;
e49829fe 9868+ au_mtx_and_read_lock(inode);
1facf9fc 9869+
4a4d8108
AM
9870+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9871+ if (unlikely(err))
9872+ goto out;
1facf9fc 9873+
4a4d8108
AM
9874+ err = au_ready_to_write(file, -1, &pin);
9875+ di_downgrade_lock(dentry, AuLock_IR);
9876+ if (unlikely(err))
9877+ goto out_unlock;
1facf9fc 9878+
4a4d8108
AM
9879+ h_file = au_hf_top(file);
9880+ au_unpin(&pin);
9881+ err = vfsub_write_u(h_file, buf, count, ppos);
9882+ au_cpup_attr_timesizes(inode);
9883+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9884+
4f0767ce 9885+out_unlock:
4a4d8108
AM
9886+ di_read_unlock(dentry, AuLock_IR);
9887+ fi_write_unlock(file);
4f0767ce 9888+out:
e49829fe 9889+ si_read_unlock(inode->i_sb);
4a4d8108 9890+ mutex_unlock(&inode->i_mutex);
dece6358
AM
9891+ return err;
9892+}
1facf9fc 9893+
4a4d8108
AM
9894+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
9895+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 9896+{
4a4d8108
AM
9897+ ssize_t err;
9898+ struct file *file;
9899+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
9900+ loff_t);
1facf9fc 9901+
4a4d8108
AM
9902+ err = security_file_permission(h_file, rw);
9903+ if (unlikely(err))
9904+ goto out;
1facf9fc 9905+
4a4d8108
AM
9906+ err = -ENOSYS;
9907+ func = NULL;
9908+ if (rw == MAY_READ)
9909+ func = h_file->f_op->aio_read;
9910+ else if (rw == MAY_WRITE)
9911+ func = h_file->f_op->aio_write;
9912+ if (func) {
9913+ file = kio->ki_filp;
9914+ kio->ki_filp = h_file;
9915+ err = func(kio, iov, nv, pos);
9916+ kio->ki_filp = file;
9917+ } else
9918+ /* currently there is no such fs */
9919+ WARN_ON_ONCE(1);
1facf9fc 9920+
4f0767ce 9921+out:
dece6358
AM
9922+ return err;
9923+}
1facf9fc 9924+
4a4d8108
AM
9925+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
9926+ unsigned long nv, loff_t pos)
1facf9fc 9927+{
4a4d8108
AM
9928+ ssize_t err;
9929+ struct file *file, *h_file;
9930+ struct dentry *dentry;
dece6358 9931+ struct super_block *sb;
1facf9fc 9932+
4a4d8108 9933+ file = kio->ki_filp;
dece6358 9934+ dentry = file->f_dentry;
1308ab2a 9935+ sb = dentry->d_sb;
e49829fe 9936+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9937+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9938+ if (unlikely(err))
9939+ goto out;
9940+
9941+ h_file = au_hf_top(file);
9942+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
9943+ /* todo: necessary? */
9944+ /* file->f_ra = h_file->f_ra; */
9945+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9946+ di_read_unlock(dentry, AuLock_IR);
9947+ fi_read_unlock(file);
1facf9fc 9948+
4f0767ce 9949+out:
4a4d8108 9950+ si_read_unlock(sb);
1308ab2a 9951+ return err;
9952+}
1facf9fc 9953+
4a4d8108
AM
9954+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
9955+ unsigned long nv, loff_t pos)
1308ab2a 9956+{
4a4d8108
AM
9957+ ssize_t err;
9958+ struct au_pin pin;
9959+ struct dentry *dentry;
9960+ struct inode *inode;
4a4d8108 9961+ struct file *file, *h_file;
1308ab2a 9962+
4a4d8108 9963+ file = kio->ki_filp;
1308ab2a 9964+ dentry = file->f_dentry;
1308ab2a 9965+ inode = dentry->d_inode;
e49829fe
JR
9966+ au_mtx_and_read_lock(inode);
9967+
4a4d8108
AM
9968+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9969+ if (unlikely(err))
1308ab2a 9970+ goto out;
1facf9fc 9971+
4a4d8108
AM
9972+ err = au_ready_to_write(file, -1, &pin);
9973+ di_downgrade_lock(dentry, AuLock_IR);
dece6358 9974+ if (unlikely(err))
4a4d8108 9975+ goto out_unlock;
1facf9fc 9976+
4a4d8108
AM
9977+ au_unpin(&pin);
9978+ h_file = au_hf_top(file);
9979+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
9980+ au_cpup_attr_timesizes(inode);
9981+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9982+
4f0767ce 9983+out_unlock:
4a4d8108
AM
9984+ di_read_unlock(dentry, AuLock_IR);
9985+ fi_write_unlock(file);
4f0767ce 9986+out:
e49829fe 9987+ si_read_unlock(inode->i_sb);
4a4d8108 9988+ mutex_unlock(&inode->i_mutex);
dece6358 9989+ return err;
1facf9fc 9990+}
9991+
4a4d8108
AM
9992+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
9993+ struct pipe_inode_info *pipe, size_t len,
9994+ unsigned int flags)
1facf9fc 9995+{
4a4d8108
AM
9996+ ssize_t err;
9997+ struct file *h_file;
9998+ struct dentry *dentry;
dece6358 9999+ struct super_block *sb;
1facf9fc 10000+
dece6358 10001+ dentry = file->f_dentry;
dece6358 10002+ sb = dentry->d_sb;
e49829fe 10003+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
10004+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
10005+ if (unlikely(err))
dece6358 10006+ goto out;
1facf9fc 10007+
4a4d8108
AM
10008+ err = -EINVAL;
10009+ h_file = au_hf_top(file);
10010+ if (au_test_loopback_kthread()) {
10011+ file->f_mapping = h_file->f_mapping;
10012+ smp_mb(); /* unnecessary? */
1308ab2a 10013+ }
4a4d8108
AM
10014+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
10015+ /* todo: necessasry? */
10016+ /* file->f_ra = h_file->f_ra; */
10017+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 10018+
4a4d8108
AM
10019+ di_read_unlock(dentry, AuLock_IR);
10020+ fi_read_unlock(file);
1facf9fc 10021+
4f0767ce 10022+out:
4a4d8108 10023+ si_read_unlock(sb);
dece6358 10024+ return err;
1facf9fc 10025+}
10026+
4a4d8108
AM
10027+static ssize_t
10028+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
10029+ size_t len, unsigned int flags)
1facf9fc 10030+{
4a4d8108
AM
10031+ ssize_t err;
10032+ struct au_pin pin;
10033+ struct dentry *dentry;
10034+ struct inode *inode;
4a4d8108 10035+ struct file *h_file;
1facf9fc 10036+
4a4d8108
AM
10037+ dentry = file->f_dentry;
10038+ inode = dentry->d_inode;
e49829fe 10039+ au_mtx_and_read_lock(inode);
4a4d8108
AM
10040+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10041+ if (unlikely(err))
10042+ goto out;
1facf9fc 10043+
4a4d8108
AM
10044+ err = au_ready_to_write(file, -1, &pin);
10045+ di_downgrade_lock(dentry, AuLock_IR);
10046+ if (unlikely(err))
10047+ goto out_unlock;
1facf9fc 10048+
4a4d8108
AM
10049+ h_file = au_hf_top(file);
10050+ au_unpin(&pin);
10051+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
10052+ au_cpup_attr_timesizes(inode);
10053+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 10054+
4f0767ce 10055+out_unlock:
4a4d8108
AM
10056+ di_read_unlock(dentry, AuLock_IR);
10057+ fi_write_unlock(file);
4f0767ce 10058+out:
e49829fe 10059+ si_read_unlock(inode->i_sb);
4a4d8108
AM
10060+ mutex_unlock(&inode->i_mutex);
10061+ return err;
10062+}
1facf9fc 10063+
4a4d8108
AM
10064+/* ---------------------------------------------------------------------- */
10065+
10066+static struct file *au_safe_file(struct vm_area_struct *vma)
10067+{
10068+ struct file *file;
10069+
10070+ file = vma->vm_file;
027c5e7a 10071+ if (au_fi(file) && au_test_aufs(file->f_dentry->d_sb))
4a4d8108
AM
10072+ return file;
10073+ return NULL;
1facf9fc 10074+}
10075+
4a4d8108 10076+static void au_reset_file(struct vm_area_struct *vma, struct file *file)
1facf9fc 10077+{
4a4d8108
AM
10078+ vma->vm_file = file;
10079+ /* smp_mb(); */ /* flush vm_file */
10080+}
1facf9fc 10081+
4a4d8108
AM
10082+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
10083+{
10084+ int err;
10085+ static DECLARE_WAIT_QUEUE_HEAD(wq);
10086+ struct file *file, *h_file;
10087+ struct au_finfo *finfo;
1facf9fc 10088+
4a4d8108
AM
10089+ /* todo: non-robr mode, user vm_file as it is? */
10090+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 10091+
4a4d8108
AM
10092+ /* do not revalidate, no si lock */
10093+ finfo = au_fi(file);
10094+ AuDebugOn(finfo->fi_hdir);
10095+ h_file = finfo->fi_htop.hf_file;
10096+ AuDebugOn(!h_file || !finfo->fi_hvmop);
10097+
10098+ mutex_lock(&finfo->fi_vm_mtx);
10099+ vma->vm_file = h_file;
10100+ err = finfo->fi_hvmop->fault(vma, vmf);
10101+ /* todo: necessary? */
10102+ /* file->f_ra = h_file->f_ra; */
10103+ au_reset_file(vma, file);
10104+ mutex_unlock(&finfo->fi_vm_mtx);
10105+#if 0 /* def CONFIG_SMP */
10106+ /* wake_up_nr(&wq, online_cpu - 1); */
10107+ wake_up_all(&wq);
10108+#else
10109+ wake_up(&wq);
10110+#endif
1facf9fc 10111+
dece6358 10112+ return err;
1facf9fc 10113+}
10114+
4a4d8108 10115+static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1facf9fc 10116+{
dece6358 10117+ int err;
4a4d8108
AM
10118+ static DECLARE_WAIT_QUEUE_HEAD(wq);
10119+ struct file *file, *h_file;
10120+ struct au_finfo *finfo;
1facf9fc 10121+
4a4d8108 10122+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 10123+
4a4d8108
AM
10124+ finfo = au_fi(file);
10125+ AuDebugOn(finfo->fi_hdir);
10126+ h_file = finfo->fi_htop.hf_file;
10127+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 10128+
4a4d8108
AM
10129+ mutex_lock(&finfo->fi_vm_mtx);
10130+ vma->vm_file = h_file;
10131+ err = finfo->fi_hvmop->page_mkwrite(vma, vmf);
10132+ au_reset_file(vma, file);
10133+ mutex_unlock(&finfo->fi_vm_mtx);
10134+ wake_up(&wq);
1308ab2a 10135+
dece6358 10136+ return err;
1facf9fc 10137+}
10138+
4a4d8108 10139+static void aufs_vm_close(struct vm_area_struct *vma)
1facf9fc 10140+{
4a4d8108
AM
10141+ static DECLARE_WAIT_QUEUE_HEAD(wq);
10142+ struct file *file, *h_file;
10143+ struct au_finfo *finfo;
dece6358 10144+
4a4d8108 10145+ wait_event(wq, (file = au_safe_file(vma)));
dece6358 10146+
4a4d8108
AM
10147+ finfo = au_fi(file);
10148+ AuDebugOn(finfo->fi_hdir);
10149+ h_file = finfo->fi_htop.hf_file;
10150+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 10151+
4a4d8108
AM
10152+ mutex_lock(&finfo->fi_vm_mtx);
10153+ vma->vm_file = h_file;
10154+ finfo->fi_hvmop->close(vma);
10155+ au_reset_file(vma, file);
10156+ mutex_unlock(&finfo->fi_vm_mtx);
10157+ wake_up(&wq);
10158+}
1facf9fc 10159+
4a4d8108
AM
10160+const struct vm_operations_struct aufs_vm_ops = {
10161+ .close = aufs_vm_close,
10162+ .fault = aufs_fault,
10163+ .page_mkwrite = aufs_page_mkwrite
1308ab2a 10164+};
dece6358 10165+
1308ab2a 10166+/* ---------------------------------------------------------------------- */
1facf9fc 10167+
4a4d8108
AM
10168+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
10169+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
1308ab2a 10170+
4a4d8108 10171+static unsigned long au_arch_prot_conv(unsigned long flags)
dece6358 10172+{
4a4d8108
AM
10173+ /* currently ppc64 only */
10174+#ifdef CONFIG_PPC64
10175+ /* cf. linux/arch/powerpc/include/asm/mman.h */
10176+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
10177+ return AuConv_VM_PROT(flags, SAO);
10178+#else
10179+ AuDebugOn(arch_calc_vm_prot_bits(-1));
10180+ return 0;
10181+#endif
dece6358
AM
10182+}
10183+
4a4d8108 10184+static unsigned long au_prot_conv(unsigned long flags)
dece6358 10185+{
4a4d8108
AM
10186+ return AuConv_VM_PROT(flags, READ)
10187+ | AuConv_VM_PROT(flags, WRITE)
10188+ | AuConv_VM_PROT(flags, EXEC)
10189+ | au_arch_prot_conv(flags);
dece6358
AM
10190+}
10191+
4a4d8108
AM
10192+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
10193+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
dece6358 10194+
4a4d8108 10195+static unsigned long au_flag_conv(unsigned long flags)
dece6358 10196+{
4a4d8108
AM
10197+ return AuConv_VM_MAP(flags, GROWSDOWN)
10198+ | AuConv_VM_MAP(flags, DENYWRITE)
10199+ | AuConv_VM_MAP(flags, EXECUTABLE)
10200+ | AuConv_VM_MAP(flags, LOCKED);
dece6358
AM
10201+}
10202+
4a4d8108
AM
10203+static struct vm_operations_struct *
10204+au_hvmop(struct file *h_file, struct vm_area_struct *vma, unsigned long *flags)
dece6358 10205+{
4a4d8108
AM
10206+ struct vm_operations_struct *h_vmop;
10207+ unsigned long prot;
10208+ int err;
dece6358 10209+
4a4d8108
AM
10210+ h_vmop = ERR_PTR(-ENODEV);
10211+ if (!h_file->f_op || !h_file->f_op->mmap)
10212+ goto out;
dece6358 10213+
4a4d8108
AM
10214+ prot = au_prot_conv(vma->vm_flags);
10215+ err = security_file_mmap(h_file, /*reqprot*/prot, prot,
10216+ au_flag_conv(vma->vm_flags), vma->vm_start, 0);
10217+ h_vmop = ERR_PTR(err);
10218+ if (unlikely(err))
10219+ goto out;
dece6358 10220+
4a4d8108
AM
10221+ err = h_file->f_op->mmap(h_file, vma);
10222+ h_vmop = ERR_PTR(err);
10223+ if (unlikely(err))
10224+ goto out;
dece6358 10225+
4a4d8108
AM
10226+ /* oops, it became 'const' */
10227+ h_vmop = (struct vm_operations_struct *)vma->vm_ops;
10228+ *flags = vma->vm_flags;
10229+ err = do_munmap(current->mm, vma->vm_start,
10230+ vma->vm_end - vma->vm_start);
10231+ if (unlikely(err)) {
10232+ AuIOErr("failed internal unmapping %.*s, %d\n",
10233+ AuDLNPair(h_file->f_dentry), err);
10234+ h_vmop = ERR_PTR(-EIO);
10235+ }
dece6358 10236+
4f0767ce 10237+out:
4a4d8108 10238+ return h_vmop;
dece6358
AM
10239+}
10240+
1308ab2a 10241+/*
4a4d8108
AM
10242+ * This is another ugly approach to keep the lock order, particularly
10243+ * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
10244+ * find it in git-log, if you want.
1308ab2a 10245+ *
4a4d8108
AM
10246+ * native readdir: i_mutex, copy_to_user, mmap_sem
10247+ * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
1308ab2a 10248+ *
4a4d8108
AM
10249+ * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
10250+ * acquire aufs rwsem. It introduces a circular locking dependency.
10251+ * To address this problem, aufs_mmap() delegates the part which requires aufs
10252+ * rwsem to its internal workqueue.
1308ab2a 10253+ */
10254+
4a4d8108
AM
10255+/* very ugly approach */
10256+#include "mtx.h"
1308ab2a 10257+
027c5e7a
AM
10258+static void au_fi_mmap_lock_and_sell(struct file *file)
10259+{
10260+ struct mutex *mtx;
10261+
10262+ FiMustWriteLock(file);
10263+
10264+ mtx = &au_fi(file)->fi_mmap;
10265+ mutex_lock(mtx);
10266+ mutex_release(&mtx->dep_map, /*nested*/0, _RET_IP_);
10267+}
10268+
10269+static void au_fi_mmap_buy(struct file *file)
10270+{
10271+ struct mutex *mtx;
10272+
10273+ mtx = &au_fi(file)->fi_mmap;
10274+ MtxMustLock(mtx);
10275+
10276+ mutex_set_owner(mtx);
10277+ mutex_acquire(&mtx->dep_map, /*subclass*/0, /*trylock*/0, _RET_IP_);
10278+}
10279+
10280+static void au_fi_mmap_unlock(struct file *file)
10281+{
10282+ mutex_unlock(&au_fi(file)->fi_mmap);
10283+}
10284+
4a4d8108
AM
10285+struct au_mmap_pre_args {
10286+ /* input */
10287+ struct file *file;
10288+ struct vm_area_struct *vma;
1308ab2a 10289+
4a4d8108
AM
10290+ /* output */
10291+ int *errp;
10292+ struct file *h_file;
10293+ struct au_branch *br;
10294+ int mmapped;
10295+};
dece6358 10296+
4a4d8108
AM
10297+static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
10298+ struct file **h_file, struct au_branch **br,
10299+ int *mmapped)
dece6358 10300+{
4a4d8108
AM
10301+ int err;
10302+ aufs_bindex_t bstart;
10303+ const unsigned char wlock
10304+ = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
10305+ struct dentry *dentry;
10306+ struct super_block *sb;
1308ab2a 10307+
4a4d8108
AM
10308+ dentry = file->f_dentry;
10309+ sb = dentry->d_sb;
e49829fe 10310+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108
AM
10311+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10312+ if (unlikely(err))
10313+ goto out;
10314+
10315+ *mmapped = !!au_test_mmapped(file);
10316+ if (wlock) {
10317+ struct au_pin pin;
10318+
10319+ err = au_ready_to_write(file, -1, &pin);
10320+ di_write_unlock(dentry);
10321+ if (unlikely(err))
10322+ goto out_unlock;
10323+ au_unpin(&pin);
10324+ } else
10325+ di_write_unlock(dentry);
10326+ bstart = au_fbstart(file);
10327+ *br = au_sbr(sb, bstart);
10328+ *h_file = au_hf_top(file);
10329+ get_file(*h_file);
027c5e7a
AM
10330+ if (!*mmapped)
10331+ au_fi_mmap_lock_and_sell(file);
4a4d8108
AM
10332+
10333+out_unlock:
10334+ fi_write_unlock(file);
10335+out:
10336+ si_read_unlock(sb);
10337+ return err;
dece6358
AM
10338+}
10339+
4a4d8108 10340+static void au_call_mmap_pre(void *args)
dece6358 10341+{
4a4d8108
AM
10342+ struct au_mmap_pre_args *a = args;
10343+ *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->br,
10344+ &a->mmapped);
dece6358
AM
10345+}
10346+
4a4d8108 10347+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 10348+{
4a4d8108
AM
10349+ int err, wkq_err;
10350+ unsigned long h_vmflags;
1308ab2a 10351+ struct au_finfo *finfo;
4a4d8108
AM
10352+ struct dentry *h_dentry;
10353+ struct vm_operations_struct *h_vmop, *vmop;
10354+ struct au_mmap_pre_args args = {
10355+ .file = file,
10356+ .vma = vma,
10357+ .errp = &err
10358+ };
10359+
b752ccd1 10360+ wkq_err = au_wkq_wait_pre(au_call_mmap_pre, &args);
4a4d8108
AM
10361+ if (unlikely(wkq_err))
10362+ err = wkq_err;
10363+ if (unlikely(err))
10364+ goto out;
027c5e7a
AM
10365+ if (!args.mmapped)
10366+ au_fi_mmap_buy(file);
4a4d8108
AM
10367+
10368+ h_dentry = args.h_file->f_dentry;
10369+ if (!args.mmapped && au_test_fs_bad_mapping(h_dentry->d_sb)) {
1308ab2a 10370+ /*
4a4d8108
AM
10371+ * by this assignment, f_mapping will differs from aufs inode
10372+ * i_mapping.
10373+ * if someone else mixes the use of f_dentry->d_inode and
10374+ * f_mapping->host, then a problem may arise.
1308ab2a 10375+ */
4a4d8108
AM
10376+ file->f_mapping = args.h_file->f_mapping;
10377+ }
1308ab2a 10378+
4a4d8108
AM
10379+ /* always try this internal mmap to get vma flags */
10380+ h_vmflags = 0; /* gcc warning */
10381+ h_vmop = au_hvmop(args.h_file, vma, &h_vmflags);
10382+ err = PTR_ERR(h_vmop);
10383+ if (IS_ERR(h_vmop))
10384+ goto out_unlock;
027c5e7a 10385+ finfo = au_fi(file);
4a4d8108
AM
10386+ AuDebugOn(args.mmapped && h_vmop != finfo->fi_hvmop);
10387+
10388+ vmop = (void *)au_dy_vmop(file, args.br, h_vmop);
10389+ err = PTR_ERR(vmop);
10390+ if (IS_ERR(vmop))
10391+ goto out_unlock;
10392+
10393+ /*
10394+ * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
10395+ * currently MAP_DENYWRITE from userspace is ignored, but elf loader
10396+ * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
10397+ * both of the aufs file and the lower file is deny_write_access()-ed.
10398+ * finally I hope we can skip handlling MAP_DENYWRITE here.
10399+ */
10400+ err = generic_file_mmap(file, vma);
10401+ if (unlikely(err))
10402+ goto out_unlock;
10403+
10404+ vma->vm_ops = vmop;
10405+ vma->vm_flags = h_vmflags;
10406+ if (!args.mmapped)
10407+ finfo->fi_hvmop = h_vmop;
10408+
10409+ vfsub_file_accessed(args.h_file);
10410+ /* update without lock, I don't think it a problem */
10411+ fsstack_copy_attr_atime(file->f_dentry->d_inode, h_dentry->d_inode);
10412+
4f0767ce 10413+out_unlock:
027c5e7a
AM
10414+ if (!args.mmapped)
10415+ au_fi_mmap_unlock(file);
4a4d8108 10416+ fput(args.h_file);
4f0767ce 10417+out:
4a4d8108
AM
10418+ return err;
10419+}
10420+
10421+/* ---------------------------------------------------------------------- */
10422+
b752ccd1 10423+static int aufs_fsync_nondir(struct file *file, int datasync)
4a4d8108
AM
10424+{
10425+ int err;
10426+ struct au_pin pin;
b752ccd1 10427+ struct dentry *dentry;
4a4d8108
AM
10428+ struct inode *inode;
10429+ struct file *h_file;
10430+ struct super_block *sb;
10431+
b752ccd1 10432+ dentry = file->f_dentry;
4a4d8108
AM
10433+ inode = dentry->d_inode;
10434+ IMustLock(file->f_mapping->host);
10435+ if (inode != file->f_mapping->host) {
10436+ mutex_unlock(&file->f_mapping->host->i_mutex);
10437+ mutex_lock(&inode->i_mutex);
10438+ }
10439+ IMustLock(inode);
10440+
10441+ sb = dentry->d_sb;
e49829fe
JR
10442+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
10443+ if (unlikely(err))
10444+ goto out;
4a4d8108
AM
10445+
10446+ err = 0; /* -EBADF; */ /* posix? */
10447+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
e49829fe 10448+ goto out_si;
4a4d8108
AM
10449+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10450+ if (unlikely(err))
e49829fe 10451+ goto out_si;
4a4d8108
AM
10452+
10453+ err = au_ready_to_write(file, -1, &pin);
10454+ di_downgrade_lock(dentry, AuLock_IR);
10455+ if (unlikely(err))
10456+ goto out_unlock;
10457+ au_unpin(&pin);
10458+
10459+ err = -EINVAL;
10460+ h_file = au_hf_top(file);
10461+ if (h_file->f_op && h_file->f_op->fsync) {
4a4d8108
AM
10462+ struct mutex *h_mtx;
10463+
10464+ /*
10465+ * no filemap_fdatawrite() since aufs file has no its own
10466+ * mapping, but dir.
10467+ */
b752ccd1 10468+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
4a4d8108 10469+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
b752ccd1 10470+ err = h_file->f_op->fsync(h_file, datasync);
4a4d8108
AM
10471+ if (!err)
10472+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
10473+ /*ignore*/
10474+ au_cpup_attr_timesizes(inode);
10475+ mutex_unlock(h_mtx);
10476+ }
10477+
4f0767ce 10478+out_unlock:
4a4d8108 10479+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 10480+ fi_write_unlock(file);
e49829fe 10481+out_si:
953406b4 10482+ si_read_unlock(sb);
e49829fe 10483+out:
4a4d8108
AM
10484+ if (inode != file->f_mapping->host) {
10485+ mutex_unlock(&inode->i_mutex);
10486+ mutex_lock(&file->f_mapping->host->i_mutex);
10487+ }
10488+ return err;
dece6358
AM
10489+}
10490+
4a4d8108
AM
10491+/* no one supports this operation, currently */
10492+#if 0
10493+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 10494+{
4a4d8108
AM
10495+ int err;
10496+ struct au_pin pin;
1308ab2a 10497+ struct dentry *dentry;
4a4d8108
AM
10498+ struct inode *inode;
10499+ struct file *file, *h_file;
1308ab2a 10500+
4a4d8108 10501+ file = kio->ki_filp;
1308ab2a 10502+ dentry = file->f_dentry;
4a4d8108 10503+ inode = dentry->d_inode;
e49829fe 10504+ au_mtx_and_read_lock(inode);
4a4d8108
AM
10505+
10506+ err = 0; /* -EBADF; */ /* posix? */
10507+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
10508+ goto out;
10509+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10510+ if (unlikely(err))
1308ab2a 10511+ goto out;
10512+
4a4d8108
AM
10513+ err = au_ready_to_write(file, -1, &pin);
10514+ di_downgrade_lock(dentry, AuLock_IR);
10515+ if (unlikely(err))
10516+ goto out_unlock;
10517+ au_unpin(&pin);
1308ab2a 10518+
4a4d8108
AM
10519+ err = -ENOSYS;
10520+ h_file = au_hf_top(file);
10521+ if (h_file->f_op && h_file->f_op->aio_fsync) {
10522+ struct dentry *h_d;
10523+ struct mutex *h_mtx;
1308ab2a 10524+
4a4d8108
AM
10525+ h_d = h_file->f_dentry;
10526+ h_mtx = &h_d->d_inode->i_mutex;
10527+ if (!is_sync_kiocb(kio)) {
10528+ get_file(h_file);
10529+ fput(file);
10530+ }
10531+ kio->ki_filp = h_file;
10532+ err = h_file->f_op->aio_fsync(kio, datasync);
10533+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
10534+ if (!err)
10535+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
10536+ /*ignore*/
10537+ au_cpup_attr_timesizes(inode);
10538+ mutex_unlock(h_mtx);
10539+ }
1308ab2a 10540+
4f0767ce 10541+out_unlock:
4a4d8108
AM
10542+ di_read_unlock(dentry, AuLock_IR);
10543+ fi_write_unlock(file);
4f0767ce 10544+out:
e49829fe 10545+ si_read_unlock(inode->sb);
4a4d8108
AM
10546+ mutex_unlock(&inode->i_mutex);
10547+ return err;
dece6358 10548+}
4a4d8108 10549+#endif
dece6358 10550+
4a4d8108 10551+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 10552+{
4a4d8108
AM
10553+ int err;
10554+ struct file *h_file;
10555+ struct dentry *dentry;
10556+ struct super_block *sb;
1308ab2a 10557+
4a4d8108
AM
10558+ dentry = file->f_dentry;
10559+ sb = dentry->d_sb;
e49829fe 10560+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
10561+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
10562+ if (unlikely(err))
10563+ goto out;
10564+
10565+ h_file = au_hf_top(file);
10566+ if (h_file->f_op && h_file->f_op->fasync)
10567+ err = h_file->f_op->fasync(fd, h_file, flag);
10568+
10569+ di_read_unlock(dentry, AuLock_IR);
10570+ fi_read_unlock(file);
1308ab2a 10571+
4f0767ce 10572+out:
4a4d8108 10573+ si_read_unlock(sb);
1308ab2a 10574+ return err;
dece6358 10575+}
4a4d8108
AM
10576+
10577+/* ---------------------------------------------------------------------- */
10578+
10579+/* no one supports this operation, currently */
10580+#if 0
10581+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
10582+ size_t len, loff_t *pos , int more)
10583+{
10584+}
10585+#endif
10586+
10587+/* ---------------------------------------------------------------------- */
10588+
10589+const struct file_operations aufs_file_fop = {
10590+ .owner = THIS_MODULE,
10591+ /*
10592+ * while generic_file_llseek/_unlocked() don't use BKL,
10593+ * don't use it since it operates file->f_mapping->host.
10594+ * in aufs, it may be a real file and may confuse users by UDBA.
10595+ */
10596+ /* .llseek = generic_file_llseek, */
027c5e7a 10597+ .llseek = default_llseek,
4a4d8108
AM
10598+
10599+ .read = aufs_read,
10600+ .write = aufs_write,
10601+ .aio_read = aufs_aio_read,
10602+ .aio_write = aufs_aio_write,
10603+#ifdef CONFIG_AUFS_POLL
10604+ .poll = aufs_poll,
10605+#endif
10606+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
10607+#ifdef CONFIG_COMPAT
10608+ .compat_ioctl = aufs_ioctl_nondir, /* same */
10609+#endif
4a4d8108
AM
10610+ .mmap = aufs_mmap,
10611+ .open = aufs_open_nondir,
10612+ .flush = aufs_flush_nondir,
10613+ .release = aufs_release_nondir,
10614+ .fsync = aufs_fsync_nondir,
10615+ /* .aio_fsync = aufs_aio_fsync_nondir, */
10616+ .fasync = aufs_fasync,
10617+ /* .sendpage = aufs_sendpage, */
10618+ .splice_write = aufs_splice_write,
10619+ .splice_read = aufs_splice_read,
10620+#if 0
10621+ .aio_splice_write = aufs_aio_splice_write,
10622+ .aio_splice_read = aufs_aio_splice_read
10623+#endif
10624+};
7f207e10
AM
10625diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
10626--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a 10627+++ linux/fs/aufs/f_op_sp.c 2011-03-21 20:22:06.853935428 +0100
e49829fe 10628@@ -0,0 +1,299 @@
1308ab2a 10629+/*
027c5e7a 10630+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1308ab2a 10631+ *
10632+ * This program, aufs is free software; you can redistribute it and/or modify
10633+ * it under the terms of the GNU General Public License as published by
10634+ * the Free Software Foundation; either version 2 of the License, or
10635+ * (at your option) any later version.
10636+ *
10637+ * This program is distributed in the hope that it will be useful,
10638+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10639+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10640+ * GNU General Public License for more details.
10641+ *
10642+ * You should have received a copy of the GNU General Public License
10643+ * along with this program; if not, write to the Free Software
10644+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10645+ */
dece6358 10646+
1308ab2a 10647+/*
4a4d8108
AM
10648+ * file operations for special files.
10649+ * while they exist in aufs virtually,
10650+ * their file I/O is handled out of aufs.
1308ab2a 10651+ */
10652+
4a4d8108
AM
10653+#include <linux/fs_stack.h>
10654+#include "aufs.h"
1308ab2a 10655+
4a4d8108
AM
10656+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
10657+ unsigned long nv, loff_t pos)
dece6358 10658+{
4a4d8108
AM
10659+ ssize_t err;
10660+ aufs_bindex_t bstart;
10661+ unsigned char wbr;
10662+ struct file *file, *h_file;
10663+ struct super_block *sb;
1308ab2a 10664+
4a4d8108
AM
10665+ file = kio->ki_filp;
10666+ sb = file->f_dentry->d_sb;
10667+ si_read_lock(sb, AuLock_FLUSH);
10668+ fi_read_lock(file);
10669+ bstart = au_fbstart(file);
10670+ h_file = au_hf_top(file);
10671+ fi_read_unlock(file);
10672+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
10673+ si_read_unlock(sb);
10674+
10675+ /* do not change the file in kio */
10676+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
10677+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
10678+ if (err > 0 && wbr)
10679+ file_accessed(h_file);
10680+
10681+ return err;
10682+}
10683+
10684+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
10685+ unsigned long nv, loff_t pos)
10686+{
10687+ ssize_t err;
10688+ aufs_bindex_t bstart;
10689+ unsigned char wbr;
10690+ struct super_block *sb;
10691+ struct file *file, *h_file;
10692+
10693+ file = kio->ki_filp;
10694+ sb = file->f_dentry->d_sb;
10695+ si_read_lock(sb, AuLock_FLUSH);
10696+ fi_read_lock(file);
10697+ bstart = au_fbstart(file);
10698+ h_file = au_hf_top(file);
10699+ fi_read_unlock(file);
10700+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
10701+ si_read_unlock(sb);
10702+
10703+ /* do not change the file in kio */
10704+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
10705+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
10706+ if (err > 0 && wbr)
10707+ file_update_time(h_file);
10708+
10709+ return err;
10710+}
10711+
10712+/* ---------------------------------------------------------------------- */
10713+
10714+static int aufs_release_sp(struct inode *inode, struct file *file)
10715+{
10716+ int err;
10717+ struct file *h_file;
10718+
10719+ fi_read_lock(file);
10720+ h_file = au_hf_top(file);
10721+ fi_read_unlock(file);
10722+ /* close this fifo in aufs */
10723+ err = h_file->f_op->release(inode, file); /* ignore */
10724+ aufs_release_nondir(inode, file); /* ignore */
10725+ return err;
10726+}
10727+
10728+/* ---------------------------------------------------------------------- */
10729+
10730+/* currently, support only FIFO */
4f0767ce
JR
10731+enum {
10732+ AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
10733+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
10734+ AuSp_Last
10735+};
4a4d8108
AM
10736+static int aufs_open_sp(struct inode *inode, struct file *file);
10737+static struct au_sp_fop {
10738+ int done;
10739+ struct file_operations fop; /* not 'const' */
10740+ spinlock_t spin;
10741+} au_sp_fop[AuSp_Last] = {
10742+ [AuSp_FIFO] = {
10743+ .fop = {
10744+ .owner = THIS_MODULE,
10745+ .open = aufs_open_sp
10746+ }
10747+ }
10748+};
10749+
10750+static void au_init_fop_sp(struct file *file)
10751+{
10752+ struct au_sp_fop *p;
10753+ int i;
10754+ struct file *h_file;
10755+
10756+ p = au_sp_fop;
10757+ if (unlikely(!p->done)) {
10758+ /* initialize first time only */
10759+ static DEFINE_SPINLOCK(spin);
10760+
10761+ spin_lock(&spin);
10762+ if (!p->done) {
10763+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
10764+ != AuSp_Last);
10765+ for (i = 0; i < AuSp_Last; i++)
10766+ spin_lock_init(&p[i].spin);
10767+ p->done = 1;
10768+ }
10769+ spin_unlock(&spin);
10770+ }
10771+
10772+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
10773+ case FMODE_READ:
10774+ i = AuSp_FIFO_R;
10775+ break;
10776+ case FMODE_WRITE:
10777+ i = AuSp_FIFO_W;
10778+ break;
10779+ case FMODE_READ | FMODE_WRITE:
10780+ i = AuSp_FIFO_RW;
10781+ break;
10782+ default:
10783+ BUG();
10784+ }
10785+
10786+ p += i;
10787+ if (unlikely(!p->done)) {
10788+ /* initialize first time only */
10789+ h_file = au_hf_top(file);
10790+ spin_lock(&p->spin);
10791+ if (!p->done) {
10792+ p->fop = *h_file->f_op;
10793+ p->fop.owner = THIS_MODULE;
10794+ if (p->fop.aio_read)
10795+ p->fop.aio_read = aufs_aio_read_sp;
10796+ if (p->fop.aio_write)
10797+ p->fop.aio_write = aufs_aio_write_sp;
10798+ p->fop.release = aufs_release_sp;
10799+ p->done = 1;
10800+ }
10801+ spin_unlock(&p->spin);
10802+ }
10803+ file->f_op = &p->fop;
10804+}
10805+
10806+static int au_cpup_sp(struct dentry *dentry)
10807+{
10808+ int err;
10809+ aufs_bindex_t bcpup;
10810+ struct au_pin pin;
10811+ struct au_wr_dir_args wr_dir_args = {
10812+ .force_btgt = -1,
10813+ .flags = 0
10814+ };
10815+
10816+ AuDbg("%.*s\n", AuDLNPair(dentry));
10817+
10818+ di_read_unlock(dentry, AuLock_IR);
10819+ di_write_lock_child(dentry);
10820+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
10821+ if (unlikely(err < 0))
10822+ goto out;
10823+ bcpup = err;
10824+ err = 0;
10825+ if (bcpup == au_dbstart(dentry))
10826+ goto out; /* success */
10827+
10828+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
10829+ AuPin_MNT_WRITE);
10830+ if (!err) {
10831+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
10832+ au_unpin(&pin);
10833+ }
10834+
4f0767ce 10835+out:
4a4d8108
AM
10836+ di_downgrade_lock(dentry, AuLock_IR);
10837+ return err;
10838+}
10839+
10840+static int au_do_open_sp(struct file *file, int flags)
10841+{
10842+ int err;
10843+ struct dentry *dentry;
10844+ struct super_block *sb;
10845+ struct file *h_file;
10846+ struct inode *h_inode;
10847+
10848+ dentry = file->f_dentry;
10849+ AuDbg("%.*s\n", AuDLNPair(dentry));
10850+
10851+ /*
10852+ * try copying-up.
10853+ * operate on the ro branch is not an error.
10854+ */
10855+ au_cpup_sp(dentry); /* ignore */
10856+
10857+ /* prepare h_file */
10858+ err = au_do_open_nondir(file, vfsub_file_flags(file));
10859+ if (unlikely(err))
10860+ goto out;
10861+
10862+ sb = dentry->d_sb;
10863+ h_file = au_hf_top(file);
10864+ h_inode = h_file->f_dentry->d_inode;
10865+ di_read_unlock(dentry, AuLock_IR);
10866+ fi_write_unlock(file);
10867+ si_read_unlock(sb);
10868+ /* open this fifo in aufs */
10869+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
10870+ si_noflush_read_lock(sb);
10871+ fi_write_lock(file);
10872+ di_read_lock_child(dentry, AuLock_IR);
10873+ if (!err)
10874+ au_init_fop_sp(file);
4a4d8108 10875+
4f0767ce 10876+out:
4a4d8108
AM
10877+ return err;
10878+}
10879+
10880+static int aufs_open_sp(struct inode *inode, struct file *file)
10881+{
10882+ int err;
10883+ struct super_block *sb;
10884+
10885+ sb = file->f_dentry->d_sb;
10886+ si_read_lock(sb, AuLock_FLUSH);
10887+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
10888+ si_read_unlock(sb);
10889+ return err;
10890+}
10891+
10892+/* ---------------------------------------------------------------------- */
10893+
10894+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
10895+{
10896+ init_special_inode(inode, mode, rdev);
10897+
10898+ switch (mode & S_IFMT) {
10899+ case S_IFIFO:
10900+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
10901+ /*FALLTHROUGH*/
10902+ case S_IFCHR:
10903+ case S_IFBLK:
10904+ case S_IFSOCK:
10905+ break;
10906+ default:
10907+ AuDebugOn(1);
10908+ }
10909+}
10910+
10911+int au_special_file(umode_t mode)
10912+{
10913+ int ret;
10914+
10915+ ret = 0;
10916+ switch (mode & S_IFMT) {
10917+ case S_IFIFO:
10918+#if 0
10919+ case S_IFCHR:
10920+ case S_IFBLK:
10921+ case S_IFSOCK:
10922+#endif
10923+ ret = 1;
10924+ }
10925+
10926+ return ret;
10927+}
7f207e10
AM
10928diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
10929--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 10930+++ linux/fs/aufs/fstype.h 2011-03-21 20:22:06.853935428 +0100
4a4d8108
AM
10931@@ -0,0 +1,497 @@
10932+/*
027c5e7a 10933+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
10934+ *
10935+ * This program, aufs is free software; you can redistribute it and/or modify
10936+ * it under the terms of the GNU General Public License as published by
10937+ * the Free Software Foundation; either version 2 of the License, or
10938+ * (at your option) any later version.
10939+ *
10940+ * This program is distributed in the hope that it will be useful,
10941+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10942+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10943+ * GNU General Public License for more details.
10944+ *
10945+ * You should have received a copy of the GNU General Public License
10946+ * along with this program; if not, write to the Free Software
10947+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10948+ */
10949+
10950+/*
10951+ * judging filesystem type
10952+ */
10953+
10954+#ifndef __AUFS_FSTYPE_H__
10955+#define __AUFS_FSTYPE_H__
10956+
10957+#ifdef __KERNEL__
10958+
10959+#include <linux/fs.h>
10960+#include <linux/magic.h>
10961+#include <linux/romfs_fs.h>
10962+#include <linux/aufs_type.h>
10963+
10964+static inline int au_test_aufs(struct super_block *sb)
10965+{
10966+ return sb->s_magic == AUFS_SUPER_MAGIC;
10967+}
10968+
10969+static inline const char *au_sbtype(struct super_block *sb)
10970+{
10971+ return sb->s_type->name;
10972+}
1308ab2a 10973+
10974+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
10975+{
10976+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
10977+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
10978+#else
10979+ return 0;
10980+#endif
10981+}
10982+
1308ab2a 10983+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 10984+{
1308ab2a 10985+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
10986+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
10987+#else
10988+ return 0;
10989+#endif
10990+}
10991+
1308ab2a 10992+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 10993+{
1308ab2a 10994+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
10995+ return sb->s_magic == CRAMFS_MAGIC;
10996+#endif
10997+ return 0;
10998+}
10999+
11000+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
11001+{
11002+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
11003+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
11004+#else
11005+ return 0;
11006+#endif
11007+}
11008+
1308ab2a 11009+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 11010+{
1308ab2a 11011+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
11012+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
11013+#else
11014+ return 0;
11015+#endif
11016+}
11017+
1308ab2a 11018+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 11019+{
1308ab2a 11020+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
11021+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
11022+#else
11023+ return 0;
11024+#endif
11025+}
11026+
1308ab2a 11027+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 11028+{
1308ab2a 11029+#ifdef CONFIG_TMPFS
11030+ return sb->s_magic == TMPFS_MAGIC;
11031+#else
11032+ return 0;
dece6358 11033+#endif
dece6358
AM
11034+}
11035+
1308ab2a 11036+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 11037+{
1308ab2a 11038+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
11039+ return !strcmp(au_sbtype(sb), "ecryptfs");
11040+#else
11041+ return 0;
11042+#endif
1facf9fc 11043+}
11044+
1308ab2a 11045+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 11046+{
1308ab2a 11047+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
11048+ return sb->s_magic == SMB_SUPER_MAGIC;
11049+#else
11050+ return 0;
1facf9fc 11051+#endif
1facf9fc 11052+}
11053+
1308ab2a 11054+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 11055+{
1308ab2a 11056+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
11057+ return sb->s_magic == OCFS2_SUPER_MAGIC;
11058+#else
11059+ return 0;
11060+#endif
1facf9fc 11061+}
11062+
1308ab2a 11063+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 11064+{
1308ab2a 11065+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
11066+ return sb->s_magic == DLMFS_MAGIC;
11067+#else
11068+ return 0;
11069+#endif
1facf9fc 11070+}
11071+
1308ab2a 11072+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 11073+{
1308ab2a 11074+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
11075+ return sb->s_magic == CODA_SUPER_MAGIC;
11076+#else
11077+ return 0;
11078+#endif
11079+}
11080+
11081+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
11082+{
11083+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
11084+ return sb->s_magic == V9FS_MAGIC;
11085+#else
11086+ return 0;
11087+#endif
11088+}
11089+
11090+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
11091+{
11092+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
11093+ return sb->s_magic == EXT4_SUPER_MAGIC;
11094+#else
11095+ return 0;
11096+#endif
11097+}
11098+
11099+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
11100+{
11101+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
11102+ return !strcmp(au_sbtype(sb), "sysv");
11103+#else
11104+ return 0;
11105+#endif
11106+}
11107+
11108+static inline int au_test_ramfs(struct super_block *sb)
11109+{
11110+ return sb->s_magic == RAMFS_MAGIC;
11111+}
11112+
11113+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
11114+{
11115+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
11116+ return sb->s_magic == UBIFS_SUPER_MAGIC;
11117+#else
11118+ return 0;
11119+#endif
11120+}
11121+
11122+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
11123+{
11124+#ifdef CONFIG_PROC_FS
11125+ return sb->s_magic == PROC_SUPER_MAGIC;
11126+#else
11127+ return 0;
11128+#endif
11129+}
11130+
11131+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
11132+{
11133+#ifdef CONFIG_SYSFS
11134+ return sb->s_magic == SYSFS_MAGIC;
11135+#else
11136+ return 0;
11137+#endif
11138+}
11139+
11140+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
11141+{
11142+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
11143+ return sb->s_magic == CONFIGFS_MAGIC;
11144+#else
11145+ return 0;
11146+#endif
11147+}
11148+
11149+static inline int au_test_minix(struct super_block *sb __maybe_unused)
11150+{
11151+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
11152+ return sb->s_magic == MINIX3_SUPER_MAGIC
11153+ || sb->s_magic == MINIX2_SUPER_MAGIC
11154+ || sb->s_magic == MINIX2_SUPER_MAGIC2
11155+ || sb->s_magic == MINIX_SUPER_MAGIC
11156+ || sb->s_magic == MINIX_SUPER_MAGIC2;
11157+#else
11158+ return 0;
11159+#endif
11160+}
11161+
11162+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
11163+{
11164+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
11165+ return sb->s_magic == CIFS_MAGIC_NUMBER;
11166+#else
11167+ return 0;
11168+#endif
11169+}
11170+
11171+static inline int au_test_fat(struct super_block *sb __maybe_unused)
11172+{
11173+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
11174+ return sb->s_magic == MSDOS_SUPER_MAGIC;
11175+#else
11176+ return 0;
11177+#endif
11178+}
11179+
11180+static inline int au_test_msdos(struct super_block *sb)
11181+{
11182+ return au_test_fat(sb);
11183+}
11184+
11185+static inline int au_test_vfat(struct super_block *sb)
11186+{
11187+ return au_test_fat(sb);
11188+}
11189+
11190+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
11191+{
11192+#ifdef CONFIG_SECURITYFS
11193+ return sb->s_magic == SECURITYFS_MAGIC;
11194+#else
11195+ return 0;
11196+#endif
11197+}
11198+
11199+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
11200+{
11201+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
11202+ return sb->s_magic == SQUASHFS_MAGIC;
11203+#else
11204+ return 0;
11205+#endif
11206+}
11207+
11208+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
11209+{
11210+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
11211+ return sb->s_magic == BTRFS_SUPER_MAGIC;
11212+#else
11213+ return 0;
11214+#endif
11215+}
11216+
11217+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
11218+{
11219+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
11220+ return sb->s_magic == XENFS_SUPER_MAGIC;
11221+#else
11222+ return 0;
11223+#endif
11224+}
11225+
11226+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
11227+{
11228+#ifdef CONFIG_DEBUG_FS
11229+ return sb->s_magic == DEBUGFS_MAGIC;
11230+#else
11231+ return 0;
11232+#endif
11233+}
11234+
11235+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
11236+{
11237+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
11238+ return sb->s_magic == NILFS_SUPER_MAGIC;
11239+#else
11240+ return 0;
11241+#endif
11242+}
11243+
4a4d8108
AM
11244+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
11245+{
11246+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
11247+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
11248+#else
11249+ return 0;
11250+#endif
11251+}
11252+
1308ab2a 11253+/* ---------------------------------------------------------------------- */
11254+/*
11255+ * they can't be an aufs branch.
11256+ */
11257+static inline int au_test_fs_unsuppoted(struct super_block *sb)
11258+{
11259+ return
11260+#ifndef CONFIG_AUFS_BR_RAMFS
11261+ au_test_ramfs(sb) ||
11262+#endif
11263+ au_test_procfs(sb)
11264+ || au_test_sysfs(sb)
11265+ || au_test_configfs(sb)
11266+ || au_test_debugfs(sb)
11267+ || au_test_securityfs(sb)
11268+ || au_test_xenfs(sb)
11269+ || au_test_ecryptfs(sb)
11270+ /* || !strcmp(au_sbtype(sb), "unionfs") */
11271+ || au_test_aufs(sb); /* will be supported in next version */
11272+}
11273+
11274+/*
11275+ * If the filesystem supports NFS-export, then it has to support NULL as
11276+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
11277+ * We can apply this principle when we handle a lower filesystem.
11278+ */
11279+static inline int au_test_fs_null_nd(struct super_block *sb)
11280+{
11281+ return !!sb->s_export_op;
11282+}
11283+
11284+static inline int au_test_fs_remote(struct super_block *sb)
11285+{
11286+ return !au_test_tmpfs(sb)
11287+#ifdef CONFIG_AUFS_BR_RAMFS
11288+ && !au_test_ramfs(sb)
11289+#endif
11290+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
11291+}
11292+
11293+/* ---------------------------------------------------------------------- */
11294+
11295+/*
11296+ * Note: these functions (below) are created after reading ->getattr() in all
11297+ * filesystems under linux/fs. it means we have to do so in every update...
11298+ */
11299+
11300+/*
11301+ * some filesystems require getattr to refresh the inode attributes before
11302+ * referencing.
11303+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
11304+ * and leave the work for d_revalidate()
11305+ */
11306+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
11307+{
11308+ return au_test_nfs(sb)
11309+ || au_test_fuse(sb)
11310+ /* || au_test_smbfs(sb) */ /* untested */
11311+ /* || au_test_ocfs2(sb) */ /* untested */
11312+ /* || au_test_btrfs(sb) */ /* untested */
11313+ /* || au_test_coda(sb) */ /* untested */
11314+ /* || au_test_v9fs(sb) */ /* untested */
11315+ ;
11316+}
11317+
11318+/*
11319+ * filesystems which don't maintain i_size or i_blocks.
11320+ */
11321+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
11322+{
11323+ return au_test_xfs(sb)
4a4d8108
AM
11324+ || au_test_btrfs(sb)
11325+ || au_test_ubifs(sb)
11326+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 11327+ /* || au_test_ext4(sb) */ /* untested */
11328+ /* || au_test_ocfs2(sb) */ /* untested */
11329+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
11330+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 11331+ /* || au_test_minix(sb) */ /* untested */
11332+ ;
11333+}
11334+
11335+/*
11336+ * filesystems which don't store the correct value in some of their inode
11337+ * attributes.
11338+ */
11339+static inline int au_test_fs_bad_iattr(struct super_block *sb)
11340+{
11341+ return au_test_fs_bad_iattr_size(sb)
11342+ /* || au_test_cifs(sb) */ /* untested */
11343+ || au_test_fat(sb)
11344+ || au_test_msdos(sb)
11345+ || au_test_vfat(sb);
1facf9fc 11346+}
11347+
11348+/* they don't check i_nlink in link(2) */
11349+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
11350+{
11351+ return au_test_tmpfs(sb)
11352+#ifdef CONFIG_AUFS_BR_RAMFS
11353+ || au_test_ramfs(sb)
11354+#endif
4a4d8108
AM
11355+ || au_test_ubifs(sb)
11356+ || au_test_btrfs(sb)
11357+ || au_test_hfsplus(sb);
1facf9fc 11358+}
11359+
11360+/*
11361+ * filesystems which sets S_NOATIME and S_NOCMTIME.
11362+ */
11363+static inline int au_test_fs_notime(struct super_block *sb)
11364+{
11365+ return au_test_nfs(sb)
11366+ || au_test_fuse(sb)
dece6358 11367+ || au_test_ubifs(sb)
1facf9fc 11368+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 11369+ ;
11370+}
11371+
11372+/*
11373+ * filesystems which requires replacing i_mapping.
11374+ */
11375+static inline int au_test_fs_bad_mapping(struct super_block *sb)
11376+{
dece6358
AM
11377+ return au_test_fuse(sb)
11378+ || au_test_ubifs(sb);
1facf9fc 11379+}
11380+
11381+/* temporary support for i#1 in cramfs */
11382+static inline int au_test_fs_unique_ino(struct inode *inode)
11383+{
11384+ if (au_test_cramfs(inode->i_sb))
11385+ return inode->i_ino != 1;
11386+ return 1;
11387+}
11388+
11389+/* ---------------------------------------------------------------------- */
11390+
11391+/*
11392+ * the filesystem where the xino files placed must support i/o after unlink and
11393+ * maintain i_size and i_blocks.
11394+ */
11395+static inline int au_test_fs_bad_xino(struct super_block *sb)
11396+{
11397+ return au_test_fs_remote(sb)
11398+ || au_test_fs_bad_iattr_size(sb)
11399+#ifdef CONFIG_AUFS_BR_RAMFS
11400+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
11401+#else
11402+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
11403+#endif
11404+ /* don't want unnecessary work for xino */
11405+ || au_test_aufs(sb)
1308ab2a 11406+ || au_test_ecryptfs(sb)
11407+ || au_test_nilfs(sb);
1facf9fc 11408+}
11409+
11410+static inline int au_test_fs_trunc_xino(struct super_block *sb)
11411+{
11412+ return au_test_tmpfs(sb)
11413+ || au_test_ramfs(sb);
11414+}
11415+
11416+/*
11417+ * test if the @sb is real-readonly.
11418+ */
11419+static inline int au_test_fs_rr(struct super_block *sb)
11420+{
11421+ return au_test_squashfs(sb)
11422+ || au_test_iso9660(sb)
11423+ || au_test_cramfs(sb)
11424+ || au_test_romfs(sb);
11425+}
11426+
11427+#endif /* __KERNEL__ */
11428+#endif /* __AUFS_FSTYPE_H__ */
7f207e10
AM
11429diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
11430--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
11431+++ linux/fs/aufs/hfsnotify.c 2011-03-21 20:22:06.853935428 +0100
11432@@ -0,0 +1,247 @@
1facf9fc 11433+/*
027c5e7a 11434+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 11435+ *
11436+ * This program, aufs is free software; you can redistribute it and/or modify
11437+ * it under the terms of the GNU General Public License as published by
11438+ * the Free Software Foundation; either version 2 of the License, or
11439+ * (at your option) any later version.
dece6358
AM
11440+ *
11441+ * This program is distributed in the hope that it will be useful,
11442+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11443+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11444+ * GNU General Public License for more details.
11445+ *
11446+ * You should have received a copy of the GNU General Public License
11447+ * along with this program; if not, write to the Free Software
11448+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 11449+ */
11450+
11451+/*
4a4d8108 11452+ * fsnotify for the lower directories
1facf9fc 11453+ */
11454+
11455+#include "aufs.h"
11456+
4a4d8108
AM
11457+/* FS_IN_IGNORED is unnecessary */
11458+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
11459+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 11460+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
1facf9fc 11461+
0c5527e5 11462+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 11463+{
0c5527e5
AM
11464+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
11465+ hn_mark);
4a4d8108 11466+ AuDbg("here\n");
7f207e10
AM
11467+ hn->hn_mark_dead = 1;
11468+ smp_mb();
11469+ wake_up_all(&au_hfsn_wq);
4a4d8108 11470+}
1facf9fc 11471+
027c5e7a 11472+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 11473+{
027c5e7a
AM
11474+ struct au_hnotify *hn;
11475+ struct super_block *sb;
11476+ struct au_branch *br;
0c5527e5 11477+ struct fsnotify_mark *mark;
027c5e7a 11478+ aufs_bindex_t bindex;
1facf9fc 11479+
027c5e7a
AM
11480+ hn = hinode->hi_notify;
11481+ sb = hn->hn_aufs_inode->i_sb;
11482+ bindex = au_br_index(sb, hinode->hi_id);
11483+ br = au_sbr(sb, bindex);
7f207e10 11484+ hn->hn_mark_dead = 0;
0c5527e5
AM
11485+ mark = &hn->hn_mark;
11486+ fsnotify_init_mark(mark, au_hfsn_free_mark);
11487+ mark->mask = AuHfsnMask;
7f207e10
AM
11488+ /*
11489+ * by udba rename or rmdir, aufs assign a new inode to the known
11490+ * h_inode, so specify 1 to allow dups.
11491+ */
027c5e7a
AM
11492+ return fsnotify_add_mark(mark, br->br_hfsn_group, hinode->hi_inode,
11493+ /*mnt*/NULL, /*allow_dups*/1);
1facf9fc 11494+}
11495+
027c5e7a 11496+static void au_hfsn_free(struct au_hinode *hinode)
1facf9fc 11497+{
027c5e7a 11498+ struct au_hnotify *hn;
0c5527e5 11499+ struct fsnotify_mark *mark;
953406b4 11500+
027c5e7a 11501+ hn = hinode->hi_notify;
0c5527e5
AM
11502+ mark = &hn->hn_mark;
11503+ fsnotify_destroy_mark(mark);
11504+ fsnotify_put_mark(mark);
7f207e10
AM
11505+
11506+ /* TODO: bad approach */
11507+ wait_event(au_hfsn_wq, hn->hn_mark_dead);
1facf9fc 11508+}
11509+
11510+/* ---------------------------------------------------------------------- */
11511+
4a4d8108 11512+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 11513+{
0c5527e5 11514+ struct fsnotify_mark *mark;
1facf9fc 11515+
0c5527e5
AM
11516+ mark = &hinode->hi_notify->hn_mark;
11517+ spin_lock(&mark->lock);
1facf9fc 11518+ if (do_set) {
0c5527e5
AM
11519+ AuDebugOn(mark->mask & AuHfsnMask);
11520+ mark->mask |= AuHfsnMask;
1facf9fc 11521+ } else {
0c5527e5
AM
11522+ AuDebugOn(!(mark->mask & AuHfsnMask));
11523+ mark->mask &= ~AuHfsnMask;
1facf9fc 11524+ }
0c5527e5 11525+ spin_unlock(&mark->lock);
4a4d8108 11526+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 11527+}
11528+
4a4d8108 11529+/* ---------------------------------------------------------------------- */
1facf9fc 11530+
4a4d8108
AM
11531+/* #define AuDbgHnotify */
11532+#ifdef AuDbgHnotify
11533+static char *au_hfsn_name(u32 mask)
11534+{
11535+#ifdef CONFIG_AUFS_DEBUG
11536+#define test_ret(flag) if (mask & flag) \
11537+ return #flag;
11538+ test_ret(FS_ACCESS);
11539+ test_ret(FS_MODIFY);
11540+ test_ret(FS_ATTRIB);
11541+ test_ret(FS_CLOSE_WRITE);
11542+ test_ret(FS_CLOSE_NOWRITE);
11543+ test_ret(FS_OPEN);
11544+ test_ret(FS_MOVED_FROM);
11545+ test_ret(FS_MOVED_TO);
11546+ test_ret(FS_CREATE);
11547+ test_ret(FS_DELETE);
11548+ test_ret(FS_DELETE_SELF);
11549+ test_ret(FS_MOVE_SELF);
11550+ test_ret(FS_UNMOUNT);
11551+ test_ret(FS_Q_OVERFLOW);
11552+ test_ret(FS_IN_IGNORED);
11553+ test_ret(FS_IN_ISDIR);
11554+ test_ret(FS_IN_ONESHOT);
11555+ test_ret(FS_EVENT_ON_CHILD);
11556+ return "";
11557+#undef test_ret
11558+#else
11559+ return "??";
11560+#endif
1facf9fc 11561+}
4a4d8108 11562+#endif
1facf9fc 11563+
11564+/* ---------------------------------------------------------------------- */
11565+
4a4d8108 11566+static int au_hfsn_handle_event(struct fsnotify_group *group,
0c5527e5
AM
11567+ struct fsnotify_mark *inode_mark,
11568+ struct fsnotify_mark *vfsmount_mark,
4a4d8108 11569+ struct fsnotify_event *event)
1facf9fc 11570+{
11571+ int err;
4a4d8108
AM
11572+ struct au_hnotify *hnotify;
11573+ struct inode *h_dir, *h_inode;
11574+ __u32 mask;
4a4d8108
AM
11575+ struct qstr h_child_qstr = {
11576+ .name = event->file_name,
11577+ .len = event->name_len
11578+ };
11579+
11580+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 11581+
11582+ err = 0;
0c5527e5 11583+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108
AM
11584+ mask = event->mask;
11585+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 11586+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 11587+ goto out;
1facf9fc 11588+
4a4d8108
AM
11589+ h_dir = event->to_tell;
11590+ h_inode = event->inode;
11591+#ifdef AuDbgHnotify
11592+ au_debug(1);
11593+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
11594+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
11595+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
11596+ h_dir->i_ino, mask, au_hfsn_name(mask),
11597+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
11598+ /* WARN_ON(1); */
1facf9fc 11599+ }
4a4d8108 11600+ au_debug(0);
1facf9fc 11601+#endif
4a4d8108 11602+
0c5527e5
AM
11603+ AuDebugOn(!inode_mark);
11604+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
11605+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
1facf9fc 11606+
4a4d8108
AM
11607+out:
11608+ return err;
11609+}
1facf9fc 11610+
027c5e7a 11611+/* isn't it waste to ask every registered 'group'? */
7f207e10 11612+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
4a4d8108 11613+/* it should be exported to modules */
7f207e10
AM
11614+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
11615+ struct inode *h_inode,
0c5527e5
AM
11616+ struct fsnotify_mark *inode_mark,
11617+ struct fsnotify_mark *vfsmount_mark,
11618+ __u32 mask, void *data, int data_type)
4a4d8108 11619+{
4a4d8108 11620+ mask = (mask & ~FS_EVENT_ON_CHILD);
7f207e10 11621+ return inode_mark->mask & mask;
4a4d8108
AM
11622+}
11623+
11624+static struct fsnotify_ops au_hfsn_ops = {
11625+ .should_send_event = au_hfsn_should_send_event,
11626+ .handle_event = au_hfsn_handle_event
11627+};
11628+
11629+/* ---------------------------------------------------------------------- */
11630+
027c5e7a
AM
11631+static void au_hfsn_fin_br(struct au_branch *br)
11632+{
11633+ if (br->br_hfsn_group)
11634+ fsnotify_put_group(br->br_hfsn_group);
11635+}
11636+
11637+static int au_hfsn_init_br(struct au_branch *br, int perm)
11638+{
11639+ br->br_hfsn_group = NULL;
11640+ br->br_hfsn_ops = au_hfsn_ops;
11641+ return 0;
11642+}
11643+
11644+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
4a4d8108
AM
11645+{
11646+ int err;
1facf9fc 11647+
4a4d8108 11648+ err = 0;
027c5e7a
AM
11649+ if (udba != AuOpt_UDBA_HNOTIFY
11650+ || !au_br_hnotifyable(perm)) {
11651+ au_hfsn_fin_br(br);
11652+ br->br_hfsn_group = NULL;
11653+ goto out;
11654+ }
11655+
11656+ if (br->br_hfsn_group)
11657+ goto out;
11658+
11659+ br->br_hfsn_group = fsnotify_alloc_group(&br->br_hfsn_ops);
11660+ if (IS_ERR(br->br_hfsn_group)) {
11661+ err = PTR_ERR(br->br_hfsn_group);
0c5527e5 11662+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
027c5e7a 11663+ br->br_hfsn_group = NULL;
4a4d8108 11664+ }
1facf9fc 11665+
027c5e7a 11666+out:
1facf9fc 11667+ AuTraceErr(err);
11668+ return err;
11669+}
11670+
4a4d8108
AM
11671+const struct au_hnotify_op au_hnotify_op = {
11672+ .ctl = au_hfsn_ctl,
11673+ .alloc = au_hfsn_alloc,
11674+ .free = au_hfsn_free,
1facf9fc 11675+
027c5e7a
AM
11676+ .reset_br = au_hfsn_reset_br,
11677+ .fin_br = au_hfsn_fin_br,
11678+ .init_br = au_hfsn_init_br
4a4d8108 11679+};
7f207e10
AM
11680diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
11681--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a 11682+++ linux/fs/aufs/hfsplus.c 2011-03-21 20:22:06.853935428 +0100
4a4d8108
AM
11683@@ -0,0 +1,58 @@
11684+/*
027c5e7a 11685+ * Copyright (C) 2010-2011 Junjiro R. Okajima
4a4d8108
AM
11686+ *
11687+ * This program, aufs is free software; you can redistribute it and/or modify
11688+ * it under the terms of the GNU General Public License as published by
11689+ * the Free Software Foundation; either version 2 of the License, or
11690+ * (at your option) any later version.
11691+ *
11692+ * This program is distributed in the hope that it will be useful,
11693+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11694+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11695+ * GNU General Public License for more details.
11696+ *
11697+ * You should have received a copy of the GNU General Public License
11698+ * along with this program; if not, write to the Free Software
11699+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11700+ */
1facf9fc 11701+
4a4d8108
AM
11702+/*
11703+ * special support for filesystems which aqucires an inode mutex
11704+ * at final closing a file, eg, hfsplus.
11705+ *
11706+ * This trick is very simple and stupid, just to open the file before really
11707+ * neceeary open to tell hfsplus that this is not the final closing.
11708+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
11709+ * and au_h_open_post() after releasing it.
11710+ */
1facf9fc 11711+
4a4d8108
AM
11712+#include <linux/file.h>
11713+#include "aufs.h"
1facf9fc 11714+
4a4d8108
AM
11715+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
11716+{
11717+ struct file *h_file;
11718+ struct dentry *h_dentry;
1facf9fc 11719+
4a4d8108
AM
11720+ h_dentry = au_h_dptr(dentry, bindex);
11721+ AuDebugOn(!h_dentry);
11722+ AuDebugOn(!h_dentry->d_inode);
11723+ IMustLock(h_dentry->d_inode);
11724+
11725+ h_file = NULL;
11726+ if (au_test_hfsplus(h_dentry->d_sb)
11727+ && S_ISREG(h_dentry->d_inode->i_mode))
11728+ h_file = au_h_open(dentry, bindex,
11729+ O_RDONLY | O_NOATIME | O_LARGEFILE,
11730+ /*file*/NULL);
11731+ return h_file;
1facf9fc 11732+}
11733+
4a4d8108
AM
11734+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
11735+ struct file *h_file)
11736+{
11737+ if (h_file) {
11738+ fput(h_file);
11739+ au_sbr_put(dentry->d_sb, bindex);
11740+ }
11741+}
7f207e10
AM
11742diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
11743--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
11744+++ linux/fs/aufs/hnotify.c 2011-03-21 20:22:06.857268914 +0100
11745@@ -0,0 +1,709 @@
e49829fe 11746+/*
027c5e7a 11747+ * Copyright (C) 2005-2011 Junjiro R. Okajima
e49829fe
JR
11748+ *
11749+ * This program, aufs is free software; you can redistribute it and/or modify
11750+ * it under the terms of the GNU General Public License as published by
11751+ * the Free Software Foundation; either version 2 of the License, or
11752+ * (at your option) any later version.
11753+ *
11754+ * This program is distributed in the hope that it will be useful,
11755+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11756+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11757+ * GNU General Public License for more details.
11758+ *
11759+ * You should have received a copy of the GNU General Public License
11760+ * along with this program; if not, write to the Free Software
11761+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11762+ */
11763+
11764+/*
7f207e10 11765+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
11766+ */
11767+
11768+#include "aufs.h"
11769+
027c5e7a 11770+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
11771+{
11772+ int err;
7f207e10 11773+ struct au_hnotify *hn;
1facf9fc 11774+
4a4d8108
AM
11775+ err = -ENOMEM;
11776+ hn = au_cache_alloc_hnotify();
11777+ if (hn) {
11778+ hn->hn_aufs_inode = inode;
027c5e7a
AM
11779+ hinode->hi_notify = hn;
11780+ err = au_hnotify_op.alloc(hinode);
11781+ AuTraceErr(err);
11782+ if (unlikely(err)) {
11783+ hinode->hi_notify = NULL;
4a4d8108
AM
11784+ au_cache_free_hnotify(hn);
11785+ /*
11786+ * The upper dir was removed by udba, but the same named
11787+ * dir left. In this case, aufs assignes a new inode
11788+ * number and set the monitor again.
11789+ * For the lower dir, the old monitnor is still left.
11790+ */
11791+ if (err == -EEXIST)
11792+ err = 0;
11793+ }
1308ab2a 11794+ }
1308ab2a 11795+
027c5e7a 11796+ AuTraceErr(err);
1308ab2a 11797+ return err;
dece6358 11798+}
1facf9fc 11799+
4a4d8108 11800+void au_hn_free(struct au_hinode *hinode)
dece6358 11801+{
4a4d8108 11802+ struct au_hnotify *hn;
1facf9fc 11803+
4a4d8108
AM
11804+ hn = hinode->hi_notify;
11805+ if (hn) {
027c5e7a 11806+ au_hnotify_op.free(hinode);
4a4d8108
AM
11807+ au_cache_free_hnotify(hn);
11808+ hinode->hi_notify = NULL;
11809+ }
11810+}
dece6358 11811+
4a4d8108 11812+/* ---------------------------------------------------------------------- */
dece6358 11813+
4a4d8108
AM
11814+void au_hn_ctl(struct au_hinode *hinode, int do_set)
11815+{
11816+ if (hinode->hi_notify)
11817+ au_hnotify_op.ctl(hinode, do_set);
11818+}
11819+
11820+void au_hn_reset(struct inode *inode, unsigned int flags)
11821+{
11822+ aufs_bindex_t bindex, bend;
11823+ struct inode *hi;
11824+ struct dentry *iwhdentry;
1facf9fc 11825+
1308ab2a 11826+ bend = au_ibend(inode);
4a4d8108
AM
11827+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
11828+ hi = au_h_iptr(inode, bindex);
11829+ if (!hi)
11830+ continue;
1308ab2a 11831+
4a4d8108
AM
11832+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
11833+ iwhdentry = au_hi_wh(inode, bindex);
11834+ if (iwhdentry)
11835+ dget(iwhdentry);
11836+ au_igrab(hi);
11837+ au_set_h_iptr(inode, bindex, NULL, 0);
11838+ au_set_h_iptr(inode, bindex, au_igrab(hi),
11839+ flags & ~AuHi_XINO);
11840+ iput(hi);
11841+ dput(iwhdentry);
11842+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 11843+ }
1facf9fc 11844+}
11845+
1308ab2a 11846+/* ---------------------------------------------------------------------- */
1facf9fc 11847+
4a4d8108 11848+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 11849+{
4a4d8108
AM
11850+ int err;
11851+ aufs_bindex_t bindex, bend, bfound, bstart;
11852+ struct inode *h_i;
1facf9fc 11853+
4a4d8108
AM
11854+ err = 0;
11855+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11856+ pr_warning("branch root dir was changed\n");
11857+ goto out;
11858+ }
1facf9fc 11859+
4a4d8108
AM
11860+ bfound = -1;
11861+ bend = au_ibend(inode);
11862+ bstart = au_ibstart(inode);
11863+#if 0 /* reserved for future use */
11864+ if (bindex == bend) {
11865+ /* keep this ino in rename case */
11866+ goto out;
11867+ }
11868+#endif
11869+ for (bindex = bstart; bindex <= bend; bindex++)
11870+ if (au_h_iptr(inode, bindex) == h_inode) {
11871+ bfound = bindex;
11872+ break;
11873+ }
11874+ if (bfound < 0)
1308ab2a 11875+ goto out;
1facf9fc 11876+
4a4d8108
AM
11877+ for (bindex = bstart; bindex <= bend; bindex++) {
11878+ h_i = au_h_iptr(inode, bindex);
11879+ if (!h_i)
11880+ continue;
1facf9fc 11881+
4a4d8108
AM
11882+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
11883+ /* ignore this error */
11884+ /* bad action? */
1facf9fc 11885+ }
1facf9fc 11886+
4a4d8108 11887+ /* children inode number will be broken */
1facf9fc 11888+
4f0767ce 11889+out:
4a4d8108
AM
11890+ AuTraceErr(err);
11891+ return err;
1facf9fc 11892+}
11893+
4a4d8108 11894+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 11895+{
4a4d8108
AM
11896+ int err, i, j, ndentry;
11897+ struct au_dcsub_pages dpages;
11898+ struct au_dpage *dpage;
11899+ struct dentry **dentries;
1facf9fc 11900+
4a4d8108
AM
11901+ err = au_dpages_init(&dpages, GFP_NOFS);
11902+ if (unlikely(err))
11903+ goto out;
11904+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
11905+ if (unlikely(err))
11906+ goto out_dpages;
1facf9fc 11907+
4a4d8108
AM
11908+ for (i = 0; i < dpages.ndpage; i++) {
11909+ dpage = dpages.dpages + i;
11910+ dentries = dpage->dentries;
11911+ ndentry = dpage->ndentry;
11912+ for (j = 0; j < ndentry; j++) {
11913+ struct dentry *d;
11914+
11915+ d = dentries[j];
11916+ if (IS_ROOT(d))
11917+ continue;
11918+
4a4d8108
AM
11919+ au_digen_dec(d);
11920+ if (d->d_inode)
11921+ /* todo: reset children xino?
11922+ cached children only? */
11923+ au_iigen_dec(d->d_inode);
1308ab2a 11924+ }
dece6358 11925+ }
1facf9fc 11926+
4f0767ce 11927+out_dpages:
4a4d8108 11928+ au_dpages_free(&dpages);
dece6358 11929+
027c5e7a 11930+#if 0
4a4d8108
AM
11931+ /* discard children */
11932+ dentry_unhash(dentry);
11933+ dput(dentry);
027c5e7a 11934+#endif
4f0767ce 11935+out:
dece6358
AM
11936+ return err;
11937+}
11938+
1308ab2a 11939+/*
4a4d8108 11940+ * return 0 if processed.
1308ab2a 11941+ */
4a4d8108
AM
11942+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
11943+ const unsigned int isdir)
dece6358 11944+{
1308ab2a 11945+ int err;
4a4d8108
AM
11946+ struct dentry *d;
11947+ struct qstr *dname;
1facf9fc 11948+
4a4d8108
AM
11949+ err = 1;
11950+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11951+ pr_warning("branch root dir was changed\n");
11952+ err = 0;
11953+ goto out;
11954+ }
dece6358 11955+
4a4d8108
AM
11956+ if (!isdir) {
11957+ AuDebugOn(!name);
11958+ au_iigen_dec(inode);
027c5e7a 11959+ spin_lock(&inode->i_lock);
4a4d8108 11960+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
027c5e7a 11961+ spin_lock(&d->d_lock);
4a4d8108
AM
11962+ dname = &d->d_name;
11963+ if (dname->len != nlen
027c5e7a
AM
11964+ && memcmp(dname->name, name, nlen)) {
11965+ spin_unlock(&d->d_lock);
4a4d8108 11966+ continue;
027c5e7a 11967+ }
4a4d8108 11968+ err = 0;
4a4d8108
AM
11969+ au_digen_dec(d);
11970+ spin_unlock(&d->d_lock);
11971+ break;
1facf9fc 11972+ }
027c5e7a 11973+ spin_unlock(&inode->i_lock);
1308ab2a 11974+ } else {
027c5e7a 11975+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
11976+ d = d_find_alias(inode);
11977+ if (!d) {
11978+ au_iigen_dec(inode);
11979+ goto out;
11980+ }
1facf9fc 11981+
027c5e7a 11982+ spin_lock(&d->d_lock);
4a4d8108 11983+ dname = &d->d_name;
027c5e7a
AM
11984+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
11985+ spin_unlock(&d->d_lock);
4a4d8108 11986+ err = hn_gen_tree(d);
027c5e7a
AM
11987+ spin_lock(&d->d_lock);
11988+ }
11989+ spin_unlock(&d->d_lock);
4a4d8108
AM
11990+ dput(d);
11991+ }
1facf9fc 11992+
4f0767ce 11993+out:
4a4d8108 11994+ AuTraceErr(err);
1308ab2a 11995+ return err;
11996+}
dece6358 11997+
4a4d8108 11998+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 11999+{
4a4d8108
AM
12000+ int err;
12001+ struct inode *inode;
1facf9fc 12002+
4a4d8108
AM
12003+ inode = dentry->d_inode;
12004+ if (IS_ROOT(dentry)
12005+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
12006+ ) {
12007+ pr_warning("branch root dir was changed\n");
12008+ return 0;
12009+ }
1308ab2a 12010+
4a4d8108
AM
12011+ err = 0;
12012+ if (!isdir) {
4a4d8108
AM
12013+ au_digen_dec(dentry);
12014+ if (inode)
12015+ au_iigen_dec(inode);
12016+ } else {
027c5e7a 12017+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
12018+ if (inode)
12019+ err = hn_gen_tree(dentry);
12020+ }
12021+
12022+ AuTraceErr(err);
12023+ return err;
1facf9fc 12024+}
12025+
4a4d8108 12026+/* ---------------------------------------------------------------------- */
1facf9fc 12027+
4a4d8108
AM
12028+/* hnotify job flags */
12029+#define AuHnJob_XINO0 1
12030+#define AuHnJob_GEN (1 << 1)
12031+#define AuHnJob_DIRENT (1 << 2)
12032+#define AuHnJob_ISDIR (1 << 3)
12033+#define AuHnJob_TRYXINO0 (1 << 4)
12034+#define AuHnJob_MNTPNT (1 << 5)
12035+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
12036+#define au_fset_hnjob(flags, name) \
12037+ do { (flags) |= AuHnJob_##name; } while (0)
12038+#define au_fclr_hnjob(flags, name) \
12039+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 12040+
4a4d8108
AM
12041+enum {
12042+ AuHn_CHILD,
12043+ AuHn_PARENT,
12044+ AuHnLast
12045+};
1facf9fc 12046+
4a4d8108
AM
12047+struct au_hnotify_args {
12048+ struct inode *h_dir, *dir, *h_child_inode;
12049+ u32 mask;
12050+ unsigned int flags[AuHnLast];
12051+ unsigned int h_child_nlen;
12052+ char h_child_name[];
12053+};
1facf9fc 12054+
4a4d8108
AM
12055+struct hn_job_args {
12056+ unsigned int flags;
12057+ struct inode *inode, *h_inode, *dir, *h_dir;
12058+ struct dentry *dentry;
12059+ char *h_name;
12060+ int h_nlen;
12061+};
1308ab2a 12062+
4a4d8108
AM
12063+static int hn_job(struct hn_job_args *a)
12064+{
12065+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 12066+
4a4d8108
AM
12067+ /* reset xino */
12068+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
12069+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 12070+
4a4d8108
AM
12071+ if (au_ftest_hnjob(a->flags, TRYXINO0)
12072+ && a->inode
12073+ && a->h_inode) {
12074+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
12075+ if (!a->h_inode->i_nlink)
12076+ hn_xino(a->inode, a->h_inode); /* ignore this error */
12077+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 12078+ }
1facf9fc 12079+
4a4d8108
AM
12080+ /* make the generation obsolete */
12081+ if (au_ftest_hnjob(a->flags, GEN)) {
12082+ int err = -1;
12083+ if (a->inode)
12084+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
12085+ isdir);
12086+ if (err && a->dentry)
12087+ hn_gen_by_name(a->dentry, isdir);
12088+ /* ignore this error */
1facf9fc 12089+ }
1facf9fc 12090+
4a4d8108
AM
12091+ /* make dir entries obsolete */
12092+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
12093+ struct au_vdir *vdir;
1facf9fc 12094+
4a4d8108
AM
12095+ vdir = au_ivdir(a->inode);
12096+ if (vdir)
12097+ vdir->vd_jiffy = 0;
12098+ /* IMustLock(a->inode); */
12099+ /* a->inode->i_version++; */
12100+ }
1facf9fc 12101+
4a4d8108
AM
12102+ /* can do nothing but warn */
12103+ if (au_ftest_hnjob(a->flags, MNTPNT)
12104+ && a->dentry
12105+ && d_mountpoint(a->dentry))
12106+ pr_warning("mount-point %.*s is removed or renamed\n",
12107+ AuDLNPair(a->dentry));
1facf9fc 12108+
4a4d8108 12109+ return 0;
1308ab2a 12110+}
1facf9fc 12111+
1308ab2a 12112+/* ---------------------------------------------------------------------- */
1facf9fc 12113+
4a4d8108
AM
12114+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
12115+ struct inode *dir)
1308ab2a 12116+{
4a4d8108
AM
12117+ struct dentry *dentry, *d, *parent;
12118+ struct qstr *dname;
1308ab2a 12119+
4a4d8108
AM
12120+ parent = d_find_alias(dir);
12121+ if (!parent)
12122+ return NULL;
1308ab2a 12123+
4a4d8108 12124+ dentry = NULL;
027c5e7a 12125+ spin_lock(&parent->d_lock);
4a4d8108
AM
12126+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
12127+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
027c5e7a 12128+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
12129+ dname = &d->d_name;
12130+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
12131+ goto cont_unlock;
12132+ if (au_di(d))
12133+ au_digen_dec(d);
12134+ else
12135+ goto cont_unlock;
12136+ if (d->d_count) {
12137+ dentry = dget_dlock(d);
4a4d8108 12138+ spin_unlock(&d->d_lock);
027c5e7a 12139+ break;
dece6358 12140+ }
1facf9fc 12141+
027c5e7a
AM
12142+ cont_unlock:
12143+ spin_unlock(&d->d_lock);
1308ab2a 12144+ }
027c5e7a 12145+ spin_unlock(&parent->d_lock);
4a4d8108 12146+ dput(parent);
1facf9fc 12147+
4a4d8108
AM
12148+ if (dentry)
12149+ di_write_lock_child(dentry);
1308ab2a 12150+
4a4d8108
AM
12151+ return dentry;
12152+}
dece6358 12153+
4a4d8108
AM
12154+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
12155+ aufs_bindex_t bindex, ino_t h_ino)
12156+{
12157+ struct inode *inode;
12158+ ino_t ino;
12159+ int err;
12160+
12161+ inode = NULL;
12162+ err = au_xino_read(sb, bindex, h_ino, &ino);
12163+ if (!err && ino)
12164+ inode = ilookup(sb, ino);
12165+ if (!inode)
12166+ goto out;
12167+
12168+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
12169+ pr_warning("wrong root branch\n");
12170+ iput(inode);
12171+ inode = NULL;
12172+ goto out;
1308ab2a 12173+ }
12174+
4a4d8108 12175+ ii_write_lock_child(inode);
1308ab2a 12176+
4f0767ce 12177+out:
4a4d8108 12178+ return inode;
dece6358
AM
12179+}
12180+
4a4d8108 12181+static void au_hn_bh(void *_args)
1facf9fc 12182+{
4a4d8108
AM
12183+ struct au_hnotify_args *a = _args;
12184+ struct super_block *sb;
12185+ aufs_bindex_t bindex, bend, bfound;
12186+ unsigned char xino, try_iput;
1facf9fc 12187+ int err;
1308ab2a 12188+ struct inode *inode;
4a4d8108
AM
12189+ ino_t h_ino;
12190+ struct hn_job_args args;
12191+ struct dentry *dentry;
12192+ struct au_sbinfo *sbinfo;
1facf9fc 12193+
4a4d8108
AM
12194+ AuDebugOn(!_args);
12195+ AuDebugOn(!a->h_dir);
12196+ AuDebugOn(!a->dir);
12197+ AuDebugOn(!a->mask);
12198+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
12199+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
12200+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 12201+
4a4d8108
AM
12202+ inode = NULL;
12203+ dentry = NULL;
12204+ /*
12205+ * do not lock a->dir->i_mutex here
12206+ * because of d_revalidate() may cause a deadlock.
12207+ */
12208+ sb = a->dir->i_sb;
12209+ AuDebugOn(!sb);
12210+ sbinfo = au_sbi(sb);
12211+ AuDebugOn(!sbinfo);
7f207e10 12212+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 12213+
4a4d8108
AM
12214+ ii_read_lock_parent(a->dir);
12215+ bfound = -1;
12216+ bend = au_ibend(a->dir);
12217+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
12218+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
12219+ bfound = bindex;
12220+ break;
12221+ }
12222+ ii_read_unlock(a->dir);
12223+ if (unlikely(bfound < 0))
12224+ goto out;
1facf9fc 12225+
4a4d8108
AM
12226+ xino = !!au_opt_test(au_mntflags(sb), XINO);
12227+ h_ino = 0;
12228+ if (a->h_child_inode)
12229+ h_ino = a->h_child_inode->i_ino;
1facf9fc 12230+
4a4d8108
AM
12231+ if (a->h_child_nlen
12232+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
12233+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
12234+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
12235+ a->dir);
12236+ try_iput = 0;
12237+ if (dentry)
12238+ inode = dentry->d_inode;
12239+ if (xino && !inode && h_ino
12240+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
12241+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
12242+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
12243+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
12244+ try_iput = 1;
12245+ }
1facf9fc 12246+
4a4d8108
AM
12247+ args.flags = a->flags[AuHn_CHILD];
12248+ args.dentry = dentry;
12249+ args.inode = inode;
12250+ args.h_inode = a->h_child_inode;
12251+ args.dir = a->dir;
12252+ args.h_dir = a->h_dir;
12253+ args.h_name = a->h_child_name;
12254+ args.h_nlen = a->h_child_nlen;
12255+ err = hn_job(&args);
12256+ if (dentry) {
027c5e7a 12257+ if (au_di(dentry))
4a4d8108
AM
12258+ di_write_unlock(dentry);
12259+ dput(dentry);
12260+ }
12261+ if (inode && try_iput) {
12262+ ii_write_unlock(inode);
12263+ iput(inode);
12264+ }
1facf9fc 12265+
4a4d8108
AM
12266+ ii_write_lock_parent(a->dir);
12267+ args.flags = a->flags[AuHn_PARENT];
12268+ args.dentry = NULL;
12269+ args.inode = a->dir;
12270+ args.h_inode = a->h_dir;
12271+ args.dir = NULL;
12272+ args.h_dir = NULL;
12273+ args.h_name = NULL;
12274+ args.h_nlen = 0;
12275+ err = hn_job(&args);
12276+ ii_write_unlock(a->dir);
1facf9fc 12277+
4f0767ce 12278+out:
4a4d8108
AM
12279+ iput(a->h_child_inode);
12280+ iput(a->h_dir);
12281+ iput(a->dir);
027c5e7a
AM
12282+ si_write_unlock(sb);
12283+ au_nwt_done(&sbinfo->si_nowait);
1308ab2a 12284+ kfree(a);
dece6358 12285+}
1facf9fc 12286+
4a4d8108
AM
12287+/* ---------------------------------------------------------------------- */
12288+
12289+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
12290+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 12291+{
4a4d8108
AM
12292+ int err, len;
12293+ unsigned int flags[AuHnLast];
12294+ unsigned char isdir, isroot, wh;
12295+ struct inode *dir;
12296+ struct au_hnotify_args *args;
12297+ char *p, *h_child_name;
dece6358 12298+
1308ab2a 12299+ err = 0;
4a4d8108
AM
12300+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
12301+ dir = igrab(hnotify->hn_aufs_inode);
12302+ if (!dir)
12303+ goto out;
1facf9fc 12304+
4a4d8108
AM
12305+ isroot = (dir->i_ino == AUFS_ROOT_INO);
12306+ wh = 0;
12307+ h_child_name = (void *)h_child_qstr->name;
12308+ len = h_child_qstr->len;
12309+ if (h_child_name) {
12310+ if (len > AUFS_WH_PFX_LEN
12311+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
12312+ h_child_name += AUFS_WH_PFX_LEN;
12313+ len -= AUFS_WH_PFX_LEN;
12314+ wh = 1;
12315+ }
1facf9fc 12316+ }
dece6358 12317+
4a4d8108
AM
12318+ isdir = 0;
12319+ if (h_child_inode)
12320+ isdir = !!S_ISDIR(h_child_inode->i_mode);
12321+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
12322+ flags[AuHn_CHILD] = 0;
12323+ if (isdir)
12324+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
12325+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
12326+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
12327+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
12328+ case FS_MOVED_FROM:
12329+ case FS_MOVED_TO:
12330+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
12331+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
12332+ /*FALLTHROUGH*/
12333+ case FS_CREATE:
12334+ AuDebugOn(!h_child_name || !h_child_inode);
12335+ break;
1facf9fc 12336+
4a4d8108
AM
12337+ case FS_DELETE:
12338+ /*
12339+ * aufs never be able to get this child inode.
12340+ * revalidation should be in d_revalidate()
12341+ * by checking i_nlink, i_generation or d_unhashed().
12342+ */
12343+ AuDebugOn(!h_child_name);
12344+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
12345+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
12346+ break;
dece6358 12347+
4a4d8108
AM
12348+ default:
12349+ AuDebugOn(1);
12350+ }
1308ab2a 12351+
4a4d8108
AM
12352+ if (wh)
12353+ h_child_inode = NULL;
1308ab2a 12354+
4a4d8108
AM
12355+ err = -ENOMEM;
12356+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 12357+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
12358+ if (unlikely(!args)) {
12359+ AuErr1("no memory\n");
12360+ iput(dir);
12361+ goto out;
12362+ }
12363+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
12364+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
12365+ args->mask = mask;
12366+ args->dir = dir;
12367+ args->h_dir = igrab(h_dir);
12368+ if (h_child_inode)
12369+ h_child_inode = igrab(h_child_inode); /* can be NULL */
12370+ args->h_child_inode = h_child_inode;
12371+ args->h_child_nlen = len;
12372+ if (len) {
12373+ p = (void *)args;
12374+ p += sizeof(*args);
12375+ memcpy(p, h_child_name, len);
12376+ p[len] = 0;
1308ab2a 12377+ }
1308ab2a 12378+
4a4d8108 12379+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
4a4d8108
AM
12380+ if (unlikely(err)) {
12381+ pr_err("wkq %d\n", err);
12382+ iput(args->h_child_inode);
12383+ iput(args->h_dir);
12384+ iput(args->dir);
12385+ kfree(args);
1facf9fc 12386+ }
1facf9fc 12387+
4a4d8108 12388+out:
1facf9fc 12389+ return err;
12390+}
12391+
027c5e7a
AM
12392+/* ---------------------------------------------------------------------- */
12393+
12394+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
12395+{
12396+ int err;
12397+
12398+ AuDebugOn(!(udba & AuOptMask_UDBA));
12399+
12400+ err = 0;
12401+ if (au_hnotify_op.reset_br)
12402+ err = au_hnotify_op.reset_br(udba, br, perm);
12403+
12404+ return err;
12405+}
12406+
12407+int au_hnotify_init_br(struct au_branch *br, int perm)
12408+{
12409+ int err;
12410+
12411+ err = 0;
12412+ if (au_hnotify_op.init_br)
12413+ err = au_hnotify_op.init_br(br, perm);
12414+
12415+ return err;
12416+}
12417+
12418+void au_hnotify_fin_br(struct au_branch *br)
12419+{
12420+ if (au_hnotify_op.fin_br)
12421+ au_hnotify_op.fin_br(br);
12422+}
12423+
4a4d8108
AM
12424+static void au_hn_destroy_cache(void)
12425+{
12426+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
12427+ au_cachep[AuCache_HNOTIFY] = NULL;
12428+}
1308ab2a 12429+
4a4d8108 12430+int __init au_hnotify_init(void)
1facf9fc 12431+{
1308ab2a 12432+ int err;
1308ab2a 12433+
4a4d8108
AM
12434+ err = -ENOMEM;
12435+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
12436+ if (au_cachep[AuCache_HNOTIFY]) {
027c5e7a
AM
12437+ err = 0;
12438+ if (au_hnotify_op.init)
12439+ err = au_hnotify_op.init();
4a4d8108
AM
12440+ if (unlikely(err))
12441+ au_hn_destroy_cache();
1308ab2a 12442+ }
1308ab2a 12443+ AuTraceErr(err);
4a4d8108 12444+ return err;
1308ab2a 12445+}
12446+
4a4d8108 12447+void au_hnotify_fin(void)
1308ab2a 12448+{
027c5e7a
AM
12449+ if (au_hnotify_op.fin)
12450+ au_hnotify_op.fin();
4a4d8108
AM
12451+ /* cf. au_cache_fin() */
12452+ if (au_cachep[AuCache_HNOTIFY])
12453+ au_hn_destroy_cache();
dece6358 12454+}
7f207e10
AM
12455diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
12456--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
12457+++ linux/fs/aufs/iinfo.c 2011-03-21 20:22:06.857268914 +0100
12458@@ -0,0 +1,264 @@
dece6358 12459+/*
027c5e7a 12460+ * Copyright (C) 2005-2011 Junjiro R. Okajima
dece6358
AM
12461+ *
12462+ * This program, aufs is free software; you can redistribute it and/or modify
12463+ * it under the terms of the GNU General Public License as published by
12464+ * the Free Software Foundation; either version 2 of the License, or
12465+ * (at your option) any later version.
12466+ *
12467+ * This program is distributed in the hope that it will be useful,
12468+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12469+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12470+ * GNU General Public License for more details.
12471+ *
12472+ * You should have received a copy of the GNU General Public License
12473+ * along with this program; if not, write to the Free Software
12474+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12475+ */
1facf9fc 12476+
dece6358 12477+/*
4a4d8108 12478+ * inode private data
dece6358 12479+ */
1facf9fc 12480+
1308ab2a 12481+#include "aufs.h"
1facf9fc 12482+
4a4d8108 12483+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12484+{
4a4d8108 12485+ struct inode *h_inode;
1facf9fc 12486+
4a4d8108 12487+ IiMustAnyLock(inode);
1facf9fc 12488+
4a4d8108
AM
12489+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
12490+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
12491+ return h_inode;
12492+}
1facf9fc 12493+
4a4d8108
AM
12494+/* todo: hard/soft set? */
12495+void au_hiput(struct au_hinode *hinode)
12496+{
12497+ au_hn_free(hinode);
12498+ dput(hinode->hi_whdentry);
12499+ iput(hinode->hi_inode);
12500+}
1facf9fc 12501+
4a4d8108
AM
12502+unsigned int au_hi_flags(struct inode *inode, int isdir)
12503+{
12504+ unsigned int flags;
12505+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 12506+
4a4d8108
AM
12507+ flags = 0;
12508+ if (au_opt_test(mnt_flags, XINO))
12509+ au_fset_hi(flags, XINO);
12510+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
12511+ au_fset_hi(flags, HNOTIFY);
12512+ return flags;
1facf9fc 12513+}
12514+
4a4d8108
AM
12515+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12516+ struct inode *h_inode, unsigned int flags)
1308ab2a 12517+{
4a4d8108
AM
12518+ struct au_hinode *hinode;
12519+ struct inode *hi;
12520+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 12521+
4a4d8108 12522+ IiMustWriteLock(inode);
dece6358 12523+
4a4d8108
AM
12524+ hinode = iinfo->ii_hinode + bindex;
12525+ hi = hinode->hi_inode;
12526+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
12527+
12528+ if (hi)
12529+ au_hiput(hinode);
12530+ hinode->hi_inode = h_inode;
12531+ if (h_inode) {
12532+ int err;
12533+ struct super_block *sb = inode->i_sb;
12534+ struct au_branch *br;
12535+
027c5e7a
AM
12536+ AuDebugOn(inode->i_mode
12537+ && (h_inode->i_mode & S_IFMT)
12538+ != (inode->i_mode & S_IFMT));
4a4d8108
AM
12539+ if (bindex == iinfo->ii_bstart)
12540+ au_cpup_igen(inode, h_inode);
12541+ br = au_sbr(sb, bindex);
12542+ hinode->hi_id = br->br_id;
12543+ if (au_ftest_hi(flags, XINO)) {
12544+ err = au_xino_write(sb, bindex, h_inode->i_ino,
12545+ inode->i_ino);
12546+ if (unlikely(err))
12547+ AuIOErr1("failed au_xino_write() %d\n", err);
12548+ }
12549+
12550+ if (au_ftest_hi(flags, HNOTIFY)
12551+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 12552+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
12553+ if (unlikely(err))
12554+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 12555+ }
12556+ }
4a4d8108 12557+}
dece6358 12558+
4a4d8108
AM
12559+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12560+ struct dentry *h_wh)
12561+{
12562+ struct au_hinode *hinode;
dece6358 12563+
4a4d8108
AM
12564+ IiMustWriteLock(inode);
12565+
12566+ hinode = au_ii(inode)->ii_hinode + bindex;
12567+ AuDebugOn(hinode->hi_whdentry);
12568+ hinode->hi_whdentry = h_wh;
1facf9fc 12569+}
12570+
4a4d8108 12571+void au_update_iigen(struct inode *inode)
1308ab2a 12572+{
4a4d8108
AM
12573+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
12574+ /* smp_mb(); */ /* atomic_set */
12575+}
1facf9fc 12576+
4a4d8108
AM
12577+/* it may be called at remount time, too */
12578+void au_update_ibrange(struct inode *inode, int do_put_zero)
12579+{
12580+ struct au_iinfo *iinfo;
027c5e7a 12581+ aufs_bindex_t bindex, bend;
1facf9fc 12582+
4a4d8108 12583+ iinfo = au_ii(inode);
027c5e7a 12584+ if (!iinfo)
4a4d8108 12585+ return;
1facf9fc 12586+
4a4d8108 12587+ IiMustWriteLock(inode);
1facf9fc 12588+
027c5e7a 12589+ if (do_put_zero && iinfo->ii_bstart >= 0) {
4a4d8108
AM
12590+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12591+ bindex++) {
12592+ struct inode *h_i;
1facf9fc 12593+
4a4d8108 12594+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
027c5e7a
AM
12595+ if (h_i && !h_i->i_nlink)
12596+ au_set_h_iptr(inode, bindex, NULL, 0);
12597+ }
4a4d8108
AM
12598+ }
12599+
027c5e7a
AM
12600+ iinfo->ii_bstart = -1;
12601+ iinfo->ii_bend = -1;
12602+ bend = au_sbend(inode->i_sb);
12603+ for (bindex = 0; bindex <= bend; bindex++)
12604+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
12605+ iinfo->ii_bstart = bindex;
4a4d8108 12606+ break;
027c5e7a
AM
12607+ }
12608+ if (iinfo->ii_bstart >= 0)
12609+ for (bindex = bend; bindex >= iinfo->ii_bstart; bindex--)
12610+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
12611+ iinfo->ii_bend = bindex;
12612+ break;
12613+ }
12614+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend);
1308ab2a 12615+}
1facf9fc 12616+
dece6358 12617+/* ---------------------------------------------------------------------- */
1facf9fc 12618+
4a4d8108 12619+void au_icntnr_init_once(void *_c)
dece6358 12620+{
4a4d8108
AM
12621+ struct au_icntnr *c = _c;
12622+ struct au_iinfo *iinfo = &c->iinfo;
e49829fe 12623+ static struct lock_class_key aufs_ii;
1facf9fc 12624+
4a4d8108 12625+ au_rw_init(&iinfo->ii_rwsem);
e49829fe 12626+ au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
4a4d8108
AM
12627+ inode_init_once(&c->vfs_inode);
12628+}
1facf9fc 12629+
4a4d8108
AM
12630+int au_iinfo_init(struct inode *inode)
12631+{
12632+ struct au_iinfo *iinfo;
12633+ struct super_block *sb;
12634+ int nbr, i;
1facf9fc 12635+
4a4d8108
AM
12636+ sb = inode->i_sb;
12637+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12638+ nbr = au_sbend(sb) + 1;
12639+ if (unlikely(nbr <= 0))
12640+ nbr = 1;
12641+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
12642+ if (iinfo->ii_hinode) {
7f207e10 12643+ au_ninodes_inc(sb);
4a4d8108
AM
12644+ for (i = 0; i < nbr; i++)
12645+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 12646+
4a4d8108
AM
12647+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
12648+ /* smp_mb(); */ /* atomic_set */
12649+ iinfo->ii_bstart = -1;
12650+ iinfo->ii_bend = -1;
12651+ iinfo->ii_vdir = NULL;
12652+ return 0;
1308ab2a 12653+ }
4a4d8108
AM
12654+ return -ENOMEM;
12655+}
1facf9fc 12656+
4a4d8108
AM
12657+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
12658+{
12659+ int err, sz;
12660+ struct au_hinode *hip;
1facf9fc 12661+
4a4d8108
AM
12662+ AuRwMustWriteLock(&iinfo->ii_rwsem);
12663+
12664+ err = -ENOMEM;
12665+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
12666+ if (!sz)
12667+ sz = sizeof(*hip);
12668+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
12669+ if (hip) {
12670+ iinfo->ii_hinode = hip;
12671+ err = 0;
1308ab2a 12672+ }
4a4d8108 12673+
1308ab2a 12674+ return err;
1facf9fc 12675+}
12676+
4a4d8108 12677+void au_iinfo_fin(struct inode *inode)
1facf9fc 12678+{
4a4d8108
AM
12679+ struct au_iinfo *iinfo;
12680+ struct au_hinode *hi;
12681+ struct super_block *sb;
b752ccd1
AM
12682+ aufs_bindex_t bindex, bend;
12683+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 12684+
4a4d8108
AM
12685+ iinfo = au_ii(inode);
12686+ /* bad_inode case */
12687+ if (!iinfo)
12688+ return;
1308ab2a 12689+
b752ccd1 12690+ sb = inode->i_sb;
7f207e10 12691+ au_ninodes_dec(sb);
b752ccd1
AM
12692+ if (si_pid_test(sb))
12693+ au_xino_delete_inode(inode, unlinked);
12694+ else {
12695+ /*
12696+ * it is safe to hide the dependency between sbinfo and
12697+ * sb->s_umount.
12698+ */
12699+ lockdep_off();
12700+ si_noflush_read_lock(sb);
12701+ au_xino_delete_inode(inode, unlinked);
12702+ si_read_unlock(sb);
12703+ lockdep_on();
12704+ }
12705+
4a4d8108
AM
12706+ if (iinfo->ii_vdir)
12707+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 12708+
b752ccd1
AM
12709+ bindex = iinfo->ii_bstart;
12710+ if (bindex >= 0) {
12711+ hi = iinfo->ii_hinode + bindex;
4a4d8108 12712+ bend = iinfo->ii_bend;
b752ccd1
AM
12713+ while (bindex++ <= bend) {
12714+ if (hi->hi_inode)
4a4d8108 12715+ au_hiput(hi);
4a4d8108
AM
12716+ hi++;
12717+ }
12718+ }
4a4d8108 12719+ kfree(iinfo->ii_hinode);
027c5e7a 12720+ iinfo->ii_hinode = NULL;
4a4d8108 12721+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 12722+}
7f207e10
AM
12723diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
12724--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
12725+++ linux/fs/aufs/inode.c 2011-03-21 20:22:06.857268914 +0100
12726@@ -0,0 +1,471 @@
4a4d8108 12727+/*
027c5e7a 12728+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
12729+ *
12730+ * This program, aufs is free software; you can redistribute it and/or modify
12731+ * it under the terms of the GNU General Public License as published by
12732+ * the Free Software Foundation; either version 2 of the License, or
12733+ * (at your option) any later version.
12734+ *
12735+ * This program is distributed in the hope that it will be useful,
12736+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12737+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12738+ * GNU General Public License for more details.
12739+ *
12740+ * You should have received a copy of the GNU General Public License
12741+ * along with this program; if not, write to the Free Software
12742+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12743+ */
1facf9fc 12744+
4a4d8108
AM
12745+/*
12746+ * inode functions
12747+ */
1facf9fc 12748+
4a4d8108 12749+#include "aufs.h"
1308ab2a 12750+
4a4d8108
AM
12751+struct inode *au_igrab(struct inode *inode)
12752+{
12753+ if (inode) {
12754+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 12755+ ihold(inode);
1facf9fc 12756+ }
4a4d8108
AM
12757+ return inode;
12758+}
1facf9fc 12759+
4a4d8108
AM
12760+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
12761+{
12762+ au_cpup_attr_all(inode, /*force*/0);
12763+ au_update_iigen(inode);
12764+ if (do_version)
12765+ inode->i_version++;
dece6358 12766+}
1facf9fc 12767+
027c5e7a 12768+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 12769+{
4a4d8108 12770+ int err, e;
027c5e7a 12771+ umode_t type;
4a4d8108 12772+ aufs_bindex_t bindex, new_bindex;
1308ab2a 12773+ struct super_block *sb;
4a4d8108 12774+ struct au_iinfo *iinfo;
027c5e7a 12775+ struct au_hinode *p, *q, tmp;
1facf9fc 12776+
4a4d8108 12777+ IiMustWriteLock(inode);
1facf9fc 12778+
027c5e7a 12779+ *update = 0;
4a4d8108 12780+ sb = inode->i_sb;
027c5e7a 12781+ type = inode->i_mode & S_IFMT;
4a4d8108
AM
12782+ iinfo = au_ii(inode);
12783+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
12784+ if (unlikely(err))
1308ab2a 12785+ goto out;
1facf9fc 12786+
027c5e7a 12787+ AuDebugOn(iinfo->ii_bstart < 0);
4a4d8108 12788+ p = iinfo->ii_hinode + iinfo->ii_bstart;
4a4d8108
AM
12789+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12790+ bindex++, p++) {
12791+ if (!p->hi_inode)
12792+ continue;
1facf9fc 12793+
027c5e7a 12794+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
12795+ new_bindex = au_br_index(sb, p->hi_id);
12796+ if (new_bindex == bindex)
12797+ continue;
1facf9fc 12798+
4a4d8108 12799+ if (new_bindex < 0) {
027c5e7a 12800+ *update = 1;
4a4d8108
AM
12801+ au_hiput(p);
12802+ p->hi_inode = NULL;
12803+ continue;
1308ab2a 12804+ }
4a4d8108
AM
12805+
12806+ if (new_bindex < iinfo->ii_bstart)
12807+ iinfo->ii_bstart = new_bindex;
12808+ if (iinfo->ii_bend < new_bindex)
12809+ iinfo->ii_bend = new_bindex;
12810+ /* swap two lower inode, and loop again */
12811+ q = iinfo->ii_hinode + new_bindex;
12812+ tmp = *q;
12813+ *q = *p;
12814+ *p = tmp;
12815+ if (tmp.hi_inode) {
12816+ bindex--;
12817+ p--;
1308ab2a 12818+ }
12819+ }
4a4d8108
AM
12820+ au_update_ibrange(inode, /*do_put_zero*/0);
12821+ e = au_dy_irefresh(inode);
12822+ if (unlikely(e && !err))
12823+ err = e;
1facf9fc 12824+
4f0767ce 12825+out:
027c5e7a
AM
12826+ AuTraceErr(err);
12827+ return err;
12828+}
12829+
12830+int au_refresh_hinode_self(struct inode *inode)
12831+{
12832+ int err, update;
12833+
12834+ err = au_ii_refresh(inode, &update);
12835+ if (!err)
12836+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
12837+
12838+ AuTraceErr(err);
4a4d8108
AM
12839+ return err;
12840+}
1facf9fc 12841+
4a4d8108
AM
12842+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
12843+{
027c5e7a 12844+ int err, e, update;
4a4d8108 12845+ unsigned int flags;
027c5e7a 12846+ umode_t mode;
4a4d8108 12847+ aufs_bindex_t bindex, bend;
027c5e7a 12848+ unsigned char isdir;
4a4d8108
AM
12849+ struct au_hinode *p;
12850+ struct au_iinfo *iinfo;
1facf9fc 12851+
027c5e7a 12852+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
12853+ if (unlikely(err))
12854+ goto out;
12855+
12856+ update = 0;
12857+ iinfo = au_ii(inode);
12858+ p = iinfo->ii_hinode + iinfo->ii_bstart;
027c5e7a
AM
12859+ mode = (inode->i_mode & S_IFMT);
12860+ isdir = S_ISDIR(mode);
4a4d8108
AM
12861+ flags = au_hi_flags(inode, isdir);
12862+ bend = au_dbend(dentry);
12863+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
12864+ struct inode *h_i;
12865+ struct dentry *h_d;
12866+
12867+ h_d = au_h_dptr(dentry, bindex);
12868+ if (!h_d || !h_d->d_inode)
12869+ continue;
12870+
027c5e7a 12871+ AuDebugOn(mode != (h_d->d_inode->i_mode & S_IFMT));
4a4d8108
AM
12872+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
12873+ h_i = au_h_iptr(inode, bindex);
12874+ if (h_i) {
12875+ if (h_i == h_d->d_inode)
12876+ continue;
12877+ err = -EIO;
12878+ break;
12879+ }
12880+ }
12881+ if (bindex < iinfo->ii_bstart)
12882+ iinfo->ii_bstart = bindex;
12883+ if (iinfo->ii_bend < bindex)
12884+ iinfo->ii_bend = bindex;
12885+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
12886+ update = 1;
1308ab2a 12887+ }
4a4d8108
AM
12888+ au_update_ibrange(inode, /*do_put_zero*/0);
12889+ e = au_dy_irefresh(inode);
12890+ if (unlikely(e && !err))
12891+ err = e;
027c5e7a
AM
12892+ if (!err)
12893+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 12894+
4f0767ce 12895+out:
4a4d8108 12896+ AuTraceErr(err);
1308ab2a 12897+ return err;
dece6358
AM
12898+}
12899+
4a4d8108 12900+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 12901+{
4a4d8108
AM
12902+ int err;
12903+ unsigned int flags;
12904+ umode_t mode;
12905+ aufs_bindex_t bindex, bstart, btail;
12906+ unsigned char isdir;
12907+ struct dentry *h_dentry;
12908+ struct inode *h_inode;
12909+ struct au_iinfo *iinfo;
dece6358 12910+
4a4d8108 12911+ IiMustWriteLock(inode);
dece6358 12912+
4a4d8108
AM
12913+ err = 0;
12914+ isdir = 0;
12915+ bstart = au_dbstart(dentry);
12916+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
12917+ mode = h_inode->i_mode;
12918+ switch (mode & S_IFMT) {
12919+ case S_IFREG:
12920+ btail = au_dbtail(dentry);
12921+ inode->i_op = &aufs_iop;
12922+ inode->i_fop = &aufs_file_fop;
12923+ err = au_dy_iaop(inode, bstart, h_inode);
12924+ if (unlikely(err))
12925+ goto out;
12926+ break;
12927+ case S_IFDIR:
12928+ isdir = 1;
12929+ btail = au_dbtaildir(dentry);
12930+ inode->i_op = &aufs_dir_iop;
12931+ inode->i_fop = &aufs_dir_fop;
12932+ break;
12933+ case S_IFLNK:
12934+ btail = au_dbtail(dentry);
12935+ inode->i_op = &aufs_symlink_iop;
12936+ break;
12937+ case S_IFBLK:
12938+ case S_IFCHR:
12939+ case S_IFIFO:
12940+ case S_IFSOCK:
12941+ btail = au_dbtail(dentry);
12942+ inode->i_op = &aufs_iop;
12943+ au_init_special_fop(inode, mode, h_inode->i_rdev);
12944+ break;
12945+ default:
12946+ AuIOErr("Unknown file type 0%o\n", mode);
12947+ err = -EIO;
1308ab2a 12948+ goto out;
4a4d8108 12949+ }
dece6358 12950+
4a4d8108
AM
12951+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
12952+ flags = au_hi_flags(inode, isdir);
12953+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
12954+ && au_ftest_hi(flags, HNOTIFY)
12955+ && dentry->d_name.len > AUFS_WH_PFX_LEN
12956+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
12957+ au_fclr_hi(flags, HNOTIFY);
12958+ iinfo = au_ii(inode);
12959+ iinfo->ii_bstart = bstart;
12960+ iinfo->ii_bend = btail;
12961+ for (bindex = bstart; bindex <= btail; bindex++) {
12962+ h_dentry = au_h_dptr(dentry, bindex);
12963+ if (h_dentry)
12964+ au_set_h_iptr(inode, bindex,
12965+ au_igrab(h_dentry->d_inode), flags);
12966+ }
12967+ au_cpup_attr_all(inode, /*force*/1);
dece6358 12968+
4f0767ce 12969+out:
4a4d8108
AM
12970+ return err;
12971+}
dece6358 12972+
027c5e7a
AM
12973+/*
12974+ * successful returns with iinfo write_locked
12975+ * minus: errno
12976+ * zero: success, matched
12977+ * plus: no error, but unmatched
12978+ */
12979+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
12980+{
12981+ int err;
12982+ aufs_bindex_t bindex, bend;
12983+ struct inode *h_inode, *h_dinode;
dece6358 12984+
4a4d8108
AM
12985+ /*
12986+ * before this function, if aufs got any iinfo lock, it must be only
12987+ * one, the parent dir.
12988+ * it can happen by UDBA and the obsoleted inode number.
12989+ */
12990+ err = -EIO;
12991+ if (unlikely(inode->i_ino == parent_ino(dentry)))
12992+ goto out;
12993+
027c5e7a 12994+ err = 1;
4a4d8108
AM
12995+ ii_write_lock_new_child(inode);
12996+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
12997+ bend = au_ibend(inode);
12998+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12999+ h_inode = au_h_iptr(inode, bindex);
13000+ if (h_inode && h_inode == h_dinode) {
4a4d8108 13001+ err = 0;
027c5e7a 13002+ if (au_iigen_test(inode, au_digen(dentry)))
4a4d8108
AM
13003+ err = au_refresh_hinode(inode, dentry);
13004+ break;
1308ab2a 13005+ }
1facf9fc 13006+ }
dece6358 13007+
4a4d8108
AM
13008+ if (unlikely(err))
13009+ ii_write_unlock(inode);
4f0767ce 13010+out:
1facf9fc 13011+ return err;
13012+}
1facf9fc 13013+
4a4d8108
AM
13014+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
13015+ unsigned int d_type, ino_t *ino)
1facf9fc 13016+{
4a4d8108
AM
13017+ int err;
13018+ struct mutex *mtx;
1facf9fc 13019+
b752ccd1 13020+ /* prevent hardlinked inode number from race condition */
4a4d8108 13021+ mtx = NULL;
b752ccd1 13022+ if (d_type != DT_DIR) {
4a4d8108
AM
13023+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
13024+ mutex_lock(mtx);
13025+ }
13026+ err = au_xino_read(sb, bindex, h_ino, ino);
13027+ if (unlikely(err))
13028+ goto out;
1308ab2a 13029+
4a4d8108
AM
13030+ if (!*ino) {
13031+ err = -EIO;
13032+ *ino = au_xino_new_ino(sb);
13033+ if (unlikely(!*ino))
1facf9fc 13034+ goto out;
4a4d8108
AM
13035+ err = au_xino_write(sb, bindex, h_ino, *ino);
13036+ if (unlikely(err))
1308ab2a 13037+ goto out;
1308ab2a 13038+ }
1facf9fc 13039+
4f0767ce 13040+out:
b752ccd1 13041+ if (mtx)
4a4d8108 13042+ mutex_unlock(mtx);
1facf9fc 13043+ return err;
13044+}
13045+
4a4d8108
AM
13046+/* successful returns with iinfo write_locked */
13047+/* todo: return with unlocked? */
13048+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 13049+{
b752ccd1 13050+ struct inode *inode, *h_inode;
4a4d8108
AM
13051+ struct dentry *h_dentry;
13052+ struct super_block *sb;
b752ccd1 13053+ struct mutex *mtx;
4a4d8108 13054+ ino_t h_ino, ino;
027c5e7a 13055+ int err;
4a4d8108 13056+ aufs_bindex_t bstart;
1facf9fc 13057+
4a4d8108
AM
13058+ sb = dentry->d_sb;
13059+ bstart = au_dbstart(dentry);
13060+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
13061+ h_inode = h_dentry->d_inode;
13062+ h_ino = h_inode->i_ino;
13063+
13064+ /*
13065+ * stop 'race'-ing between hardlinks under different
13066+ * parents.
13067+ */
13068+ mtx = NULL;
13069+ if (!S_ISDIR(h_inode->i_mode))
13070+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
13071+
4f0767ce 13072+new_ino:
b752ccd1
AM
13073+ if (mtx)
13074+ mutex_lock(mtx);
4a4d8108
AM
13075+ err = au_xino_read(sb, bstart, h_ino, &ino);
13076+ inode = ERR_PTR(err);
13077+ if (unlikely(err))
13078+ goto out;
b752ccd1 13079+
4a4d8108
AM
13080+ if (!ino) {
13081+ ino = au_xino_new_ino(sb);
13082+ if (unlikely(!ino)) {
13083+ inode = ERR_PTR(-EIO);
dece6358
AM
13084+ goto out;
13085+ }
13086+ }
1facf9fc 13087+
4a4d8108
AM
13088+ AuDbg("i%lu\n", (unsigned long)ino);
13089+ inode = au_iget_locked(sb, ino);
13090+ err = PTR_ERR(inode);
13091+ if (IS_ERR(inode))
1facf9fc 13092+ goto out;
1facf9fc 13093+
4a4d8108
AM
13094+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
13095+ if (inode->i_state & I_NEW) {
13096+ ii_write_lock_new_child(inode);
13097+ err = set_inode(inode, dentry);
13098+ if (!err) {
13099+ unlock_new_inode(inode);
13100+ goto out; /* success */
13101+ }
1308ab2a 13102+
027c5e7a
AM
13103+ /*
13104+ * iget_failed() calls iput(), but we need to call
13105+ * ii_write_unlock() after iget_failed(). so dirty hack for
13106+ * i_count.
13107+ */
13108+ atomic_inc(&inode->i_count);
4a4d8108 13109+ iget_failed(inode);
027c5e7a
AM
13110+ ii_write_unlock(inode);
13111+ au_xino_write(sb, bstart, h_ino, /*ino*/0);
13112+ /* ignore this error */
13113+ goto out_iput;
13114+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
13115+ /*
13116+ * horrible race condition between lookup, readdir and copyup
13117+ * (or something).
13118+ */
13119+ if (mtx)
13120+ mutex_unlock(mtx);
027c5e7a
AM
13121+ err = reval_inode(inode, dentry);
13122+ if (unlikely(err < 0)) {
13123+ mtx = NULL;
13124+ goto out_iput;
13125+ }
13126+
b752ccd1
AM
13127+ if (!err) {
13128+ mtx = NULL;
4a4d8108 13129+ goto out; /* success */
b752ccd1
AM
13130+ } else if (mtx)
13131+ mutex_lock(mtx);
4a4d8108
AM
13132+ }
13133+
13134+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
13135+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
13136+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
13137+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
13138+ (unsigned long)h_ino, (unsigned long)ino);
13139+ ino = 0;
13140+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
13141+ if (!err) {
13142+ iput(inode);
b752ccd1
AM
13143+ if (mtx)
13144+ mutex_unlock(mtx);
4a4d8108
AM
13145+ goto new_ino;
13146+ }
1308ab2a 13147+
4f0767ce 13148+out_iput:
4a4d8108 13149+ iput(inode);
4a4d8108 13150+ inode = ERR_PTR(err);
4f0767ce 13151+out:
b752ccd1
AM
13152+ if (mtx)
13153+ mutex_unlock(mtx);
4a4d8108 13154+ return inode;
1facf9fc 13155+}
13156+
4a4d8108 13157+/* ---------------------------------------------------------------------- */
1facf9fc 13158+
4a4d8108
AM
13159+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
13160+ struct inode *inode)
13161+{
13162+ int err;
1facf9fc 13163+
4a4d8108 13164+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 13165+
4a4d8108
AM
13166+ /* pseudo-link after flushed may happen out of bounds */
13167+ if (!err
13168+ && inode
13169+ && au_ibstart(inode) <= bindex
13170+ && bindex <= au_ibend(inode)) {
13171+ /*
13172+ * permission check is unnecessary since vfsub routine
13173+ * will be called later
13174+ */
13175+ struct inode *hi = au_h_iptr(inode, bindex);
13176+ if (hi)
13177+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 13178+ }
13179+
4a4d8108
AM
13180+ return err;
13181+}
dece6358 13182+
4a4d8108
AM
13183+int au_test_h_perm(struct inode *h_inode, int mask)
13184+{
13185+ if (!current_fsuid())
13186+ return 0;
13187+ return inode_permission(h_inode, mask);
13188+}
1facf9fc 13189+
4a4d8108
AM
13190+int au_test_h_perm_sio(struct inode *h_inode, int mask)
13191+{
13192+ if (au_test_nfs(h_inode->i_sb)
13193+ && (mask & MAY_WRITE)
13194+ && S_ISDIR(h_inode->i_mode))
13195+ mask |= MAY_READ; /* force permission check */
13196+ return au_test_h_perm(h_inode, mask);
1facf9fc 13197+}
7f207e10
AM
13198diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
13199--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
13200+++ linux/fs/aufs/inode.h 2011-03-21 20:22:06.857268914 +0100
13201@@ -0,0 +1,546 @@
4a4d8108 13202+/*
027c5e7a 13203+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
13204+ *
13205+ * This program, aufs is free software; you can redistribute it and/or modify
13206+ * it under the terms of the GNU General Public License as published by
13207+ * the Free Software Foundation; either version 2 of the License, or
13208+ * (at your option) any later version.
13209+ *
13210+ * This program is distributed in the hope that it will be useful,
13211+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13213+ * GNU General Public License for more details.
13214+ *
13215+ * You should have received a copy of the GNU General Public License
13216+ * along with this program; if not, write to the Free Software
13217+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13218+ */
1facf9fc 13219+
1308ab2a 13220+/*
4a4d8108 13221+ * inode operations
1308ab2a 13222+ */
dece6358 13223+
4a4d8108
AM
13224+#ifndef __AUFS_INODE_H__
13225+#define __AUFS_INODE_H__
dece6358 13226+
4a4d8108 13227+#ifdef __KERNEL__
1308ab2a 13228+
4a4d8108
AM
13229+#include <linux/fs.h>
13230+#include <linux/fsnotify.h>
13231+#include <linux/aufs_type.h>
13232+#include "rwsem.h"
1308ab2a 13233+
4a4d8108 13234+struct vfsmount;
1facf9fc 13235+
4a4d8108
AM
13236+struct au_hnotify {
13237+#ifdef CONFIG_AUFS_HNOTIFY
13238+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 13239+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 13240+ struct fsnotify_mark hn_mark;
7f207e10 13241+ int hn_mark_dead;
4a4d8108 13242+#endif
7f207e10 13243+ struct inode *hn_aufs_inode; /* no get/put */
4a4d8108
AM
13244+#endif
13245+} ____cacheline_aligned_in_smp;
1facf9fc 13246+
4a4d8108
AM
13247+struct au_hinode {
13248+ struct inode *hi_inode;
13249+ aufs_bindex_t hi_id;
13250+#ifdef CONFIG_AUFS_HNOTIFY
13251+ struct au_hnotify *hi_notify;
13252+#endif
dece6358 13253+
4a4d8108
AM
13254+ /* reference to the copied-up whiteout with get/put */
13255+ struct dentry *hi_whdentry;
13256+};
dece6358 13257+
4a4d8108
AM
13258+struct au_vdir;
13259+struct au_iinfo {
13260+ atomic_t ii_generation;
13261+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 13262+
4a4d8108
AM
13263+ struct au_rwsem ii_rwsem;
13264+ aufs_bindex_t ii_bstart, ii_bend;
13265+ __u32 ii_higen;
13266+ struct au_hinode *ii_hinode;
13267+ struct au_vdir *ii_vdir;
13268+};
1facf9fc 13269+
4a4d8108
AM
13270+struct au_icntnr {
13271+ struct au_iinfo iinfo;
13272+ struct inode vfs_inode;
13273+} ____cacheline_aligned_in_smp;
1308ab2a 13274+
4a4d8108
AM
13275+/* au_pin flags */
13276+#define AuPin_DI_LOCKED 1
13277+#define AuPin_MNT_WRITE (1 << 1)
13278+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
13279+#define au_fset_pin(flags, name) \
13280+ do { (flags) |= AuPin_##name; } while (0)
13281+#define au_fclr_pin(flags, name) \
13282+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
13283+
13284+struct au_pin {
13285+ /* input */
13286+ struct dentry *dentry;
13287+ unsigned int udba;
13288+ unsigned char lsc_di, lsc_hi, flags;
13289+ aufs_bindex_t bindex;
13290+
13291+ /* output */
13292+ struct dentry *parent;
13293+ struct au_hinode *hdir;
13294+ struct vfsmount *h_mnt;
13295+};
1facf9fc 13296+
1308ab2a 13297+/* ---------------------------------------------------------------------- */
13298+
4a4d8108 13299+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 13300+{
4a4d8108 13301+ struct au_iinfo *iinfo;
1facf9fc 13302+
4a4d8108
AM
13303+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
13304+ if (iinfo->ii_hinode)
13305+ return iinfo;
13306+ return NULL; /* debugging bad_inode case */
13307+}
1facf9fc 13308+
4a4d8108 13309+/* ---------------------------------------------------------------------- */
1facf9fc 13310+
4a4d8108
AM
13311+/* inode.c */
13312+struct inode *au_igrab(struct inode *inode);
027c5e7a 13313+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
13314+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
13315+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
13316+ unsigned int d_type, ino_t *ino);
13317+struct inode *au_new_inode(struct dentry *dentry, int must_new);
13318+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
13319+ struct inode *inode);
13320+int au_test_h_perm(struct inode *h_inode, int mask);
13321+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 13322+
4a4d8108
AM
13323+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
13324+ ino_t h_ino, unsigned int d_type, ino_t *ino)
13325+{
13326+#ifdef CONFIG_AUFS_SHWH
13327+ return au_ino(sb, bindex, h_ino, d_type, ino);
13328+#else
13329+ return 0;
13330+#endif
13331+}
1facf9fc 13332+
4a4d8108
AM
13333+/* i_op.c */
13334+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 13335+
4a4d8108
AM
13336+/* au_wr_dir flags */
13337+#define AuWrDir_ADD_ENTRY 1
13338+#define AuWrDir_ISDIR (1 << 1)
13339+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
13340+#define au_fset_wrdir(flags, name) \
13341+ do { (flags) |= AuWrDir_##name; } while (0)
13342+#define au_fclr_wrdir(flags, name) \
13343+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 13344+
4a4d8108
AM
13345+struct au_wr_dir_args {
13346+ aufs_bindex_t force_btgt;
13347+ unsigned char flags;
13348+};
13349+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
13350+ struct au_wr_dir_args *args);
dece6358 13351+
4a4d8108
AM
13352+struct dentry *au_pinned_h_parent(struct au_pin *pin);
13353+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
13354+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
13355+ unsigned int udba, unsigned char flags);
13356+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
13357+ unsigned int udba, unsigned char flags) __must_check;
13358+int au_do_pin(struct au_pin *pin) __must_check;
13359+void au_unpin(struct au_pin *pin);
1facf9fc 13360+
4a4d8108
AM
13361+/* i_op_add.c */
13362+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13363+ struct dentry *h_parent, int isdir);
13364+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
13365+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
13366+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13367+ struct nameidata *nd);
13368+int aufs_link(struct dentry *src_dentry, struct inode *dir,
13369+ struct dentry *dentry);
13370+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
1facf9fc 13371+
4a4d8108
AM
13372+/* i_op_del.c */
13373+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
13374+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
13375+ struct dentry *h_parent, int isdir);
13376+int aufs_unlink(struct inode *dir, struct dentry *dentry);
13377+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 13378+
4a4d8108
AM
13379+/* i_op_ren.c */
13380+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
13381+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
13382+ struct inode *dir, struct dentry *dentry);
1facf9fc 13383+
4a4d8108
AM
13384+/* iinfo.c */
13385+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
13386+void au_hiput(struct au_hinode *hinode);
13387+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
13388+ struct dentry *h_wh);
13389+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 13390+
4a4d8108
AM
13391+/* hinode flags */
13392+#define AuHi_XINO 1
13393+#define AuHi_HNOTIFY (1 << 1)
13394+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
13395+#define au_fset_hi(flags, name) \
13396+ do { (flags) |= AuHi_##name; } while (0)
13397+#define au_fclr_hi(flags, name) \
13398+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 13399+
4a4d8108
AM
13400+#ifndef CONFIG_AUFS_HNOTIFY
13401+#undef AuHi_HNOTIFY
13402+#define AuHi_HNOTIFY 0
13403+#endif
1facf9fc 13404+
4a4d8108
AM
13405+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
13406+ struct inode *h_inode, unsigned int flags);
1facf9fc 13407+
4a4d8108
AM
13408+void au_update_iigen(struct inode *inode);
13409+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 13410+
4a4d8108
AM
13411+void au_icntnr_init_once(void *_c);
13412+int au_iinfo_init(struct inode *inode);
13413+void au_iinfo_fin(struct inode *inode);
13414+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 13415+
e49829fe 13416+#ifdef CONFIG_PROC_FS
4a4d8108 13417+/* plink.c */
e49829fe
JR
13418+int au_plink_maint(struct super_block *sb, int flags);
13419+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
13420+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
13421+#ifdef CONFIG_AUFS_DEBUG
13422+void au_plink_list(struct super_block *sb);
13423+#else
13424+AuStubVoid(au_plink_list, struct super_block *sb)
13425+#endif
13426+int au_plink_test(struct inode *inode);
13427+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
13428+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
13429+ struct dentry *h_dentry);
e49829fe
JR
13430+void au_plink_put(struct super_block *sb, int verbose);
13431+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 13432+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
13433+#else
13434+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
13435+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
13436+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
13437+AuStubVoid(au_plink_list, struct super_block *sb);
13438+AuStubInt0(au_plink_test, struct inode *inode);
13439+AuStub(struct dentry *, au_plink_lkup, return NULL,
13440+ struct inode *inode, aufs_bindex_t bindex);
13441+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
13442+ struct dentry *h_dentry);
13443+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
13444+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
13445+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
13446+#endif /* CONFIG_PROC_FS */
1facf9fc 13447+
4a4d8108 13448+/* ---------------------------------------------------------------------- */
1308ab2a 13449+
4a4d8108
AM
13450+/* lock subclass for iinfo */
13451+enum {
13452+ AuLsc_II_CHILD, /* child first */
13453+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
13454+ AuLsc_II_CHILD3, /* copyup dirs */
13455+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
13456+ AuLsc_II_PARENT2,
13457+ AuLsc_II_PARENT3, /* copyup dirs */
13458+ AuLsc_II_NEW_CHILD
13459+};
1308ab2a 13460+
1facf9fc 13461+/*
4a4d8108
AM
13462+ * ii_read_lock_child, ii_write_lock_child,
13463+ * ii_read_lock_child2, ii_write_lock_child2,
13464+ * ii_read_lock_child3, ii_write_lock_child3,
13465+ * ii_read_lock_parent, ii_write_lock_parent,
13466+ * ii_read_lock_parent2, ii_write_lock_parent2,
13467+ * ii_read_lock_parent3, ii_write_lock_parent3,
13468+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 13469+ */
4a4d8108
AM
13470+#define AuReadLockFunc(name, lsc) \
13471+static inline void ii_read_lock_##name(struct inode *i) \
13472+{ \
13473+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
13474+}
13475+
13476+#define AuWriteLockFunc(name, lsc) \
13477+static inline void ii_write_lock_##name(struct inode *i) \
13478+{ \
13479+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
13480+}
13481+
13482+#define AuRWLockFuncs(name, lsc) \
13483+ AuReadLockFunc(name, lsc) \
13484+ AuWriteLockFunc(name, lsc)
13485+
13486+AuRWLockFuncs(child, CHILD);
13487+AuRWLockFuncs(child2, CHILD2);
13488+AuRWLockFuncs(child3, CHILD3);
13489+AuRWLockFuncs(parent, PARENT);
13490+AuRWLockFuncs(parent2, PARENT2);
13491+AuRWLockFuncs(parent3, PARENT3);
13492+AuRWLockFuncs(new_child, NEW_CHILD);
13493+
13494+#undef AuReadLockFunc
13495+#undef AuWriteLockFunc
13496+#undef AuRWLockFuncs
1facf9fc 13497+
13498+/*
4a4d8108 13499+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 13500+ */
4a4d8108 13501+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 13502+
4a4d8108
AM
13503+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
13504+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
13505+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 13506+
4a4d8108 13507+/* ---------------------------------------------------------------------- */
1308ab2a 13508+
027c5e7a
AM
13509+static inline void au_icntnr_init(struct au_icntnr *c)
13510+{
13511+#ifdef CONFIG_AUFS_DEBUG
13512+ c->vfs_inode.i_mode = 0;
13513+#endif
13514+}
13515+
4a4d8108
AM
13516+static inline unsigned int au_iigen(struct inode *inode)
13517+{
13518+ return atomic_read(&au_ii(inode)->ii_generation);
13519+}
1308ab2a 13520+
4a4d8108
AM
13521+/* tiny test for inode number */
13522+/* tmpfs generation is too rough */
13523+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
13524+{
13525+ struct au_iinfo *iinfo;
1308ab2a 13526+
4a4d8108
AM
13527+ iinfo = au_ii(inode);
13528+ AuRwMustAnyLock(&iinfo->ii_rwsem);
13529+ return !(iinfo->ii_hsb1 == h_inode->i_sb
13530+ && iinfo->ii_higen == h_inode->i_generation);
13531+}
1308ab2a 13532+
4a4d8108
AM
13533+static inline void au_iigen_dec(struct inode *inode)
13534+{
e49829fe 13535+ atomic_dec(&au_ii(inode)->ii_generation);
027c5e7a
AM
13536+}
13537+
13538+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
13539+{
13540+ int err;
13541+
13542+ err = 0;
13543+ if (unlikely(inode && au_iigen(inode) != sigen))
13544+ err = -EIO;
13545+
13546+ return err;
4a4d8108 13547+}
1308ab2a 13548+
4a4d8108 13549+/* ---------------------------------------------------------------------- */
1308ab2a 13550+
4a4d8108
AM
13551+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
13552+ aufs_bindex_t bindex)
13553+{
13554+ IiMustAnyLock(inode);
13555+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
13556+}
1308ab2a 13557+
4a4d8108
AM
13558+static inline aufs_bindex_t au_ibstart(struct inode *inode)
13559+{
13560+ IiMustAnyLock(inode);
13561+ return au_ii(inode)->ii_bstart;
13562+}
1308ab2a 13563+
4a4d8108
AM
13564+static inline aufs_bindex_t au_ibend(struct inode *inode)
13565+{
13566+ IiMustAnyLock(inode);
13567+ return au_ii(inode)->ii_bend;
13568+}
1308ab2a 13569+
4a4d8108
AM
13570+static inline struct au_vdir *au_ivdir(struct inode *inode)
13571+{
13572+ IiMustAnyLock(inode);
13573+ return au_ii(inode)->ii_vdir;
13574+}
1308ab2a 13575+
4a4d8108
AM
13576+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
13577+{
13578+ IiMustAnyLock(inode);
13579+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
13580+}
1308ab2a 13581+
4a4d8108 13582+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 13583+{
4a4d8108
AM
13584+ IiMustWriteLock(inode);
13585+ au_ii(inode)->ii_bstart = bindex;
13586+}
1308ab2a 13587+
4a4d8108
AM
13588+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
13589+{
13590+ IiMustWriteLock(inode);
13591+ au_ii(inode)->ii_bend = bindex;
1308ab2a 13592+}
13593+
4a4d8108
AM
13594+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
13595+{
13596+ IiMustWriteLock(inode);
13597+ au_ii(inode)->ii_vdir = vdir;
13598+}
1facf9fc 13599+
4a4d8108 13600+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 13601+{
4a4d8108
AM
13602+ IiMustAnyLock(inode);
13603+ return au_ii(inode)->ii_hinode + bindex;
13604+}
dece6358 13605+
4a4d8108 13606+/* ---------------------------------------------------------------------- */
1facf9fc 13607+
4a4d8108
AM
13608+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
13609+{
13610+ if (pin)
13611+ return pin->parent;
13612+ return NULL;
1facf9fc 13613+}
13614+
4a4d8108 13615+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 13616+{
4a4d8108
AM
13617+ if (pin && pin->hdir)
13618+ return pin->hdir->hi_inode;
13619+ return NULL;
1308ab2a 13620+}
1facf9fc 13621+
4a4d8108
AM
13622+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
13623+{
13624+ if (pin)
13625+ return pin->hdir;
13626+ return NULL;
13627+}
1facf9fc 13628+
4a4d8108 13629+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 13630+{
4a4d8108
AM
13631+ if (pin)
13632+ pin->dentry = dentry;
13633+}
1308ab2a 13634+
4a4d8108
AM
13635+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
13636+ unsigned char lflag)
13637+{
13638+ if (pin) {
7f207e10 13639+ if (lflag)
4a4d8108 13640+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 13641+ else
4a4d8108 13642+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 13643+ }
4a4d8108
AM
13644+}
13645+
13646+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
13647+{
13648+ if (pin) {
13649+ dput(pin->parent);
13650+ pin->parent = dget(parent);
1facf9fc 13651+ }
4a4d8108 13652+}
1facf9fc 13653+
4a4d8108
AM
13654+/* ---------------------------------------------------------------------- */
13655+
027c5e7a 13656+struct au_branch;
4a4d8108
AM
13657+#ifdef CONFIG_AUFS_HNOTIFY
13658+struct au_hnotify_op {
13659+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a
AM
13660+ int (*alloc)(struct au_hinode *hinode);
13661+ void (*free)(struct au_hinode *hinode);
4a4d8108
AM
13662+
13663+ void (*fin)(void);
13664+ int (*init)(void);
027c5e7a
AM
13665+
13666+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
13667+ void (*fin_br)(struct au_branch *br);
13668+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
13669+};
13670+
13671+/* hnotify.c */
027c5e7a 13672+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
13673+void au_hn_free(struct au_hinode *hinode);
13674+void au_hn_ctl(struct au_hinode *hinode, int do_set);
13675+void au_hn_reset(struct inode *inode, unsigned int flags);
13676+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
13677+ struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
13678+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
13679+int au_hnotify_init_br(struct au_branch *br, int perm);
13680+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
13681+int __init au_hnotify_init(void);
13682+void au_hnotify_fin(void);
13683+
7f207e10 13684+/* hfsnotify.c */
4a4d8108
AM
13685+extern const struct au_hnotify_op au_hnotify_op;
13686+
13687+static inline
13688+void au_hn_init(struct au_hinode *hinode)
13689+{
13690+ hinode->hi_notify = NULL;
1308ab2a 13691+}
13692+
4a4d8108
AM
13693+#else
13694+static inline
13695+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
027c5e7a 13696+ struct inode *inode __maybe_unused)
1308ab2a 13697+{
4a4d8108
AM
13698+ return -EOPNOTSUPP;
13699+}
1308ab2a 13700+
4a4d8108
AM
13701+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
13702+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
13703+ int do_set __maybe_unused)
13704+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
13705+ unsigned int flags __maybe_unused)
027c5e7a
AM
13706+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
13707+ struct au_branch *br __maybe_unused,
13708+ int perm __maybe_unused)
13709+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
13710+ int perm __maybe_unused)
13711+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
13712+AuStubInt0(__init au_hnotify_init, void)
13713+AuStubVoid(au_hnotify_fin, void)
13714+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
13715+#endif /* CONFIG_AUFS_HNOTIFY */
13716+
13717+static inline void au_hn_suspend(struct au_hinode *hdir)
13718+{
13719+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 13720+}
13721+
4a4d8108 13722+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 13723+{
4a4d8108
AM
13724+ au_hn_ctl(hdir, /*do_set*/1);
13725+}
1308ab2a 13726+
4a4d8108
AM
13727+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
13728+{
13729+ mutex_lock(&hdir->hi_inode->i_mutex);
13730+ au_hn_suspend(hdir);
13731+}
dece6358 13732+
4a4d8108
AM
13733+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
13734+ unsigned int sc __maybe_unused)
13735+{
13736+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
13737+ au_hn_suspend(hdir);
1facf9fc 13738+}
1facf9fc 13739+
4a4d8108
AM
13740+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
13741+{
13742+ au_hn_resume(hdir);
13743+ mutex_unlock(&hdir->hi_inode->i_mutex);
13744+}
13745+
13746+#endif /* __KERNEL__ */
13747+#endif /* __AUFS_INODE_H__ */
7f207e10
AM
13748diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
13749--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
13750+++ linux/fs/aufs/ioctl.c 2011-03-21 20:22:06.857268914 +0100
13751@@ -0,0 +1,158 @@
4a4d8108 13752+/*
027c5e7a 13753+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
13754+ *
13755+ * This program, aufs is free software; you can redistribute it and/or modify
13756+ * it under the terms of the GNU General Public License as published by
13757+ * the Free Software Foundation; either version 2 of the License, or
13758+ * (at your option) any later version.
13759+ *
13760+ * This program is distributed in the hope that it will be useful,
13761+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13762+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13763+ * GNU General Public License for more details.
13764+ *
13765+ * You should have received a copy of the GNU General Public License
13766+ * along with this program; if not, write to the Free Software
13767+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13768+ */
13769+
13770+/*
13771+ * ioctl
13772+ * plink-management and readdir in userspace.
13773+ * assist the pathconf(3) wrapper library.
13774+ */
13775+
13776+#include <linux/file.h>
13777+#include "aufs.h"
13778+
13779+static int au_wbr_fd(struct path *path)
13780+{
13781+ int err, fd;
13782+ aufs_bindex_t wbi, bindex, bend;
13783+ struct file *h_file;
13784+ struct super_block *sb;
13785+ struct dentry *root;
13786+ struct au_branch *wbr;
13787+
13788+ err = get_unused_fd();
13789+ if (unlikely(err < 0))
13790+ goto out;
13791+ fd = err;
13792+
13793+ wbi = 0;
13794+ sb = path->dentry->d_sb;
13795+ root = sb->s_root;
13796+ aufs_read_lock(root, AuLock_IR);
13797+ wbr = au_sbr(sb, wbi);
13798+ if (!(path->mnt->mnt_flags & MNT_READONLY)
13799+ && !au_br_writable(wbr->br_perm)) {
13800+ bend = au_sbend(sb);
13801+ for (bindex = 1; bindex <= bend; bindex++) {
13802+ wbr = au_sbr(sb, bindex);
13803+ if (au_br_writable(wbr->br_perm)) {
13804+ wbi = bindex;
13805+ break;
13806+ }
13807+ }
13808+ wbr = au_sbr(sb, wbi);
13809+ }
13810+ AuDbg("wbi %d\n", wbi);
13811+ h_file = au_h_open(root, wbi, O_RDONLY | O_DIRECTORY | O_LARGEFILE,
13812+ NULL);
13813+ aufs_read_unlock(root, AuLock_IR);
13814+ err = PTR_ERR(h_file);
13815+ if (IS_ERR(h_file))
13816+ goto out_fd;
13817+
13818+ atomic_dec(&wbr->br_count); /* cf. au_h_open() */
13819+ fd_install(fd, h_file);
13820+ err = fd;
13821+ goto out; /* success */
13822+
4f0767ce 13823+out_fd:
4a4d8108 13824+ put_unused_fd(fd);
4f0767ce 13825+out:
4a4d8108
AM
13826+ return err;
13827+}
13828+
13829+/* ---------------------------------------------------------------------- */
13830+
13831+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
13832+{
13833+ long err;
13834+
13835+ switch (cmd) {
4a4d8108
AM
13836+ case AUFS_CTL_RDU:
13837+ case AUFS_CTL_RDU_INO:
13838+ err = au_rdu_ioctl(file, cmd, arg);
13839+ break;
13840+
13841+ case AUFS_CTL_WBR_FD:
13842+ err = au_wbr_fd(&file->f_path);
13843+ break;
13844+
027c5e7a
AM
13845+ case AUFS_CTL_IBUSY:
13846+ err = au_ibusy_ioctl(file, arg);
13847+ break;
13848+
4a4d8108
AM
13849+ default:
13850+ /* do not call the lower */
13851+ AuDbg("0x%x\n", cmd);
13852+ err = -ENOTTY;
13853+ }
13854+
13855+ AuTraceErr(err);
13856+ return err;
13857+}
13858+
13859+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
13860+{
13861+ long err;
13862+
13863+ switch (cmd) {
13864+ case AUFS_CTL_WBR_FD:
13865+ err = au_wbr_fd(&file->f_path);
13866+ break;
13867+
13868+ default:
13869+ /* do not call the lower */
13870+ AuDbg("0x%x\n", cmd);
13871+ err = -ENOTTY;
13872+ }
13873+
13874+ AuTraceErr(err);
13875+ return err;
13876+}
b752ccd1
AM
13877+
13878+#ifdef CONFIG_COMPAT
13879+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
13880+ unsigned long arg)
13881+{
13882+ long err;
13883+
13884+ switch (cmd) {
13885+ case AUFS_CTL_RDU:
13886+ case AUFS_CTL_RDU_INO:
13887+ err = au_rdu_compat_ioctl(file, cmd, arg);
13888+ break;
13889+
027c5e7a
AM
13890+ case AUFS_CTL_IBUSY:
13891+ err = au_ibusy_compat_ioctl(file, arg);
13892+ break;
13893+
b752ccd1
AM
13894+ default:
13895+ err = aufs_ioctl_dir(file, cmd, arg);
13896+ }
13897+
13898+ AuTraceErr(err);
13899+ return err;
13900+}
13901+
13902+#if 0 /* unused yet */
13903+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
13904+ unsigned long arg)
13905+{
13906+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
13907+}
13908+#endif
13909+#endif
7f207e10
AM
13910diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
13911--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
13912+++ linux/fs/aufs/i_op_add.c 2011-03-21 20:22:06.857268914 +0100
13913@@ -0,0 +1,702 @@
4a4d8108 13914+/*
027c5e7a 13915+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
13916+ *
13917+ * This program, aufs is free software; you can redistribute it and/or modify
13918+ * it under the terms of the GNU General Public License as published by
13919+ * the Free Software Foundation; either version 2 of the License, or
13920+ * (at your option) any later version.
13921+ *
13922+ * This program is distributed in the hope that it will be useful,
13923+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13924+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13925+ * GNU General Public License for more details.
13926+ *
13927+ * You should have received a copy of the GNU General Public License
13928+ * along with this program; if not, write to the Free Software
13929+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13930+ */
13931+
13932+/*
13933+ * inode operations (add entry)
13934+ */
13935+
13936+#include "aufs.h"
13937+
13938+/*
13939+ * final procedure of adding a new entry, except link(2).
13940+ * remove whiteout, instantiate, copyup the parent dir's times and size
13941+ * and update version.
13942+ * if it failed, re-create the removed whiteout.
13943+ */
13944+static int epilog(struct inode *dir, aufs_bindex_t bindex,
13945+ struct dentry *wh_dentry, struct dentry *dentry)
13946+{
13947+ int err, rerr;
13948+ aufs_bindex_t bwh;
13949+ struct path h_path;
13950+ struct inode *inode, *h_dir;
13951+ struct dentry *wh;
13952+
13953+ bwh = -1;
13954+ if (wh_dentry) {
13955+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
13956+ IMustLock(h_dir);
13957+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
13958+ bwh = au_dbwh(dentry);
13959+ h_path.dentry = wh_dentry;
13960+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
13961+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
13962+ dentry);
13963+ if (unlikely(err))
13964+ goto out;
13965+ }
13966+
13967+ inode = au_new_inode(dentry, /*must_new*/1);
13968+ if (!IS_ERR(inode)) {
13969+ d_instantiate(dentry, inode);
13970+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
13971+ IMustLock(dir);
13972+ if (au_ibstart(dir) == au_dbstart(dentry))
13973+ au_cpup_attr_timesizes(dir);
13974+ dir->i_version++;
13975+ return 0; /* success */
13976+ }
13977+
13978+ err = PTR_ERR(inode);
13979+ if (!wh_dentry)
13980+ goto out;
13981+
13982+ /* revert */
13983+ /* dir inode is locked */
13984+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
13985+ rerr = PTR_ERR(wh);
13986+ if (IS_ERR(wh)) {
13987+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
13988+ AuDLNPair(dentry), err, rerr);
13989+ err = -EIO;
13990+ } else
13991+ dput(wh);
13992+
4f0767ce 13993+out:
4a4d8108
AM
13994+ return err;
13995+}
13996+
027c5e7a
AM
13997+static int au_d_may_add(struct dentry *dentry)
13998+{
13999+ int err;
14000+
14001+ err = 0;
14002+ if (unlikely(d_unhashed(dentry)))
14003+ err = -ENOENT;
14004+ if (unlikely(dentry->d_inode))
14005+ err = -EEXIST;
14006+ return err;
14007+}
14008+
4a4d8108
AM
14009+/*
14010+ * simple tests for the adding inode operations.
14011+ * following the checks in vfs, plus the parent-child relationship.
14012+ */
14013+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
14014+ struct dentry *h_parent, int isdir)
14015+{
14016+ int err;
14017+ umode_t h_mode;
14018+ struct dentry *h_dentry;
14019+ struct inode *h_inode;
14020+
14021+ err = -ENAMETOOLONG;
14022+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
14023+ goto out;
14024+
14025+ h_dentry = au_h_dptr(dentry, bindex);
14026+ h_inode = h_dentry->d_inode;
14027+ if (!dentry->d_inode) {
14028+ err = -EEXIST;
14029+ if (unlikely(h_inode))
14030+ goto out;
14031+ } else {
14032+ /* rename(2) case */
14033+ err = -EIO;
14034+ if (unlikely(!h_inode || !h_inode->i_nlink))
14035+ goto out;
14036+
14037+ h_mode = h_inode->i_mode;
14038+ if (!isdir) {
14039+ err = -EISDIR;
14040+ if (unlikely(S_ISDIR(h_mode)))
14041+ goto out;
14042+ } else if (unlikely(!S_ISDIR(h_mode))) {
14043+ err = -ENOTDIR;
14044+ goto out;
14045+ }
14046+ }
14047+
14048+ err = 0;
14049+ /* expected parent dir is locked */
14050+ if (unlikely(h_parent != h_dentry->d_parent))
14051+ err = -EIO;
14052+
4f0767ce 14053+out:
4a4d8108
AM
14054+ AuTraceErr(err);
14055+ return err;
14056+}
14057+
14058+/*
14059+ * initial procedure of adding a new entry.
14060+ * prepare writable branch and the parent dir, lock it,
14061+ * and lookup whiteout for the new entry.
14062+ */
14063+static struct dentry*
14064+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
14065+ struct dentry *src_dentry, struct au_pin *pin,
14066+ struct au_wr_dir_args *wr_dir_args)
14067+{
14068+ struct dentry *wh_dentry, *h_parent;
14069+ struct super_block *sb;
14070+ struct au_branch *br;
14071+ int err;
14072+ unsigned int udba;
14073+ aufs_bindex_t bcpup;
14074+
14075+ AuDbg("%.*s\n", AuDLNPair(dentry));
14076+
14077+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
14078+ bcpup = err;
14079+ wh_dentry = ERR_PTR(err);
14080+ if (unlikely(err < 0))
14081+ goto out;
14082+
14083+ sb = dentry->d_sb;
14084+ udba = au_opt_udba(sb);
14085+ err = au_pin(pin, dentry, bcpup, udba,
14086+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14087+ wh_dentry = ERR_PTR(err);
14088+ if (unlikely(err))
14089+ goto out;
14090+
14091+ h_parent = au_pinned_h_parent(pin);
14092+ if (udba != AuOpt_UDBA_NONE
14093+ && au_dbstart(dentry) == bcpup)
14094+ err = au_may_add(dentry, bcpup, h_parent,
14095+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
14096+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
14097+ err = -ENAMETOOLONG;
14098+ wh_dentry = ERR_PTR(err);
14099+ if (unlikely(err))
14100+ goto out_unpin;
14101+
14102+ br = au_sbr(sb, bcpup);
14103+ if (dt) {
14104+ struct path tmp = {
14105+ .dentry = h_parent,
14106+ .mnt = br->br_mnt
14107+ };
14108+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
14109+ }
14110+
14111+ wh_dentry = NULL;
14112+ if (bcpup != au_dbwh(dentry))
14113+ goto out; /* success */
14114+
14115+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
14116+
4f0767ce 14117+out_unpin:
4a4d8108
AM
14118+ if (IS_ERR(wh_dentry))
14119+ au_unpin(pin);
4f0767ce 14120+out:
4a4d8108
AM
14121+ return wh_dentry;
14122+}
14123+
14124+/* ---------------------------------------------------------------------- */
14125+
14126+enum { Mknod, Symlink, Creat };
14127+struct simple_arg {
14128+ int type;
14129+ union {
14130+ struct {
14131+ int mode;
14132+ struct nameidata *nd;
14133+ } c;
14134+ struct {
14135+ const char *symname;
14136+ } s;
14137+ struct {
14138+ int mode;
14139+ dev_t dev;
14140+ } m;
14141+ } u;
14142+};
14143+
14144+static int add_simple(struct inode *dir, struct dentry *dentry,
14145+ struct simple_arg *arg)
14146+{
14147+ int err;
14148+ aufs_bindex_t bstart;
14149+ unsigned char created;
14150+ struct au_dtime dt;
14151+ struct au_pin pin;
14152+ struct path h_path;
14153+ struct dentry *wh_dentry, *parent;
14154+ struct inode *h_dir;
14155+ struct au_wr_dir_args wr_dir_args = {
14156+ .force_btgt = -1,
14157+ .flags = AuWrDir_ADD_ENTRY
14158+ };
14159+
14160+ AuDbg("%.*s\n", AuDLNPair(dentry));
14161+ IMustLock(dir);
14162+
14163+ parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
14164+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
14165+ if (unlikely(err))
14166+ goto out;
14167+ err = au_d_may_add(dentry);
14168+ if (unlikely(err))
14169+ goto out_unlock;
4a4d8108
AM
14170+ di_write_lock_parent(parent);
14171+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
14172+ &wr_dir_args);
14173+ err = PTR_ERR(wh_dentry);
14174+ if (IS_ERR(wh_dentry))
027c5e7a 14175+ goto out_parent;
4a4d8108
AM
14176+
14177+ bstart = au_dbstart(dentry);
14178+ h_path.dentry = au_h_dptr(dentry, bstart);
14179+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
14180+ h_dir = au_pinned_h_dir(&pin);
14181+ switch (arg->type) {
14182+ case Creat:
14183+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
14184+ break;
14185+ case Symlink:
14186+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
14187+ break;
14188+ case Mknod:
14189+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
14190+ break;
14191+ default:
14192+ BUG();
14193+ }
14194+ created = !err;
14195+ if (!err)
14196+ err = epilog(dir, bstart, wh_dentry, dentry);
14197+
14198+ /* revert */
14199+ if (unlikely(created && err && h_path.dentry->d_inode)) {
14200+ int rerr;
14201+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
14202+ if (rerr) {
14203+ AuIOErr("%.*s revert failure(%d, %d)\n",
14204+ AuDLNPair(dentry), err, rerr);
14205+ err = -EIO;
14206+ }
14207+ au_dtime_revert(&dt);
4a4d8108
AM
14208+ }
14209+
14210+ au_unpin(&pin);
14211+ dput(wh_dentry);
14212+
027c5e7a
AM
14213+out_parent:
14214+ di_write_unlock(parent);
14215+out_unlock:
4a4d8108
AM
14216+ if (unlikely(err)) {
14217+ au_update_dbstart(dentry);
14218+ d_drop(dentry);
14219+ }
4a4d8108 14220+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 14221+out:
4a4d8108
AM
14222+ return err;
14223+}
14224+
14225+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
14226+{
14227+ struct simple_arg arg = {
14228+ .type = Mknod,
14229+ .u.m = {
14230+ .mode = mode,
14231+ .dev = dev
14232+ }
14233+ };
14234+ return add_simple(dir, dentry, &arg);
14235+}
14236+
14237+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
14238+{
14239+ struct simple_arg arg = {
14240+ .type = Symlink,
14241+ .u.s.symname = symname
14242+ };
14243+ return add_simple(dir, dentry, &arg);
14244+}
14245+
14246+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
14247+ struct nameidata *nd)
14248+{
14249+ struct simple_arg arg = {
14250+ .type = Creat,
14251+ .u.c = {
14252+ .mode = mode,
14253+ .nd = nd
14254+ }
14255+ };
14256+ return add_simple(dir, dentry, &arg);
14257+}
14258+
14259+/* ---------------------------------------------------------------------- */
14260+
14261+struct au_link_args {
14262+ aufs_bindex_t bdst, bsrc;
14263+ struct au_pin pin;
14264+ struct path h_path;
14265+ struct dentry *src_parent, *parent;
14266+};
14267+
14268+static int au_cpup_before_link(struct dentry *src_dentry,
14269+ struct au_link_args *a)
14270+{
14271+ int err;
14272+ struct dentry *h_src_dentry;
14273+ struct mutex *h_mtx;
14274+ struct file *h_file;
14275+
14276+ di_read_lock_parent(a->src_parent, AuLock_IR);
14277+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
14278+ if (unlikely(err))
14279+ goto out;
14280+
14281+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
14282+ h_mtx = &h_src_dentry->d_inode->i_mutex;
14283+ err = au_pin(&a->pin, src_dentry, a->bdst,
14284+ au_opt_udba(src_dentry->d_sb),
14285+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14286+ if (unlikely(err))
14287+ goto out;
14288+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14289+ h_file = au_h_open_pre(src_dentry, a->bsrc);
14290+ if (IS_ERR(h_file)) {
14291+ err = PTR_ERR(h_file);
14292+ h_file = NULL;
14293+ } else
14294+ err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
14295+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
14296+ mutex_unlock(h_mtx);
14297+ au_h_open_post(src_dentry, a->bsrc, h_file);
14298+ au_unpin(&a->pin);
14299+
4f0767ce 14300+out:
4a4d8108
AM
14301+ di_read_unlock(a->src_parent, AuLock_IR);
14302+ return err;
14303+}
14304+
14305+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
14306+{
14307+ int err;
14308+ unsigned char plink;
14309+ struct inode *h_inode, *inode;
14310+ struct dentry *h_src_dentry;
14311+ struct super_block *sb;
14312+ struct file *h_file;
14313+
14314+ plink = 0;
14315+ h_inode = NULL;
14316+ sb = src_dentry->d_sb;
14317+ inode = src_dentry->d_inode;
14318+ if (au_ibstart(inode) <= a->bdst)
14319+ h_inode = au_h_iptr(inode, a->bdst);
14320+ if (!h_inode || !h_inode->i_nlink) {
14321+ /* copyup src_dentry as the name of dentry. */
14322+ au_set_dbstart(src_dentry, a->bdst);
14323+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
14324+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
14325+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
14326+ h_file = au_h_open_pre(src_dentry, a->bsrc);
14327+ if (IS_ERR(h_file)) {
14328+ err = PTR_ERR(h_file);
14329+ h_file = NULL;
14330+ } else
14331+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
14332+ -1, AuCpup_KEEPLINO,
14333+ a->parent);
14334+ mutex_unlock(&h_inode->i_mutex);
14335+ au_h_open_post(src_dentry, a->bsrc, h_file);
14336+ au_set_h_dptr(src_dentry, a->bdst, NULL);
14337+ au_set_dbstart(src_dentry, a->bsrc);
14338+ } else {
14339+ /* the inode of src_dentry already exists on a.bdst branch */
14340+ h_src_dentry = d_find_alias(h_inode);
14341+ if (!h_src_dentry && au_plink_test(inode)) {
14342+ plink = 1;
14343+ h_src_dentry = au_plink_lkup(inode, a->bdst);
14344+ err = PTR_ERR(h_src_dentry);
14345+ if (IS_ERR(h_src_dentry))
14346+ goto out;
14347+
14348+ if (unlikely(!h_src_dentry->d_inode)) {
14349+ dput(h_src_dentry);
14350+ h_src_dentry = NULL;
14351+ }
14352+
14353+ }
14354+ if (h_src_dentry) {
14355+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
14356+ &a->h_path);
14357+ dput(h_src_dentry);
14358+ } else {
14359+ AuIOErr("no dentry found for hi%lu on b%d\n",
14360+ h_inode->i_ino, a->bdst);
14361+ err = -EIO;
14362+ }
14363+ }
14364+
14365+ if (!err && !plink)
14366+ au_plink_append(inode, a->bdst, a->h_path.dentry);
14367+
14368+out:
14369+ return err;
14370+}
14371+
14372+int aufs_link(struct dentry *src_dentry, struct inode *dir,
14373+ struct dentry *dentry)
14374+{
14375+ int err, rerr;
14376+ struct au_dtime dt;
14377+ struct au_link_args *a;
14378+ struct dentry *wh_dentry, *h_src_dentry;
14379+ struct inode *inode;
14380+ struct super_block *sb;
14381+ struct au_wr_dir_args wr_dir_args = {
14382+ /* .force_btgt = -1, */
14383+ .flags = AuWrDir_ADD_ENTRY
14384+ };
14385+
14386+ IMustLock(dir);
14387+ inode = src_dentry->d_inode;
14388+ IMustLock(inode);
14389+
4a4d8108
AM
14390+ err = -ENOMEM;
14391+ a = kzalloc(sizeof(*a), GFP_NOFS);
14392+ if (unlikely(!a))
14393+ goto out;
14394+
14395+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
14396+ err = aufs_read_and_write_lock2(dentry, src_dentry,
14397+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
14398+ if (unlikely(err))
14399+ goto out_kfree;
027c5e7a
AM
14400+ err = au_d_hashed_positive(src_dentry);
14401+ if (unlikely(err))
14402+ goto out_unlock;
14403+ err = au_d_may_add(dentry);
14404+ if (unlikely(err))
14405+ goto out_unlock;
e49829fe 14406+
4a4d8108
AM
14407+ a->src_parent = dget_parent(src_dentry);
14408+ wr_dir_args.force_btgt = au_dbstart(src_dentry);
14409+
14410+ di_write_lock_parent(a->parent);
14411+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
14412+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
14413+ &wr_dir_args);
14414+ err = PTR_ERR(wh_dentry);
14415+ if (IS_ERR(wh_dentry))
027c5e7a 14416+ goto out_parent;
4a4d8108
AM
14417+
14418+ err = 0;
14419+ sb = dentry->d_sb;
14420+ a->bdst = au_dbstart(dentry);
14421+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
14422+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
14423+ a->bsrc = au_dbstart(src_dentry);
14424+ if (au_opt_test(au_mntflags(sb), PLINK)) {
14425+ if (a->bdst < a->bsrc
14426+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
14427+ err = au_cpup_or_link(src_dentry, a);
14428+ else {
14429+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
14430+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
14431+ &a->h_path);
14432+ }
14433+ } else {
14434+ /*
14435+ * copyup src_dentry to the branch we process,
14436+ * and then link(2) to it.
14437+ */
14438+ if (a->bdst < a->bsrc
14439+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
14440+ au_unpin(&a->pin);
14441+ di_write_unlock(a->parent);
14442+ err = au_cpup_before_link(src_dentry, a);
14443+ di_write_lock_parent(a->parent);
14444+ if (!err)
14445+ err = au_pin(&a->pin, dentry, a->bdst,
14446+ au_opt_udba(sb),
14447+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14448+ if (unlikely(err))
14449+ goto out_wh;
14450+ }
14451+ if (!err) {
14452+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
14453+ err = -ENOENT;
14454+ if (h_src_dentry && h_src_dentry->d_inode)
14455+ err = vfsub_link(h_src_dentry,
14456+ au_pinned_h_dir(&a->pin),
14457+ &a->h_path);
14458+ }
14459+ }
14460+ if (unlikely(err))
14461+ goto out_unpin;
14462+
14463+ if (wh_dentry) {
14464+ a->h_path.dentry = wh_dentry;
14465+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
14466+ dentry);
14467+ if (unlikely(err))
14468+ goto out_revert;
14469+ }
14470+
14471+ dir->i_version++;
14472+ if (au_ibstart(dir) == au_dbstart(dentry))
14473+ au_cpup_attr_timesizes(dir);
14474+ inc_nlink(inode);
14475+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
14476+ d_instantiate(dentry, au_igrab(inode));
14477+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
14478+ /* some filesystem calls d_drop() */
14479+ d_drop(dentry);
14480+ goto out_unpin; /* success */
14481+
4f0767ce 14482+out_revert:
4a4d8108 14483+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
027c5e7a
AM
14484+ if (unlikely(rerr)) {
14485+ AuIOErr("%.*s reverting failed(%d, %d)\n",
14486+ AuDLNPair(dentry), err, rerr);
14487+ err = -EIO;
14488+ }
4a4d8108 14489+ au_dtime_revert(&dt);
4f0767ce 14490+out_unpin:
4a4d8108 14491+ au_unpin(&a->pin);
4f0767ce 14492+out_wh:
4a4d8108 14493+ dput(wh_dentry);
027c5e7a
AM
14494+out_parent:
14495+ di_write_unlock(a->parent);
14496+ dput(a->src_parent);
4f0767ce 14497+out_unlock:
4a4d8108
AM
14498+ if (unlikely(err)) {
14499+ au_update_dbstart(dentry);
14500+ d_drop(dentry);
14501+ }
4a4d8108 14502+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 14503+out_kfree:
4a4d8108 14504+ kfree(a);
4f0767ce 14505+out:
4a4d8108
AM
14506+ return err;
14507+}
14508+
14509+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
14510+{
14511+ int err, rerr;
14512+ aufs_bindex_t bindex;
14513+ unsigned char diropq;
14514+ struct path h_path;
14515+ struct dentry *wh_dentry, *parent, *opq_dentry;
14516+ struct mutex *h_mtx;
14517+ struct super_block *sb;
14518+ struct {
14519+ struct au_pin pin;
14520+ struct au_dtime dt;
14521+ } *a; /* reduce the stack usage */
14522+ struct au_wr_dir_args wr_dir_args = {
14523+ .force_btgt = -1,
14524+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
14525+ };
14526+
14527+ IMustLock(dir);
14528+
14529+ err = -ENOMEM;
14530+ a = kmalloc(sizeof(*a), GFP_NOFS);
14531+ if (unlikely(!a))
14532+ goto out;
14533+
027c5e7a
AM
14534+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
14535+ if (unlikely(err))
14536+ goto out_free;
14537+ err = au_d_may_add(dentry);
14538+ if (unlikely(err))
14539+ goto out_unlock;
14540+
4a4d8108
AM
14541+ parent = dentry->d_parent; /* dir inode is locked */
14542+ di_write_lock_parent(parent);
14543+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
14544+ &a->pin, &wr_dir_args);
14545+ err = PTR_ERR(wh_dentry);
14546+ if (IS_ERR(wh_dentry))
027c5e7a 14547+ goto out_parent;
4a4d8108
AM
14548+
14549+ sb = dentry->d_sb;
14550+ bindex = au_dbstart(dentry);
14551+ h_path.dentry = au_h_dptr(dentry, bindex);
14552+ h_path.mnt = au_sbr_mnt(sb, bindex);
14553+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
14554+ if (unlikely(err))
027c5e7a 14555+ goto out_unpin;
4a4d8108
AM
14556+
14557+ /* make the dir opaque */
14558+ diropq = 0;
14559+ h_mtx = &h_path.dentry->d_inode->i_mutex;
14560+ if (wh_dentry
14561+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
14562+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14563+ opq_dentry = au_diropq_create(dentry, bindex);
14564+ mutex_unlock(h_mtx);
14565+ err = PTR_ERR(opq_dentry);
14566+ if (IS_ERR(opq_dentry))
14567+ goto out_dir;
14568+ dput(opq_dentry);
14569+ diropq = 1;
14570+ }
14571+
14572+ err = epilog(dir, bindex, wh_dentry, dentry);
14573+ if (!err) {
14574+ inc_nlink(dir);
027c5e7a 14575+ goto out_unpin; /* success */
4a4d8108
AM
14576+ }
14577+
14578+ /* revert */
14579+ if (diropq) {
14580+ AuLabel(revert opq);
14581+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14582+ rerr = au_diropq_remove(dentry, bindex);
14583+ mutex_unlock(h_mtx);
14584+ if (rerr) {
14585+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
14586+ AuDLNPair(dentry), err, rerr);
14587+ err = -EIO;
14588+ }
14589+ }
14590+
4f0767ce 14591+out_dir:
4a4d8108
AM
14592+ AuLabel(revert dir);
14593+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
14594+ if (rerr) {
14595+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
14596+ AuDLNPair(dentry), err, rerr);
14597+ err = -EIO;
14598+ }
4a4d8108 14599+ au_dtime_revert(&a->dt);
027c5e7a 14600+out_unpin:
4a4d8108
AM
14601+ au_unpin(&a->pin);
14602+ dput(wh_dentry);
027c5e7a
AM
14603+out_parent:
14604+ di_write_unlock(parent);
14605+out_unlock:
4a4d8108
AM
14606+ if (unlikely(err)) {
14607+ au_update_dbstart(dentry);
14608+ d_drop(dentry);
14609+ }
4a4d8108 14610+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 14611+out_free:
4a4d8108 14612+ kfree(a);
4f0767ce 14613+out:
4a4d8108
AM
14614+ return err;
14615+}
7f207e10
AM
14616diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
14617--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
14618+++ linux/fs/aufs/i_op.c 2011-03-21 20:22:06.857268914 +0100
14619@@ -0,0 +1,976 @@
4a4d8108 14620+/*
027c5e7a 14621+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
14622+ *
14623+ * This program, aufs is free software; you can redistribute it and/or modify
14624+ * it under the terms of the GNU General Public License as published by
14625+ * the Free Software Foundation; either version 2 of the License, or
14626+ * (at your option) any later version.
14627+ *
14628+ * This program is distributed in the hope that it will be useful,
14629+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14630+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14631+ * GNU General Public License for more details.
14632+ *
14633+ * You should have received a copy of the GNU General Public License
14634+ * along with this program; if not, write to the Free Software
14635+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14636+ */
1facf9fc 14637+
1308ab2a 14638+/*
4a4d8108 14639+ * inode operations (except add/del/rename)
1308ab2a 14640+ */
4a4d8108
AM
14641+
14642+#include <linux/device_cgroup.h>
14643+#include <linux/fs_stack.h>
14644+#include <linux/mm.h>
14645+#include <linux/namei.h>
14646+#include <linux/security.h>
14647+#include <linux/uaccess.h>
14648+#include "aufs.h"
14649+
027c5e7a 14650+static int h_permission(struct inode *h_inode, int mask, unsigned int flags,
4a4d8108 14651+ struct vfsmount *h_mnt, int brperm)
1facf9fc 14652+{
1308ab2a 14653+ int err;
4a4d8108 14654+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 14655+
4a4d8108
AM
14656+ err = -EACCES;
14657+ if ((write_mask && IS_IMMUTABLE(h_inode))
14658+ || ((mask & MAY_EXEC)
14659+ && S_ISREG(h_inode->i_mode)
14660+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
14661+ || !(h_inode->i_mode & S_IXUGO))))
14662+ goto out;
14663+
14664+ /*
14665+ * - skip the lower fs test in the case of write to ro branch.
14666+ * - nfs dir permission write check is optimized, but a policy for
14667+ * link/rename requires a real check.
14668+ */
14669+ if ((write_mask && !au_br_writable(brperm))
14670+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
14671+ && write_mask && !(mask & MAY_READ))
14672+ || !h_inode->i_op->permission) {
14673+ /* AuLabel(generic_permission); */
027c5e7a 14674+ err = generic_permission(h_inode, mask, flags,
4a4d8108 14675+ h_inode->i_op->check_acl);
1308ab2a 14676+ } else {
4a4d8108 14677+ /* AuLabel(h_inode->permission); */
027c5e7a 14678+ err = h_inode->i_op->permission(h_inode, mask, flags);
4a4d8108
AM
14679+ AuTraceErr(err);
14680+ }
1facf9fc 14681+
4a4d8108
AM
14682+ if (!err)
14683+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 14684+ if (!err)
4a4d8108 14685+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
14686+
14687+#if 0
14688+ if (!err) {
14689+ /* todo: do we need to call ima_path_check()? */
14690+ struct path h_path = {
14691+ .dentry =
14692+ .mnt = h_mnt
14693+ };
14694+ err = ima_path_check(&h_path,
14695+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
14696+ IMA_COUNT_LEAVE);
1308ab2a 14697+ }
4a4d8108 14698+#endif
dece6358 14699+
4f0767ce 14700+out:
1308ab2a 14701+ return err;
14702+}
dece6358 14703+
027c5e7a 14704+static int aufs_permission(struct inode *inode, int mask, unsigned int flags)
1308ab2a 14705+{
14706+ int err;
4a4d8108
AM
14707+ aufs_bindex_t bindex, bend;
14708+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
14709+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
14710+ struct inode *h_inode;
14711+ struct super_block *sb;
14712+ struct au_branch *br;
1facf9fc 14713+
027c5e7a
AM
14714+ /* todo: support rcu-walk? */
14715+ if (flags & IPERM_FLAG_RCU)
14716+ return -ECHILD;
14717+
4a4d8108
AM
14718+ sb = inode->i_sb;
14719+ si_read_lock(sb, AuLock_FLUSH);
14720+ ii_read_lock_child(inode);
027c5e7a
AM
14721+#if 0
14722+ err = au_iigen_test(inode, au_sigen(sb));
14723+ if (unlikely(err))
14724+ goto out;
14725+#endif
dece6358 14726+
4a4d8108
AM
14727+ if (!isdir || write_mask) {
14728+ err = au_busy_or_stale();
14729+ h_inode = au_h_iptr(inode, au_ibstart(inode));
14730+ if (unlikely(!h_inode
14731+ || (h_inode->i_mode & S_IFMT)
14732+ != (inode->i_mode & S_IFMT)))
14733+ goto out;
1facf9fc 14734+
4a4d8108
AM
14735+ err = 0;
14736+ bindex = au_ibstart(inode);
14737+ br = au_sbr(sb, bindex);
027c5e7a
AM
14738+ err = h_permission(h_inode, mask, flags, br->br_mnt,
14739+ br->br_perm);
4a4d8108
AM
14740+ if (write_mask
14741+ && !err
14742+ && !special_file(h_inode->i_mode)) {
14743+ /* test whether the upper writable branch exists */
14744+ err = -EROFS;
14745+ for (; bindex >= 0; bindex--)
14746+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
14747+ err = 0;
14748+ break;
14749+ }
14750+ }
14751+ goto out;
14752+ }
dece6358 14753+
4a4d8108 14754+ /* non-write to dir */
1308ab2a 14755+ err = 0;
4a4d8108
AM
14756+ bend = au_ibend(inode);
14757+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
14758+ h_inode = au_h_iptr(inode, bindex);
14759+ if (h_inode) {
14760+ err = au_busy_or_stale();
14761+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
14762+ break;
14763+
14764+ br = au_sbr(sb, bindex);
027c5e7a 14765+ err = h_permission(h_inode, mask, flags, br->br_mnt,
4a4d8108
AM
14766+ br->br_perm);
14767+ }
14768+ }
1308ab2a 14769+
4f0767ce 14770+out:
4a4d8108
AM
14771+ ii_read_unlock(inode);
14772+ si_read_unlock(sb);
1308ab2a 14773+ return err;
14774+}
14775+
4a4d8108 14776+/* ---------------------------------------------------------------------- */
1facf9fc 14777+
4a4d8108
AM
14778+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
14779+ struct nameidata *nd)
14780+{
14781+ struct dentry *ret, *parent;
b752ccd1 14782+ struct inode *inode;
4a4d8108
AM
14783+ struct super_block *sb;
14784+ int err, npositive;
dece6358 14785+
4a4d8108 14786+ IMustLock(dir);
1308ab2a 14787+
4a4d8108 14788+ sb = dir->i_sb;
7f207e10
AM
14789+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
14790+ ret = ERR_PTR(err);
14791+ if (unlikely(err))
14792+ goto out;
14793+
4a4d8108
AM
14794+ ret = ERR_PTR(-ENAMETOOLONG);
14795+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
7f207e10 14796+ goto out_si;
4a4d8108
AM
14797+ err = au_di_init(dentry);
14798+ ret = ERR_PTR(err);
14799+ if (unlikely(err))
7f207e10 14800+ goto out_si;
1308ab2a 14801+
027c5e7a 14802+ npositive = 0; /* suppress a warning */
4a4d8108
AM
14803+ parent = dentry->d_parent; /* dir inode is locked */
14804+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
14805+ err = au_alive_dir(parent);
14806+ if (!err)
14807+ err = au_digen_test(parent, au_sigen(sb));
14808+ if (!err) {
14809+ npositive = au_lkup_dentry(dentry, au_dbstart(parent),
14810+ /*type*/0, nd);
14811+ err = npositive;
14812+ }
4a4d8108 14813+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
14814+ ret = ERR_PTR(err);
14815+ if (unlikely(err < 0))
14816+ goto out_unlock;
1308ab2a 14817+
4a4d8108
AM
14818+ inode = NULL;
14819+ if (npositive) {
b752ccd1 14820+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 14821+ ret = (void *)inode;
1facf9fc 14822+ }
4a4d8108
AM
14823+ if (IS_ERR(inode))
14824+ goto out_unlock;
14825+
14826+ ret = d_splice_alias(inode, dentry);
7f207e10 14827+ if (unlikely(IS_ERR(ret) && inode)) {
4a4d8108 14828+ ii_write_unlock(inode);
7f207e10
AM
14829+ iput(inode);
14830+ }
1facf9fc 14831+
4f0767ce 14832+out_unlock:
4a4d8108 14833+ di_write_unlock(dentry);
7f207e10 14834+out_si:
4a4d8108 14835+ si_read_unlock(sb);
7f207e10 14836+out:
4a4d8108
AM
14837+ return ret;
14838+}
1facf9fc 14839+
4a4d8108 14840+/* ---------------------------------------------------------------------- */
1facf9fc 14841+
4a4d8108
AM
14842+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
14843+ const unsigned char add_entry, aufs_bindex_t bcpup,
14844+ aufs_bindex_t bstart)
14845+{
14846+ int err;
14847+ struct dentry *h_parent;
14848+ struct inode *h_dir;
1facf9fc 14849+
027c5e7a 14850+ if (add_entry)
4a4d8108 14851+ IMustLock(parent->d_inode);
027c5e7a 14852+ else
4a4d8108
AM
14853+ di_write_lock_parent(parent);
14854+
14855+ err = 0;
14856+ if (!au_h_dptr(parent, bcpup)) {
14857+ if (bstart < bcpup)
14858+ err = au_cpdown_dirs(dentry, bcpup);
14859+ else
14860+ err = au_cpup_dirs(dentry, bcpup);
14861+ }
14862+ if (!err && add_entry) {
14863+ h_parent = au_h_dptr(parent, bcpup);
14864+ h_dir = h_parent->d_inode;
14865+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
14866+ err = au_lkup_neg(dentry, bcpup);
14867+ /* todo: no unlock here */
14868+ mutex_unlock(&h_dir->i_mutex);
027c5e7a
AM
14869+
14870+ AuDbg("bcpup %d\n", bcpup);
14871+ if (!err) {
14872+ if (!dentry->d_inode)
14873+ au_set_h_dptr(dentry, bstart, NULL);
4a4d8108
AM
14874+ au_update_dbrange(dentry, /*do_put_zero*/0);
14875+ }
1308ab2a 14876+ }
1facf9fc 14877+
4a4d8108
AM
14878+ if (!add_entry)
14879+ di_write_unlock(parent);
14880+ if (!err)
14881+ err = bcpup; /* success */
1308ab2a 14882+
027c5e7a 14883+ AuTraceErr(err);
4a4d8108
AM
14884+ return err;
14885+}
1facf9fc 14886+
4a4d8108
AM
14887+/*
14888+ * decide the branch and the parent dir where we will create a new entry.
14889+ * returns new bindex or an error.
14890+ * copyup the parent dir if needed.
14891+ */
14892+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14893+ struct au_wr_dir_args *args)
14894+{
14895+ int err;
14896+ aufs_bindex_t bcpup, bstart, src_bstart;
14897+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
14898+ ADD_ENTRY);
14899+ struct super_block *sb;
14900+ struct dentry *parent;
14901+ struct au_sbinfo *sbinfo;
1facf9fc 14902+
4a4d8108
AM
14903+ sb = dentry->d_sb;
14904+ sbinfo = au_sbi(sb);
14905+ parent = dget_parent(dentry);
14906+ bstart = au_dbstart(dentry);
14907+ bcpup = bstart;
14908+ if (args->force_btgt < 0) {
14909+ if (src_dentry) {
14910+ src_bstart = au_dbstart(src_dentry);
14911+ if (src_bstart < bstart)
14912+ bcpup = src_bstart;
14913+ } else if (add_entry) {
14914+ err = AuWbrCreate(sbinfo, dentry,
14915+ au_ftest_wrdir(args->flags, ISDIR));
14916+ bcpup = err;
14917+ }
1facf9fc 14918+
4a4d8108
AM
14919+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
14920+ if (add_entry)
14921+ err = AuWbrCopyup(sbinfo, dentry);
14922+ else {
14923+ if (!IS_ROOT(dentry)) {
14924+ di_read_lock_parent(parent, !AuLock_IR);
14925+ err = AuWbrCopyup(sbinfo, dentry);
14926+ di_read_unlock(parent, !AuLock_IR);
14927+ } else
14928+ err = AuWbrCopyup(sbinfo, dentry);
14929+ }
14930+ bcpup = err;
14931+ if (unlikely(err < 0))
14932+ goto out;
14933+ }
14934+ } else {
14935+ bcpup = args->force_btgt;
14936+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 14937+ }
027c5e7a 14938+
4a4d8108
AM
14939+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
14940+ err = bcpup;
14941+ if (bcpup == bstart)
14942+ goto out; /* success */
4a4d8108
AM
14943+
14944+ /* copyup the new parent into the branch we process */
14945+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
027c5e7a
AM
14946+ if (err >= 0) {
14947+ if (!dentry->d_inode) {
14948+ au_set_h_dptr(dentry, bstart, NULL);
14949+ au_set_dbstart(dentry, bcpup);
14950+ au_set_dbend(dentry, bcpup);
14951+ }
14952+ AuDebugOn(add_entry && !au_h_dptr(dentry, bcpup));
14953+ }
4a4d8108 14954+
4f0767ce 14955+out:
4a4d8108 14956+ dput(parent);
dece6358
AM
14957+ return err;
14958+}
1facf9fc 14959+
1308ab2a 14960+/* ---------------------------------------------------------------------- */
14961+
4a4d8108 14962+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 14963+{
4a4d8108
AM
14964+ if (pin && pin->parent)
14965+ return au_h_dptr(pin->parent, pin->bindex);
14966+ return NULL;
dece6358 14967+}
1facf9fc 14968+
4a4d8108 14969+void au_unpin(struct au_pin *p)
dece6358 14970+{
e49829fe 14971+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
4a4d8108
AM
14972+ mnt_drop_write(p->h_mnt);
14973+ if (!p->hdir)
14974+ return;
1facf9fc 14975+
4a4d8108
AM
14976+ au_hn_imtx_unlock(p->hdir);
14977+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14978+ di_read_unlock(p->parent, AuLock_IR);
14979+ iput(p->hdir->hi_inode);
14980+ dput(p->parent);
14981+ p->parent = NULL;
14982+ p->hdir = NULL;
14983+ p->h_mnt = NULL;
14984+}
1308ab2a 14985+
4a4d8108
AM
14986+int au_do_pin(struct au_pin *p)
14987+{
14988+ int err;
14989+ struct super_block *sb;
14990+ struct dentry *h_dentry, *h_parent;
14991+ struct au_branch *br;
14992+ struct inode *h_dir;
14993+
14994+ err = 0;
14995+ sb = p->dentry->d_sb;
14996+ br = au_sbr(sb, p->bindex);
14997+ if (IS_ROOT(p->dentry)) {
14998+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14999+ p->h_mnt = br->br_mnt;
15000+ err = mnt_want_write(p->h_mnt);
15001+ if (unlikely(err)) {
15002+ au_fclr_pin(p->flags, MNT_WRITE);
15003+ goto out_err;
15004+ }
15005+ }
dece6358 15006+ goto out;
1facf9fc 15007+ }
15008+
4a4d8108
AM
15009+ h_dentry = NULL;
15010+ if (p->bindex <= au_dbend(p->dentry))
15011+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 15012+
4a4d8108
AM
15013+ p->parent = dget_parent(p->dentry);
15014+ if (!au_ftest_pin(p->flags, DI_LOCKED))
15015+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 15016+
4a4d8108
AM
15017+ h_dir = NULL;
15018+ h_parent = au_h_dptr(p->parent, p->bindex);
15019+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
15020+ if (p->hdir)
15021+ h_dir = p->hdir->hi_inode;
dece6358 15022+
b752ccd1
AM
15023+ /*
15024+ * udba case, or
15025+ * if DI_LOCKED is not set, then p->parent may be different
15026+ * and h_parent can be NULL.
15027+ */
15028+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
e49829fe 15029+ err = -EBUSY;
4a4d8108
AM
15030+ if (!au_ftest_pin(p->flags, DI_LOCKED))
15031+ di_read_unlock(p->parent, AuLock_IR);
15032+ dput(p->parent);
15033+ p->parent = NULL;
15034+ goto out_err;
15035+ }
1308ab2a 15036+
4a4d8108
AM
15037+ au_igrab(h_dir);
15038+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 15039+
4a4d8108
AM
15040+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
15041+ err = -EBUSY;
15042+ goto out_unpin;
15043+ }
15044+ if (h_dentry) {
15045+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
15046+ if (unlikely(err)) {
15047+ au_fclr_pin(p->flags, MNT_WRITE);
15048+ goto out_unpin;
15049+ }
1facf9fc 15050+ }
dece6358 15051+
4a4d8108
AM
15052+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
15053+ p->h_mnt = br->br_mnt;
15054+ err = mnt_want_write(p->h_mnt);
dece6358 15055+ if (unlikely(err)) {
4a4d8108
AM
15056+ au_fclr_pin(p->flags, MNT_WRITE);
15057+ goto out_unpin;
dece6358
AM
15058+ }
15059+ }
4a4d8108
AM
15060+ goto out; /* success */
15061+
4f0767ce 15062+out_unpin:
4a4d8108 15063+ au_unpin(p);
4f0767ce 15064+out_err:
4a4d8108
AM
15065+ pr_err("err %d\n", err);
15066+ err = au_busy_or_stale();
4f0767ce 15067+out:
1facf9fc 15068+ return err;
15069+}
15070+
4a4d8108
AM
15071+void au_pin_init(struct au_pin *p, struct dentry *dentry,
15072+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
15073+ unsigned int udba, unsigned char flags)
15074+{
15075+ p->dentry = dentry;
15076+ p->udba = udba;
15077+ p->lsc_di = lsc_di;
15078+ p->lsc_hi = lsc_hi;
15079+ p->flags = flags;
15080+ p->bindex = bindex;
15081+
15082+ p->parent = NULL;
15083+ p->hdir = NULL;
15084+ p->h_mnt = NULL;
15085+}
15086+
15087+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
15088+ unsigned int udba, unsigned char flags)
15089+{
15090+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
15091+ udba, flags);
15092+ return au_do_pin(pin);
15093+}
15094+
dece6358
AM
15095+/* ---------------------------------------------------------------------- */
15096+
1308ab2a 15097+/*
4a4d8108
AM
15098+ * ->setattr() and ->getattr() are called in various cases.
15099+ * chmod, stat: dentry is revalidated.
15100+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
15101+ * unhashed.
15102+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 15103+ */
027c5e7a 15104+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
4a4d8108 15105+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 15106+{
4a4d8108
AM
15107+ int err;
15108+ struct inode *inode;
15109+ struct dentry *parent;
1facf9fc 15110+
1308ab2a 15111+ err = 0;
4a4d8108 15112+ inode = dentry->d_inode;
027c5e7a 15113+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
15114+ parent = dget_parent(dentry);
15115+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 15116+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
15117+ di_read_unlock(parent, AuLock_IR);
15118+ dput(parent);
dece6358 15119+ }
1facf9fc 15120+
4a4d8108 15121+ AuTraceErr(err);
1308ab2a 15122+ return err;
15123+}
dece6358 15124+
4a4d8108
AM
15125+#define AuIcpup_DID_CPUP 1
15126+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
7f207e10
AM
15127+#define au_fset_icpup(flags, name) \
15128+ do { (flags) |= AuIcpup_##name; } while (0)
15129+#define au_fclr_icpup(flags, name) \
15130+ do { (flags) &= ~AuIcpup_##name; } while (0)
1308ab2a 15131+
4a4d8108
AM
15132+struct au_icpup_args {
15133+ unsigned char flags;
15134+ unsigned char pin_flags;
15135+ aufs_bindex_t btgt;
15136+ unsigned int udba;
15137+ struct au_pin pin;
15138+ struct path h_path;
15139+ struct inode *h_inode;
15140+};
1308ab2a 15141+
4a4d8108
AM
15142+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
15143+ struct au_icpup_args *a)
1308ab2a 15144+{
15145+ int err;
4a4d8108 15146+ loff_t sz;
e49829fe 15147+ aufs_bindex_t bstart, ibstart;
4a4d8108
AM
15148+ struct dentry *hi_wh, *parent;
15149+ struct inode *inode;
15150+ struct file *h_file;
15151+ struct au_wr_dir_args wr_dir_args = {
15152+ .force_btgt = -1,
15153+ .flags = 0
15154+ };
15155+
15156+ bstart = au_dbstart(dentry);
15157+ inode = dentry->d_inode;
15158+ if (S_ISDIR(inode->i_mode))
15159+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
15160+ /* plink or hi_wh() case */
e49829fe 15161+ ibstart = au_ibstart(inode);
027c5e7a 15162+ if (bstart != ibstart && !au_test_ro(inode->i_sb, ibstart, inode))
e49829fe 15163+ wr_dir_args.force_btgt = ibstart;
4a4d8108
AM
15164+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
15165+ if (unlikely(err < 0))
15166+ goto out;
15167+ a->btgt = err;
15168+ if (err != bstart)
15169+ au_fset_icpup(a->flags, DID_CPUP);
15170+
15171+ err = 0;
15172+ a->pin_flags = AuPin_MNT_WRITE;
15173+ parent = NULL;
15174+ if (!IS_ROOT(dentry)) {
15175+ au_fset_pin(a->pin_flags, DI_LOCKED);
15176+ parent = dget_parent(dentry);
15177+ di_write_lock_parent(parent);
15178+ }
15179+
15180+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
15181+ if (unlikely(err))
15182+ goto out_parent;
15183+
15184+ a->h_path.dentry = au_h_dptr(dentry, bstart);
15185+ a->h_inode = a->h_path.dentry->d_inode;
15186+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
15187+ sz = -1;
15188+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
15189+ sz = ia->ia_size;
15190+
15191+ h_file = NULL;
15192+ hi_wh = NULL;
027c5e7a 15193+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
15194+ hi_wh = au_hi_wh(inode, a->btgt);
15195+ if (!hi_wh) {
15196+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
15197+ if (unlikely(err))
15198+ goto out_unlock;
15199+ hi_wh = au_hi_wh(inode, a->btgt);
15200+ /* todo: revalidate hi_wh? */
15201+ }
15202+ }
15203+
15204+ if (parent) {
15205+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
15206+ di_downgrade_lock(parent, AuLock_IR);
15207+ dput(parent);
15208+ parent = NULL;
15209+ }
15210+ if (!au_ftest_icpup(a->flags, DID_CPUP))
15211+ goto out; /* success */
15212+
15213+ if (!d_unhashed(dentry)) {
15214+ h_file = au_h_open_pre(dentry, bstart);
15215+ if (IS_ERR(h_file)) {
15216+ err = PTR_ERR(h_file);
15217+ h_file = NULL;
15218+ } else
15219+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
15220+ AuCpup_DTIME);
15221+ if (!err)
15222+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
15223+ } else if (!hi_wh)
15224+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
15225+ else
15226+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 15227+
4f0767ce 15228+out_unlock:
4a4d8108
AM
15229+ mutex_unlock(&a->h_inode->i_mutex);
15230+ au_h_open_post(dentry, bstart, h_file);
15231+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 15232+ if (!err) {
4a4d8108 15233+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 15234+ goto out; /* success */
1facf9fc 15235+ }
dece6358 15236+
4a4d8108 15237+ au_unpin(&a->pin);
4f0767ce 15238+out_parent:
4a4d8108
AM
15239+ if (parent) {
15240+ di_write_unlock(parent);
15241+ dput(parent);
15242+ }
4f0767ce 15243+out:
1facf9fc 15244+ return err;
15245+}
15246+
4a4d8108 15247+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 15248+{
4a4d8108
AM
15249+ int err;
15250+ struct inode *inode;
15251+ struct super_block *sb;
15252+ struct file *file;
15253+ struct au_icpup_args *a;
1facf9fc 15254+
4a4d8108
AM
15255+ inode = dentry->d_inode;
15256+ IMustLock(inode);
dece6358 15257+
4a4d8108
AM
15258+ err = -ENOMEM;
15259+ a = kzalloc(sizeof(*a), GFP_NOFS);
15260+ if (unlikely(!a))
15261+ goto out;
1facf9fc 15262+
4a4d8108
AM
15263+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
15264+ ia->ia_valid &= ~ATTR_MODE;
dece6358 15265+
4a4d8108
AM
15266+ file = NULL;
15267+ sb = dentry->d_sb;
e49829fe
JR
15268+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15269+ if (unlikely(err))
15270+ goto out_kfree;
15271+
4a4d8108
AM
15272+ if (ia->ia_valid & ATTR_FILE) {
15273+ /* currently ftruncate(2) only */
15274+ AuDebugOn(!S_ISREG(inode->i_mode));
15275+ file = ia->ia_file;
15276+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
15277+ if (unlikely(err))
15278+ goto out_si;
15279+ ia->ia_file = au_hf_top(file);
15280+ a->udba = AuOpt_UDBA_NONE;
15281+ } else {
15282+ /* fchmod() doesn't pass ia_file */
15283+ a->udba = au_opt_udba(sb);
027c5e7a
AM
15284+ di_write_lock_child(dentry);
15285+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
15286+ if (d_unhashed(dentry))
15287+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
15288+ if (a->udba != AuOpt_UDBA_NONE) {
15289+ AuDebugOn(IS_ROOT(dentry));
15290+ err = au_reval_for_attr(dentry, au_sigen(sb));
15291+ if (unlikely(err))
15292+ goto out_dentry;
15293+ }
dece6358 15294+ }
dece6358 15295+
4a4d8108
AM
15296+ err = au_pin_and_icpup(dentry, ia, a);
15297+ if (unlikely(err < 0))
15298+ goto out_dentry;
15299+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
15300+ ia->ia_file = NULL;
15301+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 15302+ }
dece6358 15303+
4a4d8108
AM
15304+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
15305+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
15306+ == (ATTR_MODE | ATTR_CTIME)) {
15307+ err = security_path_chmod(a->h_path.dentry, a->h_path.mnt,
15308+ ia->ia_mode);
15309+ if (unlikely(err))
15310+ goto out_unlock;
15311+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
15312+ && (ia->ia_valid & ATTR_CTIME)) {
15313+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
15314+ if (unlikely(err))
15315+ goto out_unlock;
15316+ }
dece6358 15317+
4a4d8108
AM
15318+ if (ia->ia_valid & ATTR_SIZE) {
15319+ struct file *f;
1308ab2a 15320+
953406b4 15321+ if (ia->ia_size < i_size_read(inode))
4a4d8108 15322+ /* unmap only */
953406b4 15323+ truncate_setsize(inode, ia->ia_size);
1308ab2a 15324+
4a4d8108
AM
15325+ f = NULL;
15326+ if (ia->ia_valid & ATTR_FILE)
15327+ f = ia->ia_file;
15328+ mutex_unlock(&a->h_inode->i_mutex);
15329+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
15330+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
15331+ } else
15332+ err = vfsub_notify_change(&a->h_path, ia);
15333+ if (!err)
15334+ au_cpup_attr_changeable(inode);
1308ab2a 15335+
4f0767ce 15336+out_unlock:
4a4d8108
AM
15337+ mutex_unlock(&a->h_inode->i_mutex);
15338+ au_unpin(&a->pin);
027c5e7a
AM
15339+ if (unlikely(err))
15340+ au_update_dbstart(dentry);
4f0767ce 15341+out_dentry:
4a4d8108
AM
15342+ di_write_unlock(dentry);
15343+ if (file) {
15344+ fi_write_unlock(file);
15345+ ia->ia_file = file;
15346+ ia->ia_valid |= ATTR_FILE;
15347+ }
4f0767ce 15348+out_si:
4a4d8108 15349+ si_read_unlock(sb);
e49829fe 15350+out_kfree:
4a4d8108 15351+ kfree(a);
4f0767ce 15352+out:
4a4d8108
AM
15353+ AuTraceErr(err);
15354+ return err;
1facf9fc 15355+}
15356+
4a4d8108
AM
15357+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
15358+ unsigned int nlink)
1facf9fc 15359+{
4a4d8108
AM
15360+ inode->i_mode = st->mode;
15361+ inode->i_uid = st->uid;
15362+ inode->i_gid = st->gid;
15363+ inode->i_atime = st->atime;
15364+ inode->i_mtime = st->mtime;
15365+ inode->i_ctime = st->ctime;
1facf9fc 15366+
4a4d8108
AM
15367+ au_cpup_attr_nlink(inode, /*force*/0);
15368+ if (S_ISDIR(inode->i_mode)) {
15369+ inode->i_nlink -= nlink;
15370+ inode->i_nlink += st->nlink;
15371+ }
1facf9fc 15372+
4a4d8108
AM
15373+ spin_lock(&inode->i_lock);
15374+ inode->i_blocks = st->blocks;
15375+ i_size_write(inode, st->size);
15376+ spin_unlock(&inode->i_lock);
1facf9fc 15377+}
15378+
4a4d8108
AM
15379+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
15380+ struct dentry *dentry, struct kstat *st)
1facf9fc 15381+{
4a4d8108
AM
15382+ int err;
15383+ unsigned int mnt_flags;
15384+ aufs_bindex_t bindex;
15385+ unsigned char udba_none, positive;
15386+ struct super_block *sb, *h_sb;
15387+ struct inode *inode;
15388+ struct vfsmount *h_mnt;
15389+ struct dentry *h_dentry;
1facf9fc 15390+
4a4d8108
AM
15391+ sb = dentry->d_sb;
15392+ inode = dentry->d_inode;
7f207e10
AM
15393+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15394+ if (unlikely(err))
15395+ goto out;
4a4d8108
AM
15396+ mnt_flags = au_mntflags(sb);
15397+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 15398+
4a4d8108 15399+ /* support fstat(2) */
027c5e7a 15400+ if (!d_unlinked(dentry) && !udba_none) {
4a4d8108 15401+ unsigned int sigen = au_sigen(sb);
027c5e7a
AM
15402+ err = au_digen_test(dentry, sigen);
15403+ if (!err) {
4a4d8108 15404+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a
AM
15405+ err = au_dbrange_test(dentry);
15406+ if (unlikely(err))
15407+ goto out_unlock;
15408+ } else {
4a4d8108
AM
15409+ AuDebugOn(IS_ROOT(dentry));
15410+ di_write_lock_child(dentry);
027c5e7a
AM
15411+ err = au_dbrange_test(dentry);
15412+ if (!err)
15413+ err = au_reval_for_attr(dentry, sigen);
4a4d8108
AM
15414+ di_downgrade_lock(dentry, AuLock_IR);
15415+ if (unlikely(err))
7f207e10 15416+ goto out_unlock;
4a4d8108
AM
15417+ }
15418+ } else
15419+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 15420+
4a4d8108
AM
15421+ bindex = au_ibstart(inode);
15422+ h_mnt = au_sbr_mnt(sb, bindex);
15423+ h_sb = h_mnt->mnt_sb;
15424+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
15425+ goto out_fill; /* success */
1facf9fc 15426+
4a4d8108
AM
15427+ h_dentry = NULL;
15428+ if (au_dbstart(dentry) == bindex)
15429+ h_dentry = dget(au_h_dptr(dentry, bindex));
15430+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
15431+ h_dentry = au_plink_lkup(inode, bindex);
15432+ if (IS_ERR(h_dentry))
15433+ goto out_fill; /* pretending success */
15434+ }
15435+ /* illegally overlapped or something */
15436+ if (unlikely(!h_dentry))
15437+ goto out_fill; /* pretending success */
15438+
15439+ positive = !!h_dentry->d_inode;
15440+ if (positive)
15441+ err = vfs_getattr(h_mnt, h_dentry, st);
15442+ dput(h_dentry);
15443+ if (!err) {
15444+ if (positive)
15445+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
15446+ goto out_fill; /* success */
1facf9fc 15447+ }
7f207e10
AM
15448+ AuTraceErr(err);
15449+ goto out_unlock;
4a4d8108 15450+
4f0767ce 15451+out_fill:
4a4d8108 15452+ generic_fillattr(inode, st);
7f207e10 15453+out_unlock:
4a4d8108
AM
15454+ di_read_unlock(dentry, AuLock_IR);
15455+ si_read_unlock(sb);
7f207e10
AM
15456+out:
15457+ AuTraceErr(err);
4a4d8108 15458+ return err;
1facf9fc 15459+}
15460+
15461+/* ---------------------------------------------------------------------- */
15462+
4a4d8108
AM
15463+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
15464+ int bufsiz)
1facf9fc 15465+{
15466+ int err;
4a4d8108
AM
15467+ struct super_block *sb;
15468+ struct dentry *h_dentry;
1facf9fc 15469+
4a4d8108
AM
15470+ err = -EINVAL;
15471+ h_dentry = au_h_dptr(dentry, bindex);
15472+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
15473+ goto out;
1facf9fc 15474+
4a4d8108
AM
15475+ err = security_inode_readlink(h_dentry);
15476+ if (unlikely(err))
dece6358 15477+ goto out;
1facf9fc 15478+
4a4d8108
AM
15479+ sb = dentry->d_sb;
15480+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
15481+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
15482+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 15483+ }
4a4d8108 15484+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 15485+
4f0767ce 15486+out:
4a4d8108
AM
15487+ return err;
15488+}
1facf9fc 15489+
4a4d8108
AM
15490+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
15491+{
15492+ int err;
1facf9fc 15493+
027c5e7a
AM
15494+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
15495+ if (unlikely(err))
15496+ goto out;
15497+ err = au_d_hashed_positive(dentry);
15498+ if (!err)
15499+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
4a4d8108 15500+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 15501+
027c5e7a 15502+out:
4a4d8108
AM
15503+ return err;
15504+}
1facf9fc 15505+
4a4d8108
AM
15506+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
15507+{
15508+ int err;
4a4d8108 15509+ mm_segment_t old_fs;
b752ccd1
AM
15510+ union {
15511+ char *k;
15512+ char __user *u;
15513+ } buf;
1facf9fc 15514+
4a4d8108 15515+ err = -ENOMEM;
b752ccd1
AM
15516+ buf.k = __getname_gfp(GFP_NOFS);
15517+ if (unlikely(!buf.k))
4a4d8108 15518+ goto out;
1facf9fc 15519+
027c5e7a
AM
15520+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
15521+ if (unlikely(err))
15522+ goto out_name;
15523+
15524+ err = au_d_hashed_positive(dentry);
15525+ if (!err) {
15526+ old_fs = get_fs();
15527+ set_fs(KERNEL_DS);
15528+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
15529+ set_fs(old_fs);
15530+ }
4a4d8108 15531+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 15532+
4a4d8108 15533+ if (err >= 0) {
b752ccd1 15534+ buf.k[err] = 0;
4a4d8108 15535+ /* will be freed by put_link */
b752ccd1 15536+ nd_set_link(nd, buf.k);
4a4d8108 15537+ return NULL; /* success */
1308ab2a 15538+ }
1facf9fc 15539+
027c5e7a
AM
15540+out_name:
15541+ __putname(buf.k);
4f0767ce 15542+out:
4a4d8108
AM
15543+ path_put(&nd->path);
15544+ AuTraceErr(err);
15545+ return ERR_PTR(err);
15546+}
1facf9fc 15547+
4a4d8108
AM
15548+static void aufs_put_link(struct dentry *dentry __maybe_unused,
15549+ struct nameidata *nd, void *cookie __maybe_unused)
15550+{
15551+ __putname(nd_get_link(nd));
15552+}
1facf9fc 15553+
4a4d8108 15554+/* ---------------------------------------------------------------------- */
1facf9fc 15555+
4a4d8108
AM
15556+static void aufs_truncate_range(struct inode *inode __maybe_unused,
15557+ loff_t start __maybe_unused,
15558+ loff_t end __maybe_unused)
15559+{
15560+ AuUnsupport();
15561+}
1facf9fc 15562+
4a4d8108 15563+/* ---------------------------------------------------------------------- */
1308ab2a 15564+
4a4d8108
AM
15565+struct inode_operations aufs_symlink_iop = {
15566+ .permission = aufs_permission,
15567+ .setattr = aufs_setattr,
15568+ .getattr = aufs_getattr,
15569+ .readlink = aufs_readlink,
15570+ .follow_link = aufs_follow_link,
15571+ .put_link = aufs_put_link
15572+};
15573+
15574+struct inode_operations aufs_dir_iop = {
15575+ .create = aufs_create,
15576+ .lookup = aufs_lookup,
15577+ .link = aufs_link,
15578+ .unlink = aufs_unlink,
15579+ .symlink = aufs_symlink,
15580+ .mkdir = aufs_mkdir,
15581+ .rmdir = aufs_rmdir,
15582+ .mknod = aufs_mknod,
15583+ .rename = aufs_rename,
15584+
15585+ .permission = aufs_permission,
15586+ .setattr = aufs_setattr,
15587+ .getattr = aufs_getattr
15588+};
15589+
15590+struct inode_operations aufs_iop = {
15591+ .permission = aufs_permission,
15592+ .setattr = aufs_setattr,
15593+ .getattr = aufs_getattr,
15594+ .truncate_range = aufs_truncate_range
15595+};
7f207e10
AM
15596diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
15597--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
15598+++ linux/fs/aufs/i_op_del.c 2011-03-21 20:22:06.857268914 +0100
15599@@ -0,0 +1,481 @@
1facf9fc 15600+/*
027c5e7a 15601+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 15602+ *
15603+ * This program, aufs is free software; you can redistribute it and/or modify
15604+ * it under the terms of the GNU General Public License as published by
15605+ * the Free Software Foundation; either version 2 of the License, or
15606+ * (at your option) any later version.
dece6358
AM
15607+ *
15608+ * This program is distributed in the hope that it will be useful,
15609+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15610+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15611+ * GNU General Public License for more details.
15612+ *
15613+ * You should have received a copy of the GNU General Public License
15614+ * along with this program; if not, write to the Free Software
15615+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 15616+ */
15617+
15618+/*
4a4d8108 15619+ * inode operations (del entry)
1308ab2a 15620+ */
dece6358 15621+
1308ab2a 15622+#include "aufs.h"
dece6358 15623+
4a4d8108
AM
15624+/*
15625+ * decide if a new whiteout for @dentry is necessary or not.
15626+ * when it is necessary, prepare the parent dir for the upper branch whose
15627+ * branch index is @bcpup for creation. the actual creation of the whiteout will
15628+ * be done by caller.
15629+ * return value:
15630+ * 0: wh is unnecessary
15631+ * plus: wh is necessary
15632+ * minus: error
15633+ */
15634+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 15635+{
4a4d8108
AM
15636+ int need_wh, err;
15637+ aufs_bindex_t bstart;
15638+ struct super_block *sb;
dece6358 15639+
4a4d8108
AM
15640+ sb = dentry->d_sb;
15641+ bstart = au_dbstart(dentry);
15642+ if (*bcpup < 0) {
15643+ *bcpup = bstart;
15644+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
15645+ err = AuWbrCopyup(au_sbi(sb), dentry);
15646+ *bcpup = err;
15647+ if (unlikely(err < 0))
15648+ goto out;
15649+ }
15650+ } else
15651+ AuDebugOn(bstart < *bcpup
15652+ || au_test_ro(sb, *bcpup, dentry->d_inode));
15653+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 15654+
4a4d8108
AM
15655+ if (*bcpup != bstart) {
15656+ err = au_cpup_dirs(dentry, *bcpup);
15657+ if (unlikely(err))
15658+ goto out;
15659+ need_wh = 1;
15660+ } else {
027c5e7a 15661+ struct au_dinfo *dinfo, *tmp;
4a4d8108 15662+
027c5e7a
AM
15663+ need_wh = -ENOMEM;
15664+ dinfo = au_di(dentry);
15665+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
15666+ if (tmp) {
15667+ au_di_cp(tmp, dinfo);
15668+ au_di_swap(tmp, dinfo);
15669+ /* returns the number of positive dentries */
15670+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
15671+ /*nd*/NULL);
15672+ au_di_swap(tmp, dinfo);
15673+ au_rw_write_unlock(&tmp->di_rwsem);
15674+ au_di_free(tmp);
4a4d8108
AM
15675+ }
15676+ }
15677+ AuDbg("need_wh %d\n", need_wh);
15678+ err = need_wh;
15679+
4f0767ce 15680+out:
4a4d8108 15681+ return err;
1facf9fc 15682+}
15683+
4a4d8108
AM
15684+/*
15685+ * simple tests for the del-entry operations.
15686+ * following the checks in vfs, plus the parent-child relationship.
15687+ */
15688+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
15689+ struct dentry *h_parent, int isdir)
1facf9fc 15690+{
4a4d8108
AM
15691+ int err;
15692+ umode_t h_mode;
15693+ struct dentry *h_dentry, *h_latest;
1308ab2a 15694+ struct inode *h_inode;
1facf9fc 15695+
4a4d8108
AM
15696+ h_dentry = au_h_dptr(dentry, bindex);
15697+ h_inode = h_dentry->d_inode;
15698+ if (dentry->d_inode) {
15699+ err = -ENOENT;
15700+ if (unlikely(!h_inode || !h_inode->i_nlink))
15701+ goto out;
1facf9fc 15702+
4a4d8108
AM
15703+ h_mode = h_inode->i_mode;
15704+ if (!isdir) {
15705+ err = -EISDIR;
15706+ if (unlikely(S_ISDIR(h_mode)))
15707+ goto out;
15708+ } else if (unlikely(!S_ISDIR(h_mode))) {
15709+ err = -ENOTDIR;
15710+ goto out;
15711+ }
15712+ } else {
15713+ /* rename(2) case */
15714+ err = -EIO;
15715+ if (unlikely(h_inode))
15716+ goto out;
15717+ }
1facf9fc 15718+
4a4d8108
AM
15719+ err = -ENOENT;
15720+ /* expected parent dir is locked */
15721+ if (unlikely(h_parent != h_dentry->d_parent))
15722+ goto out;
15723+ err = 0;
15724+
15725+ /*
15726+ * rmdir a dir may break the consistency on some filesystem.
15727+ * let's try heavy test.
15728+ */
15729+ err = -EACCES;
15730+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
15731+ goto out;
15732+
15733+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
15734+ au_sbr(dentry->d_sb, bindex));
15735+ err = -EIO;
15736+ if (IS_ERR(h_latest))
15737+ goto out;
15738+ if (h_latest == h_dentry)
15739+ err = 0;
15740+ dput(h_latest);
15741+
4f0767ce 15742+out:
4a4d8108 15743+ return err;
1308ab2a 15744+}
1facf9fc 15745+
4a4d8108
AM
15746+/*
15747+ * decide the branch where we operate for @dentry. the branch index will be set
15748+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
15749+ * dir for reverting.
15750+ * when a new whiteout is necessary, create it.
15751+ */
15752+static struct dentry*
15753+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
15754+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 15755+{
4a4d8108
AM
15756+ struct dentry *wh_dentry;
15757+ struct super_block *sb;
15758+ struct path h_path;
15759+ int err, need_wh;
15760+ unsigned int udba;
15761+ aufs_bindex_t bcpup;
dece6358 15762+
4a4d8108
AM
15763+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
15764+ wh_dentry = ERR_PTR(need_wh);
15765+ if (unlikely(need_wh < 0))
15766+ goto out;
15767+
15768+ sb = dentry->d_sb;
15769+ udba = au_opt_udba(sb);
15770+ bcpup = *rbcpup;
15771+ err = au_pin(pin, dentry, bcpup, udba,
15772+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15773+ wh_dentry = ERR_PTR(err);
15774+ if (unlikely(err))
15775+ goto out;
15776+
15777+ h_path.dentry = au_pinned_h_parent(pin);
15778+ if (udba != AuOpt_UDBA_NONE
15779+ && au_dbstart(dentry) == bcpup) {
15780+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
15781+ wh_dentry = ERR_PTR(err);
15782+ if (unlikely(err))
15783+ goto out_unpin;
15784+ }
15785+
15786+ h_path.mnt = au_sbr_mnt(sb, bcpup);
15787+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
15788+ wh_dentry = NULL;
15789+ if (!need_wh)
15790+ goto out; /* success, no need to create whiteout */
15791+
15792+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
15793+ if (IS_ERR(wh_dentry))
15794+ goto out_unpin;
15795+
15796+ /* returns with the parent is locked and wh_dentry is dget-ed */
15797+ goto out; /* success */
15798+
4f0767ce 15799+out_unpin:
4a4d8108 15800+ au_unpin(pin);
4f0767ce 15801+out:
4a4d8108 15802+ return wh_dentry;
1facf9fc 15803+}
15804+
4a4d8108
AM
15805+/*
15806+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
15807+ * in order to be revertible and save time for removing many child whiteouts
15808+ * under the dir.
15809+ * returns 1 when there are too many child whiteout and caller should remove
15810+ * them asynchronously. returns 0 when the number of children is enough small to
15811+ * remove now or the branch fs is a remote fs.
15812+ * otherwise return an error.
15813+ */
15814+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
15815+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 15816+{
4a4d8108
AM
15817+ int rmdir_later, err, dirwh;
15818+ struct dentry *h_dentry;
15819+ struct super_block *sb;
15820+
15821+ sb = dentry->d_sb;
15822+ SiMustAnyLock(sb);
15823+ h_dentry = au_h_dptr(dentry, bindex);
15824+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
15825+ if (unlikely(err))
15826+ goto out;
15827+
15828+ /* stop monitoring */
15829+ au_hn_free(au_hi(dentry->d_inode, bindex));
15830+
15831+ if (!au_test_fs_remote(h_dentry->d_sb)) {
15832+ dirwh = au_sbi(sb)->si_dirwh;
15833+ rmdir_later = (dirwh <= 1);
15834+ if (!rmdir_later)
15835+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
15836+ dirwh);
15837+ if (rmdir_later)
15838+ return rmdir_later;
15839+ }
1facf9fc 15840+
4a4d8108
AM
15841+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
15842+ if (unlikely(err)) {
15843+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
15844+ AuDLNPair(h_dentry), bindex, err);
15845+ err = 0;
15846+ }
dece6358 15847+
4f0767ce 15848+out:
4a4d8108
AM
15849+ AuTraceErr(err);
15850+ return err;
15851+}
1308ab2a 15852+
4a4d8108
AM
15853+/*
15854+ * final procedure for deleting a entry.
15855+ * maintain dentry and iattr.
15856+ */
15857+static void epilog(struct inode *dir, struct dentry *dentry,
15858+ aufs_bindex_t bindex)
15859+{
15860+ struct inode *inode;
1308ab2a 15861+
4a4d8108
AM
15862+ inode = dentry->d_inode;
15863+ d_drop(dentry);
15864+ inode->i_ctime = dir->i_ctime;
1308ab2a 15865+
4a4d8108
AM
15866+ if (au_ibstart(dir) == bindex)
15867+ au_cpup_attr_timesizes(dir);
15868+ dir->i_version++;
1facf9fc 15869+}
15870+
4a4d8108
AM
15871+/*
15872+ * when an error happened, remove the created whiteout and revert everything.
15873+ */
7f207e10
AM
15874+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
15875+ aufs_bindex_t bwh, struct dentry *wh_dentry,
15876+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 15877+{
4a4d8108
AM
15878+ int rerr;
15879+ struct path h_path = {
15880+ .dentry = wh_dentry,
7f207e10 15881+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 15882+ };
dece6358 15883+
7f207e10 15884+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
15885+ if (!rerr) {
15886+ au_set_dbwh(dentry, bwh);
15887+ au_dtime_revert(dt);
15888+ return 0;
15889+ }
dece6358 15890+
4a4d8108
AM
15891+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15892+ AuDLNPair(dentry), err, rerr);
15893+ return -EIO;
1facf9fc 15894+}
15895+
4a4d8108 15896+/* ---------------------------------------------------------------------- */
1facf9fc 15897+
4a4d8108 15898+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 15899+{
4a4d8108
AM
15900+ int err;
15901+ aufs_bindex_t bwh, bindex, bstart;
15902+ struct au_dtime dt;
15903+ struct au_pin pin;
15904+ struct path h_path;
15905+ struct inode *inode, *h_dir;
15906+ struct dentry *parent, *wh_dentry;
1facf9fc 15907+
4a4d8108 15908+ IMustLock(dir);
027c5e7a
AM
15909+
15910+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15911+ if (unlikely(err))
15912+ goto out;
15913+ err = au_d_hashed_positive(dentry);
15914+ if (unlikely(err))
15915+ goto out_unlock;
4a4d8108 15916+ inode = dentry->d_inode;
4a4d8108 15917+ IMustLock(inode);
027c5e7a
AM
15918+ err = -EISDIR;
15919+ if (unlikely(S_ISDIR(inode->i_mode)))
15920+ goto out_unlock; /* possible? */
1facf9fc 15921+
4a4d8108
AM
15922+ bstart = au_dbstart(dentry);
15923+ bwh = au_dbwh(dentry);
15924+ bindex = -1;
027c5e7a
AM
15925+ parent = dentry->d_parent; /* dir inode is locked */
15926+ di_write_lock_parent(parent);
4a4d8108
AM
15927+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
15928+ err = PTR_ERR(wh_dentry);
15929+ if (IS_ERR(wh_dentry))
027c5e7a 15930+ goto out_parent;
1facf9fc 15931+
4a4d8108
AM
15932+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
15933+ h_path.dentry = au_h_dptr(dentry, bstart);
15934+ dget(h_path.dentry);
15935+ if (bindex == bstart) {
15936+ h_dir = au_pinned_h_dir(&pin);
15937+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
15938+ } else {
15939+ /* dir inode is locked */
15940+ h_dir = wh_dentry->d_parent->d_inode;
15941+ IMustLock(h_dir);
15942+ err = 0;
15943+ }
dece6358 15944+
4a4d8108 15945+ if (!err) {
7f207e10 15946+ vfsub_drop_nlink(inode);
4a4d8108
AM
15947+ epilog(dir, dentry, bindex);
15948+
15949+ /* update target timestamps */
15950+ if (bindex == bstart) {
15951+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
15952+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
15953+ } else
15954+ /* todo: this timestamp may be reverted later */
15955+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 15956+ goto out_unpin; /* success */
1facf9fc 15957+ }
15958+
4a4d8108
AM
15959+ /* revert */
15960+ if (wh_dentry) {
15961+ int rerr;
15962+
7f207e10 15963+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
15964+ if (rerr)
15965+ err = rerr;
dece6358 15966+ }
1facf9fc 15967+
027c5e7a 15968+out_unpin:
4a4d8108
AM
15969+ au_unpin(&pin);
15970+ dput(wh_dentry);
15971+ dput(h_path.dentry);
027c5e7a 15972+out_parent:
4a4d8108 15973+ di_write_unlock(parent);
027c5e7a 15974+out_unlock:
4a4d8108 15975+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15976+out:
4a4d8108 15977+ return err;
dece6358
AM
15978+}
15979+
4a4d8108 15980+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 15981+{
4a4d8108
AM
15982+ int err, rmdir_later;
15983+ aufs_bindex_t bwh, bindex, bstart;
15984+ struct au_dtime dt;
15985+ struct au_pin pin;
15986+ struct inode *inode;
15987+ struct dentry *parent, *wh_dentry, *h_dentry;
15988+ struct au_whtmp_rmdir *args;
1facf9fc 15989+
4a4d8108 15990+ IMustLock(dir);
027c5e7a
AM
15991+
15992+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
15993+ if (unlikely(err))
4a4d8108 15994+ goto out;
027c5e7a
AM
15995+
15996+ /* VFS already unhashes it */
15997+ inode = dentry->d_inode;
15998+ err = -ENOENT;
15999+ if (unlikely(!inode || !inode->i_nlink
16000+ || IS_DEADDIR(inode)))
16001+ goto out_unlock;
4a4d8108 16002+ IMustLock(inode);
027c5e7a
AM
16003+ err = -ENOTDIR;
16004+ if (unlikely(!S_ISDIR(inode->i_mode)))
16005+ goto out_unlock; /* possible? */
dece6358 16006+
4a4d8108
AM
16007+ err = -ENOMEM;
16008+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
16009+ if (unlikely(!args))
16010+ goto out_unlock;
dece6358 16011+
4a4d8108
AM
16012+ parent = dentry->d_parent; /* dir inode is locked */
16013+ di_write_lock_parent(parent);
16014+ err = au_test_empty(dentry, &args->whlist);
16015+ if (unlikely(err))
027c5e7a 16016+ goto out_parent;
1facf9fc 16017+
4a4d8108
AM
16018+ bstart = au_dbstart(dentry);
16019+ bwh = au_dbwh(dentry);
16020+ bindex = -1;
16021+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
16022+ err = PTR_ERR(wh_dentry);
16023+ if (IS_ERR(wh_dentry))
027c5e7a 16024+ goto out_parent;
1facf9fc 16025+
4a4d8108
AM
16026+ h_dentry = au_h_dptr(dentry, bstart);
16027+ dget(h_dentry);
16028+ rmdir_later = 0;
16029+ if (bindex == bstart) {
16030+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
16031+ if (err > 0) {
16032+ rmdir_later = err;
16033+ err = 0;
16034+ }
16035+ } else {
16036+ /* stop monitoring */
16037+ au_hn_free(au_hi(inode, bstart));
16038+
16039+ /* dir inode is locked */
16040+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 16041+ err = 0;
16042+ }
16043+
4a4d8108 16044+ if (!err) {
027c5e7a 16045+ vfsub_dead_dir(inode);
4a4d8108
AM
16046+ au_set_dbdiropq(dentry, -1);
16047+ epilog(dir, dentry, bindex);
1308ab2a 16048+
4a4d8108
AM
16049+ if (rmdir_later) {
16050+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
16051+ args = NULL;
16052+ }
1308ab2a 16053+
4a4d8108 16054+ goto out_unpin; /* success */
1facf9fc 16055+ }
16056+
4a4d8108
AM
16057+ /* revert */
16058+ AuLabel(revert);
16059+ if (wh_dentry) {
16060+ int rerr;
1308ab2a 16061+
7f207e10 16062+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
16063+ if (rerr)
16064+ err = rerr;
1facf9fc 16065+ }
16066+
4f0767ce 16067+out_unpin:
4a4d8108
AM
16068+ au_unpin(&pin);
16069+ dput(wh_dentry);
16070+ dput(h_dentry);
027c5e7a 16071+out_parent:
4a4d8108
AM
16072+ di_write_unlock(parent);
16073+ if (args)
16074+ au_whtmp_rmdir_free(args);
4f0767ce 16075+out_unlock:
4a4d8108 16076+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 16077+out:
4a4d8108
AM
16078+ AuTraceErr(err);
16079+ return err;
dece6358 16080+}
7f207e10
AM
16081diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
16082--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
16083+++ linux/fs/aufs/i_op_ren.c 2011-03-21 20:22:06.857268914 +0100
16084@@ -0,0 +1,1017 @@
1facf9fc 16085+/*
027c5e7a 16086+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 16087+ *
16088+ * This program, aufs is free software; you can redistribute it and/or modify
16089+ * it under the terms of the GNU General Public License as published by
16090+ * the Free Software Foundation; either version 2 of the License, or
16091+ * (at your option) any later version.
dece6358
AM
16092+ *
16093+ * This program is distributed in the hope that it will be useful,
16094+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16095+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16096+ * GNU General Public License for more details.
16097+ *
16098+ * You should have received a copy of the GNU General Public License
16099+ * along with this program; if not, write to the Free Software
16100+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16101+ */
16102+
16103+/*
4a4d8108
AM
16104+ * inode operation (rename entry)
16105+ * todo: this is crazy monster
1facf9fc 16106+ */
16107+
16108+#include "aufs.h"
16109+
4a4d8108
AM
16110+enum { AuSRC, AuDST, AuSrcDst };
16111+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 16112+
4a4d8108
AM
16113+#define AuRen_ISDIR 1
16114+#define AuRen_ISSAMEDIR (1 << 1)
16115+#define AuRen_WHSRC (1 << 2)
16116+#define AuRen_WHDST (1 << 3)
16117+#define AuRen_MNT_WRITE (1 << 4)
16118+#define AuRen_DT_DSTDIR (1 << 5)
16119+#define AuRen_DIROPQ (1 << 6)
16120+#define AuRen_CPUP (1 << 7)
16121+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
16122+#define au_fset_ren(flags, name) \
16123+ do { (flags) |= AuRen_##name; } while (0)
16124+#define au_fclr_ren(flags, name) \
16125+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 16126+
4a4d8108
AM
16127+struct au_ren_args {
16128+ struct {
16129+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
16130+ *wh_dentry;
16131+ struct inode *dir, *inode;
16132+ struct au_hinode *hdir;
16133+ struct au_dtime dt[AuParentChild];
16134+ aufs_bindex_t bstart;
16135+ } sd[AuSrcDst];
1facf9fc 16136+
4a4d8108
AM
16137+#define src_dentry sd[AuSRC].dentry
16138+#define src_dir sd[AuSRC].dir
16139+#define src_inode sd[AuSRC].inode
16140+#define src_h_dentry sd[AuSRC].h_dentry
16141+#define src_parent sd[AuSRC].parent
16142+#define src_h_parent sd[AuSRC].h_parent
16143+#define src_wh_dentry sd[AuSRC].wh_dentry
16144+#define src_hdir sd[AuSRC].hdir
16145+#define src_h_dir sd[AuSRC].hdir->hi_inode
16146+#define src_dt sd[AuSRC].dt
16147+#define src_bstart sd[AuSRC].bstart
1facf9fc 16148+
4a4d8108
AM
16149+#define dst_dentry sd[AuDST].dentry
16150+#define dst_dir sd[AuDST].dir
16151+#define dst_inode sd[AuDST].inode
16152+#define dst_h_dentry sd[AuDST].h_dentry
16153+#define dst_parent sd[AuDST].parent
16154+#define dst_h_parent sd[AuDST].h_parent
16155+#define dst_wh_dentry sd[AuDST].wh_dentry
16156+#define dst_hdir sd[AuDST].hdir
16157+#define dst_h_dir sd[AuDST].hdir->hi_inode
16158+#define dst_dt sd[AuDST].dt
16159+#define dst_bstart sd[AuDST].bstart
16160+
16161+ struct dentry *h_trap;
16162+ struct au_branch *br;
16163+ struct au_hinode *src_hinode;
16164+ struct path h_path;
16165+ struct au_nhash whlist;
027c5e7a 16166+ aufs_bindex_t btgt, src_bwh, src_bdiropq;
1facf9fc 16167+
1308ab2a 16168+ unsigned int flags;
1facf9fc 16169+
4a4d8108
AM
16170+ struct au_whtmp_rmdir *thargs;
16171+ struct dentry *h_dst;
16172+};
1308ab2a 16173+
4a4d8108 16174+/* ---------------------------------------------------------------------- */
1308ab2a 16175+
4a4d8108
AM
16176+/*
16177+ * functions for reverting.
16178+ * when an error happened in a single rename systemcall, we should revert
16179+ * everything as if nothing happend.
16180+ * we don't need to revert the copied-up/down the parent dir since they are
16181+ * harmless.
16182+ */
1facf9fc 16183+
4a4d8108
AM
16184+#define RevertFailure(fmt, ...) do { \
16185+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
16186+ ##__VA_ARGS__, err, rerr); \
16187+ err = -EIO; \
16188+} while (0)
1facf9fc 16189+
4a4d8108 16190+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 16191+{
4a4d8108 16192+ int rerr;
1facf9fc 16193+
4a4d8108
AM
16194+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
16195+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
16196+ au_hn_imtx_unlock(a->src_hinode);
027c5e7a 16197+ au_set_dbdiropq(a->src_dentry, a->src_bdiropq);
4a4d8108
AM
16198+ if (rerr)
16199+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
16200+}
1facf9fc 16201+
4a4d8108
AM
16202+static void au_ren_rev_rename(int err, struct au_ren_args *a)
16203+{
16204+ int rerr;
1facf9fc 16205+
4a4d8108
AM
16206+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
16207+ a->br, /*nd*/NULL);
16208+ rerr = PTR_ERR(a->h_path.dentry);
16209+ if (IS_ERR(a->h_path.dentry)) {
16210+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
16211+ return;
1facf9fc 16212+ }
16213+
4a4d8108
AM
16214+ rerr = vfsub_rename(a->dst_h_dir,
16215+ au_h_dptr(a->src_dentry, a->btgt),
16216+ a->src_h_dir, &a->h_path);
16217+ d_drop(a->h_path.dentry);
16218+ dput(a->h_path.dentry);
16219+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
16220+ if (rerr)
16221+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 16222+}
16223+
4a4d8108 16224+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 16225+{
4a4d8108 16226+ int rerr;
1facf9fc 16227+
4a4d8108
AM
16228+ a->h_path.dentry = a->dst_h_dentry;
16229+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
16230+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
16231+ au_set_dbstart(a->src_dentry, a->src_bstart);
16232+ if (rerr)
16233+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 16234+}
16235+
4a4d8108 16236+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 16237+{
4a4d8108 16238+ int rerr;
dece6358 16239+
4a4d8108
AM
16240+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
16241+ a->br, /*nd*/NULL);
16242+ rerr = PTR_ERR(a->h_path.dentry);
16243+ if (IS_ERR(a->h_path.dentry)) {
16244+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
16245+ return;
16246+ }
16247+ if (a->h_path.dentry->d_inode) {
16248+ d_drop(a->h_path.dentry);
16249+ dput(a->h_path.dentry);
16250+ return;
dece6358
AM
16251+ }
16252+
4a4d8108
AM
16253+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
16254+ d_drop(a->h_path.dentry);
16255+ dput(a->h_path.dentry);
16256+ if (!rerr)
16257+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
16258+ else
16259+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
16260+}
1308ab2a 16261+
4a4d8108
AM
16262+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
16263+{
16264+ int rerr;
1308ab2a 16265+
4a4d8108
AM
16266+ a->h_path.dentry = a->src_wh_dentry;
16267+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 16268+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108
AM
16269+ if (rerr)
16270+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
16271+}
4a4d8108 16272+#undef RevertFailure
1facf9fc 16273+
1308ab2a 16274+/* ---------------------------------------------------------------------- */
16275+
4a4d8108
AM
16276+/*
16277+ * when we have to copyup the renaming entry, do it with the rename-target name
16278+ * in order to minimize the cost (the later actual rename is unnecessary).
16279+ * otherwise rename it on the target branch.
16280+ */
16281+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 16282+{
dece6358 16283+ int err;
4a4d8108 16284+ struct dentry *d;
1facf9fc 16285+
4a4d8108
AM
16286+ d = a->src_dentry;
16287+ if (au_dbstart(d) == a->btgt) {
16288+ a->h_path.dentry = a->dst_h_dentry;
16289+ if (au_ftest_ren(a->flags, DIROPQ)
16290+ && au_dbdiropq(d) == a->btgt)
16291+ au_fclr_ren(a->flags, DIROPQ);
16292+ AuDebugOn(au_dbstart(d) != a->btgt);
16293+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
16294+ a->dst_h_dir, &a->h_path);
16295+ } else {
16296+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
16297+ struct file *h_file;
1308ab2a 16298+
4a4d8108
AM
16299+ au_fset_ren(a->flags, CPUP);
16300+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16301+ au_set_dbstart(d, a->btgt);
16302+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
16303+ h_file = au_h_open_pre(d, a->src_bstart);
16304+ if (IS_ERR(h_file)) {
16305+ err = PTR_ERR(h_file);
16306+ h_file = NULL;
16307+ } else
16308+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
16309+ !AuCpup_DTIME, a->dst_parent);
16310+ mutex_unlock(h_mtx);
16311+ au_h_open_post(d, a->src_bstart, h_file);
16312+ if (!err) {
16313+ d = a->dst_dentry;
16314+ au_set_h_dptr(d, a->btgt, NULL);
16315+ au_update_dbstart(d);
16316+ } else {
16317+ au_set_h_dptr(d, a->btgt, NULL);
16318+ au_set_dbstart(d, a->src_bstart);
16319+ }
1308ab2a 16320+ }
027c5e7a
AM
16321+ if (!err && a->h_dst)
16322+ /* it will be set to dinfo later */
16323+ dget(a->h_dst);
1facf9fc 16324+
dece6358
AM
16325+ return err;
16326+}
1facf9fc 16327+
4a4d8108
AM
16328+/* cf. aufs_rmdir() */
16329+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 16330+{
4a4d8108
AM
16331+ int err;
16332+ struct inode *dir;
1facf9fc 16333+
4a4d8108
AM
16334+ dir = a->dst_dir;
16335+ SiMustAnyLock(dir->i_sb);
16336+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
16337+ au_sbi(dir->i_sb)->si_dirwh)
16338+ || au_test_fs_remote(a->h_dst->d_sb)) {
16339+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
16340+ if (unlikely(err))
16341+ pr_warning("failed removing whtmp dir %.*s (%d), "
16342+ "ignored.\n", AuDLNPair(a->h_dst), err);
16343+ } else {
16344+ au_nhash_wh_free(&a->thargs->whlist);
16345+ a->thargs->whlist = a->whlist;
16346+ a->whlist.nh_num = 0;
16347+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
16348+ dput(a->h_dst);
16349+ a->thargs = NULL;
16350+ }
16351+
16352+ return 0;
1308ab2a 16353+}
1facf9fc 16354+
4a4d8108
AM
16355+/* make it 'opaque' dir. */
16356+static int au_ren_diropq(struct au_ren_args *a)
16357+{
16358+ int err;
16359+ struct dentry *diropq;
1facf9fc 16360+
4a4d8108 16361+ err = 0;
027c5e7a 16362+ a->src_bdiropq = au_dbdiropq(a->src_dentry);
4a4d8108
AM
16363+ a->src_hinode = au_hi(a->src_inode, a->btgt);
16364+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
16365+ diropq = au_diropq_create(a->src_dentry, a->btgt);
16366+ au_hn_imtx_unlock(a->src_hinode);
16367+ if (IS_ERR(diropq))
16368+ err = PTR_ERR(diropq);
16369+ dput(diropq);
1facf9fc 16370+
4a4d8108
AM
16371+ return err;
16372+}
1facf9fc 16373+
4a4d8108
AM
16374+static int do_rename(struct au_ren_args *a)
16375+{
16376+ int err;
16377+ struct dentry *d, *h_d;
1facf9fc 16378+
4a4d8108
AM
16379+ /* prepare workqueue args for asynchronous rmdir */
16380+ h_d = a->dst_h_dentry;
16381+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
16382+ err = -ENOMEM;
16383+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
16384+ if (unlikely(!a->thargs))
16385+ goto out;
16386+ a->h_dst = dget(h_d);
16387+ }
1facf9fc 16388+
4a4d8108
AM
16389+ /* create whiteout for src_dentry */
16390+ if (au_ftest_ren(a->flags, WHSRC)) {
027c5e7a
AM
16391+ a->src_bwh = au_dbwh(a->src_dentry);
16392+ AuDebugOn(a->src_bwh >= 0);
4a4d8108
AM
16393+ a->src_wh_dentry
16394+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
16395+ err = PTR_ERR(a->src_wh_dentry);
16396+ if (IS_ERR(a->src_wh_dentry))
16397+ goto out_thargs;
16398+ }
1facf9fc 16399+
4a4d8108
AM
16400+ /* lookup whiteout for dentry */
16401+ if (au_ftest_ren(a->flags, WHDST)) {
16402+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
16403+ a->br);
16404+ err = PTR_ERR(h_d);
16405+ if (IS_ERR(h_d))
16406+ goto out_whsrc;
16407+ if (!h_d->d_inode)
16408+ dput(h_d);
16409+ else
16410+ a->dst_wh_dentry = h_d;
16411+ }
1facf9fc 16412+
4a4d8108
AM
16413+ /* rename dentry to tmpwh */
16414+ if (a->thargs) {
16415+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
16416+ if (unlikely(err))
16417+ goto out_whdst;
dece6358 16418+
4a4d8108
AM
16419+ d = a->dst_dentry;
16420+ au_set_h_dptr(d, a->btgt, NULL);
16421+ err = au_lkup_neg(d, a->btgt);
16422+ if (unlikely(err))
16423+ goto out_whtmp;
16424+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
16425+ }
1facf9fc 16426+
4a4d8108
AM
16427+ /* cpup src */
16428+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
16429+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
16430+ struct file *h_file;
1facf9fc 16431+
4a4d8108
AM
16432+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16433+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
16434+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
16435+ if (IS_ERR(h_file)) {
16436+ err = PTR_ERR(h_file);
16437+ h_file = NULL;
16438+ } else
16439+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
16440+ !AuCpup_DTIME);
16441+ mutex_unlock(h_mtx);
16442+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
16443+ if (unlikely(err))
16444+ goto out_whtmp;
16445+ }
1facf9fc 16446+
4a4d8108
AM
16447+ /* rename by vfs_rename or cpup */
16448+ d = a->dst_dentry;
16449+ if (au_ftest_ren(a->flags, ISDIR)
16450+ && (a->dst_wh_dentry
16451+ || au_dbdiropq(d) == a->btgt
16452+ /* hide the lower to keep xino */
16453+ || a->btgt < au_dbend(d)
16454+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
16455+ au_fset_ren(a->flags, DIROPQ);
16456+ err = au_ren_or_cpup(a);
16457+ if (unlikely(err))
16458+ /* leave the copied-up one */
16459+ goto out_whtmp;
1308ab2a 16460+
4a4d8108
AM
16461+ /* make dir opaque */
16462+ if (au_ftest_ren(a->flags, DIROPQ)) {
16463+ err = au_ren_diropq(a);
16464+ if (unlikely(err))
16465+ goto out_rename;
16466+ }
1308ab2a 16467+
4a4d8108
AM
16468+ /* update target timestamps */
16469+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
16470+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
16471+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
16472+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 16473+
4a4d8108
AM
16474+ /* remove whiteout for dentry */
16475+ if (a->dst_wh_dentry) {
16476+ a->h_path.dentry = a->dst_wh_dentry;
16477+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
16478+ a->dst_dentry);
16479+ if (unlikely(err))
16480+ goto out_diropq;
16481+ }
1facf9fc 16482+
4a4d8108
AM
16483+ /* remove whtmp */
16484+ if (a->thargs)
16485+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 16486+
4a4d8108
AM
16487+ err = 0;
16488+ goto out_success;
16489+
4f0767ce 16490+out_diropq:
4a4d8108
AM
16491+ if (au_ftest_ren(a->flags, DIROPQ))
16492+ au_ren_rev_diropq(err, a);
4f0767ce 16493+out_rename:
4a4d8108
AM
16494+ if (!au_ftest_ren(a->flags, CPUP))
16495+ au_ren_rev_rename(err, a);
16496+ else
16497+ au_ren_rev_cpup(err, a);
027c5e7a 16498+ dput(a->h_dst);
4f0767ce 16499+out_whtmp:
4a4d8108
AM
16500+ if (a->thargs)
16501+ au_ren_rev_whtmp(err, a);
4f0767ce 16502+out_whdst:
4a4d8108
AM
16503+ dput(a->dst_wh_dentry);
16504+ a->dst_wh_dentry = NULL;
4f0767ce 16505+out_whsrc:
4a4d8108
AM
16506+ if (a->src_wh_dentry)
16507+ au_ren_rev_whsrc(err, a);
4f0767ce 16508+out_success:
4a4d8108
AM
16509+ dput(a->src_wh_dentry);
16510+ dput(a->dst_wh_dentry);
4f0767ce 16511+out_thargs:
4a4d8108
AM
16512+ if (a->thargs) {
16513+ dput(a->h_dst);
16514+ au_whtmp_rmdir_free(a->thargs);
16515+ a->thargs = NULL;
16516+ }
4f0767ce 16517+out:
4a4d8108 16518+ return err;
dece6358 16519+}
1facf9fc 16520+
1308ab2a 16521+/* ---------------------------------------------------------------------- */
1facf9fc 16522+
4a4d8108
AM
16523+/*
16524+ * test if @dentry dir can be rename destination or not.
16525+ * success means, it is a logically empty dir.
16526+ */
16527+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 16528+{
4a4d8108 16529+ return au_test_empty(dentry, whlist);
1308ab2a 16530+}
1facf9fc 16531+
4a4d8108
AM
16532+/*
16533+ * test if @dentry dir can be rename source or not.
16534+ * if it can, return 0 and @children is filled.
16535+ * success means,
16536+ * - it is a logically empty dir.
16537+ * - or, it exists on writable branch and has no children including whiteouts
16538+ * on the lower branch.
16539+ */
16540+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
16541+{
16542+ int err;
16543+ unsigned int rdhash;
16544+ aufs_bindex_t bstart;
1facf9fc 16545+
4a4d8108
AM
16546+ bstart = au_dbstart(dentry);
16547+ if (bstart != btgt) {
16548+ struct au_nhash whlist;
dece6358 16549+
4a4d8108
AM
16550+ SiMustAnyLock(dentry->d_sb);
16551+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
16552+ if (!rdhash)
16553+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
16554+ dentry));
16555+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
16556+ if (unlikely(err))
16557+ goto out;
16558+ err = au_test_empty(dentry, &whlist);
16559+ au_nhash_wh_free(&whlist);
16560+ goto out;
16561+ }
dece6358 16562+
4a4d8108
AM
16563+ if (bstart == au_dbtaildir(dentry))
16564+ return 0; /* success */
dece6358 16565+
4a4d8108 16566+ err = au_test_empty_lower(dentry);
1facf9fc 16567+
4f0767ce 16568+out:
4a4d8108
AM
16569+ if (err == -ENOTEMPTY) {
16570+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
16571+ " is not supported\n");
16572+ err = -EXDEV;
16573+ }
16574+ return err;
16575+}
1308ab2a 16576+
4a4d8108
AM
16577+/* side effect: sets whlist and h_dentry */
16578+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 16579+{
4a4d8108
AM
16580+ int err;
16581+ unsigned int rdhash;
16582+ struct dentry *d;
1facf9fc 16583+
4a4d8108
AM
16584+ d = a->dst_dentry;
16585+ SiMustAnyLock(d->d_sb);
1facf9fc 16586+
4a4d8108
AM
16587+ err = 0;
16588+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
16589+ rdhash = au_sbi(d->d_sb)->si_rdhash;
16590+ if (!rdhash)
16591+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
16592+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
16593+ if (unlikely(err))
16594+ goto out;
1308ab2a 16595+
4a4d8108
AM
16596+ au_set_dbstart(d, a->dst_bstart);
16597+ err = may_rename_dstdir(d, &a->whlist);
16598+ au_set_dbstart(d, a->btgt);
16599+ }
16600+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
16601+ if (unlikely(err))
16602+ goto out;
16603+
16604+ d = a->src_dentry;
16605+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
16606+ if (au_ftest_ren(a->flags, ISDIR)) {
16607+ err = may_rename_srcdir(d, a->btgt);
16608+ if (unlikely(err)) {
16609+ au_nhash_wh_free(&a->whlist);
16610+ a->whlist.nh_num = 0;
16611+ }
16612+ }
4f0767ce 16613+out:
4a4d8108 16614+ return err;
1facf9fc 16615+}
16616+
4a4d8108 16617+/* ---------------------------------------------------------------------- */
1facf9fc 16618+
4a4d8108
AM
16619+/*
16620+ * simple tests for rename.
16621+ * following the checks in vfs, plus the parent-child relationship.
16622+ */
16623+static int au_may_ren(struct au_ren_args *a)
16624+{
16625+ int err, isdir;
16626+ struct inode *h_inode;
1facf9fc 16627+
4a4d8108
AM
16628+ if (a->src_bstart == a->btgt) {
16629+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
16630+ au_ftest_ren(a->flags, ISDIR));
16631+ if (unlikely(err))
16632+ goto out;
16633+ err = -EINVAL;
16634+ if (unlikely(a->src_h_dentry == a->h_trap))
16635+ goto out;
16636+ }
1facf9fc 16637+
4a4d8108
AM
16638+ err = 0;
16639+ if (a->dst_bstart != a->btgt)
16640+ goto out;
1facf9fc 16641+
027c5e7a
AM
16642+ err = -ENOTEMPTY;
16643+ if (unlikely(a->dst_h_dentry == a->h_trap))
16644+ goto out;
16645+
4a4d8108
AM
16646+ err = -EIO;
16647+ h_inode = a->dst_h_dentry->d_inode;
16648+ isdir = !!au_ftest_ren(a->flags, ISDIR);
16649+ if (!a->dst_dentry->d_inode) {
16650+ if (unlikely(h_inode))
16651+ goto out;
16652+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
16653+ isdir);
16654+ } else {
16655+ if (unlikely(!h_inode || !h_inode->i_nlink))
16656+ goto out;
16657+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
16658+ isdir);
16659+ if (unlikely(err))
16660+ goto out;
4a4d8108 16661+ }
1facf9fc 16662+
4f0767ce 16663+out:
4a4d8108
AM
16664+ if (unlikely(err == -ENOENT || err == -EEXIST))
16665+ err = -EIO;
16666+ AuTraceErr(err);
16667+ return err;
16668+}
1facf9fc 16669+
1308ab2a 16670+/* ---------------------------------------------------------------------- */
1facf9fc 16671+
4a4d8108
AM
16672+/*
16673+ * locking order
16674+ * (VFS)
16675+ * - src_dir and dir by lock_rename()
16676+ * - inode if exitsts
16677+ * (aufs)
16678+ * - lock all
16679+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
16680+ * + si_read_lock
16681+ * + di_write_lock2_child()
16682+ * + di_write_lock_child()
16683+ * + ii_write_lock_child()
16684+ * + di_write_lock_child2()
16685+ * + ii_write_lock_child2()
16686+ * + src_parent and parent
16687+ * + di_write_lock_parent()
16688+ * + ii_write_lock_parent()
16689+ * + di_write_lock_parent2()
16690+ * + ii_write_lock_parent2()
16691+ * + lower src_dir and dir by vfsub_lock_rename()
16692+ * + verify the every relationships between child and parent. if any
16693+ * of them failed, unlock all and return -EBUSY.
16694+ */
16695+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 16696+{
4a4d8108
AM
16697+ struct super_block *sb;
16698+
16699+ sb = a->dst_dentry->d_sb;
16700+ if (au_ftest_ren(a->flags, MNT_WRITE))
16701+ mnt_drop_write(a->br->br_mnt);
16702+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
16703+ a->dst_h_parent, a->dst_hdir);
1308ab2a 16704+}
16705+
4a4d8108 16706+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 16707+{
4a4d8108
AM
16708+ int err;
16709+ unsigned int udba;
1308ab2a 16710+
4a4d8108
AM
16711+ err = 0;
16712+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
16713+ a->src_hdir = au_hi(a->src_dir, a->btgt);
16714+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
16715+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
16716+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
16717+ a->dst_h_parent, a->dst_hdir);
16718+ udba = au_opt_udba(a->src_dentry->d_sb);
16719+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
16720+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
16721+ err = au_busy_or_stale();
16722+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
16723+ err = au_h_verify(a->src_h_dentry, udba,
16724+ a->src_h_parent->d_inode, a->src_h_parent,
16725+ a->br);
16726+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
16727+ err = au_h_verify(a->dst_h_dentry, udba,
16728+ a->dst_h_parent->d_inode, a->dst_h_parent,
16729+ a->br);
16730+ if (!err) {
16731+ err = mnt_want_write(a->br->br_mnt);
16732+ if (unlikely(err))
16733+ goto out_unlock;
16734+ au_fset_ren(a->flags, MNT_WRITE);
16735+ goto out; /* success */
16736+ }
16737+
16738+ err = au_busy_or_stale();
16739+
4f0767ce 16740+out_unlock:
4a4d8108 16741+ au_ren_unlock(a);
4f0767ce 16742+out:
4a4d8108 16743+ return err;
1facf9fc 16744+}
16745+
16746+/* ---------------------------------------------------------------------- */
16747+
4a4d8108 16748+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 16749+{
4a4d8108 16750+ struct inode *dir;
dece6358 16751+
4a4d8108
AM
16752+ dir = a->dst_dir;
16753+ dir->i_version++;
16754+ if (au_ftest_ren(a->flags, ISDIR)) {
16755+ /* is this updating defined in POSIX? */
16756+ au_cpup_attr_timesizes(a->src_inode);
16757+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 16758+ }
027c5e7a 16759+
4a4d8108
AM
16760+ if (au_ibstart(dir) == a->btgt)
16761+ au_cpup_attr_timesizes(dir);
dece6358 16762+
4a4d8108
AM
16763+ if (au_ftest_ren(a->flags, ISSAMEDIR))
16764+ return;
dece6358 16765+
4a4d8108
AM
16766+ dir = a->src_dir;
16767+ dir->i_version++;
16768+ if (au_ftest_ren(a->flags, ISDIR))
16769+ au_cpup_attr_nlink(dir, /*force*/1);
16770+ if (au_ibstart(dir) == a->btgt)
16771+ au_cpup_attr_timesizes(dir);
1facf9fc 16772+}
16773+
4a4d8108 16774+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 16775+{
4a4d8108
AM
16776+ aufs_bindex_t bend, bindex;
16777+ struct dentry *d, *h_d;
16778+ struct inode *i, *h_i;
16779+ struct super_block *sb;
dece6358 16780+
027c5e7a
AM
16781+ d = a->dst_dentry;
16782+ d_drop(d);
16783+ if (a->h_dst)
16784+ /* already dget-ed by au_ren_or_cpup() */
16785+ au_set_h_dptr(d, a->btgt, a->h_dst);
16786+
16787+ i = a->dst_inode;
16788+ if (i) {
16789+ if (!au_ftest_ren(a->flags, ISDIR))
16790+ vfsub_drop_nlink(i);
16791+ else {
16792+ vfsub_dead_dir(i);
16793+ au_cpup_attr_timesizes(i);
16794+ }
16795+ au_update_dbrange(d, /*do_put_zero*/1);
16796+ } else {
16797+ bend = a->btgt;
16798+ for (bindex = au_dbstart(d); bindex < bend; bindex++)
16799+ au_set_h_dptr(d, bindex, NULL);
16800+ bend = au_dbend(d);
16801+ for (bindex = a->btgt + 1; bindex <= bend; bindex++)
16802+ au_set_h_dptr(d, bindex, NULL);
16803+ au_update_dbrange(d, /*do_put_zero*/0);
16804+ }
16805+
4a4d8108
AM
16806+ d = a->src_dentry;
16807+ au_set_dbwh(d, -1);
16808+ bend = au_dbend(d);
16809+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
16810+ h_d = au_h_dptr(d, bindex);
16811+ if (h_d)
16812+ au_set_h_dptr(d, bindex, NULL);
16813+ }
16814+ au_set_dbend(d, a->btgt);
16815+
16816+ sb = d->d_sb;
16817+ i = a->src_inode;
16818+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
16819+ return; /* success */
16820+
16821+ bend = au_ibend(i);
16822+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
16823+ h_i = au_h_iptr(i, bindex);
16824+ if (h_i) {
16825+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
16826+ /* ignore this error */
16827+ au_set_h_iptr(i, bindex, NULL, 0);
16828+ }
16829+ }
16830+ au_set_ibend(i, a->btgt);
1308ab2a 16831+}
dece6358 16832+
4a4d8108
AM
16833+/* ---------------------------------------------------------------------- */
16834+
16835+/* mainly for link(2) and rename(2) */
16836+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 16837+{
4a4d8108
AM
16838+ aufs_bindex_t bdiropq, bwh;
16839+ struct dentry *parent;
16840+ struct au_branch *br;
16841+
16842+ parent = dentry->d_parent;
16843+ IMustLock(parent->d_inode); /* dir is locked */
16844+
16845+ bdiropq = au_dbdiropq(parent);
16846+ bwh = au_dbwh(dentry);
16847+ br = au_sbr(dentry->d_sb, btgt);
16848+ if (au_br_rdonly(br)
16849+ || (0 <= bdiropq && bdiropq < btgt)
16850+ || (0 <= bwh && bwh < btgt))
16851+ btgt = -1;
16852+
16853+ AuDbg("btgt %d\n", btgt);
16854+ return btgt;
1facf9fc 16855+}
16856+
4a4d8108
AM
16857+/* sets src_bstart, dst_bstart and btgt */
16858+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 16859+{
4a4d8108
AM
16860+ int err;
16861+ struct au_wr_dir_args wr_dir_args = {
16862+ /* .force_btgt = -1, */
16863+ .flags = AuWrDir_ADD_ENTRY
16864+ };
dece6358 16865+
4a4d8108
AM
16866+ a->src_bstart = au_dbstart(a->src_dentry);
16867+ a->dst_bstart = au_dbstart(a->dst_dentry);
16868+ if (au_ftest_ren(a->flags, ISDIR))
16869+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16870+ wr_dir_args.force_btgt = a->src_bstart;
16871+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
16872+ wr_dir_args.force_btgt = a->dst_bstart;
16873+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
16874+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
16875+ a->btgt = err;
dece6358 16876+
4a4d8108 16877+ return err;
1facf9fc 16878+}
16879+
4a4d8108 16880+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 16881+{
4a4d8108
AM
16882+ a->h_path.dentry = a->src_h_parent;
16883+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
16884+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
16885+ a->h_path.dentry = a->dst_h_parent;
16886+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
16887+ }
1facf9fc 16888+
4a4d8108
AM
16889+ au_fclr_ren(a->flags, DT_DSTDIR);
16890+ if (!au_ftest_ren(a->flags, ISDIR))
16891+ return;
dece6358 16892+
4a4d8108
AM
16893+ a->h_path.dentry = a->src_h_dentry;
16894+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
16895+ if (a->dst_h_dentry->d_inode) {
16896+ au_fset_ren(a->flags, DT_DSTDIR);
16897+ a->h_path.dentry = a->dst_h_dentry;
16898+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
16899+ }
1308ab2a 16900+}
dece6358 16901+
4a4d8108 16902+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 16903+{
4a4d8108
AM
16904+ struct dentry *h_d;
16905+ struct mutex *h_mtx;
16906+
16907+ au_dtime_revert(a->src_dt + AuPARENT);
16908+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
16909+ au_dtime_revert(a->dst_dt + AuPARENT);
16910+
16911+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
16912+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
16913+ h_mtx = &h_d->d_inode->i_mutex;
16914+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16915+ au_dtime_revert(a->src_dt + AuCHILD);
16916+ mutex_unlock(h_mtx);
16917+
16918+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
16919+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
16920+ h_mtx = &h_d->d_inode->i_mutex;
16921+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16922+ au_dtime_revert(a->dst_dt + AuCHILD);
16923+ mutex_unlock(h_mtx);
1facf9fc 16924+ }
16925+ }
16926+}
16927+
4a4d8108
AM
16928+/* ---------------------------------------------------------------------- */
16929+
16930+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
16931+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 16932+{
e49829fe 16933+ int err, flags;
4a4d8108
AM
16934+ /* reduce stack space */
16935+ struct au_ren_args *a;
16936+
16937+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
16938+ IMustLock(_src_dir);
16939+ IMustLock(_dst_dir);
16940+
16941+ err = -ENOMEM;
16942+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
16943+ a = kzalloc(sizeof(*a), GFP_NOFS);
16944+ if (unlikely(!a))
16945+ goto out;
16946+
16947+ a->src_dir = _src_dir;
16948+ a->src_dentry = _src_dentry;
16949+ a->src_inode = a->src_dentry->d_inode;
16950+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
16951+ a->dst_dir = _dst_dir;
16952+ a->dst_dentry = _dst_dentry;
16953+ a->dst_inode = a->dst_dentry->d_inode;
16954+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
16955+ if (a->dst_inode) {
16956+ IMustLock(a->dst_inode);
16957+ au_igrab(a->dst_inode);
1facf9fc 16958+ }
1facf9fc 16959+
4a4d8108 16960+ err = -ENOTDIR;
027c5e7a 16961+ flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
4a4d8108
AM
16962+ if (S_ISDIR(a->src_inode->i_mode)) {
16963+ au_fset_ren(a->flags, ISDIR);
16964+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
16965+ goto out_free;
e49829fe
JR
16966+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16967+ AuLock_DIR | flags);
4a4d8108 16968+ } else
e49829fe
JR
16969+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16970+ flags);
16971+ if (unlikely(err))
16972+ goto out_free;
1facf9fc 16973+
027c5e7a
AM
16974+ err = au_d_hashed_positive(a->src_dentry);
16975+ if (unlikely(err))
16976+ goto out_unlock;
16977+ err = -ENOENT;
16978+ if (a->dst_inode) {
16979+ /*
16980+ * If it is a dir, VFS unhash dst_dentry before this
16981+ * function. It means we cannot rely upon d_unhashed().
16982+ */
16983+ if (unlikely(!a->dst_inode->i_nlink))
16984+ goto out_unlock;
16985+ if (!S_ISDIR(a->dst_inode->i_mode)) {
16986+ err = au_d_hashed_positive(a->dst_dentry);
16987+ if (unlikely(err))
16988+ goto out_unlock;
16989+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
16990+ goto out_unlock;
16991+ } else if (unlikely(d_unhashed(a->dst_dentry)))
16992+ goto out_unlock;
16993+
4a4d8108
AM
16994+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
16995+ di_write_lock_parent(a->dst_parent);
1facf9fc 16996+
4a4d8108
AM
16997+ /* which branch we process */
16998+ err = au_ren_wbr(a);
16999+ if (unlikely(err < 0))
027c5e7a 17000+ goto out_parent;
4a4d8108
AM
17001+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
17002+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 17003+
4a4d8108
AM
17004+ /* are they available to be renamed */
17005+ err = au_ren_may_dir(a);
17006+ if (unlikely(err))
17007+ goto out_children;
1facf9fc 17008+
4a4d8108
AM
17009+ /* prepare the writable parent dir on the same branch */
17010+ if (a->dst_bstart == a->btgt) {
17011+ au_fset_ren(a->flags, WHDST);
17012+ } else {
17013+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
17014+ if (unlikely(err))
17015+ goto out_children;
17016+ }
1facf9fc 17017+
4a4d8108
AM
17018+ if (a->src_dir != a->dst_dir) {
17019+ /*
17020+ * this temporary unlock is safe,
17021+ * because both dir->i_mutex are locked.
17022+ */
17023+ di_write_unlock(a->dst_parent);
17024+ di_write_lock_parent(a->src_parent);
17025+ err = au_wr_dir_need_wh(a->src_dentry,
17026+ au_ftest_ren(a->flags, ISDIR),
17027+ &a->btgt);
17028+ di_write_unlock(a->src_parent);
17029+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
17030+ au_fclr_ren(a->flags, ISSAMEDIR);
17031+ } else
17032+ err = au_wr_dir_need_wh(a->src_dentry,
17033+ au_ftest_ren(a->flags, ISDIR),
17034+ &a->btgt);
17035+ if (unlikely(err < 0))
17036+ goto out_children;
17037+ if (err)
17038+ au_fset_ren(a->flags, WHSRC);
1facf9fc 17039+
4a4d8108
AM
17040+ /* lock them all */
17041+ err = au_ren_lock(a);
17042+ if (unlikely(err))
17043+ goto out_children;
1facf9fc 17044+
4a4d8108
AM
17045+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
17046+ err = au_may_ren(a);
17047+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
17048+ err = -ENAMETOOLONG;
17049+ if (unlikely(err))
17050+ goto out_hdir;
1facf9fc 17051+
4a4d8108
AM
17052+ /* store timestamps to be revertible */
17053+ au_ren_dt(a);
1facf9fc 17054+
4a4d8108
AM
17055+ /* here we go */
17056+ err = do_rename(a);
17057+ if (unlikely(err))
17058+ goto out_dt;
17059+
17060+ /* update dir attributes */
17061+ au_ren_refresh_dir(a);
17062+
17063+ /* dput/iput all lower dentries */
17064+ au_ren_refresh(a);
17065+
17066+ goto out_hdir; /* success */
17067+
4f0767ce 17068+out_dt:
4a4d8108 17069+ au_ren_rev_dt(err, a);
4f0767ce 17070+out_hdir:
4a4d8108 17071+ au_ren_unlock(a);
4f0767ce 17072+out_children:
4a4d8108 17073+ au_nhash_wh_free(&a->whlist);
027c5e7a
AM
17074+ if (err && a->dst_inode && a->dst_bstart != a->btgt) {
17075+ AuDbg("bstart %d, btgt %d\n", a->dst_bstart, a->btgt);
17076+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
17077+ au_set_dbstart(a->dst_dentry, a->dst_bstart);
4a4d8108 17078+ }
027c5e7a 17079+out_parent:
4a4d8108
AM
17080+ if (!err)
17081+ d_move(a->src_dentry, a->dst_dentry);
027c5e7a
AM
17082+ else {
17083+ au_update_dbstart(a->dst_dentry);
17084+ if (!a->dst_inode)
17085+ d_drop(a->dst_dentry);
17086+ }
4a4d8108
AM
17087+ if (au_ftest_ren(a->flags, ISSAMEDIR))
17088+ di_write_unlock(a->dst_parent);
17089+ else
17090+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 17091+out_unlock:
4a4d8108 17092+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 17093+out_free:
4a4d8108
AM
17094+ iput(a->dst_inode);
17095+ if (a->thargs)
17096+ au_whtmp_rmdir_free(a->thargs);
17097+ kfree(a);
4f0767ce 17098+out:
4a4d8108
AM
17099+ AuTraceErr(err);
17100+ return err;
1308ab2a 17101+}
7f207e10
AM
17102diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
17103--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
027c5e7a 17104+++ linux/fs/aufs/Kconfig 2011-03-21 20:22:06.850601942 +0100
7f207e10 17105@@ -0,0 +1,180 @@
4a4d8108
AM
17106+config AUFS_FS
17107+ tristate "Aufs (Advanced multi layered unification filesystem) support"
17108+ depends on EXPERIMENTAL
17109+ help
17110+ Aufs is a stackable unification filesystem such as Unionfs,
17111+ which unifies several directories and provides a merged single
17112+ directory.
17113+ In the early days, aufs was entirely re-designed and
17114+ re-implemented Unionfs Version 1.x series. Introducing many
17115+ original ideas, approaches and improvements, it becomes totally
17116+ different from Unionfs while keeping the basic features.
1facf9fc 17117+
4a4d8108
AM
17118+if AUFS_FS
17119+choice
17120+ prompt "Maximum number of branches"
17121+ default AUFS_BRANCH_MAX_127
17122+ help
17123+ Specifies the maximum number of branches (or member directories)
17124+ in a single aufs. The larger value consumes more system
17125+ resources and has a minor impact to performance.
17126+config AUFS_BRANCH_MAX_127
17127+ bool "127"
17128+ help
17129+ Specifies the maximum number of branches (or member directories)
17130+ in a single aufs. The larger value consumes more system
17131+ resources and has a minor impact to performance.
17132+config AUFS_BRANCH_MAX_511
17133+ bool "511"
17134+ help
17135+ Specifies the maximum number of branches (or member directories)
17136+ in a single aufs. The larger value consumes more system
17137+ resources and has a minor impact to performance.
17138+config AUFS_BRANCH_MAX_1023
17139+ bool "1023"
17140+ help
17141+ Specifies the maximum number of branches (or member directories)
17142+ in a single aufs. The larger value consumes more system
17143+ resources and has a minor impact to performance.
17144+config AUFS_BRANCH_MAX_32767
17145+ bool "32767"
17146+ help
17147+ Specifies the maximum number of branches (or member directories)
17148+ in a single aufs. The larger value consumes more system
17149+ resources and has a minor impact to performance.
17150+endchoice
1facf9fc 17151+
e49829fe
JR
17152+config AUFS_SBILIST
17153+ bool
17154+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
17155+ default y
17156+ help
17157+ Automatic configuration for internal use.
17158+ When aufs supports Magic SysRq or /proc, enabled automatically.
17159+
4a4d8108
AM
17160+config AUFS_HNOTIFY
17161+ bool "Detect direct branch access (bypassing aufs)"
17162+ help
17163+ If you want to modify files on branches directly, eg. bypassing aufs,
17164+ and want aufs to detect the changes of them fully, then enable this
17165+ option and use 'udba=notify' mount option.
7f207e10 17166+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
17167+ It will have a negative impact to the performance.
17168+ See detail in aufs.5.
dece6358 17169+
4a4d8108
AM
17170+choice
17171+ prompt "method" if AUFS_HNOTIFY
17172+ default AUFS_HFSNOTIFY
17173+config AUFS_HFSNOTIFY
17174+ bool "fsnotify"
17175+ select FSNOTIFY
4a4d8108 17176+endchoice
1facf9fc 17177+
4a4d8108
AM
17178+config AUFS_EXPORT
17179+ bool "NFS-exportable aufs"
17180+ depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
17181+ help
17182+ If you want to export your mounted aufs via NFS, then enable this
17183+ option. There are several requirements for this configuration.
17184+ See detail in aufs.5.
1facf9fc 17185+
4a4d8108
AM
17186+config AUFS_INO_T_64
17187+ bool
17188+ depends on AUFS_EXPORT
17189+ depends on 64BIT && !(ALPHA || S390)
17190+ default y
17191+ help
17192+ Automatic configuration for internal use.
17193+ /* typedef unsigned long/int __kernel_ino_t */
17194+ /* alpha and s390x are int */
1facf9fc 17195+
4a4d8108
AM
17196+config AUFS_RDU
17197+ bool "Readdir in userspace"
17198+ help
17199+ Aufs has two methods to provide a merged view for a directory,
17200+ by a user-space library and by kernel-space natively. The latter
17201+ is always enabled but sometimes large and slow.
17202+ If you enable this option, install the library in aufs2-util
17203+ package, and set some environment variables for your readdir(3),
17204+ then the work will be handled in user-space which generally
17205+ shows better performance in most cases.
17206+ See detail in aufs.5.
1facf9fc 17207+
4a4d8108
AM
17208+config AUFS_SP_IATTR
17209+ bool "Respect the attributes (mtime/ctime mainly) of special files"
17210+ help
17211+ When you write something to a special file, some attributes of it
17212+ (mtime/ctime mainly) may be updated. Generally such updates are
17213+ less important (actually some device drivers and NFS ignore
17214+ it). But some applications (such like test program) requires
17215+ such updates. If you need these updates, then enable this
17216+ configuration which introduces some overhead.
17217+ Currently this configuration handles FIFO only.
1facf9fc 17218+
4a4d8108
AM
17219+config AUFS_SHWH
17220+ bool "Show whiteouts"
17221+ help
17222+ If you want to make the whiteouts in aufs visible, then enable
17223+ this option and specify 'shwh' mount option. Although it may
17224+ sounds like philosophy or something, but in technically it
17225+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 17226+
4a4d8108
AM
17227+config AUFS_BR_RAMFS
17228+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
17229+ help
17230+ If you want to use ramfs as an aufs branch fs, then enable this
17231+ option. Generally tmpfs is recommended.
17232+ Aufs prohibited them to be a branch fs by default, because
17233+ initramfs becomes unusable after switch_root or something
17234+ generally. If you sets initramfs as an aufs branch and boot your
17235+ system by switch_root, you will meet a problem easily since the
17236+ files in initramfs may be inaccessible.
17237+ Unless you are going to use ramfs as an aufs branch fs without
17238+ switch_root or something, leave it N.
1facf9fc 17239+
4a4d8108
AM
17240+config AUFS_BR_FUSE
17241+ bool "Fuse fs as an aufs branch"
17242+ depends on FUSE_FS
17243+ select AUFS_POLL
17244+ help
17245+ If you want to use fuse-based userspace filesystem as an aufs
17246+ branch fs, then enable this option.
17247+ It implements the internal poll(2) operation which is
17248+ implemented by fuse only (curretnly).
1facf9fc 17249+
4a4d8108
AM
17250+config AUFS_POLL
17251+ bool
17252+ help
17253+ Automatic configuration for internal use.
1facf9fc 17254+
4a4d8108
AM
17255+config AUFS_BR_HFSPLUS
17256+ bool "Hfsplus as an aufs branch"
17257+ depends on HFSPLUS_FS
17258+ default y
17259+ help
17260+ If you want to use hfsplus fs as an aufs branch fs, then enable
17261+ this option. This option introduces a small overhead at
17262+ copying-up a file on hfsplus.
1facf9fc 17263+
4a4d8108
AM
17264+config AUFS_BDEV_LOOP
17265+ bool
17266+ depends on BLK_DEV_LOOP
17267+ default y
17268+ help
17269+ Automatic configuration for internal use.
17270+ Convert =[ym] into =y.
1308ab2a 17271+
4a4d8108
AM
17272+config AUFS_DEBUG
17273+ bool "Debug aufs"
17274+ help
17275+ Enable this to compile aufs internal debug code.
17276+ It will have a negative impact to the performance.
17277+
17278+config AUFS_MAGIC_SYSRQ
17279+ bool
17280+ depends on AUFS_DEBUG && MAGIC_SYSRQ
17281+ default y
17282+ help
17283+ Automatic configuration for internal use.
17284+ When aufs supports Magic SysRq, enabled automatically.
17285+endif
7f207e10
AM
17286diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
17287--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a 17288+++ linux/fs/aufs/loop.c 2011-03-21 20:22:06.857268914 +0100
b752ccd1 17289@@ -0,0 +1,63 @@
1facf9fc 17290+/*
027c5e7a 17291+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17292+ *
17293+ * This program, aufs is free software; you can redistribute it and/or modify
17294+ * it under the terms of the GNU General Public License as published by
17295+ * the Free Software Foundation; either version 2 of the License, or
17296+ * (at your option) any later version.
dece6358
AM
17297+ *
17298+ * This program is distributed in the hope that it will be useful,
17299+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17300+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17301+ * GNU General Public License for more details.
17302+ *
17303+ * You should have received a copy of the GNU General Public License
17304+ * along with this program; if not, write to the Free Software
17305+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17306+ */
17307+
17308+/*
17309+ * support for loopback block device as a branch
17310+ */
17311+
17312+#include <linux/loop.h>
17313+#include "aufs.h"
17314+
17315+/*
17316+ * test if two lower dentries have overlapping branches.
17317+ */
b752ccd1 17318+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 17319+{
b752ccd1 17320+ struct super_block *h_sb;
1facf9fc 17321+ struct loop_device *l;
17322+
b752ccd1
AM
17323+ h_sb = h_adding->d_sb;
17324+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 17325+ return 0;
17326+
b752ccd1
AM
17327+ l = h_sb->s_bdev->bd_disk->private_data;
17328+ h_adding = l->lo_backing_file->f_dentry;
17329+ /*
17330+ * h_adding can be local NFS.
17331+ * in this case aufs cannot detect the loop.
17332+ */
17333+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 17334+ return 1;
b752ccd1 17335+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 17336+}
17337+
17338+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
17339+int au_test_loopback_kthread(void)
17340+{
b752ccd1
AM
17341+ int ret;
17342+ struct task_struct *tsk = current;
17343+
17344+ ret = 0;
17345+ if (tsk->flags & PF_KTHREAD) {
17346+ const char c = tsk->comm[4];
17347+ ret = ('0' <= c && c <= '9'
17348+ && !strncmp(tsk->comm, "loop", 4));
17349+ }
1facf9fc 17350+
b752ccd1 17351+ return ret;
1facf9fc 17352+}
7f207e10
AM
17353diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
17354--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 17355+++ linux/fs/aufs/loop.h 2011-03-21 20:22:06.857268914 +0100
b752ccd1 17356@@ -0,0 +1,42 @@
1facf9fc 17357+/*
027c5e7a 17358+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17359+ *
17360+ * This program, aufs is free software; you can redistribute it and/or modify
17361+ * it under the terms of the GNU General Public License as published by
17362+ * the Free Software Foundation; either version 2 of the License, or
17363+ * (at your option) any later version.
dece6358
AM
17364+ *
17365+ * This program is distributed in the hope that it will be useful,
17366+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17367+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17368+ * GNU General Public License for more details.
17369+ *
17370+ * You should have received a copy of the GNU General Public License
17371+ * along with this program; if not, write to the Free Software
17372+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17373+ */
17374+
17375+/*
17376+ * support for loopback mount as a branch
17377+ */
17378+
17379+#ifndef __AUFS_LOOP_H__
17380+#define __AUFS_LOOP_H__
17381+
17382+#ifdef __KERNEL__
17383+
dece6358
AM
17384+struct dentry;
17385+struct super_block;
1facf9fc 17386+
17387+#ifdef CONFIG_AUFS_BDEV_LOOP
17388+/* loop.c */
b752ccd1 17389+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 17390+int au_test_loopback_kthread(void);
17391+#else
4a4d8108 17392+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 17393+ struct dentry *h_adding)
4a4d8108 17394+AuStubInt0(au_test_loopback_kthread, void)
1facf9fc 17395+#endif /* BLK_DEV_LOOP */
17396+
17397+#endif /* __KERNEL__ */
17398+#endif /* __AUFS_LOOP_H__ */
7f207e10
AM
17399diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
17400--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
027c5e7a 17401+++ linux/fs/aufs/magic.mk 2011-03-21 20:22:06.857268914 +0100
4a4d8108 17402@@ -0,0 +1,54 @@
1facf9fc 17403+
17404+# defined in ${srctree}/fs/fuse/inode.c
17405+# tristate
17406+ifdef CONFIG_FUSE_FS
17407+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
17408+endif
17409+
17410+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
17411+# tristate
17412+ifdef CONFIG_OCFS2_FS
17413+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
17414+endif
17415+
17416+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
17417+# tristate
17418+ifdef CONFIG_OCFS2_FS_O2CB
17419+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
17420+endif
17421+
1facf9fc 17422+# defined in ${srctree}/fs/cifs/cifsfs.c
17423+# tristate
17424+ifdef CONFIG_CIFS_FS
17425+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
17426+endif
17427+
17428+# defined in ${srctree}/fs/xfs/xfs_sb.h
17429+# tristate
17430+ifdef CONFIG_XFS_FS
17431+ccflags-y += -DXFS_SB_MAGIC=0x58465342
17432+endif
17433+
17434+# defined in ${srctree}/fs/configfs/mount.c
17435+# tristate
17436+ifdef CONFIG_CONFIGFS_FS
17437+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
17438+endif
17439+
17440+# defined in ${srctree}/fs/9p/v9fs.h
17441+# tristate
17442+ifdef CONFIG_9P_FS
17443+ccflags-y += -DV9FS_MAGIC=0x01021997
17444+endif
17445+
17446+# defined in ${srctree}/fs/ubifs/ubifs.h
17447+# tristate
17448+ifdef CONFIG_UBIFS_FS
17449+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
17450+endif
4a4d8108
AM
17451+
17452+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
17453+# tristate
17454+ifdef CONFIG_HFSPLUS_FS
17455+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
17456+endif
7f207e10
AM
17457diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
17458--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
027c5e7a 17459+++ linux/fs/aufs/Makefile 2011-03-21 20:22:06.850601942 +0100
7f207e10 17460@@ -0,0 +1,38 @@
4a4d8108
AM
17461+
17462+include ${src}/magic.mk
17463+ifeq (${CONFIG_AUFS_FS},m)
17464+include ${src}/conf.mk
17465+endif
17466+-include ${src}/priv_def.mk
17467+
17468+# cf. include/linux/kernel.h
17469+# enable pr_debug
17470+ccflags-y += -DDEBUG
7f207e10
AM
17471+# sparse doesn't allow spaces
17472+ccflags-y += -D'pr_fmt(fmt)=AUFS_NAME"\040%s:%d:%s[%d]:\040"fmt,__func__,__LINE__,current->comm,current->pid'
4a4d8108
AM
17473+
17474+obj-$(CONFIG_AUFS_FS) += aufs.o
17475+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
17476+ wkq.o vfsub.o dcsub.o \
e49829fe 17477+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
17478+ dinfo.o dentry.o \
17479+ dynop.o \
17480+ finfo.o file.o f_op.o \
17481+ dir.o vdir.o \
17482+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
17483+ ioctl.o
17484+
17485+# all are boolean
e49829fe 17486+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
17487+aufs-$(CONFIG_SYSFS) += sysfs.o
17488+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
17489+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
17490+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
17491+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108
AM
17492+aufs-$(CONFIG_AUFS_EXPORT) += export.o
17493+aufs-$(CONFIG_AUFS_POLL) += poll.o
17494+aufs-$(CONFIG_AUFS_RDU) += rdu.o
17495+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
17496+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
17497+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
17498+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10
AM
17499diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
17500--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
17501+++ linux/fs/aufs/module.c 2011-03-21 20:22:06.857268914 +0100
17502@@ -0,0 +1,183 @@
1facf9fc 17503+/*
027c5e7a 17504+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17505+ *
17506+ * This program, aufs is free software; you can redistribute it and/or modify
17507+ * it under the terms of the GNU General Public License as published by
17508+ * the Free Software Foundation; either version 2 of the License, or
17509+ * (at your option) any later version.
dece6358
AM
17510+ *
17511+ * This program is distributed in the hope that it will be useful,
17512+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17513+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17514+ * GNU General Public License for more details.
17515+ *
17516+ * You should have received a copy of the GNU General Public License
17517+ * along with this program; if not, write to the Free Software
17518+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17519+ */
17520+
17521+/*
17522+ * module global variables and operations
17523+ */
17524+
17525+#include <linux/module.h>
17526+#include <linux/seq_file.h>
17527+#include "aufs.h"
17528+
17529+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
17530+{
17531+ if (new_sz <= nused)
17532+ return p;
17533+
17534+ p = krealloc(p, new_sz, gfp);
17535+ if (p)
17536+ memset(p + nused, 0, new_sz - nused);
17537+ return p;
17538+}
17539+
17540+/* ---------------------------------------------------------------------- */
17541+
17542+/*
17543+ * aufs caches
17544+ */
17545+struct kmem_cache *au_cachep[AuCache_Last];
17546+static int __init au_cache_init(void)
17547+{
4a4d8108 17548+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 17549+ if (au_cachep[AuCache_DINFO])
027c5e7a 17550+ /* SLAB_DESTROY_BY_RCU */
4a4d8108
AM
17551+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
17552+ au_icntnr_init_once);
1facf9fc 17553+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
17554+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
17555+ au_fi_init_once);
1facf9fc 17556+ if (au_cachep[AuCache_FINFO])
17557+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
17558+ if (au_cachep[AuCache_VDIR])
17559+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
17560+ if (au_cachep[AuCache_DEHSTR])
17561+ return 0;
17562+
17563+ return -ENOMEM;
17564+}
17565+
17566+static void au_cache_fin(void)
17567+{
17568+ int i;
4a4d8108
AM
17569+
17570+ /* including AuCache_HNOTIFY */
1facf9fc 17571+ for (i = 0; i < AuCache_Last; i++)
17572+ if (au_cachep[i]) {
17573+ kmem_cache_destroy(au_cachep[i]);
17574+ au_cachep[i] = NULL;
17575+ }
17576+}
17577+
17578+/* ---------------------------------------------------------------------- */
17579+
17580+int au_dir_roflags;
17581+
e49829fe
JR
17582+#ifdef CONFIG_AUFS_SBILIST
17583+struct au_splhead au_sbilist;
17584+#endif
17585+
1facf9fc 17586+/*
17587+ * functions for module interface.
17588+ */
17589+MODULE_LICENSE("GPL");
17590+/* MODULE_LICENSE("GPL v2"); */
dece6358 17591+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 17592+MODULE_DESCRIPTION(AUFS_NAME
17593+ " -- Advanced multi layered unification filesystem");
17594+MODULE_VERSION(AUFS_VERSION);
17595+
1facf9fc 17596+/* this module parameter has no meaning when SYSFS is disabled */
17597+int sysaufs_brs = 1;
17598+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
17599+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
17600+
17601+/* ---------------------------------------------------------------------- */
17602+
17603+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
17604+
17605+int au_seq_path(struct seq_file *seq, struct path *path)
17606+{
17607+ return seq_path(seq, path, au_esc_chars);
17608+}
17609+
17610+/* ---------------------------------------------------------------------- */
17611+
17612+static int __init aufs_init(void)
17613+{
17614+ int err, i;
17615+ char *p;
17616+
17617+ p = au_esc_chars;
17618+ for (i = 1; i <= ' '; i++)
17619+ *p++ = i;
17620+ *p++ = '\\';
17621+ *p++ = '\x7f';
17622+ *p = 0;
17623+
17624+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
17625+
e49829fe 17626+ au_sbilist_init();
1facf9fc 17627+ sysaufs_brs_init();
17628+ au_debug_init();
4a4d8108 17629+ au_dy_init();
1facf9fc 17630+ err = sysaufs_init();
17631+ if (unlikely(err))
17632+ goto out;
e49829fe 17633+ err = au_procfs_init();
4f0767ce 17634+ if (unlikely(err))
953406b4 17635+ goto out_sysaufs;
e49829fe
JR
17636+ err = au_wkq_init();
17637+ if (unlikely(err))
17638+ goto out_procfs;
4a4d8108 17639+ err = au_hnotify_init();
1facf9fc 17640+ if (unlikely(err))
17641+ goto out_wkq;
17642+ err = au_sysrq_init();
17643+ if (unlikely(err))
17644+ goto out_hin;
17645+ err = au_cache_init();
17646+ if (unlikely(err))
17647+ goto out_sysrq;
17648+ err = register_filesystem(&aufs_fs_type);
17649+ if (unlikely(err))
17650+ goto out_cache;
4a4d8108
AM
17651+ /* since we define pr_fmt, call printk directly */
17652+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 17653+ goto out; /* success */
17654+
4f0767ce 17655+out_cache:
1facf9fc 17656+ au_cache_fin();
4f0767ce 17657+out_sysrq:
1facf9fc 17658+ au_sysrq_fin();
4f0767ce 17659+out_hin:
4a4d8108 17660+ au_hnotify_fin();
4f0767ce 17661+out_wkq:
1facf9fc 17662+ au_wkq_fin();
e49829fe
JR
17663+out_procfs:
17664+ au_procfs_fin();
4f0767ce 17665+out_sysaufs:
1facf9fc 17666+ sysaufs_fin();
4a4d8108 17667+ au_dy_fin();
4f0767ce 17668+out:
1facf9fc 17669+ return err;
17670+}
17671+
17672+static void __exit aufs_exit(void)
17673+{
17674+ unregister_filesystem(&aufs_fs_type);
17675+ au_cache_fin();
17676+ au_sysrq_fin();
4a4d8108 17677+ au_hnotify_fin();
1facf9fc 17678+ au_wkq_fin();
e49829fe 17679+ au_procfs_fin();
1facf9fc 17680+ sysaufs_fin();
4a4d8108 17681+ au_dy_fin();
1facf9fc 17682+}
17683+
17684+module_init(aufs_init);
17685+module_exit(aufs_exit);
7f207e10
AM
17686diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
17687--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 17688+++ linux/fs/aufs/module.h 2011-03-21 20:22:06.857268914 +0100
e49829fe 17689@@ -0,0 +1,91 @@
1facf9fc 17690+/*
027c5e7a 17691+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17692+ *
17693+ * This program, aufs is free software; you can redistribute it and/or modify
17694+ * it under the terms of the GNU General Public License as published by
17695+ * the Free Software Foundation; either version 2 of the License, or
17696+ * (at your option) any later version.
dece6358
AM
17697+ *
17698+ * This program is distributed in the hope that it will be useful,
17699+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17700+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17701+ * GNU General Public License for more details.
17702+ *
17703+ * You should have received a copy of the GNU General Public License
17704+ * along with this program; if not, write to the Free Software
17705+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17706+ */
17707+
17708+/*
17709+ * module initialization and module-global
17710+ */
17711+
17712+#ifndef __AUFS_MODULE_H__
17713+#define __AUFS_MODULE_H__
17714+
17715+#ifdef __KERNEL__
17716+
17717+#include <linux/slab.h>
17718+
dece6358
AM
17719+struct path;
17720+struct seq_file;
17721+
1facf9fc 17722+/* module parameters */
1facf9fc 17723+extern int sysaufs_brs;
17724+
17725+/* ---------------------------------------------------------------------- */
17726+
17727+extern int au_dir_roflags;
17728+
17729+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
17730+int au_seq_path(struct seq_file *seq, struct path *path);
17731+
e49829fe
JR
17732+#ifdef CONFIG_PROC_FS
17733+/* procfs.c */
17734+int __init au_procfs_init(void);
17735+void au_procfs_fin(void);
17736+#else
17737+AuStubInt0(au_procfs_init, void);
17738+AuStubVoid(au_procfs_fin, void);
17739+#endif
17740+
4f0767ce
JR
17741+/* ---------------------------------------------------------------------- */
17742+
17743+/* kmem cache */
1facf9fc 17744+enum {
17745+ AuCache_DINFO,
17746+ AuCache_ICNTNR,
17747+ AuCache_FINFO,
17748+ AuCache_VDIR,
17749+ AuCache_DEHSTR,
4a4d8108
AM
17750+#ifdef CONFIG_AUFS_HNOTIFY
17751+ AuCache_HNOTIFY,
1facf9fc 17752+#endif
17753+ AuCache_Last
17754+};
17755+
4a4d8108
AM
17756+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
17757+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
17758+#define AuCacheCtor(type, ctor) \
17759+ kmem_cache_create(#type, sizeof(struct type), \
17760+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 17761+
17762+extern struct kmem_cache *au_cachep[];
17763+
17764+#define AuCacheFuncs(name, index) \
4a4d8108 17765+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 17766+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 17767+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 17768+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
17769+
17770+AuCacheFuncs(dinfo, DINFO);
17771+AuCacheFuncs(icntnr, ICNTNR);
17772+AuCacheFuncs(finfo, FINFO);
17773+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
17774+AuCacheFuncs(vdir_dehstr, DEHSTR);
17775+#ifdef CONFIG_AUFS_HNOTIFY
17776+AuCacheFuncs(hnotify, HNOTIFY);
17777+#endif
1facf9fc 17778+
4a4d8108
AM
17779+#endif /* __KERNEL__ */
17780+#endif /* __AUFS_MODULE_H__ */
7f207e10
AM
17781diff -urN /usr/share/empty/fs/aufs/mtx.h linux/fs/aufs/mtx.h
17782--- /usr/share/empty/fs/aufs/mtx.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 17783+++ linux/fs/aufs/mtx.h 2011-03-21 20:22:06.857268914 +0100
4a4d8108
AM
17784@@ -0,0 +1,48 @@
17785+/*
027c5e7a 17786+ * Copyright (C) 2010-2011 Junjiro R. Okajima
4a4d8108
AM
17787+ *
17788+ * This program, aufs is free software; you can redistribute it and/or modify
17789+ * it under the terms of the GNU General Public License as published by
17790+ * the Free Software Foundation; either version 2 of the License, or
17791+ * (at your option) any later version.
17792+ *
17793+ * This program is distributed in the hope that it will be useful,
17794+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17795+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17796+ * GNU General Public License for more details.
17797+ *
17798+ * You should have received a copy of the GNU General Public License
17799+ * along with this program; if not, write to the Free Software
17800+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17801+ */
17802+
17803+/*
17804+ * very ugly approach for aufs_mmap()
17805+ * never include this file from other than f_op.c.
17806+ * see f_op.c in detail.
17807+ */
17808+
17809+#ifndef __AUFS_MTX_H__
17810+#define __AUFS_MTX_H__
17811+
17812+#ifdef __KERNEL__
17813+
17814+/* copied from ../kernel/mutex{,-debug}.h */
17815+struct mutex;
17816+struct thread_info;
17817+#ifdef CONFIG_DEBUG_MUTEXES
17818+static inline void mutex_set_owner(struct mutex *lock)
17819+{
17820+ lock->owner = current_thread_info();
17821+}
17822+#else
17823+static inline void mutex_set_owner(struct mutex *lock)
17824+{
17825+#ifdef CONFIG_SMP
17826+ lock->owner = current_thread_info();
17827+#endif
17828+}
17829+#endif
1facf9fc 17830+
17831+#endif /* __KERNEL__ */
4a4d8108 17832+#endif /* __AUFS_MTX_H__ */
7f207e10
AM
17833diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
17834--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
17835+++ linux/fs/aufs/opts.c 2011-03-21 20:22:06.857268914 +0100
17836@@ -0,0 +1,1595 @@
1facf9fc 17837+/*
027c5e7a 17838+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17839+ *
17840+ * This program, aufs is free software; you can redistribute it and/or modify
17841+ * it under the terms of the GNU General Public License as published by
17842+ * the Free Software Foundation; either version 2 of the License, or
17843+ * (at your option) any later version.
dece6358
AM
17844+ *
17845+ * This program is distributed in the hope that it will be useful,
17846+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17847+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17848+ * GNU General Public License for more details.
17849+ *
17850+ * You should have received a copy of the GNU General Public License
17851+ * along with this program; if not, write to the Free Software
17852+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17853+ */
17854+
17855+/*
17856+ * mount options/flags
17857+ */
17858+
dece6358 17859+#include <linux/file.h>
e49829fe 17860+#include <linux/jiffies.h>
dece6358 17861+#include <linux/namei.h>
1facf9fc 17862+#include <linux/types.h> /* a distribution requires */
17863+#include <linux/parser.h>
17864+#include "aufs.h"
17865+
17866+/* ---------------------------------------------------------------------- */
17867+
17868+enum {
17869+ Opt_br,
17870+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
17871+ Opt_idel, Opt_imod, Opt_ireorder,
17872+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 17873+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 17874+ Opt_xino, Opt_zxino, Opt_noxino,
17875+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
17876+ Opt_trunc_xino_path, Opt_itrunc_xino,
17877+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 17878+ Opt_shwh, Opt_noshwh,
1facf9fc 17879+ Opt_plink, Opt_noplink, Opt_list_plink,
17880+ Opt_udba,
4a4d8108 17881+ Opt_dio, Opt_nodio,
1facf9fc 17882+ /* Opt_lock, Opt_unlock, */
17883+ Opt_cmd, Opt_cmd_args,
17884+ Opt_diropq_a, Opt_diropq_w,
17885+ Opt_warn_perm, Opt_nowarn_perm,
17886+ Opt_wbr_copyup, Opt_wbr_create,
17887+ Opt_refrof, Opt_norefrof,
17888+ Opt_verbose, Opt_noverbose,
17889+ Opt_sum, Opt_nosum, Opt_wsum,
17890+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
17891+};
17892+
17893+static match_table_t options = {
17894+ {Opt_br, "br=%s"},
17895+ {Opt_br, "br:%s"},
17896+
17897+ {Opt_add, "add=%d:%s"},
17898+ {Opt_add, "add:%d:%s"},
17899+ {Opt_add, "ins=%d:%s"},
17900+ {Opt_add, "ins:%d:%s"},
17901+ {Opt_append, "append=%s"},
17902+ {Opt_append, "append:%s"},
17903+ {Opt_prepend, "prepend=%s"},
17904+ {Opt_prepend, "prepend:%s"},
17905+
17906+ {Opt_del, "del=%s"},
17907+ {Opt_del, "del:%s"},
17908+ /* {Opt_idel, "idel:%d"}, */
17909+ {Opt_mod, "mod=%s"},
17910+ {Opt_mod, "mod:%s"},
17911+ /* {Opt_imod, "imod:%d:%s"}, */
17912+
17913+ {Opt_dirwh, "dirwh=%d"},
17914+
17915+ {Opt_xino, "xino=%s"},
17916+ {Opt_noxino, "noxino"},
17917+ {Opt_trunc_xino, "trunc_xino"},
17918+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
17919+ {Opt_notrunc_xino, "notrunc_xino"},
17920+ {Opt_trunc_xino_path, "trunc_xino=%s"},
17921+ {Opt_itrunc_xino, "itrunc_xino=%d"},
17922+ /* {Opt_zxino, "zxino=%s"}, */
17923+ {Opt_trunc_xib, "trunc_xib"},
17924+ {Opt_notrunc_xib, "notrunc_xib"},
17925+
e49829fe 17926+#ifdef CONFIG_PROC_FS
1facf9fc 17927+ {Opt_plink, "plink"},
e49829fe
JR
17928+#else
17929+ {Opt_ignore_silent, "plink"},
17930+#endif
17931+
1facf9fc 17932+ {Opt_noplink, "noplink"},
e49829fe 17933+
1facf9fc 17934+#ifdef CONFIG_AUFS_DEBUG
17935+ {Opt_list_plink, "list_plink"},
17936+#endif
17937+
17938+ {Opt_udba, "udba=%s"},
17939+
4a4d8108
AM
17940+ {Opt_dio, "dio"},
17941+ {Opt_nodio, "nodio"},
17942+
1facf9fc 17943+ {Opt_diropq_a, "diropq=always"},
17944+ {Opt_diropq_a, "diropq=a"},
17945+ {Opt_diropq_w, "diropq=whiteouted"},
17946+ {Opt_diropq_w, "diropq=w"},
17947+
17948+ {Opt_warn_perm, "warn_perm"},
17949+ {Opt_nowarn_perm, "nowarn_perm"},
17950+
17951+ /* keep them temporary */
17952+ {Opt_ignore_silent, "coo=%s"},
17953+ {Opt_ignore_silent, "nodlgt"},
17954+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 17955+ {Opt_ignore_silent, "clean_plink"},
17956+
dece6358
AM
17957+#ifdef CONFIG_AUFS_SHWH
17958+ {Opt_shwh, "shwh"},
17959+#endif
17960+ {Opt_noshwh, "noshwh"},
17961+
1facf9fc 17962+ {Opt_rendir, "rendir=%d"},
17963+
17964+ {Opt_refrof, "refrof"},
17965+ {Opt_norefrof, "norefrof"},
17966+
17967+ {Opt_verbose, "verbose"},
17968+ {Opt_verbose, "v"},
17969+ {Opt_noverbose, "noverbose"},
17970+ {Opt_noverbose, "quiet"},
17971+ {Opt_noverbose, "q"},
17972+ {Opt_noverbose, "silent"},
17973+
17974+ {Opt_sum, "sum"},
17975+ {Opt_nosum, "nosum"},
17976+ {Opt_wsum, "wsum"},
17977+
17978+ {Opt_rdcache, "rdcache=%d"},
17979+ {Opt_rdblk, "rdblk=%d"},
dece6358 17980+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 17981+ {Opt_rdhash, "rdhash=%d"},
dece6358 17982+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 17983+
17984+ {Opt_wbr_create, "create=%s"},
17985+ {Opt_wbr_create, "create_policy=%s"},
17986+ {Opt_wbr_copyup, "cpup=%s"},
17987+ {Opt_wbr_copyup, "copyup=%s"},
17988+ {Opt_wbr_copyup, "copyup_policy=%s"},
17989+
17990+ /* internal use for the scripts */
17991+ {Opt_ignore_silent, "si=%s"},
17992+
17993+ {Opt_br, "dirs=%s"},
17994+ {Opt_ignore, "debug=%d"},
17995+ {Opt_ignore, "delete=whiteout"},
17996+ {Opt_ignore, "delete=all"},
17997+ {Opt_ignore, "imap=%s"},
17998+
1308ab2a 17999+ /* temporary workaround, due to old mount(8)? */
18000+ {Opt_ignore_silent, "relatime"},
18001+
1facf9fc 18002+ {Opt_err, NULL}
18003+};
18004+
18005+/* ---------------------------------------------------------------------- */
18006+
18007+static const char *au_parser_pattern(int val, struct match_token *token)
18008+{
18009+ while (token->pattern) {
18010+ if (token->token == val)
18011+ return token->pattern;
18012+ token++;
18013+ }
18014+ BUG();
18015+ return "??";
18016+}
18017+
18018+/* ---------------------------------------------------------------------- */
18019+
18020+static match_table_t brperms = {
18021+ {AuBrPerm_RO, AUFS_BRPERM_RO},
18022+ {AuBrPerm_RR, AUFS_BRPERM_RR},
18023+ {AuBrPerm_RW, AUFS_BRPERM_RW},
18024+
18025+ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
18026+ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
18027+ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
18028+
18029+ {AuBrPerm_ROWH, "nfsro"},
18030+ {AuBrPerm_RO, NULL}
18031+};
18032+
4a4d8108 18033+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 18034+{
18035+ int val;
18036+ substring_t args[MAX_OPT_ARGS];
18037+
18038+ val = match_token(perm, brperms, args);
18039+ return val;
18040+}
18041+
18042+const char *au_optstr_br_perm(int brperm)
18043+{
18044+ return au_parser_pattern(brperm, (void *)brperms);
18045+}
18046+
18047+/* ---------------------------------------------------------------------- */
18048+
18049+static match_table_t udbalevel = {
18050+ {AuOpt_UDBA_REVAL, "reval"},
18051+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
18052+#ifdef CONFIG_AUFS_HNOTIFY
18053+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
18054+#ifdef CONFIG_AUFS_HFSNOTIFY
18055+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 18056+#endif
1facf9fc 18057+#endif
18058+ {-1, NULL}
18059+};
18060+
4a4d8108 18061+static int noinline_for_stack udba_val(char *str)
1facf9fc 18062+{
18063+ substring_t args[MAX_OPT_ARGS];
18064+
7f207e10 18065+ return match_token(str, udbalevel, args);
1facf9fc 18066+}
18067+
18068+const char *au_optstr_udba(int udba)
18069+{
18070+ return au_parser_pattern(udba, (void *)udbalevel);
18071+}
18072+
18073+/* ---------------------------------------------------------------------- */
18074+
18075+static match_table_t au_wbr_create_policy = {
18076+ {AuWbrCreate_TDP, "tdp"},
18077+ {AuWbrCreate_TDP, "top-down-parent"},
18078+ {AuWbrCreate_RR, "rr"},
18079+ {AuWbrCreate_RR, "round-robin"},
18080+ {AuWbrCreate_MFS, "mfs"},
18081+ {AuWbrCreate_MFS, "most-free-space"},
18082+ {AuWbrCreate_MFSV, "mfs:%d"},
18083+ {AuWbrCreate_MFSV, "most-free-space:%d"},
18084+
18085+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
18086+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
18087+ {AuWbrCreate_PMFS, "pmfs"},
18088+ {AuWbrCreate_PMFSV, "pmfs:%d"},
18089+
18090+ {-1, NULL}
18091+};
18092+
dece6358
AM
18093+/*
18094+ * cf. linux/lib/parser.c and cmdline.c
18095+ * gave up calling memparse() since it uses simple_strtoull() instead of
18096+ * strict_...().
18097+ */
4a4d8108
AM
18098+static int noinline_for_stack
18099+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 18100+{
18101+ int err;
18102+ unsigned int len;
18103+ char a[32];
18104+
18105+ err = -ERANGE;
18106+ len = s->to - s->from;
18107+ if (len + 1 <= sizeof(a)) {
18108+ memcpy(a, s->from, len);
18109+ a[len] = '\0';
18110+ err = strict_strtoull(a, 0, result);
18111+ }
18112+ return err;
18113+}
18114+
18115+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
18116+ struct au_opt_wbr_create *create)
18117+{
18118+ int err;
18119+ unsigned long long ull;
18120+
18121+ err = 0;
18122+ if (!au_match_ull(arg, &ull))
18123+ create->mfsrr_watermark = ull;
18124+ else {
4a4d8108 18125+ pr_err("bad integer in %s\n", str);
1facf9fc 18126+ err = -EINVAL;
18127+ }
18128+
18129+ return err;
18130+}
18131+
18132+static int au_wbr_mfs_sec(substring_t *arg, char *str,
18133+ struct au_opt_wbr_create *create)
18134+{
18135+ int n, err;
18136+
18137+ err = 0;
027c5e7a 18138+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 18139+ create->mfs_second = n;
18140+ else {
4a4d8108 18141+ pr_err("bad integer in %s\n", str);
1facf9fc 18142+ err = -EINVAL;
18143+ }
18144+
18145+ return err;
18146+}
18147+
4a4d8108
AM
18148+static int noinline_for_stack
18149+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 18150+{
18151+ int err, e;
18152+ substring_t args[MAX_OPT_ARGS];
18153+
18154+ err = match_token(str, au_wbr_create_policy, args);
18155+ create->wbr_create = err;
18156+ switch (err) {
18157+ case AuWbrCreate_MFSRRV:
18158+ e = au_wbr_mfs_wmark(&args[0], str, create);
18159+ if (!e)
18160+ e = au_wbr_mfs_sec(&args[1], str, create);
18161+ if (unlikely(e))
18162+ err = e;
18163+ break;
18164+ case AuWbrCreate_MFSRR:
18165+ e = au_wbr_mfs_wmark(&args[0], str, create);
18166+ if (unlikely(e)) {
18167+ err = e;
18168+ break;
18169+ }
18170+ /*FALLTHROUGH*/
18171+ case AuWbrCreate_MFS:
18172+ case AuWbrCreate_PMFS:
027c5e7a 18173+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 18174+ break;
18175+ case AuWbrCreate_MFSV:
18176+ case AuWbrCreate_PMFSV:
18177+ e = au_wbr_mfs_sec(&args[0], str, create);
18178+ if (unlikely(e))
18179+ err = e;
18180+ break;
18181+ }
18182+
18183+ return err;
18184+}
18185+
18186+const char *au_optstr_wbr_create(int wbr_create)
18187+{
18188+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
18189+}
18190+
18191+static match_table_t au_wbr_copyup_policy = {
18192+ {AuWbrCopyup_TDP, "tdp"},
18193+ {AuWbrCopyup_TDP, "top-down-parent"},
18194+ {AuWbrCopyup_BUP, "bup"},
18195+ {AuWbrCopyup_BUP, "bottom-up-parent"},
18196+ {AuWbrCopyup_BU, "bu"},
18197+ {AuWbrCopyup_BU, "bottom-up"},
18198+ {-1, NULL}
18199+};
18200+
4a4d8108 18201+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 18202+{
18203+ substring_t args[MAX_OPT_ARGS];
18204+
18205+ return match_token(str, au_wbr_copyup_policy, args);
18206+}
18207+
18208+const char *au_optstr_wbr_copyup(int wbr_copyup)
18209+{
18210+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
18211+}
18212+
18213+/* ---------------------------------------------------------------------- */
18214+
18215+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
18216+
18217+static void dump_opts(struct au_opts *opts)
18218+{
18219+#ifdef CONFIG_AUFS_DEBUG
18220+ /* reduce stack space */
18221+ union {
18222+ struct au_opt_add *add;
18223+ struct au_opt_del *del;
18224+ struct au_opt_mod *mod;
18225+ struct au_opt_xino *xino;
18226+ struct au_opt_xino_itrunc *xino_itrunc;
18227+ struct au_opt_wbr_create *create;
18228+ } u;
18229+ struct au_opt *opt;
18230+
18231+ opt = opts->opt;
18232+ while (opt->type != Opt_tail) {
18233+ switch (opt->type) {
18234+ case Opt_add:
18235+ u.add = &opt->add;
18236+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
18237+ u.add->bindex, u.add->pathname, u.add->perm,
18238+ u.add->path.dentry);
18239+ break;
18240+ case Opt_del:
18241+ case Opt_idel:
18242+ u.del = &opt->del;
18243+ AuDbg("del {%s, %p}\n",
18244+ u.del->pathname, u.del->h_path.dentry);
18245+ break;
18246+ case Opt_mod:
18247+ case Opt_imod:
18248+ u.mod = &opt->mod;
18249+ AuDbg("mod {%s, 0x%x, %p}\n",
18250+ u.mod->path, u.mod->perm, u.mod->h_root);
18251+ break;
18252+ case Opt_append:
18253+ u.add = &opt->add;
18254+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
18255+ u.add->bindex, u.add->pathname, u.add->perm,
18256+ u.add->path.dentry);
18257+ break;
18258+ case Opt_prepend:
18259+ u.add = &opt->add;
18260+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
18261+ u.add->bindex, u.add->pathname, u.add->perm,
18262+ u.add->path.dentry);
18263+ break;
18264+ case Opt_dirwh:
18265+ AuDbg("dirwh %d\n", opt->dirwh);
18266+ break;
18267+ case Opt_rdcache:
18268+ AuDbg("rdcache %d\n", opt->rdcache);
18269+ break;
18270+ case Opt_rdblk:
18271+ AuDbg("rdblk %u\n", opt->rdblk);
18272+ break;
dece6358
AM
18273+ case Opt_rdblk_def:
18274+ AuDbg("rdblk_def\n");
18275+ break;
1facf9fc 18276+ case Opt_rdhash:
18277+ AuDbg("rdhash %u\n", opt->rdhash);
18278+ break;
dece6358
AM
18279+ case Opt_rdhash_def:
18280+ AuDbg("rdhash_def\n");
18281+ break;
1facf9fc 18282+ case Opt_xino:
18283+ u.xino = &opt->xino;
18284+ AuDbg("xino {%s %.*s}\n",
18285+ u.xino->path,
18286+ AuDLNPair(u.xino->file->f_dentry));
18287+ break;
18288+ case Opt_trunc_xino:
18289+ AuLabel(trunc_xino);
18290+ break;
18291+ case Opt_notrunc_xino:
18292+ AuLabel(notrunc_xino);
18293+ break;
18294+ case Opt_trunc_xino_path:
18295+ case Opt_itrunc_xino:
18296+ u.xino_itrunc = &opt->xino_itrunc;
18297+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
18298+ break;
18299+
18300+ case Opt_noxino:
18301+ AuLabel(noxino);
18302+ break;
18303+ case Opt_trunc_xib:
18304+ AuLabel(trunc_xib);
18305+ break;
18306+ case Opt_notrunc_xib:
18307+ AuLabel(notrunc_xib);
18308+ break;
dece6358
AM
18309+ case Opt_shwh:
18310+ AuLabel(shwh);
18311+ break;
18312+ case Opt_noshwh:
18313+ AuLabel(noshwh);
18314+ break;
1facf9fc 18315+ case Opt_plink:
18316+ AuLabel(plink);
18317+ break;
18318+ case Opt_noplink:
18319+ AuLabel(noplink);
18320+ break;
18321+ case Opt_list_plink:
18322+ AuLabel(list_plink);
18323+ break;
18324+ case Opt_udba:
18325+ AuDbg("udba %d, %s\n",
18326+ opt->udba, au_optstr_udba(opt->udba));
18327+ break;
4a4d8108
AM
18328+ case Opt_dio:
18329+ AuLabel(dio);
18330+ break;
18331+ case Opt_nodio:
18332+ AuLabel(nodio);
18333+ break;
1facf9fc 18334+ case Opt_diropq_a:
18335+ AuLabel(diropq_a);
18336+ break;
18337+ case Opt_diropq_w:
18338+ AuLabel(diropq_w);
18339+ break;
18340+ case Opt_warn_perm:
18341+ AuLabel(warn_perm);
18342+ break;
18343+ case Opt_nowarn_perm:
18344+ AuLabel(nowarn_perm);
18345+ break;
18346+ case Opt_refrof:
18347+ AuLabel(refrof);
18348+ break;
18349+ case Opt_norefrof:
18350+ AuLabel(norefrof);
18351+ break;
18352+ case Opt_verbose:
18353+ AuLabel(verbose);
18354+ break;
18355+ case Opt_noverbose:
18356+ AuLabel(noverbose);
18357+ break;
18358+ case Opt_sum:
18359+ AuLabel(sum);
18360+ break;
18361+ case Opt_nosum:
18362+ AuLabel(nosum);
18363+ break;
18364+ case Opt_wsum:
18365+ AuLabel(wsum);
18366+ break;
18367+ case Opt_wbr_create:
18368+ u.create = &opt->wbr_create;
18369+ AuDbg("create %d, %s\n", u.create->wbr_create,
18370+ au_optstr_wbr_create(u.create->wbr_create));
18371+ switch (u.create->wbr_create) {
18372+ case AuWbrCreate_MFSV:
18373+ case AuWbrCreate_PMFSV:
18374+ AuDbg("%d sec\n", u.create->mfs_second);
18375+ break;
18376+ case AuWbrCreate_MFSRR:
18377+ AuDbg("%llu watermark\n",
18378+ u.create->mfsrr_watermark);
18379+ break;
18380+ case AuWbrCreate_MFSRRV:
18381+ AuDbg("%llu watermark, %d sec\n",
18382+ u.create->mfsrr_watermark,
18383+ u.create->mfs_second);
18384+ break;
18385+ }
18386+ break;
18387+ case Opt_wbr_copyup:
18388+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
18389+ au_optstr_wbr_copyup(opt->wbr_copyup));
18390+ break;
18391+ default:
18392+ BUG();
18393+ }
18394+ opt++;
18395+ }
18396+#endif
18397+}
18398+
18399+void au_opts_free(struct au_opts *opts)
18400+{
18401+ struct au_opt *opt;
18402+
18403+ opt = opts->opt;
18404+ while (opt->type != Opt_tail) {
18405+ switch (opt->type) {
18406+ case Opt_add:
18407+ case Opt_append:
18408+ case Opt_prepend:
18409+ path_put(&opt->add.path);
18410+ break;
18411+ case Opt_del:
18412+ case Opt_idel:
18413+ path_put(&opt->del.h_path);
18414+ break;
18415+ case Opt_mod:
18416+ case Opt_imod:
18417+ dput(opt->mod.h_root);
18418+ break;
18419+ case Opt_xino:
18420+ fput(opt->xino.file);
18421+ break;
18422+ }
18423+ opt++;
18424+ }
18425+}
18426+
18427+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
18428+ aufs_bindex_t bindex)
18429+{
18430+ int err;
18431+ struct au_opt_add *add = &opt->add;
18432+ char *p;
18433+
18434+ add->bindex = bindex;
18435+ add->perm = AuBrPerm_Last;
18436+ add->pathname = opt_str;
18437+ p = strchr(opt_str, '=');
18438+ if (p) {
18439+ *p++ = 0;
18440+ if (*p)
18441+ add->perm = br_perm_val(p);
18442+ }
18443+
18444+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
18445+ if (!err) {
18446+ if (!p) {
18447+ add->perm = AuBrPerm_RO;
18448+ if (au_test_fs_rr(add->path.dentry->d_sb))
18449+ add->perm = AuBrPerm_RR;
18450+ else if (!bindex && !(sb_flags & MS_RDONLY))
18451+ add->perm = AuBrPerm_RW;
18452+ }
18453+ opt->type = Opt_add;
18454+ goto out;
18455+ }
4a4d8108 18456+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 18457+ err = -EINVAL;
18458+
4f0767ce 18459+out:
1facf9fc 18460+ return err;
18461+}
18462+
18463+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
18464+{
18465+ int err;
18466+
18467+ del->pathname = args[0].from;
18468+ AuDbg("del path %s\n", del->pathname);
18469+
18470+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
18471+ if (unlikely(err))
4a4d8108 18472+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 18473+
18474+ return err;
18475+}
18476+
18477+#if 0 /* reserved for future use */
18478+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
18479+ struct au_opt_del *del, substring_t args[])
18480+{
18481+ int err;
18482+ struct dentry *root;
18483+
18484+ err = -EINVAL;
18485+ root = sb->s_root;
18486+ aufs_read_lock(root, AuLock_FLUSH);
18487+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 18488+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 18489+ goto out;
18490+ }
18491+
18492+ err = 0;
18493+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
18494+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
18495+
4f0767ce 18496+out:
1facf9fc 18497+ aufs_read_unlock(root, !AuLock_IR);
18498+ return err;
18499+}
18500+#endif
18501+
4a4d8108
AM
18502+static int noinline_for_stack
18503+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 18504+{
18505+ int err;
18506+ struct path path;
18507+ char *p;
18508+
18509+ err = -EINVAL;
18510+ mod->path = args[0].from;
18511+ p = strchr(mod->path, '=');
18512+ if (unlikely(!p)) {
4a4d8108 18513+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 18514+ goto out;
18515+ }
18516+
18517+ *p++ = 0;
18518+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
18519+ if (unlikely(err)) {
4a4d8108 18520+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 18521+ goto out;
18522+ }
18523+
18524+ mod->perm = br_perm_val(p);
18525+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
18526+ mod->h_root = dget(path.dentry);
18527+ path_put(&path);
18528+
4f0767ce 18529+out:
1facf9fc 18530+ return err;
18531+}
18532+
18533+#if 0 /* reserved for future use */
18534+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
18535+ struct au_opt_mod *mod, substring_t args[])
18536+{
18537+ int err;
18538+ struct dentry *root;
18539+
18540+ err = -EINVAL;
18541+ root = sb->s_root;
18542+ aufs_read_lock(root, AuLock_FLUSH);
18543+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 18544+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 18545+ goto out;
18546+ }
18547+
18548+ err = 0;
18549+ mod->perm = br_perm_val(args[1].from);
18550+ AuDbg("mod path %s, perm 0x%x, %s\n",
18551+ mod->path, mod->perm, args[1].from);
18552+ mod->h_root = dget(au_h_dptr(root, bindex));
18553+
4f0767ce 18554+out:
1facf9fc 18555+ aufs_read_unlock(root, !AuLock_IR);
18556+ return err;
18557+}
18558+#endif
18559+
18560+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
18561+ substring_t args[])
18562+{
18563+ int err;
18564+ struct file *file;
18565+
18566+ file = au_xino_create(sb, args[0].from, /*silent*/0);
18567+ err = PTR_ERR(file);
18568+ if (IS_ERR(file))
18569+ goto out;
18570+
18571+ err = -EINVAL;
18572+ if (unlikely(file->f_dentry->d_sb == sb)) {
18573+ fput(file);
4a4d8108 18574+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 18575+ goto out;
18576+ }
18577+
18578+ err = 0;
18579+ xino->file = file;
18580+ xino->path = args[0].from;
18581+
4f0767ce 18582+out:
1facf9fc 18583+ return err;
18584+}
18585+
4a4d8108
AM
18586+static int noinline_for_stack
18587+au_opts_parse_xino_itrunc_path(struct super_block *sb,
18588+ struct au_opt_xino_itrunc *xino_itrunc,
18589+ substring_t args[])
1facf9fc 18590+{
18591+ int err;
18592+ aufs_bindex_t bend, bindex;
18593+ struct path path;
18594+ struct dentry *root;
18595+
18596+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
18597+ if (unlikely(err)) {
4a4d8108 18598+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 18599+ goto out;
18600+ }
18601+
18602+ xino_itrunc->bindex = -1;
18603+ root = sb->s_root;
18604+ aufs_read_lock(root, AuLock_FLUSH);
18605+ bend = au_sbend(sb);
18606+ for (bindex = 0; bindex <= bend; bindex++) {
18607+ if (au_h_dptr(root, bindex) == path.dentry) {
18608+ xino_itrunc->bindex = bindex;
18609+ break;
18610+ }
18611+ }
18612+ aufs_read_unlock(root, !AuLock_IR);
18613+ path_put(&path);
18614+
18615+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 18616+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 18617+ err = -EINVAL;
18618+ }
18619+
4f0767ce 18620+out:
1facf9fc 18621+ return err;
18622+}
18623+
18624+/* called without aufs lock */
18625+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
18626+{
18627+ int err, n, token;
18628+ aufs_bindex_t bindex;
18629+ unsigned char skipped;
18630+ struct dentry *root;
18631+ struct au_opt *opt, *opt_tail;
18632+ char *opt_str;
18633+ /* reduce the stack space */
18634+ union {
18635+ struct au_opt_xino_itrunc *xino_itrunc;
18636+ struct au_opt_wbr_create *create;
18637+ } u;
18638+ struct {
18639+ substring_t args[MAX_OPT_ARGS];
18640+ } *a;
18641+
18642+ err = -ENOMEM;
18643+ a = kmalloc(sizeof(*a), GFP_NOFS);
18644+ if (unlikely(!a))
18645+ goto out;
18646+
18647+ root = sb->s_root;
18648+ err = 0;
18649+ bindex = 0;
18650+ opt = opts->opt;
18651+ opt_tail = opt + opts->max_opt - 1;
18652+ opt->type = Opt_tail;
18653+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
18654+ err = -EINVAL;
18655+ skipped = 0;
18656+ token = match_token(opt_str, options, a->args);
18657+ switch (token) {
18658+ case Opt_br:
18659+ err = 0;
18660+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
18661+ && *opt_str) {
18662+ err = opt_add(opt, opt_str, opts->sb_flags,
18663+ bindex++);
18664+ if (unlikely(!err && ++opt > opt_tail)) {
18665+ err = -E2BIG;
18666+ break;
18667+ }
18668+ opt->type = Opt_tail;
18669+ skipped = 1;
18670+ }
18671+ break;
18672+ case Opt_add:
18673+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 18674+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18675+ break;
18676+ }
18677+ bindex = n;
18678+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
18679+ bindex);
18680+ if (!err)
18681+ opt->type = token;
18682+ break;
18683+ case Opt_append:
18684+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
18685+ /*dummy bindex*/1);
18686+ if (!err)
18687+ opt->type = token;
18688+ break;
18689+ case Opt_prepend:
18690+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
18691+ /*bindex*/0);
18692+ if (!err)
18693+ opt->type = token;
18694+ break;
18695+ case Opt_del:
18696+ err = au_opts_parse_del(&opt->del, a->args);
18697+ if (!err)
18698+ opt->type = token;
18699+ break;
18700+#if 0 /* reserved for future use */
18701+ case Opt_idel:
18702+ del->pathname = "(indexed)";
18703+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 18704+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18705+ break;
18706+ }
18707+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
18708+ if (!err)
18709+ opt->type = token;
18710+ break;
18711+#endif
18712+ case Opt_mod:
18713+ err = au_opts_parse_mod(&opt->mod, a->args);
18714+ if (!err)
18715+ opt->type = token;
18716+ break;
18717+#ifdef IMOD /* reserved for future use */
18718+ case Opt_imod:
18719+ u.mod->path = "(indexed)";
18720+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 18721+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18722+ break;
18723+ }
18724+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
18725+ if (!err)
18726+ opt->type = token;
18727+ break;
18728+#endif
18729+ case Opt_xino:
18730+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
18731+ if (!err)
18732+ opt->type = token;
18733+ break;
18734+
18735+ case Opt_trunc_xino_path:
18736+ err = au_opts_parse_xino_itrunc_path
18737+ (sb, &opt->xino_itrunc, a->args);
18738+ if (!err)
18739+ opt->type = token;
18740+ break;
18741+
18742+ case Opt_itrunc_xino:
18743+ u.xino_itrunc = &opt->xino_itrunc;
18744+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 18745+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18746+ break;
18747+ }
18748+ u.xino_itrunc->bindex = n;
18749+ aufs_read_lock(root, AuLock_FLUSH);
18750+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 18751+ pr_err("out of bounds, %d\n", n);
1facf9fc 18752+ aufs_read_unlock(root, !AuLock_IR);
18753+ break;
18754+ }
18755+ aufs_read_unlock(root, !AuLock_IR);
18756+ err = 0;
18757+ opt->type = token;
18758+ break;
18759+
18760+ case Opt_dirwh:
18761+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
18762+ break;
18763+ err = 0;
18764+ opt->type = token;
18765+ break;
18766+
18767+ case Opt_rdcache:
027c5e7a
AM
18768+ if (unlikely(match_int(&a->args[0], &n))) {
18769+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18770+ break;
027c5e7a
AM
18771+ }
18772+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
18773+ pr_err("rdcache must be smaller than %d\n",
18774+ AUFS_RDCACHE_MAX);
18775+ break;
18776+ }
18777+ opt->rdcache = n;
1facf9fc 18778+ err = 0;
18779+ opt->type = token;
18780+ break;
18781+ case Opt_rdblk:
18782+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 18783+ || n < 0
1facf9fc 18784+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 18785+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18786+ break;
18787+ }
1308ab2a 18788+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
18789+ pr_err("rdblk must be larger than %d\n",
18790+ NAME_MAX);
1facf9fc 18791+ break;
18792+ }
18793+ opt->rdblk = n;
18794+ err = 0;
18795+ opt->type = token;
18796+ break;
18797+ case Opt_rdhash:
18798+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 18799+ || n < 0
1facf9fc 18800+ || n * sizeof(struct hlist_head)
18801+ > KMALLOC_MAX_SIZE)) {
4a4d8108 18802+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18803+ break;
18804+ }
18805+ opt->rdhash = n;
18806+ err = 0;
18807+ opt->type = token;
18808+ break;
18809+
18810+ case Opt_trunc_xino:
18811+ case Opt_notrunc_xino:
18812+ case Opt_noxino:
18813+ case Opt_trunc_xib:
18814+ case Opt_notrunc_xib:
dece6358
AM
18815+ case Opt_shwh:
18816+ case Opt_noshwh:
1facf9fc 18817+ case Opt_plink:
18818+ case Opt_noplink:
18819+ case Opt_list_plink:
4a4d8108
AM
18820+ case Opt_dio:
18821+ case Opt_nodio:
1facf9fc 18822+ case Opt_diropq_a:
18823+ case Opt_diropq_w:
18824+ case Opt_warn_perm:
18825+ case Opt_nowarn_perm:
18826+ case Opt_refrof:
18827+ case Opt_norefrof:
18828+ case Opt_verbose:
18829+ case Opt_noverbose:
18830+ case Opt_sum:
18831+ case Opt_nosum:
18832+ case Opt_wsum:
dece6358
AM
18833+ case Opt_rdblk_def:
18834+ case Opt_rdhash_def:
1facf9fc 18835+ err = 0;
18836+ opt->type = token;
18837+ break;
18838+
18839+ case Opt_udba:
18840+ opt->udba = udba_val(a->args[0].from);
18841+ if (opt->udba >= 0) {
18842+ err = 0;
18843+ opt->type = token;
18844+ } else
4a4d8108 18845+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18846+ break;
18847+
18848+ case Opt_wbr_create:
18849+ u.create = &opt->wbr_create;
18850+ u.create->wbr_create
18851+ = au_wbr_create_val(a->args[0].from, u.create);
18852+ if (u.create->wbr_create >= 0) {
18853+ err = 0;
18854+ opt->type = token;
18855+ } else
4a4d8108 18856+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18857+ break;
18858+ case Opt_wbr_copyup:
18859+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
18860+ if (opt->wbr_copyup >= 0) {
18861+ err = 0;
18862+ opt->type = token;
18863+ } else
4a4d8108 18864+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18865+ break;
18866+
18867+ case Opt_ignore:
4a4d8108 18868+ pr_warning("ignored %s\n", opt_str);
1facf9fc 18869+ /*FALLTHROUGH*/
18870+ case Opt_ignore_silent:
18871+ skipped = 1;
18872+ err = 0;
18873+ break;
18874+ case Opt_err:
4a4d8108 18875+ pr_err("unknown option %s\n", opt_str);
1facf9fc 18876+ break;
18877+ }
18878+
18879+ if (!err && !skipped) {
18880+ if (unlikely(++opt > opt_tail)) {
18881+ err = -E2BIG;
18882+ opt--;
18883+ opt->type = Opt_tail;
18884+ break;
18885+ }
18886+ opt->type = Opt_tail;
18887+ }
18888+ }
18889+
18890+ kfree(a);
18891+ dump_opts(opts);
18892+ if (unlikely(err))
18893+ au_opts_free(opts);
18894+
4f0767ce 18895+out:
1facf9fc 18896+ return err;
18897+}
18898+
18899+static int au_opt_wbr_create(struct super_block *sb,
18900+ struct au_opt_wbr_create *create)
18901+{
18902+ int err;
18903+ struct au_sbinfo *sbinfo;
18904+
dece6358
AM
18905+ SiMustWriteLock(sb);
18906+
1facf9fc 18907+ err = 1; /* handled */
18908+ sbinfo = au_sbi(sb);
18909+ if (sbinfo->si_wbr_create_ops->fin) {
18910+ err = sbinfo->si_wbr_create_ops->fin(sb);
18911+ if (!err)
18912+ err = 1;
18913+ }
18914+
18915+ sbinfo->si_wbr_create = create->wbr_create;
18916+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
18917+ switch (create->wbr_create) {
18918+ case AuWbrCreate_MFSRRV:
18919+ case AuWbrCreate_MFSRR:
18920+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
18921+ /*FALLTHROUGH*/
18922+ case AuWbrCreate_MFS:
18923+ case AuWbrCreate_MFSV:
18924+ case AuWbrCreate_PMFS:
18925+ case AuWbrCreate_PMFSV:
e49829fe
JR
18926+ sbinfo->si_wbr_mfs.mfs_expire
18927+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 18928+ break;
18929+ }
18930+
18931+ if (sbinfo->si_wbr_create_ops->init)
18932+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
18933+
18934+ return err;
18935+}
18936+
18937+/*
18938+ * returns,
18939+ * plus: processed without an error
18940+ * zero: unprocessed
18941+ */
18942+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
18943+ struct au_opts *opts)
18944+{
18945+ int err;
18946+ struct au_sbinfo *sbinfo;
18947+
dece6358
AM
18948+ SiMustWriteLock(sb);
18949+
1facf9fc 18950+ err = 1; /* handled */
18951+ sbinfo = au_sbi(sb);
18952+ switch (opt->type) {
18953+ case Opt_udba:
18954+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18955+ sbinfo->si_mntflags |= opt->udba;
18956+ opts->given_udba |= opt->udba;
18957+ break;
18958+
18959+ case Opt_plink:
18960+ au_opt_set(sbinfo->si_mntflags, PLINK);
18961+ break;
18962+ case Opt_noplink:
18963+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 18964+ au_plink_put(sb, /*verbose*/1);
1facf9fc 18965+ au_opt_clr(sbinfo->si_mntflags, PLINK);
18966+ break;
18967+ case Opt_list_plink:
18968+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
18969+ au_plink_list(sb);
18970+ break;
18971+
4a4d8108
AM
18972+ case Opt_dio:
18973+ au_opt_set(sbinfo->si_mntflags, DIO);
18974+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18975+ break;
18976+ case Opt_nodio:
18977+ au_opt_clr(sbinfo->si_mntflags, DIO);
18978+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18979+ break;
18980+
1facf9fc 18981+ case Opt_diropq_a:
18982+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18983+ break;
18984+ case Opt_diropq_w:
18985+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18986+ break;
18987+
18988+ case Opt_warn_perm:
18989+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
18990+ break;
18991+ case Opt_nowarn_perm:
18992+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
18993+ break;
18994+
18995+ case Opt_refrof:
18996+ au_opt_set(sbinfo->si_mntflags, REFROF);
18997+ break;
18998+ case Opt_norefrof:
18999+ au_opt_clr(sbinfo->si_mntflags, REFROF);
19000+ break;
19001+
19002+ case Opt_verbose:
19003+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
19004+ break;
19005+ case Opt_noverbose:
19006+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
19007+ break;
19008+
19009+ case Opt_sum:
19010+ au_opt_set(sbinfo->si_mntflags, SUM);
19011+ break;
19012+ case Opt_wsum:
19013+ au_opt_clr(sbinfo->si_mntflags, SUM);
19014+ au_opt_set(sbinfo->si_mntflags, SUM_W);
19015+ case Opt_nosum:
19016+ au_opt_clr(sbinfo->si_mntflags, SUM);
19017+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
19018+ break;
19019+
19020+ case Opt_wbr_create:
19021+ err = au_opt_wbr_create(sb, &opt->wbr_create);
19022+ break;
19023+ case Opt_wbr_copyup:
19024+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
19025+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
19026+ break;
19027+
19028+ case Opt_dirwh:
19029+ sbinfo->si_dirwh = opt->dirwh;
19030+ break;
19031+
19032+ case Opt_rdcache:
e49829fe
JR
19033+ sbinfo->si_rdcache
19034+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 19035+ break;
19036+ case Opt_rdblk:
19037+ sbinfo->si_rdblk = opt->rdblk;
19038+ break;
dece6358
AM
19039+ case Opt_rdblk_def:
19040+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
19041+ break;
1facf9fc 19042+ case Opt_rdhash:
19043+ sbinfo->si_rdhash = opt->rdhash;
19044+ break;
dece6358
AM
19045+ case Opt_rdhash_def:
19046+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
19047+ break;
19048+
19049+ case Opt_shwh:
19050+ au_opt_set(sbinfo->si_mntflags, SHWH);
19051+ break;
19052+ case Opt_noshwh:
19053+ au_opt_clr(sbinfo->si_mntflags, SHWH);
19054+ break;
1facf9fc 19055+
19056+ case Opt_trunc_xino:
19057+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
19058+ break;
19059+ case Opt_notrunc_xino:
19060+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
19061+ break;
19062+
19063+ case Opt_trunc_xino_path:
19064+ case Opt_itrunc_xino:
19065+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
19066+ if (!err)
19067+ err = 1;
19068+ break;
19069+
19070+ case Opt_trunc_xib:
19071+ au_fset_opts(opts->flags, TRUNC_XIB);
19072+ break;
19073+ case Opt_notrunc_xib:
19074+ au_fclr_opts(opts->flags, TRUNC_XIB);
19075+ break;
19076+
19077+ default:
19078+ err = 0;
19079+ break;
19080+ }
19081+
19082+ return err;
19083+}
19084+
19085+/*
19086+ * returns tri-state.
19087+ * plus: processed without an error
19088+ * zero: unprocessed
19089+ * minus: error
19090+ */
19091+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
19092+ struct au_opts *opts)
19093+{
19094+ int err, do_refresh;
19095+
19096+ err = 0;
19097+ switch (opt->type) {
19098+ case Opt_append:
19099+ opt->add.bindex = au_sbend(sb) + 1;
19100+ if (opt->add.bindex < 0)
19101+ opt->add.bindex = 0;
19102+ goto add;
19103+ case Opt_prepend:
19104+ opt->add.bindex = 0;
19105+ add:
19106+ case Opt_add:
19107+ err = au_br_add(sb, &opt->add,
19108+ au_ftest_opts(opts->flags, REMOUNT));
19109+ if (!err) {
19110+ err = 1;
027c5e7a 19111+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 19112+ }
19113+ break;
19114+
19115+ case Opt_del:
19116+ case Opt_idel:
19117+ err = au_br_del(sb, &opt->del,
19118+ au_ftest_opts(opts->flags, REMOUNT));
19119+ if (!err) {
19120+ err = 1;
19121+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 19122+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 19123+ }
19124+ break;
19125+
19126+ case Opt_mod:
19127+ case Opt_imod:
19128+ err = au_br_mod(sb, &opt->mod,
19129+ au_ftest_opts(opts->flags, REMOUNT),
19130+ &do_refresh);
19131+ if (!err) {
19132+ err = 1;
027c5e7a
AM
19133+ if (do_refresh)
19134+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 19135+ }
19136+ break;
19137+ }
19138+
19139+ return err;
19140+}
19141+
19142+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
19143+ struct au_opt_xino **opt_xino,
19144+ struct au_opts *opts)
19145+{
19146+ int err;
19147+ aufs_bindex_t bend, bindex;
19148+ struct dentry *root, *parent, *h_root;
19149+
19150+ err = 0;
19151+ switch (opt->type) {
19152+ case Opt_xino:
19153+ err = au_xino_set(sb, &opt->xino,
19154+ !!au_ftest_opts(opts->flags, REMOUNT));
19155+ if (unlikely(err))
19156+ break;
19157+
19158+ *opt_xino = &opt->xino;
19159+ au_xino_brid_set(sb, -1);
19160+
19161+ /* safe d_parent access */
19162+ parent = opt->xino.file->f_dentry->d_parent;
19163+ root = sb->s_root;
19164+ bend = au_sbend(sb);
19165+ for (bindex = 0; bindex <= bend; bindex++) {
19166+ h_root = au_h_dptr(root, bindex);
19167+ if (h_root == parent) {
19168+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
19169+ break;
19170+ }
19171+ }
19172+ break;
19173+
19174+ case Opt_noxino:
19175+ au_xino_clr(sb);
19176+ au_xino_brid_set(sb, -1);
19177+ *opt_xino = (void *)-1;
19178+ break;
19179+ }
19180+
19181+ return err;
19182+}
19183+
19184+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
19185+ unsigned int pending)
19186+{
19187+ int err;
19188+ aufs_bindex_t bindex, bend;
19189+ unsigned char do_plink, skip, do_free;
19190+ struct au_branch *br;
19191+ struct au_wbr *wbr;
19192+ struct dentry *root;
19193+ struct inode *dir, *h_dir;
19194+ struct au_sbinfo *sbinfo;
19195+ struct au_hinode *hdir;
19196+
dece6358
AM
19197+ SiMustAnyLock(sb);
19198+
1facf9fc 19199+ sbinfo = au_sbi(sb);
19200+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
19201+
dece6358
AM
19202+ if (!(sb_flags & MS_RDONLY)) {
19203+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
4a4d8108 19204+ pr_warning("first branch should be rw\n");
dece6358 19205+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
4a4d8108 19206+ pr_warning("shwh should be used with ro\n");
dece6358 19207+ }
1facf9fc 19208+
4a4d8108 19209+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 19210+ && !au_opt_test(sbinfo->si_mntflags, XINO))
4a4d8108 19211+ pr_warning("udba=*notify requires xino\n");
1facf9fc 19212+
19213+ err = 0;
19214+ root = sb->s_root;
4a4d8108 19215+ dir = root->d_inode;
1facf9fc 19216+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
19217+ bend = au_sbend(sb);
19218+ for (bindex = 0; !err && bindex <= bend; bindex++) {
19219+ skip = 0;
19220+ h_dir = au_h_iptr(dir, bindex);
19221+ br = au_sbr(sb, bindex);
19222+ do_free = 0;
19223+
19224+ wbr = br->br_wbr;
19225+ if (wbr)
19226+ wbr_wh_read_lock(wbr);
19227+
19228+ switch (br->br_perm) {
19229+ case AuBrPerm_RO:
19230+ case AuBrPerm_ROWH:
19231+ case AuBrPerm_RR:
19232+ case AuBrPerm_RRWH:
19233+ do_free = !!wbr;
19234+ skip = (!wbr
19235+ || (!wbr->wbr_whbase
19236+ && !wbr->wbr_plink
19237+ && !wbr->wbr_orph));
19238+ break;
19239+
19240+ case AuBrPerm_RWNoLinkWH:
19241+ /* skip = (!br->br_whbase && !br->br_orph); */
19242+ skip = (!wbr || !wbr->wbr_whbase);
19243+ if (skip && wbr) {
19244+ if (do_plink)
19245+ skip = !!wbr->wbr_plink;
19246+ else
19247+ skip = !wbr->wbr_plink;
19248+ }
19249+ break;
19250+
19251+ case AuBrPerm_RW:
19252+ /* skip = (br->br_whbase && br->br_ohph); */
19253+ skip = (wbr && wbr->wbr_whbase);
19254+ if (skip) {
19255+ if (do_plink)
19256+ skip = !!wbr->wbr_plink;
19257+ else
19258+ skip = !wbr->wbr_plink;
19259+ }
19260+ break;
19261+
19262+ default:
19263+ BUG();
19264+ }
19265+ if (wbr)
19266+ wbr_wh_read_unlock(wbr);
19267+
19268+ if (skip)
19269+ continue;
19270+
19271+ hdir = au_hi(dir, bindex);
4a4d8108 19272+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 19273+ if (wbr)
19274+ wbr_wh_write_lock(wbr);
19275+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
19276+ if (wbr)
19277+ wbr_wh_write_unlock(wbr);
4a4d8108 19278+ au_hn_imtx_unlock(hdir);
1facf9fc 19279+
19280+ if (!err && do_free) {
19281+ kfree(wbr);
19282+ br->br_wbr = NULL;
19283+ }
19284+ }
19285+
19286+ return err;
19287+}
19288+
19289+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
19290+{
19291+ int err;
19292+ unsigned int tmp;
027c5e7a 19293+ aufs_bindex_t bindex, bend;
1facf9fc 19294+ struct au_opt *opt;
19295+ struct au_opt_xino *opt_xino, xino;
19296+ struct au_sbinfo *sbinfo;
027c5e7a 19297+ struct au_branch *br;
1facf9fc 19298+
dece6358
AM
19299+ SiMustWriteLock(sb);
19300+
1facf9fc 19301+ err = 0;
19302+ opt_xino = NULL;
19303+ opt = opts->opt;
19304+ while (err >= 0 && opt->type != Opt_tail)
19305+ err = au_opt_simple(sb, opt++, opts);
19306+ if (err > 0)
19307+ err = 0;
19308+ else if (unlikely(err < 0))
19309+ goto out;
19310+
19311+ /* disable xino and udba temporary */
19312+ sbinfo = au_sbi(sb);
19313+ tmp = sbinfo->si_mntflags;
19314+ au_opt_clr(sbinfo->si_mntflags, XINO);
19315+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
19316+
19317+ opt = opts->opt;
19318+ while (err >= 0 && opt->type != Opt_tail)
19319+ err = au_opt_br(sb, opt++, opts);
19320+ if (err > 0)
19321+ err = 0;
19322+ else if (unlikely(err < 0))
19323+ goto out;
19324+
19325+ bend = au_sbend(sb);
19326+ if (unlikely(bend < 0)) {
19327+ err = -EINVAL;
4a4d8108 19328+ pr_err("no branches\n");
1facf9fc 19329+ goto out;
19330+ }
19331+
19332+ if (au_opt_test(tmp, XINO))
19333+ au_opt_set(sbinfo->si_mntflags, XINO);
19334+ opt = opts->opt;
19335+ while (!err && opt->type != Opt_tail)
19336+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
19337+ if (unlikely(err))
19338+ goto out;
19339+
19340+ err = au_opts_verify(sb, sb->s_flags, tmp);
19341+ if (unlikely(err))
19342+ goto out;
19343+
19344+ /* restore xino */
19345+ if (au_opt_test(tmp, XINO) && !opt_xino) {
19346+ xino.file = au_xino_def(sb);
19347+ err = PTR_ERR(xino.file);
19348+ if (IS_ERR(xino.file))
19349+ goto out;
19350+
19351+ err = au_xino_set(sb, &xino, /*remount*/0);
19352+ fput(xino.file);
19353+ if (unlikely(err))
19354+ goto out;
19355+ }
19356+
19357+ /* restore udba */
027c5e7a 19358+ tmp &= AuOptMask_UDBA;
1facf9fc 19359+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a
AM
19360+ sbinfo->si_mntflags |= tmp;
19361+ bend = au_sbend(sb);
19362+ for (bindex = 0; bindex <= bend; bindex++) {
19363+ br = au_sbr(sb, bindex);
19364+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
19365+ if (unlikely(err))
19366+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
19367+ bindex, err);
19368+ /* go on even if err */
19369+ }
4a4d8108 19370+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 19371+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 19372+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 19373+ }
19374+
4f0767ce 19375+out:
1facf9fc 19376+ return err;
19377+}
19378+
19379+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
19380+{
19381+ int err, rerr;
19382+ struct inode *dir;
19383+ struct au_opt_xino *opt_xino;
19384+ struct au_opt *opt;
19385+ struct au_sbinfo *sbinfo;
19386+
dece6358
AM
19387+ SiMustWriteLock(sb);
19388+
1facf9fc 19389+ dir = sb->s_root->d_inode;
19390+ sbinfo = au_sbi(sb);
19391+ err = 0;
19392+ opt_xino = NULL;
19393+ opt = opts->opt;
19394+ while (err >= 0 && opt->type != Opt_tail) {
19395+ err = au_opt_simple(sb, opt, opts);
19396+ if (!err)
19397+ err = au_opt_br(sb, opt, opts);
19398+ if (!err)
19399+ err = au_opt_xino(sb, opt, &opt_xino, opts);
19400+ opt++;
19401+ }
19402+ if (err > 0)
19403+ err = 0;
19404+ AuTraceErr(err);
19405+ /* go on even err */
19406+
19407+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
19408+ if (unlikely(rerr && !err))
19409+ err = rerr;
19410+
19411+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
19412+ rerr = au_xib_trunc(sb);
19413+ if (unlikely(rerr && !err))
19414+ err = rerr;
19415+ }
19416+
19417+ /* will be handled by the caller */
027c5e7a 19418+ if (!au_ftest_opts(opts->flags, REFRESH)
1facf9fc 19419+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
027c5e7a 19420+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 19421+
19422+ AuDbg("status 0x%x\n", opts->flags);
19423+ return err;
19424+}
19425+
19426+/* ---------------------------------------------------------------------- */
19427+
19428+unsigned int au_opt_udba(struct super_block *sb)
19429+{
19430+ return au_mntflags(sb) & AuOptMask_UDBA;
19431+}
7f207e10
AM
19432diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
19433--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
19434+++ linux/fs/aufs/opts.h 2011-03-21 20:22:06.857268914 +0100
19435@@ -0,0 +1,210 @@
1facf9fc 19436+/*
027c5e7a 19437+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 19438+ *
19439+ * This program, aufs is free software; you can redistribute it and/or modify
19440+ * it under the terms of the GNU General Public License as published by
19441+ * the Free Software Foundation; either version 2 of the License, or
19442+ * (at your option) any later version.
dece6358
AM
19443+ *
19444+ * This program is distributed in the hope that it will be useful,
19445+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19446+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19447+ * GNU General Public License for more details.
19448+ *
19449+ * You should have received a copy of the GNU General Public License
19450+ * along with this program; if not, write to the Free Software
19451+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19452+ */
19453+
19454+/*
19455+ * mount options/flags
19456+ */
19457+
19458+#ifndef __AUFS_OPTS_H__
19459+#define __AUFS_OPTS_H__
19460+
19461+#ifdef __KERNEL__
19462+
dece6358 19463+#include <linux/path.h>
1facf9fc 19464+#include <linux/aufs_type.h>
19465+
dece6358
AM
19466+struct file;
19467+struct super_block;
19468+
1facf9fc 19469+/* ---------------------------------------------------------------------- */
19470+
19471+/* mount flags */
19472+#define AuOpt_XINO 1 /* external inode number bitmap
19473+ and translation table */
19474+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
19475+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
19476+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 19477+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
19478+#define AuOpt_SHWH (1 << 5) /* show whiteout */
19479+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
19480+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
19481+#define AuOpt_REFROF (1 << 8) /* unimplemented */
19482+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
19483+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
19484+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
19485+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
19486+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 19487+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 19488+
4a4d8108
AM
19489+#ifndef CONFIG_AUFS_HNOTIFY
19490+#undef AuOpt_UDBA_HNOTIFY
19491+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 19492+#endif
dece6358
AM
19493+#ifndef CONFIG_AUFS_SHWH
19494+#undef AuOpt_SHWH
19495+#define AuOpt_SHWH 0
19496+#endif
1facf9fc 19497+
19498+#define AuOpt_Def (AuOpt_XINO \
19499+ | AuOpt_UDBA_REVAL \
19500+ | AuOpt_PLINK \
19501+ /* | AuOpt_DIRPERM1 */ \
19502+ | AuOpt_WARN_PERM)
19503+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
19504+ | AuOpt_UDBA_REVAL \
4a4d8108 19505+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 19506+
19507+#define au_opt_test(flags, name) (flags & AuOpt_##name)
19508+#define au_opt_set(flags, name) do { \
19509+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
19510+ ((flags) |= AuOpt_##name); \
19511+} while (0)
19512+#define au_opt_set_udba(flags, name) do { \
19513+ (flags) &= ~AuOptMask_UDBA; \
19514+ ((flags) |= AuOpt_##name); \
19515+} while (0)
7f207e10
AM
19516+#define au_opt_clr(flags, name) do { \
19517+ ((flags) &= ~AuOpt_##name); \
19518+} while (0)
1facf9fc 19519+
e49829fe
JR
19520+static inline unsigned int au_opts_plink(unsigned int mntflags)
19521+{
19522+#ifdef CONFIG_PROC_FS
19523+ return mntflags;
19524+#else
19525+ return mntflags & ~AuOpt_PLINK;
19526+#endif
19527+}
19528+
1facf9fc 19529+/* ---------------------------------------------------------------------- */
19530+
19531+/* policies to select one among multiple writable branches */
19532+enum {
19533+ AuWbrCreate_TDP, /* top down parent */
19534+ AuWbrCreate_RR, /* round robin */
19535+ AuWbrCreate_MFS, /* most free space */
19536+ AuWbrCreate_MFSV, /* mfs with seconds */
19537+ AuWbrCreate_MFSRR, /* mfs then rr */
19538+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
19539+ AuWbrCreate_PMFS, /* parent and mfs */
19540+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
19541+
19542+ AuWbrCreate_Def = AuWbrCreate_TDP
19543+};
19544+
19545+enum {
19546+ AuWbrCopyup_TDP, /* top down parent */
19547+ AuWbrCopyup_BUP, /* bottom up parent */
19548+ AuWbrCopyup_BU, /* bottom up */
19549+
19550+ AuWbrCopyup_Def = AuWbrCopyup_TDP
19551+};
19552+
19553+/* ---------------------------------------------------------------------- */
19554+
19555+struct au_opt_add {
19556+ aufs_bindex_t bindex;
19557+ char *pathname;
19558+ int perm;
19559+ struct path path;
19560+};
19561+
19562+struct au_opt_del {
19563+ char *pathname;
19564+ struct path h_path;
19565+};
19566+
19567+struct au_opt_mod {
19568+ char *path;
19569+ int perm;
19570+ struct dentry *h_root;
19571+};
19572+
19573+struct au_opt_xino {
19574+ char *path;
19575+ struct file *file;
19576+};
19577+
19578+struct au_opt_xino_itrunc {
19579+ aufs_bindex_t bindex;
19580+};
19581+
19582+struct au_opt_wbr_create {
19583+ int wbr_create;
19584+ int mfs_second;
19585+ unsigned long long mfsrr_watermark;
19586+};
19587+
19588+struct au_opt {
19589+ int type;
19590+ union {
19591+ struct au_opt_xino xino;
19592+ struct au_opt_xino_itrunc xino_itrunc;
19593+ struct au_opt_add add;
19594+ struct au_opt_del del;
19595+ struct au_opt_mod mod;
19596+ int dirwh;
19597+ int rdcache;
19598+ unsigned int rdblk;
19599+ unsigned int rdhash;
19600+ int udba;
19601+ struct au_opt_wbr_create wbr_create;
19602+ int wbr_copyup;
19603+ };
19604+};
19605+
19606+/* opts flags */
19607+#define AuOpts_REMOUNT 1
027c5e7a
AM
19608+#define AuOpts_REFRESH (1 << 1)
19609+#define AuOpts_TRUNC_XIB (1 << 2)
19610+#define AuOpts_REFRESH_DYAOP (1 << 3)
1facf9fc 19611+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
19612+#define au_fset_opts(flags, name) \
19613+ do { (flags) |= AuOpts_##name; } while (0)
19614+#define au_fclr_opts(flags, name) \
19615+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 19616+
19617+struct au_opts {
19618+ struct au_opt *opt;
19619+ int max_opt;
19620+
19621+ unsigned int given_udba;
19622+ unsigned int flags;
19623+ unsigned long sb_flags;
19624+};
19625+
19626+/* ---------------------------------------------------------------------- */
19627+
19628+const char *au_optstr_br_perm(int brperm);
19629+const char *au_optstr_udba(int udba);
19630+const char *au_optstr_wbr_copyup(int wbr_copyup);
19631+const char *au_optstr_wbr_create(int wbr_create);
19632+
19633+void au_opts_free(struct au_opts *opts);
19634+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
19635+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
19636+ unsigned int pending);
19637+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
19638+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
19639+
19640+unsigned int au_opt_udba(struct super_block *sb);
19641+
19642+/* ---------------------------------------------------------------------- */
19643+
19644+#endif /* __KERNEL__ */
19645+#endif /* __AUFS_OPTS_H__ */
7f207e10
AM
19646diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
19647--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
19648+++ linux/fs/aufs/plink.c 2011-03-21 20:22:06.857268914 +0100
19649@@ -0,0 +1,515 @@
1facf9fc 19650+/*
027c5e7a 19651+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 19652+ *
19653+ * This program, aufs is free software; you can redistribute it and/or modify
19654+ * it under the terms of the GNU General Public License as published by
19655+ * the Free Software Foundation; either version 2 of the License, or
19656+ * (at your option) any later version.
dece6358
AM
19657+ *
19658+ * This program is distributed in the hope that it will be useful,
19659+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19660+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19661+ * GNU General Public License for more details.
19662+ *
19663+ * You should have received a copy of the GNU General Public License
19664+ * along with this program; if not, write to the Free Software
19665+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19666+ */
19667+
19668+/*
19669+ * pseudo-link
19670+ */
19671+
19672+#include "aufs.h"
19673+
19674+/*
e49829fe 19675+ * the pseudo-link maintenance mode.
1facf9fc 19676+ * during a user process maintains the pseudo-links,
19677+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
19678+ *
19679+ * Flags
19680+ * NOPLM:
19681+ * For entry functions which will handle plink, and i_mutex is already held
19682+ * in VFS.
19683+ * They cannot wait and should return an error at once.
19684+ * Callers has to check the error.
19685+ * NOPLMW:
19686+ * For entry functions which will handle plink, but i_mutex is not held
19687+ * in VFS.
19688+ * They can wait the plink maintenance mode to finish.
19689+ *
19690+ * They behave like F_SETLK and F_SETLKW.
19691+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 19692+ */
e49829fe
JR
19693+
19694+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 19695+{
e49829fe
JR
19696+ int err;
19697+ pid_t pid, ppid;
19698+ struct au_sbinfo *sbi;
dece6358
AM
19699+
19700+ SiMustAnyLock(sb);
19701+
e49829fe
JR
19702+ err = 0;
19703+ if (!au_opt_test(au_mntflags(sb), PLINK))
19704+ goto out;
19705+
19706+ sbi = au_sbi(sb);
19707+ pid = sbi->si_plink_maint_pid;
19708+ if (!pid || pid == current->pid)
19709+ goto out;
19710+
19711+ /* todo: it highly depends upon /sbin/mount.aufs */
19712+ rcu_read_lock();
19713+ ppid = task_pid_vnr(rcu_dereference(current->real_parent));
19714+ rcu_read_unlock();
19715+ if (pid == ppid)
19716+ goto out;
19717+
19718+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
19719+ /* if there is no i_mutex lock in VFS, we don't need to wait */
19720+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
19721+ while (sbi->si_plink_maint_pid) {
19722+ si_read_unlock(sb);
19723+ /* gave up wake_up_bit() */
19724+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
19725+
19726+ if (au_ftest_lock(flags, FLUSH))
19727+ au_nwt_flush(&sbi->si_nowait);
19728+ si_noflush_read_lock(sb);
19729+ }
19730+ } else if (au_ftest_lock(flags, NOPLM)) {
19731+ AuDbg("ppid %d, pid %d\n", ppid, pid);
19732+ err = -EAGAIN;
19733+ }
19734+
19735+out:
19736+ return err;
4a4d8108
AM
19737+}
19738+
e49829fe 19739+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 19740+{
4a4d8108 19741+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 19742+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 19743+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 19744+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
19745+}
19746+
e49829fe 19747+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
19748+{
19749+ int err;
4a4d8108
AM
19750+ struct au_sbinfo *sbinfo;
19751+
19752+ err = 0;
4a4d8108
AM
19753+ sbinfo = au_sbi(sb);
19754+ /* make sure i am the only one in this fs */
e49829fe
JR
19755+ si_write_lock(sb, AuLock_FLUSH);
19756+ if (au_opt_test(au_mntflags(sb), PLINK)) {
19757+ spin_lock(&sbinfo->si_plink_maint_lock);
19758+ if (!sbinfo->si_plink_maint_pid)
19759+ sbinfo->si_plink_maint_pid = current->pid;
19760+ else
19761+ err = -EBUSY;
19762+ spin_unlock(&sbinfo->si_plink_maint_lock);
19763+ }
4a4d8108
AM
19764+ si_write_unlock(sb);
19765+
19766+ return err;
1facf9fc 19767+}
19768+
19769+/* ---------------------------------------------------------------------- */
19770+
19771+struct pseudo_link {
4a4d8108
AM
19772+ union {
19773+ struct list_head list;
19774+ struct rcu_head rcu;
19775+ };
1facf9fc 19776+ struct inode *inode;
19777+};
19778+
19779+#ifdef CONFIG_AUFS_DEBUG
19780+void au_plink_list(struct super_block *sb)
19781+{
19782+ struct au_sbinfo *sbinfo;
19783+ struct list_head *plink_list;
19784+ struct pseudo_link *plink;
19785+
dece6358
AM
19786+ SiMustAnyLock(sb);
19787+
1facf9fc 19788+ sbinfo = au_sbi(sb);
19789+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19790+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19791+
19792+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19793+ rcu_read_lock();
19794+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 19795+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 19796+ rcu_read_unlock();
1facf9fc 19797+}
19798+#endif
19799+
19800+/* is the inode pseudo-linked? */
19801+int au_plink_test(struct inode *inode)
19802+{
19803+ int found;
19804+ struct au_sbinfo *sbinfo;
19805+ struct list_head *plink_list;
19806+ struct pseudo_link *plink;
19807+
19808+ sbinfo = au_sbi(inode->i_sb);
dece6358 19809+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 19810+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 19811+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 19812+
19813+ found = 0;
19814+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19815+ rcu_read_lock();
19816+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 19817+ if (plink->inode == inode) {
19818+ found = 1;
19819+ break;
19820+ }
4a4d8108 19821+ rcu_read_unlock();
1facf9fc 19822+ return found;
19823+}
19824+
19825+/* ---------------------------------------------------------------------- */
19826+
19827+/*
19828+ * generate a name for plink.
19829+ * the file will be stored under AUFS_WH_PLINKDIR.
19830+ */
19831+/* 20 is max digits length of ulong 64 */
19832+#define PLINK_NAME_LEN ((20 + 1) * 2)
19833+
19834+static int plink_name(char *name, int len, struct inode *inode,
19835+ aufs_bindex_t bindex)
19836+{
19837+ int rlen;
19838+ struct inode *h_inode;
19839+
19840+ h_inode = au_h_iptr(inode, bindex);
19841+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
19842+ return rlen;
19843+}
19844+
7f207e10
AM
19845+struct au_do_plink_lkup_args {
19846+ struct dentry **errp;
19847+ struct qstr *tgtname;
19848+ struct dentry *h_parent;
19849+ struct au_branch *br;
19850+};
19851+
19852+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
19853+ struct dentry *h_parent,
19854+ struct au_branch *br)
19855+{
19856+ struct dentry *h_dentry;
19857+ struct mutex *h_mtx;
19858+
19859+ h_mtx = &h_parent->d_inode->i_mutex;
19860+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
19861+ h_dentry = au_lkup_one(tgtname, h_parent, br, /*nd*/NULL);
19862+ mutex_unlock(h_mtx);
19863+ return h_dentry;
19864+}
19865+
19866+static void au_call_do_plink_lkup(void *args)
19867+{
19868+ struct au_do_plink_lkup_args *a = args;
19869+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
19870+}
19871+
1facf9fc 19872+/* lookup the plink-ed @inode under the branch at @bindex */
19873+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
19874+{
19875+ struct dentry *h_dentry, *h_parent;
19876+ struct au_branch *br;
19877+ struct inode *h_dir;
7f207e10 19878+ int wkq_err;
1facf9fc 19879+ char a[PLINK_NAME_LEN];
19880+ struct qstr tgtname = {
19881+ .name = a
19882+ };
19883+
e49829fe
JR
19884+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
19885+
1facf9fc 19886+ br = au_sbr(inode->i_sb, bindex);
19887+ h_parent = br->br_wbr->wbr_plink;
19888+ h_dir = h_parent->d_inode;
19889+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
19890+
7f207e10
AM
19891+ if (current_fsuid()) {
19892+ struct au_do_plink_lkup_args args = {
19893+ .errp = &h_dentry,
19894+ .tgtname = &tgtname,
19895+ .h_parent = h_parent,
19896+ .br = br
19897+ };
19898+
19899+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
19900+ if (unlikely(wkq_err))
19901+ h_dentry = ERR_PTR(wkq_err);
19902+ } else
19903+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
19904+
1facf9fc 19905+ return h_dentry;
19906+}
19907+
19908+/* create a pseudo-link */
19909+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
19910+ struct dentry *h_dentry, struct au_branch *br)
19911+{
19912+ int err;
19913+ struct path h_path = {
19914+ .mnt = br->br_mnt
19915+ };
19916+ struct inode *h_dir;
19917+
19918+ h_dir = h_parent->d_inode;
7f207e10 19919+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
4f0767ce 19920+again:
1facf9fc 19921+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
19922+ err = PTR_ERR(h_path.dentry);
19923+ if (IS_ERR(h_path.dentry))
19924+ goto out;
19925+
19926+ err = 0;
19927+ /* wh.plink dir is not monitored */
7f207e10 19928+ /* todo: is it really safe? */
1facf9fc 19929+ if (h_path.dentry->d_inode
19930+ && h_path.dentry->d_inode != h_dentry->d_inode) {
19931+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
19932+ dput(h_path.dentry);
19933+ h_path.dentry = NULL;
19934+ if (!err)
19935+ goto again;
19936+ }
19937+ if (!err && !h_path.dentry->d_inode)
19938+ err = vfsub_link(h_dentry, h_dir, &h_path);
19939+ dput(h_path.dentry);
19940+
4f0767ce 19941+out:
7f207e10 19942+ mutex_unlock(&h_dir->i_mutex);
1facf9fc 19943+ return err;
19944+}
19945+
19946+struct do_whplink_args {
19947+ int *errp;
19948+ struct qstr *tgt;
19949+ struct dentry *h_parent;
19950+ struct dentry *h_dentry;
19951+ struct au_branch *br;
19952+};
19953+
19954+static void call_do_whplink(void *args)
19955+{
19956+ struct do_whplink_args *a = args;
19957+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
19958+}
19959+
19960+static int whplink(struct dentry *h_dentry, struct inode *inode,
19961+ aufs_bindex_t bindex, struct au_branch *br)
19962+{
19963+ int err, wkq_err;
19964+ struct au_wbr *wbr;
19965+ struct dentry *h_parent;
19966+ struct inode *h_dir;
19967+ char a[PLINK_NAME_LEN];
19968+ struct qstr tgtname = {
19969+ .name = a
19970+ };
19971+
19972+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
19973+ h_parent = wbr->wbr_plink;
19974+ h_dir = h_parent->d_inode;
19975+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
19976+
19977+ /* always superio. */
b752ccd1 19978+ if (current_fsuid()) {
1facf9fc 19979+ struct do_whplink_args args = {
19980+ .errp = &err,
19981+ .tgt = &tgtname,
19982+ .h_parent = h_parent,
19983+ .h_dentry = h_dentry,
19984+ .br = br
19985+ };
19986+ wkq_err = au_wkq_wait(call_do_whplink, &args);
19987+ if (unlikely(wkq_err))
19988+ err = wkq_err;
19989+ } else
19990+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 19991+
19992+ return err;
19993+}
19994+
19995+/* free a single plink */
19996+static void do_put_plink(struct pseudo_link *plink, int do_del)
19997+{
1facf9fc 19998+ if (do_del)
19999+ list_del(&plink->list);
4a4d8108
AM
20000+ iput(plink->inode);
20001+ kfree(plink);
20002+}
20003+
20004+static void do_put_plink_rcu(struct rcu_head *rcu)
20005+{
20006+ struct pseudo_link *plink;
20007+
20008+ plink = container_of(rcu, struct pseudo_link, rcu);
20009+ iput(plink->inode);
1facf9fc 20010+ kfree(plink);
20011+}
20012+
20013+/*
20014+ * create a new pseudo-link for @h_dentry on @bindex.
20015+ * the linked inode is held in aufs @inode.
20016+ */
20017+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
20018+ struct dentry *h_dentry)
20019+{
20020+ struct super_block *sb;
20021+ struct au_sbinfo *sbinfo;
20022+ struct list_head *plink_list;
4a4d8108 20023+ struct pseudo_link *plink, *tmp;
1facf9fc 20024+ int found, err, cnt;
20025+
20026+ sb = inode->i_sb;
20027+ sbinfo = au_sbi(sb);
20028+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 20029+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 20030+
1facf9fc 20031+ cnt = 0;
20032+ found = 0;
20033+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
20034+ rcu_read_lock();
20035+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 20036+ cnt++;
20037+ if (plink->inode == inode) {
20038+ found = 1;
20039+ break;
20040+ }
20041+ }
4a4d8108
AM
20042+ rcu_read_unlock();
20043+ if (found)
1facf9fc 20044+ return;
4a4d8108
AM
20045+
20046+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
20047+ if (tmp)
20048+ tmp->inode = au_igrab(inode);
20049+ else {
20050+ err = -ENOMEM;
20051+ goto out;
1facf9fc 20052+ }
20053+
4a4d8108
AM
20054+ spin_lock(&sbinfo->si_plink.spin);
20055+ list_for_each_entry(plink, plink_list, list) {
20056+ if (plink->inode == inode) {
20057+ found = 1;
20058+ break;
20059+ }
1facf9fc 20060+ }
4a4d8108
AM
20061+ if (!found)
20062+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 20063+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
20064+ if (!found) {
20065+ cnt++;
20066+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
20067+ "unexpectedly many pseudo links, %d\n", cnt);
1facf9fc 20068+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
20069+ } else {
20070+ do_put_plink(tmp, 0);
20071+ return;
1facf9fc 20072+ }
20073+
4a4d8108 20074+out:
1facf9fc 20075+ if (unlikely(err)) {
4a4d8108
AM
20076+ pr_warning("err %d, damaged pseudo link.\n", err);
20077+ if (tmp) {
20078+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
20079+ call_rcu(&tmp->rcu, do_put_plink_rcu);
20080+ }
1facf9fc 20081+ }
20082+}
20083+
20084+/* free all plinks */
e49829fe 20085+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 20086+{
20087+ struct au_sbinfo *sbinfo;
20088+ struct list_head *plink_list;
20089+ struct pseudo_link *plink, *tmp;
20090+
dece6358
AM
20091+ SiMustWriteLock(sb);
20092+
1facf9fc 20093+ sbinfo = au_sbi(sb);
20094+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 20095+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 20096+
20097+ plink_list = &sbinfo->si_plink.head;
20098+ /* no spin_lock since sbinfo is write-locked */
e49829fe 20099+ WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
1facf9fc 20100+ list_for_each_entry_safe(plink, tmp, plink_list, list)
20101+ do_put_plink(plink, 0);
20102+ INIT_LIST_HEAD(plink_list);
20103+}
20104+
e49829fe
JR
20105+void au_plink_clean(struct super_block *sb, int verbose)
20106+{
20107+ struct dentry *root;
20108+
20109+ root = sb->s_root;
20110+ aufs_write_lock(root);
20111+ if (au_opt_test(au_mntflags(sb), PLINK))
20112+ au_plink_put(sb, verbose);
20113+ aufs_write_unlock(root);
20114+}
20115+
1facf9fc 20116+/* free the plinks on a branch specified by @br_id */
20117+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
20118+{
20119+ struct au_sbinfo *sbinfo;
20120+ struct list_head *plink_list;
20121+ struct pseudo_link *plink, *tmp;
20122+ struct inode *inode;
20123+ aufs_bindex_t bstart, bend, bindex;
20124+ unsigned char do_put;
20125+
dece6358
AM
20126+ SiMustWriteLock(sb);
20127+
1facf9fc 20128+ sbinfo = au_sbi(sb);
20129+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 20130+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 20131+
20132+ plink_list = &sbinfo->si_plink.head;
20133+ /* no spin_lock since sbinfo is write-locked */
20134+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
20135+ do_put = 0;
20136+ inode = au_igrab(plink->inode);
20137+ ii_write_lock_child(inode);
20138+ bstart = au_ibstart(inode);
20139+ bend = au_ibend(inode);
20140+ if (bstart >= 0) {
20141+ for (bindex = bstart; bindex <= bend; bindex++) {
20142+ if (!au_h_iptr(inode, bindex)
20143+ || au_ii_br_id(inode, bindex) != br_id)
20144+ continue;
20145+ au_set_h_iptr(inode, bindex, NULL, 0);
20146+ do_put = 1;
20147+ break;
20148+ }
20149+ } else
20150+ do_put_plink(plink, 1);
20151+
dece6358
AM
20152+ if (do_put) {
20153+ for (bindex = bstart; bindex <= bend; bindex++)
20154+ if (au_h_iptr(inode, bindex)) {
20155+ do_put = 0;
20156+ break;
20157+ }
20158+ if (do_put)
20159+ do_put_plink(plink, 1);
20160+ }
20161+ ii_write_unlock(inode);
20162+ iput(inode);
20163+ }
20164+}
7f207e10
AM
20165diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
20166--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a 20167+++ linux/fs/aufs/poll.c 2011-03-21 20:22:06.860602399 +0100
dece6358
AM
20168@@ -0,0 +1,56 @@
20169+/*
027c5e7a 20170+ * Copyright (C) 2005-2011 Junjiro R. Okajima
dece6358
AM
20171+ *
20172+ * This program, aufs is free software; you can redistribute it and/or modify
20173+ * it under the terms of the GNU General Public License as published by
20174+ * the Free Software Foundation; either version 2 of the License, or
20175+ * (at your option) any later version.
20176+ *
20177+ * This program is distributed in the hope that it will be useful,
20178+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20179+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20180+ * GNU General Public License for more details.
20181+ *
20182+ * You should have received a copy of the GNU General Public License
20183+ * along with this program; if not, write to the Free Software
20184+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20185+ */
20186+
1308ab2a 20187+/*
20188+ * poll operation
20189+ * There is only one filesystem which implements ->poll operation, currently.
20190+ */
20191+
20192+#include "aufs.h"
20193+
20194+unsigned int aufs_poll(struct file *file, poll_table *wait)
20195+{
20196+ unsigned int mask;
20197+ int err;
20198+ struct file *h_file;
20199+ struct dentry *dentry;
20200+ struct super_block *sb;
20201+
20202+ /* We should pretend an error happened. */
20203+ mask = POLLERR /* | POLLIN | POLLOUT */;
20204+ dentry = file->f_dentry;
20205+ sb = dentry->d_sb;
e49829fe 20206+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 20207+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
20208+ if (unlikely(err))
20209+ goto out;
20210+
20211+ /* it is not an error if h_file has no operation */
20212+ mask = DEFAULT_POLLMASK;
4a4d8108 20213+ h_file = au_hf_top(file);
1308ab2a 20214+ if (h_file->f_op && h_file->f_op->poll)
20215+ mask = h_file->f_op->poll(h_file, wait);
20216+
20217+ di_read_unlock(dentry, AuLock_IR);
20218+ fi_read_unlock(file);
20219+
4f0767ce 20220+out:
1308ab2a 20221+ si_read_unlock(sb);
20222+ AuTraceErr((int)mask);
20223+ return mask;
20224+}
7f207e10
AM
20225diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
20226--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a 20227+++ linux/fs/aufs/procfs.c 2011-03-21 20:22:06.860602399 +0100
e49829fe
JR
20228@@ -0,0 +1,169 @@
20229+/*
027c5e7a 20230+ * Copyright (C) 2010-2011 Junjiro R. Okajima
e49829fe
JR
20231+ *
20232+ * This program, aufs is free software; you can redistribute it and/or modify
20233+ * it under the terms of the GNU General Public License as published by
20234+ * the Free Software Foundation; either version 2 of the License, or
20235+ * (at your option) any later version.
20236+ *
20237+ * This program is distributed in the hope that it will be useful,
20238+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20239+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20240+ * GNU General Public License for more details.
20241+ *
20242+ * You should have received a copy of the GNU General Public License
20243+ * along with this program; if not, write to the Free Software
20244+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20245+ */
20246+
20247+/*
20248+ * procfs interfaces
20249+ */
20250+
20251+#include <linux/proc_fs.h>
20252+#include "aufs.h"
20253+
20254+static int au_procfs_plm_release(struct inode *inode, struct file *file)
20255+{
20256+ struct au_sbinfo *sbinfo;
20257+
20258+ sbinfo = file->private_data;
20259+ if (sbinfo) {
20260+ au_plink_maint_leave(sbinfo);
20261+ kobject_put(&sbinfo->si_kobj);
20262+ }
20263+
20264+ return 0;
20265+}
20266+
20267+static void au_procfs_plm_write_clean(struct file *file)
20268+{
20269+ struct au_sbinfo *sbinfo;
20270+
20271+ sbinfo = file->private_data;
20272+ if (sbinfo)
20273+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
20274+}
20275+
20276+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
20277+{
20278+ int err;
20279+ struct super_block *sb;
20280+ struct au_sbinfo *sbinfo;
20281+
20282+ err = -EBUSY;
20283+ if (unlikely(file->private_data))
20284+ goto out;
20285+
20286+ sb = NULL;
20287+ spin_lock(&au_sbilist.spin);
20288+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
20289+ if (id == sysaufs_si_id(sbinfo)) {
20290+ kobject_get(&sbinfo->si_kobj);
20291+ sb = sbinfo->si_sb;
20292+ break;
20293+ }
20294+ spin_unlock(&au_sbilist.spin);
20295+
20296+ err = -EINVAL;
20297+ if (unlikely(!sb))
20298+ goto out;
20299+
20300+ err = au_plink_maint_enter(sb);
20301+ if (!err)
20302+ /* keep kobject_get() */
20303+ file->private_data = sbinfo;
20304+ else
20305+ kobject_put(&sbinfo->si_kobj);
20306+out:
20307+ return err;
20308+}
20309+
20310+/*
20311+ * Accept a valid "si=xxxx" only.
20312+ * Once it is accepted successfully, accept "clean" too.
20313+ */
20314+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
20315+ size_t count, loff_t *ppos)
20316+{
20317+ ssize_t err;
20318+ unsigned long id;
20319+ /* last newline is allowed */
20320+ char buf[3 + sizeof(unsigned long) * 2 + 1];
20321+
20322+ err = -EACCES;
20323+ if (unlikely(!capable(CAP_SYS_ADMIN)))
20324+ goto out;
20325+
20326+ err = -EINVAL;
20327+ if (unlikely(count > sizeof(buf)))
20328+ goto out;
20329+
20330+ err = copy_from_user(buf, ubuf, count);
20331+ if (unlikely(err)) {
20332+ err = -EFAULT;
20333+ goto out;
20334+ }
20335+ buf[count] = 0;
20336+
20337+ err = -EINVAL;
20338+ if (!strcmp("clean", buf)) {
20339+ au_procfs_plm_write_clean(file);
20340+ goto out_success;
20341+ } else if (unlikely(strncmp("si=", buf, 3)))
20342+ goto out;
20343+
20344+ err = strict_strtoul(buf + 3, 16, &id);
20345+ if (unlikely(err))
20346+ goto out;
20347+
20348+ err = au_procfs_plm_write_si(file, id);
20349+ if (unlikely(err))
20350+ goto out;
20351+
20352+out_success:
20353+ err = count; /* success */
20354+out:
20355+ return err;
20356+}
20357+
20358+static const struct file_operations au_procfs_plm_fop = {
20359+ .write = au_procfs_plm_write,
20360+ .release = au_procfs_plm_release,
20361+ .owner = THIS_MODULE
20362+};
20363+
20364+/* ---------------------------------------------------------------------- */
20365+
20366+static struct proc_dir_entry *au_procfs_dir;
20367+
20368+void au_procfs_fin(void)
20369+{
20370+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
20371+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
20372+}
20373+
20374+int __init au_procfs_init(void)
20375+{
20376+ int err;
20377+ struct proc_dir_entry *entry;
20378+
20379+ err = -ENOMEM;
20380+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
20381+ if (unlikely(!au_procfs_dir))
20382+ goto out;
20383+
20384+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
20385+ au_procfs_dir, &au_procfs_plm_fop);
20386+ if (unlikely(!entry))
20387+ goto out_dir;
20388+
20389+ err = 0;
20390+ goto out; /* success */
20391+
20392+
20393+out_dir:
20394+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
20395+out:
20396+ return err;
20397+}
7f207e10
AM
20398diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
20399--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
20400+++ linux/fs/aufs/rdu.c 2011-03-21 20:22:06.860602399 +0100
20401@@ -0,0 +1,383 @@
1308ab2a 20402+/*
027c5e7a 20403+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1308ab2a 20404+ *
20405+ * This program, aufs is free software; you can redistribute it and/or modify
20406+ * it under the terms of the GNU General Public License as published by
20407+ * the Free Software Foundation; either version 2 of the License, or
20408+ * (at your option) any later version.
20409+ *
20410+ * This program is distributed in the hope that it will be useful,
20411+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20412+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20413+ * GNU General Public License for more details.
20414+ *
20415+ * You should have received a copy of the GNU General Public License
20416+ * along with this program; if not, write to the Free Software
20417+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20418+ */
20419+
20420+/*
20421+ * readdir in userspace.
20422+ */
20423+
b752ccd1 20424+#include <linux/compat.h>
4a4d8108 20425+#include <linux/fs_stack.h>
1308ab2a 20426+#include <linux/security.h>
20427+#include <linux/uaccess.h>
20428+#include <linux/aufs_type.h>
20429+#include "aufs.h"
20430+
20431+/* bits for struct aufs_rdu.flags */
20432+#define AuRdu_CALLED 1
20433+#define AuRdu_CONT (1 << 1)
20434+#define AuRdu_FULL (1 << 2)
20435+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
20436+#define au_fset_rdu(flags, name) \
20437+ do { (flags) |= AuRdu_##name; } while (0)
20438+#define au_fclr_rdu(flags, name) \
20439+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 20440+
20441+struct au_rdu_arg {
20442+ struct aufs_rdu *rdu;
20443+ union au_rdu_ent_ul ent;
20444+ unsigned long end;
20445+
20446+ struct super_block *sb;
20447+ int err;
20448+};
20449+
20450+static int au_rdu_fill(void *__arg, const char *name, int nlen,
20451+ loff_t offset, u64 h_ino, unsigned int d_type)
20452+{
20453+ int err, len;
20454+ struct au_rdu_arg *arg = __arg;
20455+ struct aufs_rdu *rdu = arg->rdu;
20456+ struct au_rdu_ent ent;
20457+
20458+ err = 0;
20459+ arg->err = 0;
20460+ au_fset_rdu(rdu->cookie.flags, CALLED);
20461+ len = au_rdu_len(nlen);
20462+ if (arg->ent.ul + len < arg->end) {
20463+ ent.ino = h_ino;
20464+ ent.bindex = rdu->cookie.bindex;
20465+ ent.type = d_type;
20466+ ent.nlen = nlen;
4a4d8108
AM
20467+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
20468+ ent.type = DT_UNKNOWN;
1308ab2a 20469+
20470+ err = -EFAULT;
20471+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
20472+ goto out;
20473+ if (copy_to_user(arg->ent.e->name, name, nlen))
20474+ goto out;
20475+ /* the terminating NULL */
20476+ if (__put_user(0, arg->ent.e->name + nlen))
20477+ goto out;
20478+ err = 0;
20479+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
20480+ arg->ent.ul += len;
20481+ rdu->rent++;
20482+ } else {
20483+ err = -EFAULT;
20484+ au_fset_rdu(rdu->cookie.flags, FULL);
20485+ rdu->full = 1;
20486+ rdu->tail = arg->ent;
20487+ }
20488+
4f0767ce 20489+out:
1308ab2a 20490+ /* AuTraceErr(err); */
20491+ return err;
20492+}
20493+
20494+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
20495+{
20496+ int err;
20497+ loff_t offset;
20498+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
20499+
20500+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
20501+ err = offset;
20502+ if (unlikely(offset != cookie->h_pos))
20503+ goto out;
20504+
20505+ err = 0;
20506+ do {
20507+ arg->err = 0;
20508+ au_fclr_rdu(cookie->flags, CALLED);
20509+ /* smp_mb(); */
20510+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
20511+ if (err >= 0)
20512+ err = arg->err;
20513+ } while (!err
20514+ && au_ftest_rdu(cookie->flags, CALLED)
20515+ && !au_ftest_rdu(cookie->flags, FULL));
20516+ cookie->h_pos = h_file->f_pos;
20517+
4f0767ce 20518+out:
1308ab2a 20519+ AuTraceErr(err);
20520+ return err;
20521+}
20522+
20523+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
20524+{
20525+ int err;
20526+ aufs_bindex_t bend;
20527+ struct au_rdu_arg arg;
20528+ struct dentry *dentry;
20529+ struct inode *inode;
20530+ struct file *h_file;
20531+ struct au_rdu_cookie *cookie = &rdu->cookie;
20532+
20533+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
20534+ if (unlikely(err)) {
20535+ err = -EFAULT;
20536+ AuTraceErr(err);
20537+ goto out;
20538+ }
20539+ rdu->rent = 0;
20540+ rdu->tail = rdu->ent;
20541+ rdu->full = 0;
20542+ arg.rdu = rdu;
20543+ arg.ent = rdu->ent;
20544+ arg.end = arg.ent.ul;
20545+ arg.end += rdu->sz;
20546+
20547+ err = -ENOTDIR;
20548+ if (unlikely(!file->f_op || !file->f_op->readdir))
20549+ goto out;
20550+
20551+ err = security_file_permission(file, MAY_READ);
20552+ AuTraceErr(err);
20553+ if (unlikely(err))
20554+ goto out;
20555+
20556+ dentry = file->f_dentry;
20557+ inode = dentry->d_inode;
20558+#if 1
20559+ mutex_lock(&inode->i_mutex);
20560+#else
20561+ err = mutex_lock_killable(&inode->i_mutex);
20562+ AuTraceErr(err);
20563+ if (unlikely(err))
20564+ goto out;
20565+#endif
1308ab2a 20566+
20567+ arg.sb = inode->i_sb;
e49829fe
JR
20568+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
20569+ if (unlikely(err))
20570+ goto out_mtx;
027c5e7a
AM
20571+ err = au_alive_dir(dentry);
20572+ if (unlikely(err))
20573+ goto out_si;
e49829fe 20574+ /* todo: reval? */
1308ab2a 20575+ fi_read_lock(file);
20576+
20577+ err = -EAGAIN;
20578+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
20579+ && cookie->generation != au_figen(file)))
20580+ goto out_unlock;
20581+
20582+ err = 0;
20583+ if (!rdu->blk) {
20584+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
20585+ if (!rdu->blk)
20586+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
20587+ }
20588+ bend = au_fbstart(file);
20589+ if (cookie->bindex < bend)
20590+ cookie->bindex = bend;
4a4d8108 20591+ bend = au_fbend_dir(file);
1308ab2a 20592+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
20593+ for (; !err && cookie->bindex <= bend;
20594+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 20595+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 20596+ if (!h_file)
20597+ continue;
20598+
20599+ au_fclr_rdu(cookie->flags, FULL);
20600+ err = au_rdu_do(h_file, &arg);
20601+ AuTraceErr(err);
20602+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
20603+ break;
20604+ }
20605+ AuDbg("rent %llu\n", rdu->rent);
20606+
20607+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
20608+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
20609+ au_fset_rdu(cookie->flags, CONT);
20610+ cookie->generation = au_figen(file);
20611+ }
20612+
20613+ ii_read_lock_child(inode);
20614+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
20615+ ii_read_unlock(inode);
20616+
4f0767ce 20617+out_unlock:
1308ab2a 20618+ fi_read_unlock(file);
027c5e7a 20619+out_si:
1308ab2a 20620+ si_read_unlock(arg.sb);
4f0767ce 20621+out_mtx:
1308ab2a 20622+ mutex_unlock(&inode->i_mutex);
4f0767ce 20623+out:
1308ab2a 20624+ AuTraceErr(err);
20625+ return err;
20626+}
20627+
20628+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
20629+{
20630+ int err;
20631+ ino_t ino;
20632+ unsigned long long nent;
20633+ union au_rdu_ent_ul *u;
20634+ struct au_rdu_ent ent;
20635+ struct super_block *sb;
20636+
20637+ err = 0;
20638+ nent = rdu->nent;
20639+ u = &rdu->ent;
20640+ sb = file->f_dentry->d_sb;
20641+ si_read_lock(sb, AuLock_FLUSH);
20642+ while (nent-- > 0) {
1308ab2a 20643+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
20644+ if (!err)
20645+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 20646+ if (unlikely(err)) {
20647+ err = -EFAULT;
20648+ AuTraceErr(err);
20649+ break;
20650+ }
20651+
20652+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
20653+ if (!ent.wh)
20654+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
20655+ else
20656+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
20657+ &ino);
20658+ if (unlikely(err)) {
20659+ AuTraceErr(err);
20660+ break;
20661+ }
20662+
20663+ err = __put_user(ino, &u->e->ino);
20664+ if (unlikely(err)) {
20665+ err = -EFAULT;
20666+ AuTraceErr(err);
20667+ break;
20668+ }
20669+ u->ul += au_rdu_len(ent.nlen);
20670+ }
20671+ si_read_unlock(sb);
20672+
20673+ return err;
20674+}
20675+
20676+/* ---------------------------------------------------------------------- */
20677+
20678+static int au_rdu_verify(struct aufs_rdu *rdu)
20679+{
b752ccd1 20680+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 20681+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 20682+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 20683+ rdu->blk,
20684+ rdu->rent, rdu->shwh, rdu->full,
20685+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
20686+ rdu->cookie.generation);
dece6358 20687+
b752ccd1 20688+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 20689+ return 0;
dece6358 20690+
b752ccd1
AM
20691+ AuDbg("%u:%u\n",
20692+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 20693+ return -EINVAL;
20694+}
20695+
20696+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 20697+{
1308ab2a 20698+ long err, e;
20699+ struct aufs_rdu rdu;
20700+ void __user *p = (void __user *)arg;
dece6358 20701+
1308ab2a 20702+ err = copy_from_user(&rdu, p, sizeof(rdu));
20703+ if (unlikely(err)) {
20704+ err = -EFAULT;
20705+ AuTraceErr(err);
20706+ goto out;
20707+ }
20708+ err = au_rdu_verify(&rdu);
dece6358
AM
20709+ if (unlikely(err))
20710+ goto out;
20711+
1308ab2a 20712+ switch (cmd) {
20713+ case AUFS_CTL_RDU:
20714+ err = au_rdu(file, &rdu);
20715+ if (unlikely(err))
20716+ break;
dece6358 20717+
1308ab2a 20718+ e = copy_to_user(p, &rdu, sizeof(rdu));
20719+ if (unlikely(e)) {
20720+ err = -EFAULT;
20721+ AuTraceErr(err);
20722+ }
20723+ break;
20724+ case AUFS_CTL_RDU_INO:
20725+ err = au_rdu_ino(file, &rdu);
20726+ break;
20727+
20728+ default:
4a4d8108 20729+ /* err = -ENOTTY; */
1308ab2a 20730+ err = -EINVAL;
20731+ }
dece6358 20732+
4f0767ce 20733+out:
1308ab2a 20734+ AuTraceErr(err);
20735+ return err;
1facf9fc 20736+}
b752ccd1
AM
20737+
20738+#ifdef CONFIG_COMPAT
20739+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
20740+{
20741+ long err, e;
20742+ struct aufs_rdu rdu;
20743+ void __user *p = compat_ptr(arg);
20744+
20745+ /* todo: get_user()? */
20746+ err = copy_from_user(&rdu, p, sizeof(rdu));
20747+ if (unlikely(err)) {
20748+ err = -EFAULT;
20749+ AuTraceErr(err);
20750+ goto out;
20751+ }
20752+ rdu.ent.e = compat_ptr(rdu.ent.ul);
20753+ err = au_rdu_verify(&rdu);
20754+ if (unlikely(err))
20755+ goto out;
20756+
20757+ switch (cmd) {
20758+ case AUFS_CTL_RDU:
20759+ err = au_rdu(file, &rdu);
20760+ if (unlikely(err))
20761+ break;
20762+
20763+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
20764+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
20765+ e = copy_to_user(p, &rdu, sizeof(rdu));
20766+ if (unlikely(e)) {
20767+ err = -EFAULT;
20768+ AuTraceErr(err);
20769+ }
20770+ break;
20771+ case AUFS_CTL_RDU_INO:
20772+ err = au_rdu_ino(file, &rdu);
20773+ break;
20774+
20775+ default:
20776+ /* err = -ENOTTY; */
20777+ err = -EINVAL;
20778+ }
20779+
4f0767ce 20780+out:
b752ccd1
AM
20781+ AuTraceErr(err);
20782+ return err;
20783+}
20784+#endif
7f207e10
AM
20785diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
20786--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 20787+++ linux/fs/aufs/rwsem.h 2011-03-21 20:22:06.860602399 +0100
e49829fe 20788@@ -0,0 +1,189 @@
1facf9fc 20789+/*
027c5e7a 20790+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 20791+ *
20792+ * This program, aufs is free software; you can redistribute it and/or modify
20793+ * it under the terms of the GNU General Public License as published by
20794+ * the Free Software Foundation; either version 2 of the License, or
20795+ * (at your option) any later version.
dece6358
AM
20796+ *
20797+ * This program is distributed in the hope that it will be useful,
20798+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20799+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20800+ * GNU General Public License for more details.
20801+ *
20802+ * You should have received a copy of the GNU General Public License
20803+ * along with this program; if not, write to the Free Software
20804+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20805+ */
20806+
20807+/*
20808+ * simple read-write semaphore wrappers
20809+ */
20810+
20811+#ifndef __AUFS_RWSEM_H__
20812+#define __AUFS_RWSEM_H__
20813+
20814+#ifdef __KERNEL__
20815+
dece6358 20816+#include <linux/rwsem.h>
4a4d8108 20817+#include "debug.h"
dece6358
AM
20818+
20819+struct au_rwsem {
20820+ struct rw_semaphore rwsem;
20821+#ifdef CONFIG_AUFS_DEBUG
20822+ /* just for debugging, not almighty counter */
20823+ atomic_t rcnt, wcnt;
20824+#endif
20825+};
20826+
20827+#ifdef CONFIG_AUFS_DEBUG
20828+#define AuDbgCntInit(rw) do { \
20829+ atomic_set(&(rw)->rcnt, 0); \
20830+ atomic_set(&(rw)->wcnt, 0); \
20831+ smp_mb(); /* atomic set */ \
20832+} while (0)
20833+
e49829fe 20834+#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
dece6358 20835+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
e49829fe 20836+#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
dece6358
AM
20837+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
20838+#else
20839+#define AuDbgCntInit(rw) do {} while (0)
20840+#define AuDbgRcntInc(rw) do {} while (0)
20841+#define AuDbgRcntDec(rw) do {} while (0)
20842+#define AuDbgWcntInc(rw) do {} while (0)
20843+#define AuDbgWcntDec(rw) do {} while (0)
20844+#endif /* CONFIG_AUFS_DEBUG */
20845+
20846+/* to debug easier, do not make them inlined functions */
20847+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
20848+/* rwsem_is_locked() is unusable */
20849+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
20850+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
20851+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
20852+ && atomic_read(&(rw)->wcnt) <= 0)
20853+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
20854+ || atomic_read(&(rw)->wcnt))
20855+
e49829fe
JR
20856+#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
20857+
dece6358
AM
20858+static inline void au_rw_init(struct au_rwsem *rw)
20859+{
20860+ AuDbgCntInit(rw);
20861+ init_rwsem(&rw->rwsem);
20862+}
20863+
20864+static inline void au_rw_init_wlock(struct au_rwsem *rw)
20865+{
20866+ au_rw_init(rw);
20867+ down_write(&rw->rwsem);
20868+ AuDbgWcntInc(rw);
20869+}
20870+
20871+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
20872+ unsigned int lsc)
20873+{
20874+ au_rw_init(rw);
20875+ down_write_nested(&rw->rwsem, lsc);
20876+ AuDbgWcntInc(rw);
20877+}
20878+
20879+static inline void au_rw_read_lock(struct au_rwsem *rw)
20880+{
20881+ down_read(&rw->rwsem);
20882+ AuDbgRcntInc(rw);
20883+}
20884+
20885+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
20886+{
20887+ down_read_nested(&rw->rwsem, lsc);
20888+ AuDbgRcntInc(rw);
20889+}
20890+
20891+static inline void au_rw_read_unlock(struct au_rwsem *rw)
20892+{
20893+ AuRwMustReadLock(rw);
20894+ AuDbgRcntDec(rw);
20895+ up_read(&rw->rwsem);
20896+}
20897+
20898+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
20899+{
20900+ AuRwMustWriteLock(rw);
20901+ AuDbgRcntInc(rw);
20902+ AuDbgWcntDec(rw);
20903+ downgrade_write(&rw->rwsem);
20904+}
20905+
20906+static inline void au_rw_write_lock(struct au_rwsem *rw)
20907+{
20908+ down_write(&rw->rwsem);
20909+ AuDbgWcntInc(rw);
20910+}
20911+
20912+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
20913+ unsigned int lsc)
20914+{
20915+ down_write_nested(&rw->rwsem, lsc);
20916+ AuDbgWcntInc(rw);
20917+}
1facf9fc 20918+
dece6358
AM
20919+static inline void au_rw_write_unlock(struct au_rwsem *rw)
20920+{
20921+ AuRwMustWriteLock(rw);
20922+ AuDbgWcntDec(rw);
20923+ up_write(&rw->rwsem);
20924+}
20925+
20926+/* why is not _nested version defined */
20927+static inline int au_rw_read_trylock(struct au_rwsem *rw)
20928+{
20929+ int ret = down_read_trylock(&rw->rwsem);
20930+ if (ret)
20931+ AuDbgRcntInc(rw);
20932+ return ret;
20933+}
20934+
20935+static inline int au_rw_write_trylock(struct au_rwsem *rw)
20936+{
20937+ int ret = down_write_trylock(&rw->rwsem);
20938+ if (ret)
20939+ AuDbgWcntInc(rw);
20940+ return ret;
20941+}
20942+
20943+#undef AuDbgCntInit
20944+#undef AuDbgRcntInc
20945+#undef AuDbgRcntDec
20946+#undef AuDbgWcntInc
20947+#undef AuDbgWcntDec
1facf9fc 20948+
20949+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
20950+static inline void prefix##_read_lock(param) \
dece6358 20951+{ au_rw_read_lock(rwsem); } \
1facf9fc 20952+static inline void prefix##_write_lock(param) \
dece6358 20953+{ au_rw_write_lock(rwsem); } \
1facf9fc 20954+static inline int prefix##_read_trylock(param) \
dece6358 20955+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 20956+static inline int prefix##_write_trylock(param) \
dece6358 20957+{ return au_rw_write_trylock(rwsem); }
1facf9fc 20958+/* why is not _nested version defined */
20959+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 20960+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 20961+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 20962+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 20963+
20964+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
20965+static inline void prefix##_read_unlock(param) \
dece6358 20966+{ au_rw_read_unlock(rwsem); } \
1facf9fc 20967+static inline void prefix##_write_unlock(param) \
dece6358 20968+{ au_rw_write_unlock(rwsem); } \
1facf9fc 20969+static inline void prefix##_downgrade_lock(param) \
dece6358 20970+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 20971+
20972+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
20973+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
20974+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
20975+
20976+#endif /* __KERNEL__ */
20977+#endif /* __AUFS_RWSEM_H__ */
7f207e10
AM
20978diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
20979--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
20980+++ linux/fs/aufs/sbinfo.c 2011-03-21 20:22:06.860602399 +0100
20981@@ -0,0 +1,344 @@
1facf9fc 20982+/*
027c5e7a 20983+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 20984+ *
20985+ * This program, aufs is free software; you can redistribute it and/or modify
20986+ * it under the terms of the GNU General Public License as published by
20987+ * the Free Software Foundation; either version 2 of the License, or
20988+ * (at your option) any later version.
dece6358
AM
20989+ *
20990+ * This program is distributed in the hope that it will be useful,
20991+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20992+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20993+ * GNU General Public License for more details.
20994+ *
20995+ * You should have received a copy of the GNU General Public License
20996+ * along with this program; if not, write to the Free Software
20997+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20998+ */
20999+
21000+/*
21001+ * superblock private data
21002+ */
21003+
e49829fe 21004+#include <linux/jiffies.h>
1facf9fc 21005+#include "aufs.h"
21006+
21007+/*
21008+ * they are necessary regardless sysfs is disabled.
21009+ */
21010+void au_si_free(struct kobject *kobj)
21011+{
21012+ struct au_sbinfo *sbinfo;
b752ccd1 21013+ char *locked __maybe_unused; /* debug only */
1facf9fc 21014+
21015+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
21016+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
e49829fe 21017+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
1facf9fc 21018+
e49829fe 21019+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 21020+ au_br_free(sbinfo);
e49829fe 21021+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1
AM
21022+
21023+ AuDebugOn(radix_tree_gang_lookup
21024+ (&sbinfo->au_si_pid.tree, (void **)&locked,
21025+ /*first_index*/PID_MAX_DEFAULT - 1,
21026+ /*max_items*/sizeof(locked)/sizeof(*locked)));
21027+
1facf9fc 21028+ kfree(sbinfo->si_branch);
b752ccd1 21029+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 21030+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 21031+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 21032+
21033+ kfree(sbinfo);
21034+}
21035+
21036+int au_si_alloc(struct super_block *sb)
21037+{
21038+ int err;
21039+ struct au_sbinfo *sbinfo;
e49829fe 21040+ static struct lock_class_key aufs_si;
1facf9fc 21041+
21042+ err = -ENOMEM;
4a4d8108 21043+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 21044+ if (unlikely(!sbinfo))
21045+ goto out;
21046+
b752ccd1
AM
21047+ BUILD_BUG_ON(sizeof(unsigned long) !=
21048+ sizeof(*sbinfo->au_si_pid.bitmap));
21049+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
21050+ sizeof(*sbinfo->au_si_pid.bitmap),
21051+ GFP_NOFS);
21052+ if (unlikely(!sbinfo->au_si_pid.bitmap))
21053+ goto out_sbinfo;
21054+
1facf9fc 21055+ /* will be reallocated separately */
21056+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
21057+ if (unlikely(!sbinfo->si_branch))
b752ccd1 21058+ goto out_pidmap;
1facf9fc 21059+
1facf9fc 21060+ err = sysaufs_si_init(sbinfo);
21061+ if (unlikely(err))
21062+ goto out_br;
21063+
21064+ au_nwt_init(&sbinfo->si_nowait);
dece6358 21065+ au_rw_init_wlock(&sbinfo->si_rwsem);
e49829fe 21066+ au_rw_class(&sbinfo->si_rwsem, &aufs_si);
b752ccd1
AM
21067+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
21068+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
21069+
7f207e10 21070+ atomic_long_set(&sbinfo->si_ninodes, 0);
7f207e10
AM
21071+ atomic_long_set(&sbinfo->si_nfiles, 0);
21072+
1facf9fc 21073+ sbinfo->si_bend = -1;
1facf9fc 21074+
21075+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
21076+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
21077+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
21078+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 21079+
e49829fe 21080+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 21081+
1facf9fc 21082+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 21083+ sbinfo->si_xino_brid = -1;
21084+ /* leave si_xib_last_pindex and si_xib_next_bit */
21085+
e49829fe 21086+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 21087+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
21088+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
21089+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
21090+
21091+ au_spl_init(&sbinfo->si_plink);
21092+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 21093+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 21094+
21095+ /* leave other members for sysaufs and si_mnt. */
21096+ sbinfo->si_sb = sb;
21097+ sb->s_fs_info = sbinfo;
b752ccd1 21098+ si_pid_set(sb);
1facf9fc 21099+ au_debug_sbinfo_init(sbinfo);
21100+ return 0; /* success */
21101+
4f0767ce 21102+out_br:
1facf9fc 21103+ kfree(sbinfo->si_branch);
4f0767ce 21104+out_pidmap:
b752ccd1 21105+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 21106+out_sbinfo:
1facf9fc 21107+ kfree(sbinfo);
4f0767ce 21108+out:
1facf9fc 21109+ return err;
21110+}
21111+
21112+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
21113+{
21114+ int err, sz;
21115+ struct au_branch **brp;
21116+
dece6358
AM
21117+ AuRwMustWriteLock(&sbinfo->si_rwsem);
21118+
1facf9fc 21119+ err = -ENOMEM;
21120+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
21121+ if (unlikely(!sz))
21122+ sz = sizeof(*brp);
21123+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
21124+ if (brp) {
21125+ sbinfo->si_branch = brp;
21126+ err = 0;
21127+ }
21128+
21129+ return err;
21130+}
21131+
21132+/* ---------------------------------------------------------------------- */
21133+
21134+unsigned int au_sigen_inc(struct super_block *sb)
21135+{
21136+ unsigned int gen;
21137+
dece6358
AM
21138+ SiMustWriteLock(sb);
21139+
1facf9fc 21140+ gen = ++au_sbi(sb)->si_generation;
21141+ au_update_digen(sb->s_root);
21142+ au_update_iigen(sb->s_root->d_inode);
21143+ sb->s_root->d_inode->i_version++;
21144+ return gen;
21145+}
21146+
21147+aufs_bindex_t au_new_br_id(struct super_block *sb)
21148+{
21149+ aufs_bindex_t br_id;
21150+ int i;
21151+ struct au_sbinfo *sbinfo;
21152+
dece6358
AM
21153+ SiMustWriteLock(sb);
21154+
1facf9fc 21155+ sbinfo = au_sbi(sb);
21156+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
21157+ br_id = ++sbinfo->si_last_br_id;
7f207e10 21158+ AuDebugOn(br_id < 0);
1facf9fc 21159+ if (br_id && au_br_index(sb, br_id) < 0)
21160+ return br_id;
21161+ }
21162+
21163+ return -1;
21164+}
21165+
21166+/* ---------------------------------------------------------------------- */
21167+
e49829fe
JR
21168+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
21169+int si_read_lock(struct super_block *sb, int flags)
21170+{
21171+ int err;
21172+
21173+ err = 0;
21174+ if (au_ftest_lock(flags, FLUSH))
21175+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21176+
21177+ si_noflush_read_lock(sb);
21178+ err = au_plink_maint(sb, flags);
21179+ if (unlikely(err))
21180+ si_read_unlock(sb);
21181+
21182+ return err;
21183+}
21184+
21185+int si_write_lock(struct super_block *sb, int flags)
21186+{
21187+ int err;
21188+
21189+ if (au_ftest_lock(flags, FLUSH))
21190+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21191+
21192+ si_noflush_write_lock(sb);
21193+ err = au_plink_maint(sb, flags);
21194+ if (unlikely(err))
21195+ si_write_unlock(sb);
21196+
21197+ return err;
21198+}
21199+
1facf9fc 21200+/* dentry and super_block lock. call at entry point */
e49829fe 21201+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 21202+{
e49829fe 21203+ int err;
027c5e7a 21204+ struct super_block *sb;
e49829fe 21205+
027c5e7a
AM
21206+ sb = dentry->d_sb;
21207+ err = si_read_lock(sb, flags);
21208+ if (unlikely(err))
21209+ goto out;
21210+
21211+ if (au_ftest_lock(flags, DW))
21212+ di_write_lock_child(dentry);
21213+ else
21214+ di_read_lock_child(dentry, flags);
21215+
21216+ if (au_ftest_lock(flags, GEN)) {
21217+ err = au_digen_test(dentry, au_sigen(sb));
21218+ AuDebugOn(!err && au_dbrange_test(dentry));
21219+ if (unlikely(err))
21220+ aufs_read_unlock(dentry, flags);
e49829fe
JR
21221+ }
21222+
027c5e7a 21223+out:
e49829fe 21224+ return err;
1facf9fc 21225+}
21226+
21227+void aufs_read_unlock(struct dentry *dentry, int flags)
21228+{
21229+ if (au_ftest_lock(flags, DW))
21230+ di_write_unlock(dentry);
21231+ else
21232+ di_read_unlock(dentry, flags);
21233+ si_read_unlock(dentry->d_sb);
21234+}
21235+
21236+void aufs_write_lock(struct dentry *dentry)
21237+{
e49829fe 21238+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 21239+ di_write_lock_child(dentry);
21240+}
21241+
21242+void aufs_write_unlock(struct dentry *dentry)
21243+{
21244+ di_write_unlock(dentry);
21245+ si_write_unlock(dentry->d_sb);
21246+}
21247+
e49829fe 21248+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 21249+{
e49829fe 21250+ int err;
027c5e7a
AM
21251+ unsigned int sigen;
21252+ struct super_block *sb;
e49829fe 21253+
027c5e7a
AM
21254+ sb = d1->d_sb;
21255+ err = si_read_lock(sb, flags);
21256+ if (unlikely(err))
21257+ goto out;
21258+
21259+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
21260+
21261+ if (au_ftest_lock(flags, GEN)) {
21262+ sigen = au_sigen(sb);
21263+ err = au_digen_test(d1, sigen);
21264+ AuDebugOn(!err && au_dbrange_test(d1));
21265+ if (!err) {
21266+ err = au_digen_test(d2, sigen);
21267+ AuDebugOn(!err && au_dbrange_test(d2));
21268+ }
21269+ if (unlikely(err))
21270+ aufs_read_and_write_unlock2(d1, d2);
21271+ }
21272+
21273+out:
e49829fe 21274+ return err;
1facf9fc 21275+}
21276+
21277+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
21278+{
21279+ di_write_unlock2(d1, d2);
21280+ si_read_unlock(d1->d_sb);
21281+}
b752ccd1
AM
21282+
21283+/* ---------------------------------------------------------------------- */
21284+
21285+int si_pid_test_slow(struct super_block *sb)
21286+{
21287+ void *p;
21288+
21289+ rcu_read_lock();
21290+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
21291+ rcu_read_unlock();
21292+
027c5e7a 21293+ return (long)!!p;
b752ccd1
AM
21294+}
21295+
21296+void si_pid_set_slow(struct super_block *sb)
21297+{
21298+ int err;
21299+ struct au_sbinfo *sbinfo;
21300+
21301+ AuDebugOn(si_pid_test_slow(sb));
21302+
21303+ sbinfo = au_sbi(sb);
21304+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
21305+ AuDebugOn(err);
21306+ spin_lock(&sbinfo->au_si_pid.tree_lock);
21307+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
027c5e7a 21308+ /*any valid ptr*/sb);
b752ccd1
AM
21309+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
21310+ AuDebugOn(err);
21311+ radix_tree_preload_end();
21312+}
21313+
21314+void si_pid_clr_slow(struct super_block *sb)
21315+{
21316+ void *p;
21317+ struct au_sbinfo *sbinfo;
21318+
21319+ AuDebugOn(!si_pid_test_slow(sb));
21320+
21321+ sbinfo = au_sbi(sb);
21322+ spin_lock(&sbinfo->au_si_pid.tree_lock);
21323+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
21324+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
b752ccd1 21325+}
7f207e10
AM
21326diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
21327--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 21328+++ linux/fs/aufs/spl.h 2011-03-21 20:22:06.860602399 +0100
4a4d8108 21329@@ -0,0 +1,66 @@
1facf9fc 21330+/*
027c5e7a 21331+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 21332+ *
21333+ * This program, aufs is free software; you can redistribute it and/or modify
21334+ * it under the terms of the GNU General Public License as published by
21335+ * the Free Software Foundation; either version 2 of the License, or
21336+ * (at your option) any later version.
dece6358
AM
21337+ *
21338+ * This program is distributed in the hope that it will be useful,
21339+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21340+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21341+ * GNU General Public License for more details.
21342+ *
21343+ * You should have received a copy of the GNU General Public License
21344+ * along with this program; if not, write to the Free Software
21345+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21346+ */
21347+
21348+/*
21349+ * simple list protected by a spinlock
21350+ */
21351+
21352+#ifndef __AUFS_SPL_H__
21353+#define __AUFS_SPL_H__
21354+
21355+#ifdef __KERNEL__
21356+
dece6358
AM
21357+#include <linux/spinlock.h>
21358+#include <linux/list.h>
4a4d8108 21359+#include <linux/rculist.h>
1facf9fc 21360+
21361+struct au_splhead {
21362+ spinlock_t spin;
21363+ struct list_head head;
21364+};
21365+
21366+static inline void au_spl_init(struct au_splhead *spl)
21367+{
21368+ spin_lock_init(&spl->spin);
21369+ INIT_LIST_HEAD(&spl->head);
21370+}
21371+
21372+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
21373+{
21374+ spin_lock(&spl->spin);
21375+ list_add(list, &spl->head);
21376+ spin_unlock(&spl->spin);
21377+}
21378+
21379+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
21380+{
21381+ spin_lock(&spl->spin);
21382+ list_del(list);
21383+ spin_unlock(&spl->spin);
21384+}
21385+
4a4d8108
AM
21386+static inline void au_spl_del_rcu(struct list_head *list,
21387+ struct au_splhead *spl)
21388+{
21389+ spin_lock(&spl->spin);
21390+ list_del_rcu(list);
21391+ spin_unlock(&spl->spin);
21392+}
21393+
1facf9fc 21394+#endif /* __KERNEL__ */
21395+#endif /* __AUFS_SPL_H__ */
7f207e10
AM
21396diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
21397--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
21398+++ linux/fs/aufs/super.c 2011-03-21 20:22:06.860602399 +0100
21399@@ -0,0 +1,925 @@
1facf9fc 21400+/*
027c5e7a 21401+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 21402+ *
21403+ * This program, aufs is free software; you can redistribute it and/or modify
21404+ * it under the terms of the GNU General Public License as published by
21405+ * the Free Software Foundation; either version 2 of the License, or
21406+ * (at your option) any later version.
dece6358
AM
21407+ *
21408+ * This program is distributed in the hope that it will be useful,
21409+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21410+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21411+ * GNU General Public License for more details.
21412+ *
21413+ * You should have received a copy of the GNU General Public License
21414+ * along with this program; if not, write to the Free Software
21415+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21416+ */
21417+
21418+/*
21419+ * mount and super_block operations
21420+ */
21421+
21422+#include <linux/buffer_head.h>
e49829fe 21423+#include <linux/jiffies.h>
dece6358 21424+#include <linux/module.h>
1facf9fc 21425+#include <linux/seq_file.h>
21426+#include <linux/statfs.h>
7f207e10
AM
21427+#include <linux/vmalloc.h>
21428+#include <linux/writeback.h>
1facf9fc 21429+#include "aufs.h"
21430+
21431+/*
21432+ * super_operations
21433+ */
21434+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
21435+{
21436+ struct au_icntnr *c;
21437+
21438+ c = au_cache_alloc_icntnr();
21439+ if (c) {
027c5e7a 21440+ au_icntnr_init(c);
1facf9fc 21441+ c->vfs_inode.i_version = 1; /* sigen(sb); */
21442+ c->iinfo.ii_hinode = NULL;
21443+ return &c->vfs_inode;
21444+ }
21445+ return NULL;
21446+}
21447+
027c5e7a
AM
21448+static void aufs_destroy_inode_cb(struct rcu_head *head)
21449+{
21450+ struct inode *inode = container_of(head, struct inode, i_rcu);
21451+
21452+ INIT_LIST_HEAD(&inode->i_dentry);
21453+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
21454+}
21455+
1facf9fc 21456+static void aufs_destroy_inode(struct inode *inode)
21457+{
21458+ au_iinfo_fin(inode);
027c5e7a 21459+ call_rcu(&inode->i_rcu, aufs_destroy_inode_cb);
1facf9fc 21460+}
21461+
21462+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
21463+{
21464+ struct inode *inode;
21465+ int err;
21466+
21467+ inode = iget_locked(sb, ino);
21468+ if (unlikely(!inode)) {
21469+ inode = ERR_PTR(-ENOMEM);
21470+ goto out;
21471+ }
21472+ if (!(inode->i_state & I_NEW))
21473+ goto out;
21474+
21475+ err = au_xigen_new(inode);
21476+ if (!err)
21477+ err = au_iinfo_init(inode);
21478+ if (!err)
21479+ inode->i_version++;
21480+ else {
21481+ iget_failed(inode);
21482+ inode = ERR_PTR(err);
21483+ }
21484+
4f0767ce 21485+out:
1facf9fc 21486+ /* never return NULL */
21487+ AuDebugOn(!inode);
21488+ AuTraceErrPtr(inode);
21489+ return inode;
21490+}
21491+
21492+/* lock free root dinfo */
21493+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
21494+{
21495+ int err;
21496+ aufs_bindex_t bindex, bend;
21497+ struct path path;
4a4d8108 21498+ struct au_hdentry *hdp;
1facf9fc 21499+ struct au_branch *br;
21500+
21501+ err = 0;
21502+ bend = au_sbend(sb);
4a4d8108 21503+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 21504+ for (bindex = 0; !err && bindex <= bend; bindex++) {
21505+ br = au_sbr(sb, bindex);
21506+ path.mnt = br->br_mnt;
4a4d8108 21507+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 21508+ err = au_seq_path(seq, &path);
21509+ if (err > 0)
21510+ err = seq_printf(seq, "=%s",
21511+ au_optstr_br_perm(br->br_perm));
21512+ if (!err && bindex != bend)
21513+ err = seq_putc(seq, ':');
21514+ }
21515+
21516+ return err;
21517+}
21518+
21519+static void au_show_wbr_create(struct seq_file *m, int v,
21520+ struct au_sbinfo *sbinfo)
21521+{
21522+ const char *pat;
21523+
dece6358
AM
21524+ AuRwMustAnyLock(&sbinfo->si_rwsem);
21525+
1facf9fc 21526+ seq_printf(m, ",create=");
21527+ pat = au_optstr_wbr_create(v);
21528+ switch (v) {
21529+ case AuWbrCreate_TDP:
21530+ case AuWbrCreate_RR:
21531+ case AuWbrCreate_MFS:
21532+ case AuWbrCreate_PMFS:
21533+ seq_printf(m, pat);
21534+ break;
21535+ case AuWbrCreate_MFSV:
21536+ seq_printf(m, /*pat*/"mfs:%lu",
e49829fe
JR
21537+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
21538+ / MSEC_PER_SEC);
1facf9fc 21539+ break;
21540+ case AuWbrCreate_PMFSV:
21541+ seq_printf(m, /*pat*/"pmfs:%lu",
e49829fe
JR
21542+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
21543+ / MSEC_PER_SEC);
1facf9fc 21544+ break;
21545+ case AuWbrCreate_MFSRR:
21546+ seq_printf(m, /*pat*/"mfsrr:%llu",
21547+ sbinfo->si_wbr_mfs.mfsrr_watermark);
21548+ break;
21549+ case AuWbrCreate_MFSRRV:
21550+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
21551+ sbinfo->si_wbr_mfs.mfsrr_watermark,
e49829fe
JR
21552+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
21553+ / MSEC_PER_SEC);
1facf9fc 21554+ break;
21555+ }
21556+}
21557+
21558+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
21559+{
21560+#ifdef CONFIG_SYSFS
21561+ return 0;
21562+#else
21563+ int err;
21564+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
21565+ aufs_bindex_t bindex, brid;
21566+ struct super_block *sb;
21567+ struct qstr *name;
21568+ struct file *f;
21569+ struct dentry *d, *h_root;
4a4d8108 21570+ struct au_hdentry *hdp;
1facf9fc 21571+
dece6358
AM
21572+ AuRwMustAnyLock(&sbinfo->si_rwsem);
21573+
1facf9fc 21574+ err = 0;
21575+ sb = mnt->mnt_sb;
21576+ f = au_sbi(sb)->si_xib;
21577+ if (!f)
21578+ goto out;
21579+
21580+ /* stop printing the default xino path on the first writable branch */
21581+ h_root = NULL;
21582+ brid = au_xino_brid(sb);
21583+ if (brid >= 0) {
21584+ bindex = au_br_index(sb, brid);
4a4d8108
AM
21585+ hdp = au_di(sb->s_root)->di_hdentry;
21586+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 21587+ }
21588+ d = f->f_dentry;
21589+ name = &d->d_name;
21590+ /* safe ->d_parent because the file is unlinked */
21591+ if (d->d_parent == h_root
21592+ && name->len == len
21593+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
21594+ goto out;
21595+
21596+ seq_puts(seq, ",xino=");
21597+ err = au_xino_path(seq, f);
21598+
4f0767ce 21599+out:
1facf9fc 21600+ return err;
21601+#endif
21602+}
21603+
21604+/* seq_file will re-call me in case of too long string */
21605+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
21606+{
027c5e7a 21607+ int err;
1facf9fc 21608+ unsigned int mnt_flags, v;
21609+ struct super_block *sb;
21610+ struct au_sbinfo *sbinfo;
21611+
21612+#define AuBool(name, str) do { \
21613+ v = au_opt_test(mnt_flags, name); \
21614+ if (v != au_opt_test(AuOpt_Def, name)) \
21615+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
21616+} while (0)
21617+
21618+#define AuStr(name, str) do { \
21619+ v = mnt_flags & AuOptMask_##name; \
21620+ if (v != (AuOpt_Def & AuOptMask_##name)) \
21621+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
21622+} while (0)
21623+
21624+#define AuUInt(name, str, val) do { \
21625+ if (val != AUFS_##name##_DEF) \
21626+ seq_printf(m, "," #str "=%u", val); \
21627+} while (0)
21628+
21629+ /* lock free root dinfo */
21630+ sb = mnt->mnt_sb;
21631+ si_noflush_read_lock(sb);
21632+ sbinfo = au_sbi(sb);
21633+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
21634+
21635+ mnt_flags = au_mntflags(sb);
21636+ if (au_opt_test(mnt_flags, XINO)) {
21637+ err = au_show_xino(m, mnt);
21638+ if (unlikely(err))
21639+ goto out;
21640+ } else
21641+ seq_puts(m, ",noxino");
21642+
21643+ AuBool(TRUNC_XINO, trunc_xino);
21644+ AuStr(UDBA, udba);
dece6358 21645+ AuBool(SHWH, shwh);
1facf9fc 21646+ AuBool(PLINK, plink);
4a4d8108 21647+ AuBool(DIO, dio);
1facf9fc 21648+ /* AuBool(DIRPERM1, dirperm1); */
21649+ /* AuBool(REFROF, refrof); */
21650+
21651+ v = sbinfo->si_wbr_create;
21652+ if (v != AuWbrCreate_Def)
21653+ au_show_wbr_create(m, v, sbinfo);
21654+
21655+ v = sbinfo->si_wbr_copyup;
21656+ if (v != AuWbrCopyup_Def)
21657+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
21658+
21659+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
21660+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
21661+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
21662+
21663+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
21664+
027c5e7a
AM
21665+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
21666+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 21667+
21668+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
21669+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
21670+
21671+ AuBool(SUM, sum);
21672+ /* AuBool(SUM_W, wsum); */
21673+ AuBool(WARN_PERM, warn_perm);
21674+ AuBool(VERBOSE, verbose);
21675+
4f0767ce 21676+out:
1facf9fc 21677+ /* be sure to print "br:" last */
21678+ if (!sysaufs_brs) {
21679+ seq_puts(m, ",br:");
21680+ au_show_brs(m, sb);
21681+ }
21682+ si_read_unlock(sb);
21683+ return 0;
21684+
1facf9fc 21685+#undef AuBool
21686+#undef AuStr
4a4d8108 21687+#undef AuUInt
1facf9fc 21688+}
21689+
21690+/* ---------------------------------------------------------------------- */
21691+
21692+/* sum mode which returns the summation for statfs(2) */
21693+
21694+static u64 au_add_till_max(u64 a, u64 b)
21695+{
21696+ u64 old;
21697+
21698+ old = a;
21699+ a += b;
21700+ if (old < a)
21701+ return a;
21702+ return ULLONG_MAX;
21703+}
21704+
21705+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
21706+{
21707+ int err;
21708+ u64 blocks, bfree, bavail, files, ffree;
21709+ aufs_bindex_t bend, bindex, i;
21710+ unsigned char shared;
7f207e10 21711+ struct path h_path;
1facf9fc 21712+ struct super_block *h_sb;
21713+
21714+ blocks = 0;
21715+ bfree = 0;
21716+ bavail = 0;
21717+ files = 0;
21718+ ffree = 0;
21719+
21720+ err = 0;
21721+ bend = au_sbend(sb);
21722+ for (bindex = bend; bindex >= 0; bindex--) {
7f207e10
AM
21723+ h_path.mnt = au_sbr_mnt(sb, bindex);
21724+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 21725+ shared = 0;
21726+ for (i = bindex + 1; !shared && i <= bend; i++)
21727+ shared = (au_sbr_sb(sb, i) == h_sb);
21728+ if (shared)
21729+ continue;
21730+
21731+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
21732+ h_path.dentry = h_path.mnt->mnt_root;
21733+ err = vfs_statfs(&h_path, buf);
1facf9fc 21734+ if (unlikely(err))
21735+ goto out;
21736+
21737+ blocks = au_add_till_max(blocks, buf->f_blocks);
21738+ bfree = au_add_till_max(bfree, buf->f_bfree);
21739+ bavail = au_add_till_max(bavail, buf->f_bavail);
21740+ files = au_add_till_max(files, buf->f_files);
21741+ ffree = au_add_till_max(ffree, buf->f_ffree);
21742+ }
21743+
21744+ buf->f_blocks = blocks;
21745+ buf->f_bfree = bfree;
21746+ buf->f_bavail = bavail;
21747+ buf->f_files = files;
21748+ buf->f_ffree = ffree;
21749+
4f0767ce 21750+out:
1facf9fc 21751+ return err;
21752+}
21753+
21754+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
21755+{
21756+ int err;
7f207e10 21757+ struct path h_path;
1facf9fc 21758+ struct super_block *sb;
21759+
21760+ /* lock free root dinfo */
21761+ sb = dentry->d_sb;
21762+ si_noflush_read_lock(sb);
7f207e10 21763+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 21764+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
21765+ h_path.mnt = au_sbr_mnt(sb, 0);
21766+ h_path.dentry = h_path.mnt->mnt_root;
21767+ err = vfs_statfs(&h_path, buf);
21768+ } else
1facf9fc 21769+ err = au_statfs_sum(sb, buf);
21770+ si_read_unlock(sb);
21771+
21772+ if (!err) {
21773+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 21774+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 21775+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
21776+ }
21777+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
21778+
21779+ return err;
21780+}
21781+
21782+/* ---------------------------------------------------------------------- */
21783+
1facf9fc 21784+/* final actions when unmounting a file system */
21785+static void aufs_put_super(struct super_block *sb)
21786+{
21787+ struct au_sbinfo *sbinfo;
21788+
21789+ sbinfo = au_sbi(sb);
21790+ if (!sbinfo)
21791+ return;
21792+
1facf9fc 21793+ dbgaufs_si_fin(sbinfo);
21794+ kobject_put(&sbinfo->si_kobj);
21795+}
21796+
21797+/* ---------------------------------------------------------------------- */
21798+
7f207e10
AM
21799+void au_array_free(void *array)
21800+{
21801+ if (array) {
21802+ if (!is_vmalloc_addr(array))
21803+ kfree(array);
21804+ else
21805+ vfree(array);
21806+ }
21807+}
21808+
21809+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
21810+{
21811+ void *array;
21812+ unsigned long long n;
21813+
21814+ array = NULL;
21815+ n = 0;
21816+ if (!*hint)
21817+ goto out;
21818+
21819+ if (*hint > ULLONG_MAX / sizeof(array)) {
21820+ array = ERR_PTR(-EMFILE);
21821+ pr_err("hint %llu\n", *hint);
21822+ goto out;
21823+ }
21824+
21825+ array = kmalloc(sizeof(array) * *hint, GFP_NOFS);
21826+ if (unlikely(!array))
21827+ array = vmalloc(sizeof(array) * *hint);
21828+ if (unlikely(!array)) {
21829+ array = ERR_PTR(-ENOMEM);
21830+ goto out;
21831+ }
21832+
21833+ n = cb(array, *hint, arg);
21834+ AuDebugOn(n > *hint);
21835+
21836+out:
21837+ *hint = n;
21838+ return array;
21839+}
21840+
21841+static unsigned long long au_iarray_cb(void *a,
21842+ unsigned long long max __maybe_unused,
21843+ void *arg)
21844+{
21845+ unsigned long long n;
21846+ struct inode **p, *inode;
21847+ struct list_head *head;
21848+
21849+ n = 0;
21850+ p = a;
21851+ head = arg;
21852+ spin_lock(&inode_lock);
21853+ list_for_each_entry(inode, head, i_sb_list) {
21854+ if (!is_bad_inode(inode)
21855+ && au_ii(inode)->ii_bstart >= 0) {
21856+ au_igrab(inode);
21857+ *p++ = inode;
21858+ n++;
21859+ AuDebugOn(n > max);
21860+ }
21861+ }
21862+ spin_unlock(&inode_lock);
21863+
21864+ return n;
21865+}
21866+
21867+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
21868+{
21869+ *max = atomic_long_read(&au_sbi(sb)->si_ninodes);
21870+ return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
21871+}
21872+
21873+void au_iarray_free(struct inode **a, unsigned long long max)
21874+{
21875+ unsigned long long ull;
21876+
21877+ for (ull = 0; ull < max; ull++)
21878+ iput(a[ull]);
21879+ au_array_free(a);
21880+}
21881+
21882+/* ---------------------------------------------------------------------- */
21883+
1facf9fc 21884+/*
21885+ * refresh dentry and inode at remount time.
21886+ */
027c5e7a
AM
21887+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
21888+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
21889+ struct dentry *parent)
1facf9fc 21890+{
21891+ int err;
1facf9fc 21892+
21893+ di_write_lock_child(dentry);
1facf9fc 21894+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
21895+ err = au_refresh_dentry(dentry, parent);
21896+ if (!err && dir_flags)
21897+ au_hn_reset(dentry->d_inode, dir_flags);
1facf9fc 21898+ di_read_unlock(parent, AuLock_IR);
1facf9fc 21899+ di_write_unlock(dentry);
21900+
21901+ return err;
21902+}
21903+
027c5e7a
AM
21904+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
21905+ struct au_sbinfo *sbinfo,
21906+ const unsigned int dir_flags)
1facf9fc 21907+{
027c5e7a
AM
21908+ int err;
21909+ struct dentry *parent;
21910+ struct inode *inode;
21911+
21912+ err = 0;
21913+ parent = dget_parent(dentry);
21914+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
21915+ inode = dentry->d_inode;
21916+ if (inode) {
21917+ if (!S_ISDIR(inode->i_mode))
21918+ err = au_do_refresh(dentry, /*dir_flags*/0,
21919+ parent);
21920+ else {
21921+ err = au_do_refresh(dentry, dir_flags, parent);
21922+ if (unlikely(err))
21923+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
21924+ }
21925+ } else
21926+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
21927+ AuDbgDentry(dentry);
21928+ }
21929+ dput(parent);
21930+
21931+ AuTraceErr(err);
21932+ return err;
1facf9fc 21933+}
21934+
027c5e7a 21935+static int au_refresh_d(struct super_block *sb)
1facf9fc 21936+{
21937+ int err, i, j, ndentry, e;
027c5e7a 21938+ unsigned int sigen;
1facf9fc 21939+ struct au_dcsub_pages dpages;
21940+ struct au_dpage *dpage;
027c5e7a
AM
21941+ struct dentry **dentries, *d;
21942+ struct au_sbinfo *sbinfo;
21943+ struct dentry *root = sb->s_root;
21944+ const unsigned int dir_flags = au_hi_flags(root->d_inode, /*isdir*/1);
1facf9fc 21945+
027c5e7a
AM
21946+ err = au_dpages_init(&dpages, GFP_NOFS);
21947+ if (unlikely(err))
1facf9fc 21948+ goto out;
027c5e7a
AM
21949+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
21950+ if (unlikely(err))
1facf9fc 21951+ goto out_dpages;
1facf9fc 21952+
027c5e7a
AM
21953+ sigen = au_sigen(sb);
21954+ sbinfo = au_sbi(sb);
21955+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 21956+ dpage = dpages.dpages + i;
21957+ dentries = dpage->dentries;
21958+ ndentry = dpage->ndentry;
027c5e7a 21959+ for (j = 0; j < ndentry; j++) {
1facf9fc 21960+ d = dentries[j];
027c5e7a
AM
21961+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags);
21962+ if (unlikely(e && !err))
21963+ err = e;
21964+ /* go on even err */
1facf9fc 21965+ }
21966+ }
21967+
4f0767ce 21968+out_dpages:
1facf9fc 21969+ au_dpages_free(&dpages);
4f0767ce 21970+out:
1facf9fc 21971+ return err;
21972+}
21973+
027c5e7a 21974+static int au_refresh_i(struct super_block *sb)
1facf9fc 21975+{
027c5e7a
AM
21976+ int err, e;
21977+ unsigned int sigen;
21978+ unsigned long long max, ull;
21979+ struct inode *inode, **array;
1facf9fc 21980+
027c5e7a
AM
21981+ array = au_iarray_alloc(sb, &max);
21982+ err = PTR_ERR(array);
21983+ if (IS_ERR(array))
21984+ goto out;
1facf9fc 21985+
21986+ err = 0;
027c5e7a
AM
21987+ sigen = au_sigen(sb);
21988+ for (ull = 0; ull < max; ull++) {
21989+ inode = array[ull];
21990+ if (au_iigen(inode) != sigen) {
1facf9fc 21991+ ii_write_lock_child(inode);
027c5e7a 21992+ e = au_refresh_hinode_self(inode);
1facf9fc 21993+ ii_write_unlock(inode);
21994+ if (unlikely(e)) {
027c5e7a 21995+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 21996+ if (!err)
21997+ err = e;
21998+ /* go on even if err */
21999+ }
22000+ }
1facf9fc 22001+ }
22002+
027c5e7a 22003+ au_iarray_free(array, max);
1facf9fc 22004+
4f0767ce 22005+out:
1facf9fc 22006+ return err;
22007+}
22008+
027c5e7a 22009+static void au_remount_refresh(struct super_block *sb)
1facf9fc 22010+{
027c5e7a
AM
22011+ int err, e;
22012+ unsigned int udba;
22013+ aufs_bindex_t bindex, bend;
1facf9fc 22014+ struct dentry *root;
22015+ struct inode *inode;
027c5e7a 22016+ struct au_branch *br;
1facf9fc 22017+
22018+ au_sigen_inc(sb);
027c5e7a 22019+ au_fclr_si(au_sbi(sb), FAILED_REFRESH_DIR);
1facf9fc 22020+
22021+ root = sb->s_root;
22022+ DiMustNoWaiters(root);
22023+ inode = root->d_inode;
22024+ IiMustNoWaiters(inode);
1facf9fc 22025+
027c5e7a
AM
22026+ udba = au_opt_udba(sb);
22027+ bend = au_sbend(sb);
22028+ for (bindex = 0; bindex <= bend; bindex++) {
22029+ br = au_sbr(sb, bindex);
22030+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 22031+ if (unlikely(err))
027c5e7a
AM
22032+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
22033+ bindex, err);
22034+ /* go on even if err */
1facf9fc 22035+ }
027c5e7a 22036+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 22037+
027c5e7a
AM
22038+ di_write_unlock(root);
22039+ err = au_refresh_d(sb);
22040+ e = au_refresh_i(sb);
22041+ if (unlikely(e && !err))
22042+ err = e;
1facf9fc 22043+ /* aufs_write_lock() calls ..._child() */
22044+ di_write_lock_child(root);
027c5e7a
AM
22045+
22046+ au_cpup_attr_all(inode, /*force*/1);
22047+
22048+ if (unlikely(err))
22049+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 22050+}
22051+
22052+/* stop extra interpretation of errno in mount(8), and strange error messages */
22053+static int cvt_err(int err)
22054+{
22055+ AuTraceErr(err);
22056+
22057+ switch (err) {
22058+ case -ENOENT:
22059+ case -ENOTDIR:
22060+ case -EEXIST:
22061+ case -EIO:
22062+ err = -EINVAL;
22063+ }
22064+ return err;
22065+}
22066+
22067+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
22068+{
4a4d8108
AM
22069+ int err, do_dx;
22070+ unsigned int mntflags;
1facf9fc 22071+ struct au_opts opts;
22072+ struct dentry *root;
22073+ struct inode *inode;
22074+ struct au_sbinfo *sbinfo;
22075+
22076+ err = 0;
22077+ root = sb->s_root;
22078+ if (!data || !*data) {
e49829fe
JR
22079+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
22080+ if (!err) {
22081+ di_write_lock_child(root);
22082+ err = au_opts_verify(sb, *flags, /*pending*/0);
22083+ aufs_write_unlock(root);
22084+ }
1facf9fc 22085+ goto out;
22086+ }
22087+
22088+ err = -ENOMEM;
22089+ memset(&opts, 0, sizeof(opts));
22090+ opts.opt = (void *)__get_free_page(GFP_NOFS);
22091+ if (unlikely(!opts.opt))
22092+ goto out;
22093+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
22094+ opts.flags = AuOpts_REMOUNT;
22095+ opts.sb_flags = *flags;
22096+
22097+ /* parse it before aufs lock */
22098+ err = au_opts_parse(sb, data, &opts);
22099+ if (unlikely(err))
22100+ goto out_opts;
22101+
22102+ sbinfo = au_sbi(sb);
22103+ inode = root->d_inode;
22104+ mutex_lock(&inode->i_mutex);
e49829fe
JR
22105+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
22106+ if (unlikely(err))
22107+ goto out_mtx;
22108+ di_write_lock_child(root);
1facf9fc 22109+
22110+ /* au_opts_remount() may return an error */
22111+ err = au_opts_remount(sb, &opts);
22112+ au_opts_free(&opts);
22113+
027c5e7a
AM
22114+ if (au_ftest_opts(opts.flags, REFRESH))
22115+ au_remount_refresh(sb);
1facf9fc 22116+
4a4d8108
AM
22117+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
22118+ mntflags = au_mntflags(sb);
22119+ do_dx = !!au_opt_test(mntflags, DIO);
22120+ au_dy_arefresh(do_dx);
22121+ }
22122+
1facf9fc 22123+ aufs_write_unlock(root);
953406b4 22124+
e49829fe
JR
22125+out_mtx:
22126+ mutex_unlock(&inode->i_mutex);
4f0767ce 22127+out_opts:
1facf9fc 22128+ free_page((unsigned long)opts.opt);
4f0767ce 22129+out:
1facf9fc 22130+ err = cvt_err(err);
22131+ AuTraceErr(err);
22132+ return err;
22133+}
22134+
4a4d8108 22135+static const struct super_operations aufs_sop = {
1facf9fc 22136+ .alloc_inode = aufs_alloc_inode,
22137+ .destroy_inode = aufs_destroy_inode,
b752ccd1 22138+ /* always deleting, no clearing */
1facf9fc 22139+ .drop_inode = generic_delete_inode,
22140+ .show_options = aufs_show_options,
22141+ .statfs = aufs_statfs,
22142+ .put_super = aufs_put_super,
22143+ .remount_fs = aufs_remount_fs
22144+};
22145+
22146+/* ---------------------------------------------------------------------- */
22147+
22148+static int alloc_root(struct super_block *sb)
22149+{
22150+ int err;
22151+ struct inode *inode;
22152+ struct dentry *root;
22153+
22154+ err = -ENOMEM;
22155+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
22156+ err = PTR_ERR(inode);
22157+ if (IS_ERR(inode))
22158+ goto out;
22159+
22160+ inode->i_op = &aufs_dir_iop;
22161+ inode->i_fop = &aufs_dir_fop;
22162+ inode->i_mode = S_IFDIR;
22163+ inode->i_nlink = 2;
22164+ unlock_new_inode(inode);
22165+
22166+ root = d_alloc_root(inode);
22167+ if (unlikely(!root))
22168+ goto out_iput;
22169+ err = PTR_ERR(root);
22170+ if (IS_ERR(root))
22171+ goto out_iput;
22172+
4a4d8108 22173+ err = au_di_init(root);
1facf9fc 22174+ if (!err) {
22175+ sb->s_root = root;
22176+ return 0; /* success */
22177+ }
22178+ dput(root);
22179+ goto out; /* do not iput */
22180+
4f0767ce 22181+out_iput:
1facf9fc 22182+ iget_failed(inode);
4f0767ce 22183+out:
1facf9fc 22184+ return err;
22185+
22186+}
22187+
22188+static int aufs_fill_super(struct super_block *sb, void *raw_data,
22189+ int silent __maybe_unused)
22190+{
22191+ int err;
22192+ struct au_opts opts;
22193+ struct dentry *root;
22194+ struct inode *inode;
22195+ char *arg = raw_data;
22196+
22197+ if (unlikely(!arg || !*arg)) {
22198+ err = -EINVAL;
4a4d8108 22199+ pr_err("no arg\n");
1facf9fc 22200+ goto out;
22201+ }
22202+
22203+ err = -ENOMEM;
22204+ memset(&opts, 0, sizeof(opts));
22205+ opts.opt = (void *)__get_free_page(GFP_NOFS);
22206+ if (unlikely(!opts.opt))
22207+ goto out;
22208+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
22209+ opts.sb_flags = sb->s_flags;
22210+
22211+ err = au_si_alloc(sb);
22212+ if (unlikely(err))
22213+ goto out_opts;
22214+
22215+ /* all timestamps always follow the ones on the branch */
22216+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
22217+ sb->s_op = &aufs_sop;
027c5e7a 22218+ sb->s_d_op = &aufs_dop;
1facf9fc 22219+ sb->s_magic = AUFS_SUPER_MAGIC;
22220+ sb->s_maxbytes = 0;
22221+ au_export_init(sb);
22222+
22223+ err = alloc_root(sb);
22224+ if (unlikely(err)) {
22225+ si_write_unlock(sb);
22226+ goto out_info;
22227+ }
22228+ root = sb->s_root;
22229+ inode = root->d_inode;
22230+
22231+ /*
22232+ * actually we can parse options regardless aufs lock here.
22233+ * but at remount time, parsing must be done before aufs lock.
22234+ * so we follow the same rule.
22235+ */
22236+ ii_write_lock_parent(inode);
22237+ aufs_write_unlock(root);
22238+ err = au_opts_parse(sb, arg, &opts);
22239+ if (unlikely(err))
22240+ goto out_root;
22241+
22242+ /* lock vfs_inode first, then aufs. */
22243+ mutex_lock(&inode->i_mutex);
1facf9fc 22244+ aufs_write_lock(root);
22245+ err = au_opts_mount(sb, &opts);
22246+ au_opts_free(&opts);
1facf9fc 22247+ aufs_write_unlock(root);
22248+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
22249+ if (!err)
22250+ goto out_opts; /* success */
1facf9fc 22251+
4f0767ce 22252+out_root:
1facf9fc 22253+ dput(root);
22254+ sb->s_root = NULL;
4f0767ce 22255+out_info:
1facf9fc 22256+ kobject_put(&au_sbi(sb)->si_kobj);
22257+ sb->s_fs_info = NULL;
4f0767ce 22258+out_opts:
1facf9fc 22259+ free_page((unsigned long)opts.opt);
4f0767ce 22260+out:
1facf9fc 22261+ AuTraceErr(err);
22262+ err = cvt_err(err);
22263+ AuTraceErr(err);
22264+ return err;
22265+}
22266+
22267+/* ---------------------------------------------------------------------- */
22268+
027c5e7a
AM
22269+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
22270+ const char *dev_name __maybe_unused,
22271+ void *raw_data)
1facf9fc 22272+{
027c5e7a 22273+ struct dentry *root;
1facf9fc 22274+ struct super_block *sb;
22275+
22276+ /* all timestamps always follow the ones on the branch */
22277+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
22278+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
22279+ if (IS_ERR(root))
22280+ goto out;
22281+
22282+ sb = root->d_sb;
22283+ si_write_lock(sb, !AuLock_FLUSH);
22284+ sysaufs_brs_add(sb, 0);
22285+ si_write_unlock(sb);
22286+ au_sbilist_add(sb);
22287+
22288+out:
22289+ return root;
1facf9fc 22290+}
22291+
e49829fe
JR
22292+static void aufs_kill_sb(struct super_block *sb)
22293+{
22294+ struct au_sbinfo *sbinfo;
22295+
22296+ sbinfo = au_sbi(sb);
22297+ if (sbinfo) {
22298+ au_sbilist_del(sb);
22299+ aufs_write_lock(sb->s_root);
22300+ if (sbinfo->si_wbr_create_ops->fin)
22301+ sbinfo->si_wbr_create_ops->fin(sb);
22302+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
22303+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
027c5e7a 22304+ au_remount_refresh(sb);
e49829fe
JR
22305+ }
22306+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
22307+ au_plink_put(sb, /*verbose*/1);
22308+ au_xino_clr(sb);
22309+ aufs_write_unlock(sb->s_root);
e49829fe
JR
22310+ au_nwt_flush(&sbinfo->si_nowait);
22311+ }
22312+ generic_shutdown_super(sb);
22313+}
22314+
1facf9fc 22315+struct file_system_type aufs_fs_type = {
22316+ .name = AUFS_FSTYPE,
22317+ .fs_flags =
22318+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
22319+ | FS_REVAL_DOT, /* for NFS branch and udba */
027c5e7a 22320+ .mount = aufs_mount,
e49829fe 22321+ .kill_sb = aufs_kill_sb,
1facf9fc 22322+ /* no need to __module_get() and module_put(). */
22323+ .owner = THIS_MODULE,
22324+};
7f207e10
AM
22325diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
22326--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
22327+++ linux/fs/aufs/super.h 2011-03-21 20:22:06.860602399 +0100
22328@@ -0,0 +1,527 @@
1facf9fc 22329+/*
027c5e7a 22330+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 22331+ *
22332+ * This program, aufs is free software; you can redistribute it and/or modify
22333+ * it under the terms of the GNU General Public License as published by
22334+ * the Free Software Foundation; either version 2 of the License, or
22335+ * (at your option) any later version.
dece6358
AM
22336+ *
22337+ * This program is distributed in the hope that it will be useful,
22338+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22339+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22340+ * GNU General Public License for more details.
22341+ *
22342+ * You should have received a copy of the GNU General Public License
22343+ * along with this program; if not, write to the Free Software
22344+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22345+ */
22346+
22347+/*
22348+ * super_block operations
22349+ */
22350+
22351+#ifndef __AUFS_SUPER_H__
22352+#define __AUFS_SUPER_H__
22353+
22354+#ifdef __KERNEL__
22355+
22356+#include <linux/fs.h>
1facf9fc 22357+#include <linux/aufs_type.h>
22358+#include "rwsem.h"
22359+#include "spl.h"
22360+#include "wkq.h"
22361+
22362+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
22363+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
22364+ loff_t *);
22365+
22366+/* policies to select one among multiple writable branches */
22367+struct au_wbr_copyup_operations {
22368+ int (*copyup)(struct dentry *dentry);
22369+};
22370+
22371+struct au_wbr_create_operations {
22372+ int (*create)(struct dentry *dentry, int isdir);
22373+ int (*init)(struct super_block *sb);
22374+ int (*fin)(struct super_block *sb);
22375+};
22376+
22377+struct au_wbr_mfs {
22378+ struct mutex mfs_lock; /* protect this structure */
22379+ unsigned long mfs_jiffy;
22380+ unsigned long mfs_expire;
22381+ aufs_bindex_t mfs_bindex;
22382+
22383+ unsigned long long mfsrr_bytes;
22384+ unsigned long long mfsrr_watermark;
22385+};
22386+
1facf9fc 22387+struct au_branch;
22388+struct au_sbinfo {
22389+ /* nowait tasks in the system-wide workqueue */
22390+ struct au_nowait_tasks si_nowait;
22391+
b752ccd1
AM
22392+ /*
22393+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
22394+ * rwsem for au_sbinfo is necessary.
22395+ */
dece6358 22396+ struct au_rwsem si_rwsem;
1facf9fc 22397+
b752ccd1
AM
22398+ /* prevent recursive locking in deleting inode */
22399+ struct {
22400+ unsigned long *bitmap;
22401+ spinlock_t tree_lock;
22402+ struct radix_tree_root tree;
22403+ } au_si_pid;
22404+
7f207e10
AM
22405+ /*
22406+ * dirty approach to protect sb->sb_inodes and ->s_files from remount.
22407+ */
22408+ atomic_long_t si_ninodes, si_nfiles;
22409+
1facf9fc 22410+ /* branch management */
22411+ unsigned int si_generation;
22412+
22413+ /* see above flags */
22414+ unsigned char au_si_status;
22415+
22416+ aufs_bindex_t si_bend;
7f207e10
AM
22417+
22418+ /* dirty trick to keep br_id plus */
22419+ unsigned int si_last_br_id :
22420+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 22421+ struct au_branch **si_branch;
22422+
22423+ /* policy to select a writable branch */
22424+ unsigned char si_wbr_copyup;
22425+ unsigned char si_wbr_create;
22426+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
22427+ struct au_wbr_create_operations *si_wbr_create_ops;
22428+
22429+ /* round robin */
22430+ atomic_t si_wbr_rr_next;
22431+
22432+ /* most free space */
22433+ struct au_wbr_mfs si_wbr_mfs;
22434+
22435+ /* mount flags */
22436+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
22437+ unsigned int si_mntflags;
22438+
22439+ /* external inode number (bitmap and translation table) */
22440+ au_readf_t si_xread;
22441+ au_writef_t si_xwrite;
22442+ struct file *si_xib;
22443+ struct mutex si_xib_mtx; /* protect xib members */
22444+ unsigned long *si_xib_buf;
22445+ unsigned long si_xib_last_pindex;
22446+ int si_xib_next_bit;
22447+ aufs_bindex_t si_xino_brid;
22448+ /* reserved for future use */
22449+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
22450+
22451+#ifdef CONFIG_AUFS_EXPORT
22452+ /* i_generation */
22453+ struct file *si_xigen;
22454+ atomic_t si_xigen_next;
22455+#endif
22456+
22457+ /* vdir parameters */
e49829fe 22458+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 22459+ unsigned int si_rdblk; /* deblk size */
22460+ unsigned int si_rdhash; /* hash size */
22461+
22462+ /*
22463+ * If the number of whiteouts are larger than si_dirwh, leave all of
22464+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
22465+ * future fsck.aufs or kernel thread will remove them later.
22466+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
22467+ */
22468+ unsigned int si_dirwh;
22469+
22470+ /*
22471+ * rename(2) a directory with all children.
22472+ */
22473+ /* reserved for future use */
22474+ /* int si_rendir; */
22475+
22476+ /* pseudo_link list */
22477+ struct au_splhead si_plink;
22478+ wait_queue_head_t si_plink_wq;
4a4d8108 22479+ spinlock_t si_plink_maint_lock;
e49829fe 22480+ pid_t si_plink_maint_pid;
1facf9fc 22481+
22482+ /*
22483+ * sysfs and lifetime management.
22484+ * this is not a small structure and it may be a waste of memory in case
22485+ * of sysfs is disabled, particulary when many aufs-es are mounted.
22486+ * but using sysfs is majority.
22487+ */
22488+ struct kobject si_kobj;
22489+#ifdef CONFIG_DEBUG_FS
22490+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
22491+#ifdef CONFIG_AUFS_EXPORT
22492+ struct dentry *si_dbgaufs_xigen;
22493+#endif
22494+#endif
22495+
e49829fe
JR
22496+#ifdef CONFIG_AUFS_SBILIST
22497+ struct list_head si_list;
22498+#endif
22499+
1facf9fc 22500+ /* dirty, necessary for unmounting, sysfs and sysrq */
22501+ struct super_block *si_sb;
22502+};
22503+
dece6358
AM
22504+/* sbinfo status flags */
22505+/*
22506+ * set true when refresh_dirs() failed at remount time.
22507+ * then try refreshing dirs at access time again.
22508+ * if it is false, refreshing dirs at access time is unnecesary
22509+ */
027c5e7a 22510+#define AuSi_FAILED_REFRESH_DIR 1
dece6358
AM
22511+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
22512+ unsigned int flag)
22513+{
22514+ AuRwMustAnyLock(&sbi->si_rwsem);
22515+ return sbi->au_si_status & flag;
22516+}
22517+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
22518+#define au_fset_si(sbinfo, name) do { \
22519+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
22520+ (sbinfo)->au_si_status |= AuSi_##name; \
22521+} while (0)
22522+#define au_fclr_si(sbinfo, name) do { \
22523+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
22524+ (sbinfo)->au_si_status &= ~AuSi_##name; \
22525+} while (0)
22526+
1facf9fc 22527+/* ---------------------------------------------------------------------- */
22528+
22529+/* policy to select one among writable branches */
4a4d8108
AM
22530+#define AuWbrCopyup(sbinfo, ...) \
22531+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
22532+#define AuWbrCreate(sbinfo, ...) \
22533+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 22534+
22535+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
22536+#define AuLock_DW 1 /* write-lock dentry */
22537+#define AuLock_IR (1 << 1) /* read-lock inode */
22538+#define AuLock_IW (1 << 2) /* write-lock inode */
22539+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
22540+#define AuLock_DIR (1 << 4) /* target is a dir */
e49829fe
JR
22541+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
22542+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 22543+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 22544+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
22545+#define au_fset_lock(flags, name) \
22546+ do { (flags) |= AuLock_##name; } while (0)
22547+#define au_fclr_lock(flags, name) \
22548+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 22549+
22550+/* ---------------------------------------------------------------------- */
22551+
22552+/* super.c */
22553+extern struct file_system_type aufs_fs_type;
22554+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
7f207e10
AM
22555+typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max,
22556+ void *arg);
22557+void au_array_free(void *array);
22558+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg);
22559+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
22560+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 22561+
22562+/* sbinfo.c */
22563+void au_si_free(struct kobject *kobj);
22564+int au_si_alloc(struct super_block *sb);
22565+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
22566+
22567+unsigned int au_sigen_inc(struct super_block *sb);
22568+aufs_bindex_t au_new_br_id(struct super_block *sb);
22569+
e49829fe
JR
22570+int si_read_lock(struct super_block *sb, int flags);
22571+int si_write_lock(struct super_block *sb, int flags);
22572+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 22573+void aufs_read_unlock(struct dentry *dentry, int flags);
22574+void aufs_write_lock(struct dentry *dentry);
22575+void aufs_write_unlock(struct dentry *dentry);
e49829fe 22576+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 22577+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
22578+
b752ccd1
AM
22579+int si_pid_test_slow(struct super_block *sb);
22580+void si_pid_set_slow(struct super_block *sb);
22581+void si_pid_clr_slow(struct super_block *sb);
22582+
1facf9fc 22583+/* wbr_policy.c */
22584+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
22585+extern struct au_wbr_create_operations au_wbr_create_ops[];
22586+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
22587+
22588+/* ---------------------------------------------------------------------- */
22589+
22590+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
22591+{
22592+ return sb->s_fs_info;
22593+}
22594+
22595+/* ---------------------------------------------------------------------- */
22596+
22597+#ifdef CONFIG_AUFS_EXPORT
22598+void au_export_init(struct super_block *sb);
22599+
b752ccd1 22600+static inline int au_test_nfsd(void)
1facf9fc 22601+{
b752ccd1
AM
22602+ struct task_struct *tsk = current;
22603+
22604+ return (tsk->flags & PF_KTHREAD)
22605+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 22606+}
22607+
b752ccd1 22608+void au_xigen_inc(struct inode *inode);
1facf9fc 22609+int au_xigen_new(struct inode *inode);
22610+int au_xigen_set(struct super_block *sb, struct file *base);
22611+void au_xigen_clr(struct super_block *sb);
22612+
22613+static inline int au_busy_or_stale(void)
22614+{
b752ccd1 22615+ if (!au_test_nfsd())
1facf9fc 22616+ return -EBUSY;
22617+ return -ESTALE;
22618+}
22619+#else
4a4d8108 22620+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
22621+AuStubInt0(au_test_nfsd, void)
22622+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
22623+AuStubInt0(au_xigen_new, struct inode *inode)
22624+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
22625+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 22626+static inline int au_busy_or_stale(void)
22627+{
22628+ return -EBUSY;
22629+}
22630+#endif /* CONFIG_AUFS_EXPORT */
22631+
22632+/* ---------------------------------------------------------------------- */
22633+
e49829fe
JR
22634+#ifdef CONFIG_AUFS_SBILIST
22635+/* module.c */
22636+extern struct au_splhead au_sbilist;
22637+
22638+static inline void au_sbilist_init(void)
22639+{
22640+ au_spl_init(&au_sbilist);
22641+}
22642+
22643+static inline void au_sbilist_add(struct super_block *sb)
22644+{
22645+ au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
22646+}
22647+
22648+static inline void au_sbilist_del(struct super_block *sb)
22649+{
22650+ au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
22651+}
22652+#else
22653+AuStubVoid(au_sbilist_init, void)
22654+AuStubVoid(au_sbilist_add, struct super_block*)
22655+AuStubVoid(au_sbilist_del, struct super_block*)
22656+#endif
22657+
22658+/* ---------------------------------------------------------------------- */
22659+
1facf9fc 22660+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
22661+{
dece6358
AM
22662+ /*
22663+ * This function is a dynamic '__init' fucntion actually,
22664+ * so the tiny check for si_rwsem is unnecessary.
22665+ */
22666+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 22667+#ifdef CONFIG_DEBUG_FS
22668+ sbinfo->si_dbgaufs = NULL;
22669+ sbinfo->si_dbgaufs_xib = NULL;
22670+#ifdef CONFIG_AUFS_EXPORT
22671+ sbinfo->si_dbgaufs_xigen = NULL;
22672+#endif
22673+#endif
22674+}
22675+
22676+/* ---------------------------------------------------------------------- */
22677+
b752ccd1
AM
22678+static inline pid_t si_pid_bit(void)
22679+{
22680+ /* the origin of pid is 1, but the bitmap's is 0 */
22681+ return current->pid - 1;
22682+}
22683+
22684+static inline int si_pid_test(struct super_block *sb)
22685+{
22686+ pid_t bit = si_pid_bit();
22687+ if (bit < PID_MAX_DEFAULT)
22688+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
22689+ else
22690+ return si_pid_test_slow(sb);
22691+}
22692+
22693+static inline void si_pid_set(struct super_block *sb)
22694+{
22695+ pid_t bit = si_pid_bit();
22696+ if (bit < PID_MAX_DEFAULT) {
22697+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
22698+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
22699+ /* smp_mb(); */
22700+ } else
22701+ si_pid_set_slow(sb);
22702+}
22703+
22704+static inline void si_pid_clr(struct super_block *sb)
22705+{
22706+ pid_t bit = si_pid_bit();
22707+ if (bit < PID_MAX_DEFAULT) {
22708+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
22709+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
22710+ /* smp_mb(); */
22711+ } else
22712+ si_pid_clr_slow(sb);
22713+}
22714+
22715+/* ---------------------------------------------------------------------- */
22716+
1facf9fc 22717+/* lock superblock. mainly for entry point functions */
22718+/*
b752ccd1
AM
22719+ * __si_read_lock, __si_write_lock,
22720+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 22721+ */
b752ccd1 22722+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 22723+
dece6358
AM
22724+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
22725+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
22726+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
22727+
b752ccd1
AM
22728+static inline void si_noflush_read_lock(struct super_block *sb)
22729+{
22730+ __si_read_lock(sb);
22731+ si_pid_set(sb);
22732+}
22733+
22734+static inline int si_noflush_read_trylock(struct super_block *sb)
22735+{
22736+ int locked = __si_read_trylock(sb);
22737+ if (locked)
22738+ si_pid_set(sb);
22739+ return locked;
22740+}
22741+
22742+static inline void si_noflush_write_lock(struct super_block *sb)
22743+{
22744+ __si_write_lock(sb);
22745+ si_pid_set(sb);
22746+}
22747+
22748+static inline int si_noflush_write_trylock(struct super_block *sb)
22749+{
22750+ int locked = __si_write_trylock(sb);
22751+ if (locked)
22752+ si_pid_set(sb);
22753+ return locked;
22754+}
22755+
e49829fe 22756+#if 0 /* unused */
1facf9fc 22757+static inline int si_read_trylock(struct super_block *sb, int flags)
22758+{
22759+ if (au_ftest_lock(flags, FLUSH))
22760+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22761+ return si_noflush_read_trylock(sb);
22762+}
e49829fe 22763+#endif
1facf9fc 22764+
b752ccd1
AM
22765+static inline void si_read_unlock(struct super_block *sb)
22766+{
22767+ si_pid_clr(sb);
22768+ __si_read_unlock(sb);
22769+}
22770+
b752ccd1 22771+#if 0 /* unused */
1facf9fc 22772+static inline int si_write_trylock(struct super_block *sb, int flags)
22773+{
22774+ if (au_ftest_lock(flags, FLUSH))
22775+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22776+ return si_noflush_write_trylock(sb);
22777+}
b752ccd1
AM
22778+#endif
22779+
22780+static inline void si_write_unlock(struct super_block *sb)
22781+{
22782+ si_pid_clr(sb);
22783+ __si_write_unlock(sb);
22784+}
22785+
22786+#if 0 /* unused */
22787+static inline void si_downgrade_lock(struct super_block *sb)
22788+{
22789+ __si_downgrade_lock(sb);
22790+}
22791+#endif
1facf9fc 22792+
22793+/* ---------------------------------------------------------------------- */
22794+
22795+static inline aufs_bindex_t au_sbend(struct super_block *sb)
22796+{
dece6358 22797+ SiMustAnyLock(sb);
1facf9fc 22798+ return au_sbi(sb)->si_bend;
22799+}
22800+
22801+static inline unsigned int au_mntflags(struct super_block *sb)
22802+{
dece6358 22803+ SiMustAnyLock(sb);
1facf9fc 22804+ return au_sbi(sb)->si_mntflags;
22805+}
22806+
22807+static inline unsigned int au_sigen(struct super_block *sb)
22808+{
dece6358 22809+ SiMustAnyLock(sb);
1facf9fc 22810+ return au_sbi(sb)->si_generation;
22811+}
22812+
7f207e10
AM
22813+static inline void au_ninodes_inc(struct super_block *sb)
22814+{
22815+ atomic_long_inc(&au_sbi(sb)->si_ninodes);
22816+}
22817+
22818+static inline void au_ninodes_dec(struct super_block *sb)
22819+{
22820+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes));
22821+ atomic_long_dec(&au_sbi(sb)->si_ninodes);
22822+}
22823+
22824+static inline void au_nfiles_inc(struct super_block *sb)
22825+{
22826+ atomic_long_inc(&au_sbi(sb)->si_nfiles);
22827+}
22828+
22829+static inline void au_nfiles_dec(struct super_block *sb)
22830+{
22831+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles));
22832+ atomic_long_dec(&au_sbi(sb)->si_nfiles);
22833+}
22834+
1facf9fc 22835+static inline struct au_branch *au_sbr(struct super_block *sb,
22836+ aufs_bindex_t bindex)
22837+{
dece6358 22838+ SiMustAnyLock(sb);
1facf9fc 22839+ return au_sbi(sb)->si_branch[0 + bindex];
22840+}
22841+
22842+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
22843+{
dece6358 22844+ SiMustWriteLock(sb);
1facf9fc 22845+ au_sbi(sb)->si_xino_brid = brid;
22846+}
22847+
22848+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
22849+{
dece6358 22850+ SiMustAnyLock(sb);
1facf9fc 22851+ return au_sbi(sb)->si_xino_brid;
22852+}
22853+
22854+#endif /* __KERNEL__ */
22855+#endif /* __AUFS_SUPER_H__ */
7f207e10
AM
22856diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
22857--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a 22858+++ linux/fs/aufs/sysaufs.c 2011-03-21 20:22:06.860602399 +0100
4a4d8108 22859@@ -0,0 +1,107 @@
1facf9fc 22860+/*
027c5e7a 22861+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 22862+ *
22863+ * This program, aufs is free software; you can redistribute it and/or modify
22864+ * it under the terms of the GNU General Public License as published by
22865+ * the Free Software Foundation; either version 2 of the License, or
22866+ * (at your option) any later version.
dece6358
AM
22867+ *
22868+ * This program is distributed in the hope that it will be useful,
22869+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22870+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22871+ * GNU General Public License for more details.
22872+ *
22873+ * You should have received a copy of the GNU General Public License
22874+ * along with this program; if not, write to the Free Software
22875+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22876+ */
22877+
22878+/*
22879+ * sysfs interface and lifetime management
22880+ * they are necessary regardless sysfs is disabled.
22881+ */
22882+
22883+#include <linux/fs.h>
22884+#include <linux/random.h>
22885+#include <linux/sysfs.h>
22886+#include "aufs.h"
22887+
22888+unsigned long sysaufs_si_mask;
e49829fe 22889+struct kset *sysaufs_kset;
1facf9fc 22890+
22891+#define AuSiAttr(_name) { \
22892+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
22893+ .show = sysaufs_si_##_name, \
22894+}
22895+
22896+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
22897+struct attribute *sysaufs_si_attrs[] = {
22898+ &sysaufs_si_attr_xi_path.attr,
22899+ NULL,
22900+};
22901+
4a4d8108 22902+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 22903+ .show = sysaufs_si_show
22904+};
22905+
22906+static struct kobj_type au_sbi_ktype = {
22907+ .release = au_si_free,
22908+ .sysfs_ops = &au_sbi_ops,
22909+ .default_attrs = sysaufs_si_attrs
22910+};
22911+
22912+/* ---------------------------------------------------------------------- */
22913+
22914+int sysaufs_si_init(struct au_sbinfo *sbinfo)
22915+{
22916+ int err;
22917+
e49829fe 22918+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 22919+ /* cf. sysaufs_name() */
22920+ err = kobject_init_and_add
e49829fe 22921+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 22922+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
22923+
22924+ dbgaufs_si_null(sbinfo);
22925+ if (!err) {
22926+ err = dbgaufs_si_init(sbinfo);
22927+ if (unlikely(err))
22928+ kobject_put(&sbinfo->si_kobj);
22929+ }
22930+ return err;
22931+}
22932+
22933+void sysaufs_fin(void)
22934+{
22935+ dbgaufs_fin();
e49829fe
JR
22936+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
22937+ kset_unregister(sysaufs_kset);
1facf9fc 22938+}
22939+
22940+int __init sysaufs_init(void)
22941+{
22942+ int err;
22943+
22944+ do {
22945+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
22946+ } while (!sysaufs_si_mask);
22947+
4a4d8108 22948+ err = -EINVAL;
e49829fe
JR
22949+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
22950+ if (unlikely(!sysaufs_kset))
4a4d8108 22951+ goto out;
e49829fe
JR
22952+ err = PTR_ERR(sysaufs_kset);
22953+ if (IS_ERR(sysaufs_kset))
1facf9fc 22954+ goto out;
e49829fe 22955+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 22956+ if (unlikely(err)) {
e49829fe 22957+ kset_unregister(sysaufs_kset);
1facf9fc 22958+ goto out;
22959+ }
22960+
22961+ err = dbgaufs_init();
22962+ if (unlikely(err))
22963+ sysaufs_fin();
4f0767ce 22964+out:
1facf9fc 22965+ return err;
22966+}
7f207e10
AM
22967diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
22968--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 22969+++ linux/fs/aufs/sysaufs.h 2011-03-21 20:22:06.860602399 +0100
4a4d8108 22970@@ -0,0 +1,105 @@
1facf9fc 22971+/*
027c5e7a 22972+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 22973+ *
22974+ * This program, aufs is free software; you can redistribute it and/or modify
22975+ * it under the terms of the GNU General Public License as published by
22976+ * the Free Software Foundation; either version 2 of the License, or
22977+ * (at your option) any later version.
dece6358
AM
22978+ *
22979+ * This program is distributed in the hope that it will be useful,
22980+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22981+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22982+ * GNU General Public License for more details.
22983+ *
22984+ * You should have received a copy of the GNU General Public License
22985+ * along with this program; if not, write to the Free Software
22986+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22987+ */
22988+
22989+/*
22990+ * sysfs interface and mount lifetime management
22991+ */
22992+
22993+#ifndef __SYSAUFS_H__
22994+#define __SYSAUFS_H__
22995+
22996+#ifdef __KERNEL__
22997+
1facf9fc 22998+#include <linux/sysfs.h>
22999+#include <linux/aufs_type.h>
23000+#include "module.h"
23001+
dece6358
AM
23002+struct super_block;
23003+struct au_sbinfo;
23004+
1facf9fc 23005+struct sysaufs_si_attr {
23006+ struct attribute attr;
23007+ int (*show)(struct seq_file *seq, struct super_block *sb);
23008+};
23009+
23010+/* ---------------------------------------------------------------------- */
23011+
23012+/* sysaufs.c */
23013+extern unsigned long sysaufs_si_mask;
e49829fe 23014+extern struct kset *sysaufs_kset;
1facf9fc 23015+extern struct attribute *sysaufs_si_attrs[];
23016+int sysaufs_si_init(struct au_sbinfo *sbinfo);
23017+int __init sysaufs_init(void);
23018+void sysaufs_fin(void);
23019+
23020+/* ---------------------------------------------------------------------- */
23021+
23022+/* some people doesn't like to show a pointer in kernel */
23023+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
23024+{
23025+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
23026+}
23027+
23028+#define SysaufsSiNamePrefix "si_"
23029+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
23030+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
23031+{
23032+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
23033+ sysaufs_si_id(sbinfo));
23034+}
23035+
23036+struct au_branch;
23037+#ifdef CONFIG_SYSFS
23038+/* sysfs.c */
23039+extern struct attribute_group *sysaufs_attr_group;
23040+
23041+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
23042+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
23043+ char *buf);
23044+
23045+void sysaufs_br_init(struct au_branch *br);
23046+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
23047+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
23048+
23049+#define sysaufs_brs_init() do {} while (0)
23050+
23051+#else
23052+#define sysaufs_attr_group NULL
23053+
4a4d8108 23054+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 23055+
23056+static inline
23057+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
23058+ char *buf)
23059+{
23060+ return 0;
23061+}
23062+
4a4d8108
AM
23063+AuStubVoid(sysaufs_br_init, struct au_branch *br)
23064+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
23065+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 23066+
23067+static inline void sysaufs_brs_init(void)
23068+{
23069+ sysaufs_brs = 0;
23070+}
23071+
23072+#endif /* CONFIG_SYSFS */
23073+
23074+#endif /* __KERNEL__ */
23075+#endif /* __SYSAUFS_H__ */
7f207e10
AM
23076diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
23077--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a 23078+++ linux/fs/aufs/sysfs.c 2011-03-21 20:22:06.860602399 +0100
953406b4 23079@@ -0,0 +1,250 @@
1facf9fc 23080+/*
027c5e7a 23081+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 23082+ *
23083+ * This program, aufs is free software; you can redistribute it and/or modify
23084+ * it under the terms of the GNU General Public License as published by
23085+ * the Free Software Foundation; either version 2 of the License, or
23086+ * (at your option) any later version.
dece6358
AM
23087+ *
23088+ * This program is distributed in the hope that it will be useful,
23089+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23090+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23091+ * GNU General Public License for more details.
23092+ *
23093+ * You should have received a copy of the GNU General Public License
23094+ * along with this program; if not, write to the Free Software
23095+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23096+ */
23097+
23098+/*
23099+ * sysfs interface
23100+ */
23101+
23102+#include <linux/fs.h>
dece6358 23103+#include <linux/module.h>
1facf9fc 23104+#include <linux/seq_file.h>
23105+#include <linux/sysfs.h>
23106+#include "aufs.h"
23107+
4a4d8108
AM
23108+#ifdef CONFIG_AUFS_FS_MODULE
23109+/* this entry violates the "one line per file" policy of sysfs */
23110+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
23111+ char *buf)
23112+{
23113+ ssize_t err;
23114+ static char *conf =
23115+/* this file is generated at compiling */
23116+#include "conf.str"
23117+ ;
23118+
23119+ err = snprintf(buf, PAGE_SIZE, conf);
23120+ if (unlikely(err >= PAGE_SIZE))
23121+ err = -EFBIG;
23122+ return err;
23123+}
23124+
23125+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
23126+#endif
23127+
1facf9fc 23128+static struct attribute *au_attr[] = {
4a4d8108
AM
23129+#ifdef CONFIG_AUFS_FS_MODULE
23130+ &au_config_attr.attr,
23131+#endif
1facf9fc 23132+ NULL, /* need to NULL terminate the list of attributes */
23133+};
23134+
23135+static struct attribute_group sysaufs_attr_group_body = {
23136+ .attrs = au_attr
23137+};
23138+
23139+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
23140+
23141+/* ---------------------------------------------------------------------- */
23142+
23143+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
23144+{
23145+ int err;
23146+
dece6358
AM
23147+ SiMustAnyLock(sb);
23148+
1facf9fc 23149+ err = 0;
23150+ if (au_opt_test(au_mntflags(sb), XINO)) {
23151+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
23152+ seq_putc(seq, '\n');
23153+ }
23154+ return err;
23155+}
23156+
23157+/*
23158+ * the lifetime of branch is independent from the entry under sysfs.
23159+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
23160+ * unlinked.
23161+ */
23162+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
23163+ aufs_bindex_t bindex)
23164+{
23165+ struct path path;
23166+ struct dentry *root;
23167+ struct au_branch *br;
23168+
23169+ AuDbg("b%d\n", bindex);
23170+
23171+ root = sb->s_root;
23172+ di_read_lock_parent(root, !AuLock_IR);
23173+ br = au_sbr(sb, bindex);
23174+ path.mnt = br->br_mnt;
23175+ path.dentry = au_h_dptr(root, bindex);
23176+ au_seq_path(seq, &path);
23177+ di_read_unlock(root, !AuLock_IR);
23178+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
23179+ return 0;
23180+}
23181+
23182+/* ---------------------------------------------------------------------- */
23183+
23184+static struct seq_file *au_seq(char *p, ssize_t len)
23185+{
23186+ struct seq_file *seq;
23187+
23188+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
23189+ if (seq) {
23190+ /* mutex_init(&seq.lock); */
23191+ seq->buf = p;
23192+ seq->size = len;
23193+ return seq; /* success */
23194+ }
23195+
23196+ seq = ERR_PTR(-ENOMEM);
23197+ return seq;
23198+}
23199+
23200+#define SysaufsBr_PREFIX "br"
23201+
23202+/* todo: file size may exceed PAGE_SIZE */
23203+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 23204+ char *buf)
1facf9fc 23205+{
23206+ ssize_t err;
23207+ long l;
23208+ aufs_bindex_t bend;
23209+ struct au_sbinfo *sbinfo;
23210+ struct super_block *sb;
23211+ struct seq_file *seq;
23212+ char *name;
23213+ struct attribute **cattr;
23214+
23215+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
23216+ sb = sbinfo->si_sb;
1308ab2a 23217+
23218+ /*
23219+ * prevent a race condition between sysfs and aufs.
23220+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
23221+ * prohibits maintaining the sysfs entries.
23222+ * hew we acquire read lock after sysfs_get_active_two().
23223+ * on the other hand, the remount process may maintain the sysfs/aufs
23224+ * entries after acquiring write lock.
23225+ * it can cause a deadlock.
23226+ * simply we gave up processing read here.
23227+ */
23228+ err = -EBUSY;
23229+ if (unlikely(!si_noflush_read_trylock(sb)))
23230+ goto out;
1facf9fc 23231+
23232+ seq = au_seq(buf, PAGE_SIZE);
23233+ err = PTR_ERR(seq);
23234+ if (IS_ERR(seq))
1308ab2a 23235+ goto out_unlock;
1facf9fc 23236+
23237+ name = (void *)attr->name;
23238+ cattr = sysaufs_si_attrs;
23239+ while (*cattr) {
23240+ if (!strcmp(name, (*cattr)->name)) {
23241+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
23242+ ->show(seq, sb);
23243+ goto out_seq;
23244+ }
23245+ cattr++;
23246+ }
23247+
23248+ bend = au_sbend(sb);
23249+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
23250+ name += sizeof(SysaufsBr_PREFIX) - 1;
23251+ err = strict_strtol(name, 10, &l);
23252+ if (!err) {
23253+ if (l <= bend)
23254+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
23255+ else
23256+ err = -ENOENT;
23257+ }
23258+ goto out_seq;
23259+ }
23260+ BUG();
23261+
4f0767ce 23262+out_seq:
1facf9fc 23263+ if (!err) {
23264+ err = seq->count;
23265+ /* sysfs limit */
23266+ if (unlikely(err == PAGE_SIZE))
23267+ err = -EFBIG;
23268+ }
23269+ kfree(seq);
4f0767ce 23270+out_unlock:
1facf9fc 23271+ si_read_unlock(sb);
4f0767ce 23272+out:
1facf9fc 23273+ return err;
23274+}
23275+
23276+/* ---------------------------------------------------------------------- */
23277+
23278+void sysaufs_br_init(struct au_branch *br)
23279+{
4a4d8108
AM
23280+ struct attribute *attr = &br->br_attr;
23281+
23282+ sysfs_attr_init(attr);
23283+ attr->name = br->br_name;
23284+ attr->mode = S_IRUGO;
1facf9fc 23285+}
23286+
23287+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
23288+{
23289+ struct au_branch *br;
23290+ struct kobject *kobj;
23291+ aufs_bindex_t bend;
23292+
23293+ dbgaufs_brs_del(sb, bindex);
23294+
23295+ if (!sysaufs_brs)
23296+ return;
23297+
23298+ kobj = &au_sbi(sb)->si_kobj;
23299+ bend = au_sbend(sb);
23300+ for (; bindex <= bend; bindex++) {
23301+ br = au_sbr(sb, bindex);
23302+ sysfs_remove_file(kobj, &br->br_attr);
23303+ }
23304+}
23305+
23306+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
23307+{
23308+ int err;
23309+ aufs_bindex_t bend;
23310+ struct kobject *kobj;
23311+ struct au_branch *br;
23312+
23313+ dbgaufs_brs_add(sb, bindex);
23314+
23315+ if (!sysaufs_brs)
23316+ return;
23317+
23318+ kobj = &au_sbi(sb)->si_kobj;
23319+ bend = au_sbend(sb);
23320+ for (; bindex <= bend; bindex++) {
23321+ br = au_sbr(sb, bindex);
23322+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
23323+ "%d", bindex);
23324+ err = sysfs_create_file(kobj, &br->br_attr);
23325+ if (unlikely(err))
4a4d8108
AM
23326+ pr_warning("failed %s under sysfs(%d)\n",
23327+ br->br_name, err);
1facf9fc 23328+ }
23329+}
7f207e10
AM
23330diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
23331--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
23332+++ linux/fs/aufs/sysrq.c 2011-03-21 20:22:06.860602399 +0100
23333@@ -0,0 +1,148 @@
1facf9fc 23334+/*
027c5e7a 23335+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 23336+ *
23337+ * This program, aufs is free software; you can redistribute it and/or modify
23338+ * it under the terms of the GNU General Public License as published by
23339+ * the Free Software Foundation; either version 2 of the License, or
23340+ * (at your option) any later version.
dece6358
AM
23341+ *
23342+ * This program is distributed in the hope that it will be useful,
23343+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23344+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23345+ * GNU General Public License for more details.
23346+ *
23347+ * You should have received a copy of the GNU General Public License
23348+ * along with this program; if not, write to the Free Software
23349+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23350+ */
23351+
23352+/*
23353+ * magic sysrq hanlder
23354+ */
23355+
23356+#include <linux/fs.h>
23357+#include <linux/module.h>
23358+#include <linux/moduleparam.h>
23359+/* #include <linux/sysrq.h> */
027c5e7a 23360+#include <linux/writeback.h>
1facf9fc 23361+#include "aufs.h"
23362+
23363+/* ---------------------------------------------------------------------- */
23364+
23365+static void sysrq_sb(struct super_block *sb)
23366+{
23367+ char *plevel;
23368+ struct au_sbinfo *sbinfo;
23369+ struct file *file;
23370+
23371+ plevel = au_plevel;
23372+ au_plevel = KERN_WARNING;
1facf9fc 23373+
23374+ sbinfo = au_sbi(sb);
4a4d8108
AM
23375+ /* since we define pr_fmt, call printk directly */
23376+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
23377+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 23378+ au_dpri_sb(sb);
027c5e7a
AM
23379+
23380+#if 0
4a4d8108 23381+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 23382+ au_dpri_dentry(sb->s_root);
4a4d8108 23383+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 23384+ au_dpri_inode(sb->s_root->d_inode);
027c5e7a
AM
23385+#endif
23386+
1facf9fc 23387+#if 0
027c5e7a
AM
23388+ do {
23389+ int err, i, j, ndentry;
23390+ struct au_dcsub_pages dpages;
23391+ struct au_dpage *dpage;
23392+
23393+ err = au_dpages_init(&dpages, GFP_ATOMIC);
23394+ if (unlikely(err))
23395+ break;
23396+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
23397+ if (!err)
23398+ for (i = 0; i < dpages.ndpage; i++) {
23399+ dpage = dpages.dpages + i;
23400+ ndentry = dpage->ndentry;
23401+ for (j = 0; j < ndentry; j++)
23402+ au_dpri_dentry(dpage->dentries[j]);
23403+ }
23404+ au_dpages_free(&dpages);
23405+ } while (0);
23406+#endif
23407+
23408+#if 1
23409+ {
23410+ struct inode *i;
23411+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
23412+ spin_lock(&inode_lock);
23413+ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
23414+ if (1 || list_empty(&i->i_dentry))
23415+ au_dpri_inode(i);
23416+ spin_unlock(&inode_lock);
23417+ }
1facf9fc 23418+#endif
4a4d8108 23419+ printk(KERN_WARNING AUFS_NAME ": files\n");
0c5527e5
AM
23420+ lg_global_lock(files_lglock);
23421+ do_file_list_for_each_entry(sb, file) {
4a4d8108
AM
23422+ umode_t mode;
23423+ mode = file->f_dentry->d_inode->i_mode;
23424+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 23425+ au_dpri_file(file);
0c5527e5
AM
23426+ } while_file_list_for_each_entry;
23427+ lg_global_unlock(files_lglock);
e49829fe 23428+ printk(KERN_WARNING AUFS_NAME ": done\n");
1facf9fc 23429+
23430+ au_plevel = plevel;
1facf9fc 23431+}
23432+
23433+/* ---------------------------------------------------------------------- */
23434+
23435+/* module parameter */
23436+static char *aufs_sysrq_key = "a";
23437+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
23438+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
23439+
0c5527e5 23440+static void au_sysrq(int key __maybe_unused)
1facf9fc 23441+{
1facf9fc 23442+ struct au_sbinfo *sbinfo;
23443+
027c5e7a 23444+ lockdep_off();
e49829fe
JR
23445+ spin_lock(&au_sbilist.spin);
23446+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
1facf9fc 23447+ sysrq_sb(sbinfo->si_sb);
e49829fe 23448+ spin_unlock(&au_sbilist.spin);
027c5e7a 23449+ lockdep_on();
1facf9fc 23450+}
23451+
23452+static struct sysrq_key_op au_sysrq_op = {
23453+ .handler = au_sysrq,
23454+ .help_msg = "Aufs",
23455+ .action_msg = "Aufs",
23456+ .enable_mask = SYSRQ_ENABLE_DUMP
23457+};
23458+
23459+/* ---------------------------------------------------------------------- */
23460+
23461+int __init au_sysrq_init(void)
23462+{
23463+ int err;
23464+ char key;
23465+
23466+ err = -1;
23467+ key = *aufs_sysrq_key;
23468+ if ('a' <= key && key <= 'z')
23469+ err = register_sysrq_key(key, &au_sysrq_op);
23470+ if (unlikely(err))
4a4d8108 23471+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 23472+ return err;
23473+}
23474+
23475+void au_sysrq_fin(void)
23476+{
23477+ int err;
23478+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
23479+ if (unlikely(err))
4a4d8108 23480+ pr_err("err %d (ignored)\n", err);
1facf9fc 23481+}
7f207e10
AM
23482diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
23483--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a 23484+++ linux/fs/aufs/vdir.c 2011-03-21 20:22:06.860602399 +0100
7f207e10 23485@@ -0,0 +1,886 @@
1facf9fc 23486+/*
027c5e7a 23487+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 23488+ *
23489+ * This program, aufs is free software; you can redistribute it and/or modify
23490+ * it under the terms of the GNU General Public License as published by
23491+ * the Free Software Foundation; either version 2 of the License, or
23492+ * (at your option) any later version.
dece6358
AM
23493+ *
23494+ * This program is distributed in the hope that it will be useful,
23495+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23496+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23497+ * GNU General Public License for more details.
23498+ *
23499+ * You should have received a copy of the GNU General Public License
23500+ * along with this program; if not, write to the Free Software
23501+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23502+ */
23503+
23504+/*
23505+ * virtual or vertical directory
23506+ */
23507+
dece6358 23508+#include <linux/hash.h>
1facf9fc 23509+#include "aufs.h"
23510+
dece6358 23511+static unsigned int calc_size(int nlen)
1facf9fc 23512+{
dece6358 23513+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 23514+}
23515+
23516+static int set_deblk_end(union au_vdir_deblk_p *p,
23517+ union au_vdir_deblk_p *deblk_end)
23518+{
23519+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
23520+ p->de->de_str.len = 0;
23521+ /* smp_mb(); */
23522+ return 0;
23523+ }
23524+ return -1; /* error */
23525+}
23526+
23527+/* returns true or false */
23528+static int is_deblk_end(union au_vdir_deblk_p *p,
23529+ union au_vdir_deblk_p *deblk_end)
23530+{
23531+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
23532+ return !p->de->de_str.len;
23533+ return 1;
23534+}
23535+
23536+static unsigned char *last_deblk(struct au_vdir *vdir)
23537+{
23538+ return vdir->vd_deblk[vdir->vd_nblk - 1];
23539+}
23540+
23541+/* ---------------------------------------------------------------------- */
23542+
1308ab2a 23543+/* estimate the apropriate size for name hash table */
23544+unsigned int au_rdhash_est(loff_t sz)
23545+{
23546+ unsigned int n;
23547+
23548+ n = UINT_MAX;
23549+ sz >>= 10;
23550+ if (sz < n)
23551+ n = sz;
23552+ if (sz < AUFS_RDHASH_DEF)
23553+ n = AUFS_RDHASH_DEF;
4a4d8108 23554+ /* pr_info("n %u\n", n); */
1308ab2a 23555+ return n;
23556+}
23557+
1facf9fc 23558+/*
23559+ * the allocated memory has to be freed by
dece6358 23560+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 23561+ */
dece6358 23562+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 23563+{
1facf9fc 23564+ struct hlist_head *head;
dece6358 23565+ unsigned int u;
1facf9fc 23566+
dece6358
AM
23567+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
23568+ if (head) {
23569+ nhash->nh_num = num_hash;
23570+ nhash->nh_head = head;
23571+ for (u = 0; u < num_hash; u++)
1facf9fc 23572+ INIT_HLIST_HEAD(head++);
dece6358 23573+ return 0; /* success */
1facf9fc 23574+ }
1facf9fc 23575+
dece6358 23576+ return -ENOMEM;
1facf9fc 23577+}
23578+
dece6358
AM
23579+static void nhash_count(struct hlist_head *head)
23580+{
23581+#if 0
23582+ unsigned long n;
23583+ struct hlist_node *pos;
23584+
23585+ n = 0;
23586+ hlist_for_each(pos, head)
23587+ n++;
4a4d8108 23588+ pr_info("%lu\n", n);
dece6358
AM
23589+#endif
23590+}
23591+
23592+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 23593+{
1facf9fc 23594+ struct au_vdir_wh *tpos;
23595+ struct hlist_node *pos, *node;
23596+
dece6358
AM
23597+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
23598+ /* hlist_del(pos); */
23599+ kfree(tpos);
1facf9fc 23600+ }
23601+}
23602+
dece6358 23603+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 23604+{
dece6358
AM
23605+ struct au_vdir_dehstr *tpos;
23606+ struct hlist_node *pos, *node;
1facf9fc 23607+
dece6358
AM
23608+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
23609+ /* hlist_del(pos); */
4a4d8108 23610+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 23611+ }
1facf9fc 23612+}
23613+
dece6358
AM
23614+static void au_nhash_do_free(struct au_nhash *nhash,
23615+ void (*free)(struct hlist_head *head))
1facf9fc 23616+{
1308ab2a 23617+ unsigned int n;
1facf9fc 23618+ struct hlist_head *head;
1facf9fc 23619+
dece6358 23620+ n = nhash->nh_num;
1308ab2a 23621+ if (!n)
23622+ return;
23623+
dece6358 23624+ head = nhash->nh_head;
1308ab2a 23625+ while (n-- > 0) {
dece6358
AM
23626+ nhash_count(head);
23627+ free(head++);
1facf9fc 23628+ }
dece6358 23629+ kfree(nhash->nh_head);
1facf9fc 23630+}
23631+
dece6358 23632+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 23633+{
dece6358
AM
23634+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
23635+}
1facf9fc 23636+
dece6358
AM
23637+static void au_nhash_de_free(struct au_nhash *delist)
23638+{
23639+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 23640+}
23641+
23642+/* ---------------------------------------------------------------------- */
23643+
23644+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
23645+ int limit)
23646+{
23647+ int num;
23648+ unsigned int u, n;
23649+ struct hlist_head *head;
23650+ struct au_vdir_wh *tpos;
23651+ struct hlist_node *pos;
23652+
23653+ num = 0;
23654+ n = whlist->nh_num;
23655+ head = whlist->nh_head;
1308ab2a 23656+ for (u = 0; u < n; u++, head++)
1facf9fc 23657+ hlist_for_each_entry(tpos, pos, head, wh_hash)
23658+ if (tpos->wh_bindex == btgt && ++num > limit)
23659+ return 1;
1facf9fc 23660+ return 0;
23661+}
23662+
23663+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 23664+ unsigned char *name,
1facf9fc 23665+ unsigned int len)
23666+{
dece6358
AM
23667+ unsigned int v;
23668+ /* const unsigned int magic_bit = 12; */
23669+
1308ab2a 23670+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
23671+
dece6358
AM
23672+ v = 0;
23673+ while (len--)
23674+ v += *name++;
23675+ /* v = hash_long(v, magic_bit); */
23676+ v %= nhash->nh_num;
23677+ return nhash->nh_head + v;
23678+}
23679+
23680+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
23681+ int nlen)
23682+{
23683+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 23684+}
23685+
23686+/* returns found or not */
dece6358 23687+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 23688+{
23689+ struct hlist_head *head;
23690+ struct au_vdir_wh *tpos;
23691+ struct hlist_node *pos;
23692+ struct au_vdir_destr *str;
23693+
dece6358 23694+ head = au_name_hash(whlist, name, nlen);
1facf9fc 23695+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
23696+ str = &tpos->wh_str;
23697+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
23698+ if (au_nhash_test_name(str, name, nlen))
23699+ return 1;
23700+ }
23701+ return 0;
23702+}
23703+
23704+/* returns found(true) or not */
23705+static int test_known(struct au_nhash *delist, char *name, int nlen)
23706+{
23707+ struct hlist_head *head;
23708+ struct au_vdir_dehstr *tpos;
23709+ struct hlist_node *pos;
23710+ struct au_vdir_destr *str;
23711+
23712+ head = au_name_hash(delist, name, nlen);
23713+ hlist_for_each_entry(tpos, pos, head, hash) {
23714+ str = tpos->str;
23715+ AuDbg("%.*s\n", str->len, str->name);
23716+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 23717+ return 1;
23718+ }
23719+ return 0;
23720+}
23721+
dece6358
AM
23722+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
23723+ unsigned char d_type)
23724+{
23725+#ifdef CONFIG_AUFS_SHWH
23726+ wh->wh_ino = ino;
23727+ wh->wh_type = d_type;
23728+#endif
23729+}
23730+
23731+/* ---------------------------------------------------------------------- */
23732+
23733+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
23734+ unsigned int d_type, aufs_bindex_t bindex,
23735+ unsigned char shwh)
1facf9fc 23736+{
23737+ int err;
23738+ struct au_vdir_destr *str;
23739+ struct au_vdir_wh *wh;
23740+
dece6358 23741+ AuDbg("%.*s\n", nlen, name);
1308ab2a 23742+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
23743+
1facf9fc 23744+ err = -ENOMEM;
dece6358 23745+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 23746+ if (unlikely(!wh))
23747+ goto out;
23748+
23749+ err = 0;
23750+ wh->wh_bindex = bindex;
dece6358
AM
23751+ if (shwh)
23752+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 23753+ str = &wh->wh_str;
dece6358
AM
23754+ str->len = nlen;
23755+ memcpy(str->name, name, nlen);
23756+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 23757+ /* smp_mb(); */
23758+
4f0767ce 23759+out:
1facf9fc 23760+ return err;
23761+}
23762+
1facf9fc 23763+static int append_deblk(struct au_vdir *vdir)
23764+{
23765+ int err;
dece6358 23766+ unsigned long ul;
1facf9fc 23767+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
23768+ union au_vdir_deblk_p p, deblk_end;
23769+ unsigned char **o;
23770+
23771+ err = -ENOMEM;
dece6358
AM
23772+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
23773+ GFP_NOFS);
1facf9fc 23774+ if (unlikely(!o))
23775+ goto out;
23776+
23777+ vdir->vd_deblk = o;
23778+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
23779+ if (p.deblk) {
23780+ ul = vdir->vd_nblk++;
23781+ vdir->vd_deblk[ul] = p.deblk;
23782+ vdir->vd_last.ul = ul;
23783+ vdir->vd_last.p.deblk = p.deblk;
23784+ deblk_end.deblk = p.deblk + deblk_sz;
23785+ err = set_deblk_end(&p, &deblk_end);
23786+ }
23787+
4f0767ce 23788+out:
1facf9fc 23789+ return err;
23790+}
23791+
dece6358
AM
23792+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
23793+ unsigned int d_type, struct au_nhash *delist)
23794+{
23795+ int err;
23796+ unsigned int sz;
23797+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
23798+ union au_vdir_deblk_p p, *room, deblk_end;
23799+ struct au_vdir_dehstr *dehstr;
23800+
23801+ p.deblk = last_deblk(vdir);
23802+ deblk_end.deblk = p.deblk + deblk_sz;
23803+ room = &vdir->vd_last.p;
23804+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
23805+ || !is_deblk_end(room, &deblk_end));
23806+
23807+ sz = calc_size(nlen);
23808+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
23809+ err = append_deblk(vdir);
23810+ if (unlikely(err))
23811+ goto out;
23812+
23813+ p.deblk = last_deblk(vdir);
23814+ deblk_end.deblk = p.deblk + deblk_sz;
23815+ /* smp_mb(); */
23816+ AuDebugOn(room->deblk != p.deblk);
23817+ }
23818+
23819+ err = -ENOMEM;
4a4d8108 23820+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
23821+ if (unlikely(!dehstr))
23822+ goto out;
23823+
23824+ dehstr->str = &room->de->de_str;
23825+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
23826+ room->de->de_ino = ino;
23827+ room->de->de_type = d_type;
23828+ room->de->de_str.len = nlen;
23829+ memcpy(room->de->de_str.name, name, nlen);
23830+
23831+ err = 0;
23832+ room->deblk += sz;
23833+ if (unlikely(set_deblk_end(room, &deblk_end)))
23834+ err = append_deblk(vdir);
23835+ /* smp_mb(); */
23836+
4f0767ce 23837+out:
dece6358
AM
23838+ return err;
23839+}
23840+
23841+/* ---------------------------------------------------------------------- */
23842+
23843+void au_vdir_free(struct au_vdir *vdir)
23844+{
23845+ unsigned char **deblk;
23846+
23847+ deblk = vdir->vd_deblk;
23848+ while (vdir->vd_nblk--)
23849+ kfree(*deblk++);
23850+ kfree(vdir->vd_deblk);
23851+ au_cache_free_vdir(vdir);
23852+}
23853+
1308ab2a 23854+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 23855+{
23856+ struct au_vdir *vdir;
1308ab2a 23857+ struct super_block *sb;
1facf9fc 23858+ int err;
23859+
1308ab2a 23860+ sb = file->f_dentry->d_sb;
dece6358
AM
23861+ SiMustAnyLock(sb);
23862+
1facf9fc 23863+ err = -ENOMEM;
23864+ vdir = au_cache_alloc_vdir();
23865+ if (unlikely(!vdir))
23866+ goto out;
23867+
23868+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
23869+ if (unlikely(!vdir->vd_deblk))
23870+ goto out_free;
23871+
23872+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 23873+ if (!vdir->vd_deblk_sz) {
23874+ /* estimate the apropriate size for deblk */
23875+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 23876+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 23877+ }
1facf9fc 23878+ vdir->vd_nblk = 0;
23879+ vdir->vd_version = 0;
23880+ vdir->vd_jiffy = 0;
23881+ err = append_deblk(vdir);
23882+ if (!err)
23883+ return vdir; /* success */
23884+
23885+ kfree(vdir->vd_deblk);
23886+
4f0767ce 23887+out_free:
1facf9fc 23888+ au_cache_free_vdir(vdir);
4f0767ce 23889+out:
1facf9fc 23890+ vdir = ERR_PTR(err);
23891+ return vdir;
23892+}
23893+
23894+static int reinit_vdir(struct au_vdir *vdir)
23895+{
23896+ int err;
23897+ union au_vdir_deblk_p p, deblk_end;
23898+
23899+ while (vdir->vd_nblk > 1) {
23900+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
23901+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
23902+ vdir->vd_nblk--;
23903+ }
23904+ p.deblk = vdir->vd_deblk[0];
23905+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
23906+ err = set_deblk_end(&p, &deblk_end);
23907+ /* keep vd_dblk_sz */
23908+ vdir->vd_last.ul = 0;
23909+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
23910+ vdir->vd_version = 0;
23911+ vdir->vd_jiffy = 0;
23912+ /* smp_mb(); */
23913+ return err;
23914+}
23915+
23916+/* ---------------------------------------------------------------------- */
23917+
1facf9fc 23918+#define AuFillVdir_CALLED 1
23919+#define AuFillVdir_WHABLE (1 << 1)
dece6358 23920+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 23921+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
23922+#define au_fset_fillvdir(flags, name) \
23923+ do { (flags) |= AuFillVdir_##name; } while (0)
23924+#define au_fclr_fillvdir(flags, name) \
23925+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 23926+
dece6358
AM
23927+#ifndef CONFIG_AUFS_SHWH
23928+#undef AuFillVdir_SHWH
23929+#define AuFillVdir_SHWH 0
23930+#endif
23931+
1facf9fc 23932+struct fillvdir_arg {
23933+ struct file *file;
23934+ struct au_vdir *vdir;
dece6358
AM
23935+ struct au_nhash delist;
23936+ struct au_nhash whlist;
1facf9fc 23937+ aufs_bindex_t bindex;
23938+ unsigned int flags;
23939+ int err;
23940+};
23941+
dece6358 23942+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 23943+ loff_t offset __maybe_unused, u64 h_ino,
23944+ unsigned int d_type)
23945+{
23946+ struct fillvdir_arg *arg = __arg;
23947+ char *name = (void *)__name;
23948+ struct super_block *sb;
1facf9fc 23949+ ino_t ino;
dece6358 23950+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 23951+
1facf9fc 23952+ arg->err = 0;
dece6358 23953+ sb = arg->file->f_dentry->d_sb;
1facf9fc 23954+ au_fset_fillvdir(arg->flags, CALLED);
23955+ /* smp_mb(); */
dece6358 23956+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 23957+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
23958+ if (test_known(&arg->delist, name, nlen)
23959+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
23960+ goto out; /* already exists or whiteouted */
1facf9fc 23961+
23962+ sb = arg->file->f_dentry->d_sb;
dece6358 23963+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
23964+ if (!arg->err) {
23965+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
23966+ d_type = DT_UNKNOWN;
dece6358
AM
23967+ arg->err = append_de(arg->vdir, name, nlen, ino,
23968+ d_type, &arg->delist);
4a4d8108 23969+ }
1facf9fc 23970+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
23971+ name += AUFS_WH_PFX_LEN;
dece6358
AM
23972+ nlen -= AUFS_WH_PFX_LEN;
23973+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
23974+ goto out; /* already whiteouted */
1facf9fc 23975+
dece6358
AM
23976+ if (shwh)
23977+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
23978+ &ino);
4a4d8108
AM
23979+ if (!arg->err) {
23980+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
23981+ d_type = DT_UNKNOWN;
1facf9fc 23982+ arg->err = au_nhash_append_wh
dece6358
AM
23983+ (&arg->whlist, name, nlen, ino, d_type,
23984+ arg->bindex, shwh);
4a4d8108 23985+ }
1facf9fc 23986+ }
23987+
4f0767ce 23988+out:
1facf9fc 23989+ if (!arg->err)
23990+ arg->vdir->vd_jiffy = jiffies;
23991+ /* smp_mb(); */
23992+ AuTraceErr(arg->err);
23993+ return arg->err;
23994+}
23995+
dece6358
AM
23996+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
23997+ struct au_nhash *whlist, struct au_nhash *delist)
23998+{
23999+#ifdef CONFIG_AUFS_SHWH
24000+ int err;
24001+ unsigned int nh, u;
24002+ struct hlist_head *head;
24003+ struct au_vdir_wh *tpos;
24004+ struct hlist_node *pos, *n;
24005+ char *p, *o;
24006+ struct au_vdir_destr *destr;
24007+
24008+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
24009+
24010+ err = -ENOMEM;
4a4d8108 24011+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
24012+ if (unlikely(!p))
24013+ goto out;
24014+
24015+ err = 0;
24016+ nh = whlist->nh_num;
24017+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
24018+ p += AUFS_WH_PFX_LEN;
24019+ for (u = 0; u < nh; u++) {
24020+ head = whlist->nh_head + u;
24021+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
24022+ destr = &tpos->wh_str;
24023+ memcpy(p, destr->name, destr->len);
24024+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
24025+ tpos->wh_ino, tpos->wh_type, delist);
24026+ if (unlikely(err))
24027+ break;
24028+ }
24029+ }
24030+
24031+ __putname(o);
24032+
4f0767ce 24033+out:
dece6358
AM
24034+ AuTraceErr(err);
24035+ return err;
24036+#else
24037+ return 0;
24038+#endif
24039+}
24040+
1facf9fc 24041+static int au_do_read_vdir(struct fillvdir_arg *arg)
24042+{
24043+ int err;
dece6358 24044+ unsigned int rdhash;
1facf9fc 24045+ loff_t offset;
dece6358
AM
24046+ aufs_bindex_t bend, bindex, bstart;
24047+ unsigned char shwh;
1facf9fc 24048+ struct file *hf, *file;
24049+ struct super_block *sb;
24050+
1facf9fc 24051+ file = arg->file;
24052+ sb = file->f_dentry->d_sb;
dece6358
AM
24053+ SiMustAnyLock(sb);
24054+
24055+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 24056+ if (!rdhash)
24057+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
24058+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
24059+ if (unlikely(err))
1facf9fc 24060+ goto out;
dece6358
AM
24061+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
24062+ if (unlikely(err))
1facf9fc 24063+ goto out_delist;
24064+
24065+ err = 0;
24066+ arg->flags = 0;
dece6358
AM
24067+ shwh = 0;
24068+ if (au_opt_test(au_mntflags(sb), SHWH)) {
24069+ shwh = 1;
24070+ au_fset_fillvdir(arg->flags, SHWH);
24071+ }
24072+ bstart = au_fbstart(file);
4a4d8108 24073+ bend = au_fbend_dir(file);
dece6358 24074+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 24075+ hf = au_hf_dir(file, bindex);
1facf9fc 24076+ if (!hf)
24077+ continue;
24078+
24079+ offset = vfsub_llseek(hf, 0, SEEK_SET);
24080+ err = offset;
24081+ if (unlikely(offset))
24082+ break;
24083+
24084+ arg->bindex = bindex;
24085+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
24086+ if (shwh
24087+ || (bindex != bend
24088+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 24089+ au_fset_fillvdir(arg->flags, WHABLE);
24090+ do {
24091+ arg->err = 0;
24092+ au_fclr_fillvdir(arg->flags, CALLED);
24093+ /* smp_mb(); */
24094+ err = vfsub_readdir(hf, fillvdir, arg);
24095+ if (err >= 0)
24096+ err = arg->err;
24097+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
24098+ }
dece6358
AM
24099+
24100+ if (!err && shwh)
24101+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
24102+
24103+ au_nhash_wh_free(&arg->whlist);
1facf9fc 24104+
4f0767ce 24105+out_delist:
dece6358 24106+ au_nhash_de_free(&arg->delist);
4f0767ce 24107+out:
1facf9fc 24108+ return err;
24109+}
24110+
24111+static int read_vdir(struct file *file, int may_read)
24112+{
24113+ int err;
24114+ unsigned long expire;
24115+ unsigned char do_read;
24116+ struct fillvdir_arg arg;
24117+ struct inode *inode;
24118+ struct au_vdir *vdir, *allocated;
24119+
24120+ err = 0;
24121+ inode = file->f_dentry->d_inode;
24122+ IMustLock(inode);
dece6358
AM
24123+ SiMustAnyLock(inode->i_sb);
24124+
1facf9fc 24125+ allocated = NULL;
24126+ do_read = 0;
24127+ expire = au_sbi(inode->i_sb)->si_rdcache;
24128+ vdir = au_ivdir(inode);
24129+ if (!vdir) {
24130+ do_read = 1;
1308ab2a 24131+ vdir = alloc_vdir(file);
1facf9fc 24132+ err = PTR_ERR(vdir);
24133+ if (IS_ERR(vdir))
24134+ goto out;
24135+ err = 0;
24136+ allocated = vdir;
24137+ } else if (may_read
24138+ && (inode->i_version != vdir->vd_version
24139+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
24140+ do_read = 1;
24141+ err = reinit_vdir(vdir);
24142+ if (unlikely(err))
24143+ goto out;
24144+ }
24145+
24146+ if (!do_read)
24147+ return 0; /* success */
24148+
24149+ arg.file = file;
24150+ arg.vdir = vdir;
24151+ err = au_do_read_vdir(&arg);
24152+ if (!err) {
24153+ /* file->f_pos = 0; */
24154+ vdir->vd_version = inode->i_version;
24155+ vdir->vd_last.ul = 0;
24156+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
24157+ if (allocated)
24158+ au_set_ivdir(inode, allocated);
24159+ } else if (allocated)
24160+ au_vdir_free(allocated);
24161+
4f0767ce 24162+out:
1facf9fc 24163+ return err;
24164+}
24165+
24166+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
24167+{
24168+ int err, rerr;
24169+ unsigned long ul, n;
24170+ const unsigned int deblk_sz = src->vd_deblk_sz;
24171+
24172+ AuDebugOn(tgt->vd_nblk != 1);
24173+
24174+ err = -ENOMEM;
24175+ if (tgt->vd_nblk < src->vd_nblk) {
24176+ unsigned char **p;
24177+
dece6358
AM
24178+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
24179+ GFP_NOFS);
1facf9fc 24180+ if (unlikely(!p))
24181+ goto out;
24182+ tgt->vd_deblk = p;
24183+ }
24184+
1308ab2a 24185+ if (tgt->vd_deblk_sz != deblk_sz) {
24186+ unsigned char *p;
24187+
24188+ tgt->vd_deblk_sz = deblk_sz;
24189+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
24190+ if (unlikely(!p))
24191+ goto out;
24192+ tgt->vd_deblk[0] = p;
24193+ }
1facf9fc 24194+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 24195+ tgt->vd_version = src->vd_version;
24196+ tgt->vd_jiffy = src->vd_jiffy;
24197+
24198+ n = src->vd_nblk;
24199+ for (ul = 1; ul < n; ul++) {
dece6358
AM
24200+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
24201+ GFP_NOFS);
24202+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 24203+ goto out;
1308ab2a 24204+ tgt->vd_nblk++;
1facf9fc 24205+ }
1308ab2a 24206+ tgt->vd_nblk = n;
24207+ tgt->vd_last.ul = tgt->vd_last.ul;
24208+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
24209+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
24210+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 24211+ /* smp_mb(); */
24212+ return 0; /* success */
24213+
4f0767ce 24214+out:
1facf9fc 24215+ rerr = reinit_vdir(tgt);
24216+ BUG_ON(rerr);
24217+ return err;
24218+}
24219+
24220+int au_vdir_init(struct file *file)
24221+{
24222+ int err;
24223+ struct inode *inode;
24224+ struct au_vdir *vdir_cache, *allocated;
24225+
24226+ err = read_vdir(file, !file->f_pos);
24227+ if (unlikely(err))
24228+ goto out;
24229+
24230+ allocated = NULL;
24231+ vdir_cache = au_fvdir_cache(file);
24232+ if (!vdir_cache) {
1308ab2a 24233+ vdir_cache = alloc_vdir(file);
1facf9fc 24234+ err = PTR_ERR(vdir_cache);
24235+ if (IS_ERR(vdir_cache))
24236+ goto out;
24237+ allocated = vdir_cache;
24238+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
24239+ err = reinit_vdir(vdir_cache);
24240+ if (unlikely(err))
24241+ goto out;
24242+ } else
24243+ return 0; /* success */
24244+
24245+ inode = file->f_dentry->d_inode;
24246+ err = copy_vdir(vdir_cache, au_ivdir(inode));
24247+ if (!err) {
24248+ file->f_version = inode->i_version;
24249+ if (allocated)
24250+ au_set_fvdir_cache(file, allocated);
24251+ } else if (allocated)
24252+ au_vdir_free(allocated);
24253+
4f0767ce 24254+out:
1facf9fc 24255+ return err;
24256+}
24257+
24258+static loff_t calc_offset(struct au_vdir *vdir)
24259+{
24260+ loff_t offset;
24261+ union au_vdir_deblk_p p;
24262+
24263+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
24264+ offset = vdir->vd_last.p.deblk - p.deblk;
24265+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
24266+ return offset;
24267+}
24268+
24269+/* returns true or false */
24270+static int seek_vdir(struct file *file)
24271+{
24272+ int valid;
24273+ unsigned int deblk_sz;
24274+ unsigned long ul, n;
24275+ loff_t offset;
24276+ union au_vdir_deblk_p p, deblk_end;
24277+ struct au_vdir *vdir_cache;
24278+
24279+ valid = 1;
24280+ vdir_cache = au_fvdir_cache(file);
24281+ offset = calc_offset(vdir_cache);
24282+ AuDbg("offset %lld\n", offset);
24283+ if (file->f_pos == offset)
24284+ goto out;
24285+
24286+ vdir_cache->vd_last.ul = 0;
24287+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
24288+ if (!file->f_pos)
24289+ goto out;
24290+
24291+ valid = 0;
24292+ deblk_sz = vdir_cache->vd_deblk_sz;
24293+ ul = div64_u64(file->f_pos, deblk_sz);
24294+ AuDbg("ul %lu\n", ul);
24295+ if (ul >= vdir_cache->vd_nblk)
24296+ goto out;
24297+
24298+ n = vdir_cache->vd_nblk;
24299+ for (; ul < n; ul++) {
24300+ p.deblk = vdir_cache->vd_deblk[ul];
24301+ deblk_end.deblk = p.deblk + deblk_sz;
24302+ offset = ul;
24303+ offset *= deblk_sz;
24304+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
24305+ unsigned int l;
24306+
24307+ l = calc_size(p.de->de_str.len);
24308+ offset += l;
24309+ p.deblk += l;
24310+ }
24311+ if (!is_deblk_end(&p, &deblk_end)) {
24312+ valid = 1;
24313+ vdir_cache->vd_last.ul = ul;
24314+ vdir_cache->vd_last.p = p;
24315+ break;
24316+ }
24317+ }
24318+
4f0767ce 24319+out:
1facf9fc 24320+ /* smp_mb(); */
24321+ AuTraceErr(!valid);
24322+ return valid;
24323+}
24324+
24325+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
24326+{
24327+ int err;
24328+ unsigned int l, deblk_sz;
24329+ union au_vdir_deblk_p deblk_end;
24330+ struct au_vdir *vdir_cache;
24331+ struct au_vdir_de *de;
24332+
24333+ vdir_cache = au_fvdir_cache(file);
24334+ if (!seek_vdir(file))
24335+ return 0;
24336+
24337+ deblk_sz = vdir_cache->vd_deblk_sz;
24338+ while (1) {
24339+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
24340+ deblk_end.deblk += deblk_sz;
24341+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
24342+ de = vdir_cache->vd_last.p.de;
24343+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
24344+ de->de_str.len, de->de_str.name, file->f_pos,
24345+ (unsigned long)de->de_ino, de->de_type);
24346+ err = filldir(dirent, de->de_str.name, de->de_str.len,
24347+ file->f_pos, de->de_ino, de->de_type);
24348+ if (unlikely(err)) {
24349+ AuTraceErr(err);
24350+ /* todo: ignore the error caused by udba? */
24351+ /* return err; */
24352+ return 0;
24353+ }
24354+
24355+ l = calc_size(de->de_str.len);
24356+ vdir_cache->vd_last.p.deblk += l;
24357+ file->f_pos += l;
24358+ }
24359+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
24360+ vdir_cache->vd_last.ul++;
24361+ vdir_cache->vd_last.p.deblk
24362+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
24363+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
24364+ continue;
24365+ }
24366+ break;
24367+ }
24368+
24369+ /* smp_mb(); */
24370+ return 0;
24371+}
7f207e10
AM
24372diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
24373--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a 24374+++ linux/fs/aufs/vfsub.c 2011-03-21 20:22:06.860602399 +0100
7f207e10 24375@@ -0,0 +1,790 @@
1facf9fc 24376+/*
027c5e7a 24377+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 24378+ *
24379+ * This program, aufs is free software; you can redistribute it and/or modify
24380+ * it under the terms of the GNU General Public License as published by
24381+ * the Free Software Foundation; either version 2 of the License, or
24382+ * (at your option) any later version.
dece6358
AM
24383+ *
24384+ * This program is distributed in the hope that it will be useful,
24385+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24386+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24387+ * GNU General Public License for more details.
24388+ *
24389+ * You should have received a copy of the GNU General Public License
24390+ * along with this program; if not, write to the Free Software
24391+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24392+ */
24393+
24394+/*
24395+ * sub-routines for VFS
24396+ */
24397+
4a4d8108 24398+#include <linux/file.h>
1308ab2a 24399+#include <linux/ima.h>
dece6358
AM
24400+#include <linux/namei.h>
24401+#include <linux/security.h>
24402+#include <linux/splice.h>
1facf9fc 24403+#include <linux/uaccess.h>
24404+#include "aufs.h"
24405+
24406+int vfsub_update_h_iattr(struct path *h_path, int *did)
24407+{
24408+ int err;
24409+ struct kstat st;
24410+ struct super_block *h_sb;
24411+
24412+ /* for remote fs, leave work for its getattr or d_revalidate */
24413+ /* for bad i_attr fs, handle them in aufs_getattr() */
24414+ /* still some fs may acquire i_mutex. we need to skip them */
24415+ err = 0;
24416+ if (!did)
24417+ did = &err;
24418+ h_sb = h_path->dentry->d_sb;
24419+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
24420+ if (*did)
24421+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
24422+
24423+ return err;
24424+}
24425+
24426+/* ---------------------------------------------------------------------- */
24427+
4a4d8108
AM
24428+static int au_conv_oflags(int flags)
24429+{
24430+ int mask = 0;
24431+
24432+#ifdef CONFIG_IMA
24433+ fmode_t fmode;
24434+
24435+ /* mask = MAY_OPEN; */
24436+ fmode = OPEN_FMODE(flags);
24437+ if (fmode & FMODE_READ)
24438+ mask |= MAY_READ;
24439+ if ((fmode & FMODE_WRITE)
24440+ || (flags & O_TRUNC))
24441+ mask |= MAY_WRITE;
24442+ /*
24443+ * if (flags & O_APPEND)
24444+ * mask |= MAY_APPEND;
24445+ */
24446+ if (flags & vfsub_fmode_to_uint(FMODE_EXEC))
24447+ mask |= MAY_EXEC;
24448+
24449+ AuDbg("flags 0x%x, mask 0x%x\n", flags, mask);
24450+#endif
24451+
24452+ return mask;
24453+}
24454+
24455+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 24456+{
24457+ struct file *file;
4a4d8108 24458+ int err;
1308ab2a 24459+
4a4d8108 24460+ path_get(path);
0c5527e5 24461+ file = dentry_open(path->dentry, path->mnt,
7f207e10
AM
24462+ flags /* | vfsub_fmode_to_uint(FMODE_NONOTIFY) */,
24463+ current_cred());
1308ab2a 24464+ if (IS_ERR(file))
4a4d8108
AM
24465+ goto out;
24466+
24467+ err = ima_file_check(file, au_conv_oflags(flags));
24468+ if (unlikely(err)) {
24469+ fput(file);
24470+ file = ERR_PTR(err);
24471+ }
24472+out:
1308ab2a 24473+ return file;
24474+}
24475+
1facf9fc 24476+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
24477+{
24478+ struct file *file;
24479+
7f207e10
AM
24480+ file = filp_open(path,
24481+ oflags /* | vfsub_fmode_to_uint(FMODE_NONOTIFY) */,
24482+ mode);
1facf9fc 24483+ if (IS_ERR(file))
24484+ goto out;
24485+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24486+
4f0767ce 24487+out:
1facf9fc 24488+ return file;
24489+}
24490+
24491+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
24492+{
24493+ int err;
24494+
1facf9fc 24495+ err = kern_path(name, flags, path);
1facf9fc 24496+ if (!err && path->dentry->d_inode)
24497+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
24498+ return err;
24499+}
24500+
24501+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
24502+ int len)
24503+{
24504+ struct path path = {
24505+ .mnt = NULL
24506+ };
24507+
1308ab2a 24508+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 24509+ IMustLock(parent->d_inode);
24510+
24511+ path.dentry = lookup_one_len(name, parent, len);
24512+ if (IS_ERR(path.dentry))
24513+ goto out;
24514+ if (path.dentry->d_inode)
24515+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
24516+
4f0767ce 24517+out:
4a4d8108 24518+ AuTraceErrPtr(path.dentry);
1facf9fc 24519+ return path.dentry;
24520+}
24521+
24522+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
24523+{
24524+ struct path path = {
24525+ .mnt = nd->path.mnt
24526+ };
24527+
24528+ IMustLock(nd->path.dentry->d_inode);
24529+
24530+ path.dentry = lookup_hash(nd);
4a4d8108
AM
24531+ if (IS_ERR(path.dentry))
24532+ goto out;
24533+ if (path.dentry->d_inode)
1facf9fc 24534+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
24535+
4f0767ce 24536+out:
4a4d8108 24537+ AuTraceErrPtr(path.dentry);
1facf9fc 24538+ return path.dentry;
24539+}
24540+
24541+/* ---------------------------------------------------------------------- */
24542+
24543+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
24544+ struct dentry *d2, struct au_hinode *hdir2)
24545+{
24546+ struct dentry *d;
24547+
1facf9fc 24548+ d = lock_rename(d1, d2);
4a4d8108 24549+ au_hn_suspend(hdir1);
1facf9fc 24550+ if (hdir1 != hdir2)
4a4d8108 24551+ au_hn_suspend(hdir2);
1facf9fc 24552+
24553+ return d;
24554+}
24555+
24556+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
24557+ struct dentry *d2, struct au_hinode *hdir2)
24558+{
4a4d8108 24559+ au_hn_resume(hdir1);
1facf9fc 24560+ if (hdir1 != hdir2)
4a4d8108 24561+ au_hn_resume(hdir2);
1facf9fc 24562+ unlock_rename(d1, d2);
1facf9fc 24563+}
24564+
24565+/* ---------------------------------------------------------------------- */
24566+
24567+int vfsub_create(struct inode *dir, struct path *path, int mode)
24568+{
24569+ int err;
24570+ struct dentry *d;
24571+
24572+ IMustLock(dir);
24573+
24574+ d = path->dentry;
24575+ path->dentry = d->d_parent;
b752ccd1 24576+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 24577+ path->dentry = d;
24578+ if (unlikely(err))
24579+ goto out;
24580+
24581+ if (au_test_fs_null_nd(dir->i_sb))
24582+ err = vfs_create(dir, path->dentry, mode, NULL);
24583+ else {
24584+ struct nameidata h_nd;
24585+
24586+ memset(&h_nd, 0, sizeof(h_nd));
24587+ h_nd.flags = LOOKUP_CREATE;
24588+ h_nd.intent.open.flags = O_CREAT
24589+ | vfsub_fmode_to_uint(FMODE_READ);
24590+ h_nd.intent.open.create_mode = mode;
24591+ h_nd.path.dentry = path->dentry->d_parent;
24592+ h_nd.path.mnt = path->mnt;
24593+ path_get(&h_nd.path);
24594+ err = vfs_create(dir, path->dentry, mode, &h_nd);
24595+ path_put(&h_nd.path);
24596+ }
24597+
24598+ if (!err) {
24599+ struct path tmp = *path;
24600+ int did;
24601+
24602+ vfsub_update_h_iattr(&tmp, &did);
24603+ if (did) {
24604+ tmp.dentry = path->dentry->d_parent;
24605+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24606+ }
24607+ /*ignore*/
24608+ }
24609+
4f0767ce 24610+out:
1facf9fc 24611+ return err;
24612+}
24613+
24614+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
24615+{
24616+ int err;
24617+ struct dentry *d;
24618+
24619+ IMustLock(dir);
24620+
24621+ d = path->dentry;
24622+ path->dentry = d->d_parent;
b752ccd1 24623+ err = security_path_symlink(path, d, symname);
1facf9fc 24624+ path->dentry = d;
24625+ if (unlikely(err))
24626+ goto out;
24627+
24628+ err = vfs_symlink(dir, path->dentry, symname);
24629+ if (!err) {
24630+ struct path tmp = *path;
24631+ int did;
24632+
24633+ vfsub_update_h_iattr(&tmp, &did);
24634+ if (did) {
24635+ tmp.dentry = path->dentry->d_parent;
24636+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24637+ }
24638+ /*ignore*/
24639+ }
24640+
4f0767ce 24641+out:
1facf9fc 24642+ return err;
24643+}
24644+
24645+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
24646+{
24647+ int err;
24648+ struct dentry *d;
24649+
24650+ IMustLock(dir);
24651+
24652+ d = path->dentry;
24653+ path->dentry = d->d_parent;
027c5e7a 24654+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 24655+ path->dentry = d;
24656+ if (unlikely(err))
24657+ goto out;
24658+
24659+ err = vfs_mknod(dir, path->dentry, mode, dev);
24660+ if (!err) {
24661+ struct path tmp = *path;
24662+ int did;
24663+
24664+ vfsub_update_h_iattr(&tmp, &did);
24665+ if (did) {
24666+ tmp.dentry = path->dentry->d_parent;
24667+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24668+ }
24669+ /*ignore*/
24670+ }
24671+
4f0767ce 24672+out:
1facf9fc 24673+ return err;
24674+}
24675+
24676+static int au_test_nlink(struct inode *inode)
24677+{
24678+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
24679+
24680+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
24681+ || inode->i_nlink < link_max)
24682+ return 0;
24683+ return -EMLINK;
24684+}
24685+
24686+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
24687+{
24688+ int err;
24689+ struct dentry *d;
24690+
24691+ IMustLock(dir);
24692+
24693+ err = au_test_nlink(src_dentry->d_inode);
24694+ if (unlikely(err))
24695+ return err;
24696+
24697+ d = path->dentry;
24698+ path->dentry = d->d_parent;
b752ccd1 24699+ err = security_path_link(src_dentry, path, d);
1facf9fc 24700+ path->dentry = d;
24701+ if (unlikely(err))
24702+ goto out;
24703+
1facf9fc 24704+ err = vfs_link(src_dentry, dir, path->dentry);
1facf9fc 24705+ if (!err) {
24706+ struct path tmp = *path;
24707+ int did;
24708+
24709+ /* fuse has different memory inode for the same inumber */
24710+ vfsub_update_h_iattr(&tmp, &did);
24711+ if (did) {
24712+ tmp.dentry = path->dentry->d_parent;
24713+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24714+ tmp.dentry = src_dentry;
24715+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24716+ }
24717+ /*ignore*/
24718+ }
24719+
4f0767ce 24720+out:
1facf9fc 24721+ return err;
24722+}
24723+
24724+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
24725+ struct inode *dir, struct path *path)
24726+{
24727+ int err;
24728+ struct path tmp = {
24729+ .mnt = path->mnt
24730+ };
24731+ struct dentry *d;
24732+
24733+ IMustLock(dir);
24734+ IMustLock(src_dir);
24735+
24736+ d = path->dentry;
24737+ path->dentry = d->d_parent;
24738+ tmp.dentry = src_dentry->d_parent;
b752ccd1 24739+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 24740+ path->dentry = d;
24741+ if (unlikely(err))
24742+ goto out;
24743+
1facf9fc 24744+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
1facf9fc 24745+ if (!err) {
24746+ int did;
24747+
24748+ tmp.dentry = d->d_parent;
24749+ vfsub_update_h_iattr(&tmp, &did);
24750+ if (did) {
24751+ tmp.dentry = src_dentry;
24752+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24753+ tmp.dentry = src_dentry->d_parent;
24754+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24755+ }
24756+ /*ignore*/
24757+ }
24758+
4f0767ce 24759+out:
1facf9fc 24760+ return err;
24761+}
24762+
24763+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
24764+{
24765+ int err;
24766+ struct dentry *d;
24767+
24768+ IMustLock(dir);
24769+
24770+ d = path->dentry;
24771+ path->dentry = d->d_parent;
b752ccd1 24772+ err = security_path_mkdir(path, d, mode);
1facf9fc 24773+ path->dentry = d;
24774+ if (unlikely(err))
24775+ goto out;
24776+
24777+ err = vfs_mkdir(dir, path->dentry, mode);
24778+ if (!err) {
24779+ struct path tmp = *path;
24780+ int did;
24781+
24782+ vfsub_update_h_iattr(&tmp, &did);
24783+ if (did) {
24784+ tmp.dentry = path->dentry->d_parent;
24785+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24786+ }
24787+ /*ignore*/
24788+ }
24789+
4f0767ce 24790+out:
1facf9fc 24791+ return err;
24792+}
24793+
24794+int vfsub_rmdir(struct inode *dir, struct path *path)
24795+{
24796+ int err;
24797+ struct dentry *d;
24798+
24799+ IMustLock(dir);
24800+
24801+ d = path->dentry;
24802+ path->dentry = d->d_parent;
b752ccd1 24803+ err = security_path_rmdir(path, d);
1facf9fc 24804+ path->dentry = d;
24805+ if (unlikely(err))
24806+ goto out;
24807+
1facf9fc 24808+ err = vfs_rmdir(dir, path->dentry);
1facf9fc 24809+ if (!err) {
24810+ struct path tmp = {
24811+ .dentry = path->dentry->d_parent,
24812+ .mnt = path->mnt
24813+ };
24814+
24815+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
24816+ }
24817+
4f0767ce 24818+out:
1facf9fc 24819+ return err;
24820+}
24821+
24822+/* ---------------------------------------------------------------------- */
24823+
24824+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
24825+ loff_t *ppos)
24826+{
24827+ ssize_t err;
24828+
24829+ err = vfs_read(file, ubuf, count, ppos);
24830+ if (err >= 0)
24831+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24832+ return err;
24833+}
24834+
24835+/* todo: kernel_read()? */
24836+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
24837+ loff_t *ppos)
24838+{
24839+ ssize_t err;
24840+ mm_segment_t oldfs;
b752ccd1
AM
24841+ union {
24842+ void *k;
24843+ char __user *u;
24844+ } buf;
1facf9fc 24845+
b752ccd1 24846+ buf.k = kbuf;
1facf9fc 24847+ oldfs = get_fs();
24848+ set_fs(KERNEL_DS);
b752ccd1 24849+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 24850+ set_fs(oldfs);
24851+ return err;
24852+}
24853+
24854+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
24855+ loff_t *ppos)
24856+{
24857+ ssize_t err;
24858+
1facf9fc 24859+ err = vfs_write(file, ubuf, count, ppos);
1facf9fc 24860+ if (err >= 0)
24861+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24862+ return err;
24863+}
24864+
24865+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
24866+{
24867+ ssize_t err;
24868+ mm_segment_t oldfs;
b752ccd1
AM
24869+ union {
24870+ void *k;
24871+ const char __user *u;
24872+ } buf;
1facf9fc 24873+
b752ccd1 24874+ buf.k = kbuf;
1facf9fc 24875+ oldfs = get_fs();
24876+ set_fs(KERNEL_DS);
b752ccd1 24877+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 24878+ set_fs(oldfs);
24879+ return err;
24880+}
24881+
4a4d8108
AM
24882+int vfsub_flush(struct file *file, fl_owner_t id)
24883+{
24884+ int err;
24885+
24886+ err = 0;
24887+ if (file->f_op && file->f_op->flush) {
24888+ err = file->f_op->flush(file, id);
24889+ if (!err)
24890+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
24891+ /*ignore*/
24892+ }
24893+ return err;
24894+}
24895+
1facf9fc 24896+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
24897+{
24898+ int err;
24899+
1facf9fc 24900+ err = vfs_readdir(file, filldir, arg);
1facf9fc 24901+ if (err >= 0)
24902+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24903+ return err;
24904+}
24905+
24906+long vfsub_splice_to(struct file *in, loff_t *ppos,
24907+ struct pipe_inode_info *pipe, size_t len,
24908+ unsigned int flags)
24909+{
24910+ long err;
24911+
0fc653ad 24912+ err = do_splice_to(in, ppos, pipe, len, flags);
4a4d8108 24913+ file_accessed(in);
1facf9fc 24914+ if (err >= 0)
24915+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
24916+ return err;
24917+}
24918+
24919+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
24920+ loff_t *ppos, size_t len, unsigned int flags)
24921+{
24922+ long err;
24923+
0fc653ad 24924+ err = do_splice_from(pipe, out, ppos, len, flags);
1facf9fc 24925+ if (err >= 0)
24926+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
24927+ return err;
24928+}
24929+
24930+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
24931+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
24932+ struct file *h_file)
24933+{
24934+ int err;
24935+ struct inode *h_inode;
24936+
24937+ h_inode = h_path->dentry->d_inode;
24938+ if (!h_file) {
24939+ err = mnt_want_write(h_path->mnt);
24940+ if (err)
24941+ goto out;
24942+ err = inode_permission(h_inode, MAY_WRITE);
24943+ if (err)
24944+ goto out_mnt;
24945+ err = get_write_access(h_inode);
24946+ if (err)
24947+ goto out_mnt;
4a4d8108 24948+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 24949+ if (err)
24950+ goto out_inode;
24951+ }
24952+
24953+ err = locks_verify_truncate(h_inode, h_file, length);
24954+ if (!err)
953406b4 24955+ err = security_path_truncate(h_path);
b752ccd1 24956+ if (!err)
1facf9fc 24957+ err = do_truncate(h_path->dentry, length, attr, h_file);
1facf9fc 24958+
4f0767ce 24959+out_inode:
1facf9fc 24960+ if (!h_file)
24961+ put_write_access(h_inode);
4f0767ce 24962+out_mnt:
1facf9fc 24963+ if (!h_file)
24964+ mnt_drop_write(h_path->mnt);
4f0767ce 24965+out:
1facf9fc 24966+ return err;
24967+}
24968+
24969+/* ---------------------------------------------------------------------- */
24970+
24971+struct au_vfsub_mkdir_args {
24972+ int *errp;
24973+ struct inode *dir;
24974+ struct path *path;
24975+ int mode;
24976+};
24977+
24978+static void au_call_vfsub_mkdir(void *args)
24979+{
24980+ struct au_vfsub_mkdir_args *a = args;
24981+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
24982+}
24983+
24984+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
24985+{
24986+ int err, do_sio, wkq_err;
24987+
24988+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
24989+ if (!do_sio)
24990+ err = vfsub_mkdir(dir, path, mode);
24991+ else {
24992+ struct au_vfsub_mkdir_args args = {
24993+ .errp = &err,
24994+ .dir = dir,
24995+ .path = path,
24996+ .mode = mode
24997+ };
24998+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
24999+ if (unlikely(wkq_err))
25000+ err = wkq_err;
25001+ }
25002+
25003+ return err;
25004+}
25005+
25006+struct au_vfsub_rmdir_args {
25007+ int *errp;
25008+ struct inode *dir;
25009+ struct path *path;
25010+};
25011+
25012+static void au_call_vfsub_rmdir(void *args)
25013+{
25014+ struct au_vfsub_rmdir_args *a = args;
25015+ *a->errp = vfsub_rmdir(a->dir, a->path);
25016+}
25017+
25018+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
25019+{
25020+ int err, do_sio, wkq_err;
25021+
25022+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
25023+ if (!do_sio)
25024+ err = vfsub_rmdir(dir, path);
25025+ else {
25026+ struct au_vfsub_rmdir_args args = {
25027+ .errp = &err,
25028+ .dir = dir,
25029+ .path = path
25030+ };
25031+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
25032+ if (unlikely(wkq_err))
25033+ err = wkq_err;
25034+ }
25035+
25036+ return err;
25037+}
25038+
25039+/* ---------------------------------------------------------------------- */
25040+
25041+struct notify_change_args {
25042+ int *errp;
25043+ struct path *path;
25044+ struct iattr *ia;
25045+};
25046+
25047+static void call_notify_change(void *args)
25048+{
25049+ struct notify_change_args *a = args;
25050+ struct inode *h_inode;
25051+
25052+ h_inode = a->path->dentry->d_inode;
25053+ IMustLock(h_inode);
25054+
25055+ *a->errp = -EPERM;
25056+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 25057+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 25058+ if (!*a->errp)
25059+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
25060+ }
25061+ AuTraceErr(*a->errp);
25062+}
25063+
25064+int vfsub_notify_change(struct path *path, struct iattr *ia)
25065+{
25066+ int err;
25067+ struct notify_change_args args = {
25068+ .errp = &err,
25069+ .path = path,
25070+ .ia = ia
25071+ };
25072+
25073+ call_notify_change(&args);
25074+
25075+ return err;
25076+}
25077+
25078+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
25079+{
25080+ int err, wkq_err;
25081+ struct notify_change_args args = {
25082+ .errp = &err,
25083+ .path = path,
25084+ .ia = ia
25085+ };
25086+
25087+ wkq_err = au_wkq_wait(call_notify_change, &args);
25088+ if (unlikely(wkq_err))
25089+ err = wkq_err;
25090+
25091+ return err;
25092+}
25093+
25094+/* ---------------------------------------------------------------------- */
25095+
25096+struct unlink_args {
25097+ int *errp;
25098+ struct inode *dir;
25099+ struct path *path;
25100+};
25101+
25102+static void call_unlink(void *args)
25103+{
25104+ struct unlink_args *a = args;
25105+ struct dentry *d = a->path->dentry;
25106+ struct inode *h_inode;
25107+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
027c5e7a 25108+ && d->d_count == 1);
1facf9fc 25109+
25110+ IMustLock(a->dir);
25111+
25112+ a->path->dentry = d->d_parent;
25113+ *a->errp = security_path_unlink(a->path, d);
25114+ a->path->dentry = d;
25115+ if (unlikely(*a->errp))
25116+ return;
25117+
25118+ if (!stop_sillyrename)
25119+ dget(d);
25120+ h_inode = d->d_inode;
25121+ if (h_inode)
027c5e7a 25122+ ihold(h_inode);
1facf9fc 25123+
1facf9fc 25124+ *a->errp = vfs_unlink(a->dir, d);
1facf9fc 25125+ if (!*a->errp) {
25126+ struct path tmp = {
25127+ .dentry = d->d_parent,
25128+ .mnt = a->path->mnt
25129+ };
25130+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
25131+ }
25132+
25133+ if (!stop_sillyrename)
25134+ dput(d);
25135+ if (h_inode)
25136+ iput(h_inode);
25137+
25138+ AuTraceErr(*a->errp);
25139+}
25140+
25141+/*
25142+ * @dir: must be locked.
25143+ * @dentry: target dentry.
25144+ */
25145+int vfsub_unlink(struct inode *dir, struct path *path, int force)
25146+{
25147+ int err;
25148+ struct unlink_args args = {
25149+ .errp = &err,
25150+ .dir = dir,
25151+ .path = path
25152+ };
25153+
25154+ if (!force)
25155+ call_unlink(&args);
25156+ else {
25157+ int wkq_err;
25158+
25159+ wkq_err = au_wkq_wait(call_unlink, &args);
25160+ if (unlikely(wkq_err))
25161+ err = wkq_err;
25162+ }
25163+
25164+ return err;
25165+}
7f207e10
AM
25166diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
25167--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
25168+++ linux/fs/aufs/vfsub.h 2011-03-21 20:22:06.860602399 +0100
25169@@ -0,0 +1,226 @@
1facf9fc 25170+/*
027c5e7a 25171+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 25172+ *
25173+ * This program, aufs is free software; you can redistribute it and/or modify
25174+ * it under the terms of the GNU General Public License as published by
25175+ * the Free Software Foundation; either version 2 of the License, or
25176+ * (at your option) any later version.
dece6358
AM
25177+ *
25178+ * This program is distributed in the hope that it will be useful,
25179+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25180+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25181+ * GNU General Public License for more details.
25182+ *
25183+ * You should have received a copy of the GNU General Public License
25184+ * along with this program; if not, write to the Free Software
25185+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25186+ */
25187+
25188+/*
25189+ * sub-routines for VFS
25190+ */
25191+
25192+#ifndef __AUFS_VFSUB_H__
25193+#define __AUFS_VFSUB_H__
25194+
25195+#ifdef __KERNEL__
25196+
25197+#include <linux/fs.h>
0c5527e5 25198+#include <linux/lglock.h>
7f207e10 25199+#include "debug.h"
1facf9fc 25200+
7f207e10 25201+/* copied from linux/fs/internal.h */
0c5527e5 25202+DECLARE_BRLOCK(vfsmount_lock);
0c5527e5
AM
25203+extern void file_sb_list_del(struct file *f);
25204+
7f207e10
AM
25205+/* copied from linux/fs/file_table.c */
25206+DECLARE_LGLOCK(files_lglock);
0c5527e5
AM
25207+#ifdef CONFIG_SMP
25208+/*
25209+ * These macros iterate all files on all CPUs for a given superblock.
25210+ * files_lglock must be held globally.
25211+ */
25212+#define do_file_list_for_each_entry(__sb, __file) \
25213+{ \
25214+ int i; \
25215+ for_each_possible_cpu(i) { \
25216+ struct list_head *list; \
25217+ list = per_cpu_ptr((__sb)->s_files, i); \
25218+ list_for_each_entry((__file), list, f_u.fu_list)
25219+
25220+#define while_file_list_for_each_entry \
25221+ } \
25222+}
25223+
25224+#else
25225+
25226+#define do_file_list_for_each_entry(__sb, __file) \
25227+{ \
25228+ struct list_head *list; \
25229+ list = &(sb)->s_files; \
25230+ list_for_each_entry((__file), list, f_u.fu_list)
25231+
25232+#define while_file_list_for_each_entry \
25233+}
7f207e10
AM
25234+#endif
25235+
25236+/* ---------------------------------------------------------------------- */
1facf9fc 25237+
25238+/* lock subclass for lower inode */
25239+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
25240+/* reduce? gave up. */
25241+enum {
25242+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
25243+ AuLsc_I_PARENT, /* lower inode, parent first */
25244+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 25245+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 25246+ AuLsc_I_CHILD,
25247+ AuLsc_I_CHILD2,
25248+ AuLsc_I_End
25249+};
25250+
25251+/* to debug easier, do not make them inlined functions */
25252+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
25253+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
25254+
25255+/* ---------------------------------------------------------------------- */
25256+
7f207e10
AM
25257+static inline void vfsub_drop_nlink(struct inode *inode)
25258+{
25259+ AuDebugOn(!inode->i_nlink);
25260+ drop_nlink(inode);
25261+}
25262+
027c5e7a
AM
25263+static inline void vfsub_dead_dir(struct inode *inode)
25264+{
25265+ AuDebugOn(!S_ISDIR(inode->i_mode));
25266+ inode->i_flags |= S_DEAD;
25267+ clear_nlink(inode);
25268+}
25269+
7f207e10
AM
25270+/* ---------------------------------------------------------------------- */
25271+
25272+int vfsub_update_h_iattr(struct path *h_path, int *did);
25273+struct file *vfsub_dentry_open(struct path *path, int flags);
25274+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
1facf9fc 25275+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
25276+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
25277+ int len);
25278+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
25279+
25280+/* ---------------------------------------------------------------------- */
25281+
25282+struct au_hinode;
25283+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
25284+ struct dentry *d2, struct au_hinode *hdir2);
25285+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
25286+ struct dentry *d2, struct au_hinode *hdir2);
25287+
25288+int vfsub_create(struct inode *dir, struct path *path, int mode);
25289+int vfsub_symlink(struct inode *dir, struct path *path,
25290+ const char *symname);
25291+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
25292+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
25293+ struct path *path);
25294+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
25295+ struct inode *hdir, struct path *path);
25296+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
25297+int vfsub_rmdir(struct inode *dir, struct path *path);
25298+
25299+/* ---------------------------------------------------------------------- */
25300+
25301+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
25302+ loff_t *ppos);
25303+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
25304+ loff_t *ppos);
25305+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
25306+ loff_t *ppos);
25307+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
25308+ loff_t *ppos);
4a4d8108 25309+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 25310+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
25311+
4a4d8108
AM
25312+static inline unsigned int vfsub_file_flags(struct file *file)
25313+{
25314+ unsigned int flags;
25315+
25316+ spin_lock(&file->f_lock);
25317+ flags = file->f_flags;
25318+ spin_unlock(&file->f_lock);
25319+
25320+ return flags;
25321+}
1308ab2a 25322+
1facf9fc 25323+static inline void vfsub_file_accessed(struct file *h_file)
25324+{
25325+ file_accessed(h_file);
25326+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
25327+}
25328+
25329+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
25330+ struct dentry *h_dentry)
25331+{
25332+ struct path h_path = {
25333+ .dentry = h_dentry,
25334+ .mnt = h_mnt
25335+ };
25336+ touch_atime(h_mnt, h_dentry);
25337+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
25338+}
25339+
4a4d8108
AM
25340+long vfsub_splice_to(struct file *in, loff_t *ppos,
25341+ struct pipe_inode_info *pipe, size_t len,
25342+ unsigned int flags);
25343+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
25344+ loff_t *ppos, size_t len, unsigned int flags);
25345+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
25346+ struct file *h_file);
25347+
1facf9fc 25348+/* ---------------------------------------------------------------------- */
25349+
25350+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
25351+{
25352+ loff_t err;
25353+
1facf9fc 25354+ err = vfs_llseek(file, offset, origin);
1facf9fc 25355+ return err;
25356+}
25357+
25358+/* ---------------------------------------------------------------------- */
25359+
25360+/* dirty workaround for strict type of fmode_t */
25361+union vfsub_fmu {
25362+ fmode_t fm;
25363+ unsigned int ui;
25364+};
25365+
25366+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
25367+{
25368+ union vfsub_fmu u = {
25369+ .fm = fm
25370+ };
25371+
25372+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
25373+
25374+ return u.ui;
25375+}
25376+
25377+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
25378+{
25379+ union vfsub_fmu u = {
25380+ .ui = ui
25381+ };
25382+
25383+ return u.fm;
25384+}
25385+
4a4d8108
AM
25386+/* ---------------------------------------------------------------------- */
25387+
25388+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
25389+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
25390+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
25391+int vfsub_notify_change(struct path *path, struct iattr *ia);
25392+int vfsub_unlink(struct inode *dir, struct path *path, int force);
25393+
1facf9fc 25394+#endif /* __KERNEL__ */
25395+#endif /* __AUFS_VFSUB_H__ */
7f207e10
AM
25396diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
25397--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
25398+++ linux/fs/aufs/wbr_policy.c 2011-03-21 20:22:06.860602399 +0100
25399@@ -0,0 +1,700 @@
1facf9fc 25400+/*
027c5e7a 25401+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 25402+ *
25403+ * This program, aufs is free software; you can redistribute it and/or modify
25404+ * it under the terms of the GNU General Public License as published by
25405+ * the Free Software Foundation; either version 2 of the License, or
25406+ * (at your option) any later version.
dece6358
AM
25407+ *
25408+ * This program is distributed in the hope that it will be useful,
25409+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25410+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25411+ * GNU General Public License for more details.
25412+ *
25413+ * You should have received a copy of the GNU General Public License
25414+ * along with this program; if not, write to the Free Software
25415+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25416+ */
25417+
25418+/*
25419+ * policies for selecting one among multiple writable branches
25420+ */
25421+
25422+#include <linux/statfs.h>
25423+#include "aufs.h"
25424+
25425+/* subset of cpup_attr() */
25426+static noinline_for_stack
25427+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
25428+{
25429+ int err, sbits;
25430+ struct iattr ia;
25431+ struct inode *h_isrc;
25432+
25433+ h_isrc = h_src->d_inode;
25434+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
25435+ ia.ia_mode = h_isrc->i_mode;
25436+ ia.ia_uid = h_isrc->i_uid;
25437+ ia.ia_gid = h_isrc->i_gid;
25438+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
25439+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
25440+ err = vfsub_sio_notify_change(h_path, &ia);
25441+
25442+ /* is this nfs only? */
25443+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
25444+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
25445+ ia.ia_mode = h_isrc->i_mode;
25446+ err = vfsub_sio_notify_change(h_path, &ia);
25447+ }
25448+
25449+ return err;
25450+}
25451+
25452+#define AuCpdown_PARENT_OPQ 1
25453+#define AuCpdown_WHED (1 << 1)
25454+#define AuCpdown_MADE_DIR (1 << 2)
25455+#define AuCpdown_DIROPQ (1 << 3)
25456+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
25457+#define au_fset_cpdown(flags, name) \
25458+ do { (flags) |= AuCpdown_##name; } while (0)
25459+#define au_fclr_cpdown(flags, name) \
25460+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 25461+
25462+struct au_cpdown_dir_args {
25463+ struct dentry *parent;
25464+ unsigned int flags;
25465+};
25466+
25467+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
25468+ struct au_cpdown_dir_args *a)
25469+{
25470+ int err;
25471+ struct dentry *opq_dentry;
25472+
25473+ opq_dentry = au_diropq_create(dentry, bdst);
25474+ err = PTR_ERR(opq_dentry);
25475+ if (IS_ERR(opq_dentry))
25476+ goto out;
25477+ dput(opq_dentry);
25478+ au_fset_cpdown(a->flags, DIROPQ);
25479+
4f0767ce 25480+out:
1facf9fc 25481+ return err;
25482+}
25483+
25484+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
25485+ struct inode *dir, aufs_bindex_t bdst)
25486+{
25487+ int err;
25488+ struct path h_path;
25489+ struct au_branch *br;
25490+
25491+ br = au_sbr(dentry->d_sb, bdst);
25492+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
25493+ err = PTR_ERR(h_path.dentry);
25494+ if (IS_ERR(h_path.dentry))
25495+ goto out;
25496+
25497+ err = 0;
25498+ if (h_path.dentry->d_inode) {
25499+ h_path.mnt = br->br_mnt;
25500+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
25501+ dentry);
25502+ }
25503+ dput(h_path.dentry);
25504+
4f0767ce 25505+out:
1facf9fc 25506+ return err;
25507+}
25508+
25509+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
25510+ struct dentry *h_parent, void *arg)
25511+{
25512+ int err, rerr;
4a4d8108 25513+ aufs_bindex_t bopq, bstart;
1facf9fc 25514+ struct path h_path;
25515+ struct dentry *parent;
25516+ struct inode *h_dir, *h_inode, *inode, *dir;
25517+ struct au_cpdown_dir_args *args = arg;
25518+
25519+ bstart = au_dbstart(dentry);
25520+ /* dentry is di-locked */
25521+ parent = dget_parent(dentry);
25522+ dir = parent->d_inode;
25523+ h_dir = h_parent->d_inode;
25524+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
25525+ IMustLock(h_dir);
25526+
25527+ err = au_lkup_neg(dentry, bdst);
25528+ if (unlikely(err < 0))
25529+ goto out;
25530+ h_path.dentry = au_h_dptr(dentry, bdst);
25531+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
25532+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
25533+ S_IRWXU | S_IRUGO | S_IXUGO);
25534+ if (unlikely(err))
25535+ goto out_put;
25536+ au_fset_cpdown(args->flags, MADE_DIR);
25537+
1facf9fc 25538+ bopq = au_dbdiropq(dentry);
25539+ au_fclr_cpdown(args->flags, WHED);
25540+ au_fclr_cpdown(args->flags, DIROPQ);
25541+ if (au_dbwh(dentry) == bdst)
25542+ au_fset_cpdown(args->flags, WHED);
25543+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
25544+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 25545+ h_inode = h_path.dentry->d_inode;
25546+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
25547+ if (au_ftest_cpdown(args->flags, WHED)) {
25548+ err = au_cpdown_dir_opq(dentry, bdst, args);
25549+ if (unlikely(err)) {
25550+ mutex_unlock(&h_inode->i_mutex);
25551+ goto out_dir;
25552+ }
25553+ }
25554+
25555+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
25556+ mutex_unlock(&h_inode->i_mutex);
25557+ if (unlikely(err))
25558+ goto out_opq;
25559+
25560+ if (au_ftest_cpdown(args->flags, WHED)) {
25561+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
25562+ if (unlikely(err))
25563+ goto out_opq;
25564+ }
25565+
25566+ inode = dentry->d_inode;
25567+ if (au_ibend(inode) < bdst)
25568+ au_set_ibend(inode, bdst);
25569+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
25570+ au_hi_flags(inode, /*isdir*/1));
25571+ goto out; /* success */
25572+
25573+ /* revert */
4f0767ce 25574+out_opq:
1facf9fc 25575+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
25576+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
25577+ rerr = au_diropq_remove(dentry, bdst);
25578+ mutex_unlock(&h_inode->i_mutex);
25579+ if (unlikely(rerr)) {
25580+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
25581+ AuDLNPair(dentry), bdst, rerr);
25582+ err = -EIO;
25583+ goto out;
25584+ }
25585+ }
4f0767ce 25586+out_dir:
1facf9fc 25587+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
25588+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
25589+ if (unlikely(rerr)) {
25590+ AuIOErr("failed removing %.*s b%d (%d)\n",
25591+ AuDLNPair(dentry), bdst, rerr);
25592+ err = -EIO;
25593+ }
25594+ }
4f0767ce 25595+out_put:
1facf9fc 25596+ au_set_h_dptr(dentry, bdst, NULL);
25597+ if (au_dbend(dentry) == bdst)
25598+ au_update_dbend(dentry);
4f0767ce 25599+out:
1facf9fc 25600+ dput(parent);
25601+ return err;
25602+}
25603+
25604+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
25605+{
25606+ int err;
25607+ struct au_cpdown_dir_args args = {
25608+ .parent = dget_parent(dentry),
25609+ .flags = 0
25610+ };
25611+
25612+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
25613+ dput(args.parent);
25614+
25615+ return err;
25616+}
25617+
25618+/* ---------------------------------------------------------------------- */
25619+
25620+/* policies for create */
25621+
4a4d8108
AM
25622+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
25623+{
25624+ int err, i, j, ndentry;
25625+ aufs_bindex_t bopq;
25626+ struct au_dcsub_pages dpages;
25627+ struct au_dpage *dpage;
25628+ struct dentry **dentries, *parent, *d;
25629+
25630+ err = au_dpages_init(&dpages, GFP_NOFS);
25631+ if (unlikely(err))
25632+ goto out;
25633+ parent = dget_parent(dentry);
027c5e7a 25634+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
25635+ if (unlikely(err))
25636+ goto out_free;
25637+
25638+ err = bindex;
25639+ for (i = 0; i < dpages.ndpage; i++) {
25640+ dpage = dpages.dpages + i;
25641+ dentries = dpage->dentries;
25642+ ndentry = dpage->ndentry;
25643+ for (j = 0; j < ndentry; j++) {
25644+ d = dentries[j];
25645+ di_read_lock_parent2(d, !AuLock_IR);
25646+ bopq = au_dbdiropq(d);
25647+ di_read_unlock(d, !AuLock_IR);
25648+ if (bopq >= 0 && bopq < err)
25649+ err = bopq;
25650+ }
25651+ }
25652+
25653+out_free:
25654+ dput(parent);
25655+ au_dpages_free(&dpages);
25656+out:
25657+ return err;
25658+}
25659+
1facf9fc 25660+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
25661+{
25662+ for (; bindex >= 0; bindex--)
25663+ if (!au_br_rdonly(au_sbr(sb, bindex)))
25664+ return bindex;
25665+ return -EROFS;
25666+}
25667+
25668+/* top down parent */
25669+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
25670+{
25671+ int err;
25672+ aufs_bindex_t bstart, bindex;
25673+ struct super_block *sb;
25674+ struct dentry *parent, *h_parent;
25675+
25676+ sb = dentry->d_sb;
25677+ bstart = au_dbstart(dentry);
25678+ err = bstart;
25679+ if (!au_br_rdonly(au_sbr(sb, bstart)))
25680+ goto out;
25681+
25682+ err = -EROFS;
25683+ parent = dget_parent(dentry);
25684+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
25685+ h_parent = au_h_dptr(parent, bindex);
25686+ if (!h_parent || !h_parent->d_inode)
25687+ continue;
25688+
25689+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
25690+ err = bindex;
25691+ break;
25692+ }
25693+ }
25694+ dput(parent);
25695+
25696+ /* bottom up here */
4a4d8108 25697+ if (unlikely(err < 0)) {
1facf9fc 25698+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
25699+ if (err >= 0)
25700+ err = au_wbr_nonopq(dentry, err);
25701+ }
1facf9fc 25702+
4f0767ce 25703+out:
1facf9fc 25704+ AuDbg("b%d\n", err);
25705+ return err;
25706+}
25707+
25708+/* ---------------------------------------------------------------------- */
25709+
25710+/* an exception for the policy other than tdp */
25711+static int au_wbr_create_exp(struct dentry *dentry)
25712+{
25713+ int err;
25714+ aufs_bindex_t bwh, bdiropq;
25715+ struct dentry *parent;
25716+
25717+ err = -1;
25718+ bwh = au_dbwh(dentry);
25719+ parent = dget_parent(dentry);
25720+ bdiropq = au_dbdiropq(parent);
25721+ if (bwh >= 0) {
25722+ if (bdiropq >= 0)
25723+ err = min(bdiropq, bwh);
25724+ else
25725+ err = bwh;
25726+ AuDbg("%d\n", err);
25727+ } else if (bdiropq >= 0) {
25728+ err = bdiropq;
25729+ AuDbg("%d\n", err);
25730+ }
25731+ dput(parent);
25732+
4a4d8108
AM
25733+ if (err >= 0)
25734+ err = au_wbr_nonopq(dentry, err);
25735+
1facf9fc 25736+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
25737+ err = -1;
25738+
25739+ AuDbg("%d\n", err);
25740+ return err;
25741+}
25742+
25743+/* ---------------------------------------------------------------------- */
25744+
25745+/* round robin */
25746+static int au_wbr_create_init_rr(struct super_block *sb)
25747+{
25748+ int err;
25749+
25750+ err = au_wbr_bu(sb, au_sbend(sb));
25751+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 25752+ /* smp_mb(); */
1facf9fc 25753+
25754+ AuDbg("b%d\n", err);
25755+ return err;
25756+}
25757+
25758+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
25759+{
25760+ int err, nbr;
25761+ unsigned int u;
25762+ aufs_bindex_t bindex, bend;
25763+ struct super_block *sb;
25764+ atomic_t *next;
25765+
25766+ err = au_wbr_create_exp(dentry);
25767+ if (err >= 0)
25768+ goto out;
25769+
25770+ sb = dentry->d_sb;
25771+ next = &au_sbi(sb)->si_wbr_rr_next;
25772+ bend = au_sbend(sb);
25773+ nbr = bend + 1;
25774+ for (bindex = 0; bindex <= bend; bindex++) {
25775+ if (!isdir) {
25776+ err = atomic_dec_return(next) + 1;
25777+ /* modulo for 0 is meaningless */
25778+ if (unlikely(!err))
25779+ err = atomic_dec_return(next) + 1;
25780+ } else
25781+ err = atomic_read(next);
25782+ AuDbg("%d\n", err);
25783+ u = err;
25784+ err = u % nbr;
25785+ AuDbg("%d\n", err);
25786+ if (!au_br_rdonly(au_sbr(sb, err)))
25787+ break;
25788+ err = -EROFS;
25789+ }
25790+
4a4d8108
AM
25791+ if (err >= 0)
25792+ err = au_wbr_nonopq(dentry, err);
25793+
4f0767ce 25794+out:
1facf9fc 25795+ AuDbg("%d\n", err);
25796+ return err;
25797+}
25798+
25799+/* ---------------------------------------------------------------------- */
25800+
25801+/* most free space */
25802+static void au_mfs(struct dentry *dentry)
25803+{
25804+ struct super_block *sb;
25805+ struct au_branch *br;
25806+ struct au_wbr_mfs *mfs;
25807+ aufs_bindex_t bindex, bend;
25808+ int err;
25809+ unsigned long long b, bavail;
7f207e10 25810+ struct path h_path;
1facf9fc 25811+ /* reduce the stack usage */
25812+ struct kstatfs *st;
25813+
25814+ st = kmalloc(sizeof(*st), GFP_NOFS);
25815+ if (unlikely(!st)) {
25816+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
25817+ return;
25818+ }
25819+
25820+ bavail = 0;
25821+ sb = dentry->d_sb;
25822+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 25823+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 25824+ mfs->mfs_bindex = -EROFS;
25825+ mfs->mfsrr_bytes = 0;
25826+ bend = au_sbend(sb);
25827+ for (bindex = 0; bindex <= bend; bindex++) {
25828+ br = au_sbr(sb, bindex);
25829+ if (au_br_rdonly(br))
25830+ continue;
25831+
25832+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
25833+ h_path.mnt = br->br_mnt;
25834+ h_path.dentry = h_path.mnt->mnt_root;
25835+ err = vfs_statfs(&h_path, st);
1facf9fc 25836+ if (unlikely(err)) {
25837+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
25838+ continue;
25839+ }
25840+
25841+ /* when the available size is equal, select the lower one */
25842+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
25843+ || sizeof(b) < sizeof(st->f_bsize));
25844+ b = st->f_bavail * st->f_bsize;
25845+ br->br_wbr->wbr_bytes = b;
25846+ if (b >= bavail) {
25847+ bavail = b;
25848+ mfs->mfs_bindex = bindex;
25849+ mfs->mfs_jiffy = jiffies;
25850+ }
25851+ }
25852+
25853+ mfs->mfsrr_bytes = bavail;
25854+ AuDbg("b%d\n", mfs->mfs_bindex);
25855+ kfree(st);
25856+}
25857+
25858+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
25859+{
25860+ int err;
25861+ struct super_block *sb;
25862+ struct au_wbr_mfs *mfs;
25863+
25864+ err = au_wbr_create_exp(dentry);
25865+ if (err >= 0)
25866+ goto out;
25867+
25868+ sb = dentry->d_sb;
25869+ mfs = &au_sbi(sb)->si_wbr_mfs;
25870+ mutex_lock(&mfs->mfs_lock);
25871+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
25872+ || mfs->mfs_bindex < 0
25873+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
25874+ au_mfs(dentry);
25875+ mutex_unlock(&mfs->mfs_lock);
25876+ err = mfs->mfs_bindex;
25877+
4a4d8108
AM
25878+ if (err >= 0)
25879+ err = au_wbr_nonopq(dentry, err);
25880+
4f0767ce 25881+out:
1facf9fc 25882+ AuDbg("b%d\n", err);
25883+ return err;
25884+}
25885+
25886+static int au_wbr_create_init_mfs(struct super_block *sb)
25887+{
25888+ struct au_wbr_mfs *mfs;
25889+
25890+ mfs = &au_sbi(sb)->si_wbr_mfs;
25891+ mutex_init(&mfs->mfs_lock);
25892+ mfs->mfs_jiffy = 0;
25893+ mfs->mfs_bindex = -EROFS;
25894+
25895+ return 0;
25896+}
25897+
25898+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
25899+{
25900+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
25901+ return 0;
25902+}
25903+
25904+/* ---------------------------------------------------------------------- */
25905+
25906+/* most free space and then round robin */
25907+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
25908+{
25909+ int err;
25910+ struct au_wbr_mfs *mfs;
25911+
25912+ err = au_wbr_create_mfs(dentry, isdir);
25913+ if (err >= 0) {
25914+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 25915+ mutex_lock(&mfs->mfs_lock);
1facf9fc 25916+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
25917+ err = au_wbr_create_rr(dentry, isdir);
dece6358 25918+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 25919+ }
25920+
25921+ AuDbg("b%d\n", err);
25922+ return err;
25923+}
25924+
25925+static int au_wbr_create_init_mfsrr(struct super_block *sb)
25926+{
25927+ int err;
25928+
25929+ au_wbr_create_init_mfs(sb); /* ignore */
25930+ err = au_wbr_create_init_rr(sb);
25931+
25932+ return err;
25933+}
25934+
25935+/* ---------------------------------------------------------------------- */
25936+
25937+/* top down parent and most free space */
25938+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
25939+{
25940+ int err, e2;
25941+ unsigned long long b;
25942+ aufs_bindex_t bindex, bstart, bend;
25943+ struct super_block *sb;
25944+ struct dentry *parent, *h_parent;
25945+ struct au_branch *br;
25946+
25947+ err = au_wbr_create_tdp(dentry, isdir);
25948+ if (unlikely(err < 0))
25949+ goto out;
25950+ parent = dget_parent(dentry);
25951+ bstart = au_dbstart(parent);
25952+ bend = au_dbtaildir(parent);
25953+ if (bstart == bend)
25954+ goto out_parent; /* success */
25955+
25956+ e2 = au_wbr_create_mfs(dentry, isdir);
25957+ if (e2 < 0)
25958+ goto out_parent; /* success */
25959+
25960+ /* when the available size is equal, select upper one */
25961+ sb = dentry->d_sb;
25962+ br = au_sbr(sb, err);
25963+ b = br->br_wbr->wbr_bytes;
25964+ AuDbg("b%d, %llu\n", err, b);
25965+
25966+ for (bindex = bstart; bindex <= bend; bindex++) {
25967+ h_parent = au_h_dptr(parent, bindex);
25968+ if (!h_parent || !h_parent->d_inode)
25969+ continue;
25970+
25971+ br = au_sbr(sb, bindex);
25972+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
25973+ b = br->br_wbr->wbr_bytes;
25974+ err = bindex;
25975+ AuDbg("b%d, %llu\n", err, b);
25976+ }
25977+ }
25978+
4a4d8108
AM
25979+ if (err >= 0)
25980+ err = au_wbr_nonopq(dentry, err);
25981+
4f0767ce 25982+out_parent:
1facf9fc 25983+ dput(parent);
4f0767ce 25984+out:
1facf9fc 25985+ AuDbg("b%d\n", err);
25986+ return err;
25987+}
25988+
25989+/* ---------------------------------------------------------------------- */
25990+
25991+/* policies for copyup */
25992+
25993+/* top down parent */
25994+static int au_wbr_copyup_tdp(struct dentry *dentry)
25995+{
25996+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
25997+}
25998+
25999+/* bottom up parent */
26000+static int au_wbr_copyup_bup(struct dentry *dentry)
26001+{
26002+ int err;
26003+ aufs_bindex_t bindex, bstart;
26004+ struct dentry *parent, *h_parent;
26005+ struct super_block *sb;
26006+
26007+ err = -EROFS;
26008+ sb = dentry->d_sb;
26009+ parent = dget_parent(dentry);
26010+ bstart = au_dbstart(parent);
26011+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
26012+ h_parent = au_h_dptr(parent, bindex);
26013+ if (!h_parent || !h_parent->d_inode)
26014+ continue;
26015+
26016+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
26017+ err = bindex;
26018+ break;
26019+ }
26020+ }
26021+ dput(parent);
26022+
26023+ /* bottom up here */
26024+ if (unlikely(err < 0))
26025+ err = au_wbr_bu(sb, bstart - 1);
26026+
26027+ AuDbg("b%d\n", err);
26028+ return err;
26029+}
26030+
26031+/* bottom up */
26032+static int au_wbr_copyup_bu(struct dentry *dentry)
26033+{
26034+ int err;
4a4d8108 26035+ aufs_bindex_t bstart;
1facf9fc 26036+
4a4d8108
AM
26037+ bstart = au_dbstart(dentry);
26038+ err = au_wbr_bu(dentry->d_sb, bstart);
26039+ AuDbg("b%d\n", err);
26040+ if (err > bstart)
26041+ err = au_wbr_nonopq(dentry, err);
1facf9fc 26042+
26043+ AuDbg("b%d\n", err);
26044+ return err;
26045+}
26046+
26047+/* ---------------------------------------------------------------------- */
26048+
26049+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
26050+ [AuWbrCopyup_TDP] = {
26051+ .copyup = au_wbr_copyup_tdp
26052+ },
26053+ [AuWbrCopyup_BUP] = {
26054+ .copyup = au_wbr_copyup_bup
26055+ },
26056+ [AuWbrCopyup_BU] = {
26057+ .copyup = au_wbr_copyup_bu
26058+ }
26059+};
26060+
26061+struct au_wbr_create_operations au_wbr_create_ops[] = {
26062+ [AuWbrCreate_TDP] = {
26063+ .create = au_wbr_create_tdp
26064+ },
26065+ [AuWbrCreate_RR] = {
26066+ .create = au_wbr_create_rr,
26067+ .init = au_wbr_create_init_rr
26068+ },
26069+ [AuWbrCreate_MFS] = {
26070+ .create = au_wbr_create_mfs,
26071+ .init = au_wbr_create_init_mfs,
26072+ .fin = au_wbr_create_fin_mfs
26073+ },
26074+ [AuWbrCreate_MFSV] = {
26075+ .create = au_wbr_create_mfs,
26076+ .init = au_wbr_create_init_mfs,
26077+ .fin = au_wbr_create_fin_mfs
26078+ },
26079+ [AuWbrCreate_MFSRR] = {
26080+ .create = au_wbr_create_mfsrr,
26081+ .init = au_wbr_create_init_mfsrr,
26082+ .fin = au_wbr_create_fin_mfs
26083+ },
26084+ [AuWbrCreate_MFSRRV] = {
26085+ .create = au_wbr_create_mfsrr,
26086+ .init = au_wbr_create_init_mfsrr,
26087+ .fin = au_wbr_create_fin_mfs
26088+ },
26089+ [AuWbrCreate_PMFS] = {
26090+ .create = au_wbr_create_pmfs,
26091+ .init = au_wbr_create_init_mfs,
26092+ .fin = au_wbr_create_fin_mfs
26093+ },
26094+ [AuWbrCreate_PMFSV] = {
26095+ .create = au_wbr_create_pmfs,
26096+ .init = au_wbr_create_init_mfs,
26097+ .fin = au_wbr_create_fin_mfs
26098+ }
26099+};
7f207e10
AM
26100diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
26101--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
26102+++ linux/fs/aufs/whout.c 2011-03-21 20:22:06.860602399 +0100
26103@@ -0,0 +1,1062 @@
1facf9fc 26104+/*
027c5e7a 26105+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 26106+ *
26107+ * This program, aufs is free software; you can redistribute it and/or modify
26108+ * it under the terms of the GNU General Public License as published by
26109+ * the Free Software Foundation; either version 2 of the License, or
26110+ * (at your option) any later version.
dece6358
AM
26111+ *
26112+ * This program is distributed in the hope that it will be useful,
26113+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26114+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26115+ * GNU General Public License for more details.
26116+ *
26117+ * You should have received a copy of the GNU General Public License
26118+ * along with this program; if not, write to the Free Software
26119+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26120+ */
26121+
26122+/*
26123+ * whiteout for logical deletion and opaque directory
26124+ */
26125+
26126+#include <linux/fs.h>
26127+#include "aufs.h"
26128+
26129+#define WH_MASK S_IRUGO
26130+
26131+/*
26132+ * If a directory contains this file, then it is opaque. We start with the
26133+ * .wh. flag so that it is blocked by lookup.
26134+ */
26135+static struct qstr diropq_name = {
26136+ .name = AUFS_WH_DIROPQ,
26137+ .len = sizeof(AUFS_WH_DIROPQ) - 1
26138+};
26139+
26140+/*
26141+ * generate whiteout name, which is NOT terminated by NULL.
26142+ * @name: original d_name.name
26143+ * @len: original d_name.len
26144+ * @wh: whiteout qstr
26145+ * returns zero when succeeds, otherwise error.
26146+ * succeeded value as wh->name should be freed by kfree().
26147+ */
26148+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
26149+{
26150+ char *p;
26151+
26152+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
26153+ return -ENAMETOOLONG;
26154+
26155+ wh->len = name->len + AUFS_WH_PFX_LEN;
26156+ p = kmalloc(wh->len, GFP_NOFS);
26157+ wh->name = p;
26158+ if (p) {
26159+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
26160+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
26161+ /* smp_mb(); */
26162+ return 0;
26163+ }
26164+ return -ENOMEM;
26165+}
26166+
26167+/* ---------------------------------------------------------------------- */
26168+
26169+/*
26170+ * test if the @wh_name exists under @h_parent.
26171+ * @try_sio specifies the necessary of super-io.
26172+ */
26173+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
26174+ struct au_branch *br, int try_sio)
26175+{
26176+ int err;
26177+ struct dentry *wh_dentry;
1facf9fc 26178+
1facf9fc 26179+ if (!try_sio)
26180+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
26181+ else
26182+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
26183+ err = PTR_ERR(wh_dentry);
26184+ if (IS_ERR(wh_dentry))
26185+ goto out;
26186+
26187+ err = 0;
26188+ if (!wh_dentry->d_inode)
26189+ goto out_wh; /* success */
26190+
26191+ err = 1;
26192+ if (S_ISREG(wh_dentry->d_inode->i_mode))
26193+ goto out_wh; /* success */
26194+
26195+ err = -EIO;
26196+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
26197+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
26198+
4f0767ce 26199+out_wh:
1facf9fc 26200+ dput(wh_dentry);
4f0767ce 26201+out:
1facf9fc 26202+ return err;
26203+}
26204+
26205+/*
26206+ * test if the @h_dentry sets opaque or not.
26207+ */
26208+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
26209+{
26210+ int err;
26211+ struct inode *h_dir;
26212+
26213+ h_dir = h_dentry->d_inode;
26214+ err = au_wh_test(h_dentry, &diropq_name, br,
26215+ au_test_h_perm_sio(h_dir, MAY_EXEC));
26216+ return err;
26217+}
26218+
26219+/*
26220+ * returns a negative dentry whose name is unique and temporary.
26221+ */
26222+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
26223+ struct qstr *prefix)
26224+{
1facf9fc 26225+ struct dentry *dentry;
26226+ int i;
027c5e7a 26227+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 26228+ *name, *p;
027c5e7a 26229+ /* strict atomic_t is unnecessary here */
1facf9fc 26230+ static unsigned short cnt;
26231+ struct qstr qs;
26232+
4a4d8108
AM
26233+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
26234+
1facf9fc 26235+ name = defname;
027c5e7a
AM
26236+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
26237+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 26238+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 26239+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 26240+ goto out;
26241+ dentry = ERR_PTR(-ENOMEM);
26242+ name = kmalloc(qs.len + 1, GFP_NOFS);
26243+ if (unlikely(!name))
26244+ goto out;
26245+ }
26246+
26247+ /* doubly whiteout-ed */
26248+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
26249+ p = name + AUFS_WH_PFX_LEN * 2;
26250+ memcpy(p, prefix->name, prefix->len);
26251+ p += prefix->len;
26252+ *p++ = '.';
4a4d8108 26253+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 26254+
26255+ qs.name = name;
26256+ for (i = 0; i < 3; i++) {
b752ccd1 26257+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 26258+ dentry = au_sio_lkup_one(&qs, h_parent, br);
26259+ if (IS_ERR(dentry) || !dentry->d_inode)
26260+ goto out_name;
26261+ dput(dentry);
26262+ }
4a4d8108 26263+ /* pr_warning("could not get random name\n"); */
1facf9fc 26264+ dentry = ERR_PTR(-EEXIST);
26265+ AuDbg("%.*s\n", AuLNPair(&qs));
26266+ BUG();
26267+
4f0767ce 26268+out_name:
1facf9fc 26269+ if (name != defname)
26270+ kfree(name);
4f0767ce 26271+out:
4a4d8108 26272+ AuTraceErrPtr(dentry);
1facf9fc 26273+ return dentry;
1facf9fc 26274+}
26275+
26276+/*
26277+ * rename the @h_dentry on @br to the whiteouted temporary name.
26278+ */
26279+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
26280+{
26281+ int err;
26282+ struct path h_path = {
26283+ .mnt = br->br_mnt
26284+ };
26285+ struct inode *h_dir;
26286+ struct dentry *h_parent;
26287+
26288+ h_parent = h_dentry->d_parent; /* dir inode is locked */
26289+ h_dir = h_parent->d_inode;
26290+ IMustLock(h_dir);
26291+
26292+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
26293+ err = PTR_ERR(h_path.dentry);
26294+ if (IS_ERR(h_path.dentry))
26295+ goto out;
26296+
26297+ /* under the same dir, no need to lock_rename() */
26298+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
26299+ AuTraceErr(err);
26300+ dput(h_path.dentry);
26301+
4f0767ce 26302+out:
4a4d8108 26303+ AuTraceErr(err);
1facf9fc 26304+ return err;
26305+}
26306+
26307+/* ---------------------------------------------------------------------- */
26308+/*
26309+ * functions for removing a whiteout
26310+ */
26311+
26312+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
26313+{
26314+ int force;
26315+
26316+ /*
26317+ * forces superio when the dir has a sticky bit.
26318+ * this may be a violation of unix fs semantics.
26319+ */
26320+ force = (h_dir->i_mode & S_ISVTX)
26321+ && h_path->dentry->d_inode->i_uid != current_fsuid();
26322+ return vfsub_unlink(h_dir, h_path, force);
26323+}
26324+
26325+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
26326+ struct dentry *dentry)
26327+{
26328+ int err;
26329+
26330+ err = do_unlink_wh(h_dir, h_path);
26331+ if (!err && dentry)
26332+ au_set_dbwh(dentry, -1);
26333+
26334+ return err;
26335+}
26336+
26337+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
26338+ struct au_branch *br)
26339+{
26340+ int err;
26341+ struct path h_path = {
26342+ .mnt = br->br_mnt
26343+ };
26344+
26345+ err = 0;
26346+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
26347+ if (IS_ERR(h_path.dentry))
26348+ err = PTR_ERR(h_path.dentry);
26349+ else {
26350+ if (h_path.dentry->d_inode
26351+ && S_ISREG(h_path.dentry->d_inode->i_mode))
26352+ err = do_unlink_wh(h_parent->d_inode, &h_path);
26353+ dput(h_path.dentry);
26354+ }
26355+
26356+ return err;
26357+}
26358+
26359+/* ---------------------------------------------------------------------- */
26360+/*
26361+ * initialize/clean whiteout for a branch
26362+ */
26363+
26364+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
26365+ const int isdir)
26366+{
26367+ int err;
26368+
26369+ if (!whpath->dentry->d_inode)
26370+ return;
26371+
26372+ err = mnt_want_write(whpath->mnt);
26373+ if (!err) {
26374+ if (isdir)
26375+ err = vfsub_rmdir(h_dir, whpath);
26376+ else
26377+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
26378+ mnt_drop_write(whpath->mnt);
26379+ }
26380+ if (unlikely(err))
4a4d8108
AM
26381+ pr_warning("failed removing %.*s (%d), ignored.\n",
26382+ AuDLNPair(whpath->dentry), err);
1facf9fc 26383+}
26384+
26385+static int test_linkable(struct dentry *h_root)
26386+{
26387+ struct inode *h_dir = h_root->d_inode;
26388+
26389+ if (h_dir->i_op->link)
26390+ return 0;
26391+
4a4d8108
AM
26392+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
26393+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 26394+ return -ENOSYS;
26395+}
26396+
26397+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
26398+static int au_whdir(struct inode *h_dir, struct path *path)
26399+{
26400+ int err;
26401+
26402+ err = -EEXIST;
26403+ if (!path->dentry->d_inode) {
26404+ int mode = S_IRWXU;
26405+
26406+ if (au_test_nfs(path->dentry->d_sb))
26407+ mode |= S_IXUGO;
26408+ err = mnt_want_write(path->mnt);
26409+ if (!err) {
26410+ err = vfsub_mkdir(h_dir, path, mode);
26411+ mnt_drop_write(path->mnt);
26412+ }
26413+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
26414+ err = 0;
26415+ else
4a4d8108 26416+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 26417+
26418+ return err;
26419+}
26420+
26421+struct au_wh_base {
26422+ const struct qstr *name;
26423+ struct dentry *dentry;
26424+};
26425+
26426+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
26427+ struct path *h_path)
26428+{
26429+ h_path->dentry = base[AuBrWh_BASE].dentry;
26430+ au_wh_clean(h_dir, h_path, /*isdir*/0);
26431+ h_path->dentry = base[AuBrWh_PLINK].dentry;
26432+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26433+ h_path->dentry = base[AuBrWh_ORPH].dentry;
26434+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26435+}
26436+
26437+/*
26438+ * returns tri-state,
26439+ * minus: error, caller should print the mesage
26440+ * zero: succuess
26441+ * plus: error, caller should NOT print the mesage
26442+ */
26443+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
26444+ int do_plink, struct au_wh_base base[],
26445+ struct path *h_path)
26446+{
26447+ int err;
26448+ struct inode *h_dir;
26449+
26450+ h_dir = h_root->d_inode;
26451+ h_path->dentry = base[AuBrWh_BASE].dentry;
26452+ au_wh_clean(h_dir, h_path, /*isdir*/0);
26453+ h_path->dentry = base[AuBrWh_PLINK].dentry;
26454+ if (do_plink) {
26455+ err = test_linkable(h_root);
26456+ if (unlikely(err)) {
26457+ err = 1;
26458+ goto out;
26459+ }
26460+
26461+ err = au_whdir(h_dir, h_path);
26462+ if (unlikely(err))
26463+ goto out;
26464+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
26465+ } else
26466+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26467+ h_path->dentry = base[AuBrWh_ORPH].dentry;
26468+ err = au_whdir(h_dir, h_path);
26469+ if (unlikely(err))
26470+ goto out;
26471+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
26472+
4f0767ce 26473+out:
1facf9fc 26474+ return err;
26475+}
26476+
26477+/*
26478+ * for the moment, aufs supports the branch filesystem which does not support
26479+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
26480+ * copyup failed. finally, such filesystem will not be used as the writable
26481+ * branch.
26482+ *
26483+ * returns tri-state, see above.
26484+ */
26485+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
26486+ int do_plink, struct au_wh_base base[],
26487+ struct path *h_path)
26488+{
26489+ int err;
26490+ struct inode *h_dir;
26491+
1308ab2a 26492+ WbrWhMustWriteLock(wbr);
26493+
1facf9fc 26494+ err = test_linkable(h_root);
26495+ if (unlikely(err)) {
26496+ err = 1;
26497+ goto out;
26498+ }
26499+
26500+ /*
26501+ * todo: should this create be done in /sbin/mount.aufs helper?
26502+ */
26503+ err = -EEXIST;
26504+ h_dir = h_root->d_inode;
26505+ if (!base[AuBrWh_BASE].dentry->d_inode) {
26506+ err = mnt_want_write(h_path->mnt);
26507+ if (!err) {
26508+ h_path->dentry = base[AuBrWh_BASE].dentry;
26509+ err = vfsub_create(h_dir, h_path, WH_MASK);
26510+ mnt_drop_write(h_path->mnt);
26511+ }
26512+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
26513+ err = 0;
26514+ else
4a4d8108
AM
26515+ pr_err("unknown %.*s/%.*s exists\n",
26516+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 26517+ if (unlikely(err))
26518+ goto out;
26519+
26520+ h_path->dentry = base[AuBrWh_PLINK].dentry;
26521+ if (do_plink) {
26522+ err = au_whdir(h_dir, h_path);
26523+ if (unlikely(err))
26524+ goto out;
26525+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
26526+ } else
26527+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26528+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
26529+
26530+ h_path->dentry = base[AuBrWh_ORPH].dentry;
26531+ err = au_whdir(h_dir, h_path);
26532+ if (unlikely(err))
26533+ goto out;
26534+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
26535+
4f0767ce 26536+out:
1facf9fc 26537+ return err;
26538+}
26539+
26540+/*
26541+ * initialize the whiteout base file/dir for @br.
26542+ */
26543+int au_wh_init(struct dentry *h_root, struct au_branch *br,
26544+ struct super_block *sb)
26545+{
26546+ int err, i;
26547+ const unsigned char do_plink
26548+ = !!au_opt_test(au_mntflags(sb), PLINK);
26549+ struct path path = {
26550+ .mnt = br->br_mnt
26551+ };
26552+ struct inode *h_dir;
26553+ struct au_wbr *wbr = br->br_wbr;
26554+ static const struct qstr base_name[] = {
26555+ [AuBrWh_BASE] = {
26556+ .name = AUFS_BASE_NAME,
26557+ .len = sizeof(AUFS_BASE_NAME) - 1
26558+ },
26559+ [AuBrWh_PLINK] = {
26560+ .name = AUFS_PLINKDIR_NAME,
26561+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
26562+ },
26563+ [AuBrWh_ORPH] = {
26564+ .name = AUFS_ORPHDIR_NAME,
26565+ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
26566+ }
26567+ };
26568+ struct au_wh_base base[] = {
26569+ [AuBrWh_BASE] = {
26570+ .name = base_name + AuBrWh_BASE,
26571+ .dentry = NULL
26572+ },
26573+ [AuBrWh_PLINK] = {
26574+ .name = base_name + AuBrWh_PLINK,
26575+ .dentry = NULL
26576+ },
26577+ [AuBrWh_ORPH] = {
26578+ .name = base_name + AuBrWh_ORPH,
26579+ .dentry = NULL
26580+ }
26581+ };
26582+
1308ab2a 26583+ if (wbr)
26584+ WbrWhMustWriteLock(wbr);
1facf9fc 26585+
1facf9fc 26586+ for (i = 0; i < AuBrWh_Last; i++) {
26587+ /* doubly whiteouted */
26588+ struct dentry *d;
26589+
26590+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
26591+ err = PTR_ERR(d);
26592+ if (IS_ERR(d))
26593+ goto out;
26594+
26595+ base[i].dentry = d;
26596+ AuDebugOn(wbr
26597+ && wbr->wbr_wh[i]
26598+ && wbr->wbr_wh[i] != base[i].dentry);
26599+ }
26600+
26601+ if (wbr)
26602+ for (i = 0; i < AuBrWh_Last; i++) {
26603+ dput(wbr->wbr_wh[i]);
26604+ wbr->wbr_wh[i] = NULL;
26605+ }
26606+
26607+ err = 0;
1facf9fc 26608+ switch (br->br_perm) {
26609+ case AuBrPerm_RO:
26610+ case AuBrPerm_ROWH:
26611+ case AuBrPerm_RR:
26612+ case AuBrPerm_RRWH:
4a4d8108 26613+ h_dir = h_root->d_inode;
1facf9fc 26614+ au_wh_init_ro(h_dir, base, &path);
26615+ break;
26616+
26617+ case AuBrPerm_RWNoLinkWH:
26618+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
26619+ if (err > 0)
26620+ goto out;
26621+ else if (err)
26622+ goto out_err;
26623+ break;
26624+
26625+ case AuBrPerm_RW:
26626+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
26627+ if (err > 0)
26628+ goto out;
26629+ else if (err)
26630+ goto out_err;
26631+ break;
26632+
26633+ default:
26634+ BUG();
26635+ }
26636+ goto out; /* success */
26637+
4f0767ce 26638+out_err:
4a4d8108
AM
26639+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
26640+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 26641+out:
1facf9fc 26642+ for (i = 0; i < AuBrWh_Last; i++)
26643+ dput(base[i].dentry);
26644+ return err;
26645+}
26646+
26647+/* ---------------------------------------------------------------------- */
26648+/*
26649+ * whiteouts are all hard-linked usually.
26650+ * when its link count reaches a ceiling, we create a new whiteout base
26651+ * asynchronously.
26652+ */
26653+
26654+struct reinit_br_wh {
26655+ struct super_block *sb;
26656+ struct au_branch *br;
26657+};
26658+
26659+static void reinit_br_wh(void *arg)
26660+{
26661+ int err;
26662+ aufs_bindex_t bindex;
26663+ struct path h_path;
26664+ struct reinit_br_wh *a = arg;
26665+ struct au_wbr *wbr;
26666+ struct inode *dir;
26667+ struct dentry *h_root;
26668+ struct au_hinode *hdir;
26669+
26670+ err = 0;
26671+ wbr = a->br->br_wbr;
26672+ /* big aufs lock */
26673+ si_noflush_write_lock(a->sb);
26674+ if (!au_br_writable(a->br->br_perm))
26675+ goto out;
26676+ bindex = au_br_index(a->sb, a->br->br_id);
26677+ if (unlikely(bindex < 0))
26678+ goto out;
26679+
1308ab2a 26680+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 26681+ dir = a->sb->s_root->d_inode;
1facf9fc 26682+ hdir = au_hi(dir, bindex);
26683+ h_root = au_h_dptr(a->sb->s_root, bindex);
26684+
4a4d8108 26685+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 26686+ wbr_wh_write_lock(wbr);
26687+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
26688+ h_root, a->br);
26689+ if (!err) {
26690+ err = mnt_want_write(a->br->br_mnt);
26691+ if (!err) {
26692+ h_path.dentry = wbr->wbr_whbase;
26693+ h_path.mnt = a->br->br_mnt;
26694+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
26695+ mnt_drop_write(a->br->br_mnt);
26696+ }
26697+ } else {
4a4d8108
AM
26698+ pr_warning("%.*s is moved, ignored\n",
26699+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 26700+ err = 0;
26701+ }
26702+ dput(wbr->wbr_whbase);
26703+ wbr->wbr_whbase = NULL;
26704+ if (!err)
26705+ err = au_wh_init(h_root, a->br, a->sb);
26706+ wbr_wh_write_unlock(wbr);
4a4d8108 26707+ au_hn_imtx_unlock(hdir);
1308ab2a 26708+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 26709+
4f0767ce 26710+out:
1facf9fc 26711+ if (wbr)
26712+ atomic_dec(&wbr->wbr_wh_running);
26713+ atomic_dec(&a->br->br_count);
1facf9fc 26714+ si_write_unlock(a->sb);
027c5e7a 26715+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
1facf9fc 26716+ kfree(arg);
26717+ if (unlikely(err))
26718+ AuIOErr("err %d\n", err);
26719+}
26720+
26721+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
26722+{
26723+ int do_dec, wkq_err;
26724+ struct reinit_br_wh *arg;
26725+
26726+ do_dec = 1;
26727+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
26728+ goto out;
26729+
26730+ /* ignore ENOMEM */
26731+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
26732+ if (arg) {
26733+ /*
26734+ * dec(wh_running), kfree(arg) and dec(br_count)
26735+ * in reinit function
26736+ */
26737+ arg->sb = sb;
26738+ arg->br = br;
26739+ atomic_inc(&br->br_count);
26740+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
26741+ if (unlikely(wkq_err)) {
26742+ atomic_dec(&br->br_wbr->wbr_wh_running);
26743+ atomic_dec(&br->br_count);
26744+ kfree(arg);
26745+ }
26746+ do_dec = 0;
26747+ }
26748+
4f0767ce 26749+out:
1facf9fc 26750+ if (do_dec)
26751+ atomic_dec(&br->br_wbr->wbr_wh_running);
26752+}
26753+
26754+/* ---------------------------------------------------------------------- */
26755+
26756+/*
26757+ * create the whiteout @wh.
26758+ */
26759+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
26760+ struct dentry *wh)
26761+{
26762+ int err;
26763+ struct path h_path = {
26764+ .dentry = wh
26765+ };
26766+ struct au_branch *br;
26767+ struct au_wbr *wbr;
26768+ struct dentry *h_parent;
26769+ struct inode *h_dir;
26770+
26771+ h_parent = wh->d_parent; /* dir inode is locked */
26772+ h_dir = h_parent->d_inode;
26773+ IMustLock(h_dir);
26774+
26775+ br = au_sbr(sb, bindex);
26776+ h_path.mnt = br->br_mnt;
26777+ wbr = br->br_wbr;
26778+ wbr_wh_read_lock(wbr);
26779+ if (wbr->wbr_whbase) {
26780+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
26781+ if (!err || err != -EMLINK)
26782+ goto out;
26783+
26784+ /* link count full. re-initialize br_whbase. */
26785+ kick_reinit_br_wh(sb, br);
26786+ }
26787+
26788+ /* return this error in this context */
26789+ err = vfsub_create(h_dir, &h_path, WH_MASK);
26790+
4f0767ce 26791+out:
1facf9fc 26792+ wbr_wh_read_unlock(wbr);
26793+ return err;
26794+}
26795+
26796+/* ---------------------------------------------------------------------- */
26797+
26798+/*
26799+ * create or remove the diropq.
26800+ */
26801+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
26802+ unsigned int flags)
26803+{
26804+ struct dentry *opq_dentry, *h_dentry;
26805+ struct super_block *sb;
26806+ struct au_branch *br;
26807+ int err;
26808+
26809+ sb = dentry->d_sb;
26810+ br = au_sbr(sb, bindex);
26811+ h_dentry = au_h_dptr(dentry, bindex);
26812+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
26813+ if (IS_ERR(opq_dentry))
26814+ goto out;
26815+
26816+ if (au_ftest_diropq(flags, CREATE)) {
26817+ err = link_or_create_wh(sb, bindex, opq_dentry);
26818+ if (!err) {
26819+ au_set_dbdiropq(dentry, bindex);
26820+ goto out; /* success */
26821+ }
26822+ } else {
26823+ struct path tmp = {
26824+ .dentry = opq_dentry,
26825+ .mnt = br->br_mnt
26826+ };
26827+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
26828+ if (!err)
26829+ au_set_dbdiropq(dentry, -1);
26830+ }
26831+ dput(opq_dentry);
26832+ opq_dentry = ERR_PTR(err);
26833+
4f0767ce 26834+out:
1facf9fc 26835+ return opq_dentry;
26836+}
26837+
26838+struct do_diropq_args {
26839+ struct dentry **errp;
26840+ struct dentry *dentry;
26841+ aufs_bindex_t bindex;
26842+ unsigned int flags;
26843+};
26844+
26845+static void call_do_diropq(void *args)
26846+{
26847+ struct do_diropq_args *a = args;
26848+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
26849+}
26850+
26851+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
26852+ unsigned int flags)
26853+{
26854+ struct dentry *diropq, *h_dentry;
26855+
26856+ h_dentry = au_h_dptr(dentry, bindex);
26857+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
26858+ diropq = do_diropq(dentry, bindex, flags);
26859+ else {
26860+ int wkq_err;
26861+ struct do_diropq_args args = {
26862+ .errp = &diropq,
26863+ .dentry = dentry,
26864+ .bindex = bindex,
26865+ .flags = flags
26866+ };
26867+
26868+ wkq_err = au_wkq_wait(call_do_diropq, &args);
26869+ if (unlikely(wkq_err))
26870+ diropq = ERR_PTR(wkq_err);
26871+ }
26872+
26873+ return diropq;
26874+}
26875+
26876+/* ---------------------------------------------------------------------- */
26877+
26878+/*
26879+ * lookup whiteout dentry.
26880+ * @h_parent: lower parent dentry which must exist and be locked
26881+ * @base_name: name of dentry which will be whiteouted
26882+ * returns dentry for whiteout.
26883+ */
26884+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
26885+ struct au_branch *br)
26886+{
26887+ int err;
26888+ struct qstr wh_name;
26889+ struct dentry *wh_dentry;
26890+
26891+ err = au_wh_name_alloc(&wh_name, base_name);
26892+ wh_dentry = ERR_PTR(err);
26893+ if (!err) {
26894+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
26895+ kfree(wh_name.name);
26896+ }
26897+ return wh_dentry;
26898+}
26899+
26900+/*
26901+ * link/create a whiteout for @dentry on @bindex.
26902+ */
26903+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
26904+ struct dentry *h_parent)
26905+{
26906+ struct dentry *wh_dentry;
26907+ struct super_block *sb;
26908+ int err;
26909+
26910+ sb = dentry->d_sb;
26911+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
26912+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
26913+ err = link_or_create_wh(sb, bindex, wh_dentry);
26914+ if (!err)
26915+ au_set_dbwh(dentry, bindex);
26916+ else {
26917+ dput(wh_dentry);
26918+ wh_dentry = ERR_PTR(err);
26919+ }
26920+ }
26921+
26922+ return wh_dentry;
26923+}
26924+
26925+/* ---------------------------------------------------------------------- */
26926+
26927+/* Delete all whiteouts in this directory on branch bindex. */
26928+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
26929+ aufs_bindex_t bindex, struct au_branch *br)
26930+{
26931+ int err;
26932+ unsigned long ul, n;
26933+ struct qstr wh_name;
26934+ char *p;
26935+ struct hlist_head *head;
26936+ struct au_vdir_wh *tpos;
26937+ struct hlist_node *pos;
26938+ struct au_vdir_destr *str;
26939+
26940+ err = -ENOMEM;
4a4d8108 26941+ p = __getname_gfp(GFP_NOFS);
1facf9fc 26942+ wh_name.name = p;
26943+ if (unlikely(!wh_name.name))
26944+ goto out;
26945+
26946+ err = 0;
26947+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
26948+ p += AUFS_WH_PFX_LEN;
26949+ n = whlist->nh_num;
26950+ head = whlist->nh_head;
26951+ for (ul = 0; !err && ul < n; ul++, head++) {
26952+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
26953+ if (tpos->wh_bindex != bindex)
26954+ continue;
26955+
26956+ str = &tpos->wh_str;
26957+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
26958+ memcpy(p, str->name, str->len);
26959+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
26960+ err = unlink_wh_name(h_dentry, &wh_name, br);
26961+ if (!err)
26962+ continue;
26963+ break;
26964+ }
26965+ AuIOErr("whiteout name too long %.*s\n",
26966+ str->len, str->name);
26967+ err = -EIO;
26968+ break;
26969+ }
26970+ }
26971+ __putname(wh_name.name);
26972+
4f0767ce 26973+out:
1facf9fc 26974+ return err;
26975+}
26976+
26977+struct del_wh_children_args {
26978+ int *errp;
26979+ struct dentry *h_dentry;
1308ab2a 26980+ struct au_nhash *whlist;
1facf9fc 26981+ aufs_bindex_t bindex;
26982+ struct au_branch *br;
26983+};
26984+
26985+static void call_del_wh_children(void *args)
26986+{
26987+ struct del_wh_children_args *a = args;
1308ab2a 26988+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 26989+}
26990+
26991+/* ---------------------------------------------------------------------- */
26992+
26993+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
26994+{
26995+ struct au_whtmp_rmdir *whtmp;
dece6358 26996+ int err;
1308ab2a 26997+ unsigned int rdhash;
dece6358
AM
26998+
26999+ SiMustAnyLock(sb);
1facf9fc 27000+
27001+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
27002+ if (unlikely(!whtmp)) {
27003+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 27004+ goto out;
dece6358 27005+ }
1facf9fc 27006+
27007+ whtmp->dir = NULL;
027c5e7a 27008+ whtmp->br = NULL;
1facf9fc 27009+ whtmp->wh_dentry = NULL;
1308ab2a 27010+ /* no estimation for dir size */
27011+ rdhash = au_sbi(sb)->si_rdhash;
27012+ if (!rdhash)
27013+ rdhash = AUFS_RDHASH_DEF;
27014+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
27015+ if (unlikely(err)) {
27016+ kfree(whtmp);
27017+ whtmp = ERR_PTR(err);
27018+ }
dece6358 27019+
4f0767ce 27020+out:
dece6358 27021+ return whtmp;
1facf9fc 27022+}
27023+
27024+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
27025+{
027c5e7a
AM
27026+ if (whtmp->br)
27027+ atomic_dec(&whtmp->br->br_count);
1facf9fc 27028+ dput(whtmp->wh_dentry);
27029+ iput(whtmp->dir);
dece6358 27030+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 27031+ kfree(whtmp);
27032+}
27033+
27034+/*
27035+ * rmdir the whiteouted temporary named dir @h_dentry.
27036+ * @whlist: whiteouted children.
27037+ */
27038+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
27039+ struct dentry *wh_dentry, struct au_nhash *whlist)
27040+{
27041+ int err;
27042+ struct path h_tmp;
27043+ struct inode *wh_inode, *h_dir;
27044+ struct au_branch *br;
27045+
27046+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
27047+ IMustLock(h_dir);
27048+
27049+ br = au_sbr(dir->i_sb, bindex);
27050+ wh_inode = wh_dentry->d_inode;
27051+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
27052+
27053+ /*
27054+ * someone else might change some whiteouts while we were sleeping.
27055+ * it means this whlist may have an obsoleted entry.
27056+ */
27057+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
27058+ err = del_wh_children(wh_dentry, whlist, bindex, br);
27059+ else {
27060+ int wkq_err;
27061+ struct del_wh_children_args args = {
27062+ .errp = &err,
27063+ .h_dentry = wh_dentry,
1308ab2a 27064+ .whlist = whlist,
1facf9fc 27065+ .bindex = bindex,
27066+ .br = br
27067+ };
27068+
27069+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
27070+ if (unlikely(wkq_err))
27071+ err = wkq_err;
27072+ }
27073+ mutex_unlock(&wh_inode->i_mutex);
27074+
27075+ if (!err) {
27076+ h_tmp.dentry = wh_dentry;
27077+ h_tmp.mnt = br->br_mnt;
27078+ err = vfsub_rmdir(h_dir, &h_tmp);
1facf9fc 27079+ }
27080+
27081+ if (!err) {
27082+ if (au_ibstart(dir) == bindex) {
7f207e10 27083+ /* todo: dir->i_mutex is necessary */
1facf9fc 27084+ au_cpup_attr_timesizes(dir);
7f207e10 27085+ vfsub_drop_nlink(dir);
1facf9fc 27086+ }
27087+ return 0; /* success */
27088+ }
27089+
4a4d8108
AM
27090+ pr_warning("failed removing %.*s(%d), ignored\n",
27091+ AuDLNPair(wh_dentry), err);
1facf9fc 27092+ return err;
27093+}
27094+
27095+static void call_rmdir_whtmp(void *args)
27096+{
27097+ int err;
e49829fe 27098+ aufs_bindex_t bindex;
1facf9fc 27099+ struct au_whtmp_rmdir *a = args;
27100+ struct super_block *sb;
27101+ struct dentry *h_parent;
27102+ struct inode *h_dir;
1facf9fc 27103+ struct au_hinode *hdir;
27104+
27105+ /* rmdir by nfsd may cause deadlock with this i_mutex */
27106+ /* mutex_lock(&a->dir->i_mutex); */
e49829fe 27107+ err = -EROFS;
1facf9fc 27108+ sb = a->dir->i_sb;
e49829fe
JR
27109+ si_read_lock(sb, !AuLock_FLUSH);
27110+ if (!au_br_writable(a->br->br_perm))
27111+ goto out;
27112+ bindex = au_br_index(sb, a->br->br_id);
27113+ if (unlikely(bindex < 0))
1facf9fc 27114+ goto out;
27115+
27116+ err = -EIO;
1facf9fc 27117+ ii_write_lock_parent(a->dir);
27118+ h_parent = dget_parent(a->wh_dentry);
27119+ h_dir = h_parent->d_inode;
e49829fe 27120+ hdir = au_hi(a->dir, bindex);
4a4d8108 27121+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
27122+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
27123+ a->br);
1facf9fc 27124+ if (!err) {
e49829fe 27125+ err = mnt_want_write(a->br->br_mnt);
1facf9fc 27126+ if (!err) {
e49829fe 27127+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
dece6358 27128+ &a->whlist);
e49829fe 27129+ mnt_drop_write(a->br->br_mnt);
1facf9fc 27130+ }
27131+ }
4a4d8108 27132+ au_hn_imtx_unlock(hdir);
1facf9fc 27133+ dput(h_parent);
27134+ ii_write_unlock(a->dir);
27135+
4f0767ce 27136+out:
1facf9fc 27137+ /* mutex_unlock(&a->dir->i_mutex); */
1facf9fc 27138+ au_whtmp_rmdir_free(a);
027c5e7a
AM
27139+ si_read_unlock(sb);
27140+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 27141+ if (unlikely(err))
27142+ AuIOErr("err %d\n", err);
27143+}
27144+
27145+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
27146+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
27147+{
27148+ int wkq_err;
e49829fe 27149+ struct super_block *sb;
1facf9fc 27150+
27151+ IMustLock(dir);
27152+
27153+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 27154+ sb = dir->i_sb;
1facf9fc 27155+ args->dir = au_igrab(dir);
e49829fe
JR
27156+ args->br = au_sbr(sb, bindex);
27157+ atomic_inc(&args->br->br_count);
1facf9fc 27158+ args->wh_dentry = dget(wh_dentry);
e49829fe 27159+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb);
1facf9fc 27160+ if (unlikely(wkq_err)) {
4a4d8108
AM
27161+ pr_warning("rmdir error %.*s (%d), ignored\n",
27162+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 27163+ au_whtmp_rmdir_free(args);
27164+ }
27165+}
7f207e10
AM
27166diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
27167--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 27168+++ linux/fs/aufs/whout.h 2011-03-21 20:22:06.860602399 +0100
7f207e10 27169@@ -0,0 +1,89 @@
1facf9fc 27170+/*
027c5e7a 27171+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27172+ *
27173+ * This program, aufs is free software; you can redistribute it and/or modify
27174+ * it under the terms of the GNU General Public License as published by
27175+ * the Free Software Foundation; either version 2 of the License, or
27176+ * (at your option) any later version.
dece6358
AM
27177+ *
27178+ * This program is distributed in the hope that it will be useful,
27179+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27180+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27181+ * GNU General Public License for more details.
27182+ *
27183+ * You should have received a copy of the GNU General Public License
27184+ * along with this program; if not, write to the Free Software
27185+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27186+ */
27187+
27188+/*
27189+ * whiteout for logical deletion and opaque directory
27190+ */
27191+
27192+#ifndef __AUFS_WHOUT_H__
27193+#define __AUFS_WHOUT_H__
27194+
27195+#ifdef __KERNEL__
27196+
1facf9fc 27197+#include <linux/aufs_type.h>
27198+#include "dir.h"
27199+
27200+/* whout.c */
27201+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
27202+struct au_branch;
27203+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
27204+ struct au_branch *br, int try_sio);
27205+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
27206+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
27207+ struct qstr *prefix);
27208+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
27209+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
27210+ struct dentry *dentry);
27211+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
27212+ struct super_block *sb);
27213+
27214+/* diropq flags */
27215+#define AuDiropq_CREATE 1
27216+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
27217+#define au_fset_diropq(flags, name) \
27218+ do { (flags) |= AuDiropq_##name; } while (0)
27219+#define au_fclr_diropq(flags, name) \
27220+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 27221+
27222+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
27223+ unsigned int flags);
27224+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
27225+ struct au_branch *br);
27226+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
27227+ struct dentry *h_parent);
27228+
27229+/* real rmdir for the whiteout-ed dir */
27230+struct au_whtmp_rmdir {
27231+ struct inode *dir;
e49829fe 27232+ struct au_branch *br;
1facf9fc 27233+ struct dentry *wh_dentry;
dece6358 27234+ struct au_nhash whlist;
1facf9fc 27235+};
27236+
27237+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
27238+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
27239+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
27240+ struct dentry *wh_dentry, struct au_nhash *whlist);
27241+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
27242+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
27243+
27244+/* ---------------------------------------------------------------------- */
27245+
27246+static inline struct dentry *au_diropq_create(struct dentry *dentry,
27247+ aufs_bindex_t bindex)
27248+{
27249+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
27250+}
27251+
27252+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
27253+{
27254+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
27255+}
27256+
27257+#endif /* __KERNEL__ */
27258+#endif /* __AUFS_WHOUT_H__ */
7f207e10
AM
27259diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
27260--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
27261+++ linux/fs/aufs/wkq.c 2011-03-21 20:22:06.860602399 +0100
27262@@ -0,0 +1,236 @@
1facf9fc 27263+/*
027c5e7a 27264+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27265+ *
27266+ * This program, aufs is free software; you can redistribute it and/or modify
27267+ * it under the terms of the GNU General Public License as published by
27268+ * the Free Software Foundation; either version 2 of the License, or
27269+ * (at your option) any later version.
dece6358
AM
27270+ *
27271+ * This program is distributed in the hope that it will be useful,
27272+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27273+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27274+ * GNU General Public License for more details.
27275+ *
27276+ * You should have received a copy of the GNU General Public License
27277+ * along with this program; if not, write to the Free Software
27278+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27279+ */
27280+
27281+/*
27282+ * workqueue for asynchronous/super-io operations
27283+ * todo: try new dredential scheme
27284+ */
27285+
dece6358 27286+#include <linux/module.h>
1facf9fc 27287+#include "aufs.h"
27288+
b752ccd1
AM
27289+/* internal workqueue named AUFS_WKQ_NAME and AUFS_WKQ_PRE_NAME */
27290+enum {
27291+ AuWkq_INORMAL,
27292+ AuWkq_IPRE
27293+};
27294+
27295+static struct {
27296+ char *name;
27297+ struct workqueue_struct *wkq;
27298+} au_wkq[] = {
27299+ [AuWkq_INORMAL] = {
27300+ .name = AUFS_WKQ_NAME
27301+ },
27302+ [AuWkq_IPRE] = {
27303+ .name = AUFS_WKQ_PRE_NAME
27304+ }
27305+};
1facf9fc 27306+
27307+struct au_wkinfo {
27308+ struct work_struct wk;
7f207e10 27309+ struct kobject *kobj;
1facf9fc 27310+
27311+ unsigned int flags; /* see wkq.h */
27312+
27313+ au_wkq_func_t func;
27314+ void *args;
27315+
1facf9fc 27316+ struct completion *comp;
27317+};
27318+
27319+/* ---------------------------------------------------------------------- */
27320+
1facf9fc 27321+static void wkq_func(struct work_struct *wk)
27322+{
27323+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
27324+
7f207e10
AM
27325+ AuDebugOn(current_fsuid());
27326+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
27327+
1facf9fc 27328+ wkinfo->func(wkinfo->args);
1facf9fc 27329+ if (au_ftest_wkq(wkinfo->flags, WAIT))
27330+ complete(wkinfo->comp);
27331+ else {
7f207e10 27332+ kobject_put(wkinfo->kobj);
1facf9fc 27333+ module_put(THIS_MODULE);
27334+ kfree(wkinfo);
27335+ }
27336+}
27337+
27338+/*
27339+ * Since struct completion is large, try allocating it dynamically.
27340+ */
27341+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
27342+#define AuWkqCompDeclare(name) struct completion *comp = NULL
27343+
27344+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
27345+{
27346+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
27347+ if (*comp) {
27348+ init_completion(*comp);
27349+ wkinfo->comp = *comp;
27350+ return 0;
27351+ }
27352+ return -ENOMEM;
27353+}
27354+
27355+static void au_wkq_comp_free(struct completion *comp)
27356+{
27357+ kfree(comp);
27358+}
27359+
27360+#else
27361+
27362+/* no braces */
27363+#define AuWkqCompDeclare(name) \
27364+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
27365+ struct completion *comp = &_ ## name
27366+
27367+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
27368+{
27369+ wkinfo->comp = *comp;
27370+ return 0;
27371+}
27372+
27373+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
27374+{
27375+ /* empty */
27376+}
27377+#endif /* 4KSTACKS */
27378+
b752ccd1 27379+static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags)
1facf9fc 27380+{
b752ccd1
AM
27381+ struct workqueue_struct *wkq;
27382+
1facf9fc 27383+ au_dbg_verify_kthread();
b752ccd1 27384+ if (flags & AuWkq_WAIT) {
a1f66529 27385+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
b752ccd1
AM
27386+ wkq = au_wkq[AuWkq_INORMAL].wkq;
27387+ if (flags & AuWkq_PRE)
27388+ wkq = au_wkq[AuWkq_IPRE].wkq;
27389+ queue_work(wkq, &wkinfo->wk);
4a4d8108
AM
27390+ } else {
27391+ INIT_WORK(&wkinfo->wk, wkq_func);
27392+ schedule_work(&wkinfo->wk);
27393+ }
1facf9fc 27394+}
27395+
7f207e10
AM
27396+/*
27397+ * Be careful. It is easy to make deadlock happen.
27398+ * processA: lock, wkq and wait
27399+ * processB: wkq and wait, lock in wkq
27400+ * --> deadlock
27401+ */
b752ccd1 27402+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 27403+{
27404+ int err;
27405+ AuWkqCompDeclare(comp);
27406+ struct au_wkinfo wkinfo = {
b752ccd1 27407+ .flags = flags,
1facf9fc 27408+ .func = func,
27409+ .args = args
27410+ };
27411+
27412+ err = au_wkq_comp_alloc(&wkinfo, &comp);
27413+ if (!err) {
b752ccd1 27414+ au_wkq_run(&wkinfo, flags);
1facf9fc 27415+ /* no timeout, no interrupt */
27416+ wait_for_completion(wkinfo.comp);
27417+ au_wkq_comp_free(comp);
4a4d8108 27418+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 27419+ }
27420+
27421+ return err;
27422+
27423+}
27424+
027c5e7a
AM
27425+/*
27426+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
27427+ * problem in a concurrent umounting.
27428+ */
1facf9fc 27429+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
27430+{
27431+ int err;
27432+ struct au_wkinfo *wkinfo;
27433+
27434+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
27435+
27436+ /*
27437+ * wkq_func() must free this wkinfo.
27438+ * it highly depends upon the implementation of workqueue.
27439+ */
27440+ err = 0;
27441+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
27442+ if (wkinfo) {
7f207e10 27443+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
1facf9fc 27444+ wkinfo->flags = !AuWkq_WAIT;
27445+ wkinfo->func = func;
27446+ wkinfo->args = args;
27447+ wkinfo->comp = NULL;
7f207e10 27448+ kobject_get(wkinfo->kobj);
1facf9fc 27449+ __module_get(THIS_MODULE);
27450+
4a4d8108 27451+ au_wkq_run(wkinfo, !AuWkq_WAIT);
1facf9fc 27452+ } else {
27453+ err = -ENOMEM;
e49829fe 27454+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 27455+ }
27456+
27457+ return err;
27458+}
27459+
27460+/* ---------------------------------------------------------------------- */
27461+
27462+void au_nwt_init(struct au_nowait_tasks *nwt)
27463+{
27464+ atomic_set(&nwt->nw_len, 0);
4a4d8108 27465+ /* smp_mb(); */ /* atomic_set */
1facf9fc 27466+ init_waitqueue_head(&nwt->nw_wq);
27467+}
27468+
27469+void au_wkq_fin(void)
27470+{
b752ccd1
AM
27471+ int i;
27472+
27473+ for (i = 0; i < ARRAY_SIZE(au_wkq); i++)
27474+ if (au_wkq[i].wkq)
27475+ destroy_workqueue(au_wkq[i].wkq);
1facf9fc 27476+}
27477+
27478+int __init au_wkq_init(void)
27479+{
b752ccd1
AM
27480+ int err, i;
27481+
27482+ err = 0;
27483+ for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
7f207e10
AM
27484+ BUILD_BUG_ON(!WQ_RESCUER);
27485+ au_wkq[i].wkq = alloc_workqueue(au_wkq[i].name, !WQ_RESCUER,
27486+ WQ_DFL_ACTIVE);
b752ccd1
AM
27487+ if (IS_ERR(au_wkq[i].wkq))
27488+ err = PTR_ERR(au_wkq[i].wkq);
27489+ else if (!au_wkq[i].wkq)
27490+ err = -ENOMEM;
27491+ if (unlikely(err))
27492+ au_wkq[i].wkq = NULL;
27493+ }
7f207e10 27494+ if (unlikely(err))
b752ccd1
AM
27495+ au_wkq_fin();
27496+
27497+ return err;
1facf9fc 27498+}
7f207e10
AM
27499diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
27500--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a 27501+++ linux/fs/aufs/wkq.h 2011-03-21 20:22:06.860602399 +0100
7f207e10 27502@@ -0,0 +1,90 @@
1facf9fc 27503+/*
027c5e7a 27504+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27505+ *
27506+ * This program, aufs is free software; you can redistribute it and/or modify
27507+ * it under the terms of the GNU General Public License as published by
27508+ * the Free Software Foundation; either version 2 of the License, or
27509+ * (at your option) any later version.
dece6358
AM
27510+ *
27511+ * This program is distributed in the hope that it will be useful,
27512+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27513+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27514+ * GNU General Public License for more details.
27515+ *
27516+ * You should have received a copy of the GNU General Public License
27517+ * along with this program; if not, write to the Free Software
27518+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27519+ */
27520+
27521+/*
27522+ * workqueue for asynchronous/super-io operations
27523+ * todo: try new credentials management scheme
27524+ */
27525+
27526+#ifndef __AUFS_WKQ_H__
27527+#define __AUFS_WKQ_H__
27528+
27529+#ifdef __KERNEL__
27530+
1facf9fc 27531+#include <linux/sched.h>
dece6358 27532+#include <linux/wait.h>
1facf9fc 27533+#include <linux/aufs_type.h>
27534+
dece6358
AM
27535+struct super_block;
27536+
1facf9fc 27537+/* ---------------------------------------------------------------------- */
27538+
27539+/*
27540+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
27541+ */
27542+struct au_nowait_tasks {
27543+ atomic_t nw_len;
27544+ wait_queue_head_t nw_wq;
27545+};
27546+
27547+/* ---------------------------------------------------------------------- */
27548+
27549+typedef void (*au_wkq_func_t)(void *args);
27550+
27551+/* wkq flags */
27552+#define AuWkq_WAIT 1
b752ccd1 27553+#define AuWkq_PRE (1 << 1)
1facf9fc 27554+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
27555+#define au_fset_wkq(flags, name) \
27556+ do { (flags) |= AuWkq_##name; } while (0)
27557+#define au_fclr_wkq(flags, name) \
27558+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 27559+
27560+/* wkq.c */
b752ccd1 27561+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
1facf9fc 27562+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
27563+void au_nwt_init(struct au_nowait_tasks *nwt);
27564+int __init au_wkq_init(void);
27565+void au_wkq_fin(void);
27566+
27567+/* ---------------------------------------------------------------------- */
27568+
b752ccd1
AM
27569+static inline int au_wkq_wait_pre(au_wkq_func_t func, void *args)
27570+{
27571+ return au_wkq_do_wait(AuWkq_WAIT | AuWkq_PRE, func, args);
27572+}
27573+
27574+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 27575+{
b752ccd1 27576+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 27577+}
27578+
27579+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
27580+{
e49829fe 27581+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 27582+ wake_up_all(&nwt->nw_wq);
27583+}
27584+
27585+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
27586+{
27587+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
27588+ return 0;
27589+}
27590+
27591+#endif /* __KERNEL__ */
27592+#endif /* __AUFS_WKQ_H__ */
7f207e10
AM
27593diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
27594--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
027c5e7a 27595+++ linux/fs/aufs/xino.c 2011-03-21 20:22:06.863935884 +0100
7f207e10 27596@@ -0,0 +1,1265 @@
1facf9fc 27597+/*
027c5e7a 27598+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27599+ *
27600+ * This program, aufs is free software; you can redistribute it and/or modify
27601+ * it under the terms of the GNU General Public License as published by
27602+ * the Free Software Foundation; either version 2 of the License, or
27603+ * (at your option) any later version.
dece6358
AM
27604+ *
27605+ * This program is distributed in the hope that it will be useful,
27606+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27607+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27608+ * GNU General Public License for more details.
27609+ *
27610+ * You should have received a copy of the GNU General Public License
27611+ * along with this program; if not, write to the Free Software
27612+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27613+ */
27614+
27615+/*
27616+ * external inode number translation table and bitmap
27617+ */
27618+
dece6358 27619+#include <linux/file.h>
1facf9fc 27620+#include <linux/seq_file.h>
27621+#include <linux/uaccess.h>
27622+#include "aufs.h"
27623+
b752ccd1 27624+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 27625+ loff_t *pos)
27626+{
27627+ ssize_t err;
27628+ mm_segment_t oldfs;
b752ccd1
AM
27629+ union {
27630+ void *k;
27631+ char __user *u;
27632+ } buf;
1facf9fc 27633+
b752ccd1 27634+ buf.k = kbuf;
1facf9fc 27635+ oldfs = get_fs();
27636+ set_fs(KERNEL_DS);
27637+ do {
27638+ /* todo: signal_pending? */
b752ccd1 27639+ err = func(file, buf.u, size, pos);
1facf9fc 27640+ } while (err == -EAGAIN || err == -EINTR);
27641+ set_fs(oldfs);
27642+
27643+#if 0 /* reserved for future use */
27644+ if (err > 0)
27645+ fsnotify_access(file->f_dentry);
27646+#endif
27647+
27648+ return err;
27649+}
27650+
27651+/* ---------------------------------------------------------------------- */
27652+
b752ccd1 27653+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 27654+ size_t size, loff_t *pos)
27655+{
27656+ ssize_t err;
27657+ mm_segment_t oldfs;
b752ccd1
AM
27658+ union {
27659+ void *k;
27660+ const char __user *u;
27661+ } buf;
1facf9fc 27662+
b752ccd1 27663+ buf.k = kbuf;
1facf9fc 27664+ oldfs = get_fs();
27665+ set_fs(KERNEL_DS);
1facf9fc 27666+ do {
27667+ /* todo: signal_pending? */
b752ccd1 27668+ err = func(file, buf.u, size, pos);
1facf9fc 27669+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 27670+ set_fs(oldfs);
27671+
27672+#if 0 /* reserved for future use */
27673+ if (err > 0)
27674+ fsnotify_modify(file->f_dentry);
27675+#endif
27676+
27677+ return err;
27678+}
27679+
27680+struct do_xino_fwrite_args {
27681+ ssize_t *errp;
27682+ au_writef_t func;
27683+ struct file *file;
27684+ void *buf;
27685+ size_t size;
27686+ loff_t *pos;
27687+};
27688+
27689+static void call_do_xino_fwrite(void *args)
27690+{
27691+ struct do_xino_fwrite_args *a = args;
27692+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
27693+}
27694+
27695+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
27696+ loff_t *pos)
27697+{
27698+ ssize_t err;
27699+
27700+ /* todo: signal block and no wkq? */
b752ccd1
AM
27701+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
27702+ lockdep_off();
27703+ err = do_xino_fwrite(func, file, buf, size, pos);
27704+ lockdep_on();
27705+ } else {
27706+ /*
27707+ * it breaks RLIMIT_FSIZE and normal user's limit,
27708+ * users should care about quota and real 'filesystem full.'
27709+ */
1facf9fc 27710+ int wkq_err;
27711+ struct do_xino_fwrite_args args = {
27712+ .errp = &err,
27713+ .func = func,
27714+ .file = file,
27715+ .buf = buf,
27716+ .size = size,
27717+ .pos = pos
27718+ };
27719+
27720+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
27721+ if (unlikely(wkq_err))
27722+ err = wkq_err;
b752ccd1 27723+ }
1facf9fc 27724+
27725+ return err;
27726+}
27727+
27728+/* ---------------------------------------------------------------------- */
27729+
27730+/*
27731+ * create a new xinofile at the same place/path as @base_file.
27732+ */
27733+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
27734+{
27735+ struct file *file;
4a4d8108 27736+ struct dentry *base, *parent;
1facf9fc 27737+ struct inode *dir;
27738+ struct qstr *name;
1308ab2a 27739+ struct path path;
4a4d8108 27740+ int err;
1facf9fc 27741+
27742+ base = base_file->f_dentry;
27743+ parent = base->d_parent; /* dir inode is locked */
27744+ dir = parent->d_inode;
27745+ IMustLock(dir);
27746+
27747+ file = ERR_PTR(-EINVAL);
27748+ name = &base->d_name;
4a4d8108
AM
27749+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
27750+ if (IS_ERR(path.dentry)) {
27751+ file = (void *)path.dentry;
27752+ pr_err("%.*s lookup err %ld\n",
27753+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 27754+ goto out;
27755+ }
27756+
27757+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 27758+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 27759+ if (unlikely(err)) {
27760+ file = ERR_PTR(err);
4a4d8108 27761+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 27762+ goto out_dput;
27763+ }
27764+
1308ab2a 27765+ path.mnt = base_file->f_vfsmnt;
4a4d8108 27766+ file = vfsub_dentry_open(&path,
7f207e10
AM
27767+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
27768+ /* | FMODE_NONOTIFY */);
1facf9fc 27769+ if (IS_ERR(file)) {
4a4d8108 27770+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 27771+ goto out_dput;
27772+ }
27773+
27774+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
27775+ if (unlikely(err)) {
4a4d8108 27776+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 27777+ goto out_fput;
27778+ }
27779+
27780+ if (copy_src) {
27781+ /* no one can touch copy_src xino */
27782+ err = au_copy_file(file, copy_src,
27783+ i_size_read(copy_src->f_dentry->d_inode));
27784+ if (unlikely(err)) {
4a4d8108 27785+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 27786+ goto out_fput;
27787+ }
27788+ }
27789+ goto out_dput; /* success */
27790+
4f0767ce 27791+out_fput:
1facf9fc 27792+ fput(file);
27793+ file = ERR_PTR(err);
4f0767ce 27794+out_dput:
4a4d8108 27795+ dput(path.dentry);
4f0767ce 27796+out:
1facf9fc 27797+ return file;
27798+}
27799+
27800+struct au_xino_lock_dir {
27801+ struct au_hinode *hdir;
27802+ struct dentry *parent;
27803+ struct mutex *mtx;
27804+};
27805+
27806+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
27807+ struct au_xino_lock_dir *ldir)
27808+{
27809+ aufs_bindex_t brid, bindex;
27810+
27811+ ldir->hdir = NULL;
27812+ bindex = -1;
27813+ brid = au_xino_brid(sb);
27814+ if (brid >= 0)
27815+ bindex = au_br_index(sb, brid);
27816+ if (bindex >= 0) {
27817+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 27818+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 27819+ } else {
27820+ ldir->parent = dget_parent(xino->f_dentry);
27821+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
27822+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
27823+ }
27824+}
27825+
27826+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
27827+{
27828+ if (ldir->hdir)
4a4d8108 27829+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 27830+ else {
27831+ mutex_unlock(ldir->mtx);
27832+ dput(ldir->parent);
27833+ }
27834+}
27835+
27836+/* ---------------------------------------------------------------------- */
27837+
27838+/* trucate xino files asynchronously */
27839+
27840+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
27841+{
27842+ int err;
27843+ aufs_bindex_t bi, bend;
27844+ struct au_branch *br;
27845+ struct file *new_xino, *file;
27846+ struct super_block *h_sb;
27847+ struct au_xino_lock_dir ldir;
27848+
27849+ err = -EINVAL;
27850+ bend = au_sbend(sb);
27851+ if (unlikely(bindex < 0 || bend < bindex))
27852+ goto out;
27853+ br = au_sbr(sb, bindex);
27854+ file = br->br_xino.xi_file;
27855+ if (!file)
27856+ goto out;
27857+
27858+ au_xino_lock_dir(sb, file, &ldir);
27859+ /* mnt_want_write() is unnecessary here */
27860+ new_xino = au_xino_create2(file, file);
27861+ au_xino_unlock_dir(&ldir);
27862+ err = PTR_ERR(new_xino);
27863+ if (IS_ERR(new_xino))
27864+ goto out;
27865+ err = 0;
27866+ fput(file);
27867+ br->br_xino.xi_file = new_xino;
27868+
27869+ h_sb = br->br_mnt->mnt_sb;
27870+ for (bi = 0; bi <= bend; bi++) {
27871+ if (unlikely(bi == bindex))
27872+ continue;
27873+ br = au_sbr(sb, bi);
27874+ if (br->br_mnt->mnt_sb != h_sb)
27875+ continue;
27876+
27877+ fput(br->br_xino.xi_file);
27878+ br->br_xino.xi_file = new_xino;
27879+ get_file(new_xino);
27880+ }
27881+
4f0767ce 27882+out:
1facf9fc 27883+ return err;
27884+}
27885+
27886+struct xino_do_trunc_args {
27887+ struct super_block *sb;
27888+ struct au_branch *br;
27889+};
27890+
27891+static void xino_do_trunc(void *_args)
27892+{
27893+ struct xino_do_trunc_args *args = _args;
27894+ struct super_block *sb;
27895+ struct au_branch *br;
27896+ struct inode *dir;
27897+ int err;
27898+ aufs_bindex_t bindex;
27899+
27900+ err = 0;
27901+ sb = args->sb;
27902+ dir = sb->s_root->d_inode;
27903+ br = args->br;
27904+
27905+ si_noflush_write_lock(sb);
27906+ ii_read_lock_parent(dir);
27907+ bindex = au_br_index(sb, br->br_id);
27908+ err = au_xino_trunc(sb, bindex);
dece6358
AM
27909+ if (!err
27910+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 27911+ >= br->br_xino_upper)
27912+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
27913+
1facf9fc 27914+ ii_read_unlock(dir);
27915+ if (unlikely(err))
4a4d8108 27916+ pr_warning("err b%d, (%d)\n", bindex, err);
1facf9fc 27917+ atomic_dec(&br->br_xino_running);
27918+ atomic_dec(&br->br_count);
1facf9fc 27919+ si_write_unlock(sb);
027c5e7a 27920+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 27921+ kfree(args);
27922+}
27923+
27924+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
27925+{
27926+ struct xino_do_trunc_args *args;
27927+ int wkq_err;
27928+
27929+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
27930+ < br->br_xino_upper)
27931+ return;
27932+
27933+ if (atomic_inc_return(&br->br_xino_running) > 1)
27934+ goto out;
27935+
27936+ /* lock and kfree() will be called in trunc_xino() */
27937+ args = kmalloc(sizeof(*args), GFP_NOFS);
27938+ if (unlikely(!args)) {
27939+ AuErr1("no memory\n");
27940+ goto out_args;
27941+ }
27942+
e49829fe 27943+ atomic_inc(&br->br_count);
1facf9fc 27944+ args->sb = sb;
27945+ args->br = br;
27946+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
27947+ if (!wkq_err)
27948+ return; /* success */
27949+
4a4d8108 27950+ pr_err("wkq %d\n", wkq_err);
e49829fe 27951+ atomic_dec(&br->br_count);
1facf9fc 27952+
4f0767ce 27953+out_args:
1facf9fc 27954+ kfree(args);
4f0767ce 27955+out:
e49829fe 27956+ atomic_dec(&br->br_xino_running);
1facf9fc 27957+}
27958+
27959+/* ---------------------------------------------------------------------- */
27960+
27961+static int au_xino_do_write(au_writef_t write, struct file *file,
27962+ ino_t h_ino, ino_t ino)
27963+{
27964+ loff_t pos;
27965+ ssize_t sz;
27966+
27967+ pos = h_ino;
27968+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
27969+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
27970+ return -EFBIG;
27971+ }
27972+ pos *= sizeof(ino);
27973+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
27974+ if (sz == sizeof(ino))
27975+ return 0; /* success */
27976+
27977+ AuIOErr("write failed (%zd)\n", sz);
27978+ return -EIO;
27979+}
27980+
27981+/*
27982+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
27983+ * at the position of @h_ino.
27984+ * even if @ino is zero, it is written to the xinofile and means no entry.
27985+ * if the size of the xino file on a specific filesystem exceeds the watermark,
27986+ * try truncating it.
27987+ */
27988+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
27989+ ino_t ino)
27990+{
27991+ int err;
27992+ unsigned int mnt_flags;
27993+ struct au_branch *br;
27994+
27995+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
27996+ || ((loff_t)-1) > 0);
dece6358 27997+ SiMustAnyLock(sb);
1facf9fc 27998+
27999+ mnt_flags = au_mntflags(sb);
28000+ if (!au_opt_test(mnt_flags, XINO))
28001+ return 0;
28002+
28003+ br = au_sbr(sb, bindex);
28004+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
28005+ h_ino, ino);
28006+ if (!err) {
28007+ if (au_opt_test(mnt_flags, TRUNC_XINO)
28008+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
28009+ xino_try_trunc(sb, br);
28010+ return 0; /* success */
28011+ }
28012+
28013+ AuIOErr("write failed (%d)\n", err);
28014+ return -EIO;
28015+}
28016+
28017+/* ---------------------------------------------------------------------- */
28018+
28019+/* aufs inode number bitmap */
28020+
28021+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
28022+static ino_t xib_calc_ino(unsigned long pindex, int bit)
28023+{
28024+ ino_t ino;
28025+
28026+ AuDebugOn(bit < 0 || page_bits <= bit);
28027+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
28028+ return ino;
28029+}
28030+
28031+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
28032+{
28033+ AuDebugOn(ino < AUFS_FIRST_INO);
28034+ ino -= AUFS_FIRST_INO;
28035+ *pindex = ino / page_bits;
28036+ *bit = ino % page_bits;
28037+}
28038+
28039+static int xib_pindex(struct super_block *sb, unsigned long pindex)
28040+{
28041+ int err;
28042+ loff_t pos;
28043+ ssize_t sz;
28044+ struct au_sbinfo *sbinfo;
28045+ struct file *xib;
28046+ unsigned long *p;
28047+
28048+ sbinfo = au_sbi(sb);
28049+ MtxMustLock(&sbinfo->si_xib_mtx);
28050+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
28051+ || !au_opt_test(sbinfo->si_mntflags, XINO));
28052+
28053+ if (pindex == sbinfo->si_xib_last_pindex)
28054+ return 0;
28055+
28056+ xib = sbinfo->si_xib;
28057+ p = sbinfo->si_xib_buf;
28058+ pos = sbinfo->si_xib_last_pindex;
28059+ pos *= PAGE_SIZE;
28060+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
28061+ if (unlikely(sz != PAGE_SIZE))
28062+ goto out;
28063+
28064+ pos = pindex;
28065+ pos *= PAGE_SIZE;
28066+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
28067+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
28068+ else {
28069+ memset(p, 0, PAGE_SIZE);
28070+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
28071+ }
28072+ if (sz == PAGE_SIZE) {
28073+ sbinfo->si_xib_last_pindex = pindex;
28074+ return 0; /* success */
28075+ }
28076+
4f0767ce 28077+out:
b752ccd1
AM
28078+ AuIOErr1("write failed (%zd)\n", sz);
28079+ err = sz;
28080+ if (sz >= 0)
28081+ err = -EIO;
28082+ return err;
28083+}
28084+
28085+/* ---------------------------------------------------------------------- */
28086+
28087+static void au_xib_clear_bit(struct inode *inode)
28088+{
28089+ int err, bit;
28090+ unsigned long pindex;
28091+ struct super_block *sb;
28092+ struct au_sbinfo *sbinfo;
28093+
28094+ AuDebugOn(inode->i_nlink);
28095+
28096+ sb = inode->i_sb;
28097+ xib_calc_bit(inode->i_ino, &pindex, &bit);
28098+ AuDebugOn(page_bits <= bit);
28099+ sbinfo = au_sbi(sb);
28100+ mutex_lock(&sbinfo->si_xib_mtx);
28101+ err = xib_pindex(sb, pindex);
28102+ if (!err) {
28103+ clear_bit(bit, sbinfo->si_xib_buf);
28104+ sbinfo->si_xib_next_bit = bit;
28105+ }
28106+ mutex_unlock(&sbinfo->si_xib_mtx);
28107+}
28108+
28109+/* for s_op->delete_inode() */
28110+void au_xino_delete_inode(struct inode *inode, const int unlinked)
28111+{
28112+ int err;
28113+ unsigned int mnt_flags;
28114+ aufs_bindex_t bindex, bend, bi;
28115+ unsigned char try_trunc;
28116+ struct au_iinfo *iinfo;
28117+ struct super_block *sb;
28118+ struct au_hinode *hi;
28119+ struct inode *h_inode;
28120+ struct au_branch *br;
28121+ au_writef_t xwrite;
28122+
28123+ sb = inode->i_sb;
28124+ mnt_flags = au_mntflags(sb);
28125+ if (!au_opt_test(mnt_flags, XINO)
28126+ || inode->i_ino == AUFS_ROOT_INO)
28127+ return;
28128+
28129+ if (unlinked) {
28130+ au_xigen_inc(inode);
28131+ au_xib_clear_bit(inode);
28132+ }
28133+
28134+ iinfo = au_ii(inode);
28135+ if (!iinfo)
28136+ return;
1facf9fc 28137+
b752ccd1
AM
28138+ bindex = iinfo->ii_bstart;
28139+ if (bindex < 0)
28140+ return;
1facf9fc 28141+
b752ccd1
AM
28142+ xwrite = au_sbi(sb)->si_xwrite;
28143+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
28144+ hi = iinfo->ii_hinode + bindex;
28145+ bend = iinfo->ii_bend;
28146+ for (; bindex <= bend; bindex++, hi++) {
28147+ h_inode = hi->hi_inode;
28148+ if (!h_inode
28149+ || (!unlinked && h_inode->i_nlink))
28150+ continue;
1facf9fc 28151+
b752ccd1
AM
28152+ /* inode may not be revalidated */
28153+ bi = au_br_index(sb, hi->hi_id);
28154+ if (bi < 0)
28155+ continue;
1facf9fc 28156+
b752ccd1
AM
28157+ br = au_sbr(sb, bi);
28158+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
28159+ h_inode->i_ino, /*ino*/0);
28160+ if (!err && try_trunc
28161+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
28162+ xino_try_trunc(sb, br);
1facf9fc 28163+ }
1facf9fc 28164+}
28165+
28166+/* get an unused inode number from bitmap */
28167+ino_t au_xino_new_ino(struct super_block *sb)
28168+{
28169+ ino_t ino;
28170+ unsigned long *p, pindex, ul, pend;
28171+ struct au_sbinfo *sbinfo;
28172+ struct file *file;
28173+ int free_bit, err;
28174+
28175+ if (!au_opt_test(au_mntflags(sb), XINO))
28176+ return iunique(sb, AUFS_FIRST_INO);
28177+
28178+ sbinfo = au_sbi(sb);
28179+ mutex_lock(&sbinfo->si_xib_mtx);
28180+ p = sbinfo->si_xib_buf;
28181+ free_bit = sbinfo->si_xib_next_bit;
28182+ if (free_bit < page_bits && !test_bit(free_bit, p))
28183+ goto out; /* success */
28184+ free_bit = find_first_zero_bit(p, page_bits);
28185+ if (free_bit < page_bits)
28186+ goto out; /* success */
28187+
28188+ pindex = sbinfo->si_xib_last_pindex;
28189+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
28190+ err = xib_pindex(sb, ul);
28191+ if (unlikely(err))
28192+ goto out_err;
28193+ free_bit = find_first_zero_bit(p, page_bits);
28194+ if (free_bit < page_bits)
28195+ goto out; /* success */
28196+ }
28197+
28198+ file = sbinfo->si_xib;
28199+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
28200+ for (ul = pindex + 1; ul <= pend; ul++) {
28201+ err = xib_pindex(sb, ul);
28202+ if (unlikely(err))
28203+ goto out_err;
28204+ free_bit = find_first_zero_bit(p, page_bits);
28205+ if (free_bit < page_bits)
28206+ goto out; /* success */
28207+ }
28208+ BUG();
28209+
4f0767ce 28210+out:
1facf9fc 28211+ set_bit(free_bit, p);
7f207e10 28212+ sbinfo->si_xib_next_bit = free_bit + 1;
1facf9fc 28213+ pindex = sbinfo->si_xib_last_pindex;
28214+ mutex_unlock(&sbinfo->si_xib_mtx);
28215+ ino = xib_calc_ino(pindex, free_bit);
28216+ AuDbg("i%lu\n", (unsigned long)ino);
28217+ return ino;
4f0767ce 28218+out_err:
1facf9fc 28219+ mutex_unlock(&sbinfo->si_xib_mtx);
28220+ AuDbg("i0\n");
28221+ return 0;
28222+}
28223+
28224+/*
28225+ * read @ino from xinofile for the specified branch{@sb, @bindex}
28226+ * at the position of @h_ino.
28227+ * if @ino does not exist and @do_new is true, get new one.
28228+ */
28229+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
28230+ ino_t *ino)
28231+{
28232+ int err;
28233+ ssize_t sz;
28234+ loff_t pos;
28235+ struct file *file;
28236+ struct au_sbinfo *sbinfo;
28237+
28238+ *ino = 0;
28239+ if (!au_opt_test(au_mntflags(sb), XINO))
28240+ return 0; /* no xino */
28241+
28242+ err = 0;
28243+ sbinfo = au_sbi(sb);
28244+ pos = h_ino;
28245+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
28246+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
28247+ return -EFBIG;
28248+ }
28249+ pos *= sizeof(*ino);
28250+
28251+ file = au_sbr(sb, bindex)->br_xino.xi_file;
28252+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
28253+ return 0; /* no ino */
28254+
28255+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
28256+ if (sz == sizeof(*ino))
28257+ return 0; /* success */
28258+
28259+ err = sz;
28260+ if (unlikely(sz >= 0)) {
28261+ err = -EIO;
28262+ AuIOErr("xino read error (%zd)\n", sz);
28263+ }
28264+
28265+ return err;
28266+}
28267+
28268+/* ---------------------------------------------------------------------- */
28269+
28270+/* create and set a new xino file */
28271+
28272+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
28273+{
28274+ struct file *file;
28275+ struct dentry *h_parent, *d;
28276+ struct inode *h_dir;
28277+ int err;
28278+
28279+ /*
28280+ * at mount-time, and the xino file is the default path,
4a4d8108 28281+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 28282+ * when a user specified the xino, we cannot get au_hdir to be ignored.
28283+ */
7f207e10
AM
28284+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
28285+ /* | FMODE_NONOTIFY */,
1facf9fc 28286+ S_IRUGO | S_IWUGO);
28287+ if (IS_ERR(file)) {
28288+ if (!silent)
4a4d8108 28289+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 28290+ return file;
28291+ }
28292+
28293+ /* keep file count */
28294+ h_parent = dget_parent(file->f_dentry);
28295+ h_dir = h_parent->d_inode;
28296+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
28297+ /* mnt_want_write() is unnecessary here */
28298+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
28299+ mutex_unlock(&h_dir->i_mutex);
28300+ dput(h_parent);
28301+ if (unlikely(err)) {
28302+ if (!silent)
4a4d8108 28303+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 28304+ goto out;
28305+ }
28306+
28307+ err = -EINVAL;
28308+ d = file->f_dentry;
28309+ if (unlikely(sb == d->d_sb)) {
28310+ if (!silent)
4a4d8108 28311+ pr_err("%s must be outside\n", fname);
1facf9fc 28312+ goto out;
28313+ }
28314+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
28315+ if (!silent)
4a4d8108
AM
28316+ pr_err("xino doesn't support %s(%s)\n",
28317+ fname, au_sbtype(d->d_sb));
1facf9fc 28318+ goto out;
28319+ }
28320+ return file; /* success */
28321+
4f0767ce 28322+out:
1facf9fc 28323+ fput(file);
28324+ file = ERR_PTR(err);
28325+ return file;
28326+}
28327+
28328+/*
28329+ * find another branch who is on the same filesystem of the specified
28330+ * branch{@btgt}. search until @bend.
28331+ */
28332+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
28333+ aufs_bindex_t bend)
28334+{
28335+ aufs_bindex_t bindex;
28336+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
28337+
28338+ for (bindex = 0; bindex < btgt; bindex++)
28339+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
28340+ return bindex;
28341+ for (bindex++; bindex <= bend; bindex++)
28342+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
28343+ return bindex;
28344+ return -1;
28345+}
28346+
28347+/* ---------------------------------------------------------------------- */
28348+
28349+/*
28350+ * initialize the xinofile for the specified branch @br
28351+ * at the place/path where @base_file indicates.
28352+ * test whether another branch is on the same filesystem or not,
28353+ * if @do_test is true.
28354+ */
28355+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
28356+ struct file *base_file, int do_test)
28357+{
28358+ int err;
28359+ ino_t ino;
28360+ aufs_bindex_t bend, bindex;
28361+ struct au_branch *shared_br, *b;
28362+ struct file *file;
28363+ struct super_block *tgt_sb;
28364+
28365+ shared_br = NULL;
28366+ bend = au_sbend(sb);
28367+ if (do_test) {
28368+ tgt_sb = br->br_mnt->mnt_sb;
28369+ for (bindex = 0; bindex <= bend; bindex++) {
28370+ b = au_sbr(sb, bindex);
28371+ if (tgt_sb == b->br_mnt->mnt_sb) {
28372+ shared_br = b;
28373+ break;
28374+ }
28375+ }
28376+ }
28377+
28378+ if (!shared_br || !shared_br->br_xino.xi_file) {
28379+ struct au_xino_lock_dir ldir;
28380+
28381+ au_xino_lock_dir(sb, base_file, &ldir);
28382+ /* mnt_want_write() is unnecessary here */
28383+ file = au_xino_create2(base_file, NULL);
28384+ au_xino_unlock_dir(&ldir);
28385+ err = PTR_ERR(file);
28386+ if (IS_ERR(file))
28387+ goto out;
28388+ br->br_xino.xi_file = file;
28389+ } else {
28390+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
28391+ get_file(br->br_xino.xi_file);
28392+ }
28393+
28394+ ino = AUFS_ROOT_INO;
28395+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
28396+ h_ino, ino);
b752ccd1
AM
28397+ if (unlikely(err)) {
28398+ fput(br->br_xino.xi_file);
28399+ br->br_xino.xi_file = NULL;
28400+ }
1facf9fc 28401+
4f0767ce 28402+out:
1facf9fc 28403+ return err;
28404+}
28405+
28406+/* ---------------------------------------------------------------------- */
28407+
28408+/* trucate a xino bitmap file */
28409+
28410+/* todo: slow */
28411+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
28412+{
28413+ int err, bit;
28414+ ssize_t sz;
28415+ unsigned long pindex;
28416+ loff_t pos, pend;
28417+ struct au_sbinfo *sbinfo;
28418+ au_readf_t func;
28419+ ino_t *ino;
28420+ unsigned long *p;
28421+
28422+ err = 0;
28423+ sbinfo = au_sbi(sb);
dece6358 28424+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 28425+ p = sbinfo->si_xib_buf;
28426+ func = sbinfo->si_xread;
28427+ pend = i_size_read(file->f_dentry->d_inode);
28428+ pos = 0;
28429+ while (pos < pend) {
28430+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
28431+ err = sz;
28432+ if (unlikely(sz <= 0))
28433+ goto out;
28434+
28435+ err = 0;
28436+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
28437+ if (unlikely(*ino < AUFS_FIRST_INO))
28438+ continue;
28439+
28440+ xib_calc_bit(*ino, &pindex, &bit);
28441+ AuDebugOn(page_bits <= bit);
28442+ err = xib_pindex(sb, pindex);
28443+ if (!err)
28444+ set_bit(bit, p);
28445+ else
28446+ goto out;
28447+ }
28448+ }
28449+
4f0767ce 28450+out:
1facf9fc 28451+ return err;
28452+}
28453+
28454+static int xib_restore(struct super_block *sb)
28455+{
28456+ int err;
28457+ aufs_bindex_t bindex, bend;
28458+ void *page;
28459+
28460+ err = -ENOMEM;
28461+ page = (void *)__get_free_page(GFP_NOFS);
28462+ if (unlikely(!page))
28463+ goto out;
28464+
28465+ err = 0;
28466+ bend = au_sbend(sb);
28467+ for (bindex = 0; !err && bindex <= bend; bindex++)
28468+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
28469+ err = do_xib_restore
28470+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
28471+ else
28472+ AuDbg("b%d\n", bindex);
28473+ free_page((unsigned long)page);
28474+
4f0767ce 28475+out:
1facf9fc 28476+ return err;
28477+}
28478+
28479+int au_xib_trunc(struct super_block *sb)
28480+{
28481+ int err;
28482+ ssize_t sz;
28483+ loff_t pos;
28484+ struct au_xino_lock_dir ldir;
28485+ struct au_sbinfo *sbinfo;
28486+ unsigned long *p;
28487+ struct file *file;
28488+
dece6358
AM
28489+ SiMustWriteLock(sb);
28490+
1facf9fc 28491+ err = 0;
28492+ sbinfo = au_sbi(sb);
28493+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
28494+ goto out;
28495+
28496+ file = sbinfo->si_xib;
28497+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
28498+ goto out;
28499+
28500+ au_xino_lock_dir(sb, file, &ldir);
28501+ /* mnt_want_write() is unnecessary here */
28502+ file = au_xino_create2(sbinfo->si_xib, NULL);
28503+ au_xino_unlock_dir(&ldir);
28504+ err = PTR_ERR(file);
28505+ if (IS_ERR(file))
28506+ goto out;
28507+ fput(sbinfo->si_xib);
28508+ sbinfo->si_xib = file;
28509+
28510+ p = sbinfo->si_xib_buf;
28511+ memset(p, 0, PAGE_SIZE);
28512+ pos = 0;
28513+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
28514+ if (unlikely(sz != PAGE_SIZE)) {
28515+ err = sz;
28516+ AuIOErr("err %d\n", err);
28517+ if (sz >= 0)
28518+ err = -EIO;
28519+ goto out;
28520+ }
28521+
28522+ mutex_lock(&sbinfo->si_xib_mtx);
28523+ /* mnt_want_write() is unnecessary here */
28524+ err = xib_restore(sb);
28525+ mutex_unlock(&sbinfo->si_xib_mtx);
28526+
28527+out:
28528+ return err;
28529+}
28530+
28531+/* ---------------------------------------------------------------------- */
28532+
28533+/*
28534+ * xino mount option handlers
28535+ */
28536+static au_readf_t find_readf(struct file *h_file)
28537+{
28538+ const struct file_operations *fop = h_file->f_op;
28539+
28540+ if (fop) {
28541+ if (fop->read)
28542+ return fop->read;
28543+ if (fop->aio_read)
28544+ return do_sync_read;
28545+ }
28546+ return ERR_PTR(-ENOSYS);
28547+}
28548+
28549+static au_writef_t find_writef(struct file *h_file)
28550+{
28551+ const struct file_operations *fop = h_file->f_op;
28552+
28553+ if (fop) {
28554+ if (fop->write)
28555+ return fop->write;
28556+ if (fop->aio_write)
28557+ return do_sync_write;
28558+ }
28559+ return ERR_PTR(-ENOSYS);
28560+}
28561+
28562+/* xino bitmap */
28563+static void xino_clear_xib(struct super_block *sb)
28564+{
28565+ struct au_sbinfo *sbinfo;
28566+
dece6358
AM
28567+ SiMustWriteLock(sb);
28568+
1facf9fc 28569+ sbinfo = au_sbi(sb);
28570+ sbinfo->si_xread = NULL;
28571+ sbinfo->si_xwrite = NULL;
28572+ if (sbinfo->si_xib)
28573+ fput(sbinfo->si_xib);
28574+ sbinfo->si_xib = NULL;
28575+ free_page((unsigned long)sbinfo->si_xib_buf);
28576+ sbinfo->si_xib_buf = NULL;
28577+}
28578+
28579+static int au_xino_set_xib(struct super_block *sb, struct file *base)
28580+{
28581+ int err;
28582+ loff_t pos;
28583+ struct au_sbinfo *sbinfo;
28584+ struct file *file;
28585+
dece6358
AM
28586+ SiMustWriteLock(sb);
28587+
1facf9fc 28588+ sbinfo = au_sbi(sb);
28589+ file = au_xino_create2(base, sbinfo->si_xib);
28590+ err = PTR_ERR(file);
28591+ if (IS_ERR(file))
28592+ goto out;
28593+ if (sbinfo->si_xib)
28594+ fput(sbinfo->si_xib);
28595+ sbinfo->si_xib = file;
28596+ sbinfo->si_xread = find_readf(file);
28597+ sbinfo->si_xwrite = find_writef(file);
28598+
28599+ err = -ENOMEM;
28600+ if (!sbinfo->si_xib_buf)
28601+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
28602+ if (unlikely(!sbinfo->si_xib_buf))
28603+ goto out_unset;
28604+
28605+ sbinfo->si_xib_last_pindex = 0;
28606+ sbinfo->si_xib_next_bit = 0;
28607+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
28608+ pos = 0;
28609+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
28610+ PAGE_SIZE, &pos);
28611+ if (unlikely(err != PAGE_SIZE))
28612+ goto out_free;
28613+ }
28614+ err = 0;
28615+ goto out; /* success */
28616+
4f0767ce 28617+out_free:
1facf9fc 28618+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
28619+ sbinfo->si_xib_buf = NULL;
28620+ if (err >= 0)
28621+ err = -EIO;
4f0767ce 28622+out_unset:
b752ccd1
AM
28623+ fput(sbinfo->si_xib);
28624+ sbinfo->si_xib = NULL;
28625+ sbinfo->si_xread = NULL;
28626+ sbinfo->si_xwrite = NULL;
4f0767ce 28627+out:
b752ccd1 28628+ return err;
1facf9fc 28629+}
28630+
b752ccd1
AM
28631+/* xino for each branch */
28632+static void xino_clear_br(struct super_block *sb)
28633+{
28634+ aufs_bindex_t bindex, bend;
28635+ struct au_branch *br;
1facf9fc 28636+
b752ccd1
AM
28637+ bend = au_sbend(sb);
28638+ for (bindex = 0; bindex <= bend; bindex++) {
28639+ br = au_sbr(sb, bindex);
28640+ if (!br || !br->br_xino.xi_file)
28641+ continue;
28642+
28643+ fput(br->br_xino.xi_file);
28644+ br->br_xino.xi_file = NULL;
28645+ }
28646+}
28647+
28648+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 28649+{
28650+ int err;
b752ccd1
AM
28651+ ino_t ino;
28652+ aufs_bindex_t bindex, bend, bshared;
28653+ struct {
28654+ struct file *old, *new;
28655+ } *fpair, *p;
28656+ struct au_branch *br;
28657+ struct inode *inode;
28658+ au_writef_t writef;
1facf9fc 28659+
b752ccd1
AM
28660+ SiMustWriteLock(sb);
28661+
28662+ err = -ENOMEM;
28663+ bend = au_sbend(sb);
28664+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
28665+ if (unlikely(!fpair))
1facf9fc 28666+ goto out;
28667+
b752ccd1
AM
28668+ inode = sb->s_root->d_inode;
28669+ ino = AUFS_ROOT_INO;
28670+ writef = au_sbi(sb)->si_xwrite;
28671+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
28672+ br = au_sbr(sb, bindex);
28673+ bshared = is_sb_shared(sb, bindex, bindex - 1);
28674+ if (bshared >= 0) {
28675+ /* shared xino */
28676+ *p = fpair[bshared];
28677+ get_file(p->new);
28678+ }
28679+
28680+ if (!p->new) {
28681+ /* new xino */
28682+ p->old = br->br_xino.xi_file;
28683+ p->new = au_xino_create2(base, br->br_xino.xi_file);
28684+ err = PTR_ERR(p->new);
28685+ if (IS_ERR(p->new)) {
28686+ p->new = NULL;
28687+ goto out_pair;
28688+ }
28689+ }
28690+
28691+ err = au_xino_do_write(writef, p->new,
28692+ au_h_iptr(inode, bindex)->i_ino, ino);
28693+ if (unlikely(err))
28694+ goto out_pair;
28695+ }
28696+
28697+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
28698+ br = au_sbr(sb, bindex);
28699+ if (br->br_xino.xi_file)
28700+ fput(br->br_xino.xi_file);
28701+ get_file(p->new);
28702+ br->br_xino.xi_file = p->new;
28703+ }
1facf9fc 28704+
4f0767ce 28705+out_pair:
b752ccd1
AM
28706+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
28707+ if (p->new)
28708+ fput(p->new);
28709+ else
28710+ break;
28711+ kfree(fpair);
4f0767ce 28712+out:
1facf9fc 28713+ return err;
28714+}
b752ccd1
AM
28715+
28716+void au_xino_clr(struct super_block *sb)
28717+{
28718+ struct au_sbinfo *sbinfo;
28719+
28720+ au_xigen_clr(sb);
28721+ xino_clear_xib(sb);
28722+ xino_clear_br(sb);
28723+ sbinfo = au_sbi(sb);
28724+ /* lvalue, do not call au_mntflags() */
28725+ au_opt_clr(sbinfo->si_mntflags, XINO);
28726+}
28727+
28728+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
28729+{
28730+ int err, skip;
28731+ struct dentry *parent, *cur_parent;
28732+ struct qstr *dname, *cur_name;
28733+ struct file *cur_xino;
28734+ struct inode *dir;
28735+ struct au_sbinfo *sbinfo;
28736+
28737+ SiMustWriteLock(sb);
28738+
28739+ err = 0;
28740+ sbinfo = au_sbi(sb);
28741+ parent = dget_parent(xino->file->f_dentry);
28742+ if (remount) {
28743+ skip = 0;
28744+ dname = &xino->file->f_dentry->d_name;
28745+ cur_xino = sbinfo->si_xib;
28746+ if (cur_xino) {
28747+ cur_parent = dget_parent(cur_xino->f_dentry);
28748+ cur_name = &cur_xino->f_dentry->d_name;
28749+ skip = (cur_parent == parent
28750+ && dname->len == cur_name->len
28751+ && !memcmp(dname->name, cur_name->name,
28752+ dname->len));
28753+ dput(cur_parent);
28754+ }
28755+ if (skip)
28756+ goto out;
28757+ }
28758+
28759+ au_opt_set(sbinfo->si_mntflags, XINO);
28760+ dir = parent->d_inode;
28761+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
28762+ /* mnt_want_write() is unnecessary here */
28763+ err = au_xino_set_xib(sb, xino->file);
28764+ if (!err)
28765+ err = au_xigen_set(sb, xino->file);
28766+ if (!err)
28767+ err = au_xino_set_br(sb, xino->file);
28768+ mutex_unlock(&dir->i_mutex);
28769+ if (!err)
28770+ goto out; /* success */
28771+
28772+ /* reset all */
28773+ AuIOErr("failed creating xino(%d).\n", err);
28774+
4f0767ce 28775+out:
b752ccd1
AM
28776+ dput(parent);
28777+ return err;
28778+}
28779+
28780+/* ---------------------------------------------------------------------- */
28781+
28782+/*
28783+ * create a xinofile at the default place/path.
28784+ */
28785+struct file *au_xino_def(struct super_block *sb)
28786+{
28787+ struct file *file;
28788+ char *page, *p;
28789+ struct au_branch *br;
28790+ struct super_block *h_sb;
28791+ struct path path;
28792+ aufs_bindex_t bend, bindex, bwr;
28793+
28794+ br = NULL;
28795+ bend = au_sbend(sb);
28796+ bwr = -1;
28797+ for (bindex = 0; bindex <= bend; bindex++) {
28798+ br = au_sbr(sb, bindex);
28799+ if (au_br_writable(br->br_perm)
28800+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
28801+ bwr = bindex;
28802+ break;
28803+ }
28804+ }
28805+
7f207e10
AM
28806+ if (bwr >= 0) {
28807+ file = ERR_PTR(-ENOMEM);
28808+ page = __getname_gfp(GFP_NOFS);
28809+ if (unlikely(!page))
28810+ goto out;
28811+ path.mnt = br->br_mnt;
28812+ path.dentry = au_h_dptr(sb->s_root, bwr);
28813+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
28814+ file = (void *)p;
28815+ if (!IS_ERR(p)) {
28816+ strcat(p, "/" AUFS_XINO_FNAME);
28817+ AuDbg("%s\n", p);
28818+ file = au_xino_create(sb, p, /*silent*/0);
28819+ if (!IS_ERR(file))
28820+ au_xino_brid_set(sb, br->br_id);
28821+ }
28822+ __putname(page);
28823+ } else {
28824+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
28825+ if (IS_ERR(file))
28826+ goto out;
28827+ h_sb = file->f_dentry->d_sb;
28828+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
28829+ pr_err("xino doesn't support %s(%s)\n",
28830+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
28831+ fput(file);
28832+ file = ERR_PTR(-EINVAL);
28833+ }
28834+ if (!IS_ERR(file))
28835+ au_xino_brid_set(sb, -1);
28836+ }
0c5527e5 28837+
7f207e10
AM
28838+out:
28839+ return file;
28840+}
28841+
28842+/* ---------------------------------------------------------------------- */
28843+
28844+int au_xino_path(struct seq_file *seq, struct file *file)
28845+{
28846+ int err;
28847+
28848+ err = au_seq_path(seq, &file->f_path);
28849+ if (unlikely(err < 0))
28850+ goto out;
28851+
28852+ err = 0;
28853+#define Deleted "\\040(deleted)"
28854+ seq->count -= sizeof(Deleted) - 1;
28855+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
28856+ sizeof(Deleted) - 1));
28857+#undef Deleted
28858+
28859+out:
28860+ return err;
28861+}
28862diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
28863--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
027c5e7a
AM
28864+++ linux/include/linux/aufs_type.h 2011-03-21 20:22:06.863935884 +0100
28865@@ -0,0 +1,206 @@
7f207e10 28866+/*
027c5e7a 28867+ * Copyright (C) 2005-2011 Junjiro R. Okajima
7f207e10
AM
28868+ *
28869+ * This program, aufs is free software; you can redistribute it and/or modify
28870+ * it under the terms of the GNU General Public License as published by
28871+ * the Free Software Foundation; either version 2 of the License, or
28872+ * (at your option) any later version.
28873+ *
28874+ * This program is distributed in the hope that it will be useful,
28875+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28876+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28877+ * GNU General Public License for more details.
28878+ *
28879+ * You should have received a copy of the GNU General Public License
28880+ * along with this program; if not, write to the Free Software
28881+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28882+ */
28883+
28884+#ifndef __AUFS_TYPE_H__
28885+#define __AUFS_TYPE_H__
28886+
28887+#include <linux/ioctl.h>
28888+#include <linux/kernel.h>
28889+#include <linux/limits.h>
28890+#include <linux/types.h>
28891+
027c5e7a 28892+#define AUFS_VERSION "2.1-standalone.tree-38-rcN-20110307"
7f207e10
AM
28893+
28894+/* todo? move this to linux-2.6.19/include/magic.h */
28895+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
28896+
28897+/* ---------------------------------------------------------------------- */
28898+
28899+#ifdef CONFIG_AUFS_BRANCH_MAX_127
28900+typedef __s8 aufs_bindex_t;
28901+#define AUFS_BRANCH_MAX 127
28902+#else
28903+typedef __s16 aufs_bindex_t;
28904+#ifdef CONFIG_AUFS_BRANCH_MAX_511
28905+#define AUFS_BRANCH_MAX 511
28906+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
28907+#define AUFS_BRANCH_MAX 1023
28908+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
28909+#define AUFS_BRANCH_MAX 32767
28910+#endif
28911+#endif
28912+
28913+#ifdef __KERNEL__
28914+#ifndef AUFS_BRANCH_MAX
28915+#error unknown CONFIG_AUFS_BRANCH_MAX value
28916+#endif
28917+#endif /* __KERNEL__ */
28918+
28919+/* ---------------------------------------------------------------------- */
28920+
28921+#define AUFS_NAME "aufs"
28922+#define AUFS_FSTYPE AUFS_NAME
28923+
28924+#define AUFS_ROOT_INO 2
28925+#define AUFS_FIRST_INO 11
28926+
28927+#define AUFS_WH_PFX ".wh."
28928+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
28929+#define AUFS_WH_TMP_LEN 4
28930+/* a limit for rmdir/rename a dir */
28931+#define AUFS_MAX_NAMELEN (NAME_MAX \
28932+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
28933+ - 1 /* dot */\
28934+ - AUFS_WH_TMP_LEN) /* hex */
28935+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
28936+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
28937+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
28938+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
28939+#define AUFS_DIRWH_DEF 3
28940+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 28941+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
28942+#define AUFS_RDBLK_DEF 512 /* bytes */
28943+#define AUFS_RDHASH_DEF 32
28944+#define AUFS_WKQ_NAME AUFS_NAME "d"
28945+#define AUFS_WKQ_PRE_NAME AUFS_WKQ_NAME "_pre"
027c5e7a
AM
28946+#define AUFS_MFS_DEF_SEC 30 /* seconds */
28947+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
7f207e10
AM
28948+#define AUFS_PLINK_WARN 100 /* number of plinks */
28949+
28950+/* pseudo-link maintenace under /proc */
28951+#define AUFS_PLINK_MAINT_NAME "plink_maint"
28952+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
28953+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
28954+
28955+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
28956+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
28957+
28958+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
28959+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
28960+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
28961+
28962+/* doubly whiteouted */
28963+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
28964+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
28965+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
28966+
28967+/* branch permission */
28968+#define AUFS_BRPERM_RW "rw"
28969+#define AUFS_BRPERM_RO "ro"
28970+#define AUFS_BRPERM_RR "rr"
28971+#define AUFS_BRPERM_WH "wh"
28972+#define AUFS_BRPERM_NLWH "nolwh"
28973+#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
28974+#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
28975+#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
28976+
28977+/* ---------------------------------------------------------------------- */
28978+
28979+/* ioctl */
28980+enum {
28981+ /* readdir in userspace */
28982+ AuCtl_RDU,
28983+ AuCtl_RDU_INO,
28984+
28985+ /* pathconf wrapper */
027c5e7a
AM
28986+ AuCtl_WBR_FD,
28987+
28988+ /* busy inode */
28989+ AuCtl_IBUSY
7f207e10
AM
28990+};
28991+
28992+/* borrowed from linux/include/linux/kernel.h */
28993+#ifndef ALIGN
28994+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
28995+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
28996+#endif
28997+
28998+/* borrowed from linux/include/linux/compiler-gcc3.h */
28999+#ifndef __aligned
29000+#define __aligned(x) __attribute__((aligned(x)))
29001+#define __packed __attribute__((packed))
29002+#endif
29003+
29004+struct au_rdu_cookie {
29005+ __u64 h_pos;
29006+ __s16 bindex;
29007+ __u8 flags;
29008+ __u8 pad;
29009+ __u32 generation;
29010+} __aligned(8);
29011+
29012+struct au_rdu_ent {
29013+ __u64 ino;
29014+ __s16 bindex;
29015+ __u8 type;
29016+ __u8 nlen;
29017+ __u8 wh;
29018+ char name[0];
29019+} __aligned(8);
29020+
29021+static inline int au_rdu_len(int nlen)
29022+{
29023+ /* include the terminating NULL */
29024+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
29025+ sizeof(__u64));
29026+}
29027+
29028+union au_rdu_ent_ul {
29029+ struct au_rdu_ent __user *e;
29030+ __u64 ul;
29031+};
29032+
29033+enum {
29034+ AufsCtlRduV_SZ,
29035+ AufsCtlRduV_End
29036+};
29037+
29038+struct aufs_rdu {
29039+ /* input */
29040+ union {
29041+ __u64 sz; /* AuCtl_RDU */
29042+ __u64 nent; /* AuCtl_RDU_INO */
29043+ };
29044+ union au_rdu_ent_ul ent;
29045+ __u16 verify[AufsCtlRduV_End];
29046+
29047+ /* input/output */
29048+ __u32 blk;
29049+
29050+ /* output */
29051+ union au_rdu_ent_ul tail;
29052+ /* number of entries which were added in a single call */
29053+ __u64 rent;
29054+ __u8 full;
29055+ __u8 shwh;
29056+
29057+ struct au_rdu_cookie cookie;
29058+} __aligned(8);
29059+
027c5e7a
AM
29060+struct aufs_ibusy {
29061+ __u64 ino, h_ino;
29062+ __s16 bindex;
29063+} __aligned(8);
29064+
7f207e10
AM
29065+#define AuCtlType 'A'
29066+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
29067+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
29068+#define AUFS_CTL_WBR_FD _IO(AuCtlType, AuCtl_WBR_FD)
027c5e7a 29069+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
7f207e10
AM
29070+
29071+#endif /* __AUFS_TYPE_H__ */
29072
This page took 4.092259 seconds and 4 git commands to generate.