]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-aufs2.patch
- drop obsolete ppc files; fix endif
[packages/kernel.git] / kernel-aufs2.patch
1 aufs2 kbuild patch for linux-2.6.
2
3 diff --git a/fs/Kconfig b/fs/Kconfig
4 index 3d18530..8f582e1 100644
5 --- a/fs/Kconfig
6 +++ b/fs/Kconfig
7 @@ -189,6 +189,7 @@ source "fs/romfs/Kconfig"
8  source "fs/sysv/Kconfig"
9  source "fs/ufs/Kconfig"
10  source "fs/exofs/Kconfig"
11 +source "fs/aufs/Kconfig"
12  
13  endif # MISC_FILESYSTEMS
14  
15 diff --git a/fs/Makefile b/fs/Makefile
16 index e6ec1d3..b0d795a 100644
17 --- a/fs/Makefile
18 +++ b/fs/Makefile
19 @@ -126,3 +126,4 @@ obj-$(CONFIG_BTRFS_FS)              += btrfs/
20  obj-$(CONFIG_GFS2_FS)           += gfs2/
21  obj-$(CONFIG_EXOFS_FS)          += exofs/
22  obj-$(CONFIG_CEPH_FS)          += ceph/
23 +obj-$(CONFIG_AUFS_FS)           += aufs/
24 diff --git a/include/linux/Kbuild b/include/linux/Kbuild
25 index 626b629..a841231 100644
26 --- a/include/linux/Kbuild
27 +++ b/include/linux/Kbuild
28 @@ -60,6 +60,7 @@ header-y += atmppp.h
29  header-y += atmsap.h
30  header-y += atmsvc.h
31  header-y += audit.h
32 +header-y += aufs_type.h
33  header-y += auto_fs.h
34  header-y += auto_fs4.h
35  header-y += auxvec.h
36 aufs2 base patch for linux-2.6.
37
38 diff --git a/fs/namei.c b/fs/namei.c
39 index 17ea76b..56e8ece 100644
40 --- a/fs/namei.c
41 +++ b/fs/namei.c
42 @@ -1168,7 +1168,7 @@ out:
43   * needs parent already locked. Doesn't follow mounts.
44   * SMP-safe.
45   */
46 -static struct dentry *lookup_hash(struct nameidata *nd)
47 +struct dentry *lookup_hash(struct nameidata *nd)
48  {
49         int err;
50  
51 @@ -1178,7 +1178,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
52         return __lookup_hash(&nd->last, nd->path.dentry, nd);
53  }
54  
55 -static int __lookup_one_len(const char *name, struct qstr *this,
56 +int __lookup_one_len(const char *name, struct qstr *this,
57                 struct dentry *base, int len)
58  {
59         unsigned long hash;
60 diff --git a/fs/splice.c b/fs/splice.c
61 index 8f1dfae..278c94f 100644
62 --- a/fs/splice.c
63 +++ b/fs/splice.c
64 @@ -1092,8 +1092,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
65  /*
66   * Attempt to initiate a splice from pipe to file.
67   */
68 -static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
69 -                          loff_t *ppos, size_t len, unsigned int flags)
70 +long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
71 +                   loff_t *ppos, size_t len, unsigned int flags)
72  {
73         ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
74                                 loff_t *, size_t, unsigned int);
75 @@ -1120,9 +1120,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
76  /*
77   * Attempt to initiate a splice from a file to a pipe.
78   */
79 -static long do_splice_to(struct file *in, loff_t *ppos,
80 -                        struct pipe_inode_info *pipe, size_t len,
81 -                        unsigned int flags)
82 +long do_splice_to(struct file *in, loff_t *ppos,
83 +                 struct pipe_inode_info *pipe, size_t len,
84 +                 unsigned int flags)
85  {
86         ssize_t (*splice_read)(struct file *, loff_t *,
87                                struct pipe_inode_info *, size_t, unsigned int);
88 diff --git a/include/linux/namei.h b/include/linux/namei.h
89 index 05b441d..91bc74e 100644
90 --- a/include/linux/namei.h
91 +++ b/include/linux/namei.h
92 @@ -73,6 +73,9 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
93  extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
94                 int (*open)(struct inode *, struct file *));
95  
96 +extern struct dentry *lookup_hash(struct nameidata *nd);
97 +extern int __lookup_one_len(const char *name, struct qstr *this,
98 +                           struct dentry *base, int len);
99  extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
100  
101  extern int follow_down(struct path *);
102 diff --git a/include/linux/splice.h b/include/linux/splice.h
103 index 997c3b4..be9a153 100644
104 --- a/include/linux/splice.h
105 +++ b/include/linux/splice.h
106 @@ -89,4 +89,10 @@ extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *);
107  extern void splice_shrink_spd(struct pipe_inode_info *,
108                                 struct splice_pipe_desc *);
109  
110 +extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
111 +                          loff_t *ppos, size_t len, unsigned int flags);
112 +extern long do_splice_to(struct file *in, loff_t *ppos,
113 +                        struct pipe_inode_info *pipe, size_t len,
114 +                        unsigned int flags);
115 +
116  #endif
117 aufs2 standalone patch for linux-2.6.
118
119 diff --git a/fs/namei.c b/fs/namei.c
120 index 56e8ece..ba75f28 100644
121 --- a/fs/namei.c
122 +++ b/fs/namei.c
123 @@ -347,6 +347,7 @@ int deny_write_access(struct file * file)
124  
125         return 0;
126  }
127 +EXPORT_SYMBOL(deny_write_access);
128  
129  /**
130   * path_get - get a reference to a path
131 @@ -1177,6 +1178,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
132                 return ERR_PTR(err);
133         return __lookup_hash(&nd->last, nd->path.dentry, nd);
134  }
135 +EXPORT_SYMBOL(lookup_hash);
136  
137  int __lookup_one_len(const char *name, struct qstr *this,
138                 struct dentry *base, int len)
139 @@ -1199,6 +1201,7 @@ int __lookup_one_len(const char *name, struct qstr *this,
140         this->hash = end_name_hash(hash);
141         return 0;
142  }
143 +EXPORT_SYMBOL(__lookup_one_len);
144  
145  /**
146   * lookup_one_len - filesystem helper to lookup single pathname component
147 diff --git a/fs/namespace.c b/fs/namespace.c
148 index 2e10cb1..8fa77c4 100644
149 --- a/fs/namespace.c
150 +++ b/fs/namespace.c
151 @@ -1283,6 +1283,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
152         }
153         return 0;
154  }
155 +EXPORT_SYMBOL(iterate_mounts);
156  
157  static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
158  {
159 diff --git a/fs/notify/group.c b/fs/notify/group.c
160 index d309f38..f0e9568 100644
161 --- a/fs/notify/group.c
162 +++ b/fs/notify/group.c
163 @@ -22,6 +22,7 @@
164  #include <linux/srcu.h>
165  #include <linux/rculist.h>
166  #include <linux/wait.h>
167 +#include <linux/module.h>
168  
169  #include <linux/fsnotify_backend.h>
170  #include "fsnotify.h"
171 @@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
172         if (atomic_dec_and_test(&group->refcnt))
173                 fsnotify_destroy_group(group);
174  }
175 +EXPORT_SYMBOL(fsnotify_put_group);
176  
177  /*
178   * Create a new fsnotify_group and hold a reference for the group returned.
179 @@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
180  
181         return group;
182  }
183 +EXPORT_SYMBOL(fsnotify_alloc_group);
184 diff --git a/fs/notify/mark.c b/fs/notify/mark.c
185 index 325185e..adede09 100644
186 --- a/fs/notify/mark.c
187 +++ b/fs/notify/mark.c
188 @@ -113,6 +113,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
189         if (atomic_dec_and_test(&mark->refcnt))
190                 mark->free_mark(mark);
191  }
192 +EXPORT_SYMBOL(fsnotify_put_mark);
193  
194  /*
195   * Any time a mark is getting freed we end up here.
196 @@ -190,6 +191,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
197         if (unlikely(atomic_dec_and_test(&group->num_marks)))
198                 fsnotify_final_destroy_group(group);
199  }
200 +EXPORT_SYMBOL(fsnotify_destroy_mark);
201  
202  void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
203  {
204 @@ -277,6 +279,7 @@ err:
205  
206         return ret;
207  }
208 +EXPORT_SYMBOL(fsnotify_add_mark);
209  
210  /*
211   * clear any marks in a group in which mark->flags & flags is true
212 @@ -332,6 +335,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
213         atomic_set(&mark->refcnt, 1);
214         mark->free_mark = free_mark;
215  }
216 +EXPORT_SYMBOL(fsnotify_init_mark);
217  
218  static int fsnotify_mark_destroy(void *ignored)
219  {
220 diff --git a/fs/open.c b/fs/open.c
221 index 630715f..1c864c7 100644
222 --- a/fs/open.c
223 +++ b/fs/open.c
224 @@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
225         mutex_unlock(&dentry->d_inode->i_mutex);
226         return ret;
227  }
228 +EXPORT_SYMBOL(do_truncate);
229  
230  static long do_sys_truncate(const char __user *pathname, loff_t length)
231  {
232 diff --git a/fs/splice.c b/fs/splice.c
233 index 278c94f..033f7ac 100644
234 --- a/fs/splice.c
235 +++ b/fs/splice.c
236 @@ -1116,6 +1116,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
237  
238         return splice_write(pipe, out, ppos, len, flags);
239  }
240 +EXPORT_SYMBOL(do_splice_from);
241  
242  /*
243   * Attempt to initiate a splice from a file to a pipe.
244 @@ -1142,6 +1143,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
245  
246         return splice_read(in, ppos, pipe, len, flags);
247  }
248 +EXPORT_SYMBOL(do_splice_to);
249  
250  /**
251   * splice_direct_to_actor - splices data directly between two non-pipes
252 diff --git a/security/commoncap.c b/security/commoncap.c
253 index 4e01599..3611e1b 100644
254 --- a/security/commoncap.c
255 +++ b/security/commoncap.c
256 @@ -951,3 +951,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
257         }
258         return ret;
259  }
260 +EXPORT_SYMBOL(cap_file_mmap);
261 diff --git a/security/device_cgroup.c b/security/device_cgroup.c
262 index 8d9c48f..29108aa 100644
263 --- a/security/device_cgroup.c
264 +++ b/security/device_cgroup.c
265 @@ -515,6 +515,7 @@ found:
266  
267         return -EPERM;
268  }
269 +EXPORT_SYMBOL(devcgroup_inode_permission);
270  
271  int devcgroup_inode_mknod(int mode, dev_t dev)
272  {
273 diff --git a/security/security.c b/security/security.c
274 index c53949f..0ae5b91 100644
275 --- a/security/security.c
276 +++ b/security/security.c
277 @@ -376,6 +376,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
278                 return 0;
279         return security_ops->path_mkdir(dir, dentry, mode);
280  }
281 +EXPORT_SYMBOL(security_path_mkdir);
282  
283  int security_path_rmdir(struct path *dir, struct dentry *dentry)
284  {
285 @@ -383,6 +384,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
286                 return 0;
287         return security_ops->path_rmdir(dir, dentry);
288  }
289 +EXPORT_SYMBOL(security_path_rmdir);
290  
291  int security_path_unlink(struct path *dir, struct dentry *dentry)
292  {
293 @@ -390,6 +392,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
294                 return 0;
295         return security_ops->path_unlink(dir, dentry);
296  }
297 +EXPORT_SYMBOL(security_path_unlink);
298  
299  int security_path_symlink(struct path *dir, struct dentry *dentry,
300                           const char *old_name)
301 @@ -398,6 +401,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
302                 return 0;
303         return security_ops->path_symlink(dir, dentry, old_name);
304  }
305 +EXPORT_SYMBOL(security_path_symlink);
306  
307  int security_path_link(struct dentry *old_dentry, struct path *new_dir,
308                        struct dentry *new_dentry)
309 @@ -406,6 +410,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
310                 return 0;
311         return security_ops->path_link(old_dentry, new_dir, new_dentry);
312  }
313 +EXPORT_SYMBOL(security_path_link);
314  
315  int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
316                          struct path *new_dir, struct dentry *new_dentry)
317 @@ -416,6 +421,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
318         return security_ops->path_rename(old_dir, old_dentry, new_dir,
319                                          new_dentry);
320  }
321 +EXPORT_SYMBOL(security_path_rename);
322  
323  int security_path_truncate(struct path *path)
324  {
325 @@ -423,6 +429,7 @@ int security_path_truncate(struct path *path)
326                 return 0;
327         return security_ops->path_truncate(path);
328  }
329 +EXPORT_SYMBOL(security_path_truncate);
330  
331  int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
332                         mode_t mode)
333 @@ -431,6 +438,7 @@ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
334                 return 0;
335         return security_ops->path_chmod(dentry, mnt, mode);
336  }
337 +EXPORT_SYMBOL(security_path_chmod);
338  
339  int security_path_chown(struct path *path, uid_t uid, gid_t gid)
340  {
341 @@ -438,6 +446,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
342                 return 0;
343         return security_ops->path_chown(path, uid, gid);
344  }
345 +EXPORT_SYMBOL(security_path_chown);
346  
347  int security_path_chroot(struct path *path)
348  {
349 @@ -514,6 +523,7 @@ int security_inode_readlink(struct dentry *dentry)
350                 return 0;
351         return security_ops->inode_readlink(dentry);
352  }
353 +EXPORT_SYMBOL(security_inode_readlink);
354  
355  int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
356  {
357 @@ -528,6 +538,7 @@ int security_inode_permission(struct inode *inode, int mask)
358                 return 0;
359         return security_ops->inode_permission(inode, mask);
360  }
361 +EXPORT_SYMBOL(security_inode_permission);
362  
363  int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
364  {
365 @@ -627,6 +638,7 @@ int security_file_permission(struct file *file, int mask)
366  
367         return fsnotify_perm(file, mask);
368  }
369 +EXPORT_SYMBOL(security_file_permission);
370  
371  int security_file_alloc(struct file *file)
372  {
373 @@ -654,6 +666,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
374                 return ret;
375         return ima_file_mmap(file, prot);
376  }
377 +EXPORT_SYMBOL(security_file_mmap);
378  
379  int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
380                             unsigned long prot)
381 diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
382 --- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs     1970-01-01 01:00:00.000000000 +0100
383 +++ linux/Documentation/ABI/testing/debugfs-aufs        2010-10-21 09:52:43.080290296 +0200
384 @@ -0,0 +1,37 @@
385 +What:          /debug/aufs/si_<id>/
386 +Date:          March 2009
387 +Contact:       J. R. Okajima <hooanon05@yahoo.co.jp>
388 +Description:
389 +               Under /debug/aufs, a directory named si_<id> is created
390 +               per aufs mount, where <id> is a unique id generated
391 +               internally.
392 +
393 +What:          /debug/aufs/si_<id>/xib
394 +Date:          March 2009
395 +Contact:       J. R. Okajima <hooanon05@yahoo.co.jp>
396 +Description:
397 +               It shows the consumed blocks by xib (External Inode Number
398 +               Bitmap), its block size and file size.
399 +               When the aufs mount option 'noxino' is specified, it
400 +               will be empty. About XINO files, see the aufs manual.
401 +
402 +What:          /debug/aufs/si_<id>/xino0, xino1 ... xinoN
403 +Date:          March 2009
404 +Contact:       J. R. Okajima <hooanon05@yahoo.co.jp>
405 +Description:
406 +               It shows the consumed blocks by xino (External Inode Number
407 +               Translation Table), its link count, block size and file
408 +               size.
409 +               When the aufs mount option 'noxino' is specified, it
410 +               will be empty. About XINO files, see the aufs manual.
411 +
412 +What:          /debug/aufs/si_<id>/xigen
413 +Date:          March 2009
414 +Contact:       J. R. Okajima <hooanon05@yahoo.co.jp>
415 +Description:
416 +               It shows the consumed blocks by xigen (External Inode
417 +               Generation Table), its block size and file size.
418 +               If CONFIG_AUFS_EXPORT is disabled, this entry will not
419 +               be created.
420 +               When the aufs mount option 'noxino' is specified, it
421 +               will be empty. About XINO files, see the aufs manual.
422 diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
423 --- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs       1970-01-01 01:00:00.000000000 +0100
424 +++ linux/Documentation/ABI/testing/sysfs-aufs  2010-10-21 09:52:43.080290296 +0200
425 @@ -0,0 +1,24 @@
426 +What:          /sys/fs/aufs/si_<id>/
427 +Date:          March 2009
428 +Contact:       J. R. Okajima <hooanon05@yahoo.co.jp>
429 +Description:
430 +               Under /sys/fs/aufs, a directory named si_<id> is created
431 +               per aufs mount, where <id> is a unique id generated
432 +               internally.
433 +
434 +What:          /sys/fs/aufs/si_<id>/br0, br1 ... brN
435 +Date:          March 2009
436 +Contact:       J. R. Okajima <hooanon05@yahoo.co.jp>
437 +Description:
438 +               It shows the abolute path of a member directory (which
439 +               is called branch) in aufs, and its permission.
440 +
441 +What:          /sys/fs/aufs/si_<id>/xi_path
442 +Date:          March 2009
443 +Contact:       J. R. Okajima <hooanon05@yahoo.co.jp>
444 +Description:
445 +               It shows the abolute path of XINO (External Inode Number
446 +               Bitmap, Translation Table and Generation Table) file
447 +               even if it is the default path.
448 +               When the aufs mount option 'noxino' is specified, it
449 +               will be empty. About XINO files, see the aufs manual.
450 diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
451 --- /usr/share/empty/fs/aufs/aufs.h     1970-01-01 01:00:00.000000000 +0100
452 +++ linux/fs/aufs/aufs.h        2010-10-21 09:52:43.083624114 +0200
453 @@ -0,0 +1,61 @@
454 +/*
455 + * Copyright (C) 2005-2010 Junjiro R. Okajima
456 + *
457 + * This program, aufs is free software; you can redistribute it and/or modify
458 + * it under the terms of the GNU General Public License as published by
459 + * the Free Software Foundation; either version 2 of the License, or
460 + * (at your option) any later version.
461 + *
462 + * This program is distributed in the hope that it will be useful,
463 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
464 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
465 + * GNU General Public License for more details.
466 + *
467 + * You should have received a copy of the GNU General Public License
468 + * along with this program; if not, write to the Free Software
469 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
470 + */
471 +
472 +/*
473 + * all header files
474 + */
475 +
476 +#ifndef __AUFS_H__
477 +#define __AUFS_H__
478 +
479 +#ifdef __KERNEL__
480 +
481 +#define AuStub(type, name, body, ...) \
482 +       static inline type name(__VA_ARGS__) { body; }
483 +
484 +#define AuStubVoid(name, ...) \
485 +       AuStub(void, name, , __VA_ARGS__)
486 +#define AuStubInt0(name, ...) \
487 +       AuStub(int, name, return 0, __VA_ARGS__)
488 +
489 +#include "debug.h"
490 +
491 +#include "branch.h"
492 +#include "cpup.h"
493 +#include "dcsub.h"
494 +#include "dbgaufs.h"
495 +#include "dentry.h"
496 +#include "dir.h"
497 +#include "dynop.h"
498 +#include "file.h"
499 +#include "fstype.h"
500 +#include "inode.h"
501 +#include "loop.h"
502 +#include "module.h"
503 +/* never include ./mtx.h */
504 +#include "opts.h"
505 +#include "rwsem.h"
506 +#include "spl.h"
507 +#include "super.h"
508 +#include "sysaufs.h"
509 +#include "vfsub.h"
510 +#include "whout.h"
511 +#include "wkq.h"
512 +
513 +#endif /* __KERNEL__ */
514 +#endif /* __AUFS_H__ */
515 diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
516 --- /usr/share/empty/fs/aufs/branch.c   1970-01-01 01:00:00.000000000 +0100
517 +++ linux/fs/aufs/branch.c      2010-10-21 09:52:43.086957936 +0200
518 @@ -0,0 +1,1005 @@
519 +/*
520 + * Copyright (C) 2005-2010 Junjiro R. Okajima
521 + *
522 + * This program, aufs is free software; you can redistribute it and/or modify
523 + * it under the terms of the GNU General Public License as published by
524 + * the Free Software Foundation; either version 2 of the License, or
525 + * (at your option) any later version.
526 + *
527 + * This program is distributed in the hope that it will be useful,
528 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
529 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
530 + * GNU General Public License for more details.
531 + *
532 + * You should have received a copy of the GNU General Public License
533 + * along with this program; if not, write to the Free Software
534 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
535 + */
536 +
537 +/*
538 + * branch management
539 + */
540 +
541 +#include <linux/file.h>
542 +#include <linux/statfs.h>
543 +#include "aufs.h"
544 +
545 +/*
546 + * free a single branch
547 + */
548 +static void au_br_do_free(struct au_branch *br)
549 +{
550 +       int i;
551 +       struct au_wbr *wbr;
552 +       struct au_dykey **key;
553 +
554 +       if (br->br_xino.xi_file)
555 +               fput(br->br_xino.xi_file);
556 +       mutex_destroy(&br->br_xino.xi_nondir_mtx);
557 +
558 +       AuDebugOn(atomic_read(&br->br_count));
559 +
560 +       wbr = br->br_wbr;
561 +       if (wbr) {
562 +               for (i = 0; i < AuBrWh_Last; i++)
563 +                       dput(wbr->wbr_wh[i]);
564 +               AuDebugOn(atomic_read(&wbr->wbr_wh_running));
565 +               AuRwDestroy(&wbr->wbr_wh_rwsem);
566 +       }
567 +
568 +       key = br->br_dykey;
569 +       for (i = 0; i < AuBrDynOp; i++, key++)
570 +               if (*key)
571 +                       au_dy_put(*key);
572 +               else
573 +                       break;
574 +
575 +       mntput(br->br_mnt);
576 +       kfree(wbr);
577 +       kfree(br);
578 +}
579 +
580 +/*
581 + * frees all branches
582 + */
583 +void au_br_free(struct au_sbinfo *sbinfo)
584 +{
585 +       aufs_bindex_t bmax;
586 +       struct au_branch **br;
587 +
588 +       AuRwMustWriteLock(&sbinfo->si_rwsem);
589 +
590 +       bmax = sbinfo->si_bend + 1;
591 +       br = sbinfo->si_branch;
592 +       while (bmax--)
593 +               au_br_do_free(*br++);
594 +}
595 +
596 +/*
597 + * find the index of a branch which is specified by @br_id.
598 + */
599 +int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
600 +{
601 +       aufs_bindex_t bindex, bend;
602 +
603 +       bend = au_sbend(sb);
604 +       for (bindex = 0; bindex <= bend; bindex++)
605 +               if (au_sbr_id(sb, bindex) == br_id)
606 +                       return bindex;
607 +       return -1;
608 +}
609 +
610 +/* ---------------------------------------------------------------------- */
611 +
612 +/*
613 + * add a branch
614 + */
615 +
616 +static int test_overlap(struct super_block *sb, struct dentry *h_adding,
617 +                       struct dentry *h_root)
618 +{
619 +       if (unlikely(h_adding == h_root
620 +                    || au_test_loopback_overlap(sb, h_adding)))
621 +               return 1;
622 +       if (h_adding->d_sb != h_root->d_sb)
623 +               return 0;
624 +       return au_test_subdir(h_adding, h_root)
625 +               || au_test_subdir(h_root, h_adding);
626 +}
627 +
628 +/*
629 + * returns a newly allocated branch. @new_nbranch is a number of branches
630 + * after adding a branch.
631 + */
632 +static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
633 +                                    int perm)
634 +{
635 +       struct au_branch *add_branch;
636 +       struct dentry *root;
637 +       int err;
638 +
639 +       err = -ENOMEM;
640 +       root = sb->s_root;
641 +       add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
642 +       if (unlikely(!add_branch))
643 +               goto out;
644 +
645 +       add_branch->br_wbr = NULL;
646 +       if (au_br_writable(perm)) {
647 +               /* may be freed separately at changing the branch permission */
648 +               add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
649 +                                            GFP_NOFS);
650 +               if (unlikely(!add_branch->br_wbr))
651 +                       goto out_br;
652 +       }
653 +
654 +       err = au_sbr_realloc(au_sbi(sb), new_nbranch);
655 +       if (!err)
656 +               err = au_di_realloc(au_di(root), new_nbranch);
657 +       if (!err)
658 +               err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
659 +       if (!err)
660 +               return add_branch; /* success */
661 +
662 +       kfree(add_branch->br_wbr);
663 +
664 +out_br:
665 +       kfree(add_branch);
666 +out:
667 +       return ERR_PTR(err);
668 +}
669 +
670 +/*
671 + * test if the branch permission is legal or not.
672 + */
673 +static int test_br(struct inode *inode, int brperm, char *path)
674 +{
675 +       int err;
676 +
677 +       err = (au_br_writable(brperm) && IS_RDONLY(inode));
678 +       if (!err)
679 +               goto out;
680 +
681 +       err = -EINVAL;
682 +       pr_err("write permission for readonly mount or inode, %s\n", path);
683 +
684 +out:
685 +       return err;
686 +}
687 +
688 +/*
689 + * returns:
690 + * 0: success, the caller will add it
691 + * plus: success, it is already unified, the caller should ignore it
692 + * minus: error
693 + */
694 +static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
695 +{
696 +       int err;
697 +       aufs_bindex_t bend, bindex;
698 +       struct dentry *root;
699 +       struct inode *inode, *h_inode;
700 +
701 +       root = sb->s_root;
702 +       bend = au_sbend(sb);
703 +       if (unlikely(bend >= 0
704 +                    && au_find_dbindex(root, add->path.dentry) >= 0)) {
705 +               err = 1;
706 +               if (!remount) {
707 +                       err = -EINVAL;
708 +                       pr_err("%s duplicated\n", add->pathname);
709 +               }
710 +               goto out;
711 +       }
712 +
713 +       err = -ENOSPC; /* -E2BIG; */
714 +       if (unlikely(AUFS_BRANCH_MAX <= add->bindex
715 +                    || AUFS_BRANCH_MAX - 1 <= bend)) {
716 +               pr_err("number of branches exceeded %s\n", add->pathname);
717 +               goto out;
718 +       }
719 +
720 +       err = -EDOM;
721 +       if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
722 +               pr_err("bad index %d\n", add->bindex);
723 +               goto out;
724 +       }
725 +
726 +       inode = add->path.dentry->d_inode;
727 +       err = -ENOENT;
728 +       if (unlikely(!inode->i_nlink)) {
729 +               pr_err("no existence %s\n", add->pathname);
730 +               goto out;
731 +       }
732 +
733 +       err = -EINVAL;
734 +       if (unlikely(inode->i_sb == sb)) {
735 +               pr_err("%s must be outside\n", add->pathname);
736 +               goto out;
737 +       }
738 +
739 +       if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
740 +               pr_err("unsupported filesystem, %s (%s)\n",
741 +                      add->pathname, au_sbtype(inode->i_sb));
742 +               goto out;
743 +       }
744 +
745 +       err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
746 +       if (unlikely(err))
747 +               goto out;
748 +
749 +       if (bend < 0)
750 +               return 0; /* success */
751 +
752 +       err = -EINVAL;
753 +       for (bindex = 0; bindex <= bend; bindex++)
754 +               if (unlikely(test_overlap(sb, add->path.dentry,
755 +                                         au_h_dptr(root, bindex)))) {
756 +                       pr_err("%s is overlapped\n", add->pathname);
757 +                       goto out;
758 +               }
759 +
760 +       err = 0;
761 +       if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
762 +               h_inode = au_h_dptr(root, 0)->d_inode;
763 +               if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
764 +                   || h_inode->i_uid != inode->i_uid
765 +                   || h_inode->i_gid != inode->i_gid)
766 +                       pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
767 +                                  add->pathname,
768 +                                  inode->i_uid, inode->i_gid,
769 +                                  (inode->i_mode & S_IALLUGO),
770 +                                  h_inode->i_uid, h_inode->i_gid,
771 +                                  (h_inode->i_mode & S_IALLUGO));
772 +       }
773 +
774 +out:
775 +       return err;
776 +}
777 +
778 +/*
779 + * initialize or clean the whiteouts for an adding branch
780 + */
781 +static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
782 +                        int new_perm, struct dentry *h_root)
783 +{
784 +       int err, old_perm;
785 +       aufs_bindex_t bindex;
786 +       struct mutex *h_mtx;
787 +       struct au_wbr *wbr;
788 +       struct au_hinode *hdir;
789 +
790 +       wbr = br->br_wbr;
791 +       old_perm = br->br_perm;
792 +       br->br_perm = new_perm;
793 +       hdir = NULL;
794 +       h_mtx = NULL;
795 +       bindex = au_br_index(sb, br->br_id);
796 +       if (0 <= bindex) {
797 +               hdir = au_hi(sb->s_root->d_inode, bindex);
798 +               au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
799 +       } else {
800 +               h_mtx = &h_root->d_inode->i_mutex;
801 +               mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
802 +       }
803 +       if (!wbr)
804 +               err = au_wh_init(h_root, br, sb);
805 +       else {
806 +               wbr_wh_write_lock(wbr);
807 +               err = au_wh_init(h_root, br, sb);
808 +               wbr_wh_write_unlock(wbr);
809 +       }
810 +       if (hdir)
811 +               au_hn_imtx_unlock(hdir);
812 +       else
813 +               mutex_unlock(h_mtx);
814 +       br->br_perm = old_perm;
815 +
816 +       if (!err && wbr && !au_br_writable(new_perm)) {
817 +               kfree(wbr);
818 +               br->br_wbr = NULL;
819 +       }
820 +
821 +       return err;
822 +}
823 +
824 +static int au_wbr_init(struct au_branch *br, struct super_block *sb,
825 +                      int perm, struct path *path)
826 +{
827 +       int err;
828 +       struct kstatfs kst;
829 +       struct au_wbr *wbr;
830 +       struct dentry *h_dentry;
831 +
832 +       wbr = br->br_wbr;
833 +       au_rw_init(&wbr->wbr_wh_rwsem);
834 +       memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
835 +       atomic_set(&wbr->wbr_wh_running, 0);
836 +       wbr->wbr_bytes = 0;
837 +
838 +       /*
839 +        * a limit for rmdir/rename a dir
840 +        * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
841 +        */
842 +       err = vfs_statfs(path, &kst);
843 +       if (unlikely(err))
844 +               goto out;
845 +       err = -EINVAL;
846 +       h_dentry = path->dentry;
847 +       if (kst.f_namelen >= NAME_MAX)
848 +               err = au_br_init_wh(sb, br, perm, h_dentry);
849 +       else
850 +               pr_err("%.*s(%s), unsupported namelen %ld\n",
851 +                      AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
852 +                      kst.f_namelen);
853 +
854 +out:
855 +       return err;
856 +}
857 +
858 +/* intialize a new branch */
859 +static int au_br_init(struct au_branch *br, struct super_block *sb,
860 +                     struct au_opt_add *add)
861 +{
862 +       int err;
863 +
864 +       err = 0;
865 +       memset(&br->br_xino, 0, sizeof(br->br_xino));
866 +       mutex_init(&br->br_xino.xi_nondir_mtx);
867 +       br->br_perm = add->perm;
868 +       br->br_mnt = add->path.mnt; /* set first, mntget() later */
869 +       spin_lock_init(&br->br_dykey_lock);
870 +       memset(br->br_dykey, 0, sizeof(br->br_dykey));
871 +       atomic_set(&br->br_count, 0);
872 +       br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
873 +       atomic_set(&br->br_xino_running, 0);
874 +       br->br_id = au_new_br_id(sb);
875 +
876 +       if (au_br_writable(add->perm)) {
877 +               err = au_wbr_init(br, sb, add->perm, &add->path);
878 +               if (unlikely(err))
879 +                       goto out_err;
880 +       }
881 +
882 +       if (au_opt_test(au_mntflags(sb), XINO)) {
883 +               err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
884 +                                au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
885 +               if (unlikely(err)) {
886 +                       AuDebugOn(br->br_xino.xi_file);
887 +                       goto out_err;
888 +               }
889 +       }
890 +
891 +       sysaufs_br_init(br);
892 +       mntget(add->path.mnt);
893 +       goto out; /* success */
894 +
895 +out_err:
896 +       br->br_mnt = NULL;
897 +out:
898 +       return err;
899 +}
900 +
901 +static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
902 +                            struct au_branch *br, aufs_bindex_t bend,
903 +                            aufs_bindex_t amount)
904 +{
905 +       struct au_branch **brp;
906 +
907 +       AuRwMustWriteLock(&sbinfo->si_rwsem);
908 +
909 +       brp = sbinfo->si_branch + bindex;
910 +       memmove(brp + 1, brp, sizeof(*brp) * amount);
911 +       *brp = br;
912 +       sbinfo->si_bend++;
913 +       if (unlikely(bend < 0))
914 +               sbinfo->si_bend = 0;
915 +}
916 +
917 +static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
918 +                            aufs_bindex_t bend, aufs_bindex_t amount)
919 +{
920 +       struct au_hdentry *hdp;
921 +
922 +       AuRwMustWriteLock(&dinfo->di_rwsem);
923 +
924 +       hdp = dinfo->di_hdentry + bindex;
925 +       memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
926 +       au_h_dentry_init(hdp);
927 +       dinfo->di_bend++;
928 +       if (unlikely(bend < 0))
929 +               dinfo->di_bstart = 0;
930 +}
931 +
932 +static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
933 +                            aufs_bindex_t bend, aufs_bindex_t amount)
934 +{
935 +       struct au_hinode *hip;
936 +
937 +       AuRwMustWriteLock(&iinfo->ii_rwsem);
938 +
939 +       hip = iinfo->ii_hinode + bindex;
940 +       memmove(hip + 1, hip, sizeof(*hip) * amount);
941 +       hip->hi_inode = NULL;
942 +       au_hn_init(hip);
943 +       iinfo->ii_bend++;
944 +       if (unlikely(bend < 0))
945 +               iinfo->ii_bstart = 0;
946 +}
947 +
948 +static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
949 +                        struct au_branch *br, aufs_bindex_t bindex)
950 +{
951 +       struct dentry *root;
952 +       struct inode *root_inode;
953 +       aufs_bindex_t bend, amount;
954 +
955 +       root = sb->s_root;
956 +       root_inode = root->d_inode;
957 +       au_plink_maint_block(sb);
958 +       bend = au_sbend(sb);
959 +       amount = bend + 1 - bindex;
960 +       au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
961 +       au_br_do_add_hdp(au_di(root), bindex, bend, amount);
962 +       au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
963 +       au_set_h_dptr(root, bindex, dget(h_dentry));
964 +       au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
965 +                     /*flags*/0);
966 +}
967 +
968 +int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
969 +{
970 +       int err;
971 +       aufs_bindex_t bend, add_bindex;
972 +       struct dentry *root, *h_dentry;
973 +       struct inode *root_inode;
974 +       struct au_branch *add_branch;
975 +
976 +       root = sb->s_root;
977 +       root_inode = root->d_inode;
978 +       IMustLock(root_inode);
979 +       err = test_add(sb, add, remount);
980 +       if (unlikely(err < 0))
981 +               goto out;
982 +       if (err) {
983 +               err = 0;
984 +               goto out; /* success */
985 +       }
986 +
987 +       bend = au_sbend(sb);
988 +       add_branch = au_br_alloc(sb, bend + 2, add->perm);
989 +       err = PTR_ERR(add_branch);
990 +       if (IS_ERR(add_branch))
991 +               goto out;
992 +
993 +       err = au_br_init(add_branch, sb, add);
994 +       if (unlikely(err)) {
995 +               au_br_do_free(add_branch);
996 +               goto out;
997 +       }
998 +
999 +       add_bindex = add->bindex;
1000 +       h_dentry = add->path.dentry;
1001 +       if (!remount)
1002 +               au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1003 +       else {
1004 +               sysaufs_brs_del(sb, add_bindex);
1005 +               au_br_do_add(sb, h_dentry, add_branch, add_bindex);
1006 +               sysaufs_brs_add(sb, add_bindex);
1007 +       }
1008 +
1009 +       if (!add_bindex) {
1010 +               au_cpup_attr_all(root_inode, /*force*/1);
1011 +               sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
1012 +       } else
1013 +               au_add_nlink(root_inode, h_dentry->d_inode);
1014 +
1015 +       /*
1016 +        * this test/set prevents aufs from handling unnecesary notify events
1017 +        * of xino files, in a case of re-adding a writable branch which was
1018 +        * once detached from aufs.
1019 +        */
1020 +       if (au_xino_brid(sb) < 0
1021 +           && au_br_writable(add_branch->br_perm)
1022 +           && !au_test_fs_bad_xino(h_dentry->d_sb)
1023 +           && add_branch->br_xino.xi_file
1024 +           && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
1025 +               au_xino_brid_set(sb, add_branch->br_id);
1026 +
1027 +out:
1028 +       return err;
1029 +}
1030 +
1031 +/* ---------------------------------------------------------------------- */
1032 +
1033 +/*
1034 + * delete a branch
1035 + */
1036 +
1037 +/* to show the line number, do not make it inlined function */
1038 +#define AuVerbose(do_info, fmt, ...) do { \
1039 +       if (do_info) \
1040 +               pr_info(fmt, ##__VA_ARGS__); \
1041 +} while (0)
1042 +
1043 +/*
1044 + * test if the branch is deletable or not.
1045 + */
1046 +static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
1047 +                           unsigned int sigen, const unsigned int verbose)
1048 +{
1049 +       int err, i, j, ndentry;
1050 +       aufs_bindex_t bstart, bend;
1051 +       struct au_dcsub_pages dpages;
1052 +       struct au_dpage *dpage;
1053 +       struct dentry *d;
1054 +       struct inode *inode;
1055 +
1056 +       err = au_dpages_init(&dpages, GFP_NOFS);
1057 +       if (unlikely(err))
1058 +               goto out;
1059 +       err = au_dcsub_pages(&dpages, root, NULL, NULL);
1060 +       if (unlikely(err))
1061 +               goto out_dpages;
1062 +
1063 +       for (i = 0; !err && i < dpages.ndpage; i++) {
1064 +               dpage = dpages.dpages + i;
1065 +               ndentry = dpage->ndentry;
1066 +               for (j = 0; !err && j < ndentry; j++) {
1067 +                       d = dpage->dentries[j];
1068 +                       AuDebugOn(!atomic_read(&d->d_count));
1069 +                       inode = d->d_inode;
1070 +                       if (au_digen(d) == sigen && au_iigen(inode) == sigen)
1071 +                               di_read_lock_child(d, AuLock_IR);
1072 +                       else {
1073 +                               di_write_lock_child(d);
1074 +                               err = au_reval_dpath(d, sigen);
1075 +                               if (!err)
1076 +                                       di_downgrade_lock(d, AuLock_IR);
1077 +                               else {
1078 +                                       di_write_unlock(d);
1079 +                                       break;
1080 +                               }
1081 +                       }
1082 +
1083 +                       bstart = au_dbstart(d);
1084 +                       bend = au_dbend(d);
1085 +                       if (bstart <= bindex
1086 +                           && bindex <= bend
1087 +                           && au_h_dptr(d, bindex)
1088 +                           && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
1089 +                               err = -EBUSY;
1090 +                               AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
1091 +                       }
1092 +                       di_read_unlock(d, AuLock_IR);
1093 +               }
1094 +       }
1095 +
1096 +out_dpages:
1097 +       au_dpages_free(&dpages);
1098 +out:
1099 +       return err;
1100 +}
1101 +
1102 +static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
1103 +                          unsigned int sigen, const unsigned int verbose)
1104 +{
1105 +       int err;
1106 +       struct inode *i;
1107 +       aufs_bindex_t bstart, bend;
1108 +
1109 +       err = 0;
1110 +       list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
1111 +               AuDebugOn(!atomic_read(&i->i_count));
1112 +               if (!list_empty(&i->i_dentry))
1113 +                       continue;
1114 +
1115 +               if (au_iigen(i) == sigen)
1116 +                       ii_read_lock_child(i);
1117 +               else {
1118 +                       ii_write_lock_child(i);
1119 +                       err = au_refresh_hinode_self(i, /*do_attr*/1);
1120 +                       if (!err)
1121 +                               ii_downgrade_lock(i);
1122 +                       else {
1123 +                               ii_write_unlock(i);
1124 +                               break;
1125 +                       }
1126 +               }
1127 +
1128 +               bstart = au_ibstart(i);
1129 +               bend = au_ibend(i);
1130 +               if (bstart <= bindex
1131 +                   && bindex <= bend
1132 +                   && au_h_iptr(i, bindex)
1133 +                   && (!S_ISDIR(i->i_mode) || bstart == bend)) {
1134 +                       err = -EBUSY;
1135 +                       AuVerbose(verbose, "busy i%lu\n", i->i_ino);
1136 +                       ii_read_unlock(i);
1137 +                       break;
1138 +               }
1139 +               ii_read_unlock(i);
1140 +       }
1141 +
1142 +       return err;
1143 +}
1144 +
1145 +static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
1146 +                             const unsigned int verbose)
1147 +{
1148 +       int err;
1149 +       unsigned int sigen;
1150 +
1151 +       sigen = au_sigen(root->d_sb);
1152 +       DiMustNoWaiters(root);
1153 +       IiMustNoWaiters(root->d_inode);
1154 +       di_write_unlock(root);
1155 +       err = test_dentry_busy(root, bindex, sigen, verbose);
1156 +       if (!err)
1157 +               err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1158 +       di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
1159 +
1160 +       return err;
1161 +}
1162 +
1163 +static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
1164 +                            const aufs_bindex_t bindex,
1165 +                            const aufs_bindex_t bend)
1166 +{
1167 +       struct au_branch **brp, **p;
1168 +
1169 +       AuRwMustWriteLock(&sbinfo->si_rwsem);
1170 +
1171 +       brp = sbinfo->si_branch + bindex;
1172 +       if (bindex < bend)
1173 +               memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
1174 +       sbinfo->si_branch[0 + bend] = NULL;
1175 +       sbinfo->si_bend--;
1176 +
1177 +       p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
1178 +       if (p)
1179 +               sbinfo->si_branch = p;
1180 +       /* harmless error */
1181 +}
1182 +
1183 +static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
1184 +                            const aufs_bindex_t bend)
1185 +{
1186 +       struct au_hdentry *hdp, *p;
1187 +
1188 +       AuRwMustWriteLock(&dinfo->di_rwsem);
1189 +
1190 +       hdp = dinfo->di_hdentry;
1191 +       if (bindex < bend)
1192 +               memmove(hdp + bindex, hdp + bindex + 1,
1193 +                       sizeof(*hdp) * (bend - bindex));
1194 +       hdp[0 + bend].hd_dentry = NULL;
1195 +       dinfo->di_bend--;
1196 +
1197 +       p = krealloc(hdp, sizeof(*p) * bend, GFP_NOFS);
1198 +       if (p)
1199 +               dinfo->di_hdentry = p;
1200 +       /* harmless error */
1201 +}
1202 +
1203 +static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
1204 +                            const aufs_bindex_t bend)
1205 +{
1206 +       struct au_hinode *hip, *p;
1207 +
1208 +       AuRwMustWriteLock(&iinfo->ii_rwsem);
1209 +
1210 +       hip = iinfo->ii_hinode + bindex;
1211 +       if (bindex < bend)
1212 +               memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
1213 +       iinfo->ii_hinode[0 + bend].hi_inode = NULL;
1214 +       au_hn_init(iinfo->ii_hinode + bend);
1215 +       iinfo->ii_bend--;
1216 +
1217 +       p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
1218 +       if (p)
1219 +               iinfo->ii_hinode = p;
1220 +       /* harmless error */
1221 +}
1222 +
1223 +static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
1224 +                        struct au_branch *br)
1225 +{
1226 +       aufs_bindex_t bend;
1227 +       struct au_sbinfo *sbinfo;
1228 +       struct dentry *root;
1229 +       struct inode *inode;
1230 +
1231 +       SiMustWriteLock(sb);
1232 +
1233 +       root = sb->s_root;
1234 +       inode = root->d_inode;
1235 +       au_plink_maint_block(sb);
1236 +       sbinfo = au_sbi(sb);
1237 +       bend = sbinfo->si_bend;
1238 +
1239 +       dput(au_h_dptr(root, bindex));
1240 +       au_hiput(au_hi(inode, bindex));
1241 +       au_br_do_free(br);
1242 +
1243 +       au_br_do_del_brp(sbinfo, bindex, bend);
1244 +       au_br_do_del_hdp(au_di(root), bindex, bend);
1245 +       au_br_do_del_hip(au_ii(inode), bindex, bend);
1246 +}
1247 +
1248 +int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
1249 +{
1250 +       int err, rerr, i;
1251 +       unsigned int mnt_flags;
1252 +       aufs_bindex_t bindex, bend, br_id;
1253 +       unsigned char do_wh, verbose;
1254 +       struct au_branch *br;
1255 +       struct au_wbr *wbr;
1256 +
1257 +       err = 0;
1258 +       bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
1259 +       if (bindex < 0) {
1260 +               if (remount)
1261 +                       goto out; /* success */
1262 +               err = -ENOENT;
1263 +               pr_err("%s no such branch\n", del->pathname);
1264 +               goto out;
1265 +       }
1266 +       AuDbg("bindex b%d\n", bindex);
1267 +
1268 +       err = -EBUSY;
1269 +       mnt_flags = au_mntflags(sb);
1270 +       verbose = !!au_opt_test(mnt_flags, VERBOSE);
1271 +       bend = au_sbend(sb);
1272 +       if (unlikely(!bend)) {
1273 +               AuVerbose(verbose, "no more branches left\n");
1274 +               goto out;
1275 +       }
1276 +       br = au_sbr(sb, bindex);
1277 +       i = atomic_read(&br->br_count);
1278 +       if (unlikely(i)) {
1279 +               AuVerbose(verbose, "%d file(s) opened\n", i);
1280 +               if (!verbose)
1281 +                       goto out;
1282 +       }
1283 +
1284 +       wbr = br->br_wbr;
1285 +       do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
1286 +       if (do_wh) {
1287 +               /* instead of WbrWhMustWriteLock(wbr) */
1288 +               SiMustWriteLock(sb);
1289 +               for (i = 0; i < AuBrWh_Last; i++) {
1290 +                       dput(wbr->wbr_wh[i]);
1291 +                       wbr->wbr_wh[i] = NULL;
1292 +               }
1293 +       }
1294 +
1295 +       err = test_children_busy(sb->s_root, bindex, verbose);
1296 +       if (unlikely(err)) {
1297 +               if (do_wh)
1298 +                       goto out_wh;
1299 +               goto out;
1300 +       }
1301 +
1302 +       err = 0;
1303 +       br_id = br->br_id;
1304 +       if (!remount)
1305 +               au_br_do_del(sb, bindex, br);
1306 +       else {
1307 +               sysaufs_brs_del(sb, bindex);
1308 +               au_br_do_del(sb, bindex, br);
1309 +               sysaufs_brs_add(sb, bindex);
1310 +       }
1311 +
1312 +       if (!bindex) {
1313 +               au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1314 +               sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
1315 +       } else
1316 +               au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
1317 +       if (au_opt_test(mnt_flags, PLINK))
1318 +               au_plink_half_refresh(sb, br_id);
1319 +
1320 +       if (au_xino_brid(sb) == br_id)
1321 +               au_xino_brid_set(sb, -1);
1322 +       goto out; /* success */
1323 +
1324 +out_wh:
1325 +       /* revert */
1326 +       rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
1327 +       if (rerr)
1328 +               pr_warning("failed re-creating base whiteout, %s. (%d)\n",
1329 +                          del->pathname, rerr);
1330 +out:
1331 +       return err;
1332 +}
1333 +
1334 +/* ---------------------------------------------------------------------- */
1335 +
1336 +/*
1337 + * change a branch permission
1338 + */
1339 +
1340 +static void au_warn_ima(void)
1341 +{
1342 +#ifdef CONFIG_IMA
1343 +       /* since it doesn't support mark_files_ro() */
1344 +       pr_warning("RW -> RO makes IMA to produce wrong message");
1345 +#endif
1346 +}
1347 +
1348 +static int do_need_sigen_inc(int a, int b)
1349 +{
1350 +       return au_br_whable(a) && !au_br_whable(b);
1351 +}
1352 +
1353 +static int need_sigen_inc(int old, int new)
1354 +{
1355 +       return do_need_sigen_inc(old, new)
1356 +               || do_need_sigen_inc(new, old);
1357 +}
1358 +
1359 +static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
1360 +{
1361 +       int err;
1362 +       unsigned long n, ul, bytes, files;
1363 +       aufs_bindex_t bstart;
1364 +       struct file *file, *hf, **a;
1365 +       const int step_bytes = 1024, /* memory allocation unit */
1366 +               step_files = step_bytes / sizeof(*a);
1367 +
1368 +       err = -ENOMEM;
1369 +       n = 0;
1370 +       bytes = step_bytes;
1371 +       files = step_files;
1372 +       a = kmalloc(bytes, GFP_NOFS);
1373 +       if (unlikely(!a))
1374 +               goto out;
1375 +
1376 +       /* no need file_list_lock() since sbinfo is locked? defered? */
1377 +       list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
1378 +               if (special_file(file->f_dentry->d_inode->i_mode))
1379 +                       continue;
1380 +
1381 +               AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
1382 +               fi_read_lock(file);
1383 +               if (unlikely(au_test_mmapped(file))) {
1384 +                       err = -EBUSY;
1385 +                       FiMustNoWaiters(file);
1386 +                       fi_read_unlock(file);
1387 +                       goto out_free;
1388 +               }
1389 +
1390 +               bstart = au_fbstart(file);
1391 +               if (!S_ISREG(file->f_dentry->d_inode->i_mode)
1392 +                   || !(file->f_mode & FMODE_WRITE)
1393 +                   || bstart != bindex) {
1394 +                       FiMustNoWaiters(file);
1395 +                       fi_read_unlock(file);
1396 +                       continue;
1397 +               }
1398 +
1399 +               hf = au_hf_top(file);
1400 +               FiMustNoWaiters(file);
1401 +               fi_read_unlock(file);
1402 +
1403 +               if (n < files)
1404 +                       a[n++] = hf;
1405 +               else {
1406 +                       void *p;
1407 +
1408 +                       err = -ENOMEM;
1409 +                       bytes += step_bytes;
1410 +                       files += step_files;
1411 +                       p = krealloc(a, bytes, GFP_NOFS);
1412 +                       if (p) {
1413 +                               a = p;
1414 +                               a[n++] = hf;
1415 +                       } else
1416 +                               goto out_free;
1417 +               }
1418 +       }
1419 +
1420 +       err = 0;
1421 +       if (n)
1422 +               au_warn_ima();
1423 +       for (ul = 0; ul < n; ul++) {
1424 +               /* todo: already flushed? */
1425 +               /* cf. fs/super.c:mark_files_ro() */
1426 +               hf = a[ul];
1427 +               hf->f_mode &= ~FMODE_WRITE;
1428 +               if (!file_check_writeable(hf)) {
1429 +                       file_release_write(hf);
1430 +                       mnt_drop_write(hf->f_vfsmnt);
1431 +               }
1432 +       }
1433 +
1434 +out_free:
1435 +       kfree(a);
1436 +out:
1437 +       return err;
1438 +}
1439 +
1440 +int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1441 +             int *do_update)
1442 +{
1443 +       int err, rerr;
1444 +       aufs_bindex_t bindex;
1445 +       struct path path;
1446 +       struct dentry *root;
1447 +       struct au_branch *br;
1448 +
1449 +       root = sb->s_root;
1450 +       au_plink_maint_block(sb);
1451 +       bindex = au_find_dbindex(root, mod->h_root);
1452 +       if (bindex < 0) {
1453 +               if (remount)
1454 +                       return 0; /* success */
1455 +               err = -ENOENT;
1456 +               pr_err("%s no such branch\n", mod->path);
1457 +               goto out;
1458 +       }
1459 +       AuDbg("bindex b%d\n", bindex);
1460 +
1461 +       err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
1462 +       if (unlikely(err))
1463 +               goto out;
1464 +
1465 +       br = au_sbr(sb, bindex);
1466 +       if (br->br_perm == mod->perm)
1467 +               return 0; /* success */
1468 +
1469 +       if (au_br_writable(br->br_perm)) {
1470 +               /* remove whiteout base */
1471 +               err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
1472 +               if (unlikely(err))
1473 +                       goto out;
1474 +
1475 +               if (!au_br_writable(mod->perm)) {
1476 +                       /* rw --> ro, file might be mmapped */
1477 +                       DiMustNoWaiters(root);
1478 +                       IiMustNoWaiters(root->d_inode);
1479 +                       di_write_unlock(root);
1480 +                       err = au_br_mod_files_ro(sb, bindex);
1481 +                       /* aufs_write_lock() calls ..._child() */
1482 +                       di_write_lock_child(root);
1483 +
1484 +                       if (unlikely(err)) {
1485 +                               rerr = -ENOMEM;
1486 +                               br->br_wbr = kmalloc(sizeof(*br->br_wbr),
1487 +                                                    GFP_NOFS);
1488 +                               if (br->br_wbr) {
1489 +                                       path.mnt = br->br_mnt;
1490 +                                       path.dentry = mod->h_root;
1491 +                                       rerr = au_wbr_init(br, sb, br->br_perm,
1492 +                                                          &path);
1493 +                               }
1494 +                               if (unlikely(rerr)) {
1495 +                                       AuIOErr("nested error %d (%d)\n",
1496 +                                               rerr, err);
1497 +                                       br->br_perm = mod->perm;
1498 +                               }
1499 +                       }
1500 +               }
1501 +       } else if (au_br_writable(mod->perm)) {
1502 +               /* ro --> rw */
1503 +               err = -ENOMEM;
1504 +               br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1505 +               if (br->br_wbr) {
1506 +                       path.mnt = br->br_mnt;
1507 +                       path.dentry = mod->h_root;
1508 +                       err = au_wbr_init(br, sb, mod->perm, &path);
1509 +                       if (unlikely(err)) {
1510 +                               kfree(br->br_wbr);
1511 +                               br->br_wbr = NULL;
1512 +                       }
1513 +               }
1514 +       }
1515 +
1516 +       if (!err) {
1517 +               *do_update |= need_sigen_inc(br->br_perm, mod->perm);
1518 +               br->br_perm = mod->perm;
1519 +       }
1520 +
1521 +out:
1522 +       return err;
1523 +}
1524 diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
1525 --- /usr/share/empty/fs/aufs/branch.h   1970-01-01 01:00:00.000000000 +0100
1526 +++ linux/fs/aufs/branch.h      2010-10-21 09:52:43.086957936 +0200
1527 @@ -0,0 +1,224 @@
1528 +/*
1529 + * Copyright (C) 2005-2010 Junjiro R. Okajima
1530 + *
1531 + * This program, aufs is free software; you can redistribute it and/or modify
1532 + * it under the terms of the GNU General Public License as published by
1533 + * the Free Software Foundation; either version 2 of the License, or
1534 + * (at your option) any later version.
1535 + *
1536 + * This program is distributed in the hope that it will be useful,
1537 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1538 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1539 + * GNU General Public License for more details.
1540 + *
1541 + * You should have received a copy of the GNU General Public License
1542 + * along with this program; if not, write to the Free Software
1543 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1544 + */
1545 +
1546 +/*
1547 + * branch filesystems and xino for them
1548 + */
1549 +
1550 +#ifndef __AUFS_BRANCH_H__
1551 +#define __AUFS_BRANCH_H__
1552 +
1553 +#ifdef __KERNEL__
1554 +
1555 +#include <linux/fs.h>
1556 +#include <linux/mount.h>
1557 +#include <linux/aufs_type.h>
1558 +#include "dynop.h"
1559 +#include "rwsem.h"
1560 +#include "super.h"
1561 +
1562 +/* ---------------------------------------------------------------------- */
1563 +
1564 +/* a xino file */
1565 +struct au_xino_file {
1566 +       struct file             *xi_file;
1567 +       struct mutex            xi_nondir_mtx;
1568 +
1569 +       /* todo: make xino files an array to support huge inode number */
1570 +
1571 +#ifdef CONFIG_DEBUG_FS
1572 +       struct dentry            *xi_dbgaufs;
1573 +#endif
1574 +};
1575 +
1576 +/* members for writable branch only */
1577 +enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
1578 +struct au_wbr {
1579 +       struct au_rwsem         wbr_wh_rwsem;
1580 +       struct dentry           *wbr_wh[AuBrWh_Last];
1581 +       atomic_t                wbr_wh_running;
1582 +#define wbr_whbase             wbr_wh[AuBrWh_BASE]     /* whiteout base */
1583 +#define wbr_plink              wbr_wh[AuBrWh_PLINK]    /* pseudo-link dir */
1584 +#define wbr_orph               wbr_wh[AuBrWh_ORPH]     /* dir for orphans */
1585 +
1586 +       /* mfs mode */
1587 +       unsigned long long      wbr_bytes;
1588 +};
1589 +
1590 +/* ext2 has 3 types of operations at least, ext3 has 4 */
1591 +#define AuBrDynOp (AuDyLast * 4)
1592 +
1593 +/* protected by superblock rwsem */
1594 +struct au_branch {
1595 +       struct au_xino_file     br_xino;
1596 +
1597 +       aufs_bindex_t           br_id;
1598 +
1599 +       int                     br_perm;
1600 +       struct vfsmount         *br_mnt;
1601 +       spinlock_t              br_dykey_lock;
1602 +       struct au_dykey         *br_dykey[AuBrDynOp];
1603 +       atomic_t                br_count;
1604 +
1605 +       struct au_wbr           *br_wbr;
1606 +
1607 +       /* xino truncation */
1608 +       blkcnt_t                br_xino_upper;  /* watermark in blocks */
1609 +       atomic_t                br_xino_running;
1610 +
1611 +#ifdef CONFIG_SYSFS
1612 +       /* an entry under sysfs per mount-point */
1613 +       char                    br_name[8];
1614 +       struct attribute        br_attr;
1615 +#endif
1616 +};
1617 +
1618 +/* ---------------------------------------------------------------------- */
1619 +
1620 +/* branch permission and attribute */
1621 +enum {
1622 +       AuBrPerm_RW,            /* writable, linkable wh */
1623 +       AuBrPerm_RO,            /* readonly, no wh */
1624 +       AuBrPerm_RR,            /* natively readonly, no wh */
1625 +
1626 +       AuBrPerm_RWNoLinkWH,    /* un-linkable whiteouts */
1627 +
1628 +       AuBrPerm_ROWH,          /* whiteout-able */
1629 +       AuBrPerm_RRWH,          /* whiteout-able */
1630 +
1631 +       AuBrPerm_Last
1632 +};
1633 +
1634 +static inline int au_br_writable(int brperm)
1635 +{
1636 +       return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1637 +}
1638 +
1639 +static inline int au_br_whable(int brperm)
1640 +{
1641 +       return brperm == AuBrPerm_RW
1642 +               || brperm == AuBrPerm_ROWH
1643 +               || brperm == AuBrPerm_RRWH;
1644 +}
1645 +
1646 +static inline int au_br_rdonly(struct au_branch *br)
1647 +{
1648 +       return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1649 +               || !au_br_writable(br->br_perm))
1650 +               ? -EROFS : 0;
1651 +}
1652 +
1653 +static inline int au_br_hnotifyable(int brperm __maybe_unused)
1654 +{
1655 +#ifdef CONFIG_AUFS_HNOTIFY
1656 +       return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1657 +#else
1658 +       return 0;
1659 +#endif
1660 +}
1661 +
1662 +/* ---------------------------------------------------------------------- */
1663 +
1664 +/* branch.c */
1665 +struct au_sbinfo;
1666 +void au_br_free(struct au_sbinfo *sinfo);
1667 +int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1668 +struct au_opt_add;
1669 +int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1670 +struct au_opt_del;
1671 +int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
1672 +struct au_opt_mod;
1673 +int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1674 +             int *do_update);
1675 +
1676 +/* xino.c */
1677 +static const loff_t au_loff_max = LLONG_MAX;
1678 +
1679 +int au_xib_trunc(struct super_block *sb);
1680 +ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1681 +                  loff_t *pos);
1682 +ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1683 +                   loff_t *pos);
1684 +struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
1685 +struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1686 +ino_t au_xino_new_ino(struct super_block *sb);
1687 +void au_xino_delete_inode(struct inode *inode, const int unlinked);
1688 +int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1689 +                 ino_t ino);
1690 +int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1691 +                ino_t *ino);
1692 +int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1693 +              struct file *base_file, int do_test);
1694 +int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1695 +
1696 +struct au_opt_xino;
1697 +int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1698 +void au_xino_clr(struct super_block *sb);
1699 +struct file *au_xino_def(struct super_block *sb);
1700 +int au_xino_path(struct seq_file *seq, struct file *file);
1701 +
1702 +/* ---------------------------------------------------------------------- */
1703 +
1704 +/* Superblock to branch */
1705 +static inline
1706 +aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1707 +{
1708 +       return au_sbr(sb, bindex)->br_id;
1709 +}
1710 +
1711 +static inline
1712 +struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1713 +{
1714 +       return au_sbr(sb, bindex)->br_mnt;
1715 +}
1716 +
1717 +static inline
1718 +struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1719 +{
1720 +       return au_sbr_mnt(sb, bindex)->mnt_sb;
1721 +}
1722 +
1723 +static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1724 +{
1725 +       atomic_dec_return(&au_sbr(sb, bindex)->br_count);
1726 +}
1727 +
1728 +static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1729 +{
1730 +       return au_sbr(sb, bindex)->br_perm;
1731 +}
1732 +
1733 +static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1734 +{
1735 +       return au_br_whable(au_sbr_perm(sb, bindex));
1736 +}
1737 +
1738 +/* ---------------------------------------------------------------------- */
1739 +
1740 +/*
1741 + * wbr_wh_read_lock, wbr_wh_write_lock
1742 + * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
1743 + */
1744 +AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
1745 +
1746 +#define WbrWhMustNoWaiters(wbr)        AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
1747 +#define WbrWhMustAnyLock(wbr)  AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
1748 +#define WbrWhMustWriteLock(wbr)        AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
1749 +
1750 +#endif /* __KERNEL__ */
1751 +#endif /* __AUFS_BRANCH_H__ */
1752 diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
1753 --- /usr/share/empty/fs/aufs/conf.mk    1970-01-01 01:00:00.000000000 +0100
1754 +++ linux/fs/aufs/conf.mk       2010-10-21 09:52:43.086957936 +0200
1755 @@ -0,0 +1,36 @@
1756 +
1757 +AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
1758 +
1759 +define AuConf
1760 +ifdef ${1}
1761 +AuConfStr += ${1}=${${1}}
1762 +endif
1763 +endef
1764 +
1765 +AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
1766 +       HNOTIFY HFSNOTIFY \
1767 +       EXPORT INO_T_64 \
1768 +       RDU \
1769 +       SP_IATTR \
1770 +       SHWH \
1771 +       BR_RAMFS \
1772 +       BR_FUSE POLL \
1773 +       BR_HFSPLUS \
1774 +       BDEV_LOOP \
1775 +       DEBUG MAGIC_SYSRQ
1776 +$(foreach i, ${AuConfAll}, \
1777 +       $(eval $(call AuConf,CONFIG_AUFS_${i})))
1778 +
1779 +AuConfName = ${obj}/conf.str
1780 +${AuConfName}.tmp: FORCE
1781 +       @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
1782 +${AuConfName}: ${AuConfName}.tmp
1783 +       @diff -q $< $@ > /dev/null 2>&1 || { \
1784 +       echo '  GEN    ' $@; \
1785 +       cp -p $< $@; \
1786 +       }
1787 +FORCE:
1788 +clean-files += ${AuConfName} ${AuConfName}.tmp
1789 +${obj}/sysfs.o: ${AuConfName}
1790 +
1791 +-include ${srctree}/${src}/conf_priv.mk
1792 diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
1793 --- /usr/share/empty/fs/aufs/cpup.c     1970-01-01 01:00:00.000000000 +0100
1794 +++ linux/fs/aufs/cpup.c        2010-10-21 09:52:43.086957936 +0200
1795 @@ -0,0 +1,1059 @@
1796 +/*
1797 + * Copyright (C) 2005-2010 Junjiro R. Okajima
1798 + *
1799 + * This program, aufs is free software; you can redistribute it and/or modify
1800 + * it under the terms of the GNU General Public License as published by
1801 + * the Free Software Foundation; either version 2 of the License, or
1802 + * (at your option) any later version.
1803 + *
1804 + * This program is distributed in the hope that it will be useful,
1805 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1806 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1807 + * GNU General Public License for more details.
1808 + *
1809 + * You should have received a copy of the GNU General Public License
1810 + * along with this program; if not, write to the Free Software
1811 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1812 + */
1813 +
1814 +/*
1815 + * copy-up functions, see wbr_policy.c for copy-down
1816 + */
1817 +
1818 +#include <linux/file.h>
1819 +#include <linux/fs_stack.h>
1820 +#include <linux/mm.h>
1821 +#include <linux/uaccess.h>
1822 +#include "aufs.h"
1823 +
1824 +void au_cpup_attr_flags(struct inode *dst, struct inode *src)
1825 +{
1826 +       const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
1827 +               | S_NOATIME | S_NOCMTIME;
1828 +
1829 +       dst->i_flags |= src->i_flags & ~mask;
1830 +       if (au_test_fs_notime(dst->i_sb))
1831 +               dst->i_flags |= S_NOATIME | S_NOCMTIME;
1832 +}
1833 +
1834 +void au_cpup_attr_timesizes(struct inode *inode)
1835 +{
1836 +       struct inode *h_inode;
1837 +
1838 +       h_inode = au_h_iptr(inode, au_ibstart(inode));
1839 +       fsstack_copy_attr_times(inode, h_inode);
1840 +       fsstack_copy_inode_size(inode, h_inode);
1841 +}
1842 +
1843 +void au_cpup_attr_nlink(struct inode *inode, int force)
1844 +{
1845 +       struct inode *h_inode;
1846 +       struct super_block *sb;
1847 +       aufs_bindex_t bindex, bend;
1848 +
1849 +       sb = inode->i_sb;
1850 +       bindex = au_ibstart(inode);
1851 +       h_inode = au_h_iptr(inode, bindex);
1852 +       if (!force
1853 +           && !S_ISDIR(h_inode->i_mode)
1854 +           && au_opt_test(au_mntflags(sb), PLINK)
1855 +           && au_plink_test(inode))
1856 +               return;
1857 +
1858 +       inode->i_nlink = h_inode->i_nlink;
1859 +
1860 +       /*
1861 +        * fewer nlink makes find(1) noisy, but larger nlink doesn't.
1862 +        * it may includes whplink directory.
1863 +        */
1864 +       if (S_ISDIR(h_inode->i_mode)) {
1865 +               bend = au_ibend(inode);
1866 +               for (bindex++; bindex <= bend; bindex++) {
1867 +                       h_inode = au_h_iptr(inode, bindex);
1868 +                       if (h_inode)
1869 +                               au_add_nlink(inode, h_inode);
1870 +               }
1871 +       }
1872 +}
1873 +
1874 +void au_cpup_attr_changeable(struct inode *inode)
1875 +{
1876 +       struct inode *h_inode;
1877 +
1878 +       h_inode = au_h_iptr(inode, au_ibstart(inode));
1879 +       inode->i_mode = h_inode->i_mode;
1880 +       inode->i_uid = h_inode->i_uid;
1881 +       inode->i_gid = h_inode->i_gid;
1882 +       au_cpup_attr_timesizes(inode);
1883 +       au_cpup_attr_flags(inode, h_inode);
1884 +}
1885 +
1886 +void au_cpup_igen(struct inode *inode, struct inode *h_inode)
1887 +{
1888 +       struct au_iinfo *iinfo = au_ii(inode);
1889 +
1890 +       IiMustWriteLock(inode);
1891 +
1892 +       iinfo->ii_higen = h_inode->i_generation;
1893 +       iinfo->ii_hsb1 = h_inode->i_sb;
1894 +}
1895 +
1896 +void au_cpup_attr_all(struct inode *inode, int force)
1897 +{
1898 +       struct inode *h_inode;
1899 +
1900 +       h_inode = au_h_iptr(inode, au_ibstart(inode));
1901 +       au_cpup_attr_changeable(inode);
1902 +       if (inode->i_nlink > 0)
1903 +               au_cpup_attr_nlink(inode, force);
1904 +       inode->i_rdev = h_inode->i_rdev;
1905 +       inode->i_blkbits = h_inode->i_blkbits;
1906 +       au_cpup_igen(inode, h_inode);
1907 +}
1908 +
1909 +/* ---------------------------------------------------------------------- */
1910 +
1911 +/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
1912 +
1913 +/* keep the timestamps of the parent dir when cpup */
1914 +void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
1915 +                   struct path *h_path)
1916 +{
1917 +       struct inode *h_inode;
1918 +
1919 +       dt->dt_dentry = dentry;
1920 +       dt->dt_h_path = *h_path;
1921 +       h_inode = h_path->dentry->d_inode;
1922 +       dt->dt_atime = h_inode->i_atime;
1923 +       dt->dt_mtime = h_inode->i_mtime;
1924 +       /* smp_mb(); */
1925 +}
1926 +
1927 +void au_dtime_revert(struct au_dtime *dt)
1928 +{
1929 +       struct iattr attr;
1930 +       int err;
1931 +
1932 +       attr.ia_atime = dt->dt_atime;
1933 +       attr.ia_mtime = dt->dt_mtime;
1934 +       attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
1935 +               | ATTR_ATIME | ATTR_ATIME_SET;
1936 +
1937 +       err = vfsub_notify_change(&dt->dt_h_path, &attr);
1938 +       if (unlikely(err))
1939 +               pr_warning("restoring timestamps failed(%d). ignored\n", err);
1940 +}
1941 +
1942 +/* ---------------------------------------------------------------------- */
1943 +
1944 +static noinline_for_stack
1945 +int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
1946 +{
1947 +       int err, sbits;
1948 +       struct iattr ia;
1949 +       struct path h_path;
1950 +       struct inode *h_isrc, *h_idst;
1951 +
1952 +       h_path.dentry = au_h_dptr(dst, bindex);
1953 +       h_idst = h_path.dentry->d_inode;
1954 +       h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
1955 +       h_isrc = h_src->d_inode;
1956 +       ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1957 +               | ATTR_ATIME | ATTR_MTIME
1958 +               | ATTR_ATIME_SET | ATTR_MTIME_SET;
1959 +       ia.ia_uid = h_isrc->i_uid;
1960 +       ia.ia_gid = h_isrc->i_gid;
1961 +       ia.ia_atime = h_isrc->i_atime;
1962 +       ia.ia_mtime = h_isrc->i_mtime;
1963 +       if (h_idst->i_mode != h_isrc->i_mode
1964 +           && !S_ISLNK(h_idst->i_mode)) {
1965 +               ia.ia_valid |= ATTR_MODE;
1966 +               ia.ia_mode = h_isrc->i_mode;
1967 +       }
1968 +       sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
1969 +       au_cpup_attr_flags(h_idst, h_isrc);
1970 +       err = vfsub_notify_change(&h_path, &ia);
1971 +
1972 +       /* is this nfs only? */
1973 +       if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
1974 +               ia.ia_valid = ATTR_FORCE | ATTR_MODE;
1975 +               ia.ia_mode = h_isrc->i_mode;
1976 +               err = vfsub_notify_change(&h_path, &ia);
1977 +       }
1978 +
1979 +       return err;
1980 +}
1981 +
1982 +/* ---------------------------------------------------------------------- */
1983 +
1984 +static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
1985 +                          char *buf, unsigned long blksize)
1986 +{
1987 +       int err;
1988 +       size_t sz, rbytes, wbytes;
1989 +       unsigned char all_zero;
1990 +       char *p, *zp;
1991 +       struct mutex *h_mtx;
1992 +       /* reduce stack usage */
1993 +       struct iattr *ia;
1994 +
1995 +       zp = page_address(ZERO_PAGE(0));
1996 +       if (unlikely(!zp))
1997 +               return -ENOMEM; /* possible? */
1998 +
1999 +       err = 0;
2000 +       all_zero = 0;
2001 +       while (len) {
2002 +               AuDbg("len %lld\n", len);
2003 +               sz = blksize;
2004 +               if (len < blksize)
2005 +                       sz = len;
2006 +
2007 +               rbytes = 0;
2008 +               /* todo: signal_pending? */
2009 +               while (!rbytes || err == -EAGAIN || err == -EINTR) {
2010 +                       rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
2011 +                       err = rbytes;
2012 +               }
2013 +               if (unlikely(err < 0))
2014 +                       break;
2015 +
2016 +               all_zero = 0;
2017 +               if (len >= rbytes && rbytes == blksize)
2018 +                       all_zero = !memcmp(buf, zp, rbytes);
2019 +               if (!all_zero) {
2020 +                       wbytes = rbytes;
2021 +                       p = buf;
2022 +                       while (wbytes) {
2023 +                               size_t b;
2024 +
2025 +                               b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
2026 +                               err = b;
2027 +                               /* todo: signal_pending? */
2028 +                               if (unlikely(err == -EAGAIN || err == -EINTR))
2029 +                                       continue;
2030 +                               if (unlikely(err < 0))
2031 +                                       break;
2032 +                               wbytes -= b;
2033 +                               p += b;
2034 +                       }
2035 +               } else {
2036 +                       loff_t res;
2037 +
2038 +                       AuLabel(hole);
2039 +                       res = vfsub_llseek(dst, rbytes, SEEK_CUR);
2040 +                       err = res;
2041 +                       if (unlikely(res < 0))
2042 +                               break;
2043 +               }
2044 +               len -= rbytes;
2045 +               err = 0;
2046 +       }
2047 +
2048 +       /* the last block may be a hole */
2049 +       if (!err && all_zero) {
2050 +               AuLabel(last hole);
2051 +
2052 +               err = 1;
2053 +               if (au_test_nfs(dst->f_dentry->d_sb)) {
2054 +                       /* nfs requires this step to make last hole */
2055 +                       /* is this only nfs? */
2056 +                       do {
2057 +                               /* todo: signal_pending? */
2058 +                               err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
2059 +                       } while (err == -EAGAIN || err == -EINTR);
2060 +                       if (err == 1)
2061 +                               dst->f_pos--;
2062 +               }
2063 +
2064 +               if (err == 1) {
2065 +                       ia = (void *)buf;
2066 +                       ia->ia_size = dst->f_pos;
2067 +                       ia->ia_valid = ATTR_SIZE | ATTR_FILE;
2068 +                       ia->ia_file = dst;
2069 +                       h_mtx = &dst->f_dentry->d_inode->i_mutex;
2070 +                       mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
2071 +                       err = vfsub_notify_change(&dst->f_path, ia);
2072 +                       mutex_unlock(h_mtx);
2073 +               }
2074 +       }
2075 +
2076 +       return err;
2077 +}
2078 +
2079 +int au_copy_file(struct file *dst, struct file *src, loff_t len)
2080 +{
2081 +       int err;
2082 +       unsigned long blksize;
2083 +       unsigned char do_kfree;
2084 +       char *buf;
2085 +
2086 +       err = -ENOMEM;
2087 +       blksize = dst->f_dentry->d_sb->s_blocksize;
2088 +       if (!blksize || PAGE_SIZE < blksize)
2089 +               blksize = PAGE_SIZE;
2090 +       AuDbg("blksize %lu\n", blksize);
2091 +       do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
2092 +       if (do_kfree)
2093 +               buf = kmalloc(blksize, GFP_NOFS);
2094 +       else
2095 +               buf = (void *)__get_free_page(GFP_NOFS);
2096 +       if (unlikely(!buf))
2097 +               goto out;
2098 +
2099 +       if (len > (1 << 22))
2100 +               AuDbg("copying a large file %lld\n", (long long)len);
2101 +
2102 +       src->f_pos = 0;
2103 +       dst->f_pos = 0;
2104 +       err = au_do_copy_file(dst, src, len, buf, blksize);
2105 +       if (do_kfree)
2106 +               kfree(buf);
2107 +       else
2108 +               free_page((unsigned long)buf);
2109 +
2110 +out:
2111 +       return err;
2112 +}
2113 +
2114 +/*
2115 + * to support a sparse file which is opened with O_APPEND,
2116 + * we need to close the file.
2117 + */
2118 +static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
2119 +                        aufs_bindex_t bsrc, loff_t len)
2120 +{
2121 +       int err, i;
2122 +       enum { SRC, DST };
2123 +       struct {
2124 +               aufs_bindex_t bindex;
2125 +               unsigned int flags;
2126 +               struct dentry *dentry;
2127 +               struct file *file;
2128 +               void *label, *label_file;
2129 +       } *f, file[] = {
2130 +               {
2131 +                       .bindex = bsrc,
2132 +                       .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
2133 +                       .file = NULL,
2134 +                       .label = &&out,
2135 +                       .label_file = &&out_src
2136 +               },
2137 +               {
2138 +                       .bindex = bdst,
2139 +                       .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
2140 +                       .file = NULL,
2141 +                       .label = &&out_src,
2142 +                       .label_file = &&out_dst
2143 +               }
2144 +       };
2145 +       struct super_block *sb;
2146 +
2147 +       /* bsrc branch can be ro/rw. */
2148 +       sb = dentry->d_sb;
2149 +       f = file;
2150 +       for (i = 0; i < 2; i++, f++) {
2151 +               f->dentry = au_h_dptr(dentry, f->bindex);
2152 +               f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
2153 +               err = PTR_ERR(f->file);
2154 +               if (IS_ERR(f->file))
2155 +                       goto *f->label;
2156 +               err = -EINVAL;
2157 +               if (unlikely(!f->file->f_op))
2158 +                       goto *f->label_file;
2159 +       }
2160 +
2161 +       /* try stopping to update while we copyup */
2162 +       IMustLock(file[SRC].dentry->d_inode);
2163 +       err = au_copy_file(file[DST].file, file[SRC].file, len);
2164 +
2165 +out_dst:
2166 +       fput(file[DST].file);
2167 +       au_sbr_put(sb, file[DST].bindex);
2168 +out_src:
2169 +       fput(file[SRC].file);
2170 +       au_sbr_put(sb, file[SRC].bindex);
2171 +out:
2172 +       return err;
2173 +}
2174 +
2175 +static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
2176 +                             aufs_bindex_t bsrc, loff_t len,
2177 +                             struct inode *h_dir, struct path *h_path)
2178 +{
2179 +       int err, rerr;
2180 +       loff_t l;
2181 +
2182 +       err = 0;
2183 +       l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
2184 +       if (len == -1 || l < len)
2185 +               len = l;
2186 +       if (len)
2187 +               err = au_cp_regular(dentry, bdst, bsrc, len);
2188 +       if (!err)
2189 +               goto out; /* success */
2190 +
2191 +       rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
2192 +       if (rerr) {
2193 +               AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
2194 +                       AuDLNPair(h_path->dentry), err, rerr);
2195 +               err = -EIO;
2196 +       }
2197 +
2198 +out:
2199 +       return err;
2200 +}
2201 +
2202 +static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
2203 +                             struct inode *h_dir)
2204 +{
2205 +       int err, symlen;
2206 +       mm_segment_t old_fs;
2207 +       union {
2208 +               char *k;
2209 +               char __user *u;
2210 +       } sym;
2211 +
2212 +       err = -ENOSYS;
2213 +       if (unlikely(!h_src->d_inode->i_op->readlink))
2214 +               goto out;
2215 +
2216 +       err = -ENOMEM;
2217 +       sym.k = __getname_gfp(GFP_NOFS);
2218 +       if (unlikely(!sym.k))
2219 +               goto out;
2220 +
2221 +       old_fs = get_fs();
2222 +       set_fs(KERNEL_DS);
2223 +       symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
2224 +       err = symlen;
2225 +       set_fs(old_fs);
2226 +
2227 +       if (symlen > 0) {
2228 +               sym.k[symlen] = 0;
2229 +               err = vfsub_symlink(h_dir, h_path, sym.k);
2230 +       }
2231 +       __putname(sym.k);
2232 +
2233 +out:
2234 +       return err;
2235 +}
2236 +
2237 +/* return with the lower dst inode is locked */
2238 +static noinline_for_stack
2239 +int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
2240 +              aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2241 +              struct dentry *dst_parent)
2242 +{
2243 +       int err;
2244 +       umode_t mode;
2245 +       unsigned int mnt_flags;
2246 +       unsigned char isdir;
2247 +       const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
2248 +       struct au_dtime dt;
2249 +       struct path h_path;
2250 +       struct dentry *h_src, *h_dst, *h_parent;
2251 +       struct inode *h_inode, *h_dir;
2252 +       struct super_block *sb;
2253 +
2254 +       /* bsrc branch can be ro/rw. */
2255 +       h_src = au_h_dptr(dentry, bsrc);
2256 +       h_inode = h_src->d_inode;
2257 +       AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
2258 +
2259 +       /* try stopping to be referenced while we are creating */
2260 +       h_dst = au_h_dptr(dentry, bdst);
2261 +       h_parent = h_dst->d_parent; /* dir inode is locked */
2262 +       h_dir = h_parent->d_inode;
2263 +       IMustLock(h_dir);
2264 +       AuDebugOn(h_parent != h_dst->d_parent);
2265 +
2266 +       sb = dentry->d_sb;
2267 +       h_path.mnt = au_sbr_mnt(sb, bdst);
2268 +       if (do_dt) {
2269 +               h_path.dentry = h_parent;
2270 +               au_dtime_store(&dt, dst_parent, &h_path);
2271 +       }
2272 +       h_path.dentry = h_dst;
2273 +
2274 +       isdir = 0;
2275 +       mode = h_inode->i_mode;
2276 +       switch (mode & S_IFMT) {
2277 +       case S_IFREG:
2278 +               /* try stopping to update while we are referencing */
2279 +               IMustLock(h_inode);
2280 +               err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
2281 +               if (!err)
2282 +                       err = au_do_cpup_regular
2283 +                               (dentry, bdst, bsrc, len,
2284 +                                au_h_iptr(dst_parent->d_inode, bdst), &h_path);
2285 +               break;
2286 +       case S_IFDIR:
2287 +               isdir = 1;
2288 +               err = vfsub_mkdir(h_dir, &h_path, mode);
2289 +               if (!err) {
2290 +                       /*
2291 +                        * strange behaviour from the users view,
2292 +                        * particularry setattr case
2293 +                        */
2294 +                       if (au_ibstart(dst_parent->d_inode) == bdst)
2295 +                               au_cpup_attr_nlink(dst_parent->d_inode,
2296 +                                                  /*force*/1);
2297 +                       au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
2298 +               }
2299 +               break;
2300 +       case S_IFLNK:
2301 +               err = au_do_cpup_symlink(&h_path, h_src, h_dir);
2302 +               break;
2303 +       case S_IFCHR:
2304 +       case S_IFBLK:
2305 +               AuDebugOn(!capable(CAP_MKNOD));
2306 +               /*FALLTHROUGH*/
2307 +       case S_IFIFO:
2308 +       case S_IFSOCK:
2309 +               err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
2310 +               break;
2311 +       default:
2312 +               AuIOErr("Unknown inode type 0%o\n", mode);
2313 +               err = -EIO;
2314 +       }
2315 +
2316 +       mnt_flags = au_mntflags(sb);
2317 +       if (!au_opt_test(mnt_flags, UDBA_NONE)
2318 +           && !isdir
2319 +           && au_opt_test(mnt_flags, XINO)
2320 +           && h_inode->i_nlink == 1
2321 +           /* todo: unnecessary? */
2322 +           /* && dentry->d_inode->i_nlink == 1 */
2323 +           && bdst < bsrc
2324 +           && !au_ftest_cpup(flags, KEEPLINO))
2325 +               au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
2326 +               /* ignore this error */
2327 +
2328 +       if (do_dt)
2329 +               au_dtime_revert(&dt);
2330 +       return err;
2331 +}
2332 +
2333 +/*
2334 + * copyup the @dentry from @bsrc to @bdst.
2335 + * the caller must set the both of lower dentries.
2336 + * @len is for truncating when it is -1 copyup the entire file.
2337 + * in link/rename cases, @dst_parent may be different from the real one.
2338 + */
2339 +static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2340 +                         aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2341 +                         struct dentry *dst_parent)
2342 +{
2343 +       int err, rerr;
2344 +       aufs_bindex_t old_ibstart;
2345 +       unsigned char isdir, plink;
2346 +       struct au_dtime dt;
2347 +       struct path h_path;
2348 +       struct dentry *h_src, *h_dst, *h_parent;
2349 +       struct inode *dst_inode, *h_dir, *inode;
2350 +       struct super_block *sb;
2351 +
2352 +       AuDebugOn(bsrc <= bdst);
2353 +
2354 +       sb = dentry->d_sb;
2355 +       h_path.mnt = au_sbr_mnt(sb, bdst);
2356 +       h_dst = au_h_dptr(dentry, bdst);
2357 +       h_parent = h_dst->d_parent; /* dir inode is locked */
2358 +       h_dir = h_parent->d_inode;
2359 +       IMustLock(h_dir);
2360 +
2361 +       h_src = au_h_dptr(dentry, bsrc);
2362 +       inode = dentry->d_inode;
2363 +
2364 +       if (!dst_parent)
2365 +               dst_parent = dget_parent(dentry);
2366 +       else
2367 +               dget(dst_parent);
2368 +
2369 +       plink = !!au_opt_test(au_mntflags(sb), PLINK);
2370 +       dst_inode = au_h_iptr(inode, bdst);
2371 +       if (dst_inode) {
2372 +               if (unlikely(!plink)) {
2373 +                       err = -EIO;
2374 +                       AuIOErr("i%lu exists on a upper branch "
2375 +                               "but plink is disabled\n", inode->i_ino);
2376 +                       goto out;
2377 +               }
2378 +
2379 +               if (dst_inode->i_nlink) {
2380 +                       const int do_dt = au_ftest_cpup(flags, DTIME);
2381 +
2382 +                       h_src = au_plink_lkup(inode, bdst);
2383 +                       err = PTR_ERR(h_src);
2384 +                       if (IS_ERR(h_src))
2385 +                               goto out;
2386 +                       if (unlikely(!h_src->d_inode)) {
2387 +                               err = -EIO;
2388 +                               AuIOErr("i%lu exists on a upper branch "
2389 +                                       "but plink is broken\n", inode->i_ino);
2390 +                               dput(h_src);
2391 +                               goto out;
2392 +                       }
2393 +
2394 +                       if (do_dt) {
2395 +                               h_path.dentry = h_parent;
2396 +                               au_dtime_store(&dt, dst_parent, &h_path);
2397 +                       }
2398 +                       h_path.dentry = h_dst;
2399 +                       err = vfsub_link(h_src, h_dir, &h_path);
2400 +                       if (do_dt)
2401 +                               au_dtime_revert(&dt);
2402 +                       dput(h_src);
2403 +                       goto out;
2404 +               } else
2405 +                       /* todo: cpup_wh_file? */
2406 +                       /* udba work */
2407 +                       au_update_ibrange(inode, /*do_put_zero*/1);
2408 +       }
2409 +
2410 +       old_ibstart = au_ibstart(inode);
2411 +       err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
2412 +       if (unlikely(err))
2413 +               goto out;
2414 +       dst_inode = h_dst->d_inode;
2415 +       mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
2416 +
2417 +       err = cpup_iattr(dentry, bdst, h_src);
2418 +       isdir = S_ISDIR(dst_inode->i_mode);
2419 +       if (!err) {
2420 +               if (bdst < old_ibstart) {
2421 +                       if (S_ISREG(inode->i_mode)) {
2422 +                               err = au_dy_iaop(inode, bdst, dst_inode);
2423 +                               if (unlikely(err))
2424 +                                       goto out_rev;
2425 +                       }
2426 +                       au_set_ibstart(inode, bdst);
2427 +               }
2428 +               au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
2429 +                             au_hi_flags(inode, isdir));
2430 +               mutex_unlock(&dst_inode->i_mutex);
2431 +               if (!isdir
2432 +                   && h_src->d_inode->i_nlink > 1
2433 +                   && plink)
2434 +                       au_plink_append(inode, bdst, h_dst);
2435 +               goto out; /* success */
2436 +       }
2437 +
2438 +       /* revert */
2439 +out_rev:
2440 +       h_path.dentry = h_parent;
2441 +       mutex_unlock(&dst_inode->i_mutex);
2442 +       au_dtime_store(&dt, dst_parent, &h_path);
2443 +       h_path.dentry = h_dst;
2444 +       if (!isdir)
2445 +               rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
2446 +       else
2447 +               rerr = vfsub_rmdir(h_dir, &h_path);
2448 +       au_dtime_revert(&dt);
2449 +       if (rerr) {
2450 +               AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
2451 +               err = -EIO;
2452 +       }
2453 +
2454 +out:
2455 +       dput(dst_parent);
2456 +       return err;
2457 +}
2458 +
2459 +struct au_cpup_single_args {
2460 +       int *errp;
2461 +       struct dentry *dentry;
2462 +       aufs_bindex_t bdst, bsrc;
2463 +       loff_t len;
2464 +       unsigned int flags;
2465 +       struct dentry *dst_parent;
2466 +};
2467 +
2468 +static void au_call_cpup_single(void *args)
2469 +{
2470 +       struct au_cpup_single_args *a = args;
2471 +       *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
2472 +                                 a->flags, a->dst_parent);
2473 +}
2474 +
2475 +int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2476 +                      aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2477 +                      struct dentry *dst_parent)
2478 +{
2479 +       int err, wkq_err;
2480 +       umode_t mode;
2481 +       struct dentry *h_dentry;
2482 +
2483 +       h_dentry = au_h_dptr(dentry, bsrc);
2484 +       mode = h_dentry->d_inode->i_mode & S_IFMT;
2485 +       if ((mode != S_IFCHR && mode != S_IFBLK)
2486 +           || capable(CAP_MKNOD))
2487 +               err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2488 +                                    dst_parent);
2489 +       else {
2490 +               struct au_cpup_single_args args = {
2491 +                       .errp           = &err,
2492 +                       .dentry         = dentry,
2493 +                       .bdst           = bdst,
2494 +                       .bsrc           = bsrc,
2495 +                       .len            = len,
2496 +                       .flags          = flags,
2497 +                       .dst_parent     = dst_parent
2498 +               };
2499 +               wkq_err = au_wkq_wait(au_call_cpup_single, &args);
2500 +               if (unlikely(wkq_err))
2501 +                       err = wkq_err;
2502 +       }
2503 +
2504 +       return err;
2505 +}
2506 +
2507 +/*
2508 + * copyup the @dentry from the first active lower branch to @bdst,
2509 + * using au_cpup_single().
2510 + */
2511 +static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2512 +                         unsigned int flags)
2513 +{
2514 +       int err;
2515 +       aufs_bindex_t bsrc, bend;
2516 +
2517 +       bend = au_dbend(dentry);
2518 +       for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2519 +               if (au_h_dptr(dentry, bsrc))
2520 +                       break;
2521 +
2522 +       err = au_lkup_neg(dentry, bdst);
2523 +       if (!err) {
2524 +               err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
2525 +               if (!err)
2526 +                       return 0; /* success */
2527 +
2528 +               /* revert */
2529 +               au_set_h_dptr(dentry, bdst, NULL);
2530 +               au_set_dbstart(dentry, bsrc);
2531 +       }
2532 +
2533 +       return err;
2534 +}
2535 +
2536 +struct au_cpup_simple_args {
2537 +       int *errp;
2538 +       struct dentry *dentry;
2539 +       aufs_bindex_t bdst;
2540 +       loff_t len;
2541 +       unsigned int flags;
2542 +};
2543 +
2544 +static void au_call_cpup_simple(void *args)
2545 +{
2546 +       struct au_cpup_simple_args *a = args;
2547 +       *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
2548 +}
2549 +
2550 +int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2551 +                      unsigned int flags)
2552 +{
2553 +       int err, wkq_err;
2554 +       unsigned char do_sio;
2555 +       struct dentry *parent;
2556 +       struct inode *h_dir;
2557 +
2558 +       parent = dget_parent(dentry);
2559 +       h_dir = au_h_iptr(parent->d_inode, bdst);
2560 +       do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
2561 +       if (!do_sio) {
2562 +               /*
2563 +                * testing CAP_MKNOD is for generic fs,
2564 +                * but CAP_FSETID is for xfs only, currently.
2565 +                */
2566 +               umode_t mode = dentry->d_inode->i_mode;
2567 +               do_sio = (((mode & (S_IFCHR | S_IFBLK))
2568 +                          && !capable(CAP_MKNOD))
2569 +                         || ((mode & (S_ISUID | S_ISGID))
2570 +                             && !capable(CAP_FSETID)));
2571 +       }
2572 +       if (!do_sio)
2573 +               err = au_cpup_simple(dentry, bdst, len, flags);
2574 +       else {
2575 +               struct au_cpup_simple_args args = {
2576 +                       .errp           = &err,
2577 +                       .dentry         = dentry,
2578 +                       .bdst           = bdst,
2579 +                       .len            = len,
2580 +                       .flags          = flags
2581 +               };
2582 +               wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
2583 +               if (unlikely(wkq_err))
2584 +                       err = wkq_err;
2585 +       }
2586 +
2587 +       dput(parent);
2588 +       return err;
2589 +}
2590 +
2591 +/* ---------------------------------------------------------------------- */
2592 +
2593 +/*
2594 + * copyup the deleted file for writing.
2595 + */
2596 +static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2597 +                        struct dentry *wh_dentry, struct file *file,
2598 +                        loff_t len)
2599 +{
2600 +       int err;
2601 +       aufs_bindex_t bstart;
2602 +       struct au_dinfo *dinfo;
2603 +       struct dentry *h_d_dst, *h_d_start;
2604 +       struct au_hdentry *hdp;
2605 +
2606 +       dinfo = au_di(dentry);
2607 +       AuRwMustWriteLock(&dinfo->di_rwsem);
2608 +
2609 +       bstart = dinfo->di_bstart;
2610 +       hdp = dinfo->di_hdentry;
2611 +       h_d_dst = hdp[0 + bdst].hd_dentry;
2612 +       dinfo->di_bstart = bdst;
2613 +       hdp[0 + bdst].hd_dentry = wh_dentry;
2614 +       h_d_start = hdp[0 + bstart].hd_dentry;
2615 +       if (file)
2616 +               hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
2617 +       err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2618 +                            /*h_parent*/NULL);
2619 +       if (!err && file) {
2620 +               err = au_reopen_nondir(file);
2621 +               hdp[0 + bstart].hd_dentry = h_d_start;
2622 +       }
2623 +       hdp[0 + bdst].hd_dentry = h_d_dst;
2624 +       dinfo->di_bstart = bstart;
2625 +
2626 +       return err;
2627 +}
2628 +
2629 +static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2630 +                     struct file *file)
2631 +{
2632 +       int err;
2633 +       struct au_dtime dt;
2634 +       struct dentry *parent, *h_parent, *wh_dentry;
2635 +       struct au_branch *br;
2636 +       struct path h_path;
2637 +
2638 +       br = au_sbr(dentry->d_sb, bdst);
2639 +       parent = dget_parent(dentry);
2640 +       h_parent = au_h_dptr(parent, bdst);
2641 +       wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
2642 +       err = PTR_ERR(wh_dentry);
2643 +       if (IS_ERR(wh_dentry))
2644 +               goto out;
2645 +
2646 +       h_path.dentry = h_parent;
2647 +       h_path.mnt = br->br_mnt;
2648 +       au_dtime_store(&dt, parent, &h_path);
2649 +       err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
2650 +       if (unlikely(err))
2651 +               goto out_wh;
2652 +
2653 +       dget(wh_dentry);
2654 +       h_path.dentry = wh_dentry;
2655 +       if (!S_ISDIR(wh_dentry->d_inode->i_mode))
2656 +               err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
2657 +       else
2658 +               err = vfsub_rmdir(h_parent->d_inode, &h_path);
2659 +       if (unlikely(err)) {
2660 +               AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2661 +                       AuDLNPair(wh_dentry), err);
2662 +               err = -EIO;
2663 +       }
2664 +       au_dtime_revert(&dt);
2665 +       au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2666 +
2667 +out_wh:
2668 +       dput(wh_dentry);
2669 +out:
2670 +       dput(parent);
2671 +       return err;
2672 +}
2673 +
2674 +struct au_cpup_wh_args {
2675 +       int *errp;
2676 +       struct dentry *dentry;
2677 +       aufs_bindex_t bdst;
2678 +       loff_t len;
2679 +       struct file *file;
2680 +};
2681 +
2682 +static void au_call_cpup_wh(void *args)
2683 +{
2684 +       struct au_cpup_wh_args *a = args;
2685 +       *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
2686 +}
2687 +
2688 +int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2689 +                  struct file *file)
2690 +{
2691 +       int err, wkq_err;
2692 +       struct dentry *parent, *h_orph, *h_parent, *h_dentry;
2693 +       struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
2694 +       struct au_wbr *wbr;
2695 +
2696 +       parent = dget_parent(dentry);
2697 +       dir = parent->d_inode;
2698 +       h_orph = NULL;
2699 +       h_parent = NULL;
2700 +       h_dir = au_igrab(au_h_iptr(dir, bdst));
2701 +       h_tmpdir = h_dir;
2702 +       if (!h_dir->i_nlink) {
2703 +               wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
2704 +               h_orph = wbr->wbr_orph;
2705 +
2706 +               h_parent = dget(au_h_dptr(parent, bdst));
2707 +               au_set_h_dptr(parent, bdst, dget(h_orph));
2708 +               h_tmpdir = h_orph->d_inode;
2709 +               au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
2710 +
2711 +               /* this temporary unlock is safe */
2712 +               if (file)
2713 +                       h_dentry = au_hf_top(file)->f_dentry;
2714 +               else
2715 +                       h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
2716 +               h_inode = h_dentry->d_inode;
2717 +               IMustLock(h_inode);
2718 +               mutex_unlock(&h_inode->i_mutex);
2719 +               mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
2720 +               mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
2721 +               /* todo: au_h_open_pre()? */
2722 +       }
2723 +
2724 +       if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
2725 +               err = au_cpup_wh(dentry, bdst, len, file);
2726 +       else {
2727 +               struct au_cpup_wh_args args = {
2728 +                       .errp   = &err,
2729 +                       .dentry = dentry,
2730 +                       .bdst   = bdst,
2731 +                       .len    = len,
2732 +                       .file   = file
2733 +               };
2734 +               wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
2735 +               if (unlikely(wkq_err))
2736 +                       err = wkq_err;
2737 +       }
2738 +
2739 +       if (h_orph) {
2740 +               mutex_unlock(&h_tmpdir->i_mutex);
2741 +               /* todo: au_h_open_post()? */
2742 +               au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
2743 +               au_set_h_dptr(parent, bdst, h_parent);
2744 +       }
2745 +       iput(h_dir);
2746 +       dput(parent);
2747 +
2748 +       return err;
2749 +}
2750 +
2751 +/* ---------------------------------------------------------------------- */
2752 +
2753 +/*
2754 + * generic routine for both of copy-up and copy-down.
2755 + */
2756 +/* cf. revalidate function in file.c */
2757 +int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2758 +              int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2759 +                        struct dentry *h_parent, void *arg),
2760 +              void *arg)
2761 +{
2762 +       int err;
2763 +       struct au_pin pin;
2764 +       struct dentry *d, *parent, *h_parent, *real_parent;
2765 +
2766 +       err = 0;
2767 +       parent = dget_parent(dentry);
2768 +       if (IS_ROOT(parent))
2769 +               goto out;
2770 +
2771 +       au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
2772 +                   au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
2773 +
2774 +       /* do not use au_dpage */
2775 +       real_parent = parent;
2776 +       while (1) {
2777 +               dput(parent);
2778 +               parent = dget_parent(dentry);
2779 +               h_parent = au_h_dptr(parent, bdst);
2780 +               if (h_parent)
2781 +                       goto out; /* success */
2782 +
2783 +               /* find top dir which is necessary to cpup */
2784 +               do {
2785 +                       d = parent;
2786 +                       dput(parent);
2787 +                       parent = dget_parent(d);
2788 +                       di_read_lock_parent3(parent, !AuLock_IR);
2789 +                       h_parent = au_h_dptr(parent, bdst);
2790 +                       di_read_unlock(parent, !AuLock_IR);
2791 +               } while (!h_parent);
2792 +
2793 +               if (d != real_parent)
2794 +                       di_write_lock_child3(d);
2795 +
2796 +               /* somebody else might create while we were sleeping */
2797 +               if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
2798 +                       if (au_h_dptr(d, bdst))
2799 +                               au_update_dbstart(d);
2800 +
2801 +                       au_pin_set_dentry(&pin, d);
2802 +                       err = au_do_pin(&pin);
2803 +                       if (!err) {
2804 +                               err = cp(d, bdst, h_parent, arg);
2805 +                               au_unpin(&pin);
2806 +                       }
2807 +               }
2808 +
2809 +               if (d != real_parent)
2810 +                       di_write_unlock(d);
2811 +               if (unlikely(err))
2812 +                       break;
2813 +       }
2814 +
2815 +out:
2816 +       dput(parent);
2817 +       return err;
2818 +}
2819 +
2820 +static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
2821 +                      struct dentry *h_parent __maybe_unused ,
2822 +                      void *arg __maybe_unused)
2823 +{
2824 +       return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
2825 +}
2826 +
2827 +int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2828 +{
2829 +       return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
2830 +}
2831 +
2832 +int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2833 +{
2834 +       int err;
2835 +       struct dentry *parent;
2836 +       struct inode *dir;
2837 +
2838 +       parent = dget_parent(dentry);
2839 +       dir = parent->d_inode;
2840 +       err = 0;
2841 +       if (au_h_iptr(dir, bdst))
2842 +               goto out;
2843 +
2844 +       di_read_unlock(parent, AuLock_IR);
2845 +       di_write_lock_parent(parent);
2846 +       /* someone else might change our inode while we were sleeping */
2847 +       if (!au_h_iptr(dir, bdst))
2848 +               err = au_cpup_dirs(dentry, bdst);
2849 +       di_downgrade_lock(parent, AuLock_IR);
2850 +
2851 +out:
2852 +       dput(parent);
2853 +       return err;
2854 +}
2855 diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
2856 --- /usr/share/empty/fs/aufs/cpup.h     1970-01-01 01:00:00.000000000 +0100
2857 +++ linux/fs/aufs/cpup.h        2010-10-21 09:52:43.086957936 +0200
2858 @@ -0,0 +1,81 @@
2859 +/*
2860 + * Copyright (C) 2005-2010 Junjiro R. Okajima
2861 + *
2862 + * This program, aufs is free software; you can redistribute it and/or modify
2863 + * it under the terms of the GNU General Public License as published by
2864 + * the Free Software Foundation; either version 2 of the License, or
2865 + * (at your option) any later version.
2866 + *
2867 + * This program is distributed in the hope that it will be useful,
2868 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2869 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2870 + * GNU General Public License for more details.
2871 + *
2872 + * You should have received a copy of the GNU General Public License
2873 + * along with this program; if not, write to the Free Software
2874 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2875 + */
2876 +
2877 +/*
2878 + * copy-up/down functions
2879 + */
2880 +
2881 +#ifndef __AUFS_CPUP_H__
2882 +#define __AUFS_CPUP_H__
2883 +
2884 +#ifdef __KERNEL__
2885 +
2886 +#include <linux/path.h>
2887 +#include <linux/time.h>
2888 +#include <linux/aufs_type.h>
2889 +
2890 +struct inode;
2891 +struct file;
2892 +
2893 +void au_cpup_attr_flags(struct inode *dst, struct inode *src);
2894 +void au_cpup_attr_timesizes(struct inode *inode);
2895 +void au_cpup_attr_nlink(struct inode *inode, int force);
2896 +void au_cpup_attr_changeable(struct inode *inode);
2897 +void au_cpup_igen(struct inode *inode, struct inode *h_inode);
2898 +void au_cpup_attr_all(struct inode *inode, int force);
2899 +
2900 +/* ---------------------------------------------------------------------- */
2901 +
2902 +/* cpup flags */
2903 +#define AuCpup_DTIME   1               /* do dtime_store/revert */
2904 +#define AuCpup_KEEPLINO        (1 << 1)        /* do not clear the lower xino,
2905 +                                          for link(2) */
2906 +#define au_ftest_cpup(flags, name)     ((flags) & AuCpup_##name)
2907 +#define au_fset_cpup(flags, name)      { (flags) |= AuCpup_##name; }
2908 +#define au_fclr_cpup(flags, name)      { (flags) &= ~AuCpup_##name; }
2909 +
2910 +int au_copy_file(struct file *dst, struct file *src, loff_t len);
2911 +int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2912 +                      aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2913 +                      struct dentry *dst_parent);
2914 +int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2915 +                      unsigned int flags);
2916 +int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2917 +                  struct file *file);
2918 +
2919 +int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2920 +              int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2921 +                        struct dentry *h_parent, void *arg),
2922 +              void *arg);
2923 +int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2924 +int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2925 +
2926 +/* ---------------------------------------------------------------------- */
2927 +
2928 +/* keep timestamps when copyup */
2929 +struct au_dtime {
2930 +       struct dentry *dt_dentry;
2931 +       struct path dt_h_path;
2932 +       struct timespec dt_atime, dt_mtime;
2933 +};
2934 +void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
2935 +                   struct path *h_path);
2936 +void au_dtime_revert(struct au_dtime *dt);
2937 +
2938 +#endif /* __KERNEL__ */
2939 +#endif /* __AUFS_CPUP_H__ */
2940 diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
2941 --- /usr/share/empty/fs/aufs/dbgaufs.c  1970-01-01 01:00:00.000000000 +0100
2942 +++ linux/fs/aufs/dbgaufs.c     2010-10-21 09:52:43.086957936 +0200
2943 @@ -0,0 +1,334 @@
2944 +/*
2945 + * Copyright (C) 2005-2010 Junjiro R. Okajima
2946 + *
2947 + * This program, aufs is free software; you can redistribute it and/or modify
2948 + * it under the terms of the GNU General Public License as published by
2949 + * the Free Software Foundation; either version 2 of the License, or
2950 + * (at your option) any later version.
2951 + *
2952 + * This program is distributed in the hope that it will be useful,
2953 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2954 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2955 + * GNU General Public License for more details.
2956 + *
2957 + * You should have received a copy of the GNU General Public License
2958 + * along with this program; if not, write to the Free Software
2959 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2960 + */
2961 +
2962 +/*
2963 + * debugfs interface
2964 + */
2965 +
2966 +#include <linux/debugfs.h>
2967 +#include "aufs.h"
2968 +
2969 +#ifndef CONFIG_SYSFS
2970 +#error DEBUG_FS depends upon SYSFS
2971 +#endif
2972 +
2973 +static struct dentry *dbgaufs;
2974 +static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
2975 +
2976 +/* 20 is max digits length of ulong 64 */
2977 +struct dbgaufs_arg {
2978 +       int n;
2979 +       char a[20 * 4];
2980 +};
2981 +
2982 +/*
2983 + * common function for all XINO files
2984 + */
2985 +static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
2986 +                             struct file *file)
2987 +{
2988 +       kfree(file->private_data);
2989 +       return 0;
2990 +}
2991 +
2992 +static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
2993 +{
2994 +       int err;
2995 +       struct kstat st;
2996 +       struct dbgaufs_arg *p;
2997 +
2998 +       err = -ENOMEM;
2999 +       p = kmalloc(sizeof(*p), GFP_NOFS);
3000 +       if (unlikely(!p))
3001 +               goto out;
3002 +
3003 +       err = 0;
3004 +       p->n = 0;
3005 +       file->private_data = p;
3006 +       if (!xf)
3007 +               goto out;
3008 +
3009 +       err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
3010 +       if (!err) {
3011 +               if (do_fcnt)
3012 +                       p->n = snprintf
3013 +                               (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
3014 +                                (long)file_count(xf), st.blocks, st.blksize,
3015 +                                (long long)st.size);
3016 +               else
3017 +                       p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
3018 +                                       st.blocks, st.blksize,
3019 +                                       (long long)st.size);
3020 +               AuDebugOn(p->n >= sizeof(p->a));
3021 +       } else {
3022 +               p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
3023 +               err = 0;
3024 +       }
3025 +
3026 +out:
3027 +       return err;
3028 +
3029 +}
3030 +
3031 +static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
3032 +                              size_t count, loff_t *ppos)
3033 +{
3034 +       struct dbgaufs_arg *p;
3035 +
3036 +       p = file->private_data;
3037 +       return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
3038 +}
3039 +
3040 +/* ---------------------------------------------------------------------- */
3041 +
3042 +static int dbgaufs_xib_open(struct inode *inode, struct file *file)
3043 +{
3044 +       int err;
3045 +       struct au_sbinfo *sbinfo;
3046 +       struct super_block *sb;
3047 +
3048 +       sbinfo = inode->i_private;
3049 +       sb = sbinfo->si_sb;
3050 +       si_noflush_read_lock(sb);
3051 +       err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
3052 +       si_read_unlock(sb);
3053 +       return err;
3054 +}
3055 +
3056 +static const struct file_operations dbgaufs_xib_fop = {
3057 +       .owner          = THIS_MODULE,
3058 +       .open           = dbgaufs_xib_open,
3059 +       .release        = dbgaufs_xi_release,
3060 +       .read           = dbgaufs_xi_read
3061 +};
3062 +
3063 +/* ---------------------------------------------------------------------- */
3064 +
3065 +#define DbgaufsXi_PREFIX "xi"
3066 +
3067 +static int dbgaufs_xino_open(struct inode *inode, struct file *file)
3068 +{
3069 +       int err;
3070 +       long l;
3071 +       struct au_sbinfo *sbinfo;
3072 +       struct super_block *sb;
3073 +       struct file *xf;
3074 +       struct qstr *name;
3075 +
3076 +       err = -ENOENT;
3077 +       xf = NULL;
3078 +       name = &file->f_dentry->d_name;
3079 +       if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
3080 +                    || memcmp(name->name, DbgaufsXi_PREFIX,
3081 +                              sizeof(DbgaufsXi_PREFIX) - 1)))
3082 +               goto out;
3083 +       err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
3084 +       if (unlikely(err))
3085 +               goto out;
3086 +
3087 +       sbinfo = inode->i_private;
3088 +       sb = sbinfo->si_sb;
3089 +       si_noflush_read_lock(sb);
3090 +       if (l <= au_sbend(sb)) {
3091 +               xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
3092 +               err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
3093 +       } else
3094 +               err = -ENOENT;
3095 +       si_read_unlock(sb);
3096 +
3097 +out:
3098 +       return err;
3099 +}
3100 +
3101 +static const struct file_operations dbgaufs_xino_fop = {
3102 +       .owner          = THIS_MODULE,
3103 +       .open           = dbgaufs_xino_open,
3104 +       .release        = dbgaufs_xi_release,
3105 +       .read           = dbgaufs_xi_read
3106 +};
3107 +
3108 +void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
3109 +{
3110 +       aufs_bindex_t bend;
3111 +       struct au_branch *br;
3112 +       struct au_xino_file *xi;
3113 +
3114 +       if (!au_sbi(sb)->si_dbgaufs)
3115 +               return;
3116 +
3117 +       bend = au_sbend(sb);
3118 +       for (; bindex <= bend; bindex++) {
3119 +               br = au_sbr(sb, bindex);
3120 +               xi = &br->br_xino;
3121 +               if (xi->xi_dbgaufs) {
3122 +                       debugfs_remove(xi->xi_dbgaufs);
3123 +                       xi->xi_dbgaufs = NULL;
3124 +               }
3125 +       }
3126 +}
3127 +
3128 +void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
3129 +{
3130 +       struct au_sbinfo *sbinfo;
3131 +       struct dentry *parent;
3132 +       struct au_branch *br;
3133 +       struct au_xino_file *xi;
3134 +       aufs_bindex_t bend;
3135 +       char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
3136 +
3137 +       sbinfo = au_sbi(sb);
3138 +       parent = sbinfo->si_dbgaufs;
3139 +       if (!parent)
3140 +               return;
3141 +
3142 +       bend = au_sbend(sb);
3143 +       for (; bindex <= bend; bindex++) {
3144 +               snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
3145 +               br = au_sbr(sb, bindex);
3146 +               xi = &br->br_xino;
3147 +               AuDebugOn(xi->xi_dbgaufs);
3148 +               xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
3149 +                                                    sbinfo, &dbgaufs_xino_fop);
3150 +               /* ignore an error */
3151 +               if (unlikely(!xi->xi_dbgaufs))
3152 +                       AuWarn1("failed %s under debugfs\n", name);
3153 +       }
3154 +}
3155 +
3156 +/* ---------------------------------------------------------------------- */
3157 +
3158 +#ifdef CONFIG_AUFS_EXPORT
3159 +static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
3160 +{
3161 +       int err;
3162 +       struct au_sbinfo *sbinfo;
3163 +       struct super_block *sb;
3164 +
3165 +       sbinfo = inode->i_private;
3166 +       sb = sbinfo->si_sb;
3167 +       si_noflush_read_lock(sb);
3168 +       err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
3169 +       si_read_unlock(sb);
3170 +       return err;
3171 +}
3172 +
3173 +static const struct file_operations dbgaufs_xigen_fop = {
3174 +       .owner          = THIS_MODULE,
3175 +       .open           = dbgaufs_xigen_open,
3176 +       .release        = dbgaufs_xi_release,
3177 +       .read           = dbgaufs_xi_read
3178 +};
3179 +
3180 +static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3181 +{
3182 +       int err;
3183 +
3184 +       /*
3185 +        * This function is a dynamic '__init' fucntion actually,
3186 +        * so the tiny check for si_rwsem is unnecessary.
3187 +        */
3188 +       /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3189 +
3190 +       err = -EIO;
3191 +       sbinfo->si_dbgaufs_xigen = debugfs_create_file
3192 +               ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3193 +                &dbgaufs_xigen_fop);
3194 +       if (sbinfo->si_dbgaufs_xigen)
3195 +               err = 0;
3196 +
3197 +       return err;
3198 +}
3199 +#else
3200 +static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3201 +{
3202 +       return 0;
3203 +}
3204 +#endif /* CONFIG_AUFS_EXPORT */
3205 +
3206 +/* ---------------------------------------------------------------------- */
3207 +
3208 +void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
3209 +{
3210 +       /*
3211 +        * This function is a dynamic '__init' fucntion actually,
3212 +        * so the tiny check for si_rwsem is unnecessary.
3213 +        */
3214 +       /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3215 +
3216 +       debugfs_remove_recursive(sbinfo->si_dbgaufs);
3217 +       sbinfo->si_dbgaufs = NULL;
3218 +       kobject_put(&sbinfo->si_kobj);
3219 +}
3220 +
3221 +int dbgaufs_si_init(struct au_sbinfo *sbinfo)
3222 +{
3223 +       int err;
3224 +       char name[SysaufsSiNameLen];
3225 +
3226 +       /*
3227 +        * This function is a dynamic '__init' fucntion actually,
3228 +        * so the tiny check for si_rwsem is unnecessary.
3229 +        */
3230 +       /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3231 +
3232 +       err = -ENOENT;
3233 +       if (!dbgaufs) {
3234 +               AuErr1("/debug/aufs is uninitialized\n");
3235 +               goto out;
3236 +       }
3237 +
3238 +       err = -EIO;
3239 +       sysaufs_name(sbinfo, name);
3240 +       sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
3241 +       if (unlikely(!sbinfo->si_dbgaufs))
3242 +               goto out;
3243 +       kobject_get(&sbinfo->si_kobj);
3244 +
3245 +       sbinfo->si_dbgaufs_xib = debugfs_create_file
3246 +               ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3247 +                &dbgaufs_xib_fop);
3248 +       if (unlikely(!sbinfo->si_dbgaufs_xib))
3249 +               goto out_dir;
3250 +
3251 +       err = dbgaufs_xigen_init(sbinfo);
3252 +       if (!err)
3253 +               goto out; /* success */
3254 +
3255 +out_dir:
3256 +       dbgaufs_si_fin(sbinfo);
3257 +out:
3258 +       return err;
3259 +}
3260 +
3261 +/* ---------------------------------------------------------------------- */
3262 +
3263 +void dbgaufs_fin(void)
3264 +{
3265 +       debugfs_remove(dbgaufs);
3266 +}
3267 +
3268 +int __init dbgaufs_init(void)
3269 +{
3270 +       int err;
3271 +
3272 +       err = -EIO;
3273 +       dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
3274 +       if (dbgaufs)
3275 +               err = 0;
3276 +       return err;
3277 +}
3278 diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
3279 --- /usr/share/empty/fs/aufs/dbgaufs.h  1970-01-01 01:00:00.000000000 +0100
3280 +++ linux/fs/aufs/dbgaufs.h     2010-10-21 09:52:43.086957936 +0200
3281 @@ -0,0 +1,52 @@
3282 +/*
3283 + * Copyright (C) 2005-2010 Junjiro R. Okajima
3284 + *
3285 + * This program, aufs is free software; you can redistribute it and/or modify
3286 + * it under the terms of the GNU General Public License as published by
3287 + * the Free Software Foundation; either version 2 of the License, or
3288 + * (at your option) any later version.
3289 + *
3290 + * This program is distributed in the hope that it will be useful,
3291 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3292 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3293 + * GNU General Public License for more details.
3294 + *
3295 + * You should have received a copy of the GNU General Public License
3296 + * along with this program; if not, write to the Free Software
3297 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
3298 + */
3299 +
3300 +/*
3301 + * debugfs interface
3302 + */
3303 +
3304 +#ifndef __DBGAUFS_H__
3305 +#define __DBGAUFS_H__
3306 +
3307 +#ifdef __KERNEL__
3308 +
3309 +#include <linux/init.h>
3310 +#include <linux/aufs_type.h>
3311 +
3312 +struct super_block;
3313 +struct au_sbinfo;
3314 +
3315 +#ifdef CONFIG_DEBUG_FS
3316 +/* dbgaufs.c */
3317 +void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
3318 +void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
3319 +void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
3320 +int dbgaufs_si_init(struct au_sbinfo *sbinfo);
3321 +void dbgaufs_fin(void);
3322 +int __init dbgaufs_init(void);
3323 +#else
3324 +AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
3325 +AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
3326 +AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
3327 +AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
3328 +AuStubVoid(dbgaufs_fin, void)
3329 +AuStubInt0(__init dbgaufs_init, void)
3330 +#endif /* CONFIG_DEBUG_FS */
3331 +
3332 +#endif /* __KERNEL__ */
3333 +#endif /* __DBGAUFS_H__ */
3334 diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
3335 --- /usr/share/empty/fs/aufs/dcsub.c    1970-01-01 01:00:00.000000000 +0100
3336 +++ linux/fs/aufs/dcsub.c       2010-10-21 09:52:43.086957936 +0200
3337 @@ -0,0 +1,200 @@
3338 +/*
3339 + * Copyright (C) 2005-2010 Junjiro R. Okajima
3340 + *
3341 + * This program, aufs is free software; you can redistribute it and/or modify
3342 + * it under the terms of the GNU General Public License as published by
3343 + * the Free Software Foundation; either version 2 of the License, or
3344 + * (at your option) any later version.
3345 + *
3346 + * This program is distributed in the hope that it will be useful,
3347 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3348 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3349 + * GNU General Public License for more details.
3350 + *
3351 + * You should have received a copy of the GNU General Public License
3352 + * along with this program; if not, write to the Free Software
3353 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
3354 + */
3355 +
3356 +/*
3357 + * sub-routines for dentry cache
3358 + */
3359 +
3360 +#include "aufs.h"
3361 +
3362 +static void au_dpage_free(struct au_dpage *dpage)
3363 +{
3364 +       int i;
3365 +       struct dentry **p;
3366 +
3367 +       p = dpage->dentries;
3368 +       for (i = 0; i < dpage->ndentry; i++)
3369 +               dput(*p++);
3370 +       free_page((unsigned long)dpage->dentries);
3371 +}
3372 +
3373 +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
3374 +{
3375 +       int err;
3376 +       void *p;
3377 +
3378 +       err = -ENOMEM;
3379 +       dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
3380 +       if (unlikely(!dpages->dpages))
3381 +               goto out;
3382 +
3383 +       p = (void *)__get_free_page(gfp);
3384 +       if (unlikely(!p))
3385 +               goto out_dpages;
3386 +
3387 +       dpages->dpages[0].ndentry = 0;
3388 +       dpages->dpages[0].dentries = p;
3389 +       dpages->ndpage = 1;
3390 +       return 0; /* success */
3391 +
3392 +out_dpages:
3393 +       kfree(dpages->dpages);
3394 +out:
3395 +       return err;
3396 +}
3397 +
3398 +void au_dpages_free(struct au_dcsub_pages *dpages)
3399 +{
3400 +       int i;
3401 +       struct au_dpage *p;
3402 +
3403 +       p = dpages->dpages;
3404 +       for (i = 0; i < dpages->ndpage; i++)
3405 +               au_dpage_free(p++);
3406 +       kfree(dpages->dpages);
3407 +}
3408 +
3409 +static int au_dpages_append(struct au_dcsub_pages *dpages,
3410 +                           struct dentry *dentry, gfp_t gfp)
3411 +{
3412 +       int err, sz;
3413 +       struct au_dpage *dpage;
3414 +       void *p;
3415 +
3416 +       dpage = dpages->dpages + dpages->ndpage - 1;
3417 +       sz = PAGE_SIZE / sizeof(dentry);
3418 +       if (unlikely(dpage->ndentry >= sz)) {
3419 +               AuLabel(new dpage);
3420 +               err = -ENOMEM;
3421 +               sz = dpages->ndpage * sizeof(*dpages->dpages);
3422 +               p = au_kzrealloc(dpages->dpages, sz,
3423 +                                sz + sizeof(*dpages->dpages), gfp);
3424 +               if (unlikely(!p))
3425 +                       goto out;
3426 +
3427 +               dpages->dpages = p;
3428 +               dpage = dpages->dpages + dpages->ndpage;
3429 +               p = (void *)__get_free_page(gfp);
3430 +               if (unlikely(!p))
3431 +                       goto out;
3432 +
3433 +               dpage->ndentry = 0;
3434 +               dpage->dentries = p;
3435 +               dpages->ndpage++;
3436 +       }
3437 +
3438 +       dpage->dentries[dpage->ndentry++] = dget(dentry);
3439 +       return 0; /* success */
3440 +
3441 +out:
3442 +       return err;
3443 +}
3444 +
3445 +int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3446 +                  au_dpages_test test, void *arg)
3447 +{
3448 +       int err;
3449 +       struct dentry *this_parent = root;
3450 +       struct list_head *next;
3451 +       struct super_block *sb = root->d_sb;
3452 +
3453 +       err = 0;
3454 +       spin_lock(&dcache_lock);
3455 +repeat:
3456 +       next = this_parent->d_subdirs.next;
3457 +resume:
3458 +       if (this_parent->d_sb == sb
3459 +           && !IS_ROOT(this_parent)
3460 +           && atomic_read(&this_parent->d_count)
3461 +           && this_parent->d_inode
3462 +           && (!test || test(this_parent, arg))) {
3463 +               err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3464 +               if (unlikely(err))
3465 +                       goto out;
3466 +       }
3467 +
3468 +       while (next != &this_parent->d_subdirs) {
3469 +               struct list_head *tmp = next;
3470 +               struct dentry *dentry = list_entry(tmp, struct dentry,
3471 +                                                  d_u.d_child);
3472 +               next = tmp->next;
3473 +               if (/*d_unhashed(dentry) || */!dentry->d_inode)
3474 +                       continue;
3475 +               if (!list_empty(&dentry->d_subdirs)) {
3476 +                       this_parent = dentry;
3477 +                       goto repeat;
3478 +               }
3479 +               if (dentry->d_sb == sb
3480 +                   && atomic_read(&dentry->d_count)
3481 +                   && (!test || test(dentry, arg))) {
3482 +                       err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3483 +                       if (unlikely(err))
3484 +                               goto out;
3485 +               }
3486 +       }
3487 +
3488 +       if (this_parent != root) {
3489 +               next = this_parent->d_u.d_child.next;
3490 +               this_parent = this_parent->d_parent; /* dcache_lock is locked */
3491 +               goto resume;
3492 +       }
3493 +out:
3494 +       spin_unlock(&dcache_lock);
3495 +       return err;
3496 +}
3497 +
3498 +int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3499 +                      int do_include, au_dpages_test test, void *arg)
3500 +{
3501 +       int err;
3502 +
3503 +       err = 0;
3504 +       spin_lock(&dcache_lock);
3505 +       if (do_include && (!test || test(dentry, arg))) {
3506 +               err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3507 +               if (unlikely(err))
3508 +                       goto out;
3509 +       }
3510 +       while (!IS_ROOT(dentry)) {
3511 +               dentry = dentry->d_parent; /* dcache_lock is locked */
3512 +               if (!test || test(dentry, arg)) {
3513 +                       err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3514 +                       if (unlikely(err))
3515 +                               break;
3516 +               }
3517 +       }
3518 +
3519 +out:
3520 +       spin_unlock(&dcache_lock);
3521 +
3522 +       return err;
3523 +}
3524 +
3525 +int au_test_subdir(struct dentry *d1, struct dentry *d2)
3526 +{
3527 +       struct path path[2] = {
3528 +               {
3529 +                       .dentry = d1
3530 +               },
3531 +               {
3532 +                       .dentry = d2
3533 +               }
3534 +       };
3535 +
3536 +       return path_is_under(path + 0, path + 1);
3537 +}
3538 diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
3539 --- /usr/share/empty/fs/aufs/dcsub.h    1970-01-01 01:00:00.000000000 +0100
3540 +++ linux/fs/aufs/dcsub.h       2010-10-21 09:52:43.086957936 +0200
3541 @@ -0,0 +1,54 @@
3542 +/*
3543 + * Copyright (C) 2005-2010 Junjiro R. Okajima
3544 + *
3545 + * This program, aufs is free software; you can redistribute it and/or modify
3546 + * it under the terms of the GNU General Public License as published by
3547 + * the Free Software Foundation; either version 2 of the License, or
3548 + * (at your option) any later version.
3549 + *
3550 + * This program is distributed in the hope that it will be useful,
3551 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3552 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3553 + * GNU General Public License for more details.
3554 + *
3555 + * You should have received a copy of the GNU General Public License
3556 + * along with this program; if not, write to the Free Software
3557 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
3558 + */
3559 +
3560 +/*
3561 + * sub-routines for dentry cache
3562 + */
3563 +
3564 +#ifndef __AUFS_DCSUB_H__
3565 +#define __AUFS_DCSUB_H__
3566 +
3567 +#ifdef __KERNEL__
3568 +
3569 +#include <linux/types.h>
3570 +
3571 +struct dentry;
3572 +
3573 +struct au_dpage {
3574 +       int ndentry;
3575 +       struct dentry **dentries;
3576 +};
3577 +
3578 +struct au_dcsub_pages {
3579 +       int ndpage;
3580 +       struct au_dpage *dpages;
3581 +};
3582 +
3583 +/* ---------------------------------------------------------------------- */
3584 +
3585 +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3586 +void au_dpages_free(struct au_dcsub_pages *dpages);
3587 +typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3588 +int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3589 +                  au_dpages_test test, void *arg);
3590 +int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3591 +                      int do_include, au_dpages_test test, void *arg);
3592 +int au_test_subdir(struct dentry *d1, struct dentry *d2);
3593 +
3594 +#endif /* __KERNEL__ */
3595 +#endif /* __AUFS_DCSUB_H__ */
3596 diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
3597 --- /usr/share/empty/fs/aufs/debug.c    1970-01-01 01:00:00.000000000 +0100
3598 +++ linux/fs/aufs/debug.c       2010-10-21 09:52:43.086957936 +0200
3599 @@ -0,0 +1,426 @@
3600 +/*
3601 + * Copyright (C) 2005-2010 Junjiro R. Okajima
3602 + *
3603 + * This program, aufs is free software; you can redistribute it and/or modify
3604 + * it under the terms of the GNU General Public License as published by
3605 + * the Free Software Foundation; either version 2 of the License, or
3606 + * (at your option) any later version.
3607 + *
3608 + * This program is distributed in the hope that it will be useful,
3609 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3610 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3611 + * GNU General Public License for more details.
3612 + *
3613 + * You should have received a copy of the GNU General Public License
3614 + * along with this program; if not, write to the Free Software
3615 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
3616 + */
3617 +
3618 +/*
3619 + * debug print functions
3620 + */
3621 +
3622 +#include <linux/module.h>
3623 +#include <linux/vt_kern.h>
3624 +#include "aufs.h"
3625 +
3626 +int aufs_debug;
3627 +MODULE_PARM_DESC(debug, "debug print");
3628 +module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
3629 +
3630 +char *au_plevel = KERN_DEBUG;
3631 +#define dpri(fmt, ...) do { \
3632 +       if (au_debug_test()) \
3633 +               printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
3634 +} while (0)
3635 +
3636 +/* ---------------------------------------------------------------------- */
3637 +
3638 +void au_dpri_whlist(struct au_nhash *whlist)
3639 +{
3640 +       unsigned long ul, n;
3641 +       struct hlist_head *head;
3642 +       struct au_vdir_wh *tpos;
3643 +       struct hlist_node *pos;
3644 +
3645 +       n = whlist->nh_num;
3646 +       head = whlist->nh_head;
3647 +       for (ul = 0; ul < n; ul++) {
3648 +               hlist_for_each_entry(tpos, pos, head, wh_hash)
3649 +                       dpri("b%d, %.*s, %d\n",
3650 +                            tpos->wh_bindex,
3651 +                            tpos->wh_str.len, tpos->wh_str.name,
3652 +                            tpos->wh_str.len);
3653 +               head++;
3654 +       }
3655 +}
3656 +
3657 +void au_dpri_vdir(struct au_vdir *vdir)
3658 +{
3659 +       unsigned long ul;
3660 +       union au_vdir_deblk_p p;
3661 +       unsigned char *o;
3662 +
3663 +       if (!vdir || IS_ERR(vdir)) {
3664 +               dpri("err %ld\n", PTR_ERR(vdir));
3665 +               return;
3666 +       }
3667 +
3668 +       dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
3669 +            vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
3670 +            vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
3671 +       for (ul = 0; ul < vdir->vd_nblk; ul++) {
3672 +               p.deblk = vdir->vd_deblk[ul];
3673 +               o = p.deblk;
3674 +               dpri("[%lu]: %p\n", ul, o);
3675 +       }
3676 +}
3677 +
3678 +static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3679 +                       struct dentry *wh)
3680 +{
3681 +       char *n = NULL;
3682 +       int l = 0;
3683 +
3684 +       if (!inode || IS_ERR(inode)) {
3685 +               dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3686 +               return -1;
3687 +       }
3688 +
3689 +       /* the type of i_blocks depends upon CONFIG_LSF */
3690 +       BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3691 +                    && sizeof(inode->i_blocks) != sizeof(u64));
3692 +       if (wh) {
3693 +               n = (void *)wh->d_name.name;
3694 +               l = wh->d_name.len;
3695 +       }
3696 +
3697 +       dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
3698 +            " ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
3699 +            bindex,
3700 +            inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3701 +            atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3702 +            i_size_read(inode), (unsigned long long)inode->i_blocks,
3703 +            (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3704 +            inode->i_mapping ? inode->i_mapping->nrpages : 0,
3705 +            inode->i_state, inode->i_flags, inode->i_version,
3706 +            inode->i_generation,
3707 +            l ? ", wh " : "", l, n);
3708 +       return 0;
3709 +}
3710 +
3711 +void au_dpri_inode(struct inode *inode)
3712 +{
3713 +       struct au_iinfo *iinfo;
3714 +       aufs_bindex_t bindex;
3715 +       int err;
3716 +
3717 +       err = do_pri_inode(-1, inode, NULL);
3718 +       if (err || !au_test_aufs(inode->i_sb))
3719 +               return;
3720 +
3721 +       iinfo = au_ii(inode);
3722 +       if (!iinfo)
3723 +               return;
3724 +       dpri("i-1: bstart %d, bend %d, gen %d\n",
3725 +            iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
3726 +       if (iinfo->ii_bstart < 0)
3727 +               return;
3728 +       for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
3729 +               do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
3730 +                            iinfo->ii_hinode[0 + bindex].hi_whdentry);
3731 +}
3732 +
3733 +static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
3734 +{
3735 +       struct dentry *wh = NULL;
3736 +
3737 +       if (!dentry || IS_ERR(dentry)) {
3738 +               dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
3739 +               return -1;
3740 +       }
3741 +       /* do not call dget_parent() here */
3742 +       dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
3743 +            bindex,
3744 +            AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
3745 +            dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
3746 +            atomic_read(&dentry->d_count), dentry->d_flags);
3747 +       if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
3748 +               struct au_iinfo *iinfo = au_ii(dentry->d_inode);
3749 +               if (iinfo)
3750 +                       wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
3751 +       }
3752 +       do_pri_inode(bindex, dentry->d_inode, wh);
3753 +       return 0;
3754 +}
3755 +
3756 +void au_dpri_dentry(struct dentry *dentry)
3757 +{
3758 +       struct au_dinfo *dinfo;
3759 +       aufs_bindex_t bindex;
3760 +       int err;
3761 +       struct au_hdentry *hdp;
3762 +
3763 +       err = do_pri_dentry(-1, dentry);
3764 +       if (err || !au_test_aufs(dentry->d_sb))
3765 +               return;
3766 +
3767 +       dinfo = au_di(dentry);
3768 +       if (!dinfo)
3769 +               return;
3770 +       dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
3771 +            dinfo->di_bstart, dinfo->di_bend,
3772 +            dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
3773 +       if (dinfo->di_bstart < 0)
3774 +               return;
3775 +       hdp = dinfo->di_hdentry;
3776 +       for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
3777 +               do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
3778 +}
3779 +
3780 +static int do_pri_file(aufs_bindex_t bindex, struct file *file)
3781 +{
3782 +       char a[32];
3783 +
3784 +       if (!file || IS_ERR(file)) {
3785 +               dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
3786 +               return -1;
3787 +       }
3788 +       a[0] = 0;
3789 +       if (bindex < 0
3790 +           && file->f_dentry
3791 +           && au_test_aufs(file->f_dentry->d_sb)
3792 +           && au_fi(file))
3793 +               snprintf(a, sizeof(a), ", mmapped %d",
3794 +                        !!au_fi(file)->fi_hvmop);
3795 +       dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
3796 +            bindex, file->f_mode, file->f_flags, (long)file_count(file),
3797 +            file->f_version, file->f_pos, a);
3798 +       if (file->f_dentry)
3799 +               do_pri_dentry(bindex, file->f_dentry);
3800 +       return 0;
3801 +}
3802 +
3803 +void au_dpri_file(struct file *file)
3804 +{
3805 +       struct au_finfo *finfo;
3806 +       struct au_fidir *fidir;
3807 +       struct au_hfile *hfile;
3808 +       aufs_bindex_t bindex;
3809 +       int err;
3810 +
3811 +       err = do_pri_file(-1, file);
3812 +       if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
3813 +               return;
3814 +
3815 +       finfo = au_fi(file);
3816 +       if (!finfo)
3817 +               return;
3818 +       if (finfo->fi_btop < 0)
3819 +               return;
3820 +       fidir = finfo->fi_hdir;
3821 +       if (!fidir)
3822 +               do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
3823 +       else
3824 +               for (bindex = finfo->fi_btop; bindex <= fidir->fd_bbot;
3825 +                    bindex++) {
3826 +                       hfile = fidir->fd_hfile + bindex;
3827 +                       do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
3828 +               }
3829 +}
3830 +
3831 +static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
3832 +{
3833 +       struct vfsmount *mnt;
3834 +       struct super_block *sb;
3835 +
3836 +       if (!br || IS_ERR(br))
3837 +               goto out;
3838 +       mnt = br->br_mnt;
3839 +       if (!mnt || IS_ERR(mnt))
3840 +               goto out;
3841 +       sb = mnt->mnt_sb;
3842 +       if (!sb || IS_ERR(sb))
3843 +               goto out;
3844 +
3845 +       dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
3846 +            "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
3847 +            "xino %d\n",
3848 +            bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
3849 +            au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
3850 +            sb->s_flags, sb->s_count,
3851 +            atomic_read(&sb->s_active), !!br->br_xino.xi_file);
3852 +       return 0;
3853 +
3854 +out:
3855 +       dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
3856 +       return -1;
3857 +}
3858 +
3859 +void au_dpri_sb(struct super_block *sb)
3860 +{
3861 +       struct au_sbinfo *sbinfo;
3862 +       aufs_bindex_t bindex;
3863 +       int err;
3864 +       /* to reuduce stack size */
3865 +       struct {
3866 +               struct vfsmount mnt;
3867 +               struct au_branch fake;
3868 +       } *a;
3869 +
3870 +       /* this function can be called from magic sysrq */
3871 +       a = kzalloc(sizeof(*a), GFP_ATOMIC);
3872 +       if (unlikely(!a)) {
3873 +               dpri("no memory\n");
3874 +               return;
3875 +       }
3876 +
3877 +       a->mnt.mnt_sb = sb;
3878 +       a->fake.br_perm = 0;
3879 +       a->fake.br_mnt = &a->mnt;
3880 +       a->fake.br_xino.xi_file = NULL;
3881 +       atomic_set(&a->fake.br_count, 0);
3882 +       smp_mb(); /* atomic_set */
3883 +       err = do_pri_br(-1, &a->fake);
3884 +       kfree(a);
3885 +       dpri("dev 0x%x\n", sb->s_dev);
3886 +       if (err || !au_test_aufs(sb))
3887 +               return;
3888 +
3889 +       sbinfo = au_sbi(sb);
3890 +       if (!sbinfo)
3891 +               return;
3892 +       dpri("nw %d, gen %u, kobj %d\n",
3893 +            atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
3894 +            atomic_read(&sbinfo->si_kobj.kref.refcount));
3895 +       for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
3896 +               do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
3897 +}
3898 +
3899 +/* ---------------------------------------------------------------------- */
3900 +
3901 +void au_dbg_sleep_jiffy(int jiffy)
3902 +{
3903 +       while (jiffy)
3904 +               jiffy = schedule_timeout_uninterruptible(jiffy);
3905 +}
3906 +
3907 +void au_dbg_iattr(struct iattr *ia)
3908 +{
3909 +#define AuBit(name)    if (ia->ia_valid & ATTR_ ## name) \
3910 +                               dpri(#name "\n")
3911 +       AuBit(MODE);
3912 +       AuBit(UID);
3913 +       AuBit(GID);
3914 +       AuBit(SIZE);
3915 +       AuBit(ATIME);
3916 +       AuBit(MTIME);
3917 +       AuBit(CTIME);
3918 +       AuBit(ATIME_SET);
3919 +       AuBit(MTIME_SET);
3920 +       AuBit(FORCE);
3921 +       AuBit(ATTR_FLAG);
3922 +       AuBit(KILL_SUID);
3923 +       AuBit(KILL_SGID);
3924 +       AuBit(FILE);
3925 +       AuBit(KILL_PRIV);
3926 +       AuBit(OPEN);
3927 +       AuBit(TIMES_SET);
3928 +#undef AuBit
3929 +       dpri("ia_file %p\n", ia->ia_file);
3930 +}
3931 +
3932 +/* ---------------------------------------------------------------------- */
3933 +
3934 +void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
3935 +{
3936 +       struct dentry *parent;
3937 +
3938 +       parent = dget_parent(dentry);
3939 +       AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
3940 +                 || IS_ROOT(dentry)
3941 +                 || au_digen(parent) != sigen);
3942 +       dput(parent);
3943 +}
3944 +
3945 +void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
3946 +{
3947 +       struct dentry *parent;
3948 +
3949 +       parent = dget_parent(dentry);
3950 +       AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
3951 +                 || au_digen(parent) != sigen);
3952 +       dput(parent);
3953 +}
3954 +
3955 +void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
3956 +{
3957 +       int err, i, j;
3958 +       struct au_dcsub_pages dpages;
3959 +       struct au_dpage *dpage;
3960 +       struct dentry **dentries;
3961 +
3962 +       err = au_dpages_init(&dpages, GFP_NOFS);
3963 +       AuDebugOn(err);
3964 +       err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
3965 +       AuDebugOn(err);
3966 +       for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
3967 +               dpage = dpages.dpages + i;
3968 +               dentries = dpage->dentries;
3969 +               for (j = dpage->ndentry - 1; !err && j >= 0; j--)
3970 +                       AuDebugOn(au_digen(dentries[j]) != sigen);
3971 +       }
3972 +       au_dpages_free(&dpages);
3973 +}
3974 +
3975 +void au_dbg_verify_kthread(void)
3976 +{
3977 +       if (current->flags & PF_WQ_WORKER) {
3978 +               au_dbg_blocked();
3979 +               WARN_ON(1);
3980 +       }
3981 +}
3982 +
3983 +/* ---------------------------------------------------------------------- */
3984 +
3985 +void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
3986 +{
3987 +#ifdef AuForceNoPlink
3988 +       au_opt_clr(sbinfo->si_mntflags, PLINK);
3989 +#endif
3990 +#ifdef AuForceNoXino
3991 +       au_opt_clr(sbinfo->si_mntflags, XINO);
3992 +#endif
3993 +#ifdef AuForceNoRefrof
3994 +       au_opt_clr(sbinfo->si_mntflags, REFROF);
3995 +#endif
3996 +#ifdef AuForceHnotify
3997 +       au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
3998 +#endif
3999 +#ifdef AuForceRd0
4000 +       sbinfo->si_rdblk = 0;
4001 +       sbinfo->si_rdhash = 0;
4002 +#endif
4003 +}
4004 +
4005 +int __init au_debug_init(void)
4006 +{
4007 +       aufs_bindex_t bindex;
4008 +       struct au_vdir_destr destr;
4009 +
4010 +       bindex = -1;
4011 +       AuDebugOn(bindex >= 0);
4012 +
4013 +       destr.len = -1;
4014 +       AuDebugOn(destr.len < NAME_MAX);
4015 +
4016 +#ifdef CONFIG_4KSTACKS
4017 +       pr_warning("CONFIG_4KSTACKS is defined.\n");
4018 +#endif
4019 +
4020 +#ifdef AuForceNoBrs
4021 +       sysaufs_brs = 0;
4022 +#endif
4023 +
4024 +       return 0;
4025 +}
4026 diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
4027 --- /usr/share/empty/fs/aufs/debug.h    1970-01-01 01:00:00.000000000 +0100
4028 +++ linux/fs/aufs/debug.h       2010-10-21 09:52:43.086957936 +0200
4029 @@ -0,0 +1,243 @@
4030 +/*
4031 + * Copyright (C) 2005-2010 Junjiro R. Okajima
4032 + *
4033 + * This program, aufs is free software; you can redistribute it and/or modify
4034 + * it under the terms of the GNU General Public License as published by
4035 + * the Free Software Foundation; either version 2 of the License, or
4036 + * (at your option) any later version.
4037 + *
4038 + * This program is distributed in the hope that it will be useful,
4039 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4040 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4041 + * GNU General Public License for more details.
4042 + *
4043 + * You should have received a copy of the GNU General Public License
4044 + * along with this program; if not, write to the Free Software
4045 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
4046 + */
4047 +
4048 +/*
4049 + * debug print functions
4050 + */
4051 +
4052 +#ifndef __AUFS_DEBUG_H__
4053 +#define __AUFS_DEBUG_H__
4054 +
4055 +#ifdef __KERNEL__
4056 +
4057 +#include <asm/system.h>
4058 +#include <linux/bug.h>
4059 +/* #include <linux/err.h> */
4060 +#include <linux/init.h>
4061 +#include <linux/module.h>
4062 +#include <linux/kallsyms.h>
4063 +/* #include <linux/kernel.h> */
4064 +#include <linux/delay.h>
4065 +/* #include <linux/kd.h> */
4066 +#include <linux/vt_kern.h>
4067 +#include <linux/sysrq.h>
4068 +#include <linux/aufs_type.h>
4069 +
4070 +#include <asm/system.h>
4071 +
4072 +#ifdef CONFIG_AUFS_DEBUG
4073 +#define AuDebugOn(a)           BUG_ON(a)
4074 +
4075 +/* module parameter */
4076 +extern int aufs_debug;
4077 +static inline void au_debug(int n)
4078 +{
4079 +       aufs_debug = n;
4080 +       smp_mb();
4081 +}
4082 +
4083 +static inline int au_debug_test(void)
4084 +{
4085 +       return aufs_debug;
4086 +}
4087 +#else
4088 +#define AuDebugOn(a)           do {} while (0)
4089 +AuStubVoid(au_debug, int n)
4090 +AuStubInt0(au_debug_test, void)
4091 +#endif /* CONFIG_AUFS_DEBUG */
4092 +
4093 +/* ---------------------------------------------------------------------- */
4094 +
4095 +/* debug print */
4096 +
4097 +#define AuDbg(fmt, ...) do { \
4098 +       if (au_debug_test()) \
4099 +               pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
4100 +} while (0)
4101 +#define AuLabel(l)             AuDbg(#l "\n")
4102 +#define AuIOErr(fmt, ...)      pr_err("I/O Error, " fmt, ##__VA_ARGS__)
4103 +#define AuWarn1(fmt, ...) do { \
4104 +       static unsigned char _c; \
4105 +       if (!_c++) \
4106 +               pr_warning(fmt, ##__VA_ARGS__); \
4107 +} while (0)
4108 +
4109 +#define AuErr1(fmt, ...) do { \
4110 +       static unsigned char _c; \
4111 +       if (!_c++) \
4112 +               pr_err(fmt, ##__VA_ARGS__); \
4113 +} while (0)
4114 +
4115 +#define AuIOErr1(fmt, ...) do { \
4116 +       static unsigned char _c; \
4117 +       if (!_c++) \
4118 +               AuIOErr(fmt, ##__VA_ARGS__); \
4119 +} while (0)
4120 +
4121 +#define AuUnsupportMsg "This operation is not supported." \
4122 +                       " Please report this application to aufs-users ML."
4123 +#define AuUnsupport(fmt, ...) do { \
4124 +       pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
4125 +       dump_stack(); \
4126 +} while (0)
4127 +
4128 +#define AuTraceErr(e) do { \
4129 +       if (unlikely((e) < 0)) \
4130 +               AuDbg("err %d\n", (int)(e)); \
4131 +} while (0)
4132 +
4133 +#define AuTraceErrPtr(p) do { \
4134 +       if (IS_ERR(p)) \
4135 +               AuDbg("err %ld\n", PTR_ERR(p)); \
4136 +} while (0)
4137 +
4138 +/* dirty macros for debug print, use with "%.*s" and caution */
4139 +#define AuLNPair(qstr)         (qstr)->len, (qstr)->name
4140 +#define AuDLNPair(d)           AuLNPair(&(d)->d_name)
4141 +
4142 +/* ---------------------------------------------------------------------- */
4143 +
4144 +struct au_sbinfo;
4145 +struct au_finfo;
4146 +struct dentry;
4147 +#ifdef CONFIG_AUFS_DEBUG
4148 +extern char *au_plevel;
4149 +struct au_nhash;
4150 +void au_dpri_whlist(struct au_nhash *whlist);
4151 +struct au_vdir;
4152 +void au_dpri_vdir(struct au_vdir *vdir);
4153 +struct inode;
4154 +void au_dpri_inode(struct inode *inode);
4155 +void au_dpri_dentry(struct dentry *dentry);
4156 +struct file;
4157 +void au_dpri_file(struct file *filp);
4158 +struct super_block;
4159 +void au_dpri_sb(struct super_block *sb);
4160 +
4161 +void au_dbg_sleep_jiffy(int jiffy);
4162 +struct iattr;
4163 +void au_dbg_iattr(struct iattr *ia);
4164 +
4165 +void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
4166 +void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
4167 +void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
4168 +void au_dbg_verify_kthread(void);
4169 +
4170 +int __init au_debug_init(void);
4171 +void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
4172 +#define AuDbgWhlist(w) do { \
4173 +       AuDbg(#w "\n"); \
4174 +       au_dpri_whlist(w); \
4175 +} while (0)
4176 +
4177 +#define AuDbgVdir(v) do { \
4178 +       AuDbg(#v "\n"); \
4179 +       au_dpri_vdir(v); \
4180 +} while (0)
4181 +
4182 +#define AuDbgInode(i) do { \
4183 +       AuDbg(#i "\n"); \
4184 +       au_dpri_inode(i); \
4185 +} while (0)
4186 +
4187 +#define AuDbgDentry(d) do { \
4188 +       AuDbg(#d "\n"); \
4189 +       au_dpri_dentry(d); \
4190 +} while (0)
4191 +
4192 +#define AuDbgFile(f) do { \
4193 +       AuDbg(#f "\n"); \
4194 +       au_dpri_file(f); \
4195 +} while (0)
4196 +
4197 +#define AuDbgSb(sb) do { \
4198 +       AuDbg(#sb "\n"); \
4199 +       au_dpri_sb(sb); \
4200 +} while (0)
4201 +
4202 +#define AuDbgSleep(sec) do { \
4203 +       AuDbg("sleep %d sec\n", sec); \
4204 +       ssleep(sec); \
4205 +} while (0)
4206 +
4207 +#define AuDbgSleepJiffy(jiffy) do { \
4208 +       AuDbg("sleep %d jiffies\n", jiffy); \
4209 +       au_dbg_sleep_jiffy(jiffy); \
4210 +} while (0)
4211 +
4212 +#define AuDbgIAttr(ia) do { \
4213 +       AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
4214 +       au_dbg_iattr(ia); \
4215 +} while (0)
4216 +
4217 +#define AuDbgSym(addr) do {                            \
4218 +       char sym[KSYM_SYMBOL_LEN];                      \
4219 +       sprint_symbol(sym, (unsigned long)addr);        \
4220 +       AuDbg("%s\n", sym);                             \
4221 +} while (0)
4222 +
4223 +#define AuInfoSym(addr) do {                           \
4224 +       char sym[KSYM_SYMBOL_LEN];                      \
4225 +       sprint_symbol(sym, (unsigned long)addr);        \
4226 +       AuInfo("%s\n", sym);                            \
4227 +} while (0)
4228 +#else
4229 +AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
4230 +AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
4231 +          unsigned int sigen)
4232 +AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
4233 +AuStubVoid(au_dbg_verify_kthread, void)
4234 +AuStubInt0(__init au_debug_init, void)
4235 +AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
4236 +
4237 +#define AuDbgWhlist(w)         do {} while (0)
4238 +#define AuDbgVdir(v)           do {} while (0)
4239 +#define AuDbgInode(i)          do {} while (0)
4240 +#define AuDbgDentry(d)         do {} while (0)
4241 +#define AuDbgFile(f)           do {} while (0)
4242 +#define AuDbgSb(sb)            do {} while (0)
4243 +#define AuDbgSleep(sec)                do {} while (0)
4244 +#define AuDbgSleepJiffy(jiffy) do {} while (0)
4245 +#define AuDbgIAttr(ia)         do {} while (0)
4246 +#define AuDbgSym(addr)         do {} while (0)
4247 +#define AuInfoSym(addr)                do {} while (0)
4248 +#endif /* CONFIG_AUFS_DEBUG */
4249 +
4250 +/* ---------------------------------------------------------------------- */
4251 +
4252 +#ifdef CONFIG_AUFS_MAGIC_SYSRQ
4253 +int __init au_sysrq_init(void);
4254 +void au_sysrq_fin(void);
4255 +
4256 +#ifdef CONFIG_HW_CONSOLE
4257 +#define au_dbg_blocked() do { \
4258 +       WARN_ON(1); \
4259 +       handle_sysrq('w', vc_cons[fg_console].d->port.tty); \
4260 +} while (0)
4261 +#else
4262 +AuStubVoid(au_dbg_blocked, void)
4263 +#endif
4264 +
4265 +#else
4266 +AuStubInt0(__init au_sysrq_init, void)
4267 +AuStubVoid(au_sysrq_fin, void)
4268 +AuStubVoid(au_dbg_blocked, void)
4269 +#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
4270 +
4271 +#endif /* __KERNEL__ */
4272 +#endif /* __AUFS_DEBUG_H__ */
4273 diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
4274 --- /usr/share/empty/fs/aufs/dentry.c   1970-01-01 01:00:00.000000000 +0100
4275 +++ linux/fs/aufs/dentry.c      2010-10-21 09:52:43.086957936 +0200
4276 @@ -0,0 +1,851 @@
4277 +/*
4278 + * Copyright (C) 2005-2010 Junjiro R. Okajima
4279 + *
4280 + * This program, aufs is free software; you can redistribute it and/or modify
4281 + * it under the terms of the GNU General Public License as published by
4282 + * the Free Software Foundation; either version 2 of the License, or
4283 + * (at your option) any later version.
4284 + *
4285 + * This program is distributed in the hope that it will be useful,
4286 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4287 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4288 + * GNU General Public License for more details.
4289 + *
4290 + * You should have received a copy of the GNU General Public License
4291 + * along with this program; if not, write to the Free Software
4292 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
4293 + */
4294 +
4295 +/*
4296 + * lookup and dentry operations
4297 + */
4298 +
4299 +#include <linux/namei.h>
4300 +#include "aufs.h"
4301 +
4302 +static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
4303 +{
4304 +       if (nd) {
4305 +               *h_nd = *nd;
4306 +
4307 +               /*
4308 +                * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
4309 +                * due to whiteout and branch permission.
4310 +                */
4311 +               h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
4312 +                                | LOOKUP_FOLLOW | LOOKUP_EXCL);
4313 +               /* unnecessary? */
4314 +               h_nd->intent.open.file = NULL;
4315 +       } else
4316 +               memset(h_nd, 0, sizeof(*h_nd));
4317 +}
4318 +
4319 +struct au_lkup_one_args {
4320 +       struct dentry **errp;
4321 +       struct qstr *name;
4322 +       struct dentry *h_parent;
4323 +       struct au_branch *br;
4324 +       struct nameidata *nd;
4325 +};
4326 +
4327 +struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
4328 +                          struct au_branch *br, struct nameidata *nd)
4329 +{
4330 +       struct dentry *h_dentry;
4331 +       int err;
4332 +       struct nameidata h_nd;
4333 +
4334 +       if (au_test_fs_null_nd(h_parent->d_sb))
4335 +               return vfsub_lookup_one_len(name->name, h_parent, name->len);
4336 +
4337 +       au_h_nd(&h_nd, nd);
4338 +       h_nd.path.dentry = h_parent;
4339 +       h_nd.path.mnt = br->br_mnt;
4340 +
4341 +       err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
4342 +       h_dentry = ERR_PTR(err);
4343 +       if (!err) {
4344 +               path_get(&h_nd.path);
4345 +               h_dentry = vfsub_lookup_hash(&h_nd);
4346 +               path_put(&h_nd.path);
4347 +       }
4348 +
4349 +       AuTraceErrPtr(h_dentry);
4350 +       return h_dentry;
4351 +}
4352 +
4353 +static void au_call_lkup_one(void *args)
4354 +{
4355 +       struct au_lkup_one_args *a = args;
4356 +       *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
4357 +}
4358 +
4359 +#define AuLkup_ALLOW_NEG       1
4360 +#define au_ftest_lkup(flags, name)     ((flags) & AuLkup_##name)
4361 +#define au_fset_lkup(flags, name)      { (flags) |= AuLkup_##name; }
4362 +#define au_fclr_lkup(flags, name)      { (flags) &= ~AuLkup_##name; }
4363 +
4364 +struct au_do_lookup_args {
4365 +       unsigned int            flags;
4366 +       mode_t                  type;
4367 +       struct nameidata        *nd;
4368 +};
4369 +
4370 +/*
4371 + * returns positive/negative dentry, NULL or an error.
4372 + * NULL means whiteout-ed or not-found.
4373 + */
4374 +static struct dentry*
4375 +au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
4376 +            aufs_bindex_t bindex, struct qstr *wh_name,
4377 +            struct au_do_lookup_args *args)
4378 +{
4379 +       struct dentry *h_dentry;
4380 +       struct inode *h_inode, *inode;
4381 +       struct au_branch *br;
4382 +       int wh_found, opq;
4383 +       unsigned char wh_able;
4384 +       const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
4385 +
4386 +       wh_found = 0;
4387 +       br = au_sbr(dentry->d_sb, bindex);
4388 +       wh_able = !!au_br_whable(br->br_perm);
4389 +       if (wh_able)
4390 +               wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
4391 +       h_dentry = ERR_PTR(wh_found);
4392 +       if (!wh_found)
4393 +               goto real_lookup;
4394 +       if (unlikely(wh_found < 0))
4395 +               goto out;
4396 +
4397 +       /* We found a whiteout */
4398 +       /* au_set_dbend(dentry, bindex); */
4399 +       au_set_dbwh(dentry, bindex);
4400 +       if (!allow_neg)
4401 +               return NULL; /* success */
4402 +
4403 +real_lookup:
4404 +       h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
4405 +       if (IS_ERR(h_dentry))
4406 +               goto out;
4407 +
4408 +       h_inode = h_dentry->d_inode;
4409 +       if (!h_inode) {
4410 +               if (!allow_neg)
4411 +                       goto out_neg;
4412 +       } else if (wh_found
4413 +                  || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
4414 +               goto out_neg;
4415 +
4416 +       if (au_dbend(dentry) <= bindex)
4417 +               au_set_dbend(dentry, bindex);
4418 +       if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4419 +               au_set_dbstart(dentry, bindex);
4420 +       au_set_h_dptr(dentry, bindex, h_dentry);
4421 +
4422 +       inode = dentry->d_inode;
4423 +       if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4424 +           || (inode && !S_ISDIR(inode->i_mode)))
4425 +               goto out; /* success */
4426 +
4427 +       mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4428 +       opq = au_diropq_test(h_dentry, br);
4429 +       mutex_unlock(&h_inode->i_mutex);
4430 +       if (opq > 0)
4431 +               au_set_dbdiropq(dentry, bindex);
4432 +       else if (unlikely(opq < 0)) {
4433 +               au_set_h_dptr(dentry, bindex, NULL);
4434 +               h_dentry = ERR_PTR(opq);
4435 +       }
4436 +       goto out;
4437 +
4438 +out_neg:
4439 +       dput(h_dentry);
4440 +       h_dentry = NULL;
4441 +out:
4442 +       return h_dentry;
4443 +}
4444 +
4445 +static int au_test_shwh(struct super_block *sb, const struct qstr *name)
4446 +{
4447 +       if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
4448 +                    && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
4449 +               return -EPERM;
4450 +       return 0;
4451 +}
4452 +
4453 +/*
4454 + * returns the number of lower positive dentries,
4455 + * otherwise an error.
4456 + * can be called at unlinking with @type is zero.
4457 + */
4458 +int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4459 +                  struct nameidata *nd)
4460 +{
4461 +       int npositive, err;
4462 +       aufs_bindex_t bindex, btail, bdiropq;
4463 +       unsigned char isdir;
4464 +       struct qstr whname;
4465 +       struct au_do_lookup_args args = {
4466 +               .flags  = 0,
4467 +               .type   = type,
4468 +               .nd     = nd
4469 +       };
4470 +       const struct qstr *name = &dentry->d_name;
4471 +       struct dentry *parent;
4472 +       struct inode *inode;
4473 +
4474 +       err = au_test_shwh(dentry->d_sb, name);
4475 +       if (unlikely(err))
4476 +               goto out;
4477 +
4478 +       err = au_wh_name_alloc(&whname, name);
4479 +       if (unlikely(err))
4480 +               goto out;
4481 +
4482 +       inode = dentry->d_inode;
4483 +       isdir = !!(inode && S_ISDIR(inode->i_mode));
4484 +       if (!type)
4485 +               au_fset_lkup(args.flags, ALLOW_NEG);
4486 +
4487 +       npositive = 0;
4488 +       parent = dget_parent(dentry);
4489 +       btail = au_dbtaildir(parent);
4490 +       for (bindex = bstart; bindex <= btail; bindex++) {
4491 +               struct dentry *h_parent, *h_dentry;
4492 +               struct inode *h_inode, *h_dir;
4493 +
4494 +               h_dentry = au_h_dptr(dentry, bindex);
4495 +               if (h_dentry) {
4496 +                       if (h_dentry->d_inode)
4497 +                               npositive++;
4498 +                       if (type != S_IFDIR)
4499 +                               break;
4500 +                       continue;
4501 +               }
4502 +               h_parent = au_h_dptr(parent, bindex);
4503 +               if (!h_parent)
4504 +                       continue;
4505 +               h_dir = h_parent->d_inode;
4506 +               if (!h_dir || !S_ISDIR(h_dir->i_mode))
4507 +                       continue;
4508 +
4509 +               mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4510 +               h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4511 +                                       &args);
4512 +               mutex_unlock(&h_dir->i_mutex);
4513 +               err = PTR_ERR(h_dentry);
4514 +               if (IS_ERR(h_dentry))
4515 +                       goto out_parent;
4516 +               au_fclr_lkup(args.flags, ALLOW_NEG);
4517 +
4518 +               if (au_dbwh(dentry) >= 0)
4519 +                       break;
4520 +               if (!h_dentry)
4521 +                       continue;
4522 +               h_inode = h_dentry->d_inode;
4523 +               if (!h_inode)
4524 +                       continue;
4525 +               npositive++;
4526 +               if (!args.type)
4527 +                       args.type = h_inode->i_mode & S_IFMT;
4528 +               if (args.type != S_IFDIR)
4529 +                       break;
4530 +               else if (isdir) {
4531 +                       /* the type of lower may be different */
4532 +                       bdiropq = au_dbdiropq(dentry);
4533 +                       if (bdiropq >= 0 && bdiropq <= bindex)
4534 +                               break;
4535 +               }
4536 +       }
4537 +
4538 +       if (npositive) {
4539 +               AuLabel(positive);
4540 +               au_update_dbstart(dentry);
4541 +       }
4542 +       err = npositive;
4543 +       if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
4544 +                    && au_dbstart(dentry) < 0))
4545 +               /* both of real entry and whiteout found */
4546 +               err = -EIO;
4547 +
4548 +out_parent:
4549 +       dput(parent);
4550 +       kfree(whname.name);
4551 +out:
4552 +       return err;
4553 +}
4554 +
4555 +struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4556 +                              struct au_branch *br)
4557 +{
4558 +       struct dentry *dentry;
4559 +       int wkq_err;
4560 +
4561 +       if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
4562 +               dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
4563 +       else {
4564 +               struct au_lkup_one_args args = {
4565 +                       .errp           = &dentry,
4566 +                       .name           = name,
4567 +                       .h_parent       = parent,
4568 +                       .br             = br,
4569 +                       .nd             = NULL
4570 +               };
4571 +
4572 +               wkq_err = au_wkq_wait(au_call_lkup_one, &args);
4573 +               if (unlikely(wkq_err))
4574 +                       dentry = ERR_PTR(wkq_err);
4575 +       }
4576 +
4577 +       return dentry;
4578 +}
4579 +
4580 +/*
4581 + * lookup @dentry on @bindex which should be negative.
4582 + */
4583 +int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4584 +{
4585 +       int err;
4586 +       struct dentry *parent, *h_parent, *h_dentry;
4587 +
4588 +       parent = dget_parent(dentry);
4589 +       h_parent = au_h_dptr(parent, bindex);
4590 +       h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
4591 +                                  au_sbr(dentry->d_sb, bindex));
4592 +       err = PTR_ERR(h_dentry);
4593 +       if (IS_ERR(h_dentry))
4594 +               goto out;
4595 +       if (unlikely(h_dentry->d_inode)) {
4596 +               err = -EIO;
4597 +               AuIOErr("b%d %.*s should be negative.\n",
4598 +                       bindex, AuDLNPair(h_dentry));
4599 +               dput(h_dentry);
4600 +               goto out;
4601 +       }
4602 +
4603 +       err = 0;
4604 +       if (bindex < au_dbstart(dentry))
4605 +               au_set_dbstart(dentry, bindex);
4606 +       if (au_dbend(dentry) < bindex)
4607 +               au_set_dbend(dentry, bindex);
4608 +       au_set_h_dptr(dentry, bindex, h_dentry);
4609 +
4610 +out:
4611 +       dput(parent);
4612 +       return err;
4613 +}
4614 +
4615 +/* ---------------------------------------------------------------------- */
4616 +
4617 +/* subset of struct inode */
4618 +struct au_iattr {
4619 +       unsigned long           i_ino;
4620 +       /* unsigned int         i_nlink; */
4621 +       uid_t                   i_uid;
4622 +       gid_t                   i_gid;
4623 +       u64                     i_version;
4624 +/*
4625 +       loff_t                  i_size;
4626 +       blkcnt_t                i_blocks;
4627 +*/
4628 +       umode_t                 i_mode;
4629 +};
4630 +
4631 +static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
4632 +{
4633 +       ia->i_ino = h_inode->i_ino;
4634 +       /* ia->i_nlink = h_inode->i_nlink; */
4635 +       ia->i_uid = h_inode->i_uid;
4636 +       ia->i_gid = h_inode->i_gid;
4637 +       ia->i_version = h_inode->i_version;
4638 +/*
4639 +       ia->i_size = h_inode->i_size;
4640 +       ia->i_blocks = h_inode->i_blocks;
4641 +*/
4642 +       ia->i_mode = (h_inode->i_mode & S_IFMT);
4643 +}
4644 +
4645 +static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
4646 +{
4647 +       return ia->i_ino != h_inode->i_ino
4648 +               /* || ia->i_nlink != h_inode->i_nlink */
4649 +               || ia->i_uid != h_inode->i_uid
4650 +               || ia->i_gid != h_inode->i_gid
4651 +               || ia->i_version != h_inode->i_version
4652 +/*
4653 +               || ia->i_size != h_inode->i_size
4654 +               || ia->i_blocks != h_inode->i_blocks
4655 +*/
4656 +               || ia->i_mode != (h_inode->i_mode & S_IFMT);
4657 +}
4658 +
4659 +static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
4660 +                             struct au_branch *br)
4661 +{
4662 +       int err;
4663 +       struct au_iattr ia;
4664 +       struct inode *h_inode;
4665 +       struct dentry *h_d;
4666 +       struct super_block *h_sb;
4667 +
4668 +       err = 0;
4669 +       memset(&ia, -1, sizeof(ia));
4670 +       h_sb = h_dentry->d_sb;
4671 +       h_inode = h_dentry->d_inode;
4672 +       if (h_inode)
4673 +               au_iattr_save(&ia, h_inode);
4674 +       else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
4675 +               /* nfs d_revalidate may return 0 for negative dentry */
4676 +               /* fuse d_revalidate always return 0 for negative dentry */
4677 +               goto out;
4678 +
4679 +       /* main purpose is namei.c:cached_lookup() and d_revalidate */
4680 +       h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
4681 +       err = PTR_ERR(h_d);
4682 +       if (IS_ERR(h_d))
4683 +               goto out;
4684 +
4685 +       err = 0;
4686 +       if (unlikely(h_d != h_dentry
4687 +                    || h_d->d_inode != h_inode
4688 +                    || (h_inode && au_iattr_test(&ia, h_inode))))
4689 +               err = au_busy_or_stale();
4690 +       dput(h_d);
4691 +
4692 +out:
4693 +       AuTraceErr(err);
4694 +       return err;
4695 +}
4696 +
4697 +int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
4698 +               struct dentry *h_parent, struct au_branch *br)
4699 +{
4700 +       int err;
4701 +
4702 +       err = 0;
4703 +       if (udba == AuOpt_UDBA_REVAL) {
4704 +               IMustLock(h_dir);
4705 +               err = (h_dentry->d_parent->d_inode != h_dir);
4706 +       } else if (udba == AuOpt_UDBA_HNOTIFY)
4707 +               err = au_h_verify_dentry(h_dentry, h_parent, br);
4708 +
4709 +       return err;
4710 +}
4711 +
4712 +/* ---------------------------------------------------------------------- */
4713 +
4714 +static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
4715 +                                 struct dentry *parent)
4716 +{
4717 +       struct dentry *h_d, *h_dp;
4718 +       struct au_hdentry tmp, *q;
4719 +       struct super_block *sb;
4720 +       aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
4721 +
4722 +       AuRwMustWriteLock(&dinfo->di_rwsem);
4723 +
4724 +       bend = dinfo->di_bend;
4725 +       bwh = dinfo->di_bwh;
4726 +       bdiropq = dinfo->di_bdiropq;
4727 +       for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
4728 +               h_d = p->hd_dentry;
4729 +               if (!h_d)
4730 +                       continue;
4731 +
4732 +               h_dp = dget_parent(h_d);
4733 +               if (h_dp == au_h_dptr(parent, bindex)) {
4734 +                       dput(h_dp);
4735 +                       continue;
4736 +               }
4737 +
4738 +               new_bindex = au_find_dbindex(parent, h_dp);
4739 +               dput(h_dp);
4740 +               if (dinfo->di_bwh == bindex)
4741 +                       bwh = new_bindex;
4742 +               if (dinfo->di_bdiropq == bindex)
4743 +                       bdiropq = new_bindex;
4744 +               if (new_bindex < 0) {
4745 +                       au_hdput(p);
4746 +                       p->hd_dentry = NULL;
4747 +                       continue;
4748 +               }
4749 +
4750 +               /* swap two lower dentries, and loop again */
4751 +               q = dinfo->di_hdentry + new_bindex;
4752 +               tmp = *q;
4753 +               *q = *p;
4754 +               *p = tmp;
4755 +               if (tmp.hd_dentry) {
4756 +                       bindex--;
4757 +                       p--;
4758 +               }
4759 +       }
4760 +
4761 +       sb = parent->d_sb;
4762 +       dinfo->di_bwh = -1;
4763 +       if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
4764 +               dinfo->di_bwh = bwh;
4765 +
4766 +       dinfo->di_bdiropq = -1;
4767 +       if (bdiropq >= 0
4768 +           && bdiropq <= au_sbend(sb)
4769 +           && au_sbr_whable(sb, bdiropq))
4770 +               dinfo->di_bdiropq = bdiropq;
4771 +
4772 +       bend = au_dbend(parent);
4773 +       p = dinfo->di_hdentry;
4774 +       for (bindex = 0; bindex <= bend; bindex++, p++)
4775 +               if (p->hd_dentry) {
4776 +                       dinfo->di_bstart = bindex;
4777 +                       break;
4778 +               }
4779 +
4780 +       p = dinfo->di_hdentry + bend;
4781 +       for (bindex = bend; bindex >= 0; bindex--, p--)
4782 +               if (p->hd_dentry) {
4783 +                       dinfo->di_bend = bindex;
4784 +                       break;
4785 +               }
4786 +}
4787 +
4788 +/*
4789 + * returns the number of found lower positive dentries,
4790 + * otherwise an error.
4791 + */
4792 +int au_refresh_hdentry(struct dentry *dentry, mode_t type)
4793 +{
4794 +       int npositive, err;
4795 +       unsigned int sigen;
4796 +       aufs_bindex_t bstart;
4797 +       struct au_dinfo *dinfo;
4798 +       struct super_block *sb;
4799 +       struct dentry *parent;
4800 +
4801 +       DiMustWriteLock(dentry);
4802 +
4803 +       sb = dentry->d_sb;
4804 +       AuDebugOn(IS_ROOT(dentry));
4805 +       sigen = au_sigen(sb);
4806 +       parent = dget_parent(dentry);
4807 +       AuDebugOn(au_digen(parent) != sigen
4808 +                 || au_iigen(parent->d_inode) != sigen);
4809 +
4810 +       dinfo = au_di(dentry);
4811 +       err = au_di_realloc(dinfo, au_sbend(sb) + 1);
4812 +       npositive = err;
4813 +       if (unlikely(err))
4814 +               goto out;
4815 +       au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
4816 +                             parent);
4817 +
4818 +       npositive = 0;
4819 +       bstart = au_dbstart(parent);
4820 +       if (type != S_IFDIR && dinfo->di_bstart == bstart)
4821 +               goto out_dgen; /* success */
4822 +
4823 +       npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
4824 +       if (npositive < 0)
4825 +               goto out;
4826 +       if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
4827 +               d_drop(dentry);
4828 +
4829 +out_dgen:
4830 +       au_update_digen(dentry);
4831 +out:
4832 +       dput(parent);
4833 +       AuTraceErr(npositive);
4834 +       return npositive;
4835 +}
4836 +
4837 +static noinline_for_stack
4838 +int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
4839 +                   struct dentry *dentry, aufs_bindex_t bindex)
4840 +{
4841 +       int err, valid;
4842 +       int (*reval)(struct dentry *, struct nameidata *);
4843 +
4844 +       err = 0;
4845 +       reval = NULL;
4846 +       if (h_dentry->d_op)
4847 +               reval = h_dentry->d_op->d_revalidate;
4848 +       if (!reval)
4849 +               goto out;
4850 +
4851 +       AuDbg("b%d\n", bindex);
4852 +       if (au_test_fs_null_nd(h_dentry->d_sb))
4853 +               /* it may return tri-state */
4854 +               valid = reval(h_dentry, NULL);
4855 +       else {
4856 +               struct nameidata h_nd;
4857 +               int locked;
4858 +               struct dentry *parent;
4859 +
4860 +               au_h_nd(&h_nd, nd);
4861 +               parent = nd->path.dentry;
4862 +               locked = (nd && nd->path.dentry != dentry);
4863 +               if (locked)
4864 +                       di_read_lock_parent(parent, AuLock_IR);
4865 +               BUG_ON(bindex > au_dbend(parent));
4866 +               h_nd.path.dentry = au_h_dptr(parent, bindex);
4867 +               BUG_ON(!h_nd.path.dentry);
4868 +               h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
4869 +               path_get(&h_nd.path);
4870 +               valid = reval(h_dentry, &h_nd);
4871 +               path_put(&h_nd.path);
4872 +               if (locked)
4873 +                       di_read_unlock(parent, AuLock_IR);
4874 +       }
4875 +
4876 +       if (unlikely(valid < 0))
4877 +               err = valid;
4878 +       else if (!valid)
4879 +               err = -EINVAL;
4880 +
4881 +out:
4882 +       AuTraceErr(err);
4883 +       return err;
4884 +}
4885 +
4886 +/* todo: remove this */
4887 +static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
4888 +                         struct nameidata *nd, int do_udba)
4889 +{
4890 +       int err;
4891 +       umode_t mode, h_mode;
4892 +       aufs_bindex_t bindex, btail, bstart, ibs, ibe;
4893 +       unsigned char plus, unhashed, is_root, h_plus;
4894 +       struct inode *h_inode, *h_cached_inode;
4895 +       struct dentry *h_dentry;
4896 +       struct qstr *name, *h_name;
4897 +
4898 +       err = 0;
4899 +       plus = 0;
4900 +       mode = 0;
4901 +       ibs = -1;
4902 +       ibe = -1;
4903 +       unhashed = !!d_unhashed(dentry);
4904 +       is_root = !!IS_ROOT(dentry);
4905 +       name = &dentry->d_name;
4906 +
4907 +       /*
4908 +        * Theoretically, REVAL test should be unnecessary in case of
4909 +        * {FS,I}NOTIFY.
4910 +        * But {fs,i}notify doesn't fire some necessary events,
4911 +        *      IN_ATTRIB for atime/nlink/pageio
4912 +        *      IN_DELETE for NFS dentry
4913 +        * Let's do REVAL test too.
4914 +        */
4915 +       if (do_udba && inode) {
4916 +               mode = (inode->i_mode & S_IFMT);
4917 +               plus = (inode->i_nlink > 0);
4918 +               ibs = au_ibstart(inode);
4919 +               ibe = au_ibend(inode);
4920 +       }
4921 +
4922 +       bstart = au_dbstart(dentry);
4923 +       btail = bstart;
4924 +       if (inode && S_ISDIR(inode->i_mode))
4925 +               btail = au_dbtaildir(dentry);
4926 +       for (bindex = bstart; bindex <= btail; bindex++) {
4927 +               h_dentry = au_h_dptr(dentry, bindex);
4928 +               if (!h_dentry)
4929 +                       continue;
4930 +
4931 +               AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
4932 +               h_name = &h_dentry->d_name;
4933 +               if (unlikely(do_udba
4934 +                            && !is_root
4935 +                            && (unhashed != !!d_unhashed(h_dentry)
4936 +                                || name->len != h_name->len
4937 +                                || memcmp(name->name, h_name->name, name->len))
4938 +                           )) {
4939 +                       AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
4940 +                                 unhashed, d_unhashed(h_dentry),
4941 +                                 AuDLNPair(dentry), AuDLNPair(h_dentry));
4942 +                       goto err;
4943 +               }
4944 +
4945 +               err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
4946 +               if (unlikely(err))
4947 +                       /* do not goto err, to keep the errno */
4948 +                       break;
4949 +
4950 +               /* todo: plink too? */
4951 +               if (!do_udba)
4952 +                       continue;
4953 +
4954 +               /* UDBA tests */
4955 +               h_inode = h_dentry->d_inode;
4956 +               if (unlikely(!!inode != !!h_inode))
4957 +                       goto err;
4958 +
4959 +               h_plus = plus;
4960 +               h_mode = mode;
4961 +               h_cached_inode = h_inode;
4962 +               if (h_inode) {
4963 +                       h_mode = (h_inode->i_mode & S_IFMT);
4964 +                       h_plus = (h_inode->i_nlink > 0);
4965 +               }
4966 +               if (inode && ibs <= bindex && bindex <= ibe)
4967 +                       h_cached_inode = au_h_iptr(inode, bindex);
4968 +
4969 +               if (unlikely(plus != h_plus
4970 +                            || mode != h_mode
4971 +                            || h_cached_inode != h_inode))
4972 +                       goto err;
4973 +               continue;
4974 +
4975 +       err:
4976 +               err = -EINVAL;
4977 +               break;
4978 +       }
4979 +
4980 +       return err;
4981 +}
4982 +
4983 +static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
4984 +{
4985 +       int err;
4986 +       struct dentry *parent;
4987 +       struct inode *inode;
4988 +
4989 +       inode = dentry->d_inode;
4990 +       if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
4991 +               return 0;
4992 +
4993 +       parent = dget_parent(dentry);
4994 +       di_read_lock_parent(parent, AuLock_IR);
4995 +       AuDebugOn(au_digen(parent) != sigen
4996 +                 || au_iigen(parent->d_inode) != sigen);
4997 +       au_dbg_verify_gen(parent, sigen);
4998 +
4999 +       /* returns a number of positive dentries */
5000 +       err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
5001 +       if (err >= 0)
5002 +               err = au_refresh_hinode(inode, dentry);
5003 +
5004 +       di_read_unlock(parent, AuLock_IR);
5005 +       dput(parent);
5006 +       return err;
5007 +}
5008 +
5009 +int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
5010 +{
5011 +       int err;
5012 +       struct dentry *d, *parent;
5013 +       struct inode *inode;
5014 +
5015 +       if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
5016 +               return simple_reval_dpath(dentry, sigen);
5017 +
5018 +       /* slow loop, keep it simple and stupid */
5019 +       /* cf: au_cpup_dirs() */
5020 +       err = 0;
5021 +       parent = NULL;
5022 +       while (au_digen(dentry) != sigen
5023 +              || au_iigen(dentry->d_inode) != sigen) {
5024 +               d = dentry;
5025 +               while (1) {
5026 +                       dput(parent);
5027 +                       parent = dget_parent(d);
5028 +                       if (au_digen(parent) == sigen
5029 +                           && au_iigen(parent->d_inode) == sigen)
5030 +                               break;
5031 +                       d = parent;
5032 +               }
5033 +
5034 +               inode = d->d_inode;
5035 +               if (d != dentry)
5036 +                       di_write_lock_child(d);
5037 +
5038 +               /* someone might update our dentry while we were sleeping */
5039 +               if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
5040 +                       di_read_lock_parent(parent, AuLock_IR);
5041 +                       /* returns a number of positive dentries */
5042 +                       err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
5043 +                       if (err >= 0)
5044 +                               err = au_refresh_hinode(inode, d);
5045 +                       di_read_unlock(parent, AuLock_IR);
5046 +               }
5047 +
5048 +               if (d != dentry)
5049 +                       di_write_unlock(d);
5050 +               dput(parent);
5051 +               if (unlikely(err))
5052 +                       break;
5053 +       }
5054 +
5055 +       return err;
5056 +}
5057 +
5058 +/*
5059 + * if valid returns 1, otherwise 0.
5060 + */
5061 +static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
5062 +{
5063 +       int valid, err;
5064 +       unsigned int sigen;
5065 +       unsigned char do_udba;
5066 +       struct super_block *sb;
5067 +       struct inode *inode;
5068 +
5069 +       err = -EINVAL;
5070 +       sb = dentry->d_sb;
5071 +       inode = dentry->d_inode;
5072 +       aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
5073 +       sigen = au_sigen(sb);
5074 +       if (au_digen(dentry) != sigen) {
5075 +               AuDebugOn(IS_ROOT(dentry));
5076 +               if (inode)
5077 +                       err = au_reval_dpath(dentry, sigen);
5078 +               if (unlikely(err))
5079 +                       goto out_dgrade;
5080 +       }
5081 +       if (inode && au_iigen(inode) != sigen) {
5082 +               AuDebugOn(IS_ROOT(dentry));
5083 +               err = au_refresh_hinode(inode, dentry);
5084 +               if (unlikely(err))
5085 +                       goto out_dgrade;
5086 +       }
5087 +       di_downgrade_lock(dentry, AuLock_IR);
5088 +
5089 +       err = -EINVAL;
5090 +       do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
5091 +       if (do_udba && inode) {
5092 +               aufs_bindex_t bstart = au_ibstart(inode);
5093 +
5094 +               if (bstart >= 0
5095 +                   && au_test_higen(inode, au_h_iptr(inode, bstart)))
5096 +                       goto out;
5097 +       }
5098 +
5099 +       err = h_d_revalidate(dentry, inode, nd, do_udba);
5100 +       if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
5101 +               /* both of real entry and whiteout found */
5102 +               err = -EIO;
5103 +       goto out;
5104 +
5105 +out_dgrade:
5106 +       di_downgrade_lock(dentry, AuLock_IR);
5107 +out:
5108 +       aufs_read_unlock(dentry, AuLock_IR);
5109 +       AuTraceErr(err);
5110 +       valid = !err;
5111 +       if (!valid)
5112 +               AuDbg("%.*s invalid\n", AuDLNPair(dentry));
5113 +       return valid;
5114 +}
5115 +
5116 +static void aufs_d_release(struct dentry *dentry)
5117 +{
5118 +       if (dentry->d_fsdata) {
5119 +               au_di_fin(dentry);
5120 +               au_hn_di_reinit(dentry);
5121 +       }
5122 +}
5123 +
5124 +const struct dentry_operations aufs_dop = {
5125 +       .d_revalidate   = aufs_d_revalidate,
5126 +       .d_release      = aufs_d_release
5127 +};
5128 diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
5129 --- /usr/share/empty/fs/aufs/dentry.h   1970-01-01 01:00:00.000000000 +0100
5130 +++ linux/fs/aufs/dentry.h      2010-10-21 09:52:43.086957936 +0200
5131 @@ -0,0 +1,231 @@
5132 +/*
5133 + * Copyright (C) 2005-2010 Junjiro R. Okajima
5134 + *
5135 + * This program, aufs is free software; you can redistribute it and/or modify
5136 + * it under the terms of the GNU General Public License as published by
5137 + * the Free Software Foundation; either version 2 of the License, or
5138 + * (at your option) any later version.
5139 + *
5140 + * This program is distributed in the hope that it will be useful,
5141 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5142 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5143 + * GNU General Public License for more details.
5144 + *
5145 + * You should have received a copy of the GNU General Public License
5146 + * along with this program; if not, write to the Free Software
5147 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
5148 + */
5149 +
5150 +/*
5151 + * lookup and dentry operations
5152 + */
5153 +
5154 +#ifndef __AUFS_DENTRY_H__
5155 +#define __AUFS_DENTRY_H__
5156 +
5157 +#ifdef __KERNEL__
5158 +
5159 +#include <linux/dcache.h>
5160 +#include <linux/aufs_type.h>
5161 +#include "rwsem.h"
5162 +
5163 +/* make a single member structure for future use */
5164 +/* todo: remove this structure */
5165 +struct au_hdentry {
5166 +       struct dentry           *hd_dentry;
5167 +};
5168 +
5169 +struct au_dinfo {
5170 +       atomic_t                di_generation;
5171 +
5172 +       struct au_rwsem         di_rwsem;
5173 +       aufs_bindex_t           di_bstart, di_bend, di_bwh, di_bdiropq;
5174 +       struct au_hdentry       *di_hdentry;
5175 +} ____cacheline_aligned_in_smp;
5176 +
5177 +/* ---------------------------------------------------------------------- */
5178 +
5179 +/* dentry.c */
5180 +extern const struct dentry_operations aufs_dop;
5181 +struct au_branch;
5182 +struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
5183 +                          struct au_branch *br, struct nameidata *nd);
5184 +struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
5185 +                              struct au_branch *br);
5186 +int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
5187 +               struct dentry *h_parent, struct au_branch *br);
5188 +
5189 +int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
5190 +                  struct nameidata *nd);
5191 +int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
5192 +int au_refresh_hdentry(struct dentry *dentry, mode_t type);
5193 +int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
5194 +
5195 +/* dinfo.c */
5196 +void au_di_init_once(void *_di);
5197 +int au_di_init(struct dentry *dentry);
5198 +void au_di_fin(struct dentry *dentry);
5199 +int au_di_realloc(struct au_dinfo *dinfo, int nbr);
5200 +
5201 +void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
5202 +void di_read_unlock(struct dentry *d, int flags);
5203 +void di_downgrade_lock(struct dentry *d, int flags);
5204 +void di_write_lock(struct dentry *d, unsigned int lsc);
5205 +void di_write_unlock(struct dentry *d);
5206 +void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
5207 +void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
5208 +void di_write_unlock2(struct dentry *d1, struct dentry *d2);
5209 +
5210 +struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
5211 +aufs_bindex_t au_dbtail(struct dentry *dentry);
5212 +aufs_bindex_t au_dbtaildir(struct dentry *dentry);
5213 +
5214 +void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5215 +                  struct dentry *h_dentry);
5216 +void au_update_digen(struct dentry *dentry);
5217 +void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5218 +void au_update_dbstart(struct dentry *dentry);
5219 +void au_update_dbend(struct dentry *dentry);
5220 +int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
5221 +
5222 +/* ---------------------------------------------------------------------- */
5223 +
5224 +static inline struct au_dinfo *au_di(struct dentry *dentry)
5225 +{
5226 +       return dentry->d_fsdata;
5227 +}
5228 +
5229 +/* ---------------------------------------------------------------------- */
5230 +
5231 +/* lock subclass for dinfo */
5232 +enum {
5233 +       AuLsc_DI_CHILD,         /* child first */
5234 +       AuLsc_DI_CHILD2,        /* rename(2), link(2), and cpup at hnotify */
5235 +       AuLsc_DI_CHILD3,        /* copyup dirs */
5236 +       AuLsc_DI_PARENT,
5237 +       AuLsc_DI_PARENT2,
5238 +       AuLsc_DI_PARENT3
5239 +};
5240 +
5241 +/*
5242 + * di_read_lock_child, di_write_lock_child,
5243 + * di_read_lock_child2, di_write_lock_child2,
5244 + * di_read_lock_child3, di_write_lock_child3,
5245 + * di_read_lock_parent, di_write_lock_parent,
5246 + * di_read_lock_parent2, di_write_lock_parent2,
5247 + * di_read_lock_parent3, di_write_lock_parent3,
5248 + */
5249 +#define AuReadLockFunc(name, lsc) \
5250 +static inline void di_read_lock_##name(struct dentry *d, int flags) \
5251 +{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
5252 +
5253 +#define AuWriteLockFunc(name, lsc) \
5254 +static inline void di_write_lock_##name(struct dentry *d) \
5255 +{ di_write_lock(d, AuLsc_DI_##lsc); }
5256 +
5257 +#define AuRWLockFuncs(name, lsc) \
5258 +       AuReadLockFunc(name, lsc) \
5259 +       AuWriteLockFunc(name, lsc)
5260 +
5261 +AuRWLockFuncs(child, CHILD);
5262 +AuRWLockFuncs(child2, CHILD2);
5263 +AuRWLockFuncs(child3, CHILD3);
5264 +AuRWLockFuncs(parent, PARENT);
5265 +AuRWLockFuncs(parent2, PARENT2);
5266 +AuRWLockFuncs(parent3, PARENT3);
5267 +
5268 +#undef AuReadLockFunc
5269 +#undef AuWriteLockFunc
5270 +#undef AuRWLockFuncs
5271 +
5272 +#define DiMustNoWaiters(d)     AuRwMustNoWaiters(&au_di(d)->di_rwsem)
5273 +#define DiMustAnyLock(d)       AuRwMustAnyLock(&au_di(d)->di_rwsem)
5274 +#define DiMustWriteLock(d)     AuRwMustWriteLock(&au_di(d)->di_rwsem)
5275 +
5276 +/* ---------------------------------------------------------------------- */
5277 +
5278 +/* todo: memory barrier? */
5279 +static inline unsigned int au_digen(struct dentry *d)
5280 +{
5281 +       return atomic_read(&au_di(d)->di_generation);
5282 +}
5283 +
5284 +static inline void au_h_dentry_init(struct au_hdentry *hdentry)
5285 +{
5286 +       hdentry->hd_dentry = NULL;
5287 +}
5288 +
5289 +static inline void au_hdput(struct au_hdentry *hd)
5290 +{
5291 +       if (hd)
5292 +               dput(hd->hd_dentry);
5293 +}
5294 +
5295 +static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
5296 +{
5297 +       DiMustAnyLock(dentry);
5298 +       return au_di(dentry)->di_bstart;
5299 +}
5300 +
5301 +static inline aufs_bindex_t au_dbend(struct dentry *dentry)
5302 +{
5303 +       DiMustAnyLock(dentry);
5304 +       return au_di(dentry)->di_bend;
5305 +}
5306 +
5307 +static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
5308 +{
5309 +       DiMustAnyLock(dentry);
5310 +       return au_di(dentry)->di_bwh;
5311 +}
5312 +
5313 +static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
5314 +{
5315 +       DiMustAnyLock(dentry);
5316 +       return au_di(dentry)->di_bdiropq;
5317 +}
5318 +
5319 +/* todo: hard/soft set? */
5320 +static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
5321 +{
5322 +       DiMustWriteLock(dentry);
5323 +       au_di(dentry)->di_bstart = bindex;
5324 +}
5325 +
5326 +static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
5327 +{
5328 +       DiMustWriteLock(dentry);
5329 +       au_di(dentry)->di_bend = bindex;
5330 +}
5331 +
5332 +static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
5333 +{
5334 +       DiMustWriteLock(dentry);
5335 +       /* dbwh can be outside of bstart - bend range */
5336 +       au_di(dentry)->di_bwh = bindex;
5337 +}
5338 +
5339 +static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
5340 +{
5341 +       DiMustWriteLock(dentry);
5342 +       au_di(dentry)->di_bdiropq = bindex;
5343 +}
5344 +
5345 +/* ---------------------------------------------------------------------- */
5346 +
5347 +#ifdef CONFIG_AUFS_HNOTIFY
5348 +static inline void au_digen_dec(struct dentry *d)
5349 +{
5350 +       atomic_dec_return(&au_di(d)->di_generation);
5351 +}
5352 +
5353 +static inline void au_hn_di_reinit(struct dentry *dentry)
5354 +{
5355 +       dentry->d_fsdata = NULL;
5356 +}
5357 +#else
5358 +AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
5359 +#endif /* CONFIG_AUFS_HNOTIFY */
5360 +
5361 +#endif /* __KERNEL__ */
5362 +#endif /* __AUFS_DENTRY_H__ */
5363 diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
5364 --- /usr/share/empty/fs/aufs/dinfo.c    1970-01-01 01:00:00.000000000 +0100
5365 +++ linux/fs/aufs/dinfo.c       2010-10-21 09:52:43.086957936 +0200
5366 @@ -0,0 +1,395 @@
5367 +/*
5368 + * Copyright (C) 2005-2010 Junjiro R. Okajima
5369 + *
5370 + * This program, aufs is free software; you can redistribute it and/or modify
5371 + * it under the terms of the GNU General Public License as published by
5372 + * the Free Software Foundation; either version 2 of the License, or
5373 + * (at your option) any later version.
5374 + *
5375 + * This program is distributed in the hope that it will be useful,
5376 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5377 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5378 + * GNU General Public License for more details.
5379 + *
5380 + * You should have received a copy of the GNU General Public License
5381 + * along with this program; if not, write to the Free Software
5382 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
5383 + */
5384 +
5385 +/*
5386 + * dentry private data
5387 + */
5388 +
5389 +#include "aufs.h"
5390 +
5391 +void au_di_init_once(void *_di)
5392 +{
5393 +       struct au_dinfo *di = _di;
5394 +
5395 +       au_rw_init(&di->di_rwsem);
5396 +}
5397 +
5398 +int au_di_init(struct dentry *dentry)
5399 +{
5400 +       struct au_dinfo *dinfo;
5401 +       struct super_block *sb;
5402 +       int nbr;
5403 +
5404 +       dinfo = au_cache_alloc_dinfo();
5405 +       if (unlikely(!dinfo))
5406 +               goto out;
5407 +
5408 +       sb = dentry->d_sb;
5409 +       nbr = au_sbend(sb) + 1;
5410 +       if (nbr <= 0)
5411 +               nbr = 1;
5412 +       dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
5413 +       if (unlikely(!dinfo->di_hdentry))
5414 +               goto out_dinfo;
5415 +
5416 +       atomic_set(&dinfo->di_generation, au_sigen(sb));
5417 +       /* smp_mb(); */ /* atomic_set */
5418 +       au_rw_write_lock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
5419 +       dinfo->di_bstart = -1;
5420 +       dinfo->di_bend = -1;
5421 +       dinfo->di_bwh = -1;
5422 +       dinfo->di_bdiropq = -1;
5423 +
5424 +       dentry->d_fsdata = dinfo;
5425 +       dentry->d_op = &aufs_dop;
5426 +       return 0; /* success */
5427 +
5428 +out_dinfo:
5429 +       au_cache_free_dinfo(dinfo);
5430 +out:
5431 +       return -ENOMEM;
5432 +}
5433 +
5434 +void au_di_fin(struct dentry *dentry)
5435 +{
5436 +       struct au_dinfo *di;
5437 +       struct au_hdentry *p;
5438 +       aufs_bindex_t bend, bindex;
5439 +
5440 +       /* dentry may not be revalidated */
5441 +       di = dentry->d_fsdata;
5442 +       bindex = di->di_bstart;
5443 +       if (bindex >= 0) {
5444 +               bend = di->di_bend;
5445 +               p = di->di_hdentry + bindex;
5446 +               while (bindex++ <= bend)
5447 +                       au_hdput(p++);
5448 +       }
5449 +       kfree(di->di_hdentry);
5450 +       AuRwDestroy(&di->di_rwsem);
5451 +       au_cache_free_dinfo(di);
5452 +}
5453 +
5454 +int au_di_realloc(struct au_dinfo *dinfo, int nbr)
5455 +{
5456 +       int err, sz;
5457 +       struct au_hdentry *hdp;
5458 +
5459 +       AuRwMustWriteLock(&dinfo->di_rwsem);
5460 +
5461 +       err = -ENOMEM;
5462 +       sz = sizeof(*hdp) * (dinfo->di_bend + 1);
5463 +       if (!sz)
5464 +               sz = sizeof(*hdp);
5465 +       hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
5466 +       if (hdp) {
5467 +               dinfo->di_hdentry = hdp;
5468 +               err = 0;
5469 +       }
5470 +
5471 +       return err;
5472 +}
5473 +
5474 +/* ---------------------------------------------------------------------- */
5475 +
5476 +static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
5477 +{
5478 +       switch (lsc) {
5479 +       case AuLsc_DI_CHILD:
5480 +               ii_write_lock_child(inode);
5481 +               break;
5482 +       case AuLsc_DI_CHILD2:
5483 +               ii_write_lock_child2(inode);
5484 +               break;
5485 +       case AuLsc_DI_CHILD3:
5486 +               ii_write_lock_child3(inode);
5487 +               break;
5488 +       case AuLsc_DI_PARENT:
5489 +               ii_write_lock_parent(inode);
5490 +               break;
5491 +       case AuLsc_DI_PARENT2:
5492 +               ii_write_lock_parent2(inode);
5493 +               break;
5494 +       case AuLsc_DI_PARENT3:
5495 +               ii_write_lock_parent3(inode);
5496 +               break;
5497 +       default:
5498 +               BUG();
5499 +       }
5500 +}
5501 +
5502 +static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
5503 +{
5504 +       switch (lsc) {
5505 +       case AuLsc_DI_CHILD:
5506 +               ii_read_lock_child(inode);
5507 +               break;
5508 +       case AuLsc_DI_CHILD2:
5509 +               ii_read_lock_child2(inode);
5510 +               break;
5511 +       case AuLsc_DI_CHILD3:
5512 +               ii_read_lock_child3(inode);
5513 +               break;
5514 +       case AuLsc_DI_PARENT:
5515 +               ii_read_lock_parent(inode);
5516 +               break;
5517 +       case AuLsc_DI_PARENT2:
5518 +               ii_read_lock_parent2(inode);
5519 +               break;
5520 +       case AuLsc_DI_PARENT3:
5521 +               ii_read_lock_parent3(inode);
5522 +               break;
5523 +       default:
5524 +               BUG();
5525 +       }
5526 +}
5527 +
5528 +void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
5529 +{
5530 +       au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
5531 +       if (d->d_inode) {
5532 +               if (au_ftest_lock(flags, IW))
5533 +                       do_ii_write_lock(d->d_inode, lsc);
5534 +               else if (au_ftest_lock(flags, IR))
5535 +                       do_ii_read_lock(d->d_inode, lsc);
5536 +       }
5537 +}
5538 +
5539 +void di_read_unlock(struct dentry *d, int flags)
5540 +{
5541 +       if (d->d_inode) {
5542 +               if (au_ftest_lock(flags, IW))
5543 +                       ii_write_unlock(d->d_inode);
5544 +               else if (au_ftest_lock(flags, IR))
5545 +                       ii_read_unlock(d->d_inode);
5546 +       }
5547 +       au_rw_read_unlock(&au_di(d)->di_rwsem);
5548 +}
5549 +
5550 +void di_downgrade_lock(struct dentry *d, int flags)
5551 +{
5552 +       if (d->d_inode && au_ftest_lock(flags, IR))
5553 +               ii_downgrade_lock(d->d_inode);
5554 +       au_rw_dgrade_lock(&au_di(d)->di_rwsem);
5555 +}
5556 +
5557 +void di_write_lock(struct dentry *d, unsigned int lsc)
5558 +{
5559 +       au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
5560 +       if (d->d_inode)
5561 +               do_ii_write_lock(d->d_inode, lsc);
5562 +}
5563 +
5564 +void di_write_unlock(struct dentry *d)
5565 +{
5566 +       if (d->d_inode)
5567 +               ii_write_unlock(d->d_inode);
5568 +       au_rw_write_unlock(&au_di(d)->di_rwsem);
5569 +}
5570 +
5571 +void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
5572 +{
5573 +       AuDebugOn(d1 == d2
5574 +                 || d1->d_inode == d2->d_inode
5575 +                 || d1->d_sb != d2->d_sb);
5576 +
5577 +       if (isdir && au_test_subdir(d1, d2)) {
5578 +               di_write_lock_child(d1);
5579 +               di_write_lock_child2(d2);
5580 +       } else {
5581 +               /* there should be no races */
5582 +               di_write_lock_child(d2);
5583 +               di_write_lock_child2(d1);
5584 +       }
5585 +}
5586 +
5587 +void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
5588 +{
5589 +       AuDebugOn(d1 == d2
5590 +                 || d1->d_inode == d2->d_inode
5591 +                 || d1->d_sb != d2->d_sb);
5592 +
5593 +       if (isdir && au_test_subdir(d1, d2)) {
5594 +               di_write_lock_parent(d1);
5595 +               di_write_lock_parent2(d2);
5596 +       } else {
5597 +               /* there should be no races */
5598 +               di_write_lock_parent(d2);
5599 +               di_write_lock_parent2(d1);
5600 +       }
5601 +}
5602 +
5603 +void di_write_unlock2(struct dentry *d1, struct dentry *d2)
5604 +{
5605 +       di_write_unlock(d1);
5606 +       if (d1->d_inode == d2->d_inode)
5607 +               au_rw_write_unlock(&au_di(d2)->di_rwsem);
5608 +       else
5609 +               di_write_unlock(d2);
5610 +}
5611 +
5612 +/* ---------------------------------------------------------------------- */
5613 +
5614 +struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
5615 +{
5616 +       struct dentry *d;
5617 +
5618 +       DiMustAnyLock(dentry);
5619 +
5620 +       if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
5621 +               return NULL;
5622 +       AuDebugOn(bindex < 0);
5623 +       d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
5624 +       AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
5625 +       return d;
5626 +}
5627 +
5628 +aufs_bindex_t au_dbtail(struct dentry *dentry)
5629 +{
5630 +       aufs_bindex_t bend, bwh;
5631 +
5632 +       bend = au_dbend(dentry);
5633 +       if (0 <= bend) {
5634 +               bwh = au_dbwh(dentry);
5635 +               if (!bwh)
5636 +                       return bwh;
5637 +               if (0 < bwh && bwh < bend)
5638 +                       return bwh - 1;
5639 +       }
5640 +       return bend;
5641 +}
5642 +
5643 +aufs_bindex_t au_dbtaildir(struct dentry *dentry)
5644 +{
5645 +       aufs_bindex_t bend, bopq;
5646 +
5647 +       bend = au_dbtail(dentry);
5648 +       if (0 <= bend) {
5649 +               bopq = au_dbdiropq(dentry);
5650 +               if (0 <= bopq && bopq < bend)
5651 +                       bend = bopq;
5652 +       }
5653 +       return bend;
5654 +}
5655 +
5656 +/* ---------------------------------------------------------------------- */
5657 +
5658 +void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5659 +                  struct dentry *h_dentry)
5660 +{
5661 +       struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
5662 +
5663 +       DiMustWriteLock(dentry);
5664 +
5665 +       au_hdput(hd);
5666 +       hd->hd_dentry = h_dentry;
5667 +}
5668 +
5669 +void au_update_digen(struct dentry *dentry)
5670 +{
5671 +       atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
5672 +       /* smp_mb(); */ /* atomic_set */
5673 +}
5674 +
5675 +void au_update_dbrange(struct dentry *dentry, int do_put_zero)
5676 +{
5677 +       struct au_dinfo *dinfo;
5678 +       struct dentry *h_d;
5679 +       struct au_hdentry *hdp;
5680 +
5681 +       DiMustWriteLock(dentry);
5682 +
5683 +       dinfo = au_di(dentry);
5684 +       if (!dinfo || dinfo->di_bstart < 0)
5685 +               return;
5686 +
5687 +       hdp = dinfo->di_hdentry;
5688 +       if (do_put_zero) {
5689 +               aufs_bindex_t bindex, bend;
5690 +
5691 +               bend = dinfo->di_bend;
5692 +               for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
5693 +                       h_d = hdp[0 + bindex].hd_dentry;
5694 +                       if (h_d && !h_d->d_inode)
5695 +                               au_set_h_dptr(dentry, bindex, NULL);
5696 +               }
5697 +       }
5698 +
5699 +       dinfo->di_bstart = -1;
5700 +       while (++dinfo->di_bstart <= dinfo->di_bend)
5701 +               if (hdp[0 + dinfo->di_bstart].hd_dentry)
5702 +                       break;
5703 +       if (dinfo->di_bstart > dinfo->di_bend) {
5704 +               dinfo->di_bstart = -1;
5705 +               dinfo->di_bend = -1;
5706 +               return;
5707 +       }
5708 +
5709 +       dinfo->di_bend++;
5710 +       while (0 <= --dinfo->di_bend)
5711 +               if (hdp[0 + dinfo->di_bend].hd_dentry)
5712 +                       break;
5713 +       AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
5714 +}
5715 +
5716 +void au_update_dbstart(struct dentry *dentry)
5717 +{
5718 +       aufs_bindex_t bindex, bend;
5719 +       struct dentry *h_dentry;
5720 +
5721 +       bend = au_dbend(dentry);
5722 +       for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
5723 +               h_dentry = au_h_dptr(dentry, bindex);
5724 +               if (!h_dentry)
5725 +                       continue;
5726 +               if (h_dentry->d_inode) {
5727 +                       au_set_dbstart(dentry, bindex);
5728 +                       return;
5729 +               }
5730 +               au_set_h_dptr(dentry, bindex, NULL);
5731 +       }
5732 +}
5733 +
5734 +void au_update_dbend(struct dentry *dentry)
5735 +{
5736 +       aufs_bindex_t bindex, bstart;
5737 +       struct dentry *h_dentry;
5738 +
5739 +       bstart = au_dbstart(dentry);
5740 +       for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
5741 +               h_dentry = au_h_dptr(dentry, bindex);
5742 +               if (!h_dentry)
5743 +                       continue;
5744 +               if (h_dentry->d_inode) {
5745 +                       au_set_dbend(dentry, bindex);
5746 +                       return;
5747 +               }
5748 +               au_set_h_dptr(dentry, bindex, NULL);
5749 +       }
5750 +}
5751 +
5752 +int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
5753 +{
5754 +       aufs_bindex_t bindex, bend;
5755 +
5756 +       bend = au_dbend(dentry);
5757 +       for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
5758 +               if (au_h_dptr(dentry, bindex) == h_dentry)
5759 +                       return bindex;
5760 +       return -1;
5761 +}
5762 diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
5763 --- /usr/share/empty/fs/aufs/dir.c      1970-01-01 01:00:00.000000000 +0100
5764 +++ linux/fs/aufs/dir.c 2010-10-21 09:52:43.086957936 +0200
5765 @@ -0,0 +1,638 @@
5766 +/*
5767 + * Copyright (C) 2005-2010 Junjiro R. Okajima
5768 + *
5769 + * This program, aufs is free software; you can redistribute it and/or modify
5770 + * it under the terms of the GNU General Public License as published by
5771 + * the Free Software Foundation; either version 2 of the License, or
5772 + * (at your option) any later version.
5773 + *
5774 + * This program is distributed in the hope that it will be useful,
5775 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5776 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5777 + * GNU General Public License for more details.
5778 + *
5779 + * You should have received a copy of the GNU General Public License
5780 + * along with this program; if not, write to the Free Software
5781 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
5782 + */
5783 +
5784 +/*
5785 + * directory operations
5786 + */
5787 +
5788 +#include <linux/file.h>
5789 +#include <linux/fs_stack.h>
5790 +#include "aufs.h"
5791 +
5792 +void au_add_nlink(struct inode *dir, struct inode *h_dir)
5793 +{
5794 +       AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5795 +
5796 +       dir->i_nlink += h_dir->i_nlink - 2;
5797 +       if (h_dir->i_nlink < 2)
5798 +               dir->i_nlink += 2;
5799 +}
5800 +
5801 +void au_sub_nlink(struct inode *dir, struct inode *h_dir)
5802 +{
5803 +       AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5804 +
5805 +       dir->i_nlink -= h_dir->i_nlink - 2;
5806 +       if (h_dir->i_nlink < 2)
5807 +               dir->i_nlink -= 2;
5808 +}
5809 +
5810 +loff_t au_dir_size(struct file *file, struct dentry *dentry)
5811 +{
5812 +       loff_t sz;
5813 +       aufs_bindex_t bindex, bend;
5814 +       struct file *h_file;
5815 +       struct dentry *h_dentry;
5816 +
5817 +       sz = 0;
5818 +       if (file) {
5819 +               AuDebugOn(!file->f_dentry);
5820 +               AuDebugOn(!file->f_dentry->d_inode);
5821 +               AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
5822 +
5823 +               bend = au_fbend_dir(file);
5824 +               for (bindex = au_fbstart(file);
5825 +                    bindex <= bend && sz < KMALLOC_MAX_SIZE;
5826 +                    bindex++) {
5827 +                       h_file = au_hf_dir(file, bindex);
5828 +                       if (h_file
5829 +                           && h_file->f_dentry
5830 +                           && h_file->f_dentry->d_inode)
5831 +                               sz += i_size_read(h_file->f_dentry->d_inode);
5832 +               }
5833 +       } else {
5834 +               AuDebugOn(!dentry);
5835 +               AuDebugOn(!dentry->d_inode);
5836 +               AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
5837 +
5838 +               bend = au_dbtaildir(dentry);
5839 +               for (bindex = au_dbstart(dentry);
5840 +                    bindex <= bend && sz < KMALLOC_MAX_SIZE;
5841 +                    bindex++) {
5842 +                       h_dentry = au_h_dptr(dentry, bindex);
5843 +                       if (h_dentry && h_dentry->d_inode)
5844 +                               sz += i_size_read(h_dentry->d_inode);
5845 +               }
5846 +       }
5847 +       if (sz < KMALLOC_MAX_SIZE)
5848 +               sz = roundup_pow_of_two(sz);
5849 +       if (sz > KMALLOC_MAX_SIZE)
5850 +               sz = KMALLOC_MAX_SIZE;
5851 +       else if (sz < NAME_MAX) {
5852 +               BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
5853 +               sz = AUFS_RDBLK_DEF;
5854 +       }
5855 +       return sz;
5856 +}
5857 +
5858 +/* ---------------------------------------------------------------------- */
5859 +
5860 +static int reopen_dir(struct file *file)
5861 +{
5862 +       int err;
5863 +       unsigned int flags;
5864 +       aufs_bindex_t bindex, btail, bstart;
5865 +       struct dentry *dentry, *h_dentry;
5866 +       struct file *h_file;
5867 +
5868 +       /* open all lower dirs */
5869 +       dentry = file->f_dentry;
5870 +       bstart = au_dbstart(dentry);
5871 +       for (bindex = au_fbstart(file); bindex < bstart; bindex++)
5872 +               au_set_h_fptr(file, bindex, NULL);
5873 +       au_set_fbstart(file, bstart);
5874 +
5875 +       btail = au_dbtaildir(dentry);
5876 +       for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
5877 +               au_set_h_fptr(file, bindex, NULL);
5878 +       au_set_fbend_dir(file, btail);
5879 +
5880 +       flags = vfsub_file_flags(file);
5881 +       for (bindex = bstart; bindex <= btail; bindex++) {
5882 +               h_dentry = au_h_dptr(dentry, bindex);
5883 +               if (!h_dentry)
5884 +                       continue;
5885 +               h_file = au_hf_dir(file, bindex);
5886 +               if (h_file)
5887 +                       continue;
5888 +
5889 +               h_file = au_h_open(dentry, bindex, flags, file);
5890 +               err = PTR_ERR(h_file);
5891 +               if (IS_ERR(h_file))
5892 +                       goto out; /* close all? */
5893 +               au_set_h_fptr(file, bindex, h_file);
5894 +       }
5895 +       au_update_figen(file);
5896 +       /* todo: necessary? */
5897 +       /* file->f_ra = h_file->f_ra; */
5898 +       err = 0;
5899 +
5900 +out:
5901 +       return err;
5902 +}
5903 +
5904 +static int do_open_dir(struct file *file, int flags)
5905 +{
5906 +       int err;
5907 +       aufs_bindex_t bindex, btail;
5908 +       struct dentry *dentry, *h_dentry;
5909 +       struct file *h_file;
5910 +
5911 +       FiMustWriteLock(file);
5912 +
5913 +       err = 0;
5914 +       dentry = file->f_dentry;
5915 +       file->f_version = dentry->d_inode->i_version;
5916 +       bindex = au_dbstart(dentry);
5917 +       au_set_fbstart(file, bindex);
5918 +       btail = au_dbtaildir(dentry);
5919 +       au_set_fbend_dir(file, btail);
5920 +       for (; !err && bindex <= btail; bindex++) {
5921 +               h_dentry = au_h_dptr(dentry, bindex);
5922 +               if (!h_dentry)
5923 +                       continue;
5924 +
5925 +               h_file = au_h_open(dentry, bindex, flags, file);
5926 +               if (IS_ERR(h_file)) {
5927 +                       err = PTR_ERR(h_file);
5928 +                       break;
5929 +               }
5930 +               au_set_h_fptr(file, bindex, h_file);
5931 +       }
5932 +       au_update_figen(file);
5933 +       /* todo: necessary? */
5934 +       /* file->f_ra = h_file->f_ra; */
5935 +       if (!err)
5936 +               return 0; /* success */
5937 +
5938 +       /* close all */
5939 +       for (bindex = au_fbstart(file); bindex <= btail; bindex++)
5940 +               au_set_h_fptr(file, bindex, NULL);
5941 +       au_set_fbstart(file, -1);
5942 +       au_set_fbend_dir(file, -1);
5943 +
5944 +       return err;
5945 +}
5946 +
5947 +static int aufs_open_dir(struct inode *inode __maybe_unused,
5948 +                        struct file *file)
5949 +{
5950 +       int err;
5951 +       struct super_block *sb;
5952 +       struct au_fidir *fidir;
5953 +
5954 +       err = -ENOMEM;
5955 +       sb = file->f_dentry->d_sb;
5956 +       si_read_lock(sb, AuLock_FLUSH);
5957 +       fidir = au_fidir_alloc(inode->i_sb);
5958 +       if (fidir) {
5959 +               err = au_do_open(file, do_open_dir, fidir);
5960 +               if (unlikely(err))
5961 +                       kfree(fidir);
5962 +       }
5963 +       si_read_unlock(sb);
5964 +       return err;
5965 +}
5966 +
5967 +static int aufs_release_dir(struct inode *inode __maybe_unused,
5968 +                           struct file *file)
5969 +{
5970 +       struct au_vdir *vdir_cache;
5971 +       struct super_block *sb;
5972 +       struct au_finfo *finfo;
5973 +       struct au_fidir *fidir;
5974 +       aufs_bindex_t bindex, bend;
5975 +
5976 +       au_plink_maint_leave(file);
5977 +       sb = file->f_dentry->d_sb;
5978 +       finfo = au_fi(file);
5979 +       fidir = finfo->fi_hdir;
5980 +       if (fidir) {
5981 +               vdir_cache = fidir->fd_vdir_cache; /* lock-free */
5982 +               if (vdir_cache)
5983 +                       au_vdir_free(vdir_cache);
5984 +
5985 +               bindex = finfo->fi_btop;
5986 +               if (bindex >= 0) {
5987 +                       /*
5988 +                        * calls fput() instead of filp_close(),
5989 +                        * since no dnotify or lock for the lower file.
5990 +                        */
5991 +                       bend = fidir->fd_bbot;
5992 +                       for (; bindex <= bend; bindex++)
5993 +                               au_set_h_fptr(file, bindex, NULL);
5994 +               }
5995 +               kfree(fidir);
5996 +               finfo->fi_hdir = NULL;
5997 +       }
5998 +       au_finfo_fin(file);
5999 +       return 0;
6000 +}
6001 +
6002 +/* ---------------------------------------------------------------------- */
6003 +
6004 +static int au_do_flush_dir(struct file *file, fl_owner_t id)
6005 +{
6006 +       int err;
6007 +       aufs_bindex_t bindex, bend;
6008 +       struct file *h_file;
6009 +
6010 +       err = 0;
6011 +       bend = au_fbend_dir(file);
6012 +       for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
6013 +               h_file = au_hf_dir(file, bindex);
6014 +               if (h_file)
6015 +                       err = vfsub_flush(h_file, id);
6016 +       }
6017 +       return err;
6018 +}
6019 +
6020 +static int aufs_flush_dir(struct file *file, fl_owner_t id)
6021 +{
6022 +       return au_do_flush(file, id, au_do_flush_dir);
6023 +}
6024 +
6025 +/* ---------------------------------------------------------------------- */
6026 +
6027 +static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
6028 +{
6029 +       int err;
6030 +       aufs_bindex_t bend, bindex;
6031 +       struct inode *inode;
6032 +       struct super_block *sb;
6033 +
6034 +       err = 0;
6035 +       sb = dentry->d_sb;
6036 +       inode = dentry->d_inode;
6037 +       IMustLock(inode);
6038 +       bend = au_dbend(dentry);
6039 +       for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
6040 +               struct path h_path;
6041 +               struct inode *h_inode;
6042 +
6043 +               if (au_test_ro(sb, bindex, inode))
6044 +                       continue;
6045 +               h_path.dentry = au_h_dptr(dentry, bindex);
6046 +               if (!h_path.dentry)
6047 +                       continue;
6048 +               h_inode = h_path.dentry->d_inode;
6049 +               if (!h_inode)
6050 +                       continue;
6051 +
6052 +               /* no mnt_want_write() */
6053 +               /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
6054 +               /* todo: inotiry fired? */
6055 +               h_path.mnt = au_sbr_mnt(sb, bindex);
6056 +               mutex_lock(&h_inode->i_mutex);
6057 +               err = filemap_fdatawrite(h_inode->i_mapping);
6058 +               AuDebugOn(!h_inode->i_fop);
6059 +               if (!err && h_inode->i_fop->fsync)
6060 +                       err = h_inode->i_fop->fsync(NULL, datasync);
6061 +               if (!err)
6062 +                       err = filemap_fdatawrite(h_inode->i_mapping);
6063 +               if (!err)
6064 +                       vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
6065 +               mutex_unlock(&h_inode->i_mutex);
6066 +       }
6067 +
6068 +       return err;
6069 +}
6070 +
6071 +static int au_do_fsync_dir(struct file *file, int datasync)
6072 +{
6073 +       int err;
6074 +       aufs_bindex_t bend, bindex;
6075 +       struct file *h_file;
6076 +       struct super_block *sb;
6077 +       struct inode *inode;
6078 +       struct mutex *h_mtx;
6079 +
6080 +       err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6081 +       if (unlikely(err))
6082 +               goto out;
6083 +
6084 +       sb = file->f_dentry->d_sb;
6085 +       inode = file->f_dentry->d_inode;
6086 +       bend = au_fbend_dir(file);
6087 +       for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
6088 +               h_file = au_hf_dir(file, bindex);
6089 +               if (!h_file || au_test_ro(sb, bindex, inode))
6090 +                       continue;
6091 +
6092 +               err = vfs_fsync(h_file, datasync);
6093 +               if (!err) {
6094 +                       h_mtx = &h_file->f_dentry->d_inode->i_mutex;
6095 +                       mutex_lock(h_mtx);
6096 +                       vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
6097 +                       /*ignore*/
6098 +                       mutex_unlock(h_mtx);
6099 +               }
6100 +       }
6101 +
6102 +out:
6103 +       return err;
6104 +}
6105 +
6106 +/*
6107 + * @file may be NULL
6108 + */
6109 +static int aufs_fsync_dir(struct file *file, int datasync)
6110 +{
6111 +       int err;
6112 +       struct dentry *dentry;
6113 +       struct super_block *sb;
6114 +
6115 +       dentry = file->f_dentry;
6116 +       IMustLock(dentry->d_inode);
6117 +
6118 +       err = 0;
6119 +       sb = dentry->d_sb;
6120 +       si_noflush_read_lock(sb);
6121 +       if (file)
6122 +               err = au_do_fsync_dir(file, datasync);
6123 +       else {
6124 +               di_write_lock_child(dentry);
6125 +               err = au_do_fsync_dir_no_file(dentry, datasync);
6126 +       }
6127 +       au_cpup_attr_timesizes(dentry->d_inode);
6128 +       di_write_unlock(dentry);
6129 +       if (file)
6130 +               fi_write_unlock(file);
6131 +
6132 +       si_read_unlock(sb);
6133 +       return err;
6134 +}
6135 +
6136 +/* ---------------------------------------------------------------------- */
6137 +
6138 +static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
6139 +{
6140 +       int err;
6141 +       struct dentry *dentry;
6142 +       struct inode *inode;
6143 +       struct super_block *sb;
6144 +
6145 +       dentry = file->f_dentry;
6146 +       inode = dentry->d_inode;
6147 +       IMustLock(inode);
6148 +
6149 +       sb = dentry->d_sb;
6150 +       si_read_lock(sb, AuLock_FLUSH);
6151 +       err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6152 +       if (unlikely(err))
6153 +               goto out;
6154 +       err = au_vdir_init(file);
6155 +       di_downgrade_lock(dentry, AuLock_IR);
6156 +       if (unlikely(err))
6157 +               goto out_unlock;
6158 +
6159 +       if (!au_test_nfsd()) {
6160 +               err = au_vdir_fill_de(file, dirent, filldir);
6161 +               fsstack_copy_attr_atime(inode,
6162 +                                       au_h_iptr(inode, au_ibstart(inode)));
6163 +       } else {
6164 +               /*
6165 +                * nfsd filldir may call lookup_one_len(), vfs_getattr(),
6166 +                * encode_fh() and others.
6167 +                */
6168 +               struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
6169 +
6170 +               di_read_unlock(dentry, AuLock_IR);
6171 +               si_read_unlock(sb);
6172 +               err = au_vdir_fill_de(file, dirent, filldir);
6173 +               fsstack_copy_attr_atime(inode, h_inode);
6174 +               fi_write_unlock(file);
6175 +
6176 +               AuTraceErr(err);
6177 +               return err;
6178 +       }
6179 +
6180 +out_unlock:
6181 +       di_read_unlock(dentry, AuLock_IR);
6182 +       fi_write_unlock(file);
6183 +out:
6184 +       si_read_unlock(sb);
6185 +       return err;
6186 +}
6187 +
6188 +/* ---------------------------------------------------------------------- */
6189 +
6190 +#define AuTestEmpty_WHONLY     1
6191 +#define AuTestEmpty_CALLED     (1 << 1)
6192 +#define AuTestEmpty_SHWH       (1 << 2)
6193 +#define au_ftest_testempty(flags, name)        ((flags) & AuTestEmpty_##name)
6194 +#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
6195 +#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
6196 +
6197 +#ifndef CONFIG_AUFS_SHWH
6198 +#undef AuTestEmpty_SHWH
6199 +#define AuTestEmpty_SHWH       0
6200 +#endif
6201 +
6202 +struct test_empty_arg {
6203 +       struct au_nhash *whlist;
6204 +       unsigned int flags;
6205 +       int err;
6206 +       aufs_bindex_t bindex;
6207 +};
6208 +
6209 +static int test_empty_cb(void *__arg, const char *__name, int namelen,
6210 +                        loff_t offset __maybe_unused, u64 ino,
6211 +                        unsigned int d_type)
6212 +{
6213 +       struct test_empty_arg *arg = __arg;
6214 +       char *name = (void *)__name;
6215 +
6216 +       arg->err = 0;
6217 +       au_fset_testempty(arg->flags, CALLED);
6218 +       /* smp_mb(); */
6219 +       if (name[0] == '.'
6220 +           && (namelen == 1 || (name[1] == '.' && namelen == 2)))
6221 +               goto out; /* success */
6222 +
6223 +       if (namelen <= AUFS_WH_PFX_LEN
6224 +           || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
6225 +               if (au_ftest_testempty(arg->flags, WHONLY)
6226 +                   && !au_nhash_test_known_wh(arg->whlist, name, namelen))
6227 +                       arg->err = -ENOTEMPTY;
6228 +               goto out;
6229 +       }
6230 +
6231 +       name += AUFS_WH_PFX_LEN;
6232 +       namelen -= AUFS_WH_PFX_LEN;
6233 +       if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
6234 +               arg->err = au_nhash_append_wh
6235 +                       (arg->whlist, name, namelen, ino, d_type, arg->bindex,
6236 +                        au_ftest_testempty(arg->flags, SHWH));
6237 +
6238 +out:
6239 +       /* smp_mb(); */
6240 +       AuTraceErr(arg->err);
6241 +       return arg->err;
6242 +}
6243 +
6244 +static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6245 +{
6246 +       int err;
6247 +       struct file *h_file;
6248 +
6249 +       h_file = au_h_open(dentry, arg->bindex,
6250 +                          O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
6251 +                          /*file*/NULL);
6252 +       err = PTR_ERR(h_file);
6253 +       if (IS_ERR(h_file))
6254 +               goto out;
6255 +
6256 +       err = 0;
6257 +       if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
6258 +           && !h_file->f_dentry->d_inode->i_nlink)
6259 +               goto out_put;
6260 +
6261 +       do {
6262 +               arg->err = 0;
6263 +               au_fclr_testempty(arg->flags, CALLED);
6264 +               /* smp_mb(); */
6265 +               err = vfsub_readdir(h_file, test_empty_cb, arg);
6266 +               if (err >= 0)
6267 +                       err = arg->err;
6268 +       } while (!err && au_ftest_testempty(arg->flags, CALLED));
6269 +
6270 +out_put:
6271 +       fput(h_file);
6272 +       au_sbr_put(dentry->d_sb, arg->bindex);
6273 +out:
6274 +       return err;
6275 +}
6276 +
6277 +struct do_test_empty_args {
6278 +       int *errp;
6279 +       struct dentry *dentry;
6280 +       struct test_empty_arg *arg;
6281 +};
6282 +
6283 +static void call_do_test_empty(void *args)
6284 +{
6285 +       struct do_test_empty_args *a = args;
6286 +       *a->errp = do_test_empty(a->dentry, a->arg);
6287 +}
6288 +
6289 +static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6290 +{
6291 +       int err, wkq_err;
6292 +       struct dentry *h_dentry;
6293 +       struct inode *h_inode;
6294 +
6295 +       h_dentry = au_h_dptr(dentry, arg->bindex);
6296 +       h_inode = h_dentry->d_inode;
6297 +       mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
6298 +       err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
6299 +       mutex_unlock(&h_inode->i_mutex);
6300 +       if (!err)
6301 +               err = do_test_empty(dentry, arg);
6302 +       else {
6303 +               struct do_test_empty_args args = {
6304 +                       .errp   = &err,
6305 +                       .dentry = dentry,
6306 +                       .arg    = arg
6307 +               };
6308 +               unsigned int flags = arg->flags;
6309 +
6310 +               wkq_err = au_wkq_wait(call_do_test_empty, &args);
6311 +               if (unlikely(wkq_err))
6312 +                       err = wkq_err;
6313 +               arg->flags = flags;
6314 +       }
6315 +
6316 +       return err;
6317 +}
6318 +
6319 +int au_test_empty_lower(struct dentry *dentry)
6320 +{
6321 +       int err;
6322 +       unsigned int rdhash;
6323 +       aufs_bindex_t bindex, bstart, btail;
6324 +       struct au_nhash whlist;
6325 +       struct test_empty_arg arg;
6326 +
6327 +       SiMustAnyLock(dentry->d_sb);
6328 +
6329 +       rdhash = au_sbi(dentry->d_sb)->si_rdhash;
6330 +       if (!rdhash)
6331 +               rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
6332 +       err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
6333 +       if (unlikely(err))
6334 +               goto out;
6335 +
6336 +       arg.flags = 0;
6337 +       arg.whlist = &whlist;
6338 +       bstart = au_dbstart(dentry);
6339 +       if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6340 +               au_fset_testempty(arg.flags, SHWH);
6341 +       arg.bindex = bstart;
6342 +       err = do_test_empty(dentry, &arg);
6343 +       if (unlikely(err))
6344 +               goto out_whlist;
6345 +
6346 +       au_fset_testempty(arg.flags, WHONLY);
6347 +       btail = au_dbtaildir(dentry);
6348 +       for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
6349 +               struct dentry *h_dentry;
6350 +
6351 +               h_dentry = au_h_dptr(dentry, bindex);
6352 +               if (h_dentry && h_dentry->d_inode) {
6353 +                       arg.bindex = bindex;
6354 +                       err = do_test_empty(dentry, &arg);
6355 +               }
6356 +       }
6357 +
6358 +out_whlist:
6359 +       au_nhash_wh_free(&whlist);
6360 +out:
6361 +       return err;
6362 +}
6363 +
6364 +int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
6365 +{
6366 +       int err;
6367 +       struct test_empty_arg arg;
6368 +       aufs_bindex_t bindex, btail;
6369 +
6370 +       err = 0;
6371 +       arg.whlist = whlist;
6372 +       arg.flags = AuTestEmpty_WHONLY;
6373 +       if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6374 +               au_fset_testempty(arg.flags, SHWH);
6375 +       btail = au_dbtaildir(dentry);
6376 +       for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
6377 +               struct dentry *h_dentry;
6378 +
6379 +               h_dentry = au_h_dptr(dentry, bindex);
6380 +               if (h_dentry && h_dentry->d_inode) {
6381 +                       arg.bindex = bindex;
6382 +                       err = sio_test_empty(dentry, &arg);
6383 +               }
6384 +       }
6385 +
6386 +       return err;
6387 +}
6388 +
6389 +/* ---------------------------------------------------------------------- */
6390 +
6391 +const struct file_operations aufs_dir_fop = {
6392 +       .owner          = THIS_MODULE,
6393 +       .read           = generic_read_dir,
6394 +       .readdir        = aufs_readdir,
6395 +       .unlocked_ioctl = aufs_ioctl_dir,
6396 +#ifdef CONFIG_COMPAT
6397 +       .compat_ioctl   = aufs_compat_ioctl_dir,
6398 +#endif
6399 +       .open           = aufs_open_dir,
6400 +       .release        = aufs_release_dir,
6401 +       .flush          = aufs_flush_dir,
6402 +       .fsync          = aufs_fsync_dir
6403 +};
6404 diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
6405 --- /usr/share/empty/fs/aufs/dir.h      1970-01-01 01:00:00.000000000 +0100
6406 +++ linux/fs/aufs/dir.h 2010-10-21 09:52:43.086957936 +0200
6407 @@ -0,0 +1,138 @@
6408 +/*
6409 + * Copyright (C) 2005-2010 Junjiro R. Okajima
6410 + *
6411 + * This program, aufs is free software; you can redistribute it and/or modify
6412 + * it under the terms of the GNU General Public License as published by
6413 + * the Free Software Foundation; either version 2 of the License, or
6414 + * (at your option) any later version.
6415 + *
6416 + * This program is distributed in the hope that it will be useful,
6417 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6418 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6419 + * GNU General Public License for more details.
6420 + *
6421 + * You should have received a copy of the GNU General Public License
6422 + * along with this program; if not, write to the Free Software
6423 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
6424 + */
6425 +
6426 +/*
6427 + * directory operations
6428 + */
6429 +
6430 +#ifndef __AUFS_DIR_H__
6431 +#define __AUFS_DIR_H__
6432 +
6433 +#ifdef __KERNEL__
6434 +
6435 +#include <linux/fs.h>
6436 +#include <linux/aufs_type.h>
6437 +
6438 +/* ---------------------------------------------------------------------- */
6439 +
6440 +/* need to be faster and smaller */
6441 +
6442 +struct au_nhash {
6443 +       unsigned int            nh_num;
6444 +       struct hlist_head       *nh_head;
6445 +};
6446 +
6447 +struct au_vdir_destr {
6448 +       unsigned char   len;
6449 +       unsigned char   name[0];
6450 +} __packed;
6451 +
6452 +struct au_vdir_dehstr {
6453 +       struct hlist_node       hash;
6454 +       struct au_vdir_destr    *str;
6455 +} ____cacheline_aligned_in_smp;
6456 +
6457 +struct au_vdir_de {
6458 +       ino_t                   de_ino;
6459 +       unsigned char           de_type;
6460 +       /* caution: packed */
6461 +       struct au_vdir_destr    de_str;
6462 +} __packed;
6463 +
6464 +struct au_vdir_wh {
6465 +       struct hlist_node       wh_hash;
6466 +#ifdef CONFIG_AUFS_SHWH
6467 +       ino_t                   wh_ino;
6468 +       aufs_bindex_t           wh_bindex;
6469 +       unsigned char           wh_type;
6470 +#else
6471 +       aufs_bindex_t           wh_bindex;
6472 +#endif
6473 +       /* caution: packed */
6474 +       struct au_vdir_destr    wh_str;
6475 +} __packed;
6476 +
6477 +union au_vdir_deblk_p {
6478 +       unsigned char           *deblk;
6479 +       struct au_vdir_de       *de;
6480 +};
6481 +
6482 +struct au_vdir {
6483 +       unsigned char   **vd_deblk;
6484 +       unsigned long   vd_nblk;
6485 +       struct {
6486 +               unsigned long           ul;
6487 +               union au_vdir_deblk_p   p;
6488 +       } vd_last;
6489 +
6490 +       unsigned long   vd_version;
6491 +       unsigned int    vd_deblk_sz;
6492 +       unsigned long   vd_jiffy;
6493 +} ____cacheline_aligned_in_smp;
6494 +
6495 +/* ---------------------------------------------------------------------- */
6496 +
6497 +/* dir.c */
6498 +extern const struct file_operations aufs_dir_fop;
6499 +void au_add_nlink(struct inode *dir, struct inode *h_dir);
6500 +void au_sub_nlink(struct inode *dir, struct inode *h_dir);
6501 +loff_t au_dir_size(struct file *file, struct dentry *dentry);
6502 +int au_test_empty_lower(struct dentry *dentry);
6503 +int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
6504 +
6505 +/* vdir.c */
6506 +unsigned int au_rdhash_est(loff_t sz);
6507 +int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
6508 +void au_nhash_wh_free(struct au_nhash *whlist);
6509 +int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
6510 +                           int limit);
6511 +int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
6512 +int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
6513 +                      unsigned int d_type, aufs_bindex_t bindex,
6514 +                      unsigned char shwh);
6515 +void au_vdir_free(struct au_vdir *vdir);
6516 +int au_vdir_init(struct file *file);
6517 +int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
6518 +
6519 +/* ioctl.c */
6520 +long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
6521 +
6522 +#ifdef CONFIG_AUFS_RDU
6523 +/* rdu.c */
6524 +long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
6525 +#ifdef CONFIG_COMPAT
6526 +long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6527 +                        unsigned long arg);
6528 +#endif
6529 +#else
6530 +static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
6531 +                               unsigned long arg)
6532 +{
6533 +       return -EINVAL;
6534 +}
6535 +#ifdef CONFIG_COMPAT
6536 +static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6537 +                                      unsigned long arg)
6538 +{
6539 +       return -EINVAL;
6540 +}
6541 +#endif
6542 +#endif
6543 +
6544 +#endif /* __KERNEL__ */
6545 +#endif /* __AUFS_DIR_H__ */
6546 diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
6547 --- /usr/share/empty/fs/aufs/dynop.c    1970-01-01 01:00:00.000000000 +0100
6548 +++ linux/fs/aufs/dynop.c       2010-10-21 09:52:43.086957936 +0200
6549 @@ -0,0 +1,425 @@
6550 +/*
6551 + * Copyright (C) 2010 Junjiro R. Okajima
6552 + *
6553 + * This program, aufs is free software; you can redistribute it and/or modify
6554 + * it under the terms of the GNU General Public License as published by
6555 + * the Free Software Foundation; either version 2 of the License, or
6556 + * (at your option) any later version.
6557 + *
6558 + * This program is distributed in the hope that it will be useful,
6559 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6560 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6561 + * GNU General Public License for more details.
6562 + *
6563 + * You should have received a copy of the GNU General Public License
6564 + * along with this program; if not, write to the Free Software
6565 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
6566 + */
6567 +
6568 +/*
6569 + * dynamically customizable operations for regular files
6570 + */
6571 +
6572 +#include "aufs.h"
6573 +
6574 +#define DyPrSym(key)   AuDbgSym(key->dk_op.dy_hop)
6575 +
6576 +/*
6577 + * How large will these lists be?
6578 + * Usually just a few elements, 20-30 at most for each, I guess.
6579 + */
6580 +static struct au_splhead dynop[AuDyLast];
6581 +
6582 +static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
6583 +{
6584 +       struct au_dykey *key, *tmp;
6585 +       struct list_head *head;
6586 +
6587 +       key = NULL;
6588 +       head = &spl->head;
6589 +       rcu_read_lock();
6590 +       list_for_each_entry_rcu(tmp, head, dk_list)
6591 +               if (tmp->dk_op.dy_hop == h_op) {
6592 +                       key = tmp;
6593 +                       kref_get(&key->dk_kref);
6594 +                       break;
6595 +               }
6596 +       rcu_read_unlock();
6597 +
6598 +       return key;
6599 +}
6600 +
6601 +static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
6602 +{
6603 +       struct au_dykey **k, *found;
6604 +       const void *h_op = key->dk_op.dy_hop;
6605 +       int i;
6606 +
6607 +       found = NULL;
6608 +       k = br->br_dykey;
6609 +       for (i = 0; i < AuBrDynOp; i++)
6610 +               if (k[i]) {
6611 +                       if (k[i]->dk_op.dy_hop == h_op) {
6612 +                               found = k[i];
6613 +                               break;
6614 +                       }
6615 +               } else
6616 +                       break;
6617 +       if (!found) {
6618 +               spin_lock(&br->br_dykey_lock);
6619 +               for (; i < AuBrDynOp; i++)
6620 +                       if (k[i]) {
6621 +                               if (k[i]->dk_op.dy_hop == h_op) {
6622 +                                       found = k[i];
6623 +                                       break;
6624 +                               }
6625 +                       } else {
6626 +                               k[i] = key;
6627 +                               break;
6628 +                       }
6629 +               spin_unlock(&br->br_dykey_lock);
6630 +               BUG_ON(i == AuBrDynOp); /* expand the array */
6631 +       }
6632 +
6633 +       return found;
6634 +}
6635 +
6636 +/* kref_get() if @key is already added */
6637 +static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
6638 +{
6639 +       struct au_dykey *tmp, *found;
6640 +       struct list_head *head;
6641 +       const void *h_op = key->dk_op.dy_hop;
6642 +
6643 +       found = NULL;
6644 +       head = &spl->head;
6645 +       spin_lock(&spl->spin);
6646 +       list_for_each_entry(tmp, head, dk_list)
6647 +               if (tmp->dk_op.dy_hop == h_op) {
6648 +                       kref_get(&tmp->dk_kref);
6649 +                       found = tmp;
6650 +                       break;
6651 +               }
6652 +       if (!found)
6653 +               list_add_rcu(&key->dk_list, head);
6654 +       spin_unlock(&spl->spin);
6655 +
6656 +       if (!found)
6657 +               DyPrSym(key);
6658 +       return found;
6659 +}
6660 +
6661 +static void dy_free_rcu(struct rcu_head *rcu)
6662 +{
6663 +       struct au_dykey *key;
6664 +
6665 +       key = container_of(rcu, struct au_dykey, dk_rcu);
6666 +       DyPrSym(key);
6667 +       kfree(key);
6668 +}
6669 +
6670 +static void dy_free(struct kref *kref)
6671 +{
6672 +       struct au_dykey *key;
6673 +       struct au_splhead *spl;
6674 +
6675 +       key = container_of(kref, struct au_dykey, dk_kref);
6676 +       spl = dynop + key->dk_op.dy_type;
6677 +       au_spl_del_rcu(&key->dk_list, spl);
6678 +       call_rcu(&key->dk_rcu, dy_free_rcu);
6679 +}
6680 +
6681 +void au_dy_put(struct au_dykey *key)
6682 +{
6683 +       kref_put(&key->dk_kref, dy_free);
6684 +}
6685 +
6686 +/* ---------------------------------------------------------------------- */
6687 +
6688 +#define DyDbgSize(cnt, op)     AuDebugOn(cnt != sizeof(op)/sizeof(void *))
6689 +
6690 +#ifdef CONFIG_AUFS_DEBUG
6691 +#define DyDbgDeclare(cnt)      unsigned int cnt = 0
6692 +#define DyDbgInc(cnt)          do { cnt++; } while (0)
6693 +#else
6694 +#define DyDbgDeclare(cnt)      do {} while (0)
6695 +#define DyDbgInc(cnt)          do {} while (0)
6696 +#endif
6697 +
6698 +#define DySet(func, dst, src, h_op, h_sb) do {                         \
6699 +       DyDbgInc(cnt);                                                  \
6700 +       if (h_op->func) {                                               \
6701 +               if (src.func)                                           \
6702 +                       dst.func = src.func;                            \
6703 +               else                                                    \
6704 +                       AuDbg("%s %s\n", au_sbtype(h_sb), #func);       \
6705 +       }                                                               \
6706 +} while (0)
6707 +
6708 +#define DySetForce(func, dst, src) do {                \
6709 +       AuDebugOn(!src.func);                   \
6710 +       DyDbgInc(cnt);                          \
6711 +       dst.func = src.func;                    \
6712 +} while (0)
6713 +
6714 +#define DySetAop(func) \
6715 +       DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
6716 +#define DySetAopForce(func) \
6717 +       DySetForce(func, dyaop->da_op, aufs_aop)
6718 +
6719 +static void dy_aop(struct au_dykey *key, const void *h_op,
6720 +                  struct super_block *h_sb __maybe_unused)
6721 +{
6722 +       struct au_dyaop *dyaop = (void *)key;
6723 +       const struct address_space_operations *h_aop = h_op;
6724 +       DyDbgDeclare(cnt);
6725 +
6726 +       AuDbg("%s\n", au_sbtype(h_sb));
6727 +
6728 +       DySetAop(writepage);
6729 +       DySetAopForce(readpage);        /* force */
6730 +       DySetAop(sync_page);
6731 +       DySetAop(writepages);
6732 +       DySetAop(set_page_dirty);
6733 +       DySetAop(readpages);
6734 +       DySetAop(write_begin);
6735 +       DySetAop(write_end);
6736 +       DySetAop(bmap);
6737 +       DySetAop(invalidatepage);
6738 +       DySetAop(releasepage);
6739 +       /* these two will be changed according to an aufs mount option */
6740 +       DySetAop(direct_IO);
6741 +       DySetAop(get_xip_mem);
6742 +       DySetAop(migratepage);
6743 +       DySetAop(launder_page);
6744 +       DySetAop(is_partially_uptodate);
6745 +       DySetAop(error_remove_page);
6746 +
6747 +       DyDbgSize(cnt, *h_aop);
6748 +       dyaop->da_get_xip_mem = h_aop->get_xip_mem;
6749 +}
6750 +
6751 +#define DySetVmop(func) \
6752 +       DySet(func, dyvmop->dv_op, aufs_vm_ops, h_vmop, h_sb)
6753 +#define DySetVmopForce(func) \
6754 +       DySetForce(func, dyvmop->dv_op, aufs_vm_ops)
6755 +
6756 +static void dy_vmop(struct au_dykey *key, const void *h_op,
6757 +                   struct super_block *h_sb __maybe_unused)
6758 +{
6759 +       struct au_dyvmop *dyvmop = (void *)key;
6760 +       const struct vm_operations_struct *h_vmop = h_op;
6761 +       DyDbgDeclare(cnt);
6762 +
6763 +       AuDbg("%s\n", au_sbtype(h_sb));
6764 +
6765 +       DySetVmop(open);
6766 +       DySetVmop(close);
6767 +       DySetVmop(fault);
6768 +       DySetVmop(page_mkwrite);
6769 +       DySetVmop(access);
6770 +#ifdef CONFIG_NUMA
6771 +       DySetVmop(set_policy);
6772 +       DySetVmop(get_policy);
6773 +       DySetVmop(migrate);
6774 +#endif
6775 +
6776 +       DyDbgSize(cnt, *h_vmop);
6777 +}
6778 +
6779 +/* ---------------------------------------------------------------------- */
6780 +
6781 +static void dy_bug(struct kref *kref)
6782 +{
6783 +       BUG();
6784 +}
6785 +
6786 +static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
6787 +{
6788 +       struct au_dykey *key, *old;
6789 +       struct au_splhead *spl;
6790 +       struct op {
6791 +               unsigned int sz;
6792 +               void (*set)(struct au_dykey *key, const void *h_op,
6793 +                           struct super_block *h_sb __maybe_unused);
6794 +       };
6795 +       static const struct op a[] = {
6796 +               [AuDy_AOP] = {
6797 +                       .sz     = sizeof(struct au_dyaop),
6798 +                       .set    = dy_aop
6799 +               },
6800 +               [AuDy_VMOP] = {
6801 +                       .sz     = sizeof(struct au_dyvmop),
6802 +                       .set    = dy_vmop
6803 +               }
6804 +       };
6805 +       const struct op *p;
6806 +
6807 +       spl = dynop + op->dy_type;
6808 +       key = dy_gfind_get(spl, op->dy_hop);
6809 +       if (key)
6810 +               goto out_add; /* success */
6811 +
6812 +       p = a + op->dy_type;
6813 +       key = kzalloc(p->sz, GFP_NOFS);
6814 +       if (unlikely(!key)) {
6815 +               key = ERR_PTR(-ENOMEM);
6816 +               goto out;
6817 +       }
6818 +
6819 +       key->dk_op.dy_hop = op->dy_hop;
6820 +       kref_init(&key->dk_kref);
6821 +       p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
6822 +       old = dy_gadd(spl, key);
6823 +       if (old) {
6824 +               kfree(key);
6825 +               key = old;
6826 +       }
6827 +
6828 +out_add:
6829 +       old = dy_bradd(br, key);
6830 +       if (old)
6831 +               /* its ref-count should never be zero here */
6832 +               kref_put(&key->dk_kref, dy_bug);
6833 +out:
6834 +       return key;
6835 +}
6836 +
6837 +/* ---------------------------------------------------------------------- */
6838 +/*
6839 + * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
6840 + * This behaviour is neccessary to return an error from open(O_DIRECT) instead
6841 + * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
6842 + * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
6843 + * See the aufs manual in detail.
6844 + *
6845 + * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
6846 + * performance of fadvise() and madvise() may be affected.
6847 + */
6848 +static void dy_adx(struct au_dyaop *dyaop, int do_dx)
6849 +{
6850 +       if (!do_dx) {
6851 +               dyaop->da_op.direct_IO = NULL;
6852 +               dyaop->da_op.get_xip_mem = NULL;
6853 +       } else {
6854 +               dyaop->da_op.direct_IO = aufs_aop.direct_IO;
6855 +               dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
6856 +               if (!dyaop->da_get_xip_mem)
6857 +                       dyaop->da_op.get_xip_mem = NULL;
6858 +       }
6859 +}
6860 +
6861 +static struct au_dyaop *dy_aget(struct au_branch *br,
6862 +                               const struct address_space_operations *h_aop,
6863 +                               int do_dx)
6864 +{
6865 +       struct au_dyaop *dyaop;
6866 +       struct au_dynop op;
6867 +
6868 +       op.dy_type = AuDy_AOP;
6869 +       op.dy_haop = h_aop;
6870 +       dyaop = (void *)dy_get(&op, br);
6871 +       if (IS_ERR(dyaop))
6872 +               goto out;
6873 +       dy_adx(dyaop, do_dx);
6874 +
6875 +out:
6876 +       return dyaop;
6877 +}
6878 +
6879 +int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
6880 +               struct inode *h_inode)
6881 +{
6882 +       int err, do_dx;
6883 +       struct super_block *sb;
6884 +       struct au_branch *br;
6885 +       struct au_dyaop *dyaop;
6886 +
6887 +       AuDebugOn(!S_ISREG(h_inode->i_mode));
6888 +       IiMustWriteLock(inode);
6889 +
6890 +       sb = inode->i_sb;
6891 +       br = au_sbr(sb, bindex);
6892 +       do_dx = !!au_opt_test(au_mntflags(sb), DIO);
6893 +       dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
6894 +       err = PTR_ERR(dyaop);
6895 +       if (IS_ERR(dyaop))
6896 +               /* unnecessary to call dy_fput() */
6897 +               goto out;
6898 +
6899 +       err = 0;
6900 +       inode->i_mapping->a_ops = &dyaop->da_op;
6901 +
6902 +out:
6903 +       return err;
6904 +}
6905 +
6906 +/*
6907 + * Is it safe to replace a_ops during the inode/file is in operation?
6908 + * Yes, I hope so.
6909 + */
6910 +int au_dy_irefresh(struct inode *inode)
6911 +{
6912 +       int err;
6913 +       aufs_bindex_t bstart;
6914 +       struct inode *h_inode;
6915 +
6916 +       err = 0;
6917 +       if (S_ISREG(inode->i_mode)) {
6918 +               bstart = au_ibstart(inode);
6919 +               h_inode = au_h_iptr(inode, bstart);
6920 +               err = au_dy_iaop(inode, bstart, h_inode);
6921 +       }
6922 +       return err;
6923 +}
6924 +
6925 +void au_dy_arefresh(int do_dx)
6926 +{
6927 +       struct au_splhead *spl;
6928 +       struct list_head *head;
6929 +       struct au_dykey *key;
6930 +
6931 +       spl = dynop + AuDy_AOP;
6932 +       head = &spl->head;
6933 +       spin_lock(&spl->spin);
6934 +       list_for_each_entry(key, head, dk_list)
6935 +               dy_adx((void *)key, do_dx);
6936 +       spin_unlock(&spl->spin);
6937 +}
6938 +
6939 +const struct vm_operations_struct *
6940 +au_dy_vmop(struct file *file, struct au_branch *br,
6941 +          const struct vm_operations_struct *h_vmop)
6942 +{
6943 +       struct au_dyvmop *dyvmop;
6944 +       struct au_dynop op;
6945 +
6946 +       op.dy_type = AuDy_VMOP;
6947 +       op.dy_hvmop = h_vmop;
6948 +       dyvmop = (void *)dy_get(&op, br);
6949 +       if (IS_ERR(dyvmop))
6950 +               return (void *)dyvmop;
6951 +       return &dyvmop->dv_op;
6952 +}
6953 +
6954 +/* ---------------------------------------------------------------------- */
6955 +
6956 +void __init au_dy_init(void)
6957 +{
6958 +       int i;
6959 +
6960 +       /* make sure that 'struct au_dykey *' can be any type */
6961 +       BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
6962 +       BUILD_BUG_ON(offsetof(struct au_dyvmop, dv_key));
6963 +
6964 +       for (i = 0; i < AuDyLast; i++)
6965 +               au_spl_init(dynop + i);
6966 +}
6967 +
6968 +void au_dy_fin(void)
6969 +{
6970 +       int i;
6971 +
6972 +       for (i = 0; i < AuDyLast; i++)
6973 +               WARN_ON(!list_empty(&dynop[i].head));
6974 +}
6975 diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
6976 --- /usr/share/empty/fs/aufs/dynop.h    1970-01-01 01:00:00.000000000 +0100
6977 +++ linux/fs/aufs/dynop.h       2010-10-21 09:52:43.086957936 +0200
6978 @@ -0,0 +1,89 @@
6979 +/*
6980 + * Copyright (C) 2010 Junjiro R. Okajima
6981 + *
6982 + * This program, aufs is free software; you can redistribute it and/or modify
6983 + * it under the terms of the GNU General Public License as published by
6984 + * the Free Software Foundation; either version 2 of the License, or
6985 + * (at your option) any later version.
6986 + *
6987 + * This program is distributed in the hope that it will be useful,
6988 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6989 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6990 + * GNU General Public License for more details.
6991 + *
6992 + * You should have received a copy of the GNU General Public License
6993 + * along with this program; if not, write to the Free Software
6994 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
6995 + */
6996 +
6997 +/*
6998 + * dynamically customizable operations (for regular files only)
6999 + */
7000 +
7001 +#ifndef __AUFS_DYNOP_H__
7002 +#define __AUFS_DYNOP_H__
7003 +
7004 +#ifdef __KERNEL__
7005 +
7006 +#include <linux/fs.h>
7007 +#include <linux/mm.h>
7008 +#include <linux/rcupdate.h>
7009 +#include <linux/aufs_type.h>
7010 +#include "inode.h"
7011 +
7012 +enum {AuDy_AOP, AuDy_VMOP, AuDyLast};
7013 +
7014 +struct au_dynop {
7015 +       int                                             dy_type;
7016 +       union {
7017 +               const void                              *dy_hop;
7018 +               const struct address_space_operations   *dy_haop;
7019 +               const struct vm_operations_struct       *dy_hvmop;
7020 +       };
7021 +};
7022 +
7023 +struct au_dykey {
7024 +       union {
7025 +               struct list_head        dk_list;
7026 +               struct rcu_head         dk_rcu;
7027 +       };
7028 +       struct au_dynop         dk_op;
7029 +
7030 +       /*
7031 +        * during I am in the branch local array, kref is gotten. when the
7032 +        * branch is removed, kref is put.
7033 +        */
7034 +       struct kref             dk_kref;
7035 +};
7036 +
7037 +/* stop unioning since their sizes are very different from each other */
7038 +struct au_dyaop {
7039 +       struct au_dykey                 da_key;
7040 +       struct address_space_operations da_op; /* not const */
7041 +       int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
7042 +                             void **, unsigned long *);
7043 +};
7044 +
7045 +struct au_dyvmop {
7046 +       struct au_dykey                 dv_key;
7047 +       struct vm_operations_struct     dv_op; /* not const */
7048 +};
7049 +
7050 +/* ---------------------------------------------------------------------- */
7051 +
7052 +/* dynop.c */
7053 +struct au_branch;
7054 +void au_dy_put(struct au_dykey *key);
7055 +int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
7056 +               struct inode *h_inode);
7057 +int au_dy_irefresh(struct inode *inode);
7058 +void au_dy_arefresh(int do_dio);
7059 +const struct vm_operations_struct *
7060 +au_dy_vmop(struct file *file, struct au_branch *br,
7061 +          const struct vm_operations_struct *h_vmop);
7062 +
7063 +void __init au_dy_init(void);
7064 +void au_dy_fin(void);
7065 +
7066 +#endif /* __KERNEL__ */
7067 +#endif /* __AUFS_DYNOP_H__ */
7068 diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
7069 --- /usr/share/empty/fs/aufs/export.c   1970-01-01 01:00:00.000000000 +0100
7070 +++ linux/fs/aufs/export.c      2010-10-21 09:52:43.086957936 +0200
7071 @@ -0,0 +1,788 @@
7072 +/*
7073 + * Copyright (C) 2005-2010 Junjiro R. Okajima
7074 + *
7075 + * This program, aufs is free software; you can redistribute it and/or modify
7076 + * it under the terms of the GNU General Public License as published by
7077 + * the Free Software Foundation; either version 2 of the License, or
7078 + * (at your option) any later version.
7079 + *
7080 + * This program is distributed in the hope that it will be useful,
7081 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7082 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7083 + * GNU General Public License for more details.
7084 + *
7085 + * You should have received a copy of the GNU General Public License
7086 + * along with this program; if not, write to the Free Software
7087 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
7088 + */
7089 +
7090 +/*
7091 + * export via nfs
7092 + */
7093 +
7094 +#include <linux/exportfs.h>
7095 +#include <linux/file.h>
7096 +#include <linux/mnt_namespace.h>
7097 +#include <linux/namei.h>
7098 +#include <linux/nsproxy.h>
7099 +#include <linux/random.h>
7100 +#include <linux/writeback.h>
7101 +#include "aufs.h"
7102 +
7103 +union conv {
7104 +#ifdef CONFIG_AUFS_INO_T_64
7105 +       __u32 a[2];
7106 +#else
7107 +       __u32 a[1];
7108 +#endif
7109 +       ino_t ino;
7110 +};
7111 +
7112 +static ino_t decode_ino(__u32 *a)
7113 +{
7114 +       union conv u;
7115 +
7116 +       BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
7117 +       u.a[0] = a[0];
7118 +#ifdef CONFIG_AUFS_INO_T_64
7119 +       u.a[1] = a[1];
7120 +#endif
7121 +       return u.ino;
7122 +}
7123 +
7124 +static void encode_ino(__u32 *a, ino_t ino)
7125 +{
7126 +       union conv u;
7127 +
7128 +       u.ino = ino;
7129 +       a[0] = u.a[0];
7130 +#ifdef CONFIG_AUFS_INO_T_64
7131 +       a[1] = u.a[1];
7132 +#endif
7133 +}
7134 +
7135 +/* NFS file handle */
7136 +enum {
7137 +       Fh_br_id,
7138 +       Fh_sigen,
7139 +#ifdef CONFIG_AUFS_INO_T_64
7140 +       /* support 64bit inode number */
7141 +       Fh_ino1,
7142 +       Fh_ino2,
7143 +       Fh_dir_ino1,
7144 +       Fh_dir_ino2,
7145 +#else
7146 +       Fh_ino1,
7147 +       Fh_dir_ino1,
7148 +#endif
7149 +       Fh_igen,
7150 +       Fh_h_type,
7151 +       Fh_tail,
7152 +
7153 +       Fh_ino = Fh_ino1,
7154 +       Fh_dir_ino = Fh_dir_ino1
7155 +};
7156 +
7157 +static int au_test_anon(struct dentry *dentry)
7158 +{
7159 +       return !!(dentry->d_flags & DCACHE_DISCONNECTED);
7160 +}
7161 +
7162 +/* ---------------------------------------------------------------------- */
7163 +/* inode generation external table */
7164 +
7165 +void au_xigen_inc(struct inode *inode)
7166 +{
7167 +       loff_t pos;
7168 +       ssize_t sz;
7169 +       __u32 igen;
7170 +       struct super_block *sb;
7171 +       struct au_sbinfo *sbinfo;
7172 +
7173 +       sb = inode->i_sb;
7174 +       AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
7175 +
7176 +       sbinfo = au_sbi(sb);
7177 +       pos = inode->i_ino;
7178 +       pos *= sizeof(igen);
7179 +       igen = inode->i_generation + 1;
7180 +       sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
7181 +                        sizeof(igen), &pos);
7182 +       if (sz == sizeof(igen))
7183 +               return; /* success */
7184 +
7185 +       if (unlikely(sz >= 0))
7186 +               AuIOErr("xigen error (%zd)\n", sz);
7187 +}
7188 +
7189 +int au_xigen_new(struct inode *inode)
7190 +{
7191 +       int err;
7192 +       loff_t pos;
7193 +       ssize_t sz;
7194 +       struct super_block *sb;
7195 +       struct au_sbinfo *sbinfo;
7196 +       struct file *file;
7197 +
7198 +       err = 0;
7199 +       /* todo: dirty, at mount time */
7200 +       if (inode->i_ino == AUFS_ROOT_INO)
7201 +               goto out;
7202 +       sb = inode->i_sb;
7203 +       SiMustAnyLock(sb);
7204 +       if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7205 +               goto out;
7206 +
7207 +       err = -EFBIG;
7208 +       pos = inode->i_ino;
7209 +       if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
7210 +               AuIOErr1("too large i%lld\n", pos);
7211 +               goto out;
7212 +       }
7213 +       pos *= sizeof(inode->i_generation);
7214 +
7215 +       err = 0;
7216 +       sbinfo = au_sbi(sb);
7217 +       file = sbinfo->si_xigen;
7218 +       BUG_ON(!file);
7219 +
7220 +       if (i_size_read(file->f_dentry->d_inode)
7221 +           < pos + sizeof(inode->i_generation)) {
7222 +               inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
7223 +               sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
7224 +                                sizeof(inode->i_generation), &pos);
7225 +       } else
7226 +               sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
7227 +                               sizeof(inode->i_generation), &pos);
7228 +       if (sz == sizeof(inode->i_generation))
7229 +               goto out; /* success */
7230 +
7231 +       err = sz;
7232 +       if (unlikely(sz >= 0)) {
7233 +               err = -EIO;
7234 +               AuIOErr("xigen error (%zd)\n", sz);
7235 +       }
7236 +
7237 +out:
7238 +       return err;
7239 +}
7240 +
7241 +int au_xigen_set(struct super_block *sb, struct file *base)
7242 +{
7243 +       int err;
7244 +       struct au_sbinfo *sbinfo;
7245 +       struct file *file;
7246 +
7247 +       SiMustWriteLock(sb);
7248 +
7249 +       sbinfo = au_sbi(sb);
7250 +       file = au_xino_create2(base, sbinfo->si_xigen);
7251 +       err = PTR_ERR(file);
7252 +       if (IS_ERR(file))
7253 +               goto out;
7254 +       err = 0;
7255 +       if (sbinfo->si_xigen)
7256 +               fput(sbinfo->si_xigen);
7257 +       sbinfo->si_xigen = file;
7258 +
7259 +out:
7260 +       return err;
7261 +}
7262 +
7263 +void au_xigen_clr(struct super_block *sb)
7264 +{
7265 +       struct au_sbinfo *sbinfo;
7266 +
7267 +       SiMustWriteLock(sb);
7268 +
7269 +       sbinfo = au_sbi(sb);
7270 +       if (sbinfo->si_xigen) {
7271 +               fput(sbinfo->si_xigen);
7272 +               sbinfo->si_xigen = NULL;
7273 +       }
7274 +}
7275 +
7276 +/* ---------------------------------------------------------------------- */
7277 +
7278 +static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
7279 +                                   ino_t dir_ino)
7280 +{
7281 +       struct dentry *dentry, *d;
7282 +       struct inode *inode;
7283 +       unsigned int sigen;
7284 +
7285 +       dentry = NULL;
7286 +       inode = ilookup(sb, ino);
7287 +       if (!inode)
7288 +               goto out;
7289 +
7290 +       dentry = ERR_PTR(-ESTALE);
7291 +       sigen = au_sigen(sb);
7292 +       if (unlikely(is_bad_inode(inode)
7293 +                    || IS_DEADDIR(inode)
7294 +                    || sigen != au_iigen(inode)))
7295 +               goto out_iput;
7296 +
7297 +       dentry = NULL;
7298 +       if (!dir_ino || S_ISDIR(inode->i_mode))
7299 +               dentry = d_find_alias(inode);
7300 +       else {
7301 +               spin_lock(&dcache_lock);
7302 +               list_for_each_entry(d, &inode->i_dentry, d_alias)
7303 +                       if (!au_test_anon(d)
7304 +                           && d->d_parent->d_inode->i_ino == dir_ino) {
7305 +                               dentry = dget_locked(d);
7306 +                               break;
7307 +                       }
7308 +               spin_unlock(&dcache_lock);
7309 +       }
7310 +       if (unlikely(dentry && sigen != au_digen(dentry))) {
7311 +               dput(dentry);
7312 +               dentry = ERR_PTR(-ESTALE);
7313 +       }
7314 +
7315 +out_iput:
7316 +       iput(inode);
7317 +out:
7318 +       return dentry;
7319 +}
7320 +
7321 +/* ---------------------------------------------------------------------- */
7322 +
7323 +/* todo: dirty? */
7324 +/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
7325 +
7326 +struct au_compare_mnt_args {
7327 +       /* input */
7328 +       struct super_block *sb;
7329 +
7330 +       /* output */
7331 +       struct vfsmount *mnt;
7332 +};
7333 +
7334 +static int au_compare_mnt(struct vfsmount *mnt, void *arg)
7335 +{
7336 +       struct au_compare_mnt_args *a = arg;
7337 +
7338 +       if (mnt->mnt_sb != a->sb)
7339 +               return 0;
7340 +       a->mnt = mntget(mnt);
7341 +       return 1;
7342 +}
7343 +
7344 +static struct vfsmount *au_mnt_get(struct super_block *sb)
7345 +{
7346 +       int err;
7347 +       struct au_compare_mnt_args args = {
7348 +               .sb = sb
7349 +       };
7350 +       struct mnt_namespace *ns;
7351 +
7352 +       /* no get/put ?? */
7353 +       AuDebugOn(!current->nsproxy);
7354 +       ns = current->nsproxy->mnt_ns;
7355 +       AuDebugOn(!ns);
7356 +       err = iterate_mounts(au_compare_mnt, &args, ns->root);
7357 +       AuDebugOn(!err);
7358 +       AuDebugOn(!args.mnt);
7359 +       return args.mnt;
7360 +}
7361 +
7362 +struct au_nfsd_si_lock {
7363 +       unsigned int sigen;
7364 +       aufs_bindex_t br_id;
7365 +       unsigned char force_lock;
7366 +};
7367 +
7368 +static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
7369 +                                      struct au_nfsd_si_lock *nsi_lock)
7370 +{
7371 +       aufs_bindex_t bindex;
7372 +
7373 +       si_read_lock(sb, AuLock_FLUSH);
7374 +
7375 +       /* branch id may be wrapped around */
7376 +       bindex = au_br_index(sb, nsi_lock->br_id);
7377 +       if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
7378 +               goto out; /* success */
7379 +
7380 +       if (!nsi_lock->force_lock)
7381 +               si_read_unlock(sb);
7382 +       bindex = -1;
7383 +
7384 +out:
7385 +       return bindex;
7386 +}
7387 +
7388 +struct find_name_by_ino {
7389 +       int called, found;
7390 +       ino_t ino;
7391 +       char *name;
7392 +       int namelen;
7393 +};
7394 +
7395 +static int
7396 +find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
7397 +                u64 ino, unsigned int d_type)
7398 +{
7399 +       struct find_name_by_ino *a = arg;
7400 +
7401 +       a->called++;
7402 +       if (a->ino != ino)
7403 +               return 0;
7404 +
7405 +       memcpy(a->name, name, namelen);
7406 +       a->namelen = namelen;
7407 +       a->found = 1;
7408 +       return 1;
7409 +}
7410 +
7411 +static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
7412 +                                    struct au_nfsd_si_lock *nsi_lock)
7413 +{
7414 +       struct dentry *dentry, *parent;
7415 +       struct file *file;
7416 +       struct inode *dir;
7417 +       struct find_name_by_ino arg;
7418 +       int err;
7419 +
7420 +       parent = path->dentry;
7421 +       if (nsi_lock)
7422 +               si_read_unlock(parent->d_sb);
7423 +       file = vfsub_dentry_open(path, au_dir_roflags);
7424 +       dentry = (void *)file;
7425 +       if (IS_ERR(file))
7426 +               goto out;
7427 +
7428 +       dentry = ERR_PTR(-ENOMEM);
7429 +       arg.name = __getname_gfp(GFP_NOFS);
7430 +       if (unlikely(!arg.name))
7431 +               goto out_file;
7432 +       arg.ino = ino;
7433 +       arg.found = 0;
7434 +       do {
7435 +               arg.called = 0;
7436 +               /* smp_mb(); */
7437 +               err = vfsub_readdir(file, find_name_by_ino, &arg);
7438 +       } while (!err && !arg.found && arg.called);
7439 +       dentry = ERR_PTR(err);
7440 +       if (unlikely(err))
7441 +               goto out_name;
7442 +       dentry = ERR_PTR(-ENOENT);
7443 +       if (!arg.found)
7444 +               goto out_name;
7445 +
7446 +       /* do not call au_lkup_one() */
7447 +       dir = parent->d_inode;
7448 +       mutex_lock(&dir->i_mutex);
7449 +       dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
7450 +       mutex_unlock(&dir->i_mutex);
7451 +       AuTraceErrPtr(dentry);
7452 +       if (IS_ERR(dentry))
7453 +               goto out_name;
7454 +       AuDebugOn(au_test_anon(dentry));
7455 +       if (unlikely(!dentry->d_inode)) {
7456 +               dput(dentry);
7457 +               dentry = ERR_PTR(-ENOENT);
7458 +       }
7459 +
7460 +out_name:
7461 +       __putname(arg.name);
7462 +out_file:
7463 +       fput(file);
7464 +out:
7465 +       if (unlikely(nsi_lock
7466 +                    && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
7467 +               if (!IS_ERR(dentry)) {
7468 +                       dput(dentry);
7469 +                       dentry = ERR_PTR(-ESTALE);
7470 +               }
7471 +       AuTraceErrPtr(dentry);
7472 +       return dentry;
7473 +}
7474 +
7475 +static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
7476 +                                       ino_t dir_ino,
7477 +                                       struct au_nfsd_si_lock *nsi_lock)
7478 +{
7479 +       struct dentry *dentry;
7480 +       struct path path;
7481 +
7482 +       if (dir_ino != AUFS_ROOT_INO) {
7483 +               path.dentry = decode_by_ino(sb, dir_ino, 0);
7484 +               dentry = path.dentry;
7485 +               if (!path.dentry || IS_ERR(path.dentry))
7486 +                       goto out;
7487 +               AuDebugOn(au_test_anon(path.dentry));
7488 +       } else
7489 +               path.dentry = dget(sb->s_root);
7490 +
7491 +       path.mnt = au_mnt_get(sb);
7492 +       dentry = au_lkup_by_ino(&path, ino, nsi_lock);
7493 +       path_put(&path);
7494 +
7495 +out:
7496 +       AuTraceErrPtr(dentry);
7497 +       return dentry;
7498 +}
7499 +
7500 +/* ---------------------------------------------------------------------- */
7501 +
7502 +static int h_acceptable(void *expv, struct dentry *dentry)
7503 +{
7504 +       return 1;
7505 +}
7506 +
7507 +static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
7508 +                          char *buf, int len, struct super_block *sb)
7509 +{
7510 +       char *p;
7511 +       int n;
7512 +       struct path path;
7513 +
7514 +       p = d_path(h_rootpath, buf, len);
7515 +       if (IS_ERR(p))
7516 +               goto out;
7517 +       n = strlen(p);
7518 +
7519 +       path.mnt = h_rootpath->mnt;
7520 +       path.dentry = h_parent;
7521 +       p = d_path(&path, buf, len);
7522 +       if (IS_ERR(p))
7523 +               goto out;
7524 +       if (n != 1)
7525 +               p += n;
7526 +
7527 +       path.mnt = au_mnt_get(sb);
7528 +       path.dentry = sb->s_root;
7529 +       p = d_path(&path, buf, len - strlen(p));
7530 +       mntput(path.mnt);
7531 +       if (IS_ERR(p))
7532 +               goto out;
7533 +       if (n != 1)
7534 +               p[strlen(p)] = '/';
7535 +
7536 +out:
7537 +       AuTraceErrPtr(p);
7538 +       return p;
7539 +}
7540 +
7541 +static
7542 +struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
7543 +                             ino_t ino, __u32 *fh, int fh_len,
7544 +                             struct au_nfsd_si_lock *nsi_lock)
7545 +{
7546 +       struct dentry *dentry, *h_parent, *root;
7547 +       struct super_block *h_sb;
7548 +       char *pathname, *p;
7549 +       struct vfsmount *h_mnt;
7550 +       struct au_branch *br;
7551 +       int err;
7552 +       struct path path;
7553 +
7554 +       br = au_sbr(sb, bindex);
7555 +       /* au_br_get(br); */
7556 +       h_mnt = br->br_mnt;
7557 +       h_sb = h_mnt->mnt_sb;
7558 +       /* todo: call lower fh_to_dentry()? fh_to_parent()? */
7559 +       h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
7560 +                                     fh_len - Fh_tail, fh[Fh_h_type],
7561 +                                     h_acceptable, /*context*/NULL);
7562 +       dentry = h_parent;
7563 +       if (unlikely(!h_parent || IS_ERR(h_parent))) {
7564 +               AuWarn1("%s decode_fh failed, %ld\n",
7565 +                       au_sbtype(h_sb), PTR_ERR(h_parent));
7566 +               goto out;
7567 +       }
7568 +       dentry = NULL;
7569 +       if (unlikely(au_test_anon(h_parent))) {
7570 +               AuWarn1("%s decode_fh returned a disconnected dentry\n",
7571 +                       au_sbtype(h_sb));
7572 +               goto out_h_parent;
7573 +       }
7574 +
7575 +       dentry = ERR_PTR(-ENOMEM);
7576 +       pathname = (void *)__get_free_page(GFP_NOFS);
7577 +       if (unlikely(!pathname))
7578 +               goto out_h_parent;
7579 +
7580 +       root = sb->s_root;
7581 +       path.mnt = h_mnt;
7582 +       di_read_lock_parent(root, !AuLock_IR);
7583 +       path.dentry = au_h_dptr(root, bindex);
7584 +       di_read_unlock(root, !AuLock_IR);
7585 +       p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
7586 +       dentry = (void *)p;
7587 +       if (IS_ERR(p))
7588 +               goto out_pathname;
7589 +
7590 +       si_read_unlock(sb);
7591 +       err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
7592 +       dentry = ERR_PTR(err);
7593 +       if (unlikely(err))
7594 +               goto out_relock;
7595 +
7596 +       dentry = ERR_PTR(-ENOENT);
7597 +       AuDebugOn(au_test_anon(path.dentry));
7598 +       if (unlikely(!path.dentry->d_inode))
7599 +               goto out_path;
7600 +
7601 +       if (ino != path.dentry->d_inode->i_ino)
7602 +               dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
7603 +       else
7604 +               dentry = dget(path.dentry);
7605 +
7606 +out_path:
7607 +       path_put(&path);
7608 +out_relock:
7609 +       if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
7610 +               if (!IS_ERR(dentry)) {
7611 +                       dput(dentry);
7612 +                       dentry = ERR_PTR(-ESTALE);
7613 +               }
7614 +out_pathname:
7615 +       free_page((unsigned long)pathname);
7616 +out_h_parent:
7617 +       dput(h_parent);
7618 +out:
7619 +       /* au_br_put(br); */
7620 +       AuTraceErrPtr(dentry);
7621 +       return dentry;
7622 +}
7623 +
7624 +/* ---------------------------------------------------------------------- */
7625 +
7626 +static struct dentry *
7627 +aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
7628 +                 int fh_type)
7629 +{
7630 +       struct dentry *dentry;
7631 +       __u32 *fh = fid->raw;
7632 +       ino_t ino, dir_ino;
7633 +       aufs_bindex_t bindex;
7634 +       struct au_nfsd_si_lock nsi_lock = {
7635 +               .force_lock     = 0
7636 +       };
7637 +
7638 +       dentry = ERR_PTR(-ESTALE);
7639 +       /* it should never happen, but the file handle is unreliable */
7640 +       if (unlikely(fh_len < Fh_tail))
7641 +               goto out;
7642 +       nsi_lock.sigen = fh[Fh_sigen];
7643 +       nsi_lock.br_id = fh[Fh_br_id];
7644 +
7645 +       /* branch id may be wrapped around */
7646 +       bindex = si_nfsd_read_lock(sb, &nsi_lock);
7647 +       if (unlikely(bindex < 0))
7648 +               goto out;
7649 +       nsi_lock.force_lock = 1;
7650 +
7651 +       /* is this inode still cached? */
7652 +       ino = decode_ino(fh + Fh_ino);
7653 +       /* it should never happen */
7654 +       if (unlikely(ino == AUFS_ROOT_INO))
7655 +               goto out;
7656 +
7657 +       dir_ino = decode_ino(fh + Fh_dir_ino);
7658 +       dentry = decode_by_ino(sb, ino, dir_ino);
7659 +       if (IS_ERR(dentry))
7660 +               goto out_unlock;
7661 +       if (dentry)
7662 +               goto accept;
7663 +
7664 +       /* is the parent dir cached? */
7665 +       dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
7666 +       if (IS_ERR(dentry))
7667 +               goto out_unlock;
7668 +       if (dentry)
7669 +               goto accept;
7670 +
7671 +       /* lookup path */
7672 +       dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
7673 +       if (IS_ERR(dentry))
7674 +               goto out_unlock;
7675 +       if (unlikely(!dentry))
7676 +               /* todo?: make it ESTALE */
7677 +               goto out_unlock;
7678 +
7679 +accept:
7680 +       if (dentry->d_inode->i_generation == fh[Fh_igen])
7681 +               goto out_unlock; /* success */
7682 +
7683 +       dput(dentry);
7684 +       dentry = ERR_PTR(-ESTALE);
7685 +out_unlock:
7686 +       si_read_unlock(sb);
7687 +out:
7688 +       AuTraceErrPtr(dentry);
7689 +       return dentry;
7690 +}
7691 +
7692 +#if 0 /* reserved for future use */
7693 +/* support subtreecheck option */
7694 +static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
7695 +                                       int fh_len, int fh_type)
7696 +{
7697 +       struct dentry *parent;
7698 +       __u32 *fh = fid->raw;
7699 +       ino_t dir_ino;
7700 +
7701 +       dir_ino = decode_ino(fh + Fh_dir_ino);
7702 +       parent = decode_by_ino(sb, dir_ino, 0);
7703 +       if (IS_ERR(parent))
7704 +               goto out;
7705 +       if (!parent)
7706 +               parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
7707 +                                       dir_ino, fh, fh_len);
7708 +
7709 +out:
7710 +       AuTraceErrPtr(parent);
7711 +       return parent;
7712 +}
7713 +#endif
7714 +
7715 +/* ---------------------------------------------------------------------- */
7716 +
7717 +static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
7718 +                         int connectable)
7719 +{
7720 +       int err;
7721 +       aufs_bindex_t bindex, bend;
7722 +       struct super_block *sb, *h_sb;
7723 +       struct inode *inode;
7724 +       struct dentry *parent, *h_parent;
7725 +       struct au_branch *br;
7726 +
7727 +       AuDebugOn(au_test_anon(dentry));
7728 +
7729 +       parent = NULL;
7730 +       err = -ENOSPC;
7731 +       if (unlikely(*max_len <= Fh_tail)) {
7732 +               AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
7733 +               goto out;
7734 +       }
7735 +
7736 +       err = FILEID_ROOT;
7737 +       if (IS_ROOT(dentry)) {
7738 +               AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
7739 +               goto out;
7740 +       }
7741 +
7742 +       err = -EIO;
7743 +       h_parent = NULL;
7744 +       sb = dentry->d_sb;
7745 +       aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
7746 +       parent = dget_parent(dentry);
7747 +       di_read_lock_parent(parent, !AuLock_IR);
7748 +       inode = dentry->d_inode;
7749 +       AuDebugOn(!inode);
7750 +#ifdef CONFIG_AUFS_DEBUG
7751 +       if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7752 +               AuWarn1("NFS-exporting requires xino\n");
7753 +#endif
7754 +
7755 +       bend = au_dbtaildir(parent);
7756 +       for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
7757 +               h_parent = au_h_dptr(parent, bindex);
7758 +               if (h_parent) {
7759 +                       dget(h_parent);
7760 +                       break;
7761 +               }
7762 +       }
7763 +       if (unlikely(!h_parent))
7764 +               goto out_unlock;
7765 +
7766 +       err = -EPERM;
7767 +       br = au_sbr(sb, bindex);
7768 +       h_sb = br->br_mnt->mnt_sb;
7769 +       if (unlikely(!h_sb->s_export_op)) {
7770 +               AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
7771 +               goto out_dput;
7772 +       }
7773 +
7774 +       fh[Fh_br_id] = br->br_id;
7775 +       fh[Fh_sigen] = au_sigen(sb);
7776 +       encode_ino(fh + Fh_ino, inode->i_ino);
7777 +       encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
7778 +       fh[Fh_igen] = inode->i_generation;
7779 +
7780 +       *max_len -= Fh_tail;
7781 +       fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
7782 +                                          max_len,
7783 +                                          /*connectable or subtreecheck*/0);
7784 +       err = fh[Fh_h_type];
7785 +       *max_len += Fh_tail;
7786 +       /* todo: macros? */
7787 +       if (err != 255)
7788 +               err = 99;
7789 +       else
7790 +               AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
7791 +
7792 +out_dput:
7793 +       dput(h_parent);
7794 +out_unlock:
7795 +       di_read_unlock(parent, !AuLock_IR);
7796 +       dput(parent);
7797 +       aufs_read_unlock(dentry, AuLock_IR);
7798 +out:
7799 +       if (unlikely(err < 0))
7800 +               err = 255;
7801 +       return err;
7802 +}
7803 +
7804 +/* ---------------------------------------------------------------------- */
7805 +
7806 +static int aufs_commit_metadata(struct inode *inode)
7807 +{
7808 +       int err;
7809 +       aufs_bindex_t bindex;
7810 +       struct super_block *sb;
7811 +       struct inode *h_inode;
7812 +       int (*f)(struct inode *inode);
7813 +
7814 +       sb = inode->i_sb;
7815 +       si_read_lock(sb, AuLock_FLUSH);
7816 +       ii_write_lock_child(inode);
7817 +       bindex = au_ibstart(inode);
7818 +       AuDebugOn(bindex < 0);
7819 +       h_inode = au_h_iptr(inode, bindex);
7820 +
7821 +       f = h_inode->i_sb->s_export_op->commit_metadata;
7822 +       if (f)
7823 +               err = f(h_inode);
7824 +       else {
7825 +               struct writeback_control wbc = {
7826 +                       .sync_mode      = WB_SYNC_ALL,
7827 +                       .nr_to_write    = 0 /* metadata only */
7828 +               };
7829 +
7830 +               err = sync_inode(h_inode, &wbc);
7831 +       }
7832 +
7833 +       au_cpup_attr_timesizes(inode);
7834 +       ii_write_unlock(inode);
7835 +       si_read_unlock(sb);
7836 +       return err;
7837 +}
7838 +
7839 +/* ---------------------------------------------------------------------- */
7840 +
7841 +static struct export_operations aufs_export_op = {
7842 +       .fh_to_dentry           = aufs_fh_to_dentry,
7843 +       /* .fh_to_parent        = aufs_fh_to_parent, */
7844 +       .encode_fh              = aufs_encode_fh,
7845 +       .commit_metadata        = aufs_commit_metadata
7846 +};
7847 +
7848 +void au_export_init(struct super_block *sb)
7849 +{
7850 +       struct au_sbinfo *sbinfo;
7851 +       __u32 u;
7852 +
7853 +       sb->s_export_op = &aufs_export_op;
7854 +       sbinfo = au_sbi(sb);
7855 +       sbinfo->si_xigen = NULL;
7856 +       get_random_bytes(&u, sizeof(u));
7857 +       BUILD_BUG_ON(sizeof(u) != sizeof(int));
7858 +       atomic_set(&sbinfo->si_xigen_next, u);
7859 +}
7860 diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
7861 --- /usr/share/empty/fs/aufs/file.c     1970-01-01 01:00:00.000000000 +0100
7862 +++ linux/fs/aufs/file.c        2010-10-21 09:52:43.090291764 +0200
7863 @@ -0,0 +1,652 @@
7864 +/*
7865 + * Copyright (C) 2005-2010 Junjiro R. Okajima
7866 + *
7867 + * This program, aufs is free software; you can redistribute it and/or modify
7868 + * it under the terms of the GNU General Public License as published by
7869 + * the Free Software Foundation; either version 2 of the License, or
7870 + * (at your option) any later version.
7871 + *
7872 + * This program is distributed in the hope that it will be useful,
7873 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7874 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7875 + * GNU General Public License for more details.
7876 + *
7877 + * You should have received a copy of the GNU General Public License
7878 + * along with this program; if not, write to the Free Software
7879 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
7880 + */
7881 +
7882 +/*
7883 + * handling file/dir, and address_space operation
7884 + */
7885 +
7886 +#include <linux/file.h>
7887 +#include <linux/fsnotify.h>
7888 +#include <linux/namei.h>
7889 +#include <linux/pagemap.h>
7890 +#include "aufs.h"
7891 +
7892 +/* drop flags for writing */
7893 +unsigned int au_file_roflags(unsigned int flags)
7894 +{
7895 +       flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
7896 +       flags |= O_RDONLY | O_NOATIME;
7897 +       return flags;
7898 +}
7899 +
7900 +/* common functions to regular file and dir */
7901 +struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
7902 +                      struct file *file)
7903 +{
7904 +       struct file *h_file;
7905 +       struct dentry *h_dentry;
7906 +       struct inode *h_inode;
7907 +       struct super_block *sb;
7908 +       struct au_branch *br;
7909 +       struct path h_path;
7910 +       int err, exec_flag;
7911 +
7912 +       /* a race condition can happen between open and unlink/rmdir */
7913 +       h_file = ERR_PTR(-ENOENT);
7914 +       h_dentry = au_h_dptr(dentry, bindex);
7915 +       if (au_test_nfsd() && !h_dentry)
7916 +               goto out;
7917 +       h_inode = h_dentry->d_inode;
7918 +       if (au_test_nfsd() && !h_inode)
7919 +               goto out;
7920 +       if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
7921 +                    || !h_inode))
7922 +               goto out;
7923 +
7924 +       sb = dentry->d_sb;
7925 +       br = au_sbr(sb, bindex);
7926 +       h_file = ERR_PTR(-EACCES);
7927 +       exec_flag = flags & vfsub_fmode_to_uint(FMODE_EXEC);
7928 +       if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
7929 +                       goto out;
7930 +
7931 +       /* drop flags for writing */
7932 +       if (au_test_ro(sb, bindex, dentry->d_inode))
7933 +               flags = au_file_roflags(flags);
7934 +       flags &= ~O_CREAT;
7935 +       atomic_inc(&br->br_count);
7936 +       h_path.dentry = h_dentry;
7937 +       h_path.mnt = br->br_mnt;
7938 +       if (!au_special_file(h_inode->i_mode))
7939 +               h_file = vfsub_dentry_open(&h_path, flags);
7940 +       else {
7941 +               /* this block depends upon the configuration */
7942 +               di_read_unlock(dentry, AuLock_IR);
7943 +               fi_write_unlock(file);
7944 +               si_read_unlock(sb);
7945 +               h_file = vfsub_dentry_open(&h_path, flags);
7946 +               si_noflush_read_lock(sb);
7947 +               fi_write_lock(file);
7948 +               di_read_lock_child(dentry, AuLock_IR);
7949 +       }
7950 +       if (IS_ERR(h_file))
7951 +               goto out_br;
7952 +
7953 +       if (exec_flag) {
7954 +               err = deny_write_access(h_file);
7955 +               if (unlikely(err)) {
7956 +                       fput(h_file);
7957 +                       h_file = ERR_PTR(err);
7958 +                       goto out_br;
7959 +               }
7960 +       }
7961 +       fsnotify_open(h_file);
7962 +       goto out; /* success */
7963 +
7964 +out_br:
7965 +       atomic_dec(&br->br_count);
7966 +out:
7967 +       return h_file;
7968 +}
7969 +
7970 +int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
7971 +              struct au_fidir *fidir)
7972 +{
7973 +       int err;
7974 +       struct dentry *dentry;
7975 +
7976 +       err = au_finfo_init(file, fidir);
7977 +       if (unlikely(err))
7978 +               goto out;
7979 +
7980 +       dentry = file->f_dentry;
7981 +       di_read_lock_child(dentry, AuLock_IR);
7982 +       err = open(file, vfsub_file_flags(file));
7983 +       di_read_unlock(dentry, AuLock_IR);
7984 +
7985 +       fi_write_unlock(file);
7986 +       if (unlikely(err)) {
7987 +               au_fi(file)->fi_hdir = NULL;
7988 +               au_finfo_fin(file);
7989 +       }
7990 +
7991 +out:
7992 +       return err;
7993 +}
7994 +
7995 +int au_reopen_nondir(struct file *file)
7996 +{
7997 +       int err;
7998 +       aufs_bindex_t bstart;
7999 +       struct dentry *dentry;
8000 +       struct file *h_file, *h_file_tmp;
8001 +
8002 +       dentry = file->f_dentry;
8003 +       AuDebugOn(au_special_file(dentry->d_inode->i_mode));
8004 +       bstart = au_dbstart(dentry);
8005 +       h_file_tmp = NULL;
8006 +       if (au_fbstart(file) == bstart) {
8007 +               h_file = au_hf_top(file);
8008 +               if (file->f_mode == h_file->f_mode)
8009 +                       return 0; /* success */
8010 +               h_file_tmp = h_file;
8011 +               get_file(h_file_tmp);
8012 +               au_set_h_fptr(file, bstart, NULL);
8013 +       }
8014 +       AuDebugOn(au_fi(file)->fi_hdir);
8015 +       AuDebugOn(au_fbstart(file) < bstart);
8016 +
8017 +       h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
8018 +                          file);
8019 +       err = PTR_ERR(h_file);
8020 +       if (IS_ERR(h_file))
8021 +               goto out; /* todo: close all? */
8022 +
8023 +       err = 0;
8024 +       au_set_fbstart(file, bstart);
8025 +       au_set_h_fptr(file, bstart, h_file);
8026 +       au_update_figen(file);
8027 +       /* todo: necessary? */
8028 +       /* file->f_ra = h_file->f_ra; */
8029 +
8030 +out:
8031 +       if (h_file_tmp)
8032 +               fput(h_file_tmp);
8033 +       return err;
8034 +}
8035 +
8036 +/* ---------------------------------------------------------------------- */
8037 +
8038 +static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
8039 +                       struct dentry *hi_wh)
8040 +{
8041 +       int err;
8042 +       aufs_bindex_t bstart;
8043 +       struct au_dinfo *dinfo;
8044 +       struct dentry *h_dentry;
8045 +       struct au_hdentry *hdp;
8046 +
8047 +       dinfo = au_di(file->f_dentry);
8048 +       AuRwMustWriteLock(&dinfo->di_rwsem);
8049 +
8050 +       bstart = dinfo->di_bstart;
8051 +       dinfo->di_bstart = btgt;
8052 +       hdp = dinfo->di_hdentry;
8053 +       h_dentry = hdp[0 + btgt].hd_dentry;
8054 +       hdp[0 + btgt].hd_dentry = hi_wh;
8055 +       err = au_reopen_nondir(file);
8056 +       hdp[0 + btgt].hd_dentry = h_dentry;
8057 +       dinfo->di_bstart = bstart;
8058 +
8059 +       return err;
8060 +}
8061 +
8062 +static int au_ready_to_write_wh(struct file *file, loff_t len,
8063 +                               aufs_bindex_t bcpup)
8064 +{
8065 +       int err;
8066 +       struct inode *inode;
8067 +       struct dentry *dentry, *hi_wh;
8068 +
8069 +       dentry = file->f_dentry;
8070 +       au_update_dbstart(dentry);
8071 +       inode = dentry->d_inode;
8072 +       hi_wh = au_hi_wh(inode, bcpup);
8073 +       if (!hi_wh)
8074 +               err = au_sio_cpup_wh(dentry, bcpup, len, file);
8075 +       else
8076 +               /* already copied-up after unlink */
8077 +               err = au_reopen_wh(file, bcpup, hi_wh);
8078 +
8079 +       if (!err
8080 +           && inode->i_nlink > 1
8081 +           && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
8082 +               au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
8083 +
8084 +       return err;
8085 +}
8086 +
8087 +/*
8088 + * prepare the @file for writing.
8089 + */
8090 +int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
8091 +{
8092 +       int err;
8093 +       aufs_bindex_t bstart, bcpup;
8094 +       struct dentry *dentry, *parent, *h_dentry;
8095 +       struct inode *h_inode, *inode;
8096 +       struct super_block *sb;
8097 +       struct file *h_file;
8098 +
8099 +       dentry = file->f_dentry;
8100 +       sb = dentry->d_sb;
8101 +       inode = dentry->d_inode;
8102 +       AuDebugOn(au_special_file(inode->i_mode));
8103 +       bstart = au_fbstart(file);
8104 +       err = au_test_ro(sb, bstart, inode);
8105 +       if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
8106 +               err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
8107 +               goto out;
8108 +       }
8109 +
8110 +       /* need to cpup */
8111 +       parent = dget_parent(dentry);
8112 +       di_write_lock_parent(parent);
8113 +       err = AuWbrCopyup(au_sbi(sb), dentry);
8114 +       bcpup = err;
8115 +       if (unlikely(err < 0))
8116 +               goto out_dgrade;
8117 +       err = 0;
8118 +
8119 +       if (!au_h_dptr(parent, bcpup)) {
8120 +               err = au_cpup_dirs(dentry, bcpup);
8121 +               if (unlikely(err))
8122 +                       goto out_dgrade;
8123 +       }
8124 +
8125 +       err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
8126 +                    AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8127 +       if (unlikely(err))
8128 +               goto out_dgrade;
8129 +
8130 +       h_dentry = au_hf_top(file)->f_dentry;
8131 +       h_inode = h_dentry->d_inode;
8132 +       mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8133 +       h_file = au_h_open_pre(dentry, bstart);
8134 +       if (IS_ERR(h_file)) {
8135 +               err = PTR_ERR(h_file);
8136 +               h_file = NULL;
8137 +       } else if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
8138 +           /* || !h_inode->i_nlink */) {
8139 +               err = au_ready_to_write_wh(file, len, bcpup);
8140 +               di_downgrade_lock(parent, AuLock_IR);
8141 +       } else {
8142 +               di_downgrade_lock(parent, AuLock_IR);
8143 +               if (!au_h_dptr(dentry, bcpup))
8144 +                       err = au_sio_cpup_simple(dentry, bcpup, len,
8145 +                                                AuCpup_DTIME);
8146 +               if (!err)
8147 +                       err = au_reopen_nondir(file);
8148 +       }
8149 +       mutex_unlock(&h_inode->i_mutex);
8150 +       au_h_open_post(dentry, bstart, h_file);
8151 +
8152 +       if (!err) {
8153 +               au_pin_set_parent_lflag(pin, /*lflag*/0);
8154 +               goto out_dput; /* success */
8155 +       }
8156 +       au_unpin(pin);
8157 +       goto out_unlock;
8158 +
8159 +out_dgrade:
8160 +       di_downgrade_lock(parent, AuLock_IR);
8161 +out_unlock:
8162 +       di_read_unlock(parent, AuLock_IR);
8163 +out_dput:
8164 +       dput(parent);
8165 +out:
8166 +       return err;
8167 +}
8168 +
8169 +/* ---------------------------------------------------------------------- */
8170 +
8171 +int au_do_flush(struct file *file, fl_owner_t id,
8172 +               int (*flush)(struct file *file, fl_owner_t id))
8173 +{
8174 +       int err;
8175 +       struct dentry *dentry;
8176 +       struct super_block *sb;
8177 +       struct inode *inode;
8178 +
8179 +       dentry = file->f_dentry;
8180 +       sb = dentry->d_sb;
8181 +       inode = dentry->d_inode;
8182 +       si_noflush_read_lock(sb);
8183 +       fi_read_lock(file);
8184 +       ii_read_lock_child(inode);
8185 +
8186 +       err = flush(file, id);
8187 +       au_cpup_attr_timesizes(inode);
8188 +
8189 +       ii_read_unlock(inode);
8190 +       fi_read_unlock(file);
8191 +       si_read_unlock(sb);
8192 +       return err;
8193 +}
8194 +
8195 +/* ---------------------------------------------------------------------- */
8196 +
8197 +static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
8198 +{
8199 +       int err;
8200 +       aufs_bindex_t bstart;
8201 +       struct au_pin pin;
8202 +       struct au_finfo *finfo;
8203 +       struct dentry *dentry, *parent, *hi_wh;
8204 +       struct inode *inode;
8205 +       struct super_block *sb;
8206 +
8207 +       FiMustWriteLock(file);
8208 +
8209 +       err = 0;
8210 +       finfo = au_fi(file);
8211 +       dentry = file->f_dentry;
8212 +       sb = dentry->d_sb;
8213 +       inode = dentry->d_inode;
8214 +       bstart = au_ibstart(inode);
8215 +       if (bstart == finfo->fi_btop)
8216 +               goto out;
8217 +
8218 +       parent = dget_parent(dentry);
8219 +       if (au_test_ro(sb, bstart, inode)) {
8220 +               di_read_lock_parent(parent, !AuLock_IR);
8221 +               err = AuWbrCopyup(au_sbi(sb), dentry);
8222 +               bstart = err;
8223 +               di_read_unlock(parent, !AuLock_IR);
8224 +               if (unlikely(err < 0))
8225 +                       goto out_parent;
8226 +               err = 0;
8227 +       }
8228 +
8229 +       di_read_lock_parent(parent, AuLock_IR);
8230 +       hi_wh = au_hi_wh(inode, bstart);
8231 +       if (au_opt_test(au_mntflags(sb), PLINK)
8232 +           && au_plink_test(inode)
8233 +           && !d_unhashed(dentry)) {
8234 +               err = au_test_and_cpup_dirs(dentry, bstart);
8235 +               if (unlikely(err))
8236 +                       goto out_unlock;
8237 +
8238 +               /* always superio. */
8239 +               err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
8240 +                            AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8241 +               if (!err)
8242 +                       err = au_sio_cpup_simple(dentry, bstart, -1,
8243 +                                                AuCpup_DTIME);
8244 +               au_unpin(&pin);
8245 +       } else if (hi_wh) {
8246 +               /* already copied-up after unlink */
8247 +               err = au_reopen_wh(file, bstart, hi_wh);
8248 +               *need_reopen = 0;
8249 +       }
8250 +
8251 +out_unlock:
8252 +       di_read_unlock(parent, AuLock_IR);
8253 +out_parent:
8254 +       dput(parent);
8255 +out:
8256 +       return err;
8257 +}
8258 +
8259 +static void au_do_refresh_dir(struct file *file)
8260 +{
8261 +       aufs_bindex_t bindex, bend, new_bindex, brid;
8262 +       struct au_hfile *p, tmp, *q;
8263 +       struct au_finfo *finfo;
8264 +       struct super_block *sb;
8265 +       struct au_fidir *fidir;
8266 +
8267 +       FiMustWriteLock(file);
8268 +
8269 +       sb = file->f_dentry->d_sb;
8270 +       finfo = au_fi(file);
8271 +       fidir = finfo->fi_hdir;
8272 +       AuDebugOn(!fidir);
8273 +       p = fidir->fd_hfile + finfo->fi_btop;
8274 +       brid = p->hf_br->br_id;
8275 +       bend = fidir->fd_bbot;
8276 +       for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
8277 +               if (!p->hf_file)
8278 +                       continue;
8279 +
8280 +               new_bindex = au_br_index(sb, p->hf_br->br_id);
8281 +               if (new_bindex == bindex)
8282 +                       continue;
8283 +               if (new_bindex < 0) {
8284 +                       au_set_h_fptr(file, bindex, NULL);
8285 +                       continue;
8286 +               }
8287 +
8288 +               /* swap two lower inode, and loop again */
8289 +               q = fidir->fd_hfile + new_bindex;
8290 +               tmp = *q;
8291 +               *q = *p;
8292 +               *p = tmp;
8293 +               if (tmp.hf_file) {
8294 +                       bindex--;
8295 +                       p--;
8296 +               }
8297 +       }
8298 +
8299 +       p = fidir->fd_hfile;
8300 +       if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
8301 +               bend = au_sbend(sb);
8302 +               for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
8303 +                    finfo->fi_btop++, p++)
8304 +                       if (p->hf_file) {
8305 +                               if (p->hf_file->f_dentry
8306 +                                   && p->hf_file->f_dentry->d_inode)
8307 +                                       break;
8308 +                               else
8309 +                                       au_hfput(p, file);
8310 +                       }
8311 +       } else {
8312 +               bend = au_br_index(sb, brid);
8313 +               for (finfo->fi_btop = 0; finfo->fi_btop < bend;
8314 +                    finfo->fi_btop++, p++)
8315 +                       if (p->hf_file)
8316 +                               au_hfput(p, file);
8317 +               bend = au_sbend(sb);
8318 +       }
8319 +
8320 +       p = fidir->fd_hfile + bend;
8321 +       for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
8322 +            fidir->fd_bbot--, p--)
8323 +               if (p->hf_file) {
8324 +                       if (p->hf_file->f_dentry
8325 +                           && p->hf_file->f_dentry->d_inode)
8326 +                               break;
8327 +                       else
8328 +                               au_hfput(p, file);
8329 +               }
8330 +       AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
8331 +}
8332 +
8333 +/*
8334 + * after branch manipulating, refresh the file.
8335 + */
8336 +static int refresh_file(struct file *file, int (*reopen)(struct file *file))
8337 +{
8338 +       int err, need_reopen;
8339 +       aufs_bindex_t bend, bindex;
8340 +       struct dentry *dentry;
8341 +       struct au_finfo *finfo;
8342 +       struct au_hfile *hfile;
8343 +
8344 +       dentry = file->f_dentry;
8345 +       finfo = au_fi(file);
8346 +       if (!finfo->fi_hdir) {
8347 +               hfile = &finfo->fi_htop;
8348 +               AuDebugOn(!hfile->hf_file);
8349 +               bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
8350 +               AuDebugOn(bindex < 0);
8351 +               if (bindex != finfo->fi_btop)
8352 +                       au_set_fbstart(file, bindex);
8353 +       } else {
8354 +               err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
8355 +               if (unlikely(err))
8356 +                       goto out;
8357 +               au_do_refresh_dir(file);
8358 +       }
8359 +
8360 +       err = 0;
8361 +       need_reopen = 1;
8362 +       if (!au_test_mmapped(file))
8363 +               err = au_file_refresh_by_inode(file, &need_reopen);
8364 +       if (!err && need_reopen && !d_unhashed(dentry))
8365 +               err = reopen(file);
8366 +       if (!err) {
8367 +               au_update_figen(file);
8368 +               goto out; /* success */
8369 +       }
8370 +
8371 +       /* error, close all lower files */
8372 +       if (finfo->fi_hdir) {
8373 +               bend = au_fbend_dir(file);
8374 +               for (bindex = au_fbstart(file); bindex <= bend; bindex++)
8375 +                       au_set_h_fptr(file, bindex, NULL);
8376 +       }
8377 +
8378 +out:
8379 +       return err;
8380 +}
8381 +
8382 +/* common function to regular file and dir */
8383 +int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8384 +                         int wlock)
8385 +{
8386 +       int err;
8387 +       unsigned int sigen, figen;
8388 +       aufs_bindex_t bstart;
8389 +       unsigned char pseudo_link;
8390 +       struct dentry *dentry;
8391 +       struct inode *inode;
8392 +
8393 +       err = 0;
8394 +       dentry = file->f_dentry;
8395 +       inode = dentry->d_inode;
8396 +       AuDebugOn(au_special_file(inode->i_mode));
8397 +       sigen = au_sigen(dentry->d_sb);
8398 +       fi_write_lock(file);
8399 +       figen = au_figen(file);
8400 +       di_write_lock_child(dentry);
8401 +       bstart = au_dbstart(dentry);
8402 +       pseudo_link = (bstart != au_ibstart(inode));
8403 +       if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
8404 +               if (!wlock) {
8405 +                       di_downgrade_lock(dentry, AuLock_IR);
8406 +                       fi_downgrade_lock(file);
8407 +               }
8408 +               goto out; /* success */
8409 +       }
8410 +
8411 +       AuDbg("sigen %d, figen %d\n", sigen, figen);
8412 +       if (sigen != au_digen(dentry)
8413 +           || sigen != au_iigen(inode)) {
8414 +               err = au_reval_dpath(dentry, sigen);
8415 +               if (unlikely(err < 0))
8416 +                       goto out;
8417 +               AuDebugOn(au_digen(dentry) != sigen
8418 +                         || au_iigen(inode) != sigen);
8419 +       }
8420 +
8421 +       err = refresh_file(file, reopen);
8422 +       if (!err) {
8423 +               if (!wlock) {
8424 +                       di_downgrade_lock(dentry, AuLock_IR);
8425 +                       fi_downgrade_lock(file);
8426 +               }
8427 +       } else {
8428 +               di_write_unlock(dentry);
8429 +               fi_write_unlock(file);
8430 +       }
8431 +
8432 +out:
8433 +       return err;
8434 +}
8435 +
8436 +/* ---------------------------------------------------------------------- */
8437 +
8438 +/* cf. aufs_nopage() */
8439 +/* for madvise(2) */
8440 +static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
8441 +{
8442 +       unlock_page(page);
8443 +       return 0;
8444 +}
8445 +
8446 +/* it will never be called, but necessary to support O_DIRECT */
8447 +static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
8448 +                             const struct iovec *iov, loff_t offset,
8449 +                             unsigned long nr_segs)
8450 +{ BUG(); return 0; }
8451 +
8452 +/*
8453 + * it will never be called, but madvise and fadvise behaves differently
8454 + * when get_xip_mem is defined
8455 + */
8456 +static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
8457 +                           int create, void **kmem, unsigned long *pfn)
8458 +{ BUG(); return 0; }
8459 +
8460 +/* they will never be called. */
8461 +#ifdef CONFIG_AUFS_DEBUG
8462 +static int aufs_write_begin(struct file *file, struct address_space *mapping,
8463 +                           loff_t pos, unsigned len, unsigned flags,
8464 +                           struct page **pagep, void **fsdata)
8465 +{ AuUnsupport(); return 0; }
8466 +static int aufs_write_end(struct file *file, struct address_space *mapping,
8467 +                         loff_t pos, unsigned len, unsigned copied,
8468 +                         struct page *page, void *fsdata)
8469 +{ AuUnsupport(); return 0; }
8470 +static int aufs_writepage(struct page *page, struct writeback_control *wbc)
8471 +{ AuUnsupport(); return 0; }
8472 +static void aufs_sync_page(struct page *page)
8473 +{ AuUnsupport(); }
8474 +
8475 +static int aufs_set_page_dirty(struct page *page)
8476 +{ AuUnsupport(); return 0; }
8477 +static void aufs_invalidatepage(struct page *page, unsigned long offset)
8478 +{ AuUnsupport(); }
8479 +static int aufs_releasepage(struct page *page, gfp_t gfp)
8480 +{ AuUnsupport(); return 0; }
8481 +static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
8482 +                           struct page *page)
8483 +{ AuUnsupport(); return 0; }
8484 +static int aufs_launder_page(struct page *page)
8485 +{ AuUnsupport(); return 0; }
8486 +static int aufs_is_partially_uptodate(struct page *page,
8487 +                                     read_descriptor_t *desc,
8488 +                                     unsigned long from)
8489 +{ AuUnsupport(); return 0; }
8490 +static int aufs_error_remove_page(struct address_space *mapping,
8491 +                                 struct page *page)
8492 +{ AuUnsupport(); return 0; }
8493 +#endif /* CONFIG_AUFS_DEBUG */
8494 +
8495 +const struct address_space_operations aufs_aop = {
8496 +       .readpage               = aufs_readpage,
8497 +       .direct_IO              = aufs_direct_IO,
8498 +       .get_xip_mem            = aufs_get_xip_mem,
8499 +#ifdef CONFIG_AUFS_DEBUG
8500 +       .writepage              = aufs_writepage,
8501 +       .sync_page              = aufs_sync_page,
8502 +       /* no writepages, because of writepage */
8503 +       .set_page_dirty         = aufs_set_page_dirty,
8504 +       /* no readpages, because of readpage */
8505 +       .write_begin            = aufs_write_begin,
8506 +       .write_end              = aufs_write_end,
8507 +       /* no bmap, no block device */
8508 +       .invalidatepage         = aufs_invalidatepage,
8509 +       .releasepage            = aufs_releasepage,
8510 +       .migratepage            = aufs_migratepage,
8511 +       .launder_page           = aufs_launder_page,
8512 +       .is_partially_uptodate  = aufs_is_partially_uptodate,
8513 +       .error_remove_page      = aufs_error_remove_page
8514 +#endif /* CONFIG_AUFS_DEBUG */
8515 +};
8516 diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
8517 --- /usr/share/empty/fs/aufs/file.h     1970-01-01 01:00:00.000000000 +0100
8518 +++ linux/fs/aufs/file.h        2010-10-21 09:52:43.090291764 +0200
8519 @@ -0,0 +1,238 @@
8520 +/*
8521 + * Copyright (C) 2005-2010 Junjiro R. Okajima
8522 + *
8523 + * This program, aufs is free software; you can redistribute it and/or modify
8524 + * it under the terms of the GNU General Public License as published by
8525 + * the Free Software Foundation; either version 2 of the License, or
8526 + * (at your option) any later version.
8527 + *
8528 + * This program is distributed in the hope that it will be useful,
8529 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8530 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8531 + * GNU General Public License for more details.
8532 + *
8533 + * You should have received a copy of the GNU General Public License
8534 + * along with this program; if not, write to the Free Software
8535 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
8536 + */
8537 +
8538 +/*
8539 + * file operations
8540 + */
8541 +
8542 +#ifndef __AUFS_FILE_H__
8543 +#define __AUFS_FILE_H__
8544 +
8545 +#ifdef __KERNEL__
8546 +
8547 +#include <linux/fs.h>
8548 +#include <linux/poll.h>
8549 +#include <linux/aufs_type.h>
8550 +#include "rwsem.h"
8551 +
8552 +struct au_branch;
8553 +struct au_hfile {
8554 +       struct file             *hf_file;
8555 +       struct au_branch        *hf_br;
8556 +};
8557 +
8558 +struct au_vdir;
8559 +struct au_fidir {
8560 +       aufs_bindex_t           fd_bbot;
8561 +       aufs_bindex_t           fd_nent;
8562 +       struct au_vdir          *fd_vdir_cache;
8563 +       struct au_hfile         fd_hfile[];
8564 +};
8565 +
8566 +static inline int au_fidir_sz(int nent)
8567 +{
8568 +       AuDebugOn(nent < 0);
8569 +       return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
8570 +}
8571 +
8572 +struct au_finfo {
8573 +       atomic_t                fi_generation;
8574 +
8575 +       struct au_rwsem         fi_rwsem;
8576 +       aufs_bindex_t           fi_btop;
8577 +
8578 +       /* do not union them */
8579 +       struct {                                /* for non-dir */
8580 +               struct au_hfile                 fi_htop;
8581 +               struct vm_operations_struct     *fi_hvmop;
8582 +               struct mutex                    fi_vm_mtx;
8583 +               struct mutex                    fi_mmap;
8584 +       };
8585 +       struct au_fidir         *fi_hdir;       /* for dir only */
8586 +} ____cacheline_aligned_in_smp;
8587 +
8588 +/* ---------------------------------------------------------------------- */
8589 +
8590 +/* file.c */
8591 +extern const struct address_space_operations aufs_aop;
8592 +unsigned int au_file_roflags(unsigned int flags);
8593 +struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8594 +                      struct file *file);
8595 +int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8596 +              struct au_fidir *fidir);
8597 +int au_reopen_nondir(struct file *file);
8598 +struct au_pin;
8599 +int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
8600 +int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8601 +                         int wlock);
8602 +int au_do_flush(struct file *file, fl_owner_t id,
8603 +               int (*flush)(struct file *file, fl_owner_t id));
8604 +
8605 +/* poll.c */
8606 +#ifdef CONFIG_AUFS_POLL
8607 +unsigned int aufs_poll(struct file *file, poll_table *wait);
8608 +#endif
8609 +
8610 +#ifdef CONFIG_AUFS_BR_HFSPLUS
8611 +/* hfsplus.c */
8612 +struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
8613 +void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
8614 +                   struct file *h_file);
8615 +#else
8616 +static inline
8617 +struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
8618 +{
8619 +       return NULL;
8620 +}
8621 +
8622 +AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
8623 +          struct file *h_file);
8624 +#endif
8625 +
8626 +/* f_op.c */
8627 +extern const struct file_operations aufs_file_fop;
8628 +extern const struct vm_operations_struct aufs_vm_ops;
8629 +int au_do_open_nondir(struct file *file, int flags);
8630 +int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
8631 +
8632 +#ifdef CONFIG_AUFS_SP_IATTR
8633 +/* f_op_sp.c */
8634 +int au_special_file(umode_t mode);
8635 +void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
8636 +#else
8637 +AuStubInt0(au_special_file, umode_t mode)
8638 +static inline void au_init_special_fop(struct inode *inode, umode_t mode,
8639 +                                      dev_t rdev)
8640 +{
8641 +       init_special_inode(inode, mode, rdev);
8642 +}
8643 +#endif
8644 +
8645 +/* finfo.c */
8646 +void au_hfput(struct au_hfile *hf, struct file *file);
8647 +void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
8648 +                  struct file *h_file);
8649 +
8650 +void au_update_figen(struct file *file);
8651 +void au_fi_mmap_lock(struct file *file);
8652 +void au_fi_mmap_unlock(struct file *file);
8653 +struct au_fidir *au_fidir_alloc(struct super_block *sb);
8654 +int au_fidir_realloc(struct au_finfo *finfo, int nbr);
8655 +
8656 +void au_fi_init_once(void *_fi);
8657 +void au_finfo_fin(struct file *file);
8658 +int au_finfo_init(struct file *file, struct au_fidir *fidir);
8659 +
8660 +/* ioctl.c */
8661 +long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
8662 +#ifdef CONFIG_COMPAT
8663 +long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
8664 +                          unsigned long arg);
8665 +#endif
8666 +
8667 +/* ---------------------------------------------------------------------- */
8668 +
8669 +static inline struct au_finfo *au_fi(struct file *file)
8670 +{
8671 +       return file->private_data;
8672 +}
8673 +
8674 +/* ---------------------------------------------------------------------- */
8675 +
8676 +/*
8677 + * fi_read_lock, fi_write_lock,
8678 + * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
8679 + */
8680 +AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
8681 +
8682 +#define FiMustNoWaiters(f)     AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
8683 +#define FiMustAnyLock(f)       AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
8684 +#define FiMustWriteLock(f)     AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
8685 +
8686 +/* ---------------------------------------------------------------------- */
8687 +
8688 +/* todo: hard/soft set? */
8689 +static inline aufs_bindex_t au_fbstart(struct file *file)
8690 +{
8691 +       FiMustAnyLock(file);
8692 +       return au_fi(file)->fi_btop;
8693 +}
8694 +
8695 +static inline aufs_bindex_t au_fbend_dir(struct file *file)
8696 +{
8697 +       FiMustAnyLock(file);
8698 +       AuDebugOn(!au_fi(file)->fi_hdir);
8699 +       return au_fi(file)->fi_hdir->fd_bbot;
8700 +}
8701 +
8702 +static inline struct au_vdir *au_fvdir_cache(struct file *file)
8703 +{
8704 +       FiMustAnyLock(file);
8705 +       AuDebugOn(!au_fi(file)->fi_hdir);
8706 +       return au_fi(file)->fi_hdir->fd_vdir_cache;
8707 +}
8708 +
8709 +static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
8710 +{
8711 +       FiMustWriteLock(file);
8712 +       au_fi(file)->fi_btop = bindex;
8713 +}
8714 +
8715 +static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
8716 +{
8717 +       FiMustWriteLock(file);
8718 +       AuDebugOn(!au_fi(file)->fi_hdir);
8719 +       au_fi(file)->fi_hdir->fd_bbot = bindex;
8720 +}
8721 +
8722 +static inline void au_set_fvdir_cache(struct file *file,
8723 +                                     struct au_vdir *vdir_cache)
8724 +{
8725 +       FiMustWriteLock(file);
8726 +       AuDebugOn(!au_fi(file)->fi_hdir);
8727 +       au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
8728 +}
8729 +
8730 +static inline struct file *au_hf_top(struct file *file)
8731 +{
8732 +       FiMustAnyLock(file);
8733 +       AuDebugOn(au_fi(file)->fi_hdir);
8734 +       return au_fi(file)->fi_htop.hf_file;
8735 +}
8736 +
8737 +static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
8738 +{
8739 +       FiMustAnyLock(file);
8740 +       AuDebugOn(!au_fi(file)->fi_hdir);
8741 +       return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
8742 +}
8743 +
8744 +/* todo: memory barrier? */
8745 +static inline unsigned int au_figen(struct file *f)
8746 +{
8747 +       return atomic_read(&au_fi(f)->fi_generation);
8748 +}
8749 +
8750 +static inline int au_test_mmapped(struct file *f)
8751 +{
8752 +       FiMustAnyLock(f);
8753 +       return !!(au_fi(f)->fi_hvmop);
8754 +}
8755 +
8756 +#endif /* __KERNEL__ */
8757 +#endif /* __AUFS_FILE_H__ */
8758 diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
8759 --- /usr/share/empty/fs/aufs/finfo.c    1970-01-01 01:00:00.000000000 +0100
8760 +++ linux/fs/aufs/finfo.c       2010-10-21 09:52:43.090291764 +0200
8761 @@ -0,0 +1,167 @@
8762 +/*
8763 + * Copyright (C) 2005-2010 Junjiro R. Okajima
8764 + *
8765 + * This program, aufs is free software; you can redistribute it and/or modify
8766 + * it under the terms of the GNU General Public License as published by
8767 + * the Free Software Foundation; either version 2 of the License, or
8768 + * (at your option) any later version.
8769 + *
8770 + * This program is distributed in the hope that it will be useful,
8771 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8772 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8773 + * GNU General Public License for more details.
8774 + *
8775 + * You should have received a copy of the GNU General Public License
8776 + * along with this program; if not, write to the Free Software
8777 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
8778 + */
8779 +
8780 +/*
8781 + * file private data
8782 + */
8783 +
8784 +#include <linux/file.h>
8785 +#include "aufs.h"
8786 +
8787 +void au_hfput(struct au_hfile *hf, struct file *file)
8788 +{
8789 +       /* todo: direct access f_flags */
8790 +       if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC))
8791 +               allow_write_access(hf->hf_file);
8792 +       fput(hf->hf_file);
8793 +       hf->hf_file = NULL;
8794 +       atomic_dec_return(&hf->hf_br->br_count);
8795 +       hf->hf_br = NULL;
8796 +}
8797 +
8798 +void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
8799 +{
8800 +       struct au_finfo *finfo = au_fi(file);
8801 +       struct au_hfile *hf;
8802 +       struct au_fidir *fidir;
8803 +
8804 +       fidir = finfo->fi_hdir;
8805 +       if (!fidir) {
8806 +               AuDebugOn(finfo->fi_btop != bindex);
8807 +               hf = &finfo->fi_htop;
8808 +       } else
8809 +               hf = fidir->fd_hfile + bindex;
8810 +
8811 +       if (hf && hf->hf_file)
8812 +               au_hfput(hf, file);
8813 +       if (val) {
8814 +               FiMustWriteLock(file);
8815 +               hf->hf_file = val;
8816 +               hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
8817 +       }
8818 +}
8819 +
8820 +void au_update_figen(struct file *file)
8821 +{
8822 +       atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
8823 +       /* smp_mb(); */ /* atomic_set */
8824 +}
8825 +
8826 +/* ---------------------------------------------------------------------- */
8827 +
8828 +void au_fi_mmap_lock(struct file *file)
8829 +{
8830 +       FiMustWriteLock(file);
8831 +       lockdep_off();
8832 +       mutex_lock(&au_fi(file)->fi_mmap);
8833 +       lockdep_on();
8834 +}
8835 +
8836 +void au_fi_mmap_unlock(struct file *file)
8837 +{
8838 +       lockdep_off();
8839 +       mutex_unlock(&au_fi(file)->fi_mmap);
8840 +       lockdep_on();
8841 +}
8842 +
8843 +/* ---------------------------------------------------------------------- */
8844 +
8845 +struct au_fidir *au_fidir_alloc(struct super_block *sb)
8846 +{
8847 +       struct au_fidir *fidir;
8848 +       int nbr;
8849 +
8850 +       nbr = au_sbend(sb) + 1;
8851 +       if (nbr < 2)
8852 +               nbr = 2; /* initial allocate for 2 branches */
8853 +       fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
8854 +       if (fidir) {
8855 +               fidir->fd_bbot = -1;
8856 +               fidir->fd_nent = nbr;
8857 +               fidir->fd_vdir_cache = NULL;
8858 +       }
8859 +
8860 +       return fidir;
8861 +}
8862 +
8863 +int au_fidir_realloc(struct au_finfo *finfo, int nbr)
8864 +{
8865 +       int err;
8866 +       struct au_fidir *fidir, *p;
8867 +
8868 +       AuRwMustWriteLock(&finfo->fi_rwsem);
8869 +       fidir = finfo->fi_hdir;
8870 +       AuDebugOn(!fidir);
8871 +
8872 +       err = -ENOMEM;
8873 +       p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
8874 +                        GFP_NOFS);
8875 +       if (p) {
8876 +               p->fd_nent = nbr;
8877 +               finfo->fi_hdir = p;
8878 +               err = 0;
8879 +       }
8880 +
8881 +       return err;
8882 +}
8883 +
8884 +/* ---------------------------------------------------------------------- */
8885 +
8886 +void au_finfo_fin(struct file *file)
8887 +{
8888 +       struct au_finfo *finfo;
8889 +
8890 +       finfo = au_fi(file);
8891 +       AuDebugOn(finfo->fi_hdir);
8892 +       AuRwDestroy(&finfo->fi_rwsem);
8893 +       au_cache_free_finfo(finfo);
8894 +}
8895 +
8896 +void au_fi_init_once(void *_fi)
8897 +{
8898 +       struct au_finfo *fi = _fi;
8899 +
8900 +       au_rw_init(&fi->fi_rwsem);
8901 +       mutex_init(&fi->fi_vm_mtx);
8902 +       mutex_init(&fi->fi_mmap);
8903 +}
8904 +
8905 +int au_finfo_init(struct file *file, struct au_fidir *fidir)
8906 +{
8907 +       int err;
8908 +       struct au_finfo *finfo;
8909 +       struct dentry *dentry;
8910 +
8911 +       err = -ENOMEM;
8912 +       dentry = file->f_dentry;
8913 +       finfo = au_cache_alloc_finfo();
8914 +       if (unlikely(!finfo))
8915 +               goto out;
8916 +
8917 +       err = 0;
8918 +       au_rw_write_lock(&finfo->fi_rwsem);
8919 +       finfo->fi_btop = -1;
8920 +       finfo->fi_hdir = fidir;
8921 +       atomic_set(&finfo->fi_generation, au_digen(dentry));
8922 +       /* smp_mb(); */ /* atomic_set */
8923 +
8924 +       file->private_data = finfo;
8925 +
8926 +out:
8927 +       return err;
8928 +}
8929 diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
8930 --- /usr/share/empty/fs/aufs/f_op.c     1970-01-01 01:00:00.000000000 +0100
8931 +++ linux/fs/aufs/f_op.c        2010-10-21 09:52:43.090291764 +0200
8932 @@ -0,0 +1,886 @@
8933 +/*
8934 + * Copyright (C) 2005-2010 Junjiro R. Okajima
8935 + *
8936 + * This program, aufs is free software; you can redistribute it and/or modify
8937 + * it under the terms of the GNU General Public License as published by
8938 + * the Free Software Foundation; either version 2 of the License, or
8939 + * (at your option) any later version.
8940 + *
8941 + * This program is distributed in the hope that it will be useful,
8942 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8943 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8944 + * GNU General Public License for more details.
8945 + *
8946 + * You should have received a copy of the GNU General Public License
8947 + * along with this program; if not, write to the Free Software
8948 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
8949 + */
8950 +
8951 +/*
8952 + * file and vm operations
8953 + */
8954 +
8955 +#include <linux/file.h>
8956 +#include <linux/fs_stack.h>
8957 +#include <linux/mman.h>
8958 +#include <linux/mm.h>
8959 +#include <linux/security.h>
8960 +#include "aufs.h"
8961 +
8962 +int au_do_open_nondir(struct file *file, int flags)
8963 +{
8964 +       int err;
8965 +       aufs_bindex_t bindex;
8966 +       struct file *h_file;
8967 +       struct dentry *dentry;
8968 +       struct au_finfo *finfo;
8969 +
8970 +       FiMustWriteLock(file);
8971 +
8972 +       err = 0;
8973 +       dentry = file->f_dentry;
8974 +       finfo = au_fi(file);
8975 +       memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
8976 +       finfo->fi_hvmop = NULL;
8977 +       bindex = au_dbstart(dentry);
8978 +       h_file = au_h_open(dentry, bindex, flags, file);
8979 +       if (IS_ERR(h_file))
8980 +               err = PTR_ERR(h_file);
8981 +       else {
8982 +               au_set_fbstart(file, bindex);
8983 +               au_set_h_fptr(file, bindex, h_file);
8984 +               au_update_figen(file);
8985 +               /* todo: necessary? */
8986 +               /* file->f_ra = h_file->f_ra; */
8987 +       }
8988 +       return err;
8989 +}
8990 +
8991 +static int aufs_open_nondir(struct inode *inode __maybe_unused,
8992 +                           struct file *file)
8993 +{
8994 +       int err;
8995 +       struct super_block *sb;
8996 +
8997 +       AuDbg("%.*s, f_ flags 0x%x, f_mode 0x%x\n",
8998 +             AuDLNPair(file->f_dentry), vfsub_file_flags(file),
8999 +             file->f_mode);
9000 +
9001 +       sb = file->f_dentry->d_sb;
9002 +       si_read_lock(sb, AuLock_FLUSH);
9003 +       err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
9004 +       si_read_unlock(sb);
9005 +       return err;
9006 +}
9007 +
9008 +int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
9009 +{
9010 +       struct au_finfo *finfo;
9011 +       aufs_bindex_t bindex;
9012 +
9013 +       finfo = au_fi(file);
9014 +       bindex = finfo->fi_btop;
9015 +       if (bindex >= 0)
9016 +               au_set_h_fptr(file, bindex, NULL);
9017 +
9018 +       au_finfo_fin(file);
9019 +       return 0;
9020 +}
9021 +
9022 +/* ---------------------------------------------------------------------- */
9023 +
9024 +static int au_do_flush_nondir(struct file *file, fl_owner_t id)
9025 +{
9026 +       int err;
9027 +       struct file *h_file;
9028 +
9029 +       err = 0;
9030 +       h_file = au_hf_top(file);
9031 +       if (h_file)
9032 +               err = vfsub_flush(h_file, id);
9033 +       return err;
9034 +}
9035 +
9036 +static int aufs_flush_nondir(struct file *file, fl_owner_t id)
9037 +{
9038 +       return au_do_flush(file, id, au_do_flush_nondir);
9039 +}
9040 +
9041 +/* ---------------------------------------------------------------------- */
9042 +
9043 +static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
9044 +                        loff_t *ppos)
9045 +{
9046 +       ssize_t err;
9047 +       struct dentry *dentry;
9048 +       struct file *h_file;
9049 +       struct super_block *sb;
9050 +
9051 +       dentry = file->f_dentry;
9052 +       sb = dentry->d_sb;
9053 +       si_read_lock(sb, AuLock_FLUSH);
9054 +       err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9055 +       if (unlikely(err))
9056 +               goto out;
9057 +
9058 +       h_file = au_hf_top(file);
9059 +       err = vfsub_read_u(h_file, buf, count, ppos);
9060 +       /* todo: necessary? */
9061 +       /* file->f_ra = h_file->f_ra; */
9062 +       fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9063 +
9064 +       di_read_unlock(dentry, AuLock_IR);
9065 +       fi_read_unlock(file);
9066 +out:
9067 +       si_read_unlock(sb);
9068 +       return err;
9069 +}
9070 +
9071 +static ssize_t aufs_write(struct file *file, const char __user *ubuf,
9072 +                         size_t count, loff_t *ppos)
9073 +{
9074 +       ssize_t err;
9075 +       struct au_pin pin;
9076 +       struct dentry *dentry;
9077 +       struct inode *inode;
9078 +       struct super_block *sb;
9079 +       struct file *h_file;
9080 +       char __user *buf = (char __user *)ubuf;
9081 +
9082 +       dentry = file->f_dentry;
9083 +       sb = dentry->d_sb;
9084 +       inode = dentry->d_inode;
9085 +       mutex_lock(&inode->i_mutex);
9086 +       si_read_lock(sb, AuLock_FLUSH);
9087 +
9088 +       err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9089 +       if (unlikely(err))
9090 +               goto out;
9091 +
9092 +       err = au_ready_to_write(file, -1, &pin);
9093 +       di_downgrade_lock(dentry, AuLock_IR);
9094 +       if (unlikely(err))
9095 +               goto out_unlock;
9096 +
9097 +       h_file = au_hf_top(file);
9098 +       au_unpin(&pin);
9099 +       err = vfsub_write_u(h_file, buf, count, ppos);
9100 +       au_cpup_attr_timesizes(inode);
9101 +       inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9102 +
9103 +out_unlock:
9104 +       di_read_unlock(dentry, AuLock_IR);
9105 +       fi_write_unlock(file);
9106 +out:
9107 +       si_read_unlock(sb);
9108 +       mutex_unlock(&inode->i_mutex);
9109 +       return err;
9110 +}
9111 +
9112 +static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
9113 +                        const struct iovec *iov, unsigned long nv, loff_t pos)
9114 +{
9115 +       ssize_t err;
9116 +       struct file *file;
9117 +       ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
9118 +                       loff_t);
9119 +
9120 +       err = security_file_permission(h_file, rw);
9121 +       if (unlikely(err))
9122 +               goto out;
9123 +
9124 +       err = -ENOSYS;
9125 +       func = NULL;
9126 +       if (rw == MAY_READ)
9127 +               func = h_file->f_op->aio_read;
9128 +       else if (rw == MAY_WRITE)
9129 +               func = h_file->f_op->aio_write;
9130 +       if (func) {
9131 +               file = kio->ki_filp;
9132 +               kio->ki_filp = h_file;
9133 +               err = func(kio, iov, nv, pos);
9134 +               kio->ki_filp = file;
9135 +       } else
9136 +               /* currently there is no such fs */
9137 +               WARN_ON_ONCE(1);
9138 +
9139 +out:
9140 +       return err;
9141 +}
9142 +
9143 +static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
9144 +                            unsigned long nv, loff_t pos)
9145 +{
9146 +       ssize_t err;
9147 +       struct file *file, *h_file;
9148 +       struct dentry *dentry;
9149 +       struct super_block *sb;
9150 +
9151 +       file = kio->ki_filp;
9152 +       dentry = file->f_dentry;
9153 +       sb = dentry->d_sb;
9154 +       si_read_lock(sb, AuLock_FLUSH);
9155 +       err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9156 +       if (unlikely(err))
9157 +               goto out;
9158 +
9159 +       h_file = au_hf_top(file);
9160 +       err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
9161 +       /* todo: necessary? */
9162 +       /* file->f_ra = h_file->f_ra; */
9163 +       fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9164 +       di_read_unlock(dentry, AuLock_IR);
9165 +       fi_read_unlock(file);
9166 +
9167 +out:
9168 +       si_read_unlock(sb);
9169 +       return err;
9170 +}
9171 +
9172 +static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
9173 +                             unsigned long nv, loff_t pos)
9174 +{
9175 +       ssize_t err;
9176 +       struct au_pin pin;
9177 +       struct dentry *dentry;
9178 +       struct inode *inode;
9179 +       struct super_block *sb;
9180 +       struct file *file, *h_file;
9181 +
9182 +       file = kio->ki_filp;
9183 +       dentry = file->f_dentry;
9184 +       sb = dentry->d_sb;
9185 +       inode = dentry->d_inode;
9186 +       mutex_lock(&inode->i_mutex);
9187 +       si_read_lock(sb, AuLock_FLUSH);
9188 +       err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9189 +       if (unlikely(err))
9190 +               goto out;
9191 +
9192 +       err = au_ready_to_write(file, -1, &pin);
9193 +       di_downgrade_lock(dentry, AuLock_IR);
9194 +       if (unlikely(err))
9195 +               goto out_unlock;
9196 +
9197 +       au_unpin(&pin);
9198 +       h_file = au_hf_top(file);
9199 +       err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
9200 +       au_cpup_attr_timesizes(inode);
9201 +       inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9202 +
9203 +out_unlock:
9204 +       di_read_unlock(dentry, AuLock_IR);
9205 +       fi_write_unlock(file);
9206 +out:
9207 +       si_read_unlock(sb);
9208 +       mutex_unlock(&inode->i_mutex);
9209 +       return err;
9210 +}
9211 +
9212 +static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
9213 +                               struct pipe_inode_info *pipe, size_t len,
9214 +                               unsigned int flags)
9215 +{
9216 +       ssize_t err;
9217 +       struct file *h_file;
9218 +       struct dentry *dentry;
9219 +       struct super_block *sb;
9220 +
9221 +       dentry = file->f_dentry;
9222 +       sb = dentry->d_sb;
9223 +       si_read_lock(sb, AuLock_FLUSH);
9224 +       err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9225 +       if (unlikely(err))
9226 +               goto out;
9227 +
9228 +       err = -EINVAL;
9229 +       h_file = au_hf_top(file);
9230 +       if (au_test_loopback_kthread()) {
9231 +               file->f_mapping = h_file->f_mapping;
9232 +               smp_mb(); /* unnecessary? */
9233 +       }
9234 +       err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
9235 +       /* todo: necessasry? */
9236 +       /* file->f_ra = h_file->f_ra; */
9237 +       fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9238 +
9239 +       di_read_unlock(dentry, AuLock_IR);
9240 +       fi_read_unlock(file);
9241 +
9242 +out:
9243 +       si_read_unlock(sb);
9244 +       return err;
9245 +}
9246 +
9247 +static ssize_t
9248 +aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
9249 +                 size_t len, unsigned int flags)
9250 +{
9251 +       ssize_t err;
9252 +       struct au_pin pin;
9253 +       struct dentry *dentry;
9254 +       struct inode *inode;
9255 +       struct super_block *sb;
9256 +       struct file *h_file;
9257 +
9258 +       dentry = file->f_dentry;
9259 +       inode = dentry->d_inode;
9260 +       mutex_lock(&inode->i_mutex);
9261 +       sb = dentry->d_sb;
9262 +       si_read_lock(sb, AuLock_FLUSH);
9263 +
9264 +       err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9265 +       if (unlikely(err))
9266 +               goto out;
9267 +
9268 +       err = au_ready_to_write(file, -1, &pin);
9269 +       di_downgrade_lock(dentry, AuLock_IR);
9270 +       if (unlikely(err))
9271 +               goto out_unlock;
9272 +
9273 +       h_file = au_hf_top(file);
9274 +       au_unpin(&pin);
9275 +       err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
9276 +       au_cpup_attr_timesizes(inode);
9277 +       inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9278 +
9279 +out_unlock:
9280 +       di_read_unlock(dentry, AuLock_IR);
9281 +       fi_write_unlock(file);
9282 +out:
9283 +       si_read_unlock(sb);
9284 +       mutex_unlock(&inode->i_mutex);
9285 +       return err;
9286 +}
9287 +
9288 +/* ---------------------------------------------------------------------- */
9289 +
9290 +static struct file *au_safe_file(struct vm_area_struct *vma)
9291 +{
9292 +       struct file *file;
9293 +
9294 +       file = vma->vm_file;
9295 +       if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
9296 +               return file;
9297 +       return NULL;
9298 +}
9299 +
9300 +static void au_reset_file(struct vm_area_struct *vma, struct file *file)
9301 +{
9302 +       vma->vm_file = file;
9303 +       /* smp_mb(); */ /* flush vm_file */
9304 +}
9305 +
9306 +static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
9307 +{
9308 +       int err;
9309 +       static DECLARE_WAIT_QUEUE_HEAD(wq);
9310 +       struct file *file, *h_file;
9311 +       struct au_finfo *finfo;
9312 +
9313 +       /* todo: non-robr mode, user vm_file as it is? */
9314 +       wait_event(wq, (file = au_safe_file(vma)));
9315 +
9316 +       /* do not revalidate, no si lock */
9317 +       finfo = au_fi(file);
9318 +       AuDebugOn(finfo->fi_hdir);
9319 +       h_file = finfo->fi_htop.hf_file;
9320 +       AuDebugOn(!h_file || !finfo->fi_hvmop);
9321 +
9322 +       mutex_lock(&finfo->fi_vm_mtx);
9323 +       vma->vm_file = h_file;
9324 +       err = finfo->fi_hvmop->fault(vma, vmf);
9325 +       /* todo: necessary? */
9326 +       /* file->f_ra = h_file->f_ra; */
9327 +       au_reset_file(vma, file);
9328 +       mutex_unlock(&finfo->fi_vm_mtx);
9329 +#if 0 /* def CONFIG_SMP */
9330 +       /* wake_up_nr(&wq, online_cpu - 1); */
9331 +       wake_up_all(&wq);
9332 +#else
9333 +       wake_up(&wq);
9334 +#endif
9335 +
9336 +       return err;
9337 +}
9338 +
9339 +static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
9340 +{
9341 +       int err;
9342 +       static DECLARE_WAIT_QUEUE_HEAD(wq);
9343 +       struct file *file, *h_file;
9344 +       struct au_finfo *finfo;
9345 +
9346 +       wait_event(wq, (file = au_safe_file(vma)));
9347 +
9348 +       finfo = au_fi(file);
9349 +       AuDebugOn(finfo->fi_hdir);
9350 +       h_file = finfo->fi_htop.hf_file;
9351 +       AuDebugOn(!h_file || !finfo->fi_hvmop);
9352 +
9353 +       mutex_lock(&finfo->fi_vm_mtx);
9354 +       vma->vm_file = h_file;
9355 +       err = finfo->fi_hvmop->page_mkwrite(vma, vmf);
9356 +       au_reset_file(vma, file);
9357 +       mutex_unlock(&finfo->fi_vm_mtx);
9358 +       wake_up(&wq);
9359 +
9360 +       return err;
9361 +}
9362 +
9363 +static void aufs_vm_close(struct vm_area_struct *vma)
9364 +{
9365 +       static DECLARE_WAIT_QUEUE_HEAD(wq);
9366 +       struct file *file, *h_file;
9367 +       struct au_finfo *finfo;
9368 +
9369 +       wait_event(wq, (file = au_safe_file(vma)));
9370 +
9371 +       finfo = au_fi(file);
9372 +       AuDebugOn(finfo->fi_hdir);
9373 +       h_file = finfo->fi_htop.hf_file;
9374 +       AuDebugOn(!h_file || !finfo->fi_hvmop);
9375 +
9376 +       mutex_lock(&finfo->fi_vm_mtx);
9377 +       vma->vm_file = h_file;
9378 +       finfo->fi_hvmop->close(vma);
9379 +       au_reset_file(vma, file);
9380 +       mutex_unlock(&finfo->fi_vm_mtx);
9381 +       wake_up(&wq);
9382 +}
9383 +
9384 +const struct vm_operations_struct aufs_vm_ops = {
9385 +       .close          = aufs_vm_close,
9386 +       .fault          = aufs_fault,
9387 +       .page_mkwrite   = aufs_page_mkwrite
9388 +};
9389 +
9390 +/* ---------------------------------------------------------------------- */
9391 +
9392 +/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
9393 +#define AuConv_VM_PROT(f, b)   _calc_vm_trans(f, VM_##b, PROT_##b)
9394 +
9395 +static unsigned long au_arch_prot_conv(unsigned long flags)
9396 +{
9397 +       /* currently ppc64 only */
9398 +#ifdef CONFIG_PPC64
9399 +       /* cf. linux/arch/powerpc/include/asm/mman.h */
9400 +       AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
9401 +       return AuConv_VM_PROT(flags, SAO);
9402 +#else
9403 +       AuDebugOn(arch_calc_vm_prot_bits(-1));
9404 +       return 0;
9405 +#endif
9406 +}
9407 +
9408 +static unsigned long au_prot_conv(unsigned long flags)
9409 +{
9410 +       return AuConv_VM_PROT(flags, READ)
9411 +               | AuConv_VM_PROT(flags, WRITE)
9412 +               | AuConv_VM_PROT(flags, EXEC)
9413 +               | au_arch_prot_conv(flags);
9414 +}
9415 +
9416 +/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
9417 +#define AuConv_VM_MAP(f, b)    _calc_vm_trans(f, VM_##b, MAP_##b)
9418 +
9419 +static unsigned long au_flag_conv(unsigned long flags)
9420 +{
9421 +       return AuConv_VM_MAP(flags, GROWSDOWN)
9422 +               | AuConv_VM_MAP(flags, DENYWRITE)
9423 +               | AuConv_VM_MAP(flags, EXECUTABLE)
9424 +               | AuConv_VM_MAP(flags, LOCKED);
9425 +}
9426 +
9427 +static struct vm_operations_struct *
9428 +au_hvmop(struct file *h_file, struct vm_area_struct *vma, unsigned long *flags)
9429 +{
9430 +       struct vm_operations_struct *h_vmop;
9431 +       unsigned long prot;
9432 +       int err;
9433 +
9434 +       h_vmop = ERR_PTR(-ENODEV);
9435 +       if (!h_file->f_op || !h_file->f_op->mmap)
9436 +               goto out;
9437 +
9438 +       prot = au_prot_conv(vma->vm_flags);
9439 +       err = security_file_mmap(h_file, /*reqprot*/prot, prot,
9440 +                                au_flag_conv(vma->vm_flags), vma->vm_start, 0);
9441 +       h_vmop = ERR_PTR(err);
9442 +       if (unlikely(err))
9443 +               goto out;
9444 +
9445 +       err = h_file->f_op->mmap(h_file, vma);
9446 +       h_vmop = ERR_PTR(err);
9447 +       if (unlikely(err))
9448 +               goto out;
9449 +
9450 +       /* oops, it became 'const' */
9451 +       h_vmop = (struct vm_operations_struct *)vma->vm_ops;
9452 +       *flags = vma->vm_flags;
9453 +       err = do_munmap(current->mm, vma->vm_start,
9454 +                       vma->vm_end - vma->vm_start);
9455 +       if (unlikely(err)) {
9456 +               AuIOErr("failed internal unmapping %.*s, %d\n",
9457 +                       AuDLNPair(h_file->f_dentry), err);
9458 +               h_vmop = ERR_PTR(-EIO);
9459 +       }
9460 +
9461 +out:
9462 +       return h_vmop;
9463 +}
9464 +
9465 +/*
9466 + * This is another ugly approach to keep the lock order, particularly
9467 + * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
9468 + * find it in git-log, if you want.
9469 + *
9470 + * native readdir: i_mutex, copy_to_user, mmap_sem
9471 + * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
9472 + *
9473 + * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
9474 + * acquire aufs rwsem. It introduces a circular locking dependency.
9475 + * To address this problem, aufs_mmap() delegates the part which requires aufs
9476 + * rwsem to its internal workqueue.
9477 + */
9478 +
9479 +/* very ugly approach */
9480 +#include "mtx.h"
9481 +
9482 +struct au_mmap_pre_args {
9483 +       /* input */
9484 +       struct file *file;
9485 +       struct vm_area_struct *vma;
9486 +
9487 +       /* output */
9488 +       int *errp;
9489 +       struct file *h_file;
9490 +       struct au_branch *br;
9491 +       int mmapped;
9492 +};
9493 +
9494 +static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
9495 +                      struct file **h_file, struct au_branch **br,
9496 +                      int *mmapped)
9497 +{
9498 +       int err;
9499 +       aufs_bindex_t bstart;
9500 +       const unsigned char wlock
9501 +               = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
9502 +       struct dentry *dentry;
9503 +       struct super_block *sb;
9504 +
9505 +       dentry = file->f_dentry;
9506 +       sb = dentry->d_sb;
9507 +       si_read_lock(sb, !AuLock_FLUSH);
9508 +       err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9509 +       if (unlikely(err))
9510 +               goto out;
9511 +
9512 +       *mmapped = !!au_test_mmapped(file);
9513 +       if (wlock) {
9514 +               struct au_pin pin;
9515 +
9516 +               err = au_ready_to_write(file, -1, &pin);
9517 +               di_write_unlock(dentry);
9518 +               if (unlikely(err))
9519 +                       goto out_unlock;
9520 +               au_unpin(&pin);
9521 +       } else
9522 +               di_write_unlock(dentry);
9523 +       bstart = au_fbstart(file);
9524 +       *br = au_sbr(sb, bstart);
9525 +       *h_file = au_hf_top(file);
9526 +       get_file(*h_file);
9527 +       au_fi_mmap_lock(file);
9528 +
9529 +out_unlock:
9530 +       fi_write_unlock(file);
9531 +out:
9532 +       si_read_unlock(sb);
9533 +       return err;
9534 +}
9535 +
9536 +static void au_call_mmap_pre(void *args)
9537 +{
9538 +       struct au_mmap_pre_args *a = args;
9539 +       *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->br,
9540 +                              &a->mmapped);
9541 +}
9542 +
9543 +static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
9544 +{
9545 +       int err, wkq_err;
9546 +       unsigned long h_vmflags;
9547 +       struct au_finfo *finfo;
9548 +       struct dentry *h_dentry;
9549 +       struct vm_operations_struct *h_vmop, *vmop;
9550 +       struct au_mmap_pre_args args = {
9551 +               .file           = file,
9552 +               .vma            = vma,
9553 +               .errp           = &err
9554 +       };
9555 +
9556 +       wkq_err = au_wkq_wait_pre(au_call_mmap_pre, &args);
9557 +       if (unlikely(wkq_err))
9558 +               err = wkq_err;
9559 +       if (unlikely(err))
9560 +               goto out;
9561 +       finfo = au_fi(file);
9562 +       mutex_set_owner(&finfo->fi_mmap);
9563 +
9564 +       h_dentry = args.h_file->f_dentry;
9565 +       if (!args.mmapped && au_test_fs_bad_mapping(h_dentry->d_sb)) {
9566 +               /*
9567 +                * by this assignment, f_mapping will differs from aufs inode
9568 +                * i_mapping.
9569 +                * if someone else mixes the use of f_dentry->d_inode and
9570 +                * f_mapping->host, then a problem may arise.
9571 +                */
9572 +               file->f_mapping = args.h_file->f_mapping;
9573 +       }
9574 +
9575 +       /* always try this internal mmap to get vma flags */
9576 +       h_vmflags = 0; /* gcc warning */
9577 +       h_vmop = au_hvmop(args.h_file, vma, &h_vmflags);
9578 +       err = PTR_ERR(h_vmop);
9579 +       if (IS_ERR(h_vmop))
9580 +               goto out_unlock;
9581 +       AuDebugOn(args.mmapped && h_vmop != finfo->fi_hvmop);
9582 +
9583 +       vmop = (void *)au_dy_vmop(file, args.br, h_vmop);
9584 +       err = PTR_ERR(vmop);
9585 +       if (IS_ERR(vmop))
9586 +               goto out_unlock;
9587 +
9588 +       /*
9589 +        * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
9590 +        * currently MAP_DENYWRITE from userspace is ignored, but elf loader
9591 +        * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
9592 +        * both of the aufs file and the lower file is deny_write_access()-ed.
9593 +        * finally I hope we can skip handlling MAP_DENYWRITE here.
9594 +        */
9595 +       err = generic_file_mmap(file, vma);
9596 +       if (unlikely(err))
9597 +               goto out_unlock;
9598 +
9599 +       vma->vm_ops = vmop;
9600 +       vma->vm_flags = h_vmflags;
9601 +       if (!args.mmapped)
9602 +               finfo->fi_hvmop = h_vmop;
9603 +
9604 +       vfsub_file_accessed(args.h_file);
9605 +       /* update without lock, I don't think it a problem */
9606 +       fsstack_copy_attr_atime(file->f_dentry->d_inode, h_dentry->d_inode);
9607 +
9608 +out_unlock:
9609 +       au_fi_mmap_unlock(file);
9610 +       fput(args.h_file);
9611 +out:
9612 +       return err;
9613 +}
9614 +
9615 +/* ---------------------------------------------------------------------- */
9616 +
9617 +static int aufs_fsync_nondir(struct file *file, int datasync)
9618 +{
9619 +       int err;
9620 +       struct au_pin pin;
9621 +       struct dentry *dentry;
9622 +       struct inode *inode;
9623 +       struct file *h_file;
9624 +       struct super_block *sb;
9625 +
9626 +       dentry = file->f_dentry;
9627 +       inode = dentry->d_inode;
9628 +       IMustLock(file->f_mapping->host);
9629 +       if (inode != file->f_mapping->host) {
9630 +               mutex_unlock(&file->f_mapping->host->i_mutex);
9631 +               mutex_lock(&inode->i_mutex);
9632 +       }
9633 +       IMustLock(inode);
9634 +
9635 +       sb = dentry->d_sb;
9636 +       si_read_lock(sb, AuLock_FLUSH);
9637 +
9638 +       err = 0; /* -EBADF; */ /* posix? */
9639 +       if (unlikely(!(file->f_mode & FMODE_WRITE)))
9640 +               goto out;
9641 +       err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9642 +       if (unlikely(err))
9643 +               goto out;
9644 +
9645 +       err = au_ready_to_write(file, -1, &pin);
9646 +       di_downgrade_lock(dentry, AuLock_IR);
9647 +       if (unlikely(err))
9648 +               goto out_unlock;
9649 +       au_unpin(&pin);
9650 +
9651 +       err = -EINVAL;
9652 +       h_file = au_hf_top(file);
9653 +       if (h_file->f_op && h_file->f_op->fsync) {
9654 +               struct mutex *h_mtx;
9655 +
9656 +               /*
9657 +                * no filemap_fdatawrite() since aufs file has no its own
9658 +                * mapping, but dir.
9659 +                */
9660 +               h_mtx = &h_file->f_dentry->d_inode->i_mutex;
9661 +               mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
9662 +               err = h_file->f_op->fsync(h_file, datasync);
9663 +               if (!err)
9664 +                       vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9665 +               /*ignore*/
9666 +               au_cpup_attr_timesizes(inode);
9667 +               mutex_unlock(h_mtx);
9668 +       }
9669 +
9670 +out_unlock:
9671 +       di_read_unlock(dentry, AuLock_IR);
9672 +       fi_write_unlock(file);
9673 +out:
9674 +       si_read_unlock(sb);
9675 +       if (inode != file->f_mapping->host) {
9676 +               mutex_unlock(&inode->i_mutex);
9677 +               mutex_lock(&file->f_mapping->host->i_mutex);
9678 +       }
9679 +       return err;
9680 +}
9681 +
9682 +/* no one supports this operation, currently */
9683 +#if 0
9684 +static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
9685 +{
9686 +       int err;
9687 +       struct au_pin pin;
9688 +       struct dentry *dentry;
9689 +       struct inode *inode;
9690 +       struct file *file, *h_file;
9691 +       struct super_block *sb;
9692 +
9693 +       file = kio->ki_filp;
9694 +       dentry = file->f_dentry;
9695 +       inode = dentry->d_inode;
9696 +       mutex_lock(&inode->i_mutex);
9697 +
9698 +       sb = dentry->d_sb;
9699 +       si_read_lock(sb, AuLock_FLUSH);
9700 +
9701 +       err = 0; /* -EBADF; */ /* posix? */
9702 +       if (unlikely(!(file->f_mode & FMODE_WRITE)))
9703 +               goto out;
9704 +       err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9705 +       if (unlikely(err))
9706 +               goto out;
9707 +
9708 +       err = au_ready_to_write(file, -1, &pin);
9709 +       di_downgrade_lock(dentry, AuLock_IR);
9710 +       if (unlikely(err))
9711 +               goto out_unlock;
9712 +       au_unpin(&pin);
9713 +
9714 +       err = -ENOSYS;
9715 +       h_file = au_hf_top(file);
9716 +       if (h_file->f_op && h_file->f_op->aio_fsync) {
9717 +               struct dentry *h_d;
9718 +               struct mutex *h_mtx;
9719 +
9720 +               h_d = h_file->f_dentry;
9721 +               h_mtx = &h_d->d_inode->i_mutex;
9722 +               if (!is_sync_kiocb(kio)) {
9723 +                       get_file(h_file);
9724 +                       fput(file);
9725 +               }
9726 +               kio->ki_filp = h_file;
9727 +               err = h_file->f_op->aio_fsync(kio, datasync);
9728 +               mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
9729 +               if (!err)
9730 +                       vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9731 +               /*ignore*/
9732 +               au_cpup_attr_timesizes(inode);
9733 +               mutex_unlock(h_mtx);
9734 +       }
9735 +
9736 +out_unlock:
9737 +       di_read_unlock(dentry, AuLock_IR);
9738 +       fi_write_unlock(file);
9739 +out:
9740 +       si_read_unlock(sb);
9741 +       mutex_unlock(&inode->i_mutex);
9742 +       return err;
9743 +}
9744 +#endif
9745 +
9746 +static int aufs_fasync(int fd, struct file *file, int flag)
9747 +{
9748 +       int err;
9749 +       struct file *h_file;
9750 +       struct dentry *dentry;
9751 +       struct super_block *sb;
9752 +
9753 +       dentry = file->f_dentry;
9754 +       sb = dentry->d_sb;
9755 +       si_read_lock(sb, AuLock_FLUSH);
9756 +       err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9757 +       if (unlikely(err))
9758 +               goto out;
9759 +
9760 +       h_file = au_hf_top(file);
9761 +       if (h_file->f_op && h_file->f_op->fasync)
9762 +               err = h_file->f_op->fasync(fd, h_file, flag);
9763 +
9764 +       di_read_unlock(dentry, AuLock_IR);
9765 +       fi_read_unlock(file);
9766 +
9767 +out:
9768 +       si_read_unlock(sb);
9769 +       return err;
9770 +}
9771 +
9772 +/* ---------------------------------------------------------------------- */
9773 +
9774 +/* no one supports this operation, currently */
9775 +#if 0
9776 +static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
9777 +                            size_t len, loff_t *pos , int more)
9778 +{
9779 +}
9780 +#endif
9781 +
9782 +/* ---------------------------------------------------------------------- */
9783 +
9784 +const struct file_operations aufs_file_fop = {
9785 +       .owner          = THIS_MODULE,
9786 +       /*
9787 +        * while generic_file_llseek/_unlocked() don't use BKL,
9788 +        * don't use it since it operates file->f_mapping->host.
9789 +        * in aufs, it may be a real file and may confuse users by UDBA.
9790 +        */
9791 +       /* .llseek              = generic_file_llseek, */
9792 +
9793 +       .read           = aufs_read,
9794 +       .write          = aufs_write,
9795 +       .aio_read       = aufs_aio_read,
9796 +       .aio_write      = aufs_aio_write,
9797 +#ifdef CONFIG_AUFS_POLL
9798 +       .poll           = aufs_poll,
9799 +#endif
9800 +       .unlocked_ioctl = aufs_ioctl_nondir,
9801 +#ifdef CONFIG_COMPAT
9802 +       .compat_ioctl   = aufs_ioctl_nondir, /* same */
9803 +#endif
9804 +       .mmap           = aufs_mmap,
9805 +       .open           = aufs_open_nondir,
9806 +       .flush          = aufs_flush_nondir,
9807 +       .release        = aufs_release_nondir,
9808 +       .fsync          = aufs_fsync_nondir,
9809 +       /* .aio_fsync   = aufs_aio_fsync_nondir, */
9810 +       .fasync         = aufs_fasync,
9811 +       /* .sendpage    = aufs_sendpage, */
9812 +       .splice_write   = aufs_splice_write,
9813 +       .splice_read    = aufs_splice_read,
9814 +#if 0
9815 +       .aio_splice_write = aufs_aio_splice_write,
9816 +       .aio_splice_read  = aufs_aio_splice_read
9817 +#endif
9818 +};
9819 diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
9820 --- /usr/share/empty/fs/aufs/f_op_sp.c  1970-01-01 01:00:00.000000000 +0100
9821 +++ linux/fs/aufs/f_op_sp.c     2010-10-21 09:52:43.090291764 +0200
9822 @@ -0,0 +1,301 @@
9823 +/*
9824 + * Copyright (C) 2005-2010 Junjiro R. Okajima
9825 + *
9826 + * This program, aufs is free software; you can redistribute it and/or modify
9827 + * it under the terms of the GNU General Public License as published by
9828 + * the Free Software Foundation; either version 2 of the License, or
9829 + * (at your option) any later version.
9830 + *
9831 + * This program is distributed in the hope that it will be useful,
9832 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9833 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9834 + * GNU General Public License for more details.
9835 + *
9836 + * You should have received a copy of the GNU General Public License
9837 + * along with this program; if not, write to the Free Software
9838 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
9839 + */
9840 +
9841 +/*
9842 + * file operations for special files.
9843 + * while they exist in aufs virtually,
9844 + * their file I/O is handled out of aufs.
9845 + */
9846 +
9847 +#include <linux/fs_stack.h>
9848 +#include "aufs.h"
9849 +
9850 +static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
9851 +                               unsigned long nv, loff_t pos)
9852 +{
9853 +       ssize_t err;
9854 +       aufs_bindex_t bstart;
9855 +       unsigned char wbr;
9856 +       struct file *file, *h_file;
9857 +       struct super_block *sb;
9858 +
9859 +       file = kio->ki_filp;
9860 +       sb = file->f_dentry->d_sb;
9861 +       si_read_lock(sb, AuLock_FLUSH);
9862 +       fi_read_lock(file);
9863 +       bstart = au_fbstart(file);
9864 +       h_file = au_hf_top(file);
9865 +       fi_read_unlock(file);
9866 +       wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9867 +       si_read_unlock(sb);
9868 +
9869 +       /* do not change the file in kio */
9870 +       AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
9871 +       err = h_file->f_op->aio_read(kio, iov, nv, pos);
9872 +       if (err > 0 && wbr)
9873 +               file_accessed(h_file);
9874 +
9875 +       return err;
9876 +}
9877 +
9878 +static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
9879 +                                unsigned long nv, loff_t pos)
9880 +{
9881 +       ssize_t err;
9882 +       aufs_bindex_t bstart;
9883 +       unsigned char wbr;
9884 +       struct super_block *sb;
9885 +       struct file *file, *h_file;
9886 +
9887 +       file = kio->ki_filp;
9888 +       sb = file->f_dentry->d_sb;
9889 +       si_read_lock(sb, AuLock_FLUSH);
9890 +       fi_read_lock(file);
9891 +       bstart = au_fbstart(file);
9892 +       h_file = au_hf_top(file);
9893 +       fi_read_unlock(file);
9894 +       wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9895 +       si_read_unlock(sb);
9896 +
9897 +       /* do not change the file in kio */
9898 +       AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
9899 +       err = h_file->f_op->aio_write(kio, iov, nv, pos);
9900 +       if (err > 0 && wbr)
9901 +               file_update_time(h_file);
9902 +
9903 +       return err;
9904 +}
9905 +
9906 +/* ---------------------------------------------------------------------- */
9907 +
9908 +static int aufs_release_sp(struct inode *inode, struct file *file)
9909 +{
9910 +       int err;
9911 +       struct file *h_file;
9912 +
9913 +       fi_read_lock(file);
9914 +       h_file = au_hf_top(file);
9915 +       fi_read_unlock(file);
9916 +       /* close this fifo in aufs */
9917 +       err = h_file->f_op->release(inode, file); /* ignore */
9918 +       aufs_release_nondir(inode, file); /* ignore */
9919 +       return err;
9920 +}
9921 +
9922 +/* ---------------------------------------------------------------------- */
9923 +
9924 +/* currently, support only FIFO */
9925 +enum {
9926 +       AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
9927 +       /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
9928 +       AuSp_Last
9929 +};
9930 +static int aufs_open_sp(struct inode *inode, struct file *file);
9931 +static struct au_sp_fop {
9932 +       int                     done;
9933 +       struct file_operations  fop;    /* not 'const' */
9934 +       spinlock_t              spin;
9935 +} au_sp_fop[AuSp_Last] = {
9936 +       [AuSp_FIFO] = {
9937 +               .fop    = {
9938 +                       .owner  = THIS_MODULE,
9939 +                       .open   = aufs_open_sp
9940 +               }
9941 +       }
9942 +};
9943 +
9944 +static void au_init_fop_sp(struct file *file)
9945 +{
9946 +       struct au_sp_fop *p;
9947 +       int i;
9948 +       struct file *h_file;
9949 +
9950 +       p = au_sp_fop;
9951 +       if (unlikely(!p->done)) {
9952 +               /* initialize first time only */
9953 +               static DEFINE_SPINLOCK(spin);
9954 +
9955 +               spin_lock(&spin);
9956 +               if (!p->done) {
9957 +                       BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
9958 +                                    != AuSp_Last);
9959 +                       for (i = 0; i < AuSp_Last; i++)
9960 +                               spin_lock_init(&p[i].spin);
9961 +                       p->done = 1;
9962 +               }
9963 +               spin_unlock(&spin);
9964 +       }
9965 +
9966 +       switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
9967 +       case FMODE_READ:
9968 +               i = AuSp_FIFO_R;
9969 +               break;
9970 +       case FMODE_WRITE:
9971 +               i = AuSp_FIFO_W;
9972 +               break;
9973 +       case FMODE_READ | FMODE_WRITE:
9974 +               i = AuSp_FIFO_RW;
9975 +               break;
9976 +       default:
9977 +               BUG();
9978 +       }
9979 +
9980 +       p += i;
9981 +       if (unlikely(!p->done)) {
9982 +               /* initialize first time only */
9983 +               h_file = au_hf_top(file);
9984 +               spin_lock(&p->spin);
9985 +               if (!p->done) {
9986 +                       p->fop = *h_file->f_op;
9987 +                       p->fop.owner = THIS_MODULE;
9988 +                       if (p->fop.aio_read)
9989 +                               p->fop.aio_read = aufs_aio_read_sp;
9990 +                       if (p->fop.aio_write)
9991 +                               p->fop.aio_write = aufs_aio_write_sp;
9992 +                       p->fop.release = aufs_release_sp;
9993 +                       p->done = 1;
9994 +               }
9995 +               spin_unlock(&p->spin);
9996 +       }
9997 +       file->f_op = &p->fop;
9998 +}
9999 +
10000 +static int au_cpup_sp(struct dentry *dentry)
10001 +{
10002 +       int err;
10003 +       aufs_bindex_t bcpup;
10004 +       struct au_pin pin;
10005 +       struct au_wr_dir_args wr_dir_args = {
10006 +               .force_btgt     = -1,
10007 +               .flags          = 0
10008 +       };
10009 +
10010 +       AuDbg("%.*s\n", AuDLNPair(dentry));
10011 +
10012 +       di_read_unlock(dentry, AuLock_IR);
10013 +       di_write_lock_child(dentry);
10014 +       err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
10015 +       if (unlikely(err < 0))
10016 +               goto out;
10017 +       bcpup = err;
10018 +       err = 0;
10019 +       if (bcpup == au_dbstart(dentry))
10020 +               goto out; /* success */
10021 +
10022 +       err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
10023 +                    AuPin_MNT_WRITE);
10024 +       if (!err) {
10025 +               err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
10026 +               au_unpin(&pin);
10027 +       }
10028 +
10029 +out:
10030 +       di_downgrade_lock(dentry, AuLock_IR);
10031 +       return err;
10032 +}
10033 +
10034 +static int au_do_open_sp(struct file *file, int flags)
10035 +{
10036 +       int err;
10037 +       struct dentry *dentry;
10038 +       struct super_block *sb;
10039 +       struct file *h_file;
10040 +       struct inode *h_inode;
10041 +
10042 +       dentry = file->f_dentry;
10043 +       AuDbg("%.*s\n", AuDLNPair(dentry));
10044 +
10045 +       /*
10046 +        * try copying-up.
10047 +        * operate on the ro branch is not an error.
10048 +        */
10049 +       au_cpup_sp(dentry); /* ignore */
10050 +
10051 +       /* prepare h_file */
10052 +       err = au_do_open_nondir(file, vfsub_file_flags(file));
10053 +       if (unlikely(err))
10054 +               goto out;
10055 +
10056 +       sb = dentry->d_sb;
10057 +       h_file = au_hf_top(file);
10058 +       h_inode = h_file->f_dentry->d_inode;
10059 +       di_read_unlock(dentry, AuLock_IR);
10060 +       fi_write_unlock(file);
10061 +       si_read_unlock(sb);
10062 +       /* open this fifo in aufs */
10063 +       err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
10064 +       si_noflush_read_lock(sb);
10065 +       fi_write_lock(file);
10066 +       di_read_lock_child(dentry, AuLock_IR);
10067 +       if (!err)
10068 +               au_init_fop_sp(file);
10069 +       else
10070 +               au_finfo_fin(file);
10071 +
10072 +out:
10073 +       return err;
10074 +}
10075 +
10076 +static int aufs_open_sp(struct inode *inode, struct file *file)
10077 +{
10078 +       int err;
10079 +       struct super_block *sb;
10080 +
10081 +       sb = file->f_dentry->d_sb;
10082 +       si_read_lock(sb, AuLock_FLUSH);
10083 +       err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
10084 +       si_read_unlock(sb);
10085 +       return err;
10086 +}
10087 +
10088 +/* ---------------------------------------------------------------------- */
10089 +
10090 +void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
10091 +{
10092 +       init_special_inode(inode, mode, rdev);
10093 +
10094 +       switch (mode & S_IFMT) {
10095 +       case S_IFIFO:
10096 +               inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
10097 +               /*FALLTHROUGH*/
10098 +       case S_IFCHR:
10099 +       case S_IFBLK:
10100 +       case S_IFSOCK:
10101 +               break;
10102 +       default:
10103 +               AuDebugOn(1);
10104 +       }
10105 +}
10106 +
10107 +int au_special_file(umode_t mode)
10108 +{
10109 +       int ret;
10110 +
10111 +       ret = 0;
10112 +       switch (mode & S_IFMT) {
10113 +       case S_IFIFO:
10114 +#if 0
10115 +       case S_IFCHR:
10116 +       case S_IFBLK:
10117 +       case S_IFSOCK:
10118 +#endif
10119 +               ret = 1;
10120 +       }
10121 +
10122 +       return ret;
10123 +}
10124 diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
10125 --- /usr/share/empty/fs/aufs/fstype.h   1970-01-01 01:00:00.000000000 +0100
10126 +++ linux/fs/aufs/fstype.h      2010-10-21 09:52:43.090291764 +0200
10127 @@ -0,0 +1,497 @@
10128 +/*
10129 + * Copyright (C) 2005-2010 Junjiro R. Okajima
10130 + *
10131 + * This program, aufs is free software; you can redistribute it and/or modify
10132 + * it under the terms of the GNU General Public License as published by
10133 + * the Free Software Foundation; either version 2 of the License, or
10134 + * (at your option) any later version.
10135 + *
10136 + * This program is distributed in the hope that it will be useful,
10137 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10138 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10139 + * GNU General Public License for more details.
10140 + *
10141 + * You should have received a copy of the GNU General Public License
10142 + * along with this program; if not, write to the Free Software
10143 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
10144 + */
10145 +
10146 +/*
10147 + * judging filesystem type
10148 + */
10149 +
10150 +#ifndef __AUFS_FSTYPE_H__
10151 +#define __AUFS_FSTYPE_H__
10152 +
10153 +#ifdef __KERNEL__
10154 +
10155 +#include <linux/fs.h>
10156 +#include <linux/magic.h>
10157 +#include <linux/romfs_fs.h>
10158 +#include <linux/aufs_type.h>
10159 +
10160 +static inline int au_test_aufs(struct super_block *sb)
10161 +{
10162 +       return sb->s_magic == AUFS_SUPER_MAGIC;
10163 +}
10164 +
10165 +static inline const char *au_sbtype(struct super_block *sb)
10166 +{
10167 +       return sb->s_type->name;
10168 +}
10169 +
10170 +static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
10171 +{
10172 +#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
10173 +       return sb->s_magic == ROMFS_MAGIC;
10174 +#else
10175 +       return 0;
10176 +#endif
10177 +}
10178 +
10179 +static inline int au_test_romfs(struct super_block *sb __maybe_unused)
10180 +{
10181 +#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
10182 +       return sb->s_magic == ISOFS_SUPER_MAGIC;
10183 +#else
10184 +       return 0;
10185 +#endif
10186 +}
10187 +
10188 +static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
10189 +{
10190 +#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
10191 +       return sb->s_magic == CRAMFS_MAGIC;
10192 +#endif
10193 +       return 0;
10194 +}
10195 +
10196 +static inline int au_test_nfs(struct super_block *sb __maybe_unused)
10197 +{
10198 +#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
10199 +       return sb->s_magic == NFS_SUPER_MAGIC;
10200 +#else
10201 +       return 0;
10202 +#endif
10203 +}
10204 +
10205 +static inline int au_test_fuse(struct super_block *sb __maybe_unused)
10206 +{
10207 +#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
10208 +       return sb->s_magic == FUSE_SUPER_MAGIC;
10209 +#else
10210 +       return 0;
10211 +#endif
10212 +}
10213 +
10214 +static inline int au_test_xfs(struct super_block *sb __maybe_unused)
10215 +{
10216 +#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
10217 +       return sb->s_magic == XFS_SB_MAGIC;
10218 +#else
10219 +       return 0;
10220 +#endif
10221 +}
10222 +
10223 +static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
10224 +{
10225 +#ifdef CONFIG_TMPFS
10226 +       return sb->s_magic == TMPFS_MAGIC;
10227 +#else
10228 +       return 0;
10229 +#endif
10230 +}
10231 +
10232 +static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
10233 +{
10234 +#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
10235 +       return !strcmp(au_sbtype(sb), "ecryptfs");
10236 +#else
10237 +       return 0;
10238 +#endif
10239 +}
10240 +
10241 +static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
10242 +{
10243 +#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
10244 +       return sb->s_magic == SMB_SUPER_MAGIC;
10245 +#else
10246 +       return 0;
10247 +#endif
10248 +}
10249 +
10250 +static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
10251 +{
10252 +#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
10253 +       return sb->s_magic == OCFS2_SUPER_MAGIC;
10254 +#else
10255 +       return 0;
10256 +#endif
10257 +}
10258 +
10259 +static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
10260 +{
10261 +#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
10262 +       return sb->s_magic == DLMFS_MAGIC;
10263 +#else
10264 +       return 0;
10265 +#endif
10266 +}
10267 +
10268 +static inline int au_test_coda(struct super_block *sb __maybe_unused)
10269 +{
10270 +#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
10271 +       return sb->s_magic == CODA_SUPER_MAGIC;
10272 +#else
10273 +       return 0;
10274 +#endif
10275 +}
10276 +
10277 +static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
10278 +{
10279 +#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
10280 +       return sb->s_magic == V9FS_MAGIC;
10281 +#else
10282 +       return 0;
10283 +#endif
10284 +}
10285 +
10286 +static inline int au_test_ext4(struct super_block *sb __maybe_unused)
10287 +{
10288 +#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
10289 +       return sb->s_magic == EXT4_SUPER_MAGIC;
10290 +#else
10291 +       return 0;
10292 +#endif
10293 +}
10294 +
10295 +static inline int au_test_sysv(struct super_block *sb __maybe_unused)
10296 +{
10297 +#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
10298 +       return !strcmp(au_sbtype(sb), "sysv");
10299 +#else
10300 +       return 0;
10301 +#endif
10302 +}
10303 +
10304 +static inline int au_test_ramfs(struct super_block *sb)
10305 +{
10306 +       return sb->s_magic == RAMFS_MAGIC;
10307 +}
10308 +
10309 +static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
10310 +{
10311 +#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
10312 +       return sb->s_magic == UBIFS_SUPER_MAGIC;
10313 +#else
10314 +       return 0;
10315 +#endif
10316 +}
10317 +
10318 +static inline int au_test_procfs(struct super_block *sb __maybe_unused)
10319 +{
10320 +#ifdef CONFIG_PROC_FS
10321 +       return sb->s_magic == PROC_SUPER_MAGIC;
10322 +#else
10323 +       return 0;
10324 +#endif
10325 +}
10326 +
10327 +static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
10328 +{
10329 +#ifdef CONFIG_SYSFS
10330 +       return sb->s_magic == SYSFS_MAGIC;
10331 +#else
10332 +       return 0;
10333 +#endif
10334 +}
10335 +
10336 +static inline int au_test_configfs(struct super_block *sb __maybe_unused)
10337 +{
10338 +#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
10339 +       return sb->s_magic == CONFIGFS_MAGIC;
10340 +#else
10341 +       return 0;
10342 +#endif
10343 +}
10344 +
10345 +static inline int au_test_minix(struct super_block *sb __maybe_unused)
10346 +{
10347 +#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
10348 +       return sb->s_magic == MINIX3_SUPER_MAGIC
10349 +               || sb->s_magic == MINIX2_SUPER_MAGIC
10350 +               || sb->s_magic == MINIX2_SUPER_MAGIC2
10351 +               || sb->s_magic == MINIX_SUPER_MAGIC
10352 +               || sb->s_magic == MINIX_SUPER_MAGIC2;
10353 +#else
10354 +       return 0;
10355 +#endif
10356 +}
10357 +
10358 +static inline int au_test_cifs(struct super_block *sb __maybe_unused)
10359 +{
10360 +#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
10361 +       return sb->s_magic == CIFS_MAGIC_NUMBER;
10362 +#else
10363 +       return 0;
10364 +#endif
10365 +}
10366 +
10367 +static inline int au_test_fat(struct super_block *sb __maybe_unused)
10368 +{
10369 +#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
10370 +       return sb->s_magic == MSDOS_SUPER_MAGIC;
10371 +#else
10372 +       return 0;
10373 +#endif
10374 +}
10375 +
10376 +static inline int au_test_msdos(struct super_block *sb)
10377 +{
10378 +       return au_test_fat(sb);
10379 +}
10380 +
10381 +static inline int au_test_vfat(struct super_block *sb)
10382 +{
10383 +       return au_test_fat(sb);
10384 +}
10385 +
10386 +static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
10387 +{
10388 +#ifdef CONFIG_SECURITYFS
10389 +       return sb->s_magic == SECURITYFS_MAGIC;
10390 +#else
10391 +       return 0;
10392 +#endif
10393 +}
10394 +
10395 +static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
10396 +{
10397 +#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
10398 +       return sb->s_magic == SQUASHFS_MAGIC;
10399 +#else
10400 +       return 0;
10401 +#endif
10402 +}
10403 +
10404 +static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
10405 +{
10406 +#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
10407 +       return sb->s_magic == BTRFS_SUPER_MAGIC;
10408 +#else
10409 +       return 0;
10410 +#endif
10411 +}
10412 +
10413 +static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
10414 +{
10415 +#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
10416 +       return sb->s_magic == XENFS_SUPER_MAGIC;
10417 +#else
10418 +       return 0;
10419 +#endif
10420 +}
10421 +
10422 +static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
10423 +{
10424 +#ifdef CONFIG_DEBUG_FS
10425 +       return sb->s_magic == DEBUGFS_MAGIC;
10426 +#else
10427 +       return 0;
10428 +#endif
10429 +}
10430 +
10431 +static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
10432 +{
10433 +#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
10434 +       return sb->s_magic == NILFS_SUPER_MAGIC;
10435 +#else
10436 +       return 0;
10437 +#endif
10438 +}
10439 +
10440 +static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
10441 +{
10442 +#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
10443 +       return sb->s_magic == HFSPLUS_SUPER_MAGIC;
10444 +#else
10445 +       return 0;
10446 +#endif
10447 +}
10448 +
10449 +/* ---------------------------------------------------------------------- */
10450 +/*
10451 + * they can't be an aufs branch.
10452 + */
10453 +static inline int au_test_fs_unsuppoted(struct super_block *sb)
10454 +{
10455 +       return
10456 +#ifndef CONFIG_AUFS_BR_RAMFS
10457 +               au_test_ramfs(sb) ||
10458 +#endif
10459 +               au_test_procfs(sb)
10460 +               || au_test_sysfs(sb)
10461 +               || au_test_configfs(sb)
10462 +               || au_test_debugfs(sb)
10463 +               || au_test_securityfs(sb)
10464 +               || au_test_xenfs(sb)
10465 +               || au_test_ecryptfs(sb)
10466 +               /* || !strcmp(au_sbtype(sb), "unionfs") */
10467 +               || au_test_aufs(sb); /* will be supported in next version */
10468 +}
10469 +
10470 +/*
10471 + * If the filesystem supports NFS-export, then it has to support NULL as
10472 + * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
10473 + * We can apply this principle when we handle a lower filesystem.
10474 + */
10475 +static inline int au_test_fs_null_nd(struct super_block *sb)
10476 +{
10477 +       return !!sb->s_export_op;
10478 +}
10479 +
10480 +static inline int au_test_fs_remote(struct super_block *sb)
10481 +{
10482 +       return !au_test_tmpfs(sb)
10483 +#ifdef CONFIG_AUFS_BR_RAMFS
10484 +               && !au_test_ramfs(sb)
10485 +#endif
10486 +               && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
10487 +}
10488 +
10489 +/* ---------------------------------------------------------------------- */
10490 +
10491 +/*
10492 + * Note: these functions (below) are created after reading ->getattr() in all
10493 + * filesystems under linux/fs. it means we have to do so in every update...
10494 + */
10495 +
10496 +/*
10497 + * some filesystems require getattr to refresh the inode attributes before
10498 + * referencing.
10499 + * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
10500 + * and leave the work for d_revalidate()
10501 + */
10502 +static inline int au_test_fs_refresh_iattr(struct super_block *sb)
10503 +{
10504 +       return au_test_nfs(sb)
10505 +               || au_test_fuse(sb)
10506 +               /* || au_test_smbfs(sb) */      /* untested */
10507 +               /* || au_test_ocfs2(sb) */      /* untested */
10508 +               /* || au_test_btrfs(sb) */      /* untested */
10509 +               /* || au_test_coda(sb) */       /* untested */
10510 +               /* || au_test_v9fs(sb) */       /* untested */
10511 +               ;
10512 +}
10513 +
10514 +/*
10515 + * filesystems which don't maintain i_size or i_blocks.
10516 + */
10517 +static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
10518 +{
10519 +       return au_test_xfs(sb)
10520 +               || au_test_btrfs(sb)
10521 +               || au_test_ubifs(sb)
10522 +               || au_test_hfsplus(sb)  /* maintained, but incorrect */
10523 +               /* || au_test_ext4(sb) */       /* untested */
10524 +               /* || au_test_ocfs2(sb) */      /* untested */
10525 +               /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
10526 +               /* || au_test_sysv(sb) */       /* untested */
10527 +               /* || au_test_minix(sb) */      /* untested */
10528 +               ;
10529 +}
10530 +
10531 +/*
10532 + * filesystems which don't store the correct value in some of their inode
10533 + * attributes.
10534 + */
10535 +static inline int au_test_fs_bad_iattr(struct super_block *sb)
10536 +{
10537 +       return au_test_fs_bad_iattr_size(sb)
10538 +               /* || au_test_cifs(sb) */       /* untested */
10539 +               || au_test_fat(sb)
10540 +               || au_test_msdos(sb)
10541 +               || au_test_vfat(sb);
10542 +}
10543 +
10544 +/* they don't check i_nlink in link(2) */
10545 +static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
10546 +{
10547 +       return au_test_tmpfs(sb)
10548 +#ifdef CONFIG_AUFS_BR_RAMFS
10549 +               || au_test_ramfs(sb)
10550 +#endif
10551 +               || au_test_ubifs(sb)
10552 +               || au_test_btrfs(sb)
10553 +               || au_test_hfsplus(sb);
10554 +}
10555 +
10556 +/*
10557 + * filesystems which sets S_NOATIME and S_NOCMTIME.
10558 + */
10559 +static inline int au_test_fs_notime(struct super_block *sb)
10560 +{
10561 +       return au_test_nfs(sb)
10562 +               || au_test_fuse(sb)
10563 +               || au_test_ubifs(sb)
10564 +               /* || au_test_cifs(sb) */       /* untested */
10565 +               ;
10566 +}
10567 +
10568 +/*
10569 + * filesystems which requires replacing i_mapping.
10570 + */
10571 +static inline int au_test_fs_bad_mapping(struct super_block *sb)
10572 +{
10573 +       return au_test_fuse(sb)
10574 +               || au_test_ubifs(sb);
10575 +}
10576 +
10577 +/* temporary support for i#1 in cramfs */
10578 +static inline int au_test_fs_unique_ino(struct inode *inode)
10579 +{
10580 +       if (au_test_cramfs(inode->i_sb))
10581 +               return inode->i_ino != 1;
10582 +       return 1;
10583 +}
10584 +
10585 +/* ---------------------------------------------------------------------- */
10586 +
10587 +/*
10588 + * the filesystem where the xino files placed must support i/o after unlink and
10589 + * maintain i_size and i_blocks.
10590 + */
10591 +static inline int au_test_fs_bad_xino(struct super_block *sb)
10592 +{
10593 +       return au_test_fs_remote(sb)
10594 +               || au_test_fs_bad_iattr_size(sb)
10595 +#ifdef CONFIG_AUFS_BR_RAMFS
10596 +               || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
10597 +#else
10598 +               || !au_test_fs_null_nd(sb) /* to keep xino code simple */
10599 +#endif
10600 +               /* don't want unnecessary work for xino */
10601 +               || au_test_aufs(sb)
10602 +               || au_test_ecryptfs(sb)
10603 +               || au_test_nilfs(sb);
10604 +}
10605 +
10606 +static inline int au_test_fs_trunc_xino(struct super_block *sb)
10607 +{
10608 +       return au_test_tmpfs(sb)
10609 +               || au_test_ramfs(sb);
10610 +}
10611 +
10612 +/*
10613 + * test if the @sb is real-readonly.
10614 + */
10615 +static inline int au_test_fs_rr(struct super_block *sb)
10616 +{
10617 +       return au_test_squashfs(sb)
10618 +               || au_test_iso9660(sb)
10619 +               || au_test_cramfs(sb)
10620 +               || au_test_romfs(sb);
10621 +}
10622 +
10623 +#endif /* __KERNEL__ */
10624 +#endif /* __AUFS_FSTYPE_H__ */
10625 diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
10626 --- /usr/share/empty/fs/aufs/hfsnotify.c        1970-01-01 01:00:00.000000000 +0100
10627 +++ linux/fs/aufs/hfsnotify.c   2010-10-21 09:52:43.090291764 +0200
10628 @@ -0,0 +1,216 @@
10629 +/*
10630 + * Copyright (C) 2005-2010 Junjiro R. Okajima
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 + */
10646 +
10647 +/*
10648 + * fsnotify for the lower directories
10649 + */
10650 +
10651 +#include "aufs.h"
10652 +
10653 +/* FS_IN_IGNORED is unnecessary */
10654 +static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
10655 +                                | FS_CREATE | FS_EVENT_ON_CHILD);
10656 +static struct fsnotify_group *au_hfsn_group;
10657 +static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
10658 +
10659 +static void au_hfsn_free_mark(struct fsnotify_mark *mark)
10660 +{
10661 +       struct au_hnotify *hn = container_of(mark, struct au_hnotify,
10662 +                                            hn_mark);
10663 +       AuDbg("here\n");
10664 +       hn->hn_mark_dead = 1;
10665 +       smp_mb();
10666 +       wake_up_all(&au_hfsn_wq);
10667 +}
10668 +
10669 +static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode)
10670 +{
10671 +       struct fsnotify_mark *mark;
10672 +
10673 +       hn->hn_mark_dead = 0;
10674 +       mark = &hn->hn_mark;
10675 +       fsnotify_init_mark(mark, au_hfsn_free_mark);
10676 +       mark->mask = AuHfsnMask;
10677 +       /*
10678 +        * by udba rename or rmdir, aufs assign a new inode to the known
10679 +        * h_inode, so specify 1 to allow dups.
10680 +        */
10681 +       return fsnotify_add_mark(mark, au_hfsn_group, h_inode, /*mnt*/NULL,
10682 +                                /*allow_dups*/1);
10683 +}
10684 +
10685 +static void au_hfsn_free(struct au_hnotify *hn)
10686 +{
10687 +       struct fsnotify_mark *mark;
10688 +
10689 +       mark = &hn->hn_mark;
10690 +       fsnotify_destroy_mark(mark);
10691 +       fsnotify_put_mark(mark);
10692 +
10693 +       /* TODO: bad approach */
10694 +       wait_event(au_hfsn_wq, hn->hn_mark_dead);
10695 +}
10696 +
10697 +/* ---------------------------------------------------------------------- */
10698 +
10699 +static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
10700 +{
10701 +       struct fsnotify_mark *mark;
10702 +
10703 +       mark = &hinode->hi_notify->hn_mark;
10704 +       spin_lock(&mark->lock);
10705 +       if (do_set) {
10706 +               AuDebugOn(mark->mask & AuHfsnMask);
10707 +               mark->mask |= AuHfsnMask;
10708 +       } else {
10709 +               AuDebugOn(!(mark->mask & AuHfsnMask));
10710 +               mark->mask &= ~AuHfsnMask;
10711 +       }
10712 +       spin_unlock(&mark->lock);
10713 +       /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
10714 +}
10715 +
10716 +/* ---------------------------------------------------------------------- */
10717 +
10718 +/* #define AuDbgHnotify */
10719 +#ifdef AuDbgHnotify
10720 +static char *au_hfsn_name(u32 mask)
10721 +{
10722 +#ifdef CONFIG_AUFS_DEBUG
10723 +#define test_ret(flag) if (mask & flag) \
10724 +                               return #flag;
10725 +       test_ret(FS_ACCESS);
10726 +       test_ret(FS_MODIFY);
10727 +       test_ret(FS_ATTRIB);
10728 +       test_ret(FS_CLOSE_WRITE);
10729 +       test_ret(FS_CLOSE_NOWRITE);
10730 +       test_ret(FS_OPEN);
10731 +       test_ret(FS_MOVED_FROM);
10732 +       test_ret(FS_MOVED_TO);
10733 +       test_ret(FS_CREATE);
10734 +       test_ret(FS_DELETE);
10735 +       test_ret(FS_DELETE_SELF);
10736 +       test_ret(FS_MOVE_SELF);
10737 +       test_ret(FS_UNMOUNT);
10738 +       test_ret(FS_Q_OVERFLOW);
10739 +       test_ret(FS_IN_IGNORED);
10740 +       test_ret(FS_IN_ISDIR);
10741 +       test_ret(FS_IN_ONESHOT);
10742 +       test_ret(FS_EVENT_ON_CHILD);
10743 +       return "";
10744 +#undef test_ret
10745 +#else
10746 +       return "??";
10747 +#endif
10748 +}
10749 +#endif
10750 +
10751 +/* ---------------------------------------------------------------------- */
10752 +
10753 +static int au_hfsn_handle_event(struct fsnotify_group *group,
10754 +                               struct fsnotify_mark *inode_mark,
10755 +                               struct fsnotify_mark *vfsmount_mark,
10756 +                               struct fsnotify_event *event)
10757 +{
10758 +       int err;
10759 +       struct au_hnotify *hnotify;
10760 +       struct inode *h_dir, *h_inode;
10761 +       __u32 mask;
10762 +       struct qstr h_child_qstr = {
10763 +               .name   = event->file_name,
10764 +               .len    = event->name_len
10765 +       };
10766 +
10767 +       AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
10768 +
10769 +       err = 0;
10770 +       /* if FS_UNMOUNT happens, there must be another bug */
10771 +       mask = event->mask;
10772 +       AuDebugOn(mask & FS_UNMOUNT);
10773 +       if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
10774 +               goto out;
10775 +
10776 +       h_dir = event->to_tell;
10777 +       h_inode = event->inode;
10778 +#ifdef AuDbgHnotify
10779 +       au_debug(1);
10780 +       if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
10781 +           || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
10782 +               AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
10783 +                     h_dir->i_ino, mask, au_hfsn_name(mask),
10784 +                     AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
10785 +               /* WARN_ON(1); */
10786 +       }
10787 +       au_debug(0);
10788 +#endif
10789 +
10790 +       AuDebugOn(!inode_mark);
10791 +       hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
10792 +       err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
10793 +
10794 +out:
10795 +       return err;
10796 +}
10797 +
10798 +/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
10799 +/* it should be exported to modules */
10800 +static bool au_hfsn_should_send_event(struct fsnotify_group *group,
10801 +                                     struct inode *h_inode,
10802 +                                     struct fsnotify_mark *inode_mark,
10803 +                                     struct fsnotify_mark *vfsmount_mark,
10804 +                                     __u32 mask, void *data, int data_type)
10805 +{
10806 +       mask = (mask & ~FS_EVENT_ON_CHILD);
10807 +       return inode_mark->mask & mask;
10808 +}
10809 +
10810 +static struct fsnotify_ops au_hfsn_ops = {
10811 +       .should_send_event      = au_hfsn_should_send_event,
10812 +       .handle_event           = au_hfsn_handle_event
10813 +};
10814 +
10815 +/* ---------------------------------------------------------------------- */
10816 +
10817 +static int __init au_hfsn_init(void)
10818 +{
10819 +       int err;
10820 +
10821 +       err = 0;
10822 +       au_hfsn_group = fsnotify_alloc_group(&au_hfsn_ops);
10823 +       if (IS_ERR(au_hfsn_group)) {
10824 +               err = PTR_ERR(au_hfsn_group);
10825 +               pr_err("fsnotify_alloc_group() failed, %d\n", err);
10826 +       }
10827 +
10828 +       AuTraceErr(err);
10829 +       return err;
10830 +}
10831 +
10832 +static void au_hfsn_fin(void)
10833 +{
10834 +       fsnotify_put_group(au_hfsn_group);
10835 +}
10836 +
10837 +const struct au_hnotify_op au_hnotify_op = {
10838 +       .ctl            = au_hfsn_ctl,
10839 +       .alloc          = au_hfsn_alloc,
10840 +       .free           = au_hfsn_free,
10841 +
10842 +       .fin            = au_hfsn_fin,
10843 +       .init           = au_hfsn_init
10844 +};
10845 diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
10846 --- /usr/share/empty/fs/aufs/hfsplus.c  1970-01-01 01:00:00.000000000 +0100
10847 +++ linux/fs/aufs/hfsplus.c     2010-10-21 09:52:43.090291764 +0200
10848 @@ -0,0 +1,58 @@
10849 +/*
10850 + * Copyright (C) 2010 Junjiro R. Okajima
10851 + *
10852 + * This program, aufs is free software; you can redistribute it and/or modify
10853 + * it under the terms of the GNU General Public License as published by
10854 + * the Free Software Foundation; either version 2 of the License, or
10855 + * (at your option) any later version.
10856 + *
10857 + * This program is distributed in the hope that it will be useful,
10858 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10859 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10860 + * GNU General Public License for more details.
10861 + *
10862 + * You should have received a copy of the GNU General Public License
10863 + * along with this program; if not, write to the Free Software
10864 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
10865 + */
10866 +
10867 +/*
10868 + * special support for filesystems which aqucires an inode mutex
10869 + * at final closing a file, eg, hfsplus.
10870 + *
10871 + * This trick is very simple and stupid, just to open the file before really
10872 + * neceeary open to tell hfsplus that this is not the final closing.
10873 + * The caller should call au_h_open_pre() after acquiring the inode mutex,
10874 + * and au_h_open_post() after releasing it.
10875 + */
10876 +
10877 +#include <linux/file.h>
10878 +#include "aufs.h"
10879 +
10880 +struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
10881 +{
10882 +       struct file *h_file;
10883 +       struct dentry *h_dentry;
10884 +
10885 +       h_dentry = au_h_dptr(dentry, bindex);
10886 +       AuDebugOn(!h_dentry);
10887 +       AuDebugOn(!h_dentry->d_inode);
10888 +       IMustLock(h_dentry->d_inode);
10889 +
10890 +       h_file = NULL;
10891 +       if (au_test_hfsplus(h_dentry->d_sb)
10892 +           && S_ISREG(h_dentry->d_inode->i_mode))
10893 +               h_file = au_h_open(dentry, bindex,
10894 +                                  O_RDONLY | O_NOATIME | O_LARGEFILE,
10895 +                                  /*file*/NULL);
10896 +       return h_file;
10897 +}
10898 +
10899 +void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
10900 +                   struct file *h_file)
10901 +{
10902 +       if (h_file) {
10903 +               fput(h_file);
10904 +               au_sbr_put(dentry->d_sb, bindex);
10905 +       }
10906 +}
10907 diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
10908 --- /usr/share/empty/fs/aufs/hnotify.c  1970-01-01 01:00:00.000000000 +0100
10909 +++ linux/fs/aufs/hnotify.c     2010-10-21 09:52:43.090291764 +0200
10910 @@ -0,0 +1,663 @@
10911 +/*
10912 + * Copyright (C) 2005-2010 Junjiro R. Okajima
10913 + *
10914 + * This program, aufs is free software; you can redistribute it and/or modify
10915 + * it under the terms of the GNU General Public License as published by
10916 + * the Free Software Foundation; either version 2 of the License, or
10917 + * (at your option) any later version.
10918 + *
10919 + * This program is distributed in the hope that it will be useful,
10920 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10921 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10922 + * GNU General Public License for more details.
10923 + *
10924 + * You should have received a copy of the GNU General Public License
10925 + * along with this program; if not, write to the Free Software
10926 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
10927 + */
10928 +
10929 +/*
10930 + * abstraction to notify the direct changes on lower directories
10931 + */
10932 +
10933 +#include "aufs.h"
10934 +
10935 +int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
10936 +               struct inode *h_inode)
10937 +{
10938 +       int err;
10939 +       struct au_hnotify *hn;
10940 +
10941 +       err = -ENOMEM;
10942 +       hn = au_cache_alloc_hnotify();
10943 +       if (hn) {
10944 +               hn->hn_aufs_inode = inode;
10945 +               err = au_hnotify_op.alloc(hn, h_inode);
10946 +               if (!err)
10947 +                       hinode->hi_notify = hn;
10948 +               else {
10949 +                       au_cache_free_hnotify(hn);
10950 +                       /*
10951 +                        * The upper dir was removed by udba, but the same named
10952 +                        * dir left. In this case, aufs assignes a new inode
10953 +                        * number and set the monitor again.
10954 +                        * For the lower dir, the old monitnor is still left.
10955 +                        */
10956 +                       if (err == -EEXIST)
10957 +                               err = 0;
10958 +               }
10959 +       }
10960 +
10961 +       return err;
10962 +}
10963 +
10964 +void au_hn_free(struct au_hinode *hinode)
10965 +{
10966 +       struct au_hnotify *hn;
10967 +
10968 +       hn = hinode->hi_notify;
10969 +       if (hn) {
10970 +               au_hnotify_op.free(hn);
10971 +               au_cache_free_hnotify(hn);
10972 +               hinode->hi_notify = NULL;
10973 +       }
10974 +}
10975 +
10976 +/* ---------------------------------------------------------------------- */
10977 +
10978 +void au_hn_ctl(struct au_hinode *hinode, int do_set)
10979 +{
10980 +       if (hinode->hi_notify)
10981 +               au_hnotify_op.ctl(hinode, do_set);
10982 +}
10983 +
10984 +void au_hn_reset(struct inode *inode, unsigned int flags)
10985 +{
10986 +       aufs_bindex_t bindex, bend;
10987 +       struct inode *hi;
10988 +       struct dentry *iwhdentry;
10989 +
10990 +       bend = au_ibend(inode);
10991 +       for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
10992 +               hi = au_h_iptr(inode, bindex);
10993 +               if (!hi)
10994 +                       continue;
10995 +
10996 +               /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
10997 +               iwhdentry = au_hi_wh(inode, bindex);
10998 +               if (iwhdentry)
10999 +                       dget(iwhdentry);
11000 +               au_igrab(hi);
11001 +               au_set_h_iptr(inode, bindex, NULL, 0);
11002 +               au_set_h_iptr(inode, bindex, au_igrab(hi),
11003 +                             flags & ~AuHi_XINO);
11004 +               iput(hi);
11005 +               dput(iwhdentry);
11006 +               /* mutex_unlock(&hi->i_mutex); */
11007 +       }
11008 +}
11009 +
11010 +/* ---------------------------------------------------------------------- */
11011 +
11012 +static int hn_xino(struct inode *inode, struct inode *h_inode)
11013 +{
11014 +       int err;
11015 +       aufs_bindex_t bindex, bend, bfound, bstart;
11016 +       struct inode *h_i;
11017 +
11018 +       err = 0;
11019 +       if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11020 +               pr_warning("branch root dir was changed\n");
11021 +               goto out;
11022 +       }
11023 +
11024 +       bfound = -1;
11025 +       bend = au_ibend(inode);
11026 +       bstart = au_ibstart(inode);
11027 +#if 0 /* reserved for future use */
11028 +       if (bindex == bend) {
11029 +               /* keep this ino in rename case */
11030 +               goto out;
11031 +       }
11032 +#endif
11033 +       for (bindex = bstart; bindex <= bend; bindex++)
11034 +               if (au_h_iptr(inode, bindex) == h_inode) {
11035 +                       bfound = bindex;
11036 +                       break;
11037 +               }
11038 +       if (bfound < 0)
11039 +               goto out;
11040 +
11041 +       for (bindex = bstart; bindex <= bend; bindex++) {
11042 +               h_i = au_h_iptr(inode, bindex);
11043 +               if (!h_i)
11044 +                       continue;
11045 +
11046 +               err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
11047 +               /* ignore this error */
11048 +               /* bad action? */
11049 +       }
11050 +
11051 +       /* children inode number will be broken */
11052 +
11053 +out:
11054 +       AuTraceErr(err);
11055 +       return err;
11056 +}
11057 +
11058 +static int hn_gen_tree(struct dentry *dentry)
11059 +{
11060 +       int err, i, j, ndentry;
11061 +       struct au_dcsub_pages dpages;
11062 +       struct au_dpage *dpage;
11063 +       struct dentry **dentries;
11064 +
11065 +       err = au_dpages_init(&dpages, GFP_NOFS);
11066 +       if (unlikely(err))
11067 +               goto out;
11068 +       err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
11069 +       if (unlikely(err))
11070 +               goto out_dpages;
11071 +
11072 +       for (i = 0; i < dpages.ndpage; i++) {
11073 +               dpage = dpages.dpages + i;
11074 +               dentries = dpage->dentries;
11075 +               ndentry = dpage->ndentry;
11076 +               for (j = 0; j < ndentry; j++) {
11077 +                       struct dentry *d;
11078 +
11079 +                       d = dentries[j];
11080 +                       if (IS_ROOT(d))
11081 +                               continue;
11082 +
11083 +                       d_drop(d);
11084 +                       au_digen_dec(d);
11085 +                       if (d->d_inode)
11086 +                               /* todo: reset children xino?
11087 +                                  cached children only? */
11088 +                               au_iigen_dec(d->d_inode);
11089 +               }
11090 +       }
11091 +
11092 +out_dpages:
11093 +       au_dpages_free(&dpages);
11094 +
11095 +       /* discard children */
11096 +       dentry_unhash(dentry);
11097 +       dput(dentry);
11098 +out:
11099 +       return err;
11100 +}
11101 +
11102 +/*
11103 + * return 0 if processed.
11104 + */
11105 +static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
11106 +                          const unsigned int isdir)
11107 +{
11108 +       int err;
11109 +       struct dentry *d;
11110 +       struct qstr *dname;
11111 +
11112 +       err = 1;
11113 +       if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11114 +               pr_warning("branch root dir was changed\n");
11115 +               err = 0;
11116 +               goto out;
11117 +       }
11118 +
11119 +       if (!isdir) {
11120 +               AuDebugOn(!name);
11121 +               au_iigen_dec(inode);
11122 +               spin_lock(&dcache_lock);
11123 +               list_for_each_entry(d, &inode->i_dentry, d_alias) {
11124 +                       dname = &d->d_name;
11125 +                       if (dname->len != nlen
11126 +                           && memcmp(dname->name, name, nlen))
11127 +                               continue;
11128 +                       err = 0;
11129 +                       spin_lock(&d->d_lock);
11130 +                       __d_drop(d);
11131 +                       au_digen_dec(d);
11132 +                       spin_unlock(&d->d_lock);
11133 +                       break;
11134 +               }
11135 +               spin_unlock(&dcache_lock);
11136 +       } else {
11137 +               au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
11138 +               d = d_find_alias(inode);
11139 +               if (!d) {
11140 +                       au_iigen_dec(inode);
11141 +                       goto out;
11142 +               }
11143 +
11144 +               dname = &d->d_name;
11145 +               if (dname->len == nlen && !memcmp(dname->name, name, nlen))
11146 +                       err = hn_gen_tree(d);
11147 +               dput(d);
11148 +       }
11149 +
11150 +out:
11151 +       AuTraceErr(err);
11152 +       return err;
11153 +}
11154 +
11155 +static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
11156 +{
11157 +       int err;
11158 +       struct inode *inode;
11159 +
11160 +       inode = dentry->d_inode;
11161 +       if (IS_ROOT(dentry)
11162 +           /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
11163 +               ) {
11164 +               pr_warning("branch root dir was changed\n");
11165 +               return 0;
11166 +       }
11167 +
11168 +       err = 0;
11169 +       if (!isdir) {
11170 +               d_drop(dentry);
11171 +               au_digen_dec(dentry);
11172 +               if (inode)
11173 +                       au_iigen_dec(inode);
11174 +       } else {
11175 +               au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
11176 +               if (inode)
11177 +                       err = hn_gen_tree(dentry);
11178 +       }
11179 +
11180 +       AuTraceErr(err);
11181 +       return err;
11182 +}
11183 +
11184 +/* ---------------------------------------------------------------------- */
11185 +
11186 +/* hnotify job flags */
11187 +#define AuHnJob_XINO0          1
11188 +#define AuHnJob_GEN            (1 << 1)
11189 +#define AuHnJob_DIRENT         (1 << 2)
11190 +#define AuHnJob_ISDIR          (1 << 3)
11191 +#define AuHnJob_TRYXINO0       (1 << 4)
11192 +#define AuHnJob_MNTPNT         (1 << 5)
11193 +#define au_ftest_hnjob(flags, name)    ((flags) & AuHnJob_##name)
11194 +#define au_fset_hnjob(flags, name)     { (flags) |= AuHnJob_##name; }
11195 +#define au_fclr_hnjob(flags, name)     { (flags) &= ~AuHnJob_##name; }
11196 +
11197 +enum {
11198 +       AuHn_CHILD,
11199 +       AuHn_PARENT,
11200 +       AuHnLast
11201 +};
11202 +
11203 +struct au_hnotify_args {
11204 +       struct inode *h_dir, *dir, *h_child_inode;
11205 +       u32 mask;
11206 +       unsigned int flags[AuHnLast];
11207 +       unsigned int h_child_nlen;
11208 +       char h_child_name[];
11209 +};
11210 +
11211 +struct hn_job_args {
11212 +       unsigned int flags;
11213 +       struct inode *inode, *h_inode, *dir, *h_dir;
11214 +       struct dentry *dentry;
11215 +       char *h_name;
11216 +       int h_nlen;
11217 +};
11218 +
11219 +static int hn_job(struct hn_job_args *a)
11220 +{
11221 +       const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
11222 +
11223 +       /* reset xino */
11224 +       if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
11225 +               hn_xino(a->inode, a->h_inode); /* ignore this error */
11226 +
11227 +       if (au_ftest_hnjob(a->flags, TRYXINO0)
11228 +           && a->inode
11229 +           && a->h_inode) {
11230 +               mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11231 +               if (!a->h_inode->i_nlink)
11232 +                       hn_xino(a->inode, a->h_inode); /* ignore this error */
11233 +               mutex_unlock(&a->h_inode->i_mutex);
11234 +       }
11235 +
11236 +       /* make the generation obsolete */
11237 +       if (au_ftest_hnjob(a->flags, GEN)) {
11238 +               int err = -1;
11239 +               if (a->inode)
11240 +                       err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
11241 +                                             isdir);
11242 +               if (err && a->dentry)
11243 +                       hn_gen_by_name(a->dentry, isdir);
11244 +               /* ignore this error */
11245 +       }
11246 +
11247 +       /* make dir entries obsolete */
11248 +       if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
11249 +               struct au_vdir *vdir;
11250 +
11251 +               vdir = au_ivdir(a->inode);
11252 +               if (vdir)
11253 +                       vdir->vd_jiffy = 0;
11254 +               /* IMustLock(a->inode); */
11255 +               /* a->inode->i_version++; */
11256 +       }
11257 +
11258 +       /* can do nothing but warn */
11259 +       if (au_ftest_hnjob(a->flags, MNTPNT)
11260 +           && a->dentry
11261 +           && d_mountpoint(a->dentry))
11262 +               pr_warning("mount-point %.*s is removed or renamed\n",
11263 +                          AuDLNPair(a->dentry));
11264 +
11265 +       return 0;
11266 +}
11267 +
11268 +/* ---------------------------------------------------------------------- */
11269 +
11270 +static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
11271 +                                          struct inode *dir)
11272 +{
11273 +       struct dentry *dentry, *d, *parent;
11274 +       struct qstr *dname;
11275 +
11276 +       parent = d_find_alias(dir);
11277 +       if (!parent)
11278 +               return NULL;
11279 +
11280 +       dentry = NULL;
11281 +       spin_lock(&dcache_lock);
11282 +       list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
11283 +               /* AuDbg("%.*s\n", AuDLNPair(d)); */
11284 +               dname = &d->d_name;
11285 +               if (dname->len != nlen || memcmp(dname->name, name, nlen))
11286 +                       continue;
11287 +               if (!atomic_read(&d->d_count) || !d->d_fsdata) {
11288 +                       spin_lock(&d->d_lock);
11289 +                       __d_drop(d);
11290 +                       spin_unlock(&d->d_lock);
11291 +                       continue;
11292 +               }
11293 +
11294 +               dentry = dget(d);
11295 +               break;
11296 +       }
11297 +       spin_unlock(&dcache_lock);
11298 +       dput(parent);
11299 +
11300 +       if (dentry)
11301 +               di_write_lock_child(dentry);
11302 +
11303 +       return dentry;
11304 +}
11305 +
11306 +static struct inode *lookup_wlock_by_ino(struct super_block *sb,
11307 +                                        aufs_bindex_t bindex, ino_t h_ino)
11308 +{
11309 +       struct inode *inode;
11310 +       ino_t ino;
11311 +       int err;
11312 +
11313 +       inode = NULL;
11314 +       err = au_xino_read(sb, bindex, h_ino, &ino);
11315 +       if (!err && ino)
11316 +               inode = ilookup(sb, ino);
11317 +       if (!inode)
11318 +               goto out;
11319 +
11320 +       if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11321 +               pr_warning("wrong root branch\n");
11322 +               iput(inode);
11323 +               inode = NULL;
11324 +               goto out;
11325 +       }
11326 +
11327 +       ii_write_lock_child(inode);
11328 +
11329 +out:
11330 +       return inode;
11331 +}
11332 +
11333 +static void au_hn_bh(void *_args)
11334 +{
11335 +       struct au_hnotify_args *a = _args;
11336 +       struct super_block *sb;
11337 +       aufs_bindex_t bindex, bend, bfound;
11338 +       unsigned char xino, try_iput;
11339 +       int err;
11340 +       struct inode *inode;
11341 +       ino_t h_ino;
11342 +       struct hn_job_args args;
11343 +       struct dentry *dentry;
11344 +       struct au_sbinfo *sbinfo;
11345 +
11346 +       AuDebugOn(!_args);
11347 +       AuDebugOn(!a->h_dir);
11348 +       AuDebugOn(!a->dir);
11349 +       AuDebugOn(!a->mask);
11350 +       AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
11351 +             a->mask, a->dir->i_ino, a->h_dir->i_ino,
11352 +             a->h_child_inode ? a->h_child_inode->i_ino : 0);
11353 +
11354 +       inode = NULL;
11355 +       dentry = NULL;
11356 +       /*
11357 +        * do not lock a->dir->i_mutex here
11358 +        * because of d_revalidate() may cause a deadlock.
11359 +        */
11360 +       sb = a->dir->i_sb;
11361 +       AuDebugOn(!sb);
11362 +       sbinfo = au_sbi(sb);
11363 +       AuDebugOn(!sbinfo);
11364 +       /* big aufs lock */
11365 +       si_noflush_write_lock(sb);
11366 +
11367 +       ii_read_lock_parent(a->dir);
11368 +       bfound = -1;
11369 +       bend = au_ibend(a->dir);
11370 +       for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
11371 +               if (au_h_iptr(a->dir, bindex) == a->h_dir) {
11372 +                       bfound = bindex;
11373 +                       break;
11374 +               }
11375 +       ii_read_unlock(a->dir);
11376 +       if (unlikely(bfound < 0))
11377 +               goto out;
11378 +
11379 +       xino = !!au_opt_test(au_mntflags(sb), XINO);
11380 +       h_ino = 0;
11381 +       if (a->h_child_inode)
11382 +               h_ino = a->h_child_inode->i_ino;
11383 +
11384 +       if (a->h_child_nlen
11385 +           && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
11386 +               || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
11387 +               dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
11388 +                                             a->dir);
11389 +       try_iput = 0;
11390 +       if (dentry)
11391 +               inode = dentry->d_inode;
11392 +       if (xino && !inode && h_ino
11393 +           && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
11394 +               || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
11395 +               || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
11396 +               inode = lookup_wlock_by_ino(sb, bfound, h_ino);
11397 +               try_iput = 1;
11398 +           }
11399 +
11400 +       args.flags = a->flags[AuHn_CHILD];
11401 +       args.dentry = dentry;
11402 +       args.inode = inode;
11403 +       args.h_inode = a->h_child_inode;
11404 +       args.dir = a->dir;
11405 +       args.h_dir = a->h_dir;
11406 +       args.h_name = a->h_child_name;
11407 +       args.h_nlen = a->h_child_nlen;
11408 +       err = hn_job(&args);
11409 +       if (dentry) {
11410 +               if (dentry->d_fsdata)
11411 +                       di_write_unlock(dentry);
11412 +               dput(dentry);
11413 +       }
11414 +       if (inode && try_iput) {
11415 +               ii_write_unlock(inode);
11416 +               iput(inode);
11417 +       }
11418 +
11419 +       ii_write_lock_parent(a->dir);
11420 +       args.flags = a->flags[AuHn_PARENT];
11421 +       args.dentry = NULL;
11422 +       args.inode = a->dir;
11423 +       args.h_inode = a->h_dir;
11424 +       args.dir = NULL;
11425 +       args.h_dir = NULL;
11426 +       args.h_name = NULL;
11427 +       args.h_nlen = 0;
11428 +       err = hn_job(&args);
11429 +       ii_write_unlock(a->dir);
11430 +
11431 +out:
11432 +       au_nwt_done(&sbinfo->si_nowait);
11433 +       si_write_unlock(sb);
11434 +
11435 +       iput(a->h_child_inode);
11436 +       iput(a->h_dir);
11437 +       iput(a->dir);
11438 +       kfree(a);
11439 +}
11440 +
11441 +/* ---------------------------------------------------------------------- */
11442 +
11443 +int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
11444 +              struct qstr *h_child_qstr, struct inode *h_child_inode)
11445 +{
11446 +       int err, len;
11447 +       unsigned int flags[AuHnLast];
11448 +       unsigned char isdir, isroot, wh;
11449 +       struct inode *dir;
11450 +       struct au_hnotify_args *args;
11451 +       char *p, *h_child_name;
11452 +
11453 +       err = 0;
11454 +       AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
11455 +       dir = igrab(hnotify->hn_aufs_inode);
11456 +       if (!dir)
11457 +               goto out;
11458 +
11459 +       isroot = (dir->i_ino == AUFS_ROOT_INO);
11460 +       wh = 0;
11461 +       h_child_name = (void *)h_child_qstr->name;
11462 +       len = h_child_qstr->len;
11463 +       if (h_child_name) {
11464 +               if (len > AUFS_WH_PFX_LEN
11465 +                   && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
11466 +                       h_child_name += AUFS_WH_PFX_LEN;
11467 +                       len -= AUFS_WH_PFX_LEN;
11468 +                       wh = 1;
11469 +               }
11470 +       }
11471 +
11472 +       isdir = 0;
11473 +       if (h_child_inode)
11474 +               isdir = !!S_ISDIR(h_child_inode->i_mode);
11475 +       flags[AuHn_PARENT] = AuHnJob_ISDIR;
11476 +       flags[AuHn_CHILD] = 0;
11477 +       if (isdir)
11478 +               flags[AuHn_CHILD] = AuHnJob_ISDIR;
11479 +       au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
11480 +       au_fset_hnjob(flags[AuHn_CHILD], GEN);
11481 +       switch (mask & FS_EVENTS_POSS_ON_CHILD) {
11482 +       case FS_MOVED_FROM:
11483 +       case FS_MOVED_TO:
11484 +               au_fset_hnjob(flags[AuHn_CHILD], XINO0);
11485 +               au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11486 +               /*FALLTHROUGH*/
11487 +       case FS_CREATE:
11488 +               AuDebugOn(!h_child_name || !h_child_inode);
11489 +               break;
11490 +
11491 +       case FS_DELETE:
11492 +               /*
11493 +                * aufs never be able to get this child inode.
11494 +                * revalidation should be in d_revalidate()
11495 +                * by checking i_nlink, i_generation or d_unhashed().
11496 +                */
11497 +               AuDebugOn(!h_child_name);
11498 +               au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
11499 +               au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11500 +               break;
11501 +
11502 +       default:
11503 +               AuDebugOn(1);
11504 +       }
11505 +
11506 +       if (wh)
11507 +               h_child_inode = NULL;
11508 +
11509 +       err = -ENOMEM;
11510 +       /* iput() and kfree() will be called in au_hnotify() */
11511 +       args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
11512 +       if (unlikely(!args)) {
11513 +               AuErr1("no memory\n");
11514 +               iput(dir);
11515 +               goto out;
11516 +       }
11517 +       args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
11518 +       args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
11519 +       args->mask = mask;
11520 +       args->dir = dir;
11521 +       args->h_dir = igrab(h_dir);
11522 +       if (h_child_inode)
11523 +               h_child_inode = igrab(h_child_inode); /* can be NULL */
11524 +       args->h_child_inode = h_child_inode;
11525 +       args->h_child_nlen = len;
11526 +       if (len) {
11527 +               p = (void *)args;
11528 +               p += sizeof(*args);
11529 +               memcpy(p, h_child_name, len);
11530 +               p[len] = 0;
11531 +       }
11532 +
11533 +       err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
11534 +       if (unlikely(err)) {
11535 +               pr_err("wkq %d\n", err);
11536 +               iput(args->h_child_inode);
11537 +               iput(args->h_dir);
11538 +               iput(args->dir);
11539 +               kfree(args);
11540 +       }
11541 +
11542 +out:
11543 +       return err;
11544 +}
11545 +
11546 +static void au_hn_destroy_cache(void)
11547 +{
11548 +       kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
11549 +       au_cachep[AuCache_HNOTIFY] = NULL;
11550 +}
11551 +
11552 +int __init au_hnotify_init(void)
11553 +{
11554 +       int err;
11555 +
11556 +       err = -ENOMEM;
11557 +       au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
11558 +       if (au_cachep[AuCache_HNOTIFY]) {
11559 +               err = au_hnotify_op.init();
11560 +               if (unlikely(err))
11561 +                       au_hn_destroy_cache();
11562 +       }
11563 +       AuTraceErr(err);
11564 +       return err;
11565 +}
11566 +
11567 +void au_hnotify_fin(void)
11568 +{
11569 +       au_hnotify_op.fin();
11570 +       /* cf. au_cache_fin() */
11571 +       if (au_cachep[AuCache_HNOTIFY])
11572 +               au_hn_destroy_cache();
11573 +}
11574 diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
11575 --- /usr/share/empty/fs/aufs/iinfo.c    1970-01-01 01:00:00.000000000 +0100
11576 +++ linux/fs/aufs/iinfo.c       2010-10-21 09:52:43.090291764 +0200
11577 @@ -0,0 +1,257 @@
11578 +/*
11579 + * Copyright (C) 2005-2010 Junjiro R. Okajima
11580 + *
11581 + * This program, aufs is free software; you can redistribute it and/or modify
11582 + * it under the terms of the GNU General Public License as published by
11583 + * the Free Software Foundation; either version 2 of the License, or
11584 + * (at your option) any later version.
11585 + *
11586 + * This program is distributed in the hope that it will be useful,
11587 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11588 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11589 + * GNU General Public License for more details.
11590 + *
11591 + * You should have received a copy of the GNU General Public License
11592 + * along with this program; if not, write to the Free Software
11593 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
11594 + */
11595 +
11596 +/*
11597 + * inode private data
11598 + */
11599 +
11600 +#include "aufs.h"
11601 +
11602 +struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
11603 +{
11604 +       struct inode *h_inode;
11605 +
11606 +       IiMustAnyLock(inode);
11607 +
11608 +       h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
11609 +       AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11610 +       return h_inode;
11611 +}
11612 +
11613 +/* todo: hard/soft set? */
11614 +void au_hiput(struct au_hinode *hinode)
11615 +{
11616 +       au_hn_free(hinode);
11617 +       dput(hinode->hi_whdentry);
11618 +       iput(hinode->hi_inode);
11619 +}
11620 +
11621 +unsigned int au_hi_flags(struct inode *inode, int isdir)
11622 +{
11623 +       unsigned int flags;
11624 +       const unsigned int mnt_flags = au_mntflags(inode->i_sb);
11625 +
11626 +       flags = 0;
11627 +       if (au_opt_test(mnt_flags, XINO))
11628 +               au_fset_hi(flags, XINO);
11629 +       if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
11630 +               au_fset_hi(flags, HNOTIFY);
11631 +       return flags;
11632 +}
11633 +
11634 +void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
11635 +                  struct inode *h_inode, unsigned int flags)
11636 +{
11637 +       struct au_hinode *hinode;
11638 +       struct inode *hi;
11639 +       struct au_iinfo *iinfo = au_ii(inode);
11640 +
11641 +       IiMustWriteLock(inode);
11642 +
11643 +       hinode = iinfo->ii_hinode + bindex;
11644 +       hi = hinode->hi_inode;
11645 +       AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11646 +
11647 +       if (hi)
11648 +               au_hiput(hinode);
11649 +       hinode->hi_inode = h_inode;
11650 +       if (h_inode) {
11651 +               int err;
11652 +               struct super_block *sb = inode->i_sb;
11653 +               struct au_branch *br;
11654 +
11655 +               if (bindex == iinfo->ii_bstart)
11656 +                       au_cpup_igen(inode, h_inode);
11657 +               br = au_sbr(sb, bindex);
11658 +               hinode->hi_id = br->br_id;
11659 +               if (au_ftest_hi(flags, XINO)) {
11660 +                       err = au_xino_write(sb, bindex, h_inode->i_ino,
11661 +                                           inode->i_ino);
11662 +                       if (unlikely(err))
11663 +                               AuIOErr1("failed au_xino_write() %d\n", err);
11664 +               }
11665 +
11666 +               if (au_ftest_hi(flags, HNOTIFY)
11667 +                   && au_br_hnotifyable(br->br_perm)) {
11668 +                       err = au_hn_alloc(hinode, inode, h_inode);
11669 +                       if (unlikely(err))
11670 +                               AuIOErr1("au_hn_alloc() %d\n", err);
11671 +               }
11672 +       }
11673 +}
11674 +
11675 +void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
11676 +                 struct dentry *h_wh)
11677 +{
11678 +       struct au_hinode *hinode;
11679 +
11680 +       IiMustWriteLock(inode);
11681 +
11682 +       hinode = au_ii(inode)->ii_hinode + bindex;
11683 +       AuDebugOn(hinode->hi_whdentry);
11684 +       hinode->hi_whdentry = h_wh;
11685 +}
11686 +
11687 +void au_update_iigen(struct inode *inode)
11688 +{
11689 +       atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
11690 +       /* smp_mb(); */ /* atomic_set */
11691 +}
11692 +
11693 +/* it may be called at remount time, too */
11694 +void au_update_ibrange(struct inode *inode, int do_put_zero)
11695 +{
11696 +       struct au_iinfo *iinfo;
11697 +
11698 +       iinfo = au_ii(inode);
11699 +       if (!iinfo || iinfo->ii_bstart < 0)
11700 +               return;
11701 +
11702 +       IiMustWriteLock(inode);
11703 +
11704 +       if (do_put_zero) {
11705 +               aufs_bindex_t bindex;
11706 +
11707 +               for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
11708 +                    bindex++) {
11709 +                       struct inode *h_i;
11710 +
11711 +                       h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
11712 +                       if (h_i && !h_i->i_nlink)
11713 +                               au_set_h_iptr(inode, bindex, NULL, 0);
11714 +               }
11715 +       }
11716 +
11717 +       iinfo->ii_bstart = -1;
11718 +       while (++iinfo->ii_bstart <= iinfo->ii_bend)
11719 +               if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
11720 +                       break;
11721 +       if (iinfo->ii_bstart > iinfo->ii_bend) {
11722 +               iinfo->ii_bstart = -1;
11723 +               iinfo->ii_bend = -1;
11724 +               return;
11725 +       }
11726 +
11727 +       iinfo->ii_bend++;
11728 +       while (0 <= --iinfo->ii_bend)
11729 +               if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
11730 +                       break;
11731 +       AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
11732 +}
11733 +
11734 +/* ---------------------------------------------------------------------- */
11735 +
11736 +void au_icntnr_init_once(void *_c)
11737 +{
11738 +       struct au_icntnr *c = _c;
11739 +       struct au_iinfo *iinfo = &c->iinfo;
11740 +
11741 +       au_rw_init(&iinfo->ii_rwsem);
11742 +       inode_init_once(&c->vfs_inode);
11743 +}
11744 +
11745 +int au_iinfo_init(struct inode *inode)
11746 +{
11747 +       struct au_iinfo *iinfo;
11748 +       struct super_block *sb;
11749 +       int nbr, i;
11750 +
11751 +       sb = inode->i_sb;
11752 +       iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
11753 +       nbr = au_sbend(sb) + 1;
11754 +       if (unlikely(nbr <= 0))
11755 +               nbr = 1;
11756 +       iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
11757 +       if (iinfo->ii_hinode) {
11758 +               for (i = 0; i < nbr; i++)
11759 +                       iinfo->ii_hinode[i].hi_id = -1;
11760 +
11761 +               atomic_set(&iinfo->ii_generation, au_sigen(sb));
11762 +               /* smp_mb(); */ /* atomic_set */
11763 +               iinfo->ii_bstart = -1;
11764 +               iinfo->ii_bend = -1;
11765 +               iinfo->ii_vdir = NULL;
11766 +               return 0;
11767 +       }
11768 +       return -ENOMEM;
11769 +}
11770 +
11771 +int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
11772 +{
11773 +       int err, sz;
11774 +       struct au_hinode *hip;
11775 +
11776 +       AuRwMustWriteLock(&iinfo->ii_rwsem);
11777 +
11778 +       err = -ENOMEM;
11779 +       sz = sizeof(*hip) * (iinfo->ii_bend + 1);
11780 +       if (!sz)
11781 +               sz = sizeof(*hip);
11782 +       hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
11783 +       if (hip) {
11784 +               iinfo->ii_hinode = hip;
11785 +               err = 0;
11786 +       }
11787 +
11788 +       return err;
11789 +}
11790 +
11791 +void au_iinfo_fin(struct inode *inode)
11792 +{
11793 +       struct au_iinfo *iinfo;
11794 +       struct au_hinode *hi;
11795 +       struct super_block *sb;
11796 +       aufs_bindex_t bindex, bend;
11797 +       const unsigned char unlinked = !inode->i_nlink;
11798 +
11799 +       iinfo = au_ii(inode);
11800 +       /* bad_inode case */
11801 +       if (!iinfo)
11802 +               return;
11803 +
11804 +       sb = inode->i_sb;
11805 +       if (si_pid_test(sb))
11806 +               au_xino_delete_inode(inode, unlinked);
11807 +       else {
11808 +               /*
11809 +                * it is safe to hide the dependency between sbinfo and
11810 +                * sb->s_umount.
11811 +                */
11812 +               lockdep_off();
11813 +               si_noflush_read_lock(sb);
11814 +               au_xino_delete_inode(inode, unlinked);
11815 +               si_read_unlock(sb);
11816 +               lockdep_on();
11817 +       }
11818 +
11819 +       if (iinfo->ii_vdir)
11820 +               au_vdir_free(iinfo->ii_vdir);
11821 +
11822 +       bindex = iinfo->ii_bstart;
11823 +       if (bindex >= 0) {
11824 +               hi = iinfo->ii_hinode + bindex;
11825 +               bend = iinfo->ii_bend;
11826 +               while (bindex++ <= bend) {
11827 +                       if (hi->hi_inode)
11828 +                               au_hiput(hi);
11829 +                       hi++;
11830 +               }
11831 +       }
11832 +       kfree(iinfo->ii_hinode);
11833 +       AuRwDestroy(&iinfo->ii_rwsem);
11834 +}
11835 diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
11836 --- /usr/share/empty/fs/aufs/inode.c    1970-01-01 01:00:00.000000000 +0100
11837 +++ linux/fs/aufs/inode.c       2010-10-21 09:52:43.090291764 +0200
11838 @@ -0,0 +1,443 @@
11839 +/*
11840 + * Copyright (C) 2005-2010 Junjiro R. Okajima
11841 + *
11842 + * This program, aufs is free software; you can redistribute it and/or modify
11843 + * it under the terms of the GNU General Public License as published by
11844 + * the Free Software Foundation; either version 2 of the License, or
11845 + * (at your option) any later version.
11846 + *
11847 + * This program is distributed in the hope that it will be useful,
11848 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11849 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11850 + * GNU General Public License for more details.
11851 + *
11852 + * You should have received a copy of the GNU General Public License
11853 + * along with this program; if not, write to the Free Software
11854 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
11855 + */
11856 +
11857 +/*
11858 + * inode functions
11859 + */
11860 +
11861 +#include "aufs.h"
11862 +
11863 +struct inode *au_igrab(struct inode *inode)
11864 +{
11865 +       if (inode) {
11866 +               AuDebugOn(!atomic_read(&inode->i_count));
11867 +               atomic_inc_return(&inode->i_count);
11868 +       }
11869 +       return inode;
11870 +}
11871 +
11872 +static void au_refresh_hinode_attr(struct inode *inode, int do_version)
11873 +{
11874 +       au_cpup_attr_all(inode, /*force*/0);
11875 +       au_update_iigen(inode);
11876 +       if (do_version)
11877 +               inode->i_version++;
11878 +}
11879 +
11880 +int au_refresh_hinode_self(struct inode *inode, int do_attr)
11881 +{
11882 +       int err, e;
11883 +       aufs_bindex_t bindex, new_bindex;
11884 +       unsigned char update;
11885 +       struct au_hinode *p, *q, tmp;
11886 +       struct super_block *sb;
11887 +       struct au_iinfo *iinfo;
11888 +
11889 +       IiMustWriteLock(inode);
11890 +
11891 +       update = 0;
11892 +       sb = inode->i_sb;
11893 +       iinfo = au_ii(inode);
11894 +       err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
11895 +       if (unlikely(err))
11896 +               goto out;
11897 +
11898 +       p = iinfo->ii_hinode + iinfo->ii_bstart;
11899 +       err = 0;
11900 +       for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
11901 +            bindex++, p++) {
11902 +               if (!p->hi_inode)
11903 +                       continue;
11904 +
11905 +               new_bindex = au_br_index(sb, p->hi_id);
11906 +               if (new_bindex == bindex)
11907 +                       continue;
11908 +
11909 +               if (new_bindex < 0) {
11910 +                       update = 1;
11911 +                       au_hiput(p);
11912 +                       p->hi_inode = NULL;
11913 +                       continue;
11914 +               }
11915 +
11916 +               if (new_bindex < iinfo->ii_bstart)
11917 +                       iinfo->ii_bstart = new_bindex;
11918 +               if (iinfo->ii_bend < new_bindex)
11919 +                       iinfo->ii_bend = new_bindex;
11920 +               /* swap two lower inode, and loop again */
11921 +               q = iinfo->ii_hinode + new_bindex;
11922 +               tmp = *q;
11923 +               *q = *p;
11924 +               *p = tmp;
11925 +               if (tmp.hi_inode) {
11926 +                       bindex--;
11927 +                       p--;
11928 +               }
11929 +       }
11930 +       au_update_ibrange(inode, /*do_put_zero*/0);
11931 +       e = au_dy_irefresh(inode);
11932 +       if (unlikely(e && !err))
11933 +               err = e;
11934 +       if (do_attr)
11935 +               au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
11936 +
11937 +out:
11938 +       return err;
11939 +}
11940 +
11941 +int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
11942 +{
11943 +       int err, e;
11944 +       unsigned int flags;
11945 +       aufs_bindex_t bindex, bend;
11946 +       unsigned char isdir, update;
11947 +       struct au_hinode *p;
11948 +       struct au_iinfo *iinfo;
11949 +
11950 +       err = au_refresh_hinode_self(inode, /*do_attr*/0);
11951 +       if (unlikely(err))
11952 +               goto out;
11953 +
11954 +       update = 0;
11955 +       iinfo = au_ii(inode);
11956 +       p = iinfo->ii_hinode + iinfo->ii_bstart;
11957 +       isdir = S_ISDIR(inode->i_mode);
11958 +       flags = au_hi_flags(inode, isdir);
11959 +       bend = au_dbend(dentry);
11960 +       for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
11961 +               struct inode *h_i;
11962 +               struct dentry *h_d;
11963 +
11964 +               h_d = au_h_dptr(dentry, bindex);
11965 +               if (!h_d || !h_d->d_inode)
11966 +                       continue;
11967 +
11968 +               if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
11969 +                       h_i = au_h_iptr(inode, bindex);
11970 +                       if (h_i) {
11971 +                               if (h_i == h_d->d_inode)
11972 +                                       continue;
11973 +                               err = -EIO;
11974 +                               break;
11975 +                       }
11976 +               }
11977 +               if (bindex < iinfo->ii_bstart)
11978 +                       iinfo->ii_bstart = bindex;
11979 +               if (iinfo->ii_bend < bindex)
11980 +                       iinfo->ii_bend = bindex;
11981 +               au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
11982 +               update = 1;
11983 +       }
11984 +       au_update_ibrange(inode, /*do_put_zero*/0);
11985 +       e = au_dy_irefresh(inode);
11986 +       if (unlikely(e && !err))
11987 +               err = e;
11988 +       au_refresh_hinode_attr(inode, update && isdir);
11989 +
11990 +out:
11991 +       AuTraceErr(err);
11992 +       return err;
11993 +}
11994 +
11995 +static int set_inode(struct inode *inode, struct dentry *dentry)
11996 +{
11997 +       int err;
11998 +       unsigned int flags;
11999 +       umode_t mode;
12000 +       aufs_bindex_t bindex, bstart, btail;
12001 +       unsigned char isdir;
12002 +       struct dentry *h_dentry;
12003 +       struct inode *h_inode;
12004 +       struct au_iinfo *iinfo;
12005 +
12006 +       IiMustWriteLock(inode);
12007 +
12008 +       err = 0;
12009 +       isdir = 0;
12010 +       bstart = au_dbstart(dentry);
12011 +       h_inode = au_h_dptr(dentry, bstart)->d_inode;
12012 +       mode = h_inode->i_mode;
12013 +       switch (mode & S_IFMT) {
12014 +       case S_IFREG:
12015 +               btail = au_dbtail(dentry);
12016 +               inode->i_op = &aufs_iop;
12017 +               inode->i_fop = &aufs_file_fop;
12018 +               err = au_dy_iaop(inode, bstart, h_inode);
12019 +               if (unlikely(err))
12020 +                       goto out;
12021 +               break;
12022 +       case S_IFDIR:
12023 +               isdir = 1;
12024 +               btail = au_dbtaildir(dentry);
12025 +               inode->i_op = &aufs_dir_iop;
12026 +               inode->i_fop = &aufs_dir_fop;
12027 +               break;
12028 +       case S_IFLNK:
12029 +               btail = au_dbtail(dentry);
12030 +               inode->i_op = &aufs_symlink_iop;
12031 +               break;
12032 +       case S_IFBLK:
12033 +       case S_IFCHR:
12034 +       case S_IFIFO:
12035 +       case S_IFSOCK:
12036 +               btail = au_dbtail(dentry);
12037 +               inode->i_op = &aufs_iop;
12038 +               au_init_special_fop(inode, mode, h_inode->i_rdev);
12039 +               break;
12040 +       default:
12041 +               AuIOErr("Unknown file type 0%o\n", mode);
12042 +               err = -EIO;
12043 +               goto out;
12044 +       }
12045 +
12046 +       /* do not set hnotify for whiteouted dirs (SHWH mode) */
12047 +       flags = au_hi_flags(inode, isdir);
12048 +       if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
12049 +           && au_ftest_hi(flags, HNOTIFY)
12050 +           && dentry->d_name.len > AUFS_WH_PFX_LEN
12051 +           && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
12052 +               au_fclr_hi(flags, HNOTIFY);
12053 +       iinfo = au_ii(inode);
12054 +       iinfo->ii_bstart = bstart;
12055 +       iinfo->ii_bend = btail;
12056 +       for (bindex = bstart; bindex <= btail; bindex++) {
12057 +               h_dentry = au_h_dptr(dentry, bindex);
12058 +               if (h_dentry)
12059 +                       au_set_h_iptr(inode, bindex,
12060 +                                     au_igrab(h_dentry->d_inode), flags);
12061 +       }
12062 +       au_cpup_attr_all(inode, /*force*/1);
12063 +
12064 +out:
12065 +       return err;
12066 +}
12067 +
12068 +/* successful returns with iinfo write_locked */
12069 +static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
12070 +{
12071 +       int err;
12072 +       aufs_bindex_t bindex, bend;
12073 +       struct inode *h_inode, *h_dinode;
12074 +
12075 +       *matched = 0;
12076 +
12077 +       /*
12078 +        * before this function, if aufs got any iinfo lock, it must be only
12079 +        * one, the parent dir.
12080 +        * it can happen by UDBA and the obsoleted inode number.
12081 +        */
12082 +       err = -EIO;
12083 +       if (unlikely(inode->i_ino == parent_ino(dentry)))
12084 +               goto out;
12085 +
12086 +       err = 0;
12087 +       ii_write_lock_new_child(inode);
12088 +       h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
12089 +       bend = au_ibend(inode);
12090 +       for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12091 +               h_inode = au_h_iptr(inode, bindex);
12092 +               if (h_inode && h_inode == h_dinode) {
12093 +                       *matched = 1;
12094 +                       err = 0;
12095 +                       if (au_iigen(inode) != au_digen(dentry))
12096 +                               err = au_refresh_hinode(inode, dentry);
12097 +                       break;
12098 +               }
12099 +       }
12100 +
12101 +       if (unlikely(err))
12102 +               ii_write_unlock(inode);
12103 +out:
12104 +       return err;
12105 +}
12106 +
12107 +int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12108 +          unsigned int d_type, ino_t *ino)
12109 +{
12110 +       int err;
12111 +       struct mutex *mtx;
12112 +
12113 +       /* prevent hardlinked inode number from race condition */
12114 +       mtx = NULL;
12115 +       if (d_type != DT_DIR) {
12116 +               mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
12117 +               mutex_lock(mtx);
12118 +       }
12119 +       err = au_xino_read(sb, bindex, h_ino, ino);
12120 +       if (unlikely(err))
12121 +               goto out;
12122 +
12123 +       if (!*ino) {
12124 +               err = -EIO;
12125 +               *ino = au_xino_new_ino(sb);
12126 +               if (unlikely(!*ino))
12127 +                       goto out;
12128 +               err = au_xino_write(sb, bindex, h_ino, *ino);
12129 +               if (unlikely(err))
12130 +                       goto out;
12131 +       }
12132 +
12133 +out:
12134 +       if (mtx)
12135 +               mutex_unlock(mtx);
12136 +       return err;
12137 +}
12138 +
12139 +/* successful returns with iinfo write_locked */
12140 +/* todo: return with unlocked? */
12141 +struct inode *au_new_inode(struct dentry *dentry, int must_new)
12142 +{
12143 +       struct inode *inode, *h_inode;
12144 +       struct dentry *h_dentry;
12145 +       struct super_block *sb;
12146 +       struct mutex *mtx;
12147 +       ino_t h_ino, ino;
12148 +       int err, match;
12149 +       aufs_bindex_t bstart;
12150 +
12151 +       sb = dentry->d_sb;
12152 +       bstart = au_dbstart(dentry);
12153 +       h_dentry = au_h_dptr(dentry, bstart);
12154 +       h_inode = h_dentry->d_inode;
12155 +       h_ino = h_inode->i_ino;
12156 +
12157 +       /*
12158 +        * stop 'race'-ing between hardlinks under different
12159 +        * parents.
12160 +        */
12161 +       mtx = NULL;
12162 +       if (!S_ISDIR(h_inode->i_mode))
12163 +               mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
12164 +
12165 +new_ino:
12166 +       if (mtx)
12167 +               mutex_lock(mtx);
12168 +       err = au_xino_read(sb, bstart, h_ino, &ino);
12169 +       inode = ERR_PTR(err);
12170 +       if (unlikely(err))
12171 +               goto out;
12172 +
12173 +       if (!ino) {
12174 +               ino = au_xino_new_ino(sb);
12175 +               if (unlikely(!ino)) {
12176 +                       inode = ERR_PTR(-EIO);
12177 +                       goto out;
12178 +               }
12179 +       }
12180 +
12181 +       AuDbg("i%lu\n", (unsigned long)ino);
12182 +       inode = au_iget_locked(sb, ino);
12183 +       err = PTR_ERR(inode);
12184 +       if (IS_ERR(inode))
12185 +               goto out;
12186 +
12187 +       AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
12188 +       if (inode->i_state & I_NEW) {
12189 +               ii_write_lock_new_child(inode);
12190 +               err = set_inode(inode, dentry);
12191 +               if (!err) {
12192 +                       unlock_new_inode(inode);
12193 +                       goto out; /* success */
12194 +               }
12195 +
12196 +               ii_write_unlock(inode);
12197 +               iget_failed(inode);
12198 +               goto out_err;
12199 +       } else if (!must_new) {
12200 +               /*
12201 +                * horrible race condition between lookup, readdir and copyup
12202 +                * (or something).
12203 +                */
12204 +               if (mtx)
12205 +                       mutex_unlock(mtx);
12206 +               err = reval_inode(inode, dentry, &match);
12207 +               if (!err) {
12208 +                       mtx = NULL;
12209 +                       goto out; /* success */
12210 +               } else if (match) {
12211 +                       mtx = NULL;
12212 +                       goto out_iput;
12213 +               } else if (mtx)
12214 +                       mutex_lock(mtx);
12215 +       }
12216 +
12217 +       if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
12218 +               AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
12219 +                       " b%d, %s, %.*s, hi%lu, i%lu.\n",
12220 +                       bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
12221 +                       (unsigned long)h_ino, (unsigned long)ino);
12222 +       ino = 0;
12223 +       err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
12224 +       if (!err) {
12225 +               iput(inode);
12226 +               if (mtx)
12227 +                       mutex_unlock(mtx);
12228 +               goto new_ino;
12229 +       }
12230 +
12231 +out_iput:
12232 +       iput(inode);
12233 +out_err:
12234 +       inode = ERR_PTR(err);
12235 +out:
12236 +       if (mtx)
12237 +               mutex_unlock(mtx);
12238 +       return inode;
12239 +}
12240 +
12241 +/* ---------------------------------------------------------------------- */
12242 +
12243 +int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12244 +              struct inode *inode)
12245 +{
12246 +       int err;
12247 +
12248 +       err = au_br_rdonly(au_sbr(sb, bindex));
12249 +
12250 +       /* pseudo-link after flushed may happen out of bounds */
12251 +       if (!err
12252 +           && inode
12253 +           && au_ibstart(inode) <= bindex
12254 +           && bindex <= au_ibend(inode)) {
12255 +               /*
12256 +                * permission check is unnecessary since vfsub routine
12257 +                * will be called later
12258 +                */
12259 +               struct inode *hi = au_h_iptr(inode, bindex);
12260 +               if (hi)
12261 +                       err = IS_IMMUTABLE(hi) ? -EROFS : 0;
12262 +       }
12263 +
12264 +       return err;
12265 +}
12266 +
12267 +int au_test_h_perm(struct inode *h_inode, int mask)
12268 +{
12269 +       if (!current_fsuid())
12270 +               return 0;
12271 +       return inode_permission(h_inode, mask);
12272 +}
12273 +
12274 +int au_test_h_perm_sio(struct inode *h_inode, int mask)
12275 +{
12276 +       if (au_test_nfs(h_inode->i_sb)
12277 +           && (mask & MAY_WRITE)
12278 +           && S_ISDIR(h_inode->i_mode))
12279 +               mask |= MAY_READ; /* force permission check */
12280 +       return au_test_h_perm(h_inode, mask);
12281 +}
12282 diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
12283 --- /usr/share/empty/fs/aufs/inode.h    1970-01-01 01:00:00.000000000 +0100
12284 +++ linux/fs/aufs/inode.h       2010-10-21 09:52:43.090291764 +0200
12285 @@ -0,0 +1,498 @@
12286 +/*
12287 + * Copyright (C) 2005-2010 Junjiro R. Okajima
12288 + *
12289 + * This program, aufs is free software; you can redistribute it and/or modify
12290 + * it under the terms of the GNU General Public License as published by
12291 + * the Free Software Foundation; either version 2 of the License, or
12292 + * (at your option) any later version.
12293 + *
12294 + * This program is distributed in the hope that it will be useful,
12295 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12296 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12297 + * GNU General Public License for more details.
12298 + *
12299 + * You should have received a copy of the GNU General Public License
12300 + * along with this program; if not, write to the Free Software
12301 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
12302 + */
12303 +
12304 +/*
12305 + * inode operations
12306 + */
12307 +
12308 +#ifndef __AUFS_INODE_H__
12309 +#define __AUFS_INODE_H__
12310 +
12311 +#ifdef __KERNEL__
12312 +
12313 +#include <linux/fs.h>
12314 +#include <linux/fsnotify.h>
12315 +#include <linux/aufs_type.h>
12316 +#include "rwsem.h"
12317 +
12318 +struct vfsmount;
12319 +
12320 +struct au_hnotify {
12321 +#ifdef CONFIG_AUFS_HNOTIFY
12322 +#ifdef CONFIG_AUFS_HFSNOTIFY
12323 +       /* never use fsnotify_add_vfsmount_mark() */
12324 +       struct fsnotify_mark            hn_mark;
12325 +       int                             hn_mark_dead;
12326 +#endif
12327 +       struct inode                    *hn_aufs_inode; /* no get/put */
12328 +#endif
12329 +} ____cacheline_aligned_in_smp;
12330 +
12331 +struct au_hinode {
12332 +       struct inode            *hi_inode;
12333 +       aufs_bindex_t           hi_id;
12334 +#ifdef CONFIG_AUFS_HNOTIFY
12335 +       struct au_hnotify       *hi_notify;
12336 +#endif
12337 +
12338 +       /* reference to the copied-up whiteout with get/put */
12339 +       struct dentry           *hi_whdentry;
12340 +};
12341 +
12342 +struct au_vdir;
12343 +struct au_iinfo {
12344 +       atomic_t                ii_generation;
12345 +       struct super_block      *ii_hsb1;       /* no get/put */
12346 +
12347 +       struct au_rwsem         ii_rwsem;
12348 +       aufs_bindex_t           ii_bstart, ii_bend;
12349 +       __u32                   ii_higen;
12350 +       struct au_hinode        *ii_hinode;
12351 +       struct au_vdir          *ii_vdir;
12352 +};
12353 +
12354 +struct au_icntnr {
12355 +       struct au_iinfo iinfo;
12356 +       struct inode vfs_inode;
12357 +} ____cacheline_aligned_in_smp;
12358 +
12359 +/* au_pin flags */
12360 +#define AuPin_DI_LOCKED                1
12361 +#define AuPin_MNT_WRITE                (1 << 1)
12362 +#define au_ftest_pin(flags, name)      ((flags) & AuPin_##name)
12363 +#define au_fset_pin(flags, name)       { (flags) |= AuPin_##name; }
12364 +#define au_fclr_pin(flags, name)       { (flags) &= ~AuPin_##name; }
12365 +
12366 +struct au_pin {
12367 +       /* input */
12368 +       struct dentry *dentry;
12369 +       unsigned int udba;
12370 +       unsigned char lsc_di, lsc_hi, flags;
12371 +       aufs_bindex_t bindex;
12372 +
12373 +       /* output */
12374 +       struct dentry *parent;
12375 +       struct au_hinode *hdir;
12376 +       struct vfsmount *h_mnt;
12377 +};
12378 +
12379 +/* ---------------------------------------------------------------------- */
12380 +
12381 +static inline struct au_iinfo *au_ii(struct inode *inode)
12382 +{
12383 +       struct au_iinfo *iinfo;
12384 +
12385 +       iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12386 +       if (iinfo->ii_hinode)
12387 +               return iinfo;
12388 +       return NULL; /* debugging bad_inode case */
12389 +}
12390 +
12391 +/* ---------------------------------------------------------------------- */
12392 +
12393 +/* inode.c */
12394 +struct inode *au_igrab(struct inode *inode);
12395 +int au_refresh_hinode_self(struct inode *inode, int do_attr);
12396 +int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
12397 +int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12398 +          unsigned int d_type, ino_t *ino);
12399 +struct inode *au_new_inode(struct dentry *dentry, int must_new);
12400 +int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12401 +              struct inode *inode);
12402 +int au_test_h_perm(struct inode *h_inode, int mask);
12403 +int au_test_h_perm_sio(struct inode *h_inode, int mask);
12404 +
12405 +static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
12406 +                           ino_t h_ino, unsigned int d_type, ino_t *ino)
12407 +{
12408 +#ifdef CONFIG_AUFS_SHWH
12409 +       return au_ino(sb, bindex, h_ino, d_type, ino);
12410 +#else
12411 +       return 0;
12412 +#endif
12413 +}
12414 +
12415 +/* i_op.c */
12416 +extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
12417 +
12418 +/* au_wr_dir flags */
12419 +#define AuWrDir_ADD_ENTRY      1
12420 +#define AuWrDir_ISDIR          (1 << 1)
12421 +#define au_ftest_wrdir(flags, name)    ((flags) & AuWrDir_##name)
12422 +#define au_fset_wrdir(flags, name)     { (flags) |= AuWrDir_##name; }
12423 +#define au_fclr_wrdir(flags, name)     { (flags) &= ~AuWrDir_##name; }
12424 +
12425 +struct au_wr_dir_args {
12426 +       aufs_bindex_t force_btgt;
12427 +       unsigned char flags;
12428 +};
12429 +int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
12430 +             struct au_wr_dir_args *args);
12431 +
12432 +struct dentry *au_pinned_h_parent(struct au_pin *pin);
12433 +void au_pin_init(struct au_pin *pin, struct dentry *dentry,
12434 +                aufs_bindex_t bindex, int lsc_di, int lsc_hi,
12435 +                unsigned int udba, unsigned char flags);
12436 +int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
12437 +          unsigned int udba, unsigned char flags) __must_check;
12438 +int au_do_pin(struct au_pin *pin) __must_check;
12439 +void au_unpin(struct au_pin *pin);
12440 +
12441 +/* i_op_add.c */
12442 +int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
12443 +              struct dentry *h_parent, int isdir);
12444 +int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
12445 +int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
12446 +int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
12447 +               struct nameidata *nd);
12448 +int aufs_link(struct dentry *src_dentry, struct inode *dir,
12449 +             struct dentry *dentry);
12450 +int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
12451 +
12452 +/* i_op_del.c */
12453 +int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
12454 +int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
12455 +              struct dentry *h_parent, int isdir);
12456 +int aufs_unlink(struct inode *dir, struct dentry *dentry);
12457 +int aufs_rmdir(struct inode *dir, struct dentry *dentry);
12458 +
12459 +/* i_op_ren.c */
12460 +int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
12461 +int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
12462 +               struct inode *dir, struct dentry *dentry);
12463 +
12464 +/* iinfo.c */
12465 +struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
12466 +void au_hiput(struct au_hinode *hinode);
12467 +void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12468 +                 struct dentry *h_wh);
12469 +unsigned int au_hi_flags(struct inode *inode, int isdir);
12470 +
12471 +/* hinode flags */
12472 +#define AuHi_XINO      1
12473 +#define AuHi_HNOTIFY   (1 << 1)
12474 +#define au_ftest_hi(flags, name)       ((flags) & AuHi_##name)
12475 +#define au_fset_hi(flags, name)                { (flags) |= AuHi_##name; }
12476 +#define au_fclr_hi(flags, name)                { (flags) &= ~AuHi_##name; }
12477 +
12478 +#ifndef CONFIG_AUFS_HNOTIFY
12479 +#undef AuHi_HNOTIFY
12480 +#define AuHi_HNOTIFY   0
12481 +#endif
12482 +
12483 +void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12484 +                  struct inode *h_inode, unsigned int flags);
12485 +
12486 +void au_update_iigen(struct inode *inode);
12487 +void au_update_ibrange(struct inode *inode, int do_put_zero);
12488 +
12489 +void au_icntnr_init_once(void *_c);
12490 +int au_iinfo_init(struct inode *inode);
12491 +void au_iinfo_fin(struct inode *inode);
12492 +int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
12493 +
12494 +/* plink.c */
12495 +void au_plink_maint_block(struct super_block *sb);
12496 +void au_plink_maint_leave(struct file *file);
12497 +#ifdef CONFIG_AUFS_DEBUG
12498 +void au_plink_list(struct super_block *sb);
12499 +#else
12500 +AuStubVoid(au_plink_list, struct super_block *sb)
12501 +#endif
12502 +int au_plink_test(struct inode *inode);
12503 +struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
12504 +void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
12505 +                    struct dentry *h_dentry);
12506 +void au_plink_put(struct super_block *sb);
12507 +void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
12508 +long au_plink_ioctl(struct file *file, unsigned int cmd);
12509 +
12510 +/* ---------------------------------------------------------------------- */
12511 +
12512 +/* lock subclass for iinfo */
12513 +enum {
12514 +       AuLsc_II_CHILD,         /* child first */
12515 +       AuLsc_II_CHILD2,        /* rename(2), link(2), and cpup at hnotify */
12516 +       AuLsc_II_CHILD3,        /* copyup dirs */
12517 +       AuLsc_II_PARENT,        /* see AuLsc_I_PARENT in vfsub.h */
12518 +       AuLsc_II_PARENT2,
12519 +       AuLsc_II_PARENT3,       /* copyup dirs */
12520 +       AuLsc_II_NEW_CHILD
12521 +};
12522 +
12523 +/*
12524 + * ii_read_lock_child, ii_write_lock_child,
12525 + * ii_read_lock_child2, ii_write_lock_child2,
12526 + * ii_read_lock_child3, ii_write_lock_child3,
12527 + * ii_read_lock_parent, ii_write_lock_parent,
12528 + * ii_read_lock_parent2, ii_write_lock_parent2,
12529 + * ii_read_lock_parent3, ii_write_lock_parent3,
12530 + * ii_read_lock_new_child, ii_write_lock_new_child,
12531 + */
12532 +#define AuReadLockFunc(name, lsc) \
12533 +static inline void ii_read_lock_##name(struct inode *i) \
12534 +{ \
12535 +       au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12536 +}
12537 +
12538 +#define AuWriteLockFunc(name, lsc) \
12539 +static inline void ii_write_lock_##name(struct inode *i) \
12540 +{ \
12541 +       au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12542 +}
12543 +
12544 +#define AuRWLockFuncs(name, lsc) \
12545 +       AuReadLockFunc(name, lsc) \
12546 +       AuWriteLockFunc(name, lsc)
12547 +
12548 +AuRWLockFuncs(child, CHILD);
12549 +AuRWLockFuncs(child2, CHILD2);
12550 +AuRWLockFuncs(child3, CHILD3);
12551 +AuRWLockFuncs(parent, PARENT);
12552 +AuRWLockFuncs(parent2, PARENT2);
12553 +AuRWLockFuncs(parent3, PARENT3);
12554 +AuRWLockFuncs(new_child, NEW_CHILD);
12555 +
12556 +#undef AuReadLockFunc
12557 +#undef AuWriteLockFunc
12558 +#undef AuRWLockFuncs
12559 +
12560 +/*
12561 + * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
12562 + */
12563 +AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
12564 +
12565 +#define IiMustNoWaiters(i)     AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
12566 +#define IiMustAnyLock(i)       AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
12567 +#define IiMustWriteLock(i)     AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
12568 +
12569 +/* ---------------------------------------------------------------------- */
12570 +
12571 +static inline unsigned int au_iigen(struct inode *inode)
12572 +{
12573 +       return atomic_read(&au_ii(inode)->ii_generation);
12574 +}
12575 +
12576 +/* tiny test for inode number */
12577 +/* tmpfs generation is too rough */
12578 +static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
12579 +{
12580 +       struct au_iinfo *iinfo;
12581 +
12582 +       iinfo = au_ii(inode);
12583 +       AuRwMustAnyLock(&iinfo->ii_rwsem);
12584 +       return !(iinfo->ii_hsb1 == h_inode->i_sb
12585 +                && iinfo->ii_higen == h_inode->i_generation);
12586 +}
12587 +
12588 +static inline void au_iigen_dec(struct inode *inode)
12589 +{
12590 +#ifdef CONFIG_AUFS_HNOTIFY
12591 +       atomic_dec_return(&au_ii(inode)->ii_generation);
12592 +#endif
12593 +}
12594 +
12595 +/* ---------------------------------------------------------------------- */
12596 +
12597 +static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
12598 +                                       aufs_bindex_t bindex)
12599 +{
12600 +       IiMustAnyLock(inode);
12601 +       return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
12602 +}
12603 +
12604 +static inline aufs_bindex_t au_ibstart(struct inode *inode)
12605 +{
12606 +       IiMustAnyLock(inode);
12607 +       return au_ii(inode)->ii_bstart;
12608 +}
12609 +
12610 +static inline aufs_bindex_t au_ibend(struct inode *inode)
12611 +{
12612 +       IiMustAnyLock(inode);
12613 +       return au_ii(inode)->ii_bend;
12614 +}
12615 +
12616 +static inline struct au_vdir *au_ivdir(struct inode *inode)
12617 +{
12618 +       IiMustAnyLock(inode);
12619 +       return au_ii(inode)->ii_vdir;
12620 +}
12621 +
12622 +static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
12623 +{
12624 +       IiMustAnyLock(inode);
12625 +       return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
12626 +}
12627 +
12628 +static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
12629 +{
12630 +       IiMustWriteLock(inode);
12631 +       au_ii(inode)->ii_bstart = bindex;
12632 +}
12633 +
12634 +static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
12635 +{
12636 +       IiMustWriteLock(inode);
12637 +       au_ii(inode)->ii_bend = bindex;
12638 +}
12639 +
12640 +static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
12641 +{
12642 +       IiMustWriteLock(inode);
12643 +       au_ii(inode)->ii_vdir = vdir;
12644 +}
12645 +
12646 +static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
12647 +{
12648 +       IiMustAnyLock(inode);
12649 +       return au_ii(inode)->ii_hinode + bindex;
12650 +}
12651 +
12652 +/* ---------------------------------------------------------------------- */
12653 +
12654 +static inline struct dentry *au_pinned_parent(struct au_pin *pin)
12655 +{
12656 +       if (pin)
12657 +               return pin->parent;
12658 +       return NULL;
12659 +}
12660 +
12661 +static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
12662 +{
12663 +       if (pin && pin->hdir)
12664 +               return pin->hdir->hi_inode;
12665 +       return NULL;
12666 +}
12667 +
12668 +static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
12669 +{
12670 +       if (pin)
12671 +               return pin->hdir;
12672 +       return NULL;
12673 +}
12674 +
12675 +static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
12676 +{
12677 +       if (pin)
12678 +               pin->dentry = dentry;
12679 +}
12680 +
12681 +static inline void au_pin_set_parent_lflag(struct au_pin *pin,
12682 +                                          unsigned char lflag)
12683 +{
12684 +       if (pin) {
12685 +               /* dirty macros require brackets */
12686 +               if (lflag) {
12687 +                       au_fset_pin(pin->flags, DI_LOCKED);
12688 +               } else {
12689 +                       au_fclr_pin(pin->flags, DI_LOCKED);
12690 +               }
12691 +       }
12692 +}
12693 +
12694 +static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
12695 +{
12696 +       if (pin) {
12697 +               dput(pin->parent);
12698 +               pin->parent = dget(parent);
12699 +       }
12700 +}
12701 +
12702 +/* ---------------------------------------------------------------------- */
12703 +
12704 +#ifdef CONFIG_AUFS_HNOTIFY
12705 +struct au_hnotify_op {
12706 +       void (*ctl)(struct au_hinode *hinode, int do_set);
12707 +       int (*alloc)(struct au_hnotify *hn, struct inode *h_inode);
12708 +       void (*free)(struct au_hnotify *hn);
12709 +
12710 +       void (*fin)(void);
12711 +       int (*init)(void);
12712 +};
12713 +
12714 +/* hnotify.c */
12715 +int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
12716 +               struct inode *h_inode);
12717 +void au_hn_free(struct au_hinode *hinode);
12718 +void au_hn_ctl(struct au_hinode *hinode, int do_set);
12719 +void au_hn_reset(struct inode *inode, unsigned int flags);
12720 +int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
12721 +              struct qstr *h_child_qstr, struct inode *h_child_inode);
12722 +int __init au_hnotify_init(void);
12723 +void au_hnotify_fin(void);
12724 +
12725 +/* hfsnotify.c */
12726 +extern const struct au_hnotify_op au_hnotify_op;
12727 +
12728 +static inline
12729 +void au_hn_init(struct au_hinode *hinode)
12730 +{
12731 +       hinode->hi_notify = NULL;
12732 +}
12733 +
12734 +#else
12735 +static inline
12736 +int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
12737 +               struct inode *inode __maybe_unused,
12738 +               struct inode *h_inode __maybe_unused)
12739 +{
12740 +       return -EOPNOTSUPP;
12741 +}
12742 +
12743 +AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
12744 +AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
12745 +          int do_set __maybe_unused)
12746 +AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
12747 +          unsigned int flags __maybe_unused)
12748 +AuStubInt0(__init au_hnotify_init, void)
12749 +AuStubVoid(au_hnotify_fin, void)
12750 +AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
12751 +#endif /* CONFIG_AUFS_HNOTIFY */
12752 +
12753 +static inline void au_hn_suspend(struct au_hinode *hdir)
12754 +{
12755 +       au_hn_ctl(hdir, /*do_set*/0);
12756 +}
12757 +
12758 +static inline void au_hn_resume(struct au_hinode *hdir)
12759 +{
12760 +       au_hn_ctl(hdir, /*do_set*/1);
12761 +}
12762 +
12763 +static inline void au_hn_imtx_lock(struct au_hinode *hdir)
12764 +{
12765 +       mutex_lock(&hdir->hi_inode->i_mutex);
12766 +       au_hn_suspend(hdir);
12767 +}
12768 +
12769 +static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
12770 +                                         unsigned int sc __maybe_unused)
12771 +{
12772 +       mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
12773 +       au_hn_suspend(hdir);
12774 +}
12775 +
12776 +static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
12777 +{
12778 +       au_hn_resume(hdir);
12779 +       mutex_unlock(&hdir->hi_inode->i_mutex);
12780 +}
12781 +
12782 +#endif /* __KERNEL__ */
12783 +#endif /* __AUFS_INODE_H__ */
12784 diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
12785 --- /usr/share/empty/fs/aufs/ioctl.c    1970-01-01 01:00:00.000000000 +0100
12786 +++ linux/fs/aufs/ioctl.c       2010-10-21 09:52:43.090291764 +0200
12787 @@ -0,0 +1,155 @@
12788 +/*
12789 + * Copyright (C) 2005-2010 Junjiro R. Okajima
12790 + *
12791 + * This program, aufs is free software; you can redistribute it and/or modify
12792 + * it under the terms of the GNU General Public License as published by
12793 + * the Free Software Foundation; either version 2 of the License, or
12794 + * (at your option) any later version.
12795 + *
12796 + * This program is distributed in the hope that it will be useful,
12797 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12798 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12799 + * GNU General Public License for more details.
12800 + *
12801 + * You should have received a copy of the GNU General Public License
12802 + * along with this program; if not, write to the Free Software
12803 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
12804 + */
12805 +
12806 +/*
12807 + * ioctl
12808 + * plink-management and readdir in userspace.
12809 + * assist the pathconf(3) wrapper library.
12810 + */
12811 +
12812 +#include <linux/file.h>
12813 +#include "aufs.h"
12814 +
12815 +static int au_wbr_fd(struct path *path)
12816 +{
12817 +       int err, fd;
12818 +       aufs_bindex_t wbi, bindex, bend;
12819 +       struct file *h_file;
12820 +       struct super_block *sb;
12821 +       struct dentry *root;
12822 +       struct au_branch *wbr;
12823 +
12824 +       err = get_unused_fd();
12825 +       if (unlikely(err < 0))
12826 +               goto out;
12827 +       fd = err;
12828 +
12829 +       wbi = 0;
12830 +       sb = path->dentry->d_sb;
12831 +       root = sb->s_root;
12832 +       aufs_read_lock(root, AuLock_IR);
12833 +       wbr = au_sbr(sb, wbi);
12834 +       if (!(path->mnt->mnt_flags & MNT_READONLY)
12835 +           && !au_br_writable(wbr->br_perm)) {
12836 +               bend = au_sbend(sb);
12837 +               for (bindex = 1; bindex <= bend; bindex++) {
12838 +                       wbr = au_sbr(sb, bindex);
12839 +                       if (au_br_writable(wbr->br_perm)) {
12840 +                               wbi = bindex;
12841 +                               break;
12842 +                       }
12843 +               }
12844 +               wbr = au_sbr(sb, wbi);
12845 +       }
12846 +       AuDbg("wbi %d\n", wbi);
12847 +       h_file = au_h_open(root, wbi, O_RDONLY | O_DIRECTORY | O_LARGEFILE,
12848 +                          NULL);
12849 +       aufs_read_unlock(root, AuLock_IR);
12850 +       err = PTR_ERR(h_file);
12851 +       if (IS_ERR(h_file))
12852 +               goto out_fd;
12853 +
12854 +       atomic_dec(&wbr->br_count); /* cf. au_h_open() */
12855 +       fd_install(fd, h_file);
12856 +       err = fd;
12857 +       goto out; /* success */
12858 +
12859 +out_fd:
12860 +       put_unused_fd(fd);
12861 +out:
12862 +       return err;
12863 +}
12864 +
12865 +/* ---------------------------------------------------------------------- */
12866 +
12867 +long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
12868 +{
12869 +       long err;
12870 +
12871 +       switch (cmd) {
12872 +       case AUFS_CTL_PLINK_MAINT:
12873 +       case AUFS_CTL_PLINK_CLEAN:
12874 +               err = au_plink_ioctl(file, cmd);
12875 +               break;
12876 +
12877 +       case AUFS_CTL_RDU:
12878 +       case AUFS_CTL_RDU_INO:
12879 +               err = au_rdu_ioctl(file, cmd, arg);
12880 +               break;
12881 +
12882 +       case AUFS_CTL_WBR_FD:
12883 +               err = au_wbr_fd(&file->f_path);
12884 +               break;
12885 +
12886 +       default:
12887 +               /* do not call the lower */
12888 +               AuDbg("0x%x\n", cmd);
12889 +               err = -ENOTTY;
12890 +       }
12891 +
12892 +       AuTraceErr(err);
12893 +       return err;
12894 +}
12895 +
12896 +long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
12897 +{
12898 +       long err;
12899 +
12900 +       switch (cmd) {
12901 +       case AUFS_CTL_WBR_FD:
12902 +               err = au_wbr_fd(&file->f_path);
12903 +               break;
12904 +
12905 +       default:
12906 +               /* do not call the lower */
12907 +               AuDbg("0x%x\n", cmd);
12908 +               err = -ENOTTY;
12909 +       }
12910 +
12911 +       AuTraceErr(err);
12912 +       return err;
12913 +}
12914 +
12915 +#ifdef CONFIG_COMPAT
12916 +long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
12917 +                          unsigned long arg)
12918 +{
12919 +       long err;
12920 +
12921 +       switch (cmd) {
12922 +       case AUFS_CTL_RDU:
12923 +       case AUFS_CTL_RDU_INO:
12924 +               err = au_rdu_compat_ioctl(file, cmd, arg);
12925 +               break;
12926 +
12927 +       default:
12928 +               err = aufs_ioctl_dir(file, cmd, arg);
12929 +       }
12930 +
12931 +       AuTraceErr(err);
12932 +       return err;
12933 +}
12934 +
12935 +#if 0 /* unused yet */
12936 +long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
12937 +                             unsigned long arg)
12938 +{
12939 +       return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
12940 +}
12941 +#endif
12942 +#endif
12943 diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
12944 --- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
12945 +++ linux/fs/aufs/i_op_add.c    2010-10-21 09:52:43.090291764 +0200
12946 @@ -0,0 +1,672 @@
12947 +/*
12948 + * Copyright (C) 2005-2010 Junjiro R. Okajima
12949 + *
12950 + * This program, aufs is free software; you can redistribute it and/or modify
12951 + * it under the terms of the GNU General Public License as published by
12952 + * the Free Software Foundation; either version 2 of the License, or
12953 + * (at your option) any later version.
12954 + *
12955 + * This program is distributed in the hope that it will be useful,
12956 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12957 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12958 + * GNU General Public License for more details.
12959 + *
12960 + * You should have received a copy of the GNU General Public License
12961 + * along with this program; if not, write to the Free Software
12962 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
12963 + */
12964 +
12965 +/*
12966 + * inode operations (add entry)
12967 + */
12968 +
12969 +#include "aufs.h"
12970 +
12971 +/*
12972 + * final procedure of adding a new entry, except link(2).
12973 + * remove whiteout, instantiate, copyup the parent dir's times and size
12974 + * and update version.
12975 + * if it failed, re-create the removed whiteout.
12976 + */
12977 +static int epilog(struct inode *dir, aufs_bindex_t bindex,
12978 +                 struct dentry *wh_dentry, struct dentry *dentry)
12979 +{
12980 +       int err, rerr;
12981 +       aufs_bindex_t bwh;
12982 +       struct path h_path;
12983 +       struct inode *inode, *h_dir;
12984 +       struct dentry *wh;
12985 +
12986 +       bwh = -1;
12987 +       if (wh_dentry) {
12988 +               h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
12989 +               IMustLock(h_dir);
12990 +               AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
12991 +               bwh = au_dbwh(dentry);
12992 +               h_path.dentry = wh_dentry;
12993 +               h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
12994 +               err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
12995 +                                         dentry);
12996 +               if (unlikely(err))
12997 +                       goto out;
12998 +       }
12999 +
13000 +       inode = au_new_inode(dentry, /*must_new*/1);
13001 +       if (!IS_ERR(inode)) {
13002 +               d_instantiate(dentry, inode);
13003 +               dir = dentry->d_parent->d_inode; /* dir inode is locked */
13004 +               IMustLock(dir);
13005 +               if (au_ibstart(dir) == au_dbstart(dentry))
13006 +                       au_cpup_attr_timesizes(dir);
13007 +               dir->i_version++;
13008 +               return 0; /* success */
13009 +       }
13010 +
13011 +       err = PTR_ERR(inode);
13012 +       if (!wh_dentry)
13013 +               goto out;
13014 +
13015 +       /* revert */
13016 +       /* dir inode is locked */
13017 +       wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
13018 +       rerr = PTR_ERR(wh);
13019 +       if (IS_ERR(wh)) {
13020 +               AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
13021 +                       AuDLNPair(dentry), err, rerr);
13022 +               err = -EIO;
13023 +       } else
13024 +               dput(wh);
13025 +
13026 +out:
13027 +       return err;
13028 +}
13029 +
13030 +/*
13031 + * simple tests for the adding inode operations.
13032 + * following the checks in vfs, plus the parent-child relationship.
13033 + */
13034 +int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13035 +              struct dentry *h_parent, int isdir)
13036 +{
13037 +       int err;
13038 +       umode_t h_mode;
13039 +       struct dentry *h_dentry;
13040 +       struct inode *h_inode;
13041 +
13042 +       err = -ENAMETOOLONG;
13043 +       if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13044 +               goto out;
13045 +
13046 +       h_dentry = au_h_dptr(dentry, bindex);
13047 +       h_inode = h_dentry->d_inode;
13048 +       if (!dentry->d_inode) {
13049 +               err = -EEXIST;
13050 +               if (unlikely(h_inode))
13051 +                       goto out;
13052 +       } else {
13053 +               /* rename(2) case */
13054 +               err = -EIO;
13055 +               if (unlikely(!h_inode || !h_inode->i_nlink))
13056 +                       goto out;
13057 +
13058 +               h_mode = h_inode->i_mode;
13059 +               if (!isdir) {
13060 +                       err = -EISDIR;
13061 +                       if (unlikely(S_ISDIR(h_mode)))
13062 +                               goto out;
13063 +               } else if (unlikely(!S_ISDIR(h_mode))) {
13064 +                       err = -ENOTDIR;
13065 +                       goto out;
13066 +               }
13067 +       }
13068 +
13069 +       err = 0;
13070 +       /* expected parent dir is locked */
13071 +       if (unlikely(h_parent != h_dentry->d_parent))
13072 +               err = -EIO;
13073 +
13074 +out:
13075 +       AuTraceErr(err);
13076 +       return err;
13077 +}
13078 +
13079 +/*
13080 + * initial procedure of adding a new entry.
13081 + * prepare writable branch and the parent dir, lock it,
13082 + * and lookup whiteout for the new entry.
13083 + */
13084 +static struct dentry*
13085 +lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
13086 +                 struct dentry *src_dentry, struct au_pin *pin,
13087 +                 struct au_wr_dir_args *wr_dir_args)
13088 +{
13089 +       struct dentry *wh_dentry, *h_parent;
13090 +       struct super_block *sb;
13091 +       struct au_branch *br;
13092 +       int err;
13093 +       unsigned int udba;
13094 +       aufs_bindex_t bcpup;
13095 +
13096 +       AuDbg("%.*s\n", AuDLNPair(dentry));
13097 +
13098 +       err = au_wr_dir(dentry, src_dentry, wr_dir_args);
13099 +       bcpup = err;
13100 +       wh_dentry = ERR_PTR(err);
13101 +       if (unlikely(err < 0))
13102 +               goto out;
13103 +
13104 +       sb = dentry->d_sb;
13105 +       udba = au_opt_udba(sb);
13106 +       err = au_pin(pin, dentry, bcpup, udba,
13107 +                    AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13108 +       wh_dentry = ERR_PTR(err);
13109 +       if (unlikely(err))
13110 +               goto out;
13111 +
13112 +       h_parent = au_pinned_h_parent(pin);
13113 +       if (udba != AuOpt_UDBA_NONE
13114 +           && au_dbstart(dentry) == bcpup)
13115 +               err = au_may_add(dentry, bcpup, h_parent,
13116 +                                au_ftest_wrdir(wr_dir_args->flags, ISDIR));
13117 +       else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13118 +               err = -ENAMETOOLONG;
13119 +       wh_dentry = ERR_PTR(err);
13120 +       if (unlikely(err))
13121 +               goto out_unpin;
13122 +
13123 +       br = au_sbr(sb, bcpup);
13124 +       if (dt) {
13125 +               struct path tmp = {
13126 +                       .dentry = h_parent,
13127 +                       .mnt    = br->br_mnt
13128 +               };
13129 +               au_dtime_store(dt, au_pinned_parent(pin), &tmp);
13130 +       }
13131 +
13132 +       wh_dentry = NULL;
13133 +       if (bcpup != au_dbwh(dentry))
13134 +               goto out; /* success */
13135 +
13136 +       wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
13137 +
13138 +out_unpin:
13139 +       if (IS_ERR(wh_dentry))
13140 +               au_unpin(pin);
13141 +out:
13142 +       return wh_dentry;
13143 +}
13144 +
13145 +/* ---------------------------------------------------------------------- */
13146 +
13147 +enum { Mknod, Symlink, Creat };
13148 +struct simple_arg {
13149 +       int type;
13150 +       union {
13151 +               struct {
13152 +                       int mode;
13153 +                       struct nameidata *nd;
13154 +               } c;
13155 +               struct {
13156 +                       const char *symname;
13157 +               } s;
13158 +               struct {
13159 +                       int mode;
13160 +                       dev_t dev;
13161 +               } m;
13162 +       } u;
13163 +};
13164 +
13165 +static int add_simple(struct inode *dir, struct dentry *dentry,
13166 +                     struct simple_arg *arg)
13167 +{
13168 +       int err;
13169 +       aufs_bindex_t bstart;
13170 +       unsigned char created;
13171 +       struct au_dtime dt;
13172 +       struct au_pin pin;
13173 +       struct path h_path;
13174 +       struct dentry *wh_dentry, *parent;
13175 +       struct inode *h_dir;
13176 +       struct au_wr_dir_args wr_dir_args = {
13177 +               .force_btgt     = -1,
13178 +               .flags          = AuWrDir_ADD_ENTRY
13179 +       };
13180 +
13181 +       AuDbg("%.*s\n", AuDLNPair(dentry));
13182 +       IMustLock(dir);
13183 +
13184 +       parent = dentry->d_parent; /* dir inode is locked */
13185 +       aufs_read_lock(dentry, AuLock_DW);
13186 +       di_write_lock_parent(parent);
13187 +       wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
13188 +                                     &wr_dir_args);
13189 +       err = PTR_ERR(wh_dentry);
13190 +       if (IS_ERR(wh_dentry))
13191 +               goto out;
13192 +
13193 +       bstart = au_dbstart(dentry);
13194 +       h_path.dentry = au_h_dptr(dentry, bstart);
13195 +       h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
13196 +       h_dir = au_pinned_h_dir(&pin);
13197 +       switch (arg->type) {
13198 +       case Creat:
13199 +               err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
13200 +               break;
13201 +       case Symlink:
13202 +               err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
13203 +               break;
13204 +       case Mknod:
13205 +               err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
13206 +               break;
13207 +       default:
13208 +               BUG();
13209 +       }
13210 +       created = !err;
13211 +       if (!err)
13212 +               err = epilog(dir, bstart, wh_dentry, dentry);
13213 +
13214 +       /* revert */
13215 +       if (unlikely(created && err && h_path.dentry->d_inode)) {
13216 +               int rerr;
13217 +               rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
13218 +               if (rerr) {
13219 +                       AuIOErr("%.*s revert failure(%d, %d)\n",
13220 +                               AuDLNPair(dentry), err, rerr);
13221 +                       err = -EIO;
13222 +               }
13223 +               au_dtime_revert(&dt);
13224 +               d_drop(dentry);
13225 +       }
13226 +
13227 +       au_unpin(&pin);
13228 +       dput(wh_dentry);
13229 +
13230 +out:
13231 +       if (unlikely(err)) {
13232 +               au_update_dbstart(dentry);
13233 +               d_drop(dentry);
13234 +       }
13235 +       di_write_unlock(parent);
13236 +       aufs_read_unlock(dentry, AuLock_DW);
13237 +       return err;
13238 +}
13239 +
13240 +int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
13241 +{
13242 +       struct simple_arg arg = {
13243 +               .type = Mknod,
13244 +               .u.m = {
13245 +                       .mode   = mode,
13246 +                       .dev    = dev
13247 +               }
13248 +       };
13249 +       return add_simple(dir, dentry, &arg);
13250 +}
13251 +
13252 +int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
13253 +{
13254 +       struct simple_arg arg = {
13255 +               .type = Symlink,
13256 +               .u.s.symname = symname
13257 +       };
13258 +       return add_simple(dir, dentry, &arg);
13259 +}
13260 +
13261 +int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13262 +               struct nameidata *nd)
13263 +{
13264 +       struct simple_arg arg = {
13265 +               .type = Creat,
13266 +               .u.c = {
13267 +                       .mode   = mode,
13268 +                       .nd     = nd
13269 +               }
13270 +       };
13271 +       return add_simple(dir, dentry, &arg);
13272 +}
13273 +
13274 +/* ---------------------------------------------------------------------- */
13275 +
13276 +struct au_link_args {
13277 +       aufs_bindex_t bdst, bsrc;
13278 +       struct au_pin pin;
13279 +       struct path h_path;
13280 +       struct dentry *src_parent, *parent;
13281 +};
13282 +
13283 +static int au_cpup_before_link(struct dentry *src_dentry,
13284 +                              struct au_link_args *a)
13285 +{
13286 +       int err;
13287 +       struct dentry *h_src_dentry;
13288 +       struct mutex *h_mtx;
13289 +       struct file *h_file;
13290 +
13291 +       di_read_lock_parent(a->src_parent, AuLock_IR);
13292 +       err = au_test_and_cpup_dirs(src_dentry, a->bdst);
13293 +       if (unlikely(err))
13294 +               goto out;
13295 +
13296 +       h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
13297 +       h_mtx = &h_src_dentry->d_inode->i_mutex;
13298 +       err = au_pin(&a->pin, src_dentry, a->bdst,
13299 +                    au_opt_udba(src_dentry->d_sb),
13300 +                    AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13301 +       if (unlikely(err))
13302 +               goto out;
13303 +       mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13304 +       h_file = au_h_open_pre(src_dentry, a->bsrc);
13305 +       if (IS_ERR(h_file)) {
13306 +               err = PTR_ERR(h_file);
13307 +               h_file = NULL;
13308 +       } else
13309 +               err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
13310 +                                        AuCpup_DTIME /* | AuCpup_KEEPLINO */);
13311 +       mutex_unlock(h_mtx);
13312 +       au_h_open_post(src_dentry, a->bsrc, h_file);
13313 +       au_unpin(&a->pin);
13314 +
13315 +out:
13316 +       di_read_unlock(a->src_parent, AuLock_IR);
13317 +       return err;
13318 +}
13319 +
13320 +static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
13321 +{
13322 +       int err;
13323 +       unsigned char plink;
13324 +       struct inode *h_inode, *inode;
13325 +       struct dentry *h_src_dentry;
13326 +       struct super_block *sb;
13327 +       struct file *h_file;
13328 +
13329 +       plink = 0;
13330 +       h_inode = NULL;
13331 +       sb = src_dentry->d_sb;
13332 +       inode = src_dentry->d_inode;
13333 +       if (au_ibstart(inode) <= a->bdst)
13334 +               h_inode = au_h_iptr(inode, a->bdst);
13335 +       if (!h_inode || !h_inode->i_nlink) {
13336 +               /* copyup src_dentry as the name of dentry. */
13337 +               au_set_dbstart(src_dentry, a->bdst);
13338 +               au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
13339 +               h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
13340 +               mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
13341 +               h_file = au_h_open_pre(src_dentry, a->bsrc);
13342 +               if (IS_ERR(h_file)) {
13343 +                       err = PTR_ERR(h_file);
13344 +                       h_file = NULL;
13345 +               } else
13346 +                       err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
13347 +                                                -1, AuCpup_KEEPLINO,
13348 +                                                a->parent);
13349 +               mutex_unlock(&h_inode->i_mutex);
13350 +               au_h_open_post(src_dentry, a->bsrc, h_file);
13351 +               au_set_h_dptr(src_dentry, a->bdst, NULL);
13352 +               au_set_dbstart(src_dentry, a->bsrc);
13353 +       } else {
13354 +               /* the inode of src_dentry already exists on a.bdst branch */
13355 +               h_src_dentry = d_find_alias(h_inode);
13356 +               if (!h_src_dentry && au_plink_test(inode)) {
13357 +                       plink = 1;
13358 +                       h_src_dentry = au_plink_lkup(inode, a->bdst);
13359 +                       err = PTR_ERR(h_src_dentry);
13360 +                       if (IS_ERR(h_src_dentry))
13361 +                               goto out;
13362 +
13363 +                       if (unlikely(!h_src_dentry->d_inode)) {
13364 +                               dput(h_src_dentry);
13365 +                               h_src_dentry = NULL;
13366 +                       }
13367 +
13368 +               }
13369 +               if (h_src_dentry) {
13370 +                       err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13371 +                                        &a->h_path);
13372 +                       dput(h_src_dentry);
13373 +               } else {
13374 +                       AuIOErr("no dentry found for hi%lu on b%d\n",
13375 +                               h_inode->i_ino, a->bdst);
13376 +                       err = -EIO;
13377 +               }
13378 +       }
13379 +
13380 +       if (!err && !plink)
13381 +               au_plink_append(inode, a->bdst, a->h_path.dentry);
13382 +
13383 +out:
13384 +       return err;
13385 +}
13386 +
13387 +int aufs_link(struct dentry *src_dentry, struct inode *dir,
13388 +             struct dentry *dentry)
13389 +{
13390 +       int err, rerr;
13391 +       struct au_dtime dt;
13392 +       struct au_link_args *a;
13393 +       struct dentry *wh_dentry, *h_src_dentry;
13394 +       struct inode *inode;
13395 +       struct super_block *sb;
13396 +       struct au_wr_dir_args wr_dir_args = {
13397 +               /* .force_btgt  = -1, */
13398 +               .flags          = AuWrDir_ADD_ENTRY
13399 +       };
13400 +
13401 +       IMustLock(dir);
13402 +       inode = src_dentry->d_inode;
13403 +       IMustLock(inode);
13404 +
13405 +       err = -ENOENT;
13406 +       if (unlikely(!inode->i_nlink))
13407 +               goto out;
13408 +
13409 +       err = -ENOMEM;
13410 +       a = kzalloc(sizeof(*a), GFP_NOFS);
13411 +       if (unlikely(!a))
13412 +               goto out;
13413 +
13414 +       a->parent = dentry->d_parent; /* dir inode is locked */
13415 +       aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
13416 +       a->src_parent = dget_parent(src_dentry);
13417 +       wr_dir_args.force_btgt = au_dbstart(src_dentry);
13418 +
13419 +       di_write_lock_parent(a->parent);
13420 +       wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
13421 +       wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
13422 +                                     &wr_dir_args);
13423 +       err = PTR_ERR(wh_dentry);
13424 +       if (IS_ERR(wh_dentry))
13425 +               goto out_unlock;
13426 +
13427 +       err = 0;
13428 +       sb = dentry->d_sb;
13429 +       a->bdst = au_dbstart(dentry);
13430 +       a->h_path.dentry = au_h_dptr(dentry, a->bdst);
13431 +       a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
13432 +       a->bsrc = au_dbstart(src_dentry);
13433 +       if (au_opt_test(au_mntflags(sb), PLINK)) {
13434 +               if (a->bdst < a->bsrc
13435 +                   /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
13436 +                       err = au_cpup_or_link(src_dentry, a);
13437 +               else {
13438 +                       h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13439 +                       err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13440 +                                        &a->h_path);
13441 +               }
13442 +       } else {
13443 +               /*
13444 +                * copyup src_dentry to the branch we process,
13445 +                * and then link(2) to it.
13446 +                */
13447 +               if (a->bdst < a->bsrc
13448 +                   /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
13449 +                       au_unpin(&a->pin);
13450 +                       di_write_unlock(a->parent);
13451 +                       err = au_cpup_before_link(src_dentry, a);
13452 +                       di_write_lock_parent(a->parent);
13453 +                       if (!err)
13454 +                               err = au_pin(&a->pin, dentry, a->bdst,
13455 +                                            au_opt_udba(sb),
13456 +                                            AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13457 +                       if (unlikely(err))
13458 +                               goto out_wh;
13459 +               }
13460 +               if (!err) {
13461 +                       h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13462 +                       err = -ENOENT;
13463 +                       if (h_src_dentry && h_src_dentry->d_inode)
13464 +                               err = vfsub_link(h_src_dentry,
13465 +                                                au_pinned_h_dir(&a->pin),
13466 +                                                &a->h_path);
13467 +               }
13468 +       }
13469 +       if (unlikely(err))
13470 +               goto out_unpin;
13471 +
13472 +       if (wh_dentry) {
13473 +               a->h_path.dentry = wh_dentry;
13474 +               err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
13475 +                                         dentry);
13476 +               if (unlikely(err))
13477 +                       goto out_revert;
13478 +       }
13479 +
13480 +       dir->i_version++;
13481 +       if (au_ibstart(dir) == au_dbstart(dentry))
13482 +               au_cpup_attr_timesizes(dir);
13483 +       inc_nlink(inode);
13484 +       inode->i_ctime = dir->i_ctime;
13485 +       if (!d_unhashed(a->h_path.dentry))
13486 +               d_instantiate(dentry, au_igrab(inode));
13487 +       else
13488 +               /* some filesystem calls d_drop() */
13489 +               d_drop(dentry);
13490 +       goto out_unpin; /* success */
13491 +
13492 +out_revert:
13493 +       rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
13494 +       if (!rerr)
13495 +               goto out_dt;
13496 +       AuIOErr("%.*s reverting failed(%d, %d)\n",
13497 +               AuDLNPair(dentry), err, rerr);
13498 +       err = -EIO;
13499 +out_dt:
13500 +       d_drop(dentry);
13501 +       au_dtime_revert(&dt);
13502 +out_unpin:
13503 +       au_unpin(&a->pin);
13504 +out_wh:
13505 +       dput(wh_dentry);
13506 +out_unlock:
13507 +       if (unlikely(err)) {
13508 +               au_update_dbstart(dentry);
13509 +               d_drop(dentry);
13510 +       }
13511 +       di_write_unlock(a->parent);
13512 +       dput(a->src_parent);
13513 +       aufs_read_and_write_unlock2(dentry, src_dentry);
13514 +       kfree(a);
13515 +out:
13516 +       return err;
13517 +}
13518 +
13519 +int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
13520 +{
13521 +       int err, rerr;
13522 +       aufs_bindex_t bindex;
13523 +       unsigned char diropq;
13524 +       struct path h_path;
13525 +       struct dentry *wh_dentry, *parent, *opq_dentry;
13526 +       struct mutex *h_mtx;
13527 +       struct super_block *sb;
13528 +       struct {
13529 +               struct au_pin pin;
13530 +               struct au_dtime dt;
13531 +       } *a; /* reduce the stack usage */
13532 +       struct au_wr_dir_args wr_dir_args = {
13533 +               .force_btgt     = -1,
13534 +               .flags          = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
13535 +       };
13536 +
13537 +       IMustLock(dir);
13538 +
13539 +       err = -ENOMEM;
13540 +       a = kmalloc(sizeof(*a), GFP_NOFS);
13541 +       if (unlikely(!a))
13542 +               goto out;
13543 +
13544 +       aufs_read_lock(dentry, AuLock_DW);
13545 +       parent = dentry->d_parent; /* dir inode is locked */
13546 +       di_write_lock_parent(parent);
13547 +       wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
13548 +                                     &a->pin, &wr_dir_args);
13549 +       err = PTR_ERR(wh_dentry);
13550 +       if (IS_ERR(wh_dentry))
13551 +               goto out_free;
13552 +
13553 +       sb = dentry->d_sb;
13554 +       bindex = au_dbstart(dentry);
13555 +       h_path.dentry = au_h_dptr(dentry, bindex);
13556 +       h_path.mnt = au_sbr_mnt(sb, bindex);
13557 +       err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
13558 +       if (unlikely(err))
13559 +               goto out_unlock;
13560 +
13561 +       /* make the dir opaque */
13562 +       diropq = 0;
13563 +       h_mtx = &h_path.dentry->d_inode->i_mutex;
13564 +       if (wh_dentry
13565 +           || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
13566 +               mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13567 +               opq_dentry = au_diropq_create(dentry, bindex);
13568 +               mutex_unlock(h_mtx);
13569 +               err = PTR_ERR(opq_dentry);
13570 +               if (IS_ERR(opq_dentry))
13571 +                       goto out_dir;
13572 +               dput(opq_dentry);
13573 +               diropq = 1;
13574 +       }
13575 +
13576 +       err = epilog(dir, bindex, wh_dentry, dentry);
13577 +       if (!err) {
13578 +               inc_nlink(dir);
13579 +               goto out_unlock; /* success */
13580 +       }
13581 +
13582 +       /* revert */
13583 +       if (diropq) {
13584 +               AuLabel(revert opq);
13585 +               mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13586 +               rerr = au_diropq_remove(dentry, bindex);
13587 +               mutex_unlock(h_mtx);
13588 +               if (rerr) {
13589 +                       AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
13590 +                               AuDLNPair(dentry), err, rerr);
13591 +                       err = -EIO;
13592 +               }
13593 +       }
13594 +
13595 +out_dir:
13596 +       AuLabel(revert dir);
13597 +       rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
13598 +       if (rerr) {
13599 +               AuIOErr("%.*s reverting dir failed(%d, %d)\n",
13600 +                       AuDLNPair(dentry), err, rerr);
13601 +               err = -EIO;
13602 +       }
13603 +       d_drop(dentry);
13604 +       au_dtime_revert(&a->dt);
13605 +out_unlock:
13606 +       au_unpin(&a->pin);
13607 +       dput(wh_dentry);
13608 +out_free:
13609 +       if (unlikely(err)) {
13610 +               au_update_dbstart(dentry);
13611 +               d_drop(dentry);
13612 +       }
13613 +       di_write_unlock(parent);
13614 +       aufs_read_unlock(dentry, AuLock_DW);
13615 +       kfree(a);
13616 +out:
13617 +       return err;
13618 +}
13619 diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
13620 --- /usr/share/empty/fs/aufs/i_op.c     1970-01-01 01:00:00.000000000 +0100
13621 +++ linux/fs/aufs/i_op.c        2010-10-21 09:52:43.090291764 +0200
13622 @@ -0,0 +1,911 @@
13623 +/*
13624 + * Copyright (C) 2005-2010 Junjiro R. Okajima
13625 + *
13626 + * This program, aufs is free software; you can redistribute it and/or modify
13627 + * it under the terms of the GNU General Public License as published by
13628 + * the Free Software Foundation; either version 2 of the License, or
13629 + * (at your option) any later version.
13630 + *
13631 + * This program is distributed in the hope that it will be useful,
13632 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13633 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13634 + * GNU General Public License for more details.
13635 + *
13636 + * You should have received a copy of the GNU General Public License
13637 + * along with this program; if not, write to the Free Software
13638 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
13639 + */
13640 +
13641 +/*
13642 + * inode operations (except add/del/rename)
13643 + */
13644 +
13645 +#include <linux/device_cgroup.h>
13646 +#include <linux/fs_stack.h>
13647 +#include <linux/mm.h>
13648 +#include <linux/namei.h>
13649 +#include <linux/security.h>
13650 +#include <linux/uaccess.h>
13651 +#include "aufs.h"
13652 +
13653 +static int h_permission(struct inode *h_inode, int mask,
13654 +                       struct vfsmount *h_mnt, int brperm)
13655 +{
13656 +       int err;
13657 +       const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
13658 +
13659 +       err = -EACCES;
13660 +       if ((write_mask && IS_IMMUTABLE(h_inode))
13661 +           || ((mask & MAY_EXEC)
13662 +               && S_ISREG(h_inode->i_mode)
13663 +               && ((h_mnt->mnt_flags & MNT_NOEXEC)
13664 +                   || !(h_inode->i_mode & S_IXUGO))))
13665 +               goto out;
13666 +
13667 +       /*
13668 +        * - skip the lower fs test in the case of write to ro branch.
13669 +        * - nfs dir permission write check is optimized, but a policy for
13670 +        *   link/rename requires a real check.
13671 +        */
13672 +       if ((write_mask && !au_br_writable(brperm))
13673 +           || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
13674 +               && write_mask && !(mask & MAY_READ))
13675 +           || !h_inode->i_op->permission) {
13676 +               /* AuLabel(generic_permission); */
13677 +               err = generic_permission(h_inode, mask,
13678 +                                        h_inode->i_op->check_acl);
13679 +       } else {
13680 +               /* AuLabel(h_inode->permission); */
13681 +               err = h_inode->i_op->permission(h_inode, mask);
13682 +               AuTraceErr(err);
13683 +       }
13684 +
13685 +       if (!err)
13686 +               err = devcgroup_inode_permission(h_inode, mask);
13687 +       if (!err)
13688 +               err = security_inode_permission(h_inode, mask);
13689 +
13690 +#if 0
13691 +       if (!err) {
13692 +               /* todo: do we need to call ima_path_check()? */
13693 +               struct path h_path = {
13694 +                       .dentry =
13695 +                       .mnt    = h_mnt
13696 +               };
13697 +               err = ima_path_check(&h_path,
13698 +                                    mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
13699 +                                    IMA_COUNT_LEAVE);
13700 +       }
13701 +#endif
13702 +
13703 +out:
13704 +       return err;
13705 +}
13706 +
13707 +static int aufs_permission(struct inode *inode, int mask)
13708 +{
13709 +       int err;
13710 +       aufs_bindex_t bindex, bend;
13711 +       const unsigned char isdir = !!S_ISDIR(inode->i_mode),
13712 +               write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
13713 +       struct inode *h_inode;
13714 +       struct super_block *sb;
13715 +       struct au_branch *br;
13716 +
13717 +       sb = inode->i_sb;
13718 +       si_read_lock(sb, AuLock_FLUSH);
13719 +       ii_read_lock_child(inode);
13720 +
13721 +       if (!isdir || write_mask) {
13722 +               err = au_busy_or_stale();
13723 +               h_inode = au_h_iptr(inode, au_ibstart(inode));
13724 +               if (unlikely(!h_inode
13725 +                            || (h_inode->i_mode & S_IFMT)
13726 +                            != (inode->i_mode & S_IFMT)))
13727 +                       goto out;
13728 +
13729 +               err = 0;
13730 +               bindex = au_ibstart(inode);
13731 +               br = au_sbr(sb, bindex);
13732 +               err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
13733 +               if (write_mask
13734 +                   && !err
13735 +                   && !special_file(h_inode->i_mode)) {
13736 +                       /* test whether the upper writable branch exists */
13737 +                       err = -EROFS;
13738 +                       for (; bindex >= 0; bindex--)
13739 +                               if (!au_br_rdonly(au_sbr(sb, bindex))) {
13740 +                                       err = 0;
13741 +                                       break;
13742 +                               }
13743 +               }
13744 +               goto out;
13745 +       }
13746 +
13747 +       /* non-write to dir */
13748 +       err = 0;
13749 +       bend = au_ibend(inode);
13750 +       for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
13751 +               h_inode = au_h_iptr(inode, bindex);
13752 +               if (h_inode) {
13753 +                       err = au_busy_or_stale();
13754 +                       if (unlikely(!S_ISDIR(h_inode->i_mode)))
13755 +                               break;
13756 +
13757 +                       br = au_sbr(sb, bindex);
13758 +                       err = h_permission(h_inode, mask, br->br_mnt,
13759 +                                          br->br_perm);
13760 +               }
13761 +       }
13762 +
13763 +out:
13764 +       ii_read_unlock(inode);
13765 +       si_read_unlock(sb);
13766 +       return err;
13767 +}
13768 +
13769 +/* ---------------------------------------------------------------------- */
13770 +
13771 +static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
13772 +                                 struct nameidata *nd)
13773 +{
13774 +       struct dentry *ret, *parent;
13775 +       struct inode *inode;
13776 +       struct super_block *sb;
13777 +       int err, npositive;
13778 +
13779 +       IMustLock(dir);
13780 +
13781 +       sb = dir->i_sb;
13782 +       si_read_lock(sb, AuLock_FLUSH);
13783 +       ret = ERR_PTR(-ENAMETOOLONG);
13784 +       if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13785 +               goto out;
13786 +       err = au_di_init(dentry);
13787 +       ret = ERR_PTR(err);
13788 +       if (unlikely(err))
13789 +               goto out;
13790 +
13791 +       parent = dentry->d_parent; /* dir inode is locked */
13792 +       di_read_lock_parent(parent, AuLock_IR);
13793 +       npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
13794 +       di_read_unlock(parent, AuLock_IR);
13795 +       err = npositive;
13796 +       ret = ERR_PTR(err);
13797 +       if (unlikely(err < 0))
13798 +               goto out_unlock;
13799 +
13800 +       inode = NULL;
13801 +       if (npositive) {
13802 +               inode = au_new_inode(dentry, /*must_new*/0);
13803 +               ret = (void *)inode;
13804 +       }
13805 +       if (IS_ERR(inode))
13806 +               goto out_unlock;
13807 +
13808 +       ret = d_splice_alias(inode, dentry);
13809 +       if (unlikely(IS_ERR(ret) && inode))
13810 +               ii_write_unlock(inode);
13811 +
13812 +out_unlock:
13813 +       di_write_unlock(dentry);
13814 +out:
13815 +       si_read_unlock(sb);
13816 +       return ret;
13817 +}
13818 +
13819 +/* ---------------------------------------------------------------------- */
13820 +
13821 +static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
13822 +                         const unsigned char add_entry, aufs_bindex_t bcpup,
13823 +                         aufs_bindex_t bstart)
13824 +{
13825 +       int err;
13826 +       struct dentry *h_parent;
13827 +       struct inode *h_dir;
13828 +
13829 +       if (add_entry) {
13830 +               au_update_dbstart(dentry);
13831 +               IMustLock(parent->d_inode);
13832 +       } else
13833 +               di_write_lock_parent(parent);
13834 +
13835 +       err = 0;
13836 +       if (!au_h_dptr(parent, bcpup)) {
13837 +               if (bstart < bcpup)
13838 +                       err = au_cpdown_dirs(dentry, bcpup);
13839 +               else
13840 +                       err = au_cpup_dirs(dentry, bcpup);
13841 +       }
13842 +       if (!err && add_entry) {
13843 +               h_parent = au_h_dptr(parent, bcpup);
13844 +               h_dir = h_parent->d_inode;
13845 +               mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
13846 +               err = au_lkup_neg(dentry, bcpup);
13847 +               /* todo: no unlock here */
13848 +               mutex_unlock(&h_dir->i_mutex);
13849 +               if (bstart < bcpup && au_dbstart(dentry) < 0) {
13850 +                       au_set_dbstart(dentry, 0);
13851 +                       au_update_dbrange(dentry, /*do_put_zero*/0);
13852 +               }
13853 +       }
13854 +
13855 +       if (!add_entry)
13856 +               di_write_unlock(parent);
13857 +       if (!err)
13858 +               err = bcpup; /* success */
13859 +
13860 +       return err;
13861 +}
13862 +
13863 +/*
13864 + * decide the branch and the parent dir where we will create a new entry.
13865 + * returns new bindex or an error.
13866 + * copyup the parent dir if needed.
13867 + */
13868 +int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
13869 +             struct au_wr_dir_args *args)
13870 +{
13871 +       int err;
13872 +       aufs_bindex_t bcpup, bstart, src_bstart;
13873 +       const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
13874 +                                                        ADD_ENTRY);
13875 +       struct super_block *sb;
13876 +       struct dentry *parent;
13877 +       struct au_sbinfo *sbinfo;
13878 +
13879 +       sb = dentry->d_sb;
13880 +       sbinfo = au_sbi(sb);
13881 +       parent = dget_parent(dentry);
13882 +       bstart = au_dbstart(dentry);
13883 +       bcpup = bstart;
13884 +       if (args->force_btgt < 0) {
13885 +               if (src_dentry) {
13886 +                       src_bstart = au_dbstart(src_dentry);
13887 +                       if (src_bstart < bstart)
13888 +                               bcpup = src_bstart;
13889 +               } else if (add_entry) {
13890 +                       err = AuWbrCreate(sbinfo, dentry,
13891 +                                         au_ftest_wrdir(args->flags, ISDIR));
13892 +                       bcpup = err;
13893 +               }
13894 +
13895 +               if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
13896 +                       if (add_entry)
13897 +                               err = AuWbrCopyup(sbinfo, dentry);
13898 +                       else {
13899 +                               if (!IS_ROOT(dentry)) {
13900 +                                       di_read_lock_parent(parent, !AuLock_IR);
13901 +                                       err = AuWbrCopyup(sbinfo, dentry);
13902 +                                       di_read_unlock(parent, !AuLock_IR);
13903 +                               } else
13904 +                                       err = AuWbrCopyup(sbinfo, dentry);
13905 +                       }
13906 +                       bcpup = err;
13907 +                       if (unlikely(err < 0))
13908 +                               goto out;
13909 +               }
13910 +       } else {
13911 +               bcpup = args->force_btgt;
13912 +               AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
13913 +       }
13914 +       AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
13915 +       err = bcpup;
13916 +       if (bcpup == bstart)
13917 +               goto out; /* success */
13918 +       else if (bstart < bcpup)
13919 +               au_update_dbrange(dentry, /*do_put_zero*/1);
13920 +
13921 +       /* copyup the new parent into the branch we process */
13922 +       err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
13923 +
13924 +out:
13925 +       dput(parent);
13926 +       return err;
13927 +}
13928 +
13929 +/* ---------------------------------------------------------------------- */
13930 +
13931 +struct dentry *au_pinned_h_parent(struct au_pin *pin)
13932 +{
13933 +       if (pin && pin->parent)
13934 +               return au_h_dptr(pin->parent, pin->bindex);
13935 +       return NULL;
13936 +}
13937 +
13938 +void au_unpin(struct au_pin *p)
13939 +{
13940 +       if (au_ftest_pin(p->flags, MNT_WRITE))
13941 +               mnt_drop_write(p->h_mnt);
13942 +       if (!p->hdir)
13943 +               return;
13944 +
13945 +       au_hn_imtx_unlock(p->hdir);
13946 +       if (!au_ftest_pin(p->flags, DI_LOCKED))
13947 +               di_read_unlock(p->parent, AuLock_IR);
13948 +       iput(p->hdir->hi_inode);
13949 +       dput(p->parent);
13950 +       p->parent = NULL;
13951 +       p->hdir = NULL;
13952 +       p->h_mnt = NULL;
13953 +}
13954 +
13955 +int au_do_pin(struct au_pin *p)
13956 +{
13957 +       int err;
13958 +       struct super_block *sb;
13959 +       struct dentry *h_dentry, *h_parent;
13960 +       struct au_branch *br;
13961 +       struct inode *h_dir;
13962 +
13963 +       err = 0;
13964 +       sb = p->dentry->d_sb;
13965 +       br = au_sbr(sb, p->bindex);
13966 +       if (IS_ROOT(p->dentry)) {
13967 +               if (au_ftest_pin(p->flags, MNT_WRITE)) {
13968 +                       p->h_mnt = br->br_mnt;
13969 +                       err = mnt_want_write(p->h_mnt);
13970 +                       if (unlikely(err)) {
13971 +                               au_fclr_pin(p->flags, MNT_WRITE);
13972 +                               goto out_err;
13973 +                       }
13974 +               }
13975 +               goto out;
13976 +       }
13977 +
13978 +       h_dentry = NULL;
13979 +       if (p->bindex <= au_dbend(p->dentry))
13980 +               h_dentry = au_h_dptr(p->dentry, p->bindex);
13981 +
13982 +       p->parent = dget_parent(p->dentry);
13983 +       if (!au_ftest_pin(p->flags, DI_LOCKED))
13984 +               di_read_lock(p->parent, AuLock_IR, p->lsc_di);
13985 +
13986 +       h_dir = NULL;
13987 +       h_parent = au_h_dptr(p->parent, p->bindex);
13988 +       p->hdir = au_hi(p->parent->d_inode, p->bindex);
13989 +       if (p->hdir)
13990 +               h_dir = p->hdir->hi_inode;
13991 +
13992 +       /*
13993 +        * udba case, or
13994 +        * if DI_LOCKED is not set, then p->parent may be different
13995 +        * and h_parent can be NULL.
13996 +        */
13997 +       if (unlikely(!p->hdir || !h_dir || !h_parent)) {
13998 +               if (!au_ftest_pin(p->flags, DI_LOCKED))
13999 +                       di_read_unlock(p->parent, AuLock_IR);
14000 +               dput(p->parent);
14001 +               p->parent = NULL;
14002 +               goto out_err;
14003 +       }
14004 +
14005 +       au_igrab(h_dir);
14006 +       au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
14007 +
14008 +       if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
14009 +               err = -EBUSY;
14010 +               goto out_unpin;
14011 +       }
14012 +       if (h_dentry) {
14013 +               err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
14014 +               if (unlikely(err)) {
14015 +                       au_fclr_pin(p->flags, MNT_WRITE);
14016 +                       goto out_unpin;
14017 +               }
14018 +       }
14019 +
14020 +       if (au_ftest_pin(p->flags, MNT_WRITE)) {
14021 +               p->h_mnt = br->br_mnt;
14022 +               err = mnt_want_write(p->h_mnt);
14023 +               if (unlikely(err)) {
14024 +                       au_fclr_pin(p->flags, MNT_WRITE);
14025 +                       goto out_unpin;
14026 +               }
14027 +       }
14028 +       goto out; /* success */
14029 +
14030 +out_unpin:
14031 +       au_unpin(p);
14032 +out_err:
14033 +       pr_err("err %d\n", err);
14034 +       err = au_busy_or_stale();
14035 +out:
14036 +       return err;
14037 +}
14038 +
14039 +void au_pin_init(struct au_pin *p, struct dentry *dentry,
14040 +                aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14041 +                unsigned int udba, unsigned char flags)
14042 +{
14043 +       p->dentry = dentry;
14044 +       p->udba = udba;
14045 +       p->lsc_di = lsc_di;
14046 +       p->lsc_hi = lsc_hi;
14047 +       p->flags = flags;
14048 +       p->bindex = bindex;
14049 +
14050 +       p->parent = NULL;
14051 +       p->hdir = NULL;
14052 +       p->h_mnt = NULL;
14053 +}
14054 +
14055 +int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14056 +          unsigned int udba, unsigned char flags)
14057 +{
14058 +       au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
14059 +                   udba, flags);
14060 +       return au_do_pin(pin);
14061 +}
14062 +
14063 +/* ---------------------------------------------------------------------- */
14064 +
14065 +/*
14066 + * ->setattr() and ->getattr() are called in various cases.
14067 + * chmod, stat: dentry is revalidated.
14068 + * fchmod, fstat: file and dentry are not revalidated, additionally they may be
14069 + *               unhashed.
14070 + * for ->setattr(), ia->ia_file is passed from ftruncate only.
14071 + */
14072 +static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
14073 +{
14074 +       int err;
14075 +       struct inode *inode;
14076 +       struct dentry *parent;
14077 +
14078 +       err = 0;
14079 +       inode = dentry->d_inode;
14080 +       if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
14081 +               parent = dget_parent(dentry);
14082 +               di_read_lock_parent(parent, AuLock_IR);
14083 +               /* returns a number of positive dentries */
14084 +               err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
14085 +               if (err >= 0)
14086 +                       err = au_refresh_hinode(inode, dentry);
14087 +               di_read_unlock(parent, AuLock_IR);
14088 +               dput(parent);
14089 +       }
14090 +
14091 +       AuTraceErr(err);
14092 +       return err;
14093 +}
14094 +
14095 +#define AuIcpup_DID_CPUP       1
14096 +#define au_ftest_icpup(flags, name)    ((flags) & AuIcpup_##name)
14097 +#define au_fset_icpup(flags, name)     { (flags) |= AuIcpup_##name; }
14098 +#define au_fclr_icpup(flags, name)     { (flags) &= ~AuIcpup_##name; }
14099 +
14100 +struct au_icpup_args {
14101 +       unsigned char flags;
14102 +       unsigned char pin_flags;
14103 +       aufs_bindex_t btgt;
14104 +       unsigned int udba;
14105 +       struct au_pin pin;
14106 +       struct path h_path;
14107 +       struct inode *h_inode;
14108 +};
14109 +
14110 +static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
14111 +                           struct au_icpup_args *a)
14112 +{
14113 +       int err;
14114 +       loff_t sz;
14115 +       aufs_bindex_t bstart;
14116 +       struct dentry *hi_wh, *parent;
14117 +       struct inode *inode;
14118 +       struct file *h_file;
14119 +       struct au_wr_dir_args wr_dir_args = {
14120 +               .force_btgt     = -1,
14121 +               .flags          = 0
14122 +       };
14123 +
14124 +       bstart = au_dbstart(dentry);
14125 +       inode = dentry->d_inode;
14126 +       if (S_ISDIR(inode->i_mode))
14127 +               au_fset_wrdir(wr_dir_args.flags, ISDIR);
14128 +       /* plink or hi_wh() case */
14129 +       if (bstart != au_ibstart(inode))
14130 +               wr_dir_args.force_btgt = au_ibstart(inode);
14131 +       err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
14132 +       if (unlikely(err < 0))
14133 +               goto out;
14134 +       a->btgt = err;
14135 +       if (err != bstart)
14136 +               au_fset_icpup(a->flags, DID_CPUP);
14137 +
14138 +       err = 0;
14139 +       a->pin_flags = AuPin_MNT_WRITE;
14140 +       parent = NULL;
14141 +       if (!IS_ROOT(dentry)) {
14142 +               au_fset_pin(a->pin_flags, DI_LOCKED);
14143 +               parent = dget_parent(dentry);
14144 +               di_write_lock_parent(parent);
14145 +       }
14146 +
14147 +       err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
14148 +       if (unlikely(err))
14149 +               goto out_parent;
14150 +
14151 +       a->h_path.dentry = au_h_dptr(dentry, bstart);
14152 +       a->h_inode = a->h_path.dentry->d_inode;
14153 +       mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14154 +       sz = -1;
14155 +       if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
14156 +               sz = ia->ia_size;
14157 +
14158 +       h_file = NULL;
14159 +       hi_wh = NULL;
14160 +       if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
14161 +               hi_wh = au_hi_wh(inode, a->btgt);
14162 +               if (!hi_wh) {
14163 +                       err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
14164 +                       if (unlikely(err))
14165 +                               goto out_unlock;
14166 +                       hi_wh = au_hi_wh(inode, a->btgt);
14167 +                       /* todo: revalidate hi_wh? */
14168 +               }
14169 +       }
14170 +
14171 +       if (parent) {
14172 +               au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14173 +               di_downgrade_lock(parent, AuLock_IR);
14174 +               dput(parent);
14175 +               parent = NULL;
14176 +       }
14177 +       if (!au_ftest_icpup(a->flags, DID_CPUP))
14178 +               goto out; /* success */
14179 +
14180 +       if (!d_unhashed(dentry)) {
14181 +               h_file = au_h_open_pre(dentry, bstart);
14182 +               if (IS_ERR(h_file)) {
14183 +                       err = PTR_ERR(h_file);
14184 +                       h_file = NULL;
14185 +               } else
14186 +                       err = au_sio_cpup_simple(dentry, a->btgt, sz,
14187 +                                                AuCpup_DTIME);
14188 +               if (!err)
14189 +                       a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14190 +       } else if (!hi_wh)
14191 +               a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14192 +       else
14193 +               a->h_path.dentry = hi_wh; /* do not dget here */
14194 +
14195 +out_unlock:
14196 +       mutex_unlock(&a->h_inode->i_mutex);
14197 +       au_h_open_post(dentry, bstart, h_file);
14198 +       a->h_inode = a->h_path.dentry->d_inode;
14199 +       if (!err) {
14200 +               mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14201 +               goto out; /* success */
14202 +       }
14203 +
14204 +       au_unpin(&a->pin);
14205 +out_parent:
14206 +       if (parent) {
14207 +               di_write_unlock(parent);
14208 +               dput(parent);
14209 +       }
14210 +out:
14211 +       return err;
14212 +}
14213 +
14214 +static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
14215 +{
14216 +       int err;
14217 +       struct inode *inode;
14218 +       struct super_block *sb;
14219 +       struct file *file;
14220 +       struct au_icpup_args *a;
14221 +
14222 +       inode = dentry->d_inode;
14223 +       IMustLock(inode);
14224 +
14225 +       err = -ENOMEM;
14226 +       a = kzalloc(sizeof(*a), GFP_NOFS);
14227 +       if (unlikely(!a))
14228 +               goto out;
14229 +
14230 +       if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
14231 +               ia->ia_valid &= ~ATTR_MODE;
14232 +
14233 +       file = NULL;
14234 +       sb = dentry->d_sb;
14235 +       si_read_lock(sb, AuLock_FLUSH);
14236 +       if (ia->ia_valid & ATTR_FILE) {
14237 +               /* currently ftruncate(2) only */
14238 +               AuDebugOn(!S_ISREG(inode->i_mode));
14239 +               file = ia->ia_file;
14240 +               err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
14241 +               if (unlikely(err))
14242 +                       goto out_si;
14243 +               ia->ia_file = au_hf_top(file);
14244 +               a->udba = AuOpt_UDBA_NONE;
14245 +       } else {
14246 +               /* fchmod() doesn't pass ia_file */
14247 +               a->udba = au_opt_udba(sb);
14248 +               if (d_unhashed(dentry))
14249 +                       a->udba = AuOpt_UDBA_NONE;
14250 +               di_write_lock_child(dentry);
14251 +               if (a->udba != AuOpt_UDBA_NONE) {
14252 +                       AuDebugOn(IS_ROOT(dentry));
14253 +                       err = au_reval_for_attr(dentry, au_sigen(sb));
14254 +                       if (unlikely(err))
14255 +                               goto out_dentry;
14256 +               }
14257 +       }
14258 +
14259 +       err = au_pin_and_icpup(dentry, ia, a);
14260 +       if (unlikely(err < 0))
14261 +               goto out_dentry;
14262 +       if (au_ftest_icpup(a->flags, DID_CPUP)) {
14263 +               ia->ia_file = NULL;
14264 +               ia->ia_valid &= ~ATTR_FILE;
14265 +       }
14266 +
14267 +       a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
14268 +       if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
14269 +           == (ATTR_MODE | ATTR_CTIME)) {
14270 +               err = security_path_chmod(a->h_path.dentry, a->h_path.mnt,
14271 +                                         ia->ia_mode);
14272 +               if (unlikely(err))
14273 +                       goto out_unlock;
14274 +       } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
14275 +                  && (ia->ia_valid & ATTR_CTIME)) {
14276 +               err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
14277 +               if (unlikely(err))
14278 +                       goto out_unlock;
14279 +       }
14280 +
14281 +       if (ia->ia_valid & ATTR_SIZE) {
14282 +               struct file *f;
14283 +
14284 +               if (ia->ia_size < i_size_read(inode))
14285 +                       /* unmap only */
14286 +                       truncate_setsize(inode, ia->ia_size);
14287 +
14288 +               f = NULL;
14289 +               if (ia->ia_valid & ATTR_FILE)
14290 +                       f = ia->ia_file;
14291 +               mutex_unlock(&a->h_inode->i_mutex);
14292 +               err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
14293 +               mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14294 +       } else
14295 +               err = vfsub_notify_change(&a->h_path, ia);
14296 +       if (!err)
14297 +               au_cpup_attr_changeable(inode);
14298 +
14299 +out_unlock:
14300 +       mutex_unlock(&a->h_inode->i_mutex);
14301 +       au_unpin(&a->pin);
14302 +out_dentry:
14303 +       di_write_unlock(dentry);
14304 +       if (file) {
14305 +               fi_write_unlock(file);
14306 +               ia->ia_file = file;
14307 +               ia->ia_valid |= ATTR_FILE;
14308 +       }
14309 +out_si:
14310 +       si_read_unlock(sb);
14311 +       kfree(a);
14312 +out:
14313 +       AuTraceErr(err);
14314 +       return err;
14315 +}
14316 +
14317 +static void au_refresh_iattr(struct inode *inode, struct kstat *st,
14318 +                            unsigned int nlink)
14319 +{
14320 +       inode->i_mode = st->mode;
14321 +       inode->i_uid = st->uid;
14322 +       inode->i_gid = st->gid;
14323 +       inode->i_atime = st->atime;
14324 +       inode->i_mtime = st->mtime;
14325 +       inode->i_ctime = st->ctime;
14326 +
14327 +       au_cpup_attr_nlink(inode, /*force*/0);
14328 +       if (S_ISDIR(inode->i_mode)) {
14329 +               inode->i_nlink -= nlink;
14330 +               inode->i_nlink += st->nlink;
14331 +       }
14332 +
14333 +       spin_lock(&inode->i_lock);
14334 +       inode->i_blocks = st->blocks;
14335 +       i_size_write(inode, st->size);
14336 +       spin_unlock(&inode->i_lock);
14337 +}
14338 +
14339 +static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
14340 +                       struct dentry *dentry, struct kstat *st)
14341 +{
14342 +       int err;
14343 +       unsigned int mnt_flags;
14344 +       aufs_bindex_t bindex;
14345 +       unsigned char udba_none, positive;
14346 +       struct super_block *sb, *h_sb;
14347 +       struct inode *inode;
14348 +       struct vfsmount *h_mnt;
14349 +       struct dentry *h_dentry;
14350 +
14351 +       err = 0;
14352 +       sb = dentry->d_sb;
14353 +       inode = dentry->d_inode;
14354 +       si_read_lock(sb, AuLock_FLUSH);
14355 +       mnt_flags = au_mntflags(sb);
14356 +       udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
14357 +
14358 +       /* support fstat(2) */
14359 +       if (!d_unhashed(dentry) && !udba_none) {
14360 +               unsigned int sigen = au_sigen(sb);
14361 +               if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
14362 +                       di_read_lock_child(dentry, AuLock_IR);
14363 +               else {
14364 +                       AuDebugOn(IS_ROOT(dentry));
14365 +                       di_write_lock_child(dentry);
14366 +                       err = au_reval_for_attr(dentry, sigen);
14367 +                       di_downgrade_lock(dentry, AuLock_IR);
14368 +                       if (unlikely(err))
14369 +                               goto out;
14370 +               }
14371 +       } else
14372 +               di_read_lock_child(dentry, AuLock_IR);
14373 +
14374 +       bindex = au_ibstart(inode);
14375 +       h_mnt = au_sbr_mnt(sb, bindex);
14376 +       h_sb = h_mnt->mnt_sb;
14377 +       if (!au_test_fs_bad_iattr(h_sb) && udba_none)
14378 +               goto out_fill; /* success */
14379 +
14380 +       h_dentry = NULL;
14381 +       if (au_dbstart(dentry) == bindex)
14382 +               h_dentry = dget(au_h_dptr(dentry, bindex));
14383 +       else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
14384 +               h_dentry = au_plink_lkup(inode, bindex);
14385 +               if (IS_ERR(h_dentry))
14386 +                       goto out_fill; /* pretending success */
14387 +       }
14388 +       /* illegally overlapped or something */
14389 +       if (unlikely(!h_dentry))
14390 +               goto out_fill; /* pretending success */
14391 +
14392 +       positive = !!h_dentry->d_inode;
14393 +       if (positive)
14394 +               err = vfs_getattr(h_mnt, h_dentry, st);
14395 +       dput(h_dentry);
14396 +       if (!err) {
14397 +               if (positive)
14398 +                       au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
14399 +               goto out_fill; /* success */
14400 +       }
14401 +       goto out;
14402 +
14403 +out_fill:
14404 +       generic_fillattr(inode, st);
14405 +out:
14406 +       di_read_unlock(dentry, AuLock_IR);
14407 +       si_read_unlock(sb);
14408 +       return err;
14409 +}
14410 +
14411 +/* ---------------------------------------------------------------------- */
14412 +
14413 +static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
14414 +                     int bufsiz)
14415 +{
14416 +       int err;
14417 +       struct super_block *sb;
14418 +       struct dentry *h_dentry;
14419 +
14420 +       err = -EINVAL;
14421 +       h_dentry = au_h_dptr(dentry, bindex);
14422 +       if (unlikely(!h_dentry->d_inode->i_op->readlink))
14423 +               goto out;
14424 +
14425 +       err = security_inode_readlink(h_dentry);
14426 +       if (unlikely(err))
14427 +               goto out;
14428 +
14429 +       sb = dentry->d_sb;
14430 +       if (!au_test_ro(sb, bindex, dentry->d_inode)) {
14431 +               vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
14432 +               fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
14433 +       }
14434 +       err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
14435 +
14436 +out:
14437 +       return err;
14438 +}
14439 +
14440 +static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
14441 +{
14442 +       int err;
14443 +
14444 +       aufs_read_lock(dentry, AuLock_IR);
14445 +       err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
14446 +       aufs_read_unlock(dentry, AuLock_IR);
14447 +
14448 +       return err;
14449 +}
14450 +
14451 +static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
14452 +{
14453 +       int err;
14454 +       mm_segment_t old_fs;
14455 +       union {
14456 +               char *k;
14457 +               char __user *u;
14458 +       } buf;
14459 +
14460 +       err = -ENOMEM;
14461 +       buf.k = __getname_gfp(GFP_NOFS);
14462 +       if (unlikely(!buf.k))
14463 +               goto out;
14464 +
14465 +       aufs_read_lock(dentry, AuLock_IR);
14466 +       old_fs = get_fs();
14467 +       set_fs(KERNEL_DS);
14468 +       err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
14469 +       set_fs(old_fs);
14470 +       aufs_read_unlock(dentry, AuLock_IR);
14471 +
14472 +       if (err >= 0) {
14473 +               buf.k[err] = 0;
14474 +               /* will be freed by put_link */
14475 +               nd_set_link(nd, buf.k);
14476 +               return NULL; /* success */
14477 +       }
14478 +       __putname(buf.k);
14479 +
14480 +out:
14481 +       path_put(&nd->path);
14482 +       AuTraceErr(err);
14483 +       return ERR_PTR(err);
14484 +}
14485 +
14486 +static void aufs_put_link(struct dentry *dentry __maybe_unused,
14487 +                         struct nameidata *nd, void *cookie __maybe_unused)
14488 +{
14489 +       __putname(nd_get_link(nd));
14490 +}
14491 +
14492 +/* ---------------------------------------------------------------------- */
14493 +
14494 +static void aufs_truncate_range(struct inode *inode __maybe_unused,
14495 +                               loff_t start __maybe_unused,
14496 +                               loff_t end __maybe_unused)
14497 +{
14498 +       AuUnsupport();
14499 +}
14500 +
14501 +/* ---------------------------------------------------------------------- */
14502 +
14503 +struct inode_operations aufs_symlink_iop = {
14504 +       .permission     = aufs_permission,
14505 +       .setattr        = aufs_setattr,
14506 +       .getattr        = aufs_getattr,
14507 +       .readlink       = aufs_readlink,
14508 +       .follow_link    = aufs_follow_link,
14509 +       .put_link       = aufs_put_link
14510 +};
14511 +
14512 +struct inode_operations aufs_dir_iop = {
14513 +       .create         = aufs_create,
14514 +       .lookup         = aufs_lookup,
14515 +       .link           = aufs_link,
14516 +       .unlink         = aufs_unlink,
14517 +       .symlink        = aufs_symlink,
14518 +       .mkdir          = aufs_mkdir,
14519 +       .rmdir          = aufs_rmdir,
14520 +       .mknod          = aufs_mknod,
14521 +       .rename         = aufs_rename,
14522 +
14523 +       .permission     = aufs_permission,
14524 +       .setattr        = aufs_setattr,
14525 +       .getattr        = aufs_getattr
14526 +};
14527 +
14528 +struct inode_operations aufs_iop = {
14529 +       .permission     = aufs_permission,
14530 +       .setattr        = aufs_setattr,
14531 +       .getattr        = aufs_getattr,
14532 +       .truncate_range = aufs_truncate_range
14533 +};
14534 diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
14535 --- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
14536 +++ linux/fs/aufs/i_op_del.c    2010-10-21 09:52:43.090291764 +0200
14537 @@ -0,0 +1,472 @@
14538 +/*
14539 + * Copyright (C) 2005-2010 Junjiro R. Okajima
14540 + *
14541 + * This program, aufs is free software; you can redistribute it and/or modify
14542 + * it under the terms of the GNU General Public License as published by
14543 + * the Free Software Foundation; either version 2 of the License, or
14544 + * (at your option) any later version.
14545 + *
14546 + * This program is distributed in the hope that it will be useful,
14547 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14548 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14549 + * GNU General Public License for more details.
14550 + *
14551 + * You should have received a copy of the GNU General Public License
14552 + * along with this program; if not, write to the Free Software
14553 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
14554 + */
14555 +
14556 +/*
14557 + * inode operations (del entry)
14558 + */
14559 +
14560 +#include "aufs.h"
14561 +
14562 +/*
14563 + * decide if a new whiteout for @dentry is necessary or not.
14564 + * when it is necessary, prepare the parent dir for the upper branch whose
14565 + * branch index is @bcpup for creation. the actual creation of the whiteout will
14566 + * be done by caller.
14567 + * return value:
14568 + * 0: wh is unnecessary
14569 + * plus: wh is necessary
14570 + * minus: error
14571 + */
14572 +int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
14573 +{
14574 +       int need_wh, err;
14575 +       aufs_bindex_t bstart;
14576 +       struct super_block *sb;
14577 +
14578 +       sb = dentry->d_sb;
14579 +       bstart = au_dbstart(dentry);
14580 +       if (*bcpup < 0) {
14581 +               *bcpup = bstart;
14582 +               if (au_test_ro(sb, bstart, dentry->d_inode)) {
14583 +                       err = AuWbrCopyup(au_sbi(sb), dentry);
14584 +                       *bcpup = err;
14585 +                       if (unlikely(err < 0))
14586 +                               goto out;
14587 +               }
14588 +       } else
14589 +               AuDebugOn(bstart < *bcpup
14590 +                         || au_test_ro(sb, *bcpup, dentry->d_inode));
14591 +       AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
14592 +
14593 +       if (*bcpup != bstart) {
14594 +               err = au_cpup_dirs(dentry, *bcpup);
14595 +               if (unlikely(err))
14596 +                       goto out;
14597 +               need_wh = 1;
14598 +       } else {
14599 +               aufs_bindex_t old_bend, new_bend, bdiropq = -1;
14600 +
14601 +               old_bend = au_dbend(dentry);
14602 +               if (isdir) {
14603 +                       bdiropq = au_dbdiropq(dentry);
14604 +                       au_set_dbdiropq(dentry, -1);
14605 +               }
14606 +               need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
14607 +                                        /*nd*/NULL);
14608 +               err = need_wh;
14609 +               if (isdir)
14610 +                       au_set_dbdiropq(dentry, bdiropq);
14611 +               if (unlikely(err < 0))
14612 +                       goto out;
14613 +               new_bend = au_dbend(dentry);
14614 +               if (!need_wh && old_bend != new_bend) {
14615 +                       au_set_h_dptr(dentry, new_bend, NULL);
14616 +                       au_set_dbend(dentry, old_bend);
14617 +               }
14618 +       }
14619 +       AuDbg("need_wh %d\n", need_wh);
14620 +       err = need_wh;
14621 +
14622 +out:
14623 +       return err;
14624 +}
14625 +
14626 +/*
14627 + * simple tests for the del-entry operations.
14628 + * following the checks in vfs, plus the parent-child relationship.
14629 + */
14630 +int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14631 +              struct dentry *h_parent, int isdir)
14632 +{
14633 +       int err;
14634 +       umode_t h_mode;
14635 +       struct dentry *h_dentry, *h_latest;
14636 +       struct inode *h_inode;
14637 +
14638 +       h_dentry = au_h_dptr(dentry, bindex);
14639 +       h_inode = h_dentry->d_inode;
14640 +       if (dentry->d_inode) {
14641 +               err = -ENOENT;
14642 +               if (unlikely(!h_inode || !h_inode->i_nlink))
14643 +                       goto out;
14644 +
14645 +               h_mode = h_inode->i_mode;
14646 +               if (!isdir) {
14647 +                       err = -EISDIR;
14648 +                       if (unlikely(S_ISDIR(h_mode)))
14649 +                               goto out;
14650 +               } else if (unlikely(!S_ISDIR(h_mode))) {
14651 +                       err = -ENOTDIR;
14652 +                       goto out;
14653 +               }
14654 +       } else {
14655 +               /* rename(2) case */
14656 +               err = -EIO;
14657 +               if (unlikely(h_inode))
14658 +                       goto out;
14659 +       }
14660 +
14661 +       err = -ENOENT;
14662 +       /* expected parent dir is locked */
14663 +       if (unlikely(h_parent != h_dentry->d_parent))
14664 +               goto out;
14665 +       err = 0;
14666 +
14667 +       /*
14668 +        * rmdir a dir may break the consistency on some filesystem.
14669 +        * let's try heavy test.
14670 +        */
14671 +       err = -EACCES;
14672 +       if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
14673 +               goto out;
14674 +
14675 +       h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
14676 +                                  au_sbr(dentry->d_sb, bindex));
14677 +       err = -EIO;
14678 +       if (IS_ERR(h_latest))
14679 +               goto out;
14680 +       if (h_latest == h_dentry)
14681 +               err = 0;
14682 +       dput(h_latest);
14683 +
14684 +out:
14685 +       return err;
14686 +}
14687 +
14688 +/*
14689 + * decide the branch where we operate for @dentry. the branch index will be set
14690 + * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
14691 + * dir for reverting.
14692 + * when a new whiteout is necessary, create it.
14693 + */
14694 +static struct dentry*
14695 +lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
14696 +                   struct au_dtime *dt, struct au_pin *pin)
14697 +{
14698 +       struct dentry *wh_dentry;
14699 +       struct super_block *sb;
14700 +       struct path h_path;
14701 +       int err, need_wh;
14702 +       unsigned int udba;
14703 +       aufs_bindex_t bcpup;
14704 +
14705 +       need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
14706 +       wh_dentry = ERR_PTR(need_wh);
14707 +       if (unlikely(need_wh < 0))
14708 +               goto out;
14709 +
14710 +       sb = dentry->d_sb;
14711 +       udba = au_opt_udba(sb);
14712 +       bcpup = *rbcpup;
14713 +       err = au_pin(pin, dentry, bcpup, udba,
14714 +                    AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14715 +       wh_dentry = ERR_PTR(err);
14716 +       if (unlikely(err))
14717 +               goto out;
14718 +
14719 +       h_path.dentry = au_pinned_h_parent(pin);
14720 +       if (udba != AuOpt_UDBA_NONE
14721 +           && au_dbstart(dentry) == bcpup) {
14722 +               err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
14723 +               wh_dentry = ERR_PTR(err);
14724 +               if (unlikely(err))
14725 +                       goto out_unpin;
14726 +       }
14727 +
14728 +       h_path.mnt = au_sbr_mnt(sb, bcpup);
14729 +       au_dtime_store(dt, au_pinned_parent(pin), &h_path);
14730 +       wh_dentry = NULL;
14731 +       if (!need_wh)
14732 +               goto out; /* success, no need to create whiteout */
14733 +
14734 +       wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
14735 +       if (IS_ERR(wh_dentry))
14736 +               goto out_unpin;
14737 +
14738 +       /* returns with the parent is locked and wh_dentry is dget-ed */
14739 +       goto out; /* success */
14740 +
14741 +out_unpin:
14742 +       au_unpin(pin);
14743 +out:
14744 +       return wh_dentry;
14745 +}
14746 +
14747 +/*
14748 + * when removing a dir, rename it to a unique temporary whiteout-ed name first
14749 + * in order to be revertible and save time for removing many child whiteouts
14750 + * under the dir.
14751 + * returns 1 when there are too many child whiteout and caller should remove
14752 + * them asynchronously. returns 0 when the number of children is enough small to
14753 + * remove now or the branch fs is a remote fs.
14754 + * otherwise return an error.
14755 + */
14756 +static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
14757 +                          struct au_nhash *whlist, struct inode *dir)
14758 +{
14759 +       int rmdir_later, err, dirwh;
14760 +       struct dentry *h_dentry;
14761 +       struct super_block *sb;
14762 +
14763 +       sb = dentry->d_sb;
14764 +       SiMustAnyLock(sb);
14765 +       h_dentry = au_h_dptr(dentry, bindex);
14766 +       err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
14767 +       if (unlikely(err))
14768 +               goto out;
14769 +
14770 +       /* stop monitoring */
14771 +       au_hn_free(au_hi(dentry->d_inode, bindex));
14772 +
14773 +       if (!au_test_fs_remote(h_dentry->d_sb)) {
14774 +               dirwh = au_sbi(sb)->si_dirwh;
14775 +               rmdir_later = (dirwh <= 1);
14776 +               if (!rmdir_later)
14777 +                       rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
14778 +                                                             dirwh);
14779 +               if (rmdir_later)
14780 +                       return rmdir_later;
14781 +       }
14782 +
14783 +       err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
14784 +       if (unlikely(err)) {
14785 +               AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
14786 +                       AuDLNPair(h_dentry), bindex, err);
14787 +               err = 0;
14788 +       }
14789 +
14790 +out:
14791 +       AuTraceErr(err);
14792 +       return err;
14793 +}
14794 +
14795 +/*
14796 + * final procedure for deleting a entry.
14797 + * maintain dentry and iattr.
14798 + */
14799 +static void epilog(struct inode *dir, struct dentry *dentry,
14800 +                  aufs_bindex_t bindex)
14801 +{
14802 +       struct inode *inode;
14803 +
14804 +       inode = dentry->d_inode;
14805 +       d_drop(dentry);
14806 +       inode->i_ctime = dir->i_ctime;
14807 +
14808 +       if (atomic_read(&dentry->d_count) == 1) {
14809 +               au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
14810 +               au_update_dbstart(dentry);
14811 +       }
14812 +       if (au_ibstart(dir) == bindex)
14813 +               au_cpup_attr_timesizes(dir);
14814 +       dir->i_version++;
14815 +}
14816 +
14817 +/*
14818 + * when an error happened, remove the created whiteout and revert everything.
14819 + */
14820 +static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
14821 +                    struct dentry *wh_dentry, struct dentry *dentry,
14822 +                    struct au_dtime *dt)
14823 +{
14824 +       int rerr;
14825 +       struct path h_path = {
14826 +               .dentry = wh_dentry,
14827 +               .mnt    = au_sbr_mnt(dir->i_sb, bwh)
14828 +       };
14829 +
14830 +       rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
14831 +       if (!rerr) {
14832 +               au_set_dbwh(dentry, bwh);
14833 +               au_dtime_revert(dt);
14834 +               return 0;
14835 +       }
14836 +
14837 +       AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
14838 +               AuDLNPair(dentry), err, rerr);
14839 +       return -EIO;
14840 +}
14841 +
14842 +/* ---------------------------------------------------------------------- */
14843 +
14844 +int aufs_unlink(struct inode *dir, struct dentry *dentry)
14845 +{
14846 +       int err;
14847 +       aufs_bindex_t bwh, bindex, bstart;
14848 +       struct au_dtime dt;
14849 +       struct au_pin pin;
14850 +       struct path h_path;
14851 +       struct inode *inode, *h_dir;
14852 +       struct dentry *parent, *wh_dentry;
14853 +
14854 +       IMustLock(dir);
14855 +       inode = dentry->d_inode;
14856 +       if (unlikely(!inode))
14857 +               return -ENOENT; /* possible? */
14858 +       IMustLock(inode);
14859 +
14860 +       aufs_read_lock(dentry, AuLock_DW);
14861 +       parent = dentry->d_parent; /* dir inode is locked */
14862 +       di_write_lock_parent(parent);
14863 +
14864 +       bstart = au_dbstart(dentry);
14865 +       bwh = au_dbwh(dentry);
14866 +       bindex = -1;
14867 +       wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
14868 +       err = PTR_ERR(wh_dentry);
14869 +       if (IS_ERR(wh_dentry))
14870 +               goto out;
14871 +
14872 +       h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
14873 +       h_path.dentry = au_h_dptr(dentry, bstart);
14874 +       dget(h_path.dentry);
14875 +       if (bindex == bstart) {
14876 +               h_dir = au_pinned_h_dir(&pin);
14877 +               err = vfsub_unlink(h_dir, &h_path, /*force*/0);
14878 +       } else {
14879 +               /* dir inode is locked */
14880 +               h_dir = wh_dentry->d_parent->d_inode;
14881 +               IMustLock(h_dir);
14882 +               err = 0;
14883 +       }
14884 +
14885 +       if (!err) {
14886 +               drop_nlink(inode);
14887 +               epilog(dir, dentry, bindex);
14888 +
14889 +               /* update target timestamps */
14890 +               if (bindex == bstart) {
14891 +                       vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
14892 +                       inode->i_ctime = h_path.dentry->d_inode->i_ctime;
14893 +               } else
14894 +                       /* todo: this timestamp may be reverted later */
14895 +                       inode->i_ctime = h_dir->i_ctime;
14896 +               goto out_unlock; /* success */
14897 +       }
14898 +
14899 +       /* revert */
14900 +       if (wh_dentry) {
14901 +               int rerr;
14902 +
14903 +               rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
14904 +               if (rerr)
14905 +                       err = rerr;
14906 +       }
14907 +
14908 +out_unlock:
14909 +       au_unpin(&pin);
14910 +       dput(wh_dentry);
14911 +       dput(h_path.dentry);
14912 +out:
14913 +       di_write_unlock(parent);
14914 +       aufs_read_unlock(dentry, AuLock_DW);
14915 +       return err;
14916 +}
14917 +
14918 +int aufs_rmdir(struct inode *dir, struct dentry *dentry)
14919 +{
14920 +       int err, rmdir_later;
14921 +       aufs_bindex_t bwh, bindex, bstart;
14922 +       struct au_dtime dt;
14923 +       struct au_pin pin;
14924 +       struct inode *inode;
14925 +       struct dentry *parent, *wh_dentry, *h_dentry;
14926 +       struct au_whtmp_rmdir *args;
14927 +
14928 +       IMustLock(dir);
14929 +       inode = dentry->d_inode;
14930 +       err = -ENOENT; /* possible? */
14931 +       if (unlikely(!inode))
14932 +               goto out;
14933 +       IMustLock(inode);
14934 +
14935 +       aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
14936 +       err = -ENOMEM;
14937 +       args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
14938 +       if (unlikely(!args))
14939 +               goto out_unlock;
14940 +
14941 +       parent = dentry->d_parent; /* dir inode is locked */
14942 +       di_write_lock_parent(parent);
14943 +       err = au_test_empty(dentry, &args->whlist);
14944 +       if (unlikely(err))
14945 +               goto out_args;
14946 +
14947 +       bstart = au_dbstart(dentry);
14948 +       bwh = au_dbwh(dentry);
14949 +       bindex = -1;
14950 +       wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
14951 +       err = PTR_ERR(wh_dentry);
14952 +       if (IS_ERR(wh_dentry))
14953 +               goto out_args;
14954 +
14955 +       h_dentry = au_h_dptr(dentry, bstart);
14956 +       dget(h_dentry);
14957 +       rmdir_later = 0;
14958 +       if (bindex == bstart) {
14959 +               err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
14960 +               if (err > 0) {
14961 +                       rmdir_later = err;
14962 +                       err = 0;
14963 +               }
14964 +       } else {
14965 +               /* stop monitoring */
14966 +               au_hn_free(au_hi(inode, bstart));
14967 +
14968 +               /* dir inode is locked */
14969 +               IMustLock(wh_dentry->d_parent->d_inode);
14970 +               err = 0;
14971 +       }
14972 +
14973 +       if (!err) {
14974 +               clear_nlink(inode);
14975 +               au_set_dbdiropq(dentry, -1);
14976 +               epilog(dir, dentry, bindex);
14977 +
14978 +               if (rmdir_later) {
14979 +                       au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
14980 +                       args = NULL;
14981 +               }
14982 +
14983 +               goto out_unpin; /* success */
14984 +       }
14985 +
14986 +       /* revert */
14987 +       AuLabel(revert);
14988 +       if (wh_dentry) {
14989 +               int rerr;
14990 +
14991 +               rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
14992 +               if (rerr)
14993 +                       err = rerr;
14994 +       }
14995 +
14996 +out_unpin:
14997 +       au_unpin(&pin);
14998 +       dput(wh_dentry);
14999 +       dput(h_dentry);
15000 +out_args:
15001 +       di_write_unlock(parent);
15002 +       if (args)
15003 +               au_whtmp_rmdir_free(args);
15004 +out_unlock:
15005 +       aufs_read_unlock(dentry, AuLock_DW);
15006 +out:
15007 +       AuTraceErr(err);
15008 +       return err;
15009 +}
15010 diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
15011 --- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
15012 +++ linux/fs/aufs/i_op_ren.c    2010-10-21 09:52:43.090291764 +0200
15013 @@ -0,0 +1,977 @@
15014 +/*
15015 + * Copyright (C) 2005-2010 Junjiro R. Okajima
15016 + *
15017 + * This program, aufs is free software; you can redistribute it and/or modify
15018 + * it under the terms of the GNU General Public License as published by
15019 + * the Free Software Foundation; either version 2 of the License, or
15020 + * (at your option) any later version.
15021 + *
15022 + * This program is distributed in the hope that it will be useful,
15023 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15024 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15025 + * GNU General Public License for more details.
15026 + *
15027 + * You should have received a copy of the GNU General Public License
15028 + * along with this program; if not, write to the Free Software
15029 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
15030 + */
15031 +
15032 +/*
15033 + * inode operation (rename entry)
15034 + * todo: this is crazy monster
15035 + */
15036 +
15037 +#include "aufs.h"
15038 +
15039 +enum { AuSRC, AuDST, AuSrcDst };
15040 +enum { AuPARENT, AuCHILD, AuParentChild };
15041 +
15042 +#define AuRen_ISDIR    1
15043 +#define AuRen_ISSAMEDIR        (1 << 1)
15044 +#define AuRen_WHSRC    (1 << 2)
15045 +#define AuRen_WHDST    (1 << 3)
15046 +#define AuRen_MNT_WRITE        (1 << 4)
15047 +#define AuRen_DT_DSTDIR        (1 << 5)
15048 +#define AuRen_DIROPQ   (1 << 6)
15049 +#define AuRen_CPUP     (1 << 7)
15050 +#define au_ftest_ren(flags, name)      ((flags) & AuRen_##name)
15051 +#define au_fset_ren(flags, name)       { (flags) |= AuRen_##name; }
15052 +#define au_fclr_ren(flags, name)       { (flags) &= ~AuRen_##name; }
15053 +
15054 +struct au_ren_args {
15055 +       struct {
15056 +               struct dentry *dentry, *h_dentry, *parent, *h_parent,
15057 +                       *wh_dentry;
15058 +               struct inode *dir, *inode;
15059 +               struct au_hinode *hdir;
15060 +               struct au_dtime dt[AuParentChild];
15061 +               aufs_bindex_t bstart;
15062 +       } sd[AuSrcDst];
15063 +
15064 +#define src_dentry     sd[AuSRC].dentry
15065 +#define src_dir                sd[AuSRC].dir
15066 +#define src_inode      sd[AuSRC].inode
15067 +#define src_h_dentry   sd[AuSRC].h_dentry
15068 +#define src_parent     sd[AuSRC].parent
15069 +#define src_h_parent   sd[AuSRC].h_parent
15070 +#define src_wh_dentry  sd[AuSRC].wh_dentry
15071 +#define src_hdir       sd[AuSRC].hdir
15072 +#define src_h_dir      sd[AuSRC].hdir->hi_inode
15073 +#define src_dt         sd[AuSRC].dt
15074 +#define src_bstart     sd[AuSRC].bstart
15075 +
15076 +#define dst_dentry     sd[AuDST].dentry
15077 +#define dst_dir                sd[AuDST].dir
15078 +#define dst_inode      sd[AuDST].inode
15079 +#define dst_h_dentry   sd[AuDST].h_dentry
15080 +#define dst_parent     sd[AuDST].parent
15081 +#define dst_h_parent   sd[AuDST].h_parent
15082 +#define dst_wh_dentry  sd[AuDST].wh_dentry
15083 +#define dst_hdir       sd[AuDST].hdir
15084 +#define dst_h_dir      sd[AuDST].hdir->hi_inode
15085 +#define dst_dt         sd[AuDST].dt
15086 +#define dst_bstart     sd[AuDST].bstart
15087 +
15088 +       struct dentry *h_trap;
15089 +       struct au_branch *br;
15090 +       struct au_hinode *src_hinode;
15091 +       struct path h_path;
15092 +       struct au_nhash whlist;
15093 +       aufs_bindex_t btgt;
15094 +
15095 +       unsigned int flags;
15096 +
15097 +       struct au_whtmp_rmdir *thargs;
15098 +       struct dentry *h_dst;
15099 +};
15100 +
15101 +/* ---------------------------------------------------------------------- */
15102 +
15103 +/*
15104 + * functions for reverting.
15105 + * when an error happened in a single rename systemcall, we should revert
15106 + * everything as if nothing happend.
15107 + * we don't need to revert the copied-up/down the parent dir since they are
15108 + * harmless.
15109 + */
15110 +
15111 +#define RevertFailure(fmt, ...) do { \
15112 +       AuIOErr("revert failure: " fmt " (%d, %d)\n", \
15113 +               ##__VA_ARGS__, err, rerr); \
15114 +       err = -EIO; \
15115 +} while (0)
15116 +
15117 +static void au_ren_rev_diropq(int err, struct au_ren_args *a)
15118 +{
15119 +       int rerr;
15120 +
15121 +       au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15122 +       rerr = au_diropq_remove(a->src_dentry, a->btgt);
15123 +       au_hn_imtx_unlock(a->src_hinode);
15124 +       if (rerr)
15125 +               RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
15126 +}
15127 +
15128 +static void au_ren_rev_rename(int err, struct au_ren_args *a)
15129 +{
15130 +       int rerr;
15131 +
15132 +       a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
15133 +                                      a->br, /*nd*/NULL);
15134 +       rerr = PTR_ERR(a->h_path.dentry);
15135 +       if (IS_ERR(a->h_path.dentry)) {
15136 +               RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
15137 +               return;
15138 +       }
15139 +
15140 +       rerr = vfsub_rename(a->dst_h_dir,
15141 +                           au_h_dptr(a->src_dentry, a->btgt),
15142 +                           a->src_h_dir, &a->h_path);
15143 +       d_drop(a->h_path.dentry);
15144 +       dput(a->h_path.dentry);
15145 +       /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
15146 +       if (rerr)
15147 +               RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
15148 +}
15149 +
15150 +static void au_ren_rev_cpup(int err, struct au_ren_args *a)
15151 +{
15152 +       int rerr;
15153 +
15154 +       a->h_path.dentry = a->dst_h_dentry;
15155 +       rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
15156 +       au_set_h_dptr(a->src_dentry, a->btgt, NULL);
15157 +       au_set_dbstart(a->src_dentry, a->src_bstart);
15158 +       if (rerr)
15159 +               RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
15160 +}
15161 +
15162 +static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
15163 +{
15164 +       int rerr;
15165 +
15166 +       a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
15167 +                                      a->br, /*nd*/NULL);
15168 +       rerr = PTR_ERR(a->h_path.dentry);
15169 +       if (IS_ERR(a->h_path.dentry)) {
15170 +               RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
15171 +               return;
15172 +       }
15173 +       if (a->h_path.dentry->d_inode) {
15174 +               d_drop(a->h_path.dentry);
15175 +               dput(a->h_path.dentry);
15176 +               return;
15177 +       }
15178 +
15179 +       rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
15180 +       d_drop(a->h_path.dentry);
15181 +       dput(a->h_path.dentry);
15182 +       if (!rerr)
15183 +               au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
15184 +       else
15185 +               RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
15186 +}
15187 +
15188 +static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
15189 +{
15190 +       int rerr;
15191 +
15192 +       a->h_path.dentry = a->src_wh_dentry;
15193 +       rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
15194 +       if (rerr)
15195 +               RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
15196 +}
15197 +
15198 +static void au_ren_rev_drop(struct au_ren_args *a)
15199 +{
15200 +       struct dentry *d, *h_d;
15201 +       int i;
15202 +       aufs_bindex_t bend, bindex;
15203 +
15204 +       for (i = 0; i < AuSrcDst; i++) {
15205 +               d = a->sd[i].dentry;
15206 +               d_drop(d);
15207 +               bend = au_dbend(d);
15208 +               for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
15209 +                       h_d = au_h_dptr(d, bindex);
15210 +                       if (h_d)
15211 +                               d_drop(h_d);
15212 +               }
15213 +       }
15214 +
15215 +       au_update_dbstart(a->dst_dentry);
15216 +       if (a->thargs)
15217 +               d_drop(a->h_dst);
15218 +}
15219 +#undef RevertFailure
15220 +
15221 +/* ---------------------------------------------------------------------- */
15222 +
15223 +/*
15224 + * when we have to copyup the renaming entry, do it with the rename-target name
15225 + * in order to minimize the cost (the later actual rename is unnecessary).
15226 + * otherwise rename it on the target branch.
15227 + */
15228 +static int au_ren_or_cpup(struct au_ren_args *a)
15229 +{
15230 +       int err;
15231 +       struct dentry *d;
15232 +
15233 +       d = a->src_dentry;
15234 +       if (au_dbstart(d) == a->btgt) {
15235 +               a->h_path.dentry = a->dst_h_dentry;
15236 +               if (au_ftest_ren(a->flags, DIROPQ)
15237 +                   && au_dbdiropq(d) == a->btgt)
15238 +                       au_fclr_ren(a->flags, DIROPQ);
15239 +               AuDebugOn(au_dbstart(d) != a->btgt);
15240 +               err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
15241 +                                  a->dst_h_dir, &a->h_path);
15242 +       } else {
15243 +               struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15244 +               struct file *h_file;
15245 +
15246 +               au_fset_ren(a->flags, CPUP);
15247 +               mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15248 +               au_set_dbstart(d, a->btgt);
15249 +               au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
15250 +               h_file = au_h_open_pre(d, a->src_bstart);
15251 +               if (IS_ERR(h_file)) {
15252 +                       err = PTR_ERR(h_file);
15253 +                       h_file = NULL;
15254 +               } else
15255 +                       err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
15256 +                                                !AuCpup_DTIME, a->dst_parent);
15257 +               mutex_unlock(h_mtx);
15258 +               au_h_open_post(d, a->src_bstart, h_file);
15259 +               if (!err) {
15260 +                       d = a->dst_dentry;
15261 +                       au_set_h_dptr(d, a->btgt, NULL);
15262 +                       au_update_dbstart(d);
15263 +               } else {
15264 +                       au_set_h_dptr(d, a->btgt, NULL);
15265 +                       au_set_dbstart(d, a->src_bstart);
15266 +               }
15267 +       }
15268 +
15269 +       return err;
15270 +}
15271 +
15272 +/* cf. aufs_rmdir() */
15273 +static int au_ren_del_whtmp(struct au_ren_args *a)
15274 +{
15275 +       int err;
15276 +       struct inode *dir;
15277 +
15278 +       dir = a->dst_dir;
15279 +       SiMustAnyLock(dir->i_sb);
15280 +       if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
15281 +                                    au_sbi(dir->i_sb)->si_dirwh)
15282 +           || au_test_fs_remote(a->h_dst->d_sb)) {
15283 +               err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
15284 +               if (unlikely(err))
15285 +                       pr_warning("failed removing whtmp dir %.*s (%d), "
15286 +                                  "ignored.\n", AuDLNPair(a->h_dst), err);
15287 +       } else {
15288 +               au_nhash_wh_free(&a->thargs->whlist);
15289 +               a->thargs->whlist = a->whlist;
15290 +               a->whlist.nh_num = 0;
15291 +               au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
15292 +               dput(a->h_dst);
15293 +               a->thargs = NULL;
15294 +       }
15295 +
15296 +       return 0;
15297 +}
15298 +
15299 +/* make it 'opaque' dir. */
15300 +static int au_ren_diropq(struct au_ren_args *a)
15301 +{
15302 +       int err;
15303 +       struct dentry *diropq;
15304 +
15305 +       err = 0;
15306 +       a->src_hinode = au_hi(a->src_inode, a->btgt);
15307 +       au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15308 +       diropq = au_diropq_create(a->src_dentry, a->btgt);
15309 +       au_hn_imtx_unlock(a->src_hinode);
15310 +       if (IS_ERR(diropq))
15311 +               err = PTR_ERR(diropq);
15312 +       dput(diropq);
15313 +
15314 +       return err;
15315 +}
15316 +
15317 +static int do_rename(struct au_ren_args *a)
15318 +{
15319 +       int err;
15320 +       struct dentry *d, *h_d;
15321 +
15322 +       /* prepare workqueue args for asynchronous rmdir */
15323 +       h_d = a->dst_h_dentry;
15324 +       if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
15325 +               err = -ENOMEM;
15326 +               a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
15327 +               if (unlikely(!a->thargs))
15328 +                       goto out;
15329 +               a->h_dst = dget(h_d);
15330 +       }
15331 +
15332 +       /* create whiteout for src_dentry */
15333 +       if (au_ftest_ren(a->flags, WHSRC)) {
15334 +               a->src_wh_dentry
15335 +                       = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
15336 +               err = PTR_ERR(a->src_wh_dentry);
15337 +               if (IS_ERR(a->src_wh_dentry))
15338 +                       goto out_thargs;
15339 +       }
15340 +
15341 +       /* lookup whiteout for dentry */
15342 +       if (au_ftest_ren(a->flags, WHDST)) {
15343 +               h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
15344 +                                a->br);
15345 +               err = PTR_ERR(h_d);
15346 +               if (IS_ERR(h_d))
15347 +                       goto out_whsrc;
15348 +               if (!h_d->d_inode)
15349 +                       dput(h_d);
15350 +               else
15351 +                       a->dst_wh_dentry = h_d;
15352 +       }
15353 +
15354 +       /* rename dentry to tmpwh */
15355 +       if (a->thargs) {
15356 +               err = au_whtmp_ren(a->dst_h_dentry, a->br);
15357 +               if (unlikely(err))
15358 +                       goto out_whdst;
15359 +
15360 +               d = a->dst_dentry;
15361 +               au_set_h_dptr(d, a->btgt, NULL);
15362 +               err = au_lkup_neg(d, a->btgt);
15363 +               if (unlikely(err))
15364 +                       goto out_whtmp;
15365 +               a->dst_h_dentry = au_h_dptr(d, a->btgt);
15366 +       }
15367 +
15368 +       /* cpup src */
15369 +       if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
15370 +               struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15371 +               struct file *h_file;
15372 +
15373 +               mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15374 +               AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
15375 +               h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
15376 +               if (IS_ERR(h_file)) {
15377 +                       err = PTR_ERR(h_file);
15378 +                       h_file = NULL;
15379 +               } else
15380 +                       err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
15381 +                                                !AuCpup_DTIME);
15382 +               mutex_unlock(h_mtx);
15383 +               au_h_open_post(a->src_dentry, a->src_bstart, h_file);
15384 +               if (unlikely(err))
15385 +                       goto out_whtmp;
15386 +       }
15387 +
15388 +       /* rename by vfs_rename or cpup */
15389 +       d = a->dst_dentry;
15390 +       if (au_ftest_ren(a->flags, ISDIR)
15391 +           && (a->dst_wh_dentry
15392 +               || au_dbdiropq(d) == a->btgt
15393 +               /* hide the lower to keep xino */
15394 +               || a->btgt < au_dbend(d)
15395 +               || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
15396 +               au_fset_ren(a->flags, DIROPQ);
15397 +       err = au_ren_or_cpup(a);
15398 +       if (unlikely(err))
15399 +               /* leave the copied-up one */
15400 +               goto out_whtmp;
15401 +
15402 +       /* make dir opaque */
15403 +       if (au_ftest_ren(a->flags, DIROPQ)) {
15404 +               err = au_ren_diropq(a);
15405 +               if (unlikely(err))
15406 +                       goto out_rename;
15407 +       }
15408 +
15409 +       /* update target timestamps */
15410 +       AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
15411 +       a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
15412 +       vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
15413 +       a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
15414 +
15415 +       /* remove whiteout for dentry */
15416 +       if (a->dst_wh_dentry) {
15417 +               a->h_path.dentry = a->dst_wh_dentry;
15418 +               err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
15419 +                                         a->dst_dentry);
15420 +               if (unlikely(err))
15421 +                       goto out_diropq;
15422 +       }
15423 +
15424 +       /* remove whtmp */
15425 +       if (a->thargs)
15426 +               au_ren_del_whtmp(a); /* ignore this error */
15427 +
15428 +       err = 0;
15429 +       goto out_success;
15430 +
15431 +out_diropq:
15432 +       if (au_ftest_ren(a->flags, DIROPQ))
15433 +               au_ren_rev_diropq(err, a);
15434 +out_rename:
15435 +       if (!au_ftest_ren(a->flags, CPUP))
15436 +               au_ren_rev_rename(err, a);
15437 +       else
15438 +               au_ren_rev_cpup(err, a);
15439 +out_whtmp:
15440 +       if (a->thargs)
15441 +               au_ren_rev_whtmp(err, a);
15442 +out_whdst:
15443 +       dput(a->dst_wh_dentry);
15444 +       a->dst_wh_dentry = NULL;
15445 +out_whsrc:
15446 +       if (a->src_wh_dentry)
15447 +               au_ren_rev_whsrc(err, a);
15448 +       au_ren_rev_drop(a);
15449 +out_success:
15450 +       dput(a->src_wh_dentry);
15451 +       dput(a->dst_wh_dentry);
15452 +out_thargs:
15453 +       if (a->thargs) {
15454 +               dput(a->h_dst);
15455 +               au_whtmp_rmdir_free(a->thargs);
15456 +               a->thargs = NULL;
15457 +       }
15458 +out:
15459 +       return err;
15460 +}
15461 +
15462 +/* ---------------------------------------------------------------------- */
15463 +
15464 +/*
15465 + * test if @dentry dir can be rename destination or not.
15466 + * success means, it is a logically empty dir.
15467 + */
15468 +static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
15469 +{
15470 +       return au_test_empty(dentry, whlist);
15471 +}
15472 +
15473 +/*
15474 + * test if @dentry dir can be rename source or not.
15475 + * if it can, return 0 and @children is filled.
15476 + * success means,
15477 + * - it is a logically empty dir.
15478 + * - or, it exists on writable branch and has no children including whiteouts
15479 + *       on the lower branch.
15480 + */
15481 +static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
15482 +{
15483 +       int err;
15484 +       unsigned int rdhash;
15485 +       aufs_bindex_t bstart;
15486 +
15487 +       bstart = au_dbstart(dentry);
15488 +       if (bstart != btgt) {
15489 +               struct au_nhash whlist;
15490 +
15491 +               SiMustAnyLock(dentry->d_sb);
15492 +               rdhash = au_sbi(dentry->d_sb)->si_rdhash;
15493 +               if (!rdhash)
15494 +                       rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
15495 +                                                          dentry));
15496 +               err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
15497 +               if (unlikely(err))
15498 +                       goto out;
15499 +               err = au_test_empty(dentry, &whlist);
15500 +               au_nhash_wh_free(&whlist);
15501 +               goto out;
15502 +       }
15503 +
15504 +       if (bstart == au_dbtaildir(dentry))
15505 +               return 0; /* success */
15506 +
15507 +       err = au_test_empty_lower(dentry);
15508 +
15509 +out:
15510 +       if (err == -ENOTEMPTY) {
15511 +               AuWarn1("renaming dir who has child(ren) on multiple branches,"
15512 +                       " is not supported\n");
15513 +               err = -EXDEV;
15514 +       }
15515 +       return err;
15516 +}
15517 +
15518 +/* side effect: sets whlist and h_dentry */
15519 +static int au_ren_may_dir(struct au_ren_args *a)
15520 +{
15521 +       int err;
15522 +       unsigned int rdhash;
15523 +       struct dentry *d;
15524 +
15525 +       d = a->dst_dentry;
15526 +       SiMustAnyLock(d->d_sb);
15527 +
15528 +       err = 0;
15529 +       if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
15530 +               rdhash = au_sbi(d->d_sb)->si_rdhash;
15531 +               if (!rdhash)
15532 +                       rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
15533 +               err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
15534 +               if (unlikely(err))
15535 +                       goto out;
15536 +
15537 +               au_set_dbstart(d, a->dst_bstart);
15538 +               err = may_rename_dstdir(d, &a->whlist);
15539 +               au_set_dbstart(d, a->btgt);
15540 +       }
15541 +       a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
15542 +       if (unlikely(err))
15543 +               goto out;
15544 +
15545 +       d = a->src_dentry;
15546 +       a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
15547 +       if (au_ftest_ren(a->flags, ISDIR)) {
15548 +               err = may_rename_srcdir(d, a->btgt);
15549 +               if (unlikely(err)) {
15550 +                       au_nhash_wh_free(&a->whlist);
15551 +                       a->whlist.nh_num = 0;
15552 +               }
15553 +       }
15554 +out:
15555 +       return err;
15556 +}
15557 +
15558 +/* ---------------------------------------------------------------------- */
15559 +
15560 +/*
15561 + * simple tests for rename.
15562 + * following the checks in vfs, plus the parent-child relationship.
15563 + */
15564 +static int au_may_ren(struct au_ren_args *a)
15565 +{
15566 +       int err, isdir;
15567 +       struct inode *h_inode;
15568 +
15569 +       if (a->src_bstart == a->btgt) {
15570 +               err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
15571 +                                au_ftest_ren(a->flags, ISDIR));
15572 +               if (unlikely(err))
15573 +                       goto out;
15574 +               err = -EINVAL;
15575 +               if (unlikely(a->src_h_dentry == a->h_trap))
15576 +                       goto out;
15577 +       }
15578 +
15579 +       err = 0;
15580 +       if (a->dst_bstart != a->btgt)
15581 +               goto out;
15582 +
15583 +       err = -EIO;
15584 +       h_inode = a->dst_h_dentry->d_inode;
15585 +       isdir = !!au_ftest_ren(a->flags, ISDIR);
15586 +       if (!a->dst_dentry->d_inode) {
15587 +               if (unlikely(h_inode))
15588 +                       goto out;
15589 +               err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
15590 +                                isdir);
15591 +       } else {
15592 +               if (unlikely(!h_inode || !h_inode->i_nlink))
15593 +                       goto out;
15594 +               err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
15595 +                                isdir);
15596 +               if (unlikely(err))
15597 +                       goto out;
15598 +               err = -ENOTEMPTY;
15599 +               if (unlikely(a->dst_h_dentry == a->h_trap))
15600 +                       goto out;
15601 +               err = 0;
15602 +       }
15603 +
15604 +out:
15605 +       if (unlikely(err == -ENOENT || err == -EEXIST))
15606 +               err = -EIO;
15607 +       AuTraceErr(err);
15608 +       return err;
15609 +}
15610 +
15611 +/* ---------------------------------------------------------------------- */
15612 +
15613 +/*
15614 + * locking order
15615 + * (VFS)
15616 + * - src_dir and dir by lock_rename()
15617 + * - inode if exitsts
15618 + * (aufs)
15619 + * - lock all
15620 + *   + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
15621 + *     + si_read_lock
15622 + *     + di_write_lock2_child()
15623 + *       + di_write_lock_child()
15624 + *        + ii_write_lock_child()
15625 + *       + di_write_lock_child2()
15626 + *        + ii_write_lock_child2()
15627 + *     + src_parent and parent
15628 + *       + di_write_lock_parent()
15629 + *        + ii_write_lock_parent()
15630 + *       + di_write_lock_parent2()
15631 + *        + ii_write_lock_parent2()
15632 + *   + lower src_dir and dir by vfsub_lock_rename()
15633 + *   + verify the every relationships between child and parent. if any
15634 + *     of them failed, unlock all and return -EBUSY.
15635 + */
15636 +static void au_ren_unlock(struct au_ren_args *a)
15637 +{
15638 +       struct super_block *sb;
15639 +
15640 +       sb = a->dst_dentry->d_sb;
15641 +       if (au_ftest_ren(a->flags, MNT_WRITE))
15642 +               mnt_drop_write(a->br->br_mnt);
15643 +       vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
15644 +                           a->dst_h_parent, a->dst_hdir);
15645 +}
15646 +
15647 +static int au_ren_lock(struct au_ren_args *a)
15648 +{
15649 +       int err;
15650 +       unsigned int udba;
15651 +
15652 +       err = 0;
15653 +       a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
15654 +       a->src_hdir = au_hi(a->src_dir, a->btgt);
15655 +       a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
15656 +       a->dst_hdir = au_hi(a->dst_dir, a->btgt);
15657 +       a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
15658 +                                     a->dst_h_parent, a->dst_hdir);
15659 +       udba = au_opt_udba(a->src_dentry->d_sb);
15660 +       if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
15661 +                    || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
15662 +               err = au_busy_or_stale();
15663 +       if (!err && au_dbstart(a->src_dentry) == a->btgt)
15664 +               err = au_h_verify(a->src_h_dentry, udba,
15665 +                                 a->src_h_parent->d_inode, a->src_h_parent,
15666 +                                 a->br);
15667 +       if (!err && au_dbstart(a->dst_dentry) == a->btgt)
15668 +               err = au_h_verify(a->dst_h_dentry, udba,
15669 +                                 a->dst_h_parent->d_inode, a->dst_h_parent,
15670 +                                 a->br);
15671 +       if (!err) {
15672 +               err = mnt_want_write(a->br->br_mnt);
15673 +               if (unlikely(err))
15674 +                       goto out_unlock;
15675 +               au_fset_ren(a->flags, MNT_WRITE);
15676 +               goto out; /* success */
15677 +       }
15678 +
15679 +       err = au_busy_or_stale();
15680 +
15681 +out_unlock:
15682 +       au_ren_unlock(a);
15683 +out:
15684 +       return err;
15685 +}
15686 +
15687 +/* ---------------------------------------------------------------------- */
15688 +
15689 +static void au_ren_refresh_dir(struct au_ren_args *a)
15690 +{
15691 +       struct inode *dir;
15692 +
15693 +       dir = a->dst_dir;
15694 +       dir->i_version++;
15695 +       if (au_ftest_ren(a->flags, ISDIR)) {
15696 +               /* is this updating defined in POSIX? */
15697 +               au_cpup_attr_timesizes(a->src_inode);
15698 +               au_cpup_attr_nlink(dir, /*force*/1);
15699 +               if (a->dst_inode) {
15700 +                       clear_nlink(a->dst_inode);
15701 +                       au_cpup_attr_timesizes(a->dst_inode);
15702 +               }
15703 +       }
15704 +       if (au_ibstart(dir) == a->btgt)
15705 +               au_cpup_attr_timesizes(dir);
15706 +
15707 +       if (au_ftest_ren(a->flags, ISSAMEDIR))
15708 +               return;
15709 +
15710 +       dir = a->src_dir;
15711 +       dir->i_version++;
15712 +       if (au_ftest_ren(a->flags, ISDIR))
15713 +               au_cpup_attr_nlink(dir, /*force*/1);
15714 +       if (au_ibstart(dir) == a->btgt)
15715 +               au_cpup_attr_timesizes(dir);
15716 +}
15717 +
15718 +static void au_ren_refresh(struct au_ren_args *a)
15719 +{
15720 +       aufs_bindex_t bend, bindex;
15721 +       struct dentry *d, *h_d;
15722 +       struct inode *i, *h_i;
15723 +       struct super_block *sb;
15724 +
15725 +       d = a->src_dentry;
15726 +       au_set_dbwh(d, -1);
15727 +       bend = au_dbend(d);
15728 +       for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
15729 +               h_d = au_h_dptr(d, bindex);
15730 +               if (h_d)
15731 +                       au_set_h_dptr(d, bindex, NULL);
15732 +       }
15733 +       au_set_dbend(d, a->btgt);
15734 +
15735 +       sb = d->d_sb;
15736 +       i = a->src_inode;
15737 +       if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
15738 +               return; /* success */
15739 +
15740 +       bend = au_ibend(i);
15741 +       for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
15742 +               h_i = au_h_iptr(i, bindex);
15743 +               if (h_i) {
15744 +                       au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
15745 +                       /* ignore this error */
15746 +                       au_set_h_iptr(i, bindex, NULL, 0);
15747 +               }
15748 +       }
15749 +       au_set_ibend(i, a->btgt);
15750 +}
15751 +
15752 +/* ---------------------------------------------------------------------- */
15753 +
15754 +/* mainly for link(2) and rename(2) */
15755 +int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
15756 +{
15757 +       aufs_bindex_t bdiropq, bwh;
15758 +       struct dentry *parent;
15759 +       struct au_branch *br;
15760 +
15761 +       parent = dentry->d_parent;
15762 +       IMustLock(parent->d_inode); /* dir is locked */
15763 +
15764 +       bdiropq = au_dbdiropq(parent);
15765 +       bwh = au_dbwh(dentry);
15766 +       br = au_sbr(dentry->d_sb, btgt);
15767 +       if (au_br_rdonly(br)
15768 +           || (0 <= bdiropq && bdiropq < btgt)
15769 +           || (0 <= bwh && bwh < btgt))
15770 +               btgt = -1;
15771 +
15772 +       AuDbg("btgt %d\n", btgt);
15773 +       return btgt;
15774 +}
15775 +
15776 +/* sets src_bstart, dst_bstart and btgt */
15777 +static int au_ren_wbr(struct au_ren_args *a)
15778 +{
15779 +       int err;
15780 +       struct au_wr_dir_args wr_dir_args = {
15781 +               /* .force_btgt  = -1, */
15782 +               .flags          = AuWrDir_ADD_ENTRY
15783 +       };
15784 +
15785 +       a->src_bstart = au_dbstart(a->src_dentry);
15786 +       a->dst_bstart = au_dbstart(a->dst_dentry);
15787 +       if (au_ftest_ren(a->flags, ISDIR))
15788 +               au_fset_wrdir(wr_dir_args.flags, ISDIR);
15789 +       wr_dir_args.force_btgt = a->src_bstart;
15790 +       if (a->dst_inode && a->dst_bstart < a->src_bstart)
15791 +               wr_dir_args.force_btgt = a->dst_bstart;
15792 +       wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
15793 +       err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
15794 +       a->btgt = err;
15795 +
15796 +       return err;
15797 +}
15798 +
15799 +static void au_ren_dt(struct au_ren_args *a)
15800 +{
15801 +       a->h_path.dentry = a->src_h_parent;
15802 +       au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
15803 +       if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
15804 +               a->h_path.dentry = a->dst_h_parent;
15805 +               au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
15806 +       }
15807 +
15808 +       au_fclr_ren(a->flags, DT_DSTDIR);
15809 +       if (!au_ftest_ren(a->flags, ISDIR))
15810 +               return;
15811 +
15812 +       a->h_path.dentry = a->src_h_dentry;
15813 +       au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
15814 +       if (a->dst_h_dentry->d_inode) {
15815 +               au_fset_ren(a->flags, DT_DSTDIR);
15816 +               a->h_path.dentry = a->dst_h_dentry;
15817 +               au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
15818 +       }
15819 +}
15820 +
15821 +static void au_ren_rev_dt(int err, struct au_ren_args *a)
15822 +{
15823 +       struct dentry *h_d;
15824 +       struct mutex *h_mtx;
15825 +
15826 +       au_dtime_revert(a->src_dt + AuPARENT);
15827 +       if (!au_ftest_ren(a->flags, ISSAMEDIR))
15828 +               au_dtime_revert(a->dst_dt + AuPARENT);
15829 +
15830 +       if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
15831 +               h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
15832 +               h_mtx = &h_d->d_inode->i_mutex;
15833 +               mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15834 +               au_dtime_revert(a->src_dt + AuCHILD);
15835 +               mutex_unlock(h_mtx);
15836 +
15837 +               if (au_ftest_ren(a->flags, DT_DSTDIR)) {
15838 +                       h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
15839 +                       h_mtx = &h_d->d_inode->i_mutex;
15840 +                       mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15841 +                       au_dtime_revert(a->dst_dt + AuCHILD);
15842 +                       mutex_unlock(h_mtx);
15843 +               }
15844 +       }
15845 +}
15846 +
15847 +/* ---------------------------------------------------------------------- */
15848 +
15849 +int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
15850 +               struct inode *_dst_dir, struct dentry *_dst_dentry)
15851 +{
15852 +       int err;
15853 +       /* reduce stack space */
15854 +       struct au_ren_args *a;
15855 +
15856 +       AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
15857 +       IMustLock(_src_dir);
15858 +       IMustLock(_dst_dir);
15859 +
15860 +       err = -ENOMEM;
15861 +       BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
15862 +       a = kzalloc(sizeof(*a), GFP_NOFS);
15863 +       if (unlikely(!a))
15864 +               goto out;
15865 +
15866 +       a->src_dir = _src_dir;
15867 +       a->src_dentry = _src_dentry;
15868 +       a->src_inode = a->src_dentry->d_inode;
15869 +       a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
15870 +       a->dst_dir = _dst_dir;
15871 +       a->dst_dentry = _dst_dentry;
15872 +       a->dst_inode = a->dst_dentry->d_inode;
15873 +       a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
15874 +       if (a->dst_inode) {
15875 +               IMustLock(a->dst_inode);
15876 +               au_igrab(a->dst_inode);
15877 +       }
15878 +
15879 +       err = -ENOTDIR;
15880 +       if (S_ISDIR(a->src_inode->i_mode)) {
15881 +               au_fset_ren(a->flags, ISDIR);
15882 +               if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
15883 +                       goto out_free;
15884 +               aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
15885 +                                         AuLock_DIR | AuLock_FLUSH);
15886 +       } else
15887 +               aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
15888 +                                         AuLock_FLUSH);
15889 +
15890 +       au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
15891 +       di_write_lock_parent(a->dst_parent);
15892 +
15893 +       /* which branch we process */
15894 +       err = au_ren_wbr(a);
15895 +       if (unlikely(err < 0))
15896 +               goto out_unlock;
15897 +       a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
15898 +       a->h_path.mnt = a->br->br_mnt;
15899 +
15900 +       /* are they available to be renamed */
15901 +       err = au_ren_may_dir(a);
15902 +       if (unlikely(err))
15903 +               goto out_children;
15904 +
15905 +       /* prepare the writable parent dir on the same branch */
15906 +       if (a->dst_bstart == a->btgt) {
15907 +               au_fset_ren(a->flags, WHDST);
15908 +       } else {
15909 +               err = au_cpup_dirs(a->dst_dentry, a->btgt);
15910 +               if (unlikely(err))
15911 +                       goto out_children;
15912 +       }
15913 +
15914 +       if (a->src_dir != a->dst_dir) {
15915 +               /*
15916 +                * this temporary unlock is safe,
15917 +                * because both dir->i_mutex are locked.
15918 +                */
15919 +               di_write_unlock(a->dst_parent);
15920 +               di_write_lock_parent(a->src_parent);
15921 +               err = au_wr_dir_need_wh(a->src_dentry,
15922 +                                       au_ftest_ren(a->flags, ISDIR),
15923 +                                       &a->btgt);
15924 +               di_write_unlock(a->src_parent);
15925 +               di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
15926 +               au_fclr_ren(a->flags, ISSAMEDIR);
15927 +       } else
15928 +               err = au_wr_dir_need_wh(a->src_dentry,
15929 +                                       au_ftest_ren(a->flags, ISDIR),
15930 +                                       &a->btgt);
15931 +       if (unlikely(err < 0))
15932 +               goto out_children;
15933 +       if (err)
15934 +               au_fset_ren(a->flags, WHSRC);
15935 +
15936 +       /* lock them all */
15937 +       err = au_ren_lock(a);
15938 +       if (unlikely(err))
15939 +               goto out_children;
15940 +
15941 +       if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
15942 +               err = au_may_ren(a);
15943 +       else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
15944 +               err = -ENAMETOOLONG;
15945 +       if (unlikely(err))
15946 +               goto out_hdir;
15947 +
15948 +       /* store timestamps to be revertible */
15949 +       au_ren_dt(a);
15950 +
15951 +       /* here we go */
15952 +       err = do_rename(a);
15953 +       if (unlikely(err))
15954 +               goto out_dt;
15955 +
15956 +       /* update dir attributes */
15957 +       au_ren_refresh_dir(a);
15958 +
15959 +       /* dput/iput all lower dentries */
15960 +       au_ren_refresh(a);
15961 +
15962 +       goto out_hdir; /* success */
15963 +
15964 +out_dt:
15965 +       au_ren_rev_dt(err, a);
15966 +out_hdir:
15967 +       au_ren_unlock(a);
15968 +out_children:
15969 +       au_nhash_wh_free(&a->whlist);
15970 +out_unlock:
15971 +       if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
15972 +               au_update_dbstart(a->dst_dentry);
15973 +               d_drop(a->dst_dentry);
15974 +       }
15975 +       if (!err)
15976 +               d_move(a->src_dentry, a->dst_dentry);
15977 +       if (au_ftest_ren(a->flags, ISSAMEDIR))
15978 +               di_write_unlock(a->dst_parent);
15979 +       else
15980 +               di_write_unlock2(a->src_parent, a->dst_parent);
15981 +       aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
15982 +out_free:
15983 +       iput(a->dst_inode);
15984 +       if (a->thargs)
15985 +               au_whtmp_rmdir_free(a->thargs);
15986 +       kfree(a);
15987 +out:
15988 +       AuTraceErr(err);
15989 +       return err;
15990 +}
15991 diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
15992 --- /usr/share/empty/fs/aufs/Kconfig    1970-01-01 01:00:00.000000000 +0100
15993 +++ linux/fs/aufs/Kconfig       2010-10-21 09:52:43.083624114 +0200
15994 @@ -0,0 +1,173 @@
15995 +config AUFS_FS
15996 +       tristate "Aufs (Advanced multi layered unification filesystem) support"
15997 +       depends on EXPERIMENTAL
15998 +       help
15999 +       Aufs is a stackable unification filesystem such as Unionfs,
16000 +       which unifies several directories and provides a merged single
16001 +       directory.
16002 +       In the early days, aufs was entirely re-designed and
16003 +       re-implemented Unionfs Version 1.x series. Introducing many
16004 +       original ideas, approaches and improvements, it becomes totally
16005 +       different from Unionfs while keeping the basic features.
16006 +
16007 +if AUFS_FS
16008 +choice
16009 +       prompt "Maximum number of branches"
16010 +       default AUFS_BRANCH_MAX_127
16011 +       help
16012 +       Specifies the maximum number of branches (or member directories)
16013 +       in a single aufs. The larger value consumes more system
16014 +       resources and has a minor impact to performance.
16015 +config AUFS_BRANCH_MAX_127
16016 +       bool "127"
16017 +       help
16018 +       Specifies the maximum number of branches (or member directories)
16019 +       in a single aufs. The larger value consumes more system
16020 +       resources and has a minor impact to performance.
16021 +config AUFS_BRANCH_MAX_511
16022 +       bool "511"
16023 +       help
16024 +       Specifies the maximum number of branches (or member directories)
16025 +       in a single aufs. The larger value consumes more system
16026 +       resources and has a minor impact to performance.
16027 +config AUFS_BRANCH_MAX_1023
16028 +       bool "1023"
16029 +       help
16030 +       Specifies the maximum number of branches (or member directories)
16031 +       in a single aufs. The larger value consumes more system
16032 +       resources and has a minor impact to performance.
16033 +config AUFS_BRANCH_MAX_32767
16034 +       bool "32767"
16035 +       help
16036 +       Specifies the maximum number of branches (or member directories)
16037 +       in a single aufs. The larger value consumes more system
16038 +       resources and has a minor impact to performance.
16039 +endchoice
16040 +
16041 +config AUFS_HNOTIFY
16042 +       bool "Detect direct branch access (bypassing aufs)"
16043 +       help
16044 +       If you want to modify files on branches directly, eg. bypassing aufs,
16045 +       and want aufs to detect the changes of them fully, then enable this
16046 +       option and use 'udba=notify' mount option.
16047 +       Currently there is only one available configuration, "fsnotify".
16048 +       It will have a negative impact to the performance.
16049 +       See detail in aufs.5.
16050 +
16051 +
16052 +choice
16053 +       prompt "method" if AUFS_HNOTIFY
16054 +       default AUFS_HFSNOTIFY
16055 +config AUFS_HFSNOTIFY
16056 +       bool "fsnotify"
16057 +       select FSNOTIFY
16058 +endchoice
16059 +
16060 +config AUFS_EXPORT
16061 +       bool "NFS-exportable aufs"
16062 +       depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
16063 +       help
16064 +       If you want to export your mounted aufs via NFS, then enable this
16065 +       option. There are several requirements for this configuration.
16066 +       See detail in aufs.5.
16067 +
16068 +config AUFS_INO_T_64
16069 +       bool
16070 +       depends on AUFS_EXPORT
16071 +       depends on 64BIT && !(ALPHA || S390)
16072 +       default y
16073 +       help
16074 +       Automatic configuration for internal use.
16075 +       /* typedef unsigned long/int __kernel_ino_t */
16076 +       /* alpha and s390x are int */
16077 +
16078 +config AUFS_RDU
16079 +       bool "Readdir in userspace"
16080 +       help
16081 +       Aufs has two methods to provide a merged view for a directory,
16082 +       by a user-space library and by kernel-space natively. The latter
16083 +       is always enabled but sometimes large and slow.
16084 +       If you enable this option, install the library in aufs2-util
16085 +       package, and set some environment variables for your readdir(3),
16086 +       then the work will be handled in user-space which generally
16087 +       shows better performance in most cases.
16088 +       See detail in aufs.5.
16089 +
16090 +config AUFS_SP_IATTR
16091 +       bool "Respect the attributes (mtime/ctime mainly) of special files"
16092 +       help
16093 +       When you write something to a special file, some attributes of it
16094 +       (mtime/ctime mainly) may be updated. Generally such updates are
16095 +       less important (actually some device drivers and NFS ignore
16096 +       it). But some applications (such like test program) requires
16097 +       such updates. If you need these updates, then enable this
16098 +       configuration which introduces some overhead.
16099 +       Currently this configuration handles FIFO only.
16100 +
16101 +config AUFS_SHWH
16102 +       bool "Show whiteouts"
16103 +       help
16104 +       If you want to make the whiteouts in aufs visible, then enable
16105 +       this option and specify 'shwh' mount option. Although it may
16106 +       sounds like philosophy or something, but in technically it
16107 +       simply shows the name of whiteout with keeping its behaviour.
16108 +
16109 +config AUFS_BR_RAMFS
16110 +       bool "Ramfs (initramfs/rootfs) as an aufs branch"
16111 +       help
16112 +       If you want to use ramfs as an aufs branch fs, then enable this
16113 +       option. Generally tmpfs is recommended.
16114 +       Aufs prohibited them to be a branch fs by default, because
16115 +       initramfs becomes unusable after switch_root or something
16116 +       generally. If you sets initramfs as an aufs branch and boot your
16117 +       system by switch_root, you will meet a problem easily since the
16118 +       files in initramfs may be inaccessible.
16119 +       Unless you are going to use ramfs as an aufs branch fs without
16120 +       switch_root or something, leave it N.
16121 +
16122 +config AUFS_BR_FUSE
16123 +       bool "Fuse fs as an aufs branch"
16124 +       depends on FUSE_FS
16125 +       select AUFS_POLL
16126 +       help
16127 +       If you want to use fuse-based userspace filesystem as an aufs
16128 +       branch fs, then enable this option.
16129 +       It implements the internal poll(2) operation which is
16130 +       implemented by fuse only (curretnly).
16131 +
16132 +config AUFS_POLL
16133 +       bool
16134 +       help
16135 +       Automatic configuration for internal use.
16136 +
16137 +config AUFS_BR_HFSPLUS
16138 +       bool "Hfsplus as an aufs branch"
16139 +       depends on HFSPLUS_FS
16140 +       default y
16141 +       help
16142 +       If you want to use hfsplus fs as an aufs branch fs, then enable
16143 +       this option. This option introduces a small overhead at
16144 +       copying-up a file on hfsplus.
16145 +
16146 +config AUFS_BDEV_LOOP
16147 +       bool
16148 +       depends on BLK_DEV_LOOP
16149 +       default y
16150 +       help
16151 +       Automatic configuration for internal use.
16152 +       Convert =[ym] into =y.
16153 +
16154 +config AUFS_DEBUG
16155 +       bool "Debug aufs"
16156 +       help
16157 +       Enable this to compile aufs internal debug code.
16158 +       It will have a negative impact to the performance.
16159 +
16160 +config AUFS_MAGIC_SYSRQ
16161 +       bool
16162 +       depends on AUFS_DEBUG && MAGIC_SYSRQ
16163 +       default y
16164 +       help
16165 +       Automatic configuration for internal use.
16166 +       When aufs supports Magic SysRq, enabled automatically.
16167 +endif
16168 diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
16169 --- /usr/share/empty/fs/aufs/loop.c     1970-01-01 01:00:00.000000000 +0100
16170 +++ linux/fs/aufs/loop.c        2010-10-21 09:52:43.093625591 +0200
16171 @@ -0,0 +1,63 @@
16172 +/*
16173 + * Copyright (C) 2005-2010 Junjiro R. Okajima
16174 + *
16175 + * This program, aufs is free software; you can redistribute it and/or modify
16176 + * it under the terms of the GNU General Public License as published by
16177 + * the Free Software Foundation; either version 2 of the License, or
16178 + * (at your option) any later version.
16179 + *
16180 + * This program is distributed in the hope that it will be useful,
16181 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16182 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16183 + * GNU General Public License for more details.
16184 + *
16185 + * You should have received a copy of the GNU General Public License
16186 + * along with this program; if not, write to the Free Software
16187 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16188 + */
16189 +
16190 +/*
16191 + * support for loopback block device as a branch
16192 + */
16193 +
16194 +#include <linux/loop.h>
16195 +#include "aufs.h"
16196 +
16197 +/*
16198 + * test if two lower dentries have overlapping branches.
16199 + */
16200 +int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
16201 +{
16202 +       struct super_block *h_sb;
16203 +       struct loop_device *l;
16204 +
16205 +       h_sb = h_adding->d_sb;
16206 +       if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
16207 +               return 0;
16208 +
16209 +       l = h_sb->s_bdev->bd_disk->private_data;
16210 +       h_adding = l->lo_backing_file->f_dentry;
16211 +       /*
16212 +        * h_adding can be local NFS.
16213 +        * in this case aufs cannot detect the loop.
16214 +        */
16215 +       if (unlikely(h_adding->d_sb == sb))
16216 +               return 1;
16217 +       return !!au_test_subdir(h_adding, sb->s_root);
16218 +}
16219 +
16220 +/* true if a kernel thread named 'loop[0-9].*' accesses a file */
16221 +int au_test_loopback_kthread(void)
16222 +{
16223 +       int ret;
16224 +       struct task_struct *tsk = current;
16225 +
16226 +       ret = 0;
16227 +       if (tsk->flags & PF_KTHREAD) {
16228 +               const char c = tsk->comm[4];
16229 +               ret = ('0' <= c && c <= '9'
16230 +                      && !strncmp(tsk->comm, "loop", 4));
16231 +       }
16232 +
16233 +       return ret;
16234 +}
16235 diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
16236 --- /usr/share/empty/fs/aufs/loop.h     1970-01-01 01:00:00.000000000 +0100
16237 +++ linux/fs/aufs/loop.h        2010-10-21 09:52:43.093625591 +0200
16238 @@ -0,0 +1,42 @@
16239 +/*
16240 + * Copyright (C) 2005-2010 Junjiro R. Okajima
16241 + *
16242 + * This program, aufs is free software; you can redistribute it and/or modify
16243 + * it under the terms of the GNU General Public License as published by
16244 + * the Free Software Foundation; either version 2 of the License, or
16245 + * (at your option) any later version.
16246 + *
16247 + * This program is distributed in the hope that it will be useful,
16248 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16249 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16250 + * GNU General Public License for more details.
16251 + *
16252 + * You should have received a copy of the GNU General Public License
16253 + * along with this program; if not, write to the Free Software
16254 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16255 + */
16256 +
16257 +/*
16258 + * support for loopback mount as a branch
16259 + */
16260 +
16261 +#ifndef __AUFS_LOOP_H__
16262 +#define __AUFS_LOOP_H__
16263 +
16264 +#ifdef __KERNEL__
16265 +
16266 +struct dentry;
16267 +struct super_block;
16268 +
16269 +#ifdef CONFIG_AUFS_BDEV_LOOP
16270 +/* loop.c */
16271 +int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
16272 +int au_test_loopback_kthread(void);
16273 +#else
16274 +AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
16275 +          struct dentry *h_adding)
16276 +AuStubInt0(au_test_loopback_kthread, void)
16277 +#endif /* BLK_DEV_LOOP */
16278 +
16279 +#endif /* __KERNEL__ */
16280 +#endif /* __AUFS_LOOP_H__ */
16281 diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
16282 --- /usr/share/empty/fs/aufs/magic.mk   1970-01-01 01:00:00.000000000 +0100
16283 +++ linux/fs/aufs/magic.mk      2010-10-21 09:52:43.093625591 +0200
16284 @@ -0,0 +1,54 @@
16285 +
16286 +# defined in ${srctree}/fs/fuse/inode.c
16287 +# tristate
16288 +ifdef CONFIG_FUSE_FS
16289 +ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
16290 +endif
16291 +
16292 +# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
16293 +# tristate
16294 +ifdef CONFIG_OCFS2_FS
16295 +ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
16296 +endif
16297 +
16298 +# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
16299 +# tristate
16300 +ifdef CONFIG_OCFS2_FS_O2CB
16301 +ccflags-y += -DDLMFS_MAGIC=0x76a9f425
16302 +endif
16303 +
16304 +# defined in ${srctree}/fs/cifs/cifsfs.c
16305 +# tristate
16306 +ifdef CONFIG_CIFS_FS
16307 +ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
16308 +endif
16309 +
16310 +# defined in ${srctree}/fs/xfs/xfs_sb.h
16311 +# tristate
16312 +ifdef CONFIG_XFS_FS
16313 +ccflags-y += -DXFS_SB_MAGIC=0x58465342
16314 +endif
16315 +
16316 +# defined in ${srctree}/fs/configfs/mount.c
16317 +# tristate
16318 +ifdef CONFIG_CONFIGFS_FS
16319 +ccflags-y += -DCONFIGFS_MAGIC=0x62656570
16320 +endif
16321 +
16322 +# defined in ${srctree}/fs/9p/v9fs.h
16323 +# tristate
16324 +ifdef CONFIG_9P_FS
16325 +ccflags-y += -DV9FS_MAGIC=0x01021997
16326 +endif
16327 +
16328 +# defined in ${srctree}/fs/ubifs/ubifs.h
16329 +# tristate
16330 +ifdef CONFIG_UBIFS_FS
16331 +ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
16332 +endif
16333 +
16334 +# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
16335 +# tristate
16336 +ifdef CONFIG_HFSPLUS_FS
16337 +ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
16338 +endif
16339 diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
16340 --- /usr/share/empty/fs/aufs/Makefile   1970-01-01 01:00:00.000000000 +0100
16341 +++ linux/fs/aufs/Makefile      2010-10-21 09:52:43.083624114 +0200
16342 @@ -0,0 +1,37 @@
16343 +
16344 +include ${src}/magic.mk
16345 +ifeq (${CONFIG_AUFS_FS},m)
16346 +include ${src}/conf.mk
16347 +endif
16348 +-include ${src}/priv_def.mk
16349 +
16350 +# cf. include/linux/kernel.h
16351 +# enable pr_debug
16352 +ccflags-y += -DDEBUG
16353 +ccflags-y += -D'pr_fmt(fmt)="aufs %s:%d:%s[%d]: " fmt, \
16354 +       __func__, __LINE__, current->comm, current->pid'
16355 +
16356 +obj-$(CONFIG_AUFS_FS) += aufs.o
16357 +aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
16358 +       wkq.o vfsub.o dcsub.o \
16359 +       cpup.o whout.o plink.o wbr_policy.o \
16360 +       dinfo.o dentry.o \
16361 +       dynop.o \
16362 +       finfo.o file.o f_op.o \
16363 +       dir.o vdir.o \
16364 +       iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
16365 +       ioctl.o
16366 +
16367 +# all are boolean
16368 +aufs-$(CONFIG_SYSFS) += sysfs.o
16369 +aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
16370 +aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
16371 +aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
16372 +aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
16373 +aufs-$(CONFIG_AUFS_EXPORT) += export.o
16374 +aufs-$(CONFIG_AUFS_POLL) += poll.o
16375 +aufs-$(CONFIG_AUFS_RDU) += rdu.o
16376 +aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
16377 +aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
16378 +aufs-$(CONFIG_AUFS_DEBUG) += debug.o
16379 +aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
16380 diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
16381 --- /usr/share/empty/fs/aufs/module.c   1970-01-01 01:00:00.000000000 +0100
16382 +++ linux/fs/aufs/module.c      2010-10-21 09:52:43.093625591 +0200
16383 @@ -0,0 +1,171 @@
16384 +/*
16385 + * Copyright (C) 2005-2010 Junjiro R. Okajima
16386 + *
16387 + * This program, aufs is free software; you can redistribute it and/or modify
16388 + * it under the terms of the GNU General Public License as published by
16389 + * the Free Software Foundation; either version 2 of the License, or
16390 + * (at your option) any later version.
16391 + *
16392 + * This program is distributed in the hope that it will be useful,
16393 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16394 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16395 + * GNU General Public License for more details.
16396 + *
16397 + * You should have received a copy of the GNU General Public License
16398 + * along with this program; if not, write to the Free Software
16399 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16400 + */
16401 +
16402 +/*
16403 + * module global variables and operations
16404 + */
16405 +
16406 +#include <linux/module.h>
16407 +#include <linux/seq_file.h>
16408 +#include "aufs.h"
16409 +
16410 +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
16411 +{
16412 +       if (new_sz <= nused)
16413 +               return p;
16414 +
16415 +       p = krealloc(p, new_sz, gfp);
16416 +       if (p)
16417 +               memset(p + nused, 0, new_sz - nused);
16418 +       return p;
16419 +}
16420 +
16421 +/* ---------------------------------------------------------------------- */
16422 +
16423 +/*
16424 + * aufs caches
16425 + */
16426 +struct kmem_cache *au_cachep[AuCache_Last];
16427 +static int __init au_cache_init(void)
16428 +{
16429 +       au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
16430 +       if (au_cachep[AuCache_DINFO])
16431 +               au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
16432 +                                                       au_icntnr_init_once);
16433 +       if (au_cachep[AuCache_ICNTNR])
16434 +               au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
16435 +                                                      au_fi_init_once);
16436 +       if (au_cachep[AuCache_FINFO])
16437 +               au_cachep[AuCache_VDIR] = AuCache(au_vdir);
16438 +       if (au_cachep[AuCache_VDIR])
16439 +               au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
16440 +       if (au_cachep[AuCache_DEHSTR])
16441 +               return 0;
16442 +
16443 +       return -ENOMEM;
16444 +}
16445 +
16446 +static void au_cache_fin(void)
16447 +{
16448 +       int i;
16449 +
16450 +       /* including AuCache_HNOTIFY */
16451 +       for (i = 0; i < AuCache_Last; i++)
16452 +               if (au_cachep[i]) {
16453 +                       kmem_cache_destroy(au_cachep[i]);
16454 +                       au_cachep[i] = NULL;
16455 +               }
16456 +}
16457 +
16458 +/* ---------------------------------------------------------------------- */
16459 +
16460 +int au_dir_roflags;
16461 +
16462 +/*
16463 + * functions for module interface.
16464 + */
16465 +MODULE_LICENSE("GPL");
16466 +/* MODULE_LICENSE("GPL v2"); */
16467 +MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
16468 +MODULE_DESCRIPTION(AUFS_NAME
16469 +       " -- Advanced multi layered unification filesystem");
16470 +MODULE_VERSION(AUFS_VERSION);
16471 +
16472 +/* this module parameter has no meaning when SYSFS is disabled */
16473 +int sysaufs_brs = 1;
16474 +MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
16475 +module_param_named(brs, sysaufs_brs, int, S_IRUGO);
16476 +
16477 +/* ---------------------------------------------------------------------- */
16478 +
16479 +static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
16480 +
16481 +int au_seq_path(struct seq_file *seq, struct path *path)
16482 +{
16483 +       return seq_path(seq, path, au_esc_chars);
16484 +}
16485 +
16486 +/* ---------------------------------------------------------------------- */
16487 +
16488 +static int __init aufs_init(void)
16489 +{
16490 +       int err, i;
16491 +       char *p;
16492 +
16493 +       p = au_esc_chars;
16494 +       for (i = 1; i <= ' '; i++)
16495 +               *p++ = i;
16496 +       *p++ = '\\';
16497 +       *p++ = '\x7f';
16498 +       *p = 0;
16499 +
16500 +       au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
16501 +
16502 +       sysaufs_brs_init();
16503 +       au_debug_init();
16504 +       au_dy_init();
16505 +       err = sysaufs_init();
16506 +       if (unlikely(err))
16507 +               goto out;
16508 +       err = au_wkq_init();
16509 +       if (unlikely(err))
16510 +               goto out_sysaufs;
16511 +       err = au_hnotify_init();
16512 +       if (unlikely(err))
16513 +               goto out_wkq;
16514 +       err = au_sysrq_init();
16515 +       if (unlikely(err))
16516 +               goto out_hin;
16517 +       err = au_cache_init();
16518 +       if (unlikely(err))
16519 +               goto out_sysrq;
16520 +       err = register_filesystem(&aufs_fs_type);
16521 +       if (unlikely(err))
16522 +               goto out_cache;
16523 +       /* since we define pr_fmt, call printk directly */
16524 +       printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
16525 +       goto out; /* success */
16526 +
16527 +out_cache:
16528 +       au_cache_fin();
16529 +out_sysrq:
16530 +       au_sysrq_fin();
16531 +out_hin:
16532 +       au_hnotify_fin();
16533 +out_wkq:
16534 +       au_wkq_fin();
16535 +out_sysaufs:
16536 +       sysaufs_fin();
16537 +       au_dy_fin();
16538 +out:
16539 +       return err;
16540 +}
16541 +
16542 +static void __exit aufs_exit(void)
16543 +{
16544 +       unregister_filesystem(&aufs_fs_type);
16545 +       au_cache_fin();
16546 +       au_sysrq_fin();
16547 +       au_hnotify_fin();
16548 +       au_wkq_fin();
16549 +       sysaufs_fin();
16550 +       au_dy_fin();
16551 +}
16552 +
16553 +module_init(aufs_init);
16554 +module_exit(aufs_exit);
16555 diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
16556 --- /usr/share/empty/fs/aufs/module.h   1970-01-01 01:00:00.000000000 +0100
16557 +++ linux/fs/aufs/module.h      2010-10-21 09:52:43.093625591 +0200
16558 @@ -0,0 +1,82 @@
16559 +/*
16560 + * Copyright (C) 2005-2010 Junjiro R. Okajima
16561 + *
16562 + * This program, aufs is free software; you can redistribute it and/or modify
16563 + * it under the terms of the GNU General Public License as published by
16564 + * the Free Software Foundation; either version 2 of the License, or
16565 + * (at your option) any later version.
16566 + *
16567 + * This program is distributed in the hope that it will be useful,
16568 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16569 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16570 + * GNU General Public License for more details.
16571 + *
16572 + * You should have received a copy of the GNU General Public License
16573 + * along with this program; if not, write to the Free Software
16574 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16575 + */
16576 +
16577 +/*
16578 + * module initialization and module-global
16579 + */
16580 +
16581 +#ifndef __AUFS_MODULE_H__
16582 +#define __AUFS_MODULE_H__
16583 +
16584 +#ifdef __KERNEL__
16585 +
16586 +#include <linux/slab.h>
16587 +
16588 +struct path;
16589 +struct seq_file;
16590 +
16591 +/* module parameters */
16592 +extern int sysaufs_brs;
16593 +
16594 +/* ---------------------------------------------------------------------- */
16595 +
16596 +extern int au_dir_roflags;
16597 +
16598 +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
16599 +int au_seq_path(struct seq_file *seq, struct path *path);
16600 +
16601 +/* ---------------------------------------------------------------------- */
16602 +
16603 +/* kmem cache */
16604 +enum {
16605 +       AuCache_DINFO,
16606 +       AuCache_ICNTNR,
16607 +       AuCache_FINFO,
16608 +       AuCache_VDIR,
16609 +       AuCache_DEHSTR,
16610 +#ifdef CONFIG_AUFS_HNOTIFY
16611 +       AuCache_HNOTIFY,
16612 +#endif
16613 +       AuCache_Last
16614 +};
16615 +
16616 +#define AuCacheFlags           (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
16617 +#define AuCache(type)          KMEM_CACHE(type, AuCacheFlags)
16618 +#define AuCacheCtor(type, ctor)        \
16619 +       kmem_cache_create(#type, sizeof(struct type), \
16620 +                         __alignof__(struct type), AuCacheFlags, ctor)
16621 +
16622 +extern struct kmem_cache *au_cachep[];
16623 +
16624 +#define AuCacheFuncs(name, index) \
16625 +static inline struct au_##name *au_cache_alloc_##name(void) \
16626 +{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
16627 +static inline void au_cache_free_##name(struct au_##name *p) \
16628 +{ kmem_cache_free(au_cachep[AuCache_##index], p); }
16629 +
16630 +AuCacheFuncs(dinfo, DINFO);
16631 +AuCacheFuncs(icntnr, ICNTNR);
16632 +AuCacheFuncs(finfo, FINFO);
16633 +AuCacheFuncs(vdir, VDIR);
16634 +AuCacheFuncs(vdir_dehstr, DEHSTR);
16635 +#ifdef CONFIG_AUFS_HNOTIFY
16636 +AuCacheFuncs(hnotify, HNOTIFY);
16637 +#endif
16638 +
16639 +#endif /* __KERNEL__ */
16640 +#endif /* __AUFS_MODULE_H__ */
16641 diff -urN /usr/share/empty/fs/aufs/mtx.h linux/fs/aufs/mtx.h
16642 --- /usr/share/empty/fs/aufs/mtx.h      1970-01-01 01:00:00.000000000 +0100
16643 +++ linux/fs/aufs/mtx.h 2010-10-21 09:52:43.093625591 +0200
16644 @@ -0,0 +1,48 @@
16645 +/*
16646 + * Copyright (C) 2010 Junjiro R. Okajima
16647 + *
16648 + * This program, aufs is free software; you can redistribute it and/or modify
16649 + * it under the terms of the GNU General Public License as published by
16650 + * the Free Software Foundation; either version 2 of the License, or
16651 + * (at your option) any later version.
16652 + *
16653 + * This program is distributed in the hope that it will be useful,
16654 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16655 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16656 + * GNU General Public License for more details.
16657 + *
16658 + * You should have received a copy of the GNU General Public License
16659 + * along with this program; if not, write to the Free Software
16660 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16661 + */
16662 +
16663 +/*
16664 + * very ugly approach for aufs_mmap()
16665 + * never include this file from other than f_op.c.
16666 + * see f_op.c in detail.
16667 + */
16668 +
16669 +#ifndef __AUFS_MTX_H__
16670 +#define __AUFS_MTX_H__
16671 +
16672 +#ifdef __KERNEL__
16673 +
16674 +/* copied from ../kernel/mutex{,-debug}.h */
16675 +struct mutex;
16676 +struct thread_info;
16677 +#ifdef CONFIG_DEBUG_MUTEXES
16678 +static inline void mutex_set_owner(struct mutex *lock)
16679 +{
16680 +       lock->owner = current_thread_info();
16681 +}
16682 +#else
16683 +static inline void mutex_set_owner(struct mutex *lock)
16684 +{
16685 +#ifdef CONFIG_SMP
16686 +       lock->owner = current_thread_info();
16687 +#endif
16688 +}
16689 +#endif
16690 +
16691 +#endif /* __KERNEL__ */
16692 +#endif /* __AUFS_MTX_H__ */
16693 diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
16694 --- /usr/share/empty/fs/aufs/opts.c     1970-01-01 01:00:00.000000000 +0100
16695 +++ linux/fs/aufs/opts.c        2010-10-21 09:52:43.093625591 +0200
16696 @@ -0,0 +1,1571 @@
16697 +/*
16698 + * Copyright (C) 2005-2010 Junjiro R. Okajima
16699 + *
16700 + * This program, aufs is free software; you can redistribute it and/or modify
16701 + * it under the terms of the GNU General Public License as published by
16702 + * the Free Software Foundation; either version 2 of the License, or
16703 + * (at your option) any later version.
16704 + *
16705 + * This program is distributed in the hope that it will be useful,
16706 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16707 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16708 + * GNU General Public License for more details.
16709 + *
16710 + * You should have received a copy of the GNU General Public License
16711 + * along with this program; if not, write to the Free Software
16712 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16713 + */
16714 +
16715 +/*
16716 + * mount options/flags
16717 + */
16718 +
16719 +#include <linux/file.h>
16720 +#include <linux/namei.h>
16721 +#include <linux/types.h> /* a distribution requires */
16722 +#include <linux/parser.h>
16723 +#include "aufs.h"
16724 +
16725 +/* ---------------------------------------------------------------------- */
16726 +
16727 +enum {
16728 +       Opt_br,
16729 +       Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
16730 +       Opt_idel, Opt_imod, Opt_ireorder,
16731 +       Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
16732 +       Opt_rdblk_def, Opt_rdhash_def,
16733 +       Opt_xino, Opt_zxino, Opt_noxino,
16734 +       Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
16735 +       Opt_trunc_xino_path, Opt_itrunc_xino,
16736 +       Opt_trunc_xib, Opt_notrunc_xib,
16737 +       Opt_shwh, Opt_noshwh,
16738 +       Opt_plink, Opt_noplink, Opt_list_plink,
16739 +       Opt_udba,
16740 +       Opt_dio, Opt_nodio,
16741 +       /* Opt_lock, Opt_unlock, */
16742 +       Opt_cmd, Opt_cmd_args,
16743 +       Opt_diropq_a, Opt_diropq_w,
16744 +       Opt_warn_perm, Opt_nowarn_perm,
16745 +       Opt_wbr_copyup, Opt_wbr_create,
16746 +       Opt_refrof, Opt_norefrof,
16747 +       Opt_verbose, Opt_noverbose,
16748 +       Opt_sum, Opt_nosum, Opt_wsum,
16749 +       Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
16750 +};
16751 +
16752 +static match_table_t options = {
16753 +       {Opt_br, "br=%s"},
16754 +       {Opt_br, "br:%s"},
16755 +
16756 +       {Opt_add, "add=%d:%s"},
16757 +       {Opt_add, "add:%d:%s"},
16758 +       {Opt_add, "ins=%d:%s"},
16759 +       {Opt_add, "ins:%d:%s"},
16760 +       {Opt_append, "append=%s"},
16761 +       {Opt_append, "append:%s"},
16762 +       {Opt_prepend, "prepend=%s"},
16763 +       {Opt_prepend, "prepend:%s"},
16764 +
16765 +       {Opt_del, "del=%s"},
16766 +       {Opt_del, "del:%s"},
16767 +       /* {Opt_idel, "idel:%d"}, */
16768 +       {Opt_mod, "mod=%s"},
16769 +       {Opt_mod, "mod:%s"},
16770 +       /* {Opt_imod, "imod:%d:%s"}, */
16771 +
16772 +       {Opt_dirwh, "dirwh=%d"},
16773 +
16774 +       {Opt_xino, "xino=%s"},
16775 +       {Opt_noxino, "noxino"},
16776 +       {Opt_trunc_xino, "trunc_xino"},
16777 +       {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
16778 +       {Opt_notrunc_xino, "notrunc_xino"},
16779 +       {Opt_trunc_xino_path, "trunc_xino=%s"},
16780 +       {Opt_itrunc_xino, "itrunc_xino=%d"},
16781 +       /* {Opt_zxino, "zxino=%s"}, */
16782 +       {Opt_trunc_xib, "trunc_xib"},
16783 +       {Opt_notrunc_xib, "notrunc_xib"},
16784 +
16785 +       {Opt_plink, "plink"},
16786 +       {Opt_noplink, "noplink"},
16787 +#ifdef CONFIG_AUFS_DEBUG
16788 +       {Opt_list_plink, "list_plink"},
16789 +#endif
16790 +
16791 +       {Opt_udba, "udba=%s"},
16792 +
16793 +       {Opt_dio, "dio"},
16794 +       {Opt_nodio, "nodio"},
16795 +
16796 +       {Opt_diropq_a, "diropq=always"},
16797 +       {Opt_diropq_a, "diropq=a"},
16798 +       {Opt_diropq_w, "diropq=whiteouted"},
16799 +       {Opt_diropq_w, "diropq=w"},
16800 +
16801 +       {Opt_warn_perm, "warn_perm"},
16802 +       {Opt_nowarn_perm, "nowarn_perm"},
16803 +
16804 +       /* keep them temporary */
16805 +       {Opt_ignore_silent, "coo=%s"},
16806 +       {Opt_ignore_silent, "nodlgt"},
16807 +       {Opt_ignore_silent, "nodirperm1"},
16808 +       {Opt_ignore_silent, "clean_plink"},
16809 +
16810 +#ifdef CONFIG_AUFS_SHWH
16811 +       {Opt_shwh, "shwh"},
16812 +#endif
16813 +       {Opt_noshwh, "noshwh"},
16814 +
16815 +       {Opt_rendir, "rendir=%d"},
16816 +
16817 +       {Opt_refrof, "refrof"},
16818 +       {Opt_norefrof, "norefrof"},
16819 +
16820 +       {Opt_verbose, "verbose"},
16821 +       {Opt_verbose, "v"},
16822 +       {Opt_noverbose, "noverbose"},
16823 +       {Opt_noverbose, "quiet"},
16824 +       {Opt_noverbose, "q"},
16825 +       {Opt_noverbose, "silent"},
16826 +
16827 +       {Opt_sum, "sum"},
16828 +       {Opt_nosum, "nosum"},
16829 +       {Opt_wsum, "wsum"},
16830 +
16831 +       {Opt_rdcache, "rdcache=%d"},
16832 +       {Opt_rdblk, "rdblk=%d"},
16833 +       {Opt_rdblk_def, "rdblk=def"},
16834 +       {Opt_rdhash, "rdhash=%d"},
16835 +       {Opt_rdhash_def, "rdhash=def"},
16836 +
16837 +       {Opt_wbr_create, "create=%s"},
16838 +       {Opt_wbr_create, "create_policy=%s"},
16839 +       {Opt_wbr_copyup, "cpup=%s"},
16840 +       {Opt_wbr_copyup, "copyup=%s"},
16841 +       {Opt_wbr_copyup, "copyup_policy=%s"},
16842 +
16843 +       /* internal use for the scripts */
16844 +       {Opt_ignore_silent, "si=%s"},
16845 +
16846 +       {Opt_br, "dirs=%s"},
16847 +       {Opt_ignore, "debug=%d"},
16848 +       {Opt_ignore, "delete=whiteout"},
16849 +       {Opt_ignore, "delete=all"},
16850 +       {Opt_ignore, "imap=%s"},
16851 +
16852 +       /* temporary workaround, due to old mount(8)? */
16853 +       {Opt_ignore_silent, "relatime"},
16854 +
16855 +       {Opt_err, NULL}
16856 +};
16857 +
16858 +/* ---------------------------------------------------------------------- */
16859 +
16860 +static const char *au_parser_pattern(int val, struct match_token *token)
16861 +{
16862 +       while (token->pattern) {
16863 +               if (token->token == val)
16864 +                       return token->pattern;
16865 +               token++;
16866 +       }
16867 +       BUG();
16868 +       return "??";
16869 +}
16870 +
16871 +/* ---------------------------------------------------------------------- */
16872 +
16873 +static match_table_t brperms = {
16874 +       {AuBrPerm_RO, AUFS_BRPERM_RO},
16875 +       {AuBrPerm_RR, AUFS_BRPERM_RR},
16876 +       {AuBrPerm_RW, AUFS_BRPERM_RW},
16877 +
16878 +       {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
16879 +       {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
16880 +       {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
16881 +
16882 +       {AuBrPerm_ROWH, "nfsro"},
16883 +       {AuBrPerm_RO, NULL}
16884 +};
16885 +
16886 +static int noinline_for_stack br_perm_val(char *perm)
16887 +{
16888 +       int val;
16889 +       substring_t args[MAX_OPT_ARGS];
16890 +
16891 +       val = match_token(perm, brperms, args);
16892 +       return val;
16893 +}
16894 +
16895 +const char *au_optstr_br_perm(int brperm)
16896 +{
16897 +       return au_parser_pattern(brperm, (void *)brperms);
16898 +}
16899 +
16900 +/* ---------------------------------------------------------------------- */
16901 +
16902 +static match_table_t udbalevel = {
16903 +       {AuOpt_UDBA_REVAL, "reval"},
16904 +       {AuOpt_UDBA_NONE, "none"},
16905 +#ifdef CONFIG_AUFS_HNOTIFY
16906 +       {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
16907 +#ifdef CONFIG_AUFS_HFSNOTIFY
16908 +       {AuOpt_UDBA_HNOTIFY, "fsnotify"},
16909 +#endif
16910 +#endif
16911 +       {-1, NULL}
16912 +};
16913 +
16914 +static int noinline_for_stack udba_val(char *str)
16915 +{
16916 +       substring_t args[MAX_OPT_ARGS];
16917 +
16918 +       return match_token(str, udbalevel, args);
16919 +}
16920 +
16921 +const char *au_optstr_udba(int udba)
16922 +{
16923 +       return au_parser_pattern(udba, (void *)udbalevel);
16924 +}
16925 +
16926 +/* ---------------------------------------------------------------------- */
16927 +
16928 +static match_table_t au_wbr_create_policy = {
16929 +       {AuWbrCreate_TDP, "tdp"},
16930 +       {AuWbrCreate_TDP, "top-down-parent"},
16931 +       {AuWbrCreate_RR, "rr"},
16932 +       {AuWbrCreate_RR, "round-robin"},
16933 +       {AuWbrCreate_MFS, "mfs"},
16934 +       {AuWbrCreate_MFS, "most-free-space"},
16935 +       {AuWbrCreate_MFSV, "mfs:%d"},
16936 +       {AuWbrCreate_MFSV, "most-free-space:%d"},
16937 +
16938 +       {AuWbrCreate_MFSRR, "mfsrr:%d"},
16939 +       {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
16940 +       {AuWbrCreate_PMFS, "pmfs"},
16941 +       {AuWbrCreate_PMFSV, "pmfs:%d"},
16942 +
16943 +       {-1, NULL}
16944 +};
16945 +
16946 +/*
16947 + * cf. linux/lib/parser.c and cmdline.c
16948 + * gave up calling memparse() since it uses simple_strtoull() instead of
16949 + * strict_...().
16950 + */
16951 +static int noinline_for_stack
16952 +au_match_ull(substring_t *s, unsigned long long *result)
16953 +{
16954 +       int err;
16955 +       unsigned int len;
16956 +       char a[32];
16957 +
16958 +       err = -ERANGE;
16959 +       len = s->to - s->from;
16960 +       if (len + 1 <= sizeof(a)) {
16961 +               memcpy(a, s->from, len);
16962 +               a[len] = '\0';
16963 +               err = strict_strtoull(a, 0, result);
16964 +       }
16965 +       return err;
16966 +}
16967 +
16968 +static int au_wbr_mfs_wmark(substring_t *arg, char *str,
16969 +                           struct au_opt_wbr_create *create)
16970 +{
16971 +       int err;
16972 +       unsigned long long ull;
16973 +
16974 +       err = 0;
16975 +       if (!au_match_ull(arg, &ull))
16976 +               create->mfsrr_watermark = ull;
16977 +       else {
16978 +               pr_err("bad integer in %s\n", str);
16979 +               err = -EINVAL;
16980 +       }
16981 +
16982 +       return err;
16983 +}
16984 +
16985 +static int au_wbr_mfs_sec(substring_t *arg, char *str,
16986 +                         struct au_opt_wbr_create *create)
16987 +{
16988 +       int n, err;
16989 +
16990 +       err = 0;
16991 +       if (!match_int(arg, &n) && 0 <= n)
16992 +               create->mfs_second = n;
16993 +       else {
16994 +               pr_err("bad integer in %s\n", str);
16995 +               err = -EINVAL;
16996 +       }
16997 +
16998 +       return err;
16999 +}
17000 +
17001 +static int noinline_for_stack
17002 +au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
17003 +{
17004 +       int err, e;
17005 +       substring_t args[MAX_OPT_ARGS];
17006 +
17007 +       err = match_token(str, au_wbr_create_policy, args);
17008 +       create->wbr_create = err;
17009 +       switch (err) {
17010 +       case AuWbrCreate_MFSRRV:
17011 +               e = au_wbr_mfs_wmark(&args[0], str, create);
17012 +               if (!e)
17013 +                       e = au_wbr_mfs_sec(&args[1], str, create);
17014 +               if (unlikely(e))
17015 +                       err = e;
17016 +               break;
17017 +       case AuWbrCreate_MFSRR:
17018 +               e = au_wbr_mfs_wmark(&args[0], str, create);
17019 +               if (unlikely(e)) {
17020 +                       err = e;
17021 +                       break;
17022 +               }
17023 +               /*FALLTHROUGH*/
17024 +       case AuWbrCreate_MFS:
17025 +       case AuWbrCreate_PMFS:
17026 +               create->mfs_second = AUFS_MFS_SECOND_DEF;
17027 +               break;
17028 +       case AuWbrCreate_MFSV:
17029 +       case AuWbrCreate_PMFSV:
17030 +               e = au_wbr_mfs_sec(&args[0], str, create);
17031 +               if (unlikely(e))
17032 +                       err = e;
17033 +               break;
17034 +       }
17035 +
17036 +       return err;
17037 +}
17038 +
17039 +const char *au_optstr_wbr_create(int wbr_create)
17040 +{
17041 +       return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
17042 +}
17043 +
17044 +static match_table_t au_wbr_copyup_policy = {
17045 +       {AuWbrCopyup_TDP, "tdp"},
17046 +       {AuWbrCopyup_TDP, "top-down-parent"},
17047 +       {AuWbrCopyup_BUP, "bup"},
17048 +       {AuWbrCopyup_BUP, "bottom-up-parent"},
17049 +       {AuWbrCopyup_BU, "bu"},
17050 +       {AuWbrCopyup_BU, "bottom-up"},
17051 +       {-1, NULL}
17052 +};
17053 +
17054 +static int noinline_for_stack au_wbr_copyup_val(char *str)
17055 +{
17056 +       substring_t args[MAX_OPT_ARGS];
17057 +
17058 +       return match_token(str, au_wbr_copyup_policy, args);
17059 +}
17060 +
17061 +const char *au_optstr_wbr_copyup(int wbr_copyup)
17062 +{
17063 +       return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
17064 +}
17065 +
17066 +/* ---------------------------------------------------------------------- */
17067 +
17068 +static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
17069 +
17070 +static void dump_opts(struct au_opts *opts)
17071 +{
17072 +#ifdef CONFIG_AUFS_DEBUG
17073 +       /* reduce stack space */
17074 +       union {
17075 +               struct au_opt_add *add;
17076 +               struct au_opt_del *del;
17077 +               struct au_opt_mod *mod;
17078 +               struct au_opt_xino *xino;
17079 +               struct au_opt_xino_itrunc *xino_itrunc;
17080 +               struct au_opt_wbr_create *create;
17081 +       } u;
17082 +       struct au_opt *opt;
17083 +
17084 +       opt = opts->opt;
17085 +       while (opt->type != Opt_tail) {
17086 +               switch (opt->type) {
17087 +               case Opt_add:
17088 +                       u.add = &opt->add;
17089 +                       AuDbg("add {b%d, %s, 0x%x, %p}\n",
17090 +                                 u.add->bindex, u.add->pathname, u.add->perm,
17091 +                                 u.add->path.dentry);
17092 +                       break;
17093 +               case Opt_del:
17094 +               case Opt_idel:
17095 +                       u.del = &opt->del;
17096 +                       AuDbg("del {%s, %p}\n",
17097 +                             u.del->pathname, u.del->h_path.dentry);
17098 +                       break;
17099 +               case Opt_mod:
17100 +               case Opt_imod:
17101 +                       u.mod = &opt->mod;
17102 +                       AuDbg("mod {%s, 0x%x, %p}\n",
17103 +                                 u.mod->path, u.mod->perm, u.mod->h_root);
17104 +                       break;
17105 +               case Opt_append:
17106 +                       u.add = &opt->add;
17107 +                       AuDbg("append {b%d, %s, 0x%x, %p}\n",
17108 +                                 u.add->bindex, u.add->pathname, u.add->perm,
17109 +                                 u.add->path.dentry);
17110 +                       break;
17111 +               case Opt_prepend:
17112 +                       u.add = &opt->add;
17113 +                       AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
17114 +                                 u.add->bindex, u.add->pathname, u.add->perm,
17115 +                                 u.add->path.dentry);
17116 +                       break;
17117 +               case Opt_dirwh:
17118 +                       AuDbg("dirwh %d\n", opt->dirwh);
17119 +                       break;
17120 +               case Opt_rdcache:
17121 +                       AuDbg("rdcache %d\n", opt->rdcache);
17122 +                       break;
17123 +               case Opt_rdblk:
17124 +                       AuDbg("rdblk %u\n", opt->rdblk);
17125 +                       break;
17126 +               case Opt_rdblk_def:
17127 +                       AuDbg("rdblk_def\n");
17128 +                       break;
17129 +               case Opt_rdhash:
17130 +                       AuDbg("rdhash %u\n", opt->rdhash);
17131 +                       break;
17132 +               case Opt_rdhash_def:
17133 +                       AuDbg("rdhash_def\n");
17134 +                       break;
17135 +               case Opt_xino:
17136 +                       u.xino = &opt->xino;
17137 +                       AuDbg("xino {%s %.*s}\n",
17138 +                                 u.xino->path,
17139 +                                 AuDLNPair(u.xino->file->f_dentry));
17140 +                       break;
17141 +               case Opt_trunc_xino:
17142 +                       AuLabel(trunc_xino);
17143 +                       break;
17144 +               case Opt_notrunc_xino:
17145 +                       AuLabel(notrunc_xino);
17146 +                       break;
17147 +               case Opt_trunc_xino_path:
17148 +               case Opt_itrunc_xino:
17149 +                       u.xino_itrunc = &opt->xino_itrunc;
17150 +                       AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
17151 +                       break;
17152 +
17153 +               case Opt_noxino:
17154 +                       AuLabel(noxino);
17155 +                       break;
17156 +               case Opt_trunc_xib:
17157 +                       AuLabel(trunc_xib);
17158 +                       break;
17159 +               case Opt_notrunc_xib:
17160 +                       AuLabel(notrunc_xib);
17161 +                       break;
17162 +               case Opt_shwh:
17163 +                       AuLabel(shwh);
17164 +                       break;
17165 +               case Opt_noshwh:
17166 +                       AuLabel(noshwh);
17167 +                       break;
17168 +               case Opt_plink:
17169 +                       AuLabel(plink);
17170 +                       break;
17171 +               case Opt_noplink:
17172 +                       AuLabel(noplink);
17173 +                       break;
17174 +               case Opt_list_plink:
17175 +                       AuLabel(list_plink);
17176 +                       break;
17177 +               case Opt_udba:
17178 +                       AuDbg("udba %d, %s\n",
17179 +                                 opt->udba, au_optstr_udba(opt->udba));
17180 +                       break;
17181 +               case Opt_dio:
17182 +                       AuLabel(dio);
17183 +                       break;
17184 +               case Opt_nodio:
17185 +                       AuLabel(nodio);
17186 +                       break;
17187 +               case Opt_diropq_a:
17188 +                       AuLabel(diropq_a);
17189 +                       break;
17190 +               case Opt_diropq_w:
17191 +                       AuLabel(diropq_w);
17192 +                       break;
17193 +               case Opt_warn_perm:
17194 +                       AuLabel(warn_perm);
17195 +                       break;
17196 +               case Opt_nowarn_perm:
17197 +                       AuLabel(nowarn_perm);
17198 +                       break;
17199 +               case Opt_refrof:
17200 +                       AuLabel(refrof);
17201 +                       break;
17202 +               case Opt_norefrof:
17203 +                       AuLabel(norefrof);
17204 +                       break;
17205 +               case Opt_verbose:
17206 +                       AuLabel(verbose);
17207 +                       break;
17208 +               case Opt_noverbose:
17209 +                       AuLabel(noverbose);
17210 +                       break;
17211 +               case Opt_sum:
17212 +                       AuLabel(sum);
17213 +                       break;
17214 +               case Opt_nosum:
17215 +                       AuLabel(nosum);
17216 +                       break;
17217 +               case Opt_wsum:
17218 +                       AuLabel(wsum);
17219 +                       break;
17220 +               case Opt_wbr_create:
17221 +                       u.create = &opt->wbr_create;
17222 +                       AuDbg("create %d, %s\n", u.create->wbr_create,
17223 +                                 au_optstr_wbr_create(u.create->wbr_create));
17224 +                       switch (u.create->wbr_create) {
17225 +                       case AuWbrCreate_MFSV:
17226 +                       case AuWbrCreate_PMFSV:
17227 +                               AuDbg("%d sec\n", u.create->mfs_second);
17228 +                               break;
17229 +                       case AuWbrCreate_MFSRR:
17230 +                               AuDbg("%llu watermark\n",
17231 +                                         u.create->mfsrr_watermark);
17232 +                               break;
17233 +                       case AuWbrCreate_MFSRRV:
17234 +                               AuDbg("%llu watermark, %d sec\n",
17235 +                                         u.create->mfsrr_watermark,
17236 +                                         u.create->mfs_second);
17237 +                               break;
17238 +                       }
17239 +                       break;
17240 +               case Opt_wbr_copyup:
17241 +                       AuDbg("copyup %d, %s\n", opt->wbr_copyup,
17242 +                                 au_optstr_wbr_copyup(opt->wbr_copyup));
17243 +                       break;
17244 +               default:
17245 +                       BUG();
17246 +               }
17247 +               opt++;
17248 +       }
17249 +#endif
17250 +}
17251 +
17252 +void au_opts_free(struct au_opts *opts)
17253 +{
17254 +       struct au_opt *opt;
17255 +
17256 +       opt = opts->opt;
17257 +       while (opt->type != Opt_tail) {
17258 +               switch (opt->type) {
17259 +               case Opt_add:
17260 +               case Opt_append:
17261 +               case Opt_prepend:
17262 +                       path_put(&opt->add.path);
17263 +                       break;
17264 +               case Opt_del:
17265 +               case Opt_idel:
17266 +                       path_put(&opt->del.h_path);
17267 +                       break;
17268 +               case Opt_mod:
17269 +               case Opt_imod:
17270 +                       dput(opt->mod.h_root);
17271 +                       break;
17272 +               case Opt_xino:
17273 +                       fput(opt->xino.file);
17274 +                       break;
17275 +               }
17276 +               opt++;
17277 +       }
17278 +}
17279 +
17280 +static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
17281 +                  aufs_bindex_t bindex)
17282 +{
17283 +       int err;
17284 +       struct au_opt_add *add = &opt->add;
17285 +       char *p;
17286 +
17287 +       add->bindex = bindex;
17288 +       add->perm = AuBrPerm_Last;
17289 +       add->pathname = opt_str;
17290 +       p = strchr(opt_str, '=');
17291 +       if (p) {
17292 +               *p++ = 0;
17293 +               if (*p)
17294 +                       add->perm = br_perm_val(p);
17295 +       }
17296 +
17297 +       err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
17298 +       if (!err) {
17299 +               if (!p) {
17300 +                       add->perm = AuBrPerm_RO;
17301 +                       if (au_test_fs_rr(add->path.dentry->d_sb))
17302 +                               add->perm = AuBrPerm_RR;
17303 +                       else if (!bindex && !(sb_flags & MS_RDONLY))
17304 +                               add->perm = AuBrPerm_RW;
17305 +               }
17306 +               opt->type = Opt_add;
17307 +               goto out;
17308 +       }
17309 +       pr_err("lookup failed %s (%d)\n", add->pathname, err);
17310 +       err = -EINVAL;
17311 +
17312 +out:
17313 +       return err;
17314 +}
17315 +
17316 +static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
17317 +{
17318 +       int err;
17319 +
17320 +       del->pathname = args[0].from;
17321 +       AuDbg("del path %s\n", del->pathname);
17322 +
17323 +       err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
17324 +       if (unlikely(err))
17325 +               pr_err("lookup failed %s (%d)\n", del->pathname, err);
17326 +
17327 +       return err;
17328 +}
17329 +
17330 +#if 0 /* reserved for future use */
17331 +static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
17332 +                             struct au_opt_del *del, substring_t args[])
17333 +{
17334 +       int err;
17335 +       struct dentry *root;
17336 +
17337 +       err = -EINVAL;
17338 +       root = sb->s_root;
17339 +       aufs_read_lock(root, AuLock_FLUSH);
17340 +       if (bindex < 0 || au_sbend(sb) < bindex) {
17341 +               pr_err("out of bounds, %d\n", bindex);
17342 +               goto out;
17343 +       }
17344 +
17345 +       err = 0;
17346 +       del->h_path.dentry = dget(au_h_dptr(root, bindex));
17347 +       del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
17348 +
17349 +out:
17350 +       aufs_read_unlock(root, !AuLock_IR);
17351 +       return err;
17352 +}
17353 +#endif
17354 +
17355 +static int noinline_for_stack
17356 +au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
17357 +{
17358 +       int err;
17359 +       struct path path;
17360 +       char *p;
17361 +
17362 +       err = -EINVAL;
17363 +       mod->path = args[0].from;
17364 +       p = strchr(mod->path, '=');
17365 +       if (unlikely(!p)) {
17366 +               pr_err("no permssion %s\n", args[0].from);
17367 +               goto out;
17368 +       }
17369 +
17370 +       *p++ = 0;
17371 +       err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
17372 +       if (unlikely(err)) {
17373 +               pr_err("lookup failed %s (%d)\n", mod->path, err);
17374 +               goto out;
17375 +       }
17376 +
17377 +       mod->perm = br_perm_val(p);
17378 +       AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
17379 +       mod->h_root = dget(path.dentry);
17380 +       path_put(&path);
17381 +
17382 +out:
17383 +       return err;
17384 +}
17385 +
17386 +#if 0 /* reserved for future use */
17387 +static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
17388 +                             struct au_opt_mod *mod, substring_t args[])
17389 +{
17390 +       int err;
17391 +       struct dentry *root;
17392 +
17393 +       err = -EINVAL;
17394 +       root = sb->s_root;
17395 +       aufs_read_lock(root, AuLock_FLUSH);
17396 +       if (bindex < 0 || au_sbend(sb) < bindex) {
17397 +               pr_err("out of bounds, %d\n", bindex);
17398 +               goto out;
17399 +       }
17400 +
17401 +       err = 0;
17402 +       mod->perm = br_perm_val(args[1].from);
17403 +       AuDbg("mod path %s, perm 0x%x, %s\n",
17404 +             mod->path, mod->perm, args[1].from);
17405 +       mod->h_root = dget(au_h_dptr(root, bindex));
17406 +
17407 +out:
17408 +       aufs_read_unlock(root, !AuLock_IR);
17409 +       return err;
17410 +}
17411 +#endif
17412 +
17413 +static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
17414 +                             substring_t args[])
17415 +{
17416 +       int err;
17417 +       struct file *file;
17418 +
17419 +       file = au_xino_create(sb, args[0].from, /*silent*/0);
17420 +       err = PTR_ERR(file);
17421 +       if (IS_ERR(file))
17422 +               goto out;
17423 +
17424 +       err = -EINVAL;
17425 +       if (unlikely(file->f_dentry->d_sb == sb)) {
17426 +               fput(file);
17427 +               pr_err("%s must be outside\n", args[0].from);
17428 +               goto out;
17429 +       }
17430 +
17431 +       err = 0;
17432 +       xino->file = file;
17433 +       xino->path = args[0].from;
17434 +
17435 +out:
17436 +       return err;
17437 +}
17438 +
17439 +static int noinline_for_stack
17440 +au_opts_parse_xino_itrunc_path(struct super_block *sb,
17441 +                              struct au_opt_xino_itrunc *xino_itrunc,
17442 +                              substring_t args[])
17443 +{
17444 +       int err;
17445 +       aufs_bindex_t bend, bindex;
17446 +       struct path path;
17447 +       struct dentry *root;
17448 +
17449 +       err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
17450 +       if (unlikely(err)) {
17451 +               pr_err("lookup failed %s (%d)\n", args[0].from, err);
17452 +               goto out;
17453 +       }
17454 +
17455 +       xino_itrunc->bindex = -1;
17456 +       root = sb->s_root;
17457 +       aufs_read_lock(root, AuLock_FLUSH);
17458 +       bend = au_sbend(sb);
17459 +       for (bindex = 0; bindex <= bend; bindex++) {
17460 +               if (au_h_dptr(root, bindex) == path.dentry) {
17461 +                       xino_itrunc->bindex = bindex;
17462 +                       break;
17463 +               }
17464 +       }
17465 +       aufs_read_unlock(root, !AuLock_IR);
17466 +       path_put(&path);
17467 +
17468 +       if (unlikely(xino_itrunc->bindex < 0)) {
17469 +               pr_err("no such branch %s\n", args[0].from);
17470 +               err = -EINVAL;
17471 +       }
17472 +
17473 +out:
17474 +       return err;
17475 +}
17476 +
17477 +/* called without aufs lock */
17478 +int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
17479 +{
17480 +       int err, n, token;
17481 +       aufs_bindex_t bindex;
17482 +       unsigned char skipped;
17483 +       struct dentry *root;
17484 +       struct au_opt *opt, *opt_tail;
17485 +       char *opt_str;
17486 +       /* reduce the stack space */
17487 +       union {
17488 +               struct au_opt_xino_itrunc *xino_itrunc;
17489 +               struct au_opt_wbr_create *create;
17490 +       } u;
17491 +       struct {
17492 +               substring_t args[MAX_OPT_ARGS];
17493 +       } *a;
17494 +
17495 +       err = -ENOMEM;
17496 +       a = kmalloc(sizeof(*a), GFP_NOFS);
17497 +       if (unlikely(!a))
17498 +               goto out;
17499 +
17500 +       root = sb->s_root;
17501 +       err = 0;
17502 +       bindex = 0;
17503 +       opt = opts->opt;
17504 +       opt_tail = opt + opts->max_opt - 1;
17505 +       opt->type = Opt_tail;
17506 +       while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
17507 +               err = -EINVAL;
17508 +               skipped = 0;
17509 +               token = match_token(opt_str, options, a->args);
17510 +               switch (token) {
17511 +               case Opt_br:
17512 +                       err = 0;
17513 +                       while (!err && (opt_str = strsep(&a->args[0].from, ":"))
17514 +                              && *opt_str) {
17515 +                               err = opt_add(opt, opt_str, opts->sb_flags,
17516 +                                             bindex++);
17517 +                               if (unlikely(!err && ++opt > opt_tail)) {
17518 +                                       err = -E2BIG;
17519 +                                       break;
17520 +                               }
17521 +                               opt->type = Opt_tail;
17522 +                               skipped = 1;
17523 +                       }
17524 +                       break;
17525 +               case Opt_add:
17526 +                       if (unlikely(match_int(&a->args[0], &n))) {
17527 +                               pr_err("bad integer in %s\n", opt_str);
17528 +                               break;
17529 +                       }
17530 +                       bindex = n;
17531 +                       err = opt_add(opt, a->args[1].from, opts->sb_flags,
17532 +                                     bindex);
17533 +                       if (!err)
17534 +                               opt->type = token;
17535 +                       break;
17536 +               case Opt_append:
17537 +                       err = opt_add(opt, a->args[0].from, opts->sb_flags,
17538 +                                     /*dummy bindex*/1);
17539 +                       if (!err)
17540 +                               opt->type = token;
17541 +                       break;
17542 +               case Opt_prepend:
17543 +                       err = opt_add(opt, a->args[0].from, opts->sb_flags,
17544 +                                     /*bindex*/0);
17545 +                       if (!err)
17546 +                               opt->type = token;
17547 +                       break;
17548 +               case Opt_del:
17549 +                       err = au_opts_parse_del(&opt->del, a->args);
17550 +                       if (!err)
17551 +                               opt->type = token;
17552 +                       break;
17553 +#if 0 /* reserved for future use */
17554 +               case Opt_idel:
17555 +                       del->pathname = "(indexed)";
17556 +                       if (unlikely(match_int(&args[0], &n))) {
17557 +                               pr_err("bad integer in %s\n", opt_str);
17558 +                               break;
17559 +                       }
17560 +                       err = au_opts_parse_idel(sb, n, &opt->del, a->args);
17561 +                       if (!err)
17562 +                               opt->type = token;
17563 +                       break;
17564 +#endif
17565 +               case Opt_mod:
17566 +                       err = au_opts_parse_mod(&opt->mod, a->args);
17567 +                       if (!err)
17568 +                               opt->type = token;
17569 +                       break;
17570 +#ifdef IMOD /* reserved for future use */
17571 +               case Opt_imod:
17572 +                       u.mod->path = "(indexed)";
17573 +                       if (unlikely(match_int(&a->args[0], &n))) {
17574 +                               pr_err("bad integer in %s\n", opt_str);
17575 +                               break;
17576 +                       }
17577 +                       err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
17578 +                       if (!err)
17579 +                               opt->type = token;
17580 +                       break;
17581 +#endif
17582 +               case Opt_xino:
17583 +                       err = au_opts_parse_xino(sb, &opt->xino, a->args);
17584 +                       if (!err)
17585 +                               opt->type = token;
17586 +                       break;
17587 +
17588 +               case Opt_trunc_xino_path:
17589 +                       err = au_opts_parse_xino_itrunc_path
17590 +                               (sb, &opt->xino_itrunc, a->args);
17591 +                       if (!err)
17592 +                               opt->type = token;
17593 +                       break;
17594 +
17595 +               case Opt_itrunc_xino:
17596 +                       u.xino_itrunc = &opt->xino_itrunc;
17597 +                       if (unlikely(match_int(&a->args[0], &n))) {
17598 +                               pr_err("bad integer in %s\n", opt_str);
17599 +                               break;
17600 +                       }
17601 +                       u.xino_itrunc->bindex = n;
17602 +                       aufs_read_lock(root, AuLock_FLUSH);
17603 +                       if (n < 0 || au_sbend(sb) < n) {
17604 +                               pr_err("out of bounds, %d\n", n);
17605 +                               aufs_read_unlock(root, !AuLock_IR);
17606 +                               break;
17607 +                       }
17608 +                       aufs_read_unlock(root, !AuLock_IR);
17609 +                       err = 0;
17610 +                       opt->type = token;
17611 +                       break;
17612 +
17613 +               case Opt_dirwh:
17614 +                       if (unlikely(match_int(&a->args[0], &opt->dirwh)))
17615 +                               break;
17616 +                       err = 0;
17617 +                       opt->type = token;
17618 +                       break;
17619 +
17620 +               case Opt_rdcache:
17621 +                       if (unlikely(match_int(&a->args[0], &opt->rdcache)))
17622 +                               break;
17623 +                       err = 0;
17624 +                       opt->type = token;
17625 +                       break;
17626 +               case Opt_rdblk:
17627 +                       if (unlikely(match_int(&a->args[0], &n)
17628 +                                    || n < 0
17629 +                                    || n > KMALLOC_MAX_SIZE)) {
17630 +                               pr_err("bad integer in %s\n", opt_str);
17631 +                               break;
17632 +                       }
17633 +                       if (unlikely(n && n < NAME_MAX)) {
17634 +                               pr_err("rdblk must be larger than %d\n",
17635 +                                      NAME_MAX);
17636 +                               break;
17637 +                       }
17638 +                       opt->rdblk = n;
17639 +                       err = 0;
17640 +                       opt->type = token;
17641 +                       break;
17642 +               case Opt_rdhash:
17643 +                       if (unlikely(match_int(&a->args[0], &n)
17644 +                                    || n < 0
17645 +                                    || n * sizeof(struct hlist_head)
17646 +                                    > KMALLOC_MAX_SIZE)) {
17647 +                               pr_err("bad integer in %s\n", opt_str);
17648 +                               break;
17649 +                       }
17650 +                       opt->rdhash = n;
17651 +                       err = 0;
17652 +                       opt->type = token;
17653 +                       break;
17654 +
17655 +               case Opt_trunc_xino:
17656 +               case Opt_notrunc_xino:
17657 +               case Opt_noxino:
17658 +               case Opt_trunc_xib:
17659 +               case Opt_notrunc_xib:
17660 +               case Opt_shwh:
17661 +               case Opt_noshwh:
17662 +               case Opt_plink:
17663 +               case Opt_noplink:
17664 +               case Opt_list_plink:
17665 +               case Opt_dio:
17666 +               case Opt_nodio:
17667 +               case Opt_diropq_a:
17668 +               case Opt_diropq_w:
17669 +               case Opt_warn_perm:
17670 +               case Opt_nowarn_perm:
17671 +               case Opt_refrof:
17672 +               case Opt_norefrof:
17673 +               case Opt_verbose:
17674 +               case Opt_noverbose:
17675 +               case Opt_sum:
17676 +               case Opt_nosum:
17677 +               case Opt_wsum:
17678 +               case Opt_rdblk_def:
17679 +               case Opt_rdhash_def:
17680 +                       err = 0;
17681 +                       opt->type = token;
17682 +                       break;
17683 +
17684 +               case Opt_udba:
17685 +                       opt->udba = udba_val(a->args[0].from);
17686 +                       if (opt->udba >= 0) {
17687 +                               err = 0;
17688 +                               opt->type = token;
17689 +                       } else
17690 +                               pr_err("wrong value, %s\n", opt_str);
17691 +                       break;
17692 +
17693 +               case Opt_wbr_create:
17694 +                       u.create = &opt->wbr_create;
17695 +                       u.create->wbr_create
17696 +                               = au_wbr_create_val(a->args[0].from, u.create);
17697 +                       if (u.create->wbr_create >= 0) {
17698 +                               err = 0;
17699 +                               opt->type = token;
17700 +                       } else
17701 +                               pr_err("wrong value, %s\n", opt_str);
17702 +                       break;
17703 +               case Opt_wbr_copyup:
17704 +                       opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
17705 +                       if (opt->wbr_copyup >= 0) {
17706 +                               err = 0;
17707 +                               opt->type = token;
17708 +                       } else
17709 +                               pr_err("wrong value, %s\n", opt_str);
17710 +                       break;
17711 +
17712 +               case Opt_ignore:
17713 +                       pr_warning("ignored %s\n", opt_str);
17714 +                       /*FALLTHROUGH*/
17715 +               case Opt_ignore_silent:
17716 +                       skipped = 1;
17717 +                       err = 0;
17718 +                       break;
17719 +               case Opt_err:
17720 +                       pr_err("unknown option %s\n", opt_str);
17721 +                       break;
17722 +               }
17723 +
17724 +               if (!err && !skipped) {
17725 +                       if (unlikely(++opt > opt_tail)) {
17726 +                               err = -E2BIG;
17727 +                               opt--;
17728 +                               opt->type = Opt_tail;
17729 +                               break;
17730 +                       }
17731 +                       opt->type = Opt_tail;
17732 +               }
17733 +       }
17734 +
17735 +       kfree(a);
17736 +       dump_opts(opts);
17737 +       if (unlikely(err))
17738 +               au_opts_free(opts);
17739 +
17740 +out:
17741 +       return err;
17742 +}
17743 +
17744 +static int au_opt_wbr_create(struct super_block *sb,
17745 +                            struct au_opt_wbr_create *create)
17746 +{
17747 +       int err;
17748 +       struct au_sbinfo *sbinfo;
17749 +
17750 +       SiMustWriteLock(sb);
17751 +
17752 +       err = 1; /* handled */
17753 +       sbinfo = au_sbi(sb);
17754 +       if (sbinfo->si_wbr_create_ops->fin) {
17755 +               err = sbinfo->si_wbr_create_ops->fin(sb);
17756 +               if (!err)
17757 +                       err = 1;
17758 +       }
17759 +
17760 +       sbinfo->si_wbr_create = create->wbr_create;
17761 +       sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
17762 +       switch (create->wbr_create) {
17763 +       case AuWbrCreate_MFSRRV:
17764 +       case AuWbrCreate_MFSRR:
17765 +               sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
17766 +               /*FALLTHROUGH*/
17767 +       case AuWbrCreate_MFS:
17768 +       case AuWbrCreate_MFSV:
17769 +       case AuWbrCreate_PMFS:
17770 +       case AuWbrCreate_PMFSV:
17771 +               sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
17772 +               break;
17773 +       }
17774 +
17775 +       if (sbinfo->si_wbr_create_ops->init)
17776 +               sbinfo->si_wbr_create_ops->init(sb); /* ignore */
17777 +
17778 +       return err;
17779 +}
17780 +
17781 +/*
17782 + * returns,
17783 + * plus: processed without an error
17784 + * zero: unprocessed
17785 + */
17786 +static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
17787 +                        struct au_opts *opts)
17788 +{
17789 +       int err;
17790 +       struct au_sbinfo *sbinfo;
17791 +
17792 +       SiMustWriteLock(sb);
17793 +
17794 +       err = 1; /* handled */
17795 +       sbinfo = au_sbi(sb);
17796 +       switch (opt->type) {
17797 +       case Opt_udba:
17798 +               sbinfo->si_mntflags &= ~AuOptMask_UDBA;
17799 +               sbinfo->si_mntflags |= opt->udba;
17800 +               opts->given_udba |= opt->udba;
17801 +               break;
17802 +
17803 +       case Opt_plink:
17804 +               au_opt_set(sbinfo->si_mntflags, PLINK);
17805 +               break;
17806 +       case Opt_noplink:
17807 +               if (au_opt_test(sbinfo->si_mntflags, PLINK))
17808 +                       au_plink_put(sb);
17809 +               au_opt_clr(sbinfo->si_mntflags, PLINK);
17810 +               break;
17811 +       case Opt_list_plink:
17812 +               if (au_opt_test(sbinfo->si_mntflags, PLINK))
17813 +                       au_plink_list(sb);
17814 +               break;
17815 +
17816 +       case Opt_dio:
17817 +               au_opt_set(sbinfo->si_mntflags, DIO);
17818 +               au_fset_opts(opts->flags, REFRESH_DYAOP);
17819 +               break;
17820 +       case Opt_nodio:
17821 +               au_opt_clr(sbinfo->si_mntflags, DIO);
17822 +               au_fset_opts(opts->flags, REFRESH_DYAOP);
17823 +               break;
17824 +
17825 +       case Opt_diropq_a:
17826 +               au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
17827 +               break;
17828 +       case Opt_diropq_w:
17829 +               au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
17830 +               break;
17831 +
17832 +       case Opt_warn_perm:
17833 +               au_opt_set(sbinfo->si_mntflags, WARN_PERM);
17834 +               break;
17835 +       case Opt_nowarn_perm:
17836 +               au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
17837 +               break;
17838 +
17839 +       case Opt_refrof:
17840 +               au_opt_set(sbinfo->si_mntflags, REFROF);
17841 +               break;
17842 +       case Opt_norefrof:
17843 +               au_opt_clr(sbinfo->si_mntflags, REFROF);
17844 +               break;
17845 +
17846 +       case Opt_verbose:
17847 +               au_opt_set(sbinfo->si_mntflags, VERBOSE);
17848 +               break;
17849 +       case Opt_noverbose:
17850 +               au_opt_clr(sbinfo->si_mntflags, VERBOSE);
17851 +               break;
17852 +
17853 +       case Opt_sum:
17854 +               au_opt_set(sbinfo->si_mntflags, SUM);
17855 +               break;
17856 +       case Opt_wsum:
17857 +               au_opt_clr(sbinfo->si_mntflags, SUM);
17858 +               au_opt_set(sbinfo->si_mntflags, SUM_W);
17859 +       case Opt_nosum:
17860 +               au_opt_clr(sbinfo->si_mntflags, SUM);
17861 +               au_opt_clr(sbinfo->si_mntflags, SUM_W);
17862 +               break;
17863 +
17864 +       case Opt_wbr_create:
17865 +               err = au_opt_wbr_create(sb, &opt->wbr_create);
17866 +               break;
17867 +       case Opt_wbr_copyup:
17868 +               sbinfo->si_wbr_copyup = opt->wbr_copyup;
17869 +               sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
17870 +               break;
17871 +
17872 +       case Opt_dirwh:
17873 +               sbinfo->si_dirwh = opt->dirwh;
17874 +               break;
17875 +
17876 +       case Opt_rdcache:
17877 +               sbinfo->si_rdcache = opt->rdcache * HZ;
17878 +               break;
17879 +       case Opt_rdblk:
17880 +               sbinfo->si_rdblk = opt->rdblk;
17881 +               break;
17882 +       case Opt_rdblk_def:
17883 +               sbinfo->si_rdblk = AUFS_RDBLK_DEF;
17884 +               break;
17885 +       case Opt_rdhash:
17886 +               sbinfo->si_rdhash = opt->rdhash;
17887 +               break;
17888 +       case Opt_rdhash_def:
17889 +               sbinfo->si_rdhash = AUFS_RDHASH_DEF;
17890 +               break;
17891 +
17892 +       case Opt_shwh:
17893 +               au_opt_set(sbinfo->si_mntflags, SHWH);
17894 +               break;
17895 +       case Opt_noshwh:
17896 +               au_opt_clr(sbinfo->si_mntflags, SHWH);
17897 +               break;
17898 +
17899 +       case Opt_trunc_xino:
17900 +               au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
17901 +               break;
17902 +       case Opt_notrunc_xino:
17903 +               au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
17904 +               break;
17905 +
17906 +       case Opt_trunc_xino_path:
17907 +       case Opt_itrunc_xino:
17908 +               err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
17909 +               if (!err)
17910 +                       err = 1;
17911 +               break;
17912 +
17913 +       case Opt_trunc_xib:
17914 +               au_fset_opts(opts->flags, TRUNC_XIB);
17915 +               break;
17916 +       case Opt_notrunc_xib:
17917 +               au_fclr_opts(opts->flags, TRUNC_XIB);
17918 +               break;
17919 +
17920 +       default:
17921 +               err = 0;
17922 +               break;
17923 +       }
17924 +
17925 +       return err;
17926 +}
17927 +
17928 +/*
17929 + * returns tri-state.
17930 + * plus: processed without an error
17931 + * zero: unprocessed
17932 + * minus: error
17933 + */
17934 +static int au_opt_br(struct super_block *sb, struct au_opt *opt,
17935 +                    struct au_opts *opts)
17936 +{
17937 +       int err, do_refresh;
17938 +
17939 +       err = 0;
17940 +       switch (opt->type) {
17941 +       case Opt_append:
17942 +               opt->add.bindex = au_sbend(sb) + 1;
17943 +               if (opt->add.bindex < 0)
17944 +                       opt->add.bindex = 0;
17945 +               goto add;
17946 +       case Opt_prepend:
17947 +               opt->add.bindex = 0;
17948 +       add:
17949 +       case Opt_add:
17950 +               err = au_br_add(sb, &opt->add,
17951 +                               au_ftest_opts(opts->flags, REMOUNT));
17952 +               if (!err) {
17953 +                       err = 1;
17954 +                       au_fset_opts(opts->flags, REFRESH_DIR);
17955 +                       au_fset_opts(opts->flags, REFRESH_NONDIR);
17956 +               }
17957 +               break;
17958 +
17959 +       case Opt_del:
17960 +       case Opt_idel:
17961 +               err = au_br_del(sb, &opt->del,
17962 +                               au_ftest_opts(opts->flags, REMOUNT));
17963 +               if (!err) {
17964 +                       err = 1;
17965 +                       au_fset_opts(opts->flags, TRUNC_XIB);
17966 +                       au_fset_opts(opts->flags, REFRESH_DIR);
17967 +                       au_fset_opts(opts->flags, REFRESH_NONDIR);
17968 +               }
17969 +               break;
17970 +
17971 +       case Opt_mod:
17972 +       case Opt_imod:
17973 +               err = au_br_mod(sb, &opt->mod,
17974 +                               au_ftest_opts(opts->flags, REMOUNT),
17975 +                               &do_refresh);
17976 +               if (!err) {
17977 +                       err = 1;
17978 +                       if (do_refresh) {
17979 +                               au_fset_opts(opts->flags, REFRESH_DIR);
17980 +                               au_fset_opts(opts->flags, REFRESH_NONDIR);
17981 +                       }
17982 +               }
17983 +               break;
17984 +       }
17985 +
17986 +       return err;
17987 +}
17988 +
17989 +static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
17990 +                      struct au_opt_xino **opt_xino,
17991 +                      struct au_opts *opts)
17992 +{
17993 +       int err;
17994 +       aufs_bindex_t bend, bindex;
17995 +       struct dentry *root, *parent, *h_root;
17996 +
17997 +       err = 0;
17998 +       switch (opt->type) {
17999 +       case Opt_xino:
18000 +               err = au_xino_set(sb, &opt->xino,
18001 +                                 !!au_ftest_opts(opts->flags, REMOUNT));
18002 +               if (unlikely(err))
18003 +                       break;
18004 +
18005 +               *opt_xino = &opt->xino;
18006 +               au_xino_brid_set(sb, -1);
18007 +
18008 +               /* safe d_parent access */
18009 +               parent = opt->xino.file->f_dentry->d_parent;
18010 +               root = sb->s_root;
18011 +               bend = au_sbend(sb);
18012 +               for (bindex = 0; bindex <= bend; bindex++) {
18013 +                       h_root = au_h_dptr(root, bindex);
18014 +                       if (h_root == parent) {
18015 +                               au_xino_brid_set(sb, au_sbr_id(sb, bindex));
18016 +                               break;
18017 +                       }
18018 +               }
18019 +               break;
18020 +
18021 +       case Opt_noxino:
18022 +               au_xino_clr(sb);
18023 +               au_xino_brid_set(sb, -1);
18024 +               *opt_xino = (void *)-1;
18025 +               break;
18026 +       }
18027 +
18028 +       return err;
18029 +}
18030 +
18031 +int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18032 +                  unsigned int pending)
18033 +{
18034 +       int err;
18035 +       aufs_bindex_t bindex, bend;
18036 +       unsigned char do_plink, skip, do_free;
18037 +       struct au_branch *br;
18038 +       struct au_wbr *wbr;
18039 +       struct dentry *root;
18040 +       struct inode *dir, *h_dir;
18041 +       struct au_sbinfo *sbinfo;
18042 +       struct au_hinode *hdir;
18043 +
18044 +       SiMustAnyLock(sb);
18045 +
18046 +       sbinfo = au_sbi(sb);
18047 +       AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
18048 +
18049 +       if (!(sb_flags & MS_RDONLY)) {
18050 +               if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
18051 +                       pr_warning("first branch should be rw\n");
18052 +               if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
18053 +                       pr_warning("shwh should be used with ro\n");
18054 +       }
18055 +
18056 +       if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
18057 +           && !au_opt_test(sbinfo->si_mntflags, XINO))
18058 +               pr_warning("udba=*notify requires xino\n");
18059 +
18060 +       err = 0;
18061 +       root = sb->s_root;
18062 +       dir = root->d_inode;
18063 +       do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
18064 +       bend = au_sbend(sb);
18065 +       for (bindex = 0; !err && bindex <= bend; bindex++) {
18066 +               skip = 0;
18067 +               h_dir = au_h_iptr(dir, bindex);
18068 +               br = au_sbr(sb, bindex);
18069 +               do_free = 0;
18070 +
18071 +               wbr = br->br_wbr;
18072 +               if (wbr)
18073 +                       wbr_wh_read_lock(wbr);
18074 +
18075 +               switch (br->br_perm) {
18076 +               case AuBrPerm_RO:
18077 +               case AuBrPerm_ROWH:
18078 +               case AuBrPerm_RR:
18079 +               case AuBrPerm_RRWH:
18080 +                       do_free = !!wbr;
18081 +                       skip = (!wbr
18082 +                               || (!wbr->wbr_whbase
18083 +                                   && !wbr->wbr_plink
18084 +                                   && !wbr->wbr_orph));
18085 +                       break;
18086 +
18087 +               case AuBrPerm_RWNoLinkWH:
18088 +                       /* skip = (!br->br_whbase && !br->br_orph); */
18089 +                       skip = (!wbr || !wbr->wbr_whbase);
18090 +                       if (skip && wbr) {
18091 +                               if (do_plink)
18092 +                                       skip = !!wbr->wbr_plink;
18093 +                               else
18094 +                                       skip = !wbr->wbr_plink;
18095 +                       }
18096 +                       break;
18097 +
18098 +               case AuBrPerm_RW:
18099 +                       /* skip = (br->br_whbase && br->br_ohph); */
18100 +                       skip = (wbr && wbr->wbr_whbase);
18101 +                       if (skip) {
18102 +                               if (do_plink)
18103 +                                       skip = !!wbr->wbr_plink;
18104 +                               else
18105 +                                       skip = !wbr->wbr_plink;
18106 +                       }
18107 +                       break;
18108 +
18109 +               default:
18110 +                       BUG();
18111 +               }
18112 +               if (wbr)
18113 +                       wbr_wh_read_unlock(wbr);
18114 +
18115 +               if (skip)
18116 +                       continue;
18117 +
18118 +               hdir = au_hi(dir, bindex);
18119 +               au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
18120 +               if (wbr)
18121 +                       wbr_wh_write_lock(wbr);
18122 +               err = au_wh_init(au_h_dptr(root, bindex), br, sb);
18123 +               if (wbr)
18124 +                       wbr_wh_write_unlock(wbr);
18125 +               au_hn_imtx_unlock(hdir);
18126 +
18127 +               if (!err && do_free) {
18128 +                       kfree(wbr);
18129 +                       br->br_wbr = NULL;
18130 +               }
18131 +       }
18132 +
18133 +       return err;
18134 +}
18135 +
18136 +int au_opts_mount(struct super_block *sb, struct au_opts *opts)
18137 +{
18138 +       int err;
18139 +       unsigned int tmp;
18140 +       aufs_bindex_t bend;
18141 +       struct au_opt *opt;
18142 +       struct au_opt_xino *opt_xino, xino;
18143 +       struct au_sbinfo *sbinfo;
18144 +
18145 +       SiMustWriteLock(sb);
18146 +
18147 +       err = 0;
18148 +       opt_xino = NULL;
18149 +       opt = opts->opt;
18150 +       while (err >= 0 && opt->type != Opt_tail)
18151 +               err = au_opt_simple(sb, opt++, opts);
18152 +       if (err > 0)
18153 +               err = 0;
18154 +       else if (unlikely(err < 0))
18155 +               goto out;
18156 +
18157 +       /* disable xino and udba temporary */
18158 +       sbinfo = au_sbi(sb);
18159 +       tmp = sbinfo->si_mntflags;
18160 +       au_opt_clr(sbinfo->si_mntflags, XINO);
18161 +       au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
18162 +
18163 +       opt = opts->opt;
18164 +       while (err >= 0 && opt->type != Opt_tail)
18165 +               err = au_opt_br(sb, opt++, opts);
18166 +       if (err > 0)
18167 +               err = 0;
18168 +       else if (unlikely(err < 0))
18169 +               goto out;
18170 +
18171 +       bend = au_sbend(sb);
18172 +       if (unlikely(bend < 0)) {
18173 +               err = -EINVAL;
18174 +               pr_err("no branches\n");
18175 +               goto out;
18176 +       }
18177 +
18178 +       if (au_opt_test(tmp, XINO))
18179 +               au_opt_set(sbinfo->si_mntflags, XINO);
18180 +       opt = opts->opt;
18181 +       while (!err && opt->type != Opt_tail)
18182 +               err = au_opt_xino(sb, opt++, &opt_xino, opts);
18183 +       if (unlikely(err))
18184 +               goto out;
18185 +
18186 +       err = au_opts_verify(sb, sb->s_flags, tmp);
18187 +       if (unlikely(err))
18188 +               goto out;
18189 +
18190 +       /* restore xino */
18191 +       if (au_opt_test(tmp, XINO) && !opt_xino) {
18192 +               xino.file = au_xino_def(sb);
18193 +               err = PTR_ERR(xino.file);
18194 +               if (IS_ERR(xino.file))
18195 +                       goto out;
18196 +
18197 +               err = au_xino_set(sb, &xino, /*remount*/0);
18198 +               fput(xino.file);
18199 +               if (unlikely(err))
18200 +                       goto out;
18201 +       }
18202 +
18203 +       /* restore udba */
18204 +       sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18205 +       sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
18206 +       if (au_opt_test(tmp, UDBA_HNOTIFY)) {
18207 +               struct inode *dir = sb->s_root->d_inode;
18208 +               au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
18209 +       }
18210 +
18211 +out:
18212 +       return err;
18213 +}
18214 +
18215 +int au_opts_remount(struct super_block *sb, struct au_opts *opts)
18216 +{
18217 +       int err, rerr;
18218 +       struct inode *dir;
18219 +       struct au_opt_xino *opt_xino;
18220 +       struct au_opt *opt;
18221 +       struct au_sbinfo *sbinfo;
18222 +
18223 +       SiMustWriteLock(sb);
18224 +
18225 +       dir = sb->s_root->d_inode;
18226 +       sbinfo = au_sbi(sb);
18227 +       err = 0;
18228 +       opt_xino = NULL;
18229 +       opt = opts->opt;
18230 +       while (err >= 0 && opt->type != Opt_tail) {
18231 +               err = au_opt_simple(sb, opt, opts);
18232 +               if (!err)
18233 +                       err = au_opt_br(sb, opt, opts);
18234 +               if (!err)
18235 +                       err = au_opt_xino(sb, opt, &opt_xino, opts);
18236 +               opt++;
18237 +       }
18238 +       if (err > 0)
18239 +               err = 0;
18240 +       AuTraceErr(err);
18241 +       /* go on even err */
18242 +
18243 +       rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
18244 +       if (unlikely(rerr && !err))
18245 +               err = rerr;
18246 +
18247 +       if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
18248 +               rerr = au_xib_trunc(sb);
18249 +               if (unlikely(rerr && !err))
18250 +                       err = rerr;
18251 +       }
18252 +
18253 +       /* will be handled by the caller */
18254 +       if (!au_ftest_opts(opts->flags, REFRESH_DIR)
18255 +           && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
18256 +               au_fset_opts(opts->flags, REFRESH_DIR);
18257 +
18258 +       AuDbg("status 0x%x\n", opts->flags);
18259 +       return err;
18260 +}
18261 +
18262 +/* ---------------------------------------------------------------------- */
18263 +
18264 +unsigned int au_opt_udba(struct super_block *sb)
18265 +{
18266 +       return au_mntflags(sb) & AuOptMask_UDBA;
18267 +}
18268 diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
18269 --- /usr/share/empty/fs/aufs/opts.h     1970-01-01 01:00:00.000000000 +0100
18270 +++ linux/fs/aufs/opts.h        2010-10-21 09:52:43.093625591 +0200
18271 @@ -0,0 +1,198 @@
18272 +/*
18273 + * Copyright (C) 2005-2010 Junjiro R. Okajima
18274 + *
18275 + * This program, aufs is free software; you can redistribute it and/or modify
18276 + * it under the terms of the GNU General Public License as published by
18277 + * the Free Software Foundation; either version 2 of the License, or
18278 + * (at your option) any later version.
18279 + *
18280 + * This program is distributed in the hope that it will be useful,
18281 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
18282 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18283 + * GNU General Public License for more details.
18284 + *
18285 + * You should have received a copy of the GNU General Public License
18286 + * along with this program; if not, write to the Free Software
18287 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18288 + */
18289 +
18290 +/*
18291 + * mount options/flags
18292 + */
18293 +
18294 +#ifndef __AUFS_OPTS_H__
18295 +#define __AUFS_OPTS_H__
18296 +
18297 +#ifdef __KERNEL__
18298 +
18299 +#include <linux/path.h>
18300 +#include <linux/aufs_type.h>
18301 +
18302 +struct file;
18303 +struct super_block;
18304 +
18305 +/* ---------------------------------------------------------------------- */
18306 +
18307 +/* mount flags */
18308 +#define AuOpt_XINO             1               /* external inode number bitmap
18309 +                                                  and translation table */
18310 +#define AuOpt_TRUNC_XINO       (1 << 1)        /* truncate xino files */
18311 +#define AuOpt_UDBA_NONE                (1 << 2)        /* users direct branch access */
18312 +#define AuOpt_UDBA_REVAL       (1 << 3)
18313 +#define AuOpt_UDBA_HNOTIFY     (1 << 4)
18314 +#define AuOpt_SHWH             (1 << 5)        /* show whiteout */
18315 +#define AuOpt_PLINK            (1 << 6)        /* pseudo-link */
18316 +#define AuOpt_DIRPERM1         (1 << 7)        /* unimplemented */
18317 +#define AuOpt_REFROF           (1 << 8)        /* unimplemented */
18318 +#define AuOpt_ALWAYS_DIROPQ    (1 << 9)        /* policy to creating diropq */
18319 +#define AuOpt_SUM              (1 << 10)       /* summation for statfs(2) */
18320 +#define AuOpt_SUM_W            (1 << 11)       /* unimplemented */
18321 +#define AuOpt_WARN_PERM                (1 << 12)       /* warn when add-branch */
18322 +#define AuOpt_VERBOSE          (1 << 13)       /* busy inode when del-branch */
18323 +#define AuOpt_DIO              (1 << 14)       /* direct io */
18324 +
18325 +#ifndef CONFIG_AUFS_HNOTIFY
18326 +#undef AuOpt_UDBA_HNOTIFY
18327 +#define AuOpt_UDBA_HNOTIFY     0
18328 +#endif
18329 +#ifndef CONFIG_AUFS_SHWH
18330 +#undef AuOpt_SHWH
18331 +#define AuOpt_SHWH             0
18332 +#endif
18333 +
18334 +#define AuOpt_Def      (AuOpt_XINO \
18335 +                        | AuOpt_UDBA_REVAL \
18336 +                        | AuOpt_PLINK \
18337 +                        /* | AuOpt_DIRPERM1 */ \
18338 +                        | AuOpt_WARN_PERM)
18339 +#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
18340 +                        | AuOpt_UDBA_REVAL \
18341 +                        | AuOpt_UDBA_HNOTIFY)
18342 +
18343 +#define au_opt_test(flags, name)       (flags & AuOpt_##name)
18344 +#define au_opt_set(flags, name) do { \
18345 +       BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
18346 +       ((flags) |= AuOpt_##name); \
18347 +} while (0)
18348 +#define au_opt_set_udba(flags, name) do { \
18349 +       (flags) &= ~AuOptMask_UDBA; \
18350 +       ((flags) |= AuOpt_##name); \
18351 +} while (0)
18352 +#define au_opt_clr(flags, name)                { ((flags) &= ~AuOpt_##name); }
18353 +
18354 +/* ---------------------------------------------------------------------- */
18355 +
18356 +/* policies to select one among multiple writable branches */
18357 +enum {
18358 +       AuWbrCreate_TDP,        /* top down parent */
18359 +       AuWbrCreate_RR,         /* round robin */
18360 +       AuWbrCreate_MFS,        /* most free space */
18361 +       AuWbrCreate_MFSV,       /* mfs with seconds */
18362 +       AuWbrCreate_MFSRR,      /* mfs then rr */
18363 +       AuWbrCreate_MFSRRV,     /* mfs then rr with seconds */
18364 +       AuWbrCreate_PMFS,       /* parent and mfs */
18365 +       AuWbrCreate_PMFSV,      /* parent and mfs with seconds */
18366 +
18367 +       AuWbrCreate_Def = AuWbrCreate_TDP
18368 +};
18369 +
18370 +enum {
18371 +       AuWbrCopyup_TDP,        /* top down parent */
18372 +       AuWbrCopyup_BUP,        /* bottom up parent */
18373 +       AuWbrCopyup_BU,         /* bottom up */
18374 +
18375 +       AuWbrCopyup_Def = AuWbrCopyup_TDP
18376 +};
18377 +
18378 +/* ---------------------------------------------------------------------- */
18379 +
18380 +struct au_opt_add {
18381 +       aufs_bindex_t   bindex;
18382 +       char            *pathname;
18383 +       int             perm;
18384 +       struct path     path;
18385 +};
18386 +
18387 +struct au_opt_del {
18388 +       char            *pathname;
18389 +       struct path     h_path;
18390 +};
18391 +
18392 +struct au_opt_mod {
18393 +       char            *path;
18394 +       int             perm;
18395 +       struct dentry   *h_root;
18396 +};
18397 +
18398 +struct au_opt_xino {
18399 +       char            *path;
18400 +       struct file     *file;
18401 +};
18402 +
18403 +struct au_opt_xino_itrunc {
18404 +       aufs_bindex_t   bindex;
18405 +};
18406 +
18407 +struct au_opt_wbr_create {
18408 +       int                     wbr_create;
18409 +       int                     mfs_second;
18410 +       unsigned long long      mfsrr_watermark;
18411 +};
18412 +
18413 +struct au_opt {
18414 +       int type;
18415 +       union {
18416 +               struct au_opt_xino      xino;
18417 +               struct au_opt_xino_itrunc xino_itrunc;
18418 +               struct au_opt_add       add;
18419 +               struct au_opt_del       del;
18420 +               struct au_opt_mod       mod;
18421 +               int                     dirwh;
18422 +               int                     rdcache;
18423 +               unsigned int            rdblk;
18424 +               unsigned int            rdhash;
18425 +               int                     udba;
18426 +               struct au_opt_wbr_create wbr_create;
18427 +               int                     wbr_copyup;
18428 +       };
18429 +};
18430 +
18431 +/* opts flags */
18432 +#define AuOpts_REMOUNT         1
18433 +#define AuOpts_REFRESH_DIR     (1 << 1)
18434 +#define AuOpts_REFRESH_NONDIR  (1 << 2)
18435 +#define AuOpts_TRUNC_XIB       (1 << 3)
18436 +#define AuOpts_REFRESH_DYAOP   (1 << 4)
18437 +#define au_ftest_opts(flags, name)     ((flags) & AuOpts_##name)
18438 +#define au_fset_opts(flags, name)      { (flags) |= AuOpts_##name; }
18439 +#define au_fclr_opts(flags, name)      { (flags) &= ~AuOpts_##name; }
18440 +
18441 +struct au_opts {
18442 +       struct au_opt   *opt;
18443 +       int             max_opt;
18444 +
18445 +       unsigned int    given_udba;
18446 +       unsigned int    flags;
18447 +       unsigned long   sb_flags;
18448 +};
18449 +
18450 +/* ---------------------------------------------------------------------- */
18451 +
18452 +const char *au_optstr_br_perm(int brperm);
18453 +const char *au_optstr_udba(int udba);
18454 +const char *au_optstr_wbr_copyup(int wbr_copyup);
18455 +const char *au_optstr_wbr_create(int wbr_create);
18456 +
18457 +void au_opts_free(struct au_opts *opts);
18458 +int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
18459 +int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18460 +                  unsigned int pending);
18461 +int au_opts_mount(struct super_block *sb, struct au_opts *opts);
18462 +int au_opts_remount(struct super_block *sb, struct au_opts *opts);
18463 +
18464 +unsigned int au_opt_udba(struct super_block *sb);
18465 +
18466 +/* ---------------------------------------------------------------------- */
18467 +
18468 +#endif /* __KERNEL__ */
18469 +#endif /* __AUFS_OPTS_H__ */
18470 diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
18471 --- /usr/share/empty/fs/aufs/plink.c    1970-01-01 01:00:00.000000000 +0100
18472 +++ linux/fs/aufs/plink.c       2010-10-21 09:52:43.093625591 +0200
18473 @@ -0,0 +1,451 @@
18474 +/*
18475 + * Copyright (C) 2005-2010 Junjiro R. Okajima
18476 + *
18477 + * This program, aufs is free software; you can redistribute it and/or modify
18478 + * it under the terms of the GNU General Public License as published by
18479 + * the Free Software Foundation; either version 2 of the License, or
18480 + * (at your option) any later version.
18481 + *
18482 + * This program is distributed in the hope that it will be useful,
18483 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
18484 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18485 + * GNU General Public License for more details.
18486 + *
18487 + * You should have received a copy of the GNU General Public License
18488 + * along with this program; if not, write to the Free Software
18489 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18490 + */
18491 +
18492 +/*
18493 + * pseudo-link
18494 + */
18495 +
18496 +#include "aufs.h"
18497 +
18498 +/*
18499 + * during a user process maintains the pseudo-links,
18500 + * prohibit adding a new plink and branch manipulation.
18501 + */
18502 +void au_plink_maint_block(struct super_block *sb)
18503 +{
18504 +       struct au_sbinfo *sbi = au_sbi(sb);
18505 +
18506 +       SiMustAnyLock(sb);
18507 +
18508 +       /* gave up wake_up_bit() */
18509 +       wait_event(sbi->si_plink_wq, !sbi->si_plink_maint);
18510 +}
18511 +
18512 +void au_plink_maint_leave(struct file *file)
18513 +{
18514 +       struct au_sbinfo *sbinfo;
18515 +       int iam;
18516 +
18517 +       AuDebugOn(atomic_long_read(&file->f_count));
18518 +
18519 +       sbinfo = au_sbi(file->f_dentry->d_sb);
18520 +       spin_lock(&sbinfo->si_plink_maint_lock);
18521 +       iam = (sbinfo->si_plink_maint == file);
18522 +       if (iam)
18523 +               sbinfo->si_plink_maint = NULL;
18524 +       spin_unlock(&sbinfo->si_plink_maint_lock);
18525 +       if (iam)
18526 +               wake_up_all(&sbinfo->si_plink_wq);
18527 +}
18528 +
18529 +static int au_plink_maint_enter(struct file *file)
18530 +{
18531 +       int err;
18532 +       struct super_block *sb;
18533 +       struct au_sbinfo *sbinfo;
18534 +
18535 +       err = 0;
18536 +       sb = file->f_dentry->d_sb;
18537 +       sbinfo = au_sbi(sb);
18538 +       /* make sure i am the only one in this fs */
18539 +       si_write_lock(sb);
18540 +       /* spin_lock(&sbinfo->si_plink_maint_lock); */
18541 +       if (!sbinfo->si_plink_maint)
18542 +               sbinfo->si_plink_maint = file;
18543 +       else
18544 +               err = -EBUSY;
18545 +       /* spin_unlock(&sbinfo->si_plink_maint_lock); */
18546 +       si_write_unlock(sb);
18547 +
18548 +       return err;
18549 +}
18550 +
18551 +/* ---------------------------------------------------------------------- */
18552 +
18553 +struct pseudo_link {
18554 +       union {
18555 +               struct list_head list;
18556 +               struct rcu_head rcu;
18557 +       };
18558 +       struct inode *inode;
18559 +};
18560 +
18561 +#ifdef CONFIG_AUFS_DEBUG
18562 +void au_plink_list(struct super_block *sb)
18563 +{
18564 +       struct au_sbinfo *sbinfo;
18565 +       struct list_head *plink_list;
18566 +       struct pseudo_link *plink;
18567 +
18568 +       SiMustAnyLock(sb);
18569 +
18570 +       sbinfo = au_sbi(sb);
18571 +       AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18572 +
18573 +       plink_list = &sbinfo->si_plink.head;
18574 +       rcu_read_lock();
18575 +       list_for_each_entry_rcu(plink, plink_list, list)
18576 +               AuDbg("%lu\n", plink->inode->i_ino);
18577 +       rcu_read_unlock();
18578 +}
18579 +#endif
18580 +
18581 +/* is the inode pseudo-linked? */
18582 +int au_plink_test(struct inode *inode)
18583 +{
18584 +       int found;
18585 +       struct au_sbinfo *sbinfo;
18586 +       struct list_head *plink_list;
18587 +       struct pseudo_link *plink;
18588 +
18589 +       sbinfo = au_sbi(inode->i_sb);
18590 +       AuRwMustAnyLock(&sbinfo->si_rwsem);
18591 +       AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
18592 +
18593 +       found = 0;
18594 +       plink_list = &sbinfo->si_plink.head;
18595 +       rcu_read_lock();
18596 +       list_for_each_entry_rcu(plink, plink_list, list)
18597 +               if (plink->inode == inode) {
18598 +                       found = 1;
18599 +                       break;
18600 +               }
18601 +       rcu_read_unlock();
18602 +       return found;
18603 +}
18604 +
18605 +/* ---------------------------------------------------------------------- */
18606 +
18607 +/*
18608 + * generate a name for plink.
18609 + * the file will be stored under AUFS_WH_PLINKDIR.
18610 + */
18611 +/* 20 is max digits length of ulong 64 */
18612 +#define PLINK_NAME_LEN ((20 + 1) * 2)
18613 +
18614 +static int plink_name(char *name, int len, struct inode *inode,
18615 +                     aufs_bindex_t bindex)
18616 +{
18617 +       int rlen;
18618 +       struct inode *h_inode;
18619 +
18620 +       h_inode = au_h_iptr(inode, bindex);
18621 +       rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
18622 +       return rlen;
18623 +}
18624 +
18625 +/* lookup the plink-ed @inode under the branch at @bindex */
18626 +struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
18627 +{
18628 +       struct dentry *h_dentry, *h_parent;
18629 +       struct au_branch *br;
18630 +       struct inode *h_dir;
18631 +       char a[PLINK_NAME_LEN];
18632 +       struct qstr tgtname = {
18633 +               .name   = a
18634 +       };
18635 +
18636 +       br = au_sbr(inode->i_sb, bindex);
18637 +       h_parent = br->br_wbr->wbr_plink;
18638 +       h_dir = h_parent->d_inode;
18639 +       tgtname.len = plink_name(a, sizeof(a), inode, bindex);
18640 +
18641 +       /* always superio. */
18642 +       mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
18643 +       h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
18644 +       mutex_unlock(&h_dir->i_mutex);
18645 +       return h_dentry;
18646 +}
18647 +
18648 +/* create a pseudo-link */
18649 +static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
18650 +                     struct dentry *h_dentry, struct au_branch *br)
18651 +{
18652 +       int err;
18653 +       struct path h_path = {
18654 +               .mnt = br->br_mnt
18655 +       };
18656 +       struct inode *h_dir;
18657 +
18658 +       h_dir = h_parent->d_inode;
18659 +again:
18660 +       h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
18661 +       err = PTR_ERR(h_path.dentry);
18662 +       if (IS_ERR(h_path.dentry))
18663 +               goto out;
18664 +
18665 +       err = 0;
18666 +       /* wh.plink dir is not monitored */
18667 +       if (h_path.dentry->d_inode
18668 +           && h_path.dentry->d_inode != h_dentry->d_inode) {
18669 +               err = vfsub_unlink(h_dir, &h_path, /*force*/0);
18670 +               dput(h_path.dentry);
18671 +               h_path.dentry = NULL;
18672 +               if (!err)
18673 +                       goto again;
18674 +       }
18675 +       if (!err && !h_path.dentry->d_inode)
18676 +               err = vfsub_link(h_dentry, h_dir, &h_path);
18677 +       dput(h_path.dentry);
18678 +
18679 +out:
18680 +       return err;
18681 +}
18682 +
18683 +struct do_whplink_args {
18684 +       int *errp;
18685 +       struct qstr *tgt;
18686 +       struct dentry *h_parent;
18687 +       struct dentry *h_dentry;
18688 +       struct au_branch *br;
18689 +};
18690 +
18691 +static void call_do_whplink(void *args)
18692 +{
18693 +       struct do_whplink_args *a = args;
18694 +       *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
18695 +}
18696 +
18697 +static int whplink(struct dentry *h_dentry, struct inode *inode,
18698 +                  aufs_bindex_t bindex, struct au_branch *br)
18699 +{
18700 +       int err, wkq_err;
18701 +       struct au_wbr *wbr;
18702 +       struct dentry *h_parent;
18703 +       struct inode *h_dir;
18704 +       char a[PLINK_NAME_LEN];
18705 +       struct qstr tgtname = {
18706 +               .name = a
18707 +       };
18708 +
18709 +       wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
18710 +       h_parent = wbr->wbr_plink;
18711 +       h_dir = h_parent->d_inode;
18712 +       tgtname.len = plink_name(a, sizeof(a), inode, bindex);
18713 +
18714 +       /* always superio. */
18715 +       mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
18716 +       if (current_fsuid()) {
18717 +               struct do_whplink_args args = {
18718 +                       .errp           = &err,
18719 +                       .tgt            = &tgtname,
18720 +                       .h_parent       = h_parent,
18721 +                       .h_dentry       = h_dentry,
18722 +                       .br             = br
18723 +               };
18724 +               wkq_err = au_wkq_wait(call_do_whplink, &args);
18725 +               if (unlikely(wkq_err))
18726 +                       err = wkq_err;
18727 +       } else
18728 +               err = do_whplink(&tgtname, h_parent, h_dentry, br);
18729 +       mutex_unlock(&h_dir->i_mutex);
18730 +
18731 +       return err;
18732 +}
18733 +
18734 +/* free a single plink */
18735 +static void do_put_plink(struct pseudo_link *plink, int do_del)
18736 +{
18737 +       if (do_del)
18738 +               list_del(&plink->list);
18739 +       iput(plink->inode);
18740 +       kfree(plink);
18741 +}
18742 +
18743 +static void do_put_plink_rcu(struct rcu_head *rcu)
18744 +{
18745 +       struct pseudo_link *plink;
18746 +
18747 +       plink = container_of(rcu, struct pseudo_link, rcu);
18748 +       iput(plink->inode);
18749 +       kfree(plink);
18750 +}
18751 +
18752 +/*
18753 + * create a new pseudo-link for @h_dentry on @bindex.
18754 + * the linked inode is held in aufs @inode.
18755 + */
18756 +void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
18757 +                    struct dentry *h_dentry)
18758 +{
18759 +       struct super_block *sb;
18760 +       struct au_sbinfo *sbinfo;
18761 +       struct list_head *plink_list;
18762 +       struct pseudo_link *plink, *tmp;
18763 +       int found, err, cnt;
18764 +
18765 +       sb = inode->i_sb;
18766 +       sbinfo = au_sbi(sb);
18767 +       AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18768 +
18769 +       cnt = 0;
18770 +       found = 0;
18771 +       plink_list = &sbinfo->si_plink.head;
18772 +       rcu_read_lock();
18773 +       list_for_each_entry_rcu(plink, plink_list, list) {
18774 +               cnt++;
18775 +               if (plink->inode == inode) {
18776 +                       found = 1;
18777 +                       break;
18778 +               }
18779 +       }
18780 +       rcu_read_unlock();
18781 +       if (found)
18782 +               return;
18783 +
18784 +       tmp = kmalloc(sizeof(*plink), GFP_NOFS);
18785 +       if (tmp)
18786 +               tmp->inode = au_igrab(inode);
18787 +       else {
18788 +               err = -ENOMEM;
18789 +               goto out;
18790 +       }
18791 +
18792 +       spin_lock(&sbinfo->si_plink.spin);
18793 +       list_for_each_entry(plink, plink_list, list) {
18794 +               if (plink->inode == inode) {
18795 +                       found = 1;
18796 +                       break;
18797 +               }
18798 +       }
18799 +       if (!found)
18800 +               list_add_rcu(&tmp->list, plink_list);
18801 +       spin_unlock(&sbinfo->si_plink.spin);
18802 +       if (!found) {
18803 +               cnt++;
18804 +               WARN_ONCE(cnt > AUFS_PLINK_WARN,
18805 +                         "unexpectedly many pseudo links, %d\n", cnt);
18806 +               au_plink_maint_block(sb);
18807 +               err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
18808 +       } else {
18809 +               do_put_plink(tmp, 0);
18810 +               return;
18811 +       }
18812 +
18813 +out:
18814 +       if (unlikely(err)) {
18815 +               pr_warning("err %d, damaged pseudo link.\n", err);
18816 +               if (tmp) {
18817 +                       au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
18818 +                       call_rcu(&tmp->rcu, do_put_plink_rcu);
18819 +               }
18820 +       }
18821 +}
18822 +
18823 +/* free all plinks */
18824 +void au_plink_put(struct super_block *sb)
18825 +{
18826 +       struct au_sbinfo *sbinfo;
18827 +       struct list_head *plink_list;
18828 +       struct pseudo_link *plink, *tmp;
18829 +
18830 +       SiMustWriteLock(sb);
18831 +
18832 +       sbinfo = au_sbi(sb);
18833 +       AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18834 +
18835 +       plink_list = &sbinfo->si_plink.head;
18836 +       /* no spin_lock since sbinfo is write-locked */
18837 +       list_for_each_entry_safe(plink, tmp, plink_list, list)
18838 +               do_put_plink(plink, 0);
18839 +       INIT_LIST_HEAD(plink_list);
18840 +}
18841 +
18842 +/* free the plinks on a branch specified by @br_id */
18843 +void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
18844 +{
18845 +       struct au_sbinfo *sbinfo;
18846 +       struct list_head *plink_list;
18847 +       struct pseudo_link *plink, *tmp;
18848 +       struct inode *inode;
18849 +       aufs_bindex_t bstart, bend, bindex;
18850 +       unsigned char do_put;
18851 +
18852 +       SiMustWriteLock(sb);
18853 +
18854 +       sbinfo = au_sbi(sb);
18855 +       AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18856 +
18857 +       plink_list = &sbinfo->si_plink.head;
18858 +       /* no spin_lock since sbinfo is write-locked */
18859 +       list_for_each_entry_safe(plink, tmp, plink_list, list) {
18860 +               do_put = 0;
18861 +               inode = au_igrab(plink->inode);
18862 +               ii_write_lock_child(inode);
18863 +               bstart = au_ibstart(inode);
18864 +               bend = au_ibend(inode);
18865 +               if (bstart >= 0) {
18866 +                       for (bindex = bstart; bindex <= bend; bindex++) {
18867 +                               if (!au_h_iptr(inode, bindex)
18868 +                                   || au_ii_br_id(inode, bindex) != br_id)
18869 +                                       continue;
18870 +                               au_set_h_iptr(inode, bindex, NULL, 0);
18871 +                               do_put = 1;
18872 +                               break;
18873 +                       }
18874 +               } else
18875 +                       do_put_plink(plink, 1);
18876 +
18877 +               if (do_put) {
18878 +                       for (bindex = bstart; bindex <= bend; bindex++)
18879 +                               if (au_h_iptr(inode, bindex)) {
18880 +                                       do_put = 0;
18881 +                                       break;
18882 +                               }
18883 +                       if (do_put)
18884 +                               do_put_plink(plink, 1);
18885 +               }
18886 +               ii_write_unlock(inode);
18887 +               iput(inode);
18888 +       }
18889 +}
18890 +
18891 +/* ---------------------------------------------------------------------- */
18892 +
18893 +long au_plink_ioctl(struct file *file, unsigned int cmd)
18894 +{
18895 +       long err;
18896 +       struct super_block *sb;
18897 +
18898 +       err = -EACCES;
18899 +       if (!capable(CAP_SYS_ADMIN))
18900 +               goto out;
18901 +
18902 +       err = 0;
18903 +       sb = file->f_dentry->d_sb;
18904 +       switch (cmd) {
18905 +       case AUFS_CTL_PLINK_MAINT:
18906 +               /*
18907 +                * pseudo-link maintenance mode,
18908 +                * cleared by aufs_release_dir()
18909 +                */
18910 +               err = au_plink_maint_enter(file);
18911 +               break;
18912 +       case AUFS_CTL_PLINK_CLEAN:
18913 +               aufs_write_lock(sb->s_root);
18914 +               if (au_opt_test(au_mntflags(sb), PLINK))
18915 +                       au_plink_put(sb);
18916 +               aufs_write_unlock(sb->s_root);
18917 +               break;
18918 +       default:
18919 +               /* err = -ENOTTY; */
18920 +               err = -EINVAL;
18921 +       }
18922 +out:
18923 +       return err;
18924 +}
18925 diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
18926 --- /usr/share/empty/fs/aufs/poll.c     1970-01-01 01:00:00.000000000 +0100
18927 +++ linux/fs/aufs/poll.c        2010-10-21 09:52:43.093625591 +0200
18928 @@ -0,0 +1,56 @@
18929 +/*
18930 + * Copyright (C) 2005-2010 Junjiro R. Okajima
18931 + *
18932 + * This program, aufs is free software; you can redistribute it and/or modify
18933 + * it under the terms of the GNU General Public License as published by
18934 + * the Free Software Foundation; either version 2 of the License, or
18935 + * (at your option) any later version.
18936 + *
18937 + * This program is distributed in the hope that it will be useful,
18938 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
18939 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18940 + * GNU General Public License for more details.
18941 + *
18942 + * You should have received a copy of the GNU General Public License
18943 + * along with this program; if not, write to the Free Software
18944 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18945 + */
18946 +
18947 +/*
18948 + * poll operation
18949 + * There is only one filesystem which implements ->poll operation, currently.
18950 + */
18951 +
18952 +#include "aufs.h"
18953 +
18954 +unsigned int aufs_poll(struct file *file, poll_table *wait)
18955 +{
18956 +       unsigned int mask;
18957 +       int err;
18958 +       struct file *h_file;
18959 +       struct dentry *dentry;
18960 +       struct super_block *sb;
18961 +
18962 +       /* We should pretend an error happened. */
18963 +       mask = POLLERR /* | POLLIN | POLLOUT */;
18964 +       dentry = file->f_dentry;
18965 +       sb = dentry->d_sb;
18966 +       si_read_lock(sb, AuLock_FLUSH);
18967 +       err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
18968 +       if (unlikely(err))
18969 +               goto out;
18970 +
18971 +       /* it is not an error if h_file has no operation */
18972 +       mask = DEFAULT_POLLMASK;
18973 +       h_file = au_hf_top(file);
18974 +       if (h_file->f_op && h_file->f_op->poll)
18975 +               mask = h_file->f_op->poll(h_file, wait);
18976 +
18977 +       di_read_unlock(dentry, AuLock_IR);
18978 +       fi_read_unlock(file);
18979 +
18980 +out:
18981 +       si_read_unlock(sb);
18982 +       AuTraceErr((int)mask);
18983 +       return mask;
18984 +}
18985 diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
18986 --- /usr/share/empty/fs/aufs/rdu.c      1970-01-01 01:00:00.000000000 +0100
18987 +++ linux/fs/aufs/rdu.c 2010-10-21 09:52:43.093625591 +0200
18988 @@ -0,0 +1,377 @@
18989 +/*
18990 + * Copyright (C) 2005-2010 Junjiro R. Okajima
18991 + *
18992 + * This program, aufs is free software; you can redistribute it and/or modify
18993 + * it under the terms of the GNU General Public License as published by
18994 + * the Free Software Foundation; either version 2 of the License, or
18995 + * (at your option) any later version.
18996 + *
18997 + * This program is distributed in the hope that it will be useful,
18998 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
18999 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19000 + * GNU General Public License for more details.
19001 + *
19002 + * You should have received a copy of the GNU General Public License
19003 + * along with this program; if not, write to the Free Software
19004 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19005 + */
19006 +
19007 +/*
19008 + * readdir in userspace.
19009 + */
19010 +
19011 +#include <linux/compat.h>
19012 +#include <linux/fs_stack.h>
19013 +#include <linux/security.h>
19014 +#include <linux/uaccess.h>
19015 +#include <linux/aufs_type.h>
19016 +#include "aufs.h"
19017 +
19018 +/* bits for struct aufs_rdu.flags */
19019 +#define        AuRdu_CALLED    1
19020 +#define        AuRdu_CONT      (1 << 1)
19021 +#define        AuRdu_FULL      (1 << 2)
19022 +#define au_ftest_rdu(flags, name)      ((flags) & AuRdu_##name)
19023 +#define au_fset_rdu(flags, name)       { (flags) |= AuRdu_##name; }
19024 +#define au_fclr_rdu(flags, name)       { (flags) &= ~AuRdu_##name; }
19025 +
19026 +struct au_rdu_arg {
19027 +       struct aufs_rdu                 *rdu;
19028 +       union au_rdu_ent_ul             ent;
19029 +       unsigned long                   end;
19030 +
19031 +       struct super_block              *sb;
19032 +       int                             err;
19033 +};
19034 +
19035 +static int au_rdu_fill(void *__arg, const char *name, int nlen,
19036 +                      loff_t offset, u64 h_ino, unsigned int d_type)
19037 +{
19038 +       int err, len;
19039 +       struct au_rdu_arg *arg = __arg;
19040 +       struct aufs_rdu *rdu = arg->rdu;
19041 +       struct au_rdu_ent ent;
19042 +
19043 +       err = 0;
19044 +       arg->err = 0;
19045 +       au_fset_rdu(rdu->cookie.flags, CALLED);
19046 +       len = au_rdu_len(nlen);
19047 +       if (arg->ent.ul + len  < arg->end) {
19048 +               ent.ino = h_ino;
19049 +               ent.bindex = rdu->cookie.bindex;
19050 +               ent.type = d_type;
19051 +               ent.nlen = nlen;
19052 +               if (unlikely(nlen > AUFS_MAX_NAMELEN))
19053 +                       ent.type = DT_UNKNOWN;
19054 +
19055 +               err = -EFAULT;
19056 +               if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
19057 +                       goto out;
19058 +               if (copy_to_user(arg->ent.e->name, name, nlen))
19059 +                       goto out;
19060 +               /* the terminating NULL */
19061 +               if (__put_user(0, arg->ent.e->name + nlen))
19062 +                       goto out;
19063 +               err = 0;
19064 +               /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
19065 +               arg->ent.ul += len;
19066 +               rdu->rent++;
19067 +       } else {
19068 +               err = -EFAULT;
19069 +               au_fset_rdu(rdu->cookie.flags, FULL);
19070 +               rdu->full = 1;
19071 +               rdu->tail = arg->ent;
19072 +       }
19073 +
19074 +out:
19075 +       /* AuTraceErr(err); */
19076 +       return err;
19077 +}
19078 +
19079 +static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
19080 +{
19081 +       int err;
19082 +       loff_t offset;
19083 +       struct au_rdu_cookie *cookie = &arg->rdu->cookie;
19084 +
19085 +       offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
19086 +       err = offset;
19087 +       if (unlikely(offset != cookie->h_pos))
19088 +               goto out;
19089 +
19090 +       err = 0;
19091 +       do {
19092 +               arg->err = 0;
19093 +               au_fclr_rdu(cookie->flags, CALLED);
19094 +               /* smp_mb(); */
19095 +               err = vfsub_readdir(h_file, au_rdu_fill, arg);
19096 +               if (err >= 0)
19097 +                       err = arg->err;
19098 +       } while (!err
19099 +                && au_ftest_rdu(cookie->flags, CALLED)
19100 +                && !au_ftest_rdu(cookie->flags, FULL));
19101 +       cookie->h_pos = h_file->f_pos;
19102 +
19103 +out:
19104 +       AuTraceErr(err);
19105 +       return err;
19106 +}
19107 +
19108 +static int au_rdu(struct file *file, struct aufs_rdu *rdu)
19109 +{
19110 +       int err;
19111 +       aufs_bindex_t bend;
19112 +       struct au_rdu_arg arg;
19113 +       struct dentry *dentry;
19114 +       struct inode *inode;
19115 +       struct file *h_file;
19116 +       struct au_rdu_cookie *cookie = &rdu->cookie;
19117 +
19118 +       err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
19119 +       if (unlikely(err)) {
19120 +               err = -EFAULT;
19121 +               AuTraceErr(err);
19122 +               goto out;
19123 +       }
19124 +       rdu->rent = 0;
19125 +       rdu->tail = rdu->ent;
19126 +       rdu->full = 0;
19127 +       arg.rdu = rdu;
19128 +       arg.ent = rdu->ent;
19129 +       arg.end = arg.ent.ul;
19130 +       arg.end += rdu->sz;
19131 +
19132 +       err = -ENOTDIR;
19133 +       if (unlikely(!file->f_op || !file->f_op->readdir))
19134 +               goto out;
19135 +
19136 +       err = security_file_permission(file, MAY_READ);
19137 +       AuTraceErr(err);
19138 +       if (unlikely(err))
19139 +               goto out;
19140 +
19141 +       dentry = file->f_dentry;
19142 +       inode = dentry->d_inode;
19143 +#if 1
19144 +       mutex_lock(&inode->i_mutex);
19145 +#else
19146 +       err = mutex_lock_killable(&inode->i_mutex);
19147 +       AuTraceErr(err);
19148 +       if (unlikely(err))
19149 +               goto out;
19150 +#endif
19151 +       err = -ENOENT;
19152 +       if (unlikely(IS_DEADDIR(inode)))
19153 +               goto out_mtx;
19154 +
19155 +       arg.sb = inode->i_sb;
19156 +       si_read_lock(arg.sb, AuLock_FLUSH);
19157 +       fi_read_lock(file);
19158 +
19159 +       err = -EAGAIN;
19160 +       if (unlikely(au_ftest_rdu(cookie->flags, CONT)
19161 +                    && cookie->generation != au_figen(file)))
19162 +               goto out_unlock;
19163 +
19164 +       err = 0;
19165 +       if (!rdu->blk) {
19166 +               rdu->blk = au_sbi(arg.sb)->si_rdblk;
19167 +               if (!rdu->blk)
19168 +                       rdu->blk = au_dir_size(file, /*dentry*/NULL);
19169 +       }
19170 +       bend = au_fbstart(file);
19171 +       if (cookie->bindex < bend)
19172 +               cookie->bindex = bend;
19173 +       bend = au_fbend_dir(file);
19174 +       /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
19175 +       for (; !err && cookie->bindex <= bend;
19176 +            cookie->bindex++, cookie->h_pos = 0) {
19177 +               h_file = au_hf_dir(file, cookie->bindex);
19178 +               if (!h_file)
19179 +                       continue;
19180 +
19181 +               au_fclr_rdu(cookie->flags, FULL);
19182 +               err = au_rdu_do(h_file, &arg);
19183 +               AuTraceErr(err);
19184 +               if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
19185 +                       break;
19186 +       }
19187 +       AuDbg("rent %llu\n", rdu->rent);
19188 +
19189 +       if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
19190 +               rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
19191 +               au_fset_rdu(cookie->flags, CONT);
19192 +               cookie->generation = au_figen(file);
19193 +       }
19194 +
19195 +       ii_read_lock_child(inode);
19196 +       fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
19197 +       ii_read_unlock(inode);
19198 +
19199 +out_unlock:
19200 +       fi_read_unlock(file);
19201 +       si_read_unlock(arg.sb);
19202 +out_mtx:
19203 +       mutex_unlock(&inode->i_mutex);
19204 +out:
19205 +       AuTraceErr(err);
19206 +       return err;
19207 +}
19208 +
19209 +static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
19210 +{
19211 +       int err;
19212 +       ino_t ino;
19213 +       unsigned long long nent;
19214 +       union au_rdu_ent_ul *u;
19215 +       struct au_rdu_ent ent;
19216 +       struct super_block *sb;
19217 +
19218 +       err = 0;
19219 +       nent = rdu->nent;
19220 +       u = &rdu->ent;
19221 +       sb = file->f_dentry->d_sb;
19222 +       si_read_lock(sb, AuLock_FLUSH);
19223 +       while (nent-- > 0) {
19224 +               err = copy_from_user(&ent, u->e, sizeof(ent));
19225 +               if (!err)
19226 +                       err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
19227 +               if (unlikely(err)) {
19228 +                       err = -EFAULT;
19229 +                       AuTraceErr(err);
19230 +                       break;
19231 +               }
19232 +
19233 +               /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
19234 +               if (!ent.wh)
19235 +                       err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
19236 +               else
19237 +                       err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
19238 +                                       &ino);
19239 +               if (unlikely(err)) {
19240 +                       AuTraceErr(err);
19241 +                       break;
19242 +               }
19243 +
19244 +               err = __put_user(ino, &u->e->ino);
19245 +               if (unlikely(err)) {
19246 +                       err = -EFAULT;
19247 +                       AuTraceErr(err);
19248 +                       break;
19249 +               }
19250 +               u->ul += au_rdu_len(ent.nlen);
19251 +       }
19252 +       si_read_unlock(sb);
19253 +
19254 +       return err;
19255 +}
19256 +
19257 +/* ---------------------------------------------------------------------- */
19258 +
19259 +static int au_rdu_verify(struct aufs_rdu *rdu)
19260 +{
19261 +       AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
19262 +             "%llu, b%d, 0x%x, g%u}\n",
19263 +             rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
19264 +             rdu->blk,
19265 +             rdu->rent, rdu->shwh, rdu->full,
19266 +             rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
19267 +             rdu->cookie.generation);
19268 +
19269 +       if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
19270 +               return 0;
19271 +
19272 +       AuDbg("%u:%u\n",
19273 +             rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
19274 +       return -EINVAL;
19275 +}
19276 +
19277 +long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
19278 +{
19279 +       long err, e;
19280 +       struct aufs_rdu rdu;
19281 +       void __user *p = (void __user *)arg;
19282 +
19283 +       err = copy_from_user(&rdu, p, sizeof(rdu));
19284 +       if (unlikely(err)) {
19285 +               err = -EFAULT;
19286 +               AuTraceErr(err);
19287 +               goto out;
19288 +       }
19289 +       err = au_rdu_verify(&rdu);
19290 +       if (unlikely(err))
19291 +               goto out;
19292 +
19293 +       switch (cmd) {
19294 +       case AUFS_CTL_RDU:
19295 +               err = au_rdu(file, &rdu);
19296 +               if (unlikely(err))
19297 +                       break;
19298 +
19299 +               e = copy_to_user(p, &rdu, sizeof(rdu));
19300 +               if (unlikely(e)) {
19301 +                       err = -EFAULT;
19302 +                       AuTraceErr(err);
19303 +               }
19304 +               break;
19305 +       case AUFS_CTL_RDU_INO:
19306 +               err = au_rdu_ino(file, &rdu);
19307 +               break;
19308 +
19309 +       default:
19310 +               /* err = -ENOTTY; */
19311 +               err = -EINVAL;
19312 +       }
19313 +
19314 +out:
19315 +       AuTraceErr(err);
19316 +       return err;
19317 +}
19318 +
19319 +#ifdef CONFIG_COMPAT
19320 +long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
19321 +{
19322 +       long err, e;
19323 +       struct aufs_rdu rdu;
19324 +       void __user *p = compat_ptr(arg);
19325 +
19326 +       /* todo: get_user()? */
19327 +       err = copy_from_user(&rdu, p, sizeof(rdu));
19328 +       if (unlikely(err)) {
19329 +               err = -EFAULT;
19330 +               AuTraceErr(err);
19331 +               goto out;
19332 +       }
19333 +       rdu.ent.e = compat_ptr(rdu.ent.ul);
19334 +       err = au_rdu_verify(&rdu);
19335 +       if (unlikely(err))
19336 +               goto out;
19337 +
19338 +       switch (cmd) {
19339 +       case AUFS_CTL_RDU:
19340 +               err = au_rdu(file, &rdu);
19341 +               if (unlikely(err))
19342 +                       break;
19343 +
19344 +               rdu.ent.ul = ptr_to_compat(rdu.ent.e);
19345 +               rdu.tail.ul = ptr_to_compat(rdu.tail.e);
19346 +               e = copy_to_user(p, &rdu, sizeof(rdu));
19347 +               if (unlikely(e)) {
19348 +                       err = -EFAULT;
19349 +                       AuTraceErr(err);
19350 +               }
19351 +               break;
19352 +       case AUFS_CTL_RDU_INO:
19353 +               err = au_rdu_ino(file, &rdu);
19354 +               break;
19355 +
19356 +       default:
19357 +               /* err = -ENOTTY; */
19358 +               err = -EINVAL;
19359 +       }
19360 +
19361 +out:
19362 +       AuTraceErr(err);
19363 +       return err;
19364 +}
19365 +#endif
19366 diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
19367 --- /usr/share/empty/fs/aufs/rwsem.h    1970-01-01 01:00:00.000000000 +0100
19368 +++ linux/fs/aufs/rwsem.h       2010-10-21 09:52:43.093625591 +0200
19369 @@ -0,0 +1,187 @@
19370 +/*
19371 + * Copyright (C) 2005-2010 Junjiro R. Okajima
19372 + *
19373 + * This program, aufs is free software; you can redistribute it and/or modify
19374 + * it under the terms of the GNU General Public License as published by
19375 + * the Free Software Foundation; either version 2 of the License, or
19376 + * (at your option) any later version.
19377 + *
19378 + * This program is distributed in the hope that it will be useful,
19379 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
19380 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19381 + * GNU General Public License for more details.
19382 + *
19383 + * You should have received a copy of the GNU General Public License
19384 + * along with this program; if not, write to the Free Software
19385 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19386 + */
19387 +
19388 +/*
19389 + * simple read-write semaphore wrappers
19390 + */
19391 +
19392 +#ifndef __AUFS_RWSEM_H__
19393 +#define __AUFS_RWSEM_H__
19394 +
19395 +#ifdef __KERNEL__
19396 +
19397 +#include <linux/rwsem.h>
19398 +#include "debug.h"
19399 +
19400 +struct au_rwsem {
19401 +       struct rw_semaphore     rwsem;
19402 +#ifdef CONFIG_AUFS_DEBUG
19403 +       /* just for debugging, not almighty counter */
19404 +       atomic_t                rcnt, wcnt;
19405 +#endif
19406 +};
19407 +
19408 +#ifdef CONFIG_AUFS_DEBUG
19409 +#define AuDbgCntInit(rw) do { \
19410 +       atomic_set(&(rw)->rcnt, 0); \
19411 +       atomic_set(&(rw)->wcnt, 0); \
19412 +       smp_mb(); /* atomic set */ \
19413 +} while (0)
19414 +
19415 +#define AuDbgRcntInc(rw)       atomic_inc_return(&(rw)->rcnt)
19416 +#define AuDbgRcntDec(rw)       WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
19417 +#define AuDbgWcntInc(rw)       WARN_ON(atomic_inc_return(&(rw)->wcnt) > 1)
19418 +#define AuDbgWcntDec(rw)       WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
19419 +#else
19420 +#define AuDbgCntInit(rw)       do {} while (0)
19421 +#define AuDbgRcntInc(rw)       do {} while (0)
19422 +#define AuDbgRcntDec(rw)       do {} while (0)
19423 +#define AuDbgWcntInc(rw)       do {} while (0)
19424 +#define AuDbgWcntDec(rw)       do {} while (0)
19425 +#endif /* CONFIG_AUFS_DEBUG */
19426 +
19427 +/* to debug easier, do not make them inlined functions */
19428 +#define AuRwMustNoWaiters(rw)  AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
19429 +/* rwsem_is_locked() is unusable */
19430 +#define AuRwMustReadLock(rw)   AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
19431 +#define AuRwMustWriteLock(rw)  AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
19432 +#define AuRwMustAnyLock(rw)    AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
19433 +                                       && atomic_read(&(rw)->wcnt) <= 0)
19434 +#define AuRwDestroy(rw)                AuDebugOn(atomic_read(&(rw)->rcnt) \
19435 +                                       || atomic_read(&(rw)->wcnt))
19436 +
19437 +static inline void au_rw_init(struct au_rwsem *rw)
19438 +{
19439 +       AuDbgCntInit(rw);
19440 +       init_rwsem(&rw->rwsem);
19441 +}
19442 +
19443 +static inline void au_rw_init_wlock(struct au_rwsem *rw)
19444 +{
19445 +       au_rw_init(rw);
19446 +       down_write(&rw->rwsem);
19447 +       AuDbgWcntInc(rw);
19448 +}
19449 +
19450 +static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
19451 +                                          unsigned int lsc)
19452 +{
19453 +       au_rw_init(rw);
19454 +       down_write_nested(&rw->rwsem, lsc);
19455 +       AuDbgWcntInc(rw);
19456 +}
19457 +
19458 +static inline void au_rw_read_lock(struct au_rwsem *rw)
19459 +{
19460 +       down_read(&rw->rwsem);
19461 +       AuDbgRcntInc(rw);
19462 +}
19463 +
19464 +static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
19465 +{
19466 +       down_read_nested(&rw->rwsem, lsc);
19467 +       AuDbgRcntInc(rw);
19468 +}
19469 +
19470 +static inline void au_rw_read_unlock(struct au_rwsem *rw)
19471 +{
19472 +       AuRwMustReadLock(rw);
19473 +       AuDbgRcntDec(rw);
19474 +       up_read(&rw->rwsem);
19475 +}
19476 +
19477 +static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
19478 +{
19479 +       AuRwMustWriteLock(rw);
19480 +       AuDbgRcntInc(rw);
19481 +       AuDbgWcntDec(rw);
19482 +       downgrade_write(&rw->rwsem);
19483 +}
19484 +
19485 +static inline void au_rw_write_lock(struct au_rwsem *rw)
19486 +{
19487 +       down_write(&rw->rwsem);
19488 +       AuDbgWcntInc(rw);
19489 +}
19490 +
19491 +static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
19492 +                                          unsigned int lsc)
19493 +{
19494 +       down_write_nested(&rw->rwsem, lsc);
19495 +       AuDbgWcntInc(rw);
19496 +}
19497 +
19498 +static inline void au_rw_write_unlock(struct au_rwsem *rw)
19499 +{
19500 +       AuRwMustWriteLock(rw);
19501 +       AuDbgWcntDec(rw);
19502 +       up_write(&rw->rwsem);
19503 +}
19504 +
19505 +/* why is not _nested version defined */
19506 +static inline int au_rw_read_trylock(struct au_rwsem *rw)
19507 +{
19508 +       int ret = down_read_trylock(&rw->rwsem);
19509 +       if (ret)
19510 +               AuDbgRcntInc(rw);
19511 +       return ret;
19512 +}
19513 +
19514 +static inline int au_rw_write_trylock(struct au_rwsem *rw)
19515 +{
19516 +       int ret = down_write_trylock(&rw->rwsem);
19517 +       if (ret)
19518 +               AuDbgWcntInc(rw);
19519 +       return ret;
19520 +}
19521 +
19522 +#undef AuDbgCntInit
19523 +#undef AuDbgRcntInc
19524 +#undef AuDbgRcntDec
19525 +#undef AuDbgWcntInc
19526 +#undef AuDbgWcntDec
19527 +
19528 +#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
19529 +static inline void prefix##_read_lock(param) \
19530 +{ au_rw_read_lock(rwsem); } \
19531 +static inline void prefix##_write_lock(param) \
19532 +{ au_rw_write_lock(rwsem); } \
19533 +static inline int prefix##_read_trylock(param) \
19534 +{ return au_rw_read_trylock(rwsem); } \
19535 +static inline int prefix##_write_trylock(param) \
19536 +{ return au_rw_write_trylock(rwsem); }
19537 +/* why is not _nested version defined */
19538 +/* static inline void prefix##_read_trylock_nested(param, lsc)
19539 +{ au_rw_read_trylock_nested(rwsem, lsc)); }
19540 +static inline void prefix##_write_trylock_nestd(param, lsc)
19541 +{ au_rw_write_trylock_nested(rwsem, lsc); } */
19542 +
19543 +#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
19544 +static inline void prefix##_read_unlock(param) \
19545 +{ au_rw_read_unlock(rwsem); } \
19546 +static inline void prefix##_write_unlock(param) \
19547 +{ au_rw_write_unlock(rwsem); } \
19548 +static inline void prefix##_downgrade_lock(param) \
19549 +{ au_rw_dgrade_lock(rwsem); }
19550 +
19551 +#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
19552 +       AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
19553 +       AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
19554 +
19555 +#endif /* __KERNEL__ */
19556 +#endif /* __AUFS_RWSEM_H__ */
19557 diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
19558 --- /usr/share/empty/fs/aufs/sbinfo.c   1970-01-01 01:00:00.000000000 +0100
19559 +++ linux/fs/aufs/sbinfo.c      2010-10-21 09:52:43.093625591 +0200
19560 @@ -0,0 +1,269 @@
19561 +/*
19562 + * Copyright (C) 2005-2010 Junjiro R. Okajima
19563 + *
19564 + * This program, aufs is free software; you can redistribute it and/or modify
19565 + * it under the terms of the GNU General Public License as published by
19566 + * the Free Software Foundation; either version 2 of the License, or
19567 + * (at your option) any later version.
19568 + *
19569 + * This program is distributed in the hope that it will be useful,
19570 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
19571 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19572 + * GNU General Public License for more details.
19573 + *
19574 + * You should have received a copy of the GNU General Public License
19575 + * along with this program; if not, write to the Free Software
19576 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19577 + */
19578 +
19579 +/*
19580 + * superblock private data
19581 + */
19582 +
19583 +#include "aufs.h"
19584 +
19585 +/*
19586 + * they are necessary regardless sysfs is disabled.
19587 + */
19588 +void au_si_free(struct kobject *kobj)
19589 +{
19590 +       struct au_sbinfo *sbinfo;
19591 +       struct super_block *sb;
19592 +       char *locked __maybe_unused; /* debug only */
19593 +
19594 +       sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
19595 +       AuDebugOn(!list_empty(&sbinfo->si_plink.head));
19596 +       AuDebugOn(sbinfo->si_plink_maint);
19597 +
19598 +       sb = sbinfo->si_sb;
19599 +       si_write_lock(sb);
19600 +       au_xino_clr(sb);
19601 +       au_br_free(sbinfo);
19602 +       si_write_unlock(sb);
19603 +
19604 +       AuDebugOn(radix_tree_gang_lookup
19605 +                 (&sbinfo->au_si_pid.tree, (void **)&locked,
19606 +                  /*first_index*/PID_MAX_DEFAULT - 1,
19607 +                  /*max_items*/sizeof(locked)/sizeof(*locked)));
19608 +
19609 +       kfree(sbinfo->si_branch);
19610 +       kfree(sbinfo->au_si_pid.bitmap);
19611 +       mutex_destroy(&sbinfo->si_xib_mtx);
19612 +       AuRwDestroy(&sbinfo->si_rwsem);
19613 +
19614 +       kfree(sbinfo);
19615 +}
19616 +
19617 +int au_si_alloc(struct super_block *sb)
19618 +{
19619 +       int err;
19620 +       struct au_sbinfo *sbinfo;
19621 +
19622 +       err = -ENOMEM;
19623 +       sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
19624 +       if (unlikely(!sbinfo))
19625 +               goto out;
19626 +
19627 +       BUILD_BUG_ON(sizeof(unsigned long) !=
19628 +                    sizeof(*sbinfo->au_si_pid.bitmap));
19629 +       sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
19630 +                                       sizeof(*sbinfo->au_si_pid.bitmap),
19631 +                                       GFP_NOFS);
19632 +       if (unlikely(!sbinfo->au_si_pid.bitmap))
19633 +               goto out_sbinfo;
19634 +
19635 +       /* will be reallocated separately */
19636 +       sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
19637 +       if (unlikely(!sbinfo->si_branch))
19638 +               goto out_pidmap;
19639 +
19640 +       err = sysaufs_si_init(sbinfo);
19641 +       if (unlikely(err))
19642 +               goto out_br;
19643 +
19644 +       au_nwt_init(&sbinfo->si_nowait);
19645 +       au_rw_init_wlock(&sbinfo->si_rwsem);
19646 +       spin_lock_init(&sbinfo->au_si_pid.tree_lock);
19647 +       INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
19648 +
19649 +       sbinfo->si_bend = -1;
19650 +
19651 +       sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
19652 +       sbinfo->si_wbr_create = AuWbrCreate_Def;
19653 +       sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
19654 +       sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
19655 +
19656 +       sbinfo->si_mntflags = AuOpt_Def;
19657 +
19658 +       mutex_init(&sbinfo->si_xib_mtx);
19659 +       sbinfo->si_xino_brid = -1;
19660 +       /* leave si_xib_last_pindex and si_xib_next_bit */
19661 +
19662 +       sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
19663 +       sbinfo->si_rdblk = AUFS_RDBLK_DEF;
19664 +       sbinfo->si_rdhash = AUFS_RDHASH_DEF;
19665 +       sbinfo->si_dirwh = AUFS_DIRWH_DEF;
19666 +
19667 +       au_spl_init(&sbinfo->si_plink);
19668 +       init_waitqueue_head(&sbinfo->si_plink_wq);
19669 +       spin_lock_init(&sbinfo->si_plink_maint_lock);
19670 +
19671 +       /* leave other members for sysaufs and si_mnt. */
19672 +       sbinfo->si_sb = sb;
19673 +       sb->s_fs_info = sbinfo;
19674 +       si_pid_set(sb);
19675 +       au_debug_sbinfo_init(sbinfo);
19676 +       return 0; /* success */
19677 +
19678 +out_br:
19679 +       kfree(sbinfo->si_branch);
19680 +out_pidmap:
19681 +       kfree(sbinfo->au_si_pid.bitmap);
19682 +out_sbinfo:
19683 +       kfree(sbinfo);
19684 +out:
19685 +       return err;
19686 +}
19687 +
19688 +int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
19689 +{
19690 +       int err, sz;
19691 +       struct au_branch **brp;
19692 +
19693 +       AuRwMustWriteLock(&sbinfo->si_rwsem);
19694 +
19695 +       err = -ENOMEM;
19696 +       sz = sizeof(*brp) * (sbinfo->si_bend + 1);
19697 +       if (unlikely(!sz))
19698 +               sz = sizeof(*brp);
19699 +       brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
19700 +       if (brp) {
19701 +               sbinfo->si_branch = brp;
19702 +               err = 0;
19703 +       }
19704 +
19705 +       return err;
19706 +}
19707 +
19708 +/* ---------------------------------------------------------------------- */
19709 +
19710 +unsigned int au_sigen_inc(struct super_block *sb)
19711 +{
19712 +       unsigned int gen;
19713 +
19714 +       SiMustWriteLock(sb);
19715 +
19716 +       gen = ++au_sbi(sb)->si_generation;
19717 +       au_update_digen(sb->s_root);
19718 +       au_update_iigen(sb->s_root->d_inode);
19719 +       sb->s_root->d_inode->i_version++;
19720 +       return gen;
19721 +}
19722 +
19723 +aufs_bindex_t au_new_br_id(struct super_block *sb)
19724 +{
19725 +       aufs_bindex_t br_id;
19726 +       int i;
19727 +       struct au_sbinfo *sbinfo;
19728 +
19729 +       SiMustWriteLock(sb);
19730 +
19731 +       sbinfo = au_sbi(sb);
19732 +       for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
19733 +               br_id = ++sbinfo->si_last_br_id;
19734 +               if (br_id && au_br_index(sb, br_id) < 0)
19735 +                       return br_id;
19736 +       }
19737 +
19738 +       return -1;
19739 +}
19740 +
19741 +/* ---------------------------------------------------------------------- */
19742 +
19743 +/* dentry and super_block lock. call at entry point */
19744 +void aufs_read_lock(struct dentry *dentry, int flags)
19745 +{
19746 +       si_read_lock(dentry->d_sb, flags);
19747 +       if (au_ftest_lock(flags, DW))
19748 +               di_write_lock_child(dentry);
19749 +       else
19750 +               di_read_lock_child(dentry, flags);
19751 +}
19752 +
19753 +void aufs_read_unlock(struct dentry *dentry, int flags)
19754 +{
19755 +       if (au_ftest_lock(flags, DW))
19756 +               di_write_unlock(dentry);
19757 +       else
19758 +               di_read_unlock(dentry, flags);
19759 +       si_read_unlock(dentry->d_sb);
19760 +}
19761 +
19762 +void aufs_write_lock(struct dentry *dentry)
19763 +{
19764 +       si_write_lock(dentry->d_sb);
19765 +       di_write_lock_child(dentry);
19766 +}
19767 +
19768 +void aufs_write_unlock(struct dentry *dentry)
19769 +{
19770 +       di_write_unlock(dentry);
19771 +       si_write_unlock(dentry->d_sb);
19772 +}
19773 +
19774 +void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
19775 +{
19776 +       si_read_lock(d1->d_sb, flags);
19777 +       di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
19778 +}
19779 +
19780 +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
19781 +{
19782 +       di_write_unlock2(d1, d2);
19783 +       si_read_unlock(d1->d_sb);
19784 +}
19785 +
19786 +/* ---------------------------------------------------------------------- */
19787 +
19788 +int si_pid_test_slow(struct super_block *sb)
19789 +{
19790 +       void *p;
19791 +
19792 +       rcu_read_lock();
19793 +       p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
19794 +       rcu_read_unlock();
19795 +
19796 +       return (long)p;
19797 +}
19798 +
19799 +void si_pid_set_slow(struct super_block *sb)
19800 +{
19801 +       int err;
19802 +       struct au_sbinfo *sbinfo;
19803 +
19804 +       AuDebugOn(si_pid_test_slow(sb));
19805 +
19806 +       sbinfo = au_sbi(sb);
19807 +       err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
19808 +       AuDebugOn(err);
19809 +       spin_lock(&sbinfo->au_si_pid.tree_lock);
19810 +       err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
19811 +                               (void *)1);
19812 +       spin_unlock(&sbinfo->au_si_pid.tree_lock);
19813 +       AuDebugOn(err);
19814 +       radix_tree_preload_end();
19815 +}
19816 +
19817 +void si_pid_clr_slow(struct super_block *sb)
19818 +{
19819 +       void *p;
19820 +       struct au_sbinfo *sbinfo;
19821 +
19822 +       AuDebugOn(!si_pid_test_slow(sb));
19823 +
19824 +       sbinfo = au_sbi(sb);
19825 +       spin_lock(&sbinfo->au_si_pid.tree_lock);
19826 +       p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
19827 +       spin_unlock(&sbinfo->au_si_pid.tree_lock);
19828 +       AuDebugOn(1 != (long)p);
19829 +}
19830 diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
19831 --- /usr/share/empty/fs/aufs/spl.h      1970-01-01 01:00:00.000000000 +0100
19832 +++ linux/fs/aufs/spl.h 2010-10-21 09:52:43.093625591 +0200
19833 @@ -0,0 +1,66 @@
19834 +/*
19835 + * Copyright (C) 2005-2010 Junjiro R. Okajima
19836 + *
19837 + * This program, aufs is free software; you can redistribute it and/or modify
19838 + * it under the terms of the GNU General Public License as published by
19839 + * the Free Software Foundation; either version 2 of the License, or
19840 + * (at your option) any later version.
19841 + *
19842 + * This program is distributed in the hope that it will be useful,
19843 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
19844 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19845 + * GNU General Public License for more details.
19846 + *
19847 + * You should have received a copy of the GNU General Public License
19848 + * along with this program; if not, write to the Free Software
19849 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19850 + */
19851 +
19852 +/*
19853 + * simple list protected by a spinlock
19854 + */
19855 +
19856 +#ifndef __AUFS_SPL_H__
19857 +#define __AUFS_SPL_H__
19858 +
19859 +#ifdef __KERNEL__
19860 +
19861 +#include <linux/spinlock.h>
19862 +#include <linux/list.h>
19863 +#include <linux/rculist.h>
19864 +
19865 +struct au_splhead {
19866 +       spinlock_t              spin;
19867 +       struct list_head        head;
19868 +};
19869 +
19870 +static inline void au_spl_init(struct au_splhead *spl)
19871 +{
19872 +       spin_lock_init(&spl->spin);
19873 +       INIT_LIST_HEAD(&spl->head);
19874 +}
19875 +
19876 +static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
19877 +{
19878 +       spin_lock(&spl->spin);
19879 +       list_add(list, &spl->head);
19880 +       spin_unlock(&spl->spin);
19881 +}
19882 +
19883 +static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
19884 +{
19885 +       spin_lock(&spl->spin);
19886 +       list_del(list);
19887 +       spin_unlock(&spl->spin);
19888 +}
19889 +
19890 +static inline void au_spl_del_rcu(struct list_head *list,
19891 +                                 struct au_splhead *spl)
19892 +{
19893 +       spin_lock(&spl->spin);
19894 +       list_del_rcu(list);
19895 +       spin_unlock(&spl->spin);
19896 +}
19897 +
19898 +#endif /* __KERNEL__ */
19899 +#endif /* __AUFS_SPL_H__ */
19900 diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
19901 --- /usr/share/empty/fs/aufs/super.c    1970-01-01 01:00:00.000000000 +0100
19902 +++ linux/fs/aufs/super.c       2010-10-21 09:52:43.093625591 +0200
19903 @@ -0,0 +1,852 @@
19904 +/*
19905 + * Copyright (C) 2005-2010 Junjiro R. Okajima
19906 + *
19907 + * This program, aufs is free software; you can redistribute it and/or modify
19908 + * it under the terms of the GNU General Public License as published by
19909 + * the Free Software Foundation; either version 2 of the License, or
19910 + * (at your option) any later version.
19911 + *
19912 + * This program is distributed in the hope that it will be useful,
19913 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
19914 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19915 + * GNU General Public License for more details.
19916 + *
19917 + * You should have received a copy of the GNU General Public License
19918 + * along with this program; if not, write to the Free Software
19919 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19920 + */
19921 +
19922 +/*
19923 + * mount and super_block operations
19924 + */
19925 +
19926 +#include <linux/buffer_head.h>
19927 +#include <linux/module.h>
19928 +#include <linux/seq_file.h>
19929 +#include <linux/statfs.h>
19930 +#include "aufs.h"
19931 +
19932 +/*
19933 + * super_operations
19934 + */
19935 +static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
19936 +{
19937 +       struct au_icntnr *c;
19938 +
19939 +       c = au_cache_alloc_icntnr();
19940 +       if (c) {
19941 +               c->vfs_inode.i_version = 1; /* sigen(sb); */
19942 +               c->iinfo.ii_hinode = NULL;
19943 +               return &c->vfs_inode;
19944 +       }
19945 +       return NULL;
19946 +}
19947 +
19948 +static void aufs_destroy_inode(struct inode *inode)
19949 +{
19950 +       au_iinfo_fin(inode);
19951 +       au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
19952 +}
19953 +
19954 +struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
19955 +{
19956 +       struct inode *inode;
19957 +       int err;
19958 +
19959 +       inode = iget_locked(sb, ino);
19960 +       if (unlikely(!inode)) {
19961 +               inode = ERR_PTR(-ENOMEM);
19962 +               goto out;
19963 +       }
19964 +       if (!(inode->i_state & I_NEW))
19965 +               goto out;
19966 +
19967 +       err = au_xigen_new(inode);
19968 +       if (!err)
19969 +               err = au_iinfo_init(inode);
19970 +       if (!err)
19971 +               inode->i_version++;
19972 +       else {
19973 +               iget_failed(inode);
19974 +               inode = ERR_PTR(err);
19975 +       }
19976 +
19977 +out:
19978 +       /* never return NULL */
19979 +       AuDebugOn(!inode);
19980 +       AuTraceErrPtr(inode);
19981 +       return inode;
19982 +}
19983 +
19984 +/* lock free root dinfo */
19985 +static int au_show_brs(struct seq_file *seq, struct super_block *sb)
19986 +{
19987 +       int err;
19988 +       aufs_bindex_t bindex, bend;
19989 +       struct path path;
19990 +       struct au_hdentry *hdp;
19991 +       struct au_branch *br;
19992 +
19993 +       err = 0;
19994 +       bend = au_sbend(sb);
19995 +       hdp = au_di(sb->s_root)->di_hdentry;
19996 +       for (bindex = 0; !err && bindex <= bend; bindex++) {
19997 +               br = au_sbr(sb, bindex);
19998 +               path.mnt = br->br_mnt;
19999 +               path.dentry = hdp[bindex].hd_dentry;
20000 +               err = au_seq_path(seq, &path);
20001 +               if (err > 0)
20002 +                       err = seq_printf(seq, "=%s",
20003 +                                        au_optstr_br_perm(br->br_perm));
20004 +               if (!err && bindex != bend)
20005 +                       err = seq_putc(seq, ':');
20006 +       }
20007 +
20008 +       return err;
20009 +}
20010 +
20011 +static void au_show_wbr_create(struct seq_file *m, int v,
20012 +                              struct au_sbinfo *sbinfo)
20013 +{
20014 +       const char *pat;
20015 +
20016 +       AuRwMustAnyLock(&sbinfo->si_rwsem);
20017 +
20018 +       seq_printf(m, ",create=");
20019 +       pat = au_optstr_wbr_create(v);
20020 +       switch (v) {
20021 +       case AuWbrCreate_TDP:
20022 +       case AuWbrCreate_RR:
20023 +       case AuWbrCreate_MFS:
20024 +       case AuWbrCreate_PMFS:
20025 +               seq_printf(m, pat);
20026 +               break;
20027 +       case AuWbrCreate_MFSV:
20028 +               seq_printf(m, /*pat*/"mfs:%lu",
20029 +                          sbinfo->si_wbr_mfs.mfs_expire / HZ);
20030 +               break;
20031 +       case AuWbrCreate_PMFSV:
20032 +               seq_printf(m, /*pat*/"pmfs:%lu",
20033 +                          sbinfo->si_wbr_mfs.mfs_expire / HZ);
20034 +               break;
20035 +       case AuWbrCreate_MFSRR:
20036 +               seq_printf(m, /*pat*/"mfsrr:%llu",
20037 +                          sbinfo->si_wbr_mfs.mfsrr_watermark);
20038 +               break;
20039 +       case AuWbrCreate_MFSRRV:
20040 +               seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
20041 +                          sbinfo->si_wbr_mfs.mfsrr_watermark,
20042 +                          sbinfo->si_wbr_mfs.mfs_expire / HZ);
20043 +               break;
20044 +       }
20045 +}
20046 +
20047 +static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
20048 +{
20049 +#ifdef CONFIG_SYSFS
20050 +       return 0;
20051 +#else
20052 +       int err;
20053 +       const int len = sizeof(AUFS_XINO_FNAME) - 1;
20054 +       aufs_bindex_t bindex, brid;
20055 +       struct super_block *sb;
20056 +       struct qstr *name;
20057 +       struct file *f;
20058 +       struct dentry *d, *h_root;
20059 +       struct au_hdentry *hdp;
20060 +
20061 +       AuRwMustAnyLock(&sbinfo->si_rwsem);
20062 +
20063 +       err = 0;
20064 +       sb = mnt->mnt_sb;
20065 +       f = au_sbi(sb)->si_xib;
20066 +       if (!f)
20067 +               goto out;
20068 +
20069 +       /* stop printing the default xino path on the first writable branch */
20070 +       h_root = NULL;
20071 +       brid = au_xino_brid(sb);
20072 +       if (brid >= 0) {
20073 +               bindex = au_br_index(sb, brid);
20074 +               hdp = au_di(sb->s_root)->di_hdentry;
20075 +               h_root = hdp[0 + bindex].hd_dentry;
20076 +       }
20077 +       d = f->f_dentry;
20078 +       name = &d->d_name;
20079 +       /* safe ->d_parent because the file is unlinked */
20080 +       if (d->d_parent == h_root
20081 +           && name->len == len
20082 +           && !memcmp(name->name, AUFS_XINO_FNAME, len))
20083 +               goto out;
20084 +
20085 +       seq_puts(seq, ",xino=");
20086 +       err = au_xino_path(seq, f);
20087 +
20088 +out:
20089 +       return err;
20090 +#endif
20091 +}
20092 +
20093 +/* seq_file will re-call me in case of too long string */
20094 +static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
20095 +{
20096 +       int err, n;
20097 +       unsigned int mnt_flags, v;
20098 +       struct super_block *sb;
20099 +       struct au_sbinfo *sbinfo;
20100 +
20101 +#define AuBool(name, str) do { \
20102 +       v = au_opt_test(mnt_flags, name); \
20103 +       if (v != au_opt_test(AuOpt_Def, name)) \
20104 +               seq_printf(m, ",%s" #str, v ? "" : "no"); \
20105 +} while (0)
20106 +
20107 +#define AuStr(name, str) do { \
20108 +       v = mnt_flags & AuOptMask_##name; \
20109 +       if (v != (AuOpt_Def & AuOptMask_##name)) \
20110 +               seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
20111 +} while (0)
20112 +
20113 +#define AuUInt(name, str, val) do { \
20114 +       if (val != AUFS_##name##_DEF) \
20115 +               seq_printf(m, "," #str "=%u", val); \
20116 +} while (0)
20117 +
20118 +       /* lock free root dinfo */
20119 +       sb = mnt->mnt_sb;
20120 +       si_noflush_read_lock(sb);
20121 +       sbinfo = au_sbi(sb);
20122 +       seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
20123 +
20124 +       mnt_flags = au_mntflags(sb);
20125 +       if (au_opt_test(mnt_flags, XINO)) {
20126 +               err = au_show_xino(m, mnt);
20127 +               if (unlikely(err))
20128 +                       goto out;
20129 +       } else
20130 +               seq_puts(m, ",noxino");
20131 +
20132 +       AuBool(TRUNC_XINO, trunc_xino);
20133 +       AuStr(UDBA, udba);
20134 +       AuBool(SHWH, shwh);
20135 +       AuBool(PLINK, plink);
20136 +       AuBool(DIO, dio);
20137 +       /* AuBool(DIRPERM1, dirperm1); */
20138 +       /* AuBool(REFROF, refrof); */
20139 +
20140 +       v = sbinfo->si_wbr_create;
20141 +       if (v != AuWbrCreate_Def)
20142 +               au_show_wbr_create(m, v, sbinfo);
20143 +
20144 +       v = sbinfo->si_wbr_copyup;
20145 +       if (v != AuWbrCopyup_Def)
20146 +               seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
20147 +
20148 +       v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
20149 +       if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
20150 +               seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
20151 +
20152 +       AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
20153 +
20154 +       n = sbinfo->si_rdcache / HZ;
20155 +       AuUInt(RDCACHE, rdcache, n);
20156 +
20157 +       AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
20158 +       AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
20159 +
20160 +       AuBool(SUM, sum);
20161 +       /* AuBool(SUM_W, wsum); */
20162 +       AuBool(WARN_PERM, warn_perm);
20163 +       AuBool(VERBOSE, verbose);
20164 +
20165 +out:
20166 +       /* be sure to print "br:" last */
20167 +       if (!sysaufs_brs) {
20168 +               seq_puts(m, ",br:");
20169 +               au_show_brs(m, sb);
20170 +       }
20171 +       si_read_unlock(sb);
20172 +       return 0;
20173 +
20174 +#undef AuBool
20175 +#undef AuStr
20176 +#undef AuUInt
20177 +}
20178 +
20179 +/* ---------------------------------------------------------------------- */
20180 +
20181 +/* sum mode which returns the summation for statfs(2) */
20182 +
20183 +static u64 au_add_till_max(u64 a, u64 b)
20184 +{
20185 +       u64 old;
20186 +
20187 +       old = a;
20188 +       a += b;
20189 +       if (old < a)
20190 +               return a;
20191 +       return ULLONG_MAX;
20192 +}
20193 +
20194 +static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
20195 +{
20196 +       int err;
20197 +       u64 blocks, bfree, bavail, files, ffree;
20198 +       aufs_bindex_t bend, bindex, i;
20199 +       unsigned char shared;
20200 +       struct path h_path;
20201 +       struct super_block *h_sb;
20202 +
20203 +       blocks = 0;
20204 +       bfree = 0;
20205 +       bavail = 0;
20206 +       files = 0;
20207 +       ffree = 0;
20208 +
20209 +       err = 0;
20210 +       bend = au_sbend(sb);
20211 +       for (bindex = bend; bindex >= 0; bindex--) {
20212 +               h_path.mnt = au_sbr_mnt(sb, bindex);
20213 +               h_sb = h_path.mnt->mnt_sb;
20214 +               shared = 0;
20215 +               for (i = bindex + 1; !shared && i <= bend; i++)
20216 +                       shared = (au_sbr_sb(sb, i) == h_sb);
20217 +               if (shared)
20218 +                       continue;
20219 +
20220 +               /* sb->s_root for NFS is unreliable */
20221 +               h_path.dentry = h_path.mnt->mnt_root;
20222 +               err = vfs_statfs(&h_path, buf);
20223 +               if (unlikely(err))
20224 +                       goto out;
20225 +
20226 +               blocks = au_add_till_max(blocks, buf->f_blocks);
20227 +               bfree = au_add_till_max(bfree, buf->f_bfree);
20228 +               bavail = au_add_till_max(bavail, buf->f_bavail);
20229 +               files = au_add_till_max(files, buf->f_files);
20230 +               ffree = au_add_till_max(ffree, buf->f_ffree);
20231 +       }
20232 +
20233 +       buf->f_blocks = blocks;
20234 +       buf->f_bfree = bfree;
20235 +       buf->f_bavail = bavail;
20236 +       buf->f_files = files;
20237 +       buf->f_ffree = ffree;
20238 +
20239 +out:
20240 +       return err;
20241 +}
20242 +
20243 +static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
20244 +{
20245 +       int err;
20246 +       struct path h_path;
20247 +       struct super_block *sb;
20248 +
20249 +       /* lock free root dinfo */
20250 +       sb = dentry->d_sb;
20251 +       si_noflush_read_lock(sb);
20252 +       if (!au_opt_test(au_mntflags(sb), SUM)) {
20253 +               /* sb->s_root for NFS is unreliable */
20254 +               h_path.mnt = au_sbr_mnt(sb, 0);
20255 +               h_path.dentry = h_path.mnt->mnt_root;
20256 +               err = vfs_statfs(&h_path, buf);
20257 +       } else
20258 +               err = au_statfs_sum(sb, buf);
20259 +       si_read_unlock(sb);
20260 +
20261 +       if (!err) {
20262 +               buf->f_type = AUFS_SUPER_MAGIC;
20263 +               buf->f_namelen = AUFS_MAX_NAMELEN;
20264 +               memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
20265 +       }
20266 +       /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
20267 +
20268 +       return err;
20269 +}
20270 +
20271 +/* ---------------------------------------------------------------------- */
20272 +
20273 +/*
20274 + * this IS NOT for super_operations.
20275 + * I guess it will be reverted someday.
20276 + */
20277 +static void aufs_umount_begin(struct super_block *sb)
20278 +{
20279 +       struct au_sbinfo *sbinfo;
20280 +
20281 +       sbinfo = au_sbi(sb);
20282 +       if (!sbinfo)
20283 +               return;
20284 +
20285 +       si_write_lock(sb);
20286 +       if (au_opt_test(au_mntflags(sb), PLINK))
20287 +               au_plink_put(sb);
20288 +       if (sbinfo->si_wbr_create_ops->fin)
20289 +               sbinfo->si_wbr_create_ops->fin(sb);
20290 +       si_write_unlock(sb);
20291 +}
20292 +
20293 +/* final actions when unmounting a file system */
20294 +static void aufs_put_super(struct super_block *sb)
20295 +{
20296 +       struct au_sbinfo *sbinfo;
20297 +
20298 +       sbinfo = au_sbi(sb);
20299 +       if (!sbinfo)
20300 +               return;
20301 +
20302 +       aufs_umount_begin(sb);
20303 +       dbgaufs_si_fin(sbinfo);
20304 +       kobject_put(&sbinfo->si_kobj);
20305 +}
20306 +
20307 +/* ---------------------------------------------------------------------- */
20308 +
20309 +/*
20310 + * refresh dentry and inode at remount time.
20311 + */
20312 +static int do_refresh(struct dentry *dentry, mode_t type,
20313 +                     unsigned int dir_flags)
20314 +{
20315 +       int err;
20316 +       struct dentry *parent;
20317 +
20318 +       di_write_lock_child(dentry);
20319 +       parent = dget_parent(dentry);
20320 +       di_read_lock_parent(parent, AuLock_IR);
20321 +
20322 +       /* returns the number of positive dentries */
20323 +       err = au_refresh_hdentry(dentry, type);
20324 +       if (err >= 0) {
20325 +               struct inode *inode = dentry->d_inode;
20326 +               err = au_refresh_hinode(inode, dentry);
20327 +               if (!err && type == S_IFDIR)
20328 +                       au_hn_reset(inode, dir_flags);
20329 +       }
20330 +       if (unlikely(err))
20331 +               pr_err("unrecoverable error %d, %.*s\n",
20332 +                      err, AuDLNPair(dentry));
20333 +
20334 +       di_read_unlock(parent, AuLock_IR);
20335 +       dput(parent);
20336 +       di_write_unlock(dentry);
20337 +
20338 +       return err;
20339 +}
20340 +
20341 +static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
20342 +{
20343 +       return S_ISDIR(dentry->d_inode->i_mode);
20344 +}
20345 +
20346 +/* gave up consolidating with refresh_nondir() */
20347 +static int refresh_dir(struct dentry *root, unsigned int sigen)
20348 +{
20349 +       int err, i, j, ndentry, e;
20350 +       struct au_dcsub_pages dpages;
20351 +       struct au_dpage *dpage;
20352 +       struct dentry **dentries;
20353 +       struct inode *inode;
20354 +       const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
20355 +
20356 +       err = 0;
20357 +       list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20358 +               if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20359 +                       ii_write_lock_child(inode);
20360 +                       e = au_refresh_hinode_self(inode, /*do_attr*/1);
20361 +                       ii_write_unlock(inode);
20362 +                       if (unlikely(e)) {
20363 +                               AuDbg("e %d, i%lu\n", e, inode->i_ino);
20364 +                               if (!err)
20365 +                                       err = e;
20366 +                               /* go on even if err */
20367 +                       }
20368 +               }
20369 +
20370 +       e = au_dpages_init(&dpages, GFP_NOFS);
20371 +       if (unlikely(e)) {
20372 +               if (!err)
20373 +                       err = e;
20374 +               goto out;
20375 +       }
20376 +       e = au_dcsub_pages(&dpages, root, test_dir, NULL);
20377 +       if (unlikely(e)) {
20378 +               if (!err)
20379 +                       err = e;
20380 +               goto out_dpages;
20381 +       }
20382 +
20383 +       for (i = 0; !e && i < dpages.ndpage; i++) {
20384 +               dpage = dpages.dpages + i;
20385 +               dentries = dpage->dentries;
20386 +               ndentry = dpage->ndentry;
20387 +               for (j = 0; !e && j < ndentry; j++) {
20388 +                       struct dentry *d;
20389 +
20390 +                       d = dentries[j];
20391 +                       au_dbg_verify_dir_parent(d, sigen);
20392 +                       if (au_digen(d) != sigen) {
20393 +                               e = do_refresh(d, S_IFDIR, flags);
20394 +                               if (unlikely(e && !err))
20395 +                                       err = e;
20396 +                               /* break on err */
20397 +                       }
20398 +               }
20399 +       }
20400 +
20401 +out_dpages:
20402 +       au_dpages_free(&dpages);
20403 +out:
20404 +       return err;
20405 +}
20406 +
20407 +static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
20408 +{
20409 +       return !S_ISDIR(dentry->d_inode->i_mode);
20410 +}
20411 +
20412 +static int refresh_nondir(struct dentry *root, unsigned int sigen,
20413 +                         int do_dentry)
20414 +{
20415 +       int err, i, j, ndentry, e;
20416 +       struct au_dcsub_pages dpages;
20417 +       struct au_dpage *dpage;
20418 +       struct dentry **dentries;
20419 +       struct inode *inode;
20420 +
20421 +       err = 0;
20422 +       list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20423 +               if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20424 +                       ii_write_lock_child(inode);
20425 +                       e = au_refresh_hinode_self(inode, /*do_attr*/1);
20426 +                       ii_write_unlock(inode);
20427 +                       if (unlikely(e)) {
20428 +                               AuDbg("e %d, i%lu\n", e, inode->i_ino);
20429 +                               if (!err)
20430 +                                       err = e;
20431 +                               /* go on even if err */
20432 +                       }
20433 +               }
20434 +
20435 +       if (!do_dentry)
20436 +               goto out;
20437 +
20438 +       e = au_dpages_init(&dpages, GFP_NOFS);
20439 +       if (unlikely(e)) {
20440 +               if (!err)
20441 +                       err = e;
20442 +               goto out;
20443 +       }
20444 +       e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
20445 +       if (unlikely(e)) {
20446 +               if (!err)
20447 +                       err = e;
20448 +               goto out_dpages;
20449 +       }
20450 +
20451 +       for (i = 0; i < dpages.ndpage; i++) {
20452 +               dpage = dpages.dpages + i;
20453 +               dentries = dpage->dentries;
20454 +               ndentry = dpage->ndentry;
20455 +               for (j = 0; j < ndentry; j++) {
20456 +                       struct dentry *d;
20457 +
20458 +                       d = dentries[j];
20459 +                       au_dbg_verify_nondir_parent(d, sigen);
20460 +                       inode = d->d_inode;
20461 +                       if (inode && au_digen(d) != sigen) {
20462 +                               e = do_refresh(d, inode->i_mode & S_IFMT,
20463 +                                              /*dir_flags*/0);
20464 +                               if (unlikely(e && !err))
20465 +                                       err = e;
20466 +                               /* go on even err */
20467 +                       }
20468 +               }
20469 +       }
20470 +
20471 +out_dpages:
20472 +       au_dpages_free(&dpages);
20473 +out:
20474 +       return err;
20475 +}
20476 +
20477 +static void au_remount_refresh(struct super_block *sb, unsigned int flags)
20478 +{
20479 +       int err;
20480 +       unsigned int sigen;
20481 +       struct au_sbinfo *sbinfo;
20482 +       struct dentry *root;
20483 +       struct inode *inode;
20484 +
20485 +       au_sigen_inc(sb);
20486 +       sigen = au_sigen(sb);
20487 +       sbinfo = au_sbi(sb);
20488 +       au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
20489 +
20490 +       root = sb->s_root;
20491 +       DiMustNoWaiters(root);
20492 +       inode = root->d_inode;
20493 +       IiMustNoWaiters(inode);
20494 +       au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
20495 +       di_write_unlock(root);
20496 +
20497 +       err = refresh_dir(root, sigen);
20498 +       if (unlikely(err)) {
20499 +               au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
20500 +               pr_warning("Refreshing directories failed, ignored (%d)\n",
20501 +                          err);
20502 +       }
20503 +
20504 +       if (au_ftest_opts(flags, REFRESH_NONDIR)) {
20505 +               err = refresh_nondir(root, sigen, !err);
20506 +               if (unlikely(err))
20507 +                       pr_warning("Refreshing non-directories failed, ignored"
20508 +                                  "(%d)\n", err);
20509 +       }
20510 +
20511 +       /* aufs_write_lock() calls ..._child() */
20512 +       di_write_lock_child(root);
20513 +       au_cpup_attr_all(root->d_inode, /*force*/1);
20514 +}
20515 +
20516 +/* stop extra interpretation of errno in mount(8), and strange error messages */
20517 +static int cvt_err(int err)
20518 +{
20519 +       AuTraceErr(err);
20520 +
20521 +       switch (err) {
20522 +       case -ENOENT:
20523 +       case -ENOTDIR:
20524 +       case -EEXIST:
20525 +       case -EIO:
20526 +               err = -EINVAL;
20527 +       }
20528 +       return err;
20529 +}
20530 +
20531 +static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
20532 +{
20533 +       int err, do_dx;
20534 +       unsigned int mntflags;
20535 +       struct au_opts opts;
20536 +       struct dentry *root;
20537 +       struct inode *inode;
20538 +       struct au_sbinfo *sbinfo;
20539 +
20540 +       err = 0;
20541 +       root = sb->s_root;
20542 +       if (!data || !*data) {
20543 +               aufs_write_lock(root);
20544 +               err = au_opts_verify(sb, *flags, /*pending*/0);
20545 +               aufs_write_unlock(root);
20546 +               goto out;
20547 +       }
20548 +
20549 +       err = -ENOMEM;
20550 +       memset(&opts, 0, sizeof(opts));
20551 +       opts.opt = (void *)__get_free_page(GFP_NOFS);
20552 +       if (unlikely(!opts.opt))
20553 +               goto out;
20554 +       opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
20555 +       opts.flags = AuOpts_REMOUNT;
20556 +       opts.sb_flags = *flags;
20557 +
20558 +       /* parse it before aufs lock */
20559 +       err = au_opts_parse(sb, data, &opts);
20560 +       if (unlikely(err))
20561 +               goto out_opts;
20562 +
20563 +       sbinfo = au_sbi(sb);
20564 +       inode = root->d_inode;
20565 +       mutex_lock(&inode->i_mutex);
20566 +       aufs_write_lock(root);
20567 +
20568 +       /* au_opts_remount() may return an error */
20569 +       err = au_opts_remount(sb, &opts);
20570 +       au_opts_free(&opts);
20571 +
20572 +       if (au_ftest_opts(opts.flags, REFRESH_DIR)
20573 +           || au_ftest_opts(opts.flags, REFRESH_NONDIR))
20574 +               au_remount_refresh(sb, opts.flags);
20575 +
20576 +       if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
20577 +               mntflags = au_mntflags(sb);
20578 +               do_dx = !!au_opt_test(mntflags, DIO);
20579 +               au_dy_arefresh(do_dx);
20580 +       }
20581 +
20582 +       aufs_write_unlock(root);
20583 +       mutex_unlock(&inode->i_mutex);
20584 +
20585 +out_opts:
20586 +       free_page((unsigned long)opts.opt);
20587 +out:
20588 +       err = cvt_err(err);
20589 +       AuTraceErr(err);
20590 +       return err;
20591 +}
20592 +
20593 +static const struct super_operations aufs_sop = {
20594 +       .alloc_inode    = aufs_alloc_inode,
20595 +       .destroy_inode  = aufs_destroy_inode,
20596 +       /* always deleting, no clearing */
20597 +       .drop_inode     = generic_delete_inode,
20598 +       .show_options   = aufs_show_options,
20599 +       .statfs         = aufs_statfs,
20600 +       .put_super      = aufs_put_super,
20601 +       .remount_fs     = aufs_remount_fs
20602 +};
20603 +
20604 +/* ---------------------------------------------------------------------- */
20605 +
20606 +static int alloc_root(struct super_block *sb)
20607 +{
20608 +       int err;
20609 +       struct inode *inode;
20610 +       struct dentry *root;
20611 +
20612 +       err = -ENOMEM;
20613 +       inode = au_iget_locked(sb, AUFS_ROOT_INO);
20614 +       err = PTR_ERR(inode);
20615 +       if (IS_ERR(inode))
20616 +               goto out;
20617 +
20618 +       inode->i_op = &aufs_dir_iop;
20619 +       inode->i_fop = &aufs_dir_fop;
20620 +       inode->i_mode = S_IFDIR;
20621 +       inode->i_nlink = 2;
20622 +       unlock_new_inode(inode);
20623 +
20624 +       root = d_alloc_root(inode);
20625 +       if (unlikely(!root))
20626 +               goto out_iput;
20627 +       err = PTR_ERR(root);
20628 +       if (IS_ERR(root))
20629 +               goto out_iput;
20630 +
20631 +       err = au_di_init(root);
20632 +       if (!err) {
20633 +               sb->s_root = root;
20634 +               return 0; /* success */
20635 +       }
20636 +       dput(root);
20637 +       goto out; /* do not iput */
20638 +
20639 +out_iput:
20640 +       iget_failed(inode);
20641 +       iput(inode);
20642 +out:
20643 +       return err;
20644 +
20645 +}
20646 +
20647 +static int aufs_fill_super(struct super_block *sb, void *raw_data,
20648 +                          int silent __maybe_unused)
20649 +{
20650 +       int err;
20651 +       struct au_opts opts;
20652 +       struct dentry *root;
20653 +       struct inode *inode;
20654 +       char *arg = raw_data;
20655 +
20656 +       if (unlikely(!arg || !*arg)) {
20657 +               err = -EINVAL;
20658 +               pr_err("no arg\n");
20659 +               goto out;
20660 +       }
20661 +
20662 +       err = -ENOMEM;
20663 +       memset(&opts, 0, sizeof(opts));
20664 +       opts.opt = (void *)__get_free_page(GFP_NOFS);
20665 +       if (unlikely(!opts.opt))
20666 +               goto out;
20667 +       opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
20668 +       opts.sb_flags = sb->s_flags;
20669 +
20670 +       err = au_si_alloc(sb);
20671 +       if (unlikely(err))
20672 +               goto out_opts;
20673 +
20674 +       /* all timestamps always follow the ones on the branch */
20675 +       sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
20676 +       sb->s_op = &aufs_sop;
20677 +       sb->s_magic = AUFS_SUPER_MAGIC;
20678 +       sb->s_maxbytes = 0;
20679 +       au_export_init(sb);
20680 +
20681 +       err = alloc_root(sb);
20682 +       if (unlikely(err)) {
20683 +               si_write_unlock(sb);
20684 +               goto out_info;
20685 +       }
20686 +       root = sb->s_root;
20687 +       inode = root->d_inode;
20688 +
20689 +       /*
20690 +        * actually we can parse options regardless aufs lock here.
20691 +        * but at remount time, parsing must be done before aufs lock.
20692 +        * so we follow the same rule.
20693 +        */
20694 +       ii_write_lock_parent(inode);
20695 +       aufs_write_unlock(root);
20696 +       err = au_opts_parse(sb, arg, &opts);
20697 +       if (unlikely(err))
20698 +               goto out_root;
20699 +
20700 +       /* lock vfs_inode first, then aufs. */
20701 +       mutex_lock(&inode->i_mutex);
20702 +       aufs_write_lock(root);
20703 +       err = au_opts_mount(sb, &opts);
20704 +       au_opts_free(&opts);
20705 +       aufs_write_unlock(root);
20706 +       mutex_unlock(&inode->i_mutex);
20707 +       if (!err)
20708 +               goto out_opts; /* success */
20709 +
20710 +out_root:
20711 +       dput(root);
20712 +       sb->s_root = NULL;
20713 +out_info:
20714 +       kobject_put(&au_sbi(sb)->si_kobj);
20715 +       sb->s_fs_info = NULL;
20716 +out_opts:
20717 +       free_page((unsigned long)opts.opt);
20718 +out:
20719 +       AuTraceErr(err);
20720 +       err = cvt_err(err);
20721 +       AuTraceErr(err);
20722 +       return err;
20723 +}
20724 +
20725 +/* ---------------------------------------------------------------------- */
20726 +
20727 +static int aufs_get_sb(struct file_system_type *fs_type, int flags,
20728 +                      const char *dev_name __maybe_unused, void *raw_data,
20729 +                      struct vfsmount *mnt)
20730 +{
20731 +       int err;
20732 +       struct super_block *sb;
20733 +
20734 +       /* all timestamps always follow the ones on the branch */
20735 +       /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
20736 +       err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
20737 +       if (!err) {
20738 +               sb = mnt->mnt_sb;
20739 +               si_write_lock(sb);
20740 +               sysaufs_brs_add(sb, 0);
20741 +               si_write_unlock(sb);
20742 +       }
20743 +       return err;
20744 +}
20745 +
20746 +struct file_system_type aufs_fs_type = {
20747 +       .name           = AUFS_FSTYPE,
20748 +       .fs_flags       =
20749 +               FS_RENAME_DOES_D_MOVE   /* a race between rename and others */
20750 +               | FS_REVAL_DOT,         /* for NFS branch and udba */
20751 +       .get_sb         = aufs_get_sb,
20752 +       .kill_sb        = generic_shutdown_super,
20753 +       /* no need to __module_get() and module_put(). */
20754 +       .owner          = THIS_MODULE,
20755 +};
20756 diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
20757 --- /usr/share/empty/fs/aufs/super.h    1970-01-01 01:00:00.000000000 +0100
20758 +++ linux/fs/aufs/super.h       2010-10-21 09:52:43.093625591 +0200
20759 @@ -0,0 +1,465 @@
20760 +/*
20761 + * Copyright (C) 2005-2010 Junjiro R. Okajima
20762 + *
20763 + * This program, aufs is free software; you can redistribute it and/or modify
20764 + * it under the terms of the GNU General Public License as published by
20765 + * the Free Software Foundation; either version 2 of the License, or
20766 + * (at your option) any later version.
20767 + *
20768 + * This program is distributed in the hope that it will be useful,
20769 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
20770 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20771 + * GNU General Public License for more details.
20772 + *
20773 + * You should have received a copy of the GNU General Public License
20774 + * along with this program; if not, write to the Free Software
20775 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20776 + */
20777 +
20778 +/*
20779 + * super_block operations
20780 + */
20781 +
20782 +#ifndef __AUFS_SUPER_H__
20783 +#define __AUFS_SUPER_H__
20784 +
20785 +#ifdef __KERNEL__
20786 +
20787 +#include <linux/fs.h>
20788 +#include <linux/aufs_type.h>
20789 +#include "rwsem.h"
20790 +#include "spl.h"
20791 +#include "wkq.h"
20792 +
20793 +typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
20794 +typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
20795 +                              loff_t *);
20796 +
20797 +/* policies to select one among multiple writable branches */
20798 +struct au_wbr_copyup_operations {
20799 +       int (*copyup)(struct dentry *dentry);
20800 +};
20801 +
20802 +struct au_wbr_create_operations {
20803 +       int (*create)(struct dentry *dentry, int isdir);
20804 +       int (*init)(struct super_block *sb);
20805 +       int (*fin)(struct super_block *sb);
20806 +};
20807 +
20808 +struct au_wbr_mfs {
20809 +       struct mutex    mfs_lock; /* protect this structure */
20810 +       unsigned long   mfs_jiffy;
20811 +       unsigned long   mfs_expire;
20812 +       aufs_bindex_t   mfs_bindex;
20813 +
20814 +       unsigned long long      mfsrr_bytes;
20815 +       unsigned long long      mfsrr_watermark;
20816 +};
20817 +
20818 +struct au_branch;
20819 +struct au_sbinfo {
20820 +       /* nowait tasks in the system-wide workqueue */
20821 +       struct au_nowait_tasks  si_nowait;
20822 +
20823 +       /*
20824 +        * tried sb->s_umount, but failed due to the dependecy between i_mutex.
20825 +        * rwsem for au_sbinfo is necessary.
20826 +        */
20827 +       struct au_rwsem         si_rwsem;
20828 +
20829 +       /* prevent recursive locking in deleting inode */
20830 +       struct {
20831 +               unsigned long           *bitmap;
20832 +               spinlock_t              tree_lock;
20833 +               struct radix_tree_root  tree;
20834 +       } au_si_pid;
20835 +
20836 +       /* branch management */
20837 +       unsigned int            si_generation;
20838 +
20839 +       /* see above flags */
20840 +       unsigned char           au_si_status;
20841 +
20842 +       aufs_bindex_t           si_bend;
20843 +       aufs_bindex_t           si_last_br_id;
20844 +       struct au_branch        **si_branch;
20845 +
20846 +       /* policy to select a writable branch */
20847 +       unsigned char           si_wbr_copyup;
20848 +       unsigned char           si_wbr_create;
20849 +       struct au_wbr_copyup_operations *si_wbr_copyup_ops;
20850 +       struct au_wbr_create_operations *si_wbr_create_ops;
20851 +
20852 +       /* round robin */
20853 +       atomic_t                si_wbr_rr_next;
20854 +
20855 +       /* most free space */
20856 +       struct au_wbr_mfs       si_wbr_mfs;
20857 +
20858 +       /* mount flags */
20859 +       /* include/asm-ia64/siginfo.h defines a macro named si_flags */
20860 +       unsigned int            si_mntflags;
20861 +
20862 +       /* external inode number (bitmap and translation table) */
20863 +       au_readf_t              si_xread;
20864 +       au_writef_t             si_xwrite;
20865 +       struct file             *si_xib;
20866 +       struct mutex            si_xib_mtx; /* protect xib members */
20867 +       unsigned long           *si_xib_buf;
20868 +       unsigned long           si_xib_last_pindex;
20869 +       int                     si_xib_next_bit;
20870 +       aufs_bindex_t           si_xino_brid;
20871 +       /* reserved for future use */
20872 +       /* unsigned long long   si_xib_limit; */        /* Max xib file size */
20873 +
20874 +#ifdef CONFIG_AUFS_EXPORT
20875 +       /* i_generation */
20876 +       struct file             *si_xigen;
20877 +       atomic_t                si_xigen_next;
20878 +#endif
20879 +
20880 +       /* vdir parameters */
20881 +       unsigned long           si_rdcache;     /* max cache time in HZ */
20882 +       unsigned int            si_rdblk;       /* deblk size */
20883 +       unsigned int            si_rdhash;      /* hash size */
20884 +
20885 +       /*
20886 +        * If the number of whiteouts are larger than si_dirwh, leave all of
20887 +        * them after au_whtmp_ren to reduce the cost of rmdir(2).
20888 +        * future fsck.aufs or kernel thread will remove them later.
20889 +        * Otherwise, remove all whiteouts and the dir in rmdir(2).
20890 +        */
20891 +       unsigned int            si_dirwh;
20892 +
20893 +       /*
20894 +        * rename(2) a directory with all children.
20895 +        */
20896 +       /* reserved for future use */
20897 +       /* int                  si_rendir; */
20898 +
20899 +       /* pseudo_link list */
20900 +       struct au_splhead       si_plink;
20901 +       wait_queue_head_t       si_plink_wq;
20902 +       spinlock_t              si_plink_maint_lock;
20903 +       struct file             *si_plink_maint;
20904 +
20905 +       /*
20906 +        * sysfs and lifetime management.
20907 +        * this is not a small structure and it may be a waste of memory in case
20908 +        * of sysfs is disabled, particulary when many aufs-es are mounted.
20909 +        * but using sysfs is majority.
20910 +        */
20911 +       struct kobject          si_kobj;
20912 +#ifdef CONFIG_DEBUG_FS
20913 +       struct dentry            *si_dbgaufs, *si_dbgaufs_xib;
20914 +#ifdef CONFIG_AUFS_EXPORT
20915 +       struct dentry            *si_dbgaufs_xigen;
20916 +#endif
20917 +#endif
20918 +
20919 +       /* dirty, necessary for unmounting, sysfs and sysrq */
20920 +       struct super_block      *si_sb;
20921 +};
20922 +
20923 +/* sbinfo status flags */
20924 +/*
20925 + * set true when refresh_dirs() failed at remount time.
20926 + * then try refreshing dirs at access time again.
20927 + * if it is false, refreshing dirs at access time is unnecesary
20928 + */
20929 +#define AuSi_FAILED_REFRESH_DIRS       1
20930 +static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
20931 +                                          unsigned int flag)
20932 +{
20933 +       AuRwMustAnyLock(&sbi->si_rwsem);
20934 +       return sbi->au_si_status & flag;
20935 +}
20936 +#define au_ftest_si(sbinfo, name)      au_do_ftest_si(sbinfo, AuSi_##name)
20937 +#define au_fset_si(sbinfo, name) do { \
20938 +       AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
20939 +       (sbinfo)->au_si_status |= AuSi_##name; \
20940 +} while (0)
20941 +#define au_fclr_si(sbinfo, name) do { \
20942 +       AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
20943 +       (sbinfo)->au_si_status &= ~AuSi_##name; \
20944 +} while (0)
20945 +
20946 +/* ---------------------------------------------------------------------- */
20947 +
20948 +/* policy to select one among writable branches */
20949 +#define AuWbrCopyup(sbinfo, ...) \
20950 +       ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
20951 +#define AuWbrCreate(sbinfo, ...) \
20952 +       ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
20953 +
20954 +/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
20955 +#define AuLock_DW              1               /* write-lock dentry */
20956 +#define AuLock_IR              (1 << 1)        /* read-lock inode */
20957 +#define AuLock_IW              (1 << 2)        /* write-lock inode */
20958 +#define AuLock_FLUSH           (1 << 3)        /* wait for 'nowait' tasks */
20959 +#define AuLock_DIR             (1 << 4)        /* target is a dir */
20960 +#define au_ftest_lock(flags, name)     ((flags) & AuLock_##name)
20961 +#define au_fset_lock(flags, name)      { (flags) |= AuLock_##name; }
20962 +#define au_fclr_lock(flags, name)      { (flags) &= ~AuLock_##name; }
20963 +
20964 +/* ---------------------------------------------------------------------- */
20965 +
20966 +/* super.c */
20967 +extern struct file_system_type aufs_fs_type;
20968 +struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
20969 +
20970 +/* sbinfo.c */
20971 +void au_si_free(struct kobject *kobj);
20972 +int au_si_alloc(struct super_block *sb);
20973 +int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
20974 +
20975 +unsigned int au_sigen_inc(struct super_block *sb);
20976 +aufs_bindex_t au_new_br_id(struct super_block *sb);
20977 +
20978 +void aufs_read_lock(struct dentry *dentry, int flags);
20979 +void aufs_read_unlock(struct dentry *dentry, int flags);
20980 +void aufs_write_lock(struct dentry *dentry);
20981 +void aufs_write_unlock(struct dentry *dentry);
20982 +void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
20983 +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
20984 +
20985 +int si_pid_test_slow(struct super_block *sb);
20986 +void si_pid_set_slow(struct super_block *sb);
20987 +void si_pid_clr_slow(struct super_block *sb);
20988 +
20989 +/* wbr_policy.c */
20990 +extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
20991 +extern struct au_wbr_create_operations au_wbr_create_ops[];
20992 +int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
20993 +
20994 +/* ---------------------------------------------------------------------- */
20995 +
20996 +static inline struct au_sbinfo *au_sbi(struct super_block *sb)
20997 +{
20998 +       return sb->s_fs_info;
20999 +}
21000 +
21001 +/* ---------------------------------------------------------------------- */
21002 +
21003 +#ifdef CONFIG_AUFS_EXPORT
21004 +void au_export_init(struct super_block *sb);
21005 +
21006 +static inline int au_test_nfsd(void)
21007 +{
21008 +       struct task_struct *tsk = current;
21009 +
21010 +       return (tsk->flags & PF_KTHREAD)
21011 +               && !strcmp(tsk->comm, "nfsd");
21012 +}
21013 +
21014 +void au_xigen_inc(struct inode *inode);
21015 +int au_xigen_new(struct inode *inode);
21016 +int au_xigen_set(struct super_block *sb, struct file *base);
21017 +void au_xigen_clr(struct super_block *sb);
21018 +
21019 +static inline int au_busy_or_stale(void)
21020 +{
21021 +       if (!au_test_nfsd())
21022 +               return -EBUSY;
21023 +       return -ESTALE;
21024 +}
21025 +#else
21026 +AuStubVoid(au_export_init, struct super_block *sb)
21027 +AuStubInt0(au_test_nfsd, void)
21028 +AuStubVoid(au_xigen_inc, struct inode *inode)
21029 +AuStubInt0(au_xigen_new, struct inode *inode)
21030 +AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
21031 +AuStubVoid(au_xigen_clr, struct super_block *sb)
21032 +static inline int au_busy_or_stale(void)
21033 +{
21034 +       return -EBUSY;
21035 +}
21036 +#endif /* CONFIG_AUFS_EXPORT */
21037 +
21038 +/* ---------------------------------------------------------------------- */
21039 +
21040 +static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
21041 +{
21042 +       /*
21043 +        * This function is a dynamic '__init' fucntion actually,
21044 +        * so the tiny check for si_rwsem is unnecessary.
21045 +        */
21046 +       /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
21047 +#ifdef CONFIG_DEBUG_FS
21048 +       sbinfo->si_dbgaufs = NULL;
21049 +       sbinfo->si_dbgaufs_xib = NULL;
21050 +#ifdef CONFIG_AUFS_EXPORT
21051 +       sbinfo->si_dbgaufs_xigen = NULL;
21052 +#endif
21053 +#endif
21054 +}
21055 +
21056 +/* ---------------------------------------------------------------------- */
21057 +
21058 +static inline pid_t si_pid_bit(void)
21059 +{
21060 +       /* the origin of pid is 1, but the bitmap's is 0 */
21061 +       return current->pid - 1;
21062 +}
21063 +
21064 +static inline int si_pid_test(struct super_block *sb)
21065 +{
21066 +       pid_t bit = si_pid_bit();
21067 +       if (bit < PID_MAX_DEFAULT)
21068 +               return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21069 +       else
21070 +               return si_pid_test_slow(sb);
21071 +}
21072 +
21073 +static inline void si_pid_set(struct super_block *sb)
21074 +{
21075 +       pid_t bit = si_pid_bit();
21076 +       if (bit < PID_MAX_DEFAULT) {
21077 +               AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21078 +               set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21079 +               /* smp_mb(); */
21080 +       } else
21081 +               si_pid_set_slow(sb);
21082 +}
21083 +
21084 +static inline void si_pid_clr(struct super_block *sb)
21085 +{
21086 +       pid_t bit = si_pid_bit();
21087 +       if (bit < PID_MAX_DEFAULT) {
21088 +               AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21089 +               clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21090 +               /* smp_mb(); */
21091 +       } else
21092 +               si_pid_clr_slow(sb);
21093 +}
21094 +
21095 +/* ---------------------------------------------------------------------- */
21096 +
21097 +/* lock superblock. mainly for entry point functions */
21098 +/*
21099 + * __si_read_lock, __si_write_lock,
21100 + * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
21101 + */
21102 +AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
21103 +
21104 +#define SiMustNoWaiters(sb)    AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
21105 +#define SiMustAnyLock(sb)      AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
21106 +#define SiMustWriteLock(sb)    AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
21107 +
21108 +static inline void si_noflush_read_lock(struct super_block *sb)
21109 +{
21110 +       __si_read_lock(sb);
21111 +       si_pid_set(sb);
21112 +}
21113 +
21114 +static inline int si_noflush_read_trylock(struct super_block *sb)
21115 +{
21116 +       int locked = __si_read_trylock(sb);
21117 +       if (locked)
21118 +               si_pid_set(sb);
21119 +       return locked;
21120 +}
21121 +
21122 +static inline void si_noflush_write_lock(struct super_block *sb)
21123 +{
21124 +       __si_write_lock(sb);
21125 +       si_pid_set(sb);
21126 +}
21127 +
21128 +static inline int si_noflush_write_trylock(struct super_block *sb)
21129 +{
21130 +       int locked = __si_write_trylock(sb);
21131 +       if (locked)
21132 +               si_pid_set(sb);
21133 +       return locked;
21134 +}
21135 +
21136 +static inline void si_read_lock(struct super_block *sb, int flags)
21137 +{
21138 +       if (au_ftest_lock(flags, FLUSH))
21139 +               au_nwt_flush(&au_sbi(sb)->si_nowait);
21140 +       si_noflush_read_lock(sb);
21141 +}
21142 +
21143 +static inline int si_read_trylock(struct super_block *sb, int flags)
21144 +{
21145 +       if (au_ftest_lock(flags, FLUSH))
21146 +               au_nwt_flush(&au_sbi(sb)->si_nowait);
21147 +       return si_noflush_read_trylock(sb);
21148 +}
21149 +
21150 +static inline void si_read_unlock(struct super_block *sb)
21151 +{
21152 +       si_pid_clr(sb);
21153 +       __si_read_unlock(sb);
21154 +}
21155 +
21156 +static inline void si_write_lock(struct super_block *sb)
21157 +{
21158 +       au_nwt_flush(&au_sbi(sb)->si_nowait);
21159 +       si_noflush_write_lock(sb);
21160 +}
21161 +
21162 +#if 0 /* unused */
21163 +static inline int si_write_trylock(struct super_block *sb, int flags)
21164 +{
21165 +       if (au_ftest_lock(flags, FLUSH))
21166 +               au_nwt_flush(&au_sbi(sb)->si_nowait);
21167 +       return si_noflush_write_trylock(sb);
21168 +}
21169 +#endif
21170 +
21171 +static inline void si_write_unlock(struct super_block *sb)
21172 +{
21173 +       si_pid_clr(sb);
21174 +       __si_write_unlock(sb);
21175 +}
21176 +
21177 +#if 0 /* unused */
21178 +static inline void si_downgrade_lock(struct super_block *sb)
21179 +{
21180 +       __si_downgrade_lock(sb);
21181 +}
21182 +#endif
21183 +
21184 +/* ---------------------------------------------------------------------- */
21185 +
21186 +static inline aufs_bindex_t au_sbend(struct super_block *sb)
21187 +{
21188 +       SiMustAnyLock(sb);
21189 +       return au_sbi(sb)->si_bend;
21190 +}
21191 +
21192 +static inline unsigned int au_mntflags(struct super_block *sb)
21193 +{
21194 +       SiMustAnyLock(sb);
21195 +       return au_sbi(sb)->si_mntflags;
21196 +}
21197 +
21198 +static inline unsigned int au_sigen(struct super_block *sb)
21199 +{
21200 +       SiMustAnyLock(sb);
21201 +       return au_sbi(sb)->si_generation;
21202 +}
21203 +
21204 +static inline struct au_branch *au_sbr(struct super_block *sb,
21205 +                                      aufs_bindex_t bindex)
21206 +{
21207 +       SiMustAnyLock(sb);
21208 +       return au_sbi(sb)->si_branch[0 + bindex];
21209 +}
21210 +
21211 +static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
21212 +{
21213 +       SiMustWriteLock(sb);
21214 +       au_sbi(sb)->si_xino_brid = brid;
21215 +}
21216 +
21217 +static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
21218 +{
21219 +       SiMustAnyLock(sb);
21220 +       return au_sbi(sb)->si_xino_brid;
21221 +}
21222 +
21223 +#endif /* __KERNEL__ */
21224 +#endif /* __AUFS_SUPER_H__ */
21225 diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
21226 --- /usr/share/empty/fs/aufs/sysaufs.c  1970-01-01 01:00:00.000000000 +0100
21227 +++ linux/fs/aufs/sysaufs.c     2010-10-21 09:52:43.093625591 +0200
21228 @@ -0,0 +1,107 @@
21229 +/*
21230 + * Copyright (C) 2005-2010 Junjiro R. Okajima
21231 + *
21232 + * This program, aufs is free software; you can redistribute it and/or modify
21233 + * it under the terms of the GNU General Public License as published by
21234 + * the Free Software Foundation; either version 2 of the License, or
21235 + * (at your option) any later version.
21236 + *
21237 + * This program is distributed in the hope that it will be useful,
21238 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21239 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21240 + * GNU General Public License for more details.
21241 + *
21242 + * You should have received a copy of the GNU General Public License
21243 + * along with this program; if not, write to the Free Software
21244 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21245 + */
21246 +
21247 +/*
21248 + * sysfs interface and lifetime management
21249 + * they are necessary regardless sysfs is disabled.
21250 + */
21251 +
21252 +#include <linux/fs.h>
21253 +#include <linux/random.h>
21254 +#include <linux/sysfs.h>
21255 +#include "aufs.h"
21256 +
21257 +unsigned long sysaufs_si_mask;
21258 +struct kset *sysaufs_ket;
21259 +
21260 +#define AuSiAttr(_name) { \
21261 +       .attr   = { .name = __stringify(_name), .mode = 0444 }, \
21262 +       .show   = sysaufs_si_##_name,                           \
21263 +}
21264 +
21265 +static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
21266 +struct attribute *sysaufs_si_attrs[] = {
21267 +       &sysaufs_si_attr_xi_path.attr,
21268 +       NULL,
21269 +};
21270 +
21271 +static const struct sysfs_ops au_sbi_ops = {
21272 +       .show   = sysaufs_si_show
21273 +};
21274 +
21275 +static struct kobj_type au_sbi_ktype = {
21276 +       .release        = au_si_free,
21277 +       .sysfs_ops      = &au_sbi_ops,
21278 +       .default_attrs  = sysaufs_si_attrs
21279 +};
21280 +
21281 +/* ---------------------------------------------------------------------- */
21282 +
21283 +int sysaufs_si_init(struct au_sbinfo *sbinfo)
21284 +{
21285 +       int err;
21286 +
21287 +       sbinfo->si_kobj.kset = sysaufs_ket;
21288 +       /* cf. sysaufs_name() */
21289 +       err = kobject_init_and_add
21290 +               (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->kobj*/NULL,
21291 +                SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
21292 +
21293 +       dbgaufs_si_null(sbinfo);
21294 +       if (!err) {
21295 +               err = dbgaufs_si_init(sbinfo);
21296 +               if (unlikely(err))
21297 +                       kobject_put(&sbinfo->si_kobj);
21298 +       }
21299 +       return err;
21300 +}
21301 +
21302 +void sysaufs_fin(void)
21303 +{
21304 +       dbgaufs_fin();
21305 +       sysfs_remove_group(&sysaufs_ket->kobj, sysaufs_attr_group);
21306 +       kset_unregister(sysaufs_ket);
21307 +}
21308 +
21309 +int __init sysaufs_init(void)
21310 +{
21311 +       int err;
21312 +
21313 +       do {
21314 +               get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
21315 +       } while (!sysaufs_si_mask);
21316 +
21317 +       err = -EINVAL;
21318 +       sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
21319 +       if (unlikely(!sysaufs_ket))
21320 +               goto out;
21321 +       err = PTR_ERR(sysaufs_ket);
21322 +       if (IS_ERR(sysaufs_ket))
21323 +               goto out;
21324 +       err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
21325 +       if (unlikely(err)) {
21326 +               kset_unregister(sysaufs_ket);
21327 +               goto out;
21328 +       }
21329 +
21330 +       err = dbgaufs_init();
21331 +       if (unlikely(err))
21332 +               sysaufs_fin();
21333 +out:
21334 +       return err;
21335 +}
21336 diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
21337 --- /usr/share/empty/fs/aufs/sysaufs.h  1970-01-01 01:00:00.000000000 +0100
21338 +++ linux/fs/aufs/sysaufs.h     2010-10-21 09:52:43.093625591 +0200
21339 @@ -0,0 +1,105 @@
21340 +/*
21341 + * Copyright (C) 2005-2010 Junjiro R. Okajima
21342 + *
21343 + * This program, aufs is free software; you can redistribute it and/or modify
21344 + * it under the terms of the GNU General Public License as published by
21345 + * the Free Software Foundation; either version 2 of the License, or
21346 + * (at your option) any later version.
21347 + *
21348 + * This program is distributed in the hope that it will be useful,
21349 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21350 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21351 + * GNU General Public License for more details.
21352 + *
21353 + * You should have received a copy of the GNU General Public License
21354 + * along with this program; if not, write to the Free Software
21355 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21356 + */
21357 +
21358 +/*
21359 + * sysfs interface and mount lifetime management
21360 + */
21361 +
21362 +#ifndef __SYSAUFS_H__
21363 +#define __SYSAUFS_H__
21364 +
21365 +#ifdef __KERNEL__
21366 +
21367 +#include <linux/sysfs.h>
21368 +#include <linux/aufs_type.h>
21369 +#include "module.h"
21370 +
21371 +struct super_block;
21372 +struct au_sbinfo;
21373 +
21374 +struct sysaufs_si_attr {
21375 +       struct attribute attr;
21376 +       int (*show)(struct seq_file *seq, struct super_block *sb);
21377 +};
21378 +
21379 +/* ---------------------------------------------------------------------- */
21380 +
21381 +/* sysaufs.c */
21382 +extern unsigned long sysaufs_si_mask;
21383 +extern struct kset *sysaufs_ket;
21384 +extern struct attribute *sysaufs_si_attrs[];
21385 +int sysaufs_si_init(struct au_sbinfo *sbinfo);
21386 +int __init sysaufs_init(void);
21387 +void sysaufs_fin(void);
21388 +
21389 +/* ---------------------------------------------------------------------- */
21390 +
21391 +/* some people doesn't like to show a pointer in kernel */
21392 +static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
21393 +{
21394 +       return sysaufs_si_mask ^ (unsigned long)sbinfo;
21395 +}
21396 +
21397 +#define SysaufsSiNamePrefix    "si_"
21398 +#define SysaufsSiNameLen       (sizeof(SysaufsSiNamePrefix) + 16)
21399 +static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
21400 +{
21401 +       snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
21402 +                sysaufs_si_id(sbinfo));
21403 +}
21404 +
21405 +struct au_branch;
21406 +#ifdef CONFIG_SYSFS
21407 +/* sysfs.c */
21408 +extern struct attribute_group *sysaufs_attr_group;
21409 +
21410 +int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
21411 +ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
21412 +                        char *buf);
21413 +
21414 +void sysaufs_br_init(struct au_branch *br);
21415 +void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
21416 +void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
21417 +
21418 +#define sysaufs_brs_init()     do {} while (0)
21419 +
21420 +#else
21421 +#define sysaufs_attr_group     NULL
21422 +
21423 +AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
21424 +
21425 +static inline
21426 +ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
21427 +                        char *buf)
21428 +{
21429 +       return 0;
21430 +}
21431 +
21432 +AuStubVoid(sysaufs_br_init, struct au_branch *br)
21433 +AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
21434 +AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
21435 +
21436 +static inline void sysaufs_brs_init(void)
21437 +{
21438 +       sysaufs_brs = 0;
21439 +}
21440 +
21441 +#endif /* CONFIG_SYSFS */
21442 +
21443 +#endif /* __KERNEL__ */
21444 +#endif /* __SYSAUFS_H__ */
21445 diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
21446 --- /usr/share/empty/fs/aufs/sysfs.c    1970-01-01 01:00:00.000000000 +0100
21447 +++ linux/fs/aufs/sysfs.c       2010-10-21 09:52:43.093625591 +0200
21448 @@ -0,0 +1,250 @@
21449 +/*
21450 + * Copyright (C) 2005-2010 Junjiro R. Okajima
21451 + *
21452 + * This program, aufs is free software; you can redistribute it and/or modify
21453 + * it under the terms of the GNU General Public License as published by
21454 + * the Free Software Foundation; either version 2 of the License, or
21455 + * (at your option) any later version.
21456 + *
21457 + * This program is distributed in the hope that it will be useful,
21458 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21459 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21460 + * GNU General Public License for more details.
21461 + *
21462 + * You should have received a copy of the GNU General Public License
21463 + * along with this program; if not, write to the Free Software
21464 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21465 + */
21466 +
21467 +/*
21468 + * sysfs interface
21469 + */
21470 +
21471 +#include <linux/fs.h>
21472 +#include <linux/module.h>
21473 +#include <linux/seq_file.h>
21474 +#include <linux/sysfs.h>
21475 +#include "aufs.h"
21476 +
21477 +#ifdef CONFIG_AUFS_FS_MODULE
21478 +/* this entry violates the "one line per file" policy of sysfs */
21479 +static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
21480 +                          char *buf)
21481 +{
21482 +       ssize_t err;
21483 +       static char *conf =
21484 +/* this file is generated at compiling */
21485 +#include "conf.str"
21486 +               ;
21487 +
21488 +       err = snprintf(buf, PAGE_SIZE, conf);
21489 +       if (unlikely(err >= PAGE_SIZE))
21490 +               err = -EFBIG;
21491 +       return err;
21492 +}
21493 +
21494 +static struct kobj_attribute au_config_attr = __ATTR_RO(config);
21495 +#endif
21496 +
21497 +static struct attribute *au_attr[] = {
21498 +#ifdef CONFIG_AUFS_FS_MODULE
21499 +       &au_config_attr.attr,
21500 +#endif
21501 +       NULL,   /* need to NULL terminate the list of attributes */
21502 +};
21503 +
21504 +static struct attribute_group sysaufs_attr_group_body = {
21505 +       .attrs = au_attr
21506 +};
21507 +
21508 +struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
21509 +
21510 +/* ---------------------------------------------------------------------- */
21511 +
21512 +int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
21513 +{
21514 +       int err;
21515 +
21516 +       SiMustAnyLock(sb);
21517 +
21518 +       err = 0;
21519 +       if (au_opt_test(au_mntflags(sb), XINO)) {
21520 +               err = au_xino_path(seq, au_sbi(sb)->si_xib);
21521 +               seq_putc(seq, '\n');
21522 +       }
21523 +       return err;
21524 +}
21525 +
21526 +/*
21527 + * the lifetime of branch is independent from the entry under sysfs.
21528 + * sysfs handles the lifetime of the entry, and never call ->show() after it is
21529 + * unlinked.
21530 + */
21531 +static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
21532 +                        aufs_bindex_t bindex)
21533 +{
21534 +       struct path path;
21535 +       struct dentry *root;
21536 +       struct au_branch *br;
21537 +
21538 +       AuDbg("b%d\n", bindex);
21539 +
21540 +       root = sb->s_root;
21541 +       di_read_lock_parent(root, !AuLock_IR);
21542 +       br = au_sbr(sb, bindex);
21543 +       path.mnt = br->br_mnt;
21544 +       path.dentry = au_h_dptr(root, bindex);
21545 +       au_seq_path(seq, &path);
21546 +       di_read_unlock(root, !AuLock_IR);
21547 +       seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
21548 +       return 0;
21549 +}
21550 +
21551 +/* ---------------------------------------------------------------------- */
21552 +
21553 +static struct seq_file *au_seq(char *p, ssize_t len)
21554 +{
21555 +       struct seq_file *seq;
21556 +
21557 +       seq = kzalloc(sizeof(*seq), GFP_NOFS);
21558 +       if (seq) {
21559 +               /* mutex_init(&seq.lock); */
21560 +               seq->buf = p;
21561 +               seq->size = len;
21562 +               return seq; /* success */
21563 +       }
21564 +
21565 +       seq = ERR_PTR(-ENOMEM);
21566 +       return seq;
21567 +}
21568 +
21569 +#define SysaufsBr_PREFIX "br"
21570 +
21571 +/* todo: file size may exceed PAGE_SIZE */
21572 +ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
21573 +                       char *buf)
21574 +{
21575 +       ssize_t err;
21576 +       long l;
21577 +       aufs_bindex_t bend;
21578 +       struct au_sbinfo *sbinfo;
21579 +       struct super_block *sb;
21580 +       struct seq_file *seq;
21581 +       char *name;
21582 +       struct attribute **cattr;
21583 +
21584 +       sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
21585 +       sb = sbinfo->si_sb;
21586 +
21587 +       /*
21588 +        * prevent a race condition between sysfs and aufs.
21589 +        * for instance, sysfs_file_read() calls sysfs_get_active_two() which
21590 +        * prohibits maintaining the sysfs entries.
21591 +        * hew we acquire read lock after sysfs_get_active_two().
21592 +        * on the other hand, the remount process may maintain the sysfs/aufs
21593 +        * entries after acquiring write lock.
21594 +        * it can cause a deadlock.
21595 +        * simply we gave up processing read here.
21596 +        */
21597 +       err = -EBUSY;
21598 +       if (unlikely(!si_noflush_read_trylock(sb)))
21599 +               goto out;
21600 +
21601 +       seq = au_seq(buf, PAGE_SIZE);
21602 +       err = PTR_ERR(seq);
21603 +       if (IS_ERR(seq))
21604 +               goto out_unlock;
21605 +
21606 +       name = (void *)attr->name;
21607 +       cattr = sysaufs_si_attrs;
21608 +       while (*cattr) {
21609 +               if (!strcmp(name, (*cattr)->name)) {
21610 +                       err = container_of(*cattr, struct sysaufs_si_attr, attr)
21611 +                               ->show(seq, sb);
21612 +                       goto out_seq;
21613 +               }
21614 +               cattr++;
21615 +       }
21616 +
21617 +       bend = au_sbend(sb);
21618 +       if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
21619 +               name += sizeof(SysaufsBr_PREFIX) - 1;
21620 +               err = strict_strtol(name, 10, &l);
21621 +               if (!err) {
21622 +                       if (l <= bend)
21623 +                               err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
21624 +                       else
21625 +                               err = -ENOENT;
21626 +               }
21627 +               goto out_seq;
21628 +       }
21629 +       BUG();
21630 +
21631 +out_seq:
21632 +       if (!err) {
21633 +               err = seq->count;
21634 +               /* sysfs limit */
21635 +               if (unlikely(err == PAGE_SIZE))
21636 +                       err = -EFBIG;
21637 +       }
21638 +       kfree(seq);
21639 +out_unlock:
21640 +       si_read_unlock(sb);
21641 +out:
21642 +       return err;
21643 +}
21644 +
21645 +/* ---------------------------------------------------------------------- */
21646 +
21647 +void sysaufs_br_init(struct au_branch *br)
21648 +{
21649 +       struct attribute *attr = &br->br_attr;
21650 +
21651 +       sysfs_attr_init(attr);
21652 +       attr->name = br->br_name;
21653 +       attr->mode = S_IRUGO;
21654 +}
21655 +
21656 +void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
21657 +{
21658 +       struct au_branch *br;
21659 +       struct kobject *kobj;
21660 +       aufs_bindex_t bend;
21661 +
21662 +       dbgaufs_brs_del(sb, bindex);
21663 +
21664 +       if (!sysaufs_brs)
21665 +               return;
21666 +
21667 +       kobj = &au_sbi(sb)->si_kobj;
21668 +       bend = au_sbend(sb);
21669 +       for (; bindex <= bend; bindex++) {
21670 +               br = au_sbr(sb, bindex);
21671 +               sysfs_remove_file(kobj, &br->br_attr);
21672 +       }
21673 +}
21674 +
21675 +void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
21676 +{
21677 +       int err;
21678 +       aufs_bindex_t bend;
21679 +       struct kobject *kobj;
21680 +       struct au_branch *br;
21681 +
21682 +       dbgaufs_brs_add(sb, bindex);
21683 +
21684 +       if (!sysaufs_brs)
21685 +               return;
21686 +
21687 +       kobj = &au_sbi(sb)->si_kobj;
21688 +       bend = au_sbend(sb);
21689 +       for (; bindex <= bend; bindex++) {
21690 +               br = au_sbr(sb, bindex);
21691 +               snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
21692 +                        "%d", bindex);
21693 +               err = sysfs_create_file(kobj, &br->br_attr);
21694 +               if (unlikely(err))
21695 +                       pr_warning("failed %s under sysfs(%d)\n",
21696 +                                  br->br_name, err);
21697 +       }
21698 +}
21699 diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
21700 --- /usr/share/empty/fs/aufs/sysrq.c    1970-01-01 01:00:00.000000000 +0100
21701 +++ linux/fs/aufs/sysrq.c       2010-10-21 09:52:43.093625591 +0200
21702 @@ -0,0 +1,119 @@
21703 +/*
21704 + * Copyright (C) 2005-2010 Junjiro R. Okajima
21705 + *
21706 + * This program, aufs is free software; you can redistribute it and/or modify
21707 + * it under the terms of the GNU General Public License as published by
21708 + * the Free Software Foundation; either version 2 of the License, or
21709 + * (at your option) any later version.
21710 + *
21711 + * This program is distributed in the hope that it will be useful,
21712 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21713 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21714 + * GNU General Public License for more details.
21715 + *
21716 + * You should have received a copy of the GNU General Public License
21717 + * along with this program; if not, write to the Free Software
21718 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21719 + */
21720 +
21721 +/*
21722 + * magic sysrq hanlder
21723 + */
21724 +
21725 +#include <linux/fs.h>
21726 +#include <linux/module.h>
21727 +#include <linux/moduleparam.h>
21728 +/* #include <linux/sysrq.h> */
21729 +#include "aufs.h"
21730 +
21731 +/* ---------------------------------------------------------------------- */
21732 +
21733 +static void sysrq_sb(struct super_block *sb)
21734 +{
21735 +       char *plevel;
21736 +       struct au_sbinfo *sbinfo;
21737 +       struct file *file;
21738 +
21739 +       plevel = au_plevel;
21740 +       au_plevel = KERN_WARNING;
21741 +       au_debug(1);
21742 +
21743 +       sbinfo = au_sbi(sb);
21744 +       /* since we define pr_fmt, call printk directly */
21745 +       printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
21746 +       printk(KERN_WARNING AUFS_NAME ": superblock\n");
21747 +       au_dpri_sb(sb);
21748 +       printk(KERN_WARNING AUFS_NAME ": root dentry\n");
21749 +       au_dpri_dentry(sb->s_root);
21750 +       printk(KERN_WARNING AUFS_NAME ": root inode\n");
21751 +       au_dpri_inode(sb->s_root->d_inode);
21752 +#if 0
21753 +       struct inode *i;
21754 +       printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
21755 +       list_for_each_entry(i, &sb->s_inodes, i_sb_list)
21756 +               if (list_empty(&i->i_dentry))
21757 +                       au_dpri_inode(i);
21758 +#endif
21759 +       printk(KERN_WARNING AUFS_NAME ": files\n");
21760 +       list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
21761 +               umode_t mode;
21762 +               mode = file->f_dentry->d_inode->i_mode;
21763 +               if (!special_file(mode) || au_special_file(mode))
21764 +                       au_dpri_file(file);
21765 +       }
21766 +
21767 +       au_plevel = plevel;
21768 +       au_debug(0);
21769 +}
21770 +
21771 +/* ---------------------------------------------------------------------- */
21772 +
21773 +/* module parameter */
21774 +static char *aufs_sysrq_key = "a";
21775 +module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
21776 +MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
21777 +
21778 +static void au_sysrq(int key __maybe_unused,
21779 +                    struct tty_struct *tty __maybe_unused)
21780 +{
21781 +       struct kobject *kobj;
21782 +       struct au_sbinfo *sbinfo;
21783 +
21784 +       /* spin_lock(&sysaufs_ket->list_lock); */
21785 +       list_for_each_entry(kobj, &sysaufs_ket->list, entry) {
21786 +               sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
21787 +               sysrq_sb(sbinfo->si_sb);
21788 +       }
21789 +       /* spin_unlock(&sysaufs_ket->list_lock); */
21790 +}
21791 +
21792 +static struct sysrq_key_op au_sysrq_op = {
21793 +       .handler        = au_sysrq,
21794 +       .help_msg       = "Aufs",
21795 +       .action_msg     = "Aufs",
21796 +       .enable_mask    = SYSRQ_ENABLE_DUMP
21797 +};
21798 +
21799 +/* ---------------------------------------------------------------------- */
21800 +
21801 +int __init au_sysrq_init(void)
21802 +{
21803 +       int err;
21804 +       char key;
21805 +
21806 +       err = -1;
21807 +       key = *aufs_sysrq_key;
21808 +       if ('a' <= key && key <= 'z')
21809 +               err = register_sysrq_key(key, &au_sysrq_op);
21810 +       if (unlikely(err))
21811 +               pr_err("err %d, sysrq=%c\n", err, key);
21812 +       return err;
21813 +}
21814 +
21815 +void au_sysrq_fin(void)
21816 +{
21817 +       int err;
21818 +       err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
21819 +       if (unlikely(err))
21820 +               pr_err("err %d (ignored)\n", err);
21821 +}
21822 diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
21823 --- /usr/share/empty/fs/aufs/vdir.c     1970-01-01 01:00:00.000000000 +0100
21824 +++ linux/fs/aufs/vdir.c        2010-10-21 09:52:43.093625591 +0200
21825 @@ -0,0 +1,884 @@
21826 +/*
21827 + * Copyright (C) 2005-2010 Junjiro R. Okajima
21828 + *
21829 + * This program, aufs is free software; you can redistribute it and/or modify
21830 + * it under the terms of the GNU General Public License as published by
21831 + * the Free Software Foundation; either version 2 of the License, or
21832 + * (at your option) any later version.
21833 + *
21834 + * This program is distributed in the hope that it will be useful,
21835 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21836 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21837 + * GNU General Public License for more details.
21838 + *
21839 + * You should have received a copy of the GNU General Public License
21840 + * along with this program; if not, write to the Free Software
21841 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21842 + */
21843 +
21844 +/*
21845 + * virtual or vertical directory
21846 + */
21847 +
21848 +#include <linux/hash.h>
21849 +#include "aufs.h"
21850 +
21851 +static unsigned int calc_size(int nlen)
21852 +{
21853 +       return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
21854 +}
21855 +
21856 +static int set_deblk_end(union au_vdir_deblk_p *p,
21857 +                        union au_vdir_deblk_p *deblk_end)
21858 +{
21859 +       if (calc_size(0) <= deblk_end->deblk - p->deblk) {
21860 +               p->de->de_str.len = 0;
21861 +               /* smp_mb(); */
21862 +               return 0;
21863 +       }
21864 +       return -1; /* error */
21865 +}
21866 +
21867 +/* returns true or false */
21868 +static int is_deblk_end(union au_vdir_deblk_p *p,
21869 +                       union au_vdir_deblk_p *deblk_end)
21870 +{
21871 +       if (calc_size(0) <= deblk_end->deblk - p->deblk)
21872 +               return !p->de->de_str.len;
21873 +       return 1;
21874 +}
21875 +
21876 +static unsigned char *last_deblk(struct au_vdir *vdir)
21877 +{
21878 +       return vdir->vd_deblk[vdir->vd_nblk - 1];
21879 +}
21880 +
21881 +/* ---------------------------------------------------------------------- */
21882 +
21883 +/* estimate the apropriate size for name hash table */
21884 +unsigned int au_rdhash_est(loff_t sz)
21885 +{
21886 +       unsigned int n;
21887 +
21888 +       n = UINT_MAX;
21889 +       sz >>= 10;
21890 +       if (sz < n)
21891 +               n = sz;
21892 +       if (sz < AUFS_RDHASH_DEF)
21893 +               n = AUFS_RDHASH_DEF;
21894 +       /* pr_info("n %u\n", n); */
21895 +       return n;
21896 +}
21897 +
21898 +/*
21899 + * the allocated memory has to be freed by
21900 + * au_nhash_wh_free() or au_nhash_de_free().
21901 + */
21902 +int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
21903 +{
21904 +       struct hlist_head *head;
21905 +       unsigned int u;
21906 +
21907 +       head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
21908 +       if (head) {
21909 +               nhash->nh_num = num_hash;
21910 +               nhash->nh_head = head;
21911 +               for (u = 0; u < num_hash; u++)
21912 +                       INIT_HLIST_HEAD(head++);
21913 +               return 0; /* success */
21914 +       }
21915 +
21916 +       return -ENOMEM;
21917 +}
21918 +
21919 +static void nhash_count(struct hlist_head *head)
21920 +{
21921 +#if 0
21922 +       unsigned long n;
21923 +       struct hlist_node *pos;
21924 +
21925 +       n = 0;
21926 +       hlist_for_each(pos, head)
21927 +               n++;
21928 +       pr_info("%lu\n", n);
21929 +#endif
21930 +}
21931 +
21932 +static void au_nhash_wh_do_free(struct hlist_head *head)
21933 +{
21934 +       struct au_vdir_wh *tpos;
21935 +       struct hlist_node *pos, *node;
21936 +
21937 +       hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
21938 +               /* hlist_del(pos); */
21939 +               kfree(tpos);
21940 +       }
21941 +}
21942 +
21943 +static void au_nhash_de_do_free(struct hlist_head *head)
21944 +{
21945 +       struct au_vdir_dehstr *tpos;
21946 +       struct hlist_node *pos, *node;
21947 +
21948 +       hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
21949 +               /* hlist_del(pos); */
21950 +               au_cache_free_vdir_dehstr(tpos);
21951 +       }
21952 +}
21953 +
21954 +static void au_nhash_do_free(struct au_nhash *nhash,
21955 +                            void (*free)(struct hlist_head *head))
21956 +{
21957 +       unsigned int n;
21958 +       struct hlist_head *head;
21959 +
21960 +       n = nhash->nh_num;
21961 +       if (!n)
21962 +               return;
21963 +
21964 +       head = nhash->nh_head;
21965 +       while (n-- > 0) {
21966 +               nhash_count(head);
21967 +               free(head++);
21968 +       }
21969 +       kfree(nhash->nh_head);
21970 +}
21971 +
21972 +void au_nhash_wh_free(struct au_nhash *whlist)
21973 +{
21974 +       au_nhash_do_free(whlist, au_nhash_wh_do_free);
21975 +}
21976 +
21977 +static void au_nhash_de_free(struct au_nhash *delist)
21978 +{
21979 +       au_nhash_do_free(delist, au_nhash_de_do_free);
21980 +}
21981 +
21982 +/* ---------------------------------------------------------------------- */
21983 +
21984 +int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
21985 +                           int limit)
21986 +{
21987 +       int num;
21988 +       unsigned int u, n;
21989 +       struct hlist_head *head;
21990 +       struct au_vdir_wh *tpos;
21991 +       struct hlist_node *pos;
21992 +
21993 +       num = 0;
21994 +       n = whlist->nh_num;
21995 +       head = whlist->nh_head;
21996 +       for (u = 0; u < n; u++, head++)
21997 +               hlist_for_each_entry(tpos, pos, head, wh_hash)
21998 +                       if (tpos->wh_bindex == btgt && ++num > limit)
21999 +                               return 1;
22000 +       return 0;
22001 +}
22002 +
22003 +static struct hlist_head *au_name_hash(struct au_nhash *nhash,
22004 +                                      unsigned char *name,
22005 +                                      unsigned int len)
22006 +{
22007 +       unsigned int v;
22008 +       /* const unsigned int magic_bit = 12; */
22009 +
22010 +       AuDebugOn(!nhash->nh_num || !nhash->nh_head);
22011 +
22012 +       v = 0;
22013 +       while (len--)
22014 +               v += *name++;
22015 +       /* v = hash_long(v, magic_bit); */
22016 +       v %= nhash->nh_num;
22017 +       return nhash->nh_head + v;
22018 +}
22019 +
22020 +static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
22021 +                             int nlen)
22022 +{
22023 +       return str->len == nlen && !memcmp(str->name, name, nlen);
22024 +}
22025 +
22026 +/* returns found or not */
22027 +int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
22028 +{
22029 +       struct hlist_head *head;
22030 +       struct au_vdir_wh *tpos;
22031 +       struct hlist_node *pos;
22032 +       struct au_vdir_destr *str;
22033 +
22034 +       head = au_name_hash(whlist, name, nlen);
22035 +       hlist_for_each_entry(tpos, pos, head, wh_hash) {
22036 +               str = &tpos->wh_str;
22037 +               AuDbg("%.*s\n", str->len, str->name);
22038 +               if (au_nhash_test_name(str, name, nlen))
22039 +                       return 1;
22040 +       }
22041 +       return 0;
22042 +}
22043 +
22044 +/* returns found(true) or not */
22045 +static int test_known(struct au_nhash *delist, char *name, int nlen)
22046 +{
22047 +       struct hlist_head *head;
22048 +       struct au_vdir_dehstr *tpos;
22049 +       struct hlist_node *pos;
22050 +       struct au_vdir_destr *str;
22051 +
22052 +       head = au_name_hash(delist, name, nlen);
22053 +       hlist_for_each_entry(tpos, pos, head, hash) {
22054 +               str = tpos->str;
22055 +               AuDbg("%.*s\n", str->len, str->name);
22056 +               if (au_nhash_test_name(str, name, nlen))
22057 +                       return 1;
22058 +       }
22059 +       return 0;
22060 +}
22061 +
22062 +static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
22063 +                           unsigned char d_type)
22064 +{
22065 +#ifdef CONFIG_AUFS_SHWH
22066 +       wh->wh_ino = ino;
22067 +       wh->wh_type = d_type;
22068 +#endif
22069 +}
22070 +
22071 +/* ---------------------------------------------------------------------- */
22072 +
22073 +int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
22074 +                      unsigned int d_type, aufs_bindex_t bindex,
22075 +                      unsigned char shwh)
22076 +{
22077 +       int err;
22078 +       struct au_vdir_destr *str;
22079 +       struct au_vdir_wh *wh;
22080 +
22081 +       AuDbg("%.*s\n", nlen, name);
22082 +       AuDebugOn(!whlist->nh_num || !whlist->nh_head);
22083 +
22084 +       err = -ENOMEM;
22085 +       wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
22086 +       if (unlikely(!wh))
22087 +               goto out;
22088 +
22089 +       err = 0;
22090 +       wh->wh_bindex = bindex;
22091 +       if (shwh)
22092 +               au_shwh_init_wh(wh, ino, d_type);
22093 +       str = &wh->wh_str;
22094 +       str->len = nlen;
22095 +       memcpy(str->name, name, nlen);
22096 +       hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
22097 +       /* smp_mb(); */
22098 +
22099 +out:
22100 +       return err;
22101 +}
22102 +
22103 +static int append_deblk(struct au_vdir *vdir)
22104 +{
22105 +       int err;
22106 +       unsigned long ul;
22107 +       const unsigned int deblk_sz = vdir->vd_deblk_sz;
22108 +       union au_vdir_deblk_p p, deblk_end;
22109 +       unsigned char **o;
22110 +
22111 +       err = -ENOMEM;
22112 +       o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
22113 +                    GFP_NOFS);
22114 +       if (unlikely(!o))
22115 +               goto out;
22116 +
22117 +       vdir->vd_deblk = o;
22118 +       p.deblk = kmalloc(deblk_sz, GFP_NOFS);
22119 +       if (p.deblk) {
22120 +               ul = vdir->vd_nblk++;
22121 +               vdir->vd_deblk[ul] = p.deblk;
22122 +               vdir->vd_last.ul = ul;
22123 +               vdir->vd_last.p.deblk = p.deblk;
22124 +               deblk_end.deblk = p.deblk + deblk_sz;
22125 +               err = set_deblk_end(&p, &deblk_end);
22126 +       }
22127 +
22128 +out:
22129 +       return err;
22130 +}
22131 +
22132 +static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
22133 +                    unsigned int d_type, struct au_nhash *delist)
22134 +{
22135 +       int err;
22136 +       unsigned int sz;
22137 +       const unsigned int deblk_sz = vdir->vd_deblk_sz;
22138 +       union au_vdir_deblk_p p, *room, deblk_end;
22139 +       struct au_vdir_dehstr *dehstr;
22140 +
22141 +       p.deblk = last_deblk(vdir);
22142 +       deblk_end.deblk = p.deblk + deblk_sz;
22143 +       room = &vdir->vd_last.p;
22144 +       AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
22145 +                 || !is_deblk_end(room, &deblk_end));
22146 +
22147 +       sz = calc_size(nlen);
22148 +       if (unlikely(sz > deblk_end.deblk - room->deblk)) {
22149 +               err = append_deblk(vdir);
22150 +               if (unlikely(err))
22151 +                       goto out;
22152 +
22153 +               p.deblk = last_deblk(vdir);
22154 +               deblk_end.deblk = p.deblk + deblk_sz;
22155 +               /* smp_mb(); */
22156 +               AuDebugOn(room->deblk != p.deblk);
22157 +       }
22158 +
22159 +       err = -ENOMEM;
22160 +       dehstr = au_cache_alloc_vdir_dehstr();
22161 +       if (unlikely(!dehstr))
22162 +               goto out;
22163 +
22164 +       dehstr->str = &room->de->de_str;
22165 +       hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
22166 +       room->de->de_ino = ino;
22167 +       room->de->de_type = d_type;
22168 +       room->de->de_str.len = nlen;
22169 +       memcpy(room->de->de_str.name, name, nlen);
22170 +
22171 +       err = 0;
22172 +       room->deblk += sz;
22173 +       if (unlikely(set_deblk_end(room, &deblk_end)))
22174 +               err = append_deblk(vdir);
22175 +       /* smp_mb(); */
22176 +
22177 +out:
22178 +       return err;
22179 +}
22180 +
22181 +/* ---------------------------------------------------------------------- */
22182 +
22183 +void au_vdir_free(struct au_vdir *vdir)
22184 +{
22185 +       unsigned char **deblk;
22186 +
22187 +       deblk = vdir->vd_deblk;
22188 +       while (vdir->vd_nblk--)
22189 +               kfree(*deblk++);
22190 +       kfree(vdir->vd_deblk);
22191 +       au_cache_free_vdir(vdir);
22192 +}
22193 +
22194 +static struct au_vdir *alloc_vdir(struct file *file)
22195 +{
22196 +       struct au_vdir *vdir;
22197 +       struct super_block *sb;
22198 +       int err;
22199 +
22200 +       sb = file->f_dentry->d_sb;
22201 +       SiMustAnyLock(sb);
22202 +
22203 +       err = -ENOMEM;
22204 +       vdir = au_cache_alloc_vdir();
22205 +       if (unlikely(!vdir))
22206 +               goto out;
22207 +
22208 +       vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
22209 +       if (unlikely(!vdir->vd_deblk))
22210 +               goto out_free;
22211 +
22212 +       vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
22213 +       if (!vdir->vd_deblk_sz) {
22214 +               /* estimate the apropriate size for deblk */
22215 +               vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
22216 +               /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
22217 +       }
22218 +       vdir->vd_nblk = 0;
22219 +       vdir->vd_version = 0;
22220 +       vdir->vd_jiffy = 0;
22221 +       err = append_deblk(vdir);
22222 +       if (!err)
22223 +               return vdir; /* success */
22224 +
22225 +       kfree(vdir->vd_deblk);
22226 +
22227 +out_free:
22228 +       au_cache_free_vdir(vdir);
22229 +out:
22230 +       vdir = ERR_PTR(err);
22231 +       return vdir;
22232 +}
22233 +
22234 +static int reinit_vdir(struct au_vdir *vdir)
22235 +{
22236 +       int err;
22237 +       union au_vdir_deblk_p p, deblk_end;
22238 +
22239 +       while (vdir->vd_nblk > 1) {
22240 +               kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
22241 +               /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
22242 +               vdir->vd_nblk--;
22243 +       }
22244 +       p.deblk = vdir->vd_deblk[0];
22245 +       deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
22246 +       err = set_deblk_end(&p, &deblk_end);
22247 +       /* keep vd_dblk_sz */
22248 +       vdir->vd_last.ul = 0;
22249 +       vdir->vd_last.p.deblk = vdir->vd_deblk[0];
22250 +       vdir->vd_version = 0;
22251 +       vdir->vd_jiffy = 0;
22252 +       /* smp_mb(); */
22253 +       return err;
22254 +}
22255 +
22256 +/* ---------------------------------------------------------------------- */
22257 +
22258 +#define AuFillVdir_CALLED      1
22259 +#define AuFillVdir_WHABLE      (1 << 1)
22260 +#define AuFillVdir_SHWH                (1 << 2)
22261 +#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
22262 +#define au_fset_fillvdir(flags, name)  { (flags) |= AuFillVdir_##name; }
22263 +#define au_fclr_fillvdir(flags, name)  { (flags) &= ~AuFillVdir_##name; }
22264 +
22265 +#ifndef CONFIG_AUFS_SHWH
22266 +#undef AuFillVdir_SHWH
22267 +#define AuFillVdir_SHWH                0
22268 +#endif
22269 +
22270 +struct fillvdir_arg {
22271 +       struct file             *file;
22272 +       struct au_vdir          *vdir;
22273 +       struct au_nhash         delist;
22274 +       struct au_nhash         whlist;
22275 +       aufs_bindex_t           bindex;
22276 +       unsigned int            flags;
22277 +       int                     err;
22278 +};
22279 +
22280 +static int fillvdir(void *__arg, const char *__name, int nlen,
22281 +                   loff_t offset __maybe_unused, u64 h_ino,
22282 +                   unsigned int d_type)
22283 +{
22284 +       struct fillvdir_arg *arg = __arg;
22285 +       char *name = (void *)__name;
22286 +       struct super_block *sb;
22287 +       ino_t ino;
22288 +       const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
22289 +
22290 +       arg->err = 0;
22291 +       sb = arg->file->f_dentry->d_sb;
22292 +       au_fset_fillvdir(arg->flags, CALLED);
22293 +       /* smp_mb(); */
22294 +       if (nlen <= AUFS_WH_PFX_LEN
22295 +           || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
22296 +               if (test_known(&arg->delist, name, nlen)
22297 +                   || au_nhash_test_known_wh(&arg->whlist, name, nlen))
22298 +                       goto out; /* already exists or whiteouted */
22299 +
22300 +               sb = arg->file->f_dentry->d_sb;
22301 +               arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
22302 +               if (!arg->err) {
22303 +                       if (unlikely(nlen > AUFS_MAX_NAMELEN))
22304 +                               d_type = DT_UNKNOWN;
22305 +                       arg->err = append_de(arg->vdir, name, nlen, ino,
22306 +                                            d_type, &arg->delist);
22307 +               }
22308 +       } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
22309 +               name += AUFS_WH_PFX_LEN;
22310 +               nlen -= AUFS_WH_PFX_LEN;
22311 +               if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
22312 +                       goto out; /* already whiteouted */
22313 +
22314 +               if (shwh)
22315 +                       arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
22316 +                                            &ino);
22317 +               if (!arg->err) {
22318 +                       if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
22319 +                               d_type = DT_UNKNOWN;
22320 +                       arg->err = au_nhash_append_wh
22321 +                               (&arg->whlist, name, nlen, ino, d_type,
22322 +                                arg->bindex, shwh);
22323 +               }
22324 +       }
22325 +
22326 +out:
22327 +       if (!arg->err)
22328 +               arg->vdir->vd_jiffy = jiffies;
22329 +       /* smp_mb(); */
22330 +       AuTraceErr(arg->err);
22331 +       return arg->err;
22332 +}
22333 +
22334 +static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
22335 +                         struct au_nhash *whlist, struct au_nhash *delist)
22336 +{
22337 +#ifdef CONFIG_AUFS_SHWH
22338 +       int err;
22339 +       unsigned int nh, u;
22340 +       struct hlist_head *head;
22341 +       struct au_vdir_wh *tpos;
22342 +       struct hlist_node *pos, *n;
22343 +       char *p, *o;
22344 +       struct au_vdir_destr *destr;
22345 +
22346 +       AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
22347 +
22348 +       err = -ENOMEM;
22349 +       o = p = __getname_gfp(GFP_NOFS);
22350 +       if (unlikely(!p))
22351 +               goto out;
22352 +
22353 +       err = 0;
22354 +       nh = whlist->nh_num;
22355 +       memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
22356 +       p += AUFS_WH_PFX_LEN;
22357 +       for (u = 0; u < nh; u++) {
22358 +               head = whlist->nh_head + u;
22359 +               hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
22360 +                       destr = &tpos->wh_str;
22361 +                       memcpy(p, destr->name, destr->len);
22362 +                       err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
22363 +                                       tpos->wh_ino, tpos->wh_type, delist);
22364 +                       if (unlikely(err))
22365 +                               break;
22366 +               }
22367 +       }
22368 +
22369 +       __putname(o);
22370 +
22371 +out:
22372 +       AuTraceErr(err);
22373 +       return err;
22374 +#else
22375 +       return 0;
22376 +#endif
22377 +}
22378 +
22379 +static int au_do_read_vdir(struct fillvdir_arg *arg)
22380 +{
22381 +       int err;
22382 +       unsigned int rdhash;
22383 +       loff_t offset;
22384 +       aufs_bindex_t bend, bindex, bstart;
22385 +       unsigned char shwh;
22386 +       struct file *hf, *file;
22387 +       struct super_block *sb;
22388 +
22389 +       file = arg->file;
22390 +       sb = file->f_dentry->d_sb;
22391 +       SiMustAnyLock(sb);
22392 +
22393 +       rdhash = au_sbi(sb)->si_rdhash;
22394 +       if (!rdhash)
22395 +               rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
22396 +       err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
22397 +       if (unlikely(err))
22398 +               goto out;
22399 +       err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
22400 +       if (unlikely(err))
22401 +               goto out_delist;
22402 +
22403 +       err = 0;
22404 +       arg->flags = 0;
22405 +       shwh = 0;
22406 +       if (au_opt_test(au_mntflags(sb), SHWH)) {
22407 +               shwh = 1;
22408 +               au_fset_fillvdir(arg->flags, SHWH);
22409 +       }
22410 +       bstart = au_fbstart(file);
22411 +       bend = au_fbend_dir(file);
22412 +       for (bindex = bstart; !err && bindex <= bend; bindex++) {
22413 +               hf = au_hf_dir(file, bindex);
22414 +               if (!hf)
22415 +                       continue;
22416 +
22417 +               offset = vfsub_llseek(hf, 0, SEEK_SET);
22418 +               err = offset;
22419 +               if (unlikely(offset))
22420 +                       break;
22421 +
22422 +               arg->bindex = bindex;
22423 +               au_fclr_fillvdir(arg->flags, WHABLE);
22424 +               if (shwh
22425 +                   || (bindex != bend
22426 +                       && au_br_whable(au_sbr_perm(sb, bindex))))
22427 +                       au_fset_fillvdir(arg->flags, WHABLE);
22428 +               do {
22429 +                       arg->err = 0;
22430 +                       au_fclr_fillvdir(arg->flags, CALLED);
22431 +                       /* smp_mb(); */
22432 +                       err = vfsub_readdir(hf, fillvdir, arg);
22433 +                       if (err >= 0)
22434 +                               err = arg->err;
22435 +               } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
22436 +       }
22437 +
22438 +       if (!err && shwh)
22439 +               err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
22440 +
22441 +       au_nhash_wh_free(&arg->whlist);
22442 +
22443 +out_delist:
22444 +       au_nhash_de_free(&arg->delist);
22445 +out:
22446 +       return err;
22447 +}
22448 +
22449 +static int read_vdir(struct file *file, int may_read)
22450 +{
22451 +       int err;
22452 +       unsigned long expire;
22453 +       unsigned char do_read;
22454 +       struct fillvdir_arg arg;
22455 +       struct inode *inode;
22456 +       struct au_vdir *vdir, *allocated;
22457 +
22458 +       err = 0;
22459 +       inode = file->f_dentry->d_inode;
22460 +       IMustLock(inode);
22461 +       SiMustAnyLock(inode->i_sb);
22462 +
22463 +       allocated = NULL;
22464 +       do_read = 0;
22465 +       expire = au_sbi(inode->i_sb)->si_rdcache;
22466 +       vdir = au_ivdir(inode);
22467 +       if (!vdir) {
22468 +               do_read = 1;
22469 +               vdir = alloc_vdir(file);
22470 +               err = PTR_ERR(vdir);
22471 +               if (IS_ERR(vdir))
22472 +                       goto out;
22473 +               err = 0;
22474 +               allocated = vdir;
22475 +       } else if (may_read
22476 +                  && (inode->i_version != vdir->vd_version
22477 +                      || time_after(jiffies, vdir->vd_jiffy + expire))) {
22478 +               do_read = 1;
22479 +               err = reinit_vdir(vdir);
22480 +               if (unlikely(err))
22481 +                       goto out;
22482 +       }
22483 +
22484 +       if (!do_read)
22485 +               return 0; /* success */
22486 +
22487 +       arg.file = file;
22488 +       arg.vdir = vdir;
22489 +       err = au_do_read_vdir(&arg);
22490 +       if (!err) {
22491 +               /* file->f_pos = 0; */
22492 +               vdir->vd_version = inode->i_version;
22493 +               vdir->vd_last.ul = 0;
22494 +               vdir->vd_last.p.deblk = vdir->vd_deblk[0];
22495 +               if (allocated)
22496 +                       au_set_ivdir(inode, allocated);
22497 +       } else if (allocated)
22498 +               au_vdir_free(allocated);
22499 +
22500 +out:
22501 +       return err;
22502 +}
22503 +
22504 +static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
22505 +{
22506 +       int err, rerr;
22507 +       unsigned long ul, n;
22508 +       const unsigned int deblk_sz = src->vd_deblk_sz;
22509 +
22510 +       AuDebugOn(tgt->vd_nblk != 1);
22511 +
22512 +       err = -ENOMEM;
22513 +       if (tgt->vd_nblk < src->vd_nblk) {
22514 +               unsigned char **p;
22515 +
22516 +               p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
22517 +                            GFP_NOFS);
22518 +               if (unlikely(!p))
22519 +                       goto out;
22520 +               tgt->vd_deblk = p;
22521 +       }
22522 +
22523 +       if (tgt->vd_deblk_sz != deblk_sz) {
22524 +               unsigned char *p;
22525 +
22526 +               tgt->vd_deblk_sz = deblk_sz;
22527 +               p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
22528 +               if (unlikely(!p))
22529 +                       goto out;
22530 +               tgt->vd_deblk[0] = p;
22531 +       }
22532 +       memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
22533 +       tgt->vd_version = src->vd_version;
22534 +       tgt->vd_jiffy = src->vd_jiffy;
22535 +
22536 +       n = src->vd_nblk;
22537 +       for (ul = 1; ul < n; ul++) {
22538 +               tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
22539 +                                           GFP_NOFS);
22540 +               if (unlikely(!tgt->vd_deblk[ul]))
22541 +                       goto out;
22542 +               tgt->vd_nblk++;
22543 +       }
22544 +       tgt->vd_nblk = n;
22545 +       tgt->vd_last.ul = tgt->vd_last.ul;
22546 +       tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
22547 +       tgt->vd_last.p.deblk += src->vd_last.p.deblk
22548 +               - src->vd_deblk[src->vd_last.ul];
22549 +       /* smp_mb(); */
22550 +       return 0; /* success */
22551 +
22552 +out:
22553 +       rerr = reinit_vdir(tgt);
22554 +       BUG_ON(rerr);
22555 +       return err;
22556 +}
22557 +
22558 +int au_vdir_init(struct file *file)
22559 +{
22560 +       int err;
22561 +       struct inode *inode;
22562 +       struct au_vdir *vdir_cache, *allocated;
22563 +
22564 +       err = read_vdir(file, !file->f_pos);
22565 +       if (unlikely(err))
22566 +               goto out;
22567 +
22568 +       allocated = NULL;
22569 +       vdir_cache = au_fvdir_cache(file);
22570 +       if (!vdir_cache) {
22571 +               vdir_cache = alloc_vdir(file);
22572 +               err = PTR_ERR(vdir_cache);
22573 +               if (IS_ERR(vdir_cache))
22574 +                       goto out;
22575 +               allocated = vdir_cache;
22576 +       } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
22577 +               err = reinit_vdir(vdir_cache);
22578 +               if (unlikely(err))
22579 +                       goto out;
22580 +       } else
22581 +               return 0; /* success */
22582 +
22583 +       inode = file->f_dentry->d_inode;
22584 +       err = copy_vdir(vdir_cache, au_ivdir(inode));
22585 +       if (!err) {
22586 +               file->f_version = inode->i_version;
22587 +               if (allocated)
22588 +                       au_set_fvdir_cache(file, allocated);
22589 +       } else if (allocated)
22590 +               au_vdir_free(allocated);
22591 +
22592 +out:
22593 +       return err;
22594 +}
22595 +
22596 +static loff_t calc_offset(struct au_vdir *vdir)
22597 +{
22598 +       loff_t offset;
22599 +       union au_vdir_deblk_p p;
22600 +
22601 +       p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
22602 +       offset = vdir->vd_last.p.deblk - p.deblk;
22603 +       offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
22604 +       return offset;
22605 +}
22606 +
22607 +/* returns true or false */
22608 +static int seek_vdir(struct file *file)
22609 +{
22610 +       int valid;
22611 +       unsigned int deblk_sz;
22612 +       unsigned long ul, n;
22613 +       loff_t offset;
22614 +       union au_vdir_deblk_p p, deblk_end;
22615 +       struct au_vdir *vdir_cache;
22616 +
22617 +       valid = 1;
22618 +       vdir_cache = au_fvdir_cache(file);
22619 +       offset = calc_offset(vdir_cache);
22620 +       AuDbg("offset %lld\n", offset);
22621 +       if (file->f_pos == offset)
22622 +               goto out;
22623 +
22624 +       vdir_cache->vd_last.ul = 0;
22625 +       vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
22626 +       if (!file->f_pos)
22627 +               goto out;
22628 +
22629 +       valid = 0;
22630 +       deblk_sz = vdir_cache->vd_deblk_sz;
22631 +       ul = div64_u64(file->f_pos, deblk_sz);
22632 +       AuDbg("ul %lu\n", ul);
22633 +       if (ul >= vdir_cache->vd_nblk)
22634 +               goto out;
22635 +
22636 +       n = vdir_cache->vd_nblk;
22637 +       for (; ul < n; ul++) {
22638 +               p.deblk = vdir_cache->vd_deblk[ul];
22639 +               deblk_end.deblk = p.deblk + deblk_sz;
22640 +               offset = ul;
22641 +               offset *= deblk_sz;
22642 +               while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
22643 +                       unsigned int l;
22644 +
22645 +                       l = calc_size(p.de->de_str.len);
22646 +                       offset += l;
22647 +                       p.deblk += l;
22648 +               }
22649 +               if (!is_deblk_end(&p, &deblk_end)) {
22650 +                       valid = 1;
22651 +                       vdir_cache->vd_last.ul = ul;
22652 +                       vdir_cache->vd_last.p = p;
22653 +                       break;
22654 +               }
22655 +       }
22656 +
22657 +out:
22658 +       /* smp_mb(); */
22659 +       AuTraceErr(!valid);
22660 +       return valid;
22661 +}
22662 +
22663 +int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
22664 +{
22665 +       int err;
22666 +       unsigned int l, deblk_sz;
22667 +       union au_vdir_deblk_p deblk_end;
22668 +       struct au_vdir *vdir_cache;
22669 +       struct au_vdir_de *de;
22670 +
22671 +       vdir_cache = au_fvdir_cache(file);
22672 +       if (!seek_vdir(file))
22673 +               return 0;
22674 +
22675 +       deblk_sz = vdir_cache->vd_deblk_sz;
22676 +       while (1) {
22677 +               deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
22678 +               deblk_end.deblk += deblk_sz;
22679 +               while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
22680 +                       de = vdir_cache->vd_last.p.de;
22681 +                       AuDbg("%.*s, off%lld, i%lu, dt%d\n",
22682 +                             de->de_str.len, de->de_str.name, file->f_pos,
22683 +                             (unsigned long)de->de_ino, de->de_type);
22684 +                       err = filldir(dirent, de->de_str.name, de->de_str.len,
22685 +                                     file->f_pos, de->de_ino, de->de_type);
22686 +                       if (unlikely(err)) {
22687 +                               AuTraceErr(err);
22688 +                               /* todo: ignore the error caused by udba? */
22689 +                               /* return err; */
22690 +                               return 0;
22691 +                       }
22692 +
22693 +                       l = calc_size(de->de_str.len);
22694 +                       vdir_cache->vd_last.p.deblk += l;
22695 +                       file->f_pos += l;
22696 +               }
22697 +               if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
22698 +                       vdir_cache->vd_last.ul++;
22699 +                       vdir_cache->vd_last.p.deblk
22700 +                               = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
22701 +                       file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
22702 +                       continue;
22703 +               }
22704 +               break;
22705 +       }
22706 +
22707 +       /* smp_mb(); */
22708 +       return 0;
22709 +}
22710 diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
22711 --- /usr/share/empty/fs/aufs/vfsub.c    1970-01-01 01:00:00.000000000 +0100
22712 +++ linux/fs/aufs/vfsub.c       2010-10-21 09:52:43.093625591 +0200
22713 @@ -0,0 +1,786 @@
22714 +/*
22715 + * Copyright (C) 2005-2010 Junjiro R. Okajima
22716 + *
22717 + * This program, aufs is free software; you can redistribute it and/or modify
22718 + * it under the terms of the GNU General Public License as published by
22719 + * the Free Software Foundation; either version 2 of the License, or
22720 + * (at your option) any later version.
22721 + *
22722 + * This program is distributed in the hope that it will be useful,
22723 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
22724 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22725 + * GNU General Public License for more details.
22726 + *
22727 + * You should have received a copy of the GNU General Public License
22728 + * along with this program; if not, write to the Free Software
22729 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22730 + */
22731 +
22732 +/*
22733 + * sub-routines for VFS
22734 + */
22735 +
22736 +#include <linux/file.h>
22737 +#include <linux/ima.h>
22738 +#include <linux/namei.h>
22739 +#include <linux/security.h>
22740 +#include <linux/splice.h>
22741 +#include <linux/uaccess.h>
22742 +#include "aufs.h"
22743 +
22744 +int vfsub_update_h_iattr(struct path *h_path, int *did)
22745 +{
22746 +       int err;
22747 +       struct kstat st;
22748 +       struct super_block *h_sb;
22749 +
22750 +       /* for remote fs, leave work for its getattr or d_revalidate */
22751 +       /* for bad i_attr fs, handle them in aufs_getattr() */
22752 +       /* still some fs may acquire i_mutex. we need to skip them */
22753 +       err = 0;
22754 +       if (!did)
22755 +               did = &err;
22756 +       h_sb = h_path->dentry->d_sb;
22757 +       *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
22758 +       if (*did)
22759 +               err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
22760 +
22761 +       return err;
22762 +}
22763 +
22764 +/* ---------------------------------------------------------------------- */
22765 +
22766 +static int au_conv_oflags(int flags)
22767 +{
22768 +       int mask = 0;
22769 +
22770 +#ifdef CONFIG_IMA
22771 +       fmode_t fmode;
22772 +
22773 +       /* mask = MAY_OPEN; */
22774 +       fmode = OPEN_FMODE(flags);
22775 +       if (fmode & FMODE_READ)
22776 +               mask |= MAY_READ;
22777 +       if ((fmode & FMODE_WRITE)
22778 +           || (flags & O_TRUNC))
22779 +               mask |= MAY_WRITE;
22780 +       /*
22781 +        * if (flags & O_APPEND)
22782 +        *      mask |= MAY_APPEND;
22783 +        */
22784 +       if (flags & vfsub_fmode_to_uint(FMODE_EXEC))
22785 +               mask |= MAY_EXEC;
22786 +
22787 +       AuDbg("flags 0x%x, mask 0x%x\n", flags, mask);
22788 +#endif
22789 +
22790 +       return mask;
22791 +}
22792 +
22793 +struct file *vfsub_dentry_open(struct path *path, int flags)
22794 +{
22795 +       struct file *file;
22796 +       int err;
22797 +
22798 +       path_get(path);
22799 +       file = dentry_open(path->dentry, path->mnt, flags, current_cred());
22800 +       if (IS_ERR(file))
22801 +               goto out;
22802 +
22803 +       err = ima_file_check(file, au_conv_oflags(flags));
22804 +       if (unlikely(err)) {
22805 +               fput(file);
22806 +               file = ERR_PTR(err);
22807 +       }
22808 +out:
22809 +       return file;
22810 +}
22811 +
22812 +struct file *vfsub_filp_open(const char *path, int oflags, int mode)
22813 +{
22814 +       struct file *file;
22815 +
22816 +       file = filp_open(path, oflags, mode);
22817 +       if (IS_ERR(file))
22818 +               goto out;
22819 +       vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
22820 +
22821 +out:
22822 +       return file;
22823 +}
22824 +
22825 +int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
22826 +{
22827 +       int err;
22828 +
22829 +       err = kern_path(name, flags, path);
22830 +       if (!err && path->dentry->d_inode)
22831 +               vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
22832 +       return err;
22833 +}
22834 +
22835 +struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
22836 +                                   int len)
22837 +{
22838 +       struct path path = {
22839 +               .mnt = NULL
22840 +       };
22841 +
22842 +       /* VFS checks it too, but by WARN_ON_ONCE() */
22843 +       IMustLock(parent->d_inode);
22844 +
22845 +       path.dentry = lookup_one_len(name, parent, len);
22846 +       if (IS_ERR(path.dentry))
22847 +               goto out;
22848 +       if (path.dentry->d_inode)
22849 +               vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
22850 +
22851 +out:
22852 +       AuTraceErrPtr(path.dentry);
22853 +       return path.dentry;
22854 +}
22855 +
22856 +struct dentry *vfsub_lookup_hash(struct nameidata *nd)
22857 +{
22858 +       struct path path = {
22859 +               .mnt = nd->path.mnt
22860 +       };
22861 +
22862 +       IMustLock(nd->path.dentry->d_inode);
22863 +
22864 +       path.dentry = lookup_hash(nd);
22865 +       if (IS_ERR(path.dentry))
22866 +               goto out;
22867 +       if (path.dentry->d_inode)
22868 +               vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
22869 +
22870 +out:
22871 +       AuTraceErrPtr(path.dentry);
22872 +       return path.dentry;
22873 +}
22874 +
22875 +/* ---------------------------------------------------------------------- */
22876 +
22877 +struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
22878 +                                struct dentry *d2, struct au_hinode *hdir2)
22879 +{
22880 +       struct dentry *d;
22881 +
22882 +       d = lock_rename(d1, d2);
22883 +       au_hn_suspend(hdir1);
22884 +       if (hdir1 != hdir2)
22885 +               au_hn_suspend(hdir2);
22886 +
22887 +       return d;
22888 +}
22889 +
22890 +void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
22891 +                        struct dentry *d2, struct au_hinode *hdir2)
22892 +{
22893 +       au_hn_resume(hdir1);
22894 +       if (hdir1 != hdir2)
22895 +               au_hn_resume(hdir2);
22896 +       unlock_rename(d1, d2);
22897 +}
22898 +
22899 +/* ---------------------------------------------------------------------- */
22900 +
22901 +int vfsub_create(struct inode *dir, struct path *path, int mode)
22902 +{
22903 +       int err;
22904 +       struct dentry *d;
22905 +
22906 +       IMustLock(dir);
22907 +
22908 +       d = path->dentry;
22909 +       path->dentry = d->d_parent;
22910 +       err = security_path_mknod(path, d, mode, 0);
22911 +       path->dentry = d;
22912 +       if (unlikely(err))
22913 +               goto out;
22914 +
22915 +       if (au_test_fs_null_nd(dir->i_sb))
22916 +               err = vfs_create(dir, path->dentry, mode, NULL);
22917 +       else {
22918 +               struct nameidata h_nd;
22919 +
22920 +               memset(&h_nd, 0, sizeof(h_nd));
22921 +               h_nd.flags = LOOKUP_CREATE;
22922 +               h_nd.intent.open.flags = O_CREAT
22923 +                       | vfsub_fmode_to_uint(FMODE_READ);
22924 +               h_nd.intent.open.create_mode = mode;
22925 +               h_nd.path.dentry = path->dentry->d_parent;
22926 +               h_nd.path.mnt = path->mnt;
22927 +               path_get(&h_nd.path);
22928 +               err = vfs_create(dir, path->dentry, mode, &h_nd);
22929 +               path_put(&h_nd.path);
22930 +       }
22931 +
22932 +       if (!err) {
22933 +               struct path tmp = *path;
22934 +               int did;
22935 +
22936 +               vfsub_update_h_iattr(&tmp, &did);
22937 +               if (did) {
22938 +                       tmp.dentry = path->dentry->d_parent;
22939 +                       vfsub_update_h_iattr(&tmp, /*did*/NULL);
22940 +               }
22941 +               /*ignore*/
22942 +       }
22943 +
22944 +out:
22945 +       return err;
22946 +}
22947 +
22948 +int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
22949 +{
22950 +       int err;
22951 +       struct dentry *d;
22952 +
22953 +       IMustLock(dir);
22954 +
22955 +       d = path->dentry;
22956 +       path->dentry = d->d_parent;
22957 +       err = security_path_symlink(path, d, symname);
22958 +       path->dentry = d;
22959 +       if (unlikely(err))
22960 +               goto out;
22961 +
22962 +       err = vfs_symlink(dir, path->dentry, symname);
22963 +       if (!err) {
22964 +               struct path tmp = *path;
22965 +               int did;
22966 +
22967 +               vfsub_update_h_iattr(&tmp, &did);
22968 +               if (did) {
22969 +                       tmp.dentry = path->dentry->d_parent;
22970 +                       vfsub_update_h_iattr(&tmp, /*did*/NULL);
22971 +               }
22972 +               /*ignore*/
22973 +       }
22974 +
22975 +out:
22976 +       return err;
22977 +}
22978 +
22979 +int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
22980 +{
22981 +       int err;
22982 +       struct dentry *d;
22983 +
22984 +       IMustLock(dir);
22985 +
22986 +       d = path->dentry;
22987 +       path->dentry = d->d_parent;
22988 +       err = security_path_mknod(path, d, mode, dev);
22989 +       path->dentry = d;
22990 +       if (unlikely(err))
22991 +               goto out;
22992 +
22993 +       err = vfs_mknod(dir, path->dentry, mode, dev);
22994 +       if (!err) {
22995 +               struct path tmp = *path;
22996 +               int did;
22997 +
22998 +               vfsub_update_h_iattr(&tmp, &did);
22999 +               if (did) {
23000 +                       tmp.dentry = path->dentry->d_parent;
23001 +                       vfsub_update_h_iattr(&tmp, /*did*/NULL);
23002 +               }
23003 +               /*ignore*/
23004 +       }
23005 +
23006 +out:
23007 +       return err;
23008 +}
23009 +
23010 +static int au_test_nlink(struct inode *inode)
23011 +{
23012 +       const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
23013 +
23014 +       if (!au_test_fs_no_limit_nlink(inode->i_sb)
23015 +           || inode->i_nlink < link_max)
23016 +               return 0;
23017 +       return -EMLINK;
23018 +}
23019 +
23020 +int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
23021 +{
23022 +       int err;
23023 +       struct dentry *d;
23024 +
23025 +       IMustLock(dir);
23026 +
23027 +       err = au_test_nlink(src_dentry->d_inode);
23028 +       if (unlikely(err))
23029 +               return err;
23030 +
23031 +       d = path->dentry;
23032 +       path->dentry = d->d_parent;
23033 +       err = security_path_link(src_dentry, path, d);
23034 +       path->dentry = d;
23035 +       if (unlikely(err))
23036 +               goto out;
23037 +
23038 +       err = vfs_link(src_dentry, dir, path->dentry);
23039 +       if (!err) {
23040 +               struct path tmp = *path;
23041 +               int did;
23042 +
23043 +               /* fuse has different memory inode for the same inumber */
23044 +               vfsub_update_h_iattr(&tmp, &did);
23045 +               if (did) {
23046 +                       tmp.dentry = path->dentry->d_parent;
23047 +                       vfsub_update_h_iattr(&tmp, /*did*/NULL);
23048 +                       tmp.dentry = src_dentry;
23049 +                       vfsub_update_h_iattr(&tmp, /*did*/NULL);
23050 +               }
23051 +               /*ignore*/
23052 +       }
23053 +
23054 +out:
23055 +       return err;
23056 +}
23057 +
23058 +int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
23059 +                struct inode *dir, struct path *path)
23060 +{
23061 +       int err;
23062 +       struct path tmp = {
23063 +               .mnt    = path->mnt
23064 +       };
23065 +       struct dentry *d;
23066 +
23067 +       IMustLock(dir);
23068 +       IMustLock(src_dir);
23069 +
23070 +       d = path->dentry;
23071 +       path->dentry = d->d_parent;
23072 +       tmp.dentry = src_dentry->d_parent;
23073 +       err = security_path_rename(&tmp, src_dentry, path, d);
23074 +       path->dentry = d;
23075 +       if (unlikely(err))
23076 +               goto out;
23077 +
23078 +       err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
23079 +       if (!err) {
23080 +               int did;
23081 +
23082 +               tmp.dentry = d->d_parent;
23083 +               vfsub_update_h_iattr(&tmp, &did);
23084 +               if (did) {
23085 +                       tmp.dentry = src_dentry;
23086 +                       vfsub_update_h_iattr(&tmp, /*did*/NULL);
23087 +                       tmp.dentry = src_dentry->d_parent;
23088 +                       vfsub_update_h_iattr(&tmp, /*did*/NULL);
23089 +               }
23090 +               /*ignore*/
23091 +       }
23092 +
23093 +out:
23094 +       return err;
23095 +}
23096 +
23097 +int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
23098 +{
23099 +       int err;
23100 +       struct dentry *d;
23101 +
23102 +       IMustLock(dir);
23103 +
23104 +       d = path->dentry;
23105 +       path->dentry = d->d_parent;
23106 +       err = security_path_mkdir(path, d, mode);
23107 +       path->dentry = d;
23108 +       if (unlikely(err))
23109 +               goto out;
23110 +
23111 +       err = vfs_mkdir(dir, path->dentry, mode);
23112 +       if (!err) {
23113 +               struct path tmp = *path;
23114 +               int did;
23115 +
23116 +               vfsub_update_h_iattr(&tmp, &did);
23117 +               if (did) {
23118 +                       tmp.dentry = path->dentry->d_parent;
23119 +                       vfsub_update_h_iattr(&tmp, /*did*/NULL);
23120 +               }
23121 +               /*ignore*/
23122 +       }
23123 +
23124 +out:
23125 +       return err;
23126 +}
23127 +
23128 +int vfsub_rmdir(struct inode *dir, struct path *path)
23129 +{
23130 +       int err;
23131 +       struct dentry *d;
23132 +
23133 +       IMustLock(dir);
23134 +
23135 +       d = path->dentry;
23136 +       path->dentry = d->d_parent;
23137 +       err = security_path_rmdir(path, d);
23138 +       path->dentry = d;
23139 +       if (unlikely(err))
23140 +               goto out;
23141 +
23142 +       err = vfs_rmdir(dir, path->dentry);
23143 +       if (!err) {
23144 +               struct path tmp = {
23145 +                       .dentry = path->dentry->d_parent,
23146 +                       .mnt    = path->mnt
23147 +               };
23148 +
23149 +               vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
23150 +       }
23151 +
23152 +out:
23153 +       return err;
23154 +}
23155 +
23156 +/* ---------------------------------------------------------------------- */
23157 +
23158 +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
23159 +                    loff_t *ppos)
23160 +{
23161 +       ssize_t err;
23162 +
23163 +       err = vfs_read(file, ubuf, count, ppos);
23164 +       if (err >= 0)
23165 +               vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23166 +       return err;
23167 +}
23168 +
23169 +/* todo: kernel_read()? */
23170 +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
23171 +                    loff_t *ppos)
23172 +{
23173 +       ssize_t err;
23174 +       mm_segment_t oldfs;
23175 +       union {
23176 +               void *k;
23177 +               char __user *u;
23178 +       } buf;
23179 +
23180 +       buf.k = kbuf;
23181 +       oldfs = get_fs();
23182 +       set_fs(KERNEL_DS);
23183 +       err = vfsub_read_u(file, buf.u, count, ppos);
23184 +       set_fs(oldfs);
23185 +       return err;
23186 +}
23187 +
23188 +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
23189 +                     loff_t *ppos)
23190 +{
23191 +       ssize_t err;
23192 +
23193 +       err = vfs_write(file, ubuf, count, ppos);
23194 +       if (err >= 0)
23195 +               vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23196 +       return err;
23197 +}
23198 +
23199 +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
23200 +{
23201 +       ssize_t err;
23202 +       mm_segment_t oldfs;
23203 +       union {
23204 +               void *k;
23205 +               const char __user *u;
23206 +       } buf;
23207 +
23208 +       buf.k = kbuf;
23209 +       oldfs = get_fs();
23210 +       set_fs(KERNEL_DS);
23211 +       err = vfsub_write_u(file, buf.u, count, ppos);
23212 +       set_fs(oldfs);
23213 +       return err;
23214 +}
23215 +
23216 +int vfsub_flush(struct file *file, fl_owner_t id)
23217 +{
23218 +       int err;
23219 +
23220 +       err = 0;
23221 +       if (file->f_op && file->f_op->flush) {
23222 +               err = file->f_op->flush(file, id);
23223 +               if (!err)
23224 +                       vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
23225 +               /*ignore*/
23226 +       }
23227 +       return err;
23228 +}
23229 +
23230 +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
23231 +{
23232 +       int err;
23233 +
23234 +       err = vfs_readdir(file, filldir, arg);
23235 +       if (err >= 0)
23236 +               vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23237 +       return err;
23238 +}
23239 +
23240 +long vfsub_splice_to(struct file *in, loff_t *ppos,
23241 +                    struct pipe_inode_info *pipe, size_t len,
23242 +                    unsigned int flags)
23243 +{
23244 +       long err;
23245 +
23246 +       err = do_splice_to(in, ppos, pipe, len, flags);
23247 +       file_accessed(in);
23248 +       if (err >= 0)
23249 +               vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
23250 +       return err;
23251 +}
23252 +
23253 +long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
23254 +                      loff_t *ppos, size_t len, unsigned int flags)
23255 +{
23256 +       long err;
23257 +
23258 +       err = do_splice_from(pipe, out, ppos, len, flags);
23259 +       if (err >= 0)
23260 +               vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
23261 +       return err;
23262 +}
23263 +
23264 +/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
23265 +int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
23266 +               struct file *h_file)
23267 +{
23268 +       int err;
23269 +       struct inode *h_inode;
23270 +
23271 +       h_inode = h_path->dentry->d_inode;
23272 +       if (!h_file) {
23273 +               err = mnt_want_write(h_path->mnt);
23274 +               if (err)
23275 +                       goto out;
23276 +               err = inode_permission(h_inode, MAY_WRITE);
23277 +               if (err)
23278 +                       goto out_mnt;
23279 +               err = get_write_access(h_inode);
23280 +               if (err)
23281 +                       goto out_mnt;
23282 +               err = break_lease(h_inode, O_WRONLY);
23283 +               if (err)
23284 +                       goto out_inode;
23285 +       }
23286 +
23287 +       err = locks_verify_truncate(h_inode, h_file, length);
23288 +       if (!err)
23289 +               err = security_path_truncate(h_path);
23290 +       if (!err)
23291 +               err = do_truncate(h_path->dentry, length, attr, h_file);
23292 +
23293 +out_inode:
23294 +       if (!h_file)
23295 +               put_write_access(h_inode);
23296 +out_mnt:
23297 +       if (!h_file)
23298 +               mnt_drop_write(h_path->mnt);
23299 +out:
23300 +       return err;
23301 +}
23302 +
23303 +/* ---------------------------------------------------------------------- */
23304 +
23305 +struct au_vfsub_mkdir_args {
23306 +       int *errp;
23307 +       struct inode *dir;
23308 +       struct path *path;
23309 +       int mode;
23310 +};
23311 +
23312 +static void au_call_vfsub_mkdir(void *args)
23313 +{
23314 +       struct au_vfsub_mkdir_args *a = args;
23315 +       *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
23316 +}
23317 +
23318 +int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
23319 +{
23320 +       int err, do_sio, wkq_err;
23321 +
23322 +       do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
23323 +       if (!do_sio)
23324 +               err = vfsub_mkdir(dir, path, mode);
23325 +       else {
23326 +               struct au_vfsub_mkdir_args args = {
23327 +                       .errp   = &err,
23328 +                       .dir    = dir,
23329 +                       .path   = path,
23330 +                       .mode   = mode
23331 +               };
23332 +               wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
23333 +               if (unlikely(wkq_err))
23334 +                       err = wkq_err;
23335 +       }
23336 +
23337 +       return err;
23338 +}
23339 +
23340 +struct au_vfsub_rmdir_args {
23341 +       int *errp;
23342 +       struct inode *dir;
23343 +       struct path *path;
23344 +};
23345 +
23346 +static void au_call_vfsub_rmdir(void *args)
23347 +{
23348 +       struct au_vfsub_rmdir_args *a = args;
23349 +       *a->errp = vfsub_rmdir(a->dir, a->path);
23350 +}
23351 +
23352 +int vfsub_sio_rmdir(struct inode *dir, struct path *path)
23353 +{
23354 +       int err, do_sio, wkq_err;
23355 +
23356 +       do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
23357 +       if (!do_sio)
23358 +               err = vfsub_rmdir(dir, path);
23359 +       else {
23360 +               struct au_vfsub_rmdir_args args = {
23361 +                       .errp   = &err,
23362 +                       .dir    = dir,
23363 +                       .path   = path
23364 +               };
23365 +               wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
23366 +               if (unlikely(wkq_err))
23367 +                       err = wkq_err;
23368 +       }
23369 +
23370 +       return err;
23371 +}
23372 +
23373 +/* ---------------------------------------------------------------------- */
23374 +
23375 +struct notify_change_args {
23376 +       int *errp;
23377 +       struct path *path;
23378 +       struct iattr *ia;
23379 +};
23380 +
23381 +static void call_notify_change(void *args)
23382 +{
23383 +       struct notify_change_args *a = args;
23384 +       struct inode *h_inode;
23385 +
23386 +       h_inode = a->path->dentry->d_inode;
23387 +       IMustLock(h_inode);
23388 +
23389 +       *a->errp = -EPERM;
23390 +       if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
23391 +               *a->errp = notify_change(a->path->dentry, a->ia);
23392 +               if (!*a->errp)
23393 +                       vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
23394 +       }
23395 +       AuTraceErr(*a->errp);
23396 +}
23397 +
23398 +int vfsub_notify_change(struct path *path, struct iattr *ia)
23399 +{
23400 +       int err;
23401 +       struct notify_change_args args = {
23402 +               .errp   = &err,
23403 +               .path   = path,
23404 +               .ia     = ia
23405 +       };
23406 +
23407 +       call_notify_change(&args);
23408 +
23409 +       return err;
23410 +}
23411 +
23412 +int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
23413 +{
23414 +       int err, wkq_err;
23415 +       struct notify_change_args args = {
23416 +               .errp   = &err,
23417 +               .path   = path,
23418 +               .ia     = ia
23419 +       };
23420 +
23421 +       wkq_err = au_wkq_wait(call_notify_change, &args);
23422 +       if (unlikely(wkq_err))
23423 +               err = wkq_err;
23424 +
23425 +       return err;
23426 +}
23427 +
23428 +/* ---------------------------------------------------------------------- */
23429 +
23430 +struct unlink_args {
23431 +       int *errp;
23432 +       struct inode *dir;
23433 +       struct path *path;
23434 +};
23435 +
23436 +static void call_unlink(void *args)
23437 +{
23438 +       struct unlink_args *a = args;
23439 +       struct dentry *d = a->path->dentry;
23440 +       struct inode *h_inode;
23441 +       const int stop_sillyrename = (au_test_nfs(d->d_sb)
23442 +                                     && atomic_read(&d->d_count) == 1);
23443 +
23444 +       IMustLock(a->dir);
23445 +
23446 +       a->path->dentry = d->d_parent;
23447 +       *a->errp = security_path_unlink(a->path, d);
23448 +       a->path->dentry = d;
23449 +       if (unlikely(*a->errp))
23450 +               return;
23451 +
23452 +       if (!stop_sillyrename)
23453 +               dget(d);
23454 +       h_inode = d->d_inode;
23455 +       if (h_inode)
23456 +               atomic_inc(&h_inode->i_count);
23457 +
23458 +       *a->errp = vfs_unlink(a->dir, d);
23459 +       if (!*a->errp) {
23460 +               struct path tmp = {
23461 +                       .dentry = d->d_parent,
23462 +                       .mnt    = a->path->mnt
23463 +               };
23464 +               vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
23465 +       }
23466 +
23467 +       if (!stop_sillyrename)
23468 +               dput(d);
23469 +       if (h_inode)
23470 +               iput(h_inode);
23471 +
23472 +       AuTraceErr(*a->errp);
23473 +}
23474 +
23475 +/*
23476 + * @dir: must be locked.
23477 + * @dentry: target dentry.
23478 + */
23479 +int vfsub_unlink(struct inode *dir, struct path *path, int force)
23480 +{
23481 +       int err;
23482 +       struct unlink_args args = {
23483 +               .errp   = &err,
23484 +               .dir    = dir,
23485 +               .path   = path
23486 +       };
23487 +
23488 +       if (!force)
23489 +               call_unlink(&args);
23490 +       else {
23491 +               int wkq_err;
23492 +
23493 +               wkq_err = au_wkq_wait(call_unlink, &args);
23494 +               if (unlikely(wkq_err))
23495 +                       err = wkq_err;
23496 +       }
23497 +
23498 +       return err;
23499 +}
23500 diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
23501 --- /usr/share/empty/fs/aufs/vfsub.h    1970-01-01 01:00:00.000000000 +0100
23502 +++ linux/fs/aufs/vfsub.h       2010-10-21 09:52:43.093625591 +0200
23503 @@ -0,0 +1,174 @@
23504 +/*
23505 + * Copyright (C) 2005-2010 Junjiro R. Okajima
23506 + *
23507 + * This program, aufs is free software; you can redistribute it and/or modify
23508 + * it under the terms of the GNU General Public License as published by
23509 + * the Free Software Foundation; either version 2 of the License, or
23510 + * (at your option) any later version.
23511 + *
23512 + * This program is distributed in the hope that it will be useful,
23513 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
23514 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23515 + * GNU General Public License for more details.
23516 + *
23517 + * You should have received a copy of the GNU General Public License
23518 + * along with this program; if not, write to the Free Software
23519 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23520 + */
23521 +
23522 +/*
23523 + * sub-routines for VFS
23524 + */
23525 +
23526 +#ifndef __AUFS_VFSUB_H__
23527 +#define __AUFS_VFSUB_H__
23528 +
23529 +#ifdef __KERNEL__
23530 +
23531 +#include <linux/fs.h>
23532 +
23533 +/* ---------------------------------------------------------------------- */
23534 +
23535 +/* lock subclass for lower inode */
23536 +/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
23537 +/* reduce? gave up. */
23538 +enum {
23539 +       AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
23540 +       AuLsc_I_PARENT,         /* lower inode, parent first */
23541 +       AuLsc_I_PARENT2,        /* copyup dirs */
23542 +       AuLsc_I_PARENT3,        /* copyup wh */
23543 +       AuLsc_I_CHILD,
23544 +       AuLsc_I_CHILD2,
23545 +       AuLsc_I_End
23546 +};
23547 +
23548 +/* to debug easier, do not make them inlined functions */
23549 +#define MtxMustLock(mtx)       AuDebugOn(!mutex_is_locked(mtx))
23550 +#define IMustLock(i)           MtxMustLock(&(i)->i_mutex)
23551 +
23552 +/* ---------------------------------------------------------------------- */
23553 +
23554 +int vfsub_update_h_iattr(struct path *h_path, int *did);
23555 +struct file *vfsub_dentry_open(struct path *path, int flags);
23556 +struct file *vfsub_filp_open(const char *path, int oflags, int mode);
23557 +int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
23558 +struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
23559 +                                   int len);
23560 +struct dentry *vfsub_lookup_hash(struct nameidata *nd);
23561 +
23562 +/* ---------------------------------------------------------------------- */
23563 +
23564 +struct au_hinode;
23565 +struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
23566 +                                struct dentry *d2, struct au_hinode *hdir2);
23567 +void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
23568 +                        struct dentry *d2, struct au_hinode *hdir2);
23569 +
23570 +int vfsub_create(struct inode *dir, struct path *path, int mode);
23571 +int vfsub_symlink(struct inode *dir, struct path *path,
23572 +                 const char *symname);
23573 +int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
23574 +int vfsub_link(struct dentry *src_dentry, struct inode *dir,
23575 +              struct path *path);
23576 +int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
23577 +                struct inode *hdir, struct path *path);
23578 +int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
23579 +int vfsub_rmdir(struct inode *dir, struct path *path);
23580 +
23581 +/* ---------------------------------------------------------------------- */
23582 +
23583 +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
23584 +                    loff_t *ppos);
23585 +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
23586 +                       loff_t *ppos);
23587 +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
23588 +                     loff_t *ppos);
23589 +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
23590 +                     loff_t *ppos);
23591 +int vfsub_flush(struct file *file, fl_owner_t id);
23592 +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
23593 +
23594 +static inline unsigned int vfsub_file_flags(struct file *file)
23595 +{
23596 +       unsigned int flags;
23597 +
23598 +       spin_lock(&file->f_lock);
23599 +       flags = file->f_flags;
23600 +       spin_unlock(&file->f_lock);
23601 +
23602 +       return flags;
23603 +}
23604 +
23605 +static inline void vfsub_file_accessed(struct file *h_file)
23606 +{
23607 +       file_accessed(h_file);
23608 +       vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
23609 +}
23610 +
23611 +static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
23612 +                                    struct dentry *h_dentry)
23613 +{
23614 +       struct path h_path = {
23615 +               .dentry = h_dentry,
23616 +               .mnt    = h_mnt
23617 +       };
23618 +       touch_atime(h_mnt, h_dentry);
23619 +       vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
23620 +}
23621 +
23622 +long vfsub_splice_to(struct file *in, loff_t *ppos,
23623 +                    struct pipe_inode_info *pipe, size_t len,
23624 +                    unsigned int flags);
23625 +long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
23626 +                      loff_t *ppos, size_t len, unsigned int flags);
23627 +int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
23628 +               struct file *h_file);
23629 +
23630 +/* ---------------------------------------------------------------------- */
23631 +
23632 +static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
23633 +{
23634 +       loff_t err;
23635 +
23636 +       err = vfs_llseek(file, offset, origin);
23637 +       return err;
23638 +}
23639 +
23640 +/* ---------------------------------------------------------------------- */
23641 +
23642 +/* dirty workaround for strict type of fmode_t */
23643 +union vfsub_fmu {
23644 +       fmode_t fm;
23645 +       unsigned int ui;
23646 +};
23647 +
23648 +static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
23649 +{
23650 +       union vfsub_fmu u = {
23651 +               .fm = fm
23652 +       };
23653 +
23654 +       BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
23655 +
23656 +       return u.ui;
23657 +}
23658 +
23659 +static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
23660 +{
23661 +       union vfsub_fmu u = {
23662 +               .ui = ui
23663 +       };
23664 +
23665 +       return u.fm;
23666 +}
23667 +
23668 +/* ---------------------------------------------------------------------- */
23669 +
23670 +int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
23671 +int vfsub_sio_rmdir(struct inode *dir, struct path *path);
23672 +int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
23673 +int vfsub_notify_change(struct path *path, struct iattr *ia);
23674 +int vfsub_unlink(struct inode *dir, struct path *path, int force);
23675 +
23676 +#endif /* __KERNEL__ */
23677 +#endif /* __AUFS_VFSUB_H__ */
23678 diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
23679 --- /usr/share/empty/fs/aufs/wbr_policy.c       1970-01-01 01:00:00.000000000 +0100
23680 +++ linux/fs/aufs/wbr_policy.c  2010-10-21 09:52:43.096959416 +0200
23681 @@ -0,0 +1,699 @@
23682 +/*
23683 + * Copyright (C) 2005-2010 Junjiro R. Okajima
23684 + *
23685 + * This program, aufs is free software; you can redistribute it and/or modify
23686 + * it under the terms of the GNU General Public License as published by
23687 + * the Free Software Foundation; either version 2 of the License, or
23688 + * (at your option) any later version.
23689 + *
23690 + * This program is distributed in the hope that it will be useful,
23691 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
23692 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23693 + * GNU General Public License for more details.
23694 + *
23695 + * You should have received a copy of the GNU General Public License
23696 + * along with this program; if not, write to the Free Software
23697 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23698 + */
23699 +
23700 +/*
23701 + * policies for selecting one among multiple writable branches
23702 + */
23703 +
23704 +#include <linux/statfs.h>
23705 +#include "aufs.h"
23706 +
23707 +/* subset of cpup_attr() */
23708 +static noinline_for_stack
23709 +int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
23710 +{
23711 +       int err, sbits;
23712 +       struct iattr ia;
23713 +       struct inode *h_isrc;
23714 +
23715 +       h_isrc = h_src->d_inode;
23716 +       ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
23717 +       ia.ia_mode = h_isrc->i_mode;
23718 +       ia.ia_uid = h_isrc->i_uid;
23719 +       ia.ia_gid = h_isrc->i_gid;
23720 +       sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
23721 +       au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
23722 +       err = vfsub_sio_notify_change(h_path, &ia);
23723 +
23724 +       /* is this nfs only? */
23725 +       if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
23726 +               ia.ia_valid = ATTR_FORCE | ATTR_MODE;
23727 +               ia.ia_mode = h_isrc->i_mode;
23728 +               err = vfsub_sio_notify_change(h_path, &ia);
23729 +       }
23730 +
23731 +       return err;
23732 +}
23733 +
23734 +#define AuCpdown_PARENT_OPQ    1
23735 +#define AuCpdown_WHED          (1 << 1)
23736 +#define AuCpdown_MADE_DIR      (1 << 2)
23737 +#define AuCpdown_DIROPQ                (1 << 3)
23738 +#define au_ftest_cpdown(flags, name)   ((flags) & AuCpdown_##name)
23739 +#define au_fset_cpdown(flags, name)    { (flags) |= AuCpdown_##name; }
23740 +#define au_fclr_cpdown(flags, name)    { (flags) &= ~AuCpdown_##name; }
23741 +
23742 +struct au_cpdown_dir_args {
23743 +       struct dentry *parent;
23744 +       unsigned int flags;
23745 +};
23746 +
23747 +static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
23748 +                            struct au_cpdown_dir_args *a)
23749 +{
23750 +       int err;
23751 +       struct dentry *opq_dentry;
23752 +
23753 +       opq_dentry = au_diropq_create(dentry, bdst);
23754 +       err = PTR_ERR(opq_dentry);
23755 +       if (IS_ERR(opq_dentry))
23756 +               goto out;
23757 +       dput(opq_dentry);
23758 +       au_fset_cpdown(a->flags, DIROPQ);
23759 +
23760 +out:
23761 +       return err;
23762 +}
23763 +
23764 +static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
23765 +                           struct inode *dir, aufs_bindex_t bdst)
23766 +{
23767 +       int err;
23768 +       struct path h_path;
23769 +       struct au_branch *br;
23770 +
23771 +       br = au_sbr(dentry->d_sb, bdst);
23772 +       h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
23773 +       err = PTR_ERR(h_path.dentry);
23774 +       if (IS_ERR(h_path.dentry))
23775 +               goto out;
23776 +
23777 +       err = 0;
23778 +       if (h_path.dentry->d_inode) {
23779 +               h_path.mnt = br->br_mnt;
23780 +               err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
23781 +                                         dentry);
23782 +       }
23783 +       dput(h_path.dentry);
23784 +
23785 +out:
23786 +       return err;
23787 +}
23788 +
23789 +static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
23790 +                        struct dentry *h_parent, void *arg)
23791 +{
23792 +       int err, rerr;
23793 +       aufs_bindex_t bopq, bstart;
23794 +       struct path h_path;
23795 +       struct dentry *parent;
23796 +       struct inode *h_dir, *h_inode, *inode, *dir;
23797 +       struct au_cpdown_dir_args *args = arg;
23798 +
23799 +       bstart = au_dbstart(dentry);
23800 +       /* dentry is di-locked */
23801 +       parent = dget_parent(dentry);
23802 +       dir = parent->d_inode;
23803 +       h_dir = h_parent->d_inode;
23804 +       AuDebugOn(h_dir != au_h_iptr(dir, bdst));
23805 +       IMustLock(h_dir);
23806 +
23807 +       err = au_lkup_neg(dentry, bdst);
23808 +       if (unlikely(err < 0))
23809 +               goto out;
23810 +       h_path.dentry = au_h_dptr(dentry, bdst);
23811 +       h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
23812 +       err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
23813 +                             S_IRWXU | S_IRUGO | S_IXUGO);
23814 +       if (unlikely(err))
23815 +               goto out_put;
23816 +       au_fset_cpdown(args->flags, MADE_DIR);
23817 +
23818 +       bopq = au_dbdiropq(dentry);
23819 +       au_fclr_cpdown(args->flags, WHED);
23820 +       au_fclr_cpdown(args->flags, DIROPQ);
23821 +       if (au_dbwh(dentry) == bdst)
23822 +               au_fset_cpdown(args->flags, WHED);
23823 +       if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
23824 +               au_fset_cpdown(args->flags, PARENT_OPQ);
23825 +       h_inode = h_path.dentry->d_inode;
23826 +       mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
23827 +       if (au_ftest_cpdown(args->flags, WHED)) {
23828 +               err = au_cpdown_dir_opq(dentry, bdst, args);
23829 +               if (unlikely(err)) {
23830 +                       mutex_unlock(&h_inode->i_mutex);
23831 +                       goto out_dir;
23832 +               }
23833 +       }
23834 +
23835 +       err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
23836 +       mutex_unlock(&h_inode->i_mutex);
23837 +       if (unlikely(err))
23838 +               goto out_opq;
23839 +
23840 +       if (au_ftest_cpdown(args->flags, WHED)) {
23841 +               err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
23842 +               if (unlikely(err))
23843 +                       goto out_opq;
23844 +       }
23845 +
23846 +       inode = dentry->d_inode;
23847 +       if (au_ibend(inode) < bdst)
23848 +               au_set_ibend(inode, bdst);
23849 +       au_set_h_iptr(inode, bdst, au_igrab(h_inode),
23850 +                     au_hi_flags(inode, /*isdir*/1));
23851 +       goto out; /* success */
23852 +
23853 +       /* revert */
23854 +out_opq:
23855 +       if (au_ftest_cpdown(args->flags, DIROPQ)) {
23856 +               mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
23857 +               rerr = au_diropq_remove(dentry, bdst);
23858 +               mutex_unlock(&h_inode->i_mutex);
23859 +               if (unlikely(rerr)) {
23860 +                       AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
23861 +                               AuDLNPair(dentry), bdst, rerr);
23862 +                       err = -EIO;
23863 +                       goto out;
23864 +               }
23865 +       }
23866 +out_dir:
23867 +       if (au_ftest_cpdown(args->flags, MADE_DIR)) {
23868 +               rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
23869 +               if (unlikely(rerr)) {
23870 +                       AuIOErr("failed removing %.*s b%d (%d)\n",
23871 +                               AuDLNPair(dentry), bdst, rerr);
23872 +                       err = -EIO;
23873 +               }
23874 +       }
23875 +out_put:
23876 +       au_set_h_dptr(dentry, bdst, NULL);
23877 +       if (au_dbend(dentry) == bdst)
23878 +               au_update_dbend(dentry);
23879 +out:
23880 +       dput(parent);
23881 +       return err;
23882 +}
23883 +
23884 +int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
23885 +{
23886 +       int err;
23887 +       struct au_cpdown_dir_args args = {
23888 +               .parent = dget_parent(dentry),
23889 +               .flags  = 0
23890 +       };
23891 +
23892 +       err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
23893 +       dput(args.parent);
23894 +
23895 +       return err;
23896 +}
23897 +
23898 +/* ---------------------------------------------------------------------- */
23899 +
23900 +/* policies for create */
23901 +
23902 +static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
23903 +{
23904 +       int err, i, j, ndentry;
23905 +       aufs_bindex_t bopq;
23906 +       struct au_dcsub_pages dpages;
23907 +       struct au_dpage *dpage;
23908 +       struct dentry **dentries, *parent, *d;
23909 +
23910 +       err = au_dpages_init(&dpages, GFP_NOFS);
23911 +       if (unlikely(err))
23912 +               goto out;
23913 +       parent = dget_parent(dentry);
23914 +       err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/0, /*test*/NULL,
23915 +                                /*arg*/NULL);
23916 +       if (unlikely(err))
23917 +               goto out_free;
23918 +
23919 +       err = bindex;
23920 +       for (i = 0; i < dpages.ndpage; i++) {
23921 +               dpage = dpages.dpages + i;
23922 +               dentries = dpage->dentries;
23923 +               ndentry = dpage->ndentry;
23924 +               for (j = 0; j < ndentry; j++) {
23925 +                       d = dentries[j];
23926 +                       di_read_lock_parent2(d, !AuLock_IR);
23927 +                       bopq = au_dbdiropq(d);
23928 +                       di_read_unlock(d, !AuLock_IR);
23929 +                       if (bopq >= 0 && bopq < err)
23930 +                               err = bopq;
23931 +               }
23932 +       }
23933 +
23934 +out_free:
23935 +       dput(parent);
23936 +       au_dpages_free(&dpages);
23937 +out:
23938 +       return err;
23939 +}
23940 +
23941 +static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
23942 +{
23943 +       for (; bindex >= 0; bindex--)
23944 +               if (!au_br_rdonly(au_sbr(sb, bindex)))
23945 +                       return bindex;
23946 +       return -EROFS;
23947 +}
23948 +
23949 +/* top down parent */
23950 +static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
23951 +{
23952 +       int err;
23953 +       aufs_bindex_t bstart, bindex;
23954 +       struct super_block *sb;
23955 +       struct dentry *parent, *h_parent;
23956 +
23957 +       sb = dentry->d_sb;
23958 +       bstart = au_dbstart(dentry);
23959 +       err = bstart;
23960 +       if (!au_br_rdonly(au_sbr(sb, bstart)))
23961 +               goto out;
23962 +
23963 +       err = -EROFS;
23964 +       parent = dget_parent(dentry);
23965 +       for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
23966 +               h_parent = au_h_dptr(parent, bindex);
23967 +               if (!h_parent || !h_parent->d_inode)
23968 +                       continue;
23969 +
23970 +               if (!au_br_rdonly(au_sbr(sb, bindex))) {
23971 +                       err = bindex;
23972 +                       break;
23973 +               }
23974 +       }
23975 +       dput(parent);
23976 +
23977 +       /* bottom up here */
23978 +       if (unlikely(err < 0)) {
23979 +               err = au_wbr_bu(sb, bstart - 1);
23980 +               if (err >= 0)
23981 +                       err = au_wbr_nonopq(dentry, err);
23982 +       }
23983 +
23984 +out:
23985 +       AuDbg("b%d\n", err);
23986 +       return err;
23987 +}
23988 +
23989 +/* ---------------------------------------------------------------------- */
23990 +
23991 +/* an exception for the policy other than tdp */
23992 +static int au_wbr_create_exp(struct dentry *dentry)
23993 +{
23994 +       int err;
23995 +       aufs_bindex_t bwh, bdiropq;
23996 +       struct dentry *parent;
23997 +
23998 +       err = -1;
23999 +       bwh = au_dbwh(dentry);
24000 +       parent = dget_parent(dentry);
24001 +       bdiropq = au_dbdiropq(parent);
24002 +       if (bwh >= 0) {
24003 +               if (bdiropq >= 0)
24004 +                       err = min(bdiropq, bwh);
24005 +               else
24006 +                       err = bwh;
24007 +               AuDbg("%d\n", err);
24008 +       } else if (bdiropq >= 0) {
24009 +               err = bdiropq;
24010 +               AuDbg("%d\n", err);
24011 +       }
24012 +       dput(parent);
24013 +
24014 +       if (err >= 0)
24015 +               err = au_wbr_nonopq(dentry, err);
24016 +
24017 +       if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
24018 +               err = -1;
24019 +
24020 +       AuDbg("%d\n", err);
24021 +       return err;
24022 +}
24023 +
24024 +/* ---------------------------------------------------------------------- */
24025 +
24026 +/* round robin */
24027 +static int au_wbr_create_init_rr(struct super_block *sb)
24028 +{
24029 +       int err;
24030 +
24031 +       err = au_wbr_bu(sb, au_sbend(sb));
24032 +       atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
24033 +       /* smp_mb(); */
24034 +
24035 +       AuDbg("b%d\n", err);
24036 +       return err;
24037 +}
24038 +
24039 +static int au_wbr_create_rr(struct dentry *dentry, int isdir)
24040 +{
24041 +       int err, nbr;
24042 +       unsigned int u;
24043 +       aufs_bindex_t bindex, bend;
24044 +       struct super_block *sb;
24045 +       atomic_t *next;
24046 +
24047 +       err = au_wbr_create_exp(dentry);
24048 +       if (err >= 0)
24049 +               goto out;
24050 +
24051 +       sb = dentry->d_sb;
24052 +       next = &au_sbi(sb)->si_wbr_rr_next;
24053 +       bend = au_sbend(sb);
24054 +       nbr = bend + 1;
24055 +       for (bindex = 0; bindex <= bend; bindex++) {
24056 +               if (!isdir) {
24057 +                       err = atomic_dec_return(next) + 1;
24058 +                       /* modulo for 0 is meaningless */
24059 +                       if (unlikely(!err))
24060 +                               err = atomic_dec_return(next) + 1;
24061 +               } else
24062 +                       err = atomic_read(next);
24063 +               AuDbg("%d\n", err);
24064 +               u = err;
24065 +               err = u % nbr;
24066 +               AuDbg("%d\n", err);
24067 +               if (!au_br_rdonly(au_sbr(sb, err)))
24068 +                       break;
24069 +               err = -EROFS;
24070 +       }
24071 +
24072 +       if (err >= 0)
24073 +               err = au_wbr_nonopq(dentry, err);
24074 +
24075 +out:
24076 +       AuDbg("%d\n", err);
24077 +       return err;
24078 +}
24079 +
24080 +/* ---------------------------------------------------------------------- */
24081 +
24082 +/* most free space */
24083 +static void au_mfs(struct dentry *dentry)
24084 +{
24085 +       struct super_block *sb;
24086 +       struct au_branch *br;
24087 +       struct au_wbr_mfs *mfs;
24088 +       aufs_bindex_t bindex, bend;
24089 +       int err;
24090 +       unsigned long long b, bavail;
24091 +       struct path h_path;
24092 +       /* reduce the stack usage */
24093 +       struct kstatfs *st;
24094 +
24095 +       st = kmalloc(sizeof(*st), GFP_NOFS);
24096 +       if (unlikely(!st)) {
24097 +               AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
24098 +               return;
24099 +       }
24100 +
24101 +       bavail = 0;
24102 +       sb = dentry->d_sb;
24103 +       mfs = &au_sbi(sb)->si_wbr_mfs;
24104 +       MtxMustLock(&mfs->mfs_lock);
24105 +       mfs->mfs_bindex = -EROFS;
24106 +       mfs->mfsrr_bytes = 0;
24107 +       bend = au_sbend(sb);
24108 +       for (bindex = 0; bindex <= bend; bindex++) {
24109 +               br = au_sbr(sb, bindex);
24110 +               if (au_br_rdonly(br))
24111 +                       continue;
24112 +
24113 +               /* sb->s_root for NFS is unreliable */
24114 +               h_path.mnt = br->br_mnt;
24115 +               h_path.dentry = h_path.mnt->mnt_root;
24116 +               err = vfs_statfs(&h_path, st);
24117 +               if (unlikely(err)) {
24118 +                       AuWarn1("failed statfs, b%d, %d\n", bindex, err);
24119 +                       continue;
24120 +               }
24121 +
24122 +               /* when the available size is equal, select the lower one */
24123 +               BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
24124 +                            || sizeof(b) < sizeof(st->f_bsize));
24125 +               b = st->f_bavail * st->f_bsize;
24126 +               br->br_wbr->wbr_bytes = b;
24127 +               if (b >= bavail) {
24128 +                       bavail = b;
24129 +                       mfs->mfs_bindex = bindex;
24130 +                       mfs->mfs_jiffy = jiffies;
24131 +               }
24132 +       }
24133 +
24134 +       mfs->mfsrr_bytes = bavail;
24135 +       AuDbg("b%d\n", mfs->mfs_bindex);
24136 +       kfree(st);
24137 +}
24138 +
24139 +static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
24140 +{
24141 +       int err;
24142 +       struct super_block *sb;
24143 +       struct au_wbr_mfs *mfs;
24144 +
24145 +       err = au_wbr_create_exp(dentry);
24146 +       if (err >= 0)
24147 +               goto out;
24148 +
24149 +       sb = dentry->d_sb;
24150 +       mfs = &au_sbi(sb)->si_wbr_mfs;
24151 +       mutex_lock(&mfs->mfs_lock);
24152 +       if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
24153 +           || mfs->mfs_bindex < 0
24154 +           || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
24155 +               au_mfs(dentry);
24156 +       mutex_unlock(&mfs->mfs_lock);
24157 +       err = mfs->mfs_bindex;
24158 +
24159 +       if (err >= 0)
24160 +               err = au_wbr_nonopq(dentry, err);
24161 +
24162 +out:
24163 +       AuDbg("b%d\n", err);
24164 +       return err;
24165 +}
24166 +
24167 +static int au_wbr_create_init_mfs(struct super_block *sb)
24168 +{
24169 +       struct au_wbr_mfs *mfs;
24170 +
24171 +       mfs = &au_sbi(sb)->si_wbr_mfs;
24172 +       mutex_init(&mfs->mfs_lock);
24173 +       mfs->mfs_jiffy = 0;
24174 +       mfs->mfs_bindex = -EROFS;
24175 +
24176 +       return 0;
24177 +}
24178 +
24179 +static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
24180 +{
24181 +       mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
24182 +       return 0;
24183 +}
24184 +
24185 +/* ---------------------------------------------------------------------- */
24186 +
24187 +/* most free space and then round robin */
24188 +static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
24189 +{
24190 +       int err;
24191 +       struct au_wbr_mfs *mfs;
24192 +
24193 +       err = au_wbr_create_mfs(dentry, isdir);
24194 +       if (err >= 0) {
24195 +               mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
24196 +               mutex_lock(&mfs->mfs_lock);
24197 +               if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
24198 +                       err = au_wbr_create_rr(dentry, isdir);
24199 +               mutex_unlock(&mfs->mfs_lock);
24200 +       }
24201 +
24202 +       AuDbg("b%d\n", err);
24203 +       return err;
24204 +}
24205 +
24206 +static int au_wbr_create_init_mfsrr(struct super_block *sb)
24207 +{
24208 +       int err;
24209 +
24210 +       au_wbr_create_init_mfs(sb); /* ignore */
24211 +       err = au_wbr_create_init_rr(sb);
24212 +
24213 +       return err;
24214 +}
24215 +
24216 +/* ---------------------------------------------------------------------- */
24217 +
24218 +/* top down parent and most free space */
24219 +static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
24220 +{
24221 +       int err, e2;
24222 +       unsigned long long b;
24223 +       aufs_bindex_t bindex, bstart, bend;
24224 +       struct super_block *sb;
24225 +       struct dentry *parent, *h_parent;
24226 +       struct au_branch *br;
24227 +
24228 +       err = au_wbr_create_tdp(dentry, isdir);
24229 +       if (unlikely(err < 0))
24230 +               goto out;
24231 +       parent = dget_parent(dentry);
24232 +       bstart = au_dbstart(parent);
24233 +       bend = au_dbtaildir(parent);
24234 +       if (bstart == bend)
24235 +               goto out_parent; /* success */
24236 +
24237 +       e2 = au_wbr_create_mfs(dentry, isdir);
24238 +       if (e2 < 0)
24239 +               goto out_parent; /* success */
24240 +
24241 +       /* when the available size is equal, select upper one */
24242 +       sb = dentry->d_sb;
24243 +       br = au_sbr(sb, err);
24244 +       b = br->br_wbr->wbr_bytes;
24245 +       AuDbg("b%d, %llu\n", err, b);
24246 +
24247 +       for (bindex = bstart; bindex <= bend; bindex++) {
24248 +               h_parent = au_h_dptr(parent, bindex);
24249 +               if (!h_parent || !h_parent->d_inode)
24250 +                       continue;
24251 +
24252 +               br = au_sbr(sb, bindex);
24253 +               if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
24254 +                       b = br->br_wbr->wbr_bytes;
24255 +                       err = bindex;
24256 +                       AuDbg("b%d, %llu\n", err, b);
24257 +               }
24258 +       }
24259 +
24260 +       if (err >= 0)
24261 +               err = au_wbr_nonopq(dentry, err);
24262 +
24263 +out_parent:
24264 +       dput(parent);
24265 +out:
24266 +       AuDbg("b%d\n", err);
24267 +       return err;
24268 +}
24269 +
24270 +/* ---------------------------------------------------------------------- */
24271 +
24272 +/* policies for copyup */
24273 +
24274 +/* top down parent */
24275 +static int au_wbr_copyup_tdp(struct dentry *dentry)
24276 +{
24277 +       return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
24278 +}
24279 +
24280 +/* bottom up parent */
24281 +static int au_wbr_copyup_bup(struct dentry *dentry)
24282 +{
24283 +       int err;
24284 +       aufs_bindex_t bindex, bstart;
24285 +       struct dentry *parent, *h_parent;
24286 +       struct super_block *sb;
24287 +
24288 +       err = -EROFS;
24289 +       sb = dentry->d_sb;
24290 +       parent = dget_parent(dentry);
24291 +       bstart = au_dbstart(parent);
24292 +       for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
24293 +               h_parent = au_h_dptr(parent, bindex);
24294 +               if (!h_parent || !h_parent->d_inode)
24295 +                       continue;
24296 +
24297 +               if (!au_br_rdonly(au_sbr(sb, bindex))) {
24298 +                       err = bindex;
24299 +                       break;
24300 +               }
24301 +       }
24302 +       dput(parent);
24303 +
24304 +       /* bottom up here */
24305 +       if (unlikely(err < 0))
24306 +               err = au_wbr_bu(sb, bstart - 1);
24307 +
24308 +       AuDbg("b%d\n", err);
24309 +       return err;
24310 +}
24311 +
24312 +/* bottom up */
24313 +static int au_wbr_copyup_bu(struct dentry *dentry)
24314 +{
24315 +       int err;
24316 +       aufs_bindex_t bstart;
24317 +
24318 +       bstart = au_dbstart(dentry);
24319 +       err = au_wbr_bu(dentry->d_sb, bstart);
24320 +       AuDbg("b%d\n", err);
24321 +       if (err > bstart)
24322 +               err = au_wbr_nonopq(dentry, err);
24323 +
24324 +       AuDbg("b%d\n", err);
24325 +       return err;
24326 +}
24327 +
24328 +/* ---------------------------------------------------------------------- */
24329 +
24330 +struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
24331 +       [AuWbrCopyup_TDP] = {
24332 +               .copyup = au_wbr_copyup_tdp
24333 +       },
24334 +       [AuWbrCopyup_BUP] = {
24335 +               .copyup = au_wbr_copyup_bup
24336 +       },
24337 +       [AuWbrCopyup_BU] = {
24338 +               .copyup = au_wbr_copyup_bu
24339 +       }
24340 +};
24341 +
24342 +struct au_wbr_create_operations au_wbr_create_ops[] = {
24343 +       [AuWbrCreate_TDP] = {
24344 +               .create = au_wbr_create_tdp
24345 +       },
24346 +       [AuWbrCreate_RR] = {
24347 +               .create = au_wbr_create_rr,
24348 +               .init   = au_wbr_create_init_rr
24349 +       },
24350 +       [AuWbrCreate_MFS] = {
24351 +               .create = au_wbr_create_mfs,
24352 +               .init   = au_wbr_create_init_mfs,
24353 +               .fin    = au_wbr_create_fin_mfs
24354 +       },
24355 +       [AuWbrCreate_MFSV] = {
24356 +               .create = au_wbr_create_mfs,
24357 +               .init   = au_wbr_create_init_mfs,
24358 +               .fin    = au_wbr_create_fin_mfs
24359 +       },
24360 +       [AuWbrCreate_MFSRR] = {
24361 +               .create = au_wbr_create_mfsrr,
24362 +               .init   = au_wbr_create_init_mfsrr,
24363 +               .fin    = au_wbr_create_fin_mfs
24364 +       },
24365 +       [AuWbrCreate_MFSRRV] = {
24366 +               .create = au_wbr_create_mfsrr,
24367 +               .init   = au_wbr_create_init_mfsrr,
24368 +               .fin    = au_wbr_create_fin_mfs
24369 +       },
24370 +       [AuWbrCreate_PMFS] = {
24371 +               .create = au_wbr_create_pmfs,
24372 +               .init   = au_wbr_create_init_mfs,
24373 +               .fin    = au_wbr_create_fin_mfs
24374 +       },
24375 +       [AuWbrCreate_PMFSV] = {
24376 +               .create = au_wbr_create_pmfs,
24377 +               .init   = au_wbr_create_init_mfs,
24378 +               .fin    = au_wbr_create_fin_mfs
24379 +       }
24380 +};
24381 diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
24382 --- /usr/share/empty/fs/aufs/whout.c    1970-01-01 01:00:00.000000000 +0100
24383 +++ linux/fs/aufs/whout.c       2010-10-21 09:52:43.096959416 +0200
24384 @@ -0,0 +1,1052 @@
24385 +/*
24386 + * Copyright (C) 2005-2010 Junjiro R. Okajima
24387 + *
24388 + * This program, aufs is free software; you can redistribute it and/or modify
24389 + * it under the terms of the GNU General Public License as published by
24390 + * the Free Software Foundation; either version 2 of the License, or
24391 + * (at your option) any later version.
24392 + *
24393 + * This program is distributed in the hope that it will be useful,
24394 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
24395 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24396 + * GNU General Public License for more details.
24397 + *
24398 + * You should have received a copy of the GNU General Public License
24399 + * along with this program; if not, write to the Free Software
24400 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24401 + */
24402 +
24403 +/*
24404 + * whiteout for logical deletion and opaque directory
24405 + */
24406 +
24407 +#include <linux/fs.h>
24408 +#include "aufs.h"
24409 +
24410 +#define WH_MASK                        S_IRUGO
24411 +
24412 +/*
24413 + * If a directory contains this file, then it is opaque.  We start with the
24414 + * .wh. flag so that it is blocked by lookup.
24415 + */
24416 +static struct qstr diropq_name = {
24417 +       .name = AUFS_WH_DIROPQ,
24418 +       .len = sizeof(AUFS_WH_DIROPQ) - 1
24419 +};
24420 +
24421 +/*
24422 + * generate whiteout name, which is NOT terminated by NULL.
24423 + * @name: original d_name.name
24424 + * @len: original d_name.len
24425 + * @wh: whiteout qstr
24426 + * returns zero when succeeds, otherwise error.
24427 + * succeeded value as wh->name should be freed by kfree().
24428 + */
24429 +int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
24430 +{
24431 +       char *p;
24432 +
24433 +       if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
24434 +               return -ENAMETOOLONG;
24435 +
24436 +       wh->len = name->len + AUFS_WH_PFX_LEN;
24437 +       p = kmalloc(wh->len, GFP_NOFS);
24438 +       wh->name = p;
24439 +       if (p) {
24440 +               memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
24441 +               memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
24442 +               /* smp_mb(); */
24443 +               return 0;
24444 +       }
24445 +       return -ENOMEM;
24446 +}
24447 +
24448 +/* ---------------------------------------------------------------------- */
24449 +
24450 +/*
24451 + * test if the @wh_name exists under @h_parent.
24452 + * @try_sio specifies the necessary of super-io.
24453 + */
24454 +int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
24455 +              struct au_branch *br, int try_sio)
24456 +{
24457 +       int err;
24458 +       struct dentry *wh_dentry;
24459 +
24460 +       if (!try_sio)
24461 +               wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
24462 +       else
24463 +               wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
24464 +       err = PTR_ERR(wh_dentry);
24465 +       if (IS_ERR(wh_dentry))
24466 +               goto out;
24467 +
24468 +       err = 0;
24469 +       if (!wh_dentry->d_inode)
24470 +               goto out_wh; /* success */
24471 +
24472 +       err = 1;
24473 +       if (S_ISREG(wh_dentry->d_inode->i_mode))
24474 +               goto out_wh; /* success */
24475 +
24476 +       err = -EIO;
24477 +       AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
24478 +               AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
24479 +
24480 +out_wh:
24481 +       dput(wh_dentry);
24482 +out:
24483 +       return err;
24484 +}
24485 +
24486 +/*
24487 + * test if the @h_dentry sets opaque or not.
24488 + */
24489 +int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
24490 +{
24491 +       int err;
24492 +       struct inode *h_dir;
24493 +
24494 +       h_dir = h_dentry->d_inode;
24495 +       err = au_wh_test(h_dentry, &diropq_name, br,
24496 +                        au_test_h_perm_sio(h_dir, MAY_EXEC));
24497 +       return err;
24498 +}
24499 +
24500 +/*
24501 + * returns a negative dentry whose name is unique and temporary.
24502 + */
24503 +struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
24504 +                            struct qstr *prefix)
24505 +{
24506 +       struct dentry *dentry;
24507 +       int i;
24508 +       char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN_MIN + 1],
24509 +               *name, *p;
24510 +       static unsigned short cnt;
24511 +       struct qstr qs;
24512 +
24513 +       BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
24514 +
24515 +       name = defname;
24516 +       qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
24517 +       if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
24518 +               dentry = ERR_PTR(-ENAMETOOLONG);
24519 +               if (unlikely(qs.len > NAME_MAX))
24520 +                       goto out;
24521 +               dentry = ERR_PTR(-ENOMEM);
24522 +               name = kmalloc(qs.len + 1, GFP_NOFS);
24523 +               if (unlikely(!name))
24524 +                       goto out;
24525 +       }
24526 +
24527 +       /* doubly whiteout-ed */
24528 +       memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
24529 +       p = name + AUFS_WH_PFX_LEN * 2;
24530 +       memcpy(p, prefix->name, prefix->len);
24531 +       p += prefix->len;
24532 +       *p++ = '.';
24533 +       AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
24534 +
24535 +       qs.name = name;
24536 +       for (i = 0; i < 3; i++) {
24537 +               sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
24538 +               dentry = au_sio_lkup_one(&qs, h_parent, br);
24539 +               if (IS_ERR(dentry) || !dentry->d_inode)
24540 +                       goto out_name;
24541 +               dput(dentry);
24542 +       }
24543 +       /* pr_warning("could not get random name\n"); */
24544 +       dentry = ERR_PTR(-EEXIST);
24545 +       AuDbg("%.*s\n", AuLNPair(&qs));
24546 +       BUG();
24547 +
24548 +out_name:
24549 +       if (name != defname)
24550 +               kfree(name);
24551 +out:
24552 +       AuTraceErrPtr(dentry);
24553 +       return dentry;
24554 +}
24555 +
24556 +/*
24557 + * rename the @h_dentry on @br to the whiteouted temporary name.
24558 + */
24559 +int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
24560 +{
24561 +       int err;
24562 +       struct path h_path = {
24563 +               .mnt = br->br_mnt
24564 +       };
24565 +       struct inode *h_dir;
24566 +       struct dentry *h_parent;
24567 +
24568 +       h_parent = h_dentry->d_parent; /* dir inode is locked */
24569 +       h_dir = h_parent->d_inode;
24570 +       IMustLock(h_dir);
24571 +
24572 +       h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
24573 +       err = PTR_ERR(h_path.dentry);
24574 +       if (IS_ERR(h_path.dentry))
24575 +               goto out;
24576 +
24577 +       /* under the same dir, no need to lock_rename() */
24578 +       err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
24579 +       AuTraceErr(err);
24580 +       dput(h_path.dentry);
24581 +
24582 +out:
24583 +       AuTraceErr(err);
24584 +       return err;
24585 +}
24586 +
24587 +/* ---------------------------------------------------------------------- */
24588 +/*
24589 + * functions for removing a whiteout
24590 + */
24591 +
24592 +static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
24593 +{
24594 +       int force;
24595 +
24596 +       /*
24597 +        * forces superio when the dir has a sticky bit.
24598 +        * this may be a violation of unix fs semantics.
24599 +        */
24600 +       force = (h_dir->i_mode & S_ISVTX)
24601 +               && h_path->dentry->d_inode->i_uid != current_fsuid();
24602 +       return vfsub_unlink(h_dir, h_path, force);
24603 +}
24604 +
24605 +int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
24606 +                       struct dentry *dentry)
24607 +{
24608 +       int err;
24609 +
24610 +       err = do_unlink_wh(h_dir, h_path);
24611 +       if (!err && dentry)
24612 +               au_set_dbwh(dentry, -1);
24613 +
24614 +       return err;
24615 +}
24616 +
24617 +static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
24618 +                         struct au_branch *br)
24619 +{
24620 +       int err;
24621 +       struct path h_path = {
24622 +               .mnt = br->br_mnt
24623 +       };
24624 +
24625 +       err = 0;
24626 +       h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
24627 +       if (IS_ERR(h_path.dentry))
24628 +               err = PTR_ERR(h_path.dentry);
24629 +       else {
24630 +               if (h_path.dentry->d_inode
24631 +                   && S_ISREG(h_path.dentry->d_inode->i_mode))
24632 +                       err = do_unlink_wh(h_parent->d_inode, &h_path);
24633 +               dput(h_path.dentry);
24634 +       }
24635 +
24636 +       return err;
24637 +}
24638 +
24639 +/* ---------------------------------------------------------------------- */
24640 +/*
24641 + * initialize/clean whiteout for a branch
24642 + */
24643 +
24644 +static void au_wh_clean(struct inode *h_dir, struct path *whpath,
24645 +                       const int isdir)
24646 +{
24647 +       int err;
24648 +
24649 +       if (!whpath->dentry->d_inode)
24650 +               return;
24651 +
24652 +       err = mnt_want_write(whpath->mnt);
24653 +       if (!err) {
24654 +               if (isdir)
24655 +                       err = vfsub_rmdir(h_dir, whpath);
24656 +               else
24657 +                       err = vfsub_unlink(h_dir, whpath, /*force*/0);
24658 +               mnt_drop_write(whpath->mnt);
24659 +       }
24660 +       if (unlikely(err))
24661 +               pr_warning("failed removing %.*s (%d), ignored.\n",
24662 +                          AuDLNPair(whpath->dentry), err);
24663 +}
24664 +
24665 +static int test_linkable(struct dentry *h_root)
24666 +{
24667 +       struct inode *h_dir = h_root->d_inode;
24668 +
24669 +       if (h_dir->i_op->link)
24670 +               return 0;
24671 +
24672 +       pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
24673 +              AuDLNPair(h_root), au_sbtype(h_root->d_sb));
24674 +       return -ENOSYS;
24675 +}
24676 +
24677 +/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
24678 +static int au_whdir(struct inode *h_dir, struct path *path)
24679 +{
24680 +       int err;
24681 +
24682 +       err = -EEXIST;
24683 +       if (!path->dentry->d_inode) {
24684 +               int mode = S_IRWXU;
24685 +
24686 +               if (au_test_nfs(path->dentry->d_sb))
24687 +                       mode |= S_IXUGO;
24688 +               err = mnt_want_write(path->mnt);
24689 +               if (!err) {
24690 +                       err = vfsub_mkdir(h_dir, path, mode);
24691 +                       mnt_drop_write(path->mnt);
24692 +               }
24693 +       } else if (S_ISDIR(path->dentry->d_inode->i_mode))
24694 +               err = 0;
24695 +       else
24696 +               pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
24697 +
24698 +       return err;
24699 +}
24700 +
24701 +struct au_wh_base {
24702 +       const struct qstr *name;
24703 +       struct dentry *dentry;
24704 +};
24705 +
24706 +static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
24707 +                         struct path *h_path)
24708 +{
24709 +       h_path->dentry = base[AuBrWh_BASE].dentry;
24710 +       au_wh_clean(h_dir, h_path, /*isdir*/0);
24711 +       h_path->dentry = base[AuBrWh_PLINK].dentry;
24712 +       au_wh_clean(h_dir, h_path, /*isdir*/1);
24713 +       h_path->dentry = base[AuBrWh_ORPH].dentry;
24714 +       au_wh_clean(h_dir, h_path, /*isdir*/1);
24715 +}
24716 +
24717 +/*
24718 + * returns tri-state,
24719 + * minus: error, caller should print the mesage
24720 + * zero: succuess
24721 + * plus: error, caller should NOT print the mesage
24722 + */
24723 +static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
24724 +                               int do_plink, struct au_wh_base base[],
24725 +                               struct path *h_path)
24726 +{
24727 +       int err;
24728 +       struct inode *h_dir;
24729 +
24730 +       h_dir = h_root->d_inode;
24731 +       h_path->dentry = base[AuBrWh_BASE].dentry;
24732 +       au_wh_clean(h_dir, h_path, /*isdir*/0);
24733 +       h_path->dentry = base[AuBrWh_PLINK].dentry;
24734 +       if (do_plink) {
24735 +               err = test_linkable(h_root);
24736 +               if (unlikely(err)) {
24737 +                       err = 1;
24738 +                       goto out;
24739 +               }
24740 +
24741 +               err = au_whdir(h_dir, h_path);
24742 +               if (unlikely(err))
24743 +                       goto out;
24744 +               wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
24745 +       } else
24746 +               au_wh_clean(h_dir, h_path, /*isdir*/1);
24747 +       h_path->dentry = base[AuBrWh_ORPH].dentry;
24748 +       err = au_whdir(h_dir, h_path);
24749 +       if (unlikely(err))
24750 +               goto out;
24751 +       wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
24752 +
24753 +out:
24754 +       return err;
24755 +}
24756 +
24757 +/*
24758 + * for the moment, aufs supports the branch filesystem which does not support
24759 + * link(2). testing on FAT which does not support i_op->setattr() fully either,
24760 + * copyup failed. finally, such filesystem will not be used as the writable
24761 + * branch.
24762 + *
24763 + * returns tri-state, see above.
24764 + */
24765 +static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
24766 +                        int do_plink, struct au_wh_base base[],
24767 +                        struct path *h_path)
24768 +{
24769 +       int err;
24770 +       struct inode *h_dir;
24771 +
24772 +       WbrWhMustWriteLock(wbr);
24773 +
24774 +       err = test_linkable(h_root);
24775 +       if (unlikely(err)) {
24776 +               err = 1;
24777 +               goto out;
24778 +       }
24779 +
24780 +       /*
24781 +        * todo: should this create be done in /sbin/mount.aufs helper?
24782 +        */
24783 +       err = -EEXIST;
24784 +       h_dir = h_root->d_inode;
24785 +       if (!base[AuBrWh_BASE].dentry->d_inode) {
24786 +               err = mnt_want_write(h_path->mnt);
24787 +               if (!err) {
24788 +                       h_path->dentry = base[AuBrWh_BASE].dentry;
24789 +                       err = vfsub_create(h_dir, h_path, WH_MASK);
24790 +                       mnt_drop_write(h_path->mnt);
24791 +               }
24792 +       } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
24793 +               err = 0;
24794 +       else
24795 +               pr_err("unknown %.*s/%.*s exists\n",
24796 +                      AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
24797 +       if (unlikely(err))
24798 +               goto out;
24799 +
24800 +       h_path->dentry = base[AuBrWh_PLINK].dentry;
24801 +       if (do_plink) {
24802 +               err = au_whdir(h_dir, h_path);
24803 +               if (unlikely(err))
24804 +                       goto out;
24805 +               wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
24806 +       } else
24807 +               au_wh_clean(h_dir, h_path, /*isdir*/1);
24808 +       wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
24809 +
24810 +       h_path->dentry = base[AuBrWh_ORPH].dentry;
24811 +       err = au_whdir(h_dir, h_path);
24812 +       if (unlikely(err))
24813 +               goto out;
24814 +       wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
24815 +
24816 +out:
24817 +       return err;
24818 +}
24819 +
24820 +/*
24821 + * initialize the whiteout base file/dir for @br.
24822 + */
24823 +int au_wh_init(struct dentry *h_root, struct au_branch *br,
24824 +              struct super_block *sb)
24825 +{
24826 +       int err, i;
24827 +       const unsigned char do_plink
24828 +               = !!au_opt_test(au_mntflags(sb), PLINK);
24829 +       struct path path = {
24830 +               .mnt = br->br_mnt
24831 +       };
24832 +       struct inode *h_dir;
24833 +       struct au_wbr *wbr = br->br_wbr;
24834 +       static const struct qstr base_name[] = {
24835 +               [AuBrWh_BASE] = {
24836 +                       .name   = AUFS_BASE_NAME,
24837 +                       .len    = sizeof(AUFS_BASE_NAME) - 1
24838 +               },
24839 +               [AuBrWh_PLINK] = {
24840 +                       .name   = AUFS_PLINKDIR_NAME,
24841 +                       .len    = sizeof(AUFS_PLINKDIR_NAME) - 1
24842 +               },
24843 +               [AuBrWh_ORPH] = {
24844 +                       .name   = AUFS_ORPHDIR_NAME,
24845 +                       .len    = sizeof(AUFS_ORPHDIR_NAME) - 1
24846 +               }
24847 +       };
24848 +       struct au_wh_base base[] = {
24849 +               [AuBrWh_BASE] = {
24850 +                       .name   = base_name + AuBrWh_BASE,
24851 +                       .dentry = NULL
24852 +               },
24853 +               [AuBrWh_PLINK] = {
24854 +                       .name   = base_name + AuBrWh_PLINK,
24855 +                       .dentry = NULL
24856 +               },
24857 +               [AuBrWh_ORPH] = {
24858 +                       .name   = base_name + AuBrWh_ORPH,
24859 +                       .dentry = NULL
24860 +               }
24861 +       };
24862 +
24863 +       if (wbr)
24864 +               WbrWhMustWriteLock(wbr);
24865 +
24866 +       for (i = 0; i < AuBrWh_Last; i++) {
24867 +               /* doubly whiteouted */
24868 +               struct dentry *d;
24869 +
24870 +               d = au_wh_lkup(h_root, (void *)base[i].name, br);
24871 +               err = PTR_ERR(d);
24872 +               if (IS_ERR(d))
24873 +                       goto out;
24874 +
24875 +               base[i].dentry = d;
24876 +               AuDebugOn(wbr
24877 +                         && wbr->wbr_wh[i]
24878 +                         && wbr->wbr_wh[i] != base[i].dentry);
24879 +       }
24880 +
24881 +       if (wbr)
24882 +               for (i = 0; i < AuBrWh_Last; i++) {
24883 +                       dput(wbr->wbr_wh[i]);
24884 +                       wbr->wbr_wh[i] = NULL;
24885 +               }
24886 +
24887 +       err = 0;
24888 +       switch (br->br_perm) {
24889 +       case AuBrPerm_RO:
24890 +       case AuBrPerm_ROWH:
24891 +       case AuBrPerm_RR:
24892 +       case AuBrPerm_RRWH:
24893 +               h_dir = h_root->d_inode;
24894 +               au_wh_init_ro(h_dir, base, &path);
24895 +               break;
24896 +
24897 +       case AuBrPerm_RWNoLinkWH:
24898 +               err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
24899 +               if (err > 0)
24900 +                       goto out;
24901 +               else if (err)
24902 +                       goto out_err;
24903 +               break;
24904 +
24905 +       case AuBrPerm_RW:
24906 +               err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
24907 +               if (err > 0)
24908 +                       goto out;
24909 +               else if (err)
24910 +                       goto out_err;
24911 +               break;
24912 +
24913 +       default:
24914 +               BUG();
24915 +       }
24916 +       goto out; /* success */
24917 +
24918 +out_err:
24919 +       pr_err("an error(%d) on the writable branch %.*s(%s)\n",
24920 +              err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
24921 +out:
24922 +       for (i = 0; i < AuBrWh_Last; i++)
24923 +               dput(base[i].dentry);
24924 +       return err;
24925 +}
24926 +
24927 +/* ---------------------------------------------------------------------- */
24928 +/*
24929 + * whiteouts are all hard-linked usually.
24930 + * when its link count reaches a ceiling, we create a new whiteout base
24931 + * asynchronously.
24932 + */
24933 +
24934 +struct reinit_br_wh {
24935 +       struct super_block *sb;
24936 +       struct au_branch *br;
24937 +};
24938 +
24939 +static void reinit_br_wh(void *arg)
24940 +{
24941 +       int err;
24942 +       aufs_bindex_t bindex;
24943 +       struct path h_path;
24944 +       struct reinit_br_wh *a = arg;
24945 +       struct au_wbr *wbr;
24946 +       struct inode *dir;
24947 +       struct dentry *h_root;
24948 +       struct au_hinode *hdir;
24949 +
24950 +       err = 0;
24951 +       wbr = a->br->br_wbr;
24952 +       /* big aufs lock */
24953 +       si_noflush_write_lock(a->sb);
24954 +       if (!au_br_writable(a->br->br_perm))
24955 +               goto out;
24956 +       bindex = au_br_index(a->sb, a->br->br_id);
24957 +       if (unlikely(bindex < 0))
24958 +               goto out;
24959 +
24960 +       di_read_lock_parent(a->sb->s_root, AuLock_IR);
24961 +       dir = a->sb->s_root->d_inode;
24962 +       hdir = au_hi(dir, bindex);
24963 +       h_root = au_h_dptr(a->sb->s_root, bindex);
24964 +
24965 +       au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
24966 +       wbr_wh_write_lock(wbr);
24967 +       err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
24968 +                         h_root, a->br);
24969 +       if (!err) {
24970 +               err = mnt_want_write(a->br->br_mnt);
24971 +               if (!err) {
24972 +                       h_path.dentry = wbr->wbr_whbase;
24973 +                       h_path.mnt = a->br->br_mnt;
24974 +                       err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
24975 +                       mnt_drop_write(a->br->br_mnt);
24976 +               }
24977 +       } else {
24978 +               pr_warning("%.*s is moved, ignored\n",
24979 +                          AuDLNPair(wbr->wbr_whbase));
24980 +               err = 0;
24981 +       }
24982 +       dput(wbr->wbr_whbase);
24983 +       wbr->wbr_whbase = NULL;
24984 +       if (!err)
24985 +               err = au_wh_init(h_root, a->br, a->sb);
24986 +       wbr_wh_write_unlock(wbr);
24987 +       au_hn_imtx_unlock(hdir);
24988 +       di_read_unlock(a->sb->s_root, AuLock_IR);
24989 +
24990 +out:
24991 +       if (wbr)
24992 +               atomic_dec(&wbr->wbr_wh_running);
24993 +       atomic_dec(&a->br->br_count);
24994 +       au_nwt_done(&au_sbi(a->sb)->si_nowait);
24995 +       si_write_unlock(a->sb);
24996 +       kfree(arg);
24997 +       if (unlikely(err))
24998 +               AuIOErr("err %d\n", err);
24999 +}
25000 +
25001 +static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
25002 +{
25003 +       int do_dec, wkq_err;
25004 +       struct reinit_br_wh *arg;
25005 +
25006 +       do_dec = 1;
25007 +       if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
25008 +               goto out;
25009 +
25010 +       /* ignore ENOMEM */
25011 +       arg = kmalloc(sizeof(*arg), GFP_NOFS);
25012 +       if (arg) {
25013 +               /*
25014 +                * dec(wh_running), kfree(arg) and dec(br_count)
25015 +                * in reinit function
25016 +                */
25017 +               arg->sb = sb;
25018 +               arg->br = br;
25019 +               atomic_inc(&br->br_count);
25020 +               wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
25021 +               if (unlikely(wkq_err)) {
25022 +                       atomic_dec(&br->br_wbr->wbr_wh_running);
25023 +                       atomic_dec(&br->br_count);
25024 +                       kfree(arg);
25025 +               }
25026 +               do_dec = 0;
25027 +       }
25028 +
25029 +out:
25030 +       if (do_dec)
25031 +               atomic_dec(&br->br_wbr->wbr_wh_running);
25032 +}
25033 +
25034 +/* ---------------------------------------------------------------------- */
25035 +
25036 +/*
25037 + * create the whiteout @wh.
25038 + */
25039 +static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
25040 +                            struct dentry *wh)
25041 +{
25042 +       int err;
25043 +       struct path h_path = {
25044 +               .dentry = wh
25045 +       };
25046 +       struct au_branch *br;
25047 +       struct au_wbr *wbr;
25048 +       struct dentry *h_parent;
25049 +       struct inode *h_dir;
25050 +
25051 +       h_parent = wh->d_parent; /* dir inode is locked */
25052 +       h_dir = h_parent->d_inode;
25053 +       IMustLock(h_dir);
25054 +
25055 +       br = au_sbr(sb, bindex);
25056 +       h_path.mnt = br->br_mnt;
25057 +       wbr = br->br_wbr;
25058 +       wbr_wh_read_lock(wbr);
25059 +       if (wbr->wbr_whbase) {
25060 +               err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
25061 +               if (!err || err != -EMLINK)
25062 +                       goto out;
25063 +
25064 +               /* link count full. re-initialize br_whbase. */
25065 +               kick_reinit_br_wh(sb, br);
25066 +       }
25067 +
25068 +       /* return this error in this context */
25069 +       err = vfsub_create(h_dir, &h_path, WH_MASK);
25070 +
25071 +out:
25072 +       wbr_wh_read_unlock(wbr);
25073 +       return err;
25074 +}
25075 +
25076 +/* ---------------------------------------------------------------------- */
25077 +
25078 +/*
25079 + * create or remove the diropq.
25080 + */
25081 +static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
25082 +                               unsigned int flags)
25083 +{
25084 +       struct dentry *opq_dentry, *h_dentry;
25085 +       struct super_block *sb;
25086 +       struct au_branch *br;
25087 +       int err;
25088 +
25089 +       sb = dentry->d_sb;
25090 +       br = au_sbr(sb, bindex);
25091 +       h_dentry = au_h_dptr(dentry, bindex);
25092 +       opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
25093 +       if (IS_ERR(opq_dentry))
25094 +               goto out;
25095 +
25096 +       if (au_ftest_diropq(flags, CREATE)) {
25097 +               err = link_or_create_wh(sb, bindex, opq_dentry);
25098 +               if (!err) {
25099 +                       au_set_dbdiropq(dentry, bindex);
25100 +                       goto out; /* success */
25101 +               }
25102 +       } else {
25103 +               struct path tmp = {
25104 +                       .dentry = opq_dentry,
25105 +                       .mnt    = br->br_mnt
25106 +               };
25107 +               err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
25108 +               if (!err)
25109 +                       au_set_dbdiropq(dentry, -1);
25110 +       }
25111 +       dput(opq_dentry);
25112 +       opq_dentry = ERR_PTR(err);
25113 +
25114 +out:
25115 +       return opq_dentry;
25116 +}
25117 +
25118 +struct do_diropq_args {
25119 +       struct dentry **errp;
25120 +       struct dentry *dentry;
25121 +       aufs_bindex_t bindex;
25122 +       unsigned int flags;
25123 +};
25124 +
25125 +static void call_do_diropq(void *args)
25126 +{
25127 +       struct do_diropq_args *a = args;
25128 +       *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
25129 +}
25130 +
25131 +struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
25132 +                            unsigned int flags)
25133 +{
25134 +       struct dentry *diropq, *h_dentry;
25135 +
25136 +       h_dentry = au_h_dptr(dentry, bindex);
25137 +       if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
25138 +               diropq = do_diropq(dentry, bindex, flags);
25139 +       else {
25140 +               int wkq_err;
25141 +               struct do_diropq_args args = {
25142 +                       .errp           = &diropq,
25143 +                       .dentry         = dentry,
25144 +                       .bindex         = bindex,
25145 +                       .flags          = flags
25146 +               };
25147 +
25148 +               wkq_err = au_wkq_wait(call_do_diropq, &args);
25149 +               if (unlikely(wkq_err))
25150 +                       diropq = ERR_PTR(wkq_err);
25151 +       }
25152 +
25153 +       return diropq;
25154 +}
25155 +
25156 +/* ---------------------------------------------------------------------- */
25157 +
25158 +/*
25159 + * lookup whiteout dentry.
25160 + * @h_parent: lower parent dentry which must exist and be locked
25161 + * @base_name: name of dentry which will be whiteouted
25162 + * returns dentry for whiteout.
25163 + */
25164 +struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
25165 +                         struct au_branch *br)
25166 +{
25167 +       int err;
25168 +       struct qstr wh_name;
25169 +       struct dentry *wh_dentry;
25170 +
25171 +       err = au_wh_name_alloc(&wh_name, base_name);
25172 +       wh_dentry = ERR_PTR(err);
25173 +       if (!err) {
25174 +               wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
25175 +               kfree(wh_name.name);
25176 +       }
25177 +       return wh_dentry;
25178 +}
25179 +
25180 +/*
25181 + * link/create a whiteout for @dentry on @bindex.
25182 + */
25183 +struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
25184 +                           struct dentry *h_parent)
25185 +{
25186 +       struct dentry *wh_dentry;
25187 +       struct super_block *sb;
25188 +       int err;
25189 +
25190 +       sb = dentry->d_sb;
25191 +       wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
25192 +       if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
25193 +               err = link_or_create_wh(sb, bindex, wh_dentry);
25194 +               if (!err)
25195 +                       au_set_dbwh(dentry, bindex);
25196 +               else {
25197 +                       dput(wh_dentry);
25198 +                       wh_dentry = ERR_PTR(err);
25199 +               }
25200 +       }
25201 +
25202 +       return wh_dentry;
25203 +}
25204 +
25205 +/* ---------------------------------------------------------------------- */
25206 +
25207 +/* Delete all whiteouts in this directory on branch bindex. */
25208 +static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
25209 +                          aufs_bindex_t bindex, struct au_branch *br)
25210 +{
25211 +       int err;
25212 +       unsigned long ul, n;
25213 +       struct qstr wh_name;
25214 +       char *p;
25215 +       struct hlist_head *head;
25216 +       struct au_vdir_wh *tpos;
25217 +       struct hlist_node *pos;
25218 +       struct au_vdir_destr *str;
25219 +
25220 +       err = -ENOMEM;
25221 +       p = __getname_gfp(GFP_NOFS);
25222 +       wh_name.name = p;
25223 +       if (unlikely(!wh_name.name))
25224 +               goto out;
25225 +
25226 +       err = 0;
25227 +       memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25228 +       p += AUFS_WH_PFX_LEN;
25229 +       n = whlist->nh_num;
25230 +       head = whlist->nh_head;
25231 +       for (ul = 0; !err && ul < n; ul++, head++) {
25232 +               hlist_for_each_entry(tpos, pos, head, wh_hash) {
25233 +                       if (tpos->wh_bindex != bindex)
25234 +                               continue;
25235 +
25236 +                       str = &tpos->wh_str;
25237 +                       if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
25238 +                               memcpy(p, str->name, str->len);
25239 +                               wh_name.len = AUFS_WH_PFX_LEN + str->len;
25240 +                               err = unlink_wh_name(h_dentry, &wh_name, br);
25241 +                               if (!err)
25242 +                                       continue;
25243 +                               break;
25244 +                       }
25245 +                       AuIOErr("whiteout name too long %.*s\n",
25246 +                               str->len, str->name);
25247 +                       err = -EIO;
25248 +                       break;
25249 +               }
25250 +       }
25251 +       __putname(wh_name.name);
25252 +
25253 +out:
25254 +       return err;
25255 +}
25256 +
25257 +struct del_wh_children_args {
25258 +       int *errp;
25259 +       struct dentry *h_dentry;
25260 +       struct au_nhash *whlist;
25261 +       aufs_bindex_t bindex;
25262 +       struct au_branch *br;
25263 +};
25264 +
25265 +static void call_del_wh_children(void *args)
25266 +{
25267 +       struct del_wh_children_args *a = args;
25268 +       *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
25269 +}
25270 +
25271 +/* ---------------------------------------------------------------------- */
25272 +
25273 +struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
25274 +{
25275 +       struct au_whtmp_rmdir *whtmp;
25276 +       int err;
25277 +       unsigned int rdhash;
25278 +
25279 +       SiMustAnyLock(sb);
25280 +
25281 +       whtmp = kmalloc(sizeof(*whtmp), gfp);
25282 +       if (unlikely(!whtmp)) {
25283 +               whtmp = ERR_PTR(-ENOMEM);
25284 +               goto out;
25285 +       }
25286 +
25287 +       whtmp->dir = NULL;
25288 +       whtmp->wh_dentry = NULL;
25289 +       /* no estimation for dir size */
25290 +       rdhash = au_sbi(sb)->si_rdhash;
25291 +       if (!rdhash)
25292 +               rdhash = AUFS_RDHASH_DEF;
25293 +       err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
25294 +       if (unlikely(err)) {
25295 +               kfree(whtmp);
25296 +               whtmp = ERR_PTR(err);
25297 +       }
25298 +
25299 +out:
25300 +       return whtmp;
25301 +}
25302 +
25303 +void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
25304 +{
25305 +       dput(whtmp->wh_dentry);
25306 +       iput(whtmp->dir);
25307 +       au_nhash_wh_free(&whtmp->whlist);
25308 +       kfree(whtmp);
25309 +}
25310 +
25311 +/*
25312 + * rmdir the whiteouted temporary named dir @h_dentry.
25313 + * @whlist: whiteouted children.
25314 + */
25315 +int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
25316 +                  struct dentry *wh_dentry, struct au_nhash *whlist)
25317 +{
25318 +       int err;
25319 +       struct path h_tmp;
25320 +       struct inode *wh_inode, *h_dir;
25321 +       struct au_branch *br;
25322 +
25323 +       h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
25324 +       IMustLock(h_dir);
25325 +
25326 +       br = au_sbr(dir->i_sb, bindex);
25327 +       wh_inode = wh_dentry->d_inode;
25328 +       mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
25329 +
25330 +       /*
25331 +        * someone else might change some whiteouts while we were sleeping.
25332 +        * it means this whlist may have an obsoleted entry.
25333 +        */
25334 +       if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
25335 +               err = del_wh_children(wh_dentry, whlist, bindex, br);
25336 +       else {
25337 +               int wkq_err;
25338 +               struct del_wh_children_args args = {
25339 +                       .errp           = &err,
25340 +                       .h_dentry       = wh_dentry,
25341 +                       .whlist         = whlist,
25342 +                       .bindex         = bindex,
25343 +                       .br             = br
25344 +               };
25345 +
25346 +               wkq_err = au_wkq_wait(call_del_wh_children, &args);
25347 +               if (unlikely(wkq_err))
25348 +                       err = wkq_err;
25349 +       }
25350 +       mutex_unlock(&wh_inode->i_mutex);
25351 +
25352 +       if (!err) {
25353 +               h_tmp.dentry = wh_dentry;
25354 +               h_tmp.mnt = br->br_mnt;
25355 +               err = vfsub_rmdir(h_dir, &h_tmp);
25356 +               /* d_drop(h_dentry); */
25357 +       }
25358 +
25359 +       if (!err) {
25360 +               if (au_ibstart(dir) == bindex) {
25361 +                       au_cpup_attr_timesizes(dir);
25362 +                       drop_nlink(dir);
25363 +               }
25364 +               return 0; /* success */
25365 +       }
25366 +
25367 +       pr_warning("failed removing %.*s(%d), ignored\n",
25368 +                  AuDLNPair(wh_dentry), err);
25369 +       return err;
25370 +}
25371 +
25372 +static void call_rmdir_whtmp(void *args)
25373 +{
25374 +       int err;
25375 +       struct au_whtmp_rmdir *a = args;
25376 +       struct super_block *sb;
25377 +       struct dentry *h_parent;
25378 +       struct inode *h_dir;
25379 +       struct au_branch *br;
25380 +       struct au_hinode *hdir;
25381 +
25382 +       /* rmdir by nfsd may cause deadlock with this i_mutex */
25383 +       /* mutex_lock(&a->dir->i_mutex); */
25384 +       sb = a->dir->i_sb;
25385 +       si_noflush_read_lock(sb);
25386 +       err = au_test_ro(sb, a->bindex, NULL);
25387 +       if (unlikely(err))
25388 +               goto out;
25389 +
25390 +       err = -EIO;
25391 +       br = au_sbr(sb, a->bindex);
25392 +       ii_write_lock_parent(a->dir);
25393 +       h_parent = dget_parent(a->wh_dentry);
25394 +       h_dir = h_parent->d_inode;
25395 +       hdir = au_hi(a->dir, a->bindex);
25396 +       au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
25397 +       err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, br);
25398 +       if (!err) {
25399 +               err = mnt_want_write(br->br_mnt);
25400 +               if (!err) {
25401 +                       err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
25402 +                                            &a->whlist);
25403 +                       mnt_drop_write(br->br_mnt);
25404 +               }
25405 +       }
25406 +       au_hn_imtx_unlock(hdir);
25407 +       dput(h_parent);
25408 +       ii_write_unlock(a->dir);
25409 +
25410 +out:
25411 +       /* mutex_unlock(&a->dir->i_mutex); */
25412 +       au_nwt_done(&au_sbi(sb)->si_nowait);
25413 +       si_read_unlock(sb);
25414 +       au_whtmp_rmdir_free(a);
25415 +       if (unlikely(err))
25416 +               AuIOErr("err %d\n", err);
25417 +}
25418 +
25419 +void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
25420 +                        struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
25421 +{
25422 +       int wkq_err;
25423 +
25424 +       IMustLock(dir);
25425 +
25426 +       /* all post-process will be done in do_rmdir_whtmp(). */
25427 +       args->dir = au_igrab(dir);
25428 +       args->bindex = bindex;
25429 +       args->wh_dentry = dget(wh_dentry);
25430 +       wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
25431 +       if (unlikely(wkq_err)) {
25432 +               pr_warning("rmdir error %.*s (%d), ignored\n",
25433 +                          AuDLNPair(wh_dentry), wkq_err);
25434 +               au_whtmp_rmdir_free(args);
25435 +       }
25436 +}
25437 diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
25438 --- /usr/share/empty/fs/aufs/whout.h    1970-01-01 01:00:00.000000000 +0100
25439 +++ linux/fs/aufs/whout.h       2010-10-21 09:52:43.096959416 +0200
25440 @@ -0,0 +1,87 @@
25441 +/*
25442 + * Copyright (C) 2005-2010 Junjiro R. Okajima
25443 + *
25444 + * This program, aufs is free software; you can redistribute it and/or modify
25445 + * it under the terms of the GNU General Public License as published by
25446 + * the Free Software Foundation; either version 2 of the License, or
25447 + * (at your option) any later version.
25448 + *
25449 + * This program is distributed in the hope that it will be useful,
25450 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
25451 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25452 + * GNU General Public License for more details.
25453 + *
25454 + * You should have received a copy of the GNU General Public License
25455 + * along with this program; if not, write to the Free Software
25456 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
25457 + */
25458 +
25459 +/*
25460 + * whiteout for logical deletion and opaque directory
25461 + */
25462 +
25463 +#ifndef __AUFS_WHOUT_H__
25464 +#define __AUFS_WHOUT_H__
25465 +
25466 +#ifdef __KERNEL__
25467 +
25468 +#include <linux/aufs_type.h>
25469 +#include "dir.h"
25470 +
25471 +/* whout.c */
25472 +int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
25473 +struct au_branch;
25474 +int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
25475 +              struct au_branch *br, int try_sio);
25476 +int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
25477 +struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
25478 +                            struct qstr *prefix);
25479 +int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
25480 +int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
25481 +                       struct dentry *dentry);
25482 +int au_wh_init(struct dentry *h_parent, struct au_branch *br,
25483 +              struct super_block *sb);
25484 +
25485 +/* diropq flags */
25486 +#define AuDiropq_CREATE        1
25487 +#define au_ftest_diropq(flags, name)   ((flags) & AuDiropq_##name)
25488 +#define au_fset_diropq(flags, name)    { (flags) |= AuDiropq_##name; }
25489 +#define au_fclr_diropq(flags, name)    { (flags) &= ~AuDiropq_##name; }
25490 +
25491 +struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
25492 +                            unsigned int flags);
25493 +struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
25494 +                         struct au_branch *br);
25495 +struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
25496 +                           struct dentry *h_parent);
25497 +
25498 +/* real rmdir for the whiteout-ed dir */
25499 +struct au_whtmp_rmdir {
25500 +       struct inode *dir;
25501 +       aufs_bindex_t bindex;
25502 +       struct dentry *wh_dentry;
25503 +       struct au_nhash whlist;
25504 +};
25505 +
25506 +struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
25507 +void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
25508 +int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
25509 +                  struct dentry *wh_dentry, struct au_nhash *whlist);
25510 +void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
25511 +                        struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
25512 +
25513 +/* ---------------------------------------------------------------------- */
25514 +
25515 +static inline struct dentry *au_diropq_create(struct dentry *dentry,
25516 +                                             aufs_bindex_t bindex)
25517 +{
25518 +       return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
25519 +}
25520 +
25521 +static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
25522 +{
25523 +       return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
25524 +}
25525 +
25526 +#endif /* __KERNEL__ */
25527 +#endif /* __AUFS_WHOUT_H__ */
25528 diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
25529 --- /usr/share/empty/fs/aufs/wkq.c      1970-01-01 01:00:00.000000000 +0100
25530 +++ linux/fs/aufs/wkq.c 2010-10-21 09:52:43.096959416 +0200
25531 @@ -0,0 +1,226 @@
25532 +/*
25533 + * Copyright (C) 2005-2010 Junjiro R. Okajima
25534 + *
25535 + * This program, aufs is free software; you can redistribute it and/or modify
25536 + * it under the terms of the GNU General Public License as published by
25537 + * the Free Software Foundation; either version 2 of the License, or
25538 + * (at your option) any later version.
25539 + *
25540 + * This program is distributed in the hope that it will be useful,
25541 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
25542 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25543 + * GNU General Public License for more details.
25544 + *
25545 + * You should have received a copy of the GNU General Public License
25546 + * along with this program; if not, write to the Free Software
25547 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
25548 + */
25549 +
25550 +/*
25551 + * workqueue for asynchronous/super-io operations
25552 + * todo: try new dredential scheme
25553 + */
25554 +
25555 +#include <linux/module.h>
25556 +#include "aufs.h"
25557 +
25558 +/* internal workqueue named AUFS_WKQ_NAME and AUFS_WKQ_PRE_NAME */
25559 +enum {
25560 +       AuWkq_INORMAL,
25561 +       AuWkq_IPRE
25562 +};
25563 +
25564 +static struct {
25565 +       char *name;
25566 +       struct workqueue_struct *wkq;
25567 +} au_wkq[] = {
25568 +       [AuWkq_INORMAL] = {
25569 +               .name = AUFS_WKQ_NAME
25570 +       },
25571 +       [AuWkq_IPRE] = {
25572 +               .name = AUFS_WKQ_PRE_NAME
25573 +       }
25574 +};
25575 +
25576 +struct au_wkinfo {
25577 +       struct work_struct wk;
25578 +       struct super_block *sb;
25579 +
25580 +       unsigned int flags; /* see wkq.h */
25581 +
25582 +       au_wkq_func_t func;
25583 +       void *args;
25584 +
25585 +       struct completion *comp;
25586 +};
25587 +
25588 +/* ---------------------------------------------------------------------- */
25589 +
25590 +static void wkq_func(struct work_struct *wk)
25591 +{
25592 +       struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
25593 +
25594 +       AuDebugOn(current_fsuid());
25595 +       AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
25596 +
25597 +       wkinfo->func(wkinfo->args);
25598 +       if (au_ftest_wkq(wkinfo->flags, WAIT))
25599 +               complete(wkinfo->comp);
25600 +       else {
25601 +               kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
25602 +               module_put(THIS_MODULE);
25603 +               kfree(wkinfo);
25604 +       }
25605 +}
25606 +
25607 +/*
25608 + * Since struct completion is large, try allocating it dynamically.
25609 + */
25610 +#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
25611 +#define AuWkqCompDeclare(name) struct completion *comp = NULL
25612 +
25613 +static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
25614 +{
25615 +       *comp = kmalloc(sizeof(**comp), GFP_NOFS);
25616 +       if (*comp) {
25617 +               init_completion(*comp);
25618 +               wkinfo->comp = *comp;
25619 +               return 0;
25620 +       }
25621 +       return -ENOMEM;
25622 +}
25623 +
25624 +static void au_wkq_comp_free(struct completion *comp)
25625 +{
25626 +       kfree(comp);
25627 +}
25628 +
25629 +#else
25630 +
25631 +/* no braces */
25632 +#define AuWkqCompDeclare(name) \
25633 +       DECLARE_COMPLETION_ONSTACK(_ ## name); \
25634 +       struct completion *comp = &_ ## name
25635 +
25636 +static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
25637 +{
25638 +       wkinfo->comp = *comp;
25639 +       return 0;
25640 +}
25641 +
25642 +static void au_wkq_comp_free(struct completion *comp __maybe_unused)
25643 +{
25644 +       /* empty */
25645 +}
25646 +#endif /* 4KSTACKS */
25647 +
25648 +static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags)
25649 +{
25650 +       struct workqueue_struct *wkq;
25651 +
25652 +       au_dbg_verify_kthread();
25653 +       if (flags & AuWkq_WAIT) {
25654 +               INIT_WORK_ON_STACK(&wkinfo->wk, wkq_func);
25655 +               wkq = au_wkq[AuWkq_INORMAL].wkq;
25656 +               if (flags & AuWkq_PRE)
25657 +                       wkq = au_wkq[AuWkq_IPRE].wkq;
25658 +               queue_work(wkq, &wkinfo->wk);
25659 +       } else {
25660 +               INIT_WORK(&wkinfo->wk, wkq_func);
25661 +               schedule_work(&wkinfo->wk);
25662 +       }
25663 +}
25664 +
25665 +int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
25666 +{
25667 +       int err;
25668 +       AuWkqCompDeclare(comp);
25669 +       struct au_wkinfo wkinfo = {
25670 +               .flags  = flags,
25671 +               .func   = func,
25672 +               .args   = args
25673 +       };
25674 +
25675 +       err = au_wkq_comp_alloc(&wkinfo, &comp);
25676 +       if (!err) {
25677 +               au_wkq_run(&wkinfo, flags);
25678 +               /* no timeout, no interrupt */
25679 +               wait_for_completion(wkinfo.comp);
25680 +               au_wkq_comp_free(comp);
25681 +               destroy_work_on_stack(&wkinfo.wk);
25682 +       }
25683 +
25684 +       return err;
25685 +
25686 +}
25687 +
25688 +int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
25689 +{
25690 +       int err;
25691 +       struct au_wkinfo *wkinfo;
25692 +
25693 +       atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
25694 +
25695 +       /*
25696 +        * wkq_func() must free this wkinfo.
25697 +        * it highly depends upon the implementation of workqueue.
25698 +        */
25699 +       err = 0;
25700 +       wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
25701 +       if (wkinfo) {
25702 +               wkinfo->sb = sb;
25703 +               wkinfo->flags = !AuWkq_WAIT;
25704 +               wkinfo->func = func;
25705 +               wkinfo->args = args;
25706 +               wkinfo->comp = NULL;
25707 +               kobject_get(&au_sbi(sb)->si_kobj);
25708 +               __module_get(THIS_MODULE);
25709 +
25710 +               au_wkq_run(wkinfo, !AuWkq_WAIT);
25711 +       } else {
25712 +               err = -ENOMEM;
25713 +               atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
25714 +       }
25715 +
25716 +       return err;
25717 +}
25718 +
25719 +/* ---------------------------------------------------------------------- */
25720 +
25721 +void au_nwt_init(struct au_nowait_tasks *nwt)
25722 +{
25723 +       atomic_set(&nwt->nw_len, 0);
25724 +       /* smp_mb(); */ /* atomic_set */
25725 +       init_waitqueue_head(&nwt->nw_wq);
25726 +}
25727 +
25728 +void au_wkq_fin(void)
25729 +{
25730 +       int i;
25731 +
25732 +       for (i = 0; i < ARRAY_SIZE(au_wkq); i++)
25733 +               if (au_wkq[i].wkq)
25734 +                       destroy_workqueue(au_wkq[i].wkq);
25735 +}
25736 +
25737 +int __init au_wkq_init(void)
25738 +{
25739 +       int err, i;
25740 +
25741 +       err = 0;
25742 +       for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
25743 +               BUILD_BUG_ON(!WQ_RESCUER);
25744 +               au_wkq[i].wkq = alloc_workqueue(au_wkq[i].name, !WQ_RESCUER,
25745 +                                               WQ_DFL_ACTIVE);
25746 +               if (IS_ERR(au_wkq[i].wkq))
25747 +                       err = PTR_ERR(au_wkq[i].wkq);
25748 +               else if (!au_wkq[i].wkq)
25749 +                       err = -ENOMEM;
25750 +               if (unlikely(err))
25751 +                       au_wkq[i].wkq = NULL;
25752 +       }
25753 +       if (unlikely(err))
25754 +               au_wkq_fin();
25755 +
25756 +       return err;
25757 +}
25758 diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
25759 --- /usr/share/empty/fs/aufs/wkq.h      1970-01-01 01:00:00.000000000 +0100
25760 +++ linux/fs/aufs/wkq.h 2010-10-21 09:52:43.096959416 +0200
25761 @@ -0,0 +1,88 @@
25762 +/*
25763 + * Copyright (C) 2005-2010 Junjiro R. Okajima
25764 + *
25765 + * This program, aufs is free software; you can redistribute it and/or modify
25766 + * it under the terms of the GNU General Public License as published by
25767 + * the Free Software Foundation; either version 2 of the License, or
25768 + * (at your option) any later version.
25769 + *
25770 + * This program is distributed in the hope that it will be useful,
25771 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
25772 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25773 + * GNU General Public License for more details.
25774 + *
25775 + * You should have received a copy of the GNU General Public License
25776 + * along with this program; if not, write to the Free Software
25777 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
25778 + */
25779 +
25780 +/*
25781 + * workqueue for asynchronous/super-io operations
25782 + * todo: try new credentials management scheme
25783 + */
25784 +
25785 +#ifndef __AUFS_WKQ_H__
25786 +#define __AUFS_WKQ_H__
25787 +
25788 +#ifdef __KERNEL__
25789 +
25790 +#include <linux/sched.h>
25791 +#include <linux/wait.h>
25792 +#include <linux/aufs_type.h>
25793 +
25794 +struct super_block;
25795 +
25796 +/* ---------------------------------------------------------------------- */
25797 +
25798 +/*
25799 + * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
25800 + */
25801 +struct au_nowait_tasks {
25802 +       atomic_t                nw_len;
25803 +       wait_queue_head_t       nw_wq;
25804 +};
25805 +
25806 +/* ---------------------------------------------------------------------- */
25807 +
25808 +typedef void (*au_wkq_func_t)(void *args);
25809 +
25810 +/* wkq flags */
25811 +#define AuWkq_WAIT     1
25812 +#define AuWkq_PRE      (1 << 1)
25813 +#define au_ftest_wkq(flags, name)      ((flags) & AuWkq_##name)
25814 +#define au_fset_wkq(flags, name)       { (flags) |= AuWkq_##name; }
25815 +#define au_fclr_wkq(flags, name)       { (flags) &= ~AuWkq_##name; }
25816 +
25817 +/* wkq.c */
25818 +int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
25819 +int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
25820 +void au_nwt_init(struct au_nowait_tasks *nwt);
25821 +int __init au_wkq_init(void);
25822 +void au_wkq_fin(void);
25823 +
25824 +/* ---------------------------------------------------------------------- */
25825 +
25826 +static inline int au_wkq_wait_pre(au_wkq_func_t func, void *args)
25827 +{
25828 +       return au_wkq_do_wait(AuWkq_WAIT | AuWkq_PRE, func, args);
25829 +}
25830 +
25831 +static inline int au_wkq_wait(au_wkq_func_t func, void *args)
25832 +{
25833 +       return au_wkq_do_wait(AuWkq_WAIT, func, args);
25834 +}
25835 +
25836 +static inline void au_nwt_done(struct au_nowait_tasks *nwt)
25837 +{
25838 +       if (!atomic_dec_return(&nwt->nw_len))
25839 +               wake_up_all(&nwt->nw_wq);
25840 +}
25841 +
25842 +static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
25843 +{
25844 +       wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
25845 +       return 0;
25846 +}
25847 +
25848 +#endif /* __KERNEL__ */
25849 +#endif /* __AUFS_WKQ_H__ */
25850 diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
25851 --- /usr/share/empty/fs/aufs/xino.c     1970-01-01 01:00:00.000000000 +0100
25852 +++ linux/fs/aufs/xino.c        2010-10-21 09:52:43.096959416 +0200
25853 @@ -0,0 +1,1263 @@
25854 +/*
25855 + * Copyright (C) 2005-2010 Junjiro R. Okajima
25856 + *
25857 + * This program, aufs is free software; you can redistribute it and/or modify
25858 + * it under the terms of the GNU General Public License as published by
25859 + * the Free Software Foundation; either version 2 of the License, or
25860 + * (at your option) any later version.
25861 + *
25862 + * This program is distributed in the hope that it will be useful,
25863 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
25864 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25865 + * GNU General Public License for more details.
25866 + *
25867 + * You should have received a copy of the GNU General Public License
25868 + * along with this program; if not, write to the Free Software
25869 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
25870 + */
25871 +
25872 +/*
25873 + * external inode number translation table and bitmap
25874 + */
25875 +
25876 +#include <linux/file.h>
25877 +#include <linux/seq_file.h>
25878 +#include <linux/uaccess.h>
25879 +#include "aufs.h"
25880 +
25881 +ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
25882 +                  loff_t *pos)
25883 +{
25884 +       ssize_t err;
25885 +       mm_segment_t oldfs;
25886 +       union {
25887 +               void *k;
25888 +               char __user *u;
25889 +       } buf;
25890 +
25891 +       buf.k = kbuf;
25892 +       oldfs = get_fs();
25893 +       set_fs(KERNEL_DS);
25894 +       do {
25895 +               /* todo: signal_pending? */
25896 +               err = func(file, buf.u, size, pos);
25897 +       } while (err == -EAGAIN || err == -EINTR);
25898 +       set_fs(oldfs);
25899 +
25900 +#if 0 /* reserved for future use */
25901 +       if (err > 0)
25902 +               fsnotify_access(file->f_dentry);
25903 +#endif
25904 +
25905 +       return err;
25906 +}
25907 +
25908 +/* ---------------------------------------------------------------------- */
25909 +
25910 +static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
25911 +                             size_t size, loff_t *pos)
25912 +{
25913 +       ssize_t err;
25914 +       mm_segment_t oldfs;
25915 +       union {
25916 +               void *k;
25917 +               const char __user *u;
25918 +       } buf;
25919 +
25920 +       buf.k = kbuf;
25921 +       oldfs = get_fs();
25922 +       set_fs(KERNEL_DS);
25923 +       do {
25924 +               /* todo: signal_pending? */
25925 +               err = func(file, buf.u, size, pos);
25926 +       } while (err == -EAGAIN || err == -EINTR);
25927 +       set_fs(oldfs);
25928 +
25929 +#if 0 /* reserved for future use */
25930 +       if (err > 0)
25931 +               fsnotify_modify(file->f_dentry);
25932 +#endif
25933 +
25934 +       return err;
25935 +}
25936 +
25937 +struct do_xino_fwrite_args {
25938 +       ssize_t *errp;
25939 +       au_writef_t func;
25940 +       struct file *file;
25941 +       void *buf;
25942 +       size_t size;
25943 +       loff_t *pos;
25944 +};
25945 +
25946 +static void call_do_xino_fwrite(void *args)
25947 +{
25948 +       struct do_xino_fwrite_args *a = args;
25949 +       *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
25950 +}
25951 +
25952 +ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
25953 +                   loff_t *pos)
25954 +{
25955 +       ssize_t err;
25956 +
25957 +       /* todo: signal block and no wkq? */
25958 +       if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
25959 +               lockdep_off();
25960 +               err = do_xino_fwrite(func, file, buf, size, pos);
25961 +               lockdep_on();
25962 +       } else {
25963 +               /*
25964 +                * it breaks RLIMIT_FSIZE and normal user's limit,
25965 +                * users should care about quota and real 'filesystem full.'
25966 +                */
25967 +               int wkq_err;
25968 +               struct do_xino_fwrite_args args = {
25969 +                       .errp   = &err,
25970 +                       .func   = func,
25971 +                       .file   = file,
25972 +                       .buf    = buf,
25973 +                       .size   = size,
25974 +                       .pos    = pos
25975 +               };
25976 +
25977 +               wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
25978 +               if (unlikely(wkq_err))
25979 +                       err = wkq_err;
25980 +       }
25981 +
25982 +       return err;
25983 +}
25984 +
25985 +/* ---------------------------------------------------------------------- */
25986 +
25987 +/*
25988 + * create a new xinofile at the same place/path as @base_file.
25989 + */
25990 +struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
25991 +{
25992 +       struct file *file;
25993 +       struct dentry *base, *parent;
25994 +       struct inode *dir;
25995 +       struct qstr *name;
25996 +       struct path path;
25997 +       int err;
25998 +
25999 +       base = base_file->f_dentry;
26000 +       parent = base->d_parent; /* dir inode is locked */
26001 +       dir = parent->d_inode;
26002 +       IMustLock(dir);
26003 +
26004 +       file = ERR_PTR(-EINVAL);
26005 +       name = &base->d_name;
26006 +       path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
26007 +       if (IS_ERR(path.dentry)) {
26008 +               file = (void *)path.dentry;
26009 +               pr_err("%.*s lookup err %ld\n",
26010 +                      AuLNPair(name), PTR_ERR(path.dentry));
26011 +               goto out;
26012 +       }
26013 +
26014 +       /* no need to mnt_want_write() since we call dentry_open() later */
26015 +       err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
26016 +       if (unlikely(err)) {
26017 +               file = ERR_PTR(err);
26018 +               pr_err("%.*s create err %d\n", AuLNPair(name), err);
26019 +               goto out_dput;
26020 +       }
26021 +
26022 +       path.mnt = base_file->f_vfsmnt;
26023 +       file = vfsub_dentry_open(&path,
26024 +                                O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
26025 +       if (IS_ERR(file)) {
26026 +               pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
26027 +               goto out_dput;
26028 +       }
26029 +
26030 +       err = vfsub_unlink(dir, &file->f_path, /*force*/0);
26031 +       if (unlikely(err)) {
26032 +               pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
26033 +               goto out_fput;
26034 +       }
26035 +
26036 +       if (copy_src) {
26037 +               /* no one can touch copy_src xino */
26038 +               err = au_copy_file(file, copy_src,
26039 +                                  i_size_read(copy_src->f_dentry->d_inode));
26040 +               if (unlikely(err)) {
26041 +                       pr_err("%.*s copy err %d\n", AuLNPair(name), err);
26042 +                       goto out_fput;
26043 +               }
26044 +       }
26045 +       goto out_dput; /* success */
26046 +
26047 +out_fput:
26048 +       fput(file);
26049 +       file = ERR_PTR(err);
26050 +out_dput:
26051 +       dput(path.dentry);
26052 +out:
26053 +       return file;
26054 +}
26055 +
26056 +struct au_xino_lock_dir {
26057 +       struct au_hinode *hdir;
26058 +       struct dentry *parent;
26059 +       struct mutex *mtx;
26060 +};
26061 +
26062 +static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
26063 +                            struct au_xino_lock_dir *ldir)
26064 +{
26065 +       aufs_bindex_t brid, bindex;
26066 +
26067 +       ldir->hdir = NULL;
26068 +       bindex = -1;
26069 +       brid = au_xino_brid(sb);
26070 +       if (brid >= 0)
26071 +               bindex = au_br_index(sb, brid);
26072 +       if (bindex >= 0) {
26073 +               ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
26074 +               au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
26075 +       } else {
26076 +               ldir->parent = dget_parent(xino->f_dentry);
26077 +               ldir->mtx = &ldir->parent->d_inode->i_mutex;
26078 +               mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
26079 +       }
26080 +}
26081 +
26082 +static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
26083 +{
26084 +       if (ldir->hdir)
26085 +               au_hn_imtx_unlock(ldir->hdir);
26086 +       else {
26087 +               mutex_unlock(ldir->mtx);
26088 +               dput(ldir->parent);
26089 +       }
26090 +}
26091 +
26092 +/* ---------------------------------------------------------------------- */
26093 +
26094 +/* trucate xino files asynchronously */
26095 +
26096 +int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
26097 +{
26098 +       int err;
26099 +       aufs_bindex_t bi, bend;
26100 +       struct au_branch *br;
26101 +       struct file *new_xino, *file;
26102 +       struct super_block *h_sb;
26103 +       struct au_xino_lock_dir ldir;
26104 +
26105 +       err = -EINVAL;
26106 +       bend = au_sbend(sb);
26107 +       if (unlikely(bindex < 0 || bend < bindex))
26108 +               goto out;
26109 +       br = au_sbr(sb, bindex);
26110 +       file = br->br_xino.xi_file;
26111 +       if (!file)
26112 +               goto out;
26113 +
26114 +       au_xino_lock_dir(sb, file, &ldir);
26115 +       /* mnt_want_write() is unnecessary here */
26116 +       new_xino = au_xino_create2(file, file);
26117 +       au_xino_unlock_dir(&ldir);
26118 +       err = PTR_ERR(new_xino);
26119 +       if (IS_ERR(new_xino))
26120 +               goto out;
26121 +       err = 0;
26122 +       fput(file);
26123 +       br->br_xino.xi_file = new_xino;
26124 +
26125 +       h_sb = br->br_mnt->mnt_sb;
26126 +       for (bi = 0; bi <= bend; bi++) {
26127 +               if (unlikely(bi == bindex))
26128 +                       continue;
26129 +               br = au_sbr(sb, bi);
26130 +               if (br->br_mnt->mnt_sb != h_sb)
26131 +                       continue;
26132 +
26133 +               fput(br->br_xino.xi_file);
26134 +               br->br_xino.xi_file = new_xino;
26135 +               get_file(new_xino);
26136 +       }
26137 +
26138 +out:
26139 +       return err;
26140 +}
26141 +
26142 +struct xino_do_trunc_args {
26143 +       struct super_block *sb;
26144 +       struct au_branch *br;
26145 +};
26146 +
26147 +static void xino_do_trunc(void *_args)
26148 +{
26149 +       struct xino_do_trunc_args *args = _args;
26150 +       struct super_block *sb;
26151 +       struct au_branch *br;
26152 +       struct inode *dir;
26153 +       int err;
26154 +       aufs_bindex_t bindex;
26155 +
26156 +       err = 0;
26157 +       sb = args->sb;
26158 +       dir = sb->s_root->d_inode;
26159 +       br = args->br;
26160 +
26161 +       si_noflush_write_lock(sb);
26162 +       ii_read_lock_parent(dir);
26163 +       bindex = au_br_index(sb, br->br_id);
26164 +       err = au_xino_trunc(sb, bindex);
26165 +       if (!err
26166 +           && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
26167 +           >= br->br_xino_upper)
26168 +               br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
26169 +
26170 +       ii_read_unlock(dir);
26171 +       if (unlikely(err))
26172 +               pr_warning("err b%d, (%d)\n", bindex, err);
26173 +       atomic_dec(&br->br_xino_running);
26174 +       atomic_dec(&br->br_count);
26175 +       au_nwt_done(&au_sbi(sb)->si_nowait);
26176 +       si_write_unlock(sb);
26177 +       kfree(args);
26178 +}
26179 +
26180 +static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
26181 +{
26182 +       struct xino_do_trunc_args *args;
26183 +       int wkq_err;
26184 +
26185 +       if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
26186 +           < br->br_xino_upper)
26187 +               return;
26188 +
26189 +       if (atomic_inc_return(&br->br_xino_running) > 1)
26190 +               goto out;
26191 +
26192 +       /* lock and kfree() will be called in trunc_xino() */
26193 +       args = kmalloc(sizeof(*args), GFP_NOFS);
26194 +       if (unlikely(!args)) {
26195 +               AuErr1("no memory\n");
26196 +               goto out_args;
26197 +       }
26198 +
26199 +       atomic_inc_return(&br->br_count);
26200 +       args->sb = sb;
26201 +       args->br = br;
26202 +       wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
26203 +       if (!wkq_err)
26204 +               return; /* success */
26205 +
26206 +       pr_err("wkq %d\n", wkq_err);
26207 +       atomic_dec_return(&br->br_count);
26208 +
26209 +out_args:
26210 +       kfree(args);
26211 +out:
26212 +       atomic_dec_return(&br->br_xino_running);
26213 +}
26214 +
26215 +/* ---------------------------------------------------------------------- */
26216 +
26217 +static int au_xino_do_write(au_writef_t write, struct file *file,
26218 +                           ino_t h_ino, ino_t ino)
26219 +{
26220 +       loff_t pos;
26221 +       ssize_t sz;
26222 +
26223 +       pos = h_ino;
26224 +       if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
26225 +               AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
26226 +               return -EFBIG;
26227 +       }
26228 +       pos *= sizeof(ino);
26229 +       sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
26230 +       if (sz == sizeof(ino))
26231 +               return 0; /* success */
26232 +
26233 +       AuIOErr("write failed (%zd)\n", sz);
26234 +       return -EIO;
26235 +}
26236 +
26237 +/*
26238 + * write @ino to the xinofile for the specified branch{@sb, @bindex}
26239 + * at the position of @h_ino.
26240 + * even if @ino is zero, it is written to the xinofile and means no entry.
26241 + * if the size of the xino file on a specific filesystem exceeds the watermark,
26242 + * try truncating it.
26243 + */
26244 +int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
26245 +                 ino_t ino)
26246 +{
26247 +       int err;
26248 +       unsigned int mnt_flags;
26249 +       struct au_branch *br;
26250 +
26251 +       BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
26252 +                    || ((loff_t)-1) > 0);
26253 +       SiMustAnyLock(sb);
26254 +
26255 +       mnt_flags = au_mntflags(sb);
26256 +       if (!au_opt_test(mnt_flags, XINO))
26257 +               return 0;
26258 +
26259 +       br = au_sbr(sb, bindex);
26260 +       err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
26261 +                              h_ino, ino);
26262 +       if (!err) {
26263 +               if (au_opt_test(mnt_flags, TRUNC_XINO)
26264 +                   && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
26265 +                       xino_try_trunc(sb, br);
26266 +               return 0; /* success */
26267 +       }
26268 +
26269 +       AuIOErr("write failed (%d)\n", err);
26270 +       return -EIO;
26271 +}
26272 +
26273 +/* ---------------------------------------------------------------------- */
26274 +
26275 +/* aufs inode number bitmap */
26276 +
26277 +static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
26278 +static ino_t xib_calc_ino(unsigned long pindex, int bit)
26279 +{
26280 +       ino_t ino;
26281 +
26282 +       AuDebugOn(bit < 0 || page_bits <= bit);
26283 +       ino = AUFS_FIRST_INO + pindex * page_bits + bit;
26284 +       return ino;
26285 +}
26286 +
26287 +static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
26288 +{
26289 +       AuDebugOn(ino < AUFS_FIRST_INO);
26290 +       ino -= AUFS_FIRST_INO;
26291 +       *pindex = ino / page_bits;
26292 +       *bit = ino % page_bits;
26293 +}
26294 +
26295 +static int xib_pindex(struct super_block *sb, unsigned long pindex)
26296 +{
26297 +       int err;
26298 +       loff_t pos;
26299 +       ssize_t sz;
26300 +       struct au_sbinfo *sbinfo;
26301 +       struct file *xib;
26302 +       unsigned long *p;
26303 +
26304 +       sbinfo = au_sbi(sb);
26305 +       MtxMustLock(&sbinfo->si_xib_mtx);
26306 +       AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
26307 +                 || !au_opt_test(sbinfo->si_mntflags, XINO));
26308 +
26309 +       if (pindex == sbinfo->si_xib_last_pindex)
26310 +               return 0;
26311 +
26312 +       xib = sbinfo->si_xib;
26313 +       p = sbinfo->si_xib_buf;
26314 +       pos = sbinfo->si_xib_last_pindex;
26315 +       pos *= PAGE_SIZE;
26316 +       sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
26317 +       if (unlikely(sz != PAGE_SIZE))
26318 +               goto out;
26319 +
26320 +       pos = pindex;
26321 +       pos *= PAGE_SIZE;
26322 +       if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
26323 +               sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
26324 +       else {
26325 +               memset(p, 0, PAGE_SIZE);
26326 +               sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
26327 +       }
26328 +       if (sz == PAGE_SIZE) {
26329 +               sbinfo->si_xib_last_pindex = pindex;
26330 +               return 0; /* success */
26331 +       }
26332 +
26333 +out:
26334 +       AuIOErr1("write failed (%zd)\n", sz);
26335 +       err = sz;
26336 +       if (sz >= 0)
26337 +               err = -EIO;
26338 +       return err;
26339 +}
26340 +
26341 +/* ---------------------------------------------------------------------- */
26342 +
26343 +static void au_xib_clear_bit(struct inode *inode)
26344 +{
26345 +       int err, bit;
26346 +       unsigned long pindex;
26347 +       struct super_block *sb;
26348 +       struct au_sbinfo *sbinfo;
26349 +
26350 +       AuDebugOn(inode->i_nlink);
26351 +
26352 +       sb = inode->i_sb;
26353 +       xib_calc_bit(inode->i_ino, &pindex, &bit);
26354 +       AuDebugOn(page_bits <= bit);
26355 +       sbinfo = au_sbi(sb);
26356 +       mutex_lock(&sbinfo->si_xib_mtx);
26357 +       err = xib_pindex(sb, pindex);
26358 +       if (!err) {
26359 +               clear_bit(bit, sbinfo->si_xib_buf);
26360 +               sbinfo->si_xib_next_bit = bit;
26361 +       }
26362 +       mutex_unlock(&sbinfo->si_xib_mtx);
26363 +}
26364 +
26365 +/* for s_op->delete_inode() */
26366 +void au_xino_delete_inode(struct inode *inode, const int unlinked)
26367 +{
26368 +       int err;
26369 +       unsigned int mnt_flags;
26370 +       aufs_bindex_t bindex, bend, bi;
26371 +       unsigned char try_trunc;
26372 +       struct au_iinfo *iinfo;
26373 +       struct super_block *sb;
26374 +       struct au_hinode *hi;
26375 +       struct inode *h_inode;
26376 +       struct au_branch *br;
26377 +       au_writef_t xwrite;
26378 +
26379 +       sb = inode->i_sb;
26380 +       mnt_flags = au_mntflags(sb);
26381 +       if (!au_opt_test(mnt_flags, XINO)
26382 +           || inode->i_ino == AUFS_ROOT_INO)
26383 +               return;
26384 +
26385 +       if (unlinked) {
26386 +               au_xigen_inc(inode);
26387 +               au_xib_clear_bit(inode);
26388 +       }
26389 +
26390 +       iinfo = au_ii(inode);
26391 +       if (!iinfo)
26392 +               return;
26393 +
26394 +       bindex = iinfo->ii_bstart;
26395 +       if (bindex < 0)
26396 +               return;
26397 +
26398 +       xwrite = au_sbi(sb)->si_xwrite;
26399 +       try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
26400 +       hi = iinfo->ii_hinode + bindex;
26401 +       bend = iinfo->ii_bend;
26402 +       for (; bindex <= bend; bindex++, hi++) {
26403 +               h_inode = hi->hi_inode;
26404 +               if (!h_inode
26405 +                   || (!unlinked && h_inode->i_nlink))
26406 +                       continue;
26407 +
26408 +               /* inode may not be revalidated */
26409 +               bi = au_br_index(sb, hi->hi_id);
26410 +               if (bi < 0)
26411 +                       continue;
26412 +
26413 +               br = au_sbr(sb, bi);
26414 +               err = au_xino_do_write(xwrite, br->br_xino.xi_file,
26415 +                                      h_inode->i_ino, /*ino*/0);
26416 +               if (!err && try_trunc
26417 +                   && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
26418 +                       xino_try_trunc(sb, br);
26419 +       }
26420 +}
26421 +
26422 +/* get an unused inode number from bitmap */
26423 +ino_t au_xino_new_ino(struct super_block *sb)
26424 +{
26425 +       ino_t ino;
26426 +       unsigned long *p, pindex, ul, pend;
26427 +       struct au_sbinfo *sbinfo;
26428 +       struct file *file;
26429 +       int free_bit, err;
26430 +
26431 +       if (!au_opt_test(au_mntflags(sb), XINO))
26432 +               return iunique(sb, AUFS_FIRST_INO);
26433 +
26434 +       sbinfo = au_sbi(sb);
26435 +       mutex_lock(&sbinfo->si_xib_mtx);
26436 +       p = sbinfo->si_xib_buf;
26437 +       free_bit = sbinfo->si_xib_next_bit;
26438 +       if (free_bit < page_bits && !test_bit(free_bit, p))
26439 +               goto out; /* success */
26440 +       free_bit = find_first_zero_bit(p, page_bits);
26441 +       if (free_bit < page_bits)
26442 +               goto out; /* success */
26443 +
26444 +       pindex = sbinfo->si_xib_last_pindex;
26445 +       for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
26446 +               err = xib_pindex(sb, ul);
26447 +               if (unlikely(err))
26448 +                       goto out_err;
26449 +               free_bit = find_first_zero_bit(p, page_bits);
26450 +               if (free_bit < page_bits)
26451 +                       goto out; /* success */
26452 +       }
26453 +
26454 +       file = sbinfo->si_xib;
26455 +       pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
26456 +       for (ul = pindex + 1; ul <= pend; ul++) {
26457 +               err = xib_pindex(sb, ul);
26458 +               if (unlikely(err))
26459 +                       goto out_err;
26460 +               free_bit = find_first_zero_bit(p, page_bits);
26461 +               if (free_bit < page_bits)
26462 +                       goto out; /* success */
26463 +       }
26464 +       BUG();
26465 +
26466 +out:
26467 +       set_bit(free_bit, p);
26468 +       sbinfo->si_xib_next_bit++;
26469 +       pindex = sbinfo->si_xib_last_pindex;
26470 +       mutex_unlock(&sbinfo->si_xib_mtx);
26471 +       ino = xib_calc_ino(pindex, free_bit);
26472 +       AuDbg("i%lu\n", (unsigned long)ino);
26473 +       return ino;
26474 +out_err:
26475 +       mutex_unlock(&sbinfo->si_xib_mtx);
26476 +       AuDbg("i0\n");
26477 +       return 0;
26478 +}
26479 +
26480 +/*
26481 + * read @ino from xinofile for the specified branch{@sb, @bindex}
26482 + * at the position of @h_ino.
26483 + * if @ino does not exist and @do_new is true, get new one.
26484 + */
26485 +int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
26486 +                ino_t *ino)
26487 +{
26488 +       int err;
26489 +       ssize_t sz;
26490 +       loff_t pos;
26491 +       struct file *file;
26492 +       struct au_sbinfo *sbinfo;
26493 +
26494 +       *ino = 0;
26495 +       if (!au_opt_test(au_mntflags(sb), XINO))
26496 +               return 0; /* no xino */
26497 +
26498 +       err = 0;
26499 +       sbinfo = au_sbi(sb);
26500 +       pos = h_ino;
26501 +       if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
26502 +               AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
26503 +               return -EFBIG;
26504 +       }
26505 +       pos *= sizeof(*ino);
26506 +
26507 +       file = au_sbr(sb, bindex)->br_xino.xi_file;
26508 +       if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
26509 +               return 0; /* no ino */
26510 +
26511 +       sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
26512 +       if (sz == sizeof(*ino))
26513 +               return 0; /* success */
26514 +
26515 +       err = sz;
26516 +       if (unlikely(sz >= 0)) {
26517 +               err = -EIO;
26518 +               AuIOErr("xino read error (%zd)\n", sz);
26519 +       }
26520 +
26521 +       return err;
26522 +}
26523 +
26524 +/* ---------------------------------------------------------------------- */
26525 +
26526 +/* create and set a new xino file */
26527 +
26528 +struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
26529 +{
26530 +       struct file *file;
26531 +       struct dentry *h_parent, *d;
26532 +       struct inode *h_dir;
26533 +       int err;
26534 +
26535 +       /*
26536 +        * at mount-time, and the xino file is the default path,
26537 +        * hnotify is disabled so we have no notify events to ignore.
26538 +        * when a user specified the xino, we cannot get au_hdir to be ignored.
26539 +        */
26540 +       file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
26541 +                              S_IRUGO | S_IWUGO);
26542 +       if (IS_ERR(file)) {
26543 +               if (!silent)
26544 +                       pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
26545 +               return file;
26546 +       }
26547 +
26548 +       /* keep file count */
26549 +       h_parent = dget_parent(file->f_dentry);
26550 +       h_dir = h_parent->d_inode;
26551 +       mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
26552 +       /* mnt_want_write() is unnecessary here */
26553 +       err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
26554 +       mutex_unlock(&h_dir->i_mutex);
26555 +       dput(h_parent);
26556 +       if (unlikely(err)) {
26557 +               if (!silent)
26558 +                       pr_err("unlink %s(%d)\n", fname, err);
26559 +               goto out;
26560 +       }
26561 +
26562 +       err = -EINVAL;
26563 +       d = file->f_dentry;
26564 +       if (unlikely(sb == d->d_sb)) {
26565 +               if (!silent)
26566 +                       pr_err("%s must be outside\n", fname);
26567 +               goto out;
26568 +       }
26569 +       if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
26570 +               if (!silent)
26571 +                       pr_err("xino doesn't support %s(%s)\n",
26572 +                              fname, au_sbtype(d->d_sb));
26573 +               goto out;
26574 +       }
26575 +       return file; /* success */
26576 +
26577 +out:
26578 +       fput(file);
26579 +       file = ERR_PTR(err);
26580 +       return file;
26581 +}
26582 +
26583 +/*
26584 + * find another branch who is on the same filesystem of the specified
26585 + * branch{@btgt}. search until @bend.
26586 + */
26587 +static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
26588 +                       aufs_bindex_t bend)
26589 +{
26590 +       aufs_bindex_t bindex;
26591 +       struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
26592 +
26593 +       for (bindex = 0; bindex < btgt; bindex++)
26594 +               if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
26595 +                       return bindex;
26596 +       for (bindex++; bindex <= bend; bindex++)
26597 +               if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
26598 +                       return bindex;
26599 +       return -1;
26600 +}
26601 +
26602 +/* ---------------------------------------------------------------------- */
26603 +
26604 +/*
26605 + * initialize the xinofile for the specified branch @br
26606 + * at the place/path where @base_file indicates.
26607 + * test whether another branch is on the same filesystem or not,
26608 + * if @do_test is true.
26609 + */
26610 +int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
26611 +              struct file *base_file, int do_test)
26612 +{
26613 +       int err;
26614 +       ino_t ino;
26615 +       aufs_bindex_t bend, bindex;
26616 +       struct au_branch *shared_br, *b;
26617 +       struct file *file;
26618 +       struct super_block *tgt_sb;
26619 +
26620 +       shared_br = NULL;
26621 +       bend = au_sbend(sb);
26622 +       if (do_test) {
26623 +               tgt_sb = br->br_mnt->mnt_sb;
26624 +               for (bindex = 0; bindex <= bend; bindex++) {
26625 +                       b = au_sbr(sb, bindex);
26626 +                       if (tgt_sb == b->br_mnt->mnt_sb) {
26627 +                               shared_br = b;
26628 +                               break;
26629 +                       }
26630 +               }
26631 +       }
26632 +
26633 +       if (!shared_br || !shared_br->br_xino.xi_file) {
26634 +               struct au_xino_lock_dir ldir;
26635 +
26636 +               au_xino_lock_dir(sb, base_file, &ldir);
26637 +               /* mnt_want_write() is unnecessary here */
26638 +               file = au_xino_create2(base_file, NULL);
26639 +               au_xino_unlock_dir(&ldir);
26640 +               err = PTR_ERR(file);
26641 +               if (IS_ERR(file))
26642 +                       goto out;
26643 +               br->br_xino.xi_file = file;
26644 +       } else {
26645 +               br->br_xino.xi_file = shared_br->br_xino.xi_file;
26646 +               get_file(br->br_xino.xi_file);
26647 +       }
26648 +
26649 +       ino = AUFS_ROOT_INO;
26650 +       err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
26651 +                              h_ino, ino);
26652 +       if (unlikely(err)) {
26653 +               fput(br->br_xino.xi_file);
26654 +               br->br_xino.xi_file = NULL;
26655 +       }
26656 +
26657 +out:
26658 +       return err;
26659 +}
26660 +
26661 +/* ---------------------------------------------------------------------- */
26662 +
26663 +/* trucate a xino bitmap file */
26664 +
26665 +/* todo: slow */
26666 +static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
26667 +{
26668 +       int err, bit;
26669 +       ssize_t sz;
26670 +       unsigned long pindex;
26671 +       loff_t pos, pend;
26672 +       struct au_sbinfo *sbinfo;
26673 +       au_readf_t func;
26674 +       ino_t *ino;
26675 +       unsigned long *p;
26676 +
26677 +       err = 0;
26678 +       sbinfo = au_sbi(sb);
26679 +       MtxMustLock(&sbinfo->si_xib_mtx);
26680 +       p = sbinfo->si_xib_buf;
26681 +       func = sbinfo->si_xread;
26682 +       pend = i_size_read(file->f_dentry->d_inode);
26683 +       pos = 0;
26684 +       while (pos < pend) {
26685 +               sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
26686 +               err = sz;
26687 +               if (unlikely(sz <= 0))
26688 +                       goto out;
26689 +
26690 +               err = 0;
26691 +               for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
26692 +                       if (unlikely(*ino < AUFS_FIRST_INO))
26693 +                               continue;
26694 +
26695 +                       xib_calc_bit(*ino, &pindex, &bit);
26696 +                       AuDebugOn(page_bits <= bit);
26697 +                       err = xib_pindex(sb, pindex);
26698 +                       if (!err)
26699 +                               set_bit(bit, p);
26700 +                       else
26701 +                               goto out;
26702 +               }
26703 +       }
26704 +
26705 +out:
26706 +       return err;
26707 +}
26708 +
26709 +static int xib_restore(struct super_block *sb)
26710 +{
26711 +       int err;
26712 +       aufs_bindex_t bindex, bend;
26713 +       void *page;
26714 +
26715 +       err = -ENOMEM;
26716 +       page = (void *)__get_free_page(GFP_NOFS);
26717 +       if (unlikely(!page))
26718 +               goto out;
26719 +
26720 +       err = 0;
26721 +       bend = au_sbend(sb);
26722 +       for (bindex = 0; !err && bindex <= bend; bindex++)
26723 +               if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
26724 +                       err = do_xib_restore
26725 +                               (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
26726 +               else
26727 +                       AuDbg("b%d\n", bindex);
26728 +       free_page((unsigned long)page);
26729 +
26730 +out:
26731 +       return err;
26732 +}
26733 +
26734 +int au_xib_trunc(struct super_block *sb)
26735 +{
26736 +       int err;
26737 +       ssize_t sz;
26738 +       loff_t pos;
26739 +       struct au_xino_lock_dir ldir;
26740 +       struct au_sbinfo *sbinfo;
26741 +       unsigned long *p;
26742 +       struct file *file;
26743 +
26744 +       SiMustWriteLock(sb);
26745 +
26746 +       err = 0;
26747 +       sbinfo = au_sbi(sb);
26748 +       if (!au_opt_test(sbinfo->si_mntflags, XINO))
26749 +               goto out;
26750 +
26751 +       file = sbinfo->si_xib;
26752 +       if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
26753 +               goto out;
26754 +
26755 +       au_xino_lock_dir(sb, file, &ldir);
26756 +       /* mnt_want_write() is unnecessary here */
26757 +       file = au_xino_create2(sbinfo->si_xib, NULL);
26758 +       au_xino_unlock_dir(&ldir);
26759 +       err = PTR_ERR(file);
26760 +       if (IS_ERR(file))
26761 +               goto out;
26762 +       fput(sbinfo->si_xib);
26763 +       sbinfo->si_xib = file;
26764 +
26765 +       p = sbinfo->si_xib_buf;
26766 +       memset(p, 0, PAGE_SIZE);
26767 +       pos = 0;
26768 +       sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
26769 +       if (unlikely(sz != PAGE_SIZE)) {
26770 +               err = sz;
26771 +               AuIOErr("err %d\n", err);
26772 +               if (sz >= 0)
26773 +                       err = -EIO;
26774 +               goto out;
26775 +       }
26776 +
26777 +       mutex_lock(&sbinfo->si_xib_mtx);
26778 +       /* mnt_want_write() is unnecessary here */
26779 +       err = xib_restore(sb);
26780 +       mutex_unlock(&sbinfo->si_xib_mtx);
26781 +
26782 +out:
26783 +       return err;
26784 +}
26785 +
26786 +/* ---------------------------------------------------------------------- */
26787 +
26788 +/*
26789 + * xino mount option handlers
26790 + */
26791 +static au_readf_t find_readf(struct file *h_file)
26792 +{
26793 +       const struct file_operations *fop = h_file->f_op;
26794 +
26795 +       if (fop) {
26796 +               if (fop->read)
26797 +                       return fop->read;
26798 +               if (fop->aio_read)
26799 +                       return do_sync_read;
26800 +       }
26801 +       return ERR_PTR(-ENOSYS);
26802 +}
26803 +
26804 +static au_writef_t find_writef(struct file *h_file)
26805 +{
26806 +       const struct file_operations *fop = h_file->f_op;
26807 +
26808 +       if (fop) {
26809 +               if (fop->write)
26810 +                       return fop->write;
26811 +               if (fop->aio_write)
26812 +                       return do_sync_write;
26813 +       }
26814 +       return ERR_PTR(-ENOSYS);
26815 +}
26816 +
26817 +/* xino bitmap */
26818 +static void xino_clear_xib(struct super_block *sb)
26819 +{
26820 +       struct au_sbinfo *sbinfo;
26821 +
26822 +       SiMustWriteLock(sb);
26823 +
26824 +       sbinfo = au_sbi(sb);
26825 +       sbinfo->si_xread = NULL;
26826 +       sbinfo->si_xwrite = NULL;
26827 +       if (sbinfo->si_xib)
26828 +               fput(sbinfo->si_xib);
26829 +       sbinfo->si_xib = NULL;
26830 +       free_page((unsigned long)sbinfo->si_xib_buf);
26831 +       sbinfo->si_xib_buf = NULL;
26832 +}
26833 +
26834 +static int au_xino_set_xib(struct super_block *sb, struct file *base)
26835 +{
26836 +       int err;
26837 +       loff_t pos;
26838 +       struct au_sbinfo *sbinfo;
26839 +       struct file *file;
26840 +
26841 +       SiMustWriteLock(sb);
26842 +
26843 +       sbinfo = au_sbi(sb);
26844 +       file = au_xino_create2(base, sbinfo->si_xib);
26845 +       err = PTR_ERR(file);
26846 +       if (IS_ERR(file))
26847 +               goto out;
26848 +       if (sbinfo->si_xib)
26849 +               fput(sbinfo->si_xib);
26850 +       sbinfo->si_xib = file;
26851 +       sbinfo->si_xread = find_readf(file);
26852 +       sbinfo->si_xwrite = find_writef(file);
26853 +
26854 +       err = -ENOMEM;
26855 +       if (!sbinfo->si_xib_buf)
26856 +               sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
26857 +       if (unlikely(!sbinfo->si_xib_buf))
26858 +               goto out_unset;
26859 +
26860 +       sbinfo->si_xib_last_pindex = 0;
26861 +       sbinfo->si_xib_next_bit = 0;
26862 +       if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
26863 +               pos = 0;
26864 +               err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
26865 +                                 PAGE_SIZE, &pos);
26866 +               if (unlikely(err != PAGE_SIZE))
26867 +                       goto out_free;
26868 +       }
26869 +       err = 0;
26870 +       goto out; /* success */
26871 +
26872 +out_free:
26873 +       free_page((unsigned long)sbinfo->si_xib_buf);
26874 +       sbinfo->si_xib_buf = NULL;
26875 +       if (err >= 0)
26876 +               err = -EIO;
26877 +out_unset:
26878 +       fput(sbinfo->si_xib);
26879 +       sbinfo->si_xib = NULL;
26880 +       sbinfo->si_xread = NULL;
26881 +       sbinfo->si_xwrite = NULL;
26882 +out:
26883 +       return err;
26884 +}
26885 +
26886 +/* xino for each branch */
26887 +static void xino_clear_br(struct super_block *sb)
26888 +{
26889 +       aufs_bindex_t bindex, bend;
26890 +       struct au_branch *br;
26891 +
26892 +       bend = au_sbend(sb);
26893 +       for (bindex = 0; bindex <= bend; bindex++) {
26894 +               br = au_sbr(sb, bindex);
26895 +               if (!br || !br->br_xino.xi_file)
26896 +                       continue;
26897 +
26898 +               fput(br->br_xino.xi_file);
26899 +               br->br_xino.xi_file = NULL;
26900 +       }
26901 +}
26902 +
26903 +static int au_xino_set_br(struct super_block *sb, struct file *base)
26904 +{
26905 +       int err;
26906 +       ino_t ino;
26907 +       aufs_bindex_t bindex, bend, bshared;
26908 +       struct {
26909 +               struct file *old, *new;
26910 +       } *fpair, *p;
26911 +       struct au_branch *br;
26912 +       struct inode *inode;
26913 +       au_writef_t writef;
26914 +
26915 +       SiMustWriteLock(sb);
26916 +
26917 +       err = -ENOMEM;
26918 +       bend = au_sbend(sb);
26919 +       fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
26920 +       if (unlikely(!fpair))
26921 +               goto out;
26922 +
26923 +       inode = sb->s_root->d_inode;
26924 +       ino = AUFS_ROOT_INO;
26925 +       writef = au_sbi(sb)->si_xwrite;
26926 +       for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
26927 +               br = au_sbr(sb, bindex);
26928 +               bshared = is_sb_shared(sb, bindex, bindex - 1);
26929 +               if (bshared >= 0) {
26930 +                       /* shared xino */
26931 +                       *p = fpair[bshared];
26932 +                       get_file(p->new);
26933 +               }
26934 +
26935 +               if (!p->new) {
26936 +                       /* new xino */
26937 +                       p->old = br->br_xino.xi_file;
26938 +                       p->new = au_xino_create2(base, br->br_xino.xi_file);
26939 +                       err = PTR_ERR(p->new);
26940 +                       if (IS_ERR(p->new)) {
26941 +                               p->new = NULL;
26942 +                               goto out_pair;
26943 +                       }
26944 +               }
26945 +
26946 +               err = au_xino_do_write(writef, p->new,
26947 +                                      au_h_iptr(inode, bindex)->i_ino, ino);
26948 +               if (unlikely(err))
26949 +                       goto out_pair;
26950 +       }
26951 +
26952 +       for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
26953 +               br = au_sbr(sb, bindex);
26954 +               if (br->br_xino.xi_file)
26955 +                       fput(br->br_xino.xi_file);
26956 +               get_file(p->new);
26957 +               br->br_xino.xi_file = p->new;
26958 +       }
26959 +
26960 +out_pair:
26961 +       for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
26962 +               if (p->new)
26963 +                       fput(p->new);
26964 +               else
26965 +                       break;
26966 +       kfree(fpair);
26967 +out:
26968 +       return err;
26969 +}
26970 +
26971 +void au_xino_clr(struct super_block *sb)
26972 +{
26973 +       struct au_sbinfo *sbinfo;
26974 +
26975 +       au_xigen_clr(sb);
26976 +       xino_clear_xib(sb);
26977 +       xino_clear_br(sb);
26978 +       sbinfo = au_sbi(sb);
26979 +       /* lvalue, do not call au_mntflags() */
26980 +       au_opt_clr(sbinfo->si_mntflags, XINO);
26981 +}
26982 +
26983 +int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
26984 +{
26985 +       int err, skip;
26986 +       struct dentry *parent, *cur_parent;
26987 +       struct qstr *dname, *cur_name;
26988 +       struct file *cur_xino;
26989 +       struct inode *dir;
26990 +       struct au_sbinfo *sbinfo;
26991 +
26992 +       SiMustWriteLock(sb);
26993 +
26994 +       err = 0;
26995 +       sbinfo = au_sbi(sb);
26996 +       parent = dget_parent(xino->file->f_dentry);
26997 +       if (remount) {
26998 +               skip = 0;
26999 +               dname = &xino->file->f_dentry->d_name;
27000 +               cur_xino = sbinfo->si_xib;
27001 +               if (cur_xino) {
27002 +                       cur_parent = dget_parent(cur_xino->f_dentry);
27003 +                       cur_name = &cur_xino->f_dentry->d_name;
27004 +                       skip = (cur_parent == parent
27005 +                               && dname->len == cur_name->len
27006 +                               && !memcmp(dname->name, cur_name->name,
27007 +                                          dname->len));
27008 +                       dput(cur_parent);
27009 +               }
27010 +               if (skip)
27011 +                       goto out;
27012 +       }
27013 +
27014 +       au_opt_set(sbinfo->si_mntflags, XINO);
27015 +       dir = parent->d_inode;
27016 +       mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
27017 +       /* mnt_want_write() is unnecessary here */
27018 +       err = au_xino_set_xib(sb, xino->file);
27019 +       if (!err)
27020 +               err = au_xigen_set(sb, xino->file);
27021 +       if (!err)
27022 +               err = au_xino_set_br(sb, xino->file);
27023 +       mutex_unlock(&dir->i_mutex);
27024 +       if (!err)
27025 +               goto out; /* success */
27026 +
27027 +       /* reset all */
27028 +       AuIOErr("failed creating xino(%d).\n", err);
27029 +
27030 +out:
27031 +       dput(parent);
27032 +       return err;
27033 +}
27034 +
27035 +/* ---------------------------------------------------------------------- */
27036 +
27037 +/*
27038 + * create a xinofile at the default place/path.
27039 + */
27040 +struct file *au_xino_def(struct super_block *sb)
27041 +{
27042 +       struct file *file;
27043 +       char *page, *p;
27044 +       struct au_branch *br;
27045 +       struct super_block *h_sb;
27046 +       struct path path;
27047 +       aufs_bindex_t bend, bindex, bwr;
27048 +
27049 +       br = NULL;
27050 +       bend = au_sbend(sb);
27051 +       bwr = -1;
27052 +       for (bindex = 0; bindex <= bend; bindex++) {
27053 +               br = au_sbr(sb, bindex);
27054 +               if (au_br_writable(br->br_perm)
27055 +                   && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
27056 +                       bwr = bindex;
27057 +                       break;
27058 +               }
27059 +       }
27060 +
27061 +       if (bwr >= 0) {
27062 +               file = ERR_PTR(-ENOMEM);
27063 +               page = __getname_gfp(GFP_NOFS);
27064 +               if (unlikely(!page))
27065 +                       goto out;
27066 +               path.mnt = br->br_mnt;
27067 +               path.dentry = au_h_dptr(sb->s_root, bwr);
27068 +               p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
27069 +               file = (void *)p;
27070 +               if (!IS_ERR(p)) {
27071 +                       strcat(p, "/" AUFS_XINO_FNAME);
27072 +                       AuDbg("%s\n", p);
27073 +                       file = au_xino_create(sb, p, /*silent*/0);
27074 +                       if (!IS_ERR(file))
27075 +                               au_xino_brid_set(sb, br->br_id);
27076 +               }
27077 +               __putname(page);
27078 +       } else {
27079 +               file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
27080 +               if (IS_ERR(file))
27081 +                       goto out;
27082 +               h_sb = file->f_dentry->d_sb;
27083 +               if (unlikely(au_test_fs_bad_xino(h_sb))) {
27084 +                       pr_err("xino doesn't support %s(%s)\n",
27085 +                              AUFS_XINO_DEFPATH, au_sbtype(h_sb));
27086 +                       fput(file);
27087 +                       file = ERR_PTR(-EINVAL);
27088 +               }
27089 +               if (!IS_ERR(file))
27090 +                       au_xino_brid_set(sb, -1);
27091 +       }
27092 +
27093 +out:
27094 +       return file;
27095 +}
27096 +
27097 +/* ---------------------------------------------------------------------- */
27098 +
27099 +int au_xino_path(struct seq_file *seq, struct file *file)
27100 +{
27101 +       int err;
27102 +
27103 +       err = au_seq_path(seq, &file->f_path);
27104 +       if (unlikely(err < 0))
27105 +               goto out;
27106 +
27107 +       err = 0;
27108 +#define Deleted "\\040(deleted)"
27109 +       seq->count -= sizeof(Deleted) - 1;
27110 +       AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
27111 +                        sizeof(Deleted) - 1));
27112 +#undef Deleted
27113 +
27114 +out:
27115 +       return err;
27116 +}
27117 diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
27118 --- /usr/share/empty/include/linux/aufs_type.h  1970-01-01 01:00:00.000000000 +0100
27119 +++ linux/include/linux/aufs_type.h     2010-10-21 09:52:43.096959416 +0200
27120 @@ -0,0 +1,198 @@
27121 +/*
27122 + * Copyright (C) 2005-2010 Junjiro R. Okajima
27123 + *
27124 + * This program, aufs is free software; you can redistribute it and/or modify
27125 + * it under the terms of the GNU General Public License as published by
27126 + * the Free Software Foundation; either version 2 of the License, or
27127 + * (at your option) any later version.
27128 + *
27129 + * This program is distributed in the hope that it will be useful,
27130 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
27131 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27132 + * GNU General Public License for more details.
27133 + *
27134 + * You should have received a copy of the GNU General Public License
27135 + * along with this program; if not, write to the Free Software
27136 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
27137 + */
27138 +
27139 +#ifndef __AUFS_TYPE_H__
27140 +#define __AUFS_TYPE_H__
27141 +
27142 +#include <linux/ioctl.h>
27143 +/* for those who didn't "make headers_install" */
27144 +#ifdef __KERNEL__
27145 +#include <linux/kernel.h>
27146 +#endif
27147 +#include <linux/limits.h>
27148 +#include <linux/types.h>
27149 +
27150 +#define AUFS_VERSION   "2-standalone.tree-36-rcN-20100823"
27151 +
27152 +/* todo? move this to linux-2.6.19/include/magic.h */
27153 +#define AUFS_SUPER_MAGIC       ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
27154 +
27155 +/* ---------------------------------------------------------------------- */
27156 +
27157 +#ifdef CONFIG_AUFS_BRANCH_MAX_127
27158 +typedef __s8 aufs_bindex_t;
27159 +#define AUFS_BRANCH_MAX 127
27160 +#else
27161 +typedef __s16 aufs_bindex_t;
27162 +#ifdef CONFIG_AUFS_BRANCH_MAX_511
27163 +#define AUFS_BRANCH_MAX 511
27164 +#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
27165 +#define AUFS_BRANCH_MAX 1023
27166 +#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
27167 +#define AUFS_BRANCH_MAX 32767
27168 +#endif
27169 +#endif
27170 +
27171 +#ifdef __KERNEL__
27172 +#ifndef AUFS_BRANCH_MAX
27173 +#error unknown CONFIG_AUFS_BRANCH_MAX value
27174 +#endif
27175 +#endif /* __KERNEL__ */
27176 +
27177 +/* ---------------------------------------------------------------------- */
27178 +
27179 +#define AUFS_NAME              "aufs"
27180 +#define AUFS_FSTYPE            AUFS_NAME
27181 +
27182 +#define AUFS_ROOT_INO          2
27183 +#define AUFS_FIRST_INO         11
27184 +
27185 +#define AUFS_WH_PFX            ".wh."
27186 +#define AUFS_WH_PFX_LEN                ((int)sizeof(AUFS_WH_PFX) - 1)
27187 +#define AUFS_WH_TMP_LEN                4
27188 +/* a limit for rmdir/rename a dir */
27189 +#define AUFS_MAX_NAMELEN       (NAME_MAX \
27190 +                               - AUFS_WH_PFX_LEN * 2   /* doubly whiteouted */\
27191 +                               - 1                     /* dot */\
27192 +                               - AUFS_WH_TMP_LEN)      /* hex */
27193 +#define AUFS_XINO_FNAME                "." AUFS_NAME ".xino"
27194 +#define AUFS_XINO_DEFPATH      "/tmp/" AUFS_XINO_FNAME
27195 +#define AUFS_XINO_TRUNC_INIT   64 /* blocks */
27196 +#define AUFS_XINO_TRUNC_STEP   4  /* blocks */
27197 +#define AUFS_DIRWH_DEF         3
27198 +#define AUFS_RDCACHE_DEF       10 /* seconds */
27199 +#define AUFS_RDBLK_DEF         512 /* bytes */
27200 +#define AUFS_RDHASH_DEF                32
27201 +#define AUFS_WKQ_NAME          AUFS_NAME "d"
27202 +#define AUFS_WKQ_PRE_NAME      AUFS_WKQ_NAME "_pre"
27203 +#define AUFS_MFS_SECOND_DEF    30 /* seconds */
27204 +#define AUFS_PLINK_WARN                100 /* number of plinks */
27205 +
27206 +#define AUFS_DIROPQ_NAME       AUFS_WH_PFX ".opq" /* whiteouted doubly */
27207 +#define AUFS_WH_DIROPQ         AUFS_WH_PFX AUFS_DIROPQ_NAME
27208 +
27209 +#define AUFS_BASE_NAME         AUFS_WH_PFX AUFS_NAME
27210 +#define AUFS_PLINKDIR_NAME     AUFS_WH_PFX "plnk"
27211 +#define AUFS_ORPHDIR_NAME      AUFS_WH_PFX "orph"
27212 +
27213 +/* doubly whiteouted */
27214 +#define AUFS_WH_BASE           AUFS_WH_PFX AUFS_BASE_NAME
27215 +#define AUFS_WH_PLINKDIR       AUFS_WH_PFX AUFS_PLINKDIR_NAME
27216 +#define AUFS_WH_ORPHDIR                AUFS_WH_PFX AUFS_ORPHDIR_NAME
27217 +
27218 +/* branch permission */
27219 +#define AUFS_BRPERM_RW         "rw"
27220 +#define AUFS_BRPERM_RO         "ro"
27221 +#define AUFS_BRPERM_RR         "rr"
27222 +#define AUFS_BRPERM_WH         "wh"
27223 +#define AUFS_BRPERM_NLWH       "nolwh"
27224 +#define AUFS_BRPERM_ROWH       AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
27225 +#define AUFS_BRPERM_RRWH       AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
27226 +#define AUFS_BRPERM_RWNLWH     AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
27227 +
27228 +/* ---------------------------------------------------------------------- */
27229 +
27230 +/* ioctl */
27231 +enum {
27232 +       AuCtl_PLINK_MAINT,
27233 +       AuCtl_PLINK_CLEAN,
27234 +
27235 +       /* readdir in userspace */
27236 +       AuCtl_RDU,
27237 +       AuCtl_RDU_INO,
27238 +
27239 +       /* pathconf wrapper */
27240 +       AuCtl_WBR_FD
27241 +};
27242 +
27243 +/* borrowed from linux/include/linux/kernel.h */
27244 +#ifndef ALIGN
27245 +#define ALIGN(x, a)            __ALIGN_MASK(x, (typeof(x))(a)-1)
27246 +#define __ALIGN_MASK(x, mask)  (((x)+(mask))&~(mask))
27247 +#endif
27248 +
27249 +/* borrowed from linux/include/linux/compiler-gcc3.h */
27250 +#ifndef __aligned
27251 +#define __aligned(x)                   __attribute__((aligned(x)))
27252 +#define __packed                       __attribute__((packed))
27253 +#endif
27254 +
27255 +struct au_rdu_cookie {
27256 +       __u64           h_pos;
27257 +       __s16           bindex;
27258 +       __u8            flags;
27259 +       __u8            pad;
27260 +       __u32           generation;
27261 +} __aligned(8);
27262 +
27263 +struct au_rdu_ent {
27264 +       __u64           ino;
27265 +       __s16           bindex;
27266 +       __u8            type;
27267 +       __u8            nlen;
27268 +       __u8            wh;
27269 +       char            name[0];
27270 +} __aligned(8);
27271 +
27272 +static inline int au_rdu_len(int nlen)
27273 +{
27274 +       /* include the terminating NULL */
27275 +       return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
27276 +                    sizeof(__u64));
27277 +}
27278 +
27279 +union au_rdu_ent_ul {
27280 +       struct au_rdu_ent __user        *e;
27281 +       __u64                           ul;
27282 +};
27283 +
27284 +enum {
27285 +       AufsCtlRduV_SZ,
27286 +       AufsCtlRduV_End
27287 +};
27288 +
27289 +struct aufs_rdu {
27290 +       /* input */
27291 +       union {
27292 +               __u64           sz;     /* AuCtl_RDU */
27293 +               __u64           nent;   /* AuCtl_RDU_INO */
27294 +       };
27295 +       union au_rdu_ent_ul     ent;
27296 +       __u16                   verify[AufsCtlRduV_End];
27297 +
27298 +       /* input/output */
27299 +       __u32                   blk;
27300 +
27301 +       /* output */
27302 +       union au_rdu_ent_ul     tail;
27303 +       /* number of entries which were added in a single call */
27304 +       __u64                   rent;
27305 +       __u8                    full;
27306 +       __u8                    shwh;
27307 +
27308 +       struct au_rdu_cookie    cookie;
27309 +} __aligned(8);
27310 +
27311 +#define AuCtlType              'A'
27312 +#define AUFS_CTL_PLINK_MAINT   _IO(AuCtlType, AuCtl_PLINK_MAINT)
27313 +#define AUFS_CTL_PLINK_CLEAN   _IO(AuCtlType, AuCtl_PLINK_CLEAN)
27314 +#define AUFS_CTL_RDU           _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
27315 +#define AUFS_CTL_RDU_INO       _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
27316 +#define AUFS_CTL_WBR_FD                _IO(AuCtlType, AuCtl_WBR_FD)
27317 +
27318 +#endif /* __AUFS_TYPE_H__ */
27319
This page took 1.988531 seconds and 3 git commands to generate.