]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs.patch
- dropped. It is subset of grsec_full.patch.
[packages/kernel.git] / kernel-aufs.patch
CommitLineData
024a5822
JR
1diff -urN linux/fs/aufs/aufs.h linux-aufs/fs/aufs/aufs.h
2--- linux/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
3+++ linux-aufs/fs/aufs/aufs.h 2009-03-12 16:18:04.000000000 +0100
4@@ -0,0 +1,70 @@
5+/*
6+ * Copyright (C) 2005-2009 Junjiro Okajima
7+ *
8+ * This program, aufs is free software; you can redistribute it and/or modify
9+ * it under the terms of the GNU General Public License as published by
10+ * the Free Software Foundation; either version 2 of the License, or
11+ * (at your option) any later version.
12+ *
13+ * This program is distributed in the hope that it will be useful,
14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+ * GNU General Public License for more details.
17+ *
18+ * You should have received a copy of the GNU General Public License
19+ * along with this program; if not, write to the Free Software
20+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21+ */
22+
23+/*
24+ * main header files
25+ *
26+ * $Id$
27+ */
28+
29+#ifndef __AUFS_H__
30+#define __AUFS_H__
31+
32+#ifdef __KERNEL__
33+
34+#include <linux/version.h>
35+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
36+#error you got wrong version
37+#endif
38+
39+/* introduced in linux-2.6.27 */
40+#include <linux/bug.h>
41+#ifndef WARN_ONCE
42+#define WARN_ONCE(cond, fmt ...) WARN_ON(cond)
43+#endif
44+
45+/* ---------------------------------------------------------------------- */
46+
47+#include "debug.h"
48+
49+#include "branch.h"
50+#include "cpup.h"
51+#include "dcsub.h"
52+#include "dentry.h"
53+#include "dir.h"
54+#include "file.h"
55+#include "hinode.h"
56+#include "inode.h"
57+#include "misc.h"
58+#include "module.h"
59+#include "opts.h"
60+#include "super.h"
61+#include "sysaufs.h"
62+#include "vfsub.h"
63+#include "whout.h"
64+#include "wkq.h"
65+/* reserved for future use */
66+/* #include "xattr.h" */
67+
68+#ifdef AuNoInlineForStack
69+#undef noinline_for_stack
70+#define noinline_for_stack /* */
71+#endif
72+
73+#endif /* __KERNEL__ */
74+#endif /* __AUFS_H__ */
75diff -urN linux/fs/aufs/branch.c linux-aufs/fs/aufs/branch.c
76--- linux/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
77+++ linux-aufs/fs/aufs/branch.c 2009-03-12 16:18:04.000000000 +0100
78@@ -0,0 +1,1038 @@
79+/*
80+ * Copyright (C) 2005-2009 Junjiro Okajima
81+ *
82+ * This program, aufs is free software; you can redistribute it and/or modify
83+ * it under the terms of the GNU General Public License as published by
84+ * the Free Software Foundation; either version 2 of the License, or
85+ * (at your option) any later version.
86+ *
87+ * This program is distributed in the hope that it will be useful,
88+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
89+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90+ * GNU General Public License for more details.
91+ *
92+ * You should have received a copy of the GNU General Public License
93+ * along with this program; if not, write to the Free Software
94+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
95+ */
96+
97+/*
98+ * branch management
99+ *
100+ * $Id$
101+ */
102+
103+#include <linux/iso_fs.h>
104+#include <linux/loop.h>
105+#include <linux/romfs_fs.h>
106+#include <linux/smp_lock.h>
107+#include "aufs.h"
108+
109+static void au_br_do_free(struct au_branch *br)
110+{
111+ int i;
112+ struct au_wbr *wbr;
113+
114+ AuTraceEnter();
115+
116+ if (br->br_xino.xi_file)
117+ fput(br->br_xino.xi_file);
118+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
119+ wbr = br->br_wbr;
120+ if (wbr)
121+ for (i = 0; i < AuBrWh_Last; i++)
122+ dput(wbr->wbr_wh[i]);
123+ /* do not call au_br_nfs_lockdep_off() here */
124+ if (br->br_mnt && !au_test_nfs(br->br_mnt->mnt_sb))
125+ mntput(br->br_mnt);
126+ else {
127+ lockdep_off();
128+ mntput(br->br_mnt);
129+ lockdep_on();
130+ }
131+ AuDebugOn(au_br_count(br));
132+ if (wbr) {
133+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
134+ au_rwsem_destroy(&wbr->wbr_wh_rwsem);
135+ }
136+ kfree(wbr);
137+ kfree(br);
138+}
139+
140+/*
141+ * frees all branches
142+ */
143+void au_br_free(struct au_sbinfo *sbinfo)
144+{
145+ aufs_bindex_t bmax;
146+ struct au_branch **br;
147+
148+ AuTraceEnter();
149+ bmax = sbinfo->si_bend + 1;
150+ br = sbinfo->si_branch;
151+ while (bmax--)
152+ au_br_do_free(*br++);
153+}
154+
155+/*
156+ * find the index of a branch which is specified by @br_id.
157+ */
158+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
159+{
160+ aufs_bindex_t bindex, bend;
161+
162+ AuTraceEnter();
163+
164+ bend = au_sbend(sb);
165+ for (bindex = 0; bindex <= bend; bindex++)
166+ if (au_sbr_id(sb, bindex) == br_id)
167+ return bindex;
168+ return -1;
169+}
170+
171+/*
172+ * test if the @h_sb is real-readonly.
173+ */
174+int au_test_def_rr(struct super_block *h_sb)
175+{
176+ switch (h_sb->s_magic) {
177+#ifdef CONFIG_AUFS_RR_SQUASHFS
178+ case SQUASHFS_MAGIC_LZMA:
179+ case SQUASHFS_MAGIC:
180+ case SQUASHFS_MAGIC_LZMA_SWAP:
181+ case SQUASHFS_MAGIC_SWAP:
182+ return 1; /* real readonly */
183+#endif
184+
185+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
186+ case ISOFS_SUPER_MAGIC:
187+ return 1;
188+#endif
189+
190+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
191+ case CRAMFS_MAGIC:
192+ return 1;
193+#endif
194+
195+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
196+ case ROMFS_MAGIC:
197+ return 1;
198+#endif
199+
200+ default:
201+ return 0;
202+ }
203+}
204+
205+/* ---------------------------------------------------------------------- */
206+
207+/*
208+ * test if two hidden_dentries have overlapping branches.
209+ */
210+static int do_test_overlap(struct super_block *sb, struct dentry *h_d1,
211+ struct dentry *h_d2)
212+{
213+ struct dentry *d;
214+
215+ LKTRTrace("%.*s, %.*s\n", AuDLNPair(h_d1), AuDLNPair(h_d2));
216+
217+ d = au_test_subdir(h_d1, h_d2);
218+ if (unlikely(d)) {
219+ AuDbgDentry(h_d1);
220+ AuDbgDentry(h_d2);
221+ }
222+ return !!d;
223+}
224+
225+static int test_overlap_loopback(struct super_block *sb, struct dentry *h_d1,
226+ struct dentry *h_d2)
227+{
228+#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
229+ struct inode *h_inode;
230+ struct loop_device *l;
231+
232+ LKTRTrace("%.*s, %.*s\n", AuDLNPair(h_d1), AuDLNPair(h_d2));
233+ AuDbgDentry(h_d1);
234+ AuDbgDentry(h_d2);
235+ AuDbgSb(h_d1->d_sb);
236+ AuDbgSb(h_d2->d_sb);
237+
238+ h_inode = h_d1->d_inode;
239+ if (MAJOR(h_inode->i_sb->s_dev) != LOOP_MAJOR)
240+ return 0;
241+
242+ l = h_inode->i_sb->s_bdev->bd_disk->private_data;
243+ h_d1 = l->lo_backing_file->f_dentry;
244+ /* h_d1 can be local NFS. in this case aufs cannot detect the loop */
245+ AuDbgDentry(h_d1);
246+ AuDbgDentry(h_d2);
247+ AuDbgSb(h_d1->d_sb);
248+ AuDbgSb(h_d2->d_sb);
249+ if (unlikely(h_d1->d_sb == sb))
250+ return 1;
251+ return do_test_overlap(sb, h_d1, h_d2);
252+#else
253+ return 0;
254+#endif
255+}
256+
257+static int test_overlap(struct super_block *sb, struct dentry *h_d1,
258+ struct dentry *h_d2)
259+{
260+ LKTRTrace("d1 %.*s, d2 %.*s\n", AuDLNPair(h_d1), AuDLNPair(h_d2));
261+
262+ if (unlikely(h_d1 == h_d2)) {
263+ AuDbgDentry(h_d1);
264+ AuDbgDentry(h_d2);
265+ return 1;
266+ }
267+ return do_test_overlap(sb, h_d1, h_d2)
268+ || do_test_overlap(sb, h_d2, h_d1)
269+ || test_overlap_loopback(sb, h_d1, h_d2)
270+ || test_overlap_loopback(sb, h_d2, h_d1);
271+}
272+
273+/* ---------------------------------------------------------------------- */
274+
275+static int au_br_init_wh(struct super_block *sb, aufs_bindex_t bindex,
276+ struct au_branch *br, int new_perm,
277+ struct dentry *h_root, struct vfsmount *h_mnt)
278+{
279+ int err, old_perm;
280+ struct inode *h_dir;
281+ struct au_wbr *wbr;
282+
283+ LKTRTrace("b%d, new_perm %d\n", bindex, new_perm);
284+ SiMustWriteLock(sb);
285+
286+ wbr = br->br_wbr;
287+ h_dir = h_root->d_inode;
288+ old_perm = br->br_perm;
289+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
290+ if (wbr)
291+ wbr_wh_write_lock(wbr);
292+ br->br_perm = new_perm;
293+ err = au_wh_init(h_root, br, h_mnt, sb, bindex);
294+ br->br_perm = old_perm;
295+ if (wbr)
296+ wbr_wh_write_unlock(wbr);
297+ mutex_unlock(&h_dir->i_mutex);
298+ if (!err && wbr && !au_br_writable(new_perm)) {
299+ AuDebugOn(wbr->wbr_whbase);
300+ AuDebugOn(wbr->wbr_plink);
301+ AuDebugOn(wbr->wbr_tmp);
302+ kfree(wbr);
303+ br->br_wbr = NULL;
304+ }
305+
306+ AuTraceErr(err);
307+ return err;
308+}
309+
310+/* ---------------------------------------------------------------------- */
311+
312+/*
313+ * returns a newly allocated branch. @new_nbranch is a number of branches
314+ * after adding a branch.
315+ */
316+static struct au_branch *alloc_addbr(struct super_block *sb, int new_nbranch,
317+ int perm)
318+{
319+ struct au_branch **branchp, *add_branch;
320+ int sz;
321+ void *p;
322+ struct dentry *root;
323+ struct inode *inode;
324+ struct au_hinode *hinodep;
325+ struct au_hdentry *hdentryp;
326+
327+ LKTRTrace("new_nbranch %d\n", new_nbranch);
328+ SiMustWriteLock(sb);
329+ root = sb->s_root;
330+ DiMustWriteLock(root);
331+ inode = root->d_inode;
332+ IiMustWriteLock(inode);
333+
334+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
335+ if (unlikely(!add_branch))
336+ goto out;
337+ add_branch->br_wbr = NULL;
338+ if (au_br_writable(perm)) {
339+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
340+ GFP_NOFS);
341+ if (unlikely(!add_branch->br_wbr))
342+ goto out_br;
343+ }
344+
345+ sz = sizeof(*branchp) * (new_nbranch - 1);
346+ if (unlikely(!sz))
347+ sz = sizeof(*branchp);
348+ p = au_sbi(sb)->si_branch;
349+ branchp = au_kzrealloc(p, sz, sizeof(*branchp) * new_nbranch, GFP_NOFS);
350+ if (unlikely(!branchp))
351+ goto out_wbr;
352+ au_sbi(sb)->si_branch = branchp;
353+
354+ sz = sizeof(*hdentryp) * (new_nbranch - 1);
355+ if (unlikely(!sz))
356+ sz = sizeof(*hdentryp);
357+ p = au_di(root)->di_hdentry;
358+ hdentryp = au_kzrealloc(p, sz, sizeof(*hdentryp) * new_nbranch,
359+ GFP_NOFS);
360+ if (unlikely(!hdentryp))
361+ goto out_wbr;
362+ au_di(root)->di_hdentry = hdentryp;
363+
364+ sz = sizeof(*hinodep) * (new_nbranch - 1);
365+ if (unlikely(!sz))
366+ sz = sizeof(*hinodep);
367+ p = au_ii(inode)->ii_hinode;
368+ hinodep = au_kzrealloc(p, sz, sizeof(*hinodep) * new_nbranch, GFP_NOFS);
369+ if (unlikely(!hinodep))
370+ goto out_wbr;
371+ au_ii(inode)->ii_hinode = hinodep;
372+ return add_branch; /* success */
373+
374+ out_wbr:
375+ kfree(add_branch->br_wbr);
376+ out_br:
377+ kfree(add_branch);
378+ out:
379+ AuTraceErr(-ENOMEM);
380+ return ERR_PTR(-ENOMEM);
381+}
382+
383+/*
384+ * test if the branch permission is legal or not.
385+ */
386+static int test_br(struct super_block *sb, struct inode *inode, int brperm,
387+ char *path)
388+{
389+ int err;
390+
391+ err = 0;
392+ if (unlikely(au_br_writable(brperm) && IS_RDONLY(inode))) {
393+ AuErr("write permission for readonly fs or inode, %s\n", path);
394+ err = -EINVAL;
395+ }
396+
397+ AuTraceErr(err);
398+ return err;
399+}
400+
401+static int au_unsupported_fs(struct super_block *sb)
402+{
403+ return sb->s_magic == PROC_SUPER_MAGIC
404+#ifdef SYSFS_MAGIC
405+ || sb->s_magic == SYSFS_MAGIC
406+#endif
407+ || !strcmp(au_sbtype(sb), "unionfs");
408+}
409+
410+/*
411+ * returns:
412+ * 0: success, the caller will add it
413+ * plus: success, it is already unified, the caller should ignore it
414+ * minus: error
415+ */
416+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
417+{
418+ int err;
419+ struct dentry *root;
420+ struct inode *inode, *h_inode;
421+ aufs_bindex_t bend, bindex;
422+
423+ LKTRTrace("%s, remo%d\n", add->path, remount);
424+
425+ root = sb->s_root;
426+ bend = au_sbend(sb);
427+ if (unlikely(bend >= 0
428+ && au_find_dbindex(root, add->nd.path.dentry) >= 0)) {
429+ err = 1;
430+ if (!remount) {
431+ err = -EINVAL;
432+ AuErr("%s duplicated\n", add->path);
433+ }
434+ goto out;
435+ }
436+
437+ err = -ENOSPC; /* -E2BIG; */
438+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
439+ || AUFS_BRANCH_MAX - 1 <= bend)) {
440+ AuErr("number of branches exceeded %s\n", add->path);
441+ goto out;
442+ }
443+
444+ err = -EDOM;
445+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
446+ AuErr("bad index %d\n", add->bindex);
447+ goto out;
448+ }
449+
450+ inode = add->nd.path.dentry->d_inode;
451+ AuDebugOn(!inode || !S_ISDIR(inode->i_mode));
452+ err = -ENOENT;
453+ if (unlikely(!inode->i_nlink)) {
454+ AuErr("no existence %s\n", add->path);
455+ goto out;
456+ }
457+
458+ err = -EINVAL;
459+ if (unlikely(inode->i_sb == sb)) {
460+ AuErr("%s must be outside\n", add->path);
461+ goto out;
462+ }
463+
464+ if (unlikely(au_test_nested(inode->i_sb))) {
465+ AuErr("nested " AUFS_NAME " %s\n", add->path);
466+ goto out;
467+ }
468+
469+ if (unlikely(au_unsupported_fs(inode->i_sb))) {
470+ AuErr("unsupported filesystem, %s\n", add->path);
471+ goto out;
472+ }
473+
474+ if (unlikely(au_test_unsupported_nfs(inode->i_sb))) {
475+ AuErr(AuNoNfsBranchMsg " %s\n", add->path);
476+ goto out;
477+ }
478+
479+ if (unlikely(au_test_unsupported_nfs4(inode->i_sb))) {
480+ AuErr(AuNoNfsv4BranchMsg " %s\n", add->path);
481+ goto out;
482+ }
483+
484+ err = test_br(sb, add->nd.path.dentry->d_inode, add->perm, add->path);
485+ if (unlikely(err))
486+ goto out;
487+
488+ if (bend < 0)
489+ return 0; /* success */
490+
491+ err = -EINVAL;
492+ for (bindex = 0; bindex <= bend; bindex++)
493+ if (unlikely(test_overlap(sb, add->nd.path.dentry,
494+ au_h_dptr(root, bindex)))) {
495+ AuErr("%s is overlapped\n", add->path);
496+ goto out;
497+ }
498+
499+ err = 0;
500+ h_inode = au_h_dptr(root, 0)->d_inode;
501+ if (unlikely(au_opt_test(au_mntflags(sb), WARN_PERM)
502+ && ((h_inode->i_mode & S_IALLUGO)
503+ != (inode->i_mode & S_IALLUGO)
504+ || h_inode->i_uid != inode->i_uid
505+ || h_inode->i_gid != inode->i_gid)))
506+ AuWarn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
507+ add->path,
508+ inode->i_uid, inode->i_gid, (inode->i_mode & S_IALLUGO),
509+ h_inode->i_uid, h_inode->i_gid,
510+ (h_inode->i_mode & S_IALLUGO));
511+
512+ out:
513+ AuTraceErr(err);
514+ return err;
515+}
516+
517+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
518+ int perm, struct path *path)
519+{
520+ int err;
521+ struct au_wbr *wbr;
522+
523+ AuTraceEnter();
524+ wbr = br->br_wbr;
525+ AuDebugOn(!wbr);
526+
527+ au_rw_init_nolock(&wbr->wbr_wh_rwsem);
528+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
529+ atomic_set(&wbr->wbr_wh_running, 0);
530+ wbr->wbr_bytes = 0;
531+
532+ err = au_br_init_wh(sb, /*bindex*/-1, br, perm,
533+ path->dentry, path->mnt);
534+
535+ AuTraceErr(err);
536+ return err;
537+}
538+
539+static int au_br_init(struct au_branch *br, struct super_block *sb,
540+ struct au_opt_add *add)
541+{
542+ int err;
543+ unsigned int mnt_flags;
544+
545+ AuTraceEnter();
546+
547+ err = 0;
548+ br->br_mnt = NULL;
549+ br->br_xino.xi_file = NULL;
550+ mutex_init(&br->br_xino.xi_nondir_mtx);
551+ atomic_set(&br->br_xino_running, 0);
552+ atomic_set(&br->br_count, 0);
553+
554+ if (au_br_writable(add->perm)) {
555+ err = au_wbr_init(br, sb, add->perm, &add->nd.path);
556+ if (unlikely(err))
557+ goto out;
558+ }
559+
560+ br->br_mnt = mntget(add->nd.path.mnt);
561+ mnt_flags = au_mntflags(sb);
562+ if (au_opt_test(mnt_flags, XINO)) {
563+ err = au_xino_br(sb, br, add->nd.path.dentry->d_inode->i_ino,
564+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
565+ if (unlikely(err)) {
566+ AuDebugOn(br->br_xino.xi_file);
567+ goto out;
568+ }
569+#if 0 /* reserved for future use */
570+ } else if (au_opt_test(mnt_flags, XINODIR)) {
571+ err = au_xinodir_br(sb, br, add->nd.path.dentry->d_inode->i_ino,
572+ /*do_test*/1);
573+ if (unlikely(err)) {
574+ AuDebugOn(br->br_xino.xi_file);
575+ goto out;
576+ }
577+#endif
578+ }
579+
580+ br->br_id = au_new_br_id(sb);
581+ br->br_perm = add->perm;
582+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
583+ sysaufs_br_init(br);
584+ br->br_generation = au_sigen(sb);
585+ /* smp_mb(); */ /* atomic_set */
586+
587+ out:
588+ AuTraceErr(err);
589+ return err;
590+}
591+
592+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
593+{
594+ int err, amount;
595+ aufs_bindex_t bend, add_bindex;
596+ struct dentry *root, *dentry;
597+ struct au_iinfo *iinfo;
598+ struct au_sbinfo *sbinfo;
599+ struct au_dinfo *dinfo;
600+ struct inode *root_inode;
601+ unsigned long long maxb;
602+ struct au_branch **branchp, *add_branch;
603+ struct au_hdentry *hdentryp;
604+ struct au_hinode *hinodep;
605+
606+ dentry = add->nd.path.dentry;
607+ LKTRTrace("b%d, %s, 0x%x, %.*s\n",
608+ add->bindex, add->path, add->perm, AuDLNPair(dentry));
609+ SiMustWriteLock(sb);
610+ root = sb->s_root;
611+ DiMustWriteLock(root);
612+ root_inode = root->d_inode;
613+ IMustLock(root_inode);
614+ IiMustWriteLock(root_inode);
615+
616+ err = test_add(sb, add, remount);
617+ if (unlikely(err < 0))
618+ goto out;
619+ if (err) {
620+ err = 0;
621+ goto out; /* success */
622+ }
623+
624+ bend = au_sbend(sb);
625+ add_branch = alloc_addbr(sb, bend + 2, add->perm);
626+ err = PTR_ERR(add_branch);
627+ if (IS_ERR(add_branch))
628+ goto out;
629+ err = au_br_init(add_branch, sb, add);
630+ if (unlikely(err)) {
631+ au_br_do_free(add_branch);
632+ goto out;
633+ }
634+
635+ add_bindex = add->bindex;
636+ if (remount)
637+ sysaufs_brs_del(sb, add_bindex);
638+
639+ sbinfo = au_sbi(sb);
640+ dinfo = au_di(root);
641+ iinfo = au_ii(root_inode);
642+
643+ amount = bend + 1 - add_bindex;
644+ branchp = sbinfo->si_branch + add_bindex;
645+ memmove(branchp + 1, branchp, sizeof(*branchp) * amount);
646+ *branchp = add_branch;
647+ hdentryp = dinfo->di_hdentry + add_bindex;
648+ memmove(hdentryp + 1, hdentryp, sizeof(*hdentryp) * amount);
649+ au_h_dentry_init(hdentryp);
650+ hinodep = iinfo->ii_hinode + add_bindex;
651+ memmove(hinodep + 1, hinodep, sizeof(*hinodep) * amount);
652+ hinodep->hi_inode = NULL;
653+ au_hin_init(hinodep, NULL);
654+
655+ sbinfo->si_bend++;
656+ dinfo->di_bend++;
657+ iinfo->ii_bend++;
658+ if (unlikely(bend < 0)) {
659+ sbinfo->si_bend = 0;
660+ dinfo->di_bstart = 0;
661+ iinfo->ii_bstart = 0;
662+ }
663+ au_set_h_dptr(root, add_bindex, dget(dentry));
664+ au_set_h_iptr(root_inode, add_bindex, au_igrab(dentry->d_inode), 0);
665+ if (remount)
666+ sysaufs_brs_add(sb, add_bindex);
667+
668+ if (!add_bindex)
669+ au_cpup_attr_all(root_inode, /*force*/1);
670+ else
671+ au_add_nlink(root_inode, dentry->d_inode);
672+ maxb = dentry->d_sb->s_maxbytes;
673+ if (sb->s_maxbytes < maxb)
674+ sb->s_maxbytes = maxb;
675+
676+ /* safe d_parent reference */
677+ if (!au_xino_def_br(sbinfo)
678+ && add_branch->br_xino.xi_file
679+ && add_branch->br_xino.xi_file->f_dentry->d_parent == dentry)
680+ au_xino_def_br_set(add_branch, sbinfo);
681+
682+ out:
683+ AuTraceErr(err);
684+ return err;
685+}
686+
687+/* ---------------------------------------------------------------------- */
688+
689+#define AuVerbose(do_info, fmt, args...) do { \
690+ if (!do_info) \
691+ LKTRTrace(fmt, ##args); \
692+ else \
693+ AuInfo(fmt, ##args); \
694+} while (0)
695+
696+/*
697+ * test if the branch is deletable or not.
698+ */
699+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
700+ au_gen_t sigen)
701+{
702+ int err, i, j, ndentry;
703+ struct au_dcsub_pages dpages;
704+ struct au_dpage *dpage;
705+ struct dentry *d;
706+ aufs_bindex_t bstart, bend;
707+ unsigned char verbose;
708+ struct inode *inode;
709+
710+ LKTRTrace("b%d, gen%d\n", bindex, sigen);
711+ SiMustWriteLock(root->d_sb);
712+
713+ err = au_dpages_init(&dpages, GFP_NOFS);
714+ if (unlikely(err))
715+ goto out;
716+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
717+ if (unlikely(err))
718+ goto out_dpages;
719+
720+ verbose = !!au_opt_test(au_mntflags(root->d_sb), VERBOSE);
721+ for (i = 0; !err && i < dpages.ndpage; i++) {
722+ dpage = dpages.dpages + i;
723+ ndentry = dpage->ndentry;
724+ for (j = 0; !err && j < ndentry; j++) {
725+ d = dpage->dentries[j];
726+ AuDebugOn(!atomic_read(&d->d_count));
727+ inode = d->d_inode;
728+ AuDebugOn(!inode);
729+ if (au_digen(d) == sigen
730+ && au_iigen(inode) == sigen)
731+ di_read_lock_child(d, AuLock_IR);
732+ else {
733+ di_write_lock_child(d);
734+ err = au_reval_dpath(d, sigen);
735+ if (!err)
736+ di_downgrade_lock(d, AuLock_IR);
737+ else {
738+ di_write_unlock(d);
739+ break;
740+ }
741+ }
742+
743+ bstart = au_dbstart(d);
744+ bend = au_dbend(d);
745+ if (bstart <= bindex
746+ && bindex <= bend
747+ && au_h_dptr(d, bindex)
748+ && (!S_ISDIR(d->d_inode->i_mode)
749+ || bstart == bend)) {
750+ err = -EBUSY;
751+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
752+ }
753+ di_read_unlock(d, AuLock_IR);
754+ }
755+ }
756+
757+ out_dpages:
758+ au_dpages_free(&dpages);
759+ out:
760+ AuTraceErr(err);
761+ return err;
762+}
763+
764+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
765+ au_gen_t sigen)
766+{
767+ int err;
768+ struct inode *i;
769+ aufs_bindex_t bstart, bend;
770+ unsigned char verbose;
771+
772+ LKTRTrace("b%d, gen%d\n", bindex, sigen);
773+ SiMustWriteLock(sb);
774+
775+ err = 0;
776+ verbose = !!au_opt_test(au_mntflags(sb), VERBOSE);
777+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
778+ AuDebugOn(!atomic_read(&i->i_count));
779+ if (!list_empty(&i->i_dentry))
780+ continue;
781+
782+ if (au_iigen(i) == sigen)
783+ ii_read_lock_child(i);
784+ else {
785+ ii_write_lock_child(i);
786+ err = au_refresh_hinode_self(i);
787+ if (!err)
788+ ii_downgrade_lock(i);
789+ else {
790+ ii_write_unlock(i);
791+ break;
792+ }
793+ }
794+
795+ bstart = au_ibstart(i);
796+ bend = au_ibend(i);
797+ if (bstart <= bindex
798+ && bindex <= bend
799+ && au_h_iptr(i, bindex)
800+ && (!S_ISDIR(i->i_mode) || bstart == bend)) {
801+ err = -EBUSY;
802+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
803+ ii_read_unlock(i);
804+ break;
805+ }
806+ ii_read_unlock(i);
807+ }
808+
809+ AuTraceErr(err);
810+ return err;
811+}
812+
813+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
814+{
815+ int err;
816+ au_gen_t sigen;
817+
818+ LKTRTrace("b%d\n", bindex);
819+ SiMustWriteLock(root->d_sb);
820+ DiMustWriteLock(root);
821+ /* dont trust BKL */
822+ AuDebugOn(!kernel_locked());
823+
824+ sigen = au_sigen(root->d_sb);
825+ DiMustNoWaiters(root);
826+ IiMustNoWaiters(root->d_inode);
827+ di_write_unlock(root);
828+ err = test_dentry_busy(root, bindex, sigen);
829+ if (!err)
830+ err = test_inode_busy(root->d_sb, bindex, sigen);
831+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
832+
833+ AuTraceErr(err);
834+ return err;
835+}
836+
837+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
838+{
839+ int err, rerr, i;
840+ aufs_bindex_t bindex, bend, br_id;
841+ unsigned char do_wh, verbose;
842+ struct au_sbinfo *sbinfo;
843+ struct au_dinfo *dinfo;
844+ struct au_iinfo *iinfo;
845+ struct au_branch *br, **brp;
846+ struct au_wbr *wbr;
847+ struct au_hdentry *hdp;
848+ struct au_hinode *hip;
849+
850+ LKTRTrace("%s, %.*s\n", del->path, AuDLNPair(del->h_root));
851+ SiMustWriteLock(sb);
852+ DiMustWriteLock(sb->s_root);
853+ IiMustWriteLock(sb->s_root->d_inode);
854+
855+ err = 0;
856+ bindex = au_find_dbindex(sb->s_root, del->h_root);
857+ if (bindex < 0) {
858+ if (remount)
859+ goto out; /* success */
860+ err = -ENOENT;
861+ AuErr("%s no such branch\n", del->path);
862+ goto out;
863+ }
864+ LKTRTrace("bindex b%d\n", bindex);
865+
866+ err = -EBUSY;
867+ verbose = !!au_opt_test(au_mntflags(sb), VERBOSE);
868+ bend = au_sbend(sb);
869+ if (unlikely(!bend)) {
870+ AuVerbose(verbose, "no more branches left\n");
871+ goto out;
872+ }
873+ br = au_sbr(sb, bindex);
874+ if (unlikely(au_br_count(br))) {
875+ AuVerbose(verbose, "%d file(s) opened\n", au_br_count(br));
876+ goto out;
877+ }
878+
879+ wbr = br->br_wbr;
880+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_tmp);
881+ if (do_wh) {
882+#if 0 /* reserved for future use */
883+ /* remove whiteout base */
884+ err = au_br_init_wh(sb, bindex, br, AuBr_RO, del->h_root,
885+ br->br_mnt);
886+ if (unlikely(err))
887+ goto out;
888+#else
889+ for (i = 0; i < AuBrWh_Last; i++) {
890+ dput(wbr->wbr_wh[i]);
891+ wbr->wbr_wh[i] = NULL;
892+ }
893+#endif
894+ }
895+
896+ err = test_children_busy(sb->s_root, bindex);
897+ if (unlikely(err)) {
898+ if (do_wh)
899+ goto out_wh;
900+ goto out;
901+ }
902+
903+ err = 0;
904+ if (remount)
905+ sysaufs_brs_del(sb, bindex);
906+ sbinfo = au_sbi(sb);
907+ dinfo = au_di(sb->s_root);
908+ iinfo = au_ii(sb->s_root->d_inode);
909+
910+ dput(au_h_dptr(sb->s_root, bindex));
911+ au_hiput(iinfo->ii_hinode + bindex);
912+ br_id = br->br_id;
913+ au_br_do_free(br);
914+
915+ /* todo: realloc and shrink memory? */
916+ if (bindex < bend) {
917+ const aufs_bindex_t n = bend - bindex;
918+
919+ brp = sbinfo->si_branch + bindex;
920+ memmove(brp, brp + 1, sizeof(*brp) * n);
921+ hdp = dinfo->di_hdentry + bindex;
922+ memmove(hdp, hdp + 1, sizeof(*hdp) * n);
923+ hip = iinfo->ii_hinode + bindex;
924+ memmove(hip, hip + 1, sizeof(*hip) * n);
925+ }
926+ sbinfo->si_branch[0 + bend] = NULL;
927+ dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
928+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
929+ au_hin_init(iinfo->ii_hinode + bend, NULL);
930+
931+ sbinfo->si_bend--;
932+ dinfo->di_bend--;
933+ iinfo->ii_bend--;
934+ if (remount)
935+ sysaufs_brs_add(sb, bindex);
936+
937+ if (!bindex)
938+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
939+ else
940+ au_sub_nlink(sb->s_root->d_inode, del->h_root->d_inode);
941+ if (au_opt_test(au_mntflags(sb), PLINK))
942+ au_plink_half_refresh(sb, br_id);
943+
944+ if (sb->s_maxbytes == del->h_root->d_sb->s_maxbytes) {
945+ bend--;
946+ sb->s_maxbytes = 0;
947+ for (bindex = 0; bindex <= bend; bindex++) {
948+ unsigned long long maxb;
949+ maxb = au_sbr_sb(sb, bindex)->s_maxbytes;
950+ if (sb->s_maxbytes < maxb)
951+ sb->s_maxbytes = maxb;
952+ }
953+ }
954+
955+ if (au_xino_def_br(sbinfo) == br)
956+ au_xino_def_br_set(NULL, sbinfo);
957+ goto out; /* success */
958+
959+ out_wh:
960+ /* revert */
961+ rerr = au_br_init_wh(sb, bindex, br, br->br_perm, del->h_root,
962+ br->br_mnt);
963+ if (rerr)
964+ AuWarn("failed re-creating base whiteout, %s. (%d)\n",
965+ del->path, rerr);
966+ out:
967+ AuTraceErr(err);
968+ return err;
969+}
970+
971+static int do_need_sigen_inc(int a, int b)
972+{
973+ return au_br_whable(a) && !au_br_whable(b);
974+}
975+
976+static int need_sigen_inc(int old, int new)
977+{
978+ return do_need_sigen_inc(old, new)
979+ || do_need_sigen_inc(new, old);
980+}
981+
982+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
983+{
984+ int err;
985+ struct file *file, *hf;
986+
987+ AuTraceEnter();
988+ SiMustWriteLock(sb);
989+
990+ /* no need file_list_lock() since sbinfo is locked */
991+ err = 0;
992+ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
993+ LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry));
994+ if (!au_test_aufs_file(file))
995+ continue;
996+
997+ fi_read_lock(file);
998+ if (!S_ISREG(file->f_dentry->d_inode->i_mode)
999+ || !(file->f_mode & FMODE_WRITE)
1000+ || au_fbstart(file) != bindex) {
1001+ FiMustNoWaiters(file);
1002+ fi_read_unlock(file);
1003+ continue;
1004+ }
1005+
1006+ if (unlikely(au_test_mmapped(file))) {
1007+ err = -EBUSY;
1008+ FiMustNoWaiters(file);
1009+ fi_read_unlock(file);
1010+ break;
1011+ }
1012+
1013+ /* todo: already flushed? */
1014+ hf = au_h_fptr(file, au_fbstart(file));
1015+ hf->f_flags = au_file_roflags(hf->f_flags);
1016+ hf->f_mode &= ~FMODE_WRITE;
1017+ put_write_access(hf->f_dentry->d_inode);
1018+ FiMustNoWaiters(file);
1019+ fi_read_unlock(file);
1020+ }
1021+
1022+ AuTraceErr(err);
1023+ return err;
1024+}
1025+
1026+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1027+ int *do_update)
1028+{
1029+ int err;
1030+ struct dentry *root;
1031+ aufs_bindex_t bindex;
1032+ struct au_branch *br;
1033+ struct inode *hidden_dir;
1034+
1035+ LKTRTrace("%s, %.*s, 0x%x\n",
1036+ mod->path, AuDLNPair(mod->h_root), mod->perm);
1037+ SiMustWriteLock(sb);
1038+ root = sb->s_root;
1039+ DiMustWriteLock(root);
1040+ IiMustWriteLock(root->d_inode);
1041+
1042+ bindex = au_find_dbindex(root, mod->h_root);
1043+ if (bindex < 0) {
1044+ if (remount)
1045+ return 0; /* success */
1046+ err = -ENOENT;
1047+ AuErr("%s no such branch\n", mod->path);
1048+ goto out;
1049+ }
1050+ LKTRTrace("bindex b%d\n", bindex);
1051+
1052+ hidden_dir = mod->h_root->d_inode;
1053+ err = test_br(sb, hidden_dir, mod->perm, mod->path);
1054+ if (unlikely(err))
1055+ goto out;
1056+
1057+ br = au_sbr(sb, bindex);
1058+ if (br->br_perm == mod->perm)
1059+ return 0; /* success */
1060+
1061+ if (au_br_writable(br->br_perm)) {
1062+#if 1
1063+ /* remove whiteout base */
1064+ err = au_br_init_wh(sb, bindex, br, mod->perm, mod->h_root,
1065+ br->br_mnt);
1066+ if (unlikely(err))
1067+ goto out;
1068+#else /* reserved for future use */
1069+ struct au_wbr *wbr;
1070+ wbr = br->wbr;
1071+ if (wbr)
1072+ for (i = 0; i < AuBrWh_Last; i++) {
1073+ dput(wbr->wbr_wh[i]);
1074+ wbr->wbr_wh[i] = NULL;
1075+ }
1076+#endif
1077+
1078+ if (!au_br_writable(mod->perm)) {
1079+ /* rw --> ro, file might be mmapped */
1080+
1081+#if 1 /* todo: test more? */
1082+ DiMustNoWaiters(root);
1083+ IiMustNoWaiters(root->d_inode);
1084+ di_write_unlock(root);
1085+ err = au_br_mod_files_ro(sb, bindex);
1086+ /* aufs_write_lock() calls ..._child() */
1087+ di_write_lock_child(root);
1088+#endif
1089+ }
1090+ } else if (au_br_writable(mod->perm)) {
1091+ /* ro --> rw */
1092+ err = -ENOMEM;
1093+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1094+ if (br->br_wbr) {
1095+ struct path path = {
1096+ .mnt = br->br_mnt,
1097+ .dentry = mod->h_root
1098+ };
1099+
1100+ err = au_wbr_init(br, sb, mod->perm, &path);
1101+ if (unlikely(err)) {
1102+ kfree(br->br_wbr);
1103+ br->br_wbr = NULL;
1104+ }
1105+ }
1106+ }
1107+
1108+ if (!err) {
1109+ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
1110+ br->br_perm = mod->perm;
1111+ }
1112+
1113+ out:
1114+ AuTraceErr(err);
1115+ return err;
1116+}
1117diff -urN linux/fs/aufs/branch.h linux-aufs/fs/aufs/branch.h
1118--- linux/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
1119+++ linux-aufs/fs/aufs/branch.h 2009-03-12 16:18:04.000000000 +0100
1120@@ -0,0 +1,437 @@
1121+/*
1122+ * Copyright (C) 2005-2009 Junjiro Okajima
1123+ *
1124+ * This program, aufs is free software; you can redistribute it and/or modify
1125+ * it under the terms of the GNU General Public License as published by
1126+ * the Free Software Foundation; either version 2 of the License, or
1127+ * (at your option) any later version.
1128+ *
1129+ * This program is distributed in the hope that it will be useful,
1130+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1131+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1132+ * GNU General Public License for more details.
1133+ *
1134+ * You should have received a copy of the GNU General Public License
1135+ * along with this program; if not, write to the Free Software
1136+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1137+ */
1138+
1139+/*
1140+ * branch filesystems and xino for them
1141+ *
1142+ * $Id$
1143+ */
1144+
1145+#ifndef __AUFS_BRANCH_H__
1146+#define __AUFS_BRANCH_H__
1147+
1148+#ifdef __KERNEL__
1149+
1150+#include <linux/fs.h>
1151+#include <linux/mount.h>
1152+#include <linux/sysfs.h>
1153+#include <linux/aufs_type.h>
1154+#include "misc.h"
1155+#include "super.h"
1156+
1157+/* ---------------------------------------------------------------------- */
1158+
1159+/* an entry in a xino file */
1160+struct au_xino_entry {
1161+ ino_t ino;
1162+ /* __u32 h_gen; */ /* reserved for future use */
1163+} __packed;
1164+
1165+/* reserved for future use */
1166+/* #define AuXino_INVALID_HGEN (-1) */
1167+
1168+/* a xino file */
1169+struct au_xino_file {
1170+ struct file *xi_file;
1171+ struct mutex xi_nondir_mtx;
1172+
1173+ /* reserved for future use */
1174+#if 0
1175+ struct file **xi_file;
1176+
1177+ /* array management */
1178+ unsigned long long xi_limit; /* Max xino file size */
1179+ unsigned long long xi_size; /* s_maxbytes */
1180+
1181+ /* truncation */
1182+ unsigned long long xi_upper; /* watermark in bytes */
1183+ unsigned long long xi_step; /* to next watermark in bytes */
1184+
1185+ /* truncation */
1186+ blkcnt_t xi_upper; /* watermark in blocks */
1187+ atomic_t xi_running;
1188+#endif
1189+};
1190+
1191+/* members for writable branch only */
1192+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_TMP, AuBrWh_Last};
1193+struct au_wbr {
1194+ struct au_rwsem wbr_wh_rwsem;
1195+ struct dentry *wbr_wh[AuBrWh_Last];
1196+ atomic_t wbr_wh_running;
1197+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
1198+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
1199+#define wbr_tmp wbr_wh[AuBrWh_TMP] /* temporary dir */
1200+
1201+ /* mfs mode */
1202+ unsigned long long wbr_bytes;
1203+};
1204+
1205+/* protected by superblock rwsem */
1206+struct au_branch {
1207+ struct au_xino_file br_xino;
1208+
1209+ aufs_bindex_t br_id;
1210+
1211+ int br_perm;
1212+ struct vfsmount *br_mnt;
1213+ atomic_t br_count;
1214+
1215+ struct au_wbr *br_wbr;
1216+
1217+#if 1 /* reserved for future use */
1218+ /* xino truncation */
1219+ blkcnt_t br_xino_upper; /* watermark in blocks */
1220+ atomic_t br_xino_running;
1221+#endif
1222+
1223+#ifdef CONFIG_SYSFS
1224+ /* an entry under sysfs per mount-point */
1225+ char br_name[8];
1226+ struct attribute br_attr;
1227+#endif
1228+
1229+ au_gen_t br_generation;
1230+};
1231+
1232+/* ---------------------------------------------------------------------- */
1233+
1234+/* branch permission and attribute */
1235+enum {
1236+ AuBrPerm_RW, /* writable, linkable wh */
1237+ AuBrPerm_RO, /* readonly, no wh */
1238+ AuBrPerm_RR, /* natively readonly, no wh */
1239+
1240+ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
1241+
1242+ AuBrPerm_ROWH,
1243+ AuBrPerm_RRWH, /* whiteout-able */
1244+
1245+ AuBrPerm_Last
1246+};
1247+
1248+static inline int au_br_writable(int brperm)
1249+{
1250+ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1251+}
1252+
1253+static inline int au_br_whable(int brperm)
1254+{
1255+ return brperm == AuBrPerm_RW
1256+ || brperm == AuBrPerm_ROWH
1257+ || brperm == AuBrPerm_RRWH;
1258+}
1259+
1260+#if 0 /* reserved for future use */
1261+static inline int au_br_linkable_wh(int brperm)
1262+{
1263+ return brperm == AuBrPerm_RW;
1264+}
1265+#endif
1266+
1267+static inline int au_br_hinotifyable(int brperm)
1268+{
1269+#ifdef CONFIG_AUFS_HINOTIFY
1270+ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1271+#else
1272+ return 0;
1273+#endif
1274+}
1275+
1276+/* ---------------------------------------------------------------------- */
1277+
1278+/* branch.c */
1279+struct au_sbinfo;
1280+void au_br_free(struct au_sbinfo *sinfo);
1281+int au_test_def_rr(struct super_block *h_sb);
1282+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1283+struct au_opt_add;
1284+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1285+struct au_opt_del;
1286+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
1287+struct au_opt_mod;
1288+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1289+ int *do_update);
1290+
1291+/* xino.c */
1292+#define Au_LOFF_MAX ((loff_t)LLONG_MAX)
1293+int au_xib_trunc(struct super_block *sb);
1294+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1295+ loff_t *pos);
1296+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1297+ loff_t *pos);
1298+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1299+struct file *au_xino_create2(struct super_block *sb, struct file *base_file,
1300+ struct file *copy_src);
1301+ino_t au_xino_new_ino(struct super_block *sb);
1302+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1303+ ino_t ino);
1304+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1305+ struct au_xino_entry *xinoe);
1306+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1307+ struct au_xino_entry *xinoe);
1308+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1309+ struct file *base_file, int do_test);
1310+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1311+
1312+struct au_opt_xino;
1313+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1314+void au_xino_clr(struct super_block *sb);
1315+struct file *au_xino_def(struct super_block *sb);
1316+
1317+struct au_opt_xinodir;
1318+#if 0 /* def CONFIG_AUFS_EXPORT */ /* reserved for future use */
1319+/* export.c */
1320+int au_xinodir_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1321+ int do_test);
1322+int au_xinodir_set(struct super_block *sb, struct au_opt_xinodir *xinodir,
1323+ int remount);
1324+#else
1325+static inline
1326+int au_xinodir_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1327+ int do_test)
1328+{
1329+ return 0;
1330+}
1331+
1332+static inline
1333+int au_xinodir_set(struct super_block *sb, struct au_opt_xinodir *xinodir,
1334+ int remount)
1335+{
1336+ return 0;
1337+}
1338+#endif
1339+
1340+/* ---------------------------------------------------------------------- */
1341+
1342+/* todo: memory barrier? */
1343+static inline int au_br_count(struct au_branch *br)
1344+{
1345+ return atomic_read(&br->br_count);
1346+}
1347+
1348+static inline int au_br_get(struct au_branch *br)
1349+{
1350+ return atomic_inc_return(&br->br_count);
1351+}
1352+
1353+static inline int au_br_put(struct au_branch *br)
1354+{
1355+ return atomic_dec_return(&br->br_count);
1356+}
1357+
1358+static inline au_gen_t au_br_gen(struct au_branch *br)
1359+{
1360+ return br->br_generation;
1361+}
1362+
1363+/*
1364+ * test if the @br is readonly or not.
1365+ */
1366+static inline int au_br_rdonly(struct au_branch *br)
1367+{
1368+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1369+ || !au_br_writable(br->br_perm))
1370+ ? -EROFS : 0;
1371+}
1372+
1373+/* ---------------------------------------------------------------------- */
1374+
1375+/* Superblock to branch */
1376+static inline
1377+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1378+{
1379+ return au_sbr(sb, bindex)->br_id;
1380+}
1381+
1382+static inline
1383+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1384+{
1385+ return au_sbr(sb, bindex)->br_mnt;
1386+}
1387+
1388+static inline
1389+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1390+{
1391+ return au_sbr_mnt(sb, bindex)->mnt_sb;
1392+}
1393+
1394+#if 0 /* reserved for future use */
1395+static inline int au_sbr_count(struct super_block *sb, aufs_bindex_t bindex)
1396+{
1397+ return au_br_count(au_sbr(sb, bindex));
1398+}
1399+
1400+static inline void au_sbr_get(struct super_block *sb, aufs_bindex_t bindex)
1401+{
1402+ au_br_get(au_sbr(sb, bindex));
1403+}
1404+#endif
1405+
1406+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1407+{
1408+ au_br_put(au_sbr(sb, bindex));
1409+}
1410+
1411+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1412+{
1413+ return au_sbr(sb, bindex)->br_perm;
1414+}
1415+
1416+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1417+{
1418+ return au_br_whable(au_sbr_perm(sb, bindex));
1419+}
1420+
1421+static inline int au_br_want_write(struct au_branch *br)
1422+{
1423+ int err;
1424+
1425+ AuDebugOn(!au_br_writable(br->br_perm));
1426+ err = au_mnt_want_write(br->br_mnt);
1427+ AuTraceErr(err);
1428+ return err;
1429+}
1430+
1431+static inline void au_br_drop_write(struct au_branch *br)
1432+{
1433+ AuDebugOn(!au_br_writable(br->br_perm));
1434+ au_mnt_drop_write(br->br_mnt);
1435+}
1436+
1437+static inline int au_test_trunc_xino(struct super_block *sb)
1438+{
1439+ return au_test_tmpfs(sb);
1440+}
1441+
1442+/* temporary support for i#1 in cramfs */
1443+static inline int au_test_unique_ino(struct dentry *h_dentry, ino_t h_ino)
1444+{
1445+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
1446+ if (unlikely(h_dentry->d_sb->s_magic == CRAMFS_MAGIC))
1447+ return h_ino != 1;
1448+#endif
1449+ return 1;
1450+}
1451+
1452+static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt)
1453+{
1454+ if (!au_test_nfs(h_mnt->mnt_sb)
1455+ && !au_test_ecryptfs(h_mnt->mnt_sb))
1456+ return NULL;
1457+ return h_mnt;
1458+}
1459+
1460+static inline void au_br_nfs_lockdep_off(struct super_block *sb)
1461+{
1462+ if (au_test_nfs(sb))
1463+ lockdep_off();
1464+}
1465+
1466+static inline void au_br_nfs_lockdep_on(struct super_block *sb)
1467+{
1468+ /* hoping this condition will be optimized... */
1469+ if (au_test_nfs(sb))
1470+ lockdep_on();
1471+}
1472+
1473+#ifdef CONFIG_AUFS_BR_NFS
1474+static inline int au_test_unsupported_nfs(struct super_block *h_sb)
1475+{
1476+ return 0;
1477+}
1478+
1479+/* it doesn't mntget() */
1480+static inline
1481+struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
1482+{
1483+ return au_do_nfsmnt(au_sbr_mnt(sb, bindex));
1484+}
1485+
1486+#define AuNoNfsBranchMsg "dummy"
1487+
1488+#else
1489+static inline int au_test_unsupported_nfs(struct super_block *h_sb)
1490+{
1491+ return h_sb->s_magic == NFS_SUPER_MAGIC;
1492+}
1493+
1494+/* it doesn't mntget() */
1495+static inline
1496+struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
1497+{
1498+ return NULL;
1499+}
1500+
1501+#define AuNoNfsBranchMsg "NFS branch is not supported" \
1502+ ", try some configurations and patches included in aufs source CVS."
1503+
1504+#endif /* CONFIG_AUFS_BR_NFS */
1505+
1506+#ifdef CONFIG_AUFS_BR_NFS_V4
1507+static inline int au_test_unsupported_nfs4(struct super_block *h_sb)
1508+{
1509+ return 0;
1510+}
1511+
1512+#define AuNoNfsv4BranchMsg "dummy"
1513+
1514+#else
1515+static inline int au_test_unsupported_nfs4(struct super_block *h_sb)
1516+{
1517+ return h_sb->s_magic == NFS_SUPER_MAGIC
1518+ && !strcmp(h_sb->s_type->name, "nfs4");
1519+}
1520+
1521+#define AuNoNfsv4BranchMsg "NFSv4 branch is not supported" \
1522+ ", try some configurations and patches included in aufs source CVS."
1523+
1524+#endif /* CONFIG_AUFS_BR_NFS_v4 */
1525+
1526+/* support atomic open */
1527+static inline int au_test_fs_intent(struct super_block *h_sb)
1528+{
1529+ return au_test_nfs4(h_sb) /*|| au_test_fuse(h_sb)*/;
1530+}
1531+
1532+/* ---------------------------------------------------------------------- */
1533+
1534+/*
1535+ * br_wh_read_lock, br_wh_write_lock
1536+ * br_wh_read_unlock, br_wh_write_unlock, br_wh_downgrade_lock
1537+ */
1538+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, wbr->wbr_wh_rwsem);
1539+
1540+/* to debug easier, do not make them inlined functions */
1541+#define WbrWhMustReadLock(wbr) do { \
1542+ /* SiMustAnyLock(sb); */ \
1543+ AuRwMustReadLock(&(wbr)->wbr_wh_rwsem); \
1544+} while (0)
1545+
1546+#define WbrWhMustWriteLock(wbr) do { \
1547+ /* SiMustAnyLock(sb); */ \
1548+ AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem); \
1549+} while (0)
1550+
1551+#define WbrWhMustAnyLock(br) do { \
1552+ /* SiMustAnyLock(sb); */ \
1553+ AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem); \
1554+} while (0)
1555+
1556+#endif /* __KERNEL__ */
1557+#endif /* __AUFS_BRANCH_H__ */
1558diff -urN linux/fs/aufs/br_fuse.c linux-aufs/fs/aufs/br_fuse.c
1559--- linux/fs/aufs/br_fuse.c 1970-01-01 01:00:00.000000000 +0100
1560+++ linux-aufs/fs/aufs/br_fuse.c 2009-03-12 16:18:04.000000000 +0100
1561@@ -0,0 +1,80 @@
1562+/*
1563+ * Copyright (C) 2005-2009 Junjiro Okajima
1564+ *
1565+ * This program, aufs is free software; you can redistribute it and/or modify
1566+ * it under the terms of the GNU General Public License as published by
1567+ * the Free Software Foundation; either version 2 of the License, or
1568+ * (at your option) any later version.
1569+ *
1570+ * This program is distributed in the hope that it will be useful,
1571+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1572+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1573+ * GNU General Public License for more details.
1574+ *
1575+ * You should have received a copy of the GNU General Public License
1576+ * along with this program; if not, write to the Free Software
1577+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1578+ */
1579+
1580+/*
1581+ * special handling for inode attributes on FUSE branch
1582+ *
1583+ * $Id$
1584+ */
1585+
1586+#include "aufs.h"
1587+
1588+/* h_mnt can be NULL, is it safe? */
1589+int au_update_fuse_h_inode(struct vfsmount *h_mnt, struct dentry *h_dentry)
1590+{
1591+ int err;
1592+ struct kstat st;
1593+
1594+ LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
1595+
1596+ err = 0;
1597+ if (h_dentry->d_inode
1598+ /* && atomic_read(&h_dentry->d_inode->i_count) */
1599+ && au_test_fuse(h_dentry->d_sb)) {
1600+ err = vfsub_getattr(h_mnt, h_dentry, &st, /*dlgt*/0);
1601+ if (unlikely(err)) {
1602+ AuDbg("err %d\n", err);
1603+ au_debug_on();
1604+ AuDbgDentry(h_dentry);
1605+ au_debug_off();
1606+ WARN_ON(err);
1607+ }
1608+ }
1609+ return err;
1610+}
1611+
1612+#if 0 /* temp */
1613+/*
1614+ * This function was born after a discussion with the FUSE developer.
1615+ * The inode attributes on a filesystem who defines i_op->getattr()
1616+ * is unreliable since such fs may not maintain the attributes at lookup.
1617+ * This function doesn't want the result of stat, instead wants the side-effect
1618+ * which refreshes the attributes.
1619+ * Hmm, there seems to be no such filesystem except fuse.
1620+ */
1621+int vfsub_i_attr(struct vfsmount *mnt, struct dentry *dentry, int dlgt)
1622+{
1623+ int err;
1624+ struct inode *inode;
1625+ struct inode_operations *op;
1626+ struct kstat st;
1627+
1628+ inode = dentry->d_inode;
1629+ AuDebugOn(!inode);
1630+
1631+ err = 0;
1632+ op = inode->i_op;
1633+ if (op && op->getattr && !au_test_aufs(dentry->d_sb)) {
1634+ err = security_inode_getattr(mnt, dentry);
1635+ if (!err)
1636+ err = op->getattr(mnt, dentry, &st);
1637+ }
1638+ AuTraceErr(err);
1639+ return err;
1640+}
1641+#endif
1642diff -urN linux/fs/aufs/br_nfs.c linux-aufs/fs/aufs/br_nfs.c
1643--- linux/fs/aufs/br_nfs.c 1970-01-01 01:00:00.000000000 +0100
1644+++ linux-aufs/fs/aufs/br_nfs.c 2009-03-12 16:18:04.000000000 +0100
1645@@ -0,0 +1,356 @@
1646+/*
1647+ * Copyright (C) 2005-2009 Junjiro Okajima
1648+ *
1649+ * This program, aufs is free software; you can redistribute it and/or modify
1650+ * it under the terms of the GNU General Public License as published by
1651+ * the Free Software Foundation; either version 2 of the License, or
1652+ * (at your option) any later version.
1653+ *
1654+ * This program is distributed in the hope that it will be useful,
1655+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1656+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1657+ * GNU General Public License for more details.
1658+ *
1659+ * You should have received a copy of the GNU General Public License
1660+ * along with this program; if not, write to the Free Software
1661+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1662+ */
1663+
1664+/*
1665+ * lookup functions for NFS branch in linux-2.6.19 and later
1666+ *
1667+ * $Id$
1668+ */
1669+
1670+#include "aufs.h"
1671+
1672+static struct file *au_find_h_intent(struct au_hdentry *hd, struct file *file)
1673+{
1674+ struct file *h_file, *hf;
1675+ struct au_hdintent *hdi, *tmp, *do_free;
1676+
1677+ LKTRTrace("%.*s\n", AuDLNPair(hd->hd_dentry));
1678+
1679+ h_file = NULL;
1680+ do_free = NULL;
1681+ spin_lock(&hd->hd_lock);
1682+ list_for_each_entry_safe(hdi, tmp, hd->hd_intent_list, hdi_list) {
1683+ hf = hdi->hdi_file[AuIntent_BRANCH];
1684+ if (hdi->hdi_file[AuIntent_AUFS] == file
1685+ && hf->f_dentry == hd->hd_dentry) {
1686+ h_file = hf;
1687+ do_free = hdi;
1688+ list_del(&hdi->hdi_list);
1689+ break;
1690+ }
1691+ }
1692+ spin_unlock(&hd->hd_lock);
1693+ kfree(do_free);
1694+
1695+ return h_file;
1696+}
1697+
1698+struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
1699+ struct file *file)
1700+{
1701+ struct file *h_file;
1702+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
1703+
1704+ LKTRTrace("%.*s, b%d, f %p\n", AuDLNPair(dentry), bindex, file);
1705+ DiMustAnyLock(dentry);
1706+ AuDebugOn(bindex < au_di(dentry)->di_bstart
1707+ || bindex > au_di(dentry)->di_bend);
1708+
1709+ h_file = NULL;
1710+ if (!hd->hd_intent_list || !file)
1711+ return h_file; /* success */
1712+
1713+ /* AuDebugOn(au_test_wkq(current)); */
1714+ h_file = au_find_h_intent(hd, file);
1715+ return h_file;
1716+}
1717+
1718+static int au_set_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
1719+ struct file *file, struct file *h_file)
1720+{
1721+ int err;
1722+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
1723+ struct au_hdintent *hdi;
1724+ struct file *hf;
1725+
1726+ LKTRTrace("%.*s, b%d, f %p\n", AuDLNPair(dentry), bindex, file);
1727+ /* d_revalidate() holds read_lock */
1728+ /* DiMustWriteLock(dentry); */
1729+ AuDebugOn(bindex < au_di(dentry)->di_bstart
1730+ || bindex > au_di(dentry)->di_bend
1731+ || !file
1732+ || !h_file
1733+ /* || au_test_wkq(current) */);
1734+
1735+ err = -ENOMEM;
1736+ if (hd->hd_intent_list) {
1737+ while (1) {
1738+ hf = au_find_h_intent(hd, file);
1739+ if (!hf)
1740+ break;
1741+ fput(hf);
1742+ AuWarn("freed hfile %.*s b%d left\n",
1743+ AuDLNPair(dentry), bindex);
1744+ }
1745+ } else {
1746+ spin_lock(&hd->hd_lock);
1747+ if (!hd->hd_intent_list) {
1748+ hd->hd_intent_list
1749+ = kmalloc(sizeof(*hd->hd_intent_list),
1750+ GFP_ATOMIC);
1751+ if (unlikely(!hd->hd_intent_list)) {
1752+ spin_unlock(&hd->hd_lock);
1753+ goto out;
1754+ }
1755+ INIT_LIST_HEAD(hd->hd_intent_list);
1756+ }
1757+ spin_unlock(&hd->hd_lock);
1758+ }
1759+
1760+ hdi = kmalloc(sizeof(*hdi), GFP_NOFS);
1761+ if (unlikely(!hdi))
1762+ goto out;
1763+
1764+ err = 0;
1765+ /* hdi->hdi_pid = current->pid; */
1766+ hdi->hdi_file[AuIntent_AUFS] = file;
1767+ hdi->hdi_file[AuIntent_BRANCH] = h_file;
1768+ spin_lock(&hd->hd_lock);
1769+ list_add(&hdi->hdi_list, hd->hd_intent_list);
1770+ spin_unlock(&hd->hd_lock);
1771+
1772+ out:
1773+ AuTraceErr(err);
1774+ return err;
1775+}
1776+
1777+int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry,
1778+ aufs_bindex_t bindex, struct nameidata *nd)
1779+{
1780+ int err;
1781+
1782+ AuTraceEnter();
1783+
1784+ err = 0;
1785+ if (!nd_file)
1786+ goto out;
1787+
1788+ AuDebugOn(!nd);
1789+ err = au_set_h_intent(dentry, bindex, nd->intent.open.file, nd_file);
1790+ if (unlikely(err)) {
1791+ fput(nd_file);
1792+ au_set_h_dptr(dentry, bindex, NULL);
1793+ /* todo: update bstart and bend? */
1794+ }
1795+
1796+ out:
1797+ AuTraceErr(err);
1798+ return err;
1799+}
1800+
1801+/* ---------------------------------------------------------------------- */
1802+
1803+void au_hintent_put(struct au_hdentry *hd, int do_free)
1804+{
1805+ struct au_hdintent *hdi, *tmp;
1806+ struct file *hf;
1807+
1808+ if (hd->hd_intent_list) {
1809+ /* no spin lock */
1810+ list_for_each_entry_safe(hdi, tmp, hd->hd_intent_list,
1811+ hdi_list) {
1812+ LKTRTrace("hdi %p\n", hdi);
1813+ hf = hdi->hdi_file[AuIntent_BRANCH];
1814+ if (hf)
1815+ fput(hf);
1816+ /* list_del(&hdi->hdi_list); */
1817+ kfree(hdi);
1818+ }
1819+ if (do_free)
1820+ kfree(hd->hd_intent_list);
1821+ }
1822+}
1823+
1824+/* ---------------------------------------------------------------------- */
1825+
1826+int au_fake_intent(/* struct au_ndsub *save, */struct nameidata *nd,
1827+ struct au_branch *br)
1828+{
1829+ int err;
1830+
1831+ LKTRTrace("perm %d\n", br->br_perm);
1832+
1833+ err = 0;
1834+ nd->intent.open.file = NULL;
1835+ if (nd->flags & LOOKUP_OPEN) {
1836+ if (au_test_fs_intent(br->br_mnt->mnt_sb)) {
1837+ err = -ENFILE;
1838+ nd->intent.open.file = get_empty_filp();
1839+ if (unlikely(!nd->intent.open.file))
1840+ goto out;
1841+ err = 0;
1842+ }
1843+ if (!au_br_writable(br->br_perm)) {
1844+ nd->intent.open.flags = FMODE_READ
1845+ | au_file_roflags(nd->intent.open.flags);
1846+ nd->flags &= ~LOOKUP_CREATE;
1847+ }
1848+ }
1849+
1850+ out:
1851+ AuTraceErr(err);
1852+ return err;
1853+}
1854+
1855+static void au_put_filp(struct file *file)
1856+{
1857+#if !defined(CONFIG_AUFS_MODULE) || defined(CONFIG_AUFS_PUT_FILP_PATCH)
1858+ if (unlikely(file))
1859+ put_filp(file);
1860+#else
1861+ WARN_ONCE(file, "unexpected put_fillp() call");
1862+#endif
1863+}
1864+
1865+int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry,
1866+ aufs_bindex_t bindex, struct file *file)
1867+{
1868+ int err;
1869+
1870+ LKTRTrace("nd %p, %.*s, b%d, f %d\n",
1871+ nd, AuDLNPair(dentry), bindex, !!file);
1872+
1873+ err = 0;
1874+ if ((nd->flags & LOOKUP_OPEN)
1875+ && nd->intent.open.file
1876+ && !IS_ERR(nd->intent.open.file)) {
1877+ if (nd->intent.open.file->f_dentry) {
1878+ err = au_set_h_intent(dentry, bindex, file,
1879+ nd->intent.open.file);
1880+ if (!err)
1881+ nd->intent.open.file = NULL;
1882+ }
1883+ au_put_filp(nd->intent.open.file);
1884+ }
1885+
1886+ return err;
1887+}
1888+
1889+#ifdef CONFIG_AUFS_DLGT
1890+struct au_lookup_hash_args {
1891+ struct dentry **errp;
1892+ struct qstr *name;
1893+ struct dentry *base;
1894+ struct nameidata *nd;
1895+};
1896+
1897+static void au_call_lookup_hash(void *args)
1898+{
1899+ struct au_lookup_hash_args *a = args;
1900+ *a->errp = vfsub__lookup_hash(a->name, a->base, a->nd);
1901+}
1902+
1903+static struct dentry *
1904+au_lkup_hash_dlgt(struct qstr *this, struct dentry *parent,
1905+ struct nameidata *nd, unsigned int flags)
1906+{
1907+ struct dentry *dentry;
1908+ int dirperm1;
1909+
1910+ dirperm1 = au_ftest_ndx(flags, DIRPERM1);
1911+ if (!dirperm1 && !au_ftest_ndx(flags, DLGT))
1912+ dentry = vfsub__lookup_hash(this, parent, nd);
1913+ else {
1914+ int wkq_err;
1915+ struct au_lookup_hash_args args = {
1916+ .errp = &dentry,
1917+ .name = this,
1918+ .base = parent,
1919+ .nd = nd
1920+ };
1921+ wkq_err = au_wkq_wait(au_call_lookup_hash, &args,
1922+ /*dlgt*/!dirperm1);
1923+ if (unlikely(wkq_err))
1924+ dentry = ERR_PTR(wkq_err);
1925+ }
1926+
1927+ AuTraceErrPtr(dentry);
1928+ return dentry;
1929+}
1930+#else
1931+static struct dentry *
1932+au_lkup_hash_dlgt(struct qstr *this, struct dentry *parent,
1933+ struct nameidata *nd, unsigned int flags)
1934+{
1935+ return vfsub__lookup_hash(this, parent, nd);
1936+}
1937+#endif /* CONFIG_AUFS_DLGT */
1938+
1939+struct dentry *au_lkup_hash(const char *name, struct dentry *parent,
1940+ int len, struct au_ndx *ndx)
1941+{
1942+ struct dentry *dentry;
1943+ char *p;
1944+ unsigned long hash;
1945+ struct qstr this;
1946+ unsigned int c;
1947+ struct nameidata tmp_nd, *ndo;
1948+ int err;
1949+
1950+ LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name);
1951+
1952+ /* todo: export and call __lookup_one_len() in fs/namei.c? */
1953+ dentry = ERR_PTR(-EACCES);
1954+ this.name = name;
1955+ this.len = len;
1956+ if (unlikely(!len))
1957+ goto out;
1958+
1959+ p = (void *)name;
1960+ hash = init_name_hash();
1961+ while (len--) {
1962+ c = *p++;
1963+ if (unlikely(c == '/' || c == '\0'))
1964+ goto out;
1965+ hash = partial_name_hash(c, hash);
1966+ }
1967+ this.hash = end_name_hash(hash);
1968+
1969+ ndo = ndx->nd;
1970+ if (ndo) {
1971+ tmp_nd = *ndo;
1972+ err = au_fake_intent(&tmp_nd, ndx->br);
1973+ dentry = ERR_PTR(err);
1974+ if (unlikely(err))
1975+ goto out_intent;
1976+ } else
1977+ memset(&tmp_nd, 0, sizeof(tmp_nd));
1978+
1979+ tmp_nd.path.dentry = parent;
1980+ tmp_nd.path.mnt = ndx->nfsmnt;
1981+ path_get(&tmp_nd.path);
1982+ dentry = au_lkup_hash_dlgt(&this, parent, &tmp_nd, ndx->flags);
1983+ if (!IS_ERR(dentry)) {
1984+ /* why negative dentry for a new dir was unhashed? */
1985+ if (unlikely(d_unhashed(dentry)))
1986+ d_rehash(dentry);
1987+ if (tmp_nd.intent.open.file
1988+ && tmp_nd.intent.open.file->f_dentry) {
1989+ ndx->nd_file = tmp_nd.intent.open.file;
1990+ tmp_nd.intent.open.file = NULL;
1991+ /* au_br_get(ndx->br); */
1992+ }
1993+ }
1994+ path_put(&tmp_nd.path);
1995+
1996+ out_intent:
1997+ au_put_filp(tmp_nd.intent.open.file);
1998+ out:
1999+ AuTraceErrPtr(dentry);
2000+ return dentry;
2001+}
2002diff -urN linux/fs/aufs/br_xfs.c linux-aufs/fs/aufs/br_xfs.c
2003--- linux/fs/aufs/br_xfs.c 1970-01-01 01:00:00.000000000 +0100
2004+++ linux-aufs/fs/aufs/br_xfs.c 2009-03-12 16:18:04.000000000 +0100
2005@@ -0,0 +1,69 @@
2006+/*
2007+ * Copyright (C) 2005-2009 Junjiro Okajima
2008+ *
2009+ * This program, aufs is free software; you can redistribute it and/or modify
2010+ * it under the terms of the GNU General Public License as published by
2011+ * the Free Software Foundation; either version 2 of the License, or
2012+ * (at your option) any later version.
2013+ *
2014+ * This program is distributed in the hope that it will be useful,
2015+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2016+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2017+ * GNU General Public License for more details.
2018+ *
2019+ * You should have received a copy of the GNU General Public License
2020+ * along with this program; if not, write to the Free Software
2021+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2022+ */
2023+
2024+/*
2025+ * special handling inode attributes on XFS branch in linux-2.6.24 and later
2026+ *
2027+ * $Id$
2028+ */
2029+
2030+#include "aufs.h"
2031+
2032+/* h_mnt can be NULL, is it safe? */
2033+dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt,
2034+ struct dentry *h_dentry)
2035+{
2036+ dev_t rdev;
2037+ int err;
2038+ struct kstat st;
2039+
2040+ LKTRTrace("hi%lu\n", h_inode->i_ino);
2041+ if (h_dentry)
2042+ LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
2043+
2044+ rdev = h_inode->i_rdev;
2045+ if (!rdev || !au_test_xfs(h_inode->i_sb))
2046+ goto out;
2047+
2048+ rdev = 0;
2049+ if (!h_dentry) {
2050+ err = 0;
2051+ h_dentry = d_find_alias(h_inode);
2052+ if (unlikely(!h_dentry))
2053+ goto failure;
2054+ err = PTR_ERR(h_dentry);
2055+ if (IS_ERR(h_dentry)) {
2056+ h_dentry = NULL;
2057+ goto failure;
2058+ }
2059+ LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
2060+ } else
2061+ dget(h_dentry);
2062+
2063+ err = vfsub_getattr(h_mnt, h_dentry, &st, /*dlgt*/0);
2064+ dput(h_dentry);
2065+ if (!err) {
2066+ rdev = st.rdev;
2067+ goto out; /* success */
2068+ }
2069+
2070+ failure:
2071+ AuIOErr("failed rdev for XFS inode, hi%lu, %d\n", h_inode->i_ino, err);
2072+ out:
2073+ return rdev;
2074+}
2075diff -urN linux/fs/aufs/cpup.c linux-aufs/fs/aufs/cpup.c
2076--- linux/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
2077+++ linux-aufs/fs/aufs/cpup.c 2009-03-12 16:18:04.000000000 +0100
2078@@ -0,0 +1,1132 @@
2079+/*
2080+ * Copyright (C) 2005-2009 Junjiro Okajima
2081+ *
2082+ * This program, aufs is free software; you can redistribute it and/or modify
2083+ * it under the terms of the GNU General Public License as published by
2084+ * the Free Software Foundation; either version 2 of the License, or
2085+ * (at your option) any later version.
2086+ *
2087+ * This program is distributed in the hope that it will be useful,
2088+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2089+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2090+ * GNU General Public License for more details.
2091+ *
2092+ * You should have received a copy of the GNU General Public License
2093+ * along with this program; if not, write to the Free Software
2094+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2095+ */
2096+
2097+/*
2098+ * copy-up functions, see wbr_policy.c for copy-down
2099+ *
2100+ * $Id$
2101+ */
2102+
2103+#include <linux/fs_stack.h>
2104+#include <linux/uaccess.h>
2105+#include "aufs.h"
2106+
2107+/* todo? violent cpup_attr_*() functions don't care inode lock */
2108+
2109+void au_cpup_attr_timesizes(struct inode *inode)
2110+{
2111+ struct inode *h_inode;
2112+
2113+ LKTRTrace("i%lu\n", inode->i_ino);
2114+ /* todo? IMustLock(inode); */
2115+ h_inode = au_h_iptr(inode, au_ibstart(inode));
2116+ AuDebugOn(!h_inode);
2117+ /* todo? IMustLock(!h_inode); */
2118+
2119+ fsstack_copy_attr_times(inode, h_inode);
2120+ vfsub_copy_inode_size(inode, h_inode);
2121+}
2122+
2123+void au_cpup_attr_nlink(struct inode *inode, int force)
2124+{
2125+ struct inode *h_inode;
2126+ struct super_block *sb;
2127+ aufs_bindex_t bindex, bend;
2128+
2129+ LKTRTrace("i%lu\n", inode->i_ino);
2130+ /* todo? IMustLock(inode); */
2131+ AuDebugOn(!inode->i_mode);
2132+
2133+ sb = inode->i_sb;
2134+ bindex = au_ibstart(inode);
2135+ h_inode = au_h_iptr(inode, bindex);
2136+
2137+ if (!force
2138+ && !S_ISDIR(h_inode->i_mode)
2139+ && au_opt_test(au_mntflags(sb), PLINK)
2140+ && au_plink_test(sb, inode))
2141+ return;
2142+
2143+ inode->i_nlink = h_inode->i_nlink;
2144+
2145+ /*
2146+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
2147+ * it may includes whplink directory.
2148+ */
2149+ if (S_ISDIR(h_inode->i_mode)) {
2150+ bend = au_ibend(inode);
2151+ for (bindex++; bindex <= bend; bindex++) {
2152+ h_inode = au_h_iptr(inode, bindex);
2153+ if (h_inode)
2154+ au_add_nlink(inode, h_inode);
2155+ }
2156+ }
2157+}
2158+
2159+void au_cpup_attr_changeable(struct inode *inode)
2160+{
2161+ struct inode *h_inode;
2162+
2163+ LKTRTrace("i%lu\n", inode->i_ino);
2164+ /* todo? IMustLock(inode); */
2165+ h_inode = au_h_iptr(inode, au_ibstart(inode));
2166+ AuDebugOn(!h_inode);
2167+
2168+ inode->i_mode = h_inode->i_mode;
2169+ inode->i_uid = h_inode->i_uid;
2170+ inode->i_gid = h_inode->i_gid;
2171+ au_cpup_attr_timesizes(inode);
2172+ au_cpup_attr_flags(inode, h_inode);
2173+}
2174+
2175+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
2176+{
2177+ struct au_iinfo *iinfo = au_ii(inode);
2178+ iinfo->ii_higen = h_inode->i_generation;
2179+ iinfo->ii_hsb1 = h_inode->i_sb;
2180+}
2181+
2182+void au_cpup_attr_all(struct inode *inode, int force)
2183+{
2184+ struct inode *h_inode;
2185+
2186+ LKTRTrace("i%lu\n", inode->i_ino);
2187+ /* todo? IMustLock(inode); */
2188+ h_inode = au_h_iptr(inode, au_ibstart(inode));
2189+ AuDebugOn(!h_inode);
2190+
2191+ au_cpup_attr_changeable(inode);
2192+ if (inode->i_nlink > 0)
2193+ au_cpup_attr_nlink(inode, force);
2194+
2195+ switch (inode->i_mode & S_IFMT) {
2196+ case S_IFBLK:
2197+ case S_IFCHR:
2198+ inode->i_rdev = au_h_rdev(h_inode, /*h_mnt*/NULL,
2199+ /*h_dentry*/NULL);
2200+ }
2201+ inode->i_blkbits = h_inode->i_blkbits;
2202+ au_cpup_igen(inode, h_inode);
2203+}
2204+
2205+/* ---------------------------------------------------------------------- */
2206+
2207+/* Note: dt_dentry and dt_hidden_dentry are not dget/dput-ed */
2208+
2209+/* keep the timestamps of the parent dir when cpup */
2210+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
2211+ struct dentry *h_dentry, struct au_hinode *hinode,
2212+ struct au_hinode *hdir)
2213+{
2214+ struct inode *h_inode;
2215+
2216+ LKTRTrace("%.*s, hdir %d\n", AuDLNPair(dentry), !!hdir);
2217+ AuDebugOn(!dentry || !h_dentry || !h_dentry->d_inode);
2218+
2219+ dt->dt_dentry = dentry;
2220+ dt->dt_h_dentry = h_dentry;
2221+ dt->dt_hinode = hinode;
2222+ dt->dt_hdir = hdir;
2223+ h_inode = h_dentry->d_inode;
2224+ dt->dt_atime = h_inode->i_atime;
2225+ dt->dt_mtime = h_inode->i_mtime;
2226+ /* smp_mb(); */
2227+}
2228+
2229+void au_dtime_revert(struct au_dtime *dt)
2230+{
2231+ struct iattr attr;
2232+ int err;
2233+ struct au_hin_ignore ign[2];
2234+ struct vfsub_args vargs;
2235+
2236+ LKTRTrace("%.*s\n", AuDLNPair(dt->dt_dentry));
2237+
2238+ attr.ia_atime = dt->dt_atime;
2239+ attr.ia_mtime = dt->dt_mtime;
2240+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
2241+ | ATTR_ATIME | ATTR_ATIME_SET;
2242+
2243+ vfsub_args_init(&vargs, ign,
2244+ au_test_dlgt(au_mntflags(dt->dt_dentry->d_sb)), 0);
2245+ /*
2246+ * IN_ATTRIB should be divided into
2247+ * IN_ATTRIB_ATIME, IN_ATTRIB_MTIME ...,
2248+ * and define all ORed new IN_ATTRIB macro.
2249+ */
2250+ vfsub_ign_hinode(&vargs, IN_ATTRIB, dt->dt_hinode);
2251+ vfsub_ign_hinode(&vargs, IN_ATTRIB, dt->dt_hdir);
2252+ err = vfsub_notify_change(dt->dt_h_dentry, &attr, &vargs);
2253+ if (unlikely(err))
2254+ AuWarn("restoring timestamps failed(%d). ignored\n", err);
2255+}
2256+
2257+/* ---------------------------------------------------------------------- */
2258+
2259+static noinline_for_stack
2260+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src,
2261+ struct au_hinode *hdir, struct vfsub_args *vargs)
2262+{
2263+ int err, sbits;
2264+ struct dentry *h_dst;
2265+ struct iattr ia;
2266+ struct inode *h_isrc, *h_idst;
2267+
2268+ h_dst = au_h_dptr(dst, bindex);
2269+ LKTRTrace("%.*s\n", AuDLNPair(h_dst));
2270+ h_idst = h_dst->d_inode;
2271+ /* todo? IMustLock(h_idst); */
2272+ h_isrc = h_src->d_inode;
2273+ /* todo? IMustLock(h_isrc); */
2274+
2275+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
2276+ | ATTR_ATIME | ATTR_MTIME
2277+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
2278+ ia.ia_mode = h_isrc->i_mode;
2279+ ia.ia_uid = h_isrc->i_uid;
2280+ ia.ia_gid = h_isrc->i_gid;
2281+ ia.ia_atime = h_isrc->i_atime;
2282+ ia.ia_mtime = h_isrc->i_mtime;
2283+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
2284+ au_cpup_attr_flags(h_idst, h_isrc);
2285+
2286+ vfsub_args_reinit(vargs);
2287+ vfsub_ign_hinode(vargs, IN_ATTRIB, hdir);
2288+ err = vfsub_notify_change(h_dst, &ia, vargs);
2289+
2290+ /* is this nfs only? */
2291+ if (!err && sbits && au_test_nfs(h_dst->d_sb)) {
2292+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
2293+ ia.ia_mode = h_isrc->i_mode;
2294+ vfsub_args_reinit(vargs);
2295+ vfsub_ign_hinode(vargs, IN_ATTRIB, hdir);
2296+ err = vfsub_notify_change(h_dst, &ia, vargs);
2297+ }
2298+
2299+ AuTraceErr(err);
2300+ return err;
2301+}
2302+
2303+/*
2304+ * to support a sparse file which is opened with O_APPEND,
2305+ * we need to close the file.
2306+ */
2307+static noinline_for_stack
2308+int cpup_regular(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
2309+ loff_t len, struct au_hinode *hdir, struct vfsub_args *vargs)
2310+{
2311+ int err, i;
2312+ struct super_block *sb;
2313+ struct inode *h_inode;
2314+ enum { SRC, DST };
2315+ struct {
2316+ aufs_bindex_t bindex;
2317+ unsigned int flags;
2318+ struct dentry *dentry;
2319+ struct file *file;
2320+ void *label, *label_file;
2321+ } *h, hidden[] = {
2322+ {
2323+ .bindex = bsrc,
2324+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
2325+ .file = NULL,
2326+ .label = &&out,
2327+ .label_file = &&out_src_file
2328+ },
2329+ {
2330+ .bindex = bdst,
2331+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
2332+ .file = NULL,
2333+ .label = &&out_src_file,
2334+ .label_file = &&out_dst_file
2335+ }
2336+ };
2337+
2338+ LKTRTrace("dentry %.*s, bdst %d, bsrc %d, len %lld\n",
2339+ AuDLNPair(dentry), bdst, bsrc, len);
2340+ AuDebugOn(bsrc <= bdst);
2341+ AuDebugOn(!len);
2342+ sb = dentry->d_sb;
2343+ AuDebugOn(au_test_ro(sb, bdst, dentry->d_inode));
2344+ /* bsrc branch can be ro/rw. */
2345+
2346+ h = hidden;
2347+ for (i = 0; i < 2; i++, h++) {
2348+ h->dentry = au_h_dptr(dentry, h->bindex);
2349+ AuDebugOn(!h->dentry);
2350+ h_inode = h->dentry->d_inode;
2351+ AuDebugOn(!h_inode || !S_ISREG(h_inode->i_mode));
2352+ h->file = au_h_open(dentry, h->bindex, h->flags, /*file*/NULL);
2353+ err = PTR_ERR(h->file);
2354+ if (IS_ERR(h->file))
2355+ goto *h->label;
2356+ err = -EINVAL;
2357+ if (unlikely(!h->file->f_op))
2358+ goto *h->label_file;
2359+ }
2360+
2361+ /* stop updating while we copyup */
2362+ IMustLock(hidden[SRC].dentry->d_inode);
2363+ err = au_copy_file(hidden[DST].file, hidden[SRC].file, len, hdir, sb,
2364+ vargs);
2365+
2366+ out_dst_file:
2367+ fput(hidden[DST].file);
2368+ au_sbr_put(sb, hidden[DST].bindex);
2369+ out_src_file:
2370+ fput(hidden[SRC].file);
2371+ au_sbr_put(sb, hidden[SRC].bindex);
2372+ out:
2373+ AuTraceErr(err);
2374+ return err;
2375+}
2376+
2377+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
2378+ aufs_bindex_t bsrc, loff_t len,
2379+ struct au_hinode *hdir, struct dentry *h_dst,
2380+ struct vfsub_args *vargs)
2381+{
2382+ int err, rerr;
2383+ loff_t l;
2384+
2385+ AuTraceEnter();
2386+
2387+ err = 0;
2388+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
2389+ if (len == -1 || l < len)
2390+ len = l;
2391+ if (len)
2392+ err = cpup_regular(dentry, bdst, bsrc, len, hdir, vargs);
2393+ if (!err)
2394+ goto out; /* success */
2395+
2396+ vfsub_args_reinit(vargs);
2397+ vfsub_ign_hinode(vargs, IN_DELETE, hdir);
2398+ rerr = vfsub_unlink(hdir->hi_inode, h_dst, vargs);
2399+ if (rerr) {
2400+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
2401+ AuDLNPair(h_dst), err, rerr);
2402+ err = -EIO;
2403+ }
2404+
2405+ out:
2406+ AuTraceErr(err);
2407+ return err;
2408+}
2409+
2410+static int au_do_cpup_symlink(struct dentry *h_dst, struct dentry *h_src,
2411+ struct inode *h_dir, umode_t mode,
2412+ struct vfsub_args *vargs)
2413+{
2414+ int err, symlen;
2415+ char *sym;
2416+ mm_segment_t old_fs;
2417+
2418+ AuTraceEnter();
2419+
2420+ err = -ENOMEM;
2421+ sym = __getname();
2422+ if (unlikely(!sym))
2423+ goto out;
2424+
2425+ old_fs = get_fs();
2426+ set_fs(KERNEL_DS);
2427+ symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
2428+ PATH_MAX);
2429+ err = symlen;
2430+ set_fs(old_fs);
2431+
2432+ if (symlen > 0) {
2433+ sym[symlen] = 0;
2434+ err = vfsub_symlink(h_dir, h_dst, sym, mode, vargs);
2435+ }
2436+ __putname(sym);
2437+
2438+ out:
2439+ AuTraceErr(err);
2440+ return err;
2441+}
2442+
2443+/* return with hidden dst inode is locked */
2444+static noinline_for_stack
2445+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
2446+ loff_t len, unsigned int flags, struct dentry *dst_parent,
2447+ struct vfsub_args *vargs)
2448+{
2449+ int err;
2450+ unsigned char isdir, hinotify;
2451+ struct dentry *h_src, *h_dst, *h_parent, *gparent;
2452+ struct inode *h_inode, *h_dir;
2453+ struct au_dtime dt;
2454+ umode_t mode;
2455+ struct super_block *sb;
2456+ struct au_hinode *hgdir, *hdir;
2457+ unsigned int mnt_flags;
2458+ const int do_dt = au_ftest_cpup(flags, DTIME);
2459+
2460+ LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %lld, dtime %u\n",
2461+ AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
2462+ do_dt);
2463+ sb = dentry->d_sb;
2464+ AuDebugOn(bdst >= bsrc || au_test_ro(sb, bdst, NULL));
2465+ /* bsrc branch can be ro/rw. */
2466+
2467+ h_src = au_h_dptr(dentry, bsrc);
2468+ AuDebugOn(!h_src);
2469+ h_inode = h_src->d_inode;
2470+ AuDebugOn(!h_inode);
2471+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
2472+
2473+ /* stop referencing while we are creating */
2474+ h_dst = au_h_dptr(dentry, bdst);
2475+ AuDebugOn(h_dst && h_dst->d_inode);
2476+ h_parent = h_dst->d_parent; /* dir inode is locked */
2477+ h_dir = h_parent->d_inode;
2478+ IMustLock(h_dir);
2479+ AuDebugOn(h_parent != h_dst->d_parent);
2480+
2481+ hdir = NULL;
2482+ mnt_flags = au_mntflags(sb);
2483+ hinotify = !!au_opt_test(mnt_flags, UDBA_INOTIFY);
2484+ if (hinotify) {
2485+ hdir = au_hi(dst_parent->d_inode, bdst);
2486+ AuDebugOn(hdir->hi_inode != h_dir);
2487+ }
2488+
2489+ if (do_dt) {
2490+ hgdir = NULL;
2491+ if (hinotify && !IS_ROOT(dst_parent)) {
2492+ gparent = dget_parent(dst_parent);
2493+ hgdir = au_hi(gparent->d_inode, bdst);
2494+ IMustLock(hgdir->hi_inode);
2495+ dput(gparent);
2496+ }
2497+ au_dtime_store(&dt, dst_parent, h_parent, hdir, hgdir);
2498+ }
2499+
2500+ isdir = 0;
2501+ vfsub_args_reinit(vargs);
2502+ vfsub_ign_hinode(vargs, IN_CREATE, hdir);
2503+ mode = h_inode->i_mode;
2504+ switch (mode & S_IFMT) {
2505+ case S_IFREG:
2506+ /* stop updating while we are referencing */
2507+ IMustLock(h_inode);
2508+ err = au_h_create(h_dir, h_dst, mode | S_IWUSR, vargs, NULL,
2509+ au_nfsmnt(sb, bdst));
2510+ if (!err)
2511+ err = au_do_cpup_regular(dentry, bdst, bsrc, len,
2512+ hdir, h_dst, vargs);
2513+ break;
2514+ case S_IFDIR:
2515+ isdir = 1;
2516+ err = vfsub_mkdir(h_dir, h_dst, mode, vargs);
2517+ if (!err) {
2518+ /* setattr case: dir is not locked */
2519+ if (0 && au_ibstart(dst_parent->d_inode) == bdst)
2520+ au_cpup_attr_nlink(dst_parent->d_inode,
2521+ /*force*/1);
2522+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
2523+ }
2524+ break;
2525+ case S_IFLNK:
2526+ err = au_do_cpup_symlink(h_dst, h_src, h_dir, mode, vargs);
2527+ break;
2528+ case S_IFCHR:
2529+ case S_IFBLK:
2530+ AuDebugOn(!capable(CAP_MKNOD));
2531+ /*FALLTHROUGH*/
2532+ case S_IFIFO:
2533+ case S_IFSOCK:
2534+ err = vfsub_mknod(h_dir, h_dst, mode,
2535+ au_h_rdev(h_inode, /*h_mnt*/NULL, h_src),
2536+ vargs);
2537+ break;
2538+ default:
2539+ AuIOErr("Unknown inode type 0%o\n", mode);
2540+ err = -EIO;
2541+ }
2542+
2543+ if (hinotify
2544+ && !isdir
2545+ && au_opt_test_xino(mnt_flags)
2546+ && h_inode->i_nlink == 1
2547+ /* todo: unnecessary? */
2548+ /* && dentry->d_inode->i_nlink == 1 */
2549+ && bdst < bsrc
2550+ && !au_ftest_cpup(flags, KEEPLINO))
2551+ au_xino_write0(sb, bsrc, h_inode->i_ino, /*ino*/0);
2552+ /* ignore this error */
2553+
2554+ if (do_dt)
2555+ au_dtime_revert(&dt);
2556+ AuTraceErr(err);
2557+ return err;
2558+}
2559+
2560+/*
2561+ * copyup the @dentry from @bsrc to @bdst.
2562+ * the caller must set the both of hidden dentries.
2563+ * @len is for truncating when it is -1 copyup the entire file.
2564+ */
2565+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2566+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2567+ struct dentry *dst_parent, struct vfsub_args *vargs)
2568+{
2569+ int err, rerr;
2570+ unsigned int mnt_flags;
2571+ aufs_bindex_t old_ibstart;
2572+ unsigned char isdir, plink, hinotify;
2573+ struct au_dtime dt;
2574+ struct dentry *h_src, *h_dst, *h_parent, *gparent;
2575+ struct inode *dst_inode, *h_dir, *inode;
2576+ struct super_block *sb;
2577+ struct au_hinode *hgdir, *hdir;
2578+
2579+ LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %lld, flags 0x%x\n",
2580+ AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
2581+ flags);
2582+ sb = dentry->d_sb;
2583+ AuDebugOn(bsrc <= bdst);
2584+ h_dst = au_h_dptr(dentry, bdst);
2585+ AuDebugOn(!h_dst || h_dst->d_inode);
2586+ h_parent = h_dst->d_parent; /* dir inode is locked */
2587+ h_dir = h_parent->d_inode;
2588+ IMustLock(h_dir);
2589+ h_src = au_h_dptr(dentry, bsrc);
2590+ AuDebugOn(!h_src || !h_src->d_inode);
2591+ inode = dentry->d_inode;
2592+ IiMustWriteLock(inode);
2593+ if (!dst_parent)
2594+ dst_parent = dget_parent(dentry);
2595+ else
2596+ dget(dst_parent);
2597+
2598+ mnt_flags = au_mntflags(sb);
2599+ plink = !!au_opt_test(mnt_flags, PLINK);
2600+ hinotify = !!au_opt_test(mnt_flags, UDBA_INOTIFY);
2601+ hdir = NULL;
2602+ if (hinotify)
2603+ hdir = au_hi(dst_parent->d_inode, bdst);
2604+ dst_inode = au_h_iptr(inode, bdst);
2605+ if (dst_inode) {
2606+ if (unlikely(!plink)) {
2607+ err = -EIO;
2608+ AuIOErr("i%lu exists on a upper branch "
2609+ "but plink is disabled\n", inode->i_ino);
2610+ goto out;
2611+ }
2612+
2613+ if (dst_inode->i_nlink) {
2614+ const int do_dt = au_ftest_cpup(flags, DTIME);
2615+
2616+ h_src = au_plink_lkup(sb, bdst, inode);
2617+ err = PTR_ERR(h_src);
2618+ if (IS_ERR(h_src))
2619+ goto out;
2620+ if (unlikely(!h_src->d_inode)) {
2621+ err = -EIO;
2622+ AuIOErr("i%lu exists on a upper branch "
2623+ "but plink is broken\n", inode->i_ino);
2624+ dput(h_src);
2625+ goto out;
2626+ }
2627+
2628+ if (do_dt) {
2629+ hgdir = NULL;
2630+ if (hinotify && !IS_ROOT(dst_parent)) {
2631+ gparent = dget_parent(dst_parent);
2632+ hgdir = au_hi(gparent->d_inode, bdst);
2633+ IMustLock(hgdir->hi_inode);
2634+ dput(gparent);
2635+ }
2636+ au_dtime_store(&dt, dst_parent, h_parent, hdir,
2637+ hgdir);
2638+ }
2639+ vfsub_args_reinit(vargs);
2640+ vfsub_ign_hinode(vargs, IN_CREATE, hdir);
2641+ err = vfsub_link(h_src, h_dir, h_dst, vargs);
2642+ if (do_dt)
2643+ au_dtime_revert(&dt);
2644+ dput(h_src);
2645+ goto out;
2646+ } else
2647+ /* todo: cpup_wh_file? */
2648+ /* udba work */
2649+ au_update_brange(inode, 1);
2650+ }
2651+
2652+ old_ibstart = au_ibstart(inode);
2653+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent, vargs);
2654+ if (unlikely(err))
2655+ goto out;
2656+ dst_inode = h_dst->d_inode;
2657+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
2658+
2659+ /* todo: test dlgt? */
2660+ err = cpup_iattr(dentry, bdst, h_src, hdir, vargs);
2661+#if 0 /* reserved for future use */
2662+ if (0 && !err)
2663+ err = cpup_xattrs(h_src, h_dst);
2664+#endif
2665+ isdir = S_ISDIR(dst_inode->i_mode);
2666+ if (!err) {
2667+ if (bdst < old_ibstart)
2668+ au_set_ibstart(inode, bdst);
2669+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
2670+ au_hi_flags(inode, isdir));
2671+ mutex_unlock(&dst_inode->i_mutex);
2672+ if (!isdir
2673+ && h_src->d_inode->i_nlink > 1
2674+ && plink)
2675+ au_plink_append(sb, inode, h_dst, bdst);
2676+ goto out; /* success */
2677+ }
2678+
2679+ /* revert */
2680+ mutex_unlock(&dst_inode->i_mutex);
2681+ hgdir = NULL;
2682+ if (au_opt_test(mnt_flags, UDBA_INOTIFY) && !IS_ROOT(dst_parent)) {
2683+ gparent = dget_parent(dst_parent);
2684+ hgdir = au_hi(gparent->d_inode, bdst);
2685+ dput(gparent);
2686+ }
2687+ au_dtime_store(&dt, dst_parent, h_parent, hdir, hgdir);
2688+ vfsub_args_reinit(vargs);
2689+ vfsub_ign_hinode(vargs, IN_DELETE, hdir);
2690+ if (!isdir)
2691+ rerr = vfsub_unlink(h_dir, h_dst, vargs);
2692+ else
2693+ rerr = vfsub_rmdir(h_dir, h_dst, vargs);
2694+ au_dtime_revert(&dt);
2695+ if (rerr) {
2696+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
2697+ err = -EIO;
2698+ }
2699+
2700+ out:
2701+ dput(dst_parent);
2702+ AuTraceErr(err);
2703+ return err;
2704+}
2705+
2706+struct au_cpup_single_args {
2707+ int *errp;
2708+ struct dentry *dentry;
2709+ aufs_bindex_t bdst, bsrc;
2710+ loff_t len;
2711+ unsigned int flags;
2712+ struct dentry *dst_parent;
2713+ struct vfsub_args *vargs;
2714+};
2715+
2716+static void au_call_cpup_single(void *args)
2717+{
2718+ struct au_cpup_single_args *a = args;
2719+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
2720+ a->flags, a->dst_parent, a->vargs);
2721+}
2722+
2723+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2724+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2725+ struct dentry *dst_parent)
2726+{
2727+ int err, wkq_err;
2728+ struct dentry *h_dentry;
2729+ umode_t mode;
2730+ struct au_hin_ignore ign;
2731+ struct vfsub_args vargs;
2732+
2733+ LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %lld, flags 0x%x\n",
2734+ AuDLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
2735+ flags);
2736+
2737+ vfsub_args_init(&vargs, &ign, au_test_dlgt(au_mntflags(dentry->d_sb)),
2738+ /*force_unlink*/0);
2739+ h_dentry = au_h_dptr(dentry, bsrc);
2740+ mode = h_dentry->d_inode->i_mode & S_IFMT;
2741+ if ((mode != S_IFCHR && mode != S_IFBLK)
2742+ || capable(CAP_MKNOD))
2743+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2744+ dst_parent, &vargs);
2745+ else {
2746+ struct au_cpup_single_args args = {
2747+ .errp = &err,
2748+ .dentry = dentry,
2749+ .bdst = bdst,
2750+ .bsrc = bsrc,
2751+ .len = len,
2752+ .flags = flags,
2753+ .dst_parent = dst_parent,
2754+ .vargs = &vargs
2755+ };
2756+ vfsub_fclr(vargs.flags, DLGT);
2757+ wkq_err = au_wkq_wait(au_call_cpup_single, &args, /*dlgt*/0);
2758+ if (unlikely(wkq_err))
2759+ err = wkq_err;
2760+ }
2761+
2762+ AuTraceErr(err);
2763+ return err;
2764+}
2765+
2766+/*
2767+ * copyup the @dentry from the first active hidden branch to @bdst,
2768+ * using au_cpup_single().
2769+ */
2770+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2771+ unsigned int flags, struct vfsub_args *vargs)
2772+{
2773+ int err;
2774+ struct inode *inode;
2775+ aufs_bindex_t bsrc, bend;
2776+
2777+ LKTRTrace("%.*s, bdst %d, len %lld, flags 0x%x\n",
2778+ AuDLNPair(dentry), bdst, len, flags);
2779+ inode = dentry->d_inode;
2780+ AuDebugOn(!S_ISDIR(inode->i_mode) && au_dbstart(dentry) < bdst);
2781+
2782+ bend = au_dbend(dentry);
2783+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2784+ if (au_h_dptr(dentry, bsrc))
2785+ break;
2786+ AuDebugOn(!au_h_dptr(dentry, bsrc));
2787+
2788+ err = au_lkup_neg(dentry, bdst);
2789+ if (!err) {
2790+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL,
2791+ vargs);
2792+ if (!err)
2793+ return 0; /* success */
2794+
2795+ /* revert */
2796+ au_set_h_dptr(dentry, bdst, NULL);
2797+ au_set_dbstart(dentry, bsrc);
2798+ }
2799+
2800+ AuTraceErr(err);
2801+ return err;
2802+}
2803+
2804+struct au_cpup_simple_args {
2805+ int *errp;
2806+ struct dentry *dentry;
2807+ aufs_bindex_t bdst;
2808+ loff_t len;
2809+ unsigned int flags;
2810+ struct vfsub_args *vargs;
2811+};
2812+
2813+static void au_call_cpup_simple(void *args)
2814+{
2815+ struct au_cpup_simple_args *a = args;
2816+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags,
2817+ a->vargs);
2818+}
2819+
2820+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2821+ unsigned int flags)
2822+{
2823+ int err, wkq_err;
2824+ unsigned char do_sio, dlgt;
2825+ struct dentry *parent;
2826+ struct inode *h_dir, *dir;
2827+ struct au_hin_ignore ign;
2828+ struct vfsub_args vargs;
2829+
2830+ LKTRTrace("%.*s, b%d, len %lld, flags 0x%x\n",
2831+ AuDLNPair(dentry), bdst, len, flags);
2832+
2833+ parent = dget_parent(dentry);
2834+ dir = parent->d_inode;
2835+ h_dir = au_h_iptr(dir, bdst);
2836+ dlgt = !!au_test_dlgt(au_mntflags(dir->i_sb));
2837+ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE, dlgt);
2838+ if (!do_sio) {
2839+ /*
2840+ * testing CAP_MKNOD is for generic fs,
2841+ * but CAP_FSETID is for xfs only, currently.
2842+ */
2843+ umode_t mode = dentry->d_inode->i_mode;
2844+ do_sio = (((mode & (S_IFCHR | S_IFBLK))
2845+ && !capable(CAP_MKNOD))
2846+ || ((mode & (S_ISUID | S_ISGID))
2847+ && !capable(CAP_FSETID)));
2848+ }
2849+ vfsub_args_init(&vargs, &ign, dlgt, /*force_unlink*/0);
2850+ if (!do_sio)
2851+ err = au_cpup_simple(dentry, bdst, len, flags, &vargs);
2852+ else {
2853+ struct au_cpup_simple_args args = {
2854+ .errp = &err,
2855+ .dentry = dentry,
2856+ .bdst = bdst,
2857+ .len = len,
2858+ .flags = flags,
2859+ .vargs = &vargs
2860+ };
2861+ vfsub_fclr(vargs.flags, DLGT);
2862+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args, /*dlgt*/0);
2863+ if (unlikely(wkq_err))
2864+ err = wkq_err;
2865+ }
2866+
2867+ dput(parent);
2868+ AuTraceErr(err);
2869+ return err;
2870+}
2871+
2872+/* ---------------------------------------------------------------------- */
2873+
2874+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2875+ struct dentry *wh_dentry, struct file *file,
2876+ loff_t len, struct vfsub_args *vargs)
2877+{
2878+ int err;
2879+ struct au_dinfo *dinfo;
2880+ aufs_bindex_t bstart;
2881+ struct dentry *h_d_bdst, *h_d_bstart;
2882+
2883+ AuTraceEnter();
2884+
2885+ dinfo = au_di(dentry);
2886+ bstart = dinfo->di_bstart;
2887+ h_d_bdst = dinfo->di_hdentry[0 + bdst].hd_dentry;
2888+ dinfo->di_bstart = bdst;
2889+ dinfo->di_hdentry[0 + bdst].hd_dentry = wh_dentry;
2890+ h_d_bstart = dinfo->di_hdentry[0 + bstart].hd_dentry;
2891+ if (file)
2892+ dinfo->di_hdentry[0 + bstart].hd_dentry
2893+ = au_h_fptr(file, au_fbstart(file))->f_dentry;
2894+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2895+ /*h_parent*/NULL, vargs);
2896+ if (!err && file) {
2897+ err = au_reopen_nondir(file);
2898+ dinfo->di_hdentry[0 + bstart].hd_dentry = h_d_bstart;
2899+ }
2900+ dinfo->di_hdentry[0 + bdst].hd_dentry = h_d_bdst;
2901+ dinfo->di_bstart = bstart;
2902+
2903+ AuTraceErr(err);
2904+ return err;
2905+}
2906+
2907+/*
2908+ * copyup the deleted file for writing.
2909+ */
2910+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2911+ struct file *file)
2912+{
2913+ int err;
2914+ unsigned char dlgt;
2915+ struct dentry *parent, *h_parent, *wh_dentry;
2916+ struct super_block *sb;
2917+ unsigned int mnt_flags;
2918+ struct au_dtime dt;
2919+ struct au_hin_ignore ign;
2920+ struct vfsub_args vargs;
2921+ struct au_hinode *hgdir, *hdir;
2922+ struct au_ndx ndx = {
2923+ .nd = NULL,
2924+ .flags = 0,
2925+ /* .br = NULL */
2926+ };
2927+
2928+ LKTRTrace("%.*s, bdst %d, len %llu\n", AuDLNPair(dentry), bdst, len);
2929+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
2930+ || (file && !(file->f_mode & FMODE_WRITE)));
2931+ DiMustWriteLock(dentry);
2932+
2933+ parent = dget_parent(dentry);
2934+ IiMustAnyLock(parent->d_inode);
2935+ h_parent = au_h_dptr(parent, bdst);
2936+ AuDebugOn(!h_parent);
2937+
2938+ sb = parent->d_sb;
2939+ mnt_flags = au_mntflags(sb);
2940+ dlgt = 0;
2941+ ndx.nfsmnt = au_nfsmnt(sb, bdst);
2942+ if (au_test_dlgt(mnt_flags)) {
2943+ dlgt = 1;
2944+ au_fset_ndx(ndx.flags, DLGT);
2945+ }
2946+ wh_dentry = au_whtmp_lkup(h_parent, &dentry->d_name, &ndx);
2947+ err = PTR_ERR(wh_dentry);
2948+ if (IS_ERR(wh_dentry))
2949+ goto out;
2950+
2951+ hdir = NULL;
2952+ hgdir = NULL;
2953+ if (au_opt_test(mnt_flags, UDBA_INOTIFY)) {
2954+ hdir = au_hi(parent->d_inode, bdst);
2955+ if (!IS_ROOT(parent)) {
2956+ struct dentry *gparent;
2957+ gparent = dget_parent(parent);
2958+ hgdir = au_hi(gparent->d_inode, bdst);
2959+ dput(gparent);
2960+ }
2961+ }
2962+ au_dtime_store(&dt, parent, h_parent, hdir, hgdir);
2963+ vfsub_args_init(&vargs, &ign, dlgt, /*force_unlink*/0);
2964+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len, &vargs);
2965+ if (unlikely(err))
2966+ goto out_wh;
2967+
2968+ AuDebugOn(!d_unhashed(dentry));
2969+ /* dget first to force sillyrename on nfs */
2970+ dget(wh_dentry);
2971+ vfsub_args_reinit(&vargs);
2972+ vfsub_ign_hinode(&vargs, IN_DELETE, hdir);
2973+ err = vfsub_unlink(h_parent->d_inode, wh_dentry, &vargs);
2974+ if (unlikely(err)) {
2975+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2976+ AuDLNPair(wh_dentry), err);
2977+ err = -EIO;
2978+ }
2979+ au_dtime_revert(&dt);
2980+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2981+
2982+ out_wh:
2983+ dput(wh_dentry);
2984+ out:
2985+ dput(parent);
2986+ AuTraceErr(err);
2987+ return err;
2988+}
2989+
2990+struct au_cpup_wh_args {
2991+ int *errp;
2992+ struct dentry *dentry;
2993+ aufs_bindex_t bdst;
2994+ loff_t len;
2995+ struct file *file;
2996+};
2997+
2998+static void au_call_cpup_wh(void *args)
2999+{
3000+ struct au_cpup_wh_args *a = args;
3001+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
3002+}
3003+
3004+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
3005+ struct file *file)
3006+{
3007+ int err, wkq_err;
3008+ struct dentry *parent, *h_tmp, *h_parent, *h_dentry;
3009+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
3010+ struct au_wbr *wbr;
3011+
3012+ AuTraceEnter();
3013+ parent = dget_parent(dentry);
3014+ dir = parent->d_inode;
3015+ IiMustAnyLock(dir);
3016+
3017+ h_tmp = NULL;
3018+ h_parent = NULL;
3019+ h_dir = au_igrab(au_h_iptr(dir, bdst));
3020+ h_tmpdir = h_dir;
3021+ if (!h_dir->i_nlink) {
3022+ DiMustWriteLock(parent);
3023+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
3024+ AuDebugOn(!wbr);
3025+ h_tmp = wbr->wbr_tmp;
3026+
3027+ h_parent = dget(au_h_dptr(parent, bdst));
3028+ au_set_h_dptr(parent, bdst, NULL);
3029+ au_set_h_dptr(parent, bdst, dget(h_tmp));
3030+ h_tmpdir = h_tmp->d_inode;
3031+ au_set_h_iptr(dir, bdst, NULL, 0);
3032+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
3033+
3034+ /* this temporary unlock is safe */
3035+ if (file)
3036+ h_dentry = au_h_fptr(file, au_fbstart(file))->f_dentry;
3037+ else
3038+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
3039+ h_inode = h_dentry->d_inode;
3040+ IMustLock(h_inode);
3041+ mutex_unlock(&h_inode->i_mutex);
3042+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
3043+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
3044+ }
3045+
3046+ if (!au_test_h_perm_sio
3047+ (h_tmpdir, MAY_EXEC | MAY_WRITE,
3048+ au_test_dlgt(au_mntflags(dentry->d_sb))))
3049+ err = au_cpup_wh(dentry, bdst, len, file);
3050+ else {
3051+ struct au_cpup_wh_args args = {
3052+ .errp = &err,
3053+ .dentry = dentry,
3054+ .bdst = bdst,
3055+ .len = len,
3056+ .file = file
3057+ };
3058+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args, /*dlgt*/0);
3059+ if (unlikely(wkq_err))
3060+ err = wkq_err;
3061+ }
3062+
3063+ /* todo: is this restore safe? */
3064+ if (h_tmp) {
3065+ mutex_unlock(&h_tmpdir->i_mutex);
3066+ au_set_h_iptr(dir, bdst, NULL, 0);
3067+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
3068+ au_set_h_dptr(parent, bdst, NULL);
3069+ au_set_h_dptr(parent, bdst, h_parent);
3070+ }
3071+ iput(h_dir);
3072+ dput(parent);
3073+
3074+ AuTraceErr(err);
3075+ return err;
3076+}
3077+
3078+/* ---------------------------------------------------------------------- */
3079+
3080+/*
3081+ * generic routine for both of copy-up and copy-down.
3082+ * Although I've tried building a path by dcsub, I gave up this approach.
3083+ * Since the ancestor directory may be moved/renamed during copy.
3084+ */
3085+/* cf. revalidate function in file.c */
3086+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
3087+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
3088+ struct dentry *h_parent, void *arg),
3089+ void *arg)
3090+{
3091+ int err;
3092+ unsigned char pin_flags;
3093+ struct au_pin pin;
3094+ struct super_block *sb;
3095+ struct dentry *d, *parent, *h_parent, *real_parent;
3096+
3097+ LKTRTrace("%.*s, b%d, parent i%lu\n",
3098+ AuDLNPair(dentry), bdst, (unsigned long)parent_ino(dentry));
3099+ sb = dentry->d_sb;
3100+ AuDebugOn(au_test_ro(sb, bdst, NULL));
3101+ err = 0;
3102+ parent = dget_parent(dentry);
3103+ IiMustWriteLock(parent->d_inode);
3104+ if (IS_ROOT(parent))
3105+ goto out;
3106+
3107+ pin_flags = AuPin_MNT_WRITE;
3108+ if (au_opt_test(au_mntflags(sb), UDBA_INOTIFY))
3109+ au_fset_pin(pin_flags, DO_GPARENT);
3110+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT3, AuLsc_I_PARENT2,
3111+ pin_flags);
3112+
3113+ /* do not use au_dpage */
3114+ real_parent = parent;
3115+ while (1) {
3116+ dput(parent);
3117+ parent = dget_parent(dentry);
3118+ h_parent = au_h_dptr(parent, bdst);
3119+ if (h_parent)
3120+ goto out; /* success */
3121+
3122+ /* find top dir which is needed to cpup */
3123+ do {
3124+ d = parent;
3125+ dput(parent);
3126+ parent = dget_parent(d);
3127+ di_read_lock_parent3(parent, !AuLock_IR);
3128+ h_parent = au_h_dptr(parent, bdst);
3129+ di_read_unlock(parent, !AuLock_IR);
3130+ } while (!h_parent);
3131+
3132+ if (d != real_parent)
3133+ di_write_lock_child3(d);
3134+
3135+ /* somebody else might create while we were sleeping */
3136+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
3137+ if (au_h_dptr(d, bdst))
3138+ au_update_dbstart(d);
3139+
3140+ au_pin_do_set_dentry(pin.pin + AuPin_PARENT, d);
3141+ err = au_do_pin(pin.pin + AuPin_PARENT,
3142+ au_pin_gp(&pin));
3143+ if (!err) {
3144+ err = cp(d, bdst, h_parent, arg);
3145+ au_unpin(&pin);
3146+ }
3147+ }
3148+
3149+ if (d != real_parent)
3150+ di_write_unlock(d);
3151+ if (unlikely(err))
3152+ break;
3153+ }
3154+
3155+ out:
3156+ dput(parent);
3157+ AuTraceErr(err);
3158+ return err;
3159+}
3160+
3161+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
3162+ struct dentry *h_parent, void *arg)
3163+{
3164+ int err;
3165+
3166+ err = au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
3167+
3168+ AuTraceErr(err);
3169+ return err;
3170+}
3171+
3172+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
3173+{
3174+ int err;
3175+
3176+ err = au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
3177+
3178+ AuTraceErr(err);
3179+ return err;
3180+}
3181+
3182+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
3183+{
3184+ int err;
3185+ struct dentry *parent;
3186+ struct inode *dir;
3187+
3188+ parent = dget_parent(dentry);
3189+ dir = parent->d_inode;
3190+ LKTRTrace("%.*s, b%d, parent i%lu\n",
3191+ AuDLNPair(dentry), bdst, dir->i_ino);
3192+ DiMustReadLock(parent);
3193+ IiMustReadLock(dir);
3194+
3195+ err = 0;
3196+ if (au_h_iptr(dir, bdst))
3197+ goto out;
3198+
3199+ di_read_unlock(parent, AuLock_IR);
3200+ di_write_lock_parent(parent);
3201+ /* someone else might change our inode while we were sleeping */
3202+ if (!au_h_iptr(dir, bdst))
3203+ err = au_cpup_dirs(dentry, bdst);
3204+ di_downgrade_lock(parent, AuLock_IR);
3205+
3206+ out:
3207+ dput(parent);
3208+ AuTraceErr(err);
3209+ return err;
3210+}
3211diff -urN linux/fs/aufs/cpup.h linux-aufs/fs/aufs/cpup.h
3212--- linux/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
3213+++ linux-aufs/fs/aufs/cpup.h 2009-03-12 16:18:04.000000000 +0100
3214@@ -0,0 +1,86 @@
3215+/*
3216+ * Copyright (C) 2005-2009 Junjiro Okajima
3217+ *
3218+ * This program, aufs is free software; you can redistribute it and/or modify
3219+ * it under the terms of the GNU General Public License as published by
3220+ * the Free Software Foundation; either version 2 of the License, or
3221+ * (at your option) any later version.
3222+ *
3223+ * This program is distributed in the hope that it will be useful,
3224+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3225+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3226+ * GNU General Public License for more details.
3227+ *
3228+ * You should have received a copy of the GNU General Public License
3229+ * along with this program; if not, write to the Free Software
3230+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3231+ */
3232+
3233+/*
3234+ * copy-up/down functions
3235+ *
3236+ * $Id$
3237+ */
3238+
3239+#ifndef __AUFS_CPUP_H__
3240+#define __AUFS_CPUP_H__
3241+
3242+#ifdef __KERNEL__
3243+
3244+#include <linux/fs.h>
3245+#include <linux/aufs_type.h>
3246+
3247+void au_cpup_attr_timesizes(struct inode *inode);
3248+void au_cpup_attr_nlink(struct inode *inode, int force);
3249+void au_cpup_attr_changeable(struct inode *inode);
3250+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
3251+void au_cpup_attr_all(struct inode *inode, int force);
3252+
3253+/* ---------------------------------------------------------------------- */
3254+
3255+/* cpup flags */
3256+#define AuCpup_DTIME 1 /* do dtime_store/revert */
3257+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
3258+ for link(2) */
3259+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
3260+#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; }
3261+#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; }
3262+
3263+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
3264+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3265+ struct dentry *dst_parent);
3266+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
3267+ unsigned int flags);
3268+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
3269+ struct file *file);
3270+
3271+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
3272+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
3273+ struct dentry *h_parent, void *arg),
3274+ void *arg);
3275+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
3276+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
3277+
3278+/* ---------------------------------------------------------------------- */
3279+
3280+/* keep timestamps when copyup */
3281+struct au_dtime {
3282+ struct dentry *dt_dentry, *dt_h_dentry;
3283+ struct au_hinode *dt_hinode, *dt_hdir;
3284+ struct timespec dt_atime, dt_mtime;
3285+};
3286+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
3287+ struct dentry *h_dentry, struct au_hinode *hinode,
3288+ struct au_hinode *hdir);
3289+void au_dtime_revert(struct au_dtime *dt);
3290+
3291+/* ---------------------------------------------------------------------- */
3292+
3293+static inline void au_cpup_attr_flags(struct inode *inode,
3294+ struct inode *h_inode)
3295+{
3296+ inode->i_flags |= h_inode->i_flags & ~(S_DEAD | S_PRIVATE);
3297+}
3298+
3299+#endif /* __KERNEL__ */
3300+#endif /* __AUFS_CPUP_H__ */
3301diff -urN linux/fs/aufs/dcsub.c linux-aufs/fs/aufs/dcsub.c
3302--- linux/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
3303+++ linux-aufs/fs/aufs/dcsub.c 2009-03-12 16:18:04.000000000 +0100
3304@@ -0,0 +1,251 @@
3305+/*
3306+ * Copyright (C) 2005-2009 Junjiro Okajima
3307+ *
3308+ * This program, aufs is free software; you can redistribute it and/or modify
3309+ * it under the terms of the GNU General Public License as published by
3310+ * the Free Software Foundation; either version 2 of the License, or
3311+ * (at your option) any later version.
3312+ *
3313+ * This program is distributed in the hope that it will be useful,
3314+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3315+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3316+ * GNU General Public License for more details.
3317+ *
3318+ * You should have received a copy of the GNU General Public License
3319+ * along with this program; if not, write to the Free Software
3320+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3321+ */
3322+
3323+/*
3324+ * sub-routines for dentry cache
3325+ *
3326+ * $Id$
3327+ */
3328+
3329+#include "aufs.h"
3330+
3331+static void au_dpage_free(struct au_dpage *dpage)
3332+{
3333+ int i;
3334+
3335+ AuTraceEnter();
3336+ AuDebugOn(!dpage);
3337+
3338+ for (i = 0; i < dpage->ndentry; i++)
3339+ dput(dpage->dentries[i]);
3340+ free_page((unsigned long)dpage->dentries);
3341+}
3342+
3343+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
3344+{
3345+ int err;
3346+ void *p;
3347+
3348+ AuTraceEnter();
3349+
3350+ err = -ENOMEM;
3351+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
3352+ if (unlikely(!dpages->dpages))
3353+ goto out;
3354+ p = (void *)__get_free_page(gfp);
3355+ if (unlikely(!p))
3356+ goto out_dpages;
3357+ dpages->dpages[0].ndentry = 0;
3358+ dpages->dpages[0].dentries = p;
3359+ dpages->ndpage = 1;
3360+ return 0; /* success */
3361+
3362+ out_dpages:
3363+ kfree(dpages->dpages);
3364+ out:
3365+ AuTraceErr(err);
3366+ return err;
3367+}
3368+
3369+void au_dpages_free(struct au_dcsub_pages *dpages)
3370+{
3371+ int i;
3372+
3373+ AuTraceEnter();
3374+
3375+ for (i = 0; i < dpages->ndpage; i++)
3376+ au_dpage_free(dpages->dpages + i);
3377+ kfree(dpages->dpages);
3378+}
3379+
3380+static int au_dpages_append(struct au_dcsub_pages *dpages,
3381+ struct dentry *dentry, gfp_t gfp)
3382+{
3383+ int err, sz;
3384+ struct au_dpage *dpage;
3385+ void *p;
3386+
3387+ /* AuTraceEnter(); */
3388+
3389+ dpage = dpages->dpages + dpages->ndpage - 1;
3390+ AuDebugOn(!dpage);
3391+ sz = PAGE_SIZE / sizeof(dentry);
3392+ if (unlikely(dpage->ndentry >= sz)) {
3393+ LKTRLabel(new dpage);
3394+ err = -ENOMEM;
3395+ sz = dpages->ndpage * sizeof(*dpages->dpages);
3396+ p = au_kzrealloc(dpages->dpages, sz,
3397+ sz + sizeof(*dpages->dpages), gfp);
3398+ if (unlikely(!p))
3399+ goto out;
3400+ dpages->dpages = p;
3401+ dpage = dpages->dpages + dpages->ndpage;
3402+ p = (void *)__get_free_page(gfp);
3403+ if (unlikely(!p))
3404+ goto out;
3405+ dpage->ndentry = 0;
3406+ dpage->dentries = p;
3407+ dpages->ndpage++;
3408+ }
3409+
3410+ dpage->dentries[dpage->ndentry++] = dget(dentry);
3411+ return 0; /* success */
3412+
3413+ out:
3414+ /* AuTraceErr(err); */
3415+ return err;
3416+}
3417+
3418+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3419+ au_dpages_test test, void *arg)
3420+{
3421+ int err;
3422+ struct dentry *this_parent = root;
3423+ struct list_head *next;
3424+ struct super_block *sb = root->d_sb;
3425+
3426+ AuTraceEnter();
3427+
3428+ err = 0;
3429+ spin_lock(&dcache_lock);
3430+ repeat:
3431+ next = this_parent->d_subdirs.next;
3432+ resume:
3433+ if (this_parent->d_sb == sb
3434+ && !IS_ROOT(this_parent)
3435+ && atomic_read(&this_parent->d_count)
3436+ && this_parent->d_inode
3437+ && (!test || test(this_parent, arg))) {
3438+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3439+ if (unlikely(err))
3440+ goto out;
3441+ }
3442+
3443+ while (next != &this_parent->d_subdirs) {
3444+ struct list_head *tmp = next;
3445+ struct dentry *dentry = list_entry(tmp, struct dentry,
3446+ d_u.d_child);
3447+ next = tmp->next;
3448+ if (/*d_unhashed(dentry) || */!dentry->d_inode)
3449+ continue;
3450+ if (!list_empty(&dentry->d_subdirs)) {
3451+ this_parent = dentry;
3452+ goto repeat;
3453+ }
3454+ if (dentry->d_sb == sb
3455+ && atomic_read(&dentry->d_count)
3456+ && (!test || test(dentry, arg))) {
3457+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3458+ if (unlikely(err))
3459+ goto out;
3460+ }
3461+ }
3462+
3463+ if (this_parent != root) {
3464+ next = this_parent->d_u.d_child.next;
3465+ this_parent = this_parent->d_parent; /* dcache_lock is locked */
3466+ goto resume;
3467+ }
3468+ out:
3469+ spin_unlock(&dcache_lock);
3470+#if 0 /* debug */
3471+ if (!err) {
3472+ int i, j;
3473+ j = 0;
3474+ for (i = 0; i < dpages->ndpage; i++) {
3475+ if ((dpages->dpages + i)->ndentry)
3476+ AuDbg("%d: %d\n",
3477+ i, (dpages->dpages + i)->ndentry);
3478+ j += (dpages->dpages + i)->ndentry;
3479+ }
3480+ if (j)
3481+ AuDbg("ndpage %d, %d\n", dpages->ndpage, j);
3482+ }
3483+#endif
3484+ AuTraceErr(err);
3485+ return err;
3486+}
3487+
3488+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3489+ int do_include, au_dpages_test test, void *arg)
3490+{
3491+ int err;
3492+
3493+ AuTraceEnter();
3494+
3495+ err = 0;
3496+ spin_lock(&dcache_lock);
3497+ if (do_include && (!test || test(dentry, arg))) {
3498+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3499+ if (unlikely(err))
3500+ goto out;
3501+ }
3502+ while (!IS_ROOT(dentry)) {
3503+ dentry = dentry->d_parent; /* dcache_lock is locked */
3504+ if (!test || test(dentry, arg)) {
3505+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3506+ if (unlikely(err))
3507+ break;
3508+ }
3509+ }
3510+
3511+ out:
3512+ spin_unlock(&dcache_lock);
3513+
3514+ AuTraceErr(err);
3515+ return err;
3516+}
3517+
3518+struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2)
3519+{
3520+ struct dentry *trap, **dentries;
3521+ int err, i, j;
3522+ struct au_dcsub_pages dpages;
3523+ struct au_dpage *dpage;
3524+
3525+ LKTRTrace("%.*s, %.*s\n", AuDLNPair(d1), AuDLNPair(d2));
3526+
3527+ trap = ERR_PTR(-ENOMEM);
3528+ err = au_dpages_init(&dpages, GFP_NOFS);
3529+ if (unlikely(err))
3530+ goto out;
3531+ err = au_dcsub_pages_rev(&dpages, d1, /*do_include*/1, NULL, NULL);
3532+ if (unlikely(err))
3533+ goto out_dpages;
3534+
3535+ trap = d1;
3536+ for (i = 0; !err && i < dpages.ndpage; i++) {
3537+ dpage = dpages.dpages + i;
3538+ dentries = dpage->dentries;
3539+ for (j = 0; !err && j < dpage->ndentry; j++) {
3540+ struct dentry *d;
3541+ d = dentries[j];
3542+ err = (d == d2);
3543+ if (!err)
3544+ trap = d;
3545+ }
3546+ }
3547+ if (!err)
3548+ trap = NULL;
3549+
3550+ out_dpages:
3551+ au_dpages_free(&dpages);
3552+ out:
3553+ AuTraceErrPtr(trap);
3554+ return trap;
3555+}
3556diff -urN linux/fs/aufs/dcsub.h linux-aufs/fs/aufs/dcsub.h
3557--- linux/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
3558+++ linux-aufs/fs/aufs/dcsub.h 2009-03-12 16:18:04.000000000 +0100
3559@@ -0,0 +1,54 @@
3560+/*
3561+ * Copyright (C) 2005-2009 Junjiro Okajima
3562+ *
3563+ * This program, aufs is free software; you can redistribute it and/or modify
3564+ * it under the terms of the GNU General Public License as published by
3565+ * the Free Software Foundation; either version 2 of the License, or
3566+ * (at your option) any later version.
3567+ *
3568+ * This program is distributed in the hope that it will be useful,
3569+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3570+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3571+ * GNU General Public License for more details.
3572+ *
3573+ * You should have received a copy of the GNU General Public License
3574+ * along with this program; if not, write to the Free Software
3575+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3576+ */
3577+
3578+/*
3579+ * sub-routines for dentry cache
3580+ *
3581+ * $Id$
3582+ */
3583+
3584+#ifndef __AUFS_DCSUB_H__
3585+#define __AUFS_DCSUB_H__
3586+
3587+#ifdef __KERNEL__
3588+
3589+#include <linux/dcache.h>
3590+
3591+struct au_dpage {
3592+ int ndentry;
3593+ struct dentry **dentries;
3594+};
3595+
3596+struct au_dcsub_pages {
3597+ int ndpage;
3598+ struct au_dpage *dpages;
3599+};
3600+
3601+/* ---------------------------------------------------------------------- */
3602+
3603+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3604+void au_dpages_free(struct au_dcsub_pages *dpages);
3605+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3606+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3607+ au_dpages_test test, void *arg);
3608+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3609+ int do_include, au_dpages_test test, void *arg);
3610+struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2);
3611+
3612+#endif /* __KERNEL__ */
3613+#endif /* __AUFS_DCSUB_H__ */
3614diff -urN linux/fs/aufs/debug.c linux-aufs/fs/aufs/debug.c
3615--- linux/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
3616+++ linux-aufs/fs/aufs/debug.c 2009-03-12 16:18:04.000000000 +0100
3617@@ -0,0 +1,522 @@
3618+/*
3619+ * Copyright (C) 2005-2009 Junjiro Okajima
3620+ *
3621+ * This program, aufs is free software; you can redistribute it and/or modify
3622+ * it under the terms of the GNU General Public License as published by
3623+ * the Free Software Foundation; either version 2 of the License, or
3624+ * (at your option) any later version.
3625+ *
3626+ * This program is distributed in the hope that it will be useful,
3627+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3628+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3629+ * GNU General Public License for more details.
3630+ *
3631+ * You should have received a copy of the GNU General Public License
3632+ * along with this program; if not, write to the Free Software
3633+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3634+ */
3635+
3636+/*
3637+ * debug print functions
3638+ *
3639+ * $Id$
3640+ */
3641+
3642+#include "aufs.h"
3643+
3644+atomic_t au_cond = ATOMIC_INIT(0);
3645+
3646+char *au_plevel = KERN_DEBUG;
3647+#define dpri(fmt, arg...) do { \
3648+ if (LktrCond) \
3649+ printk("%s" fmt, au_plevel, ##arg); \
3650+} while (0)
3651+
3652+/* ---------------------------------------------------------------------- */
3653+
3654+void au_dpri_whlist(struct au_nhash *whlist)
3655+{
3656+ int i;
3657+ struct hlist_head *head;
3658+ struct au_vdir_wh *tpos;
3659+ struct hlist_node *pos;
3660+
3661+ for (i = 0; i < AuSize_NHASH; i++) {
3662+ head = whlist->heads + i;
3663+ hlist_for_each_entry(tpos, pos, head, wh_hash)
3664+ dpri("b%d, %.*s, %d\n",
3665+ tpos->wh_bindex,
3666+ tpos->wh_str.len, tpos->wh_str.name,
3667+ tpos->wh_str.len);
3668+ }
3669+}
3670+
3671+void au_dpri_vdir(struct au_vdir *vdir)
3672+{
3673+ int i;
3674+ union au_vdir_deblk_p p;
3675+ unsigned char *o;
3676+
3677+ if (!vdir || IS_ERR(vdir)) {
3678+ dpri("err %ld\n", PTR_ERR(vdir));
3679+ return;
3680+ }
3681+
3682+ dpri("nblk %d, deblk %p, last{%d, %p}, ver %lu\n",
3683+ vdir->vd_nblk, vdir->vd_deblk,
3684+ vdir->vd_last.i, vdir->vd_last.p.p, vdir->vd_version);
3685+ for (i = 0; i < vdir->vd_nblk; i++) {
3686+ p.deblk = vdir->vd_deblk[i];
3687+ o = p.p;
3688+ dpri("[%d]: %p\n", i, o);
3689+ }
3690+}
3691+
3692+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3693+ struct dentry *wh)
3694+{
3695+ char *n = NULL;
3696+ int l = 0, ntfy = 0;
3697+
3698+ if (!inode || IS_ERR(inode)) {
3699+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3700+ return -1;
3701+ }
3702+
3703+ /* the type of i_blocks depends upon CONFIG_LSF */
3704+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3705+ && sizeof(inode->i_blocks) != sizeof(u64));
3706+ if (wh) {
3707+ n = (void *)wh->d_name.name;
3708+ l = wh->d_name.len;
3709+ }
3710+
3711+ ntfy = au_test_inotify(inode);
3712+ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, ntfy %d, sz %llu, blk %llu,"
3713+ " ct %lld, np %lu, st 0x%lx, f 0x%x, g %x%s%.*s\n",
3714+ bindex,
3715+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3716+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3717+ ntfy,
3718+ i_size_read(inode), (unsigned long long)inode->i_blocks,
3719+ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3720+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
3721+ inode->i_state, inode->i_flags, inode->i_generation,
3722+ l ? ", wh " : "", l, n);
3723+ return 0;
3724+}
3725+
3726+void au_dpri_inode(struct inode *inode)
3727+{
3728+ struct au_iinfo *iinfo;
3729+ aufs_bindex_t bindex;
3730+ int err;
3731+
3732+ err = do_pri_inode(-1, inode, NULL);
3733+ if (err || !au_test_aufs(inode->i_sb))
3734+ return;
3735+
3736+ iinfo = au_ii(inode);
3737+ if (!iinfo)
3738+ return;
3739+ dpri("i-1: bstart %d, bend %d, gen %d\n",
3740+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
3741+ if (iinfo->ii_bstart < 0)
3742+ return;
3743+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
3744+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
3745+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
3746+}
3747+
3748+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry,
3749+ struct list_head *intent)
3750+{
3751+ struct dentry *wh = NULL;
3752+
3753+ if (!dentry || IS_ERR(dentry)) {
3754+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
3755+ return -1;
3756+ }
3757+ /* do not call dget_parent() here */
3758+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x, intent %d\n",
3759+ bindex,
3760+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
3761+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
3762+ atomic_read(&dentry->d_count), dentry->d_flags, !!intent);
3763+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
3764+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
3765+ if (iinfo)
3766+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
3767+ }
3768+ do_pri_inode(bindex, dentry->d_inode, wh);
3769+ return 0;
3770+}
3771+
3772+static struct list_head *au_dbg_h_intent(struct au_dinfo *dinfo,
3773+ aufs_bindex_t bindex)
3774+{
3775+#ifdef CONFIG_AUFS_BR_NFS
3776+ return dinfo->di_hdentry[0 + bindex].hd_intent_list;
3777+#else
3778+ return NULL;
3779+#endif
3780+}
3781+
3782+void au_dpri_dentry(struct dentry *dentry)
3783+{
3784+ struct au_dinfo *dinfo;
3785+ aufs_bindex_t bindex;
3786+ int err;
3787+
3788+ err = do_pri_dentry(-1, dentry, NULL);
3789+ if (err || !au_test_aufs(dentry->d_sb))
3790+ return;
3791+
3792+ dinfo = au_di(dentry);
3793+ if (!dinfo)
3794+ return;
3795+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
3796+ dinfo->di_bstart, dinfo->di_bend,
3797+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
3798+ if (dinfo->di_bstart < 0)
3799+ return;
3800+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
3801+ do_pri_dentry(bindex, dinfo->di_hdentry[0 + bindex].hd_dentry,
3802+ au_dbg_h_intent(dinfo, bindex));
3803+}
3804+
3805+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
3806+{
3807+ char a[32];
3808+
3809+ if (!file || IS_ERR(file)) {
3810+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
3811+ return -1;
3812+ }
3813+ a[0] = 0;
3814+ if (bindex < 0
3815+ && file->f_dentry
3816+ && au_test_aufs(file->f_dentry->d_sb)
3817+ && au_fi(file))
3818+ snprintf(a, sizeof(a), ", mmapped %d", au_test_mmapped(file));
3819+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, pos %llu%s\n",
3820+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
3821+ file->f_pos, a);
3822+ if (file->f_dentry)
3823+ do_pri_dentry(bindex, file->f_dentry, NULL);
3824+ return 0;
3825+}
3826+
3827+void au_dpri_file(struct file *file)
3828+{
3829+ struct au_finfo *finfo;
3830+ aufs_bindex_t bindex;
3831+ int err;
3832+
3833+ err = do_pri_file(-1, file);
3834+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
3835+ return;
3836+
3837+ finfo = au_fi(file);
3838+ if (!finfo)
3839+ return;
3840+ if (finfo->fi_bstart < 0)
3841+ return;
3842+ for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
3843+ struct au_hfile *hf;
3844+ hf = finfo->fi_hfile + bindex;
3845+ do_pri_file(bindex, hf ? hf->hf_file : NULL);
3846+ }
3847+}
3848+
3849+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
3850+{
3851+ struct vfsmount *mnt;
3852+ struct super_block *sb;
3853+
3854+ if (!br || IS_ERR(br)
3855+ || !(mnt = br->br_mnt) || IS_ERR(mnt)
3856+ || !(sb = mnt->mnt_sb) || IS_ERR(sb)) {
3857+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
3858+ return -1;
3859+ }
3860+
3861+ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
3862+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt(BIAS) %d, active %d, "
3863+ "xino %d\n",
3864+ bindex, br->br_perm, au_br_count(br), br->br_wbr,
3865+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
3866+ sb->s_flags, sb->s_count - S_BIAS,
3867+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
3868+ return 0;
3869+}
3870+
3871+void au_dpri_sb(struct super_block *sb)
3872+{
3873+ struct au_sbinfo *sbinfo;
3874+ aufs_bindex_t bindex;
3875+ int err;
3876+ /* to reuduce stack size */
3877+ struct {
3878+ struct vfsmount mnt;
3879+ struct au_branch fake;
3880+ } *a;
3881+
3882+ /* this function can be called from magic sysrq */
3883+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
3884+ if (unlikely(!a)) {
3885+ dpri("no memory\n");
3886+ return;
3887+ }
3888+
3889+ a->mnt.mnt_sb = sb;
3890+ a->fake.br_perm = 0;
3891+ a->fake.br_mnt = &a->mnt;
3892+ a->fake.br_xino.xi_file = NULL;
3893+ atomic_set(&a->fake.br_count, 0);
3894+ smp_mb(); /* atomic_set */
3895+ err = do_pri_br(-1, &a->fake);
3896+ kfree(a);
3897+ dpri("dev 0x%x\n", sb->s_dev);
3898+ if (err || !au_test_aufs(sb))
3899+ return;
3900+
3901+ sbinfo = au_sbi(sb);
3902+ if (!sbinfo)
3903+ return;
3904+ dpri("nw %d, gen %u, kobj %d\n",
3905+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
3906+ atomic_read(&sbinfo->si_kobj.kref.refcount));
3907+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
3908+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
3909+}
3910+
3911+/* ---------------------------------------------------------------------- */
3912+
3913+void au_dbg_sleep(int sec)
3914+{
3915+ static DECLARE_WAIT_QUEUE_HEAD(wq);
3916+ wait_event_timeout(wq, 0, sec * HZ);
3917+}
3918+
3919+void au_dbg_sleep_jiffy(int jiffy)
3920+{
3921+ static DECLARE_WAIT_QUEUE_HEAD(wq);
3922+ wait_event_timeout(wq, 0, jiffy);
3923+}
3924+
3925+void au_dbg_iattr(struct iattr *ia)
3926+{
3927+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
3928+ dpri(#name "\n")
3929+ AuBit(MODE);
3930+ AuBit(UID);
3931+ AuBit(GID);
3932+ AuBit(SIZE);
3933+ AuBit(ATIME);
3934+ AuBit(MTIME);
3935+ AuBit(CTIME);
3936+ AuBit(ATIME_SET);
3937+ AuBit(MTIME_SET);
3938+ AuBit(FORCE);
3939+ AuBit(ATTR_FLAG);
3940+ AuBit(KILL_SUID);
3941+ AuBit(KILL_SGID);
3942+ AuBit(FILE);
3943+ AuBit(KILL_PRIV);
3944+ AuBit(OPEN);
3945+ AuBit(TIMES_SET);
3946+#undef AuBit
3947+ dpri("ia_file %p\n", ia->ia_file);
3948+}
3949+
3950+/* ---------------------------------------------------------------------- */
3951+
3952+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo)
3953+{
3954+#ifdef ForceInotify
3955+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_INOTIFY);
3956+#endif
3957+#ifdef ForceDlgt
3958+ au_opt_set(sbinfo->si_mntflags, DLGT);
3959+#endif
3960+#ifdef ForceNoPlink
3961+ au_opt_clr(sbinfo->si_mntflags, PLINK);
3962+#endif
3963+#ifdef ForceNoXino
3964+ au_opt_clr(sbinfo->si_mntflags, XINO);
3965+#endif
3966+#ifdef ForceNoRefrof
3967+ au_opt_clr(sbinfo->si_mntflags, REFROF);
3968+#endif
3969+#ifdef ForceShwh
3970+ au_opt_set(sbinfo->si_mntflags, SHWH);
3971+#endif
3972+
3973+#ifdef CONFIG_AUFS_DEBUG_LOCK
3974+ {
3975+ int i;
3976+ for (i = 0; i < AuDbgLock_Last; i++)
3977+ au_spl_init(sbinfo->si_dbg_lock + i);
3978+ }
3979+#endif
3980+}
3981+
3982+int __init au_debug_init(void)
3983+{
3984+ aufs_bindex_t bindex;
3985+ struct au_vdir_destr destr;
3986+
3987+ bindex = -1;
3988+ AuDebugOn(bindex >= 0);
3989+
3990+ destr.len = -1;
3991+ AuDebugOn(destr.len < NAME_MAX);
3992+
3993+#ifdef CONFIG_4KSTACKS
3994+ AuWarn("CONFIG_4KSTACKS is defined.\n");
3995+#endif
3996+
3997+#ifdef ForceBrs
3998+ sysaufs_brs = 1;
3999+#endif
4000+
4001+#if 0 /* verbose debug */
4002+ {
4003+ union {
4004+ struct au_branch *br;
4005+ struct au_dinfo *di;
4006+ struct au_finfo *fi;
4007+ struct au_iinfo *ii;
4008+ struct au_hinode *hi;
4009+ struct au_sbinfo *si;
4010+ struct au_vdir_destr *destr;
4011+ struct au_vdir_de *de;
4012+ struct au_vdir_wh *wh;
4013+ struct au_vdir *vd;
4014+ } u;
4015+
4016+ pr_info("br{"
4017+ "xino %d, "
4018+ "id %d, perm %d, mnt %d, count %d, "
4019+ "wbr %d, "
4020+ "xup %d, xrun %d, "
4021+ "gen %d, "
4022+ "sa %d} %d\n",
4023+ offsetof(typeof(*u.br), br_xino),
4024+ offsetof(typeof(*u.br), br_id),
4025+ offsetof(typeof(*u.br), br_perm),
4026+ offsetof(typeof(*u.br), br_mnt),
4027+ offsetof(typeof(*u.br), br_count),
4028+ offsetof(typeof(*u.br), wbr),
4029+ offsetof(typeof(*u.br), br_xino_upper),
4030+ offsetof(typeof(*u.br), br_xino_running),
4031+ offsetof(typeof(*u.br), br_generation),
4032+ offsetof(typeof(*u.br), br_sabr),
4033+ sizeof(*u.br));
4034+ pr_info("di{gen %d, rwsem %d, bstart %d, bend %d, bwh %d, "
4035+ "bdiropq %d, hdentry %d} %d\n",
4036+ offsetof(typeof(*u.di), di_generation),
4037+ offsetof(typeof(*u.di), di_rwsem),
4038+ offsetof(typeof(*u.di), di_bstart),
4039+ offsetof(typeof(*u.di), di_bend),
4040+ offsetof(typeof(*u.di), di_bwh),
4041+ offsetof(typeof(*u.di), di_bdiropq),
4042+ offsetof(typeof(*u.di), di_hdentry),
4043+ sizeof(*u.di));
4044+ pr_info("fi{gen %d, rwsem %d, hfile %d, bstart %d, bend %d, "
4045+ "h_vm_ops %d, vdir_cach %d} %d\n",
4046+ offsetof(typeof(*u.fi), fi_generation),
4047+ offsetof(typeof(*u.fi), fi_rwsem),
4048+ offsetof(typeof(*u.fi), fi_hfile),
4049+ offsetof(typeof(*u.fi), fi_bstart),
4050+ offsetof(typeof(*u.fi), fi_bend),
4051+ offsetof(typeof(*u.fi), fi_h_vm_ops),
4052+ offsetof(typeof(*u.fi), fi_vdir_cache),
4053+ sizeof(*u.fi));
4054+ pr_info("ii{gen %d, hsb %d, "
4055+ "rwsem %d, bstart %d, bend %d, hinode %d, vdir %d} "
4056+ "%d\n",
4057+ offsetof(typeof(*u.ii), ii_generation),
4058+ offsetof(typeof(*u.ii), ii_hsb1),
4059+ offsetof(typeof(*u.ii), ii_rwsem),
4060+ offsetof(typeof(*u.ii), ii_bstart),
4061+ offsetof(typeof(*u.ii), ii_bend),
4062+ offsetof(typeof(*u.ii), ii_hinode),
4063+ offsetof(typeof(*u.ii), ii_vdir),
4064+ sizeof(*u.ii));
4065+ pr_info("hi{inode %d, id %d, notify %d, wh %d} %d\n",
4066+ offsetof(typeof(*u.hi), hi_inode),
4067+ offsetof(typeof(*u.hi), hi_id),
4068+ offsetof(typeof(*u.hi), hi_notify),
4069+ offsetof(typeof(*u.hi), hi_whdentry),
4070+ sizeof(*u.hi));
4071+ pr_info("si{nwt %d, rwsem %d, gen %d, stat %d, "
4072+ "bend %d, last id %d, br %d, "
4073+ "cpup %d, creat %d, ops %d, ops %d, "
4074+ "rr %d, mfs %d, "
4075+ "mntflags %d, "
4076+ "xread %d, xwrite %d, xib %d, xmtx %d, buf %d, "
4077+ "xlast %d, xnext %d, "
4078+ "rdcache %d, "
4079+ "dirwh %d, "
4080+ "pl %d, "
4081+ "mnt %d, "
4082+ "sys %d, "
4083+ /* "lvma_l %d, lvma %d" */
4084+ "} %d\n",
4085+ offsetof(typeof(*u.si), si_nowait),
4086+ offsetof(typeof(*u.si), si_rwsem),
4087+ offsetof(typeof(*u.si), si_generation),
4088+ offsetof(typeof(*u.si), au_si_status),
4089+ offsetof(typeof(*u.si), si_bend),
4090+ offsetof(typeof(*u.si), si_last_br_id),
4091+ offsetof(typeof(*u.si), si_branch),
4092+ offsetof(typeof(*u.si), si_wbr_copyup),
4093+ offsetof(typeof(*u.si), si_wbr_create),
4094+ offsetof(typeof(*u.si), si_wbr_copyup_ops),
4095+ offsetof(typeof(*u.si), si_wbr_create_ops),
4096+ offsetof(typeof(*u.si), si_wbr_rr_next),
4097+ offsetof(typeof(*u.si), si_wbr_mfs),
4098+ offsetof(typeof(*u.si), si_mntflags),
4099+ offsetof(typeof(*u.si), si_xread),
4100+ offsetof(typeof(*u.si), si_xwrite),
4101+ offsetof(typeof(*u.si), si_xib),
4102+ offsetof(typeof(*u.si), si_xib_mtx),
4103+ offsetof(typeof(*u.si), si_xib_buf),
4104+ offsetof(typeof(*u.si), si_xib_last_pindex),
4105+ offsetof(typeof(*u.si), si_xib_next_bit),
4106+ offsetof(typeof(*u.si), si_rdcache),
4107+ offsetof(typeof(*u.si), si_dirwh),
4108+ offsetof(typeof(*u.si), si_plink),
4109+ offsetof(typeof(*u.si), si_mnt),
4110+ offsetof(typeof(*u.si), si_sa),
4111+ /*offsetof(typeof(*u.si), si_lvma_lock),
4112+ offsetof(typeof(*u.si), si_lvma),*/
4113+ sizeof(*u.si));
4114+ pr_info("destr{len %d, name %d} %d\n",
4115+ offsetof(typeof(*u.destr), len),
4116+ offsetof(typeof(*u.destr), name),
4117+ sizeof(*u.destr));
4118+ pr_info("de{ino %d, type %d, str %d} %d\n",
4119+ offsetof(typeof(*u.de), de_ino),
4120+ offsetof(typeof(*u.de), de_type),
4121+ offsetof(typeof(*u.de), de_str),
4122+ sizeof(*u.de));
4123+ pr_info("wh{hash %d, bindex %d, str %d} %d\n",
4124+ offsetof(typeof(*u.wh), wh_hash),
4125+ offsetof(typeof(*u.wh), wh_bindex),
4126+ offsetof(typeof(*u.wh), wh_str),
4127+ sizeof(*u.wh));
4128+ pr_info("vd{deblk %d, nblk %d, last %d, ver %d, jiffy %d} %d\n",
4129+ offsetof(typeof(*u.vd), vd_deblk),
4130+ offsetof(typeof(*u.vd), vd_nblk),
4131+ offsetof(typeof(*u.vd), vd_last),
4132+ offsetof(typeof(*u.vd), vd_version),
4133+ offsetof(typeof(*u.vd), vd_jiffy),
4134+ sizeof(*u.vd));
4135+ }
4136+#endif
4137+
4138+ return 0;
4139+}
4140diff -urN linux/fs/aufs/debug.h linux-aufs/fs/aufs/debug.h
4141--- linux/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
4142+++ linux-aufs/fs/aufs/debug.h 2009-03-12 16:18:04.000000000 +0100
4143@@ -0,0 +1,333 @@
4144+/*
4145+ * Copyright (C) 2005-2009 Junjiro Okajima
4146+ *
4147+ * This program, aufs is free software; you can redistribute it and/or modify
4148+ * it under the terms of the GNU General Public License as published by
4149+ * the Free Software Foundation; either version 2 of the License, or
4150+ * (at your option) any later version.
4151+ *
4152+ * This program is distributed in the hope that it will be useful,
4153+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4154+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4155+ * GNU General Public License for more details.
4156+ *
4157+ * You should have received a copy of the GNU General Public License
4158+ * along with this program; if not, write to the Free Software
4159+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4160+ */
4161+
4162+/*
4163+ * debug print functions
4164+ *
4165+ * $Id$
4166+ */
4167+
4168+#ifndef __AUFS_DEBUG_H__
4169+#define __AUFS_DEBUG_H__
4170+
4171+#ifdef __KERNEL__
4172+
4173+#include <linux/fs.h>
4174+#include <linux/kd.h>
4175+#include <linux/vt_kern.h>
4176+#include <linux/sysrq.h>
4177+
4178+/* to debug easier, do not make it an inlined function */
4179+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
4180+
4181+#ifdef CONFIG_AUFS_DEBUG
4182+/* sparse warns about pointer */
4183+#define AuDebugOn(a) BUG_ON(!!(a))
4184+extern atomic_t au_cond;
4185+#define au_debug_on() atomic_inc_return(&au_cond)
4186+#define au_debug_off() atomic_dec_return(&au_cond)
4187+static inline int au_debug_test(void)
4188+{
4189+ return atomic_read(&au_cond);
4190+}
4191+#else
4192+#define AuDebugOn(a) do {} while (0)
4193+#define au_debug_on() do {} while (0)
4194+#define au_debug_off() do {} while (0)
4195+static inline int au_debug_test(void)
4196+{
4197+ return 0;
4198+}
4199+#endif /* CONFIG_AUFS_DEBUG */
4200+
4201+/* ---------------------------------------------------------------------- */
4202+
4203+/* debug print */
4204+#if defined(CONFIG_LKTR) || defined(CONFIG_LKTR_MODULE)
4205+#include <linux/lktr.h>
4206+#ifdef CONFIG_AUFS_DEBUG
4207+#undef LktrCond
4208+#define LktrCond unlikely(au_debug_test() || (lktr_cond && lktr_cond()))
4209+#endif
4210+#else
4211+#define LktrCond au_debug_test()
4212+#define LKTRDumpVma(pre, vma, suf) do {} while (0)
4213+#define LKTRDumpStack() do {} while (0)
4214+#define LKTRTrace(fmt, args...) do { \
4215+ if (LktrCond) \
4216+ AuDbg(fmt, ##args); \
4217+} while (0)
4218+#define LKTRLabel(label) LKTRTrace("%s\n", #label)
4219+#endif /* CONFIG_LKTR */
4220+
4221+#define AuTraceErr(e) do { \
4222+ if (unlikely((e) < 0)) \
4223+ LKTRTrace("err %d\n", (int)(e)); \
4224+} while (0)
4225+
4226+#define AuTraceErrPtr(p) do { \
4227+ if (IS_ERR(p)) \
4228+ LKTRTrace("err %ld\n", PTR_ERR(p)); \
4229+} while (0)
4230+
4231+#define AuTraceEnter() LKTRLabel(enter)
4232+
4233+/* dirty macros for debug print, use with "%.*s" and caution */
4234+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
4235+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
4236+
4237+/* ---------------------------------------------------------------------- */
4238+
4239+#define AuDpri(lvl, fmt, arg...) \
4240+ printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \
4241+ __func__, __LINE__, current->comm, current->pid, ##arg)
4242+#define AuDbg(fmt, arg...) AuDpri(KERN_DEBUG, fmt, ##arg)
4243+#define AuInfo(fmt, arg...) AuDpri(KERN_INFO, fmt, ##arg)
4244+#define AuWarn(fmt, arg...) AuDpri(KERN_WARNING, fmt, ##arg)
4245+#define AuErr(fmt, arg...) AuDpri(KERN_ERR, fmt, ##arg)
4246+#define AuIOErr(fmt, arg...) AuErr("I/O Error, " fmt, ##arg)
4247+#define AuIOErrWhck(fmt, arg...) AuErr("I/O Error, try whck. " fmt, ##arg)
4248+#define AuWarn1(fmt, arg...) do { \
4249+ static unsigned char _c; \
4250+ if (!_c++) \
4251+ AuWarn(fmt, ##arg); \
4252+} while (0)
4253+
4254+#define AuErr1(fmt, arg...) do { \
4255+ static unsigned char _c; \
4256+ if (!_c++) \
4257+ AuErr(fmt, ##arg); \
4258+} while (0)
4259+
4260+#define AuIOErr1(fmt, arg...) do { \
4261+ static unsigned char _c; \
4262+ if (!_c++) \
4263+ AuIOErr(fmt, ##arg); \
4264+} while (0)
4265+
4266+#define AuUnsupportMsg "This operation is not supported." \
4267+ " Please report this application to aufs-users ML."
4268+#define AuUnsupport(fmt, args...) do { \
4269+ AuErr(AuUnsupportMsg "\n" fmt, ##args); \
4270+ dump_stack(); \
4271+} while (0)
4272+
4273+/* ---------------------------------------------------------------------- */
4274+
4275+struct au_sbinfo;
4276+#ifdef CONFIG_AUFS_DEBUG
4277+extern char *au_plevel;
4278+struct au_nhash;
4279+void au_dpri_whlist(struct au_nhash *whlist);
4280+struct au_vdir;
4281+void au_dpri_vdir(struct au_vdir *vdir);
4282+void au_dpri_inode(struct inode *inode);
4283+void au_dpri_dentry(struct dentry *dentry);
4284+void au_dpri_file(struct file *filp);
4285+void au_dpri_sb(struct super_block *sb);
4286+void au_dbg_sleep(int sec);
4287+void au_dbg_sleep_jiffy(int jiffy);
4288+
4289+#ifndef ATTR_TIMES_SET
4290+#define ATTR_TIMES_SET 0
4291+#endif
4292+void au_dbg_iattr(struct iattr *ia);
4293+int __init au_debug_init(void);
4294+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
4295+#define AuDbgWhlist(w) do { \
4296+ LKTRTrace(#w "\n"); \
4297+ au_dpri_whlist(w); \
4298+} while (0)
4299+
4300+#define AuDbgVdir(v) do { \
4301+ LKTRTrace(#v "\n"); \
4302+ au_dpri_vdir(v); \
4303+} while (0)
4304+
4305+#define AuDbgInode(i) do { \
4306+ LKTRTrace(#i "\n"); \
4307+ au_dpri_inode(i); \
4308+} while (0)
4309+
4310+#define AuDbgDentry(d) do { \
4311+ LKTRTrace(#d "\n"); \
4312+ au_dpri_dentry(d); \
4313+} while (0)
4314+
4315+#define AuDbgFile(f) do { \
4316+ LKTRTrace(#f "\n"); \
4317+ au_dpri_file(f); \
4318+} while (0)
4319+
4320+#define AuDbgSb(sb) do { \
4321+ LKTRTrace(#sb "\n"); \
4322+ au_dpri_sb(sb); \
4323+} while (0)
4324+
4325+#define AuDbgSleep(sec) do { \
4326+ AuDbg("sleep %d sec\n", sec); \
4327+ au_dbg_sleep(sec); \
4328+} while (0)
4329+
4330+#define AuDbgSleepJiffy(jiffy) do { \
4331+ AuDbg("sleep %d jiffies\n", jiffy); \
4332+ au_dbg_sleep_jiffy(jiffy); \
4333+} while (0)
4334+
4335+#define AuDbgIAttr(ia) do { \
4336+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
4337+ au_dbg_iattr(ia); \
4338+} while (0)
4339+#else
4340+static inline int au_debug_init(void)
4341+{
4342+ return 0;
4343+}
4344+static inline void au_debug_sbinfo_init(struct au_sbinfo *sbinfo)
4345+{
4346+ /* empty */
4347+}
4348+#define AuDbgWhlist(w) do {} while (0)
4349+#define AuDbgVdir(v) do {} while (0)
4350+#define AuDbgInode(i) do {} while (0)
4351+#define AuDbgDentry(d) do {} while (0)
4352+#define AuDbgFile(f) do {} while (0)
4353+#define AuDbgSb(sb) do {} while (0)
4354+#define AuDbgSleep(sec) do {} while (0)
4355+#define AuDbgSleepJiffy(jiffy) do {} while (0)
4356+#define AuDbgIAttr(ia) do {} while (0)
4357+#endif /* CONFIG_AUFS_DEBUG */
4358+
4359+#ifdef DbgUdbaRace
4360+#define AuDbgSleep_UdbaRace() AuDbgSleep(DbgUdbaRace)
4361+#else
4362+#define AuDbgSleep_UdbaRace() do {} while (0)
4363+#endif
4364+
4365+/* ---------------------------------------------------------------------- */
4366+
4367+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
4368+int __init au_sysrq_init(void);
4369+void au_sysrq_fin(void);
4370+
4371+#ifdef CONFIG_HW_CONSOLE
4372+#define au_dbg_blocked() do { \
4373+ WARN_ON(1); \
4374+ handle_sysrq('w', vc_cons[fg_console].d->vc_tty); \
4375+} while (0)
4376+#else
4377+#define au_dbg_blocked() do {} while (0)
4378+#endif
4379+
4380+#else
4381+static inline int au_sysrq_init(void)
4382+{
4383+ return 0;
4384+}
4385+#define au_sysrq_fin() do {} while (0)
4386+#define au_dbg_blocked() do {} while (0)
4387+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
4388+
4389+enum {
4390+ AuDbgLock_SI_LOCKING,
4391+ AuDbgLock_SI_LOCKED,
4392+ AuDbgLock_DI_LOCKING,
4393+ AuDbgLock_DI_LOCKED,
4394+ AuDbgLock_II_LOCKING,
4395+ AuDbgLock_II_LOCKED,
4396+ AuDbgLock_Last
4397+};
4398+#ifdef CONFIG_AUFS_DEBUG_LOCK
4399+void au_dbg_locking_si_reg(struct super_block *sb, int flags);
4400+void au_dbg_locking_si_unreg(struct super_block *sb, int flags);
4401+void au_dbg_locked_si_reg(struct super_block *sb, int flags);
4402+void au_dbg_locked_si_unreg(struct super_block *sb, int flags);
4403+void au_dbg_locking_di_reg(struct dentry *d, int flags, unsigned int lsc);
4404+void au_dbg_locking_di_unreg(struct dentry *d, int flags);
4405+void au_dbg_locked_di_reg(struct dentry *d, int flags, unsigned int lsc);
4406+void au_dbg_locked_di_unreg(struct dentry *d, int flags);
4407+void au_dbg_locking_ii_reg(struct inode *i, int flags, unsigned int lsc);
4408+void au_dbg_locking_ii_unreg(struct inode *i, int flags);
4409+void au_dbg_locked_ii_reg(struct inode *i, int flags, unsigned int lsc);
4410+void au_dbg_locked_ii_unreg(struct inode *i, int flags);
4411+#else
4412+static inline
4413+void au_dbg_locking_si_reg(struct super_block *sb, int flags)
4414+{
4415+ /* empty */
4416+}
4417+static inline
4418+void au_dbg_locking_si_unreg(struct super_block *sb, int flags)
4419+{
4420+ /* empty */
4421+}
4422+static inline
4423+void au_dbg_locked_si_reg(struct super_block *sb, int flags)
4424+{
4425+ /* empty */
4426+}
4427+static inline
4428+void au_dbg_locked_si_unreg(struct super_block *sb, int flags)
4429+{
4430+ /* empty */
4431+}
4432+
4433+static inline
4434+void au_dbg_locking_di_reg(struct dentry *d, int flags, unsigned int lsc)
4435+{
4436+ /* empty */
4437+}
4438+static inline
4439+void au_dbg_locking_di_unreg(struct dentry *d, int flags)
4440+{
4441+ /* empty */
4442+}
4443+static inline
4444+void au_dbg_locked_di_reg(struct dentry *d, int flags, unsigned int lsc)
4445+{
4446+ /* empty */
4447+}
4448+static inline
4449+void au_dbg_locked_di_unreg(struct dentry *d, int flags)
4450+{
4451+ /* empty */
4452+}
4453+static inline
4454+void au_dbg_locking_ii_reg(struct inode *i, int flags, unsigned int lsc)
4455+{
4456+ /* empty */
4457+}
4458+static inline
4459+void au_dbg_locking_ii_unreg(struct inode *i, int flags)
4460+{
4461+ /* empty */
4462+}
4463+static inline
4464+void au_dbg_locked_ii_reg(struct inode *i, int flags, unsigned int lsc)
4465+{
4466+ /* empty */
4467+}
4468+static inline
4469+void au_dbg_locked_ii_unreg(struct inode *i, int flags)
4470+{
4471+ /* empty */
4472+}
4473+#endif /* CONFIG_AUFS_DEBUG_LOCK */
4474+
4475+#endif /* __KERNEL__ */
4476+#endif /* __AUFS_DEBUG_H__ */
4477diff -urN linux/fs/aufs/dentry.c linux-aufs/fs/aufs/dentry.c
4478--- linux/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
4479+++ linux-aufs/fs/aufs/dentry.c 2009-03-12 16:18:04.000000000 +0100
4480@@ -0,0 +1,972 @@
4481+/*
4482+ * Copyright (C) 2005-2009 Junjiro Okajima
4483+ *
4484+ * This program, aufs is free software; you can redistribute it and/or modify
4485+ * it under the terms of the GNU General Public License as published by
4486+ * the Free Software Foundation; either version 2 of the License, or
4487+ * (at your option) any later version.
4488+ *
4489+ * This program is distributed in the hope that it will be useful,
4490+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4491+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4492+ * GNU General Public License for more details.
4493+ *
4494+ * You should have received a copy of the GNU General Public License
4495+ * along with this program; if not, write to the Free Software
4496+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4497+ */
4498+
4499+/*
4500+ * lookup and dentry operations
4501+ *
4502+ * $Id$
4503+ */
4504+
4505+#include "aufs.h"
4506+
4507+/* ---------------------------------------------------------------------- */
4508+
4509+/*
4510+ * au_lkup_one() is a generic abstract entry function which calls
4511+ * lookup_one_len() or __lookup_hash() finally. it is some condisions that makes
4512+ * lookup complicated, which are nfs branch, open-intent and dlgt mode.
4513+ */
4514+
4515+#if defined(CONFIG_AUFS_BR_NFS) || defined(CONFIG_AUFS_DLGT)
4516+/* cf. lookup_one_len() in linux/fs/namei.c */
4517+struct dentry *au_lkup_one(const char *name, struct dentry *parent, int len,
4518+ struct au_ndx *ndx)
4519+{
4520+ struct dentry *dentry;
4521+
4522+ LKTRTrace("%.*s/%.*s, ndx{%d, 0x%x}\n",
4523+ AuDLNPair(parent), len, name, !!ndx->nfsmnt, ndx->flags);
4524+
4525+ ndx->nd_file = NULL;
4526+ if (!ndx->nfsmnt)
4527+ dentry = au_lkup_one_dlgt(name, parent, len, ndx->flags);
4528+ else
4529+ dentry = au_lkup_hash(name, parent, len, ndx);
4530+
4531+ AuTraceErrPtr(dentry);
4532+ return dentry;
4533+}
4534+#endif /* CONFIG_AUFS_BR_NFS || CONFIG_AUFS_DLGT */
4535+
4536+struct au_lkup_one_args {
4537+ struct dentry **errp;
4538+ const char *name;
4539+ struct dentry *parent;
4540+ int len;
4541+ struct au_ndx *ndx;
4542+};
4543+
4544+static void au_call_lkup_one(void *args)
4545+{
4546+ struct au_lkup_one_args *a = args;
4547+ *a->errp = au_lkup_one(a->name, a->parent, a->len, a->ndx);
4548+}
4549+
4550+#define AuLkup_ALLOW_NEG 1
4551+#define AuLkup_DLGT (1 << 1)
4552+#define AuLkup_DIRPERM1 (1 << 2)
4553+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
4554+#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; }
4555+#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; }
4556+#ifndef CONFIG_AUFS_DLGT
4557+#undef AuLkup_DLGT
4558+#define AuLkup_DLGT 0
4559+#undef AuLkup_DIRPERM1
4560+#define AuLkup_DIRPERM1 0
4561+#endif
4562+
4563+struct au_do_lookup_args {
4564+ unsigned int flags;
4565+ mode_t type;
4566+ struct nameidata *nd;
4567+};
4568+
4569+/*
4570+ * returns positive/negative dentry, NULL or an error.
4571+ * NULL means whiteout-ed or not-found.
4572+ */
4573+static /* noinline_for_stack */
4574+struct dentry *au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
4575+ aufs_bindex_t bindex, struct qstr *wh_name,
4576+ struct au_do_lookup_args *args)
4577+{
4578+ struct dentry *h_dentry;
4579+ int err, wh_found, opq;
4580+ unsigned char wh_able;
4581+ struct inode *h_dir, *h_inode, *inode;
4582+ struct qstr *name;
4583+ struct super_block *sb;
4584+ unsigned int nd_flags;
4585+ struct au_ndx ndx = {
4586+ .flags = 0,
4587+ .nd = args->nd
4588+ };
4589+ const int allow_neg = au_ftest_lkup(args->flags, ALLOW_NEG);
4590+
4591+ LKTRTrace("%.*s/%.*s, b%d, {flags 0x%x, type 0%o, nd %d}\n",
4592+ AuDLNPair(h_parent), AuDLNPair(dentry), bindex,
4593+ args->flags, args->type, !!args->nd);
4594+ if (args->nd)
4595+ LKTRTrace("nd{0x%x}\n", args->nd->flags);
4596+ AuDebugOn(IS_ROOT(dentry));
4597+ h_dir = h_parent->d_inode;
4598+
4599+ nd_flags = 0;
4600+ wh_found = 0;
4601+ sb = dentry->d_sb;
4602+ ndx.nfsmnt = au_nfsmnt(sb, bindex);
4603+ if (au_ftest_lkup(args->flags, DLGT))
4604+ au_fset_ndx(ndx.flags, DLGT);
4605+ if (au_ftest_lkup(args->flags, DIRPERM1))
4606+ au_fset_ndx(ndx.flags, DIRPERM1);
4607+ LKTRTrace("nfsmnt %p\n", ndx.nfsmnt);
4608+ ndx.br = au_sbr(sb, bindex);
4609+ wh_able = !!au_br_whable(ndx.br->br_perm);
4610+ name = &dentry->d_name;
4611+ if (wh_able)
4612+ wh_found = au_test_robr_wh(name, h_parent, wh_name,
4613+ /*try_sio*/0, &ndx);
4614+ h_dentry = ERR_PTR(wh_found);
4615+ if (!wh_found)
4616+ goto real_lookup;
4617+ if (unlikely(wh_found < 0))
4618+ goto out;
4619+
4620+ /* We found a whiteout */
4621+ /* au_set_dbend(dentry, bindex); */
4622+ au_set_dbwh(dentry, bindex);
4623+ if (!allow_neg)
4624+ return NULL; /* success */
4625+ if (ndx.nd
4626+ && au_test_nfs(h_parent->d_sb)
4627+ && (ndx.nd->flags & LOOKUP_CREATE)) {
4628+ nd_flags = ndx.nd->flags;
4629+ ndx.nd->flags &= ~(LOOKUP_OPEN | LOOKUP_CREATE);
4630+ }
4631+
4632+ real_lookup:
4633+ /* do not superio. */
4634+ h_dentry = au_lkup_one(name->name, h_parent, name->len, &ndx);
4635+ if (IS_ERR(h_dentry))
4636+ goto out;
4637+ AuDebugOn(d_unhashed(h_dentry));
4638+ h_inode = h_dentry->d_inode;
4639+ if (!h_inode) {
4640+ if (!allow_neg)
4641+ goto out_neg;
4642+ } else if (wh_found
4643+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
4644+ goto out_neg;
4645+
4646+ if (au_dbend(dentry) <= bindex)
4647+ au_set_dbend(dentry, bindex);
4648+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4649+ au_set_dbstart(dentry, bindex);
4650+ au_set_h_dptr(dentry, bindex, h_dentry);
4651+
4652+ err = au_br_nfs_h_intent(ndx.nd_file, dentry, bindex, args->nd);
4653+ if (unlikely(err)) {
4654+ h_dentry = ERR_PTR(err);
4655+ goto out;
4656+ }
4657+
4658+ inode = dentry->d_inode;
4659+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4660+ || (inode && !S_ISDIR(inode->i_mode)))
4661+ goto out; /* success */
4662+
4663+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4664+ opq = au_diropq_test(h_dentry, &ndx);
4665+ mutex_unlock(&h_inode->i_mutex);
4666+ if (opq > 0)
4667+ au_set_dbdiropq(dentry, bindex);
4668+ else if (unlikely(opq < 0)) {
4669+ au_set_h_dptr(dentry, bindex, NULL);
4670+ h_dentry = ERR_PTR(opq);
4671+ }
4672+ goto out;
4673+
4674+ out_neg:
4675+ dput(h_dentry);
4676+ h_dentry = NULL;
4677+ out:
4678+ if (nd_flags)
4679+ ndx.nd->flags |= (nd_flags & (LOOKUP_OPEN | LOOKUP_CREATE));
4680+ AuTraceErrPtr(h_dentry);
4681+ return h_dentry;
4682+}
4683+
4684+/*
4685+ * returns the number of hidden positive dentries,
4686+ * otherwise an error.
4687+ * can be called at unlinking with @type is zero.
4688+ */
4689+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4690+ struct nameidata *nd)
4691+{
4692+ int npositive, err;
4693+ unsigned int mnt_flags;
4694+ aufs_bindex_t bindex, btail, bdiropq;
4695+ unsigned char isdir;
4696+ struct qstr whname;
4697+ struct au_do_lookup_args args = {
4698+ .type = type,
4699+ .nd = nd
4700+ };
4701+ const struct qstr *name = &dentry->d_name;
4702+ struct dentry *parent;
4703+ struct super_block *sb;
4704+ struct inode *inode;
4705+
4706+ LKTRTrace("%.*s, b%d, type 0%o\n", AuLNPair(name), bstart, type);
4707+ AuDebugOn(bstart < 0 || IS_ROOT(dentry));
4708+
4709+ /* dir may not be locked */
4710+ parent = dget_parent(dentry);
4711+
4712+ err = au_test_robr_shwh(dentry->d_sb, name);
4713+ if (unlikely(err))
4714+ goto out;
4715+
4716+ err = au_wh_name_alloc(name->name, name->len, &whname);
4717+ if (unlikely(err))
4718+ goto out;
4719+
4720+ sb = dentry->d_sb;
4721+ mnt_flags = au_mntflags(sb);
4722+ inode = dentry->d_inode;
4723+ isdir = !!(inode && S_ISDIR(inode->i_mode));
4724+ args.flags = 0;
4725+ if (au_test_dlgt(mnt_flags))
4726+ au_fset_lkup(args.flags, DLGT);
4727+ if (au_test_dirperm1(mnt_flags))
4728+ au_fset_lkup(args.flags, DIRPERM1);
4729+ if (!type)
4730+ au_fset_lkup(args.flags, ALLOW_NEG);
4731+ npositive = 0;
4732+ btail = au_dbtaildir(parent);
4733+ for (bindex = bstart; bindex <= btail; bindex++) {
4734+ struct dentry *h_parent, *h_dentry;
4735+ struct inode *h_inode, *h_dir;
4736+
4737+ h_dentry = au_h_dptr(dentry, bindex);
4738+ if (h_dentry) {
4739+ if (h_dentry->d_inode)
4740+ npositive++;
4741+ if (type != S_IFDIR)
4742+ break;
4743+ continue;
4744+ }
4745+ h_parent = au_h_dptr(parent, bindex);
4746+ if (!h_parent)
4747+ continue;
4748+ h_dir = h_parent->d_inode;
4749+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
4750+ continue;
4751+
4752+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4753+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4754+ &args);
4755+ mutex_unlock(&h_dir->i_mutex);
4756+ err = PTR_ERR(h_dentry);
4757+ if (IS_ERR(h_dentry))
4758+ goto out_wh;
4759+ au_fclr_lkup(args.flags, ALLOW_NEG);
4760+
4761+ if (au_dbwh(dentry) >= 0)
4762+ break;
4763+ if (!h_dentry)
4764+ continue;
4765+ h_inode = h_dentry->d_inode;
4766+ if (!h_inode)
4767+ continue;
4768+ npositive++;
4769+ if (!args.type)
4770+ args.type = h_inode->i_mode & S_IFMT;
4771+ if (args.type != S_IFDIR)
4772+ break;
4773+ else if (isdir) {
4774+ /* the type of lowers may be different */
4775+ bdiropq = au_dbdiropq(dentry);
4776+ if (bdiropq >= 0 && bdiropq <= bindex)
4777+ break;
4778+ }
4779+ }
4780+
4781+ if (npositive) {
4782+ LKTRLabel(positive);
4783+ au_update_dbstart(dentry);
4784+ }
4785+ err = npositive;
4786+ if (!au_opt_test(mnt_flags, UDBA_NONE) && au_dbstart(dentry) < 0)
4787+ /* both of real entry and whiteout found */
4788+ err = -EIO;
4789+
4790+ out_wh:
4791+ au_wh_name_free(&whname);
4792+ out:
4793+ dput(parent);
4794+ AuTraceErr(err);
4795+ return err;
4796+}
4797+
4798+struct dentry *au_sio_lkup_one(const char *name, struct dentry *parent, int len,
4799+ struct au_ndx *ndx)
4800+{
4801+ struct dentry *dentry;
4802+ int wkq_err;
4803+
4804+ LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name);
4805+
4806+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC,
4807+ au_ftest_ndx(ndx->flags, DLGT)))
4808+ dentry = au_lkup_one(name, parent, len, ndx);
4809+ else {
4810+ /* todo: ugly? */
4811+ unsigned int flags = ndx->flags;
4812+ struct au_lkup_one_args args = {
4813+ .errp = &dentry,
4814+ .name = name,
4815+ .parent = parent,
4816+ .len = len,
4817+ .ndx = ndx
4818+ };
4819+
4820+ au_fclr_ndx(ndx->flags, DLGT);
4821+ au_fclr_ndx(ndx->flags, DIRPERM1);
4822+ wkq_err = au_wkq_wait(au_call_lkup_one, &args, /*dlgt*/0);
4823+ if (unlikely(wkq_err))
4824+ dentry = ERR_PTR(wkq_err);
4825+ ndx->flags = flags;
4826+ }
4827+
4828+ AuTraceErrPtr(dentry);
4829+ return dentry;
4830+}
4831+
4832+/*
4833+ * lookup @dentry on @bindex which should be negative.
4834+ */
4835+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4836+{
4837+ int err;
4838+ struct dentry *parent, *h_parent, *h_dentry;
4839+ struct inode *h_dir;
4840+ struct au_ndx ndx = {
4841+ .flags = 0,
4842+ .nd = NULL,
4843+ /* .br = NULL */
4844+ };
4845+ struct super_block *sb;
4846+ unsigned int mnt_flags;
4847+
4848+ LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex);
4849+ /* dir may not be locked */
4850+ parent = dget_parent(dentry);
4851+ AuDebugOn(!parent || !parent->d_inode
4852+ || !S_ISDIR(parent->d_inode->i_mode));
4853+ h_parent = au_h_dptr(parent, bindex);
4854+ AuDebugOn(!h_parent);
4855+ h_dir = h_parent->d_inode;
4856+ AuDebugOn(!h_dir || !S_ISDIR(h_dir->i_mode));
4857+
4858+ sb = dentry->d_sb;
4859+ mnt_flags = au_mntflags(sb);
4860+ ndx.nfsmnt = au_nfsmnt(sb, bindex);
4861+ if (au_test_dlgt(mnt_flags))
4862+ au_fset_ndx(ndx.flags, DLGT);
4863+ if (au_test_dirperm1(mnt_flags))
4864+ au_fset_ndx(ndx.flags, DIRPERM1);
4865+ h_dentry = au_sio_lkup_one(dentry->d_name.name, h_parent,
4866+ dentry->d_name.len, &ndx);
4867+ err = PTR_ERR(h_dentry);
4868+ if (IS_ERR(h_dentry))
4869+ goto out;
4870+ if (unlikely(h_dentry->d_inode)) {
4871+ err = -EIO;
4872+ AuIOErr("b%d %.*s should be negative.\n",
4873+ bindex, AuDLNPair(h_dentry));
4874+ dput(h_dentry);
4875+ goto out;
4876+ }
4877+
4878+ if (bindex < au_dbstart(dentry))
4879+ au_set_dbstart(dentry, bindex);
4880+ if (au_dbend(dentry) < bindex)
4881+ au_set_dbend(dentry, bindex);
4882+ au_set_h_dptr(dentry, bindex, h_dentry);
4883+ err = 0;
4884+
4885+ out:
4886+ dput(parent);
4887+ AuTraceErr(err);
4888+ return err;
4889+}
4890+
4891+/*
4892+ * returns the number of found hidden positive dentries,
4893+ * otherwise an error.
4894+ */
4895+int au_refresh_hdentry(struct dentry *dentry, mode_t type)
4896+{
4897+ int npositive, new_sz;
4898+ struct au_dinfo *dinfo;
4899+ struct super_block *sb;
4900+ struct dentry *parent;
4901+ aufs_bindex_t bindex, parent_bend, parent_bstart, bwh, bdiropq, bend;
4902+ struct au_hdentry *p;
4903+ au_gen_t sgen;
4904+
4905+ LKTRTrace("%.*s, type 0%o\n", AuDLNPair(dentry), type);
4906+ DiMustWriteLock(dentry);
4907+ sb = dentry->d_sb;
4908+ AuDebugOn(IS_ROOT(dentry));
4909+ sgen = au_sigen(sb);
4910+ parent = dget_parent(dentry);
4911+ AuDebugOn(au_digen(parent) != sgen
4912+ || au_iigen(parent->d_inode) != sgen);
4913+
4914+ npositive = -ENOMEM;
4915+ new_sz = sizeof(*dinfo->di_hdentry) * (au_sbend(sb) + 1);
4916+ dinfo = au_di(dentry);
4917+ p = au_kzrealloc(dinfo->di_hdentry, sizeof(*p) * (dinfo->di_bend + 1),
4918+ new_sz, GFP_NOFS);
4919+ if (unlikely(!p))
4920+ goto out;
4921+ dinfo->di_hdentry = p;
4922+
4923+ bend = dinfo->di_bend;
4924+ bwh = dinfo->di_bwh;
4925+ bdiropq = dinfo->di_bdiropq;
4926+ p += dinfo->di_bstart;
4927+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
4928+ struct dentry *hd, *hdp;
4929+ struct au_hdentry tmp, *q;
4930+ aufs_bindex_t new_bindex;
4931+
4932+ hd = p->hd_dentry;
4933+ if (!hd)
4934+ continue;
4935+ hdp = dget_parent(hd);
4936+ if (hdp == au_h_dptr(parent, bindex)) {
4937+ dput(hdp);
4938+ continue;
4939+ }
4940+
4941+ new_bindex = au_find_dbindex(parent, hdp);
4942+ dput(hdp);
4943+ AuDebugOn(new_bindex == bindex);
4944+ if (dinfo->di_bwh == bindex)
4945+ bwh = new_bindex;
4946+ if (dinfo->di_bdiropq == bindex)
4947+ bdiropq = new_bindex;
4948+ /* todo: test more? */
4949+ if (new_bindex < 0) {
4950+ au_hdput(p, /*do_free*/0);
4951+ p->hd_dentry = NULL;
4952+ continue;
4953+ }
4954+ /* swap two hidden dentries, and loop again */
4955+ q = dinfo->di_hdentry + new_bindex;
4956+ tmp = *q;
4957+ *q = *p;
4958+ *p = tmp;
4959+ if (tmp.hd_dentry) {
4960+ bindex--;
4961+ p--;
4962+ }
4963+ }
4964+
4965+ /* todo: test more? */
4966+ dinfo->di_bwh = -1;
4967+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
4968+ dinfo->di_bwh = bwh;
4969+ dinfo->di_bdiropq = -1;
4970+ if (bdiropq >= 0
4971+ && bdiropq <= au_sbend(sb)
4972+ && au_sbr_whable(sb, bdiropq))
4973+ dinfo->di_bdiropq = bdiropq;
4974+ parent_bend = au_dbend(parent);
4975+ p = dinfo->di_hdentry;
4976+ for (bindex = 0; bindex <= parent_bend; bindex++, p++)
4977+ if (p->hd_dentry) {
4978+ dinfo->di_bstart = bindex;
4979+ break;
4980+ }
4981+ p = dinfo->di_hdentry + parent_bend;
4982+ for (bindex = parent_bend; bindex >= 0; bindex--, p--)
4983+ if (p->hd_dentry) {
4984+ dinfo->di_bend = bindex;
4985+ break;
4986+ }
4987+
4988+ npositive = 0;
4989+ parent_bstart = au_dbstart(parent);
4990+ if (type != S_IFDIR && dinfo->di_bstart == parent_bstart)
4991+ goto out_dgen; /* success */
4992+
4993+ npositive = au_lkup_dentry(dentry, parent_bstart, type, /*nd*/NULL);
4994+ if (npositive < 0)
4995+ goto out;
4996+ if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
4997+ d_drop(dentry);
4998+
4999+ out_dgen:
5000+ au_update_digen(dentry);
5001+ out:
5002+ dput(parent);
5003+ AuTraceErr(npositive);
5004+ return npositive;
5005+}
5006+
5007+static int au_lock_nd(struct dentry *dentry, struct nameidata *nd)
5008+{
5009+ int locked = 0;
5010+ if (nd && dentry != nd->path.dentry) {
5011+ di_read_lock_parent(nd->path.dentry, 0);
5012+ locked = 1;
5013+ }
5014+ return locked;
5015+}
5016+
5017+static void au_unlock_nd(int locked, struct nameidata *nd)
5018+{
5019+ if (locked)
5020+ di_read_unlock(nd->path.dentry, 0);
5021+}
5022+
5023+/* #define TestingFuse */
5024+static noinline_for_stack
5025+int au_do_h_d_reval(struct dentry *dentry, aufs_bindex_t bindex,
5026+ struct nameidata *nd, struct dentry *h_dentry)
5027+{
5028+ int err, valid, e;
5029+ int (*reval)(struct dentry *, struct nameidata *);
5030+ struct super_block *sb;
5031+ struct nameidata fake_nd, *p;
5032+
5033+ LKTRTrace("%.*s, b%d, nd %d\n", AuDLNPair(dentry), bindex, !!nd);
5034+
5035+ err = 0;
5036+ reval = NULL;
5037+ if (h_dentry->d_op)
5038+ reval = h_dentry->d_op->d_revalidate;
5039+ if (!reval)
5040+ goto out;
5041+
5042+ sb = dentry->d_sb;
5043+ if (nd) {
5044+ memcpy(&fake_nd, nd, sizeof(*nd));
5045+ err = au_fake_intent(&fake_nd, au_sbr(sb, bindex));
5046+ if (unlikely(err)) {
5047+ err = -EINVAL;
5048+ goto out;
5049+ }
5050+ }
5051+ p = au_fake_dm(&fake_nd, nd, sb, bindex);
5052+ AuDebugOn(IS_ERR(p));
5053+ AuDebugOn(nd && p != &fake_nd);
5054+ LKTRTrace("b%d\n", bindex);
5055+
5056+ /* it may return tri-state */
5057+ valid = reval(h_dentry, p);
5058+ if (unlikely(valid < 0))
5059+ err = valid;
5060+ else if (!valid)
5061+ err = -EINVAL;
5062+ else
5063+ AuDebugOn(err);
5064+
5065+ if (p) {
5066+ AuDebugOn(!nd);
5067+ e = au_hin_after_reval(p, dentry, bindex, nd->intent.open.file);
5068+#ifndef TestingFuse
5069+ au_update_fuse_h_inode(p->path.mnt, h_dentry); /*ignore*/
5070+#endif
5071+ if (unlikely(e && !err))
5072+ err = e;
5073+ }
5074+#ifndef TestingFuse
5075+ else
5076+ au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
5077+#endif
5078+ au_fake_dm_release(p);
5079+
5080+ out:
5081+ AuTraceErr(err);
5082+ return err;
5083+}
5084+
5085+static noinline_for_stack
5086+int h_d_revalidate(struct dentry *dentry, struct inode *inode,
5087+ struct nameidata *nd, int do_udba)
5088+{
5089+ int err;
5090+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
5091+ unsigned char plus, locked, unhashed, is_root, h_plus;
5092+ struct super_block *sb;
5093+ struct inode *first, *h_inode, *h_cached_inode;
5094+ umode_t mode, h_mode;
5095+ struct dentry *h_dentry;
5096+ struct qstr *name;
5097+
5098+ LKTRTrace("%.*s, nd %d\n", AuDLNPair(dentry), !!nd);
5099+ AuDebugOn(inode && au_digen(dentry) != au_iigen(inode));
5100+
5101+ err = 0;
5102+ sb = dentry->d_sb;
5103+ plus = 0;
5104+ mode = 0;
5105+ first = NULL;
5106+ ibs = -1;
5107+ ibe = -1;
5108+ unhashed = !!d_unhashed(dentry);
5109+ is_root = !!IS_ROOT(dentry);
5110+ name = &dentry->d_name;
5111+
5112+ /*
5113+ * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
5114+ * But inotify doesn't fire some necessary events,
5115+ * IN_ATTRIB for atime/nlink/pageio
5116+ * IN_DELETE for NFS dentry
5117+ * Let's do REVAL test too.
5118+ */
5119+ if (do_udba && inode) {
5120+ mode = (inode->i_mode & S_IFMT);
5121+ plus = (inode->i_nlink > 0);
5122+ first = au_h_iptr(inode, au_ibstart(inode));
5123+ ibs = au_ibstart(inode);
5124+ ibe = au_ibend(inode);
5125+ }
5126+
5127+ bstart = au_dbstart(dentry);
5128+ btail = bstart;
5129+ if (inode && S_ISDIR(inode->i_mode))
5130+ btail = au_dbtaildir(dentry);
5131+ locked = !!au_lock_nd(dentry, nd);
5132+ for (bindex = bstart; bindex <= btail; bindex++) {
5133+ h_dentry = au_h_dptr(dentry, bindex);
5134+ if (!h_dentry)
5135+ continue;
5136+
5137+ LKTRTrace("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
5138+#ifdef TestingFuse
5139+ /* force re-lookup for fuse, in order to update attributes */
5140+ if (au_test_fuse(h_dentry->d_sb))
5141+ goto err;
5142+#endif
5143+
5144+ if (unlikely(do_udba
5145+ && !is_root
5146+ && (unhashed != !!d_unhashed(h_dentry)
5147+ || name->len != h_dentry->d_name.len
5148+ || memcmp(name->name, h_dentry->d_name.name,
5149+ name->len)
5150+ ))) {
5151+ LKTRTrace("unhash 0x%x 0x%x, %.*s %.*s\n",
5152+ unhashed, d_unhashed(h_dentry),
5153+ AuDLNPair(dentry), AuDLNPair(h_dentry));
5154+ goto err;
5155+ }
5156+
5157+ err = au_do_h_d_reval(dentry, bindex, nd, h_dentry);
5158+ if (unlikely(err))
5159+ /* do not goto err, to keep the errno */
5160+ break;
5161+
5162+ /* todo: plink too? */
5163+ if (!do_udba)
5164+ continue;
5165+
5166+ /* UDBA tests */
5167+ h_inode = h_dentry->d_inode;
5168+ if (unlikely(!!inode != !!h_inode))
5169+ goto err;
5170+
5171+ h_plus = plus;
5172+ h_mode = mode;
5173+ h_cached_inode = h_inode;
5174+ if (h_inode) {
5175+ h_mode = (h_inode->i_mode & S_IFMT);
5176+ h_plus = (h_inode->i_nlink > 0);
5177+ }
5178+ if (inode && ibs <= bindex && bindex <= ibe)
5179+ h_cached_inode = au_h_iptr(inode, bindex);
5180+
5181+ LKTRTrace("{%d, 0%o, %p}, h{%d, 0%o, %p}\n",
5182+ plus, mode, h_cached_inode,
5183+ h_plus, h_mode, h_inode);
5184+ if (unlikely(plus != h_plus
5185+ || mode != h_mode
5186+ || h_cached_inode != h_inode))
5187+ goto err;
5188+ continue;
5189+
5190+ err:
5191+ err = -EINVAL;
5192+ break;
5193+ }
5194+ au_unlock_nd(locked, nd);
5195+
5196+ /*
5197+ * judging by timestamps is meaningless since some filesystem uses
5198+ * CURRENT_TIME_SEC instead of CURRENT_TIME.
5199+ */
5200+ /*
5201+ * NFS may stop IN_DELETE because of DCACHE_NFSFS_RENAMED.
5202+ */
5203+
5204+ AuTraceErr(err);
5205+ return err;
5206+}
5207+
5208+static int simple_reval_dpath(struct dentry *dentry, au_gen_t sgen)
5209+{
5210+ int err;
5211+ mode_t type;
5212+ struct dentry *parent;
5213+ struct inode *inode;
5214+
5215+ LKTRTrace("%.*s, sgen %d\n", AuDLNPair(dentry), sgen);
5216+ SiMustAnyLock(dentry->d_sb);
5217+ DiMustWriteLock(dentry);
5218+ inode = dentry->d_inode;
5219+ AuDebugOn(!inode);
5220+
5221+ if (au_digen(dentry) == sgen && au_iigen(inode) == sgen)
5222+ return 0;
5223+
5224+ parent = dget_parent(dentry);
5225+ di_read_lock_parent(parent, AuLock_IR);
5226+ AuDebugOn(au_digen(parent) != sgen
5227+ || au_iigen(parent->d_inode) != sgen);
5228+#ifdef CONFIG_AUFS_DEBUG
5229+ {
5230+ int i, j;
5231+ struct au_dcsub_pages dpages;
5232+ struct au_dpage *dpage;
5233+ struct dentry **dentries;
5234+
5235+ err = au_dpages_init(&dpages, GFP_NOFS);
5236+ AuDebugOn(err);
5237+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL,
5238+ NULL);
5239+ AuDebugOn(err);
5240+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
5241+ dpage = dpages.dpages + i;
5242+ dentries = dpage->dentries;
5243+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
5244+ AuDebugOn(au_digen(dentries[j]) != sgen);
5245+ }
5246+ au_dpages_free(&dpages);
5247+ }
5248+#endif
5249+ type = (inode->i_mode & S_IFMT);
5250+ /* returns a number of positive dentries */
5251+ err = au_refresh_hdentry(dentry, type);
5252+ if (err >= 0)
5253+ err = au_refresh_hinode(inode, dentry);
5254+ di_read_unlock(parent, AuLock_IR);
5255+ dput(parent);
5256+ AuTraceErr(err);
5257+ return err;
5258+}
5259+
5260+int au_reval_dpath(struct dentry *dentry, au_gen_t sgen)
5261+{
5262+ int err;
5263+ struct dentry *d, *parent;
5264+ struct inode *inode;
5265+
5266+ LKTRTrace("%.*s, sgen %d\n", AuDLNPair(dentry), sgen);
5267+ AuDebugOn(!dentry->d_inode);
5268+ DiMustWriteLock(dentry);
5269+
5270+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
5271+ return simple_reval_dpath(dentry, sgen);
5272+
5273+ /* slow loop, keep it simple and stupid */
5274+ /* cf: au_cpup_dirs() */
5275+ err = 0;
5276+ parent = NULL;
5277+ while (au_digen(dentry) != sgen || au_iigen(dentry->d_inode) != sgen) {
5278+ d = dentry;
5279+ while (1) {
5280+ dput(parent);
5281+ parent = dget_parent(d);
5282+ if (au_digen(parent) == sgen
5283+ && au_iigen(parent->d_inode) == sgen)
5284+ break;
5285+ d = parent;
5286+ }
5287+
5288+ inode = d->d_inode;
5289+ if (d != dentry)
5290+ di_write_lock_child(d);
5291+
5292+ /* someone might update our dentry while we were sleeping */
5293+ if (au_digen(d) != sgen || au_iigen(d->d_inode) != sgen) {
5294+ di_read_lock_parent(parent, AuLock_IR);
5295+ /* returns a number of positive dentries */
5296+ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
5297+ if (err >= 0)
5298+ err = au_refresh_hinode(inode, d);
5299+ di_read_unlock(parent, AuLock_IR);
5300+ }
5301+
5302+ if (d != dentry)
5303+ di_write_unlock(d);
5304+ dput(parent);
5305+ if (unlikely(err))
5306+ break;
5307+ }
5308+
5309+ AuTraceErr(err);
5310+ return err;
5311+}
5312+
5313+/*
5314+ * THIS IS A BOOLEAN FUNCTION: returns 1 if valid, 0 otherwise.
5315+ * nfsd passes NULL as nameidata.
5316+ */
5317+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
5318+{
5319+ int valid, err;
5320+ au_gen_t sgen;
5321+ unsigned char do_udba;
5322+ struct nameidata tmp_nd, *ndp;
5323+ struct super_block *sb;
5324+ struct inode *inode;
5325+
5326+ LKTRTrace("dentry %.*s\n", AuDLNPair(dentry));
5327+ if (nd && nd->path.dentry)
5328+ LKTRTrace("nd{%.*s, 0x%x}\n",
5329+ AuDLNPair(nd->path.dentry), nd->flags);
5330+ /*
5331+ * dir case: AuDebugOn(dentry->d_parent != nd->dentry);
5332+ * remove failure case:AuDebugOn(!IS_ROOT(dentry)
5333+ * && d_unhashed(dentry));
5334+ */
5335+ AuDebugOn(!dentry->d_fsdata);
5336+
5337+ err = -EINVAL;
5338+ sb = dentry->d_sb;
5339+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
5340+ inode = dentry->d_inode;
5341+ sgen = au_sigen(sb);
5342+ if (au_digen(dentry) != sgen) {
5343+ AuDebugOn(IS_ROOT(dentry));
5344+#ifdef ForceInotify
5345+ AuDbg("UDBA or digen, %.*s\n", AuDLNPair(dentry));
5346+#endif
5347+ if (inode)
5348+ err = au_reval_dpath(dentry, sgen);
5349+ if (unlikely(err))
5350+ goto out_dgrade;
5351+ AuDebugOn(au_digen(dentry) != sgen);
5352+ }
5353+ if (inode && au_iigen(inode) != sgen) {
5354+ AuDebugOn(IS_ROOT(dentry));
5355+#ifdef ForceInotify
5356+ AuDbg("UDBA or survived, %.*s\n", AuDLNPair(dentry));
5357+#endif
5358+ err = au_refresh_hinode(inode, dentry);
5359+ if (unlikely(err))
5360+ goto out_dgrade;
5361+ AuDebugOn(au_iigen(inode) != sgen);
5362+ }
5363+ di_downgrade_lock(dentry, AuLock_IR);
5364+
5365+#if 0 /* todo: support it? */
5366+ /* parent dir i_nlink is not updated in the case of setattr */
5367+ if (S_ISDIR(inode->i_mode)) {
5368+ mutex_lock(&inode->i_mutex);
5369+ ii_write_lock(inode);
5370+ au_cpup_attr_nlink(inode);
5371+ ii_write_unlock(inode);
5372+ mutex_unlock(&inode->i_mutex);
5373+ }
5374+#endif
5375+
5376+ AuDebugOn(au_digen(dentry) != sgen);
5377+ AuDebugOn(inode && au_iigen(inode) != sgen);
5378+ err = -EINVAL;
5379+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
5380+ if (do_udba && inode) {
5381+ aufs_bindex_t bstart = au_ibstart(inode);
5382+ if (bstart >= 0
5383+ && au_test_higen(inode, au_h_iptr(inode, bstart)))
5384+ goto out;
5385+ }
5386+ ndp = au_dup_nd(au_sbi(sb), &tmp_nd, nd);
5387+#if 0
5388+ if (nd) {
5389+ path = nd->path;
5390+ nd->path.dentry = au_h_dptr(nd->path.dentry, bindex);
5391+ if (fake_nd->path.dentry) {
5392+ fake_nd->path.mnt = au_sbr_mnt(sb, bindex);
5393+ AuDebugOn(!fake_nd->path.mnt);
5394+ path_get(&fake_nd->path);
5395+ nd->path.
5396+ }
5397+ }
5398+#endif
5399+ err = h_d_revalidate(dentry, inode, ndp, do_udba);
5400+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
5401+ /* both of real entry and whiteout found */
5402+ err = -EIO;
5403+ goto out;
5404+
5405+ out_dgrade:
5406+ di_downgrade_lock(dentry, AuLock_IR);
5407+ out:
5408+ au_store_fmode_exec(nd, inode);
5409+ aufs_read_unlock(dentry, AuLock_IR);
5410+ AuTraceErr(err);
5411+ valid = !err;
5412+ if (!valid)
5413+ LKTRTrace("%.*s invalid\n", AuDLNPair(dentry));
5414+ return valid;
5415+}
5416+
5417+static void aufs_d_release(struct dentry *dentry)
5418+{
5419+ struct au_dinfo *dinfo;
5420+ aufs_bindex_t bend, bindex;
5421+
5422+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
5423+ AuDebugOn(!d_unhashed(dentry));
5424+
5425+ dinfo = dentry->d_fsdata;
5426+ if (!dinfo)
5427+ return;
5428+
5429+ /* dentry may not be revalidated */
5430+ bindex = dinfo->di_bstart;
5431+ if (bindex >= 0) {
5432+ struct au_hdentry *p;
5433+ bend = dinfo->di_bend;
5434+ AuDebugOn(bend < bindex);
5435+ p = dinfo->di_hdentry + bindex;
5436+ while (bindex++ <= bend) {
5437+ if (p->hd_dentry)
5438+ au_hdput(p, /*do_free*/1);
5439+ p++;
5440+ }
5441+ }
5442+ kfree(dinfo->di_hdentry);
5443+ au_rwsem_destroy(&dinfo->di_rwsem);
5444+ au_cache_free_dinfo(dinfo);
5445+ au_hin_di_reinit(dentry);
5446+}
5447+
5448+struct dentry_operations aufs_dop = {
5449+ .d_revalidate = aufs_d_revalidate,
5450+ .d_release = aufs_d_release,
5451+ /* never use d_delete, especially in case of nfs server */
5452+};
5453diff -urN linux/fs/aufs/dentry.h linux-aufs/fs/aufs/dentry.h
5454--- linux/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
5455+++ linux-aufs/fs/aufs/dentry.h 2009-03-12 16:18:04.000000000 +0100
5456@@ -0,0 +1,396 @@
5457+/*
5458+ * Copyright (C) 2005-2009 Junjiro Okajima
5459+ *
5460+ * This program, aufs is free software; you can redistribute it and/or modify
5461+ * it under the terms of the GNU General Public License as published by
5462+ * the Free Software Foundation; either version 2 of the License, or
5463+ * (at your option) any later version.
5464+ *
5465+ * This program is distributed in the hope that it will be useful,
5466+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5467+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5468+ * GNU General Public License for more details.
5469+ *
5470+ * You should have received a copy of the GNU General Public License
5471+ * along with this program; if not, write to the Free Software
5472+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5473+ */
5474+
5475+/*
5476+ * lookup and dentry operations
5477+ *
5478+ * $Id$
5479+ */
5480+
5481+#ifndef __AUFS_DENTRY_H__
5482+#define __AUFS_DENTRY_H__
5483+
5484+#ifdef __KERNEL__
5485+
5486+#include <linux/fs.h>
5487+#include <linux/namei.h>
5488+#include <linux/aufs_type.h>
5489+#include "misc.h"
5490+#include "super.h"
5491+#include "vfsub.h"
5492+
5493+/* nameidata open_intent */
5494+enum {
5495+ AuIntent_AUFS,
5496+ AuIntent_BRANCH,
5497+ AuIntent_Last
5498+};
5499+
5500+struct au_hdintent {
5501+ struct list_head hdi_list;
5502+ struct file *hdi_file[AuIntent_Last];
5503+};
5504+
5505+struct au_hdentry {
5506+ struct dentry *hd_dentry;
5507+
5508+#ifdef CONFIG_AUFS_BR_NFS
5509+ spinlock_t hd_lock; /* intest_list */
5510+ struct list_head *hd_intent_list;
5511+#endif
5512+};
5513+
5514+struct au_dinfo {
5515+ atomic_t di_generation;
5516+
5517+ struct au_rwsem di_rwsem;
5518+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
5519+ struct au_hdentry *di_hdentry;
5520+};
5521+
5522+/* nameidata extension flags */
5523+#define AuNdx_DLGT 1
5524+#define AuNdx_DIRPERM1 (1 << 1)
5525+#define au_ftest_ndx(flags, name) ((flags) & AuNdx_##name)
5526+#define au_fset_ndx(flags, name) { (flags) |= AuNdx_##name; }
5527+#define au_fclr_ndx(flags, name) { (flags) &= ~AuNdx_##name; }
5528+#ifndef CONFIG_AUFS_DLGT
5529+#undef AuNdx_DLGT
5530+#define AuNdx_DLGT 0
5531+#undef AuNdx_DIRPERM1
5532+#define AuNdx_DIRPERM1 0
5533+#endif
5534+
5535+struct au_ndx {
5536+ struct vfsmount *nfsmnt;
5537+ unsigned int flags;
5538+ struct nameidata *nd;
5539+ struct au_branch *br;
5540+ struct file *nd_file;
5541+};
5542+
5543+/* ---------------------------------------------------------------------- */
5544+
5545+static inline void au_do_h_dentry_init(struct au_hdentry *hdentry)
5546+{
5547+ hdentry->hd_dentry = NULL;
5548+}
5549+
5550+#ifdef CONFIG_AUFS_BR_NFS
5551+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
5552+{
5553+ au_do_h_dentry_init(hdentry);
5554+ spin_lock_init(&hdentry->hd_lock);
5555+}
5556+
5557+static inline void au_h_dentry_init_all(struct au_hdentry *hdentry, int n)
5558+{
5559+ while (n--)
5560+ spin_lock_init(&hdentry[n].hd_lock);
5561+}
5562+
5563+/* br_nfs.c */
5564+struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
5565+ struct file *file);
5566+int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry,
5567+ aufs_bindex_t bindex, struct nameidata *nd);
5568+void au_hintent_put(struct au_hdentry *hd, int do_free);
5569+int au_fake_intent(struct nameidata *nd, struct au_branch *br);
5570+int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry,
5571+ aufs_bindex_t bindex, struct file *file);
5572+struct dentry *au_lkup_hash(const char *name, struct dentry *parent, int len,
5573+ struct au_ndx *ndx);
5574+#else
5575+
5576+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
5577+{
5578+ au_do_h_dentry_init(hdentry);
5579+}
5580+
5581+static inline void au_h_dentry_init_all(struct au_hdentry *hdentry, int n)
5582+{
5583+ /* nothing */
5584+}
5585+
5586+static inline
5587+struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
5588+ struct file *file)
5589+{
5590+ /* return ERR_PTR(-ENOSYS); */
5591+ return NULL;
5592+}
5593+
5594+static inline
5595+int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry,
5596+ aufs_bindex_t bindex, struct nameidata *nd)
5597+{
5598+ return 0;
5599+}
5600+
5601+static inline void au_hintent_put(struct au_hdentry *hd, int do_free)
5602+{
5603+ /* empty */
5604+}
5605+
5606+static inline int au_fake_intent(struct nameidata *nd, struct au_branch *br)
5607+{
5608+ return 0;
5609+}
5610+
5611+static inline
5612+int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry,
5613+ aufs_bindex_t bindex, struct file *file)
5614+{
5615+ return 0;
5616+}
5617+
5618+#ifdef CONFIG_AUFS_DLGT
5619+static inline
5620+struct dentry *au_lkup_hash(const char *name, struct dentry *parent, int len,
5621+ struct au_ndx *ndx)
5622+{
5623+ /* return ERR_PTR(-ENOSYS); */
5624+ return vfsub_lookup_one_len(name, parent, len);
5625+}
5626+#endif
5627+#endif /* CONFIG_AUFS_BR_NFS */
5628+
5629+#ifdef CONFIG_AUFS_DLGT
5630+/* dlgt.c */
5631+struct dentry *au_lkup_one_dlgt(const char *name, struct dentry *parent,
5632+ int len, unsigned int flags);
5633+#elif defined(CONFIG_AUFS_BR_NFS)
5634+/* regardelss kernel version */
5635+static inline
5636+struct dentry *au_lkup_one_dlgt(const char *name, struct dentry *parent,
5637+ int len, unsigned int flags)
5638+{
5639+ return vfsub_lookup_one_len(name, parent, len);
5640+}
5641+#endif
5642+
5643+/* dentry.c */
5644+extern struct dentry_operations aufs_dop;
5645+#if defined(CONFIG_AUFS_BR_NFS) || defined(CONFIG_AUFS_DLGT)
5646+struct dentry *au_lkup_one(const char *name, struct dentry *parent, int len,
5647+ struct au_ndx *ndx);
5648+#else
5649+static inline
5650+struct dentry *au_lkup_one(const char *name, struct dentry *parent, int len,
5651+ struct au_ndx *ndx)
5652+{
5653+ /* todo? ndx->nd_file = NULL; */
5654+ return vfsub_lookup_one_len(name, parent, len);
5655+}
5656+#endif
5657+struct dentry *au_sio_lkup_one(const char *name, struct dentry *parent, int len,
5658+ struct au_ndx *ndx);
5659+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
5660+ struct nameidata *nd);
5661+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
5662+int au_refresh_hdentry(struct dentry *dentry, mode_t type);
5663+int au_reval_dpath(struct dentry *dentry, au_gen_t sgen);
5664+
5665+/* dinfo.c */
5666+int au_alloc_dinfo(struct dentry *dentry);
5667+struct au_dinfo *au_di(struct dentry *dentry);
5668+
5669+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
5670+void di_read_unlock(struct dentry *d, int flags);
5671+void di_downgrade_lock(struct dentry *d, int flags);
5672+void di_write_lock(struct dentry *d, unsigned int lsc);
5673+void di_write_unlock(struct dentry *d);
5674+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
5675+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
5676+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
5677+
5678+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
5679+
5680+aufs_bindex_t au_dbtail(struct dentry *dentry);
5681+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
5682+#if 0 /* reserved for future use */
5683+aufs_bindex_t au_dbtail_generic(struct dentry *dentry);
5684+#endif
5685+
5686+void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex);
5687+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5688+ struct dentry *h_dentry);
5689+
5690+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5691+void au_update_dbstart(struct dentry *dentry);
5692+void au_update_dbend(struct dentry *dentry);
5693+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
5694+
5695+/* ---------------------------------------------------------------------- */
5696+
5697+/* todo: memory barrier? */
5698+static inline au_gen_t au_digen(struct dentry *d)
5699+{
5700+ return atomic_read(&au_di(d)->di_generation);
5701+}
5702+
5703+#ifdef CONFIG_AUFS_HINOTIFY
5704+static inline au_gen_t au_digen_dec(struct dentry *d)
5705+{
5706+ return atomic_dec_return(&au_di(d)->di_generation);
5707+}
5708+
5709+static inline void au_hin_di_reinit(struct dentry *d)
5710+{
5711+ d->d_fsdata = NULL;
5712+}
5713+#else
5714+static inline void au_hin_di_reinit(struct dentry *d)
5715+{
5716+ /* empty */
5717+}
5718+#endif /* CONFIG_AUFS_HINOTIFY */
5719+
5720+/* ---------------------------------------------------------------------- */
5721+
5722+/* lock subclass for dinfo */
5723+enum {
5724+ AuLsc_DI_CHILD, /* child first */
5725+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hinotify */
5726+ AuLsc_DI_CHILD3, /* copyup dirs */
5727+ AuLsc_DI_PARENT,
5728+ AuLsc_DI_PARENT2,
5729+ AuLsc_DI_PARENT3,
5730+ AuLsc_DI_PARENT4
5731+};
5732+
5733+/*
5734+ * di_read_lock_child, di_write_lock_child,
5735+ * di_read_lock_child2, di_write_lock_child2,
5736+ * di_read_lock_child3, di_write_lock_child3,
5737+ * di_read_lock_parent, di_write_lock_parent,
5738+ * di_read_lock_parent2, di_write_lock_parent2,
5739+ * di_read_lock_parent3, di_write_lock_parent3,
5740+ * di_read_lock_parent4, di_write_lock_parent4,
5741+ */
5742+#define AuReadLockFunc(name, lsc) \
5743+static inline void di_read_lock_##name(struct dentry *d, int flags) \
5744+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
5745+
5746+#define AuWriteLockFunc(name, lsc) \
5747+static inline void di_write_lock_##name(struct dentry *d) \
5748+{ di_write_lock(d, AuLsc_DI_##lsc); }
5749+
5750+#define AuRWLockFuncs(name, lsc) \
5751+ AuReadLockFunc(name, lsc) \
5752+ AuWriteLockFunc(name, lsc)
5753+
5754+AuRWLockFuncs(child, CHILD);
5755+AuRWLockFuncs(child2, CHILD2);
5756+AuRWLockFuncs(child3, CHILD3);
5757+AuRWLockFuncs(parent, PARENT);
5758+AuRWLockFuncs(parent2, PARENT2);
5759+AuRWLockFuncs(parent3, PARENT3);
5760+AuRWLockFuncs(parent4, PARENT4);
5761+
5762+#undef AuReadLockFunc
5763+#undef AuWriteLockFunc
5764+#undef AuRWLockFuncs
5765+
5766+/* to debug easier, do not make them inlined functions */
5767+#define DiMustReadLock(d) do { \
5768+ SiMustAnyLock((d)->d_sb); \
5769+ AuRwMustReadLock(&au_di(d)->di_rwsem); \
5770+} while (0)
5771+
5772+#define DiMustWriteLock(d) do { \
5773+ SiMustAnyLock((d)->d_sb); \
5774+ AuRwMustWriteLock(&au_di(d)->di_rwsem); \
5775+} while (0)
5776+
5777+#define DiMustAnyLock(d) do { \
5778+ SiMustAnyLock((d)->d_sb); \
5779+ AuRwMustAnyLock(&au_di(d)->di_rwsem); \
5780+} while (0)
5781+
5782+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
5783+
5784+/* ---------------------------------------------------------------------- */
5785+
5786+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
5787+{
5788+ DiMustAnyLock(dentry);
5789+ return au_di(dentry)->di_bstart;
5790+}
5791+
5792+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
5793+{
5794+ DiMustAnyLock(dentry);
5795+ return au_di(dentry)->di_bend;
5796+}
5797+
5798+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
5799+{
5800+ DiMustAnyLock(dentry);
5801+ return au_di(dentry)->di_bwh;
5802+}
5803+
5804+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
5805+{
5806+ DiMustAnyLock(dentry);
5807+ AuDebugOn(dentry->d_inode
5808+ && dentry->d_inode->i_mode
5809+ && !S_ISDIR(dentry->d_inode->i_mode));
5810+ return au_di(dentry)->di_bdiropq;
5811+}
5812+
5813+/* todo: hard/soft set? */
5814+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
5815+{
5816+ DiMustWriteLock(dentry);
5817+ AuDebugOn(au_sbend(dentry->d_sb) < bindex);
5818+ /* */
5819+ au_di(dentry)->di_bstart = bindex;
5820+}
5821+
5822+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
5823+{
5824+ DiMustWriteLock(dentry);
5825+ AuDebugOn(au_sbend(dentry->d_sb) < bindex
5826+ || bindex < au_dbstart(dentry));
5827+ au_di(dentry)->di_bend = bindex;
5828+}
5829+
5830+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
5831+{
5832+ DiMustWriteLock(dentry);
5833+ AuDebugOn(au_sbend(dentry->d_sb) < bindex);
5834+ /* dbwh can be outside of bstart - bend range */
5835+ au_di(dentry)->di_bwh = bindex;
5836+}
5837+
5838+static inline void au_hdput(struct au_hdentry *hd, int do_free)
5839+{
5840+ au_hintent_put(hd, do_free);
5841+ dput(hd->hd_dentry);
5842+}
5843+
5844+static inline void au_update_digen(struct dentry *dentry)
5845+{
5846+ AuDebugOn(!dentry->d_sb);
5847+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
5848+ /* smp_mb(); */ /* atomic_set */
5849+}
5850+
5851+#endif /* __KERNEL__ */
5852+#endif /* __AUFS_DENTRY_H__ */
5853diff -urN linux/fs/aufs/dinfo.c linux-aufs/fs/aufs/dinfo.c
5854--- linux/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
5855+++ linux-aufs/fs/aufs/dinfo.c 2009-03-12 16:18:04.000000000 +0100
5856@@ -0,0 +1,436 @@
5857+/*
5858+ * Copyright (C) 2005-2009 Junjiro Okajima
5859+ *
5860+ * This program, aufs is free software; you can redistribute it and/or modify
5861+ * it under the terms of the GNU General Public License as published by
5862+ * the Free Software Foundation; either version 2 of the License, or
5863+ * (at your option) any later version.
5864+ *
5865+ * This program is distributed in the hope that it will be useful,
5866+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5867+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5868+ * GNU General Public License for more details.
5869+ *
5870+ * You should have received a copy of the GNU General Public License
5871+ * along with this program; if not, write to the Free Software
5872+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
5873+ */
5874+
5875+/*
5876+ * dentry private data
5877+ *
5878+ * $Id$
5879+ */
5880+
5881+#include "aufs.h"
5882+
5883+int au_alloc_dinfo(struct dentry *dentry)
5884+{
5885+ struct au_dinfo *dinfo;
5886+ struct super_block *sb;
5887+ int nbr;
5888+
5889+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
5890+ AuDebugOn(dentry->d_fsdata);
5891+
5892+ dinfo = au_cache_alloc_dinfo();
5893+ if (dinfo) {
5894+ sb = dentry->d_sb;
5895+ nbr = au_sbend(sb) + 1;
5896+ if (nbr <= 0)
5897+ nbr = 1;
5898+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry),
5899+ GFP_NOFS);
5900+ if (dinfo->di_hdentry) {
5901+ au_h_dentry_init_all(dinfo->di_hdentry, nbr);
5902+ atomic_set(&dinfo->di_generation, au_sigen(sb));
5903+ /* smp_mb(); */ /* atomic_set */
5904+ au_rw_init_wlock_nested(&dinfo->di_rwsem,
5905+ AuLsc_DI_CHILD);
5906+ au_dbg_locked_di_reg(dentry, AuLock_DW, AuLsc_DI_CHILD);
5907+ dinfo->di_bstart = -1;
5908+ dinfo->di_bend = -1;
5909+ dinfo->di_bwh = -1;
5910+ dinfo->di_bdiropq = -1;
5911+
5912+ dentry->d_fsdata = dinfo;
5913+ dentry->d_op = &aufs_dop;
5914+ return 0; /* success */
5915+ }
5916+ au_cache_free_dinfo(dinfo);
5917+ }
5918+ AuTraceErr(-ENOMEM);
5919+ return -ENOMEM;
5920+}
5921+
5922+struct au_dinfo *au_di(struct dentry *dentry)
5923+{
5924+ struct au_dinfo *dinfo = dentry->d_fsdata;
5925+ AuDebugOn(!dinfo
5926+ || !dinfo->di_hdentry
5927+ /* || au_sbi(dentry->d_sb)->si_bend < dinfo->di_bend */
5928+ || dinfo->di_bend < dinfo->di_bstart
5929+ /* dbwh can be outside of this range */
5930+ || (0 <= dinfo->di_bdiropq
5931+ && (dinfo->di_bdiropq < dinfo->di_bstart
5932+ /* || dinfo->di_bend < dinfo->di_bdiropq */))
5933+ );
5934+ return dinfo;
5935+}
5936+
5937+/* ---------------------------------------------------------------------- */
5938+
5939+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
5940+{
5941+ switch (lsc) {
5942+ case AuLsc_DI_CHILD:
5943+ ii_write_lock_child(inode);
5944+ break;
5945+ case AuLsc_DI_CHILD2:
5946+ ii_write_lock_child2(inode);
5947+ break;
5948+ case AuLsc_DI_CHILD3:
5949+ ii_write_lock_child3(inode);
5950+ break;
5951+ case AuLsc_DI_PARENT:
5952+ ii_write_lock_parent(inode);
5953+ break;
5954+ case AuLsc_DI_PARENT2:
5955+ ii_write_lock_parent2(inode);
5956+ break;
5957+ case AuLsc_DI_PARENT3:
5958+ ii_write_lock_parent3(inode);
5959+ break;
5960+ case AuLsc_DI_PARENT4:
5961+ ii_write_lock_parent4(inode);
5962+ break;
5963+ default:
5964+ BUG();
5965+ }
5966+}
5967+
5968+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
5969+{
5970+ switch (lsc) {
5971+ case AuLsc_DI_CHILD:
5972+ ii_read_lock_child(inode);
5973+ break;
5974+ case AuLsc_DI_CHILD2:
5975+ ii_read_lock_child2(inode);
5976+ break;
5977+ case AuLsc_DI_CHILD3:
5978+ ii_read_lock_child3(inode);
5979+ break;
5980+ case AuLsc_DI_PARENT:
5981+ ii_read_lock_parent(inode);
5982+ break;
5983+ case AuLsc_DI_PARENT2:
5984+ ii_read_lock_parent2(inode);
5985+ break;
5986+ case AuLsc_DI_PARENT3:
5987+ ii_read_lock_parent3(inode);
5988+ break;
5989+ case AuLsc_DI_PARENT4:
5990+ ii_read_lock_parent4(inode);
5991+ break;
5992+ default:
5993+ BUG();
5994+ }
5995+}
5996+
5997+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
5998+{
5999+ LKTRTrace("%.*s, %u\n", AuDLNPair(d), lsc);
6000+ SiMustAnyLock(d->d_sb);
6001+
6002+ /* todo: always nested? */
6003+ au_dbg_locking_di_reg(d, flags, lsc);
6004+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
6005+ au_dbg_locking_di_unreg(d, flags);
6006+ au_dbg_locked_di_reg(d, flags, lsc);
6007+ if (d->d_inode) {
6008+ if (au_ftest_lock(flags, IW))
6009+ do_ii_write_lock(d->d_inode, lsc);
6010+ else if (au_ftest_lock(flags, IR))
6011+ do_ii_read_lock(d->d_inode, lsc);
6012+ }
6013+}
6014+
6015+void di_read_unlock(struct dentry *d, int flags)
6016+{
6017+ LKTRTrace("%.*s\n", AuDLNPair(d));
6018+ SiMustAnyLock(d->d_sb);
6019+
6020+ if (d->d_inode) {
6021+ if (au_ftest_lock(flags, IW))
6022+ ii_write_unlock(d->d_inode);
6023+ else if (au_ftest_lock(flags, IR))
6024+ ii_read_unlock(d->d_inode);
6025+ }
6026+ au_rw_read_unlock(&au_di(d)->di_rwsem);
6027+ au_dbg_locked_di_unreg(d, flags);
6028+}
6029+
6030+void di_downgrade_lock(struct dentry *d, int flags)
6031+{
6032+ SiMustAnyLock(d->d_sb);
6033+
6034+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
6035+ if (d->d_inode && au_ftest_lock(flags, IR))
6036+ ii_downgrade_lock(d->d_inode);
6037+}
6038+
6039+void di_write_lock(struct dentry *d, unsigned int lsc)
6040+{
6041+ LKTRTrace("%.*s, %u\n", AuDLNPair(d), lsc);
6042+ SiMustAnyLock(d->d_sb);
6043+
6044+ /* todo: always nested? */
6045+ au_dbg_locking_di_reg(d, AuLock_IW, lsc);
6046+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
6047+ au_dbg_locking_di_unreg(d, AuLock_IW);
6048+ au_dbg_locked_di_reg(d, AuLock_IW, lsc);
6049+ if (d->d_inode)
6050+ do_ii_write_lock(d->d_inode, lsc);
6051+}
6052+
6053+void di_write_unlock(struct dentry *d)
6054+{
6055+ LKTRTrace("%.*s\n", AuDLNPair(d));
6056+ SiMustAnyLock(d->d_sb);
6057+
6058+ if (d->d_inode)
6059+ ii_write_unlock(d->d_inode);
6060+ au_rw_write_unlock(&au_di(d)->di_rwsem);
6061+ au_dbg_locked_di_unreg(d, AuLock_IW);
6062+}
6063+
6064+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
6065+{
6066+ AuTraceEnter();
6067+ AuDebugOn(d1 == d2
6068+ || d1->d_inode == d2->d_inode
6069+ || d1->d_sb != d2->d_sb);
6070+
6071+ if (isdir && au_test_subdir(d1, d2)) {
6072+ di_write_lock_child(d1);
6073+ di_write_lock_child2(d2);
6074+ } else {
6075+ /* there should be no races */
6076+ di_write_lock_child(d2);
6077+ di_write_lock_child2(d1);
6078+ }
6079+}
6080+
6081+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
6082+{
6083+ AuTraceEnter();
6084+ AuDebugOn(d1 == d2
6085+ || d1->d_inode == d2->d_inode
6086+ || d1->d_sb != d2->d_sb);
6087+
6088+ if (isdir && au_test_subdir(d1, d2)) {
6089+ di_write_lock_parent(d1);
6090+ di_write_lock_parent2(d2);
6091+ } else {
6092+ /* there should be no races */
6093+ di_write_lock_parent(d2);
6094+ di_write_lock_parent2(d1);
6095+ }
6096+}
6097+
6098+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
6099+{
6100+ di_write_unlock(d1);
6101+ if (d1->d_inode == d2->d_inode) {
6102+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
6103+ au_dbg_locked_di_unreg(d2, AuLock_IW);
6104+ } else
6105+ di_write_unlock(d2);
6106+}
6107+
6108+/* ---------------------------------------------------------------------- */
6109+
6110+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
6111+{
6112+ struct dentry *d;
6113+
6114+ DiMustAnyLock(dentry);
6115+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
6116+ return NULL;
6117+ AuDebugOn(bindex < 0
6118+ /* || bindex > au_sbend(dentry->d_sb) */);
6119+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
6120+ AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
6121+ return d;
6122+}
6123+
6124+aufs_bindex_t au_dbtail(struct dentry *dentry)
6125+{
6126+ aufs_bindex_t bend, bwh;
6127+
6128+ bend = au_dbend(dentry);
6129+ if (0 <= bend) {
6130+ bwh = au_dbwh(dentry);
6131+ if (!bwh)
6132+ return bwh;
6133+ if (0 < bwh && bwh < bend)
6134+ return bwh - 1;
6135+ }
6136+ return bend;
6137+}
6138+
6139+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
6140+{
6141+ aufs_bindex_t bend, bopq;
6142+
6143+ AuDebugOn(dentry->d_inode
6144+ && dentry->d_inode->i_mode
6145+ && !S_ISDIR(dentry->d_inode->i_mode));
6146+
6147+ bend = au_dbtail(dentry);
6148+ if (0 <= bend) {
6149+ bopq = au_dbdiropq(dentry);
6150+ AuDebugOn(bend < bopq);
6151+ if (0 <= bopq && bopq < bend)
6152+ bend = bopq;
6153+ }
6154+ return bend;
6155+}
6156+
6157+#if 0 /* reserved for future use */
6158+aufs_bindex_t au_dbtail_generic(struct dentry *dentry)
6159+{
6160+ struct inode *inode;
6161+
6162+ inode = dentry->d_inode;
6163+ if (inode && S_ISDIR(inode->i_mode))
6164+ return au_dbtaildir(dentry);
6165+ else
6166+ return au_dbtail(dentry);
6167+}
6168+#endif
6169+
6170+/* ---------------------------------------------------------------------- */
6171+
6172+void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
6173+{
6174+ DiMustWriteLock(dentry);
6175+ AuDebugOn(au_sbend(dentry->d_sb) < bindex);
6176+ AuDebugOn((bindex >= 0
6177+ && (bindex < au_dbstart(dentry)
6178+ || au_dbend(dentry) < bindex))
6179+ || (dentry->d_inode
6180+ && dentry->d_inode->i_mode
6181+ && !S_ISDIR(dentry->d_inode->i_mode)));
6182+ au_di(dentry)->di_bdiropq = bindex;
6183+}
6184+
6185+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
6186+ struct dentry *h_dentry)
6187+{
6188+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
6189+ DiMustWriteLock(dentry);
6190+ AuDebugOn(bindex < au_di(dentry)->di_bstart
6191+ || bindex > au_di(dentry)->di_bend
6192+ || (h_dentry && atomic_read(&h_dentry->d_count) <= 0)
6193+ || (h_dentry && hd->hd_dentry)
6194+ );
6195+ if (hd->hd_dentry)
6196+ au_hdput(hd, /*do_free*/0);
6197+ hd->hd_dentry = h_dentry;
6198+}
6199+
6200+/* ---------------------------------------------------------------------- */
6201+
6202+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
6203+{
6204+ struct au_dinfo *dinfo;
6205+ aufs_bindex_t bindex;
6206+ struct dentry *h_d;
6207+
6208+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), do_put_zero);
6209+ DiMustWriteLock(dentry);
6210+
6211+ dinfo = au_di(dentry);
6212+ if (!dinfo || dinfo->di_bstart < 0)
6213+ return;
6214+
6215+ if (do_put_zero) {
6216+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend;
6217+ bindex++) {
6218+ h_d = dinfo->di_hdentry[0 + bindex].hd_dentry;
6219+ if (h_d && !h_d->d_inode)
6220+ au_set_h_dptr(dentry, bindex, NULL);
6221+ }
6222+ }
6223+
6224+ dinfo->di_bstart = -1;
6225+ while (++dinfo->di_bstart <= dinfo->di_bend)
6226+ if (dinfo->di_hdentry[0 + dinfo->di_bstart].hd_dentry)
6227+ break;
6228+ if (dinfo->di_bstart > dinfo->di_bend) {
6229+ dinfo->di_bstart = -1;
6230+ dinfo->di_bend = -1;
6231+ return;
6232+ }
6233+
6234+ dinfo->di_bend++;
6235+ while (0 <= --dinfo->di_bend)
6236+ if (dinfo->di_hdentry[0 + dinfo->di_bend].hd_dentry)
6237+ break;
6238+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
6239+}
6240+
6241+void au_update_dbstart(struct dentry *dentry)
6242+{
6243+ aufs_bindex_t bindex,
6244+ bstart = au_dbstart(dentry),
6245+ bend = au_dbend(dentry);
6246+ struct dentry *h_dentry;
6247+
6248+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
6249+ DiMustWriteLock(dentry);
6250+
6251+ for (bindex = bstart; bindex <= bend; bindex++) {
6252+ h_dentry = au_h_dptr(dentry, bindex);
6253+ if (!h_dentry)
6254+ continue;
6255+ if (h_dentry->d_inode) {
6256+ au_set_dbstart(dentry, bindex);
6257+ return;
6258+ }
6259+ au_set_h_dptr(dentry, bindex, NULL);
6260+ }
6261+}
6262+
6263+void au_update_dbend(struct dentry *dentry)
6264+{
6265+ aufs_bindex_t bindex,
6266+ bstart = au_dbstart(dentry),
6267+ bend = au_dbend(dentry);
6268+ struct dentry *h_dentry;
6269+
6270+ DiMustWriteLock(dentry);
6271+ for (bindex = bend; bindex <= bstart; bindex--) {
6272+ h_dentry = au_h_dptr(dentry, bindex);
6273+ if (!h_dentry)
6274+ continue;
6275+ if (h_dentry->d_inode) {
6276+ au_set_dbend(dentry, bindex);
6277+ return;
6278+ }
6279+ au_set_h_dptr(dentry, bindex, NULL);
6280+ }
6281+}
6282+
6283+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
6284+{
6285+ aufs_bindex_t bindex, bend;
6286+
6287+ bend = au_dbend(dentry);
6288+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
6289+ if (au_h_dptr(dentry, bindex) == h_dentry)
6290+ return bindex;
6291+ return -1;
6292+}
6293diff -urN linux/fs/aufs/dir.c linux-aufs/fs/aufs/dir.c
6294--- linux/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
6295+++ linux-aufs/fs/aufs/dir.c 2009-03-12 16:18:04.000000000 +0100
6296@@ -0,0 +1,559 @@
6297+/*
6298+ * Copyright (C) 2005-2009 Junjiro Okajima
6299+ *
6300+ * This program, aufs is free software; you can redistribute it and/or modify
6301+ * it under the terms of the GNU General Public License as published by
6302+ * the Free Software Foundation; either version 2 of the License, or
6303+ * (at your option) any later version.
6304+ *
6305+ * This program is distributed in the hope that it will be useful,
6306+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6307+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6308+ * GNU General Public License for more details.
6309+ *
6310+ * You should have received a copy of the GNU General Public License
6311+ * along with this program; if not, write to the Free Software
6312+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6313+ */
6314+
6315+/*
6316+ * directory operations
6317+ *
6318+ * $Id$
6319+ */
6320+
6321+#include <linux/fs_stack.h>
6322+#include "aufs.h"
6323+
6324+static int reopen_dir(struct file *file)
6325+{
6326+ int err;
6327+ struct dentry *dentry, *h_dentry;
6328+ aufs_bindex_t bindex, btail, bstart;
6329+ struct file *h_file;
6330+
6331+ dentry = file->f_dentry;
6332+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
6333+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
6334+
6335+ /* open all hidden dirs */
6336+ bstart = au_dbstart(dentry);
6337+#if 1 /* todo: necessary? */
6338+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
6339+ au_set_h_fptr(file, bindex, NULL);
6340+#endif
6341+ au_set_fbstart(file, bstart);
6342+ btail = au_dbtaildir(dentry);
6343+#if 1 /* todo: necessary? */
6344+ for (bindex = au_fbend(file); btail < bindex; bindex--)
6345+ au_set_h_fptr(file, bindex, NULL);
6346+#endif
6347+ au_set_fbend(file, btail);
6348+ for (bindex = bstart; bindex <= btail; bindex++) {
6349+ h_dentry = au_h_dptr(dentry, bindex);
6350+ if (!h_dentry)
6351+ continue;
6352+ h_file = au_h_fptr(file, bindex);
6353+ if (h_file) {
6354+ AuDebugOn(h_file->f_dentry != h_dentry);
6355+ continue;
6356+ }
6357+
6358+ h_file = au_h_open(dentry, bindex, file->f_flags, file);
6359+ err = PTR_ERR(h_file);
6360+ if (IS_ERR(h_file))
6361+ goto out; /* close all? */
6362+ /* cpup_file_flags(h_file, file); */
6363+ au_set_h_fptr(file, bindex, h_file);
6364+ }
6365+ au_update_figen(file);
6366+ /* todo: necessary? */
6367+ /* file->f_ra = h_file->f_ra; */
6368+ err = 0;
6369+
6370+ out:
6371+ AuTraceErr(err);
6372+ return err;
6373+}
6374+
6375+static int do_open_dir(struct file *file, int flags)
6376+{
6377+ int err;
6378+ aufs_bindex_t bindex, btail;
6379+ struct dentry *dentry, *h_dentry;
6380+ struct file *h_file;
6381+
6382+ dentry = file->f_dentry;
6383+ LKTRTrace("%.*s, 0x%x\n", AuDLNPair(dentry), flags);
6384+ AuDebugOn(!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode));
6385+
6386+ err = 0;
6387+ au_set_fvdir_cache(file, NULL);
6388+ file->f_version = dentry->d_inode->i_version;
6389+ bindex = au_dbstart(dentry);
6390+ au_set_fbstart(file, bindex);
6391+ btail = au_dbtaildir(dentry);
6392+ au_set_fbend(file, btail);
6393+ for (; !err && bindex <= btail; bindex++) {
6394+ h_dentry = au_h_dptr(dentry, bindex);
6395+ if (!h_dentry)
6396+ continue;
6397+
6398+ h_file = au_h_open(dentry, bindex, flags, file);
6399+ if (IS_ERR(h_file)) {
6400+ err = PTR_ERR(h_file);
6401+ break;
6402+ }
6403+ au_set_h_fptr(file, bindex, h_file);
6404+ }
6405+ au_update_figen(file);
6406+ /* todo: necessary? */
6407+ /* file->f_ra = h_file->f_ra; */
6408+ if (!err)
6409+ return 0; /* success */
6410+
6411+ /* close all */
6412+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
6413+ au_set_h_fptr(file, bindex, NULL);
6414+ au_set_fbstart(file, -1);
6415+ au_set_fbend(file, -1);
6416+ return err;
6417+}
6418+
6419+static int aufs_open_dir(struct inode *inode, struct file *file)
6420+{
6421+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry));
6422+
6423+ return au_do_open(inode, file, do_open_dir);
6424+}
6425+
6426+static int aufs_release_dir(struct inode *inode, struct file *file)
6427+{
6428+ struct au_vdir *vdir_cache;
6429+ struct super_block *sb;
6430+
6431+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry));
6432+
6433+ sb = file->f_dentry->d_sb;
6434+ si_noflush_read_lock(sb);
6435+ fi_write_lock(file);
6436+ vdir_cache = au_fvdir_cache(file);
6437+ if (vdir_cache)
6438+ au_vdir_free(vdir_cache);
6439+ fi_write_unlock(file);
6440+ au_finfo_fin(file);
6441+ si_read_unlock(sb);
6442+ return 0;
6443+}
6444+
6445+static int fsync_dir(struct dentry *dentry, int datasync)
6446+{
6447+ int err;
6448+ struct inode *inode;
6449+ struct super_block *sb;
6450+ aufs_bindex_t bend, bindex;
6451+
6452+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), datasync);
6453+ DiMustAnyLock(dentry);
6454+ sb = dentry->d_sb;
6455+ SiMustAnyLock(sb);
6456+ inode = dentry->d_inode;
6457+ IMustLock(inode);
6458+ IiMustAnyLock(inode);
6459+
6460+ err = 0;
6461+ bend = au_dbend(dentry);
6462+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
6463+ struct dentry *h_dentry;
6464+ struct inode *h_inode;
6465+ struct file_operations *fop;
6466+
6467+ if (au_test_ro(sb, bindex, inode))
6468+ continue;
6469+ h_dentry = au_h_dptr(dentry, bindex);
6470+ if (!h_dentry)
6471+ continue;
6472+ h_inode = h_dentry->d_inode;
6473+ if (!h_inode)
6474+ continue;
6475+
6476+ /* no mnt_want_write() */
6477+ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
6478+ /* todo: inotiry fired? */
6479+ mutex_lock(&h_inode->i_mutex);
6480+ fop = (void *)h_inode->i_fop;
6481+ err = filemap_fdatawrite(h_inode->i_mapping);
6482+ if (!err && fop && fop->fsync)
6483+ err = fop->fsync(NULL, h_dentry, datasync);
6484+ if (!err)
6485+ err = filemap_fdatawrite(h_inode->i_mapping);
6486+ if (!err)
6487+ au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
6488+ mutex_unlock(&h_inode->i_mutex);
6489+ }
6490+
6491+ AuTraceErr(err);
6492+ return err;
6493+}
6494+
6495+/*
6496+ * @file may be NULL
6497+ */
6498+static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
6499+ int datasync)
6500+{
6501+ int err;
6502+ struct inode *inode;
6503+ struct file *h_file;
6504+ struct super_block *sb;
6505+ aufs_bindex_t bend, bindex;
6506+
6507+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), datasync);
6508+ inode = dentry->d_inode;
6509+ IMustLock(inode);
6510+
6511+ err = 0;
6512+ sb = dentry->d_sb;
6513+ si_noflush_read_lock(sb);
6514+ if (file) {
6515+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1,
6516+ /*locked*/1);
6517+ if (unlikely(err))
6518+ goto out;
6519+ } else
6520+ di_write_lock_child(dentry);
6521+
6522+ if (file) {
6523+ bend = au_fbend(file);
6524+ for (bindex = au_fbstart(file); !err && bindex <= bend;
6525+ bindex++) {
6526+ h_file = au_h_fptr(file, bindex);
6527+ if (!h_file || au_test_ro(sb, bindex, inode))
6528+ continue;
6529+
6530+ err = -EINVAL;
6531+ if (h_file->f_op && h_file->f_op->fsync) {
6532+ /* todo: try do_fsync() in fs/sync.c? */
6533+ mutex_lock(&h_file->f_mapping->host->i_mutex);
6534+ err = h_file->f_op->fsync
6535+ (h_file, h_file->f_dentry, datasync);
6536+ if (!err)
6537+ au_update_fuse_h_inode
6538+ (h_file->f_vfsmnt,
6539+ h_file->f_dentry);
6540+ /*ignore*/
6541+ mutex_unlock(&h_file->f_mapping->host->i_mutex);
6542+ }
6543+ }
6544+ } else
6545+ err = fsync_dir(dentry, datasync);
6546+ au_cpup_attr_timesizes(inode);
6547+ di_write_unlock(dentry);
6548+ if (file)
6549+ fi_write_unlock(file);
6550+
6551+ out:
6552+ si_read_unlock(sb);
6553+ AuTraceErr(err);
6554+ return err;
6555+}
6556+
6557+/* ---------------------------------------------------------------------- */
6558+
6559+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
6560+{
6561+ int err;
6562+ struct dentry *dentry;
6563+ struct inode *inode;
6564+ struct super_block *sb;
6565+
6566+ dentry = file->f_dentry;
6567+ LKTRTrace("%.*s, pos %lld\n", AuDLNPair(dentry), file->f_pos);
6568+ inode = dentry->d_inode;
6569+ IMustLock(inode);
6570+
6571+ sb = dentry->d_sb;
6572+ si_read_lock(sb, AuLock_FLUSH);
6573+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*locked*/1);
6574+ if (unlikely(err))
6575+ goto out;
6576+ err = au_vdir_init(file);
6577+ di_downgrade_lock(dentry, AuLock_IR);
6578+ if (unlikely(err))
6579+ goto out_unlock;
6580+
6581+ if (!au_test_nfsd(current)) {
6582+ err = au_vdir_fill_de(file, dirent, filldir);
6583+ } else {
6584+ /*
6585+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
6586+ * encode_fh() and others.
6587+ */
6588+ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
6589+
6590+ di_read_unlock(dentry, AuLock_IR);
6591+ si_read_unlock(sb);
6592+ lockdep_off();
6593+ err = au_vdir_fill_de(file, dirent, filldir);
6594+ lockdep_on();
6595+ fsstack_copy_attr_atime(inode, h_inode);
6596+ fi_write_unlock(file);
6597+
6598+ AuTraceErr(err);
6599+ return err;
6600+ }
6601+
6602+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
6603+
6604+ out_unlock:
6605+ di_read_unlock(dentry, AuLock_IR);
6606+ fi_write_unlock(file);
6607+ out:
6608+ si_read_unlock(sb);
6609+ AuTraceErr(err);
6610+ return err;
6611+}
6612+
6613+/* ---------------------------------------------------------------------- */
6614+
6615+#define AuTestEmpty_WHONLY 1
6616+#define AuTestEmpty_DLGT (1 << 1)
6617+#define AuTestEmpty_DIRPERM1 (1 << 2)
6618+#define AuTestEmpty_CALLED (1 << 3)
6619+#define AuTestEmpty_SHWH (1 << 4)
6620+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
6621+#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
6622+#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
6623+#ifndef CONFIG_AUFS_DLGT
6624+#undef AuTestEmpty_DLGT
6625+#define AuTestEmpty_DLGT 0
6626+#undef AuTestEmpty_DIRPERM1
6627+#define AuTestEmpty_DIRPERM1 0
6628+#endif
6629+#ifndef CONFIG_AUFS_SHWH
6630+#undef AuTestEmpty_SHWH
6631+#define AuTestEmpty_SHWH 0
6632+#endif
6633+
6634+struct test_empty_arg {
6635+ struct au_nhash *whlist;
6636+ unsigned int flags;
6637+ int err;
6638+ aufs_bindex_t bindex;
6639+};
6640+
6641+static int test_empty_cb(void *__arg, const char *__name, int namelen,
6642+ loff_t offset, u64 ino, unsigned int d_type)
6643+{
6644+ struct test_empty_arg *arg = __arg;
6645+ char *name = (void *)__name;
6646+
6647+ LKTRTrace("%.*s\n", namelen, name);
6648+
6649+ arg->err = 0;
6650+ au_fset_testempty(arg->flags, CALLED);
6651+ /* smp_mb(); */
6652+ if (name[0] == '.'
6653+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
6654+ return 0; /* success */
6655+
6656+ if (namelen <= AUFS_WH_PFX_LEN
6657+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
6658+ if (au_ftest_testempty(arg->flags, WHONLY)
6659+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
6660+ arg->err = -ENOTEMPTY;
6661+ goto out;
6662+ }
6663+
6664+ name += AUFS_WH_PFX_LEN;
6665+ namelen -= AUFS_WH_PFX_LEN;
6666+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
6667+ arg->err = au_nhash_append_wh
6668+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
6669+ au_ftest_testempty(arg->flags, SHWH));
6670+
6671+ out:
6672+ /* smp_mb(); */
6673+ AuTraceErr(arg->err);
6674+ return arg->err;
6675+}
6676+
6677+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6678+{
6679+ int err, dlgt;
6680+ struct file *h_file;
6681+
6682+ LKTRTrace("%.*s, {%p, 0x%x, %d}\n",
6683+ AuDLNPair(dentry), arg->whlist, arg->flags, arg->bindex);
6684+
6685+ h_file = au_h_open(dentry, arg->bindex,
6686+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
6687+ /*file*/NULL);
6688+ err = PTR_ERR(h_file);
6689+ if (IS_ERR(h_file))
6690+ goto out;
6691+ err = 0;
6692+ if (au_opt_test(au_mntflags(dentry->d_sb), UDBA_INOTIFY)
6693+ && !h_file->f_dentry->d_inode->i_nlink)
6694+ goto out_put;
6695+
6696+ dlgt = au_ftest_testempty(arg->flags, DLGT);
6697+ do {
6698+ arg->err = 0;
6699+ au_fclr_testempty(arg->flags, CALLED);
6700+ /* smp_mb(); */
6701+ err = vfsub_readdir(h_file, test_empty_cb, arg, dlgt);
6702+ if (err >= 0)
6703+ err = arg->err;
6704+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
6705+
6706+ out_put:
6707+ fput(h_file);
6708+ au_sbr_put(dentry->d_sb, arg->bindex);
6709+ out:
6710+ AuTraceErr(err);
6711+ return err;
6712+}
6713+
6714+struct do_test_empty_args {
6715+ int *errp;
6716+ struct dentry *dentry;
6717+ struct test_empty_arg *arg;
6718+};
6719+
6720+static void call_do_test_empty(void *args)
6721+{
6722+ struct do_test_empty_args *a = args;
6723+ *a->errp = do_test_empty(a->dentry, a->arg);
6724+}
6725+
6726+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6727+{
6728+ int err, wkq_err;
6729+ struct dentry *h_dentry;
6730+ struct inode *h_inode;
6731+
6732+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
6733+ h_dentry = au_h_dptr(dentry, arg->bindex);
6734+ AuDebugOn(!h_dentry);
6735+ h_inode = h_dentry->d_inode;
6736+ AuDebugOn(!h_inode);
6737+
6738+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
6739+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ,
6740+ au_test_dlgt(au_mntflags(dentry->d_sb)));
6741+ mutex_unlock(&h_inode->i_mutex);
6742+ if (!err)
6743+ err = do_test_empty(dentry, arg);
6744+ else {
6745+ struct do_test_empty_args args = {
6746+ .errp = &err,
6747+ .dentry = dentry,
6748+ .arg = arg
6749+ };
6750+ unsigned int flags = arg->flags;
6751+
6752+ au_fclr_testempty(arg->flags, DLGT);
6753+ au_fclr_testempty(arg->flags, DIRPERM1);
6754+ wkq_err = au_wkq_wait(call_do_test_empty, &args, /*dlgt*/0);
6755+ if (unlikely(wkq_err))
6756+ err = wkq_err;
6757+ arg->flags = flags;
6758+ }
6759+
6760+ AuTraceErr(err);
6761+ return err;
6762+}
6763+
6764+int au_test_empty_lower(struct dentry *dentry)
6765+{
6766+ int err;
6767+ struct inode *inode;
6768+ struct test_empty_arg arg;
6769+ struct au_nhash *whlist;
6770+ aufs_bindex_t bindex, bstart, btail;
6771+ unsigned int mnt_flags;
6772+
6773+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
6774+ inode = dentry->d_inode;
6775+ AuDebugOn(!inode || !S_ISDIR(inode->i_mode));
6776+
6777+ whlist = au_nhash_new(GFP_NOFS);
6778+ err = PTR_ERR(whlist);
6779+ if (IS_ERR(whlist))
6780+ goto out;
6781+
6782+ bstart = au_dbstart(dentry);
6783+ mnt_flags = au_mntflags(dentry->d_sb);
6784+ arg.whlist = whlist;
6785+ arg.flags = 0;
6786+ if (au_test_dlgt(mnt_flags))
6787+ au_fset_testempty(arg.flags, DLGT);
6788+ if (au_opt_test(mnt_flags, SHWH))
6789+ au_fset_testempty(arg.flags, SHWH);
6790+ arg.bindex = bstart;
6791+ err = do_test_empty(dentry, &arg);
6792+ if (unlikely(err))
6793+ goto out_whlist;
6794+
6795+ au_fset_testempty(arg.flags, WHONLY);
6796+ if (au_test_dirperm1(mnt_flags))
6797+ au_fset_testempty(arg.flags, DIRPERM1);
6798+ btail = au_dbtaildir(dentry);
6799+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
6800+ struct dentry *h_dentry;
6801+ h_dentry = au_h_dptr(dentry, bindex);
6802+ if (h_dentry && h_dentry->d_inode) {
6803+ arg.bindex = bindex;
6804+ err = do_test_empty(dentry, &arg);
6805+ }
6806+ }
6807+
6808+ out_whlist:
6809+ au_nhash_del(whlist);
6810+ out:
6811+ AuTraceErr(err);
6812+ return err;
6813+}
6814+
6815+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
6816+{
6817+ int err;
6818+ struct inode *inode;
6819+ struct test_empty_arg arg;
6820+ aufs_bindex_t bindex, btail;
6821+
6822+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
6823+ inode = dentry->d_inode;
6824+ AuDebugOn(!inode || !S_ISDIR(inode->i_mode));
6825+
6826+ err = 0;
6827+ arg.whlist = whlist;
6828+ arg.flags = AuTestEmpty_WHONLY;
6829+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6830+ au_fset_testempty(arg.flags, SHWH);
6831+ btail = au_dbtaildir(dentry);
6832+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
6833+ struct dentry *h_dentry;
6834+ h_dentry = au_h_dptr(dentry, bindex);
6835+ if (h_dentry && h_dentry->d_inode) {
6836+ arg.bindex = bindex;
6837+ err = sio_test_empty(dentry, &arg);
6838+ }
6839+ }
6840+
6841+ AuTraceErr(err);
6842+ return err;
6843+}
6844+
6845+/* ---------------------------------------------------------------------- */
6846+
6847+struct file_operations aufs_dir_fop = {
6848+ .read = generic_read_dir,
6849+ .readdir = aufs_readdir,
6850+ /* .unlocked_ioctl = aufs_ioctl_dir, */
6851+ .open = aufs_open_dir,
6852+ .release = aufs_release_dir,
6853+ .flush = aufs_flush,
6854+ .fsync = aufs_fsync_dir,
6855+};
6856diff -urN linux/fs/aufs/dir.h linux-aufs/fs/aufs/dir.h
6857--- linux/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
6858+++ linux-aufs/fs/aufs/dir.h 2009-03-12 16:18:04.000000000 +0100
6859@@ -0,0 +1,147 @@
6860+/*
6861+ * Copyright (C) 2005-2009 Junjiro Okajima
6862+ *
6863+ * This program, aufs is free software; you can redistribute it and/or modify
6864+ * it under the terms of the GNU General Public License as published by
6865+ * the Free Software Foundation; either version 2 of the License, or
6866+ * (at your option) any later version.
6867+ *
6868+ * This program is distributed in the hope that it will be useful,
6869+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6870+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6871+ * GNU General Public License for more details.
6872+ *
6873+ * You should have received a copy of the GNU General Public License
6874+ * along with this program; if not, write to the Free Software
6875+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6876+ */
6877+
6878+/*
6879+ * directory operations
6880+ *
6881+ * $Id$
6882+ */
6883+
6884+#ifndef __AUFS_DIR_H__
6885+#define __AUFS_DIR_H__
6886+
6887+#ifdef __KERNEL__
6888+
6889+#include <linux/fs.h>
6890+#include <linux/aufs_type.h>
6891+
6892+/* ---------------------------------------------------------------------- */
6893+
6894+/* need to be faster and smaller */
6895+
6896+/* todo: changeable? */
6897+#define AuSize_DEBLK 512
6898+#define AuSize_NHASH 32
6899+#if AuSize_DEBLK < NAME_MAX || PAGE_SIZE < AuSize_DEBLK
6900+#error invalid size AuSize_DEBLK
6901+#endif
6902+
6903+typedef char au_vdir_deblk_t[AuSize_DEBLK];
6904+
6905+struct au_nhash {
6906+ struct hlist_head heads[AuSize_NHASH];
6907+};
6908+
6909+struct au_vdir_destr {
6910+ unsigned char len;
6911+ char name[0];
6912+} __packed;
6913+
6914+struct au_vdir_dehstr {
6915+ struct hlist_node hash;
6916+ struct au_vdir_destr *str;
6917+};
6918+
6919+struct au_vdir_de {
6920+ ino_t de_ino;
6921+ unsigned char de_type;
6922+ /* caution: packed */
6923+ struct au_vdir_destr de_str;
6924+} __packed;
6925+
6926+struct au_vdir_wh {
6927+ struct hlist_node wh_hash;
6928+ aufs_bindex_t wh_bindex;
6929+#ifdef CONFIG_AUFS_SHWH
6930+ ino_t wh_ino;
6931+ unsigned char wh_type;
6932+ /* caution: packed */
6933+#endif
6934+ struct au_vdir_destr wh_str;
6935+} __packed;
6936+
6937+union au_vdir_deblk_p {
6938+ unsigned char *p;
6939+ au_vdir_deblk_t *deblk;
6940+ struct au_vdir_de *de;
6941+};
6942+
6943+struct au_vdir {
6944+ au_vdir_deblk_t **vd_deblk;
6945+ int vd_nblk;
6946+ struct {
6947+ int i;
6948+ union au_vdir_deblk_p p;
6949+ } vd_last;
6950+
6951+ unsigned long vd_version;
6952+ unsigned long vd_jiffy;
6953+};
6954+
6955+/* ---------------------------------------------------------------------- */
6956+
6957+/* dir.c */
6958+extern struct file_operations aufs_dir_fop;
6959+int au_test_empty_lower(struct dentry *dentry);
6960+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
6961+
6962+/* vdir.c */
6963+struct au_nhash *au_nhash_new(gfp_t gfp);
6964+void au_nhash_del(struct au_nhash *nhash);
6965+void au_nhash_init(struct au_nhash *nhash);
6966+void au_nhash_move(struct au_nhash *dst, struct au_nhash *src);
6967+void au_nhash_fin(struct au_nhash *nhash);
6968+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
6969+ int limit);
6970+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int namelen);
6971+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int namelen,
6972+ ino_t ino, unsigned int d_type, aufs_bindex_t bindex,
6973+ unsigned char shwh);
6974+void au_vdir_free(struct au_vdir *vdir);
6975+int au_vdir_init(struct file *file);
6976+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
6977+
6978+/* ---------------------------------------------------------------------- */
6979+
6980+static inline
6981+void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino, unsigned char d_type)
6982+{
6983+#ifdef CONFIG_AUFS_SHWH
6984+ wh->wh_ino = ino;
6985+ wh->wh_type = d_type;
6986+#endif
6987+}
6988+
6989+static inline void au_add_nlink(struct inode *dir, struct inode *h_dir)
6990+{
6991+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
6992+ dir->i_nlink += h_dir->i_nlink - 2;
6993+ if (h_dir->i_nlink < 2)
6994+ dir->i_nlink += 2;
6995+}
6996+
6997+static inline void au_sub_nlink(struct inode *dir, struct inode *h_dir)
6998+{
6999+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
7000+ dir->i_nlink -= h_dir->i_nlink - 2;
7001+ if (h_dir->i_nlink < 2)
7002+ dir->i_nlink -= 2;
7003+}
7004+
7005+#endif /* __KERNEL__ */
7006+#endif /* __AUFS_DIR_H__ */
7007diff -urN linux/fs/aufs/dlgt.c linux-aufs/fs/aufs/dlgt.c
7008--- linux/fs/aufs/dlgt.c 1970-01-01 01:00:00.000000000 +0100
7009+++ linux-aufs/fs/aufs/dlgt.c 2009-03-12 16:18:04.000000000 +0100
7010@@ -0,0 +1,113 @@
7011+/*
7012+ * Copyright (C) 2005-2009 Junjiro Okajima
7013+ *
7014+ * This program, aufs is free software; you can redistribute it and/or modify
7015+ * it under the terms of the GNU General Public License as published by
7016+ * the Free Software Foundation; either version 2 of the License, or
7017+ * (at your option) any later version.
7018+ *
7019+ * This program is distributed in the hope that it will be useful,
7020+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7021+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7022+ * GNU General Public License for more details.
7023+ *
7024+ * You should have received a copy of the GNU General Public License
7025+ * along with this program; if not, write to the Free Software
7026+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7027+ */
7028+
7029+/*
7030+ * lookup functions in 'delegate' mode
7031+ *
7032+ * $Id$
7033+ */
7034+
7035+#include "aufs.h"
7036+
7037+/* ---------------------------------------------------------------------- */
7038+
7039+struct au_lookup_one_len_args {
7040+ struct dentry **errp;
7041+ const char *name;
7042+ struct dentry *parent;
7043+ int len;
7044+};
7045+
7046+static void au_call_lookup_one_len(void *args)
7047+{
7048+ struct au_lookup_one_len_args *a = args;
7049+ *a->errp = vfsub_lookup_one_len(a->name, a->parent, a->len);
7050+}
7051+
7052+struct dentry *au_lkup_one_dlgt(const char *name, struct dentry *parent,
7053+ int len, unsigned int flags)
7054+{
7055+ struct dentry *dentry;
7056+ int dirperm1;
7057+
7058+ LKTRTrace("%.*s/%.*s, 0x%x\n", AuDLNPair(parent), len, name, flags);
7059+
7060+ dirperm1 = au_ftest_ndx(flags, DIRPERM1);
7061+ if (!dirperm1 && !au_ftest_ndx(flags, DLGT))
7062+ dentry = vfsub_lookup_one_len(name, parent, len);
7063+ else {
7064+ int wkq_err;
7065+ struct au_lookup_one_len_args args = {
7066+ .errp = &dentry,
7067+ .name = name,
7068+ .parent = parent,
7069+ .len = len
7070+ };
7071+ wkq_err = au_wkq_wait(au_call_lookup_one_len, &args,
7072+ /*dlgt*/!dirperm1);
7073+ if (unlikely(wkq_err))
7074+ dentry = ERR_PTR(wkq_err);
7075+ }
7076+
7077+ AuTraceErrPtr(dentry);
7078+ return dentry;
7079+}
7080+
7081+/* ---------------------------------------------------------------------- */
7082+
7083+struct security_inode_permission_args {
7084+ int *errp;
7085+ struct inode *h_inode;
7086+ int mask;
7087+ struct nameidata *fake_nd;
7088+};
7089+
7090+static void call_security_inode_permission(void *args)
7091+{
7092+ struct security_inode_permission_args *a = args;
94750128 7093+ LKTRTrace("fsuid %d\n", current_fsuid());
024a5822
JR
7094+ *a->errp = vfsub_security_inode_permission(a->h_inode, a->mask,
7095+ a->fake_nd);
7096+}
7097+
7098+int au_security_inode_permission(struct inode *h_inode, int mask,
7099+ struct nameidata *fake_nd, int dlgt)
7100+{
7101+ int err;
7102+
7103+ AuTraceEnter();
7104+
7105+ if (!dlgt)
7106+ err = vfsub_security_inode_permission(h_inode, mask, fake_nd);
7107+ else {
7108+ int wkq_err;
7109+ struct security_inode_permission_args args = {
7110+ .errp = &err,
7111+ .h_inode = h_inode,
7112+ .mask = mask,
7113+ .fake_nd = fake_nd
7114+ };
7115+ wkq_err = au_wkq_wait(call_security_inode_permission, &args,
7116+ /*dlgt*/1);
7117+ if (unlikely(wkq_err))
7118+ err = wkq_err;
7119+ }
7120+
7121+ AuTraceErr(err);
7122+ return err;
7123+}
7124diff -urN linux/fs/aufs/export.c linux-aufs/fs/aufs/export.c
7125--- linux/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
7126+++ linux-aufs/fs/aufs/export.c 2009-03-12 16:18:04.000000000 +0100
1ddfd88b 7127@@ -0,0 +1,827 @@
024a5822
JR
7128+/*
7129+ * Copyright (C) 2005-2009 Junjiro Okajima
7130+ *
7131+ * This program, aufs is free software; you can redistribute it and/or modify
7132+ * it under the terms of the GNU General Public License as published by
7133+ * the Free Software Foundation; either version 2 of the License, or
7134+ * (at your option) any later version.
7135+ *
7136+ * This program is distributed in the hope that it will be useful,
7137+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7138+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7139+ * GNU General Public License for more details.
7140+ *
7141+ * You should have received a copy of the GNU General Public License
7142+ * along with this program; if not, write to the Free Software
7143+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7144+ */
7145+
7146+/*
7147+ * export via nfs
7148+ *
7149+ * $Id$
7150+ */
7151+
7152+#include <linux/exportfs.h>
7153+#include <linux/mnt_namespace.h>
7154+#include <linux/random.h>
1ddfd88b 7155+#include <linux/nsproxy.h>
024a5822
JR
7156+#include "aufs.h"
7157+
7158+union conv {
7159+#ifdef CONFIG_AUFS_INO_T_64
7160+ __u32 a[2];
7161+#else
7162+ __u32 a[1];
7163+#endif
7164+ ino_t ino;
7165+};
7166+
7167+static ino_t decode_ino(__u32 *a)
7168+{
7169+ union conv u;
7170+
7171+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
7172+ u.a[0] = a[0];
7173+#ifdef CONFIG_AUFS_INO_T_64
7174+ u.a[1] = a[1];
7175+#endif
7176+ return u.ino;
7177+}
7178+
7179+static void encode_ino(__u32 *a, ino_t ino)
7180+{
7181+ union conv u;
7182+
7183+ u.ino = ino;
7184+ a[0] = u.a[0];
7185+#ifdef CONFIG_AUFS_INO_T_64
7186+ a[1] = u.a[1];
7187+#endif
7188+}
7189+
7190+/* NFS file handle */
7191+enum {
7192+ Fh_br_id,
7193+ Fh_sigen,
7194+#ifdef CONFIG_AUFS_INO_T_64
7195+ /* support 64bit inode number */
7196+ Fh_ino1,
7197+ Fh_ino2,
7198+ Fh_dir_ino1,
7199+ Fh_dir_ino2,
7200+#else
7201+ Fh_ino1,
7202+ Fh_dir_ino1,
7203+#endif
7204+ Fh_igen,
7205+ Fh_h_type,
7206+ Fh_tail,
7207+
7208+ Fh_ino = Fh_ino1,
7209+ Fh_dir_ino = Fh_dir_ino1
7210+};
7211+
7212+static int au_test_anon(struct dentry *dentry)
7213+{
7214+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
7215+}
7216+
7217+/* ---------------------------------------------------------------------- */
7218+/* inode generation external table */
7219+
7220+int au_xigen_inc(struct inode *inode)
7221+{
7222+ int err;
7223+ loff_t pos;
7224+ ssize_t sz;
7225+ __u32 igen;
7226+ struct super_block *sb;
7227+ struct au_sbinfo *sbinfo;
7228+
7229+ LKTRTrace("i%lu\n", (unsigned long)inode->i_ino);
7230+
7231+ err = 0;
7232+ sb = inode->i_sb;
7233+ if (unlikely(!au_opt_test_xino(au_mntflags(sb))))
7234+ goto out;
7235+
7236+ pos = inode->i_ino;
7237+ pos *= sizeof(igen);
7238+ igen = inode->i_generation + 1;
7239+ sbinfo = au_sbi(sb);
7240+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
7241+ sizeof(igen), &pos);
7242+ if (sz == sizeof(igen))
7243+ goto out; /* success */
7244+
7245+ err = sz;
7246+ if (unlikely(sz >= 0)) {
7247+ err = -EIO;
7248+ AuIOErr("xigen error (%zd)\n", sz);
7249+ }
7250+
7251+ out:
7252+ AuTraceErr(err);
7253+ return err;
7254+}
7255+
7256+int au_xigen_new(struct inode *inode)
7257+{
7258+ int err;
7259+ loff_t pos;
7260+ ssize_t sz;
7261+ struct super_block *sb;
7262+ struct au_sbinfo *sbinfo;
7263+ struct file *file;
7264+
7265+ LKTRTrace("i%lu\n", inode->i_ino);
7266+
7267+ err = 0;
7268+ /* todo: dirty, at mount time */
7269+ if (inode->i_ino == AUFS_ROOT_INO)
7270+ goto out;
7271+ sb = inode->i_sb;
7272+ if (unlikely(!au_opt_test_xino(au_mntflags(sb))))
7273+ goto out;
7274+
7275+ err = -EFBIG;
7276+ pos = inode->i_ino;
7277+ if (unlikely(Au_LOFF_MAX / sizeof(inode->i_generation) - 1 < pos)) {
7278+ AuIOErr1("too large i%lld\n", pos);
7279+ goto out;
7280+ }
7281+ pos *= sizeof(inode->i_generation);
7282+
7283+ err = 0;
7284+ sbinfo = au_sbi(sb);
7285+ file = sbinfo->si_xigen;
7286+ BUG_ON(!file);
7287+
7288+ if (i_size_read(file->f_dentry->d_inode)
7289+ < pos + sizeof(inode->i_generation)) {
7290+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
7291+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
7292+ sizeof(inode->i_generation), &pos);
7293+ } else
7294+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
7295+ sizeof(inode->i_generation), &pos);
7296+ if (sz == sizeof(inode->i_generation))
7297+ goto out; /* success */
7298+
7299+ err = sz;
7300+ if (unlikely(sz >= 0)) {
7301+ err = -EIO;
7302+ AuIOErr("xigen error (%zd)\n", sz);
7303+ }
7304+
7305+ out:
7306+ AuTraceErr(err);
7307+ return err;
7308+}
7309+
7310+int au_xigen_set(struct super_block *sb, struct file *base)
7311+{
7312+ int err;
7313+ struct au_sbinfo *sbinfo;
7314+ struct file *file;
7315+
7316+ LKTRTrace("%.*s\n", AuDLNPair(base->f_dentry));
7317+ SiMustWriteLock(sb);
7318+
7319+ sbinfo = au_sbi(sb);
7320+ file = au_xino_create2(sb, base, sbinfo->si_xigen);
7321+ err = PTR_ERR(file);
7322+ if (IS_ERR(file))
7323+ goto out;
7324+ err = 0;
7325+ if (sbinfo->si_xigen)
7326+ fput(sbinfo->si_xigen);
7327+ sbinfo->si_xigen = file;
7328+
7329+ out:
7330+ AuTraceErr(err);
7331+ return err;
7332+}
7333+
7334+void au_xigen_clr(struct super_block *sb)
7335+{
7336+ struct au_sbinfo *sbinfo;
7337+
7338+ sbinfo = au_sbi(sb);
7339+ if (sbinfo->si_xigen) {
7340+ fput(sbinfo->si_xigen);
7341+ sbinfo->si_xigen = NULL;
7342+ }
7343+}
7344+
7345+/* ---------------------------------------------------------------------- */
7346+
7347+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
7348+ ino_t dir_ino)
7349+{
7350+ struct dentry *dentry, *d;
7351+ struct inode *inode;
7352+ au_gen_t sigen;
7353+
7354+ LKTRTrace("i%lu, diri%lu\n",
7355+ (unsigned long)ino, (unsigned long)dir_ino);
7356+
7357+ dentry = NULL;
7358+ inode = ilookup(sb, ino);
7359+ if (!inode)
7360+ goto out;
7361+
7362+ dentry = ERR_PTR(-ESTALE);
7363+ sigen = au_sigen(sb);
7364+ if (unlikely(is_bad_inode(inode)
7365+ || IS_DEADDIR(inode)
7366+ || sigen != au_iigen(inode)))
7367+ goto out_iput;
7368+
7369+ dentry = NULL;
7370+ if (!dir_ino || S_ISDIR(inode->i_mode))
7371+ dentry = d_find_alias(inode);
7372+ else {
7373+ spin_lock(&dcache_lock);
7374+ list_for_each_entry(d, &inode->i_dentry, d_alias)
7375+ if (!au_test_anon(d)
7376+ && d->d_parent->d_inode->i_ino == dir_ino) {
7377+ dentry = dget_locked(d);
7378+ break;
7379+ }
7380+ spin_unlock(&dcache_lock);
7381+ }
7382+ if (unlikely(dentry && sigen != au_digen(dentry))) {
7383+ dput(dentry);
7384+ dentry = ERR_PTR(-ESTALE);
7385+ }
7386+
7387+ out_iput:
7388+ iput(inode);
7389+ out:
7390+ AuTraceErrPtr(dentry);
7391+ return dentry;
7392+}
7393+
7394+/* ---------------------------------------------------------------------- */
7395+
7396+/* todo: dirty? */
7397+/*
7398+ * when you mntput() for the return value of this function,
7399+ * you have to store it to your local var.
7400+ * ie. never mntput si_mntcache directly.
7401+ */
7402+static struct vfsmount *au_do_mnt_get(struct super_block *sb)
7403+{
7404+ struct mnt_namespace *ns;
7405+ struct vfsmount *pos, *mnt;
7406+
7407+ AuTraceEnter();
7408+
7409+ /* vfsmount_lock is not exported */
7410+ /* no get/put ?? */
7411+ AuDebugOn(!current->nsproxy);
7412+ ns = current->nsproxy->mnt_ns;
7413+ AuDebugOn(!ns);
7414+ mnt = NULL;
7415+ /* the order (reverse) will not be a problem */
7416+ list_for_each_entry(pos, &ns->list, mnt_list)
7417+ if (pos->mnt_sb == sb) {
7418+ mnt = pos;
7419+ break;
7420+ }
7421+ AuDebugOn(!mnt);
7422+
7423+ return mntget(mnt);
7424+}
7425+
7426+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
7427+static struct vfsmount *au_mnt_get(struct super_block *sb)
7428+{
7429+ struct au_sbinfo *sbinfo;
7430+ struct vfsmount *mnt;
7431+
7432+ sbinfo = au_sbi(sb);
7433+ spin_lock(&sbinfo->si_mntcache_lock);
7434+ if (sbinfo->si_mntcache)
7435+ mnt = mntget(sbinfo->si_mntcache);
7436+ else {
7437+ sbinfo->si_mntcache = au_do_mnt_get(sb);
7438+ mnt = sbinfo->si_mntcache;
7439+ }
7440+ spin_unlock(&sbinfo->si_mntcache_lock);
7441+ return mnt;
7442+}
7443+#else
7444+static struct vfsmount *au_mnt_get(struct super_block *sb)
7445+{
7446+ return au_do_mnt_get(sb);
7447+}
7448+#endif
7449+
7450+struct au_nfsd_si_lock {
7451+ const au_gen_t sigen;
7452+ const aufs_bindex_t br_id;
7453+ unsigned char force_lock;
7454+};
7455+
7456+static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
7457+ struct au_nfsd_si_lock *nsi_lock)
7458+{
7459+ aufs_bindex_t bindex;
7460+
7461+ si_read_lock(sb, AuLock_FLUSH);
7462+
7463+ /* branch id may be wrapped around */
7464+ bindex = au_br_index(sb, nsi_lock->br_id);
7465+ LKTRTrace("b%d\n", bindex);
7466+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
7467+ goto out; /* success */
7468+
7469+ if (!nsi_lock->force_lock)
7470+ si_read_unlock(sb);
7471+ bindex = -1;
7472+
7473+ out:
7474+ return bindex;
7475+}
7476+
7477+struct find_name_by_ino {
7478+ int called, found;
7479+ ino_t ino;
7480+ char *name;
7481+ int namelen;
7482+};
7483+
7484+static int
7485+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
7486+ u64 ino, unsigned int d_type)
7487+{
7488+ struct find_name_by_ino *a = arg;
7489+
7490+ a->called++;
7491+ if (a->ino != ino)
7492+ return 0;
7493+
7494+ memcpy(a->name, name, namelen);
7495+ a->namelen = namelen;
7496+ a->found = 1;
7497+ return 1;
7498+}
7499+
7500+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
7501+ struct au_nfsd_si_lock *nsi_lock)
7502+{
7503+ struct dentry *dentry, *parent;
7504+ struct file *file;
7505+ struct inode *dir;
7506+ struct find_name_by_ino arg;
7507+ int err;
7508+
7509+ parent = path->dentry;
7510+ LKTRTrace("%.*s, i%lu\n", AuDLNPair(parent), (unsigned long)ino);
7511+
7512+ if (nsi_lock)
7513+ si_read_unlock(parent->d_sb);
7514+ path_get(path);
94750128 7515+ file = dentry_open(parent, path->mnt, au_dir_roflags, file->f_cred);
024a5822
JR
7516+ dentry = (void *)file;
7517+ if (IS_ERR(file))
7518+ goto out;
7519+
7520+ dentry = ERR_PTR(-ENOMEM);
7521+ arg.name = __getname();
7522+ if (unlikely(!arg.name))
7523+ goto out_file;
7524+ arg.ino = ino;
7525+ arg.found = 0;
7526+ do {
7527+ arg.called = 0;
7528+ /* smp_mb(); */
7529+ err = vfsub_readdir(file, find_name_by_ino, &arg, /*dlgt*/0);
7530+ } while (!err && !arg.found && arg.called);
7531+ dentry = ERR_PTR(err);
7532+ if (unlikely(err))
7533+ goto out_name;
7534+ dentry = ERR_PTR(-ENOENT);
7535+ if (!arg.found)
7536+ goto out_name;
7537+
7538+ /* do not call au_lkup_one(), nor dlgt */
7539+ dir = parent->d_inode;
7540+ mutex_lock(&dir->i_mutex);
7541+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
7542+ mutex_unlock(&dir->i_mutex);
7543+ AuTraceErrPtr(dentry);
7544+ if (IS_ERR(dentry))
7545+ goto out_name;
7546+ AuDebugOn(au_test_anon(dentry));
7547+ if (unlikely(!dentry->d_inode)) {
7548+ dput(dentry);
7549+ dentry = ERR_PTR(-ENOENT);
7550+ }
7551+
7552+ out_name:
7553+ __putname(arg.name);
7554+ out_file:
7555+ fput(file);
7556+ out:
7557+ if (unlikely(nsi_lock
7558+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
7559+ if (!IS_ERR(dentry)) {
7560+ dput(dentry);
7561+ dentry = ERR_PTR(-ESTALE);
7562+ }
7563+ AuTraceErrPtr(dentry);
7564+ return dentry;
7565+}
7566+
7567+static /* noinline_for_stack */
7568+struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
7569+ ino_t dir_ino, struct au_nfsd_si_lock *nsi_lock)
7570+{
7571+ struct dentry *dentry, *parent;
7572+ struct path path;
7573+
7574+ LKTRTrace("i%lu, diri%lu\n",
7575+ (unsigned long)ino, (unsigned long)dir_ino);
7576+
7577+ parent = sb->s_root;
7578+ if (dir_ino != AUFS_ROOT_INO) {
7579+ parent = decode_by_ino(sb, dir_ino, 0);
7580+ dentry = parent;
7581+ if (!parent)
7582+ goto out;
7583+ if (IS_ERR(parent))
7584+ goto out;
7585+ AuDebugOn(au_test_anon(parent));
7586+ } else
7587+ dget(parent);
7588+
7589+ path.dentry = parent;
7590+ path.mnt = au_mnt_get(sb);
7591+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
7592+ path_put(&path);
7593+
7594+ out:
7595+ AuTraceErrPtr(dentry);
7596+ return dentry;
7597+}
7598+
7599+/* ---------------------------------------------------------------------- */
7600+
7601+static int h_acceptable(void *expv, struct dentry *dentry)
7602+{
7603+ return 1;
7604+}
7605+
7606+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
7607+ char *buf, int len, struct super_block *sb)
7608+{
7609+ char *p;
7610+ int n;
7611+ struct path path;
7612+
7613+ AuTraceEnter();
7614+
7615+ p = d_path(h_rootpath, buf, len);
7616+ if (IS_ERR(p))
7617+ goto out;
7618+ n = strlen(p);
7619+
7620+ path.mnt = h_rootpath->mnt;
7621+ path.dentry = h_parent;
7622+ p = d_path(&path, buf, len);
7623+ if (IS_ERR(p))
7624+ goto out;
7625+ LKTRTrace("%s\n", p);
7626+ if (n != 1)
7627+ p += n;
7628+ LKTRTrace("%p, %s, %ld\n",
7629+ p, p, (long)(p - buf));
7630+
7631+ path.mnt = au_mnt_get(sb);
7632+ path.dentry = sb->s_root;
7633+ p = d_path(&path, buf, len - strlen(p));
7634+ mntput(path.mnt);
7635+ if (IS_ERR(p))
7636+ goto out;
7637+ if (n != 1)
7638+ p[strlen(p)] = '/';
7639+ LKTRTrace("%s\n", p);
7640+
7641+ out:
7642+ AuTraceErrPtr(p);
7643+ return p;
7644+}
7645+
7646+static noinline_for_stack
7647+struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
7648+ ino_t ino, __u32 *fh, int fh_len,
7649+ struct au_nfsd_si_lock *nsi_lock)
7650+{
7651+ struct dentry *dentry, *h_parent, *root;
7652+ struct super_block *h_sb;
7653+ char *pathname, *p;
7654+ struct vfsmount *h_mnt;
7655+ struct au_branch *br;
7656+ int err;
7657+ struct nameidata nd;
7658+
7659+ LKTRTrace("b%d\n", bindex);
7660+ SiMustAnyLock(sb);
7661+
7662+ br = au_sbr(sb, bindex);
7663+ /* au_br_get(br); */
7664+ h_mnt = br->br_mnt;
7665+ h_sb = h_mnt->mnt_sb;
7666+ LKTRTrace("%s, h_decode_fh\n", au_sbtype(h_sb));
7667+ /* in linux-2.6.24, it takes struct fid * as file handle */
7668+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
7669+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
7670+ fh_len - Fh_tail, fh[Fh_h_type],
7671+ h_acceptable, /*context*/NULL);
7672+ dentry = h_parent;
7673+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
7674+ AuWarn1("%s decode_fh failed, %ld\n",
7675+ au_sbtype(h_sb), PTR_ERR(h_parent));
7676+ goto out;
7677+ }
7678+ dentry = NULL;
7679+ if (unlikely(au_test_anon(h_parent))) {
7680+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
7681+ au_sbtype(h_sb));
7682+ goto out_h_parent;
7683+ }
7684+
7685+ dentry = ERR_PTR(-ENOMEM);
7686+ pathname = (void *)__get_free_page(GFP_NOFS);
7687+ if (unlikely(!pathname))
7688+ goto out_h_parent;
7689+
7690+ root = sb->s_root;
7691+ nd.path.mnt = h_mnt;
7692+ di_read_lock_parent(root, !AuLock_IR);
7693+ nd.path.dentry = au_h_dptr(root, bindex);
7694+ di_read_unlock(root, !AuLock_IR);
7695+ p = au_build_path(h_parent, &nd.path, pathname, PAGE_SIZE, sb);
7696+ dentry = (void *)p;
7697+ if (IS_ERR(p))
7698+ goto out_pathname;
7699+
7700+ LKTRTrace("%s\n", p);
7701+ si_read_unlock(sb);
7702+ err = vfsub_path_lookup(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd);
7703+ dentry = ERR_PTR(err);
7704+ if (unlikely(err))
7705+ goto out_relock;
7706+
7707+ dentry = ERR_PTR(-ENOENT);
7708+ AuDebugOn(au_test_anon(nd.path.dentry));
7709+ if (unlikely(!nd.path.dentry->d_inode))
7710+ goto out_nd;
7711+
7712+ if (ino != nd.path.dentry->d_inode->i_ino)
7713+ dentry = au_lkup_by_ino(&nd.path, ino, /*nsi_lock*/NULL);
7714+ else
7715+ dentry = dget(nd.path.dentry);
7716+
7717+ out_nd:
7718+ path_put(&nd.path);
7719+ out_relock:
7720+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
7721+ if (!IS_ERR(dentry)) {
7722+ dput(dentry);
7723+ dentry = ERR_PTR(-ESTALE);
7724+ }
7725+ out_pathname:
7726+ free_page((unsigned long)pathname);
7727+ out_h_parent:
7728+ dput(h_parent);
7729+ out:
7730+ /* au_br_put(br); */
7731+ AuTraceErrPtr(dentry);
7732+ return dentry;
7733+}
7734+
7735+/* ---------------------------------------------------------------------- */
7736+
7737+static struct dentry *
7738+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
7739+ int fh_type)
7740+{
7741+ struct dentry *dentry;
7742+ __u32 *fh = fid->raw;
7743+ ino_t ino, dir_ino;
7744+ aufs_bindex_t bindex;
7745+ struct au_nfsd_si_lock nsi_lock = {
7746+ .sigen = fh[Fh_sigen],
7747+ .br_id = fh[Fh_br_id],
7748+ .force_lock = 0
7749+ };
7750+
7751+ LKTRTrace("%d, fh{br_id %u, sigen %u, i%u, diri%u, g%u}\n",
7752+ fh_type, fh[Fh_br_id], fh[Fh_sigen], fh[Fh_ino],
7753+ fh[Fh_dir_ino], fh[Fh_igen]);
7754+ AuDebugOn(fh_len < Fh_tail);
7755+
7756+ dentry = ERR_PTR(-ESTALE);
7757+ /* branch id may be wrapped around */
7758+ bindex = si_nfsd_read_lock(sb, &nsi_lock);
7759+ if (unlikely(bindex < 0))
7760+ goto out;
7761+ nsi_lock.force_lock = 1;
7762+
7763+ /* is this inode still cached? */
7764+ ino = decode_ino(fh + Fh_ino);
7765+ AuDebugOn(ino == AUFS_ROOT_INO);
7766+ dir_ino = decode_ino(fh + Fh_dir_ino);
7767+ dentry = decode_by_ino(sb, ino, dir_ino);
7768+ if (IS_ERR(dentry))
7769+ goto out_unlock;
7770+ if (dentry)
7771+ goto accept;
7772+
7773+ /* is the parent dir cached? */
7774+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
7775+ if (IS_ERR(dentry))
7776+ goto out_unlock;
7777+ if (dentry)
7778+ goto accept;
7779+
7780+ /* lookup path */
7781+ dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
7782+ if (IS_ERR(dentry))
7783+ goto out_unlock;
7784+ if (unlikely(!dentry))
7785+ /* todo?: make it ESTALE */
7786+ goto out_unlock;
7787+
7788+ accept:
7789+ LKTRLabel(accept);
7790+ if (dentry->d_inode->i_generation == fh[Fh_igen])
7791+ goto out_unlock; /* success */
7792+
7793+ LKTRLabel(stale);
7794+ dput(dentry);
7795+ dentry = ERR_PTR(-ESTALE);
7796+ out_unlock:
7797+ LKTRLabel(out_unlock);
7798+ si_read_unlock(sb);
7799+ out:
7800+ LKTRLabel(out);
7801+ if (0 && IS_ERR(dentry))
7802+ dentry = ERR_PTR(-ESTALE);
7803+ AuTraceErrPtr(dentry);
7804+ return dentry;
7805+}
7806+
7807+#if 0 /* reserved for future use */
7808+/* support subtreecheck option */
7809+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
7810+ int fh_len, int fh_type)
7811+{
7812+ struct dentry *parent;
7813+ __u32 *fh = fid->raw;
7814+ ino_t dir_ino;
7815+
7816+ dir_ino = decode_ino(fh + Fh_dir_ino);
7817+ parent = decode_by_ino(sb, dir_ino, 0);
7818+ if (IS_ERR(parent))
7819+ goto out;
7820+ if (!parent)
7821+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
7822+ dir_ino, fh, fh_len);
7823+
7824+ out:
7825+ AuTraceErrPtr(parent);
7826+ return parent;
7827+}
7828+#endif
7829+
7830+/* ---------------------------------------------------------------------- */
7831+
7832+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
7833+ int connectable)
7834+{
7835+ int err;
7836+ aufs_bindex_t bindex, bend;
7837+ struct super_block *sb, *h_sb;
7838+ struct inode *inode;
7839+ struct dentry *parent, *h_parent;
7840+ struct au_branch *br;
7841+
7842+ LKTRTrace("%.*s, max %d, conn %d\n",
7843+ AuDLNPair(dentry), *max_len, connectable);
7844+ AuDebugOn(au_test_anon(dentry));
7845+
7846+ parent = NULL;
7847+ err = -ENOSPC;
7848+ if (unlikely(*max_len <= Fh_tail)) {
7849+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
7850+ goto out;
7851+ }
7852+
7853+ err = FILEID_ROOT;
7854+ if (IS_ROOT(dentry)) {
7855+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
7856+ goto out;
7857+ }
7858+
7859+ err = -EIO;
7860+ h_parent = NULL;
7861+ sb = dentry->d_sb;
7862+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
7863+ parent = dget_parent(dentry);
7864+ di_read_lock_parent(parent, !AuLock_IR);
7865+ inode = dentry->d_inode;
7866+ AuDebugOn(!inode);
7867+#ifdef CONFIG_AUFS_DEBUG
7868+ {
7869+ unsigned int mnt_flags = au_mntflags(sb);
7870+
7871+ if (unlikely(!au_opt_test_xino(mnt_flags)))
7872+ AuWarn1("NFS-exporting requires xino\n");
7873+ if (unlikely(0 && !au_opt_test(mnt_flags, UDBA_INOTIFY)))
7874+ AuWarn1("udba=inotify is recommended "
7875+ "for NFS-exporting\n");
7876+ }
7877+#endif
7878+
7879+ bend = au_dbtaildir(parent);
7880+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
7881+ h_parent = au_h_dptr(parent, bindex);
7882+ if (h_parent) {
7883+ dget(h_parent);
7884+ break;
7885+ }
7886+ }
7887+ if (unlikely(!h_parent))
7888+ goto out_unlock;
7889+ LKTRTrace("b%d\n", bindex);
7890+
7891+ err = -EPERM;
7892+ br = au_sbr(sb, bindex);
7893+ h_sb = br->br_mnt->mnt_sb;
7894+ if (unlikely(!h_sb->s_export_op)) {
7895+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
7896+ goto out_dput;
7897+ }
7898+
7899+ fh[Fh_br_id] = br->br_id;
7900+ fh[Fh_sigen] = au_sigen(sb);
7901+ encode_ino(fh + Fh_ino, inode->i_ino);
7902+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
7903+ fh[Fh_igen] = inode->i_generation;
7904+
7905+ *max_len -= Fh_tail;
7906+ /* in linux-2.6.24, it takes struct fid * as file handle */
7907+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
7908+ max_len,
7909+ /*connectable or subtreecheck*/0);
7910+ err = fh[Fh_h_type];
7911+ *max_len += Fh_tail;
7912+ /* todo: macros? */
7913+ if (err != 255)
7914+ err = 99;
7915+ else
7916+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
7917+
7918+ out_dput:
7919+ dput(h_parent);
7920+ out_unlock:
7921+ di_read_unlock(parent, !AuLock_IR);
7922+ dput(parent);
7923+ aufs_read_unlock(dentry, AuLock_IR);
7924+ out:
7925+ AuTraceErr(err);
7926+ if (unlikely(err < 0))
7927+ err = 255;
7928+ return err;
7929+}
7930+
7931+/* ---------------------------------------------------------------------- */
7932+
7933+static struct export_operations aufs_export_op = {
7934+ .fh_to_dentry = aufs_fh_to_dentry,
7935+ //.fh_to_parent = aufs_fh_to_parent,
7936+ .encode_fh = aufs_encode_fh
7937+};
7938+
7939+void au_export_init(struct super_block *sb)
7940+{
7941+ struct au_sbinfo *sbinfo;
7942+ __u32 u;
7943+
7944+ AuTraceEnter();
7945+ SiMustWriteLock(sb);
7946+
7947+ sb->s_export_op = &aufs_export_op;
7948+ sbinfo = au_sbi(sb);
7949+ sbinfo->si_xigen = NULL;
7950+ get_random_bytes(&u, sizeof(u));
7951+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
7952+ atomic_set(&sbinfo->si_xigen_next, u);
7953+ memset(&sbinfo->si_xinodir, 0, sizeof(struct path));
7954+}
7955diff -urN linux/fs/aufs/file.c linux-aufs/fs/aufs/file.c
7956--- linux/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
7957+++ linux-aufs/fs/aufs/file.c 2009-03-12 16:18:04.000000000 +0100
7958@@ -0,0 +1,777 @@
7959+/*
7960+ * Copyright (C) 2005-2009 Junjiro Okajima
7961+ *
7962+ * This program, aufs is free software; you can redistribute it and/or modify
7963+ * it under the terms of the GNU General Public License as published by
7964+ * the Free Software Foundation; either version 2 of the License, or
7965+ * (at your option) any later version.
7966+ *
7967+ * This program is distributed in the hope that it will be useful,
7968+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7969+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7970+ * GNU General Public License for more details.
7971+ *
7972+ * You should have received a copy of the GNU General Public License
7973+ * along with this program; if not, write to the Free Software
7974+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7975+ */
7976+
7977+/*
7978+ * handling file/dir, and address_space operation
7979+ *
7980+ * $Id$
7981+ */
7982+
7983+#include <linux/pagemap.h>
7984+#include "aufs.h"
7985+
7986+/*
7987+ * a dirty trick for handling FMODE_EXEC and deny_write_access().
7988+ * because FMODE_EXEC flag is not passed to f_op->open(),
7989+ * set it to file->private_data temporary.
7990+ */
7991+#if !defined(CONFIG_AUFS_MODULE) || defined(CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH)
7992+int au_store_fmode_exec(struct nameidata *nd, struct inode *inode)
7993+{
7994+ int err;
7995+ union {
7996+ void *p;
7997+ unsigned long ul;
7998+ } u;
7999+
8000+ err = 0;
8001+ if (nd
8002+ && (nd->flags & LOOKUP_OPEN)
8003+ && nd->intent.open.file
8004+ && (nd->intent.open.flags & FMODE_EXEC)
8005+ && inode
8006+ && S_ISREG(inode->i_mode)) {
8007+ u.ul = nd->intent.open.flags;
8008+ nd->intent.open.file->private_data = u.p;
8009+ /* smp_mb(); */
8010+ err = 1;
8011+ }
8012+
8013+ return err;
8014+}
8015+#endif
8016+
8017+/* drop flags for writing */
8018+unsigned int au_file_roflags(unsigned int flags)
8019+{
8020+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
8021+ flags |= O_RDONLY | O_NOATIME;
8022+ return flags;
8023+}
8024+
8025+/* common functions to regular file and dir */
8026+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8027+ struct file *file)
8028+{
8029+ struct file *h_file;
8030+ struct dentry *h_dentry;
8031+ struct inode *h_inode;
8032+ struct super_block *sb;
8033+ struct au_branch *br;
8034+ int err;
8035+
8036+ LKTRTrace("%.*s, b%d, flags 0%o, f %d\n",
8037+ AuDLNPair(dentry), bindex, flags, !!file);
8038+ h_dentry = au_h_dptr(dentry, bindex);
8039+ AuDebugOn(!h_dentry);
8040+ h_inode = h_dentry->d_inode;
8041+
8042+ /* a race condition can happen between open and unlink/rmdir */
8043+ h_file = ERR_PTR(-ENOENT);
8044+ if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
8045+ || !h_inode))
8046+ goto out;
8047+
8048+ sb = dentry->d_sb;
8049+ br = au_sbr(sb, bindex);
8050+ au_br_get(br);
8051+ /* drop flags for writing */
8052+ if (au_test_ro(sb, bindex, dentry->d_inode))
8053+ flags = au_file_roflags(flags);
8054+ flags &= ~O_CREAT;
8055+
8056+ h_file = NULL;
8057+ if (file && au_test_nfs(h_dentry->d_sb))
8058+ h_file = au_h_intent(dentry, bindex, file);
8059+ if (!h_file)
1ddfd88b 8060+ h_file = dentry_open(dget(h_dentry), mntget(br->br_mnt), flags, current_cred());
024a5822
JR
8061+
8062+ /*
8063+ * a dirty trick for handling FMODE_EXEC and deny_write_access().
8064+ */
8065+ if (file && (file->f_mode & FMODE_EXEC)) {
8066+ h_file->f_mode |= FMODE_EXEC;
8067+ smp_mb(); /* flush f_mode */
8068+ err = au_deny_write_access(h_file);
8069+ if (unlikely(err)) {
8070+ fput(h_file);
8071+ h_file = ERR_PTR(err);
8072+ }
8073+ }
8074+ if (IS_ERR(h_file))
8075+ au_br_put(br);
8076+
8077+out:
8078+ AuTraceErrPtr(h_file);
8079+ return h_file;
8080+}
8081+
8082+static int do_coo(struct dentry *dentry, aufs_bindex_t bstart)
8083+{
8084+ int err;
8085+ aufs_bindex_t bcpup;
8086+ unsigned char pin_flags;
8087+ struct au_pin pin;
8088+ struct dentry *parent;
8089+ struct mutex *h_mtx;
8090+ struct super_block *sb;
8091+
8092+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
8093+ AuDebugOn(IS_ROOT(dentry));
8094+ DiMustWriteLock(dentry);
8095+
8096+ parent = dget_parent(dentry);
8097+ di_write_lock_parent(parent);
8098+ sb = dentry->d_sb;
8099+ err = AuWbrCopyup(au_sbi(sb), dentry);
8100+ bcpup = err;
8101+ if (err < 0) {
8102+ err = 0; /* stop copyup, it is not an error */
8103+ goto out_dgrade;
8104+ }
8105+ err = 0;
8106+
8107+ if (!au_h_dptr(parent, bcpup)) {
8108+ err = au_cpup_dirs(dentry, bcpup);
8109+ if (unlikely(err))
8110+ goto out_dgrade;
8111+ }
8112+
8113+ di_downgrade_lock(parent, AuLock_IR);
8114+ pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
8115+ if (au_opt_test(au_mntflags(sb), UDBA_INOTIFY))
8116+ au_fset_pin(pin_flags, DO_GPARENT);
8117+ err = au_pin(&pin, dentry, bcpup, pin_flags);
8118+ if (unlikely(err))
8119+ goto out;
8120+ h_mtx = &au_h_dptr(dentry, bstart)->d_inode->i_mutex;
8121+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
8122+ AuDebugOn(au_h_dptr(dentry, bcpup));
8123+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
8124+ AuTraceErr(err);
8125+ mutex_unlock(h_mtx);
8126+ au_unpin(&pin);
8127+ goto out;
8128+
8129+ out_dgrade:
8130+ di_downgrade_lock(parent, AuLock_IR);
8131+ out:
8132+ di_read_unlock(parent, AuLock_IR);
8133+ dput(parent);
8134+ AuTraceErr(err);
8135+ return err;
8136+}
8137+
8138+int au_do_open(struct inode *inode, struct file *file,
8139+ int (*open)(struct file *file, int flags))
8140+{
8141+ int err;
8142+ struct dentry *dentry;
8143+ struct super_block *sb;
8144+ aufs_bindex_t bstart;
8145+ unsigned char coo;
8146+
8147+ dentry = file->f_dentry;
8148+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry));
8149+
8150+ sb = dentry->d_sb;
8151+ si_read_lock(sb, AuLock_FLUSH);
8152+ coo = 0;
8153+ if (!(sb->s_flags & MS_RDONLY))
8154+ switch (au_mntflags(sb) & AuOptMask_COO) {
8155+ case AuOpt_COO_LEAF:
8156+ coo = !S_ISDIR(inode->i_mode);
8157+ break;
8158+ case AuOpt_COO_ALL:
8159+ coo = 1;
8160+ break;
8161+ }
8162+ err = au_finfo_init(file);
8163+ if (unlikely(err))
8164+ goto out;
8165+
8166+ if (!coo)
8167+ di_read_lock_child(dentry, AuLock_IR);
8168+ else {
8169+ di_write_lock_child(dentry);
8170+ bstart = au_dbstart(dentry);
8171+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
8172+ err = do_coo(dentry, bstart);
8173+ if (err) {
8174+ di_write_unlock(dentry);
8175+ goto out_finfo;
8176+ }
8177+ }
8178+ di_downgrade_lock(dentry, AuLock_IR);
8179+ }
8180+
8181+ err = open(file, file->f_flags);
8182+ di_read_unlock(dentry, AuLock_IR);
8183+
8184+ out_finfo:
8185+ fi_write_unlock(file);
8186+ if (unlikely(err))
8187+ au_finfo_fin(file);
8188+ out:
8189+ si_read_unlock(sb);
8190+ AuTraceErr(err);
8191+ return err;
8192+}
8193+
8194+int au_reopen_nondir(struct file *file)
8195+{
8196+ int err;
8197+ aufs_bindex_t bstart, bindex, bend;
8198+ struct dentry *dentry;
8199+ struct file *h_file, *h_file_tmp;
8200+
8201+ dentry = file->f_dentry;
8202+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
8203+ bstart = au_dbstart(dentry);
8204+ //bstart = au_ibstart(inode);
8205+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
8206+ || !au_h_dptr(dentry, bstart)->d_inode);
8207+
8208+ h_file_tmp = NULL;
8209+ if (au_fbstart(file) == bstart) {
8210+ h_file = au_h_fptr(file, bstart);
8211+ if (file->f_mode == h_file->f_mode)
8212+ return 0; /* success */
8213+ h_file_tmp = h_file;
8214+ get_file(h_file_tmp);
8215+ au_set_h_fptr(file, bstart, NULL);
8216+ }
8217+ AuDebugOn(au_fbstart(file) < bstart
8218+ || au_fi(file)->fi_hfile[0 + bstart].hf_file);
8219+
8220+ h_file = au_h_open(dentry, bstart, file->f_flags & ~O_TRUNC, file);
8221+ err = PTR_ERR(h_file);
8222+ if (IS_ERR(h_file))
8223+ goto out; /* todo: close all? */
8224+ err = 0;
8225+ /* cpup_file_flags(h_file, file); */
8226+ au_set_fbstart(file, bstart);
8227+ au_set_h_fptr(file, bstart, h_file);
8228+ au_update_figen(file);
8229+ /* todo: necessary? */
8230+ /* file->f_ra = h_file->f_ra; */
8231+
8232+ /* close lower files */
8233+ bend = au_fbend(file);
8234+ for (bindex = bstart + 1; bindex <= bend; bindex++)
8235+ au_set_h_fptr(file, bindex, NULL);
8236+ au_set_fbend(file, bstart);
8237+
8238+ out:
8239+ if (h_file_tmp)
8240+ fput(h_file_tmp);
8241+ AuTraceErr(err);
8242+ return err;
8243+}
8244+
8245+/* ---------------------------------------------------------------------- */
8246+
8247+static int au_ready_to_write_wh(struct file *file, loff_t len,
8248+ aufs_bindex_t bcpup)
8249+{
8250+ int err;
8251+ aufs_bindex_t old_bstart;
8252+ struct inode *inode;
8253+ struct dentry *dentry, *hi_wh, *old_h_dentry;
8254+ struct au_dinfo *dinfo;
8255+ struct super_block *sb;
8256+
8257+ AuTraceEnter();
8258+
8259+ dentry = file->f_dentry;
8260+ inode = dentry->d_inode;
8261+ hi_wh = au_hi_wh(inode, bcpup);
8262+ if (!hi_wh)
8263+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
8264+ else {
8265+ /* already copied-up after unlink */
8266+ dinfo = au_di(dentry);
8267+ old_bstart = dinfo->di_bstart;
8268+ dinfo->di_bstart = bcpup;
8269+ old_h_dentry = dinfo->di_hdentry[0 + bcpup].hd_dentry;
8270+ dinfo->di_hdentry[0 + bcpup].hd_dentry = hi_wh;
8271+ err = au_reopen_nondir(file);
8272+ dinfo->di_hdentry[0 + bcpup].hd_dentry = old_h_dentry;
8273+ dinfo->di_bstart = old_bstart;
8274+ }
8275+
8276+ sb = dentry->d_sb;
8277+ if (!err && inode->i_nlink > 1 && au_opt_test(au_mntflags(sb), PLINK))
8278+ au_plink_append(sb, inode, au_h_dptr(dentry, bcpup), bcpup);
8279+
8280+ AuTraceErr(err);
8281+ return err;
8282+}
8283+
8284+/*
8285+ * prepare the @file for writing.
8286+ */
8287+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
8288+{
8289+ int err;
8290+ unsigned char pin_flags;
8291+ aufs_bindex_t bstart, bcpup;
8292+ struct dentry *dentry, *parent, *h_dentry;
8293+ struct inode *h_inode, *inode;
8294+ struct super_block *sb;
8295+
8296+ dentry = file->f_dentry;
8297+ LKTRTrace("%.*s, len %lld\n", AuDLNPair(dentry), len);
8298+ FiMustWriteLock(file);
8299+
8300+ sb = dentry->d_sb;
8301+ bstart = au_fbstart(file);
8302+ AuDebugOn(au_fbr(file, bstart) != au_sbr(sb, bstart));
8303+
8304+ inode = dentry->d_inode;
8305+ AuDebugOn(S_ISDIR(inode->i_mode));
8306+ LKTRTrace("rdonly %d, bstart %d\n",
8307+ au_test_ro(sb, bstart, inode), bstart);
8308+
8309+ err = au_test_ro(sb, bstart, inode);
8310+ if (!err && (au_h_fptr(file, bstart)->f_mode & FMODE_WRITE)) {
8311+ err = au_pin(pin, dentry, bstart, /*flags*/0);
8312+ goto out;
8313+ }
8314+
8315+ /* need to cpup */
8316+ parent = dget_parent(dentry);
8317+ di_write_lock_parent(parent);
8318+ err = AuWbrCopyup(au_sbi(sb), dentry);
8319+ bcpup = err;
8320+ if (unlikely(err < 0))
8321+ goto out_dgrade;
8322+ err = 0;
8323+
8324+ if (!au_h_dptr(parent, bcpup)) {
8325+ err = au_cpup_dirs(dentry, bcpup);
8326+ if (unlikely(err))
8327+ goto out_dgrade;
8328+ }
8329+
8330+ pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
8331+ if (au_opt_test(au_mntflags(sb), UDBA_INOTIFY))
8332+ au_fset_pin(pin_flags, DO_GPARENT);
8333+ err = au_pin(pin, dentry, bcpup, pin_flags);
8334+ if (unlikely(err))
8335+ goto out_dgrade;
8336+
8337+ AuDebugOn(au_fbstart(file) != bstart);
8338+ h_dentry = au_h_fptr(file, bstart)->f_dentry;
8339+ h_inode = h_dentry->d_inode;
8340+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8341+ if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
8342+ /* || !h_inode->i_nlink */) {
8343+ err = au_ready_to_write_wh(file, len, bcpup);
8344+ di_downgrade_lock(parent, AuLock_IR);
8345+ } else {
8346+ di_downgrade_lock(parent, AuLock_IR);
8347+ if (!au_h_dptr(dentry, bcpup))
8348+ err = au_sio_cpup_simple(dentry, bcpup, len,
8349+ AuCpup_DTIME);
8350+ AuTraceErr(err);
8351+ if (!err)
8352+ err = au_reopen_nondir(file);
8353+ AuTraceErr(err);
8354+ }
8355+ mutex_unlock(&h_inode->i_mutex);
8356+
8357+ if (!err) {
8358+ au_unpin_gp(pin);
8359+ au_pin_set_parent_lflag(pin, /*lflag*/0);
8360+ goto out_dput; /* success */
8361+ }
8362+ au_unpin(pin);
8363+ goto out_unlock;
8364+
8365+ out_dgrade:
8366+ di_downgrade_lock(parent, AuLock_IR);
8367+ out_unlock:
8368+ di_read_unlock(parent, AuLock_IR);
8369+ out_dput:
8370+ dput(parent);
8371+ out:
8372+ AuTraceErr(err);
8373+ return err;
8374+}
8375+
8376+/* ---------------------------------------------------------------------- */
8377+
8378+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
8379+{
8380+ int err;
8381+ unsigned int mnt_flags;
8382+ unsigned char pin_flags;
8383+ aufs_bindex_t bstart, new_bstart, old_bstart;
8384+ struct au_pin pin;
8385+ struct au_finfo *finfo;
8386+ struct dentry *dentry, *parent, *old_h_dentry, *hi_wh;
8387+ struct inode *inode, *dir;
8388+ struct super_block *sb;
8389+ struct au_dinfo *dinfo;
8390+
8391+ dentry = file->f_dentry;
8392+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
8393+ FiMustWriteLock(file);
8394+
8395+ err = 0;
8396+ finfo = au_fi(file);
8397+ inode = dentry->d_inode;
8398+ sb = dentry->d_sb;
8399+ mnt_flags = au_mntflags(sb);
8400+ pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
8401+ if (au_opt_test(mnt_flags, UDBA_INOTIFY))
8402+ au_fset_pin(pin_flags, DO_GPARENT);
8403+ again:
8404+ bstart = au_ibstart(inode);
8405+ if (bstart == finfo->fi_bstart)
8406+ goto out;
8407+
8408+ new_bstart = bstart;
8409+ parent = dget_parent(dentry);
8410+ dir = parent->d_inode;
8411+ if (au_test_ro(sb, bstart, inode)) {
8412+ di_read_lock_parent(parent, !AuLock_IR);
8413+ err = AuWbrCopyup(au_sbi(sb), dentry);
8414+ new_bstart = err;
8415+ di_read_unlock(parent, !AuLock_IR);
8416+ if (unlikely(err < 0))
8417+ goto out_dput;
8418+ err = 0;
8419+ }
8420+ /* someone else might change our inode while we were sleeping */
8421+ /* todo: test more? */
8422+ if (bstart != au_ibstart(inode)) {
8423+ err = 0;
8424+ dput(parent);
8425+ goto again;
8426+ }
8427+ di_read_lock_parent(parent, AuLock_IR);
8428+ bstart = new_bstart;
8429+
8430+ hi_wh = au_hi_wh(inode, bstart);
8431+ if (au_opt_test(mnt_flags, PLINK)
8432+ && au_plink_test(sb, inode)
8433+ && !d_unhashed(dentry)) {
8434+ err = au_test_and_cpup_dirs(dentry, bstart);
8435+ if (unlikely(err))
8436+ goto out_unlock;
8437+
8438+ /* always superio. */
8439+#if 1
8440+ err = au_pin(&pin, dentry, bstart, pin_flags);
8441+ if (!err)
8442+ err = au_sio_cpup_simple(dentry, bstart, -1,
8443+ AuCpup_DTIME);
8444+ au_unpin(&pin);
8445+#else /* reserved for future use */
8446+ if (!au_test_wkq(current)) {
8447+ int wkq_err;
8448+ struct cpup_pseudo_link_args args = {
8449+ .errp = &err,
8450+ .dentry = dentry,
8451+ .bdst = bstart,
8452+ .do_lock = 1
8453+ };
8454+ wkq_err = au_wkq_wait(call_cpup_pseudo_link, &args);
8455+ if (unlikely(wkq_err))
8456+ err = wkq_err;
8457+ } else
8458+ err = cpup_pseudo_link(dentry, bstart, /*do_lock*/1);
8459+#endif
8460+ } else if (hi_wh) {
8461+ /* already copied-up after unlink */
8462+ dinfo = au_di(dentry);
8463+ old_bstart = dinfo->di_bstart;
8464+ dinfo->di_bstart = bstart;
8465+ old_h_dentry = dinfo->di_hdentry[0 + bstart].hd_dentry;
8466+ dinfo->di_hdentry[0 + bstart].hd_dentry = hi_wh;
8467+ err = au_reopen_nondir(file);
8468+ dinfo->di_hdentry[0 + bstart].hd_dentry = old_h_dentry;
8469+ dinfo->di_bstart = old_bstart;
8470+ *need_reopen = 0;
8471+ }
8472+
8473+ out_unlock:
8474+ di_read_unlock(parent, AuLock_IR);
8475+ out_dput:
8476+ dput(parent);
8477+ out:
8478+ AuTraceErr(err);
8479+ return err;
8480+}
8481+
8482+/*
8483+ * after branch manipulating, refresh the file.
8484+ */
8485+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
8486+{
8487+ int err, new_sz, need_reopen;
8488+ struct dentry *dentry;
8489+ aufs_bindex_t bend, bindex, brid;
8490+ struct au_hfile *p;
8491+ struct au_finfo *finfo;
8492+ struct super_block *sb;
8493+ struct inode *inode;
8494+
8495+ dentry = file->f_dentry;
8496+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
8497+ FiMustWriteLock(file);
8498+ DiMustAnyLock(dentry);
8499+ inode = dentry->d_inode;
8500+ IiMustAnyLock(inode);
8501+
8502+ err = -ENOMEM;
8503+ sb = dentry->d_sb;
8504+ finfo = au_fi(file);
8505+ new_sz = sizeof(*finfo->fi_hfile) * (au_sbend(sb) + 1);
8506+ p = au_kzrealloc(finfo->fi_hfile, sizeof(*p) * (finfo->fi_bend + 1),
8507+ new_sz, GFP_NOFS);
8508+ if (unlikely(!p))
8509+ goto out;
8510+ finfo->fi_hfile = p;
8511+
8512+ p += finfo->fi_bstart;
8513+ brid = p->hf_br->br_id;
8514+ bend = finfo->fi_bend;
8515+ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) {
8516+ struct au_hfile tmp, *q;
8517+ aufs_bindex_t new_bindex;
8518+
8519+ if (!p->hf_file)
8520+ continue;
8521+ new_bindex = au_find_bindex(sb, p->hf_br);
8522+ if (new_bindex == bindex)
8523+ continue;
8524+ /* todo: test more? */
8525+ if (new_bindex < 0) {
8526+ au_set_h_fptr(file, bindex, NULL);
8527+ continue;
8528+ }
8529+
8530+ /* swap two hidden inode, and loop again */
8531+ q = finfo->fi_hfile + new_bindex;
8532+ tmp = *q;
8533+ *q = *p;
8534+ *p = tmp;
8535+ if (tmp.hf_file) {
8536+ bindex--;
8537+ p--;
8538+ }
8539+ }
8540+ {
8541+ aufs_bindex_t s = finfo->fi_bstart, e = finfo->fi_bend;
8542+ finfo->fi_bstart = 0;
8543+ finfo->fi_bend = au_sbend(sb);
8544+ finfo->fi_bstart = s;
8545+ finfo->fi_bend = e;
8546+ }
8547+
8548+ p = finfo->fi_hfile;
8549+ if (!au_test_mmapped(file) && !d_unhashed(dentry)) {
8550+ bend = au_sbend(sb);
8551+ for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
8552+ finfo->fi_bstart++, p++)
8553+ if (p->hf_file) {
8554+ if (p->hf_file->f_dentry
8555+ && p->hf_file->f_dentry->d_inode)
8556+ break;
8557+ else
8558+ au_hfput(p);
8559+ }
8560+ } else {
8561+ bend = au_br_index(sb, brid);
8562+ for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
8563+ finfo->fi_bstart++, p++)
8564+ if (p->hf_file)
8565+ au_hfput(p);
8566+ bend = au_sbend(sb);
8567+ }
8568+
8569+ p = finfo->fi_hfile + bend;
8570+ for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
8571+ finfo->fi_bend--, p--)
8572+ if (p->hf_file) {
8573+ if (p->hf_file->f_dentry
8574+ && p->hf_file->f_dentry->d_inode)
8575+ break;
8576+ else
8577+ au_hfput(p);
8578+ }
8579+ AuDebugOn(finfo->fi_bend < finfo->fi_bstart);
8580+
8581+ err = 0;
8582+ need_reopen = 1;
8583+ if (!au_test_mmapped(file))
8584+ err = au_file_refresh_by_inode(file, &need_reopen);
8585+ if (!err && need_reopen && !d_unhashed(dentry))
8586+ err = reopen(file);
8587+ if (!err) {
8588+ au_update_figen(file);
8589+ return 0; /* success */
8590+ }
8591+
8592+ /* error, close all hidden files */
8593+ bend = au_fbend(file);
8594+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
8595+ au_set_h_fptr(file, bindex, NULL);
8596+
8597+ out:
8598+ AuTraceErr(err);
8599+ return err;
8600+}
8601+
8602+/* common function to regular file and dir */
8603+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8604+ int wlock, int locked)
8605+{
8606+ int err;
8607+ struct dentry *dentry;
8608+ struct super_block *sb;
8609+ aufs_bindex_t bstart;
8610+ unsigned char pseudo_link;
8611+ au_gen_t sgen, fgen;
8612+
8613+ dentry = file->f_dentry;
8614+ LKTRTrace("%.*s, w %d, l %d\n", AuDLNPair(dentry), wlock, locked);
8615+ sb = dentry->d_sb;
8616+ SiMustAnyLock(sb);
8617+
8618+ err = 0;
8619+ sgen = au_sigen(sb);
8620+ fi_write_lock(file);
8621+ fgen = au_figen(file);
8622+ di_write_lock_child(dentry);
8623+ bstart = au_dbstart(dentry);
8624+ pseudo_link = (bstart != au_ibstart(dentry->d_inode));
8625+ if (sgen == fgen && !pseudo_link && au_fbstart(file) == bstart) {
8626+ if (!wlock) {
8627+ di_downgrade_lock(dentry, AuLock_IR);
8628+ fi_downgrade_lock(file);
8629+ }
8630+ goto out; /* success */
8631+ }
8632+
8633+ LKTRTrace("sgen %d, fgen %d\n", sgen, fgen);
8634+ if (sgen != au_digen(dentry)
8635+ || sgen != au_iigen(dentry->d_inode)) {
8636+ /*
8637+ * d_path() and path_lookup() is a simple and good approach
8638+ * to revalidate. but si_rwsem in DEBUG_RWSEM will cause a
8639+ * deadlock. removed the code.
8640+ */
8641+ err = au_reval_dpath(dentry, sgen);
8642+ if (unlikely(err < 0))
8643+ goto out;
8644+ AuDebugOn(au_digen(dentry) != sgen
8645+ || au_iigen(dentry->d_inode) != sgen);
8646+ }
8647+
8648+ err = refresh_file(file, reopen
8649+ /* , au_opt_test(au_mnt_flags(sb), REFROF) */);
8650+ if (!err) {
8651+ if (!wlock) {
8652+ di_downgrade_lock(dentry, AuLock_IR);
8653+ fi_downgrade_lock(file);
8654+ }
8655+ } else {
8656+ di_write_unlock(dentry);
8657+ fi_write_unlock(file);
8658+ }
8659+
8660+ out:
8661+ AuTraceErr(err);
8662+ return err;
8663+}
8664+
8665+/* ---------------------------------------------------------------------- */
8666+
8667+/* cf. aufs_nopage() */
8668+/* for madvise(2) */
8669+static int aufs_readpage(struct file *file, struct page *page)
8670+{
8671+ AuTraceEnter();
8672+ unlock_page(page);
8673+ return 0;
8674+}
8675+
8676+/* they will never be called. */
8677+#ifdef CONFIG_AUFS_DEBUG
8678+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
8679+static int aufs_prepare_write(struct file *file, struct page *page,
8680+ unsigned from, unsigned to)
8681+{ AuUnsupport(); return 0; }
8682+static int aufs_commit_write(struct file *file, struct page *page,
8683+ unsigned from, unsigned to)
8684+{ AuUnsupport(); return 0; }
8685+#endif
8686+static int aufs_write_begin(struct file *file, struct address_space *mapping,
8687+ loff_t pos, unsigned len, unsigned flags,
8688+ struct page **pagep, void **fsdata)
8689+{ AuUnsupport(); return 0; }
8690+static int aufs_write_end(struct file *file, struct address_space *mapping,
8691+ loff_t pos, unsigned len, unsigned copied,
8692+ struct page *page, void *fsdata)
8693+{ AuUnsupport(); return 0; }
8694+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
8695+{ AuUnsupport(); return 0; }
8696+static void aufs_sync_page(struct page *page)
8697+{ AuUnsupport(); }
8698+
8699+static int aufs_set_page_dirty(struct page *page)
8700+{ AuUnsupport(); return 0; }
8701+static void aufs_invalidatepage(struct page *page, unsigned long offset)
8702+{ AuUnsupport(); }
8703+static int aufs_releasepage(struct page *page, gfp_t gfp)
8704+{ AuUnsupport(); return 0; }
8705+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
8706+ const struct iovec *iov, loff_t offset,
8707+ unsigned long nr_segs)
8708+{ AuUnsupport(); return 0; }
8709+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
8710+static struct page *aufs_get_xip_page(struct address_space *mapping,
8711+ sector_t offset, int create)
8712+{ AuUnsupport(); return NULL; }
8713+#endif
8714+#endif /* CONFIG_AUFS_DEBUG */
8715+
8716+struct address_space_operations aufs_aop = {
8717+ .readpage = aufs_readpage,
8718+#ifdef CONFIG_AUFS_DEBUG
8719+ .writepage = aufs_writepage,
8720+ .sync_page = aufs_sync_page,
8721+ .set_page_dirty = aufs_set_page_dirty,
8722+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
8723+ .prepare_write = aufs_prepare_write,
8724+ .commit_write = aufs_commit_write,
8725+#endif
8726+ .write_begin = aufs_write_begin,
8727+ .write_end = aufs_write_end,
8728+ .invalidatepage = aufs_invalidatepage,
8729+ .releasepage = aufs_releasepage,
8730+ .direct_IO = aufs_direct_IO,
8731+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
8732+ .get_xip_page = aufs_get_xip_page,
8733+#endif
8734+#endif /* CONFIG_AUFS_DEBUG */
8735+};
8736diff -urN linux/fs/aufs/file.h linux-aufs/fs/aufs/file.h
8737--- linux/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
8738+++ linux-aufs/fs/aufs/file.h 2009-03-12 16:18:04.000000000 +0100
8739@@ -0,0 +1,257 @@
8740+/*
8741+ * Copyright (C) 2005-2009 Junjiro Okajima
8742+ *
8743+ * This program, aufs is free software; you can redistribute it and/or modify
8744+ * it under the terms of the GNU General Public License as published by
8745+ * the Free Software Foundation; either version 2 of the License, or
8746+ * (at your option) any later version.
8747+ *
8748+ * This program is distributed in the hope that it will be useful,
8749+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8750+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8751+ * GNU General Public License for more details.
8752+ *
8753+ * You should have received a copy of the GNU General Public License
8754+ * along with this program; if not, write to the Free Software
8755+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8756+ */
8757+
8758+/*
8759+ * file operations
8760+ *
8761+ * $Id$
8762+ */
8763+
8764+#ifndef __AUFS_FILE_H__
8765+#define __AUFS_FILE_H__
8766+
8767+#ifdef __KERNEL__
8768+
8769+#include <linux/file.h>
8770+#include <linux/fs.h>
8771+#include <linux/mm.h>
8772+#include <linux/aufs_type.h>
8773+#include "dentry.h"
8774+#include "misc.h"
8775+#include "super.h"
8776+
8777+/* ---------------------------------------------------------------------- */
8778+
8779+struct au_branch;
8780+struct au_hfile {
8781+ struct file *hf_file;
8782+ struct au_branch *hf_br;
8783+};
8784+
8785+struct au_vdir;
8786+struct au_finfo {
8787+ atomic_t fi_generation;
8788+
8789+ struct au_rwsem fi_rwsem;
8790+ struct au_hfile *fi_hfile;
8791+ aufs_bindex_t fi_bstart, fi_bend;
8792+
8793+ union {
8794+ struct vm_operations_struct *fi_h_vm_ops;
8795+ struct au_vdir *fi_vdir_cache;
8796+ };
8797+};
8798+
8799+/* ---------------------------------------------------------------------- */
8800+
8801+/* file.c */
8802+extern struct address_space_operations aufs_aop;
8803+unsigned int au_file_roflags(unsigned int flags);
8804+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8805+ struct file *file);
8806+int au_do_open(struct inode *inode, struct file *file,
8807+ int (*open)(struct file *file, int flags));
8808+int au_reopen_nondir(struct file *file);
8809+struct au_pin;
8810+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
8811+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8812+ int wlock, int locked);
8813+
8814+/* f_op.c */
8815+extern struct file_operations aufs_file_fop;
8816+int aufs_flush(struct file *file, fl_owner_t id);
8817+
8818+/* finfo.c */
8819+struct au_finfo *au_fi(struct file *file);
8820+struct au_branch *au_fbr(struct file *file, aufs_bindex_t bindex);
8821+struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex);
8822+
8823+void au_hfput(struct au_hfile *hf);
8824+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
8825+ struct file *h_file);
8826+
8827+void au_finfo_fin(struct file *file);
8828+int au_finfo_init(struct file *file);
8829+
8830+#ifdef CONFIG_AUFS_ROBR
8831+/* robr.c */
8832+struct file *au_robr_safe_file(struct vm_area_struct *vma);
8833+void au_robr_reset_file(struct vm_area_struct *vma, struct file *file);
8834+#else
8835+static inline struct file *au_robr_safe_file(struct vm_area_struct *vma)
8836+{
8837+ struct file *file;
8838+
8839+ file = vma->vm_file;
8840+ if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
8841+ return file;
8842+ return NULL;
8843+}
8844+
8845+static inline
8846+void au_robr_reset_file(struct vm_area_struct *vma, struct file *file)
8847+{
8848+ vma->vm_file = file;
8849+ /* smp_mb(); */ /* flush vm_file */
8850+}
8851+#endif /* CONFIG_AUFS_ROBR */
8852+
8853+#if 0 /* reserved for future use */
8854+/* ioctl.c */
8855+long aufs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
8856+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
8857+#endif
8858+
8859+/* ---------------------------------------------------------------------- */
8860+
8861+/* todo: memory barrier? */
8862+static inline au_gen_t au_figen(struct file *f)
8863+{
8864+ return atomic_read(&au_fi(f)->fi_generation);
8865+}
8866+
8867+static inline int au_test_mmapped(struct file *f)
8868+{
8869+ return !!(au_fi(f)->fi_h_vm_ops);
8870+}
8871+
8872+static inline int au_test_aufs_file(struct file *f)
8873+{
8874+ return !(f->f_dentry->d_inode->i_mode
8875+ & (S_IFCHR | S_IFBLK | S_IFIFO | S_IFSOCK));
8876+}
8877+
8878+/* ---------------------------------------------------------------------- */
8879+
8880+#if !defined(CONFIG_AUFS_MODULE) || defined(CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH)
8881+int au_store_fmode_exec(struct nameidata *nd, struct inode *inode);
8882+
8883+static inline int au_deny_write_access(struct file *h_file)
8884+{
8885+ LKTRTrace("%.*s\n", AuDLNPair(h_file->f_dentry));
8886+ return deny_write_access(h_file);
8887+}
8888+
8889+static inline void au_allow_write_access(struct file *h_file)
8890+{
8891+ allow_write_access(h_file);
8892+}
8893+
8894+#else
8895+
8896+static inline int au_store_fmode_exec(struct nameidata *nd, struct inode *inode)
8897+{
8898+ /* nothing */
8899+ return 0;
8900+}
8901+
8902+static inline int au_deny_write_access(struct file *h_file)
8903+{
8904+ /* nothing */
8905+ return 0;
8906+}
8907+
8908+static inline void au_allow_write_access(struct file *h_file)
8909+{
8910+ /* nothing */
8911+}
8912+#endif /* CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH */
8913+
8914+/* ---------------------------------------------------------------------- */
8915+
8916+/*
8917+ * fi_read_lock, fi_write_lock,
8918+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
8919+ */
8920+AuSimpleRwsemFuncs(fi, struct file *f, au_fi(f)->fi_rwsem);
8921+
8922+/* to debug easier, do not make them inlined functions */
8923+#define FiMustReadLock(f) do { \
8924+ SiMustAnyLock((f)->f_dentry->d_sb); \
8925+ AuRwMustReadLock(&au_fi(f)->fi_rwsem); \
8926+} while (0)
8927+
8928+#define FiMustWriteLock(f) do { \
8929+ SiMustAnyLock((f)->f_dentry->d_sb); \
8930+ AuRwMustWriteLock(&au_fi(f)->fi_rwsem); \
8931+} while (0)
8932+
8933+#define FiMustAnyLock(f) do { \
8934+ SiMustAnyLock((f)->f_dentry->d_sb); \
8935+ AuRwMustAnyLock(&au_fi(f)->fi_rwsem); \
8936+} while (0)
8937+
8938+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
8939+
8940+/* ---------------------------------------------------------------------- */
8941+
8942+/* todo: hard/soft set? */
8943+static inline aufs_bindex_t au_fbstart(struct file *file)
8944+{
8945+ FiMustAnyLock(file);
8946+ return au_fi(file)->fi_bstart;
8947+}
8948+
8949+static inline aufs_bindex_t au_fbend(struct file *file)
8950+{
8951+ FiMustAnyLock(file);
8952+ return au_fi(file)->fi_bend;
8953+}
8954+
8955+static inline struct au_vdir *au_fvdir_cache(struct file *file)
8956+{
8957+#ifdef CONFIG_AUFS_EXPORT
8958+ AuRwMustAnyLock(&au_fi(file)->fi_rwsem);
8959+#else
8960+ FiMustAnyLock(file);
8961+#endif
8962+ return au_fi(file)->fi_vdir_cache;
8963+}
8964+
8965+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
8966+{
8967+ FiMustWriteLock(file);
8968+ AuDebugOn(au_sbend(file->f_dentry->d_sb) < bindex);
8969+ au_fi(file)->fi_bstart = bindex;
8970+}
8971+
8972+static inline void au_set_fbend(struct file *file, aufs_bindex_t bindex)
8973+{
8974+ FiMustWriteLock(file);
8975+ AuDebugOn(au_sbend(file->f_dentry->d_sb) < bindex
8976+ || bindex < au_fbstart(file));
8977+ au_fi(file)->fi_bend = bindex;
8978+}
8979+
8980+static inline void au_set_fvdir_cache(struct file *file,
8981+ struct au_vdir *vdir_cache)
8982+{
8983+ FiMustWriteLock(file);
8984+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode)
8985+ || (au_fi(file)->fi_vdir_cache && vdir_cache));
8986+ au_fi(file)->fi_vdir_cache = vdir_cache;
8987+}
8988+
8989+static inline void au_update_figen(struct file *file)
8990+{
8991+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
8992+ /* smp_mb(); */ /* atomic_set */
8993+}
8994+
8995+#endif /* __KERNEL__ */
8996+#endif /* __AUFS_FILE_H__ */
8997diff -urN linux/fs/aufs/finfo.c linux-aufs/fs/aufs/finfo.c
8998--- linux/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
8999+++ linux-aufs/fs/aufs/finfo.c 2009-03-12 16:18:04.000000000 +0100
9000@@ -0,0 +1,186 @@
9001+/*
9002+ * Copyright (C) 2005-2009 Junjiro Okajima
9003+ *
9004+ * This program, aufs is free software; you can redistribute it and/or modify
9005+ * it under the terms of the GNU General Public License as published by
9006+ * the Free Software Foundation; either version 2 of the License, or
9007+ * (at your option) any later version.
9008+ *
9009+ * This program is distributed in the hope that it will be useful,
9010+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9011+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9012+ * GNU General Public License for more details.
9013+ *
9014+ * You should have received a copy of the GNU General Public License
9015+ * along with this program; if not, write to the Free Software
9016+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9017+ */
9018+
9019+/*
9020+ * file private data
9021+ *
9022+ * $Id$
9023+ */
9024+
9025+#include "aufs.h"
9026+
9027+struct au_finfo *au_fi(struct file *file)
9028+{
9029+ struct au_finfo *finfo = file->private_data;
9030+ AuDebugOn(!finfo
9031+ || !finfo->fi_hfile
9032+ || (0 < finfo->fi_bend
9033+ && (/* au_sbi(file->f_dentry->d_sb)->si_bend
9034+ < finfo->fi_bend
9035+ || */ finfo->fi_bend < finfo->fi_bstart)));
9036+ return finfo;
9037+}
9038+
9039+struct au_branch *au_fbr(struct file *file, aufs_bindex_t bindex)
9040+{
9041+ struct au_finfo *finfo = au_fi(file);
9042+ struct au_hfile *hf;
9043+
9044+ FiMustAnyLock(file);
9045+ AuDebugOn(!finfo
9046+ || finfo->fi_bstart < 0
9047+ || bindex < finfo->fi_bstart
9048+ || finfo->fi_bend < bindex);
9049+ hf = finfo->fi_hfile + bindex;
9050+ AuDebugOn(hf->hf_br && au_br_count(hf->hf_br) <= 0);
9051+ return hf->hf_br;
9052+}
9053+
9054+struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex)
9055+{
9056+ struct au_finfo *finfo = au_fi(file);
9057+ struct au_hfile *hf;
9058+
9059+ FiMustAnyLock(file);
9060+ AuDebugOn(!finfo
9061+ || finfo->fi_bstart < 0
9062+ || bindex < finfo->fi_bstart
9063+ || finfo->fi_bend < bindex);
9064+ hf = finfo->fi_hfile + bindex;
9065+ AuDebugOn(hf->hf_file
9066+ && file_count(hf->hf_file) <= 0
9067+ && au_br_count(hf->hf_br) <= 0);
9068+ return hf->hf_file;
9069+}
9070+
9071+void au_hfput(struct au_hfile *hf)
9072+{
9073+ if (hf->hf_file->f_mode & FMODE_EXEC)
9074+ au_allow_write_access(hf->hf_file);
9075+ fput(hf->hf_file);
9076+ hf->hf_file = NULL;
9077+ AuDebugOn(!hf->hf_br);
9078+ au_br_put(hf->hf_br);
9079+ hf->hf_br = NULL;
9080+}
9081+
9082+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
9083+{
9084+ struct au_finfo *finfo = au_fi(file);
9085+ struct au_hfile *hf;
9086+
9087+ FiMustWriteLock(file);
9088+ AuDebugOn(!finfo
9089+ || finfo->fi_bstart < 0
9090+ || bindex < finfo->fi_bstart
9091+ || finfo->fi_bend < bindex);
9092+ AuDebugOn(val && file_count(val) <= 0);
9093+ hf = finfo->fi_hfile + bindex;
9094+ AuDebugOn(val && hf->hf_file);
9095+ if (hf->hf_file)
9096+ au_hfput(hf);
9097+ if (val) {
9098+ hf->hf_file = val;
9099+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
9100+ }
9101+}
9102+
9103+void au_finfo_fin(struct file *file)
9104+{
9105+ struct au_finfo *finfo;
9106+ struct dentry *dentry;
9107+ aufs_bindex_t bindex, bend;
9108+
9109+ dentry = file->f_dentry;
9110+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
9111+ SiMustAnyLock(dentry->d_sb);
9112+
9113+ fi_write_lock(file);
9114+ bend = au_fbend(file);
9115+ bindex = au_fbstart(file);
9116+ if (bindex >= 0)
9117+ for (; bindex <= bend; bindex++)
9118+ au_set_h_fptr(file, bindex, NULL);
9119+
9120+ finfo = au_fi(file);
9121+#ifdef CONFIG_AUFS_DEBUG
9122+ if (finfo->fi_bstart >= 0) {
9123+ bend = au_fbend(file);
9124+ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
9125+ struct au_hfile *hf;
9126+ hf = finfo->fi_hfile + bindex;
9127+ AuDebugOn(hf->hf_file || hf->hf_br);
9128+ }
9129+ }
9130+#endif
9131+
9132+ kfree(finfo->fi_hfile);
9133+ fi_write_unlock(file);
9134+ au_rwsem_destroy(&finfo->fi_rwsem);
9135+ au_cache_free_finfo(finfo);
9136+}
9137+
9138+int au_finfo_init(struct file *file)
9139+{
9140+ struct au_finfo *finfo;
9141+ struct dentry *dentry;
9142+ union {
9143+ void *p;
9144+ unsigned long ul;
9145+ } u;
9146+
9147+ dentry = file->f_dentry;
9148+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
9149+ AuDebugOn(!dentry->d_inode);
9150+
9151+ finfo = au_cache_alloc_finfo();
9152+ if (finfo) {
9153+ finfo->fi_hfile = kcalloc(au_sbend(dentry->d_sb) + 1,
9154+ sizeof(*finfo->fi_hfile), GFP_NOFS);
9155+ if (finfo->fi_hfile) {
9156+ au_rw_init_wlock(&finfo->fi_rwsem);
9157+ //au_dbg_lock_fi_reg(file);
9158+ finfo->fi_bstart = -1;
9159+ finfo->fi_bend = -1;
9160+ atomic_set(&finfo->fi_generation, au_digen(dentry));
9161+ /* smp_mb(); */ /* atomic_set */
9162+
9163+ /*
9164+ * a dirty trick for handling FMODE_EXEC and
9165+ * deny_write_access().
9166+ * because FMODE_EXEC flag is not passed to
9167+ * f_op->open(),
9168+ * aufs set it to file->private_data temporary in lookup
9169+ * or dentry revalidation operations.
9170+ * restore the flag to f_mode here.
9171+ */
9172+ u.p = file->private_data;
9173+ if (u.ul & FMODE_EXEC) {
9174+ file->f_mode |= FMODE_EXEC;
9175+ smp_mb(); /* flush f_mode */
9176+ }
9177+
9178+ file->private_data = finfo;
9179+ return 0; /* success */
9180+ }
9181+ au_cache_free_finfo(finfo);
9182+ }
9183+
9184+ AuTraceErr(-ENOMEM);
9185+ return -ENOMEM;
9186+}
9187diff -urN linux/fs/aufs/f_op.c linux-aufs/fs/aufs/f_op.c
9188--- linux/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
9189+++ linux-aufs/fs/aufs/f_op.c 2009-03-12 16:18:04.000000000 +0100
9190@@ -0,0 +1,673 @@
9191+/*
9192+ * Copyright (C) 2005-2009 Junjiro Okajima
9193+ *
9194+ * This program, aufs is free software; you can redistribute it and/or modify
9195+ * it under the terms of the GNU General Public License as published by
9196+ * the Free Software Foundation; either version 2 of the License, or
9197+ * (at your option) any later version.
9198+ *
9199+ * This program is distributed in the hope that it will be useful,
9200+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9201+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9202+ * GNU General Public License for more details.
9203+ *
9204+ * You should have received a copy of the GNU General Public License
9205+ * along with this program; if not, write to the Free Software
9206+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9207+ */
9208+
9209+/*
9210+ * file and vm operations
9211+ *
9212+ * $Id$
9213+ */
9214+
9215+#include <linux/fs_stack.h>
9216+#include <linux/poll.h>
9217+#include "aufs.h"
9218+
9219+/* common function to regular file and dir */
9220+int aufs_flush(struct file *file, fl_owner_t id)
9221+{
9222+ int err;
9223+ struct dentry *dentry;
9224+ aufs_bindex_t bindex, bend;
9225+ struct file *h_file;
9226+
9227+ dentry = file->f_dentry;
9228+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
9229+
9230+ si_noflush_read_lock(dentry->d_sb);
9231+ fi_read_lock(file);
9232+ di_read_lock_child(dentry, AuLock_IW);
9233+
9234+ err = 0;
9235+ bend = au_fbend(file);
9236+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
9237+ h_file = au_h_fptr(file, bindex);
9238+ if (h_file && h_file->f_op && h_file->f_op->flush) {
9239+ err = h_file->f_op->flush(h_file, id);
9240+ if (!err)
9241+ au_update_fuse_h_inode
9242+ (h_file->f_vfsmnt, h_file->f_dentry);
9243+ /*ignore*/
9244+ }
9245+ }
9246+ au_cpup_attr_timesizes(dentry->d_inode);
9247+
9248+ di_read_unlock(dentry, AuLock_IW);
9249+ fi_read_unlock(file);
9250+ si_read_unlock(dentry->d_sb);
9251+ AuTraceErr(err);
9252+ return err;
9253+}
9254+
9255+/* ---------------------------------------------------------------------- */
9256+
9257+static int do_open_nondir(struct file *file, int flags)
9258+{
9259+ int err;
9260+ aufs_bindex_t bindex;
9261+ struct super_block *sb;
9262+ struct file *h_file;
9263+ struct dentry *dentry;
9264+ struct inode *inode;
9265+ struct au_finfo *finfo;
9266+
9267+ dentry = file->f_dentry;
9268+ LKTRTrace("%.*s, flags 0%o\n", AuDLNPair(dentry), flags);
9269+ FiMustWriteLock(file);
9270+ inode = dentry->d_inode;
9271+ AuDebugOn(!inode || S_ISDIR(inode->i_mode));
9272+
9273+ err = 0;
9274+ finfo = au_fi(file);
9275+ finfo->fi_h_vm_ops = NULL;
9276+ sb = dentry->d_sb;
9277+ bindex = au_dbstart(dentry);
9278+ AuDebugOn(!au_h_dptr(dentry, bindex)->d_inode);
9279+ /* O_TRUNC is processed already */
9280+ BUG_ON(au_test_ro(sb, bindex, inode) && (flags & O_TRUNC));
9281+
9282+ h_file = au_h_open(dentry, bindex, flags, file);
9283+ if (IS_ERR(h_file))
9284+ err = PTR_ERR(h_file);
9285+ else {
9286+ au_set_fbstart(file, bindex);
9287+ au_set_fbend(file, bindex);
9288+ au_set_h_fptr(file, bindex, h_file);
9289+ au_update_figen(file);
9290+ /* todo: necessary? */
9291+ /* file->f_ra = h_file->f_ra; */
9292+ err = 0;
9293+ }
9294+ AuTraceErr(err);
9295+ return err;
9296+}
9297+
9298+static int aufs_open_nondir(struct inode *inode, struct file *file)
9299+{
9300+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry));
9301+
9302+ return au_do_open(inode, file, do_open_nondir);
9303+}
9304+
9305+static int aufs_release_nondir(struct inode *inode, struct file *file)
9306+{
9307+ struct super_block *sb = file->f_dentry->d_sb;
9308+
9309+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry));
9310+
9311+ si_noflush_read_lock(sb);
9312+ au_finfo_fin(file);
9313+ si_read_unlock(sb);
9314+ return 0;
9315+}
9316+
9317+/* ---------------------------------------------------------------------- */
9318+
9319+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
9320+ loff_t *ppos)
9321+{
9322+ ssize_t err;
9323+ struct dentry *dentry;
9324+ struct file *h_file;
9325+ struct super_block *sb;
9326+ struct inode *h_inode;
9327+
9328+ dentry = file->f_dentry;
9329+ LKTRTrace("%.*s, cnt %zu, pos %lld\n", AuDLNPair(dentry), count, *ppos);
9330+
9331+ sb = dentry->d_sb;
9332+ si_read_lock(sb, AuLock_FLUSH);
9333+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0,
9334+ /*locked*/0);
9335+ if (unlikely(err))
9336+ goto out;
9337+
9338+ /* support LSM and notify */
9339+ h_file = au_h_fptr(file, au_fbstart(file));
9340+ h_inode = h_file->f_dentry->d_inode;
9341+ err = vfsub_read_u(h_file, buf, count, ppos,
9342+ au_test_dlgt(au_mntflags(sb)));
9343+ /* todo: necessary? */
9344+ /* file->f_ra = h_file->f_ra; */
9345+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9346+
9347+ di_read_unlock(dentry, AuLock_IR);
9348+ fi_read_unlock(file);
9349+ out:
9350+ si_read_unlock(sb);
9351+ AuTraceErr(err);
9352+ return err;
9353+}
9354+
9355+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
9356+ size_t count, loff_t *ppos)
9357+{
9358+ ssize_t err;
9359+ struct dentry *dentry;
9360+ struct inode *inode;
9361+ struct super_block *sb;
9362+ unsigned int mnt_flags;
9363+ struct file *h_file;
9364+ char __user *buf = (char __user *)ubuf;
9365+ struct au_hin_ignore ign;
9366+ struct vfsub_args vargs;
9367+ aufs_bindex_t bstart;
9368+ int hinotify;
9369+ struct au_pin pin;
9370+
9371+ dentry = file->f_dentry;
9372+ LKTRTrace("%.*s, cnt %zu, pos %lld\n", AuDLNPair(dentry), count, *ppos);
9373+
9374+ inode = dentry->d_inode;
9375+ mutex_lock(&inode->i_mutex);
9376+ sb = dentry->d_sb;
9377+ si_read_lock(sb, AuLock_FLUSH);
9378+ mnt_flags = au_mntflags(sb);
9379+ hinotify = !!au_opt_test(mnt_flags, UDBA_INOTIFY);
9380+ vfsub_args_init(&vargs, &ign, au_test_dlgt(mnt_flags), 0);
9381+
9382+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
9383+ /*locked*/1);
9384+ if (unlikely(err))
9385+ goto out;
9386+ err = au_ready_to_write(file, -1, &pin);
9387+ di_downgrade_lock(dentry, AuLock_IR);
9388+ if (unlikely(err))
9389+ goto out_unlock;
9390+
9391+ bstart = au_fbstart(file);
9392+ h_file = au_h_fptr(file, bstart);
9393+ if (!hinotify) {
9394+ au_unpin(&pin);
9395+ err = vfsub_write_u(h_file, buf, count, ppos, &vargs);
9396+ } else {
9397+ vfsub_ign_hinode(&vargs, IN_MODIFY, au_pinned_hdir(&pin));
9398+ err = vfsub_write_u(h_file, buf, count, ppos, &vargs);
9399+ au_unpin(&pin);
9400+ }
9401+ au_cpup_attr_timesizes(inode);
9402+
9403+ out_unlock:
9404+ di_read_unlock(dentry, AuLock_IR);
9405+ fi_write_unlock(file);
9406+ out:
9407+ si_read_unlock(sb);
9408+ mutex_unlock(&inode->i_mutex);
9409+ AuTraceErr(err);
9410+ return err;
9411+}
9412+
9413+#ifdef CONFIG_AUFS_SPLICE_PATCH
9414+static int au_test_loopback(void)
9415+{
9416+ const char c = current->comm[4];
9417+ /* true if a kernel thread named 'loop[0-9].*' accesses a file */
9418+ const int loopback = (current->mm == NULL
9419+ && '0' <= c && c <= '9'
9420+ && strncmp(current->comm, "loop", 4) == 0);
9421+ return loopback;
9422+}
9423+
9424+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
9425+ struct pipe_inode_info *pipe, size_t len,
9426+ unsigned int flags)
9427+{
9428+ ssize_t err;
9429+ struct file *h_file;
9430+ struct dentry *dentry;
9431+ struct super_block *sb;
9432+
9433+ dentry = file->f_dentry;
9434+ LKTRTrace("%.*s, pos %lld, len %zu\n", AuDLNPair(dentry), *ppos, len);
9435+
9436+ sb = dentry->d_sb;
9437+ si_read_lock(sb, AuLock_FLUSH);
9438+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0,
9439+ /*locked*/0);
9440+ if (unlikely(err))
9441+ goto out;
9442+
9443+ err = -EINVAL;
9444+ /* support LSM and notify */
9445+ h_file = au_h_fptr(file, au_fbstart(file));
9446+ if (au_test_loopback()) {
9447+ file->f_mapping = h_file->f_mapping;
9448+ smp_mb(); /* unnecessary? */
9449+ }
9450+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags,
9451+ au_test_dlgt(au_mntflags(sb)));
9452+ /* todo: necessasry? */
9453+ /* file->f_ra = h_file->f_ra; */
9454+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9455+ di_read_unlock(dentry, AuLock_IR);
9456+ fi_read_unlock(file);
9457+
9458+ out:
9459+ si_read_unlock(sb);
9460+ AuTraceErr(err);
9461+ return err;
9462+}
9463+
9464+static ssize_t
9465+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
9466+ size_t len, unsigned int flags)
9467+{
9468+ ssize_t err;
9469+ struct dentry *dentry;
9470+ struct inode *inode, *h_inode;
9471+ struct super_block *sb;
9472+ struct file *h_file;
9473+ /* struct au_hin_ignore ign; */
9474+ struct vfsub_args vargs;
9475+ unsigned int mnt_flags;
9476+ struct au_pin pin;
9477+
9478+ dentry = file->f_dentry;
9479+ LKTRTrace("%.*s, len %zu, pos %lld\n", AuDLNPair(dentry), len, *ppos);
9480+
9481+ inode = dentry->d_inode;
9482+ mutex_lock(&inode->i_mutex);
9483+ sb = dentry->d_sb;
9484+ si_read_lock(sb, AuLock_FLUSH);
9485+ mnt_flags = au_mntflags(sb);
9486+ vfsub_args_init(&vargs, /*&ign*/NULL, au_test_dlgt(mnt_flags), 0);
9487+
9488+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
9489+ /*locked*/1);
9490+ if (unlikely(err))
9491+ goto out;
9492+ err = au_ready_to_write(file, -1, &pin);
9493+ di_downgrade_lock(dentry, AuLock_IR);
9494+ if (unlikely(err))
9495+ goto out_unlock;
9496+
9497+ /* support LSM and notify */
9498+ /* current vfs_splice_from() doesn't fire up the inotify event */
9499+ h_file = au_h_fptr(file, au_fbstart(file));
9500+ h_inode = h_file->f_dentry->d_inode;
9501+ if (1 || !au_opt_test(mnt_flags, UDBA_INOTIFY)) {
9502+ au_unpin(&pin);
9503+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags, &vargs);
9504+ }
9505+#if 0 /* reserved for future use */
9506+ else {
9507+ struct dentry *parent = dget_parent(dentry);
9508+ vfsub_ign_hinode(&vargs, IN_MODIFY, au_pinned_hdir(&pin));
9509+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags, &vargs);
9510+ au_unpin(&pin);
9511+ }
9512+#endif
9513+ au_cpup_attr_timesizes(inode);
9514+
9515+ out_unlock:
9516+ di_read_unlock(dentry, AuLock_IR);
9517+ fi_write_unlock(file);
9518+ out:
9519+ si_read_unlock(sb);
9520+ mutex_unlock(&inode->i_mutex);
9521+ AuTraceErr(err);
9522+ return err;
9523+}
9524+#endif /* CONFIG_AUFS_SPLICE_PATCH */
9525+
9526+/* ---------------------------------------------------------------------- */
9527+
9528+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
9529+{
9530+ int err;
9531+ struct dentry *dentry;
9532+ struct file *file, *h_file;
9533+ struct inode *inode;
9534+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9535+ struct au_finfo *finfo;
9536+
9537+ AuTraceEnter();
9538+ AuDebugOn(!vma || !vma->vm_file);
9539+ /* todo: non-robr mode, user vm_file as it is? */
9540+ wait_event(wq, (file = au_robr_safe_file(vma)));
9541+ AuDebugOn(!au_test_aufs(file->f_dentry->d_sb));
9542+ dentry = file->f_dentry;
9543+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
9544+ inode = dentry->d_inode;
9545+ AuDebugOn(!S_ISREG(inode->i_mode));
9546+
9547+ /* do not revalidate, no si lock */
9548+ finfo = au_fi(file);
9549+ h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
9550+ AuDebugOn(!h_file || !au_test_mmapped(file));
9551+ fi_write_lock(file);
9552+ vma->vm_file = h_file;
9553+ err = finfo->fi_h_vm_ops->fault(vma, vmf);
9554+ /* todo: necessary? */
9555+ /* file->f_ra = h_file->f_ra; */
9556+ au_robr_reset_file(vma, file);
9557+ fi_write_unlock(file);
9558+#if 0 /* def CONFIG_SMP */
9559+ /* wake_up_nr(&wq, online_cpu - 1); */
9560+ wake_up_all(&wq);
9561+#else
9562+ wake_up(&wq);
9563+#endif
9564+
9565+ if (!(err & VM_FAULT_ERROR)) {
9566+#if 0 /* debug */
9567+ struct page *page;
9568+ page = vmf->page;
9569+ AuDbg("%p, %d\n", page, page_mapcount(page));
9570+
9571+ page->mapping = file->f_mapping;
9572+ get_page(page);
9573+ file->f_mapping = h_file->f_mapping;
9574+ touch_atime(NULL, dentry);
9575+ inode->i_atime = h_file->f_dentry->d_inode->i_atime;
9576+#endif
9577+ }
9578+ AuTraceErr(err);
9579+ return err;
9580+}
9581+
9582+static struct vm_operations_struct aufs_vm_ops = {
9583+ .fault = aufs_fault,
9584+#if 0 /* reserved for future use */
9585+ .open = aufs_vmaopen,
9586+ .close = aufs_vmaclose,
9587+ unsigned long (*nopfn)(struct vm_area_struct *area,
9588+ unsigned long address);
9589+ page_mkwrite(struct vm_area_struct *vma, struct page *page)
9590+#endif
9591+};
9592+
9593+/* ---------------------------------------------------------------------- */
9594+
9595+static struct vm_operations_struct *au_vm_ops(struct file *h_file,
9596+ struct vm_area_struct *vma)
9597+{
9598+ struct vm_operations_struct *vm_ops;
9599+ int err;
9600+
9601+ AuTraceEnter();
9602+
9603+ au_br_nfs_lockdep_off(h_file->f_vfsmnt->mnt_sb);
9604+ err = h_file->f_op->mmap(h_file, vma);
9605+ au_br_nfs_lockdep_on(h_file->f_vfsmnt->mnt_sb);
9606+ vm_ops = ERR_PTR(err);
9607+ if (unlikely(err))
9608+ goto out;
9609+ vm_ops = vma->vm_ops;
9610+ err = do_munmap(current->mm, vma->vm_start,
9611+ vma->vm_end - vma->vm_start);
9612+ if (unlikely(err)) {
9613+ AuIOErr("failed internal unmapping %.*s, %d\n",
9614+ AuDLNPair(h_file->f_dentry), err);
9615+ vm_ops = ERR_PTR(-EIO);
9616+ }
9617+
9618+ out:
9619+ AuTraceErrPtr(vm_ops);
9620+ return vm_ops;
9621+}
9622+
9623+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
9624+{
9625+ int err;
9626+ unsigned char wlock, mmapped;
9627+ struct dentry *dentry;
9628+ struct super_block *sb;
9629+ struct file *h_file;
9630+ struct vm_operations_struct *vm_ops;
9631+
9632+ dentry = file->f_dentry;
9633+ LKTRTrace("%.*s, %lx, len %lu\n",
9634+ AuDLNPair(dentry), vma->vm_start,
9635+ vma->vm_end - vma->vm_start);
9636+ AuDebugOn(!S_ISREG(dentry->d_inode->i_mode));
9637+ AuDebugOn(down_write_trylock(&vma->vm_mm->mmap_sem));
9638+
9639+ mmapped = au_test_mmapped(file); /* can be harmless race condition */
9640+ wlock = !!(file->f_mode & FMODE_WRITE);
9641+ sb = dentry->d_sb;
9642+ si_read_lock(sb, AuLock_FLUSH);
9643+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, wlock | !mmapped,
9644+ /*locked*/0);
9645+ if (unlikely(err))
9646+ goto out;
9647+
9648+ if (wlock) {
9649+ struct au_pin pin;
9650+
9651+ err = au_ready_to_write(file, -1, &pin);
9652+ di_downgrade_lock(dentry, AuLock_IR);
9653+ if (unlikely(err))
9654+ goto out_unlock;
9655+ au_unpin(&pin);
9656+ } else if (!mmapped)
9657+ di_downgrade_lock(dentry, AuLock_IR);
9658+
9659+ h_file = au_h_fptr(file, au_fbstart(file));
9660+ if (au_test_fuse(h_file->f_dentry->d_sb)) {
9661+ /*
9662+ * by this assignment, f_mapping will differs from aufs inode
9663+ * i_mapping.
9664+ * if someone else mixes the use of f_dentry->d_inode and
9665+ * f_mapping->host, then a problem may arise.
9666+ */
9667+ file->f_mapping = h_file->f_mapping;
9668+ }
9669+
9670+ if (0 && h_file->f_op->mmap == generic_file_mmap) {
9671+ err = generic_file_mmap(file, vma); /* instead of h_file */
9672+ if (unlikely(err))
9673+ goto out_unlock;
9674+ au_fi(file)->fi_h_vm_ops = vma->vm_ops;
9675+ } else {
9676+ vm_ops = NULL;
9677+ if (!mmapped) {
9678+ vm_ops = au_vm_ops(h_file, vma);
9679+ err = PTR_ERR(vm_ops);
9680+ if (IS_ERR(vm_ops))
9681+ goto out_unlock;
9682+ }
9683+
9684+ err = generic_file_mmap(file, vma);
9685+ if (unlikely(err))
9686+ goto out_unlock;
9687+ vma->vm_ops = &aufs_vm_ops;
9688+ /* test again */
9689+ if (!au_test_mmapped(file)) {
9690+ FiMustWriteLock(file);
9691+ au_fi(file)->fi_h_vm_ops = vm_ops;
9692+ }
9693+ }
9694+
9695+ file_accessed(h_file);
9696+ au_update_fuse_h_inode(h_file->f_vfsmnt, h_file->f_dentry); /*ignore*/
9697+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9698+
9699+ out_unlock:
9700+ di_read_unlock(dentry, AuLock_IR);
9701+ if (!wlock && mmapped)
9702+ fi_read_unlock(file);
9703+ else
9704+ fi_write_unlock(file);
9705+ out:
9706+ si_read_unlock(sb);
9707+ AuTraceErr(err);
9708+ return err;
9709+}
9710+
9711+/* ---------------------------------------------------------------------- */
9712+
9713+static unsigned int aufs_poll(struct file *file, poll_table *wait)
9714+{
9715+ unsigned int mask;
9716+ struct file *h_file;
9717+ int err;
9718+ struct dentry *dentry;
9719+ struct super_block *sb;
9720+
9721+ dentry = file->f_dentry;
9722+ LKTRTrace("%.*s, wait %p\n", AuDLNPair(dentry), wait);
9723+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode));
9724+
9725+ /* We should pretend an error happened. */
9726+ mask = POLLERR /* | POLLIN | POLLOUT */;
9727+ sb = dentry->d_sb;
9728+ si_read_lock(sb, AuLock_FLUSH);
9729+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0,
9730+ /*locked*/0);
9731+ if (unlikely(err))
9732+ goto out;
9733+
9734+ /* it is not an error of hidden_file has no operation */
9735+ mask = DEFAULT_POLLMASK;
9736+ h_file = au_h_fptr(file, au_fbstart(file));
9737+ if (h_file->f_op && h_file->f_op->poll)
9738+ mask = h_file->f_op->poll(h_file, wait);
9739+ di_read_unlock(dentry, AuLock_IR);
9740+ fi_read_unlock(file);
9741+
9742+ out:
9743+ si_read_unlock(sb);
9744+ AuTraceErr((int)mask);
9745+ return mask;
9746+}
9747+
9748+static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
9749+ int datasync)
9750+{
9751+ int err;
9752+ struct inode *inode;
9753+ struct file *h_file;
9754+ struct super_block *sb;
9755+ struct au_pin pin;
9756+
9757+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), datasync);
9758+ inode = dentry->d_inode;
9759+
9760+ IMustLock(file->f_mapping->host);
9761+ if (inode != file->f_mapping->host) {
9762+ mutex_unlock(&file->f_mapping->host->i_mutex);
9763+ mutex_lock(&inode->i_mutex);
9764+ }
9765+ IMustLock(inode);
9766+
9767+ sb = dentry->d_sb;
9768+ si_read_lock(sb, AuLock_FLUSH);
9769+ err = 0; /* -EBADF; */ /* posix? */
9770+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
9771+ goto out;
9772+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
9773+ /*locked*/1);
9774+ if (unlikely(err))
9775+ goto out;
9776+ err = au_ready_to_write(file, -1, &pin);
9777+ di_downgrade_lock(dentry, AuLock_IR);
9778+ if (unlikely(err))
9779+ goto out_unlock;
9780+ au_unpin(&pin);
9781+
9782+ err = -EINVAL;
9783+ h_file = au_h_fptr(file, au_fbstart(file));
9784+ if (h_file->f_op && h_file->f_op->fsync) {
9785+ struct mutex *h_mtx = &h_file->f_dentry->d_inode->i_mutex;
9786+
9787+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
9788+ err = h_file->f_op->fsync(h_file, h_file->f_dentry, datasync);
9789+ if (!err)
9790+ au_update_fuse_h_inode(h_file->f_vfsmnt,
9791+ h_file->f_dentry);
9792+ au_cpup_attr_timesizes(inode);
9793+ mutex_unlock(h_mtx);
9794+ }
9795+
9796+ out_unlock:
9797+ di_read_unlock(dentry, AuLock_IR);
9798+ fi_write_unlock(file);
9799+ out:
9800+ si_read_unlock(sb);
9801+ if (inode != file->f_mapping->host) {
9802+ mutex_unlock(&inode->i_mutex);
9803+ mutex_lock(&file->f_mapping->host->i_mutex);
9804+ }
9805+ AuTraceErr(err);
9806+ return err;
9807+}
9808+
9809+static int aufs_fasync(int fd, struct file *file, int flag)
9810+{
9811+ int err;
9812+ struct file *h_file;
9813+ struct dentry *dentry;
9814+ struct super_block *sb;
9815+
9816+ dentry = file->f_dentry;
9817+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), flag);
9818+
9819+ sb = dentry->d_sb;
9820+ si_read_lock(sb, AuLock_FLUSH);
9821+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0,
9822+ /*locked*/0);
9823+ if (unlikely(err))
9824+ goto out;
9825+
9826+ h_file = au_h_fptr(file, au_fbstart(file));
9827+ if (h_file->f_op && h_file->f_op->fasync)
9828+ err = h_file->f_op->fasync(fd, h_file, flag);
9829+ di_read_unlock(dentry, AuLock_IR);
9830+ fi_read_unlock(file);
9831+
9832+ out:
9833+ si_read_unlock(sb);
9834+ AuTraceErr(err);
9835+ return err;
9836+}
9837+
9838+/* ---------------------------------------------------------------------- */
9839+
9840+struct file_operations aufs_file_fop = {
9841+ /*
9842+ * while generic_file_llseek/_unlocked() don't use BKL,
9843+ * don't use it since it operates file->f_mapping->host.
9844+ * in aufs, it may be a real file and may confuse users by UDBA.
9845+ */
9846+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
9847+ /* .llseek = generic_file_llseek, */
9848+#endif
9849+ .read = aufs_read,
9850+ .write = aufs_write,
9851+ .poll = aufs_poll,
9852+ /* .unlocked_ioctl = aufs_ioctl, */
9853+ .mmap = aufs_mmap,
9854+ .open = aufs_open_nondir,
9855+ .flush = aufs_flush,
9856+ .release = aufs_release_nondir,
9857+ .fsync = aufs_fsync_nondir,
9858+ .fasync = aufs_fasync,
9859+#ifdef CONFIG_AUFS_SPLICE_PATCH
9860+ .splice_write = aufs_splice_write,
9861+ .splice_read = aufs_splice_read,
9862+#endif
9863+};
9864diff -urN linux/fs/aufs/getattr.c linux-aufs/fs/aufs/getattr.c
9865--- linux/fs/aufs/getattr.c 1970-01-01 01:00:00.000000000 +0100
9866+++ linux-aufs/fs/aufs/getattr.c 2009-03-12 16:18:04.000000000 +0100
9867@@ -0,0 +1,133 @@
9868+/*
9869+ * Copyright (C) 2005-2009 Junjiro Okajima
9870+ *
9871+ * This program, aufs is free software; you can redistribute it and/or modify
9872+ * it under the terms of the GNU General Public License as published by
9873+ * the Free Software Foundation; either version 2 of the License, or
9874+ * (at your option) any later version.
9875+ *
9876+ * This program is distributed in the hope that it will be useful,
9877+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9878+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9879+ * GNU General Public License for more details.
9880+ *
9881+ * You should have received a copy of the GNU General Public License
9882+ * along with this program; if not, write to the Free Software
9883+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9884+ */
9885+
9886+/*
9887+ * inode attributes on NFS/FUSE branch or HINOTIFY
9888+ *
9889+ * $Id$
9890+ */
9891+
9892+#include "aufs.h"
9893+
9894+static struct dentry *
9895+au_h_dget_any(struct dentry *dentry, aufs_bindex_t *bindex)
9896+{
9897+ struct dentry *h_dentry;
9898+ struct inode *inode, *h_inode;
9899+ struct super_block *sb;
9900+ aufs_bindex_t ib, db;
9901+
9902+ /* must be positive dentry */
9903+ inode = dentry->d_inode;
9904+ LKTRTrace("%.*s, i%lu\n", AuDLNPair(dentry), inode->i_ino);
9905+
9906+ sb = dentry->d_sb;
9907+ db = au_dbstart(dentry);
9908+ ib = au_ibstart(inode);
9909+ if (db == ib) {
9910+ *bindex = db;
9911+ h_dentry = dget(au_h_dptr(dentry, db));
9912+ if (h_dentry)
9913+ goto out; /* success */
9914+ }
9915+
9916+ *bindex = ib;
9917+ h_inode = au_h_iptr(inode, ib);
9918+ h_dentry = d_find_alias(h_inode);
9919+ if (h_dentry)
9920+ goto out; /* success */
9921+
9922+#if 0
9923+ if (au_opt_test(au_mntflags(sb), PLINK)
9924+ && au_plink_test(sb, inode)) {
9925+ h_dentry = au_plink_lkup(sb, ib, inode);
9926+ if (IS_ERR(h_dentry))
9927+ goto out;
9928+ AuDebugOn(!h_dentry->d_inode);
9929+ goto out; /* success */
9930+ }
9931+#endif
9932+
9933+ h_dentry = dget(au_hi_wh(inode, ib));
9934+
9935+ out:
9936+ AuTraceErrPtr(h_dentry);
9937+ return h_dentry;
9938+}
9939+
9940+int aufs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st)
9941+{
9942+ int err;
9943+ unsigned int mnt_flags;
9944+ aufs_bindex_t bindex;
9945+ unsigned char did_lock;
9946+ struct inode *inode;
9947+ struct dentry *h_dentry;
9948+ struct super_block *sb, *h_sb;
9949+
9950+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
9951+
9952+ err = 0;
9953+ sb = dentry->d_sb;
9954+ si_read_lock(sb, AuLock_FLUSH);
9955+ mnt_flags = au_mntflags(sb);
9956+ if (dentry != sb->s_root) {
9957+ di_read_lock_parent(dentry, AuLock_IR);
9958+ inode = dentry->d_inode;
9959+ did_lock = 1;
9960+
9961+ /* todo: test bit inotify option too? */
9962+ bindex = au_ibstart(inode);
9963+ h_sb = au_sbr_sb(sb, bindex);
9964+ /* todo: fix this condition */
9965+ if ((au_opt_test(mnt_flags, PLINK) && au_plink_test(sb, inode))
9966+ /* au_iigen(inode) == au_sigen(sb) */
9967+ || (!au_test_fuse(h_sb) && !au_test_nfs(h_sb)))
9968+ goto fill;
9969+
9970+ h_dentry = au_h_dget_any(dentry, &bindex);
9971+ err = PTR_ERR(h_dentry);
9972+ if (IS_ERR(h_dentry))
9973+ goto out;
9974+ } else {
9975+ /* lock free root dinfo */
9976+ did_lock = 0;
9977+ bindex = 0;
9978+ inode = dentry->d_inode;
9979+ h_dentry = dget(au_di(dentry)->di_hdentry->hd_dentry);
9980+ }
9981+
9982+ err = -EIO;
9983+ if (h_dentry && h_dentry->d_inode)
9984+ err = vfsub_getattr(au_sbr_mnt(sb, bindex), h_dentry, st,
9985+ au_test_dlgt(mnt_flags));
9986+ dput(h_dentry);
9987+ if (!err) {
9988+ /* todo: I don't like this approach */
9989+ au_cpup_attr_all(inode, /*force*/0);
9990+ fill:
9991+ generic_fillattr(inode, st);
9992+ }
9993+
9994+ out:
9995+ if (did_lock)
9996+ di_read_unlock(dentry, AuLock_IR);
9997+ si_read_unlock(sb);
9998+ AuTraceErr(err);
9999+ return err;
10000+}
10001diff -urN linux/fs/aufs/hinode.h linux-aufs/fs/aufs/hinode.h
10002--- linux/fs/aufs/hinode.h 1970-01-01 01:00:00.000000000 +0100
10003+++ linux-aufs/fs/aufs/hinode.h 2009-03-12 16:18:04.000000000 +0100
10004@@ -0,0 +1,175 @@
10005+/*
10006+ * Copyright (C) 2005-2009 Junjiro Okajima
10007+ *
10008+ * This program, aufs is free software; you can redistribute it and/or modify
10009+ * it under the terms of the GNU General Public License as published by
10010+ * the Free Software Foundation; either version 2 of the License, or
10011+ * (at your option) any later version.
10012+ *
10013+ * This program is distributed in the hope that it will be useful,
10014+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10015+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10016+ * GNU General Public License for more details.
10017+ *
10018+ * You should have received a copy of the GNU General Public License
10019+ * along with this program; if not, write to the Free Software
10020+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10021+ */
10022+
10023+/*
10024+ * lower (branch filesystem) inode and setting inotify
10025+ *
10026+ * $Id$
10027+ */
10028+
10029+#ifndef __AUFS_HINODE_H__
10030+#define __AUFS_HINODE_H__
10031+
10032+#ifdef __KERNEL__
10033+
10034+#include <linux/fs.h>
10035+#include <linux/inotify.h>
10036+#include <linux/aufs_type.h>
10037+#include "super.h"
10038+#include "vfsub.h"
10039+
10040+/* ---------------------------------------------------------------------- */
10041+
10042+struct au_hinotify {
10043+#ifdef CONFIG_AUFS_HINOTIFY
10044+ struct au_splhead hin_ignore;
10045+ struct inotify_watch hin_watch;
10046+ struct inode *hin_aufs_inode; /* no get/put */
10047+#endif
10048+};
10049+
10050+struct au_hinode {
10051+ struct inode *hi_inode;
10052+ aufs_bindex_t hi_id;
10053+#ifdef CONFIG_AUFS_HINOTIFY
10054+ struct au_hinotify *hi_notify;
10055+#endif
10056+
10057+ /* reference to the copied-up whiteout with get/put */
10058+ struct dentry *hi_whdentry;
10059+};
10060+
10061+struct au_hin_ignore {
10062+#ifdef CONFIG_AUFS_HINOTIFY
10063+ struct list_head ign_list;
10064+
10065+ pid_t ign_pid;
10066+ __u32 ign_events, ign_handled;
10067+ struct au_hinode *ign_hinode;
10068+#endif
10069+};
10070+
10071+/* ---------------------------------------------------------------------- */
10072+
10073+#ifdef CONFIG_AUFS_HINOTIFY
10074+/* inotify events */
10075+static const __u32 AuInMask = (IN_MOVE | IN_DELETE | IN_CREATE
10076+ /* | IN_ACCESS */
10077+ | IN_MODIFY | IN_ATTRIB
10078+ /* | IN_DELETE_SELF | IN_MOVE_SELF */
10079+ );
10080+
10081+static inline
10082+void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
10083+{
10084+ hinode->hi_notify = val;
10085+}
10086+
10087+/* hinotify.c */
10088+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
10089+ struct inode *h_inode);
10090+void au_hin_free(struct au_hinode *hinode);
10091+void au_hin_ctl(struct au_hinode *hinode, const __u32 mask);
10092+void au_reset_hinotify(struct inode *inode, unsigned int flags);
10093+
10094+int au_hin_verify_gen(struct dentry *dentry);
10095+
10096+int __init au_inotify_init(void);
10097+void au_inotify_fin(void);
10098+
10099+static inline void au_hin_suspend(struct au_hinode *hinode)
10100+{
10101+ au_hin_ctl(hinode, 0);
10102+}
10103+
10104+static inline void au_hin_resume(struct au_hinode *hinode)
10105+{
10106+ au_hin_ctl(hinode, AuInMask);
10107+}
10108+
10109+#else
10110+
10111+static inline
10112+void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
10113+{
10114+ /* empty */
10115+}
10116+
10117+static inline
10118+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
10119+ struct inode *h_inode)
10120+{
10121+ return -EOPNOTSUPP;
10122+}
10123+
10124+static inline void au_hin_free(struct au_hinode *hinode)
10125+{
10126+ /* nothing */
10127+}
10128+
10129+static inline void au_reset_hinotify(struct inode *inode, unsigned int flags)
10130+{
10131+ /* nothing */
10132+}
10133+
10134+static inline int au_hin_verify_gen(struct dentry *dentry)
10135+{
10136+ return 0;
10137+}
10138+
10139+static inline int au_inotify_init(void)
10140+{
10141+ return 0;
10142+}
10143+
10144+#define au_inotify_fin() do {} while (0)
10145+
10146+static inline void au_hin_suspend(struct au_hinode *hinode)
10147+{
10148+ /* empty */
10149+}
10150+
10151+static inline void au_hin_resume(struct au_hinode *hinode)
10152+{
10153+ /* empty */
10154+}
10155+#endif /* CONFIG_AUFS_HINOTIFY */
10156+
10157+#if defined(CONFIG_AUFS_HINOTIFY) && defined(CONFIG_AUFS_DEBUG)
10158+static inline void au_hin_list_del(struct list_head *e)
10159+{
10160+ list_del_init(e);
10161+}
10162+
10163+void au_dbg_hin_list(struct vfsub_args *vargs);
10164+#else
10165+static inline void au_hin_list_del(struct list_head *e)
10166+{
10167+ list_del(e);
10168+}
10169+
10170+static inline void au_dbg_hin_list(struct vfsub_args *vargs)
10171+{
10172+ /* empty */
10173+}
10174+#endif /* CONFIG_AUFS_DEBUG */
10175+
10176+/* ---------------------------------------------------------------------- */
10177+
10178+#endif /* __KERNEL__ */
10179+#endif /* __AUFS_HINODE_H__ */
10180diff -urN linux/fs/aufs/hin_or_dlgt.c linux-aufs/fs/aufs/hin_or_dlgt.c
10181--- linux/fs/aufs/hin_or_dlgt.c 1970-01-01 01:00:00.000000000 +0100
10182+++ linux-aufs/fs/aufs/hin_or_dlgt.c 2009-03-12 16:18:04.000000000 +0100
10183@@ -0,0 +1,736 @@
10184+/*
10185+ * Copyright (C) 2005-2009 Junjiro Okajima
10186+ *
10187+ * This program, aufs is free software; you can redistribute it and/or modify
10188+ * it under the terms of the GNU General Public License as published by
10189+ * the Free Software Foundation; either version 2 of the License, or
10190+ * (at your option) any later version.
10191+ *
10192+ * This program is distributed in the hope that it will be useful,
10193+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10194+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10195+ * GNU General Public License for more details.
10196+ *
10197+ * You should have received a copy of the GNU General Public License
10198+ * along with this program; if not, write to the Free Software
10199+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10200+ */
10201+
10202+/*
10203+ * sub-routines for vfs in hinotify or dlgt mode
10204+ *
10205+ * $Id$
10206+ */
10207+
10208+#include <linux/uaccess.h>
10209+#include "aufs.h"
10210+
10211+#if !defined(CONFIG_AUFS_HINOTIFY) && !defined(CONFIG_AUFS_DLGT)
10212+#error mis-configuraion or Makefile
10213+#endif
10214+
10215+/* ---------------------------------------------------------------------- */
10216+
10217+struct permission_args {
10218+ int *errp;
10219+ struct inode *inode;
10220+ int mask;
10221+ struct nameidata *nd;
10222+};
10223+
10224+static void call_permission(void *args)
10225+{
10226+ struct permission_args *a = args;
10227+ *a->errp = do_vfsub_permission(a->inode, a->mask, a->nd);
10228+}
10229+
10230+int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
10231+ int dlgt)
10232+{
10233+ if (!dlgt)
10234+ return do_vfsub_permission(inode, mask, nd);
10235+ else {
10236+ int err, wkq_err;
10237+ struct permission_args args = {
10238+ .errp = &err,
10239+ .inode = inode,
10240+ .mask = mask,
10241+ .nd = nd
10242+ };
10243+ wkq_err = au_wkq_wait(call_permission, &args, /*dlgt*/1);
10244+ if (unlikely(wkq_err))
10245+ err = wkq_err;
10246+ return err;
10247+ }
10248+}
10249+
10250+/* ---------------------------------------------------------------------- */
10251+
10252+struct create_args {
10253+ int *errp;
10254+ struct inode *dir;
10255+ struct dentry *dentry;
10256+ int mode;
10257+ struct nameidata *nd;
10258+ struct vfsub_args *vargs;
10259+};
10260+
10261+static void call_create(void *args)
10262+{
10263+ struct create_args *a = args;
10264+ vfsub_ignore(a->vargs);
10265+ *a->errp = do_vfsub_create(a->dir, a->dentry, a->mode, a->nd);
10266+ if (unlikely(*a->errp))
10267+ vfsub_unignore(a->vargs);
10268+ au_dbg_hin_list(a->vargs);
10269+}
10270+
10271+int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
10272+ struct nameidata *nd, struct vfsub_args *vargs)
10273+{
10274+ int err;
10275+ struct create_args args = {
10276+ .errp = &err,
10277+ .dir = dir,
10278+ .dentry = dentry,
10279+ .mode = mode,
10280+ .nd = nd,
10281+ .vargs = vargs
10282+ };
10283+
10284+ if (!vfsub_ftest(vargs->flags, DLGT))
10285+ call_create(&args);
10286+ else {
10287+ int wkq_err;
10288+ wkq_err = au_wkq_wait(call_create, &args, /*dlgt*/1);
10289+ if (unlikely(wkq_err))
10290+ err = wkq_err;
10291+ }
10292+ return err;
10293+}
10294+
10295+struct symlink_args {
10296+ int *errp;
10297+ struct inode *dir;
10298+ struct dentry *dentry;
10299+ const char *symname;
10300+ int mode;
10301+ struct vfsub_args *vargs;
10302+};
10303+
10304+static void call_symlink(void *args)
10305+{
10306+ struct symlink_args *a = args;
10307+ vfsub_ignore(a->vargs);
10308+ *a->errp = do_vfsub_symlink(a->dir, a->dentry, a->symname, a->mode);
10309+ if (unlikely(*a->errp))
10310+ vfsub_unignore(a->vargs);
10311+ au_dbg_hin_list(a->vargs);
10312+}
10313+
10314+int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
10315+ int mode, struct vfsub_args *vargs)
10316+{
10317+ int err;
10318+ struct symlink_args args = {
10319+ .errp = &err,
10320+ .dir = dir,
10321+ .dentry = dentry,
10322+ .symname = symname,
10323+ .mode = mode,
10324+ .vargs = vargs
10325+ };
10326+
10327+ if (!vfsub_ftest(vargs->flags, DLGT))
10328+ call_symlink(&args);
10329+ else {
10330+ int wkq_err;
10331+ wkq_err = au_wkq_wait(call_symlink, &args, /*dlgt*/1);
10332+ if (unlikely(wkq_err))
10333+ err = wkq_err;
10334+ }
10335+ return err;
10336+}
10337+
10338+struct mknod_args {
10339+ int *errp;
10340+ struct inode *dir;
10341+ struct dentry *dentry;
10342+ int mode;
10343+ dev_t dev;
10344+ struct vfsub_args *vargs;
10345+};
10346+
10347+static void call_mknod(void *args)
10348+{
10349+ struct mknod_args *a = args;
10350+ vfsub_ignore(a->vargs);
10351+ *a->errp = do_vfsub_mknod(a->dir, a->dentry, a->mode, a->dev);
10352+ if (unlikely(*a->errp))
10353+ vfsub_unignore(a->vargs);
10354+ au_dbg_hin_list(a->vargs);
10355+}
10356+
10357+int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
10358+ struct vfsub_args *vargs)
10359+{
10360+ int err;
10361+ struct mknod_args args = {
10362+ .errp = &err,
10363+ .dir = dir,
10364+ .dentry = dentry,
10365+ .mode = mode,
10366+ .dev = dev,
10367+ .vargs = vargs
10368+ };
10369+
10370+ if (!vfsub_ftest(vargs->flags, DLGT))
10371+ call_mknod(&args);
10372+ else {
10373+ int wkq_err;
10374+ wkq_err = au_wkq_wait(call_mknod, &args, /*dlgt*/1);
10375+ if (unlikely(wkq_err))
10376+ err = wkq_err;
10377+ }
10378+ return err;
10379+}
10380+
10381+struct mkdir_args {
10382+ int *errp;
10383+ struct inode *dir;
10384+ struct dentry *dentry;
10385+ int mode;
10386+ struct vfsub_args *vargs;
10387+};
10388+
10389+static void call_mkdir(void *args)
10390+{
10391+ struct mkdir_args *a = args;
10392+ vfsub_ignore(a->vargs);
10393+ *a->errp = do_vfsub_mkdir(a->dir, a->dentry, a->mode);
10394+ if (unlikely(*a->errp))
10395+ vfsub_unignore(a->vargs);
10396+ au_dbg_hin_list(a->vargs);
10397+}
10398+
10399+int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode,
10400+ struct vfsub_args *vargs)
10401+{
10402+ int err;
10403+ struct mkdir_args args = {
10404+ .errp = &err,
10405+ .dir = dir,
10406+ .dentry = dentry,
10407+ .mode = mode,
10408+ .vargs = vargs
10409+ };
10410+
10411+ if (!vfsub_ftest(vargs->flags, DLGT))
10412+ call_mkdir(&args);
10413+ else {
10414+ int wkq_err;
10415+ wkq_err = au_wkq_wait(call_mkdir, &args, /*dlgt*/1);
10416+ if (unlikely(wkq_err))
10417+ err = wkq_err;
10418+ }
10419+ return err;
10420+}
10421+
10422+/* ---------------------------------------------------------------------- */
10423+
10424+struct link_args {
10425+ int *errp;
10426+ struct inode *dir;
10427+ struct dentry *src_dentry, *dentry;
10428+ struct vfsub_args *vargs;
10429+};
10430+
10431+static void call_link(void *args)
10432+{
10433+ struct link_args *a = args;
10434+ vfsub_ignore(a->vargs);
10435+ *a->errp = do_vfsub_link(a->src_dentry, a->dir, a->dentry);
10436+ if (unlikely(*a->errp))
10437+ vfsub_unignore(a->vargs);
10438+ au_dbg_hin_list(a->vargs);
10439+}
10440+
10441+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
10442+ struct dentry *dentry, struct vfsub_args *vargs)
10443+{
10444+ int err;
10445+ struct link_args args = {
10446+ .errp = &err,
10447+ .src_dentry = src_dentry,
10448+ .dir = dir,
10449+ .dentry = dentry,
10450+ .vargs = vargs
10451+ };
10452+
10453+ if (!vfsub_ftest(vargs->flags, DLGT))
10454+ call_link(&args);
10455+ else {
10456+ int wkq_err;
10457+ wkq_err = au_wkq_wait(call_link, &args, /*dlgt*/1);
10458+ if (unlikely(wkq_err))
10459+ err = wkq_err;
10460+ }
10461+ return err;
10462+}
10463+
10464+struct rename_args {
10465+ int *errp;
10466+ struct inode *src_dir, *dir;
10467+ struct dentry *src_dentry, *dentry;
10468+ struct vfsub_args *vargs;
10469+};
10470+
10471+static void call_rename(void *args)
10472+{
10473+ struct rename_args *a = args;
10474+ vfsub_ignore(a->vargs);
10475+ *a->errp = do_vfsub_rename(a->src_dir, a->src_dentry, a->dir,
10476+ a->dentry);
10477+ if (unlikely(*a->errp))
10478+ vfsub_unignore(a->vargs);
10479+ au_dbg_hin_list(a->vargs);
10480+}
10481+
10482+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
10483+ struct inode *dir, struct dentry *dentry,
10484+ struct vfsub_args *vargs)
10485+{
10486+ int err;
10487+ struct rename_args args = {
10488+ .errp = &err,
10489+ .src_dir = src_dir,
10490+ .src_dentry = src_dentry,
10491+ .dir = dir,
10492+ .dentry = dentry,
10493+ .vargs = vargs
10494+ };
10495+
10496+ if (!vfsub_ftest(vargs->flags, DLGT))
10497+ call_rename(&args);
10498+ else {
10499+ int wkq_err;
10500+ wkq_err = au_wkq_wait(call_rename, &args, /*dlgt*/1);
10501+ if (unlikely(wkq_err))
10502+ err = wkq_err;
10503+ }
10504+ return err;
10505+}
10506+
10507+struct rmdir_args {
10508+ int *errp;
10509+ struct inode *dir;
10510+ struct dentry *dentry;
10511+ struct vfsub_args *vargs;
10512+};
10513+
10514+static void call_rmdir(void *args)
10515+{
10516+ struct rmdir_args *a = args;
10517+ vfsub_ignore(a->vargs);
10518+ *a->errp = do_vfsub_rmdir(a->dir, a->dentry);
10519+ if (unlikely(*a->errp))
10520+ vfsub_unignore(a->vargs);
10521+ au_dbg_hin_list(a->vargs);
10522+}
10523+
10524+int vfsub_rmdir(struct inode *dir, struct dentry *dentry,
10525+ struct vfsub_args *vargs)
10526+{
10527+ int err;
10528+ struct rmdir_args args = {
10529+ .errp = &err,
10530+ .dir = dir,
10531+ .dentry = dentry,
10532+ .vargs = vargs
10533+ };
10534+
10535+ if (!vfsub_ftest(vargs->flags, DLGT))
10536+ call_rmdir(&args);
10537+ else {
10538+ int wkq_err;
10539+ wkq_err = au_wkq_wait(call_rmdir, &args, /*dlgt*/1);
10540+ if (unlikely(wkq_err))
10541+ err = wkq_err;
10542+ }
10543+ return err;
10544+}
10545+
10546+/* ---------------------------------------------------------------------- */
10547+
10548+struct read_args {
10549+ ssize_t *errp;
10550+ struct file *file;
10551+ union {
10552+ void *kbuf;
10553+ char __user *ubuf;
10554+ };
10555+ size_t count;
10556+ loff_t *ppos;
10557+};
10558+
10559+static void call_read_k(void *args)
10560+{
10561+ struct read_args *a = args;
10562+ LKTRTrace("%.*s, cnt %zu, pos %lld\n",
10563+ AuDLNPair(a->file->f_dentry), a->count, *a->ppos);
10564+ *a->errp = do_vfsub_read_k(a->file, a->kbuf, a->count, a->ppos);
10565+}
10566+
10567+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
10568+ loff_t *ppos, int dlgt)
10569+{
10570+ if (!dlgt)
10571+ return do_vfsub_read_u(file, ubuf, count, ppos);
10572+ else {
10573+ int wkq_err;
10574+ ssize_t err, read;
10575+ struct read_args args = {
10576+ .errp = &err,
10577+ .file = file,
10578+ .count = count,
10579+ .ppos = ppos
10580+ };
10581+
10582+ if (!count)
10583+ return 0;
10584+
10585+ /*
10586+ * workaround an application bug.
10587+ * generally, read(2) or write(2) may return the value shorter
10588+ * than requested. But many applications don't support it,
10589+ * for example bash.
10590+ */
10591+ err = -ENOMEM;
10592+ if (args.count > PAGE_SIZE)
10593+ args.count = PAGE_SIZE;
10594+ args.kbuf = kmalloc(args.count, GFP_NOFS);
10595+ if (unlikely(!args.kbuf))
10596+ goto out;
10597+
10598+ read = 0;
10599+ do {
10600+ wkq_err = au_wkq_wait(call_read_k, &args, /*dlgt*/1);
10601+ if (unlikely(wkq_err))
10602+ err = wkq_err;
10603+ if (unlikely(err > 0
10604+ && copy_to_user(ubuf, args.kbuf, err))) {
10605+ err = -EFAULT;
10606+ goto out_free;
10607+ } else if (!err)
10608+ break;
10609+ else if (unlikely(err < 0))
10610+ goto out_free;
10611+ count -= err;
10612+ /* do not read too much because of file i/o pointer */
10613+ if (count < args.count)
10614+ args.count = count;
10615+ ubuf += err;
10616+ read += err;
10617+ } while (count);
10618+ smp_mb(); /* flush ubuf */
10619+ err = read;
10620+
10621+ out_free:
10622+ kfree(args.kbuf);
10623+ out:
10624+ return err;
10625+ }
10626+}
10627+
10628+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
10629+ int dlgt)
10630+{
10631+ if (!dlgt)
10632+ return do_vfsub_read_k(file, kbuf, count, ppos);
10633+ else {
10634+ ssize_t err;
10635+ int wkq_err;
10636+ struct read_args args = {
10637+ .errp = &err,
10638+ .file = file,
10639+ .count = count,
10640+ .ppos = ppos
10641+ };
10642+ args.kbuf = kbuf;
10643+ wkq_err = au_wkq_wait(call_read_k, &args, /*dlgt*/1);
10644+ if (unlikely(wkq_err))
10645+ err = wkq_err;
10646+ return err;
10647+ }
10648+}
10649+
10650+struct write_args {
10651+ ssize_t *errp;
10652+ struct file *file;
10653+ union {
10654+ void *kbuf;
10655+ const char __user *ubuf;
10656+ };
10657+ size_t count;
10658+ loff_t *ppos;
10659+ struct vfsub_args *vargs;
10660+};
10661+
10662+static void call_write_k(void *args)
10663+{
10664+ struct write_args *a = args;
10665+ vfsub_ignore(a->vargs);
10666+ *a->errp = do_vfsub_write_k(a->file, a->kbuf, a->count, a->ppos);
10667+ if (unlikely(*a->errp <= 0))
10668+ vfsub_unignore(a->vargs);
10669+ au_dbg_hin_list(a->vargs);
10670+}
10671+
10672+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
10673+ loff_t *ppos, struct vfsub_args *vargs)
10674+{
10675+ ssize_t err;
10676+
10677+ if (!vfsub_ftest(vargs->flags, DLGT)) {
10678+ vfsub_ignore(vargs);
10679+ err = do_vfsub_write_u(file, ubuf, count, ppos);
10680+ if (unlikely(err <= 0))
10681+ vfsub_unignore(vargs);
10682+ au_dbg_hin_list(vargs);
10683+ } else {
10684+ ssize_t written;
10685+ int wkq_err;
10686+ struct write_args args = {
10687+ .errp = &err,
10688+ .file = file,
10689+ .count = count,
10690+ .ppos = ppos,
10691+ .vargs = vargs
10692+ };
10693+
10694+ if (!count)
10695+ return 0;
10696+
10697+ /*
10698+ * workaround an application bug.
10699+ * generally, read(2) or write(2) may return the value shorter
10700+ * than requested. But many applications don't support it,
10701+ * for example bash.
10702+ */
10703+ err = -ENOMEM;
10704+ if (args.count > PAGE_SIZE)
10705+ args.count = PAGE_SIZE;
10706+ args.kbuf = kmalloc(args.count, GFP_NOFS);
10707+ if (unlikely(!args.kbuf))
10708+ goto out;
10709+
10710+ written = 0;
10711+ do {
10712+ if (unlikely(copy_from_user(args.kbuf, ubuf,
10713+ args.count))) {
10714+ err = -EFAULT;
10715+ goto out_free;
10716+ }
10717+
10718+ wkq_err = au_wkq_wait(call_write_k, &args, /*dlgt*/1);
10719+ if (unlikely(wkq_err))
10720+ err = wkq_err;
10721+ if (err > 0) {
10722+ count -= err;
10723+ if (count < args.count)
10724+ args.count = count;
10725+ ubuf += err;
10726+ written += err;
10727+ } else if (!err)
10728+ break;
10729+ else if (unlikely(err < 0))
10730+ goto out_free;
10731+ } while (count);
10732+ err = written;
10733+
10734+ out_free:
10735+ kfree(args.kbuf);
10736+ }
10737+ out:
10738+ return err;
10739+}
10740+
10741+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
10742+ struct vfsub_args *vargs)
10743+{
10744+ ssize_t err;
10745+ struct write_args args = {
10746+ .errp = &err,
10747+ .file = file,
10748+ .count = count,
10749+ .ppos = ppos,
10750+ .vargs = vargs
10751+ };
10752+
10753+ args.kbuf = kbuf;
10754+ if (!vfsub_ftest(vargs->flags, DLGT))
10755+ call_write_k(&args);
10756+ else {
10757+ int wkq_err;
10758+ wkq_err = au_wkq_wait(call_write_k, &args, /*dlgt*/1);
10759+ if (unlikely(wkq_err))
10760+ err = wkq_err;
10761+ }
10762+ return err;
10763+}
10764+
10765+struct readdir_args {
10766+ int *errp;
10767+ struct file *file;
10768+ filldir_t filldir;
10769+ void *arg;
10770+};
10771+
10772+static void call_readdir(void *args)
10773+{
10774+ struct readdir_args *a = args;
10775+ *a->errp = do_vfsub_readdir(a->file, a->filldir, a->arg);
10776+}
10777+
10778+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
10779+{
10780+ if (!dlgt)
10781+ return do_vfsub_readdir(file, filldir, arg);
10782+ else {
10783+ int err, wkq_err;
10784+ struct readdir_args args = {
10785+ .errp = &err,
10786+ .file = file,
10787+ .filldir = filldir,
10788+ .arg = arg
10789+ };
10790+ wkq_err = au_wkq_wait(call_readdir, &args, /*dlgt*/1);
10791+ if (unlikely(wkq_err))
10792+ err = wkq_err;
10793+ return err;
10794+ }
10795+}
10796+
10797+/* ---------------------------------------------------------------------- */
10798+
10799+struct splice_to_args {
10800+ long *errp;
10801+ struct file *in;
10802+ loff_t *ppos;
10803+ struct pipe_inode_info *pipe;
10804+ size_t len;
10805+ unsigned int flags;
10806+};
10807+
10808+static void call_splice_to(void *args)
10809+{
10810+ struct splice_to_args *a = args;
10811+ *a->errp = do_vfsub_splice_to(a->in, a->ppos, a->pipe, a->len,
10812+ a->flags);
10813+}
10814+
10815+long vfsub_splice_to(struct file *in, loff_t *ppos,
10816+ struct pipe_inode_info *pipe, size_t len,
10817+ unsigned int flags, int dlgt)
10818+{
10819+ if (!dlgt)
10820+ return do_vfsub_splice_to(in, ppos, pipe, len, flags);
10821+ else {
10822+ long err;
10823+ int wkq_err;
10824+ struct splice_to_args args = {
10825+ .errp = &err,
10826+ .in = in,
10827+ .ppos = ppos,
10828+ .pipe = pipe,
10829+ .len = len,
10830+ .flags = flags
10831+ };
10832+ wkq_err = au_wkq_wait(call_splice_to, &args, /*dlgt*/1);
10833+ if (unlikely(wkq_err))
10834+ err = wkq_err;
10835+ return err;
10836+ }
10837+}
10838+
10839+struct splice_from_args {
10840+ long *errp;
10841+ struct pipe_inode_info *pipe;
10842+ struct file *out;
10843+ loff_t *ppos;
10844+ size_t len;
10845+ unsigned int flags;
10846+ struct vfsub_args *vargs;
10847+};
10848+
10849+static void call_splice_from(void *args)
10850+{
10851+ struct splice_from_args *a = args;
10852+ vfsub_ignore(a->vargs);
10853+ *a->errp = do_vfsub_splice_from(a->pipe, a->out, a->ppos, a->len,
10854+ a->flags);
10855+ if (unlikely(*a->errp < 0))
10856+ vfsub_unignore(a->vargs);
10857+ au_dbg_hin_list(a->vargs);
10858+}
10859+
10860+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
10861+ loff_t *ppos, size_t len, unsigned int flags,
10862+ struct vfsub_args *vargs)
10863+{
10864+ long err;
10865+ struct splice_from_args args = {
10866+ .errp = &err,
10867+ .pipe = pipe,
10868+ .out = out,
10869+ .ppos = ppos,
10870+ .len = len,
10871+ .flags = flags,
10872+ .vargs = vargs
10873+ };
10874+
10875+ if (!vfsub_ftest(vargs->flags, DLGT))
10876+ call_splice_from(&args);
10877+ else {
10878+ int wkq_err;
10879+ wkq_err = au_wkq_wait(call_splice_from, &args, /*dlgt*/1);
10880+ if (unlikely(wkq_err))
10881+ err = wkq_err;
10882+ }
10883+ return err;
10884+}
10885+
10886+/* ---------------------------------------------------------------------- */
10887+
10888+struct getattr_args {
10889+ int *errp;
10890+ struct vfsmount *mnt;
10891+ struct dentry *dentry;
10892+ struct kstat *st;
10893+};
10894+
10895+static void call_getattr(void *args)
10896+{
10897+ struct getattr_args *a = args;
10898+ *a->errp = do_vfsub_getattr(a->mnt, a->dentry, a->st);
10899+}
10900+
10901+int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st,
10902+ int dlgt)
10903+{
10904+ if (!dlgt)
10905+ return do_vfsub_getattr(mnt, dentry, st);
10906+ else {
10907+ int err, wkq_err;
10908+ struct getattr_args args = {
10909+ .errp = &err,
10910+ .mnt = mnt,
10911+ .dentry = dentry,
10912+ .st = st
10913+ };
10914+ wkq_err = au_wkq_wait(call_getattr, &args, /*dlgt*/1);
10915+ if (unlikely(wkq_err))
10916+ err = wkq_err;
10917+ return err;
10918+ }
10919+}
10920diff -urN linux/fs/aufs/hinotify.c linux-aufs/fs/aufs/hinotify.c
10921--- linux/fs/aufs/hinotify.c 1970-01-01 01:00:00.000000000 +0100
10922+++ linux-aufs/fs/aufs/hinotify.c 2009-03-12 16:18:04.000000000 +0100
10923@@ -0,0 +1,1146 @@
10924+/*
10925+ * Copyright (C) 2005-2009 Junjiro Okajima
10926+ *
10927+ * This program, aufs is free software; you can redistribute it and/or modify
10928+ * it under the terms of the GNU General Public License as published by
10929+ * the Free Software Foundation; either version 2 of the License, or
10930+ * (at your option) any later version.
10931+ *
10932+ * This program is distributed in the hope that it will be useful,
10933+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10934+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10935+ * GNU General Public License for more details.
10936+ *
10937+ * You should have received a copy of the GNU General Public License
10938+ * along with this program; if not, write to the Free Software
10939+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10940+ */
10941+
10942+/*
10943+ * internal/hidden inotify handler
10944+ *
10945+ * $Id$
10946+ */
10947+
10948+#include "aufs.h"
10949+
10950+/*
10951+#ifdef DbgInotify
10952+#define AuDbgHin(args...) AuDbg(##args)
10953+#else
10954+#define AuDbgHin(args...) do {} while ()
10955+#endif
10956+*/
10957+
10958+static struct inotify_handle *in_handle;
10959+
10960+AuCacheFuncs(hinotify, AuCache_HINOTIFY);
10961+
10962+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
10963+ struct inode *h_inode)
10964+{
10965+ int err;
10966+ struct au_hinotify *hin;
10967+ s32 wd;
10968+
10969+ LKTRTrace("i%lu, hi%lu\n", inode->i_ino, h_inode->i_ino);
10970+
10971+ err = -ENOMEM;
10972+ hin = au_cache_alloc_hinotify();
10973+ if (hin) {
10974+ AuDebugOn(hinode->hi_notify);
10975+ hinode->hi_notify = hin;
10976+ au_spl_init(&hin->hin_ignore);
10977+ hin->hin_aufs_inode = inode;
10978+
10979+ inotify_init_watch(&hin->hin_watch);
10980+ wd = inotify_add_watch(in_handle, &hin->hin_watch, h_inode,
10981+ AuInMask);
10982+ if (wd >= 0)
10983+ return 0; /* success */
10984+
10985+ err = wd;
10986+ put_inotify_watch(&hin->hin_watch);
10987+ au_cache_free_hinotify(hin);
10988+ hinode->hi_notify = NULL;
10989+ }
10990+
10991+ AuTraceErr(err);
10992+ return err;
10993+}
10994+
10995+void au_hin_free(struct au_hinode *hinode)
10996+{
10997+ int err;
10998+ struct au_hinotify *hin;
10999+
11000+ AuTraceEnter();
11001+
11002+ hin = hinode->hi_notify;
11003+ if (hin) {
11004+ err = 0;
11005+ if (atomic_read(&hin->hin_watch.count))
11006+ err = inotify_rm_watch(in_handle, &hin->hin_watch);
11007+ if (unlikely(err))
11008+ /* it means the watch is already removed */
11009+ LKTRTrace("failed inotify_rm_watch() %d\n", err);
11010+ au_cache_free_hinotify(hin);
11011+ hinode->hi_notify = NULL;
11012+ }
11013+}
11014+
11015+/* ---------------------------------------------------------------------- */
11016+
11017+void au_hin_ctl(struct au_hinode *hinode, const __u32 mask)
11018+{
11019+ struct inode *h_inode;
11020+ struct inotify_watch *watch;
11021+
11022+ h_inode = hinode->hi_inode;
11023+ LKTRTrace("hi%lu, sb %p, 0x%x\n", h_inode->i_ino, h_inode->i_sb, mask);
11024+ IMustLock(h_inode);
11025+ if (!hinode->hi_notify)
11026+ return;
11027+
11028+ watch = &hinode->hi_notify->hin_watch;
11029+#if 0 /* reserved for future use */
11030+ {
11031+ u32 wd;
11032+ wd = inotify_find_update_watch(in_handle, h_inode, mask);
11033+ AuTraceErr(wd);
11034+ /* ignore an err; */
11035+ }
11036+#else
11037+ /* struct inotify_handle is hidden */
11038+ mutex_lock(&h_inode->inotify_mutex);
11039+ /* mutex_lock(&watch->ih->mutex); */
11040+ watch->mask = mask;
11041+ /* mutex_unlock(&watch->ih->mutex); */
11042+ mutex_unlock(&h_inode->inotify_mutex);
11043+#endif
11044+ LKTRTrace("watch %p, mask %u\n", watch, watch->mask);
11045+}
11046+
11047+void au_reset_hinotify(struct inode *inode, unsigned int flags)
11048+{
11049+ aufs_bindex_t bindex, bend;
11050+ struct inode *hi;
11051+ struct dentry *iwhdentry;
11052+
11053+ LKTRTrace("i%lu, 0x%x\n", inode->i_ino, flags);
11054+
11055+ bend = au_ibend(inode);
11056+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
11057+ hi = au_h_iptr(inode, bindex);
11058+ if (hi) {
11059+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
11060+ iwhdentry = au_hi_wh(inode, bindex);
11061+ if (iwhdentry)
11062+ dget(iwhdentry);
11063+ au_igrab(hi);
11064+ au_set_h_iptr(inode, bindex, NULL, 0);
11065+ au_set_h_iptr(inode, bindex, au_igrab(hi),
11066+ flags & ~AuHi_XINO);
11067+ iput(hi);
11068+ dput(iwhdentry);
11069+ /* mutex_unlock(&hi->i_mutex); */
11070+ }
11071+ }
11072+}
11073+
11074+/* ---------------------------------------------------------------------- */
11075+
11076+void au_unpin_gp(struct au_pin *args)
11077+{
11078+ struct au_pin1 *gp;
11079+
11080+ gp = au_pin_gp(args);
11081+ AuDebugOn(!gp);
11082+ if (gp->dentry)
11083+ LKTRTrace("%.*s\n", AuDLNPair(gp->dentry));
11084+ else
11085+ AuTraceEnter();
11086+
11087+ au_do_unpin(gp, NULL);
11088+}
11089+
11090+int au_hin_verify_gen(struct dentry *dentry)
11091+{
11092+ struct super_block *sb = dentry->d_sb;
11093+ au_gen_t sigen;
11094+ struct inode *inode;
11095+
11096+ if (!au_opt_test(au_mntflags(sb), UDBA_INOTIFY))
11097+ return 0;
11098+
11099+ sigen = au_sigen(dentry->d_sb);
11100+ inode = dentry->d_inode;
11101+ return au_digen(dentry) != sigen
11102+ || (inode && au_iigen(inode) != sigen);
11103+}
11104+
11105+/* ---------------------------------------------------------------------- */
11106+
11107+/* cf. fsnotify_change() */
11108+__u32 vfsub_events_notify_change(struct iattr *ia)
11109+{
11110+ __u32 events;
11111+ const unsigned int amtime = (ATTR_ATIME | ATTR_MTIME);
11112+
11113+ events = 0;
11114+ if ((ia->ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE))
11115+ || (ia->ia_valid & amtime) == amtime)
11116+ events |= IN_ATTRIB;
11117+ if ((ia->ia_valid & ATTR_SIZE)
11118+ || (ia->ia_valid & amtime) == ATTR_MTIME)
11119+ events |= IN_MODIFY;
11120+ return events;
11121+}
11122+
11123+void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events,
11124+ struct au_hinode *hinode)
11125+{
11126+ struct au_hinotify *hin;
11127+ struct super_block *sb;
11128+ struct au_hin_ignore *ign;
11129+
11130+ if (!hinode)
11131+ return;
11132+
11133+ hin = hinode->hi_notify;
11134+ if (!hin || !hin->hin_watch.mask)
11135+ return;
11136+
11137+ sb = hin->hin_aufs_inode->i_sb;
11138+ AuDebugOn(!au_opt_test(au_mntflags(sb), UDBA_INOTIFY));
11139+
11140+ ign = vargs->ignore + vargs->nignore++;
11141+ ign->ign_events = events;
11142+ ign->ign_handled = 0;
11143+ ign->ign_hinode = hinode;
11144+
11145+ {
11146+ struct inode *h_inode;
11147+ h_inode = hinode->hi_inode;
11148+ if (!mutex_is_locked(&h_inode->i_mutex))
11149+ au_dbg_blocked();
11150+ IMustLock(h_inode);
11151+ }
11152+}
11153+
11154+static void au_hin_ignore(struct au_hin_ignore *ign)
11155+{
11156+ struct au_hinode *hinode;
11157+ __u32 events;
11158+ struct au_hinotify *hin;
11159+ struct inode *h_inode;
11160+
11161+ hinode = ign->ign_hinode;
11162+ events = ign->ign_events;
11163+ LKTRTrace("0x%x\n", events);
11164+ AuDebugOn(!hinode || !events);
11165+
11166+ hin = hinode->hi_notify;
11167+ h_inode = hinode->hi_inode;
11168+ if (h_inode && hin) {
11169+ LKTRTrace("hi%lu\n", h_inode->i_ino);
11170+#ifdef DbgInotify
11171+ AuDbg("hi%lu, 0x%x\n", h_inode->i_ino, events);
11172+#endif
11173+
11174+ au_spl_add(&ign->ign_list, &hin->hin_ignore);
11175+ /* AuDbg("list_add %p, 0x%x\n", ign, events); */
11176+ }
11177+#if 1 /* todo: test dlgt */
11178+ else
11179+ /*
11180+ * it may happen by this scenario.
11181+ * - a file and its parent dir exist on two branches
11182+ * - a file on the upper branch is opened
11183+ * - the parent dir and the file are removed by udba
11184+ * - the parent is re-accessed, and new dentry/inode in
11185+ * aufs is generated for it, based upon the one on the lower
11186+ * branch
11187+ * - the opened file is re-accessed, re-validated, and it may be
11188+ * re-connected to the new parent dentry
11189+ * it means the file in aufs cannot get the actual removed
11190+ * parent dir on the branch.
11191+ */
11192+ INIT_LIST_HEAD(&ign->ign_list);
11193+#endif
11194+}
11195+
11196+static void au_hin_unignore(struct au_hin_ignore *ign)
11197+{
11198+ struct au_hinode *hinode;
11199+ __u32 events;
11200+ struct au_hinotify *hin;
11201+ struct inode *h_inode;
11202+
11203+ hinode = ign->ign_hinode;
11204+ events = ign->ign_events;
11205+ LKTRTrace("0x%x\n", events);
11206+ /* AuDbg("0x%x\n", events); */
11207+ AuDebugOn(!hinode || !events);
11208+
11209+ hin = hinode->hi_notify;
11210+ h_inode = hinode->hi_inode;
11211+ if (!h_inode || !hin)
11212+ return;
11213+ LKTRTrace("hi%lu\n", h_inode->i_ino);
11214+#ifdef DbgInotify
11215+ AuDbg("hi%lu, 0x%x\n", h_inode->i_ino, events);
11216+#endif
11217+
11218+ spin_lock(&hin->hin_ignore.spin);
11219+ au_hin_list_del(&ign->ign_list);
11220+ spin_unlock(&hin->hin_ignore.spin);
11221+ /* AuDbg("list_del %p, 0x%x\n", ign, events); */
11222+}
11223+
11224+static int au_hin_test_ignore(u32 mask, struct au_hinotify *hin)
11225+{
11226+ int do_ignore;
11227+ u32 events;
11228+ struct au_hin_ignore *ign, *tmp;
11229+ struct list_head *head;
11230+
11231+ do_ignore = 0;
11232+ head = &hin->hin_ignore.head;
11233+ spin_lock(&hin->hin_ignore.spin);
11234+ list_for_each_entry_safe(ign, tmp, head, ign_list) {
11235+ /* AuDbg("ign %p\n", ign); */
11236+ if (ign->ign_pid == current->pid) {
11237+ events = (mask & ign->ign_events);
11238+ if (events) {
11239+ do_ignore = 1;
11240+ ign->ign_handled |= events;
11241+ if (ign->ign_events == ign->ign_handled) {
11242+ list_del_init(&ign->ign_list);
11243+ /*
11244+ AuDbg("list_del %p, 0x%x\n",
11245+ ign, events);
11246+ */
11247+ }
11248+ break;
11249+ }
11250+ }
11251+ }
11252+ spin_unlock(&hin->hin_ignore.spin);
11253+
11254+ return do_ignore;
11255+}
11256+
11257+void vfsub_ignore(struct vfsub_args *vargs)
11258+{
11259+ int n;
11260+ struct au_hin_ignore *ign;
11261+ struct super_block *sb;
11262+ struct au_hinode *hinode;
11263+ struct inode *h_inode;
11264+
11265+ n = vargs->nignore;
11266+ if (!n)
11267+ return;
11268+
11269+ ign = vargs->ignore;
11270+ hinode = ign->ign_hinode;
11271+ sb = hinode->hi_notify->hin_aufs_inode->i_sb;
11272+ h_inode = hinode->hi_inode;
11273+ if (au_opt_test(au_mntflags(sb), UDBA_INOTIFY)) {
11274+ if (!mutex_is_locked(&h_inode->i_mutex))
11275+ au_dbg_blocked();
11276+ IMustLock(h_inode);
11277+ }
11278+ while (n-- > 0) {
11279+ ign->ign_pid = current->pid;
11280+ au_hin_ignore(ign++);
11281+ }
11282+}
11283+
11284+void vfsub_unignore(struct vfsub_args *vargs)
11285+{
11286+ int n;
11287+ struct au_hin_ignore *ign;
11288+
11289+ n = vargs->nignore;
11290+ if (!n)
11291+ return;
11292+
11293+ ign = vargs->ignore;
11294+ while (n-- > 0)
11295+ au_hin_unignore(ign++);
11296+}
11297+
11298+#ifdef CONFIG_AUFS_DEBUG
11299+void au_dbg_hin_list(struct vfsub_args *vargs)
11300+{
11301+ int n;
11302+ struct au_hin_ignore *ign;
11303+
11304+ n = vargs->nignore;
11305+ if (!n)
11306+ return;
11307+
11308+ ign = vargs->ignore;
11309+ while (n-- > 0) {
11310+ /* AuDebugOn(!list_empty(&ign++->ign_list)); */
11311+ if (list_empty(&ign++->ign_list))
11312+ continue;
11313+ ign--;
11314+ AuDbg("%d: pid %d, 0x%x\n",
11315+ n + 1, ign->ign_pid, ign->ign_events);
11316+ au_hin_unignore(ign);
11317+ ign++;
11318+ au_dbg_blocked();
11319+ }
11320+}
11321+#endif
11322+
11323+/* ---------------------------------------------------------------------- */
11324+
11325+static char *in_name(u32 mask)
11326+{
11327+#ifdef CONFIG_AUFS_DEBUG
11328+#define test_ret(flag) if (mask & flag) \
11329+ return #flag;
11330+ test_ret(IN_ACCESS);
11331+ test_ret(IN_MODIFY);
11332+ test_ret(IN_ATTRIB);
11333+ test_ret(IN_CLOSE_WRITE);
11334+ test_ret(IN_CLOSE_NOWRITE);
11335+ test_ret(IN_OPEN);
11336+ test_ret(IN_MOVED_FROM);
11337+ test_ret(IN_MOVED_TO);
11338+ test_ret(IN_CREATE);
11339+ test_ret(IN_DELETE);
11340+ test_ret(IN_DELETE_SELF);
11341+ test_ret(IN_MOVE_SELF);
11342+ test_ret(IN_UNMOUNT);
11343+ test_ret(IN_Q_OVERFLOW);
11344+ test_ret(IN_IGNORED);
11345+ return "";
11346+#undef test_ret
11347+#else
11348+ return "??";
11349+#endif
11350+}
11351+
11352+/* ---------------------------------------------------------------------- */
11353+
11354+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
11355+ struct inode *dir)
11356+{
11357+ struct dentry *dentry, *d, *parent;
11358+ struct qstr *dname;
11359+
11360+ LKTRTrace("%.*s, dir%lu\n", nlen, name, dir->i_ino);
11361+
11362+ parent = d_find_alias(dir);
11363+ if (!parent)
11364+ return NULL;
11365+
11366+ dentry = NULL;
11367+ spin_lock(&dcache_lock);
11368+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
11369+ LKTRTrace("%.*s\n", AuDLNPair(d));
11370+ dname = &d->d_name;
11371+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
11372+ continue;
11373+ if (!atomic_read(&d->d_count) || !d->d_fsdata) {
11374+ spin_lock(&d->d_lock);
11375+ __d_drop(d);
11376+ spin_unlock(&d->d_lock);
11377+ continue;
11378+ }
11379+
11380+ dentry = dget(d);
11381+ break;
11382+ }
11383+ spin_unlock(&dcache_lock);
11384+ dput(parent);
11385+
11386+ if (dentry) {
11387+#if 0
11388+ lktr_set_pid(current->pid, LktrArrayPid);
11389+ AuDbgDentry(dentry);
11390+ lktr_clear_pid(current->pid, LktrArrayPid);
11391+#endif
11392+ di_write_lock_child(dentry);
11393+ }
11394+ return dentry;
11395+}
11396+
11397+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
11398+ aufs_bindex_t bindex, ino_t h_ino)
11399+{
11400+ struct inode *inode;
11401+ struct au_xino_entry xinoe;
11402+ int err;
11403+
11404+ LKTRTrace("b%d, hi%lu\n", bindex, (unsigned long)h_ino);
11405+ AuDebugOn(!au_opt_test_xino(au_mntflags(sb)));
11406+
11407+ inode = NULL;
11408+ err = au_xino_read(sb, bindex, h_ino, &xinoe);
11409+ if (!err && xinoe.ino)
11410+ inode = ilookup(sb, xinoe.ino);
11411+ if (!inode)
11412+ goto out;
11413+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11414+ AuWarn("wrong root branch\n");
11415+ iput(inode);
11416+ inode = NULL;
11417+ goto out;
11418+ }
11419+
11420+ ii_write_lock_child(inode);
11421+
11422+ out:
11423+ return inode;
11424+}
11425+
11426+static int hin_xino(struct inode *inode, struct inode *h_inode)
11427+{
11428+ int err;
11429+ aufs_bindex_t bindex, bend, bfound, bstart;
11430+ struct inode *h_i;
11431+
11432+ LKTRTrace("i%lu, hi%lu\n", inode->i_ino, h_inode->i_ino);
11433+
11434+ err = 0;
11435+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11436+ AuWarn("branch root dir was changed\n");
11437+ goto out;
11438+ }
11439+
11440+ bfound = -1;
11441+ bend = au_ibend(inode);
11442+ bstart = au_ibstart(inode);
11443+#if 0 /* reserved for future use */
11444+ if (bindex == bend) {
11445+ /* keep this ino in rename case */
11446+ goto out;
11447+ }
11448+#endif
11449+ for (bindex = bstart; bindex <= bend; bindex++) {
11450+ if (au_h_iptr(inode, bindex) == h_inode) {
11451+ bfound = bindex;
11452+ break;
11453+ }
11454+ }
11455+ if (bfound < 0)
11456+ goto out;
11457+
11458+ for (bindex = bstart; bindex <= bend; bindex++) {
11459+ h_i = au_h_iptr(inode, bindex);
11460+ if (h_i)
11461+ err = au_xino_write0(inode->i_sb, bindex, h_i->i_ino,
11462+ 0);
11463+ /* ignore this error */
11464+ /* bad action? */
11465+ }
11466+
11467+ /* children inode number will be broken */
11468+
11469+ out:
11470+ AuTraceErr(err);
11471+ return err;
11472+}
11473+
11474+static int hin_gen_tree(struct dentry *dentry)
11475+{
11476+ int err, i, j, ndentry;
11477+ struct au_dcsub_pages dpages;
11478+ struct au_dpage *dpage;
11479+ struct dentry **dentries;
11480+
11481+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
11482+
11483+ err = au_dpages_init(&dpages, GFP_NOFS);
11484+ if (unlikely(err))
11485+ goto out;
11486+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
11487+ if (unlikely(err))
11488+ goto out_dpages;
11489+
11490+ for (i = 0; i < dpages.ndpage; i++) {
11491+ dpage = dpages.dpages + i;
11492+ dentries = dpage->dentries;
11493+ ndentry = dpage->ndentry;
11494+ for (j = 0; j < ndentry; j++) {
11495+ struct dentry *d;
11496+ d = dentries[j];
11497+ LKTRTrace("%.*s\n", AuDLNPair(d));
11498+ if (IS_ROOT(d))
11499+ continue;
11500+
11501+ d_drop(d);
11502+ au_digen_dec(d);
11503+ if (d->d_inode)
11504+ /* todo: reset children xino?
11505+ cached children only? */
11506+ au_iigen_dec(d->d_inode);
11507+ }
11508+ }
11509+
11510+ out_dpages:
11511+ au_dpages_free(&dpages);
11512+
11513+ /* discard children */
11514+ dentry_unhash(dentry);
11515+ dput(dentry);
11516+ out:
11517+ AuTraceErr(err);
11518+ return err;
11519+}
11520+
11521+/*
11522+ * return 0 if processed.
11523+ */
11524+static int hin_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
11525+ const unsigned int isdir)
11526+{
11527+ int err;
11528+ struct dentry *d;
11529+ struct qstr *dname;
11530+
11531+ LKTRTrace("%.*s, i%lu\n", nlen, name, inode->i_ino);
11532+
11533+ err = 1;
11534+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11535+ AuWarn("branch root dir was changed\n");
11536+ err = 0;
11537+ goto out;
11538+ }
11539+
11540+ if (!isdir) {
11541+ AuDebugOn(!name);
11542+ au_iigen_dec(inode);
11543+ spin_lock(&dcache_lock);
11544+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
11545+ dname = &d->d_name;
11546+ if (dname->len != nlen
11547+ && memcmp(dname->name, name, nlen))
11548+ continue;
11549+ err = 0;
11550+ spin_lock(&d->d_lock);
11551+ __d_drop(d);
11552+ au_digen_dec(d);
11553+ spin_unlock(&d->d_lock);
11554+ break;
11555+ }
11556+ spin_unlock(&dcache_lock);
11557+ } else {
11558+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
11559+ d = d_find_alias(inode);
11560+ if (!d) {
11561+ au_iigen_dec(inode);
11562+ goto out;
11563+ }
11564+
11565+ dname = &d->d_name;
11566+ if (dname->len == nlen && !memcmp(dname->name, name, nlen))
11567+ err = hin_gen_tree(d);
11568+ dput(d);
11569+ }
11570+
11571+ out:
11572+ AuTraceErr(err);
11573+ return err;
11574+}
11575+
11576+static int hin_gen_by_name(struct dentry *dentry, const unsigned int isdir)
11577+{
11578+ int err;
11579+ struct inode *inode;
11580+
11581+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
11582+
11583+ inode = dentry->d_inode;
11584+ if (IS_ROOT(dentry)
11585+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
11586+ ) {
11587+ AuWarn("branch root dir was changed\n");
11588+ return 0;
11589+ }
11590+
11591+ err = 0;
11592+ if (!isdir) {
11593+ d_drop(dentry);
11594+ au_digen_dec(dentry);
11595+ if (inode)
11596+ au_iigen_dec(inode);
11597+ } else {
11598+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
11599+ if (inode)
11600+ err = hin_gen_tree(dentry);
11601+ }
11602+
11603+ AuTraceErr(err);
11604+ return err;
11605+}
11606+
11607+static void hin_attr(struct inode *inode, struct inode *h_inode)
11608+{
11609+ struct dentry *h_dentry;
11610+
11611+ LKTRTrace("i%lu, hi%lu\n", inode->i_ino, h_inode->i_ino);
11612+
11613+ if (au_h_iptr(inode, au_ibstart(inode)) != h_inode)
11614+ return;
11615+
11616+ h_dentry = d_find_alias(h_inode);
11617+ if (h_dentry) {
11618+ au_update_fuse_h_inode(NULL, h_dentry);
11619+ /* ignore an error*/
11620+ dput(h_dentry);
11621+ }
11622+
11623+ au_cpup_attr_all(inode, /*force*/1);
11624+}
11625+
11626+/* ---------------------------------------------------------------------- */
11627+
11628+/* hinotify job flags */
11629+#define AuHinJob_XINO0 1
11630+#define AuHinJob_GEN (1 << 1)
11631+#define AuHinJob_DIRENT (1 << 2)
11632+#define AuHinJob_ATTR (1 << 3)
11633+#define AuHinJob_ISDIR (1 << 4)
11634+#define AuHinJob_TRYXINO0 (1 << 5)
11635+#define AuHinJob_MNTPNT (1 << 6)
11636+#define au_ftest_hinjob(flags, name) ((flags) & AuHinJob_##name)
11637+#define au_fset_hinjob(flags, name) { (flags) |= AuHinJob_##name; }
11638+#define au_fclr_hinjob(flags, name) { (flags) &= ~AuHinJob_##name; }
11639+
11640+struct hin_job_args {
11641+ unsigned int flags;
11642+ struct inode *inode, *h_inode, *dir, *h_dir;
11643+ struct dentry *dentry;
11644+ char *h_name;
11645+ int h_nlen;
11646+};
11647+
11648+static int hin_job(struct hin_job_args *a)
11649+{
11650+ const unsigned int isdir = au_ftest_hinjob(a->flags, ISDIR);
11651+
11652+ /* reset xino */
11653+ if (au_ftest_hinjob(a->flags, XINO0) && a->inode)
11654+ hin_xino(a->inode, a->h_inode);
11655+ /* ignore this error */
11656+
11657+ if (au_ftest_hinjob(a->flags, TRYXINO0)
11658+ && a->inode
11659+ && a->h_inode) {
11660+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11661+ if (!a->h_inode->i_nlink)
11662+ hin_xino(a->inode, a->h_inode);
11663+ /* ignore this error */
11664+ mutex_unlock(&a->h_inode->i_mutex);
11665+ }
11666+
11667+ /* make the generation obsolete */
11668+ if (au_ftest_hinjob(a->flags, GEN)) {
11669+ int err = -1;
11670+ if (a->inode)
11671+ err = hin_gen_by_inode(a->h_name, a->h_nlen, a->inode,
11672+ isdir);
11673+ if (err && a->dentry)
11674+ hin_gen_by_name(a->dentry, isdir);
11675+ /* ignore this error */
11676+ }
11677+
11678+ /* make dir entries obsolete */
11679+ if (au_ftest_hinjob(a->flags, DIRENT) && a->inode) {
11680+ struct au_vdir *vdir;
11681+ IiMustWriteLock(a->inode);
11682+ vdir = au_ivdir(a->inode);
11683+ if (vdir)
11684+ vdir->vd_jiffy = 0;
11685+ /* IMustLock(a->inode); */
11686+ /* a->inode->i_version++; */
11687+ }
11688+
11689+ /* update the attr */
11690+ if (au_ftest_hinjob(a->flags, ATTR) && a->inode && a->h_inode) {
11691+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11692+ hin_attr(a->inode, a->h_inode);
11693+ mutex_unlock(&a->h_inode->i_mutex);
11694+ }
11695+
11696+ /* can do nothing but warn */
11697+ if (au_ftest_hinjob(a->flags, MNTPNT)
11698+ && a->dentry
11699+ && d_mountpoint(a->dentry))
11700+ AuWarn("mount-point %.*s is removed or renamed\n",
11701+ AuDLNPair(a->dentry));
11702+
11703+ return 0;
11704+}
11705+
11706+/* ---------------------------------------------------------------------- */
11707+
11708+enum { CHILD, PARENT };
11709+struct postproc_args {
11710+ struct inode *h_dir, *dir, *h_child_inode;
11711+ u32 mask;
11712+ unsigned int flags[2];
11713+ unsigned int h_child_nlen;
11714+ char h_child_name[];
11715+};
11716+
11717+static void postproc(void *_args)
11718+{
11719+ struct postproc_args *a = _args;
11720+ struct super_block *sb;
11721+ aufs_bindex_t bindex, bend, bfound;
11722+ unsigned char xino, try_iput;
11723+ int err;
11724+ struct inode *inode;
11725+ ino_t h_ino;
11726+ struct hin_job_args args;
11727+ struct dentry *dentry;
11728+ struct au_sbinfo *sbinfo;
11729+
11730+ AuDebugOn(!_args);
11731+ AuDebugOn(!a->h_dir);
11732+ AuDebugOn(!a->dir);
11733+ AuDebugOn(!a->mask);
11734+ LKTRTrace("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
11735+ a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
11736+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
11737+
11738+ inode = NULL;
11739+ dentry = NULL;
11740+ /*
11741+ * do not lock a->dir->i_mutex here
11742+ * because of d_revalidate() may cause a deadlock.
11743+ */
11744+#if 0
11745+ /*
11746+ * just wait for the dir becoming non-busy.
11747+ * for instance, prevent NFSD lookup from "nlink == 0" message.
11748+ * but it is not guranteed.
11749+ */
11750+ mutex_lock(&a->dir->i_mutex);
11751+ mutex_unlock(&a->dir->i_mutex);
11752+#endif
11753+
11754+ sb = a->dir->i_sb;
11755+ AuDebugOn(!sb);
11756+ sbinfo = au_sbi(sb);
11757+ AuDebugOn(!sbinfo);
11758+ /* big aufs lock */
11759+ si_noflush_write_lock(sb);
11760+
11761+ ii_read_lock_parent(a->dir);
11762+ bfound = -1;
11763+ bend = au_ibend(a->dir);
11764+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
11765+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
11766+ bfound = bindex;
11767+ break;
11768+ }
11769+ ii_read_unlock(a->dir);
11770+ if (unlikely(bfound < 0))
11771+ goto out;
11772+
11773+ xino = !!au_opt_test_xino(au_mntflags(sb));
11774+ h_ino = 0;
11775+ if (a->h_child_inode)
11776+ h_ino = a->h_child_inode->i_ino;
11777+
11778+ if (a->h_child_nlen
11779+ && (au_ftest_hinjob(a->flags[CHILD], GEN)
11780+ || au_ftest_hinjob(a->flags[CHILD], MNTPNT)))
11781+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
11782+ a->dir);
11783+ try_iput = 0;
11784+ if (dentry)
11785+ inode = dentry->d_inode;
11786+ if (xino && !inode && h_ino
11787+ && (au_ftest_hinjob(a->flags[CHILD], XINO0)
11788+ || au_ftest_hinjob(a->flags[CHILD], TRYXINO0)
11789+ || au_ftest_hinjob(a->flags[CHILD], GEN)
11790+ || au_ftest_hinjob(a->flags[CHILD], ATTR))) {
11791+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
11792+ try_iput = 1;
11793+ }
11794+
11795+ args.flags = a->flags[CHILD];
11796+ args.dentry = dentry;
11797+ args.inode = inode;
11798+ args.h_inode = a->h_child_inode;
11799+ args.dir = a->dir;
11800+ args.h_dir = a->h_dir;
11801+ args.h_name = a->h_child_name;
11802+ args.h_nlen = a->h_child_nlen;
11803+ err = hin_job(&args);
11804+ if (dentry) {
11805+ if (dentry->d_fsdata)
11806+ di_write_unlock(dentry);
11807+ dput(dentry);
11808+ }
11809+ if (inode && try_iput) {
11810+ ii_write_unlock(inode);
11811+ iput(inode);
11812+ }
11813+
11814+ ii_write_lock_parent(a->dir);
11815+ args.flags = a->flags[PARENT];
11816+ args.dentry = NULL;
11817+ args.inode = a->dir;
11818+ args.h_inode = a->h_dir;
11819+ args.dir = NULL;
11820+ args.h_dir = NULL;
11821+ args.h_name = NULL;
11822+ args.h_nlen = 0;
11823+ err = hin_job(&args);
11824+ ii_write_unlock(a->dir);
11825+
11826+ out:
11827+ au_nwt_done(&sbinfo->si_nowait);
11828+ si_write_unlock(sb);
11829+
11830+ iput(a->h_child_inode);
11831+ iput(a->h_dir);
11832+ iput(a->dir);
11833+ kfree(a);
11834+}
11835+
11836+static void aufs_inotify(struct inotify_watch *watch, u32 wd, u32 mask,
11837+ u32 cookie, const char *h_child_name,
11838+ struct inode *h_child_inode)
11839+{
11840+ struct au_hinotify *hinotify;
11841+ struct postproc_args *args;
11842+ int len, wkq_err;
11843+ unsigned char isdir, isroot, wh;
11844+ char *p;
11845+ struct inode *dir;
11846+ unsigned int flags[2];
11847+
11848+ LKTRTrace("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
11849+ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
11850+ h_child_name ? h_child_name : "",
11851+ h_child_inode ? h_child_inode->i_ino : 0);
11852+
11853+ /* if IN_UNMOUNT happens, there must be another bug */
11854+ if (mask & (IN_IGNORED | IN_UNMOUNT)) {
11855+ put_inotify_watch(watch);
11856+ return;
11857+ }
11858+
11859+#ifdef DbgInotify
11860+ if (!h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME))
11861+ AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
11862+ " hi%lu\n",
11863+ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
11864+ h_child_name ? h_child_name : "",
11865+ h_child_inode ? h_child_inode->i_ino : 0);
11866+#endif
11867+
11868+ hinotify = container_of(watch, struct au_hinotify, hin_watch);
11869+ AuDebugOn(!hinotify || !hinotify->hin_aufs_inode);
11870+ if (au_hin_test_ignore(mask, hinotify)) {
11871+#ifdef DbgInotify
11872+ AuDbg("ignored\n");
11873+#endif
11874+ return;
11875+ }
11876+#if 0 /* tmp debug */
11877+ if (h_child_name && !strcmp(h_child_name, AUFS_XINO_FNAME)) {
11878+ AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
11879+ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
11880+ h_child_name ? h_child_name : "",
11881+ h_child_inode ? h_child_inode->i_ino : 0);
11882+ //au_dbg_blocked();
11883+ }
11884+#endif
11885+
11886+ dir = igrab(hinotify->hin_aufs_inode);
11887+ if (!dir)
11888+ return;
11889+ isroot = (dir->i_ino == AUFS_ROOT_INO);
11890+ len = 0;
11891+ wh = 0;
11892+ if (h_child_name) {
11893+ len = strlen(h_child_name);
11894+ if (!memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
11895+ h_child_name += AUFS_WH_PFX_LEN;
11896+ len -= AUFS_WH_PFX_LEN;
11897+ wh = 1;
11898+ }
11899+ }
11900+
11901+ isdir = 0;
11902+ if (h_child_inode)
11903+ isdir = !!S_ISDIR(h_child_inode->i_mode);
11904+ flags[PARENT] = AuHinJob_ISDIR;
11905+ flags[CHILD] = 0;
11906+ if (isdir)
11907+ flags[CHILD] = AuHinJob_ISDIR;
11908+ switch (mask & IN_ALL_EVENTS) {
11909+ case IN_MODIFY:
11910+ /*FALLTHROUGH*/
11911+ case IN_ATTRIB:
11912+ if (h_child_inode) {
11913+ if (!wh)
11914+ au_fset_hinjob(flags[CHILD], ATTR);
11915+ } else
11916+ au_fset_hinjob(flags[PARENT], ATTR);
11917+ break;
11918+
11919+ /* IN_MOVED_FROM is the first event in rename(2) */
11920+ case IN_MOVED_FROM:
11921+ case IN_MOVED_TO:
11922+ AuDebugOn(!h_child_name || !h_child_inode);
11923+ au_fset_hinjob(flags[CHILD], GEN);
11924+ au_fset_hinjob(flags[CHILD], ATTR);
11925+ if (1 || isdir)
11926+ au_fset_hinjob(flags[CHILD], XINO0);
11927+ au_fset_hinjob(flags[CHILD], MNTPNT);
11928+
11929+ au_fset_hinjob(flags[PARENT], ATTR);
11930+ au_fset_hinjob(flags[PARENT], DIRENT);
11931+ break;
11932+
11933+ case IN_CREATE:
11934+ AuDebugOn(!h_child_name || !h_child_inode);
11935+ au_fset_hinjob(flags[PARENT], ATTR);
11936+ au_fset_hinjob(flags[PARENT], DIRENT);
11937+ au_fset_hinjob(flags[CHILD], GEN);
11938+ /* hard link */
11939+ if (!isdir && h_child_inode->i_nlink > 1)
11940+ au_fset_hinjob(flags[CHILD], ATTR);
11941+ break;
11942+
11943+ case IN_DELETE:
11944+ /*
11945+ * aufs never be able to get this child inode.
11946+ * revalidation should be in d_revalidate()
11947+ * by checking i_nlink, i_generation or d_unhashed().
11948+ */
11949+ AuDebugOn(!h_child_name);
11950+ au_fset_hinjob(flags[PARENT], ATTR);
11951+ au_fset_hinjob(flags[PARENT], DIRENT);
11952+ au_fset_hinjob(flags[CHILD], GEN);
11953+ au_fset_hinjob(flags[CHILD], TRYXINO0);
11954+ au_fset_hinjob(flags[CHILD], MNTPNT);
11955+ break;
11956+
11957+ case IN_DELETE_SELF:
11958+#if 0
11959+ if (!isroot)
11960+ au_fset_hinjob(flags[PARENT], GEN);
11961+ /*FALLTHROUGH*/
11962+#endif
11963+
11964+ case IN_MOVE_SELF:
11965+#if 0
11966+ /*
11967+ * when an inotify is set to an aufs inode,
11968+ * such inode can be isolated and this event can be fired
11969+ * solely.
11970+ */
11971+ AuDebugOn(h_child_name || h_child_inode);
11972+ if (unlikely(isroot)) {
11973+ AuWarn("root branch was moved\n");
11974+ iput(dir);
11975+ return;
11976+ }
11977+ au_fset_hinjob(flags[PARENT], XINO0);
11978+ au_fset_hinjob(flags[PARENT], GEN);
11979+ au_fset_hinjob(flags[PARENT], ATTR);
11980+ au_fset_hinjob(flags[PARENT], DIRENT);
11981+ /* au_fset_hinjob(flags[PARENT], MNTPNT); */
11982+ break;
11983+#endif
11984+
11985+ case IN_ACCESS:
11986+ default:
11987+ AuDebugOn(1);
11988+ }
11989+
11990+ if (wh)
11991+ h_child_inode = NULL;
11992+
11993+ /* iput() and kfree() will be called in postproc() */
11994+ /*
11995+ * inotify_mutex is already acquired and kmalloc/prune_icache may lock
11996+ * iprune_mutex. strange.
11997+ */
11998+ lockdep_off();
11999+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
12000+ lockdep_on();
12001+ if (unlikely(!args)) {
12002+ AuErr1("no memory\n");
12003+ iput(dir);
12004+ return;
12005+ }
12006+ args->flags[PARENT] = flags[PARENT];
12007+ args->flags[CHILD] = flags[CHILD];
12008+ args->mask = mask;
12009+ args->dir = dir;
12010+ args->h_dir = igrab(watch->inode);
12011+ if (h_child_inode)
12012+ h_child_inode = igrab(h_child_inode); /* can be NULL */
12013+ args->h_child_inode = h_child_inode;
12014+ args->h_child_nlen = len;
12015+ if (len) {
12016+ p = (void *)args;
12017+ p += sizeof(*args);
12018+ memcpy(p, h_child_name, len + 1);
12019+ }
12020+
12021+ lockdep_off();
12022+ wkq_err = au_wkq_nowait(postproc, args, dir->i_sb, /*dlgt*/0);
12023+ lockdep_on();
12024+ if (unlikely(wkq_err))
12025+ AuErr("wkq %d\n", wkq_err);
12026+}
12027+
12028+static void aufs_inotify_destroy(struct inotify_watch *watch)
12029+{
12030+ return;
12031+}
12032+
12033+static struct inotify_operations aufs_inotify_ops = {
12034+ .handle_event = aufs_inotify,
12035+ .destroy_watch = aufs_inotify_destroy
12036+};
12037+
12038+/* ---------------------------------------------------------------------- */
12039+
12040+static void au_hin_destroy_cache(void)
12041+{
12042+ kmem_cache_destroy(au_cachep[AuCache_HINOTIFY]);
12043+ au_cachep[AuCache_HINOTIFY] = NULL;
12044+}
12045+
12046+int __init au_inotify_init(void)
12047+{
12048+ int err;
12049+
12050+ err = -ENOMEM;
12051+ au_cachep[AuCache_HINOTIFY] = AuCache(au_hinotify);
12052+ if (au_cachep[AuCache_HINOTIFY]) {
12053+ err = 0;
12054+ in_handle = inotify_init(&aufs_inotify_ops);
12055+ if (IS_ERR(in_handle)) {
12056+ err = PTR_ERR(in_handle);
12057+ au_hin_destroy_cache();
12058+ }
12059+ }
12060+ AuTraceErr(err);
12061+ return err;
12062+}
12063+
12064+void au_inotify_fin(void)
12065+{
12066+ inotify_destroy(in_handle);
12067+ if (au_cachep[AuCache_HINOTIFY])
12068+ au_hin_destroy_cache();
12069+}
12070diff -urN linux/fs/aufs/iinfo.c linux-aufs/fs/aufs/iinfo.c
12071--- linux/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
12072+++ linux-aufs/fs/aufs/iinfo.c 2009-03-12 16:18:04.000000000 +0100
12073@@ -0,0 +1,284 @@
12074+/*
12075+ * Copyright (C) 2005-2009 Junjiro Okajima
12076+ *
12077+ * This program, aufs is free software; you can redistribute it and/or modify
12078+ * it under the terms of the GNU General Public License as published by
12079+ * the Free Software Foundation; either version 2 of the License, or
12080+ * (at your option) any later version.
12081+ *
12082+ * This program is distributed in the hope that it will be useful,
12083+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12084+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12085+ * GNU General Public License for more details.
12086+ *
12087+ * You should have received a copy of the GNU General Public License
12088+ * along with this program; if not, write to the Free Software
12089+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12090+ */
12091+
12092+/*
12093+ * inode private data
12094+ *
12095+ * $Id$
12096+ */
12097+
12098+#include "aufs.h"
12099+
12100+struct au_iinfo *au_ii(struct inode *inode)
12101+{
12102+ struct au_iinfo *iinfo;
12103+
12104+ iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
12105+ /* bad_inode case */
12106+ if (unlikely(!iinfo->ii_hinode))
12107+ return NULL;
12108+ AuDebugOn(!iinfo->ii_hinode
12109+ /* || au_sbi(inode->i_sb)->si_bend < iinfo->ii_bend */
12110+ || iinfo->ii_bend < iinfo->ii_bstart);
12111+ return iinfo;
12112+}
12113+
12114+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
12115+{
12116+ struct inode *hidden_inode;
12117+
12118+ /* lock free root dinfo/inode */
12119+ if (inode->i_ino != AUFS_ROOT_INO) {
12120+ IiMustAnyLock(inode);
12121+ AuDebugOn(bindex < 0 || au_ibend(inode) < bindex);
12122+ } else {
12123+ SiMustAnyLock(inode->i_sb);
12124+ AuDebugOn(bindex < 0 || au_sbend(inode->i_sb) < bindex);
12125+ }
12126+ hidden_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
12127+ AuDebugOn(hidden_inode && atomic_read(&hidden_inode->i_count) <= 0);
12128+ return hidden_inode;
12129+}
12130+
12131+aufs_bindex_t au_ii_br_id(struct inode *inode, aufs_bindex_t bindex)
12132+{
12133+ IiMustAnyLock(inode);
12134+ AuDebugOn(bindex < 0
12135+ || au_ibend(inode) < bindex
12136+ || !au_ii(inode)->ii_hinode[0 + bindex].hi_inode);
12137+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
12138+}
12139+
12140+/* todo: hard/soft set? */
12141+void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
12142+{
12143+ struct au_iinfo *iinfo = au_ii(inode);
12144+ struct inode *h_inode;
12145+
12146+ IiMustWriteLock(inode);
12147+ AuDebugOn(au_sbend(inode->i_sb) < bindex);
12148+ iinfo->ii_bstart = bindex;
12149+ h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
12150+ if (h_inode)
12151+ au_cpup_igen(inode, h_inode);
12152+}
12153+
12154+unsigned int au_hi_flags(struct inode *inode, int isdir)
12155+{
12156+ unsigned int flags;
12157+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
12158+
12159+ flags = 0;
12160+ if (au_opt_test_xino(mnt_flags))
12161+ au_fset_hi(flags, XINO);
12162+ if (isdir && au_opt_test(mnt_flags, UDBA_INOTIFY))
12163+ au_fset_hi(flags, NOTIFY);
12164+ return flags;
12165+}
12166+
12167+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12168+ struct inode *h_inode, unsigned int flags)
12169+{
12170+ struct au_hinode *hinode;
12171+ struct inode *hi;
12172+ struct au_iinfo *iinfo = au_ii(inode);
12173+
12174+ LKTRTrace("i%lu, b%d, hi%lu, flags 0x%x\n",
12175+ inode->i_ino, bindex, h_inode ? h_inode->i_ino : 0, flags);
12176+ IiMustWriteLock(inode);
12177+ hinode = iinfo->ii_hinode + bindex;
12178+ hi = hinode->hi_inode;
12179+ AuDebugOn(bindex < au_ibstart(inode) || au_ibend(inode) < bindex);
12180+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
12181+ AuDebugOn(h_inode && hi);
12182+
12183+ if (hi)
12184+ au_hiput(hinode);
12185+ hinode->hi_inode = h_inode;
12186+ if (h_inode) {
12187+ int err;
12188+ struct super_block *sb = inode->i_sb;
12189+
12190+ if (bindex == iinfo->ii_bstart)
12191+ au_cpup_igen(inode, h_inode);
12192+ hinode->hi_id = au_sbr_id(sb, bindex);
12193+ if (au_ftest_hi(flags, XINO)) {
12194+ struct au_xino_entry xinoe = {
12195+ .ino = inode->i_ino,
12196+ /* .h_gen = h_inode->i_generation */
12197+ };
12198+ err = au_xino_write(sb, bindex, h_inode->i_ino, &xinoe);
12199+ if (unlikely(err))
12200+ AuIOErr1("failed au_xino_write() %d\n", err);
12201+ }
12202+
12203+ if (au_ftest_hi(flags, NOTIFY)
12204+ && au_br_hinotifyable(au_sbr_perm(sb, bindex))) {
12205+ err = au_hin_alloc(hinode, inode, h_inode);
12206+ if (unlikely(err))
12207+ AuIOErr1("au_hin_alloc() %d\n", err);
12208+ }
12209+ }
12210+}
12211+
12212+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12213+ struct dentry *h_wh)
12214+{
12215+ struct au_hinode *hinode;
12216+
12217+ IiMustWriteLock(inode);
12218+ hinode = au_ii(inode)->ii_hinode + bindex;
12219+ AuDebugOn(hinode->hi_whdentry);
12220+ hinode->hi_whdentry = h_wh;
12221+}
12222+
12223+void au_update_iigen(struct inode *inode)
12224+{
12225+ AuDebugOn(!inode->i_sb);
12226+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
12227+ /* smp_mb(); */ /* atomic_set */
12228+}
12229+
12230+/* it may be called at remount time, too */
12231+void au_update_brange(struct inode *inode, int do_put_zero)
12232+{
12233+ struct au_iinfo *iinfo;
12234+
12235+ LKTRTrace("i%lu, %d\n", inode->i_ino, do_put_zero);
12236+ IiMustWriteLock(inode);
12237+
12238+ iinfo = au_ii(inode);
12239+ if (!iinfo || iinfo->ii_bstart < 0)
12240+ return;
12241+
12242+ if (do_put_zero) {
12243+ aufs_bindex_t bindex;
12244+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12245+ bindex++) {
12246+ struct inode *h_i;
12247+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
12248+ if (h_i && !h_i->i_nlink)
12249+ au_set_h_iptr(inode, bindex, NULL, 0);
12250+ }
12251+ }
12252+
12253+ iinfo->ii_bstart = -1;
12254+ while (++iinfo->ii_bstart <= iinfo->ii_bend)
12255+ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
12256+ break;
12257+ if (iinfo->ii_bstart > iinfo->ii_bend) {
12258+ iinfo->ii_bstart = -1;
12259+ iinfo->ii_bend = -1;
12260+ return;
12261+ }
12262+
12263+ iinfo->ii_bend++;
12264+ while (0 <= --iinfo->ii_bend)
12265+ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
12266+ break;
12267+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
12268+}
12269+
12270+/* ---------------------------------------------------------------------- */
12271+
12272+int au_iinfo_init(struct inode *inode)
12273+{
12274+ struct au_iinfo *iinfo;
12275+ struct super_block *sb;
12276+ int nbr, i;
12277+
12278+ sb = inode->i_sb;
12279+ AuDebugOn(!sb);
12280+ iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
12281+ AuDebugOn(iinfo->ii_hinode);
12282+ nbr = au_sbend(sb) + 1;
12283+ if (nbr <= 0)
12284+ nbr = 1;
12285+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
12286+ if (iinfo->ii_hinode) {
12287+ for (i = 0; i < nbr; i++)
12288+ iinfo->ii_hinode[i].hi_id = -1;
12289+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
12290+ /* smp_mb(); */ /* atomic_set */
12291+ au_rw_init_nolock(&iinfo->ii_rwsem);
12292+ iinfo->ii_bstart = -1;
12293+ iinfo->ii_bend = -1;
12294+ iinfo->ii_vdir = NULL;
12295+ return 0;
12296+ }
12297+ return -ENOMEM;
12298+}
12299+
12300+static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
12301+ ino_t ino)
12302+{
12303+ int err, locked;
12304+ aufs_bindex_t bindex;
12305+
12306+ err = 0;
12307+ locked = si_noflush_read_trylock(sb); /* crucio! */
12308+ bindex = au_br_index(sb, hinode->hi_id);
12309+ if (bindex >= 0)
12310+ err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
12311+ /* error action? */
12312+ if (locked)
12313+ si_read_unlock(sb);
12314+ return err;
12315+}
12316+
12317+void au_iinfo_fin(struct inode *inode)
12318+{
12319+ struct au_iinfo *iinfo;
12320+ aufs_bindex_t bend;
12321+ unsigned char unlinked;
12322+ struct au_hinode *hi;
12323+ struct super_block *sb;
12324+ ino_t ino;
12325+
12326+ iinfo = au_ii(inode);
12327+ /* bad_inode case */
12328+ if (!iinfo)
12329+ return;
12330+
12331+ if (iinfo->ii_vdir)
12332+ au_vdir_free(iinfo->ii_vdir);
12333+
12334+ if (iinfo->ii_bstart >= 0) {
12335+ sb = inode->i_sb;
12336+ unlinked = !inode->i_nlink;
12337+ ino = 0;
12338+ if (unlinked)
12339+ ino = inode->i_ino;
12340+ hi = iinfo->ii_hinode + iinfo->ii_bstart;
12341+ bend = iinfo->ii_bend;
12342+ while (iinfo->ii_bstart++ <= bend) {
12343+ if (hi->hi_inode) {
12344+ if (unlinked || !hi->hi_inode->i_nlink) {
12345+ au_iinfo_write0(sb, hi, ino);
12346+ /* ignore this error */
12347+ ino = 0;
12348+ }
12349+ au_hiput(hi);
12350+ }
12351+ hi++;
12352+ }
12353+ }
12354+
12355+ kfree(iinfo->ii_hinode);
12356+ au_rwsem_destroy(&iinfo->ii_rwsem);
12357+}
12358diff -urN linux/fs/aufs/inode.c linux-aufs/fs/aufs/inode.c
12359--- linux/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
12360+++ linux-aufs/fs/aufs/inode.c 2009-03-12 16:18:04.000000000 +0100
12361@@ -0,0 +1,421 @@
12362+/*
12363+ * Copyright (C) 2005-2009 Junjiro Okajima
12364+ *
12365+ * This program, aufs is free software; you can redistribute it and/or modify
12366+ * it under the terms of the GNU General Public License as published by
12367+ * the Free Software Foundation; either version 2 of the License, or
12368+ * (at your option) any later version.
12369+ *
12370+ * This program is distributed in the hope that it will be useful,
12371+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12372+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12373+ * GNU General Public License for more details.
12374+ *
12375+ * You should have received a copy of the GNU General Public License
12376+ * along with this program; if not, write to the Free Software
12377+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12378+ */
12379+
12380+/*
12381+ * inode functions
12382+ *
12383+ * $Id$
12384+ */
12385+
12386+#include "aufs.h"
12387+
12388+int au_refresh_hinode_self(struct inode *inode)
12389+{
12390+ int err, new_sz, update;
12391+ struct inode *first;
12392+ struct au_hinode *p, *q, tmp;
12393+ struct super_block *sb;
12394+ struct au_iinfo *iinfo;
12395+ aufs_bindex_t bindex, bend, new_bindex;
12396+
12397+ LKTRTrace("i%lu\n", inode->i_ino);
12398+ IiMustWriteLock(inode);
12399+
12400+ err = -ENOMEM;
12401+ update = 0;
12402+ sb = inode->i_sb;
12403+ bend = au_sbend(sb);
12404+ new_sz = sizeof(*iinfo->ii_hinode) * (bend + 1);
12405+ iinfo = au_ii(inode);
12406+ p = au_kzrealloc(iinfo->ii_hinode, sizeof(*p) * (iinfo->ii_bend + 1),
12407+ new_sz, GFP_NOFS);
12408+ if (unlikely(!p))
12409+ goto out;
12410+
12411+ iinfo->ii_hinode = p;
12412+ p = iinfo->ii_hinode + iinfo->ii_bstart;
12413+ first = p->hi_inode;
12414+ err = 0;
12415+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12416+ bindex++, p++) {
12417+ if (!p->hi_inode)
12418+ continue;
12419+
12420+ new_bindex = au_br_index(sb, p->hi_id);
12421+ if (new_bindex == bindex)
12422+ continue;
12423+ if (new_bindex < 0) {
12424+ update++;
12425+ au_hiput(p);
12426+ p->hi_inode = NULL;
12427+ continue;
12428+ }
12429+
12430+ if (new_bindex < iinfo->ii_bstart)
12431+ iinfo->ii_bstart = new_bindex;
12432+ if (iinfo->ii_bend < new_bindex)
12433+ iinfo->ii_bend = new_bindex;
12434+ /* swap two hidden inode, and loop again */
12435+ q = iinfo->ii_hinode + new_bindex;
12436+ tmp = *q;
12437+ *q = *p;
12438+ *p = tmp;
12439+ if (tmp.hi_inode) {
12440+ bindex--;
12441+ p--;
12442+ }
12443+ }
12444+ au_update_brange(inode, /*do_put_zero*/0);
12445+
12446+ if (unlikely(err))
12447+ goto out;
12448+
12449+ if (1 || first != au_h_iptr(inode, iinfo->ii_bstart))
12450+ au_cpup_attr_all(inode, /*force*/0);
12451+ if (update && S_ISDIR(inode->i_mode))
12452+ inode->i_version++;
12453+ au_update_iigen(inode);
12454+
12455+ out:
12456+ AuTraceErr(err);
12457+ return err;
12458+}
12459+
12460+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
12461+{
12462+ int err, update;
12463+ struct inode *first;
12464+ struct au_hinode *p;
12465+ struct super_block *sb;
12466+ struct au_iinfo *iinfo;
12467+ aufs_bindex_t bindex, bend;
12468+ unsigned char isdir;
12469+ unsigned int flags;
12470+
12471+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
12472+ IiMustWriteLock(inode);
12473+
12474+ err = au_refresh_hinode_self(inode);
12475+ if (unlikely(err))
12476+ goto out;
12477+
12478+ sb = dentry->d_sb;
12479+ bend = au_sbend(sb);
12480+ iinfo = au_ii(inode);
12481+ update = 0;
12482+ p = iinfo->ii_hinode + iinfo->ii_bstart;
12483+ first = p->hi_inode;
12484+ isdir = S_ISDIR(inode->i_mode);
12485+ flags = au_hi_flags(inode, isdir);
12486+ bend = au_dbend(dentry);
12487+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
12488+ struct inode *hi;
12489+ struct dentry *hd;
12490+
12491+ hd = au_h_dptr(dentry, bindex);
12492+ if (!hd || !hd->d_inode)
12493+ continue;
12494+
12495+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
12496+ hi = au_h_iptr(inode, bindex);
12497+ if (hi) {
12498+ if (hi == hd->d_inode)
12499+ continue;
12500+ err = -ESTALE;
12501+ break;
12502+ }
12503+ }
12504+ if (bindex < iinfo->ii_bstart)
12505+ iinfo->ii_bstart = bindex;
12506+ if (iinfo->ii_bend < bindex)
12507+ iinfo->ii_bend = bindex;
12508+ au_set_h_iptr(inode, bindex, au_igrab(hd->d_inode), flags);
12509+ update++;
12510+ }
12511+ au_update_brange(inode, /*do_put_zero*/0);
12512+
12513+ if (unlikely(err))
12514+ goto out;
12515+
12516+ if (1 || first != au_h_iptr(inode, iinfo->ii_bstart))
12517+ au_cpup_attr_all(inode, /*force*/0);
12518+ if (update && isdir)
12519+ inode->i_version++;
12520+ au_update_iigen(inode);
12521+
12522+ out:
12523+ AuTraceErr(err);
12524+ return err;
12525+}
12526+
12527+static int set_inode(struct inode *inode, struct dentry *dentry)
12528+{
12529+ int err;
12530+ struct dentry *h_dentry;
12531+ struct inode *h_inode;
12532+ umode_t mode;
12533+ aufs_bindex_t bindex, bstart, btail;
12534+ unsigned char isdir;
12535+ struct au_iinfo *iinfo;
12536+ unsigned int flags;
12537+
12538+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry));
12539+ AuDebugOn(!(inode->i_state & I_NEW));
12540+ IiMustWriteLock(inode);
12541+ bstart = au_dbstart(dentry);
12542+ h_dentry = au_h_dptr(dentry, bstart);
12543+ AuDebugOn(!h_dentry);
12544+ h_inode = h_dentry->d_inode;
12545+ AuDebugOn(!h_inode);
12546+
12547+ err = 0;
12548+ isdir = 0;
12549+ mode = h_inode->i_mode;
12550+ switch (mode & S_IFMT) {
12551+ case S_IFREG:
12552+ btail = au_dbtail(dentry);
12553+ inode->i_op = &aufs_iop;
12554+ inode->i_fop = &aufs_file_fop;
12555+ inode->i_mapping->a_ops = &aufs_aop;
12556+ break;
12557+ case S_IFDIR:
12558+ isdir = 1;
12559+ btail = au_dbtaildir(dentry);
12560+ inode->i_op = &aufs_dir_iop;
12561+ inode->i_fop = &aufs_dir_fop;
12562+ break;
12563+ case S_IFLNK:
12564+ btail = au_dbtail(dentry);
12565+ inode->i_op = &aufs_symlink_iop;
12566+ /* inode->i_fop = &aufs_file_fop; */
12567+ break;
12568+ case S_IFBLK:
12569+ case S_IFCHR:
12570+ case S_IFIFO:
12571+ case S_IFSOCK:
12572+ btail = au_dbtail(dentry);
12573+ inode->i_op = &aufs_iop;
12574+ init_special_inode(inode, mode,
12575+ au_h_rdev(h_inode, /*h_mnt*/NULL, h_dentry));
12576+ break;
12577+ default:
12578+ AuIOErr("Unknown file type 0%o\n", mode);
12579+ err = -EIO;
12580+ goto out;
12581+ }
12582+
12583+ /* do not set inotify for whiteouted dirs (SHWH mode) */
12584+ flags = au_hi_flags(inode, isdir);
12585+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
12586+ && au_ftest_hi(flags, NOTIFY)
12587+ && dentry->d_name.len > AUFS_WH_PFX_LEN
12588+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
12589+ au_fclr_hi(flags, NOTIFY);
12590+ iinfo = au_ii(inode);
12591+ iinfo->ii_bstart = bstart;
12592+ iinfo->ii_bend = btail;
12593+ for (bindex = bstart; bindex <= btail; bindex++) {
12594+ h_dentry = au_h_dptr(dentry, bindex);
12595+ if (!h_dentry)
12596+ continue;
12597+ AuDebugOn(!h_dentry->d_inode);
12598+ au_set_h_iptr(inode, bindex, au_igrab(h_dentry->d_inode),
12599+ flags);
12600+ }
12601+ au_cpup_attr_all(inode, /*force*/1);
12602+
12603+ out:
12604+ AuTraceErr(err);
12605+ return err;
12606+}
12607+
12608+/* successful returns with iinfo write_locked */
12609+/* todo: return with unlocked? */
12610+static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
12611+{
12612+ int err;
12613+ struct inode *h_inode, *h_dinode;
12614+ aufs_bindex_t bindex, bend;
12615+
12616+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry));
12617+
12618+ *matched = 0;
12619+
12620+ /*
12621+ * before this function, if aufs got any iinfo lock, it must be only
12622+ * one, the parent dir.
12623+ * it can happen by UDBA and the obsoleted inode number.
12624+ */
12625+ err = -EIO;
12626+ if (unlikely(inode->i_ino == parent_ino(dentry)))
12627+ goto out;
12628+
12629+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
12630+ /* mutex_lock_nested(&inode->i_mutex, AuLsc_I_CHILD); */
12631+ ii_write_lock_new_child(inode);
12632+ /* it happend */
12633+ if (unlikely(IS_DEADDIR(inode)))
12634+ goto out_unlock;
12635+
12636+ err = 0;
12637+ bend = au_ibend(inode);
12638+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12639+ h_inode = au_h_iptr(inode, bindex);
12640+ if (h_inode && h_inode == h_dinode) {
12641+ /* && (ibs != bstart
12642+ || !au_test_higen(inode, h_inode))); */
12643+ *matched = 1;
12644+ err = 0;
12645+ if (au_iigen(inode) != au_digen(dentry))
12646+ err = au_refresh_hinode(inode, dentry);
12647+ break;
12648+ }
12649+ }
12650+
12651+ out_unlock:
12652+ if (unlikely(err))
12653+ ii_write_unlock(inode);
12654+ /* mutex_unlock(&inode->i_mutex); */
12655+ out:
12656+ AuTraceErr(err);
12657+ return err;
12658+}
12659+
12660+/* successful returns with iinfo write_locked */
12661+/* todo: return with unlocked? */
12662+struct inode *au_new_inode(struct dentry *dentry, int must_new)
12663+{
12664+ struct inode *inode, *h_inode;
12665+ struct dentry *h_dentry;
12666+ struct super_block *sb;
12667+ ino_t h_ino;
12668+ int err, match;
12669+ aufs_bindex_t bstart;
12670+ struct au_xino_entry xinoe;
12671+
12672+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
12673+ sb = dentry->d_sb;
12674+ bstart = au_dbstart(dentry);
12675+ h_dentry = au_h_dptr(dentry, bstart);
12676+ AuDebugOn(!h_dentry);
12677+ h_inode = h_dentry->d_inode;
12678+ AuDebugOn(!h_inode);
12679+
12680+ h_ino = h_inode->i_ino;
12681+ err = au_xino_read(sb, bstart, h_ino, &xinoe);
12682+ inode = ERR_PTR(err);
12683+ if (unlikely(err))
12684+ goto out;
12685+ new_ino:
12686+ if (!xinoe.ino) {
12687+ xinoe.ino = au_xino_new_ino(sb);
12688+ if (!xinoe.ino) {
12689+ inode = ERR_PTR(-EIO);
12690+ goto out;
12691+ }
12692+ }
12693+
12694+ LKTRTrace("i%lu\n", (unsigned long)xinoe.ino);
12695+ inode = au_iget_locked(sb, xinoe.ino);
12696+ err = PTR_ERR(inode);
12697+ if (IS_ERR(inode))
12698+ goto out;
12699+
12700+ LKTRTrace("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
12701+ if (inode->i_state & I_NEW) {
12702+ ii_write_lock_new_child(inode);
12703+ err = set_inode(inode, dentry);
12704+ unlock_new_inode(inode);
12705+ if (!err)
12706+ goto out; /* success */
12707+ iget_failed(inode);
12708+ ii_write_unlock(inode);
12709+ goto out_iput;
12710+ } else if (!must_new) {
12711+ AuDebugOn(inode->i_state & I_LOCK);
12712+ err = reval_inode(inode, dentry, &match);
12713+ if (!err)
12714+ goto out; /* success */
12715+ else if (match)
12716+ goto out_iput;
12717+ }
12718+
12719+ if (unlikely(au_test_unique_ino(h_dentry, h_ino)))
12720+ AuWarn1("Un-notified UDBA or repeatedly renamed dir,"
12721+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
12722+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
12723+ (unsigned long)h_ino, (unsigned long)xinoe.ino);
12724+ xinoe.ino = 0;
12725+ err = au_xino_write0(sb, bstart, h_ino, 0);
12726+ if (!err) {
12727+ iput(inode);
12728+ goto new_ino;
12729+ }
12730+ /* force noxino? */
12731+
12732+ out_iput:
12733+ iput(inode);
12734+ inode = ERR_PTR(err);
12735+ out:
12736+ AuTraceErrPtr(inode);
12737+ return inode;
12738+}
12739+
12740+/* ---------------------------------------------------------------------- */
12741+
12742+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12743+ struct inode *inode)
12744+{
12745+ int err;
12746+
12747+ err = au_br_rdonly(au_sbr(sb, bindex));
12748+
12749+ /* pseudo-link after flushed may out of bounds */
12750+ if (!err
12751+ && inode
12752+ && au_ibstart(inode) <= bindex
12753+ && bindex <= au_ibend(inode)) {
12754+ /*
12755+ * permission check is unnecessary since vfsub routine
12756+ * will be called later
12757+ */
12758+ struct inode *hi = au_h_iptr(inode, bindex);
12759+ if (hi)
12760+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
12761+ }
12762+
12763+ AuTraceErr(err);
12764+ return err;
12765+}
12766+
12767+int au_test_h_perm(struct inode *h_inode, int mask, int dlgt)
12768+{
94750128 12769+ if (!current_fsuid())
024a5822
JR
12770+ return 0;
12771+ /* todo: fake nameidata? */
12772+ return vfsub_permission(h_inode, mask, NULL, dlgt);
12773+}
12774+
12775+int au_test_h_perm_sio(struct inode *h_inode, int mask, int dlgt)
12776+{
12777+ if (au_test_nfs(h_inode->i_sb)
12778+ && (mask & MAY_WRITE)
12779+ && S_ISDIR(h_inode->i_mode))
12780+ mask |= MAY_READ; /* force permission check */
12781+ return au_test_h_perm(h_inode, mask, dlgt);
12782+}
12783diff -urN linux/fs/aufs/inode.h linux-aufs/fs/aufs/inode.h
12784--- linux/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
12785+++ linux-aufs/fs/aufs/inode.h 2009-03-12 16:18:04.000000000 +0100
12786@@ -0,0 +1,595 @@
12787+/*
12788+ * Copyright (C) 2005-2009 Junjiro Okajima
12789+ *
12790+ * This program, aufs is free software; you can redistribute it and/or modify
12791+ * it under the terms of the GNU General Public License as published by
12792+ * the Free Software Foundation; either version 2 of the License, or
12793+ * (at your option) any later version.
12794+ *
12795+ * This program is distributed in the hope that it will be useful,
12796+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12797+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12798+ * GNU General Public License for more details.
12799+ *
12800+ * You should have received a copy of the GNU General Public License
12801+ * along with this program; if not, write to the Free Software
12802+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12803+ */
12804+
12805+/*
12806+ * inode operations
12807+ *
12808+ * $Id$
12809+ */
12810+
12811+#ifndef __AUFS_INODE_H__
12812+#define __AUFS_INODE_H__
12813+
12814+#ifdef __KERNEL__
12815+
12816+#include <linux/fs.h>
12817+#include <linux/namei.h>
12818+#include <linux/security.h>
12819+#include <linux/aufs_type.h>
12820+#include "hinode.h"
12821+#include "misc.h"
12822+#include "super.h"
12823+
12824+struct au_hinode;
12825+struct au_vdir;
12826+struct au_iinfo {
12827+ atomic_t ii_generation;
12828+ struct super_block *ii_hsb1; /* no get/put */
12829+
12830+ struct au_rwsem ii_rwsem;
12831+ aufs_bindex_t ii_bstart, ii_bend;
12832+ __u32 ii_higen;
12833+ struct au_hinode *ii_hinode;
12834+ struct au_vdir *ii_vdir;
12835+};
12836+
12837+struct aufs_icntnr {
12838+ struct au_iinfo iinfo;
12839+ struct inode vfs_inode;
12840+};
12841+
12842+/* au_pin flags */
12843+#define AuPin_DI_LOCKED 1
12844+#define AuPin_DO_GPARENT (1 << 1)
12845+#define AuPin_MNT_WRITE (1 << 2)
12846+#define AuPin_VFS_RENAME (1 << 3)
12847+/* will be set automatically */
12848+#define AuPin_VERIFY (1 << 4)
12849+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
12850+#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
12851+#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
12852+
12853+struct au_pin1 {
12854+ /* input */
12855+ struct dentry *dentry;
12856+ unsigned char lsc_di, lsc_hi, flags;
12857+ aufs_bindex_t bindex;
12858+
12859+ /* output */
12860+ struct dentry *parent;
12861+ struct inode *h_dir;
12862+};
12863+
12864+enum {AuPin_PARENT, AuPin_GPARENT};
12865+struct au_pin {
12866+#ifdef CONFIG_AUFS_HINOTIFY
12867+ struct au_pin1 pin[2];
12868+#else
12869+ struct au_pin1 pin[1]; /* no grand parent */
12870+#endif
12871+};
12872+
12873+/* ---------------------------------------------------------------------- */
12874+
12875+/* inode.c */
12876+int au_refresh_hinode_self(struct inode *inode);
12877+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
12878+struct inode *au_new_inode(struct dentry *dentry, int must_new);
12879+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12880+ struct inode *inode);
12881+int au_test_h_perm(struct inode *h_inode, int mask, int dlgt);
12882+int au_test_h_perm_sio(struct inode *h_inode, int mask, int dlgt);
12883+
12884+/* i_op.c */
12885+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
12886+
12887+/* au_wr_dir flags */
12888+#define AuWrDir_ADD_ENTRY 1
12889+#define AuWrDir_ISDIR (1 << 1)
12890+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
12891+#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
12892+#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
12893+
12894+struct au_wr_dir_args {
12895+ aufs_bindex_t force_btgt;
12896+ unsigned char flags;
12897+};
12898+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
12899+ struct au_wr_dir_args *args);
12900+
12901+void au_pin_init(struct au_pin *args, struct dentry *dentry,
12902+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
12903+ unsigned char flags);
12904+int au_pin(struct au_pin *args, struct dentry *dentry, aufs_bindex_t bindex,
12905+ unsigned char flags) __must_check;
12906+int au_do_pin(struct au_pin1 *p, struct au_pin1 *gp) __must_check;
12907+void au_do_unpin(struct au_pin1 *p, struct au_pin1 *gp);
12908+
12909+/* i_op_add.c */
12910+struct au_ndx;
12911+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
12912+ struct dentry *h_parent, int isdir, struct au_ndx *ndx);
12913+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
12914+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
12915+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
12916+ struct nameidata *nd);
12917+int aufs_link(struct dentry *src_dentry, struct inode *dir,
12918+ struct dentry *dentry);
12919+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
12920+
12921+/* i_op_del.c */
12922+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
12923+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
12924+ struct dentry *h_parent, int isdir, struct au_ndx *ndx);
12925+int aufs_unlink(struct inode *dir, struct dentry *dentry);
12926+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
12927+
12928+/* i_op_ren.c */
12929+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
12930+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
12931+ struct inode *dir, struct dentry *dentry);
12932+
12933+#ifdef CONFIG_AUFS_DLGT
12934+/* dlgt.c */
12935+int au_security_inode_permission(struct inode *h_inode, int mask,
12936+ struct nameidata *fake_nd, int dlgt);
12937+#else
12938+static inline
12939+int au_security_inode_permission(struct inode *h_inode, int mask,
12940+ struct nameidata *fake_nd, int dlgt)
12941+{
12942+ return vfsub_security_inode_permission(h_inode, mask, fake_nd);
12943+}
12944+#endif /* CONFIG_AUFS_DLGT */
12945+
12946+#ifdef CONFIG_AUFS_GETATTR
12947+/* getattr.c */
12948+int aufs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st);
12949+#endif
12950+
12951+#if 0 /* reserved for future use */
12952+/* xattr.c */
12953+int aufs_setxattr(struct dentry *dentry, const char *name, const void *value,
12954+ size_t sz, int flags);
12955+ssize_t aufs_getxattr(struct dentry *dentry, const char *name, void *value,
12956+ size_t sz);
12957+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t sz);
12958+int aufs_removexattr(struct dentry *dentry, const char *name);
12959+#endif
12960+
12961+/* iinfo.c */
12962+struct au_iinfo *au_ii(struct inode *inode);
12963+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
12964+aufs_bindex_t au_ii_br_id(struct inode *inode, aufs_bindex_t bindex);
12965+
12966+void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex);
12967+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12968+ struct dentry *h_wh);
12969+unsigned int au_hi_flags(struct inode *inode, int isdir);
12970+
12971+/* hinode flags */
12972+#define AuHi_XINO 1
12973+#define AuHi_NOTIFY (1 << 1)
12974+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
12975+#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; }
12976+#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; }
12977+#ifndef CONFIG_AUFS_HINOTIFY
12978+#undef AuHi_NOTIFY
12979+#define AuHi_NOTIFY 0
12980+#endif
12981+
12982+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12983+ struct inode *h_inode, unsigned int flags);
12984+
12985+void au_update_iigen(struct inode *inode);
12986+void au_update_brange(struct inode *inode, int do_put_zero);
12987+
12988+int au_iinfo_init(struct inode *inode);
12989+void au_iinfo_fin(struct inode *inode);
12990+
12991+/* plink.c */
12992+#ifdef CONFIG_AUFS_DEBUG
12993+void au_plink_list(struct super_block *sb);
12994+#else
12995+static inline void au_plink_list(struct super_block *sb)
12996+{
12997+ /* nothing */
12998+}
12999+#endif
13000+int au_plink_test(struct super_block *sb, struct inode *inode);
13001+struct dentry *au_plink_lkup(struct super_block *sb, aufs_bindex_t bindex,
13002+ struct inode *inode);
13003+void au_plink_append(struct super_block *sb, struct inode *inode,
13004+ struct dentry *h_dentry, aufs_bindex_t bindex);
13005+void au_plink_put(struct super_block *sb);
13006+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
13007+
13008+/* ---------------------------------------------------------------------- */
13009+
13010+/* lock subclass for iinfo */
13011+enum {
13012+ AuLsc_II_CHILD, /* child first */
13013+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hinotify */
13014+ AuLsc_II_CHILD3, /* copyup dirs */
13015+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
13016+ AuLsc_II_PARENT2,
13017+ AuLsc_II_PARENT3,
13018+ AuLsc_II_PARENT4,
13019+ AuLsc_II_NEW_CHILD,
13020+};
13021+
13022+/*
13023+ * ii_read_lock_child, ii_write_lock_child,
13024+ * ii_read_lock_child2, ii_write_lock_child2,
13025+ * ii_read_lock_child3, ii_write_lock_child3,
13026+ * ii_read_lock_parent, ii_write_lock_parent,
13027+ * ii_read_lock_parent2, ii_write_lock_parent2,
13028+ * ii_read_lock_parent3, ii_write_lock_parent3,
13029+ * ii_read_lock_parent4, ii_write_lock_parent4,
13030+ * ii_read_lock_new_child, ii_write_lock_new_child,
13031+ */
13032+#define AuReadLockFunc(name, lsc) \
13033+static inline void ii_read_lock_##name(struct inode *i) \
13034+{ \
13035+ au_dbg_locking_ii_reg(i, 0, AuLsc_II_##lsc); \
13036+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
13037+ au_dbg_locking_ii_unreg(i, 0); \
13038+ au_dbg_locked_ii_reg(i, 0, AuLsc_II_##lsc); \
13039+}
13040+
13041+#define AuWriteLockFunc(name, lsc) \
13042+static inline void ii_write_lock_##name(struct inode *i) \
13043+{ \
13044+ au_dbg_locking_ii_reg(i, 1, AuLsc_II_##lsc); \
13045+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
13046+ au_dbg_locking_ii_unreg(i, 1); \
13047+ au_dbg_locked_ii_reg(i, 1, AuLsc_II_##lsc); \
13048+}
13049+
13050+#define AuRWLockFuncs(name, lsc) \
13051+ AuReadLockFunc(name, lsc) \
13052+ AuWriteLockFunc(name, lsc)
13053+
13054+AuRWLockFuncs(child, CHILD);
13055+AuRWLockFuncs(child2, CHILD2);
13056+AuRWLockFuncs(child3, CHILD3);
13057+AuRWLockFuncs(parent, PARENT);
13058+AuRWLockFuncs(parent2, PARENT2);
13059+AuRWLockFuncs(parent3, PARENT3);
13060+AuRWLockFuncs(parent4, PARENT4);
13061+AuRWLockFuncs(new_child, NEW_CHILD);
13062+
13063+#undef AuReadLockFunc
13064+#undef AuWriteLockFunc
13065+#undef AuRWLockFuncs
13066+
13067+/*
13068+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
13069+ */
13070+AuSimpleUnlockRwsemFuncs(ii_do, struct inode *i, au_ii(i)->ii_rwsem);
13071+static inline void ii_read_unlock(struct inode *i)
13072+{
13073+ ii_do_read_unlock(i);
13074+ au_dbg_locked_ii_unreg(i, 0);
13075+}
13076+
13077+static inline void ii_write_unlock(struct inode *i)
13078+{
13079+ ii_do_write_unlock(i);
13080+ au_dbg_locked_ii_unreg(i, 0);
13081+}
13082+
13083+static inline void ii_downgrade_lock(struct inode *i)
13084+{
13085+ ii_do_downgrade_lock(i);
13086+}
13087+
13088+/* to debug easier, do not make them inlined functions */
13089+#define IiMustReadLock(i) do { \
13090+ SiMustAnyLock((i)->i_sb); \
13091+ AuRwMustReadLock(&au_ii(i)->ii_rwsem); \
13092+} while (0)
13093+
13094+#define IiMustWriteLock(i) do { \
13095+ SiMustAnyLock((i)->i_sb); \
13096+ AuRwMustWriteLock(&au_ii(i)->ii_rwsem); \
13097+} while (0)
13098+
13099+#define IiMustAnyLock(i) do { \
13100+ SiMustAnyLock((i)->i_sb); \
13101+ AuRwMustAnyLock(&au_ii(i)->ii_rwsem); \
13102+} while (0)
13103+
13104+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
13105+
13106+/* ---------------------------------------------------------------------- */
13107+
13108+static inline struct inode *au_igrab(struct inode *inode)
13109+{
13110+ if (inode) {
13111+ AuDebugOn(!atomic_read(&inode->i_count));
13112+ atomic_inc_return(&inode->i_count);
13113+ }
13114+ return inode;
13115+}
13116+
13117+/* ---------------------------------------------------------------------- */
13118+
13119+static inline aufs_bindex_t au_ibstart(struct inode *inode)
13120+{
13121+ /* lock free root dinfo/inode */
13122+ if (inode->i_ino != AUFS_ROOT_INO)
13123+ IiMustAnyLock(inode);
13124+ else
13125+ SiMustAnyLock(inode->i_sb);
13126+ return au_ii(inode)->ii_bstart;
13127+}
13128+
13129+static inline aufs_bindex_t au_ibend(struct inode *inode)
13130+{
13131+ /* lock free root dinfo/inode */
13132+ if (inode->i_ino != AUFS_ROOT_INO)
13133+ IiMustAnyLock(inode);
13134+ else
13135+ SiMustAnyLock(inode->i_sb);
13136+ return au_ii(inode)->ii_bend;
13137+}
13138+
13139+static inline struct au_vdir *au_ivdir(struct inode *inode)
13140+{
13141+ IiMustAnyLock(inode);
13142+ AuDebugOn(!S_ISDIR(inode->i_mode));
13143+ return au_ii(inode)->ii_vdir;
13144+}
13145+
13146+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
13147+{
13148+ struct au_hinode *hinode;
13149+ IiMustAnyLock(inode);
13150+ hinode = au_ii(inode)->ii_hinode + bindex;
13151+ return hinode->hi_whdentry;
13152+}
13153+
13154+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
13155+{
13156+ IiMustWriteLock(inode);
13157+ AuDebugOn(au_sbend(inode->i_sb) < bindex || bindex < au_ibstart(inode));
13158+ au_ii(inode)->ii_bend = bindex;
13159+}
13160+
13161+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
13162+{
13163+ IiMustWriteLock(inode);
13164+ AuDebugOn(!S_ISDIR(inode->i_mode) || (au_ii(inode)->ii_vdir && vdir));
13165+ au_ii(inode)->ii_vdir = vdir;
13166+}
13167+
13168+static inline void au_hiput(struct au_hinode *hinode)
13169+{
13170+ au_hin_free(hinode);
13171+ dput(hinode->hi_whdentry);
13172+ iput(hinode->hi_inode);
13173+}
13174+
13175+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
13176+{
13177+ /* todo: this lock check causes some unnecessary locks in callers. */
13178+ IiMustAnyLock(inode);
13179+ return au_ii(inode)->ii_hinode + bindex;
13180+}
13181+
13182+/* tiny test for inode number */
13183+/* tmpfs generation is too rough */
13184+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
13185+{
13186+ struct au_iinfo *iinfo;
13187+
13188+ IiMustAnyLock(inode);
13189+
13190+ iinfo = au_ii(inode);
13191+ return !(iinfo->ii_hsb1 == h_inode->i_sb
13192+ && iinfo->ii_higen == h_inode->i_generation);
13193+}
13194+
13195+static inline au_gen_t au_iigen(struct inode *inode)
13196+{
13197+ return atomic_read(&au_ii(inode)->ii_generation);
13198+}
13199+
13200+#ifdef CONFIG_AUFS_HINOTIFY
13201+static inline au_gen_t au_iigen_dec(struct inode *inode)
13202+{
13203+ /* AuDbg("i%lu\n", inode->i_ino); */
13204+ return atomic_dec_return(&au_ii(inode)->ii_generation);
13205+}
13206+#endif
13207+
13208+/* ---------------------------------------------------------------------- */
13209+
13210+#ifdef CONFIG_AUFS_HINOTIFY
13211+static inline struct au_pin1 *au_pin_gp(struct au_pin *args)
13212+{
13213+ return args->pin + AuPin_GPARENT;
13214+}
13215+
13216+/* hinotify.c */
13217+void au_unpin_gp(struct au_pin *args);
13218+
13219+#else
13220+
13221+static inline struct au_pin1 *au_pin_gp(struct au_pin *args)
13222+{
13223+ return NULL;
13224+}
13225+
13226+static inline void au_unpin_gp(struct au_pin *args)
13227+{
13228+ /* empty */
13229+}
13230+#endif /* HINOTIFY */
13231+
13232+static inline void au_unpin(struct au_pin *args)
13233+{
13234+ au_do_unpin(args->pin + AuPin_PARENT, au_pin_gp(args));
13235+}
13236+
13237+static inline
13238+struct au_hinode *au_do_pinned_hdir(struct au_pin1 *pin)
13239+{
13240+ if (pin && pin->parent)
13241+ return au_hi(pin->parent->d_inode, pin->bindex);
13242+ return NULL;
13243+}
13244+
13245+struct dentry *au_do_pinned_h_parent(struct au_pin1 *pin);
13246+
13247+static inline struct dentry *au_do_pinned_parent(struct au_pin1 *pin)
13248+{
13249+ if (pin)
13250+ return pin->parent;
13251+ return NULL;
13252+}
13253+
13254+static inline struct inode *au_do_pinned_h_dir(struct au_pin1 *pin)
13255+{
13256+ if (pin)
13257+ return pin->h_dir;
13258+ return NULL;
13259+}
13260+
13261+static inline
13262+void au_pin_do_set_dentry(struct au_pin1 *pin, struct dentry *dentry)
13263+{
13264+ if (pin)
13265+ pin->dentry = dentry;
13266+}
13267+
13268+static inline
13269+void au_pin_do_set_parent(struct au_pin1 *pin, struct dentry *parent)
13270+{
13271+ if (pin) {
13272+ dput(pin->parent);
13273+ pin->parent = dget(parent);
13274+ }
13275+}
13276+
13277+static inline void au_pin_do_set_h_dir(struct au_pin1 *pin, struct inode *h_dir)
13278+{
13279+ if (pin) {
13280+ iput(pin->h_dir);
13281+ pin->h_dir = au_igrab(h_dir);
13282+ }
13283+}
13284+
13285+static inline
13286+void au_pin_do_set_parent_lflag(struct au_pin1 *pin, unsigned char lflag)
13287+{
13288+ if (pin) {
13289+ /* dirty macros require brackets */
13290+ if (lflag) {
13291+ au_fset_pin(pin->flags, DI_LOCKED);
13292+ } else {
13293+ au_fclr_pin(pin->flags, DI_LOCKED);
13294+ }
13295+ }
13296+}
13297+
13298+static inline
13299+struct au_hinode *au_pinned_hdir(struct au_pin *args)
13300+{
13301+ return au_do_pinned_hdir(args->pin + AuPin_PARENT);
13302+}
13303+
13304+static inline
13305+struct au_hinode *au_pinned_hgdir(struct au_pin *args)
13306+{
13307+ return au_do_pinned_hdir(au_pin_gp(args));
13308+}
13309+
13310+static inline
13311+struct dentry *au_pinned_h_parent(struct au_pin *args)
13312+{
13313+ return au_do_pinned_h_parent(args->pin + AuPin_PARENT);
13314+}
13315+
13316+#if 0 /* reserved for future use */
13317+static inline
13318+struct dentry *au_pinned_h_gparent(struct au_pin *args)
13319+{
13320+ return au_do_pinned_h_parent(au_pin_gp(args));
13321+}
13322+#endif
13323+
13324+static inline
13325+struct dentry *au_pinned_parent(struct au_pin *args)
13326+{
13327+ return au_do_pinned_parent(args->pin + AuPin_PARENT);
13328+}
13329+
13330+static inline
13331+struct dentry *au_pinned_gparent(struct au_pin *args)
13332+{
13333+ return au_do_pinned_parent(au_pin_gp(args));
13334+}
13335+
13336+static inline
13337+struct inode *au_pinned_h_dir(struct au_pin *args)
13338+{
13339+ return au_do_pinned_h_dir(args->pin + AuPin_PARENT);
13340+}
13341+
13342+static inline
13343+struct inode *au_pinned_h_gdir(struct au_pin *args)
13344+{
13345+ return au_do_pinned_h_dir(au_pin_gp(args));
13346+}
13347+
13348+static inline void au_pin_set_parent(struct au_pin *args, struct dentry *d)
13349+{
13350+ au_pin_do_set_parent(args->pin + AuPin_PARENT, d);
13351+}
13352+
13353+static inline void au_pin_set_gparent(struct au_pin *args, struct dentry *d)
13354+{
13355+ au_pin_do_set_parent(au_pin_gp(args), d);
13356+}
13357+
13358+static inline void au_pin_set_h_dir(struct au_pin *args, struct inode *h_dir)
13359+{
13360+ au_pin_do_set_h_dir(args->pin + AuPin_PARENT, h_dir);
13361+}
13362+
13363+static inline void au_pin_set_h_gdir(struct au_pin *args, struct inode *h_dir)
13364+{
13365+ au_pin_do_set_h_dir(au_pin_gp(args), h_dir);
13366+}
13367+
13368+static inline
13369+void au_pin_set_parent_lflag(struct au_pin *args, unsigned char lflag)
13370+{
13371+ au_pin_do_set_parent_lflag(args->pin + AuPin_PARENT, lflag);
13372+}
13373+
13374+static inline
13375+void au_pin_set_gparent_lflag(struct au_pin *args, unsigned char lflag)
13376+{
13377+ au_pin_do_set_parent_lflag(au_pin_gp(args), lflag);
13378+}
13379+
13380+#endif /* __KERNEL__ */
13381+#endif /* __AUFS_INODE_H__ */
13382diff -urN linux/fs/aufs/i_op_add.c linux-aufs/fs/aufs/i_op_add.c
13383--- linux/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
13384+++ linux-aufs/fs/aufs/i_op_add.c 2009-03-12 16:18:04.000000000 +0100
13385@@ -0,0 +1,757 @@
13386+/*
13387+ * Copyright (C) 2005-2009 Junjiro Okajima
13388+ *
13389+ * This program, aufs is free software; you can redistribute it and/or modify
13390+ * it under the terms of the GNU General Public License as published by
13391+ * the Free Software Foundation; either version 2 of the License, or
13392+ * (at your option) any later version.
13393+ *
13394+ * This program is distributed in the hope that it will be useful,
13395+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13396+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13397+ * GNU General Public License for more details.
13398+ *
13399+ * You should have received a copy of the GNU General Public License
13400+ * along with this program; if not, write to the Free Software
13401+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13402+ */
13403+
13404+/*
13405+ * inode operations (add entry)
13406+ *
13407+ * $Id$
13408+ */
13409+
13410+#include "aufs.h"
13411+
13412+/*
13413+ * final procedure of adding a new entry, except link(2).
13414+ * remove whiteout, instantiate, copyup the parent dir's times and size
13415+ * and update version.
13416+ * if it failed, re-create the removed whiteout.
13417+ */
13418+static int epilog(struct inode *dir, aufs_bindex_t bindex,
13419+ struct dentry *wh_dentry, struct dentry *dentry)
13420+{
13421+ int err, rerr;
13422+ aufs_bindex_t bwh;
13423+ struct inode *inode, *h_dir;
13424+ struct dentry *wh;
13425+ struct au_ndx ndx;
13426+ struct super_block *sb;
13427+
13428+ LKTRTrace("wh %p, %.*s\n", wh_dentry, AuDLNPair(dentry));
13429+
13430+ sb = dentry->d_sb;
13431+ bwh = -1;
13432+ if (wh_dentry) {
13433+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
13434+ IMustLock(h_dir);
13435+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
13436+ bwh = au_dbwh(dentry);
13437+ err = au_wh_unlink_dentry(au_hi(dir, bindex), wh_dentry, dentry,
13438+ /*dlgt*/0);
13439+ if (unlikely(err))
13440+ goto out;
13441+ }
13442+
13443+ inode = au_new_inode(dentry, /*must_new*/1);
13444+ if (!IS_ERR(inode)) {
13445+ d_instantiate(dentry, inode);
13446+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
13447+ IMustLock(dir);
13448+ /* or always cpup dir mtime? */
13449+ if (au_ibstart(dir) == au_dbstart(dentry))
13450+ au_cpup_attr_timesizes(dir);
13451+ dir->i_version++;
13452+ return 0; /* success */
13453+ }
13454+
13455+ err = PTR_ERR(inode);
13456+ if (!wh_dentry)
13457+ goto out;
13458+
13459+ /* revert */
13460+ ndx.flags = 0;
13461+ if (au_test_dlgt(au_mntflags(sb)))
13462+ au_fset_ndx(ndx.flags, DLGT);
13463+ ndx.nfsmnt = au_nfsmnt(sb, bwh);
13464+ ndx.nd = NULL;
13465+ /* ndx.br = NULL; */
13466+ /* dir inode is locked */
13467+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent, &ndx);
13468+ rerr = PTR_ERR(wh);
13469+ if (IS_ERR(wh)) {
13470+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
13471+ AuDLNPair(dentry), err, rerr);
13472+ err = -EIO;
13473+ } else
13474+ dput(wh);
13475+
13476+ out:
13477+ AuTraceErr(err);
13478+ return err;
13479+}
13480+
13481+/*
13482+ * simple tests for the adding inode operations.
13483+ * following the checks in vfs, plus the parent-child relationship.
13484+ */
13485+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13486+ struct dentry *h_parent, int isdir, struct au_ndx *ndx)
13487+{
13488+ int err, exist;
13489+ struct dentry *h_dentry;
13490+ struct inode *h_inode;
13491+ umode_t h_mode;
13492+
13493+ LKTRTrace("%.*s/%.*s, b%d, dir %d\n",
13494+ AuDLNPair(h_parent), AuDLNPair(dentry), bindex, isdir);
13495+
13496+ exist = !!dentry->d_inode;
13497+ h_dentry = au_h_dptr(dentry, bindex);
13498+ h_inode = h_dentry->d_inode;
13499+ if (!exist) {
13500+ err = -EEXIST;
13501+ if (unlikely(h_inode))
13502+ goto out;
13503+ } else {
13504+ /* rename(2) case */
13505+ err = -EIO;
13506+ if (unlikely(!h_inode || !h_inode->i_nlink))
13507+ goto out;
13508+
13509+ h_mode = h_inode->i_mode;
13510+ if (!isdir) {
13511+ err = -EISDIR;
13512+ if (unlikely(S_ISDIR(h_mode)))
13513+ goto out;
13514+ } else if (unlikely(!S_ISDIR(h_mode))) {
13515+ err = -ENOTDIR;
13516+ goto out;
13517+ }
13518+ }
13519+
13520+ err = -EIO;
13521+ /* expected parent dir is locked */
13522+ if (unlikely(h_parent != h_dentry->d_parent))
13523+ goto out;
13524+ err = 0;
13525+
13526+ if (au_opt_test(au_mntflags(dentry->d_sb), UDBA_INOTIFY)) {
13527+ struct dentry *h_latest;
13528+ struct qstr *qstr = &dentry->d_name;
13529+
13530+ err = -EACCES;
13531+ if (unlikely(au_test_h_perm
13532+ (h_parent->d_inode, MAY_EXEC | MAY_WRITE,
13533+ au_ftest_ndx(ndx->flags, DLGT))))
13534+ goto out;
13535+
13536+ h_latest = au_sio_lkup_one(qstr->name, h_parent, qstr->len,
13537+ ndx);
13538+ err = PTR_ERR(h_latest);
13539+ if (IS_ERR(h_latest))
13540+ goto out;
13541+ err = -EIO;
13542+ dput(h_latest);
13543+ /* fuse d_revalidate always return 0 for negative dentries */
13544+ if (h_latest == h_dentry || au_test_fuse(h_dentry->d_sb))
13545+ err = 0;
13546+ }
13547+
13548+ out:
13549+ AuTraceErr(err);
13550+ return err;
13551+}
13552+
13553+/*
13554+ * initial procedure of adding a new entry.
13555+ * prepare writable branch and the parent dir, lock it,
13556+ * lookup whiteout for the new entry.
13557+ */
13558+static struct dentry*
13559+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
13560+ struct dentry *src_dentry, struct au_pin *pin,
13561+ struct au_wr_dir_args *wr_dir_args)
13562+{
13563+ struct dentry *wh_dentry, *h_parent;
13564+ struct super_block *sb;
13565+ int err;
13566+ unsigned int mnt_flags;
13567+ unsigned char pin_flags;
13568+ aufs_bindex_t bstart, bcpup;
13569+ struct au_ndx ndx;
13570+
13571+ LKTRTrace("%.*s, src %p\n", AuDLNPair(dentry), src_dentry);
13572+
13573+ bstart = au_dbstart(dentry);
13574+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
13575+ bcpup = err;
13576+ wh_dentry = ERR_PTR(err);
13577+ if (unlikely(err < 0))
13578+ goto out;
13579+
13580+ sb = dentry->d_sb;
13581+ mnt_flags = au_mntflags(sb);
13582+ pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
13583+ if (dt && au_opt_test(mnt_flags, UDBA_INOTIFY))
13584+ au_fset_pin(pin_flags, DO_GPARENT);
13585+ err = au_pin(pin, dentry, bcpup, pin_flags);
13586+ wh_dentry = ERR_PTR(err);
13587+ if (unlikely(err))
13588+ goto out;
13589+
13590+ ndx.nfsmnt = au_nfsmnt(sb, bcpup);
13591+ ndx.flags = 0;
13592+ if (au_test_dlgt(mnt_flags))
13593+ au_fset_ndx(ndx.flags, DLGT);
13594+ ndx.nd = NULL;
13595+ /* ndx.br = NULL; */
13596+ /* ndx.nd_file = NULL; */
13597+
13598+ h_parent = au_pinned_h_parent(pin);
13599+ if (!au_opt_test(mnt_flags, UDBA_NONE) && au_dbstart(dentry) == bcpup) {
13600+ struct nameidata nd;
13601+
13602+ if (ndx.nfsmnt) {
13603+ /* todo: dirty? */
13604+ ndx.nd = &nd;
13605+ ndx.br = au_sbr(sb, bcpup);
13606+ memset(&nd, 0, sizeof(nd));
13607+ nd.flags = LOOKUP_CREATE;
13608+ nd.intent.open.flags = O_EXCL;
13609+ }
13610+ err = au_may_add(dentry, bcpup, h_parent,
13611+ au_ftest_wrdir(wr_dir_args->flags, ISDIR),
13612+ &ndx);
13613+ wh_dentry = ERR_PTR(err);
13614+ if (unlikely(err))
13615+ goto out_unpin;
13616+ ndx.nd = NULL;
13617+ ndx.br = NULL;
13618+ }
13619+
13620+ if (dt)
13621+ au_dtime_store(dt, au_pinned_parent(pin), h_parent,
13622+ au_pinned_hdir(pin), au_pinned_hgdir(pin));
13623+
13624+ wh_dentry = NULL;
13625+ if (/* bcpup != bstart || */ bcpup != au_dbwh(dentry))
13626+ goto out; /* success */
13627+
13628+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, &ndx);
13629+
13630+ out_unpin:
13631+ if (IS_ERR(wh_dentry))
13632+ au_unpin(pin);
13633+ out:
13634+ AuTraceErrPtr(wh_dentry);
13635+ return wh_dentry;
13636+}
13637+
13638+/* ---------------------------------------------------------------------- */
13639+
13640+enum { Mknod, Symlink, Creat };
13641+struct simple_arg {
13642+ int type;
13643+ union {
13644+ struct {
13645+ int mode;
13646+ struct nameidata *nd;
13647+ } c;
13648+ struct {
13649+ const char *symname;
13650+ } s;
13651+ struct {
13652+ int mode;
13653+ dev_t dev;
13654+ } m;
13655+ } u;
13656+};
13657+
13658+static int add_simple(struct inode *dir, struct dentry *dentry,
13659+ struct simple_arg *arg)
13660+{
13661+ int err;
13662+ struct dentry *h_dentry, *wh_dentry, *parent;
13663+ struct inode *h_dir;
13664+ struct au_dtime dt;
13665+ struct vfsub_args vargs;
13666+ struct super_block *sb;
13667+ aufs_bindex_t bstart;
13668+ unsigned char created;
13669+ struct au_hin_ignore ign;
13670+ struct au_pin pin;
13671+ struct au_wr_dir_args wr_dir_args = {
13672+ .force_btgt = -1,
13673+ .flags = AuWrDir_ADD_ENTRY
13674+ };
13675+
13676+ LKTRTrace("type %d, %.*s\n", arg->type, AuDLNPair(dentry));
13677+ IMustLock(dir);
13678+
13679+ sb = dir->i_sb;
13680+ parent = dentry->d_parent; /* dir inode is locked */
13681+ aufs_read_lock(dentry, AuLock_DW);
13682+ vfsub_args_init(&vargs, &ign, !!au_test_dlgt(au_mntflags(sb)), 0);
13683+ di_write_lock_parent(parent);
13684+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
13685+ &wr_dir_args);
13686+ err = PTR_ERR(wh_dentry);
13687+ if (IS_ERR(wh_dentry))
13688+ goto out;
13689+
13690+ bstart = au_dbstart(dentry);
13691+ h_dentry = au_h_dptr(dentry, bstart);
13692+ h_dir = au_pinned_h_dir(&pin);
13693+ vfsub_ign_hinode(&vargs, IN_CREATE, au_pinned_hdir(&pin));
13694+
13695+ switch (arg->type) {
13696+ case Creat:
13697+ AuDebugOn(au_test_nfs(h_dir->i_sb) && !arg->u.c.nd);
13698+ err = au_h_create(h_dir, h_dentry, arg->u.c.mode, &vargs,
13699+ arg->u.c.nd, au_nfsmnt(sb, bstart));
13700+ break;
13701+ case Symlink:
13702+ err = vfsub_symlink(h_dir, h_dentry, arg->u.s.symname,
13703+ S_IALLUGO, &vargs);
13704+ break;
13705+ case Mknod:
13706+ err = vfsub_mknod(h_dir, h_dentry, arg->u.m.mode, arg->u.m.dev,
13707+ &vargs);
13708+ break;
13709+ default:
13710+ BUG();
13711+ }
13712+ created = !err;
13713+ if (!err)
13714+ err = epilog(dir, bstart, wh_dentry, dentry);
13715+
13716+ /* revert */
13717+ if (unlikely(created && err && h_dentry->d_inode)) {
13718+ int rerr;
13719+ vfsub_args_reinit(&vargs);
13720+ vfsub_ign_hinode(&vargs, IN_DELETE, au_pinned_hdir(&pin));
13721+ rerr = vfsub_unlink(h_dir, h_dentry, &vargs);
13722+ if (rerr) {
13723+ AuIOErr("%.*s revert failure(%d, %d)\n",
13724+ AuDLNPair(dentry), err, rerr);
13725+ err = -EIO;
13726+ }
13727+ /* todo: inotify will be fired to the grand parent dir? */
13728+ au_dtime_revert(&dt);
13729+ d_drop(dentry);
13730+ }
13731+
13732+ au_unpin(&pin);
13733+ dput(wh_dentry);
13734+
13735+ out:
13736+ if (unlikely(err)) {
13737+ au_update_dbstart(dentry);
13738+ d_drop(dentry);
13739+ }
13740+ di_write_unlock(parent);
13741+ aufs_read_unlock(dentry, AuLock_DW);
13742+ AuTraceErr(err);
13743+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
13744+ err = -ESTALE;
13745+ return err;
13746+}
13747+
13748+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
13749+{
13750+ struct simple_arg arg = {
13751+ .type = Mknod,
13752+ .u.m = {
13753+ .mode = mode,
13754+ .dev = dev
13755+ }
13756+ };
13757+ return add_simple(dir, dentry, &arg);
13758+}
13759+
13760+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
13761+{
13762+ struct simple_arg arg = {
13763+ .type = Symlink,
13764+ .u.s.symname = symname
13765+ };
13766+ return add_simple(dir, dentry, &arg);
13767+}
13768+
13769+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13770+ struct nameidata *nd)
13771+{
13772+ struct simple_arg arg = {
13773+ .type = Creat,
13774+ .u.c = {
13775+ .mode = mode,
13776+ .nd = nd
13777+ }
13778+ };
13779+ return add_simple(dir, dentry, &arg);
13780+}
13781+
13782+/* ---------------------------------------------------------------------- */
13783+
13784+struct au_link_args {
13785+ unsigned int mnt_flags;
13786+ unsigned char pin_flags;
13787+ aufs_bindex_t bdst, bsrc;
13788+ struct vfsub_args vargs;
13789+ struct au_pin pin;
13790+ struct au_hin_ignore ign;
13791+ struct dentry *h_dentry;
13792+ struct dentry *src_parent, *parent;
13793+};
13794+
13795+static int au_cpup_before_link(struct dentry *src_dentry, struct inode *dir,
13796+ struct dentry *dentry, struct au_link_args *a)
13797+{
13798+ int err;
13799+ const int hinotify = au_opt_test(a->mnt_flags, UDBA_INOTIFY);
13800+ struct mutex *h_mtx;
13801+
13802+ LKTRTrace("src %.*s, i%lu, dst %.*s\n",
13803+ AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry));
13804+
13805+ di_read_lock_parent(a->src_parent, AuLock_IR);
13806+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
13807+ if (unlikely(err))
13808+ goto out;
13809+
13810+ AuDebugOn(au_dbstart(src_dentry) != a->bsrc);
13811+ h_mtx = &au_h_dptr(src_dentry, a->bsrc)->d_inode->i_mutex;
13812+ a->pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
13813+ if (hinotify)
13814+ au_fset_pin(a->pin_flags, DO_GPARENT);
13815+ err = au_pin(&a->pin, src_dentry, a->bdst, a->pin_flags);
13816+ if (unlikely(err))
13817+ goto out;
13818+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13819+ /* todo: no KEEPLINO because of noplink? */
13820+ err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
13821+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
13822+ mutex_unlock(h_mtx);
13823+ au_unpin(&a->pin);
13824+
13825+ out:
13826+ di_read_unlock(a->src_parent, AuLock_IR);
13827+ AuTraceErr(err);
13828+ return err;
13829+}
13830+
13831+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
13832+{
13833+ int err;
13834+ struct inode *h_inode;
13835+ aufs_bindex_t bstart;
13836+ struct dentry *h_src_dentry;
13837+
13838+ AuTraceEnter();
13839+ AuDebugOn(au_dbstart(src_dentry) != a->bsrc);
13840+
13841+ bstart = au_ibstart(src_dentry->d_inode);
13842+ h_inode = NULL;
13843+ if (bstart <= a->bdst)
13844+ h_inode = au_h_iptr(src_dentry->d_inode, a->bdst);
13845+ if (!h_inode || !h_inode->i_nlink) {
13846+ /* copyup src_dentry as the name of dentry. */
13847+ au_set_dbstart(src_dentry, a->bdst);
13848+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_dentry));
13849+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
13850+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
13851+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
13852+ AuCpup_KEEPLINO, a->parent);
13853+ mutex_unlock(&h_inode->i_mutex);
13854+ au_set_h_dptr(src_dentry, a->bdst, NULL);
13855+ au_set_dbstart(src_dentry, a->bsrc);
13856+ } else {
13857+ /* the inode of src_dentry already exists on a.bdst branch */
13858+ h_src_dentry = d_find_alias(h_inode);
13859+ if (h_src_dentry) {
13860+ /* vfsub_args_reinit(&a->vargs); */
13861+ vfsub_ign_hinode(&a->vargs, IN_CREATE,
13862+ au_pinned_hdir(&a->pin));
13863+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13864+ a->h_dentry, &a->vargs);
13865+ dput(h_src_dentry);
13866+ } else {
13867+ AuIOErr("no dentry found for i%lu on b%d\n",
13868+ h_inode->i_ino, a->bdst);
13869+ err = -EIO;
13870+ }
13871+ }
13872+
13873+ if (!err)
13874+ au_plink_append(src_dentry->d_sb, src_dentry->d_inode,
13875+ a->h_dentry, a->bdst);
13876+
13877+ AuTraceErr(err);
13878+ return err;
13879+}
13880+
13881+int aufs_link(struct dentry *src_dentry, struct inode *dir,
13882+ struct dentry *dentry)
13883+{
13884+ int err, rerr;
13885+ struct au_dtime dt;
13886+ struct super_block *sb;
13887+ struct au_link_args *a;
13888+ struct au_wr_dir_args wr_dir_args = {
13889+ /* .force_btgt = -1, */
13890+ .flags = AuWrDir_ADD_ENTRY
13891+ };
13892+ struct dentry *wh_dentry, *h_src_dentry;
13893+ struct inode *inode;
13894+
13895+ LKTRTrace("src %.*s, i%lu, dst %.*s\n",
13896+ AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry));
13897+ IMustLock(dir);
13898+ inode = src_dentry->d_inode;
13899+ IMustLock(inode);
13900+ AuDebugOn(S_ISDIR(inode->i_mode));
13901+
13902+ err = -ENOMEM;
13903+ a = kzalloc(sizeof(*a), GFP_NOFS);
13904+ if (unlikely(!a))
13905+ goto out;
13906+
13907+ sb = dentry->d_sb;
13908+ a->parent = dentry->d_parent; /* dir inode is locked */
13909+ aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
13910+ a->src_parent = dget_parent(src_dentry);
13911+ wr_dir_args.force_btgt = au_dbstart(src_dentry);
13912+ a->mnt_flags = au_mntflags(sb);
13913+ vfsub_args_init(&a->vargs, &a->ign, au_test_dlgt(a->mnt_flags), 0);
13914+
13915+ di_write_lock_parent(a->parent);
13916+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
13917+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
13918+ &wr_dir_args);
13919+ err = PTR_ERR(wh_dentry);
13920+ if (IS_ERR(wh_dentry))
13921+ goto out_unlock;
13922+ err = 0;
13923+
13924+ a->bdst = au_dbstart(dentry);
13925+ a->h_dentry = au_h_dptr(dentry, a->bdst);
13926+
13927+ /* todo: minor optimize,
13928+ their sb may be same while their bindex differs? */
13929+ a->bsrc = au_dbstart(src_dentry);
13930+ if (au_opt_test(a->mnt_flags, PLINK)) {
13931+ if (a->bdst < a->bsrc
13932+ /* && h_src_dentry->d_sb != a->h_dentry->d_sb */)
13933+ err = au_cpup_or_link(src_dentry, a);
13934+ else {
13935+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13936+ AuDebugOn(!h_src_dentry);
13937+ AuDebugOn(!h_src_dentry->d_inode);
13938+ vfsub_ign_hinode(&a->vargs, IN_CREATE,
13939+ au_pinned_hdir(&a->pin));
13940+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13941+ a->h_dentry, &a->vargs);
13942+ }
13943+ } else {
13944+ /*
13945+ * copyup src_dentry to the branch we process,
13946+ * and then link(2) to it.
13947+ */
13948+ if (a->bdst < a->bsrc
13949+ /* && h_src_dentry->d_sb != a->h_dentry->d_sb */) {
13950+ au_unpin(&a->pin);
13951+ di_write_unlock(a->parent);
13952+ err = au_cpup_before_link(src_dentry, dir, dentry, a);
13953+ if (!err) {
13954+ a->pin_flags
13955+ = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
13956+ if (au_opt_test(a->mnt_flags, UDBA_INOTIFY))
13957+ au_fset_pin(a->pin_flags, DO_GPARENT);
13958+ di_write_lock_parent(a->parent);
13959+ err = au_pin(&a->pin, dentry, a->bdst,
13960+ a->pin_flags);
13961+ if (unlikely(err))
13962+ goto out_wh;
13963+ }
13964+ }
13965+ if (!err) {
13966+ /* vfsub_args_reinit(&a->vargs); */
13967+ vfsub_ign_hinode(&a->vargs, IN_CREATE,
13968+ au_pinned_hdir(&a->pin));
13969+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13970+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13971+ a->h_dentry, &a->vargs);
13972+ }
13973+ }
13974+ if (unlikely(err))
13975+ goto out_unpin;
13976+
13977+ if (wh_dentry) {
13978+ err = au_wh_unlink_dentry(au_pinned_hdir(&a->pin), wh_dentry,
13979+ dentry, /*dlgt*/0);
13980+ if (unlikely(err))
13981+ goto out_revert;
13982+ }
13983+
13984+#if 0 /* cannot support it */
13985+ /* fuse has different memory inode for the same inode number */
13986+ if (au_test_fuse(a->h_dentry->d_sb)) {
13987+ LKTRLabel(here);
13988+ d_drop(a->h_dentry);
13989+ /*d_drop(h_src_dentry);
13990+ d_drop(src_dentry);*/
13991+ inc_nlink(a->inode);
13992+ a->inode->i_ctime = dir->i_ctime;
13993+ }
13994+#endif
13995+
13996+ dir->i_version++;
13997+ if (au_ibstart(dir) == au_dbstart(dentry))
13998+ au_cpup_attr_timesizes(dir);
13999+ if (!d_unhashed(a->h_dentry)
14000+ /* || h_old_inode->i_nlink <= nlink */
14001+ /* || SB_NFS(h_src_dentry->d_sb) */) {
14002+ d_instantiate(dentry, au_igrab(inode));
14003+ inc_nlink(inode);
14004+ inode->i_ctime = dir->i_ctime;
14005+ } else
14006+ /* nfs case (< 2.6.15) */
14007+ d_drop(dentry);
14008+ goto out_unpin; /* success */
14009+
14010+ out_revert:
14011+ vfsub_args_reinit(&a->vargs);
14012+ vfsub_ign_hinode(&a->vargs, IN_DELETE, au_pinned_hdir(&a->pin));
14013+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), a->h_dentry, &a->vargs);
14014+ if (!rerr)
14015+ goto out_dt;
14016+ AuIOErr("%.*s reverting failed(%d, %d)\n",
14017+ AuDLNPair(dentry), err, rerr);
14018+ err = -EIO;
14019+ out_dt:
14020+ d_drop(dentry);
14021+ au_dtime_revert(&dt);
14022+ out_unpin:
14023+ au_unpin(&a->pin);
14024+ out_wh:
14025+ dput(wh_dentry);
14026+ out_unlock:
14027+ if (unlikely(err)) {
14028+ au_update_dbstart(dentry);
14029+ d_drop(dentry);
14030+ }
14031+ di_write_unlock(a->parent);
14032+ dput(a->src_parent);
14033+ aufs_read_and_write_unlock2(dentry, src_dentry);
14034+ kfree(a);
14035+ out:
14036+ AuTraceErr(err);
14037+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
14038+ err = -ESTALE;
14039+ return err;
14040+}
14041+
14042+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
14043+{
14044+ int err, rerr;
14045+ struct dentry *h_dentry, *wh_dentry, *parent, *opq_dentry;
14046+ struct mutex *h_mtx;
14047+ struct au_dtime dt;
14048+ aufs_bindex_t bindex;
14049+ unsigned char diropq, dlgt;
14050+ unsigned int mnt_flags;
14051+ struct au_hin_ignore ign;
14052+ struct vfsub_args vargs;
14053+ struct au_pin pin;
14054+ struct au_wr_dir_args wr_dir_args = {
14055+ .force_btgt = -1,
14056+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
14057+ };
14058+
14059+ LKTRTrace("i%lu, %.*s, mode 0%o\n",
14060+ dir->i_ino, AuDLNPair(dentry), mode);
14061+ IMustLock(dir);
14062+
14063+ aufs_read_lock(dentry, AuLock_DW);
14064+ parent = dentry->d_parent; /* dir inode is locked */
14065+ mnt_flags = au_mntflags(dentry->d_sb);
14066+ dlgt = !!au_test_dlgt(mnt_flags);
14067+ vfsub_args_init(&vargs, &ign, dlgt, 0);
14068+
14069+ di_write_lock_parent(parent);
14070+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
14071+ &wr_dir_args);
14072+ err = PTR_ERR(wh_dentry);
14073+ if (IS_ERR(wh_dentry))
14074+ goto out;
14075+
14076+ bindex = au_dbstart(dentry);
14077+ h_dentry = au_h_dptr(dentry, bindex);
14078+ vfsub_ign_hinode(&vargs, IN_CREATE, au_pinned_hdir(&pin));
14079+ err = vfsub_mkdir(au_pinned_h_dir(&pin), h_dentry, mode, &vargs);
14080+ if (unlikely(err))
14081+ goto out_unlock;
14082+
14083+ /* make the dir opaque */
14084+ diropq = 0;
14085+ h_mtx = &h_dentry->d_inode->i_mutex;
14086+ if (wh_dentry || au_opt_test(mnt_flags, ALWAYS_DIROPQ)) {
14087+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14088+ opq_dentry = au_diropq_create(dentry, bindex, /*dlgt*/0);
14089+ mutex_unlock(h_mtx);
14090+ err = PTR_ERR(opq_dentry);
14091+ if (IS_ERR(opq_dentry))
14092+ goto out_dir;
14093+ dput(opq_dentry);
14094+ diropq = 1;
14095+ }
14096+
14097+ err = epilog(dir, bindex, wh_dentry, dentry);
14098+ if (!err) {
14099+ inc_nlink(dir);
14100+ goto out_unlock; /* success */
14101+ }
14102+
14103+ /* revert */
14104+ if (diropq) {
14105+ LKTRLabel(revert opq);
14106+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14107+ rerr = au_diropq_remove(dentry, bindex, dlgt);
14108+ mutex_unlock(h_mtx);
14109+ if (rerr) {
14110+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
14111+ AuDLNPair(dentry), err, rerr);
14112+ err = -EIO;
14113+ }
14114+ }
14115+
14116+ out_dir:
14117+ LKTRLabel(revert dir);
14118+ vfsub_args_reinit(&vargs);
14119+ vfsub_ign_hinode(&vargs, IN_DELETE, au_pinned_hdir(&pin));
14120+ rerr = vfsub_rmdir(au_pinned_h_dir(&pin), h_dentry, &vargs);
14121+ if (rerr) {
14122+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
14123+ AuDLNPair(dentry), err, rerr);
14124+ err = -EIO;
14125+ }
14126+ d_drop(dentry);
14127+ au_dtime_revert(&dt);
14128+ out_unlock:
14129+ au_unpin(&pin);
14130+ dput(wh_dentry);
14131+ out:
14132+ if (unlikely(err)) {
14133+ au_update_dbstart(dentry);
14134+ d_drop(dentry);
14135+ }
14136+ di_write_unlock(parent);
14137+ aufs_read_unlock(dentry, AuLock_DW);
14138+ AuTraceErr(err);
14139+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
14140+ err = -ESTALE;
14141+ return err;
14142+}
14143diff -urN linux/fs/aufs/i_op.c linux-aufs/fs/aufs/i_op.c
14144--- linux/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
14145+++ linux-aufs/fs/aufs/i_op.c 2009-03-12 16:18:04.000000000 +0100
14146@@ -0,0 +1,1049 @@
14147+/*
14148+ * Copyright (C) 2005-2009 Junjiro Okajima
14149+ *
14150+ * This program, aufs is free software; you can redistribute it and/or modify
14151+ * it under the terms of the GNU General Public License as published by
14152+ * the Free Software Foundation; either version 2 of the License, or
14153+ * (at your option) any later version.
14154+ *
14155+ * This program is distributed in the hope that it will be useful,
14156+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14157+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14158+ * GNU General Public License for more details.
14159+ *
14160+ * You should have received a copy of the GNU General Public License
14161+ * along with this program; if not, write to the Free Software
14162+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14163+ */
14164+
14165+/*
14166+ * inode operations (except add/del/rename)
14167+ *
14168+ * $Id$
14169+ */
14170+
14171+#include <linux/fs_stack.h>
14172+#include <linux/uaccess.h>
14173+#include "aufs.h"
14174+
14175+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
14176+static int h_permission(struct inode *h_inode, int mask,
14177+ struct vfsmount *h_mnt, int brperm, int dlgt)
14178+{
14179+ int err, submask;
14180+ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
14181+
14182+ LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n",
14183+ h_inode->i_ino, mask, brperm);
14184+
14185+ err = -EACCES;
14186+ if ((write_mask && IS_IMMUTABLE(h_inode))
14187+ || ((mask & MAY_EXEC) && S_ISREG(h_inode->i_mode)
14188+ && (h_mnt->mnt_flags & MNT_NOEXEC)))
14189+ goto out;
14190+
14191+ /*
14192+ * - skip hidden fs test in the case of write to ro branch.
14193+ * - nfs dir permission write check is optimized, but a policy for
14194+ * link/rename requires a real check.
14195+ */
14196+ submask = mask & ~MAY_APPEND;
14197+ if ((write_mask && !au_br_writable(brperm))
14198+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
14199+ && write_mask && !(mask & MAY_READ))
14200+ || !h_inode->i_op
14201+ || !h_inode->i_op->permission) {
14202+ /* LKTRLabel(generic_permission); */
14203+ err = generic_permission(h_inode, submask, NULL);
14204+ } else {
14205+ /* LKTRLabel(h_inode->permission); */
14206+ err = h_inode->i_op->permission(h_inode, submask);
14207+ AuTraceErr(err);
14208+ }
14209+
14210+#if 1 /* todo: export? */
14211+ if (!err)
14212+ err = au_security_inode_permission(h_inode, mask, NULL,
14213+ dlgt);
14214+#endif
14215+
14216+ out:
14217+ AuTraceErr(err);
14218+ return err;
14219+}
14220+
14221+static int aufs_permission(struct inode *inode, int mask)
14222+{
14223+ int err;
14224+ aufs_bindex_t bindex, bend;
14225+ unsigned char dlgt;
14226+ const unsigned char isdir = S_ISDIR(inode->i_mode);
14227+ struct inode *h_inode;
14228+ struct super_block *sb;
14229+ unsigned int mnt_flags;
14230+ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
14231+
14232+ LKTRTrace("ino %lu, mask 0x%x, isdir %d, write_mask %d\n",
14233+ inode->i_ino, mask, isdir, write_mask);
14234+
14235+ sb = inode->i_sb;
14236+ si_read_lock(sb, AuLock_FLUSH);
14237+ ii_read_lock_child(inode);
14238+ mnt_flags = au_mntflags(sb);
14239+ dlgt = !!au_test_dlgt(mnt_flags);
14240+
14241+ if (!isdir || write_mask || au_test_dirperm1(mnt_flags)) {
14242+ h_inode = au_h_iptr(inode, au_ibstart(inode));
14243+ AuDebugOn(!h_inode
14244+ || ((h_inode->i_mode & S_IFMT)
14245+ != (inode->i_mode & S_IFMT)));
14246+ err = 0;
14247+ bindex = au_ibstart(inode);
14248+ LKTRTrace("b%d\n", bindex);
14249+ err = h_permission(h_inode, mask, au_sbr_mnt(sb, bindex),
14250+ au_sbr_perm(sb, bindex), dlgt);
14251+
14252+ if (write_mask && !err) {
14253+ /* test whether the upper writable branch exists */
14254+ err = -EROFS;
14255+ for (; bindex >= 0; bindex--)
14256+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
14257+ err = 0;
14258+ break;
14259+ }
14260+ }
14261+ goto out;
14262+ }
14263+
14264+ /* non-write to dir */
14265+ err = 0;
14266+ bend = au_ibend(inode);
14267+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
14268+ h_inode = au_h_iptr(inode, bindex);
14269+ if (!h_inode)
14270+ continue;
14271+ AuDebugOn(!S_ISDIR(h_inode->i_mode));
14272+
14273+ LKTRTrace("b%d\n", bindex);
14274+ err = h_permission(h_inode, mask, au_sbr_mnt(sb, bindex),
14275+ au_sbr_perm(sb, bindex), dlgt);
14276+ }
14277+
14278+ out:
14279+ ii_read_unlock(inode);
14280+ si_read_unlock(sb);
14281+ AuTraceErr(err);
14282+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
14283+ err = -ESTALE;
14284+ return err;
14285+}
14286+#else
14287+
14288+static int silly_lock(struct inode *inode, struct nameidata *nd)
14289+{
14290+ int locked = 0;
14291+ struct super_block *sb = inode->i_sb;
14292+
14293+ LKTRTrace("i%lu, nd %p\n", inode->i_ino, nd);
14294+
14295+ if (!nd || !nd->path.dentry) {
14296+ si_read_lock(sb, AuLock_FLUSH);
14297+ ii_read_lock_child(inode);
14298+ } else if (nd->path.dentry->d_inode != inode) {
14299+ locked = 1;
14300+ /* lock child first, then parent */
14301+ si_read_lock(sb, AuLock_FLUSH);
14302+ ii_read_lock_child(inode);
14303+ di_read_lock_parent(nd->path.dentry, 0);
14304+ } else {
14305+ locked = 2;
14306+ aufs_read_lock(nd->path.dentry, AuLock_FLUSH | AuLock_IR);
14307+ }
14308+ return locked;
14309+}
14310+
14311+static void silly_unlock(int locked, struct inode *inode, struct nameidata *nd)
14312+{
14313+ struct super_block *sb = inode->i_sb;
14314+
14315+ LKTRTrace("locked %d, i%lu, nd %p\n", locked, inode->i_ino, nd);
14316+
14317+ switch (locked) {
14318+ case 0:
14319+ ii_read_unlock(inode);
14320+ si_read_unlock(sb);
14321+ break;
14322+ case 1:
14323+ di_read_unlock(nd->path.dentry, 0);
14324+ ii_read_unlock(inode);
14325+ si_read_unlock(sb);
14326+ break;
14327+ case 2:
14328+ aufs_read_unlock(nd->path.dentry, AuLock_IR);
14329+ break;
14330+ default:
14331+ BUG();
14332+ }
14333+}
14334+
14335+static int h_permission(struct inode *h_inode, int mask,
14336+ struct nameidata *fake_nd, int brperm, int dlgt)
14337+{
14338+ int err, submask;
14339+ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
14340+
14341+ LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n",
14342+ h_inode->i_ino, mask, brperm);
14343+
14344+ err = -EACCES;
14345+ if ((write_mask && IS_IMMUTABLE(h_inode))
14346+ || ((mask & MAY_EXEC) && S_ISREG(h_inode->i_mode)
14347+ && fake_nd && fake_nd->path.mnt
14348+ && (fake_nd->path.mnt->mnt_flags & MNT_NOEXEC)))
14349+ goto out;
14350+
14351+ /*
14352+ * - skip hidden fs test in the case of write to ro branch.
14353+ * - nfs dir permission write check is optimized, but a policy for
14354+ * link/rename requires a real check.
14355+ */
14356+ submask = mask & ~MAY_APPEND;
14357+ if ((write_mask && !au_br_writable(brperm))
14358+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
14359+ && write_mask && !(mask & MAY_READ))
14360+ || !h_inode->i_op
14361+ || !h_inode->i_op->permission) {
14362+ /* LKTRLabel(generic_permission); */
14363+ err = generic_permission(h_inode, submask, NULL);
14364+ } else {
14365+ /* LKTRLabel(h_inode->permission); */
14366+ err = h_inode->i_op->permission(h_inode, submask, fake_nd);
14367+ AuTraceErr(err);
14368+ }
14369+
14370+#if 1 /* todo: export? */
14371+ if (!err)
14372+ err = au_security_inode_permission(h_inode, mask, fake_nd,
14373+ dlgt);
14374+#endif
14375+
14376+ out:
14377+ AuTraceErr(err);
14378+ return err;
14379+}
14380+
14381+static int aufs_permission(struct inode *inode, int mask, struct nameidata *nd)
14382+{
14383+ int err;
14384+ aufs_bindex_t bindex, bend;
14385+ unsigned char locked, dlgt, do_nd;
14386+ const unsigned char isdir = S_ISDIR(inode->i_mode);
14387+ struct inode *h_inode;
14388+ struct super_block *sb;
14389+ unsigned int mnt_flags;
14390+ struct path path;
14391+ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
14392+
14393+ LKTRTrace("ino %lu, mask 0x%x, isdir %d, write_mask %d, "
14394+ "nd %d{%d, %d}\n",
14395+ inode->i_ino, mask, isdir, write_mask,
14396+ !!nd, nd ? !!nd->path.dentry : 0, nd ? !!nd->path.mnt : 0);
14397+
14398+ sb = inode->i_sb;
14399+ locked = silly_lock(inode, nd);
14400+ do_nd = (nd && locked >= 1);
14401+ mnt_flags = au_mntflags(sb);
14402+ dlgt = !!au_test_dlgt(mnt_flags);
14403+
14404+ if (!isdir || write_mask || au_test_dirperm1(mnt_flags)) {
14405+ h_inode = au_h_iptr(inode, au_ibstart(inode));
14406+ AuDebugOn(!h_inode
14407+ || ((h_inode->i_mode & S_IFMT)
14408+ != (inode->i_mode & S_IFMT)));
14409+ err = 0;
14410+ bindex = au_ibstart(inode);
14411+ LKTRTrace("b%d\n", bindex);
14412+ if (do_nd) {
14413+ path = nd->path;
14414+ nd->path.mnt = au_sbr_mnt(sb, bindex);
14415+ nd->path.dentry = au_h_dptr(nd->path.dentry, bindex);
14416+ path_get(&nd->path);
14417+ err = h_permission(h_inode, mask, nd,
14418+ au_sbr_perm(sb, bindex), dlgt);
14419+ path_put(&nd->path);
14420+ nd->path = path;
14421+ } else {
14422+ AuDebugOn(nd && nd->path.mnt);
14423+ err = h_permission(h_inode, mask, nd,
14424+ au_sbr_perm(sb, bindex), dlgt);
14425+ }
14426+
14427+ if (write_mask && !err) {
14428+ /* test whether the upper writable branch exists */
14429+ err = -EROFS;
14430+ for (; bindex >= 0; bindex--)
14431+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
14432+ err = 0;
14433+ break;
14434+ }
14435+ }
14436+ goto out;
14437+ }
14438+
14439+ /* non-write to dir */
14440+ if (do_nd)
14441+ path = nd->path;
14442+ else {
14443+ path.mnt = NULL;
14444+ path.dentry = NULL;
14445+ }
14446+ err = 0;
14447+ bend = au_ibend(inode);
14448+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
14449+ h_inode = au_h_iptr(inode, bindex);
14450+ if (!h_inode)
14451+ continue;
14452+ AuDebugOn(!S_ISDIR(h_inode->i_mode));
14453+
14454+ LKTRTrace("b%d\n", bindex);
14455+ if (do_nd) {
14456+ nd->path.mnt = au_sbr_mnt(sb, bindex);
14457+ nd->path.dentry = au_h_dptr(path.dentry, bindex);
14458+ path_get(&nd->path);
14459+ err = h_permission(h_inode, mask, nd,
14460+ au_sbr_perm(sb, bindex), dlgt);
14461+ path_put(&nd->path);
14462+ } else {
14463+ AuDebugOn(nd && nd->path.mnt);
14464+ err = h_permission(h_inode, mask, nd,
14465+ au_sbr_perm(sb, bindex), dlgt);
14466+ }
14467+ }
14468+ if (do_nd)
14469+ nd->path = path;
14470+
14471+ out:
14472+ silly_unlock(locked, inode, nd);
14473+ AuTraceErr(err);
14474+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
14475+ err = -ESTALE;
14476+ return err;
14477+}
14478+#endif /* KERNEL_VERSION(2, 6, 27) */
14479+
14480+/* ---------------------------------------------------------------------- */
14481+
14482+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
14483+ struct nameidata *nd)
14484+{
14485+ struct dentry *ret, *parent;
14486+ int err, npositive;
14487+ struct inode *inode, *h_inode;
14488+ struct nameidata tmp_nd, *ndp;
14489+ aufs_bindex_t bstart;
14490+ struct mutex *mtx;
14491+ struct super_block *sb;
14492+
14493+ LKTRTrace("dir %lu, %.*s, nd{0x%x}\n",
14494+ dir->i_ino, AuDLNPair(dentry), nd ? nd->flags : 0);
14495+ AuDebugOn(IS_ROOT(dentry));
14496+ IMustLock(dir);
14497+
14498+ sb = dir->i_sb;
14499+ si_read_lock(sb, AuLock_FLUSH);
14500+ err = au_alloc_dinfo(dentry);
14501+ ret = ERR_PTR(err);
14502+ if (unlikely(err))
14503+ goto out;
14504+
14505+ /* nd can be NULL */
14506+ ndp = au_dup_nd(au_sbi(sb), &tmp_nd, nd);
14507+ parent = dentry->d_parent; /* dir inode is locked */
14508+ di_read_lock_parent(parent, AuLock_IR);
14509+ npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, ndp);
14510+ di_read_unlock(parent, AuLock_IR);
14511+ err = npositive;
14512+ ret = ERR_PTR(err);
14513+ if (unlikely(err < 0))
14514+ goto out_unlock;
14515+
14516+ inode = NULL;
14517+ if (npositive) {
14518+ bstart = au_dbstart(dentry);
14519+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
14520+ AuDebugOn(!h_inode);
14521+ if (!S_ISDIR(h_inode->i_mode)) {
14522+ /*
14523+ * stop 'race'-ing between hardlinks under different
14524+ * parents.
14525+ */
14526+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
14527+ mutex_lock(mtx);
14528+ inode = au_new_inode(dentry, /*must_new*/0);
14529+ mutex_unlock(mtx);
14530+ } else
14531+ inode = au_new_inode(dentry, /*must_new*/0);
14532+ ret = (void *)inode;
14533+ }
14534+ if (!IS_ERR(inode)) {
14535+ ret = d_splice_alias(inode, dentry);
14536+ if (unlikely(IS_ERR(ret) && inode))
14537+ ii_write_unlock(inode);
14538+ AuDebugOn(nd
14539+ && (nd->flags & LOOKUP_OPEN)
14540+ && nd->intent.open.file
14541+ && nd->intent.open.file->f_dentry);
14542+ au_store_fmode_exec(nd, inode);
14543+ }
14544+
14545+ out_unlock:
14546+ di_write_unlock(dentry);
14547+ out:
14548+ si_read_unlock(sb);
14549+ AuTraceErrPtr(ret);
14550+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
14551+ err = -ESTALE;
14552+ return ret;
14553+}
14554+
14555+/* ---------------------------------------------------------------------- */
14556+
14557+/*
14558+ * decide the branch and the parent dir where we will create a new entry.
14559+ * returns new bindex or an error.
14560+ * copyup the parent dir if needed.
14561+ */
14562+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14563+ struct au_wr_dir_args *args)
14564+{
14565+ int err;
14566+ aufs_bindex_t bcpup, bstart, src_bstart;
14567+ struct super_block *sb;
14568+ struct dentry *parent;
14569+ struct au_sbinfo *sbinfo;
14570+ const int add_entry = au_ftest_wrdir(args->flags, ADD_ENTRY);
14571+
14572+ LKTRTrace("%.*s, src %p, {%d, 0x%x}\n",
14573+ AuDLNPair(dentry), src_dentry, args->force_btgt, args->flags);
14574+
14575+ sb = dentry->d_sb;
14576+ sbinfo = au_sbi(sb);
14577+ parent = dget_parent(dentry);
14578+ bstart = au_dbstart(dentry);
14579+ bcpup = bstart;
14580+ if (args->force_btgt < 0) {
14581+ if (src_dentry) {
14582+ src_bstart = au_dbstart(src_dentry);
14583+ if (src_bstart < bstart)
14584+ bcpup = src_bstart;
14585+ } else if (add_entry) {
14586+ err = AuWbrCreate(sbinfo, dentry,
14587+ au_ftest_wrdir(args->flags, ISDIR));
14588+ bcpup = err;
14589+ }
14590+
14591+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
14592+ if (add_entry)
14593+ err = AuWbrCopyup(sbinfo, dentry);
14594+ else {
14595+ if (!IS_ROOT(dentry)) {
14596+ di_read_lock_parent(parent, !AuLock_IR);
14597+ err = AuWbrCopyup(sbinfo, dentry);
14598+ di_read_unlock(parent, !AuLock_IR);
14599+ } else
14600+ err = AuWbrCopyup(sbinfo, dentry);
14601+ }
14602+ bcpup = err;
14603+ if (unlikely(err < 0))
14604+ goto out;
14605+ }
14606+ } else {
14607+ bcpup = args->force_btgt;
14608+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
14609+ }
14610+ LKTRTrace("bstart %d, bcpup %d\n", bstart, bcpup);
14611+ if (bstart < bcpup)
14612+ au_update_dbrange(dentry, /*do_put_zero*/1);
14613+
14614+ err = bcpup;
14615+ if (bcpup == bstart)
14616+ goto out; /* success */
14617+
14618+ /* copyup the new parent into the branch we process */
14619+ if (add_entry) {
14620+ au_update_dbstart(dentry);
14621+ IMustLock(parent->d_inode);
14622+ DiMustWriteLock(parent);
14623+ IiMustWriteLock(parent->d_inode);
14624+ } else
14625+ di_write_lock_parent(parent);
14626+
14627+ err = 0;
14628+ if (!au_h_dptr(parent, bcpup)) {
14629+ if (bstart < bcpup)
14630+ err = au_cpdown_dirs(dentry, bcpup);
14631+ else
14632+ err = au_cpup_dirs(dentry, bcpup);
14633+ }
14634+ if (!err && add_entry) {
14635+ struct dentry *h_parent;
14636+ struct inode *h_dir;
14637+
14638+ h_parent = au_h_dptr(parent, bcpup);
14639+ AuDebugOn(!h_parent);
14640+ h_dir = h_parent->d_inode;
14641+ AuDebugOn(!h_dir);
14642+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
14643+ err = au_lkup_neg(dentry, bcpup);
14644+ mutex_unlock(&h_dir->i_mutex);
14645+ if (bstart < bcpup && au_dbstart(dentry) < 0) {
14646+ au_set_dbstart(dentry, 0);
14647+ au_update_dbrange(dentry, /*do_put_zero*/0);
14648+ }
14649+ }
14650+
14651+ if (!add_entry)
14652+ di_write_unlock(parent);
14653+ if (!err)
14654+ err = bcpup; /* success */
14655+ out:
14656+ dput(parent);
14657+ LKTRTrace("err %d\n", err);
14658+ AuTraceErr(err);
14659+ return err;
14660+}
14661+
14662+/* ---------------------------------------------------------------------- */
14663+
14664+struct dentry *au_do_pinned_h_parent(struct au_pin1 *pin)
14665+{
14666+ if (pin && pin->parent)
14667+ return au_h_dptr(pin->parent, pin->bindex);
14668+ return NULL;
14669+}
14670+
14671+void au_do_unpin(struct au_pin1 *p, struct au_pin1 *gp)
14672+{
14673+ if (p->dentry)
14674+ LKTRTrace("%.*s\n", AuDLNPair(p->dentry));
14675+ LKTRTrace("p{%d, %d, %d, %d, 0x%x}, gp %p\n",
14676+ p->lsc_di, p->lsc_hi, !!p->parent, !!p->h_dir, p->flags, gp);
14677+
14678+ if (au_ftest_pin(p->flags, MNT_WRITE))
14679+ au_br_drop_write(au_sbr(p->dentry->d_sb, p->bindex));
14680+ if (au_ftest_pin(p->flags, VFS_RENAME))
14681+ vfsub_unlock_rename_mutex(au_sbr_sb(p->dentry->d_sb,
14682+ p->bindex));
14683+ if (!p->h_dir)
14684+ return;
14685+
14686+ mutex_unlock(&p->h_dir->i_mutex);
14687+ if (gp)
14688+ au_do_unpin(gp, NULL);
14689+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14690+ di_read_unlock(p->parent, AuLock_IR);
14691+ iput(p->h_dir);
14692+ dput(p->parent);
14693+ p->parent = NULL;
14694+ p->h_dir = NULL;
14695+}
14696+
14697+int au_do_pin(struct au_pin1 *p, struct au_pin1 *gp)
14698+{
14699+ int err;
14700+ struct dentry *h_dentry;
14701+
14702+ LKTRTrace("%.*s, %d, b%d, 0x%x\n",
14703+ AuDLNPair(p->dentry), !!gp, p->bindex, p->flags);
14704+ AuDebugOn(au_ftest_pin(p->flags, DO_GPARENT) && !gp);
14705+ /* AuDebugOn(!do_gp && gp); */
14706+
14707+ err = 0;
14708+ if (IS_ROOT(p->dentry)) {
14709+ if (au_ftest_pin(p->flags, VFS_RENAME))
14710+ vfsub_lock_rename_mutex(au_sbr_sb(p->dentry->d_sb,
14711+ p->bindex));
14712+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14713+ err = au_br_want_write(au_sbr(p->dentry->d_sb,
14714+ p->bindex));
14715+ if (unlikely(err))
14716+ au_fclr_pin(p->flags, MNT_WRITE);
14717+ }
14718+ goto out;
14719+ }
14720+
14721+ h_dentry = NULL;
14722+ if (p->bindex <= au_dbend(p->dentry))
14723+ h_dentry = au_h_dptr(p->dentry, p->bindex);
14724+
14725+ p->parent = dget_parent(p->dentry);
14726+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14727+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
14728+ else
14729+ DiMustAnyLock(p->parent);
14730+ AuDebugOn(!p->parent->d_inode);
14731+ p->h_dir = au_igrab(au_h_iptr(p->parent->d_inode, p->bindex));
14732+ /* udba case */
14733+ if (unlikely(au_ftest_pin(p->flags, VERIFY) && !p->h_dir)) {
14734+ err = -EIO;
14735+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14736+ di_read_unlock(p->parent, AuLock_IR);
14737+ dput(p->parent);
14738+ p->parent = NULL;
14739+ goto out;
14740+ }
14741+
14742+ if (au_ftest_pin(p->flags, DO_GPARENT)) {
14743+ gp->dentry = p->parent;
14744+ err = au_do_pin(gp, NULL);
14745+ if (unlikely(err))
14746+ gp->dentry = NULL;
14747+ }
14748+ if (au_ftest_pin(p->flags, VFS_RENAME))
14749+ vfsub_lock_rename_mutex(p->h_dir->i_sb);
14750+ mutex_lock_nested(&p->h_dir->i_mutex, p->lsc_hi);
14751+ if (!err) {
14752+ /* todo: call d_revalidate() here? */
14753+#if 0
14754+ if (h_dentry && h_dentry->d_op && h_dentry->d_op->d_revalidate
14755+ && !h_dentry->d_op->d_revalidate(h_dentry, NULL))
14756+ err = -EIO;
14757+#endif
14758+ if (!h_dentry
14759+ || !au_ftest_pin(p->flags, VERIFY)
14760+ || !au_verify_parent(h_dentry, p->h_dir)) {
14761+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14762+ err = au_br_want_write(au_sbr(p->dentry->d_sb,
14763+ p->bindex));
14764+ if (unlikely(err))
14765+ au_fclr_pin(p->flags, MNT_WRITE);
14766+ }
14767+ if (!err)
14768+ goto out; /* success */
14769+ } else
14770+ err = -EIO;
14771+ }
14772+
14773+ AuDbgDentry(p->dentry);
14774+ AuDbgDentry(h_dentry);
14775+ AuDbgDentry(p->parent);
14776+ AuDbgInode(p->h_dir);
14777+ if (h_dentry)
14778+ AuDbgDentry(h_dentry->d_parent);
14779+
14780+ au_do_unpin(p, gp);
14781+ if (au_ftest_pin(p->flags, DO_GPARENT))
14782+ gp->dentry = NULL;
14783+
14784+ out:
14785+ AuTraceErr(err);
14786+ return err;
14787+}
14788+
14789+void au_pin_init(struct au_pin *args, struct dentry *dentry,
14790+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14791+ unsigned char flags)
14792+{
14793+ struct au_pin1 *p;
14794+ unsigned char f;
14795+
14796+ AuTraceEnter();
14797+
14798+ memset(args, 0, sizeof(*args));
14799+ p = args->pin + AuPin_PARENT;
14800+ p->dentry = dentry;
14801+ p->lsc_di = lsc_di;
14802+ p->lsc_hi = lsc_hi;
14803+ p->flags = flags;
14804+ p->bindex = bindex;
14805+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE))
14806+ au_fset_pin(p->flags, VERIFY);
14807+ if (!au_ftest_pin(flags, DO_GPARENT))
14808+ return;
14809+
14810+ f = p->flags;
14811+ p = au_pin_gp(args);
14812+ if (p) {
14813+ p->lsc_di = lsc_di + 1; /* child first */
14814+ p->lsc_hi = lsc_hi - 1; /* parent first */
14815+ p->bindex = bindex;
14816+ p->flags = f & ~(AuPin_MNT_WRITE
14817+ | AuPin_DO_GPARENT
14818+ | AuPin_DI_LOCKED);
14819+ }
14820+}
14821+
14822+int au_pin(struct au_pin *args, struct dentry *dentry, aufs_bindex_t bindex,
14823+ unsigned char flags)
14824+{
14825+ LKTRTrace("%.*s, b%d, 0x%x\n",
14826+ AuDLNPair(dentry), bindex, flags);
14827+
14828+ au_pin_init(args, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
14829+ flags);
14830+ return au_do_pin(args->pin + AuPin_PARENT, au_pin_gp(args));
14831+}
14832+
14833+/* ---------------------------------------------------------------------- */
14834+
14835+struct au_icpup_args {
14836+ unsigned char isdir, hinotify, did_cpup; /* flags */
14837+ unsigned char pin_flags;
14838+ aufs_bindex_t btgt;
14839+ struct au_pin pin;
14840+ struct au_hin_ignore ign[2];
14841+ struct vfsub_args vargs;
14842+ struct dentry *h_dentry;
14843+ struct inode *h_inode;
14844+};
14845+
14846+/* todo: refine it */
14847+static int au_lock_and_icpup(struct dentry *dentry, loff_t sz,
14848+ struct au_icpup_args *a)
14849+{
14850+ int err;
14851+ aufs_bindex_t bstart;
14852+ struct super_block *sb;
14853+ struct dentry *hi_wh, *parent;
14854+ struct inode *inode;
14855+ struct au_wr_dir_args wr_dir_args = {
14856+ .force_btgt = -1,
14857+ .flags = 0
14858+ };
14859+
14860+ LKTRTrace("%.*s, %lld\n", AuDLNPair(dentry), sz);
14861+
14862+ di_write_lock_child(dentry);
14863+ bstart = au_dbstart(dentry);
14864+ sb = dentry->d_sb;
14865+ inode = dentry->d_inode;
14866+ a->isdir = !!S_ISDIR(inode->i_mode);
14867+ if (a->isdir)
14868+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
14869+ /* plink or hi_wh() */
14870+ if (bstart != au_ibstart(inode))
14871+ wr_dir_args.force_btgt = au_ibstart(inode);
14872+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
14873+ if (unlikely(err < 0))
14874+ goto out_dentry;
14875+ a->btgt = err;
14876+ a->did_cpup = (err != bstart);
14877+ err = 0;
14878+
14879+ /* crazy udba locks */
14880+ a->pin_flags = AuPin_MNT_WRITE;
14881+ a->hinotify = !!au_opt_test(au_mntflags(sb), UDBA_INOTIFY);
14882+ if (a->hinotify)
14883+ au_fset_pin(a->pin_flags, DO_GPARENT);
14884+ parent = NULL;
14885+ if (!IS_ROOT(dentry)) {
14886+ au_fset_pin(a->pin_flags, DI_LOCKED);
14887+ parent = dget_parent(dentry);
14888+ di_write_lock_parent(parent);
14889+ }
14890+ err = au_pin(&a->pin, dentry, a->btgt, a->pin_flags);
14891+ if (unlikely(err)) {
14892+ if (parent) {
14893+ di_write_unlock(parent);
14894+ dput(parent);
14895+ }
14896+ goto out_dentry;
14897+ }
14898+ a->h_dentry = au_h_dptr(dentry, bstart);
14899+ a->h_inode = a->h_dentry->d_inode;
14900+ AuDebugOn(!a->h_inode);
14901+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14902+ if (!a->did_cpup) {
14903+ au_unpin_gp(&a->pin);
14904+ if (parent) {
14905+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14906+ di_downgrade_lock(parent, AuLock_IR);
14907+ dput(parent);
14908+ }
14909+ goto out; /* success */
14910+ }
14911+
14912+ hi_wh = NULL;
14913+ if (!d_unhashed(dentry)) {
14914+ if (parent) {
14915+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14916+ di_downgrade_lock(parent, AuLock_IR);
14917+ dput(parent);
14918+ }
14919+ err = au_sio_cpup_simple(dentry, a->btgt, sz, AuCpup_DTIME);
14920+ if (!err)
14921+ a->h_dentry = au_h_dptr(dentry, a->btgt);
14922+ } else {
14923+ hi_wh = au_hi_wh(inode, a->btgt);
14924+ if (!hi_wh) {
14925+ err = au_sio_cpup_wh(dentry, a->btgt, sz,
14926+ /*file*/NULL);
14927+ if (!err)
14928+ hi_wh = au_hi_wh(inode, a->btgt);
14929+ /* todo: revalidate hi_wh? */
14930+ }
14931+ if (parent) {
14932+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14933+ di_downgrade_lock(parent, AuLock_IR);
14934+ dput(parent);
14935+ }
14936+ if (!hi_wh)
14937+ a->h_dentry = au_h_dptr(dentry, a->btgt);
14938+ else
14939+ a->h_dentry = hi_wh; /* do not dget here */
14940+ }
14941+
14942+ mutex_unlock(&a->h_inode->i_mutex);
14943+ a->h_inode = a->h_dentry->d_inode;
14944+ AuDebugOn(!a->h_inode);
14945+ if (!err) {
14946+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14947+ au_unpin_gp(&a->pin);
14948+ goto out; /* success */
14949+ }
14950+
14951+ au_unpin(&a->pin);
14952+
14953+ out_dentry:
14954+ di_write_unlock(dentry);
14955+ out:
14956+ AuTraceErr(err);
14957+ return err;
14958+}
14959+
14960+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
14961+{
14962+ int err;
14963+ struct inode *inode;
14964+ struct super_block *sb;
14965+ __u32 events;
14966+ struct file *file;
14967+ loff_t sz;
14968+ struct au_icpup_args *a;
14969+
14970+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
14971+ inode = dentry->d_inode;
14972+ IMustLock(inode);
14973+
14974+ err = -ENOMEM;
14975+ a = kzalloc(sizeof(*a), GFP_NOFS);
14976+ if (unlikely(!a))
14977+ goto out;
14978+
14979+ file = NULL;
14980+ sb = dentry->d_sb;
14981+ si_read_lock(sb, AuLock_FLUSH);
14982+ vfsub_args_init(&a->vargs, a->ign, au_test_dlgt(au_mntflags(sb)), 0);
14983+
14984+ if (ia->ia_valid & ATTR_FILE) {
14985+ /* currently ftruncate(2) only */
14986+ file = ia->ia_file;
14987+ fi_write_lock(file);
14988+ ia->ia_file = au_h_fptr(file, au_fbstart(file));
14989+ }
14990+
14991+ sz = -1;
14992+ if ((ia->ia_valid & ATTR_SIZE)
14993+ && ia->ia_size < i_size_read(inode))
14994+ sz = ia->ia_size;
14995+ err = au_lock_and_icpup(dentry, sz, a);
14996+ if (unlikely(err < 0))
14997+ goto out_si;
14998+ if (a->did_cpup) {
14999+ ia->ia_file = NULL;
15000+ ia->ia_valid &= ~ATTR_FILE;
15001+ }
15002+
15003+ if ((ia->ia_valid & ATTR_SIZE)
15004+ && ia->ia_size < i_size_read(inode)) {
15005+ err = vmtruncate(inode, ia->ia_size);
15006+ if (unlikely(err))
15007+ goto out_unlock;
15008+ }
15009+
15010+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
15011+ ia->ia_valid &= ~ATTR_MODE;
15012+
15013+ events = 0;
15014+ if (a->hinotify) {
15015+ events = vfsub_events_notify_change(ia);
15016+ if (events) {
15017+ if (a->isdir)
15018+ vfsub_ign_hinode(&a->vargs, events,
15019+ au_hi(inode, a->btgt));
15020+ vfsub_ign_hinode(&a->vargs, events,
15021+ au_pinned_hdir(&a->pin));
15022+ }
15023+ }
15024+ err = vfsub_notify_change(a->h_dentry, ia, &a->vargs);
15025+ if (!err)
15026+ au_cpup_attr_changeable(inode);
15027+
15028+ out_unlock:
15029+ mutex_unlock(&a->h_inode->i_mutex);
15030+ au_unpin(&a->pin);
15031+ di_write_unlock(dentry);
15032+ out_si:
15033+ if (file) {
15034+ fi_write_unlock(file);
15035+ ia->ia_file = file;
15036+ ia->ia_valid |= ATTR_FILE;
15037+ }
15038+ si_read_unlock(sb);
15039+ kfree(a);
15040+ out:
15041+ AuTraceErr(err);
15042+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
15043+ err = -ESTALE;
15044+ return err;
15045+}
15046+
15047+/* ---------------------------------------------------------------------- */
15048+
15049+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
15050+ int bufsiz)
15051+{
15052+ struct super_block *sb;
15053+ struct dentry *h_dentry;
15054+
15055+ LKTRTrace("%.*s, b%d, %d\n", AuDLNPair(dentry), bindex, bufsiz);
15056+
15057+ h_dentry = au_h_dptr(dentry, bindex);
15058+ if (unlikely(/* !h_dentry
15059+ || !h_dentry->d_inode
15060+ || */
15061+ !h_dentry->d_inode->i_op
15062+ || !h_dentry->d_inode->i_op->readlink))
15063+ return -EINVAL;
15064+
15065+ sb = dentry->d_sb;
15066+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
15067+ touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
15068+ au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
15069+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
15070+ }
15071+ return h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
15072+}
15073+
15074+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
15075+{
15076+ int err;
15077+
15078+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), bufsiz);
15079+
15080+ aufs_read_lock(dentry, AuLock_IR);
15081+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
15082+ aufs_read_unlock(dentry, AuLock_IR);
15083+ AuTraceErr(err);
15084+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
15085+ err = -ESTALE;
15086+ return err;
15087+}
15088+
15089+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
15090+{
15091+ int err;
15092+ char *buf;
15093+ mm_segment_t old_fs;
15094+
15095+ LKTRTrace("%.*s, nd %.*s\n",
15096+ AuDLNPair(dentry), AuDLNPair(nd->path.dentry));
15097+
15098+ err = -ENOMEM;
15099+ buf = __getname();
15100+ if (unlikely(!buf))
15101+ goto out;
15102+
15103+ aufs_read_lock(dentry, AuLock_IR);
15104+ old_fs = get_fs();
15105+ set_fs(KERNEL_DS);
15106+ err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
15107+ PATH_MAX);
15108+ set_fs(old_fs);
15109+ aufs_read_unlock(dentry, AuLock_IR);
15110+
15111+ if (err >= 0) {
15112+ buf[err] = 0;
15113+ /* will be freed by put_link */
15114+ nd_set_link(nd, buf);
15115+ return NULL; /* success */
15116+ }
15117+ __putname(buf);
15118+
15119+ out:
15120+ path_put(&nd->path);
15121+ AuTraceErr(err);
15122+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
15123+ err = -ESTALE;
15124+ return ERR_PTR(err);
15125+}
15126+
15127+static void aufs_put_link(struct dentry *dentry, struct nameidata *nd,
15128+ void *cookie)
15129+{
15130+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
15131+ __putname(nd_get_link(nd));
15132+}
15133+
15134+/* ---------------------------------------------------------------------- */
15135+
15136+static void aufs_truncate_range(struct inode *inode, loff_t start, loff_t end)
15137+{
15138+ AuUnsupport();
15139+}
15140+
15141+/* ---------------------------------------------------------------------- */
15142+
15143+struct inode_operations aufs_symlink_iop = {
15144+ .permission = aufs_permission,
15145+ .setattr = aufs_setattr,
15146+#ifdef CONFIG_AUFS_GETATTR
15147+ .getattr = aufs_getattr,
15148+#endif
15149+
15150+ .readlink = aufs_readlink,
15151+ .follow_link = aufs_follow_link,
15152+ .put_link = aufs_put_link
15153+};
15154+
15155+struct inode_operations aufs_dir_iop = {
15156+ .create = aufs_create,
15157+ .lookup = aufs_lookup,
15158+ .link = aufs_link,
15159+ .unlink = aufs_unlink,
15160+ .symlink = aufs_symlink,
15161+ .mkdir = aufs_mkdir,
15162+ .rmdir = aufs_rmdir,
15163+ .mknod = aufs_mknod,
15164+ .rename = aufs_rename,
15165+
15166+ .permission = aufs_permission,
15167+ .setattr = aufs_setattr,
15168+#ifdef CONFIG_AUFS_GETATTR
15169+ .getattr = aufs_getattr,
15170+#endif
15171+
15172+#if 0 /* reserved for future use */
15173+ .setxattr = aufs_setxattr,
15174+ .getxattr = aufs_getxattr,
15175+ .listxattr = aufs_listxattr,
15176+ .removexattr = aufs_removexattr
15177+#endif
15178+};
15179+
15180+struct inode_operations aufs_iop = {
15181+ .permission = aufs_permission,
15182+ .setattr = aufs_setattr,
15183+#ifdef CONFIG_AUFS_GETATTR
15184+ .getattr = aufs_getattr,
15185+#endif
15186+
15187+#if 0 /* reserved for future use */
15188+ .setxattr = aufs_setxattr,
15189+ .getxattr = aufs_getxattr,
15190+ .listxattr = aufs_listxattr,
15191+ .removexattr = aufs_removexattr,
15192+#endif
15193+
15194+ .truncate_range = aufs_truncate_range
15195+};
15196diff -urN linux/fs/aufs/i_op_del.c linux-aufs/fs/aufs/i_op_del.c
15197--- linux/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
15198+++ linux-aufs/fs/aufs/i_op_del.c 2009-03-12 16:18:04.000000000 +0100
15199@@ -0,0 +1,566 @@
15200+/*
15201+ * Copyright (C) 2005-2009 Junjiro Okajima
15202+ *
15203+ * This program, aufs is free software; you can redistribute it and/or modify
15204+ * it under the terms of the GNU General Public License as published by
15205+ * the Free Software Foundation; either version 2 of the License, or
15206+ * (at your option) any later version.
15207+ *
15208+ * This program is distributed in the hope that it will be useful,
15209+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15210+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15211+ * GNU General Public License for more details.
15212+ *
15213+ * You should have received a copy of the GNU General Public License
15214+ * along with this program; if not, write to the Free Software
15215+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15216+ */
15217+
15218+/*
15219+ * inode operations (del entry)
15220+ *
15221+ * $Id$
15222+ */
15223+
15224+#include "aufs.h"
15225+
15226+/* returns,
15227+ * 0: wh is unnecessary
15228+ * plus: wh is necessary
15229+ * minus: error
15230+ */
15231+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
15232+{
15233+ int need_wh, err;
15234+ aufs_bindex_t bstart;
15235+ struct dentry *h_dentry;
15236+ struct super_block *sb;
15237+
15238+ LKTRTrace("%.*s, isdir %d, *bcpup %d\n",
15239+ AuDLNPair(dentry), isdir, *bcpup);
15240+ sb = dentry->d_sb;
15241+
15242+ bstart = au_dbstart(dentry);
15243+ LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
15244+ h_dentry = au_h_dptr(dentry, bstart);
15245+ if (*bcpup < 0) {
15246+ *bcpup = bstart;
15247+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
15248+ err = AuWbrCopyup(au_sbi(sb), dentry);
15249+ *bcpup = err;
15250+ if (unlikely(err < 0))
15251+ goto out;
15252+ }
15253+ } else
15254+ AuDebugOn(bstart < *bcpup
15255+ || au_test_ro(sb, *bcpup, dentry->d_inode));
15256+ LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
15257+
15258+ if (*bcpup != bstart) {
15259+ err = au_cpup_dirs(dentry, *bcpup);
15260+ if (unlikely(err))
15261+ goto out;
15262+ need_wh = 1;
15263+ } else {
15264+ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
15265+ old_bend = au_dbend(dentry);
15266+ if (isdir) {
15267+ bdiropq = au_dbdiropq(dentry);
15268+ au_set_dbdiropq(dentry, -1);
15269+ }
15270+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
15271+ /*nd*/NULL);
15272+ err = need_wh;
15273+ if (isdir)
15274+ au_set_dbdiropq(dentry, bdiropq);
15275+ if (unlikely(err < 0))
15276+ goto out;
15277+ new_bend = au_dbend(dentry);
15278+ if (!need_wh && old_bend != new_bend) {
15279+ au_set_h_dptr(dentry, new_bend, NULL);
15280+ au_set_dbend(dentry, old_bend);
15281+#if 0 /* todo: remove this? */
15282+ } else if (!au_h_dptr(dentry, new_bend)->d_inode) {
15283+ LKTRTrace("negative\n");
15284+ au_set_h_dptr(dentry, new_bend, NULL);
15285+ au_set_dbend(dentry, old_bend);
15286+ need_wh = 0;
15287+#endif
15288+ }
15289+ }
15290+ LKTRTrace("need_wh %d\n", need_wh);
15291+ err = need_wh;
15292+
15293+ out:
15294+ AuTraceErr(err);
15295+ return err;
15296+}
15297+
15298+/*
15299+ * simple tests for the removal inode operations.
15300+ * following the checks in vfs, plus the parent-child relationship.
15301+ */
15302+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
15303+ struct dentry *h_parent, int isdir, struct au_ndx *ndx)
15304+{
15305+ int err, exist;
15306+ struct super_block *sb;
15307+ struct dentry *h_dentry;
15308+ struct inode *h_inode;
15309+ umode_t h_mode;
15310+
15311+ LKTRTrace("%.*s/%.*s, b%d, dir %d\n",
15312+ AuDLNPair(h_parent), AuDLNPair(dentry), bindex, isdir);
15313+
15314+ sb = dentry->d_sb;
15315+ exist = !!dentry->d_inode;
15316+ h_dentry = au_h_dptr(dentry, bindex);
15317+ h_inode = h_dentry->d_inode;
15318+ if (exist) {
15319+ err = -ENOENT;
15320+ if (unlikely(!h_inode || !h_inode->i_nlink))
15321+ goto out;
15322+
15323+ h_mode = h_inode->i_mode;
15324+ if (!isdir) {
15325+ err = -EISDIR;
15326+ if (unlikely(S_ISDIR(h_mode)))
15327+ goto out;
15328+ } else if (unlikely(!S_ISDIR(h_mode))) {
15329+ err = -ENOTDIR;
15330+ goto out;
15331+ }
15332+ } else {
15333+ /* rename(2) case */
15334+ err = -EIO;
15335+ if (unlikely(h_inode))
15336+ goto out;
15337+ }
15338+
15339+ err = -ENOENT;
15340+ /* expected parent dir is locked */
15341+ if (unlikely(h_parent != h_dentry->d_parent))
15342+ goto out;
15343+ err = 0;
15344+
15345+ /*
15346+ * some filesystem may unlink a dir and corrupt its consistency.
15347+ * so let's try heavy test.
15348+ */
15349+ if (1 /*au_opt_test(au_mntflags(sb), UDBA_INOTIFY)*/) {
15350+ struct dentry *h_latest;
15351+ struct qstr *qstr = &dentry->d_name;
15352+
15353+ err = -EACCES;
15354+ if (unlikely(au_test_h_perm(h_parent->d_inode,
15355+ MAY_EXEC | MAY_WRITE,
15356+ au_ftest_ndx(ndx->flags, DLGT))))
15357+ goto out;
15358+
15359+ h_latest = au_sio_lkup_one(qstr->name, h_parent, qstr->len,
15360+ ndx);
15361+ err = -EIO;
15362+ if (IS_ERR(h_latest))
15363+ goto out;
15364+ dput(h_latest);
15365+ if (h_latest == h_dentry)
15366+ err = 0;
15367+ }
15368+
15369+ out:
15370+ AuTraceErr(err);
15371+ return err;
15372+}
15373+
15374+static struct dentry *
15375+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
15376+ struct au_dtime *dt, struct au_pin *pin)
15377+{
15378+ struct dentry *wh_dentry, *h_parent;
15379+ struct super_block *sb;
15380+ int err, need_wh;
15381+ unsigned int mnt_flags;
15382+ unsigned char pin_flags;
15383+ aufs_bindex_t bcpup;
15384+ struct au_ndx ndx;
15385+
15386+ LKTRTrace("%.*s, isdir %d\n", AuDLNPair(dentry), isdir);
15387+
15388+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
15389+ err = need_wh;
15390+ wh_dentry = ERR_PTR(err);
15391+ if (unlikely(err < 0))
15392+ goto out;
15393+
15394+ sb = dentry->d_sb;
15395+ mnt_flags = au_mntflags(sb);
15396+ bcpup = *rbcpup;
15397+ pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
15398+ if (au_opt_test(mnt_flags, UDBA_INOTIFY))
15399+ au_fset_pin(pin_flags, DO_GPARENT);
15400+ err = au_pin(pin, dentry, bcpup, pin_flags);
15401+ wh_dentry = ERR_PTR(err);
15402+ if (unlikely(err))
15403+ goto out;
15404+ h_parent = au_pinned_h_parent(pin);
15405+ if (!au_opt_test(mnt_flags, UDBA_NONE) && au_dbstart(dentry) == bcpup) {
15406+ ndx.nfsmnt = au_nfsmnt(sb, bcpup);
15407+ ndx.flags = 0;
15408+ if (au_test_dlgt(mnt_flags))
15409+ au_fset_ndx(ndx.flags, DLGT);
15410+ ndx.nd = NULL;
15411+ /* ndx.br = au_sbr(sb, bcpup); */
15412+ /* ndx.nd_file = NULL; */
15413+ err = au_may_del(dentry, bcpup, h_parent, isdir, &ndx);
15414+ wh_dentry = ERR_PTR(err);
15415+ if (unlikely(err))
15416+ goto out_unpin;
15417+ }
15418+
15419+ au_dtime_store(dt, au_pinned_parent(pin), h_parent, au_pinned_hdir(pin),
15420+ au_pinned_hgdir(pin));
15421+ wh_dentry = NULL;
15422+ if (!need_wh)
15423+ goto out; /* success, no need to create whiteout */
15424+
15425+ ndx.nfsmnt = au_nfsmnt(sb, bcpup);
15426+ ndx.flags = 0;
15427+ if (au_test_dlgt(mnt_flags))
15428+ au_fset_ndx(ndx.flags, DLGT);
15429+ ndx.nd = NULL;
15430+ /* ndx.br = NULL; */
15431+ wh_dentry = au_wh_create(dentry, bcpup, h_parent, &ndx);
15432+ if (!IS_ERR(wh_dentry))
15433+ goto out; /* success */
15434+ /* returns with the parent is locked and wh_dentry is DGETed */
15435+
15436+ out_unpin:
15437+ au_unpin(pin);
15438+ out:
15439+ AuTraceErrPtr(wh_dentry);
15440+ return wh_dentry;
15441+}
15442+
15443+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
15444+ struct au_nhash *whlist, struct inode *dir)
15445+{
15446+ int rmdir_later, err;
15447+ struct dentry *h_dentry;
15448+ struct inode *inode, *h_inode;
15449+ struct super_block *sb;
15450+
15451+ LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex);
15452+
15453+ inode = NULL;
15454+ h_inode = NULL;
15455+ sb = dentry->d_sb;
15456+ if (au_opt_test(au_mntflags(sb), UDBA_INOTIFY)) {
15457+ inode = dentry->d_inode;
15458+ h_inode = au_h_iptr(inode, bindex);
15459+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
15460+ }
15461+ h_dentry = au_h_dptr(dentry, bindex);
15462+ err = au_whtmp_ren(dir, bindex, h_dentry);
15463+ if (inode) {
15464+ /* todo: bad approach? */
15465+ if (!err)
15466+ au_hin_suspend(au_hi(inode, bindex));
15467+ mutex_unlock(&h_inode->i_mutex);
15468+ }
15469+ if (unlikely(err))
15470+ goto out;
15471+
15472+ if (!au_test_nfs(h_dentry->d_sb)) {
15473+ const int dirwh = au_sbi(sb)->si_dirwh;
15474+ rmdir_later = (dirwh <= 1);
15475+ if (!rmdir_later)
15476+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
15477+ dirwh);
15478+ if (rmdir_later)
15479+ return rmdir_later;
15480+ }
15481+
15482+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
15483+ if (unlikely(err)) {
15484+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
15485+ AuDLNPair(h_dentry), bindex, err);
15486+ /* we do not revert the inotify watch */
15487+ err = 0;
15488+ }
15489+
15490+ out:
15491+ AuTraceErr(err);
15492+ return err;
15493+}
15494+
15495+static void epilog(struct inode *dir, struct dentry *dentry,
15496+ aufs_bindex_t bindex)
15497+{
15498+ /* todo: unnecessary? */
15499+ d_drop(dentry);
15500+ dentry->d_inode->i_ctime = dir->i_ctime;
15501+
15502+ if (atomic_read(&dentry->d_count) == 1) {
15503+ au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
15504+ au_update_dbstart(dentry);
15505+ }
15506+ if (au_ibstart(dir) == bindex)
15507+ au_cpup_attr_timesizes(dir);
15508+ dir->i_version++;
15509+}
15510+
15511+/* revert flags */
15512+#define AuRev_DLGT 1
15513+#define au_ftest_rev(flags, name) ((flags) & AuRev_##name)
15514+#define au_fset_rev(flags, name) { (flags) |= AuRev_##name; }
15515+#define au_fclr_rev(flags, name) { (flags) &= ~AuRev_##name; }
15516+#ifndef CONFIG_AUFS_DLGT
15517+#undef AuRev_DLGT
15518+#define AuRev_DLGT 0
15519+#endif
15520+
15521+static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
15522+ struct dentry *wh_dentry, struct dentry *dentry,
15523+ struct au_dtime *dt, unsigned int flags)
15524+{
15525+ int rerr;
15526+
15527+ rerr = au_wh_unlink_dentry(au_hi(dir, bwh), wh_dentry, dentry,
15528+ au_ftest_rev(flags, DLGT));
15529+ if (!rerr) {
15530+ au_set_dbwh(dentry, bwh);
15531+ au_dtime_revert(dt);
15532+ return 0;
15533+ }
15534+
15535+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15536+ AuDLNPair(dentry), err, rerr);
15537+ return -EIO;
15538+}
15539+
15540+/* ---------------------------------------------------------------------- */
15541+
15542+int aufs_unlink(struct inode *dir, struct dentry *dentry)
15543+{
15544+ int err;
15545+ struct inode *inode, *h_dir;
15546+ struct dentry *parent, *wh_dentry, *h_dentry;
15547+ struct au_dtime dt;
15548+ aufs_bindex_t bwh, bindex, bstart;
15549+ unsigned char dlgt;
15550+ struct super_block *sb;
15551+ struct au_hin_ignore ign;
15552+ struct vfsub_args vargs;
15553+ struct au_pin pin;
15554+
15555+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
15556+ IMustLock(dir);
15557+ inode = dentry->d_inode;
15558+ if (unlikely(!inode))
15559+ return -ENOENT; /* possible? */
15560+ IMustLock(inode);
15561+
15562+ aufs_read_lock(dentry, AuLock_DW);
15563+ parent = dentry->d_parent; /* dir inode is locked */
15564+ di_write_lock_parent(parent);
15565+
15566+ bstart = au_dbstart(dentry);
15567+ bwh = au_dbwh(dentry);
15568+ bindex = -1;
15569+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
15570+ err = PTR_ERR(wh_dentry);
15571+ if (IS_ERR(wh_dentry))
15572+ goto out;
15573+
15574+ sb = dir->i_sb;
15575+ dlgt = !!au_test_dlgt(au_mntflags(sb));
15576+ AuDebugOn(au_dbstart(dentry) != bstart);
15577+ h_dentry = au_h_dptr(dentry, bstart);
15578+ dget(h_dentry);
15579+
15580+ if (bindex == bstart) {
15581+ vfsub_args_init(&vargs, &ign, dlgt, 0);
15582+ vfsub_ign_hinode(&vargs, IN_DELETE, au_pinned_hdir(&pin));
15583+ h_dir = au_pinned_h_dir(&pin);
15584+ err = vfsub_unlink(h_dir, h_dentry, &vargs);
15585+ } else {
15586+ /* dir inode is locked */
15587+ AuDebugOn(!wh_dentry
15588+ || wh_dentry->d_parent != au_h_dptr(parent, bindex));
15589+ h_dir = wh_dentry->d_parent->d_inode;
15590+ IMustLock(h_dir);
15591+ err = 0;
15592+ }
15593+
15594+ if (!err) {
15595+ drop_nlink(inode);
15596+#if 0 /* todo: update plink? */
15597+ if (!inode->i_nlink
15598+ && au_opt_test(p->a.mnt_flags, PLINK)
15599+ && au_plink_test(sb, inode)
15600+ /* && atomic_read(&inode->i_count) == 2) */) {
15601+ au_debug_on();
15602+ DbgInode(inode);
15603+ au_debug_off();
15604+ }
15605+#endif
15606+ /*
15607+ * although this is not a dir,
15608+ * set it here since we need to detect the dead inode.
15609+ */
15610+ if (!inode->i_nlink)
15611+ inode->i_flags |= S_DEAD;
15612+ epilog(dir, dentry, bindex);
15613+
15614+ /* update target timestamps */
15615+ if (bindex == bstart) {
15616+ au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
15617+ inode->i_ctime = h_dentry->d_inode->i_ctime;
15618+ } else
15619+ /* todo: this timestamp may be reverted later */
15620+ inode->i_ctime = h_dir->i_ctime;
15621+ goto out_unlock; /* success */
15622+ }
15623+
15624+ /* revert */
15625+ if (wh_dentry) {
15626+ int rerr;
15627+ unsigned int rev_flags;
15628+
15629+ rev_flags = 0;
15630+ if (dlgt)
15631+ au_fset_rev(rev_flags, DLGT);
15632+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt,
15633+ rev_flags);
15634+ if (rerr)
15635+ err = rerr;
15636+ }
15637+
15638+ out_unlock:
15639+ au_unpin(&pin);
15640+ dput(wh_dentry);
15641+ dput(h_dentry);
15642+ out:
15643+ di_write_unlock(parent);
15644+ aufs_read_unlock(dentry, AuLock_DW);
15645+ AuTraceErr(err);
15646+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
15647+ err = -ESTALE;
15648+ return err;
15649+}
15650+
15651+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
15652+{
15653+ int err, rmdir_later;
15654+ struct inode *inode;
15655+ struct dentry *parent, *wh_dentry, *h_dentry;
15656+ struct au_dtime dt;
15657+ aufs_bindex_t bwh, bindex, bstart;
15658+ struct au_whtmp_rmdir_args *args;
15659+ struct au_nhash *whlist;
15660+ struct super_block *sb;
15661+ unsigned int mnt_flags;
15662+ struct au_pin pin;
15663+
15664+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
15665+ IMustLock(dir);
15666+ inode = dentry->d_inode;
15667+ err = -ENOENT; /* possible? */
15668+ if (unlikely(!inode))
15669+ goto out;
15670+ IMustLock(inode);
15671+
15672+ whlist = au_nhash_new(GFP_NOFS);
15673+ err = PTR_ERR(whlist);
15674+ if (IS_ERR(whlist))
15675+ goto out;
15676+
15677+ err = -ENOMEM;
15678+ args = kmalloc(sizeof(*args), GFP_NOFS);
15679+ if (unlikely(!args))
15680+ goto out_whlist;
15681+
15682+ aufs_read_lock(dentry, AuLock_DW);
15683+ parent = dentry->d_parent; /* dir inode is locked */
15684+ di_write_lock_parent(parent);
15685+ err = au_test_empty(dentry, whlist);
15686+ if (unlikely(err))
15687+ goto out_args;
15688+
15689+ bstart = au_dbstart(dentry);
15690+ bwh = au_dbwh(dentry);
15691+ bindex = -1;
15692+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
15693+ err = PTR_ERR(wh_dentry);
15694+ if (IS_ERR(wh_dentry))
15695+ goto out_args;
15696+
15697+ AuDebugOn(au_dbstart(dentry) != bstart);
15698+ h_dentry = au_h_dptr(dentry, bstart);
15699+ dget(h_dentry);
15700+
15701+ rmdir_later = 0;
15702+ if (bindex == bstart) {
15703+ err = renwh_and_rmdir(dentry, bstart, whlist, dir);
15704+ if (err > 0) {
15705+ rmdir_later = err;
15706+ err = 0;
15707+ }
15708+ } else {
15709+ /* dir inode is locked */
15710+ AuDebugOn(!wh_dentry
15711+ || wh_dentry->d_parent != au_h_dptr(parent, bindex));
15712+ IMustLock(wh_dentry->d_parent->d_inode);
15713+ err = 0;
15714+ }
15715+
15716+ sb = dentry->d_sb;
15717+ mnt_flags = au_mntflags(sb);
15718+ if (!err) {
15719+ if (au_opt_test(mnt_flags, UDBA_INOTIFY) && rmdir_later)
15720+ au_reset_hinotify(inode, /*flags*/0);
15721+ clear_nlink(inode);
15722+ inode->i_flags |= S_DEAD;
15723+ au_set_dbdiropq(dentry, -1);
15724+ epilog(dir, dentry, bindex);
15725+
15726+ if (rmdir_later) {
15727+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, whlist,
15728+ args);
15729+ args = NULL;
15730+ }
15731+
15732+ goto out_unlock; /* success */
15733+ }
15734+
15735+ /* revert */
15736+ LKTRLabel(revert);
15737+ if (wh_dentry) {
15738+ int rerr;
15739+ unsigned int rev_flags;
15740+
15741+ rev_flags = 0;
15742+ if (au_test_dlgt(mnt_flags))
15743+ au_fset_rev(rev_flags, DLGT);
15744+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt,
15745+ rev_flags);
15746+ if (rerr)
15747+ err = rerr;
15748+ }
15749+
15750+ out_unlock:
15751+ au_unpin(&pin);
15752+ dput(wh_dentry);
15753+ dput(h_dentry);
15754+ out_args:
15755+ di_write_unlock(parent);
15756+ aufs_read_unlock(dentry, AuLock_DW);
15757+ kfree(args);
15758+ out_whlist:
15759+ au_nhash_del(whlist);
15760+ out:
15761+ AuTraceErr(err);
15762+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
15763+ err = -ESTALE;
15764+ return err;
15765+}
15766diff -urN linux/fs/aufs/i_op_ren.c linux-aufs/fs/aufs/i_op_ren.c
15767--- linux/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
15768+++ linux-aufs/fs/aufs/i_op_ren.c 2009-03-12 16:18:04.000000000 +0100
15769@@ -0,0 +1,1261 @@
15770+/*
15771+ * Copyright (C) 2005-2009 Junjiro Okajima
15772+ *
15773+ * This program, aufs is free software; you can redistribute it and/or modify
15774+ * it under the terms of the GNU General Public License as published by
15775+ * the Free Software Foundation; either version 2 of the License, or
15776+ * (at your option) any later version.
15777+ *
15778+ * This program is distributed in the hope that it will be useful,
15779+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15780+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15781+ * GNU General Public License for more details.
15782+ *
15783+ * You should have received a copy of the GNU General Public License
15784+ * along with this program; if not, write to the Free Software
15785+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15786+ */
15787+
15788+/*
15789+ * inode operation (rename entry)
15790+ * todo: this is crazy monster
15791+ *
15792+ * $Id$
15793+ */
15794+
15795+#include "aufs.h"
15796+
15797+enum { SRC, DST };
15798+
15799+#define AuRen_ISDIR 1
15800+#define AuRen_ISSAMEDIR (1 << 1)
15801+#define AuRen_WHSRC (1 << 2)
15802+#define AuRen_WHDST (1 << 3)
15803+#define AuRen_DLGT (1 << 4)
15804+#define AuRen_VFSLOCK (1 << 5)
15805+#define AuRen_PINNED (1 << 6)
15806+#define AuRen_MNT_WRITE (1 << 7)
15807+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
15808+#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
15809+#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
15810+#ifndef CONFIG_AUFS_DLGT
15811+#undef AuRen_DLGT
15812+#define AuRen_DLGT 0
15813+#endif
15814+
15815+struct au_ren_args {
15816+ /* original args */
15817+ struct dentry *src_dentry, *dentry;
15818+ struct inode *src_dir, *dir;
15819+
15820+ struct dentry *h_dentry[2], *h_parent[2], *h_trap, *h_locked[2];
15821+ /* todo: remove them */
15822+ struct dentry *parent[2], *gparent[2];
15823+ struct au_pin pin[2];
15824+ struct au_nhash whlist;
15825+ aufs_bindex_t btgt, bstart[2];
15826+ /* do_rename() only */
15827+ unsigned char need_diropq, bycpup;
15828+ struct super_block *sb;
15829+ unsigned int flags;
15830+ unsigned int mnt_flags;
15831+ struct au_ndx ndx;
15832+
15833+ /* do_rename() only */
15834+#ifdef CONFIG_AUFS_BR_NFS
15835+ struct au_hin_ignore ign[3];
15836+#else
15837+ struct au_hin_ignore ign[2];
15838+#endif
15839+ struct vfsub_args vargs;
15840+ struct au_whtmp_rmdir_args *thargs;
15841+ struct dentry *wh_dentry[2], *h_dst, *h_src;
15842+};
15843+
15844+/* ---------------------------------------------------------------------- */
15845+
15846+#define RevertFailure(fmt, args...) do { \
15847+ AuIOErrWhck("revert failure: " fmt " (%d, %d)\n", \
15848+ ##args, err, rerr); \
15849+ err = -EIO; \
15850+ } while (0)
15851+
15852+static noinline_for_stack
15853+void au_ren_rev_diropq(int err, struct au_ren_args *a)
15854+{
15855+ int rerr;
15856+ struct mutex *h_mtx;
15857+
15858+ /* lock inode simply since inotify is not set to h_inode. */
15859+ h_mtx = &au_h_dptr(a->src_dentry, a->btgt)->d_inode->i_mutex;
15860+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15861+ rerr = au_diropq_remove(a->src_dentry, a->btgt,
15862+ au_ftest_ren(a->flags, DLGT));
15863+ mutex_unlock(h_mtx);
15864+ if (rerr)
15865+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
15866+}
15867+
15868+static noinline_for_stack
15869+void au_ren_rev_rename(int err, struct au_ren_args *a)
15870+{
15871+ int rerr;
15872+ struct dentry *h_d;
15873+ struct qstr *name = &a->src_dentry->d_name;
15874+
15875+ h_d = au_lkup_one(name->name, a->h_parent[SRC], name->len, &a->ndx);
15876+ rerr = PTR_ERR(h_d);
15877+ if (IS_ERR(h_d)) {
15878+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
15879+ return;
15880+ }
15881+
15882+ AuDebugOn(h_d->d_inode);
15883+ vfsub_args_reinit(&a->vargs);
15884+ vfsub_ign_hinode(&a->vargs, IN_MOVED_FROM,
15885+ au_pinned_hdir(a->pin + DST));
15886+ vfsub_ign_hinode(&a->vargs, IN_MOVED_TO, au_pinned_hdir(a->pin + SRC));
15887+ rerr = vfsub_rename(au_pinned_h_dir(a->pin + DST),
15888+ au_h_dptr(a->src_dentry, a->btgt),
15889+ au_pinned_h_dir(a->pin + SRC), h_d, &a->vargs);
15890+ d_drop(h_d);
15891+ dput(h_d);
15892+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
15893+ if (rerr)
15894+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
15895+}
15896+
15897+static noinline_for_stack
15898+void au_ren_rev_cpup(int err, struct au_ren_args *a)
15899+{
15900+ int rerr;
15901+
15902+ vfsub_args_reinit(&a->vargs);
15903+ vfsub_ign_hinode(&a->vargs, IN_DELETE, au_pinned_hdir(a->pin + DST));
15904+ rerr = vfsub_unlink(au_pinned_h_dir(a->pin + DST), a->h_dentry[DST],
15905+ &a->vargs);
15906+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
15907+ au_set_dbstart(a->src_dentry, a->bstart[SRC]);
15908+ if (rerr)
15909+ RevertFailure("unlink %.*s", AuDLNPair(a->h_dentry[DST]));
15910+}
15911+
15912+static noinline_for_stack
15913+void au_ren_rev_whtmp(int err, struct au_ren_args *a)
15914+{
15915+ int rerr;
15916+ struct dentry *h_d;
15917+ struct mutex *h_mtx;
15918+ struct qstr *name = &a->dentry->d_name;
15919+
15920+ h_d = au_lkup_one(name->name, a->h_parent[DST], name->len, &a->ndx);
15921+ rerr = PTR_ERR(h_d);
15922+ if (IS_ERR(h_d)) {
15923+ RevertFailure("lookup %.*s", AuLNPair(name));
15924+ return;
15925+ }
15926+ if (h_d->d_inode) {
15927+ d_drop(h_d);
15928+ dput(h_d);
15929+ return;
15930+ }
15931+
15932+ h_mtx = &a->h_dst->d_inode->i_mutex;
15933+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15934+ au_hin_resume(au_hi(a->src_dentry->d_inode, a->btgt));
15935+ mutex_unlock(h_mtx);
15936+ vfsub_args_reinit(&a->vargs);
15937+ vfsub_ign_hinode(&a->vargs, IN_MOVED_TO | IN_MOVED_FROM,
15938+ au_pinned_hdir(a->pin + DST));
15939+ rerr = vfsub_rename(au_pinned_h_dir(a->pin + DST), a->h_dst,
15940+ au_pinned_h_dir(a->pin + DST), h_d, &a->vargs);
15941+ d_drop(h_d);
15942+ dput(h_d);
15943+ if (!rerr) {
15944+ au_set_h_dptr(a->dentry, a->btgt, NULL);
15945+ au_set_h_dptr(a->dentry, a->btgt, dget(a->h_dst));
15946+ } else
15947+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
15948+}
15949+
15950+static noinline_for_stack
15951+void au_ren_rev_whsrc(int err, struct au_ren_args *a)
15952+{
15953+ int rerr;
15954+
15955+ rerr = au_wh_unlink_dentry(au_pinned_hdir(a->pin + SRC),
15956+ a->wh_dentry[SRC], a->src_dentry, /*dlgt*/0);
15957+ if (rerr)
15958+ RevertFailure("unlink %.*s", AuDLNPair(a->wh_dentry[SRC]));
15959+}
15960+#undef RevertFailure
15961+
15962+/* ---------------------------------------------------------------------- */
15963+
15964+static /* noinline_for_stack */
15965+int au_ren_or_cpup(struct au_ren_args *a)
15966+{
15967+ int err;
15968+
15969+ AuTraceEnter();
15970+
15971+ if (au_dbstart(a->src_dentry) == a->btgt) {
15972+ if (a->need_diropq && au_dbdiropq(a->src_dentry) == a->btgt)
15973+ a->need_diropq = 0;
15974+ vfsub_ign_hinode(&a->vargs, IN_MOVED_FROM,
15975+ au_pinned_hdir(a->pin + SRC));
15976+ vfsub_ign_hinode(&a->vargs, IN_MOVED_TO,
15977+ au_pinned_hdir(a->pin + DST));
15978+ /* nfs_rename() calls d_delete() */
15979+ if (au_test_nfs(au_pinned_h_dir(a->pin + DST)->i_sb)
15980+ && a->h_dentry[DST]->d_inode
15981+ && (S_ISDIR(a->h_dentry[DST]->d_inode->i_mode)
15982+ || atomic_read(&a->h_dentry[DST]->d_count) <= 2))
15983+ vfsub_ign_hinode(&a->vargs, IN_DELETE,
15984+ au_pinned_hdir(a->pin + DST));
15985+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
15986+ err = vfsub_rename(au_pinned_h_dir(a->pin + SRC),
15987+ au_h_dptr(a->src_dentry, a->btgt),
15988+ au_pinned_h_dir(a->pin + DST),
15989+ a->h_dentry[DST], &a->vargs);
15990+ } else {
15991+ struct mutex *h_mtx = &a->h_dentry[SRC]->d_inode->i_mutex;
15992+
15993+ a->bycpup = 1;
15994+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15995+ au_set_dbstart(a->src_dentry, a->btgt);
15996+ au_set_h_dptr(a->src_dentry, a->btgt, dget(a->h_dentry[DST]));
15997+ err = au_sio_cpup_single(a->src_dentry, a->btgt, a->bstart[SRC],
15998+ -1, !AuCpup_DTIME, a->parent[DST]);
15999+ if (unlikely(err)) {
16000+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
16001+ au_set_dbstart(a->src_dentry, a->bstart[SRC]);
16002+ }
16003+ mutex_unlock(h_mtx);
16004+ }
16005+
16006+ return err;
16007+}
16008+
16009+static /* noinline_for_stack */
16010+int au_ren_del_whtmp(struct au_ren_args *a)
16011+{
16012+ int err;
16013+
16014+ AuTraceEnter();
16015+
16016+ if (au_test_nfs(a->h_dst->d_sb)
16017+ || !au_nhash_test_longer_wh(&a->whlist, a->btgt,
16018+ au_sbi(a->sb)->si_dirwh)) {
16019+ err = au_whtmp_rmdir(a->dir, a->btgt, a->h_dst, &a->whlist);
16020+ if (unlikely(err))
16021+ AuWarn("failed removing whtmp dir %.*s (%d), "
16022+ "ignored.\n", AuDLNPair(a->h_dst), err);
16023+ } else {
16024+ au_whtmp_kick_rmdir(a->dir, a->btgt, a->h_dst, &a->whlist,
16025+ a->thargs);
16026+ dput(a->h_dst);
16027+ a->thargs = NULL;
16028+ }
16029+
16030+ return 0;
16031+}
16032+
16033+static /* noinline_for_stack */
16034+int au_ren_diropq(struct au_ren_args *a)
16035+{
16036+ int err;
16037+ struct dentry *diropq;
16038+ struct mutex *h_mtx;
16039+
16040+ AuTraceEnter();
16041+
16042+ err = 0;
16043+ h_mtx = &au_h_dptr(a->src_dentry, a->btgt)->d_inode->i_mutex;
16044+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16045+ diropq = au_diropq_create(a->src_dentry, a->btgt,
16046+ au_ftest_ren(a->flags, DLGT));
16047+ mutex_unlock(h_mtx);
16048+ if (IS_ERR(diropq))
16049+ err = PTR_ERR(diropq);
16050+ dput(diropq);
16051+
16052+ return err;
16053+}
16054+
16055+static /* noinline_for_stack */
16056+int do_rename(struct au_ren_args *a)
16057+{
16058+ int err;
16059+ aufs_bindex_t bindex, bend;
16060+ struct dentry *h_d;
16061+
16062+ LKTRTrace("%.*s/%.*s, %.*s/%.*s, "
16063+ "hd{%p, %p}, hp{%p, %p}, wh %p, btgt %d, bstart{%d, %d}, "
16064+ "flags 0x%x\n",
16065+ AuDLNPair(a->parent[SRC]), AuDLNPair(a->src_dentry),
16066+ AuDLNPair(a->parent[DST]), AuDLNPair(a->dentry),
16067+ a->h_dentry[SRC], a->h_dentry[DST],
16068+ a->h_parent[SRC], a->h_parent[DST],
16069+ &a->whlist, a->btgt,
16070+ a->bstart[SRC], a->bstart[DST],
16071+ a->flags);
16072+
16073+ /* prepare workqueue args */
16074+ if (au_ftest_ren(a->flags, ISDIR) && a->h_dentry[DST]->d_inode) {
16075+ err = -ENOMEM;
16076+ a->thargs = kmalloc(sizeof(*a->thargs), GFP_NOFS);
16077+ if (unlikely(!a->thargs))
16078+ goto out;
16079+ a->h_dst = dget(a->h_dentry[DST]);
16080+ }
16081+
16082+ a->ndx.nfsmnt = au_nfsmnt(a->sb, a->btgt);
16083+ if (au_ftest_ren(a->flags, DLGT))
16084+ au_fset_ndx(a->ndx.flags, DLGT);
16085+
16086+ /* create whiteout for src_dentry */
16087+ if (au_ftest_ren(a->flags, WHSRC)) {
16088+ a->wh_dentry[SRC] = au_wh_create(a->src_dentry, a->btgt,
16089+ a->h_parent[SRC], &a->ndx);
16090+ err = PTR_ERR(a->wh_dentry[SRC]);
16091+ if (IS_ERR(a->wh_dentry[SRC]))
16092+ goto out_thargs;
16093+ }
16094+
16095+ /* lookup whiteout for dentry */
16096+ if (au_ftest_ren(a->flags, WHDST)) {
16097+ h_d = au_wh_lkup(a->h_parent[DST], &a->dentry->d_name, &a->ndx);
16098+ err = PTR_ERR(h_d);
16099+ if (IS_ERR(h_d))
16100+ goto out_whsrc;
16101+ if (!h_d->d_inode)
16102+ dput(h_d);
16103+ else
16104+ a->wh_dentry[DST] = h_d;
16105+ }
16106+
16107+ /* rename dentry to tmpwh */
16108+ if (a->thargs) {
16109+ struct au_hinode *hinode;
16110+
16111+ AuDbgDentry(a->h_dentry[DST]);
16112+ err = au_whtmp_ren(a->dir, a->btgt, a->h_dentry[DST]);
16113+ if (unlikely(err))
16114+ goto out_whdst;
16115+ AuDbgDentry(a->h_dentry[DST]);
16116+ hinode = au_hi(a->dentry->d_inode, a->btgt);
16117+ /* todo: bad approach? */
16118+ mutex_lock_nested(&hinode->hi_inode->i_mutex, AuLsc_I_CHILD);
16119+ au_hin_suspend(hinode);
16120+ mutex_unlock(&hinode->hi_inode->i_mutex);
16121+ au_set_h_dptr(a->dentry, a->btgt, NULL);
16122+ AuDbgDentry(a->h_dentry[DST]);
16123+ err = au_lkup_neg(a->dentry, a->btgt);
16124+ if (unlikely(err))
16125+ goto out_whtmp;
16126+ a->h_dentry[DST] = au_h_dptr(a->dentry, a->btgt);
16127+ }
16128+
16129+ /* cpup src */
16130+ if (a->h_dentry[DST]->d_inode && a->bstart[SRC] != a->btgt) {
16131+ struct mutex *h_mtx = &a->h_dentry[SRC]->d_inode->i_mutex;
16132+
16133+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16134+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
16135+ !AuCpup_DTIME);
16136+ mutex_unlock(h_mtx);
16137+ if (unlikely(err))
16138+ goto out_whtmp;
16139+ }
16140+
16141+ /* rename by vfs_rename or cpup */
16142+ a->need_diropq = au_ftest_ren(a->flags, ISDIR)
16143+ && (a->wh_dentry[DST]
16144+ || au_dbdiropq(a->dentry) == a->btgt
16145+ /* hide the lower to keep xino */
16146+ || a->btgt < au_dbend(a->dentry)
16147+ || au_opt_test(a->mnt_flags, ALWAYS_DIROPQ));
16148+ a->bycpup = 0;
16149+ vfsub_args_init(&a->vargs, a->ign, au_ftest_ren(a->flags, DLGT), 0);
16150+ err = au_ren_or_cpup(a);
16151+ if (unlikely(err))
16152+ goto out_whtmp;
16153+
16154+ /* make dir opaque */
16155+ if (a->need_diropq) {
16156+ err = au_ren_diropq(a);
16157+ if (unlikely(err))
16158+ goto out_rename;
16159+ }
16160+
16161+ /* update target timestamps */
16162+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
16163+ a->h_src = au_h_dptr(a->src_dentry, a->btgt);
16164+ au_update_fuse_h_inode(NULL, a->h_src); /*ignore*/
16165+ /*
16166+ * fsstack_copy_attr_atime(a->src_dentry->d_inode, a->h_src->d_inode);
16167+ */
16168+ a->src_dentry->d_inode->i_ctime = a->h_src->d_inode->i_ctime;
16169+
16170+ /* remove whiteout for dentry */
16171+ if (a->wh_dentry[DST]) {
16172+ err = au_wh_unlink_dentry(au_pinned_hdir(a->pin + DST),
16173+ a->wh_dentry[DST], a->dentry,
16174+ /*dlgt*/0);
16175+ if (unlikely(err))
16176+ goto out_diropq;
16177+ }
16178+
16179+ /* remove whtmp */
16180+ if (a->thargs)
16181+ /* ignore this error */
16182+ au_ren_del_whtmp(a);
16183+
16184+ err = 0;
16185+ goto out_success;
16186+
16187+ out_diropq:
16188+ if (a->need_diropq)
16189+ au_ren_rev_diropq(err, a);
16190+ out_rename:
16191+ if (!a->bycpup)
16192+ au_ren_rev_rename(err, a);
16193+ else
16194+ au_ren_rev_cpup(err, a);
16195+ out_whtmp:
16196+ if (a->thargs)
16197+ au_ren_rev_whtmp(err, a);
16198+ out_whdst:
16199+ dput(a->wh_dentry[DST]);
16200+ a->wh_dentry[DST] = NULL;
16201+ out_whsrc:
16202+ if (a->wh_dentry[SRC])
16203+ au_ren_rev_whsrc(err, a);
16204+ d_drop(a->src_dentry);
16205+ bend = au_dbend(a->src_dentry);
16206+ for (bindex = au_dbstart(a->src_dentry); bindex <= bend; bindex++) {
16207+ h_d = au_h_dptr(a->src_dentry, bindex);
16208+ if (h_d)
16209+ d_drop(h_d);
16210+ }
16211+ d_drop(a->dentry);
16212+ bend = au_dbend(a->dentry);
16213+ for (bindex = au_dbstart(a->dentry); bindex <= bend; bindex++) {
16214+ h_d = au_h_dptr(a->dentry, bindex);
16215+ if (h_d)
16216+ d_drop(h_d);
16217+ }
16218+ au_update_dbstart(a->dentry);
16219+ if (a->thargs)
16220+ d_drop(a->h_dst);
16221+ out_success:
16222+ dput(a->wh_dentry[SRC]);
16223+ dput(a->wh_dentry[DST]);
16224+ out_thargs:
16225+ if (a->thargs) {
16226+ dput(a->h_dst);
16227+ kfree(a->thargs);
16228+ }
16229+ out:
16230+ AuTraceErr(err);
16231+ return err;
16232+}
16233+
16234+/*
16235+ * test if @dentry dir can be rename destination or not.
16236+ * success means, it is a logically empty dir.
16237+ */
16238+static int may_rename_dstdir(struct dentry *dentry, aufs_bindex_t btgt,
16239+ struct au_nhash *whlist)
16240+{
16241+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
16242+
16243+ return au_test_empty(dentry, whlist);
16244+}
16245+
16246+/*
16247+ * test if @dentry dir can be rename source or not.
16248+ * if it can, return 0 and @children is filled.
16249+ * success means,
16250+ * - or, it is a logically empty dir.
16251+ * - or, it exists on writable branch and has no children including whiteouts
16252+ * on the lower branch.
16253+ */
16254+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
16255+{
16256+ int err;
16257+ aufs_bindex_t bstart;
16258+
16259+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
16260+
16261+ bstart = au_dbstart(dentry);
16262+ if (bstart != btgt) {
16263+ struct au_nhash *whlist;
16264+
16265+ whlist = au_nhash_new(GFP_NOFS);
16266+ err = PTR_ERR(whlist);
16267+ if (IS_ERR(whlist))
16268+ goto out;
16269+ err = au_test_empty(dentry, whlist);
16270+ au_nhash_del(whlist);
16271+ goto out;
16272+ }
16273+
16274+ if (bstart == au_dbtaildir(dentry))
16275+ return 0; /* success */
16276+
16277+ err = au_test_empty_lower(dentry);
16278+
16279+ out:
16280+ if (/* unlikely */(err == -ENOTEMPTY)) {
16281+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
16282+ " is not supported\n");
16283+ err = -EXDEV;
16284+ }
16285+ AuTraceErr(err);
16286+ return err;
16287+}
16288+
16289+/* mainly for link(2) and rename(2) */
16290+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
16291+{
16292+ aufs_bindex_t bdiropq, bwh;
16293+ struct dentry *parent;
16294+
16295+ LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), btgt);
16296+ parent = dentry->d_parent;
16297+ IMustLock(parent->d_inode); /* dir is locked */
16298+
16299+ bdiropq = au_dbdiropq(parent);
16300+ bwh = au_dbwh(dentry);
16301+ if (au_br_rdonly(au_sbr(dentry->d_sb, btgt))
16302+ || (0 <= bdiropq && bdiropq < btgt)
16303+ || (0 <= bwh && bwh < btgt))
16304+ btgt = -1;
16305+
16306+ LKTRTrace("btgt %d\n", btgt);
16307+ return btgt;
16308+}
16309+
16310+/*
16311+ * simple tests for rename.
16312+ * following the checks in vfs, plus the parent-child relationship.
16313+ */
16314+static int au_may_ren(struct au_ren_args *a)
16315+{
16316+ int err;
16317+ struct inode *h_inode;
16318+
16319+ AuTraceEnter();
16320+
16321+ if (a->bstart[SRC] == a->btgt) {
16322+ err = au_may_del(a->src_dentry, a->btgt, a->h_parent[SRC],
16323+ au_ftest_ren(a->flags, ISDIR), &a->ndx);
16324+ if (unlikely(err))
16325+ goto out;
16326+ err = -EINVAL;
16327+ if (unlikely(a->h_dentry[SRC] == a->h_trap))
16328+ goto out;
16329+ }
16330+
16331+ err = 0;
16332+ if (a->bstart[DST] != a->btgt)
16333+ goto out;
16334+
16335+ err = -EIO;
16336+ h_inode = a->h_dentry[DST]->d_inode;
16337+ if (!a->dentry->d_inode) {
16338+ if (unlikely(h_inode))
16339+ goto out;
16340+ err = au_may_add(a->dentry, a->btgt, a->h_parent[DST],
16341+ au_ftest_ren(a->flags, ISDIR), &a->ndx);
16342+ } else {
16343+ if (unlikely(!h_inode || !h_inode->i_nlink))
16344+ goto out;
16345+ err = au_may_del(a->dentry, a->btgt, a->h_parent[DST],
16346+ au_ftest_ren(a->flags, ISDIR), &a->ndx);
16347+ if (unlikely(err))
16348+ goto out;
16349+ err = -ENOTEMPTY;
16350+ if (unlikely(a->h_dentry[DST] == a->h_trap))
16351+ goto out;
16352+ err = 0;
16353+ }
16354+
16355+ out:
16356+ if (unlikely(err == -ENOENT || err == -EEXIST))
16357+ err = -EIO;
16358+ AuTraceErr(err);
16359+ return err;
16360+}
16361+
16362+/*
16363+ * locking order
16364+ * (VFS)
16365+ * - src_dir and dir by lock_rename()
16366+ * - inode if exitsts
16367+ * (aufs)
16368+ * - lock all
16369+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
16370+ * + si_read_lock
16371+ * + di_write_lock2_child()
16372+ * + di_write_lock_child()
16373+ * + ii_write_lock_child()
16374+ * + di_write_lock_child2()
16375+ * + ii_write_lock_child2()
16376+ * + src_parent and parent
16377+ * + di_write_lock_parent()
16378+ * + ii_write_lock_parent()
16379+ * + di_write_lock_parent2()
16380+ * + ii_write_lock_parent2()
16381+ * + if udab=inotify is specified, lock grand parents (crazy)
16382+ * + di_read_lock_gparent()
16383+ * + ii_read_lock_gparent()
16384+ * + di_read_lock_gparent2()
16385+ * + ii_read_lock_gparent2()
16386+ * + mutex_lock(s_vfs_rename_mutex)
16387+ * + mutex_lock_gparent()
16388+ * + mutex_lock_gparent2()
16389+ * + mutex_lock_parent()
16390+ * + mutex_lock_parent2()
16391+ * + else lower src_dir and dir by vfsub_lock_rename()
16392+ * + verify the every relations between child, parent and grand parent. if any
16393+ * of them failed, unlock all and return -EBUSY.
16394+ */
16395+static void au_ren_pin_init(struct au_pin *first, struct dentry *d1,
16396+ struct au_pin *next, struct dentry *d2,
16397+ aufs_bindex_t bindex)
16398+{
16399+ AuTraceEnter();
16400+
16401+ /* AuLsc_DI_PARENT3 is for higher gparent initially */
16402+ au_pin_init(first, d1, bindex, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
16403+ AuPin_DI_LOCKED | AuPin_DO_GPARENT);
16404+ /* AuLsc_DI_PARENT4 is for lower gparent initially */
16405+ au_pin_init(next, d2, bindex, AuLsc_DI_PARENT3, AuLsc_I_PARENT4,
16406+ AuPin_DI_LOCKED | AuPin_DO_GPARENT);
16407+}
16408+
16409+static void au_ren_fake_pin(struct au_ren_args *a)
16410+{
16411+ int i;
16412+ struct au_pin1 *p;
16413+ struct inode *h_i;
16414+
16415+ AuTraceEnter();
16416+
16417+ /* they increment the ref counter */
16418+ for (i = 0; i < 2; i++) {
16419+ p = a->pin[i].pin + AuPin_PARENT;
16420+ au_pin_set_parent(a->pin + i, a->parent[i]);
16421+ dput(a->parent[i]);
16422+ h_i = a->h_parent[i]->d_inode;
16423+ au_pin_set_h_dir(a->pin + i, h_i);
16424+ iput(h_i);
16425+
16426+ if (!a->gparent[i]) {
16427+ au_pin_set_gparent(a->pin + i, NULL);
16428+ au_pin_set_h_gdir(a->pin + i, NULL);
16429+ } else {
16430+ au_pin_set_gparent(a->pin + i, a->gparent[i]);
16431+ dput(a->gparent[i]);
16432+ h_i = au_h_iptr(a->gparent[i]->d_inode, a->btgt);
16433+ au_pin_set_h_gdir(a->pin + i, h_i);
16434+ iput(h_i);
16435+ }
16436+ }
16437+}
16438+
16439+/* crazy */
16440+/* cf. i_op.c: au_do_pin() */
16441+static int au_ren_pin4(int higher, int lower, struct au_ren_args *a)
16442+{
16443+ int err, i, lsc;
16444+ struct au_pin *p;
16445+ struct au_pin1 *p4[4];
16446+ struct inode *h_dir;
16447+
16448+#if 0
16449+ lktr_set_pid(current->pid, LktrArrayPid);
16450+ LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
16451+ a->src_dir->i_ino, AuDLNPair(a->src_dentry),
16452+ a->dir->i_ino, AuDLNPair(a->dentry));
16453+ lktr_clear_pid(current->pid, LktrArrayPid);
16454+#endif
16455+ LKTRTrace("%d, %d\n", higher, lower);
16456+
16457+ err = 0;
16458+ p = a->pin + higher;
16459+ p4[0] = au_pin_gp(p); /* highest */
16460+ p4[1] = p->pin + AuPin_PARENT;
16461+ p = a->pin + lower;
16462+ p4[2] = au_pin_gp(p);
16463+ p4[3] = p->pin + AuPin_PARENT;
16464+
16465+ if (a->gparent[higher]) {
16466+ au_pin_do_set_parent(p4[0], a->gparent[higher]);
16467+ au_pin_do_set_dentry(p4[0], a->parent[higher]);
16468+ }
16469+ au_pin_do_set_parent(p4[1], a->parent[higher]);
16470+ if (a->gparent[lower]) {
16471+ au_pin_do_set_parent(p4[2], a->gparent[lower]);
16472+ au_pin_do_set_dentry(p4[2], a->parent[lower]);
16473+ }
16474+ au_pin_do_set_parent(p4[3], a->parent[lower]);
16475+
16476+#if 0
16477+ lktr_set_pid(current->pid, LktrArrayPid);
16478+ for (i = 0; i < 4; i++)
16479+ AuDbgDentry(p4[i]->parent);
16480+#endif
16481+ DiMustWriteLock(p4[3]->parent);
16482+ di_write_unlock(p4[1]->parent);
16483+ if (p4[2]->parent)
16484+ di_read_lock_parent2(p4[2]->parent, AuLock_IR);
16485+ di_write_lock_parent3(p4[1]->parent);
16486+ if (p4[0]->parent)
16487+ di_read_lock_parent4(p4[0]->parent, AuLock_IR);
16488+ //lktr_clear_pid(current->pid, LktrArrayPid);
16489+
16490+ vfsub_lock_rename_mutex(au_sbr_sb(a->dentry->d_sb, a->btgt));
16491+ au_fset_ren(a->flags, VFSLOCK);
16492+
16493+ lsc = AuLsc_I_PARENT;
16494+ for (i = 0; i < 4; i++, lsc++) {
16495+ if (p4[i]->parent) {
16496+ h_dir = au_h_iptr(p4[i]->parent->d_inode, a->btgt);
16497+ au_pin_do_set_h_dir(p4[i], h_dir);
16498+ mutex_lock_nested(&h_dir->i_mutex, lsc);
16499+ }
16500+ }
16501+
16502+ AuTraceErr(err);
16503+ return err;
16504+}
16505+
16506+static struct dentry *au_ren_pin3(int higher, int lower, struct au_ren_args *a)
16507+{
16508+ struct dentry *h_trap;
16509+ struct au_pin *p;
16510+ int err;
16511+
16512+ LKTRTrace("%d, %d\n", higher, lower);
16513+
16514+ p = a->pin + higher;
16515+ AuDebugOn(!au_pin_gp(p));
16516+ au_fset_pin(au_pin_gp(p)->flags, VFS_RENAME);
16517+ err = au_do_pin(p->pin + AuPin_PARENT, au_pin_gp(p));
16518+ h_trap = ERR_PTR(err);
16519+ if (unlikely(err))
16520+ goto out;
16521+ p = a->pin + lower;
16522+ au_fclr_pin(p->pin[AuPin_PARENT].flags, DO_GPARENT);
16523+ err = au_do_pin(p->pin + AuPin_PARENT, NULL);
16524+ h_trap = ERR_PTR(err);
16525+ if (unlikely(err)) {
16526+ p = a->pin + higher;
16527+ au_do_unpin(p->pin + AuPin_PARENT, au_pin_gp(p));
16528+ goto out;
16529+ }
16530+ h_trap = au_pinned_h_parent(p);
16531+
16532+ out:
16533+ AuTraceErrPtr(h_trap);
16534+ return h_trap;
16535+}
16536+
16537+static struct dentry *au_ren_pin(struct au_ren_args *a)
16538+{
16539+ struct dentry *h_trap;
16540+ struct inode *h_gdir;
16541+ int err, i, same_gp;
16542+
16543+ //lktr_set_pid(current->pid, LktrArrayPid);
16544+ AuTraceEnter();
16545+ AuDebugOn(!au_opt_test(a->mnt_flags, UDBA_INOTIFY));
16546+
16547+ /* gdir is not locked */
16548+ same_gp = 0;
16549+ if (!IS_ROOT(a->parent[SRC]))
16550+ a->gparent[SRC] = dget_parent(a->parent[SRC]);
16551+ if (!IS_ROOT(a->parent[DST])) {
16552+ a->gparent[DST] = dget_parent(a->parent[DST]);
16553+ same_gp = (a->gparent[SRC] == a->gparent[DST]);
16554+ }
16555+
16556+ /*
16557+ * patterns
16558+ * - gparent[SRC] is parent[DST]
16559+ * - parent[SRC] is gparent[DST]
16560+ * - gparent[SRC] is gparent[DST]
16561+ * - gparent[SRC] is a descendant of parent[DST]
16562+ * - parent[SRC] is an ancestor of gparent[DST]
16563+ * - not within grand parent range
16564+ */
16565+ err = 0;
16566+ h_trap = ERR_PTR(-EBUSY);
16567+ if (a->gparent[SRC] == a->parent[DST]) {
16568+ //AuDbg("here\n");
16569+ LKTRLabel(here);
16570+ au_ren_pin_init(a->pin + DST, a->dentry, a->pin + SRC,
16571+ a->src_dentry, a->btgt);
16572+ h_trap = au_ren_pin3(DST, SRC, a);
16573+ if (!IS_ERR(h_trap)) {
16574+ h_gdir = au_pinned_h_dir(a->pin + DST);
16575+ err = au_verify_parent(a->h_parent[SRC], h_gdir);
16576+ if (unlikely(err))
16577+ h_trap = ERR_PTR(-EBUSY);
16578+ }
16579+ } else if (a->parent[SRC] == a->gparent[DST] || same_gp) {
16580+ //AuDbg("here\n");
16581+ LKTRLabel(here);
16582+ au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST,
16583+ a->dentry, a->btgt);
16584+ h_trap = au_ren_pin3(SRC, DST, a);
16585+ if (!IS_ERR(h_trap)) {
16586+ if (!same_gp)
16587+ h_gdir = au_pinned_h_dir(a->pin + SRC);
16588+ else
16589+ h_gdir = au_pinned_h_gdir(a->pin + SRC);
16590+ err = au_verify_parent(a->h_parent[DST], h_gdir);
16591+ if (unlikely(err))
16592+ h_trap = ERR_PTR(-EBUSY);
16593+ }
16594+ } else if (a->gparent[SRC]
16595+ && (h_trap = au_test_subdir(a->gparent[SRC],
16596+ a->parent[DST]))) {
16597+ //AuDbg("here\n");
16598+ LKTRLabel(here);
16599+ au_ren_pin_init(a->pin + DST, a->dentry, a->pin + SRC,
16600+ a->src_dentry, a->btgt);
16601+ if (a->gparent[DST]) {
16602+ err = au_ren_pin4(DST, SRC, a);
16603+ if (unlikely(err))
16604+ h_trap = ERR_PTR(err);
16605+ } else {
16606+ struct dentry *t;
16607+ t = au_ren_pin3(DST, SRC, a);
16608+ AuDebugOn(t == h_trap);
16609+ }
16610+#if 1
16611+ } else if (a->gparent[DST]
16612+ && (h_trap = au_test_subdir(a->gparent[DST],
16613+ a->parent[SRC]))) {
16614+ /* todo: is this really necessary? */
16615+ //AuDbg("here\n");
16616+ LKTRLabel(here);
16617+ au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST,
16618+ a->dentry, a->btgt);
16619+ if (a->gparent[SRC]) {
16620+ err = au_ren_pin4(SRC, DST, a);
16621+ if (unlikely(err))
16622+ h_trap = ERR_PTR(err);
16623+ } else {
16624+ struct dentry *t;
16625+ t = au_ren_pin3(SRC, DST, a);
16626+ AuDebugOn(t == h_trap);
16627+ }
16628+#endif
16629+ } else /* if (a->gparent[DST]
16630+ && (h_trap = au_test_subdir(a->gparent[DST],
16631+ a->parent[SRC]))) */ {
16632+ //AuDbg("here\n");
16633+ LKTRLabel(here);
16634+ h_trap = NULL;
16635+ if (a->gparent[DST])
16636+ h_trap = au_test_subdir(a->gparent[DST],
16637+ a->parent[SRC]);
16638+ au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST,
16639+ a->dentry, a->btgt);
16640+ err = au_ren_pin4(SRC, DST, a);
16641+ if (unlikely(err))
16642+ h_trap = ERR_PTR(err);
16643+ }
16644+ au_fset_ren(a->flags, PINNED);
16645+
16646+ if (!IS_ERR(h_trap)) {
16647+ err = 0;
16648+ for (i = 0; !err && i < 2; i++) {
16649+ h_gdir = au_pinned_h_gdir(a->pin + i);
16650+ if (h_gdir)
16651+ err = au_verify_parent(a->h_parent[i], h_gdir);
16652+ }
16653+ if (unlikely(err)) {
16654+ h_trap = ERR_PTR(err);
16655+ //AuDbg("here\n");
16656+ }
16657+ }
16658+
16659+ dput(a->gparent[SRC]);
16660+ dput(a->gparent[DST]);
16661+ memset(a->gparent, 0, sizeof(a->gparent));
16662+ AuTraceErrPtr(h_trap);
16663+ //lktr_clear_pid(current->pid, LktrArrayPid);
16664+ return h_trap;
16665+}
16666+
16667+static void au_ren_unlock(struct au_ren_args *a)
16668+{
16669+ int i;
16670+
16671+ AuTraceEnter();
16672+
16673+ if (au_ftest_ren(a->flags, MNT_WRITE))
16674+ au_mnt_drop_write(au_sbr_mnt(a->dentry->d_sb, a->btgt));
16675+ if (a->h_locked[0])
16676+ vfsub_unlock_rename(a->h_locked[0], a->h_locked[1]);
16677+ if (au_ftest_ren(a->flags, PINNED)) {
16678+ au_unpin(a->pin + SRC);
16679+ au_unpin(a->pin + DST);
16680+ memset(a->gparent, 0, sizeof(a->gparent));
16681+ }
16682+ if (au_ftest_ren(a->flags, VFSLOCK))
16683+ vfsub_unlock_rename_mutex(au_sbr_sb(a->dentry->d_sb, a->btgt));
16684+ for (i = 0; i < 2; i++)
16685+ if (a->gparent[i]) {
16686+ di_read_unlock(a->gparent[i], AuLock_IR);
16687+ dput(a->gparent[i]);
16688+ }
16689+}
16690+
16691+static int au_ren_lock(struct au_ren_args *a)
16692+{
16693+ int err;
16694+ const int hinotify = au_opt_test(a->mnt_flags, UDBA_INOTIFY);
16695+
16696+ AuTraceEnter();
16697+
16698+ err = 0;
16699+ if (!hinotify
16700+ || (au_ftest_ren(a->flags, ISSAMEDIR) && IS_ROOT(a->parent[SRC]))) {
16701+ au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST,
16702+ a->dentry, a->btgt);
16703+ LKTRLabel(here);
16704+ a->h_locked[0] = a->h_parent[SRC];
16705+ a->h_locked[1] = a->h_parent[DST];
16706+ a->h_trap = vfsub_lock_rename(a->h_locked[0], a->h_locked[1]);
16707+ au_ren_fake_pin(a);
16708+ } else if (au_ftest_ren(a->flags, ISSAMEDIR)
16709+ && !IS_ROOT(a->parent[SRC])) {
16710+ /* this and next block should not be compiled when
16711+ hinotify is disabled */
16712+ /* irregular/tricky rename lock */
16713+ LKTRLabel(here);
16714+ au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST,
16715+ a->dentry, a->btgt);
16716+ a->gparent[SRC] = dget_parent(a->parent[SRC]);
16717+ di_read_lock_parent2(a->gparent[SRC], AuLock_IR);
16718+ a->h_locked[0] = a->h_parent[SRC];
16719+ a->h_locked[1] = dget_parent(a->h_parent[SRC]);
16720+ a->h_trap = vfsub_lock_rename(a->h_locked[0], a->h_locked[1]);
16721+ err = au_verify_parent(a->h_parent[SRC],
16722+ a->h_locked[1]->d_inode);
16723+ dput(a->h_locked[1]);
16724+ if (!err)
16725+ au_ren_fake_pin(a);
16726+ } else {
16727+ /* 3 or 4 dir locks. crazy */
16728+ LKTRLabel(here);
16729+ a->h_trap = au_ren_pin(a);
16730+ if (IS_ERR(a->h_trap))
16731+ err = PTR_ERR(a->h_trap);
16732+ }
16733+
16734+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
16735+ err = au_verify_parent(a->h_dentry[SRC],
16736+ a->h_parent[SRC]->d_inode);
16737+ if (!err && au_dbstart(a->dentry) == a->btgt)
16738+ err = au_verify_parent(a->h_dentry[DST],
16739+ a->h_parent[DST]->d_inode);
16740+ if (!err) {
16741+ err = au_br_want_write(au_sbr(a->dentry->d_sb, a->btgt));
16742+ if (unlikely(err))
16743+ goto out_unlock;
16744+ au_fset_ren(a->flags, MNT_WRITE);
16745+ goto out; /* success */
16746+ }
16747+
16748+ err = -EBUSY;
16749+
16750+ out_unlock:
16751+ au_ren_unlock(a);
16752+ out:
16753+ AuTraceErr(err);
16754+ return err;
16755+}
16756+
16757+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
16758+ struct inode *dir, struct dentry *dentry)
16759+{
16760+ int err;
16761+ aufs_bindex_t bend, bindex;
16762+ unsigned char do_dt_dstdir, hinotify;
16763+ struct inode *inode[2];
16764+ enum { PARENT, CHILD };
16765+ /* reduce stack space */
16766+ struct {
16767+ struct au_ren_args a;
16768+ struct au_dtime dt[2][2];
16769+ } *p;
16770+ struct au_wr_dir_args wr_dir_args = {
16771+ /* .force_btgt = -1, */
16772+ .flags = AuWrDir_ADD_ENTRY
16773+ };
16774+
16775+ LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
16776+ src_dir->i_ino, AuDLNPair(src_dentry),
16777+ dir->i_ino, AuDLNPair(dentry));
16778+ AuDebugOn(IS_ROOT(src_dentry) || IS_ROOT(dentry));
16779+ IMustLock(src_dir);
16780+ IMustLock(dir);
16781+ inode[DST] = dentry->d_inode;
16782+ if (inode[DST]) {
16783+ IMustLock(inode[DST]);
16784+ au_igrab(inode[DST]);
16785+ }
16786+
16787+ err = -ENOMEM;
16788+ BUILD_BUG_ON(sizeof(*p) > PAGE_SIZE);
16789+ p = kzalloc(sizeof(*p), GFP_NOFS);
16790+ if (unlikely(!p))
16791+ goto out;
16792+
16793+ err = -ENOTDIR;
16794+ p->a.src_dir = src_dir;
16795+ p->a.src_dentry = src_dentry;
16796+ p->a.dir = dir;
16797+ p->a.dentry = dentry;
16798+ p->a.sb = src_dentry->d_sb;
16799+ inode[SRC] = src_dentry->d_inode;
16800+ p->a.flags = 0;
16801+ if (S_ISDIR(inode[SRC]->i_mode)) {
16802+ au_fset_ren(p->a.flags, ISDIR);
16803+ if (unlikely(inode[DST] && !S_ISDIR(inode[DST]->i_mode)))
16804+ goto out_free;
16805+ aufs_read_and_write_lock2(dentry, src_dentry, AuLock_DIR);
16806+ } else
16807+ aufs_read_and_write_lock2(dentry, src_dentry, 0);
16808+
16809+ p->a.mnt_flags = au_mntflags(p->a.sb);
16810+ if (au_test_dlgt(p->a.mnt_flags))
16811+ au_fset_ren(p->a.flags, DLGT);
16812+ p->a.parent[SRC] = src_dentry->d_parent; /* dir inode is locked */
16813+ p->a.parent[DST] = dentry->d_parent; /* dir inode is locked */
16814+ au_fset_ren(p->a.flags, ISSAMEDIR); /* temporary */
16815+ di_write_lock_parent(p->a.parent[DST]);
16816+
16817+ /* which branch we process */
16818+ p->a.bstart[SRC] = au_dbstart(src_dentry);
16819+ p->a.bstart[DST] = au_dbstart(dentry);
16820+ if (au_ftest_ren(p->a.flags, ISDIR))
16821+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16822+ wr_dir_args.force_btgt = p->a.bstart[SRC];
16823+ if (dentry->d_inode && p->a.bstart[DST] < p->a.bstart[SRC])
16824+ wr_dir_args.force_btgt = p->a.bstart[DST];
16825+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
16826+ err = au_wr_dir(dentry, src_dentry, &wr_dir_args);
16827+ p->a.btgt = err;
16828+ if (unlikely(err < 0))
16829+ goto out_unlock;
16830+
16831+ /* are they available to be renamed */
16832+ err = 0;
16833+ au_nhash_init(&p->a.whlist);
16834+ if (au_ftest_ren(p->a.flags, ISDIR) && inode[DST]) {
16835+ au_set_dbstart(dentry, p->a.bstart[DST]);
16836+ err = may_rename_dstdir(dentry, p->a.btgt, &p->a.whlist);
16837+ au_set_dbstart(dentry, p->a.btgt);
16838+ }
16839+ p->a.h_dentry[DST] = au_h_dptr(dentry, au_dbstart(dentry));
16840+ if (unlikely(err))
16841+ goto out_unlock;
16842+ /* todo: minor optimize,
16843+ their sb may be same while their bindex differs? */
16844+ p->a.h_dentry[SRC] = au_h_dptr(src_dentry, au_dbstart(src_dentry));
16845+ if (au_ftest_ren(p->a.flags, ISDIR)) {
16846+ err = may_rename_srcdir(src_dentry, p->a.btgt);
16847+ if (unlikely(err))
16848+ goto out_children;
16849+ }
16850+
16851+ /* prepare the writable parent dir on the same branch */
16852+ if (p->a.bstart[DST] == p->a.btgt) {
16853+ au_fset_ren(p->a.flags, WHDST);
16854+ } else {
16855+ err = au_cpup_dirs(dentry, p->a.btgt);
16856+ if (unlikely(err))
16857+ goto out_children;
16858+ }
16859+
16860+ if (src_dir != dir) {
16861+ /*
16862+ * this temporary unlock is safe,
16863+ * because both dir->i_mutex are locked.
16864+ */
16865+ di_write_unlock(p->a.parent[DST]);
16866+ di_write_lock_parent(p->a.parent[SRC]);
16867+ err = au_wr_dir_need_wh
16868+ (src_dentry, au_ftest_ren(p->a.flags, ISDIR),
16869+ &p->a.btgt);
16870+ di_write_unlock(p->a.parent[SRC]);
16871+ di_write_lock2_parent(p->a.parent[SRC], p->a.parent[DST],
16872+ /*isdir*/1);
16873+ au_fclr_ren(p->a.flags, ISSAMEDIR);
16874+ } else
16875+ err = au_wr_dir_need_wh
16876+ (src_dentry, au_ftest_ren(p->a.flags, ISDIR),
16877+ &p->a.btgt);
16878+ if (unlikely(err < 0))
16879+ goto out_children;
16880+ if (err)
16881+ au_fset_ren(p->a.flags, WHSRC);
16882+
16883+ hinotify = au_opt_test(p->a.mnt_flags, UDBA_INOTIFY);
16884+ p->a.h_parent[SRC] = au_h_dptr(p->a.parent[SRC], p->a.btgt);
16885+ p->a.h_parent[DST] = au_h_dptr(p->a.parent[DST], p->a.btgt);
16886+ err = au_ren_lock(&p->a);
16887+ if (unlikely(err))
16888+ goto out_children;
16889+
16890+ if (!au_opt_test(p->a.mnt_flags, UDBA_NONE)) {
16891+ p->a.ndx.nfsmnt = au_nfsmnt(p->a.sb, p->a.btgt);
16892+ if (au_ftest_ren(p->a.flags, DLGT))
16893+ au_fset_ndx(p->a.ndx.flags, DLGT);
16894+ err = au_may_ren(&p->a);
16895+ if (unlikely(err))
16896+ goto out_hdir;
16897+ memset(&p->a.ndx, 0, sizeof(p->a.ndx));
16898+ }
16899+
16900+ /* store timestamps to be revertible */
16901+ au_dtime_store(p->dt[PARENT] + SRC, p->a.parent[SRC],
16902+ p->a.h_parent[SRC], au_pinned_hdir(p->a.pin + SRC),
16903+ au_pinned_hgdir(p->a.pin + SRC)
16904+ /* hgdir[SRC] */);
16905+ if (!au_ftest_ren(p->a.flags, ISSAMEDIR))
16906+ au_dtime_store(p->dt[PARENT] + DST, p->a.parent[DST],
16907+ p->a.h_parent[DST],
16908+ au_pinned_hdir(p->a.pin + DST),
16909+ au_pinned_hgdir(p->a.pin + DST)
16910+ /* hgdir[DST] */);
16911+ do_dt_dstdir = 0;
16912+ if (au_ftest_ren(p->a.flags, ISDIR)) {
16913+ au_dtime_store(p->dt[CHILD] + SRC, src_dentry,
16914+ p->a.h_dentry[SRC], au_hi(inode[SRC], p->a.btgt),
16915+ au_pinned_hdir(p->a.pin + SRC));
16916+ if (p->a.h_dentry[DST]->d_inode) {
16917+ do_dt_dstdir = 1;
16918+ au_dtime_store(p->dt[CHILD] + DST, dentry,
16919+ p->a.h_dentry[DST],
16920+ au_hi(inode[DST], p->a.btgt),
16921+ au_pinned_hdir(p->a.pin + DST));
16922+ }
16923+ }
16924+
16925+ err = do_rename(&p->a);
16926+ if (unlikely(err))
16927+ goto out_dt;
16928+
16929+ /* update dir attributes */
16930+ dir->i_version++;
16931+ if (au_ftest_ren(p->a.flags, ISDIR)) {
16932+ /* is this updating defined in POSIX? */
16933+ /* mutex_lock(&inode[SRC]->i_mutex); */
16934+ au_cpup_attr_timesizes(inode[SRC]);
16935+ /* mutex_unlock(&inode[SRC]->i_mutex); */
16936+
16937+ au_cpup_attr_nlink(dir, /*force*/1);
16938+ if (inode[DST]) {
16939+ clear_nlink(inode[DST]);
16940+ au_cpup_attr_timesizes(inode[DST]);
16941+ }
16942+ }
16943+ if (au_ibstart(dir) == p->a.btgt)
16944+ au_cpup_attr_timesizes(dir);
16945+
16946+ if (!au_ftest_ren(p->a.flags, ISSAMEDIR)) {
16947+ src_dir->i_version++;
16948+ if (au_ftest_ren(p->a.flags, ISDIR))
16949+ au_cpup_attr_nlink(src_dir, /*force*/1);
16950+ if (au_ibstart(src_dir) == p->a.btgt)
16951+ au_cpup_attr_timesizes(src_dir);
16952+ }
16953+
16954+ /* todo: simple d_drop(src_dentry) is not enough? */
16955+ /* dput/iput all lower dentries */
16956+ au_set_dbwh(src_dentry, -1);
16957+ bend = au_dbend(src_dentry);
16958+ for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
16959+ struct dentry *hd;
16960+ hd = au_h_dptr(src_dentry, bindex);
16961+ if (hd)
16962+ au_set_h_dptr(src_dentry, bindex, NULL);
16963+ }
16964+ au_set_dbend(src_dentry, p->a.btgt);
16965+
16966+ if (au_opt_test(p->a.mnt_flags, PLINK)
16967+ && au_plink_test(src_dentry->d_sb, inode[SRC]))
16968+ goto out_hdir; /* success */
16969+ bend = au_ibend(inode[SRC]);
16970+ for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
16971+ struct inode *hi;
16972+ hi = au_h_iptr(inode[SRC], bindex);
16973+ if (hi) {
16974+ au_xino_write0(p->a.sb, bindex, hi->i_ino, 0);
16975+ /* ignore this error */
16976+ au_set_h_iptr(inode[SRC], bindex, NULL, 0);
16977+ }
16978+ }
16979+ au_set_ibend(inode[SRC], p->a.btgt);
16980+ goto out_hdir; /* success */
16981+
16982+ out_dt:
16983+ au_dtime_revert(p->dt[PARENT] + SRC);
16984+ if (!au_ftest_ren(p->a.flags, ISSAMEDIR))
16985+ au_dtime_revert(p->dt[PARENT] + DST);
16986+ if (au_ftest_ren(p->a.flags, ISDIR) && err != -EIO) {
16987+ struct dentry *hd;
16988+
16989+ hd = p->dt[CHILD][SRC].dt_h_dentry;
16990+ mutex_lock_nested(&hd->d_inode->i_mutex, AuLsc_I_CHILD);
16991+ au_dtime_revert(p->dt[CHILD] + SRC);
16992+ mutex_unlock(&hd->d_inode->i_mutex);
16993+ if (do_dt_dstdir) {
16994+ hd = p->dt[CHILD][DST].dt_h_dentry;
16995+ mutex_lock_nested(&hd->d_inode->i_mutex, AuLsc_I_CHILD);
16996+ au_dtime_revert(p->dt[CHILD] + DST);
16997+ mutex_unlock(&hd->d_inode->i_mutex);
16998+ }
16999+ }
17000+ out_hdir:
17001+ au_ren_unlock(&p->a);
17002+ out_children:
17003+ au_nhash_fin(&p->a.whlist);
17004+ out_unlock:
17005+ if (unlikely(err && au_ftest_ren(p->a.flags, ISDIR))) {
17006+ au_update_dbstart(dentry);
17007+ d_drop(dentry);
17008+ }
17009+ if (!err) {
17010+ d_move(src_dentry, dentry);
17011+ if (inode[DST]
17012+ && (inode[DST]->i_nlink == 1
17013+ || au_ftest_ren(p->a.flags, ISDIR)))
17014+ inode[DST]->i_flags |= S_DEAD;
17015+ }
17016+ if (au_ftest_ren(p->a.flags, ISSAMEDIR))
17017+ di_write_unlock(p->a.parent[DST]);
17018+ else
17019+ di_write_unlock2(p->a.parent[SRC], p->a.parent[DST]);
17020+ aufs_read_and_write_unlock2(dentry, src_dentry);
17021+ out_free:
17022+ kfree(p);
17023+ out:
17024+ iput(inode[DST]);
17025+ AuTraceErr(err);
17026+ //lktr_clear_pid(current->pid, LktrArrayPid);
17027+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
17028+ err = -ESTALE;
17029+ return err;
17030+}
17031diff -urN linux/fs/aufs/Makefile linux-aufs/fs/aufs/Makefile
17032--- linux/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
17033+++ linux-aufs/fs/aufs/Makefile 2008-10-20 03:47:24.000000000 +0200
17034@@ -0,0 +1,74 @@
17035+# AUFS Makefile for the Linux 2.6.25 and later
17036+# $Id$
17037+
17038+# the environment variables are not inherited since 2.6.23
17039+ifdef AUFS_EXTRA_CFLAGS
17040+ccflags-y += ${AUFS_EXTRA_CFLAGS}
17041+endif
17042+
17043+########################################
17044+
17045+ifdef CONFIG_AUFS_RR_SQUASHFS
17046+# cf. squashfs3.2-r2 and sqlzma patch.
17047+ccflags-y += -DSQUASHFS_MAGIC=0x73717368
17048+ccflags-y += -DSQUASHFS_MAGIC_SWAP=0x68737173
17049+ccflags-y += -DSQUASHFS_MAGIC_LZMA=0x71736873
17050+ccflags-y += -DSQUASHFS_MAGIC_LZMA_SWAP=0x73687371
17051+endif
17052+
17053+# defined in ${srctree}/fs/fuse/inode.c
17054+ccflags-$(CONFIG_AUFS_WORKAROUND_FUSE) += -DFUSE_SUPER_MAGIC=0x65735546
17055+
17056+# defined in ${srctree}/fs/xfs/xfs_sb.h
17057+# tristate
17058+ifdef CONFIG_XFS_FS
17059+ccflags-y += -DXFS_SB_MAGIC=0x58465342
17060+endif
17061+
17062+# defined in ${srctree}/mm/shmem.c
17063+# tristate
17064+ifdef CONFIG_TMPFS
17065+ccflags-y += -DTMPFS_MAGIC=0x01021994
17066+endif
17067+
17068+# defined in ${srctree}fs/sysfs/mount.c
17069+# bool
17070+ccflags-$(CONFIG_SYSFS) += -DSYSFS_MAGIC=0x62656572
17071+
17072+ifndef EXTRAVERSION
17073+EXTRAVERSION = $(shell echo ${KERNELVERSION} | cut -f3- -d. | cut -f2- -d-)
17074+endif
17075+# for -mm tree, support the latest version only
17076+ifneq ($(strip $(shell echo ${EXTRAVERSION} | fgrep -- mm)),)
17077+ccflags-y += -DCONFIG_AUFS_UNIONFS22_PATCH -DCONFIG_AUFS_UNIONFS23_PATCH
17078+endif
17079+
17080+-include $(dir $(lastword ${MAKEFILE_LIST}))priv.mk
17081+#$(warning ${ccflags-y})
17082+
17083+########################################
17084+
17085+obj-$(CONFIG_AUFS) += aufs.o
17086+aufs-y := module.o super.o sbinfo.o branch.o xino.o sysaufs.o opts.o \
17087+ wkq.o vfsub.o dcsub.o \
17088+ cpup.o whout.o plink.o wbr_policy.o \
17089+ dentry.o dinfo.o \
17090+ file.o f_op.o finfo.o \
17091+ dir.o vdir.o \
17092+ inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o iinfo.o \
17093+ misc.o
17094+
17095+aufs-$(CONFIG_SYSFS) += sysfs.o
17096+aufs-$(CONFIG_AUFS_BR_NFS) += br_nfs.o
17097+aufs-$(CONFIG_AUFS_BR_XFS) += br_xfs.o
17098+aufs-$(CONFIG_AUFS_WORKAROUND_FUSE) += br_fuse.o
17099+aufs-$(CONFIG_AUFS_DLGT) += dlgt.o
17100+aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
17101+aufs-$(CONFIG_AUFS_HIN_OR_DLGT) += hin_or_dlgt.o
17102+aufs-$(CONFIG_AUFS_GETATTR) += getattr.o
17103+aufs-$(CONFIG_AUFS_EXPORT) += export.o
17104+aufs-$(CONFIG_AUFS_ROBR) += robr.o
17105+# reserved for future use
17106+#aufs-$(CONFIG_AUFS_XATTR) += xattr.o
17107+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
17108+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
17109diff -urN linux/fs/aufs/misc.c linux-aufs/fs/aufs/misc.c
17110--- linux/fs/aufs/misc.c 1970-01-01 01:00:00.000000000 +0100
17111+++ linux-aufs/fs/aufs/misc.c 2009-03-12 16:18:04.000000000 +0100
17112@@ -0,0 +1,308 @@
17113+/*
17114+ * Copyright (C) 2005-2009 Junjiro Okajima
17115+ *
17116+ * This program, aufs is free software; you can redistribute it and/or modify
17117+ * it under the terms of the GNU General Public License as published by
17118+ * the Free Software Foundation; either version 2 of the License, or
17119+ * (at your option) any later version.
17120+ *
17121+ * This program is distributed in the hope that it will be useful,
17122+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17123+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17124+ * GNU General Public License for more details.
17125+ *
17126+ * You should have received a copy of the GNU General Public License
17127+ * along with this program; if not, write to the Free Software
17128+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17129+ */
17130+
17131+/*
17132+ * $Id$
17133+ */
17134+
17135+#include "aufs.h"
17136+
17137+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
17138+{
17139+ void *q;
17140+
17141+ LKTRTrace("p %p, nused %d, sz %d\n", p, nused, new_sz);
17142+ AuDebugOn(new_sz <= 0);
17143+ if (new_sz <= nused)
17144+ return p;
17145+
17146+ q = krealloc(p, new_sz, gfp);
17147+ if (q)
17148+ memset(q + nused, 0, new_sz - nused);
17149+ return q;
17150+}
17151+
17152+/* ---------------------------------------------------------------------- */
17153+
17154+struct nameidata *au_dup_nd(struct au_sbinfo *sbinfo, struct nameidata *dst,
17155+ struct nameidata *src)
17156+{
17157+ LKTRTrace("src %p\n", src);
17158+
17159+ if (src) {
17160+ *dst = *src;
17161+ dst->flags &= ~LOOKUP_PARENT;
17162+ if (sbinfo->si_wbr_create == AuWbrCreate_TDP) {
17163+ if ((dst->flags & LOOKUP_CREATE)
17164+ && !(dst->intent.open.flags & O_CREAT))
17165+ dst->flags &= ~LOOKUP_CREATE;
17166+ } else {
17167+ dst->flags &= ~LOOKUP_CREATE;
17168+ dst->intent.open.flags &= ~O_CREAT;
17169+ }
17170+ } else
17171+ dst = NULL;
17172+
17173+ return dst;
17174+}
17175+
17176+struct nameidata *au_fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
17177+ struct super_block *sb, aufs_bindex_t bindex)
17178+{
17179+ LKTRTrace("nd %p, b%d\n", nd, bindex);
17180+
17181+ if (!nd)
17182+ return NULL;
17183+
17184+ DiMustAnyLock(nd->path.dentry);
17185+
17186+ fake_nd->path.dentry = NULL;
17187+ fake_nd->path.mnt = NULL;
17188+
17189+ if (bindex <= au_dbend(nd->path.dentry))
17190+ fake_nd->path.dentry = au_h_dptr(nd->path.dentry, bindex);
17191+ if (fake_nd->path.dentry) {
17192+ fake_nd->path.mnt = au_sbr_mnt(sb, bindex);
17193+ AuDebugOn(!fake_nd->path.mnt);
17194+ path_get(&fake_nd->path);
17195+ } else
17196+ fake_nd = ERR_PTR(-ENOENT);
17197+
17198+ AuTraceErrPtr(fake_nd);
17199+ return fake_nd;
17200+}
17201+
17202+void au_fake_dm_release(struct nameidata *fake_nd)
17203+{
17204+ if (fake_nd)
17205+ path_put(&fake_nd->path);
17206+}
17207+
17208+int au_h_create(struct inode *h_dir, struct dentry *h_dentry, int mode,
17209+ struct vfsub_args *vargs, struct nameidata *nd,
17210+ struct vfsmount *nfsmnt)
17211+{
17212+ int err;
17213+
17214+ LKTRTrace("hi%lu, %.*s, 0%o, nd %d, nfsmnt %d\n",
17215+ h_dir->i_ino, AuDLNPair(h_dentry), mode, !!nd, !!nfsmnt);
17216+
17217+ err = -ENOSYS;
17218+ if (!nfsmnt)
17219+ err = vfsub_create(h_dir, h_dentry, mode, /*nd*/NULL, vargs);
17220+ else {
17221+ struct nameidata fake_nd;
17222+
17223+ if (nd)
17224+ fake_nd = *nd;
17225+ else
17226+ memset(&fake_nd, 0, sizeof(fake_nd));
17227+ fake_nd.path.dentry = h_dentry;
17228+ fake_nd.path.mnt = nfsmnt;
17229+ path_get(&fake_nd.path);
17230+ fake_nd.flags = LOOKUP_CREATE;
17231+ fake_nd.intent.open.flags = O_CREAT | FMODE_READ;
17232+ fake_nd.intent.open.create_mode = mode;
17233+
17234+ err = vfsub_create(h_dir, h_dentry, mode, &fake_nd, vargs);
17235+ path_put(&fake_nd.path);
17236+ }
17237+
17238+ AuTraceErr(err);
17239+ return err;
17240+}
17241+
17242+/* ---------------------------------------------------------------------- */
17243+
17244+/* empty_zero_page is not exported on PPC before 2.6.26 */
17245+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) \
17246+ && (defined(CONFIG_PPC) || defined(CONFIG_PPC64))
17247+static char *au_zp_alloc(void)
17248+{
17249+ return (void *)get_zeroed_page(GFP_NOFS);
17250+}
17251+
17252+static void au_zp_free(char *p)
17253+{
17254+ if (p)
17255+ free_page((unsigned long)p);
17256+}
17257+#else
17258+static char *au_zp_alloc(void)
17259+{
17260+ return page_address(ZERO_PAGE(0));
17261+}
17262+
17263+static void au_zp_free(char *p)
17264+{
17265+ /* empty */
17266+}
17267+#endif
17268+
17269+int au_copy_file(struct file *dst, struct file *src, loff_t len,
17270+ struct au_hinode *hdir, struct super_block *sb,
17271+ struct vfsub_args *vargs)
17272+{
17273+ int err, all_zero, do_kfree;
17274+ unsigned long blksize;
17275+ char *buf, *zp;
17276+ /* reduce stack usage */
17277+ struct iattr *ia;
17278+
17279+ LKTRTrace("%.*s, %.*s\n",
17280+ AuDLNPair(dst->f_dentry), AuDLNPair(src->f_dentry));
17281+ AuDebugOn(!(dst->f_mode & FMODE_WRITE));
17282+#ifdef CONFIG_AUFS_DEBUG
17283+ {
17284+ struct dentry *parent;
17285+ parent = dget_parent(dst->f_dentry);
17286+ IMustLock(parent->d_inode);
17287+ dput(parent);
17288+ }
17289+#endif
17290+
17291+ err = -ENOMEM;
17292+ zp = au_zp_alloc();
17293+ if (unlikely(!zp))
17294+ goto out;
17295+ blksize = dst->f_dentry->d_sb->s_blocksize;
17296+ if (!blksize || PAGE_SIZE < blksize)
17297+ blksize = PAGE_SIZE;
17298+ LKTRTrace("blksize %lu\n", blksize);
17299+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(*ia));
17300+ if (do_kfree)
17301+ buf = kmalloc(blksize, GFP_NOFS);
17302+ else
17303+ buf = (void *)__get_free_page(GFP_NOFS);
17304+ if (unlikely(!buf))
17305+ goto out;
17306+
17307+#ifdef CONFIG_AUFS_DEBUG
17308+ if (len > (1 << 22))
17309+ AuWarn("copying a large file %lld\n", (long long)len);
17310+#endif
17311+ err = 0;
17312+ all_zero = 0;
17313+ src->f_pos = 0;
17314+ dst->f_pos = 0;
17315+ while (len) {
17316+ size_t sz, rbytes, wbytes;
17317+ char *p;
17318+
17319+ LKTRTrace("len %lld\n", len);
17320+ sz = blksize;
17321+ if (len < blksize)
17322+ sz = len;
17323+
17324+ /* support LSM and notify */
17325+ rbytes = 0;
17326+ /* todo: signal_pending? */
17327+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
17328+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos,
17329+ vfsub_ftest(vargs->flags, DLGT));
17330+ err = rbytes;
17331+ }
17332+ if (unlikely(err < 0))
17333+ break;
17334+
17335+ all_zero = 0;
17336+ if (len >= rbytes && rbytes == blksize) {
17337+#if 1
17338+ all_zero = !memcmp(buf, zp, rbytes);
17339+#else /* reserved for future use */
17340+ unsigned long long *ullp;
17341+ size_t n, i;
17342+
17343+ all_zero = 1;
17344+ ullp = (void *)buf;
17345+ n = rbytes / sizeof(*ullp);
17346+ i = n;
17347+ while (n-- > 0 && all_zero)
17348+ all_zero = !*ullp++;
17349+ p = (void *)ullp;
17350+ i *= sizeof(*ullp);
17351+ for (; all_zero && i < rbytes; i++)
17352+ all_zero = !*p++;
17353+#endif
17354+ }
17355+ if (!all_zero) {
17356+ wbytes = rbytes;
17357+ p = buf;
17358+ while (wbytes) {
17359+ size_t b;
17360+ /* support LSM and notify */
17361+ vfsub_args_reinit(vargs);
17362+ vfsub_ign_hinode(vargs, IN_MODIFY, hdir);
17363+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos,
17364+ vargs);
17365+ err = b;
17366+ /* todo: signal_pending? */
17367+ if (unlikely(err == -EAGAIN || err == -EINTR))
17368+ continue;
17369+ if (unlikely(err < 0))
17370+ break;
17371+ wbytes -= b;
17372+ p += b;
17373+ }
17374+ } else {
17375+ loff_t res;
17376+ LKTRLabel(hole);
17377+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
17378+ err = res;
17379+ if (unlikely(res < 0))
17380+ break;
17381+ }
17382+ len -= rbytes;
17383+ err = 0;
17384+ }
17385+
17386+ /* the last block may be a hole */
17387+ if (!err && all_zero) {
17388+ struct dentry *h_d = dst->f_dentry;
17389+ struct inode *h_i = h_d->d_inode;
17390+
17391+ LKTRLabel(last hole);
17392+ do {
17393+ /* todo: signal_pending? */
17394+ vfsub_args_reinit(vargs);
17395+ vfsub_ign_hinode(vargs, IN_MODIFY, hdir);
17396+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos, vargs);
17397+ } while (err == -EAGAIN || err == -EINTR);
17398+ if (err == 1) {
17399+ ia = (void *)buf;
17400+ ia->ia_size = dst->f_pos;
17401+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
17402+ ia->ia_file = dst;
17403+ vfsub_args_reinit(vargs);
17404+ vfsub_ign_hinode(vargs, vfsub_events_notify_change(ia),
17405+ hdir);
17406+ mutex_lock_nested(&h_i->i_mutex, AuLsc_I_CHILD2);
17407+ err = vfsub_notify_change(h_d, ia, vargs);
17408+ mutex_unlock(&h_i->i_mutex);
17409+ }
17410+ }
17411+ if (do_kfree)
17412+ kfree(buf);
17413+ else
17414+ free_page((unsigned long)buf);
17415+
17416+ out:
17417+ au_zp_free(zp);
17418+ AuTraceErr(err);
17419+ return err;
17420+}
17421diff -urN linux/fs/aufs/misc.h linux-aufs/fs/aufs/misc.h
17422--- linux/fs/aufs/misc.h 1970-01-01 01:00:00.000000000 +0100
17423+++ linux-aufs/fs/aufs/misc.h 2009-03-12 16:18:04.000000000 +0100
17424@@ -0,0 +1,244 @@
17425+/*
17426+ * Copyright (C) 2005-2009 Junjiro Okajima
17427+ *
17428+ * This program, aufs is free software; you can redistribute it and/or modify
17429+ * it under the terms of the GNU General Public License as published by
17430+ * the Free Software Foundation; either version 2 of the License, or
17431+ * (at your option) any later version.
17432+ *
17433+ * This program is distributed in the hope that it will be useful,
17434+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17435+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17436+ * GNU General Public License for more details.
17437+ *
17438+ * You should have received a copy of the GNU General Public License
17439+ * along with this program; if not, write to the Free Software
17440+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17441+ */
17442+
17443+/*
17444+ * $Id$
17445+ */
17446+
17447+#ifndef __AUFS_MISC_H__
17448+#define __AUFS_MISC_H__
17449+
17450+#ifdef __KERNEL__
17451+
17452+#include <linux/fs.h>
17453+#include <linux/namei.h>
17454+#include <linux/aufs_type.h>
17455+
17456+/* ---------------------------------------------------------------------- */
17457+
17458+typedef unsigned int au_gen_t;
17459+/* see linux/include/linux/jiffies.h */
17460+#define AuGenYounger(a, b) ((int)(b) - (int)(a) < 0)
17461+#define AuGenOlder(a, b) AufsGenYounger(b, a)
17462+
17463+/* ---------------------------------------------------------------------- */
17464+
17465+struct au_splhead {
17466+ spinlock_t spin;
17467+ struct list_head head;
17468+};
17469+
17470+static inline void au_spl_init(struct au_splhead *spl)
17471+{
17472+ spin_lock_init(&spl->spin);
17473+ INIT_LIST_HEAD(&spl->head);
17474+}
17475+
17476+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
17477+{
17478+ spin_lock(&spl->spin);
17479+ list_add(list, &spl->head);
17480+ spin_unlock(&spl->spin);
17481+}
17482+
17483+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
17484+{
17485+ spin_lock(&spl->spin);
17486+ list_del(list);
17487+ spin_unlock(&spl->spin);
17488+}
17489+
17490+/* ---------------------------------------------------------------------- */
17491+
17492+struct au_rwsem {
17493+ struct rw_semaphore rwsem;
17494+#ifdef CONFIG_AUFS_DEBUG
17495+ atomic_t rcnt;
17496+#endif
17497+};
17498+
17499+#ifdef CONFIG_AUFS_DEBUG
17500+#define AuDbgRcntInit(rw) do { \
17501+ atomic_set(&(rw)->rcnt, 0); \
17502+ smp_mb(); /* atomic set */ \
17503+} while (0)
17504+
17505+#define AuDbgRcntInc(rw) atomic_inc_return(&(rw)->rcnt)
17506+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
17507+#else
17508+#define AuDbgRcntInit(rw) do {} while (0)
17509+#define AuDbgRcntInc(rw) do {} while (0)
17510+#define AuDbgRcntDec(rw) do {} while (0)
17511+#endif /* CONFIG_AUFS_DEBUG */
17512+
17513+#define au_rwsem_destroy(rw) AuDebugOn(rwsem_is_locked(&(rw)->rwsem))
17514+
17515+static inline void au_rw_init_nolock(struct au_rwsem *rw)
17516+{
17517+ AuDbgRcntInit(rw);
17518+ init_rwsem(&rw->rwsem);
17519+}
17520+
17521+static inline void au_rw_init_wlock(struct au_rwsem *rw)
17522+{
17523+ au_rw_init_nolock(rw);
17524+ down_write(&rw->rwsem);
17525+}
17526+
17527+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
17528+ unsigned int lsc)
17529+{
17530+ au_rw_init_nolock(rw);
17531+ down_write_nested(&rw->rwsem, lsc);
17532+}
17533+
17534+static inline void au_rw_read_lock(struct au_rwsem *rw)
17535+{
17536+ down_read(&rw->rwsem);
17537+ AuDbgRcntInc(rw);
17538+}
17539+
17540+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
17541+{
17542+ down_read_nested(&rw->rwsem, lsc);
17543+ AuDbgRcntInc(rw);
17544+}
17545+
17546+static inline void au_rw_read_unlock(struct au_rwsem *rw)
17547+{
17548+ AuDbgRcntDec(rw);
17549+ up_read(&rw->rwsem);
17550+}
17551+
17552+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
17553+{
17554+ AuDbgRcntInc(rw);
17555+ downgrade_write(&rw->rwsem);
17556+}
17557+
17558+static inline void au_rw_write_lock(struct au_rwsem *rw)
17559+{
17560+ down_write(&rw->rwsem);
17561+}
17562+
17563+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
17564+ unsigned int lsc)
17565+{
17566+ down_write_nested(&rw->rwsem, lsc);
17567+}
17568+
17569+static inline void au_rw_write_unlock(struct au_rwsem *rw)
17570+{
17571+ up_write(&rw->rwsem);
17572+}
17573+
17574+/* why is not _nested version defined */
17575+static inline int au_rw_read_trylock(struct au_rwsem *rw)
17576+{
17577+ int ret = down_read_trylock(&rw->rwsem);
17578+ if (ret)
17579+ AuDbgRcntInc(rw);
17580+ return ret;
17581+}
17582+
17583+static inline int au_rw_write_trylock(struct au_rwsem *rw)
17584+{
17585+ return down_write_trylock(&rw->rwsem);
17586+}
17587+
17588+#undef AuDbgRcntInit
17589+#undef AuDbgRcntInc
17590+#undef AuDbgRcntDec
17591+
17592+/* to debug easier, do not make them inlined functions */
17593+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
17594+#define AuRwMustAnyLock(rw) AuDebugOn(down_write_trylock(&(rw)->rwsem))
17595+#ifdef CONFIG_AUFS_DEBUG
17596+#define AuRwMustReadLock(rw) do { \
17597+ AuRwMustAnyLock(rw); \
17598+ AuDebugOn(!atomic_read(&(rw)->rcnt)); \
17599+} while (0)
17600+
17601+#define AuRwMustWriteLock(rw) do { \
17602+ AuRwMustAnyLock(rw); \
17603+ AuDebugOn(atomic_read(&(rw)->rcnt)); \
17604+} while (0)
17605+#else
17606+#define AuRwMustReadLock(rw) AuRwMustAnyLock(rw)
17607+#define AuRwMustWriteLock(rw) AuRwMustAnyLock(rw)
17608+#endif /* CONFIG_AUFS_DEBUG */
17609+
17610+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
17611+static inline void prefix##_read_lock(param) \
17612+{ au_rw_read_lock(&(rwsem)); } \
17613+static inline void prefix##_write_lock(param) \
17614+{ au_rw_write_lock(&(rwsem)); } \
17615+static inline int prefix##_read_trylock(param) \
17616+{ return au_rw_read_trylock(&(rwsem)); } \
17617+static inline int prefix##_write_trylock(param) \
17618+{ return au_rw_write_trylock(&(rwsem)); }
17619+/* static inline void prefix##_read_trylock_nested(param, lsc)
17620+{au_rw_read_trylock_nested(&(rwsem, lsc));}
17621+static inline void prefix##_write_trylock_nestd(param, lsc)
17622+{au_rw_write_trylock_nested(&(rwsem), nested);} */
17623+
17624+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
17625+static inline void prefix##_read_unlock(param) \
17626+{ au_rw_read_unlock(&(rwsem)); } \
17627+static inline void prefix##_write_unlock(param) \
17628+{ au_rw_write_unlock(&(rwsem)); } \
17629+static inline void prefix##_downgrade_lock(param) \
17630+{ au_rw_dgrade_lock(&(rwsem)); }
17631+
17632+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
17633+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
17634+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
17635+
17636+/* ---------------------------------------------------------------------- */
17637+
17638+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
17639+
17640+struct au_nd_store {
17641+ unsigned int flags;
17642+ struct path path;
17643+ struct open_intent intent;
17644+};
17645+struct au_sbinfo;
17646+void au_nd_store(struct au_nd_store *store, struct nameidata *nd,
17647+ struct au_sbinfo *sbinfo);
17648+void au_nd_revert(struct au_nd_store *store, struct nameidata *nd,
17649+ struct au_sbinfo *sbinfo);
17650+
17651+struct nameidata *au_dup_nd(struct au_sbinfo *sbinfo, struct nameidata *dst,
17652+ struct nameidata *src);
17653+
17654+struct nameidata *au_fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
17655+ struct super_block *sb, aufs_bindex_t bindex);
17656+void au_fake_dm_release(struct nameidata *fake_nd);
17657+struct vfsub_args;
17658+int au_h_create(struct inode *h_dir, struct dentry *h_dentry, int mode,
17659+ struct vfsub_args *vargs, struct nameidata *nd,
17660+ struct vfsmount *nfsmnt);
17661+
17662+struct au_hinode;
17663+int au_copy_file(struct file *dst, struct file *src, loff_t len,
17664+ struct au_hinode *hdir, struct super_block *sb,
17665+ struct vfsub_args *vargs);
17666+
17667+#endif /* __KERNEL__ */
17668+#endif /* __AUFS_MISC_H__ */
17669diff -urN linux/fs/aufs/module.c linux-aufs/fs/aufs/module.c
17670--- linux/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
17671+++ linux-aufs/fs/aufs/module.c 2009-03-12 16:18:04.000000000 +0100
17672@@ -0,0 +1,269 @@
17673+/*
17674+ * Copyright (C) 2005-2009 Junjiro Okajima
17675+ *
17676+ * This program, aufs is free software; you can redistribute it and/or modify
17677+ * it under the terms of the GNU General Public License as published by
17678+ * the Free Software Foundation; either version 2 of the License, or
17679+ * (at your option) any later version.
17680+ *
17681+ * This program is distributed in the hope that it will be useful,
17682+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17683+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17684+ * GNU General Public License for more details.
17685+ *
17686+ * You should have received a copy of the GNU General Public License
17687+ * along with this program; if not, write to the Free Software
17688+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17689+ */
17690+
17691+/*
17692+ * module global variables and operations
17693+ *
17694+ * $Id$
17695+ */
17696+
17697+#include <linux/module.h>
17698+#include "aufs.h"
17699+
17700+/* ---------------------------------------------------------------------- */
17701+
17702+/*
17703+ * aufs caches
17704+ */
17705+struct kmem_cache *au_cachep[AuCache_Last];
17706+static int __init create_cache(void)
17707+{
17708+ au_cachep[AuCache_DINFO] = AuCache(au_dinfo);
17709+ if (au_cachep[AuCache_DINFO])
17710+ au_cachep[AuCache_ICNTNR] = AuCache(aufs_icntnr);
17711+ if (au_cachep[AuCache_ICNTNR])
17712+ au_cachep[AuCache_FINFO] = AuCache(au_finfo);
17713+ if (au_cachep[AuCache_FINFO])
17714+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
17715+ if (au_cachep[AuCache_VDIR])
17716+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
17717+ if (au_cachep[AuCache_DEHSTR])
17718+ return 0;
17719+
17720+ return -ENOMEM;
17721+}
17722+
17723+static void destroy_cache(void)
17724+{
17725+ int i;
17726+ for (i = 0; i < AuCache_Last; i++)
17727+ if (au_cachep[i]) {
17728+ kmem_cache_destroy(au_cachep[i]);
17729+ au_cachep[i] = NULL;
17730+ }
17731+}
17732+
17733+/* ---------------------------------------------------------------------- */
17734+
17735+char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
17736+int au_dir_roflags;
17737+
17738+/*
17739+ * functions for module interface.
17740+ */
17741+MODULE_LICENSE("GPL");
17742+/* MODULE_LICENSE("GPL v2"); */
17743+MODULE_AUTHOR("Junjiro Okajima");
17744+MODULE_DESCRIPTION(AUFS_NAME " -- Another unionfs");
17745+MODULE_VERSION(AUFS_VERSION);
17746+
17747+/* it should be 'byte', but param_set_byte() prints it by "%c" */
17748+short aufs_nwkq = AUFS_NWKQ_DEF;
17749+MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
17750+module_param_named(nwkq, aufs_nwkq, short, S_IRUGO);
17751+
17752+int sysaufs_brs;
17753+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
17754+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
17755+
17756+/* ---------------------------------------------------------------------- */
17757+
17758+static int __init aufs_init(void)
17759+{
17760+ int err, i;
17761+ char *p;
17762+
17763+ au_debug_init();
17764+#ifdef CONFIG_AUFS_INO_T_64
17765+ BUILD_BUG_ON(sizeof(ino_t) != sizeof(long long));
17766+#else
17767+ BUILD_BUG_ON(sizeof(ino_t) != sizeof(int));
17768+#endif
17769+
17770+ p = au_esc_chars;
17771+ for (i = 1; i <= ' '; i++)
17772+ *p++ = i;
17773+ *p++ = '\\';
17774+ *p++ = '\x7f';
17775+ *p = 0;
17776+
17777+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
17778+
17779+ err = -EINVAL;
17780+ if (unlikely(aufs_nwkq <= 0))
17781+ goto out;
17782+
17783+ err = sysaufs_init();
17784+ if (unlikely(err))
17785+ goto out;
17786+ err = au_wkq_init();
17787+ if (unlikely(err))
17788+ goto out_sysaufs;
17789+ err = au_inotify_init();
17790+ if (unlikely(err))
17791+ goto out_wkq;
17792+ err = au_sysrq_init();
17793+ if (unlikely(err))
17794+ goto out_inotify;
17795+
17796+ err = create_cache();
17797+ if (unlikely(err))
17798+ goto out_sysrq;
17799+
17800+ err = register_filesystem(&aufs_fs_type);
17801+ if (unlikely(err))
17802+ goto out_cache;
17803+ pr_info(AUFS_NAME " " AUFS_VERSION "\n");
17804+ return 0; /* success */
17805+
17806+ out_cache:
17807+ destroy_cache();
17808+ out_sysrq:
17809+ au_sysrq_fin();
17810+ out_inotify:
17811+ au_inotify_fin();
17812+ out_wkq:
17813+ au_wkq_fin();
17814+ out_sysaufs:
17815+ sysaufs_fin();
17816+ out:
17817+ AuTraceErr(err);
17818+ return err;
17819+}
17820+
17821+static void __exit aufs_exit(void)
17822+{
17823+ unregister_filesystem(&aufs_fs_type);
17824+ destroy_cache();
17825+
17826+ au_sysrq_fin();
17827+ au_inotify_fin();
17828+ au_wkq_fin();
17829+ sysaufs_fin();
17830+}
17831+
17832+module_init(aufs_init);
17833+module_exit(aufs_exit);
17834+
17835+/* ---------------------------------------------------------------------- */
17836+
17837+/* fake Kconfig */
17838+#if 1
17839+
17840+#if AUFS_BRANCH_MAX > 511 && PAGE_SIZE > 4096
17841+#warning pagesize is larger than 4kb, \
17842+ CONFIG_AUFS_BRANCH_MAX_511 or smaller is recommended.
17843+#endif
17844+
17845+#ifdef CONFIG_AUFS_STAT
17846+#ifndef CONFIG_SYSFS
17847+#error CONFIG_AUFS_STAT requires CONFIG_SYSFS.
17848+#endif
17849+#endif /* CONFIG_AUFS_STAT */
17850+
17851+#ifdef CONFIG_AUFS_SYSAUFS
17852+#warning CONFIG_AUFS_SYSAUFS is unnecessary for linux-2.6.25 and later.
17853+#endif
17854+
17855+#ifdef CONFIG_AUFS_HINOTIFY
17856+#ifndef CONFIG_INOTIFY
17857+#error enable CONFIG_INOTIFY to use CONFIG_AUFS_HINOTIFY.
17858+#endif
17859+#endif /* CONFIG_AUFS_HINOTIFY */
17860+
17861+#ifdef CONFIG_AUFS_EXPORT
17862+#if !defined(CONFIG_EXPORTFS) && !defined(CONFIG_EXPORTFS_MODULE)
17863+#error CONFIG_AUFS_EXPORT requires CONFIG_EXPORTFS
17864+#endif
17865+#if defined(CONFIG_EXPORTFS_MODULE) && defined(CONFIG_AUFS)
17866+#error need CONFIG_EXPORTFS = y to link aufs statically with CONFIG_AUFS_EXPORT.
17867+#endif
17868+#endif /* CONFIG_AUFS_EXPORT */
17869+
17870+#ifdef CONFIG_AUFS_SEC_PERM_PATCH
17871+#ifndef CONFIG_SECURITY
17872+#warning AUFS_SEC_PERM_PATCH is unnecessary since SECURITY is disabled.
17873+#endif
17874+#ifdef CONFIG_AUFS
17875+#warning AUFS_SEC_PERM_PATCH is unnecessary since AUFS is not a module.
17876+#endif
17877+#endif
17878+
17879+#ifdef CONFIG_AUFS_LHASH_PATCH
17880+#if !defined(CONFIG_NFS_FS) && !defined(CONFIG_NFS_FS_MODULE)
17881+#warning CONFIG_AUFS_LHASH_PATCH is unnecessary since CONFIG_NFS_FS is disabled.
17882+#endif
17883+#endif
17884+
17885+#ifdef CONFIG_AUFS_PUT_FILP_PATCH
17886+#ifndef CONFIG_NFS_V4
17887+#warning AUFS_PUT_FILP_PATCH is unnecessary since NFS_V4 is disabled.
17888+#endif
17889+#ifdef CONFIG_AUFS
17890+#warning AUFS_PUT_FILP_PATCH is unnecessary since AUFS is not a module.
17891+#endif
17892+#endif /* CONFIG_AUFS_PUT_FILP_PATCH */
17893+
17894+#ifdef CONFIG_AUFS_FSYNC_SUPER_PATCH
17895+#ifdef CONFIG_AUFS
17896+#warning AUFS_FSYNC_SUPER_PATCH is unnecessary since AUFS is not a module.
17897+#endif
17898+#endif
17899+
17900+#ifdef CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH
17901+#ifdef CONFIG_AUFS
17902+#warning AUFS_DENY_WRITE_ACCESS_PATCH is unnecessary since AUFS is not a module.
17903+#endif
17904+#endif
17905+
17906+#ifdef CONFIG_AUFS_KSIZE_PATCH
17907+#warning CONFIG_AUFS_KSIZE_PATCH is unnecessary for linux-2.6.22 and later.
17908+#endif
17909+
17910+#ifdef CONFIG_AUFS_WORKAROUND_FUSE
17911+#if !defined(CONFIG_FUSE_FS) && !defined(CONFIG_FUSE_FS_MODULE)
17912+#warning CONFIG_AUFS_WORKAROUND_FUSE is enabled while FUSE is disabled.
17913+#endif
17914+#endif
17915+
17916+#ifdef CONFIG_AUFS_DEBUG_LOCK
17917+#ifndef CONFIG_AUFS_MAGIC_SYSRQ
17918+#warning CONFIG_AUFS_DEBUG_LOCK is enabled but CONFIG_AUFS_MAGIC_SYSRQ.
17919+#endif
17920+#endif
17921+
17922+#ifdef CONFIG_AUFS_COMPAT
17923+#warning CONFIG_AUFS_COMPAT will be removed in the near future.
17924+#endif
17925+
17926+#ifdef CONFIG_AUFS_UNIONFS23_PATCH
17927+#ifndef CONFIG_AUFS_UNIONFS22_PATCH
17928+#error mis-config. AUFS_UNIONFS23_PATCH is enabled but AUFS_UNIONFS22_PATCH.
17929+#endif
17930+#ifndef CONFIG_AUFS_SPLICE_PATCH
17931+#error mis-config. AUFS_UNIONFS23_PATCH is enabled but AUFS_SPLICE_PATCH.
17932+#endif
17933+#endif
17934+
17935+#ifdef CONFIG_DEBUG_PROVE_LOCKING
17936+#if MAX_LOCKDEP_SUBCLASSES < AuLsc_I_End
17937+#warning lockdep will not work since aufs uses deeper locks.
17938+#endif
17939+#endif
17940+
17941+#endif
17942diff -urN linux/fs/aufs/module.h linux-aufs/fs/aufs/module.h
17943--- linux/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
17944+++ linux-aufs/fs/aufs/module.h 2009-03-12 16:18:04.000000000 +0100
17945@@ -0,0 +1,73 @@
17946+/*
17947+ * Copyright (C) 2005-2009 Junjiro Okajima
17948+ *
17949+ * This program, aufs is free software; you can redistribute it and/or modify
17950+ * it under the terms of the GNU General Public License as published by
17951+ * the Free Software Foundation; either version 2 of the License, or
17952+ * (at your option) any later version.
17953+ *
17954+ * This program is distributed in the hope that it will be useful,
17955+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17956+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17957+ * GNU General Public License for more details.
17958+ *
17959+ * You should have received a copy of the GNU General Public License
17960+ * along with this program; if not, write to the Free Software
17961+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17962+ */
17963+
17964+/*
17965+ * module initialization and module-global
17966+ *
17967+ * $Id$
17968+ */
17969+
17970+#ifndef __AUFS_MODULE_H__
17971+#define __AUFS_MODULE_H__
17972+
17973+#ifdef __KERNEL__
17974+
17975+/* module parameters */
17976+extern short aufs_nwkq;
17977+extern int sysaufs_brs;
17978+
17979+/* ---------------------------------------------------------------------- */
17980+
17981+extern char au_esc_chars[];
17982+extern int au_dir_roflags;
17983+
17984+/* kmem cache */
17985+enum {
17986+ AuCache_DINFO,
17987+ AuCache_ICNTNR,
17988+ AuCache_FINFO,
17989+ AuCache_VDIR,
17990+ AuCache_DEHSTR,
17991+#ifdef CONFIG_AUFS_HINOTIFY
17992+ AuCache_HINOTIFY,
17993+#endif
17994+ AuCache_Last
17995+};
17996+
17997+extern struct kmem_cache *au_cachep[];
17998+
17999+#define AuCacheArgs(type, sz) (type), (sz), 0, SLAB_RECLAIM_ACCOUNT, NULL
18000+#define AuCache(type) \
18001+ kmem_cache_create(AuCacheArgs(#type, sizeof(struct type)))
18002+
18003+/* ---------------------------------------------------------------------- */
18004+
18005+#define AuCacheFuncs(name, index) \
18006+static inline void *au_cache_alloc_##name(void) \
18007+{ return kmem_cache_alloc(au_cachep[index], GFP_NOFS); } \
18008+static inline void au_cache_free_##name(void *p) \
18009+{ kmem_cache_free(au_cachep[index], p); }
18010+
18011+AuCacheFuncs(dinfo, AuCache_DINFO);
18012+AuCacheFuncs(icntnr, AuCache_ICNTNR);
18013+AuCacheFuncs(finfo, AuCache_FINFO);
18014+AuCacheFuncs(vdir, AuCache_VDIR);
18015+AuCacheFuncs(dehstr, AuCache_DEHSTR);
18016+
18017+#endif /* __KERNEL__ */
18018+#endif /* __AUFS_MODULE_H__ */
18019diff -urN linux/fs/aufs/opts.c linux-aufs/fs/aufs/opts.c
18020--- linux/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
18021+++ linux-aufs/fs/aufs/opts.c 2009-03-12 16:18:04.000000000 +0100
18022@@ -0,0 +1,1613 @@
18023+/*
18024+ * Copyright (C) 2005-2009 Junjiro Okajima
18025+ *
18026+ * This program, aufs is free software; you can redistribute it and/or modify
18027+ * it under the terms of the GNU General Public License as published by
18028+ * the Free Software Foundation; either version 2 of the License, or
18029+ * (at your option) any later version.
18030+ *
18031+ * This program is distributed in the hope that it will be useful,
18032+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18033+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18034+ * GNU General Public License for more details.
18035+ *
18036+ * You should have received a copy of the GNU General Public License
18037+ * along with this program; if not, write to the Free Software
18038+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18039+ */
18040+
18041+/*
18042+ * mount options/flags
18043+ *
18044+ * $Id$
18045+ */
18046+
18047+#include <linux/types.h> /* a distribution requires */
18048+#include <linux/parser.h>
18049+#include "aufs.h"
18050+
18051+/* ---------------------------------------------------------------------- */
18052+
18053+enum {
18054+ Opt_br,
18055+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
18056+ Opt_idel, Opt_imod, Opt_ireorder,
18057+ Opt_dirwh, Opt_rdcache, Opt_deblk, Opt_nhash, Opt_rendir,
18058+ Opt_xino, Opt_zxino, Opt_noxino,
18059+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
18060+ Opt_trunc_xino_path, Opt_itrunc_xino,
18061+ Opt_xinodir,
18062+ Opt_trunc_xib, Opt_notrunc_xib,
18063+ Opt_dirperm1, Opt_nodirperm1,
18064+ Opt_shwh, Opt_noshwh,
18065+ Opt_plink, Opt_noplink, Opt_list_plink, Opt_clean_plink,
18066+ Opt_udba,
18067+ /* Opt_lock, Opt_unlock, */
18068+ Opt_cmd, Opt_cmd_args,
18069+ Opt_diropq_a, Opt_diropq_w,
18070+ Opt_warn_perm, Opt_nowarn_perm,
18071+ Opt_wbr_copyup, Opt_wbr_create,
18072+ Opt_coo,
18073+ Opt_dlgt, Opt_nodlgt,
18074+ Opt_refrof, Opt_norefrof,
18075+ Opt_verbose, Opt_noverbose,
18076+ Opt_sum, Opt_nosum, Opt_wsum,
18077+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
18078+};
18079+
18080+static match_table_t options = {
18081+ {Opt_br, "br=%s"},
18082+ {Opt_br, "br:%s"},
18083+
18084+ {Opt_add, "add=%d:%s"},
18085+ {Opt_add, "add:%d:%s"},
18086+ {Opt_add, "ins=%d:%s"},
18087+ {Opt_add, "ins:%d:%s"},
18088+ {Opt_append, "append=%s"},
18089+ {Opt_append, "append:%s"},
18090+ {Opt_prepend, "prepend=%s"},
18091+ {Opt_prepend, "prepend:%s"},
18092+
18093+ {Opt_del, "del=%s"},
18094+ {Opt_del, "del:%s"},
18095+ /* {Opt_idel, "idel:%d"}, */
18096+ {Opt_mod, "mod=%s"},
18097+ {Opt_mod, "mod:%s"},
18098+ {Opt_imod, "imod:%d:%s"},
18099+
18100+ {Opt_dirwh, "dirwh=%d"},
18101+ {Opt_dirwh, "dirwh:%d"},
18102+
18103+ {Opt_xino, "xino=%s"},
18104+ {Opt_xino, "xino:%s"},
18105+#if 0 /* def CONFIG_AUFS_EXPORT */ /* reserved for futur use */
18106+ {Opt_xinodir, "xinodir=%s"},
18107+ {Opt_xinodir, "xinodir:%s"},
18108+#endif
18109+ {Opt_noxino, "noxino"},
18110+ {Opt_trunc_xino, "trunc_xino"},
18111+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
18112+ {Opt_notrunc_xino, "notrunc_xino"},
18113+ {Opt_trunc_xino_path, "trunc_xino=%s"},
18114+ {Opt_trunc_xino_path, "trunc_xino:%s"},
18115+ {Opt_itrunc_xino, "itrunc_xino=%d"},
18116+ {Opt_itrunc_xino, "itrunc_xino:%d"},
18117+ /* {Opt_zxino, "zxino=%s"}, */
18118+ {Opt_trunc_xib, "trunc_xib"},
18119+ {Opt_notrunc_xib, "notrunc_xib"},
18120+
18121+ {Opt_plink, "plink"},
18122+ {Opt_noplink, "noplink"},
18123+#ifdef CONFIG_AUFS_DEBUG
18124+ {Opt_list_plink, "list_plink"},
18125+#endif
18126+ {Opt_clean_plink, "clean_plink"},
18127+
18128+ {Opt_udba, "udba=%s"},
18129+
18130+ {Opt_diropq_a, "diropq=always"},
18131+ {Opt_diropq_a, "diropq=a"},
18132+ {Opt_diropq_w, "diropq=whiteouted"},
18133+ {Opt_diropq_w, "diropq=w"},
18134+
18135+ {Opt_warn_perm, "warn_perm"},
18136+ {Opt_nowarn_perm, "nowarn_perm"},
18137+
18138+#ifdef CONFIG_AUFS_DLGT
18139+ {Opt_dlgt, "dlgt"},
18140+ {Opt_dirperm1, "dirperm1"},
18141+#endif
18142+ {Opt_nodlgt, "nodlgt"},
18143+ {Opt_nodirperm1, "nodirperm1"},
18144+
18145+#ifdef CONFIG_AUFS_SHWH
18146+ {Opt_shwh, "shwh"},
18147+#endif
18148+ {Opt_noshwh, "noshwh"},
18149+
18150+ {Opt_rendir, "rendir=%d"},
18151+ {Opt_rendir, "rendir:%d"},
18152+
18153+ {Opt_refrof, "refrof"},
18154+ {Opt_norefrof, "norefrof"},
18155+
18156+ {Opt_verbose, "verbose"},
18157+ {Opt_verbose, "v"},
18158+ {Opt_noverbose, "noverbose"},
18159+ {Opt_noverbose, "quiet"},
18160+ {Opt_noverbose, "q"},
18161+ {Opt_noverbose, "silent"},
18162+
18163+ {Opt_sum, "sum"},
18164+ {Opt_nosum, "nosum"},
18165+ {Opt_wsum, "wsum"},
18166+
18167+ {Opt_rdcache, "rdcache=%d"},
18168+ {Opt_rdcache, "rdcache:%d"},
18169+
18170+ {Opt_coo, "coo=%s"},
18171+
18172+ {Opt_wbr_create, "create=%s"},
18173+ {Opt_wbr_create, "create:%s"},
18174+ {Opt_wbr_create, "create_policy=%s"},
18175+ {Opt_wbr_create, "create_policy:%s"},
18176+ {Opt_wbr_copyup, "cpup=%s"},
18177+ {Opt_wbr_copyup, "cpup:%s"},
18178+ {Opt_wbr_copyup, "copyup=%s"},
18179+ {Opt_wbr_copyup, "copyup:%s"},
18180+ {Opt_wbr_copyup, "copyup_policy=%s"},
18181+ {Opt_wbr_copyup, "copyup_policy:%s"},
18182+
18183+ /* internal use for the scripts */
18184+ {Opt_ignore_silent, "si=%s"},
18185+
18186+#if 0 /* reserved for future use */
18187+ {Opt_deblk, "deblk=%d"},
18188+ {Opt_deblk, "deblk:%d"},
18189+ {Opt_nhash, "nhash=%d"},
18190+ {Opt_nhash, "nhash:%d"},
18191+#endif
18192+
18193+ {Opt_br, "dirs=%s"},
18194+ {Opt_ignore, "debug=%d"},
18195+ {Opt_ignore, "delete=whiteout"},
18196+ {Opt_ignore, "delete=all"},
18197+ {Opt_ignore, "imap=%s"},
18198+
18199+ {Opt_err, NULL}
18200+};
18201+
18202+/* ---------------------------------------------------------------------- */
18203+
18204+static const char *au_parser_pattern(int val, struct match_token *token)
18205+{
18206+ while (token->pattern) {
18207+ if (token->token == val)
18208+ return token->pattern;
18209+ token++;
18210+ }
18211+ BUG();
18212+ return "??";
18213+}
18214+
18215+/* ---------------------------------------------------------------------- */
18216+
18217+#define RW "rw"
18218+#define RO "ro"
18219+#define WH "wh"
18220+#define RR "rr"
18221+#define NoLinkWH "nolwh"
18222+
18223+static match_table_t brperms = {
18224+ {AuBrPerm_RR, RR},
18225+ {AuBrPerm_RO, RO},
18226+ {AuBrPerm_RW, RW},
18227+
18228+ {AuBrPerm_RRWH, RR "+" WH},
18229+ {AuBrPerm_ROWH, RO "+" WH},
18230+ {AuBrPerm_RWNoLinkWH, RW "+" NoLinkWH},
18231+
18232+ {AuBrPerm_ROWH, "nfsro"},
18233+ {AuBrPerm_RO, NULL}
18234+};
18235+
18236+static noinline_for_stack int br_perm_val(char *perm)
18237+{
18238+ int val;
18239+ substring_t args[MAX_OPT_ARGS];
18240+
18241+ AuDebugOn(!perm || !*perm);
18242+ LKTRTrace("perm %s\n", perm);
18243+ val = match_token(perm, brperms, args);
18244+ AuTraceErr(val);
18245+ return val;
18246+}
18247+
18248+const char *au_optstr_br_perm(int brperm)
18249+{
18250+ return au_parser_pattern(brperm, (void *)brperms);
18251+}
18252+
18253+/* ---------------------------------------------------------------------- */
18254+
18255+static match_table_t udbalevel = {
18256+ {AuOpt_UDBA_REVAL, "reval"},
18257+#ifdef CONFIG_AUFS_HINOTIFY
18258+ {AuOpt_UDBA_INOTIFY, "inotify"},
18259+#endif
18260+ {AuOpt_UDBA_NONE, "none"},
18261+ {-1, NULL}
18262+};
18263+
18264+static noinline_for_stack int udba_val(char *str)
18265+{
18266+ substring_t args[MAX_OPT_ARGS];
18267+ return match_token(str, udbalevel, args);
18268+}
18269+
18270+const char *au_optstr_udba(int udba)
18271+{
18272+ return au_parser_pattern(udba, (void *)udbalevel);
18273+}
18274+
18275+/* ---------------------------------------------------------------------- */
18276+
18277+static match_table_t coolevel = {
18278+ {AuOpt_COO_NONE, "none"},
18279+ {AuOpt_COO_LEAF, "leaf"},
18280+ {AuOpt_COO_ALL, "all"},
18281+ {-1, NULL}
18282+};
18283+
18284+static noinline_for_stack int coo_val(char *str)
18285+{
18286+ substring_t args[MAX_OPT_ARGS];
18287+ return match_token(str, coolevel, args);
18288+}
18289+
18290+const char *au_optstr_coo(int coo)
18291+{
18292+ return au_parser_pattern(coo, (void *)coolevel);
18293+}
18294+
18295+/* ---------------------------------------------------------------------- */
18296+
18297+static match_table_t au_wbr_create_policy = {
18298+ {AuWbrCreate_TDP, "tdp"},
18299+ {AuWbrCreate_TDP, "top-down-parent"},
18300+ {AuWbrCreate_RR, "rr"},
18301+ {AuWbrCreate_RR, "round-robin"},
18302+ {AuWbrCreate_MFS, "mfs"},
18303+ {AuWbrCreate_MFS, "most-free-space"},
18304+ {AuWbrCreate_MFSV, "mfs:%d"},
18305+ {AuWbrCreate_MFSV, "most-free-space:%d"},
18306+
18307+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
18308+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
18309+ {AuWbrCreate_PMFS, "pmfs"},
18310+ {AuWbrCreate_PMFSV, "pmfs:%d"},
18311+
18312+ {-1, NULL}
18313+};
18314+
18315+/* cf. linux/lib/parser.c */
18316+static int au_match_ull(substring_t *s, unsigned long long *result)
18317+{
18318+ int err;
18319+ unsigned int len;
18320+ char a[32];
18321+
18322+ err = -ERANGE;
18323+ len = s->to - s->from;
18324+ if (len + 1 <= sizeof(a)) {
18325+ memcpy(a, s->from, len);
18326+ a[len] = '\0';
18327+#if 1
18328+ err = strict_strtoull(a, 0, result);
18329+#else
18330+ char *next;
18331+ *result = memparse(a, &next);
18332+ err = *result;
18333+ if (!IS_ERR((void *)err))
18334+ err = 0;
18335+#endif
18336+ }
18337+ return err;
18338+}
18339+
18340+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
18341+ struct au_opt_wbr_create *create)
18342+{
18343+ int err;
18344+ unsigned long long ull;
18345+
18346+ err = 0;
18347+ if (!au_match_ull(arg, &ull))
18348+ create->mfsrr_watermark = ull;
18349+ else {
18350+ AuErr("bad integer in %s\n", str);
18351+ err = -EINVAL;
18352+ }
18353+
18354+ AuTraceErr(err);
18355+ return err;
18356+}
18357+
18358+static int au_wbr_mfs_sec(substring_t *arg, char *str,
18359+ struct au_opt_wbr_create *create)
18360+{
18361+ int n, err;
18362+
18363+ err = 0;
18364+ if (!match_int(arg, &n) && 0 <= n)
18365+ create->mfs_second = n;
18366+ else {
18367+ AuErr("bad integer in %s\n", str);
18368+ err = -EINVAL;
18369+ }
18370+
18371+ AuTraceErr(err);
18372+ return err;
18373+}
18374+
18375+static noinline_for_stack
18376+int au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
18377+{
18378+ int err, e;
18379+ substring_t args[MAX_OPT_ARGS];
18380+
18381+ err = match_token(str, au_wbr_create_policy, args);
18382+ create->wbr_create = err;
18383+ switch (err) {
18384+ case AuWbrCreate_MFSRRV:
18385+ e = au_wbr_mfs_wmark(&args[0], str, create);
18386+ if (!e)
18387+ e = au_wbr_mfs_sec(&args[1], str, create);
18388+ if (unlikely(e))
18389+ err = e;
18390+ break;
18391+ case AuWbrCreate_MFSRR:
18392+ e = au_wbr_mfs_wmark(&args[0], str, create);
18393+ if (unlikely(e)) {
18394+ err = e;
18395+ break;
18396+ }
18397+ /*FALLTHROUGH*/
18398+ case AuWbrCreate_MFS:
18399+ case AuWbrCreate_PMFS:
18400+ create->mfs_second = AUFS_MFS_SECOND_DEF;
18401+ break;
18402+ case AuWbrCreate_MFSV:
18403+ case AuWbrCreate_PMFSV:
18404+ e = au_wbr_mfs_sec(&args[0], str, create);
18405+ if (unlikely(e))
18406+ err = e;
18407+ break;
18408+ }
18409+
18410+ return err;
18411+}
18412+
18413+const char *au_optstr_wbr_create(int wbr_create)
18414+{
18415+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
18416+}
18417+
18418+static match_table_t au_wbr_copyup_policy = {
18419+ {AuWbrCopyup_TDP, "tdp"},
18420+ {AuWbrCopyup_TDP, "top-down-parent"},
18421+ {AuWbrCopyup_BUP, "bup"},
18422+ {AuWbrCopyup_BUP, "bottom-up-parent"},
18423+ {AuWbrCopyup_BU, "bu"},
18424+ {AuWbrCopyup_BU, "bottom-up"},
18425+ {-1, NULL}
18426+};
18427+
18428+static noinline_for_stack int au_wbr_copyup_val(char *str)
18429+{
18430+ substring_t args[MAX_OPT_ARGS];
18431+ return match_token(str, au_wbr_copyup_policy, args);
18432+}
18433+
18434+const char *au_optstr_wbr_copyup(int wbr_copyup)
18435+{
18436+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
18437+}
18438+
18439+/* ---------------------------------------------------------------------- */
18440+
18441+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
18442+
18443+static void dump_opts(struct au_opts *opts)
18444+{
18445+#ifdef CONFIG_AUFS_DEBUG
18446+ /* reduce stack space */
18447+ union {
18448+ struct au_opt_add *add;
18449+ struct au_opt_del *del;
18450+ struct au_opt_mod *mod;
18451+ struct au_opt_xino *xino;
18452+ struct au_opt_xinodir *xinodir;
18453+ struct au_opt_xino_itrunc *xino_itrunc;
18454+ struct au_opt_wbr_create *create;
18455+ } u;
18456+ struct au_opt *opt;
18457+
18458+ AuTraceEnter();
18459+
18460+ opt = opts->opt;
18461+ while (/* opt < opts_tail && */ opt->type != Opt_tail) {
18462+ switch (opt->type) {
18463+ case Opt_add:
18464+ u.add = &opt->add;
18465+ LKTRTrace("add {b%d, %s, 0x%x, %p}\n",
18466+ u.add->bindex, u.add->path, u.add->perm,
18467+ u.add->nd.path.dentry);
18468+ break;
18469+ case Opt_del:
18470+ case Opt_idel:
18471+ u.del = &opt->del;
18472+ LKTRTrace("del {%s, %p}\n", u.del->path, u.del->h_root);
18473+ break;
18474+ case Opt_mod:
18475+ case Opt_imod:
18476+ u.mod = &opt->mod;
18477+ LKTRTrace("mod {%s, 0x%x, %p}\n",
18478+ u.mod->path, u.mod->perm, u.mod->h_root);
18479+ break;
18480+ case Opt_append:
18481+ u.add = &opt->add;
18482+ LKTRTrace("append {b%d, %s, 0x%x, %p}\n",
18483+ u.add->bindex, u.add->path, u.add->perm,
18484+ u.add->nd.path.dentry);
18485+ break;
18486+ case Opt_prepend:
18487+ u.add = &opt->add;
18488+ LKTRTrace("prepend {b%d, %s, 0x%x, %p}\n",
18489+ u.add->bindex, u.add->path, u.add->perm,
18490+ u.add->nd.path.dentry);
18491+ break;
18492+ case Opt_dirwh:
18493+ LKTRTrace("dirwh %d\n", opt->dirwh);
18494+ break;
18495+ case Opt_rdcache:
18496+ LKTRTrace("rdcache %d\n", opt->rdcache);
18497+ break;
18498+ case Opt_xino:
18499+ u.xino = &opt->xino;
18500+ LKTRTrace("xino {%s %.*s}\n",
18501+ u.xino->path,
18502+ AuDLNPair(u.xino->file->f_dentry));
18503+ break;
18504+ case Opt_xinodir:
18505+ u.xinodir = &opt->xinodir;
18506+ LKTRTrace("xinodir {%s %.*s}\n",
18507+ u.xinodir->name,
18508+ AuDLNPair(u.xinodir->path.dentry));
18509+ break;
18510+ case Opt_trunc_xino:
18511+ LKTRLabel(trunc_xino);
18512+ break;
18513+ case Opt_notrunc_xino:
18514+ LKTRLabel(notrunc_xino);
18515+ break;
18516+ case Opt_trunc_xino_path:
18517+ case Opt_itrunc_xino:
18518+ u.xino_itrunc = &opt->xino_itrunc;
18519+ LKTRTrace("trunc_xino %d\n", u.xino_itrunc->bindex);
18520+ break;
18521+
18522+ case Opt_noxino:
18523+ LKTRLabel(noxino);
18524+ break;
18525+ case Opt_trunc_xib:
18526+ LKTRLabel(trunc_xib);
18527+ break;
18528+ case Opt_notrunc_xib:
18529+ LKTRLabel(notrunc_xib);
18530+ break;
18531+ case Opt_dirperm1:
18532+ LKTRLabel(dirperm1);
18533+ break;
18534+ case Opt_nodirperm1:
18535+ LKTRLabel(nodirperm1);
18536+ break;
18537+ case Opt_shwh:
18538+ LKTRLabel(shwh);
18539+ break;
18540+ case Opt_noshwh:
18541+ LKTRLabel(noshwh);
18542+ break;
18543+ case Opt_plink:
18544+ LKTRLabel(plink);
18545+ break;
18546+ case Opt_noplink:
18547+ LKTRLabel(noplink);
18548+ break;
18549+ case Opt_list_plink:
18550+ LKTRLabel(list_plink);
18551+ break;
18552+ case Opt_clean_plink:
18553+ LKTRLabel(clean_plink);
18554+ break;
18555+ case Opt_udba:
18556+ LKTRTrace("udba %d, %s\n",
18557+ opt->udba, au_optstr_udba(opt->udba));
18558+ break;
18559+ case Opt_diropq_a:
18560+ LKTRLabel(diropq_a);
18561+ break;
18562+ case Opt_diropq_w:
18563+ LKTRLabel(diropq_w);
18564+ break;
18565+ case Opt_warn_perm:
18566+ LKTRLabel(warn_perm);
18567+ break;
18568+ case Opt_nowarn_perm:
18569+ LKTRLabel(nowarn_perm);
18570+ break;
18571+ case Opt_dlgt:
18572+ LKTRLabel(dlgt);
18573+ break;
18574+ case Opt_nodlgt:
18575+ LKTRLabel(nodlgt);
18576+ break;
18577+ case Opt_refrof:
18578+ LKTRLabel(refrof);
18579+ break;
18580+ case Opt_norefrof:
18581+ LKTRLabel(norefrof);
18582+ break;
18583+ case Opt_verbose:
18584+ LKTRLabel(verbose);
18585+ break;
18586+ case Opt_noverbose:
18587+ LKTRLabel(noverbose);
18588+ break;
18589+ case Opt_sum:
18590+ LKTRLabel(sum);
18591+ break;
18592+ case Opt_nosum:
18593+ LKTRLabel(nosum);
18594+ break;
18595+ case Opt_wsum:
18596+ LKTRLabel(wsum);
18597+ break;
18598+ case Opt_coo:
18599+ LKTRTrace("coo %d, %s\n",
18600+ opt->coo, au_optstr_coo(opt->coo));
18601+ break;
18602+ case Opt_wbr_create:
18603+ u.create = &opt->wbr_create;
18604+ LKTRTrace("create %d, %s\n", u.create->wbr_create,
18605+ au_optstr_wbr_create(u.create->wbr_create));
18606+ switch (u.create->wbr_create) {
18607+ case AuWbrCreate_MFSV:
18608+ case AuWbrCreate_PMFSV:
18609+ LKTRTrace("%d sec\n", u.create->mfs_second);
18610+ break;
18611+ case AuWbrCreate_MFSRR:
18612+ LKTRTrace("%llu watermark\n",
18613+ u.create->mfsrr_watermark);
18614+ break;
18615+ case AuWbrCreate_MFSRRV:
18616+ LKTRTrace("%llu watermark, %d sec\n",
18617+ u.create->mfsrr_watermark,
18618+ u.create->mfs_second);
18619+ break;
18620+ }
18621+ break;
18622+ case Opt_wbr_copyup:
18623+ LKTRTrace("copyup %d, %s\n", opt->wbr_copyup,
18624+ au_optstr_wbr_copyup(opt->wbr_copyup));
18625+ break;
18626+ default:
18627+ BUG();
18628+ }
18629+ opt++;
18630+ }
18631+#endif
18632+}
18633+
18634+void au_opts_free(struct au_opts *opts)
18635+{
18636+ struct au_opt *opt;
18637+
18638+ AuTraceEnter();
18639+
18640+ opt = opts->opt;
18641+ while (opt->type != Opt_tail) {
18642+ switch (opt->type) {
18643+ case Opt_add:
18644+ case Opt_append:
18645+ case Opt_prepend:
18646+ path_put(&opt->add.nd.path);
18647+ break;
18648+ case Opt_del:
18649+ case Opt_idel:
18650+ dput(opt->del.h_root);
18651+ break;
18652+ case Opt_mod:
18653+ case Opt_imod:
18654+ dput(opt->mod.h_root);
18655+ break;
18656+ case Opt_xino:
18657+ fput(opt->xino.file);
18658+ break;
18659+ case Opt_xinodir:
18660+ path_put(&opt->xinodir.path);
18661+ break;
18662+ }
18663+ opt++;
18664+ }
18665+}
18666+
18667+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
18668+ struct super_block *sb, aufs_bindex_t bindex)
18669+{
18670+ int err;
18671+ struct au_opt_add *add = &opt->add;
18672+ char *p;
18673+
18674+ LKTRTrace("%s, b%d\n", opt_str, bindex);
18675+
18676+ add->bindex = bindex;
18677+ add->perm = AuBrPerm_Last;
18678+ add->path = opt_str;
18679+ p = strchr(opt_str, '=');
18680+ if (p) {
18681+ *p++ = 0;
18682+ if (*p)
18683+ add->perm = br_perm_val(p);
18684+ }
18685+
18686+ /* LSM may detect it */
18687+ /* do not superio. */
18688+ err = vfsub_path_lookup(add->path, lkup_dirflags, &add->nd);
18689+ if (!err) {
18690+ if (!p /* && add->perm == AuBrPerm_Last */) {
18691+ add->perm = AuBrPerm_RO;
18692+ if (au_test_def_rr(add->nd.path.dentry->d_sb))
18693+ add->perm = AuBrPerm_RR;
18694+ if (!bindex && !(sb_flags & MS_RDONLY))
18695+ add->perm = AuBrPerm_RW;
18696+#ifdef CONFIG_AUFS_COMPAT
18697+ add->perm = AuBrPerm_RW;
18698+#endif
18699+ }
18700+ opt->type = Opt_add;
18701+ goto out;
18702+ }
18703+ AuErr("lookup failed %s (%d)\n", add->path, err);
18704+ err = -EINVAL;
18705+
18706+ out:
18707+ AuTraceErr(err);
18708+ return err;
18709+}
18710+
18711+/* called without aufs lock */
18712+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
18713+{
18714+ int err, n, token;
18715+ struct dentry *root;
18716+ struct au_opt *opt, *opt_tail;
18717+ char *opt_str, *p;
18718+ aufs_bindex_t bindex, bend;
18719+ unsigned char skipped;
18720+ union {
18721+ struct au_opt_del *del;
18722+ struct au_opt_mod *mod;
18723+ struct au_opt_xino *xino;
18724+ struct au_opt_xinodir *xinodir;
18725+ struct au_opt_xino_itrunc *xino_itrunc;
18726+ struct au_opt_wbr_create *create;
18727+ } u;
18728+ struct file *file;
18729+ /* reduce the stack space */
18730+ struct {
18731+ substring_t args[MAX_OPT_ARGS];
18732+ struct nameidata nd;
18733+ } *a;
18734+
18735+ LKTRTrace("%s, nopts %d\n", str, opts->max_opt);
18736+
18737+ err = -ENOMEM;
18738+ a = kmalloc(sizeof(*a), GFP_NOFS);
18739+ if (unlikely(!a))
18740+ goto out;
18741+
18742+ root = sb->s_root;
18743+ err = 0;
18744+ bindex = 0;
18745+ opt = opts->opt;
18746+ opt_tail = opt + opts->max_opt - 1;
18747+ opt->type = Opt_tail;
18748+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
18749+ err = -EINVAL;
18750+ token = match_token(opt_str, options, a->args);
18751+ LKTRTrace("%s, token %d, a->args[0]{%p, %p}\n",
18752+ opt_str, token, a->args[0].from, a->args[0].to);
18753+
18754+ skipped = 0;
18755+ switch (token) {
18756+ case Opt_br:
18757+ err = 0;
18758+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
18759+ && *opt_str) {
18760+ err = opt_add(opt, opt_str, opts->sb_flags, sb,
18761+ bindex++);
18762+ if (unlikely(!err && ++opt > opt_tail)) {
18763+ err = -E2BIG;
18764+ break;
18765+ }
18766+ opt->type = Opt_tail;
18767+ skipped = 1;
18768+ }
18769+ break;
18770+ case Opt_add:
18771+ if (unlikely(match_int(&a->args[0], &n))) {
18772+ AuErr("bad integer in %s\n", opt_str);
18773+ break;
18774+ }
18775+ bindex = n;
18776+ err = opt_add(opt, a->args[1].from, opts->sb_flags, sb,
18777+ bindex);
18778+ break;
18779+ case Opt_append:
18780+ err = opt_add(opt, a->args[0].from, opts->sb_flags, sb,
18781+ /*dummy bindex*/1);
18782+ if (!err)
18783+ opt->type = token;
18784+ break;
18785+ case Opt_prepend:
18786+ err = opt_add(opt, a->args[0].from, opts->sb_flags, sb,
18787+ /*bindex*/0);
18788+ if (!err)
18789+ opt->type = token;
18790+ break;
18791+ case Opt_del:
18792+ u.del = &opt->del;
18793+ u.del->path = a->args[0].from;
18794+ LKTRTrace("del path %s\n", u.del->path);
18795+ /* LSM may detect it */
18796+ /* do not superio. */
18797+ err = vfsub_path_lookup(u.del->path, lkup_dirflags,
18798+ &a->nd);
18799+ if (unlikely(err)) {
18800+ AuErr("lookup failed %s (%d)\n",
18801+ u.del->path, err);
18802+ break;
18803+ }
18804+ u.del->h_root = dget(a->nd.path.dentry);
18805+ path_put(&a->nd.path);
18806+ opt->type = token;
18807+ break;
18808+#if 0 /* reserved for future use */
18809+ case Opt_idel:
18810+ u.del = &opt->del;
18811+ u.del->path = "(indexed)";
18812+ if (unlikely(match_int(&a->args[0], &n))) {
18813+ AuErr("bad integer in %s\n", opt_str);
18814+ break;
18815+ }
18816+ bindex = n;
18817+ aufs_read_lock(root, AuLock_FLUSH);
18818+ if (bindex < 0 || au_sbend(sb) < bindex) {
18819+ AuErr("out of bounds, %d\n", bindex);
18820+ aufs_read_unlock(root, !AuLock_IR);
18821+ break;
18822+ }
18823+ err = 0;
18824+ u.del->h_root = dget(au_h_dptr(root, bindex));
18825+ opt->type = token;
18826+ aufs_read_unlock(root, !AuLock_IR);
18827+ break;
18828+#endif
18829+ case Opt_mod:
18830+ u.mod = &opt->mod;
18831+ u.mod->path = a->args[0].from;
18832+ p = strchr(u.mod->path, '=');
18833+ if (unlikely(!p)) {
18834+ AuErr("no permssion %s\n", opt_str);
18835+ break;
18836+ }
18837+ *p++ = 0;
18838+ u.mod->perm = br_perm_val(p);
18839+ LKTRTrace("mod path %s, perm 0x%x, %s\n",
18840+ u.mod->path, u.mod->perm, p);
18841+ /* LSM may detect it */
18842+ /* do not superio. */
18843+ err = vfsub_path_lookup(u.mod->path, lkup_dirflags,
18844+ &a->nd);
18845+ if (unlikely(err)) {
18846+ AuErr("lookup failed %s (%d)\n",
18847+ u.mod->path, err);
18848+ break;
18849+ }
18850+ u.mod->h_root = dget(a->nd.path.dentry);
18851+ path_put(&a->nd.path);
18852+ opt->type = token;
18853+ break;
18854+#ifdef IMOD /* reserved for future use */
18855+ case Opt_imod:
18856+ u.mod = &opt->mod;
18857+ u.mod->path = "(indexed)";
18858+ if (unlikely(match_int(&a->args[0], &n))) {
18859+ AuErr("bad integer in %s\n", opt_str);
18860+ break;
18861+ }
18862+ bindex = n;
18863+ aufs_read_lock(root, AuLock_FLUSH);
18864+ if (bindex < 0 || au_sbend(sb) < bindex) {
18865+ AuErr("out of bounds, %d\n", bindex);
18866+ aufs_read_unlock(root, !AuLock_IR);
18867+ break;
18868+ }
18869+ u.mod->perm = br_perm_val(a->args[1].from);
18870+ LKTRTrace("mod path %s, perm 0x%x, %s\n",
18871+ u.mod->path, u.mod->perm, a->args[1].from);
18872+ err = 0;
18873+ u.mod->h_root = dget(au_h_dptr(root, bindex));
18874+ opt->type = token;
18875+ aufs_read_unlock(root, !AuLock_IR);
18876+ break;
18877+#endif
18878+ case Opt_xino:
18879+ u.xino = &opt->xino;
18880+ file = au_xino_create(sb, a->args[0].from, /*silent*/0);
18881+ err = PTR_ERR(file);
18882+ if (IS_ERR(file))
18883+ break;
18884+ err = -EINVAL;
18885+ if (unlikely(file->f_dentry->d_sb == sb)) {
18886+ fput(file);
18887+ AuErr("%s must be outside\n", a->args[0].from);
18888+ break;
18889+ }
18890+ err = 0;
18891+ u.xino->file = file;
18892+ u.xino->path = a->args[0].from;
18893+ opt->type = token;
18894+ break;
18895+
18896+#if 0 /* def CONFIG_AUFS_EXPORT */ /* reserved for futur use */
18897+ case Opt_xinodir:
18898+ u.xinodir = &opt->xinodir;
18899+ u.xinodir->name = a->args[0].from;
18900+ err = vfsub_path_lookup(u.xinodir->name, lkup_dirflags,
18901+ &a->nd);
18902+ if (unlikely(err)) {
18903+ AuErr("lookup failed %s (%d)\n",
18904+ u.xinodir->name, err);
18905+ break;
18906+ }
18907+ u.xinodir->path = a->nd.path;
18908+ /* do not path_put() */
18909+ opt->type = token;
18910+ break;
18911+#endif
18912+
18913+ case Opt_trunc_xino_path:
18914+ u.xino_itrunc = &opt->xino_itrunc;
18915+ p = a->args[0].from;
18916+ LKTRTrace("trunc_xino path %s\n", p);
18917+ /* LSM may detect it */
18918+ /* do not superio. */
18919+ err = vfsub_path_lookup(p, lkup_dirflags, &a->nd);
18920+ if (unlikely(err)) {
18921+ AuErr("lookup failed %s (%d)\n", p , err);
18922+ break;
18923+ }
18924+ u.xino_itrunc->bindex = -1;
18925+ aufs_read_lock(root, AuLock_FLUSH);
18926+ bend = au_sbend(sb);
18927+ for (bindex = 0; bindex <= bend; bindex++) {
18928+ if (au_h_dptr(root, bindex)
18929+ == a->nd.path.dentry) {
18930+ u.xino_itrunc->bindex = bindex;
18931+ break;
18932+ }
18933+ }
18934+ aufs_read_unlock(root, !AuLock_IR);
18935+ path_put(&a->nd.path);
18936+ if (unlikely(u.xino_itrunc->bindex < 0)) {
18937+ AuErr("no such branch %s\n", p);
18938+ err = -EINVAL;
18939+ break;
18940+ }
18941+ opt->type = token;
18942+ break;
18943+
18944+ case Opt_itrunc_xino:
18945+ u.xino_itrunc = &opt->xino_itrunc;
18946+ if (unlikely(match_int(&a->args[0], &n))) {
18947+ AuErr("bad integer in %s\n", opt_str);
18948+ break;
18949+ }
18950+ u.xino_itrunc->bindex = n;
18951+ aufs_read_lock(root, AuLock_FLUSH);
18952+ if (n < 0 || au_sbend(sb) < n) {
18953+ AuErr("out of bounds, %d\n", n);
18954+ aufs_read_unlock(root, !AuLock_IR);
18955+ break;
18956+ }
18957+ aufs_read_unlock(root, !AuLock_IR);
18958+ err = 0;
18959+ opt->type = token;
18960+ break;
18961+
18962+ case Opt_dirwh:
18963+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
18964+ break;
18965+ err = 0;
18966+ opt->type = token;
18967+ break;
18968+
18969+ case Opt_rdcache:
18970+ if (unlikely(match_int(&a->args[0], &opt->rdcache)))
18971+ break;
18972+ err = 0;
18973+ opt->type = token;
18974+ break;
18975+
18976+ case Opt_shwh:
18977+ if (opts->sb_flags & MS_RDONLY) {
18978+ err = 0;
18979+ opt->type = token;
18980+ } else
18981+ AuErr("shwh requires ro\n");
18982+ break;
18983+
18984+ case Opt_trunc_xino:
18985+ case Opt_notrunc_xino:
18986+ case Opt_noxino:
18987+ case Opt_trunc_xib:
18988+ case Opt_notrunc_xib:
18989+ case Opt_dirperm1:
18990+ case Opt_nodirperm1:
18991+ case Opt_noshwh:
18992+ case Opt_plink:
18993+ case Opt_noplink:
18994+ case Opt_list_plink:
18995+ case Opt_clean_plink:
18996+ case Opt_diropq_a:
18997+ case Opt_diropq_w:
18998+ case Opt_warn_perm:
18999+ case Opt_nowarn_perm:
19000+ case Opt_dlgt:
19001+ case Opt_nodlgt:
19002+ case Opt_refrof:
19003+ case Opt_norefrof:
19004+ case Opt_verbose:
19005+ case Opt_noverbose:
19006+ case Opt_sum:
19007+ case Opt_nosum:
19008+ case Opt_wsum:
19009+ err = 0;
19010+ opt->type = token;
19011+ break;
19012+
19013+ case Opt_udba:
19014+ opt->udba = udba_val(a->args[0].from);
19015+ if (opt->udba >= 0) {
19016+ err = 0;
19017+ opt->type = token;
19018+ } else
19019+ AuErr("wrong value, %s\n", opt_str);
19020+ break;
19021+
19022+ case Opt_wbr_create:
19023+ u.create = &opt->wbr_create;
19024+ u.create->wbr_create
19025+ = au_wbr_create_val(a->args[0].from, u.create);
19026+ if (u.create->wbr_create >= 0) {
19027+ err = 0;
19028+ opt->type = token;
19029+ } else
19030+ AuErr("wrong value, %s\n", opt_str);
19031+ break;
19032+ case Opt_wbr_copyup:
19033+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
19034+ if (opt->wbr_copyup >= 0) {
19035+ err = 0;
19036+ opt->type = token;
19037+ } else
19038+ AuErr("wrong value, %s\n", opt_str);
19039+ break;
19040+
19041+ case Opt_coo:
19042+ opt->coo = coo_val(a->args[0].from);
19043+ if (opt->coo >= 0) {
19044+ if (opt->coo == AuOpt_COO_NONE
19045+ || !(opts->sb_flags & MS_RDONLY)) {
19046+ err = 0;
19047+ opt->type = token;
19048+ } else
19049+ AuErr("bad %s for readonly mount\n",
19050+ opt_str);
19051+ } else
19052+ AuErr("wrong value, %s\n", opt_str);
19053+ break;
19054+
19055+ case Opt_ignore:
19056+#ifndef CONFIG_AUFS_COMPAT
19057+ AuWarn("ignored %s\n", opt_str);
19058+#endif
19059+ case Opt_ignore_silent:
19060+ skipped = 1;
19061+ err = 0;
19062+ break;
19063+ case Opt_err:
19064+ AuErr("unknown option %s\n", opt_str);
19065+ break;
19066+ }
19067+
19068+ if (!err && !skipped) {
19069+ if (unlikely(++opt > opt_tail)) {
19070+ err = -E2BIG;
19071+ opt--;
19072+ opt->type = Opt_tail;
19073+ break;
19074+ }
19075+ opt->type = Opt_tail;
19076+ }
19077+ }
19078+
19079+ kfree(a);
19080+ dump_opts(opts);
19081+ if (unlikely(err))
19082+ au_opts_free(opts);
19083+
19084+ out:
19085+ AuTraceErr(err);
19086+ return err;
19087+}
19088+
19089+/*
19090+ * returns,
19091+ * plus: processed without an error
19092+ * zero: unprocessed
19093+ */
19094+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
19095+ struct au_opts *opts)
19096+{
19097+ int err;
19098+ struct au_sbinfo *sbinfo;
19099+ struct au_opt_wbr_create *create;
19100+
19101+ AuTraceEnter();
19102+
19103+ err = 1; /* handled */
19104+ sbinfo = au_sbi(sb);
19105+ switch (opt->type) {
19106+ case Opt_udba:
19107+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
19108+ sbinfo->si_mntflags |= opt->udba;
19109+ opts->given_udba |= opt->udba;
19110+ break;
19111+
19112+ case Opt_plink:
19113+ au_opt_set(sbinfo->si_mntflags, PLINK);
19114+ break;
19115+ case Opt_noplink:
19116+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
19117+ au_plink_put(sb);
19118+ au_opt_clr(sbinfo->si_mntflags, PLINK);
19119+ break;
19120+ case Opt_list_plink:
19121+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
19122+ au_plink_list(sb);
19123+ break;
19124+ case Opt_clean_plink:
19125+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
19126+ au_plink_put(sb);
19127+ break;
19128+
19129+ case Opt_diropq_a:
19130+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
19131+ break;
19132+ case Opt_diropq_w:
19133+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
19134+ break;
19135+
19136+ case Opt_dlgt:
19137+ au_opt_set(sbinfo->si_mntflags, DLGT);
19138+ break;
19139+ case Opt_nodlgt:
19140+ au_opt_clr(sbinfo->si_mntflags, DLGT);
19141+ break;
19142+
19143+ case Opt_warn_perm:
19144+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
19145+ break;
19146+ case Opt_nowarn_perm:
19147+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
19148+ break;
19149+
19150+ case Opt_refrof:
19151+ au_opt_set(sbinfo->si_mntflags, REFROF);
19152+ break;
19153+ case Opt_norefrof:
19154+ /* au_opt_set(sbinfo->si_mntflags, COO_LEAF); */
19155+ au_opt_clr(sbinfo->si_mntflags, REFROF);
19156+ break;
19157+
19158+ case Opt_verbose:
19159+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
19160+ break;
19161+ case Opt_noverbose:
19162+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
19163+ break;
19164+
19165+ case Opt_sum:
19166+ au_opt_set(sbinfo->si_mntflags, SUM);
19167+ break;
19168+ case Opt_wsum:
19169+ au_opt_clr(sbinfo->si_mntflags, SUM);
19170+ au_opt_set(sbinfo->si_mntflags, SUM_W);
19171+ case Opt_nosum:
19172+ au_opt_clr(sbinfo->si_mntflags, SUM);
19173+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
19174+ break;
19175+
19176+ case Opt_wbr_create:
19177+ create = &opt->wbr_create;
19178+ if (sbinfo->si_wbr_create_ops->fin) {
19179+ err = sbinfo->si_wbr_create_ops->fin(sb);
19180+ if (!err)
19181+ err = 1;
19182+ }
19183+ sbinfo->si_wbr_create = create->wbr_create;
19184+ sbinfo->si_wbr_create_ops
19185+ = au_wbr_create_ops + create->wbr_create;
19186+ switch (create->wbr_create) {
19187+ case AuWbrCreate_MFSRRV:
19188+ case AuWbrCreate_MFSRR:
19189+ sbinfo->si_wbr_mfs.mfsrr_watermark
19190+ = create->mfsrr_watermark;
19191+ /*FALLTHROUGH*/
19192+ case AuWbrCreate_MFS:
19193+ case AuWbrCreate_MFSV:
19194+ case AuWbrCreate_PMFS:
19195+ case AuWbrCreate_PMFSV:
19196+ sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
19197+ break;
19198+ }
19199+ if (sbinfo->si_wbr_create_ops->init)
19200+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
19201+ break;
19202+ case Opt_wbr_copyup:
19203+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
19204+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
19205+ break;
19206+
19207+ case Opt_coo:
19208+ sbinfo->si_mntflags &= ~AuOptMask_COO;
19209+ sbinfo->si_mntflags |= opt->coo;
19210+ break;
19211+
19212+ case Opt_dirwh:
19213+ sbinfo->si_dirwh = opt->dirwh;
19214+ break;
19215+
19216+ case Opt_rdcache:
19217+ sbinfo->si_rdcache = opt->rdcache * HZ;
19218+ break;
19219+
19220+ case Opt_trunc_xino:
19221+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
19222+ break;
19223+ case Opt_notrunc_xino:
19224+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
19225+ break;
19226+
19227+ case Opt_dirperm1:
19228+ au_opt_set(sbinfo->si_mntflags, DIRPERM1);
19229+ break;
19230+ case Opt_nodirperm1:
19231+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
19232+ break;
19233+
19234+ case Opt_shwh:
19235+ au_opt_set(sbinfo->si_mntflags, SHWH);
19236+ break;
19237+ case Opt_noshwh:
19238+ au_opt_clr(sbinfo->si_mntflags, SHWH);
19239+ break;
19240+
19241+ case Opt_trunc_xino_path:
19242+ case Opt_itrunc_xino:
19243+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
19244+ if (!err)
19245+ err = 1;
19246+ break;
19247+
19248+ case Opt_trunc_xib:
19249+ au_fset_opts(opts->flags, TRUNC_XIB);
19250+ break;
19251+ case Opt_notrunc_xib:
19252+ au_fclr_opts(opts->flags, TRUNC_XIB);
19253+ break;
19254+
19255+ default:
19256+ err = 0;
19257+ break;
19258+ }
19259+
19260+ AuTraceErr(err);
19261+ return err;
19262+}
19263+
19264+/*
19265+ * returns tri-state.
19266+ * plus: processed without an error
19267+ * zero: unprocessed
19268+ * minus: error
19269+ */
19270+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
19271+ struct au_opts *opts)
19272+{
19273+ int err, do_refresh;
19274+
19275+ AuTraceEnter();
19276+
19277+ err = 0;
19278+ switch (opt->type) {
19279+ case Opt_append:
19280+ opt->add.bindex = au_sbend(sb) + 1;
19281+ if (opt->add.bindex < 0)
19282+ opt->add.bindex = 0;
19283+ goto add;
19284+ case Opt_prepend:
19285+ opt->add.bindex = 0;
19286+ add:
19287+ case Opt_add:
19288+ err = au_br_add(sb, &opt->add,
19289+ au_ftest_opts(opts->flags, REMOUNT));
19290+ if (!err) {
19291+ err = 1;
19292+ au_fset_opts(opts->flags, REFRESH_DIR);
19293+ if (au_br_whable(opt->add.perm))
19294+ au_fset_opts(opts->flags, REFRESH_NONDIR);
19295+ }
19296+ break;
19297+
19298+ case Opt_del:
19299+ case Opt_idel:
19300+ err = au_br_del(sb, &opt->del,
19301+ au_ftest_opts(opts->flags, REMOUNT));
19302+ if (!err) {
19303+ err = 1;
19304+ au_fset_opts(opts->flags, TRUNC_XIB);
19305+ au_fset_opts(opts->flags, REFRESH_DIR);
19306+ au_fset_opts(opts->flags, REFRESH_NONDIR);
19307+ }
19308+ break;
19309+
19310+ case Opt_mod:
19311+ case Opt_imod:
19312+ err = au_br_mod(sb, &opt->mod,
19313+ au_ftest_opts(opts->flags, REMOUNT),
19314+ &do_refresh);
19315+ if (!err) {
19316+ err = 1;
19317+ if (do_refresh) {
19318+ au_fset_opts(opts->flags, REFRESH_DIR);
19319+ au_fset_opts(opts->flags, REFRESH_NONDIR);
19320+ }
19321+ }
19322+ break;
19323+ }
19324+
19325+ AuTraceErr(err);
19326+ return err;
19327+}
19328+
19329+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
19330+ struct au_opt_xino **opt_xino,
19331+ struct au_opt_xinodir **opt_xinodir,
19332+ struct au_opts *opts)
19333+{
19334+ int err;
19335+ const int remount = !!au_ftest_opts(opts->flags, REMOUNT);
19336+
19337+ AuTraceEnter();
19338+
19339+ err = 0;
19340+ switch (opt->type) {
19341+ case Opt_xino:
19342+ err = au_xino_set(sb, &opt->xino, remount);
19343+ if (!err)
19344+ *opt_xino = &opt->xino;
19345+ break;
19346+#if 0 /* def CONFIG_AUFS_EXPORT */ /* reserved for futur use */
19347+ case Opt_xinodir:
19348+ err = au_xinodir_set(sb, &opt->xinodir, remount);
19349+ if (!err)
19350+ *opt_xinodir = &opt->xinodir;
19351+ break;
19352+#endif
19353+ case Opt_noxino:
19354+ au_xino_clr(sb);
19355+ *opt_xino = (void *)-1;
19356+ break;
19357+ }
19358+
19359+ AuTraceErr(err);
19360+ return err;
19361+}
19362+
19363+int verify_opts(struct super_block *sb, unsigned long sb_flags,
19364+ unsigned int pending, int remount)
19365+{
19366+ int err;
19367+ aufs_bindex_t bindex, bend;
19368+ unsigned char do_plink, skip, do_free;
19369+ struct au_branch *br;
19370+ struct au_wbr *wbr;
19371+ struct dentry *root;
19372+ struct inode *dir, *h_dir;
19373+ unsigned int mnt_flags;
19374+
19375+ AuTraceEnter();
19376+ mnt_flags = au_mntflags(sb);
19377+ AuDebugOn(!(mnt_flags & AuOptMask_COO));
19378+ AuDebugOn(!(mnt_flags & AuOptMask_UDBA));
19379+
19380+ if (!(sb_flags & MS_RDONLY)) {
19381+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
19382+ AuWarn("first branch should be rw\n");
19383+ if (unlikely(au_opt_test(mnt_flags, SHWH)))
19384+ AuWarn("shwh should be used with ro\n");
19385+ } else if (unlikely(!au_opt_test(mnt_flags, COO_NONE))) {
19386+ AuWarn("resetting coo for readonly mount\n");
19387+ au_opt_set_coo(au_sbi(sb)->si_mntflags, COO_NONE);
19388+ }
19389+
19390+ if (unlikely(au_opt_test((mnt_flags | pending), UDBA_INOTIFY)
19391+ && !au_opt_test_xino(mnt_flags)))
19392+ AuWarn("udba=inotify requires xino\n");
19393+
19394+ err = 0;
19395+ root = sb->s_root;
19396+ dir = sb->s_root->d_inode;
19397+ do_plink = !!au_opt_test(mnt_flags, PLINK);
19398+ bend = au_sbend(sb);
19399+ for (bindex = 0; !err && bindex <= bend; bindex++) {
19400+ skip = 0;
19401+ h_dir = au_h_iptr(dir, bindex);
19402+ br = au_sbr(sb, bindex);
19403+ do_free = 0;
19404+ wbr = br->br_wbr;
19405+ if (wbr)
19406+ wbr_wh_read_lock(wbr);
19407+ switch (br->br_perm) {
19408+ case AuBrPerm_RR:
19409+ case AuBrPerm_RO:
19410+ case AuBrPerm_RRWH:
19411+ case AuBrPerm_ROWH:
19412+ do_free = !!wbr;
19413+ skip = (!wbr
19414+ || (!wbr->wbr_whbase
19415+ && !wbr->wbr_plink
19416+ && !wbr->wbr_tmp));
19417+ break;
19418+
19419+ case AuBrPerm_RWNoLinkWH:
19420+ /* skip = (!br->br_whbase && !br->br_tmp); */
19421+ skip = (!wbr || !wbr->wbr_whbase);
19422+ if (skip && wbr) {
19423+ if (do_plink)
19424+ skip = !!wbr->wbr_plink;
19425+ else
19426+ skip = !wbr->wbr_plink;
19427+ }
19428+ break;
19429+
19430+ case AuBrPerm_RW:
19431+ /* skip = (br->br_whbase && br->br_tmp); */
19432+ skip = (wbr && wbr->wbr_whbase);
19433+ if (skip) {
19434+ if (do_plink)
19435+ skip = !!wbr->wbr_plink;
19436+ else
19437+ skip = !wbr->wbr_plink;
19438+ }
19439+ break;
19440+
19441+ default:
19442+ BUG();
19443+ }
19444+ if (wbr)
19445+ wbr_wh_read_unlock(wbr);
19446+
19447+ if (skip)
19448+ continue;
19449+
19450+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
19451+ if (wbr)
19452+ wbr_wh_write_lock(wbr);
19453+ err = au_wh_init(au_h_dptr(root, bindex), br, br->br_mnt, sb,
19454+ bindex);
19455+ if (wbr)
19456+ wbr_wh_write_unlock(wbr);
19457+ mutex_unlock(&h_dir->i_mutex);
19458+
19459+ if (!err && do_free) {
19460+ kfree(wbr);
19461+ br->br_wbr = NULL;
19462+ }
19463+ }
19464+
19465+ AuTraceErr(err);
19466+ return err;
19467+}
19468+
19469+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
19470+{
19471+ int err;
19472+ struct inode *dir;
19473+ struct au_opt *opt;
19474+ struct au_opt_xino *opt_xino, xino;
19475+ struct au_opt_xinodir *opt_xinodir;
19476+ aufs_bindex_t bend;
19477+ struct au_sbinfo *sbinfo;
19478+ unsigned int tmp;
19479+ struct au_branch *br;
19480+
19481+ AuTraceEnter();
19482+ SiMustWriteLock(sb);
19483+ DiMustWriteLock(sb->s_root);
19484+ dir = sb->s_root->d_inode;
19485+ IiMustWriteLock(dir);
19486+
19487+ err = 0;
19488+ opt_xino = NULL;
19489+ opt_xinodir = NULL;
19490+ opt = opts->opt;
19491+ while (err >= 0 && opt->type != Opt_tail)
19492+ err = au_opt_simple(sb, opt++, opts);
19493+ if (err > 0)
19494+ err = 0;
19495+ else if (unlikely(err < 0))
19496+ goto out;
19497+
19498+ /* disable xino, xinodir, hinotify, dlgt temporary */
19499+ sbinfo = au_sbi(sb);
19500+ tmp = sbinfo->si_mntflags;
19501+ au_opt_clr(sbinfo->si_mntflags, XINO);
19502+ au_opt_clr(sbinfo->si_mntflags, XINODIR);
19503+ au_opt_clr(sbinfo->si_mntflags, DLGT);
19504+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
19505+
19506+ opt = opts->opt;
19507+ while (err >= 0 && opt->type != Opt_tail)
19508+ err = au_opt_br(sb, opt++, opts);
19509+ if (err > 0)
19510+ err = 0;
19511+ else if (unlikely(err < 0))
19512+ goto out;
19513+
19514+ bend = au_sbend(sb);
19515+ if (unlikely(bend < 0)) {
19516+ err = -EINVAL;
19517+ AuErr("no branches\n");
19518+ goto out;
19519+ }
19520+
19521+ if (au_opt_test(tmp, XINO))
19522+ au_opt_set(sbinfo->si_mntflags, XINO);
19523+ else if (au_opt_test(tmp, XINODIR))
19524+ au_opt_set(sbinfo->si_mntflags, XINODIR);
19525+ opt = opts->opt;
19526+ while (!err && opt->type != Opt_tail)
19527+ err = au_opt_xino(sb, opt++, &opt_xino, &opt_xinodir, opts);
19528+ if (unlikely(err))
19529+ goto out;
19530+
19531+ /* todo: test this error case? */
19532+ err = verify_opts(sb, sb->s_flags, tmp, /*remount*/0);
19533+ if (unlikely(err))
19534+ goto out;
19535+
19536+ /* enable xino */
19537+ if (au_opt_test(tmp, XINO) && !opt_xino) {
19538+ xino.file = au_xino_def(sb);
19539+ err = PTR_ERR(xino.file);
19540+ if (IS_ERR(xino.file))
19541+ goto out;
19542+
19543+ br = au_xino_def_br(sbinfo);
19544+ err = au_xino_set(sb, &xino, /*remount*/0);
19545+ fput(xino.file);
19546+ if (unlikely(err))
19547+ goto out;
19548+ au_xino_def_br_set(br, sbinfo);
19549+ }
19550+
19551+ /* restore hinotify */
19552+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
19553+ sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
19554+ if (au_opt_test(tmp, UDBA_INOTIFY))
19555+ au_reset_hinotify(dir, au_hi_flags(dir, 1) & ~AuHi_XINO);
19556+
19557+ /* restore dlgt */
19558+ if (au_opt_test(tmp, DLGT))
19559+ au_opt_set(sbinfo->si_mntflags, DLGT);
19560+
19561+ out:
19562+ AuTraceErr(err);
19563+ return err;
19564+}
19565+
19566+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
19567+{
19568+ int err, rerr;
19569+ struct inode *dir;
19570+ struct au_opt_xino *opt_xino;
19571+ struct au_opt_xinodir *opt_xinodir;
19572+ struct au_opt *opt;
19573+ unsigned char dlgt;
19574+ struct au_sbinfo *sbinfo;
19575+
19576+ AuTraceEnter();
19577+ SiMustWriteLock(sb);
19578+ DiMustWriteLock(sb->s_root);
19579+ dir = sb->s_root->d_inode;
19580+ IiMustWriteLock(dir);
19581+ sbinfo = au_sbi(sb);
19582+
19583+ err = 0;
19584+ dlgt = !!au_opt_test(sbinfo->si_mntflags, DLGT);
19585+ opt_xino = NULL;
19586+ opt_xinodir = NULL;
19587+ opt = opts->opt;
19588+ while (err >= 0 && opt->type != Opt_tail) {
19589+ err = au_opt_simple(sb, opt, opts);
19590+
19591+ /* disable it temporary */
19592+ dlgt = !!au_opt_test(sbinfo->si_mntflags, DLGT);
19593+ au_opt_clr(sbinfo->si_mntflags, DLGT);
19594+
19595+ if (!err)
19596+ err = au_opt_br(sb, opt, opts);
19597+ if (!err)
19598+ err = au_opt_xino(sb, opt, &opt_xino, &opt_xinodir,
19599+ opts);
19600+
19601+ /* restore it */
19602+ if (dlgt)
19603+ au_opt_set(sbinfo->si_mntflags, DLGT);
19604+ opt++;
19605+ }
19606+ if (err > 0)
19607+ err = 0;
19608+ AuTraceErr(err);
19609+
19610+ /* go on even err */
19611+
19612+ /* todo: test this error case? */
19613+ au_opt_clr(sbinfo->si_mntflags, DLGT);
19614+ rerr = verify_opts(sb, opts->sb_flags, sbinfo->si_mntflags,
19615+ /*remount*/1);
19616+ if (unlikely(dlgt))
19617+ au_opt_set(sbinfo->si_mntflags, DLGT);
19618+ if (unlikely(rerr && !err))
19619+ err = rerr;
19620+
19621+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
19622+ rerr = au_xib_trunc(sb);
19623+ if (unlikely(rerr && !err))
19624+ err = rerr;
19625+ }
19626+
19627+ /* they are handled by the caller */
19628+ if (!au_ftest_opts(opts->flags, REFRESH_DIR)
19629+ && (opts->given_udba || au_opt_test_xino(sbinfo->si_mntflags)))
19630+ au_fset_opts(opts->flags, REFRESH_DIR);
19631+
19632+ LKTRTrace("status 0x%x\n", opts->flags);
19633+ AuTraceErr(err);
19634+ return err;
19635+}
19636diff -urN linux/fs/aufs/opts.h linux-aufs/fs/aufs/opts.h
19637--- linux/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
19638+++ linux-aufs/fs/aufs/opts.h 2009-03-12 16:18:04.000000000 +0100
19639@@ -0,0 +1,255 @@
19640+/*
19641+ * Copyright (C) 2005-2009 Junjiro Okajima
19642+ *
19643+ * This program, aufs is free software; you can redistribute it and/or modify
19644+ * it under the terms of the GNU General Public License as published by
19645+ * the Free Software Foundation; either version 2 of the License, or
19646+ * (at your option) any later version.
19647+ *
19648+ * This program is distributed in the hope that it will be useful,
19649+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19650+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19651+ * GNU General Public License for more details.
19652+ *
19653+ * You should have received a copy of the GNU General Public License
19654+ * along with this program; if not, write to the Free Software
19655+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19656+ */
19657+
19658+/*
19659+ * mount options/flags
19660+ *
19661+ * $Id$
19662+ */
19663+
19664+#ifndef __AUFS_OPTS_H__
19665+#define __AUFS_OPTS_H__
19666+
19667+#ifdef __KERNEL__
19668+
19669+#include <linux/fs.h>
19670+#include <linux/namei.h>
19671+#include <linux/aufs_type.h>
19672+#include "wkq.h"
19673+
19674+/* ---------------------------------------------------------------------- */
19675+/* mount flags */
19676+
19677+/* external inode number bitmap and translation table */
19678+#define AuOpt_XINO 1
19679+#define AuOpt_XINODIR (1 << 1)
19680+#define AuOpt_TRUNC_XINO (1 << 2)
19681+#define AuOpt_UDBA_NONE (1 << 3) /* users direct branch access */
19682+#define AuOpt_UDBA_REVAL (1 << 4)
19683+#define AuOpt_UDBA_INOTIFY (1 << 5)
19684+#define AuOpt_SHWH (1 << 6)
19685+#define AuOpt_PLINK (1 << 7)
19686+#define AuOpt_WARN_PERM (1 << 8)
19687+#define AuOpt_DIRPERM1 (1 << 9)
19688+#define AuOpt_DLGT (1 << 10)
19689+#define AuOpt_COO_NONE (1 << 11) /* copyup on open */
19690+#define AuOpt_COO_LEAF (1 << 12)
19691+#define AuOpt_COO_ALL (1 << 13)
19692+#define AuOpt_ALWAYS_DIROPQ (1 << 14)
19693+#define AuOpt_REFROF (1 << 15)
19694+#define AuOpt_VERBOSE (1 << 16)
19695+#define AuOpt_SUM (1 << 17)
19696+#define AuOpt_SUM_W (1 << 18) /* unimplemented */
19697+
19698+#if 1 /* ndef CONFIG_AUFS_EXPORT */ /* reserved for future use */
19699+#undef AuOpt_XINODIR
19700+#define AuOpt_XINODIR 0
19701+#endif
19702+#ifndef CONFIG_AUFS_HINOTIFY
19703+#undef AuOpt_UDBA_INOTIFY
19704+#define AuOpt_UDBA_INOTIFY 0
19705+#endif
19706+#ifndef CONFIG_AUFS_SHWH
19707+#undef AuOpt_SHWH
19708+#define AuOpt_SHWH 0
19709+#endif
19710+#ifndef CONFIG_AUFS_DLGT
19711+#undef AuOpt_DIRPERM1
19712+#define AuOpt_DIRPERM1 0
19713+#undef AuOpt_DLGT
19714+#define AuOpt_DLGT 0
19715+#endif
19716+
19717+/* policies to select one among multiple writable branches */
19718+enum {
19719+ AuWbrCreate_TDP, /* top down parent */
19720+ AuWbrCreate_RR, /* round robin */
19721+ AuWbrCreate_MFS, /* most free space */
19722+ AuWbrCreate_MFSV, /* mfs with seconds */
19723+ AuWbrCreate_MFSRR, /* mfs then rr */
19724+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
19725+ AuWbrCreate_PMFS, /* parent and mfs */
19726+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
19727+
19728+ AuWbrCreate_Def = AuWbrCreate_TDP
19729+};
19730+
19731+enum {
19732+ AuWbrCopyup_TDP, /* top down parent */
19733+ AuWbrCopyup_BUP, /* bottom up parent */
19734+ AuWbrCopyup_BU, /* bottom up */
19735+
19736+ AuWbrCopyup_Def = AuWbrCopyup_TDP
19737+};
19738+
19739+#define AuOptMask_COO (AuOpt_COO_NONE \
19740+ | AuOpt_COO_LEAF \
19741+ | AuOpt_COO_ALL)
19742+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
19743+ | AuOpt_UDBA_REVAL \
19744+ | AuOpt_UDBA_INOTIFY)
19745+
19746+#ifdef CONFIG_AUFS_COMPAT
19747+#define AuOpt_DefExtra1 AuOpt_ALWAYS_DIROPQ
19748+#else
19749+#define AuOpt_DefExtra1 0
19750+#endif
19751+
19752+#define AuOpt_Def (AuOpt_XINO \
19753+ | AuOpt_UDBA_REVAL \
19754+ | AuOpt_WARN_PERM \
19755+ | AuOpt_COO_NONE \
19756+ | AuOpt_PLINK \
19757+ | AuOpt_DefExtra1)
19758+
19759+/* ---------------------------------------------------------------------- */
19760+
19761+struct au_opt_add {
19762+ aufs_bindex_t bindex;
19763+ char *path;
19764+ int perm;
19765+ struct nameidata nd;
19766+};
19767+
19768+struct au_opt_del {
19769+ char *path;
19770+ struct dentry *h_root;
19771+};
19772+
19773+struct au_opt_mod {
19774+ char *path;
19775+ int perm;
19776+ struct dentry *h_root;
19777+};
19778+
19779+struct au_opt_xino {
19780+ char *path;
19781+ struct file *file;
19782+};
19783+
19784+struct au_opt_xinodir {
19785+ char *name;
19786+ struct path path;
19787+};
19788+
19789+struct au_opt_xino_itrunc {
19790+ aufs_bindex_t bindex;
19791+};
19792+
19793+struct au_opt_xino_trunc_v {
19794+ unsigned long long upper;
19795+ int step;
19796+};
19797+
19798+struct au_opt_wbr_create {
19799+ int wbr_create;
19800+ int mfs_second;
19801+ unsigned long long mfsrr_watermark;
19802+};
19803+
19804+struct au_opt {
19805+ int type;
19806+ union {
19807+ struct au_opt_xino xino;
19808+ struct au_opt_xinodir xinodir;
19809+ struct au_opt_xino_itrunc xino_itrunc;
19810+ struct au_opt_add add;
19811+ struct au_opt_del del;
19812+ struct au_opt_mod mod;
19813+ int dirwh;
19814+ int rdcache;
19815+ int deblk;
19816+ int nhash;
19817+ int udba;
19818+ int coo;
19819+ struct au_opt_wbr_create wbr_create;
19820+ int wbr_copyup;
19821+ };
19822+};
19823+
19824+/* opts flags */
19825+#define AuOpts_REMOUNT 1
19826+#define AuOpts_REFRESH_DIR (1 << 1)
19827+#define AuOpts_REFRESH_NONDIR (1 << 2)
19828+#define AuOpts_TRUNC_XIB (1 << 3)
19829+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
19830+#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
19831+#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
19832+
19833+struct au_opts {
19834+ struct au_opt *opt;
19835+ int max_opt;
19836+
19837+ unsigned int given_udba;
19838+ unsigned int flags;
19839+ unsigned long sb_flags;
19840+};
19841+
19842+/* ---------------------------------------------------------------------- */
19843+
19844+const char *au_optstr_br_perm(int brperm);
19845+const char *au_optstr_udba(int udba);
19846+const char *au_optstr_coo(int coo);
19847+const char *au_optstr_wbr_copyup(int wbr_copyup);
19848+const char *au_optstr_wbr_create(int wbr_create);
19849+
19850+void au_opts_free(struct au_opts *opts);
19851+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
19852+int verify_opts(struct super_block *sb, unsigned long sb_flags,
19853+ unsigned int pending, int remount);
19854+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
19855+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
19856+
19857+/* ---------------------------------------------------------------------- */
19858+
19859+#define au_opt_test(flags, name) (flags & AuOpt_##name)
19860+
19861+static inline int au_opt_test_xino(unsigned int flags)
19862+{
19863+ return flags & (AuOpt_XINO | AuOpt_XINODIR);
19864+}
19865+
19866+#define au_opt_set(flags, name) do { \
19867+ BUILD_BUG_ON(AuOpt_##name & (AuOptMask_COO | AuOptMask_UDBA)); \
19868+ ((flags) |= AuOpt_##name); \
19869+} while (0)
19870+
19871+#define au_opt_set_coo(flags, name) do { \
19872+ (flags) &= ~AuOptMask_COO; \
19873+ ((flags) |= AuOpt_##name); \
19874+} while (0)
19875+
19876+#define au_opt_set_udba(flags, name) do { \
19877+ (flags) &= ~AuOptMask_UDBA; \
19878+ ((flags) |= AuOpt_##name); \
19879+} while (0)
19880+
19881+#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
19882+
19883+static inline int au_test_dlgt(unsigned int flags)
19884+{
19885+ return au_opt_test(flags, DLGT) && !au_test_wkq(current);
19886+}
19887+
19888+static inline int au_test_dirperm1(unsigned int flags)
19889+{
19890+ return au_opt_test(flags, DIRPERM1) && !au_test_wkq(current);
19891+}
19892+
19893+#endif /* __KERNEL__ */
19894+#endif /* __AUFS_OPTS_H__ */
19895diff -urN linux/fs/aufs/plink.c linux-aufs/fs/aufs/plink.c
19896--- linux/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
19897+++ linux-aufs/fs/aufs/plink.c 2009-03-12 16:18:04.000000000 +0100
19898@@ -0,0 +1,364 @@
19899+/*
19900+ * Copyright (C) 2005-2009 Junjiro Okajima
19901+ *
19902+ * This program, aufs is free software; you can redistribute it and/or modify
19903+ * it under the terms of the GNU General Public License as published by
19904+ * the Free Software Foundation; either version 2 of the License, or
19905+ * (at your option) any later version.
19906+ *
19907+ * This program is distributed in the hope that it will be useful,
19908+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19909+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19910+ * GNU General Public License for more details.
19911+ *
19912+ * You should have received a copy of the GNU General Public License
19913+ * along with this program; if not, write to the Free Software
19914+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19915+ */
19916+
19917+/*
19918+ * pseudo-link
19919+ *
19920+ * $Id$
19921+ */
19922+
19923+#include "aufs.h"
19924+
19925+struct pseudo_link {
19926+ struct list_head list;
19927+ struct inode *inode;
19928+};
19929+
19930+#ifdef CONFIG_AUFS_DEBUG
19931+void au_plink_list(struct super_block *sb)
19932+{
19933+ struct au_sbinfo *sbinfo;
19934+ struct list_head *plink_list;
19935+ struct pseudo_link *plink;
19936+
19937+ AuTraceEnter();
19938+ SiMustAnyLock(sb);
19939+ sbinfo = au_sbi(sb);
19940+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
19941+
19942+ plink_list = &sbinfo->si_plink.head;
19943+ spin_lock(&sbinfo->si_plink.spin);
19944+ list_for_each_entry(plink, plink_list, list)
19945+ AuDbg("%lu\n", plink->inode->i_ino);
19946+ spin_unlock(&sbinfo->si_plink.spin);
19947+}
19948+#endif
19949+
19950+int au_plink_test(struct super_block *sb, struct inode *inode)
19951+{
19952+ int found;
19953+ struct au_sbinfo *sbinfo;
19954+ struct list_head *plink_list;
19955+ struct pseudo_link *plink;
19956+
19957+ LKTRTrace("i%lu\n", inode->i_ino);
19958+ SiMustAnyLock(sb);
19959+ sbinfo = au_sbi(sb);
19960+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
19961+
19962+ found = 0;
19963+ plink_list = &sbinfo->si_plink.head;
19964+ spin_lock(&sbinfo->si_plink.spin);
19965+ list_for_each_entry(plink, plink_list, list)
19966+ if (plink->inode == inode) {
19967+ found = 1;
19968+ break;
19969+ }
19970+ spin_unlock(&sbinfo->si_plink.spin);
19971+ return found;
19972+}
19973+
19974+/* 20 is max digits length of ulong 64 */
19975+#define PLINK_NAME_LEN ((20 + 1) * 2)
19976+
19977+static int plink_name(char *name, int len, struct inode *inode,
19978+ aufs_bindex_t bindex)
19979+{
19980+ int rlen;
19981+ struct inode *h_inode;
19982+
19983+ LKTRTrace("i%lu, b%d\n", inode->i_ino, bindex);
19984+ AuDebugOn(len != PLINK_NAME_LEN);
19985+ h_inode = au_h_iptr(inode, bindex);
19986+ AuDebugOn(!h_inode);
19987+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
19988+ AuDebugOn(rlen >= len);
19989+ return rlen;
19990+}
19991+
19992+struct dentry *au_plink_lkup(struct super_block *sb, aufs_bindex_t bindex,
19993+ struct inode *inode)
19994+{
19995+ struct dentry *h_dentry, *h_parent;
19996+ struct au_branch *br;
19997+ struct au_wbr *wbr;
19998+ struct inode *h_dir;
19999+ char tgtname[PLINK_NAME_LEN];
20000+ int len;
20001+ struct au_ndx ndx = {
20002+ .flags = 0,
20003+ .nd = NULL,
20004+ /* .br = NULL */
20005+ };
20006+
20007+ LKTRTrace("b%d, i%lu\n", bindex, inode->i_ino);
20008+ br = au_sbr(sb, bindex);
20009+ wbr = br->br_wbr;
20010+ AuDebugOn(!wbr);
20011+ h_parent = wbr->wbr_plink;
20012+ AuDebugOn(!h_parent);
20013+ h_dir = h_parent->d_inode;
20014+ AuDebugOn(!h_dir);
20015+
20016+ len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
20017+
20018+ /* always superio. */
20019+ ndx.nfsmnt = au_do_nfsmnt(br->br_mnt);
20020+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
20021+ h_dentry = au_sio_lkup_one(tgtname, h_parent, len, &ndx);
20022+ mutex_unlock(&h_dir->i_mutex);
20023+ return h_dentry;
20024+}
20025+
20026+static int do_whplink(char *tgt, int len, struct dentry *h_parent,
20027+ struct dentry *h_dentry, struct vfsmount *nfsmnt,
20028+ struct super_block *sb)
20029+{
20030+ int err, dlgt;
20031+ struct dentry *h_tgt;
20032+ struct inode *h_dir;
20033+ struct vfsub_args vargs;
20034+ struct au_ndx ndx = {
20035+ .nfsmnt = nfsmnt,
20036+ .flags = 0,
20037+ .nd = NULL,
20038+ /* .br = NULL */
20039+ };
20040+
20041+ AuTraceEnter();
20042+
20043+ dlgt = !!au_test_dlgt(au_mntflags(sb));
20044+ if (dlgt)
20045+ au_fset_ndx(ndx.flags, DLGT);
20046+ h_tgt = au_lkup_one(tgt, h_parent, len, &ndx);
20047+ err = PTR_ERR(h_tgt);
20048+ if (IS_ERR(h_tgt))
20049+ goto out;
20050+
20051+ err = 0;
20052+ vfsub_args_init(&vargs, NULL, dlgt, 0);
20053+ /* wh.plink dir is not monitored */
20054+ h_dir = h_parent->d_inode;
20055+ if (h_tgt->d_inode && h_tgt->d_inode != h_dentry->d_inode)
20056+ err = vfsub_unlink(h_dir, h_tgt, &vargs);
20057+ if (!err && !h_tgt->d_inode) {
20058+ err = vfsub_link(h_dentry, h_dir, h_tgt, &vargs);
20059+ /* todo: unnecessary? */
20060+ /* inc_nlink(inode); */
20061+ }
20062+ dput(h_tgt);
20063+
20064+ out:
20065+ AuTraceErr(err);
20066+ return err;
20067+}
20068+
20069+struct do_whplink_args {
20070+ int *errp;
20071+ char *tgt;
20072+ int len;
20073+ struct dentry *h_parent;
20074+ struct dentry *h_dentry;
20075+ struct vfsmount *nfsmnt;
20076+ struct super_block *sb;
20077+};
20078+
20079+static void call_do_whplink(void *args)
20080+{
20081+ struct do_whplink_args *a = args;
20082+ *a->errp = do_whplink(a->tgt, a->len, a->h_parent, a->h_dentry,
20083+ a->nfsmnt, a->sb);
20084+}
20085+
20086+static int whplink(struct dentry *h_dentry, struct inode *inode,
20087+ aufs_bindex_t bindex, struct super_block *sb)
20088+{
20089+ int err, len, wkq_err;
20090+ struct au_branch *br;
20091+ struct au_wbr *wbr;
20092+ struct dentry *h_parent;
20093+ struct inode *h_dir;
20094+ char tgtname[PLINK_NAME_LEN];
20095+
20096+ LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
20097+ br = au_sbr(inode->i_sb, bindex);
20098+ wbr = br->br_wbr;
20099+ AuDebugOn(!wbr);
20100+ h_parent = wbr->wbr_plink;
20101+ AuDebugOn(!h_parent);
20102+ h_dir = h_parent->d_inode;
20103+ AuDebugOn(!h_dir);
20104+
20105+ len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
20106+
20107+ /* always superio. */
20108+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
20109+ if (!au_test_wkq(current)) {
20110+ struct do_whplink_args args = {
20111+ .errp = &err,
20112+ .tgt = tgtname,
20113+ .len = len,
20114+ .h_parent = h_parent,
20115+ .h_dentry = h_dentry,
20116+ .nfsmnt = au_do_nfsmnt(br->br_mnt),
20117+ .sb = sb
20118+ };
20119+ wkq_err = au_wkq_wait(call_do_whplink, &args, /*dlgt*/0);
20120+ if (unlikely(wkq_err))
20121+ err = wkq_err;
20122+ } else
20123+ err = do_whplink(tgtname, len, h_parent, h_dentry,
20124+ au_do_nfsmnt(br->br_mnt), sb);
20125+ mutex_unlock(&h_dir->i_mutex);
20126+
20127+ AuTraceErr(err);
20128+ return err;
20129+}
20130+
20131+static void do_put_plink(struct pseudo_link *plink, int do_del)
20132+{
20133+ AuTraceEnter();
20134+
20135+ iput(plink->inode);
20136+ if (do_del)
20137+ list_del(&plink->list);
20138+ kfree(plink);
20139+}
20140+
20141+void au_plink_append(struct super_block *sb, struct inode *inode,
20142+ struct dentry *h_dentry, aufs_bindex_t bindex)
20143+{
20144+ struct au_sbinfo *sbinfo;
20145+ struct list_head *plink_list;
20146+ struct pseudo_link *plink;
20147+ int found, err, cnt;
20148+
20149+ LKTRTrace("i%lu\n", inode->i_ino);
20150+ SiMustAnyLock(sb);
20151+ sbinfo = au_sbi(sb);
20152+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
20153+
20154+ cnt = 0;
20155+ found = 0;
20156+ plink_list = &sbinfo->si_plink.head;
20157+ spin_lock(&sbinfo->si_plink.spin);
20158+ list_for_each_entry(plink, plink_list, list) {
20159+ cnt++;
20160+ if (plink->inode == inode) {
20161+ found = 1;
20162+ break;
20163+ }
20164+ }
20165+
20166+ err = 0;
20167+ plink = NULL;
20168+ if (!found) {
20169+ plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
20170+ if (plink) {
20171+ plink->inode = au_igrab(inode);
20172+ list_add(&plink->list, plink_list);
20173+ cnt++;
20174+ } else
20175+ err = -ENOMEM;
20176+ }
20177+ spin_unlock(&sbinfo->si_plink.spin);
20178+
20179+#if 0 /* todo: test here */
20180+ if (found)
20181+ return; /* success */
20182+#endif
20183+
20184+ if (!err)
20185+ err = whplink(h_dentry, inode, bindex, sb);
20186+
20187+ if (unlikely(cnt > AUFS_PLINK_WARN))
20188+ AuWarn1("unexpectedly many pseudo links, %d\n", cnt);
20189+ if (unlikely(err)) {
20190+ AuWarn("err %d, damaged pseudo link. ignored.\n", err);
20191+ if (!found && plink)
20192+ do_put_plink(plink, /*do_del*/1);
20193+ }
20194+}
20195+
20196+void au_plink_put(struct super_block *sb)
20197+{
20198+ struct au_sbinfo *sbinfo;
20199+ struct list_head *plink_list;
20200+ struct pseudo_link *plink, *tmp;
20201+
20202+ AuTraceEnter();
20203+ SiMustWriteLock(sb);
20204+ sbinfo = au_sbi(sb);
20205+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
20206+
20207+ plink_list = &sbinfo->si_plink.head;
20208+ /* spin_lock(&sbinfo->si_plink.spin); */
20209+ list_for_each_entry_safe(plink, tmp, plink_list, list)
20210+ do_put_plink(plink, 0);
20211+ INIT_LIST_HEAD(plink_list);
20212+ /* spin_unlock(&sbinfo->si_plink.head); */
20213+}
20214+
20215+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
20216+{
20217+ struct au_sbinfo *sbinfo;
20218+ struct list_head *plink_list;
20219+ struct pseudo_link *plink, *tmp;
20220+ struct inode *inode;
20221+ aufs_bindex_t bstart, bend, bindex;
20222+ int do_put;
20223+
20224+ AuTraceEnter();
20225+ SiMustWriteLock(sb);
20226+ sbinfo = au_sbi(sb);
20227+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
20228+
20229+ plink_list = &sbinfo->si_plink.head;
20230+ /* spin_lock(&sbinfo->si_plink.spin); */
20231+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
20232+ do_put = 0;
20233+ inode = au_igrab(plink->inode);
20234+ ii_write_lock_child(inode);
20235+ bstart = au_ibstart(inode);
20236+ bend = au_ibend(inode);
20237+ if (bstart >= 0) {
20238+ for (bindex = bstart; bindex <= bend; bindex++) {
20239+ if (!au_h_iptr(inode, bindex)
20240+ || au_ii_br_id(inode, bindex) != br_id)
20241+ continue;
20242+ au_set_h_iptr(inode, bindex, NULL, 0);
20243+ do_put = 1;
20244+ break;
20245+ }
20246+ } else
20247+ do_put_plink(plink, 1);
20248+
20249+ if (do_put) {
20250+ for (bindex = bstart; bindex <= bend; bindex++)
20251+ if (au_h_iptr(inode, bindex)) {
20252+ do_put = 0;
20253+ break;
20254+ }
20255+ if (do_put)
20256+ do_put_plink(plink, 1);
20257+ }
20258+ ii_write_unlock(inode);
20259+ iput(inode);
20260+ }
20261+ /* spin_unlock(&sbinfo->si_plink.spin); */
20262+}
20263diff -urN linux/fs/aufs/robr.c linux-aufs/fs/aufs/robr.c
20264--- linux/fs/aufs/robr.c 1970-01-01 01:00:00.000000000 +0100
20265+++ linux-aufs/fs/aufs/robr.c 2009-03-12 16:18:04.000000000 +0100
20266@@ -0,0 +1,117 @@
20267+/*
20268+ * Copyright (C) 2005-2009 Junjiro Okajima
20269+ *
20270+ * This program, aufs is free software; you can redistribute it and/or modify
20271+ * it under the terms of the GNU General Public License as published by
20272+ * the Free Software Foundation; either version 2 of the License, or
20273+ * (at your option) any later version.
20274+ *
20275+ * This program is distributed in the hope that it will be useful,
20276+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20277+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20278+ * GNU General Public License for more details.
20279+ *
20280+ * You should have received a copy of the GNU General Public License
20281+ * along with this program; if not, write to the Free Software
20282+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20283+ */
20284+
20285+/*
20286+ * 'robr', aufs as readonly branch of another aufs
20287+ *
20288+ * $Id$
20289+ */
20290+
20291+#include "aufs.h"
20292+
20293+/* ---------------------------------------------------------------------- */
20294+
20295+int au_test_robr_wh(struct qstr *name, struct dentry *h_parent,
20296+ struct qstr *wh_name, int try_sio, struct au_ndx *ndx)
20297+{
20298+ if (strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
20299+ return au_wh_test(h_parent, wh_name, try_sio, ndx);
20300+ return -EPERM;
20301+}
20302+
20303+int au_test_robr_shwh(struct super_block *sb, const struct qstr *name)
20304+{
20305+ return 0;
20306+}
20307+
20308+/* ---------------------------------------------------------------------- */
20309+
20310+struct au_robr_lvma {
20311+ struct list_head list;
20312+ struct vm_area_struct *vma;
20313+};
20314+
20315+struct file *au_robr_safe_file(struct vm_area_struct *vma)
20316+{
20317+ struct file *file = vma->vm_file;
20318+ struct super_block *sb = file->f_dentry->d_sb;
20319+ struct au_robr_lvma *lvma, *entry;
20320+ struct au_sbinfo *sbinfo;
20321+ struct list_head *head;
20322+ unsigned char found, warn;
20323+
20324+ AuTraceEnter();
20325+
20326+ if (!file->private_data || !au_test_aufs(sb))
20327+ return NULL;
20328+
20329+ warn = 0;
20330+ found = 0;
20331+ sbinfo = au_sbi(sb);
20332+ head = &sbinfo->si_lvma.head;
20333+ spin_lock(&sbinfo->si_lvma.spin);
20334+ list_for_each_entry(entry, head, list) {
20335+ found = (entry->vma == vma);
20336+ if (unlikely(found))
20337+ break;
20338+ }
20339+ if (!found) {
20340+ lvma = kmalloc(sizeof(*lvma), GFP_ATOMIC);
20341+ if (lvma) {
20342+ lvma->vma = vma;
20343+ list_add(&lvma->list, head);
20344+ } else {
20345+ warn = 1;
20346+ file = NULL;
20347+ }
20348+ } else
20349+ file = NULL;
20350+ spin_unlock(&sbinfo->si_lvma.spin);
20351+
20352+ if (unlikely(warn))
20353+ AuWarn1("no memory for lvma\n");
20354+ return file;
20355+}
20356+
20357+void au_robr_reset_file(struct vm_area_struct *vma, struct file *file)
20358+{
20359+ struct super_block *sb = file->f_dentry->d_sb;
20360+ struct au_robr_lvma *entry, *found;
20361+ struct au_sbinfo *sbinfo;
20362+ struct list_head *head;
20363+
20364+ AuTraceEnter();
20365+ AuDebugOn(!au_test_aufs(sb));
20366+
20367+ vma->vm_file = file;
20368+ /* smp_mb(); */ /* flush vm_file */
20369+
20370+ found = NULL;
20371+ sbinfo = au_sbi(sb);
20372+ head = &sbinfo->si_lvma.head;
20373+ spin_lock(&sbinfo->si_lvma.spin);
20374+ list_for_each_entry(entry, head, list)
20375+ if (entry->vma == vma) {
20376+ found = entry;
20377+ break;
20378+ }
20379+ AuDebugOn(!found);
20380+ list_del(&found->list);
20381+ spin_unlock(&sbinfo->si_lvma.spin);
20382+ kfree(found);
20383+}
20384diff -urN linux/fs/aufs/sbinfo.c linux-aufs/fs/aufs/sbinfo.c
20385--- linux/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
20386+++ linux-aufs/fs/aufs/sbinfo.c 2009-03-12 16:18:04.000000000 +0100
20387@@ -0,0 +1,221 @@
20388+/*
20389+ * Copyright (C) 2005-2009 Junjiro Okajima
20390+ *
20391+ * This program, aufs is free software; you can redistribute it and/or modify
20392+ * it under the terms of the GNU General Public License as published by
20393+ * the Free Software Foundation; either version 2 of the License, or
20394+ * (at your option) any later version.
20395+ *
20396+ * This program is distributed in the hope that it will be useful,
20397+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20398+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20399+ * GNU General Public License for more details.
20400+ *
20401+ * You should have received a copy of the GNU General Public License
20402+ * along with this program; if not, write to the Free Software
20403+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20404+ */
20405+
20406+/*
20407+ * superblock private data
20408+ *
20409+ * $Id$
20410+ */
20411+
20412+#include <linux/smp_lock.h>
20413+#include "aufs.h"
20414+
20415+/*
20416+ * they are necessary regardless sysfs is disabled.
20417+ */
20418+void au_si_free(struct kobject *kobj)
20419+{
20420+ struct au_sbinfo *sbinfo;
20421+ struct super_block *sb;
20422+
20423+ LKTRTrace("kobj %p\n", kobj);
20424+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
20425+ LKTRTrace("sbinfo %p\n", sbinfo);
20426+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
20427+
20428+ sb = sbinfo->si_sb;
20429+ si_write_lock(sb);
20430+ au_xino_clr(sb);
20431+ au_br_free(sbinfo);
20432+ kfree(sbinfo->si_branch);
20433+ au_export_put(sbinfo);
20434+ mutex_destroy(&sbinfo->si_xib_mtx);
20435+ si_write_unlock(sb);
20436+ au_rwsem_destroy(&sbinfo->si_rwsem);
20437+
20438+ kfree(sbinfo);
20439+}
20440+
20441+int au_si_alloc(struct super_block *sb)
20442+{
20443+ int err;
20444+ struct au_sbinfo *sbinfo;
20445+
20446+ AuTraceEnter();
20447+
20448+ err = -ENOMEM;
20449+ sbinfo = kmalloc(sizeof(*sbinfo), GFP_NOFS);
20450+ if (unlikely(!sbinfo))
20451+ goto out;
20452+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
20453+ if (unlikely(!sbinfo->si_branch))
20454+ goto out_sbinfo;
20455+
20456+ memset(&sbinfo->si_kobj, 0, sizeof(sbinfo->si_kobj));
20457+ err = sysaufs_si_init(sbinfo);
20458+ if (unlikely(err))
20459+ goto out_br;
20460+
20461+ au_rw_init_wlock(&sbinfo->si_rwsem);
20462+ //au_dbg_locked_si_reg(sb, 1);
20463+ sbinfo->si_generation = 0;
20464+ sbinfo->au_si_status = 0;
20465+ sbinfo->si_bend = -1;
20466+ sbinfo->si_last_br_id = 0;
20467+
20468+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
20469+ sbinfo->si_wbr_create = AuWbrCreate_Def;
20470+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + AuWbrCopyup_Def;
20471+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + AuWbrCreate_Def;
20472+
20473+ sbinfo->si_mntflags = AuOpt_Def;
20474+
20475+ sbinfo->si_xread = NULL;
20476+ sbinfo->si_xwrite = NULL;
20477+ sbinfo->si_xib = NULL;
20478+ mutex_init(&sbinfo->si_xib_mtx);
20479+ sbinfo->si_xib_buf = NULL;
20480+ au_xino_def_br_set(NULL, sbinfo);
20481+ /* leave si_xib_last_pindex and si_xib_next_bit */
20482+
20483+ au_nwt_init(&sbinfo->si_nowait);
20484+
20485+ sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
20486+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
20487+
20488+ au_spl_init(&sbinfo->si_plink);
20489+
20490+ au_robr_lvma_init(sbinfo);
20491+
20492+ /* leave other members for sysaufs and si_mnt. */
20493+ sbinfo->si_sb = sb;
20494+
20495+ sb->s_fs_info = sbinfo;
20496+
20497+ au_debug_sbinfo_init(sbinfo);
20498+ return 0; /* success */
20499+
20500+ out_br:
20501+ kfree(sbinfo->si_branch);
20502+ out_sbinfo:
20503+ kfree(sbinfo);
20504+ out:
20505+ AuTraceErr(err);
20506+ return err;
20507+}
20508+
20509+/* ---------------------------------------------------------------------- */
20510+
20511+struct au_branch *au_sbr(struct super_block *sb, aufs_bindex_t bindex)
20512+{
20513+ struct au_branch *br;
20514+
20515+ SiMustAnyLock(sb);
20516+ AuDebugOn(bindex < 0 || au_sbend(sb) < bindex);
20517+ br = au_sbi(sb)->si_branch[0 + bindex];
20518+ AuDebugOn(!br);
20519+ return br;
20520+}
20521+
20522+au_gen_t au_sigen_inc(struct super_block *sb)
20523+{
20524+ au_gen_t gen;
20525+
20526+ SiMustWriteLock(sb);
20527+ gen = ++au_sbi(sb)->si_generation;
20528+ au_update_digen(sb->s_root);
20529+ au_update_iigen(sb->s_root->d_inode);
20530+ sb->s_root->d_inode->i_version++;
20531+ return gen;
20532+}
20533+
20534+int au_find_bindex(struct super_block *sb, struct au_branch *br)
20535+{
20536+ aufs_bindex_t bindex, bend;
20537+
20538+ bend = au_sbend(sb);
20539+ for (bindex = 0; bindex <= bend; bindex++)
20540+ if (au_sbr(sb, bindex) == br)
20541+ return bindex;
20542+ return -1;
20543+}
20544+
20545+/* ---------------------------------------------------------------------- */
20546+
20547+/* dentry and super_block lock. call at entry point */
20548+void aufs_read_lock(struct dentry *dentry, int flags)
20549+{
20550+ si_read_lock(dentry->d_sb, flags);
20551+ if (au_ftest_lock(flags, DW))
20552+ di_write_lock_child(dentry);
20553+ else
20554+ di_read_lock_child(dentry, flags);
20555+}
20556+
20557+void aufs_read_unlock(struct dentry *dentry, int flags)
20558+{
20559+ if (au_ftest_lock(flags, DW))
20560+ di_write_unlock(dentry);
20561+ else
20562+ di_read_unlock(dentry, flags);
20563+ si_read_unlock(dentry->d_sb);
20564+}
20565+
20566+void aufs_write_lock(struct dentry *dentry)
20567+{
20568+ si_write_lock(dentry->d_sb);
20569+ di_write_lock_child(dentry);
20570+}
20571+
20572+void aufs_write_unlock(struct dentry *dentry)
20573+{
20574+ di_write_unlock(dentry);
20575+ si_write_unlock(dentry->d_sb);
20576+}
20577+
20578+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
20579+{
20580+ AuDebugOn(d1 == d2 || d1->d_sb != d2->d_sb);
20581+ si_read_lock(d1->d_sb, flags);
20582+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
20583+}
20584+
20585+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
20586+{
20587+ AuDebugOn(d1 == d2 || d1->d_sb != d2->d_sb);
20588+ di_write_unlock2(d1, d2);
20589+ si_read_unlock(d1->d_sb);
20590+}
20591+
20592+/* ---------------------------------------------------------------------- */
20593+
20594+aufs_bindex_t au_new_br_id(struct super_block *sb)
20595+{
20596+ aufs_bindex_t br_id;
20597+ struct au_sbinfo *sbinfo;
20598+
20599+ AuTraceEnter();
20600+ SiMustWriteLock(sb);
20601+
20602+ sbinfo = au_sbi(sb);
20603+ while (1) {
20604+ br_id = ++sbinfo->si_last_br_id;
20605+ if (br_id && au_br_index(sb, br_id) < 0)
20606+ return br_id;
20607+ }
20608+}
20609diff -urN linux/fs/aufs/super.c linux-aufs/fs/aufs/super.c
20610--- linux/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
20611+++ linux-aufs/fs/aufs/super.c 2009-03-12 16:18:04.000000000 +0100
20612@@ -0,0 +1,939 @@
20613+/*
20614+ * Copyright (C) 2005-2009 Junjiro Okajima
20615+ *
20616+ * This program, aufs is free software; you can redistribute it and/or modify
20617+ * it under the terms of the GNU General Public License as published by
20618+ * the Free Software Foundation; either version 2 of the License, or
20619+ * (at your option) any later version.
20620+ *
20621+ * This program is distributed in the hope that it will be useful,
20622+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20623+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20624+ * GNU General Public License for more details.
20625+ *
20626+ * You should have received a copy of the GNU General Public License
20627+ * along with this program; if not, write to the Free Software
20628+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20629+ */
20630+
20631+/*
20632+ * mount and super_block operations
20633+ *
20634+ * $Id$
20635+ */
20636+
20637+#include <linux/module.h>
20638+#include <linux/buffer_head.h>
20639+#include <linux/seq_file.h>
20640+#include <linux/smp_lock.h>
20641+#include <linux/statfs.h>
20642+
20643+#include "aufs.h"
20644+
20645+/*
20646+ * super_operations
20647+ */
20648+static struct inode *aufs_alloc_inode(struct super_block *sb)
20649+{
20650+ struct aufs_icntnr *c;
20651+
20652+ AuTraceEnter();
20653+
20654+ c = au_cache_alloc_icntnr();
20655+ if (c) {
20656+ inode_init_once(&c->vfs_inode);
20657+ c->vfs_inode.i_version = 1; /* sigen(sb); */
20658+ c->iinfo.ii_hinode = NULL;
20659+ return &c->vfs_inode;
20660+ }
20661+ return NULL;
20662+}
20663+
20664+static void aufs_destroy_inode(struct inode *inode)
20665+{
20666+ int err;
20667+
20668+ LKTRTrace("i%lu\n", inode->i_ino);
20669+
20670+ if (!inode->i_nlink || IS_DEADDIR(inode)) {
20671+ /* todo: move this lock into xigen_inc() */
20672+ /* in nowait task or remount, sbi is write-locked */
20673+ struct super_block *sb = inode->i_sb;
20674+ const int locked = si_noflush_read_trylock(sb);
20675+
20676+ err = au_xigen_inc(inode);
20677+ if (unlikely(err))
20678+ AuWarn1("failed resetting i_generation, %d\n", err);
20679+ if (locked)
20680+ si_read_unlock(sb);
20681+ }
20682+
20683+ au_iinfo_fin(inode);
20684+ au_cache_free_icntnr(container_of(inode, struct aufs_icntnr,
20685+ vfs_inode));
20686+}
20687+
20688+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
20689+{
20690+ struct inode *inode;
20691+ int err;
20692+
20693+ LKTRTrace("i%lu\n", (unsigned long)ino);
20694+
20695+ inode = iget_locked(sb, ino);
20696+ if (unlikely(!inode)) {
20697+ inode = ERR_PTR(-ENOMEM);
20698+ goto out;
20699+ }
20700+ AuDebugOn(IS_ERR(inode));
20701+ if (!(inode->i_state & I_NEW))
20702+ goto out;
20703+
20704+ err = au_xigen_new(inode);
20705+ if (!err)
20706+ err = au_iinfo_init(inode);
20707+ if (!err)
20708+ inode->i_version++;
20709+ else {
20710+ iget_failed(inode);
20711+ inode = ERR_PTR(err);
20712+ }
20713+
20714+ out:
20715+ /* never return NULL */
20716+ AuDebugOn(!inode);
20717+ AuTraceErrPtr(inode);
20718+ return inode;
20719+}
20720+
20721+/* lock free root dinfo */
20722+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
20723+{
20724+ int err;
20725+ aufs_bindex_t bindex, bend;
20726+ struct path path;
20727+ struct au_hdentry *hd;
20728+
20729+ AuTraceEnter();
20730+
20731+ err = 0;
20732+ bend = au_sbend(sb);
20733+ hd = au_di(sb->s_root)->di_hdentry;
20734+ for (bindex = 0; !err && bindex <= bend; bindex++) {
20735+ path.mnt = au_sbr_mnt(sb, bindex);
20736+ path.dentry = hd[bindex].hd_dentry;
20737+ err = seq_path(seq, &path, au_esc_chars);
20738+ if (err > 0) {
20739+ const char *p = au_optstr_br_perm(au_sbr_perm(sb,
20740+ bindex));
20741+ err = seq_printf(seq, "=%s", p);
20742+ }
20743+ if (!err && bindex != bend)
20744+ err = seq_putc(seq, ':');
20745+ }
20746+
20747+ AuTraceErr(err);
20748+ return err;
20749+}
20750+
20751+static void au_show_wbr_create(struct seq_file *m, int v,
20752+ struct au_sbinfo *sbinfo)
20753+{
20754+ const char *pat;
20755+
20756+ AuDebugOn(v == AuWbrCreate_Def);
20757+
20758+ seq_printf(m, ",create=");
20759+ pat = au_optstr_wbr_create(v);
20760+ switch (v) {
20761+ case AuWbrCreate_TDP:
20762+ case AuWbrCreate_RR:
20763+ case AuWbrCreate_MFS:
20764+ case AuWbrCreate_PMFS:
20765+ seq_printf(m, pat);
20766+ break;
20767+ case AuWbrCreate_MFSV:
20768+ seq_printf(m, /*pat*/"mfs:%lu",
20769+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
20770+ break;
20771+ case AuWbrCreate_PMFSV:
20772+ seq_printf(m, /*pat*/"pmfs:%lu",
20773+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
20774+ break;
20775+ case AuWbrCreate_MFSRR:
20776+ seq_printf(m, /*pat*/"mfsrr:%llu",
20777+ sbinfo->si_wbr_mfs.mfsrr_watermark);
20778+ break;
20779+ case AuWbrCreate_MFSRRV:
20780+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
20781+ sbinfo->si_wbr_mfs.mfsrr_watermark,
20782+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
20783+ break;
20784+ }
20785+}
20786+
20787+/* seq_file will re-call me in case of too long string */
20788+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
20789+{
20790+ int err, n;
20791+ unsigned int mnt_flags, v;
20792+ struct path path;
20793+ struct super_block *sb;
20794+ struct au_sbinfo *sbinfo;
20795+ struct file *xino;
20796+
20797+ AuTraceEnter();
20798+
20799+ sb = mnt->mnt_sb;
20800+ /* lock free root dinfo */
20801+ si_noflush_read_lock(sb);
20802+ sbinfo = au_sbi(sb);
20803+ seq_printf(m, ",si=%lx", au_si_mask ^ (unsigned long)sbinfo);
20804+ mnt_flags = au_mntflags(sb);
20805+ if (au_opt_test(mnt_flags, XINO)) {
20806+ seq_puts(m, ",xino=");
20807+ xino = sbinfo->si_xib;
20808+ path.mnt = xino->f_vfsmnt;
20809+ path.dentry = xino->f_dentry;
20810+ err = seq_path(m, &path, au_esc_chars);
20811+ if (unlikely(err <= 0))
20812+ goto out;
20813+ err = 0;
20814+#define Deleted "\\040(deleted)"
20815+ m->count -= sizeof(Deleted) - 1;
20816+ AuDebugOn(memcmp(m->buf + m->count, Deleted,
20817+ sizeof(Deleted) - 1));
20818+#undef Deleted
20819+#ifdef CONFIG_AUFS_EXPORT /* reserved for future use */
20820+ } else if (au_opt_test(mnt_flags, XINODIR)) {
20821+ seq_puts(m, ",xinodir=");
20822+ seq_path(m, &sbinfo->si_xinodir, au_esc_chars);
20823+#endif
20824+ } else
20825+ seq_puts(m, ",noxino");
20826+
20827+#define AuBool(name, str) do { \
20828+ v = au_opt_test(mnt_flags, name); \
20829+ if (v != au_opt_test(AuOpt_Def, name)) \
20830+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
20831+} while (0)
20832+
20833+#define AuStr(name, str) do { \
20834+ v = mnt_flags & AuOptMask_##name; \
20835+ if (v != (AuOpt_Def & AuOptMask_##name)) \
20836+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
20837+} while (0)
20838+
20839+#ifdef CONFIG_AUFS_COMPAT
20840+#define AuStr_BrOpt "dirs="
20841+#else
20842+#define AuStr_BrOpt "br:"
20843+#endif
20844+
20845+ AuBool(TRUNC_XINO, trunc_xino);
20846+ AuBool(DIRPERM1, dirperm1);
20847+ AuBool(SHWH, shwh);
20848+ AuBool(PLINK, plink);
20849+ AuStr(UDBA, udba);
20850+
20851+ v = sbinfo->si_wbr_create;
20852+ if (v != AuWbrCreate_Def)
20853+ au_show_wbr_create(m, v, sbinfo);
20854+
20855+ v = sbinfo->si_wbr_copyup;
20856+ if (v != AuWbrCopyup_Def)
20857+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
20858+
20859+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
20860+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
20861+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
20862+ AuBool(REFROF, refrof);
20863+ AuBool(DLGT, dlgt);
20864+ AuBool(WARN_PERM, warn_perm);
20865+ AuBool(VERBOSE, verbose);
20866+ AuBool(SUM, sum);
20867+ /* AuBool(SUM_W, wsum); */
20868+
20869+ n = sbinfo->si_dirwh;
20870+ if (n != AUFS_DIRWH_DEF)
20871+ seq_printf(m, ",dirwh=%d", n);
20872+ n = sbinfo->si_rdcache / HZ;
20873+ if (n != AUFS_RDCACHE_DEF)
20874+ seq_printf(m, ",rdcache=%d", n);
20875+
20876+ AuStr(COO, coo);
20877+
20878+ out:
20879+ if (!sysaufs_brs) {
20880+ seq_puts(m, "," AuStr_BrOpt);
20881+ au_show_brs(m, sb);
20882+ }
20883+ si_read_unlock(sb);
20884+ return 0;
20885+
20886+#undef AuBool
20887+#undef AuStr
20888+#undef AuStr_BrOpt
20889+}
20890+
20891+static u64 au_add_till_max(u64 a, u64 b)
20892+{
20893+ u64 old;
20894+
20895+ old = a;
20896+ a += b;
20897+ if (old < a)
20898+ return a;
20899+ return ULLONG_MAX;
20900+}
20901+
20902+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf, int dlgt)
20903+{
20904+ int err;
20905+ aufs_bindex_t bend, bindex, i;
20906+ unsigned char shared;
20907+ u64 blocks, bfree, bavail, files, ffree;
20908+ struct super_block *h_sb;
20909+
20910+ AuTraceEnter();
20911+
20912+ blocks = 0;
20913+ bfree = 0;
20914+ bavail = 0;
20915+ files = 0;
20916+ ffree = 0;
20917+
20918+ err = 0;
20919+ bend = au_sbend(sb);
20920+ for (bindex = bend; bindex >= 0; bindex--) {
20921+ h_sb = au_sbr_sb(sb, bindex);
20922+ shared = 0;
20923+ for (i = bindex + 1; !shared && i <= bend; i++)
20924+ shared = au_sbr_sb(sb, i) == h_sb;
20925+ if (shared)
20926+ continue;
20927+
20928+ err = vfsub_statfs(h_sb->s_root, buf, dlgt);
20929+ if (unlikely(err))
20930+ goto out;
20931+
20932+ blocks = au_add_till_max(blocks, buf->f_blocks);
20933+ bfree = au_add_till_max(bfree, buf->f_bfree);
20934+ bavail = au_add_till_max(bavail, buf->f_bavail);
20935+ files = au_add_till_max(files, buf->f_files);
20936+ ffree = au_add_till_max(ffree, buf->f_ffree);
20937+ }
20938+
20939+ buf->f_blocks = blocks;
20940+ buf->f_bfree = bfree;
20941+ buf->f_bavail = bavail;
20942+ buf->f_files = files;
20943+ buf->f_ffree = ffree;
20944+
20945+ out:
20946+ AuTraceErr(err);
20947+ return err;
20948+}
20949+
20950+/* todo: in case of round-robin policy, return the sum of all rw branches? */
20951+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
20952+{
20953+ int err;
20954+ unsigned int mnt_flags;
20955+ unsigned char dlgt;
20956+ struct super_block *sb;
20957+
20958+ AuTraceEnter();
20959+
20960+ /* lock free root dinfo */
20961+ sb = dentry->d_sb;
20962+ si_noflush_read_lock(sb);
20963+ mnt_flags = au_mntflags(sb);
20964+ dlgt = !!au_test_dlgt(mnt_flags);
20965+ if (!au_opt_test(mnt_flags, SUM))
20966+ err = vfsub_statfs(au_sbr_sb(sb, 0)->s_root, buf, dlgt);
20967+ else
20968+ err = au_statfs_sum(sb, buf, dlgt);
20969+ si_read_unlock(sb);
20970+ if (!err) {
20971+ buf->f_type = AUFS_SUPER_MAGIC;
20972+ buf->f_namelen -= AUFS_WH_PFX_LEN;
20973+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
20974+ }
20975+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
20976+
20977+ AuTraceErr(err);
20978+ return err;
20979+}
20980+
20981+static void au_fsync_br(struct super_block *sb)
20982+{
20983+#ifdef CONFIG_AUFS_FSYNC_SUPER_PATCH
20984+ aufs_bindex_t bend, bindex;
20985+ int brperm;
20986+ struct au_branch *br;
20987+ struct super_block *h_sb;
20988+
20989+ AuTraceEnter();
20990+
20991+ si_write_lock(sb);
20992+ bend = au_sbend(sb);
20993+ for (bindex = 0; bindex < bend; bindex++) {
20994+ br = au_sbr(sb, bindex);
20995+ brperm = br->br_perm;
20996+ if (brperm == AuBrPerm_RR || brperm == AuBrPerm_RRWH)
20997+ continue;
20998+ h_sb = br->br_mnt->mnt_sb;
20999+ if (bdev_read_only(h_sb->s_bdev))
21000+ continue;
21001+
21002+ lockdep_off();
21003+ down_write(&h_sb->s_umount);
21004+ shrink_dcache_sb(h_sb);
21005+ fsync_super(h_sb);
21006+ up_write(&h_sb->s_umount);
21007+ lockdep_on();
21008+ }
21009+ si_write_unlock(sb);
21010+#endif
21011+}
21012+
21013+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
21014+/* this IS NOT for super_operations */
21015+static void aufs_umount_begin(struct super_block *arg)
21016+#define AuUmountBeginSb(arg) (arg)
21017+#else
21018+/* this IS for super_operations */
21019+static void aufs_umount_begin(struct vfsmount *arg, int flags)
21020+#define AuUmountBeginSb(arg) ((arg)->mnt_sb)
21021+#endif
21022+{
21023+ struct super_block *sb = AuUmountBeginSb(arg);
21024+ struct au_sbinfo *sbinfo;
21025+
21026+ AuTraceEnter();
21027+ /* dont trust BKL */
21028+ AuDebugOn(!kernel_locked());
21029+
21030+ sbinfo = au_sbi(sb);
21031+ if (!sbinfo)
21032+ return;
21033+
21034+ au_fsync_br(sb);
21035+
21036+ si_write_lock(sb);
21037+ if (au_opt_test(au_mntflags(sb), PLINK))
21038+ au_plink_put(sb);
21039+ au_mnt_reset(sbinfo);
21040+#if 0 /* reserved for future use */
21041+ if (sbinfo->si_wbr_create_ops->fin)
21042+ sbinfo->si_wbr_create_ops->fin(sb);
21043+#endif
21044+ si_write_unlock(sb);
21045+}
21046+
21047+/* final actions when unmounting a file system */
21048+static void aufs_put_super(struct super_block *sb)
21049+{
21050+ struct au_sbinfo *sbinfo;
21051+
21052+ AuTraceEnter();
21053+
21054+ sbinfo = au_sbi(sb);
21055+ if (!sbinfo)
21056+ return;
21057+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
21058+ aufs_umount_begin(sb);
21059+#endif
21060+ kobject_put(&sbinfo->si_kobj);
21061+}
21062+
21063+/* ---------------------------------------------------------------------- */
21064+
21065+/*
21066+ * refresh dentry and inode at remount time.
21067+ */
21068+static int do_refresh(struct dentry *dentry, mode_t type,
21069+ unsigned int dir_flags)
21070+{
21071+ int err;
21072+ struct dentry *parent;
21073+ struct inode *inode;
21074+
21075+ LKTRTrace("%.*s, 0%o\n", AuDLNPair(dentry), type);
21076+ inode = dentry->d_inode;
21077+ AuDebugOn(!inode);
21078+
21079+ di_write_lock_child(dentry);
21080+ parent = dget_parent(dentry);
21081+ di_read_lock_parent(parent, AuLock_IR);
21082+ /* returns a number of positive dentries */
21083+ err = au_refresh_hdentry(dentry, type);
21084+ if (err >= 0) {
21085+ err = au_refresh_hinode(inode, dentry);
21086+ if (!err && type == S_IFDIR)
21087+ au_reset_hinotify(inode, dir_flags);
21088+ }
21089+ if (unlikely(err))
21090+ AuErr("unrecoverable error %d, %.*s\n", err, AuDLNPair(dentry));
21091+ di_read_unlock(parent, AuLock_IR);
21092+ dput(parent);
21093+ di_write_unlock(dentry);
21094+
21095+ AuTraceErr(err);
21096+ return err;
21097+}
21098+
21099+static int test_dir(struct dentry *dentry, void *arg)
21100+{
21101+ return S_ISDIR(dentry->d_inode->i_mode);
21102+}
21103+
21104+/* todo: merge with refresh_nondir()? */
21105+static int refresh_dir(struct dentry *root, au_gen_t sgen)
21106+{
21107+ int err, i, j, ndentry, e;
21108+ struct au_dcsub_pages dpages;
21109+ struct au_dpage *dpage;
21110+ struct dentry **dentries;
21111+ struct inode *inode;
21112+ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
21113+
21114+ LKTRTrace("sgen %d\n", sgen);
21115+ SiMustWriteLock(root->d_sb);
21116+ /* dont trust BKL */
21117+ AuDebugOn(au_digen(root) != sgen || !kernel_locked());
21118+
21119+ err = 0;
21120+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
21121+ if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sgen) {
21122+ ii_write_lock_child(inode);
21123+ e = au_refresh_hinode_self(inode);
21124+ ii_write_unlock(inode);
21125+ if (unlikely(e)) {
21126+ LKTRTrace("e %d, i%lu\n", e, inode->i_ino);
21127+ if (!err)
21128+ err = e;
21129+ /* go on even if err */
21130+ }
21131+ }
21132+
21133+ e = au_dpages_init(&dpages, GFP_NOFS);
21134+ if (unlikely(e)) {
21135+ if (!err)
21136+ err = e;
21137+ goto out;
21138+ }
21139+ e = au_dcsub_pages(&dpages, root, test_dir, NULL);
21140+ if (unlikely(e)) {
21141+ if (!err)
21142+ err = e;
21143+ goto out_dpages;
21144+ }
21145+
21146+ for (i = 0; !e && i < dpages.ndpage; i++) {
21147+ dpage = dpages.dpages + i;
21148+ dentries = dpage->dentries;
21149+ ndentry = dpage->ndentry;
21150+ for (j = 0; !e && j < ndentry; j++) {
21151+ struct dentry *d;
21152+ d = dentries[j];
21153+#ifdef CONFIG_AUFS_DEBUG
21154+ {
21155+ struct dentry *parent;
21156+ parent = dget_parent(d);
21157+ AuDebugOn(!S_ISDIR(d->d_inode->i_mode)
21158+ || IS_ROOT(d)
21159+ || au_digen(parent) != sgen);
21160+ dput(parent);
21161+ }
21162+#endif
21163+ if (au_digen(d) != sgen) {
21164+ e = do_refresh(d, S_IFDIR, flags);
21165+ if (unlikely(e && !err))
21166+ err = e;
21167+ /* break on err */
21168+ }
21169+ }
21170+ }
21171+
21172+ out_dpages:
21173+ au_dpages_free(&dpages);
21174+ out:
21175+ AuTraceErr(err);
21176+ return err;
21177+}
21178+
21179+static int test_nondir(struct dentry *dentry, void *arg)
21180+{
21181+ return !S_ISDIR(dentry->d_inode->i_mode);
21182+}
21183+
21184+static int refresh_nondir(struct dentry *root, au_gen_t sgen, int do_dentry)
21185+{
21186+ int err, i, j, ndentry, e;
21187+ struct au_dcsub_pages dpages;
21188+ struct au_dpage *dpage;
21189+ struct dentry **dentries;
21190+ struct inode *inode;
21191+
21192+ LKTRTrace("sgen %d\n", sgen);
21193+ SiMustWriteLock(root->d_sb);
21194+ /* dont trust BKL */
21195+ AuDebugOn(au_digen(root) != sgen || !kernel_locked());
21196+
21197+ err = 0;
21198+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
21199+ if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sgen) {
21200+ ii_write_lock_child(inode);
21201+ e = au_refresh_hinode_self(inode);
21202+ ii_write_unlock(inode);
21203+ if (unlikely(e)) {
21204+ LKTRTrace("e %d, i%lu\n", e, inode->i_ino);
21205+ if (!err)
21206+ err = e;
21207+ /* go on even if err */
21208+ }
21209+ }
21210+
21211+ if (!do_dentry)
21212+ goto out;
21213+
21214+ e = au_dpages_init(&dpages, GFP_NOFS);
21215+ if (unlikely(e)) {
21216+ if (!err)
21217+ err = e;
21218+ goto out;
21219+ }
21220+ e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
21221+ if (unlikely(e)) {
21222+ if (!err)
21223+ err = e;
21224+ goto out_dpages;
21225+ }
21226+
21227+ for (i = 0; i < dpages.ndpage; i++) {
21228+ dpage = dpages.dpages + i;
21229+ dentries = dpage->dentries;
21230+ ndentry = dpage->ndentry;
21231+ for (j = 0; j < ndentry; j++) {
21232+ struct dentry *d;
21233+ d = dentries[j];
21234+#ifdef CONFIG_AUFS_DEBUG
21235+ {
21236+ struct dentry *parent;
21237+ parent = dget_parent(d);
21238+ AuDebugOn(S_ISDIR(d->d_inode->i_mode)
21239+ || au_digen(parent) != sgen);
21240+ dput(parent);
21241+ }
21242+#endif
21243+ inode = d->d_inode;
21244+ if (inode && au_digen(d) != sgen) {
21245+ e = do_refresh(d, inode->i_mode & S_IFMT, 0);
21246+ if (unlikely(e && !err))
21247+ err = e;
21248+ /* go on even err */
21249+ }
21250+ }
21251+ }
21252+
21253+ out_dpages:
21254+ au_dpages_free(&dpages);
21255+ out:
21256+ AuTraceErr(err);
21257+ return err;
21258+}
21259+
21260+/* stop extra interpretation of errno in mount(8), and strange error messages */
21261+static int cvt_err(int err)
21262+{
21263+ AuTraceErr(err);
21264+
21265+ switch (err) {
21266+ case -ENOENT:
21267+ case -ENOTDIR:
21268+ case -EEXIST:
21269+ case -EIO:
21270+ err = -EINVAL;
21271+ }
21272+ return err;
21273+}
21274+
21275+/* protected by s_umount */
21276+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
21277+{
21278+ int err, rerr;
21279+ au_gen_t sigen;
21280+ struct dentry *root;
21281+ struct inode *inode;
21282+ struct au_opts opts;
21283+ struct au_sbinfo *sbinfo;
21284+ unsigned char dlgt;
21285+
21286+ LKTRTrace("flags 0x%x, data %s, len %lu\n",
21287+ *flags, data ? data : "NULL",
21288+ (unsigned long)(data ? strlen(data) : 0));
21289+
21290+ au_fsync_br(sb);
21291+
21292+ err = 0;
21293+ root = sb->s_root;
21294+ if (!data || !*data) {
21295+ aufs_write_lock(root);
21296+ err = verify_opts(sb, *flags, /*pending*/0, /*remount*/1);
21297+ aufs_write_unlock(root);
21298+ goto out; /* success */
21299+ }
21300+
21301+ err = -ENOMEM;
21302+ memset(&opts, 0, sizeof(opts));
21303+ opts.opt = (void *)__get_free_page(GFP_NOFS);
21304+ if (unlikely(!opts.opt))
21305+ goto out;
21306+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
21307+ opts.flags = AuOpts_REMOUNT;
21308+ opts.sb_flags = *flags;
21309+
21310+ /* parse it before aufs lock */
21311+ err = au_opts_parse(sb, data, &opts);
21312+ if (unlikely(err))
21313+ goto out_opts;
21314+
21315+ sbinfo = au_sbi(sb);
21316+ inode = root->d_inode;
21317+ mutex_lock(&inode->i_mutex);
21318+ aufs_write_lock(root);
21319+
21320+ /* au_do_opts() may return an error */
21321+ err = au_opts_remount(sb, &opts);
21322+ au_opts_free(&opts);
21323+
21324+ if (au_ftest_opts(opts.flags, REFRESH_DIR)
21325+ || au_ftest_opts(opts.flags, REFRESH_NONDIR)) {
21326+ dlgt = !!au_opt_test(sbinfo->si_mntflags, DLGT);
21327+ au_opt_clr(sbinfo->si_mntflags, DLGT);
21328+ au_sigen_inc(sb);
21329+ au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
21330+ sigen = au_sigen(sb);
21331+ au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
21332+
21333+ DiMustNoWaiters(root);
21334+ IiMustNoWaiters(root->d_inode);
21335+ di_write_unlock(root);
21336+
21337+ rerr = refresh_dir(root, sigen);
21338+ if (unlikely(rerr)) {
21339+ au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
21340+ AuWarn("Refreshing directories failed, ignores (%d)\n",
21341+ rerr);
21342+ }
21343+
21344+ if (au_ftest_opts(opts.flags, REFRESH_NONDIR)) {
21345+ rerr = refresh_nondir(root, sigen, !rerr);
21346+ if (unlikely(rerr))
21347+ AuWarn("Refreshing non-directories failed,"
21348+ " ignores (%d)\n", rerr);
21349+ }
21350+
21351+ /* aufs_write_lock() calls ..._child() */
21352+ di_write_lock_child(root);
21353+
21354+ au_cpup_attr_all(inode, /*force*/1);
21355+ if (dlgt)
21356+ au_opt_set(sbinfo->si_mntflags, DLGT);
21357+ }
21358+
21359+ aufs_write_unlock(root);
21360+ mutex_unlock(&inode->i_mutex);
21361+
21362+ out_opts:
21363+ free_page((unsigned long)opts.opt);
21364+ out:
21365+ err = cvt_err(err);
21366+ AuTraceErr(err);
21367+ return err;
21368+}
21369+
21370+static struct super_operations aufs_sop = {
21371+ .alloc_inode = aufs_alloc_inode,
21372+ .destroy_inode = aufs_destroy_inode,
21373+ .drop_inode = generic_delete_inode,
21374+
21375+ .show_options = aufs_show_options,
21376+ .statfs = aufs_statfs,
21377+
21378+ .put_super = aufs_put_super,
21379+ .remount_fs = aufs_remount_fs,
21380+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
21381+ .umount_begin = aufs_umount_begin
21382+#endif
21383+};
21384+
21385+/* ---------------------------------------------------------------------- */
21386+
21387+static int alloc_root(struct super_block *sb)
21388+{
21389+ int err;
21390+ struct inode *inode;
21391+ struct dentry *root;
21392+
21393+ AuTraceEnter();
21394+
21395+ err = -ENOMEM;
21396+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
21397+ err = PTR_ERR(inode);
21398+ if (IS_ERR(inode))
21399+ goto out;
21400+ inode->i_op = &aufs_dir_iop;
21401+ inode->i_fop = &aufs_dir_fop;
21402+ inode->i_mode = S_IFDIR;
21403+ unlock_new_inode(inode);
21404+ root = d_alloc_root(inode);
21405+ if (unlikely(!root))
21406+ goto out_iput;
21407+ err = PTR_ERR(root);
21408+ if (IS_ERR(root))
21409+ goto out_iput;
21410+
21411+ err = au_alloc_dinfo(root);
21412+ if (!err) {
21413+ sb->s_root = root;
21414+ return 0; /* success */
21415+ }
21416+ dput(root);
21417+ goto out; /* do not iput */
21418+
21419+ out_iput:
21420+ iget_failed(inode);
21421+ iput(inode);
21422+ out:
21423+ AuTraceErr(err);
21424+ return err;
21425+
21426+}
21427+
21428+static int aufs_fill_super(struct super_block *sb, void *raw_data, int silent)
21429+{
21430+ int err;
21431+ struct dentry *root;
21432+ struct inode *inode;
21433+ struct au_opts opts;
21434+ char *arg = raw_data;
21435+
21436+ if (unlikely(!arg || !*arg)) {
21437+ err = -EINVAL;
21438+ AuErr("no arg\n");
21439+ goto out;
21440+ }
21441+ LKTRTrace("%s, silent %d\n", arg, silent);
21442+
21443+ err = -ENOMEM;
21444+ memset(&opts, 0, sizeof(opts));
21445+ opts.opt = (void *)__get_free_page(GFP_NOFS);
21446+ if (unlikely(!opts.opt))
21447+ goto out;
21448+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
21449+ opts.sb_flags = sb->s_flags;
21450+
21451+ err = au_si_alloc(sb);
21452+ if (unlikely(err))
21453+ goto out_opts;
21454+ SiMustWriteLock(sb);
21455+
21456+ /* all timestamps always follow the ones on the branch */
21457+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
21458+ sb->s_op = &aufs_sop;
21459+ sb->s_magic = AUFS_SUPER_MAGIC;
21460+ au_export_init(sb);
21461+
21462+ err = alloc_root(sb);
21463+ if (unlikely(err)) {
21464+ AuDebugOn(sb->s_root);
21465+ si_write_unlock(sb);
21466+ goto out_info;
21467+ }
21468+ root = sb->s_root;
21469+ DiMustWriteLock(root);
21470+ inode = root->d_inode;
21471+ inode->i_nlink = 2;
21472+
21473+ /*
21474+ * actually we can parse options regardless aufs lock here.
21475+ * but at remount time, parsing must be done before aufs lock.
21476+ * so we follow the same rule.
21477+ */
21478+ ii_write_lock_parent(inode);
21479+ au_dbg_locked_si_reg(sb, 1);
21480+ aufs_write_unlock(root);
21481+ err = au_opts_parse(sb, arg, &opts);
21482+ if (unlikely(err))
21483+ goto out_root;
21484+
21485+ /* lock vfs_inode first, then aufs. */
21486+ mutex_lock(&inode->i_mutex);
21487+ inode->i_op = &aufs_dir_iop;
21488+ inode->i_fop = &aufs_dir_fop;
21489+ aufs_write_lock(root);
21490+
21491+ sb->s_maxbytes = 0;
21492+ err = au_opts_mount(sb, &opts);
21493+ au_opts_free(&opts);
21494+ if (unlikely(err))
21495+ goto out_unlock;
21496+ AuDebugOn(!sb->s_maxbytes);
21497+
21498+ aufs_write_unlock(root);
21499+ mutex_unlock(&inode->i_mutex);
21500+ goto out_opts; /* success */
21501+
21502+ out_unlock:
21503+ aufs_write_unlock(root);
21504+ mutex_unlock(&inode->i_mutex);
21505+ out_root:
21506+ dput(root);
21507+ sb->s_root = NULL;
21508+ out_info:
21509+ kobject_put(&au_sbi(sb)->si_kobj);
21510+ sb->s_fs_info = NULL;
21511+ out_opts:
21512+ free_page((unsigned long)opts.opt);
21513+ out:
21514+ AuTraceErr(err);
21515+ err = cvt_err(err);
21516+ AuTraceErr(err);
21517+ return err;
21518+}
21519+
21520+/* ---------------------------------------------------------------------- */
21521+
21522+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
21523+ const char *dev_name, void *raw_data,
21524+ struct vfsmount *mnt)
21525+{
21526+ int err;
21527+ struct super_block *sb;
21528+
21529+ /* all timestamps always follow the ones on the branch */
21530+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
21531+ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
21532+ if (!err) {
21533+ sb = mnt->mnt_sb;
21534+ au_mnt_init(au_sbi(sb), mnt);
21535+ si_write_lock(sb);
21536+ sysaufs_brs_add(sb, 0);
21537+ si_write_unlock(sb);
21538+ }
21539+ return err;
21540+}
21541+
21542+struct file_system_type aufs_fs_type = {
21543+ .name = AUFS_FSTYPE,
21544+ .fs_flags =
21545+ FS_RENAME_DOES_D_MOVE /* a race between rename and others*/
21546+ | FS_REVAL_DOT, /* for NFS branch and udba */
21547+ .get_sb = aufs_get_sb,
21548+ .kill_sb = generic_shutdown_super,
21549+ /* no need to __module_get() and module_put(). */
21550+ .owner = THIS_MODULE,
21551+};
21552diff -urN linux/fs/aufs/super.h linux-aufs/fs/aufs/super.h
21553--- linux/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
21554+++ linux-aufs/fs/aufs/super.h 2009-03-12 16:18:04.000000000 +0100
21555@@ -0,0 +1,579 @@
21556+/*
21557+ * Copyright (C) 2005-2009 Junjiro Okajima
21558+ *
21559+ * This program, aufs is free software; you can redistribute it and/or modify
21560+ * it under the terms of the GNU General Public License as published by
21561+ * the Free Software Foundation; either version 2 of the License, or
21562+ * (at your option) any later version.
21563+ *
21564+ * This program is distributed in the hope that it will be useful,
21565+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21566+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21567+ * GNU General Public License for more details.
21568+ *
21569+ * You should have received a copy of the GNU General Public License
21570+ * along with this program; if not, write to the Free Software
21571+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21572+ */
21573+
21574+/*
21575+ * super_block operations
21576+ *
21577+ * $Id$
21578+ */
21579+
21580+#ifndef __AUFS_SUPER_H__
21581+#define __AUFS_SUPER_H__
21582+
21583+#ifdef __KERNEL__
21584+
21585+#include <linux/fs.h>
21586+#include <linux/cramfs_fs.h>
21587+#include <linux/kobject.h>
21588+#include <linux/magic.h>
21589+#include <linux/mount.h>
21590+#include <linux/aufs_type.h>
21591+#include "misc.h"
21592+#include "wkq.h"
21593+
21594+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
21595+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
21596+ loff_t *);
21597+
21598+struct au_wbr_copyup_operations {
21599+ int (*copyup)(struct dentry *dentry);
21600+};
21601+
21602+struct au_wbr_create_operations {
21603+ int (*create)(struct dentry *dentry, int isdir);
21604+ int (*init)(struct super_block *sb);
21605+ int (*fin)(struct super_block *sb);
21606+};
21607+
21608+struct au_wbr_mfs {
21609+ struct mutex mfs_lock; /* protect this structure */
21610+ unsigned long mfs_jiffy;
21611+ unsigned long mfs_expire;
21612+ aufs_bindex_t mfs_bindex;
21613+
21614+ unsigned long long mfsrr_bytes;
21615+ unsigned long long mfsrr_watermark;
21616+};
21617+
21618+/* sbinfo status flags */
21619+/*
21620+ * set true when refresh_dirs() failed at remount time.
21621+ * then try refreshing dirs at access time again.
21622+ * if it is false, refreshing dirs at access time is unnecesary
21623+ */
21624+#define AuSi_FAILED_REFRESH_DIRS 1
21625+#define au_ftest_si(sbinfo, name) ((sbinfo)->au_si_status & AuSi_##name)
21626+#define au_fset_si(sbinfo, name) \
21627+ { (sbinfo)->au_si_status |= AuSi_##name; }
21628+#define au_fclr_si(sbinfo, name) \
21629+ { (sbinfo)->au_si_status &= ~AuSi_##name; }
21630+
21631+struct au_branch;
21632+struct au_sbinfo {
21633+ /* nowait tasks in the system-wide workqueue */
21634+ struct au_nowait_tasks si_nowait;
21635+
21636+ struct au_rwsem si_rwsem;
21637+
21638+ /* branch management */
21639+ au_gen_t si_generation;
21640+
21641+ /* see above flags */
21642+ unsigned char au_si_status;
21643+
21644+ aufs_bindex_t si_bend;
21645+ aufs_bindex_t si_last_br_id;
21646+ struct au_branch **si_branch;
21647+
21648+ /* policy to select a writable branch */
21649+ unsigned char si_wbr_copyup;
21650+ unsigned char si_wbr_create;
21651+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
21652+ struct au_wbr_create_operations *si_wbr_create_ops;
21653+
21654+ /* round robin */
21655+ atomic_t si_wbr_rr_next;
21656+
21657+ /* most free space */
21658+ struct au_wbr_mfs si_wbr_mfs;
21659+
21660+ /* mount flags */
21661+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
21662+ unsigned int si_mntflags;
21663+
21664+ /* external inode number (bitmap and translation table) */
21665+ au_readf_t si_xread;
21666+ au_writef_t si_xwrite;
21667+ struct file *si_xib;
21668+ struct mutex si_xib_mtx; /* protect xib members */
21669+ unsigned long *si_xib_buf;
21670+ unsigned long si_xib_last_pindex;
21671+ int si_xib_next_bit;
21672+ /* reserved for future use */
21673+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
21674+
21675+#ifdef CONFIG_AUFS_HINOTIFY
21676+ struct au_branch *si_xino_def_br;
21677+#endif
21678+
21679+#ifdef CONFIG_AUFS_EXPORT
21680+ /* i_generation */
21681+ struct file *si_xigen;
21682+ atomic_t si_xigen_next;
21683+#endif
21684+
21685+ /* readdir cache time, max, in HZ */
21686+ unsigned long si_rdcache;
21687+
21688+ /*
21689+ * If the number of whiteouts are larger than si_dirwh, leave all of
21690+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
21691+ * future fsck.aufs or kernel thread will remove them later.
21692+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
21693+ */
21694+ unsigned int si_dirwh;
21695+
21696+ /*
21697+ * rename(2) a directory with all children.
21698+ */
21699+ /* reserved for future use */
21700+ /* int si_rendir; */
21701+
21702+ /* pseudo_link list */ /* todo: dirty? */
21703+ struct au_splhead si_plink;
21704+
21705+#if defined(CONFIG_AUFS_EXPORT) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
21706+ /* dirty, for export, async ops, and sysfs */
21707+ spinlock_t si_mntcache_lock;
21708+ struct vfsmount *si_mntcache; /* no get/put */
21709+#endif
21710+
21711+ /*
21712+ * sysfs and lifetime management.
21713+ * this is not a small structure and it may be a waste of memory in case
21714+ * of sysfs is disabled, particulary when many aufs-es are mounted.
21715+ */
21716+ struct kobject si_kobj;
21717+
21718+#ifdef CONFIG_AUFS_ROBR
21719+ /* locked vma list for mmap() */ /* todo: dirty? */
21720+ struct au_splhead si_lvma;
21721+#endif
21722+
21723+#ifdef CONFIG_AUFS_EXPORT /* reserved for future use */
21724+ struct path si_xinodir;
21725+#endif
21726+
21727+ /* dirty, necessary for unmounting, sysfs and sysrq */
21728+ struct super_block *si_sb;
21729+
21730+#ifdef CONFIG_AUFS_DEBUG_LOCK
21731+ struct au_splhead si_dbg_lock[AuDbgLock_Last];
21732+#endif
21733+};
21734+
21735+/* ---------------------------------------------------------------------- */
21736+
21737+/* policy to select one among writable branches */
21738+#define AuWbrCopyup(sbinfo, args...) \
21739+ ((sbinfo)->si_wbr_copyup_ops->copyup(args))
21740+#define AuWbrCreate(sbinfo, args...) \
21741+ ((sbinfo)->si_wbr_create_ops->create(args))
21742+
21743+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
21744+#define AuLock_DW 1 /* write-lock dentry */
21745+#define AuLock_IR (1 << 1) /* read-lock inode */
21746+#define AuLock_IW (1 << 2) /* write-lock inode */
21747+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
21748+#define AuLock_DIR (1 << 4) /* target is a dir */
21749+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
21750+#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
21751+#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
21752+
21753+/* ---------------------------------------------------------------------- */
21754+
21755+/* super.c */
21756+extern struct file_system_type aufs_fs_type;
21757+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
21758+
21759+/* sbinfo.c */
21760+void au_si_free(struct kobject *kobj);
21761+int au_si_alloc(struct super_block *sb);
21762+struct au_branch *au_sbr(struct super_block *sb, aufs_bindex_t bindex);
21763+au_gen_t au_sigen_inc(struct super_block *sb);
21764+int au_find_bindex(struct super_block *sb, struct au_branch *br);
21765+
21766+void aufs_read_lock(struct dentry *dentry, int flags);
21767+void aufs_read_unlock(struct dentry *dentry, int flags);
21768+void aufs_write_lock(struct dentry *dentry);
21769+void aufs_write_unlock(struct dentry *dentry);
21770+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
21771+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
21772+
21773+aufs_bindex_t au_new_br_id(struct super_block *sb);
21774+
21775+/* wbr_policy.c */
21776+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
21777+extern struct au_wbr_create_operations au_wbr_create_ops[];
21778+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
21779+
21780+/* ---------------------------------------------------------------------- */
21781+
21782+#if defined(CONFIG_AUFS_EXPORT) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
21783+static inline void au_mnt_init(struct au_sbinfo *sbinfo, struct vfsmount *mnt)
21784+{
21785+ spin_lock_init(&sbinfo->si_mntcache_lock);
21786+ sbinfo->si_mntcache = mnt;
21787+}
21788+
21789+static inline void au_mnt_reset(struct au_sbinfo *sbinfo)
21790+{
21791+ spin_lock(&sbinfo->si_mntcache_lock);
21792+ sbinfo->si_mntcache = NULL;
21793+ spin_unlock(&sbinfo->si_mntcache_lock);
21794+}
21795+#else
21796+static inline void au_mnt_init(struct au_sbinfo *sbinfo, struct vfsmount *mnt)
21797+{
21798+ /* emptr */
21799+}
21800+
21801+static inline void au_mnt_reset(struct au_sbinfo *sbinfo)
21802+{
21803+ /* emptr */
21804+}
21805+#endif /* EXPORT && < 2.6.26 */
21806+
21807+/* ---------------------------------------------------------------------- */
21808+
21809+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
21810+static inline int au_mnt_want_write(struct vfsmount *h_mnt)
21811+{
21812+ return mnt_want_write(h_mnt);
21813+}
21814+
21815+static inline void au_mnt_drop_write(struct vfsmount *h_mnt)
21816+{
21817+ mnt_drop_write(h_mnt);
21818+}
21819+#else
21820+static inline int au_mnt_want_write(struct vfsmount *h_mnt)
21821+{
21822+ return 0;
21823+}
21824+
21825+static inline void au_mnt_drop_write(struct vfsmount *h_mnt)
21826+{
21827+ /* empty */
21828+}
21829+#endif
21830+
21831+/* ---------------------------------------------------------------------- */
21832+
21833+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
21834+{
21835+ return sb->s_fs_info;
21836+}
21837+
21838+static inline const char *au_sbtype(struct super_block *sb)
21839+{
21840+ return sb->s_type->name;
21841+}
21842+
21843+static inline int au_test_aufs(struct super_block *sb)
21844+{
21845+ return sb->s_magic == AUFS_SUPER_MAGIC;
21846+}
21847+
21848+static inline int au_test_nfs(struct super_block *sb)
21849+{
21850+#ifdef CONFIG_AUFS_BR_NFS
21851+ return sb->s_magic == NFS_SUPER_MAGIC;
21852+#else
21853+ return 0;
21854+#endif
21855+}
21856+
21857+static inline int au_test_nfs4(struct super_block *sb)
21858+{
21859+#ifdef CONFIG_AUFS_BR_NFS_V4
21860+ return au_test_nfs(sb) && !strcmp(sb->s_type->name, "nfs4");
21861+#else
21862+ return 0;
21863+#endif
21864+}
21865+
21866+static inline int au_test_fuse(struct super_block *sb)
21867+{
21868+#ifdef CONFIG_AUFS_WORKAROUND_FUSE
21869+ return sb->s_magic == FUSE_SUPER_MAGIC;
21870+#else
21871+ return 0;
21872+#endif
21873+}
21874+
21875+static inline int au_test_xfs(struct super_block *sb)
21876+{
21877+#ifdef CONFIG_AUFS_BR_XFS
21878+ return sb->s_magic == XFS_SB_MAGIC;
21879+#else
21880+ return 0;
21881+#endif
21882+}
21883+
21884+static inline int au_test_tmpfs(struct super_block *sb)
21885+{
21886+#ifdef CONFIG_TMPFS
21887+ return sb->s_magic == TMPFS_MAGIC;
21888+#else
21889+ return 0;
21890+#endif
21891+}
21892+
21893+static inline int au_test_ecryptfs(struct super_block *sb)
21894+{
21895+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
21896+ /* why don't they use s_magic? */
21897+ return !strcmp(sb->s_type->name, "ecryptfs");
21898+#else
21899+ return 0;
21900+#endif
21901+}
21902+
21903+/* ---------------------------------------------------------------------- */
21904+
21905+#ifdef CONFIG_AUFS_HINOTIFY
21906+static inline void au_xino_def_br_set(struct au_branch *br,
21907+ struct au_sbinfo *sbinfo)
21908+{
21909+ sbinfo->si_xino_def_br = br;
21910+}
21911+
21912+static inline struct au_branch *au_xino_def_br(struct au_sbinfo *sbinfo)
21913+{
21914+ return sbinfo->si_xino_def_br;
21915+}
21916+#else
21917+static inline void au_xino_def_br_set(struct au_branch *br,
21918+ struct au_sbinfo *sbinfo)
21919+{
21920+ /* empty */
21921+}
21922+
21923+static inline struct au_branch *au_xino_def_br(struct au_sbinfo *sbinfo)
21924+{
21925+ return NULL;
21926+}
21927+#endif
21928+
21929+/* ---------------------------------------------------------------------- */
21930+
21931+#ifdef CONFIG_AUFS_EXPORT
21932+void au_export_init(struct super_block *sb);
21933+
21934+static inline int au_test_nfsd(struct task_struct *tsk)
21935+{
21936+ return !tsk->mm && !strcmp(tsk->comm, "nfsd");
21937+}
21938+
21939+static inline void au_export_put(struct au_sbinfo *sbinfo)
21940+{
21941+ path_put(&sbinfo->si_xinodir);
21942+}
21943+
21944+int au_xigen_inc(struct inode *inode);
21945+int au_xigen_new(struct inode *inode);
21946+int au_xigen_set(struct super_block *sb, struct file *base);
21947+void au_xigen_clr(struct super_block *sb);
21948+#else
21949+static inline void au_export_init(struct super_block *sb)
21950+{
21951+ /* nothing */
21952+}
21953+
21954+static inline int au_test_nfsd(struct task_struct *tsk)
21955+{
21956+ return 0;
21957+}
21958+
21959+static inline void au_export_put(struct au_sbinfo *sbinfo)
21960+{
21961+ /* nothing */
21962+}
21963+
21964+static inline int au_xigen_inc(struct inode *inode)
21965+{
21966+ return 0;
21967+}
21968+
21969+static inline int au_xigen_new(struct inode *inode)
21970+{
21971+ return 0;
21972+}
21973+
21974+static inline int au_xigen_set(struct super_block *sb, struct file *base)
21975+{
21976+ return 0;
21977+}
21978+
21979+static inline void au_xigen_clr(struct super_block *sb)
21980+{
21981+ /* empty */
21982+}
21983+#endif /* CONFIG_AUFS_EXPORT */
21984+
21985+#ifdef CONFIG_AUFS_ROBR
21986+static inline int au_test_nested(struct super_block *h_sb)
21987+{
21988+ return 0;
21989+}
21990+
21991+static inline void au_robr_lvma_init(struct au_sbinfo *sbinfo)
21992+{
21993+ au_spl_init(&sbinfo->si_lvma);
21994+}
21995+#else
21996+static inline int au_test_nested(struct super_block *h_sb)
21997+{
21998+ int err = 0;
21999+ if (unlikely(au_test_aufs(h_sb))) {
22000+ err = -EINVAL;
22001+ AuTraceErr(err);
22002+ }
22003+ return err;
22004+}
22005+
22006+static inline void au_robr_lvma_init(struct au_sbinfo *sbinfo)
22007+{
22008+ /* empty */
22009+}
22010+#endif /* CONFIG_AUFS_ROBR */
22011+
22012+/* ---------------------------------------------------------------------- */
22013+
22014+/* lock superblock. mainly for entry point functions */
22015+/*
22016+ * si_do_noflush_read_lock, si_do_noflush_write_lock,
22017+ * si_do_read_unlock, si_do_write_unlock, si_do_downgrade_lock
22018+ */
22019+AuSimpleLockRwsemFuncs(si_do_noflush, struct super_block *sb,
22020+ au_sbi(sb)->si_rwsem);
22021+AuSimpleUnlockRwsemFuncs(si_do, struct super_block *sb, au_sbi(sb)->si_rwsem);
22022+
22023+static inline void si_noflush_read_lock(struct super_block *sb)
22024+{
22025+ au_dbg_locking_si_reg(sb, 0);
22026+ si_do_noflush_read_lock(sb);
22027+ au_dbg_locking_si_unreg(sb, 0);
22028+ au_dbg_locked_si_reg(sb, 0);
22029+}
22030+
22031+static inline void si_noflush_write_lock(struct super_block *sb)
22032+{
22033+ au_dbg_locking_si_reg(sb, 1);
22034+ si_do_noflush_write_lock(sb);
22035+ au_dbg_locking_si_unreg(sb, 1);
22036+ au_dbg_locked_si_reg(sb, 1);
22037+}
22038+
22039+static inline int si_noflush_read_trylock(struct super_block *sb)
22040+{
22041+ int locked;
22042+
22043+ au_dbg_locking_si_reg(sb, 0);
22044+ locked = si_do_noflush_read_trylock(sb);
22045+ au_dbg_locking_si_unreg(sb, 0);
22046+ if (locked)
22047+ au_dbg_locked_si_reg(sb, 0);
22048+ return locked;
22049+}
22050+
22051+static inline int si_noflush_write_trylock(struct super_block *sb)
22052+{
22053+ int locked;
22054+
22055+ au_dbg_locking_si_reg(sb, 1);
22056+ locked = si_do_noflush_write_trylock(sb);
22057+ au_dbg_locking_si_unreg(sb, 1);
22058+ if (locked)
22059+ au_dbg_locked_si_reg(sb, 1);
22060+ return locked;
22061+}
22062+
22063+static inline void si_read_unlock(struct super_block *sb)
22064+{
22065+ si_do_read_unlock(sb);
22066+ au_dbg_locked_si_unreg(sb, 0);
22067+}
22068+
22069+static inline void si_write_unlock(struct super_block *sb)
22070+{
22071+ si_do_write_unlock(sb);
22072+ au_dbg_locked_si_unreg(sb, 1);
22073+}
22074+
22075+static inline void si_downgrade_lock(struct super_block *sb)
22076+{
22077+ si_do_downgrade_lock(sb);
22078+}
22079+
22080+static inline void si_read_lock(struct super_block *sb, int flags)
22081+{
22082+ if (/* !au_test_nfsd(current) && */au_ftest_lock(flags, FLUSH))
22083+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22084+ si_noflush_read_lock(sb);
22085+}
22086+
22087+static inline void si_write_lock(struct super_block *sb)
22088+{
22089+ //WARN_ON(au_test_nfsd(current));
22090+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22091+ si_noflush_write_lock(sb);
22092+}
22093+
22094+static inline int si_read_trylock(struct super_block *sb, int flags)
22095+{
22096+ if (/* !au_test_nfsd(current) && */au_ftest_lock(flags, FLUSH))
22097+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22098+ return si_noflush_read_trylock(sb);
22099+}
22100+
22101+static inline int si_write_trylock(struct super_block *sb, int flags)
22102+{
22103+ if (/* !au_test_nfsd(current) && */au_ftest_lock(flags, FLUSH))
22104+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22105+ return si_noflush_write_trylock(sb);
22106+}
22107+
22108+/* to debug easier, do not make them inlined functions */
22109+#define SiMustReadLock(sb) AuRwMustReadLock(&au_sbi(sb)->si_rwsem)
22110+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
22111+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
22112+
22113+/* ---------------------------------------------------------------------- */
22114+
22115+static inline aufs_bindex_t au_sbend(struct super_block *sb)
22116+{
22117+ SiMustAnyLock(sb);
22118+ return au_sbi(sb)->si_bend;
22119+}
22120+
22121+static inline unsigned int au_mntflags(struct super_block *sb)
22122+{
22123+ SiMustAnyLock(sb);
22124+ return au_sbi(sb)->si_mntflags;
22125+}
22126+
22127+static inline au_gen_t au_sigen(struct super_block *sb)
22128+{
22129+ SiMustAnyLock(sb);
22130+ return au_sbi(sb)->si_generation;
22131+}
22132+
22133+#endif /* __KERNEL__ */
22134+#endif /* __AUFS_SUPER_H__ */
22135diff -urN linux/fs/aufs/sysaufs.c linux-aufs/fs/aufs/sysaufs.c
22136--- linux/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
22137+++ linux-aufs/fs/aufs/sysaufs.c 2009-03-12 16:18:04.000000000 +0100
22138@@ -0,0 +1,109 @@
22139+/*
22140+ * Copyright (C) 2005-2009 Junjiro Okajima
22141+ *
22142+ * This program, aufs is free software; you can redistribute it and/or modify
22143+ * it under the terms of the GNU General Public License as published by
22144+ * the Free Software Foundation; either version 2 of the License, or
22145+ * (at your option) any later version.
22146+ *
22147+ * This program is distributed in the hope that it will be useful,
22148+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22149+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22150+ * GNU General Public License for more details.
22151+ *
22152+ * You should have received a copy of the GNU General Public License
22153+ * along with this program; if not, write to the Free Software
22154+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22155+ */
22156+
22157+/*
22158+ * sysfs interface and lifetime management
22159+ * they are necessary regardless sysfs is disabled.
22160+ *
22161+ * $Id$
22162+ */
22163+
22164+#include <linux/fs.h>
22165+#include <linux/module.h>
22166+#include <linux/random.h>
22167+#include <linux/sysfs.h>
22168+#include "aufs.h"
22169+
22170+/* ---------------------------------------------------------------------- */
22171+
22172+unsigned long au_si_mask;
22173+
22174+/* ---------------------------------------------------------------------- */
22175+
22176+struct kset *au_kset;
22177+
22178+#define AuSbiAttr(_name) { \
22179+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
22180+ .show = sysaufs_sbi_##_name, \
22181+}
22182+
22183+static struct au_sbi_attr au_sbi_attr_xino = AuSbiAttr(xino);
22184+#ifdef CONFIG_AUFS_EXPORT
22185+static struct au_sbi_attr au_sbi_attr_xigen = AuSbiAttr(xigen);
22186+#endif
22187+struct attribute *au_sbi_attrs[] = {
22188+ &au_sbi_attr_xino.attr,
22189+#ifdef CONFIG_AUFS_EXPORT
22190+ &au_sbi_attr_xigen.attr,
22191+#endif
22192+ NULL,
22193+};
22194+
22195+static struct sysfs_ops au_sbi_ops = {
22196+ .show = sysaufs_sbi_show
22197+};
22198+
22199+static struct kobj_type au_sbi_ktype = {
22200+ .release = au_si_free,
22201+ .sysfs_ops = &au_sbi_ops,
22202+ .default_attrs = au_sbi_attrs
22203+};
22204+
22205+/* ---------------------------------------------------------------------- */
22206+
22207+int sysaufs_si_init(struct au_sbinfo *sbinfo)
22208+{
22209+ int err;
22210+
22211+ sbinfo->si_kobj.kset = au_kset;
22212+ /* some people doesn't like to show a pointer in kernel */
22213+ err = kobject_init_and_add(&sbinfo->si_kobj, &au_sbi_ktype,
22214+ NULL/*&au_kset->kobj*/,
22215+ SysaufsSb_PREFIX "%lx",
22216+ au_si_mask ^ (unsigned long)sbinfo);
22217+ AuTraceErr(err);
22218+ return err;
22219+}
22220+
22221+
22222+/* ---------------------------------------------------------------------- */
22223+
22224+void sysaufs_fin(void)
22225+{
22226+ sysfs_remove_group(&au_kset->kobj, au_attr_group);
22227+ kset_unregister(au_kset);
22228+}
22229+
22230+int __init sysaufs_init(void)
22231+{
22232+ int err;
22233+
22234+ get_random_bytes(&au_si_mask, sizeof(au_si_mask));
22235+
22236+ au_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
22237+ err = PTR_ERR(au_kset);
22238+ if (IS_ERR(au_kset))
22239+ goto out;
22240+ err = sysfs_create_group(&au_kset->kobj, au_attr_group);
22241+ if (unlikely(err))
22242+ kset_unregister(au_kset);
22243+
22244+ out:
22245+ AuTraceErr(err);
22246+ return err;
22247+}
22248diff -urN linux/fs/aufs/sysaufs.h linux-aufs/fs/aufs/sysaufs.h
22249--- linux/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
22250+++ linux-aufs/fs/aufs/sysaufs.h 2009-03-12 16:18:04.000000000 +0100
22251@@ -0,0 +1,119 @@
22252+/*
22253+ * Copyright (C) 2005-2009 Junjiro Okajima
22254+ *
22255+ * This program, aufs is free software; you can redistribute it and/or modify
22256+ * it under the terms of the GNU General Public License as published by
22257+ * the Free Software Foundation; either version 2 of the License, or
22258+ * (at your option) any later version.
22259+ *
22260+ * This program is distributed in the hope that it will be useful,
22261+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22262+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22263+ * GNU General Public License for more details.
22264+ *
22265+ * You should have received a copy of the GNU General Public License
22266+ * along with this program; if not, write to the Free Software
22267+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22268+ */
22269+
22270+/*
22271+ * sysfs interface and lifetime management
22272+ *
22273+ * $Id$
22274+ */
22275+
22276+#ifndef __SYSAUFS_H__
22277+#define __SYSAUFS_H__
22278+
22279+#ifdef __KERNEL__
22280+
22281+#include <linux/fs.h>
22282+#include <linux/sysfs.h>
22283+#include "module.h"
22284+#include "super.h"
22285+
22286+#define SysaufsSb_PREFIX "si_" /* followed by %p */
22287+
22288+struct au_sbi_attr {
22289+ struct attribute attr;
22290+ int (*show)(struct seq_file *seq, struct super_block *sb);
22291+};
22292+
22293+/* ---------------------------------------------------------------------- */
22294+
22295+/* sysaufs.c */
22296+extern unsigned long au_si_mask;
22297+extern struct kset *au_kset;
22298+extern struct attribute *au_sbi_attrs[];
22299+int sysaufs_si_init(struct au_sbinfo *sbinfo);
22300+int __init sysaufs_init(void);
22301+void sysaufs_fin(void);
22302+
22303+/* ---------------------------------------------------------------------- */
22304+
22305+struct au_branch;
22306+#ifdef CONFIG_SYSFS
22307+/* sysfs.c */
22308+extern struct attribute_group *au_attr_group;
22309+extern struct kobj_type *au_ktype;
22310+
22311+int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb);
22312+#ifdef CONFIG_AUFS_EXPORT
22313+int sysaufs_sbi_xigen(struct seq_file *seq, struct super_block *sb);
22314+#endif
22315+int sysaufs_sbi_mntpnt1(struct seq_file *seq, struct super_block *sb);
22316+ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr,
22317+ char *buf);
22318+
22319+void sysaufs_br_init(struct au_branch *br);
22320+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
22321+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
22322+#else
22323+#define au_attr_group NULL
22324+#define au_ktype NULL
22325+
22326+static inline
22327+int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb)
22328+{
22329+ return 0;
22330+}
22331+
22332+#ifdef CONFIG_AUFS_EXPORT
22333+static inline
22334+int sysaufs_sbi_xigen(struct seq_file *seq, struct super_block *sb)
22335+{
22336+ return 0;
22337+}
22338+#endif
22339+
22340+static inline
22341+int sysaufs_sbi_mntpnt1(struct seq_file *seq, struct super_block *sb)
22342+{
22343+ return 0;
22344+}
22345+
22346+static inline
22347+ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr,
22348+ char *buf)
22349+{
22350+ return 0;
22351+}
22352+
22353+static inline void sysaufs_br_init(struct au_branch *br)
22354+{
22355+ /* empty */
22356+}
22357+
22358+static inline void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
22359+{
22360+ /* nothing */
22361+}
22362+
22363+static inline void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
22364+{
22365+ /* nothing */
22366+}
22367+#endif /* CONFIG_SYSFS */
22368+
22369+#endif /* __KERNEL__ */
22370+#endif /* __SYSAUFS_H__ */
22371diff -urN linux/fs/aufs/sysfs.c linux-aufs/fs/aufs/sysfs.c
22372--- linux/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
22373+++ linux-aufs/fs/aufs/sysfs.c 2009-03-12 16:18:04.000000000 +0100
22374@@ -0,0 +1,533 @@
22375+/*
22376+ * Copyright (C) 2005-2009 Junjiro Okajima
22377+ *
22378+ * This program, aufs is free software; you can redistribute it and/or modify
22379+ * it under the terms of the GNU General Public License as published by
22380+ * the Free Software Foundation; either version 2 of the License, or
22381+ * (at your option) any later version.
22382+ *
22383+ * This program is distributed in the hope that it will be useful,
22384+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22385+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22386+ * GNU General Public License for more details.
22387+ *
22388+ * You should have received a copy of the GNU General Public License
22389+ * along with this program; if not, write to the Free Software
22390+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22391+ */
22392+
22393+/*
22394+ * sysfs interface
22395+ *
22396+ * $Id$
22397+ */
22398+
22399+#include <linux/fs.h>
22400+#include <linux/module.h>
22401+#include <linux/seq_file.h>
22402+#include <linux/sysfs.h>
22403+#include "aufs.h"
22404+
22405+
22406+#ifdef CONFIG_AUFS_LOCAL
22407+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
22408+ char *buf)
22409+{
22410+#define conf_bool(name) "CONFIG_AUFS_" #name "=y\n"
22411+ static const char opt[] =
22412+#ifdef CONFIG_AUFS
22413+ "CONFIG_AUFS=y\n"
22414+#else
22415+ "CONFIG_AUFS=m\n"
22416+#endif
22417+#ifdef CONFIG_AUFS_BRANCH_MAX_127
22418+ conf_bool(BRANCH_MAX_127)
22419+#elif defined(CONFIG_AUFS_BRANCH_MAX_511)
22420+ conf_bool(BRANCH_MAX_511)
22421+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
22422+ conf_bool(BRANCH_MAX_1023)
22423+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
22424+ conf_bool(BRANCH_MAX_32767)
22425+#endif
22426+#ifdef CONFIG_AUFS_STAT
22427+ conf_bool(STAT)
22428+#endif
22429+#ifdef CONFIG_AUFS_HINOTIFY
22430+ conf_bool(HINOTIFY)
22431+#endif
22432+#ifdef CONFIG_AUFS_EXPORT
22433+ conf_bool(EXPORT)
22434+#endif
22435+#ifdef CONFIG_AUFS_INO_T_64
22436+ conf_bool(INO_T_64)
22437+#endif
22438+#ifdef CONFIG_AUFS_ROBR
22439+ conf_bool(ROBR)
22440+#endif
22441+#ifdef CONFIG_AUFS_DLGT
22442+ conf_bool(DLGT)
22443+#endif
22444+#ifdef CONFIG_AUFS_HIN_OR_DLGT
22445+ conf_bool(HIN_OR_DLGT)
22446+#endif
22447+#ifdef CONFIG_AUFS_SHWH
22448+ conf_bool(SHWH)
22449+#endif
22450+#ifdef CONFIG_AUFS_RR_SQUASHFS
22451+ conf_bool(RR_SQUASHFS)
22452+#endif
22453+#ifdef CONFIG_AUFS_SEC_PERM_PATCH
22454+ conf_bool(SEC_PERM_PATCH)
22455+#endif
22456+#ifdef CONFIG_AUFS_SPLICE_PATCH
22457+ conf_bool(SPLICE_PATCH)
22458+#endif
22459+#ifdef CONFIG_AUFS_LHASH_PATCH
22460+ conf_bool(LHASH_PATCH)
22461+#endif
22462+#ifdef CONFIG_AUFS_PUT_FILP_PATCH
22463+ conf_bool(PUT_FILP_PATCH)
22464+#endif
22465+#ifdef CONFIG_AUFS_BR_NFS
22466+ conf_bool(BR_NFS)
22467+#endif
22468+#ifdef CONFIG_AUFS_BR_NFS_V4
22469+ conf_bool(BR_NFS_V4)
22470+#endif
22471+#ifdef CONFIG_AUFS_BR_XFS
22472+ conf_bool(BR_XFS)
22473+#endif
22474+#ifdef CONFIG_AUFS_FSYNC_SUPER_PATCH
22475+ conf_bool(FSYNC_SUPER_PATCH)
22476+#endif
22477+#ifdef CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH
22478+ conf_bool(DENY_WRITE_ACCESS_PATCH)
22479+#endif
22480+#ifdef CONFIG_AUFS_KSIZE_PATCH
22481+ conf_bool(KSIZE_PATCH)
22482+#endif
22483+#ifdef CONFIG_AUFS_WORKAROUND_FUSE
22484+ conf_bool(WORKAROUND_FUSE)
22485+#endif
22486+#ifdef CONFIG_AUFS_GETATTR
22487+ conf_bool(GETATTR)
22488+#endif
22489+#ifdef CONFIG_AUFS_DEBUG
22490+ conf_bool(DEBUG)
22491+#endif
22492+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
22493+ conf_bool(MAGIC_SYSRQ)
22494+#endif
22495+#ifdef CONFIG_AUFS_DEBUG_LOCK
22496+ conf_bool(DEBUG_LOCK)
22497+#endif
22498+#ifdef CONFIG_AUFS_COMPAT
22499+ conf_bool(COMPAT)
22500+#endif
22501+#ifdef CONFIG_AUFS_UNIONFS22_PATCH
22502+ conf_bool(UNIONFS22_PATCH)
22503+#endif
22504+#ifdef CONFIG_AUFS_UNIONFS23_PATCH
22505+ conf_bool(UNIONFS23_PATCH)
22506+#endif
22507+ ;
22508+#undef conf_bool
22509+
22510+ char *p = buf;
22511+ const char *end = buf + PAGE_SIZE;
22512+
22513+ p += snprintf(p, end - p, "%s", opt);
22514+#ifdef DbgUdbaRace
22515+ if (p < end)
22516+ p += snprintf(p, end - p, "DbgUdbaRace=%d\n", DbgUdbaRace);
22517+#endif
22518+ if (p < end)
22519+ return p - buf;
22520+ else
22521+ return -EFBIG;
22522+}
22523+
22524+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
22525+#endif
22526+
22527+#ifdef CONFIG_AUFS_STAT
22528+static ssize_t stat_show(struct kobject *kobj, struct kobj_attribute *attr,
22529+ char *buf)
22530+{
22531+ char *p = buf;
22532+ const char *end = buf + PAGE_SIZE;
22533+ int i;
22534+
22535+ p += snprintf(p, end - p, "wkq max_busy:");
22536+ for (i = 0; p < end && i < aufs_nwkq; i++)
22537+ p += snprintf(p, end - p, " %u", au_wkq[i].max_busy);
22538+ if (p < end)
22539+ p += snprintf(p, end - p, ", %u(generic)\n",
22540+ au_wkq[aufs_nwkq].max_busy);
22541+
22542+ if (p < end)
22543+ return p - buf;
22544+ else
22545+ return -EFBIG;
22546+}
22547+
22548+static struct kobj_attribute au_stat_attr = __ATTR_RO(stat);
22549+#endif
22550+
22551+#ifdef CONFIG_AUFS_DEBUG
22552+static ssize_t debug_show(struct kobject *kobj, struct kobj_attribute *attr,
22553+ char *buf)
22554+{
22555+ return sprintf(buf, "%d\n", au_debug_test());
22556+}
22557+
22558+static ssize_t debug_store(struct kobject *kobj, struct kobj_attribute *attr,
22559+ const char *buf, size_t sz)
22560+{
22561+ LKTRTrace("%.*s\n", (unsigned int)sz, buf);
22562+
22563+ if (unlikely(!sz || (*buf != '0' && *buf != '1')))
22564+ return -EOPNOTSUPP;
22565+
22566+ if (*buf == '0')
22567+ au_debug_off();
22568+ else if (*buf == '1')
22569+ au_debug_on();
22570+ return sz;
22571+}
22572+
22573+static struct kobj_attribute au_debug_attr = __ATTR(debug, S_IRUGO | S_IWUSR,
22574+ debug_show, debug_store);
22575+#endif
22576+
22577+static struct attribute *au_attr[] = {
22578+#ifdef CONFIG_AUFS_LOCAL
22579+ &au_config_attr.attr,
22580+#endif
22581+#ifdef CONFIG_AUFS_STAT
22582+ &au_stat_attr.attr,
22583+#endif
22584+#ifdef CONFIG_AUFS_DEBUG
22585+ &au_debug_attr.attr,
22586+#endif
22587+ NULL, /* need to NULL terminate the list of attributes */
22588+};
22589+
22590+static struct attribute_group au_attr_group_body = {
22591+ .attrs = au_attr
22592+};
22593+
22594+struct attribute_group *au_attr_group = &au_attr_group_body;
22595+
22596+/* ---------------------------------------------------------------------- */
22597+
22598+/*
22599+ * they are copied from linux/lib/kobject.c,
22600+ * and will be exported in the future.
22601+ */
22602+static ssize_t au_attr_show(struct kobject *kobj, struct attribute *attr,
22603+ char *buf)
22604+{
22605+ struct kobj_attribute *kattr;
22606+ ssize_t ret = -EIO;
22607+
22608+ kattr = container_of(attr, struct kobj_attribute, attr);
22609+ if (kattr->show)
22610+ ret = kattr->show(kobj, kattr, buf);
22611+ return ret;
22612+}
22613+
22614+#ifdef CONFIG_AUFS_DEBUG
22615+static ssize_t au_attr_store(struct kobject *kobj, struct attribute *attr,
22616+ const char *buf, size_t count)
22617+{
22618+ struct kobj_attribute *kattr;
22619+ ssize_t ret = -EIO;
22620+
22621+ kattr = container_of(attr, struct kobj_attribute, attr);
22622+ if (kattr->store)
22623+ ret = kattr->store(kobj, kattr, buf, count);
22624+ return ret;
22625+}
22626+#endif
22627+
22628+static struct sysfs_ops sysaufs_ops = {
22629+ .show = au_attr_show,
22630+#ifdef CONFIG_AUFS_DEBUG
22631+ .store = au_attr_store
22632+#endif
22633+};
22634+
22635+static struct kobj_type au_ktype_body = {
22636+ .sysfs_ops = &sysaufs_ops
22637+};
22638+struct kobj_type *au_ktype = &au_ktype_body;
22639+
22640+/* ---------------------------------------------------------------------- */
22641+
22642+static noinline_for_stack
22643+int sysaufs_sbi_xi(struct seq_file *seq, struct file *xf, int dlgt,
22644+ int print_path)
22645+{
22646+ int err;
22647+ struct kstat st;
22648+ struct path path;
22649+
22650+ err = vfsub_getattr(xf->f_vfsmnt, xf->f_dentry, &st, dlgt);
22651+ if (!err) {
22652+ seq_printf(seq, "%llux%lu %lld",
22653+ st.blocks, st.blksize, (long long)st.size);
22654+ if (print_path) {
22655+ path.dentry = xf->f_dentry;
22656+ path.mnt = xf->f_vfsmnt;
22657+ seq_putc(seq, ' ');
22658+ seq_path(seq, &path, au_esc_chars);
22659+ }
22660+ seq_putc(seq, '\n');
22661+ } else
22662+ seq_printf(seq, "err %d\n", err);
22663+
22664+ AuTraceErr(err);
22665+ return err;
22666+}
22667+
22668+int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb)
22669+{
22670+ int err;
22671+ unsigned int mnt_flags;
22672+ aufs_bindex_t bend, bindex;
22673+ unsigned char dlgt, xinodir;
22674+ struct kstat st;
22675+ struct path path;
22676+ struct au_sbinfo *sbinfo;
22677+ struct file *xf;
22678+
22679+ AuTraceEnter();
22680+
22681+ sbinfo = au_sbi(sb);
22682+ mnt_flags = au_mntflags(sb);
22683+ xinodir = !!au_opt_test(mnt_flags, XINODIR);
22684+ if (!au_opt_test_xino(mnt_flags)) {
22685+#ifdef CONFIG_AUFS_DEBUG
22686+ AuDebugOn(sbinfo->si_xib);
22687+ bend = au_sbend(sb);
22688+ for (bindex = 0; bindex <= bend; bindex++)
22689+ AuDebugOn(au_sbr(sb, bindex)->br_xino.xi_file);
22690+#endif
22691+ err = 0;
22692+ goto out; /* success */
22693+ }
22694+
22695+ dlgt = !!au_test_dlgt(mnt_flags);
22696+ err = sysaufs_sbi_xi(seq, sbinfo->si_xib, dlgt, xinodir);
22697+
22698+ bend = au_sbend(sb);
22699+ for (bindex = 0; !err && bindex <= bend; bindex++) {
22700+ xf = au_sbr(sb, bindex)->br_xino.xi_file;
22701+ if (!xf)
22702+ continue;
22703+ seq_printf(seq, "%d: ", bindex);
22704+ err = vfsub_getattr(xf->f_vfsmnt, xf->f_dentry, &st, dlgt);
22705+ if (!err) {
22706+ seq_printf(seq, "%ld, %llux%lu %lld",
22707+ (long)file_count(xf), st.blocks, st.blksize,
22708+ (long long)st.size);
22709+ if (xinodir) {
22710+ path.dentry = xf->f_dentry;
22711+ path.mnt = xf->f_vfsmnt;
22712+ seq_putc(seq, ' ');
22713+ seq_path(seq, &path, au_esc_chars);
22714+ }
22715+ seq_putc(seq, '\n');
22716+ } else
22717+ seq_printf(seq, "err %d\n", err);
22718+ }
22719+
22720+ out:
22721+ AuTraceErr(err);
22722+ return err;
22723+}
22724+
22725+#ifdef CONFIG_AUFS_EXPORT
22726+int sysaufs_sbi_xigen(struct seq_file *seq, struct super_block *sb)
22727+{
22728+ int err;
22729+ unsigned int mnt_flags;
22730+ struct au_sbinfo *sbinfo;
22731+
22732+ AuTraceEnter();
22733+
22734+ err = 0;
22735+ sbinfo = au_sbi(sb);
22736+ mnt_flags = au_mntflags(sb);
22737+ if (au_opt_test_xino(mnt_flags))
22738+ err = sysaufs_sbi_xi(seq, sbinfo->si_xigen,
22739+ !!au_opt_test(mnt_flags, DLGT),
22740+ !!au_opt_test(mnt_flags, XINODIR));
22741+
22742+ AuTraceErr(err);
22743+ return err;
22744+}
22745+#endif
22746+
22747+/*
22748+ * the lifetime of branch is independent from the entry under sysfs.
22749+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
22750+ * unlinked.
22751+ */
22752+#define SysaufsBr_PREFIX "br"
22753+static int sysaufs_sbi_br(struct seq_file *seq, struct super_block *sb,
22754+ aufs_bindex_t bindex)
22755+{
22756+ int err;
22757+ struct dentry *root;
22758+ struct au_branch *br;
22759+ struct path path;
22760+
22761+ LKTRTrace("b%d\n", bindex);
22762+
22763+ err = -ENOENT;
22764+ if (unlikely(au_sbend(sb) < bindex))
22765+ goto out;
22766+
22767+ err = 0;
22768+ root = sb->s_root;
22769+ di_read_lock_parent(root, !AuLock_IR);
22770+ br = au_sbr(sb, bindex);
22771+ path.mnt = br->br_mnt;
22772+ path.dentry = au_h_dptr(root, bindex);
22773+ seq_path(seq, &path, au_esc_chars);
22774+ di_read_unlock(root, !AuLock_IR);
22775+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
22776+
22777+ out:
22778+ AuTraceErr(err);
22779+ return err;
22780+}
22781+
22782+/* ---------------------------------------------------------------------- */
22783+
22784+static struct seq_file *au_seq(char *p, ssize_t len)
22785+{
22786+ struct seq_file *seq;
22787+
22788+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
22789+ if (seq) {
22790+ /* todo: necessary? */
22791+ /* mutex_init(&seq.lock); */
22792+ seq->buf = p;
22793+ seq->size = len;
22794+ return seq; /* success */
22795+ }
22796+
22797+ seq = ERR_PTR(-ENOMEM);
22798+ AuTraceErrPtr(seq);
22799+ return seq;
22800+}
22801+
22802+/* todo: file size may exceed PAGE_SIZE */
22803+ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr,
22804+ char *buf)
22805+{
22806+ ssize_t err;
22807+ long l;
22808+ struct au_sbinfo *sbinfo;
22809+ struct super_block *sb;
22810+ struct seq_file *seq;
22811+ char *name;
22812+ struct attribute **cattr;
22813+
22814+ LKTRTrace("%s/%s\n", kobject_name(kobj), attr->name);
22815+
22816+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
22817+ sb = sbinfo->si_sb;
22818+ si_noflush_read_lock(sb);
22819+
22820+ seq = au_seq(buf, PAGE_SIZE);
22821+ err = PTR_ERR(seq);
22822+ if (IS_ERR(seq))
22823+ goto out;
22824+
22825+ name = (void *)attr->name;
22826+ cattr = au_sbi_attrs;
22827+ while (*cattr) {
22828+ if (!strcmp(name, (*cattr)->name)) {
22829+ err = container_of(*cattr, struct au_sbi_attr, attr)
22830+ ->show(seq, sb);
22831+ goto out_seq;
22832+ }
22833+ cattr++;
22834+ }
22835+
22836+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
22837+ name += sizeof(SysaufsBr_PREFIX) - 1;
22838+ err = strict_strtol(name, 10, &l);
22839+ if (!err)
22840+ err = sysaufs_sbi_br(seq, sb, (aufs_bindex_t)l);
22841+ goto out_seq;
22842+ }
22843+ BUG();
22844+
22845+ out_seq:
22846+ if (!err) {
22847+ err = seq->count;
22848+ /* sysfs limit */
22849+ if (unlikely(err == PAGE_SIZE))
22850+ err = -EFBIG;
22851+ }
22852+ kfree(seq);
22853+ out:
22854+ si_read_unlock(sb);
22855+ AuTraceErr(err);
22856+ return err;
22857+}
22858+
22859+/* ---------------------------------------------------------------------- */
22860+
22861+void sysaufs_br_init(struct au_branch *br)
22862+{
22863+ br->br_attr.name = br->br_name;
22864+ br->br_attr.mode = S_IRUGO;
22865+ br->br_attr.owner = THIS_MODULE;
22866+}
22867+
22868+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
22869+{
22870+ struct au_sbinfo *sbinfo;
22871+ aufs_bindex_t bend;
22872+
22873+ LKTRTrace("b%d\n", bindex);
22874+
22875+ if (!sysaufs_brs)
22876+ return;
22877+
22878+ sbinfo = au_sbi(sb);
22879+ bend = au_sbend(sb);
22880+ for (; bindex <= bend; bindex++)
22881+ sysfs_remove_file(&sbinfo->si_kobj,
22882+ &au_sbr(sb, bindex)->br_attr);
22883+}
22884+
22885+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
22886+{
22887+ int err;
22888+ struct kobject *kobj;
22889+ aufs_bindex_t bend;
22890+ struct au_branch *br;
22891+
22892+ LKTRTrace("b%d\n", bindex);
22893+
22894+ if (!sysaufs_brs)
22895+ return;
22896+
22897+ kobj = &au_sbi(sb)->si_kobj;
22898+ bend = au_sbend(sb);
22899+ for (; bindex <= bend; bindex++) {
22900+ br = au_sbr(sb, bindex);
22901+ snprintf(br->br_name, sizeof(br->br_name),
22902+ SysaufsBr_PREFIX "%d", bindex);
22903+ err = sysfs_create_file(kobj, &br->br_attr);
22904+ if (unlikely(err))
22905+ AuWarn("failed %s under sysfs(%d)\n", br->br_name, err);
22906+ }
22907+}
22908diff -urN linux/fs/aufs/sysrq.c linux-aufs/fs/aufs/sysrq.c
22909--- linux/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
22910+++ linux-aufs/fs/aufs/sysrq.c 2009-03-12 16:18:04.000000000 +0100
22911@@ -0,0 +1,280 @@
22912+/*
22913+ * Copyright (C) 2005-2009 Junjiro Okajima
22914+ *
22915+ * This program, aufs is free software; you can redistribute it and/or modify
22916+ * it under the terms of the GNU General Public License as published by
22917+ * the Free Software Foundation; either version 2 of the License, or
22918+ * (at your option) any later version.
22919+ *
22920+ * This program is distributed in the hope that it will be useful,
22921+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22922+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22923+ * GNU General Public License for more details.
22924+ *
22925+ * You should have received a copy of the GNU General Public License
22926+ * along with this program; if not, write to the Free Software
22927+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22928+ */
22929+
22930+/*
22931+ * magic sysrq hanlder
22932+ *
22933+ * $Id$
22934+ */
22935+
22936+#include <linux/fs.h>
22937+#include <linux/module.h>
22938+#include <linux/moduleparam.h>
22939+/* #include <linux/sysrq.h> */
22940+#include "aufs.h"
22941+
22942+#ifdef CONFIG_AUFS_DEBUG_LOCK
22943+struct au_dbg_lock {
22944+ struct list_head list;
22945+ union {
22946+ struct super_block *sb;
22947+ struct dentry *dentry;
22948+ struct inode *inode;
22949+ void *any;
22950+ };
22951+ int flags;
22952+ unsigned int lsc;
22953+ pid_t pid;
22954+};
22955+
22956+static void au_dbg_reg(struct au_splhead *spl, void *any, int flags,
22957+ unsigned int lsc)
22958+{
22959+ struct au_dbg_lock *p = kmalloc(sizeof(*p), GFP_NOFS);
22960+
22961+ if (p) {
22962+ p->any = any;
22963+ p->flags = flags;
22964+ p->lsc = lsc;
22965+ p->pid = current->pid;
22966+ spin_lock(&spl->spin);
22967+ list_add(&p->list, &spl->head);
22968+ spin_unlock(&spl->spin);
22969+ }
22970+ WARN_ON(!p);
22971+}
22972+
22973+static void au_dbg_unreg(struct au_splhead *spl, void *any, int flags)
22974+{
22975+ struct au_dbg_lock *p, *tmp, *found;
22976+ struct list_head *head = &spl->head;
22977+ const pid_t pid = current->pid;
22978+
22979+ found = NULL;
22980+ spin_lock(&spl->spin);
22981+ list_for_each_entry_safe(p, tmp, head, list)
22982+ if (p->any == any && p->pid == pid) {
22983+ list_del(&p->list);
22984+ found = p;
22985+ break;
22986+ }
22987+ spin_unlock(&spl->spin);
22988+ kfree(found);
22989+ WARN_ON(!found);
22990+}
22991+
22992+/* ---------------------------------------------------------------------- */
22993+
22994+void au_dbg_locking_si_reg(struct super_block *sb, int flags)
22995+{
22996+ au_dbg_reg(au_sbi(sb)->si_dbg_lock + AuDbgLock_SI_LOCKING, sb, flags,
22997+ -1);
22998+}
22999+
23000+void au_dbg_locking_si_unreg(struct super_block *sb, int flags)
23001+{
23002+ au_dbg_unreg(au_sbi(sb)->si_dbg_lock + AuDbgLock_SI_LOCKING, sb, flags);
23003+}
23004+
23005+void au_dbg_locked_si_reg(struct super_block *sb, int flags)
23006+{
23007+ au_dbg_reg(au_sbi(sb)->si_dbg_lock + AuDbgLock_SI_LOCKED, sb, flags,
23008+ -1);
23009+}
23010+
23011+void au_dbg_locked_si_unreg(struct super_block *sb, int flags)
23012+{
23013+ au_dbg_unreg(au_sbi(sb)->si_dbg_lock + AuDbgLock_SI_LOCKED, sb, flags);
23014+}
23015+
23016+void au_dbg_locking_di_reg(struct dentry *d, int flags, unsigned int lsc)
23017+{
23018+ au_dbg_reg(au_sbi(d->d_sb)->si_dbg_lock + AuDbgLock_DI_LOCKING, d,
23019+ flags, lsc);
23020+}
23021+
23022+void au_dbg_locking_di_unreg(struct dentry *d, int flags)
23023+{
23024+ au_dbg_unreg(au_sbi(d->d_sb)->si_dbg_lock + AuDbgLock_DI_LOCKING, d,
23025+ flags);
23026+}
23027+
23028+void au_dbg_locked_di_reg(struct dentry *d, int flags, unsigned int lsc)
23029+{
23030+ au_dbg_reg(au_sbi(d->d_sb)->si_dbg_lock + AuDbgLock_DI_LOCKED, d, flags,
23031+ lsc);
23032+}
23033+
23034+void au_dbg_locked_di_unreg(struct dentry *d, int flags)
23035+{
23036+ au_dbg_unreg(au_sbi(d->d_sb)->si_dbg_lock + AuDbgLock_DI_LOCKED, d,
23037+ flags);
23038+}
23039+
23040+void au_dbg_locking_ii_reg(struct inode *i, int flags, unsigned int lsc)
23041+{
23042+ au_dbg_reg(au_sbi(i->i_sb)->si_dbg_lock + AuDbgLock_II_LOCKING, i,
23043+ flags, lsc);
23044+}
23045+
23046+void au_dbg_locking_ii_unreg(struct inode *i, int flags)
23047+{
23048+ au_dbg_unreg(au_sbi(i->i_sb)->si_dbg_lock + AuDbgLock_II_LOCKING, i,
23049+ flags);
23050+}
23051+
23052+void au_dbg_locked_ii_reg(struct inode *i, int flags, unsigned int lsc)
23053+{
23054+ au_dbg_reg(au_sbi(i->i_sb)->si_dbg_lock + AuDbgLock_II_LOCKED, i, flags,
23055+ lsc);
23056+}
23057+
23058+void au_dbg_locked_ii_unreg(struct inode *i, int flags)
23059+{
23060+ au_dbg_unreg(au_sbi(i->i_sb)->si_dbg_lock + AuDbgLock_II_LOCKED, i,
23061+ flags);
23062+}
23063+#endif /* CONFIG_AUFS_DEBUG_LOCK */
23064+
23065+/* ---------------------------------------------------------------------- */
23066+
23067+static void sysrq_sb(struct super_block *sb)
23068+{
23069+ char *plevel;
23070+ struct inode *i;
23071+ struct au_sbinfo *sbinfo;
23072+ struct file *file;
23073+
23074+ plevel = au_plevel;
23075+ au_plevel = KERN_WARNING;
23076+ au_debug_on();
23077+
23078+ sbinfo = au_sbi(sb);
23079+ pr_warning("si=%lx\n", au_si_mask ^ (unsigned long)sbinfo);
23080+ pr_warning(AUFS_NAME ": superblock\n");
23081+ au_dpri_sb(sb);
23082+ pr_warning(AUFS_NAME ": root dentry\n");
23083+ au_dpri_dentry(sb->s_root);
23084+ pr_warning(AUFS_NAME ": root inode\n");
23085+ au_dpri_inode(sb->s_root->d_inode);
23086+ pr_warning(AUFS_NAME ": isolated inode\n");
23087+ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
23088+ if (list_empty(&i->i_dentry))
23089+ au_dpri_inode(i);
23090+ pr_warning(AUFS_NAME ": files\n");
23091+ list_for_each_entry(file, &sb->s_files, f_u.fu_list)
23092+ if (au_test_aufs_file(file))
23093+ au_dpri_file(file);
23094+
23095+#ifdef CONFIG_AUFS_DEBUG_LOCK
23096+ {
23097+ struct au_dbg_lock *p;
23098+ struct list_head *head;
23099+
23100+ pr_warning(AUFS_NAME ": locking si\n");
23101+ head = &sbinfo->si_dbg_lock[AuDbgLock_SI_LOCKING].head;
23102+ list_for_each_entry(p, head, list)
23103+ pr_warning("pid: %d, 0x%x\n", p->pid, p->flags);
23104+ pr_warning(AUFS_NAME ": locked si\n");
23105+ head = &sbinfo->si_dbg_lock[AuDbgLock_SI_LOCKED].head;
23106+ list_for_each_entry(p, head, list)
23107+ pr_warning("pid: %d, 0x%x\n", p->pid, p->flags);
23108+ pr_warning(AUFS_NAME ": locking di\n");
23109+ head = &sbinfo->si_dbg_lock[AuDbgLock_DI_LOCKING].head;
23110+ list_for_each_entry(p, head, list) {
23111+ pr_warning("pid: %d, 0x%x, %d\n",
23112+ p->pid, p->flags, p->lsc);
23113+ au_dpri_dentry(p->dentry);
23114+ }
23115+ pr_warning(AUFS_NAME ": locked di\n");
23116+ head = &sbinfo->si_dbg_lock[AuDbgLock_DI_LOCKED].head;
23117+ list_for_each_entry(p, head, list) {
23118+ pr_warning("pid: %d, 0x%x, %d\n",
23119+ p->pid, p->flags, p->lsc);
23120+ au_dpri_dentry(p->dentry);
23121+ }
23122+ pr_warning(AUFS_NAME ": locking ii\n");
23123+ head = &sbinfo->si_dbg_lock[AuDbgLock_II_LOCKING].head;
23124+ list_for_each_entry(p, head, list) {
23125+ pr_warning("pid: %d, %d\n", p->pid, p->lsc);
23126+ au_dpri_inode(p->inode);
23127+ }
23128+ pr_warning(AUFS_NAME ": locked ii\n");
23129+ head = &sbinfo->si_dbg_lock[AuDbgLock_II_LOCKED].head;
23130+ list_for_each_entry(p, head, list) {
23131+ pr_warning("pid: %d, %d\n", p->pid, p->lsc);
23132+ au_dpri_inode(p->inode);
23133+ }
23134+ }
23135+#endif
23136+
23137+ au_plevel = plevel;
23138+ au_debug_off();
23139+}
23140+
23141+/* ---------------------------------------------------------------------- */
23142+
23143+/* module parameter */
23144+static char *aufs_sysrq_key = "a";
23145+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
23146+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
23147+
23148+static void au_sysrq(int key, struct tty_struct *tty)
23149+{
23150+ struct kobject *kobj;
23151+ struct au_sbinfo *sbinfo;
23152+
23153+ /* spin_lock(&au_kset->list_lock); */
23154+ list_for_each_entry(kobj, &au_kset->list, entry) {
23155+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
23156+ sysrq_sb(sbinfo->si_sb);
23157+ }
23158+ /* spin_unlock(&au_kset->list_lock); */
23159+}
23160+
23161+static struct sysrq_key_op au_sysrq_op = {
23162+ .handler = au_sysrq,
23163+ .help_msg = "Aufs",
23164+ .action_msg = "Aufs",
23165+ /* todo: test mask? */
23166+ .enable_mask = SYSRQ_ENABLE_DUMP
23167+};
23168+
23169+/* ---------------------------------------------------------------------- */
23170+
23171+int __init au_sysrq_init(void)
23172+{
23173+ int err;
23174+ char key;
23175+
23176+ err = -1;
23177+ key = *aufs_sysrq_key;
23178+ if ('a' <= key && key <= 'z')
23179+ err = register_sysrq_key(key, &au_sysrq_op);
23180+ if (unlikely(err))
23181+ AuErr("err %d, sysrq=%c\n", err, key);
23182+ return err;
23183+}
23184+
23185+void au_sysrq_fin(void)
23186+{
23187+ int err;
23188+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
23189+ if (unlikely(err))
23190+ AuErr("err %d (ignored)\n", err);
23191+}
23192diff -urN linux/fs/aufs/vdir.c linux-aufs/fs/aufs/vdir.c
23193--- linux/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
23194+++ linux-aufs/fs/aufs/vdir.c 2009-03-12 16:18:04.000000000 +0100
23195@@ -0,0 +1,941 @@
23196+/*
23197+ * Copyright (C) 2005-2009 Junjiro Okajima
23198+ *
23199+ * This program, aufs is free software; you can redistribute it and/or modify
23200+ * it under the terms of the GNU General Public License as published by
23201+ * the Free Software Foundation; either version 2 of the License, or
23202+ * (at your option) any later version.
23203+ *
23204+ * This program is distributed in the hope that it will be useful,
23205+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23206+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23207+ * GNU General Public License for more details.
23208+ *
23209+ * You should have received a copy of the GNU General Public License
23210+ * along with this program; if not, write to the Free Software
23211+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23212+ */
23213+
23214+/*
23215+ * virtual or vertical directory
23216+ *
23217+ * $Id$
23218+ */
23219+
23220+#include "aufs.h"
23221+
23222+static int calc_size(int namelen)
23223+{
23224+ int sz;
23225+
23226+ sz = sizeof(struct au_vdir_de) + namelen;
23227+ if (sizeof(ino_t) == sizeof(long)) {
23228+ const int mask = sizeof(ino_t) - 1;
23229+ if (sz & mask) {
23230+ sz += sizeof(ino_t);
23231+ sz &= ~mask;
23232+ }
23233+ }
23234+
23235+ AuDebugOn(sz % sizeof(ino_t));
23236+ return sz;
23237+}
23238+
23239+static int set_deblk_end(union au_vdir_deblk_p *p,
23240+ union au_vdir_deblk_p *deblk_end)
23241+{
23242+ if (calc_size(0) <= deblk_end->p - p->p) {
23243+ p->de->de_str.len = 0;
23244+ /* smp_mb(); */
23245+ return 0;
23246+ }
23247+ return -1; /* error */
23248+}
23249+
23250+/* returns true or false */
23251+static int is_deblk_end(union au_vdir_deblk_p *p,
23252+ union au_vdir_deblk_p *deblk_end)
23253+{
23254+ if (calc_size(0) <= deblk_end->p - p->p)
23255+ return !p->de->de_str.len;
23256+ return 1;
23257+}
23258+
23259+static au_vdir_deblk_t *last_deblk(struct au_vdir *vdir)
23260+{
23261+ return vdir->vd_deblk[vdir->vd_nblk - 1];
23262+}
23263+
23264+void au_nhash_init(struct au_nhash *nhash)
23265+{
23266+ int i;
23267+ for (i = 0; i < AuSize_NHASH; i++)
23268+ INIT_HLIST_HEAD(nhash->heads + i);
23269+}
23270+
23271+struct au_nhash *au_nhash_new(gfp_t gfp)
23272+{
23273+ struct au_nhash *nhash;
23274+
23275+ nhash = kmalloc(sizeof(*nhash), gfp);
23276+ if (nhash) {
23277+ au_nhash_init(nhash);
23278+ return nhash;
23279+ }
23280+ return ERR_PTR(-ENOMEM);
23281+}
23282+
23283+void au_nhash_del(struct au_nhash *nhash)
23284+{
23285+ au_nhash_fin(nhash);
23286+ kfree(nhash);
23287+}
23288+
23289+void au_nhash_move(struct au_nhash *dst, struct au_nhash *src)
23290+{
23291+ int i;
23292+
23293+ AuTraceEnter();
23294+
23295+ *dst = *src;
23296+ for (i = 0; i < AuSize_NHASH; i++) {
23297+ struct hlist_head *h;
23298+ h = dst->heads + i;
23299+ if (h->first)
23300+ h->first->pprev = &h->first;
23301+ INIT_HLIST_HEAD(src->heads + i);
23302+ }
23303+ /* smp_mb(); */
23304+}
23305+
23306+/* ---------------------------------------------------------------------- */
23307+
23308+void au_nhash_fin(struct au_nhash *whlist)
23309+{
23310+ int i;
23311+ struct hlist_head *head;
23312+ struct au_vdir_wh *tpos;
23313+ struct hlist_node *pos, *n;
23314+
23315+ AuTraceEnter();
23316+
23317+ for (i = 0; i < AuSize_NHASH; i++) {
23318+ head = whlist->heads + i;
23319+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
23320+ /* hlist_del(pos); */
23321+ kfree(tpos);
23322+ }
23323+ }
23324+}
23325+
23326+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
23327+ int limit)
23328+{
23329+ int n, i;
23330+ struct hlist_head *head;
23331+ struct au_vdir_wh *tpos;
23332+ struct hlist_node *pos;
23333+
23334+ LKTRTrace("limit %d\n", limit);
23335+
23336+ n = 0;
23337+ for (i = 0; i < AuSize_NHASH; i++) {
23338+ head = whlist->heads + i;
23339+ hlist_for_each_entry(tpos, pos, head, wh_hash)
23340+ if (tpos->wh_bindex == btgt && ++n > limit)
23341+ return 1;
23342+ }
23343+ return 0;
23344+}
23345+
23346+static unsigned int au_name_hash(const unsigned char *name, unsigned int len)
23347+{
23348+ return full_name_hash(name, len) % AuSize_NHASH;
23349+}
23350+
23351+/* returns found(true) or not */
23352+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int namelen)
23353+{
23354+ struct hlist_head *head;
23355+ struct au_vdir_wh *tpos;
23356+ struct hlist_node *pos;
23357+ struct au_vdir_destr *str;
23358+
23359+ LKTRTrace("%.*s\n", namelen, name);
23360+
23361+ head = whlist->heads + au_name_hash(name, namelen);
23362+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
23363+ str = &tpos->wh_str;
23364+ LKTRTrace("%.*s\n", str->len, str->name);
23365+ if (str->len == namelen && !memcmp(str->name, name, namelen))
23366+ return 1;
23367+ }
23368+ return 0;
23369+}
23370+
23371+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int namelen,
23372+ ino_t ino, unsigned int d_type, aufs_bindex_t bindex,
23373+ unsigned char shwh)
23374+{
23375+ int err;
23376+ struct au_vdir_destr *str;
23377+ struct au_vdir_wh *wh;
23378+
23379+ LKTRTrace("%.*s\n", namelen, name);
23380+
23381+ err = -ENOMEM;
23382+ wh = kmalloc(sizeof(*wh) + namelen, GFP_NOFS);
23383+ if (unlikely(!wh))
23384+ goto out;
23385+ err = 0;
23386+ wh->wh_bindex = bindex;
23387+ if (shwh)
23388+ au_shwh_init_wh(wh, ino, d_type);
23389+ str = &wh->wh_str;
23390+ str->len = namelen;
23391+ memcpy(str->name, name, namelen);
23392+ hlist_add_head(&wh->wh_hash,
23393+ whlist->heads + au_name_hash(name, namelen));
23394+ /* smp_mb(); */
23395+
23396+ out:
23397+ AuTraceErr(err);
23398+ return err;
23399+}
23400+
23401+/* ---------------------------------------------------------------------- */
23402+
23403+void au_vdir_free(struct au_vdir *vdir)
23404+{
23405+ au_vdir_deblk_t **deblk;
23406+
23407+ AuTraceEnter();
23408+
23409+ deblk = vdir->vd_deblk;
23410+ while (vdir->vd_nblk--) {
23411+ kfree(*deblk);
23412+ deblk++;
23413+ }
23414+ kfree(vdir->vd_deblk);
23415+ au_cache_free_vdir(vdir);
23416+}
23417+
23418+static int append_deblk(struct au_vdir *vdir)
23419+{
23420+ int err, sz, i;
23421+ au_vdir_deblk_t **o;
23422+ union au_vdir_deblk_p p, deblk_end;
23423+
23424+ AuTraceEnter();
23425+
23426+ err = -ENOMEM;
23427+ sz = sizeof(*o) * vdir->vd_nblk;
23428+ o = au_kzrealloc(vdir->vd_deblk, sz, sz + sizeof(*o), GFP_NOFS);
23429+ if (unlikely(!o))
23430+ goto out;
23431+ vdir->vd_deblk = o;
23432+ p.deblk = kmalloc(sizeof(*p.deblk), GFP_NOFS);
23433+ if (p.deblk) {
23434+ i = vdir->vd_nblk++;
23435+ vdir->vd_deblk[i] = p.deblk;
23436+ vdir->vd_last.i = i;
23437+ vdir->vd_last.p.p = p.p;
23438+ deblk_end.deblk = p.deblk + 1;
23439+ err = set_deblk_end(&p, &deblk_end);
23440+ AuDebugOn(err);
23441+ }
23442+
23443+ out:
23444+ AuTraceErr(err);
23445+ return err;
23446+}
23447+
23448+static struct au_vdir *alloc_vdir(void)
23449+{
23450+ struct au_vdir *vdir;
23451+ int err;
23452+
23453+ AuTraceEnter();
23454+
23455+ err = -ENOMEM;
23456+ vdir = au_cache_alloc_vdir();
23457+ if (unlikely(!vdir))
23458+ goto out;
23459+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
23460+ if (unlikely(!vdir->vd_deblk))
23461+ goto out_free;
23462+
23463+ vdir->vd_nblk = 0;
23464+ vdir->vd_version = 0;
23465+ vdir->vd_jiffy = 0;
23466+ err = append_deblk(vdir);
23467+ if (!err)
23468+ return vdir; /* success */
23469+
23470+ kfree(vdir->vd_deblk);
23471+
23472+ out_free:
23473+ au_cache_free_vdir(vdir);
23474+ out:
23475+ vdir = ERR_PTR(err);
23476+ AuTraceErrPtr(vdir);
23477+ return vdir;
23478+}
23479+
23480+static int reinit_vdir(struct au_vdir *vdir)
23481+{
23482+ int err;
23483+ union au_vdir_deblk_p p, deblk_end;
23484+
23485+ AuTraceEnter();
23486+
23487+ while (vdir->vd_nblk > 1) {
23488+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
23489+ vdir->vd_deblk[vdir->vd_nblk - 1] = NULL;
23490+ vdir->vd_nblk--;
23491+ }
23492+ p.deblk = vdir->vd_deblk[0];
23493+ deblk_end.deblk = p.deblk + 1;
23494+ err = set_deblk_end(&p, &deblk_end);
23495+ AuDebugOn(err);
23496+ vdir->vd_version = 0;
23497+ vdir->vd_jiffy = 0;
23498+ vdir->vd_last.i = 0;
23499+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
23500+ /* smp_mb(); */
23501+ return err;
23502+}
23503+
23504+/* ---------------------------------------------------------------------- */
23505+
23506+static void free_dehlist(struct au_nhash *dehlist)
23507+{
23508+ int i;
23509+ struct hlist_head *head;
23510+ struct au_vdir_dehstr *tpos;
23511+ struct hlist_node *pos, *n;
23512+
23513+ AuTraceEnter();
23514+
23515+ for (i = 0; i < AuSize_NHASH; i++) {
23516+ head = dehlist->heads + i;
23517+ hlist_for_each_entry_safe(tpos, pos, n, head, hash) {
23518+ /* hlist_del(pos); */
23519+ au_cache_free_dehstr(tpos);
23520+ }
23521+ }
23522+}
23523+
23524+/* returns found(true) or not */
23525+static int test_known(struct au_nhash *delist, char *name, int namelen)
23526+{
23527+ struct hlist_head *head;
23528+ struct au_vdir_dehstr *tpos;
23529+ struct hlist_node *pos;
23530+ struct au_vdir_destr *str;
23531+
23532+ LKTRTrace("%.*s\n", namelen, name);
23533+
23534+ head = delist->heads + au_name_hash(name, namelen);
23535+ hlist_for_each_entry(tpos, pos, head, hash) {
23536+ str = tpos->str;
23537+ LKTRTrace("%.*s\n", str->len, str->name);
23538+ if (str->len == namelen && !memcmp(str->name, name, namelen))
23539+ return 1;
23540+ }
23541+ return 0;
23542+
23543+}
23544+
23545+static int append_de(struct au_vdir *vdir, char *name, int namelen, ino_t ino,
23546+ unsigned int d_type, struct au_nhash *delist)
23547+{
23548+ int err, sz;
23549+ union au_vdir_deblk_p p, *room, deblk_end;
23550+ struct au_vdir_dehstr *dehstr;
23551+
23552+ LKTRTrace("%.*s %d, i%lu, dt%u\n",
23553+ namelen, name, namelen, (unsigned long)ino, d_type);
23554+
23555+ p.deblk = last_deblk(vdir);
23556+ deblk_end.deblk = p.deblk + 1;
23557+ room = &vdir->vd_last.p;
23558+ AuDebugOn(room->p < p.p || deblk_end.p <= room->p
23559+ || !is_deblk_end(room, &deblk_end));
23560+
23561+ sz = calc_size(namelen);
23562+ if (unlikely(sz > deblk_end.p - room->p)) {
23563+ err = append_deblk(vdir);
23564+ if (unlikely(err))
23565+ goto out;
23566+ p.deblk = last_deblk(vdir);
23567+ deblk_end.deblk = p.deblk + 1;
23568+ /* smp_mb(); */
23569+ AuDebugOn(room->p != p.p);
23570+ }
23571+
23572+ err = -ENOMEM;
23573+ dehstr = au_cache_alloc_dehstr();
23574+ if (unlikely(!dehstr))
23575+ goto out;
23576+ dehstr->str = &room->de->de_str;
23577+ hlist_add_head(&dehstr->hash,
23578+ delist->heads + au_name_hash(name, namelen));
23579+
23580+ room->de->de_ino = ino;
23581+ room->de->de_type = d_type;
23582+ room->de->de_str.len = namelen;
23583+ memcpy(room->de->de_str.name, name, namelen);
23584+
23585+ err = 0;
23586+ room->p += sz;
23587+ if (unlikely(set_deblk_end(room, &deblk_end)))
23588+ err = append_deblk(vdir);
23589+ /* smp_mb(); */
23590+
23591+ out:
23592+ AuTraceErr(err);
23593+ return err;
23594+}
23595+
23596+/* ---------------------------------------------------------------------- */
23597+
23598+static int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
23599+ unsigned int d_type, ino_t *ino)
23600+{
23601+ int err;
23602+ struct au_xino_entry xinoe;
23603+ struct mutex *mtx;
23604+ const int isdir = (d_type == DT_DIR);
23605+
23606+ /* prevent hardlinks from race condition */
23607+ mtx = NULL;
23608+ if (!isdir) {
23609+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
23610+ mutex_lock(mtx);
23611+ }
23612+ err = au_xino_read(sb, bindex, h_ino, &xinoe);
23613+ if (unlikely(err))
23614+ goto out;
23615+
23616+ if (!xinoe.ino) {
23617+ err = -EIO;
23618+ xinoe.ino = au_xino_new_ino(sb);
23619+ if (unlikely(!xinoe.ino))
23620+ goto out;
23621+
23622+#if 0 /* reserved for future use */
23623+ struct inode *h_inode;
23624+ xinoe.h_gen = AuXino_INVALID_HGEN;
23625+ h_inode = ilookup(au_sbr_sb(sb, bindex), h_ino);
23626+ if (h_inode) {
23627+ if (!is_bad_inode(h_inode)) {
23628+ xinoe.h_gen = h_inode->i_generation;
23629+ WARN_ON(xinoe.h_gen == AuXino_INVALID_HGEN);
23630+ }
23631+ iput(h_inode);
23632+ }
23633+#endif
23634+ err = au_xino_write(sb, bindex, h_ino, &xinoe);
23635+ if (unlikely(err))
23636+ goto out;
23637+ }
23638+
23639+ *ino = xinoe.ino;
23640+
23641+ out:
23642+ if (!isdir)
23643+ mutex_unlock(mtx);
23644+ AuTraceErr(err);
23645+ return err;
23646+}
23647+
23648+static int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
23649+ unsigned int d_type, ino_t *ino)
23650+{
23651+#ifdef CONFIG_AUFS_SHWH
23652+ return au_ino(sb, bindex, h_ino, d_type, ino);
23653+#else
23654+ return 0;
23655+#endif
23656+}
23657+
23658+#define AuFillVdir_CALLED 1
23659+#define AuFillVdir_SHWH (1 << 1)
23660+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
23661+#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
23662+#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
23663+#ifndef CONFIG_AUFS_SHWH
23664+#undef AuFillVdir_SHWH
23665+#define AuFillVdir_SHWH 0
23666+#endif
23667+
23668+struct fillvdir_arg {
23669+ struct file *file;
23670+ struct au_vdir *vdir;
23671+ struct au_nhash *delist;
23672+ struct au_nhash *whlist;
23673+ aufs_bindex_t bindex;
23674+ unsigned int flags;
23675+ int err;
23676+};
23677+
23678+static int fillvdir(void *__arg, const char *__name, int namelen, loff_t offset,
23679+ u64 h_ino, unsigned int d_type)
23680+{
23681+ struct fillvdir_arg *arg = __arg;
23682+ char *name = (void *)__name;
23683+ aufs_bindex_t bindex, bend;
23684+ struct super_block *sb;
23685+ ino_t ino;
23686+
23687+ LKTRTrace("%.*s, namelen %d, i%llu, dt%u\n",
23688+ namelen, name, namelen, (unsigned long long)h_ino, d_type);
23689+
23690+ sb = arg->file->f_dentry->d_sb;
23691+ bend = arg->bindex;
23692+ arg->err = 0;
23693+ au_fset_fillvdir(arg->flags, CALLED);
23694+ /* smp_mb(); */
23695+ if (namelen <= AUFS_WH_PFX_LEN
23696+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
23697+ for (bindex = 0; bindex < bend; bindex++)
23698+ if (test_known(arg->delist + bindex, name, namelen)
23699+ || au_nhash_test_known_wh(arg->whlist + bindex,
23700+ name, namelen))
23701+ goto out; /* already exists or whiteouted */
23702+
23703+ ino = 1; /* why does gcc warns? */
23704+ arg->err = au_ino(sb, bend, h_ino, d_type, &ino);
23705+ if (!arg->err)
23706+ arg->err = append_de(arg->vdir, name, namelen, ino,
23707+ d_type, arg->delist + bend);
23708+ } else {
23709+ name += AUFS_WH_PFX_LEN;
23710+ namelen -= AUFS_WH_PFX_LEN;
23711+ for (bindex = 0; bindex < bend; bindex++)
23712+ if (au_nhash_test_known_wh(arg->whlist + bend, name,
23713+ namelen))
23714+ goto out; /* already whiteouted */
23715+
23716+ ino = 1; /* dummy */
23717+ if (au_ftest_fillvdir(arg->flags, SHWH))
23718+ arg->err = au_wh_ino(sb, bend, h_ino, d_type, &ino);
23719+ if (!arg->err)
23720+ arg->err = au_nhash_append_wh
23721+ (arg->whlist + bend, name, namelen, ino, d_type,
23722+ bend, au_ftest_fillvdir(arg->flags, SHWH));
23723+ }
23724+
23725+ out:
23726+ if (!arg->err)
23727+ arg->vdir->vd_jiffy = jiffies;
23728+ /* smp_mb(); */
23729+ AuTraceErr(arg->err);
23730+ return arg->err;
23731+}
23732+
23733+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
23734+ aufs_bindex_t bstart, aufs_bindex_t bend,
23735+ struct au_nhash *_whlist, struct au_nhash *_delist)
23736+{
23737+#ifdef CONFIG_AUFS_SHWH
23738+ int err, i;
23739+ struct hlist_head *head;
23740+ struct au_vdir_wh *tpos;
23741+ struct hlist_node *pos, *n;
23742+ char *p, *o;
23743+ struct au_nhash *whlist, *delist;
23744+ struct au_vdir_destr *destr;
23745+ aufs_bindex_t bindex;
23746+
23747+ AuTraceEnter();
23748+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
23749+
23750+ err = -ENOMEM;
23751+ o = p = __getname();
23752+ if (unlikely(!p))
23753+ goto out;
23754+
23755+ err = 0;
23756+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
23757+ p += AUFS_WH_PFX_LEN;
23758+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
23759+ whlist = _whlist + bindex;
23760+ delist = _delist + bindex;
23761+
23762+ for (i = 0; i < AuSize_NHASH; i++) {
23763+ head = whlist->heads + i;
23764+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
23765+ destr = &tpos->wh_str;
23766+ memcpy(p, destr->name, destr->len);
23767+ err = append_de(vdir, o,
23768+ destr->len + AUFS_WH_PFX_LEN,
23769+ tpos->wh_ino, tpos->wh_type,
23770+ delist);
23771+ if (unlikely(err))
23772+ break;
23773+ }
23774+ }
23775+ }
23776+
23777+ __putname(o);
23778+
23779+ out:
23780+ AuTraceErr(err);
23781+ return err;
23782+#else
23783+ return 0;
23784+#endif
23785+}
23786+
23787+static int au_do_read_vdir(struct fillvdir_arg *arg)
23788+{
23789+ int err;
23790+ unsigned int mnt_flags;
23791+ loff_t offset;
23792+ aufs_bindex_t bend, bindex, bstart;
23793+ unsigned char dlgt, shwh;
23794+ struct super_block *sb;
23795+ struct file *hf;
23796+
23797+ AuTraceEnter();
23798+
23799+ err = -ENOMEM;
23800+ bend = au_fbend(arg->file);
23801+ arg->delist = kmalloc(sizeof(*arg->delist) * (bend + 1), GFP_NOFS);
23802+ if (unlikely(!arg->delist))
23803+ goto out;
23804+ arg->whlist = kmalloc(sizeof(*arg->whlist) * (bend + 1), GFP_NOFS);
23805+ if (unlikely(!arg->whlist))
23806+ goto out_delist;
23807+ err = 0;
23808+ for (bindex = 0; bindex <= bend; bindex++) {
23809+ au_nhash_init(arg->delist + bindex);
23810+ au_nhash_init(arg->whlist + bindex);
23811+ }
23812+
23813+ sb = arg->file->f_dentry->d_sb;
23814+ mnt_flags = au_mntflags(sb);
23815+ dlgt = !!au_test_dlgt(mnt_flags);
23816+ arg->flags = 0;
23817+ shwh = 0;
23818+ if (au_opt_test(mnt_flags, SHWH)) {
23819+ shwh = 1;
23820+ au_fset_fillvdir(arg->flags, SHWH);
23821+ }
23822+ bstart = au_fbstart(arg->file);
23823+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
23824+ hf = au_h_fptr(arg->file, bindex);
23825+ if (!hf)
23826+ continue;
23827+
23828+ offset = vfsub_llseek(hf, 0, SEEK_SET);
23829+ err = offset;
23830+ if (unlikely(offset))
23831+ break;
23832+ arg->bindex = bindex;
23833+ do {
23834+ arg->err = 0;
23835+ au_fclr_fillvdir(arg->flags, CALLED);
23836+ /* smp_mb(); */
23837+ err = vfsub_readdir(hf, fillvdir, arg, dlgt);
23838+ if (err >= 0)
23839+ err = arg->err;
23840+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
23841+ }
23842+
23843+ if (!err && shwh)
23844+ err = au_handle_shwh(sb, arg->vdir, bstart, bend, arg->whlist,
23845+ arg->delist);
23846+
23847+ for (bindex = bstart; bindex <= bend; bindex++) {
23848+ free_dehlist(arg->delist + bindex);
23849+ au_nhash_fin(arg->whlist + bindex);
23850+ }
23851+ kfree(arg->whlist);
23852+
23853+ out_delist:
23854+ kfree(arg->delist);
23855+ out:
23856+ AuTraceErr(err);
23857+ return err;
23858+}
23859+
23860+static int read_vdir(struct file *file, int may_read)
23861+{
23862+ int err;
23863+ unsigned long expire;
23864+ struct fillvdir_arg arg;
23865+ unsigned char do_read;
23866+ struct dentry *dentry;
23867+ struct inode *inode;
23868+ struct au_vdir *vdir, *allocated;
23869+ struct super_block *sb;
23870+
23871+ dentry = file->f_dentry;
23872+ LKTRTrace("%.*s, may %d\n", AuDLNPair(dentry), may_read);
23873+ FiMustWriteLock(file);
23874+ inode = dentry->d_inode;
23875+ IMustLock(inode);
23876+ IiMustWriteLock(inode);
23877+ AuDebugOn(!S_ISDIR(inode->i_mode));
23878+
23879+ err = 0;
23880+ allocated = NULL;
23881+ do_read = 0;
23882+ sb = inode->i_sb;
23883+ expire = au_sbi(sb)->si_rdcache;
23884+ vdir = au_ivdir(inode);
23885+ if (!vdir) {
23886+ AuDebugOn(au_fvdir_cache(file));
23887+ do_read = 1;
23888+ vdir = alloc_vdir();
23889+ err = PTR_ERR(vdir);
23890+ if (IS_ERR(vdir))
23891+ goto out;
23892+ err = 0;
23893+ allocated = vdir;
23894+ } else if (may_read
23895+ && (inode->i_version != vdir->vd_version
23896+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
23897+ LKTRTrace("iver %llu, vdver %lu, exp %lu\n",
23898+ (unsigned long long)inode->i_version,
23899+ vdir->vd_version, vdir->vd_jiffy + expire);
23900+ do_read = 1;
23901+ err = reinit_vdir(vdir);
23902+ if (unlikely(err))
23903+ goto out;
23904+ }
23905+
23906+ if (!do_read)
23907+ return 0; /* success */
23908+
23909+ arg.file = file;
23910+ arg.vdir = vdir;
23911+ err = au_do_read_vdir(&arg);
23912+ if (!err) {
23913+ /* todo: necessary? */
23914+ /* file->f_pos = 0; */
23915+ vdir->vd_version = inode->i_version;
23916+ vdir->vd_last.i = 0;
23917+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
23918+ if (allocated)
23919+ au_set_ivdir(inode, allocated);
23920+ } else if (allocated)
23921+ au_vdir_free(allocated);
23922+
23923+ out:
23924+ AuTraceErr(err);
23925+ return err;
23926+}
23927+
23928+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
23929+{
23930+ int err, i, rerr, n;
23931+
23932+ AuTraceEnter();
23933+ AuDebugOn(tgt->vd_nblk != 1);
23934+
23935+ err = -ENOMEM;
23936+ if (tgt->vd_nblk < src->vd_nblk) {
23937+ au_vdir_deblk_t **p;
23938+ p = au_kzrealloc(tgt->vd_deblk, sizeof(*p) * tgt->vd_nblk,
23939+ sizeof(*p) * src->vd_nblk, GFP_NOFS);
23940+ if (unlikely(!p))
23941+ goto out;
23942+ tgt->vd_deblk = p;
23943+ }
23944+
23945+ tgt->vd_nblk = src->vd_nblk;
23946+ n = src->vd_nblk;
23947+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], AuSize_DEBLK);
23948+ /* tgt->vd_last.i = 0; */
23949+ /* tgt->vd_last.p.deblk = tgt->vd_deblk[0]; */
23950+ tgt->vd_version = src->vd_version;
23951+ tgt->vd_jiffy = src->vd_jiffy;
23952+
23953+ for (i = 1; i < n; i++) {
23954+ tgt->vd_deblk[i] = kmalloc(AuSize_DEBLK, GFP_NOFS);
23955+ if (tgt->vd_deblk[i])
23956+ memcpy(tgt->vd_deblk[i], src->vd_deblk[i],
23957+ AuSize_DEBLK);
23958+ else
23959+ goto out;
23960+ }
23961+ /* smp_mb(); */
23962+ return 0; /* success */
23963+
23964+ out:
23965+ rerr = reinit_vdir(tgt);
23966+ BUG_ON(rerr);
23967+ AuTraceErr(err);
23968+ return err;
23969+}
23970+
23971+int au_vdir_init(struct file *file)
23972+{
23973+ int err;
23974+ struct dentry *dentry;
23975+ struct inode *inode;
23976+ struct au_vdir *vdir_cache, *allocated;
23977+
23978+ dentry = file->f_dentry;
23979+ LKTRTrace("%.*s, pos %lld\n", AuDLNPair(dentry), file->f_pos);
23980+ FiMustWriteLock(file);
23981+ inode = dentry->d_inode;
23982+ IiMustWriteLock(inode);
23983+ AuDebugOn(!S_ISDIR(inode->i_mode));
23984+
23985+ err = read_vdir(file, !file->f_pos);
23986+ if (unlikely(err))
23987+ goto out;
23988+
23989+ allocated = NULL;
23990+ vdir_cache = au_fvdir_cache(file);
23991+ if (!vdir_cache) {
23992+ vdir_cache = alloc_vdir();
23993+ err = PTR_ERR(vdir_cache);
23994+ if (IS_ERR(vdir_cache))
23995+ goto out;
23996+ allocated = vdir_cache;
23997+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
23998+ err = reinit_vdir(vdir_cache);
23999+ if (unlikely(err))
24000+ goto out;
24001+ } else
24002+ return 0; /* success */
24003+
24004+ err = copy_vdir(vdir_cache, au_ivdir(inode));
24005+ if (!err) {
24006+ file->f_version = inode->i_version;
24007+ if (allocated)
24008+ au_set_fvdir_cache(file, allocated);
24009+ } else if (allocated)
24010+ au_vdir_free(allocated);
24011+
24012+ out:
24013+ AuTraceErr(err);
24014+ return err;
24015+}
24016+
24017+static loff_t calc_offset(struct au_vdir *vdir)
24018+{
24019+ loff_t offset;
24020+ union au_vdir_deblk_p p;
24021+
24022+ p.deblk = vdir->vd_deblk[vdir->vd_last.i];
24023+ offset = vdir->vd_last.p.p - p.p;
24024+ offset += sizeof(*p.deblk) * vdir->vd_last.i;
24025+ return offset;
24026+}
24027+
24028+/* returns true or false */
24029+static int seek_vdir(struct file *file)
24030+{
24031+ int valid, i, n;
24032+ struct dentry *dentry;
24033+ struct au_vdir *vdir_cache;
24034+ loff_t offset;
24035+ union au_vdir_deblk_p p, deblk_end;
24036+
24037+ dentry = file->f_dentry;
24038+ LKTRTrace("%.*s, pos %lld\n", AuDLNPair(dentry), file->f_pos);
24039+ vdir_cache = au_fvdir_cache(file);
24040+ AuDebugOn(!vdir_cache);
24041+
24042+ valid = 1;
24043+ offset = calc_offset(vdir_cache);
24044+ LKTRTrace("offset %lld\n", offset);
24045+ if (file->f_pos == offset)
24046+ goto out;
24047+
24048+ vdir_cache->vd_last.i = 0;
24049+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
24050+ if (!file->f_pos)
24051+ goto out;
24052+
24053+ valid = 0;
24054+ i = file->f_pos / AuSize_DEBLK;
24055+ LKTRTrace("i %d\n", i);
24056+ if (i >= vdir_cache->vd_nblk)
24057+ goto out;
24058+
24059+ n = vdir_cache->vd_nblk;
24060+ for (; i < n; i++) {
24061+ p.deblk = vdir_cache->vd_deblk[i];
24062+ deblk_end.deblk = p.deblk + 1;
24063+ offset = i;
24064+ offset *= AuSize_DEBLK;
24065+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
24066+ int l;
24067+ l = calc_size(p.de->de_str.len);
24068+ offset += l;
24069+ p.p += l;
24070+ }
24071+ if (!is_deblk_end(&p, &deblk_end)) {
24072+ valid = 1;
24073+ vdir_cache->vd_last.i = i;
24074+ vdir_cache->vd_last.p = p;
24075+ break;
24076+ }
24077+ }
24078+
24079+ out:
24080+ /* smp_mb(); */
24081+ AuTraceErr(!valid);
24082+ return valid;
24083+}
24084+
24085+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
24086+{
24087+ int err, l;
24088+ struct dentry *dentry;
24089+ struct au_vdir *vdir_cache;
24090+ struct au_vdir_de *de;
24091+ union au_vdir_deblk_p deblk_end;
24092+
24093+ dentry = file->f_dentry;
24094+ LKTRTrace("%.*s, pos %lld\n", AuDLNPair(dentry), file->f_pos);
24095+ vdir_cache = au_fvdir_cache(file);
24096+ AuDebugOn(!vdir_cache);
24097+
24098+ if (!seek_vdir(file))
24099+ return 0;
24100+
24101+ while (1) {
24102+ deblk_end.deblk
24103+ = vdir_cache->vd_deblk[vdir_cache->vd_last.i] + 1;
24104+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
24105+ de = vdir_cache->vd_last.p.de;
24106+ LKTRTrace("%.*s, off%lld, i%lu, dt%d\n",
24107+ de->de_str.len, de->de_str.name,
24108+ file->f_pos, (unsigned long)de->de_ino,
24109+ de->de_type);
24110+ err = filldir(dirent, de->de_str.name, de->de_str.len,
24111+ file->f_pos, de->de_ino, de->de_type);
24112+ if (unlikely(err)) {
24113+ AuTraceErr(err);
24114+ /* todo: ignore the error caused by udba? */
24115+ /* return err; */
24116+ return 0;
24117+ }
24118+
24119+ l = calc_size(de->de_str.len);
24120+ vdir_cache->vd_last.p.p += l;
24121+ file->f_pos += l;
24122+ }
24123+ if (vdir_cache->vd_last.i < vdir_cache->vd_nblk - 1) {
24124+ vdir_cache->vd_last.i++;
24125+ vdir_cache->vd_last.p.deblk
24126+ = vdir_cache->vd_deblk[vdir_cache->vd_last.i];
24127+ file->f_pos = sizeof(*vdir_cache->vd_last.p.deblk)
24128+ * vdir_cache->vd_last.i;
24129+ continue;
24130+ }
24131+ break;
24132+ }
24133+
24134+ /* smp_mb(); */
24135+ return 0;
24136+}
24137diff -urN linux/fs/aufs/vfsub.c linux-aufs/fs/aufs/vfsub.c
24138--- linux/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
24139+++ linux-aufs/fs/aufs/vfsub.c 2009-03-12 16:18:04.000000000 +0100
24140@@ -0,0 +1,686 @@
24141+/*
24142+ * Copyright (C) 2005-2009 Junjiro Okajima
24143+ *
24144+ * This program, aufs is free software; you can redistribute it and/or modify
24145+ * it under the terms of the GNU General Public License as published by
24146+ * the Free Software Foundation; either version 2 of the License, or
24147+ * (at your option) any later version.
24148+ *
24149+ * This program is distributed in the hope that it will be useful,
24150+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24151+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24152+ * GNU General Public License for more details.
24153+ *
24154+ * You should have received a copy of the GNU General Public License
24155+ * along with this program; if not, write to the Free Software
24156+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24157+ */
24158+
24159+/*
24160+ * sub-routines for VFS
24161+ *
24162+ * $Id$
24163+ */
24164+
24165+#include <linux/uaccess.h>
24166+#include "aufs.h"
24167+
24168+/* ---------------------------------------------------------------------- */
24169+
24170+void vfsub_args_init(struct vfsub_args *vargs, struct au_hin_ignore *ign,
24171+ int dlgt, int force_unlink)
24172+{
24173+ do_vfsub_args_reinit(vargs, ign);
24174+ vargs->flags = 0;
24175+ if (dlgt)
24176+ vfsub_fset(vargs->flags, DLGT);
24177+ if (force_unlink)
24178+ vfsub_fset(vargs->flags, FORCE_UNLINK);
24179+}
24180+
24181+/* ---------------------------------------------------------------------- */
24182+
24183+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
24184+{
24185+ struct file *err;
24186+
24187+ LKTRTrace("%s\n", path);
24188+
24189+ lockdep_off();
24190+ err = filp_open(path, oflags, mode);
24191+ lockdep_on();
24192+ if (!IS_ERR(err))
24193+ au_update_fuse_h_inode(err->f_vfsmnt, err->f_dentry); /*ignore*/
24194+ return err;
24195+}
24196+
24197+int vfsub_path_lookup(const char *name, unsigned int flags,
24198+ struct nameidata *nd)
24199+{
24200+ int err;
24201+
24202+ LKTRTrace("%s\n", name);
24203+
24204+ /* lockdep_off(); */
24205+ err = path_lookup(name, flags, nd);
24206+ /* lockdep_on(); */
24207+ if (!err)
24208+ au_update_fuse_h_inode(nd->path.mnt, nd->path.dentry);
24209+ /*ignore*/
24210+ return err;
24211+}
24212+
24213+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
24214+ int len)
24215+{
24216+ struct dentry *d;
24217+
24218+ LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name);
24219+ IMustLock(parent->d_inode);
24220+
24221+ d = lookup_one_len(name, parent, len);
24222+ if (!IS_ERR(d))
24223+ au_update_fuse_h_inode(NULL, d); /*ignore*/
24224+ return d;
24225+}
24226+
24227+#ifdef CONFIG_AUFS_LHASH_PATCH
24228+struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent,
24229+ struct nameidata *nd)
24230+{
24231+ struct dentry *d;
24232+
24233+ LKTRTrace("%.*s/%.*s, nd %d\n",
24234+ AuDLNPair(parent), AuLNPair(name), !!nd);
24235+ if (nd)
24236+ LKTRTrace("nd{0x%x}\n", nd->flags);
24237+ IMustLock(parent->d_inode);
24238+
24239+ d = __lookup_hash(name, parent, nd);
24240+ if (!IS_ERR(d))
24241+ au_update_fuse_h_inode(NULL, d); /*ignore*/
24242+ return d;
24243+}
24244+#endif
24245+
24246+/* ---------------------------------------------------------------------- */
24247+
24248+int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
24249+ struct nameidata *nd)
24250+{
24251+ int err;
24252+ struct vfsmount *mnt;
24253+
24254+ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
24255+ IMustLock(dir);
24256+
24257+ err = vfs_create(dir, dentry, mode, nd);
24258+ if (!err) {
24259+ mnt = NULL;
24260+ if (nd)
24261+ mnt = nd->path.mnt;
24262+ /* dir inode is locked */
24263+ au_update_fuse_h_inode(mnt, dentry->d_parent); /*ignore*/
24264+ au_update_fuse_h_inode(mnt, dentry); /*ignore*/
24265+ }
24266+ return err;
24267+}
24268+
24269+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
24270+#define VfsubSymlinkArgs dir, dentry, symname
24271+#else
24272+#define VfsubSymlinkArgs dir, dentry, symname, mode
24273+#endif
24274+
24275+int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
24276+ const char *symname, int mode)
24277+{
24278+ int err;
24279+
24280+ LKTRTrace("i%lu, %.*s, %s, 0x%x\n",
24281+ dir->i_ino, AuDLNPair(dentry), symname, mode);
24282+ IMustLock(dir);
24283+
24284+ err = vfs_symlink(VfsubSymlinkArgs);
24285+ if (!err) {
24286+ /* dir inode is locked */
24287+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24288+ au_update_fuse_h_inode(NULL, dentry); /*ignore*/
24289+ }
24290+ return err;
24291+}
24292+
24293+int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
24294+ dev_t dev)
24295+{
24296+ int err;
24297+
24298+ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
24299+ IMustLock(dir);
24300+
24301+ err = vfs_mknod(dir, dentry, mode, dev);
24302+ if (!err) {
24303+ /* dir inode is locked */
24304+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24305+ au_update_fuse_h_inode(NULL, dentry); /*ignore*/
24306+ }
24307+ return err;
24308+}
24309+
24310+int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
24311+ struct dentry *dentry)
24312+{
24313+ int err;
24314+
24315+ LKTRTrace("%.*s, i%lu, %.*s\n",
24316+ AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry));
24317+ IMustLock(dir);
24318+
24319+ lockdep_off();
24320+ err = vfs_link(src_dentry, dir, dentry);
24321+ lockdep_on();
24322+ if (!err) {
24323+ LKTRTrace("src_i %p, dst_i %p\n",
24324+ src_dentry->d_inode, dentry->d_inode);
24325+ /* fuse has different memory inode for the same inumber */
24326+ au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
24327+ /* dir inode is locked */
24328+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24329+ au_update_fuse_h_inode(NULL, dentry); /*ignore*/
24330+ }
24331+ return err;
24332+}
24333+
24334+int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
24335+ struct inode *dir, struct dentry *dentry)
24336+{
24337+ int err;
24338+
24339+ LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
24340+ src_dir->i_ino, AuDLNPair(src_dentry),
24341+ dir->i_ino, AuDLNPair(dentry));
24342+ IMustLock(dir);
24343+ IMustLock(src_dir);
24344+ AuDebugOn(src_dir != dir && !vfsub_is_rename_mutex_locked(dir->i_sb));
24345+
24346+ lockdep_off();
24347+ err = vfs_rename(src_dir, src_dentry, dir, dentry);
24348+ lockdep_on();
24349+ if (!err) {
24350+ /* dir inode is locked */
24351+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24352+ au_update_fuse_h_inode(NULL, src_dentry->d_parent); /*ignore*/
24353+ au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
24354+ }
24355+ return err;
24356+}
24357+
24358+int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode)
24359+{
24360+ int err;
24361+
24362+ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
24363+ IMustLock(dir);
24364+
24365+ err = vfs_mkdir(dir, dentry, mode);
24366+ if (!err) {
24367+ /* dir inode is locked */
24368+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24369+ au_update_fuse_h_inode(NULL, dentry); /*ignore*/
24370+ }
24371+ return err;
24372+}
24373+
24374+int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry)
24375+{
24376+ int err;
24377+
24378+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
24379+ IMustLock(dir);
24380+
24381+ lockdep_off();
24382+ err = vfs_rmdir(dir, dentry);
24383+ lockdep_on();
24384+ /* dir inode is locked */
24385+ if (!err)
24386+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24387+ return err;
24388+}
24389+
24390+int do_vfsub_unlink(struct inode *dir, struct dentry *dentry)
24391+{
24392+ int err;
24393+
24394+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
24395+ IMustLock(dir);
24396+
24397+ /* vfs_unlink() locks inode */
24398+ lockdep_off();
24399+ err = vfs_unlink(dir, dentry);
24400+ lockdep_on();
24401+ /* dir inode is locked */
24402+ if (!err)
24403+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24404+ return err;
24405+}
24406+
24407+/* ---------------------------------------------------------------------- */
24408+
24409+ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
24410+ loff_t *ppos)
24411+{
24412+ ssize_t err;
24413+
24414+ LKTRTrace("%.*s, cnt %zu, pos %lld\n",
24415+ AuDLNPair(file->f_dentry), count, *ppos);
24416+
24417+ /* todo: always off, regardless nfs branch? */
24418+ au_br_nfs_lockdep_off(file->f_vfsmnt->mnt_sb);
24419+ err = vfs_read(file, ubuf, count, ppos);
24420+ au_br_nfs_lockdep_on(file->f_vfsmnt->mnt_sb);
24421+ if (err >= 0)
24422+ au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
24423+ /*ignore*/
24424+ return err;
24425+}
24426+
24427+/* todo: kernel_read()? */
24428+ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count,
24429+ loff_t *ppos)
24430+{
24431+ ssize_t err;
24432+ mm_segment_t oldfs;
24433+
24434+ oldfs = get_fs();
24435+ set_fs(KERNEL_DS);
24436+ err = do_vfsub_read_u(file, (char __user *)kbuf, count, ppos);
24437+ set_fs(oldfs);
24438+ return err;
24439+}
24440+
24441+ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
24442+ size_t count, loff_t *ppos)
24443+{
24444+ ssize_t err;
24445+
24446+ LKTRTrace("%.*s, cnt %zu, pos %lld\n",
24447+ AuDLNPair(file->f_dentry), count, *ppos);
24448+
24449+ lockdep_off();
24450+ err = vfs_write(file, ubuf, count, ppos);
24451+ lockdep_on();
24452+ if (err >= 0)
24453+ au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
24454+ /*ignore*/
24455+ return err;
24456+}
24457+
24458+ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count,
24459+ loff_t *ppos)
24460+{
24461+ ssize_t err;
24462+ mm_segment_t oldfs;
24463+
24464+ oldfs = get_fs();
24465+ set_fs(KERNEL_DS);
24466+ err = do_vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
24467+ set_fs(oldfs);
24468+ return err;
24469+}
24470+
24471+int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
24472+{
24473+ int err;
24474+
24475+ LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry));
24476+
24477+ lockdep_off();
24478+ err = vfs_readdir(file, filldir, arg);
24479+ lockdep_on();
24480+ if (err >= 0)
24481+ au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
24482+ /*ignore*/
24483+ return err;
24484+}
24485+
24486+#ifdef CONFIG_AUFS_SPLICE_PATCH
24487+long do_vfsub_splice_to(struct file *in, loff_t *ppos,
24488+ struct pipe_inode_info *pipe, size_t len,
24489+ unsigned int flags)
24490+{
24491+ long err;
24492+
24493+ LKTRTrace("%.*s, pos %lld, len %zu, 0x%x\n",
24494+ AuDLNPair(in->f_dentry), *ppos, len, flags);
24495+
24496+ lockdep_off();
24497+ err = vfs_splice_to(in, ppos, pipe, len, flags);
24498+ lockdep_on();
24499+ if (err >= 0)
24500+ au_update_fuse_h_inode(in->f_vfsmnt, in->f_dentry); /*ignore*/
24501+ return err;
24502+}
24503+
24504+long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
24505+ loff_t *ppos, size_t len, unsigned int flags)
24506+{
24507+ long err;
24508+
24509+ LKTRTrace("%.*s, pos %lld, len %zu, 0x%x\n",
24510+ AuDLNPair(out->f_dentry), *ppos, len, flags);
24511+
24512+ lockdep_off();
24513+ err = vfs_splice_from(pipe, out, ppos, len, flags);
24514+ lockdep_on();
24515+ if (err >= 0)
24516+ au_update_fuse_h_inode(out->f_vfsmnt, out->f_dentry); /*ignore*/
24517+ return err;
24518+}
24519+#endif
24520+
24521+/* ---------------------------------------------------------------------- */
24522+
24523+struct au_vfsub_mkdir_args {
24524+ int *errp;
24525+ struct inode *dir;
24526+ struct dentry *dentry;
24527+ int mode;
24528+ struct vfsub_args *vargs;
24529+};
24530+
24531+static void au_call_vfsub_mkdir(void *args)
24532+{
24533+ struct au_vfsub_mkdir_args *a = args;
24534+ *a->errp = vfsub_mkdir(a->dir, a->dentry, a->mode, a->vargs);
24535+}
24536+
24537+int vfsub_sio_mkdir(struct au_hinode *hdir, struct dentry *dentry, int mode,
24538+ int dlgt)
24539+{
24540+ int err, do_sio, wkq_err;
24541+ struct inode *dir = hdir->hi_inode;
24542+ struct au_hin_ignore ign;
24543+ struct vfsub_args vargs;
24544+
24545+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
24546+
24547+ vfsub_args_init(&vargs, &ign, dlgt, /*force_unlink*/0);
24548+ vfsub_ign_hinode(&vargs, IN_CREATE, hdir);
24549+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE, dlgt);
24550+ if (!do_sio)
24551+ err = vfsub_mkdir(dir, dentry, mode, &vargs);
24552+ else {
24553+ struct au_vfsub_mkdir_args args = {
24554+ .errp = &err,
24555+ .dir = dir,
24556+ .dentry = dentry,
24557+ .mode = mode,
24558+ .vargs = &vargs
24559+ };
24560+ vfsub_fclr(vargs.flags, DLGT);
24561+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args, /*dlgt*/0);
24562+ if (unlikely(wkq_err))
24563+ err = wkq_err;
24564+ }
24565+
24566+ AuTraceErr(err);
24567+ return err;
24568+}
24569+
24570+struct au_vfsub_rmdir_args {
24571+ int *errp;
24572+ struct inode *dir;
24573+ struct dentry *dentry;
24574+ struct vfsub_args *vargs;
24575+};
24576+
24577+static void au_call_vfsub_rmdir(void *args)
24578+{
24579+ struct au_vfsub_rmdir_args *a = args;
24580+ *a->errp = vfsub_rmdir(a->dir, a->dentry, a->vargs);
24581+}
24582+
24583+int vfsub_sio_rmdir(struct au_hinode *hdir, struct dentry *dentry, int dlgt)
24584+{
24585+ int err, do_sio, wkq_err;
24586+ struct inode *dir = hdir->hi_inode;
24587+ struct au_hin_ignore ign;
24588+ struct vfsub_args vargs;
24589+
24590+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
24591+
24592+ vfsub_args_init(&vargs, &ign, dlgt, /*force_unlink*/0);
24593+ vfsub_ign_hinode(&vargs, IN_DELETE, hdir);
24594+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE, dlgt);
24595+ if (!do_sio)
24596+ err = vfsub_rmdir(dir, dentry, &vargs);
24597+ else {
24598+ struct au_vfsub_rmdir_args args = {
24599+ .errp = &err,
24600+ .dir = dir,
24601+ .dentry = dentry,
24602+ .vargs = &vargs
24603+ };
24604+ vfsub_fclr(vargs.flags, DLGT);
24605+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args, /*dlgt*/0);
24606+ if (unlikely(wkq_err))
24607+ err = wkq_err;
24608+ }
24609+
24610+ AuTraceErr(err);
24611+ return err;
24612+}
24613+
24614+/* ---------------------------------------------------------------------- */
24615+
24616+struct notify_change_args {
24617+ int *errp;
24618+ struct dentry *h_dentry;
24619+ struct iattr *ia;
24620+ struct vfsub_args *vargs;
24621+};
24622+
24623+static void call_notify_change(void *args)
24624+{
24625+ struct notify_change_args *a = args;
24626+ struct inode *h_inode;
24627+
24628+ LKTRTrace("%.*s, ia_valid 0x%x\n",
24629+ AuDLNPair(a->h_dentry), a->ia->ia_valid);
24630+ h_inode = a->h_dentry->d_inode;
24631+ IMustLock(h_inode);
24632+
24633+ *a->errp = -EPERM;
24634+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
24635+ vfsub_ignore(a->vargs);
24636+ lockdep_off();
24637+ *a->errp = notify_change(a->h_dentry, a->ia);
24638+ lockdep_on();
24639+ if (!*a->errp)
24640+ au_update_fuse_h_inode(NULL, a->h_dentry); /*ignore*/
24641+ else
24642+ vfsub_unignore(a->vargs);
24643+ au_dbg_hin_list(a->vargs);
24644+ }
24645+ AuTraceErr(*a->errp);
24646+}
24647+
24648+#ifdef CONFIG_AUFS_DLGT
24649+static void vfsub_notify_change_dlgt(struct notify_change_args *args,
24650+ unsigned int flags)
24651+{
24652+ if (!vfsub_ftest(flags, DLGT))
24653+ call_notify_change(args);
24654+ else {
24655+ int wkq_err;
24656+ wkq_err = au_wkq_wait(call_notify_change, args, /*dlgt*/1);
24657+ if (unlikely(wkq_err))
24658+ *args->errp = wkq_err;
24659+ }
24660+}
24661+#else
24662+static void vfsub_notify_change_dlgt(struct notify_change_args *args,
24663+ unsigned int flags)
24664+{
24665+ call_notify_change(args);
24666+}
24667+#endif
24668+
24669+int vfsub_notify_change(struct dentry *dentry, struct iattr *ia,
24670+ struct vfsub_args *vargs)
24671+{
24672+ int err;
24673+ struct notify_change_args args = {
24674+ .errp = &err,
24675+ .h_dentry = dentry,
24676+ .ia = ia,
24677+ .vargs = vargs
24678+ };
24679+
24680+ vfsub_notify_change_dlgt(&args, vargs->flags);
24681+
24682+ AuTraceErr(err);
24683+ return err;
24684+}
24685+
24686+int vfsub_sio_notify_change(struct au_hinode *hdir, struct dentry *dentry,
24687+ struct iattr *ia)
24688+{
24689+ int err, wkq_err;
24690+ struct au_hin_ignore ign;
24691+ struct vfsub_args vargs;
24692+ __u32 events;
24693+ struct notify_change_args args = {
24694+ .errp = &err,
24695+ .h_dentry = dentry,
24696+ .ia = ia,
24697+ .vargs = &vargs
24698+ };
24699+
24700+ LKTRTrace("%.*s, 0x%x\n", AuDLNPair(dentry), ia->ia_valid);
24701+
24702+ vfsub_args_init(&vargs, &ign, /*dlgt*/0, /*force_unlink*/0);
24703+ events = vfsub_events_notify_change(ia);
24704+ if (events)
24705+ vfsub_ign_hinode(&vargs, events, hdir);
24706+ wkq_err = au_wkq_wait(call_notify_change, &args, /*dlgt*/0);
24707+ if (unlikely(wkq_err))
24708+ err = wkq_err;
24709+
24710+ AuTraceErr(err);
24711+ return err;
24712+}
24713+
24714+/* ---------------------------------------------------------------------- */
24715+
24716+struct unlink_args {
24717+ int *errp;
24718+ struct inode *dir;
24719+ struct dentry *dentry;
24720+ struct vfsub_args *vargs;
24721+};
24722+
24723+static void call_unlink(void *args)
24724+{
24725+ struct unlink_args *a = args;
24726+ struct inode *h_inode;
24727+ const int stop_sillyrename = (au_test_nfs(a->dentry->d_sb)
24728+ && atomic_read(&a->dentry->d_count) == 1);
24729+
24730+ LKTRTrace("%.*s, stop_silly %d, cnt %d\n",
24731+ AuDLNPair(a->dentry), stop_sillyrename,
24732+ atomic_read(&a->dentry->d_count));
24733+
24734+ if (!stop_sillyrename)
24735+ dget(a->dentry);
24736+ h_inode = a->dentry->d_inode;
24737+ if (h_inode)
24738+ atomic_inc_return(&h_inode->i_count);
24739+ vfsub_ignore(a->vargs);
24740+ *a->errp = do_vfsub_unlink(a->dir, a->dentry);
24741+ if (unlikely(*a->errp || (a->dentry->d_flags & DCACHE_NFSFS_RENAMED)))
24742+ vfsub_unignore(a->vargs);
24743+ au_dbg_hin_list(a->vargs);
24744+ if (!stop_sillyrename)
24745+ dput(a->dentry);
24746+ if (h_inode)
24747+ iput(h_inode);
24748+
24749+ AuTraceErr(*a->errp);
24750+}
24751+
24752+/*
24753+ * @dir: must be locked.
24754+ * @dentry: target dentry.
24755+ */
24756+int vfsub_unlink(struct inode *dir, struct dentry *dentry,
24757+ struct vfsub_args *vargs)
24758+{
24759+ int err;
24760+ struct unlink_args args = {
24761+ .errp = &err,
24762+ .dir = dir,
24763+ .dentry = dentry,
24764+ .vargs = vargs
24765+ };
24766+
24767+ if (!vfsub_ftest(vargs->flags, DLGT)
24768+ && !vfsub_ftest(vargs->flags, FORCE_UNLINK))
24769+ call_unlink(&args);
24770+ else {
24771+ int wkq_err;
24772+ wkq_err = au_wkq_wait(call_unlink, &args,
24773+ vfsub_ftest(vargs->flags, DLGT));
24774+ if (unlikely(wkq_err))
24775+ err = wkq_err;
24776+ }
24777+
24778+ return err;
24779+}
24780+
24781+/* ---------------------------------------------------------------------- */
24782+
24783+struct statfs_args {
24784+ int *errp;
24785+ void *arg;
24786+ struct kstatfs *buf;
24787+};
24788+
24789+static void call_statfs(void *args)
24790+{
24791+ struct statfs_args *a = args;
24792+ *a->errp = vfs_statfs(a->arg, a->buf);
24793+}
24794+
24795+#ifdef CONFIG_AUFS_DLGT
24796+static void vfsub_statfs_dlgt(struct statfs_args *args, int dlgt)
24797+{
24798+ if (!dlgt)
24799+ call_statfs(args);
24800+ else {
24801+ int wkq_err;
24802+ wkq_err = au_wkq_wait(call_statfs, args, /*dlgt*/1);
24803+ if (unlikely(wkq_err))
24804+ *args->errp = wkq_err;
24805+ }
24806+}
24807+#else
24808+static void vfsub_statfs_dlgt(struct statfs_args *args, int dlgt)
24809+{
24810+ call_statfs(args);
24811+}
24812+#endif
24813+
24814+int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt)
24815+{
24816+ int err;
24817+ struct statfs_args args = {
24818+ .errp = &err,
24819+ .arg = arg,
24820+ .buf = buf
24821+ };
24822+
24823+ vfsub_statfs_dlgt(&args, dlgt);
24824+
24825+ return err;
24826+}
24827diff -urN linux/fs/aufs/vfsub.h linux-aufs/fs/aufs/vfsub.h
24828--- linux/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
24829+++ linux-aufs/fs/aufs/vfsub.h 2009-03-12 16:18:04.000000000 +0100
24830@@ -0,0 +1,530 @@
24831+/*
24832+ * Copyright (C) 2005-2009 Junjiro Okajima
24833+ *
24834+ * This program, aufs is free software; you can redistribute it and/or modify
24835+ * it under the terms of the GNU General Public License as published by
24836+ * the Free Software Foundation; either version 2 of the License, or
24837+ * (at your option) any later version.
24838+ *
24839+ * This program is distributed in the hope that it will be useful,
24840+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24841+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24842+ * GNU General Public License for more details.
24843+ *
24844+ * You should have received a copy of the GNU General Public License
24845+ * along with this program; if not, write to the Free Software
24846+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24847+ */
24848+
24849+/*
24850+ * sub-routines for VFS
24851+ *
24852+ * $Id$
24853+ */
24854+
24855+#ifndef __AUFS_VFSUB_H__
24856+#define __AUFS_VFSUB_H__
24857+
24858+#ifdef __KERNEL__
24859+
24860+#include <linux/fs.h>
24861+#include <linux/fs_stack.h>
24862+#include <linux/inotify.h>
24863+#include <linux/namei.h>
24864+#include <linux/security.h>
24865+#include <linux/splice.h>
24866+
24867+/* ---------------------------------------------------------------------- */
24868+
24869+/* vfsub flags */
24870+#define Vfsub_DLGT 1 /* operation with delegation */
24871+#define Vfsub_FORCE_UNLINK (1 << 1) /* force unlinking */
24872+#define vfsub_ftest(flags, name) ((flags) & Vfsub_##name)
24873+#define vfsub_fset(flags, name) { (flags) |= Vfsub_##name; }
24874+#define vfsub_fclr(flags, name) { (flags) &= ~Vfsub_##name; }
24875+#ifndef CONFIG_AUFS_DLGT
24876+#undef Vfsub_DLGT
24877+#define Vfsub_DLGT 0
24878+#endif
24879+
24880+struct au_hin_ignore;
24881+struct vfsub_args {
24882+#ifdef CONFIG_AUFS_HINOTIFY
24883+ /* inotify events to be ignored */
24884+ int nignore;
24885+ struct au_hin_ignore *ignore;
24886+#endif
24887+
24888+ unsigned int flags;
24889+};
24890+
24891+struct au_hinode;
24892+#ifdef CONFIG_AUFS_HINOTIFY
24893+static inline
24894+void do_vfsub_args_reinit(struct vfsub_args *vargs, struct au_hin_ignore *ign)
24895+{
24896+ vargs->nignore = 0;
24897+ vargs->ignore = ign;
24898+}
24899+
24900+static inline void vfsub_args_reinit(struct vfsub_args *vargs)
24901+{
24902+ vargs->nignore = 0;
24903+}
24904+
24905+__u32 vfsub_events_notify_change(struct iattr *ia);
24906+void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events,
24907+ struct au_hinode *hinode);
24908+void vfsub_ignore(struct vfsub_args *vargs);
24909+void vfsub_unignore(struct vfsub_args *vargs);
24910+#else
24911+static inline
24912+void do_vfsub_args_reinit(struct vfsub_args *vargs, struct au_hin_ignore *ign)
24913+{
24914+ /* empty */
24915+}
24916+
24917+static inline void vfsub_args_reinit(struct vfsub_args *vargs)
24918+{
24919+ /* empty */
24920+}
24921+
24922+static inline __u32 vfsub_events_notify_change(struct iattr *ia)
24923+{
24924+ return 0;
24925+}
24926+
24927+static inline void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events,
24928+ struct au_hinode *hinode)
24929+{
24930+ /* empty */
24931+}
24932+
24933+static inline void vfsub_ignore(struct vfsub_args *vargs)
24934+{
24935+ /* empty */
24936+}
24937+
24938+static inline void vfsub_unignore(struct vfsub_args *vargs)
24939+{
24940+ /* empty */
24941+}
24942+#endif /* CONFIG_AUFS_HINOTIFY */
24943+
24944+void vfsub_args_init(struct vfsub_args *vargs, struct au_hin_ignore *ign,
24945+ int dlgt, int force_unlink);
24946+
24947+/* ---------------------------------------------------------------------- */
24948+
24949+/* inotify_inode_watched() is not exported */
24950+static inline int au_test_inotify(struct inode *inode)
24951+{
24952+#ifdef CONFIG_INOTIFY
24953+ return !list_empty(&inode->inotify_watches);
24954+#endif
24955+ return 0;
24956+}
24957+
24958+/* ---------------------------------------------------------------------- */
24959+
24960+/* lock subclass for hidden inode */
24961+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
24962+/* reduce? gave up. */
24963+enum {
24964+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
24965+ AuLsc_I_PARENT, /* hidden inode, parent first */
24966+ AuLsc_I_PARENT2, /* copyup dirs */
24967+ AuLsc_I_PARENT3, /* rename with hinotify */
24968+ AuLsc_I_PARENT4, /* ditto */
24969+ AuLsc_I_CHILD,
24970+ AuLsc_I_CHILD2,
24971+ AuLsc_I_End
24972+};
24973+
24974+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
24975+
24976+static inline void vfsub_lock_rename_mutex(struct super_block *sb)
24977+{
24978+ lockdep_off();
24979+ mutex_lock(&sb->s_vfs_rename_mutex);
24980+ lockdep_on();
24981+}
24982+
24983+static inline void vfsub_unlock_rename_mutex(struct super_block *sb)
24984+{
24985+ lockdep_off();
24986+ mutex_unlock(&sb->s_vfs_rename_mutex);
24987+ lockdep_on();
24988+}
24989+
24990+static inline int vfsub_is_rename_mutex_locked(struct super_block *sb)
24991+{
24992+ int res;
24993+
24994+ lockdep_off();
24995+ res = mutex_is_locked(&sb->s_vfs_rename_mutex);
24996+ lockdep_on();
24997+
24998+ return res;
24999+}
25000+
25001+static inline
25002+struct dentry *vfsub_lock_rename(struct dentry *d1, struct dentry *d2)
25003+{
25004+ struct dentry *d;
25005+
25006+ lockdep_off();
25007+ d = lock_rename(d1, d2);
25008+ lockdep_on();
25009+ return d;
25010+}
25011+
25012+static inline void vfsub_unlock_rename(struct dentry *d1, struct dentry *d2)
25013+{
25014+ lockdep_off();
25015+ unlock_rename(d1, d2);
25016+ lockdep_on();
25017+}
25018+
25019+static inline int au_verify_parent(struct dentry *dentry, struct inode *dir)
25020+{
25021+ IMustLock(dir);
25022+ return /* !dir->i_nlink || */ dentry->d_parent->d_inode != dir;
25023+}
25024+
25025+/* ---------------------------------------------------------------------- */
25026+
25027+#ifdef CONFIG_AUFS_WORKAROUND_FUSE
25028+/* br_fuse.c */
25029+int au_update_fuse_h_inode(struct vfsmount *h_mnt, struct dentry *h_dentry);
25030+#else
25031+static inline
25032+int au_update_fuse_h_inode(struct vfsmount *h_mnt, struct dentry *h_dentry)
25033+{
25034+ return 0;
25035+}
25036+#endif
25037+
25038+#ifdef CONFIG_AUFS_BR_XFS
25039+/* br_xfs.c */
25040+dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt,
25041+ struct dentry *h_dentry);
25042+#else
25043+static inline
25044+dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt,
25045+ struct dentry *h_dentry)
25046+{
25047+ return h_inode->i_rdev;
25048+}
25049+#endif
25050+
25051+/* simple abstractions, for future use */
25052+static inline
25053+int do_vfsub_permission(struct inode *inode, int mask, struct nameidata *nd)
25054+{
25055+ LKTRTrace("i%lu, mask 0x%x, nd %d\n", inode->i_ino, mask, !!nd);
25056+ IMustLock(inode);
25057+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
25058+ return inode_permission(inode, mask);
25059+#else
25060+ return permission(inode, mask, nd);
25061+#endif
25062+}
25063+
25064+static inline
25065+int vfsub_security_inode_permission(struct inode *inode, int mask,
25066+ struct nameidata *nd)
25067+{
25068+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
25069+ mask &= MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND;
25070+ return security_inode_permission(inode, mask);
25071+#else
25072+ return security_inode_permission(inode, mask, nd);
25073+#endif
25074+}
25075+
25076+/* ---------------------------------------------------------------------- */
25077+
25078+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
25079+int vfsub_path_lookup(const char *name, unsigned int flags,
25080+ struct nameidata *nd);
25081+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
25082+ int len);
25083+
25084+#ifdef CONFIG_AUFS_LHASH_PATCH
25085+struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent,
25086+ struct nameidata *nd);
25087+#endif
25088+
25089+/* ---------------------------------------------------------------------- */
25090+
25091+int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
25092+ struct nameidata *nd);
25093+int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
25094+ const char *symname, int mode);
25095+int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
25096+ dev_t dev);
25097+int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
25098+ struct dentry *dentry);
25099+int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
25100+ struct inode *dir, struct dentry *dentry);
25101+int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode);
25102+int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry);
25103+int do_vfsub_unlink(struct inode *dir, struct dentry *dentry);
25104+
25105+/* ---------------------------------------------------------------------- */
25106+
25107+ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
25108+ loff_t *ppos);
25109+/* todo: kernel_read()? */
25110+ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count,
25111+ loff_t *ppos);
25112+ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
25113+ size_t count, loff_t *ppos);
25114+ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count,
25115+ loff_t *ppos);
25116+int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
25117+
25118+/* ---------------------------------------------------------------------- */
25119+
25120+#ifndef CONFIG_AUFS_UNIONFS22_PATCH
25121+static inline void vfsub_copy_inode_size(struct inode *inode,
25122+ struct inode *h_inode)
25123+{
25124+ spin_lock(&inode->i_lock);
25125+ fsstack_copy_inode_size(inode, h_inode);
25126+ spin_unlock(&inode->i_lock);
25127+}
25128+#else
25129+static inline void vfsub_copy_inode_size(struct inode *inode,
25130+ struct inode *h_inode)
25131+{
25132+ fsstack_copy_inode_size(inode, h_inode);
25133+}
25134+#endif
25135+
25136+#ifndef CONFIG_AUFS_UNIONFS23_PATCH
25137+#define vfs_splice_to do_splice_to
25138+#define vfs_splice_from do_splice_from
25139+#endif
25140+
25141+#ifdef CONFIG_AUFS_SPLICE_PATCH
25142+long do_vfsub_splice_to(struct file *in, loff_t *ppos,
25143+ struct pipe_inode_info *pipe, size_t len,
25144+ unsigned int flags);
25145+long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
25146+ loff_t *ppos, size_t len, unsigned int flags);
25147+#else
25148+static inline
25149+long do_vfsub_splice_to(struct file *in, loff_t *ppos,
25150+ struct pipe_inode_info *pipe, size_t len,
25151+ unsigned int flags)
25152+{
25153+ return -ENOSYS;
25154+}
25155+
25156+static inline
25157+long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
25158+ loff_t *ppos, size_t len, unsigned int flags)
25159+{
25160+ return -ENOSYS;
25161+}
25162+#endif /* CONFIG_AUFS_SPLICE_PATCH */
25163+
25164+/* ---------------------------------------------------------------------- */
25165+
25166+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
25167+{
25168+ loff_t err;
25169+
25170+ LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry));
25171+
25172+ lockdep_off();
25173+ err = vfs_llseek(file, offset, origin);
25174+ lockdep_on();
25175+ return err;
25176+}
25177+
25178+static inline int do_vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry,
25179+ struct kstat *st)
25180+{
25181+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
25182+ return vfs_getattr(mnt, dentry, st);
25183+}
25184+
25185+/* ---------------------------------------------------------------------- */
25186+
25187+#ifdef CONFIG_AUFS_HIN_OR_DLGT
25188+/* hin_or_dlgt.c */
25189+int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
25190+ int dlgt);
25191+
25192+int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
25193+ struct nameidata *nd, struct vfsub_args *vargs);
25194+int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
25195+ int mode, struct vfsub_args *vargs);
25196+int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
25197+ struct vfsub_args *vargs);
25198+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
25199+ struct dentry *dentry, struct vfsub_args *vargs);
25200+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
25201+ struct inode *dir, struct dentry *dentry,
25202+ struct vfsub_args *vargs);
25203+int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode,
25204+ struct vfsub_args *vargs);
25205+int vfsub_rmdir(struct inode *dir, struct dentry *dentry,
25206+ struct vfsub_args *vargs);
25207+
25208+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
25209+ loff_t *ppos, int dlgt);
25210+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
25211+ int dlgt);
25212+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
25213+ loff_t *ppos, struct vfsub_args *vargs);
25214+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
25215+ struct vfsub_args *vargs);
25216+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt);
25217+long vfsub_splice_to(struct file *in, loff_t *ppos,
25218+ struct pipe_inode_info *pipe, size_t len,
25219+ unsigned int flags, int dlgt);
25220+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
25221+ loff_t *ppos, size_t len, unsigned int flags,
25222+ struct vfsub_args *vargs);
25223+
25224+int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st,
25225+ int dlgt);
25226+#else
25227+
25228+static inline
25229+int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
25230+ int dlgt)
25231+{
25232+ return do_vfsub_permission(inode, mask, nd);
25233+}
25234+
25235+static inline
25236+int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
25237+ struct nameidata *nd, struct vfsub_args *vargs)
25238+{
25239+ return do_vfsub_create(dir, dentry, mode, nd);
25240+}
25241+
25242+static inline
25243+int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
25244+ int mode, struct vfsub_args *vargs)
25245+{
25246+ return do_vfsub_symlink(dir, dentry, symname, mode);
25247+}
25248+
25249+static inline
25250+int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
25251+ struct vfsub_args *vargs)
25252+{
25253+ return do_vfsub_mknod(dir, dentry, mode, dev);
25254+}
25255+
25256+static inline
25257+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
25258+ struct dentry *dentry, struct vfsub_args *vargs)
25259+{
25260+ return do_vfsub_link(src_dentry, dir, dentry);
25261+}
25262+
25263+static inline
25264+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
25265+ struct inode *dir, struct dentry *dentry,
25266+ struct vfsub_args *vargs)
25267+{
25268+ return do_vfsub_rename(src_dir, src_dentry, dir, dentry);
25269+}
25270+
25271+static inline
25272+int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode,
25273+ struct vfsub_args *vargs)
25274+{
25275+ return do_vfsub_mkdir(dir, dentry, mode);
25276+}
25277+
25278+static inline
25279+int vfsub_rmdir(struct inode *dir, struct dentry *dentry,
25280+ struct vfsub_args *vargs)
25281+{
25282+ return do_vfsub_rmdir(dir, dentry);
25283+}
25284+
25285+static inline
25286+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
25287+ loff_t *ppos, int dlgt)
25288+{
25289+ return do_vfsub_read_u(file, ubuf, count, ppos);
25290+}
25291+
25292+static inline
25293+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
25294+ int dlgt)
25295+{
25296+ return do_vfsub_read_k(file, kbuf, count, ppos);
25297+}
25298+
25299+static inline
25300+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
25301+ loff_t *ppos, struct vfsub_args *vargs)
25302+{
25303+ return do_vfsub_write_u(file, ubuf, count, ppos);
25304+}
25305+
25306+static inline
25307+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
25308+ struct vfsub_args *vargs)
25309+{
25310+ return do_vfsub_write_k(file, kbuf, count, ppos);
25311+}
25312+
25313+static inline
25314+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
25315+{
25316+ return do_vfsub_readdir(file, filldir, arg);
25317+}
25318+
25319+static inline
25320+long vfsub_splice_to(struct file *in, loff_t *ppos,
25321+ struct pipe_inode_info *pipe, size_t len,
25322+ unsigned int flags, int dlgt)
25323+{
25324+ return do_vfsub_splice_to(in, ppos, pipe, len, flags);
25325+}
25326+
25327+static inline
25328+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
25329+ loff_t *ppos, size_t len, unsigned int flags,
25330+ struct vfsub_args *vargs)
25331+{
25332+ return do_vfsub_splice_from(pipe, out, ppos, len, flags);
25333+}
25334+
25335+static inline
25336+int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st,
25337+ int dlgt)
25338+{
25339+ return do_vfsub_getattr(mnt, dentry, st);
25340+}
25341+#endif /* HIN_OR_DLGT */
25342+
25343+/* ---------------------------------------------------------------------- */
25344+
25345+int vfsub_sio_mkdir(struct au_hinode *hdir, struct dentry *dentry, int mode,
25346+ int dlgt);
25347+int vfsub_sio_rmdir(struct au_hinode *hdir, struct dentry *dentry, int dlgt);
25348+int vfsub_sio_notify_change(struct au_hinode *hdir, struct dentry *dentry,
25349+ struct iattr *ia);
25350+
25351+/* ---------------------------------------------------------------------- */
25352+
25353+int vfsub_notify_change(struct dentry *dentry, struct iattr *ia,
25354+ struct vfsub_args *vargs);
25355+int vfsub_unlink(struct inode *dir, struct dentry *dentry,
25356+ struct vfsub_args *vargs);
25357+int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt);
25358+
25359+#endif /* __KERNEL__ */
25360+#endif /* __AUFS_VFSUB_H__ */
25361diff -urN linux/fs/aufs/wbr_policy.c linux-aufs/fs/aufs/wbr_policy.c
25362--- linux/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
25363+++ linux-aufs/fs/aufs/wbr_policy.c 2009-03-12 16:18:04.000000000 +0100
25364@@ -0,0 +1,696 @@
25365+/*
25366+ * Copyright (C) 2005-2009 Junjiro Okajima
25367+ *
25368+ * This program, aufs is free software; you can redistribute it and/or modify
25369+ * it under the terms of the GNU General Public License as published by
25370+ * the Free Software Foundation; either version 2 of the License, or
25371+ * (at your option) any later version.
25372+ *
25373+ * This program is distributed in the hope that it will be useful,
25374+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25375+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25376+ * GNU General Public License for more details.
25377+ *
25378+ * You should have received a copy of the GNU General Public License
25379+ * along with this program; if not, write to the Free Software
25380+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25381+ */
25382+
25383+/*
25384+ * policies for selecting one among multiple writable branches
25385+ *
25386+ * $Id$
25387+ */
25388+
25389+#include <linux/statfs.h>
25390+#include "aufs.h"
25391+
25392+static int au_cpdown_attr(struct au_hinode *hdir, struct dentry *h_dst,
25393+ struct dentry *h_src)
25394+{
25395+ int err, sbits;
25396+ struct iattr ia;
25397+ struct inode *h_idst, *h_isrc;
25398+
25399+ LKTRTrace("%.*s\n", AuDLNPair(h_dst));
25400+ h_idst = h_dst->d_inode;
25401+ /* todo? IMustLock(h_idst); */
25402+ h_isrc = h_src->d_inode;
25403+ /* todo? IMustLock(h_isrc); */
25404+
25405+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
25406+ ia.ia_mode = h_isrc->i_mode;
25407+ ia.ia_uid = h_isrc->i_uid;
25408+ ia.ia_gid = h_isrc->i_gid;
25409+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
25410+ au_cpup_attr_flags(h_idst, h_isrc);
25411+ err = vfsub_sio_notify_change(hdir, h_dst, &ia);
25412+
25413+ /* is this nfs only? */
25414+ if (!err && sbits && au_test_nfs(h_dst->d_sb)) {
25415+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
25416+ ia.ia_mode = h_isrc->i_mode;
25417+ err = vfsub_sio_notify_change(hdir, h_dst, &ia);
25418+ }
25419+
25420+ AuTraceErr(err);
25421+ return err;
25422+}
25423+
25424+struct au_cpdown_dir_args {
25425+ struct dentry *parent;
25426+ unsigned int parent_opq; /* bit-flags */
25427+};
25428+
25429+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
25430+ struct dentry *h_parent, void *arg)
25431+{
25432+ int err, rerr;
25433+ struct au_cpdown_dir_args *args = arg;
25434+ aufs_bindex_t bend, bopq, bstart;
25435+ unsigned char parent_opq, whed, dlgt, do_opq, made_dir, diropq;
25436+ struct dentry *h_dentry, *opq_dentry, *wh_dentry, *parent;
25437+ struct inode *h_dir, *h_inode, *inode, *dir;
25438+
25439+ LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bdst);
25440+ bstart = au_dbstart(dentry);
25441+ AuDebugOn(bstart <= bdst
25442+ && bdst <= au_dbend(dentry)
25443+ && au_h_dptr(dentry, bdst));
25444+ AuDebugOn(!h_parent);
25445+ /* todo: safe? */
25446+ parent = dget_parent(dentry);
25447+ dir = parent->d_inode;
25448+ dput(parent);
25449+ h_dir = h_parent->d_inode;
25450+ AuDebugOn(!h_dir);
25451+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
25452+ IMustLock(h_dir);
25453+
25454+ err = au_lkup_neg(dentry, bdst);
25455+ if (unlikely(err < 0))
25456+ goto out;
25457+ h_dentry = au_h_dptr(dentry, bdst);
25458+ dlgt = !!au_test_dlgt(au_mntflags(dentry->d_sb));
25459+ err = vfsub_sio_mkdir(au_hi(dir, bdst), h_dentry,
25460+ S_IRWXU | S_IRUGO | S_IXUGO, dlgt);
25461+ if (unlikely(err))
25462+ goto out_put;
25463+
25464+ made_dir = 1;
25465+ bend = au_dbend(dentry);
25466+ bopq = au_dbdiropq(dentry);
25467+ whed = (au_dbwh(dentry) == bdst);
25468+ if (!args->parent_opq)
25469+ args->parent_opq |= (bopq <= bdst);
25470+ parent_opq = (args->parent_opq && args->parent == dentry);
25471+ do_opq = 0;
25472+ diropq = 0;
25473+ h_inode = h_dentry->d_inode;
25474+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
25475+ if (whed || (parent_opq && do_opq)) {
25476+ opq_dentry = au_diropq_create(dentry, bdst, dlgt);
25477+ err = PTR_ERR(opq_dentry);
25478+ if (IS_ERR(opq_dentry)) {
25479+ mutex_unlock(&h_inode->i_mutex);
25480+ goto out_dir;
25481+ }
25482+ dput(opq_dentry);
25483+ diropq = 1;
25484+ }
25485+
25486+ err = au_cpdown_attr(au_hi(dir, bdst), h_dentry,
25487+ au_h_dptr(dentry, bstart));
25488+ mutex_unlock(&h_inode->i_mutex);
25489+ if (unlikely(err))
25490+ goto out_opq;
25491+
25492+ wh_dentry = NULL;
25493+ if (whed) {
25494+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, /*ndx*/NULL);
25495+ err = PTR_ERR(wh_dentry);
25496+ if (IS_ERR(wh_dentry))
25497+ goto out_opq;
25498+ err = 0;
25499+ if (wh_dentry->d_inode)
25500+ err = au_wh_unlink_dentry(au_hi(dir, bdst), wh_dentry,
25501+ dentry, dlgt);
25502+ dput(wh_dentry);
25503+ if (unlikely(err))
25504+ goto out_opq;
25505+ }
25506+
25507+ inode = dentry->d_inode;
25508+ if (au_ibend(inode) < bdst)
25509+ au_set_ibend(inode, bdst);
25510+ au_set_h_iptr(inode, bdst, au_igrab(h_inode), au_hi_flags(inode, 1));
25511+ goto out; /* success */
25512+
25513+ /* revert */
25514+ out_opq:
25515+ if (diropq) {
25516+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
25517+ rerr = au_diropq_remove(dentry, bdst, dlgt);
25518+ mutex_unlock(&h_inode->i_mutex);
25519+ if (unlikely(rerr)) {
25520+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
25521+ AuDLNPair(dentry), bdst, rerr);
25522+ err = -EIO;
25523+ goto out;
25524+ }
25525+ }
25526+ out_dir:
25527+ if (made_dir) {
25528+ rerr = vfsub_sio_rmdir(au_hi(dir, bdst), h_dentry, dlgt);
25529+ if (unlikely(rerr)) {
25530+ AuIOErr("failed removing %.*s b%d (%d)\n",
25531+ AuDLNPair(dentry), bdst, rerr);
25532+ err = -EIO;
25533+ }
25534+ }
25535+ out_put:
25536+ au_set_h_dptr(dentry, bdst, NULL);
25537+ if (au_dbend(dentry) == bdst)
25538+ au_update_dbend(dentry);
25539+ out:
25540+ AuTraceErr(err);
25541+ return err;
25542+}
25543+
25544+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
25545+{
25546+ int err;
25547+ struct au_cpdown_dir_args args = {
25548+ .parent = dget_parent(dentry),
25549+ .parent_opq = 0
25550+ };
25551+
25552+ LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bdst);
25553+
25554+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
25555+ dput(args.parent);
25556+
25557+ AuTraceErr(err);
25558+ return err;
25559+}
25560+
25561+/* ---------------------------------------------------------------------- */
25562+
25563+/* policies for create */
25564+
25565+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
25566+{
25567+ for (; bindex >= 0; bindex--)
25568+ if (!au_br_rdonly(au_sbr(sb, bindex)))
25569+ return bindex;
25570+ return -EROFS;
25571+}
25572+
25573+/* top down parent */
25574+static int au_wbr_create_tdp(struct dentry *dentry, int isdir)
25575+{
25576+ int err;
25577+ struct super_block *sb;
25578+ aufs_bindex_t bstart, bindex;
25579+ unsigned char dirperm1;
25580+ struct dentry *parent, *h_parent;
25581+ struct inode *h_dir;
25582+
25583+ LKTRTrace("%.*s, dir %d\n", AuDLNPair(dentry), isdir);
25584+
25585+ sb = dentry->d_sb;
25586+ dirperm1 = !!au_test_dirperm1(au_mntflags(sb));
25587+ bstart = au_dbstart(dentry);
25588+ AuDebugOn(bstart < 0);
25589+ err = bstart;
25590+ /* todo: can 'err' be an illegal? */
25591+ if (/* err >= 0 && */ !au_br_rdonly(au_sbr(sb, bstart)))
25592+ goto out;
25593+
25594+ err = -EROFS;
25595+ parent = dget_parent(dentry);
25596+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
25597+ h_parent = au_h_dptr(parent, bindex);
25598+ if (!h_parent)
25599+ continue;
25600+ h_dir = h_parent->d_inode;
25601+ if (!h_dir)
25602+ continue;
25603+
25604+ if (!au_br_rdonly(au_sbr(sb, bindex))
25605+ && (!dirperm1
25606+ || au_test_h_perm(h_dir, MAY_WRITE | MAY_EXEC,
25607+ /*dlgt*/0))) {
25608+ err = bindex;
25609+ break;
25610+ }
25611+ }
25612+ dput(parent);
25613+
25614+ /* bottom up here */
25615+ if (unlikely(err < 0))
25616+ err = au_wbr_bu(sb, bstart - 1);
25617+
25618+ out:
25619+ LKTRTrace("b%d\n", err);
25620+ return err;
25621+}
25622+
25623+/* ---------------------------------------------------------------------- */
25624+
25625+/* an exception for the policy other than tdp */
25626+static int au_wbr_create_exp(struct dentry *dentry)
25627+{
25628+ int err;
25629+ struct dentry *parent;
25630+ aufs_bindex_t bwh, bdiropq;
25631+
25632+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
25633+
25634+ err = -1;
25635+ bwh = au_dbwh(dentry);
25636+ parent = dget_parent(dentry);
25637+ bdiropq = au_dbdiropq(parent);
25638+ if (bwh >= 0) {
25639+ if (bdiropq >= 0)
25640+ err = min(bdiropq, bwh);
25641+ else
25642+ err = bwh;
25643+ LKTRTrace("%d\n", err);
25644+ } else if (bdiropq >= 0) {
25645+ err = bdiropq;
25646+ LKTRTrace("%d\n", err);
25647+ }
25648+ dput(parent);
25649+
25650+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
25651+ err = -1;
25652+
25653+ LKTRTrace("%d\n", err);
25654+ return err;
25655+}
25656+
25657+/* ---------------------------------------------------------------------- */
25658+
25659+/* round robin */
25660+static int au_wbr_create_init_rr(struct super_block *sb)
25661+{
25662+ int err;
25663+
25664+ err = au_wbr_bu(sb, au_sbend(sb));
25665+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
25666+
25667+ LKTRTrace("b%d\n", err);
25668+ return err;
25669+}
25670+
25671+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
25672+{
25673+ int err, nbr;
25674+ struct super_block *sb;
25675+ atomic_t *next;
25676+ unsigned int u;
25677+ aufs_bindex_t bindex, bend;
25678+
25679+ LKTRTrace("%.*s, dir %d\n", AuDLNPair(dentry), isdir);
25680+
25681+ sb = dentry->d_sb;
25682+ next = NULL;
25683+ err = au_wbr_create_exp(dentry);
25684+ if (err >= 0)
25685+ goto out;
25686+
25687+ next = &au_sbi(sb)->si_wbr_rr_next;
25688+ bend = au_sbend(sb);
25689+ nbr = bend + 1;
25690+ for (bindex = 0; bindex <= bend; bindex++) {
25691+ if (!isdir) {
25692+ err = atomic_dec_return(next) + 1;
25693+ /* modulo for 0 is meaningless */
25694+ if (unlikely(!err))
25695+ err = atomic_dec_return(next) + 1;
25696+ } else
25697+ err = atomic_read(next);
25698+ LKTRTrace("%d\n", err);
25699+ u = err;
25700+ err = u % nbr;
25701+ LKTRTrace("%d\n", err);
25702+ if (!au_br_rdonly(au_sbr(sb, err)))
25703+ break;
25704+ err = -EROFS;
25705+ }
25706+
25707+ out:
25708+ LKTRTrace("%d\n", err);
25709+ return err;
25710+}
25711+
25712+/* ---------------------------------------------------------------------- */
25713+
25714+/* most free space */
25715+static void *au_wbr_statfs_arg(struct au_branch *br, struct super_block *sb,
25716+ aufs_bindex_t bindex)
25717+{
25718+ struct super_block *h_sb;
25719+
25720+ h_sb = br->br_mnt->mnt_sb;
25721+
25722+ if (!au_test_nfs(h_sb))
25723+ return h_sb->s_root;
25724+
25725+ /* sigh,,, why nfs s_root has wrong inode? */
25726+ return au_di(sb->s_root)->di_hdentry[0 + bindex].hd_dentry;
25727+}
25728+
25729+static void au_mfs(struct dentry *dentry)
25730+{
25731+ struct super_block *sb;
25732+ aufs_bindex_t bindex, bend;
25733+ unsigned char dlgt;
25734+ int err;
25735+ struct kstatfs st;
25736+ unsigned long long b, bavail;
25737+ void *arg;
25738+ struct au_branch *br;
25739+ struct au_wbr_mfs *mfs;
25740+
25741+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
25742+
25743+ bavail = 0;
25744+ sb = dentry->d_sb;
25745+ mfs = &au_sbi(sb)->si_wbr_mfs;
25746+ mfs->mfs_bindex = -EROFS;
25747+ mfs->mfsrr_bytes = 0;
25748+ dlgt = !!au_test_dlgt(au_mntflags(sb));
25749+ bend = au_sbend(sb);
25750+ for (bindex = 0; bindex <= bend; bindex++) {
25751+ br = au_sbr(sb, bindex);
25752+ if (au_br_rdonly(br))
25753+ continue;
25754+ AuDebugOn(!br->br_wbr);
25755+ arg = au_wbr_statfs_arg(br, sb, bindex);
25756+ if (!arg)
25757+ continue;
25758+
25759+ err = vfsub_statfs(arg, &st, dlgt);
25760+ LKTRTrace("b%d, %d, %llu\n",
25761+ bindex, err, (unsigned long long)st.f_bavail);
25762+ if (unlikely(err)) {
25763+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
25764+ continue;
25765+ }
25766+
25767+ /* when the available size is equal, select lower one */
25768+ b = st.f_bavail * st.f_bsize;
25769+ br->br_wbr->wbr_bytes = b;
25770+ if (b >= bavail) {
25771+ bavail = b;
25772+ mfs->mfs_bindex = bindex;
25773+ mfs->mfs_jiffy = jiffies;
25774+ }
25775+ }
25776+
25777+ mfs->mfsrr_bytes = bavail;
25778+ LKTRTrace("b%d\n", mfs->mfs_bindex);
25779+}
25780+
25781+static int au_wbr_create_mfs(struct dentry *dentry, int isdir)
25782+{
25783+ int err;
25784+ struct super_block *sb;
25785+ struct au_wbr_mfs *mfs;
25786+
25787+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
25788+
25789+ sb = dentry->d_sb;
25790+ err = au_wbr_create_exp(dentry);
25791+ if (err >= 0)
25792+ goto out;
25793+
25794+ mfs = &au_sbi(sb)->si_wbr_mfs;
25795+ mutex_lock(&mfs->mfs_lock);
25796+ if (unlikely(time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
25797+ || mfs->mfs_bindex < 0
25798+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex))))
25799+ au_mfs(dentry);
25800+ mutex_unlock(&mfs->mfs_lock);
25801+ err = mfs->mfs_bindex;
25802+
25803+ out:
25804+ LKTRTrace("b%d\n", err);
25805+ return err;
25806+}
25807+
25808+static int au_wbr_create_init_mfs(struct super_block *sb)
25809+{
25810+ struct au_wbr_mfs *mfs;
25811+
25812+ mfs = &au_sbi(sb)->si_wbr_mfs;
25813+ LKTRTrace("expire %lu\n", mfs->mfs_expire);
25814+
25815+ mutex_init(&mfs->mfs_lock);
25816+ mfs->mfs_jiffy = 0;
25817+ mfs->mfs_bindex = -EROFS;
25818+
25819+ return 0;
25820+}
25821+
25822+static int au_wbr_create_fin_mfs(struct super_block *sb)
25823+{
25824+ AuTraceEnter();
25825+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
25826+ return 0;
25827+}
25828+
25829+/* ---------------------------------------------------------------------- */
25830+
25831+/* most free space and then round robin */
25832+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
25833+{
25834+ int err;
25835+ struct au_wbr_mfs *mfs;
25836+
25837+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), isdir);
25838+
25839+ err = au_wbr_create_mfs(dentry, isdir);
25840+ if (err >= 0) {
25841+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
25842+ LKTRTrace("%llu bytes, %llu wmark\n",
25843+ mfs->mfsrr_bytes, mfs->mfsrr_watermark);
25844+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
25845+ err = au_wbr_create_rr(dentry, isdir);
25846+ }
25847+
25848+ LKTRTrace("b%d\n", err);
25849+ return err;
25850+}
25851+
25852+static int au_wbr_create_init_mfsrr(struct super_block *sb)
25853+{
25854+ int err;
25855+
25856+ au_wbr_create_init_mfs(sb); /* ignore */
25857+ err = au_wbr_create_init_rr(sb);
25858+
25859+ AuTraceErr(err);
25860+ return err;
25861+}
25862+
25863+/* ---------------------------------------------------------------------- */
25864+
25865+/* top down parent and most free space */
25866+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
25867+{
25868+ int err, e2;
25869+ struct super_block *sb;
25870+ struct dentry *parent, *h_parent;
25871+ aufs_bindex_t bindex, bstart, bend;
25872+ unsigned char dirperm1;
25873+ struct au_branch *br;
25874+ unsigned long long b;
25875+ struct inode *h_dir;
25876+
25877+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), isdir);
25878+
25879+ err = au_wbr_create_tdp(dentry, isdir);
25880+ if (unlikely(err < 0))
25881+ goto out;
25882+ parent = dget_parent(dentry);
25883+ bstart = au_dbstart(parent);
25884+ bend = au_dbtaildir(parent);
25885+ if (bstart == bend)
25886+ goto out_parent; /* success */
25887+
25888+ e2 = au_wbr_create_mfs(dentry, isdir);
25889+ if (e2 < 0)
25890+ goto out_parent; /* success */
25891+
25892+ /* when the available size is equal, select upper one */
25893+ sb = dentry->d_sb;
25894+ br = au_sbr(sb, err);
25895+ AuDebugOn(!br->br_wbr);
25896+ dirperm1 = !!au_test_dirperm1(au_mntflags(sb));
25897+ b = br->br_wbr->wbr_bytes;
25898+ LKTRTrace("b%d, %llu\n", err, b);
25899+
25900+ if (dirperm1) {
25901+ for (bindex = bstart; bindex <= bend; bindex++) {
25902+ h_parent = au_h_dptr(parent, bindex);
25903+ if (!h_parent)
25904+ continue;
25905+ h_dir = h_parent->d_inode;
25906+ if (!h_dir)
25907+ continue;
25908+
25909+ br = au_sbr(sb, bindex);
25910+ if (!au_br_rdonly(br)
25911+ && au_test_h_perm(h_dir, MAY_WRITE | MAY_EXEC,
25912+ /*dlgt*/0)
25913+ && br->br_wbr->wbr_bytes > b) {
25914+ b = br->br_wbr->wbr_bytes;
25915+ err = bindex;
25916+ LKTRTrace("b%d, %llu\n", err, b);
25917+ }
25918+ }
25919+ if (err >= 0)
25920+ goto out_parent;
25921+ }
25922+ for (bindex = bstart; bindex <= bend; bindex++) {
25923+ h_parent = au_h_dptr(parent, bindex);
25924+ if (!h_parent || !h_parent->d_inode)
25925+ continue;
25926+
25927+ br = au_sbr(sb, bindex);
25928+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
25929+ b = br->br_wbr->wbr_bytes;
25930+ err = bindex;
25931+ LKTRTrace("b%d, %llu\n", err, b);
25932+ }
25933+ }
25934+
25935+ out_parent:
25936+ dput(parent);
25937+ out:
25938+ LKTRTrace("b%d\n", err);
25939+ return err;
25940+}
25941+
25942+/* ---------------------------------------------------------------------- */
25943+
25944+/* policies for copyup */
25945+
25946+/* top down parent */
25947+static int au_wbr_copyup_tdp(struct dentry *dentry)
25948+{
25949+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
25950+}
25951+
25952+/* bottom up parent */
25953+static int au_wbr_copyup_bup(struct dentry *dentry)
25954+{
25955+ int err;
25956+ struct dentry *parent, *h_parent;
25957+ aufs_bindex_t bindex, bstart;
25958+ unsigned char dirperm1;
25959+ struct super_block *sb;
25960+ struct inode *h_dir;
25961+
25962+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
25963+
25964+ err = -EROFS;
25965+ sb = dentry->d_sb;
25966+ dirperm1 = !!au_test_dirperm1(au_mntflags(sb));
25967+ parent = dget_parent(dentry);
25968+ bstart = au_dbstart(parent);
25969+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
25970+ h_parent = au_h_dptr(parent, bindex);
25971+ if (!h_parent)
25972+ continue;
25973+ h_dir = h_parent->d_inode;
25974+ if (!h_dir)
25975+ continue;
25976+
25977+ if (!au_br_rdonly(au_sbr(sb, bindex))
25978+ && (!dirperm1
25979+ || au_test_h_perm(h_dir, MAY_WRITE | MAY_EXEC,
25980+ /*dlgt*/0))) {
25981+ err = bindex;
25982+ break;
25983+ }
25984+ }
25985+ dput(parent);
25986+
25987+ /* bottom up here */
25988+ if (unlikely(err < 0))
25989+ err = au_wbr_bu(sb, bstart - 1);
25990+
25991+ LKTRTrace("b%d\n", err);
25992+ return err;
25993+}
25994+
25995+/* bottom up */
25996+static int au_wbr_copyup_bu(struct dentry *dentry)
25997+{
25998+ int err;
25999+
26000+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
26001+
26002+ err = au_wbr_bu(dentry->d_sb, au_dbstart(dentry));
26003+
26004+ LKTRTrace("b%d\n", err);
26005+ return err;
26006+}
26007+
26008+/* ---------------------------------------------------------------------- */
26009+
26010+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
26011+ [AuWbrCopyup_TDP] = {
26012+ .copyup = au_wbr_copyup_tdp
26013+ },
26014+ [AuWbrCopyup_BUP] = {
26015+ .copyup = au_wbr_copyup_bup
26016+ },
26017+ [AuWbrCopyup_BU] = {
26018+ .copyup = au_wbr_copyup_bu
26019+ }
26020+};
26021+
26022+struct au_wbr_create_operations au_wbr_create_ops[] = {
26023+ [AuWbrCreate_TDP] = {
26024+ .create = au_wbr_create_tdp
26025+ },
26026+ [AuWbrCreate_RR] = {
26027+ .create = au_wbr_create_rr,
26028+ .init = au_wbr_create_init_rr
26029+ },
26030+ [AuWbrCreate_MFS] = {
26031+ .create = au_wbr_create_mfs,
26032+ .init = au_wbr_create_init_mfs,
26033+ .fin = au_wbr_create_fin_mfs
26034+ },
26035+ [AuWbrCreate_MFSV] = {
26036+ .create = au_wbr_create_mfs,
26037+ .init = au_wbr_create_init_mfs,
26038+ .fin = au_wbr_create_fin_mfs
26039+ },
26040+ [AuWbrCreate_MFSRR] = {
26041+ .create = au_wbr_create_mfsrr,
26042+ .init = au_wbr_create_init_mfsrr,
26043+ .fin = au_wbr_create_fin_mfs
26044+ },
26045+ [AuWbrCreate_MFSRRV] = {
26046+ .create = au_wbr_create_mfsrr,
26047+ .init = au_wbr_create_init_mfsrr,
26048+ .fin = au_wbr_create_fin_mfs
26049+ },
26050+ [AuWbrCreate_PMFS] = {
26051+ .create = au_wbr_create_pmfs,
26052+ .init = au_wbr_create_init_mfs,
26053+ .fin = au_wbr_create_fin_mfs
26054+ },
26055+ [AuWbrCreate_PMFSV] = {
26056+ .create = au_wbr_create_pmfs,
26057+ .init = au_wbr_create_init_mfs,
26058+ .fin = au_wbr_create_fin_mfs
26059+ }
26060+};
26061diff -urN linux/fs/aufs/whout.c linux-aufs/fs/aufs/whout.c
26062--- linux/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
26063+++ linux-aufs/fs/aufs/whout.c 2009-03-12 16:18:04.000000000 +0100
26064@@ -0,0 +1,1160 @@
26065+/*
26066+ * Copyright (C) 2005-2009 Junjiro Okajima
26067+ *
26068+ * This program, aufs is free software; you can redistribute it and/or modify
26069+ * it under the terms of the GNU General Public License as published by
26070+ * the Free Software Foundation; either version 2 of the License, or
26071+ * (at your option) any later version.
26072+ *
26073+ * This program is distributed in the hope that it will be useful,
26074+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26075+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26076+ * GNU General Public License for more details.
26077+ *
26078+ * You should have received a copy of the GNU General Public License
26079+ * along with this program; if not, write to the Free Software
26080+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26081+ */
26082+
26083+/*
26084+ * whiteout for logical deletion and opaque directory
26085+ *
26086+ * $Id$
26087+ */
26088+
26089+#include <linux/fs.h>
26090+#include <linux/namei.h>
26091+#include "aufs.h"
26092+
26093+#define WH_MASK S_IRUGO
26094+
26095+/* If a directory contains this file, then it is opaque. We start with the
26096+ * .wh. flag so that it is blocked by lookup.
26097+ */
26098+static struct qstr diropq_name = {
26099+ .name = AUFS_WH_DIROPQ,
26100+ .len = sizeof(AUFS_WH_DIROPQ) - 1
26101+};
26102+
26103+/*
26104+ * generate whiteout name, which is NOT terminated by NULL.
26105+ * @name: original d_name.name
26106+ * @len: original d_name.len
26107+ * @wh: whiteout qstr
26108+ * returns zero when succeeds, otherwise error.
26109+ * succeeded value as wh->name should be freed by au_wh_name_free().
26110+ */
26111+int au_wh_name_alloc(const char *name, int len, struct qstr *wh)
26112+{
26113+ char *p;
26114+
26115+ AuDebugOn(!name || !len || !wh);
26116+
26117+ if (unlikely(len > PATH_MAX - AUFS_WH_PFX_LEN))
26118+ return -ENAMETOOLONG;
26119+
26120+ wh->len = len + AUFS_WH_PFX_LEN;
26121+ p = kmalloc(wh->len, GFP_NOFS);
26122+ wh->name = p;
26123+ if (p) {
26124+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
26125+ memcpy(p + AUFS_WH_PFX_LEN, name, len);
26126+ /* smp_mb(); */
26127+ return 0;
26128+ }
26129+ return -ENOMEM;
26130+}
26131+
26132+void au_wh_name_free(struct qstr *wh)
26133+{
26134+ AuDebugOn(!wh || !wh->name);
26135+ kfree(wh->name);
26136+}
26137+
26138+/* ---------------------------------------------------------------------- */
26139+
26140+/*
26141+ * test if the @wh_name exists under @h_parent.
26142+ * @try_sio specifies the necessary of super-io.
26143+ */
26144+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
26145+ struct au_ndx *ndx)
26146+{
26147+ int err;
26148+ struct dentry *wh_dentry;
26149+ struct inode *h_dir;
26150+ unsigned int flags;
26151+
26152+ LKTRTrace("%.*s/%.*s, ndx{%p, 0x%x}\n", AuDLNPair(h_parent),
26153+ wh_name->len, wh_name->name, ndx->nfsmnt, ndx->flags);
26154+ h_dir = h_parent->d_inode;
26155+ AuDebugOn(!S_ISDIR(h_dir->i_mode));
26156+
26157+ flags = 0;
26158+ if (ndx && ndx->nd) {
26159+ flags = ndx->nd->flags;
26160+ ndx->nd->flags &= ~(LOOKUP_OPEN | LOOKUP_CREATE);
26161+ }
26162+
26163+ if (!try_sio)
26164+ wh_dentry = au_lkup_one(wh_name->name, h_parent,
26165+ wh_name->len, ndx);
26166+ else
26167+ wh_dentry = au_sio_lkup_one(wh_name->name, h_parent,
26168+ wh_name->len, ndx);
26169+ if (flags)
26170+ ndx->nd->flags = flags;
26171+ err = PTR_ERR(wh_dentry);
26172+ if (IS_ERR(wh_dentry))
26173+ goto out;
26174+
26175+ err = 0;
26176+ if (!wh_dentry->d_inode)
26177+ goto out_wh; /* success */
26178+
26179+ err = 1;
26180+ if (S_ISREG(wh_dentry->d_inode->i_mode))
26181+ goto out_wh; /* success */
26182+
26183+ err = -EIO;
26184+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
26185+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
26186+
26187+ out_wh:
26188+ dput(wh_dentry);
26189+ out:
26190+ AuTraceErr(err);
26191+ return err;
26192+}
26193+
26194+/*
26195+ * test if the @h_dentry sets opaque or not.
26196+ */
26197+int au_diropq_test(struct dentry *h_dentry, struct au_ndx *ndx)
26198+{
26199+ int err, try_sio;
26200+ struct inode *h_dir;
26201+
26202+ LKTRTrace("dentry %.*s\n", AuDLNPair(h_dentry));
26203+ h_dir = h_dentry->d_inode;
26204+ AuDebugOn(!S_ISDIR(h_dir->i_mode));
26205+
26206+ try_sio = au_test_h_perm_sio(h_dir, MAY_EXEC,
26207+ au_ftest_ndx(ndx->flags, DLGT));
26208+ err = au_wh_test(h_dentry, &diropq_name, try_sio, ndx);
26209+ AuTraceErr(err);
26210+ return err;
26211+}
26212+
26213+/*
26214+ * returns a negative dentry whose name is unique and temporary.
26215+ */
26216+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct qstr *prefix,
26217+ struct au_ndx *ndx)
26218+{
26219+#define HEX_LEN 4
26220+ struct dentry *dentry;
26221+ int len, i;
26222+ char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
26223+ + HEX_LEN + 1], *name, *p;
26224+ static unsigned char cnt;
26225+
26226+ LKTRTrace("hp %.*s, prefix %.*s\n",
26227+ AuDLNPair(h_parent), prefix->len, prefix->name);
26228+ AuDebugOn(!h_parent->d_inode);
26229+
26230+ name = defname;
26231+ len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
26232+ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
26233+ dentry = ERR_PTR(-ENAMETOOLONG);
26234+ if (unlikely(len >= PATH_MAX))
26235+ goto out;
26236+ dentry = ERR_PTR(-ENOMEM);
26237+ name = kmalloc(len + 1, GFP_NOFS);
26238+ if (unlikely(!name))
26239+ goto out;
26240+ }
26241+
26242+ /* doubly whiteout-ed */
26243+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
26244+ p = name + AUFS_WH_PFX_LEN * 2;
26245+ memcpy(p, prefix->name, prefix->len);
26246+ p += prefix->len;
26247+ *p++ = '.';
26248+ AuDebugOn(name + len + 1 - p <= HEX_LEN);
26249+
26250+ for (i = 0; i < 3; i++) {
26251+ sprintf(p, "%.*d", HEX_LEN, cnt++);
26252+ dentry = au_sio_lkup_one(name, h_parent, len, ndx);
26253+ if (IS_ERR(dentry) || !dentry->d_inode)
26254+ goto out_name;
26255+ dput(dentry);
26256+ }
26257+ /* AuWarn("could not get random name\n"); */
26258+ dentry = ERR_PTR(-EEXIST);
26259+ AuDbg("%.*s\n", len, name);
26260+ BUG();
26261+
26262+ out_name:
26263+ if (name != defname)
26264+ kfree(name);
26265+ out:
26266+ AuTraceErrPtr(dentry);
26267+ return dentry;
26268+#undef HEX_LEN
26269+}
26270+
26271+/*
26272+ * rename the @dentry of @bindex to the whiteouted temporary name.
26273+ */
26274+int au_whtmp_ren(struct inode *dir, aufs_bindex_t bindex,
26275+ struct dentry *h_dentry)
26276+{
26277+ int err, dlgt;
26278+ struct inode *h_dir;
26279+ struct dentry *h_parent, *tmp_dentry;
26280+ struct super_block *sb;
26281+ unsigned int mnt_flags;
26282+ struct au_hin_ignore ign;
26283+ struct vfsub_args vargs;
26284+ struct au_ndx ndx = {
26285+ .flags = 0,
26286+ .nd = NULL,
26287+ /* .br = NULL */
26288+ };
26289+
26290+ LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
26291+ AuDebugOn(!h_dentry->d_inode);
26292+ h_parent = h_dentry->d_parent; /* dir inode is locked */
26293+ h_dir = h_parent->d_inode;
26294+ IMustLock(h_dir);
26295+
26296+ sb = dir->i_sb;
26297+ mnt_flags = au_mntflags(sb);
26298+ dlgt = !!au_test_dlgt(mnt_flags);
26299+ if (dlgt)
26300+ au_fset_ndx(ndx.flags, DLGT);
26301+ ndx.nfsmnt = au_nfsmnt(sb, bindex);
26302+ tmp_dentry = au_whtmp_lkup(h_parent, &h_dentry->d_name, &ndx);
26303+ err = PTR_ERR(tmp_dentry);
26304+ if (IS_ERR(tmp_dentry))
26305+ goto out;
26306+
26307+ /* under the same dir, no need to lock_rename() */
26308+ vfsub_args_init(&vargs, &ign, dlgt, 0);
26309+ AuDebugOn(!S_ISDIR(h_dentry->d_inode->i_mode));
26310+ vfsub_ign_hinode(&vargs, IN_MOVED_FROM | IN_MOVED_TO,
26311+ au_hi(dir, bindex));
26312+ err = vfsub_rename(h_dir, h_dentry, h_dir, tmp_dentry, &vargs);
26313+ AuTraceErr(err);
26314+ dput(tmp_dentry);
26315+
26316+ out:
26317+ AuTraceErr(err);
26318+ return err;
26319+}
26320+
26321+/* ---------------------------------------------------------------------- */
26322+
26323+static int do_unlink_wh(struct au_hinode *hdir, struct inode *h_dir,
26324+ struct dentry *wh_dentry, const int dlgt)
26325+{
26326+ int err;
26327+ struct au_hin_ignore ign;
26328+ struct vfsub_args vargs;
26329+
26330+ AuDebugOn(hdir && h_dir);
26331+ AuDebugOn(!hdir && !h_dir);
26332+ if (!h_dir)
26333+ h_dir = hdir->hi_inode;
26334+ LKTRTrace("hi%lu, wh %.*s\n", h_dir->i_ino, AuDLNPair(wh_dentry));
26335+ AuDebugOn(!wh_dentry->d_inode || !S_ISREG(wh_dentry->d_inode->i_mode));
26336+
26337+ /*
26338+ * forces superio when the dir has a sticky bit.
26339+ * this may be a violation of unix fs semantics.
26340+ */
26341+ vfsub_args_init(&vargs, &ign, dlgt,
26342+ (h_dir->i_mode & S_ISVTX)
94750128 26343+ && wh_dentry->d_inode->i_uid != current_fsuid());
024a5822
JR
26344+ vfsub_ign_hinode(&vargs, IN_DELETE, hdir);
26345+ err = vfsub_unlink(h_dir, wh_dentry, &vargs);
26346+ AuTraceErr(err);
26347+ return err;
26348+}
26349+
26350+int au_wh_unlink_dentry(struct au_hinode *hdir, struct dentry *wh_dentry,
26351+ struct dentry *dentry, int dlgt)
26352+{
26353+ int err;
26354+
26355+ LKTRTrace("i%lu, wh %.*s, d %p\n",
26356+ hdir->hi_inode->i_ino, AuDLNPair(wh_dentry), dentry);
26357+ AuDebugOn((dentry && au_dbwh(dentry) < 0)
26358+ || !wh_dentry->d_inode
26359+ || !S_ISREG(wh_dentry->d_inode->i_mode));
26360+
26361+ err = do_unlink_wh(hdir, /*h_dir*/NULL, wh_dentry, dlgt);
26362+ if (!err && dentry)
26363+ au_set_dbwh(dentry, -1);
26364+
26365+ AuTraceErr(err);
26366+ return err;
26367+}
26368+
26369+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
26370+ struct au_ndx *ndx)
26371+{
26372+ int err;
26373+ struct dentry *wh_dentry;
26374+
26375+ LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(wh));
26376+
26377+ /* au_test_h_perm() is already done */
26378+ wh_dentry = au_lkup_one(wh->name, h_parent, wh->len, ndx);
26379+ if (IS_ERR(wh_dentry))
26380+ err = PTR_ERR(wh_dentry);
26381+ else {
26382+ err = 0;
26383+ if (wh_dentry->d_inode && S_ISREG(wh_dentry->d_inode->i_mode))
26384+ err = do_unlink_wh(/*hdir*/NULL, h_parent->d_inode,
26385+ wh_dentry,
26386+ au_ftest_ndx(ndx->flags, DLGT));
26387+ dput(wh_dentry);
26388+ }
26389+
26390+ AuTraceErr(err);
26391+ return err;
26392+}
26393+
26394+/* ---------------------------------------------------------------------- */
26395+
26396+static void clean_wh(struct inode *h_dir, struct path *whpath,
26397+ struct au_hinode *hdir, struct vfsub_args *vargs)
26398+{
26399+ int err;
26400+
26401+ AuTraceEnter();
26402+
26403+ if (!whpath->dentry->d_inode)
26404+ return;
26405+
26406+ err = au_mnt_want_write(whpath->mnt);
26407+ if (!err) {
26408+ vfsub_args_reinit(vargs);
26409+ vfsub_ign_hinode(vargs, IN_DELETE, hdir);
26410+ err = vfsub_unlink(h_dir, whpath->dentry, vargs);
26411+ au_mnt_drop_write(whpath->mnt);
26412+ }
26413+ if (unlikely(err))
26414+ AuWarn("failed unlink %.*s (%d), ignored.\n",
26415+ AuDLNPair(whpath->dentry), err);
26416+}
26417+
26418+static void au_whdir_clean(struct inode *h_dir, struct path *whpath,
26419+ struct au_hinode *hdir, struct vfsub_args *vargs)
26420+{
26421+ int err;
26422+
26423+ AuTraceEnter();
26424+
26425+ if (!whpath->dentry->d_inode)
26426+ return;
26427+
26428+ err = au_mnt_want_write(whpath->mnt);
26429+ if (!err) {
26430+ vfsub_args_reinit(vargs);
26431+ vfsub_ign_hinode(vargs, IN_DELETE, hdir);
26432+ err = vfsub_rmdir(h_dir, whpath->dentry, vargs);
26433+ au_mnt_drop_write(whpath->mnt);
26434+ }
26435+ if (unlikely(err))
26436+ AuWarn("failed rmdir %.*s (%d), ignored.\n",
26437+ AuDLNPair(whpath->dentry), err);
26438+}
26439+
26440+static int test_linkable(struct inode *h_dir)
26441+{
26442+ if (h_dir->i_op && h_dir->i_op->link)
26443+ return 0;
26444+ return -ENOSYS;
26445+}
26446+
26447+/* todo: should this mkdir be done in /sbin/mount.aufs script? */
26448+static int au_whdir(struct inode *h_dir, struct path *path,
26449+ struct au_hinode *hdir, struct vfsub_args *vargs)
26450+{
26451+ int err;
26452+
26453+ err = -EEXIST;
26454+ if (!path->dentry->d_inode) {
26455+ int mode = S_IRWXU;
26456+ if (au_test_nfs(path->dentry->d_sb))
26457+ mode |= S_IXUGO;
26458+ err = au_mnt_want_write(path->mnt);
26459+ if (!err) {
26460+ vfsub_args_reinit(vargs);
26461+ vfsub_ign_hinode(vargs, IN_CREATE, hdir);
26462+ err = vfsub_mkdir(h_dir, path->dentry, mode, vargs);
26463+ au_mnt_drop_write(path->mnt);
26464+ }
26465+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
26466+ err = 0;
26467+ else
26468+ AuErr("unknown %.*s exists\n", AuDLNPair(path->dentry));
26469+
26470+ return err;
26471+}
26472+
26473+/*
26474+ * initialize the whiteout base file/dir for @br.
26475+ */
26476+int au_wh_init(struct dentry *h_root, struct au_branch *br,
26477+ struct vfsmount *h_mnt, struct super_block *sb,
26478+ aufs_bindex_t bindex)
26479+{
26480+ int err, i;
26481+ const unsigned int mnt_flags = au_mntflags(sb);
26482+ const unsigned char do_plink = !!au_opt_test(mnt_flags, PLINK),
26483+ do_hinotify = au_opt_test(mnt_flags, UDBA_INOTIFY);
26484+ struct path path = {
26485+ .mnt = h_mnt
26486+ };
26487+ struct au_hin_ignore ign;
26488+ struct vfsub_args vargs;
26489+ struct inode *h_dir;
26490+ struct au_hinode *hdir;
26491+ struct au_wbr *wbr = br->br_wbr;
26492+ struct vfsmount *nfsmnt = au_do_nfsmnt(h_mnt);
26493+ static const struct qstr base_name[] = {
26494+ [AuBrWh_BASE] = {
26495+ .name = AUFS_BASE_NAME,
26496+ .len = sizeof(AUFS_BASE_NAME) - 1
26497+ },
26498+ [AuBrWh_PLINK] = {
26499+ .name = AUFS_PLINKDIR_NAME,
26500+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
26501+ },
26502+ [AuBrWh_TMP] = {
26503+ .name = AUFS_TMPDIR_NAME,
26504+ .len = sizeof(AUFS_TMPDIR_NAME) - 1
26505+ }
26506+ };
26507+ struct {
26508+ const struct qstr *name;
26509+ struct dentry *dentry;
26510+ } base[] = {
26511+ [AuBrWh_BASE] = {
26512+ .name = base_name + AuBrWh_BASE,
26513+ .dentry = NULL
26514+ },
26515+ [AuBrWh_PLINK] = {
26516+ .name = base_name + AuBrWh_PLINK,
26517+ .dentry = NULL
26518+ },
26519+ [AuBrWh_TMP] = {
26520+ .name = base_name + AuBrWh_TMP,
26521+ .dentry = NULL
26522+ }
26523+ };
26524+ struct au_ndx ndx = {
26525+ .nfsmnt = nfsmnt,
26526+ .flags = 0, /* always no dlgt */
26527+ .nd = NULL,
26528+ /* .br = NULL */
26529+ };
26530+
26531+ LKTRTrace("nfsmnt %p\n", nfsmnt);
26532+ WbrWhMustWriteLock(wbr);
26533+ SiMustWriteLock(sb);
26534+ h_dir = h_root->d_inode;
26535+
26536+ for (i = 0; i < AuBrWh_Last; i++) {
26537+ /* doubly whiteouted */
26538+ struct dentry *d;
26539+ d = au_wh_lkup(h_root, (void *)base[i].name, &ndx);
26540+ err = PTR_ERR(d);
26541+ if (IS_ERR(d))
26542+ goto out;
26543+ base[i].dentry = d;
26544+ if (!au_test_ecryptfs(d->d_sb))
26545+ AuDebugOn(wbr
26546+ && wbr->wbr_wh[i]
26547+ && wbr->wbr_wh[i] != base[i].dentry);
26548+ else
26549+ /* ecryptfs problem?: it returns different dentry */
26550+ AuDebugOn(wbr
26551+ && wbr->wbr_wh[i]
26552+ && !!wbr->wbr_wh[i] != !!base[i].dentry);
26553+ }
26554+
26555+ if (wbr)
26556+ for (i = 0; i < AuBrWh_Last; i++) {
26557+ dput(wbr->wbr_wh[i]);
26558+ wbr->wbr_wh[i] = NULL;
26559+ }
26560+
26561+ err = 0;
26562+ hdir = NULL;
26563+ if (bindex >= 0 && do_hinotify)
26564+ hdir = au_hi(sb->s_root->d_inode, bindex);
26565+ vfsub_args_init(&vargs, &ign, au_test_dlgt(mnt_flags), 0);
26566+
26567+ switch (br->br_perm) {
26568+ case AuBrPerm_RR:
26569+ case AuBrPerm_RO:
26570+ case AuBrPerm_RRWH:
26571+ case AuBrPerm_ROWH:
26572+ path.dentry = base[AuBrWh_BASE].dentry;
26573+ clean_wh(h_dir, &path, hdir, &vargs);
26574+ path.dentry = base[AuBrWh_PLINK].dentry;
26575+ au_whdir_clean(h_dir, &path, hdir, &vargs);
26576+ path.dentry = base[AuBrWh_TMP].dentry;
26577+ au_whdir_clean(h_dir, &path, hdir, &vargs);
26578+ break;
26579+
26580+ case AuBrPerm_RWNoLinkWH:
26581+ path.dentry = base[AuBrWh_BASE].dentry;
26582+ clean_wh(h_dir, &path, hdir, &vargs);
26583+ path.dentry = base[AuBrWh_PLINK].dentry;
26584+ if (do_plink) {
26585+ err = test_linkable(h_dir);
26586+ if (unlikely(err))
26587+ goto out_nolink;
26588+
26589+ err = au_whdir(h_dir, &path, hdir, &vargs);
26590+ if (unlikely(err))
26591+ goto out_err;
26592+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
26593+ } else
26594+ au_whdir_clean(h_dir, &path, hdir, &vargs);
26595+ path.dentry = base[AuBrWh_TMP].dentry;
26596+ err = au_whdir(h_dir, &path, hdir, &vargs);
26597+ if (unlikely(err))
26598+ goto out_err;
26599+ wbr->wbr_tmp = dget(base[AuBrWh_TMP].dentry);
26600+ break;
26601+
26602+ case AuBrPerm_RW:
26603+ /*
26604+ * for the moment, aufs supports the branch filesystem
26605+ * which does not support link(2).
26606+ * testing on FAT which does not support i_op->setattr() fully
26607+ * either, copyup failed.
26608+ * finally, such filesystem will not be used as the writable
26609+ * branch.
26610+ */
26611+ err = test_linkable(h_dir);
26612+ if (unlikely(err))
26613+ goto out_nolink;
26614+
26615+ err = -EEXIST;
26616+ /*
26617+ * todo: should this create be done
26618+ * in /sbin/mount.aufs script?
26619+ */
26620+ if (!base[AuBrWh_BASE].dentry->d_inode) {
26621+ err = au_mnt_want_write(h_mnt);
26622+ if (!err) {
26623+ vfsub_args_reinit(&vargs);
26624+ vfsub_ign_hinode(&vargs, IN_CREATE, hdir);
26625+ err = au_h_create
26626+ (h_dir, base[AuBrWh_BASE].dentry,
26627+ WH_MASK, &vargs, /*nd*/NULL, nfsmnt);
26628+ au_mnt_drop_write(h_mnt);
26629+ }
26630+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
26631+ err = 0;
26632+ else
26633+ AuErr("unknown %.*s/%.*s exists\n",
26634+ AuDLNPair(h_root),
26635+ AuDLNPair(base[AuBrWh_BASE].dentry));
26636+ if (unlikely(err))
26637+ goto out_err;
26638+
26639+ path.dentry = base[AuBrWh_PLINK].dentry;
26640+ if (do_plink) {
26641+ err = au_whdir(h_dir, &path, hdir, &vargs);
26642+ if (unlikely(err))
26643+ goto out_err;
26644+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
26645+ } else
26646+ au_whdir_clean(h_dir, &path, hdir, &vargs);
26647+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
26648+
26649+ path.dentry = base[AuBrWh_TMP].dentry;
26650+ err = au_whdir(h_dir, &path, hdir, &vargs);
26651+ if (unlikely(err))
26652+ goto out_err;
26653+ wbr->wbr_tmp = dget(base[AuBrWh_TMP].dentry);
26654+ break;
26655+
26656+ default:
26657+ BUG();
26658+ }
26659+
26660+ out:
26661+ for (i = 0; i < AuBrWh_Last; i++)
26662+ dput(base[i].dentry);
26663+ AuTraceErr(err);
26664+ return err;
26665+ out_nolink:
26666+ AuErr("%.*s doesn't support link(2), use noplink and rw+nolwh\n",
26667+ AuDLNPair(h_root));
26668+ goto out;
26669+ out_err:
26670+ AuErr("an error(%d) on the writable branch %.*s(%s)\n",
26671+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
26672+ goto out;
26673+}
26674+
26675+struct reinit_br_wh {
26676+ struct super_block *sb;
26677+ struct au_branch *br;
26678+};
26679+
26680+static void reinit_br_wh(void *arg)
26681+{
26682+ int err;
26683+ struct reinit_br_wh *a = arg;
26684+ struct au_wbr *wbr;
26685+ struct inode *h_dir, *dir;
26686+ struct dentry *h_root;
26687+ aufs_bindex_t bindex;
26688+ struct au_hin_ignore ign;
26689+ struct vfsub_args vargs;
26690+
26691+ AuTraceEnter();
94750128 26692+ AuDebugOn(current_fsuid());
024a5822
JR
26693+
26694+ err = 0;
26695+ wbr = a->br->br_wbr;
26696+ /* big aufs lock */
26697+ si_noflush_write_lock(a->sb);
26698+ if (!au_br_writable(a->br->br_perm))
26699+ goto out;
26700+ bindex = au_br_index(a->sb, a->br->br_id);
26701+ if (unlikely(bindex < 0))
26702+ goto out;
26703+
26704+ AuDebugOn(!wbr);
26705+ AuDebugOn(!wbr->wbr_whbase || !wbr->wbr_whbase->d_inode);
26706+
26707+ dir = a->sb->s_root->d_inode;
26708+ ii_read_lock_parent(dir);
26709+ h_root = dget_parent(wbr->wbr_whbase);
26710+ h_dir = h_root->d_inode;
26711+ AuDebugOn(!h_dir->i_op || !h_dir->i_op->link);
26712+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
26713+ wbr_wh_write_lock(wbr);
26714+ if (!au_verify_parent(wbr->wbr_whbase, h_dir)) {
26715+ err = au_br_want_write(a->br);
26716+ if (!err) {
26717+ vfsub_args_init(&vargs, &ign, /*dlgt*/0, 0);
26718+ vfsub_ign_hinode(&vargs, IN_DELETE, au_hi(dir, bindex));
26719+ err = vfsub_unlink(h_dir, wbr->wbr_whbase, &vargs);
26720+ au_br_drop_write(a->br);
26721+ }
26722+ } else {
26723+ AuWarn("%.*s is moved, ignored\n", AuDLNPair(wbr->wbr_whbase));
26724+ err = 0;
26725+ }
26726+ dput(wbr->wbr_whbase);
26727+ wbr->wbr_whbase = NULL;
26728+ if (!err)
26729+ err = au_wh_init(h_root, a->br, a->br->br_mnt, a->sb, bindex);
26730+ wbr_wh_write_unlock(wbr);
26731+ mutex_unlock(&h_dir->i_mutex);
26732+ dput(h_root);
26733+ ii_read_unlock(dir);
26734+
26735+ out:
26736+ if (wbr)
26737+ atomic_dec_return(&wbr->wbr_wh_running);
26738+ au_br_put(a->br);
26739+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
26740+ si_write_unlock(a->sb);
26741+ kfree(arg);
26742+ if (unlikely(err))
26743+ AuIOErr("err %d\n", err);
26744+}
26745+
26746+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
26747+{
26748+ int do_dec, wkq_err;
26749+ struct reinit_br_wh *arg;
26750+
26751+ AuTraceEnter();
26752+ AuDebugOn(!br->br_wbr);
26753+
26754+ do_dec = 1;
26755+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
26756+ goto out;
26757+
26758+ /* ignore ENOMEM */
26759+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
26760+ if (arg) {
26761+ /*
26762+ * dec(wh_running), kfree(arg) and au_br_put()
26763+ * in reinit function
26764+ */
26765+ arg->sb = sb;
26766+ arg->br = br;
26767+ au_br_get(br);
26768+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*dlgt*/0);
26769+ if (unlikely(wkq_err)) {
26770+ atomic_dec_return(&br->br_wbr->wbr_wh_running);
26771+ au_br_put(br);
26772+ kfree(arg);
26773+ }
26774+ do_dec = 0;
26775+ }
26776+
26777+ out:
26778+ if (do_dec)
26779+ atomic_dec_return(&br->br_wbr->wbr_wh_running);
26780+}
26781+
26782+/*
26783+ * create the whiteout @wh.
26784+ */
26785+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
26786+ struct dentry *wh, struct inode *dir)
26787+{
26788+ int err, dlgt;
26789+ struct au_branch *br;
26790+ struct au_wbr *wbr;
26791+ struct dentry *h_parent;
26792+ struct inode *h_dir;
26793+ struct au_hin_ignore ign;
26794+ struct vfsub_args vargs;
26795+
26796+ LKTRTrace("%.*s\n", AuDLNPair(wh));
26797+ h_parent = wh->d_parent; /* dir inode is locked */
26798+ h_dir = h_parent->d_inode;
26799+ IMustLock(h_dir);
26800+ br = au_sbr(sb, bindex);
26801+ wbr = br->br_wbr;
26802+ AuDebugOn(!wbr);
26803+
26804+ dlgt = !!au_test_dlgt(au_mntflags(sb));
26805+ wbr_wh_read_lock(wbr);
26806+ if (wbr->wbr_whbase) {
26807+ vfsub_args_init(&vargs, &ign, dlgt, 0);
26808+ if (dir)
26809+ vfsub_ign_hinode(&vargs, IN_CREATE, au_hi(dir, bindex));
26810+ err = vfsub_link(wbr->wbr_whbase, h_dir, wh, &vargs);
26811+ if (!err || err != -EMLINK)
26812+ goto out;
26813+
26814+ /* link count full. re-initialize br_whbase. */
26815+ kick_reinit_br_wh(sb, br);
26816+ }
26817+
26818+ /* return this error in this context */
26819+ vfsub_args_init(&vargs, &ign, dlgt, 0);
26820+ if (dir)
26821+ vfsub_ign_hinode(&vargs, IN_CREATE, au_hi(dir, bindex));
26822+ err = au_h_create(h_dir, wh, WH_MASK, &vargs, /*nd*/NULL,
26823+ au_do_nfsmnt(br->br_mnt));
26824+
26825+ out:
26826+ wbr_wh_read_unlock(wbr);
26827+ AuTraceErr(err);
26828+ return err;
26829+}
26830+
26831+/* ---------------------------------------------------------------------- */
26832+
26833+/*
26834+ * create or remove the diropq.
26835+ */
26836+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
26837+ unsigned int flags)
26838+{
26839+ struct dentry *opq_dentry, *h_dentry;
26840+ struct inode *h_dir;
26841+ int err, dlgt;
26842+ struct super_block *sb;
26843+ struct au_ndx ndx = {
26844+ .flags = 0,
26845+ .nd = NULL,
26846+ /* .br = NULL */
26847+ };
26848+
26849+ LKTRTrace("%.*s, bindex %d, flags 0x%x\n",
26850+ AuDLNPair(dentry), bindex, flags);
26851+ h_dentry = au_h_dptr(dentry, bindex);
26852+ AuDebugOn(!h_dentry);
26853+ h_dir = h_dentry->d_inode;
26854+ AuDebugOn(!h_dir || !S_ISDIR(h_dir->i_mode));
26855+
26856+ /* already checked by au_test_h_perm(). */
26857+ sb = dentry->d_sb;
26858+ ndx.nfsmnt = au_nfsmnt(sb, bindex);
26859+ dlgt = 0;
26860+ if (au_ftest_diropq(flags, DLGT)) {
26861+ dlgt = 1;
26862+ au_fset_ndx(ndx.flags, DLGT);
26863+ }
26864+ opq_dentry = au_lkup_one(diropq_name.name, h_dentry, diropq_name.len,
26865+ &ndx);
26866+ if (IS_ERR(opq_dentry))
26867+ goto out;
26868+
26869+ if (au_ftest_diropq(flags, CREATE)) {
26870+ AuDebugOn(opq_dentry->d_inode);
26871+ err = link_or_create_wh(dentry->d_sb, bindex, opq_dentry,
26872+ dentry->d_inode);
26873+ if (!err) {
26874+ au_set_dbdiropq(dentry, bindex);
26875+ goto out; /* success */
26876+ }
26877+ } else {
26878+ AuDebugOn(/* !S_ISDIR(dentry->d_inode->i_mode)
26879+ * || */!opq_dentry->d_inode);
26880+ err = do_unlink_wh(au_hi(dentry->d_inode, bindex),
26881+ /*h_dir*/NULL, opq_dentry, dlgt);
26882+ if (!err)
26883+ au_set_dbdiropq(dentry, -1);
26884+ }
26885+ dput(opq_dentry);
26886+ opq_dentry = ERR_PTR(err);
26887+
26888+ out:
26889+ AuTraceErrPtr(opq_dentry);
26890+ return opq_dentry;
26891+}
26892+
26893+struct do_diropq_args {
26894+ struct dentry **errp;
26895+ struct dentry *dentry;
26896+ aufs_bindex_t bindex;
26897+ unsigned int flags;
26898+};
26899+
26900+static void call_do_diropq(void *args)
26901+{
26902+ struct do_diropq_args *a = args;
26903+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
26904+}
26905+
26906+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
26907+ unsigned int flags)
26908+{
26909+ struct dentry *diropq, *h_dentry;
26910+
26911+ LKTRTrace("%.*s, bindex %d, flags 0x%x\n",
26912+ AuDLNPair(dentry), bindex, flags);
26913+
26914+ h_dentry = au_h_dptr(dentry, bindex);
26915+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE,
26916+ au_ftest_diropq(flags, DLGT)))
26917+ diropq = do_diropq(dentry, bindex, flags);
26918+ else {
26919+ int wkq_err;
26920+ struct do_diropq_args args = {
26921+ .errp = &diropq,
26922+ .dentry = dentry,
26923+ .bindex = bindex,
26924+ .flags = flags
26925+ };
26926+ wkq_err = au_wkq_wait(call_do_diropq, &args, /*dlgt*/0);
26927+ if (unlikely(wkq_err))
26928+ diropq = ERR_PTR(wkq_err);
26929+ }
26930+
26931+ AuTraceErrPtr(diropq);
26932+ return diropq;
26933+}
26934+
26935+/* ---------------------------------------------------------------------- */
26936+
26937+/*
26938+ * lookup whiteout dentry.
26939+ * @h_parent: hidden parent dentry which must exist and be locked
26940+ * @base_name: name of dentry which will be whiteouted
26941+ * returns dentry for whiteout.
26942+ */
26943+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
26944+ struct au_ndx *ndx)
26945+{
26946+ int err;
26947+ struct qstr wh_name;
26948+ struct dentry *wh_dentry;
26949+
26950+ LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(base_name));
26951+
26952+ err = au_wh_name_alloc(base_name->name, base_name->len, &wh_name);
26953+ wh_dentry = ERR_PTR(err);
26954+ if (!err) {
26955+ /* do not superio. */
26956+ wh_dentry = au_lkup_one(wh_name.name, h_parent,
26957+ wh_name.len, ndx);
26958+ au_wh_name_free(&wh_name);
26959+ }
26960+ AuTraceErrPtr(wh_dentry);
26961+ return wh_dentry;
26962+}
26963+
26964+/*
26965+ * link/create a whiteout for @dentry on @bindex.
26966+ */
26967+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
26968+ struct dentry *h_parent, struct au_ndx *ndx)
26969+{
26970+ struct dentry *wh_dentry;
26971+ struct inode *dir;
26972+ int err;
26973+ struct super_block *sb;
26974+
26975+ LKTRTrace("%.*s/%.*s on b%d\n", AuDLNPair(h_parent),
26976+ AuDLNPair(dentry), bindex);
26977+
26978+ sb = dentry->d_sb;
26979+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, ndx);
26980+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
26981+ dir = dentry->d_parent->d_inode; /* dir is locked */
26982+ IMustLock(dir);
26983+ err = link_or_create_wh(sb, bindex, wh_dentry, dir);
26984+ if (!err)
26985+ au_set_dbwh(dentry, bindex);
26986+ else {
26987+ dput(wh_dentry);
26988+ wh_dentry = ERR_PTR(err);
26989+ }
26990+ }
26991+
26992+ AuTraceErrPtr(wh_dentry);
26993+ return wh_dentry;
26994+}
26995+
26996+/* ---------------------------------------------------------------------- */
26997+
26998+/* Delete all whiteouts in this directory on branch bindex. */
26999+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
27000+ aufs_bindex_t bindex, struct au_ndx *ndx)
27001+{
27002+ int err, i;
27003+ struct qstr wh_name;
27004+ char *p;
27005+ struct inode *h_inode;
27006+ struct hlist_head *head;
27007+ struct au_vdir_wh *tpos;
27008+ struct hlist_node *pos;
27009+ struct au_vdir_destr *str;
27010+
27011+ LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
27012+ h_inode = h_dentry->d_inode;
27013+ AuDebugOn(IS_RDONLY(h_inode));
27014+
27015+ err = -ENOMEM;
27016+ p = __getname();
27017+ wh_name.name = p;
27018+ if (unlikely(!wh_name.name))
27019+ goto out;
27020+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
27021+ p += AUFS_WH_PFX_LEN;
27022+
27023+ /* already checked by au_test_h_perm(). */
27024+ err = 0;
27025+ for (i = 0; !err && i < AuSize_NHASH; i++) {
27026+ head = whlist->heads + i;
27027+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
27028+ if (tpos->wh_bindex != bindex)
27029+ continue;
27030+ str = &tpos->wh_str;
27031+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
27032+ memcpy(p, str->name, str->len);
27033+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
27034+ err = unlink_wh_name(h_dentry, &wh_name, ndx);
27035+ if (!err)
27036+ continue;
27037+ break;
27038+ }
27039+ AuIOErr("whiteout name too long %.*s\n",
27040+ str->len, str->name);
27041+ err = -EIO;
27042+ break;
27043+ }
27044+ }
27045+ __putname(wh_name.name);
27046+
27047+ out:
27048+ AuTraceErr(err);
27049+ return err;
27050+}
27051+
27052+struct del_wh_children_args {
27053+ int *errp;
27054+ struct dentry *h_dentry;
27055+ struct au_nhash *whlist;
27056+ aufs_bindex_t bindex;
27057+ struct au_ndx *ndx;
27058+};
27059+
27060+static void call_del_wh_children(void *args)
27061+{
27062+ struct del_wh_children_args *a = args;
27063+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->ndx);
27064+}
27065+
27066+/* ---------------------------------------------------------------------- */
27067+
27068+/*
27069+ * rmdir the whiteouted temporary named dir @h_dentry.
27070+ * @whlist: whiteouted children.
27071+ */
27072+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
27073+ struct dentry *wh_dentry, struct au_nhash *whlist)
27074+{
27075+ int err, dlgt;
27076+ struct inode *wh_inode, *h_dir;
27077+ struct super_block *sb;
27078+ unsigned int mnt_flags;
27079+ struct au_hin_ignore ign;
27080+ struct vfsub_args vargs;
27081+ struct au_ndx ndx = {
27082+ .flags = 0,
27083+ .nd = NULL,
27084+ /* .br = NULL */
27085+ };
27086+
27087+ LKTRTrace("i%lu, %.*s, b%d\n",
27088+ dir->i_ino, AuDLNPair(wh_dentry), bindex);
27089+ /* IMustLock(dir); */
27090+ IiMustAnyLock(dir);
27091+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
27092+ IMustLock(h_dir);
27093+
27094+ sb = dir->i_sb;
27095+ mnt_flags = au_mntflags(sb);
27096+ dlgt = !!au_test_dlgt(mnt_flags);
27097+ if (dlgt)
27098+ au_fset_ndx(ndx.flags, DLGT);
27099+ ndx.nfsmnt = au_nfsmnt(sb, bindex);
27100+ wh_inode = wh_dentry->d_inode;
27101+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
27102+
27103+ /*
27104+ * someone else might change some whiteouts while we were sleeping.
27105+ * it means this whlist may have an obsoleted entry.
27106+ */
27107+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE, dlgt))
27108+ err = del_wh_children(wh_dentry, whlist, bindex, &ndx);
27109+ else {
27110+ int wkq_err;
27111+ /* ugly */
27112+ unsigned int flags = ndx.flags;
27113+ struct del_wh_children_args args = {
27114+ .errp = &err,
27115+ .h_dentry = wh_dentry,
27116+ .whlist = whlist,
27117+ .bindex = bindex,
27118+ .ndx = &ndx
27119+ };
27120+
27121+ ndx.flags = 0;
27122+ wkq_err = au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0);
27123+ if (unlikely(wkq_err))
27124+ err = wkq_err;
27125+ ndx.flags = flags;
27126+ }
27127+ mutex_unlock(&wh_inode->i_mutex);
27128+
27129+ if (!err) {
27130+ vfsub_args_init(&vargs, &ign, dlgt, 0);
27131+ vfsub_ign_hinode(&vargs, IN_DELETE, au_hi(dir, bindex));
27132+ err = vfsub_rmdir(h_dir, wh_dentry, &vargs);
27133+ /* d_drop(h_dentry); */
27134+ }
27135+
27136+ if (!err) {
27137+ if (au_ibstart(dir) == bindex) {
27138+ au_cpup_attr_timesizes(dir);
27139+ /* au_cpup_attr_nlink(dir); */
27140+ drop_nlink(dir);
27141+ }
27142+ return 0; /* success */
27143+ }
27144+
27145+ AuWarn("failed removing %.*s(%d), ignored\n",
27146+ AuDLNPair(wh_dentry), err);
27147+ return err;
27148+}
27149+
27150+static void au_whtmp_rmdir_free_args(struct au_whtmp_rmdir_args *args)
27151+{
27152+ au_nhash_fin(&args->whlist);
27153+ dput(args->wh_dentry);
27154+ iput(args->dir);
27155+ kfree(args);
27156+}
27157+
27158+static void call_rmdir_whtmp(void *args)
27159+{
27160+ int err;
27161+ struct au_whtmp_rmdir_args *a = args;
27162+ struct super_block *sb;
27163+ struct dentry *h_parent;
27164+ struct inode *h_dir;
27165+
27166+ LKTRTrace("%.*s, b%d, dir i%lu\n",
27167+ AuDLNPair(a->wh_dentry), a->bindex, a->dir->i_ino);
27168+
27169+ /* rmdir by nfsd may cause deadlock with this i_mutex */
27170+ /* mutex_lock(&a->dir->i_mutex); */
27171+ sb = a->dir->i_sb;
27172+ si_noflush_read_lock(sb);
27173+ err = au_test_ro(sb, a->bindex, NULL);
27174+ if (unlikely(err))
27175+ goto out;
27176+
27177+ err = -EIO;
27178+ ii_write_lock_parent(a->dir);
27179+ h_parent = dget_parent(a->wh_dentry);
27180+ h_dir = h_parent->d_inode;
27181+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
27182+ if (!au_verify_parent(a->wh_dentry, h_dir)) {
27183+ err = au_br_want_write(au_sbr(sb, a->bindex));
27184+ if (!err) {
27185+ err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
27186+ &a->whlist);
27187+ au_br_drop_write(au_sbr(sb, a->bindex));
27188+ }
27189+ }
27190+ mutex_unlock(&h_dir->i_mutex);
27191+ dput(h_parent);
27192+ ii_write_unlock(a->dir);
27193+
27194+ out:
27195+ /* mutex_unlock(&a->dir->i_mutex); */
27196+ au_nwt_done(&au_sbi(sb)->si_nowait);
27197+ si_read_unlock(sb);
27198+ au_whtmp_rmdir_free_args(a);
27199+ if (unlikely(err))
27200+ AuIOErr("err %d\n", err);
27201+}
27202+
27203+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
27204+ struct dentry *wh_dentry, struct au_nhash *whlist,
27205+ struct au_whtmp_rmdir_args *args)
27206+{
27207+ int wkq_err;
27208+
27209+ LKTRTrace("%.*s\n", AuDLNPair(wh_dentry));
27210+ IMustLock(dir);
27211+
27212+ /* all post-process will be done in do_rmdir_whtmp(). */
27213+ args->dir = au_igrab(dir);
27214+ args->bindex = bindex;
27215+ args->wh_dentry = dget(wh_dentry);
27216+ au_nhash_init(&args->whlist);
27217+ au_nhash_move(&args->whlist, whlist);
27218+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb, /*dlgt*/0);
27219+ if (unlikely(wkq_err)) {
27220+ AuWarn("rmdir error %.*s (%d), ignored\n",
27221+ AuDLNPair(wh_dentry), wkq_err);
27222+ au_whtmp_rmdir_free_args(args);
27223+ }
27224+}
27225diff -urN linux/fs/aufs/whout.h linux-aufs/fs/aufs/whout.h
27226--- linux/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
27227+++ linux-aufs/fs/aufs/whout.h 2009-03-12 16:18:04.000000000 +0100
27228@@ -0,0 +1,137 @@
27229+/*
27230+ * Copyright (C) 2005-2009 Junjiro Okajima
27231+ *
27232+ * This program, aufs is free software; you can redistribute it and/or modify
27233+ * it under the terms of the GNU General Public License as published by
27234+ * the Free Software Foundation; either version 2 of the License, or
27235+ * (at your option) any later version.
27236+ *
27237+ * This program is distributed in the hope that it will be useful,
27238+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27239+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27240+ * GNU General Public License for more details.
27241+ *
27242+ * You should have received a copy of the GNU General Public License
27243+ * along with this program; if not, write to the Free Software
27244+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27245+ */
27246+
27247+/*
27248+ * whiteout for logical deletion and opaque directory
27249+ *
27250+ * $Id$
27251+ */
27252+
27253+#ifndef __AUFS_WHOUT_H__
27254+#define __AUFS_WHOUT_H__
27255+
27256+#ifdef __KERNEL__
27257+
27258+#include <linux/fs.h>
27259+#include <linux/aufs_type.h>
27260+#include "dir.h"
27261+#include "opts.h"
27262+#include "super.h"
27263+
27264+int au_wh_name_alloc(const char *name, int len, struct qstr *wh);
27265+void au_wh_name_free(struct qstr *wh);
27266+
27267+struct au_ndx;
27268+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
27269+ struct au_ndx *ndx);
27270+int au_diropq_test(struct dentry *h_dentry, struct au_ndx *ndx);
27271+
27272+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct qstr *prefix,
27273+ struct au_ndx *ndx);
27274+int au_whtmp_ren(struct inode *dir, aufs_bindex_t bindex,
27275+ struct dentry *h_dentry);
27276+int au_wh_unlink_dentry(struct au_hinode *dir, struct dentry *wh_dentry,
27277+ struct dentry *dentry, int dlgt);
27278+
27279+struct au_branch;
27280+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
27281+ struct vfsmount *nfsmnt, struct super_block *sb,
27282+ aufs_bindex_t bindex);
27283+
27284+/* diropq flags */
27285+#define AuDiropq_CREATE 1
27286+#define AuDiropq_DLGT (1 << 1)
27287+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
27288+#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
27289+#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
27290+#ifndef CONFIG_AUFS_DLGT
27291+#undef AuDiropq_DLGT
27292+#define AuDiropq_DLGT 0
27293+#endif
27294+
27295+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
27296+ unsigned int flags);
27297+
27298+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
27299+ struct au_ndx *ndx);
27300+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
27301+ struct dentry *h_parent, struct au_ndx *ndx);
27302+
27303+/* real rmdir the whiteout-ed dir */
27304+struct au_whtmp_rmdir_args {
27305+ struct inode *dir;
27306+ aufs_bindex_t bindex;
27307+ struct dentry *wh_dentry;
27308+ struct au_nhash whlist;
27309+};
27310+
27311+struct au_nhash;
27312+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
27313+ struct dentry *wh_dentry, struct au_nhash *whlist);
27314+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
27315+ struct dentry *wh_dentry, struct au_nhash *whlist,
27316+ struct au_whtmp_rmdir_args *args);
27317+
27318+/* ---------------------------------------------------------------------- */
27319+
27320+static inline
27321+struct dentry *au_diropq_create(struct dentry *dentry, aufs_bindex_t bindex,
27322+ int dlgt)
27323+{
27324+ unsigned int flags = AuDiropq_CREATE;
27325+ if (dlgt)
27326+ au_fset_diropq(flags, DLGT);
27327+ return au_diropq_sio(dentry, bindex, flags);
27328+}
27329+
27330+static inline
27331+int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex, int dlgt)
27332+{
27333+ unsigned int flags = !AuDiropq_CREATE;
27334+ if (dlgt)
27335+ au_fset_diropq(flags, DLGT);
27336+ return PTR_ERR(au_diropq_sio(dentry, bindex, flags));
27337+}
27338+
27339+/* ---------------------------------------------------------------------- */
27340+
27341+#ifdef CONFIG_AUFS_ROBR
27342+/* robr.c */
27343+int au_test_robr_wh(struct qstr *name, struct dentry *h_parent,
27344+ struct qstr *wh_name, int try_sio, struct au_ndx *ndx);
27345+int au_test_robr_shwh(struct super_block *sb, const struct qstr *name);
27346+#else
27347+static inline
27348+int au_test_robr_wh(struct qstr *name, struct dentry *h_parent,
27349+ struct qstr *wh_name, int try_sio, struct au_ndx *ndx)
27350+{
27351+ return au_wh_test(h_parent, wh_name, try_sio, ndx);
27352+}
27353+
27354+static inline
27355+int au_test_robr_shwh(struct super_block *sb, const struct qstr *name)
27356+{
27357+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
27358+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
27359+ return -EPERM;
27360+ return 0;
27361+}
27362+#endif /* CONFIG_AUFS_ROBR */
27363+
27364+#endif /* __KERNEL__ */
27365+#endif /* __AUFS_WHOUT_H__ */
27366diff -urN linux/fs/aufs/wkq.c linux-aufs/fs/aufs/wkq.c
27367--- linux/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
27368+++ linux-aufs/fs/aufs/wkq.c 2009-03-12 16:18:04.000000000 +0100
1ddfd88b 27369@@ -0,0 +1,353 @@
024a5822
JR
27370+/*
27371+ * Copyright (C) 2005-2009 Junjiro Okajima
27372+ *
27373+ * This program, aufs is free software; you can redistribute it and/or modify
27374+ * it under the terms of the GNU General Public License as published by
27375+ * the Free Software Foundation; either version 2 of the License, or
27376+ * (at your option) any later version.
27377+ *
27378+ * This program is distributed in the hope that it will be useful,
27379+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27380+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27381+ * GNU General Public License for more details.
27382+ *
27383+ * You should have received a copy of the GNU General Public License
27384+ * along with this program; if not, write to the Free Software
27385+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27386+ */
27387+
27388+/*
27389+ * workqueue for asynchronous/super-io/delegated operations
27390+ *
27391+ * $Id$
27392+ */
27393+
27394+#include <linux/module.h>
27395+#include "aufs.h"
27396+
27397+struct au_wkq *au_wkq;
27398+
1ddfd88b 27399+struct au_cred {
27400+#ifdef CONFIG_AUFS_DLGT
27401+ struct cred *cred;
27402+#if 0 /* reserved for future use */
27403+ unsigned keep_capabilities:1;
27404+ struct user_struct *user;
27405+ struct fs_struct *fs;
27406+ struct nsproxy *nsproxy;
27407+#endif
27408+#endif
27409+};
024a5822
JR
27410+
27411+struct au_wkinfo {
27412+ struct work_struct wk;
27413+ struct super_block *sb;
27414+
27415+ unsigned int flags;
1ddfd88b 27416+ struct au_cred cred;
024a5822
JR
27417+
27418+ au_wkq_func_t func;
27419+ void *args;
27420+
27421+ atomic_t *busyp;
27422+ struct completion *comp;
27423+};
27424+
27425+/* ---------------------------------------------------------------------- */
27426+
27427+#ifdef CONFIG_AUFS_DLGT
1ddfd88b 27428+static void cred_store(struct au_cred *cred)
024a5822 27429+{
94750128 27430+ cred = get_current_cred();
024a5822
JR
27431+}
27432+
1ddfd88b 27433+static void cred_revert(struct au_cred *cred)
024a5822
JR
27434+{
27435+ AuDebugOn(!au_test_wkq(current));
94750128 27436+ revert_creds(cred);
024a5822
JR
27437+}
27438+
1ddfd88b 27439+static void cred_switch(struct au_cred *old, struct au_cred *new)
024a5822
JR
27440+{
27441+ cred_store(old);
27442+ cred_revert(new);
27443+}
27444+
27445+static void dlgt_cred_store(unsigned int flags, struct au_wkinfo *wkinfo)
27446+{
27447+ if (au_ftest_wkq(flags, DLGT))
27448+ cred_store(&wkinfo->cred);
27449+}
27450+
27451+static void dlgt_func(struct au_wkinfo *wkinfo)
27452+{
27453+ if (!au_ftest_wkq(wkinfo->flags, DLGT))
27454+ wkinfo->func(wkinfo->args);
27455+ else {
1ddfd88b 27456+ struct au_cred cred;
024a5822
JR
27457+ cred_switch(&cred, &wkinfo->cred);
27458+ wkinfo->func(wkinfo->args);
27459+ cred_revert(&cred);
27460+ }
27461+}
27462+#else
27463+static void dlgt_cred_store(unsigned int flags, struct au_wkinfo *wkinfo)
27464+{
27465+ /* empty */
27466+}
27467+
27468+static void dlgt_func(struct au_wkinfo *wkinfo)
27469+{
27470+ wkinfo->func(wkinfo->args);
27471+}
27472+#endif /* CONFIG_AUFS_DLGT */
27473+
27474+/* ---------------------------------------------------------------------- */
27475+
27476+static void update_busy(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
27477+{
27478+#ifdef CONFIG_AUFS_STAT
27479+ unsigned int new, old;
27480+
27481+ do {
27482+ new = atomic_read(wkinfo->busyp);
27483+ old = wkq->max_busy;
27484+ if (new <= old)
27485+ break;
27486+ } while (cmpxchg(&wkq->max_busy, old, new) == old);
27487+#endif
27488+}
27489+
27490+static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
27491+{
27492+ AuTraceEnter();
27493+
27494+ wkinfo->busyp = &wkq->busy;
27495+ update_busy(wkq, wkinfo);
27496+ if (au_ftest_wkq(wkinfo->flags, WAIT))
27497+ return !queue_work(wkq->q, &wkinfo->wk);
27498+ else
27499+ return !schedule_work(&wkinfo->wk);
27500+}
27501+
27502+static void do_wkq(struct au_wkinfo *wkinfo)
27503+{
27504+ unsigned int idle, n;
27505+ int i, idle_idx;
27506+
27507+ AuTraceEnter();
27508+
27509+ while (1) {
27510+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
27511+ idle_idx = 0;
27512+ idle = UINT_MAX;
27513+ for (i = 0; i < aufs_nwkq; i++) {
27514+ n = atomic_inc_return(&au_wkq[i].busy);
27515+ if (n == 1 && !enqueue(au_wkq + i, wkinfo))
27516+ return; /* success */
27517+
27518+ if (n < idle) {
27519+ idle_idx = i;
27520+ idle = n;
27521+ }
27522+ atomic_dec_return(&au_wkq[i].busy);
27523+ }
27524+ } else
27525+ idle_idx = aufs_nwkq;
27526+
27527+ atomic_inc_return(&au_wkq[idle_idx].busy);
27528+ if (!enqueue(au_wkq + idle_idx, wkinfo))
27529+ return; /* success */
27530+
27531+ /* impossible? */
27532+ AuWarn1("failed to queue_work()\n");
27533+ yield();
27534+ }
27535+}
27536+
27537+static void wkq_func(struct work_struct *wk)
27538+{
27539+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
27540+
27541+ LKTRTrace("wkinfo{0x%x, %p, %p, %p}\n",
27542+ wkinfo->flags, wkinfo->func, wkinfo->busyp, wkinfo->comp);
27543+
27544+ dlgt_func(wkinfo);
27545+ atomic_dec_return(wkinfo->busyp);
27546+ if (au_ftest_wkq(wkinfo->flags, WAIT))
27547+ complete(wkinfo->comp);
27548+ else {
27549+ kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
27550+ module_put(THIS_MODULE);
27551+ kfree(wkinfo);
27552+ }
27553+}
27554+
27555+#if defined(CONFIG_4KSTACKS) || defined(Test4KSTACKS)
27556+#define AuWkqCompDeclare(name) struct completion *comp = NULL
27557+
27558+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
27559+{
27560+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
27561+ if (*comp) {
27562+ init_completion(*comp);
27563+ wkinfo->comp = *comp;
27564+ return 0;
27565+ }
27566+ return -ENOMEM;
27567+}
27568+
27569+static void au_wkq_comp_free(struct completion *comp)
27570+{
27571+ kfree(comp);
27572+}
27573+
27574+#else
27575+
27576+/* no braces */
27577+#define AuWkqCompDeclare(name) \
27578+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
27579+ struct completion *comp = &_ ## name
27580+
27581+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
27582+{
27583+ wkinfo->comp = *comp;
27584+ return 0;
27585+}
27586+
27587+static void au_wkq_comp_free(struct completion *comp)
27588+{
27589+ /* empty */
27590+}
27591+#endif /* 4KSTACKS */
27592+
27593+static void au_wkq_run(struct au_wkinfo *wkinfo)
27594+{
27595+#if 1 /* tmp debug */
27596+ if (au_test_wkq(current))
27597+ au_dbg_blocked();
27598+#endif
27599+ AuDebugOn(au_test_wkq(current));
27600+
27601+ INIT_WORK(&wkinfo->wk, wkq_func);
27602+ dlgt_cred_store(wkinfo->flags, wkinfo);
27603+ do_wkq(wkinfo);
27604+}
27605+
27606+int au_wkq_wait(au_wkq_func_t func, void *args, int dlgt)
27607+{
27608+ int err;
27609+ AuWkqCompDeclare(comp);
27610+ struct au_wkinfo wkinfo = {
27611+ .flags = AuWkq_WAIT,
27612+ .func = func,
27613+ .args = args
27614+ };
27615+
27616+ LKTRTrace("dlgt %d\n", dlgt);
27617+
27618+ err = au_wkq_comp_alloc(&wkinfo, &comp);
27619+ if (!err) {
27620+ if (dlgt)
27621+ au_fset_wkq(wkinfo.flags, DLGT);
27622+ au_wkq_run(&wkinfo);
27623+ /* no timeout, no interrupt */
27624+ wait_for_completion(wkinfo.comp);
27625+ au_wkq_comp_free(comp);
27626+ }
27627+
27628+ AuTraceErr(err);
27629+ return err;
27630+
27631+}
27632+
27633+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
27634+ int dlgt)
27635+{
27636+ int err;
27637+ struct au_wkinfo *wkinfo;
27638+
27639+ LKTRTrace("dlgt %d\n", dlgt);
27640+ AuDebugOn(!sb);
27641+
27642+ atomic_inc_return(&au_sbi(sb)->si_nowait.nw_len);
27643+
27644+ /*
27645+ * wkq_func() must free this wkinfo.
27646+ * it highly depends upon the implementation of workqueue.
27647+ */
27648+ err = 0;
27649+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
27650+ if (wkinfo) {
27651+ wkinfo->sb = sb;
27652+ wkinfo->flags = !AuWkq_WAIT;
27653+ wkinfo->func = func;
27654+ wkinfo->args = args;
27655+ wkinfo->comp = NULL;
27656+ if (dlgt)
27657+ au_fset_wkq(wkinfo->flags, DLGT);
27658+ kobject_get(&au_sbi(sb)->si_kobj);
27659+ __module_get(THIS_MODULE);
27660+
27661+ au_wkq_run(wkinfo);
27662+ } else {
27663+ err = -ENOMEM;
27664+ atomic_dec_return(&au_sbi(sb)->si_nowait.nw_len);
27665+ }
27666+
27667+ AuTraceErr(err);
27668+ return err;
27669+}
27670+
27671+/* ---------------------------------------------------------------------- */
27672+
27673+void au_wkq_fin(void)
27674+{
27675+ int i;
27676+
27677+ AuTraceEnter();
27678+
27679+ for (i = 0; i < aufs_nwkq; i++)
27680+ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
27681+ destroy_workqueue(au_wkq[i].q);
27682+ kfree(au_wkq);
27683+}
27684+
27685+int __init au_wkq_init(void)
27686+{
27687+ int err, i;
27688+ struct au_wkq *nowaitq;
27689+
27690+ LKTRTrace("%d\n", aufs_nwkq);
27691+
27692+ /* '+1' is for accounting of nowait queue */
27693+ err = -ENOMEM;
27694+ au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_NOFS);
27695+ if (unlikely(!au_wkq))
27696+ goto out;
27697+
27698+ err = 0;
27699+ for (i = 0; i < aufs_nwkq; i++) {
27700+ au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
27701+ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
27702+ atomic_set(&au_wkq[i].busy, 0);
27703+ au_wkq_max_busy_init(au_wkq + i);
27704+ continue;
27705+ }
27706+
27707+ err = PTR_ERR(au_wkq[i].q);
27708+ au_wkq_fin();
27709+ break;
27710+ }
27711+
27712+ /* nowait accounting */
27713+ nowaitq = au_wkq + aufs_nwkq;
27714+ atomic_set(&nowaitq->busy, 0);
27715+ au_wkq_max_busy_init(nowaitq);
27716+ nowaitq->q = NULL;
27717+ /* smp_mb(); */ /* atomic_set */
27718+
27719+ out:
27720+ AuTraceErr(err);
27721+ return err;
27722+}
27723diff -urN linux/fs/aufs/wkq.h linux-aufs/fs/aufs/wkq.h
27724--- linux/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
27725+++ linux-aufs/fs/aufs/wkq.h 2009-03-12 16:18:04.000000000 +0100
27726@@ -0,0 +1,128 @@
27727+/*
27728+ * Copyright (C) 2005-2009 Junjiro Okajima
27729+ *
27730+ * This program, aufs is free software; you can redistribute it and/or modify
27731+ * it under the terms of the GNU General Public License as published by
27732+ * the Free Software Foundation; either version 2 of the License, or
27733+ * (at your option) any later version.
27734+ *
27735+ * This program is distributed in the hope that it will be useful,
27736+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27737+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27738+ * GNU General Public License for more details.
27739+ *
27740+ * You should have received a copy of the GNU General Public License
27741+ * along with this program; if not, write to the Free Software
27742+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27743+ */
27744+
27745+/*
27746+ * workqueue for asynchronous/super-io/delegated operations
27747+ *
27748+ * $Id$
27749+ */
27750+
27751+#ifndef __AUFS_WKQ_H__
27752+#define __AUFS_WKQ_H__
27753+
27754+#ifdef __KERNEL__
27755+
27756+#include <linux/fs.h>
27757+#include <linux/sched.h>
27758+#include <linux/workqueue.h>
27759+#include <linux/aufs_type.h>
27760+
27761+/* ---------------------------------------------------------------------- */
27762+
27763+/* internal workqueue named AUFS_WKQ_NAME */
27764+struct au_wkq {
27765+ struct workqueue_struct *q;
27766+
27767+ /* balancing */
27768+ atomic_t busy;
27769+
27770+ /* accounting */
27771+#ifdef CONFIG_AUFS_STAT
27772+ unsigned int max_busy;
27773+#endif
27774+};
27775+
27776+/*
27777+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
27778+ */
27779+struct au_nowait_tasks {
27780+ atomic_t nw_len;
27781+ wait_queue_head_t nw_wq;
27782+};
27783+
27784+/* ---------------------------------------------------------------------- */
27785+
27786+extern struct au_wkq *au_wkq;
27787+typedef void (*au_wkq_func_t)(void *args);
27788+
27789+/* wkq flags */
27790+#define AuWkq_WAIT 1
27791+#define AuWkq_DLGT (1 << 1)
27792+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
27793+#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
27794+#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
27795+#ifndef CONFIG_AUFS_DLGT
27796+#undef AuWkq_DLGT
27797+#define AuWkq_DLGT 0
27798+#endif
27799+
27800+int au_wkq_wait(au_wkq_func_t func, void *args, int dlgt);
27801+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
27802+ int dlgt);
27803+int __init au_wkq_init(void);
27804+void au_wkq_fin(void);
27805+
27806+/* ---------------------------------------------------------------------- */
27807+
27808+static inline int au_test_nowait_wkq(struct task_struct *tsk)
27809+{
27810+ static const char *p = "events";
27811+ return !tsk->mm && !strncmp(tsk->comm, p, strlen(p));
27812+}
27813+
27814+static inline int au_test_wkq(struct task_struct *tsk)
27815+{
27816+ return !tsk->mm && !strcmp(tsk->comm, AUFS_WKQ_NAME);
27817+#if 0 /* reserved for future use, per-cpu workqueue */
27818+ return !tsk->mm
27819+ && !memcmp(tsk->comm, AUFS_WKQ_NAME "/",
27820+ sizeof(AUFS_WKQ_NAME));
27821+#endif
27822+}
27823+
27824+static inline void au_wkq_max_busy_init(struct au_wkq *wkq)
27825+{
27826+#ifdef CONFIG_AUFS_STAT
27827+ wkq->max_busy = 0;
27828+#endif
27829+}
27830+
27831+/* todo: memory barrier? */
27832+static inline void au_nwt_init(struct au_nowait_tasks *nwt)
27833+{
27834+ atomic_set(&nwt->nw_len, 0);
27835+ smp_mb(); /* atomic_set */
27836+ init_waitqueue_head(&nwt->nw_wq);
27837+}
27838+
27839+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
27840+{
27841+ AuTraceEnter();
27842+
27843+ if (!atomic_dec_return(&nwt->nw_len))
27844+ wake_up_all(&nwt->nw_wq);
27845+}
27846+
27847+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
27848+{
27849+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
27850+ return 0;
27851+}
27852+
27853+#endif /* __KERNEL__ */
27854+#endif /* __AUFS_WKQ_H__ */
27855diff -urN linux/fs/aufs/xino.c linux-aufs/fs/aufs/xino.c
27856--- linux/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
27857+++ linux-aufs/fs/aufs/xino.c 2009-03-12 16:18:04.000000000 +0100
27858@@ -0,0 +1,1268 @@
27859+/*
27860+ * Copyright (C) 2005-2009 Junjiro Okajima
27861+ *
27862+ * This program, aufs is free software; you can redistribute it and/or modify
27863+ * it under the terms of the GNU General Public License as published by
27864+ * the Free Software Foundation; either version 2 of the License, or
27865+ * (at your option) any later version.
27866+ *
27867+ * This program is distributed in the hope that it will be useful,
27868+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27869+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27870+ * GNU General Public License for more details.
27871+ *
27872+ * You should have received a copy of the GNU General Public License
27873+ * along with this program; if not, write to the Free Software
27874+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27875+ */
27876+
27877+/*
27878+ * external inode number translation table and bitmap
27879+ *
27880+ * $Id$
27881+ */
27882+
27883+#include <linux/uaccess.h>
27884+#include "aufs.h"
27885+
27886+/* ---------------------------------------------------------------------- */
27887+
27888+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
27889+ loff_t *pos)
27890+{
27891+ ssize_t err;
27892+ mm_segment_t oldfs;
27893+
27894+ LKTRTrace("%.*s, sz %zu, *pos %lld\n",
27895+ AuDLNPair(file->f_dentry), size, *pos);
27896+
27897+ oldfs = get_fs();
27898+ set_fs(KERNEL_DS);
27899+ do {
27900+ /* todo: signal_pending? */
27901+ err = func(file, (char __user *)buf, size, pos);
27902+ } while (err == -EAGAIN || err == -EINTR);
27903+ set_fs(oldfs);
27904+
27905+#if 0 /* reserved for future use */
27906+ if (err > 0)
27907+ fsnotify_access(file->f_dentry);
27908+#endif
27909+
27910+ AuTraceErr(err);
27911+ return err;
27912+}
27913+
27914+/* ---------------------------------------------------------------------- */
27915+
27916+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
27917+ size_t size, loff_t *pos)
27918+{
27919+ ssize_t err;
27920+ mm_segment_t oldfs;
27921+
27922+ lockdep_off();
27923+ oldfs = get_fs();
27924+ set_fs(KERNEL_DS);
27925+ do {
27926+ /* todo: signal_pending? */
27927+ err = func(file, (const char __user *)buf, size, pos);
27928+ } while (err == -EAGAIN || err == -EINTR);
27929+ set_fs(oldfs);
27930+ lockdep_on();
27931+
27932+ if (err >= 0)
27933+ au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
27934+ /*ignore*/
27935+
27936+#if 0 /* reserved for future use */
27937+ if (err > 0)
27938+ fsnotify_modify(file->f_dentry);
27939+#endif
27940+
27941+ AuTraceErr(err);
27942+ return err;
27943+}
27944+
27945+struct do_xino_fwrite_args {
27946+ ssize_t *errp;
27947+ au_writef_t func;
27948+ struct file *file;
27949+ void *buf;
27950+ size_t size;
27951+ loff_t *pos;
27952+};
27953+
27954+static void call_do_xino_fwrite(void *args)
27955+{
27956+ struct do_xino_fwrite_args *a = args;
27957+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
27958+}
27959+
27960+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
27961+ loff_t *pos)
27962+{
27963+ ssize_t err;
27964+
27965+ LKTRTrace("%.*s, sz %zu, *pos %lld\n",
27966+ AuDLNPair(file->f_dentry), size, *pos);
27967+
27968+ /* todo: signal block and no wkq? */
27969+ /*
27970+ * it breaks RLIMIT_FSIZE and normal user's limit,
27971+ * users should care about quota and real 'filesystem full.'
27972+ */
27973+ if (!au_test_wkq(current)) {
27974+ int wkq_err;
27975+ struct do_xino_fwrite_args args = {
27976+ .errp = &err,
27977+ .func = func,
27978+ .file = file,
27979+ .buf = buf,
27980+ .size = size,
27981+ .pos = pos
27982+ };
27983+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args, /*dlgt*/0);
27984+ if (unlikely(wkq_err))
27985+ err = wkq_err;
27986+ } else
27987+ err = do_xino_fwrite(func, file, buf, size, pos);
27988+
27989+ AuTraceErr(err);
27990+ return err;
27991+}
27992+
27993+/* ---------------------------------------------------------------------- */
27994+
27995+struct xino_do_trunc_args {
27996+ struct super_block *sb;
27997+ struct au_branch *br;
27998+};
27999+
28000+static void xino_do_trunc(void *_args)
28001+{
28002+ struct xino_do_trunc_args *args = _args;
28003+ struct super_block *sb;
28004+ aufs_bindex_t bindex;
28005+ int err;
28006+ struct file *file;
28007+ struct inode *dir;
28008+ struct au_sbinfo *sbinfo;
28009+
28010+ err = 0;
28011+ sb = args->sb;
28012+ dir = sb->s_root->d_inode;
28013+ si_noflush_write_lock(sb);
28014+ ii_read_lock_parent(dir);
28015+ bindex = au_br_index(sb, args->br->br_id);
28016+ AuDebugOn(bindex < 0);
28017+ err = au_xino_trunc(sb, bindex);
28018+ if (unlikely(err))
28019+ goto out;
28020+
28021+ file = args->br->br_xino.xi_file;
28022+ au_update_fuse_h_inode(args->br->br_mnt, file->f_dentry); /*ignore*/
28023+ if (file->f_dentry->d_inode->i_blocks >= args->br->br_xino_upper)
28024+ args->br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
28025+
28026+ out:
28027+ ii_read_unlock(dir);
28028+ if (unlikely(err))
28029+ AuWarn("err b%d, (%d)\n", bindex, err);
28030+ atomic_dec_return(&args->br->br_xino_running);
28031+ au_br_put(args->br);
28032+ sbinfo = au_sbi(sb);
28033+ au_nwt_done(&sbinfo->si_nowait);
28034+ si_write_unlock(sb);
28035+ kfree(args);
28036+}
28037+
28038+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
28039+{
28040+ struct xino_do_trunc_args *args;
28041+ struct au_sbinfo *sbinfo;
28042+ struct file *file = br->br_xino.xi_file;
28043+ int wkq_err;
28044+
28045+ au_update_fuse_h_inode(br->br_mnt, file->f_dentry); /*ignore*/
28046+ if (file->f_dentry->d_inode->i_blocks < br->br_xino_upper)
28047+ return;
28048+ if (atomic_inc_return(&br->br_xino_running) > 1)
28049+ goto out;
28050+
28051+ /* lock and kfree() will be called in trunc_xino() */
28052+ args = kmalloc(sizeof(*args), GFP_NOFS);
28053+ if (unlikely(!args)) {
28054+ AuErr1("no memory\n");
28055+ goto out_args;
28056+ }
28057+
28058+ sbinfo = au_sbi(sb);
28059+ au_br_get(br);
28060+ args->sb = sb;
28061+ args->br = br;
28062+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*dlgt*/0);
28063+ if (!wkq_err)
28064+ return; /* success */
28065+
28066+ AuErr("wkq %d\n", wkq_err);
28067+ au_br_put(br);
28068+
28069+ out_args:
28070+ kfree(args);
28071+ out:
28072+ atomic_dec_return(&br->br_xino_running);
28073+}
28074+
28075+/* ---------------------------------------------------------------------- */
28076+
28077+static int au_xino_do_write(au_writef_t write, struct file *file,
28078+ ino_t h_ino, struct au_xino_entry *xinoe)
28079+{
28080+ loff_t pos;
28081+ ssize_t sz;
28082+
28083+ AuTraceEnter();
28084+
28085+ pos = h_ino;
28086+ if (unlikely(Au_LOFF_MAX / sizeof(*xinoe) - 1 < pos)) {
28087+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
28088+ return -EFBIG;
28089+ }
28090+ pos *= sizeof(*xinoe);
28091+ sz = xino_fwrite(write, file, xinoe, sizeof(*xinoe), &pos);
28092+ if (sz == sizeof(*xinoe))
28093+ return 0; /* success */
28094+
28095+ AuIOErr("write failed (%zd)\n", sz);
28096+ return -EIO;
28097+}
28098+
28099+/*
28100+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
28101+ * at the position of @_ino.
28102+ * when @ino is zero, it is written to the xinofile and means no entry.
28103+ */
28104+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
28105+ struct au_xino_entry *xinoe)
28106+{
28107+ int err;
28108+ struct file *file;
28109+ struct au_branch *br;
28110+ unsigned int mnt_flags;
28111+
28112+ LKTRTrace("b%d, hi%lu, i%lu\n",
28113+ bindex, (unsigned long)h_ino, (unsigned long)xinoe->ino);
28114+ BUILD_BUG_ON(sizeof(long long) != sizeof(Au_LOFF_MAX)
28115+ || ((loff_t)-1) > 0);
28116+
28117+ mnt_flags = au_mntflags(sb);
28118+ if (!au_opt_test_xino(mnt_flags))
28119+ return 0;
28120+
28121+ br = au_sbr(sb, bindex);
28122+ file = br->br_xino.xi_file;
28123+ AuDebugOn(!file);
28124+
28125+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, h_ino, xinoe);
28126+ if (!err) {
28127+ if (au_opt_test(mnt_flags, TRUNC_XINO)
28128+ && au_test_trunc_xino(br->br_mnt->mnt_sb))
28129+ xino_try_trunc(sb, br);
28130+ return 0; /* success */
28131+ }
28132+
28133+ AuIOErr("write failed (%d)\n", err);
28134+ return -EIO;
28135+}
28136+
28137+/* ---------------------------------------------------------------------- */
28138+
28139+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
28140+static ino_t xib_calc_ino(unsigned long pindex, int bit)
28141+{
28142+ ino_t ino;
28143+
28144+ AuDebugOn(bit < 0 || page_bits <= bit);
28145+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
28146+ return ino;
28147+}
28148+
28149+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
28150+{
28151+ AuDebugOn(ino < AUFS_FIRST_INO);
28152+ ino -= AUFS_FIRST_INO;
28153+ *pindex = ino / page_bits;
28154+ *bit = ino % page_bits;
28155+}
28156+
28157+static int xib_pindex(struct super_block *sb, unsigned long pindex)
28158+{
28159+ int err;
28160+ struct au_sbinfo *sbinfo;
28161+ loff_t pos;
28162+ ssize_t sz;
28163+ struct file *xib;
28164+ unsigned long *p;
28165+
28166+ LKTRTrace("pindex %lu\n", pindex);
28167+ sbinfo = au_sbi(sb);
28168+ MtxMustLock(&sbinfo->si_xib_mtx);
28169+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
28170+ || !au_opt_test_xino(sbinfo->si_mntflags));
28171+
28172+ if (pindex == sbinfo->si_xib_last_pindex)
28173+ return 0;
28174+
28175+ xib = sbinfo->si_xib;
28176+ p = sbinfo->si_xib_buf;
28177+ pos = sbinfo->si_xib_last_pindex;
28178+ pos *= PAGE_SIZE;
28179+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
28180+ if (unlikely(sz != PAGE_SIZE))
28181+ goto out;
28182+
28183+ pos = pindex;
28184+ pos *= PAGE_SIZE;
28185+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
28186+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
28187+ else {
28188+ memset(p, 0, PAGE_SIZE);
28189+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
28190+ }
28191+ if (sz == PAGE_SIZE) {
28192+ sbinfo->si_xib_last_pindex = pindex;
28193+ return 0; /* success */
28194+ }
28195+
28196+ out:
28197+ AuIOErr1("write failed (%zd)\n", sz);
28198+ err = sz;
28199+ if (sz >= 0)
28200+ err = -EIO;
28201+ AuTraceErr(err);
28202+ return err;
28203+}
28204+
28205+/* ---------------------------------------------------------------------- */
28206+
28207+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
28208+ ino_t ino)
28209+{
28210+ int err, bit;
28211+ unsigned long pindex;
28212+ struct au_sbinfo *sbinfo;
28213+ struct au_xino_entry xinoe = {
28214+ .ino = 0
28215+ };
28216+
28217+ LKTRTrace("b%d, hi%lu, i%lu\n",
28218+ bindex, (unsigned long)h_ino, (unsigned long)ino);
28219+
28220+ if (!au_opt_test_xino(au_mntflags(sb)))
28221+ return 0;
28222+
28223+ err = 0;
28224+ sbinfo = au_sbi(sb);
28225+ if (ino) {
28226+ AuDebugOn(ino < AUFS_FIRST_INO);
28227+ xib_calc_bit(ino, &pindex, &bit);
28228+ AuDebugOn(page_bits <= bit);
28229+ mutex_lock(&sbinfo->si_xib_mtx);
28230+ err = xib_pindex(sb, pindex);
28231+ if (!err) {
28232+ clear_bit(bit, sbinfo->si_xib_buf);
28233+ sbinfo->si_xib_next_bit = bit;
28234+ }
28235+ mutex_unlock(&sbinfo->si_xib_mtx);
28236+ }
28237+
28238+ if (!err)
28239+ err = au_xino_write(sb, bindex, h_ino, &xinoe);
28240+ return err;
28241+}
28242+
28243+ino_t au_xino_new_ino(struct super_block *sb)
28244+{
28245+ ino_t ino;
28246+ struct au_sbinfo *sbinfo;
28247+ int free_bit, err;
28248+ unsigned long *p, pindex, ul, pend;
28249+ struct file *file;
28250+
28251+ AuTraceEnter();
28252+
28253+ if (!au_opt_test_xino(au_mntflags(sb)))
28254+ return iunique(sb, AUFS_FIRST_INO);
28255+
28256+ sbinfo = au_sbi(sb);
28257+ mutex_lock(&sbinfo->si_xib_mtx);
28258+ p = sbinfo->si_xib_buf;
28259+ free_bit = sbinfo->si_xib_next_bit;
28260+ if (free_bit < page_bits && !test_bit(free_bit, p))
28261+ goto out; /* success */
28262+ free_bit = find_first_zero_bit(p, page_bits);
28263+ if (free_bit < page_bits)
28264+ goto out; /* success */
28265+
28266+ pindex = sbinfo->si_xib_last_pindex;
28267+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
28268+ err = xib_pindex(sb, ul);
28269+ if (unlikely(err))
28270+ goto out_err;
28271+ free_bit = find_first_zero_bit(p, page_bits);
28272+ if (free_bit < page_bits)
28273+ goto out; /* success */
28274+ }
28275+
28276+ file = sbinfo->si_xib;
28277+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
28278+ for (ul = pindex + 1; ul <= pend; ul++) {
28279+ err = xib_pindex(sb, ul);
28280+ if (unlikely(err))
28281+ goto out_err;
28282+ free_bit = find_first_zero_bit(p, page_bits);
28283+ if (free_bit < page_bits)
28284+ goto out; /* success */
28285+ }
28286+ BUG();
28287+
28288+ out:
28289+ set_bit(free_bit, p);
28290+ sbinfo->si_xib_next_bit++;
28291+ pindex = sbinfo->si_xib_last_pindex;
28292+ mutex_unlock(&sbinfo->si_xib_mtx);
28293+ ino = xib_calc_ino(pindex, free_bit);
28294+ LKTRTrace("i%lu\n", (unsigned long)ino);
28295+ return ino;
28296+ out_err:
28297+ mutex_unlock(&sbinfo->si_xib_mtx);
28298+ LKTRTrace("i0\n");
28299+ return 0;
28300+}
28301+
28302+/*
28303+ * read @ino from xinofile for the specified branch{@sb, @bindex}
28304+ * at the position of @h_ino.
28305+ * if @ino does not exist and @do_new is true, get new one.
28306+ */
28307+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
28308+ struct au_xino_entry *xinoe)
28309+{
28310+ int err;
28311+ struct file *file;
28312+ loff_t pos;
28313+ ssize_t sz;
28314+ struct au_sbinfo *sbinfo;
28315+
28316+ LKTRTrace("b%d, hi%lu\n", bindex, (unsigned long)h_ino);
28317+
28318+ xinoe->ino = 0;
28319+ if (!au_opt_test_xino(au_mntflags(sb)))
28320+ return 0; /* no ino */
28321+
28322+ err = 0;
28323+ sbinfo = au_sbi(sb);
28324+ pos = h_ino;
28325+ if (unlikely(Au_LOFF_MAX / sizeof(*xinoe) - 1 < pos)) {
28326+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
28327+ return -EFBIG;
28328+ }
28329+ pos *= sizeof(*xinoe);
28330+
28331+ file = au_sbr(sb, bindex)->br_xino.xi_file;
28332+ AuDebugOn(!file);
28333+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*xinoe))
28334+ return 0; /* no ino */
28335+
28336+ sz = xino_fread(sbinfo->si_xread, file, xinoe, sizeof(*xinoe), &pos);
28337+ if (sz == sizeof(*xinoe))
28338+ return 0; /* success */
28339+
28340+ err = sz;
28341+ if (unlikely(sz >= 0)) {
28342+ err = -EIO;
28343+ AuIOErr("xino read error (%zd)\n", sz);
28344+ }
28345+
28346+ AuTraceErr(err);
28347+ return err;
28348+}
28349+
28350+/* ---------------------------------------------------------------------- */
28351+
28352+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
28353+{
28354+ struct file *file;
28355+ int err;
28356+ struct dentry *h_parent;
28357+ struct inode *h_dir;
28358+ struct vfsub_args vargs;
28359+
28360+ LKTRTrace("%s\n", fname);
28361+
28362+ /*
28363+ * at mount-time, and the xino file is the default path,
28364+ * hinotify is disabled so we have no inotify events to ignore.
28365+ * when a user specified the xino, we cannot get au_hdir to be ignored.
28366+ */
28367+ vfsub_args_init(&vargs, /*ign*/NULL, /*dlgt*/0, 0);
28368+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
28369+ S_IRUGO | S_IWUGO);
28370+ if (IS_ERR(file)) {
28371+ if (!silent)
28372+ AuErr("open %s(%ld)\n", fname, PTR_ERR(file));
28373+ return file;
28374+ }
28375+
28376+ /* keep file count */
28377+ h_parent = dget_parent(file->f_dentry);
28378+ h_dir = h_parent->d_inode;
28379+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
28380+ /* mnt_want_write() is unnecessary here */
28381+ err = vfsub_unlink(h_dir, file->f_dentry, &vargs);
28382+ mutex_unlock(&h_dir->i_mutex);
28383+ dput(h_parent);
28384+ if (unlikely(err)) {
28385+ if (!silent)
28386+ AuErr("unlink %s(%d)\n", fname, err);
28387+ goto out;
28388+ }
28389+
28390+ if (sb != file->f_dentry->d_sb)
28391+ return file; /* success */
28392+
28393+ if (!silent)
28394+ AuErr("%s must be outside\n", fname);
28395+ err = -EINVAL;
28396+
28397+ out:
28398+ fput(file);
28399+ file = ERR_PTR(err);
28400+ return file;
28401+}
28402+
28403+/*
28404+ * find another branch who is on the same filesystem of the specified
28405+ * branch{@btgt}. search until @bend.
28406+ */
28407+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
28408+ aufs_bindex_t bend)
28409+{
28410+ aufs_bindex_t bindex;
28411+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
28412+
28413+ for (bindex = 0; bindex < btgt; bindex++)
28414+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
28415+ return bindex;
28416+ for (bindex++; bindex <= bend; bindex++)
28417+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
28418+ return bindex;
28419+ return -1;
28420+}
28421+
28422+/*
28423+ * create a new xinofile at the same place/path as @base_file.
28424+ */
28425+struct file *au_xino_create2(struct super_block *sb, struct file *base_file,
28426+ struct file *copy_src)
28427+{
28428+ struct file *file;
28429+ int err;
28430+ struct dentry *base, *dentry, *parent;
28431+ struct inode *dir, *inode;
28432+ struct qstr *name;
28433+ struct au_hinode *hdir;
28434+ struct au_branch *br;
28435+ aufs_bindex_t bindex;
28436+ struct au_hin_ignore ign;
28437+ struct vfsub_args vargs;
28438+ struct au_ndx ndx = {
28439+ .nfsmnt = NULL,
28440+ .flags = 0,
28441+ .nd = NULL,
28442+ /* .br = NULL */
28443+ };
28444+
28445+ base = base_file->f_dentry;
28446+ LKTRTrace("%.*s\n", AuDLNPair(base));
28447+ parent = base->d_parent; /* dir inode is locked */
28448+ dir = parent->d_inode;
28449+ IMustLock(dir);
28450+
28451+ file = ERR_PTR(-EINVAL);
28452+ if (unlikely(au_test_nfs(parent->d_sb)
28453+ || au_test_ecryptfs(parent->d_sb)))
28454+ goto out;
28455+
28456+ /* do not superio, nor NFS. */
28457+ name = &base->d_name;
28458+ dentry = au_lkup_one(name->name, parent, name->len, &ndx);
28459+ if (IS_ERR(dentry)) {
28460+ file = (void *)dentry;
28461+ AuErr("%.*s lookup err %ld\n", AuLNPair(name), PTR_ERR(dentry));
28462+ goto out;
28463+ }
28464+
28465+ hdir = NULL;
28466+ br = au_xino_def_br(au_sbi(sb));
28467+ if (br) {
28468+ bindex = au_find_bindex(sb, br);
28469+ if (bindex >= 0)
28470+ hdir = au_hi(sb->s_root->d_inode, bindex);
28471+ }
28472+ vfsub_args_init(&vargs, &ign, 0, 0);
28473+ vfsub_ign_hinode(&vargs, IN_CREATE, hdir);
28474+ /* no need to mnt_want_write() since we call dentry_open() later */
28475+ err = vfsub_create(dir, dentry, S_IRUGO | S_IWUGO, NULL, &vargs);
28476+ if (unlikely(err)) {
28477+ file = ERR_PTR(err);
28478+ AuErr("%.*s create err %d\n", AuLNPair(name), err);
28479+ goto out_dput;
28480+ }
28481+ file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt),
94750128 28482+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE, base_file->f_cred);
024a5822
JR
28483+ if (IS_ERR(file)) {
28484+ AuErr("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
28485+ goto out_dput;
28486+ }
28487+ vfsub_args_reinit(&vargs);
28488+ vfsub_ign_hinode(&vargs, IN_DELETE, hdir);
28489+ err = vfsub_unlink(dir, dentry, &vargs);
28490+ if (unlikely(err)) {
28491+ AuErr("%.*s unlink err %d\n", AuLNPair(name), err);
28492+ goto out_fput;
28493+ }
28494+
28495+ if (copy_src) {
28496+ inode = copy_src->f_dentry->d_inode;
28497+ err = au_copy_file(file, copy_src, i_size_read(inode),
28498+ hdir, sb, &vargs);
28499+ if (unlikely(err)) {
28500+ AuErr("%.*s copy err %d\n", AuLNPair(name), err);
28501+ goto out_fput;
28502+ }
28503+ }
28504+ goto out_dput; /* success */
28505+
28506+ out_fput:
28507+ fput(file);
28508+ file = ERR_PTR(err);
28509+ out_dput:
28510+ dput(dentry);
28511+ out:
28512+ AuTraceErrPtr(file);
28513+ return file;
28514+}
28515+
28516+/* ---------------------------------------------------------------------- */
28517+
28518+/*
28519+ * initialize the xinofile for the specified branch{@sb, @bindex}
28520+ * at the place/path where @base_file indicates.
28521+ * test whether another branch is on the same filesystem or not,
28522+ * if @do_test is true.
28523+ */
28524+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
28525+ struct file *base_file, int do_test)
28526+{
28527+ int err;
28528+ struct au_branch *shared_br;
28529+ aufs_bindex_t bshared, bend, bindex;
28530+ unsigned char do_create;
28531+ struct inode *dir;
28532+ struct au_xino_entry xinoe;
28533+ struct dentry *parent;
28534+ struct file *file;
28535+ struct super_block *tgt_sb;
28536+
28537+ LKTRTrace("base_file %p, do_test %d\n", base_file, do_test);
28538+ SiMustWriteLock(sb);
28539+ AuDebugOn(!au_opt_test_xino(au_mntflags(sb)));
28540+ AuDebugOn(br->br_xino.xi_file);
28541+
28542+ do_create = 1;
28543+ bshared = -1;
28544+ shared_br = NULL;
28545+ bend = au_sbend(sb);
28546+ if (do_test) {
28547+ tgt_sb = br->br_mnt->mnt_sb;
28548+ for (bindex = 0; bindex <= bend; bindex++)
28549+ if (tgt_sb == au_sbr_sb(sb, bindex)) {
28550+ bshared = bindex;
28551+ break;
28552+ }
28553+ }
28554+ if (bshared >= 0) {
28555+ shared_br = au_sbr(sb, bshared);
28556+ do_create = !shared_br->br_xino.xi_file;
28557+ }
28558+
28559+ if (do_create) {
28560+ parent = dget_parent(base_file->f_dentry);
28561+ dir = parent->d_inode;
28562+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
28563+ /* mnt_want_write() is unnecessary here */
28564+ file = au_xino_create2(sb, base_file, NULL);
28565+ mutex_unlock(&dir->i_mutex);
28566+ dput(parent);
28567+ err = PTR_ERR(file);
28568+ if (IS_ERR(file))
28569+ goto out;
28570+ br->br_xino.xi_file = file;
28571+ } else {
28572+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
28573+ get_file(br->br_xino.xi_file);
28574+ }
28575+
28576+ xinoe.ino = AUFS_ROOT_INO;
28577+#if 0 /* reserved for future use */
28578+ xinoe.h_gen = h_inode->i_generation;
28579+ WARN_ON(xinoe.h_gen == AuXino_INVALID_HGEN);
28580+#endif
28581+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
28582+ h_ino, &xinoe);
28583+ if (!err)
28584+ return 0; /* success */
28585+
28586+
28587+ out:
28588+ AuTraceErr(err);
28589+ return err;
28590+}
28591+
28592+/* too slow */
28593+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
28594+{
28595+ int err, bit;
28596+ struct au_sbinfo *sbinfo;
28597+ au_readf_t func;
28598+ loff_t pos, pend;
28599+ ssize_t sz;
28600+ struct au_xino_entry *xinoe;
28601+ unsigned long pindex;
28602+
28603+ AuTraceEnter();
28604+ SiMustWriteLock(sb);
28605+
28606+ err = 0;
28607+ sbinfo = au_sbi(sb);
28608+ func = sbinfo->si_xread;
28609+ pend = i_size_read(file->f_dentry->d_inode);
28610+#ifdef CONFIG_AUFS_DEBUG
28611+ if (unlikely(pend > (1 << 22)))
28612+ AuWarn("testing a large xino file %lld\n", (long long)pend);
28613+#endif
28614+ pos = 0;
28615+ while (pos < pend) {
28616+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
28617+ err = sz;
28618+ if (unlikely(sz <= 0))
28619+ goto out;
28620+
28621+ err = 0;
28622+ for (xinoe = page; sz > 0; xinoe++, sz -= sizeof(xinoe)) {
28623+ if (unlikely(xinoe->ino < AUFS_FIRST_INO))
28624+ continue;
28625+
28626+ xib_calc_bit(xinoe->ino, &pindex, &bit);
28627+ AuDebugOn(page_bits <= bit);
28628+ err = xib_pindex(sb, pindex);
28629+ if (!err)
28630+ set_bit(bit, sbinfo->si_xib_buf);
28631+ else
28632+ goto out;
28633+ }
28634+ }
28635+
28636+ out:
28637+ AuTraceErr(err);
28638+ return err;
28639+}
28640+
28641+static int xib_restore(struct super_block *sb)
28642+{
28643+ int err;
28644+ aufs_bindex_t bindex, bend;
28645+ void *page;
28646+
28647+ AuTraceEnter();
28648+
28649+ err = -ENOMEM;
28650+ page = (void *)__get_free_page(GFP_NOFS);
28651+ if (unlikely(!page))
28652+ goto out;
28653+
28654+ err = 0;
28655+ bend = au_sbend(sb);
28656+ for (bindex = 0; !err && bindex <= bend; bindex++)
28657+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
28658+ err = do_xib_restore
28659+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
28660+ else
28661+ LKTRTrace("b%d\n", bindex);
28662+ free_page((unsigned long)page);
28663+
28664+ out:
28665+ AuTraceErr(err);
28666+ return err;
28667+}
28668+
28669+int au_xib_trunc(struct super_block *sb)
28670+{
28671+ int err;
28672+ unsigned int mnt_flags;
28673+ ssize_t sz;
28674+ loff_t pos;
28675+ struct au_sbinfo *sbinfo;
28676+ unsigned long *p;
28677+ struct dentry *parent;
28678+ struct inode *dir;
28679+ struct file *file;
28680+
28681+ AuTraceEnter();
28682+ SiMustWriteLock(sb);
28683+
28684+ err = 0;
28685+ mnt_flags = au_mntflags(sb);
28686+ if (!au_opt_test_xino(mnt_flags))
28687+ goto out;
28688+
28689+ sbinfo = au_sbi(sb);
28690+ if (i_size_read(sbinfo->si_xib->f_dentry->d_inode) <= PAGE_SIZE)
28691+ goto out;
28692+ parent = dget_parent(sbinfo->si_xib->f_dentry);
28693+ dir = parent->d_inode;
28694+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
28695+ /* mnt_want_write() is unnecessary here */
28696+ file = au_xino_create2(sb, sbinfo->si_xib, NULL);
28697+ mutex_unlock(&dir->i_mutex);
28698+ dput(parent);
28699+ err = PTR_ERR(file);
28700+ if (IS_ERR(file))
28701+ goto out;
28702+ fput(sbinfo->si_xib);
28703+ sbinfo->si_xib = file;
28704+
28705+ p = sbinfo->si_xib_buf;
28706+ memset(p, 0, PAGE_SIZE);
28707+ pos = 0;
28708+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
28709+ if (unlikely(sz != PAGE_SIZE)) {
28710+ err = sz;
28711+ AuIOErr("err %d\n", err);
28712+ if (sz >= 0)
28713+ err = -EIO;
28714+ goto out;
28715+ }
28716+
28717+ if (au_opt_test_xino(mnt_flags)) {
28718+ mutex_lock(&sbinfo->si_xib_mtx);
28719+ /* mnt_want_write() is unnecessary here */
28720+ err = xib_restore(sb);
28721+ mutex_unlock(&sbinfo->si_xib_mtx);
28722+#if 0 /* reserved for future use */
28723+ } else {
28724+ /* is it really safe? */
28725+ /* dont trust BKL */
28726+ AuDebugOn(!kernel_locked());
28727+ ino = AUFS_FIRST_INO;
28728+ list_for_each_entry(inode, &sb->s_inodes, i_sb_list)
28729+ if (ino < inode->i_ino)
28730+ ino = inode->i_ino;
28731+
28732+ /* make iunique to return larger than active max inode number */
28733+ iunique(sb, ino);
28734+ err = 0;
28735+#endif
28736+ }
28737+
28738+out:
28739+ AuTraceErr(err);
28740+ return err;
28741+}
28742+
28743+/* ---------------------------------------------------------------------- */
28744+
28745+/*
28746+ * xino mount option handlers
28747+ */
28748+static au_readf_t find_readf(struct file *h_file)
28749+{
28750+ const struct file_operations *fop = h_file->f_op;
28751+
28752+ if (fop) {
28753+ if (fop->read)
28754+ return fop->read;
28755+ if (fop->aio_read)
28756+ return do_sync_read;
28757+ }
28758+ return ERR_PTR(-ENOSYS);
28759+}
28760+
28761+static au_writef_t find_writef(struct file *h_file)
28762+{
28763+ const struct file_operations *fop = h_file->f_op;
28764+
28765+ if (fop) {
28766+ if (fop->write)
28767+ return fop->write;
28768+ if (fop->aio_write)
28769+ return do_sync_write;
28770+ }
28771+ return ERR_PTR(-ENOSYS);
28772+}
28773+
28774+/* xino bitmap */
28775+static void xino_clear_xib(struct super_block *sb)
28776+{
28777+ struct au_sbinfo *sbinfo;
28778+
28779+ AuTraceEnter();
28780+ SiMustWriteLock(sb);
28781+
28782+ sbinfo = au_sbi(sb);
28783+ sbinfo->si_xread = NULL;
28784+ sbinfo->si_xwrite = NULL;
28785+ if (sbinfo->si_xib)
28786+ fput(sbinfo->si_xib);
28787+ sbinfo->si_xib = NULL;
28788+ free_page((unsigned long)sbinfo->si_xib_buf);
28789+ sbinfo->si_xib_buf = NULL;
28790+}
28791+
28792+static int au_xino_set_xib(struct super_block *sb, struct file *base)
28793+{
28794+ int err;
28795+ struct au_sbinfo *sbinfo;
28796+ struct file *file;
28797+ loff_t pos;
28798+
28799+ LKTRTrace("%.*s\n", AuDLNPair(base->f_dentry));
28800+ SiMustWriteLock(sb);
28801+
28802+ sbinfo = au_sbi(sb);
28803+ file = au_xino_create2(sb, base, sbinfo->si_xib);
28804+ err = PTR_ERR(file);
28805+ if (IS_ERR(file))
28806+ goto out;
28807+ if (sbinfo->si_xib)
28808+ fput(sbinfo->si_xib);
28809+ sbinfo->si_xib = file;
28810+ sbinfo->si_xread = find_readf(file);
28811+ AuDebugOn(IS_ERR(sbinfo->si_xread));
28812+ sbinfo->si_xwrite = find_writef(file);
28813+ AuDebugOn(IS_ERR(sbinfo->si_xwrite));
28814+
28815+ err = -ENOMEM;
28816+ if (!sbinfo->si_xib_buf)
28817+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
28818+ if (unlikely(!sbinfo->si_xib_buf))
28819+ goto out_unset;
28820+
28821+ sbinfo->si_xib_last_pindex = 0;
28822+ sbinfo->si_xib_next_bit = 0;
28823+
28824+ /* no need to lock for i_size_read() */
28825+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
28826+ pos = 0;
28827+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
28828+ PAGE_SIZE, &pos);
28829+ if (unlikely(err != PAGE_SIZE))
28830+ goto out_free;
28831+ }
28832+ err = 0;
28833+ goto out; /* success */
28834+
28835+ out_free:
28836+ free_page((unsigned long)sbinfo->si_xib_buf);
28837+ sbinfo->si_xib_buf = NULL;
28838+ if (err >= 0)
28839+ err = -EIO;
28840+ out_unset:
28841+ fput(sbinfo->si_xib);
28842+ sbinfo->si_xib = NULL;
28843+ sbinfo->si_xread = NULL;
28844+ sbinfo->si_xwrite = NULL;
28845+ out:
28846+ AuTraceErr(err);
28847+ return err;
28848+}
28849+
28850+/* xino for each branch */
28851+static void xino_clear_br(struct super_block *sb)
28852+{
28853+ aufs_bindex_t bindex, bend;
28854+ struct au_branch *br;
28855+
28856+ AuTraceEnter();
28857+ SiMustWriteLock(sb);
28858+
28859+ bend = au_sbend(sb);
28860+ for (bindex = 0; bindex <= bend; bindex++) {
28861+ br = au_sbr(sb, bindex);
28862+ if (!br || !br->br_xino.xi_file)
28863+ continue;
28864+
28865+ fput(br->br_xino.xi_file);
28866+ br->br_xino.xi_file = NULL;
28867+ }
28868+}
28869+
28870+static int au_xino_set_br(struct super_block *sb, struct file *base)
28871+{
28872+ int err;
28873+ aufs_bindex_t bindex, bend, bshared;
28874+ struct {
28875+ struct file *old, *new;
28876+ } *fpair, *p;
28877+ struct au_branch *br;
28878+ struct au_xino_entry xinoe;
28879+ struct inode *inode;
28880+ au_writef_t writef;
28881+
28882+ LKTRTrace("%.*s\n", AuDLNPair(base->f_dentry));
28883+ SiMustWriteLock(sb);
28884+
28885+ err = -ENOMEM;
28886+ bend = au_sbend(sb);
28887+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
28888+ if (unlikely(!fpair))
28889+ goto out;
28890+
28891+ inode = sb->s_root->d_inode;
28892+ xinoe.ino = AUFS_ROOT_INO;
28893+ writef = au_sbi(sb)->si_xwrite;
28894+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
28895+ br = au_sbr(sb, bindex);
28896+ bshared = is_sb_shared(sb, bindex, bindex - 1);
28897+ if (bshared >= 0) {
28898+ /* shared xino */
28899+ *p = fpair[bshared];
28900+ get_file(p->new);
28901+ }
28902+
28903+ if (!p->new) {
28904+ /* new xino */
28905+ p->old = br->br_xino.xi_file;
28906+ p->new = au_xino_create2(sb, base, br->br_xino.xi_file);
28907+ err = PTR_ERR(p->new);
28908+ if (IS_ERR(p->new)) {
28909+ p->new = NULL;
28910+ goto out_pair;
28911+ }
28912+ }
28913+
28914+ err = au_xino_do_write(writef, p->new,
28915+ au_h_iptr(inode, bindex)->i_ino, &xinoe);
28916+ if (unlikely(err))
28917+ goto out_pair;
28918+ }
28919+
28920+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
28921+ br = au_sbr(sb, bindex);
28922+ AuDebugOn(p->old != br->br_xino.xi_file);
28923+ if (br->br_xino.xi_file)
28924+ fput(br->br_xino.xi_file);
28925+ get_file(p->new);
28926+ br->br_xino.xi_file = p->new;
28927+ }
28928+
28929+ out_pair:
28930+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
28931+ if (p->new)
28932+ fput(p->new);
28933+ else
28934+ break;
28935+ kfree(fpair);
28936+ out:
28937+ AuTraceErr(err);
28938+ return err;
28939+}
28940+
28941+void au_xino_clr(struct super_block *sb)
28942+{
28943+ struct au_sbinfo *sbinfo;
28944+
28945+ AuTraceEnter();
28946+ SiMustWriteLock(sb);
28947+
28948+ au_xigen_clr(sb);
28949+ xino_clear_xib(sb);
28950+ xino_clear_br(sb);
28951+ sbinfo = au_sbi(sb);
28952+ /* lvalue, do not call au_mntflags() */
28953+ au_opt_clr(sbinfo->si_mntflags, XINO);
28954+ au_xino_def_br_set(NULL, sbinfo);
28955+}
28956+
28957+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
28958+{
28959+ int err, skip;
28960+ struct dentry *parent, *cur_parent;
28961+ struct qstr *dname, *cur_name;
28962+ struct file *cur_xino;
28963+ struct inode *dir;
28964+ struct au_sbinfo *sbinfo;
28965+
28966+ LKTRTrace("remount %d\n", remount);
28967+ SiMustWriteLock(sb);
28968+
28969+ err = 0;
28970+ sbinfo = au_sbi(sb);
28971+ parent = dget_parent(xino->file->f_dentry);
28972+ if (remount) {
28973+ skip = 0;
28974+ dname = &xino->file->f_dentry->d_name;
28975+ cur_xino = sbinfo->si_xib;
28976+ if (cur_xino) {
28977+ cur_parent = dget_parent(cur_xino->f_dentry);
28978+ cur_name = &cur_xino->f_dentry->d_name;
28979+ skip = (cur_parent == parent
28980+ && dname->len == cur_name->len
28981+ && !memcmp(dname->name, cur_name->name,
28982+ dname->len));
28983+ dput(cur_parent);
28984+ }
28985+ if (skip)
28986+ goto out;
28987+ }
28988+
28989+ au_opt_set(sbinfo->si_mntflags, XINO);
28990+ au_xino_def_br_set(NULL, sbinfo);
28991+ dir = parent->d_inode;
28992+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
28993+ /* mnt_want_write() is unnecessary here */
28994+ err = au_xino_set_xib(sb, xino->file);
28995+ if (!err)
28996+ err = au_xigen_set(sb, xino->file);
28997+ if (!err)
28998+ err = au_xino_set_br(sb, xino->file);
28999+ mutex_unlock(&dir->i_mutex);
29000+ if (!err)
29001+ goto out; /* success */
29002+
29003+ /* reset all */
29004+ AuIOErr("failed creating xino(%d).\n", err);
29005+
29006+ out:
29007+ dput(parent);
29008+ AuTraceErr(err);
29009+ return err;
29010+}
29011+
29012+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
29013+{
29014+ int err;
29015+ struct au_branch *br;
29016+ struct file *new_xino;
29017+ struct super_block *h_sb;
29018+ aufs_bindex_t bi, bend;
29019+ struct dentry *parent;
29020+ struct inode *dir;
29021+
29022+ LKTRTrace("b%d\n", bindex);
29023+ SiMustWriteLock(sb);
29024+
29025+ err = -EINVAL;
29026+ bend = au_sbend(sb);
29027+ if (unlikely(bindex < 0 || bend < bindex))
29028+ goto out;
29029+ br = au_sbr(sb, bindex);
29030+ if (!br->br_xino.xi_file)
29031+ goto out;
29032+
29033+ parent = dget_parent(br->br_xino.xi_file->f_dentry);
29034+ dir = parent->d_inode;
29035+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
29036+ /* mnt_want_write() is unnecessary here */
29037+ new_xino = au_xino_create2(sb, br->br_xino.xi_file,
29038+ br->br_xino.xi_file);
29039+ mutex_unlock(&dir->i_mutex);
29040+ dput(parent);
29041+ err = PTR_ERR(new_xino);
29042+ if (IS_ERR(new_xino))
29043+ goto out;
29044+ err = 0;
29045+ fput(br->br_xino.xi_file);
29046+ br->br_xino.xi_file = new_xino;
29047+
29048+ h_sb = br->br_mnt->mnt_sb;
29049+ for (bi = 0; bi <= bend; bi++) {
29050+ if (unlikely(bi == bindex))
29051+ continue;
29052+ br = au_sbr(sb, bi);
29053+ if (br->br_mnt->mnt_sb != h_sb)
29054+ continue;
29055+
29056+ fput(br->br_xino.xi_file);
29057+ br->br_xino.xi_file = new_xino;
29058+ get_file(new_xino);
29059+ }
29060+
29061+ out:
29062+ AuTraceErr(err);
29063+ return err;
29064+}
29065+
29066+/* ---------------------------------------------------------------------- */
29067+
29068+/*
29069+ * create a xinofile at the default place/path.
29070+ */
29071+struct file *au_xino_def(struct super_block *sb)
29072+{
29073+ struct file *file;
29074+ aufs_bindex_t bend, bindex, bwr;
29075+ char *page, *p;
29076+ struct path path;
29077+ struct au_branch *br;
29078+
29079+ AuTraceEnter();
29080+
29081+ bend = au_sbend(sb);
29082+ bwr = -1;
29083+ for (bindex = 0; bindex <= bend; bindex++) {
29084+ br = au_sbr(sb, bindex);
29085+ if (au_br_writable(br->br_perm)
29086+ && !au_test_nfs(br->br_mnt->mnt_sb)
29087+ && !au_test_ecryptfs(br->br_mnt->mnt_sb)) {
29088+ bwr = bindex;
29089+ break;
29090+ }
29091+ }
29092+
29093+ if (bwr >= 0) {
29094+ file = ERR_PTR(-ENOMEM);
29095+ page = __getname();
29096+ if (unlikely(!page))
29097+ goto out;
29098+ path.mnt = au_sbr_mnt(sb, bwr);
29099+ path.dentry = au_h_dptr(sb->s_root, bwr);
29100+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
29101+ file = (void *)p;
29102+ if (!IS_ERR(p)) {
29103+ strcat(p, "/" AUFS_XINO_FNAME);
29104+ LKTRTrace("%s\n", p);
29105+ file = au_xino_create(sb, p, /*silent*/0);
29106+ if (!IS_ERR(file))
29107+ au_xino_def_br_set(au_sbr(sb, bwr), au_sbi(sb));
29108+ }
29109+ __putname(page);
29110+ } else {
29111+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
29112+ if (unlikely(au_test_nfs(file->f_dentry->d_sb)
29113+ || au_test_ecryptfs(file->f_dentry->d_sb))) {
29114+ AuErr("xino or noxino option is required "
29115+ "since %s is NFS\n", AUFS_XINO_DEFPATH);
29116+ fput(file);
29117+ file = ERR_PTR(-EINVAL);
29118+ }
29119+ if (!IS_ERR(file))
29120+ au_xino_def_br_set(NULL, au_sbi(sb));
29121+ }
29122+
29123+ out:
29124+ AuTraceErrPtr(file);
29125+ return file;
29126+}
29127diff -urN linux/fs/Kconfig linux-aufs/fs/Kconfig
29128--- linux/fs/Kconfig 2009-01-05 11:42:15.000000000 +0100
29129+++ linux-aufs/fs/Kconfig 2009-03-12 17:02:25.753047602 +0100
29130@@ -1022,6 +1022,350 @@
29131 help
29132 If you say Y here, you can turn on debugging output from Unionfs.
29133
29134+config AUFS
29135+ tristate "Another unionfs"
29136+ help
29137+ Aufs is a stackable unification filesystem such as Unionfs,
29138+ which unifies several directories and provides a merged single
29139+ directory.
29140+ In the early days, aufs was entirely re-designed and
29141+ re-implemented Unionfs Version 1.x series. After many original
29142+ ideas, approaches and improvements, it becomes totally
29143+ different from Unionfs while keeping the basic features.
29144+ See Unionfs for the basic features.
29145+
29146+if AUFS
29147+comment "These options are for "#UTS_RELEASE
29148+
29149+choice
29150+ prompt "Maximum number of branches"
29151+ default AUFS_BRANCH_MAX_127
29152+ help
29153+ Specifies the maximum number of branches (or member directories) in a
29154+ single aufs. The larger value consumes more system resources and has
29155+ an impact to performance.
29156+config AUFS_BRANCH_MAX_127
29157+ bool "127"
29158+ help
29159+ Specifies the maximum number of branches (or member directories) in a
29160+ single aufs. The larger value consumes more system resources and has
29161+ an impact to performance.
29162+config AUFS_BRANCH_MAX_511
29163+ bool "511"
29164+ help
29165+ Specifies the maximum number of branches (or member directories) in a
29166+ single aufs. The larger value consumes more system resources and has
29167+ an impact to performance.
29168+config AUFS_BRANCH_MAX_1023
29169+ bool "1023"
29170+ help
29171+ Specifies the maximum number of branches (or member directories) in a
29172+ single aufs. The larger value consumes more system resources and has
29173+ an impact to performance.
29174+# 128kb is available for kmalloc?
29175+config AUFS_BRANCH_MAX_32767
29176+ bool "32767"
29177+ help
29178+ Specifies the maximum number of branches (or member directories) in a
29179+ single aufs. The larger value consumes more system resources and has
29180+ an impact to performance.
29181+endchoice
29182+
29183+config AUFS_STAT
29184+ bool "Use <sysfs>/fs/aufs/stat"
29185+ depends on SYSFS
29186+ help
29187+ Shows some statistic data via <sysfs>/fs/aufs/stat.
29188+ See detail in aufs.5.
29189+
29190+comment "SYSFS and AUFS_STAT are disabled"
29191+ depends on SYSFS = n
29192+
29193+config AUFS_HINOTIFY
29194+ bool "Use inotify to detect actions on a branch"
29195+ depends on INOTIFY
29196+ help
29197+ If you want to modify files on branches directly, eg. bypassing aufs,
29198+ and want aufs to detect the changes of them fully, then enable this
29199+ option and use 'udba=inotify' mount option.
29200+ It will have a negative impact to the performance.
29201+ See detail in aufs.5.
29202+
29203+comment "INOTIFY and AUFS_HINOTIFY are disabled"
29204+ depends on INOTIFY = n
29205+
29206+config AUFS_EXPORT
29207+ bool "NFS-exportable aufs"
29208+ depends on (AUFS = y && EXPORTFS = y) || (AUFS = m && EXPORTFS)
29209+ help
29210+ If you want to export your mounted aufs, then enable this
29211+ option. There are several requirements for this configuration.
29212+ See detail in aufs.5.
29213+
29214+comment "EXPORTFS and AUFS_EXPORT are disabled"
29215+ depends on EXPORTFS = n
29216+
29217+comment "AUFS_EXPORT is disabled since EXPORTFS is a module but AUFS"
29218+ depends on EXPORTFS = m && AUFS = y
29219+
29220+# automatic configuration for internal use
29221+config AUFS_INO_T_64
29222+ bool # never appear on the menu
29223+ # typedef unsigned long/int __kernel_ino_t
29224+ # alpha and s390x are int
29225+ depends on 64BIT && !(ALPHA || S390)
29226+ default y
29227+
29228+config AUFS_ROBR
29229+ bool "Aufs as an readonly branch of another aufs mount"
29230+ help
29231+ If you want make your aufs to be a part of another aufs, then
29232+ enable this option. In other words, you can specify your aufs
29233+ path in 'br:' mount option for another aufs, but cannot
29234+ specify 'rw' as the branch permission.
29235+ It will have a negative impact to the performance.
29236+ See detail in aufs.5.
29237+
29238+config AUFS_DLGT
29239+ bool "Delegate the internal branch access the kernel thread"
29240+ help
29241+ If you want aufs to delegate
29242+ the internal access to the branches which is made by aufs, to
29243+ the kernel thread, in order to hide the access issued by your
29244+ application from your LSM or something or make your
29245+ application to be traced strictly by the task I/O accounting,
29246+ then enable this option and use 'dlgt' mount option.
29247+ It will have a negative impact to the performance.
29248+ See detail in aufs.5.
29249+
29250+# automatic configuration for internal use
29251+config AUFS_HIN_OR_DLGT
29252+ bool # never appear on the menu
29253+ depends on AUFS_HINOTIFY || AUFS_DLGT
29254+ default y
29255+ help
29256+ Automatic configuration for internal use.
29257+
29258+config AUFS_SHWH
29259+ bool "Show whiteouts"
29260+ help
29261+ If you want to make the whiteouts in aufs visible, then enable
29262+ this option and specify 'shwh' mount option. Although it may
29263+ sounds like philosophy or something, but in technically it
29264+ simply shows the name of whiteout with keeping its behaviour.
29265+
29266+# this is not in mainstream kernel
29267+config AUFS_RR_SQUASHFS
29268+ bool "Make squashfs branch RR (real readonly) by default"
29269+ default y
29270+ help
29271+ If you use squashfs or LZMA patched squashfs as an aufs branch
29272+ and want to set '=rr' to it by default, then enable this
29273+ configuration.
29274+ 'rr' stands for real readonly and it optimizes some aspects of
29275+ 'ro.'
29276+ See detail in aufs.5.
29277+
29278+config AUFS_SEC_PERM_PATCH
29279+ bool "sec_perm-2.6.24.patch was applied or not"
29280+ depends on AUFS = m
29281+ depends on SECURITY
29282+ help
29283+ If you build aufs as a module and enabled CONFIG_SECURITY,
29284+ then you need to apply the patch
29285+ 'CVS_TREE/aufs/patch/sec_perm-2.6.24.patch' to your kernel
29286+ source, and enable this configuration.
29287+ The sec_perm-2.6.24.patch exports a kernel function
29288+ security_inode_permission() to modules.
29289+
29290+comment "SECURITY and AUFS_SEC_PERM_PATCH are disabled"
29291+ depends on SECURITY = n
29292+
29293+config AUFS_SPLICE_PATCH
29294+ bool "splice.patch for sendfile(2) and splice(2)"
29295+ help
29296+ If you use 'loopback mount' on a fs-image file, or use
29297+ splice(2) or sendfile(2) systemcall in aufs, then you need to
29298+ apply the patch 'CVS_TREE/aufs/patch/splice.patch' to your
29299+ kernel source, and enable this configuration.
29300+ The splice.patch makes the kernel function do_splice_to/from()
29301+ global and exports them to modules.
29302+
29303+config AUFS_LHASH_PATCH
29304+ bool "lhash.patch for NFS branch"
29305+ depends on NFS_FS
29306+ help
29307+ If you use mounted NFS as an aufs branch filesystem, then you
29308+ need to apply the patch 'CVS_TREE/aufs/patch/lhash.patch' (or
29309+ lhash-2.6.22.patch for linux-2.6.22 and later) to your kernel
29310+ source, and enable this configuration.
29311+ The patch file makes the kernel function __lookup_hash() global
29312+ and exports it to modules.
29313+
29314+comment "NFS_FS and AUFS_LHASH_PATCH are disabled"
29315+ depends on NFS_FS = n
29316+
29317+config AUFS_PUT_FILP_PATCH
29318+ bool "put_filp.patch for 'atomic open'"
29319+ depends on AUFS = m && NFS_V4
29320+ help
29321+ If you build aufs as a module and use a filesystem which
29322+ operates 'atomic open' (for instance NFSv4) as an aufs branch
29323+ filesystem, then you need to apply the patch
29324+ 'CVS_TREE/aufs/patch/put_filp.patch' to your kernel source,
29325+ and enable this configuration.
29326+ The put_filp.patch exports a kernel function put_filp() to
29327+ modules.
29328+
29329+comment "NFS_V4 and AUFS_PUT_FILP_PATCH are disabled"
29330+ depends on NFS_V4 = n
29331+
29332+# automatic configuration for internal use
29333+config AUFS_BR_NFS
29334+ bool # never appear on the menu
29335+ depends on NFS_FS
29336+ depends on AUFS_LHASH_PATCH
29337+ default y
29338+ help
29339+ Automatic configuration for internal use.
29340+ When aufs supports NFS branch, enabled automatically.
29341+
29342+config AUFS_BR_NFS_V4
29343+ bool # never appear on the menu
29344+ depends on NFS_V4 && AUFS_BR_NFS
29345+ depends on AUFS = y || (AUFS = m && AUFS_PUT_FILP_PATCH)
29346+ default y
29347+ help
29348+ Automatic configuration for internal use.
29349+ When aufs supports a branch filesystem which operates
29350+ 'atomic_open', for instance NFSv4, this configuration is enabled
29351+ automatically.
29352+
29353+config AUFS_BR_XFS
29354+ bool # never appear on the menu
29355+ depends on XFS_FS
29356+ default y
29357+ help
29358+ Automatic configuration for internal use.
29359+ When aufs supports XFS branch, enabled automatically.
29360+
29361+config AUFS_FSYNC_SUPER_PATCH
29362+ bool "fsync_super-2.6.xx.patch was applied or not"
29363+ depends on AUFS = m
29364+ help
29365+ If you build aufs as a module and want to flush everything for
29366+ branch filesystems which are not marked as 'rr' nor 'rr+wh' at
29367+ umount or remount time, then you need to apply the patch
29368+ 'CVS_TREE/aufs/patch/fsync_super-2.6.16.patch' or
29369+ '...-2.6.19.patch' to your kernel source, and enable this
29370+ configuration.
29371+ It may be helpful at shutdown time in case of your aufs is a
29372+ root filesystem. But this behaviour will not guarantee the
29373+ consistency of branch filesystems. To guarantee it, try the
29374+ approach described in the aufs manual, and do not forget
29375+ installing auplink script.
29376+ The fsync_super-2.6.xx.patch does nothing but exports a kernel
29377+ function fsync_super() to modules.
29378+
29379+config AUFS_DENY_WRITE_ACCESS_PATCH
29380+ bool "deny_write_access.patch was applied or not"
29381+ depends on AUFS = m
29382+ help
29383+ A security enhancement to deny writing to a running executable
29384+ which exists on an aufs branch filesystem and executed through
29385+ aufs. If you applied
29386+ 'CVS_TREE/aufs/patch/deny_write_access.patch' to your kernel
29387+ and you are compiling aufs as a module, then enable this
29388+ option.
29389+ The write_deny_access.patch does nothing but export the
29390+ function.
29391+
29392+config AUFS_WORKAROUND_FUSE
29393+ bool "Special handling for FUSE-based filesystem"
29394+ depends on FUSE_FS
29395+ help
29396+ A FUSE-based filesystem may not initialize its inode
29397+ attributes and the FUSE developer thinks the inode attributes
29398+ in a positive dentry which is returned by VFS lookup operation
29399+ are not reliable.
29400+ If you use a FUSE-based filesystem as an aufs branch, and it
29401+ customizes the inode attribute on it without overriding
29402+ fuse_lowlevel_ops.lookup, probably you need to enable this
29403+ configuration.
29404+ If you enable this configuration, aufs calls getattr operation
29405+ in every lookup and revalidate operation for the FUSE-based
29406+ filesystem branch.
29407+ It will have a negative impact to the performance even if you do
29408+ not use a FUSE-based filesystem branch.
29409+
29410+# automatic configuration for internal use
29411+config AUFS_GETATTR
29412+ bool # never appear on the menu
29413+ depends on AUFS_HINOTIFY || AUFS_WORKAROUND_FUSE || AUFS_BR_NFS
29414+ default y
29415+ help
29416+ Automatic configuration for internal use.
29417+
29418+config AUFS_DEBUG
29419+ bool "Debug aufs"
29420+ default y
29421+ help
29422+ Enable this to compile aufs internal debug code.
29423+ It will have a negative impact to the performance.
29424+
29425+# automatic configuration for internal use
29426+config AUFS_MAGIC_SYSRQ
29427+ bool # never appear on the menu
29428+ depends on AUFS_DEBUG && MAGIC_SYSRQ
29429+ default y
29430+ help
29431+ Automatic configuration for internal use.
29432+ When aufs supports Magic SysRq, enabled automatically.
29433+
29434+config AUFS_DEBUG_LOCK
29435+ bool "Show lock status in Magic SysRq"
29436+ depends on AUFS_MAGIC_SYSRQ
29437+ help
29438+ For developers only. Sometimes it is useful when a deadlock
29439+ occurs in aufs. Trace every aufs lock acquire and release, and
29440+ print them when Magic SysRq-<AUFS> key is pressed.
29441+ It will have a huge negative impact to the performance.
29442+
29443+config AUFS_COMPAT
29444+ bool "Compatibility with Unionfs (obsolete)"
29445+ help
29446+ This makes aufs compatible with unionfs-style mount options and some
29447+ behaviours.
29448+ The dirs= mount option and =nfsro branch permission flag are always
29449+ interpreted as br: mount option and =ro flag respectively. The
29450+ 'debug', 'delete' and 'imap' mount options are ignored.
29451+ If you disable this option, you will get,
29452+ - aufs issues a warning about the ignored mount options
29453+ - the default branch permission flag is set. RW for the first branch,
29454+ and RO for the rests.
29455+ - the name of a internal file which represents the directory is
29456+ 'opaque', becomes '.wh..wh..opq'
29457+ - the 'diropq=w' mount option is set by default
29458+
29459+config AUFS_UNIONFS22_PATCH
29460+ bool "Unionfs-2.2 or later patch is applied or not (obsolete)"
29461+ help
29462+ Unionfs version 2.2 (and later) patch introduces some changes in VFS
29463+ layer which has an impact to aufs. If you have applied such
29464+ patch to your kernel, you need to enable this configuration even
29465+ if you disabled CONFIG_UNIONFS.
29466+
29467+config AUFS_UNIONFS23_PATCH
29468+ bool "Unionfs-2.3 or later patch is applied or not (obsolete)"
29469+ select AUFS_SPLICE_PATCH
29470+ select AUFS_UNIONFS22_PATCH
29471+ help
29472+ Unionfs version 2.3 (and later) patch introduces some changes in VFS
29473+ layer which has an impact to aufs. If you have applied such
29474+ patch to your kernel, you need to enable this configuration even
29475+ if you disabled CONFIG_UNIONFS.
29476+endif
29477+
29478 endmenu
29479
29480 menu "Miscellaneous filesystems"
29481diff -urN linux/fs/Makefile linux-aufs/fs/Makefile
29482--- linux/fs/Makefile 2009-03-12 11:25:26.000000000 +0100
29483+++ linux-aufs/fs/Makefile 2009-03-12 17:03:22.897115295 +0100
1e07564d 29484@@ -125,3 +125,4 @@
29485 obj-$(CONFIG_BTRFS_FS) += btrfs/
29486 obj-$(CONFIG_GFS2_FS) += gfs2/
29487 obj-$(CONFIG_EXOFS_FS) += exofs/
024a5822 29488+obj-$(CONFIG_AUFS) += aufs/
024a5822
JR
29489diff -urN linux/include/linux/aufs_type.h linux-aufs/include/linux/aufs_type.h
29490--- linux/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
29491+++ linux-aufs/include/linux/aufs_type.h 2009-03-12 16:18:04.000000000 +0100
29492@@ -0,0 +1,127 @@
29493+/*
29494+ * Copyright (C) 2005-2009 Junjiro Okajima
29495+ *
29496+ * This program, aufs is free software; you can redistribute it and/or modify
29497+ * it under the terms of the GNU General Public License as published by
29498+ * the Free Software Foundation; either version 2 of the License, or
29499+ * (at your option) any later version.
29500+ *
29501+ * This program is distributed in the hope that it will be useful,
29502+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29503+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29504+ * GNU General Public License for more details.
29505+ *
29506+ * You should have received a copy of the GNU General Public License
29507+ * along with this program; if not, write to the Free Software
29508+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29509+ */
29510+
29511+/* $Id$ */
29512+
29513+#include <linux/ioctl.h>
29514+
29515+#ifndef __AUFS_TYPE_H__
29516+#define __AUFS_TYPE_H__
29517+
29518+#define AUFS_VERSION "20090126"
29519+
29520+/* move this to linux-2.6.19/include/magic.h */
29521+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
29522+
29523+/* ---------------------------------------------------------------------- */
29524+
29525+#ifdef CONFIG_AUFS_BRANCH_MAX_127
29526+/* some environments treat 'char' as 'unsigned char' by default */
29527+typedef signed char aufs_bindex_t;
29528+#define AUFS_BRANCH_MAX 127
29529+#else
29530+typedef short aufs_bindex_t;
29531+#ifdef CONFIG_AUFS_BRANCH_MAX_511
29532+#define AUFS_BRANCH_MAX 511
29533+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
29534+#define AUFS_BRANCH_MAX 1023
29535+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
29536+#define AUFS_BRANCH_MAX 32767
29537+#else
29538+#error unknown CONFIG_AUFS_BRANCH_MAX value
29539+#endif
29540+#endif
29541+
29542+#define AUFS_NAME "aufs"
29543+#define AUFS_FSTYPE AUFS_NAME
29544+
29545+#define AUFS_ROOT_INO 2
29546+#define AUFS_FIRST_INO 11
29547+
29548+#define AUFS_WH_PFX ".wh."
29549+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
29550+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
29551+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
29552+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
29553+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
29554+#define AUFS_DIRWH_DEF 3
29555+#define AUFS_RDCACHE_DEF 10 /* seconds */
29556+#define AUFS_WKQ_NAME AUFS_NAME "d"
29557+#define AUFS_NWKQ_DEF 4
29558+#define AUFS_MFS_SECOND_DEF 30 /* seconds */
29559+#define AUFS_PLINK_WARN 100 /* number of plinks */
29560+
29561+#ifdef CONFIG_AUFS_COMPAT
29562+#define AUFS_DIROPQ_NAME "__dir_opaque"
29563+#else
29564+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
29565+#endif
29566+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
29567+
29568+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
29569+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
29570+#define AUFS_TMPDIR_NAME AUFS_WH_PFX ".tmp"
29571+
29572+/* doubly whiteouted */
29573+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
29574+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
29575+#define AUFS_WH_TMPDIR AUFS_WH_PFX AUFS_TMPDIR_NAME
29576+
29577+/* ---------------------------------------------------------------------- */
29578+
29579+/* ioctl */
29580+#if 0 /* reserved for future use */
29581+enum {
29582+ AuCtlErr,
29583+ AuCtlErr_Last
29584+};
29585+enum {
29586+ AuCtl_DIROPQ_GET, AuCtl_DIROPQ_SET,
29587+ AuCtl_MOVE,
29588+ AuCtl_MVDOWN,
29589+
29590+ /* unimplmented */
29591+ AuCtl_REFRESH, AuCtl_REFRESHV,
29592+ AuCtl_FLUSH_PLINK,
29593+ AuCtl_CPUP,
29594+ AuCtl_CPDOWN
29595+};
29596+
29597+struct aufs_ctl {
29598+ int err;
29599+ aufs_bindex_t bsrc, bdst;
29600+ char *path;
29601+};
29602+
29603+#define AuCtlType 'A'
29604+#define AUFS_CTL_DIROPQ_GET _IO(AuCtlType, AuCtl_DIROPQ_GET)
29605+#define AUFS_CTL_DIROPQ_SET _IOW(AuCtlType, AuCtl_DIROPQ_SET, aufs_bindex_t)
29606+#define AUFS_CTL_MOVE \
29607+ _IOW(AuCtlType, AuCtl_MVDOWN, aufs_bindex_t)
29608+#define AUFS_CTL_MVDOWN \
29609+ _IOWR(AuCtlType, AuCtl_MVDOWN, struct aufs_ctl)
29610+
29611+#define AUFS_CTL_REFRESH _IO(AuCtlType, AuCtl_REFRESH)
29612+#define AUFS_CTL_REFRESHV _IO(AuCtlType, AuCtl_REFRESHV)
29613+#define AUFS_CTL_FLUSH_PLINK _IOR(AuCtlType, AuCtl_FLUSH_PLINK)
29614+#define AUFS_CTL_CPUP _IOWR(AuCtlType, AuCtl_CPUP, struct aufs_ctl)
29615+#define AUFS_CTL_CPDOWN \
29616+ _IOWR(AuCtlType, AuCtl_CPDOWN, struct aufs_ctl_cp)
29617+#endif
29618+
29619+#endif /* __AUFS_TYPE_H__ */
This page took 3.43185 seconds and 4 git commands to generate.