]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs.patch
- remove from HEAD
[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
7127@@ -0,0 +1,826 @@
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>
7155+#include "aufs.h"
7156+
7157+union conv {
7158+#ifdef CONFIG_AUFS_INO_T_64
7159+ __u32 a[2];
7160+#else
7161+ __u32 a[1];
7162+#endif
7163+ ino_t ino;
7164+};
7165+
7166+static ino_t decode_ino(__u32 *a)
7167+{
7168+ union conv u;
7169+
7170+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
7171+ u.a[0] = a[0];
7172+#ifdef CONFIG_AUFS_INO_T_64
7173+ u.a[1] = a[1];
7174+#endif
7175+ return u.ino;
7176+}
7177+
7178+static void encode_ino(__u32 *a, ino_t ino)
7179+{
7180+ union conv u;
7181+
7182+ u.ino = ino;
7183+ a[0] = u.a[0];
7184+#ifdef CONFIG_AUFS_INO_T_64
7185+ a[1] = u.a[1];
7186+#endif
7187+}
7188+
7189+/* NFS file handle */
7190+enum {
7191+ Fh_br_id,
7192+ Fh_sigen,
7193+#ifdef CONFIG_AUFS_INO_T_64
7194+ /* support 64bit inode number */
7195+ Fh_ino1,
7196+ Fh_ino2,
7197+ Fh_dir_ino1,
7198+ Fh_dir_ino2,
7199+#else
7200+ Fh_ino1,
7201+ Fh_dir_ino1,
7202+#endif
7203+ Fh_igen,
7204+ Fh_h_type,
7205+ Fh_tail,
7206+
7207+ Fh_ino = Fh_ino1,
7208+ Fh_dir_ino = Fh_dir_ino1
7209+};
7210+
7211+static int au_test_anon(struct dentry *dentry)
7212+{
7213+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
7214+}
7215+
7216+/* ---------------------------------------------------------------------- */
7217+/* inode generation external table */
7218+
7219+int au_xigen_inc(struct inode *inode)
7220+{
7221+ int err;
7222+ loff_t pos;
7223+ ssize_t sz;
7224+ __u32 igen;
7225+ struct super_block *sb;
7226+ struct au_sbinfo *sbinfo;
7227+
7228+ LKTRTrace("i%lu\n", (unsigned long)inode->i_ino);
7229+
7230+ err = 0;
7231+ sb = inode->i_sb;
7232+ if (unlikely(!au_opt_test_xino(au_mntflags(sb))))
7233+ goto out;
7234+
7235+ pos = inode->i_ino;
7236+ pos *= sizeof(igen);
7237+ igen = inode->i_generation + 1;
7238+ sbinfo = au_sbi(sb);
7239+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
7240+ sizeof(igen), &pos);
7241+ if (sz == sizeof(igen))
7242+ goto out; /* success */
7243+
7244+ err = sz;
7245+ if (unlikely(sz >= 0)) {
7246+ err = -EIO;
7247+ AuIOErr("xigen error (%zd)\n", sz);
7248+ }
7249+
7250+ out:
7251+ AuTraceErr(err);
7252+ return err;
7253+}
7254+
7255+int au_xigen_new(struct inode *inode)
7256+{
7257+ int err;
7258+ loff_t pos;
7259+ ssize_t sz;
7260+ struct super_block *sb;
7261+ struct au_sbinfo *sbinfo;
7262+ struct file *file;
7263+
7264+ LKTRTrace("i%lu\n", inode->i_ino);
7265+
7266+ err = 0;
7267+ /* todo: dirty, at mount time */
7268+ if (inode->i_ino == AUFS_ROOT_INO)
7269+ goto out;
7270+ sb = inode->i_sb;
7271+ if (unlikely(!au_opt_test_xino(au_mntflags(sb))))
7272+ goto out;
7273+
7274+ err = -EFBIG;
7275+ pos = inode->i_ino;
7276+ if (unlikely(Au_LOFF_MAX / sizeof(inode->i_generation) - 1 < pos)) {
7277+ AuIOErr1("too large i%lld\n", pos);
7278+ goto out;
7279+ }
7280+ pos *= sizeof(inode->i_generation);
7281+
7282+ err = 0;
7283+ sbinfo = au_sbi(sb);
7284+ file = sbinfo->si_xigen;
7285+ BUG_ON(!file);
7286+
7287+ if (i_size_read(file->f_dentry->d_inode)
7288+ < pos + sizeof(inode->i_generation)) {
7289+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
7290+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
7291+ sizeof(inode->i_generation), &pos);
7292+ } else
7293+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
7294+ sizeof(inode->i_generation), &pos);
7295+ if (sz == sizeof(inode->i_generation))
7296+ goto out; /* success */
7297+
7298+ err = sz;
7299+ if (unlikely(sz >= 0)) {
7300+ err = -EIO;
7301+ AuIOErr("xigen error (%zd)\n", sz);
7302+ }
7303+
7304+ out:
7305+ AuTraceErr(err);
7306+ return err;
7307+}
7308+
7309+int au_xigen_set(struct super_block *sb, struct file *base)
7310+{
7311+ int err;
7312+ struct au_sbinfo *sbinfo;
7313+ struct file *file;
7314+
7315+ LKTRTrace("%.*s\n", AuDLNPair(base->f_dentry));
7316+ SiMustWriteLock(sb);
7317+
7318+ sbinfo = au_sbi(sb);
7319+ file = au_xino_create2(sb, base, sbinfo->si_xigen);
7320+ err = PTR_ERR(file);
7321+ if (IS_ERR(file))
7322+ goto out;
7323+ err = 0;
7324+ if (sbinfo->si_xigen)
7325+ fput(sbinfo->si_xigen);
7326+ sbinfo->si_xigen = file;
7327+
7328+ out:
7329+ AuTraceErr(err);
7330+ return err;
7331+}
7332+
7333+void au_xigen_clr(struct super_block *sb)
7334+{
7335+ struct au_sbinfo *sbinfo;
7336+
7337+ sbinfo = au_sbi(sb);
7338+ if (sbinfo->si_xigen) {
7339+ fput(sbinfo->si_xigen);
7340+ sbinfo->si_xigen = NULL;
7341+ }
7342+}
7343+
7344+/* ---------------------------------------------------------------------- */
7345+
7346+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
7347+ ino_t dir_ino)
7348+{
7349+ struct dentry *dentry, *d;
7350+ struct inode *inode;
7351+ au_gen_t sigen;
7352+
7353+ LKTRTrace("i%lu, diri%lu\n",
7354+ (unsigned long)ino, (unsigned long)dir_ino);
7355+
7356+ dentry = NULL;
7357+ inode = ilookup(sb, ino);
7358+ if (!inode)
7359+ goto out;
7360+
7361+ dentry = ERR_PTR(-ESTALE);
7362+ sigen = au_sigen(sb);
7363+ if (unlikely(is_bad_inode(inode)
7364+ || IS_DEADDIR(inode)
7365+ || sigen != au_iigen(inode)))
7366+ goto out_iput;
7367+
7368+ dentry = NULL;
7369+ if (!dir_ino || S_ISDIR(inode->i_mode))
7370+ dentry = d_find_alias(inode);
7371+ else {
7372+ spin_lock(&dcache_lock);
7373+ list_for_each_entry(d, &inode->i_dentry, d_alias)
7374+ if (!au_test_anon(d)
7375+ && d->d_parent->d_inode->i_ino == dir_ino) {
7376+ dentry = dget_locked(d);
7377+ break;
7378+ }
7379+ spin_unlock(&dcache_lock);
7380+ }
7381+ if (unlikely(dentry && sigen != au_digen(dentry))) {
7382+ dput(dentry);
7383+ dentry = ERR_PTR(-ESTALE);
7384+ }
7385+
7386+ out_iput:
7387+ iput(inode);
7388+ out:
7389+ AuTraceErrPtr(dentry);
7390+ return dentry;
7391+}
7392+
7393+/* ---------------------------------------------------------------------- */
7394+
7395+/* todo: dirty? */
7396+/*
7397+ * when you mntput() for the return value of this function,
7398+ * you have to store it to your local var.
7399+ * ie. never mntput si_mntcache directly.
7400+ */
7401+static struct vfsmount *au_do_mnt_get(struct super_block *sb)
7402+{
7403+ struct mnt_namespace *ns;
7404+ struct vfsmount *pos, *mnt;
7405+
7406+ AuTraceEnter();
7407+
7408+ /* vfsmount_lock is not exported */
7409+ /* no get/put ?? */
7410+ AuDebugOn(!current->nsproxy);
7411+ ns = current->nsproxy->mnt_ns;
7412+ AuDebugOn(!ns);
7413+ mnt = NULL;
7414+ /* the order (reverse) will not be a problem */
7415+ list_for_each_entry(pos, &ns->list, mnt_list)
7416+ if (pos->mnt_sb == sb) {
7417+ mnt = pos;
7418+ break;
7419+ }
7420+ AuDebugOn(!mnt);
7421+
7422+ return mntget(mnt);
7423+}
7424+
7425+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
7426+static struct vfsmount *au_mnt_get(struct super_block *sb)
7427+{
7428+ struct au_sbinfo *sbinfo;
7429+ struct vfsmount *mnt;
7430+
7431+ sbinfo = au_sbi(sb);
7432+ spin_lock(&sbinfo->si_mntcache_lock);
7433+ if (sbinfo->si_mntcache)
7434+ mnt = mntget(sbinfo->si_mntcache);
7435+ else {
7436+ sbinfo->si_mntcache = au_do_mnt_get(sb);
7437+ mnt = sbinfo->si_mntcache;
7438+ }
7439+ spin_unlock(&sbinfo->si_mntcache_lock);
7440+ return mnt;
7441+}
7442+#else
7443+static struct vfsmount *au_mnt_get(struct super_block *sb)
7444+{
7445+ return au_do_mnt_get(sb);
7446+}
7447+#endif
7448+
7449+struct au_nfsd_si_lock {
7450+ const au_gen_t sigen;
7451+ const aufs_bindex_t br_id;
7452+ unsigned char force_lock;
7453+};
7454+
7455+static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
7456+ struct au_nfsd_si_lock *nsi_lock)
7457+{
7458+ aufs_bindex_t bindex;
7459+
7460+ si_read_lock(sb, AuLock_FLUSH);
7461+
7462+ /* branch id may be wrapped around */
7463+ bindex = au_br_index(sb, nsi_lock->br_id);
7464+ LKTRTrace("b%d\n", bindex);
7465+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
7466+ goto out; /* success */
7467+
7468+ if (!nsi_lock->force_lock)
7469+ si_read_unlock(sb);
7470+ bindex = -1;
7471+
7472+ out:
7473+ return bindex;
7474+}
7475+
7476+struct find_name_by_ino {
7477+ int called, found;
7478+ ino_t ino;
7479+ char *name;
7480+ int namelen;
7481+};
7482+
7483+static int
7484+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
7485+ u64 ino, unsigned int d_type)
7486+{
7487+ struct find_name_by_ino *a = arg;
7488+
7489+ a->called++;
7490+ if (a->ino != ino)
7491+ return 0;
7492+
7493+ memcpy(a->name, name, namelen);
7494+ a->namelen = namelen;
7495+ a->found = 1;
7496+ return 1;
7497+}
7498+
7499+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
7500+ struct au_nfsd_si_lock *nsi_lock)
7501+{
7502+ struct dentry *dentry, *parent;
7503+ struct file *file;
7504+ struct inode *dir;
7505+ struct find_name_by_ino arg;
7506+ int err;
7507+
7508+ parent = path->dentry;
7509+ LKTRTrace("%.*s, i%lu\n", AuDLNPair(parent), (unsigned long)ino);
7510+
7511+ if (nsi_lock)
7512+ si_read_unlock(parent->d_sb);
7513+ path_get(path);
94750128 7514+ file = dentry_open(parent, path->mnt, au_dir_roflags, file->f_cred);
024a5822
JR
7515+ dentry = (void *)file;
7516+ if (IS_ERR(file))
7517+ goto out;
7518+
7519+ dentry = ERR_PTR(-ENOMEM);
7520+ arg.name = __getname();
7521+ if (unlikely(!arg.name))
7522+ goto out_file;
7523+ arg.ino = ino;
7524+ arg.found = 0;
7525+ do {
7526+ arg.called = 0;
7527+ /* smp_mb(); */
7528+ err = vfsub_readdir(file, find_name_by_ino, &arg, /*dlgt*/0);
7529+ } while (!err && !arg.found && arg.called);
7530+ dentry = ERR_PTR(err);
7531+ if (unlikely(err))
7532+ goto out_name;
7533+ dentry = ERR_PTR(-ENOENT);
7534+ if (!arg.found)
7535+ goto out_name;
7536+
7537+ /* do not call au_lkup_one(), nor dlgt */
7538+ dir = parent->d_inode;
7539+ mutex_lock(&dir->i_mutex);
7540+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
7541+ mutex_unlock(&dir->i_mutex);
7542+ AuTraceErrPtr(dentry);
7543+ if (IS_ERR(dentry))
7544+ goto out_name;
7545+ AuDebugOn(au_test_anon(dentry));
7546+ if (unlikely(!dentry->d_inode)) {
7547+ dput(dentry);
7548+ dentry = ERR_PTR(-ENOENT);
7549+ }
7550+
7551+ out_name:
7552+ __putname(arg.name);
7553+ out_file:
7554+ fput(file);
7555+ out:
7556+ if (unlikely(nsi_lock
7557+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
7558+ if (!IS_ERR(dentry)) {
7559+ dput(dentry);
7560+ dentry = ERR_PTR(-ESTALE);
7561+ }
7562+ AuTraceErrPtr(dentry);
7563+ return dentry;
7564+}
7565+
7566+static /* noinline_for_stack */
7567+struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
7568+ ino_t dir_ino, struct au_nfsd_si_lock *nsi_lock)
7569+{
7570+ struct dentry *dentry, *parent;
7571+ struct path path;
7572+
7573+ LKTRTrace("i%lu, diri%lu\n",
7574+ (unsigned long)ino, (unsigned long)dir_ino);
7575+
7576+ parent = sb->s_root;
7577+ if (dir_ino != AUFS_ROOT_INO) {
7578+ parent = decode_by_ino(sb, dir_ino, 0);
7579+ dentry = parent;
7580+ if (!parent)
7581+ goto out;
7582+ if (IS_ERR(parent))
7583+ goto out;
7584+ AuDebugOn(au_test_anon(parent));
7585+ } else
7586+ dget(parent);
7587+
7588+ path.dentry = parent;
7589+ path.mnt = au_mnt_get(sb);
7590+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
7591+ path_put(&path);
7592+
7593+ out:
7594+ AuTraceErrPtr(dentry);
7595+ return dentry;
7596+}
7597+
7598+/* ---------------------------------------------------------------------- */
7599+
7600+static int h_acceptable(void *expv, struct dentry *dentry)
7601+{
7602+ return 1;
7603+}
7604+
7605+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
7606+ char *buf, int len, struct super_block *sb)
7607+{
7608+ char *p;
7609+ int n;
7610+ struct path path;
7611+
7612+ AuTraceEnter();
7613+
7614+ p = d_path(h_rootpath, buf, len);
7615+ if (IS_ERR(p))
7616+ goto out;
7617+ n = strlen(p);
7618+
7619+ path.mnt = h_rootpath->mnt;
7620+ path.dentry = h_parent;
7621+ p = d_path(&path, buf, len);
7622+ if (IS_ERR(p))
7623+ goto out;
7624+ LKTRTrace("%s\n", p);
7625+ if (n != 1)
7626+ p += n;
7627+ LKTRTrace("%p, %s, %ld\n",
7628+ p, p, (long)(p - buf));
7629+
7630+ path.mnt = au_mnt_get(sb);
7631+ path.dentry = sb->s_root;
7632+ p = d_path(&path, buf, len - strlen(p));
7633+ mntput(path.mnt);
7634+ if (IS_ERR(p))
7635+ goto out;
7636+ if (n != 1)
7637+ p[strlen(p)] = '/';
7638+ LKTRTrace("%s\n", p);
7639+
7640+ out:
7641+ AuTraceErrPtr(p);
7642+ return p;
7643+}
7644+
7645+static noinline_for_stack
7646+struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
7647+ ino_t ino, __u32 *fh, int fh_len,
7648+ struct au_nfsd_si_lock *nsi_lock)
7649+{
7650+ struct dentry *dentry, *h_parent, *root;
7651+ struct super_block *h_sb;
7652+ char *pathname, *p;
7653+ struct vfsmount *h_mnt;
7654+ struct au_branch *br;
7655+ int err;
7656+ struct nameidata nd;
7657+
7658+ LKTRTrace("b%d\n", bindex);
7659+ SiMustAnyLock(sb);
7660+
7661+ br = au_sbr(sb, bindex);
7662+ /* au_br_get(br); */
7663+ h_mnt = br->br_mnt;
7664+ h_sb = h_mnt->mnt_sb;
7665+ LKTRTrace("%s, h_decode_fh\n", au_sbtype(h_sb));
7666+ /* in linux-2.6.24, it takes struct fid * as file handle */
7667+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
7668+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
7669+ fh_len - Fh_tail, fh[Fh_h_type],
7670+ h_acceptable, /*context*/NULL);
7671+ dentry = h_parent;
7672+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
7673+ AuWarn1("%s decode_fh failed, %ld\n",
7674+ au_sbtype(h_sb), PTR_ERR(h_parent));
7675+ goto out;
7676+ }
7677+ dentry = NULL;
7678+ if (unlikely(au_test_anon(h_parent))) {
7679+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
7680+ au_sbtype(h_sb));
7681+ goto out_h_parent;
7682+ }
7683+
7684+ dentry = ERR_PTR(-ENOMEM);
7685+ pathname = (void *)__get_free_page(GFP_NOFS);
7686+ if (unlikely(!pathname))
7687+ goto out_h_parent;
7688+
7689+ root = sb->s_root;
7690+ nd.path.mnt = h_mnt;
7691+ di_read_lock_parent(root, !AuLock_IR);
7692+ nd.path.dentry = au_h_dptr(root, bindex);
7693+ di_read_unlock(root, !AuLock_IR);
7694+ p = au_build_path(h_parent, &nd.path, pathname, PAGE_SIZE, sb);
7695+ dentry = (void *)p;
7696+ if (IS_ERR(p))
7697+ goto out_pathname;
7698+
7699+ LKTRTrace("%s\n", p);
7700+ si_read_unlock(sb);
7701+ err = vfsub_path_lookup(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd);
7702+ dentry = ERR_PTR(err);
7703+ if (unlikely(err))
7704+ goto out_relock;
7705+
7706+ dentry = ERR_PTR(-ENOENT);
7707+ AuDebugOn(au_test_anon(nd.path.dentry));
7708+ if (unlikely(!nd.path.dentry->d_inode))
7709+ goto out_nd;
7710+
7711+ if (ino != nd.path.dentry->d_inode->i_ino)
7712+ dentry = au_lkup_by_ino(&nd.path, ino, /*nsi_lock*/NULL);
7713+ else
7714+ dentry = dget(nd.path.dentry);
7715+
7716+ out_nd:
7717+ path_put(&nd.path);
7718+ out_relock:
7719+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
7720+ if (!IS_ERR(dentry)) {
7721+ dput(dentry);
7722+ dentry = ERR_PTR(-ESTALE);
7723+ }
7724+ out_pathname:
7725+ free_page((unsigned long)pathname);
7726+ out_h_parent:
7727+ dput(h_parent);
7728+ out:
7729+ /* au_br_put(br); */
7730+ AuTraceErrPtr(dentry);
7731+ return dentry;
7732+}
7733+
7734+/* ---------------------------------------------------------------------- */
7735+
7736+static struct dentry *
7737+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
7738+ int fh_type)
7739+{
7740+ struct dentry *dentry;
7741+ __u32 *fh = fid->raw;
7742+ ino_t ino, dir_ino;
7743+ aufs_bindex_t bindex;
7744+ struct au_nfsd_si_lock nsi_lock = {
7745+ .sigen = fh[Fh_sigen],
7746+ .br_id = fh[Fh_br_id],
7747+ .force_lock = 0
7748+ };
7749+
7750+ LKTRTrace("%d, fh{br_id %u, sigen %u, i%u, diri%u, g%u}\n",
7751+ fh_type, fh[Fh_br_id], fh[Fh_sigen], fh[Fh_ino],
7752+ fh[Fh_dir_ino], fh[Fh_igen]);
7753+ AuDebugOn(fh_len < Fh_tail);
7754+
7755+ dentry = ERR_PTR(-ESTALE);
7756+ /* branch id may be wrapped around */
7757+ bindex = si_nfsd_read_lock(sb, &nsi_lock);
7758+ if (unlikely(bindex < 0))
7759+ goto out;
7760+ nsi_lock.force_lock = 1;
7761+
7762+ /* is this inode still cached? */
7763+ ino = decode_ino(fh + Fh_ino);
7764+ AuDebugOn(ino == AUFS_ROOT_INO);
7765+ dir_ino = decode_ino(fh + Fh_dir_ino);
7766+ dentry = decode_by_ino(sb, ino, dir_ino);
7767+ if (IS_ERR(dentry))
7768+ goto out_unlock;
7769+ if (dentry)
7770+ goto accept;
7771+
7772+ /* is the parent dir cached? */
7773+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
7774+ if (IS_ERR(dentry))
7775+ goto out_unlock;
7776+ if (dentry)
7777+ goto accept;
7778+
7779+ /* lookup path */
7780+ dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
7781+ if (IS_ERR(dentry))
7782+ goto out_unlock;
7783+ if (unlikely(!dentry))
7784+ /* todo?: make it ESTALE */
7785+ goto out_unlock;
7786+
7787+ accept:
7788+ LKTRLabel(accept);
7789+ if (dentry->d_inode->i_generation == fh[Fh_igen])
7790+ goto out_unlock; /* success */
7791+
7792+ LKTRLabel(stale);
7793+ dput(dentry);
7794+ dentry = ERR_PTR(-ESTALE);
7795+ out_unlock:
7796+ LKTRLabel(out_unlock);
7797+ si_read_unlock(sb);
7798+ out:
7799+ LKTRLabel(out);
7800+ if (0 && IS_ERR(dentry))
7801+ dentry = ERR_PTR(-ESTALE);
7802+ AuTraceErrPtr(dentry);
7803+ return dentry;
7804+}
7805+
7806+#if 0 /* reserved for future use */
7807+/* support subtreecheck option */
7808+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
7809+ int fh_len, int fh_type)
7810+{
7811+ struct dentry *parent;
7812+ __u32 *fh = fid->raw;
7813+ ino_t dir_ino;
7814+
7815+ dir_ino = decode_ino(fh + Fh_dir_ino);
7816+ parent = decode_by_ino(sb, dir_ino, 0);
7817+ if (IS_ERR(parent))
7818+ goto out;
7819+ if (!parent)
7820+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
7821+ dir_ino, fh, fh_len);
7822+
7823+ out:
7824+ AuTraceErrPtr(parent);
7825+ return parent;
7826+}
7827+#endif
7828+
7829+/* ---------------------------------------------------------------------- */
7830+
7831+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
7832+ int connectable)
7833+{
7834+ int err;
7835+ aufs_bindex_t bindex, bend;
7836+ struct super_block *sb, *h_sb;
7837+ struct inode *inode;
7838+ struct dentry *parent, *h_parent;
7839+ struct au_branch *br;
7840+
7841+ LKTRTrace("%.*s, max %d, conn %d\n",
7842+ AuDLNPair(dentry), *max_len, connectable);
7843+ AuDebugOn(au_test_anon(dentry));
7844+
7845+ parent = NULL;
7846+ err = -ENOSPC;
7847+ if (unlikely(*max_len <= Fh_tail)) {
7848+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
7849+ goto out;
7850+ }
7851+
7852+ err = FILEID_ROOT;
7853+ if (IS_ROOT(dentry)) {
7854+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
7855+ goto out;
7856+ }
7857+
7858+ err = -EIO;
7859+ h_parent = NULL;
7860+ sb = dentry->d_sb;
7861+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
7862+ parent = dget_parent(dentry);
7863+ di_read_lock_parent(parent, !AuLock_IR);
7864+ inode = dentry->d_inode;
7865+ AuDebugOn(!inode);
7866+#ifdef CONFIG_AUFS_DEBUG
7867+ {
7868+ unsigned int mnt_flags = au_mntflags(sb);
7869+
7870+ if (unlikely(!au_opt_test_xino(mnt_flags)))
7871+ AuWarn1("NFS-exporting requires xino\n");
7872+ if (unlikely(0 && !au_opt_test(mnt_flags, UDBA_INOTIFY)))
7873+ AuWarn1("udba=inotify is recommended "
7874+ "for NFS-exporting\n");
7875+ }
7876+#endif
7877+
7878+ bend = au_dbtaildir(parent);
7879+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
7880+ h_parent = au_h_dptr(parent, bindex);
7881+ if (h_parent) {
7882+ dget(h_parent);
7883+ break;
7884+ }
7885+ }
7886+ if (unlikely(!h_parent))
7887+ goto out_unlock;
7888+ LKTRTrace("b%d\n", bindex);
7889+
7890+ err = -EPERM;
7891+ br = au_sbr(sb, bindex);
7892+ h_sb = br->br_mnt->mnt_sb;
7893+ if (unlikely(!h_sb->s_export_op)) {
7894+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
7895+ goto out_dput;
7896+ }
7897+
7898+ fh[Fh_br_id] = br->br_id;
7899+ fh[Fh_sigen] = au_sigen(sb);
7900+ encode_ino(fh + Fh_ino, inode->i_ino);
7901+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
7902+ fh[Fh_igen] = inode->i_generation;
7903+
7904+ *max_len -= Fh_tail;
7905+ /* in linux-2.6.24, it takes struct fid * as file handle */
7906+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
7907+ max_len,
7908+ /*connectable or subtreecheck*/0);
7909+ err = fh[Fh_h_type];
7910+ *max_len += Fh_tail;
7911+ /* todo: macros? */
7912+ if (err != 255)
7913+ err = 99;
7914+ else
7915+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
7916+
7917+ out_dput:
7918+ dput(h_parent);
7919+ out_unlock:
7920+ di_read_unlock(parent, !AuLock_IR);
7921+ dput(parent);
7922+ aufs_read_unlock(dentry, AuLock_IR);
7923+ out:
7924+ AuTraceErr(err);
7925+ if (unlikely(err < 0))
7926+ err = 255;
7927+ return err;
7928+}
7929+
7930+/* ---------------------------------------------------------------------- */
7931+
7932+static struct export_operations aufs_export_op = {
7933+ .fh_to_dentry = aufs_fh_to_dentry,
7934+ //.fh_to_parent = aufs_fh_to_parent,
7935+ .encode_fh = aufs_encode_fh
7936+};
7937+
7938+void au_export_init(struct super_block *sb)
7939+{
7940+ struct au_sbinfo *sbinfo;
7941+ __u32 u;
7942+
7943+ AuTraceEnter();
7944+ SiMustWriteLock(sb);
7945+
7946+ sb->s_export_op = &aufs_export_op;
7947+ sbinfo = au_sbi(sb);
7948+ sbinfo->si_xigen = NULL;
7949+ get_random_bytes(&u, sizeof(u));
7950+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
7951+ atomic_set(&sbinfo->si_xigen_next, u);
7952+ memset(&sbinfo->si_xinodir, 0, sizeof(struct path));
7953+}
7954diff -urN linux/fs/aufs/file.c linux-aufs/fs/aufs/file.c
7955--- linux/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
7956+++ linux-aufs/fs/aufs/file.c 2009-03-12 16:18:04.000000000 +0100
7957@@ -0,0 +1,777 @@
7958+/*
7959+ * Copyright (C) 2005-2009 Junjiro Okajima
7960+ *
7961+ * This program, aufs is free software; you can redistribute it and/or modify
7962+ * it under the terms of the GNU General Public License as published by
7963+ * the Free Software Foundation; either version 2 of the License, or
7964+ * (at your option) any later version.
7965+ *
7966+ * This program is distributed in the hope that it will be useful,
7967+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7968+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7969+ * GNU General Public License for more details.
7970+ *
7971+ * You should have received a copy of the GNU General Public License
7972+ * along with this program; if not, write to the Free Software
7973+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7974+ */
7975+
7976+/*
7977+ * handling file/dir, and address_space operation
7978+ *
7979+ * $Id$
7980+ */
7981+
7982+#include <linux/pagemap.h>
7983+#include "aufs.h"
7984+
7985+/*
7986+ * a dirty trick for handling FMODE_EXEC and deny_write_access().
7987+ * because FMODE_EXEC flag is not passed to f_op->open(),
7988+ * set it to file->private_data temporary.
7989+ */
7990+#if !defined(CONFIG_AUFS_MODULE) || defined(CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH)
7991+int au_store_fmode_exec(struct nameidata *nd, struct inode *inode)
7992+{
7993+ int err;
7994+ union {
7995+ void *p;
7996+ unsigned long ul;
7997+ } u;
7998+
7999+ err = 0;
8000+ if (nd
8001+ && (nd->flags & LOOKUP_OPEN)
8002+ && nd->intent.open.file
8003+ && (nd->intent.open.flags & FMODE_EXEC)
8004+ && inode
8005+ && S_ISREG(inode->i_mode)) {
8006+ u.ul = nd->intent.open.flags;
8007+ nd->intent.open.file->private_data = u.p;
8008+ /* smp_mb(); */
8009+ err = 1;
8010+ }
8011+
8012+ return err;
8013+}
8014+#endif
8015+
8016+/* drop flags for writing */
8017+unsigned int au_file_roflags(unsigned int flags)
8018+{
8019+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
8020+ flags |= O_RDONLY | O_NOATIME;
8021+ return flags;
8022+}
8023+
8024+/* common functions to regular file and dir */
8025+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8026+ struct file *file)
8027+{
8028+ struct file *h_file;
8029+ struct dentry *h_dentry;
8030+ struct inode *h_inode;
8031+ struct super_block *sb;
8032+ struct au_branch *br;
8033+ int err;
8034+
8035+ LKTRTrace("%.*s, b%d, flags 0%o, f %d\n",
8036+ AuDLNPair(dentry), bindex, flags, !!file);
8037+ h_dentry = au_h_dptr(dentry, bindex);
8038+ AuDebugOn(!h_dentry);
8039+ h_inode = h_dentry->d_inode;
8040+
8041+ /* a race condition can happen between open and unlink/rmdir */
8042+ h_file = ERR_PTR(-ENOENT);
8043+ if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
8044+ || !h_inode))
8045+ goto out;
8046+
8047+ sb = dentry->d_sb;
8048+ br = au_sbr(sb, bindex);
8049+ au_br_get(br);
8050+ /* drop flags for writing */
8051+ if (au_test_ro(sb, bindex, dentry->d_inode))
8052+ flags = au_file_roflags(flags);
8053+ flags &= ~O_CREAT;
8054+
8055+ h_file = NULL;
8056+ if (file && au_test_nfs(h_dentry->d_sb))
8057+ h_file = au_h_intent(dentry, bindex, file);
8058+ if (!h_file)
94750128 8059+ h_file = dentry_open(dget(h_dentry), mntget(br->br_mnt), flags, file->f_cred);
024a5822
JR
8060+
8061+ /*
8062+ * a dirty trick for handling FMODE_EXEC and deny_write_access().
8063+ */
8064+ if (file && (file->f_mode & FMODE_EXEC)) {
8065+ h_file->f_mode |= FMODE_EXEC;
8066+ smp_mb(); /* flush f_mode */
8067+ err = au_deny_write_access(h_file);
8068+ if (unlikely(err)) {
8069+ fput(h_file);
8070+ h_file = ERR_PTR(err);
8071+ }
8072+ }
8073+ if (IS_ERR(h_file))
8074+ au_br_put(br);
8075+
8076+out:
8077+ AuTraceErrPtr(h_file);
8078+ return h_file;
8079+}
8080+
8081+static int do_coo(struct dentry *dentry, aufs_bindex_t bstart)
8082+{
8083+ int err;
8084+ aufs_bindex_t bcpup;
8085+ unsigned char pin_flags;
8086+ struct au_pin pin;
8087+ struct dentry *parent;
8088+ struct mutex *h_mtx;
8089+ struct super_block *sb;
8090+
8091+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
8092+ AuDebugOn(IS_ROOT(dentry));
8093+ DiMustWriteLock(dentry);
8094+
8095+ parent = dget_parent(dentry);
8096+ di_write_lock_parent(parent);
8097+ sb = dentry->d_sb;
8098+ err = AuWbrCopyup(au_sbi(sb), dentry);
8099+ bcpup = err;
8100+ if (err < 0) {
8101+ err = 0; /* stop copyup, it is not an error */
8102+ goto out_dgrade;
8103+ }
8104+ err = 0;
8105+
8106+ if (!au_h_dptr(parent, bcpup)) {
8107+ err = au_cpup_dirs(dentry, bcpup);
8108+ if (unlikely(err))
8109+ goto out_dgrade;
8110+ }
8111+
8112+ di_downgrade_lock(parent, AuLock_IR);
8113+ pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
8114+ if (au_opt_test(au_mntflags(sb), UDBA_INOTIFY))
8115+ au_fset_pin(pin_flags, DO_GPARENT);
8116+ err = au_pin(&pin, dentry, bcpup, pin_flags);
8117+ if (unlikely(err))
8118+ goto out;
8119+ h_mtx = &au_h_dptr(dentry, bstart)->d_inode->i_mutex;
8120+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
8121+ AuDebugOn(au_h_dptr(dentry, bcpup));
8122+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
8123+ AuTraceErr(err);
8124+ mutex_unlock(h_mtx);
8125+ au_unpin(&pin);
8126+ goto out;
8127+
8128+ out_dgrade:
8129+ di_downgrade_lock(parent, AuLock_IR);
8130+ out:
8131+ di_read_unlock(parent, AuLock_IR);
8132+ dput(parent);
8133+ AuTraceErr(err);
8134+ return err;
8135+}
8136+
8137+int au_do_open(struct inode *inode, struct file *file,
8138+ int (*open)(struct file *file, int flags))
8139+{
8140+ int err;
8141+ struct dentry *dentry;
8142+ struct super_block *sb;
8143+ aufs_bindex_t bstart;
8144+ unsigned char coo;
8145+
8146+ dentry = file->f_dentry;
8147+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry));
8148+
8149+ sb = dentry->d_sb;
8150+ si_read_lock(sb, AuLock_FLUSH);
8151+ coo = 0;
8152+ if (!(sb->s_flags & MS_RDONLY))
8153+ switch (au_mntflags(sb) & AuOptMask_COO) {
8154+ case AuOpt_COO_LEAF:
8155+ coo = !S_ISDIR(inode->i_mode);
8156+ break;
8157+ case AuOpt_COO_ALL:
8158+ coo = 1;
8159+ break;
8160+ }
8161+ err = au_finfo_init(file);
8162+ if (unlikely(err))
8163+ goto out;
8164+
8165+ if (!coo)
8166+ di_read_lock_child(dentry, AuLock_IR);
8167+ else {
8168+ di_write_lock_child(dentry);
8169+ bstart = au_dbstart(dentry);
8170+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
8171+ err = do_coo(dentry, bstart);
8172+ if (err) {
8173+ di_write_unlock(dentry);
8174+ goto out_finfo;
8175+ }
8176+ }
8177+ di_downgrade_lock(dentry, AuLock_IR);
8178+ }
8179+
8180+ err = open(file, file->f_flags);
8181+ di_read_unlock(dentry, AuLock_IR);
8182+
8183+ out_finfo:
8184+ fi_write_unlock(file);
8185+ if (unlikely(err))
8186+ au_finfo_fin(file);
8187+ out:
8188+ si_read_unlock(sb);
8189+ AuTraceErr(err);
8190+ return err;
8191+}
8192+
8193+int au_reopen_nondir(struct file *file)
8194+{
8195+ int err;
8196+ aufs_bindex_t bstart, bindex, bend;
8197+ struct dentry *dentry;
8198+ struct file *h_file, *h_file_tmp;
8199+
8200+ dentry = file->f_dentry;
8201+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
8202+ bstart = au_dbstart(dentry);
8203+ //bstart = au_ibstart(inode);
8204+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
8205+ || !au_h_dptr(dentry, bstart)->d_inode);
8206+
8207+ h_file_tmp = NULL;
8208+ if (au_fbstart(file) == bstart) {
8209+ h_file = au_h_fptr(file, bstart);
8210+ if (file->f_mode == h_file->f_mode)
8211+ return 0; /* success */
8212+ h_file_tmp = h_file;
8213+ get_file(h_file_tmp);
8214+ au_set_h_fptr(file, bstart, NULL);
8215+ }
8216+ AuDebugOn(au_fbstart(file) < bstart
8217+ || au_fi(file)->fi_hfile[0 + bstart].hf_file);
8218+
8219+ h_file = au_h_open(dentry, bstart, file->f_flags & ~O_TRUNC, file);
8220+ err = PTR_ERR(h_file);
8221+ if (IS_ERR(h_file))
8222+ goto out; /* todo: close all? */
8223+ err = 0;
8224+ /* cpup_file_flags(h_file, file); */
8225+ au_set_fbstart(file, bstart);
8226+ au_set_h_fptr(file, bstart, h_file);
8227+ au_update_figen(file);
8228+ /* todo: necessary? */
8229+ /* file->f_ra = h_file->f_ra; */
8230+
8231+ /* close lower files */
8232+ bend = au_fbend(file);
8233+ for (bindex = bstart + 1; bindex <= bend; bindex++)
8234+ au_set_h_fptr(file, bindex, NULL);
8235+ au_set_fbend(file, bstart);
8236+
8237+ out:
8238+ if (h_file_tmp)
8239+ fput(h_file_tmp);
8240+ AuTraceErr(err);
8241+ return err;
8242+}
8243+
8244+/* ---------------------------------------------------------------------- */
8245+
8246+static int au_ready_to_write_wh(struct file *file, loff_t len,
8247+ aufs_bindex_t bcpup)
8248+{
8249+ int err;
8250+ aufs_bindex_t old_bstart;
8251+ struct inode *inode;
8252+ struct dentry *dentry, *hi_wh, *old_h_dentry;
8253+ struct au_dinfo *dinfo;
8254+ struct super_block *sb;
8255+
8256+ AuTraceEnter();
8257+
8258+ dentry = file->f_dentry;
8259+ inode = dentry->d_inode;
8260+ hi_wh = au_hi_wh(inode, bcpup);
8261+ if (!hi_wh)
8262+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
8263+ else {
8264+ /* already copied-up after unlink */
8265+ dinfo = au_di(dentry);
8266+ old_bstart = dinfo->di_bstart;
8267+ dinfo->di_bstart = bcpup;
8268+ old_h_dentry = dinfo->di_hdentry[0 + bcpup].hd_dentry;
8269+ dinfo->di_hdentry[0 + bcpup].hd_dentry = hi_wh;
8270+ err = au_reopen_nondir(file);
8271+ dinfo->di_hdentry[0 + bcpup].hd_dentry = old_h_dentry;
8272+ dinfo->di_bstart = old_bstart;
8273+ }
8274+
8275+ sb = dentry->d_sb;
8276+ if (!err && inode->i_nlink > 1 && au_opt_test(au_mntflags(sb), PLINK))
8277+ au_plink_append(sb, inode, au_h_dptr(dentry, bcpup), bcpup);
8278+
8279+ AuTraceErr(err);
8280+ return err;
8281+}
8282+
8283+/*
8284+ * prepare the @file for writing.
8285+ */
8286+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
8287+{
8288+ int err;
8289+ unsigned char pin_flags;
8290+ aufs_bindex_t bstart, bcpup;
8291+ struct dentry *dentry, *parent, *h_dentry;
8292+ struct inode *h_inode, *inode;
8293+ struct super_block *sb;
8294+
8295+ dentry = file->f_dentry;
8296+ LKTRTrace("%.*s, len %lld\n", AuDLNPair(dentry), len);
8297+ FiMustWriteLock(file);
8298+
8299+ sb = dentry->d_sb;
8300+ bstart = au_fbstart(file);
8301+ AuDebugOn(au_fbr(file, bstart) != au_sbr(sb, bstart));
8302+
8303+ inode = dentry->d_inode;
8304+ AuDebugOn(S_ISDIR(inode->i_mode));
8305+ LKTRTrace("rdonly %d, bstart %d\n",
8306+ au_test_ro(sb, bstart, inode), bstart);
8307+
8308+ err = au_test_ro(sb, bstart, inode);
8309+ if (!err && (au_h_fptr(file, bstart)->f_mode & FMODE_WRITE)) {
8310+ err = au_pin(pin, dentry, bstart, /*flags*/0);
8311+ goto out;
8312+ }
8313+
8314+ /* need to cpup */
8315+ parent = dget_parent(dentry);
8316+ di_write_lock_parent(parent);
8317+ err = AuWbrCopyup(au_sbi(sb), dentry);
8318+ bcpup = err;
8319+ if (unlikely(err < 0))
8320+ goto out_dgrade;
8321+ err = 0;
8322+
8323+ if (!au_h_dptr(parent, bcpup)) {
8324+ err = au_cpup_dirs(dentry, bcpup);
8325+ if (unlikely(err))
8326+ goto out_dgrade;
8327+ }
8328+
8329+ pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
8330+ if (au_opt_test(au_mntflags(sb), UDBA_INOTIFY))
8331+ au_fset_pin(pin_flags, DO_GPARENT);
8332+ err = au_pin(pin, dentry, bcpup, pin_flags);
8333+ if (unlikely(err))
8334+ goto out_dgrade;
8335+
8336+ AuDebugOn(au_fbstart(file) != bstart);
8337+ h_dentry = au_h_fptr(file, bstart)->f_dentry;
8338+ h_inode = h_dentry->d_inode;
8339+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8340+ if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
8341+ /* || !h_inode->i_nlink */) {
8342+ err = au_ready_to_write_wh(file, len, bcpup);
8343+ di_downgrade_lock(parent, AuLock_IR);
8344+ } else {
8345+ di_downgrade_lock(parent, AuLock_IR);
8346+ if (!au_h_dptr(dentry, bcpup))
8347+ err = au_sio_cpup_simple(dentry, bcpup, len,
8348+ AuCpup_DTIME);
8349+ AuTraceErr(err);
8350+ if (!err)
8351+ err = au_reopen_nondir(file);
8352+ AuTraceErr(err);
8353+ }
8354+ mutex_unlock(&h_inode->i_mutex);
8355+
8356+ if (!err) {
8357+ au_unpin_gp(pin);
8358+ au_pin_set_parent_lflag(pin, /*lflag*/0);
8359+ goto out_dput; /* success */
8360+ }
8361+ au_unpin(pin);
8362+ goto out_unlock;
8363+
8364+ out_dgrade:
8365+ di_downgrade_lock(parent, AuLock_IR);
8366+ out_unlock:
8367+ di_read_unlock(parent, AuLock_IR);
8368+ out_dput:
8369+ dput(parent);
8370+ out:
8371+ AuTraceErr(err);
8372+ return err;
8373+}
8374+
8375+/* ---------------------------------------------------------------------- */
8376+
8377+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
8378+{
8379+ int err;
8380+ unsigned int mnt_flags;
8381+ unsigned char pin_flags;
8382+ aufs_bindex_t bstart, new_bstart, old_bstart;
8383+ struct au_pin pin;
8384+ struct au_finfo *finfo;
8385+ struct dentry *dentry, *parent, *old_h_dentry, *hi_wh;
8386+ struct inode *inode, *dir;
8387+ struct super_block *sb;
8388+ struct au_dinfo *dinfo;
8389+
8390+ dentry = file->f_dentry;
8391+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
8392+ FiMustWriteLock(file);
8393+
8394+ err = 0;
8395+ finfo = au_fi(file);
8396+ inode = dentry->d_inode;
8397+ sb = dentry->d_sb;
8398+ mnt_flags = au_mntflags(sb);
8399+ pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
8400+ if (au_opt_test(mnt_flags, UDBA_INOTIFY))
8401+ au_fset_pin(pin_flags, DO_GPARENT);
8402+ again:
8403+ bstart = au_ibstart(inode);
8404+ if (bstart == finfo->fi_bstart)
8405+ goto out;
8406+
8407+ new_bstart = bstart;
8408+ parent = dget_parent(dentry);
8409+ dir = parent->d_inode;
8410+ if (au_test_ro(sb, bstart, inode)) {
8411+ di_read_lock_parent(parent, !AuLock_IR);
8412+ err = AuWbrCopyup(au_sbi(sb), dentry);
8413+ new_bstart = err;
8414+ di_read_unlock(parent, !AuLock_IR);
8415+ if (unlikely(err < 0))
8416+ goto out_dput;
8417+ err = 0;
8418+ }
8419+ /* someone else might change our inode while we were sleeping */
8420+ /* todo: test more? */
8421+ if (bstart != au_ibstart(inode)) {
8422+ err = 0;
8423+ dput(parent);
8424+ goto again;
8425+ }
8426+ di_read_lock_parent(parent, AuLock_IR);
8427+ bstart = new_bstart;
8428+
8429+ hi_wh = au_hi_wh(inode, bstart);
8430+ if (au_opt_test(mnt_flags, PLINK)
8431+ && au_plink_test(sb, inode)
8432+ && !d_unhashed(dentry)) {
8433+ err = au_test_and_cpup_dirs(dentry, bstart);
8434+ if (unlikely(err))
8435+ goto out_unlock;
8436+
8437+ /* always superio. */
8438+#if 1
8439+ err = au_pin(&pin, dentry, bstart, pin_flags);
8440+ if (!err)
8441+ err = au_sio_cpup_simple(dentry, bstart, -1,
8442+ AuCpup_DTIME);
8443+ au_unpin(&pin);
8444+#else /* reserved for future use */
8445+ if (!au_test_wkq(current)) {
8446+ int wkq_err;
8447+ struct cpup_pseudo_link_args args = {
8448+ .errp = &err,
8449+ .dentry = dentry,
8450+ .bdst = bstart,
8451+ .do_lock = 1
8452+ };
8453+ wkq_err = au_wkq_wait(call_cpup_pseudo_link, &args);
8454+ if (unlikely(wkq_err))
8455+ err = wkq_err;
8456+ } else
8457+ err = cpup_pseudo_link(dentry, bstart, /*do_lock*/1);
8458+#endif
8459+ } else if (hi_wh) {
8460+ /* already copied-up after unlink */
8461+ dinfo = au_di(dentry);
8462+ old_bstart = dinfo->di_bstart;
8463+ dinfo->di_bstart = bstart;
8464+ old_h_dentry = dinfo->di_hdentry[0 + bstart].hd_dentry;
8465+ dinfo->di_hdentry[0 + bstart].hd_dentry = hi_wh;
8466+ err = au_reopen_nondir(file);
8467+ dinfo->di_hdentry[0 + bstart].hd_dentry = old_h_dentry;
8468+ dinfo->di_bstart = old_bstart;
8469+ *need_reopen = 0;
8470+ }
8471+
8472+ out_unlock:
8473+ di_read_unlock(parent, AuLock_IR);
8474+ out_dput:
8475+ dput(parent);
8476+ out:
8477+ AuTraceErr(err);
8478+ return err;
8479+}
8480+
8481+/*
8482+ * after branch manipulating, refresh the file.
8483+ */
8484+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
8485+{
8486+ int err, new_sz, need_reopen;
8487+ struct dentry *dentry;
8488+ aufs_bindex_t bend, bindex, brid;
8489+ struct au_hfile *p;
8490+ struct au_finfo *finfo;
8491+ struct super_block *sb;
8492+ struct inode *inode;
8493+
8494+ dentry = file->f_dentry;
8495+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
8496+ FiMustWriteLock(file);
8497+ DiMustAnyLock(dentry);
8498+ inode = dentry->d_inode;
8499+ IiMustAnyLock(inode);
8500+
8501+ err = -ENOMEM;
8502+ sb = dentry->d_sb;
8503+ finfo = au_fi(file);
8504+ new_sz = sizeof(*finfo->fi_hfile) * (au_sbend(sb) + 1);
8505+ p = au_kzrealloc(finfo->fi_hfile, sizeof(*p) * (finfo->fi_bend + 1),
8506+ new_sz, GFP_NOFS);
8507+ if (unlikely(!p))
8508+ goto out;
8509+ finfo->fi_hfile = p;
8510+
8511+ p += finfo->fi_bstart;
8512+ brid = p->hf_br->br_id;
8513+ bend = finfo->fi_bend;
8514+ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) {
8515+ struct au_hfile tmp, *q;
8516+ aufs_bindex_t new_bindex;
8517+
8518+ if (!p->hf_file)
8519+ continue;
8520+ new_bindex = au_find_bindex(sb, p->hf_br);
8521+ if (new_bindex == bindex)
8522+ continue;
8523+ /* todo: test more? */
8524+ if (new_bindex < 0) {
8525+ au_set_h_fptr(file, bindex, NULL);
8526+ continue;
8527+ }
8528+
8529+ /* swap two hidden inode, and loop again */
8530+ q = finfo->fi_hfile + new_bindex;
8531+ tmp = *q;
8532+ *q = *p;
8533+ *p = tmp;
8534+ if (tmp.hf_file) {
8535+ bindex--;
8536+ p--;
8537+ }
8538+ }
8539+ {
8540+ aufs_bindex_t s = finfo->fi_bstart, e = finfo->fi_bend;
8541+ finfo->fi_bstart = 0;
8542+ finfo->fi_bend = au_sbend(sb);
8543+ finfo->fi_bstart = s;
8544+ finfo->fi_bend = e;
8545+ }
8546+
8547+ p = finfo->fi_hfile;
8548+ if (!au_test_mmapped(file) && !d_unhashed(dentry)) {
8549+ bend = au_sbend(sb);
8550+ for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
8551+ finfo->fi_bstart++, p++)
8552+ if (p->hf_file) {
8553+ if (p->hf_file->f_dentry
8554+ && p->hf_file->f_dentry->d_inode)
8555+ break;
8556+ else
8557+ au_hfput(p);
8558+ }
8559+ } else {
8560+ bend = au_br_index(sb, brid);
8561+ for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
8562+ finfo->fi_bstart++, p++)
8563+ if (p->hf_file)
8564+ au_hfput(p);
8565+ bend = au_sbend(sb);
8566+ }
8567+
8568+ p = finfo->fi_hfile + bend;
8569+ for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
8570+ finfo->fi_bend--, p--)
8571+ if (p->hf_file) {
8572+ if (p->hf_file->f_dentry
8573+ && p->hf_file->f_dentry->d_inode)
8574+ break;
8575+ else
8576+ au_hfput(p);
8577+ }
8578+ AuDebugOn(finfo->fi_bend < finfo->fi_bstart);
8579+
8580+ err = 0;
8581+ need_reopen = 1;
8582+ if (!au_test_mmapped(file))
8583+ err = au_file_refresh_by_inode(file, &need_reopen);
8584+ if (!err && need_reopen && !d_unhashed(dentry))
8585+ err = reopen(file);
8586+ if (!err) {
8587+ au_update_figen(file);
8588+ return 0; /* success */
8589+ }
8590+
8591+ /* error, close all hidden files */
8592+ bend = au_fbend(file);
8593+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
8594+ au_set_h_fptr(file, bindex, NULL);
8595+
8596+ out:
8597+ AuTraceErr(err);
8598+ return err;
8599+}
8600+
8601+/* common function to regular file and dir */
8602+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8603+ int wlock, int locked)
8604+{
8605+ int err;
8606+ struct dentry *dentry;
8607+ struct super_block *sb;
8608+ aufs_bindex_t bstart;
8609+ unsigned char pseudo_link;
8610+ au_gen_t sgen, fgen;
8611+
8612+ dentry = file->f_dentry;
8613+ LKTRTrace("%.*s, w %d, l %d\n", AuDLNPair(dentry), wlock, locked);
8614+ sb = dentry->d_sb;
8615+ SiMustAnyLock(sb);
8616+
8617+ err = 0;
8618+ sgen = au_sigen(sb);
8619+ fi_write_lock(file);
8620+ fgen = au_figen(file);
8621+ di_write_lock_child(dentry);
8622+ bstart = au_dbstart(dentry);
8623+ pseudo_link = (bstart != au_ibstart(dentry->d_inode));
8624+ if (sgen == fgen && !pseudo_link && au_fbstart(file) == bstart) {
8625+ if (!wlock) {
8626+ di_downgrade_lock(dentry, AuLock_IR);
8627+ fi_downgrade_lock(file);
8628+ }
8629+ goto out; /* success */
8630+ }
8631+
8632+ LKTRTrace("sgen %d, fgen %d\n", sgen, fgen);
8633+ if (sgen != au_digen(dentry)
8634+ || sgen != au_iigen(dentry->d_inode)) {
8635+ /*
8636+ * d_path() and path_lookup() is a simple and good approach
8637+ * to revalidate. but si_rwsem in DEBUG_RWSEM will cause a
8638+ * deadlock. removed the code.
8639+ */
8640+ err = au_reval_dpath(dentry, sgen);
8641+ if (unlikely(err < 0))
8642+ goto out;
8643+ AuDebugOn(au_digen(dentry) != sgen
8644+ || au_iigen(dentry->d_inode) != sgen);
8645+ }
8646+
8647+ err = refresh_file(file, reopen
8648+ /* , au_opt_test(au_mnt_flags(sb), REFROF) */);
8649+ if (!err) {
8650+ if (!wlock) {
8651+ di_downgrade_lock(dentry, AuLock_IR);
8652+ fi_downgrade_lock(file);
8653+ }
8654+ } else {
8655+ di_write_unlock(dentry);
8656+ fi_write_unlock(file);
8657+ }
8658+
8659+ out:
8660+ AuTraceErr(err);
8661+ return err;
8662+}
8663+
8664+/* ---------------------------------------------------------------------- */
8665+
8666+/* cf. aufs_nopage() */
8667+/* for madvise(2) */
8668+static int aufs_readpage(struct file *file, struct page *page)
8669+{
8670+ AuTraceEnter();
8671+ unlock_page(page);
8672+ return 0;
8673+}
8674+
8675+/* they will never be called. */
8676+#ifdef CONFIG_AUFS_DEBUG
8677+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
8678+static int aufs_prepare_write(struct file *file, struct page *page,
8679+ unsigned from, unsigned to)
8680+{ AuUnsupport(); return 0; }
8681+static int aufs_commit_write(struct file *file, struct page *page,
8682+ unsigned from, unsigned to)
8683+{ AuUnsupport(); return 0; }
8684+#endif
8685+static int aufs_write_begin(struct file *file, struct address_space *mapping,
8686+ loff_t pos, unsigned len, unsigned flags,
8687+ struct page **pagep, void **fsdata)
8688+{ AuUnsupport(); return 0; }
8689+static int aufs_write_end(struct file *file, struct address_space *mapping,
8690+ loff_t pos, unsigned len, unsigned copied,
8691+ struct page *page, void *fsdata)
8692+{ AuUnsupport(); return 0; }
8693+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
8694+{ AuUnsupport(); return 0; }
8695+static void aufs_sync_page(struct page *page)
8696+{ AuUnsupport(); }
8697+
8698+static int aufs_set_page_dirty(struct page *page)
8699+{ AuUnsupport(); return 0; }
8700+static void aufs_invalidatepage(struct page *page, unsigned long offset)
8701+{ AuUnsupport(); }
8702+static int aufs_releasepage(struct page *page, gfp_t gfp)
8703+{ AuUnsupport(); return 0; }
8704+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
8705+ const struct iovec *iov, loff_t offset,
8706+ unsigned long nr_segs)
8707+{ AuUnsupport(); return 0; }
8708+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
8709+static struct page *aufs_get_xip_page(struct address_space *mapping,
8710+ sector_t offset, int create)
8711+{ AuUnsupport(); return NULL; }
8712+#endif
8713+#endif /* CONFIG_AUFS_DEBUG */
8714+
8715+struct address_space_operations aufs_aop = {
8716+ .readpage = aufs_readpage,
8717+#ifdef CONFIG_AUFS_DEBUG
8718+ .writepage = aufs_writepage,
8719+ .sync_page = aufs_sync_page,
8720+ .set_page_dirty = aufs_set_page_dirty,
8721+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
8722+ .prepare_write = aufs_prepare_write,
8723+ .commit_write = aufs_commit_write,
8724+#endif
8725+ .write_begin = aufs_write_begin,
8726+ .write_end = aufs_write_end,
8727+ .invalidatepage = aufs_invalidatepage,
8728+ .releasepage = aufs_releasepage,
8729+ .direct_IO = aufs_direct_IO,
8730+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
8731+ .get_xip_page = aufs_get_xip_page,
8732+#endif
8733+#endif /* CONFIG_AUFS_DEBUG */
8734+};
8735diff -urN linux/fs/aufs/file.h linux-aufs/fs/aufs/file.h
8736--- linux/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
8737+++ linux-aufs/fs/aufs/file.h 2009-03-12 16:18:04.000000000 +0100
8738@@ -0,0 +1,257 @@
8739+/*
8740+ * Copyright (C) 2005-2009 Junjiro Okajima
8741+ *
8742+ * This program, aufs is free software; you can redistribute it and/or modify
8743+ * it under the terms of the GNU General Public License as published by
8744+ * the Free Software Foundation; either version 2 of the License, or
8745+ * (at your option) any later version.
8746+ *
8747+ * This program is distributed in the hope that it will be useful,
8748+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8749+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8750+ * GNU General Public License for more details.
8751+ *
8752+ * You should have received a copy of the GNU General Public License
8753+ * along with this program; if not, write to the Free Software
8754+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8755+ */
8756+
8757+/*
8758+ * file operations
8759+ *
8760+ * $Id$
8761+ */
8762+
8763+#ifndef __AUFS_FILE_H__
8764+#define __AUFS_FILE_H__
8765+
8766+#ifdef __KERNEL__
8767+
8768+#include <linux/file.h>
8769+#include <linux/fs.h>
8770+#include <linux/mm.h>
8771+#include <linux/aufs_type.h>
8772+#include "dentry.h"
8773+#include "misc.h"
8774+#include "super.h"
8775+
8776+/* ---------------------------------------------------------------------- */
8777+
8778+struct au_branch;
8779+struct au_hfile {
8780+ struct file *hf_file;
8781+ struct au_branch *hf_br;
8782+};
8783+
8784+struct au_vdir;
8785+struct au_finfo {
8786+ atomic_t fi_generation;
8787+
8788+ struct au_rwsem fi_rwsem;
8789+ struct au_hfile *fi_hfile;
8790+ aufs_bindex_t fi_bstart, fi_bend;
8791+
8792+ union {
8793+ struct vm_operations_struct *fi_h_vm_ops;
8794+ struct au_vdir *fi_vdir_cache;
8795+ };
8796+};
8797+
8798+/* ---------------------------------------------------------------------- */
8799+
8800+/* file.c */
8801+extern struct address_space_operations aufs_aop;
8802+unsigned int au_file_roflags(unsigned int flags);
8803+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8804+ struct file *file);
8805+int au_do_open(struct inode *inode, struct file *file,
8806+ int (*open)(struct file *file, int flags));
8807+int au_reopen_nondir(struct file *file);
8808+struct au_pin;
8809+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
8810+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8811+ int wlock, int locked);
8812+
8813+/* f_op.c */
8814+extern struct file_operations aufs_file_fop;
8815+int aufs_flush(struct file *file, fl_owner_t id);
8816+
8817+/* finfo.c */
8818+struct au_finfo *au_fi(struct file *file);
8819+struct au_branch *au_fbr(struct file *file, aufs_bindex_t bindex);
8820+struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex);
8821+
8822+void au_hfput(struct au_hfile *hf);
8823+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
8824+ struct file *h_file);
8825+
8826+void au_finfo_fin(struct file *file);
8827+int au_finfo_init(struct file *file);
8828+
8829+#ifdef CONFIG_AUFS_ROBR
8830+/* robr.c */
8831+struct file *au_robr_safe_file(struct vm_area_struct *vma);
8832+void au_robr_reset_file(struct vm_area_struct *vma, struct file *file);
8833+#else
8834+static inline struct file *au_robr_safe_file(struct vm_area_struct *vma)
8835+{
8836+ struct file *file;
8837+
8838+ file = vma->vm_file;
8839+ if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
8840+ return file;
8841+ return NULL;
8842+}
8843+
8844+static inline
8845+void au_robr_reset_file(struct vm_area_struct *vma, struct file *file)
8846+{
8847+ vma->vm_file = file;
8848+ /* smp_mb(); */ /* flush vm_file */
8849+}
8850+#endif /* CONFIG_AUFS_ROBR */
8851+
8852+#if 0 /* reserved for future use */
8853+/* ioctl.c */
8854+long aufs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
8855+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
8856+#endif
8857+
8858+/* ---------------------------------------------------------------------- */
8859+
8860+/* todo: memory barrier? */
8861+static inline au_gen_t au_figen(struct file *f)
8862+{
8863+ return atomic_read(&au_fi(f)->fi_generation);
8864+}
8865+
8866+static inline int au_test_mmapped(struct file *f)
8867+{
8868+ return !!(au_fi(f)->fi_h_vm_ops);
8869+}
8870+
8871+static inline int au_test_aufs_file(struct file *f)
8872+{
8873+ return !(f->f_dentry->d_inode->i_mode
8874+ & (S_IFCHR | S_IFBLK | S_IFIFO | S_IFSOCK));
8875+}
8876+
8877+/* ---------------------------------------------------------------------- */
8878+
8879+#if !defined(CONFIG_AUFS_MODULE) || defined(CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH)
8880+int au_store_fmode_exec(struct nameidata *nd, struct inode *inode);
8881+
8882+static inline int au_deny_write_access(struct file *h_file)
8883+{
8884+ LKTRTrace("%.*s\n", AuDLNPair(h_file->f_dentry));
8885+ return deny_write_access(h_file);
8886+}
8887+
8888+static inline void au_allow_write_access(struct file *h_file)
8889+{
8890+ allow_write_access(h_file);
8891+}
8892+
8893+#else
8894+
8895+static inline int au_store_fmode_exec(struct nameidata *nd, struct inode *inode)
8896+{
8897+ /* nothing */
8898+ return 0;
8899+}
8900+
8901+static inline int au_deny_write_access(struct file *h_file)
8902+{
8903+ /* nothing */
8904+ return 0;
8905+}
8906+
8907+static inline void au_allow_write_access(struct file *h_file)
8908+{
8909+ /* nothing */
8910+}
8911+#endif /* CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH */
8912+
8913+/* ---------------------------------------------------------------------- */
8914+
8915+/*
8916+ * fi_read_lock, fi_write_lock,
8917+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
8918+ */
8919+AuSimpleRwsemFuncs(fi, struct file *f, au_fi(f)->fi_rwsem);
8920+
8921+/* to debug easier, do not make them inlined functions */
8922+#define FiMustReadLock(f) do { \
8923+ SiMustAnyLock((f)->f_dentry->d_sb); \
8924+ AuRwMustReadLock(&au_fi(f)->fi_rwsem); \
8925+} while (0)
8926+
8927+#define FiMustWriteLock(f) do { \
8928+ SiMustAnyLock((f)->f_dentry->d_sb); \
8929+ AuRwMustWriteLock(&au_fi(f)->fi_rwsem); \
8930+} while (0)
8931+
8932+#define FiMustAnyLock(f) do { \
8933+ SiMustAnyLock((f)->f_dentry->d_sb); \
8934+ AuRwMustAnyLock(&au_fi(f)->fi_rwsem); \
8935+} while (0)
8936+
8937+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
8938+
8939+/* ---------------------------------------------------------------------- */
8940+
8941+/* todo: hard/soft set? */
8942+static inline aufs_bindex_t au_fbstart(struct file *file)
8943+{
8944+ FiMustAnyLock(file);
8945+ return au_fi(file)->fi_bstart;
8946+}
8947+
8948+static inline aufs_bindex_t au_fbend(struct file *file)
8949+{
8950+ FiMustAnyLock(file);
8951+ return au_fi(file)->fi_bend;
8952+}
8953+
8954+static inline struct au_vdir *au_fvdir_cache(struct file *file)
8955+{
8956+#ifdef CONFIG_AUFS_EXPORT
8957+ AuRwMustAnyLock(&au_fi(file)->fi_rwsem);
8958+#else
8959+ FiMustAnyLock(file);
8960+#endif
8961+ return au_fi(file)->fi_vdir_cache;
8962+}
8963+
8964+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
8965+{
8966+ FiMustWriteLock(file);
8967+ AuDebugOn(au_sbend(file->f_dentry->d_sb) < bindex);
8968+ au_fi(file)->fi_bstart = bindex;
8969+}
8970+
8971+static inline void au_set_fbend(struct file *file, aufs_bindex_t bindex)
8972+{
8973+ FiMustWriteLock(file);
8974+ AuDebugOn(au_sbend(file->f_dentry->d_sb) < bindex
8975+ || bindex < au_fbstart(file));
8976+ au_fi(file)->fi_bend = bindex;
8977+}
8978+
8979+static inline void au_set_fvdir_cache(struct file *file,
8980+ struct au_vdir *vdir_cache)
8981+{
8982+ FiMustWriteLock(file);
8983+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode)
8984+ || (au_fi(file)->fi_vdir_cache && vdir_cache));
8985+ au_fi(file)->fi_vdir_cache = vdir_cache;
8986+}
8987+
8988+static inline void au_update_figen(struct file *file)
8989+{
8990+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
8991+ /* smp_mb(); */ /* atomic_set */
8992+}
8993+
8994+#endif /* __KERNEL__ */
8995+#endif /* __AUFS_FILE_H__ */
8996diff -urN linux/fs/aufs/finfo.c linux-aufs/fs/aufs/finfo.c
8997--- linux/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
8998+++ linux-aufs/fs/aufs/finfo.c 2009-03-12 16:18:04.000000000 +0100
8999@@ -0,0 +1,186 @@
9000+/*
9001+ * Copyright (C) 2005-2009 Junjiro Okajima
9002+ *
9003+ * This program, aufs is free software; you can redistribute it and/or modify
9004+ * it under the terms of the GNU General Public License as published by
9005+ * the Free Software Foundation; either version 2 of the License, or
9006+ * (at your option) any later version.
9007+ *
9008+ * This program is distributed in the hope that it will be useful,
9009+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9010+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9011+ * GNU General Public License for more details.
9012+ *
9013+ * You should have received a copy of the GNU General Public License
9014+ * along with this program; if not, write to the Free Software
9015+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9016+ */
9017+
9018+/*
9019+ * file private data
9020+ *
9021+ * $Id$
9022+ */
9023+
9024+#include "aufs.h"
9025+
9026+struct au_finfo *au_fi(struct file *file)
9027+{
9028+ struct au_finfo *finfo = file->private_data;
9029+ AuDebugOn(!finfo
9030+ || !finfo->fi_hfile
9031+ || (0 < finfo->fi_bend
9032+ && (/* au_sbi(file->f_dentry->d_sb)->si_bend
9033+ < finfo->fi_bend
9034+ || */ finfo->fi_bend < finfo->fi_bstart)));
9035+ return finfo;
9036+}
9037+
9038+struct au_branch *au_fbr(struct file *file, aufs_bindex_t bindex)
9039+{
9040+ struct au_finfo *finfo = au_fi(file);
9041+ struct au_hfile *hf;
9042+
9043+ FiMustAnyLock(file);
9044+ AuDebugOn(!finfo
9045+ || finfo->fi_bstart < 0
9046+ || bindex < finfo->fi_bstart
9047+ || finfo->fi_bend < bindex);
9048+ hf = finfo->fi_hfile + bindex;
9049+ AuDebugOn(hf->hf_br && au_br_count(hf->hf_br) <= 0);
9050+ return hf->hf_br;
9051+}
9052+
9053+struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex)
9054+{
9055+ struct au_finfo *finfo = au_fi(file);
9056+ struct au_hfile *hf;
9057+
9058+ FiMustAnyLock(file);
9059+ AuDebugOn(!finfo
9060+ || finfo->fi_bstart < 0
9061+ || bindex < finfo->fi_bstart
9062+ || finfo->fi_bend < bindex);
9063+ hf = finfo->fi_hfile + bindex;
9064+ AuDebugOn(hf->hf_file
9065+ && file_count(hf->hf_file) <= 0
9066+ && au_br_count(hf->hf_br) <= 0);
9067+ return hf->hf_file;
9068+}
9069+
9070+void au_hfput(struct au_hfile *hf)
9071+{
9072+ if (hf->hf_file->f_mode & FMODE_EXEC)
9073+ au_allow_write_access(hf->hf_file);
9074+ fput(hf->hf_file);
9075+ hf->hf_file = NULL;
9076+ AuDebugOn(!hf->hf_br);
9077+ au_br_put(hf->hf_br);
9078+ hf->hf_br = NULL;
9079+}
9080+
9081+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
9082+{
9083+ struct au_finfo *finfo = au_fi(file);
9084+ struct au_hfile *hf;
9085+
9086+ FiMustWriteLock(file);
9087+ AuDebugOn(!finfo
9088+ || finfo->fi_bstart < 0
9089+ || bindex < finfo->fi_bstart
9090+ || finfo->fi_bend < bindex);
9091+ AuDebugOn(val && file_count(val) <= 0);
9092+ hf = finfo->fi_hfile + bindex;
9093+ AuDebugOn(val && hf->hf_file);
9094+ if (hf->hf_file)
9095+ au_hfput(hf);
9096+ if (val) {
9097+ hf->hf_file = val;
9098+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
9099+ }
9100+}
9101+
9102+void au_finfo_fin(struct file *file)
9103+{
9104+ struct au_finfo *finfo;
9105+ struct dentry *dentry;
9106+ aufs_bindex_t bindex, bend;
9107+
9108+ dentry = file->f_dentry;
9109+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
9110+ SiMustAnyLock(dentry->d_sb);
9111+
9112+ fi_write_lock(file);
9113+ bend = au_fbend(file);
9114+ bindex = au_fbstart(file);
9115+ if (bindex >= 0)
9116+ for (; bindex <= bend; bindex++)
9117+ au_set_h_fptr(file, bindex, NULL);
9118+
9119+ finfo = au_fi(file);
9120+#ifdef CONFIG_AUFS_DEBUG
9121+ if (finfo->fi_bstart >= 0) {
9122+ bend = au_fbend(file);
9123+ for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
9124+ struct au_hfile *hf;
9125+ hf = finfo->fi_hfile + bindex;
9126+ AuDebugOn(hf->hf_file || hf->hf_br);
9127+ }
9128+ }
9129+#endif
9130+
9131+ kfree(finfo->fi_hfile);
9132+ fi_write_unlock(file);
9133+ au_rwsem_destroy(&finfo->fi_rwsem);
9134+ au_cache_free_finfo(finfo);
9135+}
9136+
9137+int au_finfo_init(struct file *file)
9138+{
9139+ struct au_finfo *finfo;
9140+ struct dentry *dentry;
9141+ union {
9142+ void *p;
9143+ unsigned long ul;
9144+ } u;
9145+
9146+ dentry = file->f_dentry;
9147+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
9148+ AuDebugOn(!dentry->d_inode);
9149+
9150+ finfo = au_cache_alloc_finfo();
9151+ if (finfo) {
9152+ finfo->fi_hfile = kcalloc(au_sbend(dentry->d_sb) + 1,
9153+ sizeof(*finfo->fi_hfile), GFP_NOFS);
9154+ if (finfo->fi_hfile) {
9155+ au_rw_init_wlock(&finfo->fi_rwsem);
9156+ //au_dbg_lock_fi_reg(file);
9157+ finfo->fi_bstart = -1;
9158+ finfo->fi_bend = -1;
9159+ atomic_set(&finfo->fi_generation, au_digen(dentry));
9160+ /* smp_mb(); */ /* atomic_set */
9161+
9162+ /*
9163+ * a dirty trick for handling FMODE_EXEC and
9164+ * deny_write_access().
9165+ * because FMODE_EXEC flag is not passed to
9166+ * f_op->open(),
9167+ * aufs set it to file->private_data temporary in lookup
9168+ * or dentry revalidation operations.
9169+ * restore the flag to f_mode here.
9170+ */
9171+ u.p = file->private_data;
9172+ if (u.ul & FMODE_EXEC) {
9173+ file->f_mode |= FMODE_EXEC;
9174+ smp_mb(); /* flush f_mode */
9175+ }
9176+
9177+ file->private_data = finfo;
9178+ return 0; /* success */
9179+ }
9180+ au_cache_free_finfo(finfo);
9181+ }
9182+
9183+ AuTraceErr(-ENOMEM);
9184+ return -ENOMEM;
9185+}
9186diff -urN linux/fs/aufs/f_op.c linux-aufs/fs/aufs/f_op.c
9187--- linux/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
9188+++ linux-aufs/fs/aufs/f_op.c 2009-03-12 16:18:04.000000000 +0100
9189@@ -0,0 +1,673 @@
9190+/*
9191+ * Copyright (C) 2005-2009 Junjiro Okajima
9192+ *
9193+ * This program, aufs is free software; you can redistribute it and/or modify
9194+ * it under the terms of the GNU General Public License as published by
9195+ * the Free Software Foundation; either version 2 of the License, or
9196+ * (at your option) any later version.
9197+ *
9198+ * This program is distributed in the hope that it will be useful,
9199+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9200+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9201+ * GNU General Public License for more details.
9202+ *
9203+ * You should have received a copy of the GNU General Public License
9204+ * along with this program; if not, write to the Free Software
9205+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9206+ */
9207+
9208+/*
9209+ * file and vm operations
9210+ *
9211+ * $Id$
9212+ */
9213+
9214+#include <linux/fs_stack.h>
9215+#include <linux/poll.h>
9216+#include "aufs.h"
9217+
9218+/* common function to regular file and dir */
9219+int aufs_flush(struct file *file, fl_owner_t id)
9220+{
9221+ int err;
9222+ struct dentry *dentry;
9223+ aufs_bindex_t bindex, bend;
9224+ struct file *h_file;
9225+
9226+ dentry = file->f_dentry;
9227+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
9228+
9229+ si_noflush_read_lock(dentry->d_sb);
9230+ fi_read_lock(file);
9231+ di_read_lock_child(dentry, AuLock_IW);
9232+
9233+ err = 0;
9234+ bend = au_fbend(file);
9235+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
9236+ h_file = au_h_fptr(file, bindex);
9237+ if (h_file && h_file->f_op && h_file->f_op->flush) {
9238+ err = h_file->f_op->flush(h_file, id);
9239+ if (!err)
9240+ au_update_fuse_h_inode
9241+ (h_file->f_vfsmnt, h_file->f_dentry);
9242+ /*ignore*/
9243+ }
9244+ }
9245+ au_cpup_attr_timesizes(dentry->d_inode);
9246+
9247+ di_read_unlock(dentry, AuLock_IW);
9248+ fi_read_unlock(file);
9249+ si_read_unlock(dentry->d_sb);
9250+ AuTraceErr(err);
9251+ return err;
9252+}
9253+
9254+/* ---------------------------------------------------------------------- */
9255+
9256+static int do_open_nondir(struct file *file, int flags)
9257+{
9258+ int err;
9259+ aufs_bindex_t bindex;
9260+ struct super_block *sb;
9261+ struct file *h_file;
9262+ struct dentry *dentry;
9263+ struct inode *inode;
9264+ struct au_finfo *finfo;
9265+
9266+ dentry = file->f_dentry;
9267+ LKTRTrace("%.*s, flags 0%o\n", AuDLNPair(dentry), flags);
9268+ FiMustWriteLock(file);
9269+ inode = dentry->d_inode;
9270+ AuDebugOn(!inode || S_ISDIR(inode->i_mode));
9271+
9272+ err = 0;
9273+ finfo = au_fi(file);
9274+ finfo->fi_h_vm_ops = NULL;
9275+ sb = dentry->d_sb;
9276+ bindex = au_dbstart(dentry);
9277+ AuDebugOn(!au_h_dptr(dentry, bindex)->d_inode);
9278+ /* O_TRUNC is processed already */
9279+ BUG_ON(au_test_ro(sb, bindex, inode) && (flags & O_TRUNC));
9280+
9281+ h_file = au_h_open(dentry, bindex, flags, file);
9282+ if (IS_ERR(h_file))
9283+ err = PTR_ERR(h_file);
9284+ else {
9285+ au_set_fbstart(file, bindex);
9286+ au_set_fbend(file, bindex);
9287+ au_set_h_fptr(file, bindex, h_file);
9288+ au_update_figen(file);
9289+ /* todo: necessary? */
9290+ /* file->f_ra = h_file->f_ra; */
9291+ err = 0;
9292+ }
9293+ AuTraceErr(err);
9294+ return err;
9295+}
9296+
9297+static int aufs_open_nondir(struct inode *inode, struct file *file)
9298+{
9299+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry));
9300+
9301+ return au_do_open(inode, file, do_open_nondir);
9302+}
9303+
9304+static int aufs_release_nondir(struct inode *inode, struct file *file)
9305+{
9306+ struct super_block *sb = file->f_dentry->d_sb;
9307+
9308+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(file->f_dentry));
9309+
9310+ si_noflush_read_lock(sb);
9311+ au_finfo_fin(file);
9312+ si_read_unlock(sb);
9313+ return 0;
9314+}
9315+
9316+/* ---------------------------------------------------------------------- */
9317+
9318+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
9319+ loff_t *ppos)
9320+{
9321+ ssize_t err;
9322+ struct dentry *dentry;
9323+ struct file *h_file;
9324+ struct super_block *sb;
9325+ struct inode *h_inode;
9326+
9327+ dentry = file->f_dentry;
9328+ LKTRTrace("%.*s, cnt %zu, pos %lld\n", AuDLNPair(dentry), count, *ppos);
9329+
9330+ sb = dentry->d_sb;
9331+ si_read_lock(sb, AuLock_FLUSH);
9332+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0,
9333+ /*locked*/0);
9334+ if (unlikely(err))
9335+ goto out;
9336+
9337+ /* support LSM and notify */
9338+ h_file = au_h_fptr(file, au_fbstart(file));
9339+ h_inode = h_file->f_dentry->d_inode;
9340+ err = vfsub_read_u(h_file, buf, count, ppos,
9341+ au_test_dlgt(au_mntflags(sb)));
9342+ /* todo: necessary? */
9343+ /* file->f_ra = h_file->f_ra; */
9344+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9345+
9346+ di_read_unlock(dentry, AuLock_IR);
9347+ fi_read_unlock(file);
9348+ out:
9349+ si_read_unlock(sb);
9350+ AuTraceErr(err);
9351+ return err;
9352+}
9353+
9354+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
9355+ size_t count, loff_t *ppos)
9356+{
9357+ ssize_t err;
9358+ struct dentry *dentry;
9359+ struct inode *inode;
9360+ struct super_block *sb;
9361+ unsigned int mnt_flags;
9362+ struct file *h_file;
9363+ char __user *buf = (char __user *)ubuf;
9364+ struct au_hin_ignore ign;
9365+ struct vfsub_args vargs;
9366+ aufs_bindex_t bstart;
9367+ int hinotify;
9368+ struct au_pin pin;
9369+
9370+ dentry = file->f_dentry;
9371+ LKTRTrace("%.*s, cnt %zu, pos %lld\n", AuDLNPair(dentry), count, *ppos);
9372+
9373+ inode = dentry->d_inode;
9374+ mutex_lock(&inode->i_mutex);
9375+ sb = dentry->d_sb;
9376+ si_read_lock(sb, AuLock_FLUSH);
9377+ mnt_flags = au_mntflags(sb);
9378+ hinotify = !!au_opt_test(mnt_flags, UDBA_INOTIFY);
9379+ vfsub_args_init(&vargs, &ign, au_test_dlgt(mnt_flags), 0);
9380+
9381+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
9382+ /*locked*/1);
9383+ if (unlikely(err))
9384+ goto out;
9385+ err = au_ready_to_write(file, -1, &pin);
9386+ di_downgrade_lock(dentry, AuLock_IR);
9387+ if (unlikely(err))
9388+ goto out_unlock;
9389+
9390+ bstart = au_fbstart(file);
9391+ h_file = au_h_fptr(file, bstart);
9392+ if (!hinotify) {
9393+ au_unpin(&pin);
9394+ err = vfsub_write_u(h_file, buf, count, ppos, &vargs);
9395+ } else {
9396+ vfsub_ign_hinode(&vargs, IN_MODIFY, au_pinned_hdir(&pin));
9397+ err = vfsub_write_u(h_file, buf, count, ppos, &vargs);
9398+ au_unpin(&pin);
9399+ }
9400+ au_cpup_attr_timesizes(inode);
9401+
9402+ out_unlock:
9403+ di_read_unlock(dentry, AuLock_IR);
9404+ fi_write_unlock(file);
9405+ out:
9406+ si_read_unlock(sb);
9407+ mutex_unlock(&inode->i_mutex);
9408+ AuTraceErr(err);
9409+ return err;
9410+}
9411+
9412+#ifdef CONFIG_AUFS_SPLICE_PATCH
9413+static int au_test_loopback(void)
9414+{
9415+ const char c = current->comm[4];
9416+ /* true if a kernel thread named 'loop[0-9].*' accesses a file */
9417+ const int loopback = (current->mm == NULL
9418+ && '0' <= c && c <= '9'
9419+ && strncmp(current->comm, "loop", 4) == 0);
9420+ return loopback;
9421+}
9422+
9423+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
9424+ struct pipe_inode_info *pipe, size_t len,
9425+ unsigned int flags)
9426+{
9427+ ssize_t err;
9428+ struct file *h_file;
9429+ struct dentry *dentry;
9430+ struct super_block *sb;
9431+
9432+ dentry = file->f_dentry;
9433+ LKTRTrace("%.*s, pos %lld, len %zu\n", AuDLNPair(dentry), *ppos, len);
9434+
9435+ sb = dentry->d_sb;
9436+ si_read_lock(sb, AuLock_FLUSH);
9437+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0,
9438+ /*locked*/0);
9439+ if (unlikely(err))
9440+ goto out;
9441+
9442+ err = -EINVAL;
9443+ /* support LSM and notify */
9444+ h_file = au_h_fptr(file, au_fbstart(file));
9445+ if (au_test_loopback()) {
9446+ file->f_mapping = h_file->f_mapping;
9447+ smp_mb(); /* unnecessary? */
9448+ }
9449+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags,
9450+ au_test_dlgt(au_mntflags(sb)));
9451+ /* todo: necessasry? */
9452+ /* file->f_ra = h_file->f_ra; */
9453+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9454+ di_read_unlock(dentry, AuLock_IR);
9455+ fi_read_unlock(file);
9456+
9457+ out:
9458+ si_read_unlock(sb);
9459+ AuTraceErr(err);
9460+ return err;
9461+}
9462+
9463+static ssize_t
9464+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
9465+ size_t len, unsigned int flags)
9466+{
9467+ ssize_t err;
9468+ struct dentry *dentry;
9469+ struct inode *inode, *h_inode;
9470+ struct super_block *sb;
9471+ struct file *h_file;
9472+ /* struct au_hin_ignore ign; */
9473+ struct vfsub_args vargs;
9474+ unsigned int mnt_flags;
9475+ struct au_pin pin;
9476+
9477+ dentry = file->f_dentry;
9478+ LKTRTrace("%.*s, len %zu, pos %lld\n", AuDLNPair(dentry), len, *ppos);
9479+
9480+ inode = dentry->d_inode;
9481+ mutex_lock(&inode->i_mutex);
9482+ sb = dentry->d_sb;
9483+ si_read_lock(sb, AuLock_FLUSH);
9484+ mnt_flags = au_mntflags(sb);
9485+ vfsub_args_init(&vargs, /*&ign*/NULL, au_test_dlgt(mnt_flags), 0);
9486+
9487+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
9488+ /*locked*/1);
9489+ if (unlikely(err))
9490+ goto out;
9491+ err = au_ready_to_write(file, -1, &pin);
9492+ di_downgrade_lock(dentry, AuLock_IR);
9493+ if (unlikely(err))
9494+ goto out_unlock;
9495+
9496+ /* support LSM and notify */
9497+ /* current vfs_splice_from() doesn't fire up the inotify event */
9498+ h_file = au_h_fptr(file, au_fbstart(file));
9499+ h_inode = h_file->f_dentry->d_inode;
9500+ if (1 || !au_opt_test(mnt_flags, UDBA_INOTIFY)) {
9501+ au_unpin(&pin);
9502+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags, &vargs);
9503+ }
9504+#if 0 /* reserved for future use */
9505+ else {
9506+ struct dentry *parent = dget_parent(dentry);
9507+ vfsub_ign_hinode(&vargs, IN_MODIFY, au_pinned_hdir(&pin));
9508+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags, &vargs);
9509+ au_unpin(&pin);
9510+ }
9511+#endif
9512+ au_cpup_attr_timesizes(inode);
9513+
9514+ out_unlock:
9515+ di_read_unlock(dentry, AuLock_IR);
9516+ fi_write_unlock(file);
9517+ out:
9518+ si_read_unlock(sb);
9519+ mutex_unlock(&inode->i_mutex);
9520+ AuTraceErr(err);
9521+ return err;
9522+}
9523+#endif /* CONFIG_AUFS_SPLICE_PATCH */
9524+
9525+/* ---------------------------------------------------------------------- */
9526+
9527+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
9528+{
9529+ int err;
9530+ struct dentry *dentry;
9531+ struct file *file, *h_file;
9532+ struct inode *inode;
9533+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9534+ struct au_finfo *finfo;
9535+
9536+ AuTraceEnter();
9537+ AuDebugOn(!vma || !vma->vm_file);
9538+ /* todo: non-robr mode, user vm_file as it is? */
9539+ wait_event(wq, (file = au_robr_safe_file(vma)));
9540+ AuDebugOn(!au_test_aufs(file->f_dentry->d_sb));
9541+ dentry = file->f_dentry;
9542+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
9543+ inode = dentry->d_inode;
9544+ AuDebugOn(!S_ISREG(inode->i_mode));
9545+
9546+ /* do not revalidate, no si lock */
9547+ finfo = au_fi(file);
9548+ h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
9549+ AuDebugOn(!h_file || !au_test_mmapped(file));
9550+ fi_write_lock(file);
9551+ vma->vm_file = h_file;
9552+ err = finfo->fi_h_vm_ops->fault(vma, vmf);
9553+ /* todo: necessary? */
9554+ /* file->f_ra = h_file->f_ra; */
9555+ au_robr_reset_file(vma, file);
9556+ fi_write_unlock(file);
9557+#if 0 /* def CONFIG_SMP */
9558+ /* wake_up_nr(&wq, online_cpu - 1); */
9559+ wake_up_all(&wq);
9560+#else
9561+ wake_up(&wq);
9562+#endif
9563+
9564+ if (!(err & VM_FAULT_ERROR)) {
9565+#if 0 /* debug */
9566+ struct page *page;
9567+ page = vmf->page;
9568+ AuDbg("%p, %d\n", page, page_mapcount(page));
9569+
9570+ page->mapping = file->f_mapping;
9571+ get_page(page);
9572+ file->f_mapping = h_file->f_mapping;
9573+ touch_atime(NULL, dentry);
9574+ inode->i_atime = h_file->f_dentry->d_inode->i_atime;
9575+#endif
9576+ }
9577+ AuTraceErr(err);
9578+ return err;
9579+}
9580+
9581+static struct vm_operations_struct aufs_vm_ops = {
9582+ .fault = aufs_fault,
9583+#if 0 /* reserved for future use */
9584+ .open = aufs_vmaopen,
9585+ .close = aufs_vmaclose,
9586+ unsigned long (*nopfn)(struct vm_area_struct *area,
9587+ unsigned long address);
9588+ page_mkwrite(struct vm_area_struct *vma, struct page *page)
9589+#endif
9590+};
9591+
9592+/* ---------------------------------------------------------------------- */
9593+
9594+static struct vm_operations_struct *au_vm_ops(struct file *h_file,
9595+ struct vm_area_struct *vma)
9596+{
9597+ struct vm_operations_struct *vm_ops;
9598+ int err;
9599+
9600+ AuTraceEnter();
9601+
9602+ au_br_nfs_lockdep_off(h_file->f_vfsmnt->mnt_sb);
9603+ err = h_file->f_op->mmap(h_file, vma);
9604+ au_br_nfs_lockdep_on(h_file->f_vfsmnt->mnt_sb);
9605+ vm_ops = ERR_PTR(err);
9606+ if (unlikely(err))
9607+ goto out;
9608+ vm_ops = vma->vm_ops;
9609+ err = do_munmap(current->mm, vma->vm_start,
9610+ vma->vm_end - vma->vm_start);
9611+ if (unlikely(err)) {
9612+ AuIOErr("failed internal unmapping %.*s, %d\n",
9613+ AuDLNPair(h_file->f_dentry), err);
9614+ vm_ops = ERR_PTR(-EIO);
9615+ }
9616+
9617+ out:
9618+ AuTraceErrPtr(vm_ops);
9619+ return vm_ops;
9620+}
9621+
9622+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
9623+{
9624+ int err;
9625+ unsigned char wlock, mmapped;
9626+ struct dentry *dentry;
9627+ struct super_block *sb;
9628+ struct file *h_file;
9629+ struct vm_operations_struct *vm_ops;
9630+
9631+ dentry = file->f_dentry;
9632+ LKTRTrace("%.*s, %lx, len %lu\n",
9633+ AuDLNPair(dentry), vma->vm_start,
9634+ vma->vm_end - vma->vm_start);
9635+ AuDebugOn(!S_ISREG(dentry->d_inode->i_mode));
9636+ AuDebugOn(down_write_trylock(&vma->vm_mm->mmap_sem));
9637+
9638+ mmapped = au_test_mmapped(file); /* can be harmless race condition */
9639+ wlock = !!(file->f_mode & FMODE_WRITE);
9640+ sb = dentry->d_sb;
9641+ si_read_lock(sb, AuLock_FLUSH);
9642+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, wlock | !mmapped,
9643+ /*locked*/0);
9644+ if (unlikely(err))
9645+ goto out;
9646+
9647+ if (wlock) {
9648+ struct au_pin pin;
9649+
9650+ err = au_ready_to_write(file, -1, &pin);
9651+ di_downgrade_lock(dentry, AuLock_IR);
9652+ if (unlikely(err))
9653+ goto out_unlock;
9654+ au_unpin(&pin);
9655+ } else if (!mmapped)
9656+ di_downgrade_lock(dentry, AuLock_IR);
9657+
9658+ h_file = au_h_fptr(file, au_fbstart(file));
9659+ if (au_test_fuse(h_file->f_dentry->d_sb)) {
9660+ /*
9661+ * by this assignment, f_mapping will differs from aufs inode
9662+ * i_mapping.
9663+ * if someone else mixes the use of f_dentry->d_inode and
9664+ * f_mapping->host, then a problem may arise.
9665+ */
9666+ file->f_mapping = h_file->f_mapping;
9667+ }
9668+
9669+ if (0 && h_file->f_op->mmap == generic_file_mmap) {
9670+ err = generic_file_mmap(file, vma); /* instead of h_file */
9671+ if (unlikely(err))
9672+ goto out_unlock;
9673+ au_fi(file)->fi_h_vm_ops = vma->vm_ops;
9674+ } else {
9675+ vm_ops = NULL;
9676+ if (!mmapped) {
9677+ vm_ops = au_vm_ops(h_file, vma);
9678+ err = PTR_ERR(vm_ops);
9679+ if (IS_ERR(vm_ops))
9680+ goto out_unlock;
9681+ }
9682+
9683+ err = generic_file_mmap(file, vma);
9684+ if (unlikely(err))
9685+ goto out_unlock;
9686+ vma->vm_ops = &aufs_vm_ops;
9687+ /* test again */
9688+ if (!au_test_mmapped(file)) {
9689+ FiMustWriteLock(file);
9690+ au_fi(file)->fi_h_vm_ops = vm_ops;
9691+ }
9692+ }
9693+
9694+ file_accessed(h_file);
9695+ au_update_fuse_h_inode(h_file->f_vfsmnt, h_file->f_dentry); /*ignore*/
9696+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9697+
9698+ out_unlock:
9699+ di_read_unlock(dentry, AuLock_IR);
9700+ if (!wlock && mmapped)
9701+ fi_read_unlock(file);
9702+ else
9703+ fi_write_unlock(file);
9704+ out:
9705+ si_read_unlock(sb);
9706+ AuTraceErr(err);
9707+ return err;
9708+}
9709+
9710+/* ---------------------------------------------------------------------- */
9711+
9712+static unsigned int aufs_poll(struct file *file, poll_table *wait)
9713+{
9714+ unsigned int mask;
9715+ struct file *h_file;
9716+ int err;
9717+ struct dentry *dentry;
9718+ struct super_block *sb;
9719+
9720+ dentry = file->f_dentry;
9721+ LKTRTrace("%.*s, wait %p\n", AuDLNPair(dentry), wait);
9722+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode));
9723+
9724+ /* We should pretend an error happened. */
9725+ mask = POLLERR /* | POLLIN | POLLOUT */;
9726+ sb = dentry->d_sb;
9727+ si_read_lock(sb, AuLock_FLUSH);
9728+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0,
9729+ /*locked*/0);
9730+ if (unlikely(err))
9731+ goto out;
9732+
9733+ /* it is not an error of hidden_file has no operation */
9734+ mask = DEFAULT_POLLMASK;
9735+ h_file = au_h_fptr(file, au_fbstart(file));
9736+ if (h_file->f_op && h_file->f_op->poll)
9737+ mask = h_file->f_op->poll(h_file, wait);
9738+ di_read_unlock(dentry, AuLock_IR);
9739+ fi_read_unlock(file);
9740+
9741+ out:
9742+ si_read_unlock(sb);
9743+ AuTraceErr((int)mask);
9744+ return mask;
9745+}
9746+
9747+static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
9748+ int datasync)
9749+{
9750+ int err;
9751+ struct inode *inode;
9752+ struct file *h_file;
9753+ struct super_block *sb;
9754+ struct au_pin pin;
9755+
9756+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), datasync);
9757+ inode = dentry->d_inode;
9758+
9759+ IMustLock(file->f_mapping->host);
9760+ if (inode != file->f_mapping->host) {
9761+ mutex_unlock(&file->f_mapping->host->i_mutex);
9762+ mutex_lock(&inode->i_mutex);
9763+ }
9764+ IMustLock(inode);
9765+
9766+ sb = dentry->d_sb;
9767+ si_read_lock(sb, AuLock_FLUSH);
9768+ err = 0; /* -EBADF; */ /* posix? */
9769+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
9770+ goto out;
9771+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
9772+ /*locked*/1);
9773+ if (unlikely(err))
9774+ goto out;
9775+ err = au_ready_to_write(file, -1, &pin);
9776+ di_downgrade_lock(dentry, AuLock_IR);
9777+ if (unlikely(err))
9778+ goto out_unlock;
9779+ au_unpin(&pin);
9780+
9781+ err = -EINVAL;
9782+ h_file = au_h_fptr(file, au_fbstart(file));
9783+ if (h_file->f_op && h_file->f_op->fsync) {
9784+ struct mutex *h_mtx = &h_file->f_dentry->d_inode->i_mutex;
9785+
9786+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
9787+ err = h_file->f_op->fsync(h_file, h_file->f_dentry, datasync);
9788+ if (!err)
9789+ au_update_fuse_h_inode(h_file->f_vfsmnt,
9790+ h_file->f_dentry);
9791+ au_cpup_attr_timesizes(inode);
9792+ mutex_unlock(h_mtx);
9793+ }
9794+
9795+ out_unlock:
9796+ di_read_unlock(dentry, AuLock_IR);
9797+ fi_write_unlock(file);
9798+ out:
9799+ si_read_unlock(sb);
9800+ if (inode != file->f_mapping->host) {
9801+ mutex_unlock(&inode->i_mutex);
9802+ mutex_lock(&file->f_mapping->host->i_mutex);
9803+ }
9804+ AuTraceErr(err);
9805+ return err;
9806+}
9807+
9808+static int aufs_fasync(int fd, struct file *file, int flag)
9809+{
9810+ int err;
9811+ struct file *h_file;
9812+ struct dentry *dentry;
9813+ struct super_block *sb;
9814+
9815+ dentry = file->f_dentry;
9816+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), flag);
9817+
9818+ sb = dentry->d_sb;
9819+ si_read_lock(sb, AuLock_FLUSH);
9820+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0,
9821+ /*locked*/0);
9822+ if (unlikely(err))
9823+ goto out;
9824+
9825+ h_file = au_h_fptr(file, au_fbstart(file));
9826+ if (h_file->f_op && h_file->f_op->fasync)
9827+ err = h_file->f_op->fasync(fd, h_file, flag);
9828+ di_read_unlock(dentry, AuLock_IR);
9829+ fi_read_unlock(file);
9830+
9831+ out:
9832+ si_read_unlock(sb);
9833+ AuTraceErr(err);
9834+ return err;
9835+}
9836+
9837+/* ---------------------------------------------------------------------- */
9838+
9839+struct file_operations aufs_file_fop = {
9840+ /*
9841+ * while generic_file_llseek/_unlocked() don't use BKL,
9842+ * don't use it since it operates file->f_mapping->host.
9843+ * in aufs, it may be a real file and may confuse users by UDBA.
9844+ */
9845+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
9846+ /* .llseek = generic_file_llseek, */
9847+#endif
9848+ .read = aufs_read,
9849+ .write = aufs_write,
9850+ .poll = aufs_poll,
9851+ /* .unlocked_ioctl = aufs_ioctl, */
9852+ .mmap = aufs_mmap,
9853+ .open = aufs_open_nondir,
9854+ .flush = aufs_flush,
9855+ .release = aufs_release_nondir,
9856+ .fsync = aufs_fsync_nondir,
9857+ .fasync = aufs_fasync,
9858+#ifdef CONFIG_AUFS_SPLICE_PATCH
9859+ .splice_write = aufs_splice_write,
9860+ .splice_read = aufs_splice_read,
9861+#endif
9862+};
9863diff -urN linux/fs/aufs/getattr.c linux-aufs/fs/aufs/getattr.c
9864--- linux/fs/aufs/getattr.c 1970-01-01 01:00:00.000000000 +0100
9865+++ linux-aufs/fs/aufs/getattr.c 2009-03-12 16:18:04.000000000 +0100
9866@@ -0,0 +1,133 @@
9867+/*
9868+ * Copyright (C) 2005-2009 Junjiro Okajima
9869+ *
9870+ * This program, aufs is free software; you can redistribute it and/or modify
9871+ * it under the terms of the GNU General Public License as published by
9872+ * the Free Software Foundation; either version 2 of the License, or
9873+ * (at your option) any later version.
9874+ *
9875+ * This program is distributed in the hope that it will be useful,
9876+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9877+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9878+ * GNU General Public License for more details.
9879+ *
9880+ * You should have received a copy of the GNU General Public License
9881+ * along with this program; if not, write to the Free Software
9882+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9883+ */
9884+
9885+/*
9886+ * inode attributes on NFS/FUSE branch or HINOTIFY
9887+ *
9888+ * $Id$
9889+ */
9890+
9891+#include "aufs.h"
9892+
9893+static struct dentry *
9894+au_h_dget_any(struct dentry *dentry, aufs_bindex_t *bindex)
9895+{
9896+ struct dentry *h_dentry;
9897+ struct inode *inode, *h_inode;
9898+ struct super_block *sb;
9899+ aufs_bindex_t ib, db;
9900+
9901+ /* must be positive dentry */
9902+ inode = dentry->d_inode;
9903+ LKTRTrace("%.*s, i%lu\n", AuDLNPair(dentry), inode->i_ino);
9904+
9905+ sb = dentry->d_sb;
9906+ db = au_dbstart(dentry);
9907+ ib = au_ibstart(inode);
9908+ if (db == ib) {
9909+ *bindex = db;
9910+ h_dentry = dget(au_h_dptr(dentry, db));
9911+ if (h_dentry)
9912+ goto out; /* success */
9913+ }
9914+
9915+ *bindex = ib;
9916+ h_inode = au_h_iptr(inode, ib);
9917+ h_dentry = d_find_alias(h_inode);
9918+ if (h_dentry)
9919+ goto out; /* success */
9920+
9921+#if 0
9922+ if (au_opt_test(au_mntflags(sb), PLINK)
9923+ && au_plink_test(sb, inode)) {
9924+ h_dentry = au_plink_lkup(sb, ib, inode);
9925+ if (IS_ERR(h_dentry))
9926+ goto out;
9927+ AuDebugOn(!h_dentry->d_inode);
9928+ goto out; /* success */
9929+ }
9930+#endif
9931+
9932+ h_dentry = dget(au_hi_wh(inode, ib));
9933+
9934+ out:
9935+ AuTraceErrPtr(h_dentry);
9936+ return h_dentry;
9937+}
9938+
9939+int aufs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st)
9940+{
9941+ int err;
9942+ unsigned int mnt_flags;
9943+ aufs_bindex_t bindex;
9944+ unsigned char did_lock;
9945+ struct inode *inode;
9946+ struct dentry *h_dentry;
9947+ struct super_block *sb, *h_sb;
9948+
9949+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
9950+
9951+ err = 0;
9952+ sb = dentry->d_sb;
9953+ si_read_lock(sb, AuLock_FLUSH);
9954+ mnt_flags = au_mntflags(sb);
9955+ if (dentry != sb->s_root) {
9956+ di_read_lock_parent(dentry, AuLock_IR);
9957+ inode = dentry->d_inode;
9958+ did_lock = 1;
9959+
9960+ /* todo: test bit inotify option too? */
9961+ bindex = au_ibstart(inode);
9962+ h_sb = au_sbr_sb(sb, bindex);
9963+ /* todo: fix this condition */
9964+ if ((au_opt_test(mnt_flags, PLINK) && au_plink_test(sb, inode))
9965+ /* au_iigen(inode) == au_sigen(sb) */
9966+ || (!au_test_fuse(h_sb) && !au_test_nfs(h_sb)))
9967+ goto fill;
9968+
9969+ h_dentry = au_h_dget_any(dentry, &bindex);
9970+ err = PTR_ERR(h_dentry);
9971+ if (IS_ERR(h_dentry))
9972+ goto out;
9973+ } else {
9974+ /* lock free root dinfo */
9975+ did_lock = 0;
9976+ bindex = 0;
9977+ inode = dentry->d_inode;
9978+ h_dentry = dget(au_di(dentry)->di_hdentry->hd_dentry);
9979+ }
9980+
9981+ err = -EIO;
9982+ if (h_dentry && h_dentry->d_inode)
9983+ err = vfsub_getattr(au_sbr_mnt(sb, bindex), h_dentry, st,
9984+ au_test_dlgt(mnt_flags));
9985+ dput(h_dentry);
9986+ if (!err) {
9987+ /* todo: I don't like this approach */
9988+ au_cpup_attr_all(inode, /*force*/0);
9989+ fill:
9990+ generic_fillattr(inode, st);
9991+ }
9992+
9993+ out:
9994+ if (did_lock)
9995+ di_read_unlock(dentry, AuLock_IR);
9996+ si_read_unlock(sb);
9997+ AuTraceErr(err);
9998+ return err;
9999+}
10000diff -urN linux/fs/aufs/hinode.h linux-aufs/fs/aufs/hinode.h
10001--- linux/fs/aufs/hinode.h 1970-01-01 01:00:00.000000000 +0100
10002+++ linux-aufs/fs/aufs/hinode.h 2009-03-12 16:18:04.000000000 +0100
10003@@ -0,0 +1,175 @@
10004+/*
10005+ * Copyright (C) 2005-2009 Junjiro Okajima
10006+ *
10007+ * This program, aufs is free software; you can redistribute it and/or modify
10008+ * it under the terms of the GNU General Public License as published by
10009+ * the Free Software Foundation; either version 2 of the License, or
10010+ * (at your option) any later version.
10011+ *
10012+ * This program is distributed in the hope that it will be useful,
10013+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10014+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10015+ * GNU General Public License for more details.
10016+ *
10017+ * You should have received a copy of the GNU General Public License
10018+ * along with this program; if not, write to the Free Software
10019+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10020+ */
10021+
10022+/*
10023+ * lower (branch filesystem) inode and setting inotify
10024+ *
10025+ * $Id$
10026+ */
10027+
10028+#ifndef __AUFS_HINODE_H__
10029+#define __AUFS_HINODE_H__
10030+
10031+#ifdef __KERNEL__
10032+
10033+#include <linux/fs.h>
10034+#include <linux/inotify.h>
10035+#include <linux/aufs_type.h>
10036+#include "super.h"
10037+#include "vfsub.h"
10038+
10039+/* ---------------------------------------------------------------------- */
10040+
10041+struct au_hinotify {
10042+#ifdef CONFIG_AUFS_HINOTIFY
10043+ struct au_splhead hin_ignore;
10044+ struct inotify_watch hin_watch;
10045+ struct inode *hin_aufs_inode; /* no get/put */
10046+#endif
10047+};
10048+
10049+struct au_hinode {
10050+ struct inode *hi_inode;
10051+ aufs_bindex_t hi_id;
10052+#ifdef CONFIG_AUFS_HINOTIFY
10053+ struct au_hinotify *hi_notify;
10054+#endif
10055+
10056+ /* reference to the copied-up whiteout with get/put */
10057+ struct dentry *hi_whdentry;
10058+};
10059+
10060+struct au_hin_ignore {
10061+#ifdef CONFIG_AUFS_HINOTIFY
10062+ struct list_head ign_list;
10063+
10064+ pid_t ign_pid;
10065+ __u32 ign_events, ign_handled;
10066+ struct au_hinode *ign_hinode;
10067+#endif
10068+};
10069+
10070+/* ---------------------------------------------------------------------- */
10071+
10072+#ifdef CONFIG_AUFS_HINOTIFY
10073+/* inotify events */
10074+static const __u32 AuInMask = (IN_MOVE | IN_DELETE | IN_CREATE
10075+ /* | IN_ACCESS */
10076+ | IN_MODIFY | IN_ATTRIB
10077+ /* | IN_DELETE_SELF | IN_MOVE_SELF */
10078+ );
10079+
10080+static inline
10081+void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
10082+{
10083+ hinode->hi_notify = val;
10084+}
10085+
10086+/* hinotify.c */
10087+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
10088+ struct inode *h_inode);
10089+void au_hin_free(struct au_hinode *hinode);
10090+void au_hin_ctl(struct au_hinode *hinode, const __u32 mask);
10091+void au_reset_hinotify(struct inode *inode, unsigned int flags);
10092+
10093+int au_hin_verify_gen(struct dentry *dentry);
10094+
10095+int __init au_inotify_init(void);
10096+void au_inotify_fin(void);
10097+
10098+static inline void au_hin_suspend(struct au_hinode *hinode)
10099+{
10100+ au_hin_ctl(hinode, 0);
10101+}
10102+
10103+static inline void au_hin_resume(struct au_hinode *hinode)
10104+{
10105+ au_hin_ctl(hinode, AuInMask);
10106+}
10107+
10108+#else
10109+
10110+static inline
10111+void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
10112+{
10113+ /* empty */
10114+}
10115+
10116+static inline
10117+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
10118+ struct inode *h_inode)
10119+{
10120+ return -EOPNOTSUPP;
10121+}
10122+
10123+static inline void au_hin_free(struct au_hinode *hinode)
10124+{
10125+ /* nothing */
10126+}
10127+
10128+static inline void au_reset_hinotify(struct inode *inode, unsigned int flags)
10129+{
10130+ /* nothing */
10131+}
10132+
10133+static inline int au_hin_verify_gen(struct dentry *dentry)
10134+{
10135+ return 0;
10136+}
10137+
10138+static inline int au_inotify_init(void)
10139+{
10140+ return 0;
10141+}
10142+
10143+#define au_inotify_fin() do {} while (0)
10144+
10145+static inline void au_hin_suspend(struct au_hinode *hinode)
10146+{
10147+ /* empty */
10148+}
10149+
10150+static inline void au_hin_resume(struct au_hinode *hinode)
10151+{
10152+ /* empty */
10153+}
10154+#endif /* CONFIG_AUFS_HINOTIFY */
10155+
10156+#if defined(CONFIG_AUFS_HINOTIFY) && defined(CONFIG_AUFS_DEBUG)
10157+static inline void au_hin_list_del(struct list_head *e)
10158+{
10159+ list_del_init(e);
10160+}
10161+
10162+void au_dbg_hin_list(struct vfsub_args *vargs);
10163+#else
10164+static inline void au_hin_list_del(struct list_head *e)
10165+{
10166+ list_del(e);
10167+}
10168+
10169+static inline void au_dbg_hin_list(struct vfsub_args *vargs)
10170+{
10171+ /* empty */
10172+}
10173+#endif /* CONFIG_AUFS_DEBUG */
10174+
10175+/* ---------------------------------------------------------------------- */
10176+
10177+#endif /* __KERNEL__ */
10178+#endif /* __AUFS_HINODE_H__ */
10179diff -urN linux/fs/aufs/hin_or_dlgt.c linux-aufs/fs/aufs/hin_or_dlgt.c
10180--- linux/fs/aufs/hin_or_dlgt.c 1970-01-01 01:00:00.000000000 +0100
10181+++ linux-aufs/fs/aufs/hin_or_dlgt.c 2009-03-12 16:18:04.000000000 +0100
10182@@ -0,0 +1,736 @@
10183+/*
10184+ * Copyright (C) 2005-2009 Junjiro Okajima
10185+ *
10186+ * This program, aufs is free software; you can redistribute it and/or modify
10187+ * it under the terms of the GNU General Public License as published by
10188+ * the Free Software Foundation; either version 2 of the License, or
10189+ * (at your option) any later version.
10190+ *
10191+ * This program is distributed in the hope that it will be useful,
10192+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10193+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10194+ * GNU General Public License for more details.
10195+ *
10196+ * You should have received a copy of the GNU General Public License
10197+ * along with this program; if not, write to the Free Software
10198+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10199+ */
10200+
10201+/*
10202+ * sub-routines for vfs in hinotify or dlgt mode
10203+ *
10204+ * $Id$
10205+ */
10206+
10207+#include <linux/uaccess.h>
10208+#include "aufs.h"
10209+
10210+#if !defined(CONFIG_AUFS_HINOTIFY) && !defined(CONFIG_AUFS_DLGT)
10211+#error mis-configuraion or Makefile
10212+#endif
10213+
10214+/* ---------------------------------------------------------------------- */
10215+
10216+struct permission_args {
10217+ int *errp;
10218+ struct inode *inode;
10219+ int mask;
10220+ struct nameidata *nd;
10221+};
10222+
10223+static void call_permission(void *args)
10224+{
10225+ struct permission_args *a = args;
10226+ *a->errp = do_vfsub_permission(a->inode, a->mask, a->nd);
10227+}
10228+
10229+int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
10230+ int dlgt)
10231+{
10232+ if (!dlgt)
10233+ return do_vfsub_permission(inode, mask, nd);
10234+ else {
10235+ int err, wkq_err;
10236+ struct permission_args args = {
10237+ .errp = &err,
10238+ .inode = inode,
10239+ .mask = mask,
10240+ .nd = nd
10241+ };
10242+ wkq_err = au_wkq_wait(call_permission, &args, /*dlgt*/1);
10243+ if (unlikely(wkq_err))
10244+ err = wkq_err;
10245+ return err;
10246+ }
10247+}
10248+
10249+/* ---------------------------------------------------------------------- */
10250+
10251+struct create_args {
10252+ int *errp;
10253+ struct inode *dir;
10254+ struct dentry *dentry;
10255+ int mode;
10256+ struct nameidata *nd;
10257+ struct vfsub_args *vargs;
10258+};
10259+
10260+static void call_create(void *args)
10261+{
10262+ struct create_args *a = args;
10263+ vfsub_ignore(a->vargs);
10264+ *a->errp = do_vfsub_create(a->dir, a->dentry, a->mode, a->nd);
10265+ if (unlikely(*a->errp))
10266+ vfsub_unignore(a->vargs);
10267+ au_dbg_hin_list(a->vargs);
10268+}
10269+
10270+int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
10271+ struct nameidata *nd, struct vfsub_args *vargs)
10272+{
10273+ int err;
10274+ struct create_args args = {
10275+ .errp = &err,
10276+ .dir = dir,
10277+ .dentry = dentry,
10278+ .mode = mode,
10279+ .nd = nd,
10280+ .vargs = vargs
10281+ };
10282+
10283+ if (!vfsub_ftest(vargs->flags, DLGT))
10284+ call_create(&args);
10285+ else {
10286+ int wkq_err;
10287+ wkq_err = au_wkq_wait(call_create, &args, /*dlgt*/1);
10288+ if (unlikely(wkq_err))
10289+ err = wkq_err;
10290+ }
10291+ return err;
10292+}
10293+
10294+struct symlink_args {
10295+ int *errp;
10296+ struct inode *dir;
10297+ struct dentry *dentry;
10298+ const char *symname;
10299+ int mode;
10300+ struct vfsub_args *vargs;
10301+};
10302+
10303+static void call_symlink(void *args)
10304+{
10305+ struct symlink_args *a = args;
10306+ vfsub_ignore(a->vargs);
10307+ *a->errp = do_vfsub_symlink(a->dir, a->dentry, a->symname, a->mode);
10308+ if (unlikely(*a->errp))
10309+ vfsub_unignore(a->vargs);
10310+ au_dbg_hin_list(a->vargs);
10311+}
10312+
10313+int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
10314+ int mode, struct vfsub_args *vargs)
10315+{
10316+ int err;
10317+ struct symlink_args args = {
10318+ .errp = &err,
10319+ .dir = dir,
10320+ .dentry = dentry,
10321+ .symname = symname,
10322+ .mode = mode,
10323+ .vargs = vargs
10324+ };
10325+
10326+ if (!vfsub_ftest(vargs->flags, DLGT))
10327+ call_symlink(&args);
10328+ else {
10329+ int wkq_err;
10330+ wkq_err = au_wkq_wait(call_symlink, &args, /*dlgt*/1);
10331+ if (unlikely(wkq_err))
10332+ err = wkq_err;
10333+ }
10334+ return err;
10335+}
10336+
10337+struct mknod_args {
10338+ int *errp;
10339+ struct inode *dir;
10340+ struct dentry *dentry;
10341+ int mode;
10342+ dev_t dev;
10343+ struct vfsub_args *vargs;
10344+};
10345+
10346+static void call_mknod(void *args)
10347+{
10348+ struct mknod_args *a = args;
10349+ vfsub_ignore(a->vargs);
10350+ *a->errp = do_vfsub_mknod(a->dir, a->dentry, a->mode, a->dev);
10351+ if (unlikely(*a->errp))
10352+ vfsub_unignore(a->vargs);
10353+ au_dbg_hin_list(a->vargs);
10354+}
10355+
10356+int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
10357+ struct vfsub_args *vargs)
10358+{
10359+ int err;
10360+ struct mknod_args args = {
10361+ .errp = &err,
10362+ .dir = dir,
10363+ .dentry = dentry,
10364+ .mode = mode,
10365+ .dev = dev,
10366+ .vargs = vargs
10367+ };
10368+
10369+ if (!vfsub_ftest(vargs->flags, DLGT))
10370+ call_mknod(&args);
10371+ else {
10372+ int wkq_err;
10373+ wkq_err = au_wkq_wait(call_mknod, &args, /*dlgt*/1);
10374+ if (unlikely(wkq_err))
10375+ err = wkq_err;
10376+ }
10377+ return err;
10378+}
10379+
10380+struct mkdir_args {
10381+ int *errp;
10382+ struct inode *dir;
10383+ struct dentry *dentry;
10384+ int mode;
10385+ struct vfsub_args *vargs;
10386+};
10387+
10388+static void call_mkdir(void *args)
10389+{
10390+ struct mkdir_args *a = args;
10391+ vfsub_ignore(a->vargs);
10392+ *a->errp = do_vfsub_mkdir(a->dir, a->dentry, a->mode);
10393+ if (unlikely(*a->errp))
10394+ vfsub_unignore(a->vargs);
10395+ au_dbg_hin_list(a->vargs);
10396+}
10397+
10398+int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode,
10399+ struct vfsub_args *vargs)
10400+{
10401+ int err;
10402+ struct mkdir_args args = {
10403+ .errp = &err,
10404+ .dir = dir,
10405+ .dentry = dentry,
10406+ .mode = mode,
10407+ .vargs = vargs
10408+ };
10409+
10410+ if (!vfsub_ftest(vargs->flags, DLGT))
10411+ call_mkdir(&args);
10412+ else {
10413+ int wkq_err;
10414+ wkq_err = au_wkq_wait(call_mkdir, &args, /*dlgt*/1);
10415+ if (unlikely(wkq_err))
10416+ err = wkq_err;
10417+ }
10418+ return err;
10419+}
10420+
10421+/* ---------------------------------------------------------------------- */
10422+
10423+struct link_args {
10424+ int *errp;
10425+ struct inode *dir;
10426+ struct dentry *src_dentry, *dentry;
10427+ struct vfsub_args *vargs;
10428+};
10429+
10430+static void call_link(void *args)
10431+{
10432+ struct link_args *a = args;
10433+ vfsub_ignore(a->vargs);
10434+ *a->errp = do_vfsub_link(a->src_dentry, a->dir, a->dentry);
10435+ if (unlikely(*a->errp))
10436+ vfsub_unignore(a->vargs);
10437+ au_dbg_hin_list(a->vargs);
10438+}
10439+
10440+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
10441+ struct dentry *dentry, struct vfsub_args *vargs)
10442+{
10443+ int err;
10444+ struct link_args args = {
10445+ .errp = &err,
10446+ .src_dentry = src_dentry,
10447+ .dir = dir,
10448+ .dentry = dentry,
10449+ .vargs = vargs
10450+ };
10451+
10452+ if (!vfsub_ftest(vargs->flags, DLGT))
10453+ call_link(&args);
10454+ else {
10455+ int wkq_err;
10456+ wkq_err = au_wkq_wait(call_link, &args, /*dlgt*/1);
10457+ if (unlikely(wkq_err))
10458+ err = wkq_err;
10459+ }
10460+ return err;
10461+}
10462+
10463+struct rename_args {
10464+ int *errp;
10465+ struct inode *src_dir, *dir;
10466+ struct dentry *src_dentry, *dentry;
10467+ struct vfsub_args *vargs;
10468+};
10469+
10470+static void call_rename(void *args)
10471+{
10472+ struct rename_args *a = args;
10473+ vfsub_ignore(a->vargs);
10474+ *a->errp = do_vfsub_rename(a->src_dir, a->src_dentry, a->dir,
10475+ a->dentry);
10476+ if (unlikely(*a->errp))
10477+ vfsub_unignore(a->vargs);
10478+ au_dbg_hin_list(a->vargs);
10479+}
10480+
10481+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
10482+ struct inode *dir, struct dentry *dentry,
10483+ struct vfsub_args *vargs)
10484+{
10485+ int err;
10486+ struct rename_args args = {
10487+ .errp = &err,
10488+ .src_dir = src_dir,
10489+ .src_dentry = src_dentry,
10490+ .dir = dir,
10491+ .dentry = dentry,
10492+ .vargs = vargs
10493+ };
10494+
10495+ if (!vfsub_ftest(vargs->flags, DLGT))
10496+ call_rename(&args);
10497+ else {
10498+ int wkq_err;
10499+ wkq_err = au_wkq_wait(call_rename, &args, /*dlgt*/1);
10500+ if (unlikely(wkq_err))
10501+ err = wkq_err;
10502+ }
10503+ return err;
10504+}
10505+
10506+struct rmdir_args {
10507+ int *errp;
10508+ struct inode *dir;
10509+ struct dentry *dentry;
10510+ struct vfsub_args *vargs;
10511+};
10512+
10513+static void call_rmdir(void *args)
10514+{
10515+ struct rmdir_args *a = args;
10516+ vfsub_ignore(a->vargs);
10517+ *a->errp = do_vfsub_rmdir(a->dir, a->dentry);
10518+ if (unlikely(*a->errp))
10519+ vfsub_unignore(a->vargs);
10520+ au_dbg_hin_list(a->vargs);
10521+}
10522+
10523+int vfsub_rmdir(struct inode *dir, struct dentry *dentry,
10524+ struct vfsub_args *vargs)
10525+{
10526+ int err;
10527+ struct rmdir_args args = {
10528+ .errp = &err,
10529+ .dir = dir,
10530+ .dentry = dentry,
10531+ .vargs = vargs
10532+ };
10533+
10534+ if (!vfsub_ftest(vargs->flags, DLGT))
10535+ call_rmdir(&args);
10536+ else {
10537+ int wkq_err;
10538+ wkq_err = au_wkq_wait(call_rmdir, &args, /*dlgt*/1);
10539+ if (unlikely(wkq_err))
10540+ err = wkq_err;
10541+ }
10542+ return err;
10543+}
10544+
10545+/* ---------------------------------------------------------------------- */
10546+
10547+struct read_args {
10548+ ssize_t *errp;
10549+ struct file *file;
10550+ union {
10551+ void *kbuf;
10552+ char __user *ubuf;
10553+ };
10554+ size_t count;
10555+ loff_t *ppos;
10556+};
10557+
10558+static void call_read_k(void *args)
10559+{
10560+ struct read_args *a = args;
10561+ LKTRTrace("%.*s, cnt %zu, pos %lld\n",
10562+ AuDLNPair(a->file->f_dentry), a->count, *a->ppos);
10563+ *a->errp = do_vfsub_read_k(a->file, a->kbuf, a->count, a->ppos);
10564+}
10565+
10566+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
10567+ loff_t *ppos, int dlgt)
10568+{
10569+ if (!dlgt)
10570+ return do_vfsub_read_u(file, ubuf, count, ppos);
10571+ else {
10572+ int wkq_err;
10573+ ssize_t err, read;
10574+ struct read_args args = {
10575+ .errp = &err,
10576+ .file = file,
10577+ .count = count,
10578+ .ppos = ppos
10579+ };
10580+
10581+ if (!count)
10582+ return 0;
10583+
10584+ /*
10585+ * workaround an application bug.
10586+ * generally, read(2) or write(2) may return the value shorter
10587+ * than requested. But many applications don't support it,
10588+ * for example bash.
10589+ */
10590+ err = -ENOMEM;
10591+ if (args.count > PAGE_SIZE)
10592+ args.count = PAGE_SIZE;
10593+ args.kbuf = kmalloc(args.count, GFP_NOFS);
10594+ if (unlikely(!args.kbuf))
10595+ goto out;
10596+
10597+ read = 0;
10598+ do {
10599+ wkq_err = au_wkq_wait(call_read_k, &args, /*dlgt*/1);
10600+ if (unlikely(wkq_err))
10601+ err = wkq_err;
10602+ if (unlikely(err > 0
10603+ && copy_to_user(ubuf, args.kbuf, err))) {
10604+ err = -EFAULT;
10605+ goto out_free;
10606+ } else if (!err)
10607+ break;
10608+ else if (unlikely(err < 0))
10609+ goto out_free;
10610+ count -= err;
10611+ /* do not read too much because of file i/o pointer */
10612+ if (count < args.count)
10613+ args.count = count;
10614+ ubuf += err;
10615+ read += err;
10616+ } while (count);
10617+ smp_mb(); /* flush ubuf */
10618+ err = read;
10619+
10620+ out_free:
10621+ kfree(args.kbuf);
10622+ out:
10623+ return err;
10624+ }
10625+}
10626+
10627+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
10628+ int dlgt)
10629+{
10630+ if (!dlgt)
10631+ return do_vfsub_read_k(file, kbuf, count, ppos);
10632+ else {
10633+ ssize_t err;
10634+ int wkq_err;
10635+ struct read_args args = {
10636+ .errp = &err,
10637+ .file = file,
10638+ .count = count,
10639+ .ppos = ppos
10640+ };
10641+ args.kbuf = kbuf;
10642+ wkq_err = au_wkq_wait(call_read_k, &args, /*dlgt*/1);
10643+ if (unlikely(wkq_err))
10644+ err = wkq_err;
10645+ return err;
10646+ }
10647+}
10648+
10649+struct write_args {
10650+ ssize_t *errp;
10651+ struct file *file;
10652+ union {
10653+ void *kbuf;
10654+ const char __user *ubuf;
10655+ };
10656+ size_t count;
10657+ loff_t *ppos;
10658+ struct vfsub_args *vargs;
10659+};
10660+
10661+static void call_write_k(void *args)
10662+{
10663+ struct write_args *a = args;
10664+ vfsub_ignore(a->vargs);
10665+ *a->errp = do_vfsub_write_k(a->file, a->kbuf, a->count, a->ppos);
10666+ if (unlikely(*a->errp <= 0))
10667+ vfsub_unignore(a->vargs);
10668+ au_dbg_hin_list(a->vargs);
10669+}
10670+
10671+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
10672+ loff_t *ppos, struct vfsub_args *vargs)
10673+{
10674+ ssize_t err;
10675+
10676+ if (!vfsub_ftest(vargs->flags, DLGT)) {
10677+ vfsub_ignore(vargs);
10678+ err = do_vfsub_write_u(file, ubuf, count, ppos);
10679+ if (unlikely(err <= 0))
10680+ vfsub_unignore(vargs);
10681+ au_dbg_hin_list(vargs);
10682+ } else {
10683+ ssize_t written;
10684+ int wkq_err;
10685+ struct write_args args = {
10686+ .errp = &err,
10687+ .file = file,
10688+ .count = count,
10689+ .ppos = ppos,
10690+ .vargs = vargs
10691+ };
10692+
10693+ if (!count)
10694+ return 0;
10695+
10696+ /*
10697+ * workaround an application bug.
10698+ * generally, read(2) or write(2) may return the value shorter
10699+ * than requested. But many applications don't support it,
10700+ * for example bash.
10701+ */
10702+ err = -ENOMEM;
10703+ if (args.count > PAGE_SIZE)
10704+ args.count = PAGE_SIZE;
10705+ args.kbuf = kmalloc(args.count, GFP_NOFS);
10706+ if (unlikely(!args.kbuf))
10707+ goto out;
10708+
10709+ written = 0;
10710+ do {
10711+ if (unlikely(copy_from_user(args.kbuf, ubuf,
10712+ args.count))) {
10713+ err = -EFAULT;
10714+ goto out_free;
10715+ }
10716+
10717+ wkq_err = au_wkq_wait(call_write_k, &args, /*dlgt*/1);
10718+ if (unlikely(wkq_err))
10719+ err = wkq_err;
10720+ if (err > 0) {
10721+ count -= err;
10722+ if (count < args.count)
10723+ args.count = count;
10724+ ubuf += err;
10725+ written += err;
10726+ } else if (!err)
10727+ break;
10728+ else if (unlikely(err < 0))
10729+ goto out_free;
10730+ } while (count);
10731+ err = written;
10732+
10733+ out_free:
10734+ kfree(args.kbuf);
10735+ }
10736+ out:
10737+ return err;
10738+}
10739+
10740+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
10741+ struct vfsub_args *vargs)
10742+{
10743+ ssize_t err;
10744+ struct write_args args = {
10745+ .errp = &err,
10746+ .file = file,
10747+ .count = count,
10748+ .ppos = ppos,
10749+ .vargs = vargs
10750+ };
10751+
10752+ args.kbuf = kbuf;
10753+ if (!vfsub_ftest(vargs->flags, DLGT))
10754+ call_write_k(&args);
10755+ else {
10756+ int wkq_err;
10757+ wkq_err = au_wkq_wait(call_write_k, &args, /*dlgt*/1);
10758+ if (unlikely(wkq_err))
10759+ err = wkq_err;
10760+ }
10761+ return err;
10762+}
10763+
10764+struct readdir_args {
10765+ int *errp;
10766+ struct file *file;
10767+ filldir_t filldir;
10768+ void *arg;
10769+};
10770+
10771+static void call_readdir(void *args)
10772+{
10773+ struct readdir_args *a = args;
10774+ *a->errp = do_vfsub_readdir(a->file, a->filldir, a->arg);
10775+}
10776+
10777+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
10778+{
10779+ if (!dlgt)
10780+ return do_vfsub_readdir(file, filldir, arg);
10781+ else {
10782+ int err, wkq_err;
10783+ struct readdir_args args = {
10784+ .errp = &err,
10785+ .file = file,
10786+ .filldir = filldir,
10787+ .arg = arg
10788+ };
10789+ wkq_err = au_wkq_wait(call_readdir, &args, /*dlgt*/1);
10790+ if (unlikely(wkq_err))
10791+ err = wkq_err;
10792+ return err;
10793+ }
10794+}
10795+
10796+/* ---------------------------------------------------------------------- */
10797+
10798+struct splice_to_args {
10799+ long *errp;
10800+ struct file *in;
10801+ loff_t *ppos;
10802+ struct pipe_inode_info *pipe;
10803+ size_t len;
10804+ unsigned int flags;
10805+};
10806+
10807+static void call_splice_to(void *args)
10808+{
10809+ struct splice_to_args *a = args;
10810+ *a->errp = do_vfsub_splice_to(a->in, a->ppos, a->pipe, a->len,
10811+ a->flags);
10812+}
10813+
10814+long vfsub_splice_to(struct file *in, loff_t *ppos,
10815+ struct pipe_inode_info *pipe, size_t len,
10816+ unsigned int flags, int dlgt)
10817+{
10818+ if (!dlgt)
10819+ return do_vfsub_splice_to(in, ppos, pipe, len, flags);
10820+ else {
10821+ long err;
10822+ int wkq_err;
10823+ struct splice_to_args args = {
10824+ .errp = &err,
10825+ .in = in,
10826+ .ppos = ppos,
10827+ .pipe = pipe,
10828+ .len = len,
10829+ .flags = flags
10830+ };
10831+ wkq_err = au_wkq_wait(call_splice_to, &args, /*dlgt*/1);
10832+ if (unlikely(wkq_err))
10833+ err = wkq_err;
10834+ return err;
10835+ }
10836+}
10837+
10838+struct splice_from_args {
10839+ long *errp;
10840+ struct pipe_inode_info *pipe;
10841+ struct file *out;
10842+ loff_t *ppos;
10843+ size_t len;
10844+ unsigned int flags;
10845+ struct vfsub_args *vargs;
10846+};
10847+
10848+static void call_splice_from(void *args)
10849+{
10850+ struct splice_from_args *a = args;
10851+ vfsub_ignore(a->vargs);
10852+ *a->errp = do_vfsub_splice_from(a->pipe, a->out, a->ppos, a->len,
10853+ a->flags);
10854+ if (unlikely(*a->errp < 0))
10855+ vfsub_unignore(a->vargs);
10856+ au_dbg_hin_list(a->vargs);
10857+}
10858+
10859+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
10860+ loff_t *ppos, size_t len, unsigned int flags,
10861+ struct vfsub_args *vargs)
10862+{
10863+ long err;
10864+ struct splice_from_args args = {
10865+ .errp = &err,
10866+ .pipe = pipe,
10867+ .out = out,
10868+ .ppos = ppos,
10869+ .len = len,
10870+ .flags = flags,
10871+ .vargs = vargs
10872+ };
10873+
10874+ if (!vfsub_ftest(vargs->flags, DLGT))
10875+ call_splice_from(&args);
10876+ else {
10877+ int wkq_err;
10878+ wkq_err = au_wkq_wait(call_splice_from, &args, /*dlgt*/1);
10879+ if (unlikely(wkq_err))
10880+ err = wkq_err;
10881+ }
10882+ return err;
10883+}
10884+
10885+/* ---------------------------------------------------------------------- */
10886+
10887+struct getattr_args {
10888+ int *errp;
10889+ struct vfsmount *mnt;
10890+ struct dentry *dentry;
10891+ struct kstat *st;
10892+};
10893+
10894+static void call_getattr(void *args)
10895+{
10896+ struct getattr_args *a = args;
10897+ *a->errp = do_vfsub_getattr(a->mnt, a->dentry, a->st);
10898+}
10899+
10900+int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st,
10901+ int dlgt)
10902+{
10903+ if (!dlgt)
10904+ return do_vfsub_getattr(mnt, dentry, st);
10905+ else {
10906+ int err, wkq_err;
10907+ struct getattr_args args = {
10908+ .errp = &err,
10909+ .mnt = mnt,
10910+ .dentry = dentry,
10911+ .st = st
10912+ };
10913+ wkq_err = au_wkq_wait(call_getattr, &args, /*dlgt*/1);
10914+ if (unlikely(wkq_err))
10915+ err = wkq_err;
10916+ return err;
10917+ }
10918+}
10919diff -urN linux/fs/aufs/hinotify.c linux-aufs/fs/aufs/hinotify.c
10920--- linux/fs/aufs/hinotify.c 1970-01-01 01:00:00.000000000 +0100
10921+++ linux-aufs/fs/aufs/hinotify.c 2009-03-12 16:18:04.000000000 +0100
10922@@ -0,0 +1,1146 @@
10923+/*
10924+ * Copyright (C) 2005-2009 Junjiro Okajima
10925+ *
10926+ * This program, aufs is free software; you can redistribute it and/or modify
10927+ * it under the terms of the GNU General Public License as published by
10928+ * the Free Software Foundation; either version 2 of the License, or
10929+ * (at your option) any later version.
10930+ *
10931+ * This program is distributed in the hope that it will be useful,
10932+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10933+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10934+ * GNU General Public License for more details.
10935+ *
10936+ * You should have received a copy of the GNU General Public License
10937+ * along with this program; if not, write to the Free Software
10938+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10939+ */
10940+
10941+/*
10942+ * internal/hidden inotify handler
10943+ *
10944+ * $Id$
10945+ */
10946+
10947+#include "aufs.h"
10948+
10949+/*
10950+#ifdef DbgInotify
10951+#define AuDbgHin(args...) AuDbg(##args)
10952+#else
10953+#define AuDbgHin(args...) do {} while ()
10954+#endif
10955+*/
10956+
10957+static struct inotify_handle *in_handle;
10958+
10959+AuCacheFuncs(hinotify, AuCache_HINOTIFY);
10960+
10961+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
10962+ struct inode *h_inode)
10963+{
10964+ int err;
10965+ struct au_hinotify *hin;
10966+ s32 wd;
10967+
10968+ LKTRTrace("i%lu, hi%lu\n", inode->i_ino, h_inode->i_ino);
10969+
10970+ err = -ENOMEM;
10971+ hin = au_cache_alloc_hinotify();
10972+ if (hin) {
10973+ AuDebugOn(hinode->hi_notify);
10974+ hinode->hi_notify = hin;
10975+ au_spl_init(&hin->hin_ignore);
10976+ hin->hin_aufs_inode = inode;
10977+
10978+ inotify_init_watch(&hin->hin_watch);
10979+ wd = inotify_add_watch(in_handle, &hin->hin_watch, h_inode,
10980+ AuInMask);
10981+ if (wd >= 0)
10982+ return 0; /* success */
10983+
10984+ err = wd;
10985+ put_inotify_watch(&hin->hin_watch);
10986+ au_cache_free_hinotify(hin);
10987+ hinode->hi_notify = NULL;
10988+ }
10989+
10990+ AuTraceErr(err);
10991+ return err;
10992+}
10993+
10994+void au_hin_free(struct au_hinode *hinode)
10995+{
10996+ int err;
10997+ struct au_hinotify *hin;
10998+
10999+ AuTraceEnter();
11000+
11001+ hin = hinode->hi_notify;
11002+ if (hin) {
11003+ err = 0;
11004+ if (atomic_read(&hin->hin_watch.count))
11005+ err = inotify_rm_watch(in_handle, &hin->hin_watch);
11006+ if (unlikely(err))
11007+ /* it means the watch is already removed */
11008+ LKTRTrace("failed inotify_rm_watch() %d\n", err);
11009+ au_cache_free_hinotify(hin);
11010+ hinode->hi_notify = NULL;
11011+ }
11012+}
11013+
11014+/* ---------------------------------------------------------------------- */
11015+
11016+void au_hin_ctl(struct au_hinode *hinode, const __u32 mask)
11017+{
11018+ struct inode *h_inode;
11019+ struct inotify_watch *watch;
11020+
11021+ h_inode = hinode->hi_inode;
11022+ LKTRTrace("hi%lu, sb %p, 0x%x\n", h_inode->i_ino, h_inode->i_sb, mask);
11023+ IMustLock(h_inode);
11024+ if (!hinode->hi_notify)
11025+ return;
11026+
11027+ watch = &hinode->hi_notify->hin_watch;
11028+#if 0 /* reserved for future use */
11029+ {
11030+ u32 wd;
11031+ wd = inotify_find_update_watch(in_handle, h_inode, mask);
11032+ AuTraceErr(wd);
11033+ /* ignore an err; */
11034+ }
11035+#else
11036+ /* struct inotify_handle is hidden */
11037+ mutex_lock(&h_inode->inotify_mutex);
11038+ /* mutex_lock(&watch->ih->mutex); */
11039+ watch->mask = mask;
11040+ /* mutex_unlock(&watch->ih->mutex); */
11041+ mutex_unlock(&h_inode->inotify_mutex);
11042+#endif
11043+ LKTRTrace("watch %p, mask %u\n", watch, watch->mask);
11044+}
11045+
11046+void au_reset_hinotify(struct inode *inode, unsigned int flags)
11047+{
11048+ aufs_bindex_t bindex, bend;
11049+ struct inode *hi;
11050+ struct dentry *iwhdentry;
11051+
11052+ LKTRTrace("i%lu, 0x%x\n", inode->i_ino, flags);
11053+
11054+ bend = au_ibend(inode);
11055+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
11056+ hi = au_h_iptr(inode, bindex);
11057+ if (hi) {
11058+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
11059+ iwhdentry = au_hi_wh(inode, bindex);
11060+ if (iwhdentry)
11061+ dget(iwhdentry);
11062+ au_igrab(hi);
11063+ au_set_h_iptr(inode, bindex, NULL, 0);
11064+ au_set_h_iptr(inode, bindex, au_igrab(hi),
11065+ flags & ~AuHi_XINO);
11066+ iput(hi);
11067+ dput(iwhdentry);
11068+ /* mutex_unlock(&hi->i_mutex); */
11069+ }
11070+ }
11071+}
11072+
11073+/* ---------------------------------------------------------------------- */
11074+
11075+void au_unpin_gp(struct au_pin *args)
11076+{
11077+ struct au_pin1 *gp;
11078+
11079+ gp = au_pin_gp(args);
11080+ AuDebugOn(!gp);
11081+ if (gp->dentry)
11082+ LKTRTrace("%.*s\n", AuDLNPair(gp->dentry));
11083+ else
11084+ AuTraceEnter();
11085+
11086+ au_do_unpin(gp, NULL);
11087+}
11088+
11089+int au_hin_verify_gen(struct dentry *dentry)
11090+{
11091+ struct super_block *sb = dentry->d_sb;
11092+ au_gen_t sigen;
11093+ struct inode *inode;
11094+
11095+ if (!au_opt_test(au_mntflags(sb), UDBA_INOTIFY))
11096+ return 0;
11097+
11098+ sigen = au_sigen(dentry->d_sb);
11099+ inode = dentry->d_inode;
11100+ return au_digen(dentry) != sigen
11101+ || (inode && au_iigen(inode) != sigen);
11102+}
11103+
11104+/* ---------------------------------------------------------------------- */
11105+
11106+/* cf. fsnotify_change() */
11107+__u32 vfsub_events_notify_change(struct iattr *ia)
11108+{
11109+ __u32 events;
11110+ const unsigned int amtime = (ATTR_ATIME | ATTR_MTIME);
11111+
11112+ events = 0;
11113+ if ((ia->ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE))
11114+ || (ia->ia_valid & amtime) == amtime)
11115+ events |= IN_ATTRIB;
11116+ if ((ia->ia_valid & ATTR_SIZE)
11117+ || (ia->ia_valid & amtime) == ATTR_MTIME)
11118+ events |= IN_MODIFY;
11119+ return events;
11120+}
11121+
11122+void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events,
11123+ struct au_hinode *hinode)
11124+{
11125+ struct au_hinotify *hin;
11126+ struct super_block *sb;
11127+ struct au_hin_ignore *ign;
11128+
11129+ if (!hinode)
11130+ return;
11131+
11132+ hin = hinode->hi_notify;
11133+ if (!hin || !hin->hin_watch.mask)
11134+ return;
11135+
11136+ sb = hin->hin_aufs_inode->i_sb;
11137+ AuDebugOn(!au_opt_test(au_mntflags(sb), UDBA_INOTIFY));
11138+
11139+ ign = vargs->ignore + vargs->nignore++;
11140+ ign->ign_events = events;
11141+ ign->ign_handled = 0;
11142+ ign->ign_hinode = hinode;
11143+
11144+ {
11145+ struct inode *h_inode;
11146+ h_inode = hinode->hi_inode;
11147+ if (!mutex_is_locked(&h_inode->i_mutex))
11148+ au_dbg_blocked();
11149+ IMustLock(h_inode);
11150+ }
11151+}
11152+
11153+static void au_hin_ignore(struct au_hin_ignore *ign)
11154+{
11155+ struct au_hinode *hinode;
11156+ __u32 events;
11157+ struct au_hinotify *hin;
11158+ struct inode *h_inode;
11159+
11160+ hinode = ign->ign_hinode;
11161+ events = ign->ign_events;
11162+ LKTRTrace("0x%x\n", events);
11163+ AuDebugOn(!hinode || !events);
11164+
11165+ hin = hinode->hi_notify;
11166+ h_inode = hinode->hi_inode;
11167+ if (h_inode && hin) {
11168+ LKTRTrace("hi%lu\n", h_inode->i_ino);
11169+#ifdef DbgInotify
11170+ AuDbg("hi%lu, 0x%x\n", h_inode->i_ino, events);
11171+#endif
11172+
11173+ au_spl_add(&ign->ign_list, &hin->hin_ignore);
11174+ /* AuDbg("list_add %p, 0x%x\n", ign, events); */
11175+ }
11176+#if 1 /* todo: test dlgt */
11177+ else
11178+ /*
11179+ * it may happen by this scenario.
11180+ * - a file and its parent dir exist on two branches
11181+ * - a file on the upper branch is opened
11182+ * - the parent dir and the file are removed by udba
11183+ * - the parent is re-accessed, and new dentry/inode in
11184+ * aufs is generated for it, based upon the one on the lower
11185+ * branch
11186+ * - the opened file is re-accessed, re-validated, and it may be
11187+ * re-connected to the new parent dentry
11188+ * it means the file in aufs cannot get the actual removed
11189+ * parent dir on the branch.
11190+ */
11191+ INIT_LIST_HEAD(&ign->ign_list);
11192+#endif
11193+}
11194+
11195+static void au_hin_unignore(struct au_hin_ignore *ign)
11196+{
11197+ struct au_hinode *hinode;
11198+ __u32 events;
11199+ struct au_hinotify *hin;
11200+ struct inode *h_inode;
11201+
11202+ hinode = ign->ign_hinode;
11203+ events = ign->ign_events;
11204+ LKTRTrace("0x%x\n", events);
11205+ /* AuDbg("0x%x\n", events); */
11206+ AuDebugOn(!hinode || !events);
11207+
11208+ hin = hinode->hi_notify;
11209+ h_inode = hinode->hi_inode;
11210+ if (!h_inode || !hin)
11211+ return;
11212+ LKTRTrace("hi%lu\n", h_inode->i_ino);
11213+#ifdef DbgInotify
11214+ AuDbg("hi%lu, 0x%x\n", h_inode->i_ino, events);
11215+#endif
11216+
11217+ spin_lock(&hin->hin_ignore.spin);
11218+ au_hin_list_del(&ign->ign_list);
11219+ spin_unlock(&hin->hin_ignore.spin);
11220+ /* AuDbg("list_del %p, 0x%x\n", ign, events); */
11221+}
11222+
11223+static int au_hin_test_ignore(u32 mask, struct au_hinotify *hin)
11224+{
11225+ int do_ignore;
11226+ u32 events;
11227+ struct au_hin_ignore *ign, *tmp;
11228+ struct list_head *head;
11229+
11230+ do_ignore = 0;
11231+ head = &hin->hin_ignore.head;
11232+ spin_lock(&hin->hin_ignore.spin);
11233+ list_for_each_entry_safe(ign, tmp, head, ign_list) {
11234+ /* AuDbg("ign %p\n", ign); */
11235+ if (ign->ign_pid == current->pid) {
11236+ events = (mask & ign->ign_events);
11237+ if (events) {
11238+ do_ignore = 1;
11239+ ign->ign_handled |= events;
11240+ if (ign->ign_events == ign->ign_handled) {
11241+ list_del_init(&ign->ign_list);
11242+ /*
11243+ AuDbg("list_del %p, 0x%x\n",
11244+ ign, events);
11245+ */
11246+ }
11247+ break;
11248+ }
11249+ }
11250+ }
11251+ spin_unlock(&hin->hin_ignore.spin);
11252+
11253+ return do_ignore;
11254+}
11255+
11256+void vfsub_ignore(struct vfsub_args *vargs)
11257+{
11258+ int n;
11259+ struct au_hin_ignore *ign;
11260+ struct super_block *sb;
11261+ struct au_hinode *hinode;
11262+ struct inode *h_inode;
11263+
11264+ n = vargs->nignore;
11265+ if (!n)
11266+ return;
11267+
11268+ ign = vargs->ignore;
11269+ hinode = ign->ign_hinode;
11270+ sb = hinode->hi_notify->hin_aufs_inode->i_sb;
11271+ h_inode = hinode->hi_inode;
11272+ if (au_opt_test(au_mntflags(sb), UDBA_INOTIFY)) {
11273+ if (!mutex_is_locked(&h_inode->i_mutex))
11274+ au_dbg_blocked();
11275+ IMustLock(h_inode);
11276+ }
11277+ while (n-- > 0) {
11278+ ign->ign_pid = current->pid;
11279+ au_hin_ignore(ign++);
11280+ }
11281+}
11282+
11283+void vfsub_unignore(struct vfsub_args *vargs)
11284+{
11285+ int n;
11286+ struct au_hin_ignore *ign;
11287+
11288+ n = vargs->nignore;
11289+ if (!n)
11290+ return;
11291+
11292+ ign = vargs->ignore;
11293+ while (n-- > 0)
11294+ au_hin_unignore(ign++);
11295+}
11296+
11297+#ifdef CONFIG_AUFS_DEBUG
11298+void au_dbg_hin_list(struct vfsub_args *vargs)
11299+{
11300+ int n;
11301+ struct au_hin_ignore *ign;
11302+
11303+ n = vargs->nignore;
11304+ if (!n)
11305+ return;
11306+
11307+ ign = vargs->ignore;
11308+ while (n-- > 0) {
11309+ /* AuDebugOn(!list_empty(&ign++->ign_list)); */
11310+ if (list_empty(&ign++->ign_list))
11311+ continue;
11312+ ign--;
11313+ AuDbg("%d: pid %d, 0x%x\n",
11314+ n + 1, ign->ign_pid, ign->ign_events);
11315+ au_hin_unignore(ign);
11316+ ign++;
11317+ au_dbg_blocked();
11318+ }
11319+}
11320+#endif
11321+
11322+/* ---------------------------------------------------------------------- */
11323+
11324+static char *in_name(u32 mask)
11325+{
11326+#ifdef CONFIG_AUFS_DEBUG
11327+#define test_ret(flag) if (mask & flag) \
11328+ return #flag;
11329+ test_ret(IN_ACCESS);
11330+ test_ret(IN_MODIFY);
11331+ test_ret(IN_ATTRIB);
11332+ test_ret(IN_CLOSE_WRITE);
11333+ test_ret(IN_CLOSE_NOWRITE);
11334+ test_ret(IN_OPEN);
11335+ test_ret(IN_MOVED_FROM);
11336+ test_ret(IN_MOVED_TO);
11337+ test_ret(IN_CREATE);
11338+ test_ret(IN_DELETE);
11339+ test_ret(IN_DELETE_SELF);
11340+ test_ret(IN_MOVE_SELF);
11341+ test_ret(IN_UNMOUNT);
11342+ test_ret(IN_Q_OVERFLOW);
11343+ test_ret(IN_IGNORED);
11344+ return "";
11345+#undef test_ret
11346+#else
11347+ return "??";
11348+#endif
11349+}
11350+
11351+/* ---------------------------------------------------------------------- */
11352+
11353+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
11354+ struct inode *dir)
11355+{
11356+ struct dentry *dentry, *d, *parent;
11357+ struct qstr *dname;
11358+
11359+ LKTRTrace("%.*s, dir%lu\n", nlen, name, dir->i_ino);
11360+
11361+ parent = d_find_alias(dir);
11362+ if (!parent)
11363+ return NULL;
11364+
11365+ dentry = NULL;
11366+ spin_lock(&dcache_lock);
11367+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
11368+ LKTRTrace("%.*s\n", AuDLNPair(d));
11369+ dname = &d->d_name;
11370+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
11371+ continue;
11372+ if (!atomic_read(&d->d_count) || !d->d_fsdata) {
11373+ spin_lock(&d->d_lock);
11374+ __d_drop(d);
11375+ spin_unlock(&d->d_lock);
11376+ continue;
11377+ }
11378+
11379+ dentry = dget(d);
11380+ break;
11381+ }
11382+ spin_unlock(&dcache_lock);
11383+ dput(parent);
11384+
11385+ if (dentry) {
11386+#if 0
11387+ lktr_set_pid(current->pid, LktrArrayPid);
11388+ AuDbgDentry(dentry);
11389+ lktr_clear_pid(current->pid, LktrArrayPid);
11390+#endif
11391+ di_write_lock_child(dentry);
11392+ }
11393+ return dentry;
11394+}
11395+
11396+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
11397+ aufs_bindex_t bindex, ino_t h_ino)
11398+{
11399+ struct inode *inode;
11400+ struct au_xino_entry xinoe;
11401+ int err;
11402+
11403+ LKTRTrace("b%d, hi%lu\n", bindex, (unsigned long)h_ino);
11404+ AuDebugOn(!au_opt_test_xino(au_mntflags(sb)));
11405+
11406+ inode = NULL;
11407+ err = au_xino_read(sb, bindex, h_ino, &xinoe);
11408+ if (!err && xinoe.ino)
11409+ inode = ilookup(sb, xinoe.ino);
11410+ if (!inode)
11411+ goto out;
11412+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11413+ AuWarn("wrong root branch\n");
11414+ iput(inode);
11415+ inode = NULL;
11416+ goto out;
11417+ }
11418+
11419+ ii_write_lock_child(inode);
11420+
11421+ out:
11422+ return inode;
11423+}
11424+
11425+static int hin_xino(struct inode *inode, struct inode *h_inode)
11426+{
11427+ int err;
11428+ aufs_bindex_t bindex, bend, bfound, bstart;
11429+ struct inode *h_i;
11430+
11431+ LKTRTrace("i%lu, hi%lu\n", inode->i_ino, h_inode->i_ino);
11432+
11433+ err = 0;
11434+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11435+ AuWarn("branch root dir was changed\n");
11436+ goto out;
11437+ }
11438+
11439+ bfound = -1;
11440+ bend = au_ibend(inode);
11441+ bstart = au_ibstart(inode);
11442+#if 0 /* reserved for future use */
11443+ if (bindex == bend) {
11444+ /* keep this ino in rename case */
11445+ goto out;
11446+ }
11447+#endif
11448+ for (bindex = bstart; bindex <= bend; bindex++) {
11449+ if (au_h_iptr(inode, bindex) == h_inode) {
11450+ bfound = bindex;
11451+ break;
11452+ }
11453+ }
11454+ if (bfound < 0)
11455+ goto out;
11456+
11457+ for (bindex = bstart; bindex <= bend; bindex++) {
11458+ h_i = au_h_iptr(inode, bindex);
11459+ if (h_i)
11460+ err = au_xino_write0(inode->i_sb, bindex, h_i->i_ino,
11461+ 0);
11462+ /* ignore this error */
11463+ /* bad action? */
11464+ }
11465+
11466+ /* children inode number will be broken */
11467+
11468+ out:
11469+ AuTraceErr(err);
11470+ return err;
11471+}
11472+
11473+static int hin_gen_tree(struct dentry *dentry)
11474+{
11475+ int err, i, j, ndentry;
11476+ struct au_dcsub_pages dpages;
11477+ struct au_dpage *dpage;
11478+ struct dentry **dentries;
11479+
11480+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
11481+
11482+ err = au_dpages_init(&dpages, GFP_NOFS);
11483+ if (unlikely(err))
11484+ goto out;
11485+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
11486+ if (unlikely(err))
11487+ goto out_dpages;
11488+
11489+ for (i = 0; i < dpages.ndpage; i++) {
11490+ dpage = dpages.dpages + i;
11491+ dentries = dpage->dentries;
11492+ ndentry = dpage->ndentry;
11493+ for (j = 0; j < ndentry; j++) {
11494+ struct dentry *d;
11495+ d = dentries[j];
11496+ LKTRTrace("%.*s\n", AuDLNPair(d));
11497+ if (IS_ROOT(d))
11498+ continue;
11499+
11500+ d_drop(d);
11501+ au_digen_dec(d);
11502+ if (d->d_inode)
11503+ /* todo: reset children xino?
11504+ cached children only? */
11505+ au_iigen_dec(d->d_inode);
11506+ }
11507+ }
11508+
11509+ out_dpages:
11510+ au_dpages_free(&dpages);
11511+
11512+ /* discard children */
11513+ dentry_unhash(dentry);
11514+ dput(dentry);
11515+ out:
11516+ AuTraceErr(err);
11517+ return err;
11518+}
11519+
11520+/*
11521+ * return 0 if processed.
11522+ */
11523+static int hin_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
11524+ const unsigned int isdir)
11525+{
11526+ int err;
11527+ struct dentry *d;
11528+ struct qstr *dname;
11529+
11530+ LKTRTrace("%.*s, i%lu\n", nlen, name, inode->i_ino);
11531+
11532+ err = 1;
11533+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11534+ AuWarn("branch root dir was changed\n");
11535+ err = 0;
11536+ goto out;
11537+ }
11538+
11539+ if (!isdir) {
11540+ AuDebugOn(!name);
11541+ au_iigen_dec(inode);
11542+ spin_lock(&dcache_lock);
11543+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
11544+ dname = &d->d_name;
11545+ if (dname->len != nlen
11546+ && memcmp(dname->name, name, nlen))
11547+ continue;
11548+ err = 0;
11549+ spin_lock(&d->d_lock);
11550+ __d_drop(d);
11551+ au_digen_dec(d);
11552+ spin_unlock(&d->d_lock);
11553+ break;
11554+ }
11555+ spin_unlock(&dcache_lock);
11556+ } else {
11557+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
11558+ d = d_find_alias(inode);
11559+ if (!d) {
11560+ au_iigen_dec(inode);
11561+ goto out;
11562+ }
11563+
11564+ dname = &d->d_name;
11565+ if (dname->len == nlen && !memcmp(dname->name, name, nlen))
11566+ err = hin_gen_tree(d);
11567+ dput(d);
11568+ }
11569+
11570+ out:
11571+ AuTraceErr(err);
11572+ return err;
11573+}
11574+
11575+static int hin_gen_by_name(struct dentry *dentry, const unsigned int isdir)
11576+{
11577+ int err;
11578+ struct inode *inode;
11579+
11580+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
11581+
11582+ inode = dentry->d_inode;
11583+ if (IS_ROOT(dentry)
11584+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
11585+ ) {
11586+ AuWarn("branch root dir was changed\n");
11587+ return 0;
11588+ }
11589+
11590+ err = 0;
11591+ if (!isdir) {
11592+ d_drop(dentry);
11593+ au_digen_dec(dentry);
11594+ if (inode)
11595+ au_iigen_dec(inode);
11596+ } else {
11597+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
11598+ if (inode)
11599+ err = hin_gen_tree(dentry);
11600+ }
11601+
11602+ AuTraceErr(err);
11603+ return err;
11604+}
11605+
11606+static void hin_attr(struct inode *inode, struct inode *h_inode)
11607+{
11608+ struct dentry *h_dentry;
11609+
11610+ LKTRTrace("i%lu, hi%lu\n", inode->i_ino, h_inode->i_ino);
11611+
11612+ if (au_h_iptr(inode, au_ibstart(inode)) != h_inode)
11613+ return;
11614+
11615+ h_dentry = d_find_alias(h_inode);
11616+ if (h_dentry) {
11617+ au_update_fuse_h_inode(NULL, h_dentry);
11618+ /* ignore an error*/
11619+ dput(h_dentry);
11620+ }
11621+
11622+ au_cpup_attr_all(inode, /*force*/1);
11623+}
11624+
11625+/* ---------------------------------------------------------------------- */
11626+
11627+/* hinotify job flags */
11628+#define AuHinJob_XINO0 1
11629+#define AuHinJob_GEN (1 << 1)
11630+#define AuHinJob_DIRENT (1 << 2)
11631+#define AuHinJob_ATTR (1 << 3)
11632+#define AuHinJob_ISDIR (1 << 4)
11633+#define AuHinJob_TRYXINO0 (1 << 5)
11634+#define AuHinJob_MNTPNT (1 << 6)
11635+#define au_ftest_hinjob(flags, name) ((flags) & AuHinJob_##name)
11636+#define au_fset_hinjob(flags, name) { (flags) |= AuHinJob_##name; }
11637+#define au_fclr_hinjob(flags, name) { (flags) &= ~AuHinJob_##name; }
11638+
11639+struct hin_job_args {
11640+ unsigned int flags;
11641+ struct inode *inode, *h_inode, *dir, *h_dir;
11642+ struct dentry *dentry;
11643+ char *h_name;
11644+ int h_nlen;
11645+};
11646+
11647+static int hin_job(struct hin_job_args *a)
11648+{
11649+ const unsigned int isdir = au_ftest_hinjob(a->flags, ISDIR);
11650+
11651+ /* reset xino */
11652+ if (au_ftest_hinjob(a->flags, XINO0) && a->inode)
11653+ hin_xino(a->inode, a->h_inode);
11654+ /* ignore this error */
11655+
11656+ if (au_ftest_hinjob(a->flags, TRYXINO0)
11657+ && a->inode
11658+ && a->h_inode) {
11659+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11660+ if (!a->h_inode->i_nlink)
11661+ hin_xino(a->inode, a->h_inode);
11662+ /* ignore this error */
11663+ mutex_unlock(&a->h_inode->i_mutex);
11664+ }
11665+
11666+ /* make the generation obsolete */
11667+ if (au_ftest_hinjob(a->flags, GEN)) {
11668+ int err = -1;
11669+ if (a->inode)
11670+ err = hin_gen_by_inode(a->h_name, a->h_nlen, a->inode,
11671+ isdir);
11672+ if (err && a->dentry)
11673+ hin_gen_by_name(a->dentry, isdir);
11674+ /* ignore this error */
11675+ }
11676+
11677+ /* make dir entries obsolete */
11678+ if (au_ftest_hinjob(a->flags, DIRENT) && a->inode) {
11679+ struct au_vdir *vdir;
11680+ IiMustWriteLock(a->inode);
11681+ vdir = au_ivdir(a->inode);
11682+ if (vdir)
11683+ vdir->vd_jiffy = 0;
11684+ /* IMustLock(a->inode); */
11685+ /* a->inode->i_version++; */
11686+ }
11687+
11688+ /* update the attr */
11689+ if (au_ftest_hinjob(a->flags, ATTR) && a->inode && a->h_inode) {
11690+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11691+ hin_attr(a->inode, a->h_inode);
11692+ mutex_unlock(&a->h_inode->i_mutex);
11693+ }
11694+
11695+ /* can do nothing but warn */
11696+ if (au_ftest_hinjob(a->flags, MNTPNT)
11697+ && a->dentry
11698+ && d_mountpoint(a->dentry))
11699+ AuWarn("mount-point %.*s is removed or renamed\n",
11700+ AuDLNPair(a->dentry));
11701+
11702+ return 0;
11703+}
11704+
11705+/* ---------------------------------------------------------------------- */
11706+
11707+enum { CHILD, PARENT };
11708+struct postproc_args {
11709+ struct inode *h_dir, *dir, *h_child_inode;
11710+ u32 mask;
11711+ unsigned int flags[2];
11712+ unsigned int h_child_nlen;
11713+ char h_child_name[];
11714+};
11715+
11716+static void postproc(void *_args)
11717+{
11718+ struct postproc_args *a = _args;
11719+ struct super_block *sb;
11720+ aufs_bindex_t bindex, bend, bfound;
11721+ unsigned char xino, try_iput;
11722+ int err;
11723+ struct inode *inode;
11724+ ino_t h_ino;
11725+ struct hin_job_args args;
11726+ struct dentry *dentry;
11727+ struct au_sbinfo *sbinfo;
11728+
11729+ AuDebugOn(!_args);
11730+ AuDebugOn(!a->h_dir);
11731+ AuDebugOn(!a->dir);
11732+ AuDebugOn(!a->mask);
11733+ LKTRTrace("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
11734+ a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
11735+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
11736+
11737+ inode = NULL;
11738+ dentry = NULL;
11739+ /*
11740+ * do not lock a->dir->i_mutex here
11741+ * because of d_revalidate() may cause a deadlock.
11742+ */
11743+#if 0
11744+ /*
11745+ * just wait for the dir becoming non-busy.
11746+ * for instance, prevent NFSD lookup from "nlink == 0" message.
11747+ * but it is not guranteed.
11748+ */
11749+ mutex_lock(&a->dir->i_mutex);
11750+ mutex_unlock(&a->dir->i_mutex);
11751+#endif
11752+
11753+ sb = a->dir->i_sb;
11754+ AuDebugOn(!sb);
11755+ sbinfo = au_sbi(sb);
11756+ AuDebugOn(!sbinfo);
11757+ /* big aufs lock */
11758+ si_noflush_write_lock(sb);
11759+
11760+ ii_read_lock_parent(a->dir);
11761+ bfound = -1;
11762+ bend = au_ibend(a->dir);
11763+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
11764+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
11765+ bfound = bindex;
11766+ break;
11767+ }
11768+ ii_read_unlock(a->dir);
11769+ if (unlikely(bfound < 0))
11770+ goto out;
11771+
11772+ xino = !!au_opt_test_xino(au_mntflags(sb));
11773+ h_ino = 0;
11774+ if (a->h_child_inode)
11775+ h_ino = a->h_child_inode->i_ino;
11776+
11777+ if (a->h_child_nlen
11778+ && (au_ftest_hinjob(a->flags[CHILD], GEN)
11779+ || au_ftest_hinjob(a->flags[CHILD], MNTPNT)))
11780+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
11781+ a->dir);
11782+ try_iput = 0;
11783+ if (dentry)
11784+ inode = dentry->d_inode;
11785+ if (xino && !inode && h_ino
11786+ && (au_ftest_hinjob(a->flags[CHILD], XINO0)
11787+ || au_ftest_hinjob(a->flags[CHILD], TRYXINO0)
11788+ || au_ftest_hinjob(a->flags[CHILD], GEN)
11789+ || au_ftest_hinjob(a->flags[CHILD], ATTR))) {
11790+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
11791+ try_iput = 1;
11792+ }
11793+
11794+ args.flags = a->flags[CHILD];
11795+ args.dentry = dentry;
11796+ args.inode = inode;
11797+ args.h_inode = a->h_child_inode;
11798+ args.dir = a->dir;
11799+ args.h_dir = a->h_dir;
11800+ args.h_name = a->h_child_name;
11801+ args.h_nlen = a->h_child_nlen;
11802+ err = hin_job(&args);
11803+ if (dentry) {
11804+ if (dentry->d_fsdata)
11805+ di_write_unlock(dentry);
11806+ dput(dentry);
11807+ }
11808+ if (inode && try_iput) {
11809+ ii_write_unlock(inode);
11810+ iput(inode);
11811+ }
11812+
11813+ ii_write_lock_parent(a->dir);
11814+ args.flags = a->flags[PARENT];
11815+ args.dentry = NULL;
11816+ args.inode = a->dir;
11817+ args.h_inode = a->h_dir;
11818+ args.dir = NULL;
11819+ args.h_dir = NULL;
11820+ args.h_name = NULL;
11821+ args.h_nlen = 0;
11822+ err = hin_job(&args);
11823+ ii_write_unlock(a->dir);
11824+
11825+ out:
11826+ au_nwt_done(&sbinfo->si_nowait);
11827+ si_write_unlock(sb);
11828+
11829+ iput(a->h_child_inode);
11830+ iput(a->h_dir);
11831+ iput(a->dir);
11832+ kfree(a);
11833+}
11834+
11835+static void aufs_inotify(struct inotify_watch *watch, u32 wd, u32 mask,
11836+ u32 cookie, const char *h_child_name,
11837+ struct inode *h_child_inode)
11838+{
11839+ struct au_hinotify *hinotify;
11840+ struct postproc_args *args;
11841+ int len, wkq_err;
11842+ unsigned char isdir, isroot, wh;
11843+ char *p;
11844+ struct inode *dir;
11845+ unsigned int flags[2];
11846+
11847+ LKTRTrace("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
11848+ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
11849+ h_child_name ? h_child_name : "",
11850+ h_child_inode ? h_child_inode->i_ino : 0);
11851+
11852+ /* if IN_UNMOUNT happens, there must be another bug */
11853+ if (mask & (IN_IGNORED | IN_UNMOUNT)) {
11854+ put_inotify_watch(watch);
11855+ return;
11856+ }
11857+
11858+#ifdef DbgInotify
11859+ if (!h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME))
11860+ AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
11861+ " hi%lu\n",
11862+ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
11863+ h_child_name ? h_child_name : "",
11864+ h_child_inode ? h_child_inode->i_ino : 0);
11865+#endif
11866+
11867+ hinotify = container_of(watch, struct au_hinotify, hin_watch);
11868+ AuDebugOn(!hinotify || !hinotify->hin_aufs_inode);
11869+ if (au_hin_test_ignore(mask, hinotify)) {
11870+#ifdef DbgInotify
11871+ AuDbg("ignored\n");
11872+#endif
11873+ return;
11874+ }
11875+#if 0 /* tmp debug */
11876+ if (h_child_name && !strcmp(h_child_name, AUFS_XINO_FNAME)) {
11877+ AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
11878+ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
11879+ h_child_name ? h_child_name : "",
11880+ h_child_inode ? h_child_inode->i_ino : 0);
11881+ //au_dbg_blocked();
11882+ }
11883+#endif
11884+
11885+ dir = igrab(hinotify->hin_aufs_inode);
11886+ if (!dir)
11887+ return;
11888+ isroot = (dir->i_ino == AUFS_ROOT_INO);
11889+ len = 0;
11890+ wh = 0;
11891+ if (h_child_name) {
11892+ len = strlen(h_child_name);
11893+ if (!memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
11894+ h_child_name += AUFS_WH_PFX_LEN;
11895+ len -= AUFS_WH_PFX_LEN;
11896+ wh = 1;
11897+ }
11898+ }
11899+
11900+ isdir = 0;
11901+ if (h_child_inode)
11902+ isdir = !!S_ISDIR(h_child_inode->i_mode);
11903+ flags[PARENT] = AuHinJob_ISDIR;
11904+ flags[CHILD] = 0;
11905+ if (isdir)
11906+ flags[CHILD] = AuHinJob_ISDIR;
11907+ switch (mask & IN_ALL_EVENTS) {
11908+ case IN_MODIFY:
11909+ /*FALLTHROUGH*/
11910+ case IN_ATTRIB:
11911+ if (h_child_inode) {
11912+ if (!wh)
11913+ au_fset_hinjob(flags[CHILD], ATTR);
11914+ } else
11915+ au_fset_hinjob(flags[PARENT], ATTR);
11916+ break;
11917+
11918+ /* IN_MOVED_FROM is the first event in rename(2) */
11919+ case IN_MOVED_FROM:
11920+ case IN_MOVED_TO:
11921+ AuDebugOn(!h_child_name || !h_child_inode);
11922+ au_fset_hinjob(flags[CHILD], GEN);
11923+ au_fset_hinjob(flags[CHILD], ATTR);
11924+ if (1 || isdir)
11925+ au_fset_hinjob(flags[CHILD], XINO0);
11926+ au_fset_hinjob(flags[CHILD], MNTPNT);
11927+
11928+ au_fset_hinjob(flags[PARENT], ATTR);
11929+ au_fset_hinjob(flags[PARENT], DIRENT);
11930+ break;
11931+
11932+ case IN_CREATE:
11933+ AuDebugOn(!h_child_name || !h_child_inode);
11934+ au_fset_hinjob(flags[PARENT], ATTR);
11935+ au_fset_hinjob(flags[PARENT], DIRENT);
11936+ au_fset_hinjob(flags[CHILD], GEN);
11937+ /* hard link */
11938+ if (!isdir && h_child_inode->i_nlink > 1)
11939+ au_fset_hinjob(flags[CHILD], ATTR);
11940+ break;
11941+
11942+ case IN_DELETE:
11943+ /*
11944+ * aufs never be able to get this child inode.
11945+ * revalidation should be in d_revalidate()
11946+ * by checking i_nlink, i_generation or d_unhashed().
11947+ */
11948+ AuDebugOn(!h_child_name);
11949+ au_fset_hinjob(flags[PARENT], ATTR);
11950+ au_fset_hinjob(flags[PARENT], DIRENT);
11951+ au_fset_hinjob(flags[CHILD], GEN);
11952+ au_fset_hinjob(flags[CHILD], TRYXINO0);
11953+ au_fset_hinjob(flags[CHILD], MNTPNT);
11954+ break;
11955+
11956+ case IN_DELETE_SELF:
11957+#if 0
11958+ if (!isroot)
11959+ au_fset_hinjob(flags[PARENT], GEN);
11960+ /*FALLTHROUGH*/
11961+#endif
11962+
11963+ case IN_MOVE_SELF:
11964+#if 0
11965+ /*
11966+ * when an inotify is set to an aufs inode,
11967+ * such inode can be isolated and this event can be fired
11968+ * solely.
11969+ */
11970+ AuDebugOn(h_child_name || h_child_inode);
11971+ if (unlikely(isroot)) {
11972+ AuWarn("root branch was moved\n");
11973+ iput(dir);
11974+ return;
11975+ }
11976+ au_fset_hinjob(flags[PARENT], XINO0);
11977+ au_fset_hinjob(flags[PARENT], GEN);
11978+ au_fset_hinjob(flags[PARENT], ATTR);
11979+ au_fset_hinjob(flags[PARENT], DIRENT);
11980+ /* au_fset_hinjob(flags[PARENT], MNTPNT); */
11981+ break;
11982+#endif
11983+
11984+ case IN_ACCESS:
11985+ default:
11986+ AuDebugOn(1);
11987+ }
11988+
11989+ if (wh)
11990+ h_child_inode = NULL;
11991+
11992+ /* iput() and kfree() will be called in postproc() */
11993+ /*
11994+ * inotify_mutex is already acquired and kmalloc/prune_icache may lock
11995+ * iprune_mutex. strange.
11996+ */
11997+ lockdep_off();
11998+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
11999+ lockdep_on();
12000+ if (unlikely(!args)) {
12001+ AuErr1("no memory\n");
12002+ iput(dir);
12003+ return;
12004+ }
12005+ args->flags[PARENT] = flags[PARENT];
12006+ args->flags[CHILD] = flags[CHILD];
12007+ args->mask = mask;
12008+ args->dir = dir;
12009+ args->h_dir = igrab(watch->inode);
12010+ if (h_child_inode)
12011+ h_child_inode = igrab(h_child_inode); /* can be NULL */
12012+ args->h_child_inode = h_child_inode;
12013+ args->h_child_nlen = len;
12014+ if (len) {
12015+ p = (void *)args;
12016+ p += sizeof(*args);
12017+ memcpy(p, h_child_name, len + 1);
12018+ }
12019+
12020+ lockdep_off();
12021+ wkq_err = au_wkq_nowait(postproc, args, dir->i_sb, /*dlgt*/0);
12022+ lockdep_on();
12023+ if (unlikely(wkq_err))
12024+ AuErr("wkq %d\n", wkq_err);
12025+}
12026+
12027+static void aufs_inotify_destroy(struct inotify_watch *watch)
12028+{
12029+ return;
12030+}
12031+
12032+static struct inotify_operations aufs_inotify_ops = {
12033+ .handle_event = aufs_inotify,
12034+ .destroy_watch = aufs_inotify_destroy
12035+};
12036+
12037+/* ---------------------------------------------------------------------- */
12038+
12039+static void au_hin_destroy_cache(void)
12040+{
12041+ kmem_cache_destroy(au_cachep[AuCache_HINOTIFY]);
12042+ au_cachep[AuCache_HINOTIFY] = NULL;
12043+}
12044+
12045+int __init au_inotify_init(void)
12046+{
12047+ int err;
12048+
12049+ err = -ENOMEM;
12050+ au_cachep[AuCache_HINOTIFY] = AuCache(au_hinotify);
12051+ if (au_cachep[AuCache_HINOTIFY]) {
12052+ err = 0;
12053+ in_handle = inotify_init(&aufs_inotify_ops);
12054+ if (IS_ERR(in_handle)) {
12055+ err = PTR_ERR(in_handle);
12056+ au_hin_destroy_cache();
12057+ }
12058+ }
12059+ AuTraceErr(err);
12060+ return err;
12061+}
12062+
12063+void au_inotify_fin(void)
12064+{
12065+ inotify_destroy(in_handle);
12066+ if (au_cachep[AuCache_HINOTIFY])
12067+ au_hin_destroy_cache();
12068+}
12069diff -urN linux/fs/aufs/iinfo.c linux-aufs/fs/aufs/iinfo.c
12070--- linux/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
12071+++ linux-aufs/fs/aufs/iinfo.c 2009-03-12 16:18:04.000000000 +0100
12072@@ -0,0 +1,284 @@
12073+/*
12074+ * Copyright (C) 2005-2009 Junjiro Okajima
12075+ *
12076+ * This program, aufs is free software; you can redistribute it and/or modify
12077+ * it under the terms of the GNU General Public License as published by
12078+ * the Free Software Foundation; either version 2 of the License, or
12079+ * (at your option) any later version.
12080+ *
12081+ * This program is distributed in the hope that it will be useful,
12082+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12083+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12084+ * GNU General Public License for more details.
12085+ *
12086+ * You should have received a copy of the GNU General Public License
12087+ * along with this program; if not, write to the Free Software
12088+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12089+ */
12090+
12091+/*
12092+ * inode private data
12093+ *
12094+ * $Id$
12095+ */
12096+
12097+#include "aufs.h"
12098+
12099+struct au_iinfo *au_ii(struct inode *inode)
12100+{
12101+ struct au_iinfo *iinfo;
12102+
12103+ iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
12104+ /* bad_inode case */
12105+ if (unlikely(!iinfo->ii_hinode))
12106+ return NULL;
12107+ AuDebugOn(!iinfo->ii_hinode
12108+ /* || au_sbi(inode->i_sb)->si_bend < iinfo->ii_bend */
12109+ || iinfo->ii_bend < iinfo->ii_bstart);
12110+ return iinfo;
12111+}
12112+
12113+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
12114+{
12115+ struct inode *hidden_inode;
12116+
12117+ /* lock free root dinfo/inode */
12118+ if (inode->i_ino != AUFS_ROOT_INO) {
12119+ IiMustAnyLock(inode);
12120+ AuDebugOn(bindex < 0 || au_ibend(inode) < bindex);
12121+ } else {
12122+ SiMustAnyLock(inode->i_sb);
12123+ AuDebugOn(bindex < 0 || au_sbend(inode->i_sb) < bindex);
12124+ }
12125+ hidden_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
12126+ AuDebugOn(hidden_inode && atomic_read(&hidden_inode->i_count) <= 0);
12127+ return hidden_inode;
12128+}
12129+
12130+aufs_bindex_t au_ii_br_id(struct inode *inode, aufs_bindex_t bindex)
12131+{
12132+ IiMustAnyLock(inode);
12133+ AuDebugOn(bindex < 0
12134+ || au_ibend(inode) < bindex
12135+ || !au_ii(inode)->ii_hinode[0 + bindex].hi_inode);
12136+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
12137+}
12138+
12139+/* todo: hard/soft set? */
12140+void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
12141+{
12142+ struct au_iinfo *iinfo = au_ii(inode);
12143+ struct inode *h_inode;
12144+
12145+ IiMustWriteLock(inode);
12146+ AuDebugOn(au_sbend(inode->i_sb) < bindex);
12147+ iinfo->ii_bstart = bindex;
12148+ h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
12149+ if (h_inode)
12150+ au_cpup_igen(inode, h_inode);
12151+}
12152+
12153+unsigned int au_hi_flags(struct inode *inode, int isdir)
12154+{
12155+ unsigned int flags;
12156+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
12157+
12158+ flags = 0;
12159+ if (au_opt_test_xino(mnt_flags))
12160+ au_fset_hi(flags, XINO);
12161+ if (isdir && au_opt_test(mnt_flags, UDBA_INOTIFY))
12162+ au_fset_hi(flags, NOTIFY);
12163+ return flags;
12164+}
12165+
12166+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12167+ struct inode *h_inode, unsigned int flags)
12168+{
12169+ struct au_hinode *hinode;
12170+ struct inode *hi;
12171+ struct au_iinfo *iinfo = au_ii(inode);
12172+
12173+ LKTRTrace("i%lu, b%d, hi%lu, flags 0x%x\n",
12174+ inode->i_ino, bindex, h_inode ? h_inode->i_ino : 0, flags);
12175+ IiMustWriteLock(inode);
12176+ hinode = iinfo->ii_hinode + bindex;
12177+ hi = hinode->hi_inode;
12178+ AuDebugOn(bindex < au_ibstart(inode) || au_ibend(inode) < bindex);
12179+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
12180+ AuDebugOn(h_inode && hi);
12181+
12182+ if (hi)
12183+ au_hiput(hinode);
12184+ hinode->hi_inode = h_inode;
12185+ if (h_inode) {
12186+ int err;
12187+ struct super_block *sb = inode->i_sb;
12188+
12189+ if (bindex == iinfo->ii_bstart)
12190+ au_cpup_igen(inode, h_inode);
12191+ hinode->hi_id = au_sbr_id(sb, bindex);
12192+ if (au_ftest_hi(flags, XINO)) {
12193+ struct au_xino_entry xinoe = {
12194+ .ino = inode->i_ino,
12195+ /* .h_gen = h_inode->i_generation */
12196+ };
12197+ err = au_xino_write(sb, bindex, h_inode->i_ino, &xinoe);
12198+ if (unlikely(err))
12199+ AuIOErr1("failed au_xino_write() %d\n", err);
12200+ }
12201+
12202+ if (au_ftest_hi(flags, NOTIFY)
12203+ && au_br_hinotifyable(au_sbr_perm(sb, bindex))) {
12204+ err = au_hin_alloc(hinode, inode, h_inode);
12205+ if (unlikely(err))
12206+ AuIOErr1("au_hin_alloc() %d\n", err);
12207+ }
12208+ }
12209+}
12210+
12211+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12212+ struct dentry *h_wh)
12213+{
12214+ struct au_hinode *hinode;
12215+
12216+ IiMustWriteLock(inode);
12217+ hinode = au_ii(inode)->ii_hinode + bindex;
12218+ AuDebugOn(hinode->hi_whdentry);
12219+ hinode->hi_whdentry = h_wh;
12220+}
12221+
12222+void au_update_iigen(struct inode *inode)
12223+{
12224+ AuDebugOn(!inode->i_sb);
12225+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
12226+ /* smp_mb(); */ /* atomic_set */
12227+}
12228+
12229+/* it may be called at remount time, too */
12230+void au_update_brange(struct inode *inode, int do_put_zero)
12231+{
12232+ struct au_iinfo *iinfo;
12233+
12234+ LKTRTrace("i%lu, %d\n", inode->i_ino, do_put_zero);
12235+ IiMustWriteLock(inode);
12236+
12237+ iinfo = au_ii(inode);
12238+ if (!iinfo || iinfo->ii_bstart < 0)
12239+ return;
12240+
12241+ if (do_put_zero) {
12242+ aufs_bindex_t bindex;
12243+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12244+ bindex++) {
12245+ struct inode *h_i;
12246+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
12247+ if (h_i && !h_i->i_nlink)
12248+ au_set_h_iptr(inode, bindex, NULL, 0);
12249+ }
12250+ }
12251+
12252+ iinfo->ii_bstart = -1;
12253+ while (++iinfo->ii_bstart <= iinfo->ii_bend)
12254+ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
12255+ break;
12256+ if (iinfo->ii_bstart > iinfo->ii_bend) {
12257+ iinfo->ii_bstart = -1;
12258+ iinfo->ii_bend = -1;
12259+ return;
12260+ }
12261+
12262+ iinfo->ii_bend++;
12263+ while (0 <= --iinfo->ii_bend)
12264+ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
12265+ break;
12266+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
12267+}
12268+
12269+/* ---------------------------------------------------------------------- */
12270+
12271+int au_iinfo_init(struct inode *inode)
12272+{
12273+ struct au_iinfo *iinfo;
12274+ struct super_block *sb;
12275+ int nbr, i;
12276+
12277+ sb = inode->i_sb;
12278+ AuDebugOn(!sb);
12279+ iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
12280+ AuDebugOn(iinfo->ii_hinode);
12281+ nbr = au_sbend(sb) + 1;
12282+ if (nbr <= 0)
12283+ nbr = 1;
12284+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
12285+ if (iinfo->ii_hinode) {
12286+ for (i = 0; i < nbr; i++)
12287+ iinfo->ii_hinode[i].hi_id = -1;
12288+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
12289+ /* smp_mb(); */ /* atomic_set */
12290+ au_rw_init_nolock(&iinfo->ii_rwsem);
12291+ iinfo->ii_bstart = -1;
12292+ iinfo->ii_bend = -1;
12293+ iinfo->ii_vdir = NULL;
12294+ return 0;
12295+ }
12296+ return -ENOMEM;
12297+}
12298+
12299+static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
12300+ ino_t ino)
12301+{
12302+ int err, locked;
12303+ aufs_bindex_t bindex;
12304+
12305+ err = 0;
12306+ locked = si_noflush_read_trylock(sb); /* crucio! */
12307+ bindex = au_br_index(sb, hinode->hi_id);
12308+ if (bindex >= 0)
12309+ err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
12310+ /* error action? */
12311+ if (locked)
12312+ si_read_unlock(sb);
12313+ return err;
12314+}
12315+
12316+void au_iinfo_fin(struct inode *inode)
12317+{
12318+ struct au_iinfo *iinfo;
12319+ aufs_bindex_t bend;
12320+ unsigned char unlinked;
12321+ struct au_hinode *hi;
12322+ struct super_block *sb;
12323+ ino_t ino;
12324+
12325+ iinfo = au_ii(inode);
12326+ /* bad_inode case */
12327+ if (!iinfo)
12328+ return;
12329+
12330+ if (iinfo->ii_vdir)
12331+ au_vdir_free(iinfo->ii_vdir);
12332+
12333+ if (iinfo->ii_bstart >= 0) {
12334+ sb = inode->i_sb;
12335+ unlinked = !inode->i_nlink;
12336+ ino = 0;
12337+ if (unlinked)
12338+ ino = inode->i_ino;
12339+ hi = iinfo->ii_hinode + iinfo->ii_bstart;
12340+ bend = iinfo->ii_bend;
12341+ while (iinfo->ii_bstart++ <= bend) {
12342+ if (hi->hi_inode) {
12343+ if (unlinked || !hi->hi_inode->i_nlink) {
12344+ au_iinfo_write0(sb, hi, ino);
12345+ /* ignore this error */
12346+ ino = 0;
12347+ }
12348+ au_hiput(hi);
12349+ }
12350+ hi++;
12351+ }
12352+ }
12353+
12354+ kfree(iinfo->ii_hinode);
12355+ au_rwsem_destroy(&iinfo->ii_rwsem);
12356+}
12357diff -urN linux/fs/aufs/inode.c linux-aufs/fs/aufs/inode.c
12358--- linux/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
12359+++ linux-aufs/fs/aufs/inode.c 2009-03-12 16:18:04.000000000 +0100
12360@@ -0,0 +1,421 @@
12361+/*
12362+ * Copyright (C) 2005-2009 Junjiro Okajima
12363+ *
12364+ * This program, aufs is free software; you can redistribute it and/or modify
12365+ * it under the terms of the GNU General Public License as published by
12366+ * the Free Software Foundation; either version 2 of the License, or
12367+ * (at your option) any later version.
12368+ *
12369+ * This program is distributed in the hope that it will be useful,
12370+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12371+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12372+ * GNU General Public License for more details.
12373+ *
12374+ * You should have received a copy of the GNU General Public License
12375+ * along with this program; if not, write to the Free Software
12376+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12377+ */
12378+
12379+/*
12380+ * inode functions
12381+ *
12382+ * $Id$
12383+ */
12384+
12385+#include "aufs.h"
12386+
12387+int au_refresh_hinode_self(struct inode *inode)
12388+{
12389+ int err, new_sz, update;
12390+ struct inode *first;
12391+ struct au_hinode *p, *q, tmp;
12392+ struct super_block *sb;
12393+ struct au_iinfo *iinfo;
12394+ aufs_bindex_t bindex, bend, new_bindex;
12395+
12396+ LKTRTrace("i%lu\n", inode->i_ino);
12397+ IiMustWriteLock(inode);
12398+
12399+ err = -ENOMEM;
12400+ update = 0;
12401+ sb = inode->i_sb;
12402+ bend = au_sbend(sb);
12403+ new_sz = sizeof(*iinfo->ii_hinode) * (bend + 1);
12404+ iinfo = au_ii(inode);
12405+ p = au_kzrealloc(iinfo->ii_hinode, sizeof(*p) * (iinfo->ii_bend + 1),
12406+ new_sz, GFP_NOFS);
12407+ if (unlikely(!p))
12408+ goto out;
12409+
12410+ iinfo->ii_hinode = p;
12411+ p = iinfo->ii_hinode + iinfo->ii_bstart;
12412+ first = p->hi_inode;
12413+ err = 0;
12414+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12415+ bindex++, p++) {
12416+ if (!p->hi_inode)
12417+ continue;
12418+
12419+ new_bindex = au_br_index(sb, p->hi_id);
12420+ if (new_bindex == bindex)
12421+ continue;
12422+ if (new_bindex < 0) {
12423+ update++;
12424+ au_hiput(p);
12425+ p->hi_inode = NULL;
12426+ continue;
12427+ }
12428+
12429+ if (new_bindex < iinfo->ii_bstart)
12430+ iinfo->ii_bstart = new_bindex;
12431+ if (iinfo->ii_bend < new_bindex)
12432+ iinfo->ii_bend = new_bindex;
12433+ /* swap two hidden inode, and loop again */
12434+ q = iinfo->ii_hinode + new_bindex;
12435+ tmp = *q;
12436+ *q = *p;
12437+ *p = tmp;
12438+ if (tmp.hi_inode) {
12439+ bindex--;
12440+ p--;
12441+ }
12442+ }
12443+ au_update_brange(inode, /*do_put_zero*/0);
12444+
12445+ if (unlikely(err))
12446+ goto out;
12447+
12448+ if (1 || first != au_h_iptr(inode, iinfo->ii_bstart))
12449+ au_cpup_attr_all(inode, /*force*/0);
12450+ if (update && S_ISDIR(inode->i_mode))
12451+ inode->i_version++;
12452+ au_update_iigen(inode);
12453+
12454+ out:
12455+ AuTraceErr(err);
12456+ return err;
12457+}
12458+
12459+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
12460+{
12461+ int err, update;
12462+ struct inode *first;
12463+ struct au_hinode *p;
12464+ struct super_block *sb;
12465+ struct au_iinfo *iinfo;
12466+ aufs_bindex_t bindex, bend;
12467+ unsigned char isdir;
12468+ unsigned int flags;
12469+
12470+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
12471+ IiMustWriteLock(inode);
12472+
12473+ err = au_refresh_hinode_self(inode);
12474+ if (unlikely(err))
12475+ goto out;
12476+
12477+ sb = dentry->d_sb;
12478+ bend = au_sbend(sb);
12479+ iinfo = au_ii(inode);
12480+ update = 0;
12481+ p = iinfo->ii_hinode + iinfo->ii_bstart;
12482+ first = p->hi_inode;
12483+ isdir = S_ISDIR(inode->i_mode);
12484+ flags = au_hi_flags(inode, isdir);
12485+ bend = au_dbend(dentry);
12486+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
12487+ struct inode *hi;
12488+ struct dentry *hd;
12489+
12490+ hd = au_h_dptr(dentry, bindex);
12491+ if (!hd || !hd->d_inode)
12492+ continue;
12493+
12494+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
12495+ hi = au_h_iptr(inode, bindex);
12496+ if (hi) {
12497+ if (hi == hd->d_inode)
12498+ continue;
12499+ err = -ESTALE;
12500+ break;
12501+ }
12502+ }
12503+ if (bindex < iinfo->ii_bstart)
12504+ iinfo->ii_bstart = bindex;
12505+ if (iinfo->ii_bend < bindex)
12506+ iinfo->ii_bend = bindex;
12507+ au_set_h_iptr(inode, bindex, au_igrab(hd->d_inode), flags);
12508+ update++;
12509+ }
12510+ au_update_brange(inode, /*do_put_zero*/0);
12511+
12512+ if (unlikely(err))
12513+ goto out;
12514+
12515+ if (1 || first != au_h_iptr(inode, iinfo->ii_bstart))
12516+ au_cpup_attr_all(inode, /*force*/0);
12517+ if (update && isdir)
12518+ inode->i_version++;
12519+ au_update_iigen(inode);
12520+
12521+ out:
12522+ AuTraceErr(err);
12523+ return err;
12524+}
12525+
12526+static int set_inode(struct inode *inode, struct dentry *dentry)
12527+{
12528+ int err;
12529+ struct dentry *h_dentry;
12530+ struct inode *h_inode;
12531+ umode_t mode;
12532+ aufs_bindex_t bindex, bstart, btail;
12533+ unsigned char isdir;
12534+ struct au_iinfo *iinfo;
12535+ unsigned int flags;
12536+
12537+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry));
12538+ AuDebugOn(!(inode->i_state & I_NEW));
12539+ IiMustWriteLock(inode);
12540+ bstart = au_dbstart(dentry);
12541+ h_dentry = au_h_dptr(dentry, bstart);
12542+ AuDebugOn(!h_dentry);
12543+ h_inode = h_dentry->d_inode;
12544+ AuDebugOn(!h_inode);
12545+
12546+ err = 0;
12547+ isdir = 0;
12548+ mode = h_inode->i_mode;
12549+ switch (mode & S_IFMT) {
12550+ case S_IFREG:
12551+ btail = au_dbtail(dentry);
12552+ inode->i_op = &aufs_iop;
12553+ inode->i_fop = &aufs_file_fop;
12554+ inode->i_mapping->a_ops = &aufs_aop;
12555+ break;
12556+ case S_IFDIR:
12557+ isdir = 1;
12558+ btail = au_dbtaildir(dentry);
12559+ inode->i_op = &aufs_dir_iop;
12560+ inode->i_fop = &aufs_dir_fop;
12561+ break;
12562+ case S_IFLNK:
12563+ btail = au_dbtail(dentry);
12564+ inode->i_op = &aufs_symlink_iop;
12565+ /* inode->i_fop = &aufs_file_fop; */
12566+ break;
12567+ case S_IFBLK:
12568+ case S_IFCHR:
12569+ case S_IFIFO:
12570+ case S_IFSOCK:
12571+ btail = au_dbtail(dentry);
12572+ inode->i_op = &aufs_iop;
12573+ init_special_inode(inode, mode,
12574+ au_h_rdev(h_inode, /*h_mnt*/NULL, h_dentry));
12575+ break;
12576+ default:
12577+ AuIOErr("Unknown file type 0%o\n", mode);
12578+ err = -EIO;
12579+ goto out;
12580+ }
12581+
12582+ /* do not set inotify for whiteouted dirs (SHWH mode) */
12583+ flags = au_hi_flags(inode, isdir);
12584+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
12585+ && au_ftest_hi(flags, NOTIFY)
12586+ && dentry->d_name.len > AUFS_WH_PFX_LEN
12587+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
12588+ au_fclr_hi(flags, NOTIFY);
12589+ iinfo = au_ii(inode);
12590+ iinfo->ii_bstart = bstart;
12591+ iinfo->ii_bend = btail;
12592+ for (bindex = bstart; bindex <= btail; bindex++) {
12593+ h_dentry = au_h_dptr(dentry, bindex);
12594+ if (!h_dentry)
12595+ continue;
12596+ AuDebugOn(!h_dentry->d_inode);
12597+ au_set_h_iptr(inode, bindex, au_igrab(h_dentry->d_inode),
12598+ flags);
12599+ }
12600+ au_cpup_attr_all(inode, /*force*/1);
12601+
12602+ out:
12603+ AuTraceErr(err);
12604+ return err;
12605+}
12606+
12607+/* successful returns with iinfo write_locked */
12608+/* todo: return with unlocked? */
12609+static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
12610+{
12611+ int err;
12612+ struct inode *h_inode, *h_dinode;
12613+ aufs_bindex_t bindex, bend;
12614+
12615+ LKTRTrace("i%lu, %.*s\n", inode->i_ino, AuDLNPair(dentry));
12616+
12617+ *matched = 0;
12618+
12619+ /*
12620+ * before this function, if aufs got any iinfo lock, it must be only
12621+ * one, the parent dir.
12622+ * it can happen by UDBA and the obsoleted inode number.
12623+ */
12624+ err = -EIO;
12625+ if (unlikely(inode->i_ino == parent_ino(dentry)))
12626+ goto out;
12627+
12628+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
12629+ /* mutex_lock_nested(&inode->i_mutex, AuLsc_I_CHILD); */
12630+ ii_write_lock_new_child(inode);
12631+ /* it happend */
12632+ if (unlikely(IS_DEADDIR(inode)))
12633+ goto out_unlock;
12634+
12635+ err = 0;
12636+ bend = au_ibend(inode);
12637+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12638+ h_inode = au_h_iptr(inode, bindex);
12639+ if (h_inode && h_inode == h_dinode) {
12640+ /* && (ibs != bstart
12641+ || !au_test_higen(inode, h_inode))); */
12642+ *matched = 1;
12643+ err = 0;
12644+ if (au_iigen(inode) != au_digen(dentry))
12645+ err = au_refresh_hinode(inode, dentry);
12646+ break;
12647+ }
12648+ }
12649+
12650+ out_unlock:
12651+ if (unlikely(err))
12652+ ii_write_unlock(inode);
12653+ /* mutex_unlock(&inode->i_mutex); */
12654+ out:
12655+ AuTraceErr(err);
12656+ return err;
12657+}
12658+
12659+/* successful returns with iinfo write_locked */
12660+/* todo: return with unlocked? */
12661+struct inode *au_new_inode(struct dentry *dentry, int must_new)
12662+{
12663+ struct inode *inode, *h_inode;
12664+ struct dentry *h_dentry;
12665+ struct super_block *sb;
12666+ ino_t h_ino;
12667+ int err, match;
12668+ aufs_bindex_t bstart;
12669+ struct au_xino_entry xinoe;
12670+
12671+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
12672+ sb = dentry->d_sb;
12673+ bstart = au_dbstart(dentry);
12674+ h_dentry = au_h_dptr(dentry, bstart);
12675+ AuDebugOn(!h_dentry);
12676+ h_inode = h_dentry->d_inode;
12677+ AuDebugOn(!h_inode);
12678+
12679+ h_ino = h_inode->i_ino;
12680+ err = au_xino_read(sb, bstart, h_ino, &xinoe);
12681+ inode = ERR_PTR(err);
12682+ if (unlikely(err))
12683+ goto out;
12684+ new_ino:
12685+ if (!xinoe.ino) {
12686+ xinoe.ino = au_xino_new_ino(sb);
12687+ if (!xinoe.ino) {
12688+ inode = ERR_PTR(-EIO);
12689+ goto out;
12690+ }
12691+ }
12692+
12693+ LKTRTrace("i%lu\n", (unsigned long)xinoe.ino);
12694+ inode = au_iget_locked(sb, xinoe.ino);
12695+ err = PTR_ERR(inode);
12696+ if (IS_ERR(inode))
12697+ goto out;
12698+
12699+ LKTRTrace("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
12700+ if (inode->i_state & I_NEW) {
12701+ ii_write_lock_new_child(inode);
12702+ err = set_inode(inode, dentry);
12703+ unlock_new_inode(inode);
12704+ if (!err)
12705+ goto out; /* success */
12706+ iget_failed(inode);
12707+ ii_write_unlock(inode);
12708+ goto out_iput;
12709+ } else if (!must_new) {
12710+ AuDebugOn(inode->i_state & I_LOCK);
12711+ err = reval_inode(inode, dentry, &match);
12712+ if (!err)
12713+ goto out; /* success */
12714+ else if (match)
12715+ goto out_iput;
12716+ }
12717+
12718+ if (unlikely(au_test_unique_ino(h_dentry, h_ino)))
12719+ AuWarn1("Un-notified UDBA or repeatedly renamed dir,"
12720+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
12721+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
12722+ (unsigned long)h_ino, (unsigned long)xinoe.ino);
12723+ xinoe.ino = 0;
12724+ err = au_xino_write0(sb, bstart, h_ino, 0);
12725+ if (!err) {
12726+ iput(inode);
12727+ goto new_ino;
12728+ }
12729+ /* force noxino? */
12730+
12731+ out_iput:
12732+ iput(inode);
12733+ inode = ERR_PTR(err);
12734+ out:
12735+ AuTraceErrPtr(inode);
12736+ return inode;
12737+}
12738+
12739+/* ---------------------------------------------------------------------- */
12740+
12741+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12742+ struct inode *inode)
12743+{
12744+ int err;
12745+
12746+ err = au_br_rdonly(au_sbr(sb, bindex));
12747+
12748+ /* pseudo-link after flushed may out of bounds */
12749+ if (!err
12750+ && inode
12751+ && au_ibstart(inode) <= bindex
12752+ && bindex <= au_ibend(inode)) {
12753+ /*
12754+ * permission check is unnecessary since vfsub routine
12755+ * will be called later
12756+ */
12757+ struct inode *hi = au_h_iptr(inode, bindex);
12758+ if (hi)
12759+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
12760+ }
12761+
12762+ AuTraceErr(err);
12763+ return err;
12764+}
12765+
12766+int au_test_h_perm(struct inode *h_inode, int mask, int dlgt)
12767+{
94750128 12768+ if (!current_fsuid())
024a5822
JR
12769+ return 0;
12770+ /* todo: fake nameidata? */
12771+ return vfsub_permission(h_inode, mask, NULL, dlgt);
12772+}
12773+
12774+int au_test_h_perm_sio(struct inode *h_inode, int mask, int dlgt)
12775+{
12776+ if (au_test_nfs(h_inode->i_sb)
12777+ && (mask & MAY_WRITE)
12778+ && S_ISDIR(h_inode->i_mode))
12779+ mask |= MAY_READ; /* force permission check */
12780+ return au_test_h_perm(h_inode, mask, dlgt);
12781+}
12782diff -urN linux/fs/aufs/inode.h linux-aufs/fs/aufs/inode.h
12783--- linux/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
12784+++ linux-aufs/fs/aufs/inode.h 2009-03-12 16:18:04.000000000 +0100
12785@@ -0,0 +1,595 @@
12786+/*
12787+ * Copyright (C) 2005-2009 Junjiro Okajima
12788+ *
12789+ * This program, aufs is free software; you can redistribute it and/or modify
12790+ * it under the terms of the GNU General Public License as published by
12791+ * the Free Software Foundation; either version 2 of the License, or
12792+ * (at your option) any later version.
12793+ *
12794+ * This program is distributed in the hope that it will be useful,
12795+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12796+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12797+ * GNU General Public License for more details.
12798+ *
12799+ * You should have received a copy of the GNU General Public License
12800+ * along with this program; if not, write to the Free Software
12801+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12802+ */
12803+
12804+/*
12805+ * inode operations
12806+ *
12807+ * $Id$
12808+ */
12809+
12810+#ifndef __AUFS_INODE_H__
12811+#define __AUFS_INODE_H__
12812+
12813+#ifdef __KERNEL__
12814+
12815+#include <linux/fs.h>
12816+#include <linux/namei.h>
12817+#include <linux/security.h>
12818+#include <linux/aufs_type.h>
12819+#include "hinode.h"
12820+#include "misc.h"
12821+#include "super.h"
12822+
12823+struct au_hinode;
12824+struct au_vdir;
12825+struct au_iinfo {
12826+ atomic_t ii_generation;
12827+ struct super_block *ii_hsb1; /* no get/put */
12828+
12829+ struct au_rwsem ii_rwsem;
12830+ aufs_bindex_t ii_bstart, ii_bend;
12831+ __u32 ii_higen;
12832+ struct au_hinode *ii_hinode;
12833+ struct au_vdir *ii_vdir;
12834+};
12835+
12836+struct aufs_icntnr {
12837+ struct au_iinfo iinfo;
12838+ struct inode vfs_inode;
12839+};
12840+
12841+/* au_pin flags */
12842+#define AuPin_DI_LOCKED 1
12843+#define AuPin_DO_GPARENT (1 << 1)
12844+#define AuPin_MNT_WRITE (1 << 2)
12845+#define AuPin_VFS_RENAME (1 << 3)
12846+/* will be set automatically */
12847+#define AuPin_VERIFY (1 << 4)
12848+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
12849+#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
12850+#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
12851+
12852+struct au_pin1 {
12853+ /* input */
12854+ struct dentry *dentry;
12855+ unsigned char lsc_di, lsc_hi, flags;
12856+ aufs_bindex_t bindex;
12857+
12858+ /* output */
12859+ struct dentry *parent;
12860+ struct inode *h_dir;
12861+};
12862+
12863+enum {AuPin_PARENT, AuPin_GPARENT};
12864+struct au_pin {
12865+#ifdef CONFIG_AUFS_HINOTIFY
12866+ struct au_pin1 pin[2];
12867+#else
12868+ struct au_pin1 pin[1]; /* no grand parent */
12869+#endif
12870+};
12871+
12872+/* ---------------------------------------------------------------------- */
12873+
12874+/* inode.c */
12875+int au_refresh_hinode_self(struct inode *inode);
12876+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
12877+struct inode *au_new_inode(struct dentry *dentry, int must_new);
12878+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12879+ struct inode *inode);
12880+int au_test_h_perm(struct inode *h_inode, int mask, int dlgt);
12881+int au_test_h_perm_sio(struct inode *h_inode, int mask, int dlgt);
12882+
12883+/* i_op.c */
12884+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
12885+
12886+/* au_wr_dir flags */
12887+#define AuWrDir_ADD_ENTRY 1
12888+#define AuWrDir_ISDIR (1 << 1)
12889+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
12890+#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
12891+#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
12892+
12893+struct au_wr_dir_args {
12894+ aufs_bindex_t force_btgt;
12895+ unsigned char flags;
12896+};
12897+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
12898+ struct au_wr_dir_args *args);
12899+
12900+void au_pin_init(struct au_pin *args, struct dentry *dentry,
12901+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
12902+ unsigned char flags);
12903+int au_pin(struct au_pin *args, struct dentry *dentry, aufs_bindex_t bindex,
12904+ unsigned char flags) __must_check;
12905+int au_do_pin(struct au_pin1 *p, struct au_pin1 *gp) __must_check;
12906+void au_do_unpin(struct au_pin1 *p, struct au_pin1 *gp);
12907+
12908+/* i_op_add.c */
12909+struct au_ndx;
12910+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
12911+ struct dentry *h_parent, int isdir, struct au_ndx *ndx);
12912+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
12913+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
12914+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
12915+ struct nameidata *nd);
12916+int aufs_link(struct dentry *src_dentry, struct inode *dir,
12917+ struct dentry *dentry);
12918+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
12919+
12920+/* i_op_del.c */
12921+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
12922+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
12923+ struct dentry *h_parent, int isdir, struct au_ndx *ndx);
12924+int aufs_unlink(struct inode *dir, struct dentry *dentry);
12925+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
12926+
12927+/* i_op_ren.c */
12928+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
12929+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
12930+ struct inode *dir, struct dentry *dentry);
12931+
12932+#ifdef CONFIG_AUFS_DLGT
12933+/* dlgt.c */
12934+int au_security_inode_permission(struct inode *h_inode, int mask,
12935+ struct nameidata *fake_nd, int dlgt);
12936+#else
12937+static inline
12938+int au_security_inode_permission(struct inode *h_inode, int mask,
12939+ struct nameidata *fake_nd, int dlgt)
12940+{
12941+ return vfsub_security_inode_permission(h_inode, mask, fake_nd);
12942+}
12943+#endif /* CONFIG_AUFS_DLGT */
12944+
12945+#ifdef CONFIG_AUFS_GETATTR
12946+/* getattr.c */
12947+int aufs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st);
12948+#endif
12949+
12950+#if 0 /* reserved for future use */
12951+/* xattr.c */
12952+int aufs_setxattr(struct dentry *dentry, const char *name, const void *value,
12953+ size_t sz, int flags);
12954+ssize_t aufs_getxattr(struct dentry *dentry, const char *name, void *value,
12955+ size_t sz);
12956+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t sz);
12957+int aufs_removexattr(struct dentry *dentry, const char *name);
12958+#endif
12959+
12960+/* iinfo.c */
12961+struct au_iinfo *au_ii(struct inode *inode);
12962+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
12963+aufs_bindex_t au_ii_br_id(struct inode *inode, aufs_bindex_t bindex);
12964+
12965+void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex);
12966+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12967+ struct dentry *h_wh);
12968+unsigned int au_hi_flags(struct inode *inode, int isdir);
12969+
12970+/* hinode flags */
12971+#define AuHi_XINO 1
12972+#define AuHi_NOTIFY (1 << 1)
12973+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
12974+#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; }
12975+#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; }
12976+#ifndef CONFIG_AUFS_HINOTIFY
12977+#undef AuHi_NOTIFY
12978+#define AuHi_NOTIFY 0
12979+#endif
12980+
12981+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12982+ struct inode *h_inode, unsigned int flags);
12983+
12984+void au_update_iigen(struct inode *inode);
12985+void au_update_brange(struct inode *inode, int do_put_zero);
12986+
12987+int au_iinfo_init(struct inode *inode);
12988+void au_iinfo_fin(struct inode *inode);
12989+
12990+/* plink.c */
12991+#ifdef CONFIG_AUFS_DEBUG
12992+void au_plink_list(struct super_block *sb);
12993+#else
12994+static inline void au_plink_list(struct super_block *sb)
12995+{
12996+ /* nothing */
12997+}
12998+#endif
12999+int au_plink_test(struct super_block *sb, struct inode *inode);
13000+struct dentry *au_plink_lkup(struct super_block *sb, aufs_bindex_t bindex,
13001+ struct inode *inode);
13002+void au_plink_append(struct super_block *sb, struct inode *inode,
13003+ struct dentry *h_dentry, aufs_bindex_t bindex);
13004+void au_plink_put(struct super_block *sb);
13005+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
13006+
13007+/* ---------------------------------------------------------------------- */
13008+
13009+/* lock subclass for iinfo */
13010+enum {
13011+ AuLsc_II_CHILD, /* child first */
13012+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hinotify */
13013+ AuLsc_II_CHILD3, /* copyup dirs */
13014+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
13015+ AuLsc_II_PARENT2,
13016+ AuLsc_II_PARENT3,
13017+ AuLsc_II_PARENT4,
13018+ AuLsc_II_NEW_CHILD,
13019+};
13020+
13021+/*
13022+ * ii_read_lock_child, ii_write_lock_child,
13023+ * ii_read_lock_child2, ii_write_lock_child2,
13024+ * ii_read_lock_child3, ii_write_lock_child3,
13025+ * ii_read_lock_parent, ii_write_lock_parent,
13026+ * ii_read_lock_parent2, ii_write_lock_parent2,
13027+ * ii_read_lock_parent3, ii_write_lock_parent3,
13028+ * ii_read_lock_parent4, ii_write_lock_parent4,
13029+ * ii_read_lock_new_child, ii_write_lock_new_child,
13030+ */
13031+#define AuReadLockFunc(name, lsc) \
13032+static inline void ii_read_lock_##name(struct inode *i) \
13033+{ \
13034+ au_dbg_locking_ii_reg(i, 0, AuLsc_II_##lsc); \
13035+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
13036+ au_dbg_locking_ii_unreg(i, 0); \
13037+ au_dbg_locked_ii_reg(i, 0, AuLsc_II_##lsc); \
13038+}
13039+
13040+#define AuWriteLockFunc(name, lsc) \
13041+static inline void ii_write_lock_##name(struct inode *i) \
13042+{ \
13043+ au_dbg_locking_ii_reg(i, 1, AuLsc_II_##lsc); \
13044+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
13045+ au_dbg_locking_ii_unreg(i, 1); \
13046+ au_dbg_locked_ii_reg(i, 1, AuLsc_II_##lsc); \
13047+}
13048+
13049+#define AuRWLockFuncs(name, lsc) \
13050+ AuReadLockFunc(name, lsc) \
13051+ AuWriteLockFunc(name, lsc)
13052+
13053+AuRWLockFuncs(child, CHILD);
13054+AuRWLockFuncs(child2, CHILD2);
13055+AuRWLockFuncs(child3, CHILD3);
13056+AuRWLockFuncs(parent, PARENT);
13057+AuRWLockFuncs(parent2, PARENT2);
13058+AuRWLockFuncs(parent3, PARENT3);
13059+AuRWLockFuncs(parent4, PARENT4);
13060+AuRWLockFuncs(new_child, NEW_CHILD);
13061+
13062+#undef AuReadLockFunc
13063+#undef AuWriteLockFunc
13064+#undef AuRWLockFuncs
13065+
13066+/*
13067+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
13068+ */
13069+AuSimpleUnlockRwsemFuncs(ii_do, struct inode *i, au_ii(i)->ii_rwsem);
13070+static inline void ii_read_unlock(struct inode *i)
13071+{
13072+ ii_do_read_unlock(i);
13073+ au_dbg_locked_ii_unreg(i, 0);
13074+}
13075+
13076+static inline void ii_write_unlock(struct inode *i)
13077+{
13078+ ii_do_write_unlock(i);
13079+ au_dbg_locked_ii_unreg(i, 0);
13080+}
13081+
13082+static inline void ii_downgrade_lock(struct inode *i)
13083+{
13084+ ii_do_downgrade_lock(i);
13085+}
13086+
13087+/* to debug easier, do not make them inlined functions */
13088+#define IiMustReadLock(i) do { \
13089+ SiMustAnyLock((i)->i_sb); \
13090+ AuRwMustReadLock(&au_ii(i)->ii_rwsem); \
13091+} while (0)
13092+
13093+#define IiMustWriteLock(i) do { \
13094+ SiMustAnyLock((i)->i_sb); \
13095+ AuRwMustWriteLock(&au_ii(i)->ii_rwsem); \
13096+} while (0)
13097+
13098+#define IiMustAnyLock(i) do { \
13099+ SiMustAnyLock((i)->i_sb); \
13100+ AuRwMustAnyLock(&au_ii(i)->ii_rwsem); \
13101+} while (0)
13102+
13103+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
13104+
13105+/* ---------------------------------------------------------------------- */
13106+
13107+static inline struct inode *au_igrab(struct inode *inode)
13108+{
13109+ if (inode) {
13110+ AuDebugOn(!atomic_read(&inode->i_count));
13111+ atomic_inc_return(&inode->i_count);
13112+ }
13113+ return inode;
13114+}
13115+
13116+/* ---------------------------------------------------------------------- */
13117+
13118+static inline aufs_bindex_t au_ibstart(struct inode *inode)
13119+{
13120+ /* lock free root dinfo/inode */
13121+ if (inode->i_ino != AUFS_ROOT_INO)
13122+ IiMustAnyLock(inode);
13123+ else
13124+ SiMustAnyLock(inode->i_sb);
13125+ return au_ii(inode)->ii_bstart;
13126+}
13127+
13128+static inline aufs_bindex_t au_ibend(struct inode *inode)
13129+{
13130+ /* lock free root dinfo/inode */
13131+ if (inode->i_ino != AUFS_ROOT_INO)
13132+ IiMustAnyLock(inode);
13133+ else
13134+ SiMustAnyLock(inode->i_sb);
13135+ return au_ii(inode)->ii_bend;
13136+}
13137+
13138+static inline struct au_vdir *au_ivdir(struct inode *inode)
13139+{
13140+ IiMustAnyLock(inode);
13141+ AuDebugOn(!S_ISDIR(inode->i_mode));
13142+ return au_ii(inode)->ii_vdir;
13143+}
13144+
13145+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
13146+{
13147+ struct au_hinode *hinode;
13148+ IiMustAnyLock(inode);
13149+ hinode = au_ii(inode)->ii_hinode + bindex;
13150+ return hinode->hi_whdentry;
13151+}
13152+
13153+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
13154+{
13155+ IiMustWriteLock(inode);
13156+ AuDebugOn(au_sbend(inode->i_sb) < bindex || bindex < au_ibstart(inode));
13157+ au_ii(inode)->ii_bend = bindex;
13158+}
13159+
13160+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
13161+{
13162+ IiMustWriteLock(inode);
13163+ AuDebugOn(!S_ISDIR(inode->i_mode) || (au_ii(inode)->ii_vdir && vdir));
13164+ au_ii(inode)->ii_vdir = vdir;
13165+}
13166+
13167+static inline void au_hiput(struct au_hinode *hinode)
13168+{
13169+ au_hin_free(hinode);
13170+ dput(hinode->hi_whdentry);
13171+ iput(hinode->hi_inode);
13172+}
13173+
13174+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
13175+{
13176+ /* todo: this lock check causes some unnecessary locks in callers. */
13177+ IiMustAnyLock(inode);
13178+ return au_ii(inode)->ii_hinode + bindex;
13179+}
13180+
13181+/* tiny test for inode number */
13182+/* tmpfs generation is too rough */
13183+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
13184+{
13185+ struct au_iinfo *iinfo;
13186+
13187+ IiMustAnyLock(inode);
13188+
13189+ iinfo = au_ii(inode);
13190+ return !(iinfo->ii_hsb1 == h_inode->i_sb
13191+ && iinfo->ii_higen == h_inode->i_generation);
13192+}
13193+
13194+static inline au_gen_t au_iigen(struct inode *inode)
13195+{
13196+ return atomic_read(&au_ii(inode)->ii_generation);
13197+}
13198+
13199+#ifdef CONFIG_AUFS_HINOTIFY
13200+static inline au_gen_t au_iigen_dec(struct inode *inode)
13201+{
13202+ /* AuDbg("i%lu\n", inode->i_ino); */
13203+ return atomic_dec_return(&au_ii(inode)->ii_generation);
13204+}
13205+#endif
13206+
13207+/* ---------------------------------------------------------------------- */
13208+
13209+#ifdef CONFIG_AUFS_HINOTIFY
13210+static inline struct au_pin1 *au_pin_gp(struct au_pin *args)
13211+{
13212+ return args->pin + AuPin_GPARENT;
13213+}
13214+
13215+/* hinotify.c */
13216+void au_unpin_gp(struct au_pin *args);
13217+
13218+#else
13219+
13220+static inline struct au_pin1 *au_pin_gp(struct au_pin *args)
13221+{
13222+ return NULL;
13223+}
13224+
13225+static inline void au_unpin_gp(struct au_pin *args)
13226+{
13227+ /* empty */
13228+}
13229+#endif /* HINOTIFY */
13230+
13231+static inline void au_unpin(struct au_pin *args)
13232+{
13233+ au_do_unpin(args->pin + AuPin_PARENT, au_pin_gp(args));
13234+}
13235+
13236+static inline
13237+struct au_hinode *au_do_pinned_hdir(struct au_pin1 *pin)
13238+{
13239+ if (pin && pin->parent)
13240+ return au_hi(pin->parent->d_inode, pin->bindex);
13241+ return NULL;
13242+}
13243+
13244+struct dentry *au_do_pinned_h_parent(struct au_pin1 *pin);
13245+
13246+static inline struct dentry *au_do_pinned_parent(struct au_pin1 *pin)
13247+{
13248+ if (pin)
13249+ return pin->parent;
13250+ return NULL;
13251+}
13252+
13253+static inline struct inode *au_do_pinned_h_dir(struct au_pin1 *pin)
13254+{
13255+ if (pin)
13256+ return pin->h_dir;
13257+ return NULL;
13258+}
13259+
13260+static inline
13261+void au_pin_do_set_dentry(struct au_pin1 *pin, struct dentry *dentry)
13262+{
13263+ if (pin)
13264+ pin->dentry = dentry;
13265+}
13266+
13267+static inline
13268+void au_pin_do_set_parent(struct au_pin1 *pin, struct dentry *parent)
13269+{
13270+ if (pin) {
13271+ dput(pin->parent);
13272+ pin->parent = dget(parent);
13273+ }
13274+}
13275+
13276+static inline void au_pin_do_set_h_dir(struct au_pin1 *pin, struct inode *h_dir)
13277+{
13278+ if (pin) {
13279+ iput(pin->h_dir);
13280+ pin->h_dir = au_igrab(h_dir);
13281+ }
13282+}
13283+
13284+static inline
13285+void au_pin_do_set_parent_lflag(struct au_pin1 *pin, unsigned char lflag)
13286+{
13287+ if (pin) {
13288+ /* dirty macros require brackets */
13289+ if (lflag) {
13290+ au_fset_pin(pin->flags, DI_LOCKED);
13291+ } else {
13292+ au_fclr_pin(pin->flags, DI_LOCKED);
13293+ }
13294+ }
13295+}
13296+
13297+static inline
13298+struct au_hinode *au_pinned_hdir(struct au_pin *args)
13299+{
13300+ return au_do_pinned_hdir(args->pin + AuPin_PARENT);
13301+}
13302+
13303+static inline
13304+struct au_hinode *au_pinned_hgdir(struct au_pin *args)
13305+{
13306+ return au_do_pinned_hdir(au_pin_gp(args));
13307+}
13308+
13309+static inline
13310+struct dentry *au_pinned_h_parent(struct au_pin *args)
13311+{
13312+ return au_do_pinned_h_parent(args->pin + AuPin_PARENT);
13313+}
13314+
13315+#if 0 /* reserved for future use */
13316+static inline
13317+struct dentry *au_pinned_h_gparent(struct au_pin *args)
13318+{
13319+ return au_do_pinned_h_parent(au_pin_gp(args));
13320+}
13321+#endif
13322+
13323+static inline
13324+struct dentry *au_pinned_parent(struct au_pin *args)
13325+{
13326+ return au_do_pinned_parent(args->pin + AuPin_PARENT);
13327+}
13328+
13329+static inline
13330+struct dentry *au_pinned_gparent(struct au_pin *args)
13331+{
13332+ return au_do_pinned_parent(au_pin_gp(args));
13333+}
13334+
13335+static inline
13336+struct inode *au_pinned_h_dir(struct au_pin *args)
13337+{
13338+ return au_do_pinned_h_dir(args->pin + AuPin_PARENT);
13339+}
13340+
13341+static inline
13342+struct inode *au_pinned_h_gdir(struct au_pin *args)
13343+{
13344+ return au_do_pinned_h_dir(au_pin_gp(args));
13345+}
13346+
13347+static inline void au_pin_set_parent(struct au_pin *args, struct dentry *d)
13348+{
13349+ au_pin_do_set_parent(args->pin + AuPin_PARENT, d);
13350+}
13351+
13352+static inline void au_pin_set_gparent(struct au_pin *args, struct dentry *d)
13353+{
13354+ au_pin_do_set_parent(au_pin_gp(args), d);
13355+}
13356+
13357+static inline void au_pin_set_h_dir(struct au_pin *args, struct inode *h_dir)
13358+{
13359+ au_pin_do_set_h_dir(args->pin + AuPin_PARENT, h_dir);
13360+}
13361+
13362+static inline void au_pin_set_h_gdir(struct au_pin *args, struct inode *h_dir)
13363+{
13364+ au_pin_do_set_h_dir(au_pin_gp(args), h_dir);
13365+}
13366+
13367+static inline
13368+void au_pin_set_parent_lflag(struct au_pin *args, unsigned char lflag)
13369+{
13370+ au_pin_do_set_parent_lflag(args->pin + AuPin_PARENT, lflag);
13371+}
13372+
13373+static inline
13374+void au_pin_set_gparent_lflag(struct au_pin *args, unsigned char lflag)
13375+{
13376+ au_pin_do_set_parent_lflag(au_pin_gp(args), lflag);
13377+}
13378+
13379+#endif /* __KERNEL__ */
13380+#endif /* __AUFS_INODE_H__ */
13381diff -urN linux/fs/aufs/i_op_add.c linux-aufs/fs/aufs/i_op_add.c
13382--- linux/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
13383+++ linux-aufs/fs/aufs/i_op_add.c 2009-03-12 16:18:04.000000000 +0100
13384@@ -0,0 +1,757 @@
13385+/*
13386+ * Copyright (C) 2005-2009 Junjiro Okajima
13387+ *
13388+ * This program, aufs is free software; you can redistribute it and/or modify
13389+ * it under the terms of the GNU General Public License as published by
13390+ * the Free Software Foundation; either version 2 of the License, or
13391+ * (at your option) any later version.
13392+ *
13393+ * This program is distributed in the hope that it will be useful,
13394+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13395+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13396+ * GNU General Public License for more details.
13397+ *
13398+ * You should have received a copy of the GNU General Public License
13399+ * along with this program; if not, write to the Free Software
13400+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13401+ */
13402+
13403+/*
13404+ * inode operations (add entry)
13405+ *
13406+ * $Id$
13407+ */
13408+
13409+#include "aufs.h"
13410+
13411+/*
13412+ * final procedure of adding a new entry, except link(2).
13413+ * remove whiteout, instantiate, copyup the parent dir's times and size
13414+ * and update version.
13415+ * if it failed, re-create the removed whiteout.
13416+ */
13417+static int epilog(struct inode *dir, aufs_bindex_t bindex,
13418+ struct dentry *wh_dentry, struct dentry *dentry)
13419+{
13420+ int err, rerr;
13421+ aufs_bindex_t bwh;
13422+ struct inode *inode, *h_dir;
13423+ struct dentry *wh;
13424+ struct au_ndx ndx;
13425+ struct super_block *sb;
13426+
13427+ LKTRTrace("wh %p, %.*s\n", wh_dentry, AuDLNPair(dentry));
13428+
13429+ sb = dentry->d_sb;
13430+ bwh = -1;
13431+ if (wh_dentry) {
13432+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
13433+ IMustLock(h_dir);
13434+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
13435+ bwh = au_dbwh(dentry);
13436+ err = au_wh_unlink_dentry(au_hi(dir, bindex), wh_dentry, dentry,
13437+ /*dlgt*/0);
13438+ if (unlikely(err))
13439+ goto out;
13440+ }
13441+
13442+ inode = au_new_inode(dentry, /*must_new*/1);
13443+ if (!IS_ERR(inode)) {
13444+ d_instantiate(dentry, inode);
13445+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
13446+ IMustLock(dir);
13447+ /* or always cpup dir mtime? */
13448+ if (au_ibstart(dir) == au_dbstart(dentry))
13449+ au_cpup_attr_timesizes(dir);
13450+ dir->i_version++;
13451+ return 0; /* success */
13452+ }
13453+
13454+ err = PTR_ERR(inode);
13455+ if (!wh_dentry)
13456+ goto out;
13457+
13458+ /* revert */
13459+ ndx.flags = 0;
13460+ if (au_test_dlgt(au_mntflags(sb)))
13461+ au_fset_ndx(ndx.flags, DLGT);
13462+ ndx.nfsmnt = au_nfsmnt(sb, bwh);
13463+ ndx.nd = NULL;
13464+ /* ndx.br = NULL; */
13465+ /* dir inode is locked */
13466+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent, &ndx);
13467+ rerr = PTR_ERR(wh);
13468+ if (IS_ERR(wh)) {
13469+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
13470+ AuDLNPair(dentry), err, rerr);
13471+ err = -EIO;
13472+ } else
13473+ dput(wh);
13474+
13475+ out:
13476+ AuTraceErr(err);
13477+ return err;
13478+}
13479+
13480+/*
13481+ * simple tests for the adding inode operations.
13482+ * following the checks in vfs, plus the parent-child relationship.
13483+ */
13484+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13485+ struct dentry *h_parent, int isdir, struct au_ndx *ndx)
13486+{
13487+ int err, exist;
13488+ struct dentry *h_dentry;
13489+ struct inode *h_inode;
13490+ umode_t h_mode;
13491+
13492+ LKTRTrace("%.*s/%.*s, b%d, dir %d\n",
13493+ AuDLNPair(h_parent), AuDLNPair(dentry), bindex, isdir);
13494+
13495+ exist = !!dentry->d_inode;
13496+ h_dentry = au_h_dptr(dentry, bindex);
13497+ h_inode = h_dentry->d_inode;
13498+ if (!exist) {
13499+ err = -EEXIST;
13500+ if (unlikely(h_inode))
13501+ goto out;
13502+ } else {
13503+ /* rename(2) case */
13504+ err = -EIO;
13505+ if (unlikely(!h_inode || !h_inode->i_nlink))
13506+ goto out;
13507+
13508+ h_mode = h_inode->i_mode;
13509+ if (!isdir) {
13510+ err = -EISDIR;
13511+ if (unlikely(S_ISDIR(h_mode)))
13512+ goto out;
13513+ } else if (unlikely(!S_ISDIR(h_mode))) {
13514+ err = -ENOTDIR;
13515+ goto out;
13516+ }
13517+ }
13518+
13519+ err = -EIO;
13520+ /* expected parent dir is locked */
13521+ if (unlikely(h_parent != h_dentry->d_parent))
13522+ goto out;
13523+ err = 0;
13524+
13525+ if (au_opt_test(au_mntflags(dentry->d_sb), UDBA_INOTIFY)) {
13526+ struct dentry *h_latest;
13527+ struct qstr *qstr = &dentry->d_name;
13528+
13529+ err = -EACCES;
13530+ if (unlikely(au_test_h_perm
13531+ (h_parent->d_inode, MAY_EXEC | MAY_WRITE,
13532+ au_ftest_ndx(ndx->flags, DLGT))))
13533+ goto out;
13534+
13535+ h_latest = au_sio_lkup_one(qstr->name, h_parent, qstr->len,
13536+ ndx);
13537+ err = PTR_ERR(h_latest);
13538+ if (IS_ERR(h_latest))
13539+ goto out;
13540+ err = -EIO;
13541+ dput(h_latest);
13542+ /* fuse d_revalidate always return 0 for negative dentries */
13543+ if (h_latest == h_dentry || au_test_fuse(h_dentry->d_sb))
13544+ err = 0;
13545+ }
13546+
13547+ out:
13548+ AuTraceErr(err);
13549+ return err;
13550+}
13551+
13552+/*
13553+ * initial procedure of adding a new entry.
13554+ * prepare writable branch and the parent dir, lock it,
13555+ * lookup whiteout for the new entry.
13556+ */
13557+static struct dentry*
13558+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
13559+ struct dentry *src_dentry, struct au_pin *pin,
13560+ struct au_wr_dir_args *wr_dir_args)
13561+{
13562+ struct dentry *wh_dentry, *h_parent;
13563+ struct super_block *sb;
13564+ int err;
13565+ unsigned int mnt_flags;
13566+ unsigned char pin_flags;
13567+ aufs_bindex_t bstart, bcpup;
13568+ struct au_ndx ndx;
13569+
13570+ LKTRTrace("%.*s, src %p\n", AuDLNPair(dentry), src_dentry);
13571+
13572+ bstart = au_dbstart(dentry);
13573+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
13574+ bcpup = err;
13575+ wh_dentry = ERR_PTR(err);
13576+ if (unlikely(err < 0))
13577+ goto out;
13578+
13579+ sb = dentry->d_sb;
13580+ mnt_flags = au_mntflags(sb);
13581+ pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
13582+ if (dt && au_opt_test(mnt_flags, UDBA_INOTIFY))
13583+ au_fset_pin(pin_flags, DO_GPARENT);
13584+ err = au_pin(pin, dentry, bcpup, pin_flags);
13585+ wh_dentry = ERR_PTR(err);
13586+ if (unlikely(err))
13587+ goto out;
13588+
13589+ ndx.nfsmnt = au_nfsmnt(sb, bcpup);
13590+ ndx.flags = 0;
13591+ if (au_test_dlgt(mnt_flags))
13592+ au_fset_ndx(ndx.flags, DLGT);
13593+ ndx.nd = NULL;
13594+ /* ndx.br = NULL; */
13595+ /* ndx.nd_file = NULL; */
13596+
13597+ h_parent = au_pinned_h_parent(pin);
13598+ if (!au_opt_test(mnt_flags, UDBA_NONE) && au_dbstart(dentry) == bcpup) {
13599+ struct nameidata nd;
13600+
13601+ if (ndx.nfsmnt) {
13602+ /* todo: dirty? */
13603+ ndx.nd = &nd;
13604+ ndx.br = au_sbr(sb, bcpup);
13605+ memset(&nd, 0, sizeof(nd));
13606+ nd.flags = LOOKUP_CREATE;
13607+ nd.intent.open.flags = O_EXCL;
13608+ }
13609+ err = au_may_add(dentry, bcpup, h_parent,
13610+ au_ftest_wrdir(wr_dir_args->flags, ISDIR),
13611+ &ndx);
13612+ wh_dentry = ERR_PTR(err);
13613+ if (unlikely(err))
13614+ goto out_unpin;
13615+ ndx.nd = NULL;
13616+ ndx.br = NULL;
13617+ }
13618+
13619+ if (dt)
13620+ au_dtime_store(dt, au_pinned_parent(pin), h_parent,
13621+ au_pinned_hdir(pin), au_pinned_hgdir(pin));
13622+
13623+ wh_dentry = NULL;
13624+ if (/* bcpup != bstart || */ bcpup != au_dbwh(dentry))
13625+ goto out; /* success */
13626+
13627+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, &ndx);
13628+
13629+ out_unpin:
13630+ if (IS_ERR(wh_dentry))
13631+ au_unpin(pin);
13632+ out:
13633+ AuTraceErrPtr(wh_dentry);
13634+ return wh_dentry;
13635+}
13636+
13637+/* ---------------------------------------------------------------------- */
13638+
13639+enum { Mknod, Symlink, Creat };
13640+struct simple_arg {
13641+ int type;
13642+ union {
13643+ struct {
13644+ int mode;
13645+ struct nameidata *nd;
13646+ } c;
13647+ struct {
13648+ const char *symname;
13649+ } s;
13650+ struct {
13651+ int mode;
13652+ dev_t dev;
13653+ } m;
13654+ } u;
13655+};
13656+
13657+static int add_simple(struct inode *dir, struct dentry *dentry,
13658+ struct simple_arg *arg)
13659+{
13660+ int err;
13661+ struct dentry *h_dentry, *wh_dentry, *parent;
13662+ struct inode *h_dir;
13663+ struct au_dtime dt;
13664+ struct vfsub_args vargs;
13665+ struct super_block *sb;
13666+ aufs_bindex_t bstart;
13667+ unsigned char created;
13668+ struct au_hin_ignore ign;
13669+ struct au_pin pin;
13670+ struct au_wr_dir_args wr_dir_args = {
13671+ .force_btgt = -1,
13672+ .flags = AuWrDir_ADD_ENTRY
13673+ };
13674+
13675+ LKTRTrace("type %d, %.*s\n", arg->type, AuDLNPair(dentry));
13676+ IMustLock(dir);
13677+
13678+ sb = dir->i_sb;
13679+ parent = dentry->d_parent; /* dir inode is locked */
13680+ aufs_read_lock(dentry, AuLock_DW);
13681+ vfsub_args_init(&vargs, &ign, !!au_test_dlgt(au_mntflags(sb)), 0);
13682+ di_write_lock_parent(parent);
13683+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
13684+ &wr_dir_args);
13685+ err = PTR_ERR(wh_dentry);
13686+ if (IS_ERR(wh_dentry))
13687+ goto out;
13688+
13689+ bstart = au_dbstart(dentry);
13690+ h_dentry = au_h_dptr(dentry, bstart);
13691+ h_dir = au_pinned_h_dir(&pin);
13692+ vfsub_ign_hinode(&vargs, IN_CREATE, au_pinned_hdir(&pin));
13693+
13694+ switch (arg->type) {
13695+ case Creat:
13696+ AuDebugOn(au_test_nfs(h_dir->i_sb) && !arg->u.c.nd);
13697+ err = au_h_create(h_dir, h_dentry, arg->u.c.mode, &vargs,
13698+ arg->u.c.nd, au_nfsmnt(sb, bstart));
13699+ break;
13700+ case Symlink:
13701+ err = vfsub_symlink(h_dir, h_dentry, arg->u.s.symname,
13702+ S_IALLUGO, &vargs);
13703+ break;
13704+ case Mknod:
13705+ err = vfsub_mknod(h_dir, h_dentry, arg->u.m.mode, arg->u.m.dev,
13706+ &vargs);
13707+ break;
13708+ default:
13709+ BUG();
13710+ }
13711+ created = !err;
13712+ if (!err)
13713+ err = epilog(dir, bstart, wh_dentry, dentry);
13714+
13715+ /* revert */
13716+ if (unlikely(created && err && h_dentry->d_inode)) {
13717+ int rerr;
13718+ vfsub_args_reinit(&vargs);
13719+ vfsub_ign_hinode(&vargs, IN_DELETE, au_pinned_hdir(&pin));
13720+ rerr = vfsub_unlink(h_dir, h_dentry, &vargs);
13721+ if (rerr) {
13722+ AuIOErr("%.*s revert failure(%d, %d)\n",
13723+ AuDLNPair(dentry), err, rerr);
13724+ err = -EIO;
13725+ }
13726+ /* todo: inotify will be fired to the grand parent dir? */
13727+ au_dtime_revert(&dt);
13728+ d_drop(dentry);
13729+ }
13730+
13731+ au_unpin(&pin);
13732+ dput(wh_dentry);
13733+
13734+ out:
13735+ if (unlikely(err)) {
13736+ au_update_dbstart(dentry);
13737+ d_drop(dentry);
13738+ }
13739+ di_write_unlock(parent);
13740+ aufs_read_unlock(dentry, AuLock_DW);
13741+ AuTraceErr(err);
13742+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
13743+ err = -ESTALE;
13744+ return err;
13745+}
13746+
13747+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
13748+{
13749+ struct simple_arg arg = {
13750+ .type = Mknod,
13751+ .u.m = {
13752+ .mode = mode,
13753+ .dev = dev
13754+ }
13755+ };
13756+ return add_simple(dir, dentry, &arg);
13757+}
13758+
13759+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
13760+{
13761+ struct simple_arg arg = {
13762+ .type = Symlink,
13763+ .u.s.symname = symname
13764+ };
13765+ return add_simple(dir, dentry, &arg);
13766+}
13767+
13768+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13769+ struct nameidata *nd)
13770+{
13771+ struct simple_arg arg = {
13772+ .type = Creat,
13773+ .u.c = {
13774+ .mode = mode,
13775+ .nd = nd
13776+ }
13777+ };
13778+ return add_simple(dir, dentry, &arg);
13779+}
13780+
13781+/* ---------------------------------------------------------------------- */
13782+
13783+struct au_link_args {
13784+ unsigned int mnt_flags;
13785+ unsigned char pin_flags;
13786+ aufs_bindex_t bdst, bsrc;
13787+ struct vfsub_args vargs;
13788+ struct au_pin pin;
13789+ struct au_hin_ignore ign;
13790+ struct dentry *h_dentry;
13791+ struct dentry *src_parent, *parent;
13792+};
13793+
13794+static int au_cpup_before_link(struct dentry *src_dentry, struct inode *dir,
13795+ struct dentry *dentry, struct au_link_args *a)
13796+{
13797+ int err;
13798+ const int hinotify = au_opt_test(a->mnt_flags, UDBA_INOTIFY);
13799+ struct mutex *h_mtx;
13800+
13801+ LKTRTrace("src %.*s, i%lu, dst %.*s\n",
13802+ AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry));
13803+
13804+ di_read_lock_parent(a->src_parent, AuLock_IR);
13805+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
13806+ if (unlikely(err))
13807+ goto out;
13808+
13809+ AuDebugOn(au_dbstart(src_dentry) != a->bsrc);
13810+ h_mtx = &au_h_dptr(src_dentry, a->bsrc)->d_inode->i_mutex;
13811+ a->pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
13812+ if (hinotify)
13813+ au_fset_pin(a->pin_flags, DO_GPARENT);
13814+ err = au_pin(&a->pin, src_dentry, a->bdst, a->pin_flags);
13815+ if (unlikely(err))
13816+ goto out;
13817+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13818+ /* todo: no KEEPLINO because of noplink? */
13819+ err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
13820+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
13821+ mutex_unlock(h_mtx);
13822+ au_unpin(&a->pin);
13823+
13824+ out:
13825+ di_read_unlock(a->src_parent, AuLock_IR);
13826+ AuTraceErr(err);
13827+ return err;
13828+}
13829+
13830+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
13831+{
13832+ int err;
13833+ struct inode *h_inode;
13834+ aufs_bindex_t bstart;
13835+ struct dentry *h_src_dentry;
13836+
13837+ AuTraceEnter();
13838+ AuDebugOn(au_dbstart(src_dentry) != a->bsrc);
13839+
13840+ bstart = au_ibstart(src_dentry->d_inode);
13841+ h_inode = NULL;
13842+ if (bstart <= a->bdst)
13843+ h_inode = au_h_iptr(src_dentry->d_inode, a->bdst);
13844+ if (!h_inode || !h_inode->i_nlink) {
13845+ /* copyup src_dentry as the name of dentry. */
13846+ au_set_dbstart(src_dentry, a->bdst);
13847+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_dentry));
13848+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
13849+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
13850+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
13851+ AuCpup_KEEPLINO, a->parent);
13852+ mutex_unlock(&h_inode->i_mutex);
13853+ au_set_h_dptr(src_dentry, a->bdst, NULL);
13854+ au_set_dbstart(src_dentry, a->bsrc);
13855+ } else {
13856+ /* the inode of src_dentry already exists on a.bdst branch */
13857+ h_src_dentry = d_find_alias(h_inode);
13858+ if (h_src_dentry) {
13859+ /* vfsub_args_reinit(&a->vargs); */
13860+ vfsub_ign_hinode(&a->vargs, IN_CREATE,
13861+ au_pinned_hdir(&a->pin));
13862+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13863+ a->h_dentry, &a->vargs);
13864+ dput(h_src_dentry);
13865+ } else {
13866+ AuIOErr("no dentry found for i%lu on b%d\n",
13867+ h_inode->i_ino, a->bdst);
13868+ err = -EIO;
13869+ }
13870+ }
13871+
13872+ if (!err)
13873+ au_plink_append(src_dentry->d_sb, src_dentry->d_inode,
13874+ a->h_dentry, a->bdst);
13875+
13876+ AuTraceErr(err);
13877+ return err;
13878+}
13879+
13880+int aufs_link(struct dentry *src_dentry, struct inode *dir,
13881+ struct dentry *dentry)
13882+{
13883+ int err, rerr;
13884+ struct au_dtime dt;
13885+ struct super_block *sb;
13886+ struct au_link_args *a;
13887+ struct au_wr_dir_args wr_dir_args = {
13888+ /* .force_btgt = -1, */
13889+ .flags = AuWrDir_ADD_ENTRY
13890+ };
13891+ struct dentry *wh_dentry, *h_src_dentry;
13892+ struct inode *inode;
13893+
13894+ LKTRTrace("src %.*s, i%lu, dst %.*s\n",
13895+ AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry));
13896+ IMustLock(dir);
13897+ inode = src_dentry->d_inode;
13898+ IMustLock(inode);
13899+ AuDebugOn(S_ISDIR(inode->i_mode));
13900+
13901+ err = -ENOMEM;
13902+ a = kzalloc(sizeof(*a), GFP_NOFS);
13903+ if (unlikely(!a))
13904+ goto out;
13905+
13906+ sb = dentry->d_sb;
13907+ a->parent = dentry->d_parent; /* dir inode is locked */
13908+ aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
13909+ a->src_parent = dget_parent(src_dentry);
13910+ wr_dir_args.force_btgt = au_dbstart(src_dentry);
13911+ a->mnt_flags = au_mntflags(sb);
13912+ vfsub_args_init(&a->vargs, &a->ign, au_test_dlgt(a->mnt_flags), 0);
13913+
13914+ di_write_lock_parent(a->parent);
13915+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
13916+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
13917+ &wr_dir_args);
13918+ err = PTR_ERR(wh_dentry);
13919+ if (IS_ERR(wh_dentry))
13920+ goto out_unlock;
13921+ err = 0;
13922+
13923+ a->bdst = au_dbstart(dentry);
13924+ a->h_dentry = au_h_dptr(dentry, a->bdst);
13925+
13926+ /* todo: minor optimize,
13927+ their sb may be same while their bindex differs? */
13928+ a->bsrc = au_dbstart(src_dentry);
13929+ if (au_opt_test(a->mnt_flags, PLINK)) {
13930+ if (a->bdst < a->bsrc
13931+ /* && h_src_dentry->d_sb != a->h_dentry->d_sb */)
13932+ err = au_cpup_or_link(src_dentry, a);
13933+ else {
13934+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13935+ AuDebugOn(!h_src_dentry);
13936+ AuDebugOn(!h_src_dentry->d_inode);
13937+ vfsub_ign_hinode(&a->vargs, IN_CREATE,
13938+ au_pinned_hdir(&a->pin));
13939+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13940+ a->h_dentry, &a->vargs);
13941+ }
13942+ } else {
13943+ /*
13944+ * copyup src_dentry to the branch we process,
13945+ * and then link(2) to it.
13946+ */
13947+ if (a->bdst < a->bsrc
13948+ /* && h_src_dentry->d_sb != a->h_dentry->d_sb */) {
13949+ au_unpin(&a->pin);
13950+ di_write_unlock(a->parent);
13951+ err = au_cpup_before_link(src_dentry, dir, dentry, a);
13952+ if (!err) {
13953+ a->pin_flags
13954+ = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
13955+ if (au_opt_test(a->mnt_flags, UDBA_INOTIFY))
13956+ au_fset_pin(a->pin_flags, DO_GPARENT);
13957+ di_write_lock_parent(a->parent);
13958+ err = au_pin(&a->pin, dentry, a->bdst,
13959+ a->pin_flags);
13960+ if (unlikely(err))
13961+ goto out_wh;
13962+ }
13963+ }
13964+ if (!err) {
13965+ /* vfsub_args_reinit(&a->vargs); */
13966+ vfsub_ign_hinode(&a->vargs, IN_CREATE,
13967+ au_pinned_hdir(&a->pin));
13968+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13969+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13970+ a->h_dentry, &a->vargs);
13971+ }
13972+ }
13973+ if (unlikely(err))
13974+ goto out_unpin;
13975+
13976+ if (wh_dentry) {
13977+ err = au_wh_unlink_dentry(au_pinned_hdir(&a->pin), wh_dentry,
13978+ dentry, /*dlgt*/0);
13979+ if (unlikely(err))
13980+ goto out_revert;
13981+ }
13982+
13983+#if 0 /* cannot support it */
13984+ /* fuse has different memory inode for the same inode number */
13985+ if (au_test_fuse(a->h_dentry->d_sb)) {
13986+ LKTRLabel(here);
13987+ d_drop(a->h_dentry);
13988+ /*d_drop(h_src_dentry);
13989+ d_drop(src_dentry);*/
13990+ inc_nlink(a->inode);
13991+ a->inode->i_ctime = dir->i_ctime;
13992+ }
13993+#endif
13994+
13995+ dir->i_version++;
13996+ if (au_ibstart(dir) == au_dbstart(dentry))
13997+ au_cpup_attr_timesizes(dir);
13998+ if (!d_unhashed(a->h_dentry)
13999+ /* || h_old_inode->i_nlink <= nlink */
14000+ /* || SB_NFS(h_src_dentry->d_sb) */) {
14001+ d_instantiate(dentry, au_igrab(inode));
14002+ inc_nlink(inode);
14003+ inode->i_ctime = dir->i_ctime;
14004+ } else
14005+ /* nfs case (< 2.6.15) */
14006+ d_drop(dentry);
14007+ goto out_unpin; /* success */
14008+
14009+ out_revert:
14010+ vfsub_args_reinit(&a->vargs);
14011+ vfsub_ign_hinode(&a->vargs, IN_DELETE, au_pinned_hdir(&a->pin));
14012+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), a->h_dentry, &a->vargs);
14013+ if (!rerr)
14014+ goto out_dt;
14015+ AuIOErr("%.*s reverting failed(%d, %d)\n",
14016+ AuDLNPair(dentry), err, rerr);
14017+ err = -EIO;
14018+ out_dt:
14019+ d_drop(dentry);
14020+ au_dtime_revert(&dt);
14021+ out_unpin:
14022+ au_unpin(&a->pin);
14023+ out_wh:
14024+ dput(wh_dentry);
14025+ out_unlock:
14026+ if (unlikely(err)) {
14027+ au_update_dbstart(dentry);
14028+ d_drop(dentry);
14029+ }
14030+ di_write_unlock(a->parent);
14031+ dput(a->src_parent);
14032+ aufs_read_and_write_unlock2(dentry, src_dentry);
14033+ kfree(a);
14034+ out:
14035+ AuTraceErr(err);
14036+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
14037+ err = -ESTALE;
14038+ return err;
14039+}
14040+
14041+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
14042+{
14043+ int err, rerr;
14044+ struct dentry *h_dentry, *wh_dentry, *parent, *opq_dentry;
14045+ struct mutex *h_mtx;
14046+ struct au_dtime dt;
14047+ aufs_bindex_t bindex;
14048+ unsigned char diropq, dlgt;
14049+ unsigned int mnt_flags;
14050+ struct au_hin_ignore ign;
14051+ struct vfsub_args vargs;
14052+ struct au_pin pin;
14053+ struct au_wr_dir_args wr_dir_args = {
14054+ .force_btgt = -1,
14055+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
14056+ };
14057+
14058+ LKTRTrace("i%lu, %.*s, mode 0%o\n",
14059+ dir->i_ino, AuDLNPair(dentry), mode);
14060+ IMustLock(dir);
14061+
14062+ aufs_read_lock(dentry, AuLock_DW);
14063+ parent = dentry->d_parent; /* dir inode is locked */
14064+ mnt_flags = au_mntflags(dentry->d_sb);
14065+ dlgt = !!au_test_dlgt(mnt_flags);
14066+ vfsub_args_init(&vargs, &ign, dlgt, 0);
14067+
14068+ di_write_lock_parent(parent);
14069+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
14070+ &wr_dir_args);
14071+ err = PTR_ERR(wh_dentry);
14072+ if (IS_ERR(wh_dentry))
14073+ goto out;
14074+
14075+ bindex = au_dbstart(dentry);
14076+ h_dentry = au_h_dptr(dentry, bindex);
14077+ vfsub_ign_hinode(&vargs, IN_CREATE, au_pinned_hdir(&pin));
14078+ err = vfsub_mkdir(au_pinned_h_dir(&pin), h_dentry, mode, &vargs);
14079+ if (unlikely(err))
14080+ goto out_unlock;
14081+
14082+ /* make the dir opaque */
14083+ diropq = 0;
14084+ h_mtx = &h_dentry->d_inode->i_mutex;
14085+ if (wh_dentry || au_opt_test(mnt_flags, ALWAYS_DIROPQ)) {
14086+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14087+ opq_dentry = au_diropq_create(dentry, bindex, /*dlgt*/0);
14088+ mutex_unlock(h_mtx);
14089+ err = PTR_ERR(opq_dentry);
14090+ if (IS_ERR(opq_dentry))
14091+ goto out_dir;
14092+ dput(opq_dentry);
14093+ diropq = 1;
14094+ }
14095+
14096+ err = epilog(dir, bindex, wh_dentry, dentry);
14097+ if (!err) {
14098+ inc_nlink(dir);
14099+ goto out_unlock; /* success */
14100+ }
14101+
14102+ /* revert */
14103+ if (diropq) {
14104+ LKTRLabel(revert opq);
14105+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14106+ rerr = au_diropq_remove(dentry, bindex, dlgt);
14107+ mutex_unlock(h_mtx);
14108+ if (rerr) {
14109+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
14110+ AuDLNPair(dentry), err, rerr);
14111+ err = -EIO;
14112+ }
14113+ }
14114+
14115+ out_dir:
14116+ LKTRLabel(revert dir);
14117+ vfsub_args_reinit(&vargs);
14118+ vfsub_ign_hinode(&vargs, IN_DELETE, au_pinned_hdir(&pin));
14119+ rerr = vfsub_rmdir(au_pinned_h_dir(&pin), h_dentry, &vargs);
14120+ if (rerr) {
14121+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
14122+ AuDLNPair(dentry), err, rerr);
14123+ err = -EIO;
14124+ }
14125+ d_drop(dentry);
14126+ au_dtime_revert(&dt);
14127+ out_unlock:
14128+ au_unpin(&pin);
14129+ dput(wh_dentry);
14130+ out:
14131+ if (unlikely(err)) {
14132+ au_update_dbstart(dentry);
14133+ d_drop(dentry);
14134+ }
14135+ di_write_unlock(parent);
14136+ aufs_read_unlock(dentry, AuLock_DW);
14137+ AuTraceErr(err);
14138+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
14139+ err = -ESTALE;
14140+ return err;
14141+}
14142diff -urN linux/fs/aufs/i_op.c linux-aufs/fs/aufs/i_op.c
14143--- linux/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
14144+++ linux-aufs/fs/aufs/i_op.c 2009-03-12 16:18:04.000000000 +0100
14145@@ -0,0 +1,1049 @@
14146+/*
14147+ * Copyright (C) 2005-2009 Junjiro Okajima
14148+ *
14149+ * This program, aufs is free software; you can redistribute it and/or modify
14150+ * it under the terms of the GNU General Public License as published by
14151+ * the Free Software Foundation; either version 2 of the License, or
14152+ * (at your option) any later version.
14153+ *
14154+ * This program is distributed in the hope that it will be useful,
14155+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14156+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14157+ * GNU General Public License for more details.
14158+ *
14159+ * You should have received a copy of the GNU General Public License
14160+ * along with this program; if not, write to the Free Software
14161+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14162+ */
14163+
14164+/*
14165+ * inode operations (except add/del/rename)
14166+ *
14167+ * $Id$
14168+ */
14169+
14170+#include <linux/fs_stack.h>
14171+#include <linux/uaccess.h>
14172+#include "aufs.h"
14173+
14174+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
14175+static int h_permission(struct inode *h_inode, int mask,
14176+ struct vfsmount *h_mnt, int brperm, int dlgt)
14177+{
14178+ int err, submask;
14179+ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
14180+
14181+ LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n",
14182+ h_inode->i_ino, mask, brperm);
14183+
14184+ err = -EACCES;
14185+ if ((write_mask && IS_IMMUTABLE(h_inode))
14186+ || ((mask & MAY_EXEC) && S_ISREG(h_inode->i_mode)
14187+ && (h_mnt->mnt_flags & MNT_NOEXEC)))
14188+ goto out;
14189+
14190+ /*
14191+ * - skip hidden fs test in the case of write to ro branch.
14192+ * - nfs dir permission write check is optimized, but a policy for
14193+ * link/rename requires a real check.
14194+ */
14195+ submask = mask & ~MAY_APPEND;
14196+ if ((write_mask && !au_br_writable(brperm))
14197+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
14198+ && write_mask && !(mask & MAY_READ))
14199+ || !h_inode->i_op
14200+ || !h_inode->i_op->permission) {
14201+ /* LKTRLabel(generic_permission); */
14202+ err = generic_permission(h_inode, submask, NULL);
14203+ } else {
14204+ /* LKTRLabel(h_inode->permission); */
14205+ err = h_inode->i_op->permission(h_inode, submask);
14206+ AuTraceErr(err);
14207+ }
14208+
14209+#if 1 /* todo: export? */
14210+ if (!err)
14211+ err = au_security_inode_permission(h_inode, mask, NULL,
14212+ dlgt);
14213+#endif
14214+
14215+ out:
14216+ AuTraceErr(err);
14217+ return err;
14218+}
14219+
14220+static int aufs_permission(struct inode *inode, int mask)
14221+{
14222+ int err;
14223+ aufs_bindex_t bindex, bend;
14224+ unsigned char dlgt;
14225+ const unsigned char isdir = S_ISDIR(inode->i_mode);
14226+ struct inode *h_inode;
14227+ struct super_block *sb;
14228+ unsigned int mnt_flags;
14229+ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
14230+
14231+ LKTRTrace("ino %lu, mask 0x%x, isdir %d, write_mask %d\n",
14232+ inode->i_ino, mask, isdir, write_mask);
14233+
14234+ sb = inode->i_sb;
14235+ si_read_lock(sb, AuLock_FLUSH);
14236+ ii_read_lock_child(inode);
14237+ mnt_flags = au_mntflags(sb);
14238+ dlgt = !!au_test_dlgt(mnt_flags);
14239+
14240+ if (!isdir || write_mask || au_test_dirperm1(mnt_flags)) {
14241+ h_inode = au_h_iptr(inode, au_ibstart(inode));
14242+ AuDebugOn(!h_inode
14243+ || ((h_inode->i_mode & S_IFMT)
14244+ != (inode->i_mode & S_IFMT)));
14245+ err = 0;
14246+ bindex = au_ibstart(inode);
14247+ LKTRTrace("b%d\n", bindex);
14248+ err = h_permission(h_inode, mask, au_sbr_mnt(sb, bindex),
14249+ au_sbr_perm(sb, bindex), dlgt);
14250+
14251+ if (write_mask && !err) {
14252+ /* test whether the upper writable branch exists */
14253+ err = -EROFS;
14254+ for (; bindex >= 0; bindex--)
14255+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
14256+ err = 0;
14257+ break;
14258+ }
14259+ }
14260+ goto out;
14261+ }
14262+
14263+ /* non-write to dir */
14264+ err = 0;
14265+ bend = au_ibend(inode);
14266+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
14267+ h_inode = au_h_iptr(inode, bindex);
14268+ if (!h_inode)
14269+ continue;
14270+ AuDebugOn(!S_ISDIR(h_inode->i_mode));
14271+
14272+ LKTRTrace("b%d\n", bindex);
14273+ err = h_permission(h_inode, mask, au_sbr_mnt(sb, bindex),
14274+ au_sbr_perm(sb, bindex), dlgt);
14275+ }
14276+
14277+ out:
14278+ ii_read_unlock(inode);
14279+ si_read_unlock(sb);
14280+ AuTraceErr(err);
14281+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
14282+ err = -ESTALE;
14283+ return err;
14284+}
14285+#else
14286+
14287+static int silly_lock(struct inode *inode, struct nameidata *nd)
14288+{
14289+ int locked = 0;
14290+ struct super_block *sb = inode->i_sb;
14291+
14292+ LKTRTrace("i%lu, nd %p\n", inode->i_ino, nd);
14293+
14294+ if (!nd || !nd->path.dentry) {
14295+ si_read_lock(sb, AuLock_FLUSH);
14296+ ii_read_lock_child(inode);
14297+ } else if (nd->path.dentry->d_inode != inode) {
14298+ locked = 1;
14299+ /* lock child first, then parent */
14300+ si_read_lock(sb, AuLock_FLUSH);
14301+ ii_read_lock_child(inode);
14302+ di_read_lock_parent(nd->path.dentry, 0);
14303+ } else {
14304+ locked = 2;
14305+ aufs_read_lock(nd->path.dentry, AuLock_FLUSH | AuLock_IR);
14306+ }
14307+ return locked;
14308+}
14309+
14310+static void silly_unlock(int locked, struct inode *inode, struct nameidata *nd)
14311+{
14312+ struct super_block *sb = inode->i_sb;
14313+
14314+ LKTRTrace("locked %d, i%lu, nd %p\n", locked, inode->i_ino, nd);
14315+
14316+ switch (locked) {
14317+ case 0:
14318+ ii_read_unlock(inode);
14319+ si_read_unlock(sb);
14320+ break;
14321+ case 1:
14322+ di_read_unlock(nd->path.dentry, 0);
14323+ ii_read_unlock(inode);
14324+ si_read_unlock(sb);
14325+ break;
14326+ case 2:
14327+ aufs_read_unlock(nd->path.dentry, AuLock_IR);
14328+ break;
14329+ default:
14330+ BUG();
14331+ }
14332+}
14333+
14334+static int h_permission(struct inode *h_inode, int mask,
14335+ struct nameidata *fake_nd, int brperm, int dlgt)
14336+{
14337+ int err, submask;
14338+ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
14339+
14340+ LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n",
14341+ h_inode->i_ino, mask, brperm);
14342+
14343+ err = -EACCES;
14344+ if ((write_mask && IS_IMMUTABLE(h_inode))
14345+ || ((mask & MAY_EXEC) && S_ISREG(h_inode->i_mode)
14346+ && fake_nd && fake_nd->path.mnt
14347+ && (fake_nd->path.mnt->mnt_flags & MNT_NOEXEC)))
14348+ goto out;
14349+
14350+ /*
14351+ * - skip hidden fs test in the case of write to ro branch.
14352+ * - nfs dir permission write check is optimized, but a policy for
14353+ * link/rename requires a real check.
14354+ */
14355+ submask = mask & ~MAY_APPEND;
14356+ if ((write_mask && !au_br_writable(brperm))
14357+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
14358+ && write_mask && !(mask & MAY_READ))
14359+ || !h_inode->i_op
14360+ || !h_inode->i_op->permission) {
14361+ /* LKTRLabel(generic_permission); */
14362+ err = generic_permission(h_inode, submask, NULL);
14363+ } else {
14364+ /* LKTRLabel(h_inode->permission); */
14365+ err = h_inode->i_op->permission(h_inode, submask, fake_nd);
14366+ AuTraceErr(err);
14367+ }
14368+
14369+#if 1 /* todo: export? */
14370+ if (!err)
14371+ err = au_security_inode_permission(h_inode, mask, fake_nd,
14372+ dlgt);
14373+#endif
14374+
14375+ out:
14376+ AuTraceErr(err);
14377+ return err;
14378+}
14379+
14380+static int aufs_permission(struct inode *inode, int mask, struct nameidata *nd)
14381+{
14382+ int err;
14383+ aufs_bindex_t bindex, bend;
14384+ unsigned char locked, dlgt, do_nd;
14385+ const unsigned char isdir = S_ISDIR(inode->i_mode);
14386+ struct inode *h_inode;
14387+ struct super_block *sb;
14388+ unsigned int mnt_flags;
14389+ struct path path;
14390+ const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
14391+
14392+ LKTRTrace("ino %lu, mask 0x%x, isdir %d, write_mask %d, "
14393+ "nd %d{%d, %d}\n",
14394+ inode->i_ino, mask, isdir, write_mask,
14395+ !!nd, nd ? !!nd->path.dentry : 0, nd ? !!nd->path.mnt : 0);
14396+
14397+ sb = inode->i_sb;
14398+ locked = silly_lock(inode, nd);
14399+ do_nd = (nd && locked >= 1);
14400+ mnt_flags = au_mntflags(sb);
14401+ dlgt = !!au_test_dlgt(mnt_flags);
14402+
14403+ if (!isdir || write_mask || au_test_dirperm1(mnt_flags)) {
14404+ h_inode = au_h_iptr(inode, au_ibstart(inode));
14405+ AuDebugOn(!h_inode
14406+ || ((h_inode->i_mode & S_IFMT)
14407+ != (inode->i_mode & S_IFMT)));
14408+ err = 0;
14409+ bindex = au_ibstart(inode);
14410+ LKTRTrace("b%d\n", bindex);
14411+ if (do_nd) {
14412+ path = nd->path;
14413+ nd->path.mnt = au_sbr_mnt(sb, bindex);
14414+ nd->path.dentry = au_h_dptr(nd->path.dentry, bindex);
14415+ path_get(&nd->path);
14416+ err = h_permission(h_inode, mask, nd,
14417+ au_sbr_perm(sb, bindex), dlgt);
14418+ path_put(&nd->path);
14419+ nd->path = path;
14420+ } else {
14421+ AuDebugOn(nd && nd->path.mnt);
14422+ err = h_permission(h_inode, mask, nd,
14423+ au_sbr_perm(sb, bindex), dlgt);
14424+ }
14425+
14426+ if (write_mask && !err) {
14427+ /* test whether the upper writable branch exists */
14428+ err = -EROFS;
14429+ for (; bindex >= 0; bindex--)
14430+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
14431+ err = 0;
14432+ break;
14433+ }
14434+ }
14435+ goto out;
14436+ }
14437+
14438+ /* non-write to dir */
14439+ if (do_nd)
14440+ path = nd->path;
14441+ else {
14442+ path.mnt = NULL;
14443+ path.dentry = NULL;
14444+ }
14445+ err = 0;
14446+ bend = au_ibend(inode);
14447+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
14448+ h_inode = au_h_iptr(inode, bindex);
14449+ if (!h_inode)
14450+ continue;
14451+ AuDebugOn(!S_ISDIR(h_inode->i_mode));
14452+
14453+ LKTRTrace("b%d\n", bindex);
14454+ if (do_nd) {
14455+ nd->path.mnt = au_sbr_mnt(sb, bindex);
14456+ nd->path.dentry = au_h_dptr(path.dentry, bindex);
14457+ path_get(&nd->path);
14458+ err = h_permission(h_inode, mask, nd,
14459+ au_sbr_perm(sb, bindex), dlgt);
14460+ path_put(&nd->path);
14461+ } else {
14462+ AuDebugOn(nd && nd->path.mnt);
14463+ err = h_permission(h_inode, mask, nd,
14464+ au_sbr_perm(sb, bindex), dlgt);
14465+ }
14466+ }
14467+ if (do_nd)
14468+ nd->path = path;
14469+
14470+ out:
14471+ silly_unlock(locked, inode, nd);
14472+ AuTraceErr(err);
14473+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
14474+ err = -ESTALE;
14475+ return err;
14476+}
14477+#endif /* KERNEL_VERSION(2, 6, 27) */
14478+
14479+/* ---------------------------------------------------------------------- */
14480+
14481+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
14482+ struct nameidata *nd)
14483+{
14484+ struct dentry *ret, *parent;
14485+ int err, npositive;
14486+ struct inode *inode, *h_inode;
14487+ struct nameidata tmp_nd, *ndp;
14488+ aufs_bindex_t bstart;
14489+ struct mutex *mtx;
14490+ struct super_block *sb;
14491+
14492+ LKTRTrace("dir %lu, %.*s, nd{0x%x}\n",
14493+ dir->i_ino, AuDLNPair(dentry), nd ? nd->flags : 0);
14494+ AuDebugOn(IS_ROOT(dentry));
14495+ IMustLock(dir);
14496+
14497+ sb = dir->i_sb;
14498+ si_read_lock(sb, AuLock_FLUSH);
14499+ err = au_alloc_dinfo(dentry);
14500+ ret = ERR_PTR(err);
14501+ if (unlikely(err))
14502+ goto out;
14503+
14504+ /* nd can be NULL */
14505+ ndp = au_dup_nd(au_sbi(sb), &tmp_nd, nd);
14506+ parent = dentry->d_parent; /* dir inode is locked */
14507+ di_read_lock_parent(parent, AuLock_IR);
14508+ npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, ndp);
14509+ di_read_unlock(parent, AuLock_IR);
14510+ err = npositive;
14511+ ret = ERR_PTR(err);
14512+ if (unlikely(err < 0))
14513+ goto out_unlock;
14514+
14515+ inode = NULL;
14516+ if (npositive) {
14517+ bstart = au_dbstart(dentry);
14518+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
14519+ AuDebugOn(!h_inode);
14520+ if (!S_ISDIR(h_inode->i_mode)) {
14521+ /*
14522+ * stop 'race'-ing between hardlinks under different
14523+ * parents.
14524+ */
14525+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
14526+ mutex_lock(mtx);
14527+ inode = au_new_inode(dentry, /*must_new*/0);
14528+ mutex_unlock(mtx);
14529+ } else
14530+ inode = au_new_inode(dentry, /*must_new*/0);
14531+ ret = (void *)inode;
14532+ }
14533+ if (!IS_ERR(inode)) {
14534+ ret = d_splice_alias(inode, dentry);
14535+ if (unlikely(IS_ERR(ret) && inode))
14536+ ii_write_unlock(inode);
14537+ AuDebugOn(nd
14538+ && (nd->flags & LOOKUP_OPEN)
14539+ && nd->intent.open.file
14540+ && nd->intent.open.file->f_dentry);
14541+ au_store_fmode_exec(nd, inode);
14542+ }
14543+
14544+ out_unlock:
14545+ di_write_unlock(dentry);
14546+ out:
14547+ si_read_unlock(sb);
14548+ AuTraceErrPtr(ret);
14549+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
14550+ err = -ESTALE;
14551+ return ret;
14552+}
14553+
14554+/* ---------------------------------------------------------------------- */
14555+
14556+/*
14557+ * decide the branch and the parent dir where we will create a new entry.
14558+ * returns new bindex or an error.
14559+ * copyup the parent dir if needed.
14560+ */
14561+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14562+ struct au_wr_dir_args *args)
14563+{
14564+ int err;
14565+ aufs_bindex_t bcpup, bstart, src_bstart;
14566+ struct super_block *sb;
14567+ struct dentry *parent;
14568+ struct au_sbinfo *sbinfo;
14569+ const int add_entry = au_ftest_wrdir(args->flags, ADD_ENTRY);
14570+
14571+ LKTRTrace("%.*s, src %p, {%d, 0x%x}\n",
14572+ AuDLNPair(dentry), src_dentry, args->force_btgt, args->flags);
14573+
14574+ sb = dentry->d_sb;
14575+ sbinfo = au_sbi(sb);
14576+ parent = dget_parent(dentry);
14577+ bstart = au_dbstart(dentry);
14578+ bcpup = bstart;
14579+ if (args->force_btgt < 0) {
14580+ if (src_dentry) {
14581+ src_bstart = au_dbstart(src_dentry);
14582+ if (src_bstart < bstart)
14583+ bcpup = src_bstart;
14584+ } else if (add_entry) {
14585+ err = AuWbrCreate(sbinfo, dentry,
14586+ au_ftest_wrdir(args->flags, ISDIR));
14587+ bcpup = err;
14588+ }
14589+
14590+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
14591+ if (add_entry)
14592+ err = AuWbrCopyup(sbinfo, dentry);
14593+ else {
14594+ if (!IS_ROOT(dentry)) {
14595+ di_read_lock_parent(parent, !AuLock_IR);
14596+ err = AuWbrCopyup(sbinfo, dentry);
14597+ di_read_unlock(parent, !AuLock_IR);
14598+ } else
14599+ err = AuWbrCopyup(sbinfo, dentry);
14600+ }
14601+ bcpup = err;
14602+ if (unlikely(err < 0))
14603+ goto out;
14604+ }
14605+ } else {
14606+ bcpup = args->force_btgt;
14607+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
14608+ }
14609+ LKTRTrace("bstart %d, bcpup %d\n", bstart, bcpup);
14610+ if (bstart < bcpup)
14611+ au_update_dbrange(dentry, /*do_put_zero*/1);
14612+
14613+ err = bcpup;
14614+ if (bcpup == bstart)
14615+ goto out; /* success */
14616+
14617+ /* copyup the new parent into the branch we process */
14618+ if (add_entry) {
14619+ au_update_dbstart(dentry);
14620+ IMustLock(parent->d_inode);
14621+ DiMustWriteLock(parent);
14622+ IiMustWriteLock(parent->d_inode);
14623+ } else
14624+ di_write_lock_parent(parent);
14625+
14626+ err = 0;
14627+ if (!au_h_dptr(parent, bcpup)) {
14628+ if (bstart < bcpup)
14629+ err = au_cpdown_dirs(dentry, bcpup);
14630+ else
14631+ err = au_cpup_dirs(dentry, bcpup);
14632+ }
14633+ if (!err && add_entry) {
14634+ struct dentry *h_parent;
14635+ struct inode *h_dir;
14636+
14637+ h_parent = au_h_dptr(parent, bcpup);
14638+ AuDebugOn(!h_parent);
14639+ h_dir = h_parent->d_inode;
14640+ AuDebugOn(!h_dir);
14641+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
14642+ err = au_lkup_neg(dentry, bcpup);
14643+ mutex_unlock(&h_dir->i_mutex);
14644+ if (bstart < bcpup && au_dbstart(dentry) < 0) {
14645+ au_set_dbstart(dentry, 0);
14646+ au_update_dbrange(dentry, /*do_put_zero*/0);
14647+ }
14648+ }
14649+
14650+ if (!add_entry)
14651+ di_write_unlock(parent);
14652+ if (!err)
14653+ err = bcpup; /* success */
14654+ out:
14655+ dput(parent);
14656+ LKTRTrace("err %d\n", err);
14657+ AuTraceErr(err);
14658+ return err;
14659+}
14660+
14661+/* ---------------------------------------------------------------------- */
14662+
14663+struct dentry *au_do_pinned_h_parent(struct au_pin1 *pin)
14664+{
14665+ if (pin && pin->parent)
14666+ return au_h_dptr(pin->parent, pin->bindex);
14667+ return NULL;
14668+}
14669+
14670+void au_do_unpin(struct au_pin1 *p, struct au_pin1 *gp)
14671+{
14672+ if (p->dentry)
14673+ LKTRTrace("%.*s\n", AuDLNPair(p->dentry));
14674+ LKTRTrace("p{%d, %d, %d, %d, 0x%x}, gp %p\n",
14675+ p->lsc_di, p->lsc_hi, !!p->parent, !!p->h_dir, p->flags, gp);
14676+
14677+ if (au_ftest_pin(p->flags, MNT_WRITE))
14678+ au_br_drop_write(au_sbr(p->dentry->d_sb, p->bindex));
14679+ if (au_ftest_pin(p->flags, VFS_RENAME))
14680+ vfsub_unlock_rename_mutex(au_sbr_sb(p->dentry->d_sb,
14681+ p->bindex));
14682+ if (!p->h_dir)
14683+ return;
14684+
14685+ mutex_unlock(&p->h_dir->i_mutex);
14686+ if (gp)
14687+ au_do_unpin(gp, NULL);
14688+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14689+ di_read_unlock(p->parent, AuLock_IR);
14690+ iput(p->h_dir);
14691+ dput(p->parent);
14692+ p->parent = NULL;
14693+ p->h_dir = NULL;
14694+}
14695+
14696+int au_do_pin(struct au_pin1 *p, struct au_pin1 *gp)
14697+{
14698+ int err;
14699+ struct dentry *h_dentry;
14700+
14701+ LKTRTrace("%.*s, %d, b%d, 0x%x\n",
14702+ AuDLNPair(p->dentry), !!gp, p->bindex, p->flags);
14703+ AuDebugOn(au_ftest_pin(p->flags, DO_GPARENT) && !gp);
14704+ /* AuDebugOn(!do_gp && gp); */
14705+
14706+ err = 0;
14707+ if (IS_ROOT(p->dentry)) {
14708+ if (au_ftest_pin(p->flags, VFS_RENAME))
14709+ vfsub_lock_rename_mutex(au_sbr_sb(p->dentry->d_sb,
14710+ p->bindex));
14711+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14712+ err = au_br_want_write(au_sbr(p->dentry->d_sb,
14713+ p->bindex));
14714+ if (unlikely(err))
14715+ au_fclr_pin(p->flags, MNT_WRITE);
14716+ }
14717+ goto out;
14718+ }
14719+
14720+ h_dentry = NULL;
14721+ if (p->bindex <= au_dbend(p->dentry))
14722+ h_dentry = au_h_dptr(p->dentry, p->bindex);
14723+
14724+ p->parent = dget_parent(p->dentry);
14725+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14726+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
14727+ else
14728+ DiMustAnyLock(p->parent);
14729+ AuDebugOn(!p->parent->d_inode);
14730+ p->h_dir = au_igrab(au_h_iptr(p->parent->d_inode, p->bindex));
14731+ /* udba case */
14732+ if (unlikely(au_ftest_pin(p->flags, VERIFY) && !p->h_dir)) {
14733+ err = -EIO;
14734+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14735+ di_read_unlock(p->parent, AuLock_IR);
14736+ dput(p->parent);
14737+ p->parent = NULL;
14738+ goto out;
14739+ }
14740+
14741+ if (au_ftest_pin(p->flags, DO_GPARENT)) {
14742+ gp->dentry = p->parent;
14743+ err = au_do_pin(gp, NULL);
14744+ if (unlikely(err))
14745+ gp->dentry = NULL;
14746+ }
14747+ if (au_ftest_pin(p->flags, VFS_RENAME))
14748+ vfsub_lock_rename_mutex(p->h_dir->i_sb);
14749+ mutex_lock_nested(&p->h_dir->i_mutex, p->lsc_hi);
14750+ if (!err) {
14751+ /* todo: call d_revalidate() here? */
14752+#if 0
14753+ if (h_dentry && h_dentry->d_op && h_dentry->d_op->d_revalidate
14754+ && !h_dentry->d_op->d_revalidate(h_dentry, NULL))
14755+ err = -EIO;
14756+#endif
14757+ if (!h_dentry
14758+ || !au_ftest_pin(p->flags, VERIFY)
14759+ || !au_verify_parent(h_dentry, p->h_dir)) {
14760+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14761+ err = au_br_want_write(au_sbr(p->dentry->d_sb,
14762+ p->bindex));
14763+ if (unlikely(err))
14764+ au_fclr_pin(p->flags, MNT_WRITE);
14765+ }
14766+ if (!err)
14767+ goto out; /* success */
14768+ } else
14769+ err = -EIO;
14770+ }
14771+
14772+ AuDbgDentry(p->dentry);
14773+ AuDbgDentry(h_dentry);
14774+ AuDbgDentry(p->parent);
14775+ AuDbgInode(p->h_dir);
14776+ if (h_dentry)
14777+ AuDbgDentry(h_dentry->d_parent);
14778+
14779+ au_do_unpin(p, gp);
14780+ if (au_ftest_pin(p->flags, DO_GPARENT))
14781+ gp->dentry = NULL;
14782+
14783+ out:
14784+ AuTraceErr(err);
14785+ return err;
14786+}
14787+
14788+void au_pin_init(struct au_pin *args, struct dentry *dentry,
14789+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14790+ unsigned char flags)
14791+{
14792+ struct au_pin1 *p;
14793+ unsigned char f;
14794+
14795+ AuTraceEnter();
14796+
14797+ memset(args, 0, sizeof(*args));
14798+ p = args->pin + AuPin_PARENT;
14799+ p->dentry = dentry;
14800+ p->lsc_di = lsc_di;
14801+ p->lsc_hi = lsc_hi;
14802+ p->flags = flags;
14803+ p->bindex = bindex;
14804+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE))
14805+ au_fset_pin(p->flags, VERIFY);
14806+ if (!au_ftest_pin(flags, DO_GPARENT))
14807+ return;
14808+
14809+ f = p->flags;
14810+ p = au_pin_gp(args);
14811+ if (p) {
14812+ p->lsc_di = lsc_di + 1; /* child first */
14813+ p->lsc_hi = lsc_hi - 1; /* parent first */
14814+ p->bindex = bindex;
14815+ p->flags = f & ~(AuPin_MNT_WRITE
14816+ | AuPin_DO_GPARENT
14817+ | AuPin_DI_LOCKED);
14818+ }
14819+}
14820+
14821+int au_pin(struct au_pin *args, struct dentry *dentry, aufs_bindex_t bindex,
14822+ unsigned char flags)
14823+{
14824+ LKTRTrace("%.*s, b%d, 0x%x\n",
14825+ AuDLNPair(dentry), bindex, flags);
14826+
14827+ au_pin_init(args, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
14828+ flags);
14829+ return au_do_pin(args->pin + AuPin_PARENT, au_pin_gp(args));
14830+}
14831+
14832+/* ---------------------------------------------------------------------- */
14833+
14834+struct au_icpup_args {
14835+ unsigned char isdir, hinotify, did_cpup; /* flags */
14836+ unsigned char pin_flags;
14837+ aufs_bindex_t btgt;
14838+ struct au_pin pin;
14839+ struct au_hin_ignore ign[2];
14840+ struct vfsub_args vargs;
14841+ struct dentry *h_dentry;
14842+ struct inode *h_inode;
14843+};
14844+
14845+/* todo: refine it */
14846+static int au_lock_and_icpup(struct dentry *dentry, loff_t sz,
14847+ struct au_icpup_args *a)
14848+{
14849+ int err;
14850+ aufs_bindex_t bstart;
14851+ struct super_block *sb;
14852+ struct dentry *hi_wh, *parent;
14853+ struct inode *inode;
14854+ struct au_wr_dir_args wr_dir_args = {
14855+ .force_btgt = -1,
14856+ .flags = 0
14857+ };
14858+
14859+ LKTRTrace("%.*s, %lld\n", AuDLNPair(dentry), sz);
14860+
14861+ di_write_lock_child(dentry);
14862+ bstart = au_dbstart(dentry);
14863+ sb = dentry->d_sb;
14864+ inode = dentry->d_inode;
14865+ a->isdir = !!S_ISDIR(inode->i_mode);
14866+ if (a->isdir)
14867+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
14868+ /* plink or hi_wh() */
14869+ if (bstart != au_ibstart(inode))
14870+ wr_dir_args.force_btgt = au_ibstart(inode);
14871+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
14872+ if (unlikely(err < 0))
14873+ goto out_dentry;
14874+ a->btgt = err;
14875+ a->did_cpup = (err != bstart);
14876+ err = 0;
14877+
14878+ /* crazy udba locks */
14879+ a->pin_flags = AuPin_MNT_WRITE;
14880+ a->hinotify = !!au_opt_test(au_mntflags(sb), UDBA_INOTIFY);
14881+ if (a->hinotify)
14882+ au_fset_pin(a->pin_flags, DO_GPARENT);
14883+ parent = NULL;
14884+ if (!IS_ROOT(dentry)) {
14885+ au_fset_pin(a->pin_flags, DI_LOCKED);
14886+ parent = dget_parent(dentry);
14887+ di_write_lock_parent(parent);
14888+ }
14889+ err = au_pin(&a->pin, dentry, a->btgt, a->pin_flags);
14890+ if (unlikely(err)) {
14891+ if (parent) {
14892+ di_write_unlock(parent);
14893+ dput(parent);
14894+ }
14895+ goto out_dentry;
14896+ }
14897+ a->h_dentry = au_h_dptr(dentry, bstart);
14898+ a->h_inode = a->h_dentry->d_inode;
14899+ AuDebugOn(!a->h_inode);
14900+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14901+ if (!a->did_cpup) {
14902+ au_unpin_gp(&a->pin);
14903+ if (parent) {
14904+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14905+ di_downgrade_lock(parent, AuLock_IR);
14906+ dput(parent);
14907+ }
14908+ goto out; /* success */
14909+ }
14910+
14911+ hi_wh = NULL;
14912+ if (!d_unhashed(dentry)) {
14913+ if (parent) {
14914+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14915+ di_downgrade_lock(parent, AuLock_IR);
14916+ dput(parent);
14917+ }
14918+ err = au_sio_cpup_simple(dentry, a->btgt, sz, AuCpup_DTIME);
14919+ if (!err)
14920+ a->h_dentry = au_h_dptr(dentry, a->btgt);
14921+ } else {
14922+ hi_wh = au_hi_wh(inode, a->btgt);
14923+ if (!hi_wh) {
14924+ err = au_sio_cpup_wh(dentry, a->btgt, sz,
14925+ /*file*/NULL);
14926+ if (!err)
14927+ hi_wh = au_hi_wh(inode, a->btgt);
14928+ /* todo: revalidate hi_wh? */
14929+ }
14930+ if (parent) {
14931+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14932+ di_downgrade_lock(parent, AuLock_IR);
14933+ dput(parent);
14934+ }
14935+ if (!hi_wh)
14936+ a->h_dentry = au_h_dptr(dentry, a->btgt);
14937+ else
14938+ a->h_dentry = hi_wh; /* do not dget here */
14939+ }
14940+
14941+ mutex_unlock(&a->h_inode->i_mutex);
14942+ a->h_inode = a->h_dentry->d_inode;
14943+ AuDebugOn(!a->h_inode);
14944+ if (!err) {
14945+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14946+ au_unpin_gp(&a->pin);
14947+ goto out; /* success */
14948+ }
14949+
14950+ au_unpin(&a->pin);
14951+
14952+ out_dentry:
14953+ di_write_unlock(dentry);
14954+ out:
14955+ AuTraceErr(err);
14956+ return err;
14957+}
14958+
14959+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
14960+{
14961+ int err;
14962+ struct inode *inode;
14963+ struct super_block *sb;
14964+ __u32 events;
14965+ struct file *file;
14966+ loff_t sz;
14967+ struct au_icpup_args *a;
14968+
14969+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
14970+ inode = dentry->d_inode;
14971+ IMustLock(inode);
14972+
14973+ err = -ENOMEM;
14974+ a = kzalloc(sizeof(*a), GFP_NOFS);
14975+ if (unlikely(!a))
14976+ goto out;
14977+
14978+ file = NULL;
14979+ sb = dentry->d_sb;
14980+ si_read_lock(sb, AuLock_FLUSH);
14981+ vfsub_args_init(&a->vargs, a->ign, au_test_dlgt(au_mntflags(sb)), 0);
14982+
14983+ if (ia->ia_valid & ATTR_FILE) {
14984+ /* currently ftruncate(2) only */
14985+ file = ia->ia_file;
14986+ fi_write_lock(file);
14987+ ia->ia_file = au_h_fptr(file, au_fbstart(file));
14988+ }
14989+
14990+ sz = -1;
14991+ if ((ia->ia_valid & ATTR_SIZE)
14992+ && ia->ia_size < i_size_read(inode))
14993+ sz = ia->ia_size;
14994+ err = au_lock_and_icpup(dentry, sz, a);
14995+ if (unlikely(err < 0))
14996+ goto out_si;
14997+ if (a->did_cpup) {
14998+ ia->ia_file = NULL;
14999+ ia->ia_valid &= ~ATTR_FILE;
15000+ }
15001+
15002+ if ((ia->ia_valid & ATTR_SIZE)
15003+ && ia->ia_size < i_size_read(inode)) {
15004+ err = vmtruncate(inode, ia->ia_size);
15005+ if (unlikely(err))
15006+ goto out_unlock;
15007+ }
15008+
15009+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
15010+ ia->ia_valid &= ~ATTR_MODE;
15011+
15012+ events = 0;
15013+ if (a->hinotify) {
15014+ events = vfsub_events_notify_change(ia);
15015+ if (events) {
15016+ if (a->isdir)
15017+ vfsub_ign_hinode(&a->vargs, events,
15018+ au_hi(inode, a->btgt));
15019+ vfsub_ign_hinode(&a->vargs, events,
15020+ au_pinned_hdir(&a->pin));
15021+ }
15022+ }
15023+ err = vfsub_notify_change(a->h_dentry, ia, &a->vargs);
15024+ if (!err)
15025+ au_cpup_attr_changeable(inode);
15026+
15027+ out_unlock:
15028+ mutex_unlock(&a->h_inode->i_mutex);
15029+ au_unpin(&a->pin);
15030+ di_write_unlock(dentry);
15031+ out_si:
15032+ if (file) {
15033+ fi_write_unlock(file);
15034+ ia->ia_file = file;
15035+ ia->ia_valid |= ATTR_FILE;
15036+ }
15037+ si_read_unlock(sb);
15038+ kfree(a);
15039+ out:
15040+ AuTraceErr(err);
15041+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
15042+ err = -ESTALE;
15043+ return err;
15044+}
15045+
15046+/* ---------------------------------------------------------------------- */
15047+
15048+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
15049+ int bufsiz)
15050+{
15051+ struct super_block *sb;
15052+ struct dentry *h_dentry;
15053+
15054+ LKTRTrace("%.*s, b%d, %d\n", AuDLNPair(dentry), bindex, bufsiz);
15055+
15056+ h_dentry = au_h_dptr(dentry, bindex);
15057+ if (unlikely(/* !h_dentry
15058+ || !h_dentry->d_inode
15059+ || */
15060+ !h_dentry->d_inode->i_op
15061+ || !h_dentry->d_inode->i_op->readlink))
15062+ return -EINVAL;
15063+
15064+ sb = dentry->d_sb;
15065+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
15066+ touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
15067+ au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
15068+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
15069+ }
15070+ return h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
15071+}
15072+
15073+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
15074+{
15075+ int err;
15076+
15077+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), bufsiz);
15078+
15079+ aufs_read_lock(dentry, AuLock_IR);
15080+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
15081+ aufs_read_unlock(dentry, AuLock_IR);
15082+ AuTraceErr(err);
15083+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
15084+ err = -ESTALE;
15085+ return err;
15086+}
15087+
15088+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
15089+{
15090+ int err;
15091+ char *buf;
15092+ mm_segment_t old_fs;
15093+
15094+ LKTRTrace("%.*s, nd %.*s\n",
15095+ AuDLNPair(dentry), AuDLNPair(nd->path.dentry));
15096+
15097+ err = -ENOMEM;
15098+ buf = __getname();
15099+ if (unlikely(!buf))
15100+ goto out;
15101+
15102+ aufs_read_lock(dentry, AuLock_IR);
15103+ old_fs = get_fs();
15104+ set_fs(KERNEL_DS);
15105+ err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
15106+ PATH_MAX);
15107+ set_fs(old_fs);
15108+ aufs_read_unlock(dentry, AuLock_IR);
15109+
15110+ if (err >= 0) {
15111+ buf[err] = 0;
15112+ /* will be freed by put_link */
15113+ nd_set_link(nd, buf);
15114+ return NULL; /* success */
15115+ }
15116+ __putname(buf);
15117+
15118+ out:
15119+ path_put(&nd->path);
15120+ AuTraceErr(err);
15121+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
15122+ err = -ESTALE;
15123+ return ERR_PTR(err);
15124+}
15125+
15126+static void aufs_put_link(struct dentry *dentry, struct nameidata *nd,
15127+ void *cookie)
15128+{
15129+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
15130+ __putname(nd_get_link(nd));
15131+}
15132+
15133+/* ---------------------------------------------------------------------- */
15134+
15135+static void aufs_truncate_range(struct inode *inode, loff_t start, loff_t end)
15136+{
15137+ AuUnsupport();
15138+}
15139+
15140+/* ---------------------------------------------------------------------- */
15141+
15142+struct inode_operations aufs_symlink_iop = {
15143+ .permission = aufs_permission,
15144+ .setattr = aufs_setattr,
15145+#ifdef CONFIG_AUFS_GETATTR
15146+ .getattr = aufs_getattr,
15147+#endif
15148+
15149+ .readlink = aufs_readlink,
15150+ .follow_link = aufs_follow_link,
15151+ .put_link = aufs_put_link
15152+};
15153+
15154+struct inode_operations aufs_dir_iop = {
15155+ .create = aufs_create,
15156+ .lookup = aufs_lookup,
15157+ .link = aufs_link,
15158+ .unlink = aufs_unlink,
15159+ .symlink = aufs_symlink,
15160+ .mkdir = aufs_mkdir,
15161+ .rmdir = aufs_rmdir,
15162+ .mknod = aufs_mknod,
15163+ .rename = aufs_rename,
15164+
15165+ .permission = aufs_permission,
15166+ .setattr = aufs_setattr,
15167+#ifdef CONFIG_AUFS_GETATTR
15168+ .getattr = aufs_getattr,
15169+#endif
15170+
15171+#if 0 /* reserved for future use */
15172+ .setxattr = aufs_setxattr,
15173+ .getxattr = aufs_getxattr,
15174+ .listxattr = aufs_listxattr,
15175+ .removexattr = aufs_removexattr
15176+#endif
15177+};
15178+
15179+struct inode_operations aufs_iop = {
15180+ .permission = aufs_permission,
15181+ .setattr = aufs_setattr,
15182+#ifdef CONFIG_AUFS_GETATTR
15183+ .getattr = aufs_getattr,
15184+#endif
15185+
15186+#if 0 /* reserved for future use */
15187+ .setxattr = aufs_setxattr,
15188+ .getxattr = aufs_getxattr,
15189+ .listxattr = aufs_listxattr,
15190+ .removexattr = aufs_removexattr,
15191+#endif
15192+
15193+ .truncate_range = aufs_truncate_range
15194+};
15195diff -urN linux/fs/aufs/i_op_del.c linux-aufs/fs/aufs/i_op_del.c
15196--- linux/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
15197+++ linux-aufs/fs/aufs/i_op_del.c 2009-03-12 16:18:04.000000000 +0100
15198@@ -0,0 +1,566 @@
15199+/*
15200+ * Copyright (C) 2005-2009 Junjiro Okajima
15201+ *
15202+ * This program, aufs is free software; you can redistribute it and/or modify
15203+ * it under the terms of the GNU General Public License as published by
15204+ * the Free Software Foundation; either version 2 of the License, or
15205+ * (at your option) any later version.
15206+ *
15207+ * This program is distributed in the hope that it will be useful,
15208+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15209+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15210+ * GNU General Public License for more details.
15211+ *
15212+ * You should have received a copy of the GNU General Public License
15213+ * along with this program; if not, write to the Free Software
15214+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15215+ */
15216+
15217+/*
15218+ * inode operations (del entry)
15219+ *
15220+ * $Id$
15221+ */
15222+
15223+#include "aufs.h"
15224+
15225+/* returns,
15226+ * 0: wh is unnecessary
15227+ * plus: wh is necessary
15228+ * minus: error
15229+ */
15230+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
15231+{
15232+ int need_wh, err;
15233+ aufs_bindex_t bstart;
15234+ struct dentry *h_dentry;
15235+ struct super_block *sb;
15236+
15237+ LKTRTrace("%.*s, isdir %d, *bcpup %d\n",
15238+ AuDLNPair(dentry), isdir, *bcpup);
15239+ sb = dentry->d_sb;
15240+
15241+ bstart = au_dbstart(dentry);
15242+ LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
15243+ h_dentry = au_h_dptr(dentry, bstart);
15244+ if (*bcpup < 0) {
15245+ *bcpup = bstart;
15246+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
15247+ err = AuWbrCopyup(au_sbi(sb), dentry);
15248+ *bcpup = err;
15249+ if (unlikely(err < 0))
15250+ goto out;
15251+ }
15252+ } else
15253+ AuDebugOn(bstart < *bcpup
15254+ || au_test_ro(sb, *bcpup, dentry->d_inode));
15255+ LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
15256+
15257+ if (*bcpup != bstart) {
15258+ err = au_cpup_dirs(dentry, *bcpup);
15259+ if (unlikely(err))
15260+ goto out;
15261+ need_wh = 1;
15262+ } else {
15263+ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
15264+ old_bend = au_dbend(dentry);
15265+ if (isdir) {
15266+ bdiropq = au_dbdiropq(dentry);
15267+ au_set_dbdiropq(dentry, -1);
15268+ }
15269+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
15270+ /*nd*/NULL);
15271+ err = need_wh;
15272+ if (isdir)
15273+ au_set_dbdiropq(dentry, bdiropq);
15274+ if (unlikely(err < 0))
15275+ goto out;
15276+ new_bend = au_dbend(dentry);
15277+ if (!need_wh && old_bend != new_bend) {
15278+ au_set_h_dptr(dentry, new_bend, NULL);
15279+ au_set_dbend(dentry, old_bend);
15280+#if 0 /* todo: remove this? */
15281+ } else if (!au_h_dptr(dentry, new_bend)->d_inode) {
15282+ LKTRTrace("negative\n");
15283+ au_set_h_dptr(dentry, new_bend, NULL);
15284+ au_set_dbend(dentry, old_bend);
15285+ need_wh = 0;
15286+#endif
15287+ }
15288+ }
15289+ LKTRTrace("need_wh %d\n", need_wh);
15290+ err = need_wh;
15291+
15292+ out:
15293+ AuTraceErr(err);
15294+ return err;
15295+}
15296+
15297+/*
15298+ * simple tests for the removal inode operations.
15299+ * following the checks in vfs, plus the parent-child relationship.
15300+ */
15301+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
15302+ struct dentry *h_parent, int isdir, struct au_ndx *ndx)
15303+{
15304+ int err, exist;
15305+ struct super_block *sb;
15306+ struct dentry *h_dentry;
15307+ struct inode *h_inode;
15308+ umode_t h_mode;
15309+
15310+ LKTRTrace("%.*s/%.*s, b%d, dir %d\n",
15311+ AuDLNPair(h_parent), AuDLNPair(dentry), bindex, isdir);
15312+
15313+ sb = dentry->d_sb;
15314+ exist = !!dentry->d_inode;
15315+ h_dentry = au_h_dptr(dentry, bindex);
15316+ h_inode = h_dentry->d_inode;
15317+ if (exist) {
15318+ err = -ENOENT;
15319+ if (unlikely(!h_inode || !h_inode->i_nlink))
15320+ goto out;
15321+
15322+ h_mode = h_inode->i_mode;
15323+ if (!isdir) {
15324+ err = -EISDIR;
15325+ if (unlikely(S_ISDIR(h_mode)))
15326+ goto out;
15327+ } else if (unlikely(!S_ISDIR(h_mode))) {
15328+ err = -ENOTDIR;
15329+ goto out;
15330+ }
15331+ } else {
15332+ /* rename(2) case */
15333+ err = -EIO;
15334+ if (unlikely(h_inode))
15335+ goto out;
15336+ }
15337+
15338+ err = -ENOENT;
15339+ /* expected parent dir is locked */
15340+ if (unlikely(h_parent != h_dentry->d_parent))
15341+ goto out;
15342+ err = 0;
15343+
15344+ /*
15345+ * some filesystem may unlink a dir and corrupt its consistency.
15346+ * so let's try heavy test.
15347+ */
15348+ if (1 /*au_opt_test(au_mntflags(sb), UDBA_INOTIFY)*/) {
15349+ struct dentry *h_latest;
15350+ struct qstr *qstr = &dentry->d_name;
15351+
15352+ err = -EACCES;
15353+ if (unlikely(au_test_h_perm(h_parent->d_inode,
15354+ MAY_EXEC | MAY_WRITE,
15355+ au_ftest_ndx(ndx->flags, DLGT))))
15356+ goto out;
15357+
15358+ h_latest = au_sio_lkup_one(qstr->name, h_parent, qstr->len,
15359+ ndx);
15360+ err = -EIO;
15361+ if (IS_ERR(h_latest))
15362+ goto out;
15363+ dput(h_latest);
15364+ if (h_latest == h_dentry)
15365+ err = 0;
15366+ }
15367+
15368+ out:
15369+ AuTraceErr(err);
15370+ return err;
15371+}
15372+
15373+static struct dentry *
15374+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
15375+ struct au_dtime *dt, struct au_pin *pin)
15376+{
15377+ struct dentry *wh_dentry, *h_parent;
15378+ struct super_block *sb;
15379+ int err, need_wh;
15380+ unsigned int mnt_flags;
15381+ unsigned char pin_flags;
15382+ aufs_bindex_t bcpup;
15383+ struct au_ndx ndx;
15384+
15385+ LKTRTrace("%.*s, isdir %d\n", AuDLNPair(dentry), isdir);
15386+
15387+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
15388+ err = need_wh;
15389+ wh_dentry = ERR_PTR(err);
15390+ if (unlikely(err < 0))
15391+ goto out;
15392+
15393+ sb = dentry->d_sb;
15394+ mnt_flags = au_mntflags(sb);
15395+ bcpup = *rbcpup;
15396+ pin_flags = AuPin_DI_LOCKED | AuPin_MNT_WRITE;
15397+ if (au_opt_test(mnt_flags, UDBA_INOTIFY))
15398+ au_fset_pin(pin_flags, DO_GPARENT);
15399+ err = au_pin(pin, dentry, bcpup, pin_flags);
15400+ wh_dentry = ERR_PTR(err);
15401+ if (unlikely(err))
15402+ goto out;
15403+ h_parent = au_pinned_h_parent(pin);
15404+ if (!au_opt_test(mnt_flags, UDBA_NONE) && au_dbstart(dentry) == bcpup) {
15405+ ndx.nfsmnt = au_nfsmnt(sb, bcpup);
15406+ ndx.flags = 0;
15407+ if (au_test_dlgt(mnt_flags))
15408+ au_fset_ndx(ndx.flags, DLGT);
15409+ ndx.nd = NULL;
15410+ /* ndx.br = au_sbr(sb, bcpup); */
15411+ /* ndx.nd_file = NULL; */
15412+ err = au_may_del(dentry, bcpup, h_parent, isdir, &ndx);
15413+ wh_dentry = ERR_PTR(err);
15414+ if (unlikely(err))
15415+ goto out_unpin;
15416+ }
15417+
15418+ au_dtime_store(dt, au_pinned_parent(pin), h_parent, au_pinned_hdir(pin),
15419+ au_pinned_hgdir(pin));
15420+ wh_dentry = NULL;
15421+ if (!need_wh)
15422+ goto out; /* success, no need to create whiteout */
15423+
15424+ ndx.nfsmnt = au_nfsmnt(sb, bcpup);
15425+ ndx.flags = 0;
15426+ if (au_test_dlgt(mnt_flags))
15427+ au_fset_ndx(ndx.flags, DLGT);
15428+ ndx.nd = NULL;
15429+ /* ndx.br = NULL; */
15430+ wh_dentry = au_wh_create(dentry, bcpup, h_parent, &ndx);
15431+ if (!IS_ERR(wh_dentry))
15432+ goto out; /* success */
15433+ /* returns with the parent is locked and wh_dentry is DGETed */
15434+
15435+ out_unpin:
15436+ au_unpin(pin);
15437+ out:
15438+ AuTraceErrPtr(wh_dentry);
15439+ return wh_dentry;
15440+}
15441+
15442+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
15443+ struct au_nhash *whlist, struct inode *dir)
15444+{
15445+ int rmdir_later, err;
15446+ struct dentry *h_dentry;
15447+ struct inode *inode, *h_inode;
15448+ struct super_block *sb;
15449+
15450+ LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex);
15451+
15452+ inode = NULL;
15453+ h_inode = NULL;
15454+ sb = dentry->d_sb;
15455+ if (au_opt_test(au_mntflags(sb), UDBA_INOTIFY)) {
15456+ inode = dentry->d_inode;
15457+ h_inode = au_h_iptr(inode, bindex);
15458+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
15459+ }
15460+ h_dentry = au_h_dptr(dentry, bindex);
15461+ err = au_whtmp_ren(dir, bindex, h_dentry);
15462+ if (inode) {
15463+ /* todo: bad approach? */
15464+ if (!err)
15465+ au_hin_suspend(au_hi(inode, bindex));
15466+ mutex_unlock(&h_inode->i_mutex);
15467+ }
15468+ if (unlikely(err))
15469+ goto out;
15470+
15471+ if (!au_test_nfs(h_dentry->d_sb)) {
15472+ const int dirwh = au_sbi(sb)->si_dirwh;
15473+ rmdir_later = (dirwh <= 1);
15474+ if (!rmdir_later)
15475+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
15476+ dirwh);
15477+ if (rmdir_later)
15478+ return rmdir_later;
15479+ }
15480+
15481+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
15482+ if (unlikely(err)) {
15483+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
15484+ AuDLNPair(h_dentry), bindex, err);
15485+ /* we do not revert the inotify watch */
15486+ err = 0;
15487+ }
15488+
15489+ out:
15490+ AuTraceErr(err);
15491+ return err;
15492+}
15493+
15494+static void epilog(struct inode *dir, struct dentry *dentry,
15495+ aufs_bindex_t bindex)
15496+{
15497+ /* todo: unnecessary? */
15498+ d_drop(dentry);
15499+ dentry->d_inode->i_ctime = dir->i_ctime;
15500+
15501+ if (atomic_read(&dentry->d_count) == 1) {
15502+ au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
15503+ au_update_dbstart(dentry);
15504+ }
15505+ if (au_ibstart(dir) == bindex)
15506+ au_cpup_attr_timesizes(dir);
15507+ dir->i_version++;
15508+}
15509+
15510+/* revert flags */
15511+#define AuRev_DLGT 1
15512+#define au_ftest_rev(flags, name) ((flags) & AuRev_##name)
15513+#define au_fset_rev(flags, name) { (flags) |= AuRev_##name; }
15514+#define au_fclr_rev(flags, name) { (flags) &= ~AuRev_##name; }
15515+#ifndef CONFIG_AUFS_DLGT
15516+#undef AuRev_DLGT
15517+#define AuRev_DLGT 0
15518+#endif
15519+
15520+static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
15521+ struct dentry *wh_dentry, struct dentry *dentry,
15522+ struct au_dtime *dt, unsigned int flags)
15523+{
15524+ int rerr;
15525+
15526+ rerr = au_wh_unlink_dentry(au_hi(dir, bwh), wh_dentry, dentry,
15527+ au_ftest_rev(flags, DLGT));
15528+ if (!rerr) {
15529+ au_set_dbwh(dentry, bwh);
15530+ au_dtime_revert(dt);
15531+ return 0;
15532+ }
15533+
15534+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15535+ AuDLNPair(dentry), err, rerr);
15536+ return -EIO;
15537+}
15538+
15539+/* ---------------------------------------------------------------------- */
15540+
15541+int aufs_unlink(struct inode *dir, struct dentry *dentry)
15542+{
15543+ int err;
15544+ struct inode *inode, *h_dir;
15545+ struct dentry *parent, *wh_dentry, *h_dentry;
15546+ struct au_dtime dt;
15547+ aufs_bindex_t bwh, bindex, bstart;
15548+ unsigned char dlgt;
15549+ struct super_block *sb;
15550+ struct au_hin_ignore ign;
15551+ struct vfsub_args vargs;
15552+ struct au_pin pin;
15553+
15554+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
15555+ IMustLock(dir);
15556+ inode = dentry->d_inode;
15557+ if (unlikely(!inode))
15558+ return -ENOENT; /* possible? */
15559+ IMustLock(inode);
15560+
15561+ aufs_read_lock(dentry, AuLock_DW);
15562+ parent = dentry->d_parent; /* dir inode is locked */
15563+ di_write_lock_parent(parent);
15564+
15565+ bstart = au_dbstart(dentry);
15566+ bwh = au_dbwh(dentry);
15567+ bindex = -1;
15568+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
15569+ err = PTR_ERR(wh_dentry);
15570+ if (IS_ERR(wh_dentry))
15571+ goto out;
15572+
15573+ sb = dir->i_sb;
15574+ dlgt = !!au_test_dlgt(au_mntflags(sb));
15575+ AuDebugOn(au_dbstart(dentry) != bstart);
15576+ h_dentry = au_h_dptr(dentry, bstart);
15577+ dget(h_dentry);
15578+
15579+ if (bindex == bstart) {
15580+ vfsub_args_init(&vargs, &ign, dlgt, 0);
15581+ vfsub_ign_hinode(&vargs, IN_DELETE, au_pinned_hdir(&pin));
15582+ h_dir = au_pinned_h_dir(&pin);
15583+ err = vfsub_unlink(h_dir, h_dentry, &vargs);
15584+ } else {
15585+ /* dir inode is locked */
15586+ AuDebugOn(!wh_dentry
15587+ || wh_dentry->d_parent != au_h_dptr(parent, bindex));
15588+ h_dir = wh_dentry->d_parent->d_inode;
15589+ IMustLock(h_dir);
15590+ err = 0;
15591+ }
15592+
15593+ if (!err) {
15594+ drop_nlink(inode);
15595+#if 0 /* todo: update plink? */
15596+ if (!inode->i_nlink
15597+ && au_opt_test(p->a.mnt_flags, PLINK)
15598+ && au_plink_test(sb, inode)
15599+ /* && atomic_read(&inode->i_count) == 2) */) {
15600+ au_debug_on();
15601+ DbgInode(inode);
15602+ au_debug_off();
15603+ }
15604+#endif
15605+ /*
15606+ * although this is not a dir,
15607+ * set it here since we need to detect the dead inode.
15608+ */
15609+ if (!inode->i_nlink)
15610+ inode->i_flags |= S_DEAD;
15611+ epilog(dir, dentry, bindex);
15612+
15613+ /* update target timestamps */
15614+ if (bindex == bstart) {
15615+ au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
15616+ inode->i_ctime = h_dentry->d_inode->i_ctime;
15617+ } else
15618+ /* todo: this timestamp may be reverted later */
15619+ inode->i_ctime = h_dir->i_ctime;
15620+ goto out_unlock; /* success */
15621+ }
15622+
15623+ /* revert */
15624+ if (wh_dentry) {
15625+ int rerr;
15626+ unsigned int rev_flags;
15627+
15628+ rev_flags = 0;
15629+ if (dlgt)
15630+ au_fset_rev(rev_flags, DLGT);
15631+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt,
15632+ rev_flags);
15633+ if (rerr)
15634+ err = rerr;
15635+ }
15636+
15637+ out_unlock:
15638+ au_unpin(&pin);
15639+ dput(wh_dentry);
15640+ dput(h_dentry);
15641+ out:
15642+ di_write_unlock(parent);
15643+ aufs_read_unlock(dentry, AuLock_DW);
15644+ AuTraceErr(err);
15645+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
15646+ err = -ESTALE;
15647+ return err;
15648+}
15649+
15650+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
15651+{
15652+ int err, rmdir_later;
15653+ struct inode *inode;
15654+ struct dentry *parent, *wh_dentry, *h_dentry;
15655+ struct au_dtime dt;
15656+ aufs_bindex_t bwh, bindex, bstart;
15657+ struct au_whtmp_rmdir_args *args;
15658+ struct au_nhash *whlist;
15659+ struct super_block *sb;
15660+ unsigned int mnt_flags;
15661+ struct au_pin pin;
15662+
15663+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
15664+ IMustLock(dir);
15665+ inode = dentry->d_inode;
15666+ err = -ENOENT; /* possible? */
15667+ if (unlikely(!inode))
15668+ goto out;
15669+ IMustLock(inode);
15670+
15671+ whlist = au_nhash_new(GFP_NOFS);
15672+ err = PTR_ERR(whlist);
15673+ if (IS_ERR(whlist))
15674+ goto out;
15675+
15676+ err = -ENOMEM;
15677+ args = kmalloc(sizeof(*args), GFP_NOFS);
15678+ if (unlikely(!args))
15679+ goto out_whlist;
15680+
15681+ aufs_read_lock(dentry, AuLock_DW);
15682+ parent = dentry->d_parent; /* dir inode is locked */
15683+ di_write_lock_parent(parent);
15684+ err = au_test_empty(dentry, whlist);
15685+ if (unlikely(err))
15686+ goto out_args;
15687+
15688+ bstart = au_dbstart(dentry);
15689+ bwh = au_dbwh(dentry);
15690+ bindex = -1;
15691+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
15692+ err = PTR_ERR(wh_dentry);
15693+ if (IS_ERR(wh_dentry))
15694+ goto out_args;
15695+
15696+ AuDebugOn(au_dbstart(dentry) != bstart);
15697+ h_dentry = au_h_dptr(dentry, bstart);
15698+ dget(h_dentry);
15699+
15700+ rmdir_later = 0;
15701+ if (bindex == bstart) {
15702+ err = renwh_and_rmdir(dentry, bstart, whlist, dir);
15703+ if (err > 0) {
15704+ rmdir_later = err;
15705+ err = 0;
15706+ }
15707+ } else {
15708+ /* dir inode is locked */
15709+ AuDebugOn(!wh_dentry
15710+ || wh_dentry->d_parent != au_h_dptr(parent, bindex));
15711+ IMustLock(wh_dentry->d_parent->d_inode);
15712+ err = 0;
15713+ }
15714+
15715+ sb = dentry->d_sb;
15716+ mnt_flags = au_mntflags(sb);
15717+ if (!err) {
15718+ if (au_opt_test(mnt_flags, UDBA_INOTIFY) && rmdir_later)
15719+ au_reset_hinotify(inode, /*flags*/0);
15720+ clear_nlink(inode);
15721+ inode->i_flags |= S_DEAD;
15722+ au_set_dbdiropq(dentry, -1);
15723+ epilog(dir, dentry, bindex);
15724+
15725+ if (rmdir_later) {
15726+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, whlist,
15727+ args);
15728+ args = NULL;
15729+ }
15730+
15731+ goto out_unlock; /* success */
15732+ }
15733+
15734+ /* revert */
15735+ LKTRLabel(revert);
15736+ if (wh_dentry) {
15737+ int rerr;
15738+ unsigned int rev_flags;
15739+
15740+ rev_flags = 0;
15741+ if (au_test_dlgt(mnt_flags))
15742+ au_fset_rev(rev_flags, DLGT);
15743+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt,
15744+ rev_flags);
15745+ if (rerr)
15746+ err = rerr;
15747+ }
15748+
15749+ out_unlock:
15750+ au_unpin(&pin);
15751+ dput(wh_dentry);
15752+ dput(h_dentry);
15753+ out_args:
15754+ di_write_unlock(parent);
15755+ aufs_read_unlock(dentry, AuLock_DW);
15756+ kfree(args);
15757+ out_whlist:
15758+ au_nhash_del(whlist);
15759+ out:
15760+ AuTraceErr(err);
15761+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
15762+ err = -ESTALE;
15763+ return err;
15764+}
15765diff -urN linux/fs/aufs/i_op_ren.c linux-aufs/fs/aufs/i_op_ren.c
15766--- linux/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
15767+++ linux-aufs/fs/aufs/i_op_ren.c 2009-03-12 16:18:04.000000000 +0100
15768@@ -0,0 +1,1261 @@
15769+/*
15770+ * Copyright (C) 2005-2009 Junjiro Okajima
15771+ *
15772+ * This program, aufs is free software; you can redistribute it and/or modify
15773+ * it under the terms of the GNU General Public License as published by
15774+ * the Free Software Foundation; either version 2 of the License, or
15775+ * (at your option) any later version.
15776+ *
15777+ * This program is distributed in the hope that it will be useful,
15778+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15779+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15780+ * GNU General Public License for more details.
15781+ *
15782+ * You should have received a copy of the GNU General Public License
15783+ * along with this program; if not, write to the Free Software
15784+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15785+ */
15786+
15787+/*
15788+ * inode operation (rename entry)
15789+ * todo: this is crazy monster
15790+ *
15791+ * $Id$
15792+ */
15793+
15794+#include "aufs.h"
15795+
15796+enum { SRC, DST };
15797+
15798+#define AuRen_ISDIR 1
15799+#define AuRen_ISSAMEDIR (1 << 1)
15800+#define AuRen_WHSRC (1 << 2)
15801+#define AuRen_WHDST (1 << 3)
15802+#define AuRen_DLGT (1 << 4)
15803+#define AuRen_VFSLOCK (1 << 5)
15804+#define AuRen_PINNED (1 << 6)
15805+#define AuRen_MNT_WRITE (1 << 7)
15806+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
15807+#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
15808+#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
15809+#ifndef CONFIG_AUFS_DLGT
15810+#undef AuRen_DLGT
15811+#define AuRen_DLGT 0
15812+#endif
15813+
15814+struct au_ren_args {
15815+ /* original args */
15816+ struct dentry *src_dentry, *dentry;
15817+ struct inode *src_dir, *dir;
15818+
15819+ struct dentry *h_dentry[2], *h_parent[2], *h_trap, *h_locked[2];
15820+ /* todo: remove them */
15821+ struct dentry *parent[2], *gparent[2];
15822+ struct au_pin pin[2];
15823+ struct au_nhash whlist;
15824+ aufs_bindex_t btgt, bstart[2];
15825+ /* do_rename() only */
15826+ unsigned char need_diropq, bycpup;
15827+ struct super_block *sb;
15828+ unsigned int flags;
15829+ unsigned int mnt_flags;
15830+ struct au_ndx ndx;
15831+
15832+ /* do_rename() only */
15833+#ifdef CONFIG_AUFS_BR_NFS
15834+ struct au_hin_ignore ign[3];
15835+#else
15836+ struct au_hin_ignore ign[2];
15837+#endif
15838+ struct vfsub_args vargs;
15839+ struct au_whtmp_rmdir_args *thargs;
15840+ struct dentry *wh_dentry[2], *h_dst, *h_src;
15841+};
15842+
15843+/* ---------------------------------------------------------------------- */
15844+
15845+#define RevertFailure(fmt, args...) do { \
15846+ AuIOErrWhck("revert failure: " fmt " (%d, %d)\n", \
15847+ ##args, err, rerr); \
15848+ err = -EIO; \
15849+ } while (0)
15850+
15851+static noinline_for_stack
15852+void au_ren_rev_diropq(int err, struct au_ren_args *a)
15853+{
15854+ int rerr;
15855+ struct mutex *h_mtx;
15856+
15857+ /* lock inode simply since inotify is not set to h_inode. */
15858+ h_mtx = &au_h_dptr(a->src_dentry, a->btgt)->d_inode->i_mutex;
15859+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15860+ rerr = au_diropq_remove(a->src_dentry, a->btgt,
15861+ au_ftest_ren(a->flags, DLGT));
15862+ mutex_unlock(h_mtx);
15863+ if (rerr)
15864+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
15865+}
15866+
15867+static noinline_for_stack
15868+void au_ren_rev_rename(int err, struct au_ren_args *a)
15869+{
15870+ int rerr;
15871+ struct dentry *h_d;
15872+ struct qstr *name = &a->src_dentry->d_name;
15873+
15874+ h_d = au_lkup_one(name->name, a->h_parent[SRC], name->len, &a->ndx);
15875+ rerr = PTR_ERR(h_d);
15876+ if (IS_ERR(h_d)) {
15877+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
15878+ return;
15879+ }
15880+
15881+ AuDebugOn(h_d->d_inode);
15882+ vfsub_args_reinit(&a->vargs);
15883+ vfsub_ign_hinode(&a->vargs, IN_MOVED_FROM,
15884+ au_pinned_hdir(a->pin + DST));
15885+ vfsub_ign_hinode(&a->vargs, IN_MOVED_TO, au_pinned_hdir(a->pin + SRC));
15886+ rerr = vfsub_rename(au_pinned_h_dir(a->pin + DST),
15887+ au_h_dptr(a->src_dentry, a->btgt),
15888+ au_pinned_h_dir(a->pin + SRC), h_d, &a->vargs);
15889+ d_drop(h_d);
15890+ dput(h_d);
15891+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
15892+ if (rerr)
15893+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
15894+}
15895+
15896+static noinline_for_stack
15897+void au_ren_rev_cpup(int err, struct au_ren_args *a)
15898+{
15899+ int rerr;
15900+
15901+ vfsub_args_reinit(&a->vargs);
15902+ vfsub_ign_hinode(&a->vargs, IN_DELETE, au_pinned_hdir(a->pin + DST));
15903+ rerr = vfsub_unlink(au_pinned_h_dir(a->pin + DST), a->h_dentry[DST],
15904+ &a->vargs);
15905+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
15906+ au_set_dbstart(a->src_dentry, a->bstart[SRC]);
15907+ if (rerr)
15908+ RevertFailure("unlink %.*s", AuDLNPair(a->h_dentry[DST]));
15909+}
15910+
15911+static noinline_for_stack
15912+void au_ren_rev_whtmp(int err, struct au_ren_args *a)
15913+{
15914+ int rerr;
15915+ struct dentry *h_d;
15916+ struct mutex *h_mtx;
15917+ struct qstr *name = &a->dentry->d_name;
15918+
15919+ h_d = au_lkup_one(name->name, a->h_parent[DST], name->len, &a->ndx);
15920+ rerr = PTR_ERR(h_d);
15921+ if (IS_ERR(h_d)) {
15922+ RevertFailure("lookup %.*s", AuLNPair(name));
15923+ return;
15924+ }
15925+ if (h_d->d_inode) {
15926+ d_drop(h_d);
15927+ dput(h_d);
15928+ return;
15929+ }
15930+
15931+ h_mtx = &a->h_dst->d_inode->i_mutex;
15932+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15933+ au_hin_resume(au_hi(a->src_dentry->d_inode, a->btgt));
15934+ mutex_unlock(h_mtx);
15935+ vfsub_args_reinit(&a->vargs);
15936+ vfsub_ign_hinode(&a->vargs, IN_MOVED_TO | IN_MOVED_FROM,
15937+ au_pinned_hdir(a->pin + DST));
15938+ rerr = vfsub_rename(au_pinned_h_dir(a->pin + DST), a->h_dst,
15939+ au_pinned_h_dir(a->pin + DST), h_d, &a->vargs);
15940+ d_drop(h_d);
15941+ dput(h_d);
15942+ if (!rerr) {
15943+ au_set_h_dptr(a->dentry, a->btgt, NULL);
15944+ au_set_h_dptr(a->dentry, a->btgt, dget(a->h_dst));
15945+ } else
15946+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
15947+}
15948+
15949+static noinline_for_stack
15950+void au_ren_rev_whsrc(int err, struct au_ren_args *a)
15951+{
15952+ int rerr;
15953+
15954+ rerr = au_wh_unlink_dentry(au_pinned_hdir(a->pin + SRC),
15955+ a->wh_dentry[SRC], a->src_dentry, /*dlgt*/0);
15956+ if (rerr)
15957+ RevertFailure("unlink %.*s", AuDLNPair(a->wh_dentry[SRC]));
15958+}
15959+#undef RevertFailure
15960+
15961+/* ---------------------------------------------------------------------- */
15962+
15963+static /* noinline_for_stack */
15964+int au_ren_or_cpup(struct au_ren_args *a)
15965+{
15966+ int err;
15967+
15968+ AuTraceEnter();
15969+
15970+ if (au_dbstart(a->src_dentry) == a->btgt) {
15971+ if (a->need_diropq && au_dbdiropq(a->src_dentry) == a->btgt)
15972+ a->need_diropq = 0;
15973+ vfsub_ign_hinode(&a->vargs, IN_MOVED_FROM,
15974+ au_pinned_hdir(a->pin + SRC));
15975+ vfsub_ign_hinode(&a->vargs, IN_MOVED_TO,
15976+ au_pinned_hdir(a->pin + DST));
15977+ /* nfs_rename() calls d_delete() */
15978+ if (au_test_nfs(au_pinned_h_dir(a->pin + DST)->i_sb)
15979+ && a->h_dentry[DST]->d_inode
15980+ && (S_ISDIR(a->h_dentry[DST]->d_inode->i_mode)
15981+ || atomic_read(&a->h_dentry[DST]->d_count) <= 2))
15982+ vfsub_ign_hinode(&a->vargs, IN_DELETE,
15983+ au_pinned_hdir(a->pin + DST));
15984+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
15985+ err = vfsub_rename(au_pinned_h_dir(a->pin + SRC),
15986+ au_h_dptr(a->src_dentry, a->btgt),
15987+ au_pinned_h_dir(a->pin + DST),
15988+ a->h_dentry[DST], &a->vargs);
15989+ } else {
15990+ struct mutex *h_mtx = &a->h_dentry[SRC]->d_inode->i_mutex;
15991+
15992+ a->bycpup = 1;
15993+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15994+ au_set_dbstart(a->src_dentry, a->btgt);
15995+ au_set_h_dptr(a->src_dentry, a->btgt, dget(a->h_dentry[DST]));
15996+ err = au_sio_cpup_single(a->src_dentry, a->btgt, a->bstart[SRC],
15997+ -1, !AuCpup_DTIME, a->parent[DST]);
15998+ if (unlikely(err)) {
15999+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
16000+ au_set_dbstart(a->src_dentry, a->bstart[SRC]);
16001+ }
16002+ mutex_unlock(h_mtx);
16003+ }
16004+
16005+ return err;
16006+}
16007+
16008+static /* noinline_for_stack */
16009+int au_ren_del_whtmp(struct au_ren_args *a)
16010+{
16011+ int err;
16012+
16013+ AuTraceEnter();
16014+
16015+ if (au_test_nfs(a->h_dst->d_sb)
16016+ || !au_nhash_test_longer_wh(&a->whlist, a->btgt,
16017+ au_sbi(a->sb)->si_dirwh)) {
16018+ err = au_whtmp_rmdir(a->dir, a->btgt, a->h_dst, &a->whlist);
16019+ if (unlikely(err))
16020+ AuWarn("failed removing whtmp dir %.*s (%d), "
16021+ "ignored.\n", AuDLNPair(a->h_dst), err);
16022+ } else {
16023+ au_whtmp_kick_rmdir(a->dir, a->btgt, a->h_dst, &a->whlist,
16024+ a->thargs);
16025+ dput(a->h_dst);
16026+ a->thargs = NULL;
16027+ }
16028+
16029+ return 0;
16030+}
16031+
16032+static /* noinline_for_stack */
16033+int au_ren_diropq(struct au_ren_args *a)
16034+{
16035+ int err;
16036+ struct dentry *diropq;
16037+ struct mutex *h_mtx;
16038+
16039+ AuTraceEnter();
16040+
16041+ err = 0;
16042+ h_mtx = &au_h_dptr(a->src_dentry, a->btgt)->d_inode->i_mutex;
16043+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16044+ diropq = au_diropq_create(a->src_dentry, a->btgt,
16045+ au_ftest_ren(a->flags, DLGT));
16046+ mutex_unlock(h_mtx);
16047+ if (IS_ERR(diropq))
16048+ err = PTR_ERR(diropq);
16049+ dput(diropq);
16050+
16051+ return err;
16052+}
16053+
16054+static /* noinline_for_stack */
16055+int do_rename(struct au_ren_args *a)
16056+{
16057+ int err;
16058+ aufs_bindex_t bindex, bend;
16059+ struct dentry *h_d;
16060+
16061+ LKTRTrace("%.*s/%.*s, %.*s/%.*s, "
16062+ "hd{%p, %p}, hp{%p, %p}, wh %p, btgt %d, bstart{%d, %d}, "
16063+ "flags 0x%x\n",
16064+ AuDLNPair(a->parent[SRC]), AuDLNPair(a->src_dentry),
16065+ AuDLNPair(a->parent[DST]), AuDLNPair(a->dentry),
16066+ a->h_dentry[SRC], a->h_dentry[DST],
16067+ a->h_parent[SRC], a->h_parent[DST],
16068+ &a->whlist, a->btgt,
16069+ a->bstart[SRC], a->bstart[DST],
16070+ a->flags);
16071+
16072+ /* prepare workqueue args */
16073+ if (au_ftest_ren(a->flags, ISDIR) && a->h_dentry[DST]->d_inode) {
16074+ err = -ENOMEM;
16075+ a->thargs = kmalloc(sizeof(*a->thargs), GFP_NOFS);
16076+ if (unlikely(!a->thargs))
16077+ goto out;
16078+ a->h_dst = dget(a->h_dentry[DST]);
16079+ }
16080+
16081+ a->ndx.nfsmnt = au_nfsmnt(a->sb, a->btgt);
16082+ if (au_ftest_ren(a->flags, DLGT))
16083+ au_fset_ndx(a->ndx.flags, DLGT);
16084+
16085+ /* create whiteout for src_dentry */
16086+ if (au_ftest_ren(a->flags, WHSRC)) {
16087+ a->wh_dentry[SRC] = au_wh_create(a->src_dentry, a->btgt,
16088+ a->h_parent[SRC], &a->ndx);
16089+ err = PTR_ERR(a->wh_dentry[SRC]);
16090+ if (IS_ERR(a->wh_dentry[SRC]))
16091+ goto out_thargs;
16092+ }
16093+
16094+ /* lookup whiteout for dentry */
16095+ if (au_ftest_ren(a->flags, WHDST)) {
16096+ h_d = au_wh_lkup(a->h_parent[DST], &a->dentry->d_name, &a->ndx);
16097+ err = PTR_ERR(h_d);
16098+ if (IS_ERR(h_d))
16099+ goto out_whsrc;
16100+ if (!h_d->d_inode)
16101+ dput(h_d);
16102+ else
16103+ a->wh_dentry[DST] = h_d;
16104+ }
16105+
16106+ /* rename dentry to tmpwh */
16107+ if (a->thargs) {
16108+ struct au_hinode *hinode;
16109+
16110+ AuDbgDentry(a->h_dentry[DST]);
16111+ err = au_whtmp_ren(a->dir, a->btgt, a->h_dentry[DST]);
16112+ if (unlikely(err))
16113+ goto out_whdst;
16114+ AuDbgDentry(a->h_dentry[DST]);
16115+ hinode = au_hi(a->dentry->d_inode, a->btgt);
16116+ /* todo: bad approach? */
16117+ mutex_lock_nested(&hinode->hi_inode->i_mutex, AuLsc_I_CHILD);
16118+ au_hin_suspend(hinode);
16119+ mutex_unlock(&hinode->hi_inode->i_mutex);
16120+ au_set_h_dptr(a->dentry, a->btgt, NULL);
16121+ AuDbgDentry(a->h_dentry[DST]);
16122+ err = au_lkup_neg(a->dentry, a->btgt);
16123+ if (unlikely(err))
16124+ goto out_whtmp;
16125+ a->h_dentry[DST] = au_h_dptr(a->dentry, a->btgt);
16126+ }
16127+
16128+ /* cpup src */
16129+ if (a->h_dentry[DST]->d_inode && a->bstart[SRC] != a->btgt) {
16130+ struct mutex *h_mtx = &a->h_dentry[SRC]->d_inode->i_mutex;
16131+
16132+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16133+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
16134+ !AuCpup_DTIME);
16135+ mutex_unlock(h_mtx);
16136+ if (unlikely(err))
16137+ goto out_whtmp;
16138+ }
16139+
16140+ /* rename by vfs_rename or cpup */
16141+ a->need_diropq = au_ftest_ren(a->flags, ISDIR)
16142+ && (a->wh_dentry[DST]
16143+ || au_dbdiropq(a->dentry) == a->btgt
16144+ /* hide the lower to keep xino */
16145+ || a->btgt < au_dbend(a->dentry)
16146+ || au_opt_test(a->mnt_flags, ALWAYS_DIROPQ));
16147+ a->bycpup = 0;
16148+ vfsub_args_init(&a->vargs, a->ign, au_ftest_ren(a->flags, DLGT), 0);
16149+ err = au_ren_or_cpup(a);
16150+ if (unlikely(err))
16151+ goto out_whtmp;
16152+
16153+ /* make dir opaque */
16154+ if (a->need_diropq) {
16155+ err = au_ren_diropq(a);
16156+ if (unlikely(err))
16157+ goto out_rename;
16158+ }
16159+
16160+ /* update target timestamps */
16161+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
16162+ a->h_src = au_h_dptr(a->src_dentry, a->btgt);
16163+ au_update_fuse_h_inode(NULL, a->h_src); /*ignore*/
16164+ /*
16165+ * fsstack_copy_attr_atime(a->src_dentry->d_inode, a->h_src->d_inode);
16166+ */
16167+ a->src_dentry->d_inode->i_ctime = a->h_src->d_inode->i_ctime;
16168+
16169+ /* remove whiteout for dentry */
16170+ if (a->wh_dentry[DST]) {
16171+ err = au_wh_unlink_dentry(au_pinned_hdir(a->pin + DST),
16172+ a->wh_dentry[DST], a->dentry,
16173+ /*dlgt*/0);
16174+ if (unlikely(err))
16175+ goto out_diropq;
16176+ }
16177+
16178+ /* remove whtmp */
16179+ if (a->thargs)
16180+ /* ignore this error */
16181+ au_ren_del_whtmp(a);
16182+
16183+ err = 0;
16184+ goto out_success;
16185+
16186+ out_diropq:
16187+ if (a->need_diropq)
16188+ au_ren_rev_diropq(err, a);
16189+ out_rename:
16190+ if (!a->bycpup)
16191+ au_ren_rev_rename(err, a);
16192+ else
16193+ au_ren_rev_cpup(err, a);
16194+ out_whtmp:
16195+ if (a->thargs)
16196+ au_ren_rev_whtmp(err, a);
16197+ out_whdst:
16198+ dput(a->wh_dentry[DST]);
16199+ a->wh_dentry[DST] = NULL;
16200+ out_whsrc:
16201+ if (a->wh_dentry[SRC])
16202+ au_ren_rev_whsrc(err, a);
16203+ d_drop(a->src_dentry);
16204+ bend = au_dbend(a->src_dentry);
16205+ for (bindex = au_dbstart(a->src_dentry); bindex <= bend; bindex++) {
16206+ h_d = au_h_dptr(a->src_dentry, bindex);
16207+ if (h_d)
16208+ d_drop(h_d);
16209+ }
16210+ d_drop(a->dentry);
16211+ bend = au_dbend(a->dentry);
16212+ for (bindex = au_dbstart(a->dentry); bindex <= bend; bindex++) {
16213+ h_d = au_h_dptr(a->dentry, bindex);
16214+ if (h_d)
16215+ d_drop(h_d);
16216+ }
16217+ au_update_dbstart(a->dentry);
16218+ if (a->thargs)
16219+ d_drop(a->h_dst);
16220+ out_success:
16221+ dput(a->wh_dentry[SRC]);
16222+ dput(a->wh_dentry[DST]);
16223+ out_thargs:
16224+ if (a->thargs) {
16225+ dput(a->h_dst);
16226+ kfree(a->thargs);
16227+ }
16228+ out:
16229+ AuTraceErr(err);
16230+ return err;
16231+}
16232+
16233+/*
16234+ * test if @dentry dir can be rename destination or not.
16235+ * success means, it is a logically empty dir.
16236+ */
16237+static int may_rename_dstdir(struct dentry *dentry, aufs_bindex_t btgt,
16238+ struct au_nhash *whlist)
16239+{
16240+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
16241+
16242+ return au_test_empty(dentry, whlist);
16243+}
16244+
16245+/*
16246+ * test if @dentry dir can be rename source or not.
16247+ * if it can, return 0 and @children is filled.
16248+ * success means,
16249+ * - or, it is a logically empty dir.
16250+ * - or, it exists on writable branch and has no children including whiteouts
16251+ * on the lower branch.
16252+ */
16253+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
16254+{
16255+ int err;
16256+ aufs_bindex_t bstart;
16257+
16258+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
16259+
16260+ bstart = au_dbstart(dentry);
16261+ if (bstart != btgt) {
16262+ struct au_nhash *whlist;
16263+
16264+ whlist = au_nhash_new(GFP_NOFS);
16265+ err = PTR_ERR(whlist);
16266+ if (IS_ERR(whlist))
16267+ goto out;
16268+ err = au_test_empty(dentry, whlist);
16269+ au_nhash_del(whlist);
16270+ goto out;
16271+ }
16272+
16273+ if (bstart == au_dbtaildir(dentry))
16274+ return 0; /* success */
16275+
16276+ err = au_test_empty_lower(dentry);
16277+
16278+ out:
16279+ if (/* unlikely */(err == -ENOTEMPTY)) {
16280+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
16281+ " is not supported\n");
16282+ err = -EXDEV;
16283+ }
16284+ AuTraceErr(err);
16285+ return err;
16286+}
16287+
16288+/* mainly for link(2) and rename(2) */
16289+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
16290+{
16291+ aufs_bindex_t bdiropq, bwh;
16292+ struct dentry *parent;
16293+
16294+ LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), btgt);
16295+ parent = dentry->d_parent;
16296+ IMustLock(parent->d_inode); /* dir is locked */
16297+
16298+ bdiropq = au_dbdiropq(parent);
16299+ bwh = au_dbwh(dentry);
16300+ if (au_br_rdonly(au_sbr(dentry->d_sb, btgt))
16301+ || (0 <= bdiropq && bdiropq < btgt)
16302+ || (0 <= bwh && bwh < btgt))
16303+ btgt = -1;
16304+
16305+ LKTRTrace("btgt %d\n", btgt);
16306+ return btgt;
16307+}
16308+
16309+/*
16310+ * simple tests for rename.
16311+ * following the checks in vfs, plus the parent-child relationship.
16312+ */
16313+static int au_may_ren(struct au_ren_args *a)
16314+{
16315+ int err;
16316+ struct inode *h_inode;
16317+
16318+ AuTraceEnter();
16319+
16320+ if (a->bstart[SRC] == a->btgt) {
16321+ err = au_may_del(a->src_dentry, a->btgt, a->h_parent[SRC],
16322+ au_ftest_ren(a->flags, ISDIR), &a->ndx);
16323+ if (unlikely(err))
16324+ goto out;
16325+ err = -EINVAL;
16326+ if (unlikely(a->h_dentry[SRC] == a->h_trap))
16327+ goto out;
16328+ }
16329+
16330+ err = 0;
16331+ if (a->bstart[DST] != a->btgt)
16332+ goto out;
16333+
16334+ err = -EIO;
16335+ h_inode = a->h_dentry[DST]->d_inode;
16336+ if (!a->dentry->d_inode) {
16337+ if (unlikely(h_inode))
16338+ goto out;
16339+ err = au_may_add(a->dentry, a->btgt, a->h_parent[DST],
16340+ au_ftest_ren(a->flags, ISDIR), &a->ndx);
16341+ } else {
16342+ if (unlikely(!h_inode || !h_inode->i_nlink))
16343+ goto out;
16344+ err = au_may_del(a->dentry, a->btgt, a->h_parent[DST],
16345+ au_ftest_ren(a->flags, ISDIR), &a->ndx);
16346+ if (unlikely(err))
16347+ goto out;
16348+ err = -ENOTEMPTY;
16349+ if (unlikely(a->h_dentry[DST] == a->h_trap))
16350+ goto out;
16351+ err = 0;
16352+ }
16353+
16354+ out:
16355+ if (unlikely(err == -ENOENT || err == -EEXIST))
16356+ err = -EIO;
16357+ AuTraceErr(err);
16358+ return err;
16359+}
16360+
16361+/*
16362+ * locking order
16363+ * (VFS)
16364+ * - src_dir and dir by lock_rename()
16365+ * - inode if exitsts
16366+ * (aufs)
16367+ * - lock all
16368+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
16369+ * + si_read_lock
16370+ * + di_write_lock2_child()
16371+ * + di_write_lock_child()
16372+ * + ii_write_lock_child()
16373+ * + di_write_lock_child2()
16374+ * + ii_write_lock_child2()
16375+ * + src_parent and parent
16376+ * + di_write_lock_parent()
16377+ * + ii_write_lock_parent()
16378+ * + di_write_lock_parent2()
16379+ * + ii_write_lock_parent2()
16380+ * + if udab=inotify is specified, lock grand parents (crazy)
16381+ * + di_read_lock_gparent()
16382+ * + ii_read_lock_gparent()
16383+ * + di_read_lock_gparent2()
16384+ * + ii_read_lock_gparent2()
16385+ * + mutex_lock(s_vfs_rename_mutex)
16386+ * + mutex_lock_gparent()
16387+ * + mutex_lock_gparent2()
16388+ * + mutex_lock_parent()
16389+ * + mutex_lock_parent2()
16390+ * + else lower src_dir and dir by vfsub_lock_rename()
16391+ * + verify the every relations between child, parent and grand parent. if any
16392+ * of them failed, unlock all and return -EBUSY.
16393+ */
16394+static void au_ren_pin_init(struct au_pin *first, struct dentry *d1,
16395+ struct au_pin *next, struct dentry *d2,
16396+ aufs_bindex_t bindex)
16397+{
16398+ AuTraceEnter();
16399+
16400+ /* AuLsc_DI_PARENT3 is for higher gparent initially */
16401+ au_pin_init(first, d1, bindex, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
16402+ AuPin_DI_LOCKED | AuPin_DO_GPARENT);
16403+ /* AuLsc_DI_PARENT4 is for lower gparent initially */
16404+ au_pin_init(next, d2, bindex, AuLsc_DI_PARENT3, AuLsc_I_PARENT4,
16405+ AuPin_DI_LOCKED | AuPin_DO_GPARENT);
16406+}
16407+
16408+static void au_ren_fake_pin(struct au_ren_args *a)
16409+{
16410+ int i;
16411+ struct au_pin1 *p;
16412+ struct inode *h_i;
16413+
16414+ AuTraceEnter();
16415+
16416+ /* they increment the ref counter */
16417+ for (i = 0; i < 2; i++) {
16418+ p = a->pin[i].pin + AuPin_PARENT;
16419+ au_pin_set_parent(a->pin + i, a->parent[i]);
16420+ dput(a->parent[i]);
16421+ h_i = a->h_parent[i]->d_inode;
16422+ au_pin_set_h_dir(a->pin + i, h_i);
16423+ iput(h_i);
16424+
16425+ if (!a->gparent[i]) {
16426+ au_pin_set_gparent(a->pin + i, NULL);
16427+ au_pin_set_h_gdir(a->pin + i, NULL);
16428+ } else {
16429+ au_pin_set_gparent(a->pin + i, a->gparent[i]);
16430+ dput(a->gparent[i]);
16431+ h_i = au_h_iptr(a->gparent[i]->d_inode, a->btgt);
16432+ au_pin_set_h_gdir(a->pin + i, h_i);
16433+ iput(h_i);
16434+ }
16435+ }
16436+}
16437+
16438+/* crazy */
16439+/* cf. i_op.c: au_do_pin() */
16440+static int au_ren_pin4(int higher, int lower, struct au_ren_args *a)
16441+{
16442+ int err, i, lsc;
16443+ struct au_pin *p;
16444+ struct au_pin1 *p4[4];
16445+ struct inode *h_dir;
16446+
16447+#if 0
16448+ lktr_set_pid(current->pid, LktrArrayPid);
16449+ LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
16450+ a->src_dir->i_ino, AuDLNPair(a->src_dentry),
16451+ a->dir->i_ino, AuDLNPair(a->dentry));
16452+ lktr_clear_pid(current->pid, LktrArrayPid);
16453+#endif
16454+ LKTRTrace("%d, %d\n", higher, lower);
16455+
16456+ err = 0;
16457+ p = a->pin + higher;
16458+ p4[0] = au_pin_gp(p); /* highest */
16459+ p4[1] = p->pin + AuPin_PARENT;
16460+ p = a->pin + lower;
16461+ p4[2] = au_pin_gp(p);
16462+ p4[3] = p->pin + AuPin_PARENT;
16463+
16464+ if (a->gparent[higher]) {
16465+ au_pin_do_set_parent(p4[0], a->gparent[higher]);
16466+ au_pin_do_set_dentry(p4[0], a->parent[higher]);
16467+ }
16468+ au_pin_do_set_parent(p4[1], a->parent[higher]);
16469+ if (a->gparent[lower]) {
16470+ au_pin_do_set_parent(p4[2], a->gparent[lower]);
16471+ au_pin_do_set_dentry(p4[2], a->parent[lower]);
16472+ }
16473+ au_pin_do_set_parent(p4[3], a->parent[lower]);
16474+
16475+#if 0
16476+ lktr_set_pid(current->pid, LktrArrayPid);
16477+ for (i = 0; i < 4; i++)
16478+ AuDbgDentry(p4[i]->parent);
16479+#endif
16480+ DiMustWriteLock(p4[3]->parent);
16481+ di_write_unlock(p4[1]->parent);
16482+ if (p4[2]->parent)
16483+ di_read_lock_parent2(p4[2]->parent, AuLock_IR);
16484+ di_write_lock_parent3(p4[1]->parent);
16485+ if (p4[0]->parent)
16486+ di_read_lock_parent4(p4[0]->parent, AuLock_IR);
16487+ //lktr_clear_pid(current->pid, LktrArrayPid);
16488+
16489+ vfsub_lock_rename_mutex(au_sbr_sb(a->dentry->d_sb, a->btgt));
16490+ au_fset_ren(a->flags, VFSLOCK);
16491+
16492+ lsc = AuLsc_I_PARENT;
16493+ for (i = 0; i < 4; i++, lsc++) {
16494+ if (p4[i]->parent) {
16495+ h_dir = au_h_iptr(p4[i]->parent->d_inode, a->btgt);
16496+ au_pin_do_set_h_dir(p4[i], h_dir);
16497+ mutex_lock_nested(&h_dir->i_mutex, lsc);
16498+ }
16499+ }
16500+
16501+ AuTraceErr(err);
16502+ return err;
16503+}
16504+
16505+static struct dentry *au_ren_pin3(int higher, int lower, struct au_ren_args *a)
16506+{
16507+ struct dentry *h_trap;
16508+ struct au_pin *p;
16509+ int err;
16510+
16511+ LKTRTrace("%d, %d\n", higher, lower);
16512+
16513+ p = a->pin + higher;
16514+ AuDebugOn(!au_pin_gp(p));
16515+ au_fset_pin(au_pin_gp(p)->flags, VFS_RENAME);
16516+ err = au_do_pin(p->pin + AuPin_PARENT, au_pin_gp(p));
16517+ h_trap = ERR_PTR(err);
16518+ if (unlikely(err))
16519+ goto out;
16520+ p = a->pin + lower;
16521+ au_fclr_pin(p->pin[AuPin_PARENT].flags, DO_GPARENT);
16522+ err = au_do_pin(p->pin + AuPin_PARENT, NULL);
16523+ h_trap = ERR_PTR(err);
16524+ if (unlikely(err)) {
16525+ p = a->pin + higher;
16526+ au_do_unpin(p->pin + AuPin_PARENT, au_pin_gp(p));
16527+ goto out;
16528+ }
16529+ h_trap = au_pinned_h_parent(p);
16530+
16531+ out:
16532+ AuTraceErrPtr(h_trap);
16533+ return h_trap;
16534+}
16535+
16536+static struct dentry *au_ren_pin(struct au_ren_args *a)
16537+{
16538+ struct dentry *h_trap;
16539+ struct inode *h_gdir;
16540+ int err, i, same_gp;
16541+
16542+ //lktr_set_pid(current->pid, LktrArrayPid);
16543+ AuTraceEnter();
16544+ AuDebugOn(!au_opt_test(a->mnt_flags, UDBA_INOTIFY));
16545+
16546+ /* gdir is not locked */
16547+ same_gp = 0;
16548+ if (!IS_ROOT(a->parent[SRC]))
16549+ a->gparent[SRC] = dget_parent(a->parent[SRC]);
16550+ if (!IS_ROOT(a->parent[DST])) {
16551+ a->gparent[DST] = dget_parent(a->parent[DST]);
16552+ same_gp = (a->gparent[SRC] == a->gparent[DST]);
16553+ }
16554+
16555+ /*
16556+ * patterns
16557+ * - gparent[SRC] is parent[DST]
16558+ * - parent[SRC] is gparent[DST]
16559+ * - gparent[SRC] is gparent[DST]
16560+ * - gparent[SRC] is a descendant of parent[DST]
16561+ * - parent[SRC] is an ancestor of gparent[DST]
16562+ * - not within grand parent range
16563+ */
16564+ err = 0;
16565+ h_trap = ERR_PTR(-EBUSY);
16566+ if (a->gparent[SRC] == a->parent[DST]) {
16567+ //AuDbg("here\n");
16568+ LKTRLabel(here);
16569+ au_ren_pin_init(a->pin + DST, a->dentry, a->pin + SRC,
16570+ a->src_dentry, a->btgt);
16571+ h_trap = au_ren_pin3(DST, SRC, a);
16572+ if (!IS_ERR(h_trap)) {
16573+ h_gdir = au_pinned_h_dir(a->pin + DST);
16574+ err = au_verify_parent(a->h_parent[SRC], h_gdir);
16575+ if (unlikely(err))
16576+ h_trap = ERR_PTR(-EBUSY);
16577+ }
16578+ } else if (a->parent[SRC] == a->gparent[DST] || same_gp) {
16579+ //AuDbg("here\n");
16580+ LKTRLabel(here);
16581+ au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST,
16582+ a->dentry, a->btgt);
16583+ h_trap = au_ren_pin3(SRC, DST, a);
16584+ if (!IS_ERR(h_trap)) {
16585+ if (!same_gp)
16586+ h_gdir = au_pinned_h_dir(a->pin + SRC);
16587+ else
16588+ h_gdir = au_pinned_h_gdir(a->pin + SRC);
16589+ err = au_verify_parent(a->h_parent[DST], h_gdir);
16590+ if (unlikely(err))
16591+ h_trap = ERR_PTR(-EBUSY);
16592+ }
16593+ } else if (a->gparent[SRC]
16594+ && (h_trap = au_test_subdir(a->gparent[SRC],
16595+ a->parent[DST]))) {
16596+ //AuDbg("here\n");
16597+ LKTRLabel(here);
16598+ au_ren_pin_init(a->pin + DST, a->dentry, a->pin + SRC,
16599+ a->src_dentry, a->btgt);
16600+ if (a->gparent[DST]) {
16601+ err = au_ren_pin4(DST, SRC, a);
16602+ if (unlikely(err))
16603+ h_trap = ERR_PTR(err);
16604+ } else {
16605+ struct dentry *t;
16606+ t = au_ren_pin3(DST, SRC, a);
16607+ AuDebugOn(t == h_trap);
16608+ }
16609+#if 1
16610+ } else if (a->gparent[DST]
16611+ && (h_trap = au_test_subdir(a->gparent[DST],
16612+ a->parent[SRC]))) {
16613+ /* todo: is this really necessary? */
16614+ //AuDbg("here\n");
16615+ LKTRLabel(here);
16616+ au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST,
16617+ a->dentry, a->btgt);
16618+ if (a->gparent[SRC]) {
16619+ err = au_ren_pin4(SRC, DST, a);
16620+ if (unlikely(err))
16621+ h_trap = ERR_PTR(err);
16622+ } else {
16623+ struct dentry *t;
16624+ t = au_ren_pin3(SRC, DST, a);
16625+ AuDebugOn(t == h_trap);
16626+ }
16627+#endif
16628+ } else /* if (a->gparent[DST]
16629+ && (h_trap = au_test_subdir(a->gparent[DST],
16630+ a->parent[SRC]))) */ {
16631+ //AuDbg("here\n");
16632+ LKTRLabel(here);
16633+ h_trap = NULL;
16634+ if (a->gparent[DST])
16635+ h_trap = au_test_subdir(a->gparent[DST],
16636+ a->parent[SRC]);
16637+ au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST,
16638+ a->dentry, a->btgt);
16639+ err = au_ren_pin4(SRC, DST, a);
16640+ if (unlikely(err))
16641+ h_trap = ERR_PTR(err);
16642+ }
16643+ au_fset_ren(a->flags, PINNED);
16644+
16645+ if (!IS_ERR(h_trap)) {
16646+ err = 0;
16647+ for (i = 0; !err && i < 2; i++) {
16648+ h_gdir = au_pinned_h_gdir(a->pin + i);
16649+ if (h_gdir)
16650+ err = au_verify_parent(a->h_parent[i], h_gdir);
16651+ }
16652+ if (unlikely(err)) {
16653+ h_trap = ERR_PTR(err);
16654+ //AuDbg("here\n");
16655+ }
16656+ }
16657+
16658+ dput(a->gparent[SRC]);
16659+ dput(a->gparent[DST]);
16660+ memset(a->gparent, 0, sizeof(a->gparent));
16661+ AuTraceErrPtr(h_trap);
16662+ //lktr_clear_pid(current->pid, LktrArrayPid);
16663+ return h_trap;
16664+}
16665+
16666+static void au_ren_unlock(struct au_ren_args *a)
16667+{
16668+ int i;
16669+
16670+ AuTraceEnter();
16671+
16672+ if (au_ftest_ren(a->flags, MNT_WRITE))
16673+ au_mnt_drop_write(au_sbr_mnt(a->dentry->d_sb, a->btgt));
16674+ if (a->h_locked[0])
16675+ vfsub_unlock_rename(a->h_locked[0], a->h_locked[1]);
16676+ if (au_ftest_ren(a->flags, PINNED)) {
16677+ au_unpin(a->pin + SRC);
16678+ au_unpin(a->pin + DST);
16679+ memset(a->gparent, 0, sizeof(a->gparent));
16680+ }
16681+ if (au_ftest_ren(a->flags, VFSLOCK))
16682+ vfsub_unlock_rename_mutex(au_sbr_sb(a->dentry->d_sb, a->btgt));
16683+ for (i = 0; i < 2; i++)
16684+ if (a->gparent[i]) {
16685+ di_read_unlock(a->gparent[i], AuLock_IR);
16686+ dput(a->gparent[i]);
16687+ }
16688+}
16689+
16690+static int au_ren_lock(struct au_ren_args *a)
16691+{
16692+ int err;
16693+ const int hinotify = au_opt_test(a->mnt_flags, UDBA_INOTIFY);
16694+
16695+ AuTraceEnter();
16696+
16697+ err = 0;
16698+ if (!hinotify
16699+ || (au_ftest_ren(a->flags, ISSAMEDIR) && IS_ROOT(a->parent[SRC]))) {
16700+ au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST,
16701+ a->dentry, a->btgt);
16702+ LKTRLabel(here);
16703+ a->h_locked[0] = a->h_parent[SRC];
16704+ a->h_locked[1] = a->h_parent[DST];
16705+ a->h_trap = vfsub_lock_rename(a->h_locked[0], a->h_locked[1]);
16706+ au_ren_fake_pin(a);
16707+ } else if (au_ftest_ren(a->flags, ISSAMEDIR)
16708+ && !IS_ROOT(a->parent[SRC])) {
16709+ /* this and next block should not be compiled when
16710+ hinotify is disabled */
16711+ /* irregular/tricky rename lock */
16712+ LKTRLabel(here);
16713+ au_ren_pin_init(a->pin + SRC, a->src_dentry, a->pin + DST,
16714+ a->dentry, a->btgt);
16715+ a->gparent[SRC] = dget_parent(a->parent[SRC]);
16716+ di_read_lock_parent2(a->gparent[SRC], AuLock_IR);
16717+ a->h_locked[0] = a->h_parent[SRC];
16718+ a->h_locked[1] = dget_parent(a->h_parent[SRC]);
16719+ a->h_trap = vfsub_lock_rename(a->h_locked[0], a->h_locked[1]);
16720+ err = au_verify_parent(a->h_parent[SRC],
16721+ a->h_locked[1]->d_inode);
16722+ dput(a->h_locked[1]);
16723+ if (!err)
16724+ au_ren_fake_pin(a);
16725+ } else {
16726+ /* 3 or 4 dir locks. crazy */
16727+ LKTRLabel(here);
16728+ a->h_trap = au_ren_pin(a);
16729+ if (IS_ERR(a->h_trap))
16730+ err = PTR_ERR(a->h_trap);
16731+ }
16732+
16733+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
16734+ err = au_verify_parent(a->h_dentry[SRC],
16735+ a->h_parent[SRC]->d_inode);
16736+ if (!err && au_dbstart(a->dentry) == a->btgt)
16737+ err = au_verify_parent(a->h_dentry[DST],
16738+ a->h_parent[DST]->d_inode);
16739+ if (!err) {
16740+ err = au_br_want_write(au_sbr(a->dentry->d_sb, a->btgt));
16741+ if (unlikely(err))
16742+ goto out_unlock;
16743+ au_fset_ren(a->flags, MNT_WRITE);
16744+ goto out; /* success */
16745+ }
16746+
16747+ err = -EBUSY;
16748+
16749+ out_unlock:
16750+ au_ren_unlock(a);
16751+ out:
16752+ AuTraceErr(err);
16753+ return err;
16754+}
16755+
16756+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
16757+ struct inode *dir, struct dentry *dentry)
16758+{
16759+ int err;
16760+ aufs_bindex_t bend, bindex;
16761+ unsigned char do_dt_dstdir, hinotify;
16762+ struct inode *inode[2];
16763+ enum { PARENT, CHILD };
16764+ /* reduce stack space */
16765+ struct {
16766+ struct au_ren_args a;
16767+ struct au_dtime dt[2][2];
16768+ } *p;
16769+ struct au_wr_dir_args wr_dir_args = {
16770+ /* .force_btgt = -1, */
16771+ .flags = AuWrDir_ADD_ENTRY
16772+ };
16773+
16774+ LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
16775+ src_dir->i_ino, AuDLNPair(src_dentry),
16776+ dir->i_ino, AuDLNPair(dentry));
16777+ AuDebugOn(IS_ROOT(src_dentry) || IS_ROOT(dentry));
16778+ IMustLock(src_dir);
16779+ IMustLock(dir);
16780+ inode[DST] = dentry->d_inode;
16781+ if (inode[DST]) {
16782+ IMustLock(inode[DST]);
16783+ au_igrab(inode[DST]);
16784+ }
16785+
16786+ err = -ENOMEM;
16787+ BUILD_BUG_ON(sizeof(*p) > PAGE_SIZE);
16788+ p = kzalloc(sizeof(*p), GFP_NOFS);
16789+ if (unlikely(!p))
16790+ goto out;
16791+
16792+ err = -ENOTDIR;
16793+ p->a.src_dir = src_dir;
16794+ p->a.src_dentry = src_dentry;
16795+ p->a.dir = dir;
16796+ p->a.dentry = dentry;
16797+ p->a.sb = src_dentry->d_sb;
16798+ inode[SRC] = src_dentry->d_inode;
16799+ p->a.flags = 0;
16800+ if (S_ISDIR(inode[SRC]->i_mode)) {
16801+ au_fset_ren(p->a.flags, ISDIR);
16802+ if (unlikely(inode[DST] && !S_ISDIR(inode[DST]->i_mode)))
16803+ goto out_free;
16804+ aufs_read_and_write_lock2(dentry, src_dentry, AuLock_DIR);
16805+ } else
16806+ aufs_read_and_write_lock2(dentry, src_dentry, 0);
16807+
16808+ p->a.mnt_flags = au_mntflags(p->a.sb);
16809+ if (au_test_dlgt(p->a.mnt_flags))
16810+ au_fset_ren(p->a.flags, DLGT);
16811+ p->a.parent[SRC] = src_dentry->d_parent; /* dir inode is locked */
16812+ p->a.parent[DST] = dentry->d_parent; /* dir inode is locked */
16813+ au_fset_ren(p->a.flags, ISSAMEDIR); /* temporary */
16814+ di_write_lock_parent(p->a.parent[DST]);
16815+
16816+ /* which branch we process */
16817+ p->a.bstart[SRC] = au_dbstart(src_dentry);
16818+ p->a.bstart[DST] = au_dbstart(dentry);
16819+ if (au_ftest_ren(p->a.flags, ISDIR))
16820+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16821+ wr_dir_args.force_btgt = p->a.bstart[SRC];
16822+ if (dentry->d_inode && p->a.bstart[DST] < p->a.bstart[SRC])
16823+ wr_dir_args.force_btgt = p->a.bstart[DST];
16824+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
16825+ err = au_wr_dir(dentry, src_dentry, &wr_dir_args);
16826+ p->a.btgt = err;
16827+ if (unlikely(err < 0))
16828+ goto out_unlock;
16829+
16830+ /* are they available to be renamed */
16831+ err = 0;
16832+ au_nhash_init(&p->a.whlist);
16833+ if (au_ftest_ren(p->a.flags, ISDIR) && inode[DST]) {
16834+ au_set_dbstart(dentry, p->a.bstart[DST]);
16835+ err = may_rename_dstdir(dentry, p->a.btgt, &p->a.whlist);
16836+ au_set_dbstart(dentry, p->a.btgt);
16837+ }
16838+ p->a.h_dentry[DST] = au_h_dptr(dentry, au_dbstart(dentry));
16839+ if (unlikely(err))
16840+ goto out_unlock;
16841+ /* todo: minor optimize,
16842+ their sb may be same while their bindex differs? */
16843+ p->a.h_dentry[SRC] = au_h_dptr(src_dentry, au_dbstart(src_dentry));
16844+ if (au_ftest_ren(p->a.flags, ISDIR)) {
16845+ err = may_rename_srcdir(src_dentry, p->a.btgt);
16846+ if (unlikely(err))
16847+ goto out_children;
16848+ }
16849+
16850+ /* prepare the writable parent dir on the same branch */
16851+ if (p->a.bstart[DST] == p->a.btgt) {
16852+ au_fset_ren(p->a.flags, WHDST);
16853+ } else {
16854+ err = au_cpup_dirs(dentry, p->a.btgt);
16855+ if (unlikely(err))
16856+ goto out_children;
16857+ }
16858+
16859+ if (src_dir != dir) {
16860+ /*
16861+ * this temporary unlock is safe,
16862+ * because both dir->i_mutex are locked.
16863+ */
16864+ di_write_unlock(p->a.parent[DST]);
16865+ di_write_lock_parent(p->a.parent[SRC]);
16866+ err = au_wr_dir_need_wh
16867+ (src_dentry, au_ftest_ren(p->a.flags, ISDIR),
16868+ &p->a.btgt);
16869+ di_write_unlock(p->a.parent[SRC]);
16870+ di_write_lock2_parent(p->a.parent[SRC], p->a.parent[DST],
16871+ /*isdir*/1);
16872+ au_fclr_ren(p->a.flags, ISSAMEDIR);
16873+ } else
16874+ err = au_wr_dir_need_wh
16875+ (src_dentry, au_ftest_ren(p->a.flags, ISDIR),
16876+ &p->a.btgt);
16877+ if (unlikely(err < 0))
16878+ goto out_children;
16879+ if (err)
16880+ au_fset_ren(p->a.flags, WHSRC);
16881+
16882+ hinotify = au_opt_test(p->a.mnt_flags, UDBA_INOTIFY);
16883+ p->a.h_parent[SRC] = au_h_dptr(p->a.parent[SRC], p->a.btgt);
16884+ p->a.h_parent[DST] = au_h_dptr(p->a.parent[DST], p->a.btgt);
16885+ err = au_ren_lock(&p->a);
16886+ if (unlikely(err))
16887+ goto out_children;
16888+
16889+ if (!au_opt_test(p->a.mnt_flags, UDBA_NONE)) {
16890+ p->a.ndx.nfsmnt = au_nfsmnt(p->a.sb, p->a.btgt);
16891+ if (au_ftest_ren(p->a.flags, DLGT))
16892+ au_fset_ndx(p->a.ndx.flags, DLGT);
16893+ err = au_may_ren(&p->a);
16894+ if (unlikely(err))
16895+ goto out_hdir;
16896+ memset(&p->a.ndx, 0, sizeof(p->a.ndx));
16897+ }
16898+
16899+ /* store timestamps to be revertible */
16900+ au_dtime_store(p->dt[PARENT] + SRC, p->a.parent[SRC],
16901+ p->a.h_parent[SRC], au_pinned_hdir(p->a.pin + SRC),
16902+ au_pinned_hgdir(p->a.pin + SRC)
16903+ /* hgdir[SRC] */);
16904+ if (!au_ftest_ren(p->a.flags, ISSAMEDIR))
16905+ au_dtime_store(p->dt[PARENT] + DST, p->a.parent[DST],
16906+ p->a.h_parent[DST],
16907+ au_pinned_hdir(p->a.pin + DST),
16908+ au_pinned_hgdir(p->a.pin + DST)
16909+ /* hgdir[DST] */);
16910+ do_dt_dstdir = 0;
16911+ if (au_ftest_ren(p->a.flags, ISDIR)) {
16912+ au_dtime_store(p->dt[CHILD] + SRC, src_dentry,
16913+ p->a.h_dentry[SRC], au_hi(inode[SRC], p->a.btgt),
16914+ au_pinned_hdir(p->a.pin + SRC));
16915+ if (p->a.h_dentry[DST]->d_inode) {
16916+ do_dt_dstdir = 1;
16917+ au_dtime_store(p->dt[CHILD] + DST, dentry,
16918+ p->a.h_dentry[DST],
16919+ au_hi(inode[DST], p->a.btgt),
16920+ au_pinned_hdir(p->a.pin + DST));
16921+ }
16922+ }
16923+
16924+ err = do_rename(&p->a);
16925+ if (unlikely(err))
16926+ goto out_dt;
16927+
16928+ /* update dir attributes */
16929+ dir->i_version++;
16930+ if (au_ftest_ren(p->a.flags, ISDIR)) {
16931+ /* is this updating defined in POSIX? */
16932+ /* mutex_lock(&inode[SRC]->i_mutex); */
16933+ au_cpup_attr_timesizes(inode[SRC]);
16934+ /* mutex_unlock(&inode[SRC]->i_mutex); */
16935+
16936+ au_cpup_attr_nlink(dir, /*force*/1);
16937+ if (inode[DST]) {
16938+ clear_nlink(inode[DST]);
16939+ au_cpup_attr_timesizes(inode[DST]);
16940+ }
16941+ }
16942+ if (au_ibstart(dir) == p->a.btgt)
16943+ au_cpup_attr_timesizes(dir);
16944+
16945+ if (!au_ftest_ren(p->a.flags, ISSAMEDIR)) {
16946+ src_dir->i_version++;
16947+ if (au_ftest_ren(p->a.flags, ISDIR))
16948+ au_cpup_attr_nlink(src_dir, /*force*/1);
16949+ if (au_ibstart(src_dir) == p->a.btgt)
16950+ au_cpup_attr_timesizes(src_dir);
16951+ }
16952+
16953+ /* todo: simple d_drop(src_dentry) is not enough? */
16954+ /* dput/iput all lower dentries */
16955+ au_set_dbwh(src_dentry, -1);
16956+ bend = au_dbend(src_dentry);
16957+ for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
16958+ struct dentry *hd;
16959+ hd = au_h_dptr(src_dentry, bindex);
16960+ if (hd)
16961+ au_set_h_dptr(src_dentry, bindex, NULL);
16962+ }
16963+ au_set_dbend(src_dentry, p->a.btgt);
16964+
16965+ if (au_opt_test(p->a.mnt_flags, PLINK)
16966+ && au_plink_test(src_dentry->d_sb, inode[SRC]))
16967+ goto out_hdir; /* success */
16968+ bend = au_ibend(inode[SRC]);
16969+ for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
16970+ struct inode *hi;
16971+ hi = au_h_iptr(inode[SRC], bindex);
16972+ if (hi) {
16973+ au_xino_write0(p->a.sb, bindex, hi->i_ino, 0);
16974+ /* ignore this error */
16975+ au_set_h_iptr(inode[SRC], bindex, NULL, 0);
16976+ }
16977+ }
16978+ au_set_ibend(inode[SRC], p->a.btgt);
16979+ goto out_hdir; /* success */
16980+
16981+ out_dt:
16982+ au_dtime_revert(p->dt[PARENT] + SRC);
16983+ if (!au_ftest_ren(p->a.flags, ISSAMEDIR))
16984+ au_dtime_revert(p->dt[PARENT] + DST);
16985+ if (au_ftest_ren(p->a.flags, ISDIR) && err != -EIO) {
16986+ struct dentry *hd;
16987+
16988+ hd = p->dt[CHILD][SRC].dt_h_dentry;
16989+ mutex_lock_nested(&hd->d_inode->i_mutex, AuLsc_I_CHILD);
16990+ au_dtime_revert(p->dt[CHILD] + SRC);
16991+ mutex_unlock(&hd->d_inode->i_mutex);
16992+ if (do_dt_dstdir) {
16993+ hd = p->dt[CHILD][DST].dt_h_dentry;
16994+ mutex_lock_nested(&hd->d_inode->i_mutex, AuLsc_I_CHILD);
16995+ au_dtime_revert(p->dt[CHILD] + DST);
16996+ mutex_unlock(&hd->d_inode->i_mutex);
16997+ }
16998+ }
16999+ out_hdir:
17000+ au_ren_unlock(&p->a);
17001+ out_children:
17002+ au_nhash_fin(&p->a.whlist);
17003+ out_unlock:
17004+ if (unlikely(err && au_ftest_ren(p->a.flags, ISDIR))) {
17005+ au_update_dbstart(dentry);
17006+ d_drop(dentry);
17007+ }
17008+ if (!err) {
17009+ d_move(src_dentry, dentry);
17010+ if (inode[DST]
17011+ && (inode[DST]->i_nlink == 1
17012+ || au_ftest_ren(p->a.flags, ISDIR)))
17013+ inode[DST]->i_flags |= S_DEAD;
17014+ }
17015+ if (au_ftest_ren(p->a.flags, ISSAMEDIR))
17016+ di_write_unlock(p->a.parent[DST]);
17017+ else
17018+ di_write_unlock2(p->a.parent[SRC], p->a.parent[DST]);
17019+ aufs_read_and_write_unlock2(dentry, src_dentry);
17020+ out_free:
17021+ kfree(p);
17022+ out:
17023+ iput(inode[DST]);
17024+ AuTraceErr(err);
17025+ //lktr_clear_pid(current->pid, LktrArrayPid);
17026+ if (unlikely(err == -EBUSY && au_test_nfsd(current)))
17027+ err = -ESTALE;
17028+ return err;
17029+}
17030diff -urN linux/fs/aufs/Makefile linux-aufs/fs/aufs/Makefile
17031--- linux/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
17032+++ linux-aufs/fs/aufs/Makefile 2008-10-20 03:47:24.000000000 +0200
17033@@ -0,0 +1,74 @@
17034+# AUFS Makefile for the Linux 2.6.25 and later
17035+# $Id$
17036+
17037+# the environment variables are not inherited since 2.6.23
17038+ifdef AUFS_EXTRA_CFLAGS
17039+ccflags-y += ${AUFS_EXTRA_CFLAGS}
17040+endif
17041+
17042+########################################
17043+
17044+ifdef CONFIG_AUFS_RR_SQUASHFS
17045+# cf. squashfs3.2-r2 and sqlzma patch.
17046+ccflags-y += -DSQUASHFS_MAGIC=0x73717368
17047+ccflags-y += -DSQUASHFS_MAGIC_SWAP=0x68737173
17048+ccflags-y += -DSQUASHFS_MAGIC_LZMA=0x71736873
17049+ccflags-y += -DSQUASHFS_MAGIC_LZMA_SWAP=0x73687371
17050+endif
17051+
17052+# defined in ${srctree}/fs/fuse/inode.c
17053+ccflags-$(CONFIG_AUFS_WORKAROUND_FUSE) += -DFUSE_SUPER_MAGIC=0x65735546
17054+
17055+# defined in ${srctree}/fs/xfs/xfs_sb.h
17056+# tristate
17057+ifdef CONFIG_XFS_FS
17058+ccflags-y += -DXFS_SB_MAGIC=0x58465342
17059+endif
17060+
17061+# defined in ${srctree}/mm/shmem.c
17062+# tristate
17063+ifdef CONFIG_TMPFS
17064+ccflags-y += -DTMPFS_MAGIC=0x01021994
17065+endif
17066+
17067+# defined in ${srctree}fs/sysfs/mount.c
17068+# bool
17069+ccflags-$(CONFIG_SYSFS) += -DSYSFS_MAGIC=0x62656572
17070+
17071+ifndef EXTRAVERSION
17072+EXTRAVERSION = $(shell echo ${KERNELVERSION} | cut -f3- -d. | cut -f2- -d-)
17073+endif
17074+# for -mm tree, support the latest version only
17075+ifneq ($(strip $(shell echo ${EXTRAVERSION} | fgrep -- mm)),)
17076+ccflags-y += -DCONFIG_AUFS_UNIONFS22_PATCH -DCONFIG_AUFS_UNIONFS23_PATCH
17077+endif
17078+
17079+-include $(dir $(lastword ${MAKEFILE_LIST}))priv.mk
17080+#$(warning ${ccflags-y})
17081+
17082+########################################
17083+
17084+obj-$(CONFIG_AUFS) += aufs.o
17085+aufs-y := module.o super.o sbinfo.o branch.o xino.o sysaufs.o opts.o \
17086+ wkq.o vfsub.o dcsub.o \
17087+ cpup.o whout.o plink.o wbr_policy.o \
17088+ dentry.o dinfo.o \
17089+ file.o f_op.o finfo.o \
17090+ dir.o vdir.o \
17091+ inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o iinfo.o \
17092+ misc.o
17093+
17094+aufs-$(CONFIG_SYSFS) += sysfs.o
17095+aufs-$(CONFIG_AUFS_BR_NFS) += br_nfs.o
17096+aufs-$(CONFIG_AUFS_BR_XFS) += br_xfs.o
17097+aufs-$(CONFIG_AUFS_WORKAROUND_FUSE) += br_fuse.o
17098+aufs-$(CONFIG_AUFS_DLGT) += dlgt.o
17099+aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
17100+aufs-$(CONFIG_AUFS_HIN_OR_DLGT) += hin_or_dlgt.o
17101+aufs-$(CONFIG_AUFS_GETATTR) += getattr.o
17102+aufs-$(CONFIG_AUFS_EXPORT) += export.o
17103+aufs-$(CONFIG_AUFS_ROBR) += robr.o
17104+# reserved for future use
17105+#aufs-$(CONFIG_AUFS_XATTR) += xattr.o
17106+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
17107+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
17108diff -urN linux/fs/aufs/misc.c linux-aufs/fs/aufs/misc.c
17109--- linux/fs/aufs/misc.c 1970-01-01 01:00:00.000000000 +0100
17110+++ linux-aufs/fs/aufs/misc.c 2009-03-12 16:18:04.000000000 +0100
17111@@ -0,0 +1,308 @@
17112+/*
17113+ * Copyright (C) 2005-2009 Junjiro Okajima
17114+ *
17115+ * This program, aufs is free software; you can redistribute it and/or modify
17116+ * it under the terms of the GNU General Public License as published by
17117+ * the Free Software Foundation; either version 2 of the License, or
17118+ * (at your option) any later version.
17119+ *
17120+ * This program is distributed in the hope that it will be useful,
17121+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17122+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17123+ * GNU General Public License for more details.
17124+ *
17125+ * You should have received a copy of the GNU General Public License
17126+ * along with this program; if not, write to the Free Software
17127+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17128+ */
17129+
17130+/*
17131+ * $Id$
17132+ */
17133+
17134+#include "aufs.h"
17135+
17136+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
17137+{
17138+ void *q;
17139+
17140+ LKTRTrace("p %p, nused %d, sz %d\n", p, nused, new_sz);
17141+ AuDebugOn(new_sz <= 0);
17142+ if (new_sz <= nused)
17143+ return p;
17144+
17145+ q = krealloc(p, new_sz, gfp);
17146+ if (q)
17147+ memset(q + nused, 0, new_sz - nused);
17148+ return q;
17149+}
17150+
17151+/* ---------------------------------------------------------------------- */
17152+
17153+struct nameidata *au_dup_nd(struct au_sbinfo *sbinfo, struct nameidata *dst,
17154+ struct nameidata *src)
17155+{
17156+ LKTRTrace("src %p\n", src);
17157+
17158+ if (src) {
17159+ *dst = *src;
17160+ dst->flags &= ~LOOKUP_PARENT;
17161+ if (sbinfo->si_wbr_create == AuWbrCreate_TDP) {
17162+ if ((dst->flags & LOOKUP_CREATE)
17163+ && !(dst->intent.open.flags & O_CREAT))
17164+ dst->flags &= ~LOOKUP_CREATE;
17165+ } else {
17166+ dst->flags &= ~LOOKUP_CREATE;
17167+ dst->intent.open.flags &= ~O_CREAT;
17168+ }
17169+ } else
17170+ dst = NULL;
17171+
17172+ return dst;
17173+}
17174+
17175+struct nameidata *au_fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
17176+ struct super_block *sb, aufs_bindex_t bindex)
17177+{
17178+ LKTRTrace("nd %p, b%d\n", nd, bindex);
17179+
17180+ if (!nd)
17181+ return NULL;
17182+
17183+ DiMustAnyLock(nd->path.dentry);
17184+
17185+ fake_nd->path.dentry = NULL;
17186+ fake_nd->path.mnt = NULL;
17187+
17188+ if (bindex <= au_dbend(nd->path.dentry))
17189+ fake_nd->path.dentry = au_h_dptr(nd->path.dentry, bindex);
17190+ if (fake_nd->path.dentry) {
17191+ fake_nd->path.mnt = au_sbr_mnt(sb, bindex);
17192+ AuDebugOn(!fake_nd->path.mnt);
17193+ path_get(&fake_nd->path);
17194+ } else
17195+ fake_nd = ERR_PTR(-ENOENT);
17196+
17197+ AuTraceErrPtr(fake_nd);
17198+ return fake_nd;
17199+}
17200+
17201+void au_fake_dm_release(struct nameidata *fake_nd)
17202+{
17203+ if (fake_nd)
17204+ path_put(&fake_nd->path);
17205+}
17206+
17207+int au_h_create(struct inode *h_dir, struct dentry *h_dentry, int mode,
17208+ struct vfsub_args *vargs, struct nameidata *nd,
17209+ struct vfsmount *nfsmnt)
17210+{
17211+ int err;
17212+
17213+ LKTRTrace("hi%lu, %.*s, 0%o, nd %d, nfsmnt %d\n",
17214+ h_dir->i_ino, AuDLNPair(h_dentry), mode, !!nd, !!nfsmnt);
17215+
17216+ err = -ENOSYS;
17217+ if (!nfsmnt)
17218+ err = vfsub_create(h_dir, h_dentry, mode, /*nd*/NULL, vargs);
17219+ else {
17220+ struct nameidata fake_nd;
17221+
17222+ if (nd)
17223+ fake_nd = *nd;
17224+ else
17225+ memset(&fake_nd, 0, sizeof(fake_nd));
17226+ fake_nd.path.dentry = h_dentry;
17227+ fake_nd.path.mnt = nfsmnt;
17228+ path_get(&fake_nd.path);
17229+ fake_nd.flags = LOOKUP_CREATE;
17230+ fake_nd.intent.open.flags = O_CREAT | FMODE_READ;
17231+ fake_nd.intent.open.create_mode = mode;
17232+
17233+ err = vfsub_create(h_dir, h_dentry, mode, &fake_nd, vargs);
17234+ path_put(&fake_nd.path);
17235+ }
17236+
17237+ AuTraceErr(err);
17238+ return err;
17239+}
17240+
17241+/* ---------------------------------------------------------------------- */
17242+
17243+/* empty_zero_page is not exported on PPC before 2.6.26 */
17244+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) \
17245+ && (defined(CONFIG_PPC) || defined(CONFIG_PPC64))
17246+static char *au_zp_alloc(void)
17247+{
17248+ return (void *)get_zeroed_page(GFP_NOFS);
17249+}
17250+
17251+static void au_zp_free(char *p)
17252+{
17253+ if (p)
17254+ free_page((unsigned long)p);
17255+}
17256+#else
17257+static char *au_zp_alloc(void)
17258+{
17259+ return page_address(ZERO_PAGE(0));
17260+}
17261+
17262+static void au_zp_free(char *p)
17263+{
17264+ /* empty */
17265+}
17266+#endif
17267+
17268+int au_copy_file(struct file *dst, struct file *src, loff_t len,
17269+ struct au_hinode *hdir, struct super_block *sb,
17270+ struct vfsub_args *vargs)
17271+{
17272+ int err, all_zero, do_kfree;
17273+ unsigned long blksize;
17274+ char *buf, *zp;
17275+ /* reduce stack usage */
17276+ struct iattr *ia;
17277+
17278+ LKTRTrace("%.*s, %.*s\n",
17279+ AuDLNPair(dst->f_dentry), AuDLNPair(src->f_dentry));
17280+ AuDebugOn(!(dst->f_mode & FMODE_WRITE));
17281+#ifdef CONFIG_AUFS_DEBUG
17282+ {
17283+ struct dentry *parent;
17284+ parent = dget_parent(dst->f_dentry);
17285+ IMustLock(parent->d_inode);
17286+ dput(parent);
17287+ }
17288+#endif
17289+
17290+ err = -ENOMEM;
17291+ zp = au_zp_alloc();
17292+ if (unlikely(!zp))
17293+ goto out;
17294+ blksize = dst->f_dentry->d_sb->s_blocksize;
17295+ if (!blksize || PAGE_SIZE < blksize)
17296+ blksize = PAGE_SIZE;
17297+ LKTRTrace("blksize %lu\n", blksize);
17298+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(*ia));
17299+ if (do_kfree)
17300+ buf = kmalloc(blksize, GFP_NOFS);
17301+ else
17302+ buf = (void *)__get_free_page(GFP_NOFS);
17303+ if (unlikely(!buf))
17304+ goto out;
17305+
17306+#ifdef CONFIG_AUFS_DEBUG
17307+ if (len > (1 << 22))
17308+ AuWarn("copying a large file %lld\n", (long long)len);
17309+#endif
17310+ err = 0;
17311+ all_zero = 0;
17312+ src->f_pos = 0;
17313+ dst->f_pos = 0;
17314+ while (len) {
17315+ size_t sz, rbytes, wbytes;
17316+ char *p;
17317+
17318+ LKTRTrace("len %lld\n", len);
17319+ sz = blksize;
17320+ if (len < blksize)
17321+ sz = len;
17322+
17323+ /* support LSM and notify */
17324+ rbytes = 0;
17325+ /* todo: signal_pending? */
17326+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
17327+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos,
17328+ vfsub_ftest(vargs->flags, DLGT));
17329+ err = rbytes;
17330+ }
17331+ if (unlikely(err < 0))
17332+ break;
17333+
17334+ all_zero = 0;
17335+ if (len >= rbytes && rbytes == blksize) {
17336+#if 1
17337+ all_zero = !memcmp(buf, zp, rbytes);
17338+#else /* reserved for future use */
17339+ unsigned long long *ullp;
17340+ size_t n, i;
17341+
17342+ all_zero = 1;
17343+ ullp = (void *)buf;
17344+ n = rbytes / sizeof(*ullp);
17345+ i = n;
17346+ while (n-- > 0 && all_zero)
17347+ all_zero = !*ullp++;
17348+ p = (void *)ullp;
17349+ i *= sizeof(*ullp);
17350+ for (; all_zero && i < rbytes; i++)
17351+ all_zero = !*p++;
17352+#endif
17353+ }
17354+ if (!all_zero) {
17355+ wbytes = rbytes;
17356+ p = buf;
17357+ while (wbytes) {
17358+ size_t b;
17359+ /* support LSM and notify */
17360+ vfsub_args_reinit(vargs);
17361+ vfsub_ign_hinode(vargs, IN_MODIFY, hdir);
17362+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos,
17363+ vargs);
17364+ err = b;
17365+ /* todo: signal_pending? */
17366+ if (unlikely(err == -EAGAIN || err == -EINTR))
17367+ continue;
17368+ if (unlikely(err < 0))
17369+ break;
17370+ wbytes -= b;
17371+ p += b;
17372+ }
17373+ } else {
17374+ loff_t res;
17375+ LKTRLabel(hole);
17376+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
17377+ err = res;
17378+ if (unlikely(res < 0))
17379+ break;
17380+ }
17381+ len -= rbytes;
17382+ err = 0;
17383+ }
17384+
17385+ /* the last block may be a hole */
17386+ if (!err && all_zero) {
17387+ struct dentry *h_d = dst->f_dentry;
17388+ struct inode *h_i = h_d->d_inode;
17389+
17390+ LKTRLabel(last hole);
17391+ do {
17392+ /* todo: signal_pending? */
17393+ vfsub_args_reinit(vargs);
17394+ vfsub_ign_hinode(vargs, IN_MODIFY, hdir);
17395+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos, vargs);
17396+ } while (err == -EAGAIN || err == -EINTR);
17397+ if (err == 1) {
17398+ ia = (void *)buf;
17399+ ia->ia_size = dst->f_pos;
17400+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
17401+ ia->ia_file = dst;
17402+ vfsub_args_reinit(vargs);
17403+ vfsub_ign_hinode(vargs, vfsub_events_notify_change(ia),
17404+ hdir);
17405+ mutex_lock_nested(&h_i->i_mutex, AuLsc_I_CHILD2);
17406+ err = vfsub_notify_change(h_d, ia, vargs);
17407+ mutex_unlock(&h_i->i_mutex);
17408+ }
17409+ }
17410+ if (do_kfree)
17411+ kfree(buf);
17412+ else
17413+ free_page((unsigned long)buf);
17414+
17415+ out:
17416+ au_zp_free(zp);
17417+ AuTraceErr(err);
17418+ return err;
17419+}
17420diff -urN linux/fs/aufs/misc.h linux-aufs/fs/aufs/misc.h
17421--- linux/fs/aufs/misc.h 1970-01-01 01:00:00.000000000 +0100
17422+++ linux-aufs/fs/aufs/misc.h 2009-03-12 16:18:04.000000000 +0100
17423@@ -0,0 +1,244 @@
17424+/*
17425+ * Copyright (C) 2005-2009 Junjiro Okajima
17426+ *
17427+ * This program, aufs is free software; you can redistribute it and/or modify
17428+ * it under the terms of the GNU General Public License as published by
17429+ * the Free Software Foundation; either version 2 of the License, or
17430+ * (at your option) any later version.
17431+ *
17432+ * This program is distributed in the hope that it will be useful,
17433+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17434+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17435+ * GNU General Public License for more details.
17436+ *
17437+ * You should have received a copy of the GNU General Public License
17438+ * along with this program; if not, write to the Free Software
17439+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17440+ */
17441+
17442+/*
17443+ * $Id$
17444+ */
17445+
17446+#ifndef __AUFS_MISC_H__
17447+#define __AUFS_MISC_H__
17448+
17449+#ifdef __KERNEL__
17450+
17451+#include <linux/fs.h>
17452+#include <linux/namei.h>
17453+#include <linux/aufs_type.h>
17454+
17455+/* ---------------------------------------------------------------------- */
17456+
17457+typedef unsigned int au_gen_t;
17458+/* see linux/include/linux/jiffies.h */
17459+#define AuGenYounger(a, b) ((int)(b) - (int)(a) < 0)
17460+#define AuGenOlder(a, b) AufsGenYounger(b, a)
17461+
17462+/* ---------------------------------------------------------------------- */
17463+
17464+struct au_splhead {
17465+ spinlock_t spin;
17466+ struct list_head head;
17467+};
17468+
17469+static inline void au_spl_init(struct au_splhead *spl)
17470+{
17471+ spin_lock_init(&spl->spin);
17472+ INIT_LIST_HEAD(&spl->head);
17473+}
17474+
17475+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
17476+{
17477+ spin_lock(&spl->spin);
17478+ list_add(list, &spl->head);
17479+ spin_unlock(&spl->spin);
17480+}
17481+
17482+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
17483+{
17484+ spin_lock(&spl->spin);
17485+ list_del(list);
17486+ spin_unlock(&spl->spin);
17487+}
17488+
17489+/* ---------------------------------------------------------------------- */
17490+
17491+struct au_rwsem {
17492+ struct rw_semaphore rwsem;
17493+#ifdef CONFIG_AUFS_DEBUG
17494+ atomic_t rcnt;
17495+#endif
17496+};
17497+
17498+#ifdef CONFIG_AUFS_DEBUG
17499+#define AuDbgRcntInit(rw) do { \
17500+ atomic_set(&(rw)->rcnt, 0); \
17501+ smp_mb(); /* atomic set */ \
17502+} while (0)
17503+
17504+#define AuDbgRcntInc(rw) atomic_inc_return(&(rw)->rcnt)
17505+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
17506+#else
17507+#define AuDbgRcntInit(rw) do {} while (0)
17508+#define AuDbgRcntInc(rw) do {} while (0)
17509+#define AuDbgRcntDec(rw) do {} while (0)
17510+#endif /* CONFIG_AUFS_DEBUG */
17511+
17512+#define au_rwsem_destroy(rw) AuDebugOn(rwsem_is_locked(&(rw)->rwsem))
17513+
17514+static inline void au_rw_init_nolock(struct au_rwsem *rw)
17515+{
17516+ AuDbgRcntInit(rw);
17517+ init_rwsem(&rw->rwsem);
17518+}
17519+
17520+static inline void au_rw_init_wlock(struct au_rwsem *rw)
17521+{
17522+ au_rw_init_nolock(rw);
17523+ down_write(&rw->rwsem);
17524+}
17525+
17526+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
17527+ unsigned int lsc)
17528+{
17529+ au_rw_init_nolock(rw);
17530+ down_write_nested(&rw->rwsem, lsc);
17531+}
17532+
17533+static inline void au_rw_read_lock(struct au_rwsem *rw)
17534+{
17535+ down_read(&rw->rwsem);
17536+ AuDbgRcntInc(rw);
17537+}
17538+
17539+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
17540+{
17541+ down_read_nested(&rw->rwsem, lsc);
17542+ AuDbgRcntInc(rw);
17543+}
17544+
17545+static inline void au_rw_read_unlock(struct au_rwsem *rw)
17546+{
17547+ AuDbgRcntDec(rw);
17548+ up_read(&rw->rwsem);
17549+}
17550+
17551+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
17552+{
17553+ AuDbgRcntInc(rw);
17554+ downgrade_write(&rw->rwsem);
17555+}
17556+
17557+static inline void au_rw_write_lock(struct au_rwsem *rw)
17558+{
17559+ down_write(&rw->rwsem);
17560+}
17561+
17562+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
17563+ unsigned int lsc)
17564+{
17565+ down_write_nested(&rw->rwsem, lsc);
17566+}
17567+
17568+static inline void au_rw_write_unlock(struct au_rwsem *rw)
17569+{
17570+ up_write(&rw->rwsem);
17571+}
17572+
17573+/* why is not _nested version defined */
17574+static inline int au_rw_read_trylock(struct au_rwsem *rw)
17575+{
17576+ int ret = down_read_trylock(&rw->rwsem);
17577+ if (ret)
17578+ AuDbgRcntInc(rw);
17579+ return ret;
17580+}
17581+
17582+static inline int au_rw_write_trylock(struct au_rwsem *rw)
17583+{
17584+ return down_write_trylock(&rw->rwsem);
17585+}
17586+
17587+#undef AuDbgRcntInit
17588+#undef AuDbgRcntInc
17589+#undef AuDbgRcntDec
17590+
17591+/* to debug easier, do not make them inlined functions */
17592+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
17593+#define AuRwMustAnyLock(rw) AuDebugOn(down_write_trylock(&(rw)->rwsem))
17594+#ifdef CONFIG_AUFS_DEBUG
17595+#define AuRwMustReadLock(rw) do { \
17596+ AuRwMustAnyLock(rw); \
17597+ AuDebugOn(!atomic_read(&(rw)->rcnt)); \
17598+} while (0)
17599+
17600+#define AuRwMustWriteLock(rw) do { \
17601+ AuRwMustAnyLock(rw); \
17602+ AuDebugOn(atomic_read(&(rw)->rcnt)); \
17603+} while (0)
17604+#else
17605+#define AuRwMustReadLock(rw) AuRwMustAnyLock(rw)
17606+#define AuRwMustWriteLock(rw) AuRwMustAnyLock(rw)
17607+#endif /* CONFIG_AUFS_DEBUG */
17608+
17609+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
17610+static inline void prefix##_read_lock(param) \
17611+{ au_rw_read_lock(&(rwsem)); } \
17612+static inline void prefix##_write_lock(param) \
17613+{ au_rw_write_lock(&(rwsem)); } \
17614+static inline int prefix##_read_trylock(param) \
17615+{ return au_rw_read_trylock(&(rwsem)); } \
17616+static inline int prefix##_write_trylock(param) \
17617+{ return au_rw_write_trylock(&(rwsem)); }
17618+/* static inline void prefix##_read_trylock_nested(param, lsc)
17619+{au_rw_read_trylock_nested(&(rwsem, lsc));}
17620+static inline void prefix##_write_trylock_nestd(param, lsc)
17621+{au_rw_write_trylock_nested(&(rwsem), nested);} */
17622+
17623+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
17624+static inline void prefix##_read_unlock(param) \
17625+{ au_rw_read_unlock(&(rwsem)); } \
17626+static inline void prefix##_write_unlock(param) \
17627+{ au_rw_write_unlock(&(rwsem)); } \
17628+static inline void prefix##_downgrade_lock(param) \
17629+{ au_rw_dgrade_lock(&(rwsem)); }
17630+
17631+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
17632+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
17633+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
17634+
17635+/* ---------------------------------------------------------------------- */
17636+
17637+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
17638+
17639+struct au_nd_store {
17640+ unsigned int flags;
17641+ struct path path;
17642+ struct open_intent intent;
17643+};
17644+struct au_sbinfo;
17645+void au_nd_store(struct au_nd_store *store, struct nameidata *nd,
17646+ struct au_sbinfo *sbinfo);
17647+void au_nd_revert(struct au_nd_store *store, struct nameidata *nd,
17648+ struct au_sbinfo *sbinfo);
17649+
17650+struct nameidata *au_dup_nd(struct au_sbinfo *sbinfo, struct nameidata *dst,
17651+ struct nameidata *src);
17652+
17653+struct nameidata *au_fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
17654+ struct super_block *sb, aufs_bindex_t bindex);
17655+void au_fake_dm_release(struct nameidata *fake_nd);
17656+struct vfsub_args;
17657+int au_h_create(struct inode *h_dir, struct dentry *h_dentry, int mode,
17658+ struct vfsub_args *vargs, struct nameidata *nd,
17659+ struct vfsmount *nfsmnt);
17660+
17661+struct au_hinode;
17662+int au_copy_file(struct file *dst, struct file *src, loff_t len,
17663+ struct au_hinode *hdir, struct super_block *sb,
17664+ struct vfsub_args *vargs);
17665+
17666+#endif /* __KERNEL__ */
17667+#endif /* __AUFS_MISC_H__ */
17668diff -urN linux/fs/aufs/module.c linux-aufs/fs/aufs/module.c
17669--- linux/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
17670+++ linux-aufs/fs/aufs/module.c 2009-03-12 16:18:04.000000000 +0100
17671@@ -0,0 +1,269 @@
17672+/*
17673+ * Copyright (C) 2005-2009 Junjiro Okajima
17674+ *
17675+ * This program, aufs is free software; you can redistribute it and/or modify
17676+ * it under the terms of the GNU General Public License as published by
17677+ * the Free Software Foundation; either version 2 of the License, or
17678+ * (at your option) any later version.
17679+ *
17680+ * This program is distributed in the hope that it will be useful,
17681+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17682+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17683+ * GNU General Public License for more details.
17684+ *
17685+ * You should have received a copy of the GNU General Public License
17686+ * along with this program; if not, write to the Free Software
17687+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17688+ */
17689+
17690+/*
17691+ * module global variables and operations
17692+ *
17693+ * $Id$
17694+ */
17695+
17696+#include <linux/module.h>
17697+#include "aufs.h"
17698+
17699+/* ---------------------------------------------------------------------- */
17700+
17701+/*
17702+ * aufs caches
17703+ */
17704+struct kmem_cache *au_cachep[AuCache_Last];
17705+static int __init create_cache(void)
17706+{
17707+ au_cachep[AuCache_DINFO] = AuCache(au_dinfo);
17708+ if (au_cachep[AuCache_DINFO])
17709+ au_cachep[AuCache_ICNTNR] = AuCache(aufs_icntnr);
17710+ if (au_cachep[AuCache_ICNTNR])
17711+ au_cachep[AuCache_FINFO] = AuCache(au_finfo);
17712+ if (au_cachep[AuCache_FINFO])
17713+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
17714+ if (au_cachep[AuCache_VDIR])
17715+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
17716+ if (au_cachep[AuCache_DEHSTR])
17717+ return 0;
17718+
17719+ return -ENOMEM;
17720+}
17721+
17722+static void destroy_cache(void)
17723+{
17724+ int i;
17725+ for (i = 0; i < AuCache_Last; i++)
17726+ if (au_cachep[i]) {
17727+ kmem_cache_destroy(au_cachep[i]);
17728+ au_cachep[i] = NULL;
17729+ }
17730+}
17731+
17732+/* ---------------------------------------------------------------------- */
17733+
17734+char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
17735+int au_dir_roflags;
17736+
17737+/*
17738+ * functions for module interface.
17739+ */
17740+MODULE_LICENSE("GPL");
17741+/* MODULE_LICENSE("GPL v2"); */
17742+MODULE_AUTHOR("Junjiro Okajima");
17743+MODULE_DESCRIPTION(AUFS_NAME " -- Another unionfs");
17744+MODULE_VERSION(AUFS_VERSION);
17745+
17746+/* it should be 'byte', but param_set_byte() prints it by "%c" */
17747+short aufs_nwkq = AUFS_NWKQ_DEF;
17748+MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
17749+module_param_named(nwkq, aufs_nwkq, short, S_IRUGO);
17750+
17751+int sysaufs_brs;
17752+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
17753+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
17754+
17755+/* ---------------------------------------------------------------------- */
17756+
17757+static int __init aufs_init(void)
17758+{
17759+ int err, i;
17760+ char *p;
17761+
17762+ au_debug_init();
17763+#ifdef CONFIG_AUFS_INO_T_64
17764+ BUILD_BUG_ON(sizeof(ino_t) != sizeof(long long));
17765+#else
17766+ BUILD_BUG_ON(sizeof(ino_t) != sizeof(int));
17767+#endif
17768+
17769+ p = au_esc_chars;
17770+ for (i = 1; i <= ' '; i++)
17771+ *p++ = i;
17772+ *p++ = '\\';
17773+ *p++ = '\x7f';
17774+ *p = 0;
17775+
17776+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
17777+
17778+ err = -EINVAL;
17779+ if (unlikely(aufs_nwkq <= 0))
17780+ goto out;
17781+
17782+ err = sysaufs_init();
17783+ if (unlikely(err))
17784+ goto out;
17785+ err = au_wkq_init();
17786+ if (unlikely(err))
17787+ goto out_sysaufs;
17788+ err = au_inotify_init();
17789+ if (unlikely(err))
17790+ goto out_wkq;
17791+ err = au_sysrq_init();
17792+ if (unlikely(err))
17793+ goto out_inotify;
17794+
17795+ err = create_cache();
17796+ if (unlikely(err))
17797+ goto out_sysrq;
17798+
17799+ err = register_filesystem(&aufs_fs_type);
17800+ if (unlikely(err))
17801+ goto out_cache;
17802+ pr_info(AUFS_NAME " " AUFS_VERSION "\n");
17803+ return 0; /* success */
17804+
17805+ out_cache:
17806+ destroy_cache();
17807+ out_sysrq:
17808+ au_sysrq_fin();
17809+ out_inotify:
17810+ au_inotify_fin();
17811+ out_wkq:
17812+ au_wkq_fin();
17813+ out_sysaufs:
17814+ sysaufs_fin();
17815+ out:
17816+ AuTraceErr(err);
17817+ return err;
17818+}
17819+
17820+static void __exit aufs_exit(void)
17821+{
17822+ unregister_filesystem(&aufs_fs_type);
17823+ destroy_cache();
17824+
17825+ au_sysrq_fin();
17826+ au_inotify_fin();
17827+ au_wkq_fin();
17828+ sysaufs_fin();
17829+}
17830+
17831+module_init(aufs_init);
17832+module_exit(aufs_exit);
17833+
17834+/* ---------------------------------------------------------------------- */
17835+
17836+/* fake Kconfig */
17837+#if 1
17838+
17839+#if AUFS_BRANCH_MAX > 511 && PAGE_SIZE > 4096
17840+#warning pagesize is larger than 4kb, \
17841+ CONFIG_AUFS_BRANCH_MAX_511 or smaller is recommended.
17842+#endif
17843+
17844+#ifdef CONFIG_AUFS_STAT
17845+#ifndef CONFIG_SYSFS
17846+#error CONFIG_AUFS_STAT requires CONFIG_SYSFS.
17847+#endif
17848+#endif /* CONFIG_AUFS_STAT */
17849+
17850+#ifdef CONFIG_AUFS_SYSAUFS
17851+#warning CONFIG_AUFS_SYSAUFS is unnecessary for linux-2.6.25 and later.
17852+#endif
17853+
17854+#ifdef CONFIG_AUFS_HINOTIFY
17855+#ifndef CONFIG_INOTIFY
17856+#error enable CONFIG_INOTIFY to use CONFIG_AUFS_HINOTIFY.
17857+#endif
17858+#endif /* CONFIG_AUFS_HINOTIFY */
17859+
17860+#ifdef CONFIG_AUFS_EXPORT
17861+#if !defined(CONFIG_EXPORTFS) && !defined(CONFIG_EXPORTFS_MODULE)
17862+#error CONFIG_AUFS_EXPORT requires CONFIG_EXPORTFS
17863+#endif
17864+#if defined(CONFIG_EXPORTFS_MODULE) && defined(CONFIG_AUFS)
17865+#error need CONFIG_EXPORTFS = y to link aufs statically with CONFIG_AUFS_EXPORT.
17866+#endif
17867+#endif /* CONFIG_AUFS_EXPORT */
17868+
17869+#ifdef CONFIG_AUFS_SEC_PERM_PATCH
17870+#ifndef CONFIG_SECURITY
17871+#warning AUFS_SEC_PERM_PATCH is unnecessary since SECURITY is disabled.
17872+#endif
17873+#ifdef CONFIG_AUFS
17874+#warning AUFS_SEC_PERM_PATCH is unnecessary since AUFS is not a module.
17875+#endif
17876+#endif
17877+
17878+#ifdef CONFIG_AUFS_LHASH_PATCH
17879+#if !defined(CONFIG_NFS_FS) && !defined(CONFIG_NFS_FS_MODULE)
17880+#warning CONFIG_AUFS_LHASH_PATCH is unnecessary since CONFIG_NFS_FS is disabled.
17881+#endif
17882+#endif
17883+
17884+#ifdef CONFIG_AUFS_PUT_FILP_PATCH
17885+#ifndef CONFIG_NFS_V4
17886+#warning AUFS_PUT_FILP_PATCH is unnecessary since NFS_V4 is disabled.
17887+#endif
17888+#ifdef CONFIG_AUFS
17889+#warning AUFS_PUT_FILP_PATCH is unnecessary since AUFS is not a module.
17890+#endif
17891+#endif /* CONFIG_AUFS_PUT_FILP_PATCH */
17892+
17893+#ifdef CONFIG_AUFS_FSYNC_SUPER_PATCH
17894+#ifdef CONFIG_AUFS
17895+#warning AUFS_FSYNC_SUPER_PATCH is unnecessary since AUFS is not a module.
17896+#endif
17897+#endif
17898+
17899+#ifdef CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH
17900+#ifdef CONFIG_AUFS
17901+#warning AUFS_DENY_WRITE_ACCESS_PATCH is unnecessary since AUFS is not a module.
17902+#endif
17903+#endif
17904+
17905+#ifdef CONFIG_AUFS_KSIZE_PATCH
17906+#warning CONFIG_AUFS_KSIZE_PATCH is unnecessary for linux-2.6.22 and later.
17907+#endif
17908+
17909+#ifdef CONFIG_AUFS_WORKAROUND_FUSE
17910+#if !defined(CONFIG_FUSE_FS) && !defined(CONFIG_FUSE_FS_MODULE)
17911+#warning CONFIG_AUFS_WORKAROUND_FUSE is enabled while FUSE is disabled.
17912+#endif
17913+#endif
17914+
17915+#ifdef CONFIG_AUFS_DEBUG_LOCK
17916+#ifndef CONFIG_AUFS_MAGIC_SYSRQ
17917+#warning CONFIG_AUFS_DEBUG_LOCK is enabled but CONFIG_AUFS_MAGIC_SYSRQ.
17918+#endif
17919+#endif
17920+
17921+#ifdef CONFIG_AUFS_COMPAT
17922+#warning CONFIG_AUFS_COMPAT will be removed in the near future.
17923+#endif
17924+
17925+#ifdef CONFIG_AUFS_UNIONFS23_PATCH
17926+#ifndef CONFIG_AUFS_UNIONFS22_PATCH
17927+#error mis-config. AUFS_UNIONFS23_PATCH is enabled but AUFS_UNIONFS22_PATCH.
17928+#endif
17929+#ifndef CONFIG_AUFS_SPLICE_PATCH
17930+#error mis-config. AUFS_UNIONFS23_PATCH is enabled but AUFS_SPLICE_PATCH.
17931+#endif
17932+#endif
17933+
17934+#ifdef CONFIG_DEBUG_PROVE_LOCKING
17935+#if MAX_LOCKDEP_SUBCLASSES < AuLsc_I_End
17936+#warning lockdep will not work since aufs uses deeper locks.
17937+#endif
17938+#endif
17939+
17940+#endif
17941diff -urN linux/fs/aufs/module.h linux-aufs/fs/aufs/module.h
17942--- linux/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
17943+++ linux-aufs/fs/aufs/module.h 2009-03-12 16:18:04.000000000 +0100
17944@@ -0,0 +1,73 @@
17945+/*
17946+ * Copyright (C) 2005-2009 Junjiro Okajima
17947+ *
17948+ * This program, aufs is free software; you can redistribute it and/or modify
17949+ * it under the terms of the GNU General Public License as published by
17950+ * the Free Software Foundation; either version 2 of the License, or
17951+ * (at your option) any later version.
17952+ *
17953+ * This program is distributed in the hope that it will be useful,
17954+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17955+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17956+ * GNU General Public License for more details.
17957+ *
17958+ * You should have received a copy of the GNU General Public License
17959+ * along with this program; if not, write to the Free Software
17960+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17961+ */
17962+
17963+/*
17964+ * module initialization and module-global
17965+ *
17966+ * $Id$
17967+ */
17968+
17969+#ifndef __AUFS_MODULE_H__
17970+#define __AUFS_MODULE_H__
17971+
17972+#ifdef __KERNEL__
17973+
17974+/* module parameters */
17975+extern short aufs_nwkq;
17976+extern int sysaufs_brs;
17977+
17978+/* ---------------------------------------------------------------------- */
17979+
17980+extern char au_esc_chars[];
17981+extern int au_dir_roflags;
17982+
17983+/* kmem cache */
17984+enum {
17985+ AuCache_DINFO,
17986+ AuCache_ICNTNR,
17987+ AuCache_FINFO,
17988+ AuCache_VDIR,
17989+ AuCache_DEHSTR,
17990+#ifdef CONFIG_AUFS_HINOTIFY
17991+ AuCache_HINOTIFY,
17992+#endif
17993+ AuCache_Last
17994+};
17995+
17996+extern struct kmem_cache *au_cachep[];
17997+
17998+#define AuCacheArgs(type, sz) (type), (sz), 0, SLAB_RECLAIM_ACCOUNT, NULL
17999+#define AuCache(type) \
18000+ kmem_cache_create(AuCacheArgs(#type, sizeof(struct type)))
18001+
18002+/* ---------------------------------------------------------------------- */
18003+
18004+#define AuCacheFuncs(name, index) \
18005+static inline void *au_cache_alloc_##name(void) \
18006+{ return kmem_cache_alloc(au_cachep[index], GFP_NOFS); } \
18007+static inline void au_cache_free_##name(void *p) \
18008+{ kmem_cache_free(au_cachep[index], p); }
18009+
18010+AuCacheFuncs(dinfo, AuCache_DINFO);
18011+AuCacheFuncs(icntnr, AuCache_ICNTNR);
18012+AuCacheFuncs(finfo, AuCache_FINFO);
18013+AuCacheFuncs(vdir, AuCache_VDIR);
18014+AuCacheFuncs(dehstr, AuCache_DEHSTR);
18015+
18016+#endif /* __KERNEL__ */
18017+#endif /* __AUFS_MODULE_H__ */
18018diff -urN linux/fs/aufs/opts.c linux-aufs/fs/aufs/opts.c
18019--- linux/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
18020+++ linux-aufs/fs/aufs/opts.c 2009-03-12 16:18:04.000000000 +0100
18021@@ -0,0 +1,1613 @@
18022+/*
18023+ * Copyright (C) 2005-2009 Junjiro Okajima
18024+ *
18025+ * This program, aufs is free software; you can redistribute it and/or modify
18026+ * it under the terms of the GNU General Public License as published by
18027+ * the Free Software Foundation; either version 2 of the License, or
18028+ * (at your option) any later version.
18029+ *
18030+ * This program is distributed in the hope that it will be useful,
18031+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18032+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18033+ * GNU General Public License for more details.
18034+ *
18035+ * You should have received a copy of the GNU General Public License
18036+ * along with this program; if not, write to the Free Software
18037+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18038+ */
18039+
18040+/*
18041+ * mount options/flags
18042+ *
18043+ * $Id$
18044+ */
18045+
18046+#include <linux/types.h> /* a distribution requires */
18047+#include <linux/parser.h>
18048+#include "aufs.h"
18049+
18050+/* ---------------------------------------------------------------------- */
18051+
18052+enum {
18053+ Opt_br,
18054+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
18055+ Opt_idel, Opt_imod, Opt_ireorder,
18056+ Opt_dirwh, Opt_rdcache, Opt_deblk, Opt_nhash, Opt_rendir,
18057+ Opt_xino, Opt_zxino, Opt_noxino,
18058+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
18059+ Opt_trunc_xino_path, Opt_itrunc_xino,
18060+ Opt_xinodir,
18061+ Opt_trunc_xib, Opt_notrunc_xib,
18062+ Opt_dirperm1, Opt_nodirperm1,
18063+ Opt_shwh, Opt_noshwh,
18064+ Opt_plink, Opt_noplink, Opt_list_plink, Opt_clean_plink,
18065+ Opt_udba,
18066+ /* Opt_lock, Opt_unlock, */
18067+ Opt_cmd, Opt_cmd_args,
18068+ Opt_diropq_a, Opt_diropq_w,
18069+ Opt_warn_perm, Opt_nowarn_perm,
18070+ Opt_wbr_copyup, Opt_wbr_create,
18071+ Opt_coo,
18072+ Opt_dlgt, Opt_nodlgt,
18073+ Opt_refrof, Opt_norefrof,
18074+ Opt_verbose, Opt_noverbose,
18075+ Opt_sum, Opt_nosum, Opt_wsum,
18076+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
18077+};
18078+
18079+static match_table_t options = {
18080+ {Opt_br, "br=%s"},
18081+ {Opt_br, "br:%s"},
18082+
18083+ {Opt_add, "add=%d:%s"},
18084+ {Opt_add, "add:%d:%s"},
18085+ {Opt_add, "ins=%d:%s"},
18086+ {Opt_add, "ins:%d:%s"},
18087+ {Opt_append, "append=%s"},
18088+ {Opt_append, "append:%s"},
18089+ {Opt_prepend, "prepend=%s"},
18090+ {Opt_prepend, "prepend:%s"},
18091+
18092+ {Opt_del, "del=%s"},
18093+ {Opt_del, "del:%s"},
18094+ /* {Opt_idel, "idel:%d"}, */
18095+ {Opt_mod, "mod=%s"},
18096+ {Opt_mod, "mod:%s"},
18097+ {Opt_imod, "imod:%d:%s"},
18098+
18099+ {Opt_dirwh, "dirwh=%d"},
18100+ {Opt_dirwh, "dirwh:%d"},
18101+
18102+ {Opt_xino, "xino=%s"},
18103+ {Opt_xino, "xino:%s"},
18104+#if 0 /* def CONFIG_AUFS_EXPORT */ /* reserved for futur use */
18105+ {Opt_xinodir, "xinodir=%s"},
18106+ {Opt_xinodir, "xinodir:%s"},
18107+#endif
18108+ {Opt_noxino, "noxino"},
18109+ {Opt_trunc_xino, "trunc_xino"},
18110+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
18111+ {Opt_notrunc_xino, "notrunc_xino"},
18112+ {Opt_trunc_xino_path, "trunc_xino=%s"},
18113+ {Opt_trunc_xino_path, "trunc_xino:%s"},
18114+ {Opt_itrunc_xino, "itrunc_xino=%d"},
18115+ {Opt_itrunc_xino, "itrunc_xino:%d"},
18116+ /* {Opt_zxino, "zxino=%s"}, */
18117+ {Opt_trunc_xib, "trunc_xib"},
18118+ {Opt_notrunc_xib, "notrunc_xib"},
18119+
18120+ {Opt_plink, "plink"},
18121+ {Opt_noplink, "noplink"},
18122+#ifdef CONFIG_AUFS_DEBUG
18123+ {Opt_list_plink, "list_plink"},
18124+#endif
18125+ {Opt_clean_plink, "clean_plink"},
18126+
18127+ {Opt_udba, "udba=%s"},
18128+
18129+ {Opt_diropq_a, "diropq=always"},
18130+ {Opt_diropq_a, "diropq=a"},
18131+ {Opt_diropq_w, "diropq=whiteouted"},
18132+ {Opt_diropq_w, "diropq=w"},
18133+
18134+ {Opt_warn_perm, "warn_perm"},
18135+ {Opt_nowarn_perm, "nowarn_perm"},
18136+
18137+#ifdef CONFIG_AUFS_DLGT
18138+ {Opt_dlgt, "dlgt"},
18139+ {Opt_dirperm1, "dirperm1"},
18140+#endif
18141+ {Opt_nodlgt, "nodlgt"},
18142+ {Opt_nodirperm1, "nodirperm1"},
18143+
18144+#ifdef CONFIG_AUFS_SHWH
18145+ {Opt_shwh, "shwh"},
18146+#endif
18147+ {Opt_noshwh, "noshwh"},
18148+
18149+ {Opt_rendir, "rendir=%d"},
18150+ {Opt_rendir, "rendir:%d"},
18151+
18152+ {Opt_refrof, "refrof"},
18153+ {Opt_norefrof, "norefrof"},
18154+
18155+ {Opt_verbose, "verbose"},
18156+ {Opt_verbose, "v"},
18157+ {Opt_noverbose, "noverbose"},
18158+ {Opt_noverbose, "quiet"},
18159+ {Opt_noverbose, "q"},
18160+ {Opt_noverbose, "silent"},
18161+
18162+ {Opt_sum, "sum"},
18163+ {Opt_nosum, "nosum"},
18164+ {Opt_wsum, "wsum"},
18165+
18166+ {Opt_rdcache, "rdcache=%d"},
18167+ {Opt_rdcache, "rdcache:%d"},
18168+
18169+ {Opt_coo, "coo=%s"},
18170+
18171+ {Opt_wbr_create, "create=%s"},
18172+ {Opt_wbr_create, "create:%s"},
18173+ {Opt_wbr_create, "create_policy=%s"},
18174+ {Opt_wbr_create, "create_policy:%s"},
18175+ {Opt_wbr_copyup, "cpup=%s"},
18176+ {Opt_wbr_copyup, "cpup:%s"},
18177+ {Opt_wbr_copyup, "copyup=%s"},
18178+ {Opt_wbr_copyup, "copyup:%s"},
18179+ {Opt_wbr_copyup, "copyup_policy=%s"},
18180+ {Opt_wbr_copyup, "copyup_policy:%s"},
18181+
18182+ /* internal use for the scripts */
18183+ {Opt_ignore_silent, "si=%s"},
18184+
18185+#if 0 /* reserved for future use */
18186+ {Opt_deblk, "deblk=%d"},
18187+ {Opt_deblk, "deblk:%d"},
18188+ {Opt_nhash, "nhash=%d"},
18189+ {Opt_nhash, "nhash:%d"},
18190+#endif
18191+
18192+ {Opt_br, "dirs=%s"},
18193+ {Opt_ignore, "debug=%d"},
18194+ {Opt_ignore, "delete=whiteout"},
18195+ {Opt_ignore, "delete=all"},
18196+ {Opt_ignore, "imap=%s"},
18197+
18198+ {Opt_err, NULL}
18199+};
18200+
18201+/* ---------------------------------------------------------------------- */
18202+
18203+static const char *au_parser_pattern(int val, struct match_token *token)
18204+{
18205+ while (token->pattern) {
18206+ if (token->token == val)
18207+ return token->pattern;
18208+ token++;
18209+ }
18210+ BUG();
18211+ return "??";
18212+}
18213+
18214+/* ---------------------------------------------------------------------- */
18215+
18216+#define RW "rw"
18217+#define RO "ro"
18218+#define WH "wh"
18219+#define RR "rr"
18220+#define NoLinkWH "nolwh"
18221+
18222+static match_table_t brperms = {
18223+ {AuBrPerm_RR, RR},
18224+ {AuBrPerm_RO, RO},
18225+ {AuBrPerm_RW, RW},
18226+
18227+ {AuBrPerm_RRWH, RR "+" WH},
18228+ {AuBrPerm_ROWH, RO "+" WH},
18229+ {AuBrPerm_RWNoLinkWH, RW "+" NoLinkWH},
18230+
18231+ {AuBrPerm_ROWH, "nfsro"},
18232+ {AuBrPerm_RO, NULL}
18233+};
18234+
18235+static noinline_for_stack int br_perm_val(char *perm)
18236+{
18237+ int val;
18238+ substring_t args[MAX_OPT_ARGS];
18239+
18240+ AuDebugOn(!perm || !*perm);
18241+ LKTRTrace("perm %s\n", perm);
18242+ val = match_token(perm, brperms, args);
18243+ AuTraceErr(val);
18244+ return val;
18245+}
18246+
18247+const char *au_optstr_br_perm(int brperm)
18248+{
18249+ return au_parser_pattern(brperm, (void *)brperms);
18250+}
18251+
18252+/* ---------------------------------------------------------------------- */
18253+
18254+static match_table_t udbalevel = {
18255+ {AuOpt_UDBA_REVAL, "reval"},
18256+#ifdef CONFIG_AUFS_HINOTIFY
18257+ {AuOpt_UDBA_INOTIFY, "inotify"},
18258+#endif
18259+ {AuOpt_UDBA_NONE, "none"},
18260+ {-1, NULL}
18261+};
18262+
18263+static noinline_for_stack int udba_val(char *str)
18264+{
18265+ substring_t args[MAX_OPT_ARGS];
18266+ return match_token(str, udbalevel, args);
18267+}
18268+
18269+const char *au_optstr_udba(int udba)
18270+{
18271+ return au_parser_pattern(udba, (void *)udbalevel);
18272+}
18273+
18274+/* ---------------------------------------------------------------------- */
18275+
18276+static match_table_t coolevel = {
18277+ {AuOpt_COO_NONE, "none"},
18278+ {AuOpt_COO_LEAF, "leaf"},
18279+ {AuOpt_COO_ALL, "all"},
18280+ {-1, NULL}
18281+};
18282+
18283+static noinline_for_stack int coo_val(char *str)
18284+{
18285+ substring_t args[MAX_OPT_ARGS];
18286+ return match_token(str, coolevel, args);
18287+}
18288+
18289+const char *au_optstr_coo(int coo)
18290+{
18291+ return au_parser_pattern(coo, (void *)coolevel);
18292+}
18293+
18294+/* ---------------------------------------------------------------------- */
18295+
18296+static match_table_t au_wbr_create_policy = {
18297+ {AuWbrCreate_TDP, "tdp"},
18298+ {AuWbrCreate_TDP, "top-down-parent"},
18299+ {AuWbrCreate_RR, "rr"},
18300+ {AuWbrCreate_RR, "round-robin"},
18301+ {AuWbrCreate_MFS, "mfs"},
18302+ {AuWbrCreate_MFS, "most-free-space"},
18303+ {AuWbrCreate_MFSV, "mfs:%d"},
18304+ {AuWbrCreate_MFSV, "most-free-space:%d"},
18305+
18306+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
18307+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
18308+ {AuWbrCreate_PMFS, "pmfs"},
18309+ {AuWbrCreate_PMFSV, "pmfs:%d"},
18310+
18311+ {-1, NULL}
18312+};
18313+
18314+/* cf. linux/lib/parser.c */
18315+static int au_match_ull(substring_t *s, unsigned long long *result)
18316+{
18317+ int err;
18318+ unsigned int len;
18319+ char a[32];
18320+
18321+ err = -ERANGE;
18322+ len = s->to - s->from;
18323+ if (len + 1 <= sizeof(a)) {
18324+ memcpy(a, s->from, len);
18325+ a[len] = '\0';
18326+#if 1
18327+ err = strict_strtoull(a, 0, result);
18328+#else
18329+ char *next;
18330+ *result = memparse(a, &next);
18331+ err = *result;
18332+ if (!IS_ERR((void *)err))
18333+ err = 0;
18334+#endif
18335+ }
18336+ return err;
18337+}
18338+
18339+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
18340+ struct au_opt_wbr_create *create)
18341+{
18342+ int err;
18343+ unsigned long long ull;
18344+
18345+ err = 0;
18346+ if (!au_match_ull(arg, &ull))
18347+ create->mfsrr_watermark = ull;
18348+ else {
18349+ AuErr("bad integer in %s\n", str);
18350+ err = -EINVAL;
18351+ }
18352+
18353+ AuTraceErr(err);
18354+ return err;
18355+}
18356+
18357+static int au_wbr_mfs_sec(substring_t *arg, char *str,
18358+ struct au_opt_wbr_create *create)
18359+{
18360+ int n, err;
18361+
18362+ err = 0;
18363+ if (!match_int(arg, &n) && 0 <= n)
18364+ create->mfs_second = n;
18365+ else {
18366+ AuErr("bad integer in %s\n", str);
18367+ err = -EINVAL;
18368+ }
18369+
18370+ AuTraceErr(err);
18371+ return err;
18372+}
18373+
18374+static noinline_for_stack
18375+int au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
18376+{
18377+ int err, e;
18378+ substring_t args[MAX_OPT_ARGS];
18379+
18380+ err = match_token(str, au_wbr_create_policy, args);
18381+ create->wbr_create = err;
18382+ switch (err) {
18383+ case AuWbrCreate_MFSRRV:
18384+ e = au_wbr_mfs_wmark(&args[0], str, create);
18385+ if (!e)
18386+ e = au_wbr_mfs_sec(&args[1], str, create);
18387+ if (unlikely(e))
18388+ err = e;
18389+ break;
18390+ case AuWbrCreate_MFSRR:
18391+ e = au_wbr_mfs_wmark(&args[0], str, create);
18392+ if (unlikely(e)) {
18393+ err = e;
18394+ break;
18395+ }
18396+ /*FALLTHROUGH*/
18397+ case AuWbrCreate_MFS:
18398+ case AuWbrCreate_PMFS:
18399+ create->mfs_second = AUFS_MFS_SECOND_DEF;
18400+ break;
18401+ case AuWbrCreate_MFSV:
18402+ case AuWbrCreate_PMFSV:
18403+ e = au_wbr_mfs_sec(&args[0], str, create);
18404+ if (unlikely(e))
18405+ err = e;
18406+ break;
18407+ }
18408+
18409+ return err;
18410+}
18411+
18412+const char *au_optstr_wbr_create(int wbr_create)
18413+{
18414+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
18415+}
18416+
18417+static match_table_t au_wbr_copyup_policy = {
18418+ {AuWbrCopyup_TDP, "tdp"},
18419+ {AuWbrCopyup_TDP, "top-down-parent"},
18420+ {AuWbrCopyup_BUP, "bup"},
18421+ {AuWbrCopyup_BUP, "bottom-up-parent"},
18422+ {AuWbrCopyup_BU, "bu"},
18423+ {AuWbrCopyup_BU, "bottom-up"},
18424+ {-1, NULL}
18425+};
18426+
18427+static noinline_for_stack int au_wbr_copyup_val(char *str)
18428+{
18429+ substring_t args[MAX_OPT_ARGS];
18430+ return match_token(str, au_wbr_copyup_policy, args);
18431+}
18432+
18433+const char *au_optstr_wbr_copyup(int wbr_copyup)
18434+{
18435+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
18436+}
18437+
18438+/* ---------------------------------------------------------------------- */
18439+
18440+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
18441+
18442+static void dump_opts(struct au_opts *opts)
18443+{
18444+#ifdef CONFIG_AUFS_DEBUG
18445+ /* reduce stack space */
18446+ union {
18447+ struct au_opt_add *add;
18448+ struct au_opt_del *del;
18449+ struct au_opt_mod *mod;
18450+ struct au_opt_xino *xino;
18451+ struct au_opt_xinodir *xinodir;
18452+ struct au_opt_xino_itrunc *xino_itrunc;
18453+ struct au_opt_wbr_create *create;
18454+ } u;
18455+ struct au_opt *opt;
18456+
18457+ AuTraceEnter();
18458+
18459+ opt = opts->opt;
18460+ while (/* opt < opts_tail && */ opt->type != Opt_tail) {
18461+ switch (opt->type) {
18462+ case Opt_add:
18463+ u.add = &opt->add;
18464+ LKTRTrace("add {b%d, %s, 0x%x, %p}\n",
18465+ u.add->bindex, u.add->path, u.add->perm,
18466+ u.add->nd.path.dentry);
18467+ break;
18468+ case Opt_del:
18469+ case Opt_idel:
18470+ u.del = &opt->del;
18471+ LKTRTrace("del {%s, %p}\n", u.del->path, u.del->h_root);
18472+ break;
18473+ case Opt_mod:
18474+ case Opt_imod:
18475+ u.mod = &opt->mod;
18476+ LKTRTrace("mod {%s, 0x%x, %p}\n",
18477+ u.mod->path, u.mod->perm, u.mod->h_root);
18478+ break;
18479+ case Opt_append:
18480+ u.add = &opt->add;
18481+ LKTRTrace("append {b%d, %s, 0x%x, %p}\n",
18482+ u.add->bindex, u.add->path, u.add->perm,
18483+ u.add->nd.path.dentry);
18484+ break;
18485+ case Opt_prepend:
18486+ u.add = &opt->add;
18487+ LKTRTrace("prepend {b%d, %s, 0x%x, %p}\n",
18488+ u.add->bindex, u.add->path, u.add->perm,
18489+ u.add->nd.path.dentry);
18490+ break;
18491+ case Opt_dirwh:
18492+ LKTRTrace("dirwh %d\n", opt->dirwh);
18493+ break;
18494+ case Opt_rdcache:
18495+ LKTRTrace("rdcache %d\n", opt->rdcache);
18496+ break;
18497+ case Opt_xino:
18498+ u.xino = &opt->xino;
18499+ LKTRTrace("xino {%s %.*s}\n",
18500+ u.xino->path,
18501+ AuDLNPair(u.xino->file->f_dentry));
18502+ break;
18503+ case Opt_xinodir:
18504+ u.xinodir = &opt->xinodir;
18505+ LKTRTrace("xinodir {%s %.*s}\n",
18506+ u.xinodir->name,
18507+ AuDLNPair(u.xinodir->path.dentry));
18508+ break;
18509+ case Opt_trunc_xino:
18510+ LKTRLabel(trunc_xino);
18511+ break;
18512+ case Opt_notrunc_xino:
18513+ LKTRLabel(notrunc_xino);
18514+ break;
18515+ case Opt_trunc_xino_path:
18516+ case Opt_itrunc_xino:
18517+ u.xino_itrunc = &opt->xino_itrunc;
18518+ LKTRTrace("trunc_xino %d\n", u.xino_itrunc->bindex);
18519+ break;
18520+
18521+ case Opt_noxino:
18522+ LKTRLabel(noxino);
18523+ break;
18524+ case Opt_trunc_xib:
18525+ LKTRLabel(trunc_xib);
18526+ break;
18527+ case Opt_notrunc_xib:
18528+ LKTRLabel(notrunc_xib);
18529+ break;
18530+ case Opt_dirperm1:
18531+ LKTRLabel(dirperm1);
18532+ break;
18533+ case Opt_nodirperm1:
18534+ LKTRLabel(nodirperm1);
18535+ break;
18536+ case Opt_shwh:
18537+ LKTRLabel(shwh);
18538+ break;
18539+ case Opt_noshwh:
18540+ LKTRLabel(noshwh);
18541+ break;
18542+ case Opt_plink:
18543+ LKTRLabel(plink);
18544+ break;
18545+ case Opt_noplink:
18546+ LKTRLabel(noplink);
18547+ break;
18548+ case Opt_list_plink:
18549+ LKTRLabel(list_plink);
18550+ break;
18551+ case Opt_clean_plink:
18552+ LKTRLabel(clean_plink);
18553+ break;
18554+ case Opt_udba:
18555+ LKTRTrace("udba %d, %s\n",
18556+ opt->udba, au_optstr_udba(opt->udba));
18557+ break;
18558+ case Opt_diropq_a:
18559+ LKTRLabel(diropq_a);
18560+ break;
18561+ case Opt_diropq_w:
18562+ LKTRLabel(diropq_w);
18563+ break;
18564+ case Opt_warn_perm:
18565+ LKTRLabel(warn_perm);
18566+ break;
18567+ case Opt_nowarn_perm:
18568+ LKTRLabel(nowarn_perm);
18569+ break;
18570+ case Opt_dlgt:
18571+ LKTRLabel(dlgt);
18572+ break;
18573+ case Opt_nodlgt:
18574+ LKTRLabel(nodlgt);
18575+ break;
18576+ case Opt_refrof:
18577+ LKTRLabel(refrof);
18578+ break;
18579+ case Opt_norefrof:
18580+ LKTRLabel(norefrof);
18581+ break;
18582+ case Opt_verbose:
18583+ LKTRLabel(verbose);
18584+ break;
18585+ case Opt_noverbose:
18586+ LKTRLabel(noverbose);
18587+ break;
18588+ case Opt_sum:
18589+ LKTRLabel(sum);
18590+ break;
18591+ case Opt_nosum:
18592+ LKTRLabel(nosum);
18593+ break;
18594+ case Opt_wsum:
18595+ LKTRLabel(wsum);
18596+ break;
18597+ case Opt_coo:
18598+ LKTRTrace("coo %d, %s\n",
18599+ opt->coo, au_optstr_coo(opt->coo));
18600+ break;
18601+ case Opt_wbr_create:
18602+ u.create = &opt->wbr_create;
18603+ LKTRTrace("create %d, %s\n", u.create->wbr_create,
18604+ au_optstr_wbr_create(u.create->wbr_create));
18605+ switch (u.create->wbr_create) {
18606+ case AuWbrCreate_MFSV:
18607+ case AuWbrCreate_PMFSV:
18608+ LKTRTrace("%d sec\n", u.create->mfs_second);
18609+ break;
18610+ case AuWbrCreate_MFSRR:
18611+ LKTRTrace("%llu watermark\n",
18612+ u.create->mfsrr_watermark);
18613+ break;
18614+ case AuWbrCreate_MFSRRV:
18615+ LKTRTrace("%llu watermark, %d sec\n",
18616+ u.create->mfsrr_watermark,
18617+ u.create->mfs_second);
18618+ break;
18619+ }
18620+ break;
18621+ case Opt_wbr_copyup:
18622+ LKTRTrace("copyup %d, %s\n", opt->wbr_copyup,
18623+ au_optstr_wbr_copyup(opt->wbr_copyup));
18624+ break;
18625+ default:
18626+ BUG();
18627+ }
18628+ opt++;
18629+ }
18630+#endif
18631+}
18632+
18633+void au_opts_free(struct au_opts *opts)
18634+{
18635+ struct au_opt *opt;
18636+
18637+ AuTraceEnter();
18638+
18639+ opt = opts->opt;
18640+ while (opt->type != Opt_tail) {
18641+ switch (opt->type) {
18642+ case Opt_add:
18643+ case Opt_append:
18644+ case Opt_prepend:
18645+ path_put(&opt->add.nd.path);
18646+ break;
18647+ case Opt_del:
18648+ case Opt_idel:
18649+ dput(opt->del.h_root);
18650+ break;
18651+ case Opt_mod:
18652+ case Opt_imod:
18653+ dput(opt->mod.h_root);
18654+ break;
18655+ case Opt_xino:
18656+ fput(opt->xino.file);
18657+ break;
18658+ case Opt_xinodir:
18659+ path_put(&opt->xinodir.path);
18660+ break;
18661+ }
18662+ opt++;
18663+ }
18664+}
18665+
18666+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
18667+ struct super_block *sb, aufs_bindex_t bindex)
18668+{
18669+ int err;
18670+ struct au_opt_add *add = &opt->add;
18671+ char *p;
18672+
18673+ LKTRTrace("%s, b%d\n", opt_str, bindex);
18674+
18675+ add->bindex = bindex;
18676+ add->perm = AuBrPerm_Last;
18677+ add->path = opt_str;
18678+ p = strchr(opt_str, '=');
18679+ if (p) {
18680+ *p++ = 0;
18681+ if (*p)
18682+ add->perm = br_perm_val(p);
18683+ }
18684+
18685+ /* LSM may detect it */
18686+ /* do not superio. */
18687+ err = vfsub_path_lookup(add->path, lkup_dirflags, &add->nd);
18688+ if (!err) {
18689+ if (!p /* && add->perm == AuBrPerm_Last */) {
18690+ add->perm = AuBrPerm_RO;
18691+ if (au_test_def_rr(add->nd.path.dentry->d_sb))
18692+ add->perm = AuBrPerm_RR;
18693+ if (!bindex && !(sb_flags & MS_RDONLY))
18694+ add->perm = AuBrPerm_RW;
18695+#ifdef CONFIG_AUFS_COMPAT
18696+ add->perm = AuBrPerm_RW;
18697+#endif
18698+ }
18699+ opt->type = Opt_add;
18700+ goto out;
18701+ }
18702+ AuErr("lookup failed %s (%d)\n", add->path, err);
18703+ err = -EINVAL;
18704+
18705+ out:
18706+ AuTraceErr(err);
18707+ return err;
18708+}
18709+
18710+/* called without aufs lock */
18711+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
18712+{
18713+ int err, n, token;
18714+ struct dentry *root;
18715+ struct au_opt *opt, *opt_tail;
18716+ char *opt_str, *p;
18717+ aufs_bindex_t bindex, bend;
18718+ unsigned char skipped;
18719+ union {
18720+ struct au_opt_del *del;
18721+ struct au_opt_mod *mod;
18722+ struct au_opt_xino *xino;
18723+ struct au_opt_xinodir *xinodir;
18724+ struct au_opt_xino_itrunc *xino_itrunc;
18725+ struct au_opt_wbr_create *create;
18726+ } u;
18727+ struct file *file;
18728+ /* reduce the stack space */
18729+ struct {
18730+ substring_t args[MAX_OPT_ARGS];
18731+ struct nameidata nd;
18732+ } *a;
18733+
18734+ LKTRTrace("%s, nopts %d\n", str, opts->max_opt);
18735+
18736+ err = -ENOMEM;
18737+ a = kmalloc(sizeof(*a), GFP_NOFS);
18738+ if (unlikely(!a))
18739+ goto out;
18740+
18741+ root = sb->s_root;
18742+ err = 0;
18743+ bindex = 0;
18744+ opt = opts->opt;
18745+ opt_tail = opt + opts->max_opt - 1;
18746+ opt->type = Opt_tail;
18747+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
18748+ err = -EINVAL;
18749+ token = match_token(opt_str, options, a->args);
18750+ LKTRTrace("%s, token %d, a->args[0]{%p, %p}\n",
18751+ opt_str, token, a->args[0].from, a->args[0].to);
18752+
18753+ skipped = 0;
18754+ switch (token) {
18755+ case Opt_br:
18756+ err = 0;
18757+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
18758+ && *opt_str) {
18759+ err = opt_add(opt, opt_str, opts->sb_flags, sb,
18760+ bindex++);
18761+ if (unlikely(!err && ++opt > opt_tail)) {
18762+ err = -E2BIG;
18763+ break;
18764+ }
18765+ opt->type = Opt_tail;
18766+ skipped = 1;
18767+ }
18768+ break;
18769+ case Opt_add:
18770+ if (unlikely(match_int(&a->args[0], &n))) {
18771+ AuErr("bad integer in %s\n", opt_str);
18772+ break;
18773+ }
18774+ bindex = n;
18775+ err = opt_add(opt, a->args[1].from, opts->sb_flags, sb,
18776+ bindex);
18777+ break;
18778+ case Opt_append:
18779+ err = opt_add(opt, a->args[0].from, opts->sb_flags, sb,
18780+ /*dummy bindex*/1);
18781+ if (!err)
18782+ opt->type = token;
18783+ break;
18784+ case Opt_prepend:
18785+ err = opt_add(opt, a->args[0].from, opts->sb_flags, sb,
18786+ /*bindex*/0);
18787+ if (!err)
18788+ opt->type = token;
18789+ break;
18790+ case Opt_del:
18791+ u.del = &opt->del;
18792+ u.del->path = a->args[0].from;
18793+ LKTRTrace("del path %s\n", u.del->path);
18794+ /* LSM may detect it */
18795+ /* do not superio. */
18796+ err = vfsub_path_lookup(u.del->path, lkup_dirflags,
18797+ &a->nd);
18798+ if (unlikely(err)) {
18799+ AuErr("lookup failed %s (%d)\n",
18800+ u.del->path, err);
18801+ break;
18802+ }
18803+ u.del->h_root = dget(a->nd.path.dentry);
18804+ path_put(&a->nd.path);
18805+ opt->type = token;
18806+ break;
18807+#if 0 /* reserved for future use */
18808+ case Opt_idel:
18809+ u.del = &opt->del;
18810+ u.del->path = "(indexed)";
18811+ if (unlikely(match_int(&a->args[0], &n))) {
18812+ AuErr("bad integer in %s\n", opt_str);
18813+ break;
18814+ }
18815+ bindex = n;
18816+ aufs_read_lock(root, AuLock_FLUSH);
18817+ if (bindex < 0 || au_sbend(sb) < bindex) {
18818+ AuErr("out of bounds, %d\n", bindex);
18819+ aufs_read_unlock(root, !AuLock_IR);
18820+ break;
18821+ }
18822+ err = 0;
18823+ u.del->h_root = dget(au_h_dptr(root, bindex));
18824+ opt->type = token;
18825+ aufs_read_unlock(root, !AuLock_IR);
18826+ break;
18827+#endif
18828+ case Opt_mod:
18829+ u.mod = &opt->mod;
18830+ u.mod->path = a->args[0].from;
18831+ p = strchr(u.mod->path, '=');
18832+ if (unlikely(!p)) {
18833+ AuErr("no permssion %s\n", opt_str);
18834+ break;
18835+ }
18836+ *p++ = 0;
18837+ u.mod->perm = br_perm_val(p);
18838+ LKTRTrace("mod path %s, perm 0x%x, %s\n",
18839+ u.mod->path, u.mod->perm, p);
18840+ /* LSM may detect it */
18841+ /* do not superio. */
18842+ err = vfsub_path_lookup(u.mod->path, lkup_dirflags,
18843+ &a->nd);
18844+ if (unlikely(err)) {
18845+ AuErr("lookup failed %s (%d)\n",
18846+ u.mod->path, err);
18847+ break;
18848+ }
18849+ u.mod->h_root = dget(a->nd.path.dentry);
18850+ path_put(&a->nd.path);
18851+ opt->type = token;
18852+ break;
18853+#ifdef IMOD /* reserved for future use */
18854+ case Opt_imod:
18855+ u.mod = &opt->mod;
18856+ u.mod->path = "(indexed)";
18857+ if (unlikely(match_int(&a->args[0], &n))) {
18858+ AuErr("bad integer in %s\n", opt_str);
18859+ break;
18860+ }
18861+ bindex = n;
18862+ aufs_read_lock(root, AuLock_FLUSH);
18863+ if (bindex < 0 || au_sbend(sb) < bindex) {
18864+ AuErr("out of bounds, %d\n", bindex);
18865+ aufs_read_unlock(root, !AuLock_IR);
18866+ break;
18867+ }
18868+ u.mod->perm = br_perm_val(a->args[1].from);
18869+ LKTRTrace("mod path %s, perm 0x%x, %s\n",
18870+ u.mod->path, u.mod->perm, a->args[1].from);
18871+ err = 0;
18872+ u.mod->h_root = dget(au_h_dptr(root, bindex));
18873+ opt->type = token;
18874+ aufs_read_unlock(root, !AuLock_IR);
18875+ break;
18876+#endif
18877+ case Opt_xino:
18878+ u.xino = &opt->xino;
18879+ file = au_xino_create(sb, a->args[0].from, /*silent*/0);
18880+ err = PTR_ERR(file);
18881+ if (IS_ERR(file))
18882+ break;
18883+ err = -EINVAL;
18884+ if (unlikely(file->f_dentry->d_sb == sb)) {
18885+ fput(file);
18886+ AuErr("%s must be outside\n", a->args[0].from);
18887+ break;
18888+ }
18889+ err = 0;
18890+ u.xino->file = file;
18891+ u.xino->path = a->args[0].from;
18892+ opt->type = token;
18893+ break;
18894+
18895+#if 0 /* def CONFIG_AUFS_EXPORT */ /* reserved for futur use */
18896+ case Opt_xinodir:
18897+ u.xinodir = &opt->xinodir;
18898+ u.xinodir->name = a->args[0].from;
18899+ err = vfsub_path_lookup(u.xinodir->name, lkup_dirflags,
18900+ &a->nd);
18901+ if (unlikely(err)) {
18902+ AuErr("lookup failed %s (%d)\n",
18903+ u.xinodir->name, err);
18904+ break;
18905+ }
18906+ u.xinodir->path = a->nd.path;
18907+ /* do not path_put() */
18908+ opt->type = token;
18909+ break;
18910+#endif
18911+
18912+ case Opt_trunc_xino_path:
18913+ u.xino_itrunc = &opt->xino_itrunc;
18914+ p = a->args[0].from;
18915+ LKTRTrace("trunc_xino path %s\n", p);
18916+ /* LSM may detect it */
18917+ /* do not superio. */
18918+ err = vfsub_path_lookup(p, lkup_dirflags, &a->nd);
18919+ if (unlikely(err)) {
18920+ AuErr("lookup failed %s (%d)\n", p , err);
18921+ break;
18922+ }
18923+ u.xino_itrunc->bindex = -1;
18924+ aufs_read_lock(root, AuLock_FLUSH);
18925+ bend = au_sbend(sb);
18926+ for (bindex = 0; bindex <= bend; bindex++) {
18927+ if (au_h_dptr(root, bindex)
18928+ == a->nd.path.dentry) {
18929+ u.xino_itrunc->bindex = bindex;
18930+ break;
18931+ }
18932+ }
18933+ aufs_read_unlock(root, !AuLock_IR);
18934+ path_put(&a->nd.path);
18935+ if (unlikely(u.xino_itrunc->bindex < 0)) {
18936+ AuErr("no such branch %s\n", p);
18937+ err = -EINVAL;
18938+ break;
18939+ }
18940+ opt->type = token;
18941+ break;
18942+
18943+ case Opt_itrunc_xino:
18944+ u.xino_itrunc = &opt->xino_itrunc;
18945+ if (unlikely(match_int(&a->args[0], &n))) {
18946+ AuErr("bad integer in %s\n", opt_str);
18947+ break;
18948+ }
18949+ u.xino_itrunc->bindex = n;
18950+ aufs_read_lock(root, AuLock_FLUSH);
18951+ if (n < 0 || au_sbend(sb) < n) {
18952+ AuErr("out of bounds, %d\n", n);
18953+ aufs_read_unlock(root, !AuLock_IR);
18954+ break;
18955+ }
18956+ aufs_read_unlock(root, !AuLock_IR);
18957+ err = 0;
18958+ opt->type = token;
18959+ break;
18960+
18961+ case Opt_dirwh:
18962+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
18963+ break;
18964+ err = 0;
18965+ opt->type = token;
18966+ break;
18967+
18968+ case Opt_rdcache:
18969+ if (unlikely(match_int(&a->args[0], &opt->rdcache)))
18970+ break;
18971+ err = 0;
18972+ opt->type = token;
18973+ break;
18974+
18975+ case Opt_shwh:
18976+ if (opts->sb_flags & MS_RDONLY) {
18977+ err = 0;
18978+ opt->type = token;
18979+ } else
18980+ AuErr("shwh requires ro\n");
18981+ break;
18982+
18983+ case Opt_trunc_xino:
18984+ case Opt_notrunc_xino:
18985+ case Opt_noxino:
18986+ case Opt_trunc_xib:
18987+ case Opt_notrunc_xib:
18988+ case Opt_dirperm1:
18989+ case Opt_nodirperm1:
18990+ case Opt_noshwh:
18991+ case Opt_plink:
18992+ case Opt_noplink:
18993+ case Opt_list_plink:
18994+ case Opt_clean_plink:
18995+ case Opt_diropq_a:
18996+ case Opt_diropq_w:
18997+ case Opt_warn_perm:
18998+ case Opt_nowarn_perm:
18999+ case Opt_dlgt:
19000+ case Opt_nodlgt:
19001+ case Opt_refrof:
19002+ case Opt_norefrof:
19003+ case Opt_verbose:
19004+ case Opt_noverbose:
19005+ case Opt_sum:
19006+ case Opt_nosum:
19007+ case Opt_wsum:
19008+ err = 0;
19009+ opt->type = token;
19010+ break;
19011+
19012+ case Opt_udba:
19013+ opt->udba = udba_val(a->args[0].from);
19014+ if (opt->udba >= 0) {
19015+ err = 0;
19016+ opt->type = token;
19017+ } else
19018+ AuErr("wrong value, %s\n", opt_str);
19019+ break;
19020+
19021+ case Opt_wbr_create:
19022+ u.create = &opt->wbr_create;
19023+ u.create->wbr_create
19024+ = au_wbr_create_val(a->args[0].from, u.create);
19025+ if (u.create->wbr_create >= 0) {
19026+ err = 0;
19027+ opt->type = token;
19028+ } else
19029+ AuErr("wrong value, %s\n", opt_str);
19030+ break;
19031+ case Opt_wbr_copyup:
19032+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
19033+ if (opt->wbr_copyup >= 0) {
19034+ err = 0;
19035+ opt->type = token;
19036+ } else
19037+ AuErr("wrong value, %s\n", opt_str);
19038+ break;
19039+
19040+ case Opt_coo:
19041+ opt->coo = coo_val(a->args[0].from);
19042+ if (opt->coo >= 0) {
19043+ if (opt->coo == AuOpt_COO_NONE
19044+ || !(opts->sb_flags & MS_RDONLY)) {
19045+ err = 0;
19046+ opt->type = token;
19047+ } else
19048+ AuErr("bad %s for readonly mount\n",
19049+ opt_str);
19050+ } else
19051+ AuErr("wrong value, %s\n", opt_str);
19052+ break;
19053+
19054+ case Opt_ignore:
19055+#ifndef CONFIG_AUFS_COMPAT
19056+ AuWarn("ignored %s\n", opt_str);
19057+#endif
19058+ case Opt_ignore_silent:
19059+ skipped = 1;
19060+ err = 0;
19061+ break;
19062+ case Opt_err:
19063+ AuErr("unknown option %s\n", opt_str);
19064+ break;
19065+ }
19066+
19067+ if (!err && !skipped) {
19068+ if (unlikely(++opt > opt_tail)) {
19069+ err = -E2BIG;
19070+ opt--;
19071+ opt->type = Opt_tail;
19072+ break;
19073+ }
19074+ opt->type = Opt_tail;
19075+ }
19076+ }
19077+
19078+ kfree(a);
19079+ dump_opts(opts);
19080+ if (unlikely(err))
19081+ au_opts_free(opts);
19082+
19083+ out:
19084+ AuTraceErr(err);
19085+ return err;
19086+}
19087+
19088+/*
19089+ * returns,
19090+ * plus: processed without an error
19091+ * zero: unprocessed
19092+ */
19093+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
19094+ struct au_opts *opts)
19095+{
19096+ int err;
19097+ struct au_sbinfo *sbinfo;
19098+ struct au_opt_wbr_create *create;
19099+
19100+ AuTraceEnter();
19101+
19102+ err = 1; /* handled */
19103+ sbinfo = au_sbi(sb);
19104+ switch (opt->type) {
19105+ case Opt_udba:
19106+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
19107+ sbinfo->si_mntflags |= opt->udba;
19108+ opts->given_udba |= opt->udba;
19109+ break;
19110+
19111+ case Opt_plink:
19112+ au_opt_set(sbinfo->si_mntflags, PLINK);
19113+ break;
19114+ case Opt_noplink:
19115+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
19116+ au_plink_put(sb);
19117+ au_opt_clr(sbinfo->si_mntflags, PLINK);
19118+ break;
19119+ case Opt_list_plink:
19120+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
19121+ au_plink_list(sb);
19122+ break;
19123+ case Opt_clean_plink:
19124+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
19125+ au_plink_put(sb);
19126+ break;
19127+
19128+ case Opt_diropq_a:
19129+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
19130+ break;
19131+ case Opt_diropq_w:
19132+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
19133+ break;
19134+
19135+ case Opt_dlgt:
19136+ au_opt_set(sbinfo->si_mntflags, DLGT);
19137+ break;
19138+ case Opt_nodlgt:
19139+ au_opt_clr(sbinfo->si_mntflags, DLGT);
19140+ break;
19141+
19142+ case Opt_warn_perm:
19143+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
19144+ break;
19145+ case Opt_nowarn_perm:
19146+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
19147+ break;
19148+
19149+ case Opt_refrof:
19150+ au_opt_set(sbinfo->si_mntflags, REFROF);
19151+ break;
19152+ case Opt_norefrof:
19153+ /* au_opt_set(sbinfo->si_mntflags, COO_LEAF); */
19154+ au_opt_clr(sbinfo->si_mntflags, REFROF);
19155+ break;
19156+
19157+ case Opt_verbose:
19158+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
19159+ break;
19160+ case Opt_noverbose:
19161+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
19162+ break;
19163+
19164+ case Opt_sum:
19165+ au_opt_set(sbinfo->si_mntflags, SUM);
19166+ break;
19167+ case Opt_wsum:
19168+ au_opt_clr(sbinfo->si_mntflags, SUM);
19169+ au_opt_set(sbinfo->si_mntflags, SUM_W);
19170+ case Opt_nosum:
19171+ au_opt_clr(sbinfo->si_mntflags, SUM);
19172+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
19173+ break;
19174+
19175+ case Opt_wbr_create:
19176+ create = &opt->wbr_create;
19177+ if (sbinfo->si_wbr_create_ops->fin) {
19178+ err = sbinfo->si_wbr_create_ops->fin(sb);
19179+ if (!err)
19180+ err = 1;
19181+ }
19182+ sbinfo->si_wbr_create = create->wbr_create;
19183+ sbinfo->si_wbr_create_ops
19184+ = au_wbr_create_ops + create->wbr_create;
19185+ switch (create->wbr_create) {
19186+ case AuWbrCreate_MFSRRV:
19187+ case AuWbrCreate_MFSRR:
19188+ sbinfo->si_wbr_mfs.mfsrr_watermark
19189+ = create->mfsrr_watermark;
19190+ /*FALLTHROUGH*/
19191+ case AuWbrCreate_MFS:
19192+ case AuWbrCreate_MFSV:
19193+ case AuWbrCreate_PMFS:
19194+ case AuWbrCreate_PMFSV:
19195+ sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
19196+ break;
19197+ }
19198+ if (sbinfo->si_wbr_create_ops->init)
19199+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
19200+ break;
19201+ case Opt_wbr_copyup:
19202+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
19203+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
19204+ break;
19205+
19206+ case Opt_coo:
19207+ sbinfo->si_mntflags &= ~AuOptMask_COO;
19208+ sbinfo->si_mntflags |= opt->coo;
19209+ break;
19210+
19211+ case Opt_dirwh:
19212+ sbinfo->si_dirwh = opt->dirwh;
19213+ break;
19214+
19215+ case Opt_rdcache:
19216+ sbinfo->si_rdcache = opt->rdcache * HZ;
19217+ break;
19218+
19219+ case Opt_trunc_xino:
19220+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
19221+ break;
19222+ case Opt_notrunc_xino:
19223+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
19224+ break;
19225+
19226+ case Opt_dirperm1:
19227+ au_opt_set(sbinfo->si_mntflags, DIRPERM1);
19228+ break;
19229+ case Opt_nodirperm1:
19230+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
19231+ break;
19232+
19233+ case Opt_shwh:
19234+ au_opt_set(sbinfo->si_mntflags, SHWH);
19235+ break;
19236+ case Opt_noshwh:
19237+ au_opt_clr(sbinfo->si_mntflags, SHWH);
19238+ break;
19239+
19240+ case Opt_trunc_xino_path:
19241+ case Opt_itrunc_xino:
19242+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
19243+ if (!err)
19244+ err = 1;
19245+ break;
19246+
19247+ case Opt_trunc_xib:
19248+ au_fset_opts(opts->flags, TRUNC_XIB);
19249+ break;
19250+ case Opt_notrunc_xib:
19251+ au_fclr_opts(opts->flags, TRUNC_XIB);
19252+ break;
19253+
19254+ default:
19255+ err = 0;
19256+ break;
19257+ }
19258+
19259+ AuTraceErr(err);
19260+ return err;
19261+}
19262+
19263+/*
19264+ * returns tri-state.
19265+ * plus: processed without an error
19266+ * zero: unprocessed
19267+ * minus: error
19268+ */
19269+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
19270+ struct au_opts *opts)
19271+{
19272+ int err, do_refresh;
19273+
19274+ AuTraceEnter();
19275+
19276+ err = 0;
19277+ switch (opt->type) {
19278+ case Opt_append:
19279+ opt->add.bindex = au_sbend(sb) + 1;
19280+ if (opt->add.bindex < 0)
19281+ opt->add.bindex = 0;
19282+ goto add;
19283+ case Opt_prepend:
19284+ opt->add.bindex = 0;
19285+ add:
19286+ case Opt_add:
19287+ err = au_br_add(sb, &opt->add,
19288+ au_ftest_opts(opts->flags, REMOUNT));
19289+ if (!err) {
19290+ err = 1;
19291+ au_fset_opts(opts->flags, REFRESH_DIR);
19292+ if (au_br_whable(opt->add.perm))
19293+ au_fset_opts(opts->flags, REFRESH_NONDIR);
19294+ }
19295+ break;
19296+
19297+ case Opt_del:
19298+ case Opt_idel:
19299+ err = au_br_del(sb, &opt->del,
19300+ au_ftest_opts(opts->flags, REMOUNT));
19301+ if (!err) {
19302+ err = 1;
19303+ au_fset_opts(opts->flags, TRUNC_XIB);
19304+ au_fset_opts(opts->flags, REFRESH_DIR);
19305+ au_fset_opts(opts->flags, REFRESH_NONDIR);
19306+ }
19307+ break;
19308+
19309+ case Opt_mod:
19310+ case Opt_imod:
19311+ err = au_br_mod(sb, &opt->mod,
19312+ au_ftest_opts(opts->flags, REMOUNT),
19313+ &do_refresh);
19314+ if (!err) {
19315+ err = 1;
19316+ if (do_refresh) {
19317+ au_fset_opts(opts->flags, REFRESH_DIR);
19318+ au_fset_opts(opts->flags, REFRESH_NONDIR);
19319+ }
19320+ }
19321+ break;
19322+ }
19323+
19324+ AuTraceErr(err);
19325+ return err;
19326+}
19327+
19328+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
19329+ struct au_opt_xino **opt_xino,
19330+ struct au_opt_xinodir **opt_xinodir,
19331+ struct au_opts *opts)
19332+{
19333+ int err;
19334+ const int remount = !!au_ftest_opts(opts->flags, REMOUNT);
19335+
19336+ AuTraceEnter();
19337+
19338+ err = 0;
19339+ switch (opt->type) {
19340+ case Opt_xino:
19341+ err = au_xino_set(sb, &opt->xino, remount);
19342+ if (!err)
19343+ *opt_xino = &opt->xino;
19344+ break;
19345+#if 0 /* def CONFIG_AUFS_EXPORT */ /* reserved for futur use */
19346+ case Opt_xinodir:
19347+ err = au_xinodir_set(sb, &opt->xinodir, remount);
19348+ if (!err)
19349+ *opt_xinodir = &opt->xinodir;
19350+ break;
19351+#endif
19352+ case Opt_noxino:
19353+ au_xino_clr(sb);
19354+ *opt_xino = (void *)-1;
19355+ break;
19356+ }
19357+
19358+ AuTraceErr(err);
19359+ return err;
19360+}
19361+
19362+int verify_opts(struct super_block *sb, unsigned long sb_flags,
19363+ unsigned int pending, int remount)
19364+{
19365+ int err;
19366+ aufs_bindex_t bindex, bend;
19367+ unsigned char do_plink, skip, do_free;
19368+ struct au_branch *br;
19369+ struct au_wbr *wbr;
19370+ struct dentry *root;
19371+ struct inode *dir, *h_dir;
19372+ unsigned int mnt_flags;
19373+
19374+ AuTraceEnter();
19375+ mnt_flags = au_mntflags(sb);
19376+ AuDebugOn(!(mnt_flags & AuOptMask_COO));
19377+ AuDebugOn(!(mnt_flags & AuOptMask_UDBA));
19378+
19379+ if (!(sb_flags & MS_RDONLY)) {
19380+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
19381+ AuWarn("first branch should be rw\n");
19382+ if (unlikely(au_opt_test(mnt_flags, SHWH)))
19383+ AuWarn("shwh should be used with ro\n");
19384+ } else if (unlikely(!au_opt_test(mnt_flags, COO_NONE))) {
19385+ AuWarn("resetting coo for readonly mount\n");
19386+ au_opt_set_coo(au_sbi(sb)->si_mntflags, COO_NONE);
19387+ }
19388+
19389+ if (unlikely(au_opt_test((mnt_flags | pending), UDBA_INOTIFY)
19390+ && !au_opt_test_xino(mnt_flags)))
19391+ AuWarn("udba=inotify requires xino\n");
19392+
19393+ err = 0;
19394+ root = sb->s_root;
19395+ dir = sb->s_root->d_inode;
19396+ do_plink = !!au_opt_test(mnt_flags, PLINK);
19397+ bend = au_sbend(sb);
19398+ for (bindex = 0; !err && bindex <= bend; bindex++) {
19399+ skip = 0;
19400+ h_dir = au_h_iptr(dir, bindex);
19401+ br = au_sbr(sb, bindex);
19402+ do_free = 0;
19403+ wbr = br->br_wbr;
19404+ if (wbr)
19405+ wbr_wh_read_lock(wbr);
19406+ switch (br->br_perm) {
19407+ case AuBrPerm_RR:
19408+ case AuBrPerm_RO:
19409+ case AuBrPerm_RRWH:
19410+ case AuBrPerm_ROWH:
19411+ do_free = !!wbr;
19412+ skip = (!wbr
19413+ || (!wbr->wbr_whbase
19414+ && !wbr->wbr_plink
19415+ && !wbr->wbr_tmp));
19416+ break;
19417+
19418+ case AuBrPerm_RWNoLinkWH:
19419+ /* skip = (!br->br_whbase && !br->br_tmp); */
19420+ skip = (!wbr || !wbr->wbr_whbase);
19421+ if (skip && wbr) {
19422+ if (do_plink)
19423+ skip = !!wbr->wbr_plink;
19424+ else
19425+ skip = !wbr->wbr_plink;
19426+ }
19427+ break;
19428+
19429+ case AuBrPerm_RW:
19430+ /* skip = (br->br_whbase && br->br_tmp); */
19431+ skip = (wbr && wbr->wbr_whbase);
19432+ if (skip) {
19433+ if (do_plink)
19434+ skip = !!wbr->wbr_plink;
19435+ else
19436+ skip = !wbr->wbr_plink;
19437+ }
19438+ break;
19439+
19440+ default:
19441+ BUG();
19442+ }
19443+ if (wbr)
19444+ wbr_wh_read_unlock(wbr);
19445+
19446+ if (skip)
19447+ continue;
19448+
19449+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
19450+ if (wbr)
19451+ wbr_wh_write_lock(wbr);
19452+ err = au_wh_init(au_h_dptr(root, bindex), br, br->br_mnt, sb,
19453+ bindex);
19454+ if (wbr)
19455+ wbr_wh_write_unlock(wbr);
19456+ mutex_unlock(&h_dir->i_mutex);
19457+
19458+ if (!err && do_free) {
19459+ kfree(wbr);
19460+ br->br_wbr = NULL;
19461+ }
19462+ }
19463+
19464+ AuTraceErr(err);
19465+ return err;
19466+}
19467+
19468+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
19469+{
19470+ int err;
19471+ struct inode *dir;
19472+ struct au_opt *opt;
19473+ struct au_opt_xino *opt_xino, xino;
19474+ struct au_opt_xinodir *opt_xinodir;
19475+ aufs_bindex_t bend;
19476+ struct au_sbinfo *sbinfo;
19477+ unsigned int tmp;
19478+ struct au_branch *br;
19479+
19480+ AuTraceEnter();
19481+ SiMustWriteLock(sb);
19482+ DiMustWriteLock(sb->s_root);
19483+ dir = sb->s_root->d_inode;
19484+ IiMustWriteLock(dir);
19485+
19486+ err = 0;
19487+ opt_xino = NULL;
19488+ opt_xinodir = NULL;
19489+ opt = opts->opt;
19490+ while (err >= 0 && opt->type != Opt_tail)
19491+ err = au_opt_simple(sb, opt++, opts);
19492+ if (err > 0)
19493+ err = 0;
19494+ else if (unlikely(err < 0))
19495+ goto out;
19496+
19497+ /* disable xino, xinodir, hinotify, dlgt temporary */
19498+ sbinfo = au_sbi(sb);
19499+ tmp = sbinfo->si_mntflags;
19500+ au_opt_clr(sbinfo->si_mntflags, XINO);
19501+ au_opt_clr(sbinfo->si_mntflags, XINODIR);
19502+ au_opt_clr(sbinfo->si_mntflags, DLGT);
19503+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
19504+
19505+ opt = opts->opt;
19506+ while (err >= 0 && opt->type != Opt_tail)
19507+ err = au_opt_br(sb, opt++, opts);
19508+ if (err > 0)
19509+ err = 0;
19510+ else if (unlikely(err < 0))
19511+ goto out;
19512+
19513+ bend = au_sbend(sb);
19514+ if (unlikely(bend < 0)) {
19515+ err = -EINVAL;
19516+ AuErr("no branches\n");
19517+ goto out;
19518+ }
19519+
19520+ if (au_opt_test(tmp, XINO))
19521+ au_opt_set(sbinfo->si_mntflags, XINO);
19522+ else if (au_opt_test(tmp, XINODIR))
19523+ au_opt_set(sbinfo->si_mntflags, XINODIR);
19524+ opt = opts->opt;
19525+ while (!err && opt->type != Opt_tail)
19526+ err = au_opt_xino(sb, opt++, &opt_xino, &opt_xinodir, opts);
19527+ if (unlikely(err))
19528+ goto out;
19529+
19530+ /* todo: test this error case? */
19531+ err = verify_opts(sb, sb->s_flags, tmp, /*remount*/0);
19532+ if (unlikely(err))
19533+ goto out;
19534+
19535+ /* enable xino */
19536+ if (au_opt_test(tmp, XINO) && !opt_xino) {
19537+ xino.file = au_xino_def(sb);
19538+ err = PTR_ERR(xino.file);
19539+ if (IS_ERR(xino.file))
19540+ goto out;
19541+
19542+ br = au_xino_def_br(sbinfo);
19543+ err = au_xino_set(sb, &xino, /*remount*/0);
19544+ fput(xino.file);
19545+ if (unlikely(err))
19546+ goto out;
19547+ au_xino_def_br_set(br, sbinfo);
19548+ }
19549+
19550+ /* restore hinotify */
19551+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
19552+ sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
19553+ if (au_opt_test(tmp, UDBA_INOTIFY))
19554+ au_reset_hinotify(dir, au_hi_flags(dir, 1) & ~AuHi_XINO);
19555+
19556+ /* restore dlgt */
19557+ if (au_opt_test(tmp, DLGT))
19558+ au_opt_set(sbinfo->si_mntflags, DLGT);
19559+
19560+ out:
19561+ AuTraceErr(err);
19562+ return err;
19563+}
19564+
19565+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
19566+{
19567+ int err, rerr;
19568+ struct inode *dir;
19569+ struct au_opt_xino *opt_xino;
19570+ struct au_opt_xinodir *opt_xinodir;
19571+ struct au_opt *opt;
19572+ unsigned char dlgt;
19573+ struct au_sbinfo *sbinfo;
19574+
19575+ AuTraceEnter();
19576+ SiMustWriteLock(sb);
19577+ DiMustWriteLock(sb->s_root);
19578+ dir = sb->s_root->d_inode;
19579+ IiMustWriteLock(dir);
19580+ sbinfo = au_sbi(sb);
19581+
19582+ err = 0;
19583+ dlgt = !!au_opt_test(sbinfo->si_mntflags, DLGT);
19584+ opt_xino = NULL;
19585+ opt_xinodir = NULL;
19586+ opt = opts->opt;
19587+ while (err >= 0 && opt->type != Opt_tail) {
19588+ err = au_opt_simple(sb, opt, opts);
19589+
19590+ /* disable it temporary */
19591+ dlgt = !!au_opt_test(sbinfo->si_mntflags, DLGT);
19592+ au_opt_clr(sbinfo->si_mntflags, DLGT);
19593+
19594+ if (!err)
19595+ err = au_opt_br(sb, opt, opts);
19596+ if (!err)
19597+ err = au_opt_xino(sb, opt, &opt_xino, &opt_xinodir,
19598+ opts);
19599+
19600+ /* restore it */
19601+ if (dlgt)
19602+ au_opt_set(sbinfo->si_mntflags, DLGT);
19603+ opt++;
19604+ }
19605+ if (err > 0)
19606+ err = 0;
19607+ AuTraceErr(err);
19608+
19609+ /* go on even err */
19610+
19611+ /* todo: test this error case? */
19612+ au_opt_clr(sbinfo->si_mntflags, DLGT);
19613+ rerr = verify_opts(sb, opts->sb_flags, sbinfo->si_mntflags,
19614+ /*remount*/1);
19615+ if (unlikely(dlgt))
19616+ au_opt_set(sbinfo->si_mntflags, DLGT);
19617+ if (unlikely(rerr && !err))
19618+ err = rerr;
19619+
19620+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
19621+ rerr = au_xib_trunc(sb);
19622+ if (unlikely(rerr && !err))
19623+ err = rerr;
19624+ }
19625+
19626+ /* they are handled by the caller */
19627+ if (!au_ftest_opts(opts->flags, REFRESH_DIR)
19628+ && (opts->given_udba || au_opt_test_xino(sbinfo->si_mntflags)))
19629+ au_fset_opts(opts->flags, REFRESH_DIR);
19630+
19631+ LKTRTrace("status 0x%x\n", opts->flags);
19632+ AuTraceErr(err);
19633+ return err;
19634+}
19635diff -urN linux/fs/aufs/opts.h linux-aufs/fs/aufs/opts.h
19636--- linux/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
19637+++ linux-aufs/fs/aufs/opts.h 2009-03-12 16:18:04.000000000 +0100
19638@@ -0,0 +1,255 @@
19639+/*
19640+ * Copyright (C) 2005-2009 Junjiro Okajima
19641+ *
19642+ * This program, aufs is free software; you can redistribute it and/or modify
19643+ * it under the terms of the GNU General Public License as published by
19644+ * the Free Software Foundation; either version 2 of the License, or
19645+ * (at your option) any later version.
19646+ *
19647+ * This program is distributed in the hope that it will be useful,
19648+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19649+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19650+ * GNU General Public License for more details.
19651+ *
19652+ * You should have received a copy of the GNU General Public License
19653+ * along with this program; if not, write to the Free Software
19654+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19655+ */
19656+
19657+/*
19658+ * mount options/flags
19659+ *
19660+ * $Id$
19661+ */
19662+
19663+#ifndef __AUFS_OPTS_H__
19664+#define __AUFS_OPTS_H__
19665+
19666+#ifdef __KERNEL__
19667+
19668+#include <linux/fs.h>
19669+#include <linux/namei.h>
19670+#include <linux/aufs_type.h>
19671+#include "wkq.h"
19672+
19673+/* ---------------------------------------------------------------------- */
19674+/* mount flags */
19675+
19676+/* external inode number bitmap and translation table */
19677+#define AuOpt_XINO 1
19678+#define AuOpt_XINODIR (1 << 1)
19679+#define AuOpt_TRUNC_XINO (1 << 2)
19680+#define AuOpt_UDBA_NONE (1 << 3) /* users direct branch access */
19681+#define AuOpt_UDBA_REVAL (1 << 4)
19682+#define AuOpt_UDBA_INOTIFY (1 << 5)
19683+#define AuOpt_SHWH (1 << 6)
19684+#define AuOpt_PLINK (1 << 7)
19685+#define AuOpt_WARN_PERM (1 << 8)
19686+#define AuOpt_DIRPERM1 (1 << 9)
19687+#define AuOpt_DLGT (1 << 10)
19688+#define AuOpt_COO_NONE (1 << 11) /* copyup on open */
19689+#define AuOpt_COO_LEAF (1 << 12)
19690+#define AuOpt_COO_ALL (1 << 13)
19691+#define AuOpt_ALWAYS_DIROPQ (1 << 14)
19692+#define AuOpt_REFROF (1 << 15)
19693+#define AuOpt_VERBOSE (1 << 16)
19694+#define AuOpt_SUM (1 << 17)
19695+#define AuOpt_SUM_W (1 << 18) /* unimplemented */
19696+
19697+#if 1 /* ndef CONFIG_AUFS_EXPORT */ /* reserved for future use */
19698+#undef AuOpt_XINODIR
19699+#define AuOpt_XINODIR 0
19700+#endif
19701+#ifndef CONFIG_AUFS_HINOTIFY
19702+#undef AuOpt_UDBA_INOTIFY
19703+#define AuOpt_UDBA_INOTIFY 0
19704+#endif
19705+#ifndef CONFIG_AUFS_SHWH
19706+#undef AuOpt_SHWH
19707+#define AuOpt_SHWH 0
19708+#endif
19709+#ifndef CONFIG_AUFS_DLGT
19710+#undef AuOpt_DIRPERM1
19711+#define AuOpt_DIRPERM1 0
19712+#undef AuOpt_DLGT
19713+#define AuOpt_DLGT 0
19714+#endif
19715+
19716+/* policies to select one among multiple writable branches */
19717+enum {
19718+ AuWbrCreate_TDP, /* top down parent */
19719+ AuWbrCreate_RR, /* round robin */
19720+ AuWbrCreate_MFS, /* most free space */
19721+ AuWbrCreate_MFSV, /* mfs with seconds */
19722+ AuWbrCreate_MFSRR, /* mfs then rr */
19723+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
19724+ AuWbrCreate_PMFS, /* parent and mfs */
19725+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
19726+
19727+ AuWbrCreate_Def = AuWbrCreate_TDP
19728+};
19729+
19730+enum {
19731+ AuWbrCopyup_TDP, /* top down parent */
19732+ AuWbrCopyup_BUP, /* bottom up parent */
19733+ AuWbrCopyup_BU, /* bottom up */
19734+
19735+ AuWbrCopyup_Def = AuWbrCopyup_TDP
19736+};
19737+
19738+#define AuOptMask_COO (AuOpt_COO_NONE \
19739+ | AuOpt_COO_LEAF \
19740+ | AuOpt_COO_ALL)
19741+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
19742+ | AuOpt_UDBA_REVAL \
19743+ | AuOpt_UDBA_INOTIFY)
19744+
19745+#ifdef CONFIG_AUFS_COMPAT
19746+#define AuOpt_DefExtra1 AuOpt_ALWAYS_DIROPQ
19747+#else
19748+#define AuOpt_DefExtra1 0
19749+#endif
19750+
19751+#define AuOpt_Def (AuOpt_XINO \
19752+ | AuOpt_UDBA_REVAL \
19753+ | AuOpt_WARN_PERM \
19754+ | AuOpt_COO_NONE \
19755+ | AuOpt_PLINK \
19756+ | AuOpt_DefExtra1)
19757+
19758+/* ---------------------------------------------------------------------- */
19759+
19760+struct au_opt_add {
19761+ aufs_bindex_t bindex;
19762+ char *path;
19763+ int perm;
19764+ struct nameidata nd;
19765+};
19766+
19767+struct au_opt_del {
19768+ char *path;
19769+ struct dentry *h_root;
19770+};
19771+
19772+struct au_opt_mod {
19773+ char *path;
19774+ int perm;
19775+ struct dentry *h_root;
19776+};
19777+
19778+struct au_opt_xino {
19779+ char *path;
19780+ struct file *file;
19781+};
19782+
19783+struct au_opt_xinodir {
19784+ char *name;
19785+ struct path path;
19786+};
19787+
19788+struct au_opt_xino_itrunc {
19789+ aufs_bindex_t bindex;
19790+};
19791+
19792+struct au_opt_xino_trunc_v {
19793+ unsigned long long upper;
19794+ int step;
19795+};
19796+
19797+struct au_opt_wbr_create {
19798+ int wbr_create;
19799+ int mfs_second;
19800+ unsigned long long mfsrr_watermark;
19801+};
19802+
19803+struct au_opt {
19804+ int type;
19805+ union {
19806+ struct au_opt_xino xino;
19807+ struct au_opt_xinodir xinodir;
19808+ struct au_opt_xino_itrunc xino_itrunc;
19809+ struct au_opt_add add;
19810+ struct au_opt_del del;
19811+ struct au_opt_mod mod;
19812+ int dirwh;
19813+ int rdcache;
19814+ int deblk;
19815+ int nhash;
19816+ int udba;
19817+ int coo;
19818+ struct au_opt_wbr_create wbr_create;
19819+ int wbr_copyup;
19820+ };
19821+};
19822+
19823+/* opts flags */
19824+#define AuOpts_REMOUNT 1
19825+#define AuOpts_REFRESH_DIR (1 << 1)
19826+#define AuOpts_REFRESH_NONDIR (1 << 2)
19827+#define AuOpts_TRUNC_XIB (1 << 3)
19828+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
19829+#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
19830+#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
19831+
19832+struct au_opts {
19833+ struct au_opt *opt;
19834+ int max_opt;
19835+
19836+ unsigned int given_udba;
19837+ unsigned int flags;
19838+ unsigned long sb_flags;
19839+};
19840+
19841+/* ---------------------------------------------------------------------- */
19842+
19843+const char *au_optstr_br_perm(int brperm);
19844+const char *au_optstr_udba(int udba);
19845+const char *au_optstr_coo(int coo);
19846+const char *au_optstr_wbr_copyup(int wbr_copyup);
19847+const char *au_optstr_wbr_create(int wbr_create);
19848+
19849+void au_opts_free(struct au_opts *opts);
19850+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
19851+int verify_opts(struct super_block *sb, unsigned long sb_flags,
19852+ unsigned int pending, int remount);
19853+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
19854+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
19855+
19856+/* ---------------------------------------------------------------------- */
19857+
19858+#define au_opt_test(flags, name) (flags & AuOpt_##name)
19859+
19860+static inline int au_opt_test_xino(unsigned int flags)
19861+{
19862+ return flags & (AuOpt_XINO | AuOpt_XINODIR);
19863+}
19864+
19865+#define au_opt_set(flags, name) do { \
19866+ BUILD_BUG_ON(AuOpt_##name & (AuOptMask_COO | AuOptMask_UDBA)); \
19867+ ((flags) |= AuOpt_##name); \
19868+} while (0)
19869+
19870+#define au_opt_set_coo(flags, name) do { \
19871+ (flags) &= ~AuOptMask_COO; \
19872+ ((flags) |= AuOpt_##name); \
19873+} while (0)
19874+
19875+#define au_opt_set_udba(flags, name) do { \
19876+ (flags) &= ~AuOptMask_UDBA; \
19877+ ((flags) |= AuOpt_##name); \
19878+} while (0)
19879+
19880+#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
19881+
19882+static inline int au_test_dlgt(unsigned int flags)
19883+{
19884+ return au_opt_test(flags, DLGT) && !au_test_wkq(current);
19885+}
19886+
19887+static inline int au_test_dirperm1(unsigned int flags)
19888+{
19889+ return au_opt_test(flags, DIRPERM1) && !au_test_wkq(current);
19890+}
19891+
19892+#endif /* __KERNEL__ */
19893+#endif /* __AUFS_OPTS_H__ */
19894diff -urN linux/fs/aufs/plink.c linux-aufs/fs/aufs/plink.c
19895--- linux/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
19896+++ linux-aufs/fs/aufs/plink.c 2009-03-12 16:18:04.000000000 +0100
19897@@ -0,0 +1,364 @@
19898+/*
19899+ * Copyright (C) 2005-2009 Junjiro Okajima
19900+ *
19901+ * This program, aufs is free software; you can redistribute it and/or modify
19902+ * it under the terms of the GNU General Public License as published by
19903+ * the Free Software Foundation; either version 2 of the License, or
19904+ * (at your option) any later version.
19905+ *
19906+ * This program is distributed in the hope that it will be useful,
19907+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19908+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19909+ * GNU General Public License for more details.
19910+ *
19911+ * You should have received a copy of the GNU General Public License
19912+ * along with this program; if not, write to the Free Software
19913+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19914+ */
19915+
19916+/*
19917+ * pseudo-link
19918+ *
19919+ * $Id$
19920+ */
19921+
19922+#include "aufs.h"
19923+
19924+struct pseudo_link {
19925+ struct list_head list;
19926+ struct inode *inode;
19927+};
19928+
19929+#ifdef CONFIG_AUFS_DEBUG
19930+void au_plink_list(struct super_block *sb)
19931+{
19932+ struct au_sbinfo *sbinfo;
19933+ struct list_head *plink_list;
19934+ struct pseudo_link *plink;
19935+
19936+ AuTraceEnter();
19937+ SiMustAnyLock(sb);
19938+ sbinfo = au_sbi(sb);
19939+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
19940+
19941+ plink_list = &sbinfo->si_plink.head;
19942+ spin_lock(&sbinfo->si_plink.spin);
19943+ list_for_each_entry(plink, plink_list, list)
19944+ AuDbg("%lu\n", plink->inode->i_ino);
19945+ spin_unlock(&sbinfo->si_plink.spin);
19946+}
19947+#endif
19948+
19949+int au_plink_test(struct super_block *sb, struct inode *inode)
19950+{
19951+ int found;
19952+ struct au_sbinfo *sbinfo;
19953+ struct list_head *plink_list;
19954+ struct pseudo_link *plink;
19955+
19956+ LKTRTrace("i%lu\n", inode->i_ino);
19957+ SiMustAnyLock(sb);
19958+ sbinfo = au_sbi(sb);
19959+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
19960+
19961+ found = 0;
19962+ plink_list = &sbinfo->si_plink.head;
19963+ spin_lock(&sbinfo->si_plink.spin);
19964+ list_for_each_entry(plink, plink_list, list)
19965+ if (plink->inode == inode) {
19966+ found = 1;
19967+ break;
19968+ }
19969+ spin_unlock(&sbinfo->si_plink.spin);
19970+ return found;
19971+}
19972+
19973+/* 20 is max digits length of ulong 64 */
19974+#define PLINK_NAME_LEN ((20 + 1) * 2)
19975+
19976+static int plink_name(char *name, int len, struct inode *inode,
19977+ aufs_bindex_t bindex)
19978+{
19979+ int rlen;
19980+ struct inode *h_inode;
19981+
19982+ LKTRTrace("i%lu, b%d\n", inode->i_ino, bindex);
19983+ AuDebugOn(len != PLINK_NAME_LEN);
19984+ h_inode = au_h_iptr(inode, bindex);
19985+ AuDebugOn(!h_inode);
19986+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
19987+ AuDebugOn(rlen >= len);
19988+ return rlen;
19989+}
19990+
19991+struct dentry *au_plink_lkup(struct super_block *sb, aufs_bindex_t bindex,
19992+ struct inode *inode)
19993+{
19994+ struct dentry *h_dentry, *h_parent;
19995+ struct au_branch *br;
19996+ struct au_wbr *wbr;
19997+ struct inode *h_dir;
19998+ char tgtname[PLINK_NAME_LEN];
19999+ int len;
20000+ struct au_ndx ndx = {
20001+ .flags = 0,
20002+ .nd = NULL,
20003+ /* .br = NULL */
20004+ };
20005+
20006+ LKTRTrace("b%d, i%lu\n", bindex, inode->i_ino);
20007+ br = au_sbr(sb, bindex);
20008+ wbr = br->br_wbr;
20009+ AuDebugOn(!wbr);
20010+ h_parent = wbr->wbr_plink;
20011+ AuDebugOn(!h_parent);
20012+ h_dir = h_parent->d_inode;
20013+ AuDebugOn(!h_dir);
20014+
20015+ len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
20016+
20017+ /* always superio. */
20018+ ndx.nfsmnt = au_do_nfsmnt(br->br_mnt);
20019+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
20020+ h_dentry = au_sio_lkup_one(tgtname, h_parent, len, &ndx);
20021+ mutex_unlock(&h_dir->i_mutex);
20022+ return h_dentry;
20023+}
20024+
20025+static int do_whplink(char *tgt, int len, struct dentry *h_parent,
20026+ struct dentry *h_dentry, struct vfsmount *nfsmnt,
20027+ struct super_block *sb)
20028+{
20029+ int err, dlgt;
20030+ struct dentry *h_tgt;
20031+ struct inode *h_dir;
20032+ struct vfsub_args vargs;
20033+ struct au_ndx ndx = {
20034+ .nfsmnt = nfsmnt,
20035+ .flags = 0,
20036+ .nd = NULL,
20037+ /* .br = NULL */
20038+ };
20039+
20040+ AuTraceEnter();
20041+
20042+ dlgt = !!au_test_dlgt(au_mntflags(sb));
20043+ if (dlgt)
20044+ au_fset_ndx(ndx.flags, DLGT);
20045+ h_tgt = au_lkup_one(tgt, h_parent, len, &ndx);
20046+ err = PTR_ERR(h_tgt);
20047+ if (IS_ERR(h_tgt))
20048+ goto out;
20049+
20050+ err = 0;
20051+ vfsub_args_init(&vargs, NULL, dlgt, 0);
20052+ /* wh.plink dir is not monitored */
20053+ h_dir = h_parent->d_inode;
20054+ if (h_tgt->d_inode && h_tgt->d_inode != h_dentry->d_inode)
20055+ err = vfsub_unlink(h_dir, h_tgt, &vargs);
20056+ if (!err && !h_tgt->d_inode) {
20057+ err = vfsub_link(h_dentry, h_dir, h_tgt, &vargs);
20058+ /* todo: unnecessary? */
20059+ /* inc_nlink(inode); */
20060+ }
20061+ dput(h_tgt);
20062+
20063+ out:
20064+ AuTraceErr(err);
20065+ return err;
20066+}
20067+
20068+struct do_whplink_args {
20069+ int *errp;
20070+ char *tgt;
20071+ int len;
20072+ struct dentry *h_parent;
20073+ struct dentry *h_dentry;
20074+ struct vfsmount *nfsmnt;
20075+ struct super_block *sb;
20076+};
20077+
20078+static void call_do_whplink(void *args)
20079+{
20080+ struct do_whplink_args *a = args;
20081+ *a->errp = do_whplink(a->tgt, a->len, a->h_parent, a->h_dentry,
20082+ a->nfsmnt, a->sb);
20083+}
20084+
20085+static int whplink(struct dentry *h_dentry, struct inode *inode,
20086+ aufs_bindex_t bindex, struct super_block *sb)
20087+{
20088+ int err, len, wkq_err;
20089+ struct au_branch *br;
20090+ struct au_wbr *wbr;
20091+ struct dentry *h_parent;
20092+ struct inode *h_dir;
20093+ char tgtname[PLINK_NAME_LEN];
20094+
20095+ LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
20096+ br = au_sbr(inode->i_sb, bindex);
20097+ wbr = br->br_wbr;
20098+ AuDebugOn(!wbr);
20099+ h_parent = wbr->wbr_plink;
20100+ AuDebugOn(!h_parent);
20101+ h_dir = h_parent->d_inode;
20102+ AuDebugOn(!h_dir);
20103+
20104+ len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
20105+
20106+ /* always superio. */
20107+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
20108+ if (!au_test_wkq(current)) {
20109+ struct do_whplink_args args = {
20110+ .errp = &err,
20111+ .tgt = tgtname,
20112+ .len = len,
20113+ .h_parent = h_parent,
20114+ .h_dentry = h_dentry,
20115+ .nfsmnt = au_do_nfsmnt(br->br_mnt),
20116+ .sb = sb
20117+ };
20118+ wkq_err = au_wkq_wait(call_do_whplink, &args, /*dlgt*/0);
20119+ if (unlikely(wkq_err))
20120+ err = wkq_err;
20121+ } else
20122+ err = do_whplink(tgtname, len, h_parent, h_dentry,
20123+ au_do_nfsmnt(br->br_mnt), sb);
20124+ mutex_unlock(&h_dir->i_mutex);
20125+
20126+ AuTraceErr(err);
20127+ return err;
20128+}
20129+
20130+static void do_put_plink(struct pseudo_link *plink, int do_del)
20131+{
20132+ AuTraceEnter();
20133+
20134+ iput(plink->inode);
20135+ if (do_del)
20136+ list_del(&plink->list);
20137+ kfree(plink);
20138+}
20139+
20140+void au_plink_append(struct super_block *sb, struct inode *inode,
20141+ struct dentry *h_dentry, aufs_bindex_t bindex)
20142+{
20143+ struct au_sbinfo *sbinfo;
20144+ struct list_head *plink_list;
20145+ struct pseudo_link *plink;
20146+ int found, err, cnt;
20147+
20148+ LKTRTrace("i%lu\n", inode->i_ino);
20149+ SiMustAnyLock(sb);
20150+ sbinfo = au_sbi(sb);
20151+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
20152+
20153+ cnt = 0;
20154+ found = 0;
20155+ plink_list = &sbinfo->si_plink.head;
20156+ spin_lock(&sbinfo->si_plink.spin);
20157+ list_for_each_entry(plink, plink_list, list) {
20158+ cnt++;
20159+ if (plink->inode == inode) {
20160+ found = 1;
20161+ break;
20162+ }
20163+ }
20164+
20165+ err = 0;
20166+ plink = NULL;
20167+ if (!found) {
20168+ plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
20169+ if (plink) {
20170+ plink->inode = au_igrab(inode);
20171+ list_add(&plink->list, plink_list);
20172+ cnt++;
20173+ } else
20174+ err = -ENOMEM;
20175+ }
20176+ spin_unlock(&sbinfo->si_plink.spin);
20177+
20178+#if 0 /* todo: test here */
20179+ if (found)
20180+ return; /* success */
20181+#endif
20182+
20183+ if (!err)
20184+ err = whplink(h_dentry, inode, bindex, sb);
20185+
20186+ if (unlikely(cnt > AUFS_PLINK_WARN))
20187+ AuWarn1("unexpectedly many pseudo links, %d\n", cnt);
20188+ if (unlikely(err)) {
20189+ AuWarn("err %d, damaged pseudo link. ignored.\n", err);
20190+ if (!found && plink)
20191+ do_put_plink(plink, /*do_del*/1);
20192+ }
20193+}
20194+
20195+void au_plink_put(struct super_block *sb)
20196+{
20197+ struct au_sbinfo *sbinfo;
20198+ struct list_head *plink_list;
20199+ struct pseudo_link *plink, *tmp;
20200+
20201+ AuTraceEnter();
20202+ SiMustWriteLock(sb);
20203+ sbinfo = au_sbi(sb);
20204+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
20205+
20206+ plink_list = &sbinfo->si_plink.head;
20207+ /* spin_lock(&sbinfo->si_plink.spin); */
20208+ list_for_each_entry_safe(plink, tmp, plink_list, list)
20209+ do_put_plink(plink, 0);
20210+ INIT_LIST_HEAD(plink_list);
20211+ /* spin_unlock(&sbinfo->si_plink.head); */
20212+}
20213+
20214+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
20215+{
20216+ struct au_sbinfo *sbinfo;
20217+ struct list_head *plink_list;
20218+ struct pseudo_link *plink, *tmp;
20219+ struct inode *inode;
20220+ aufs_bindex_t bstart, bend, bindex;
20221+ int do_put;
20222+
20223+ AuTraceEnter();
20224+ SiMustWriteLock(sb);
20225+ sbinfo = au_sbi(sb);
20226+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
20227+
20228+ plink_list = &sbinfo->si_plink.head;
20229+ /* spin_lock(&sbinfo->si_plink.spin); */
20230+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
20231+ do_put = 0;
20232+ inode = au_igrab(plink->inode);
20233+ ii_write_lock_child(inode);
20234+ bstart = au_ibstart(inode);
20235+ bend = au_ibend(inode);
20236+ if (bstart >= 0) {
20237+ for (bindex = bstart; bindex <= bend; bindex++) {
20238+ if (!au_h_iptr(inode, bindex)
20239+ || au_ii_br_id(inode, bindex) != br_id)
20240+ continue;
20241+ au_set_h_iptr(inode, bindex, NULL, 0);
20242+ do_put = 1;
20243+ break;
20244+ }
20245+ } else
20246+ do_put_plink(plink, 1);
20247+
20248+ if (do_put) {
20249+ for (bindex = bstart; bindex <= bend; bindex++)
20250+ if (au_h_iptr(inode, bindex)) {
20251+ do_put = 0;
20252+ break;
20253+ }
20254+ if (do_put)
20255+ do_put_plink(plink, 1);
20256+ }
20257+ ii_write_unlock(inode);
20258+ iput(inode);
20259+ }
20260+ /* spin_unlock(&sbinfo->si_plink.spin); */
20261+}
20262diff -urN linux/fs/aufs/robr.c linux-aufs/fs/aufs/robr.c
20263--- linux/fs/aufs/robr.c 1970-01-01 01:00:00.000000000 +0100
20264+++ linux-aufs/fs/aufs/robr.c 2009-03-12 16:18:04.000000000 +0100
20265@@ -0,0 +1,117 @@
20266+/*
20267+ * Copyright (C) 2005-2009 Junjiro Okajima
20268+ *
20269+ * This program, aufs is free software; you can redistribute it and/or modify
20270+ * it under the terms of the GNU General Public License as published by
20271+ * the Free Software Foundation; either version 2 of the License, or
20272+ * (at your option) any later version.
20273+ *
20274+ * This program is distributed in the hope that it will be useful,
20275+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20276+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20277+ * GNU General Public License for more details.
20278+ *
20279+ * You should have received a copy of the GNU General Public License
20280+ * along with this program; if not, write to the Free Software
20281+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20282+ */
20283+
20284+/*
20285+ * 'robr', aufs as readonly branch of another aufs
20286+ *
20287+ * $Id$
20288+ */
20289+
20290+#include "aufs.h"
20291+
20292+/* ---------------------------------------------------------------------- */
20293+
20294+int au_test_robr_wh(struct qstr *name, struct dentry *h_parent,
20295+ struct qstr *wh_name, int try_sio, struct au_ndx *ndx)
20296+{
20297+ if (strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
20298+ return au_wh_test(h_parent, wh_name, try_sio, ndx);
20299+ return -EPERM;
20300+}
20301+
20302+int au_test_robr_shwh(struct super_block *sb, const struct qstr *name)
20303+{
20304+ return 0;
20305+}
20306+
20307+/* ---------------------------------------------------------------------- */
20308+
20309+struct au_robr_lvma {
20310+ struct list_head list;
20311+ struct vm_area_struct *vma;
20312+};
20313+
20314+struct file *au_robr_safe_file(struct vm_area_struct *vma)
20315+{
20316+ struct file *file = vma->vm_file;
20317+ struct super_block *sb = file->f_dentry->d_sb;
20318+ struct au_robr_lvma *lvma, *entry;
20319+ struct au_sbinfo *sbinfo;
20320+ struct list_head *head;
20321+ unsigned char found, warn;
20322+
20323+ AuTraceEnter();
20324+
20325+ if (!file->private_data || !au_test_aufs(sb))
20326+ return NULL;
20327+
20328+ warn = 0;
20329+ found = 0;
20330+ sbinfo = au_sbi(sb);
20331+ head = &sbinfo->si_lvma.head;
20332+ spin_lock(&sbinfo->si_lvma.spin);
20333+ list_for_each_entry(entry, head, list) {
20334+ found = (entry->vma == vma);
20335+ if (unlikely(found))
20336+ break;
20337+ }
20338+ if (!found) {
20339+ lvma = kmalloc(sizeof(*lvma), GFP_ATOMIC);
20340+ if (lvma) {
20341+ lvma->vma = vma;
20342+ list_add(&lvma->list, head);
20343+ } else {
20344+ warn = 1;
20345+ file = NULL;
20346+ }
20347+ } else
20348+ file = NULL;
20349+ spin_unlock(&sbinfo->si_lvma.spin);
20350+
20351+ if (unlikely(warn))
20352+ AuWarn1("no memory for lvma\n");
20353+ return file;
20354+}
20355+
20356+void au_robr_reset_file(struct vm_area_struct *vma, struct file *file)
20357+{
20358+ struct super_block *sb = file->f_dentry->d_sb;
20359+ struct au_robr_lvma *entry, *found;
20360+ struct au_sbinfo *sbinfo;
20361+ struct list_head *head;
20362+
20363+ AuTraceEnter();
20364+ AuDebugOn(!au_test_aufs(sb));
20365+
20366+ vma->vm_file = file;
20367+ /* smp_mb(); */ /* flush vm_file */
20368+
20369+ found = NULL;
20370+ sbinfo = au_sbi(sb);
20371+ head = &sbinfo->si_lvma.head;
20372+ spin_lock(&sbinfo->si_lvma.spin);
20373+ list_for_each_entry(entry, head, list)
20374+ if (entry->vma == vma) {
20375+ found = entry;
20376+ break;
20377+ }
20378+ AuDebugOn(!found);
20379+ list_del(&found->list);
20380+ spin_unlock(&sbinfo->si_lvma.spin);
20381+ kfree(found);
20382+}
20383diff -urN linux/fs/aufs/sbinfo.c linux-aufs/fs/aufs/sbinfo.c
20384--- linux/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
20385+++ linux-aufs/fs/aufs/sbinfo.c 2009-03-12 16:18:04.000000000 +0100
20386@@ -0,0 +1,221 @@
20387+/*
20388+ * Copyright (C) 2005-2009 Junjiro Okajima
20389+ *
20390+ * This program, aufs is free software; you can redistribute it and/or modify
20391+ * it under the terms of the GNU General Public License as published by
20392+ * the Free Software Foundation; either version 2 of the License, or
20393+ * (at your option) any later version.
20394+ *
20395+ * This program is distributed in the hope that it will be useful,
20396+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20397+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20398+ * GNU General Public License for more details.
20399+ *
20400+ * You should have received a copy of the GNU General Public License
20401+ * along with this program; if not, write to the Free Software
20402+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20403+ */
20404+
20405+/*
20406+ * superblock private data
20407+ *
20408+ * $Id$
20409+ */
20410+
20411+#include <linux/smp_lock.h>
20412+#include "aufs.h"
20413+
20414+/*
20415+ * they are necessary regardless sysfs is disabled.
20416+ */
20417+void au_si_free(struct kobject *kobj)
20418+{
20419+ struct au_sbinfo *sbinfo;
20420+ struct super_block *sb;
20421+
20422+ LKTRTrace("kobj %p\n", kobj);
20423+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
20424+ LKTRTrace("sbinfo %p\n", sbinfo);
20425+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
20426+
20427+ sb = sbinfo->si_sb;
20428+ si_write_lock(sb);
20429+ au_xino_clr(sb);
20430+ au_br_free(sbinfo);
20431+ kfree(sbinfo->si_branch);
20432+ au_export_put(sbinfo);
20433+ mutex_destroy(&sbinfo->si_xib_mtx);
20434+ si_write_unlock(sb);
20435+ au_rwsem_destroy(&sbinfo->si_rwsem);
20436+
20437+ kfree(sbinfo);
20438+}
20439+
20440+int au_si_alloc(struct super_block *sb)
20441+{
20442+ int err;
20443+ struct au_sbinfo *sbinfo;
20444+
20445+ AuTraceEnter();
20446+
20447+ err = -ENOMEM;
20448+ sbinfo = kmalloc(sizeof(*sbinfo), GFP_NOFS);
20449+ if (unlikely(!sbinfo))
20450+ goto out;
20451+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
20452+ if (unlikely(!sbinfo->si_branch))
20453+ goto out_sbinfo;
20454+
20455+ memset(&sbinfo->si_kobj, 0, sizeof(sbinfo->si_kobj));
20456+ err = sysaufs_si_init(sbinfo);
20457+ if (unlikely(err))
20458+ goto out_br;
20459+
20460+ au_rw_init_wlock(&sbinfo->si_rwsem);
20461+ //au_dbg_locked_si_reg(sb, 1);
20462+ sbinfo->si_generation = 0;
20463+ sbinfo->au_si_status = 0;
20464+ sbinfo->si_bend = -1;
20465+ sbinfo->si_last_br_id = 0;
20466+
20467+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
20468+ sbinfo->si_wbr_create = AuWbrCreate_Def;
20469+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + AuWbrCopyup_Def;
20470+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + AuWbrCreate_Def;
20471+
20472+ sbinfo->si_mntflags = AuOpt_Def;
20473+
20474+ sbinfo->si_xread = NULL;
20475+ sbinfo->si_xwrite = NULL;
20476+ sbinfo->si_xib = NULL;
20477+ mutex_init(&sbinfo->si_xib_mtx);
20478+ sbinfo->si_xib_buf = NULL;
20479+ au_xino_def_br_set(NULL, sbinfo);
20480+ /* leave si_xib_last_pindex and si_xib_next_bit */
20481+
20482+ au_nwt_init(&sbinfo->si_nowait);
20483+
20484+ sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
20485+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
20486+
20487+ au_spl_init(&sbinfo->si_plink);
20488+
20489+ au_robr_lvma_init(sbinfo);
20490+
20491+ /* leave other members for sysaufs and si_mnt. */
20492+ sbinfo->si_sb = sb;
20493+
20494+ sb->s_fs_info = sbinfo;
20495+
20496+ au_debug_sbinfo_init(sbinfo);
20497+ return 0; /* success */
20498+
20499+ out_br:
20500+ kfree(sbinfo->si_branch);
20501+ out_sbinfo:
20502+ kfree(sbinfo);
20503+ out:
20504+ AuTraceErr(err);
20505+ return err;
20506+}
20507+
20508+/* ---------------------------------------------------------------------- */
20509+
20510+struct au_branch *au_sbr(struct super_block *sb, aufs_bindex_t bindex)
20511+{
20512+ struct au_branch *br;
20513+
20514+ SiMustAnyLock(sb);
20515+ AuDebugOn(bindex < 0 || au_sbend(sb) < bindex);
20516+ br = au_sbi(sb)->si_branch[0 + bindex];
20517+ AuDebugOn(!br);
20518+ return br;
20519+}
20520+
20521+au_gen_t au_sigen_inc(struct super_block *sb)
20522+{
20523+ au_gen_t gen;
20524+
20525+ SiMustWriteLock(sb);
20526+ gen = ++au_sbi(sb)->si_generation;
20527+ au_update_digen(sb->s_root);
20528+ au_update_iigen(sb->s_root->d_inode);
20529+ sb->s_root->d_inode->i_version++;
20530+ return gen;
20531+}
20532+
20533+int au_find_bindex(struct super_block *sb, struct au_branch *br)
20534+{
20535+ aufs_bindex_t bindex, bend;
20536+
20537+ bend = au_sbend(sb);
20538+ for (bindex = 0; bindex <= bend; bindex++)
20539+ if (au_sbr(sb, bindex) == br)
20540+ return bindex;
20541+ return -1;
20542+}
20543+
20544+/* ---------------------------------------------------------------------- */
20545+
20546+/* dentry and super_block lock. call at entry point */
20547+void aufs_read_lock(struct dentry *dentry, int flags)
20548+{
20549+ si_read_lock(dentry->d_sb, flags);
20550+ if (au_ftest_lock(flags, DW))
20551+ di_write_lock_child(dentry);
20552+ else
20553+ di_read_lock_child(dentry, flags);
20554+}
20555+
20556+void aufs_read_unlock(struct dentry *dentry, int flags)
20557+{
20558+ if (au_ftest_lock(flags, DW))
20559+ di_write_unlock(dentry);
20560+ else
20561+ di_read_unlock(dentry, flags);
20562+ si_read_unlock(dentry->d_sb);
20563+}
20564+
20565+void aufs_write_lock(struct dentry *dentry)
20566+{
20567+ si_write_lock(dentry->d_sb);
20568+ di_write_lock_child(dentry);
20569+}
20570+
20571+void aufs_write_unlock(struct dentry *dentry)
20572+{
20573+ di_write_unlock(dentry);
20574+ si_write_unlock(dentry->d_sb);
20575+}
20576+
20577+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
20578+{
20579+ AuDebugOn(d1 == d2 || d1->d_sb != d2->d_sb);
20580+ si_read_lock(d1->d_sb, flags);
20581+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
20582+}
20583+
20584+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
20585+{
20586+ AuDebugOn(d1 == d2 || d1->d_sb != d2->d_sb);
20587+ di_write_unlock2(d1, d2);
20588+ si_read_unlock(d1->d_sb);
20589+}
20590+
20591+/* ---------------------------------------------------------------------- */
20592+
20593+aufs_bindex_t au_new_br_id(struct super_block *sb)
20594+{
20595+ aufs_bindex_t br_id;
20596+ struct au_sbinfo *sbinfo;
20597+
20598+ AuTraceEnter();
20599+ SiMustWriteLock(sb);
20600+
20601+ sbinfo = au_sbi(sb);
20602+ while (1) {
20603+ br_id = ++sbinfo->si_last_br_id;
20604+ if (br_id && au_br_index(sb, br_id) < 0)
20605+ return br_id;
20606+ }
20607+}
20608diff -urN linux/fs/aufs/super.c linux-aufs/fs/aufs/super.c
20609--- linux/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
20610+++ linux-aufs/fs/aufs/super.c 2009-03-12 16:18:04.000000000 +0100
20611@@ -0,0 +1,939 @@
20612+/*
20613+ * Copyright (C) 2005-2009 Junjiro Okajima
20614+ *
20615+ * This program, aufs is free software; you can redistribute it and/or modify
20616+ * it under the terms of the GNU General Public License as published by
20617+ * the Free Software Foundation; either version 2 of the License, or
20618+ * (at your option) any later version.
20619+ *
20620+ * This program is distributed in the hope that it will be useful,
20621+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20622+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20623+ * GNU General Public License for more details.
20624+ *
20625+ * You should have received a copy of the GNU General Public License
20626+ * along with this program; if not, write to the Free Software
20627+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20628+ */
20629+
20630+/*
20631+ * mount and super_block operations
20632+ *
20633+ * $Id$
20634+ */
20635+
20636+#include <linux/module.h>
20637+#include <linux/buffer_head.h>
20638+#include <linux/seq_file.h>
20639+#include <linux/smp_lock.h>
20640+#include <linux/statfs.h>
20641+
20642+#include "aufs.h"
20643+
20644+/*
20645+ * super_operations
20646+ */
20647+static struct inode *aufs_alloc_inode(struct super_block *sb)
20648+{
20649+ struct aufs_icntnr *c;
20650+
20651+ AuTraceEnter();
20652+
20653+ c = au_cache_alloc_icntnr();
20654+ if (c) {
20655+ inode_init_once(&c->vfs_inode);
20656+ c->vfs_inode.i_version = 1; /* sigen(sb); */
20657+ c->iinfo.ii_hinode = NULL;
20658+ return &c->vfs_inode;
20659+ }
20660+ return NULL;
20661+}
20662+
20663+static void aufs_destroy_inode(struct inode *inode)
20664+{
20665+ int err;
20666+
20667+ LKTRTrace("i%lu\n", inode->i_ino);
20668+
20669+ if (!inode->i_nlink || IS_DEADDIR(inode)) {
20670+ /* todo: move this lock into xigen_inc() */
20671+ /* in nowait task or remount, sbi is write-locked */
20672+ struct super_block *sb = inode->i_sb;
20673+ const int locked = si_noflush_read_trylock(sb);
20674+
20675+ err = au_xigen_inc(inode);
20676+ if (unlikely(err))
20677+ AuWarn1("failed resetting i_generation, %d\n", err);
20678+ if (locked)
20679+ si_read_unlock(sb);
20680+ }
20681+
20682+ au_iinfo_fin(inode);
20683+ au_cache_free_icntnr(container_of(inode, struct aufs_icntnr,
20684+ vfs_inode));
20685+}
20686+
20687+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
20688+{
20689+ struct inode *inode;
20690+ int err;
20691+
20692+ LKTRTrace("i%lu\n", (unsigned long)ino);
20693+
20694+ inode = iget_locked(sb, ino);
20695+ if (unlikely(!inode)) {
20696+ inode = ERR_PTR(-ENOMEM);
20697+ goto out;
20698+ }
20699+ AuDebugOn(IS_ERR(inode));
20700+ if (!(inode->i_state & I_NEW))
20701+ goto out;
20702+
20703+ err = au_xigen_new(inode);
20704+ if (!err)
20705+ err = au_iinfo_init(inode);
20706+ if (!err)
20707+ inode->i_version++;
20708+ else {
20709+ iget_failed(inode);
20710+ inode = ERR_PTR(err);
20711+ }
20712+
20713+ out:
20714+ /* never return NULL */
20715+ AuDebugOn(!inode);
20716+ AuTraceErrPtr(inode);
20717+ return inode;
20718+}
20719+
20720+/* lock free root dinfo */
20721+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
20722+{
20723+ int err;
20724+ aufs_bindex_t bindex, bend;
20725+ struct path path;
20726+ struct au_hdentry *hd;
20727+
20728+ AuTraceEnter();
20729+
20730+ err = 0;
20731+ bend = au_sbend(sb);
20732+ hd = au_di(sb->s_root)->di_hdentry;
20733+ for (bindex = 0; !err && bindex <= bend; bindex++) {
20734+ path.mnt = au_sbr_mnt(sb, bindex);
20735+ path.dentry = hd[bindex].hd_dentry;
20736+ err = seq_path(seq, &path, au_esc_chars);
20737+ if (err > 0) {
20738+ const char *p = au_optstr_br_perm(au_sbr_perm(sb,
20739+ bindex));
20740+ err = seq_printf(seq, "=%s", p);
20741+ }
20742+ if (!err && bindex != bend)
20743+ err = seq_putc(seq, ':');
20744+ }
20745+
20746+ AuTraceErr(err);
20747+ return err;
20748+}
20749+
20750+static void au_show_wbr_create(struct seq_file *m, int v,
20751+ struct au_sbinfo *sbinfo)
20752+{
20753+ const char *pat;
20754+
20755+ AuDebugOn(v == AuWbrCreate_Def);
20756+
20757+ seq_printf(m, ",create=");
20758+ pat = au_optstr_wbr_create(v);
20759+ switch (v) {
20760+ case AuWbrCreate_TDP:
20761+ case AuWbrCreate_RR:
20762+ case AuWbrCreate_MFS:
20763+ case AuWbrCreate_PMFS:
20764+ seq_printf(m, pat);
20765+ break;
20766+ case AuWbrCreate_MFSV:
20767+ seq_printf(m, /*pat*/"mfs:%lu",
20768+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
20769+ break;
20770+ case AuWbrCreate_PMFSV:
20771+ seq_printf(m, /*pat*/"pmfs:%lu",
20772+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
20773+ break;
20774+ case AuWbrCreate_MFSRR:
20775+ seq_printf(m, /*pat*/"mfsrr:%llu",
20776+ sbinfo->si_wbr_mfs.mfsrr_watermark);
20777+ break;
20778+ case AuWbrCreate_MFSRRV:
20779+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
20780+ sbinfo->si_wbr_mfs.mfsrr_watermark,
20781+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
20782+ break;
20783+ }
20784+}
20785+
20786+/* seq_file will re-call me in case of too long string */
20787+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
20788+{
20789+ int err, n;
20790+ unsigned int mnt_flags, v;
20791+ struct path path;
20792+ struct super_block *sb;
20793+ struct au_sbinfo *sbinfo;
20794+ struct file *xino;
20795+
20796+ AuTraceEnter();
20797+
20798+ sb = mnt->mnt_sb;
20799+ /* lock free root dinfo */
20800+ si_noflush_read_lock(sb);
20801+ sbinfo = au_sbi(sb);
20802+ seq_printf(m, ",si=%lx", au_si_mask ^ (unsigned long)sbinfo);
20803+ mnt_flags = au_mntflags(sb);
20804+ if (au_opt_test(mnt_flags, XINO)) {
20805+ seq_puts(m, ",xino=");
20806+ xino = sbinfo->si_xib;
20807+ path.mnt = xino->f_vfsmnt;
20808+ path.dentry = xino->f_dentry;
20809+ err = seq_path(m, &path, au_esc_chars);
20810+ if (unlikely(err <= 0))
20811+ goto out;
20812+ err = 0;
20813+#define Deleted "\\040(deleted)"
20814+ m->count -= sizeof(Deleted) - 1;
20815+ AuDebugOn(memcmp(m->buf + m->count, Deleted,
20816+ sizeof(Deleted) - 1));
20817+#undef Deleted
20818+#ifdef CONFIG_AUFS_EXPORT /* reserved for future use */
20819+ } else if (au_opt_test(mnt_flags, XINODIR)) {
20820+ seq_puts(m, ",xinodir=");
20821+ seq_path(m, &sbinfo->si_xinodir, au_esc_chars);
20822+#endif
20823+ } else
20824+ seq_puts(m, ",noxino");
20825+
20826+#define AuBool(name, str) do { \
20827+ v = au_opt_test(mnt_flags, name); \
20828+ if (v != au_opt_test(AuOpt_Def, name)) \
20829+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
20830+} while (0)
20831+
20832+#define AuStr(name, str) do { \
20833+ v = mnt_flags & AuOptMask_##name; \
20834+ if (v != (AuOpt_Def & AuOptMask_##name)) \
20835+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
20836+} while (0)
20837+
20838+#ifdef CONFIG_AUFS_COMPAT
20839+#define AuStr_BrOpt "dirs="
20840+#else
20841+#define AuStr_BrOpt "br:"
20842+#endif
20843+
20844+ AuBool(TRUNC_XINO, trunc_xino);
20845+ AuBool(DIRPERM1, dirperm1);
20846+ AuBool(SHWH, shwh);
20847+ AuBool(PLINK, plink);
20848+ AuStr(UDBA, udba);
20849+
20850+ v = sbinfo->si_wbr_create;
20851+ if (v != AuWbrCreate_Def)
20852+ au_show_wbr_create(m, v, sbinfo);
20853+
20854+ v = sbinfo->si_wbr_copyup;
20855+ if (v != AuWbrCopyup_Def)
20856+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
20857+
20858+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
20859+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
20860+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
20861+ AuBool(REFROF, refrof);
20862+ AuBool(DLGT, dlgt);
20863+ AuBool(WARN_PERM, warn_perm);
20864+ AuBool(VERBOSE, verbose);
20865+ AuBool(SUM, sum);
20866+ /* AuBool(SUM_W, wsum); */
20867+
20868+ n = sbinfo->si_dirwh;
20869+ if (n != AUFS_DIRWH_DEF)
20870+ seq_printf(m, ",dirwh=%d", n);
20871+ n = sbinfo->si_rdcache / HZ;
20872+ if (n != AUFS_RDCACHE_DEF)
20873+ seq_printf(m, ",rdcache=%d", n);
20874+
20875+ AuStr(COO, coo);
20876+
20877+ out:
20878+ if (!sysaufs_brs) {
20879+ seq_puts(m, "," AuStr_BrOpt);
20880+ au_show_brs(m, sb);
20881+ }
20882+ si_read_unlock(sb);
20883+ return 0;
20884+
20885+#undef AuBool
20886+#undef AuStr
20887+#undef AuStr_BrOpt
20888+}
20889+
20890+static u64 au_add_till_max(u64 a, u64 b)
20891+{
20892+ u64 old;
20893+
20894+ old = a;
20895+ a += b;
20896+ if (old < a)
20897+ return a;
20898+ return ULLONG_MAX;
20899+}
20900+
20901+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf, int dlgt)
20902+{
20903+ int err;
20904+ aufs_bindex_t bend, bindex, i;
20905+ unsigned char shared;
20906+ u64 blocks, bfree, bavail, files, ffree;
20907+ struct super_block *h_sb;
20908+
20909+ AuTraceEnter();
20910+
20911+ blocks = 0;
20912+ bfree = 0;
20913+ bavail = 0;
20914+ files = 0;
20915+ ffree = 0;
20916+
20917+ err = 0;
20918+ bend = au_sbend(sb);
20919+ for (bindex = bend; bindex >= 0; bindex--) {
20920+ h_sb = au_sbr_sb(sb, bindex);
20921+ shared = 0;
20922+ for (i = bindex + 1; !shared && i <= bend; i++)
20923+ shared = au_sbr_sb(sb, i) == h_sb;
20924+ if (shared)
20925+ continue;
20926+
20927+ err = vfsub_statfs(h_sb->s_root, buf, dlgt);
20928+ if (unlikely(err))
20929+ goto out;
20930+
20931+ blocks = au_add_till_max(blocks, buf->f_blocks);
20932+ bfree = au_add_till_max(bfree, buf->f_bfree);
20933+ bavail = au_add_till_max(bavail, buf->f_bavail);
20934+ files = au_add_till_max(files, buf->f_files);
20935+ ffree = au_add_till_max(ffree, buf->f_ffree);
20936+ }
20937+
20938+ buf->f_blocks = blocks;
20939+ buf->f_bfree = bfree;
20940+ buf->f_bavail = bavail;
20941+ buf->f_files = files;
20942+ buf->f_ffree = ffree;
20943+
20944+ out:
20945+ AuTraceErr(err);
20946+ return err;
20947+}
20948+
20949+/* todo: in case of round-robin policy, return the sum of all rw branches? */
20950+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
20951+{
20952+ int err;
20953+ unsigned int mnt_flags;
20954+ unsigned char dlgt;
20955+ struct super_block *sb;
20956+
20957+ AuTraceEnter();
20958+
20959+ /* lock free root dinfo */
20960+ sb = dentry->d_sb;
20961+ si_noflush_read_lock(sb);
20962+ mnt_flags = au_mntflags(sb);
20963+ dlgt = !!au_test_dlgt(mnt_flags);
20964+ if (!au_opt_test(mnt_flags, SUM))
20965+ err = vfsub_statfs(au_sbr_sb(sb, 0)->s_root, buf, dlgt);
20966+ else
20967+ err = au_statfs_sum(sb, buf, dlgt);
20968+ si_read_unlock(sb);
20969+ if (!err) {
20970+ buf->f_type = AUFS_SUPER_MAGIC;
20971+ buf->f_namelen -= AUFS_WH_PFX_LEN;
20972+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
20973+ }
20974+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
20975+
20976+ AuTraceErr(err);
20977+ return err;
20978+}
20979+
20980+static void au_fsync_br(struct super_block *sb)
20981+{
20982+#ifdef CONFIG_AUFS_FSYNC_SUPER_PATCH
20983+ aufs_bindex_t bend, bindex;
20984+ int brperm;
20985+ struct au_branch *br;
20986+ struct super_block *h_sb;
20987+
20988+ AuTraceEnter();
20989+
20990+ si_write_lock(sb);
20991+ bend = au_sbend(sb);
20992+ for (bindex = 0; bindex < bend; bindex++) {
20993+ br = au_sbr(sb, bindex);
20994+ brperm = br->br_perm;
20995+ if (brperm == AuBrPerm_RR || brperm == AuBrPerm_RRWH)
20996+ continue;
20997+ h_sb = br->br_mnt->mnt_sb;
20998+ if (bdev_read_only(h_sb->s_bdev))
20999+ continue;
21000+
21001+ lockdep_off();
21002+ down_write(&h_sb->s_umount);
21003+ shrink_dcache_sb(h_sb);
21004+ fsync_super(h_sb);
21005+ up_write(&h_sb->s_umount);
21006+ lockdep_on();
21007+ }
21008+ si_write_unlock(sb);
21009+#endif
21010+}
21011+
21012+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
21013+/* this IS NOT for super_operations */
21014+static void aufs_umount_begin(struct super_block *arg)
21015+#define AuUmountBeginSb(arg) (arg)
21016+#else
21017+/* this IS for super_operations */
21018+static void aufs_umount_begin(struct vfsmount *arg, int flags)
21019+#define AuUmountBeginSb(arg) ((arg)->mnt_sb)
21020+#endif
21021+{
21022+ struct super_block *sb = AuUmountBeginSb(arg);
21023+ struct au_sbinfo *sbinfo;
21024+
21025+ AuTraceEnter();
21026+ /* dont trust BKL */
21027+ AuDebugOn(!kernel_locked());
21028+
21029+ sbinfo = au_sbi(sb);
21030+ if (!sbinfo)
21031+ return;
21032+
21033+ au_fsync_br(sb);
21034+
21035+ si_write_lock(sb);
21036+ if (au_opt_test(au_mntflags(sb), PLINK))
21037+ au_plink_put(sb);
21038+ au_mnt_reset(sbinfo);
21039+#if 0 /* reserved for future use */
21040+ if (sbinfo->si_wbr_create_ops->fin)
21041+ sbinfo->si_wbr_create_ops->fin(sb);
21042+#endif
21043+ si_write_unlock(sb);
21044+}
21045+
21046+/* final actions when unmounting a file system */
21047+static void aufs_put_super(struct super_block *sb)
21048+{
21049+ struct au_sbinfo *sbinfo;
21050+
21051+ AuTraceEnter();
21052+
21053+ sbinfo = au_sbi(sb);
21054+ if (!sbinfo)
21055+ return;
21056+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
21057+ aufs_umount_begin(sb);
21058+#endif
21059+ kobject_put(&sbinfo->si_kobj);
21060+}
21061+
21062+/* ---------------------------------------------------------------------- */
21063+
21064+/*
21065+ * refresh dentry and inode at remount time.
21066+ */
21067+static int do_refresh(struct dentry *dentry, mode_t type,
21068+ unsigned int dir_flags)
21069+{
21070+ int err;
21071+ struct dentry *parent;
21072+ struct inode *inode;
21073+
21074+ LKTRTrace("%.*s, 0%o\n", AuDLNPair(dentry), type);
21075+ inode = dentry->d_inode;
21076+ AuDebugOn(!inode);
21077+
21078+ di_write_lock_child(dentry);
21079+ parent = dget_parent(dentry);
21080+ di_read_lock_parent(parent, AuLock_IR);
21081+ /* returns a number of positive dentries */
21082+ err = au_refresh_hdentry(dentry, type);
21083+ if (err >= 0) {
21084+ err = au_refresh_hinode(inode, dentry);
21085+ if (!err && type == S_IFDIR)
21086+ au_reset_hinotify(inode, dir_flags);
21087+ }
21088+ if (unlikely(err))
21089+ AuErr("unrecoverable error %d, %.*s\n", err, AuDLNPair(dentry));
21090+ di_read_unlock(parent, AuLock_IR);
21091+ dput(parent);
21092+ di_write_unlock(dentry);
21093+
21094+ AuTraceErr(err);
21095+ return err;
21096+}
21097+
21098+static int test_dir(struct dentry *dentry, void *arg)
21099+{
21100+ return S_ISDIR(dentry->d_inode->i_mode);
21101+}
21102+
21103+/* todo: merge with refresh_nondir()? */
21104+static int refresh_dir(struct dentry *root, au_gen_t sgen)
21105+{
21106+ int err, i, j, ndentry, e;
21107+ struct au_dcsub_pages dpages;
21108+ struct au_dpage *dpage;
21109+ struct dentry **dentries;
21110+ struct inode *inode;
21111+ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
21112+
21113+ LKTRTrace("sgen %d\n", sgen);
21114+ SiMustWriteLock(root->d_sb);
21115+ /* dont trust BKL */
21116+ AuDebugOn(au_digen(root) != sgen || !kernel_locked());
21117+
21118+ err = 0;
21119+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
21120+ if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sgen) {
21121+ ii_write_lock_child(inode);
21122+ e = au_refresh_hinode_self(inode);
21123+ ii_write_unlock(inode);
21124+ if (unlikely(e)) {
21125+ LKTRTrace("e %d, i%lu\n", e, inode->i_ino);
21126+ if (!err)
21127+ err = e;
21128+ /* go on even if err */
21129+ }
21130+ }
21131+
21132+ e = au_dpages_init(&dpages, GFP_NOFS);
21133+ if (unlikely(e)) {
21134+ if (!err)
21135+ err = e;
21136+ goto out;
21137+ }
21138+ e = au_dcsub_pages(&dpages, root, test_dir, NULL);
21139+ if (unlikely(e)) {
21140+ if (!err)
21141+ err = e;
21142+ goto out_dpages;
21143+ }
21144+
21145+ for (i = 0; !e && i < dpages.ndpage; i++) {
21146+ dpage = dpages.dpages + i;
21147+ dentries = dpage->dentries;
21148+ ndentry = dpage->ndentry;
21149+ for (j = 0; !e && j < ndentry; j++) {
21150+ struct dentry *d;
21151+ d = dentries[j];
21152+#ifdef CONFIG_AUFS_DEBUG
21153+ {
21154+ struct dentry *parent;
21155+ parent = dget_parent(d);
21156+ AuDebugOn(!S_ISDIR(d->d_inode->i_mode)
21157+ || IS_ROOT(d)
21158+ || au_digen(parent) != sgen);
21159+ dput(parent);
21160+ }
21161+#endif
21162+ if (au_digen(d) != sgen) {
21163+ e = do_refresh(d, S_IFDIR, flags);
21164+ if (unlikely(e && !err))
21165+ err = e;
21166+ /* break on err */
21167+ }
21168+ }
21169+ }
21170+
21171+ out_dpages:
21172+ au_dpages_free(&dpages);
21173+ out:
21174+ AuTraceErr(err);
21175+ return err;
21176+}
21177+
21178+static int test_nondir(struct dentry *dentry, void *arg)
21179+{
21180+ return !S_ISDIR(dentry->d_inode->i_mode);
21181+}
21182+
21183+static int refresh_nondir(struct dentry *root, au_gen_t sgen, int do_dentry)
21184+{
21185+ int err, i, j, ndentry, e;
21186+ struct au_dcsub_pages dpages;
21187+ struct au_dpage *dpage;
21188+ struct dentry **dentries;
21189+ struct inode *inode;
21190+
21191+ LKTRTrace("sgen %d\n", sgen);
21192+ SiMustWriteLock(root->d_sb);
21193+ /* dont trust BKL */
21194+ AuDebugOn(au_digen(root) != sgen || !kernel_locked());
21195+
21196+ err = 0;
21197+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
21198+ if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sgen) {
21199+ ii_write_lock_child(inode);
21200+ e = au_refresh_hinode_self(inode);
21201+ ii_write_unlock(inode);
21202+ if (unlikely(e)) {
21203+ LKTRTrace("e %d, i%lu\n", e, inode->i_ino);
21204+ if (!err)
21205+ err = e;
21206+ /* go on even if err */
21207+ }
21208+ }
21209+
21210+ if (!do_dentry)
21211+ goto out;
21212+
21213+ e = au_dpages_init(&dpages, GFP_NOFS);
21214+ if (unlikely(e)) {
21215+ if (!err)
21216+ err = e;
21217+ goto out;
21218+ }
21219+ e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
21220+ if (unlikely(e)) {
21221+ if (!err)
21222+ err = e;
21223+ goto out_dpages;
21224+ }
21225+
21226+ for (i = 0; i < dpages.ndpage; i++) {
21227+ dpage = dpages.dpages + i;
21228+ dentries = dpage->dentries;
21229+ ndentry = dpage->ndentry;
21230+ for (j = 0; j < ndentry; j++) {
21231+ struct dentry *d;
21232+ d = dentries[j];
21233+#ifdef CONFIG_AUFS_DEBUG
21234+ {
21235+ struct dentry *parent;
21236+ parent = dget_parent(d);
21237+ AuDebugOn(S_ISDIR(d->d_inode->i_mode)
21238+ || au_digen(parent) != sgen);
21239+ dput(parent);
21240+ }
21241+#endif
21242+ inode = d->d_inode;
21243+ if (inode && au_digen(d) != sgen) {
21244+ e = do_refresh(d, inode->i_mode & S_IFMT, 0);
21245+ if (unlikely(e && !err))
21246+ err = e;
21247+ /* go on even err */
21248+ }
21249+ }
21250+ }
21251+
21252+ out_dpages:
21253+ au_dpages_free(&dpages);
21254+ out:
21255+ AuTraceErr(err);
21256+ return err;
21257+}
21258+
21259+/* stop extra interpretation of errno in mount(8), and strange error messages */
21260+static int cvt_err(int err)
21261+{
21262+ AuTraceErr(err);
21263+
21264+ switch (err) {
21265+ case -ENOENT:
21266+ case -ENOTDIR:
21267+ case -EEXIST:
21268+ case -EIO:
21269+ err = -EINVAL;
21270+ }
21271+ return err;
21272+}
21273+
21274+/* protected by s_umount */
21275+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
21276+{
21277+ int err, rerr;
21278+ au_gen_t sigen;
21279+ struct dentry *root;
21280+ struct inode *inode;
21281+ struct au_opts opts;
21282+ struct au_sbinfo *sbinfo;
21283+ unsigned char dlgt;
21284+
21285+ LKTRTrace("flags 0x%x, data %s, len %lu\n",
21286+ *flags, data ? data : "NULL",
21287+ (unsigned long)(data ? strlen(data) : 0));
21288+
21289+ au_fsync_br(sb);
21290+
21291+ err = 0;
21292+ root = sb->s_root;
21293+ if (!data || !*data) {
21294+ aufs_write_lock(root);
21295+ err = verify_opts(sb, *flags, /*pending*/0, /*remount*/1);
21296+ aufs_write_unlock(root);
21297+ goto out; /* success */
21298+ }
21299+
21300+ err = -ENOMEM;
21301+ memset(&opts, 0, sizeof(opts));
21302+ opts.opt = (void *)__get_free_page(GFP_NOFS);
21303+ if (unlikely(!opts.opt))
21304+ goto out;
21305+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
21306+ opts.flags = AuOpts_REMOUNT;
21307+ opts.sb_flags = *flags;
21308+
21309+ /* parse it before aufs lock */
21310+ err = au_opts_parse(sb, data, &opts);
21311+ if (unlikely(err))
21312+ goto out_opts;
21313+
21314+ sbinfo = au_sbi(sb);
21315+ inode = root->d_inode;
21316+ mutex_lock(&inode->i_mutex);
21317+ aufs_write_lock(root);
21318+
21319+ /* au_do_opts() may return an error */
21320+ err = au_opts_remount(sb, &opts);
21321+ au_opts_free(&opts);
21322+
21323+ if (au_ftest_opts(opts.flags, REFRESH_DIR)
21324+ || au_ftest_opts(opts.flags, REFRESH_NONDIR)) {
21325+ dlgt = !!au_opt_test(sbinfo->si_mntflags, DLGT);
21326+ au_opt_clr(sbinfo->si_mntflags, DLGT);
21327+ au_sigen_inc(sb);
21328+ au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
21329+ sigen = au_sigen(sb);
21330+ au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
21331+
21332+ DiMustNoWaiters(root);
21333+ IiMustNoWaiters(root->d_inode);
21334+ di_write_unlock(root);
21335+
21336+ rerr = refresh_dir(root, sigen);
21337+ if (unlikely(rerr)) {
21338+ au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
21339+ AuWarn("Refreshing directories failed, ignores (%d)\n",
21340+ rerr);
21341+ }
21342+
21343+ if (au_ftest_opts(opts.flags, REFRESH_NONDIR)) {
21344+ rerr = refresh_nondir(root, sigen, !rerr);
21345+ if (unlikely(rerr))
21346+ AuWarn("Refreshing non-directories failed,"
21347+ " ignores (%d)\n", rerr);
21348+ }
21349+
21350+ /* aufs_write_lock() calls ..._child() */
21351+ di_write_lock_child(root);
21352+
21353+ au_cpup_attr_all(inode, /*force*/1);
21354+ if (dlgt)
21355+ au_opt_set(sbinfo->si_mntflags, DLGT);
21356+ }
21357+
21358+ aufs_write_unlock(root);
21359+ mutex_unlock(&inode->i_mutex);
21360+
21361+ out_opts:
21362+ free_page((unsigned long)opts.opt);
21363+ out:
21364+ err = cvt_err(err);
21365+ AuTraceErr(err);
21366+ return err;
21367+}
21368+
21369+static struct super_operations aufs_sop = {
21370+ .alloc_inode = aufs_alloc_inode,
21371+ .destroy_inode = aufs_destroy_inode,
21372+ .drop_inode = generic_delete_inode,
21373+
21374+ .show_options = aufs_show_options,
21375+ .statfs = aufs_statfs,
21376+
21377+ .put_super = aufs_put_super,
21378+ .remount_fs = aufs_remount_fs,
21379+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
21380+ .umount_begin = aufs_umount_begin
21381+#endif
21382+};
21383+
21384+/* ---------------------------------------------------------------------- */
21385+
21386+static int alloc_root(struct super_block *sb)
21387+{
21388+ int err;
21389+ struct inode *inode;
21390+ struct dentry *root;
21391+
21392+ AuTraceEnter();
21393+
21394+ err = -ENOMEM;
21395+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
21396+ err = PTR_ERR(inode);
21397+ if (IS_ERR(inode))
21398+ goto out;
21399+ inode->i_op = &aufs_dir_iop;
21400+ inode->i_fop = &aufs_dir_fop;
21401+ inode->i_mode = S_IFDIR;
21402+ unlock_new_inode(inode);
21403+ root = d_alloc_root(inode);
21404+ if (unlikely(!root))
21405+ goto out_iput;
21406+ err = PTR_ERR(root);
21407+ if (IS_ERR(root))
21408+ goto out_iput;
21409+
21410+ err = au_alloc_dinfo(root);
21411+ if (!err) {
21412+ sb->s_root = root;
21413+ return 0; /* success */
21414+ }
21415+ dput(root);
21416+ goto out; /* do not iput */
21417+
21418+ out_iput:
21419+ iget_failed(inode);
21420+ iput(inode);
21421+ out:
21422+ AuTraceErr(err);
21423+ return err;
21424+
21425+}
21426+
21427+static int aufs_fill_super(struct super_block *sb, void *raw_data, int silent)
21428+{
21429+ int err;
21430+ struct dentry *root;
21431+ struct inode *inode;
21432+ struct au_opts opts;
21433+ char *arg = raw_data;
21434+
21435+ if (unlikely(!arg || !*arg)) {
21436+ err = -EINVAL;
21437+ AuErr("no arg\n");
21438+ goto out;
21439+ }
21440+ LKTRTrace("%s, silent %d\n", arg, silent);
21441+
21442+ err = -ENOMEM;
21443+ memset(&opts, 0, sizeof(opts));
21444+ opts.opt = (void *)__get_free_page(GFP_NOFS);
21445+ if (unlikely(!opts.opt))
21446+ goto out;
21447+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
21448+ opts.sb_flags = sb->s_flags;
21449+
21450+ err = au_si_alloc(sb);
21451+ if (unlikely(err))
21452+ goto out_opts;
21453+ SiMustWriteLock(sb);
21454+
21455+ /* all timestamps always follow the ones on the branch */
21456+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
21457+ sb->s_op = &aufs_sop;
21458+ sb->s_magic = AUFS_SUPER_MAGIC;
21459+ au_export_init(sb);
21460+
21461+ err = alloc_root(sb);
21462+ if (unlikely(err)) {
21463+ AuDebugOn(sb->s_root);
21464+ si_write_unlock(sb);
21465+ goto out_info;
21466+ }
21467+ root = sb->s_root;
21468+ DiMustWriteLock(root);
21469+ inode = root->d_inode;
21470+ inode->i_nlink = 2;
21471+
21472+ /*
21473+ * actually we can parse options regardless aufs lock here.
21474+ * but at remount time, parsing must be done before aufs lock.
21475+ * so we follow the same rule.
21476+ */
21477+ ii_write_lock_parent(inode);
21478+ au_dbg_locked_si_reg(sb, 1);
21479+ aufs_write_unlock(root);
21480+ err = au_opts_parse(sb, arg, &opts);
21481+ if (unlikely(err))
21482+ goto out_root;
21483+
21484+ /* lock vfs_inode first, then aufs. */
21485+ mutex_lock(&inode->i_mutex);
21486+ inode->i_op = &aufs_dir_iop;
21487+ inode->i_fop = &aufs_dir_fop;
21488+ aufs_write_lock(root);
21489+
21490+ sb->s_maxbytes = 0;
21491+ err = au_opts_mount(sb, &opts);
21492+ au_opts_free(&opts);
21493+ if (unlikely(err))
21494+ goto out_unlock;
21495+ AuDebugOn(!sb->s_maxbytes);
21496+
21497+ aufs_write_unlock(root);
21498+ mutex_unlock(&inode->i_mutex);
21499+ goto out_opts; /* success */
21500+
21501+ out_unlock:
21502+ aufs_write_unlock(root);
21503+ mutex_unlock(&inode->i_mutex);
21504+ out_root:
21505+ dput(root);
21506+ sb->s_root = NULL;
21507+ out_info:
21508+ kobject_put(&au_sbi(sb)->si_kobj);
21509+ sb->s_fs_info = NULL;
21510+ out_opts:
21511+ free_page((unsigned long)opts.opt);
21512+ out:
21513+ AuTraceErr(err);
21514+ err = cvt_err(err);
21515+ AuTraceErr(err);
21516+ return err;
21517+}
21518+
21519+/* ---------------------------------------------------------------------- */
21520+
21521+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
21522+ const char *dev_name, void *raw_data,
21523+ struct vfsmount *mnt)
21524+{
21525+ int err;
21526+ struct super_block *sb;
21527+
21528+ /* all timestamps always follow the ones on the branch */
21529+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
21530+ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
21531+ if (!err) {
21532+ sb = mnt->mnt_sb;
21533+ au_mnt_init(au_sbi(sb), mnt);
21534+ si_write_lock(sb);
21535+ sysaufs_brs_add(sb, 0);
21536+ si_write_unlock(sb);
21537+ }
21538+ return err;
21539+}
21540+
21541+struct file_system_type aufs_fs_type = {
21542+ .name = AUFS_FSTYPE,
21543+ .fs_flags =
21544+ FS_RENAME_DOES_D_MOVE /* a race between rename and others*/
21545+ | FS_REVAL_DOT, /* for NFS branch and udba */
21546+ .get_sb = aufs_get_sb,
21547+ .kill_sb = generic_shutdown_super,
21548+ /* no need to __module_get() and module_put(). */
21549+ .owner = THIS_MODULE,
21550+};
21551diff -urN linux/fs/aufs/super.h linux-aufs/fs/aufs/super.h
21552--- linux/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
21553+++ linux-aufs/fs/aufs/super.h 2009-03-12 16:18:04.000000000 +0100
21554@@ -0,0 +1,579 @@
21555+/*
21556+ * Copyright (C) 2005-2009 Junjiro Okajima
21557+ *
21558+ * This program, aufs is free software; you can redistribute it and/or modify
21559+ * it under the terms of the GNU General Public License as published by
21560+ * the Free Software Foundation; either version 2 of the License, or
21561+ * (at your option) any later version.
21562+ *
21563+ * This program is distributed in the hope that it will be useful,
21564+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21565+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21566+ * GNU General Public License for more details.
21567+ *
21568+ * You should have received a copy of the GNU General Public License
21569+ * along with this program; if not, write to the Free Software
21570+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21571+ */
21572+
21573+/*
21574+ * super_block operations
21575+ *
21576+ * $Id$
21577+ */
21578+
21579+#ifndef __AUFS_SUPER_H__
21580+#define __AUFS_SUPER_H__
21581+
21582+#ifdef __KERNEL__
21583+
21584+#include <linux/fs.h>
21585+#include <linux/cramfs_fs.h>
21586+#include <linux/kobject.h>
21587+#include <linux/magic.h>
21588+#include <linux/mount.h>
21589+#include <linux/aufs_type.h>
21590+#include "misc.h"
21591+#include "wkq.h"
21592+
21593+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
21594+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
21595+ loff_t *);
21596+
21597+struct au_wbr_copyup_operations {
21598+ int (*copyup)(struct dentry *dentry);
21599+};
21600+
21601+struct au_wbr_create_operations {
21602+ int (*create)(struct dentry *dentry, int isdir);
21603+ int (*init)(struct super_block *sb);
21604+ int (*fin)(struct super_block *sb);
21605+};
21606+
21607+struct au_wbr_mfs {
21608+ struct mutex mfs_lock; /* protect this structure */
21609+ unsigned long mfs_jiffy;
21610+ unsigned long mfs_expire;
21611+ aufs_bindex_t mfs_bindex;
21612+
21613+ unsigned long long mfsrr_bytes;
21614+ unsigned long long mfsrr_watermark;
21615+};
21616+
21617+/* sbinfo status flags */
21618+/*
21619+ * set true when refresh_dirs() failed at remount time.
21620+ * then try refreshing dirs at access time again.
21621+ * if it is false, refreshing dirs at access time is unnecesary
21622+ */
21623+#define AuSi_FAILED_REFRESH_DIRS 1
21624+#define au_ftest_si(sbinfo, name) ((sbinfo)->au_si_status & AuSi_##name)
21625+#define au_fset_si(sbinfo, name) \
21626+ { (sbinfo)->au_si_status |= AuSi_##name; }
21627+#define au_fclr_si(sbinfo, name) \
21628+ { (sbinfo)->au_si_status &= ~AuSi_##name; }
21629+
21630+struct au_branch;
21631+struct au_sbinfo {
21632+ /* nowait tasks in the system-wide workqueue */
21633+ struct au_nowait_tasks si_nowait;
21634+
21635+ struct au_rwsem si_rwsem;
21636+
21637+ /* branch management */
21638+ au_gen_t si_generation;
21639+
21640+ /* see above flags */
21641+ unsigned char au_si_status;
21642+
21643+ aufs_bindex_t si_bend;
21644+ aufs_bindex_t si_last_br_id;
21645+ struct au_branch **si_branch;
21646+
21647+ /* policy to select a writable branch */
21648+ unsigned char si_wbr_copyup;
21649+ unsigned char si_wbr_create;
21650+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
21651+ struct au_wbr_create_operations *si_wbr_create_ops;
21652+
21653+ /* round robin */
21654+ atomic_t si_wbr_rr_next;
21655+
21656+ /* most free space */
21657+ struct au_wbr_mfs si_wbr_mfs;
21658+
21659+ /* mount flags */
21660+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
21661+ unsigned int si_mntflags;
21662+
21663+ /* external inode number (bitmap and translation table) */
21664+ au_readf_t si_xread;
21665+ au_writef_t si_xwrite;
21666+ struct file *si_xib;
21667+ struct mutex si_xib_mtx; /* protect xib members */
21668+ unsigned long *si_xib_buf;
21669+ unsigned long si_xib_last_pindex;
21670+ int si_xib_next_bit;
21671+ /* reserved for future use */
21672+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
21673+
21674+#ifdef CONFIG_AUFS_HINOTIFY
21675+ struct au_branch *si_xino_def_br;
21676+#endif
21677+
21678+#ifdef CONFIG_AUFS_EXPORT
21679+ /* i_generation */
21680+ struct file *si_xigen;
21681+ atomic_t si_xigen_next;
21682+#endif
21683+
21684+ /* readdir cache time, max, in HZ */
21685+ unsigned long si_rdcache;
21686+
21687+ /*
21688+ * If the number of whiteouts are larger than si_dirwh, leave all of
21689+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
21690+ * future fsck.aufs or kernel thread will remove them later.
21691+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
21692+ */
21693+ unsigned int si_dirwh;
21694+
21695+ /*
21696+ * rename(2) a directory with all children.
21697+ */
21698+ /* reserved for future use */
21699+ /* int si_rendir; */
21700+
21701+ /* pseudo_link list */ /* todo: dirty? */
21702+ struct au_splhead si_plink;
21703+
21704+#if defined(CONFIG_AUFS_EXPORT) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
21705+ /* dirty, for export, async ops, and sysfs */
21706+ spinlock_t si_mntcache_lock;
21707+ struct vfsmount *si_mntcache; /* no get/put */
21708+#endif
21709+
21710+ /*
21711+ * sysfs and lifetime management.
21712+ * this is not a small structure and it may be a waste of memory in case
21713+ * of sysfs is disabled, particulary when many aufs-es are mounted.
21714+ */
21715+ struct kobject si_kobj;
21716+
21717+#ifdef CONFIG_AUFS_ROBR
21718+ /* locked vma list for mmap() */ /* todo: dirty? */
21719+ struct au_splhead si_lvma;
21720+#endif
21721+
21722+#ifdef CONFIG_AUFS_EXPORT /* reserved for future use */
21723+ struct path si_xinodir;
21724+#endif
21725+
21726+ /* dirty, necessary for unmounting, sysfs and sysrq */
21727+ struct super_block *si_sb;
21728+
21729+#ifdef CONFIG_AUFS_DEBUG_LOCK
21730+ struct au_splhead si_dbg_lock[AuDbgLock_Last];
21731+#endif
21732+};
21733+
21734+/* ---------------------------------------------------------------------- */
21735+
21736+/* policy to select one among writable branches */
21737+#define AuWbrCopyup(sbinfo, args...) \
21738+ ((sbinfo)->si_wbr_copyup_ops->copyup(args))
21739+#define AuWbrCreate(sbinfo, args...) \
21740+ ((sbinfo)->si_wbr_create_ops->create(args))
21741+
21742+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
21743+#define AuLock_DW 1 /* write-lock dentry */
21744+#define AuLock_IR (1 << 1) /* read-lock inode */
21745+#define AuLock_IW (1 << 2) /* write-lock inode */
21746+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
21747+#define AuLock_DIR (1 << 4) /* target is a dir */
21748+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
21749+#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
21750+#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
21751+
21752+/* ---------------------------------------------------------------------- */
21753+
21754+/* super.c */
21755+extern struct file_system_type aufs_fs_type;
21756+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
21757+
21758+/* sbinfo.c */
21759+void au_si_free(struct kobject *kobj);
21760+int au_si_alloc(struct super_block *sb);
21761+struct au_branch *au_sbr(struct super_block *sb, aufs_bindex_t bindex);
21762+au_gen_t au_sigen_inc(struct super_block *sb);
21763+int au_find_bindex(struct super_block *sb, struct au_branch *br);
21764+
21765+void aufs_read_lock(struct dentry *dentry, int flags);
21766+void aufs_read_unlock(struct dentry *dentry, int flags);
21767+void aufs_write_lock(struct dentry *dentry);
21768+void aufs_write_unlock(struct dentry *dentry);
21769+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
21770+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
21771+
21772+aufs_bindex_t au_new_br_id(struct super_block *sb);
21773+
21774+/* wbr_policy.c */
21775+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
21776+extern struct au_wbr_create_operations au_wbr_create_ops[];
21777+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
21778+
21779+/* ---------------------------------------------------------------------- */
21780+
21781+#if defined(CONFIG_AUFS_EXPORT) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
21782+static inline void au_mnt_init(struct au_sbinfo *sbinfo, struct vfsmount *mnt)
21783+{
21784+ spin_lock_init(&sbinfo->si_mntcache_lock);
21785+ sbinfo->si_mntcache = mnt;
21786+}
21787+
21788+static inline void au_mnt_reset(struct au_sbinfo *sbinfo)
21789+{
21790+ spin_lock(&sbinfo->si_mntcache_lock);
21791+ sbinfo->si_mntcache = NULL;
21792+ spin_unlock(&sbinfo->si_mntcache_lock);
21793+}
21794+#else
21795+static inline void au_mnt_init(struct au_sbinfo *sbinfo, struct vfsmount *mnt)
21796+{
21797+ /* emptr */
21798+}
21799+
21800+static inline void au_mnt_reset(struct au_sbinfo *sbinfo)
21801+{
21802+ /* emptr */
21803+}
21804+#endif /* EXPORT && < 2.6.26 */
21805+
21806+/* ---------------------------------------------------------------------- */
21807+
21808+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
21809+static inline int au_mnt_want_write(struct vfsmount *h_mnt)
21810+{
21811+ return mnt_want_write(h_mnt);
21812+}
21813+
21814+static inline void au_mnt_drop_write(struct vfsmount *h_mnt)
21815+{
21816+ mnt_drop_write(h_mnt);
21817+}
21818+#else
21819+static inline int au_mnt_want_write(struct vfsmount *h_mnt)
21820+{
21821+ return 0;
21822+}
21823+
21824+static inline void au_mnt_drop_write(struct vfsmount *h_mnt)
21825+{
21826+ /* empty */
21827+}
21828+#endif
21829+
21830+/* ---------------------------------------------------------------------- */
21831+
21832+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
21833+{
21834+ return sb->s_fs_info;
21835+}
21836+
21837+static inline const char *au_sbtype(struct super_block *sb)
21838+{
21839+ return sb->s_type->name;
21840+}
21841+
21842+static inline int au_test_aufs(struct super_block *sb)
21843+{
21844+ return sb->s_magic == AUFS_SUPER_MAGIC;
21845+}
21846+
21847+static inline int au_test_nfs(struct super_block *sb)
21848+{
21849+#ifdef CONFIG_AUFS_BR_NFS
21850+ return sb->s_magic == NFS_SUPER_MAGIC;
21851+#else
21852+ return 0;
21853+#endif
21854+}
21855+
21856+static inline int au_test_nfs4(struct super_block *sb)
21857+{
21858+#ifdef CONFIG_AUFS_BR_NFS_V4
21859+ return au_test_nfs(sb) && !strcmp(sb->s_type->name, "nfs4");
21860+#else
21861+ return 0;
21862+#endif
21863+}
21864+
21865+static inline int au_test_fuse(struct super_block *sb)
21866+{
21867+#ifdef CONFIG_AUFS_WORKAROUND_FUSE
21868+ return sb->s_magic == FUSE_SUPER_MAGIC;
21869+#else
21870+ return 0;
21871+#endif
21872+}
21873+
21874+static inline int au_test_xfs(struct super_block *sb)
21875+{
21876+#ifdef CONFIG_AUFS_BR_XFS
21877+ return sb->s_magic == XFS_SB_MAGIC;
21878+#else
21879+ return 0;
21880+#endif
21881+}
21882+
21883+static inline int au_test_tmpfs(struct super_block *sb)
21884+{
21885+#ifdef CONFIG_TMPFS
21886+ return sb->s_magic == TMPFS_MAGIC;
21887+#else
21888+ return 0;
21889+#endif
21890+}
21891+
21892+static inline int au_test_ecryptfs(struct super_block *sb)
21893+{
21894+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
21895+ /* why don't they use s_magic? */
21896+ return !strcmp(sb->s_type->name, "ecryptfs");
21897+#else
21898+ return 0;
21899+#endif
21900+}
21901+
21902+/* ---------------------------------------------------------------------- */
21903+
21904+#ifdef CONFIG_AUFS_HINOTIFY
21905+static inline void au_xino_def_br_set(struct au_branch *br,
21906+ struct au_sbinfo *sbinfo)
21907+{
21908+ sbinfo->si_xino_def_br = br;
21909+}
21910+
21911+static inline struct au_branch *au_xino_def_br(struct au_sbinfo *sbinfo)
21912+{
21913+ return sbinfo->si_xino_def_br;
21914+}
21915+#else
21916+static inline void au_xino_def_br_set(struct au_branch *br,
21917+ struct au_sbinfo *sbinfo)
21918+{
21919+ /* empty */
21920+}
21921+
21922+static inline struct au_branch *au_xino_def_br(struct au_sbinfo *sbinfo)
21923+{
21924+ return NULL;
21925+}
21926+#endif
21927+
21928+/* ---------------------------------------------------------------------- */
21929+
21930+#ifdef CONFIG_AUFS_EXPORT
21931+void au_export_init(struct super_block *sb);
21932+
21933+static inline int au_test_nfsd(struct task_struct *tsk)
21934+{
21935+ return !tsk->mm && !strcmp(tsk->comm, "nfsd");
21936+}
21937+
21938+static inline void au_export_put(struct au_sbinfo *sbinfo)
21939+{
21940+ path_put(&sbinfo->si_xinodir);
21941+}
21942+
21943+int au_xigen_inc(struct inode *inode);
21944+int au_xigen_new(struct inode *inode);
21945+int au_xigen_set(struct super_block *sb, struct file *base);
21946+void au_xigen_clr(struct super_block *sb);
21947+#else
21948+static inline void au_export_init(struct super_block *sb)
21949+{
21950+ /* nothing */
21951+}
21952+
21953+static inline int au_test_nfsd(struct task_struct *tsk)
21954+{
21955+ return 0;
21956+}
21957+
21958+static inline void au_export_put(struct au_sbinfo *sbinfo)
21959+{
21960+ /* nothing */
21961+}
21962+
21963+static inline int au_xigen_inc(struct inode *inode)
21964+{
21965+ return 0;
21966+}
21967+
21968+static inline int au_xigen_new(struct inode *inode)
21969+{
21970+ return 0;
21971+}
21972+
21973+static inline int au_xigen_set(struct super_block *sb, struct file *base)
21974+{
21975+ return 0;
21976+}
21977+
21978+static inline void au_xigen_clr(struct super_block *sb)
21979+{
21980+ /* empty */
21981+}
21982+#endif /* CONFIG_AUFS_EXPORT */
21983+
21984+#ifdef CONFIG_AUFS_ROBR
21985+static inline int au_test_nested(struct super_block *h_sb)
21986+{
21987+ return 0;
21988+}
21989+
21990+static inline void au_robr_lvma_init(struct au_sbinfo *sbinfo)
21991+{
21992+ au_spl_init(&sbinfo->si_lvma);
21993+}
21994+#else
21995+static inline int au_test_nested(struct super_block *h_sb)
21996+{
21997+ int err = 0;
21998+ if (unlikely(au_test_aufs(h_sb))) {
21999+ err = -EINVAL;
22000+ AuTraceErr(err);
22001+ }
22002+ return err;
22003+}
22004+
22005+static inline void au_robr_lvma_init(struct au_sbinfo *sbinfo)
22006+{
22007+ /* empty */
22008+}
22009+#endif /* CONFIG_AUFS_ROBR */
22010+
22011+/* ---------------------------------------------------------------------- */
22012+
22013+/* lock superblock. mainly for entry point functions */
22014+/*
22015+ * si_do_noflush_read_lock, si_do_noflush_write_lock,
22016+ * si_do_read_unlock, si_do_write_unlock, si_do_downgrade_lock
22017+ */
22018+AuSimpleLockRwsemFuncs(si_do_noflush, struct super_block *sb,
22019+ au_sbi(sb)->si_rwsem);
22020+AuSimpleUnlockRwsemFuncs(si_do, struct super_block *sb, au_sbi(sb)->si_rwsem);
22021+
22022+static inline void si_noflush_read_lock(struct super_block *sb)
22023+{
22024+ au_dbg_locking_si_reg(sb, 0);
22025+ si_do_noflush_read_lock(sb);
22026+ au_dbg_locking_si_unreg(sb, 0);
22027+ au_dbg_locked_si_reg(sb, 0);
22028+}
22029+
22030+static inline void si_noflush_write_lock(struct super_block *sb)
22031+{
22032+ au_dbg_locking_si_reg(sb, 1);
22033+ si_do_noflush_write_lock(sb);
22034+ au_dbg_locking_si_unreg(sb, 1);
22035+ au_dbg_locked_si_reg(sb, 1);
22036+}
22037+
22038+static inline int si_noflush_read_trylock(struct super_block *sb)
22039+{
22040+ int locked;
22041+
22042+ au_dbg_locking_si_reg(sb, 0);
22043+ locked = si_do_noflush_read_trylock(sb);
22044+ au_dbg_locking_si_unreg(sb, 0);
22045+ if (locked)
22046+ au_dbg_locked_si_reg(sb, 0);
22047+ return locked;
22048+}
22049+
22050+static inline int si_noflush_write_trylock(struct super_block *sb)
22051+{
22052+ int locked;
22053+
22054+ au_dbg_locking_si_reg(sb, 1);
22055+ locked = si_do_noflush_write_trylock(sb);
22056+ au_dbg_locking_si_unreg(sb, 1);
22057+ if (locked)
22058+ au_dbg_locked_si_reg(sb, 1);
22059+ return locked;
22060+}
22061+
22062+static inline void si_read_unlock(struct super_block *sb)
22063+{
22064+ si_do_read_unlock(sb);
22065+ au_dbg_locked_si_unreg(sb, 0);
22066+}
22067+
22068+static inline void si_write_unlock(struct super_block *sb)
22069+{
22070+ si_do_write_unlock(sb);
22071+ au_dbg_locked_si_unreg(sb, 1);
22072+}
22073+
22074+static inline void si_downgrade_lock(struct super_block *sb)
22075+{
22076+ si_do_downgrade_lock(sb);
22077+}
22078+
22079+static inline void si_read_lock(struct super_block *sb, int flags)
22080+{
22081+ if (/* !au_test_nfsd(current) && */au_ftest_lock(flags, FLUSH))
22082+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22083+ si_noflush_read_lock(sb);
22084+}
22085+
22086+static inline void si_write_lock(struct super_block *sb)
22087+{
22088+ //WARN_ON(au_test_nfsd(current));
22089+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22090+ si_noflush_write_lock(sb);
22091+}
22092+
22093+static inline int si_read_trylock(struct super_block *sb, int flags)
22094+{
22095+ if (/* !au_test_nfsd(current) && */au_ftest_lock(flags, FLUSH))
22096+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22097+ return si_noflush_read_trylock(sb);
22098+}
22099+
22100+static inline int si_write_trylock(struct super_block *sb, int flags)
22101+{
22102+ if (/* !au_test_nfsd(current) && */au_ftest_lock(flags, FLUSH))
22103+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22104+ return si_noflush_write_trylock(sb);
22105+}
22106+
22107+/* to debug easier, do not make them inlined functions */
22108+#define SiMustReadLock(sb) AuRwMustReadLock(&au_sbi(sb)->si_rwsem)
22109+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
22110+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
22111+
22112+/* ---------------------------------------------------------------------- */
22113+
22114+static inline aufs_bindex_t au_sbend(struct super_block *sb)
22115+{
22116+ SiMustAnyLock(sb);
22117+ return au_sbi(sb)->si_bend;
22118+}
22119+
22120+static inline unsigned int au_mntflags(struct super_block *sb)
22121+{
22122+ SiMustAnyLock(sb);
22123+ return au_sbi(sb)->si_mntflags;
22124+}
22125+
22126+static inline au_gen_t au_sigen(struct super_block *sb)
22127+{
22128+ SiMustAnyLock(sb);
22129+ return au_sbi(sb)->si_generation;
22130+}
22131+
22132+#endif /* __KERNEL__ */
22133+#endif /* __AUFS_SUPER_H__ */
22134diff -urN linux/fs/aufs/sysaufs.c linux-aufs/fs/aufs/sysaufs.c
22135--- linux/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
22136+++ linux-aufs/fs/aufs/sysaufs.c 2009-03-12 16:18:04.000000000 +0100
22137@@ -0,0 +1,109 @@
22138+/*
22139+ * Copyright (C) 2005-2009 Junjiro Okajima
22140+ *
22141+ * This program, aufs is free software; you can redistribute it and/or modify
22142+ * it under the terms of the GNU General Public License as published by
22143+ * the Free Software Foundation; either version 2 of the License, or
22144+ * (at your option) any later version.
22145+ *
22146+ * This program is distributed in the hope that it will be useful,
22147+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22148+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22149+ * GNU General Public License for more details.
22150+ *
22151+ * You should have received a copy of the GNU General Public License
22152+ * along with this program; if not, write to the Free Software
22153+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22154+ */
22155+
22156+/*
22157+ * sysfs interface and lifetime management
22158+ * they are necessary regardless sysfs is disabled.
22159+ *
22160+ * $Id$
22161+ */
22162+
22163+#include <linux/fs.h>
22164+#include <linux/module.h>
22165+#include <linux/random.h>
22166+#include <linux/sysfs.h>
22167+#include "aufs.h"
22168+
22169+/* ---------------------------------------------------------------------- */
22170+
22171+unsigned long au_si_mask;
22172+
22173+/* ---------------------------------------------------------------------- */
22174+
22175+struct kset *au_kset;
22176+
22177+#define AuSbiAttr(_name) { \
22178+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
22179+ .show = sysaufs_sbi_##_name, \
22180+}
22181+
22182+static struct au_sbi_attr au_sbi_attr_xino = AuSbiAttr(xino);
22183+#ifdef CONFIG_AUFS_EXPORT
22184+static struct au_sbi_attr au_sbi_attr_xigen = AuSbiAttr(xigen);
22185+#endif
22186+struct attribute *au_sbi_attrs[] = {
22187+ &au_sbi_attr_xino.attr,
22188+#ifdef CONFIG_AUFS_EXPORT
22189+ &au_sbi_attr_xigen.attr,
22190+#endif
22191+ NULL,
22192+};
22193+
22194+static struct sysfs_ops au_sbi_ops = {
22195+ .show = sysaufs_sbi_show
22196+};
22197+
22198+static struct kobj_type au_sbi_ktype = {
22199+ .release = au_si_free,
22200+ .sysfs_ops = &au_sbi_ops,
22201+ .default_attrs = au_sbi_attrs
22202+};
22203+
22204+/* ---------------------------------------------------------------------- */
22205+
22206+int sysaufs_si_init(struct au_sbinfo *sbinfo)
22207+{
22208+ int err;
22209+
22210+ sbinfo->si_kobj.kset = au_kset;
22211+ /* some people doesn't like to show a pointer in kernel */
22212+ err = kobject_init_and_add(&sbinfo->si_kobj, &au_sbi_ktype,
22213+ NULL/*&au_kset->kobj*/,
22214+ SysaufsSb_PREFIX "%lx",
22215+ au_si_mask ^ (unsigned long)sbinfo);
22216+ AuTraceErr(err);
22217+ return err;
22218+}
22219+
22220+
22221+/* ---------------------------------------------------------------------- */
22222+
22223+void sysaufs_fin(void)
22224+{
22225+ sysfs_remove_group(&au_kset->kobj, au_attr_group);
22226+ kset_unregister(au_kset);
22227+}
22228+
22229+int __init sysaufs_init(void)
22230+{
22231+ int err;
22232+
22233+ get_random_bytes(&au_si_mask, sizeof(au_si_mask));
22234+
22235+ au_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
22236+ err = PTR_ERR(au_kset);
22237+ if (IS_ERR(au_kset))
22238+ goto out;
22239+ err = sysfs_create_group(&au_kset->kobj, au_attr_group);
22240+ if (unlikely(err))
22241+ kset_unregister(au_kset);
22242+
22243+ out:
22244+ AuTraceErr(err);
22245+ return err;
22246+}
22247diff -urN linux/fs/aufs/sysaufs.h linux-aufs/fs/aufs/sysaufs.h
22248--- linux/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
22249+++ linux-aufs/fs/aufs/sysaufs.h 2009-03-12 16:18:04.000000000 +0100
22250@@ -0,0 +1,119 @@
22251+/*
22252+ * Copyright (C) 2005-2009 Junjiro Okajima
22253+ *
22254+ * This program, aufs is free software; you can redistribute it and/or modify
22255+ * it under the terms of the GNU General Public License as published by
22256+ * the Free Software Foundation; either version 2 of the License, or
22257+ * (at your option) any later version.
22258+ *
22259+ * This program is distributed in the hope that it will be useful,
22260+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22261+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22262+ * GNU General Public License for more details.
22263+ *
22264+ * You should have received a copy of the GNU General Public License
22265+ * along with this program; if not, write to the Free Software
22266+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22267+ */
22268+
22269+/*
22270+ * sysfs interface and lifetime management
22271+ *
22272+ * $Id$
22273+ */
22274+
22275+#ifndef __SYSAUFS_H__
22276+#define __SYSAUFS_H__
22277+
22278+#ifdef __KERNEL__
22279+
22280+#include <linux/fs.h>
22281+#include <linux/sysfs.h>
22282+#include "module.h"
22283+#include "super.h"
22284+
22285+#define SysaufsSb_PREFIX "si_" /* followed by %p */
22286+
22287+struct au_sbi_attr {
22288+ struct attribute attr;
22289+ int (*show)(struct seq_file *seq, struct super_block *sb);
22290+};
22291+
22292+/* ---------------------------------------------------------------------- */
22293+
22294+/* sysaufs.c */
22295+extern unsigned long au_si_mask;
22296+extern struct kset *au_kset;
22297+extern struct attribute *au_sbi_attrs[];
22298+int sysaufs_si_init(struct au_sbinfo *sbinfo);
22299+int __init sysaufs_init(void);
22300+void sysaufs_fin(void);
22301+
22302+/* ---------------------------------------------------------------------- */
22303+
22304+struct au_branch;
22305+#ifdef CONFIG_SYSFS
22306+/* sysfs.c */
22307+extern struct attribute_group *au_attr_group;
22308+extern struct kobj_type *au_ktype;
22309+
22310+int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb);
22311+#ifdef CONFIG_AUFS_EXPORT
22312+int sysaufs_sbi_xigen(struct seq_file *seq, struct super_block *sb);
22313+#endif
22314+int sysaufs_sbi_mntpnt1(struct seq_file *seq, struct super_block *sb);
22315+ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr,
22316+ char *buf);
22317+
22318+void sysaufs_br_init(struct au_branch *br);
22319+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
22320+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
22321+#else
22322+#define au_attr_group NULL
22323+#define au_ktype NULL
22324+
22325+static inline
22326+int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb)
22327+{
22328+ return 0;
22329+}
22330+
22331+#ifdef CONFIG_AUFS_EXPORT
22332+static inline
22333+int sysaufs_sbi_xigen(struct seq_file *seq, struct super_block *sb)
22334+{
22335+ return 0;
22336+}
22337+#endif
22338+
22339+static inline
22340+int sysaufs_sbi_mntpnt1(struct seq_file *seq, struct super_block *sb)
22341+{
22342+ return 0;
22343+}
22344+
22345+static inline
22346+ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr,
22347+ char *buf)
22348+{
22349+ return 0;
22350+}
22351+
22352+static inline void sysaufs_br_init(struct au_branch *br)
22353+{
22354+ /* empty */
22355+}
22356+
22357+static inline void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
22358+{
22359+ /* nothing */
22360+}
22361+
22362+static inline void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
22363+{
22364+ /* nothing */
22365+}
22366+#endif /* CONFIG_SYSFS */
22367+
22368+#endif /* __KERNEL__ */
22369+#endif /* __SYSAUFS_H__ */
22370diff -urN linux/fs/aufs/sysfs.c linux-aufs/fs/aufs/sysfs.c
22371--- linux/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
22372+++ linux-aufs/fs/aufs/sysfs.c 2009-03-12 16:18:04.000000000 +0100
22373@@ -0,0 +1,533 @@
22374+/*
22375+ * Copyright (C) 2005-2009 Junjiro Okajima
22376+ *
22377+ * This program, aufs is free software; you can redistribute it and/or modify
22378+ * it under the terms of the GNU General Public License as published by
22379+ * the Free Software Foundation; either version 2 of the License, or
22380+ * (at your option) any later version.
22381+ *
22382+ * This program is distributed in the hope that it will be useful,
22383+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22384+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22385+ * GNU General Public License for more details.
22386+ *
22387+ * You should have received a copy of the GNU General Public License
22388+ * along with this program; if not, write to the Free Software
22389+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22390+ */
22391+
22392+/*
22393+ * sysfs interface
22394+ *
22395+ * $Id$
22396+ */
22397+
22398+#include <linux/fs.h>
22399+#include <linux/module.h>
22400+#include <linux/seq_file.h>
22401+#include <linux/sysfs.h>
22402+#include "aufs.h"
22403+
22404+
22405+#ifdef CONFIG_AUFS_LOCAL
22406+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
22407+ char *buf)
22408+{
22409+#define conf_bool(name) "CONFIG_AUFS_" #name "=y\n"
22410+ static const char opt[] =
22411+#ifdef CONFIG_AUFS
22412+ "CONFIG_AUFS=y\n"
22413+#else
22414+ "CONFIG_AUFS=m\n"
22415+#endif
22416+#ifdef CONFIG_AUFS_BRANCH_MAX_127
22417+ conf_bool(BRANCH_MAX_127)
22418+#elif defined(CONFIG_AUFS_BRANCH_MAX_511)
22419+ conf_bool(BRANCH_MAX_511)
22420+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
22421+ conf_bool(BRANCH_MAX_1023)
22422+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
22423+ conf_bool(BRANCH_MAX_32767)
22424+#endif
22425+#ifdef CONFIG_AUFS_STAT
22426+ conf_bool(STAT)
22427+#endif
22428+#ifdef CONFIG_AUFS_HINOTIFY
22429+ conf_bool(HINOTIFY)
22430+#endif
22431+#ifdef CONFIG_AUFS_EXPORT
22432+ conf_bool(EXPORT)
22433+#endif
22434+#ifdef CONFIG_AUFS_INO_T_64
22435+ conf_bool(INO_T_64)
22436+#endif
22437+#ifdef CONFIG_AUFS_ROBR
22438+ conf_bool(ROBR)
22439+#endif
22440+#ifdef CONFIG_AUFS_DLGT
22441+ conf_bool(DLGT)
22442+#endif
22443+#ifdef CONFIG_AUFS_HIN_OR_DLGT
22444+ conf_bool(HIN_OR_DLGT)
22445+#endif
22446+#ifdef CONFIG_AUFS_SHWH
22447+ conf_bool(SHWH)
22448+#endif
22449+#ifdef CONFIG_AUFS_RR_SQUASHFS
22450+ conf_bool(RR_SQUASHFS)
22451+#endif
22452+#ifdef CONFIG_AUFS_SEC_PERM_PATCH
22453+ conf_bool(SEC_PERM_PATCH)
22454+#endif
22455+#ifdef CONFIG_AUFS_SPLICE_PATCH
22456+ conf_bool(SPLICE_PATCH)
22457+#endif
22458+#ifdef CONFIG_AUFS_LHASH_PATCH
22459+ conf_bool(LHASH_PATCH)
22460+#endif
22461+#ifdef CONFIG_AUFS_PUT_FILP_PATCH
22462+ conf_bool(PUT_FILP_PATCH)
22463+#endif
22464+#ifdef CONFIG_AUFS_BR_NFS
22465+ conf_bool(BR_NFS)
22466+#endif
22467+#ifdef CONFIG_AUFS_BR_NFS_V4
22468+ conf_bool(BR_NFS_V4)
22469+#endif
22470+#ifdef CONFIG_AUFS_BR_XFS
22471+ conf_bool(BR_XFS)
22472+#endif
22473+#ifdef CONFIG_AUFS_FSYNC_SUPER_PATCH
22474+ conf_bool(FSYNC_SUPER_PATCH)
22475+#endif
22476+#ifdef CONFIG_AUFS_DENY_WRITE_ACCESS_PATCH
22477+ conf_bool(DENY_WRITE_ACCESS_PATCH)
22478+#endif
22479+#ifdef CONFIG_AUFS_KSIZE_PATCH
22480+ conf_bool(KSIZE_PATCH)
22481+#endif
22482+#ifdef CONFIG_AUFS_WORKAROUND_FUSE
22483+ conf_bool(WORKAROUND_FUSE)
22484+#endif
22485+#ifdef CONFIG_AUFS_GETATTR
22486+ conf_bool(GETATTR)
22487+#endif
22488+#ifdef CONFIG_AUFS_DEBUG
22489+ conf_bool(DEBUG)
22490+#endif
22491+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
22492+ conf_bool(MAGIC_SYSRQ)
22493+#endif
22494+#ifdef CONFIG_AUFS_DEBUG_LOCK
22495+ conf_bool(DEBUG_LOCK)
22496+#endif
22497+#ifdef CONFIG_AUFS_COMPAT
22498+ conf_bool(COMPAT)
22499+#endif
22500+#ifdef CONFIG_AUFS_UNIONFS22_PATCH
22501+ conf_bool(UNIONFS22_PATCH)
22502+#endif
22503+#ifdef CONFIG_AUFS_UNIONFS23_PATCH
22504+ conf_bool(UNIONFS23_PATCH)
22505+#endif
22506+ ;
22507+#undef conf_bool
22508+
22509+ char *p = buf;
22510+ const char *end = buf + PAGE_SIZE;
22511+
22512+ p += snprintf(p, end - p, "%s", opt);
22513+#ifdef DbgUdbaRace
22514+ if (p < end)
22515+ p += snprintf(p, end - p, "DbgUdbaRace=%d\n", DbgUdbaRace);
22516+#endif
22517+ if (p < end)
22518+ return p - buf;
22519+ else
22520+ return -EFBIG;
22521+}
22522+
22523+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
22524+#endif
22525+
22526+#ifdef CONFIG_AUFS_STAT
22527+static ssize_t stat_show(struct kobject *kobj, struct kobj_attribute *attr,
22528+ char *buf)
22529+{
22530+ char *p = buf;
22531+ const char *end = buf + PAGE_SIZE;
22532+ int i;
22533+
22534+ p += snprintf(p, end - p, "wkq max_busy:");
22535+ for (i = 0; p < end && i < aufs_nwkq; i++)
22536+ p += snprintf(p, end - p, " %u", au_wkq[i].max_busy);
22537+ if (p < end)
22538+ p += snprintf(p, end - p, ", %u(generic)\n",
22539+ au_wkq[aufs_nwkq].max_busy);
22540+
22541+ if (p < end)
22542+ return p - buf;
22543+ else
22544+ return -EFBIG;
22545+}
22546+
22547+static struct kobj_attribute au_stat_attr = __ATTR_RO(stat);
22548+#endif
22549+
22550+#ifdef CONFIG_AUFS_DEBUG
22551+static ssize_t debug_show(struct kobject *kobj, struct kobj_attribute *attr,
22552+ char *buf)
22553+{
22554+ return sprintf(buf, "%d\n", au_debug_test());
22555+}
22556+
22557+static ssize_t debug_store(struct kobject *kobj, struct kobj_attribute *attr,
22558+ const char *buf, size_t sz)
22559+{
22560+ LKTRTrace("%.*s\n", (unsigned int)sz, buf);
22561+
22562+ if (unlikely(!sz || (*buf != '0' && *buf != '1')))
22563+ return -EOPNOTSUPP;
22564+
22565+ if (*buf == '0')
22566+ au_debug_off();
22567+ else if (*buf == '1')
22568+ au_debug_on();
22569+ return sz;
22570+}
22571+
22572+static struct kobj_attribute au_debug_attr = __ATTR(debug, S_IRUGO | S_IWUSR,
22573+ debug_show, debug_store);
22574+#endif
22575+
22576+static struct attribute *au_attr[] = {
22577+#ifdef CONFIG_AUFS_LOCAL
22578+ &au_config_attr.attr,
22579+#endif
22580+#ifdef CONFIG_AUFS_STAT
22581+ &au_stat_attr.attr,
22582+#endif
22583+#ifdef CONFIG_AUFS_DEBUG
22584+ &au_debug_attr.attr,
22585+#endif
22586+ NULL, /* need to NULL terminate the list of attributes */
22587+};
22588+
22589+static struct attribute_group au_attr_group_body = {
22590+ .attrs = au_attr
22591+};
22592+
22593+struct attribute_group *au_attr_group = &au_attr_group_body;
22594+
22595+/* ---------------------------------------------------------------------- */
22596+
22597+/*
22598+ * they are copied from linux/lib/kobject.c,
22599+ * and will be exported in the future.
22600+ */
22601+static ssize_t au_attr_show(struct kobject *kobj, struct attribute *attr,
22602+ char *buf)
22603+{
22604+ struct kobj_attribute *kattr;
22605+ ssize_t ret = -EIO;
22606+
22607+ kattr = container_of(attr, struct kobj_attribute, attr);
22608+ if (kattr->show)
22609+ ret = kattr->show(kobj, kattr, buf);
22610+ return ret;
22611+}
22612+
22613+#ifdef CONFIG_AUFS_DEBUG
22614+static ssize_t au_attr_store(struct kobject *kobj, struct attribute *attr,
22615+ const char *buf, size_t count)
22616+{
22617+ struct kobj_attribute *kattr;
22618+ ssize_t ret = -EIO;
22619+
22620+ kattr = container_of(attr, struct kobj_attribute, attr);
22621+ if (kattr->store)
22622+ ret = kattr->store(kobj, kattr, buf, count);
22623+ return ret;
22624+}
22625+#endif
22626+
22627+static struct sysfs_ops sysaufs_ops = {
22628+ .show = au_attr_show,
22629+#ifdef CONFIG_AUFS_DEBUG
22630+ .store = au_attr_store
22631+#endif
22632+};
22633+
22634+static struct kobj_type au_ktype_body = {
22635+ .sysfs_ops = &sysaufs_ops
22636+};
22637+struct kobj_type *au_ktype = &au_ktype_body;
22638+
22639+/* ---------------------------------------------------------------------- */
22640+
22641+static noinline_for_stack
22642+int sysaufs_sbi_xi(struct seq_file *seq, struct file *xf, int dlgt,
22643+ int print_path)
22644+{
22645+ int err;
22646+ struct kstat st;
22647+ struct path path;
22648+
22649+ err = vfsub_getattr(xf->f_vfsmnt, xf->f_dentry, &st, dlgt);
22650+ if (!err) {
22651+ seq_printf(seq, "%llux%lu %lld",
22652+ st.blocks, st.blksize, (long long)st.size);
22653+ if (print_path) {
22654+ path.dentry = xf->f_dentry;
22655+ path.mnt = xf->f_vfsmnt;
22656+ seq_putc(seq, ' ');
22657+ seq_path(seq, &path, au_esc_chars);
22658+ }
22659+ seq_putc(seq, '\n');
22660+ } else
22661+ seq_printf(seq, "err %d\n", err);
22662+
22663+ AuTraceErr(err);
22664+ return err;
22665+}
22666+
22667+int sysaufs_sbi_xino(struct seq_file *seq, struct super_block *sb)
22668+{
22669+ int err;
22670+ unsigned int mnt_flags;
22671+ aufs_bindex_t bend, bindex;
22672+ unsigned char dlgt, xinodir;
22673+ struct kstat st;
22674+ struct path path;
22675+ struct au_sbinfo *sbinfo;
22676+ struct file *xf;
22677+
22678+ AuTraceEnter();
22679+
22680+ sbinfo = au_sbi(sb);
22681+ mnt_flags = au_mntflags(sb);
22682+ xinodir = !!au_opt_test(mnt_flags, XINODIR);
22683+ if (!au_opt_test_xino(mnt_flags)) {
22684+#ifdef CONFIG_AUFS_DEBUG
22685+ AuDebugOn(sbinfo->si_xib);
22686+ bend = au_sbend(sb);
22687+ for (bindex = 0; bindex <= bend; bindex++)
22688+ AuDebugOn(au_sbr(sb, bindex)->br_xino.xi_file);
22689+#endif
22690+ err = 0;
22691+ goto out; /* success */
22692+ }
22693+
22694+ dlgt = !!au_test_dlgt(mnt_flags);
22695+ err = sysaufs_sbi_xi(seq, sbinfo->si_xib, dlgt, xinodir);
22696+
22697+ bend = au_sbend(sb);
22698+ for (bindex = 0; !err && bindex <= bend; bindex++) {
22699+ xf = au_sbr(sb, bindex)->br_xino.xi_file;
22700+ if (!xf)
22701+ continue;
22702+ seq_printf(seq, "%d: ", bindex);
22703+ err = vfsub_getattr(xf->f_vfsmnt, xf->f_dentry, &st, dlgt);
22704+ if (!err) {
22705+ seq_printf(seq, "%ld, %llux%lu %lld",
22706+ (long)file_count(xf), st.blocks, st.blksize,
22707+ (long long)st.size);
22708+ if (xinodir) {
22709+ path.dentry = xf->f_dentry;
22710+ path.mnt = xf->f_vfsmnt;
22711+ seq_putc(seq, ' ');
22712+ seq_path(seq, &path, au_esc_chars);
22713+ }
22714+ seq_putc(seq, '\n');
22715+ } else
22716+ seq_printf(seq, "err %d\n", err);
22717+ }
22718+
22719+ out:
22720+ AuTraceErr(err);
22721+ return err;
22722+}
22723+
22724+#ifdef CONFIG_AUFS_EXPORT
22725+int sysaufs_sbi_xigen(struct seq_file *seq, struct super_block *sb)
22726+{
22727+ int err;
22728+ unsigned int mnt_flags;
22729+ struct au_sbinfo *sbinfo;
22730+
22731+ AuTraceEnter();
22732+
22733+ err = 0;
22734+ sbinfo = au_sbi(sb);
22735+ mnt_flags = au_mntflags(sb);
22736+ if (au_opt_test_xino(mnt_flags))
22737+ err = sysaufs_sbi_xi(seq, sbinfo->si_xigen,
22738+ !!au_opt_test(mnt_flags, DLGT),
22739+ !!au_opt_test(mnt_flags, XINODIR));
22740+
22741+ AuTraceErr(err);
22742+ return err;
22743+}
22744+#endif
22745+
22746+/*
22747+ * the lifetime of branch is independent from the entry under sysfs.
22748+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
22749+ * unlinked.
22750+ */
22751+#define SysaufsBr_PREFIX "br"
22752+static int sysaufs_sbi_br(struct seq_file *seq, struct super_block *sb,
22753+ aufs_bindex_t bindex)
22754+{
22755+ int err;
22756+ struct dentry *root;
22757+ struct au_branch *br;
22758+ struct path path;
22759+
22760+ LKTRTrace("b%d\n", bindex);
22761+
22762+ err = -ENOENT;
22763+ if (unlikely(au_sbend(sb) < bindex))
22764+ goto out;
22765+
22766+ err = 0;
22767+ root = sb->s_root;
22768+ di_read_lock_parent(root, !AuLock_IR);
22769+ br = au_sbr(sb, bindex);
22770+ path.mnt = br->br_mnt;
22771+ path.dentry = au_h_dptr(root, bindex);
22772+ seq_path(seq, &path, au_esc_chars);
22773+ di_read_unlock(root, !AuLock_IR);
22774+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
22775+
22776+ out:
22777+ AuTraceErr(err);
22778+ return err;
22779+}
22780+
22781+/* ---------------------------------------------------------------------- */
22782+
22783+static struct seq_file *au_seq(char *p, ssize_t len)
22784+{
22785+ struct seq_file *seq;
22786+
22787+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
22788+ if (seq) {
22789+ /* todo: necessary? */
22790+ /* mutex_init(&seq.lock); */
22791+ seq->buf = p;
22792+ seq->size = len;
22793+ return seq; /* success */
22794+ }
22795+
22796+ seq = ERR_PTR(-ENOMEM);
22797+ AuTraceErrPtr(seq);
22798+ return seq;
22799+}
22800+
22801+/* todo: file size may exceed PAGE_SIZE */
22802+ssize_t sysaufs_sbi_show(struct kobject *kobj, struct attribute *attr,
22803+ char *buf)
22804+{
22805+ ssize_t err;
22806+ long l;
22807+ struct au_sbinfo *sbinfo;
22808+ struct super_block *sb;
22809+ struct seq_file *seq;
22810+ char *name;
22811+ struct attribute **cattr;
22812+
22813+ LKTRTrace("%s/%s\n", kobject_name(kobj), attr->name);
22814+
22815+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
22816+ sb = sbinfo->si_sb;
22817+ si_noflush_read_lock(sb);
22818+
22819+ seq = au_seq(buf, PAGE_SIZE);
22820+ err = PTR_ERR(seq);
22821+ if (IS_ERR(seq))
22822+ goto out;
22823+
22824+ name = (void *)attr->name;
22825+ cattr = au_sbi_attrs;
22826+ while (*cattr) {
22827+ if (!strcmp(name, (*cattr)->name)) {
22828+ err = container_of(*cattr, struct au_sbi_attr, attr)
22829+ ->show(seq, sb);
22830+ goto out_seq;
22831+ }
22832+ cattr++;
22833+ }
22834+
22835+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
22836+ name += sizeof(SysaufsBr_PREFIX) - 1;
22837+ err = strict_strtol(name, 10, &l);
22838+ if (!err)
22839+ err = sysaufs_sbi_br(seq, sb, (aufs_bindex_t)l);
22840+ goto out_seq;
22841+ }
22842+ BUG();
22843+
22844+ out_seq:
22845+ if (!err) {
22846+ err = seq->count;
22847+ /* sysfs limit */
22848+ if (unlikely(err == PAGE_SIZE))
22849+ err = -EFBIG;
22850+ }
22851+ kfree(seq);
22852+ out:
22853+ si_read_unlock(sb);
22854+ AuTraceErr(err);
22855+ return err;
22856+}
22857+
22858+/* ---------------------------------------------------------------------- */
22859+
22860+void sysaufs_br_init(struct au_branch *br)
22861+{
22862+ br->br_attr.name = br->br_name;
22863+ br->br_attr.mode = S_IRUGO;
22864+ br->br_attr.owner = THIS_MODULE;
22865+}
22866+
22867+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
22868+{
22869+ struct au_sbinfo *sbinfo;
22870+ aufs_bindex_t bend;
22871+
22872+ LKTRTrace("b%d\n", bindex);
22873+
22874+ if (!sysaufs_brs)
22875+ return;
22876+
22877+ sbinfo = au_sbi(sb);
22878+ bend = au_sbend(sb);
22879+ for (; bindex <= bend; bindex++)
22880+ sysfs_remove_file(&sbinfo->si_kobj,
22881+ &au_sbr(sb, bindex)->br_attr);
22882+}
22883+
22884+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
22885+{
22886+ int err;
22887+ struct kobject *kobj;
22888+ aufs_bindex_t bend;
22889+ struct au_branch *br;
22890+
22891+ LKTRTrace("b%d\n", bindex);
22892+
22893+ if (!sysaufs_brs)
22894+ return;
22895+
22896+ kobj = &au_sbi(sb)->si_kobj;
22897+ bend = au_sbend(sb);
22898+ for (; bindex <= bend; bindex++) {
22899+ br = au_sbr(sb, bindex);
22900+ snprintf(br->br_name, sizeof(br->br_name),
22901+ SysaufsBr_PREFIX "%d", bindex);
22902+ err = sysfs_create_file(kobj, &br->br_attr);
22903+ if (unlikely(err))
22904+ AuWarn("failed %s under sysfs(%d)\n", br->br_name, err);
22905+ }
22906+}
22907diff -urN linux/fs/aufs/sysrq.c linux-aufs/fs/aufs/sysrq.c
22908--- linux/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
22909+++ linux-aufs/fs/aufs/sysrq.c 2009-03-12 16:18:04.000000000 +0100
22910@@ -0,0 +1,280 @@
22911+/*
22912+ * Copyright (C) 2005-2009 Junjiro Okajima
22913+ *
22914+ * This program, aufs is free software; you can redistribute it and/or modify
22915+ * it under the terms of the GNU General Public License as published by
22916+ * the Free Software Foundation; either version 2 of the License, or
22917+ * (at your option) any later version.
22918+ *
22919+ * This program is distributed in the hope that it will be useful,
22920+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22921+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22922+ * GNU General Public License for more details.
22923+ *
22924+ * You should have received a copy of the GNU General Public License
22925+ * along with this program; if not, write to the Free Software
22926+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22927+ */
22928+
22929+/*
22930+ * magic sysrq hanlder
22931+ *
22932+ * $Id$
22933+ */
22934+
22935+#include <linux/fs.h>
22936+#include <linux/module.h>
22937+#include <linux/moduleparam.h>
22938+/* #include <linux/sysrq.h> */
22939+#include "aufs.h"
22940+
22941+#ifdef CONFIG_AUFS_DEBUG_LOCK
22942+struct au_dbg_lock {
22943+ struct list_head list;
22944+ union {
22945+ struct super_block *sb;
22946+ struct dentry *dentry;
22947+ struct inode *inode;
22948+ void *any;
22949+ };
22950+ int flags;
22951+ unsigned int lsc;
22952+ pid_t pid;
22953+};
22954+
22955+static void au_dbg_reg(struct au_splhead *spl, void *any, int flags,
22956+ unsigned int lsc)
22957+{
22958+ struct au_dbg_lock *p = kmalloc(sizeof(*p), GFP_NOFS);
22959+
22960+ if (p) {
22961+ p->any = any;
22962+ p->flags = flags;
22963+ p->lsc = lsc;
22964+ p->pid = current->pid;
22965+ spin_lock(&spl->spin);
22966+ list_add(&p->list, &spl->head);
22967+ spin_unlock(&spl->spin);
22968+ }
22969+ WARN_ON(!p);
22970+}
22971+
22972+static void au_dbg_unreg(struct au_splhead *spl, void *any, int flags)
22973+{
22974+ struct au_dbg_lock *p, *tmp, *found;
22975+ struct list_head *head = &spl->head;
22976+ const pid_t pid = current->pid;
22977+
22978+ found = NULL;
22979+ spin_lock(&spl->spin);
22980+ list_for_each_entry_safe(p, tmp, head, list)
22981+ if (p->any == any && p->pid == pid) {
22982+ list_del(&p->list);
22983+ found = p;
22984+ break;
22985+ }
22986+ spin_unlock(&spl->spin);
22987+ kfree(found);
22988+ WARN_ON(!found);
22989+}
22990+
22991+/* ---------------------------------------------------------------------- */
22992+
22993+void au_dbg_locking_si_reg(struct super_block *sb, int flags)
22994+{
22995+ au_dbg_reg(au_sbi(sb)->si_dbg_lock + AuDbgLock_SI_LOCKING, sb, flags,
22996+ -1);
22997+}
22998+
22999+void au_dbg_locking_si_unreg(struct super_block *sb, int flags)
23000+{
23001+ au_dbg_unreg(au_sbi(sb)->si_dbg_lock + AuDbgLock_SI_LOCKING, sb, flags);
23002+}
23003+
23004+void au_dbg_locked_si_reg(struct super_block *sb, int flags)
23005+{
23006+ au_dbg_reg(au_sbi(sb)->si_dbg_lock + AuDbgLock_SI_LOCKED, sb, flags,
23007+ -1);
23008+}
23009+
23010+void au_dbg_locked_si_unreg(struct super_block *sb, int flags)
23011+{
23012+ au_dbg_unreg(au_sbi(sb)->si_dbg_lock + AuDbgLock_SI_LOCKED, sb, flags);
23013+}
23014+
23015+void au_dbg_locking_di_reg(struct dentry *d, int flags, unsigned int lsc)
23016+{
23017+ au_dbg_reg(au_sbi(d->d_sb)->si_dbg_lock + AuDbgLock_DI_LOCKING, d,
23018+ flags, lsc);
23019+}
23020+
23021+void au_dbg_locking_di_unreg(struct dentry *d, int flags)
23022+{
23023+ au_dbg_unreg(au_sbi(d->d_sb)->si_dbg_lock + AuDbgLock_DI_LOCKING, d,
23024+ flags);
23025+}
23026+
23027+void au_dbg_locked_di_reg(struct dentry *d, int flags, unsigned int lsc)
23028+{
23029+ au_dbg_reg(au_sbi(d->d_sb)->si_dbg_lock + AuDbgLock_DI_LOCKED, d, flags,
23030+ lsc);
23031+}
23032+
23033+void au_dbg_locked_di_unreg(struct dentry *d, int flags)
23034+{
23035+ au_dbg_unreg(au_sbi(d->d_sb)->si_dbg_lock + AuDbgLock_DI_LOCKED, d,
23036+ flags);
23037+}
23038+
23039+void au_dbg_locking_ii_reg(struct inode *i, int flags, unsigned int lsc)
23040+{
23041+ au_dbg_reg(au_sbi(i->i_sb)->si_dbg_lock + AuDbgLock_II_LOCKING, i,
23042+ flags, lsc);
23043+}
23044+
23045+void au_dbg_locking_ii_unreg(struct inode *i, int flags)
23046+{
23047+ au_dbg_unreg(au_sbi(i->i_sb)->si_dbg_lock + AuDbgLock_II_LOCKING, i,
23048+ flags);
23049+}
23050+
23051+void au_dbg_locked_ii_reg(struct inode *i, int flags, unsigned int lsc)
23052+{
23053+ au_dbg_reg(au_sbi(i->i_sb)->si_dbg_lock + AuDbgLock_II_LOCKED, i, flags,
23054+ lsc);
23055+}
23056+
23057+void au_dbg_locked_ii_unreg(struct inode *i, int flags)
23058+{
23059+ au_dbg_unreg(au_sbi(i->i_sb)->si_dbg_lock + AuDbgLock_II_LOCKED, i,
23060+ flags);
23061+}
23062+#endif /* CONFIG_AUFS_DEBUG_LOCK */
23063+
23064+/* ---------------------------------------------------------------------- */
23065+
23066+static void sysrq_sb(struct super_block *sb)
23067+{
23068+ char *plevel;
23069+ struct inode *i;
23070+ struct au_sbinfo *sbinfo;
23071+ struct file *file;
23072+
23073+ plevel = au_plevel;
23074+ au_plevel = KERN_WARNING;
23075+ au_debug_on();
23076+
23077+ sbinfo = au_sbi(sb);
23078+ pr_warning("si=%lx\n", au_si_mask ^ (unsigned long)sbinfo);
23079+ pr_warning(AUFS_NAME ": superblock\n");
23080+ au_dpri_sb(sb);
23081+ pr_warning(AUFS_NAME ": root dentry\n");
23082+ au_dpri_dentry(sb->s_root);
23083+ pr_warning(AUFS_NAME ": root inode\n");
23084+ au_dpri_inode(sb->s_root->d_inode);
23085+ pr_warning(AUFS_NAME ": isolated inode\n");
23086+ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
23087+ if (list_empty(&i->i_dentry))
23088+ au_dpri_inode(i);
23089+ pr_warning(AUFS_NAME ": files\n");
23090+ list_for_each_entry(file, &sb->s_files, f_u.fu_list)
23091+ if (au_test_aufs_file(file))
23092+ au_dpri_file(file);
23093+
23094+#ifdef CONFIG_AUFS_DEBUG_LOCK
23095+ {
23096+ struct au_dbg_lock *p;
23097+ struct list_head *head;
23098+
23099+ pr_warning(AUFS_NAME ": locking si\n");
23100+ head = &sbinfo->si_dbg_lock[AuDbgLock_SI_LOCKING].head;
23101+ list_for_each_entry(p, head, list)
23102+ pr_warning("pid: %d, 0x%x\n", p->pid, p->flags);
23103+ pr_warning(AUFS_NAME ": locked si\n");
23104+ head = &sbinfo->si_dbg_lock[AuDbgLock_SI_LOCKED].head;
23105+ list_for_each_entry(p, head, list)
23106+ pr_warning("pid: %d, 0x%x\n", p->pid, p->flags);
23107+ pr_warning(AUFS_NAME ": locking di\n");
23108+ head = &sbinfo->si_dbg_lock[AuDbgLock_DI_LOCKING].head;
23109+ list_for_each_entry(p, head, list) {
23110+ pr_warning("pid: %d, 0x%x, %d\n",
23111+ p->pid, p->flags, p->lsc);
23112+ au_dpri_dentry(p->dentry);
23113+ }
23114+ pr_warning(AUFS_NAME ": locked di\n");
23115+ head = &sbinfo->si_dbg_lock[AuDbgLock_DI_LOCKED].head;
23116+ list_for_each_entry(p, head, list) {
23117+ pr_warning("pid: %d, 0x%x, %d\n",
23118+ p->pid, p->flags, p->lsc);
23119+ au_dpri_dentry(p->dentry);
23120+ }
23121+ pr_warning(AUFS_NAME ": locking ii\n");
23122+ head = &sbinfo->si_dbg_lock[AuDbgLock_II_LOCKING].head;
23123+ list_for_each_entry(p, head, list) {
23124+ pr_warning("pid: %d, %d\n", p->pid, p->lsc);
23125+ au_dpri_inode(p->inode);
23126+ }
23127+ pr_warning(AUFS_NAME ": locked ii\n");
23128+ head = &sbinfo->si_dbg_lock[AuDbgLock_II_LOCKED].head;
23129+ list_for_each_entry(p, head, list) {
23130+ pr_warning("pid: %d, %d\n", p->pid, p->lsc);
23131+ au_dpri_inode(p->inode);
23132+ }
23133+ }
23134+#endif
23135+
23136+ au_plevel = plevel;
23137+ au_debug_off();
23138+}
23139+
23140+/* ---------------------------------------------------------------------- */
23141+
23142+/* module parameter */
23143+static char *aufs_sysrq_key = "a";
23144+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
23145+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
23146+
23147+static void au_sysrq(int key, struct tty_struct *tty)
23148+{
23149+ struct kobject *kobj;
23150+ struct au_sbinfo *sbinfo;
23151+
23152+ /* spin_lock(&au_kset->list_lock); */
23153+ list_for_each_entry(kobj, &au_kset->list, entry) {
23154+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
23155+ sysrq_sb(sbinfo->si_sb);
23156+ }
23157+ /* spin_unlock(&au_kset->list_lock); */
23158+}
23159+
23160+static struct sysrq_key_op au_sysrq_op = {
23161+ .handler = au_sysrq,
23162+ .help_msg = "Aufs",
23163+ .action_msg = "Aufs",
23164+ /* todo: test mask? */
23165+ .enable_mask = SYSRQ_ENABLE_DUMP
23166+};
23167+
23168+/* ---------------------------------------------------------------------- */
23169+
23170+int __init au_sysrq_init(void)
23171+{
23172+ int err;
23173+ char key;
23174+
23175+ err = -1;
23176+ key = *aufs_sysrq_key;
23177+ if ('a' <= key && key <= 'z')
23178+ err = register_sysrq_key(key, &au_sysrq_op);
23179+ if (unlikely(err))
23180+ AuErr("err %d, sysrq=%c\n", err, key);
23181+ return err;
23182+}
23183+
23184+void au_sysrq_fin(void)
23185+{
23186+ int err;
23187+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
23188+ if (unlikely(err))
23189+ AuErr("err %d (ignored)\n", err);
23190+}
23191diff -urN linux/fs/aufs/vdir.c linux-aufs/fs/aufs/vdir.c
23192--- linux/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
23193+++ linux-aufs/fs/aufs/vdir.c 2009-03-12 16:18:04.000000000 +0100
23194@@ -0,0 +1,941 @@
23195+/*
23196+ * Copyright (C) 2005-2009 Junjiro Okajima
23197+ *
23198+ * This program, aufs is free software; you can redistribute it and/or modify
23199+ * it under the terms of the GNU General Public License as published by
23200+ * the Free Software Foundation; either version 2 of the License, or
23201+ * (at your option) any later version.
23202+ *
23203+ * This program is distributed in the hope that it will be useful,
23204+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23205+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23206+ * GNU General Public License for more details.
23207+ *
23208+ * You should have received a copy of the GNU General Public License
23209+ * along with this program; if not, write to the Free Software
23210+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23211+ */
23212+
23213+/*
23214+ * virtual or vertical directory
23215+ *
23216+ * $Id$
23217+ */
23218+
23219+#include "aufs.h"
23220+
23221+static int calc_size(int namelen)
23222+{
23223+ int sz;
23224+
23225+ sz = sizeof(struct au_vdir_de) + namelen;
23226+ if (sizeof(ino_t) == sizeof(long)) {
23227+ const int mask = sizeof(ino_t) - 1;
23228+ if (sz & mask) {
23229+ sz += sizeof(ino_t);
23230+ sz &= ~mask;
23231+ }
23232+ }
23233+
23234+ AuDebugOn(sz % sizeof(ino_t));
23235+ return sz;
23236+}
23237+
23238+static int set_deblk_end(union au_vdir_deblk_p *p,
23239+ union au_vdir_deblk_p *deblk_end)
23240+{
23241+ if (calc_size(0) <= deblk_end->p - p->p) {
23242+ p->de->de_str.len = 0;
23243+ /* smp_mb(); */
23244+ return 0;
23245+ }
23246+ return -1; /* error */
23247+}
23248+
23249+/* returns true or false */
23250+static int is_deblk_end(union au_vdir_deblk_p *p,
23251+ union au_vdir_deblk_p *deblk_end)
23252+{
23253+ if (calc_size(0) <= deblk_end->p - p->p)
23254+ return !p->de->de_str.len;
23255+ return 1;
23256+}
23257+
23258+static au_vdir_deblk_t *last_deblk(struct au_vdir *vdir)
23259+{
23260+ return vdir->vd_deblk[vdir->vd_nblk - 1];
23261+}
23262+
23263+void au_nhash_init(struct au_nhash *nhash)
23264+{
23265+ int i;
23266+ for (i = 0; i < AuSize_NHASH; i++)
23267+ INIT_HLIST_HEAD(nhash->heads + i);
23268+}
23269+
23270+struct au_nhash *au_nhash_new(gfp_t gfp)
23271+{
23272+ struct au_nhash *nhash;
23273+
23274+ nhash = kmalloc(sizeof(*nhash), gfp);
23275+ if (nhash) {
23276+ au_nhash_init(nhash);
23277+ return nhash;
23278+ }
23279+ return ERR_PTR(-ENOMEM);
23280+}
23281+
23282+void au_nhash_del(struct au_nhash *nhash)
23283+{
23284+ au_nhash_fin(nhash);
23285+ kfree(nhash);
23286+}
23287+
23288+void au_nhash_move(struct au_nhash *dst, struct au_nhash *src)
23289+{
23290+ int i;
23291+
23292+ AuTraceEnter();
23293+
23294+ *dst = *src;
23295+ for (i = 0; i < AuSize_NHASH; i++) {
23296+ struct hlist_head *h;
23297+ h = dst->heads + i;
23298+ if (h->first)
23299+ h->first->pprev = &h->first;
23300+ INIT_HLIST_HEAD(src->heads + i);
23301+ }
23302+ /* smp_mb(); */
23303+}
23304+
23305+/* ---------------------------------------------------------------------- */
23306+
23307+void au_nhash_fin(struct au_nhash *whlist)
23308+{
23309+ int i;
23310+ struct hlist_head *head;
23311+ struct au_vdir_wh *tpos;
23312+ struct hlist_node *pos, *n;
23313+
23314+ AuTraceEnter();
23315+
23316+ for (i = 0; i < AuSize_NHASH; i++) {
23317+ head = whlist->heads + i;
23318+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
23319+ /* hlist_del(pos); */
23320+ kfree(tpos);
23321+ }
23322+ }
23323+}
23324+
23325+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
23326+ int limit)
23327+{
23328+ int n, i;
23329+ struct hlist_head *head;
23330+ struct au_vdir_wh *tpos;
23331+ struct hlist_node *pos;
23332+
23333+ LKTRTrace("limit %d\n", limit);
23334+
23335+ n = 0;
23336+ for (i = 0; i < AuSize_NHASH; i++) {
23337+ head = whlist->heads + i;
23338+ hlist_for_each_entry(tpos, pos, head, wh_hash)
23339+ if (tpos->wh_bindex == btgt && ++n > limit)
23340+ return 1;
23341+ }
23342+ return 0;
23343+}
23344+
23345+static unsigned int au_name_hash(const unsigned char *name, unsigned int len)
23346+{
23347+ return full_name_hash(name, len) % AuSize_NHASH;
23348+}
23349+
23350+/* returns found(true) or not */
23351+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int namelen)
23352+{
23353+ struct hlist_head *head;
23354+ struct au_vdir_wh *tpos;
23355+ struct hlist_node *pos;
23356+ struct au_vdir_destr *str;
23357+
23358+ LKTRTrace("%.*s\n", namelen, name);
23359+
23360+ head = whlist->heads + au_name_hash(name, namelen);
23361+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
23362+ str = &tpos->wh_str;
23363+ LKTRTrace("%.*s\n", str->len, str->name);
23364+ if (str->len == namelen && !memcmp(str->name, name, namelen))
23365+ return 1;
23366+ }
23367+ return 0;
23368+}
23369+
23370+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int namelen,
23371+ ino_t ino, unsigned int d_type, aufs_bindex_t bindex,
23372+ unsigned char shwh)
23373+{
23374+ int err;
23375+ struct au_vdir_destr *str;
23376+ struct au_vdir_wh *wh;
23377+
23378+ LKTRTrace("%.*s\n", namelen, name);
23379+
23380+ err = -ENOMEM;
23381+ wh = kmalloc(sizeof(*wh) + namelen, GFP_NOFS);
23382+ if (unlikely(!wh))
23383+ goto out;
23384+ err = 0;
23385+ wh->wh_bindex = bindex;
23386+ if (shwh)
23387+ au_shwh_init_wh(wh, ino, d_type);
23388+ str = &wh->wh_str;
23389+ str->len = namelen;
23390+ memcpy(str->name, name, namelen);
23391+ hlist_add_head(&wh->wh_hash,
23392+ whlist->heads + au_name_hash(name, namelen));
23393+ /* smp_mb(); */
23394+
23395+ out:
23396+ AuTraceErr(err);
23397+ return err;
23398+}
23399+
23400+/* ---------------------------------------------------------------------- */
23401+
23402+void au_vdir_free(struct au_vdir *vdir)
23403+{
23404+ au_vdir_deblk_t **deblk;
23405+
23406+ AuTraceEnter();
23407+
23408+ deblk = vdir->vd_deblk;
23409+ while (vdir->vd_nblk--) {
23410+ kfree(*deblk);
23411+ deblk++;
23412+ }
23413+ kfree(vdir->vd_deblk);
23414+ au_cache_free_vdir(vdir);
23415+}
23416+
23417+static int append_deblk(struct au_vdir *vdir)
23418+{
23419+ int err, sz, i;
23420+ au_vdir_deblk_t **o;
23421+ union au_vdir_deblk_p p, deblk_end;
23422+
23423+ AuTraceEnter();
23424+
23425+ err = -ENOMEM;
23426+ sz = sizeof(*o) * vdir->vd_nblk;
23427+ o = au_kzrealloc(vdir->vd_deblk, sz, sz + sizeof(*o), GFP_NOFS);
23428+ if (unlikely(!o))
23429+ goto out;
23430+ vdir->vd_deblk = o;
23431+ p.deblk = kmalloc(sizeof(*p.deblk), GFP_NOFS);
23432+ if (p.deblk) {
23433+ i = vdir->vd_nblk++;
23434+ vdir->vd_deblk[i] = p.deblk;
23435+ vdir->vd_last.i = i;
23436+ vdir->vd_last.p.p = p.p;
23437+ deblk_end.deblk = p.deblk + 1;
23438+ err = set_deblk_end(&p, &deblk_end);
23439+ AuDebugOn(err);
23440+ }
23441+
23442+ out:
23443+ AuTraceErr(err);
23444+ return err;
23445+}
23446+
23447+static struct au_vdir *alloc_vdir(void)
23448+{
23449+ struct au_vdir *vdir;
23450+ int err;
23451+
23452+ AuTraceEnter();
23453+
23454+ err = -ENOMEM;
23455+ vdir = au_cache_alloc_vdir();
23456+ if (unlikely(!vdir))
23457+ goto out;
23458+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
23459+ if (unlikely(!vdir->vd_deblk))
23460+ goto out_free;
23461+
23462+ vdir->vd_nblk = 0;
23463+ vdir->vd_version = 0;
23464+ vdir->vd_jiffy = 0;
23465+ err = append_deblk(vdir);
23466+ if (!err)
23467+ return vdir; /* success */
23468+
23469+ kfree(vdir->vd_deblk);
23470+
23471+ out_free:
23472+ au_cache_free_vdir(vdir);
23473+ out:
23474+ vdir = ERR_PTR(err);
23475+ AuTraceErrPtr(vdir);
23476+ return vdir;
23477+}
23478+
23479+static int reinit_vdir(struct au_vdir *vdir)
23480+{
23481+ int err;
23482+ union au_vdir_deblk_p p, deblk_end;
23483+
23484+ AuTraceEnter();
23485+
23486+ while (vdir->vd_nblk > 1) {
23487+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
23488+ vdir->vd_deblk[vdir->vd_nblk - 1] = NULL;
23489+ vdir->vd_nblk--;
23490+ }
23491+ p.deblk = vdir->vd_deblk[0];
23492+ deblk_end.deblk = p.deblk + 1;
23493+ err = set_deblk_end(&p, &deblk_end);
23494+ AuDebugOn(err);
23495+ vdir->vd_version = 0;
23496+ vdir->vd_jiffy = 0;
23497+ vdir->vd_last.i = 0;
23498+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
23499+ /* smp_mb(); */
23500+ return err;
23501+}
23502+
23503+/* ---------------------------------------------------------------------- */
23504+
23505+static void free_dehlist(struct au_nhash *dehlist)
23506+{
23507+ int i;
23508+ struct hlist_head *head;
23509+ struct au_vdir_dehstr *tpos;
23510+ struct hlist_node *pos, *n;
23511+
23512+ AuTraceEnter();
23513+
23514+ for (i = 0; i < AuSize_NHASH; i++) {
23515+ head = dehlist->heads + i;
23516+ hlist_for_each_entry_safe(tpos, pos, n, head, hash) {
23517+ /* hlist_del(pos); */
23518+ au_cache_free_dehstr(tpos);
23519+ }
23520+ }
23521+}
23522+
23523+/* returns found(true) or not */
23524+static int test_known(struct au_nhash *delist, char *name, int namelen)
23525+{
23526+ struct hlist_head *head;
23527+ struct au_vdir_dehstr *tpos;
23528+ struct hlist_node *pos;
23529+ struct au_vdir_destr *str;
23530+
23531+ LKTRTrace("%.*s\n", namelen, name);
23532+
23533+ head = delist->heads + au_name_hash(name, namelen);
23534+ hlist_for_each_entry(tpos, pos, head, hash) {
23535+ str = tpos->str;
23536+ LKTRTrace("%.*s\n", str->len, str->name);
23537+ if (str->len == namelen && !memcmp(str->name, name, namelen))
23538+ return 1;
23539+ }
23540+ return 0;
23541+
23542+}
23543+
23544+static int append_de(struct au_vdir *vdir, char *name, int namelen, ino_t ino,
23545+ unsigned int d_type, struct au_nhash *delist)
23546+{
23547+ int err, sz;
23548+ union au_vdir_deblk_p p, *room, deblk_end;
23549+ struct au_vdir_dehstr *dehstr;
23550+
23551+ LKTRTrace("%.*s %d, i%lu, dt%u\n",
23552+ namelen, name, namelen, (unsigned long)ino, d_type);
23553+
23554+ p.deblk = last_deblk(vdir);
23555+ deblk_end.deblk = p.deblk + 1;
23556+ room = &vdir->vd_last.p;
23557+ AuDebugOn(room->p < p.p || deblk_end.p <= room->p
23558+ || !is_deblk_end(room, &deblk_end));
23559+
23560+ sz = calc_size(namelen);
23561+ if (unlikely(sz > deblk_end.p - room->p)) {
23562+ err = append_deblk(vdir);
23563+ if (unlikely(err))
23564+ goto out;
23565+ p.deblk = last_deblk(vdir);
23566+ deblk_end.deblk = p.deblk + 1;
23567+ /* smp_mb(); */
23568+ AuDebugOn(room->p != p.p);
23569+ }
23570+
23571+ err = -ENOMEM;
23572+ dehstr = au_cache_alloc_dehstr();
23573+ if (unlikely(!dehstr))
23574+ goto out;
23575+ dehstr->str = &room->de->de_str;
23576+ hlist_add_head(&dehstr->hash,
23577+ delist->heads + au_name_hash(name, namelen));
23578+
23579+ room->de->de_ino = ino;
23580+ room->de->de_type = d_type;
23581+ room->de->de_str.len = namelen;
23582+ memcpy(room->de->de_str.name, name, namelen);
23583+
23584+ err = 0;
23585+ room->p += sz;
23586+ if (unlikely(set_deblk_end(room, &deblk_end)))
23587+ err = append_deblk(vdir);
23588+ /* smp_mb(); */
23589+
23590+ out:
23591+ AuTraceErr(err);
23592+ return err;
23593+}
23594+
23595+/* ---------------------------------------------------------------------- */
23596+
23597+static int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
23598+ unsigned int d_type, ino_t *ino)
23599+{
23600+ int err;
23601+ struct au_xino_entry xinoe;
23602+ struct mutex *mtx;
23603+ const int isdir = (d_type == DT_DIR);
23604+
23605+ /* prevent hardlinks from race condition */
23606+ mtx = NULL;
23607+ if (!isdir) {
23608+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
23609+ mutex_lock(mtx);
23610+ }
23611+ err = au_xino_read(sb, bindex, h_ino, &xinoe);
23612+ if (unlikely(err))
23613+ goto out;
23614+
23615+ if (!xinoe.ino) {
23616+ err = -EIO;
23617+ xinoe.ino = au_xino_new_ino(sb);
23618+ if (unlikely(!xinoe.ino))
23619+ goto out;
23620+
23621+#if 0 /* reserved for future use */
23622+ struct inode *h_inode;
23623+ xinoe.h_gen = AuXino_INVALID_HGEN;
23624+ h_inode = ilookup(au_sbr_sb(sb, bindex), h_ino);
23625+ if (h_inode) {
23626+ if (!is_bad_inode(h_inode)) {
23627+ xinoe.h_gen = h_inode->i_generation;
23628+ WARN_ON(xinoe.h_gen == AuXino_INVALID_HGEN);
23629+ }
23630+ iput(h_inode);
23631+ }
23632+#endif
23633+ err = au_xino_write(sb, bindex, h_ino, &xinoe);
23634+ if (unlikely(err))
23635+ goto out;
23636+ }
23637+
23638+ *ino = xinoe.ino;
23639+
23640+ out:
23641+ if (!isdir)
23642+ mutex_unlock(mtx);
23643+ AuTraceErr(err);
23644+ return err;
23645+}
23646+
23647+static int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
23648+ unsigned int d_type, ino_t *ino)
23649+{
23650+#ifdef CONFIG_AUFS_SHWH
23651+ return au_ino(sb, bindex, h_ino, d_type, ino);
23652+#else
23653+ return 0;
23654+#endif
23655+}
23656+
23657+#define AuFillVdir_CALLED 1
23658+#define AuFillVdir_SHWH (1 << 1)
23659+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
23660+#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
23661+#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
23662+#ifndef CONFIG_AUFS_SHWH
23663+#undef AuFillVdir_SHWH
23664+#define AuFillVdir_SHWH 0
23665+#endif
23666+
23667+struct fillvdir_arg {
23668+ struct file *file;
23669+ struct au_vdir *vdir;
23670+ struct au_nhash *delist;
23671+ struct au_nhash *whlist;
23672+ aufs_bindex_t bindex;
23673+ unsigned int flags;
23674+ int err;
23675+};
23676+
23677+static int fillvdir(void *__arg, const char *__name, int namelen, loff_t offset,
23678+ u64 h_ino, unsigned int d_type)
23679+{
23680+ struct fillvdir_arg *arg = __arg;
23681+ char *name = (void *)__name;
23682+ aufs_bindex_t bindex, bend;
23683+ struct super_block *sb;
23684+ ino_t ino;
23685+
23686+ LKTRTrace("%.*s, namelen %d, i%llu, dt%u\n",
23687+ namelen, name, namelen, (unsigned long long)h_ino, d_type);
23688+
23689+ sb = arg->file->f_dentry->d_sb;
23690+ bend = arg->bindex;
23691+ arg->err = 0;
23692+ au_fset_fillvdir(arg->flags, CALLED);
23693+ /* smp_mb(); */
23694+ if (namelen <= AUFS_WH_PFX_LEN
23695+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
23696+ for (bindex = 0; bindex < bend; bindex++)
23697+ if (test_known(arg->delist + bindex, name, namelen)
23698+ || au_nhash_test_known_wh(arg->whlist + bindex,
23699+ name, namelen))
23700+ goto out; /* already exists or whiteouted */
23701+
23702+ ino = 1; /* why does gcc warns? */
23703+ arg->err = au_ino(sb, bend, h_ino, d_type, &ino);
23704+ if (!arg->err)
23705+ arg->err = append_de(arg->vdir, name, namelen, ino,
23706+ d_type, arg->delist + bend);
23707+ } else {
23708+ name += AUFS_WH_PFX_LEN;
23709+ namelen -= AUFS_WH_PFX_LEN;
23710+ for (bindex = 0; bindex < bend; bindex++)
23711+ if (au_nhash_test_known_wh(arg->whlist + bend, name,
23712+ namelen))
23713+ goto out; /* already whiteouted */
23714+
23715+ ino = 1; /* dummy */
23716+ if (au_ftest_fillvdir(arg->flags, SHWH))
23717+ arg->err = au_wh_ino(sb, bend, h_ino, d_type, &ino);
23718+ if (!arg->err)
23719+ arg->err = au_nhash_append_wh
23720+ (arg->whlist + bend, name, namelen, ino, d_type,
23721+ bend, au_ftest_fillvdir(arg->flags, SHWH));
23722+ }
23723+
23724+ out:
23725+ if (!arg->err)
23726+ arg->vdir->vd_jiffy = jiffies;
23727+ /* smp_mb(); */
23728+ AuTraceErr(arg->err);
23729+ return arg->err;
23730+}
23731+
23732+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
23733+ aufs_bindex_t bstart, aufs_bindex_t bend,
23734+ struct au_nhash *_whlist, struct au_nhash *_delist)
23735+{
23736+#ifdef CONFIG_AUFS_SHWH
23737+ int err, i;
23738+ struct hlist_head *head;
23739+ struct au_vdir_wh *tpos;
23740+ struct hlist_node *pos, *n;
23741+ char *p, *o;
23742+ struct au_nhash *whlist, *delist;
23743+ struct au_vdir_destr *destr;
23744+ aufs_bindex_t bindex;
23745+
23746+ AuTraceEnter();
23747+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
23748+
23749+ err = -ENOMEM;
23750+ o = p = __getname();
23751+ if (unlikely(!p))
23752+ goto out;
23753+
23754+ err = 0;
23755+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
23756+ p += AUFS_WH_PFX_LEN;
23757+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
23758+ whlist = _whlist + bindex;
23759+ delist = _delist + bindex;
23760+
23761+ for (i = 0; i < AuSize_NHASH; i++) {
23762+ head = whlist->heads + i;
23763+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
23764+ destr = &tpos->wh_str;
23765+ memcpy(p, destr->name, destr->len);
23766+ err = append_de(vdir, o,
23767+ destr->len + AUFS_WH_PFX_LEN,
23768+ tpos->wh_ino, tpos->wh_type,
23769+ delist);
23770+ if (unlikely(err))
23771+ break;
23772+ }
23773+ }
23774+ }
23775+
23776+ __putname(o);
23777+
23778+ out:
23779+ AuTraceErr(err);
23780+ return err;
23781+#else
23782+ return 0;
23783+#endif
23784+}
23785+
23786+static int au_do_read_vdir(struct fillvdir_arg *arg)
23787+{
23788+ int err;
23789+ unsigned int mnt_flags;
23790+ loff_t offset;
23791+ aufs_bindex_t bend, bindex, bstart;
23792+ unsigned char dlgt, shwh;
23793+ struct super_block *sb;
23794+ struct file *hf;
23795+
23796+ AuTraceEnter();
23797+
23798+ err = -ENOMEM;
23799+ bend = au_fbend(arg->file);
23800+ arg->delist = kmalloc(sizeof(*arg->delist) * (bend + 1), GFP_NOFS);
23801+ if (unlikely(!arg->delist))
23802+ goto out;
23803+ arg->whlist = kmalloc(sizeof(*arg->whlist) * (bend + 1), GFP_NOFS);
23804+ if (unlikely(!arg->whlist))
23805+ goto out_delist;
23806+ err = 0;
23807+ for (bindex = 0; bindex <= bend; bindex++) {
23808+ au_nhash_init(arg->delist + bindex);
23809+ au_nhash_init(arg->whlist + bindex);
23810+ }
23811+
23812+ sb = arg->file->f_dentry->d_sb;
23813+ mnt_flags = au_mntflags(sb);
23814+ dlgt = !!au_test_dlgt(mnt_flags);
23815+ arg->flags = 0;
23816+ shwh = 0;
23817+ if (au_opt_test(mnt_flags, SHWH)) {
23818+ shwh = 1;
23819+ au_fset_fillvdir(arg->flags, SHWH);
23820+ }
23821+ bstart = au_fbstart(arg->file);
23822+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
23823+ hf = au_h_fptr(arg->file, bindex);
23824+ if (!hf)
23825+ continue;
23826+
23827+ offset = vfsub_llseek(hf, 0, SEEK_SET);
23828+ err = offset;
23829+ if (unlikely(offset))
23830+ break;
23831+ arg->bindex = bindex;
23832+ do {
23833+ arg->err = 0;
23834+ au_fclr_fillvdir(arg->flags, CALLED);
23835+ /* smp_mb(); */
23836+ err = vfsub_readdir(hf, fillvdir, arg, dlgt);
23837+ if (err >= 0)
23838+ err = arg->err;
23839+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
23840+ }
23841+
23842+ if (!err && shwh)
23843+ err = au_handle_shwh(sb, arg->vdir, bstart, bend, arg->whlist,
23844+ arg->delist);
23845+
23846+ for (bindex = bstart; bindex <= bend; bindex++) {
23847+ free_dehlist(arg->delist + bindex);
23848+ au_nhash_fin(arg->whlist + bindex);
23849+ }
23850+ kfree(arg->whlist);
23851+
23852+ out_delist:
23853+ kfree(arg->delist);
23854+ out:
23855+ AuTraceErr(err);
23856+ return err;
23857+}
23858+
23859+static int read_vdir(struct file *file, int may_read)
23860+{
23861+ int err;
23862+ unsigned long expire;
23863+ struct fillvdir_arg arg;
23864+ unsigned char do_read;
23865+ struct dentry *dentry;
23866+ struct inode *inode;
23867+ struct au_vdir *vdir, *allocated;
23868+ struct super_block *sb;
23869+
23870+ dentry = file->f_dentry;
23871+ LKTRTrace("%.*s, may %d\n", AuDLNPair(dentry), may_read);
23872+ FiMustWriteLock(file);
23873+ inode = dentry->d_inode;
23874+ IMustLock(inode);
23875+ IiMustWriteLock(inode);
23876+ AuDebugOn(!S_ISDIR(inode->i_mode));
23877+
23878+ err = 0;
23879+ allocated = NULL;
23880+ do_read = 0;
23881+ sb = inode->i_sb;
23882+ expire = au_sbi(sb)->si_rdcache;
23883+ vdir = au_ivdir(inode);
23884+ if (!vdir) {
23885+ AuDebugOn(au_fvdir_cache(file));
23886+ do_read = 1;
23887+ vdir = alloc_vdir();
23888+ err = PTR_ERR(vdir);
23889+ if (IS_ERR(vdir))
23890+ goto out;
23891+ err = 0;
23892+ allocated = vdir;
23893+ } else if (may_read
23894+ && (inode->i_version != vdir->vd_version
23895+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
23896+ LKTRTrace("iver %llu, vdver %lu, exp %lu\n",
23897+ (unsigned long long)inode->i_version,
23898+ vdir->vd_version, vdir->vd_jiffy + expire);
23899+ do_read = 1;
23900+ err = reinit_vdir(vdir);
23901+ if (unlikely(err))
23902+ goto out;
23903+ }
23904+
23905+ if (!do_read)
23906+ return 0; /* success */
23907+
23908+ arg.file = file;
23909+ arg.vdir = vdir;
23910+ err = au_do_read_vdir(&arg);
23911+ if (!err) {
23912+ /* todo: necessary? */
23913+ /* file->f_pos = 0; */
23914+ vdir->vd_version = inode->i_version;
23915+ vdir->vd_last.i = 0;
23916+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
23917+ if (allocated)
23918+ au_set_ivdir(inode, allocated);
23919+ } else if (allocated)
23920+ au_vdir_free(allocated);
23921+
23922+ out:
23923+ AuTraceErr(err);
23924+ return err;
23925+}
23926+
23927+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
23928+{
23929+ int err, i, rerr, n;
23930+
23931+ AuTraceEnter();
23932+ AuDebugOn(tgt->vd_nblk != 1);
23933+
23934+ err = -ENOMEM;
23935+ if (tgt->vd_nblk < src->vd_nblk) {
23936+ au_vdir_deblk_t **p;
23937+ p = au_kzrealloc(tgt->vd_deblk, sizeof(*p) * tgt->vd_nblk,
23938+ sizeof(*p) * src->vd_nblk, GFP_NOFS);
23939+ if (unlikely(!p))
23940+ goto out;
23941+ tgt->vd_deblk = p;
23942+ }
23943+
23944+ tgt->vd_nblk = src->vd_nblk;
23945+ n = src->vd_nblk;
23946+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], AuSize_DEBLK);
23947+ /* tgt->vd_last.i = 0; */
23948+ /* tgt->vd_last.p.deblk = tgt->vd_deblk[0]; */
23949+ tgt->vd_version = src->vd_version;
23950+ tgt->vd_jiffy = src->vd_jiffy;
23951+
23952+ for (i = 1; i < n; i++) {
23953+ tgt->vd_deblk[i] = kmalloc(AuSize_DEBLK, GFP_NOFS);
23954+ if (tgt->vd_deblk[i])
23955+ memcpy(tgt->vd_deblk[i], src->vd_deblk[i],
23956+ AuSize_DEBLK);
23957+ else
23958+ goto out;
23959+ }
23960+ /* smp_mb(); */
23961+ return 0; /* success */
23962+
23963+ out:
23964+ rerr = reinit_vdir(tgt);
23965+ BUG_ON(rerr);
23966+ AuTraceErr(err);
23967+ return err;
23968+}
23969+
23970+int au_vdir_init(struct file *file)
23971+{
23972+ int err;
23973+ struct dentry *dentry;
23974+ struct inode *inode;
23975+ struct au_vdir *vdir_cache, *allocated;
23976+
23977+ dentry = file->f_dentry;
23978+ LKTRTrace("%.*s, pos %lld\n", AuDLNPair(dentry), file->f_pos);
23979+ FiMustWriteLock(file);
23980+ inode = dentry->d_inode;
23981+ IiMustWriteLock(inode);
23982+ AuDebugOn(!S_ISDIR(inode->i_mode));
23983+
23984+ err = read_vdir(file, !file->f_pos);
23985+ if (unlikely(err))
23986+ goto out;
23987+
23988+ allocated = NULL;
23989+ vdir_cache = au_fvdir_cache(file);
23990+ if (!vdir_cache) {
23991+ vdir_cache = alloc_vdir();
23992+ err = PTR_ERR(vdir_cache);
23993+ if (IS_ERR(vdir_cache))
23994+ goto out;
23995+ allocated = vdir_cache;
23996+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
23997+ err = reinit_vdir(vdir_cache);
23998+ if (unlikely(err))
23999+ goto out;
24000+ } else
24001+ return 0; /* success */
24002+
24003+ err = copy_vdir(vdir_cache, au_ivdir(inode));
24004+ if (!err) {
24005+ file->f_version = inode->i_version;
24006+ if (allocated)
24007+ au_set_fvdir_cache(file, allocated);
24008+ } else if (allocated)
24009+ au_vdir_free(allocated);
24010+
24011+ out:
24012+ AuTraceErr(err);
24013+ return err;
24014+}
24015+
24016+static loff_t calc_offset(struct au_vdir *vdir)
24017+{
24018+ loff_t offset;
24019+ union au_vdir_deblk_p p;
24020+
24021+ p.deblk = vdir->vd_deblk[vdir->vd_last.i];
24022+ offset = vdir->vd_last.p.p - p.p;
24023+ offset += sizeof(*p.deblk) * vdir->vd_last.i;
24024+ return offset;
24025+}
24026+
24027+/* returns true or false */
24028+static int seek_vdir(struct file *file)
24029+{
24030+ int valid, i, n;
24031+ struct dentry *dentry;
24032+ struct au_vdir *vdir_cache;
24033+ loff_t offset;
24034+ union au_vdir_deblk_p p, deblk_end;
24035+
24036+ dentry = file->f_dentry;
24037+ LKTRTrace("%.*s, pos %lld\n", AuDLNPair(dentry), file->f_pos);
24038+ vdir_cache = au_fvdir_cache(file);
24039+ AuDebugOn(!vdir_cache);
24040+
24041+ valid = 1;
24042+ offset = calc_offset(vdir_cache);
24043+ LKTRTrace("offset %lld\n", offset);
24044+ if (file->f_pos == offset)
24045+ goto out;
24046+
24047+ vdir_cache->vd_last.i = 0;
24048+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
24049+ if (!file->f_pos)
24050+ goto out;
24051+
24052+ valid = 0;
24053+ i = file->f_pos / AuSize_DEBLK;
24054+ LKTRTrace("i %d\n", i);
24055+ if (i >= vdir_cache->vd_nblk)
24056+ goto out;
24057+
24058+ n = vdir_cache->vd_nblk;
24059+ for (; i < n; i++) {
24060+ p.deblk = vdir_cache->vd_deblk[i];
24061+ deblk_end.deblk = p.deblk + 1;
24062+ offset = i;
24063+ offset *= AuSize_DEBLK;
24064+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
24065+ int l;
24066+ l = calc_size(p.de->de_str.len);
24067+ offset += l;
24068+ p.p += l;
24069+ }
24070+ if (!is_deblk_end(&p, &deblk_end)) {
24071+ valid = 1;
24072+ vdir_cache->vd_last.i = i;
24073+ vdir_cache->vd_last.p = p;
24074+ break;
24075+ }
24076+ }
24077+
24078+ out:
24079+ /* smp_mb(); */
24080+ AuTraceErr(!valid);
24081+ return valid;
24082+}
24083+
24084+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
24085+{
24086+ int err, l;
24087+ struct dentry *dentry;
24088+ struct au_vdir *vdir_cache;
24089+ struct au_vdir_de *de;
24090+ union au_vdir_deblk_p deblk_end;
24091+
24092+ dentry = file->f_dentry;
24093+ LKTRTrace("%.*s, pos %lld\n", AuDLNPair(dentry), file->f_pos);
24094+ vdir_cache = au_fvdir_cache(file);
24095+ AuDebugOn(!vdir_cache);
24096+
24097+ if (!seek_vdir(file))
24098+ return 0;
24099+
24100+ while (1) {
24101+ deblk_end.deblk
24102+ = vdir_cache->vd_deblk[vdir_cache->vd_last.i] + 1;
24103+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
24104+ de = vdir_cache->vd_last.p.de;
24105+ LKTRTrace("%.*s, off%lld, i%lu, dt%d\n",
24106+ de->de_str.len, de->de_str.name,
24107+ file->f_pos, (unsigned long)de->de_ino,
24108+ de->de_type);
24109+ err = filldir(dirent, de->de_str.name, de->de_str.len,
24110+ file->f_pos, de->de_ino, de->de_type);
24111+ if (unlikely(err)) {
24112+ AuTraceErr(err);
24113+ /* todo: ignore the error caused by udba? */
24114+ /* return err; */
24115+ return 0;
24116+ }
24117+
24118+ l = calc_size(de->de_str.len);
24119+ vdir_cache->vd_last.p.p += l;
24120+ file->f_pos += l;
24121+ }
24122+ if (vdir_cache->vd_last.i < vdir_cache->vd_nblk - 1) {
24123+ vdir_cache->vd_last.i++;
24124+ vdir_cache->vd_last.p.deblk
24125+ = vdir_cache->vd_deblk[vdir_cache->vd_last.i];
24126+ file->f_pos = sizeof(*vdir_cache->vd_last.p.deblk)
24127+ * vdir_cache->vd_last.i;
24128+ continue;
24129+ }
24130+ break;
24131+ }
24132+
24133+ /* smp_mb(); */
24134+ return 0;
24135+}
24136diff -urN linux/fs/aufs/vfsub.c linux-aufs/fs/aufs/vfsub.c
24137--- linux/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
24138+++ linux-aufs/fs/aufs/vfsub.c 2009-03-12 16:18:04.000000000 +0100
24139@@ -0,0 +1,686 @@
24140+/*
24141+ * Copyright (C) 2005-2009 Junjiro Okajima
24142+ *
24143+ * This program, aufs is free software; you can redistribute it and/or modify
24144+ * it under the terms of the GNU General Public License as published by
24145+ * the Free Software Foundation; either version 2 of the License, or
24146+ * (at your option) any later version.
24147+ *
24148+ * This program is distributed in the hope that it will be useful,
24149+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24150+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24151+ * GNU General Public License for more details.
24152+ *
24153+ * You should have received a copy of the GNU General Public License
24154+ * along with this program; if not, write to the Free Software
24155+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24156+ */
24157+
24158+/*
24159+ * sub-routines for VFS
24160+ *
24161+ * $Id$
24162+ */
24163+
24164+#include <linux/uaccess.h>
24165+#include "aufs.h"
24166+
24167+/* ---------------------------------------------------------------------- */
24168+
24169+void vfsub_args_init(struct vfsub_args *vargs, struct au_hin_ignore *ign,
24170+ int dlgt, int force_unlink)
24171+{
24172+ do_vfsub_args_reinit(vargs, ign);
24173+ vargs->flags = 0;
24174+ if (dlgt)
24175+ vfsub_fset(vargs->flags, DLGT);
24176+ if (force_unlink)
24177+ vfsub_fset(vargs->flags, FORCE_UNLINK);
24178+}
24179+
24180+/* ---------------------------------------------------------------------- */
24181+
24182+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
24183+{
24184+ struct file *err;
24185+
24186+ LKTRTrace("%s\n", path);
24187+
24188+ lockdep_off();
24189+ err = filp_open(path, oflags, mode);
24190+ lockdep_on();
24191+ if (!IS_ERR(err))
24192+ au_update_fuse_h_inode(err->f_vfsmnt, err->f_dentry); /*ignore*/
24193+ return err;
24194+}
24195+
24196+int vfsub_path_lookup(const char *name, unsigned int flags,
24197+ struct nameidata *nd)
24198+{
24199+ int err;
24200+
24201+ LKTRTrace("%s\n", name);
24202+
24203+ /* lockdep_off(); */
24204+ err = path_lookup(name, flags, nd);
24205+ /* lockdep_on(); */
24206+ if (!err)
24207+ au_update_fuse_h_inode(nd->path.mnt, nd->path.dentry);
24208+ /*ignore*/
24209+ return err;
24210+}
24211+
24212+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
24213+ int len)
24214+{
24215+ struct dentry *d;
24216+
24217+ LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name);
24218+ IMustLock(parent->d_inode);
24219+
24220+ d = lookup_one_len(name, parent, len);
24221+ if (!IS_ERR(d))
24222+ au_update_fuse_h_inode(NULL, d); /*ignore*/
24223+ return d;
24224+}
24225+
24226+#ifdef CONFIG_AUFS_LHASH_PATCH
24227+struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent,
24228+ struct nameidata *nd)
24229+{
24230+ struct dentry *d;
24231+
24232+ LKTRTrace("%.*s/%.*s, nd %d\n",
24233+ AuDLNPair(parent), AuLNPair(name), !!nd);
24234+ if (nd)
24235+ LKTRTrace("nd{0x%x}\n", nd->flags);
24236+ IMustLock(parent->d_inode);
24237+
24238+ d = __lookup_hash(name, parent, nd);
24239+ if (!IS_ERR(d))
24240+ au_update_fuse_h_inode(NULL, d); /*ignore*/
24241+ return d;
24242+}
24243+#endif
24244+
24245+/* ---------------------------------------------------------------------- */
24246+
24247+int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
24248+ struct nameidata *nd)
24249+{
24250+ int err;
24251+ struct vfsmount *mnt;
24252+
24253+ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
24254+ IMustLock(dir);
24255+
24256+ err = vfs_create(dir, dentry, mode, nd);
24257+ if (!err) {
24258+ mnt = NULL;
24259+ if (nd)
24260+ mnt = nd->path.mnt;
24261+ /* dir inode is locked */
24262+ au_update_fuse_h_inode(mnt, dentry->d_parent); /*ignore*/
24263+ au_update_fuse_h_inode(mnt, dentry); /*ignore*/
24264+ }
24265+ return err;
24266+}
24267+
24268+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
24269+#define VfsubSymlinkArgs dir, dentry, symname
24270+#else
24271+#define VfsubSymlinkArgs dir, dentry, symname, mode
24272+#endif
24273+
24274+int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
24275+ const char *symname, int mode)
24276+{
24277+ int err;
24278+
24279+ LKTRTrace("i%lu, %.*s, %s, 0x%x\n",
24280+ dir->i_ino, AuDLNPair(dentry), symname, mode);
24281+ IMustLock(dir);
24282+
24283+ err = vfs_symlink(VfsubSymlinkArgs);
24284+ if (!err) {
24285+ /* dir inode is locked */
24286+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24287+ au_update_fuse_h_inode(NULL, dentry); /*ignore*/
24288+ }
24289+ return err;
24290+}
24291+
24292+int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
24293+ dev_t dev)
24294+{
24295+ int err;
24296+
24297+ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
24298+ IMustLock(dir);
24299+
24300+ err = vfs_mknod(dir, dentry, mode, dev);
24301+ if (!err) {
24302+ /* dir inode is locked */
24303+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24304+ au_update_fuse_h_inode(NULL, dentry); /*ignore*/
24305+ }
24306+ return err;
24307+}
24308+
24309+int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
24310+ struct dentry *dentry)
24311+{
24312+ int err;
24313+
24314+ LKTRTrace("%.*s, i%lu, %.*s\n",
24315+ AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry));
24316+ IMustLock(dir);
24317+
24318+ lockdep_off();
24319+ err = vfs_link(src_dentry, dir, dentry);
24320+ lockdep_on();
24321+ if (!err) {
24322+ LKTRTrace("src_i %p, dst_i %p\n",
24323+ src_dentry->d_inode, dentry->d_inode);
24324+ /* fuse has different memory inode for the same inumber */
24325+ au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
24326+ /* dir inode is locked */
24327+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24328+ au_update_fuse_h_inode(NULL, dentry); /*ignore*/
24329+ }
24330+ return err;
24331+}
24332+
24333+int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
24334+ struct inode *dir, struct dentry *dentry)
24335+{
24336+ int err;
24337+
24338+ LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
24339+ src_dir->i_ino, AuDLNPair(src_dentry),
24340+ dir->i_ino, AuDLNPair(dentry));
24341+ IMustLock(dir);
24342+ IMustLock(src_dir);
24343+ AuDebugOn(src_dir != dir && !vfsub_is_rename_mutex_locked(dir->i_sb));
24344+
24345+ lockdep_off();
24346+ err = vfs_rename(src_dir, src_dentry, dir, dentry);
24347+ lockdep_on();
24348+ if (!err) {
24349+ /* dir inode is locked */
24350+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24351+ au_update_fuse_h_inode(NULL, src_dentry->d_parent); /*ignore*/
24352+ au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
24353+ }
24354+ return err;
24355+}
24356+
24357+int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode)
24358+{
24359+ int err;
24360+
24361+ LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
24362+ IMustLock(dir);
24363+
24364+ err = vfs_mkdir(dir, dentry, mode);
24365+ if (!err) {
24366+ /* dir inode is locked */
24367+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24368+ au_update_fuse_h_inode(NULL, dentry); /*ignore*/
24369+ }
24370+ return err;
24371+}
24372+
24373+int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry)
24374+{
24375+ int err;
24376+
24377+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
24378+ IMustLock(dir);
24379+
24380+ lockdep_off();
24381+ err = vfs_rmdir(dir, dentry);
24382+ lockdep_on();
24383+ /* dir inode is locked */
24384+ if (!err)
24385+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24386+ return err;
24387+}
24388+
24389+int do_vfsub_unlink(struct inode *dir, struct dentry *dentry)
24390+{
24391+ int err;
24392+
24393+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
24394+ IMustLock(dir);
24395+
24396+ /* vfs_unlink() locks inode */
24397+ lockdep_off();
24398+ err = vfs_unlink(dir, dentry);
24399+ lockdep_on();
24400+ /* dir inode is locked */
24401+ if (!err)
24402+ au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
24403+ return err;
24404+}
24405+
24406+/* ---------------------------------------------------------------------- */
24407+
24408+ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
24409+ loff_t *ppos)
24410+{
24411+ ssize_t err;
24412+
24413+ LKTRTrace("%.*s, cnt %zu, pos %lld\n",
24414+ AuDLNPair(file->f_dentry), count, *ppos);
24415+
24416+ /* todo: always off, regardless nfs branch? */
24417+ au_br_nfs_lockdep_off(file->f_vfsmnt->mnt_sb);
24418+ err = vfs_read(file, ubuf, count, ppos);
24419+ au_br_nfs_lockdep_on(file->f_vfsmnt->mnt_sb);
24420+ if (err >= 0)
24421+ au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
24422+ /*ignore*/
24423+ return err;
24424+}
24425+
24426+/* todo: kernel_read()? */
24427+ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count,
24428+ loff_t *ppos)
24429+{
24430+ ssize_t err;
24431+ mm_segment_t oldfs;
24432+
24433+ oldfs = get_fs();
24434+ set_fs(KERNEL_DS);
24435+ err = do_vfsub_read_u(file, (char __user *)kbuf, count, ppos);
24436+ set_fs(oldfs);
24437+ return err;
24438+}
24439+
24440+ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
24441+ size_t count, loff_t *ppos)
24442+{
24443+ ssize_t err;
24444+
24445+ LKTRTrace("%.*s, cnt %zu, pos %lld\n",
24446+ AuDLNPair(file->f_dentry), count, *ppos);
24447+
24448+ lockdep_off();
24449+ err = vfs_write(file, ubuf, count, ppos);
24450+ lockdep_on();
24451+ if (err >= 0)
24452+ au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
24453+ /*ignore*/
24454+ return err;
24455+}
24456+
24457+ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count,
24458+ loff_t *ppos)
24459+{
24460+ ssize_t err;
24461+ mm_segment_t oldfs;
24462+
24463+ oldfs = get_fs();
24464+ set_fs(KERNEL_DS);
24465+ err = do_vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
24466+ set_fs(oldfs);
24467+ return err;
24468+}
24469+
24470+int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
24471+{
24472+ int err;
24473+
24474+ LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry));
24475+
24476+ lockdep_off();
24477+ err = vfs_readdir(file, filldir, arg);
24478+ lockdep_on();
24479+ if (err >= 0)
24480+ au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
24481+ /*ignore*/
24482+ return err;
24483+}
24484+
24485+#ifdef CONFIG_AUFS_SPLICE_PATCH
24486+long do_vfsub_splice_to(struct file *in, loff_t *ppos,
24487+ struct pipe_inode_info *pipe, size_t len,
24488+ unsigned int flags)
24489+{
24490+ long err;
24491+
24492+ LKTRTrace("%.*s, pos %lld, len %zu, 0x%x\n",
24493+ AuDLNPair(in->f_dentry), *ppos, len, flags);
24494+
24495+ lockdep_off();
24496+ err = vfs_splice_to(in, ppos, pipe, len, flags);
24497+ lockdep_on();
24498+ if (err >= 0)
24499+ au_update_fuse_h_inode(in->f_vfsmnt, in->f_dentry); /*ignore*/
24500+ return err;
24501+}
24502+
24503+long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
24504+ loff_t *ppos, size_t len, unsigned int flags)
24505+{
24506+ long err;
24507+
24508+ LKTRTrace("%.*s, pos %lld, len %zu, 0x%x\n",
24509+ AuDLNPair(out->f_dentry), *ppos, len, flags);
24510+
24511+ lockdep_off();
24512+ err = vfs_splice_from(pipe, out, ppos, len, flags);
24513+ lockdep_on();
24514+ if (err >= 0)
24515+ au_update_fuse_h_inode(out->f_vfsmnt, out->f_dentry); /*ignore*/
24516+ return err;
24517+}
24518+#endif
24519+
24520+/* ---------------------------------------------------------------------- */
24521+
24522+struct au_vfsub_mkdir_args {
24523+ int *errp;
24524+ struct inode *dir;
24525+ struct dentry *dentry;
24526+ int mode;
24527+ struct vfsub_args *vargs;
24528+};
24529+
24530+static void au_call_vfsub_mkdir(void *args)
24531+{
24532+ struct au_vfsub_mkdir_args *a = args;
24533+ *a->errp = vfsub_mkdir(a->dir, a->dentry, a->mode, a->vargs);
24534+}
24535+
24536+int vfsub_sio_mkdir(struct au_hinode *hdir, struct dentry *dentry, int mode,
24537+ int dlgt)
24538+{
24539+ int err, do_sio, wkq_err;
24540+ struct inode *dir = hdir->hi_inode;
24541+ struct au_hin_ignore ign;
24542+ struct vfsub_args vargs;
24543+
24544+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
24545+
24546+ vfsub_args_init(&vargs, &ign, dlgt, /*force_unlink*/0);
24547+ vfsub_ign_hinode(&vargs, IN_CREATE, hdir);
24548+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE, dlgt);
24549+ if (!do_sio)
24550+ err = vfsub_mkdir(dir, dentry, mode, &vargs);
24551+ else {
24552+ struct au_vfsub_mkdir_args args = {
24553+ .errp = &err,
24554+ .dir = dir,
24555+ .dentry = dentry,
24556+ .mode = mode,
24557+ .vargs = &vargs
24558+ };
24559+ vfsub_fclr(vargs.flags, DLGT);
24560+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args, /*dlgt*/0);
24561+ if (unlikely(wkq_err))
24562+ err = wkq_err;
24563+ }
24564+
24565+ AuTraceErr(err);
24566+ return err;
24567+}
24568+
24569+struct au_vfsub_rmdir_args {
24570+ int *errp;
24571+ struct inode *dir;
24572+ struct dentry *dentry;
24573+ struct vfsub_args *vargs;
24574+};
24575+
24576+static void au_call_vfsub_rmdir(void *args)
24577+{
24578+ struct au_vfsub_rmdir_args *a = args;
24579+ *a->errp = vfsub_rmdir(a->dir, a->dentry, a->vargs);
24580+}
24581+
24582+int vfsub_sio_rmdir(struct au_hinode *hdir, struct dentry *dentry, int dlgt)
24583+{
24584+ int err, do_sio, wkq_err;
24585+ struct inode *dir = hdir->hi_inode;
24586+ struct au_hin_ignore ign;
24587+ struct vfsub_args vargs;
24588+
24589+ LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
24590+
24591+ vfsub_args_init(&vargs, &ign, dlgt, /*force_unlink*/0);
24592+ vfsub_ign_hinode(&vargs, IN_DELETE, hdir);
24593+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE, dlgt);
24594+ if (!do_sio)
24595+ err = vfsub_rmdir(dir, dentry, &vargs);
24596+ else {
24597+ struct au_vfsub_rmdir_args args = {
24598+ .errp = &err,
24599+ .dir = dir,
24600+ .dentry = dentry,
24601+ .vargs = &vargs
24602+ };
24603+ vfsub_fclr(vargs.flags, DLGT);
24604+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args, /*dlgt*/0);
24605+ if (unlikely(wkq_err))
24606+ err = wkq_err;
24607+ }
24608+
24609+ AuTraceErr(err);
24610+ return err;
24611+}
24612+
24613+/* ---------------------------------------------------------------------- */
24614+
24615+struct notify_change_args {
24616+ int *errp;
24617+ struct dentry *h_dentry;
24618+ struct iattr *ia;
24619+ struct vfsub_args *vargs;
24620+};
24621+
24622+static void call_notify_change(void *args)
24623+{
24624+ struct notify_change_args *a = args;
24625+ struct inode *h_inode;
24626+
24627+ LKTRTrace("%.*s, ia_valid 0x%x\n",
24628+ AuDLNPair(a->h_dentry), a->ia->ia_valid);
24629+ h_inode = a->h_dentry->d_inode;
24630+ IMustLock(h_inode);
24631+
24632+ *a->errp = -EPERM;
24633+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
24634+ vfsub_ignore(a->vargs);
24635+ lockdep_off();
24636+ *a->errp = notify_change(a->h_dentry, a->ia);
24637+ lockdep_on();
24638+ if (!*a->errp)
24639+ au_update_fuse_h_inode(NULL, a->h_dentry); /*ignore*/
24640+ else
24641+ vfsub_unignore(a->vargs);
24642+ au_dbg_hin_list(a->vargs);
24643+ }
24644+ AuTraceErr(*a->errp);
24645+}
24646+
24647+#ifdef CONFIG_AUFS_DLGT
24648+static void vfsub_notify_change_dlgt(struct notify_change_args *args,
24649+ unsigned int flags)
24650+{
24651+ if (!vfsub_ftest(flags, DLGT))
24652+ call_notify_change(args);
24653+ else {
24654+ int wkq_err;
24655+ wkq_err = au_wkq_wait(call_notify_change, args, /*dlgt*/1);
24656+ if (unlikely(wkq_err))
24657+ *args->errp = wkq_err;
24658+ }
24659+}
24660+#else
24661+static void vfsub_notify_change_dlgt(struct notify_change_args *args,
24662+ unsigned int flags)
24663+{
24664+ call_notify_change(args);
24665+}
24666+#endif
24667+
24668+int vfsub_notify_change(struct dentry *dentry, struct iattr *ia,
24669+ struct vfsub_args *vargs)
24670+{
24671+ int err;
24672+ struct notify_change_args args = {
24673+ .errp = &err,
24674+ .h_dentry = dentry,
24675+ .ia = ia,
24676+ .vargs = vargs
24677+ };
24678+
24679+ vfsub_notify_change_dlgt(&args, vargs->flags);
24680+
24681+ AuTraceErr(err);
24682+ return err;
24683+}
24684+
24685+int vfsub_sio_notify_change(struct au_hinode *hdir, struct dentry *dentry,
24686+ struct iattr *ia)
24687+{
24688+ int err, wkq_err;
24689+ struct au_hin_ignore ign;
24690+ struct vfsub_args vargs;
24691+ __u32 events;
24692+ struct notify_change_args args = {
24693+ .errp = &err,
24694+ .h_dentry = dentry,
24695+ .ia = ia,
24696+ .vargs = &vargs
24697+ };
24698+
24699+ LKTRTrace("%.*s, 0x%x\n", AuDLNPair(dentry), ia->ia_valid);
24700+
24701+ vfsub_args_init(&vargs, &ign, /*dlgt*/0, /*force_unlink*/0);
24702+ events = vfsub_events_notify_change(ia);
24703+ if (events)
24704+ vfsub_ign_hinode(&vargs, events, hdir);
24705+ wkq_err = au_wkq_wait(call_notify_change, &args, /*dlgt*/0);
24706+ if (unlikely(wkq_err))
24707+ err = wkq_err;
24708+
24709+ AuTraceErr(err);
24710+ return err;
24711+}
24712+
24713+/* ---------------------------------------------------------------------- */
24714+
24715+struct unlink_args {
24716+ int *errp;
24717+ struct inode *dir;
24718+ struct dentry *dentry;
24719+ struct vfsub_args *vargs;
24720+};
24721+
24722+static void call_unlink(void *args)
24723+{
24724+ struct unlink_args *a = args;
24725+ struct inode *h_inode;
24726+ const int stop_sillyrename = (au_test_nfs(a->dentry->d_sb)
24727+ && atomic_read(&a->dentry->d_count) == 1);
24728+
24729+ LKTRTrace("%.*s, stop_silly %d, cnt %d\n",
24730+ AuDLNPair(a->dentry), stop_sillyrename,
24731+ atomic_read(&a->dentry->d_count));
24732+
24733+ if (!stop_sillyrename)
24734+ dget(a->dentry);
24735+ h_inode = a->dentry->d_inode;
24736+ if (h_inode)
24737+ atomic_inc_return(&h_inode->i_count);
24738+ vfsub_ignore(a->vargs);
24739+ *a->errp = do_vfsub_unlink(a->dir, a->dentry);
24740+ if (unlikely(*a->errp || (a->dentry->d_flags & DCACHE_NFSFS_RENAMED)))
24741+ vfsub_unignore(a->vargs);
24742+ au_dbg_hin_list(a->vargs);
24743+ if (!stop_sillyrename)
24744+ dput(a->dentry);
24745+ if (h_inode)
24746+ iput(h_inode);
24747+
24748+ AuTraceErr(*a->errp);
24749+}
24750+
24751+/*
24752+ * @dir: must be locked.
24753+ * @dentry: target dentry.
24754+ */
24755+int vfsub_unlink(struct inode *dir, struct dentry *dentry,
24756+ struct vfsub_args *vargs)
24757+{
24758+ int err;
24759+ struct unlink_args args = {
24760+ .errp = &err,
24761+ .dir = dir,
24762+ .dentry = dentry,
24763+ .vargs = vargs
24764+ };
24765+
24766+ if (!vfsub_ftest(vargs->flags, DLGT)
24767+ && !vfsub_ftest(vargs->flags, FORCE_UNLINK))
24768+ call_unlink(&args);
24769+ else {
24770+ int wkq_err;
24771+ wkq_err = au_wkq_wait(call_unlink, &args,
24772+ vfsub_ftest(vargs->flags, DLGT));
24773+ if (unlikely(wkq_err))
24774+ err = wkq_err;
24775+ }
24776+
24777+ return err;
24778+}
24779+
24780+/* ---------------------------------------------------------------------- */
24781+
24782+struct statfs_args {
24783+ int *errp;
24784+ void *arg;
24785+ struct kstatfs *buf;
24786+};
24787+
24788+static void call_statfs(void *args)
24789+{
24790+ struct statfs_args *a = args;
24791+ *a->errp = vfs_statfs(a->arg, a->buf);
24792+}
24793+
24794+#ifdef CONFIG_AUFS_DLGT
24795+static void vfsub_statfs_dlgt(struct statfs_args *args, int dlgt)
24796+{
24797+ if (!dlgt)
24798+ call_statfs(args);
24799+ else {
24800+ int wkq_err;
24801+ wkq_err = au_wkq_wait(call_statfs, args, /*dlgt*/1);
24802+ if (unlikely(wkq_err))
24803+ *args->errp = wkq_err;
24804+ }
24805+}
24806+#else
24807+static void vfsub_statfs_dlgt(struct statfs_args *args, int dlgt)
24808+{
24809+ call_statfs(args);
24810+}
24811+#endif
24812+
24813+int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt)
24814+{
24815+ int err;
24816+ struct statfs_args args = {
24817+ .errp = &err,
24818+ .arg = arg,
24819+ .buf = buf
24820+ };
24821+
24822+ vfsub_statfs_dlgt(&args, dlgt);
24823+
24824+ return err;
24825+}
24826diff -urN linux/fs/aufs/vfsub.h linux-aufs/fs/aufs/vfsub.h
24827--- linux/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
24828+++ linux-aufs/fs/aufs/vfsub.h 2009-03-12 16:18:04.000000000 +0100
24829@@ -0,0 +1,530 @@
24830+/*
24831+ * Copyright (C) 2005-2009 Junjiro Okajima
24832+ *
24833+ * This program, aufs is free software; you can redistribute it and/or modify
24834+ * it under the terms of the GNU General Public License as published by
24835+ * the Free Software Foundation; either version 2 of the License, or
24836+ * (at your option) any later version.
24837+ *
24838+ * This program is distributed in the hope that it will be useful,
24839+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24840+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24841+ * GNU General Public License for more details.
24842+ *
24843+ * You should have received a copy of the GNU General Public License
24844+ * along with this program; if not, write to the Free Software
24845+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24846+ */
24847+
24848+/*
24849+ * sub-routines for VFS
24850+ *
24851+ * $Id$
24852+ */
24853+
24854+#ifndef __AUFS_VFSUB_H__
24855+#define __AUFS_VFSUB_H__
24856+
24857+#ifdef __KERNEL__
24858+
24859+#include <linux/fs.h>
24860+#include <linux/fs_stack.h>
24861+#include <linux/inotify.h>
24862+#include <linux/namei.h>
24863+#include <linux/security.h>
24864+#include <linux/splice.h>
24865+
24866+/* ---------------------------------------------------------------------- */
24867+
24868+/* vfsub flags */
24869+#define Vfsub_DLGT 1 /* operation with delegation */
24870+#define Vfsub_FORCE_UNLINK (1 << 1) /* force unlinking */
24871+#define vfsub_ftest(flags, name) ((flags) & Vfsub_##name)
24872+#define vfsub_fset(flags, name) { (flags) |= Vfsub_##name; }
24873+#define vfsub_fclr(flags, name) { (flags) &= ~Vfsub_##name; }
24874+#ifndef CONFIG_AUFS_DLGT
24875+#undef Vfsub_DLGT
24876+#define Vfsub_DLGT 0
24877+#endif
24878+
24879+struct au_hin_ignore;
24880+struct vfsub_args {
24881+#ifdef CONFIG_AUFS_HINOTIFY
24882+ /* inotify events to be ignored */
24883+ int nignore;
24884+ struct au_hin_ignore *ignore;
24885+#endif
24886+
24887+ unsigned int flags;
24888+};
24889+
24890+struct au_hinode;
24891+#ifdef CONFIG_AUFS_HINOTIFY
24892+static inline
24893+void do_vfsub_args_reinit(struct vfsub_args *vargs, struct au_hin_ignore *ign)
24894+{
24895+ vargs->nignore = 0;
24896+ vargs->ignore = ign;
24897+}
24898+
24899+static inline void vfsub_args_reinit(struct vfsub_args *vargs)
24900+{
24901+ vargs->nignore = 0;
24902+}
24903+
24904+__u32 vfsub_events_notify_change(struct iattr *ia);
24905+void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events,
24906+ struct au_hinode *hinode);
24907+void vfsub_ignore(struct vfsub_args *vargs);
24908+void vfsub_unignore(struct vfsub_args *vargs);
24909+#else
24910+static inline
24911+void do_vfsub_args_reinit(struct vfsub_args *vargs, struct au_hin_ignore *ign)
24912+{
24913+ /* empty */
24914+}
24915+
24916+static inline void vfsub_args_reinit(struct vfsub_args *vargs)
24917+{
24918+ /* empty */
24919+}
24920+
24921+static inline __u32 vfsub_events_notify_change(struct iattr *ia)
24922+{
24923+ return 0;
24924+}
24925+
24926+static inline void vfsub_ign_hinode(struct vfsub_args *vargs, __u32 events,
24927+ struct au_hinode *hinode)
24928+{
24929+ /* empty */
24930+}
24931+
24932+static inline void vfsub_ignore(struct vfsub_args *vargs)
24933+{
24934+ /* empty */
24935+}
24936+
24937+static inline void vfsub_unignore(struct vfsub_args *vargs)
24938+{
24939+ /* empty */
24940+}
24941+#endif /* CONFIG_AUFS_HINOTIFY */
24942+
24943+void vfsub_args_init(struct vfsub_args *vargs, struct au_hin_ignore *ign,
24944+ int dlgt, int force_unlink);
24945+
24946+/* ---------------------------------------------------------------------- */
24947+
24948+/* inotify_inode_watched() is not exported */
24949+static inline int au_test_inotify(struct inode *inode)
24950+{
24951+#ifdef CONFIG_INOTIFY
24952+ return !list_empty(&inode->inotify_watches);
24953+#endif
24954+ return 0;
24955+}
24956+
24957+/* ---------------------------------------------------------------------- */
24958+
24959+/* lock subclass for hidden inode */
24960+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
24961+/* reduce? gave up. */
24962+enum {
24963+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
24964+ AuLsc_I_PARENT, /* hidden inode, parent first */
24965+ AuLsc_I_PARENT2, /* copyup dirs */
24966+ AuLsc_I_PARENT3, /* rename with hinotify */
24967+ AuLsc_I_PARENT4, /* ditto */
24968+ AuLsc_I_CHILD,
24969+ AuLsc_I_CHILD2,
24970+ AuLsc_I_End
24971+};
24972+
24973+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
24974+
24975+static inline void vfsub_lock_rename_mutex(struct super_block *sb)
24976+{
24977+ lockdep_off();
24978+ mutex_lock(&sb->s_vfs_rename_mutex);
24979+ lockdep_on();
24980+}
24981+
24982+static inline void vfsub_unlock_rename_mutex(struct super_block *sb)
24983+{
24984+ lockdep_off();
24985+ mutex_unlock(&sb->s_vfs_rename_mutex);
24986+ lockdep_on();
24987+}
24988+
24989+static inline int vfsub_is_rename_mutex_locked(struct super_block *sb)
24990+{
24991+ int res;
24992+
24993+ lockdep_off();
24994+ res = mutex_is_locked(&sb->s_vfs_rename_mutex);
24995+ lockdep_on();
24996+
24997+ return res;
24998+}
24999+
25000+static inline
25001+struct dentry *vfsub_lock_rename(struct dentry *d1, struct dentry *d2)
25002+{
25003+ struct dentry *d;
25004+
25005+ lockdep_off();
25006+ d = lock_rename(d1, d2);
25007+ lockdep_on();
25008+ return d;
25009+}
25010+
25011+static inline void vfsub_unlock_rename(struct dentry *d1, struct dentry *d2)
25012+{
25013+ lockdep_off();
25014+ unlock_rename(d1, d2);
25015+ lockdep_on();
25016+}
25017+
25018+static inline int au_verify_parent(struct dentry *dentry, struct inode *dir)
25019+{
25020+ IMustLock(dir);
25021+ return /* !dir->i_nlink || */ dentry->d_parent->d_inode != dir;
25022+}
25023+
25024+/* ---------------------------------------------------------------------- */
25025+
25026+#ifdef CONFIG_AUFS_WORKAROUND_FUSE
25027+/* br_fuse.c */
25028+int au_update_fuse_h_inode(struct vfsmount *h_mnt, struct dentry *h_dentry);
25029+#else
25030+static inline
25031+int au_update_fuse_h_inode(struct vfsmount *h_mnt, struct dentry *h_dentry)
25032+{
25033+ return 0;
25034+}
25035+#endif
25036+
25037+#ifdef CONFIG_AUFS_BR_XFS
25038+/* br_xfs.c */
25039+dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt,
25040+ struct dentry *h_dentry);
25041+#else
25042+static inline
25043+dev_t au_h_rdev(struct inode *h_inode, struct vfsmount *h_mnt,
25044+ struct dentry *h_dentry)
25045+{
25046+ return h_inode->i_rdev;
25047+}
25048+#endif
25049+
25050+/* simple abstractions, for future use */
25051+static inline
25052+int do_vfsub_permission(struct inode *inode, int mask, struct nameidata *nd)
25053+{
25054+ LKTRTrace("i%lu, mask 0x%x, nd %d\n", inode->i_ino, mask, !!nd);
25055+ IMustLock(inode);
25056+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
25057+ return inode_permission(inode, mask);
25058+#else
25059+ return permission(inode, mask, nd);
25060+#endif
25061+}
25062+
25063+static inline
25064+int vfsub_security_inode_permission(struct inode *inode, int mask,
25065+ struct nameidata *nd)
25066+{
25067+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
25068+ mask &= MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND;
25069+ return security_inode_permission(inode, mask);
25070+#else
25071+ return security_inode_permission(inode, mask, nd);
25072+#endif
25073+}
25074+
25075+/* ---------------------------------------------------------------------- */
25076+
25077+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
25078+int vfsub_path_lookup(const char *name, unsigned int flags,
25079+ struct nameidata *nd);
25080+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
25081+ int len);
25082+
25083+#ifdef CONFIG_AUFS_LHASH_PATCH
25084+struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent,
25085+ struct nameidata *nd);
25086+#endif
25087+
25088+/* ---------------------------------------------------------------------- */
25089+
25090+int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
25091+ struct nameidata *nd);
25092+int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
25093+ const char *symname, int mode);
25094+int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
25095+ dev_t dev);
25096+int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
25097+ struct dentry *dentry);
25098+int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
25099+ struct inode *dir, struct dentry *dentry);
25100+int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode);
25101+int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry);
25102+int do_vfsub_unlink(struct inode *dir, struct dentry *dentry);
25103+
25104+/* ---------------------------------------------------------------------- */
25105+
25106+ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
25107+ loff_t *ppos);
25108+/* todo: kernel_read()? */
25109+ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count,
25110+ loff_t *ppos);
25111+ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
25112+ size_t count, loff_t *ppos);
25113+ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count,
25114+ loff_t *ppos);
25115+int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
25116+
25117+/* ---------------------------------------------------------------------- */
25118+
25119+#ifndef CONFIG_AUFS_UNIONFS22_PATCH
25120+static inline void vfsub_copy_inode_size(struct inode *inode,
25121+ struct inode *h_inode)
25122+{
25123+ spin_lock(&inode->i_lock);
25124+ fsstack_copy_inode_size(inode, h_inode);
25125+ spin_unlock(&inode->i_lock);
25126+}
25127+#else
25128+static inline void vfsub_copy_inode_size(struct inode *inode,
25129+ struct inode *h_inode)
25130+{
25131+ fsstack_copy_inode_size(inode, h_inode);
25132+}
25133+#endif
25134+
25135+#ifndef CONFIG_AUFS_UNIONFS23_PATCH
25136+#define vfs_splice_to do_splice_to
25137+#define vfs_splice_from do_splice_from
25138+#endif
25139+
25140+#ifdef CONFIG_AUFS_SPLICE_PATCH
25141+long do_vfsub_splice_to(struct file *in, loff_t *ppos,
25142+ struct pipe_inode_info *pipe, size_t len,
25143+ unsigned int flags);
25144+long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
25145+ loff_t *ppos, size_t len, unsigned int flags);
25146+#else
25147+static inline
25148+long do_vfsub_splice_to(struct file *in, loff_t *ppos,
25149+ struct pipe_inode_info *pipe, size_t len,
25150+ unsigned int flags)
25151+{
25152+ return -ENOSYS;
25153+}
25154+
25155+static inline
25156+long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
25157+ loff_t *ppos, size_t len, unsigned int flags)
25158+{
25159+ return -ENOSYS;
25160+}
25161+#endif /* CONFIG_AUFS_SPLICE_PATCH */
25162+
25163+/* ---------------------------------------------------------------------- */
25164+
25165+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
25166+{
25167+ loff_t err;
25168+
25169+ LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry));
25170+
25171+ lockdep_off();
25172+ err = vfs_llseek(file, offset, origin);
25173+ lockdep_on();
25174+ return err;
25175+}
25176+
25177+static inline int do_vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry,
25178+ struct kstat *st)
25179+{
25180+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
25181+ return vfs_getattr(mnt, dentry, st);
25182+}
25183+
25184+/* ---------------------------------------------------------------------- */
25185+
25186+#ifdef CONFIG_AUFS_HIN_OR_DLGT
25187+/* hin_or_dlgt.c */
25188+int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
25189+ int dlgt);
25190+
25191+int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
25192+ struct nameidata *nd, struct vfsub_args *vargs);
25193+int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
25194+ int mode, struct vfsub_args *vargs);
25195+int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
25196+ struct vfsub_args *vargs);
25197+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
25198+ struct dentry *dentry, struct vfsub_args *vargs);
25199+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
25200+ struct inode *dir, struct dentry *dentry,
25201+ struct vfsub_args *vargs);
25202+int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode,
25203+ struct vfsub_args *vargs);
25204+int vfsub_rmdir(struct inode *dir, struct dentry *dentry,
25205+ struct vfsub_args *vargs);
25206+
25207+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
25208+ loff_t *ppos, int dlgt);
25209+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
25210+ int dlgt);
25211+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
25212+ loff_t *ppos, struct vfsub_args *vargs);
25213+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
25214+ struct vfsub_args *vargs);
25215+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt);
25216+long vfsub_splice_to(struct file *in, loff_t *ppos,
25217+ struct pipe_inode_info *pipe, size_t len,
25218+ unsigned int flags, int dlgt);
25219+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
25220+ loff_t *ppos, size_t len, unsigned int flags,
25221+ struct vfsub_args *vargs);
25222+
25223+int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st,
25224+ int dlgt);
25225+#else
25226+
25227+static inline
25228+int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
25229+ int dlgt)
25230+{
25231+ return do_vfsub_permission(inode, mask, nd);
25232+}
25233+
25234+static inline
25235+int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
25236+ struct nameidata *nd, struct vfsub_args *vargs)
25237+{
25238+ return do_vfsub_create(dir, dentry, mode, nd);
25239+}
25240+
25241+static inline
25242+int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
25243+ int mode, struct vfsub_args *vargs)
25244+{
25245+ return do_vfsub_symlink(dir, dentry, symname, mode);
25246+}
25247+
25248+static inline
25249+int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
25250+ struct vfsub_args *vargs)
25251+{
25252+ return do_vfsub_mknod(dir, dentry, mode, dev);
25253+}
25254+
25255+static inline
25256+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
25257+ struct dentry *dentry, struct vfsub_args *vargs)
25258+{
25259+ return do_vfsub_link(src_dentry, dir, dentry);
25260+}
25261+
25262+static inline
25263+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
25264+ struct inode *dir, struct dentry *dentry,
25265+ struct vfsub_args *vargs)
25266+{
25267+ return do_vfsub_rename(src_dir, src_dentry, dir, dentry);
25268+}
25269+
25270+static inline
25271+int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode,
25272+ struct vfsub_args *vargs)
25273+{
25274+ return do_vfsub_mkdir(dir, dentry, mode);
25275+}
25276+
25277+static inline
25278+int vfsub_rmdir(struct inode *dir, struct dentry *dentry,
25279+ struct vfsub_args *vargs)
25280+{
25281+ return do_vfsub_rmdir(dir, dentry);
25282+}
25283+
25284+static inline
25285+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
25286+ loff_t *ppos, int dlgt)
25287+{
25288+ return do_vfsub_read_u(file, ubuf, count, ppos);
25289+}
25290+
25291+static inline
25292+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
25293+ int dlgt)
25294+{
25295+ return do_vfsub_read_k(file, kbuf, count, ppos);
25296+}
25297+
25298+static inline
25299+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
25300+ loff_t *ppos, struct vfsub_args *vargs)
25301+{
25302+ return do_vfsub_write_u(file, ubuf, count, ppos);
25303+}
25304+
25305+static inline
25306+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
25307+ struct vfsub_args *vargs)
25308+{
25309+ return do_vfsub_write_k(file, kbuf, count, ppos);
25310+}
25311+
25312+static inline
25313+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
25314+{
25315+ return do_vfsub_readdir(file, filldir, arg);
25316+}
25317+
25318+static inline
25319+long vfsub_splice_to(struct file *in, loff_t *ppos,
25320+ struct pipe_inode_info *pipe, size_t len,
25321+ unsigned int flags, int dlgt)
25322+{
25323+ return do_vfsub_splice_to(in, ppos, pipe, len, flags);
25324+}
25325+
25326+static inline
25327+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
25328+ loff_t *ppos, size_t len, unsigned int flags,
25329+ struct vfsub_args *vargs)
25330+{
25331+ return do_vfsub_splice_from(pipe, out, ppos, len, flags);
25332+}
25333+
25334+static inline
25335+int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st,
25336+ int dlgt)
25337+{
25338+ return do_vfsub_getattr(mnt, dentry, st);
25339+}
25340+#endif /* HIN_OR_DLGT */
25341+
25342+/* ---------------------------------------------------------------------- */
25343+
25344+int vfsub_sio_mkdir(struct au_hinode *hdir, struct dentry *dentry, int mode,
25345+ int dlgt);
25346+int vfsub_sio_rmdir(struct au_hinode *hdir, struct dentry *dentry, int dlgt);
25347+int vfsub_sio_notify_change(struct au_hinode *hdir, struct dentry *dentry,
25348+ struct iattr *ia);
25349+
25350+/* ---------------------------------------------------------------------- */
25351+
25352+int vfsub_notify_change(struct dentry *dentry, struct iattr *ia,
25353+ struct vfsub_args *vargs);
25354+int vfsub_unlink(struct inode *dir, struct dentry *dentry,
25355+ struct vfsub_args *vargs);
25356+int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt);
25357+
25358+#endif /* __KERNEL__ */
25359+#endif /* __AUFS_VFSUB_H__ */
25360diff -urN linux/fs/aufs/wbr_policy.c linux-aufs/fs/aufs/wbr_policy.c
25361--- linux/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
25362+++ linux-aufs/fs/aufs/wbr_policy.c 2009-03-12 16:18:04.000000000 +0100
25363@@ -0,0 +1,696 @@
25364+/*
25365+ * Copyright (C) 2005-2009 Junjiro Okajima
25366+ *
25367+ * This program, aufs is free software; you can redistribute it and/or modify
25368+ * it under the terms of the GNU General Public License as published by
25369+ * the Free Software Foundation; either version 2 of the License, or
25370+ * (at your option) any later version.
25371+ *
25372+ * This program is distributed in the hope that it will be useful,
25373+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25374+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25375+ * GNU General Public License for more details.
25376+ *
25377+ * You should have received a copy of the GNU General Public License
25378+ * along with this program; if not, write to the Free Software
25379+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25380+ */
25381+
25382+/*
25383+ * policies for selecting one among multiple writable branches
25384+ *
25385+ * $Id$
25386+ */
25387+
25388+#include <linux/statfs.h>
25389+#include "aufs.h"
25390+
25391+static int au_cpdown_attr(struct au_hinode *hdir, struct dentry *h_dst,
25392+ struct dentry *h_src)
25393+{
25394+ int err, sbits;
25395+ struct iattr ia;
25396+ struct inode *h_idst, *h_isrc;
25397+
25398+ LKTRTrace("%.*s\n", AuDLNPair(h_dst));
25399+ h_idst = h_dst->d_inode;
25400+ /* todo? IMustLock(h_idst); */
25401+ h_isrc = h_src->d_inode;
25402+ /* todo? IMustLock(h_isrc); */
25403+
25404+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
25405+ ia.ia_mode = h_isrc->i_mode;
25406+ ia.ia_uid = h_isrc->i_uid;
25407+ ia.ia_gid = h_isrc->i_gid;
25408+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
25409+ au_cpup_attr_flags(h_idst, h_isrc);
25410+ err = vfsub_sio_notify_change(hdir, h_dst, &ia);
25411+
25412+ /* is this nfs only? */
25413+ if (!err && sbits && au_test_nfs(h_dst->d_sb)) {
25414+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
25415+ ia.ia_mode = h_isrc->i_mode;
25416+ err = vfsub_sio_notify_change(hdir, h_dst, &ia);
25417+ }
25418+
25419+ AuTraceErr(err);
25420+ return err;
25421+}
25422+
25423+struct au_cpdown_dir_args {
25424+ struct dentry *parent;
25425+ unsigned int parent_opq; /* bit-flags */
25426+};
25427+
25428+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
25429+ struct dentry *h_parent, void *arg)
25430+{
25431+ int err, rerr;
25432+ struct au_cpdown_dir_args *args = arg;
25433+ aufs_bindex_t bend, bopq, bstart;
25434+ unsigned char parent_opq, whed, dlgt, do_opq, made_dir, diropq;
25435+ struct dentry *h_dentry, *opq_dentry, *wh_dentry, *parent;
25436+ struct inode *h_dir, *h_inode, *inode, *dir;
25437+
25438+ LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bdst);
25439+ bstart = au_dbstart(dentry);
25440+ AuDebugOn(bstart <= bdst
25441+ && bdst <= au_dbend(dentry)
25442+ && au_h_dptr(dentry, bdst));
25443+ AuDebugOn(!h_parent);
25444+ /* todo: safe? */
25445+ parent = dget_parent(dentry);
25446+ dir = parent->d_inode;
25447+ dput(parent);
25448+ h_dir = h_parent->d_inode;
25449+ AuDebugOn(!h_dir);
25450+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
25451+ IMustLock(h_dir);
25452+
25453+ err = au_lkup_neg(dentry, bdst);
25454+ if (unlikely(err < 0))
25455+ goto out;
25456+ h_dentry = au_h_dptr(dentry, bdst);
25457+ dlgt = !!au_test_dlgt(au_mntflags(dentry->d_sb));
25458+ err = vfsub_sio_mkdir(au_hi(dir, bdst), h_dentry,
25459+ S_IRWXU | S_IRUGO | S_IXUGO, dlgt);
25460+ if (unlikely(err))
25461+ goto out_put;
25462+
25463+ made_dir = 1;
25464+ bend = au_dbend(dentry);
25465+ bopq = au_dbdiropq(dentry);
25466+ whed = (au_dbwh(dentry) == bdst);
25467+ if (!args->parent_opq)
25468+ args->parent_opq |= (bopq <= bdst);
25469+ parent_opq = (args->parent_opq && args->parent == dentry);
25470+ do_opq = 0;
25471+ diropq = 0;
25472+ h_inode = h_dentry->d_inode;
25473+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
25474+ if (whed || (parent_opq && do_opq)) {
25475+ opq_dentry = au_diropq_create(dentry, bdst, dlgt);
25476+ err = PTR_ERR(opq_dentry);
25477+ if (IS_ERR(opq_dentry)) {
25478+ mutex_unlock(&h_inode->i_mutex);
25479+ goto out_dir;
25480+ }
25481+ dput(opq_dentry);
25482+ diropq = 1;
25483+ }
25484+
25485+ err = au_cpdown_attr(au_hi(dir, bdst), h_dentry,
25486+ au_h_dptr(dentry, bstart));
25487+ mutex_unlock(&h_inode->i_mutex);
25488+ if (unlikely(err))
25489+ goto out_opq;
25490+
25491+ wh_dentry = NULL;
25492+ if (whed) {
25493+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, /*ndx*/NULL);
25494+ err = PTR_ERR(wh_dentry);
25495+ if (IS_ERR(wh_dentry))
25496+ goto out_opq;
25497+ err = 0;
25498+ if (wh_dentry->d_inode)
25499+ err = au_wh_unlink_dentry(au_hi(dir, bdst), wh_dentry,
25500+ dentry, dlgt);
25501+ dput(wh_dentry);
25502+ if (unlikely(err))
25503+ goto out_opq;
25504+ }
25505+
25506+ inode = dentry->d_inode;
25507+ if (au_ibend(inode) < bdst)
25508+ au_set_ibend(inode, bdst);
25509+ au_set_h_iptr(inode, bdst, au_igrab(h_inode), au_hi_flags(inode, 1));
25510+ goto out; /* success */
25511+
25512+ /* revert */
25513+ out_opq:
25514+ if (diropq) {
25515+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
25516+ rerr = au_diropq_remove(dentry, bdst, dlgt);
25517+ mutex_unlock(&h_inode->i_mutex);
25518+ if (unlikely(rerr)) {
25519+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
25520+ AuDLNPair(dentry), bdst, rerr);
25521+ err = -EIO;
25522+ goto out;
25523+ }
25524+ }
25525+ out_dir:
25526+ if (made_dir) {
25527+ rerr = vfsub_sio_rmdir(au_hi(dir, bdst), h_dentry, dlgt);
25528+ if (unlikely(rerr)) {
25529+ AuIOErr("failed removing %.*s b%d (%d)\n",
25530+ AuDLNPair(dentry), bdst, rerr);
25531+ err = -EIO;
25532+ }
25533+ }
25534+ out_put:
25535+ au_set_h_dptr(dentry, bdst, NULL);
25536+ if (au_dbend(dentry) == bdst)
25537+ au_update_dbend(dentry);
25538+ out:
25539+ AuTraceErr(err);
25540+ return err;
25541+}
25542+
25543+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
25544+{
25545+ int err;
25546+ struct au_cpdown_dir_args args = {
25547+ .parent = dget_parent(dentry),
25548+ .parent_opq = 0
25549+ };
25550+
25551+ LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bdst);
25552+
25553+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
25554+ dput(args.parent);
25555+
25556+ AuTraceErr(err);
25557+ return err;
25558+}
25559+
25560+/* ---------------------------------------------------------------------- */
25561+
25562+/* policies for create */
25563+
25564+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
25565+{
25566+ for (; bindex >= 0; bindex--)
25567+ if (!au_br_rdonly(au_sbr(sb, bindex)))
25568+ return bindex;
25569+ return -EROFS;
25570+}
25571+
25572+/* top down parent */
25573+static int au_wbr_create_tdp(struct dentry *dentry, int isdir)
25574+{
25575+ int err;
25576+ struct super_block *sb;
25577+ aufs_bindex_t bstart, bindex;
25578+ unsigned char dirperm1;
25579+ struct dentry *parent, *h_parent;
25580+ struct inode *h_dir;
25581+
25582+ LKTRTrace("%.*s, dir %d\n", AuDLNPair(dentry), isdir);
25583+
25584+ sb = dentry->d_sb;
25585+ dirperm1 = !!au_test_dirperm1(au_mntflags(sb));
25586+ bstart = au_dbstart(dentry);
25587+ AuDebugOn(bstart < 0);
25588+ err = bstart;
25589+ /* todo: can 'err' be an illegal? */
25590+ if (/* err >= 0 && */ !au_br_rdonly(au_sbr(sb, bstart)))
25591+ goto out;
25592+
25593+ err = -EROFS;
25594+ parent = dget_parent(dentry);
25595+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
25596+ h_parent = au_h_dptr(parent, bindex);
25597+ if (!h_parent)
25598+ continue;
25599+ h_dir = h_parent->d_inode;
25600+ if (!h_dir)
25601+ continue;
25602+
25603+ if (!au_br_rdonly(au_sbr(sb, bindex))
25604+ && (!dirperm1
25605+ || au_test_h_perm(h_dir, MAY_WRITE | MAY_EXEC,
25606+ /*dlgt*/0))) {
25607+ err = bindex;
25608+ break;
25609+ }
25610+ }
25611+ dput(parent);
25612+
25613+ /* bottom up here */
25614+ if (unlikely(err < 0))
25615+ err = au_wbr_bu(sb, bstart - 1);
25616+
25617+ out:
25618+ LKTRTrace("b%d\n", err);
25619+ return err;
25620+}
25621+
25622+/* ---------------------------------------------------------------------- */
25623+
25624+/* an exception for the policy other than tdp */
25625+static int au_wbr_create_exp(struct dentry *dentry)
25626+{
25627+ int err;
25628+ struct dentry *parent;
25629+ aufs_bindex_t bwh, bdiropq;
25630+
25631+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
25632+
25633+ err = -1;
25634+ bwh = au_dbwh(dentry);
25635+ parent = dget_parent(dentry);
25636+ bdiropq = au_dbdiropq(parent);
25637+ if (bwh >= 0) {
25638+ if (bdiropq >= 0)
25639+ err = min(bdiropq, bwh);
25640+ else
25641+ err = bwh;
25642+ LKTRTrace("%d\n", err);
25643+ } else if (bdiropq >= 0) {
25644+ err = bdiropq;
25645+ LKTRTrace("%d\n", err);
25646+ }
25647+ dput(parent);
25648+
25649+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
25650+ err = -1;
25651+
25652+ LKTRTrace("%d\n", err);
25653+ return err;
25654+}
25655+
25656+/* ---------------------------------------------------------------------- */
25657+
25658+/* round robin */
25659+static int au_wbr_create_init_rr(struct super_block *sb)
25660+{
25661+ int err;
25662+
25663+ err = au_wbr_bu(sb, au_sbend(sb));
25664+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
25665+
25666+ LKTRTrace("b%d\n", err);
25667+ return err;
25668+}
25669+
25670+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
25671+{
25672+ int err, nbr;
25673+ struct super_block *sb;
25674+ atomic_t *next;
25675+ unsigned int u;
25676+ aufs_bindex_t bindex, bend;
25677+
25678+ LKTRTrace("%.*s, dir %d\n", AuDLNPair(dentry), isdir);
25679+
25680+ sb = dentry->d_sb;
25681+ next = NULL;
25682+ err = au_wbr_create_exp(dentry);
25683+ if (err >= 0)
25684+ goto out;
25685+
25686+ next = &au_sbi(sb)->si_wbr_rr_next;
25687+ bend = au_sbend(sb);
25688+ nbr = bend + 1;
25689+ for (bindex = 0; bindex <= bend; bindex++) {
25690+ if (!isdir) {
25691+ err = atomic_dec_return(next) + 1;
25692+ /* modulo for 0 is meaningless */
25693+ if (unlikely(!err))
25694+ err = atomic_dec_return(next) + 1;
25695+ } else
25696+ err = atomic_read(next);
25697+ LKTRTrace("%d\n", err);
25698+ u = err;
25699+ err = u % nbr;
25700+ LKTRTrace("%d\n", err);
25701+ if (!au_br_rdonly(au_sbr(sb, err)))
25702+ break;
25703+ err = -EROFS;
25704+ }
25705+
25706+ out:
25707+ LKTRTrace("%d\n", err);
25708+ return err;
25709+}
25710+
25711+/* ---------------------------------------------------------------------- */
25712+
25713+/* most free space */
25714+static void *au_wbr_statfs_arg(struct au_branch *br, struct super_block *sb,
25715+ aufs_bindex_t bindex)
25716+{
25717+ struct super_block *h_sb;
25718+
25719+ h_sb = br->br_mnt->mnt_sb;
25720+
25721+ if (!au_test_nfs(h_sb))
25722+ return h_sb->s_root;
25723+
25724+ /* sigh,,, why nfs s_root has wrong inode? */
25725+ return au_di(sb->s_root)->di_hdentry[0 + bindex].hd_dentry;
25726+}
25727+
25728+static void au_mfs(struct dentry *dentry)
25729+{
25730+ struct super_block *sb;
25731+ aufs_bindex_t bindex, bend;
25732+ unsigned char dlgt;
25733+ int err;
25734+ struct kstatfs st;
25735+ unsigned long long b, bavail;
25736+ void *arg;
25737+ struct au_branch *br;
25738+ struct au_wbr_mfs *mfs;
25739+
25740+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
25741+
25742+ bavail = 0;
25743+ sb = dentry->d_sb;
25744+ mfs = &au_sbi(sb)->si_wbr_mfs;
25745+ mfs->mfs_bindex = -EROFS;
25746+ mfs->mfsrr_bytes = 0;
25747+ dlgt = !!au_test_dlgt(au_mntflags(sb));
25748+ bend = au_sbend(sb);
25749+ for (bindex = 0; bindex <= bend; bindex++) {
25750+ br = au_sbr(sb, bindex);
25751+ if (au_br_rdonly(br))
25752+ continue;
25753+ AuDebugOn(!br->br_wbr);
25754+ arg = au_wbr_statfs_arg(br, sb, bindex);
25755+ if (!arg)
25756+ continue;
25757+
25758+ err = vfsub_statfs(arg, &st, dlgt);
25759+ LKTRTrace("b%d, %d, %llu\n",
25760+ bindex, err, (unsigned long long)st.f_bavail);
25761+ if (unlikely(err)) {
25762+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
25763+ continue;
25764+ }
25765+
25766+ /* when the available size is equal, select lower one */
25767+ b = st.f_bavail * st.f_bsize;
25768+ br->br_wbr->wbr_bytes = b;
25769+ if (b >= bavail) {
25770+ bavail = b;
25771+ mfs->mfs_bindex = bindex;
25772+ mfs->mfs_jiffy = jiffies;
25773+ }
25774+ }
25775+
25776+ mfs->mfsrr_bytes = bavail;
25777+ LKTRTrace("b%d\n", mfs->mfs_bindex);
25778+}
25779+
25780+static int au_wbr_create_mfs(struct dentry *dentry, int isdir)
25781+{
25782+ int err;
25783+ struct super_block *sb;
25784+ struct au_wbr_mfs *mfs;
25785+
25786+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
25787+
25788+ sb = dentry->d_sb;
25789+ err = au_wbr_create_exp(dentry);
25790+ if (err >= 0)
25791+ goto out;
25792+
25793+ mfs = &au_sbi(sb)->si_wbr_mfs;
25794+ mutex_lock(&mfs->mfs_lock);
25795+ if (unlikely(time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
25796+ || mfs->mfs_bindex < 0
25797+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex))))
25798+ au_mfs(dentry);
25799+ mutex_unlock(&mfs->mfs_lock);
25800+ err = mfs->mfs_bindex;
25801+
25802+ out:
25803+ LKTRTrace("b%d\n", err);
25804+ return err;
25805+}
25806+
25807+static int au_wbr_create_init_mfs(struct super_block *sb)
25808+{
25809+ struct au_wbr_mfs *mfs;
25810+
25811+ mfs = &au_sbi(sb)->si_wbr_mfs;
25812+ LKTRTrace("expire %lu\n", mfs->mfs_expire);
25813+
25814+ mutex_init(&mfs->mfs_lock);
25815+ mfs->mfs_jiffy = 0;
25816+ mfs->mfs_bindex = -EROFS;
25817+
25818+ return 0;
25819+}
25820+
25821+static int au_wbr_create_fin_mfs(struct super_block *sb)
25822+{
25823+ AuTraceEnter();
25824+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
25825+ return 0;
25826+}
25827+
25828+/* ---------------------------------------------------------------------- */
25829+
25830+/* most free space and then round robin */
25831+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
25832+{
25833+ int err;
25834+ struct au_wbr_mfs *mfs;
25835+
25836+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), isdir);
25837+
25838+ err = au_wbr_create_mfs(dentry, isdir);
25839+ if (err >= 0) {
25840+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
25841+ LKTRTrace("%llu bytes, %llu wmark\n",
25842+ mfs->mfsrr_bytes, mfs->mfsrr_watermark);
25843+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
25844+ err = au_wbr_create_rr(dentry, isdir);
25845+ }
25846+
25847+ LKTRTrace("b%d\n", err);
25848+ return err;
25849+}
25850+
25851+static int au_wbr_create_init_mfsrr(struct super_block *sb)
25852+{
25853+ int err;
25854+
25855+ au_wbr_create_init_mfs(sb); /* ignore */
25856+ err = au_wbr_create_init_rr(sb);
25857+
25858+ AuTraceErr(err);
25859+ return err;
25860+}
25861+
25862+/* ---------------------------------------------------------------------- */
25863+
25864+/* top down parent and most free space */
25865+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
25866+{
25867+ int err, e2;
25868+ struct super_block *sb;
25869+ struct dentry *parent, *h_parent;
25870+ aufs_bindex_t bindex, bstart, bend;
25871+ unsigned char dirperm1;
25872+ struct au_branch *br;
25873+ unsigned long long b;
25874+ struct inode *h_dir;
25875+
25876+ LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), isdir);
25877+
25878+ err = au_wbr_create_tdp(dentry, isdir);
25879+ if (unlikely(err < 0))
25880+ goto out;
25881+ parent = dget_parent(dentry);
25882+ bstart = au_dbstart(parent);
25883+ bend = au_dbtaildir(parent);
25884+ if (bstart == bend)
25885+ goto out_parent; /* success */
25886+
25887+ e2 = au_wbr_create_mfs(dentry, isdir);
25888+ if (e2 < 0)
25889+ goto out_parent; /* success */
25890+
25891+ /* when the available size is equal, select upper one */
25892+ sb = dentry->d_sb;
25893+ br = au_sbr(sb, err);
25894+ AuDebugOn(!br->br_wbr);
25895+ dirperm1 = !!au_test_dirperm1(au_mntflags(sb));
25896+ b = br->br_wbr->wbr_bytes;
25897+ LKTRTrace("b%d, %llu\n", err, b);
25898+
25899+ if (dirperm1) {
25900+ for (bindex = bstart; bindex <= bend; bindex++) {
25901+ h_parent = au_h_dptr(parent, bindex);
25902+ if (!h_parent)
25903+ continue;
25904+ h_dir = h_parent->d_inode;
25905+ if (!h_dir)
25906+ continue;
25907+
25908+ br = au_sbr(sb, bindex);
25909+ if (!au_br_rdonly(br)
25910+ && au_test_h_perm(h_dir, MAY_WRITE | MAY_EXEC,
25911+ /*dlgt*/0)
25912+ && br->br_wbr->wbr_bytes > b) {
25913+ b = br->br_wbr->wbr_bytes;
25914+ err = bindex;
25915+ LKTRTrace("b%d, %llu\n", err, b);
25916+ }
25917+ }
25918+ if (err >= 0)
25919+ goto out_parent;
25920+ }
25921+ for (bindex = bstart; bindex <= bend; bindex++) {
25922+ h_parent = au_h_dptr(parent, bindex);
25923+ if (!h_parent || !h_parent->d_inode)
25924+ continue;
25925+
25926+ br = au_sbr(sb, bindex);
25927+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
25928+ b = br->br_wbr->wbr_bytes;
25929+ err = bindex;
25930+ LKTRTrace("b%d, %llu\n", err, b);
25931+ }
25932+ }
25933+
25934+ out_parent:
25935+ dput(parent);
25936+ out:
25937+ LKTRTrace("b%d\n", err);
25938+ return err;
25939+}
25940+
25941+/* ---------------------------------------------------------------------- */
25942+
25943+/* policies for copyup */
25944+
25945+/* top down parent */
25946+static int au_wbr_copyup_tdp(struct dentry *dentry)
25947+{
25948+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
25949+}
25950+
25951+/* bottom up parent */
25952+static int au_wbr_copyup_bup(struct dentry *dentry)
25953+{
25954+ int err;
25955+ struct dentry *parent, *h_parent;
25956+ aufs_bindex_t bindex, bstart;
25957+ unsigned char dirperm1;
25958+ struct super_block *sb;
25959+ struct inode *h_dir;
25960+
25961+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
25962+
25963+ err = -EROFS;
25964+ sb = dentry->d_sb;
25965+ dirperm1 = !!au_test_dirperm1(au_mntflags(sb));
25966+ parent = dget_parent(dentry);
25967+ bstart = au_dbstart(parent);
25968+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
25969+ h_parent = au_h_dptr(parent, bindex);
25970+ if (!h_parent)
25971+ continue;
25972+ h_dir = h_parent->d_inode;
25973+ if (!h_dir)
25974+ continue;
25975+
25976+ if (!au_br_rdonly(au_sbr(sb, bindex))
25977+ && (!dirperm1
25978+ || au_test_h_perm(h_dir, MAY_WRITE | MAY_EXEC,
25979+ /*dlgt*/0))) {
25980+ err = bindex;
25981+ break;
25982+ }
25983+ }
25984+ dput(parent);
25985+
25986+ /* bottom up here */
25987+ if (unlikely(err < 0))
25988+ err = au_wbr_bu(sb, bstart - 1);
25989+
25990+ LKTRTrace("b%d\n", err);
25991+ return err;
25992+}
25993+
25994+/* bottom up */
25995+static int au_wbr_copyup_bu(struct dentry *dentry)
25996+{
25997+ int err;
25998+
25999+ LKTRTrace("%.*s\n", AuDLNPair(dentry));
26000+
26001+ err = au_wbr_bu(dentry->d_sb, au_dbstart(dentry));
26002+
26003+ LKTRTrace("b%d\n", err);
26004+ return err;
26005+}
26006+
26007+/* ---------------------------------------------------------------------- */
26008+
26009+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
26010+ [AuWbrCopyup_TDP] = {
26011+ .copyup = au_wbr_copyup_tdp
26012+ },
26013+ [AuWbrCopyup_BUP] = {
26014+ .copyup = au_wbr_copyup_bup
26015+ },
26016+ [AuWbrCopyup_BU] = {
26017+ .copyup = au_wbr_copyup_bu
26018+ }
26019+};
26020+
26021+struct au_wbr_create_operations au_wbr_create_ops[] = {
26022+ [AuWbrCreate_TDP] = {
26023+ .create = au_wbr_create_tdp
26024+ },
26025+ [AuWbrCreate_RR] = {
26026+ .create = au_wbr_create_rr,
26027+ .init = au_wbr_create_init_rr
26028+ },
26029+ [AuWbrCreate_MFS] = {
26030+ .create = au_wbr_create_mfs,
26031+ .init = au_wbr_create_init_mfs,
26032+ .fin = au_wbr_create_fin_mfs
26033+ },
26034+ [AuWbrCreate_MFSV] = {
26035+ .create = au_wbr_create_mfs,
26036+ .init = au_wbr_create_init_mfs,
26037+ .fin = au_wbr_create_fin_mfs
26038+ },
26039+ [AuWbrCreate_MFSRR] = {
26040+ .create = au_wbr_create_mfsrr,
26041+ .init = au_wbr_create_init_mfsrr,
26042+ .fin = au_wbr_create_fin_mfs
26043+ },
26044+ [AuWbrCreate_MFSRRV] = {
26045+ .create = au_wbr_create_mfsrr,
26046+ .init = au_wbr_create_init_mfsrr,
26047+ .fin = au_wbr_create_fin_mfs
26048+ },
26049+ [AuWbrCreate_PMFS] = {
26050+ .create = au_wbr_create_pmfs,
26051+ .init = au_wbr_create_init_mfs,
26052+ .fin = au_wbr_create_fin_mfs
26053+ },
26054+ [AuWbrCreate_PMFSV] = {
26055+ .create = au_wbr_create_pmfs,
26056+ .init = au_wbr_create_init_mfs,
26057+ .fin = au_wbr_create_fin_mfs
26058+ }
26059+};
26060diff -urN linux/fs/aufs/whout.c linux-aufs/fs/aufs/whout.c
26061--- linux/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
26062+++ linux-aufs/fs/aufs/whout.c 2009-03-12 16:18:04.000000000 +0100
26063@@ -0,0 +1,1160 @@
26064+/*
26065+ * Copyright (C) 2005-2009 Junjiro Okajima
26066+ *
26067+ * This program, aufs is free software; you can redistribute it and/or modify
26068+ * it under the terms of the GNU General Public License as published by
26069+ * the Free Software Foundation; either version 2 of the License, or
26070+ * (at your option) any later version.
26071+ *
26072+ * This program is distributed in the hope that it will be useful,
26073+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26074+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26075+ * GNU General Public License for more details.
26076+ *
26077+ * You should have received a copy of the GNU General Public License
26078+ * along with this program; if not, write to the Free Software
26079+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26080+ */
26081+
26082+/*
26083+ * whiteout for logical deletion and opaque directory
26084+ *
26085+ * $Id$
26086+ */
26087+
26088+#include <linux/fs.h>
26089+#include <linux/namei.h>
26090+#include "aufs.h"
26091+
26092+#define WH_MASK S_IRUGO
26093+
26094+/* If a directory contains this file, then it is opaque. We start with the
26095+ * .wh. flag so that it is blocked by lookup.
26096+ */
26097+static struct qstr diropq_name = {
26098+ .name = AUFS_WH_DIROPQ,
26099+ .len = sizeof(AUFS_WH_DIROPQ) - 1
26100+};
26101+
26102+/*
26103+ * generate whiteout name, which is NOT terminated by NULL.
26104+ * @name: original d_name.name
26105+ * @len: original d_name.len
26106+ * @wh: whiteout qstr
26107+ * returns zero when succeeds, otherwise error.
26108+ * succeeded value as wh->name should be freed by au_wh_name_free().
26109+ */
26110+int au_wh_name_alloc(const char *name, int len, struct qstr *wh)
26111+{
26112+ char *p;
26113+
26114+ AuDebugOn(!name || !len || !wh);
26115+
26116+ if (unlikely(len > PATH_MAX - AUFS_WH_PFX_LEN))
26117+ return -ENAMETOOLONG;
26118+
26119+ wh->len = len + AUFS_WH_PFX_LEN;
26120+ p = kmalloc(wh->len, GFP_NOFS);
26121+ wh->name = p;
26122+ if (p) {
26123+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
26124+ memcpy(p + AUFS_WH_PFX_LEN, name, len);
26125+ /* smp_mb(); */
26126+ return 0;
26127+ }
26128+ return -ENOMEM;
26129+}
26130+
26131+void au_wh_name_free(struct qstr *wh)
26132+{
26133+ AuDebugOn(!wh || !wh->name);
26134+ kfree(wh->name);
26135+}
26136+
26137+/* ---------------------------------------------------------------------- */
26138+
26139+/*
26140+ * test if the @wh_name exists under @h_parent.
26141+ * @try_sio specifies the necessary of super-io.
26142+ */
26143+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
26144+ struct au_ndx *ndx)
26145+{
26146+ int err;
26147+ struct dentry *wh_dentry;
26148+ struct inode *h_dir;
26149+ unsigned int flags;
26150+
26151+ LKTRTrace("%.*s/%.*s, ndx{%p, 0x%x}\n", AuDLNPair(h_parent),
26152+ wh_name->len, wh_name->name, ndx->nfsmnt, ndx->flags);
26153+ h_dir = h_parent->d_inode;
26154+ AuDebugOn(!S_ISDIR(h_dir->i_mode));
26155+
26156+ flags = 0;
26157+ if (ndx && ndx->nd) {
26158+ flags = ndx->nd->flags;
26159+ ndx->nd->flags &= ~(LOOKUP_OPEN | LOOKUP_CREATE);
26160+ }
26161+
26162+ if (!try_sio)
26163+ wh_dentry = au_lkup_one(wh_name->name, h_parent,
26164+ wh_name->len, ndx);
26165+ else
26166+ wh_dentry = au_sio_lkup_one(wh_name->name, h_parent,
26167+ wh_name->len, ndx);
26168+ if (flags)
26169+ ndx->nd->flags = flags;
26170+ err = PTR_ERR(wh_dentry);
26171+ if (IS_ERR(wh_dentry))
26172+ goto out;
26173+
26174+ err = 0;
26175+ if (!wh_dentry->d_inode)
26176+ goto out_wh; /* success */
26177+
26178+ err = 1;
26179+ if (S_ISREG(wh_dentry->d_inode->i_mode))
26180+ goto out_wh; /* success */
26181+
26182+ err = -EIO;
26183+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
26184+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
26185+
26186+ out_wh:
26187+ dput(wh_dentry);
26188+ out:
26189+ AuTraceErr(err);
26190+ return err;
26191+}
26192+
26193+/*
26194+ * test if the @h_dentry sets opaque or not.
26195+ */
26196+int au_diropq_test(struct dentry *h_dentry, struct au_ndx *ndx)
26197+{
26198+ int err, try_sio;
26199+ struct inode *h_dir;
26200+
26201+ LKTRTrace("dentry %.*s\n", AuDLNPair(h_dentry));
26202+ h_dir = h_dentry->d_inode;
26203+ AuDebugOn(!S_ISDIR(h_dir->i_mode));
26204+
26205+ try_sio = au_test_h_perm_sio(h_dir, MAY_EXEC,
26206+ au_ftest_ndx(ndx->flags, DLGT));
26207+ err = au_wh_test(h_dentry, &diropq_name, try_sio, ndx);
26208+ AuTraceErr(err);
26209+ return err;
26210+}
26211+
26212+/*
26213+ * returns a negative dentry whose name is unique and temporary.
26214+ */
26215+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct qstr *prefix,
26216+ struct au_ndx *ndx)
26217+{
26218+#define HEX_LEN 4
26219+ struct dentry *dentry;
26220+ int len, i;
26221+ char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
26222+ + HEX_LEN + 1], *name, *p;
26223+ static unsigned char cnt;
26224+
26225+ LKTRTrace("hp %.*s, prefix %.*s\n",
26226+ AuDLNPair(h_parent), prefix->len, prefix->name);
26227+ AuDebugOn(!h_parent->d_inode);
26228+
26229+ name = defname;
26230+ len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
26231+ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
26232+ dentry = ERR_PTR(-ENAMETOOLONG);
26233+ if (unlikely(len >= PATH_MAX))
26234+ goto out;
26235+ dentry = ERR_PTR(-ENOMEM);
26236+ name = kmalloc(len + 1, GFP_NOFS);
26237+ if (unlikely(!name))
26238+ goto out;
26239+ }
26240+
26241+ /* doubly whiteout-ed */
26242+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
26243+ p = name + AUFS_WH_PFX_LEN * 2;
26244+ memcpy(p, prefix->name, prefix->len);
26245+ p += prefix->len;
26246+ *p++ = '.';
26247+ AuDebugOn(name + len + 1 - p <= HEX_LEN);
26248+
26249+ for (i = 0; i < 3; i++) {
26250+ sprintf(p, "%.*d", HEX_LEN, cnt++);
26251+ dentry = au_sio_lkup_one(name, h_parent, len, ndx);
26252+ if (IS_ERR(dentry) || !dentry->d_inode)
26253+ goto out_name;
26254+ dput(dentry);
26255+ }
26256+ /* AuWarn("could not get random name\n"); */
26257+ dentry = ERR_PTR(-EEXIST);
26258+ AuDbg("%.*s\n", len, name);
26259+ BUG();
26260+
26261+ out_name:
26262+ if (name != defname)
26263+ kfree(name);
26264+ out:
26265+ AuTraceErrPtr(dentry);
26266+ return dentry;
26267+#undef HEX_LEN
26268+}
26269+
26270+/*
26271+ * rename the @dentry of @bindex to the whiteouted temporary name.
26272+ */
26273+int au_whtmp_ren(struct inode *dir, aufs_bindex_t bindex,
26274+ struct dentry *h_dentry)
26275+{
26276+ int err, dlgt;
26277+ struct inode *h_dir;
26278+ struct dentry *h_parent, *tmp_dentry;
26279+ struct super_block *sb;
26280+ unsigned int mnt_flags;
26281+ struct au_hin_ignore ign;
26282+ struct vfsub_args vargs;
26283+ struct au_ndx ndx = {
26284+ .flags = 0,
26285+ .nd = NULL,
26286+ /* .br = NULL */
26287+ };
26288+
26289+ LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
26290+ AuDebugOn(!h_dentry->d_inode);
26291+ h_parent = h_dentry->d_parent; /* dir inode is locked */
26292+ h_dir = h_parent->d_inode;
26293+ IMustLock(h_dir);
26294+
26295+ sb = dir->i_sb;
26296+ mnt_flags = au_mntflags(sb);
26297+ dlgt = !!au_test_dlgt(mnt_flags);
26298+ if (dlgt)
26299+ au_fset_ndx(ndx.flags, DLGT);
26300+ ndx.nfsmnt = au_nfsmnt(sb, bindex);
26301+ tmp_dentry = au_whtmp_lkup(h_parent, &h_dentry->d_name, &ndx);
26302+ err = PTR_ERR(tmp_dentry);
26303+ if (IS_ERR(tmp_dentry))
26304+ goto out;
26305+
26306+ /* under the same dir, no need to lock_rename() */
26307+ vfsub_args_init(&vargs, &ign, dlgt, 0);
26308+ AuDebugOn(!S_ISDIR(h_dentry->d_inode->i_mode));
26309+ vfsub_ign_hinode(&vargs, IN_MOVED_FROM | IN_MOVED_TO,
26310+ au_hi(dir, bindex));
26311+ err = vfsub_rename(h_dir, h_dentry, h_dir, tmp_dentry, &vargs);
26312+ AuTraceErr(err);
26313+ dput(tmp_dentry);
26314+
26315+ out:
26316+ AuTraceErr(err);
26317+ return err;
26318+}
26319+
26320+/* ---------------------------------------------------------------------- */
26321+
26322+static int do_unlink_wh(struct au_hinode *hdir, struct inode *h_dir,
26323+ struct dentry *wh_dentry, const int dlgt)
26324+{
26325+ int err;
26326+ struct au_hin_ignore ign;
26327+ struct vfsub_args vargs;
26328+
26329+ AuDebugOn(hdir && h_dir);
26330+ AuDebugOn(!hdir && !h_dir);
26331+ if (!h_dir)
26332+ h_dir = hdir->hi_inode;
26333+ LKTRTrace("hi%lu, wh %.*s\n", h_dir->i_ino, AuDLNPair(wh_dentry));
26334+ AuDebugOn(!wh_dentry->d_inode || !S_ISREG(wh_dentry->d_inode->i_mode));
26335+
26336+ /*
26337+ * forces superio when the dir has a sticky bit.
26338+ * this may be a violation of unix fs semantics.
26339+ */
26340+ vfsub_args_init(&vargs, &ign, dlgt,
26341+ (h_dir->i_mode & S_ISVTX)
94750128 26342+ && wh_dentry->d_inode->i_uid != current_fsuid());
024a5822
JR
26343+ vfsub_ign_hinode(&vargs, IN_DELETE, hdir);
26344+ err = vfsub_unlink(h_dir, wh_dentry, &vargs);
26345+ AuTraceErr(err);
26346+ return err;
26347+}
26348+
26349+int au_wh_unlink_dentry(struct au_hinode *hdir, struct dentry *wh_dentry,
26350+ struct dentry *dentry, int dlgt)
26351+{
26352+ int err;
26353+
26354+ LKTRTrace("i%lu, wh %.*s, d %p\n",
26355+ hdir->hi_inode->i_ino, AuDLNPair(wh_dentry), dentry);
26356+ AuDebugOn((dentry && au_dbwh(dentry) < 0)
26357+ || !wh_dentry->d_inode
26358+ || !S_ISREG(wh_dentry->d_inode->i_mode));
26359+
26360+ err = do_unlink_wh(hdir, /*h_dir*/NULL, wh_dentry, dlgt);
26361+ if (!err && dentry)
26362+ au_set_dbwh(dentry, -1);
26363+
26364+ AuTraceErr(err);
26365+ return err;
26366+}
26367+
26368+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
26369+ struct au_ndx *ndx)
26370+{
26371+ int err;
26372+ struct dentry *wh_dentry;
26373+
26374+ LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(wh));
26375+
26376+ /* au_test_h_perm() is already done */
26377+ wh_dentry = au_lkup_one(wh->name, h_parent, wh->len, ndx);
26378+ if (IS_ERR(wh_dentry))
26379+ err = PTR_ERR(wh_dentry);
26380+ else {
26381+ err = 0;
26382+ if (wh_dentry->d_inode && S_ISREG(wh_dentry->d_inode->i_mode))
26383+ err = do_unlink_wh(/*hdir*/NULL, h_parent->d_inode,
26384+ wh_dentry,
26385+ au_ftest_ndx(ndx->flags, DLGT));
26386+ dput(wh_dentry);
26387+ }
26388+
26389+ AuTraceErr(err);
26390+ return err;
26391+}
26392+
26393+/* ---------------------------------------------------------------------- */
26394+
26395+static void clean_wh(struct inode *h_dir, struct path *whpath,
26396+ struct au_hinode *hdir, struct vfsub_args *vargs)
26397+{
26398+ int err;
26399+
26400+ AuTraceEnter();
26401+
26402+ if (!whpath->dentry->d_inode)
26403+ return;
26404+
26405+ err = au_mnt_want_write(whpath->mnt);
26406+ if (!err) {
26407+ vfsub_args_reinit(vargs);
26408+ vfsub_ign_hinode(vargs, IN_DELETE, hdir);
26409+ err = vfsub_unlink(h_dir, whpath->dentry, vargs);
26410+ au_mnt_drop_write(whpath->mnt);
26411+ }
26412+ if (unlikely(err))
26413+ AuWarn("failed unlink %.*s (%d), ignored.\n",
26414+ AuDLNPair(whpath->dentry), err);
26415+}
26416+
26417+static void au_whdir_clean(struct inode *h_dir, struct path *whpath,
26418+ struct au_hinode *hdir, struct vfsub_args *vargs)
26419+{
26420+ int err;
26421+
26422+ AuTraceEnter();
26423+
26424+ if (!whpath->dentry->d_inode)
26425+ return;
26426+
26427+ err = au_mnt_want_write(whpath->mnt);
26428+ if (!err) {
26429+ vfsub_args_reinit(vargs);
26430+ vfsub_ign_hinode(vargs, IN_DELETE, hdir);
26431+ err = vfsub_rmdir(h_dir, whpath->dentry, vargs);
26432+ au_mnt_drop_write(whpath->mnt);
26433+ }
26434+ if (unlikely(err))
26435+ AuWarn("failed rmdir %.*s (%d), ignored.\n",
26436+ AuDLNPair(whpath->dentry), err);
26437+}
26438+
26439+static int test_linkable(struct inode *h_dir)
26440+{
26441+ if (h_dir->i_op && h_dir->i_op->link)
26442+ return 0;
26443+ return -ENOSYS;
26444+}
26445+
26446+/* todo: should this mkdir be done in /sbin/mount.aufs script? */
26447+static int au_whdir(struct inode *h_dir, struct path *path,
26448+ struct au_hinode *hdir, struct vfsub_args *vargs)
26449+{
26450+ int err;
26451+
26452+ err = -EEXIST;
26453+ if (!path->dentry->d_inode) {
26454+ int mode = S_IRWXU;
26455+ if (au_test_nfs(path->dentry->d_sb))
26456+ mode |= S_IXUGO;
26457+ err = au_mnt_want_write(path->mnt);
26458+ if (!err) {
26459+ vfsub_args_reinit(vargs);
26460+ vfsub_ign_hinode(vargs, IN_CREATE, hdir);
26461+ err = vfsub_mkdir(h_dir, path->dentry, mode, vargs);
26462+ au_mnt_drop_write(path->mnt);
26463+ }
26464+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
26465+ err = 0;
26466+ else
26467+ AuErr("unknown %.*s exists\n", AuDLNPair(path->dentry));
26468+
26469+ return err;
26470+}
26471+
26472+/*
26473+ * initialize the whiteout base file/dir for @br.
26474+ */
26475+int au_wh_init(struct dentry *h_root, struct au_branch *br,
26476+ struct vfsmount *h_mnt, struct super_block *sb,
26477+ aufs_bindex_t bindex)
26478+{
26479+ int err, i;
26480+ const unsigned int mnt_flags = au_mntflags(sb);
26481+ const unsigned char do_plink = !!au_opt_test(mnt_flags, PLINK),
26482+ do_hinotify = au_opt_test(mnt_flags, UDBA_INOTIFY);
26483+ struct path path = {
26484+ .mnt = h_mnt
26485+ };
26486+ struct au_hin_ignore ign;
26487+ struct vfsub_args vargs;
26488+ struct inode *h_dir;
26489+ struct au_hinode *hdir;
26490+ struct au_wbr *wbr = br->br_wbr;
26491+ struct vfsmount *nfsmnt = au_do_nfsmnt(h_mnt);
26492+ static const struct qstr base_name[] = {
26493+ [AuBrWh_BASE] = {
26494+ .name = AUFS_BASE_NAME,
26495+ .len = sizeof(AUFS_BASE_NAME) - 1
26496+ },
26497+ [AuBrWh_PLINK] = {
26498+ .name = AUFS_PLINKDIR_NAME,
26499+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
26500+ },
26501+ [AuBrWh_TMP] = {
26502+ .name = AUFS_TMPDIR_NAME,
26503+ .len = sizeof(AUFS_TMPDIR_NAME) - 1
26504+ }
26505+ };
26506+ struct {
26507+ const struct qstr *name;
26508+ struct dentry *dentry;
26509+ } base[] = {
26510+ [AuBrWh_BASE] = {
26511+ .name = base_name + AuBrWh_BASE,
26512+ .dentry = NULL
26513+ },
26514+ [AuBrWh_PLINK] = {
26515+ .name = base_name + AuBrWh_PLINK,
26516+ .dentry = NULL
26517+ },
26518+ [AuBrWh_TMP] = {
26519+ .name = base_name + AuBrWh_TMP,
26520+ .dentry = NULL
26521+ }
26522+ };
26523+ struct au_ndx ndx = {
26524+ .nfsmnt = nfsmnt,
26525+ .flags = 0, /* always no dlgt */
26526+ .nd = NULL,
26527+ /* .br = NULL */
26528+ };
26529+
26530+ LKTRTrace("nfsmnt %p\n", nfsmnt);
26531+ WbrWhMustWriteLock(wbr);
26532+ SiMustWriteLock(sb);
26533+ h_dir = h_root->d_inode;
26534+
26535+ for (i = 0; i < AuBrWh_Last; i++) {
26536+ /* doubly whiteouted */
26537+ struct dentry *d;
26538+ d = au_wh_lkup(h_root, (void *)base[i].name, &ndx);
26539+ err = PTR_ERR(d);
26540+ if (IS_ERR(d))
26541+ goto out;
26542+ base[i].dentry = d;
26543+ if (!au_test_ecryptfs(d->d_sb))
26544+ AuDebugOn(wbr
26545+ && wbr->wbr_wh[i]
26546+ && wbr->wbr_wh[i] != base[i].dentry);
26547+ else
26548+ /* ecryptfs problem?: it returns different dentry */
26549+ AuDebugOn(wbr
26550+ && wbr->wbr_wh[i]
26551+ && !!wbr->wbr_wh[i] != !!base[i].dentry);
26552+ }
26553+
26554+ if (wbr)
26555+ for (i = 0; i < AuBrWh_Last; i++) {
26556+ dput(wbr->wbr_wh[i]);
26557+ wbr->wbr_wh[i] = NULL;
26558+ }
26559+
26560+ err = 0;
26561+ hdir = NULL;
26562+ if (bindex >= 0 && do_hinotify)
26563+ hdir = au_hi(sb->s_root->d_inode, bindex);
26564+ vfsub_args_init(&vargs, &ign, au_test_dlgt(mnt_flags), 0);
26565+
26566+ switch (br->br_perm) {
26567+ case AuBrPerm_RR:
26568+ case AuBrPerm_RO:
26569+ case AuBrPerm_RRWH:
26570+ case AuBrPerm_ROWH:
26571+ path.dentry = base[AuBrWh_BASE].dentry;
26572+ clean_wh(h_dir, &path, hdir, &vargs);
26573+ path.dentry = base[AuBrWh_PLINK].dentry;
26574+ au_whdir_clean(h_dir, &path, hdir, &vargs);
26575+ path.dentry = base[AuBrWh_TMP].dentry;
26576+ au_whdir_clean(h_dir, &path, hdir, &vargs);
26577+ break;
26578+
26579+ case AuBrPerm_RWNoLinkWH:
26580+ path.dentry = base[AuBrWh_BASE].dentry;
26581+ clean_wh(h_dir, &path, hdir, &vargs);
26582+ path.dentry = base[AuBrWh_PLINK].dentry;
26583+ if (do_plink) {
26584+ err = test_linkable(h_dir);
26585+ if (unlikely(err))
26586+ goto out_nolink;
26587+
26588+ err = au_whdir(h_dir, &path, hdir, &vargs);
26589+ if (unlikely(err))
26590+ goto out_err;
26591+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
26592+ } else
26593+ au_whdir_clean(h_dir, &path, hdir, &vargs);
26594+ path.dentry = base[AuBrWh_TMP].dentry;
26595+ err = au_whdir(h_dir, &path, hdir, &vargs);
26596+ if (unlikely(err))
26597+ goto out_err;
26598+ wbr->wbr_tmp = dget(base[AuBrWh_TMP].dentry);
26599+ break;
26600+
26601+ case AuBrPerm_RW:
26602+ /*
26603+ * for the moment, aufs supports the branch filesystem
26604+ * which does not support link(2).
26605+ * testing on FAT which does not support i_op->setattr() fully
26606+ * either, copyup failed.
26607+ * finally, such filesystem will not be used as the writable
26608+ * branch.
26609+ */
26610+ err = test_linkable(h_dir);
26611+ if (unlikely(err))
26612+ goto out_nolink;
26613+
26614+ err = -EEXIST;
26615+ /*
26616+ * todo: should this create be done
26617+ * in /sbin/mount.aufs script?
26618+ */
26619+ if (!base[AuBrWh_BASE].dentry->d_inode) {
26620+ err = au_mnt_want_write(h_mnt);
26621+ if (!err) {
26622+ vfsub_args_reinit(&vargs);
26623+ vfsub_ign_hinode(&vargs, IN_CREATE, hdir);
26624+ err = au_h_create
26625+ (h_dir, base[AuBrWh_BASE].dentry,
26626+ WH_MASK, &vargs, /*nd*/NULL, nfsmnt);
26627+ au_mnt_drop_write(h_mnt);
26628+ }
26629+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
26630+ err = 0;
26631+ else
26632+ AuErr("unknown %.*s/%.*s exists\n",
26633+ AuDLNPair(h_root),
26634+ AuDLNPair(base[AuBrWh_BASE].dentry));
26635+ if (unlikely(err))
26636+ goto out_err;
26637+
26638+ path.dentry = base[AuBrWh_PLINK].dentry;
26639+ if (do_plink) {
26640+ err = au_whdir(h_dir, &path, hdir, &vargs);
26641+ if (unlikely(err))
26642+ goto out_err;
26643+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
26644+ } else
26645+ au_whdir_clean(h_dir, &path, hdir, &vargs);
26646+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
26647+
26648+ path.dentry = base[AuBrWh_TMP].dentry;
26649+ err = au_whdir(h_dir, &path, hdir, &vargs);
26650+ if (unlikely(err))
26651+ goto out_err;
26652+ wbr->wbr_tmp = dget(base[AuBrWh_TMP].dentry);
26653+ break;
26654+
26655+ default:
26656+ BUG();
26657+ }
26658+
26659+ out:
26660+ for (i = 0; i < AuBrWh_Last; i++)
26661+ dput(base[i].dentry);
26662+ AuTraceErr(err);
26663+ return err;
26664+ out_nolink:
26665+ AuErr("%.*s doesn't support link(2), use noplink and rw+nolwh\n",
26666+ AuDLNPair(h_root));
26667+ goto out;
26668+ out_err:
26669+ AuErr("an error(%d) on the writable branch %.*s(%s)\n",
26670+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
26671+ goto out;
26672+}
26673+
26674+struct reinit_br_wh {
26675+ struct super_block *sb;
26676+ struct au_branch *br;
26677+};
26678+
26679+static void reinit_br_wh(void *arg)
26680+{
26681+ int err;
26682+ struct reinit_br_wh *a = arg;
26683+ struct au_wbr *wbr;
26684+ struct inode *h_dir, *dir;
26685+ struct dentry *h_root;
26686+ aufs_bindex_t bindex;
26687+ struct au_hin_ignore ign;
26688+ struct vfsub_args vargs;
26689+
26690+ AuTraceEnter();
94750128 26691+ AuDebugOn(current_fsuid());
024a5822
JR
26692+
26693+ err = 0;
26694+ wbr = a->br->br_wbr;
26695+ /* big aufs lock */
26696+ si_noflush_write_lock(a->sb);
26697+ if (!au_br_writable(a->br->br_perm))
26698+ goto out;
26699+ bindex = au_br_index(a->sb, a->br->br_id);
26700+ if (unlikely(bindex < 0))
26701+ goto out;
26702+
26703+ AuDebugOn(!wbr);
26704+ AuDebugOn(!wbr->wbr_whbase || !wbr->wbr_whbase->d_inode);
26705+
26706+ dir = a->sb->s_root->d_inode;
26707+ ii_read_lock_parent(dir);
26708+ h_root = dget_parent(wbr->wbr_whbase);
26709+ h_dir = h_root->d_inode;
26710+ AuDebugOn(!h_dir->i_op || !h_dir->i_op->link);
26711+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
26712+ wbr_wh_write_lock(wbr);
26713+ if (!au_verify_parent(wbr->wbr_whbase, h_dir)) {
26714+ err = au_br_want_write(a->br);
26715+ if (!err) {
26716+ vfsub_args_init(&vargs, &ign, /*dlgt*/0, 0);
26717+ vfsub_ign_hinode(&vargs, IN_DELETE, au_hi(dir, bindex));
26718+ err = vfsub_unlink(h_dir, wbr->wbr_whbase, &vargs);
26719+ au_br_drop_write(a->br);
26720+ }
26721+ } else {
26722+ AuWarn("%.*s is moved, ignored\n", AuDLNPair(wbr->wbr_whbase));
26723+ err = 0;
26724+ }
26725+ dput(wbr->wbr_whbase);
26726+ wbr->wbr_whbase = NULL;
26727+ if (!err)
26728+ err = au_wh_init(h_root, a->br, a->br->br_mnt, a->sb, bindex);
26729+ wbr_wh_write_unlock(wbr);
26730+ mutex_unlock(&h_dir->i_mutex);
26731+ dput(h_root);
26732+ ii_read_unlock(dir);
26733+
26734+ out:
26735+ if (wbr)
26736+ atomic_dec_return(&wbr->wbr_wh_running);
26737+ au_br_put(a->br);
26738+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
26739+ si_write_unlock(a->sb);
26740+ kfree(arg);
26741+ if (unlikely(err))
26742+ AuIOErr("err %d\n", err);
26743+}
26744+
26745+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
26746+{
26747+ int do_dec, wkq_err;
26748+ struct reinit_br_wh *arg;
26749+
26750+ AuTraceEnter();
26751+ AuDebugOn(!br->br_wbr);
26752+
26753+ do_dec = 1;
26754+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
26755+ goto out;
26756+
26757+ /* ignore ENOMEM */
26758+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
26759+ if (arg) {
26760+ /*
26761+ * dec(wh_running), kfree(arg) and au_br_put()
26762+ * in reinit function
26763+ */
26764+ arg->sb = sb;
26765+ arg->br = br;
26766+ au_br_get(br);
26767+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*dlgt*/0);
26768+ if (unlikely(wkq_err)) {
26769+ atomic_dec_return(&br->br_wbr->wbr_wh_running);
26770+ au_br_put(br);
26771+ kfree(arg);
26772+ }
26773+ do_dec = 0;
26774+ }
26775+
26776+ out:
26777+ if (do_dec)
26778+ atomic_dec_return(&br->br_wbr->wbr_wh_running);
26779+}
26780+
26781+/*
26782+ * create the whiteout @wh.
26783+ */
26784+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
26785+ struct dentry *wh, struct inode *dir)
26786+{
26787+ int err, dlgt;
26788+ struct au_branch *br;
26789+ struct au_wbr *wbr;
26790+ struct dentry *h_parent;
26791+ struct inode *h_dir;
26792+ struct au_hin_ignore ign;
26793+ struct vfsub_args vargs;
26794+
26795+ LKTRTrace("%.*s\n", AuDLNPair(wh));
26796+ h_parent = wh->d_parent; /* dir inode is locked */
26797+ h_dir = h_parent->d_inode;
26798+ IMustLock(h_dir);
26799+ br = au_sbr(sb, bindex);
26800+ wbr = br->br_wbr;
26801+ AuDebugOn(!wbr);
26802+
26803+ dlgt = !!au_test_dlgt(au_mntflags(sb));
26804+ wbr_wh_read_lock(wbr);
26805+ if (wbr->wbr_whbase) {
26806+ vfsub_args_init(&vargs, &ign, dlgt, 0);
26807+ if (dir)
26808+ vfsub_ign_hinode(&vargs, IN_CREATE, au_hi(dir, bindex));
26809+ err = vfsub_link(wbr->wbr_whbase, h_dir, wh, &vargs);
26810+ if (!err || err != -EMLINK)
26811+ goto out;
26812+
26813+ /* link count full. re-initialize br_whbase. */
26814+ kick_reinit_br_wh(sb, br);
26815+ }
26816+
26817+ /* return this error in this context */
26818+ vfsub_args_init(&vargs, &ign, dlgt, 0);
26819+ if (dir)
26820+ vfsub_ign_hinode(&vargs, IN_CREATE, au_hi(dir, bindex));
26821+ err = au_h_create(h_dir, wh, WH_MASK, &vargs, /*nd*/NULL,
26822+ au_do_nfsmnt(br->br_mnt));
26823+
26824+ out:
26825+ wbr_wh_read_unlock(wbr);
26826+ AuTraceErr(err);
26827+ return err;
26828+}
26829+
26830+/* ---------------------------------------------------------------------- */
26831+
26832+/*
26833+ * create or remove the diropq.
26834+ */
26835+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
26836+ unsigned int flags)
26837+{
26838+ struct dentry *opq_dentry, *h_dentry;
26839+ struct inode *h_dir;
26840+ int err, dlgt;
26841+ struct super_block *sb;
26842+ struct au_ndx ndx = {
26843+ .flags = 0,
26844+ .nd = NULL,
26845+ /* .br = NULL */
26846+ };
26847+
26848+ LKTRTrace("%.*s, bindex %d, flags 0x%x\n",
26849+ AuDLNPair(dentry), bindex, flags);
26850+ h_dentry = au_h_dptr(dentry, bindex);
26851+ AuDebugOn(!h_dentry);
26852+ h_dir = h_dentry->d_inode;
26853+ AuDebugOn(!h_dir || !S_ISDIR(h_dir->i_mode));
26854+
26855+ /* already checked by au_test_h_perm(). */
26856+ sb = dentry->d_sb;
26857+ ndx.nfsmnt = au_nfsmnt(sb, bindex);
26858+ dlgt = 0;
26859+ if (au_ftest_diropq(flags, DLGT)) {
26860+ dlgt = 1;
26861+ au_fset_ndx(ndx.flags, DLGT);
26862+ }
26863+ opq_dentry = au_lkup_one(diropq_name.name, h_dentry, diropq_name.len,
26864+ &ndx);
26865+ if (IS_ERR(opq_dentry))
26866+ goto out;
26867+
26868+ if (au_ftest_diropq(flags, CREATE)) {
26869+ AuDebugOn(opq_dentry->d_inode);
26870+ err = link_or_create_wh(dentry->d_sb, bindex, opq_dentry,
26871+ dentry->d_inode);
26872+ if (!err) {
26873+ au_set_dbdiropq(dentry, bindex);
26874+ goto out; /* success */
26875+ }
26876+ } else {
26877+ AuDebugOn(/* !S_ISDIR(dentry->d_inode->i_mode)
26878+ * || */!opq_dentry->d_inode);
26879+ err = do_unlink_wh(au_hi(dentry->d_inode, bindex),
26880+ /*h_dir*/NULL, opq_dentry, dlgt);
26881+ if (!err)
26882+ au_set_dbdiropq(dentry, -1);
26883+ }
26884+ dput(opq_dentry);
26885+ opq_dentry = ERR_PTR(err);
26886+
26887+ out:
26888+ AuTraceErrPtr(opq_dentry);
26889+ return opq_dentry;
26890+}
26891+
26892+struct do_diropq_args {
26893+ struct dentry **errp;
26894+ struct dentry *dentry;
26895+ aufs_bindex_t bindex;
26896+ unsigned int flags;
26897+};
26898+
26899+static void call_do_diropq(void *args)
26900+{
26901+ struct do_diropq_args *a = args;
26902+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
26903+}
26904+
26905+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
26906+ unsigned int flags)
26907+{
26908+ struct dentry *diropq, *h_dentry;
26909+
26910+ LKTRTrace("%.*s, bindex %d, flags 0x%x\n",
26911+ AuDLNPair(dentry), bindex, flags);
26912+
26913+ h_dentry = au_h_dptr(dentry, bindex);
26914+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE,
26915+ au_ftest_diropq(flags, DLGT)))
26916+ diropq = do_diropq(dentry, bindex, flags);
26917+ else {
26918+ int wkq_err;
26919+ struct do_diropq_args args = {
26920+ .errp = &diropq,
26921+ .dentry = dentry,
26922+ .bindex = bindex,
26923+ .flags = flags
26924+ };
26925+ wkq_err = au_wkq_wait(call_do_diropq, &args, /*dlgt*/0);
26926+ if (unlikely(wkq_err))
26927+ diropq = ERR_PTR(wkq_err);
26928+ }
26929+
26930+ AuTraceErrPtr(diropq);
26931+ return diropq;
26932+}
26933+
26934+/* ---------------------------------------------------------------------- */
26935+
26936+/*
26937+ * lookup whiteout dentry.
26938+ * @h_parent: hidden parent dentry which must exist and be locked
26939+ * @base_name: name of dentry which will be whiteouted
26940+ * returns dentry for whiteout.
26941+ */
26942+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
26943+ struct au_ndx *ndx)
26944+{
26945+ int err;
26946+ struct qstr wh_name;
26947+ struct dentry *wh_dentry;
26948+
26949+ LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(base_name));
26950+
26951+ err = au_wh_name_alloc(base_name->name, base_name->len, &wh_name);
26952+ wh_dentry = ERR_PTR(err);
26953+ if (!err) {
26954+ /* do not superio. */
26955+ wh_dentry = au_lkup_one(wh_name.name, h_parent,
26956+ wh_name.len, ndx);
26957+ au_wh_name_free(&wh_name);
26958+ }
26959+ AuTraceErrPtr(wh_dentry);
26960+ return wh_dentry;
26961+}
26962+
26963+/*
26964+ * link/create a whiteout for @dentry on @bindex.
26965+ */
26966+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
26967+ struct dentry *h_parent, struct au_ndx *ndx)
26968+{
26969+ struct dentry *wh_dentry;
26970+ struct inode *dir;
26971+ int err;
26972+ struct super_block *sb;
26973+
26974+ LKTRTrace("%.*s/%.*s on b%d\n", AuDLNPair(h_parent),
26975+ AuDLNPair(dentry), bindex);
26976+
26977+ sb = dentry->d_sb;
26978+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, ndx);
26979+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
26980+ dir = dentry->d_parent->d_inode; /* dir is locked */
26981+ IMustLock(dir);
26982+ err = link_or_create_wh(sb, bindex, wh_dentry, dir);
26983+ if (!err)
26984+ au_set_dbwh(dentry, bindex);
26985+ else {
26986+ dput(wh_dentry);
26987+ wh_dentry = ERR_PTR(err);
26988+ }
26989+ }
26990+
26991+ AuTraceErrPtr(wh_dentry);
26992+ return wh_dentry;
26993+}
26994+
26995+/* ---------------------------------------------------------------------- */
26996+
26997+/* Delete all whiteouts in this directory on branch bindex. */
26998+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
26999+ aufs_bindex_t bindex, struct au_ndx *ndx)
27000+{
27001+ int err, i;
27002+ struct qstr wh_name;
27003+ char *p;
27004+ struct inode *h_inode;
27005+ struct hlist_head *head;
27006+ struct au_vdir_wh *tpos;
27007+ struct hlist_node *pos;
27008+ struct au_vdir_destr *str;
27009+
27010+ LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
27011+ h_inode = h_dentry->d_inode;
27012+ AuDebugOn(IS_RDONLY(h_inode));
27013+
27014+ err = -ENOMEM;
27015+ p = __getname();
27016+ wh_name.name = p;
27017+ if (unlikely(!wh_name.name))
27018+ goto out;
27019+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
27020+ p += AUFS_WH_PFX_LEN;
27021+
27022+ /* already checked by au_test_h_perm(). */
27023+ err = 0;
27024+ for (i = 0; !err && i < AuSize_NHASH; i++) {
27025+ head = whlist->heads + i;
27026+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
27027+ if (tpos->wh_bindex != bindex)
27028+ continue;
27029+ str = &tpos->wh_str;
27030+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
27031+ memcpy(p, str->name, str->len);
27032+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
27033+ err = unlink_wh_name(h_dentry, &wh_name, ndx);
27034+ if (!err)
27035+ continue;
27036+ break;
27037+ }
27038+ AuIOErr("whiteout name too long %.*s\n",
27039+ str->len, str->name);
27040+ err = -EIO;
27041+ break;
27042+ }
27043+ }
27044+ __putname(wh_name.name);
27045+
27046+ out:
27047+ AuTraceErr(err);
27048+ return err;
27049+}
27050+
27051+struct del_wh_children_args {
27052+ int *errp;
27053+ struct dentry *h_dentry;
27054+ struct au_nhash *whlist;
27055+ aufs_bindex_t bindex;
27056+ struct au_ndx *ndx;
27057+};
27058+
27059+static void call_del_wh_children(void *args)
27060+{
27061+ struct del_wh_children_args *a = args;
27062+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->ndx);
27063+}
27064+
27065+/* ---------------------------------------------------------------------- */
27066+
27067+/*
27068+ * rmdir the whiteouted temporary named dir @h_dentry.
27069+ * @whlist: whiteouted children.
27070+ */
27071+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
27072+ struct dentry *wh_dentry, struct au_nhash *whlist)
27073+{
27074+ int err, dlgt;
27075+ struct inode *wh_inode, *h_dir;
27076+ struct super_block *sb;
27077+ unsigned int mnt_flags;
27078+ struct au_hin_ignore ign;
27079+ struct vfsub_args vargs;
27080+ struct au_ndx ndx = {
27081+ .flags = 0,
27082+ .nd = NULL,
27083+ /* .br = NULL */
27084+ };
27085+
27086+ LKTRTrace("i%lu, %.*s, b%d\n",
27087+ dir->i_ino, AuDLNPair(wh_dentry), bindex);
27088+ /* IMustLock(dir); */
27089+ IiMustAnyLock(dir);
27090+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
27091+ IMustLock(h_dir);
27092+
27093+ sb = dir->i_sb;
27094+ mnt_flags = au_mntflags(sb);
27095+ dlgt = !!au_test_dlgt(mnt_flags);
27096+ if (dlgt)
27097+ au_fset_ndx(ndx.flags, DLGT);
27098+ ndx.nfsmnt = au_nfsmnt(sb, bindex);
27099+ wh_inode = wh_dentry->d_inode;
27100+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
27101+
27102+ /*
27103+ * someone else might change some whiteouts while we were sleeping.
27104+ * it means this whlist may have an obsoleted entry.
27105+ */
27106+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE, dlgt))
27107+ err = del_wh_children(wh_dentry, whlist, bindex, &ndx);
27108+ else {
27109+ int wkq_err;
27110+ /* ugly */
27111+ unsigned int flags = ndx.flags;
27112+ struct del_wh_children_args args = {
27113+ .errp = &err,
27114+ .h_dentry = wh_dentry,
27115+ .whlist = whlist,
27116+ .bindex = bindex,
27117+ .ndx = &ndx
27118+ };
27119+
27120+ ndx.flags = 0;
27121+ wkq_err = au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0);
27122+ if (unlikely(wkq_err))
27123+ err = wkq_err;
27124+ ndx.flags = flags;
27125+ }
27126+ mutex_unlock(&wh_inode->i_mutex);
27127+
27128+ if (!err) {
27129+ vfsub_args_init(&vargs, &ign, dlgt, 0);
27130+ vfsub_ign_hinode(&vargs, IN_DELETE, au_hi(dir, bindex));
27131+ err = vfsub_rmdir(h_dir, wh_dentry, &vargs);
27132+ /* d_drop(h_dentry); */
27133+ }
27134+
27135+ if (!err) {
27136+ if (au_ibstart(dir) == bindex) {
27137+ au_cpup_attr_timesizes(dir);
27138+ /* au_cpup_attr_nlink(dir); */
27139+ drop_nlink(dir);
27140+ }
27141+ return 0; /* success */
27142+ }
27143+
27144+ AuWarn("failed removing %.*s(%d), ignored\n",
27145+ AuDLNPair(wh_dentry), err);
27146+ return err;
27147+}
27148+
27149+static void au_whtmp_rmdir_free_args(struct au_whtmp_rmdir_args *args)
27150+{
27151+ au_nhash_fin(&args->whlist);
27152+ dput(args->wh_dentry);
27153+ iput(args->dir);
27154+ kfree(args);
27155+}
27156+
27157+static void call_rmdir_whtmp(void *args)
27158+{
27159+ int err;
27160+ struct au_whtmp_rmdir_args *a = args;
27161+ struct super_block *sb;
27162+ struct dentry *h_parent;
27163+ struct inode *h_dir;
27164+
27165+ LKTRTrace("%.*s, b%d, dir i%lu\n",
27166+ AuDLNPair(a->wh_dentry), a->bindex, a->dir->i_ino);
27167+
27168+ /* rmdir by nfsd may cause deadlock with this i_mutex */
27169+ /* mutex_lock(&a->dir->i_mutex); */
27170+ sb = a->dir->i_sb;
27171+ si_noflush_read_lock(sb);
27172+ err = au_test_ro(sb, a->bindex, NULL);
27173+ if (unlikely(err))
27174+ goto out;
27175+
27176+ err = -EIO;
27177+ ii_write_lock_parent(a->dir);
27178+ h_parent = dget_parent(a->wh_dentry);
27179+ h_dir = h_parent->d_inode;
27180+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
27181+ if (!au_verify_parent(a->wh_dentry, h_dir)) {
27182+ err = au_br_want_write(au_sbr(sb, a->bindex));
27183+ if (!err) {
27184+ err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
27185+ &a->whlist);
27186+ au_br_drop_write(au_sbr(sb, a->bindex));
27187+ }
27188+ }
27189+ mutex_unlock(&h_dir->i_mutex);
27190+ dput(h_parent);
27191+ ii_write_unlock(a->dir);
27192+
27193+ out:
27194+ /* mutex_unlock(&a->dir->i_mutex); */
27195+ au_nwt_done(&au_sbi(sb)->si_nowait);
27196+ si_read_unlock(sb);
27197+ au_whtmp_rmdir_free_args(a);
27198+ if (unlikely(err))
27199+ AuIOErr("err %d\n", err);
27200+}
27201+
27202+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
27203+ struct dentry *wh_dentry, struct au_nhash *whlist,
27204+ struct au_whtmp_rmdir_args *args)
27205+{
27206+ int wkq_err;
27207+
27208+ LKTRTrace("%.*s\n", AuDLNPair(wh_dentry));
27209+ IMustLock(dir);
27210+
27211+ /* all post-process will be done in do_rmdir_whtmp(). */
27212+ args->dir = au_igrab(dir);
27213+ args->bindex = bindex;
27214+ args->wh_dentry = dget(wh_dentry);
27215+ au_nhash_init(&args->whlist);
27216+ au_nhash_move(&args->whlist, whlist);
27217+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb, /*dlgt*/0);
27218+ if (unlikely(wkq_err)) {
27219+ AuWarn("rmdir error %.*s (%d), ignored\n",
27220+ AuDLNPair(wh_dentry), wkq_err);
27221+ au_whtmp_rmdir_free_args(args);
27222+ }
27223+}
27224diff -urN linux/fs/aufs/whout.h linux-aufs/fs/aufs/whout.h
27225--- linux/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
27226+++ linux-aufs/fs/aufs/whout.h 2009-03-12 16:18:04.000000000 +0100
27227@@ -0,0 +1,137 @@
27228+/*
27229+ * Copyright (C) 2005-2009 Junjiro Okajima
27230+ *
27231+ * This program, aufs is free software; you can redistribute it and/or modify
27232+ * it under the terms of the GNU General Public License as published by
27233+ * the Free Software Foundation; either version 2 of the License, or
27234+ * (at your option) any later version.
27235+ *
27236+ * This program is distributed in the hope that it will be useful,
27237+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27238+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27239+ * GNU General Public License for more details.
27240+ *
27241+ * You should have received a copy of the GNU General Public License
27242+ * along with this program; if not, write to the Free Software
27243+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27244+ */
27245+
27246+/*
27247+ * whiteout for logical deletion and opaque directory
27248+ *
27249+ * $Id$
27250+ */
27251+
27252+#ifndef __AUFS_WHOUT_H__
27253+#define __AUFS_WHOUT_H__
27254+
27255+#ifdef __KERNEL__
27256+
27257+#include <linux/fs.h>
27258+#include <linux/aufs_type.h>
27259+#include "dir.h"
27260+#include "opts.h"
27261+#include "super.h"
27262+
27263+int au_wh_name_alloc(const char *name, int len, struct qstr *wh);
27264+void au_wh_name_free(struct qstr *wh);
27265+
27266+struct au_ndx;
27267+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
27268+ struct au_ndx *ndx);
27269+int au_diropq_test(struct dentry *h_dentry, struct au_ndx *ndx);
27270+
27271+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct qstr *prefix,
27272+ struct au_ndx *ndx);
27273+int au_whtmp_ren(struct inode *dir, aufs_bindex_t bindex,
27274+ struct dentry *h_dentry);
27275+int au_wh_unlink_dentry(struct au_hinode *dir, struct dentry *wh_dentry,
27276+ struct dentry *dentry, int dlgt);
27277+
27278+struct au_branch;
27279+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
27280+ struct vfsmount *nfsmnt, struct super_block *sb,
27281+ aufs_bindex_t bindex);
27282+
27283+/* diropq flags */
27284+#define AuDiropq_CREATE 1
27285+#define AuDiropq_DLGT (1 << 1)
27286+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
27287+#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
27288+#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
27289+#ifndef CONFIG_AUFS_DLGT
27290+#undef AuDiropq_DLGT
27291+#define AuDiropq_DLGT 0
27292+#endif
27293+
27294+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
27295+ unsigned int flags);
27296+
27297+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
27298+ struct au_ndx *ndx);
27299+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
27300+ struct dentry *h_parent, struct au_ndx *ndx);
27301+
27302+/* real rmdir the whiteout-ed dir */
27303+struct au_whtmp_rmdir_args {
27304+ struct inode *dir;
27305+ aufs_bindex_t bindex;
27306+ struct dentry *wh_dentry;
27307+ struct au_nhash whlist;
27308+};
27309+
27310+struct au_nhash;
27311+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
27312+ struct dentry *wh_dentry, struct au_nhash *whlist);
27313+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
27314+ struct dentry *wh_dentry, struct au_nhash *whlist,
27315+ struct au_whtmp_rmdir_args *args);
27316+
27317+/* ---------------------------------------------------------------------- */
27318+
27319+static inline
27320+struct dentry *au_diropq_create(struct dentry *dentry, aufs_bindex_t bindex,
27321+ int dlgt)
27322+{
27323+ unsigned int flags = AuDiropq_CREATE;
27324+ if (dlgt)
27325+ au_fset_diropq(flags, DLGT);
27326+ return au_diropq_sio(dentry, bindex, flags);
27327+}
27328+
27329+static inline
27330+int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex, int dlgt)
27331+{
27332+ unsigned int flags = !AuDiropq_CREATE;
27333+ if (dlgt)
27334+ au_fset_diropq(flags, DLGT);
27335+ return PTR_ERR(au_diropq_sio(dentry, bindex, flags));
27336+}
27337+
27338+/* ---------------------------------------------------------------------- */
27339+
27340+#ifdef CONFIG_AUFS_ROBR
27341+/* robr.c */
27342+int au_test_robr_wh(struct qstr *name, struct dentry *h_parent,
27343+ struct qstr *wh_name, int try_sio, struct au_ndx *ndx);
27344+int au_test_robr_shwh(struct super_block *sb, const struct qstr *name);
27345+#else
27346+static inline
27347+int au_test_robr_wh(struct qstr *name, struct dentry *h_parent,
27348+ struct qstr *wh_name, int try_sio, struct au_ndx *ndx)
27349+{
27350+ return au_wh_test(h_parent, wh_name, try_sio, ndx);
27351+}
27352+
27353+static inline
27354+int au_test_robr_shwh(struct super_block *sb, const struct qstr *name)
27355+{
27356+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
27357+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
27358+ return -EPERM;
27359+ return 0;
27360+}
27361+#endif /* CONFIG_AUFS_ROBR */
27362+
27363+#endif /* __KERNEL__ */
27364+#endif /* __AUFS_WHOUT_H__ */
27365diff -urN linux/fs/aufs/wkq.c linux-aufs/fs/aufs/wkq.c
27366--- linux/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
27367+++ linux-aufs/fs/aufs/wkq.c 2009-03-12 16:18:04.000000000 +0100
94750128 27368@@ -0,0 +1,343 @@
024a5822
JR
27369+/*
27370+ * Copyright (C) 2005-2009 Junjiro Okajima
27371+ *
27372+ * This program, aufs is free software; you can redistribute it and/or modify
27373+ * it under the terms of the GNU General Public License as published by
27374+ * the Free Software Foundation; either version 2 of the License, or
27375+ * (at your option) any later version.
27376+ *
27377+ * This program is distributed in the hope that it will be useful,
27378+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27379+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27380+ * GNU General Public License for more details.
27381+ *
27382+ * You should have received a copy of the GNU General Public License
27383+ * along with this program; if not, write to the Free Software
27384+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27385+ */
27386+
27387+/*
27388+ * workqueue for asynchronous/super-io/delegated operations
27389+ *
27390+ * $Id$
27391+ */
27392+
27393+#include <linux/module.h>
27394+#include "aufs.h"
27395+
27396+struct au_wkq *au_wkq;
27397+
94750128 27398+
024a5822
JR
27399+
27400+struct au_wkinfo {
27401+ struct work_struct wk;
27402+ struct super_block *sb;
27403+
27404+ unsigned int flags;
94750128 27405+ struct cred cred;
024a5822
JR
27406+
27407+ au_wkq_func_t func;
27408+ void *args;
27409+
27410+ atomic_t *busyp;
27411+ struct completion *comp;
27412+};
27413+
27414+/* ---------------------------------------------------------------------- */
27415+
27416+#ifdef CONFIG_AUFS_DLGT
94750128 27417+static void cred_store(struct cred *cred)
024a5822 27418+{
94750128 27419+ cred = get_current_cred();
024a5822
JR
27420+}
27421+
94750128 27422+static void cred_revert(struct cred *cred)
024a5822
JR
27423+{
27424+ AuDebugOn(!au_test_wkq(current));
94750128 27425+ revert_creds(cred);
024a5822
JR
27426+}
27427+
94750128 27428+static void cred_switch(struct cred *old, struct cred *new)
024a5822
JR
27429+{
27430+ cred_store(old);
27431+ cred_revert(new);
27432+}
27433+
27434+static void dlgt_cred_store(unsigned int flags, struct au_wkinfo *wkinfo)
27435+{
27436+ if (au_ftest_wkq(flags, DLGT))
27437+ cred_store(&wkinfo->cred);
27438+}
27439+
27440+static void dlgt_func(struct au_wkinfo *wkinfo)
27441+{
27442+ if (!au_ftest_wkq(wkinfo->flags, DLGT))
27443+ wkinfo->func(wkinfo->args);
27444+ else {
94750128 27445+ struct cred cred;
024a5822
JR
27446+ cred_switch(&cred, &wkinfo->cred);
27447+ wkinfo->func(wkinfo->args);
27448+ cred_revert(&cred);
27449+ }
27450+}
27451+#else
27452+static void dlgt_cred_store(unsigned int flags, struct au_wkinfo *wkinfo)
27453+{
27454+ /* empty */
27455+}
27456+
27457+static void dlgt_func(struct au_wkinfo *wkinfo)
27458+{
27459+ wkinfo->func(wkinfo->args);
27460+}
27461+#endif /* CONFIG_AUFS_DLGT */
27462+
27463+/* ---------------------------------------------------------------------- */
27464+
27465+static void update_busy(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
27466+{
27467+#ifdef CONFIG_AUFS_STAT
27468+ unsigned int new, old;
27469+
27470+ do {
27471+ new = atomic_read(wkinfo->busyp);
27472+ old = wkq->max_busy;
27473+ if (new <= old)
27474+ break;
27475+ } while (cmpxchg(&wkq->max_busy, old, new) == old);
27476+#endif
27477+}
27478+
27479+static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
27480+{
27481+ AuTraceEnter();
27482+
27483+ wkinfo->busyp = &wkq->busy;
27484+ update_busy(wkq, wkinfo);
27485+ if (au_ftest_wkq(wkinfo->flags, WAIT))
27486+ return !queue_work(wkq->q, &wkinfo->wk);
27487+ else
27488+ return !schedule_work(&wkinfo->wk);
27489+}
27490+
27491+static void do_wkq(struct au_wkinfo *wkinfo)
27492+{
27493+ unsigned int idle, n;
27494+ int i, idle_idx;
27495+
27496+ AuTraceEnter();
27497+
27498+ while (1) {
27499+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
27500+ idle_idx = 0;
27501+ idle = UINT_MAX;
27502+ for (i = 0; i < aufs_nwkq; i++) {
27503+ n = atomic_inc_return(&au_wkq[i].busy);
27504+ if (n == 1 && !enqueue(au_wkq + i, wkinfo))
27505+ return; /* success */
27506+
27507+ if (n < idle) {
27508+ idle_idx = i;
27509+ idle = n;
27510+ }
27511+ atomic_dec_return(&au_wkq[i].busy);
27512+ }
27513+ } else
27514+ idle_idx = aufs_nwkq;
27515+
27516+ atomic_inc_return(&au_wkq[idle_idx].busy);
27517+ if (!enqueue(au_wkq + idle_idx, wkinfo))
27518+ return; /* success */
27519+
27520+ /* impossible? */
27521+ AuWarn1("failed to queue_work()\n");
27522+ yield();
27523+ }
27524+}
27525+
27526+static void wkq_func(struct work_struct *wk)
27527+{
27528+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
27529+
27530+ LKTRTrace("wkinfo{0x%x, %p, %p, %p}\n",
27531+ wkinfo->flags, wkinfo->func, wkinfo->busyp, wkinfo->comp);
27532+
27533+ dlgt_func(wkinfo);
27534+ atomic_dec_return(wkinfo->busyp);
27535+ if (au_ftest_wkq(wkinfo->flags, WAIT))
27536+ complete(wkinfo->comp);
27537+ else {
27538+ kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
27539+ module_put(THIS_MODULE);
27540+ kfree(wkinfo);
27541+ }
27542+}
27543+
27544+#if defined(CONFIG_4KSTACKS) || defined(Test4KSTACKS)
27545+#define AuWkqCompDeclare(name) struct completion *comp = NULL
27546+
27547+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
27548+{
27549+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
27550+ if (*comp) {
27551+ init_completion(*comp);
27552+ wkinfo->comp = *comp;
27553+ return 0;
27554+ }
27555+ return -ENOMEM;
27556+}
27557+
27558+static void au_wkq_comp_free(struct completion *comp)
27559+{
27560+ kfree(comp);
27561+}
27562+
27563+#else
27564+
27565+/* no braces */
27566+#define AuWkqCompDeclare(name) \
27567+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
27568+ struct completion *comp = &_ ## name
27569+
27570+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
27571+{
27572+ wkinfo->comp = *comp;
27573+ return 0;
27574+}
27575+
27576+static void au_wkq_comp_free(struct completion *comp)
27577+{
27578+ /* empty */
27579+}
27580+#endif /* 4KSTACKS */
27581+
27582+static void au_wkq_run(struct au_wkinfo *wkinfo)
27583+{
27584+#if 1 /* tmp debug */
27585+ if (au_test_wkq(current))
27586+ au_dbg_blocked();
27587+#endif
27588+ AuDebugOn(au_test_wkq(current));
27589+
27590+ INIT_WORK(&wkinfo->wk, wkq_func);
27591+ dlgt_cred_store(wkinfo->flags, wkinfo);
27592+ do_wkq(wkinfo);
27593+}
27594+
27595+int au_wkq_wait(au_wkq_func_t func, void *args, int dlgt)
27596+{
27597+ int err;
27598+ AuWkqCompDeclare(comp);
27599+ struct au_wkinfo wkinfo = {
27600+ .flags = AuWkq_WAIT,
27601+ .func = func,
27602+ .args = args
27603+ };
27604+
27605+ LKTRTrace("dlgt %d\n", dlgt);
27606+
27607+ err = au_wkq_comp_alloc(&wkinfo, &comp);
27608+ if (!err) {
27609+ if (dlgt)
27610+ au_fset_wkq(wkinfo.flags, DLGT);
27611+ au_wkq_run(&wkinfo);
27612+ /* no timeout, no interrupt */
27613+ wait_for_completion(wkinfo.comp);
27614+ au_wkq_comp_free(comp);
27615+ }
27616+
27617+ AuTraceErr(err);
27618+ return err;
27619+
27620+}
27621+
27622+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
27623+ int dlgt)
27624+{
27625+ int err;
27626+ struct au_wkinfo *wkinfo;
27627+
27628+ LKTRTrace("dlgt %d\n", dlgt);
27629+ AuDebugOn(!sb);
27630+
27631+ atomic_inc_return(&au_sbi(sb)->si_nowait.nw_len);
27632+
27633+ /*
27634+ * wkq_func() must free this wkinfo.
27635+ * it highly depends upon the implementation of workqueue.
27636+ */
27637+ err = 0;
27638+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
27639+ if (wkinfo) {
27640+ wkinfo->sb = sb;
27641+ wkinfo->flags = !AuWkq_WAIT;
27642+ wkinfo->func = func;
27643+ wkinfo->args = args;
27644+ wkinfo->comp = NULL;
27645+ if (dlgt)
27646+ au_fset_wkq(wkinfo->flags, DLGT);
27647+ kobject_get(&au_sbi(sb)->si_kobj);
27648+ __module_get(THIS_MODULE);
27649+
27650+ au_wkq_run(wkinfo);
27651+ } else {
27652+ err = -ENOMEM;
27653+ atomic_dec_return(&au_sbi(sb)->si_nowait.nw_len);
27654+ }
27655+
27656+ AuTraceErr(err);
27657+ return err;
27658+}
27659+
27660+/* ---------------------------------------------------------------------- */
27661+
27662+void au_wkq_fin(void)
27663+{
27664+ int i;
27665+
27666+ AuTraceEnter();
27667+
27668+ for (i = 0; i < aufs_nwkq; i++)
27669+ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
27670+ destroy_workqueue(au_wkq[i].q);
27671+ kfree(au_wkq);
27672+}
27673+
27674+int __init au_wkq_init(void)
27675+{
27676+ int err, i;
27677+ struct au_wkq *nowaitq;
27678+
27679+ LKTRTrace("%d\n", aufs_nwkq);
27680+
27681+ /* '+1' is for accounting of nowait queue */
27682+ err = -ENOMEM;
27683+ au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_NOFS);
27684+ if (unlikely(!au_wkq))
27685+ goto out;
27686+
27687+ err = 0;
27688+ for (i = 0; i < aufs_nwkq; i++) {
27689+ au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
27690+ if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
27691+ atomic_set(&au_wkq[i].busy, 0);
27692+ au_wkq_max_busy_init(au_wkq + i);
27693+ continue;
27694+ }
27695+
27696+ err = PTR_ERR(au_wkq[i].q);
27697+ au_wkq_fin();
27698+ break;
27699+ }
27700+
27701+ /* nowait accounting */
27702+ nowaitq = au_wkq + aufs_nwkq;
27703+ atomic_set(&nowaitq->busy, 0);
27704+ au_wkq_max_busy_init(nowaitq);
27705+ nowaitq->q = NULL;
27706+ /* smp_mb(); */ /* atomic_set */
27707+
27708+ out:
27709+ AuTraceErr(err);
27710+ return err;
27711+}
27712diff -urN linux/fs/aufs/wkq.h linux-aufs/fs/aufs/wkq.h
27713--- linux/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
27714+++ linux-aufs/fs/aufs/wkq.h 2009-03-12 16:18:04.000000000 +0100
27715@@ -0,0 +1,128 @@
27716+/*
27717+ * Copyright (C) 2005-2009 Junjiro Okajima
27718+ *
27719+ * This program, aufs is free software; you can redistribute it and/or modify
27720+ * it under the terms of the GNU General Public License as published by
27721+ * the Free Software Foundation; either version 2 of the License, or
27722+ * (at your option) any later version.
27723+ *
27724+ * This program is distributed in the hope that it will be useful,
27725+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27726+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27727+ * GNU General Public License for more details.
27728+ *
27729+ * You should have received a copy of the GNU General Public License
27730+ * along with this program; if not, write to the Free Software
27731+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27732+ */
27733+
27734+/*
27735+ * workqueue for asynchronous/super-io/delegated operations
27736+ *
27737+ * $Id$
27738+ */
27739+
27740+#ifndef __AUFS_WKQ_H__
27741+#define __AUFS_WKQ_H__
27742+
27743+#ifdef __KERNEL__
27744+
27745+#include <linux/fs.h>
27746+#include <linux/sched.h>
27747+#include <linux/workqueue.h>
27748+#include <linux/aufs_type.h>
27749+
27750+/* ---------------------------------------------------------------------- */
27751+
27752+/* internal workqueue named AUFS_WKQ_NAME */
27753+struct au_wkq {
27754+ struct workqueue_struct *q;
27755+
27756+ /* balancing */
27757+ atomic_t busy;
27758+
27759+ /* accounting */
27760+#ifdef CONFIG_AUFS_STAT
27761+ unsigned int max_busy;
27762+#endif
27763+};
27764+
27765+/*
27766+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
27767+ */
27768+struct au_nowait_tasks {
27769+ atomic_t nw_len;
27770+ wait_queue_head_t nw_wq;
27771+};
27772+
27773+/* ---------------------------------------------------------------------- */
27774+
27775+extern struct au_wkq *au_wkq;
27776+typedef void (*au_wkq_func_t)(void *args);
27777+
27778+/* wkq flags */
27779+#define AuWkq_WAIT 1
27780+#define AuWkq_DLGT (1 << 1)
27781+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
27782+#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
27783+#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
27784+#ifndef CONFIG_AUFS_DLGT
27785+#undef AuWkq_DLGT
27786+#define AuWkq_DLGT 0
27787+#endif
27788+
27789+int au_wkq_wait(au_wkq_func_t func, void *args, int dlgt);
27790+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
27791+ int dlgt);
27792+int __init au_wkq_init(void);
27793+void au_wkq_fin(void);
27794+
27795+/* ---------------------------------------------------------------------- */
27796+
27797+static inline int au_test_nowait_wkq(struct task_struct *tsk)
27798+{
27799+ static const char *p = "events";
27800+ return !tsk->mm && !strncmp(tsk->comm, p, strlen(p));
27801+}
27802+
27803+static inline int au_test_wkq(struct task_struct *tsk)
27804+{
27805+ return !tsk->mm && !strcmp(tsk->comm, AUFS_WKQ_NAME);
27806+#if 0 /* reserved for future use, per-cpu workqueue */
27807+ return !tsk->mm
27808+ && !memcmp(tsk->comm, AUFS_WKQ_NAME "/",
27809+ sizeof(AUFS_WKQ_NAME));
27810+#endif
27811+}
27812+
27813+static inline void au_wkq_max_busy_init(struct au_wkq *wkq)
27814+{
27815+#ifdef CONFIG_AUFS_STAT
27816+ wkq->max_busy = 0;
27817+#endif
27818+}
27819+
27820+/* todo: memory barrier? */
27821+static inline void au_nwt_init(struct au_nowait_tasks *nwt)
27822+{
27823+ atomic_set(&nwt->nw_len, 0);
27824+ smp_mb(); /* atomic_set */
27825+ init_waitqueue_head(&nwt->nw_wq);
27826+}
27827+
27828+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
27829+{
27830+ AuTraceEnter();
27831+
27832+ if (!atomic_dec_return(&nwt->nw_len))
27833+ wake_up_all(&nwt->nw_wq);
27834+}
27835+
27836+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
27837+{
27838+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
27839+ return 0;
27840+}
27841+
27842+#endif /* __KERNEL__ */
27843+#endif /* __AUFS_WKQ_H__ */
27844diff -urN linux/fs/aufs/xino.c linux-aufs/fs/aufs/xino.c
27845--- linux/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
27846+++ linux-aufs/fs/aufs/xino.c 2009-03-12 16:18:04.000000000 +0100
27847@@ -0,0 +1,1268 @@
27848+/*
27849+ * Copyright (C) 2005-2009 Junjiro Okajima
27850+ *
27851+ * This program, aufs is free software; you can redistribute it and/or modify
27852+ * it under the terms of the GNU General Public License as published by
27853+ * the Free Software Foundation; either version 2 of the License, or
27854+ * (at your option) any later version.
27855+ *
27856+ * This program is distributed in the hope that it will be useful,
27857+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27858+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27859+ * GNU General Public License for more details.
27860+ *
27861+ * You should have received a copy of the GNU General Public License
27862+ * along with this program; if not, write to the Free Software
27863+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27864+ */
27865+
27866+/*
27867+ * external inode number translation table and bitmap
27868+ *
27869+ * $Id$
27870+ */
27871+
27872+#include <linux/uaccess.h>
27873+#include "aufs.h"
27874+
27875+/* ---------------------------------------------------------------------- */
27876+
27877+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
27878+ loff_t *pos)
27879+{
27880+ ssize_t err;
27881+ mm_segment_t oldfs;
27882+
27883+ LKTRTrace("%.*s, sz %zu, *pos %lld\n",
27884+ AuDLNPair(file->f_dentry), size, *pos);
27885+
27886+ oldfs = get_fs();
27887+ set_fs(KERNEL_DS);
27888+ do {
27889+ /* todo: signal_pending? */
27890+ err = func(file, (char __user *)buf, size, pos);
27891+ } while (err == -EAGAIN || err == -EINTR);
27892+ set_fs(oldfs);
27893+
27894+#if 0 /* reserved for future use */
27895+ if (err > 0)
27896+ fsnotify_access(file->f_dentry);
27897+#endif
27898+
27899+ AuTraceErr(err);
27900+ return err;
27901+}
27902+
27903+/* ---------------------------------------------------------------------- */
27904+
27905+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
27906+ size_t size, loff_t *pos)
27907+{
27908+ ssize_t err;
27909+ mm_segment_t oldfs;
27910+
27911+ lockdep_off();
27912+ oldfs = get_fs();
27913+ set_fs(KERNEL_DS);
27914+ do {
27915+ /* todo: signal_pending? */
27916+ err = func(file, (const char __user *)buf, size, pos);
27917+ } while (err == -EAGAIN || err == -EINTR);
27918+ set_fs(oldfs);
27919+ lockdep_on();
27920+
27921+ if (err >= 0)
27922+ au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
27923+ /*ignore*/
27924+
27925+#if 0 /* reserved for future use */
27926+ if (err > 0)
27927+ fsnotify_modify(file->f_dentry);
27928+#endif
27929+
27930+ AuTraceErr(err);
27931+ return err;
27932+}
27933+
27934+struct do_xino_fwrite_args {
27935+ ssize_t *errp;
27936+ au_writef_t func;
27937+ struct file *file;
27938+ void *buf;
27939+ size_t size;
27940+ loff_t *pos;
27941+};
27942+
27943+static void call_do_xino_fwrite(void *args)
27944+{
27945+ struct do_xino_fwrite_args *a = args;
27946+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
27947+}
27948+
27949+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
27950+ loff_t *pos)
27951+{
27952+ ssize_t err;
27953+
27954+ LKTRTrace("%.*s, sz %zu, *pos %lld\n",
27955+ AuDLNPair(file->f_dentry), size, *pos);
27956+
27957+ /* todo: signal block and no wkq? */
27958+ /*
27959+ * it breaks RLIMIT_FSIZE and normal user's limit,
27960+ * users should care about quota and real 'filesystem full.'
27961+ */
27962+ if (!au_test_wkq(current)) {
27963+ int wkq_err;
27964+ struct do_xino_fwrite_args args = {
27965+ .errp = &err,
27966+ .func = func,
27967+ .file = file,
27968+ .buf = buf,
27969+ .size = size,
27970+ .pos = pos
27971+ };
27972+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args, /*dlgt*/0);
27973+ if (unlikely(wkq_err))
27974+ err = wkq_err;
27975+ } else
27976+ err = do_xino_fwrite(func, file, buf, size, pos);
27977+
27978+ AuTraceErr(err);
27979+ return err;
27980+}
27981+
27982+/* ---------------------------------------------------------------------- */
27983+
27984+struct xino_do_trunc_args {
27985+ struct super_block *sb;
27986+ struct au_branch *br;
27987+};
27988+
27989+static void xino_do_trunc(void *_args)
27990+{
27991+ struct xino_do_trunc_args *args = _args;
27992+ struct super_block *sb;
27993+ aufs_bindex_t bindex;
27994+ int err;
27995+ struct file *file;
27996+ struct inode *dir;
27997+ struct au_sbinfo *sbinfo;
27998+
27999+ err = 0;
28000+ sb = args->sb;
28001+ dir = sb->s_root->d_inode;
28002+ si_noflush_write_lock(sb);
28003+ ii_read_lock_parent(dir);
28004+ bindex = au_br_index(sb, args->br->br_id);
28005+ AuDebugOn(bindex < 0);
28006+ err = au_xino_trunc(sb, bindex);
28007+ if (unlikely(err))
28008+ goto out;
28009+
28010+ file = args->br->br_xino.xi_file;
28011+ au_update_fuse_h_inode(args->br->br_mnt, file->f_dentry); /*ignore*/
28012+ if (file->f_dentry->d_inode->i_blocks >= args->br->br_xino_upper)
28013+ args->br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
28014+
28015+ out:
28016+ ii_read_unlock(dir);
28017+ if (unlikely(err))
28018+ AuWarn("err b%d, (%d)\n", bindex, err);
28019+ atomic_dec_return(&args->br->br_xino_running);
28020+ au_br_put(args->br);
28021+ sbinfo = au_sbi(sb);
28022+ au_nwt_done(&sbinfo->si_nowait);
28023+ si_write_unlock(sb);
28024+ kfree(args);
28025+}
28026+
28027+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
28028+{
28029+ struct xino_do_trunc_args *args;
28030+ struct au_sbinfo *sbinfo;
28031+ struct file *file = br->br_xino.xi_file;
28032+ int wkq_err;
28033+
28034+ au_update_fuse_h_inode(br->br_mnt, file->f_dentry); /*ignore*/
28035+ if (file->f_dentry->d_inode->i_blocks < br->br_xino_upper)
28036+ return;
28037+ if (atomic_inc_return(&br->br_xino_running) > 1)
28038+ goto out;
28039+
28040+ /* lock and kfree() will be called in trunc_xino() */
28041+ args = kmalloc(sizeof(*args), GFP_NOFS);
28042+ if (unlikely(!args)) {
28043+ AuErr1("no memory\n");
28044+ goto out_args;
28045+ }
28046+
28047+ sbinfo = au_sbi(sb);
28048+ au_br_get(br);
28049+ args->sb = sb;
28050+ args->br = br;
28051+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*dlgt*/0);
28052+ if (!wkq_err)
28053+ return; /* success */
28054+
28055+ AuErr("wkq %d\n", wkq_err);
28056+ au_br_put(br);
28057+
28058+ out_args:
28059+ kfree(args);
28060+ out:
28061+ atomic_dec_return(&br->br_xino_running);
28062+}
28063+
28064+/* ---------------------------------------------------------------------- */
28065+
28066+static int au_xino_do_write(au_writef_t write, struct file *file,
28067+ ino_t h_ino, struct au_xino_entry *xinoe)
28068+{
28069+ loff_t pos;
28070+ ssize_t sz;
28071+
28072+ AuTraceEnter();
28073+
28074+ pos = h_ino;
28075+ if (unlikely(Au_LOFF_MAX / sizeof(*xinoe) - 1 < pos)) {
28076+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
28077+ return -EFBIG;
28078+ }
28079+ pos *= sizeof(*xinoe);
28080+ sz = xino_fwrite(write, file, xinoe, sizeof(*xinoe), &pos);
28081+ if (sz == sizeof(*xinoe))
28082+ return 0; /* success */
28083+
28084+ AuIOErr("write failed (%zd)\n", sz);
28085+ return -EIO;
28086+}
28087+
28088+/*
28089+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
28090+ * at the position of @_ino.
28091+ * when @ino is zero, it is written to the xinofile and means no entry.
28092+ */
28093+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
28094+ struct au_xino_entry *xinoe)
28095+{
28096+ int err;
28097+ struct file *file;
28098+ struct au_branch *br;
28099+ unsigned int mnt_flags;
28100+
28101+ LKTRTrace("b%d, hi%lu, i%lu\n",
28102+ bindex, (unsigned long)h_ino, (unsigned long)xinoe->ino);
28103+ BUILD_BUG_ON(sizeof(long long) != sizeof(Au_LOFF_MAX)
28104+ || ((loff_t)-1) > 0);
28105+
28106+ mnt_flags = au_mntflags(sb);
28107+ if (!au_opt_test_xino(mnt_flags))
28108+ return 0;
28109+
28110+ br = au_sbr(sb, bindex);
28111+ file = br->br_xino.xi_file;
28112+ AuDebugOn(!file);
28113+
28114+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, h_ino, xinoe);
28115+ if (!err) {
28116+ if (au_opt_test(mnt_flags, TRUNC_XINO)
28117+ && au_test_trunc_xino(br->br_mnt->mnt_sb))
28118+ xino_try_trunc(sb, br);
28119+ return 0; /* success */
28120+ }
28121+
28122+ AuIOErr("write failed (%d)\n", err);
28123+ return -EIO;
28124+}
28125+
28126+/* ---------------------------------------------------------------------- */
28127+
28128+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
28129+static ino_t xib_calc_ino(unsigned long pindex, int bit)
28130+{
28131+ ino_t ino;
28132+
28133+ AuDebugOn(bit < 0 || page_bits <= bit);
28134+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
28135+ return ino;
28136+}
28137+
28138+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
28139+{
28140+ AuDebugOn(ino < AUFS_FIRST_INO);
28141+ ino -= AUFS_FIRST_INO;
28142+ *pindex = ino / page_bits;
28143+ *bit = ino % page_bits;
28144+}
28145+
28146+static int xib_pindex(struct super_block *sb, unsigned long pindex)
28147+{
28148+ int err;
28149+ struct au_sbinfo *sbinfo;
28150+ loff_t pos;
28151+ ssize_t sz;
28152+ struct file *xib;
28153+ unsigned long *p;
28154+
28155+ LKTRTrace("pindex %lu\n", pindex);
28156+ sbinfo = au_sbi(sb);
28157+ MtxMustLock(&sbinfo->si_xib_mtx);
28158+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
28159+ || !au_opt_test_xino(sbinfo->si_mntflags));
28160+
28161+ if (pindex == sbinfo->si_xib_last_pindex)
28162+ return 0;
28163+
28164+ xib = sbinfo->si_xib;
28165+ p = sbinfo->si_xib_buf;
28166+ pos = sbinfo->si_xib_last_pindex;
28167+ pos *= PAGE_SIZE;
28168+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
28169+ if (unlikely(sz != PAGE_SIZE))
28170+ goto out;
28171+
28172+ pos = pindex;
28173+ pos *= PAGE_SIZE;
28174+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
28175+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
28176+ else {
28177+ memset(p, 0, PAGE_SIZE);
28178+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
28179+ }
28180+ if (sz == PAGE_SIZE) {
28181+ sbinfo->si_xib_last_pindex = pindex;
28182+ return 0; /* success */
28183+ }
28184+
28185+ out:
28186+ AuIOErr1("write failed (%zd)\n", sz);
28187+ err = sz;
28188+ if (sz >= 0)
28189+ err = -EIO;
28190+ AuTraceErr(err);
28191+ return err;
28192+}
28193+
28194+/* ---------------------------------------------------------------------- */
28195+
28196+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
28197+ ino_t ino)
28198+{
28199+ int err, bit;
28200+ unsigned long pindex;
28201+ struct au_sbinfo *sbinfo;
28202+ struct au_xino_entry xinoe = {
28203+ .ino = 0
28204+ };
28205+
28206+ LKTRTrace("b%d, hi%lu, i%lu\n",
28207+ bindex, (unsigned long)h_ino, (unsigned long)ino);
28208+
28209+ if (!au_opt_test_xino(au_mntflags(sb)))
28210+ return 0;
28211+
28212+ err = 0;
28213+ sbinfo = au_sbi(sb);
28214+ if (ino) {
28215+ AuDebugOn(ino < AUFS_FIRST_INO);
28216+ xib_calc_bit(ino, &pindex, &bit);
28217+ AuDebugOn(page_bits <= bit);
28218+ mutex_lock(&sbinfo->si_xib_mtx);
28219+ err = xib_pindex(sb, pindex);
28220+ if (!err) {
28221+ clear_bit(bit, sbinfo->si_xib_buf);
28222+ sbinfo->si_xib_next_bit = bit;
28223+ }
28224+ mutex_unlock(&sbinfo->si_xib_mtx);
28225+ }
28226+
28227+ if (!err)
28228+ err = au_xino_write(sb, bindex, h_ino, &xinoe);
28229+ return err;
28230+}
28231+
28232+ino_t au_xino_new_ino(struct super_block *sb)
28233+{
28234+ ino_t ino;
28235+ struct au_sbinfo *sbinfo;
28236+ int free_bit, err;
28237+ unsigned long *p, pindex, ul, pend;
28238+ struct file *file;
28239+
28240+ AuTraceEnter();
28241+
28242+ if (!au_opt_test_xino(au_mntflags(sb)))
28243+ return iunique(sb, AUFS_FIRST_INO);
28244+
28245+ sbinfo = au_sbi(sb);
28246+ mutex_lock(&sbinfo->si_xib_mtx);
28247+ p = sbinfo->si_xib_buf;
28248+ free_bit = sbinfo->si_xib_next_bit;
28249+ if (free_bit < page_bits && !test_bit(free_bit, p))
28250+ goto out; /* success */
28251+ free_bit = find_first_zero_bit(p, page_bits);
28252+ if (free_bit < page_bits)
28253+ goto out; /* success */
28254+
28255+ pindex = sbinfo->si_xib_last_pindex;
28256+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
28257+ err = xib_pindex(sb, ul);
28258+ if (unlikely(err))
28259+ goto out_err;
28260+ free_bit = find_first_zero_bit(p, page_bits);
28261+ if (free_bit < page_bits)
28262+ goto out; /* success */
28263+ }
28264+
28265+ file = sbinfo->si_xib;
28266+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
28267+ for (ul = pindex + 1; ul <= pend; 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+ BUG();
28276+
28277+ out:
28278+ set_bit(free_bit, p);
28279+ sbinfo->si_xib_next_bit++;
28280+ pindex = sbinfo->si_xib_last_pindex;
28281+ mutex_unlock(&sbinfo->si_xib_mtx);
28282+ ino = xib_calc_ino(pindex, free_bit);
28283+ LKTRTrace("i%lu\n", (unsigned long)ino);
28284+ return ino;
28285+ out_err:
28286+ mutex_unlock(&sbinfo->si_xib_mtx);
28287+ LKTRTrace("i0\n");
28288+ return 0;
28289+}
28290+
28291+/*
28292+ * read @ino from xinofile for the specified branch{@sb, @bindex}
28293+ * at the position of @h_ino.
28294+ * if @ino does not exist and @do_new is true, get new one.
28295+ */
28296+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
28297+ struct au_xino_entry *xinoe)
28298+{
28299+ int err;
28300+ struct file *file;
28301+ loff_t pos;
28302+ ssize_t sz;
28303+ struct au_sbinfo *sbinfo;
28304+
28305+ LKTRTrace("b%d, hi%lu\n", bindex, (unsigned long)h_ino);
28306+
28307+ xinoe->ino = 0;
28308+ if (!au_opt_test_xino(au_mntflags(sb)))
28309+ return 0; /* no ino */
28310+
28311+ err = 0;
28312+ sbinfo = au_sbi(sb);
28313+ pos = h_ino;
28314+ if (unlikely(Au_LOFF_MAX / sizeof(*xinoe) - 1 < pos)) {
28315+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
28316+ return -EFBIG;
28317+ }
28318+ pos *= sizeof(*xinoe);
28319+
28320+ file = au_sbr(sb, bindex)->br_xino.xi_file;
28321+ AuDebugOn(!file);
28322+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*xinoe))
28323+ return 0; /* no ino */
28324+
28325+ sz = xino_fread(sbinfo->si_xread, file, xinoe, sizeof(*xinoe), &pos);
28326+ if (sz == sizeof(*xinoe))
28327+ return 0; /* success */
28328+
28329+ err = sz;
28330+ if (unlikely(sz >= 0)) {
28331+ err = -EIO;
28332+ AuIOErr("xino read error (%zd)\n", sz);
28333+ }
28334+
28335+ AuTraceErr(err);
28336+ return err;
28337+}
28338+
28339+/* ---------------------------------------------------------------------- */
28340+
28341+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
28342+{
28343+ struct file *file;
28344+ int err;
28345+ struct dentry *h_parent;
28346+ struct inode *h_dir;
28347+ struct vfsub_args vargs;
28348+
28349+ LKTRTrace("%s\n", fname);
28350+
28351+ /*
28352+ * at mount-time, and the xino file is the default path,
28353+ * hinotify is disabled so we have no inotify events to ignore.
28354+ * when a user specified the xino, we cannot get au_hdir to be ignored.
28355+ */
28356+ vfsub_args_init(&vargs, /*ign*/NULL, /*dlgt*/0, 0);
28357+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
28358+ S_IRUGO | S_IWUGO);
28359+ if (IS_ERR(file)) {
28360+ if (!silent)
28361+ AuErr("open %s(%ld)\n", fname, PTR_ERR(file));
28362+ return file;
28363+ }
28364+
28365+ /* keep file count */
28366+ h_parent = dget_parent(file->f_dentry);
28367+ h_dir = h_parent->d_inode;
28368+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
28369+ /* mnt_want_write() is unnecessary here */
28370+ err = vfsub_unlink(h_dir, file->f_dentry, &vargs);
28371+ mutex_unlock(&h_dir->i_mutex);
28372+ dput(h_parent);
28373+ if (unlikely(err)) {
28374+ if (!silent)
28375+ AuErr("unlink %s(%d)\n", fname, err);
28376+ goto out;
28377+ }
28378+
28379+ if (sb != file->f_dentry->d_sb)
28380+ return file; /* success */
28381+
28382+ if (!silent)
28383+ AuErr("%s must be outside\n", fname);
28384+ err = -EINVAL;
28385+
28386+ out:
28387+ fput(file);
28388+ file = ERR_PTR(err);
28389+ return file;
28390+}
28391+
28392+/*
28393+ * find another branch who is on the same filesystem of the specified
28394+ * branch{@btgt}. search until @bend.
28395+ */
28396+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
28397+ aufs_bindex_t bend)
28398+{
28399+ aufs_bindex_t bindex;
28400+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
28401+
28402+ for (bindex = 0; bindex < btgt; bindex++)
28403+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
28404+ return bindex;
28405+ for (bindex++; bindex <= bend; bindex++)
28406+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
28407+ return bindex;
28408+ return -1;
28409+}
28410+
28411+/*
28412+ * create a new xinofile at the same place/path as @base_file.
28413+ */
28414+struct file *au_xino_create2(struct super_block *sb, struct file *base_file,
28415+ struct file *copy_src)
28416+{
28417+ struct file *file;
28418+ int err;
28419+ struct dentry *base, *dentry, *parent;
28420+ struct inode *dir, *inode;
28421+ struct qstr *name;
28422+ struct au_hinode *hdir;
28423+ struct au_branch *br;
28424+ aufs_bindex_t bindex;
28425+ struct au_hin_ignore ign;
28426+ struct vfsub_args vargs;
28427+ struct au_ndx ndx = {
28428+ .nfsmnt = NULL,
28429+ .flags = 0,
28430+ .nd = NULL,
28431+ /* .br = NULL */
28432+ };
28433+
28434+ base = base_file->f_dentry;
28435+ LKTRTrace("%.*s\n", AuDLNPair(base));
28436+ parent = base->d_parent; /* dir inode is locked */
28437+ dir = parent->d_inode;
28438+ IMustLock(dir);
28439+
28440+ file = ERR_PTR(-EINVAL);
28441+ if (unlikely(au_test_nfs(parent->d_sb)
28442+ || au_test_ecryptfs(parent->d_sb)))
28443+ goto out;
28444+
28445+ /* do not superio, nor NFS. */
28446+ name = &base->d_name;
28447+ dentry = au_lkup_one(name->name, parent, name->len, &ndx);
28448+ if (IS_ERR(dentry)) {
28449+ file = (void *)dentry;
28450+ AuErr("%.*s lookup err %ld\n", AuLNPair(name), PTR_ERR(dentry));
28451+ goto out;
28452+ }
28453+
28454+ hdir = NULL;
28455+ br = au_xino_def_br(au_sbi(sb));
28456+ if (br) {
28457+ bindex = au_find_bindex(sb, br);
28458+ if (bindex >= 0)
28459+ hdir = au_hi(sb->s_root->d_inode, bindex);
28460+ }
28461+ vfsub_args_init(&vargs, &ign, 0, 0);
28462+ vfsub_ign_hinode(&vargs, IN_CREATE, hdir);
28463+ /* no need to mnt_want_write() since we call dentry_open() later */
28464+ err = vfsub_create(dir, dentry, S_IRUGO | S_IWUGO, NULL, &vargs);
28465+ if (unlikely(err)) {
28466+ file = ERR_PTR(err);
28467+ AuErr("%.*s create err %d\n", AuLNPair(name), err);
28468+ goto out_dput;
28469+ }
28470+ file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt),
94750128 28471+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE, base_file->f_cred);
024a5822
JR
28472+ if (IS_ERR(file)) {
28473+ AuErr("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
28474+ goto out_dput;
28475+ }
28476+ vfsub_args_reinit(&vargs);
28477+ vfsub_ign_hinode(&vargs, IN_DELETE, hdir);
28478+ err = vfsub_unlink(dir, dentry, &vargs);
28479+ if (unlikely(err)) {
28480+ AuErr("%.*s unlink err %d\n", AuLNPair(name), err);
28481+ goto out_fput;
28482+ }
28483+
28484+ if (copy_src) {
28485+ inode = copy_src->f_dentry->d_inode;
28486+ err = au_copy_file(file, copy_src, i_size_read(inode),
28487+ hdir, sb, &vargs);
28488+ if (unlikely(err)) {
28489+ AuErr("%.*s copy err %d\n", AuLNPair(name), err);
28490+ goto out_fput;
28491+ }
28492+ }
28493+ goto out_dput; /* success */
28494+
28495+ out_fput:
28496+ fput(file);
28497+ file = ERR_PTR(err);
28498+ out_dput:
28499+ dput(dentry);
28500+ out:
28501+ AuTraceErrPtr(file);
28502+ return file;
28503+}
28504+
28505+/* ---------------------------------------------------------------------- */
28506+
28507+/*
28508+ * initialize the xinofile for the specified branch{@sb, @bindex}
28509+ * at the place/path where @base_file indicates.
28510+ * test whether another branch is on the same filesystem or not,
28511+ * if @do_test is true.
28512+ */
28513+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
28514+ struct file *base_file, int do_test)
28515+{
28516+ int err;
28517+ struct au_branch *shared_br;
28518+ aufs_bindex_t bshared, bend, bindex;
28519+ unsigned char do_create;
28520+ struct inode *dir;
28521+ struct au_xino_entry xinoe;
28522+ struct dentry *parent;
28523+ struct file *file;
28524+ struct super_block *tgt_sb;
28525+
28526+ LKTRTrace("base_file %p, do_test %d\n", base_file, do_test);
28527+ SiMustWriteLock(sb);
28528+ AuDebugOn(!au_opt_test_xino(au_mntflags(sb)));
28529+ AuDebugOn(br->br_xino.xi_file);
28530+
28531+ do_create = 1;
28532+ bshared = -1;
28533+ shared_br = NULL;
28534+ bend = au_sbend(sb);
28535+ if (do_test) {
28536+ tgt_sb = br->br_mnt->mnt_sb;
28537+ for (bindex = 0; bindex <= bend; bindex++)
28538+ if (tgt_sb == au_sbr_sb(sb, bindex)) {
28539+ bshared = bindex;
28540+ break;
28541+ }
28542+ }
28543+ if (bshared >= 0) {
28544+ shared_br = au_sbr(sb, bshared);
28545+ do_create = !shared_br->br_xino.xi_file;
28546+ }
28547+
28548+ if (do_create) {
28549+ parent = dget_parent(base_file->f_dentry);
28550+ dir = parent->d_inode;
28551+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
28552+ /* mnt_want_write() is unnecessary here */
28553+ file = au_xino_create2(sb, base_file, NULL);
28554+ mutex_unlock(&dir->i_mutex);
28555+ dput(parent);
28556+ err = PTR_ERR(file);
28557+ if (IS_ERR(file))
28558+ goto out;
28559+ br->br_xino.xi_file = file;
28560+ } else {
28561+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
28562+ get_file(br->br_xino.xi_file);
28563+ }
28564+
28565+ xinoe.ino = AUFS_ROOT_INO;
28566+#if 0 /* reserved for future use */
28567+ xinoe.h_gen = h_inode->i_generation;
28568+ WARN_ON(xinoe.h_gen == AuXino_INVALID_HGEN);
28569+#endif
28570+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
28571+ h_ino, &xinoe);
28572+ if (!err)
28573+ return 0; /* success */
28574+
28575+
28576+ out:
28577+ AuTraceErr(err);
28578+ return err;
28579+}
28580+
28581+/* too slow */
28582+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
28583+{
28584+ int err, bit;
28585+ struct au_sbinfo *sbinfo;
28586+ au_readf_t func;
28587+ loff_t pos, pend;
28588+ ssize_t sz;
28589+ struct au_xino_entry *xinoe;
28590+ unsigned long pindex;
28591+
28592+ AuTraceEnter();
28593+ SiMustWriteLock(sb);
28594+
28595+ err = 0;
28596+ sbinfo = au_sbi(sb);
28597+ func = sbinfo->si_xread;
28598+ pend = i_size_read(file->f_dentry->d_inode);
28599+#ifdef CONFIG_AUFS_DEBUG
28600+ if (unlikely(pend > (1 << 22)))
28601+ AuWarn("testing a large xino file %lld\n", (long long)pend);
28602+#endif
28603+ pos = 0;
28604+ while (pos < pend) {
28605+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
28606+ err = sz;
28607+ if (unlikely(sz <= 0))
28608+ goto out;
28609+
28610+ err = 0;
28611+ for (xinoe = page; sz > 0; xinoe++, sz -= sizeof(xinoe)) {
28612+ if (unlikely(xinoe->ino < AUFS_FIRST_INO))
28613+ continue;
28614+
28615+ xib_calc_bit(xinoe->ino, &pindex, &bit);
28616+ AuDebugOn(page_bits <= bit);
28617+ err = xib_pindex(sb, pindex);
28618+ if (!err)
28619+ set_bit(bit, sbinfo->si_xib_buf);
28620+ else
28621+ goto out;
28622+ }
28623+ }
28624+
28625+ out:
28626+ AuTraceErr(err);
28627+ return err;
28628+}
28629+
28630+static int xib_restore(struct super_block *sb)
28631+{
28632+ int err;
28633+ aufs_bindex_t bindex, bend;
28634+ void *page;
28635+
28636+ AuTraceEnter();
28637+
28638+ err = -ENOMEM;
28639+ page = (void *)__get_free_page(GFP_NOFS);
28640+ if (unlikely(!page))
28641+ goto out;
28642+
28643+ err = 0;
28644+ bend = au_sbend(sb);
28645+ for (bindex = 0; !err && bindex <= bend; bindex++)
28646+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
28647+ err = do_xib_restore
28648+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
28649+ else
28650+ LKTRTrace("b%d\n", bindex);
28651+ free_page((unsigned long)page);
28652+
28653+ out:
28654+ AuTraceErr(err);
28655+ return err;
28656+}
28657+
28658+int au_xib_trunc(struct super_block *sb)
28659+{
28660+ int err;
28661+ unsigned int mnt_flags;
28662+ ssize_t sz;
28663+ loff_t pos;
28664+ struct au_sbinfo *sbinfo;
28665+ unsigned long *p;
28666+ struct dentry *parent;
28667+ struct inode *dir;
28668+ struct file *file;
28669+
28670+ AuTraceEnter();
28671+ SiMustWriteLock(sb);
28672+
28673+ err = 0;
28674+ mnt_flags = au_mntflags(sb);
28675+ if (!au_opt_test_xino(mnt_flags))
28676+ goto out;
28677+
28678+ sbinfo = au_sbi(sb);
28679+ if (i_size_read(sbinfo->si_xib->f_dentry->d_inode) <= PAGE_SIZE)
28680+ goto out;
28681+ parent = dget_parent(sbinfo->si_xib->f_dentry);
28682+ dir = parent->d_inode;
28683+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
28684+ /* mnt_want_write() is unnecessary here */
28685+ file = au_xino_create2(sb, sbinfo->si_xib, NULL);
28686+ mutex_unlock(&dir->i_mutex);
28687+ dput(parent);
28688+ err = PTR_ERR(file);
28689+ if (IS_ERR(file))
28690+ goto out;
28691+ fput(sbinfo->si_xib);
28692+ sbinfo->si_xib = file;
28693+
28694+ p = sbinfo->si_xib_buf;
28695+ memset(p, 0, PAGE_SIZE);
28696+ pos = 0;
28697+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
28698+ if (unlikely(sz != PAGE_SIZE)) {
28699+ err = sz;
28700+ AuIOErr("err %d\n", err);
28701+ if (sz >= 0)
28702+ err = -EIO;
28703+ goto out;
28704+ }
28705+
28706+ if (au_opt_test_xino(mnt_flags)) {
28707+ mutex_lock(&sbinfo->si_xib_mtx);
28708+ /* mnt_want_write() is unnecessary here */
28709+ err = xib_restore(sb);
28710+ mutex_unlock(&sbinfo->si_xib_mtx);
28711+#if 0 /* reserved for future use */
28712+ } else {
28713+ /* is it really safe? */
28714+ /* dont trust BKL */
28715+ AuDebugOn(!kernel_locked());
28716+ ino = AUFS_FIRST_INO;
28717+ list_for_each_entry(inode, &sb->s_inodes, i_sb_list)
28718+ if (ino < inode->i_ino)
28719+ ino = inode->i_ino;
28720+
28721+ /* make iunique to return larger than active max inode number */
28722+ iunique(sb, ino);
28723+ err = 0;
28724+#endif
28725+ }
28726+
28727+out:
28728+ AuTraceErr(err);
28729+ return err;
28730+}
28731+
28732+/* ---------------------------------------------------------------------- */
28733+
28734+/*
28735+ * xino mount option handlers
28736+ */
28737+static au_readf_t find_readf(struct file *h_file)
28738+{
28739+ const struct file_operations *fop = h_file->f_op;
28740+
28741+ if (fop) {
28742+ if (fop->read)
28743+ return fop->read;
28744+ if (fop->aio_read)
28745+ return do_sync_read;
28746+ }
28747+ return ERR_PTR(-ENOSYS);
28748+}
28749+
28750+static au_writef_t find_writef(struct file *h_file)
28751+{
28752+ const struct file_operations *fop = h_file->f_op;
28753+
28754+ if (fop) {
28755+ if (fop->write)
28756+ return fop->write;
28757+ if (fop->aio_write)
28758+ return do_sync_write;
28759+ }
28760+ return ERR_PTR(-ENOSYS);
28761+}
28762+
28763+/* xino bitmap */
28764+static void xino_clear_xib(struct super_block *sb)
28765+{
28766+ struct au_sbinfo *sbinfo;
28767+
28768+ AuTraceEnter();
28769+ SiMustWriteLock(sb);
28770+
28771+ sbinfo = au_sbi(sb);
28772+ sbinfo->si_xread = NULL;
28773+ sbinfo->si_xwrite = NULL;
28774+ if (sbinfo->si_xib)
28775+ fput(sbinfo->si_xib);
28776+ sbinfo->si_xib = NULL;
28777+ free_page((unsigned long)sbinfo->si_xib_buf);
28778+ sbinfo->si_xib_buf = NULL;
28779+}
28780+
28781+static int au_xino_set_xib(struct super_block *sb, struct file *base)
28782+{
28783+ int err;
28784+ struct au_sbinfo *sbinfo;
28785+ struct file *file;
28786+ loff_t pos;
28787+
28788+ LKTRTrace("%.*s\n", AuDLNPair(base->f_dentry));
28789+ SiMustWriteLock(sb);
28790+
28791+ sbinfo = au_sbi(sb);
28792+ file = au_xino_create2(sb, base, sbinfo->si_xib);
28793+ err = PTR_ERR(file);
28794+ if (IS_ERR(file))
28795+ goto out;
28796+ if (sbinfo->si_xib)
28797+ fput(sbinfo->si_xib);
28798+ sbinfo->si_xib = file;
28799+ sbinfo->si_xread = find_readf(file);
28800+ AuDebugOn(IS_ERR(sbinfo->si_xread));
28801+ sbinfo->si_xwrite = find_writef(file);
28802+ AuDebugOn(IS_ERR(sbinfo->si_xwrite));
28803+
28804+ err = -ENOMEM;
28805+ if (!sbinfo->si_xib_buf)
28806+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
28807+ if (unlikely(!sbinfo->si_xib_buf))
28808+ goto out_unset;
28809+
28810+ sbinfo->si_xib_last_pindex = 0;
28811+ sbinfo->si_xib_next_bit = 0;
28812+
28813+ /* no need to lock for i_size_read() */
28814+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
28815+ pos = 0;
28816+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
28817+ PAGE_SIZE, &pos);
28818+ if (unlikely(err != PAGE_SIZE))
28819+ goto out_free;
28820+ }
28821+ err = 0;
28822+ goto out; /* success */
28823+
28824+ out_free:
28825+ free_page((unsigned long)sbinfo->si_xib_buf);
28826+ sbinfo->si_xib_buf = NULL;
28827+ if (err >= 0)
28828+ err = -EIO;
28829+ out_unset:
28830+ fput(sbinfo->si_xib);
28831+ sbinfo->si_xib = NULL;
28832+ sbinfo->si_xread = NULL;
28833+ sbinfo->si_xwrite = NULL;
28834+ out:
28835+ AuTraceErr(err);
28836+ return err;
28837+}
28838+
28839+/* xino for each branch */
28840+static void xino_clear_br(struct super_block *sb)
28841+{
28842+ aufs_bindex_t bindex, bend;
28843+ struct au_branch *br;
28844+
28845+ AuTraceEnter();
28846+ SiMustWriteLock(sb);
28847+
28848+ bend = au_sbend(sb);
28849+ for (bindex = 0; bindex <= bend; bindex++) {
28850+ br = au_sbr(sb, bindex);
28851+ if (!br || !br->br_xino.xi_file)
28852+ continue;
28853+
28854+ fput(br->br_xino.xi_file);
28855+ br->br_xino.xi_file = NULL;
28856+ }
28857+}
28858+
28859+static int au_xino_set_br(struct super_block *sb, struct file *base)
28860+{
28861+ int err;
28862+ aufs_bindex_t bindex, bend, bshared;
28863+ struct {
28864+ struct file *old, *new;
28865+ } *fpair, *p;
28866+ struct au_branch *br;
28867+ struct au_xino_entry xinoe;
28868+ struct inode *inode;
28869+ au_writef_t writef;
28870+
28871+ LKTRTrace("%.*s\n", AuDLNPair(base->f_dentry));
28872+ SiMustWriteLock(sb);
28873+
28874+ err = -ENOMEM;
28875+ bend = au_sbend(sb);
28876+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
28877+ if (unlikely(!fpair))
28878+ goto out;
28879+
28880+ inode = sb->s_root->d_inode;
28881+ xinoe.ino = AUFS_ROOT_INO;
28882+ writef = au_sbi(sb)->si_xwrite;
28883+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
28884+ br = au_sbr(sb, bindex);
28885+ bshared = is_sb_shared(sb, bindex, bindex - 1);
28886+ if (bshared >= 0) {
28887+ /* shared xino */
28888+ *p = fpair[bshared];
28889+ get_file(p->new);
28890+ }
28891+
28892+ if (!p->new) {
28893+ /* new xino */
28894+ p->old = br->br_xino.xi_file;
28895+ p->new = au_xino_create2(sb, base, br->br_xino.xi_file);
28896+ err = PTR_ERR(p->new);
28897+ if (IS_ERR(p->new)) {
28898+ p->new = NULL;
28899+ goto out_pair;
28900+ }
28901+ }
28902+
28903+ err = au_xino_do_write(writef, p->new,
28904+ au_h_iptr(inode, bindex)->i_ino, &xinoe);
28905+ if (unlikely(err))
28906+ goto out_pair;
28907+ }
28908+
28909+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
28910+ br = au_sbr(sb, bindex);
28911+ AuDebugOn(p->old != br->br_xino.xi_file);
28912+ if (br->br_xino.xi_file)
28913+ fput(br->br_xino.xi_file);
28914+ get_file(p->new);
28915+ br->br_xino.xi_file = p->new;
28916+ }
28917+
28918+ out_pair:
28919+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
28920+ if (p->new)
28921+ fput(p->new);
28922+ else
28923+ break;
28924+ kfree(fpair);
28925+ out:
28926+ AuTraceErr(err);
28927+ return err;
28928+}
28929+
28930+void au_xino_clr(struct super_block *sb)
28931+{
28932+ struct au_sbinfo *sbinfo;
28933+
28934+ AuTraceEnter();
28935+ SiMustWriteLock(sb);
28936+
28937+ au_xigen_clr(sb);
28938+ xino_clear_xib(sb);
28939+ xino_clear_br(sb);
28940+ sbinfo = au_sbi(sb);
28941+ /* lvalue, do not call au_mntflags() */
28942+ au_opt_clr(sbinfo->si_mntflags, XINO);
28943+ au_xino_def_br_set(NULL, sbinfo);
28944+}
28945+
28946+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
28947+{
28948+ int err, skip;
28949+ struct dentry *parent, *cur_parent;
28950+ struct qstr *dname, *cur_name;
28951+ struct file *cur_xino;
28952+ struct inode *dir;
28953+ struct au_sbinfo *sbinfo;
28954+
28955+ LKTRTrace("remount %d\n", remount);
28956+ SiMustWriteLock(sb);
28957+
28958+ err = 0;
28959+ sbinfo = au_sbi(sb);
28960+ parent = dget_parent(xino->file->f_dentry);
28961+ if (remount) {
28962+ skip = 0;
28963+ dname = &xino->file->f_dentry->d_name;
28964+ cur_xino = sbinfo->si_xib;
28965+ if (cur_xino) {
28966+ cur_parent = dget_parent(cur_xino->f_dentry);
28967+ cur_name = &cur_xino->f_dentry->d_name;
28968+ skip = (cur_parent == parent
28969+ && dname->len == cur_name->len
28970+ && !memcmp(dname->name, cur_name->name,
28971+ dname->len));
28972+ dput(cur_parent);
28973+ }
28974+ if (skip)
28975+ goto out;
28976+ }
28977+
28978+ au_opt_set(sbinfo->si_mntflags, XINO);
28979+ au_xino_def_br_set(NULL, sbinfo);
28980+ dir = parent->d_inode;
28981+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
28982+ /* mnt_want_write() is unnecessary here */
28983+ err = au_xino_set_xib(sb, xino->file);
28984+ if (!err)
28985+ err = au_xigen_set(sb, xino->file);
28986+ if (!err)
28987+ err = au_xino_set_br(sb, xino->file);
28988+ mutex_unlock(&dir->i_mutex);
28989+ if (!err)
28990+ goto out; /* success */
28991+
28992+ /* reset all */
28993+ AuIOErr("failed creating xino(%d).\n", err);
28994+
28995+ out:
28996+ dput(parent);
28997+ AuTraceErr(err);
28998+ return err;
28999+}
29000+
29001+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
29002+{
29003+ int err;
29004+ struct au_branch *br;
29005+ struct file *new_xino;
29006+ struct super_block *h_sb;
29007+ aufs_bindex_t bi, bend;
29008+ struct dentry *parent;
29009+ struct inode *dir;
29010+
29011+ LKTRTrace("b%d\n", bindex);
29012+ SiMustWriteLock(sb);
29013+
29014+ err = -EINVAL;
29015+ bend = au_sbend(sb);
29016+ if (unlikely(bindex < 0 || bend < bindex))
29017+ goto out;
29018+ br = au_sbr(sb, bindex);
29019+ if (!br->br_xino.xi_file)
29020+ goto out;
29021+
29022+ parent = dget_parent(br->br_xino.xi_file->f_dentry);
29023+ dir = parent->d_inode;
29024+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
29025+ /* mnt_want_write() is unnecessary here */
29026+ new_xino = au_xino_create2(sb, br->br_xino.xi_file,
29027+ br->br_xino.xi_file);
29028+ mutex_unlock(&dir->i_mutex);
29029+ dput(parent);
29030+ err = PTR_ERR(new_xino);
29031+ if (IS_ERR(new_xino))
29032+ goto out;
29033+ err = 0;
29034+ fput(br->br_xino.xi_file);
29035+ br->br_xino.xi_file = new_xino;
29036+
29037+ h_sb = br->br_mnt->mnt_sb;
29038+ for (bi = 0; bi <= bend; bi++) {
29039+ if (unlikely(bi == bindex))
29040+ continue;
29041+ br = au_sbr(sb, bi);
29042+ if (br->br_mnt->mnt_sb != h_sb)
29043+ continue;
29044+
29045+ fput(br->br_xino.xi_file);
29046+ br->br_xino.xi_file = new_xino;
29047+ get_file(new_xino);
29048+ }
29049+
29050+ out:
29051+ AuTraceErr(err);
29052+ return err;
29053+}
29054+
29055+/* ---------------------------------------------------------------------- */
29056+
29057+/*
29058+ * create a xinofile at the default place/path.
29059+ */
29060+struct file *au_xino_def(struct super_block *sb)
29061+{
29062+ struct file *file;
29063+ aufs_bindex_t bend, bindex, bwr;
29064+ char *page, *p;
29065+ struct path path;
29066+ struct au_branch *br;
29067+
29068+ AuTraceEnter();
29069+
29070+ bend = au_sbend(sb);
29071+ bwr = -1;
29072+ for (bindex = 0; bindex <= bend; bindex++) {
29073+ br = au_sbr(sb, bindex);
29074+ if (au_br_writable(br->br_perm)
29075+ && !au_test_nfs(br->br_mnt->mnt_sb)
29076+ && !au_test_ecryptfs(br->br_mnt->mnt_sb)) {
29077+ bwr = bindex;
29078+ break;
29079+ }
29080+ }
29081+
29082+ if (bwr >= 0) {
29083+ file = ERR_PTR(-ENOMEM);
29084+ page = __getname();
29085+ if (unlikely(!page))
29086+ goto out;
29087+ path.mnt = au_sbr_mnt(sb, bwr);
29088+ path.dentry = au_h_dptr(sb->s_root, bwr);
29089+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
29090+ file = (void *)p;
29091+ if (!IS_ERR(p)) {
29092+ strcat(p, "/" AUFS_XINO_FNAME);
29093+ LKTRTrace("%s\n", p);
29094+ file = au_xino_create(sb, p, /*silent*/0);
29095+ if (!IS_ERR(file))
29096+ au_xino_def_br_set(au_sbr(sb, bwr), au_sbi(sb));
29097+ }
29098+ __putname(page);
29099+ } else {
29100+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
29101+ if (unlikely(au_test_nfs(file->f_dentry->d_sb)
29102+ || au_test_ecryptfs(file->f_dentry->d_sb))) {
29103+ AuErr("xino or noxino option is required "
29104+ "since %s is NFS\n", AUFS_XINO_DEFPATH);
29105+ fput(file);
29106+ file = ERR_PTR(-EINVAL);
29107+ }
29108+ if (!IS_ERR(file))
29109+ au_xino_def_br_set(NULL, au_sbi(sb));
29110+ }
29111+
29112+ out:
29113+ AuTraceErrPtr(file);
29114+ return file;
29115+}
29116diff -urN linux/fs/Kconfig linux-aufs/fs/Kconfig
29117--- linux/fs/Kconfig 2009-01-05 11:42:15.000000000 +0100
29118+++ linux-aufs/fs/Kconfig 2009-03-12 17:02:25.753047602 +0100
29119@@ -1022,6 +1022,350 @@
29120 help
29121 If you say Y here, you can turn on debugging output from Unionfs.
29122
29123+config AUFS
29124+ tristate "Another unionfs"
29125+ help
29126+ Aufs is a stackable unification filesystem such as Unionfs,
29127+ which unifies several directories and provides a merged single
29128+ directory.
29129+ In the early days, aufs was entirely re-designed and
29130+ re-implemented Unionfs Version 1.x series. After many original
29131+ ideas, approaches and improvements, it becomes totally
29132+ different from Unionfs while keeping the basic features.
29133+ See Unionfs for the basic features.
29134+
29135+if AUFS
29136+comment "These options are for "#UTS_RELEASE
29137+
29138+choice
29139+ prompt "Maximum number of branches"
29140+ default AUFS_BRANCH_MAX_127
29141+ help
29142+ Specifies the maximum number of branches (or member directories) in a
29143+ single aufs. The larger value consumes more system resources and has
29144+ an impact to performance.
29145+config AUFS_BRANCH_MAX_127
29146+ bool "127"
29147+ help
29148+ Specifies the maximum number of branches (or member directories) in a
29149+ single aufs. The larger value consumes more system resources and has
29150+ an impact to performance.
29151+config AUFS_BRANCH_MAX_511
29152+ bool "511"
29153+ help
29154+ Specifies the maximum number of branches (or member directories) in a
29155+ single aufs. The larger value consumes more system resources and has
29156+ an impact to performance.
29157+config AUFS_BRANCH_MAX_1023
29158+ bool "1023"
29159+ help
29160+ Specifies the maximum number of branches (or member directories) in a
29161+ single aufs. The larger value consumes more system resources and has
29162+ an impact to performance.
29163+# 128kb is available for kmalloc?
29164+config AUFS_BRANCH_MAX_32767
29165+ bool "32767"
29166+ help
29167+ Specifies the maximum number of branches (or member directories) in a
29168+ single aufs. The larger value consumes more system resources and has
29169+ an impact to performance.
29170+endchoice
29171+
29172+config AUFS_STAT
29173+ bool "Use <sysfs>/fs/aufs/stat"
29174+ depends on SYSFS
29175+ help
29176+ Shows some statistic data via <sysfs>/fs/aufs/stat.
29177+ See detail in aufs.5.
29178+
29179+comment "SYSFS and AUFS_STAT are disabled"
29180+ depends on SYSFS = n
29181+
29182+config AUFS_HINOTIFY
29183+ bool "Use inotify to detect actions on a branch"
29184+ depends on INOTIFY
29185+ help
29186+ If you want to modify files on branches directly, eg. bypassing aufs,
29187+ and want aufs to detect the changes of them fully, then enable this
29188+ option and use 'udba=inotify' mount option.
29189+ It will have a negative impact to the performance.
29190+ See detail in aufs.5.
29191+
29192+comment "INOTIFY and AUFS_HINOTIFY are disabled"
29193+ depends on INOTIFY = n
29194+
29195+config AUFS_EXPORT
29196+ bool "NFS-exportable aufs"
29197+ depends on (AUFS = y && EXPORTFS = y) || (AUFS = m && EXPORTFS)
29198+ help
29199+ If you want to export your mounted aufs, then enable this
29200+ option. There are several requirements for this configuration.
29201+ See detail in aufs.5.
29202+
29203+comment "EXPORTFS and AUFS_EXPORT are disabled"
29204+ depends on EXPORTFS = n
29205+
29206+comment "AUFS_EXPORT is disabled since EXPORTFS is a module but AUFS"
29207+ depends on EXPORTFS = m && AUFS = y
29208+
29209+# automatic configuration for internal use
29210+config AUFS_INO_T_64
29211+ bool # never appear on the menu
29212+ # typedef unsigned long/int __kernel_ino_t
29213+ # alpha and s390x are int
29214+ depends on 64BIT && !(ALPHA || S390)
29215+ default y
29216+
29217+config AUFS_ROBR
29218+ bool "Aufs as an readonly branch of another aufs mount"
29219+ help
29220+ If you want make your aufs to be a part of another aufs, then
29221+ enable this option. In other words, you can specify your aufs
29222+ path in 'br:' mount option for another aufs, but cannot
29223+ specify 'rw' as the branch permission.
29224+ It will have a negative impact to the performance.
29225+ See detail in aufs.5.
29226+
29227+config AUFS_DLGT
29228+ bool "Delegate the internal branch access the kernel thread"
29229+ help
29230+ If you want aufs to delegate
29231+ the internal access to the branches which is made by aufs, to
29232+ the kernel thread, in order to hide the access issued by your
29233+ application from your LSM or something or make your
29234+ application to be traced strictly by the task I/O accounting,
29235+ then enable this option and use 'dlgt' mount option.
29236+ It will have a negative impact to the performance.
29237+ See detail in aufs.5.
29238+
29239+# automatic configuration for internal use
29240+config AUFS_HIN_OR_DLGT
29241+ bool # never appear on the menu
29242+ depends on AUFS_HINOTIFY || AUFS_DLGT
29243+ default y
29244+ help
29245+ Automatic configuration for internal use.
29246+
29247+config AUFS_SHWH
29248+ bool "Show whiteouts"
29249+ help
29250+ If you want to make the whiteouts in aufs visible, then enable
29251+ this option and specify 'shwh' mount option. Although it may
29252+ sounds like philosophy or something, but in technically it
29253+ simply shows the name of whiteout with keeping its behaviour.
29254+
29255+# this is not in mainstream kernel
29256+config AUFS_RR_SQUASHFS
29257+ bool "Make squashfs branch RR (real readonly) by default"
29258+ default y
29259+ help
29260+ If you use squashfs or LZMA patched squashfs as an aufs branch
29261+ and want to set '=rr' to it by default, then enable this
29262+ configuration.
29263+ 'rr' stands for real readonly and it optimizes some aspects of
29264+ 'ro.'
29265+ See detail in aufs.5.
29266+
29267+config AUFS_SEC_PERM_PATCH
29268+ bool "sec_perm-2.6.24.patch was applied or not"
29269+ depends on AUFS = m
29270+ depends on SECURITY
29271+ help
29272+ If you build aufs as a module and enabled CONFIG_SECURITY,
29273+ then you need to apply the patch
29274+ 'CVS_TREE/aufs/patch/sec_perm-2.6.24.patch' to your kernel
29275+ source, and enable this configuration.
29276+ The sec_perm-2.6.24.patch exports a kernel function
29277+ security_inode_permission() to modules.
29278+
29279+comment "SECURITY and AUFS_SEC_PERM_PATCH are disabled"
29280+ depends on SECURITY = n
29281+
29282+config AUFS_SPLICE_PATCH
29283+ bool "splice.patch for sendfile(2) and splice(2)"
29284+ help
29285+ If you use 'loopback mount' on a fs-image file, or use
29286+ splice(2) or sendfile(2) systemcall in aufs, then you need to
29287+ apply the patch 'CVS_TREE/aufs/patch/splice.patch' to your
29288+ kernel source, and enable this configuration.
29289+ The splice.patch makes the kernel function do_splice_to/from()
29290+ global and exports them to modules.
29291+
29292+config AUFS_LHASH_PATCH
29293+ bool "lhash.patch for NFS branch"
29294+ depends on NFS_FS
29295+ help
29296+ If you use mounted NFS as an aufs branch filesystem, then you
29297+ need to apply the patch 'CVS_TREE/aufs/patch/lhash.patch' (or
29298+ lhash-2.6.22.patch for linux-2.6.22 and later) to your kernel
29299+ source, and enable this configuration.
29300+ The patch file makes the kernel function __lookup_hash() global
29301+ and exports it to modules.
29302+
29303+comment "NFS_FS and AUFS_LHASH_PATCH are disabled"
29304+ depends on NFS_FS = n
29305+
29306+config AUFS_PUT_FILP_PATCH
29307+ bool "put_filp.patch for 'atomic open'"
29308+ depends on AUFS = m && NFS_V4
29309+ help
29310+ If you build aufs as a module and use a filesystem which
29311+ operates 'atomic open' (for instance NFSv4) as an aufs branch
29312+ filesystem, then you need to apply the patch
29313+ 'CVS_TREE/aufs/patch/put_filp.patch' to your kernel source,
29314+ and enable this configuration.
29315+ The put_filp.patch exports a kernel function put_filp() to
29316+ modules.
29317+
29318+comment "NFS_V4 and AUFS_PUT_FILP_PATCH are disabled"
29319+ depends on NFS_V4 = n
29320+
29321+# automatic configuration for internal use
29322+config AUFS_BR_NFS
29323+ bool # never appear on the menu
29324+ depends on NFS_FS
29325+ depends on AUFS_LHASH_PATCH
29326+ default y
29327+ help
29328+ Automatic configuration for internal use.
29329+ When aufs supports NFS branch, enabled automatically.
29330+
29331+config AUFS_BR_NFS_V4
29332+ bool # never appear on the menu
29333+ depends on NFS_V4 && AUFS_BR_NFS
29334+ depends on AUFS = y || (AUFS = m && AUFS_PUT_FILP_PATCH)
29335+ default y
29336+ help
29337+ Automatic configuration for internal use.
29338+ When aufs supports a branch filesystem which operates
29339+ 'atomic_open', for instance NFSv4, this configuration is enabled
29340+ automatically.
29341+
29342+config AUFS_BR_XFS
29343+ bool # never appear on the menu
29344+ depends on XFS_FS
29345+ default y
29346+ help
29347+ Automatic configuration for internal use.
29348+ When aufs supports XFS branch, enabled automatically.
29349+
29350+config AUFS_FSYNC_SUPER_PATCH
29351+ bool "fsync_super-2.6.xx.patch was applied or not"
29352+ depends on AUFS = m
29353+ help
29354+ If you build aufs as a module and want to flush everything for
29355+ branch filesystems which are not marked as 'rr' nor 'rr+wh' at
29356+ umount or remount time, then you need to apply the patch
29357+ 'CVS_TREE/aufs/patch/fsync_super-2.6.16.patch' or
29358+ '...-2.6.19.patch' to your kernel source, and enable this
29359+ configuration.
29360+ It may be helpful at shutdown time in case of your aufs is a
29361+ root filesystem. But this behaviour will not guarantee the
29362+ consistency of branch filesystems. To guarantee it, try the
29363+ approach described in the aufs manual, and do not forget
29364+ installing auplink script.
29365+ The fsync_super-2.6.xx.patch does nothing but exports a kernel
29366+ function fsync_super() to modules.
29367+
29368+config AUFS_DENY_WRITE_ACCESS_PATCH
29369+ bool "deny_write_access.patch was applied or not"
29370+ depends on AUFS = m
29371+ help
29372+ A security enhancement to deny writing to a running executable
29373+ which exists on an aufs branch filesystem and executed through
29374+ aufs. If you applied
29375+ 'CVS_TREE/aufs/patch/deny_write_access.patch' to your kernel
29376+ and you are compiling aufs as a module, then enable this
29377+ option.
29378+ The write_deny_access.patch does nothing but export the
29379+ function.
29380+
29381+config AUFS_WORKAROUND_FUSE
29382+ bool "Special handling for FUSE-based filesystem"
29383+ depends on FUSE_FS
29384+ help
29385+ A FUSE-based filesystem may not initialize its inode
29386+ attributes and the FUSE developer thinks the inode attributes
29387+ in a positive dentry which is returned by VFS lookup operation
29388+ are not reliable.
29389+ If you use a FUSE-based filesystem as an aufs branch, and it
29390+ customizes the inode attribute on it without overriding
29391+ fuse_lowlevel_ops.lookup, probably you need to enable this
29392+ configuration.
29393+ If you enable this configuration, aufs calls getattr operation
29394+ in every lookup and revalidate operation for the FUSE-based
29395+ filesystem branch.
29396+ It will have a negative impact to the performance even if you do
29397+ not use a FUSE-based filesystem branch.
29398+
29399+# automatic configuration for internal use
29400+config AUFS_GETATTR
29401+ bool # never appear on the menu
29402+ depends on AUFS_HINOTIFY || AUFS_WORKAROUND_FUSE || AUFS_BR_NFS
29403+ default y
29404+ help
29405+ Automatic configuration for internal use.
29406+
29407+config AUFS_DEBUG
29408+ bool "Debug aufs"
29409+ default y
29410+ help
29411+ Enable this to compile aufs internal debug code.
29412+ It will have a negative impact to the performance.
29413+
29414+# automatic configuration for internal use
29415+config AUFS_MAGIC_SYSRQ
29416+ bool # never appear on the menu
29417+ depends on AUFS_DEBUG && MAGIC_SYSRQ
29418+ default y
29419+ help
29420+ Automatic configuration for internal use.
29421+ When aufs supports Magic SysRq, enabled automatically.
29422+
29423+config AUFS_DEBUG_LOCK
29424+ bool "Show lock status in Magic SysRq"
29425+ depends on AUFS_MAGIC_SYSRQ
29426+ help
29427+ For developers only. Sometimes it is useful when a deadlock
29428+ occurs in aufs. Trace every aufs lock acquire and release, and
29429+ print them when Magic SysRq-<AUFS> key is pressed.
29430+ It will have a huge negative impact to the performance.
29431+
29432+config AUFS_COMPAT
29433+ bool "Compatibility with Unionfs (obsolete)"
29434+ help
29435+ This makes aufs compatible with unionfs-style mount options and some
29436+ behaviours.
29437+ The dirs= mount option and =nfsro branch permission flag are always
29438+ interpreted as br: mount option and =ro flag respectively. The
29439+ 'debug', 'delete' and 'imap' mount options are ignored.
29440+ If you disable this option, you will get,
29441+ - aufs issues a warning about the ignored mount options
29442+ - the default branch permission flag is set. RW for the first branch,
29443+ and RO for the rests.
29444+ - the name of a internal file which represents the directory is
29445+ 'opaque', becomes '.wh..wh..opq'
29446+ - the 'diropq=w' mount option is set by default
29447+
29448+config AUFS_UNIONFS22_PATCH
29449+ bool "Unionfs-2.2 or later patch is applied or not (obsolete)"
29450+ help
29451+ Unionfs version 2.2 (and later) patch introduces some changes in VFS
29452+ layer which has an impact to aufs. If you have applied such
29453+ patch to your kernel, you need to enable this configuration even
29454+ if you disabled CONFIG_UNIONFS.
29455+
29456+config AUFS_UNIONFS23_PATCH
29457+ bool "Unionfs-2.3 or later patch is applied or not (obsolete)"
29458+ select AUFS_SPLICE_PATCH
29459+ select AUFS_UNIONFS22_PATCH
29460+ help
29461+ Unionfs version 2.3 (and later) patch introduces some changes in VFS
29462+ layer which has an impact to aufs. If you have applied such
29463+ patch to your kernel, you need to enable this configuration even
29464+ if you disabled CONFIG_UNIONFS.
29465+endif
29466+
29467 endmenu
29468
29469 menu "Miscellaneous filesystems"
29470diff -urN linux/fs/Makefile linux-aufs/fs/Makefile
29471--- linux/fs/Makefile 2009-03-12 11:25:26.000000000 +0100
29472+++ linux-aufs/fs/Makefile 2009-03-12 17:03:22.897115295 +0100
29473@@ -89,6 +89,7 @@
29474 obj-$(CONFIG_HFS_FS) += hfs/
29475 obj-$(CONFIG_ECRYPT_FS) += ecryptfs/
29476 obj-$(CONFIG_UNION_FS) += unionfs/
29477+obj-$(CONFIG_AUFS) += aufs/
29478 obj-$(CONFIG_VXFS_FS) += freevxfs/
29479 obj-$(CONFIG_NFS_FS) += nfs/
29480 obj-$(CONFIG_EXPORTFS) += exportfs/
29481diff -urN linux/include/linux/aufs_type.h linux-aufs/include/linux/aufs_type.h
29482--- linux/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
29483+++ linux-aufs/include/linux/aufs_type.h 2009-03-12 16:18:04.000000000 +0100
29484@@ -0,0 +1,127 @@
29485+/*
29486+ * Copyright (C) 2005-2009 Junjiro Okajima
29487+ *
29488+ * This program, aufs is free software; you can redistribute it and/or modify
29489+ * it under the terms of the GNU General Public License as published by
29490+ * the Free Software Foundation; either version 2 of the License, or
29491+ * (at your option) any later version.
29492+ *
29493+ * This program is distributed in the hope that it will be useful,
29494+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29495+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29496+ * GNU General Public License for more details.
29497+ *
29498+ * You should have received a copy of the GNU General Public License
29499+ * along with this program; if not, write to the Free Software
29500+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29501+ */
29502+
29503+/* $Id$ */
29504+
29505+#include <linux/ioctl.h>
29506+
29507+#ifndef __AUFS_TYPE_H__
29508+#define __AUFS_TYPE_H__
29509+
29510+#define AUFS_VERSION "20090126"
29511+
29512+/* move this to linux-2.6.19/include/magic.h */
29513+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
29514+
29515+/* ---------------------------------------------------------------------- */
29516+
29517+#ifdef CONFIG_AUFS_BRANCH_MAX_127
29518+/* some environments treat 'char' as 'unsigned char' by default */
29519+typedef signed char aufs_bindex_t;
29520+#define AUFS_BRANCH_MAX 127
29521+#else
29522+typedef short aufs_bindex_t;
29523+#ifdef CONFIG_AUFS_BRANCH_MAX_511
29524+#define AUFS_BRANCH_MAX 511
29525+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
29526+#define AUFS_BRANCH_MAX 1023
29527+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
29528+#define AUFS_BRANCH_MAX 32767
29529+#else
29530+#error unknown CONFIG_AUFS_BRANCH_MAX value
29531+#endif
29532+#endif
29533+
29534+#define AUFS_NAME "aufs"
29535+#define AUFS_FSTYPE AUFS_NAME
29536+
29537+#define AUFS_ROOT_INO 2
29538+#define AUFS_FIRST_INO 11
29539+
29540+#define AUFS_WH_PFX ".wh."
29541+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
29542+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
29543+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
29544+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
29545+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
29546+#define AUFS_DIRWH_DEF 3
29547+#define AUFS_RDCACHE_DEF 10 /* seconds */
29548+#define AUFS_WKQ_NAME AUFS_NAME "d"
29549+#define AUFS_NWKQ_DEF 4
29550+#define AUFS_MFS_SECOND_DEF 30 /* seconds */
29551+#define AUFS_PLINK_WARN 100 /* number of plinks */
29552+
29553+#ifdef CONFIG_AUFS_COMPAT
29554+#define AUFS_DIROPQ_NAME "__dir_opaque"
29555+#else
29556+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
29557+#endif
29558+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
29559+
29560+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
29561+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
29562+#define AUFS_TMPDIR_NAME AUFS_WH_PFX ".tmp"
29563+
29564+/* doubly whiteouted */
29565+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
29566+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
29567+#define AUFS_WH_TMPDIR AUFS_WH_PFX AUFS_TMPDIR_NAME
29568+
29569+/* ---------------------------------------------------------------------- */
29570+
29571+/* ioctl */
29572+#if 0 /* reserved for future use */
29573+enum {
29574+ AuCtlErr,
29575+ AuCtlErr_Last
29576+};
29577+enum {
29578+ AuCtl_DIROPQ_GET, AuCtl_DIROPQ_SET,
29579+ AuCtl_MOVE,
29580+ AuCtl_MVDOWN,
29581+
29582+ /* unimplmented */
29583+ AuCtl_REFRESH, AuCtl_REFRESHV,
29584+ AuCtl_FLUSH_PLINK,
29585+ AuCtl_CPUP,
29586+ AuCtl_CPDOWN
29587+};
29588+
29589+struct aufs_ctl {
29590+ int err;
29591+ aufs_bindex_t bsrc, bdst;
29592+ char *path;
29593+};
29594+
29595+#define AuCtlType 'A'
29596+#define AUFS_CTL_DIROPQ_GET _IO(AuCtlType, AuCtl_DIROPQ_GET)
29597+#define AUFS_CTL_DIROPQ_SET _IOW(AuCtlType, AuCtl_DIROPQ_SET, aufs_bindex_t)
29598+#define AUFS_CTL_MOVE \
29599+ _IOW(AuCtlType, AuCtl_MVDOWN, aufs_bindex_t)
29600+#define AUFS_CTL_MVDOWN \
29601+ _IOWR(AuCtlType, AuCtl_MVDOWN, struct aufs_ctl)
29602+
29603+#define AUFS_CTL_REFRESH _IO(AuCtlType, AuCtl_REFRESH)
29604+#define AUFS_CTL_REFRESHV _IO(AuCtlType, AuCtl_REFRESHV)
29605+#define AUFS_CTL_FLUSH_PLINK _IOR(AuCtlType, AuCtl_FLUSH_PLINK)
29606+#define AUFS_CTL_CPUP _IOWR(AuCtlType, AuCtl_CPUP, struct aufs_ctl)
29607+#define AUFS_CTL_CPDOWN \
29608+ _IOWR(AuCtlType, AuCtl_CPDOWN, struct aufs_ctl_cp)
29609+#endif
29610+
29611+#endif /* __AUFS_TYPE_H__ */
This page took 4.399956 seconds and 4 git commands to generate.