]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs2.patch
- updated aufs2 patch
[packages/kernel.git] / kernel-aufs2.patch
CommitLineData
4a4d8108
AM
1diff -urN --exclude '*.orig' linux-2.6.34.org/Documentation/ABI/testing/debugfs-aufs linux-2.6.34/Documentation/ABI/testing/debugfs-aufs
2--- linux-2.6.34.org/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
3+++ linux-2.6.34/Documentation/ABI/testing/debugfs-aufs 2010-05-31 22:15:32.000000000 +0200
4@@ -0,0 +1,37 @@
1facf9fc 5+What: /debug/aufs/si_<id>/
6+Date: March 2009
7+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
8+Description:
9+ Under /debug/aufs, a directory named si_<id> is created
10+ per aufs mount, where <id> is a unique id generated
11+ internally.
12+
13+What: /debug/aufs/si_<id>/xib
14+Date: March 2009
15+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
16+Description:
17+ It shows the consumed blocks by xib (External Inode Number
18+ Bitmap), its block size and file size.
19+ When the aufs mount option 'noxino' is specified, it
4a4d8108 20+ will be empty. About XINO files, see the aufs manual.
1facf9fc 21+
22+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
23+Date: March 2009
24+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
25+Description:
26+ It shows the consumed blocks by xino (External Inode Number
27+ Translation Table), its link count, block size and file
28+ size.
29+ When the aufs mount option 'noxino' is specified, it
4a4d8108 30+ will be empty. About XINO files, see the aufs manual.
1facf9fc 31+
32+What: /debug/aufs/si_<id>/xigen
33+Date: March 2009
34+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
35+Description:
36+ It shows the consumed blocks by xigen (External Inode
37+ Generation Table), its block size and file size.
38+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
39+ be created.
40+ When the aufs mount option 'noxino' is specified, it
4a4d8108
AM
41+ will be empty. About XINO files, see the aufs manual.
42diff -urN --exclude '*.orig' linux-2.6.34.org/Documentation/ABI/testing/sysfs-aufs linux-2.6.34/Documentation/ABI/testing/sysfs-aufs
43--- linux-2.6.34.org/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
44+++ linux-2.6.34/Documentation/ABI/testing/sysfs-aufs 2010-05-31 22:15:32.000000000 +0200
45@@ -0,0 +1,24 @@
1facf9fc 46+What: /sys/fs/aufs/si_<id>/
47+Date: March 2009
48+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
49+Description:
50+ Under /sys/fs/aufs, a directory named si_<id> is created
51+ per aufs mount, where <id> is a unique id generated
52+ internally.
53+
54+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
55+Date: March 2009
56+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
57+Description:
58+ It shows the abolute path of a member directory (which
59+ is called branch) in aufs, and its permission.
60+
61+What: /sys/fs/aufs/si_<id>/xi_path
62+Date: March 2009
63+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
64+Description:
65+ It shows the abolute path of XINO (External Inode Number
66+ Bitmap, Translation Table and Generation Table) file
67+ even if it is the default path.
68+ When the aufs mount option 'noxino' is specified, it
4a4d8108
AM
69+ will be empty. About XINO files, see the aufs manual.
70diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/aufs.h linux-2.6.34/fs/aufs/aufs.h
71--- linux-2.6.34.org/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
72+++ linux-2.6.34/fs/aufs/aufs.h 2010-05-31 22:15:32.000000000 +0200
73@@ -0,0 +1,61 @@
1facf9fc 74+/*
4a4d8108 75+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 76+ *
77+ * This program, aufs is free software; you can redistribute it and/or modify
78+ * it under the terms of the GNU General Public License as published by
79+ * the Free Software Foundation; either version 2 of the License, or
80+ * (at your option) any later version.
dece6358
AM
81+ *
82+ * This program is distributed in the hope that it will be useful,
83+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
84+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85+ * GNU General Public License for more details.
86+ *
87+ * You should have received a copy of the GNU General Public License
88+ * along with this program; if not, write to the Free Software
89+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 90+ */
91+
92+/*
93+ * all header files
94+ */
95+
96+#ifndef __AUFS_H__
97+#define __AUFS_H__
98+
99+#ifdef __KERNEL__
100+
4a4d8108
AM
101+#define AuStub(type, name, body, ...) \
102+ static inline type name(__VA_ARGS__) { body; }
103+
104+#define AuStubVoid(name, ...) \
105+ AuStub(void, name, , __VA_ARGS__)
106+#define AuStubInt0(name, ...) \
107+ AuStub(int, name, return 0, __VA_ARGS__)
108+
1facf9fc 109+#include "debug.h"
110+
111+#include "branch.h"
112+#include "cpup.h"
113+#include "dcsub.h"
114+#include "dbgaufs.h"
115+#include "dentry.h"
116+#include "dir.h"
4a4d8108 117+#include "dynop.h"
1facf9fc 118+#include "file.h"
119+#include "fstype.h"
120+#include "inode.h"
121+#include "loop.h"
122+#include "module.h"
4a4d8108 123+/* never include ./mtx.h */
1facf9fc 124+#include "opts.h"
125+#include "rwsem.h"
126+#include "spl.h"
127+#include "super.h"
128+#include "sysaufs.h"
129+#include "vfsub.h"
130+#include "whout.h"
131+#include "wkq.h"
132+
133+#endif /* __KERNEL__ */
134+#endif /* __AUFS_H__ */
4a4d8108
AM
135diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/branch.c linux-2.6.34/fs/aufs/branch.c
136--- linux-2.6.34.org/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
137+++ linux-2.6.34/fs/aufs/branch.c 2010-05-31 22:15:32.000000000 +0200
138@@ -0,0 +1,1007 @@
1facf9fc 139+/*
4a4d8108 140+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 141+ *
142+ * This program, aufs is free software; you can redistribute it and/or modify
143+ * it under the terms of the GNU General Public License as published by
144+ * the Free Software Foundation; either version 2 of the License, or
145+ * (at your option) any later version.
dece6358
AM
146+ *
147+ * This program is distributed in the hope that it will be useful,
148+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
149+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
150+ * GNU General Public License for more details.
151+ *
152+ * You should have received a copy of the GNU General Public License
153+ * along with this program; if not, write to the Free Software
154+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 155+ */
156+
157+/*
158+ * branch management
159+ */
160+
dece6358 161+#include <linux/file.h>
4a4d8108 162+#include <linux/statfs.h>
1facf9fc 163+#include "aufs.h"
164+
165+/*
166+ * free a single branch
167+ */
168+static void au_br_do_free(struct au_branch *br)
169+{
170+ int i;
171+ struct au_wbr *wbr;
4a4d8108 172+ struct au_dykey **key;
1facf9fc 173+
174+ if (br->br_xino.xi_file)
175+ fput(br->br_xino.xi_file);
176+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
177+
178+ AuDebugOn(atomic_read(&br->br_count));
179+
180+ wbr = br->br_wbr;
181+ if (wbr) {
182+ for (i = 0; i < AuBrWh_Last; i++)
183+ dput(wbr->wbr_wh[i]);
184+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 185+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 186+ }
187+
4a4d8108
AM
188+ key = br->br_dykey;
189+ for (i = 0; i < AuBrDynOp; i++, key++)
190+ if (*key)
191+ au_dy_put(*key);
192+ else
193+ break;
194+
1facf9fc 195+ /* some filesystems acquire extra lock */
4a4d8108 196+ /* lockdep_off(); */
1facf9fc 197+ mntput(br->br_mnt);
4a4d8108 198+ /* lockdep_on(); */
1facf9fc 199+
200+ kfree(wbr);
201+ kfree(br);
202+}
203+
204+/*
205+ * frees all branches
206+ */
207+void au_br_free(struct au_sbinfo *sbinfo)
208+{
209+ aufs_bindex_t bmax;
210+ struct au_branch **br;
211+
dece6358
AM
212+ AuRwMustWriteLock(&sbinfo->si_rwsem);
213+
1facf9fc 214+ bmax = sbinfo->si_bend + 1;
215+ br = sbinfo->si_branch;
216+ while (bmax--)
217+ au_br_do_free(*br++);
218+}
219+
220+/*
221+ * find the index of a branch which is specified by @br_id.
222+ */
223+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
224+{
225+ aufs_bindex_t bindex, bend;
226+
227+ bend = au_sbend(sb);
228+ for (bindex = 0; bindex <= bend; bindex++)
229+ if (au_sbr_id(sb, bindex) == br_id)
230+ return bindex;
231+ return -1;
232+}
233+
234+/* ---------------------------------------------------------------------- */
235+
236+/*
237+ * add a branch
238+ */
239+
240+static int test_overlap(struct super_block *sb, struct dentry *h_d1,
241+ struct dentry *h_d2)
242+{
243+ if (unlikely(h_d1 == h_d2))
244+ return 1;
4a4d8108
AM
245+ return au_test_subdir(h_d1, h_d2)
246+ || au_test_subdir(h_d2, h_d1)
1facf9fc 247+ || au_test_loopback_overlap(sb, h_d1, h_d2)
248+ || au_test_loopback_overlap(sb, h_d2, h_d1);
249+}
250+
251+/*
252+ * returns a newly allocated branch. @new_nbranch is a number of branches
253+ * after adding a branch.
254+ */
255+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
256+ int perm)
257+{
258+ struct au_branch *add_branch;
259+ struct dentry *root;
4a4d8108 260+ int err;
1facf9fc 261+
4a4d8108 262+ err = -ENOMEM;
1facf9fc 263+ root = sb->s_root;
264+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
265+ if (unlikely(!add_branch))
266+ goto out;
267+
268+ add_branch->br_wbr = NULL;
269+ if (au_br_writable(perm)) {
270+ /* may be freed separately at changing the branch permission */
271+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
272+ GFP_NOFS);
273+ if (unlikely(!add_branch->br_wbr))
274+ goto out_br;
275+ }
276+
4a4d8108
AM
277+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
278+ if (!err)
279+ err = au_di_realloc(au_di(root), new_nbranch);
280+ if (!err)
281+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
282+ if (!err)
283+ return add_branch; /* success */
1facf9fc 284+
1facf9fc 285+ kfree(add_branch->br_wbr);
4a4d8108 286+
1facf9fc 287+ out_br:
288+ kfree(add_branch);
289+ out:
4a4d8108 290+ return ERR_PTR(err);
1facf9fc 291+}
292+
293+/*
294+ * test if the branch permission is legal or not.
295+ */
296+static int test_br(struct inode *inode, int brperm, char *path)
297+{
298+ int err;
299+
4a4d8108
AM
300+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
301+ if (!err)
302+ goto out;
1facf9fc 303+
4a4d8108
AM
304+ err = -EINVAL;
305+ pr_err("write permission for readonly mount or inode, %s\n", path);
306+
307+ out:
1facf9fc 308+ return err;
309+}
310+
311+/*
312+ * returns:
313+ * 0: success, the caller will add it
314+ * plus: success, it is already unified, the caller should ignore it
315+ * minus: error
316+ */
317+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
318+{
319+ int err;
320+ aufs_bindex_t bend, bindex;
321+ struct dentry *root;
322+ struct inode *inode, *h_inode;
323+
324+ root = sb->s_root;
325+ bend = au_sbend(sb);
326+ if (unlikely(bend >= 0
327+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
328+ err = 1;
329+ if (!remount) {
330+ err = -EINVAL;
4a4d8108 331+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 332+ }
333+ goto out;
334+ }
335+
336+ err = -ENOSPC; /* -E2BIG; */
337+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
338+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 339+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 340+ goto out;
341+ }
342+
343+ err = -EDOM;
344+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 345+ pr_err("bad index %d\n", add->bindex);
1facf9fc 346+ goto out;
347+ }
348+
349+ inode = add->path.dentry->d_inode;
350+ err = -ENOENT;
351+ if (unlikely(!inode->i_nlink)) {
4a4d8108 352+ pr_err("no existence %s\n", add->pathname);
1facf9fc 353+ goto out;
354+ }
355+
356+ err = -EINVAL;
357+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 358+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 359+ goto out;
360+ }
361+
362+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
363+ pr_err("unsupported filesystem, %s (%s)\n",
364+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 365+ goto out;
366+ }
367+
368+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
369+ if (unlikely(err))
370+ goto out;
371+
372+ if (bend < 0)
373+ return 0; /* success */
374+
375+ err = -EINVAL;
376+ for (bindex = 0; bindex <= bend; bindex++)
377+ if (unlikely(test_overlap(sb, add->path.dentry,
378+ au_h_dptr(root, bindex)))) {
4a4d8108 379+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 380+ goto out;
381+ }
382+
383+ err = 0;
384+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
385+ h_inode = au_h_dptr(root, 0)->d_inode;
386+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
387+ || h_inode->i_uid != inode->i_uid
388+ || h_inode->i_gid != inode->i_gid)
4a4d8108
AM
389+ pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
390+ add->pathname,
391+ inode->i_uid, inode->i_gid,
392+ (inode->i_mode & S_IALLUGO),
393+ h_inode->i_uid, h_inode->i_gid,
394+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 395+ }
396+
397+ out:
398+ return err;
399+}
400+
401+/*
402+ * initialize or clean the whiteouts for an adding branch
403+ */
404+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
405+ int new_perm, struct dentry *h_root)
406+{
407+ int err, old_perm;
408+ aufs_bindex_t bindex;
409+ struct mutex *h_mtx;
410+ struct au_wbr *wbr;
411+ struct au_hinode *hdir;
412+
413+ wbr = br->br_wbr;
414+ old_perm = br->br_perm;
415+ br->br_perm = new_perm;
416+ hdir = NULL;
417+ h_mtx = NULL;
418+ bindex = au_br_index(sb, br->br_id);
419+ if (0 <= bindex) {
420+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 421+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 422+ } else {
423+ h_mtx = &h_root->d_inode->i_mutex;
424+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
425+ }
426+ if (!wbr)
427+ err = au_wh_init(h_root, br, sb);
428+ else {
429+ wbr_wh_write_lock(wbr);
430+ err = au_wh_init(h_root, br, sb);
431+ wbr_wh_write_unlock(wbr);
432+ }
433+ if (hdir)
4a4d8108 434+ au_hn_imtx_unlock(hdir);
1facf9fc 435+ else
436+ mutex_unlock(h_mtx);
437+ br->br_perm = old_perm;
438+
439+ if (!err && wbr && !au_br_writable(new_perm)) {
440+ kfree(wbr);
441+ br->br_wbr = NULL;
442+ }
443+
444+ return err;
445+}
446+
447+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
448+ int perm, struct path *path)
449+{
450+ int err;
4a4d8108 451+ struct kstatfs kst;
1facf9fc 452+ struct au_wbr *wbr;
4a4d8108 453+ struct dentry *h_dentry;
1facf9fc 454+
455+ wbr = br->br_wbr;
dece6358 456+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 457+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
458+ atomic_set(&wbr->wbr_wh_running, 0);
459+ wbr->wbr_bytes = 0;
460+
4a4d8108
AM
461+ /*
462+ * a limit for rmdir/rename a dir
463+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
464+ */
465+ h_dentry = path->dentry;
466+ err = vfs_statfs(h_dentry, &kst);
467+ if (unlikely(err))
468+ goto out;
469+ err = -EINVAL;
470+ if (kst.f_namelen >= NAME_MAX)
471+ err = au_br_init_wh(sb, br, perm, h_dentry);
472+ else
473+ pr_err("%.*s(%s), unsupported namelen %ld\n",
474+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
475+ kst.f_namelen);
1facf9fc 476+
4a4d8108 477+ out:
1facf9fc 478+ return err;
479+}
480+
481+/* intialize a new branch */
482+static int au_br_init(struct au_branch *br, struct super_block *sb,
483+ struct au_opt_add *add)
484+{
485+ int err;
486+
487+ err = 0;
488+ memset(&br->br_xino, 0, sizeof(br->br_xino));
489+ mutex_init(&br->br_xino.xi_nondir_mtx);
490+ br->br_perm = add->perm;
491+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
492+ spin_lock_init(&br->br_dykey_lock);
493+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 494+ atomic_set(&br->br_count, 0);
495+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
496+ atomic_set(&br->br_xino_running, 0);
497+ br->br_id = au_new_br_id(sb);
498+
499+ if (au_br_writable(add->perm)) {
500+ err = au_wbr_init(br, sb, add->perm, &add->path);
501+ if (unlikely(err))
502+ goto out;
503+ }
504+
505+ if (au_opt_test(au_mntflags(sb), XINO)) {
506+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
507+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
508+ if (unlikely(err)) {
509+ AuDebugOn(br->br_xino.xi_file);
510+ goto out;
511+ }
512+ }
513+
514+ sysaufs_br_init(br);
515+ mntget(add->path.mnt);
516+
517+ out:
518+ return err;
519+}
520+
521+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
522+ struct au_branch *br, aufs_bindex_t bend,
523+ aufs_bindex_t amount)
524+{
525+ struct au_branch **brp;
526+
dece6358
AM
527+ AuRwMustWriteLock(&sbinfo->si_rwsem);
528+
1facf9fc 529+ brp = sbinfo->si_branch + bindex;
530+ memmove(brp + 1, brp, sizeof(*brp) * amount);
531+ *brp = br;
532+ sbinfo->si_bend++;
533+ if (unlikely(bend < 0))
534+ sbinfo->si_bend = 0;
535+}
536+
537+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
538+ aufs_bindex_t bend, aufs_bindex_t amount)
539+{
540+ struct au_hdentry *hdp;
541+
1308ab2a 542+ AuRwMustWriteLock(&dinfo->di_rwsem);
543+
1facf9fc 544+ hdp = dinfo->di_hdentry + bindex;
545+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
546+ au_h_dentry_init(hdp);
547+ dinfo->di_bend++;
548+ if (unlikely(bend < 0))
549+ dinfo->di_bstart = 0;
550+}
551+
552+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
553+ aufs_bindex_t bend, aufs_bindex_t amount)
554+{
555+ struct au_hinode *hip;
556+
1308ab2a 557+ AuRwMustWriteLock(&iinfo->ii_rwsem);
558+
1facf9fc 559+ hip = iinfo->ii_hinode + bindex;
560+ memmove(hip + 1, hip, sizeof(*hip) * amount);
561+ hip->hi_inode = NULL;
4a4d8108 562+ au_hn_init(hip);
1facf9fc 563+ iinfo->ii_bend++;
564+ if (unlikely(bend < 0))
565+ iinfo->ii_bstart = 0;
566+}
567+
568+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
569+ struct au_branch *br, aufs_bindex_t bindex)
570+{
571+ struct dentry *root;
572+ struct inode *root_inode;
573+ aufs_bindex_t bend, amount;
574+
575+ root = sb->s_root;
576+ root_inode = root->d_inode;
4a4d8108 577+ au_plink_maint_block(sb);
1facf9fc 578+ bend = au_sbend(sb);
579+ amount = bend + 1 - bindex;
580+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
581+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
582+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
583+ au_set_h_dptr(root, bindex, dget(h_dentry));
584+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
585+ /*flags*/0);
586+}
587+
588+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
589+{
590+ int err;
1facf9fc 591+ aufs_bindex_t bend, add_bindex;
592+ struct dentry *root, *h_dentry;
593+ struct inode *root_inode;
594+ struct au_branch *add_branch;
595+
596+ root = sb->s_root;
597+ root_inode = root->d_inode;
598+ IMustLock(root_inode);
599+ err = test_add(sb, add, remount);
600+ if (unlikely(err < 0))
601+ goto out;
602+ if (err) {
603+ err = 0;
604+ goto out; /* success */
605+ }
606+
607+ bend = au_sbend(sb);
608+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
609+ err = PTR_ERR(add_branch);
610+ if (IS_ERR(add_branch))
611+ goto out;
612+
613+ err = au_br_init(add_branch, sb, add);
614+ if (unlikely(err)) {
615+ au_br_do_free(add_branch);
616+ goto out;
617+ }
618+
619+ add_bindex = add->bindex;
620+ h_dentry = add->path.dentry;
621+ if (!remount)
622+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
623+ else {
624+ sysaufs_brs_del(sb, add_bindex);
625+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
626+ sysaufs_brs_add(sb, add_bindex);
627+ }
628+
1308ab2a 629+ if (!add_bindex) {
1facf9fc 630+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 631+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
632+ } else
1facf9fc 633+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 634+
635+ /*
4a4d8108 636+ * this test/set prevents aufs from handling unnecesary notify events
1facf9fc 637+ * of xino files, in a case of re-adding a writable branch which was
638+ * once detached from aufs.
639+ */
640+ if (au_xino_brid(sb) < 0
641+ && au_br_writable(add_branch->br_perm)
642+ && !au_test_fs_bad_xino(h_dentry->d_sb)
643+ && add_branch->br_xino.xi_file
644+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
645+ au_xino_brid_set(sb, add_branch->br_id);
646+
647+ out:
648+ return err;
649+}
650+
651+/* ---------------------------------------------------------------------- */
652+
653+/*
654+ * delete a branch
655+ */
656+
657+/* to show the line number, do not make it inlined function */
4a4d8108 658+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 659+ if (do_info) \
4a4d8108 660+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 661+} while (0)
662+
663+/*
664+ * test if the branch is deletable or not.
665+ */
666+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
667+ unsigned int sigen)
668+{
669+ int err, i, j, ndentry;
670+ aufs_bindex_t bstart, bend;
671+ unsigned char verbose;
672+ struct au_dcsub_pages dpages;
673+ struct au_dpage *dpage;
674+ struct dentry *d;
675+ struct inode *inode;
676+
677+ err = au_dpages_init(&dpages, GFP_NOFS);
678+ if (unlikely(err))
679+ goto out;
680+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
681+ if (unlikely(err))
682+ goto out_dpages;
683+
684+ verbose = !!au_opt_test(au_mntflags(root->d_sb), VERBOSE);
685+ for (i = 0; !err && i < dpages.ndpage; i++) {
686+ dpage = dpages.dpages + i;
687+ ndentry = dpage->ndentry;
688+ for (j = 0; !err && j < ndentry; j++) {
689+ d = dpage->dentries[j];
690+ AuDebugOn(!atomic_read(&d->d_count));
691+ inode = d->d_inode;
692+ if (au_digen(d) == sigen && au_iigen(inode) == sigen)
693+ di_read_lock_child(d, AuLock_IR);
694+ else {
695+ di_write_lock_child(d);
696+ err = au_reval_dpath(d, sigen);
697+ if (!err)
698+ di_downgrade_lock(d, AuLock_IR);
699+ else {
700+ di_write_unlock(d);
701+ break;
702+ }
703+ }
704+
705+ bstart = au_dbstart(d);
706+ bend = au_dbend(d);
707+ if (bstart <= bindex
708+ && bindex <= bend
709+ && au_h_dptr(d, bindex)
710+ && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
711+ err = -EBUSY;
712+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
713+ }
714+ di_read_unlock(d, AuLock_IR);
715+ }
716+ }
717+
718+ out_dpages:
719+ au_dpages_free(&dpages);
720+ out:
721+ return err;
722+}
723+
724+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
725+ unsigned int sigen)
726+{
727+ int err;
728+ struct inode *i;
729+ aufs_bindex_t bstart, bend;
730+ unsigned char verbose;
731+
732+ err = 0;
733+ verbose = !!au_opt_test(au_mntflags(sb), VERBOSE);
734+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
735+ AuDebugOn(!atomic_read(&i->i_count));
736+ if (!list_empty(&i->i_dentry))
737+ continue;
738+
739+ if (au_iigen(i) == sigen)
740+ ii_read_lock_child(i);
741+ else {
742+ ii_write_lock_child(i);
743+ err = au_refresh_hinode_self(i, /*do_attr*/1);
744+ if (!err)
745+ ii_downgrade_lock(i);
746+ else {
747+ ii_write_unlock(i);
748+ break;
749+ }
750+ }
751+
752+ bstart = au_ibstart(i);
753+ bend = au_ibend(i);
754+ if (bstart <= bindex
755+ && bindex <= bend
756+ && au_h_iptr(i, bindex)
757+ && (!S_ISDIR(i->i_mode) || bstart == bend)) {
758+ err = -EBUSY;
759+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
760+ ii_read_unlock(i);
761+ break;
762+ }
763+ ii_read_unlock(i);
764+ }
765+
766+ return err;
767+}
768+
769+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
770+{
771+ int err;
772+ unsigned int sigen;
773+
774+ sigen = au_sigen(root->d_sb);
775+ DiMustNoWaiters(root);
776+ IiMustNoWaiters(root->d_inode);
777+ di_write_unlock(root);
778+ err = test_dentry_busy(root, bindex, sigen);
779+ if (!err)
780+ err = test_inode_busy(root->d_sb, bindex, sigen);
781+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
782+
783+ return err;
784+}
785+
786+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
787+ const aufs_bindex_t bindex,
788+ const aufs_bindex_t bend)
789+{
790+ struct au_branch **brp, **p;
791+
dece6358
AM
792+ AuRwMustWriteLock(&sbinfo->si_rwsem);
793+
1facf9fc 794+ brp = sbinfo->si_branch + bindex;
795+ if (bindex < bend)
796+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
797+ sbinfo->si_branch[0 + bend] = NULL;
798+ sbinfo->si_bend--;
799+
800+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
801+ if (p)
802+ sbinfo->si_branch = p;
4a4d8108 803+ /* harmless error */
1facf9fc 804+}
805+
806+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
807+ const aufs_bindex_t bend)
808+{
809+ struct au_hdentry *hdp, *p;
810+
1308ab2a 811+ AuRwMustWriteLock(&dinfo->di_rwsem);
812+
4a4d8108 813+ hdp = dinfo->di_hdentry;
1facf9fc 814+ if (bindex < bend)
4a4d8108
AM
815+ memmove(hdp + bindex, hdp + bindex + 1,
816+ sizeof(*hdp) * (bend - bindex));
817+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 818+ dinfo->di_bend--;
819+
4a4d8108 820+ p = krealloc(hdp, sizeof(*p) * bend, GFP_NOFS);
1facf9fc 821+ if (p)
822+ dinfo->di_hdentry = p;
4a4d8108 823+ /* harmless error */
1facf9fc 824+}
825+
826+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
827+ const aufs_bindex_t bend)
828+{
829+ struct au_hinode *hip, *p;
830+
1308ab2a 831+ AuRwMustWriteLock(&iinfo->ii_rwsem);
832+
1facf9fc 833+ hip = iinfo->ii_hinode + bindex;
834+ if (bindex < bend)
835+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
836+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 837+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 838+ iinfo->ii_bend--;
839+
840+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
841+ if (p)
842+ iinfo->ii_hinode = p;
4a4d8108 843+ /* harmless error */
1facf9fc 844+}
845+
846+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
847+ struct au_branch *br)
848+{
849+ aufs_bindex_t bend;
850+ struct au_sbinfo *sbinfo;
851+ struct dentry *root;
852+ struct inode *inode;
853+
dece6358
AM
854+ SiMustWriteLock(sb);
855+
1facf9fc 856+ root = sb->s_root;
857+ inode = root->d_inode;
4a4d8108 858+ au_plink_maint_block(sb);
1facf9fc 859+ sbinfo = au_sbi(sb);
860+ bend = sbinfo->si_bend;
861+
862+ dput(au_h_dptr(root, bindex));
863+ au_hiput(au_hi(inode, bindex));
864+ au_br_do_free(br);
865+
866+ au_br_do_del_brp(sbinfo, bindex, bend);
867+ au_br_do_del_hdp(au_di(root), bindex, bend);
868+ au_br_do_del_hip(au_ii(inode), bindex, bend);
869+}
870+
871+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
872+{
873+ int err, rerr, i;
874+ unsigned int mnt_flags;
875+ aufs_bindex_t bindex, bend, br_id;
876+ unsigned char do_wh, verbose;
877+ struct au_branch *br;
878+ struct au_wbr *wbr;
879+
880+ err = 0;
881+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
882+ if (bindex < 0) {
883+ if (remount)
884+ goto out; /* success */
885+ err = -ENOENT;
4a4d8108 886+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 887+ goto out;
888+ }
889+ AuDbg("bindex b%d\n", bindex);
890+
891+ err = -EBUSY;
892+ mnt_flags = au_mntflags(sb);
893+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
894+ bend = au_sbend(sb);
895+ if (unlikely(!bend)) {
896+ AuVerbose(verbose, "no more branches left\n");
897+ goto out;
898+ }
899+ br = au_sbr(sb, bindex);
900+ i = atomic_read(&br->br_count);
901+ if (unlikely(i)) {
902+ AuVerbose(verbose, "%d file(s) opened\n", i);
903+ goto out;
904+ }
905+
906+ wbr = br->br_wbr;
907+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
908+ if (do_wh) {
1308ab2a 909+ /* instead of WbrWhMustWriteLock(wbr) */
910+ SiMustWriteLock(sb);
1facf9fc 911+ for (i = 0; i < AuBrWh_Last; i++) {
912+ dput(wbr->wbr_wh[i]);
913+ wbr->wbr_wh[i] = NULL;
914+ }
915+ }
916+
917+ err = test_children_busy(sb->s_root, bindex);
918+ if (unlikely(err)) {
919+ if (do_wh)
920+ goto out_wh;
921+ goto out;
922+ }
923+
924+ err = 0;
925+ br_id = br->br_id;
926+ if (!remount)
927+ au_br_do_del(sb, bindex, br);
928+ else {
929+ sysaufs_brs_del(sb, bindex);
930+ au_br_do_del(sb, bindex, br);
931+ sysaufs_brs_add(sb, bindex);
932+ }
933+
1308ab2a 934+ if (!bindex) {
1facf9fc 935+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 936+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
937+ } else
1facf9fc 938+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
939+ if (au_opt_test(mnt_flags, PLINK))
940+ au_plink_half_refresh(sb, br_id);
941+
1facf9fc 942+ if (au_xino_brid(sb) == br->br_id)
943+ au_xino_brid_set(sb, -1);
944+ goto out; /* success */
945+
946+ out_wh:
947+ /* revert */
948+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
949+ if (rerr)
4a4d8108
AM
950+ pr_warning("failed re-creating base whiteout, %s. (%d)\n",
951+ del->pathname, rerr);
1facf9fc 952+ out:
953+ return err;
954+}
955+
956+/* ---------------------------------------------------------------------- */
957+
958+/*
959+ * change a branch permission
960+ */
961+
dece6358
AM
962+static void au_warn_ima(void)
963+{
964+#ifdef CONFIG_IMA
1308ab2a 965+ /* since it doesn't support mark_files_ro() */
4a4d8108 966+ pr_warning("RW -> RO makes IMA to produce wrong message");
dece6358
AM
967+#endif
968+}
969+
1facf9fc 970+static int do_need_sigen_inc(int a, int b)
971+{
972+ return au_br_whable(a) && !au_br_whable(b);
973+}
974+
975+static int need_sigen_inc(int old, int new)
976+{
977+ return do_need_sigen_inc(old, new)
978+ || do_need_sigen_inc(new, old);
979+}
980+
981+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
982+{
983+ int err;
984+ unsigned long n, ul, bytes, files;
985+ aufs_bindex_t bstart;
986+ struct file *file, *hf, **a;
987+ const int step_bytes = 1024, /* memory allocation unit */
988+ step_files = step_bytes / sizeof(*a);
989+
990+ err = -ENOMEM;
991+ n = 0;
992+ bytes = step_bytes;
993+ files = step_files;
994+ a = kmalloc(bytes, GFP_NOFS);
995+ if (unlikely(!a))
996+ goto out;
997+
998+ /* no need file_list_lock() since sbinfo is locked? defered? */
999+ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
1000+ if (special_file(file->f_dentry->d_inode->i_mode))
1001+ continue;
1002+
1003+ AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
1004+ fi_read_lock(file);
1005+ if (unlikely(au_test_mmapped(file))) {
1006+ err = -EBUSY;
1007+ FiMustNoWaiters(file);
1008+ fi_read_unlock(file);
1009+ goto out_free;
1010+ }
1011+
1012+ bstart = au_fbstart(file);
1013+ if (!S_ISREG(file->f_dentry->d_inode->i_mode)
1014+ || !(file->f_mode & FMODE_WRITE)
1015+ || bstart != bindex) {
1016+ FiMustNoWaiters(file);
1017+ fi_read_unlock(file);
1018+ continue;
1019+ }
1020+
4a4d8108 1021+ hf = au_hf_top(file);
1facf9fc 1022+ FiMustNoWaiters(file);
1023+ fi_read_unlock(file);
1024+
1025+ if (n < files)
1026+ a[n++] = hf;
1027+ else {
1028+ void *p;
1029+
1030+ err = -ENOMEM;
1031+ bytes += step_bytes;
1032+ files += step_files;
1033+ p = krealloc(a, bytes, GFP_NOFS);
1034+ if (p) {
1035+ a = p;
1036+ a[n++] = hf;
1037+ } else
1038+ goto out_free;
1039+ }
1040+ }
1041+
1042+ err = 0;
dece6358
AM
1043+ if (n)
1044+ au_warn_ima();
1facf9fc 1045+ for (ul = 0; ul < n; ul++) {
1046+ /* todo: already flushed? */
1047+ /* cf. fs/super.c:mark_files_ro() */
1048+ hf = a[ul];
1049+ hf->f_mode &= ~FMODE_WRITE;
1050+ if (!file_check_writeable(hf)) {
1051+ file_release_write(hf);
1052+ mnt_drop_write(hf->f_vfsmnt);
1053+ }
1054+ }
1055+
1056+ out_free:
1057+ kfree(a);
1058+ out:
1059+ return err;
1060+}
1061+
1062+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1063+ int *do_update)
1064+{
1065+ int err, rerr;
1066+ aufs_bindex_t bindex;
1308ab2a 1067+ struct path path;
1facf9fc 1068+ struct dentry *root;
1069+ struct au_branch *br;
1070+
1071+ root = sb->s_root;
4a4d8108 1072+ au_plink_maint_block(sb);
1facf9fc 1073+ bindex = au_find_dbindex(root, mod->h_root);
1074+ if (bindex < 0) {
1075+ if (remount)
1076+ return 0; /* success */
1077+ err = -ENOENT;
4a4d8108 1078+ pr_err("%s no such branch\n", mod->path);
1facf9fc 1079+ goto out;
1080+ }
1081+ AuDbg("bindex b%d\n", bindex);
1082+
1083+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
1084+ if (unlikely(err))
1085+ goto out;
1086+
1087+ br = au_sbr(sb, bindex);
1088+ if (br->br_perm == mod->perm)
1089+ return 0; /* success */
1090+
1091+ if (au_br_writable(br->br_perm)) {
1092+ /* remove whiteout base */
1093+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
1094+ if (unlikely(err))
1095+ goto out;
1096+
1097+ if (!au_br_writable(mod->perm)) {
1098+ /* rw --> ro, file might be mmapped */
1099+ DiMustNoWaiters(root);
1100+ IiMustNoWaiters(root->d_inode);
1101+ di_write_unlock(root);
1102+ err = au_br_mod_files_ro(sb, bindex);
1103+ /* aufs_write_lock() calls ..._child() */
1104+ di_write_lock_child(root);
1105+
1106+ if (unlikely(err)) {
1107+ rerr = -ENOMEM;
1108+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
1109+ GFP_NOFS);
1308ab2a 1110+ if (br->br_wbr) {
1111+ path.mnt = br->br_mnt;
1112+ path.dentry = mod->h_root;
1113+ rerr = au_wbr_init(br, sb, br->br_perm,
1114+ &path);
1115+ }
1facf9fc 1116+ if (unlikely(rerr)) {
1117+ AuIOErr("nested error %d (%d)\n",
1118+ rerr, err);
1119+ br->br_perm = mod->perm;
1120+ }
1121+ }
1122+ }
1123+ } else if (au_br_writable(mod->perm)) {
1124+ /* ro --> rw */
1125+ err = -ENOMEM;
1126+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1127+ if (br->br_wbr) {
1308ab2a 1128+ path.mnt = br->br_mnt;
1129+ path.dentry = mod->h_root;
1facf9fc 1130+ err = au_wbr_init(br, sb, mod->perm, &path);
1131+ if (unlikely(err)) {
1132+ kfree(br->br_wbr);
1133+ br->br_wbr = NULL;
1134+ }
1135+ }
1136+ }
1137+
1138+ if (!err) {
1139+ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
1140+ br->br_perm = mod->perm;
1141+ }
1142+
1143+ out:
1144+ return err;
1145+}
4a4d8108
AM
1146diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/branch.h linux-2.6.34/fs/aufs/branch.h
1147--- linux-2.6.34.org/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
1148+++ linux-2.6.34/fs/aufs/branch.h 2010-05-31 22:15:32.000000000 +0200
1149@@ -0,0 +1,225 @@
1facf9fc 1150+/*
4a4d8108 1151+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1152+ *
1153+ * This program, aufs is free software; you can redistribute it and/or modify
1154+ * it under the terms of the GNU General Public License as published by
1155+ * the Free Software Foundation; either version 2 of the License, or
1156+ * (at your option) any later version.
dece6358
AM
1157+ *
1158+ * This program is distributed in the hope that it will be useful,
1159+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1160+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1161+ * GNU General Public License for more details.
1162+ *
1163+ * You should have received a copy of the GNU General Public License
1164+ * along with this program; if not, write to the Free Software
1165+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1166+ */
1167+
1168+/*
1169+ * branch filesystems and xino for them
1170+ */
1171+
1172+#ifndef __AUFS_BRANCH_H__
1173+#define __AUFS_BRANCH_H__
1174+
1175+#ifdef __KERNEL__
1176+
1177+#include <linux/fs.h>
1178+#include <linux/mount.h>
1facf9fc 1179+#include <linux/aufs_type.h>
4a4d8108 1180+#include "dynop.h"
1facf9fc 1181+#include "rwsem.h"
1182+#include "super.h"
1183+
1184+/* ---------------------------------------------------------------------- */
1185+
1186+/* a xino file */
1187+struct au_xino_file {
1188+ struct file *xi_file;
1189+ struct mutex xi_nondir_mtx;
1190+
1191+ /* todo: make xino files an array to support huge inode number */
1192+
1193+#ifdef CONFIG_DEBUG_FS
1194+ struct dentry *xi_dbgaufs;
1195+#endif
1196+};
1197+
1198+/* members for writable branch only */
1199+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
1200+struct au_wbr {
dece6358 1201+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 1202+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 1203+ atomic_t wbr_wh_running;
1facf9fc 1204+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
1205+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
1206+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
1207+
1208+ /* mfs mode */
1209+ unsigned long long wbr_bytes;
1210+};
1211+
4a4d8108
AM
1212+/* ext2 has 3 types of operations at least, ext3 has 4 */
1213+#define AuBrDynOp (AuDyLast * 4)
1214+
1facf9fc 1215+/* protected by superblock rwsem */
1216+struct au_branch {
1217+ struct au_xino_file br_xino;
1218+
1219+ aufs_bindex_t br_id;
1220+
1221+ int br_perm;
1222+ struct vfsmount *br_mnt;
4a4d8108
AM
1223+ spinlock_t br_dykey_lock;
1224+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 1225+ atomic_t br_count;
1226+
1227+ struct au_wbr *br_wbr;
1228+
1229+ /* xino truncation */
1230+ blkcnt_t br_xino_upper; /* watermark in blocks */
1231+ atomic_t br_xino_running;
1232+
1233+#ifdef CONFIG_SYSFS
1234+ /* an entry under sysfs per mount-point */
1235+ char br_name[8];
1236+ struct attribute br_attr;
1237+#endif
1238+};
1239+
1240+/* ---------------------------------------------------------------------- */
1241+
1242+/* branch permission and attribute */
1243+enum {
1244+ AuBrPerm_RW, /* writable, linkable wh */
1245+ AuBrPerm_RO, /* readonly, no wh */
1246+ AuBrPerm_RR, /* natively readonly, no wh */
1247+
1248+ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
1249+
1250+ AuBrPerm_ROWH, /* whiteout-able */
1251+ AuBrPerm_RRWH, /* whiteout-able */
1252+
1253+ AuBrPerm_Last
1254+};
1255+
1256+static inline int au_br_writable(int brperm)
1257+{
1258+ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1259+}
1260+
1261+static inline int au_br_whable(int brperm)
1262+{
1263+ return brperm == AuBrPerm_RW
1264+ || brperm == AuBrPerm_ROWH
1265+ || brperm == AuBrPerm_RRWH;
1266+}
1267+
1268+static inline int au_br_rdonly(struct au_branch *br)
1269+{
1270+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1271+ || !au_br_writable(br->br_perm))
1272+ ? -EROFS : 0;
1273+}
1274+
4a4d8108 1275+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 1276+{
4a4d8108 1277+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 1278+ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1279+#else
1280+ return 0;
1281+#endif
1282+}
1283+
1284+/* ---------------------------------------------------------------------- */
1285+
1286+/* branch.c */
1287+struct au_sbinfo;
1288+void au_br_free(struct au_sbinfo *sinfo);
1289+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1290+struct au_opt_add;
1291+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1292+struct au_opt_del;
1293+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
1294+struct au_opt_mod;
1295+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1296+ int *do_update);
1297+
1298+/* xino.c */
1299+static const loff_t au_loff_max = LLONG_MAX;
1300+
1301+int au_xib_trunc(struct super_block *sb);
1302+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1303+ loff_t *pos);
1304+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1305+ loff_t *pos);
1306+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
1307+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1308+ino_t au_xino_new_ino(struct super_block *sb);
1309+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1310+ ino_t ino);
1311+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1312+ ino_t ino);
1313+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1314+ ino_t *ino);
1315+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1316+ struct file *base_file, int do_test);
1317+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1318+
1319+struct au_opt_xino;
1320+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1321+void au_xino_clr(struct super_block *sb);
1322+struct file *au_xino_def(struct super_block *sb);
1323+int au_xino_path(struct seq_file *seq, struct file *file);
1324+
1325+/* ---------------------------------------------------------------------- */
1326+
1327+/* Superblock to branch */
1328+static inline
1329+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1330+{
1331+ return au_sbr(sb, bindex)->br_id;
1332+}
1333+
1334+static inline
1335+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1336+{
1337+ return au_sbr(sb, bindex)->br_mnt;
1338+}
1339+
1340+static inline
1341+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1342+{
1343+ return au_sbr_mnt(sb, bindex)->mnt_sb;
1344+}
1345+
1346+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1347+{
dece6358 1348+ atomic_dec_return(&au_sbr(sb, bindex)->br_count);
1facf9fc 1349+}
1350+
1351+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1352+{
1353+ return au_sbr(sb, bindex)->br_perm;
1354+}
1355+
1356+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1357+{
1358+ return au_br_whable(au_sbr_perm(sb, bindex));
1359+}
1360+
1361+/* ---------------------------------------------------------------------- */
1362+
1363+/*
1364+ * wbr_wh_read_lock, wbr_wh_write_lock
1365+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
1366+ */
1367+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
1368+
dece6358
AM
1369+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
1370+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
1371+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
1372+
1facf9fc 1373+#endif /* __KERNEL__ */
1374+#endif /* __AUFS_BRANCH_H__ */
4a4d8108
AM
1375diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/conf.mk linux-2.6.34/fs/aufs/conf.mk
1376--- linux-2.6.34.org/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
1377+++ linux-2.6.34/fs/aufs/conf.mk 2010-05-31 22:15:32.000000000 +0200
1378@@ -0,0 +1,33 @@
1379+
1380+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
1381+
1382+define AuConf
1383+ifdef ${1}
1384+AuConfStr += ${1}=${${1}}
1385+endif
1386+endef
1387+
1388+$(foreach i, BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
1389+ HNOTIFY HFSNOTIFY HINOTIFY \
1390+ EXPORT INO_T_64 \
1391+ RDU \
1392+ SP_IATTR \
1393+ SHWH \
1394+ BR_RAMFS \
1395+ BR_FUSE POLL \
1396+ BR_HFSPLUS \
1397+ BDEV_LOOP \
1398+ DEBUG MAGIC_SYSRQ, \
1399+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
1400+
1401+AuConfName = ${obj}/conf.str
1402+${AuConfName}.tmp: FORCE
1403+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
1404+${AuConfName}: ${AuConfName}.tmp
1405+ @diff -q $< $@ > /dev/null 2>&1 || { \
1406+ echo ' GEN ' $@; \
1407+ cp -p $< $@; \
1408+ }
1409+FORCE:
1410+clean-files += ${AuConfName} ${AuConfName}.tmp
1411+${obj}/sysfs.o: ${AuConfName}
1412diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/cpup.c linux-2.6.34/fs/aufs/cpup.c
1413--- linux-2.6.34.org/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
1414+++ linux-2.6.34/fs/aufs/cpup.c 2010-05-31 22:15:32.000000000 +0200
1415@@ -0,0 +1,1057 @@
1facf9fc 1416+/*
4a4d8108 1417+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1418+ *
1419+ * This program, aufs is free software; you can redistribute it and/or modify
1420+ * it under the terms of the GNU General Public License as published by
1421+ * the Free Software Foundation; either version 2 of the License, or
1422+ * (at your option) any later version.
dece6358
AM
1423+ *
1424+ * This program is distributed in the hope that it will be useful,
1425+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1426+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1427+ * GNU General Public License for more details.
1428+ *
1429+ * You should have received a copy of the GNU General Public License
1430+ * along with this program; if not, write to the Free Software
1431+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1432+ */
1433+
1434+/*
1435+ * copy-up functions, see wbr_policy.c for copy-down
1436+ */
1437+
dece6358 1438+#include <linux/file.h>
1facf9fc 1439+#include <linux/fs_stack.h>
dece6358 1440+#include <linux/mm.h>
1facf9fc 1441+#include <linux/uaccess.h>
1442+#include "aufs.h"
1443+
1444+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
1445+{
1446+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
1447+ | S_NOATIME | S_NOCMTIME;
1448+
1449+ dst->i_flags |= src->i_flags & ~mask;
1450+ if (au_test_fs_notime(dst->i_sb))
1451+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
1452+}
1453+
1454+void au_cpup_attr_timesizes(struct inode *inode)
1455+{
1456+ struct inode *h_inode;
1457+
1458+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1459+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 1460+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 1461+}
1462+
1463+void au_cpup_attr_nlink(struct inode *inode, int force)
1464+{
1465+ struct inode *h_inode;
1466+ struct super_block *sb;
1467+ aufs_bindex_t bindex, bend;
1468+
1469+ sb = inode->i_sb;
1470+ bindex = au_ibstart(inode);
1471+ h_inode = au_h_iptr(inode, bindex);
1472+ if (!force
1473+ && !S_ISDIR(h_inode->i_mode)
1474+ && au_opt_test(au_mntflags(sb), PLINK)
1475+ && au_plink_test(inode))
1476+ return;
1477+
1478+ inode->i_nlink = h_inode->i_nlink;
1479+
1480+ /*
1481+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
1482+ * it may includes whplink directory.
1483+ */
1484+ if (S_ISDIR(h_inode->i_mode)) {
1485+ bend = au_ibend(inode);
1486+ for (bindex++; bindex <= bend; bindex++) {
1487+ h_inode = au_h_iptr(inode, bindex);
1488+ if (h_inode)
1489+ au_add_nlink(inode, h_inode);
1490+ }
1491+ }
1492+}
1493+
1494+void au_cpup_attr_changeable(struct inode *inode)
1495+{
1496+ struct inode *h_inode;
1497+
1498+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1499+ inode->i_mode = h_inode->i_mode;
1500+ inode->i_uid = h_inode->i_uid;
1501+ inode->i_gid = h_inode->i_gid;
1502+ au_cpup_attr_timesizes(inode);
1503+ au_cpup_attr_flags(inode, h_inode);
1504+}
1505+
1506+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
1507+{
1508+ struct au_iinfo *iinfo = au_ii(inode);
1509+
1308ab2a 1510+ IiMustWriteLock(inode);
1511+
1facf9fc 1512+ iinfo->ii_higen = h_inode->i_generation;
1513+ iinfo->ii_hsb1 = h_inode->i_sb;
1514+}
1515+
1516+void au_cpup_attr_all(struct inode *inode, int force)
1517+{
1518+ struct inode *h_inode;
1519+
1520+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1521+ au_cpup_attr_changeable(inode);
1522+ if (inode->i_nlink > 0)
1523+ au_cpup_attr_nlink(inode, force);
1524+ inode->i_rdev = h_inode->i_rdev;
1525+ inode->i_blkbits = h_inode->i_blkbits;
1526+ au_cpup_igen(inode, h_inode);
1527+}
1528+
1529+/* ---------------------------------------------------------------------- */
1530+
1531+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
1532+
1533+/* keep the timestamps of the parent dir when cpup */
1534+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
1535+ struct path *h_path)
1536+{
1537+ struct inode *h_inode;
1538+
1539+ dt->dt_dentry = dentry;
1540+ dt->dt_h_path = *h_path;
1541+ h_inode = h_path->dentry->d_inode;
1542+ dt->dt_atime = h_inode->i_atime;
1543+ dt->dt_mtime = h_inode->i_mtime;
1544+ /* smp_mb(); */
1545+}
1546+
1547+void au_dtime_revert(struct au_dtime *dt)
1548+{
1549+ struct iattr attr;
1550+ int err;
1551+
1552+ attr.ia_atime = dt->dt_atime;
1553+ attr.ia_mtime = dt->dt_mtime;
1554+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
1555+ | ATTR_ATIME | ATTR_ATIME_SET;
1556+
1557+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
1558+ if (unlikely(err))
4a4d8108 1559+ pr_warning("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 1560+}
1561+
1562+/* ---------------------------------------------------------------------- */
1563+
1564+static noinline_for_stack
1565+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
1566+{
1567+ int err, sbits;
1568+ struct iattr ia;
1569+ struct path h_path;
1308ab2a 1570+ struct inode *h_isrc, *h_idst;
1facf9fc 1571+
1572+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 1573+ h_idst = h_path.dentry->d_inode;
1facf9fc 1574+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
1575+ h_isrc = h_src->d_inode;
1308ab2a 1576+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 1577+ | ATTR_ATIME | ATTR_MTIME
1578+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 1579+ ia.ia_uid = h_isrc->i_uid;
1580+ ia.ia_gid = h_isrc->i_gid;
1581+ ia.ia_atime = h_isrc->i_atime;
1582+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 1583+ if (h_idst->i_mode != h_isrc->i_mode
1584+ && !S_ISLNK(h_idst->i_mode)) {
1585+ ia.ia_valid |= ATTR_MODE;
1586+ ia.ia_mode = h_isrc->i_mode;
1587+ }
1588+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
1589+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 1590+ err = vfsub_notify_change(&h_path, &ia);
1591+
1592+ /* is this nfs only? */
1593+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
1594+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
1595+ ia.ia_mode = h_isrc->i_mode;
1596+ err = vfsub_notify_change(&h_path, &ia);
1597+ }
1598+
1599+ return err;
1600+}
1601+
1602+/* ---------------------------------------------------------------------- */
1603+
1604+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
1605+ char *buf, unsigned long blksize)
1606+{
1607+ int err;
1608+ size_t sz, rbytes, wbytes;
1609+ unsigned char all_zero;
1610+ char *p, *zp;
1611+ struct mutex *h_mtx;
1612+ /* reduce stack usage */
1613+ struct iattr *ia;
1614+
1615+ zp = page_address(ZERO_PAGE(0));
1616+ if (unlikely(!zp))
1617+ return -ENOMEM; /* possible? */
1618+
1619+ err = 0;
1620+ all_zero = 0;
1621+ while (len) {
1622+ AuDbg("len %lld\n", len);
1623+ sz = blksize;
1624+ if (len < blksize)
1625+ sz = len;
1626+
1627+ rbytes = 0;
1628+ /* todo: signal_pending? */
1629+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
1630+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
1631+ err = rbytes;
1632+ }
1633+ if (unlikely(err < 0))
1634+ break;
1635+
1636+ all_zero = 0;
1637+ if (len >= rbytes && rbytes == blksize)
1638+ all_zero = !memcmp(buf, zp, rbytes);
1639+ if (!all_zero) {
1640+ wbytes = rbytes;
1641+ p = buf;
1642+ while (wbytes) {
1643+ size_t b;
1644+
1645+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
1646+ err = b;
1647+ /* todo: signal_pending? */
1648+ if (unlikely(err == -EAGAIN || err == -EINTR))
1649+ continue;
1650+ if (unlikely(err < 0))
1651+ break;
1652+ wbytes -= b;
1653+ p += b;
1654+ }
1655+ } else {
1656+ loff_t res;
1657+
1658+ AuLabel(hole);
1659+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
1660+ err = res;
1661+ if (unlikely(res < 0))
1662+ break;
1663+ }
1664+ len -= rbytes;
1665+ err = 0;
1666+ }
1667+
1668+ /* the last block may be a hole */
1669+ if (!err && all_zero) {
1670+ AuLabel(last hole);
1671+
1672+ err = 1;
1673+ if (au_test_nfs(dst->f_dentry->d_sb)) {
1674+ /* nfs requires this step to make last hole */
1675+ /* is this only nfs? */
1676+ do {
1677+ /* todo: signal_pending? */
1678+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
1679+ } while (err == -EAGAIN || err == -EINTR);
1680+ if (err == 1)
1681+ dst->f_pos--;
1682+ }
1683+
1684+ if (err == 1) {
1685+ ia = (void *)buf;
1686+ ia->ia_size = dst->f_pos;
1687+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
1688+ ia->ia_file = dst;
1689+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
1690+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
1691+ err = vfsub_notify_change(&dst->f_path, ia);
1692+ mutex_unlock(h_mtx);
1693+ }
1694+ }
1695+
1696+ return err;
1697+}
1698+
1699+int au_copy_file(struct file *dst, struct file *src, loff_t len)
1700+{
1701+ int err;
1702+ unsigned long blksize;
1703+ unsigned char do_kfree;
1704+ char *buf;
1705+
1706+ err = -ENOMEM;
1707+ blksize = dst->f_dentry->d_sb->s_blocksize;
1708+ if (!blksize || PAGE_SIZE < blksize)
1709+ blksize = PAGE_SIZE;
1710+ AuDbg("blksize %lu\n", blksize);
1711+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
1712+ if (do_kfree)
1713+ buf = kmalloc(blksize, GFP_NOFS);
1714+ else
1715+ buf = (void *)__get_free_page(GFP_NOFS);
1716+ if (unlikely(!buf))
1717+ goto out;
1718+
1719+ if (len > (1 << 22))
1720+ AuDbg("copying a large file %lld\n", (long long)len);
1721+
1722+ src->f_pos = 0;
1723+ dst->f_pos = 0;
1724+ err = au_do_copy_file(dst, src, len, buf, blksize);
1725+ if (do_kfree)
1726+ kfree(buf);
1727+ else
1728+ free_page((unsigned long)buf);
1729+
1730+ out:
1731+ return err;
1732+}
1733+
1734+/*
1735+ * to support a sparse file which is opened with O_APPEND,
1736+ * we need to close the file.
1737+ */
1738+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 1739+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 1740+{
1741+ int err, i;
1742+ enum { SRC, DST };
1743+ struct {
1744+ aufs_bindex_t bindex;
1745+ unsigned int flags;
1746+ struct dentry *dentry;
1747+ struct file *file;
1748+ void *label, *label_file;
1749+ } *f, file[] = {
1750+ {
1751+ .bindex = bsrc,
1752+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
1753+ .file = NULL,
1754+ .label = &&out,
1755+ .label_file = &&out_src
1756+ },
1757+ {
1758+ .bindex = bdst,
1759+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
1760+ .file = NULL,
1761+ .label = &&out_src,
1762+ .label_file = &&out_dst
1763+ }
1764+ };
1765+ struct super_block *sb;
1766+
1767+ /* bsrc branch can be ro/rw. */
1768+ sb = dentry->d_sb;
1769+ f = file;
1770+ for (i = 0; i < 2; i++, f++) {
1771+ f->dentry = au_h_dptr(dentry, f->bindex);
1772+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
1773+ err = PTR_ERR(f->file);
1774+ if (IS_ERR(f->file))
1775+ goto *f->label;
1776+ err = -EINVAL;
1777+ if (unlikely(!f->file->f_op))
1778+ goto *f->label_file;
1779+ }
1780+
1781+ /* try stopping to update while we copyup */
1782+ IMustLock(file[SRC].dentry->d_inode);
1783+ err = au_copy_file(file[DST].file, file[SRC].file, len);
1784+
1785+ out_dst:
1786+ fput(file[DST].file);
1787+ au_sbr_put(sb, file[DST].bindex);
1788+ out_src:
1789+ fput(file[SRC].file);
1790+ au_sbr_put(sb, file[SRC].bindex);
1791+ out:
1792+ return err;
1793+}
1794+
1795+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
1796+ aufs_bindex_t bsrc, loff_t len,
1797+ struct inode *h_dir, struct path *h_path)
1798+{
1799+ int err, rerr;
1800+ loff_t l;
1801+
1802+ err = 0;
1803+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
1804+ if (len == -1 || l < len)
1805+ len = l;
1806+ if (len)
1807+ err = au_cp_regular(dentry, bdst, bsrc, len);
1808+ if (!err)
1809+ goto out; /* success */
1810+
1811+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
1812+ if (rerr) {
1813+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
1814+ AuDLNPair(h_path->dentry), err, rerr);
1815+ err = -EIO;
1816+ }
1817+
1818+ out:
1819+ return err;
1820+}
1821+
1822+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
1823+ struct inode *h_dir)
1824+{
1825+ int err, symlen;
1826+ mm_segment_t old_fs;
1827+ char *sym;
1828+
1829+ err = -ENOSYS;
1830+ if (unlikely(!h_src->d_inode->i_op->readlink))
1831+ goto out;
1832+
1833+ err = -ENOMEM;
4a4d8108 1834+ sym = __getname_gfp(GFP_NOFS);
1facf9fc 1835+ if (unlikely(!sym))
1836+ goto out;
1837+
1838+ old_fs = get_fs();
1839+ set_fs(KERNEL_DS);
1840+ symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
1841+ PATH_MAX);
1842+ err = symlen;
1843+ set_fs(old_fs);
1844+
1845+ if (symlen > 0) {
1846+ sym[symlen] = 0;
1847+ err = vfsub_symlink(h_dir, h_path, sym);
1848+ }
1849+ __putname(sym);
1850+
1851+ out:
1852+ return err;
1853+}
1854+
1855+/* return with the lower dst inode is locked */
1856+static noinline_for_stack
1857+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
1858+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
1859+ struct dentry *dst_parent)
1860+{
1861+ int err;
1862+ umode_t mode;
1863+ unsigned int mnt_flags;
1864+ unsigned char isdir;
1865+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
1866+ struct au_dtime dt;
1867+ struct path h_path;
1868+ struct dentry *h_src, *h_dst, *h_parent;
1869+ struct inode *h_inode, *h_dir;
1870+ struct super_block *sb;
1871+
1872+ /* bsrc branch can be ro/rw. */
1873+ h_src = au_h_dptr(dentry, bsrc);
1874+ h_inode = h_src->d_inode;
1875+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
1876+
1877+ /* try stopping to be referenced while we are creating */
1878+ h_dst = au_h_dptr(dentry, bdst);
1879+ h_parent = h_dst->d_parent; /* dir inode is locked */
1880+ h_dir = h_parent->d_inode;
1881+ IMustLock(h_dir);
1882+ AuDebugOn(h_parent != h_dst->d_parent);
1883+
1884+ sb = dentry->d_sb;
1885+ h_path.mnt = au_sbr_mnt(sb, bdst);
1886+ if (do_dt) {
1887+ h_path.dentry = h_parent;
1888+ au_dtime_store(&dt, dst_parent, &h_path);
1889+ }
1890+ h_path.dentry = h_dst;
1891+
1892+ isdir = 0;
1893+ mode = h_inode->i_mode;
1894+ switch (mode & S_IFMT) {
1895+ case S_IFREG:
1896+ /* try stopping to update while we are referencing */
1897+ IMustLock(h_inode);
1898+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
1899+ if (!err)
1900+ err = au_do_cpup_regular
1901+ (dentry, bdst, bsrc, len,
1902+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
1903+ break;
1904+ case S_IFDIR:
1905+ isdir = 1;
1906+ err = vfsub_mkdir(h_dir, &h_path, mode);
1907+ if (!err) {
1908+ /*
1909+ * strange behaviour from the users view,
1910+ * particularry setattr case
1911+ */
1912+ if (au_ibstart(dst_parent->d_inode) == bdst)
1913+ au_cpup_attr_nlink(dst_parent->d_inode,
1914+ /*force*/1);
1915+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
1916+ }
1917+ break;
1918+ case S_IFLNK:
1919+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
1920+ break;
1921+ case S_IFCHR:
1922+ case S_IFBLK:
1923+ AuDebugOn(!capable(CAP_MKNOD));
1924+ /*FALLTHROUGH*/
1925+ case S_IFIFO:
1926+ case S_IFSOCK:
1927+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
1928+ break;
1929+ default:
1930+ AuIOErr("Unknown inode type 0%o\n", mode);
1931+ err = -EIO;
1932+ }
1933+
1934+ mnt_flags = au_mntflags(sb);
1935+ if (!au_opt_test(mnt_flags, UDBA_NONE)
1936+ && !isdir
1937+ && au_opt_test(mnt_flags, XINO)
1938+ && h_inode->i_nlink == 1
1939+ /* todo: unnecessary? */
1940+ /* && dentry->d_inode->i_nlink == 1 */
1941+ && bdst < bsrc
1942+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 1943+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 1944+ /* ignore this error */
1945+
1946+ if (do_dt)
1947+ au_dtime_revert(&dt);
1948+ return err;
1949+}
1950+
1951+/*
1952+ * copyup the @dentry from @bsrc to @bdst.
1953+ * the caller must set the both of lower dentries.
1954+ * @len is for truncating when it is -1 copyup the entire file.
1955+ * in link/rename cases, @dst_parent may be different from the real one.
1956+ */
1957+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
1958+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
1959+ struct dentry *dst_parent)
1960+{
1961+ int err, rerr;
1962+ aufs_bindex_t old_ibstart;
1963+ unsigned char isdir, plink;
1964+ struct au_dtime dt;
1965+ struct path h_path;
1966+ struct dentry *h_src, *h_dst, *h_parent;
1967+ struct inode *dst_inode, *h_dir, *inode;
1968+ struct super_block *sb;
1969+
1970+ AuDebugOn(bsrc <= bdst);
1971+
1972+ sb = dentry->d_sb;
1973+ h_path.mnt = au_sbr_mnt(sb, bdst);
1974+ h_dst = au_h_dptr(dentry, bdst);
1975+ h_parent = h_dst->d_parent; /* dir inode is locked */
1976+ h_dir = h_parent->d_inode;
1977+ IMustLock(h_dir);
1978+
1979+ h_src = au_h_dptr(dentry, bsrc);
1980+ inode = dentry->d_inode;
1981+
1982+ if (!dst_parent)
1983+ dst_parent = dget_parent(dentry);
1984+ else
1985+ dget(dst_parent);
1986+
1987+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
1988+ dst_inode = au_h_iptr(inode, bdst);
1989+ if (dst_inode) {
1990+ if (unlikely(!plink)) {
1991+ err = -EIO;
1992+ AuIOErr("i%lu exists on a upper branch "
1993+ "but plink is disabled\n", inode->i_ino);
1994+ goto out;
1995+ }
1996+
1997+ if (dst_inode->i_nlink) {
1998+ const int do_dt = au_ftest_cpup(flags, DTIME);
1999+
2000+ h_src = au_plink_lkup(inode, bdst);
2001+ err = PTR_ERR(h_src);
2002+ if (IS_ERR(h_src))
2003+ goto out;
2004+ if (unlikely(!h_src->d_inode)) {
2005+ err = -EIO;
2006+ AuIOErr("i%lu exists on a upper branch "
2007+ "but plink is broken\n", inode->i_ino);
2008+ dput(h_src);
2009+ goto out;
2010+ }
2011+
2012+ if (do_dt) {
2013+ h_path.dentry = h_parent;
2014+ au_dtime_store(&dt, dst_parent, &h_path);
2015+ }
2016+ h_path.dentry = h_dst;
2017+ err = vfsub_link(h_src, h_dir, &h_path);
2018+ if (do_dt)
2019+ au_dtime_revert(&dt);
2020+ dput(h_src);
2021+ goto out;
2022+ } else
2023+ /* todo: cpup_wh_file? */
2024+ /* udba work */
4a4d8108 2025+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 2026+ }
2027+
2028+ old_ibstart = au_ibstart(inode);
2029+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
2030+ if (unlikely(err))
2031+ goto out;
2032+ dst_inode = h_dst->d_inode;
2033+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
2034+
2035+ err = cpup_iattr(dentry, bdst, h_src);
2036+ isdir = S_ISDIR(dst_inode->i_mode);
2037+ if (!err) {
4a4d8108
AM
2038+ if (bdst < old_ibstart) {
2039+ if (S_ISREG(inode->i_mode)) {
2040+ err = au_dy_iaop(inode, bdst, dst_inode);
2041+ if (unlikely(err))
2042+ goto out_rev;
2043+ }
1facf9fc 2044+ au_set_ibstart(inode, bdst);
4a4d8108 2045+ }
1facf9fc 2046+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
2047+ au_hi_flags(inode, isdir));
2048+ mutex_unlock(&dst_inode->i_mutex);
2049+ if (!isdir
2050+ && h_src->d_inode->i_nlink > 1
2051+ && plink)
2052+ au_plink_append(inode, bdst, h_dst);
2053+ goto out; /* success */
2054+ }
2055+
2056+ /* revert */
4a4d8108 2057+out_rev:
1facf9fc 2058+ h_path.dentry = h_parent;
2059+ mutex_unlock(&dst_inode->i_mutex);
2060+ au_dtime_store(&dt, dst_parent, &h_path);
2061+ h_path.dentry = h_dst;
2062+ if (!isdir)
2063+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
2064+ else
2065+ rerr = vfsub_rmdir(h_dir, &h_path);
2066+ au_dtime_revert(&dt);
2067+ if (rerr) {
2068+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
2069+ err = -EIO;
2070+ }
2071+
2072+ out:
2073+ dput(dst_parent);
2074+ return err;
2075+}
2076+
2077+struct au_cpup_single_args {
2078+ int *errp;
2079+ struct dentry *dentry;
2080+ aufs_bindex_t bdst, bsrc;
2081+ loff_t len;
2082+ unsigned int flags;
2083+ struct dentry *dst_parent;
2084+};
2085+
2086+static void au_call_cpup_single(void *args)
2087+{
2088+ struct au_cpup_single_args *a = args;
2089+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
2090+ a->flags, a->dst_parent);
2091+}
2092+
2093+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2094+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2095+ struct dentry *dst_parent)
2096+{
2097+ int err, wkq_err;
2098+ umode_t mode;
2099+ struct dentry *h_dentry;
2100+
2101+ h_dentry = au_h_dptr(dentry, bsrc);
2102+ mode = h_dentry->d_inode->i_mode & S_IFMT;
2103+ if ((mode != S_IFCHR && mode != S_IFBLK)
2104+ || capable(CAP_MKNOD))
2105+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2106+ dst_parent);
2107+ else {
2108+ struct au_cpup_single_args args = {
2109+ .errp = &err,
2110+ .dentry = dentry,
2111+ .bdst = bdst,
2112+ .bsrc = bsrc,
2113+ .len = len,
2114+ .flags = flags,
2115+ .dst_parent = dst_parent
2116+ };
2117+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
2118+ if (unlikely(wkq_err))
2119+ err = wkq_err;
2120+ }
2121+
2122+ return err;
2123+}
2124+
2125+/*
2126+ * copyup the @dentry from the first active lower branch to @bdst,
2127+ * using au_cpup_single().
2128+ */
2129+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2130+ unsigned int flags)
2131+{
2132+ int err;
2133+ aufs_bindex_t bsrc, bend;
2134+
2135+ bend = au_dbend(dentry);
2136+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2137+ if (au_h_dptr(dentry, bsrc))
2138+ break;
2139+
2140+ err = au_lkup_neg(dentry, bdst);
2141+ if (!err) {
2142+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
2143+ if (!err)
2144+ return 0; /* success */
2145+
2146+ /* revert */
2147+ au_set_h_dptr(dentry, bdst, NULL);
2148+ au_set_dbstart(dentry, bsrc);
2149+ }
2150+
2151+ return err;
2152+}
2153+
2154+struct au_cpup_simple_args {
2155+ int *errp;
2156+ struct dentry *dentry;
2157+ aufs_bindex_t bdst;
2158+ loff_t len;
2159+ unsigned int flags;
2160+};
2161+
2162+static void au_call_cpup_simple(void *args)
2163+{
2164+ struct au_cpup_simple_args *a = args;
2165+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
2166+}
2167+
2168+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2169+ unsigned int flags)
2170+{
2171+ int err, wkq_err;
2172+ unsigned char do_sio;
2173+ struct dentry *parent;
2174+ struct inode *h_dir;
2175+
2176+ parent = dget_parent(dentry);
2177+ h_dir = au_h_iptr(parent->d_inode, bdst);
2178+ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
2179+ if (!do_sio) {
2180+ /*
2181+ * testing CAP_MKNOD is for generic fs,
2182+ * but CAP_FSETID is for xfs only, currently.
2183+ */
2184+ umode_t mode = dentry->d_inode->i_mode;
2185+ do_sio = (((mode & (S_IFCHR | S_IFBLK))
2186+ && !capable(CAP_MKNOD))
2187+ || ((mode & (S_ISUID | S_ISGID))
2188+ && !capable(CAP_FSETID)));
2189+ }
2190+ if (!do_sio)
2191+ err = au_cpup_simple(dentry, bdst, len, flags);
2192+ else {
2193+ struct au_cpup_simple_args args = {
2194+ .errp = &err,
2195+ .dentry = dentry,
2196+ .bdst = bdst,
2197+ .len = len,
2198+ .flags = flags
2199+ };
2200+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
2201+ if (unlikely(wkq_err))
2202+ err = wkq_err;
2203+ }
2204+
2205+ dput(parent);
2206+ return err;
2207+}
2208+
2209+/* ---------------------------------------------------------------------- */
2210+
2211+/*
2212+ * copyup the deleted file for writing.
2213+ */
2214+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2215+ struct dentry *wh_dentry, struct file *file,
2216+ loff_t len)
2217+{
2218+ int err;
2219+ aufs_bindex_t bstart;
2220+ struct au_dinfo *dinfo;
2221+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 2222+ struct au_hdentry *hdp;
1facf9fc 2223+
2224+ dinfo = au_di(dentry);
1308ab2a 2225+ AuRwMustWriteLock(&dinfo->di_rwsem);
2226+
1facf9fc 2227+ bstart = dinfo->di_bstart;
4a4d8108
AM
2228+ hdp = dinfo->di_hdentry;
2229+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 2230+ dinfo->di_bstart = bdst;
4a4d8108
AM
2231+ hdp[0 + bdst].hd_dentry = wh_dentry;
2232+ h_d_start = hdp[0 + bstart].hd_dentry;
1facf9fc 2233+ if (file)
4a4d8108 2234+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2235+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2236+ /*h_parent*/NULL);
2237+ if (!err && file) {
2238+ err = au_reopen_nondir(file);
4a4d8108 2239+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 2240+ }
4a4d8108 2241+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 2242+ dinfo->di_bstart = bstart;
2243+
2244+ return err;
2245+}
2246+
2247+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2248+ struct file *file)
2249+{
2250+ int err;
2251+ struct au_dtime dt;
2252+ struct dentry *parent, *h_parent, *wh_dentry;
2253+ struct au_branch *br;
2254+ struct path h_path;
2255+
2256+ br = au_sbr(dentry->d_sb, bdst);
2257+ parent = dget_parent(dentry);
2258+ h_parent = au_h_dptr(parent, bdst);
2259+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
2260+ err = PTR_ERR(wh_dentry);
2261+ if (IS_ERR(wh_dentry))
2262+ goto out;
2263+
2264+ h_path.dentry = h_parent;
2265+ h_path.mnt = br->br_mnt;
2266+ au_dtime_store(&dt, parent, &h_path);
2267+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
2268+ if (unlikely(err))
2269+ goto out_wh;
2270+
2271+ dget(wh_dentry);
2272+ h_path.dentry = wh_dentry;
4a4d8108
AM
2273+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
2274+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
2275+ else
2276+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 2277+ if (unlikely(err)) {
2278+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2279+ AuDLNPair(wh_dentry), err);
2280+ err = -EIO;
2281+ }
2282+ au_dtime_revert(&dt);
2283+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2284+
2285+ out_wh:
2286+ dput(wh_dentry);
2287+ out:
2288+ dput(parent);
2289+ return err;
2290+}
2291+
2292+struct au_cpup_wh_args {
2293+ int *errp;
2294+ struct dentry *dentry;
2295+ aufs_bindex_t bdst;
2296+ loff_t len;
2297+ struct file *file;
2298+};
2299+
2300+static void au_call_cpup_wh(void *args)
2301+{
2302+ struct au_cpup_wh_args *a = args;
2303+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
2304+}
2305+
2306+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2307+ struct file *file)
2308+{
2309+ int err, wkq_err;
2310+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
2311+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
2312+ struct au_wbr *wbr;
2313+
2314+ parent = dget_parent(dentry);
2315+ dir = parent->d_inode;
2316+ h_orph = NULL;
2317+ h_parent = NULL;
2318+ h_dir = au_igrab(au_h_iptr(dir, bdst));
2319+ h_tmpdir = h_dir;
2320+ if (!h_dir->i_nlink) {
2321+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
2322+ h_orph = wbr->wbr_orph;
2323+
2324+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 2325+ au_set_h_dptr(parent, bdst, dget(h_orph));
2326+ h_tmpdir = h_orph->d_inode;
1facf9fc 2327+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
2328+
2329+ /* this temporary unlock is safe */
2330+ if (file)
4a4d8108 2331+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2332+ else
2333+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
2334+ h_inode = h_dentry->d_inode;
2335+ IMustLock(h_inode);
2336+ mutex_unlock(&h_inode->i_mutex);
dece6358 2337+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 2338+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 2339+ /* todo: au_h_open_pre()? */
1facf9fc 2340+ }
2341+
2342+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
2343+ err = au_cpup_wh(dentry, bdst, len, file);
2344+ else {
2345+ struct au_cpup_wh_args args = {
2346+ .errp = &err,
2347+ .dentry = dentry,
2348+ .bdst = bdst,
2349+ .len = len,
2350+ .file = file
2351+ };
2352+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
2353+ if (unlikely(wkq_err))
2354+ err = wkq_err;
2355+ }
2356+
2357+ if (h_orph) {
2358+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 2359+ /* todo: au_h_open_post()? */
1facf9fc 2360+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 2361+ au_set_h_dptr(parent, bdst, h_parent);
2362+ }
2363+ iput(h_dir);
2364+ dput(parent);
2365+
2366+ return err;
2367+}
2368+
2369+/* ---------------------------------------------------------------------- */
2370+
2371+/*
2372+ * generic routine for both of copy-up and copy-down.
2373+ */
2374+/* cf. revalidate function in file.c */
2375+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2376+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2377+ struct dentry *h_parent, void *arg),
2378+ void *arg)
2379+{
2380+ int err;
2381+ struct au_pin pin;
2382+ struct dentry *d, *parent, *h_parent, *real_parent;
2383+
2384+ err = 0;
2385+ parent = dget_parent(dentry);
2386+ if (IS_ROOT(parent))
2387+ goto out;
2388+
2389+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
2390+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
2391+
2392+ /* do not use au_dpage */
2393+ real_parent = parent;
2394+ while (1) {
2395+ dput(parent);
2396+ parent = dget_parent(dentry);
2397+ h_parent = au_h_dptr(parent, bdst);
2398+ if (h_parent)
2399+ goto out; /* success */
2400+
2401+ /* find top dir which is necessary to cpup */
2402+ do {
2403+ d = parent;
2404+ dput(parent);
2405+ parent = dget_parent(d);
2406+ di_read_lock_parent3(parent, !AuLock_IR);
2407+ h_parent = au_h_dptr(parent, bdst);
2408+ di_read_unlock(parent, !AuLock_IR);
2409+ } while (!h_parent);
2410+
2411+ if (d != real_parent)
2412+ di_write_lock_child3(d);
2413+
2414+ /* somebody else might create while we were sleeping */
2415+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
2416+ if (au_h_dptr(d, bdst))
2417+ au_update_dbstart(d);
2418+
2419+ au_pin_set_dentry(&pin, d);
2420+ err = au_do_pin(&pin);
2421+ if (!err) {
2422+ err = cp(d, bdst, h_parent, arg);
2423+ au_unpin(&pin);
2424+ }
2425+ }
2426+
2427+ if (d != real_parent)
2428+ di_write_unlock(d);
2429+ if (unlikely(err))
2430+ break;
2431+ }
2432+
2433+ out:
2434+ dput(parent);
2435+ return err;
2436+}
2437+
2438+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
2439+ struct dentry *h_parent __maybe_unused ,
2440+ void *arg __maybe_unused)
2441+{
2442+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
2443+}
2444+
2445+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2446+{
2447+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
2448+}
2449+
2450+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2451+{
2452+ int err;
2453+ struct dentry *parent;
2454+ struct inode *dir;
2455+
2456+ parent = dget_parent(dentry);
2457+ dir = parent->d_inode;
2458+ err = 0;
2459+ if (au_h_iptr(dir, bdst))
2460+ goto out;
2461+
2462+ di_read_unlock(parent, AuLock_IR);
2463+ di_write_lock_parent(parent);
2464+ /* someone else might change our inode while we were sleeping */
2465+ if (!au_h_iptr(dir, bdst))
2466+ err = au_cpup_dirs(dentry, bdst);
2467+ di_downgrade_lock(parent, AuLock_IR);
2468+
2469+ out:
2470+ dput(parent);
2471+ return err;
2472+}
4a4d8108
AM
2473diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/cpup.h linux-2.6.34/fs/aufs/cpup.h
2474--- linux-2.6.34.org/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
2475+++ linux-2.6.34/fs/aufs/cpup.h 2010-05-31 22:15:32.000000000 +0200
dece6358 2476@@ -0,0 +1,81 @@
1facf9fc 2477+/*
4a4d8108 2478+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2479+ *
2480+ * This program, aufs is free software; you can redistribute it and/or modify
2481+ * it under the terms of the GNU General Public License as published by
2482+ * the Free Software Foundation; either version 2 of the License, or
2483+ * (at your option) any later version.
dece6358
AM
2484+ *
2485+ * This program is distributed in the hope that it will be useful,
2486+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2487+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2488+ * GNU General Public License for more details.
2489+ *
2490+ * You should have received a copy of the GNU General Public License
2491+ * along with this program; if not, write to the Free Software
2492+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2493+ */
2494+
2495+/*
2496+ * copy-up/down functions
2497+ */
2498+
2499+#ifndef __AUFS_CPUP_H__
2500+#define __AUFS_CPUP_H__
2501+
2502+#ifdef __KERNEL__
2503+
dece6358
AM
2504+#include <linux/path.h>
2505+#include <linux/time.h>
1facf9fc 2506+#include <linux/aufs_type.h>
2507+
dece6358
AM
2508+struct inode;
2509+struct file;
2510+
1facf9fc 2511+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
2512+void au_cpup_attr_timesizes(struct inode *inode);
2513+void au_cpup_attr_nlink(struct inode *inode, int force);
2514+void au_cpup_attr_changeable(struct inode *inode);
2515+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
2516+void au_cpup_attr_all(struct inode *inode, int force);
2517+
2518+/* ---------------------------------------------------------------------- */
2519+
2520+/* cpup flags */
2521+#define AuCpup_DTIME 1 /* do dtime_store/revert */
2522+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
2523+ for link(2) */
2524+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
2525+#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; }
2526+#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; }
2527+
2528+int au_copy_file(struct file *dst, struct file *src, loff_t len);
2529+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2530+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2531+ struct dentry *dst_parent);
2532+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2533+ unsigned int flags);
2534+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2535+ struct file *file);
2536+
2537+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2538+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2539+ struct dentry *h_parent, void *arg),
2540+ void *arg);
2541+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2542+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2543+
2544+/* ---------------------------------------------------------------------- */
2545+
2546+/* keep timestamps when copyup */
2547+struct au_dtime {
2548+ struct dentry *dt_dentry;
2549+ struct path dt_h_path;
2550+ struct timespec dt_atime, dt_mtime;
2551+};
2552+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
2553+ struct path *h_path);
2554+void au_dtime_revert(struct au_dtime *dt);
2555+
2556+#endif /* __KERNEL__ */
2557+#endif /* __AUFS_CPUP_H__ */
4a4d8108
AM
2558diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/dbgaufs.c linux-2.6.34/fs/aufs/dbgaufs.c
2559--- linux-2.6.34.org/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
2560+++ linux-2.6.34/fs/aufs/dbgaufs.c 2010-05-31 22:15:32.000000000 +0200
2561@@ -0,0 +1,334 @@
1facf9fc 2562+/*
4a4d8108 2563+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2564+ *
2565+ * This program, aufs is free software; you can redistribute it and/or modify
2566+ * it under the terms of the GNU General Public License as published by
2567+ * the Free Software Foundation; either version 2 of the License, or
2568+ * (at your option) any later version.
dece6358
AM
2569+ *
2570+ * This program is distributed in the hope that it will be useful,
2571+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2572+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2573+ * GNU General Public License for more details.
2574+ *
2575+ * You should have received a copy of the GNU General Public License
2576+ * along with this program; if not, write to the Free Software
2577+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2578+ */
2579+
2580+/*
2581+ * debugfs interface
2582+ */
2583+
2584+#include <linux/debugfs.h>
2585+#include "aufs.h"
2586+
2587+#ifndef CONFIG_SYSFS
2588+#error DEBUG_FS depends upon SYSFS
2589+#endif
2590+
2591+static struct dentry *dbgaufs;
2592+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
2593+
2594+/* 20 is max digits length of ulong 64 */
2595+struct dbgaufs_arg {
2596+ int n;
2597+ char a[20 * 4];
2598+};
2599+
2600+/*
2601+ * common function for all XINO files
2602+ */
2603+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
2604+ struct file *file)
2605+{
2606+ kfree(file->private_data);
2607+ return 0;
2608+}
2609+
2610+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
2611+{
2612+ int err;
2613+ struct kstat st;
2614+ struct dbgaufs_arg *p;
2615+
2616+ err = -ENOMEM;
2617+ p = kmalloc(sizeof(*p), GFP_NOFS);
2618+ if (unlikely(!p))
2619+ goto out;
2620+
2621+ err = 0;
2622+ p->n = 0;
2623+ file->private_data = p;
2624+ if (!xf)
2625+ goto out;
2626+
2627+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
2628+ if (!err) {
2629+ if (do_fcnt)
2630+ p->n = snprintf
2631+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
2632+ (long)file_count(xf), st.blocks, st.blksize,
2633+ (long long)st.size);
2634+ else
2635+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
2636+ st.blocks, st.blksize,
2637+ (long long)st.size);
2638+ AuDebugOn(p->n >= sizeof(p->a));
2639+ } else {
2640+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
2641+ err = 0;
2642+ }
2643+
2644+ out:
2645+ return err;
2646+
2647+}
2648+
2649+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
2650+ size_t count, loff_t *ppos)
2651+{
2652+ struct dbgaufs_arg *p;
2653+
2654+ p = file->private_data;
2655+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
2656+}
2657+
2658+/* ---------------------------------------------------------------------- */
2659+
2660+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
2661+{
2662+ int err;
2663+ struct au_sbinfo *sbinfo;
2664+ struct super_block *sb;
2665+
2666+ sbinfo = inode->i_private;
2667+ sb = sbinfo->si_sb;
2668+ si_noflush_read_lock(sb);
2669+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
2670+ si_read_unlock(sb);
2671+ return err;
2672+}
2673+
2674+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 2675+ .owner = THIS_MODULE,
1facf9fc 2676+ .open = dbgaufs_xib_open,
2677+ .release = dbgaufs_xi_release,
2678+ .read = dbgaufs_xi_read
2679+};
2680+
2681+/* ---------------------------------------------------------------------- */
2682+
2683+#define DbgaufsXi_PREFIX "xi"
2684+
2685+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
2686+{
2687+ int err;
2688+ long l;
2689+ struct au_sbinfo *sbinfo;
2690+ struct super_block *sb;
2691+ struct file *xf;
2692+ struct qstr *name;
2693+
2694+ err = -ENOENT;
2695+ xf = NULL;
2696+ name = &file->f_dentry->d_name;
2697+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
2698+ || memcmp(name->name, DbgaufsXi_PREFIX,
2699+ sizeof(DbgaufsXi_PREFIX) - 1)))
2700+ goto out;
2701+ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
2702+ if (unlikely(err))
2703+ goto out;
2704+
2705+ sbinfo = inode->i_private;
2706+ sb = sbinfo->si_sb;
2707+ si_noflush_read_lock(sb);
2708+ if (l <= au_sbend(sb)) {
2709+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
2710+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
2711+ } else
2712+ err = -ENOENT;
2713+ si_read_unlock(sb);
2714+
2715+ out:
2716+ return err;
2717+}
2718+
2719+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 2720+ .owner = THIS_MODULE,
1facf9fc 2721+ .open = dbgaufs_xino_open,
2722+ .release = dbgaufs_xi_release,
2723+ .read = dbgaufs_xi_read
2724+};
2725+
2726+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
2727+{
2728+ aufs_bindex_t bend;
2729+ struct au_branch *br;
2730+ struct au_xino_file *xi;
2731+
2732+ if (!au_sbi(sb)->si_dbgaufs)
2733+ return;
2734+
2735+ bend = au_sbend(sb);
2736+ for (; bindex <= bend; bindex++) {
2737+ br = au_sbr(sb, bindex);
2738+ xi = &br->br_xino;
2739+ if (xi->xi_dbgaufs) {
2740+ debugfs_remove(xi->xi_dbgaufs);
2741+ xi->xi_dbgaufs = NULL;
2742+ }
2743+ }
2744+}
2745+
2746+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
2747+{
2748+ struct au_sbinfo *sbinfo;
2749+ struct dentry *parent;
2750+ struct au_branch *br;
2751+ struct au_xino_file *xi;
2752+ aufs_bindex_t bend;
2753+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
2754+
2755+ sbinfo = au_sbi(sb);
2756+ parent = sbinfo->si_dbgaufs;
2757+ if (!parent)
2758+ return;
2759+
2760+ bend = au_sbend(sb);
2761+ for (; bindex <= bend; bindex++) {
2762+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
2763+ br = au_sbr(sb, bindex);
2764+ xi = &br->br_xino;
2765+ AuDebugOn(xi->xi_dbgaufs);
2766+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
2767+ sbinfo, &dbgaufs_xino_fop);
2768+ /* ignore an error */
2769+ if (unlikely(!xi->xi_dbgaufs))
2770+ AuWarn1("failed %s under debugfs\n", name);
2771+ }
2772+}
2773+
2774+/* ---------------------------------------------------------------------- */
2775+
2776+#ifdef CONFIG_AUFS_EXPORT
2777+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
2778+{
2779+ int err;
2780+ struct au_sbinfo *sbinfo;
2781+ struct super_block *sb;
2782+
2783+ sbinfo = inode->i_private;
2784+ sb = sbinfo->si_sb;
2785+ si_noflush_read_lock(sb);
2786+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
2787+ si_read_unlock(sb);
2788+ return err;
2789+}
2790+
2791+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 2792+ .owner = THIS_MODULE,
1facf9fc 2793+ .open = dbgaufs_xigen_open,
2794+ .release = dbgaufs_xi_release,
2795+ .read = dbgaufs_xi_read
2796+};
2797+
2798+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
2799+{
2800+ int err;
2801+
dece6358
AM
2802+ /*
2803+ * This function is a dynamic '__init' fucntion actually,
2804+ * so the tiny check for si_rwsem is unnecessary.
2805+ */
2806+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
2807+
1facf9fc 2808+ err = -EIO;
2809+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
2810+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
2811+ &dbgaufs_xigen_fop);
2812+ if (sbinfo->si_dbgaufs_xigen)
2813+ err = 0;
2814+
2815+ return err;
2816+}
2817+#else
2818+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
2819+{
2820+ return 0;
2821+}
2822+#endif /* CONFIG_AUFS_EXPORT */
2823+
2824+/* ---------------------------------------------------------------------- */
2825+
2826+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
2827+{
dece6358
AM
2828+ /*
2829+ * This function is a dynamic '__init' fucntion actually,
2830+ * so the tiny check for si_rwsem is unnecessary.
2831+ */
2832+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
2833+
1facf9fc 2834+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
2835+ sbinfo->si_dbgaufs = NULL;
2836+ kobject_put(&sbinfo->si_kobj);
2837+}
2838+
2839+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
2840+{
2841+ int err;
2842+ char name[SysaufsSiNameLen];
2843+
dece6358
AM
2844+ /*
2845+ * This function is a dynamic '__init' fucntion actually,
2846+ * so the tiny check for si_rwsem is unnecessary.
2847+ */
2848+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
2849+
1facf9fc 2850+ err = -ENOENT;
2851+ if (!dbgaufs) {
2852+ AuErr1("/debug/aufs is uninitialized\n");
2853+ goto out;
2854+ }
2855+
2856+ err = -EIO;
2857+ sysaufs_name(sbinfo, name);
2858+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
2859+ if (unlikely(!sbinfo->si_dbgaufs))
2860+ goto out;
2861+ kobject_get(&sbinfo->si_kobj);
2862+
2863+ sbinfo->si_dbgaufs_xib = debugfs_create_file
2864+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
2865+ &dbgaufs_xib_fop);
2866+ if (unlikely(!sbinfo->si_dbgaufs_xib))
2867+ goto out_dir;
2868+
2869+ err = dbgaufs_xigen_init(sbinfo);
2870+ if (!err)
2871+ goto out; /* success */
2872+
2873+ out_dir:
2874+ dbgaufs_si_fin(sbinfo);
2875+ out:
2876+ return err;
2877+}
2878+
2879+/* ---------------------------------------------------------------------- */
2880+
2881+void dbgaufs_fin(void)
2882+{
2883+ debugfs_remove(dbgaufs);
2884+}
2885+
2886+int __init dbgaufs_init(void)
2887+{
2888+ int err;
2889+
2890+ err = -EIO;
2891+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
2892+ if (dbgaufs)
2893+ err = 0;
2894+ return err;
2895+}
4a4d8108
AM
2896diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/dbgaufs.h linux-2.6.34/fs/aufs/dbgaufs.h
2897--- linux-2.6.34.org/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
2898+++ linux-2.6.34/fs/aufs/dbgaufs.h 2010-05-31 22:15:32.000000000 +0200
2899@@ -0,0 +1,52 @@
1facf9fc 2900+/*
4a4d8108 2901+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2902+ *
2903+ * This program, aufs is free software; you can redistribute it and/or modify
2904+ * it under the terms of the GNU General Public License as published by
2905+ * the Free Software Foundation; either version 2 of the License, or
2906+ * (at your option) any later version.
dece6358
AM
2907+ *
2908+ * This program is distributed in the hope that it will be useful,
2909+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2910+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2911+ * GNU General Public License for more details.
2912+ *
2913+ * You should have received a copy of the GNU General Public License
2914+ * along with this program; if not, write to the Free Software
2915+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2916+ */
2917+
2918+/*
2919+ * debugfs interface
2920+ */
2921+
2922+#ifndef __DBGAUFS_H__
2923+#define __DBGAUFS_H__
2924+
2925+#ifdef __KERNEL__
2926+
dece6358 2927+#include <linux/init.h>
1facf9fc 2928+#include <linux/aufs_type.h>
2929+
dece6358 2930+struct super_block;
1facf9fc 2931+struct au_sbinfo;
dece6358 2932+
1facf9fc 2933+#ifdef CONFIG_DEBUG_FS
2934+/* dbgaufs.c */
2935+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
2936+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
2937+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
2938+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
2939+void dbgaufs_fin(void);
2940+int __init dbgaufs_init(void);
1facf9fc 2941+#else
4a4d8108
AM
2942+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
2943+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
2944+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
2945+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
2946+AuStubVoid(dbgaufs_fin, void)
2947+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 2948+#endif /* CONFIG_DEBUG_FS */
2949+
2950+#endif /* __KERNEL__ */
2951+#endif /* __DBGAUFS_H__ */
4a4d8108
AM
2952diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/dcsub.c linux-2.6.34/fs/aufs/dcsub.c
2953--- linux-2.6.34.org/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
2954+++ linux-2.6.34/fs/aufs/dcsub.c 2010-05-31 22:15:32.000000000 +0200
2955@@ -0,0 +1,200 @@
1facf9fc 2956+/*
4a4d8108 2957+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2958+ *
2959+ * This program, aufs is free software; you can redistribute it and/or modify
2960+ * it under the terms of the GNU General Public License as published by
2961+ * the Free Software Foundation; either version 2 of the License, or
2962+ * (at your option) any later version.
dece6358
AM
2963+ *
2964+ * This program is distributed in the hope that it will be useful,
2965+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2966+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2967+ * GNU General Public License for more details.
2968+ *
2969+ * You should have received a copy of the GNU General Public License
2970+ * along with this program; if not, write to the Free Software
2971+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2972+ */
2973+
2974+/*
2975+ * sub-routines for dentry cache
2976+ */
2977+
2978+#include "aufs.h"
2979+
2980+static void au_dpage_free(struct au_dpage *dpage)
2981+{
2982+ int i;
2983+ struct dentry **p;
2984+
2985+ p = dpage->dentries;
2986+ for (i = 0; i < dpage->ndentry; i++)
2987+ dput(*p++);
2988+ free_page((unsigned long)dpage->dentries);
2989+}
2990+
2991+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
2992+{
2993+ int err;
2994+ void *p;
2995+
2996+ err = -ENOMEM;
2997+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
2998+ if (unlikely(!dpages->dpages))
2999+ goto out;
3000+
3001+ p = (void *)__get_free_page(gfp);
3002+ if (unlikely(!p))
3003+ goto out_dpages;
3004+
3005+ dpages->dpages[0].ndentry = 0;
3006+ dpages->dpages[0].dentries = p;
3007+ dpages->ndpage = 1;
3008+ return 0; /* success */
3009+
3010+ out_dpages:
3011+ kfree(dpages->dpages);
3012+ out:
3013+ return err;
3014+}
3015+
3016+void au_dpages_free(struct au_dcsub_pages *dpages)
3017+{
3018+ int i;
3019+ struct au_dpage *p;
3020+
3021+ p = dpages->dpages;
3022+ for (i = 0; i < dpages->ndpage; i++)
3023+ au_dpage_free(p++);
3024+ kfree(dpages->dpages);
3025+}
3026+
3027+static int au_dpages_append(struct au_dcsub_pages *dpages,
3028+ struct dentry *dentry, gfp_t gfp)
3029+{
3030+ int err, sz;
3031+ struct au_dpage *dpage;
3032+ void *p;
3033+
3034+ dpage = dpages->dpages + dpages->ndpage - 1;
3035+ sz = PAGE_SIZE / sizeof(dentry);
3036+ if (unlikely(dpage->ndentry >= sz)) {
3037+ AuLabel(new dpage);
3038+ err = -ENOMEM;
3039+ sz = dpages->ndpage * sizeof(*dpages->dpages);
3040+ p = au_kzrealloc(dpages->dpages, sz,
3041+ sz + sizeof(*dpages->dpages), gfp);
3042+ if (unlikely(!p))
3043+ goto out;
3044+
3045+ dpages->dpages = p;
3046+ dpage = dpages->dpages + dpages->ndpage;
3047+ p = (void *)__get_free_page(gfp);
3048+ if (unlikely(!p))
3049+ goto out;
3050+
3051+ dpage->ndentry = 0;
3052+ dpage->dentries = p;
3053+ dpages->ndpage++;
3054+ }
3055+
3056+ dpage->dentries[dpage->ndentry++] = dget(dentry);
3057+ return 0; /* success */
3058+
3059+ out:
3060+ return err;
3061+}
3062+
3063+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3064+ au_dpages_test test, void *arg)
3065+{
3066+ int err;
3067+ struct dentry *this_parent = root;
3068+ struct list_head *next;
3069+ struct super_block *sb = root->d_sb;
3070+
3071+ err = 0;
3072+ spin_lock(&dcache_lock);
3073+ repeat:
3074+ next = this_parent->d_subdirs.next;
3075+ resume:
3076+ if (this_parent->d_sb == sb
3077+ && !IS_ROOT(this_parent)
3078+ && atomic_read(&this_parent->d_count)
3079+ && this_parent->d_inode
3080+ && (!test || test(this_parent, arg))) {
3081+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3082+ if (unlikely(err))
3083+ goto out;
3084+ }
3085+
3086+ while (next != &this_parent->d_subdirs) {
3087+ struct list_head *tmp = next;
3088+ struct dentry *dentry = list_entry(tmp, struct dentry,
3089+ d_u.d_child);
3090+ next = tmp->next;
3091+ if (/*d_unhashed(dentry) || */!dentry->d_inode)
3092+ continue;
3093+ if (!list_empty(&dentry->d_subdirs)) {
3094+ this_parent = dentry;
3095+ goto repeat;
3096+ }
3097+ if (dentry->d_sb == sb
3098+ && atomic_read(&dentry->d_count)
3099+ && (!test || test(dentry, arg))) {
3100+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3101+ if (unlikely(err))
3102+ goto out;
3103+ }
3104+ }
3105+
3106+ if (this_parent != root) {
3107+ next = this_parent->d_u.d_child.next;
3108+ this_parent = this_parent->d_parent; /* dcache_lock is locked */
3109+ goto resume;
3110+ }
3111+ out:
3112+ spin_unlock(&dcache_lock);
3113+ return err;
3114+}
3115+
3116+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3117+ int do_include, au_dpages_test test, void *arg)
3118+{
3119+ int err;
3120+
3121+ err = 0;
3122+ spin_lock(&dcache_lock);
3123+ if (do_include && (!test || test(dentry, arg))) {
3124+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3125+ if (unlikely(err))
3126+ goto out;
3127+ }
3128+ while (!IS_ROOT(dentry)) {
3129+ dentry = dentry->d_parent; /* dcache_lock is locked */
3130+ if (!test || test(dentry, arg)) {
3131+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3132+ if (unlikely(err))
3133+ break;
3134+ }
3135+ }
3136+
3137+ out:
3138+ spin_unlock(&dcache_lock);
3139+
3140+ return err;
3141+}
3142+
4a4d8108 3143+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 3144+{
4a4d8108
AM
3145+ struct path path[2] = {
3146+ {
3147+ .dentry = d1
3148+ },
3149+ {
3150+ .dentry = d2
3151+ }
3152+ };
1facf9fc 3153+
4a4d8108 3154+ return path_is_under(path + 0, path + 1);
1facf9fc 3155+}
4a4d8108
AM
3156diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/dcsub.h linux-2.6.34/fs/aufs/dcsub.h
3157--- linux-2.6.34.org/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
3158+++ linux-2.6.34/fs/aufs/dcsub.h 2010-05-31 22:15:32.000000000 +0200
dece6358 3159@@ -0,0 +1,54 @@
1facf9fc 3160+/*
4a4d8108 3161+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3162+ *
3163+ * This program, aufs is free software; you can redistribute it and/or modify
3164+ * it under the terms of the GNU General Public License as published by
3165+ * the Free Software Foundation; either version 2 of the License, or
3166+ * (at your option) any later version.
dece6358
AM
3167+ *
3168+ * This program is distributed in the hope that it will be useful,
3169+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3170+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3171+ * GNU General Public License for more details.
3172+ *
3173+ * You should have received a copy of the GNU General Public License
3174+ * along with this program; if not, write to the Free Software
3175+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3176+ */
3177+
3178+/*
3179+ * sub-routines for dentry cache
3180+ */
3181+
3182+#ifndef __AUFS_DCSUB_H__
3183+#define __AUFS_DCSUB_H__
3184+
3185+#ifdef __KERNEL__
3186+
dece6358
AM
3187+#include <linux/types.h>
3188+
3189+struct dentry;
1facf9fc 3190+
3191+struct au_dpage {
3192+ int ndentry;
3193+ struct dentry **dentries;
3194+};
3195+
3196+struct au_dcsub_pages {
3197+ int ndpage;
3198+ struct au_dpage *dpages;
3199+};
3200+
3201+/* ---------------------------------------------------------------------- */
3202+
3203+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3204+void au_dpages_free(struct au_dcsub_pages *dpages);
3205+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3206+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3207+ au_dpages_test test, void *arg);
3208+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3209+ int do_include, au_dpages_test test, void *arg);
4a4d8108 3210+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 3211+
3212+#endif /* __KERNEL__ */
3213+#endif /* __AUFS_DCSUB_H__ */
4a4d8108
AM
3214diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/debug.c linux-2.6.34/fs/aufs/debug.c
3215--- linux-2.6.34.org/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
3216+++ linux-2.6.34/fs/aufs/debug.c 2010-05-31 22:15:32.000000000 +0200
3217@@ -0,0 +1,425 @@
1facf9fc 3218+/*
4a4d8108 3219+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3220+ *
3221+ * This program, aufs is free software; you can redistribute it and/or modify
3222+ * it under the terms of the GNU General Public License as published by
3223+ * the Free Software Foundation; either version 2 of the License, or
3224+ * (at your option) any later version.
dece6358
AM
3225+ *
3226+ * This program is distributed in the hope that it will be useful,
3227+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3228+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3229+ * GNU General Public License for more details.
3230+ *
3231+ * You should have received a copy of the GNU General Public License
3232+ * along with this program; if not, write to the Free Software
3233+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3234+ */
3235+
3236+/*
3237+ * debug print functions
3238+ */
3239+
dece6358
AM
3240+#include <linux/module.h>
3241+#include <linux/vt_kern.h>
1facf9fc 3242+#include "aufs.h"
3243+
3244+int aufs_debug;
3245+MODULE_PARM_DESC(debug, "debug print");
3246+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
3247+
3248+char *au_plevel = KERN_DEBUG;
4a4d8108 3249+#define dpri(fmt, ...) do { \
1facf9fc 3250+ if (au_debug_test()) \
4a4d8108 3251+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 3252+} while (0)
3253+
3254+/* ---------------------------------------------------------------------- */
3255+
3256+void au_dpri_whlist(struct au_nhash *whlist)
3257+{
3258+ unsigned long ul, n;
3259+ struct hlist_head *head;
3260+ struct au_vdir_wh *tpos;
3261+ struct hlist_node *pos;
3262+
3263+ n = whlist->nh_num;
3264+ head = whlist->nh_head;
3265+ for (ul = 0; ul < n; ul++) {
3266+ hlist_for_each_entry(tpos, pos, head, wh_hash)
3267+ dpri("b%d, %.*s, %d\n",
3268+ tpos->wh_bindex,
3269+ tpos->wh_str.len, tpos->wh_str.name,
3270+ tpos->wh_str.len);
3271+ head++;
3272+ }
3273+}
3274+
3275+void au_dpri_vdir(struct au_vdir *vdir)
3276+{
3277+ unsigned long ul;
3278+ union au_vdir_deblk_p p;
3279+ unsigned char *o;
3280+
3281+ if (!vdir || IS_ERR(vdir)) {
3282+ dpri("err %ld\n", PTR_ERR(vdir));
3283+ return;
3284+ }
3285+
3286+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
3287+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
3288+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
3289+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
3290+ p.deblk = vdir->vd_deblk[ul];
3291+ o = p.deblk;
3292+ dpri("[%lu]: %p\n", ul, o);
3293+ }
3294+}
3295+
3296+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3297+ struct dentry *wh)
3298+{
3299+ char *n = NULL;
3300+ int l = 0;
3301+
3302+ if (!inode || IS_ERR(inode)) {
3303+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3304+ return -1;
3305+ }
3306+
3307+ /* the type of i_blocks depends upon CONFIG_LSF */
3308+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3309+ && sizeof(inode->i_blocks) != sizeof(u64));
3310+ if (wh) {
3311+ n = (void *)wh->d_name.name;
3312+ l = wh->d_name.len;
3313+ }
3314+
3315+ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
3316+ " ct %lld, np %lu, st 0x%lx, f 0x%x, g %x%s%.*s\n",
3317+ bindex,
3318+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3319+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3320+ i_size_read(inode), (unsigned long long)inode->i_blocks,
3321+ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3322+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
3323+ inode->i_state, inode->i_flags, inode->i_generation,
3324+ l ? ", wh " : "", l, n);
3325+ return 0;
3326+}
3327+
3328+void au_dpri_inode(struct inode *inode)
3329+{
3330+ struct au_iinfo *iinfo;
3331+ aufs_bindex_t bindex;
3332+ int err;
3333+
3334+ err = do_pri_inode(-1, inode, NULL);
3335+ if (err || !au_test_aufs(inode->i_sb))
3336+ return;
3337+
3338+ iinfo = au_ii(inode);
3339+ if (!iinfo)
3340+ return;
3341+ dpri("i-1: bstart %d, bend %d, gen %d\n",
3342+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
3343+ if (iinfo->ii_bstart < 0)
3344+ return;
3345+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
3346+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
3347+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
3348+}
3349+
3350+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
3351+{
3352+ struct dentry *wh = NULL;
3353+
3354+ if (!dentry || IS_ERR(dentry)) {
3355+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
3356+ return -1;
3357+ }
3358+ /* do not call dget_parent() here */
3359+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
3360+ bindex,
3361+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
3362+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
3363+ atomic_read(&dentry->d_count), dentry->d_flags);
3364+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
3365+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
3366+ if (iinfo)
3367+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
3368+ }
3369+ do_pri_inode(bindex, dentry->d_inode, wh);
3370+ return 0;
3371+}
3372+
3373+void au_dpri_dentry(struct dentry *dentry)
3374+{
3375+ struct au_dinfo *dinfo;
3376+ aufs_bindex_t bindex;
3377+ int err;
4a4d8108 3378+ struct au_hdentry *hdp;
1facf9fc 3379+
3380+ err = do_pri_dentry(-1, dentry);
3381+ if (err || !au_test_aufs(dentry->d_sb))
3382+ return;
3383+
3384+ dinfo = au_di(dentry);
3385+ if (!dinfo)
3386+ return;
3387+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
3388+ dinfo->di_bstart, dinfo->di_bend,
3389+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
3390+ if (dinfo->di_bstart < 0)
3391+ return;
4a4d8108 3392+ hdp = dinfo->di_hdentry;
1facf9fc 3393+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 3394+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 3395+}
3396+
3397+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
3398+{
3399+ char a[32];
3400+
3401+ if (!file || IS_ERR(file)) {
3402+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
3403+ return -1;
3404+ }
3405+ a[0] = 0;
3406+ if (bindex < 0
3407+ && file->f_dentry
3408+ && au_test_aufs(file->f_dentry->d_sb)
3409+ && au_fi(file))
4a4d8108
AM
3410+ snprintf(a, sizeof(a), ", mmapped %d",
3411+ !!au_fi(file)->fi_hvmop);
1facf9fc 3412+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, pos %llu%s\n",
3413+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
3414+ file->f_pos, a);
3415+ if (file->f_dentry)
3416+ do_pri_dentry(bindex, file->f_dentry);
3417+ return 0;
3418+}
3419+
3420+void au_dpri_file(struct file *file)
3421+{
3422+ struct au_finfo *finfo;
4a4d8108
AM
3423+ struct au_fidir *fidir;
3424+ struct au_hfile *hfile;
1facf9fc 3425+ aufs_bindex_t bindex;
3426+ int err;
3427+
3428+ err = do_pri_file(-1, file);
3429+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
3430+ return;
3431+
3432+ finfo = au_fi(file);
3433+ if (!finfo)
3434+ return;
4a4d8108 3435+ if (finfo->fi_btop < 0)
1facf9fc 3436+ return;
4a4d8108
AM
3437+ fidir = finfo->fi_hdir;
3438+ if (!fidir)
3439+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
3440+ else
3441+ for (bindex = finfo->fi_btop; bindex <= fidir->fd_bbot;
3442+ bindex++) {
3443+ hfile = fidir->fd_hfile + bindex;
3444+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
3445+ }
1facf9fc 3446+}
3447+
3448+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
3449+{
3450+ struct vfsmount *mnt;
3451+ struct super_block *sb;
3452+
3453+ if (!br || IS_ERR(br))
3454+ goto out;
3455+ mnt = br->br_mnt;
3456+ if (!mnt || IS_ERR(mnt))
3457+ goto out;
3458+ sb = mnt->mnt_sb;
3459+ if (!sb || IS_ERR(sb))
3460+ goto out;
3461+
3462+ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
3463+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt(BIAS) %d, active %d, "
3464+ "xino %d\n",
3465+ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
3466+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
3467+ sb->s_flags, sb->s_count - S_BIAS,
3468+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
3469+ return 0;
3470+
3471+ out:
3472+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
3473+ return -1;
3474+}
3475+
3476+void au_dpri_sb(struct super_block *sb)
3477+{
3478+ struct au_sbinfo *sbinfo;
3479+ aufs_bindex_t bindex;
3480+ int err;
3481+ /* to reuduce stack size */
3482+ struct {
3483+ struct vfsmount mnt;
3484+ struct au_branch fake;
3485+ } *a;
3486+
3487+ /* this function can be called from magic sysrq */
3488+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
3489+ if (unlikely(!a)) {
3490+ dpri("no memory\n");
3491+ return;
3492+ }
3493+
3494+ a->mnt.mnt_sb = sb;
3495+ a->fake.br_perm = 0;
3496+ a->fake.br_mnt = &a->mnt;
3497+ a->fake.br_xino.xi_file = NULL;
3498+ atomic_set(&a->fake.br_count, 0);
3499+ smp_mb(); /* atomic_set */
3500+ err = do_pri_br(-1, &a->fake);
3501+ kfree(a);
3502+ dpri("dev 0x%x\n", sb->s_dev);
3503+ if (err || !au_test_aufs(sb))
3504+ return;
3505+
3506+ sbinfo = au_sbi(sb);
3507+ if (!sbinfo)
3508+ return;
3509+ dpri("nw %d, gen %u, kobj %d\n",
3510+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
3511+ atomic_read(&sbinfo->si_kobj.kref.refcount));
3512+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
3513+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
3514+}
3515+
3516+/* ---------------------------------------------------------------------- */
3517+
3518+void au_dbg_sleep_jiffy(int jiffy)
3519+{
3520+ while (jiffy)
3521+ jiffy = schedule_timeout_uninterruptible(jiffy);
3522+}
3523+
3524+void au_dbg_iattr(struct iattr *ia)
3525+{
3526+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
3527+ dpri(#name "\n")
3528+ AuBit(MODE);
3529+ AuBit(UID);
3530+ AuBit(GID);
3531+ AuBit(SIZE);
3532+ AuBit(ATIME);
3533+ AuBit(MTIME);
3534+ AuBit(CTIME);
3535+ AuBit(ATIME_SET);
3536+ AuBit(MTIME_SET);
3537+ AuBit(FORCE);
3538+ AuBit(ATTR_FLAG);
3539+ AuBit(KILL_SUID);
3540+ AuBit(KILL_SGID);
3541+ AuBit(FILE);
3542+ AuBit(KILL_PRIV);
3543+ AuBit(OPEN);
3544+ AuBit(TIMES_SET);
3545+#undef AuBit
3546+ dpri("ia_file %p\n", ia->ia_file);
3547+}
3548+
3549+/* ---------------------------------------------------------------------- */
3550+
3551+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
3552+{
3553+ struct dentry *parent;
3554+
3555+ parent = dget_parent(dentry);
3556+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
3557+ || IS_ROOT(dentry)
3558+ || au_digen(parent) != sigen);
3559+ dput(parent);
3560+}
3561+
3562+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
3563+{
3564+ struct dentry *parent;
3565+
3566+ parent = dget_parent(dentry);
3567+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
3568+ || au_digen(parent) != sigen);
3569+ dput(parent);
3570+}
3571+
3572+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
3573+{
3574+ int err, i, j;
3575+ struct au_dcsub_pages dpages;
3576+ struct au_dpage *dpage;
3577+ struct dentry **dentries;
3578+
3579+ err = au_dpages_init(&dpages, GFP_NOFS);
3580+ AuDebugOn(err);
3581+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
3582+ AuDebugOn(err);
3583+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
3584+ dpage = dpages.dpages + i;
3585+ dentries = dpage->dentries;
3586+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
3587+ AuDebugOn(au_digen(dentries[j]) != sigen);
3588+ }
3589+ au_dpages_free(&dpages);
3590+}
3591+
1facf9fc 3592+void au_dbg_verify_kthread(void)
3593+{
3594+ if (au_test_wkq(current)) {
3595+ au_dbg_blocked();
3596+ BUG();
3597+ }
3598+}
3599+
3600+/* ---------------------------------------------------------------------- */
3601+
3602+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
3603+{
3604+#ifdef AuForceNoPlink
3605+ au_opt_clr(sbinfo->si_mntflags, PLINK);
3606+#endif
3607+#ifdef AuForceNoXino
3608+ au_opt_clr(sbinfo->si_mntflags, XINO);
3609+#endif
3610+#ifdef AuForceNoRefrof
3611+ au_opt_clr(sbinfo->si_mntflags, REFROF);
3612+#endif
4a4d8108
AM
3613+#ifdef AuForceHnotify
3614+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 3615+#endif
1308ab2a 3616+#ifdef AuForceRd0
3617+ sbinfo->si_rdblk = 0;
3618+ sbinfo->si_rdhash = 0;
3619+#endif
1facf9fc 3620+}
3621+
3622+int __init au_debug_init(void)
3623+{
3624+ aufs_bindex_t bindex;
3625+ struct au_vdir_destr destr;
3626+
3627+ bindex = -1;
3628+ AuDebugOn(bindex >= 0);
3629+
3630+ destr.len = -1;
3631+ AuDebugOn(destr.len < NAME_MAX);
3632+
3633+#ifdef CONFIG_4KSTACKS
4a4d8108 3634+ pr_warning("CONFIG_4KSTACKS is defined.\n");
1facf9fc 3635+#endif
3636+
3637+#ifdef AuForceNoBrs
3638+ sysaufs_brs = 0;
3639+#endif
3640+
3641+ return 0;
3642+}
4a4d8108
AM
3643diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/debug.h linux-2.6.34/fs/aufs/debug.h
3644--- linux-2.6.34.org/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
3645+++ linux-2.6.34/fs/aufs/debug.h 2010-05-31 22:15:32.000000000 +0200
3646@@ -0,0 +1,243 @@
1facf9fc 3647+/*
4a4d8108 3648+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3649+ *
3650+ * This program, aufs is free software; you can redistribute it and/or modify
3651+ * it under the terms of the GNU General Public License as published by
3652+ * the Free Software Foundation; either version 2 of the License, or
3653+ * (at your option) any later version.
dece6358
AM
3654+ *
3655+ * This program is distributed in the hope that it will be useful,
3656+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3657+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3658+ * GNU General Public License for more details.
3659+ *
3660+ * You should have received a copy of the GNU General Public License
3661+ * along with this program; if not, write to the Free Software
3662+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3663+ */
3664+
3665+/*
3666+ * debug print functions
3667+ */
3668+
3669+#ifndef __AUFS_DEBUG_H__
3670+#define __AUFS_DEBUG_H__
3671+
3672+#ifdef __KERNEL__
3673+
1308ab2a 3674+#include <asm/system.h>
dece6358
AM
3675+#include <linux/bug.h>
3676+/* #include <linux/err.h> */
1308ab2a 3677+#include <linux/init.h>
4a4d8108
AM
3678+#include <linux/module.h>
3679+#include <linux/kallsyms.h>
dece6358 3680+/* #include <linux/kernel.h> */
1facf9fc 3681+#include <linux/delay.h>
dece6358
AM
3682+/* #include <linux/kd.h> */
3683+/* #include <linux/vt_kern.h> */
1facf9fc 3684+#include <linux/sysrq.h>
3685+#include <linux/aufs_type.h>
3686+
4a4d8108
AM
3687+#include <asm/system.h>
3688+
1facf9fc 3689+#ifdef CONFIG_AUFS_DEBUG
3690+#define AuDebugOn(a) BUG_ON(a)
3691+
3692+/* module parameter */
3693+extern int aufs_debug;
3694+static inline void au_debug(int n)
3695+{
3696+ aufs_debug = n;
3697+ smp_mb();
3698+}
3699+
3700+static inline int au_debug_test(void)
3701+{
3702+ return aufs_debug;
3703+}
3704+#else
3705+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
3706+AuStubVoid(au_debug, int n)
3707+AuStubInt0(au_debug_test, void)
1facf9fc 3708+#endif /* CONFIG_AUFS_DEBUG */
3709+
3710+/* ---------------------------------------------------------------------- */
3711+
3712+/* debug print */
3713+
4a4d8108 3714+#define AuDbg(fmt, ...) do { \
1facf9fc 3715+ if (au_debug_test()) \
4a4d8108 3716+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 3717+} while (0)
4a4d8108
AM
3718+#define AuLabel(l) AuDbg(#l "\n")
3719+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
3720+#define AuWarn1(fmt, ...) do { \
1facf9fc 3721+ static unsigned char _c; \
3722+ if (!_c++) \
4a4d8108 3723+ pr_warning(fmt, ##__VA_ARGS__); \
1facf9fc 3724+} while (0)
3725+
4a4d8108 3726+#define AuErr1(fmt, ...) do { \
1facf9fc 3727+ static unsigned char _c; \
3728+ if (!_c++) \
4a4d8108 3729+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 3730+} while (0)
3731+
4a4d8108 3732+#define AuIOErr1(fmt, ...) do { \
1facf9fc 3733+ static unsigned char _c; \
3734+ if (!_c++) \
4a4d8108 3735+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 3736+} while (0)
3737+
3738+#define AuUnsupportMsg "This operation is not supported." \
3739+ " Please report this application to aufs-users ML."
4a4d8108
AM
3740+#define AuUnsupport(fmt, ...) do { \
3741+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 3742+ dump_stack(); \
3743+} while (0)
3744+
3745+#define AuTraceErr(e) do { \
3746+ if (unlikely((e) < 0)) \
3747+ AuDbg("err %d\n", (int)(e)); \
3748+} while (0)
3749+
3750+#define AuTraceErrPtr(p) do { \
3751+ if (IS_ERR(p)) \
3752+ AuDbg("err %ld\n", PTR_ERR(p)); \
3753+} while (0)
3754+
3755+/* dirty macros for debug print, use with "%.*s" and caution */
3756+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
3757+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
3758+
3759+/* ---------------------------------------------------------------------- */
3760+
3761+struct au_sbinfo;
3762+struct au_finfo;
dece6358 3763+struct dentry;
1facf9fc 3764+#ifdef CONFIG_AUFS_DEBUG
3765+extern char *au_plevel;
3766+struct au_nhash;
3767+void au_dpri_whlist(struct au_nhash *whlist);
3768+struct au_vdir;
3769+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 3770+struct inode;
1facf9fc 3771+void au_dpri_inode(struct inode *inode);
3772+void au_dpri_dentry(struct dentry *dentry);
dece6358 3773+struct file;
1facf9fc 3774+void au_dpri_file(struct file *filp);
dece6358 3775+struct super_block;
1facf9fc 3776+void au_dpri_sb(struct super_block *sb);
3777+
3778+void au_dbg_sleep_jiffy(int jiffy);
dece6358 3779+struct iattr;
1facf9fc 3780+void au_dbg_iattr(struct iattr *ia);
3781+
3782+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
3783+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
3784+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 3785+void au_dbg_verify_kthread(void);
3786+
3787+int __init au_debug_init(void);
3788+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
3789+#define AuDbgWhlist(w) do { \
3790+ AuDbg(#w "\n"); \
3791+ au_dpri_whlist(w); \
3792+} while (0)
3793+
3794+#define AuDbgVdir(v) do { \
3795+ AuDbg(#v "\n"); \
3796+ au_dpri_vdir(v); \
3797+} while (0)
3798+
3799+#define AuDbgInode(i) do { \
3800+ AuDbg(#i "\n"); \
3801+ au_dpri_inode(i); \
3802+} while (0)
3803+
3804+#define AuDbgDentry(d) do { \
3805+ AuDbg(#d "\n"); \
3806+ au_dpri_dentry(d); \
3807+} while (0)
3808+
3809+#define AuDbgFile(f) do { \
3810+ AuDbg(#f "\n"); \
3811+ au_dpri_file(f); \
3812+} while (0)
3813+
3814+#define AuDbgSb(sb) do { \
3815+ AuDbg(#sb "\n"); \
3816+ au_dpri_sb(sb); \
3817+} while (0)
3818+
3819+#define AuDbgSleep(sec) do { \
3820+ AuDbg("sleep %d sec\n", sec); \
3821+ ssleep(sec); \
3822+} while (0)
3823+
3824+#define AuDbgSleepJiffy(jiffy) do { \
3825+ AuDbg("sleep %d jiffies\n", jiffy); \
3826+ au_dbg_sleep_jiffy(jiffy); \
3827+} while (0)
3828+
3829+#define AuDbgIAttr(ia) do { \
3830+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
3831+ au_dbg_iattr(ia); \
3832+} while (0)
4a4d8108
AM
3833+
3834+#define AuDbgSym(addr) do { \
3835+ char sym[KSYM_SYMBOL_LEN]; \
3836+ sprint_symbol(sym, (unsigned long)addr); \
3837+ AuDbg("%s\n", sym); \
3838+} while (0)
3839+
3840+#define AuInfoSym(addr) do { \
3841+ char sym[KSYM_SYMBOL_LEN]; \
3842+ sprint_symbol(sym, (unsigned long)addr); \
3843+ AuInfo("%s\n", sym); \
3844+} while (0)
1facf9fc 3845+#else
4a4d8108
AM
3846+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
3847+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
3848+ unsigned int sigen)
3849+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
3850+AuStubVoid(au_dbg_verify_kthread, void)
3851+AuStubInt0(__init au_debug_init, void)
3852+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 3853+
1facf9fc 3854+#define AuDbgWhlist(w) do {} while (0)
3855+#define AuDbgVdir(v) do {} while (0)
3856+#define AuDbgInode(i) do {} while (0)
3857+#define AuDbgDentry(d) do {} while (0)
3858+#define AuDbgFile(f) do {} while (0)
3859+#define AuDbgSb(sb) do {} while (0)
3860+#define AuDbgSleep(sec) do {} while (0)
3861+#define AuDbgSleepJiffy(jiffy) do {} while (0)
3862+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
3863+#define AuDbgSym(addr) do {} while (0)
3864+#define AuInfoSym(addr) do {} while (0)
1facf9fc 3865+#endif /* CONFIG_AUFS_DEBUG */
3866+
3867+/* ---------------------------------------------------------------------- */
3868+
3869+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
3870+int __init au_sysrq_init(void);
3871+void au_sysrq_fin(void);
3872+
3873+#ifdef CONFIG_HW_CONSOLE
3874+#define au_dbg_blocked() do { \
3875+ WARN_ON(1); \
3876+ handle_sysrq('w', vc_cons[fg_console].d->vc_tty); \
3877+} while (0)
3878+#else
4a4d8108 3879+AuStubVoid(au_dbg_blocked, void)
1facf9fc 3880+#endif
3881+
3882+#else
4a4d8108
AM
3883+AuStubInt0(__init au_sysrq_init, void)
3884+AuStubVoid(au_sysrq_fin, void)
3885+AuStubVoid(au_dbg_blocked, void)
1facf9fc 3886+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
3887+
3888+#endif /* __KERNEL__ */
3889+#endif /* __AUFS_DEBUG_H__ */
4a4d8108
AM
3890diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/dentry.c linux-2.6.34/fs/aufs/dentry.c
3891--- linux-2.6.34.org/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
3892+++ linux-2.6.34/fs/aufs/dentry.c 2010-05-31 22:15:32.000000000 +0200
3893@@ -0,0 +1,850 @@
1facf9fc 3894+/*
4a4d8108 3895+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3896+ *
3897+ * This program, aufs is free software; you can redistribute it and/or modify
3898+ * it under the terms of the GNU General Public License as published by
3899+ * the Free Software Foundation; either version 2 of the License, or
3900+ * (at your option) any later version.
dece6358
AM
3901+ *
3902+ * This program is distributed in the hope that it will be useful,
3903+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3904+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3905+ * GNU General Public License for more details.
3906+ *
3907+ * You should have received a copy of the GNU General Public License
3908+ * along with this program; if not, write to the Free Software
3909+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3910+ */
3911+
3912+/*
3913+ * lookup and dentry operations
3914+ */
3915+
dece6358 3916+#include <linux/namei.h>
1facf9fc 3917+#include "aufs.h"
3918+
3919+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
3920+{
3921+ if (nd) {
3922+ *h_nd = *nd;
3923+
3924+ /*
3925+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
3926+ * due to whiteout and branch permission.
3927+ */
3928+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
3929+ | LOOKUP_FOLLOW);
3930+ /* unnecessary? */
3931+ h_nd->intent.open.file = NULL;
3932+ } else
3933+ memset(h_nd, 0, sizeof(*h_nd));
3934+}
3935+
3936+struct au_lkup_one_args {
3937+ struct dentry **errp;
3938+ struct qstr *name;
3939+ struct dentry *h_parent;
3940+ struct au_branch *br;
3941+ struct nameidata *nd;
3942+};
3943+
3944+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
3945+ struct au_branch *br, struct nameidata *nd)
3946+{
3947+ struct dentry *h_dentry;
3948+ int err;
3949+ struct nameidata h_nd;
3950+
3951+ if (au_test_fs_null_nd(h_parent->d_sb))
3952+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
3953+
3954+ au_h_nd(&h_nd, nd);
3955+ h_nd.path.dentry = h_parent;
3956+ h_nd.path.mnt = br->br_mnt;
3957+
3958+ err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
3959+ h_dentry = ERR_PTR(err);
3960+ if (!err) {
3961+ path_get(&h_nd.path);
3962+ h_dentry = vfsub_lookup_hash(&h_nd);
3963+ path_put(&h_nd.path);
3964+ }
3965+
4a4d8108 3966+ AuTraceErrPtr(h_dentry);
1facf9fc 3967+ return h_dentry;
3968+}
3969+
3970+static void au_call_lkup_one(void *args)
3971+{
3972+ struct au_lkup_one_args *a = args;
3973+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
3974+}
3975+
3976+#define AuLkup_ALLOW_NEG 1
3977+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
3978+#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; }
3979+#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; }
3980+
3981+struct au_do_lookup_args {
3982+ unsigned int flags;
3983+ mode_t type;
3984+ struct nameidata *nd;
3985+};
3986+
3987+/*
3988+ * returns positive/negative dentry, NULL or an error.
3989+ * NULL means whiteout-ed or not-found.
3990+ */
3991+static struct dentry*
3992+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
3993+ aufs_bindex_t bindex, struct qstr *wh_name,
3994+ struct au_do_lookup_args *args)
3995+{
3996+ struct dentry *h_dentry;
3997+ struct inode *h_inode, *inode;
1facf9fc 3998+ struct au_branch *br;
3999+ int wh_found, opq;
4000+ unsigned char wh_able;
4001+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
4002+
1facf9fc 4003+ wh_found = 0;
4004+ br = au_sbr(dentry->d_sb, bindex);
4005+ wh_able = !!au_br_whable(br->br_perm);
4006+ if (wh_able)
4007+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
4008+ h_dentry = ERR_PTR(wh_found);
4009+ if (!wh_found)
4010+ goto real_lookup;
4011+ if (unlikely(wh_found < 0))
4012+ goto out;
4013+
4014+ /* We found a whiteout */
4015+ /* au_set_dbend(dentry, bindex); */
4016+ au_set_dbwh(dentry, bindex);
4017+ if (!allow_neg)
4018+ return NULL; /* success */
4019+
4020+ real_lookup:
4a4d8108 4021+ h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
1facf9fc 4022+ if (IS_ERR(h_dentry))
4023+ goto out;
4024+
4025+ h_inode = h_dentry->d_inode;
4026+ if (!h_inode) {
4027+ if (!allow_neg)
4028+ goto out_neg;
4029+ } else if (wh_found
4030+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
4031+ goto out_neg;
4032+
4033+ if (au_dbend(dentry) <= bindex)
4034+ au_set_dbend(dentry, bindex);
4035+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4036+ au_set_dbstart(dentry, bindex);
4037+ au_set_h_dptr(dentry, bindex, h_dentry);
4038+
4039+ inode = dentry->d_inode;
4040+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4041+ || (inode && !S_ISDIR(inode->i_mode)))
4042+ goto out; /* success */
4043+
4044+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4045+ opq = au_diropq_test(h_dentry, br);
4046+ mutex_unlock(&h_inode->i_mutex);
4047+ if (opq > 0)
4048+ au_set_dbdiropq(dentry, bindex);
4049+ else if (unlikely(opq < 0)) {
4050+ au_set_h_dptr(dentry, bindex, NULL);
4051+ h_dentry = ERR_PTR(opq);
4052+ }
4053+ goto out;
4054+
4055+ out_neg:
4056+ dput(h_dentry);
4057+ h_dentry = NULL;
4058+ out:
4059+ return h_dentry;
4060+}
4061+
dece6358
AM
4062+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
4063+{
4064+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
4065+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
4066+ return -EPERM;
4067+ return 0;
4068+}
4069+
1facf9fc 4070+/*
4071+ * returns the number of lower positive dentries,
4072+ * otherwise an error.
4073+ * can be called at unlinking with @type is zero.
4074+ */
4075+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4076+ struct nameidata *nd)
4077+{
4078+ int npositive, err;
4079+ aufs_bindex_t bindex, btail, bdiropq;
4080+ unsigned char isdir;
4081+ struct qstr whname;
4082+ struct au_do_lookup_args args = {
4083+ .flags = 0,
4084+ .type = type,
4085+ .nd = nd
4086+ };
4087+ const struct qstr *name = &dentry->d_name;
4088+ struct dentry *parent;
4089+ struct inode *inode;
4090+
dece6358
AM
4091+ err = au_test_shwh(dentry->d_sb, name);
4092+ if (unlikely(err))
1facf9fc 4093+ goto out;
4094+
4095+ err = au_wh_name_alloc(&whname, name);
4096+ if (unlikely(err))
4097+ goto out;
4098+
4099+ inode = dentry->d_inode;
4100+ isdir = !!(inode && S_ISDIR(inode->i_mode));
4101+ if (!type)
4102+ au_fset_lkup(args.flags, ALLOW_NEG);
4103+
4104+ npositive = 0;
4a4d8108 4105+ parent = dget_parent(dentry);
1facf9fc 4106+ btail = au_dbtaildir(parent);
4107+ for (bindex = bstart; bindex <= btail; bindex++) {
4108+ struct dentry *h_parent, *h_dentry;
4109+ struct inode *h_inode, *h_dir;
4110+
4111+ h_dentry = au_h_dptr(dentry, bindex);
4112+ if (h_dentry) {
4113+ if (h_dentry->d_inode)
4114+ npositive++;
4115+ if (type != S_IFDIR)
4116+ break;
4117+ continue;
4118+ }
4119+ h_parent = au_h_dptr(parent, bindex);
4120+ if (!h_parent)
4121+ continue;
4122+ h_dir = h_parent->d_inode;
4123+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
4124+ continue;
4125+
4126+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4127+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4128+ &args);
4129+ mutex_unlock(&h_dir->i_mutex);
4130+ err = PTR_ERR(h_dentry);
4131+ if (IS_ERR(h_dentry))
4a4d8108 4132+ goto out_parent;
1facf9fc 4133+ au_fclr_lkup(args.flags, ALLOW_NEG);
4134+
4135+ if (au_dbwh(dentry) >= 0)
4136+ break;
4137+ if (!h_dentry)
4138+ continue;
4139+ h_inode = h_dentry->d_inode;
4140+ if (!h_inode)
4141+ continue;
4142+ npositive++;
4143+ if (!args.type)
4144+ args.type = h_inode->i_mode & S_IFMT;
4145+ if (args.type != S_IFDIR)
4146+ break;
4147+ else if (isdir) {
4148+ /* the type of lower may be different */
4149+ bdiropq = au_dbdiropq(dentry);
4150+ if (bdiropq >= 0 && bdiropq <= bindex)
4151+ break;
4152+ }
4153+ }
4154+
4155+ if (npositive) {
4156+ AuLabel(positive);
4157+ au_update_dbstart(dentry);
4158+ }
4159+ err = npositive;
4160+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
4161+ && au_dbstart(dentry) < 0))
4162+ /* both of real entry and whiteout found */
4163+ err = -EIO;
4164+
4a4d8108
AM
4165+ out_parent:
4166+ dput(parent);
1facf9fc 4167+ kfree(whname.name);
4168+ out:
1facf9fc 4169+ return err;
4170+}
4171+
4172+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4173+ struct au_branch *br)
4174+{
4175+ struct dentry *dentry;
4176+ int wkq_err;
4177+
4178+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
4179+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
4180+ else {
4181+ struct au_lkup_one_args args = {
4182+ .errp = &dentry,
4183+ .name = name,
4184+ .h_parent = parent,
4185+ .br = br,
4186+ .nd = NULL
4187+ };
4188+
4189+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
4190+ if (unlikely(wkq_err))
4191+ dentry = ERR_PTR(wkq_err);
4192+ }
4193+
4194+ return dentry;
4195+}
4196+
4197+/*
4198+ * lookup @dentry on @bindex which should be negative.
4199+ */
4200+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4201+{
4202+ int err;
4203+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 4204+
1facf9fc 4205+ parent = dget_parent(dentry);
4206+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 4207+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 4208+ au_sbr(dentry->d_sb, bindex));
4209+ err = PTR_ERR(h_dentry);
4210+ if (IS_ERR(h_dentry))
4211+ goto out;
4212+ if (unlikely(h_dentry->d_inode)) {
4213+ err = -EIO;
4214+ AuIOErr("b%d %.*s should be negative.\n",
4215+ bindex, AuDLNPair(h_dentry));
4216+ dput(h_dentry);
4217+ goto out;
4218+ }
4219+
4a4d8108 4220+ err = 0;
1facf9fc 4221+ if (bindex < au_dbstart(dentry))
4222+ au_set_dbstart(dentry, bindex);
4223+ if (au_dbend(dentry) < bindex)
4224+ au_set_dbend(dentry, bindex);
4225+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 4226+
4227+ out:
4228+ dput(parent);
4229+ return err;
4230+}
4231+
4232+/* ---------------------------------------------------------------------- */
4233+
4234+/* subset of struct inode */
4235+struct au_iattr {
4236+ unsigned long i_ino;
4237+ /* unsigned int i_nlink; */
4238+ uid_t i_uid;
4239+ gid_t i_gid;
4240+ u64 i_version;
4241+/*
4242+ loff_t i_size;
4243+ blkcnt_t i_blocks;
4244+*/
4245+ umode_t i_mode;
4246+};
4247+
4248+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
4249+{
4250+ ia->i_ino = h_inode->i_ino;
4251+ /* ia->i_nlink = h_inode->i_nlink; */
4252+ ia->i_uid = h_inode->i_uid;
4253+ ia->i_gid = h_inode->i_gid;
4254+ ia->i_version = h_inode->i_version;
4255+/*
4256+ ia->i_size = h_inode->i_size;
4257+ ia->i_blocks = h_inode->i_blocks;
4258+*/
4259+ ia->i_mode = (h_inode->i_mode & S_IFMT);
4260+}
4261+
4262+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
4263+{
4264+ return ia->i_ino != h_inode->i_ino
4265+ /* || ia->i_nlink != h_inode->i_nlink */
4266+ || ia->i_uid != h_inode->i_uid
4267+ || ia->i_gid != h_inode->i_gid
4268+ || ia->i_version != h_inode->i_version
4269+/*
4270+ || ia->i_size != h_inode->i_size
4271+ || ia->i_blocks != h_inode->i_blocks
4272+*/
4273+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
4274+}
4275+
4276+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
4277+ struct au_branch *br)
4278+{
4279+ int err;
4280+ struct au_iattr ia;
4281+ struct inode *h_inode;
4282+ struct dentry *h_d;
4283+ struct super_block *h_sb;
4284+
4285+ err = 0;
4286+ memset(&ia, -1, sizeof(ia));
4287+ h_sb = h_dentry->d_sb;
4288+ h_inode = h_dentry->d_inode;
4289+ if (h_inode)
4290+ au_iattr_save(&ia, h_inode);
4291+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
4292+ /* nfs d_revalidate may return 0 for negative dentry */
4293+ /* fuse d_revalidate always return 0 for negative dentry */
4294+ goto out;
4295+
4296+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
4297+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
4298+ err = PTR_ERR(h_d);
4299+ if (IS_ERR(h_d))
4300+ goto out;
4301+
4302+ err = 0;
4303+ if (unlikely(h_d != h_dentry
4304+ || h_d->d_inode != h_inode
4305+ || (h_inode && au_iattr_test(&ia, h_inode))))
4306+ err = au_busy_or_stale();
4307+ dput(h_d);
4308+
4309+ out:
4310+ AuTraceErr(err);
4311+ return err;
4312+}
4313+
4314+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
4315+ struct dentry *h_parent, struct au_branch *br)
4316+{
4317+ int err;
4318+
4319+ err = 0;
4320+ if (udba == AuOpt_UDBA_REVAL) {
4321+ IMustLock(h_dir);
4322+ err = (h_dentry->d_parent->d_inode != h_dir);
4a4d8108 4323+ } else if (udba == AuOpt_UDBA_HNOTIFY)
1facf9fc 4324+ err = au_h_verify_dentry(h_dentry, h_parent, br);
4325+
4326+ return err;
4327+}
4328+
4329+/* ---------------------------------------------------------------------- */
4330+
4331+static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
4332+ struct dentry *parent)
4333+{
4334+ struct dentry *h_d, *h_dp;
4335+ struct au_hdentry tmp, *q;
4336+ struct super_block *sb;
4337+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
4338+
1308ab2a 4339+ AuRwMustWriteLock(&dinfo->di_rwsem);
4340+
1facf9fc 4341+ bend = dinfo->di_bend;
4342+ bwh = dinfo->di_bwh;
4343+ bdiropq = dinfo->di_bdiropq;
4344+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
4345+ h_d = p->hd_dentry;
4346+ if (!h_d)
4347+ continue;
4348+
4349+ h_dp = dget_parent(h_d);
4350+ if (h_dp == au_h_dptr(parent, bindex)) {
4351+ dput(h_dp);
4352+ continue;
4353+ }
4354+
4355+ new_bindex = au_find_dbindex(parent, h_dp);
4356+ dput(h_dp);
4357+ if (dinfo->di_bwh == bindex)
4358+ bwh = new_bindex;
4359+ if (dinfo->di_bdiropq == bindex)
4360+ bdiropq = new_bindex;
4361+ if (new_bindex < 0) {
4362+ au_hdput(p);
4363+ p->hd_dentry = NULL;
4364+ continue;
4365+ }
4366+
4367+ /* swap two lower dentries, and loop again */
4368+ q = dinfo->di_hdentry + new_bindex;
4369+ tmp = *q;
4370+ *q = *p;
4371+ *p = tmp;
4372+ if (tmp.hd_dentry) {
4373+ bindex--;
4374+ p--;
4375+ }
4376+ }
4377+
4378+ sb = parent->d_sb;
4379+ dinfo->di_bwh = -1;
4380+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
4381+ dinfo->di_bwh = bwh;
4382+
4383+ dinfo->di_bdiropq = -1;
4384+ if (bdiropq >= 0
4385+ && bdiropq <= au_sbend(sb)
4386+ && au_sbr_whable(sb, bdiropq))
4387+ dinfo->di_bdiropq = bdiropq;
4388+
4389+ bend = au_dbend(parent);
4390+ p = dinfo->di_hdentry;
4391+ for (bindex = 0; bindex <= bend; bindex++, p++)
4392+ if (p->hd_dentry) {
4393+ dinfo->di_bstart = bindex;
4394+ break;
4395+ }
4396+
4397+ p = dinfo->di_hdentry + bend;
4398+ for (bindex = bend; bindex >= 0; bindex--, p--)
4399+ if (p->hd_dentry) {
4400+ dinfo->di_bend = bindex;
4401+ break;
4402+ }
4403+}
4404+
4405+/*
4406+ * returns the number of found lower positive dentries,
4407+ * otherwise an error.
4408+ */
4409+int au_refresh_hdentry(struct dentry *dentry, mode_t type)
4410+{
4411+ int npositive, err;
4412+ unsigned int sigen;
4413+ aufs_bindex_t bstart;
4414+ struct au_dinfo *dinfo;
4415+ struct super_block *sb;
4416+ struct dentry *parent;
4417+
1308ab2a 4418+ DiMustWriteLock(dentry);
4419+
1facf9fc 4420+ sb = dentry->d_sb;
4421+ AuDebugOn(IS_ROOT(dentry));
4422+ sigen = au_sigen(sb);
4423+ parent = dget_parent(dentry);
4424+ AuDebugOn(au_digen(parent) != sigen
4425+ || au_iigen(parent->d_inode) != sigen);
4426+
4427+ dinfo = au_di(dentry);
4428+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
4429+ npositive = err;
4430+ if (unlikely(err))
4431+ goto out;
4432+ au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
4433+ parent);
4434+
4435+ npositive = 0;
4436+ bstart = au_dbstart(parent);
4437+ if (type != S_IFDIR && dinfo->di_bstart == bstart)
4438+ goto out_dgen; /* success */
4439+
4440+ npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
4441+ if (npositive < 0)
4442+ goto out;
4443+ if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
4444+ d_drop(dentry);
4445+
4446+ out_dgen:
4447+ au_update_digen(dentry);
4448+ out:
4449+ dput(parent);
4450+ AuTraceErr(npositive);
4451+ return npositive;
4452+}
4453+
4454+static noinline_for_stack
4455+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
4456+ struct dentry *dentry, aufs_bindex_t bindex)
4457+{
4458+ int err, valid;
4459+ int (*reval)(struct dentry *, struct nameidata *);
4460+
4461+ err = 0;
4462+ reval = NULL;
4463+ if (h_dentry->d_op)
4464+ reval = h_dentry->d_op->d_revalidate;
4465+ if (!reval)
4466+ goto out;
4467+
4468+ AuDbg("b%d\n", bindex);
4469+ if (au_test_fs_null_nd(h_dentry->d_sb))
4470+ /* it may return tri-state */
4471+ valid = reval(h_dentry, NULL);
4472+ else {
4473+ struct nameidata h_nd;
4474+ int locked;
4475+ struct dentry *parent;
4476+
4477+ au_h_nd(&h_nd, nd);
4478+ parent = nd->path.dentry;
4479+ locked = (nd && nd->path.dentry != dentry);
4480+ if (locked)
4481+ di_read_lock_parent(parent, AuLock_IR);
4482+ BUG_ON(bindex > au_dbend(parent));
4483+ h_nd.path.dentry = au_h_dptr(parent, bindex);
4484+ BUG_ON(!h_nd.path.dentry);
4485+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
4486+ path_get(&h_nd.path);
4487+ valid = reval(h_dentry, &h_nd);
4488+ path_put(&h_nd.path);
4489+ if (locked)
4490+ di_read_unlock(parent, AuLock_IR);
4491+ }
4492+
4493+ if (unlikely(valid < 0))
4494+ err = valid;
4495+ else if (!valid)
4496+ err = -EINVAL;
4497+
4498+ out:
4499+ AuTraceErr(err);
4500+ return err;
4501+}
4502+
4503+/* todo: remove this */
4504+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
4505+ struct nameidata *nd, int do_udba)
4506+{
4507+ int err;
4508+ umode_t mode, h_mode;
4509+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
4510+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 4511+ struct inode *h_inode, *h_cached_inode;
1facf9fc 4512+ struct dentry *h_dentry;
4513+ struct qstr *name, *h_name;
4514+
4515+ err = 0;
4516+ plus = 0;
4517+ mode = 0;
1facf9fc 4518+ ibs = -1;
4519+ ibe = -1;
4520+ unhashed = !!d_unhashed(dentry);
4521+ is_root = !!IS_ROOT(dentry);
4522+ name = &dentry->d_name;
4523+
4524+ /*
4525+ * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
4526+ * But inotify doesn't fire some necessary events,
4527+ * IN_ATTRIB for atime/nlink/pageio
4528+ * IN_DELETE for NFS dentry
4529+ * Let's do REVAL test too.
4530+ */
4531+ if (do_udba && inode) {
4532+ mode = (inode->i_mode & S_IFMT);
4533+ plus = (inode->i_nlink > 0);
1facf9fc 4534+ ibs = au_ibstart(inode);
4535+ ibe = au_ibend(inode);
4536+ }
4537+
4538+ bstart = au_dbstart(dentry);
4539+ btail = bstart;
4540+ if (inode && S_ISDIR(inode->i_mode))
4541+ btail = au_dbtaildir(dentry);
4542+ for (bindex = bstart; bindex <= btail; bindex++) {
4543+ h_dentry = au_h_dptr(dentry, bindex);
4544+ if (!h_dentry)
4545+ continue;
4546+
4547+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
4548+ h_name = &h_dentry->d_name;
4549+ if (unlikely(do_udba
4550+ && !is_root
4551+ && (unhashed != !!d_unhashed(h_dentry)
4552+ || name->len != h_name->len
4553+ || memcmp(name->name, h_name->name, name->len))
4554+ )) {
4555+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
4556+ unhashed, d_unhashed(h_dentry),
4557+ AuDLNPair(dentry), AuDLNPair(h_dentry));
4558+ goto err;
4559+ }
4560+
4561+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
4562+ if (unlikely(err))
4563+ /* do not goto err, to keep the errno */
4564+ break;
4565+
4566+ /* todo: plink too? */
4567+ if (!do_udba)
4568+ continue;
4569+
4570+ /* UDBA tests */
4571+ h_inode = h_dentry->d_inode;
4572+ if (unlikely(!!inode != !!h_inode))
4573+ goto err;
4574+
4575+ h_plus = plus;
4576+ h_mode = mode;
4577+ h_cached_inode = h_inode;
4578+ if (h_inode) {
4579+ h_mode = (h_inode->i_mode & S_IFMT);
4580+ h_plus = (h_inode->i_nlink > 0);
4581+ }
4582+ if (inode && ibs <= bindex && bindex <= ibe)
4583+ h_cached_inode = au_h_iptr(inode, bindex);
4584+
4585+ if (unlikely(plus != h_plus
4586+ || mode != h_mode
4587+ || h_cached_inode != h_inode))
4588+ goto err;
4589+ continue;
4590+
4591+ err:
4592+ err = -EINVAL;
4593+ break;
4594+ }
4595+
4596+ return err;
4597+}
4598+
4599+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
4600+{
4601+ int err;
4602+ struct dentry *parent;
4603+ struct inode *inode;
4604+
4605+ inode = dentry->d_inode;
4606+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
4607+ return 0;
4608+
4609+ parent = dget_parent(dentry);
4610+ di_read_lock_parent(parent, AuLock_IR);
4611+ AuDebugOn(au_digen(parent) != sigen
4612+ || au_iigen(parent->d_inode) != sigen);
4613+ au_dbg_verify_gen(parent, sigen);
4614+
4615+ /* returns a number of positive dentries */
4616+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
4617+ if (err >= 0)
4618+ err = au_refresh_hinode(inode, dentry);
4619+
4620+ di_read_unlock(parent, AuLock_IR);
4621+ dput(parent);
4622+ return err;
4623+}
4624+
4625+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
4626+{
4627+ int err;
4628+ struct dentry *d, *parent;
4629+ struct inode *inode;
4630+
4631+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
4632+ return simple_reval_dpath(dentry, sigen);
4633+
4634+ /* slow loop, keep it simple and stupid */
4635+ /* cf: au_cpup_dirs() */
4636+ err = 0;
4637+ parent = NULL;
4638+ while (au_digen(dentry) != sigen
4639+ || au_iigen(dentry->d_inode) != sigen) {
4640+ d = dentry;
4641+ while (1) {
4642+ dput(parent);
4643+ parent = dget_parent(d);
4644+ if (au_digen(parent) == sigen
4645+ && au_iigen(parent->d_inode) == sigen)
4646+ break;
4647+ d = parent;
4648+ }
4649+
4650+ inode = d->d_inode;
4651+ if (d != dentry)
4652+ di_write_lock_child(d);
4653+
4654+ /* someone might update our dentry while we were sleeping */
4655+ if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
4656+ di_read_lock_parent(parent, AuLock_IR);
4657+ /* returns a number of positive dentries */
4658+ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
4659+ if (err >= 0)
4660+ err = au_refresh_hinode(inode, d);
4661+ di_read_unlock(parent, AuLock_IR);
4662+ }
4663+
4664+ if (d != dentry)
4665+ di_write_unlock(d);
4666+ dput(parent);
4667+ if (unlikely(err))
4668+ break;
4669+ }
4670+
4671+ return err;
4672+}
4673+
4674+/*
4675+ * if valid returns 1, otherwise 0.
4676+ */
4677+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
4678+{
4679+ int valid, err;
4680+ unsigned int sigen;
4681+ unsigned char do_udba;
4682+ struct super_block *sb;
4683+ struct inode *inode;
4684+
4685+ err = -EINVAL;
4686+ sb = dentry->d_sb;
4687+ inode = dentry->d_inode;
4688+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
4689+ sigen = au_sigen(sb);
4690+ if (au_digen(dentry) != sigen) {
4691+ AuDebugOn(IS_ROOT(dentry));
4692+ if (inode)
4693+ err = au_reval_dpath(dentry, sigen);
4694+ if (unlikely(err))
4695+ goto out_dgrade;
1facf9fc 4696+ }
4697+ if (inode && au_iigen(inode) != sigen) {
4698+ AuDebugOn(IS_ROOT(dentry));
4699+ err = au_refresh_hinode(inode, dentry);
4700+ if (unlikely(err))
4701+ goto out_dgrade;
1facf9fc 4702+ }
4703+ di_downgrade_lock(dentry, AuLock_IR);
4704+
1facf9fc 4705+ err = -EINVAL;
4706+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
4707+ if (do_udba && inode) {
4708+ aufs_bindex_t bstart = au_ibstart(inode);
4709+
4710+ if (bstart >= 0
4711+ && au_test_higen(inode, au_h_iptr(inode, bstart)))
4712+ goto out;
4713+ }
4714+
4715+ err = h_d_revalidate(dentry, inode, nd, do_udba);
4716+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
4717+ /* both of real entry and whiteout found */
4718+ err = -EIO;
4719+ goto out;
4720+
4721+ out_dgrade:
4722+ di_downgrade_lock(dentry, AuLock_IR);
4723+ out:
1facf9fc 4724+ aufs_read_unlock(dentry, AuLock_IR);
4725+ AuTraceErr(err);
4726+ valid = !err;
4727+ if (!valid)
4728+ AuDbg("%.*s invalid\n", AuDLNPair(dentry));
4729+ return valid;
4730+}
4731+
4732+static void aufs_d_release(struct dentry *dentry)
4733+{
4a4d8108
AM
4734+ if (dentry->d_fsdata) {
4735+ au_di_fin(dentry);
4736+ au_hn_di_reinit(dentry);
1facf9fc 4737+ }
1facf9fc 4738+}
4739+
4a4d8108 4740+const struct dentry_operations aufs_dop = {
1facf9fc 4741+ .d_revalidate = aufs_d_revalidate,
4742+ .d_release = aufs_d_release
4743+};
4a4d8108
AM
4744diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/dentry.h linux-2.6.34/fs/aufs/dentry.h
4745--- linux-2.6.34.org/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
4746+++ linux-2.6.34/fs/aufs/dentry.h 2010-05-31 22:15:32.000000000 +0200
1308ab2a 4747@@ -0,0 +1,231 @@
1facf9fc 4748+/*
4a4d8108 4749+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4750+ *
4751+ * This program, aufs is free software; you can redistribute it and/or modify
4752+ * it under the terms of the GNU General Public License as published by
4753+ * the Free Software Foundation; either version 2 of the License, or
4754+ * (at your option) any later version.
dece6358
AM
4755+ *
4756+ * This program is distributed in the hope that it will be useful,
4757+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4758+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4759+ * GNU General Public License for more details.
4760+ *
4761+ * You should have received a copy of the GNU General Public License
4762+ * along with this program; if not, write to the Free Software
4763+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4764+ */
4765+
4766+/*
4767+ * lookup and dentry operations
4768+ */
4769+
4770+#ifndef __AUFS_DENTRY_H__
4771+#define __AUFS_DENTRY_H__
4772+
4773+#ifdef __KERNEL__
4774+
dece6358 4775+#include <linux/dcache.h>
1facf9fc 4776+#include <linux/aufs_type.h>
4777+#include "rwsem.h"
4778+
4779+/* make a single member structure for future use */
4780+/* todo: remove this structure */
4781+struct au_hdentry {
4782+ struct dentry *hd_dentry;
4783+};
4784+
4785+struct au_dinfo {
4786+ atomic_t di_generation;
4787+
dece6358 4788+ struct au_rwsem di_rwsem;
1facf9fc 4789+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
4790+ struct au_hdentry *di_hdentry;
4a4d8108 4791+} ____cacheline_aligned_in_smp;
1facf9fc 4792+
4793+/* ---------------------------------------------------------------------- */
4794+
4795+/* dentry.c */
4a4d8108 4796+extern const struct dentry_operations aufs_dop;
1facf9fc 4797+struct au_branch;
4798+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
4799+ struct au_branch *br, struct nameidata *nd);
4800+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4801+ struct au_branch *br);
4802+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
4803+ struct dentry *h_parent, struct au_branch *br);
4804+
4805+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4806+ struct nameidata *nd);
4807+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
4808+int au_refresh_hdentry(struct dentry *dentry, mode_t type);
4809+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
4810+
4811+/* dinfo.c */
4a4d8108
AM
4812+void au_di_init_once(void *_di);
4813+int au_di_init(struct dentry *dentry);
4814+void au_di_fin(struct dentry *dentry);
1facf9fc 4815+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
4816+
4817+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
4818+void di_read_unlock(struct dentry *d, int flags);
4819+void di_downgrade_lock(struct dentry *d, int flags);
4820+void di_write_lock(struct dentry *d, unsigned int lsc);
4821+void di_write_unlock(struct dentry *d);
4822+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
4823+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
4824+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
4825+
4826+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
4827+aufs_bindex_t au_dbtail(struct dentry *dentry);
4828+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
4829+
4830+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
4831+ struct dentry *h_dentry);
4832+void au_update_digen(struct dentry *dentry);
4833+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
4834+void au_update_dbstart(struct dentry *dentry);
4835+void au_update_dbend(struct dentry *dentry);
4836+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
4837+
4838+/* ---------------------------------------------------------------------- */
4839+
4840+static inline struct au_dinfo *au_di(struct dentry *dentry)
4841+{
4842+ return dentry->d_fsdata;
4843+}
4844+
4845+/* ---------------------------------------------------------------------- */
4846+
4847+/* lock subclass for dinfo */
4848+enum {
4849+ AuLsc_DI_CHILD, /* child first */
4a4d8108 4850+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 4851+ AuLsc_DI_CHILD3, /* copyup dirs */
4852+ AuLsc_DI_PARENT,
4853+ AuLsc_DI_PARENT2,
4854+ AuLsc_DI_PARENT3
4855+};
4856+
4857+/*
4858+ * di_read_lock_child, di_write_lock_child,
4859+ * di_read_lock_child2, di_write_lock_child2,
4860+ * di_read_lock_child3, di_write_lock_child3,
4861+ * di_read_lock_parent, di_write_lock_parent,
4862+ * di_read_lock_parent2, di_write_lock_parent2,
4863+ * di_read_lock_parent3, di_write_lock_parent3,
4864+ */
4865+#define AuReadLockFunc(name, lsc) \
4866+static inline void di_read_lock_##name(struct dentry *d, int flags) \
4867+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
4868+
4869+#define AuWriteLockFunc(name, lsc) \
4870+static inline void di_write_lock_##name(struct dentry *d) \
4871+{ di_write_lock(d, AuLsc_DI_##lsc); }
4872+
4873+#define AuRWLockFuncs(name, lsc) \
4874+ AuReadLockFunc(name, lsc) \
4875+ AuWriteLockFunc(name, lsc)
4876+
4877+AuRWLockFuncs(child, CHILD);
4878+AuRWLockFuncs(child2, CHILD2);
4879+AuRWLockFuncs(child3, CHILD3);
4880+AuRWLockFuncs(parent, PARENT);
4881+AuRWLockFuncs(parent2, PARENT2);
4882+AuRWLockFuncs(parent3, PARENT3);
4883+
4884+#undef AuReadLockFunc
4885+#undef AuWriteLockFunc
4886+#undef AuRWLockFuncs
4887+
4888+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
4889+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
4890+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 4891+
4892+/* ---------------------------------------------------------------------- */
4893+
4894+/* todo: memory barrier? */
4895+static inline unsigned int au_digen(struct dentry *d)
4896+{
4897+ return atomic_read(&au_di(d)->di_generation);
4898+}
4899+
4900+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
4901+{
4902+ hdentry->hd_dentry = NULL;
4903+}
4904+
4905+static inline void au_hdput(struct au_hdentry *hd)
4906+{
4a4d8108
AM
4907+ if (hd)
4908+ dput(hd->hd_dentry);
1facf9fc 4909+}
4910+
4911+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
4912+{
1308ab2a 4913+ DiMustAnyLock(dentry);
1facf9fc 4914+ return au_di(dentry)->di_bstart;
4915+}
4916+
4917+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
4918+{
1308ab2a 4919+ DiMustAnyLock(dentry);
1facf9fc 4920+ return au_di(dentry)->di_bend;
4921+}
4922+
4923+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
4924+{
1308ab2a 4925+ DiMustAnyLock(dentry);
1facf9fc 4926+ return au_di(dentry)->di_bwh;
4927+}
4928+
4929+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
4930+{
1308ab2a 4931+ DiMustAnyLock(dentry);
1facf9fc 4932+ return au_di(dentry)->di_bdiropq;
4933+}
4934+
4935+/* todo: hard/soft set? */
4936+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
4937+{
1308ab2a 4938+ DiMustWriteLock(dentry);
1facf9fc 4939+ au_di(dentry)->di_bstart = bindex;
4940+}
4941+
4942+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
4943+{
1308ab2a 4944+ DiMustWriteLock(dentry);
1facf9fc 4945+ au_di(dentry)->di_bend = bindex;
4946+}
4947+
4948+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
4949+{
1308ab2a 4950+ DiMustWriteLock(dentry);
1facf9fc 4951+ /* dbwh can be outside of bstart - bend range */
4952+ au_di(dentry)->di_bwh = bindex;
4953+}
4954+
4955+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
4956+{
1308ab2a 4957+ DiMustWriteLock(dentry);
1facf9fc 4958+ au_di(dentry)->di_bdiropq = bindex;
4959+}
4960+
4961+/* ---------------------------------------------------------------------- */
4962+
4a4d8108 4963+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 4964+static inline void au_digen_dec(struct dentry *d)
4965+{
dece6358 4966+ atomic_dec_return(&au_di(d)->di_generation);
1facf9fc 4967+}
4968+
4a4d8108 4969+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 4970+{
4971+ dentry->d_fsdata = NULL;
4972+}
4973+#else
4a4d8108
AM
4974+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
4975+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 4976+
4977+#endif /* __KERNEL__ */
4978+#endif /* __AUFS_DENTRY_H__ */
4a4d8108
AM
4979diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/dinfo.c linux-2.6.34/fs/aufs/dinfo.c
4980--- linux-2.6.34.org/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
4981+++ linux-2.6.34/fs/aufs/dinfo.c 2010-05-31 22:15:32.000000000 +0200
4982@@ -0,0 +1,395 @@
1facf9fc 4983+/*
4a4d8108 4984+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4985+ *
4986+ * This program, aufs is free software; you can redistribute it and/or modify
4987+ * it under the terms of the GNU General Public License as published by
4988+ * the Free Software Foundation; either version 2 of the License, or
4989+ * (at your option) any later version.
dece6358
AM
4990+ *
4991+ * This program is distributed in the hope that it will be useful,
4992+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4993+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4994+ * GNU General Public License for more details.
4995+ *
4996+ * You should have received a copy of the GNU General Public License
4997+ * along with this program; if not, write to the Free Software
4998+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4999+ */
5000+
5001+/*
5002+ * dentry private data
5003+ */
5004+
5005+#include "aufs.h"
5006+
4a4d8108
AM
5007+void au_di_init_once(void *_di)
5008+{
5009+ struct au_dinfo *di = _di;
5010+
5011+ au_rw_init(&di->di_rwsem);
5012+}
5013+
5014+int au_di_init(struct dentry *dentry)
1facf9fc 5015+{
5016+ struct au_dinfo *dinfo;
5017+ struct super_block *sb;
5018+ int nbr;
5019+
5020+ dinfo = au_cache_alloc_dinfo();
5021+ if (unlikely(!dinfo))
5022+ goto out;
5023+
5024+ sb = dentry->d_sb;
5025+ nbr = au_sbend(sb) + 1;
5026+ if (nbr <= 0)
5027+ nbr = 1;
5028+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
5029+ if (unlikely(!dinfo->di_hdentry))
5030+ goto out_dinfo;
5031+
5032+ atomic_set(&dinfo->di_generation, au_sigen(sb));
5033+ /* smp_mb(); */ /* atomic_set */
4a4d8108 5034+ au_rw_write_lock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
1facf9fc 5035+ dinfo->di_bstart = -1;
5036+ dinfo->di_bend = -1;
5037+ dinfo->di_bwh = -1;
5038+ dinfo->di_bdiropq = -1;
5039+
5040+ dentry->d_fsdata = dinfo;
5041+ dentry->d_op = &aufs_dop;
5042+ return 0; /* success */
5043+
5044+ out_dinfo:
5045+ au_cache_free_dinfo(dinfo);
5046+ out:
5047+ return -ENOMEM;
5048+}
5049+
4a4d8108
AM
5050+void au_di_fin(struct dentry *dentry)
5051+{
5052+ struct au_dinfo *di;
5053+ struct au_hdentry *p;
5054+ aufs_bindex_t bend, bindex;
5055+
5056+ /* dentry may not be revalidated */
5057+ di = dentry->d_fsdata;
5058+ bindex = di->di_bstart;
5059+ if (bindex >= 0) {
5060+ bend = di->di_bend;
5061+ p = di->di_hdentry + bindex;
5062+ while (bindex++ <= bend)
5063+ au_hdput(p++);
5064+ }
5065+ kfree(di->di_hdentry);
5066+ AuRwDestroy(&di->di_rwsem);
5067+ au_cache_free_dinfo(di);
5068+}
5069+
1facf9fc 5070+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
5071+{
5072+ int err, sz;
5073+ struct au_hdentry *hdp;
5074+
1308ab2a 5075+ AuRwMustWriteLock(&dinfo->di_rwsem);
5076+
1facf9fc 5077+ err = -ENOMEM;
5078+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
5079+ if (!sz)
5080+ sz = sizeof(*hdp);
5081+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
5082+ if (hdp) {
5083+ dinfo->di_hdentry = hdp;
5084+ err = 0;
5085+ }
5086+
5087+ return err;
5088+}
5089+
5090+/* ---------------------------------------------------------------------- */
5091+
5092+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
5093+{
5094+ switch (lsc) {
5095+ case AuLsc_DI_CHILD:
5096+ ii_write_lock_child(inode);
5097+ break;
5098+ case AuLsc_DI_CHILD2:
5099+ ii_write_lock_child2(inode);
5100+ break;
5101+ case AuLsc_DI_CHILD3:
5102+ ii_write_lock_child3(inode);
5103+ break;
5104+ case AuLsc_DI_PARENT:
5105+ ii_write_lock_parent(inode);
5106+ break;
5107+ case AuLsc_DI_PARENT2:
5108+ ii_write_lock_parent2(inode);
5109+ break;
5110+ case AuLsc_DI_PARENT3:
5111+ ii_write_lock_parent3(inode);
5112+ break;
5113+ default:
5114+ BUG();
5115+ }
5116+}
5117+
5118+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
5119+{
5120+ switch (lsc) {
5121+ case AuLsc_DI_CHILD:
5122+ ii_read_lock_child(inode);
5123+ break;
5124+ case AuLsc_DI_CHILD2:
5125+ ii_read_lock_child2(inode);
5126+ break;
5127+ case AuLsc_DI_CHILD3:
5128+ ii_read_lock_child3(inode);
5129+ break;
5130+ case AuLsc_DI_PARENT:
5131+ ii_read_lock_parent(inode);
5132+ break;
5133+ case AuLsc_DI_PARENT2:
5134+ ii_read_lock_parent2(inode);
5135+ break;
5136+ case AuLsc_DI_PARENT3:
5137+ ii_read_lock_parent3(inode);
5138+ break;
5139+ default:
5140+ BUG();
5141+ }
5142+}
5143+
5144+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
5145+{
dece6358 5146+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5147+ if (d->d_inode) {
5148+ if (au_ftest_lock(flags, IW))
5149+ do_ii_write_lock(d->d_inode, lsc);
5150+ else if (au_ftest_lock(flags, IR))
5151+ do_ii_read_lock(d->d_inode, lsc);
5152+ }
5153+}
5154+
5155+void di_read_unlock(struct dentry *d, int flags)
5156+{
5157+ if (d->d_inode) {
5158+ if (au_ftest_lock(flags, IW))
5159+ ii_write_unlock(d->d_inode);
5160+ else if (au_ftest_lock(flags, IR))
5161+ ii_read_unlock(d->d_inode);
5162+ }
dece6358 5163+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 5164+}
5165+
5166+void di_downgrade_lock(struct dentry *d, int flags)
5167+{
1facf9fc 5168+ if (d->d_inode && au_ftest_lock(flags, IR))
5169+ ii_downgrade_lock(d->d_inode);
dece6358 5170+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 5171+}
5172+
5173+void di_write_lock(struct dentry *d, unsigned int lsc)
5174+{
dece6358 5175+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5176+ if (d->d_inode)
5177+ do_ii_write_lock(d->d_inode, lsc);
5178+}
5179+
5180+void di_write_unlock(struct dentry *d)
5181+{
5182+ if (d->d_inode)
5183+ ii_write_unlock(d->d_inode);
dece6358 5184+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 5185+}
5186+
5187+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
5188+{
5189+ AuDebugOn(d1 == d2
5190+ || d1->d_inode == d2->d_inode
5191+ || d1->d_sb != d2->d_sb);
5192+
5193+ if (isdir && au_test_subdir(d1, d2)) {
5194+ di_write_lock_child(d1);
5195+ di_write_lock_child2(d2);
5196+ } else {
5197+ /* there should be no races */
5198+ di_write_lock_child(d2);
5199+ di_write_lock_child2(d1);
5200+ }
5201+}
5202+
5203+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
5204+{
5205+ AuDebugOn(d1 == d2
5206+ || d1->d_inode == d2->d_inode
5207+ || d1->d_sb != d2->d_sb);
5208+
5209+ if (isdir && au_test_subdir(d1, d2)) {
5210+ di_write_lock_parent(d1);
5211+ di_write_lock_parent2(d2);
5212+ } else {
5213+ /* there should be no races */
5214+ di_write_lock_parent(d2);
5215+ di_write_lock_parent2(d1);
5216+ }
5217+}
5218+
5219+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
5220+{
5221+ di_write_unlock(d1);
5222+ if (d1->d_inode == d2->d_inode)
dece6358 5223+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 5224+ else
5225+ di_write_unlock(d2);
5226+}
5227+
5228+/* ---------------------------------------------------------------------- */
5229+
5230+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
5231+{
5232+ struct dentry *d;
5233+
1308ab2a 5234+ DiMustAnyLock(dentry);
5235+
1facf9fc 5236+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
5237+ return NULL;
5238+ AuDebugOn(bindex < 0);
5239+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
5240+ AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
5241+ return d;
5242+}
5243+
5244+aufs_bindex_t au_dbtail(struct dentry *dentry)
5245+{
5246+ aufs_bindex_t bend, bwh;
5247+
5248+ bend = au_dbend(dentry);
5249+ if (0 <= bend) {
5250+ bwh = au_dbwh(dentry);
5251+ if (!bwh)
5252+ return bwh;
5253+ if (0 < bwh && bwh < bend)
5254+ return bwh - 1;
5255+ }
5256+ return bend;
5257+}
5258+
5259+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
5260+{
5261+ aufs_bindex_t bend, bopq;
5262+
5263+ bend = au_dbtail(dentry);
5264+ if (0 <= bend) {
5265+ bopq = au_dbdiropq(dentry);
5266+ if (0 <= bopq && bopq < bend)
5267+ bend = bopq;
5268+ }
5269+ return bend;
5270+}
5271+
5272+/* ---------------------------------------------------------------------- */
5273+
5274+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5275+ struct dentry *h_dentry)
5276+{
5277+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
5278+
1308ab2a 5279+ DiMustWriteLock(dentry);
5280+
4a4d8108 5281+ au_hdput(hd);
1facf9fc 5282+ hd->hd_dentry = h_dentry;
5283+}
5284+
5285+void au_update_digen(struct dentry *dentry)
5286+{
5287+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
5288+ /* smp_mb(); */ /* atomic_set */
5289+}
5290+
5291+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
5292+{
5293+ struct au_dinfo *dinfo;
5294+ struct dentry *h_d;
4a4d8108 5295+ struct au_hdentry *hdp;
1facf9fc 5296+
1308ab2a 5297+ DiMustWriteLock(dentry);
5298+
1facf9fc 5299+ dinfo = au_di(dentry);
5300+ if (!dinfo || dinfo->di_bstart < 0)
5301+ return;
5302+
4a4d8108 5303+ hdp = dinfo->di_hdentry;
1facf9fc 5304+ if (do_put_zero) {
5305+ aufs_bindex_t bindex, bend;
5306+
5307+ bend = dinfo->di_bend;
5308+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 5309+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 5310+ if (h_d && !h_d->d_inode)
5311+ au_set_h_dptr(dentry, bindex, NULL);
5312+ }
5313+ }
5314+
5315+ dinfo->di_bstart = -1;
5316+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 5317+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 5318+ break;
5319+ if (dinfo->di_bstart > dinfo->di_bend) {
5320+ dinfo->di_bstart = -1;
5321+ dinfo->di_bend = -1;
5322+ return;
5323+ }
5324+
5325+ dinfo->di_bend++;
5326+ while (0 <= --dinfo->di_bend)
4a4d8108 5327+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 5328+ break;
5329+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
5330+}
5331+
5332+void au_update_dbstart(struct dentry *dentry)
5333+{
5334+ aufs_bindex_t bindex, bend;
5335+ struct dentry *h_dentry;
5336+
5337+ bend = au_dbend(dentry);
5338+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
5339+ h_dentry = au_h_dptr(dentry, bindex);
5340+ if (!h_dentry)
5341+ continue;
5342+ if (h_dentry->d_inode) {
5343+ au_set_dbstart(dentry, bindex);
5344+ return;
5345+ }
5346+ au_set_h_dptr(dentry, bindex, NULL);
5347+ }
5348+}
5349+
5350+void au_update_dbend(struct dentry *dentry)
5351+{
5352+ aufs_bindex_t bindex, bstart;
5353+ struct dentry *h_dentry;
5354+
5355+ bstart = au_dbstart(dentry);
5356+ for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
5357+ h_dentry = au_h_dptr(dentry, bindex);
5358+ if (!h_dentry)
5359+ continue;
5360+ if (h_dentry->d_inode) {
5361+ au_set_dbend(dentry, bindex);
5362+ return;
5363+ }
5364+ au_set_h_dptr(dentry, bindex, NULL);
5365+ }
5366+}
5367+
5368+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
5369+{
5370+ aufs_bindex_t bindex, bend;
5371+
5372+ bend = au_dbend(dentry);
5373+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
5374+ if (au_h_dptr(dentry, bindex) == h_dentry)
5375+ return bindex;
5376+ return -1;
5377+}
4a4d8108
AM
5378diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/dir.c linux-2.6.34/fs/aufs/dir.c
5379--- linux-2.6.34.org/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
5380+++ linux-2.6.34/fs/aufs/dir.c 2010-05-31 22:15:32.000000000 +0200
5381@@ -0,0 +1,637 @@
1facf9fc 5382+/*
4a4d8108 5383+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5384+ *
5385+ * This program, aufs is free software; you can redistribute it and/or modify
5386+ * it under the terms of the GNU General Public License as published by
5387+ * the Free Software Foundation; either version 2 of the License, or
5388+ * (at your option) any later version.
dece6358
AM
5389+ *
5390+ * This program is distributed in the hope that it will be useful,
5391+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5392+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5393+ * GNU General Public License for more details.
5394+ *
5395+ * You should have received a copy of the GNU General Public License
5396+ * along with this program; if not, write to the Free Software
5397+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5398+ */
5399+
5400+/*
5401+ * directory operations
5402+ */
5403+
dece6358 5404+#include <linux/file.h>
1facf9fc 5405+#include <linux/fs_stack.h>
5406+#include "aufs.h"
5407+
5408+void au_add_nlink(struct inode *dir, struct inode *h_dir)
5409+{
5410+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5411+
5412+ dir->i_nlink += h_dir->i_nlink - 2;
5413+ if (h_dir->i_nlink < 2)
5414+ dir->i_nlink += 2;
5415+}
5416+
5417+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
5418+{
5419+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5420+
5421+ dir->i_nlink -= h_dir->i_nlink - 2;
5422+ if (h_dir->i_nlink < 2)
5423+ dir->i_nlink -= 2;
5424+}
5425+
1308ab2a 5426+loff_t au_dir_size(struct file *file, struct dentry *dentry)
5427+{
5428+ loff_t sz;
5429+ aufs_bindex_t bindex, bend;
5430+ struct file *h_file;
5431+ struct dentry *h_dentry;
5432+
5433+ sz = 0;
5434+ if (file) {
5435+ AuDebugOn(!file->f_dentry);
5436+ AuDebugOn(!file->f_dentry->d_inode);
5437+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
5438+
4a4d8108 5439+ bend = au_fbend_dir(file);
1308ab2a 5440+ for (bindex = au_fbstart(file);
5441+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5442+ bindex++) {
4a4d8108 5443+ h_file = au_hf_dir(file, bindex);
1308ab2a 5444+ if (h_file
5445+ && h_file->f_dentry
5446+ && h_file->f_dentry->d_inode)
5447+ sz += i_size_read(h_file->f_dentry->d_inode);
5448+ }
5449+ } else {
5450+ AuDebugOn(!dentry);
5451+ AuDebugOn(!dentry->d_inode);
5452+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
5453+
5454+ bend = au_dbtaildir(dentry);
5455+ for (bindex = au_dbstart(dentry);
5456+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5457+ bindex++) {
5458+ h_dentry = au_h_dptr(dentry, bindex);
5459+ if (h_dentry && h_dentry->d_inode)
5460+ sz += i_size_read(h_dentry->d_inode);
5461+ }
5462+ }
5463+ if (sz < KMALLOC_MAX_SIZE)
5464+ sz = roundup_pow_of_two(sz);
5465+ if (sz > KMALLOC_MAX_SIZE)
5466+ sz = KMALLOC_MAX_SIZE;
5467+ else if (sz < NAME_MAX) {
5468+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
5469+ sz = AUFS_RDBLK_DEF;
5470+ }
5471+ return sz;
5472+}
5473+
1facf9fc 5474+/* ---------------------------------------------------------------------- */
5475+
5476+static int reopen_dir(struct file *file)
5477+{
5478+ int err;
5479+ unsigned int flags;
5480+ aufs_bindex_t bindex, btail, bstart;
5481+ struct dentry *dentry, *h_dentry;
5482+ struct file *h_file;
5483+
5484+ /* open all lower dirs */
5485+ dentry = file->f_dentry;
5486+ bstart = au_dbstart(dentry);
5487+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
5488+ au_set_h_fptr(file, bindex, NULL);
5489+ au_set_fbstart(file, bstart);
5490+
5491+ btail = au_dbtaildir(dentry);
4a4d8108 5492+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 5493+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 5494+ au_set_fbend_dir(file, btail);
1facf9fc 5495+
4a4d8108 5496+ flags = vfsub_file_flags(file);
1facf9fc 5497+ for (bindex = bstart; bindex <= btail; bindex++) {
5498+ h_dentry = au_h_dptr(dentry, bindex);
5499+ if (!h_dentry)
5500+ continue;
4a4d8108 5501+ h_file = au_hf_dir(file, bindex);
1facf9fc 5502+ if (h_file)
5503+ continue;
5504+
5505+ h_file = au_h_open(dentry, bindex, flags, file);
5506+ err = PTR_ERR(h_file);
5507+ if (IS_ERR(h_file))
5508+ goto out; /* close all? */
5509+ au_set_h_fptr(file, bindex, h_file);
5510+ }
5511+ au_update_figen(file);
5512+ /* todo: necessary? */
5513+ /* file->f_ra = h_file->f_ra; */
5514+ err = 0;
5515+
5516+ out:
5517+ return err;
5518+}
5519+
5520+static int do_open_dir(struct file *file, int flags)
5521+{
5522+ int err;
5523+ aufs_bindex_t bindex, btail;
5524+ struct dentry *dentry, *h_dentry;
5525+ struct file *h_file;
5526+
1308ab2a 5527+ FiMustWriteLock(file);
5528+
1facf9fc 5529+ err = 0;
5530+ dentry = file->f_dentry;
1facf9fc 5531+ file->f_version = dentry->d_inode->i_version;
5532+ bindex = au_dbstart(dentry);
5533+ au_set_fbstart(file, bindex);
5534+ btail = au_dbtaildir(dentry);
4a4d8108 5535+ au_set_fbend_dir(file, btail);
1facf9fc 5536+ for (; !err && bindex <= btail; bindex++) {
5537+ h_dentry = au_h_dptr(dentry, bindex);
5538+ if (!h_dentry)
5539+ continue;
5540+
5541+ h_file = au_h_open(dentry, bindex, flags, file);
5542+ if (IS_ERR(h_file)) {
5543+ err = PTR_ERR(h_file);
5544+ break;
5545+ }
5546+ au_set_h_fptr(file, bindex, h_file);
5547+ }
5548+ au_update_figen(file);
5549+ /* todo: necessary? */
5550+ /* file->f_ra = h_file->f_ra; */
5551+ if (!err)
5552+ return 0; /* success */
5553+
5554+ /* close all */
5555+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
5556+ au_set_h_fptr(file, bindex, NULL);
5557+ au_set_fbstart(file, -1);
4a4d8108
AM
5558+ au_set_fbend_dir(file, -1);
5559+
1facf9fc 5560+ return err;
5561+}
5562+
5563+static int aufs_open_dir(struct inode *inode __maybe_unused,
5564+ struct file *file)
5565+{
4a4d8108
AM
5566+ int err;
5567+ struct super_block *sb;
5568+ struct au_fidir *fidir;
5569+
5570+ err = -ENOMEM;
5571+ sb = file->f_dentry->d_sb;
5572+ si_read_lock(sb, AuLock_FLUSH);
5573+ fidir = au_fidir_alloc(inode->i_sb);
5574+ if (fidir) {
5575+ err = au_do_open(file, do_open_dir, fidir);
5576+ if (unlikely(err))
5577+ kfree(fidir);
5578+ }
5579+ si_read_unlock(sb);
5580+ return err;
1facf9fc 5581+}
5582+
5583+static int aufs_release_dir(struct inode *inode __maybe_unused,
5584+ struct file *file)
5585+{
5586+ struct au_vdir *vdir_cache;
5587+ struct super_block *sb;
4a4d8108
AM
5588+ struct au_finfo *finfo;
5589+ struct au_fidir *fidir;
5590+ aufs_bindex_t bindex, bend;
1facf9fc 5591+
4a4d8108 5592+ au_plink_maint_leave(file);
1facf9fc 5593+ sb = file->f_dentry->d_sb;
4a4d8108
AM
5594+ finfo = au_fi(file);
5595+ fidir = finfo->fi_hdir;
5596+ if (fidir) {
5597+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
5598+ if (vdir_cache)
5599+ au_vdir_free(vdir_cache);
5600+
5601+ bindex = finfo->fi_btop;
5602+ if (bindex >= 0) {
5603+ /*
5604+ * calls fput() instead of filp_close(),
5605+ * since no dnotify or lock for the lower file.
5606+ */
5607+ bend = fidir->fd_bbot;
5608+ for (; bindex <= bend; bindex++)
5609+ au_set_h_fptr(file, bindex, NULL);
5610+ }
5611+ kfree(fidir);
5612+ finfo->fi_hdir = NULL;
1facf9fc 5613+ }
1facf9fc 5614+ au_finfo_fin(file);
1facf9fc 5615+ return 0;
5616+}
5617+
5618+/* ---------------------------------------------------------------------- */
5619+
4a4d8108
AM
5620+static int au_do_flush_dir(struct file *file, fl_owner_t id)
5621+{
5622+ int err;
5623+ aufs_bindex_t bindex, bend;
5624+ struct file *h_file;
5625+
5626+ err = 0;
5627+ bend = au_fbend_dir(file);
5628+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
5629+ h_file = au_hf_dir(file, bindex);
5630+ if (h_file)
5631+ err = vfsub_flush(h_file, id);
5632+ }
5633+ return err;
5634+}
5635+
5636+static int aufs_flush_dir(struct file *file, fl_owner_t id)
5637+{
5638+ return au_do_flush(file, id, au_do_flush_dir);
5639+}
5640+
5641+/* ---------------------------------------------------------------------- */
5642+
1facf9fc 5643+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
5644+{
5645+ int err;
5646+ aufs_bindex_t bend, bindex;
5647+ struct inode *inode;
5648+ struct super_block *sb;
5649+
5650+ err = 0;
5651+ sb = dentry->d_sb;
5652+ inode = dentry->d_inode;
5653+ IMustLock(inode);
5654+ bend = au_dbend(dentry);
5655+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
5656+ struct path h_path;
5657+ struct inode *h_inode;
5658+
5659+ if (au_test_ro(sb, bindex, inode))
5660+ continue;
5661+ h_path.dentry = au_h_dptr(dentry, bindex);
5662+ if (!h_path.dentry)
5663+ continue;
5664+ h_inode = h_path.dentry->d_inode;
5665+ if (!h_inode)
5666+ continue;
5667+
5668+ /* no mnt_want_write() */
5669+ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
5670+ /* todo: inotiry fired? */
5671+ h_path.mnt = au_sbr_mnt(sb, bindex);
5672+ mutex_lock(&h_inode->i_mutex);
5673+ err = filemap_fdatawrite(h_inode->i_mapping);
5674+ AuDebugOn(!h_inode->i_fop);
5675+ if (!err && h_inode->i_fop->fsync)
5676+ err = h_inode->i_fop->fsync(NULL, h_path.dentry,
5677+ datasync);
5678+ if (!err)
5679+ err = filemap_fdatawrite(h_inode->i_mapping);
5680+ if (!err)
5681+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
5682+ mutex_unlock(&h_inode->i_mutex);
5683+ }
5684+
5685+ return err;
5686+}
5687+
5688+static int au_do_fsync_dir(struct file *file, int datasync)
5689+{
5690+ int err;
5691+ aufs_bindex_t bend, bindex;
5692+ struct file *h_file;
5693+ struct super_block *sb;
5694+ struct inode *inode;
5695+ struct mutex *h_mtx;
5696+
5697+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
5698+ if (unlikely(err))
5699+ goto out;
5700+
5701+ sb = file->f_dentry->d_sb;
5702+ inode = file->f_dentry->d_inode;
4a4d8108 5703+ bend = au_fbend_dir(file);
1facf9fc 5704+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 5705+ h_file = au_hf_dir(file, bindex);
1facf9fc 5706+ if (!h_file || au_test_ro(sb, bindex, inode))
5707+ continue;
5708+
5709+ err = vfs_fsync(h_file, h_file->f_dentry, datasync);
5710+ if (!err) {
5711+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
5712+ mutex_lock(h_mtx);
5713+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
5714+ /*ignore*/
5715+ mutex_unlock(h_mtx);
5716+ }
5717+ }
5718+
5719+ out:
5720+ return err;
5721+}
5722+
5723+/*
5724+ * @file may be NULL
5725+ */
5726+static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
5727+ int datasync)
5728+{
5729+ int err;
5730+ struct super_block *sb;
5731+
5732+ IMustLock(dentry->d_inode);
5733+
5734+ err = 0;
5735+ sb = dentry->d_sb;
5736+ si_noflush_read_lock(sb);
5737+ if (file)
5738+ err = au_do_fsync_dir(file, datasync);
5739+ else {
5740+ di_write_lock_child(dentry);
5741+ err = au_do_fsync_dir_no_file(dentry, datasync);
5742+ }
5743+ au_cpup_attr_timesizes(dentry->d_inode);
5744+ di_write_unlock(dentry);
5745+ if (file)
5746+ fi_write_unlock(file);
5747+
5748+ si_read_unlock(sb);
5749+ return err;
5750+}
5751+
5752+/* ---------------------------------------------------------------------- */
5753+
5754+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
5755+{
5756+ int err;
5757+ struct dentry *dentry;
5758+ struct inode *inode;
5759+ struct super_block *sb;
5760+
5761+ dentry = file->f_dentry;
5762+ inode = dentry->d_inode;
5763+ IMustLock(inode);
5764+
5765+ sb = dentry->d_sb;
5766+ si_read_lock(sb, AuLock_FLUSH);
5767+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
5768+ if (unlikely(err))
5769+ goto out;
5770+ err = au_vdir_init(file);
5771+ di_downgrade_lock(dentry, AuLock_IR);
5772+ if (unlikely(err))
5773+ goto out_unlock;
5774+
5775+ if (!au_test_nfsd(current)) {
5776+ err = au_vdir_fill_de(file, dirent, filldir);
5777+ fsstack_copy_attr_atime(inode,
5778+ au_h_iptr(inode, au_ibstart(inode)));
5779+ } else {
5780+ /*
5781+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
5782+ * encode_fh() and others.
5783+ */
5784+ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
5785+
5786+ di_read_unlock(dentry, AuLock_IR);
5787+ si_read_unlock(sb);
4a4d8108 5788+ /* lockdep_off(); */
1facf9fc 5789+ err = au_vdir_fill_de(file, dirent, filldir);
4a4d8108 5790+ /* lockdep_on(); */
1facf9fc 5791+ fsstack_copy_attr_atime(inode, h_inode);
5792+ fi_write_unlock(file);
5793+
5794+ AuTraceErr(err);
5795+ return err;
5796+ }
5797+
5798+ out_unlock:
5799+ di_read_unlock(dentry, AuLock_IR);
5800+ fi_write_unlock(file);
5801+ out:
5802+ si_read_unlock(sb);
5803+ return err;
5804+}
5805+
5806+/* ---------------------------------------------------------------------- */
5807+
5808+#define AuTestEmpty_WHONLY 1
dece6358
AM
5809+#define AuTestEmpty_CALLED (1 << 1)
5810+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 5811+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
5812+#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
5813+#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
5814+
dece6358
AM
5815+#ifndef CONFIG_AUFS_SHWH
5816+#undef AuTestEmpty_SHWH
5817+#define AuTestEmpty_SHWH 0
5818+#endif
5819+
1facf9fc 5820+struct test_empty_arg {
1308ab2a 5821+ struct au_nhash *whlist;
1facf9fc 5822+ unsigned int flags;
5823+ int err;
5824+ aufs_bindex_t bindex;
5825+};
5826+
5827+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
5828+ loff_t offset __maybe_unused, u64 ino,
5829+ unsigned int d_type)
1facf9fc 5830+{
5831+ struct test_empty_arg *arg = __arg;
5832+ char *name = (void *)__name;
5833+
5834+ arg->err = 0;
5835+ au_fset_testempty(arg->flags, CALLED);
5836+ /* smp_mb(); */
5837+ if (name[0] == '.'
5838+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
5839+ goto out; /* success */
5840+
5841+ if (namelen <= AUFS_WH_PFX_LEN
5842+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
5843+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 5844+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 5845+ arg->err = -ENOTEMPTY;
5846+ goto out;
5847+ }
5848+
5849+ name += AUFS_WH_PFX_LEN;
5850+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 5851+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 5852+ arg->err = au_nhash_append_wh
1308ab2a 5853+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 5854+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 5855+
5856+ out:
5857+ /* smp_mb(); */
5858+ AuTraceErr(arg->err);
5859+ return arg->err;
5860+}
5861+
5862+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
5863+{
5864+ int err;
5865+ struct file *h_file;
5866+
5867+ h_file = au_h_open(dentry, arg->bindex,
5868+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
5869+ /*file*/NULL);
5870+ err = PTR_ERR(h_file);
5871+ if (IS_ERR(h_file))
5872+ goto out;
5873+
5874+ err = 0;
5875+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
5876+ && !h_file->f_dentry->d_inode->i_nlink)
5877+ goto out_put;
5878+
5879+ do {
5880+ arg->err = 0;
5881+ au_fclr_testempty(arg->flags, CALLED);
5882+ /* smp_mb(); */
5883+ err = vfsub_readdir(h_file, test_empty_cb, arg);
5884+ if (err >= 0)
5885+ err = arg->err;
5886+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
5887+
5888+ out_put:
5889+ fput(h_file);
5890+ au_sbr_put(dentry->d_sb, arg->bindex);
5891+ out:
5892+ return err;
5893+}
5894+
5895+struct do_test_empty_args {
5896+ int *errp;
5897+ struct dentry *dentry;
5898+ struct test_empty_arg *arg;
5899+};
5900+
5901+static void call_do_test_empty(void *args)
5902+{
5903+ struct do_test_empty_args *a = args;
5904+ *a->errp = do_test_empty(a->dentry, a->arg);
5905+}
5906+
5907+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
5908+{
5909+ int err, wkq_err;
5910+ struct dentry *h_dentry;
5911+ struct inode *h_inode;
5912+
5913+ h_dentry = au_h_dptr(dentry, arg->bindex);
5914+ h_inode = h_dentry->d_inode;
5915+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
5916+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
5917+ mutex_unlock(&h_inode->i_mutex);
5918+ if (!err)
5919+ err = do_test_empty(dentry, arg);
5920+ else {
5921+ struct do_test_empty_args args = {
5922+ .errp = &err,
5923+ .dentry = dentry,
5924+ .arg = arg
5925+ };
5926+ unsigned int flags = arg->flags;
5927+
5928+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
5929+ if (unlikely(wkq_err))
5930+ err = wkq_err;
5931+ arg->flags = flags;
5932+ }
5933+
5934+ return err;
5935+}
5936+
5937+int au_test_empty_lower(struct dentry *dentry)
5938+{
5939+ int err;
1308ab2a 5940+ unsigned int rdhash;
1facf9fc 5941+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 5942+ struct au_nhash whlist;
1facf9fc 5943+ struct test_empty_arg arg;
1facf9fc 5944+
dece6358
AM
5945+ SiMustAnyLock(dentry->d_sb);
5946+
1308ab2a 5947+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
5948+ if (!rdhash)
5949+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
5950+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 5951+ if (unlikely(err))
1facf9fc 5952+ goto out;
5953+
1facf9fc 5954+ arg.flags = 0;
1308ab2a 5955+ arg.whlist = &whlist;
5956+ bstart = au_dbstart(dentry);
dece6358
AM
5957+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
5958+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 5959+ arg.bindex = bstart;
5960+ err = do_test_empty(dentry, &arg);
5961+ if (unlikely(err))
5962+ goto out_whlist;
5963+
5964+ au_fset_testempty(arg.flags, WHONLY);
5965+ btail = au_dbtaildir(dentry);
5966+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
5967+ struct dentry *h_dentry;
5968+
5969+ h_dentry = au_h_dptr(dentry, bindex);
5970+ if (h_dentry && h_dentry->d_inode) {
5971+ arg.bindex = bindex;
5972+ err = do_test_empty(dentry, &arg);
5973+ }
5974+ }
5975+
5976+ out_whlist:
1308ab2a 5977+ au_nhash_wh_free(&whlist);
1facf9fc 5978+ out:
5979+ return err;
5980+}
5981+
5982+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
5983+{
5984+ int err;
5985+ struct test_empty_arg arg;
5986+ aufs_bindex_t bindex, btail;
5987+
5988+ err = 0;
1308ab2a 5989+ arg.whlist = whlist;
1facf9fc 5990+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
5991+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
5992+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 5993+ btail = au_dbtaildir(dentry);
5994+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
5995+ struct dentry *h_dentry;
5996+
5997+ h_dentry = au_h_dptr(dentry, bindex);
5998+ if (h_dentry && h_dentry->d_inode) {
5999+ arg.bindex = bindex;
6000+ err = sio_test_empty(dentry, &arg);
6001+ }
6002+ }
6003+
6004+ return err;
6005+}
6006+
6007+/* ---------------------------------------------------------------------- */
6008+
6009+const struct file_operations aufs_dir_fop = {
4a4d8108 6010+ .owner = THIS_MODULE,
1facf9fc 6011+ .read = generic_read_dir,
6012+ .readdir = aufs_readdir,
6013+ .unlocked_ioctl = aufs_ioctl_dir,
6014+ .open = aufs_open_dir,
6015+ .release = aufs_release_dir,
4a4d8108 6016+ .flush = aufs_flush_dir,
1facf9fc 6017+ .fsync = aufs_fsync_dir
6018+};
4a4d8108
AM
6019diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/dir.h linux-2.6.34/fs/aufs/dir.h
6020--- linux-2.6.34.org/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
6021+++ linux-2.6.34/fs/aufs/dir.h 2010-05-31 22:15:32.000000000 +0200
1308ab2a 6022@@ -0,0 +1,127 @@
1facf9fc 6023+/*
4a4d8108 6024+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 6025+ *
6026+ * This program, aufs is free software; you can redistribute it and/or modify
6027+ * it under the terms of the GNU General Public License as published by
6028+ * the Free Software Foundation; either version 2 of the License, or
6029+ * (at your option) any later version.
dece6358
AM
6030+ *
6031+ * This program is distributed in the hope that it will be useful,
6032+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6033+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6034+ * GNU General Public License for more details.
6035+ *
6036+ * You should have received a copy of the GNU General Public License
6037+ * along with this program; if not, write to the Free Software
6038+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6039+ */
6040+
6041+/*
6042+ * directory operations
6043+ */
6044+
6045+#ifndef __AUFS_DIR_H__
6046+#define __AUFS_DIR_H__
6047+
6048+#ifdef __KERNEL__
6049+
6050+#include <linux/fs.h>
6051+#include <linux/aufs_type.h>
6052+
6053+/* ---------------------------------------------------------------------- */
6054+
6055+/* need to be faster and smaller */
6056+
6057+struct au_nhash {
dece6358
AM
6058+ unsigned int nh_num;
6059+ struct hlist_head *nh_head;
1facf9fc 6060+};
6061+
6062+struct au_vdir_destr {
6063+ unsigned char len;
6064+ unsigned char name[0];
6065+} __packed;
6066+
6067+struct au_vdir_dehstr {
6068+ struct hlist_node hash;
6069+ struct au_vdir_destr *str;
4a4d8108 6070+} ____cacheline_aligned_in_smp;
1facf9fc 6071+
6072+struct au_vdir_de {
6073+ ino_t de_ino;
6074+ unsigned char de_type;
6075+ /* caution: packed */
6076+ struct au_vdir_destr de_str;
6077+} __packed;
6078+
6079+struct au_vdir_wh {
6080+ struct hlist_node wh_hash;
dece6358
AM
6081+#ifdef CONFIG_AUFS_SHWH
6082+ ino_t wh_ino;
1facf9fc 6083+ aufs_bindex_t wh_bindex;
dece6358
AM
6084+ unsigned char wh_type;
6085+#else
6086+ aufs_bindex_t wh_bindex;
6087+#endif
6088+ /* caution: packed */
1facf9fc 6089+ struct au_vdir_destr wh_str;
6090+} __packed;
6091+
6092+union au_vdir_deblk_p {
6093+ unsigned char *deblk;
6094+ struct au_vdir_de *de;
6095+};
6096+
6097+struct au_vdir {
6098+ unsigned char **vd_deblk;
6099+ unsigned long vd_nblk;
1facf9fc 6100+ struct {
6101+ unsigned long ul;
6102+ union au_vdir_deblk_p p;
6103+ } vd_last;
6104+
6105+ unsigned long vd_version;
dece6358 6106+ unsigned int vd_deblk_sz;
1facf9fc 6107+ unsigned long vd_jiffy;
4a4d8108 6108+} ____cacheline_aligned_in_smp;
1facf9fc 6109+
6110+/* ---------------------------------------------------------------------- */
6111+
6112+/* dir.c */
6113+extern const struct file_operations aufs_dir_fop;
6114+void au_add_nlink(struct inode *dir, struct inode *h_dir);
6115+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 6116+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 6117+int au_test_empty_lower(struct dentry *dentry);
6118+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
6119+
6120+/* vdir.c */
1308ab2a 6121+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
6122+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
6123+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 6124+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
6125+ int limit);
dece6358
AM
6126+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
6127+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
6128+ unsigned int d_type, aufs_bindex_t bindex,
6129+ unsigned char shwh);
1facf9fc 6130+void au_vdir_free(struct au_vdir *vdir);
6131+int au_vdir_init(struct file *file);
6132+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
6133+
6134+/* ioctl.c */
6135+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
6136+
1308ab2a 6137+#ifdef CONFIG_AUFS_RDU
6138+/* rdu.c */
6139+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
6140+#else
6141+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
6142+ unsigned long arg)
6143+{
6144+ return -EINVAL;
6145+}
6146+#endif
6147+
1facf9fc 6148+#endif /* __KERNEL__ */
6149+#endif /* __AUFS_DIR_H__ */
4a4d8108
AM
6150diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/dynop.c linux-2.6.34/fs/aufs/dynop.c
6151--- linux-2.6.34.org/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
6152+++ linux-2.6.34/fs/aufs/dynop.c 2010-05-31 22:15:32.000000000 +0200
6153@@ -0,0 +1,404 @@
1facf9fc 6154+/*
4a4d8108 6155+ * Copyright (C) 2010 Junjiro R. Okajima
1facf9fc 6156+ *
6157+ * This program, aufs is free software; you can redistribute it and/or modify
6158+ * it under the terms of the GNU General Public License as published by
6159+ * the Free Software Foundation; either version 2 of the License, or
6160+ * (at your option) any later version.
dece6358
AM
6161+ *
6162+ * This program is distributed in the hope that it will be useful,
6163+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6164+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6165+ * GNU General Public License for more details.
6166+ *
6167+ * You should have received a copy of the GNU General Public License
6168+ * along with this program; if not, write to the Free Software
6169+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6170+ */
6171+
6172+/*
4a4d8108 6173+ * dynamically customizable operations for regular files
1facf9fc 6174+ */
6175+
1facf9fc 6176+#include "aufs.h"
6177+
4a4d8108 6178+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 6179+
4a4d8108
AM
6180+/*
6181+ * How large will these lists be?
6182+ * Usually just a few elements, 20-30 at most for each, I guess.
6183+ */
6184+static struct au_splhead dynop[AuDyLast];
6185+
6186+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 6187+{
4a4d8108
AM
6188+ struct au_dykey *key, *tmp;
6189+ struct list_head *head;
1facf9fc 6190+
4a4d8108
AM
6191+ key = NULL;
6192+ head = &spl->head;
6193+ rcu_read_lock();
6194+ list_for_each_entry_rcu(tmp, head, dk_list)
6195+ if (tmp->dk_op.dy_hop == h_op) {
6196+ key = tmp;
6197+ kref_get(&key->dk_kref);
6198+ break;
6199+ }
6200+ rcu_read_unlock();
6201+
6202+ return key;
1facf9fc 6203+}
6204+
4a4d8108 6205+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 6206+{
4a4d8108
AM
6207+ struct au_dykey **k, *found;
6208+ const void *h_op = key->dk_op.dy_hop;
6209+ int i;
1facf9fc 6210+
4a4d8108
AM
6211+ found = NULL;
6212+ k = br->br_dykey;
6213+ for (i = 0; i < AuBrDynOp; i++)
6214+ if (k[i]) {
6215+ if (k[i]->dk_op.dy_hop == h_op) {
6216+ found = k[i];
6217+ break;
6218+ }
6219+ } else
6220+ break;
6221+ if (!found) {
6222+ spin_lock(&br->br_dykey_lock);
6223+ for (; i < AuBrDynOp; i++)
6224+ if (k[i]) {
6225+ if (k[i]->dk_op.dy_hop == h_op) {
6226+ found = k[i];
6227+ break;
6228+ }
6229+ } else {
6230+ k[i] = key;
6231+ break;
6232+ }
6233+ spin_unlock(&br->br_dykey_lock);
6234+ BUG_ON(i == AuBrDynOp); /* expand the array */
6235+ }
6236+
6237+ return found;
1facf9fc 6238+}
6239+
4a4d8108
AM
6240+/* kref_get() if @key is already added */
6241+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
6242+{
6243+ struct au_dykey *tmp, *found;
6244+ struct list_head *head;
6245+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 6246+
4a4d8108
AM
6247+ found = NULL;
6248+ head = &spl->head;
6249+ spin_lock(&spl->spin);
6250+ list_for_each_entry(tmp, head, dk_list)
6251+ if (tmp->dk_op.dy_hop == h_op) {
6252+ kref_get(&tmp->dk_kref);
6253+ found = tmp;
6254+ break;
6255+ }
6256+ if (!found)
6257+ list_add_rcu(&key->dk_list, head);
6258+ spin_unlock(&spl->spin);
1facf9fc 6259+
4a4d8108
AM
6260+ if (!found)
6261+ DyPrSym(key);
6262+ return found;
6263+}
6264+
6265+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 6266+{
4a4d8108
AM
6267+ struct au_dykey *key;
6268+
6269+ key = container_of(rcu, struct au_dykey, dk_rcu);
6270+ DyPrSym(key);
6271+ kfree(key);
1facf9fc 6272+}
6273+
4a4d8108
AM
6274+static void dy_free(struct kref *kref)
6275+{
6276+ struct au_dykey *key;
6277+ struct au_splhead *spl;
1facf9fc 6278+
4a4d8108
AM
6279+ key = container_of(kref, struct au_dykey, dk_kref);
6280+ spl = dynop + key->dk_op.dy_type;
6281+ au_spl_del_rcu(&key->dk_list, spl);
6282+ call_rcu(&key->dk_rcu, dy_free_rcu);
6283+}
6284+
6285+void au_dy_put(struct au_dykey *key)
1facf9fc 6286+{
4a4d8108
AM
6287+ kref_put(&key->dk_kref, dy_free);
6288+}
1facf9fc 6289+
4a4d8108
AM
6290+/* ---------------------------------------------------------------------- */
6291+
6292+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
6293+
6294+#ifdef CONFIG_AUFS_DEBUG
6295+#define DyDbgDeclare(cnt) unsigned int cnt = 0
6296+#define DyDbgInc(cnt) cnt++
6297+#else
6298+#define DyDbgDeclare(cnt) do {} while (0)
6299+#define DyDbgInc(cnt) do {} while (0)
6300+#endif
6301+
6302+#define DySet(func, dst, src, h_op, h_sb) do { \
6303+ DyDbgInc(cnt); \
6304+ if (h_op->func) { \
6305+ if (src.func) \
6306+ dst.func = src.func; \
6307+ else \
6308+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
6309+ } \
6310+} while (0)
6311+
6312+#define DySetForce(func, dst, src) do { \
6313+ AuDebugOn(!src.func); \
6314+ DyDbgInc(cnt); \
6315+ dst.func = src.func; \
6316+} while (0)
6317+
6318+#define DySetAop(func) \
6319+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
6320+#define DySetAopForce(func) \
6321+ DySetForce(func, dyaop->da_op, aufs_aop)
6322+
6323+static void dy_aop(struct au_dykey *key, const void *h_op,
6324+ struct super_block *h_sb __maybe_unused)
6325+{
6326+ struct au_dyaop *dyaop = (void *)key;
6327+ const struct address_space_operations *h_aop = h_op;
6328+ DyDbgDeclare(cnt);
6329+
6330+ AuDbg("%s\n", au_sbtype(h_sb));
6331+
6332+ DySetAop(writepage);
6333+ DySetAopForce(readpage); /* force */
6334+ DySetAop(sync_page);
6335+ DySetAop(writepages);
6336+ DySetAop(set_page_dirty);
6337+ DySetAop(readpages);
6338+ DySetAop(write_begin);
6339+ DySetAop(write_end);
6340+ DySetAop(bmap);
6341+ DySetAop(invalidatepage);
6342+ DySetAop(releasepage);
6343+ /* these two will be changed according to an aufs mount option */
6344+ DySetAop(direct_IO);
6345+ DySetAop(get_xip_mem);
6346+ DySetAop(migratepage);
6347+ DySetAop(launder_page);
6348+ DySetAop(is_partially_uptodate);
6349+ DySetAop(error_remove_page);
6350+
6351+ DyDbgSize(cnt, *h_aop);
6352+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
6353+}
6354+
6355+#define DySetVmop(func) \
6356+ DySet(func, dyvmop->dv_op, aufs_vm_ops, h_vmop, h_sb)
6357+#define DySetVmopForce(func) \
6358+ DySetForce(func, dyvmop->dv_op, aufs_vm_ops)
6359+
6360+static void dy_vmop(struct au_dykey *key, const void *h_op,
6361+ struct super_block *h_sb __maybe_unused)
6362+{
6363+ struct au_dyvmop *dyvmop = (void *)key;
6364+ const struct vm_operations_struct *h_vmop = h_op;
6365+ DyDbgDeclare(cnt);
6366+
6367+ AuDbg("%s\n", au_sbtype(h_sb));
6368+
6369+ DySetVmop(open);
6370+ DySetVmop(close);
6371+ DySetVmop(fault);
6372+ DySetVmop(page_mkwrite);
6373+ DySetVmop(access);
6374+#ifdef CONFIG_NUMA
6375+ DySetVmop(set_policy);
6376+ DySetVmop(get_policy);
6377+ DySetVmop(migrate);
6378+#endif
6379+
6380+ DyDbgSize(cnt, *h_vmop);
6381+}
6382+
6383+/* ---------------------------------------------------------------------- */
6384+
6385+static void dy_bug(struct kref *kref)
6386+{
6387+ BUG();
6388+}
6389+
6390+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
6391+{
6392+ struct au_dykey *key, *old;
6393+ struct au_splhead *spl;
6394+ static const struct {
6395+ unsigned int sz;
6396+ void (*set_op)(struct au_dykey *key, const void *h_op,
6397+ struct super_block *h_sb __maybe_unused);
6398+ } a[] = {
6399+ [AuDy_AOP] = {
6400+ .sz = sizeof(struct au_dyaop),
6401+ .set_op = dy_aop
6402+ },
6403+ [AuDy_VMOP] = {
6404+ .sz = sizeof(struct au_dyvmop),
6405+ .set_op = dy_vmop
6406+ }
6407+ }, *p;
6408+
6409+ spl = dynop + op->dy_type;
6410+ key = dy_gfind_get(spl, op->dy_hop);
6411+ if (key)
6412+ goto out_add; /* success */
6413+
6414+ p = a + op->dy_type;
6415+ key = kzalloc(p->sz, GFP_NOFS);
6416+ if (unlikely(!key)) {
6417+ key = ERR_PTR(-ENOMEM);
6418+ goto out;
6419+ }
6420+
6421+ key->dk_op.dy_hop = op->dy_hop;
6422+ kref_init(&key->dk_kref);
6423+ p->set_op(key, op->dy_hop, br->br_mnt->mnt_sb);
6424+ old = dy_gadd(spl, key);
6425+ if (old) {
6426+ kfree(key);
6427+ key = old;
6428+ }
6429+
6430+out_add:
6431+ old = dy_bradd(br, key);
6432+ if (old)
6433+ /* its ref-count should never be zero here */
6434+ kref_put(&key->dk_kref, dy_bug);
6435+out:
6436+ return key;
6437+}
6438+
6439+/* ---------------------------------------------------------------------- */
6440+/*
6441+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
6442+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
6443+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
6444+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
6445+ * See the aufs manual in detail.
6446+ *
6447+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
6448+ * performance of fadvise() and madvise() may be affected.
6449+ */
6450+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
6451+{
6452+ if (!do_dx) {
6453+ dyaop->da_op.direct_IO = NULL;
6454+ dyaop->da_op.get_xip_mem = NULL;
6455+ } else {
6456+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
6457+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
6458+ if (!dyaop->da_get_xip_mem)
6459+ dyaop->da_op.get_xip_mem = NULL;
6460+ }
6461+}
6462+
6463+static struct au_dyaop *dy_aget(struct au_branch *br,
6464+ const struct address_space_operations *h_aop,
6465+ int do_dx)
6466+{
6467+ struct au_dyaop *dyaop;
6468+ struct au_dynop op;
6469+
6470+ op.dy_type = AuDy_AOP;
6471+ op.dy_haop = h_aop;
6472+ dyaop = (void *)dy_get(&op, br);
6473+ if (IS_ERR(dyaop))
6474+ goto out;
6475+ dy_adx(dyaop, do_dx);
6476+
6477+out:
6478+ return dyaop;
6479+}
6480+
6481+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
6482+ struct inode *h_inode)
6483+{
6484+ int err, do_dx;
6485+ struct super_block *sb;
6486+ struct au_branch *br;
6487+ struct au_dyaop *dyaop;
6488+
6489+ AuDebugOn(!S_ISREG(h_inode->i_mode));
6490+ IiMustWriteLock(inode);
6491+
6492+ sb = inode->i_sb;
6493+ br = au_sbr(sb, bindex);
6494+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
6495+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
6496+ err = PTR_ERR(dyaop);
6497+ if (IS_ERR(dyaop))
6498+ /* unnecessary to call dy_fput() */
6499+ goto out;
6500+
6501+ err = 0;
6502+ inode->i_mapping->a_ops = &dyaop->da_op;
6503+
6504+out:
6505+ return err;
6506+}
6507+
6508+void au_dy_arefresh(int do_dx)
6509+{
6510+ struct au_splhead *spl;
6511+ struct list_head *head;
6512+ struct au_dykey *key;
6513+
6514+ spl = dynop + AuDy_AOP;
6515+ head = &spl->head;
6516+ spin_lock(&spl->spin);
6517+ list_for_each_entry(key, head, dk_list)
6518+ dy_adx((void *)key, do_dx);
6519+ spin_unlock(&spl->spin);
6520+}
6521+
6522+const struct vm_operations_struct *
6523+au_dy_vmop(struct file *file, struct au_branch *br,
6524+ const struct vm_operations_struct *h_vmop)
6525+{
6526+ struct au_dyvmop *dyvmop;
6527+ struct au_dynop op;
6528+
6529+ op.dy_type = AuDy_VMOP;
6530+ op.dy_hvmop = h_vmop;
6531+ dyvmop = (void *)dy_get(&op, br);
6532+ if (IS_ERR(dyvmop))
6533+ return (void *)dyvmop;
6534+ return &dyvmop->dv_op;
6535+}
6536+
6537+/* ---------------------------------------------------------------------- */
6538+
6539+void __init au_dy_init(void)
6540+{
6541+ int i;
6542+
6543+ /* make sure that 'struct au_dykey *' can be any type */
6544+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
6545+ BUILD_BUG_ON(offsetof(struct au_dyvmop, dv_key));
6546+
6547+ for (i = 0; i < AuDyLast; i++)
6548+ au_spl_init(dynop + i);
6549+}
6550+
6551+void au_dy_fin(void)
6552+{
6553+ int i;
6554+
6555+ for (i = 0; i < AuDyLast; i++)
6556+ WARN_ON(!list_empty(&dynop[i].head));
6557+}
6558diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/dynop.h linux-2.6.34/fs/aufs/dynop.h
6559--- linux-2.6.34.org/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
6560+++ linux-2.6.34/fs/aufs/dynop.h 2010-05-31 22:15:32.000000000 +0200
6561@@ -0,0 +1,109 @@
6562+/*
6563+ * Copyright (C) 2010 Junjiro R. Okajima
6564+ *
6565+ * This program, aufs is free software; you can redistribute it and/or modify
6566+ * it under the terms of the GNU General Public License as published by
6567+ * the Free Software Foundation; either version 2 of the License, or
6568+ * (at your option) any later version.
6569+ *
6570+ * This program is distributed in the hope that it will be useful,
6571+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6572+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6573+ * GNU General Public License for more details.
6574+ *
6575+ * You should have received a copy of the GNU General Public License
6576+ * along with this program; if not, write to the Free Software
6577+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6578+ */
6579+
6580+/*
6581+ * dynamically customizable operations (for regular files only)
6582+ */
6583+
6584+#ifndef __AUFS_DYNOP_H__
6585+#define __AUFS_DYNOP_H__
6586+
6587+#ifdef __KERNEL__
6588+
6589+#include <linux/fs.h>
6590+#include <linux/mm.h>
6591+#include <linux/rcupdate.h>
6592+#include <linux/aufs_type.h>
6593+#include "inode.h"
6594+
6595+enum {AuDy_AOP, AuDy_VMOP, AuDyLast};
6596+
6597+struct au_dynop {
6598+ int dy_type;
6599+ union {
6600+ const void *dy_hop;
6601+ const struct address_space_operations *dy_haop;
6602+ const struct vm_operations_struct *dy_hvmop;
6603+ };
6604+};
6605+
6606+struct au_dykey {
6607+ union {
6608+ struct list_head dk_list;
6609+ struct rcu_head dk_rcu;
6610+ };
6611+ struct au_dynop dk_op;
6612+
6613+ /*
6614+ * during I am in the branch local array, kref is gotten. when the
6615+ * branch is removed, kref is put.
6616+ */
6617+ struct kref dk_kref;
6618+};
6619+
6620+/* stop unioning since their sizes are very different from each other */
6621+struct au_dyaop {
6622+ struct au_dykey da_key;
6623+ struct address_space_operations da_op; /* not const */
6624+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
6625+ void **, unsigned long *);
6626+};
6627+
6628+struct au_dyvmop {
6629+ struct au_dykey dv_key;
6630+ struct vm_operations_struct dv_op; /* not const */
6631+};
6632+
6633+/* ---------------------------------------------------------------------- */
6634+
6635+/* dynop.c */
6636+struct au_branch;
6637+void au_dy_put(struct au_dykey *key);
6638+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
6639+ struct inode *h_inode);
6640+void au_dy_arefresh(int do_dio);
6641+const struct vm_operations_struct *
6642+au_dy_vmop(struct file *file, struct au_branch *br,
6643+ const struct vm_operations_struct *h_vmop);
6644+
6645+void __init au_dy_init(void);
6646+void au_dy_fin(void);
6647+
6648+/* ---------------------------------------------------------------------- */
6649+
6650+/*
6651+ * Is it safe to replace a_ops during the inode/file is in operation?
6652+ * Yes, I hope so.
6653+ */
6654+static inline int au_dy_irefresh(struct inode *inode)
6655+{
6656+ int err;
6657+ aufs_bindex_t bstart;
6658+ struct inode *h_inode;
6659+
6660+ err = 0;
6661+ if (S_ISREG(inode->i_mode)) {
6662+ bstart = au_ibstart(inode);
6663+ h_inode = au_h_iptr(inode, bstart);
6664+ err = au_dy_iaop(inode, bstart, h_inode);
6665+ }
6666+ return err;
6667+}
6668+
6669+#endif /* __KERNEL__ */
6670+#endif /* __AUFS_DYNOP_H__ */
6671diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/export.c linux-2.6.34/fs/aufs/export.c
6672--- linux-2.6.34.org/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
6673+++ linux-2.6.34/fs/aufs/export.c 2010-05-31 22:15:32.000000000 +0200
6674@@ -0,0 +1,801 @@
6675+/*
6676+ * Copyright (C) 2005-2010 Junjiro R. Okajima
6677+ *
6678+ * This program, aufs is free software; you can redistribute it and/or modify
6679+ * it under the terms of the GNU General Public License as published by
6680+ * the Free Software Foundation; either version 2 of the License, or
6681+ * (at your option) any later version.
6682+ *
6683+ * This program is distributed in the hope that it will be useful,
6684+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6685+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6686+ * GNU General Public License for more details.
6687+ *
6688+ * You should have received a copy of the GNU General Public License
6689+ * along with this program; if not, write to the Free Software
6690+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6691+ */
6692+
6693+/*
6694+ * export via nfs
6695+ */
6696+
6697+#include <linux/exportfs.h>
6698+#include <linux/file.h>
6699+#include <linux/mnt_namespace.h>
6700+#include <linux/namei.h>
6701+#include <linux/nsproxy.h>
6702+#include <linux/random.h>
6703+#include <linux/writeback.h>
6704+#include "aufs.h"
6705+
6706+union conv {
6707+#ifdef CONFIG_AUFS_INO_T_64
6708+ __u32 a[2];
6709+#else
6710+ __u32 a[1];
6711+#endif
6712+ ino_t ino;
6713+};
6714+
6715+static ino_t decode_ino(__u32 *a)
6716+{
6717+ union conv u;
6718+
6719+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
6720+ u.a[0] = a[0];
6721+#ifdef CONFIG_AUFS_INO_T_64
6722+ u.a[1] = a[1];
6723+#endif
6724+ return u.ino;
6725+}
6726+
6727+static void encode_ino(__u32 *a, ino_t ino)
6728+{
6729+ union conv u;
6730+
6731+ u.ino = ino;
6732+ a[0] = u.a[0];
6733+#ifdef CONFIG_AUFS_INO_T_64
6734+ a[1] = u.a[1];
6735+#endif
6736+}
6737+
6738+/* NFS file handle */
6739+enum {
6740+ Fh_br_id,
6741+ Fh_sigen,
6742+#ifdef CONFIG_AUFS_INO_T_64
6743+ /* support 64bit inode number */
6744+ Fh_ino1,
6745+ Fh_ino2,
6746+ Fh_dir_ino1,
6747+ Fh_dir_ino2,
6748+#else
6749+ Fh_ino1,
6750+ Fh_dir_ino1,
6751+#endif
6752+ Fh_igen,
6753+ Fh_h_type,
6754+ Fh_tail,
6755+
6756+ Fh_ino = Fh_ino1,
6757+ Fh_dir_ino = Fh_dir_ino1
6758+};
6759+
6760+static int au_test_anon(struct dentry *dentry)
6761+{
6762+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
6763+}
6764+
6765+/* ---------------------------------------------------------------------- */
6766+/* inode generation external table */
6767+
6768+int au_xigen_inc(struct inode *inode)
6769+{
6770+ int err;
6771+ loff_t pos;
6772+ ssize_t sz;
6773+ __u32 igen;
6774+ struct super_block *sb;
6775+ struct au_sbinfo *sbinfo;
6776+
6777+ err = 0;
6778+ sb = inode->i_sb;
6779+ sbinfo = au_sbi(sb);
dece6358
AM
6780+ /*
6781+ * temporary workaround for escaping from SiMustAnyLock() in
6782+ * au_mntflags(), since this function is called from au_iinfo_fin().
6783+ */
6784+ if (unlikely(!au_opt_test(sbinfo->si_mntflags, XINO)))
1facf9fc 6785+ goto out;
6786+
6787+ pos = inode->i_ino;
6788+ pos *= sizeof(igen);
6789+ igen = inode->i_generation + 1;
1facf9fc 6790+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
6791+ sizeof(igen), &pos);
6792+ if (sz == sizeof(igen))
6793+ goto out; /* success */
6794+
6795+ err = sz;
6796+ if (unlikely(sz >= 0)) {
6797+ err = -EIO;
6798+ AuIOErr("xigen error (%zd)\n", sz);
6799+ }
6800+
6801+ out:
6802+ return err;
6803+}
6804+
6805+int au_xigen_new(struct inode *inode)
6806+{
6807+ int err;
6808+ loff_t pos;
6809+ ssize_t sz;
6810+ struct super_block *sb;
6811+ struct au_sbinfo *sbinfo;
6812+ struct file *file;
6813+
6814+ err = 0;
6815+ /* todo: dirty, at mount time */
6816+ if (inode->i_ino == AUFS_ROOT_INO)
6817+ goto out;
6818+ sb = inode->i_sb;
dece6358 6819+ SiMustAnyLock(sb);
1facf9fc 6820+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
6821+ goto out;
6822+
6823+ err = -EFBIG;
6824+ pos = inode->i_ino;
6825+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
6826+ AuIOErr1("too large i%lld\n", pos);
6827+ goto out;
6828+ }
6829+ pos *= sizeof(inode->i_generation);
6830+
6831+ err = 0;
6832+ sbinfo = au_sbi(sb);
6833+ file = sbinfo->si_xigen;
6834+ BUG_ON(!file);
6835+
6836+ if (i_size_read(file->f_dentry->d_inode)
6837+ < pos + sizeof(inode->i_generation)) {
6838+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
6839+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
6840+ sizeof(inode->i_generation), &pos);
6841+ } else
6842+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
6843+ sizeof(inode->i_generation), &pos);
6844+ if (sz == sizeof(inode->i_generation))
6845+ goto out; /* success */
6846+
6847+ err = sz;
6848+ if (unlikely(sz >= 0)) {
6849+ err = -EIO;
6850+ AuIOErr("xigen error (%zd)\n", sz);
6851+ }
6852+
6853+ out:
6854+ return err;
6855+}
6856+
6857+int au_xigen_set(struct super_block *sb, struct file *base)
6858+{
6859+ int err;
6860+ struct au_sbinfo *sbinfo;
6861+ struct file *file;
6862+
dece6358
AM
6863+ SiMustWriteLock(sb);
6864+
1facf9fc 6865+ sbinfo = au_sbi(sb);
6866+ file = au_xino_create2(base, sbinfo->si_xigen);
6867+ err = PTR_ERR(file);
6868+ if (IS_ERR(file))
6869+ goto out;
6870+ err = 0;
6871+ if (sbinfo->si_xigen)
6872+ fput(sbinfo->si_xigen);
6873+ sbinfo->si_xigen = file;
6874+
6875+ out:
6876+ return err;
6877+}
6878+
6879+void au_xigen_clr(struct super_block *sb)
6880+{
6881+ struct au_sbinfo *sbinfo;
6882+
dece6358
AM
6883+ SiMustWriteLock(sb);
6884+
1facf9fc 6885+ sbinfo = au_sbi(sb);
6886+ if (sbinfo->si_xigen) {
6887+ fput(sbinfo->si_xigen);
6888+ sbinfo->si_xigen = NULL;
6889+ }
6890+}
6891+
6892+/* ---------------------------------------------------------------------- */
6893+
6894+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
6895+ ino_t dir_ino)
6896+{
6897+ struct dentry *dentry, *d;
6898+ struct inode *inode;
6899+ unsigned int sigen;
6900+
6901+ dentry = NULL;
6902+ inode = ilookup(sb, ino);
6903+ if (!inode)
6904+ goto out;
6905+
6906+ dentry = ERR_PTR(-ESTALE);
6907+ sigen = au_sigen(sb);
6908+ if (unlikely(is_bad_inode(inode)
6909+ || IS_DEADDIR(inode)
6910+ || sigen != au_iigen(inode)))
6911+ goto out_iput;
6912+
6913+ dentry = NULL;
6914+ if (!dir_ino || S_ISDIR(inode->i_mode))
6915+ dentry = d_find_alias(inode);
6916+ else {
6917+ spin_lock(&dcache_lock);
6918+ list_for_each_entry(d, &inode->i_dentry, d_alias)
6919+ if (!au_test_anon(d)
6920+ && d->d_parent->d_inode->i_ino == dir_ino) {
6921+ dentry = dget_locked(d);
6922+ break;
6923+ }
6924+ spin_unlock(&dcache_lock);
6925+ }
6926+ if (unlikely(dentry && sigen != au_digen(dentry))) {
6927+ dput(dentry);
6928+ dentry = ERR_PTR(-ESTALE);
6929+ }
6930+
6931+ out_iput:
6932+ iput(inode);
6933+ out:
6934+ return dentry;
6935+}
6936+
6937+/* ---------------------------------------------------------------------- */
6938+
6939+/* todo: dirty? */
6940+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
6941+
6942+struct au_compare_mnt_args {
6943+ /* input */
6944+ struct super_block *sb;
6945+
6946+ /* output */
6947+ struct vfsmount *mnt;
6948+};
6949+
6950+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
6951+{
6952+ struct au_compare_mnt_args *a = arg;
6953+
6954+ if (mnt->mnt_sb != a->sb)
6955+ return 0;
6956+ a->mnt = mntget(mnt);
6957+ return 1;
6958+}
6959+
1facf9fc 6960+static struct vfsmount *au_mnt_get(struct super_block *sb)
6961+{
4a4d8108
AM
6962+ int err;
6963+ struct au_compare_mnt_args args = {
6964+ .sb = sb
6965+ };
1facf9fc 6966+ struct mnt_namespace *ns;
1facf9fc 6967+
1facf9fc 6968+ /* no get/put ?? */
6969+ AuDebugOn(!current->nsproxy);
6970+ ns = current->nsproxy->mnt_ns;
6971+ AuDebugOn(!ns);
4a4d8108
AM
6972+ err = iterate_mounts(au_compare_mnt, &args, ns->root);
6973+ AuDebugOn(!err);
6974+ AuDebugOn(!args.mnt);
6975+ return args.mnt;
1facf9fc 6976+}
6977+
6978+struct au_nfsd_si_lock {
4a4d8108
AM
6979+ unsigned int sigen;
6980+ aufs_bindex_t br_id;
1facf9fc 6981+ unsigned char force_lock;
6982+};
6983+
6984+static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
6985+ struct au_nfsd_si_lock *nsi_lock)
6986+{
6987+ aufs_bindex_t bindex;
6988+
6989+ si_read_lock(sb, AuLock_FLUSH);
6990+
6991+ /* branch id may be wrapped around */
6992+ bindex = au_br_index(sb, nsi_lock->br_id);
6993+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
6994+ goto out; /* success */
6995+
6996+ if (!nsi_lock->force_lock)
6997+ si_read_unlock(sb);
6998+ bindex = -1;
6999+
7000+ out:
7001+ return bindex;
7002+}
7003+
7004+struct find_name_by_ino {
7005+ int called, found;
7006+ ino_t ino;
7007+ char *name;
7008+ int namelen;
7009+};
7010+
7011+static int
7012+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
7013+ u64 ino, unsigned int d_type)
7014+{
7015+ struct find_name_by_ino *a = arg;
7016+
7017+ a->called++;
7018+ if (a->ino != ino)
7019+ return 0;
7020+
7021+ memcpy(a->name, name, namelen);
7022+ a->namelen = namelen;
7023+ a->found = 1;
7024+ return 1;
7025+}
7026+
7027+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
7028+ struct au_nfsd_si_lock *nsi_lock)
7029+{
7030+ struct dentry *dentry, *parent;
7031+ struct file *file;
7032+ struct inode *dir;
7033+ struct find_name_by_ino arg;
7034+ int err;
7035+
7036+ parent = path->dentry;
7037+ if (nsi_lock)
7038+ si_read_unlock(parent->d_sb);
4a4d8108 7039+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 7040+ dentry = (void *)file;
7041+ if (IS_ERR(file))
7042+ goto out;
7043+
7044+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 7045+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 7046+ if (unlikely(!arg.name))
7047+ goto out_file;
7048+ arg.ino = ino;
7049+ arg.found = 0;
7050+ do {
7051+ arg.called = 0;
7052+ /* smp_mb(); */
7053+ err = vfsub_readdir(file, find_name_by_ino, &arg);
7054+ } while (!err && !arg.found && arg.called);
7055+ dentry = ERR_PTR(err);
7056+ if (unlikely(err))
7057+ goto out_name;
7058+ dentry = ERR_PTR(-ENOENT);
7059+ if (!arg.found)
7060+ goto out_name;
7061+
7062+ /* do not call au_lkup_one() */
7063+ dir = parent->d_inode;
7064+ mutex_lock(&dir->i_mutex);
7065+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
7066+ mutex_unlock(&dir->i_mutex);
7067+ AuTraceErrPtr(dentry);
7068+ if (IS_ERR(dentry))
7069+ goto out_name;
7070+ AuDebugOn(au_test_anon(dentry));
7071+ if (unlikely(!dentry->d_inode)) {
7072+ dput(dentry);
7073+ dentry = ERR_PTR(-ENOENT);
7074+ }
7075+
7076+ out_name:
7077+ __putname(arg.name);
7078+ out_file:
7079+ fput(file);
7080+ out:
7081+ if (unlikely(nsi_lock
7082+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
7083+ if (!IS_ERR(dentry)) {
7084+ dput(dentry);
7085+ dentry = ERR_PTR(-ESTALE);
7086+ }
7087+ AuTraceErrPtr(dentry);
7088+ return dentry;
7089+}
7090+
7091+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
7092+ ino_t dir_ino,
7093+ struct au_nfsd_si_lock *nsi_lock)
7094+{
7095+ struct dentry *dentry;
7096+ struct path path;
7097+
7098+ if (dir_ino != AUFS_ROOT_INO) {
7099+ path.dentry = decode_by_ino(sb, dir_ino, 0);
7100+ dentry = path.dentry;
7101+ if (!path.dentry || IS_ERR(path.dentry))
7102+ goto out;
7103+ AuDebugOn(au_test_anon(path.dentry));
7104+ } else
7105+ path.dentry = dget(sb->s_root);
7106+
7107+ path.mnt = au_mnt_get(sb);
7108+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
7109+ path_put(&path);
7110+
7111+ out:
7112+ AuTraceErrPtr(dentry);
7113+ return dentry;
7114+}
7115+
7116+/* ---------------------------------------------------------------------- */
7117+
7118+static int h_acceptable(void *expv, struct dentry *dentry)
7119+{
7120+ return 1;
7121+}
7122+
7123+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
7124+ char *buf, int len, struct super_block *sb)
7125+{
7126+ char *p;
7127+ int n;
7128+ struct path path;
7129+
7130+ p = d_path(h_rootpath, buf, len);
7131+ if (IS_ERR(p))
7132+ goto out;
7133+ n = strlen(p);
7134+
7135+ path.mnt = h_rootpath->mnt;
7136+ path.dentry = h_parent;
7137+ p = d_path(&path, buf, len);
7138+ if (IS_ERR(p))
7139+ goto out;
7140+ if (n != 1)
7141+ p += n;
7142+
7143+ path.mnt = au_mnt_get(sb);
7144+ path.dentry = sb->s_root;
7145+ p = d_path(&path, buf, len - strlen(p));
7146+ mntput(path.mnt);
7147+ if (IS_ERR(p))
7148+ goto out;
7149+ if (n != 1)
7150+ p[strlen(p)] = '/';
7151+
7152+ out:
7153+ AuTraceErrPtr(p);
7154+ return p;
7155+}
7156+
7157+static
7158+struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
7159+ ino_t ino, __u32 *fh, int fh_len,
7160+ struct au_nfsd_si_lock *nsi_lock)
7161+{
7162+ struct dentry *dentry, *h_parent, *root;
7163+ struct super_block *h_sb;
7164+ char *pathname, *p;
7165+ struct vfsmount *h_mnt;
7166+ struct au_branch *br;
7167+ int err;
7168+ struct path path;
7169+
7170+ br = au_sbr(sb, bindex);
7171+ /* au_br_get(br); */
7172+ h_mnt = br->br_mnt;
7173+ h_sb = h_mnt->mnt_sb;
7174+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
7175+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
7176+ fh_len - Fh_tail, fh[Fh_h_type],
7177+ h_acceptable, /*context*/NULL);
7178+ dentry = h_parent;
7179+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
7180+ AuWarn1("%s decode_fh failed, %ld\n",
7181+ au_sbtype(h_sb), PTR_ERR(h_parent));
7182+ goto out;
7183+ }
7184+ dentry = NULL;
7185+ if (unlikely(au_test_anon(h_parent))) {
7186+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
7187+ au_sbtype(h_sb));
7188+ goto out_h_parent;
7189+ }
7190+
7191+ dentry = ERR_PTR(-ENOMEM);
7192+ pathname = (void *)__get_free_page(GFP_NOFS);
7193+ if (unlikely(!pathname))
7194+ goto out_h_parent;
7195+
7196+ root = sb->s_root;
7197+ path.mnt = h_mnt;
7198+ di_read_lock_parent(root, !AuLock_IR);
7199+ path.dentry = au_h_dptr(root, bindex);
7200+ di_read_unlock(root, !AuLock_IR);
7201+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
7202+ dentry = (void *)p;
7203+ if (IS_ERR(p))
7204+ goto out_pathname;
7205+
7206+ si_read_unlock(sb);
7207+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
7208+ dentry = ERR_PTR(err);
7209+ if (unlikely(err))
7210+ goto out_relock;
7211+
7212+ dentry = ERR_PTR(-ENOENT);
7213+ AuDebugOn(au_test_anon(path.dentry));
7214+ if (unlikely(!path.dentry->d_inode))
7215+ goto out_path;
7216+
7217+ if (ino != path.dentry->d_inode->i_ino)
7218+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
7219+ else
7220+ dentry = dget(path.dentry);
7221+
7222+ out_path:
7223+ path_put(&path);
7224+ out_relock:
7225+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
7226+ if (!IS_ERR(dentry)) {
7227+ dput(dentry);
7228+ dentry = ERR_PTR(-ESTALE);
7229+ }
7230+ out_pathname:
7231+ free_page((unsigned long)pathname);
7232+ out_h_parent:
7233+ dput(h_parent);
7234+ out:
7235+ /* au_br_put(br); */
7236+ AuTraceErrPtr(dentry);
7237+ return dentry;
7238+}
7239+
7240+/* ---------------------------------------------------------------------- */
7241+
7242+static struct dentry *
7243+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
7244+ int fh_type)
7245+{
7246+ struct dentry *dentry;
7247+ __u32 *fh = fid->raw;
7248+ ino_t ino, dir_ino;
7249+ aufs_bindex_t bindex;
7250+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 7251+ .force_lock = 0
7252+ };
7253+
1facf9fc 7254+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
7255+ /* it should never happen, but the file handle is unreliable */
7256+ if (unlikely(fh_len < Fh_tail))
7257+ goto out;
7258+ nsi_lock.sigen = fh[Fh_sigen];
7259+ nsi_lock.br_id = fh[Fh_br_id];
7260+
1facf9fc 7261+ /* branch id may be wrapped around */
7262+ bindex = si_nfsd_read_lock(sb, &nsi_lock);
7263+ if (unlikely(bindex < 0))
7264+ goto out;
7265+ nsi_lock.force_lock = 1;
7266+
7267+ /* is this inode still cached? */
7268+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
7269+ /* it should never happen */
7270+ if (unlikely(ino == AUFS_ROOT_INO))
7271+ goto out;
7272+
1facf9fc 7273+ dir_ino = decode_ino(fh + Fh_dir_ino);
7274+ dentry = decode_by_ino(sb, ino, dir_ino);
7275+ if (IS_ERR(dentry))
7276+ goto out_unlock;
7277+ if (dentry)
7278+ goto accept;
7279+
7280+ /* is the parent dir cached? */
7281+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
7282+ if (IS_ERR(dentry))
7283+ goto out_unlock;
7284+ if (dentry)
7285+ goto accept;
7286+
7287+ /* lookup path */
7288+ dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
7289+ if (IS_ERR(dentry))
7290+ goto out_unlock;
7291+ if (unlikely(!dentry))
7292+ /* todo?: make it ESTALE */
7293+ goto out_unlock;
7294+
7295+ accept:
7296+ if (dentry->d_inode->i_generation == fh[Fh_igen])
7297+ goto out_unlock; /* success */
7298+
7299+ dput(dentry);
7300+ dentry = ERR_PTR(-ESTALE);
7301+ out_unlock:
7302+ si_read_unlock(sb);
7303+ out:
7304+ AuTraceErrPtr(dentry);
7305+ return dentry;
7306+}
7307+
7308+#if 0 /* reserved for future use */
7309+/* support subtreecheck option */
7310+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
7311+ int fh_len, int fh_type)
7312+{
7313+ struct dentry *parent;
7314+ __u32 *fh = fid->raw;
7315+ ino_t dir_ino;
7316+
7317+ dir_ino = decode_ino(fh + Fh_dir_ino);
7318+ parent = decode_by_ino(sb, dir_ino, 0);
7319+ if (IS_ERR(parent))
7320+ goto out;
7321+ if (!parent)
7322+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
7323+ dir_ino, fh, fh_len);
7324+
7325+ out:
7326+ AuTraceErrPtr(parent);
7327+ return parent;
7328+}
7329+#endif
7330+
7331+/* ---------------------------------------------------------------------- */
7332+
7333+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
7334+ int connectable)
7335+{
7336+ int err;
7337+ aufs_bindex_t bindex, bend;
7338+ struct super_block *sb, *h_sb;
7339+ struct inode *inode;
7340+ struct dentry *parent, *h_parent;
7341+ struct au_branch *br;
7342+
7343+ AuDebugOn(au_test_anon(dentry));
7344+
7345+ parent = NULL;
7346+ err = -ENOSPC;
7347+ if (unlikely(*max_len <= Fh_tail)) {
7348+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
7349+ goto out;
7350+ }
7351+
7352+ err = FILEID_ROOT;
7353+ if (IS_ROOT(dentry)) {
7354+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
7355+ goto out;
7356+ }
7357+
7358+ err = -EIO;
7359+ h_parent = NULL;
7360+ sb = dentry->d_sb;
7361+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
7362+ parent = dget_parent(dentry);
7363+ di_read_lock_parent(parent, !AuLock_IR);
7364+ inode = dentry->d_inode;
7365+ AuDebugOn(!inode);
7366+#ifdef CONFIG_AUFS_DEBUG
7367+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7368+ AuWarn1("NFS-exporting requires xino\n");
7369+#endif
7370+
7371+ bend = au_dbtaildir(parent);
7372+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
7373+ h_parent = au_h_dptr(parent, bindex);
7374+ if (h_parent) {
7375+ dget(h_parent);
7376+ break;
7377+ }
7378+ }
7379+ if (unlikely(!h_parent))
7380+ goto out_unlock;
7381+
7382+ err = -EPERM;
7383+ br = au_sbr(sb, bindex);
7384+ h_sb = br->br_mnt->mnt_sb;
7385+ if (unlikely(!h_sb->s_export_op)) {
7386+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
7387+ goto out_dput;
7388+ }
7389+
7390+ fh[Fh_br_id] = br->br_id;
7391+ fh[Fh_sigen] = au_sigen(sb);
7392+ encode_ino(fh + Fh_ino, inode->i_ino);
7393+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
7394+ fh[Fh_igen] = inode->i_generation;
7395+
7396+ *max_len -= Fh_tail;
7397+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
7398+ max_len,
7399+ /*connectable or subtreecheck*/0);
7400+ err = fh[Fh_h_type];
7401+ *max_len += Fh_tail;
7402+ /* todo: macros? */
7403+ if (err != 255)
7404+ err = 99;
7405+ else
7406+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
7407+
7408+ out_dput:
7409+ dput(h_parent);
7410+ out_unlock:
7411+ di_read_unlock(parent, !AuLock_IR);
7412+ dput(parent);
7413+ aufs_read_unlock(dentry, AuLock_IR);
7414+ out:
7415+ if (unlikely(err < 0))
7416+ err = 255;
7417+ return err;
7418+}
7419+
7420+/* ---------------------------------------------------------------------- */
7421+
4a4d8108
AM
7422+static int aufs_commit_metadata(struct inode *inode)
7423+{
7424+ int err;
7425+ aufs_bindex_t bindex;
7426+ struct super_block *sb;
7427+ struct inode *h_inode;
7428+ int (*f)(struct inode *inode);
7429+
7430+ sb = inode->i_sb;
7431+ si_read_lock(sb, AuLock_FLUSH);
7432+ ii_write_lock_child(inode);
7433+ bindex = au_ibstart(inode);
7434+ AuDebugOn(bindex < 0);
7435+ h_inode = au_h_iptr(inode, bindex);
7436+
7437+ f = h_inode->i_sb->s_export_op->commit_metadata;
7438+ if (f)
7439+ err = f(h_inode);
7440+ else {
7441+ struct writeback_control wbc = {
7442+ .sync_mode = WB_SYNC_ALL,
7443+ .nr_to_write = 0 /* metadata only */
7444+ };
7445+
7446+ err = sync_inode(h_inode, &wbc);
7447+ }
7448+
7449+ au_cpup_attr_timesizes(inode);
7450+ ii_write_unlock(inode);
7451+ si_read_unlock(sb);
7452+ return err;
7453+}
7454+
7455+/* ---------------------------------------------------------------------- */
7456+
1facf9fc 7457+static struct export_operations aufs_export_op = {
4a4d8108 7458+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 7459+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
7460+ .encode_fh = aufs_encode_fh,
7461+ .commit_metadata = aufs_commit_metadata
1facf9fc 7462+};
7463+
7464+void au_export_init(struct super_block *sb)
7465+{
7466+ struct au_sbinfo *sbinfo;
7467+ __u32 u;
7468+
7469+ sb->s_export_op = &aufs_export_op;
7470+ sbinfo = au_sbi(sb);
7471+ sbinfo->si_xigen = NULL;
7472+ get_random_bytes(&u, sizeof(u));
7473+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
7474+ atomic_set(&sbinfo->si_xigen_next, u);
7475+}
4a4d8108
AM
7476diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/file.c linux-2.6.34/fs/aufs/file.c
7477--- linux-2.6.34.org/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
7478+++ linux-2.6.34/fs/aufs/file.c 2010-05-31 22:15:32.000000000 +0200
7479@@ -0,0 +1,652 @@
1facf9fc 7480+/*
4a4d8108 7481+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 7482+ *
7483+ * This program, aufs is free software; you can redistribute it and/or modify
7484+ * it under the terms of the GNU General Public License as published by
7485+ * the Free Software Foundation; either version 2 of the License, or
7486+ * (at your option) any later version.
dece6358
AM
7487+ *
7488+ * This program is distributed in the hope that it will be useful,
7489+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7490+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7491+ * GNU General Public License for more details.
7492+ *
7493+ * You should have received a copy of the GNU General Public License
7494+ * along with this program; if not, write to the Free Software
7495+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7496+ */
7497+
7498+/*
4a4d8108 7499+ * handling file/dir, and address_space operation
1facf9fc 7500+ */
7501+
dece6358 7502+#include <linux/file.h>
4a4d8108
AM
7503+#include <linux/fsnotify.h>
7504+#include <linux/namei.h>
7505+#include <linux/pagemap.h>
1facf9fc 7506+#include "aufs.h"
7507+
4a4d8108
AM
7508+/* drop flags for writing */
7509+unsigned int au_file_roflags(unsigned int flags)
7510+{
7511+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
7512+ flags |= O_RDONLY | O_NOATIME;
7513+ return flags;
7514+}
7515+
7516+/* common functions to regular file and dir */
7517+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
7518+ struct file *file)
1facf9fc 7519+{
1308ab2a 7520+ struct file *h_file;
4a4d8108
AM
7521+ struct dentry *h_dentry;
7522+ struct inode *h_inode;
7523+ struct super_block *sb;
7524+ struct au_branch *br;
7525+ struct path h_path;
7526+ int err, exec_flag;
1facf9fc 7527+
4a4d8108
AM
7528+ /* a race condition can happen between open and unlink/rmdir */
7529+ h_file = ERR_PTR(-ENOENT);
7530+ h_dentry = au_h_dptr(dentry, bindex);
7531+ if (au_test_nfsd(current) && !h_dentry)
7532+ goto out;
7533+ h_inode = h_dentry->d_inode;
7534+ if (au_test_nfsd(current) && !h_inode)
7535+ goto out;
7536+ if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
7537+ || !h_inode))
7538+ goto out;
1facf9fc 7539+
4a4d8108
AM
7540+ sb = dentry->d_sb;
7541+ br = au_sbr(sb, bindex);
7542+ h_file = ERR_PTR(-EACCES);
7543+ exec_flag = flags & vfsub_fmode_to_uint(FMODE_EXEC);
7544+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
7545+ goto out;
1facf9fc 7546+
4a4d8108
AM
7547+ /* drop flags for writing */
7548+ if (au_test_ro(sb, bindex, dentry->d_inode))
7549+ flags = au_file_roflags(flags);
7550+ flags &= ~O_CREAT;
7551+ atomic_inc(&br->br_count);
7552+ h_path.dentry = h_dentry;
7553+ h_path.mnt = br->br_mnt;
7554+ if (!au_special_file(h_inode->i_mode))
7555+ h_file = vfsub_dentry_open(&h_path, flags);
7556+ else {
7557+ /* this block depends upon the configuration */
7558+ di_read_unlock(dentry, AuLock_IR);
7559+ fi_write_unlock(file);
7560+ si_read_unlock(sb);
7561+ h_file = vfsub_dentry_open(&h_path, flags);
7562+ si_noflush_read_lock(sb);
7563+ fi_write_lock(file);
7564+ di_read_lock_child(dentry, AuLock_IR);
dece6358 7565+ }
4a4d8108
AM
7566+ if (IS_ERR(h_file))
7567+ goto out_br;
dece6358 7568+
4a4d8108
AM
7569+ if (exec_flag) {
7570+ err = deny_write_access(h_file);
7571+ if (unlikely(err)) {
7572+ fput(h_file);
7573+ h_file = ERR_PTR(err);
7574+ goto out_br;
7575+ }
7576+ }
7577+ fsnotify_open(h_dentry);
7578+ goto out; /* success */
1facf9fc 7579+
4a4d8108
AM
7580+ out_br:
7581+ atomic_dec(&br->br_count);
7582+ out:
7583+ return h_file;
7584+}
1308ab2a 7585+
4a4d8108
AM
7586+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
7587+ struct au_fidir *fidir)
1facf9fc 7588+{
dece6358 7589+ int err;
1facf9fc 7590+ struct dentry *dentry;
1308ab2a 7591+
4a4d8108
AM
7592+ err = au_finfo_init(file, fidir);
7593+ if (unlikely(err))
7594+ goto out;
1facf9fc 7595+
7596+ dentry = file->f_dentry;
4a4d8108
AM
7597+ di_read_lock_child(dentry, AuLock_IR);
7598+ err = open(file, vfsub_file_flags(file));
7599+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 7600+
4a4d8108
AM
7601+ fi_write_unlock(file);
7602+ if (unlikely(err)) {
7603+ au_fi(file)->fi_hdir = NULL;
7604+ au_finfo_fin(file);
1308ab2a 7605+ }
4a4d8108
AM
7606+
7607+ out:
1308ab2a 7608+ return err;
7609+}
dece6358 7610+
4a4d8108 7611+int au_reopen_nondir(struct file *file)
1308ab2a 7612+{
4a4d8108
AM
7613+ int err;
7614+ aufs_bindex_t bstart;
7615+ struct dentry *dentry;
7616+ struct file *h_file, *h_file_tmp;
1308ab2a 7617+
4a4d8108
AM
7618+ dentry = file->f_dentry;
7619+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
7620+ bstart = au_dbstart(dentry);
7621+ h_file_tmp = NULL;
7622+ if (au_fbstart(file) == bstart) {
7623+ h_file = au_hf_top(file);
7624+ if (file->f_mode == h_file->f_mode)
7625+ return 0; /* success */
7626+ h_file_tmp = h_file;
7627+ get_file(h_file_tmp);
7628+ au_set_h_fptr(file, bstart, NULL);
7629+ }
7630+ AuDebugOn(au_fi(file)->fi_hdir);
7631+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 7632+
4a4d8108
AM
7633+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
7634+ file);
7635+ err = PTR_ERR(h_file);
7636+ if (IS_ERR(h_file))
7637+ goto out; /* todo: close all? */
7638+
7639+ err = 0;
7640+ au_set_fbstart(file, bstart);
7641+ au_set_h_fptr(file, bstart, h_file);
7642+ au_update_figen(file);
7643+ /* todo: necessary? */
7644+ /* file->f_ra = h_file->f_ra; */
7645+
7646+ out:
7647+ if (h_file_tmp)
7648+ fput(h_file_tmp);
7649+ return err;
1facf9fc 7650+}
7651+
1308ab2a 7652+/* ---------------------------------------------------------------------- */
7653+
4a4d8108
AM
7654+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
7655+ struct dentry *hi_wh)
1facf9fc 7656+{
4a4d8108
AM
7657+ int err;
7658+ aufs_bindex_t bstart;
7659+ struct au_dinfo *dinfo;
7660+ struct dentry *h_dentry;
7661+ struct au_hdentry *hdp;
1facf9fc 7662+
4a4d8108
AM
7663+ dinfo = au_di(file->f_dentry);
7664+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 7665+
4a4d8108
AM
7666+ bstart = dinfo->di_bstart;
7667+ dinfo->di_bstart = btgt;
7668+ hdp = dinfo->di_hdentry;
7669+ h_dentry = hdp[0 + btgt].hd_dentry;
7670+ hdp[0 + btgt].hd_dentry = hi_wh;
7671+ err = au_reopen_nondir(file);
7672+ hdp[0 + btgt].hd_dentry = h_dentry;
7673+ dinfo->di_bstart = bstart;
1facf9fc 7674+
1facf9fc 7675+ return err;
7676+}
7677+
4a4d8108
AM
7678+static int au_ready_to_write_wh(struct file *file, loff_t len,
7679+ aufs_bindex_t bcpup)
1facf9fc 7680+{
4a4d8108 7681+ int err;
dece6358 7682+ struct inode *inode;
4a4d8108 7683+ struct dentry *dentry, *hi_wh;
1facf9fc 7684+
dece6358 7685+ dentry = file->f_dentry;
4a4d8108 7686+ au_update_dbstart(dentry);
dece6358 7687+ inode = dentry->d_inode;
4a4d8108
AM
7688+ hi_wh = au_hi_wh(inode, bcpup);
7689+ if (!hi_wh)
7690+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
7691+ else
7692+ /* already copied-up after unlink */
7693+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 7694+
4a4d8108
AM
7695+ if (!err
7696+ && inode->i_nlink > 1
7697+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
7698+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 7699+
dece6358 7700+ return err;
1facf9fc 7701+}
7702+
4a4d8108
AM
7703+/*
7704+ * prepare the @file for writing.
7705+ */
7706+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 7707+{
4a4d8108
AM
7708+ int err;
7709+ aufs_bindex_t bstart, bcpup;
7710+ struct dentry *dentry, *parent, *h_dentry;
7711+ struct inode *h_inode, *inode;
1facf9fc 7712+ struct super_block *sb;
4a4d8108 7713+ struct file *h_file;
1facf9fc 7714+
7715+ dentry = file->f_dentry;
1facf9fc 7716+ sb = dentry->d_sb;
4a4d8108
AM
7717+ inode = dentry->d_inode;
7718+ AuDebugOn(au_special_file(inode->i_mode));
7719+ bstart = au_fbstart(file);
7720+ err = au_test_ro(sb, bstart, inode);
7721+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
7722+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 7723+ goto out;
4a4d8108 7724+ }
1facf9fc 7725+
4a4d8108
AM
7726+ /* need to cpup */
7727+ parent = dget_parent(dentry);
7728+ di_write_lock_parent(parent);
7729+ err = AuWbrCopyup(au_sbi(sb), dentry);
7730+ bcpup = err;
7731+ if (unlikely(err < 0))
7732+ goto out_dgrade;
7733+ err = 0;
7734+
7735+ if (!au_h_dptr(parent, bcpup)) {
7736+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 7737+ if (unlikely(err))
4a4d8108
AM
7738+ goto out_dgrade;
7739+ }
7740+
7741+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
7742+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
7743+ if (unlikely(err))
7744+ goto out_dgrade;
7745+
7746+ h_dentry = au_hf_top(file)->f_dentry;
7747+ h_inode = h_dentry->d_inode;
7748+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
7749+ h_file = au_h_open_pre(dentry, bstart);
7750+ if (IS_ERR(h_file)) {
7751+ err = PTR_ERR(h_file);
7752+ h_file = NULL;
7753+ } else if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
7754+ /* || !h_inode->i_nlink */) {
7755+ err = au_ready_to_write_wh(file, len, bcpup);
7756+ di_downgrade_lock(parent, AuLock_IR);
7757+ } else {
7758+ di_downgrade_lock(parent, AuLock_IR);
7759+ if (!au_h_dptr(dentry, bcpup))
7760+ err = au_sio_cpup_simple(dentry, bcpup, len,
7761+ AuCpup_DTIME);
7762+ if (!err)
7763+ err = au_reopen_nondir(file);
7764+ }
7765+ mutex_unlock(&h_inode->i_mutex);
7766+ au_h_open_post(dentry, bstart, h_file);
7767+
7768+ if (!err) {
7769+ au_pin_set_parent_lflag(pin, /*lflag*/0);
7770+ goto out_dput; /* success */
7771+ }
7772+ au_unpin(pin);
7773+ goto out_unlock;
1facf9fc 7774+
4a4d8108
AM
7775+ out_dgrade:
7776+ di_downgrade_lock(parent, AuLock_IR);
1facf9fc 7777+ out_unlock:
4a4d8108
AM
7778+ di_read_unlock(parent, AuLock_IR);
7779+ out_dput:
7780+ dput(parent);
1facf9fc 7781+ out:
1facf9fc 7782+ return err;
7783+}
7784+
4a4d8108
AM
7785+/* ---------------------------------------------------------------------- */
7786+
7787+int au_do_flush(struct file *file, fl_owner_t id,
7788+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 7789+{
4a4d8108 7790+ int err;
1308ab2a 7791+ struct dentry *dentry;
1facf9fc 7792+ struct super_block *sb;
4a4d8108 7793+ struct inode *inode;
1facf9fc 7794+
1facf9fc 7795+ dentry = file->f_dentry;
7796+ sb = dentry->d_sb;
dece6358 7797+ inode = dentry->d_inode;
4a4d8108
AM
7798+ si_noflush_read_lock(sb);
7799+ fi_read_lock(file);
7800+ di_read_lock_child(dentry, AuLock_IW);
1facf9fc 7801+
4a4d8108
AM
7802+ err = flush(file, id);
7803+ au_cpup_attr_timesizes(inode);
1facf9fc 7804+
4a4d8108
AM
7805+ di_read_unlock(dentry, AuLock_IW);
7806+ fi_read_unlock(file);
1308ab2a 7807+ si_read_unlock(sb);
dece6358 7808+ return err;
1facf9fc 7809+}
7810+
4a4d8108
AM
7811+/* ---------------------------------------------------------------------- */
7812+
7813+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 7814+{
4a4d8108
AM
7815+ int err;
7816+ aufs_bindex_t bstart;
7817+ struct au_pin pin;
7818+ struct au_finfo *finfo;
7819+ struct dentry *dentry, *parent, *hi_wh;
7820+ struct inode *inode;
1facf9fc 7821+ struct super_block *sb;
7822+
4a4d8108
AM
7823+ FiMustWriteLock(file);
7824+
7825+ err = 0;
7826+ finfo = au_fi(file);
1308ab2a 7827+ dentry = file->f_dentry;
7828+ sb = dentry->d_sb;
4a4d8108
AM
7829+ inode = dentry->d_inode;
7830+ bstart = au_ibstart(inode);
7831+ if (bstart == finfo->fi_btop)
1308ab2a 7832+ goto out;
dece6358 7833+
4a4d8108
AM
7834+ parent = dget_parent(dentry);
7835+ if (au_test_ro(sb, bstart, inode)) {
7836+ di_read_lock_parent(parent, !AuLock_IR);
7837+ err = AuWbrCopyup(au_sbi(sb), dentry);
7838+ bstart = err;
7839+ di_read_unlock(parent, !AuLock_IR);
7840+ if (unlikely(err < 0))
7841+ goto out_parent;
7842+ err = 0;
1facf9fc 7843+ }
1facf9fc 7844+
4a4d8108
AM
7845+ di_read_lock_parent(parent, AuLock_IR);
7846+ hi_wh = au_hi_wh(inode, bstart);
7847+ if (au_opt_test(au_mntflags(sb), PLINK)
7848+ && au_plink_test(inode)
7849+ && !d_unhashed(dentry)) {
7850+ err = au_test_and_cpup_dirs(dentry, bstart);
7851+ if (unlikely(err))
7852+ goto out_unlock;
7853+
7854+ /* always superio. */
7855+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
7856+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
7857+ if (!err)
7858+ err = au_sio_cpup_simple(dentry, bstart, -1,
7859+ AuCpup_DTIME);
7860+ au_unpin(&pin);
7861+ } else if (hi_wh) {
7862+ /* already copied-up after unlink */
7863+ err = au_reopen_wh(file, bstart, hi_wh);
7864+ *need_reopen = 0;
7865+ }
1facf9fc 7866+
4a4d8108
AM
7867+ out_unlock:
7868+ di_read_unlock(parent, AuLock_IR);
7869+ out_parent:
7870+ dput(parent);
1308ab2a 7871+ out:
1308ab2a 7872+ return err;
dece6358 7873+}
1facf9fc 7874+
4a4d8108 7875+static void au_do_refresh_dir(struct file *file)
dece6358 7876+{
4a4d8108
AM
7877+ aufs_bindex_t bindex, bend, new_bindex, brid;
7878+ struct au_hfile *p, tmp, *q;
7879+ struct au_finfo *finfo;
1308ab2a 7880+ struct super_block *sb;
4a4d8108 7881+ struct au_fidir *fidir;
1facf9fc 7882+
4a4d8108 7883+ FiMustWriteLock(file);
1facf9fc 7884+
4a4d8108
AM
7885+ sb = file->f_dentry->d_sb;
7886+ finfo = au_fi(file);
7887+ fidir = finfo->fi_hdir;
7888+ AuDebugOn(!fidir);
7889+ p = fidir->fd_hfile + finfo->fi_btop;
7890+ brid = p->hf_br->br_id;
7891+ bend = fidir->fd_bbot;
7892+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
7893+ if (!p->hf_file)
7894+ continue;
1308ab2a 7895+
4a4d8108
AM
7896+ new_bindex = au_br_index(sb, p->hf_br->br_id);
7897+ if (new_bindex == bindex)
7898+ continue;
7899+ if (new_bindex < 0) {
7900+ au_set_h_fptr(file, bindex, NULL);
7901+ continue;
7902+ }
1308ab2a 7903+
4a4d8108
AM
7904+ /* swap two lower inode, and loop again */
7905+ q = fidir->fd_hfile + new_bindex;
7906+ tmp = *q;
7907+ *q = *p;
7908+ *p = tmp;
7909+ if (tmp.hf_file) {
7910+ bindex--;
7911+ p--;
7912+ }
7913+ }
1308ab2a 7914+
4a4d8108
AM
7915+ p = fidir->fd_hfile;
7916+ if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
7917+ bend = au_sbend(sb);
7918+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
7919+ finfo->fi_btop++, p++)
7920+ if (p->hf_file) {
7921+ if (p->hf_file->f_dentry
7922+ && p->hf_file->f_dentry->d_inode)
7923+ break;
7924+ else
7925+ au_hfput(p, file);
7926+ }
7927+ } else {
7928+ bend = au_br_index(sb, brid);
7929+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
7930+ finfo->fi_btop++, p++)
7931+ if (p->hf_file)
7932+ au_hfput(p, file);
7933+ bend = au_sbend(sb);
7934+ }
1308ab2a 7935+
4a4d8108
AM
7936+ p = fidir->fd_hfile + bend;
7937+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
7938+ fidir->fd_bbot--, p--)
7939+ if (p->hf_file) {
7940+ if (p->hf_file->f_dentry
7941+ && p->hf_file->f_dentry->d_inode)
7942+ break;
7943+ else
7944+ au_hfput(p, file);
7945+ }
7946+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 7947+}
7948+
4a4d8108
AM
7949+/*
7950+ * after branch manipulating, refresh the file.
7951+ */
7952+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 7953+{
4a4d8108
AM
7954+ int err, need_reopen;
7955+ aufs_bindex_t bend, bindex;
7956+ struct dentry *dentry;
1308ab2a 7957+ struct au_finfo *finfo;
4a4d8108 7958+ struct au_hfile *hfile;
1facf9fc 7959+
4a4d8108 7960+ dentry = file->f_dentry;
1308ab2a 7961+ finfo = au_fi(file);
4a4d8108
AM
7962+ if (!finfo->fi_hdir) {
7963+ hfile = &finfo->fi_htop;
7964+ AuDebugOn(!hfile->hf_file);
7965+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
7966+ AuDebugOn(bindex < 0);
7967+ if (bindex != finfo->fi_btop)
7968+ au_set_fbstart(file, bindex);
7969+ } else {
7970+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
7971+ if (unlikely(err))
7972+ goto out;
7973+ au_do_refresh_dir(file);
7974+ }
1facf9fc 7975+
4a4d8108
AM
7976+ err = 0;
7977+ need_reopen = 1;
7978+ if (!au_test_mmapped(file))
7979+ err = au_file_refresh_by_inode(file, &need_reopen);
7980+ if (!err && need_reopen && !d_unhashed(dentry))
7981+ err = reopen(file);
7982+ if (!err) {
7983+ au_update_figen(file);
7984+ goto out; /* success */
7985+ }
7986+
7987+ /* error, close all lower files */
7988+ if (finfo->fi_hdir) {
7989+ bend = au_fbend_dir(file);
7990+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
7991+ au_set_h_fptr(file, bindex, NULL);
7992+ }
1facf9fc 7993+
4a4d8108 7994+ out:
1facf9fc 7995+ return err;
7996+}
7997+
4a4d8108
AM
7998+/* common function to regular file and dir */
7999+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8000+ int wlock)
dece6358 8001+{
1308ab2a 8002+ int err;
4a4d8108
AM
8003+ unsigned int sigen, figen;
8004+ aufs_bindex_t bstart;
8005+ unsigned char pseudo_link;
8006+ struct dentry *dentry;
8007+ struct inode *inode;
1facf9fc 8008+
4a4d8108
AM
8009+ err = 0;
8010+ dentry = file->f_dentry;
8011+ inode = dentry->d_inode;
8012+ AuDebugOn(au_special_file(inode->i_mode));
8013+ sigen = au_sigen(dentry->d_sb);
8014+ fi_write_lock(file);
8015+ figen = au_figen(file);
8016+ di_write_lock_child(dentry);
8017+ bstart = au_dbstart(dentry);
8018+ pseudo_link = (bstart != au_ibstart(inode));
8019+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
8020+ if (!wlock) {
8021+ di_downgrade_lock(dentry, AuLock_IR);
8022+ fi_downgrade_lock(file);
8023+ }
8024+ goto out; /* success */
8025+ }
dece6358 8026+
4a4d8108
AM
8027+ AuDbg("sigen %d, figen %d\n", sigen, figen);
8028+ if (sigen != au_digen(dentry)
8029+ || sigen != au_iigen(inode)) {
8030+ err = au_reval_dpath(dentry, sigen);
8031+ if (unlikely(err < 0))
8032+ goto out;
8033+ AuDebugOn(au_digen(dentry) != sigen
8034+ || au_iigen(inode) != sigen);
8035+ }
dece6358 8036+
4a4d8108
AM
8037+ err = refresh_file(file, reopen);
8038+ if (!err) {
8039+ if (!wlock) {
8040+ di_downgrade_lock(dentry, AuLock_IR);
8041+ fi_downgrade_lock(file);
8042+ }
8043+ } else {
8044+ di_write_unlock(dentry);
8045+ fi_write_unlock(file);
8046+ }
1facf9fc 8047+
4a4d8108 8048+ out:
1308ab2a 8049+ return err;
8050+}
1facf9fc 8051+
4a4d8108
AM
8052+/* ---------------------------------------------------------------------- */
8053+
8054+/* cf. aufs_nopage() */
8055+/* for madvise(2) */
8056+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 8057+{
4a4d8108
AM
8058+ unlock_page(page);
8059+ return 0;
8060+}
1facf9fc 8061+
4a4d8108
AM
8062+/* it will never be called, but necessary to support O_DIRECT */
8063+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
8064+ const struct iovec *iov, loff_t offset,
8065+ unsigned long nr_segs)
8066+{ BUG(); return 0; }
1facf9fc 8067+
4a4d8108
AM
8068+/*
8069+ * it will never be called, but madvise and fadvise behaves differently
8070+ * when get_xip_mem is defined
8071+ */
8072+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
8073+ int create, void **kmem, unsigned long *pfn)
8074+{ BUG(); return 0; }
1facf9fc 8075+
4a4d8108
AM
8076+/* they will never be called. */
8077+#ifdef CONFIG_AUFS_DEBUG
8078+static int aufs_write_begin(struct file *file, struct address_space *mapping,
8079+ loff_t pos, unsigned len, unsigned flags,
8080+ struct page **pagep, void **fsdata)
8081+{ AuUnsupport(); return 0; }
8082+static int aufs_write_end(struct file *file, struct address_space *mapping,
8083+ loff_t pos, unsigned len, unsigned copied,
8084+ struct page *page, void *fsdata)
8085+{ AuUnsupport(); return 0; }
8086+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
8087+{ AuUnsupport(); return 0; }
8088+static void aufs_sync_page(struct page *page)
8089+{ AuUnsupport(); }
1308ab2a 8090+
4a4d8108
AM
8091+static int aufs_set_page_dirty(struct page *page)
8092+{ AuUnsupport(); return 0; }
8093+static void aufs_invalidatepage(struct page *page, unsigned long offset)
8094+{ AuUnsupport(); }
8095+static int aufs_releasepage(struct page *page, gfp_t gfp)
8096+{ AuUnsupport(); return 0; }
8097+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
8098+ struct page *page)
8099+{ AuUnsupport(); return 0; }
8100+static int aufs_launder_page(struct page *page)
8101+{ AuUnsupport(); return 0; }
8102+static int aufs_is_partially_uptodate(struct page *page,
8103+ read_descriptor_t *desc,
8104+ unsigned long from)
8105+{ AuUnsupport(); return 0; }
8106+static int aufs_error_remove_page(struct address_space *mapping,
8107+ struct page *page)
8108+{ AuUnsupport(); return 0; }
8109+#endif /* CONFIG_AUFS_DEBUG */
8110+
8111+const struct address_space_operations aufs_aop = {
8112+ .readpage = aufs_readpage,
8113+ .direct_IO = aufs_direct_IO,
8114+ .get_xip_mem = aufs_get_xip_mem,
8115+#ifdef CONFIG_AUFS_DEBUG
8116+ .writepage = aufs_writepage,
8117+ .sync_page = aufs_sync_page,
8118+ /* no writepages, because of writepage */
8119+ .set_page_dirty = aufs_set_page_dirty,
8120+ /* no readpages, because of readpage */
8121+ .write_begin = aufs_write_begin,
8122+ .write_end = aufs_write_end,
8123+ /* no bmap, no block device */
8124+ .invalidatepage = aufs_invalidatepage,
8125+ .releasepage = aufs_releasepage,
8126+ .migratepage = aufs_migratepage,
8127+ .launder_page = aufs_launder_page,
8128+ .is_partially_uptodate = aufs_is_partially_uptodate,
8129+ .error_remove_page = aufs_error_remove_page
8130+#endif /* CONFIG_AUFS_DEBUG */
dece6358 8131+};
4a4d8108
AM
8132diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/file.h linux-2.6.34/fs/aufs/file.h
8133--- linux-2.6.34.org/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
8134+++ linux-2.6.34/fs/aufs/file.h 2010-05-31 22:15:32.000000000 +0200
8135@@ -0,0 +1,234 @@
8136+/*
8137+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8138+ *
8139+ * This program, aufs is free software; you can redistribute it and/or modify
8140+ * it under the terms of the GNU General Public License as published by
8141+ * the Free Software Foundation; either version 2 of the License, or
8142+ * (at your option) any later version.
8143+ *
8144+ * This program is distributed in the hope that it will be useful,
8145+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8146+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8147+ * GNU General Public License for more details.
8148+ *
8149+ * You should have received a copy of the GNU General Public License
8150+ * along with this program; if not, write to the Free Software
8151+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8152+ */
1facf9fc 8153+
4a4d8108
AM
8154+/*
8155+ * file operations
8156+ */
1facf9fc 8157+
4a4d8108
AM
8158+#ifndef __AUFS_FILE_H__
8159+#define __AUFS_FILE_H__
1facf9fc 8160+
4a4d8108 8161+#ifdef __KERNEL__
1facf9fc 8162+
4a4d8108
AM
8163+#include <linux/fs.h>
8164+#include <linux/poll.h>
8165+#include <linux/aufs_type.h>
8166+#include "rwsem.h"
1facf9fc 8167+
4a4d8108
AM
8168+struct au_branch;
8169+struct au_hfile {
8170+ struct file *hf_file;
8171+ struct au_branch *hf_br;
8172+};
1facf9fc 8173+
4a4d8108
AM
8174+struct au_vdir;
8175+struct au_fidir {
8176+ aufs_bindex_t fd_bbot;
8177+ aufs_bindex_t fd_nent;
8178+ struct au_vdir *fd_vdir_cache;
8179+ struct au_hfile fd_hfile[];
8180+};
1facf9fc 8181+
4a4d8108 8182+static inline int au_fidir_sz(int nent)
dece6358 8183+{
4a4d8108
AM
8184+ AuDebugOn(nent < 0);
8185+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
8186+}
1facf9fc 8187+
4a4d8108
AM
8188+struct au_finfo {
8189+ atomic_t fi_generation;
dece6358 8190+
4a4d8108
AM
8191+ struct au_rwsem fi_rwsem;
8192+ aufs_bindex_t fi_btop;
8193+
8194+ /* do not union them */
8195+ struct { /* for non-dir */
8196+ struct au_hfile fi_htop;
8197+ struct vm_operations_struct *fi_hvmop;
8198+ struct mutex fi_vm_mtx;
8199+ struct mutex fi_mmap;
8200+ };
8201+ struct au_fidir *fi_hdir; /* for dir only */
8202+} ____cacheline_aligned_in_smp;
1facf9fc 8203+
4a4d8108 8204+/* ---------------------------------------------------------------------- */
1facf9fc 8205+
4a4d8108
AM
8206+/* file.c */
8207+extern const struct address_space_operations aufs_aop;
8208+unsigned int au_file_roflags(unsigned int flags);
8209+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8210+ struct file *file);
8211+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8212+ struct au_fidir *fidir);
8213+int au_reopen_nondir(struct file *file);
8214+struct au_pin;
8215+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
8216+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8217+ int wlock);
8218+int au_do_flush(struct file *file, fl_owner_t id,
8219+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 8220+
4a4d8108
AM
8221+/* poll.c */
8222+#ifdef CONFIG_AUFS_POLL
8223+unsigned int aufs_poll(struct file *file, poll_table *wait);
8224+#endif
1facf9fc 8225+
4a4d8108
AM
8226+#ifdef CONFIG_AUFS_BR_HFSPLUS
8227+/* hfsplus.c */
8228+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
8229+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
8230+ struct file *h_file);
8231+#else
8232+static inline
8233+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 8234+{
4a4d8108
AM
8235+ return NULL;
8236+}
1facf9fc 8237+
4a4d8108
AM
8238+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
8239+ struct file *h_file);
8240+#endif
1facf9fc 8241+
4a4d8108
AM
8242+/* f_op.c */
8243+extern const struct file_operations aufs_file_fop;
8244+extern const struct vm_operations_struct aufs_vm_ops;
8245+int au_do_open_nondir(struct file *file, int flags);
8246+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
8247+
8248+#ifdef CONFIG_AUFS_SP_IATTR
8249+/* f_op_sp.c */
8250+int au_special_file(umode_t mode);
8251+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
8252+#else
8253+AuStubInt0(au_special_file, umode_t mode)
8254+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
8255+ dev_t rdev)
8256+{
8257+ init_special_inode(inode, mode, rdev);
8258+}
8259+#endif
1facf9fc 8260+
4a4d8108
AM
8261+/* finfo.c */
8262+void au_hfput(struct au_hfile *hf, struct file *file);
8263+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
8264+ struct file *h_file);
1facf9fc 8265+
4a4d8108
AM
8266+void au_update_figen(struct file *file);
8267+void au_fi_mmap_lock(struct file *file);
8268+void au_fi_mmap_unlock(struct file *file);
8269+struct au_fidir *au_fidir_alloc(struct super_block *sb);
8270+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 8271+
4a4d8108
AM
8272+void au_fi_init_once(void *_fi);
8273+void au_finfo_fin(struct file *file);
8274+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 8275+
4a4d8108
AM
8276+/* ioctl.c */
8277+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
1facf9fc 8278+
4a4d8108 8279+/* ---------------------------------------------------------------------- */
1facf9fc 8280+
4a4d8108
AM
8281+static inline struct au_finfo *au_fi(struct file *file)
8282+{
8283+ return file->private_data;
8284+}
1facf9fc 8285+
4a4d8108 8286+/* ---------------------------------------------------------------------- */
1facf9fc 8287+
4a4d8108
AM
8288+/*
8289+ * fi_read_lock, fi_write_lock,
8290+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
8291+ */
8292+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 8293+
4a4d8108
AM
8294+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
8295+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
8296+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 8297+
1308ab2a 8298+/* ---------------------------------------------------------------------- */
8299+
4a4d8108
AM
8300+/* todo: hard/soft set? */
8301+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 8302+{
4a4d8108
AM
8303+ FiMustAnyLock(file);
8304+ return au_fi(file)->fi_btop;
8305+}
dece6358 8306+
4a4d8108
AM
8307+static inline aufs_bindex_t au_fbend_dir(struct file *file)
8308+{
8309+ FiMustAnyLock(file);
8310+ AuDebugOn(!au_fi(file)->fi_hdir);
8311+ return au_fi(file)->fi_hdir->fd_bbot;
8312+}
1facf9fc 8313+
4a4d8108
AM
8314+static inline struct au_vdir *au_fvdir_cache(struct file *file)
8315+{
8316+ FiMustAnyLock(file);
8317+ AuDebugOn(!au_fi(file)->fi_hdir);
8318+ return au_fi(file)->fi_hdir->fd_vdir_cache;
8319+}
1facf9fc 8320+
4a4d8108
AM
8321+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
8322+{
8323+ FiMustWriteLock(file);
8324+ au_fi(file)->fi_btop = bindex;
8325+}
1facf9fc 8326+
4a4d8108
AM
8327+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
8328+{
8329+ FiMustWriteLock(file);
8330+ AuDebugOn(!au_fi(file)->fi_hdir);
8331+ au_fi(file)->fi_hdir->fd_bbot = bindex;
8332+}
1308ab2a 8333+
4a4d8108
AM
8334+static inline void au_set_fvdir_cache(struct file *file,
8335+ struct au_vdir *vdir_cache)
8336+{
8337+ FiMustWriteLock(file);
8338+ AuDebugOn(!au_fi(file)->fi_hdir);
8339+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
8340+}
dece6358 8341+
4a4d8108
AM
8342+static inline struct file *au_hf_top(struct file *file)
8343+{
8344+ FiMustAnyLock(file);
8345+ AuDebugOn(au_fi(file)->fi_hdir);
8346+ return au_fi(file)->fi_htop.hf_file;
8347+}
1facf9fc 8348+
4a4d8108
AM
8349+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
8350+{
8351+ FiMustAnyLock(file);
8352+ AuDebugOn(!au_fi(file)->fi_hdir);
8353+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
8354+}
8355+
4a4d8108
AM
8356+/* todo: memory barrier? */
8357+static inline unsigned int au_figen(struct file *f)
dece6358 8358+{
4a4d8108
AM
8359+ return atomic_read(&au_fi(f)->fi_generation);
8360+}
dece6358 8361+
4a4d8108
AM
8362+static inline int au_test_mmapped(struct file *f)
8363+{
8364+ FiMustAnyLock(f);
8365+ return !!(au_fi(f)->fi_hvmop);
8366+}
1308ab2a 8367+
4a4d8108
AM
8368+#endif /* __KERNEL__ */
8369+#endif /* __AUFS_FILE_H__ */
8370diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/finfo.c linux-2.6.34/fs/aufs/finfo.c
8371--- linux-2.6.34.org/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
8372+++ linux-2.6.34/fs/aufs/finfo.c 2010-05-31 22:15:32.000000000 +0200
8373@@ -0,0 +1,167 @@
8374+/*
8375+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8376+ *
8377+ * This program, aufs is free software; you can redistribute it and/or modify
8378+ * it under the terms of the GNU General Public License as published by
8379+ * the Free Software Foundation; either version 2 of the License, or
8380+ * (at your option) any later version.
8381+ *
8382+ * This program is distributed in the hope that it will be useful,
8383+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8384+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8385+ * GNU General Public License for more details.
8386+ *
8387+ * You should have received a copy of the GNU General Public License
8388+ * along with this program; if not, write to the Free Software
8389+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8390+ */
1308ab2a 8391+
4a4d8108
AM
8392+/*
8393+ * file private data
8394+ */
1facf9fc 8395+
4a4d8108
AM
8396+#include <linux/file.h>
8397+#include "aufs.h"
1facf9fc 8398+
4a4d8108
AM
8399+void au_hfput(struct au_hfile *hf, struct file *file)
8400+{
8401+ /* todo: direct access f_flags */
8402+ if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC))
8403+ allow_write_access(hf->hf_file);
8404+ fput(hf->hf_file);
8405+ hf->hf_file = NULL;
8406+ atomic_dec_return(&hf->hf_br->br_count);
8407+ hf->hf_br = NULL;
8408+}
1facf9fc 8409+
4a4d8108
AM
8410+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
8411+{
8412+ struct au_finfo *finfo = au_fi(file);
8413+ struct au_hfile *hf;
8414+ struct au_fidir *fidir;
8415+
8416+ fidir = finfo->fi_hdir;
8417+ if (!fidir) {
8418+ AuDebugOn(finfo->fi_btop != bindex);
8419+ hf = &finfo->fi_htop;
8420+ } else
8421+ hf = fidir->fd_hfile + bindex;
8422+
8423+ if (hf && hf->hf_file)
8424+ au_hfput(hf, file);
8425+ if (val) {
8426+ FiMustWriteLock(file);
8427+ hf->hf_file = val;
8428+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 8429+ }
4a4d8108 8430+}
1facf9fc 8431+
4a4d8108
AM
8432+void au_update_figen(struct file *file)
8433+{
8434+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
8435+ /* smp_mb(); */ /* atomic_set */
1facf9fc 8436+}
8437+
4a4d8108
AM
8438+/* ---------------------------------------------------------------------- */
8439+
8440+void au_fi_mmap_lock(struct file *file)
1facf9fc 8441+{
4a4d8108
AM
8442+ FiMustWriteLock(file);
8443+ lockdep_off();
8444+ mutex_lock(&au_fi(file)->fi_mmap);
8445+ lockdep_on();
8446+}
1facf9fc 8447+
4a4d8108
AM
8448+void au_fi_mmap_unlock(struct file *file)
8449+{
8450+ lockdep_off();
8451+ mutex_unlock(&au_fi(file)->fi_mmap);
8452+ lockdep_on();
8453+}
1308ab2a 8454+
4a4d8108 8455+/* ---------------------------------------------------------------------- */
1308ab2a 8456+
4a4d8108
AM
8457+struct au_fidir *au_fidir_alloc(struct super_block *sb)
8458+{
8459+ struct au_fidir *fidir;
8460+ int nbr;
8461+
8462+ nbr = au_sbend(sb) + 1;
8463+ if (nbr < 2)
8464+ nbr = 2; /* initial allocate for 2 branches */
8465+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
8466+ if (fidir) {
8467+ fidir->fd_bbot = -1;
8468+ fidir->fd_nent = nbr;
8469+ fidir->fd_vdir_cache = NULL;
8470+ }
8471+
8472+ return fidir;
8473+}
8474+
8475+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
8476+{
8477+ int err;
8478+ struct au_fidir *fidir, *p;
8479+
8480+ AuRwMustWriteLock(&finfo->fi_rwsem);
8481+ fidir = finfo->fi_hdir;
8482+ AuDebugOn(!fidir);
8483+
8484+ err = -ENOMEM;
8485+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
8486+ GFP_NOFS);
8487+ if (p) {
8488+ p->fd_nent = nbr;
8489+ finfo->fi_hdir = p;
8490+ err = 0;
8491+ }
1facf9fc 8492+
dece6358 8493+ return err;
1facf9fc 8494+}
1308ab2a 8495+
8496+/* ---------------------------------------------------------------------- */
8497+
4a4d8108 8498+void au_finfo_fin(struct file *file)
1308ab2a 8499+{
4a4d8108
AM
8500+ struct au_finfo *finfo;
8501+
8502+ finfo = au_fi(file);
8503+ AuDebugOn(finfo->fi_hdir);
8504+ AuRwDestroy(&finfo->fi_rwsem);
8505+ au_cache_free_finfo(finfo);
1308ab2a 8506+}
1308ab2a 8507+
4a4d8108
AM
8508+void au_fi_init_once(void *_fi)
8509+{
8510+ struct au_finfo *fi = _fi;
1308ab2a 8511+
4a4d8108
AM
8512+ au_rw_init(&fi->fi_rwsem);
8513+ mutex_init(&fi->fi_vm_mtx);
8514+ mutex_init(&fi->fi_mmap);
8515+}
1308ab2a 8516+
4a4d8108
AM
8517+int au_finfo_init(struct file *file, struct au_fidir *fidir)
8518+{
8519+ int err;
8520+ struct au_finfo *finfo;
8521+ struct dentry *dentry;
8522+
8523+ err = -ENOMEM;
8524+ dentry = file->f_dentry;
8525+ finfo = au_cache_alloc_finfo();
8526+ if (unlikely(!finfo))
8527+ goto out;
8528+
8529+ err = 0;
8530+ au_rw_write_lock(&finfo->fi_rwsem);
8531+ finfo->fi_btop = -1;
8532+ finfo->fi_hdir = fidir;
8533+ atomic_set(&finfo->fi_generation, au_digen(dentry));
8534+ /* smp_mb(); */ /* atomic_set */
8535+
8536+ file->private_data = finfo;
8537+
8538+out:
8539+ return err;
8540+}
8541diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/f_op.c linux-2.6.34/fs/aufs/f_op.c
8542--- linux-2.6.34.org/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
8543+++ linux-2.6.34/fs/aufs/f_op.c 2010-05-31 22:15:32.000000000 +0200
8544@@ -0,0 +1,884 @@
dece6358 8545+/*
4a4d8108 8546+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
8547+ *
8548+ * This program, aufs is free software; you can redistribute it and/or modify
8549+ * it under the terms of the GNU General Public License as published by
8550+ * the Free Software Foundation; either version 2 of the License, or
8551+ * (at your option) any later version.
8552+ *
8553+ * This program is distributed in the hope that it will be useful,
8554+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8555+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8556+ * GNU General Public License for more details.
8557+ *
8558+ * You should have received a copy of the GNU General Public License
8559+ * along with this program; if not, write to the Free Software
8560+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8561+ */
1facf9fc 8562+
8563+/*
4a4d8108 8564+ * file and vm operations
1facf9fc 8565+ */
dece6358
AM
8566+
8567+#include <linux/file.h>
4a4d8108
AM
8568+#include <linux/fs_stack.h>
8569+#include <linux/mman.h>
8570+#include <linux/mm.h>
8571+#include <linux/security.h>
dece6358
AM
8572+#include "aufs.h"
8573+
4a4d8108 8574+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 8575+{
4a4d8108
AM
8576+ int err;
8577+ aufs_bindex_t bindex;
8578+ struct file *h_file;
8579+ struct dentry *dentry;
8580+ struct au_finfo *finfo;
8581+
8582+ FiMustWriteLock(file);
8583+
8584+ err = 0;
8585+ dentry = file->f_dentry;
8586+ finfo = au_fi(file);
8587+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
8588+ finfo->fi_hvmop = NULL;
8589+ bindex = au_dbstart(dentry);
8590+ h_file = au_h_open(dentry, bindex, flags, file);
8591+ if (IS_ERR(h_file))
8592+ err = PTR_ERR(h_file);
8593+ else {
8594+ au_set_fbstart(file, bindex);
8595+ au_set_h_fptr(file, bindex, h_file);
8596+ au_update_figen(file);
8597+ /* todo: necessary? */
8598+ /* file->f_ra = h_file->f_ra; */
8599+ }
8600+ return err;
1facf9fc 8601+}
8602+
4a4d8108
AM
8603+static int aufs_open_nondir(struct inode *inode __maybe_unused,
8604+ struct file *file)
1facf9fc 8605+{
4a4d8108 8606+ int err;
1308ab2a 8607+ struct super_block *sb;
1facf9fc 8608+
4a4d8108
AM
8609+ AuDbg("%.*s, f_ flags 0x%x, f_mode 0x%x\n",
8610+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
8611+ file->f_mode);
1facf9fc 8612+
4a4d8108
AM
8613+ sb = file->f_dentry->d_sb;
8614+ si_read_lock(sb, AuLock_FLUSH);
8615+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
8616+ si_read_unlock(sb);
8617+ return err;
8618+}
1facf9fc 8619+
4a4d8108
AM
8620+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
8621+{
8622+ struct au_finfo *finfo;
8623+ aufs_bindex_t bindex;
1facf9fc 8624+
4a4d8108
AM
8625+ finfo = au_fi(file);
8626+ bindex = finfo->fi_btop;
8627+ if (bindex >= 0)
8628+ au_set_h_fptr(file, bindex, NULL);
dece6358 8629+
4a4d8108
AM
8630+ au_finfo_fin(file);
8631+ return 0;
1facf9fc 8632+}
8633+
4a4d8108
AM
8634+/* ---------------------------------------------------------------------- */
8635+
8636+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 8637+{
1308ab2a 8638+ int err;
4a4d8108
AM
8639+ struct file *h_file;
8640+
8641+ err = 0;
8642+ h_file = au_hf_top(file);
8643+ if (h_file)
8644+ err = vfsub_flush(h_file, id);
8645+ return err;
8646+}
8647+
8648+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
8649+{
8650+ return au_do_flush(file, id, au_do_flush_nondir);
8651+}
8652+
8653+/* ---------------------------------------------------------------------- */
8654+
8655+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
8656+ loff_t *ppos)
8657+{
8658+ ssize_t err;
dece6358 8659+ struct dentry *dentry;
4a4d8108 8660+ struct file *h_file;
dece6358 8661+ struct super_block *sb;
1facf9fc 8662+
dece6358
AM
8663+ dentry = file->f_dentry;
8664+ sb = dentry->d_sb;
8665+ si_read_lock(sb, AuLock_FLUSH);
4a4d8108 8666+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
8667+ if (unlikely(err))
8668+ goto out;
1facf9fc 8669+
4a4d8108
AM
8670+ h_file = au_hf_top(file);
8671+ err = vfsub_read_u(h_file, buf, count, ppos);
8672+ /* todo: necessary? */
8673+ /* file->f_ra = h_file->f_ra; */
8674+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1308ab2a 8675+
4a4d8108
AM
8676+ di_read_unlock(dentry, AuLock_IR);
8677+ fi_read_unlock(file);
dece6358
AM
8678+ out:
8679+ si_read_unlock(sb);
8680+ return err;
8681+}
1facf9fc 8682+
4a4d8108
AM
8683+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
8684+ size_t count, loff_t *ppos)
dece6358 8685+{
4a4d8108
AM
8686+ ssize_t err;
8687+ struct au_pin pin;
dece6358 8688+ struct dentry *dentry;
4a4d8108
AM
8689+ struct inode *inode;
8690+ struct super_block *sb;
8691+ struct file *h_file;
8692+ char __user *buf = (char __user *)ubuf;
1facf9fc 8693+
dece6358 8694+ dentry = file->f_dentry;
4a4d8108
AM
8695+ sb = dentry->d_sb;
8696+ inode = dentry->d_inode;
8697+ mutex_lock(&inode->i_mutex);
8698+ si_read_lock(sb, AuLock_FLUSH);
1facf9fc 8699+
4a4d8108
AM
8700+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
8701+ if (unlikely(err))
8702+ goto out;
1facf9fc 8703+
4a4d8108
AM
8704+ err = au_ready_to_write(file, -1, &pin);
8705+ di_downgrade_lock(dentry, AuLock_IR);
8706+ if (unlikely(err))
8707+ goto out_unlock;
1facf9fc 8708+
4a4d8108
AM
8709+ h_file = au_hf_top(file);
8710+ au_unpin(&pin);
8711+ err = vfsub_write_u(h_file, buf, count, ppos);
8712+ au_cpup_attr_timesizes(inode);
8713+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 8714+
4a4d8108
AM
8715+ out_unlock:
8716+ di_read_unlock(dentry, AuLock_IR);
8717+ fi_write_unlock(file);
dece6358 8718+ out:
4a4d8108
AM
8719+ si_read_unlock(sb);
8720+ mutex_unlock(&inode->i_mutex);
dece6358
AM
8721+ return err;
8722+}
1facf9fc 8723+
4a4d8108
AM
8724+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
8725+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 8726+{
4a4d8108
AM
8727+ ssize_t err;
8728+ struct file *file;
8729+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
8730+ loff_t);
1facf9fc 8731+
4a4d8108
AM
8732+ err = security_file_permission(h_file, rw);
8733+ if (unlikely(err))
8734+ goto out;
1facf9fc 8735+
4a4d8108
AM
8736+ err = -ENOSYS;
8737+ func = NULL;
8738+ if (rw == MAY_READ)
8739+ func = h_file->f_op->aio_read;
8740+ else if (rw == MAY_WRITE)
8741+ func = h_file->f_op->aio_write;
8742+ if (func) {
8743+ file = kio->ki_filp;
8744+ kio->ki_filp = h_file;
8745+ err = func(kio, iov, nv, pos);
8746+ kio->ki_filp = file;
8747+ } else
8748+ /* currently there is no such fs */
8749+ WARN_ON_ONCE(1);
1facf9fc 8750+
4a4d8108 8751+ out:
dece6358
AM
8752+ return err;
8753+}
1facf9fc 8754+
4a4d8108
AM
8755+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
8756+ unsigned long nv, loff_t pos)
1facf9fc 8757+{
4a4d8108
AM
8758+ ssize_t err;
8759+ struct file *file, *h_file;
8760+ struct dentry *dentry;
dece6358 8761+ struct super_block *sb;
1facf9fc 8762+
4a4d8108 8763+ file = kio->ki_filp;
dece6358 8764+ dentry = file->f_dentry;
1308ab2a 8765+ sb = dentry->d_sb;
4a4d8108
AM
8766+ si_read_lock(sb, AuLock_FLUSH);
8767+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
8768+ if (unlikely(err))
8769+ goto out;
8770+
8771+ h_file = au_hf_top(file);
8772+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
8773+ /* todo: necessary? */
8774+ /* file->f_ra = h_file->f_ra; */
8775+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
8776+ di_read_unlock(dentry, AuLock_IR);
8777+ fi_read_unlock(file);
1facf9fc 8778+
4a4d8108
AM
8779+ out:
8780+ si_read_unlock(sb);
1308ab2a 8781+ return err;
8782+}
1facf9fc 8783+
4a4d8108
AM
8784+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
8785+ unsigned long nv, loff_t pos)
1308ab2a 8786+{
4a4d8108
AM
8787+ ssize_t err;
8788+ struct au_pin pin;
8789+ struct dentry *dentry;
8790+ struct inode *inode;
1308ab2a 8791+ struct super_block *sb;
4a4d8108 8792+ struct file *file, *h_file;
1308ab2a 8793+
4a4d8108 8794+ file = kio->ki_filp;
1308ab2a 8795+ dentry = file->f_dentry;
8796+ sb = dentry->d_sb;
1308ab2a 8797+ inode = dentry->d_inode;
4a4d8108
AM
8798+ mutex_lock(&inode->i_mutex);
8799+ si_read_lock(sb, AuLock_FLUSH);
8800+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
8801+ if (unlikely(err))
1308ab2a 8802+ goto out;
1facf9fc 8803+
4a4d8108
AM
8804+ err = au_ready_to_write(file, -1, &pin);
8805+ di_downgrade_lock(dentry, AuLock_IR);
dece6358 8806+ if (unlikely(err))
4a4d8108 8807+ goto out_unlock;
1facf9fc 8808+
4a4d8108
AM
8809+ au_unpin(&pin);
8810+ h_file = au_hf_top(file);
8811+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
8812+ au_cpup_attr_timesizes(inode);
8813+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 8814+
1308ab2a 8815+ out_unlock:
4a4d8108
AM
8816+ di_read_unlock(dentry, AuLock_IR);
8817+ fi_write_unlock(file);
dece6358 8818+ out:
4a4d8108
AM
8819+ si_read_unlock(sb);
8820+ mutex_unlock(&inode->i_mutex);
dece6358 8821+ return err;
1facf9fc 8822+}
8823+
4a4d8108
AM
8824+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
8825+ struct pipe_inode_info *pipe, size_t len,
8826+ unsigned int flags)
1facf9fc 8827+{
4a4d8108
AM
8828+ ssize_t err;
8829+ struct file *h_file;
8830+ struct dentry *dentry;
dece6358 8831+ struct super_block *sb;
1facf9fc 8832+
dece6358 8833+ dentry = file->f_dentry;
dece6358 8834+ sb = dentry->d_sb;
4a4d8108
AM
8835+ si_read_lock(sb, AuLock_FLUSH);
8836+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
8837+ if (unlikely(err))
dece6358 8838+ goto out;
1facf9fc 8839+
4a4d8108
AM
8840+ err = -EINVAL;
8841+ h_file = au_hf_top(file);
8842+ if (au_test_loopback_kthread()) {
8843+ file->f_mapping = h_file->f_mapping;
8844+ smp_mb(); /* unnecessary? */
1308ab2a 8845+ }
4a4d8108
AM
8846+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
8847+ /* todo: necessasry? */
8848+ /* file->f_ra = h_file->f_ra; */
8849+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 8850+
4a4d8108
AM
8851+ di_read_unlock(dentry, AuLock_IR);
8852+ fi_read_unlock(file);
1facf9fc 8853+
dece6358 8854+ out:
4a4d8108 8855+ si_read_unlock(sb);
dece6358 8856+ return err;
1facf9fc 8857+}
8858+
4a4d8108
AM
8859+static ssize_t
8860+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
8861+ size_t len, unsigned int flags)
1facf9fc 8862+{
4a4d8108
AM
8863+ ssize_t err;
8864+ struct au_pin pin;
8865+ struct dentry *dentry;
8866+ struct inode *inode;
1308ab2a 8867+ struct super_block *sb;
4a4d8108 8868+ struct file *h_file;
1facf9fc 8869+
4a4d8108
AM
8870+ dentry = file->f_dentry;
8871+ inode = dentry->d_inode;
8872+ mutex_lock(&inode->i_mutex);
8873+ sb = dentry->d_sb;
8874+ si_read_lock(sb, AuLock_FLUSH);
1facf9fc 8875+
4a4d8108
AM
8876+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
8877+ if (unlikely(err))
8878+ goto out;
1facf9fc 8879+
4a4d8108
AM
8880+ err = au_ready_to_write(file, -1, &pin);
8881+ di_downgrade_lock(dentry, AuLock_IR);
8882+ if (unlikely(err))
8883+ goto out_unlock;
1facf9fc 8884+
4a4d8108
AM
8885+ h_file = au_hf_top(file);
8886+ au_unpin(&pin);
8887+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
8888+ au_cpup_attr_timesizes(inode);
8889+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 8890+
4a4d8108
AM
8891+ out_unlock:
8892+ di_read_unlock(dentry, AuLock_IR);
8893+ fi_write_unlock(file);
8894+ out:
8895+ si_read_unlock(sb);
8896+ mutex_unlock(&inode->i_mutex);
8897+ return err;
8898+}
1facf9fc 8899+
4a4d8108
AM
8900+/* ---------------------------------------------------------------------- */
8901+
8902+static struct file *au_safe_file(struct vm_area_struct *vma)
8903+{
8904+ struct file *file;
8905+
8906+ file = vma->vm_file;
8907+ if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
8908+ return file;
8909+ return NULL;
1facf9fc 8910+}
8911+
4a4d8108 8912+static void au_reset_file(struct vm_area_struct *vma, struct file *file)
1facf9fc 8913+{
4a4d8108
AM
8914+ vma->vm_file = file;
8915+ /* smp_mb(); */ /* flush vm_file */
8916+}
1facf9fc 8917+
4a4d8108
AM
8918+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
8919+{
8920+ int err;
8921+ static DECLARE_WAIT_QUEUE_HEAD(wq);
8922+ struct file *file, *h_file;
8923+ struct au_finfo *finfo;
1facf9fc 8924+
4a4d8108
AM
8925+ /* todo: non-robr mode, user vm_file as it is? */
8926+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 8927+
4a4d8108
AM
8928+ /* do not revalidate, no si lock */
8929+ finfo = au_fi(file);
8930+ AuDebugOn(finfo->fi_hdir);
8931+ h_file = finfo->fi_htop.hf_file;
8932+ AuDebugOn(!h_file || !finfo->fi_hvmop);
8933+
8934+ mutex_lock(&finfo->fi_vm_mtx);
8935+ vma->vm_file = h_file;
8936+ err = finfo->fi_hvmop->fault(vma, vmf);
8937+ /* todo: necessary? */
8938+ /* file->f_ra = h_file->f_ra; */
8939+ au_reset_file(vma, file);
8940+ mutex_unlock(&finfo->fi_vm_mtx);
8941+#if 0 /* def CONFIG_SMP */
8942+ /* wake_up_nr(&wq, online_cpu - 1); */
8943+ wake_up_all(&wq);
8944+#else
8945+ wake_up(&wq);
8946+#endif
1facf9fc 8947+
dece6358 8948+ return err;
1facf9fc 8949+}
8950+
4a4d8108 8951+static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1facf9fc 8952+{
dece6358 8953+ int err;
4a4d8108
AM
8954+ static DECLARE_WAIT_QUEUE_HEAD(wq);
8955+ struct file *file, *h_file;
8956+ struct au_finfo *finfo;
1facf9fc 8957+
4a4d8108 8958+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 8959+
4a4d8108
AM
8960+ finfo = au_fi(file);
8961+ AuDebugOn(finfo->fi_hdir);
8962+ h_file = finfo->fi_htop.hf_file;
8963+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 8964+
4a4d8108
AM
8965+ mutex_lock(&finfo->fi_vm_mtx);
8966+ vma->vm_file = h_file;
8967+ err = finfo->fi_hvmop->page_mkwrite(vma, vmf);
8968+ au_reset_file(vma, file);
8969+ mutex_unlock(&finfo->fi_vm_mtx);
8970+ wake_up(&wq);
1308ab2a 8971+
dece6358 8972+ return err;
1facf9fc 8973+}
8974+
4a4d8108 8975+static void aufs_vm_close(struct vm_area_struct *vma)
1facf9fc 8976+{
4a4d8108
AM
8977+ static DECLARE_WAIT_QUEUE_HEAD(wq);
8978+ struct file *file, *h_file;
8979+ struct au_finfo *finfo;
dece6358 8980+
4a4d8108 8981+ wait_event(wq, (file = au_safe_file(vma)));
dece6358 8982+
4a4d8108
AM
8983+ finfo = au_fi(file);
8984+ AuDebugOn(finfo->fi_hdir);
8985+ h_file = finfo->fi_htop.hf_file;
8986+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 8987+
4a4d8108
AM
8988+ mutex_lock(&finfo->fi_vm_mtx);
8989+ vma->vm_file = h_file;
8990+ finfo->fi_hvmop->close(vma);
8991+ au_reset_file(vma, file);
8992+ mutex_unlock(&finfo->fi_vm_mtx);
8993+ wake_up(&wq);
8994+}
1facf9fc 8995+
4a4d8108
AM
8996+const struct vm_operations_struct aufs_vm_ops = {
8997+ .close = aufs_vm_close,
8998+ .fault = aufs_fault,
8999+ .page_mkwrite = aufs_page_mkwrite
1308ab2a 9000+};
dece6358 9001+
1308ab2a 9002+/* ---------------------------------------------------------------------- */
1facf9fc 9003+
4a4d8108
AM
9004+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
9005+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
1308ab2a 9006+
4a4d8108 9007+static unsigned long au_arch_prot_conv(unsigned long flags)
dece6358 9008+{
4a4d8108
AM
9009+ /* currently ppc64 only */
9010+#ifdef CONFIG_PPC64
9011+ /* cf. linux/arch/powerpc/include/asm/mman.h */
9012+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
9013+ return AuConv_VM_PROT(flags, SAO);
9014+#else
9015+ AuDebugOn(arch_calc_vm_prot_bits(-1));
9016+ return 0;
9017+#endif
dece6358
AM
9018+}
9019+
4a4d8108 9020+static unsigned long au_prot_conv(unsigned long flags)
dece6358 9021+{
4a4d8108
AM
9022+ return AuConv_VM_PROT(flags, READ)
9023+ | AuConv_VM_PROT(flags, WRITE)
9024+ | AuConv_VM_PROT(flags, EXEC)
9025+ | au_arch_prot_conv(flags);
dece6358
AM
9026+}
9027+
4a4d8108
AM
9028+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
9029+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
dece6358 9030+
4a4d8108 9031+static unsigned long au_flag_conv(unsigned long flags)
dece6358 9032+{
4a4d8108
AM
9033+ return AuConv_VM_MAP(flags, GROWSDOWN)
9034+ | AuConv_VM_MAP(flags, DENYWRITE)
9035+ | AuConv_VM_MAP(flags, EXECUTABLE)
9036+ | AuConv_VM_MAP(flags, LOCKED);
dece6358
AM
9037+}
9038+
4a4d8108
AM
9039+static struct vm_operations_struct *
9040+au_hvmop(struct file *h_file, struct vm_area_struct *vma, unsigned long *flags)
dece6358 9041+{
4a4d8108
AM
9042+ struct vm_operations_struct *h_vmop;
9043+ unsigned long prot;
9044+ int err;
dece6358 9045+
4a4d8108
AM
9046+ h_vmop = ERR_PTR(-ENODEV);
9047+ if (!h_file->f_op || !h_file->f_op->mmap)
9048+ goto out;
dece6358 9049+
4a4d8108
AM
9050+ prot = au_prot_conv(vma->vm_flags);
9051+ err = security_file_mmap(h_file, /*reqprot*/prot, prot,
9052+ au_flag_conv(vma->vm_flags), vma->vm_start, 0);
9053+ h_vmop = ERR_PTR(err);
9054+ if (unlikely(err))
9055+ goto out;
dece6358 9056+
4a4d8108
AM
9057+ err = h_file->f_op->mmap(h_file, vma);
9058+ h_vmop = ERR_PTR(err);
9059+ if (unlikely(err))
9060+ goto out;
dece6358 9061+
4a4d8108
AM
9062+ /* oops, it became 'const' */
9063+ h_vmop = (struct vm_operations_struct *)vma->vm_ops;
9064+ *flags = vma->vm_flags;
9065+ err = do_munmap(current->mm, vma->vm_start,
9066+ vma->vm_end - vma->vm_start);
9067+ if (unlikely(err)) {
9068+ AuIOErr("failed internal unmapping %.*s, %d\n",
9069+ AuDLNPair(h_file->f_dentry), err);
9070+ h_vmop = ERR_PTR(-EIO);
9071+ }
dece6358 9072+
4a4d8108
AM
9073+ out:
9074+ return h_vmop;
dece6358
AM
9075+}
9076+
1308ab2a 9077+/*
4a4d8108
AM
9078+ * This is another ugly approach to keep the lock order, particularly
9079+ * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
9080+ * find it in git-log, if you want.
1308ab2a 9081+ *
4a4d8108
AM
9082+ * native readdir: i_mutex, copy_to_user, mmap_sem
9083+ * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
1308ab2a 9084+ *
4a4d8108
AM
9085+ * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
9086+ * acquire aufs rwsem. It introduces a circular locking dependency.
9087+ * To address this problem, aufs_mmap() delegates the part which requires aufs
9088+ * rwsem to its internal workqueue.
1308ab2a 9089+ */
9090+
4a4d8108
AM
9091+/* very ugly approach */
9092+#include "mtx.h"
1308ab2a 9093+
4a4d8108
AM
9094+struct au_mmap_pre_args {
9095+ /* input */
9096+ struct file *file;
9097+ struct vm_area_struct *vma;
1308ab2a 9098+
4a4d8108
AM
9099+ /* output */
9100+ int *errp;
9101+ struct file *h_file;
9102+ struct au_branch *br;
9103+ int mmapped;
9104+};
dece6358 9105+
4a4d8108
AM
9106+static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
9107+ struct file **h_file, struct au_branch **br,
9108+ int *mmapped)
dece6358 9109+{
4a4d8108
AM
9110+ int err;
9111+ aufs_bindex_t bstart;
9112+ const unsigned char wlock
9113+ = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
9114+ struct dentry *dentry;
9115+ struct super_block *sb;
1308ab2a 9116+
4a4d8108
AM
9117+ dentry = file->f_dentry;
9118+ sb = dentry->d_sb;
9119+ si_read_lock(sb, !AuLock_FLUSH);
9120+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9121+ if (unlikely(err))
9122+ goto out;
9123+
9124+ *mmapped = !!au_test_mmapped(file);
9125+ if (wlock) {
9126+ struct au_pin pin;
9127+
9128+ err = au_ready_to_write(file, -1, &pin);
9129+ di_write_unlock(dentry);
9130+ if (unlikely(err))
9131+ goto out_unlock;
9132+ au_unpin(&pin);
9133+ } else
9134+ di_write_unlock(dentry);
9135+ bstart = au_fbstart(file);
9136+ *br = au_sbr(sb, bstart);
9137+ *h_file = au_hf_top(file);
9138+ get_file(*h_file);
9139+ au_fi_mmap_lock(file);
9140+
9141+out_unlock:
9142+ fi_write_unlock(file);
9143+out:
9144+ si_read_unlock(sb);
9145+ return err;
dece6358
AM
9146+}
9147+
4a4d8108 9148+static void au_call_mmap_pre(void *args)
dece6358 9149+{
4a4d8108
AM
9150+ struct au_mmap_pre_args *a = args;
9151+ *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->br,
9152+ &a->mmapped);
dece6358
AM
9153+}
9154+
4a4d8108 9155+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 9156+{
4a4d8108
AM
9157+ int err, wkq_err;
9158+ unsigned long h_vmflags;
1308ab2a 9159+ struct au_finfo *finfo;
4a4d8108
AM
9160+ struct dentry *h_dentry;
9161+ struct vm_operations_struct *h_vmop, *vmop;
9162+ struct au_mmap_pre_args args = {
9163+ .file = file,
9164+ .vma = vma,
9165+ .errp = &err
9166+ };
9167+
9168+ wkq_err = au_wkq_wait(au_call_mmap_pre, &args);
9169+ if (unlikely(wkq_err))
9170+ err = wkq_err;
9171+ if (unlikely(err))
9172+ goto out;
9173+ finfo = au_fi(file);
9174+ mutex_set_owner(&finfo->fi_mmap);
9175+
9176+ h_dentry = args.h_file->f_dentry;
9177+ if (!args.mmapped && au_test_fs_bad_mapping(h_dentry->d_sb)) {
1308ab2a 9178+ /*
4a4d8108
AM
9179+ * by this assignment, f_mapping will differs from aufs inode
9180+ * i_mapping.
9181+ * if someone else mixes the use of f_dentry->d_inode and
9182+ * f_mapping->host, then a problem may arise.
1308ab2a 9183+ */
4a4d8108
AM
9184+ file->f_mapping = args.h_file->f_mapping;
9185+ }
1308ab2a 9186+
4a4d8108
AM
9187+ /* always try this internal mmap to get vma flags */
9188+ h_vmflags = 0; /* gcc warning */
9189+ h_vmop = au_hvmop(args.h_file, vma, &h_vmflags);
9190+ err = PTR_ERR(h_vmop);
9191+ if (IS_ERR(h_vmop))
9192+ goto out_unlock;
9193+ AuDebugOn(args.mmapped && h_vmop != finfo->fi_hvmop);
9194+
9195+ vmop = (void *)au_dy_vmop(file, args.br, h_vmop);
9196+ err = PTR_ERR(vmop);
9197+ if (IS_ERR(vmop))
9198+ goto out_unlock;
9199+
9200+ /*
9201+ * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
9202+ * currently MAP_DENYWRITE from userspace is ignored, but elf loader
9203+ * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
9204+ * both of the aufs file and the lower file is deny_write_access()-ed.
9205+ * finally I hope we can skip handlling MAP_DENYWRITE here.
9206+ */
9207+ err = generic_file_mmap(file, vma);
9208+ if (unlikely(err))
9209+ goto out_unlock;
9210+
9211+ vma->vm_ops = vmop;
9212+ vma->vm_flags = h_vmflags;
9213+ if (!args.mmapped)
9214+ finfo->fi_hvmop = h_vmop;
9215+
9216+ vfsub_file_accessed(args.h_file);
9217+ /* update without lock, I don't think it a problem */
9218+ fsstack_copy_attr_atime(file->f_dentry->d_inode, h_dentry->d_inode);
9219+
9220+ out_unlock:
9221+ au_fi_mmap_unlock(file);
9222+ fput(args.h_file);
9223+ out:
9224+ return err;
9225+}
9226+
9227+/* ---------------------------------------------------------------------- */
9228+
9229+static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
9230+ int datasync)
9231+{
9232+ int err;
9233+ struct au_pin pin;
9234+ struct inode *inode;
9235+ struct file *h_file;
9236+ struct super_block *sb;
9237+
9238+ inode = dentry->d_inode;
9239+ IMustLock(file->f_mapping->host);
9240+ if (inode != file->f_mapping->host) {
9241+ mutex_unlock(&file->f_mapping->host->i_mutex);
9242+ mutex_lock(&inode->i_mutex);
9243+ }
9244+ IMustLock(inode);
9245+
9246+ sb = dentry->d_sb;
9247+ si_read_lock(sb, AuLock_FLUSH);
9248+
9249+ err = 0; /* -EBADF; */ /* posix? */
9250+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
9251+ goto out;
9252+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9253+ if (unlikely(err))
9254+ goto out;
9255+
9256+ err = au_ready_to_write(file, -1, &pin);
9257+ di_downgrade_lock(dentry, AuLock_IR);
9258+ if (unlikely(err))
9259+ goto out_unlock;
9260+ au_unpin(&pin);
9261+
9262+ err = -EINVAL;
9263+ h_file = au_hf_top(file);
9264+ if (h_file->f_op && h_file->f_op->fsync) {
9265+ struct dentry *h_d;
9266+ struct mutex *h_mtx;
9267+
9268+ /*
9269+ * no filemap_fdatawrite() since aufs file has no its own
9270+ * mapping, but dir.
9271+ */
9272+ h_d = h_file->f_dentry;
9273+ h_mtx = &h_d->d_inode->i_mutex;
9274+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
9275+ err = h_file->f_op->fsync(h_file, h_d, datasync);
9276+ if (!err)
9277+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9278+ /*ignore*/
9279+ au_cpup_attr_timesizes(inode);
9280+ mutex_unlock(h_mtx);
9281+ }
9282+
9283+ out_unlock:
9284+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 9285+ fi_write_unlock(file);
4a4d8108
AM
9286+ out:
9287+ si_read_unlock(sb);
9288+ if (inode != file->f_mapping->host) {
9289+ mutex_unlock(&inode->i_mutex);
9290+ mutex_lock(&file->f_mapping->host->i_mutex);
9291+ }
9292+ return err;
dece6358
AM
9293+}
9294+
4a4d8108
AM
9295+/* no one supports this operation, currently */
9296+#if 0
9297+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 9298+{
4a4d8108
AM
9299+ int err;
9300+ struct au_pin pin;
1308ab2a 9301+ struct dentry *dentry;
4a4d8108
AM
9302+ struct inode *inode;
9303+ struct file *file, *h_file;
9304+ struct super_block *sb;
1308ab2a 9305+
4a4d8108 9306+ file = kio->ki_filp;
1308ab2a 9307+ dentry = file->f_dentry;
4a4d8108
AM
9308+ inode = dentry->d_inode;
9309+ mutex_lock(&inode->i_mutex);
9310+
9311+ sb = dentry->d_sb;
9312+ si_read_lock(sb, AuLock_FLUSH);
9313+
9314+ err = 0; /* -EBADF; */ /* posix? */
9315+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
9316+ goto out;
9317+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9318+ if (unlikely(err))
1308ab2a 9319+ goto out;
9320+
4a4d8108
AM
9321+ err = au_ready_to_write(file, -1, &pin);
9322+ di_downgrade_lock(dentry, AuLock_IR);
9323+ if (unlikely(err))
9324+ goto out_unlock;
9325+ au_unpin(&pin);
1308ab2a 9326+
4a4d8108
AM
9327+ err = -ENOSYS;
9328+ h_file = au_hf_top(file);
9329+ if (h_file->f_op && h_file->f_op->aio_fsync) {
9330+ struct dentry *h_d;
9331+ struct mutex *h_mtx;
1308ab2a 9332+
4a4d8108
AM
9333+ h_d = h_file->f_dentry;
9334+ h_mtx = &h_d->d_inode->i_mutex;
9335+ if (!is_sync_kiocb(kio)) {
9336+ get_file(h_file);
9337+ fput(file);
9338+ }
9339+ kio->ki_filp = h_file;
9340+ err = h_file->f_op->aio_fsync(kio, datasync);
9341+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
9342+ if (!err)
9343+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9344+ /*ignore*/
9345+ au_cpup_attr_timesizes(inode);
9346+ mutex_unlock(h_mtx);
9347+ }
1308ab2a 9348+
4a4d8108
AM
9349+ out_unlock:
9350+ di_read_unlock(dentry, AuLock_IR);
9351+ fi_write_unlock(file);
1308ab2a 9352+ out:
4a4d8108
AM
9353+ si_read_unlock(sb);
9354+ mutex_unlock(&inode->i_mutex);
9355+ return err;
dece6358 9356+}
4a4d8108 9357+#endif
dece6358 9358+
4a4d8108 9359+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 9360+{
4a4d8108
AM
9361+ int err;
9362+ struct file *h_file;
9363+ struct dentry *dentry;
9364+ struct super_block *sb;
1308ab2a 9365+
4a4d8108
AM
9366+ dentry = file->f_dentry;
9367+ sb = dentry->d_sb;
9368+ si_read_lock(sb, AuLock_FLUSH);
9369+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9370+ if (unlikely(err))
9371+ goto out;
9372+
9373+ h_file = au_hf_top(file);
9374+ if (h_file->f_op && h_file->f_op->fasync)
9375+ err = h_file->f_op->fasync(fd, h_file, flag);
9376+
9377+ di_read_unlock(dentry, AuLock_IR);
9378+ fi_read_unlock(file);
1308ab2a 9379+
4a4d8108
AM
9380+ out:
9381+ si_read_unlock(sb);
1308ab2a 9382+ return err;
dece6358 9383+}
4a4d8108
AM
9384+
9385+/* ---------------------------------------------------------------------- */
9386+
9387+/* no one supports this operation, currently */
9388+#if 0
9389+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
9390+ size_t len, loff_t *pos , int more)
9391+{
9392+}
9393+#endif
9394+
9395+/* ---------------------------------------------------------------------- */
9396+
9397+const struct file_operations aufs_file_fop = {
9398+ .owner = THIS_MODULE,
9399+ /*
9400+ * while generic_file_llseek/_unlocked() don't use BKL,
9401+ * don't use it since it operates file->f_mapping->host.
9402+ * in aufs, it may be a real file and may confuse users by UDBA.
9403+ */
9404+ /* .llseek = generic_file_llseek, */
9405+
9406+ .read = aufs_read,
9407+ .write = aufs_write,
9408+ .aio_read = aufs_aio_read,
9409+ .aio_write = aufs_aio_write,
9410+#ifdef CONFIG_AUFS_POLL
9411+ .poll = aufs_poll,
9412+#endif
9413+ .unlocked_ioctl = aufs_ioctl_nondir,
9414+ .mmap = aufs_mmap,
9415+ .open = aufs_open_nondir,
9416+ .flush = aufs_flush_nondir,
9417+ .release = aufs_release_nondir,
9418+ .fsync = aufs_fsync_nondir,
9419+ /* .aio_fsync = aufs_aio_fsync_nondir, */
9420+ .fasync = aufs_fasync,
9421+ /* .sendpage = aufs_sendpage, */
9422+ .splice_write = aufs_splice_write,
9423+ .splice_read = aufs_splice_read,
9424+#if 0
9425+ .aio_splice_write = aufs_aio_splice_write,
9426+ .aio_splice_read = aufs_aio_splice_read
9427+#endif
9428+};
9429diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/f_op_sp.c linux-2.6.34/fs/aufs/f_op_sp.c
9430--- linux-2.6.34.org/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
9431+++ linux-2.6.34/fs/aufs/f_op_sp.c 2010-05-31 22:15:32.000000000 +0200
9432@@ -0,0 +1,299 @@
1308ab2a 9433+/*
4a4d8108 9434+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 9435+ *
9436+ * This program, aufs is free software; you can redistribute it and/or modify
9437+ * it under the terms of the GNU General Public License as published by
9438+ * the Free Software Foundation; either version 2 of the License, or
9439+ * (at your option) any later version.
9440+ *
9441+ * This program is distributed in the hope that it will be useful,
9442+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9443+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9444+ * GNU General Public License for more details.
9445+ *
9446+ * You should have received a copy of the GNU General Public License
9447+ * along with this program; if not, write to the Free Software
9448+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9449+ */
dece6358 9450+
1308ab2a 9451+/*
4a4d8108
AM
9452+ * file operations for special files.
9453+ * while they exist in aufs virtually,
9454+ * their file I/O is handled out of aufs.
1308ab2a 9455+ */
9456+
4a4d8108
AM
9457+#include <linux/fs_stack.h>
9458+#include "aufs.h"
1308ab2a 9459+
4a4d8108
AM
9460+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
9461+ unsigned long nv, loff_t pos)
dece6358 9462+{
4a4d8108
AM
9463+ ssize_t err;
9464+ aufs_bindex_t bstart;
9465+ unsigned char wbr;
9466+ struct file *file, *h_file;
9467+ struct super_block *sb;
1308ab2a 9468+
4a4d8108
AM
9469+ file = kio->ki_filp;
9470+ sb = file->f_dentry->d_sb;
9471+ si_read_lock(sb, AuLock_FLUSH);
9472+ fi_read_lock(file);
9473+ bstart = au_fbstart(file);
9474+ h_file = au_hf_top(file);
9475+ fi_read_unlock(file);
9476+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9477+ si_read_unlock(sb);
9478+
9479+ /* do not change the file in kio */
9480+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
9481+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
9482+ if (err > 0 && wbr)
9483+ file_accessed(h_file);
9484+
9485+ return err;
9486+}
9487+
9488+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
9489+ unsigned long nv, loff_t pos)
9490+{
9491+ ssize_t err;
9492+ aufs_bindex_t bstart;
9493+ unsigned char wbr;
9494+ struct super_block *sb;
9495+ struct file *file, *h_file;
9496+
9497+ file = kio->ki_filp;
9498+ sb = file->f_dentry->d_sb;
9499+ si_read_lock(sb, AuLock_FLUSH);
9500+ fi_read_lock(file);
9501+ bstart = au_fbstart(file);
9502+ h_file = au_hf_top(file);
9503+ fi_read_unlock(file);
9504+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9505+ si_read_unlock(sb);
9506+
9507+ /* do not change the file in kio */
9508+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
9509+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
9510+ if (err > 0 && wbr)
9511+ file_update_time(h_file);
9512+
9513+ return err;
9514+}
9515+
9516+/* ---------------------------------------------------------------------- */
9517+
9518+static int aufs_release_sp(struct inode *inode, struct file *file)
9519+{
9520+ int err;
9521+ struct file *h_file;
9522+
9523+ fi_read_lock(file);
9524+ h_file = au_hf_top(file);
9525+ fi_read_unlock(file);
9526+ /* close this fifo in aufs */
9527+ err = h_file->f_op->release(inode, file); /* ignore */
9528+ aufs_release_nondir(inode, file); /* ignore */
9529+ return err;
9530+}
9531+
9532+/* ---------------------------------------------------------------------- */
9533+
9534+/* currently, support only FIFO */
9535+enum {AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
9536+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
9537+ AuSp_Last};
9538+static int aufs_open_sp(struct inode *inode, struct file *file);
9539+static struct au_sp_fop {
9540+ int done;
9541+ struct file_operations fop; /* not 'const' */
9542+ spinlock_t spin;
9543+} au_sp_fop[AuSp_Last] = {
9544+ [AuSp_FIFO] = {
9545+ .fop = {
9546+ .owner = THIS_MODULE,
9547+ .open = aufs_open_sp
9548+ }
9549+ }
9550+};
9551+
9552+static void au_init_fop_sp(struct file *file)
9553+{
9554+ struct au_sp_fop *p;
9555+ int i;
9556+ struct file *h_file;
9557+
9558+ p = au_sp_fop;
9559+ if (unlikely(!p->done)) {
9560+ /* initialize first time only */
9561+ static DEFINE_SPINLOCK(spin);
9562+
9563+ spin_lock(&spin);
9564+ if (!p->done) {
9565+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
9566+ != AuSp_Last);
9567+ for (i = 0; i < AuSp_Last; i++)
9568+ spin_lock_init(&p[i].spin);
9569+ p->done = 1;
9570+ }
9571+ spin_unlock(&spin);
9572+ }
9573+
9574+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
9575+ case FMODE_READ:
9576+ i = AuSp_FIFO_R;
9577+ break;
9578+ case FMODE_WRITE:
9579+ i = AuSp_FIFO_W;
9580+ break;
9581+ case FMODE_READ | FMODE_WRITE:
9582+ i = AuSp_FIFO_RW;
9583+ break;
9584+ default:
9585+ BUG();
9586+ }
9587+
9588+ p += i;
9589+ if (unlikely(!p->done)) {
9590+ /* initialize first time only */
9591+ h_file = au_hf_top(file);
9592+ spin_lock(&p->spin);
9593+ if (!p->done) {
9594+ p->fop = *h_file->f_op;
9595+ p->fop.owner = THIS_MODULE;
9596+ if (p->fop.aio_read)
9597+ p->fop.aio_read = aufs_aio_read_sp;
9598+ if (p->fop.aio_write)
9599+ p->fop.aio_write = aufs_aio_write_sp;
9600+ p->fop.release = aufs_release_sp;
9601+ p->done = 1;
9602+ }
9603+ spin_unlock(&p->spin);
9604+ }
9605+ file->f_op = &p->fop;
9606+}
9607+
9608+static int au_cpup_sp(struct dentry *dentry)
9609+{
9610+ int err;
9611+ aufs_bindex_t bcpup;
9612+ struct au_pin pin;
9613+ struct au_wr_dir_args wr_dir_args = {
9614+ .force_btgt = -1,
9615+ .flags = 0
9616+ };
9617+
9618+ AuDbg("%.*s\n", AuDLNPair(dentry));
9619+
9620+ di_read_unlock(dentry, AuLock_IR);
9621+ di_write_lock_child(dentry);
9622+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
9623+ if (unlikely(err < 0))
9624+ goto out;
9625+ bcpup = err;
9626+ err = 0;
9627+ if (bcpup == au_dbstart(dentry))
9628+ goto out; /* success */
9629+
9630+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
9631+ AuPin_MNT_WRITE);
9632+ if (!err) {
9633+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
9634+ au_unpin(&pin);
9635+ }
9636+
9637+ out:
9638+ di_downgrade_lock(dentry, AuLock_IR);
9639+ return err;
9640+}
9641+
9642+static int au_do_open_sp(struct file *file, int flags)
9643+{
9644+ int err;
9645+ struct dentry *dentry;
9646+ struct super_block *sb;
9647+ struct file *h_file;
9648+ struct inode *h_inode;
9649+
9650+ dentry = file->f_dentry;
9651+ AuDbg("%.*s\n", AuDLNPair(dentry));
9652+
9653+ /*
9654+ * try copying-up.
9655+ * operate on the ro branch is not an error.
9656+ */
9657+ au_cpup_sp(dentry); /* ignore */
9658+
9659+ /* prepare h_file */
9660+ err = au_do_open_nondir(file, vfsub_file_flags(file));
9661+ if (unlikely(err))
9662+ goto out;
9663+
9664+ sb = dentry->d_sb;
9665+ h_file = au_hf_top(file);
9666+ h_inode = h_file->f_dentry->d_inode;
9667+ di_read_unlock(dentry, AuLock_IR);
9668+ fi_write_unlock(file);
9669+ si_read_unlock(sb);
9670+ /* open this fifo in aufs */
9671+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
9672+ si_noflush_read_lock(sb);
9673+ fi_write_lock(file);
9674+ di_read_lock_child(dentry, AuLock_IR);
9675+ if (!err)
9676+ au_init_fop_sp(file);
9677+ else
9678+ au_finfo_fin(file);
9679+
9680+ out:
9681+ return err;
9682+}
9683+
9684+static int aufs_open_sp(struct inode *inode, struct file *file)
9685+{
9686+ int err;
9687+ struct super_block *sb;
9688+
9689+ sb = file->f_dentry->d_sb;
9690+ si_read_lock(sb, AuLock_FLUSH);
9691+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
9692+ si_read_unlock(sb);
9693+ return err;
9694+}
9695+
9696+/* ---------------------------------------------------------------------- */
9697+
9698+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
9699+{
9700+ init_special_inode(inode, mode, rdev);
9701+
9702+ switch (mode & S_IFMT) {
9703+ case S_IFIFO:
9704+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
9705+ /*FALLTHROUGH*/
9706+ case S_IFCHR:
9707+ case S_IFBLK:
9708+ case S_IFSOCK:
9709+ break;
9710+ default:
9711+ AuDebugOn(1);
9712+ }
9713+}
9714+
9715+int au_special_file(umode_t mode)
9716+{
9717+ int ret;
9718+
9719+ ret = 0;
9720+ switch (mode & S_IFMT) {
9721+ case S_IFIFO:
9722+#if 0
9723+ case S_IFCHR:
9724+ case S_IFBLK:
9725+ case S_IFSOCK:
9726+#endif
9727+ ret = 1;
9728+ }
9729+
9730+ return ret;
9731+}
9732diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/fstype.h linux-2.6.34/fs/aufs/fstype.h
9733--- linux-2.6.34.org/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
9734+++ linux-2.6.34/fs/aufs/fstype.h 2010-05-31 22:15:32.000000000 +0200
9735@@ -0,0 +1,497 @@
9736+/*
9737+ * Copyright (C) 2005-2010 Junjiro R. Okajima
9738+ *
9739+ * This program, aufs is free software; you can redistribute it and/or modify
9740+ * it under the terms of the GNU General Public License as published by
9741+ * the Free Software Foundation; either version 2 of the License, or
9742+ * (at your option) any later version.
9743+ *
9744+ * This program is distributed in the hope that it will be useful,
9745+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9746+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9747+ * GNU General Public License for more details.
9748+ *
9749+ * You should have received a copy of the GNU General Public License
9750+ * along with this program; if not, write to the Free Software
9751+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9752+ */
9753+
9754+/*
9755+ * judging filesystem type
9756+ */
9757+
9758+#ifndef __AUFS_FSTYPE_H__
9759+#define __AUFS_FSTYPE_H__
9760+
9761+#ifdef __KERNEL__
9762+
9763+#include <linux/fs.h>
9764+#include <linux/magic.h>
9765+#include <linux/romfs_fs.h>
9766+#include <linux/aufs_type.h>
9767+
9768+static inline int au_test_aufs(struct super_block *sb)
9769+{
9770+ return sb->s_magic == AUFS_SUPER_MAGIC;
9771+}
9772+
9773+static inline const char *au_sbtype(struct super_block *sb)
9774+{
9775+ return sb->s_type->name;
9776+}
1308ab2a 9777+
9778+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
9779+{
9780+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
9781+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
9782+#else
9783+ return 0;
9784+#endif
9785+}
9786+
1308ab2a 9787+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 9788+{
1308ab2a 9789+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
9790+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
9791+#else
9792+ return 0;
9793+#endif
9794+}
9795+
1308ab2a 9796+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 9797+{
1308ab2a 9798+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
9799+ return sb->s_magic == CRAMFS_MAGIC;
9800+#endif
9801+ return 0;
9802+}
9803+
9804+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
9805+{
9806+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
9807+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
9808+#else
9809+ return 0;
9810+#endif
9811+}
9812+
1308ab2a 9813+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 9814+{
1308ab2a 9815+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
9816+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
9817+#else
9818+ return 0;
9819+#endif
9820+}
9821+
1308ab2a 9822+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 9823+{
1308ab2a 9824+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
9825+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
9826+#else
9827+ return 0;
9828+#endif
9829+}
9830+
1308ab2a 9831+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 9832+{
1308ab2a 9833+#ifdef CONFIG_TMPFS
9834+ return sb->s_magic == TMPFS_MAGIC;
9835+#else
9836+ return 0;
dece6358 9837+#endif
dece6358
AM
9838+}
9839+
1308ab2a 9840+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 9841+{
1308ab2a 9842+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
9843+ return !strcmp(au_sbtype(sb), "ecryptfs");
9844+#else
9845+ return 0;
9846+#endif
1facf9fc 9847+}
9848+
1308ab2a 9849+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 9850+{
1308ab2a 9851+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
9852+ return sb->s_magic == SMB_SUPER_MAGIC;
9853+#else
9854+ return 0;
1facf9fc 9855+#endif
1facf9fc 9856+}
9857+
1308ab2a 9858+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 9859+{
1308ab2a 9860+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
9861+ return sb->s_magic == OCFS2_SUPER_MAGIC;
9862+#else
9863+ return 0;
9864+#endif
1facf9fc 9865+}
9866+
1308ab2a 9867+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 9868+{
1308ab2a 9869+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
9870+ return sb->s_magic == DLMFS_MAGIC;
9871+#else
9872+ return 0;
9873+#endif
1facf9fc 9874+}
9875+
1308ab2a 9876+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 9877+{
1308ab2a 9878+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
9879+ return sb->s_magic == CODA_SUPER_MAGIC;
9880+#else
9881+ return 0;
9882+#endif
9883+}
9884+
9885+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
9886+{
9887+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
9888+ return sb->s_magic == V9FS_MAGIC;
9889+#else
9890+ return 0;
9891+#endif
9892+}
9893+
9894+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
9895+{
9896+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
9897+ return sb->s_magic == EXT4_SUPER_MAGIC;
9898+#else
9899+ return 0;
9900+#endif
9901+}
9902+
9903+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
9904+{
9905+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
9906+ return !strcmp(au_sbtype(sb), "sysv");
9907+#else
9908+ return 0;
9909+#endif
9910+}
9911+
9912+static inline int au_test_ramfs(struct super_block *sb)
9913+{
9914+ return sb->s_magic == RAMFS_MAGIC;
9915+}
9916+
9917+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
9918+{
9919+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
9920+ return sb->s_magic == UBIFS_SUPER_MAGIC;
9921+#else
9922+ return 0;
9923+#endif
9924+}
9925+
9926+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
9927+{
9928+#ifdef CONFIG_PROC_FS
9929+ return sb->s_magic == PROC_SUPER_MAGIC;
9930+#else
9931+ return 0;
9932+#endif
9933+}
9934+
9935+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
9936+{
9937+#ifdef CONFIG_SYSFS
9938+ return sb->s_magic == SYSFS_MAGIC;
9939+#else
9940+ return 0;
9941+#endif
9942+}
9943+
9944+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
9945+{
9946+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
9947+ return sb->s_magic == CONFIGFS_MAGIC;
9948+#else
9949+ return 0;
9950+#endif
9951+}
9952+
9953+static inline int au_test_minix(struct super_block *sb __maybe_unused)
9954+{
9955+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
9956+ return sb->s_magic == MINIX3_SUPER_MAGIC
9957+ || sb->s_magic == MINIX2_SUPER_MAGIC
9958+ || sb->s_magic == MINIX2_SUPER_MAGIC2
9959+ || sb->s_magic == MINIX_SUPER_MAGIC
9960+ || sb->s_magic == MINIX_SUPER_MAGIC2;
9961+#else
9962+ return 0;
9963+#endif
9964+}
9965+
9966+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
9967+{
9968+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
9969+ return sb->s_magic == CIFS_MAGIC_NUMBER;
9970+#else
9971+ return 0;
9972+#endif
9973+}
9974+
9975+static inline int au_test_fat(struct super_block *sb __maybe_unused)
9976+{
9977+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
9978+ return sb->s_magic == MSDOS_SUPER_MAGIC;
9979+#else
9980+ return 0;
9981+#endif
9982+}
9983+
9984+static inline int au_test_msdos(struct super_block *sb)
9985+{
9986+ return au_test_fat(sb);
9987+}
9988+
9989+static inline int au_test_vfat(struct super_block *sb)
9990+{
9991+ return au_test_fat(sb);
9992+}
9993+
9994+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
9995+{
9996+#ifdef CONFIG_SECURITYFS
9997+ return sb->s_magic == SECURITYFS_MAGIC;
9998+#else
9999+ return 0;
10000+#endif
10001+}
10002+
10003+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
10004+{
10005+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
10006+ return sb->s_magic == SQUASHFS_MAGIC;
10007+#else
10008+ return 0;
10009+#endif
10010+}
10011+
10012+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
10013+{
10014+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
10015+ return sb->s_magic == BTRFS_SUPER_MAGIC;
10016+#else
10017+ return 0;
10018+#endif
10019+}
10020+
10021+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
10022+{
10023+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
10024+ return sb->s_magic == XENFS_SUPER_MAGIC;
10025+#else
10026+ return 0;
10027+#endif
10028+}
10029+
10030+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
10031+{
10032+#ifdef CONFIG_DEBUG_FS
10033+ return sb->s_magic == DEBUGFS_MAGIC;
10034+#else
10035+ return 0;
10036+#endif
10037+}
10038+
10039+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
10040+{
10041+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
10042+ return sb->s_magic == NILFS_SUPER_MAGIC;
10043+#else
10044+ return 0;
10045+#endif
10046+}
10047+
4a4d8108
AM
10048+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
10049+{
10050+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
10051+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
10052+#else
10053+ return 0;
10054+#endif
10055+}
10056+
1308ab2a 10057+/* ---------------------------------------------------------------------- */
10058+/*
10059+ * they can't be an aufs branch.
10060+ */
10061+static inline int au_test_fs_unsuppoted(struct super_block *sb)
10062+{
10063+ return
10064+#ifndef CONFIG_AUFS_BR_RAMFS
10065+ au_test_ramfs(sb) ||
10066+#endif
10067+ au_test_procfs(sb)
10068+ || au_test_sysfs(sb)
10069+ || au_test_configfs(sb)
10070+ || au_test_debugfs(sb)
10071+ || au_test_securityfs(sb)
10072+ || au_test_xenfs(sb)
10073+ || au_test_ecryptfs(sb)
10074+ /* || !strcmp(au_sbtype(sb), "unionfs") */
10075+ || au_test_aufs(sb); /* will be supported in next version */
10076+}
10077+
10078+/*
10079+ * If the filesystem supports NFS-export, then it has to support NULL as
10080+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
10081+ * We can apply this principle when we handle a lower filesystem.
10082+ */
10083+static inline int au_test_fs_null_nd(struct super_block *sb)
10084+{
10085+ return !!sb->s_export_op;
10086+}
10087+
10088+static inline int au_test_fs_remote(struct super_block *sb)
10089+{
10090+ return !au_test_tmpfs(sb)
10091+#ifdef CONFIG_AUFS_BR_RAMFS
10092+ && !au_test_ramfs(sb)
10093+#endif
10094+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
10095+}
10096+
10097+/* ---------------------------------------------------------------------- */
10098+
10099+/*
10100+ * Note: these functions (below) are created after reading ->getattr() in all
10101+ * filesystems under linux/fs. it means we have to do so in every update...
10102+ */
10103+
10104+/*
10105+ * some filesystems require getattr to refresh the inode attributes before
10106+ * referencing.
10107+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
10108+ * and leave the work for d_revalidate()
10109+ */
10110+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
10111+{
10112+ return au_test_nfs(sb)
10113+ || au_test_fuse(sb)
10114+ /* || au_test_smbfs(sb) */ /* untested */
10115+ /* || au_test_ocfs2(sb) */ /* untested */
10116+ /* || au_test_btrfs(sb) */ /* untested */
10117+ /* || au_test_coda(sb) */ /* untested */
10118+ /* || au_test_v9fs(sb) */ /* untested */
10119+ ;
10120+}
10121+
10122+/*
10123+ * filesystems which don't maintain i_size or i_blocks.
10124+ */
10125+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
10126+{
10127+ return au_test_xfs(sb)
4a4d8108
AM
10128+ || au_test_btrfs(sb)
10129+ || au_test_ubifs(sb)
10130+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 10131+ /* || au_test_ext4(sb) */ /* untested */
10132+ /* || au_test_ocfs2(sb) */ /* untested */
10133+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
10134+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 10135+ /* || au_test_minix(sb) */ /* untested */
10136+ ;
10137+}
10138+
10139+/*
10140+ * filesystems which don't store the correct value in some of their inode
10141+ * attributes.
10142+ */
10143+static inline int au_test_fs_bad_iattr(struct super_block *sb)
10144+{
10145+ return au_test_fs_bad_iattr_size(sb)
10146+ /* || au_test_cifs(sb) */ /* untested */
10147+ || au_test_fat(sb)
10148+ || au_test_msdos(sb)
10149+ || au_test_vfat(sb);
1facf9fc 10150+}
10151+
10152+/* they don't check i_nlink in link(2) */
10153+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
10154+{
10155+ return au_test_tmpfs(sb)
10156+#ifdef CONFIG_AUFS_BR_RAMFS
10157+ || au_test_ramfs(sb)
10158+#endif
4a4d8108
AM
10159+ || au_test_ubifs(sb)
10160+ || au_test_btrfs(sb)
10161+ || au_test_hfsplus(sb);
1facf9fc 10162+}
10163+
10164+/*
10165+ * filesystems which sets S_NOATIME and S_NOCMTIME.
10166+ */
10167+static inline int au_test_fs_notime(struct super_block *sb)
10168+{
10169+ return au_test_nfs(sb)
10170+ || au_test_fuse(sb)
dece6358 10171+ || au_test_ubifs(sb)
1facf9fc 10172+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 10173+ ;
10174+}
10175+
10176+/*
10177+ * filesystems which requires replacing i_mapping.
10178+ */
10179+static inline int au_test_fs_bad_mapping(struct super_block *sb)
10180+{
dece6358
AM
10181+ return au_test_fuse(sb)
10182+ || au_test_ubifs(sb);
1facf9fc 10183+}
10184+
10185+/* temporary support for i#1 in cramfs */
10186+static inline int au_test_fs_unique_ino(struct inode *inode)
10187+{
10188+ if (au_test_cramfs(inode->i_sb))
10189+ return inode->i_ino != 1;
10190+ return 1;
10191+}
10192+
10193+/* ---------------------------------------------------------------------- */
10194+
10195+/*
10196+ * the filesystem where the xino files placed must support i/o after unlink and
10197+ * maintain i_size and i_blocks.
10198+ */
10199+static inline int au_test_fs_bad_xino(struct super_block *sb)
10200+{
10201+ return au_test_fs_remote(sb)
10202+ || au_test_fs_bad_iattr_size(sb)
10203+#ifdef CONFIG_AUFS_BR_RAMFS
10204+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
10205+#else
10206+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
10207+#endif
10208+ /* don't want unnecessary work for xino */
10209+ || au_test_aufs(sb)
1308ab2a 10210+ || au_test_ecryptfs(sb)
10211+ || au_test_nilfs(sb);
1facf9fc 10212+}
10213+
10214+static inline int au_test_fs_trunc_xino(struct super_block *sb)
10215+{
10216+ return au_test_tmpfs(sb)
10217+ || au_test_ramfs(sb);
10218+}
10219+
10220+/*
10221+ * test if the @sb is real-readonly.
10222+ */
10223+static inline int au_test_fs_rr(struct super_block *sb)
10224+{
10225+ return au_test_squashfs(sb)
10226+ || au_test_iso9660(sb)
10227+ || au_test_cramfs(sb)
10228+ || au_test_romfs(sb);
10229+}
10230+
10231+#endif /* __KERNEL__ */
10232+#endif /* __AUFS_FSTYPE_H__ */
4a4d8108
AM
10233diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/hfsnotify.c linux-2.6.34/fs/aufs/hfsnotify.c
10234--- linux-2.6.34.org/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
10235+++ linux-2.6.34/fs/aufs/hfsnotify.c 2010-05-31 22:15:32.000000000 +0200
10236@@ -0,0 +1,230 @@
1facf9fc 10237+/*
4a4d8108 10238+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 10239+ *
10240+ * This program, aufs is free software; you can redistribute it and/or modify
10241+ * it under the terms of the GNU General Public License as published by
10242+ * the Free Software Foundation; either version 2 of the License, or
10243+ * (at your option) any later version.
dece6358
AM
10244+ *
10245+ * This program is distributed in the hope that it will be useful,
10246+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10247+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10248+ * GNU General Public License for more details.
10249+ *
10250+ * You should have received a copy of the GNU General Public License
10251+ * along with this program; if not, write to the Free Software
10252+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 10253+ */
10254+
10255+/*
4a4d8108 10256+ * fsnotify for the lower directories
1facf9fc 10257+ */
10258+
10259+#include "aufs.h"
10260+
4a4d8108
AM
10261+/* FS_IN_IGNORED is unnecessary */
10262+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
10263+ | FS_CREATE | FS_EVENT_ON_CHILD);
10264+static struct fsnotify_group *au_hfsn_group;
1facf9fc 10265+
4a4d8108 10266+static void au_hfsn_free_mark(struct fsnotify_mark_entry *entry)
1facf9fc 10267+{
4a4d8108
AM
10268+#if 0
10269+ struct au_hnotify *hn = container_of(entry, struct au_hnotify,
10270+ hn_entry);
10271+ au_cache_free_hnotify(hn);
10272+#endif
10273+ AuDbg("here\n");
10274+}
1facf9fc 10275+
4a4d8108
AM
10276+static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode)
10277+{
10278+ struct fsnotify_mark_entry *entry;
1facf9fc 10279+
4a4d8108
AM
10280+ entry = &hn->hn_entry;
10281+ fsnotify_init_mark(entry, au_hfsn_free_mark);
10282+ entry->mask = AuHfsnMask;
10283+ return fsnotify_add_mark(entry, au_hfsn_group, h_inode);
1facf9fc 10284+}
10285+
4a4d8108 10286+static void au_hfsn_free(struct au_hnotify *hn)
1facf9fc 10287+{
4a4d8108 10288+ struct fsnotify_mark_entry *entry;
1facf9fc 10289+
4a4d8108
AM
10290+ entry = &hn->hn_entry;
10291+ fsnotify_destroy_mark_by_entry(entry);
10292+ fsnotify_put_mark(entry);
1facf9fc 10293+}
10294+
10295+/* ---------------------------------------------------------------------- */
10296+
4a4d8108 10297+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 10298+{
4a4d8108 10299+ struct fsnotify_mark_entry *entry;
1facf9fc 10300+
4a4d8108
AM
10301+ entry = &hinode->hi_notify->hn_entry;
10302+ spin_lock(&entry->lock);
1facf9fc 10303+ if (do_set) {
4a4d8108
AM
10304+ AuDebugOn(entry->mask & AuHfsnMask);
10305+ entry->mask |= AuHfsnMask;
1facf9fc 10306+ } else {
4a4d8108
AM
10307+ AuDebugOn(!(entry->mask & AuHfsnMask));
10308+ entry->mask &= ~AuHfsnMask;
1facf9fc 10309+ }
4a4d8108
AM
10310+ spin_unlock(&entry->lock);
10311+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 10312+}
10313+
4a4d8108 10314+/* ---------------------------------------------------------------------- */
1facf9fc 10315+
4a4d8108
AM
10316+/* #define AuDbgHnotify */
10317+#ifdef AuDbgHnotify
10318+static char *au_hfsn_name(u32 mask)
10319+{
10320+#ifdef CONFIG_AUFS_DEBUG
10321+#define test_ret(flag) if (mask & flag) \
10322+ return #flag;
10323+ test_ret(FS_ACCESS);
10324+ test_ret(FS_MODIFY);
10325+ test_ret(FS_ATTRIB);
10326+ test_ret(FS_CLOSE_WRITE);
10327+ test_ret(FS_CLOSE_NOWRITE);
10328+ test_ret(FS_OPEN);
10329+ test_ret(FS_MOVED_FROM);
10330+ test_ret(FS_MOVED_TO);
10331+ test_ret(FS_CREATE);
10332+ test_ret(FS_DELETE);
10333+ test_ret(FS_DELETE_SELF);
10334+ test_ret(FS_MOVE_SELF);
10335+ test_ret(FS_UNMOUNT);
10336+ test_ret(FS_Q_OVERFLOW);
10337+ test_ret(FS_IN_IGNORED);
10338+ test_ret(FS_IN_ISDIR);
10339+ test_ret(FS_IN_ONESHOT);
10340+ test_ret(FS_EVENT_ON_CHILD);
10341+ return "";
10342+#undef test_ret
10343+#else
10344+ return "??";
10345+#endif
1facf9fc 10346+}
4a4d8108 10347+#endif
1facf9fc 10348+
10349+/* ---------------------------------------------------------------------- */
10350+
4a4d8108
AM
10351+static int au_hfsn_handle_event(struct fsnotify_group *group,
10352+ struct fsnotify_event *event)
1facf9fc 10353+{
10354+ int err;
4a4d8108
AM
10355+ struct au_hnotify *hnotify;
10356+ struct inode *h_dir, *h_inode;
10357+ __u32 mask;
10358+ struct fsnotify_mark_entry *entry;
10359+ struct qstr h_child_qstr = {
10360+ .name = event->file_name,
10361+ .len = event->name_len
10362+ };
10363+
10364+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 10365+
10366+ err = 0;
4a4d8108
AM
10367+ /* if IN_UNMOUNT happens, there must be another bug */
10368+ mask = event->mask;
10369+ AuDebugOn(mask & FS_UNMOUNT);
10370+ if (mask & (IN_IGNORED | IN_UNMOUNT))
1facf9fc 10371+ goto out;
1facf9fc 10372+
4a4d8108
AM
10373+ h_dir = event->to_tell;
10374+ h_inode = event->inode;
10375+#ifdef AuDbgHnotify
10376+ au_debug(1);
10377+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
10378+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
10379+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
10380+ h_dir->i_ino, mask, au_hfsn_name(mask),
10381+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
10382+ /* WARN_ON(1); */
1facf9fc 10383+ }
4a4d8108 10384+ au_debug(0);
1facf9fc 10385+#endif
4a4d8108
AM
10386+
10387+ spin_lock(&h_dir->i_lock);
10388+ entry = fsnotify_find_mark_entry(group, h_dir);
10389+ spin_unlock(&h_dir->i_lock);
10390+ if (entry) {
10391+ hnotify = container_of(entry, struct au_hnotify, hn_entry);
10392+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
10393+ fsnotify_put_mark(entry);
1facf9fc 10394+ }
1facf9fc 10395+
4a4d8108
AM
10396+out:
10397+ return err;
10398+}
1facf9fc 10399+
4a4d8108
AM
10400+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
10401+/* it should be exported to modules */
10402+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
10403+ struct inode *h_inode, __u32 mask)
10404+{
10405+ struct fsnotify_mark_entry *entry;
10406+ bool send;
10407+
10408+ spin_lock(&h_inode->i_lock);
10409+ entry = fsnotify_find_mark_entry(group, h_inode);
10410+ spin_unlock(&h_inode->i_lock);
10411+ if (!entry)
10412+ return false;
10413+
10414+ mask = (mask & ~FS_EVENT_ON_CHILD);
10415+ send = (entry->mask & mask);
10416+
10417+ /* find took a reference */
10418+ fsnotify_put_mark(entry);
10419+
10420+ return send;
10421+}
10422+
10423+static struct fsnotify_ops au_hfsn_ops = {
10424+ .should_send_event = au_hfsn_should_send_event,
10425+ .handle_event = au_hfsn_handle_event
10426+};
10427+
10428+/* ---------------------------------------------------------------------- */
10429+
10430+static int __init au_hfsn_init(void)
10431+{
10432+ int err;
10433+ unsigned int gn;
10434+ const unsigned int gn_max = 10;
10435+
10436+ gn = 0;
10437+ for (gn = 0; gn < gn_max; gn++) {
10438+ au_hfsn_group = fsnotify_obtain_group(gn, AuHfsnMask,
10439+ &au_hfsn_ops);
10440+ if (au_hfsn_group != ERR_PTR(-EEXIST))
10441+ break;
1facf9fc 10442+ }
10443+
4a4d8108
AM
10444+ err = 0;
10445+ if (IS_ERR(au_hfsn_group)) {
10446+ pr_err("fsnotify_obtain_group() failed %u times\n", gn_max);
10447+ err = PTR_ERR(au_hfsn_group);
10448+ }
1facf9fc 10449+
1facf9fc 10450+ AuTraceErr(err);
10451+ return err;
10452+}
10453+
4a4d8108 10454+static void au_hfsn_fin(void)
1facf9fc 10455+{
4a4d8108
AM
10456+ fsnotify_put_group(au_hfsn_group);
10457+}
1facf9fc 10458+
4a4d8108
AM
10459+const struct au_hnotify_op au_hnotify_op = {
10460+ .ctl = au_hfsn_ctl,
10461+ .alloc = au_hfsn_alloc,
10462+ .free = au_hfsn_free,
1facf9fc 10463+
4a4d8108
AM
10464+ .fin = au_hfsn_fin,
10465+ .init = au_hfsn_init
10466+};
10467diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/hfsplus.c linux-2.6.34/fs/aufs/hfsplus.c
10468--- linux-2.6.34.org/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
10469+++ linux-2.6.34/fs/aufs/hfsplus.c 2010-05-31 22:15:32.000000000 +0200
10470@@ -0,0 +1,58 @@
10471+/*
10472+ * Copyright (C) 2010 Junjiro R. Okajima
10473+ *
10474+ * This program, aufs is free software; you can redistribute it and/or modify
10475+ * it under the terms of the GNU General Public License as published by
10476+ * the Free Software Foundation; either version 2 of the License, or
10477+ * (at your option) any later version.
10478+ *
10479+ * This program is distributed in the hope that it will be useful,
10480+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10481+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10482+ * GNU General Public License for more details.
10483+ *
10484+ * You should have received a copy of the GNU General Public License
10485+ * along with this program; if not, write to the Free Software
10486+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10487+ */
1facf9fc 10488+
4a4d8108
AM
10489+/*
10490+ * special support for filesystems which aqucires an inode mutex
10491+ * at final closing a file, eg, hfsplus.
10492+ *
10493+ * This trick is very simple and stupid, just to open the file before really
10494+ * neceeary open to tell hfsplus that this is not the final closing.
10495+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
10496+ * and au_h_open_post() after releasing it.
10497+ */
1facf9fc 10498+
4a4d8108
AM
10499+#include <linux/file.h>
10500+#include "aufs.h"
1facf9fc 10501+
4a4d8108
AM
10502+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
10503+{
10504+ struct file *h_file;
10505+ struct dentry *h_dentry;
1facf9fc 10506+
4a4d8108
AM
10507+ h_dentry = au_h_dptr(dentry, bindex);
10508+ AuDebugOn(!h_dentry);
10509+ AuDebugOn(!h_dentry->d_inode);
10510+ IMustLock(h_dentry->d_inode);
10511+
10512+ h_file = NULL;
10513+ if (au_test_hfsplus(h_dentry->d_sb)
10514+ && S_ISREG(h_dentry->d_inode->i_mode))
10515+ h_file = au_h_open(dentry, bindex,
10516+ O_RDONLY | O_NOATIME | O_LARGEFILE,
10517+ /*file*/NULL);
10518+ return h_file;
1facf9fc 10519+}
10520+
4a4d8108
AM
10521+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
10522+ struct file *h_file)
10523+{
10524+ if (h_file) {
10525+ fput(h_file);
10526+ au_sbr_put(dentry->d_sb, bindex);
10527+ }
10528+}
10529diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/hinotify.c linux-2.6.34/fs/aufs/hinotify.c
10530--- linux-2.6.34.org/fs/aufs/hinotify.c 1970-01-01 01:00:00.000000000 +0100
10531+++ linux-2.6.34/fs/aufs/hinotify.c 2010-05-31 22:15:32.000000000 +0200
10532@@ -0,0 +1,227 @@
1facf9fc 10533+/*
4a4d8108
AM
10534+ * Copyright (C) 2005-2010 Junjiro R. Okajima
10535+ *
10536+ * This program, aufs is free software; you can redistribute it and/or modify
10537+ * it under the terms of the GNU General Public License as published by
10538+ * the Free Software Foundation; either version 2 of the License, or
10539+ * (at your option) any later version.
10540+ *
10541+ * This program is distributed in the hope that it will be useful,
10542+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10543+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10544+ * GNU General Public License for more details.
10545+ *
10546+ * You should have received a copy of the GNU General Public License
10547+ * along with this program; if not, write to the Free Software
10548+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10549+ */
10550+
10551+/*
10552+ * inotify for the lower directories (deprecated)
1facf9fc 10553+ */
4a4d8108
AM
10554+
10555+#include "aufs.h"
10556+
10557+static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
10558+static struct inotify_handle *au_hin_handle;
10559+
10560+/* ---------------------------------------------------------------------- */
10561+
10562+static int au_hin_alloc(struct au_hnotify *hn, struct inode *h_inode)
1facf9fc 10563+{
10564+ int err;
4a4d8108
AM
10565+ s32 wd;
10566+ struct inotify_watch *watch;
1facf9fc 10567+
4a4d8108
AM
10568+ err = -EEXIST;
10569+ wd = inotify_find_watch(au_hin_handle, h_inode, &watch);
10570+ if (wd >= 0) {
10571+ put_inotify_watch(watch);
1facf9fc 10572+ goto out;
10573+ }
10574+
4a4d8108
AM
10575+ err = 0;
10576+ inotify_init_watch(&hn->hn_watch);
10577+ wd = inotify_add_watch(au_hin_handle, &hn->hn_watch, h_inode,
10578+ AuHinMask);
10579+ if (unlikely(wd < 0)) {
10580+ err = wd;
10581+ put_inotify_watch(&hn->hn_watch);
1facf9fc 10582+ }
10583+
4a4d8108 10584+out:
1facf9fc 10585+ return err;
10586+}
10587+
4a4d8108 10588+static void au_hin_free(struct au_hnotify *hn)
1facf9fc 10589+{
10590+ int err;
1facf9fc 10591+
10592+ err = 0;
4a4d8108
AM
10593+ if (atomic_read(&hn->hn_watch.count))
10594+ err = inotify_rm_watch(au_hin_handle, &hn->hn_watch);
10595+ if (unlikely(err))
10596+ /* it means the watch is already removed */
10597+ pr_warning("failed inotify_rm_watch() %d\n", err);
1facf9fc 10598+}
10599+
10600+/* ---------------------------------------------------------------------- */
10601+
4a4d8108 10602+static void au_hin_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 10603+{
4a4d8108
AM
10604+ struct inode *h_inode;
10605+ struct inotify_watch *watch;
1facf9fc 10606+
4a4d8108
AM
10607+ h_inode = hinode->hi_inode;
10608+ IMustLock(h_inode);
1facf9fc 10609+
4a4d8108
AM
10610+ /* todo: try inotify_find_update_watch()? */
10611+ watch = &hinode->hi_notify->hn_watch;
10612+ mutex_lock(&h_inode->inotify_mutex);
10613+ /* mutex_lock(&watch->ih->mutex); */
10614+ if (do_set) {
10615+ AuDebugOn(watch->mask & AuHinMask);
10616+ watch->mask |= AuHinMask;
10617+ } else {
10618+ AuDebugOn(!(watch->mask & AuHinMask));
10619+ watch->mask &= ~AuHinMask;
1facf9fc 10620+ }
4a4d8108
AM
10621+ /* mutex_unlock(&watch->ih->mutex); */
10622+ mutex_unlock(&h_inode->inotify_mutex);
1facf9fc 10623+}
10624+
10625+/* ---------------------------------------------------------------------- */
10626+
4a4d8108 10627+#ifdef AuDbgHnotify
1facf9fc 10628+static char *in_name(u32 mask)
10629+{
10630+#ifdef CONFIG_AUFS_DEBUG
10631+#define test_ret(flag) if (mask & flag) \
10632+ return #flag;
10633+ test_ret(IN_ACCESS);
10634+ test_ret(IN_MODIFY);
10635+ test_ret(IN_ATTRIB);
10636+ test_ret(IN_CLOSE_WRITE);
10637+ test_ret(IN_CLOSE_NOWRITE);
10638+ test_ret(IN_OPEN);
10639+ test_ret(IN_MOVED_FROM);
10640+ test_ret(IN_MOVED_TO);
10641+ test_ret(IN_CREATE);
10642+ test_ret(IN_DELETE);
10643+ test_ret(IN_DELETE_SELF);
10644+ test_ret(IN_MOVE_SELF);
10645+ test_ret(IN_UNMOUNT);
10646+ test_ret(IN_Q_OVERFLOW);
10647+ test_ret(IN_IGNORED);
10648+ return "";
10649+#undef test_ret
10650+#else
10651+ return "??";
10652+#endif
10653+}
4a4d8108 10654+#endif
1facf9fc 10655+
4a4d8108
AM
10656+static u32 au_hin_conv_mask(u32 mask)
10657+{
10658+ u32 conv;
10659+
10660+ conv = 0;
10661+#define do_conv(flag) conv |= (mask & IN_ ## flag) ? FS_ ## flag : 0
10662+ do_conv(ACCESS);
10663+ do_conv(MODIFY);
10664+ do_conv(ATTRIB);
10665+ do_conv(CLOSE_WRITE);
10666+ do_conv(CLOSE_NOWRITE);
10667+ do_conv(OPEN);
10668+ do_conv(MOVED_FROM);
10669+ do_conv(MOVED_TO);
10670+ do_conv(CREATE);
10671+ do_conv(DELETE);
10672+ do_conv(DELETE_SELF);
10673+ do_conv(MOVE_SELF);
10674+ do_conv(UNMOUNT);
10675+ do_conv(Q_OVERFLOW);
10676+#undef do_conv
10677+#define do_conv(flag) conv |= (mask & IN_ ## flag) ? FS_IN_ ## flag : 0
10678+ do_conv(IGNORED);
10679+ /* do_conv(ISDIR); */
10680+ /* do_conv(ONESHOT); */
10681+#undef do_conv
10682+
10683+ return conv;
1facf9fc 10684+}
10685+
1facf9fc 10686+static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
10687+ u32 mask, u32 cookie __maybe_unused,
10688+ const char *h_child_name, struct inode *h_child_inode)
10689+{
4a4d8108
AM
10690+ struct au_hnotify *hnotify;
10691+ struct qstr h_child_qstr = {
10692+ .name = h_child_name
10693+ };
1facf9fc 10694+
10695+ /* if IN_UNMOUNT happens, there must be another bug */
10696+ AuDebugOn(mask & IN_UNMOUNT);
10697+ if (mask & (IN_IGNORED | IN_UNMOUNT)) {
10698+ put_inotify_watch(watch);
10699+ return;
10700+ }
4a4d8108
AM
10701+
10702+#ifdef AuDbgHnotify
1facf9fc 10703+ au_debug(1);
10704+ if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
10705+ AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
10706+ " hi%lu\n",
10707+ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
10708+ h_child_name ? h_child_name : "",
10709+ h_child_inode ? h_child_inode->i_ino : 0);
10710+ WARN_ON(1);
10711+ }
10712+ au_debug(0);
10713+#endif
10714+
4a4d8108
AM
10715+ if (h_child_name)
10716+ h_child_qstr.len = strlen(h_child_name);
10717+ hnotify = container_of(watch, struct au_hnotify, hn_watch);
10718+ mask = au_hin_conv_mask(mask);
10719+ au_hnotify(watch->inode, hnotify, mask, &h_child_qstr, h_child_inode);
10720+}
1facf9fc 10721+
4a4d8108
AM
10722+static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
10723+{
10724+ return;
10725+}
1facf9fc 10726+
4a4d8108
AM
10727+static struct inotify_operations aufs_inotify_ops = {
10728+ .handle_event = aufs_inotify,
10729+ .destroy_watch = aufs_inotify_destroy
10730+};
1facf9fc 10731+
4a4d8108 10732+/* ---------------------------------------------------------------------- */
1facf9fc 10733+
4a4d8108
AM
10734+static int __init au_hin_init(void)
10735+{
10736+ int err;
1facf9fc 10737+
4a4d8108
AM
10738+ err = 0;
10739+ au_hin_handle = inotify_init(&aufs_inotify_ops);
10740+ if (IS_ERR(au_hin_handle))
10741+ err = PTR_ERR(au_hin_handle);
1facf9fc 10742+
4a4d8108
AM
10743+ AuTraceErr(err);
10744+ return err;
10745+}
1facf9fc 10746+
4a4d8108 10747+static void au_hin_fin(void)
1facf9fc 10748+{
4a4d8108 10749+ inotify_destroy(au_hin_handle);
1facf9fc 10750+}
10751+
4a4d8108
AM
10752+const struct au_hnotify_op au_hnotify_op = {
10753+ .ctl = au_hin_ctl,
10754+ .alloc = au_hin_alloc,
10755+ .free = au_hin_free,
1facf9fc 10756+
4a4d8108
AM
10757+ .fin = au_hin_fin,
10758+ .init = au_hin_init
10759+};
10760diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/hnotify.c linux-2.6.34/fs/aufs/hnotify.c
10761--- linux-2.6.34.org/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
10762+++ linux-2.6.34/fs/aufs/hnotify.c 2010-05-31 22:15:32.000000000 +0200
10763@@ -0,0 +1,671 @@
1facf9fc 10764+/*
4a4d8108 10765+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 10766+ *
10767+ * This program, aufs is free software; you can redistribute it and/or modify
10768+ * it under the terms of the GNU General Public License as published by
10769+ * the Free Software Foundation; either version 2 of the License, or
10770+ * (at your option) any later version.
dece6358
AM
10771+ *
10772+ * This program is distributed in the hope that it will be useful,
10773+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10774+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10775+ * GNU General Public License for more details.
10776+ *
10777+ * You should have received a copy of the GNU General Public License
10778+ * along with this program; if not, write to the Free Software
10779+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 10780+ */
10781+
10782+/*
4a4d8108 10783+ * abstraction to notify the direct changes on lower directories
1facf9fc 10784+ */
10785+
1308ab2a 10786+#include "aufs.h"
1facf9fc 10787+
4a4d8108
AM
10788+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
10789+ struct inode *h_inode)
dece6358 10790+{
1308ab2a 10791+ int err;
4a4d8108 10792+ struct au_hnotify *hn;
1facf9fc 10793+
4a4d8108
AM
10794+ err = -ENOMEM;
10795+ hn = au_cache_alloc_hnotify();
10796+ if (hn) {
10797+ hn->hn_aufs_inode = inode;
10798+ err = au_hnotify_op.alloc(hn, h_inode);
10799+ if (!err)
10800+ hinode->hi_notify = hn;
10801+ else {
10802+ au_cache_free_hnotify(hn);
10803+ /*
10804+ * The upper dir was removed by udba, but the same named
10805+ * dir left. In this case, aufs assignes a new inode
10806+ * number and set the monitor again.
10807+ * For the lower dir, the old monitnor is still left.
10808+ */
10809+ if (err == -EEXIST)
10810+ err = 0;
10811+ }
1308ab2a 10812+ }
1308ab2a 10813+
1308ab2a 10814+ return err;
dece6358 10815+}
1facf9fc 10816+
4a4d8108 10817+void au_hn_free(struct au_hinode *hinode)
dece6358 10818+{
4a4d8108 10819+ struct au_hnotify *hn;
1facf9fc 10820+
4a4d8108
AM
10821+ hn = hinode->hi_notify;
10822+ if (hn) {
10823+ au_hnotify_op.free(hn);
10824+ au_cache_free_hnotify(hn);
10825+ hinode->hi_notify = NULL;
10826+ }
10827+}
dece6358 10828+
4a4d8108 10829+/* ---------------------------------------------------------------------- */
dece6358 10830+
4a4d8108
AM
10831+void au_hn_ctl(struct au_hinode *hinode, int do_set)
10832+{
10833+ if (hinode->hi_notify)
10834+ au_hnotify_op.ctl(hinode, do_set);
10835+}
10836+
10837+void au_hn_reset(struct inode *inode, unsigned int flags)
10838+{
10839+ aufs_bindex_t bindex, bend;
10840+ struct inode *hi;
10841+ struct dentry *iwhdentry;
1facf9fc 10842+
1308ab2a 10843+ bend = au_ibend(inode);
4a4d8108
AM
10844+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
10845+ hi = au_h_iptr(inode, bindex);
10846+ if (!hi)
10847+ continue;
1308ab2a 10848+
4a4d8108
AM
10849+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
10850+ iwhdentry = au_hi_wh(inode, bindex);
10851+ if (iwhdentry)
10852+ dget(iwhdentry);
10853+ au_igrab(hi);
10854+ au_set_h_iptr(inode, bindex, NULL, 0);
10855+ au_set_h_iptr(inode, bindex, au_igrab(hi),
10856+ flags & ~AuHi_XINO);
10857+ iput(hi);
10858+ dput(iwhdentry);
10859+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 10860+ }
1facf9fc 10861+}
10862+
1308ab2a 10863+/* ---------------------------------------------------------------------- */
1facf9fc 10864+
4a4d8108 10865+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 10866+{
4a4d8108
AM
10867+ int err;
10868+ aufs_bindex_t bindex, bend, bfound, bstart;
10869+ struct inode *h_i;
1facf9fc 10870+
4a4d8108
AM
10871+ err = 0;
10872+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
10873+ pr_warning("branch root dir was changed\n");
10874+ goto out;
10875+ }
1facf9fc 10876+
4a4d8108
AM
10877+ bfound = -1;
10878+ bend = au_ibend(inode);
10879+ bstart = au_ibstart(inode);
10880+#if 0 /* reserved for future use */
10881+ if (bindex == bend) {
10882+ /* keep this ino in rename case */
10883+ goto out;
10884+ }
10885+#endif
10886+ for (bindex = bstart; bindex <= bend; bindex++)
10887+ if (au_h_iptr(inode, bindex) == h_inode) {
10888+ bfound = bindex;
10889+ break;
10890+ }
10891+ if (bfound < 0)
1308ab2a 10892+ goto out;
1facf9fc 10893+
4a4d8108
AM
10894+ for (bindex = bstart; bindex <= bend; bindex++) {
10895+ h_i = au_h_iptr(inode, bindex);
10896+ if (!h_i)
10897+ continue;
1facf9fc 10898+
4a4d8108
AM
10899+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
10900+ /* ignore this error */
10901+ /* bad action? */
1facf9fc 10902+ }
1facf9fc 10903+
4a4d8108 10904+ /* children inode number will be broken */
1facf9fc 10905+
1308ab2a 10906+ out:
4a4d8108
AM
10907+ AuTraceErr(err);
10908+ return err;
1facf9fc 10909+}
10910+
4a4d8108 10911+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 10912+{
4a4d8108
AM
10913+ int err, i, j, ndentry;
10914+ struct au_dcsub_pages dpages;
10915+ struct au_dpage *dpage;
10916+ struct dentry **dentries;
1facf9fc 10917+
4a4d8108
AM
10918+ err = au_dpages_init(&dpages, GFP_NOFS);
10919+ if (unlikely(err))
10920+ goto out;
10921+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
10922+ if (unlikely(err))
10923+ goto out_dpages;
1facf9fc 10924+
4a4d8108
AM
10925+ for (i = 0; i < dpages.ndpage; i++) {
10926+ dpage = dpages.dpages + i;
10927+ dentries = dpage->dentries;
10928+ ndentry = dpage->ndentry;
10929+ for (j = 0; j < ndentry; j++) {
10930+ struct dentry *d;
10931+
10932+ d = dentries[j];
10933+ if (IS_ROOT(d))
10934+ continue;
10935+
10936+ d_drop(d);
10937+ au_digen_dec(d);
10938+ if (d->d_inode)
10939+ /* todo: reset children xino?
10940+ cached children only? */
10941+ au_iigen_dec(d->d_inode);
1308ab2a 10942+ }
dece6358 10943+ }
1facf9fc 10944+
4a4d8108
AM
10945+ out_dpages:
10946+ au_dpages_free(&dpages);
dece6358 10947+
4a4d8108
AM
10948+ /* discard children */
10949+ dentry_unhash(dentry);
10950+ dput(dentry);
10951+ out:
dece6358
AM
10952+ return err;
10953+}
10954+
1308ab2a 10955+/*
4a4d8108 10956+ * return 0 if processed.
1308ab2a 10957+ */
4a4d8108
AM
10958+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
10959+ const unsigned int isdir)
dece6358 10960+{
1308ab2a 10961+ int err;
4a4d8108
AM
10962+ struct dentry *d;
10963+ struct qstr *dname;
1facf9fc 10964+
4a4d8108
AM
10965+ err = 1;
10966+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
10967+ pr_warning("branch root dir was changed\n");
10968+ err = 0;
10969+ goto out;
10970+ }
dece6358 10971+
4a4d8108
AM
10972+ if (!isdir) {
10973+ AuDebugOn(!name);
10974+ au_iigen_dec(inode);
10975+ spin_lock(&dcache_lock);
10976+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
10977+ dname = &d->d_name;
10978+ if (dname->len != nlen
10979+ && memcmp(dname->name, name, nlen))
10980+ continue;
10981+ err = 0;
10982+ spin_lock(&d->d_lock);
10983+ __d_drop(d);
10984+ au_digen_dec(d);
10985+ spin_unlock(&d->d_lock);
10986+ break;
1facf9fc 10987+ }
4a4d8108 10988+ spin_unlock(&dcache_lock);
1308ab2a 10989+ } else {
4a4d8108
AM
10990+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
10991+ d = d_find_alias(inode);
10992+ if (!d) {
10993+ au_iigen_dec(inode);
10994+ goto out;
10995+ }
1facf9fc 10996+
4a4d8108
AM
10997+ dname = &d->d_name;
10998+ if (dname->len == nlen && !memcmp(dname->name, name, nlen))
10999+ err = hn_gen_tree(d);
11000+ dput(d);
11001+ }
1facf9fc 11002+
1308ab2a 11003+ out:
4a4d8108 11004+ AuTraceErr(err);
1308ab2a 11005+ return err;
11006+}
dece6358 11007+
4a4d8108 11008+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 11009+{
4a4d8108
AM
11010+ int err;
11011+ struct inode *inode;
1facf9fc 11012+
4a4d8108
AM
11013+ inode = dentry->d_inode;
11014+ if (IS_ROOT(dentry)
11015+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
11016+ ) {
11017+ pr_warning("branch root dir was changed\n");
11018+ return 0;
11019+ }
1308ab2a 11020+
4a4d8108
AM
11021+ err = 0;
11022+ if (!isdir) {
11023+ d_drop(dentry);
11024+ au_digen_dec(dentry);
11025+ if (inode)
11026+ au_iigen_dec(inode);
11027+ } else {
11028+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
11029+ if (inode)
11030+ err = hn_gen_tree(dentry);
11031+ }
11032+
11033+ AuTraceErr(err);
11034+ return err;
1facf9fc 11035+}
11036+
4a4d8108 11037+/* ---------------------------------------------------------------------- */
1facf9fc 11038+
4a4d8108
AM
11039+/* hnotify job flags */
11040+#define AuHnJob_XINO0 1
11041+#define AuHnJob_GEN (1 << 1)
11042+#define AuHnJob_DIRENT (1 << 2)
11043+#define AuHnJob_ISDIR (1 << 3)
11044+#define AuHnJob_TRYXINO0 (1 << 4)
11045+#define AuHnJob_MNTPNT (1 << 5)
11046+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
11047+#define au_fset_hnjob(flags, name) { (flags) |= AuHnJob_##name; }
11048+#define au_fclr_hnjob(flags, name) { (flags) &= ~AuHnJob_##name; }
1facf9fc 11049+
4a4d8108
AM
11050+enum {
11051+ AuHn_CHILD,
11052+ AuHn_PARENT,
11053+ AuHnLast
11054+};
1facf9fc 11055+
4a4d8108
AM
11056+struct au_hnotify_args {
11057+ struct inode *h_dir, *dir, *h_child_inode;
11058+ u32 mask;
11059+ unsigned int flags[AuHnLast];
11060+ unsigned int h_child_nlen;
11061+ char h_child_name[];
11062+};
1facf9fc 11063+
4a4d8108
AM
11064+struct hn_job_args {
11065+ unsigned int flags;
11066+ struct inode *inode, *h_inode, *dir, *h_dir;
11067+ struct dentry *dentry;
11068+ char *h_name;
11069+ int h_nlen;
11070+};
1308ab2a 11071+
4a4d8108
AM
11072+static int hn_job(struct hn_job_args *a)
11073+{
11074+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 11075+
4a4d8108
AM
11076+ /* reset xino */
11077+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
11078+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 11079+
4a4d8108
AM
11080+ if (au_ftest_hnjob(a->flags, TRYXINO0)
11081+ && a->inode
11082+ && a->h_inode) {
11083+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11084+ if (!a->h_inode->i_nlink)
11085+ hn_xino(a->inode, a->h_inode); /* ignore this error */
11086+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 11087+ }
1facf9fc 11088+
4a4d8108
AM
11089+ /* make the generation obsolete */
11090+ if (au_ftest_hnjob(a->flags, GEN)) {
11091+ int err = -1;
11092+ if (a->inode)
11093+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
11094+ isdir);
11095+ if (err && a->dentry)
11096+ hn_gen_by_name(a->dentry, isdir);
11097+ /* ignore this error */
1facf9fc 11098+ }
1facf9fc 11099+
4a4d8108
AM
11100+ /* make dir entries obsolete */
11101+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
11102+ struct au_vdir *vdir;
1facf9fc 11103+
4a4d8108
AM
11104+ vdir = au_ivdir(a->inode);
11105+ if (vdir)
11106+ vdir->vd_jiffy = 0;
11107+ /* IMustLock(a->inode); */
11108+ /* a->inode->i_version++; */
11109+ }
1facf9fc 11110+
4a4d8108
AM
11111+ /* can do nothing but warn */
11112+ if (au_ftest_hnjob(a->flags, MNTPNT)
11113+ && a->dentry
11114+ && d_mountpoint(a->dentry))
11115+ pr_warning("mount-point %.*s is removed or renamed\n",
11116+ AuDLNPair(a->dentry));
1facf9fc 11117+
4a4d8108 11118+ return 0;
1308ab2a 11119+}
1facf9fc 11120+
1308ab2a 11121+/* ---------------------------------------------------------------------- */
1facf9fc 11122+
4a4d8108
AM
11123+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
11124+ struct inode *dir)
1308ab2a 11125+{
4a4d8108
AM
11126+ struct dentry *dentry, *d, *parent;
11127+ struct qstr *dname;
1308ab2a 11128+
4a4d8108
AM
11129+ parent = d_find_alias(dir);
11130+ if (!parent)
11131+ return NULL;
1308ab2a 11132+
4a4d8108
AM
11133+ dentry = NULL;
11134+ spin_lock(&dcache_lock);
11135+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
11136+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
11137+ dname = &d->d_name;
11138+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
11139+ continue;
11140+ if (!atomic_read(&d->d_count) || !d->d_fsdata) {
11141+ spin_lock(&d->d_lock);
11142+ __d_drop(d);
11143+ spin_unlock(&d->d_lock);
11144+ continue;
dece6358 11145+ }
1facf9fc 11146+
4a4d8108
AM
11147+ dentry = dget(d);
11148+ break;
1308ab2a 11149+ }
4a4d8108
AM
11150+ spin_unlock(&dcache_lock);
11151+ dput(parent);
1facf9fc 11152+
4a4d8108
AM
11153+ if (dentry)
11154+ di_write_lock_child(dentry);
1308ab2a 11155+
4a4d8108
AM
11156+ return dentry;
11157+}
dece6358 11158+
4a4d8108
AM
11159+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
11160+ aufs_bindex_t bindex, ino_t h_ino)
11161+{
11162+ struct inode *inode;
11163+ ino_t ino;
11164+ int err;
11165+
11166+ inode = NULL;
11167+ err = au_xino_read(sb, bindex, h_ino, &ino);
11168+ if (!err && ino)
11169+ inode = ilookup(sb, ino);
11170+ if (!inode)
11171+ goto out;
11172+
11173+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11174+ pr_warning("wrong root branch\n");
11175+ iput(inode);
11176+ inode = NULL;
11177+ goto out;
1308ab2a 11178+ }
11179+
4a4d8108 11180+ ii_write_lock_child(inode);
1308ab2a 11181+
dece6358 11182+ out:
4a4d8108 11183+ return inode;
dece6358
AM
11184+}
11185+
4a4d8108 11186+static void au_hn_bh(void *_args)
1facf9fc 11187+{
4a4d8108
AM
11188+ struct au_hnotify_args *a = _args;
11189+ struct super_block *sb;
11190+ aufs_bindex_t bindex, bend, bfound;
11191+ unsigned char xino, try_iput;
1facf9fc 11192+ int err;
1308ab2a 11193+ struct inode *inode;
4a4d8108
AM
11194+ ino_t h_ino;
11195+ struct hn_job_args args;
11196+ struct dentry *dentry;
11197+ struct au_sbinfo *sbinfo;
1facf9fc 11198+
4a4d8108
AM
11199+ AuDebugOn(!_args);
11200+ AuDebugOn(!a->h_dir);
11201+ AuDebugOn(!a->dir);
11202+ AuDebugOn(!a->mask);
11203+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
11204+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
11205+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 11206+
4a4d8108
AM
11207+ inode = NULL;
11208+ dentry = NULL;
11209+ /*
11210+ * do not lock a->dir->i_mutex here
11211+ * because of d_revalidate() may cause a deadlock.
11212+ */
11213+ sb = a->dir->i_sb;
11214+ AuDebugOn(!sb);
11215+ sbinfo = au_sbi(sb);
11216+ AuDebugOn(!sbinfo);
11217+ /* big aufs lock */
11218+ si_noflush_write_lock(sb);
1facf9fc 11219+
4a4d8108
AM
11220+ ii_read_lock_parent(a->dir);
11221+ bfound = -1;
11222+ bend = au_ibend(a->dir);
11223+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
11224+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
11225+ bfound = bindex;
11226+ break;
11227+ }
11228+ ii_read_unlock(a->dir);
11229+ if (unlikely(bfound < 0))
11230+ goto out;
1facf9fc 11231+
4a4d8108
AM
11232+ xino = !!au_opt_test(au_mntflags(sb), XINO);
11233+ h_ino = 0;
11234+ if (a->h_child_inode)
11235+ h_ino = a->h_child_inode->i_ino;
1facf9fc 11236+
4a4d8108
AM
11237+ if (a->h_child_nlen
11238+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
11239+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
11240+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
11241+ a->dir);
11242+ try_iput = 0;
11243+ if (dentry)
11244+ inode = dentry->d_inode;
11245+ if (xino && !inode && h_ino
11246+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
11247+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
11248+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
11249+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
11250+ try_iput = 1;
11251+ }
1facf9fc 11252+
4a4d8108
AM
11253+ args.flags = a->flags[AuHn_CHILD];
11254+ args.dentry = dentry;
11255+ args.inode = inode;
11256+ args.h_inode = a->h_child_inode;
11257+ args.dir = a->dir;
11258+ args.h_dir = a->h_dir;
11259+ args.h_name = a->h_child_name;
11260+ args.h_nlen = a->h_child_nlen;
11261+ err = hn_job(&args);
11262+ if (dentry) {
11263+ if (dentry->d_fsdata)
11264+ di_write_unlock(dentry);
11265+ dput(dentry);
11266+ }
11267+ if (inode && try_iput) {
11268+ ii_write_unlock(inode);
11269+ iput(inode);
11270+ }
1facf9fc 11271+
4a4d8108
AM
11272+ ii_write_lock_parent(a->dir);
11273+ args.flags = a->flags[AuHn_PARENT];
11274+ args.dentry = NULL;
11275+ args.inode = a->dir;
11276+ args.h_inode = a->h_dir;
11277+ args.dir = NULL;
11278+ args.h_dir = NULL;
11279+ args.h_name = NULL;
11280+ args.h_nlen = 0;
11281+ err = hn_job(&args);
11282+ ii_write_unlock(a->dir);
1facf9fc 11283+
4a4d8108
AM
11284+ out:
11285+ au_nwt_done(&sbinfo->si_nowait);
11286+ si_write_unlock(sb);
1308ab2a 11287+
4a4d8108
AM
11288+ iput(a->h_child_inode);
11289+ iput(a->h_dir);
11290+ iput(a->dir);
1308ab2a 11291+ kfree(a);
dece6358 11292+}
1facf9fc 11293+
4a4d8108
AM
11294+/* ---------------------------------------------------------------------- */
11295+
11296+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
11297+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 11298+{
4a4d8108
AM
11299+ int err, len;
11300+ unsigned int flags[AuHnLast];
11301+ unsigned char isdir, isroot, wh;
11302+ struct inode *dir;
11303+ struct au_hnotify_args *args;
11304+ char *p, *h_child_name;
dece6358 11305+
1308ab2a 11306+ err = 0;
4a4d8108
AM
11307+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
11308+ dir = igrab(hnotify->hn_aufs_inode);
11309+ if (!dir)
11310+ goto out;
1facf9fc 11311+
4a4d8108
AM
11312+ isroot = (dir->i_ino == AUFS_ROOT_INO);
11313+ wh = 0;
11314+ h_child_name = (void *)h_child_qstr->name;
11315+ len = h_child_qstr->len;
11316+ if (h_child_name) {
11317+ if (len > AUFS_WH_PFX_LEN
11318+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
11319+ h_child_name += AUFS_WH_PFX_LEN;
11320+ len -= AUFS_WH_PFX_LEN;
11321+ wh = 1;
11322+ }
1facf9fc 11323+ }
dece6358 11324+
4a4d8108
AM
11325+ isdir = 0;
11326+ if (h_child_inode)
11327+ isdir = !!S_ISDIR(h_child_inode->i_mode);
11328+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
11329+ flags[AuHn_CHILD] = 0;
11330+ if (isdir)
11331+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
11332+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
11333+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
11334+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
11335+ case FS_MOVED_FROM:
11336+ case FS_MOVED_TO:
11337+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
11338+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11339+ /*FALLTHROUGH*/
11340+ case FS_CREATE:
11341+ AuDebugOn(!h_child_name || !h_child_inode);
11342+ break;
1facf9fc 11343+
4a4d8108
AM
11344+ case FS_DELETE:
11345+ /*
11346+ * aufs never be able to get this child inode.
11347+ * revalidation should be in d_revalidate()
11348+ * by checking i_nlink, i_generation or d_unhashed().
11349+ */
11350+ AuDebugOn(!h_child_name);
11351+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
11352+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11353+ break;
dece6358 11354+
4a4d8108
AM
11355+ default:
11356+ AuDebugOn(1);
11357+ }
1308ab2a 11358+
4a4d8108
AM
11359+ if (wh)
11360+ h_child_inode = NULL;
1308ab2a 11361+
4a4d8108
AM
11362+ err = -ENOMEM;
11363+ /* iput() and kfree() will be called in au_hnotify() */
11364+ /*
11365+ * inotify_mutex is already acquired and kmalloc/prune_icache may lock
11366+ * iprune_mutex. strange.
11367+ */
11368+ /* lockdep_off(); */
11369+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
11370+ /* lockdep_on(); */
11371+ if (unlikely(!args)) {
11372+ AuErr1("no memory\n");
11373+ iput(dir);
11374+ goto out;
11375+ }
11376+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
11377+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
11378+ args->mask = mask;
11379+ args->dir = dir;
11380+ args->h_dir = igrab(h_dir);
11381+ if (h_child_inode)
11382+ h_child_inode = igrab(h_child_inode); /* can be NULL */
11383+ args->h_child_inode = h_child_inode;
11384+ args->h_child_nlen = len;
11385+ if (len) {
11386+ p = (void *)args;
11387+ p += sizeof(*args);
11388+ memcpy(p, h_child_name, len);
11389+ p[len] = 0;
1308ab2a 11390+ }
1308ab2a 11391+
4a4d8108
AM
11392+ /* lockdep_off(); */
11393+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
11394+ /* lockdep_on(); */
11395+ if (unlikely(err)) {
11396+ pr_err("wkq %d\n", err);
11397+ iput(args->h_child_inode);
11398+ iput(args->h_dir);
11399+ iput(args->dir);
11400+ kfree(args);
1facf9fc 11401+ }
1facf9fc 11402+
4a4d8108 11403+out:
1facf9fc 11404+ return err;
11405+}
11406+
4a4d8108
AM
11407+static void au_hn_destroy_cache(void)
11408+{
11409+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
11410+ au_cachep[AuCache_HNOTIFY] = NULL;
11411+}
1308ab2a 11412+
4a4d8108 11413+int __init au_hnotify_init(void)
1facf9fc 11414+{
1308ab2a 11415+ int err;
1308ab2a 11416+
4a4d8108
AM
11417+ err = -ENOMEM;
11418+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
11419+ if (au_cachep[AuCache_HNOTIFY]) {
11420+ err = au_hnotify_op.init();
11421+ if (unlikely(err))
11422+ au_hn_destroy_cache();
1308ab2a 11423+ }
1308ab2a 11424+ AuTraceErr(err);
4a4d8108 11425+ return err;
1308ab2a 11426+}
11427+
4a4d8108 11428+void au_hnotify_fin(void)
1308ab2a 11429+{
4a4d8108
AM
11430+ au_hnotify_op.fin();
11431+ /* cf. au_cache_fin() */
11432+ if (au_cachep[AuCache_HNOTIFY])
11433+ au_hn_destroy_cache();
dece6358 11434+}
4a4d8108
AM
11435diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/iinfo.c linux-2.6.34/fs/aufs/iinfo.c
11436--- linux-2.6.34.org/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
11437+++ linux-2.6.34/fs/aufs/iinfo.c 2010-05-31 22:15:32.000000000 +0200
11438@@ -0,0 +1,277 @@
dece6358 11439+/*
4a4d8108 11440+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
11441+ *
11442+ * This program, aufs is free software; you can redistribute it and/or modify
11443+ * it under the terms of the GNU General Public License as published by
11444+ * the Free Software Foundation; either version 2 of the License, or
11445+ * (at your option) any later version.
11446+ *
11447+ * This program is distributed in the hope that it will be useful,
11448+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11449+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11450+ * GNU General Public License for more details.
11451+ *
11452+ * You should have received a copy of the GNU General Public License
11453+ * along with this program; if not, write to the Free Software
11454+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11455+ */
1facf9fc 11456+
dece6358 11457+/*
4a4d8108 11458+ * inode private data
dece6358 11459+ */
1facf9fc 11460+
1308ab2a 11461+#include "aufs.h"
1facf9fc 11462+
4a4d8108 11463+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 11464+{
4a4d8108 11465+ struct inode *h_inode;
1facf9fc 11466+
4a4d8108 11467+ IiMustAnyLock(inode);
1facf9fc 11468+
4a4d8108
AM
11469+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
11470+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11471+ return h_inode;
11472+}
1facf9fc 11473+
4a4d8108
AM
11474+/* todo: hard/soft set? */
11475+void au_hiput(struct au_hinode *hinode)
11476+{
11477+ au_hn_free(hinode);
11478+ dput(hinode->hi_whdentry);
11479+ iput(hinode->hi_inode);
11480+}
1facf9fc 11481+
4a4d8108
AM
11482+unsigned int au_hi_flags(struct inode *inode, int isdir)
11483+{
11484+ unsigned int flags;
11485+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 11486+
4a4d8108
AM
11487+ flags = 0;
11488+ if (au_opt_test(mnt_flags, XINO))
11489+ au_fset_hi(flags, XINO);
11490+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
11491+ au_fset_hi(flags, HNOTIFY);
11492+ return flags;
1facf9fc 11493+}
11494+
4a4d8108
AM
11495+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
11496+ struct inode *h_inode, unsigned int flags)
1308ab2a 11497+{
4a4d8108
AM
11498+ struct au_hinode *hinode;
11499+ struct inode *hi;
11500+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 11501+
4a4d8108 11502+ IiMustWriteLock(inode);
dece6358 11503+
4a4d8108
AM
11504+ hinode = iinfo->ii_hinode + bindex;
11505+ hi = hinode->hi_inode;
11506+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11507+
11508+ if (hi)
11509+ au_hiput(hinode);
11510+ hinode->hi_inode = h_inode;
11511+ if (h_inode) {
11512+ int err;
11513+ struct super_block *sb = inode->i_sb;
11514+ struct au_branch *br;
11515+
11516+ if (bindex == iinfo->ii_bstart)
11517+ au_cpup_igen(inode, h_inode);
11518+ br = au_sbr(sb, bindex);
11519+ hinode->hi_id = br->br_id;
11520+ if (au_ftest_hi(flags, XINO)) {
11521+ err = au_xino_write(sb, bindex, h_inode->i_ino,
11522+ inode->i_ino);
11523+ if (unlikely(err))
11524+ AuIOErr1("failed au_xino_write() %d\n", err);
11525+ }
11526+
11527+ if (au_ftest_hi(flags, HNOTIFY)
11528+ && au_br_hnotifyable(br->br_perm)) {
11529+ err = au_hn_alloc(hinode, inode, h_inode);
11530+ if (unlikely(err))
11531+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 11532+ }
11533+ }
4a4d8108 11534+}
dece6358 11535+
4a4d8108
AM
11536+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
11537+ struct dentry *h_wh)
11538+{
11539+ struct au_hinode *hinode;
dece6358 11540+
4a4d8108
AM
11541+ IiMustWriteLock(inode);
11542+
11543+ hinode = au_ii(inode)->ii_hinode + bindex;
11544+ AuDebugOn(hinode->hi_whdentry);
11545+ hinode->hi_whdentry = h_wh;
1facf9fc 11546+}
11547+
4a4d8108 11548+void au_update_iigen(struct inode *inode)
1308ab2a 11549+{
4a4d8108
AM
11550+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
11551+ /* smp_mb(); */ /* atomic_set */
11552+}
1facf9fc 11553+
4a4d8108
AM
11554+/* it may be called at remount time, too */
11555+void au_update_ibrange(struct inode *inode, int do_put_zero)
11556+{
11557+ struct au_iinfo *iinfo;
1facf9fc 11558+
4a4d8108
AM
11559+ iinfo = au_ii(inode);
11560+ if (!iinfo || iinfo->ii_bstart < 0)
11561+ return;
1facf9fc 11562+
4a4d8108 11563+ IiMustWriteLock(inode);
1facf9fc 11564+
4a4d8108
AM
11565+ if (do_put_zero) {
11566+ aufs_bindex_t bindex;
1facf9fc 11567+
4a4d8108
AM
11568+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
11569+ bindex++) {
11570+ struct inode *h_i;
1facf9fc 11571+
4a4d8108
AM
11572+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
11573+ if (h_i && !h_i->i_nlink)
11574+ au_set_h_iptr(inode, bindex, NULL, 0);
11575+ }
11576+ }
1308ab2a 11577+
4a4d8108
AM
11578+ iinfo->ii_bstart = -1;
11579+ while (++iinfo->ii_bstart <= iinfo->ii_bend)
11580+ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
11581+ break;
11582+ if (iinfo->ii_bstart > iinfo->ii_bend) {
11583+ iinfo->ii_bstart = -1;
11584+ iinfo->ii_bend = -1;
11585+ return;
11586+ }
11587+
11588+ iinfo->ii_bend++;
11589+ while (0 <= --iinfo->ii_bend)
11590+ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
11591+ break;
11592+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
1308ab2a 11593+}
1facf9fc 11594+
dece6358 11595+/* ---------------------------------------------------------------------- */
1facf9fc 11596+
4a4d8108 11597+void au_icntnr_init_once(void *_c)
dece6358 11598+{
4a4d8108
AM
11599+ struct au_icntnr *c = _c;
11600+ struct au_iinfo *iinfo = &c->iinfo;
1facf9fc 11601+
4a4d8108
AM
11602+ au_rw_init(&iinfo->ii_rwsem);
11603+ inode_init_once(&c->vfs_inode);
11604+}
1facf9fc 11605+
4a4d8108
AM
11606+int au_iinfo_init(struct inode *inode)
11607+{
11608+ struct au_iinfo *iinfo;
11609+ struct super_block *sb;
11610+ int nbr, i;
1facf9fc 11611+
4a4d8108
AM
11612+ sb = inode->i_sb;
11613+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
11614+ nbr = au_sbend(sb) + 1;
11615+ if (unlikely(nbr <= 0))
11616+ nbr = 1;
11617+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
11618+ if (iinfo->ii_hinode) {
11619+ for (i = 0; i < nbr; i++)
11620+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 11621+
4a4d8108
AM
11622+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
11623+ /* smp_mb(); */ /* atomic_set */
11624+ iinfo->ii_bstart = -1;
11625+ iinfo->ii_bend = -1;
11626+ iinfo->ii_vdir = NULL;
11627+ return 0;
1308ab2a 11628+ }
4a4d8108
AM
11629+ return -ENOMEM;
11630+}
1facf9fc 11631+
4a4d8108
AM
11632+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
11633+{
11634+ int err, sz;
11635+ struct au_hinode *hip;
1facf9fc 11636+
4a4d8108
AM
11637+ AuRwMustWriteLock(&iinfo->ii_rwsem);
11638+
11639+ err = -ENOMEM;
11640+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
11641+ if (!sz)
11642+ sz = sizeof(*hip);
11643+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
11644+ if (hip) {
11645+ iinfo->ii_hinode = hip;
11646+ err = 0;
1308ab2a 11647+ }
4a4d8108 11648+
1308ab2a 11649+ return err;
1facf9fc 11650+}
11651+
4a4d8108
AM
11652+static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
11653+ ino_t ino)
1facf9fc 11654+{
4a4d8108
AM
11655+ int err;
11656+ aufs_bindex_t bindex;
11657+ unsigned char locked;
1facf9fc 11658+
4a4d8108
AM
11659+ err = 0;
11660+ locked = !!si_noflush_read_trylock(sb);
11661+ bindex = au_br_index(sb, hinode->hi_id);
11662+ if (bindex >= 0)
11663+ err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
11664+ /* error action? */
11665+ if (locked)
11666+ si_read_unlock(sb);
11667+ return err;
1facf9fc 11668+}
11669+
4a4d8108 11670+void au_iinfo_fin(struct inode *inode)
1facf9fc 11671+{
4a4d8108
AM
11672+ ino_t ino;
11673+ aufs_bindex_t bend;
11674+ unsigned char unlinked = !inode->i_nlink;
11675+ struct au_iinfo *iinfo;
11676+ struct au_hinode *hi;
11677+ struct super_block *sb;
1facf9fc 11678+
4a4d8108
AM
11679+ if (unlinked) {
11680+ int err = au_xigen_inc(inode);
11681+ if (unlikely(err))
11682+ AuWarn1("failed resetting i_generation, %d\n", err);
11683+ }
1308ab2a 11684+
4a4d8108
AM
11685+ iinfo = au_ii(inode);
11686+ /* bad_inode case */
11687+ if (!iinfo)
11688+ return;
1308ab2a 11689+
4a4d8108
AM
11690+ if (iinfo->ii_vdir)
11691+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 11692+
4a4d8108
AM
11693+ if (iinfo->ii_bstart >= 0) {
11694+ sb = inode->i_sb;
11695+ ino = 0;
11696+ if (unlinked)
11697+ ino = inode->i_ino;
11698+ hi = iinfo->ii_hinode + iinfo->ii_bstart;
11699+ bend = iinfo->ii_bend;
11700+ while (iinfo->ii_bstart++ <= bend) {
11701+ if (hi->hi_inode) {
11702+ if (unlinked || !hi->hi_inode->i_nlink) {
11703+ au_iinfo_write0(sb, hi, ino);
11704+ /* ignore this error */
11705+ ino = 0;
11706+ }
11707+ au_hiput(hi);
11708+ }
11709+ hi++;
11710+ }
11711+ }
1facf9fc 11712+
4a4d8108
AM
11713+ kfree(iinfo->ii_hinode);
11714+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 11715+}
4a4d8108
AM
11716diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/inode.c linux-2.6.34/fs/aufs/inode.c
11717--- linux-2.6.34.org/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
11718+++ linux-2.6.34/fs/aufs/inode.c 2010-05-31 22:15:32.000000000 +0200
11719@@ -0,0 +1,416 @@
11720+/*
11721+ * Copyright (C) 2005-2010 Junjiro R. Okajima
11722+ *
11723+ * This program, aufs is free software; you can redistribute it and/or modify
11724+ * it under the terms of the GNU General Public License as published by
11725+ * the Free Software Foundation; either version 2 of the License, or
11726+ * (at your option) any later version.
11727+ *
11728+ * This program is distributed in the hope that it will be useful,
11729+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11730+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11731+ * GNU General Public License for more details.
11732+ *
11733+ * You should have received a copy of the GNU General Public License
11734+ * along with this program; if not, write to the Free Software
11735+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11736+ */
1facf9fc 11737+
4a4d8108
AM
11738+/*
11739+ * inode functions
11740+ */
1facf9fc 11741+
4a4d8108 11742+#include "aufs.h"
1308ab2a 11743+
4a4d8108
AM
11744+struct inode *au_igrab(struct inode *inode)
11745+{
11746+ if (inode) {
11747+ AuDebugOn(!atomic_read(&inode->i_count));
11748+ atomic_inc_return(&inode->i_count);
1facf9fc 11749+ }
4a4d8108
AM
11750+ return inode;
11751+}
1facf9fc 11752+
4a4d8108
AM
11753+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
11754+{
11755+ au_cpup_attr_all(inode, /*force*/0);
11756+ au_update_iigen(inode);
11757+ if (do_version)
11758+ inode->i_version++;
dece6358 11759+}
1facf9fc 11760+
4a4d8108 11761+int au_refresh_hinode_self(struct inode *inode, int do_attr)
dece6358 11762+{
4a4d8108
AM
11763+ int err, e;
11764+ aufs_bindex_t bindex, new_bindex;
11765+ unsigned char update;
11766+ struct au_hinode *p, *q, tmp;
1308ab2a 11767+ struct super_block *sb;
4a4d8108 11768+ struct au_iinfo *iinfo;
1facf9fc 11769+
4a4d8108 11770+ IiMustWriteLock(inode);
1facf9fc 11771+
4a4d8108
AM
11772+ update = 0;
11773+ sb = inode->i_sb;
11774+ iinfo = au_ii(inode);
11775+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
11776+ if (unlikely(err))
1308ab2a 11777+ goto out;
1facf9fc 11778+
4a4d8108
AM
11779+ p = iinfo->ii_hinode + iinfo->ii_bstart;
11780+ err = 0;
11781+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
11782+ bindex++, p++) {
11783+ if (!p->hi_inode)
11784+ continue;
1facf9fc 11785+
4a4d8108
AM
11786+ new_bindex = au_br_index(sb, p->hi_id);
11787+ if (new_bindex == bindex)
11788+ continue;
1facf9fc 11789+
4a4d8108
AM
11790+ if (new_bindex < 0) {
11791+ update = 1;
11792+ au_hiput(p);
11793+ p->hi_inode = NULL;
11794+ continue;
1308ab2a 11795+ }
4a4d8108
AM
11796+
11797+ if (new_bindex < iinfo->ii_bstart)
11798+ iinfo->ii_bstart = new_bindex;
11799+ if (iinfo->ii_bend < new_bindex)
11800+ iinfo->ii_bend = new_bindex;
11801+ /* swap two lower inode, and loop again */
11802+ q = iinfo->ii_hinode + new_bindex;
11803+ tmp = *q;
11804+ *q = *p;
11805+ *p = tmp;
11806+ if (tmp.hi_inode) {
11807+ bindex--;
11808+ p--;
1308ab2a 11809+ }
11810+ }
4a4d8108
AM
11811+ au_update_ibrange(inode, /*do_put_zero*/0);
11812+ e = au_dy_irefresh(inode);
11813+ if (unlikely(e && !err))
11814+ err = e;
11815+ if (do_attr)
11816+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
1facf9fc 11817+
4a4d8108
AM
11818+ out:
11819+ return err;
11820+}
1facf9fc 11821+
4a4d8108
AM
11822+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
11823+{
11824+ int err, e;
11825+ unsigned int flags;
11826+ aufs_bindex_t bindex, bend;
11827+ unsigned char isdir, update;
11828+ struct au_hinode *p;
11829+ struct au_iinfo *iinfo;
1facf9fc 11830+
4a4d8108
AM
11831+ err = au_refresh_hinode_self(inode, /*do_attr*/0);
11832+ if (unlikely(err))
11833+ goto out;
11834+
11835+ update = 0;
11836+ iinfo = au_ii(inode);
11837+ p = iinfo->ii_hinode + iinfo->ii_bstart;
11838+ isdir = S_ISDIR(inode->i_mode);
11839+ flags = au_hi_flags(inode, isdir);
11840+ bend = au_dbend(dentry);
11841+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
11842+ struct inode *h_i;
11843+ struct dentry *h_d;
11844+
11845+ h_d = au_h_dptr(dentry, bindex);
11846+ if (!h_d || !h_d->d_inode)
11847+ continue;
11848+
11849+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
11850+ h_i = au_h_iptr(inode, bindex);
11851+ if (h_i) {
11852+ if (h_i == h_d->d_inode)
11853+ continue;
11854+ err = -EIO;
11855+ break;
11856+ }
11857+ }
11858+ if (bindex < iinfo->ii_bstart)
11859+ iinfo->ii_bstart = bindex;
11860+ if (iinfo->ii_bend < bindex)
11861+ iinfo->ii_bend = bindex;
11862+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
11863+ update = 1;
1308ab2a 11864+ }
4a4d8108
AM
11865+ au_update_ibrange(inode, /*do_put_zero*/0);
11866+ e = au_dy_irefresh(inode);
11867+ if (unlikely(e && !err))
11868+ err = e;
11869+ au_refresh_hinode_attr(inode, update && isdir);
11870+
1308ab2a 11871+ out:
4a4d8108 11872+ AuTraceErr(err);
1308ab2a 11873+ return err;
dece6358
AM
11874+}
11875+
4a4d8108 11876+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 11877+{
4a4d8108
AM
11878+ int err;
11879+ unsigned int flags;
11880+ umode_t mode;
11881+ aufs_bindex_t bindex, bstart, btail;
11882+ unsigned char isdir;
11883+ struct dentry *h_dentry;
11884+ struct inode *h_inode;
11885+ struct au_iinfo *iinfo;
dece6358 11886+
4a4d8108 11887+ IiMustWriteLock(inode);
dece6358 11888+
4a4d8108
AM
11889+ err = 0;
11890+ isdir = 0;
11891+ bstart = au_dbstart(dentry);
11892+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
11893+ mode = h_inode->i_mode;
11894+ switch (mode & S_IFMT) {
11895+ case S_IFREG:
11896+ btail = au_dbtail(dentry);
11897+ inode->i_op = &aufs_iop;
11898+ inode->i_fop = &aufs_file_fop;
11899+ err = au_dy_iaop(inode, bstart, h_inode);
11900+ if (unlikely(err))
11901+ goto out;
11902+ break;
11903+ case S_IFDIR:
11904+ isdir = 1;
11905+ btail = au_dbtaildir(dentry);
11906+ inode->i_op = &aufs_dir_iop;
11907+ inode->i_fop = &aufs_dir_fop;
11908+ break;
11909+ case S_IFLNK:
11910+ btail = au_dbtail(dentry);
11911+ inode->i_op = &aufs_symlink_iop;
11912+ break;
11913+ case S_IFBLK:
11914+ case S_IFCHR:
11915+ case S_IFIFO:
11916+ case S_IFSOCK:
11917+ btail = au_dbtail(dentry);
11918+ inode->i_op = &aufs_iop;
11919+ au_init_special_fop(inode, mode, h_inode->i_rdev);
11920+ break;
11921+ default:
11922+ AuIOErr("Unknown file type 0%o\n", mode);
11923+ err = -EIO;
1308ab2a 11924+ goto out;
4a4d8108 11925+ }
dece6358 11926+
4a4d8108
AM
11927+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
11928+ flags = au_hi_flags(inode, isdir);
11929+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
11930+ && au_ftest_hi(flags, HNOTIFY)
11931+ && dentry->d_name.len > AUFS_WH_PFX_LEN
11932+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
11933+ au_fclr_hi(flags, HNOTIFY);
11934+ iinfo = au_ii(inode);
11935+ iinfo->ii_bstart = bstart;
11936+ iinfo->ii_bend = btail;
11937+ for (bindex = bstart; bindex <= btail; bindex++) {
11938+ h_dentry = au_h_dptr(dentry, bindex);
11939+ if (h_dentry)
11940+ au_set_h_iptr(inode, bindex,
11941+ au_igrab(h_dentry->d_inode), flags);
11942+ }
11943+ au_cpup_attr_all(inode, /*force*/1);
dece6358 11944+
4a4d8108
AM
11945+ out:
11946+ return err;
11947+}
dece6358 11948+
4a4d8108
AM
11949+/* successful returns with iinfo write_locked */
11950+static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
11951+{
11952+ int err;
11953+ aufs_bindex_t bindex, bend;
11954+ struct inode *h_inode, *h_dinode;
dece6358 11955+
4a4d8108 11956+ *matched = 0;
dece6358 11957+
4a4d8108
AM
11958+ /*
11959+ * before this function, if aufs got any iinfo lock, it must be only
11960+ * one, the parent dir.
11961+ * it can happen by UDBA and the obsoleted inode number.
11962+ */
11963+ err = -EIO;
11964+ if (unlikely(inode->i_ino == parent_ino(dentry)))
11965+ goto out;
11966+
11967+ err = 0;
11968+ ii_write_lock_new_child(inode);
11969+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
11970+ bend = au_ibend(inode);
11971+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
11972+ h_inode = au_h_iptr(inode, bindex);
11973+ if (h_inode && h_inode == h_dinode) {
11974+ *matched = 1;
11975+ err = 0;
11976+ if (au_iigen(inode) != au_digen(dentry))
11977+ err = au_refresh_hinode(inode, dentry);
11978+ break;
1308ab2a 11979+ }
1facf9fc 11980+ }
dece6358 11981+
4a4d8108
AM
11982+ if (unlikely(err))
11983+ ii_write_unlock(inode);
1facf9fc 11984+ out:
1facf9fc 11985+ return err;
11986+}
1facf9fc 11987+
4a4d8108
AM
11988+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
11989+ unsigned int d_type, ino_t *ino)
1facf9fc 11990+{
4a4d8108
AM
11991+ int err;
11992+ struct mutex *mtx;
11993+ const int isdir = (d_type == DT_DIR);
1facf9fc 11994+
4a4d8108
AM
11995+ /* prevent hardlinks from race condition */
11996+ mtx = NULL;
11997+ if (!isdir) {
11998+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
11999+ mutex_lock(mtx);
12000+ }
12001+ err = au_xino_read(sb, bindex, h_ino, ino);
12002+ if (unlikely(err))
12003+ goto out;
1308ab2a 12004+
4a4d8108
AM
12005+ if (!*ino) {
12006+ err = -EIO;
12007+ *ino = au_xino_new_ino(sb);
12008+ if (unlikely(!*ino))
1facf9fc 12009+ goto out;
4a4d8108
AM
12010+ err = au_xino_write(sb, bindex, h_ino, *ino);
12011+ if (unlikely(err))
1308ab2a 12012+ goto out;
1308ab2a 12013+ }
1facf9fc 12014+
12015+ out:
4a4d8108
AM
12016+ if (!isdir)
12017+ mutex_unlock(mtx);
1facf9fc 12018+ return err;
12019+}
12020+
4a4d8108
AM
12021+/* successful returns with iinfo write_locked */
12022+/* todo: return with unlocked? */
12023+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 12024+{
4a4d8108
AM
12025+ struct inode *inode;
12026+ struct dentry *h_dentry;
12027+ struct super_block *sb;
12028+ ino_t h_ino, ino;
12029+ int err, match;
12030+ aufs_bindex_t bstart;
1facf9fc 12031+
4a4d8108
AM
12032+ sb = dentry->d_sb;
12033+ bstart = au_dbstart(dentry);
12034+ h_dentry = au_h_dptr(dentry, bstart);
12035+ h_ino = h_dentry->d_inode->i_ino;
12036+ err = au_xino_read(sb, bstart, h_ino, &ino);
12037+ inode = ERR_PTR(err);
12038+ if (unlikely(err))
12039+ goto out;
12040+ new_ino:
12041+ if (!ino) {
12042+ ino = au_xino_new_ino(sb);
12043+ if (unlikely(!ino)) {
12044+ inode = ERR_PTR(-EIO);
dece6358
AM
12045+ goto out;
12046+ }
12047+ }
1facf9fc 12048+
4a4d8108
AM
12049+ AuDbg("i%lu\n", (unsigned long)ino);
12050+ inode = au_iget_locked(sb, ino);
12051+ err = PTR_ERR(inode);
12052+ if (IS_ERR(inode))
1facf9fc 12053+ goto out;
1facf9fc 12054+
4a4d8108
AM
12055+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
12056+ if (inode->i_state & I_NEW) {
12057+ ii_write_lock_new_child(inode);
12058+ err = set_inode(inode, dentry);
12059+ if (!err) {
12060+ unlock_new_inode(inode);
12061+ goto out; /* success */
12062+ }
1308ab2a 12063+
4a4d8108
AM
12064+ ii_write_unlock(inode);
12065+ iget_failed(inode);
12066+ goto out_err;
12067+ } else if (!must_new) {
12068+ err = reval_inode(inode, dentry, &match);
12069+ if (!err)
12070+ goto out; /* success */
12071+ else if (match)
12072+ goto out_iput;
12073+ }
12074+
12075+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
12076+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
12077+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
12078+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
12079+ (unsigned long)h_ino, (unsigned long)ino);
12080+ ino = 0;
12081+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
12082+ if (!err) {
12083+ iput(inode);
12084+ goto new_ino;
12085+ }
1308ab2a 12086+
4a4d8108
AM
12087+ out_iput:
12088+ iput(inode);
12089+ out_err:
12090+ inode = ERR_PTR(err);
1facf9fc 12091+ out:
4a4d8108 12092+ return inode;
1facf9fc 12093+}
12094+
4a4d8108 12095+/* ---------------------------------------------------------------------- */
1facf9fc 12096+
4a4d8108
AM
12097+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12098+ struct inode *inode)
12099+{
12100+ int err;
1facf9fc 12101+
4a4d8108 12102+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 12103+
4a4d8108
AM
12104+ /* pseudo-link after flushed may happen out of bounds */
12105+ if (!err
12106+ && inode
12107+ && au_ibstart(inode) <= bindex
12108+ && bindex <= au_ibend(inode)) {
12109+ /*
12110+ * permission check is unnecessary since vfsub routine
12111+ * will be called later
12112+ */
12113+ struct inode *hi = au_h_iptr(inode, bindex);
12114+ if (hi)
12115+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 12116+ }
12117+
4a4d8108
AM
12118+ return err;
12119+}
dece6358 12120+
4a4d8108
AM
12121+int au_test_h_perm(struct inode *h_inode, int mask)
12122+{
12123+ if (!current_fsuid())
12124+ return 0;
12125+ return inode_permission(h_inode, mask);
12126+}
1facf9fc 12127+
4a4d8108
AM
12128+int au_test_h_perm_sio(struct inode *h_inode, int mask)
12129+{
12130+ if (au_test_nfs(h_inode->i_sb)
12131+ && (mask & MAY_WRITE)
12132+ && S_ISDIR(h_inode->i_mode))
12133+ mask |= MAY_READ; /* force permission check */
12134+ return au_test_h_perm(h_inode, mask);
1facf9fc 12135+}
4a4d8108
AM
12136diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/inode.h linux-2.6.34/fs/aufs/inode.h
12137--- linux-2.6.34.org/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
12138+++ linux-2.6.34/fs/aufs/inode.h 2010-05-31 22:15:32.000000000 +0200
12139@@ -0,0 +1,498 @@
12140+/*
12141+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12142+ *
12143+ * This program, aufs is free software; you can redistribute it and/or modify
12144+ * it under the terms of the GNU General Public License as published by
12145+ * the Free Software Foundation; either version 2 of the License, or
12146+ * (at your option) any later version.
12147+ *
12148+ * This program is distributed in the hope that it will be useful,
12149+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12150+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12151+ * GNU General Public License for more details.
12152+ *
12153+ * You should have received a copy of the GNU General Public License
12154+ * along with this program; if not, write to the Free Software
12155+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12156+ */
1facf9fc 12157+
1308ab2a 12158+/*
4a4d8108 12159+ * inode operations
1308ab2a 12160+ */
dece6358 12161+
4a4d8108
AM
12162+#ifndef __AUFS_INODE_H__
12163+#define __AUFS_INODE_H__
dece6358 12164+
4a4d8108 12165+#ifdef __KERNEL__
1308ab2a 12166+
4a4d8108
AM
12167+#include <linux/fs.h>
12168+#include <linux/fsnotify.h>
12169+#include <linux/aufs_type.h>
12170+#include "rwsem.h"
1308ab2a 12171+
4a4d8108 12172+struct vfsmount;
1facf9fc 12173+
4a4d8108
AM
12174+struct au_hnotify {
12175+#ifdef CONFIG_AUFS_HNOTIFY
12176+#ifdef CONFIG_AUFS_HFSNOTIFY
12177+ struct fsnotify_mark_entry hn_entry;
12178+#else
12179+ struct inotify_watch hn_watch;
12180+#endif
12181+ struct inode *hn_aufs_inode; /* no get/put */
12182+#endif
12183+} ____cacheline_aligned_in_smp;
1facf9fc 12184+
4a4d8108
AM
12185+struct au_hinode {
12186+ struct inode *hi_inode;
12187+ aufs_bindex_t hi_id;
12188+#ifdef CONFIG_AUFS_HNOTIFY
12189+ struct au_hnotify *hi_notify;
12190+#endif
dece6358 12191+
4a4d8108
AM
12192+ /* reference to the copied-up whiteout with get/put */
12193+ struct dentry *hi_whdentry;
12194+};
dece6358 12195+
4a4d8108
AM
12196+struct au_vdir;
12197+struct au_iinfo {
12198+ atomic_t ii_generation;
12199+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 12200+
4a4d8108
AM
12201+ struct au_rwsem ii_rwsem;
12202+ aufs_bindex_t ii_bstart, ii_bend;
12203+ __u32 ii_higen;
12204+ struct au_hinode *ii_hinode;
12205+ struct au_vdir *ii_vdir;
12206+};
1facf9fc 12207+
4a4d8108
AM
12208+struct au_icntnr {
12209+ struct au_iinfo iinfo;
12210+ struct inode vfs_inode;
12211+} ____cacheline_aligned_in_smp;
1308ab2a 12212+
4a4d8108
AM
12213+/* au_pin flags */
12214+#define AuPin_DI_LOCKED 1
12215+#define AuPin_MNT_WRITE (1 << 1)
12216+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
12217+#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
12218+#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
12219+
12220+struct au_pin {
12221+ /* input */
12222+ struct dentry *dentry;
12223+ unsigned int udba;
12224+ unsigned char lsc_di, lsc_hi, flags;
12225+ aufs_bindex_t bindex;
12226+
12227+ /* output */
12228+ struct dentry *parent;
12229+ struct au_hinode *hdir;
12230+ struct vfsmount *h_mnt;
12231+};
1facf9fc 12232+
1308ab2a 12233+/* ---------------------------------------------------------------------- */
12234+
4a4d8108 12235+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 12236+{
4a4d8108 12237+ struct au_iinfo *iinfo;
1facf9fc 12238+
4a4d8108
AM
12239+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12240+ if (iinfo->ii_hinode)
12241+ return iinfo;
12242+ return NULL; /* debugging bad_inode case */
12243+}
1facf9fc 12244+
4a4d8108 12245+/* ---------------------------------------------------------------------- */
1facf9fc 12246+
4a4d8108
AM
12247+/* inode.c */
12248+struct inode *au_igrab(struct inode *inode);
12249+int au_refresh_hinode_self(struct inode *inode, int do_attr);
12250+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
12251+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12252+ unsigned int d_type, ino_t *ino);
12253+struct inode *au_new_inode(struct dentry *dentry, int must_new);
12254+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12255+ struct inode *inode);
12256+int au_test_h_perm(struct inode *h_inode, int mask);
12257+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 12258+
4a4d8108
AM
12259+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
12260+ ino_t h_ino, unsigned int d_type, ino_t *ino)
12261+{
12262+#ifdef CONFIG_AUFS_SHWH
12263+ return au_ino(sb, bindex, h_ino, d_type, ino);
12264+#else
12265+ return 0;
12266+#endif
12267+}
1facf9fc 12268+
4a4d8108
AM
12269+/* i_op.c */
12270+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 12271+
4a4d8108
AM
12272+/* au_wr_dir flags */
12273+#define AuWrDir_ADD_ENTRY 1
12274+#define AuWrDir_ISDIR (1 << 1)
12275+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
12276+#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
12277+#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
1facf9fc 12278+
4a4d8108
AM
12279+struct au_wr_dir_args {
12280+ aufs_bindex_t force_btgt;
12281+ unsigned char flags;
12282+};
12283+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
12284+ struct au_wr_dir_args *args);
dece6358 12285+
4a4d8108
AM
12286+struct dentry *au_pinned_h_parent(struct au_pin *pin);
12287+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
12288+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
12289+ unsigned int udba, unsigned char flags);
12290+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
12291+ unsigned int udba, unsigned char flags) __must_check;
12292+int au_do_pin(struct au_pin *pin) __must_check;
12293+void au_unpin(struct au_pin *pin);
1facf9fc 12294+
4a4d8108
AM
12295+/* i_op_add.c */
12296+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
12297+ struct dentry *h_parent, int isdir);
12298+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
12299+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
12300+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
12301+ struct nameidata *nd);
12302+int aufs_link(struct dentry *src_dentry, struct inode *dir,
12303+ struct dentry *dentry);
12304+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
1facf9fc 12305+
4a4d8108
AM
12306+/* i_op_del.c */
12307+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
12308+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
12309+ struct dentry *h_parent, int isdir);
12310+int aufs_unlink(struct inode *dir, struct dentry *dentry);
12311+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 12312+
4a4d8108
AM
12313+/* i_op_ren.c */
12314+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
12315+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
12316+ struct inode *dir, struct dentry *dentry);
1facf9fc 12317+
4a4d8108
AM
12318+/* iinfo.c */
12319+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
12320+void au_hiput(struct au_hinode *hinode);
12321+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12322+ struct dentry *h_wh);
12323+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 12324+
4a4d8108
AM
12325+/* hinode flags */
12326+#define AuHi_XINO 1
12327+#define AuHi_HNOTIFY (1 << 1)
12328+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
12329+#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; }
12330+#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; }
1facf9fc 12331+
4a4d8108
AM
12332+#ifndef CONFIG_AUFS_HNOTIFY
12333+#undef AuHi_HNOTIFY
12334+#define AuHi_HNOTIFY 0
12335+#endif
1facf9fc 12336+
4a4d8108
AM
12337+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12338+ struct inode *h_inode, unsigned int flags);
1facf9fc 12339+
4a4d8108
AM
12340+void au_update_iigen(struct inode *inode);
12341+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 12342+
4a4d8108
AM
12343+void au_icntnr_init_once(void *_c);
12344+int au_iinfo_init(struct inode *inode);
12345+void au_iinfo_fin(struct inode *inode);
12346+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 12347+
4a4d8108
AM
12348+/* plink.c */
12349+void au_plink_maint_block(struct super_block *sb);
12350+void au_plink_maint_leave(struct file *file);
12351+#ifdef CONFIG_AUFS_DEBUG
12352+void au_plink_list(struct super_block *sb);
12353+#else
12354+AuStubVoid(au_plink_list, struct super_block *sb)
12355+#endif
12356+int au_plink_test(struct inode *inode);
12357+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
12358+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
12359+ struct dentry *h_dentry);
12360+void au_plink_put(struct super_block *sb);
12361+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
12362+long au_plink_ioctl(struct file *file, unsigned int cmd);
1facf9fc 12363+
4a4d8108 12364+/* ---------------------------------------------------------------------- */
1308ab2a 12365+
4a4d8108
AM
12366+/* lock subclass for iinfo */
12367+enum {
12368+ AuLsc_II_CHILD, /* child first */
12369+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
12370+ AuLsc_II_CHILD3, /* copyup dirs */
12371+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
12372+ AuLsc_II_PARENT2,
12373+ AuLsc_II_PARENT3, /* copyup dirs */
12374+ AuLsc_II_NEW_CHILD
12375+};
1308ab2a 12376+
1facf9fc 12377+/*
4a4d8108
AM
12378+ * ii_read_lock_child, ii_write_lock_child,
12379+ * ii_read_lock_child2, ii_write_lock_child2,
12380+ * ii_read_lock_child3, ii_write_lock_child3,
12381+ * ii_read_lock_parent, ii_write_lock_parent,
12382+ * ii_read_lock_parent2, ii_write_lock_parent2,
12383+ * ii_read_lock_parent3, ii_write_lock_parent3,
12384+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 12385+ */
4a4d8108
AM
12386+#define AuReadLockFunc(name, lsc) \
12387+static inline void ii_read_lock_##name(struct inode *i) \
12388+{ \
12389+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12390+}
12391+
12392+#define AuWriteLockFunc(name, lsc) \
12393+static inline void ii_write_lock_##name(struct inode *i) \
12394+{ \
12395+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12396+}
12397+
12398+#define AuRWLockFuncs(name, lsc) \
12399+ AuReadLockFunc(name, lsc) \
12400+ AuWriteLockFunc(name, lsc)
12401+
12402+AuRWLockFuncs(child, CHILD);
12403+AuRWLockFuncs(child2, CHILD2);
12404+AuRWLockFuncs(child3, CHILD3);
12405+AuRWLockFuncs(parent, PARENT);
12406+AuRWLockFuncs(parent2, PARENT2);
12407+AuRWLockFuncs(parent3, PARENT3);
12408+AuRWLockFuncs(new_child, NEW_CHILD);
12409+
12410+#undef AuReadLockFunc
12411+#undef AuWriteLockFunc
12412+#undef AuRWLockFuncs
1facf9fc 12413+
12414+/*
4a4d8108 12415+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 12416+ */
4a4d8108 12417+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 12418+
4a4d8108
AM
12419+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
12420+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
12421+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 12422+
4a4d8108 12423+/* ---------------------------------------------------------------------- */
1308ab2a 12424+
4a4d8108
AM
12425+static inline unsigned int au_iigen(struct inode *inode)
12426+{
12427+ return atomic_read(&au_ii(inode)->ii_generation);
12428+}
1308ab2a 12429+
4a4d8108
AM
12430+/* tiny test for inode number */
12431+/* tmpfs generation is too rough */
12432+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
12433+{
12434+ struct au_iinfo *iinfo;
1308ab2a 12435+
4a4d8108
AM
12436+ iinfo = au_ii(inode);
12437+ AuRwMustAnyLock(&iinfo->ii_rwsem);
12438+ return !(iinfo->ii_hsb1 == h_inode->i_sb
12439+ && iinfo->ii_higen == h_inode->i_generation);
12440+}
1308ab2a 12441+
4a4d8108
AM
12442+static inline void au_iigen_dec(struct inode *inode)
12443+{
12444+#ifdef CONFIG_AUFS_HNOTIFY
12445+ atomic_dec_return(&au_ii(inode)->ii_generation);
12446+#endif
12447+}
1308ab2a 12448+
4a4d8108 12449+/* ---------------------------------------------------------------------- */
1308ab2a 12450+
4a4d8108
AM
12451+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
12452+ aufs_bindex_t bindex)
12453+{
12454+ IiMustAnyLock(inode);
12455+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
12456+}
1308ab2a 12457+
4a4d8108
AM
12458+static inline aufs_bindex_t au_ibstart(struct inode *inode)
12459+{
12460+ IiMustAnyLock(inode);
12461+ return au_ii(inode)->ii_bstart;
12462+}
1308ab2a 12463+
4a4d8108
AM
12464+static inline aufs_bindex_t au_ibend(struct inode *inode)
12465+{
12466+ IiMustAnyLock(inode);
12467+ return au_ii(inode)->ii_bend;
12468+}
1308ab2a 12469+
4a4d8108
AM
12470+static inline struct au_vdir *au_ivdir(struct inode *inode)
12471+{
12472+ IiMustAnyLock(inode);
12473+ return au_ii(inode)->ii_vdir;
12474+}
1308ab2a 12475+
4a4d8108
AM
12476+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
12477+{
12478+ IiMustAnyLock(inode);
12479+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
12480+}
1308ab2a 12481+
4a4d8108 12482+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12483+{
4a4d8108
AM
12484+ IiMustWriteLock(inode);
12485+ au_ii(inode)->ii_bstart = bindex;
12486+}
1308ab2a 12487+
4a4d8108
AM
12488+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
12489+{
12490+ IiMustWriteLock(inode);
12491+ au_ii(inode)->ii_bend = bindex;
1308ab2a 12492+}
12493+
4a4d8108
AM
12494+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
12495+{
12496+ IiMustWriteLock(inode);
12497+ au_ii(inode)->ii_vdir = vdir;
12498+}
1facf9fc 12499+
4a4d8108 12500+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12501+{
4a4d8108
AM
12502+ IiMustAnyLock(inode);
12503+ return au_ii(inode)->ii_hinode + bindex;
12504+}
dece6358 12505+
4a4d8108 12506+/* ---------------------------------------------------------------------- */
1facf9fc 12507+
4a4d8108
AM
12508+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
12509+{
12510+ if (pin)
12511+ return pin->parent;
12512+ return NULL;
1facf9fc 12513+}
12514+
4a4d8108 12515+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 12516+{
4a4d8108
AM
12517+ if (pin && pin->hdir)
12518+ return pin->hdir->hi_inode;
12519+ return NULL;
1308ab2a 12520+}
1facf9fc 12521+
4a4d8108
AM
12522+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
12523+{
12524+ if (pin)
12525+ return pin->hdir;
12526+ return NULL;
12527+}
1facf9fc 12528+
4a4d8108 12529+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 12530+{
4a4d8108
AM
12531+ if (pin)
12532+ pin->dentry = dentry;
12533+}
1308ab2a 12534+
4a4d8108
AM
12535+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
12536+ unsigned char lflag)
12537+{
12538+ if (pin) {
12539+ /* dirty macros require brackets */
12540+ if (lflag) {
12541+ au_fset_pin(pin->flags, DI_LOCKED);
12542+ } else {
12543+ au_fclr_pin(pin->flags, DI_LOCKED);
12544+ }
1308ab2a 12545+ }
4a4d8108
AM
12546+}
12547+
12548+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
12549+{
12550+ if (pin) {
12551+ dput(pin->parent);
12552+ pin->parent = dget(parent);
1facf9fc 12553+ }
4a4d8108 12554+}
1facf9fc 12555+
4a4d8108
AM
12556+/* ---------------------------------------------------------------------- */
12557+
12558+#ifdef CONFIG_AUFS_HNOTIFY
12559+struct au_hnotify_op {
12560+ void (*ctl)(struct au_hinode *hinode, int do_set);
12561+ int (*alloc)(struct au_hnotify *hn, struct inode *h_inode);
12562+ void (*free)(struct au_hnotify *hn);
12563+
12564+ void (*fin)(void);
12565+ int (*init)(void);
12566+};
12567+
12568+/* hnotify.c */
12569+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
12570+ struct inode *h_inode);
12571+void au_hn_free(struct au_hinode *hinode);
12572+void au_hn_ctl(struct au_hinode *hinode, int do_set);
12573+void au_hn_reset(struct inode *inode, unsigned int flags);
12574+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
12575+ struct qstr *h_child_qstr, struct inode *h_child_inode);
12576+int __init au_hnotify_init(void);
12577+void au_hnotify_fin(void);
12578+
12579+/* hinotify.c */
12580+extern const struct au_hnotify_op au_hnotify_op;
12581+
12582+static inline
12583+void au_hn_init(struct au_hinode *hinode)
12584+{
12585+ hinode->hi_notify = NULL;
1308ab2a 12586+}
12587+
4a4d8108
AM
12588+#else
12589+static inline
12590+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
12591+ struct inode *inode __maybe_unused,
12592+ struct inode *h_inode __maybe_unused)
1308ab2a 12593+{
4a4d8108
AM
12594+ return -EOPNOTSUPP;
12595+}
1308ab2a 12596+
4a4d8108
AM
12597+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
12598+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
12599+ int do_set __maybe_unused)
12600+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
12601+ unsigned int flags __maybe_unused)
12602+AuStubInt0(__init au_hnotify_init, void)
12603+AuStubVoid(au_hnotify_fin, void)
12604+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
12605+#endif /* CONFIG_AUFS_HNOTIFY */
12606+
12607+static inline void au_hn_suspend(struct au_hinode *hdir)
12608+{
12609+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 12610+}
12611+
4a4d8108 12612+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 12613+{
4a4d8108
AM
12614+ au_hn_ctl(hdir, /*do_set*/1);
12615+}
1308ab2a 12616+
4a4d8108
AM
12617+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
12618+{
12619+ mutex_lock(&hdir->hi_inode->i_mutex);
12620+ au_hn_suspend(hdir);
12621+}
dece6358 12622+
4a4d8108
AM
12623+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
12624+ unsigned int sc __maybe_unused)
12625+{
12626+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
12627+ au_hn_suspend(hdir);
1facf9fc 12628+}
1facf9fc 12629+
4a4d8108
AM
12630+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
12631+{
12632+ au_hn_resume(hdir);
12633+ mutex_unlock(&hdir->hi_inode->i_mutex);
12634+}
12635+
12636+#endif /* __KERNEL__ */
12637+#endif /* __AUFS_INODE_H__ */
12638diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/ioctl.c linux-2.6.34/fs/aufs/ioctl.c
12639--- linux-2.6.34.org/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
12640+++ linux-2.6.34/fs/aufs/ioctl.c 2010-05-31 22:15:32.000000000 +0200
12641@@ -0,0 +1,126 @@
12642+/*
12643+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12644+ *
12645+ * This program, aufs is free software; you can redistribute it and/or modify
12646+ * it under the terms of the GNU General Public License as published by
12647+ * the Free Software Foundation; either version 2 of the License, or
12648+ * (at your option) any later version.
12649+ *
12650+ * This program is distributed in the hope that it will be useful,
12651+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12652+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12653+ * GNU General Public License for more details.
12654+ *
12655+ * You should have received a copy of the GNU General Public License
12656+ * along with this program; if not, write to the Free Software
12657+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12658+ */
12659+
12660+/*
12661+ * ioctl
12662+ * plink-management and readdir in userspace.
12663+ * assist the pathconf(3) wrapper library.
12664+ */
12665+
12666+#include <linux/file.h>
12667+#include "aufs.h"
12668+
12669+static int au_wbr_fd(struct path *path)
12670+{
12671+ int err, fd;
12672+ aufs_bindex_t wbi, bindex, bend;
12673+ struct file *h_file;
12674+ struct super_block *sb;
12675+ struct dentry *root;
12676+ struct au_branch *wbr;
12677+
12678+ err = get_unused_fd();
12679+ if (unlikely(err < 0))
12680+ goto out;
12681+ fd = err;
12682+
12683+ wbi = 0;
12684+ sb = path->dentry->d_sb;
12685+ root = sb->s_root;
12686+ aufs_read_lock(root, AuLock_IR);
12687+ wbr = au_sbr(sb, wbi);
12688+ if (!(path->mnt->mnt_flags & MNT_READONLY)
12689+ && !au_br_writable(wbr->br_perm)) {
12690+ bend = au_sbend(sb);
12691+ for (bindex = 1; bindex <= bend; bindex++) {
12692+ wbr = au_sbr(sb, bindex);
12693+ if (au_br_writable(wbr->br_perm)) {
12694+ wbi = bindex;
12695+ break;
12696+ }
12697+ }
12698+ wbr = au_sbr(sb, wbi);
12699+ }
12700+ AuDbg("wbi %d\n", wbi);
12701+ h_file = au_h_open(root, wbi, O_RDONLY | O_DIRECTORY | O_LARGEFILE,
12702+ NULL);
12703+ aufs_read_unlock(root, AuLock_IR);
12704+ err = PTR_ERR(h_file);
12705+ if (IS_ERR(h_file))
12706+ goto out_fd;
12707+
12708+ atomic_dec(&wbr->br_count); /* cf. au_h_open() */
12709+ fd_install(fd, h_file);
12710+ err = fd;
12711+ goto out; /* success */
12712+
12713+ out_fd:
12714+ put_unused_fd(fd);
12715+ out:
12716+ return err;
12717+}
12718+
12719+/* ---------------------------------------------------------------------- */
12720+
12721+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
12722+{
12723+ long err;
12724+
12725+ switch (cmd) {
12726+ case AUFS_CTL_PLINK_MAINT:
12727+ case AUFS_CTL_PLINK_CLEAN:
12728+ err = au_plink_ioctl(file, cmd);
12729+ break;
12730+
12731+ case AUFS_CTL_RDU:
12732+ case AUFS_CTL_RDU_INO:
12733+ err = au_rdu_ioctl(file, cmd, arg);
12734+ break;
12735+
12736+ case AUFS_CTL_WBR_FD:
12737+ err = au_wbr_fd(&file->f_path);
12738+ break;
12739+
12740+ default:
12741+ /* do not call the lower */
12742+ AuDbg("0x%x\n", cmd);
12743+ err = -ENOTTY;
12744+ }
12745+
12746+ AuTraceErr(err);
12747+ return err;
12748+}
12749+
12750+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
12751+{
12752+ long err;
12753+
12754+ switch (cmd) {
12755+ case AUFS_CTL_WBR_FD:
12756+ err = au_wbr_fd(&file->f_path);
12757+ break;
12758+
12759+ default:
12760+ /* do not call the lower */
12761+ AuDbg("0x%x\n", cmd);
12762+ err = -ENOTTY;
12763+ }
12764+
12765+ AuTraceErr(err);
12766+ return err;
12767+}
12768diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/i_op_add.c linux-2.6.34/fs/aufs/i_op_add.c
12769--- linux-2.6.34.org/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
12770+++ linux-2.6.34/fs/aufs/i_op_add.c 2010-05-31 22:15:32.000000000 +0200
12771@@ -0,0 +1,672 @@
12772+/*
12773+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12774+ *
12775+ * This program, aufs is free software; you can redistribute it and/or modify
12776+ * it under the terms of the GNU General Public License as published by
12777+ * the Free Software Foundation; either version 2 of the License, or
12778+ * (at your option) any later version.
12779+ *
12780+ * This program is distributed in the hope that it will be useful,
12781+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12782+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12783+ * GNU General Public License for more details.
12784+ *
12785+ * You should have received a copy of the GNU General Public License
12786+ * along with this program; if not, write to the Free Software
12787+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12788+ */
12789+
12790+/*
12791+ * inode operations (add entry)
12792+ */
12793+
12794+#include "aufs.h"
12795+
12796+/*
12797+ * final procedure of adding a new entry, except link(2).
12798+ * remove whiteout, instantiate, copyup the parent dir's times and size
12799+ * and update version.
12800+ * if it failed, re-create the removed whiteout.
12801+ */
12802+static int epilog(struct inode *dir, aufs_bindex_t bindex,
12803+ struct dentry *wh_dentry, struct dentry *dentry)
12804+{
12805+ int err, rerr;
12806+ aufs_bindex_t bwh;
12807+ struct path h_path;
12808+ struct inode *inode, *h_dir;
12809+ struct dentry *wh;
12810+
12811+ bwh = -1;
12812+ if (wh_dentry) {
12813+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
12814+ IMustLock(h_dir);
12815+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
12816+ bwh = au_dbwh(dentry);
12817+ h_path.dentry = wh_dentry;
12818+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
12819+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
12820+ dentry);
12821+ if (unlikely(err))
12822+ goto out;
12823+ }
12824+
12825+ inode = au_new_inode(dentry, /*must_new*/1);
12826+ if (!IS_ERR(inode)) {
12827+ d_instantiate(dentry, inode);
12828+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
12829+ IMustLock(dir);
12830+ if (au_ibstart(dir) == au_dbstart(dentry))
12831+ au_cpup_attr_timesizes(dir);
12832+ dir->i_version++;
12833+ return 0; /* success */
12834+ }
12835+
12836+ err = PTR_ERR(inode);
12837+ if (!wh_dentry)
12838+ goto out;
12839+
12840+ /* revert */
12841+ /* dir inode is locked */
12842+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
12843+ rerr = PTR_ERR(wh);
12844+ if (IS_ERR(wh)) {
12845+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
12846+ AuDLNPair(dentry), err, rerr);
12847+ err = -EIO;
12848+ } else
12849+ dput(wh);
12850+
12851+ out:
12852+ return err;
12853+}
12854+
12855+/*
12856+ * simple tests for the adding inode operations.
12857+ * following the checks in vfs, plus the parent-child relationship.
12858+ */
12859+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
12860+ struct dentry *h_parent, int isdir)
12861+{
12862+ int err;
12863+ umode_t h_mode;
12864+ struct dentry *h_dentry;
12865+ struct inode *h_inode;
12866+
12867+ err = -ENAMETOOLONG;
12868+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
12869+ goto out;
12870+
12871+ h_dentry = au_h_dptr(dentry, bindex);
12872+ h_inode = h_dentry->d_inode;
12873+ if (!dentry->d_inode) {
12874+ err = -EEXIST;
12875+ if (unlikely(h_inode))
12876+ goto out;
12877+ } else {
12878+ /* rename(2) case */
12879+ err = -EIO;
12880+ if (unlikely(!h_inode || !h_inode->i_nlink))
12881+ goto out;
12882+
12883+ h_mode = h_inode->i_mode;
12884+ if (!isdir) {
12885+ err = -EISDIR;
12886+ if (unlikely(S_ISDIR(h_mode)))
12887+ goto out;
12888+ } else if (unlikely(!S_ISDIR(h_mode))) {
12889+ err = -ENOTDIR;
12890+ goto out;
12891+ }
12892+ }
12893+
12894+ err = 0;
12895+ /* expected parent dir is locked */
12896+ if (unlikely(h_parent != h_dentry->d_parent))
12897+ err = -EIO;
12898+
12899+ out:
12900+ AuTraceErr(err);
12901+ return err;
12902+}
12903+
12904+/*
12905+ * initial procedure of adding a new entry.
12906+ * prepare writable branch and the parent dir, lock it,
12907+ * and lookup whiteout for the new entry.
12908+ */
12909+static struct dentry*
12910+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
12911+ struct dentry *src_dentry, struct au_pin *pin,
12912+ struct au_wr_dir_args *wr_dir_args)
12913+{
12914+ struct dentry *wh_dentry, *h_parent;
12915+ struct super_block *sb;
12916+ struct au_branch *br;
12917+ int err;
12918+ unsigned int udba;
12919+ aufs_bindex_t bcpup;
12920+
12921+ AuDbg("%.*s\n", AuDLNPair(dentry));
12922+
12923+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
12924+ bcpup = err;
12925+ wh_dentry = ERR_PTR(err);
12926+ if (unlikely(err < 0))
12927+ goto out;
12928+
12929+ sb = dentry->d_sb;
12930+ udba = au_opt_udba(sb);
12931+ err = au_pin(pin, dentry, bcpup, udba,
12932+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
12933+ wh_dentry = ERR_PTR(err);
12934+ if (unlikely(err))
12935+ goto out;
12936+
12937+ h_parent = au_pinned_h_parent(pin);
12938+ if (udba != AuOpt_UDBA_NONE
12939+ && au_dbstart(dentry) == bcpup)
12940+ err = au_may_add(dentry, bcpup, h_parent,
12941+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
12942+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
12943+ err = -ENAMETOOLONG;
12944+ wh_dentry = ERR_PTR(err);
12945+ if (unlikely(err))
12946+ goto out_unpin;
12947+
12948+ br = au_sbr(sb, bcpup);
12949+ if (dt) {
12950+ struct path tmp = {
12951+ .dentry = h_parent,
12952+ .mnt = br->br_mnt
12953+ };
12954+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
12955+ }
12956+
12957+ wh_dentry = NULL;
12958+ if (bcpup != au_dbwh(dentry))
12959+ goto out; /* success */
12960+
12961+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
12962+
12963+ out_unpin:
12964+ if (IS_ERR(wh_dentry))
12965+ au_unpin(pin);
12966+ out:
12967+ return wh_dentry;
12968+}
12969+
12970+/* ---------------------------------------------------------------------- */
12971+
12972+enum { Mknod, Symlink, Creat };
12973+struct simple_arg {
12974+ int type;
12975+ union {
12976+ struct {
12977+ int mode;
12978+ struct nameidata *nd;
12979+ } c;
12980+ struct {
12981+ const char *symname;
12982+ } s;
12983+ struct {
12984+ int mode;
12985+ dev_t dev;
12986+ } m;
12987+ } u;
12988+};
12989+
12990+static int add_simple(struct inode *dir, struct dentry *dentry,
12991+ struct simple_arg *arg)
12992+{
12993+ int err;
12994+ aufs_bindex_t bstart;
12995+ unsigned char created;
12996+ struct au_dtime dt;
12997+ struct au_pin pin;
12998+ struct path h_path;
12999+ struct dentry *wh_dentry, *parent;
13000+ struct inode *h_dir;
13001+ struct au_wr_dir_args wr_dir_args = {
13002+ .force_btgt = -1,
13003+ .flags = AuWrDir_ADD_ENTRY
13004+ };
13005+
13006+ AuDbg("%.*s\n", AuDLNPair(dentry));
13007+ IMustLock(dir);
13008+
13009+ parent = dentry->d_parent; /* dir inode is locked */
13010+ aufs_read_lock(dentry, AuLock_DW);
13011+ di_write_lock_parent(parent);
13012+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
13013+ &wr_dir_args);
13014+ err = PTR_ERR(wh_dentry);
13015+ if (IS_ERR(wh_dentry))
13016+ goto out;
13017+
13018+ bstart = au_dbstart(dentry);
13019+ h_path.dentry = au_h_dptr(dentry, bstart);
13020+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
13021+ h_dir = au_pinned_h_dir(&pin);
13022+ switch (arg->type) {
13023+ case Creat:
13024+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
13025+ break;
13026+ case Symlink:
13027+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
13028+ break;
13029+ case Mknod:
13030+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
13031+ break;
13032+ default:
13033+ BUG();
13034+ }
13035+ created = !err;
13036+ if (!err)
13037+ err = epilog(dir, bstart, wh_dentry, dentry);
13038+
13039+ /* revert */
13040+ if (unlikely(created && err && h_path.dentry->d_inode)) {
13041+ int rerr;
13042+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
13043+ if (rerr) {
13044+ AuIOErr("%.*s revert failure(%d, %d)\n",
13045+ AuDLNPair(dentry), err, rerr);
13046+ err = -EIO;
13047+ }
13048+ au_dtime_revert(&dt);
13049+ d_drop(dentry);
13050+ }
13051+
13052+ au_unpin(&pin);
13053+ dput(wh_dentry);
13054+
13055+ out:
13056+ if (unlikely(err)) {
13057+ au_update_dbstart(dentry);
13058+ d_drop(dentry);
13059+ }
13060+ di_write_unlock(parent);
13061+ aufs_read_unlock(dentry, AuLock_DW);
13062+ return err;
13063+}
13064+
13065+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
13066+{
13067+ struct simple_arg arg = {
13068+ .type = Mknod,
13069+ .u.m = {
13070+ .mode = mode,
13071+ .dev = dev
13072+ }
13073+ };
13074+ return add_simple(dir, dentry, &arg);
13075+}
13076+
13077+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
13078+{
13079+ struct simple_arg arg = {
13080+ .type = Symlink,
13081+ .u.s.symname = symname
13082+ };
13083+ return add_simple(dir, dentry, &arg);
13084+}
13085+
13086+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13087+ struct nameidata *nd)
13088+{
13089+ struct simple_arg arg = {
13090+ .type = Creat,
13091+ .u.c = {
13092+ .mode = mode,
13093+ .nd = nd
13094+ }
13095+ };
13096+ return add_simple(dir, dentry, &arg);
13097+}
13098+
13099+/* ---------------------------------------------------------------------- */
13100+
13101+struct au_link_args {
13102+ aufs_bindex_t bdst, bsrc;
13103+ struct au_pin pin;
13104+ struct path h_path;
13105+ struct dentry *src_parent, *parent;
13106+};
13107+
13108+static int au_cpup_before_link(struct dentry *src_dentry,
13109+ struct au_link_args *a)
13110+{
13111+ int err;
13112+ struct dentry *h_src_dentry;
13113+ struct mutex *h_mtx;
13114+ struct file *h_file;
13115+
13116+ di_read_lock_parent(a->src_parent, AuLock_IR);
13117+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
13118+ if (unlikely(err))
13119+ goto out;
13120+
13121+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
13122+ h_mtx = &h_src_dentry->d_inode->i_mutex;
13123+ err = au_pin(&a->pin, src_dentry, a->bdst,
13124+ au_opt_udba(src_dentry->d_sb),
13125+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13126+ if (unlikely(err))
13127+ goto out;
13128+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13129+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13130+ if (IS_ERR(h_file)) {
13131+ err = PTR_ERR(h_file);
13132+ h_file = NULL;
13133+ } else
13134+ err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
13135+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
13136+ mutex_unlock(h_mtx);
13137+ au_h_open_post(src_dentry, a->bsrc, h_file);
13138+ au_unpin(&a->pin);
13139+
13140+ out:
13141+ di_read_unlock(a->src_parent, AuLock_IR);
13142+ return err;
13143+}
13144+
13145+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
13146+{
13147+ int err;
13148+ unsigned char plink;
13149+ struct inode *h_inode, *inode;
13150+ struct dentry *h_src_dentry;
13151+ struct super_block *sb;
13152+ struct file *h_file;
13153+
13154+ plink = 0;
13155+ h_inode = NULL;
13156+ sb = src_dentry->d_sb;
13157+ inode = src_dentry->d_inode;
13158+ if (au_ibstart(inode) <= a->bdst)
13159+ h_inode = au_h_iptr(inode, a->bdst);
13160+ if (!h_inode || !h_inode->i_nlink) {
13161+ /* copyup src_dentry as the name of dentry. */
13162+ au_set_dbstart(src_dentry, a->bdst);
13163+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
13164+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
13165+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
13166+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13167+ if (IS_ERR(h_file)) {
13168+ err = PTR_ERR(h_file);
13169+ h_file = NULL;
13170+ } else
13171+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
13172+ -1, AuCpup_KEEPLINO,
13173+ a->parent);
13174+ mutex_unlock(&h_inode->i_mutex);
13175+ au_h_open_post(src_dentry, a->bsrc, h_file);
13176+ au_set_h_dptr(src_dentry, a->bdst, NULL);
13177+ au_set_dbstart(src_dentry, a->bsrc);
13178+ } else {
13179+ /* the inode of src_dentry already exists on a.bdst branch */
13180+ h_src_dentry = d_find_alias(h_inode);
13181+ if (!h_src_dentry && au_plink_test(inode)) {
13182+ plink = 1;
13183+ h_src_dentry = au_plink_lkup(inode, a->bdst);
13184+ err = PTR_ERR(h_src_dentry);
13185+ if (IS_ERR(h_src_dentry))
13186+ goto out;
13187+
13188+ if (unlikely(!h_src_dentry->d_inode)) {
13189+ dput(h_src_dentry);
13190+ h_src_dentry = NULL;
13191+ }
13192+
13193+ }
13194+ if (h_src_dentry) {
13195+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13196+ &a->h_path);
13197+ dput(h_src_dentry);
13198+ } else {
13199+ AuIOErr("no dentry found for hi%lu on b%d\n",
13200+ h_inode->i_ino, a->bdst);
13201+ err = -EIO;
13202+ }
13203+ }
13204+
13205+ if (!err && !plink)
13206+ au_plink_append(inode, a->bdst, a->h_path.dentry);
13207+
13208+out:
13209+ return err;
13210+}
13211+
13212+int aufs_link(struct dentry *src_dentry, struct inode *dir,
13213+ struct dentry *dentry)
13214+{
13215+ int err, rerr;
13216+ struct au_dtime dt;
13217+ struct au_link_args *a;
13218+ struct dentry *wh_dentry, *h_src_dentry;
13219+ struct inode *inode;
13220+ struct super_block *sb;
13221+ struct au_wr_dir_args wr_dir_args = {
13222+ /* .force_btgt = -1, */
13223+ .flags = AuWrDir_ADD_ENTRY
13224+ };
13225+
13226+ IMustLock(dir);
13227+ inode = src_dentry->d_inode;
13228+ IMustLock(inode);
13229+
13230+ err = -ENOENT;
13231+ if (unlikely(!inode->i_nlink))
13232+ goto out;
13233+
13234+ err = -ENOMEM;
13235+ a = kzalloc(sizeof(*a), GFP_NOFS);
13236+ if (unlikely(!a))
13237+ goto out;
13238+
13239+ a->parent = dentry->d_parent; /* dir inode is locked */
13240+ aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
13241+ a->src_parent = dget_parent(src_dentry);
13242+ wr_dir_args.force_btgt = au_dbstart(src_dentry);
13243+
13244+ di_write_lock_parent(a->parent);
13245+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
13246+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
13247+ &wr_dir_args);
13248+ err = PTR_ERR(wh_dentry);
13249+ if (IS_ERR(wh_dentry))
13250+ goto out_unlock;
13251+
13252+ err = 0;
13253+ sb = dentry->d_sb;
13254+ a->bdst = au_dbstart(dentry);
13255+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
13256+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
13257+ a->bsrc = au_dbstart(src_dentry);
13258+ if (au_opt_test(au_mntflags(sb), PLINK)) {
13259+ if (a->bdst < a->bsrc
13260+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
13261+ err = au_cpup_or_link(src_dentry, a);
13262+ else {
13263+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13264+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13265+ &a->h_path);
13266+ }
13267+ } else {
13268+ /*
13269+ * copyup src_dentry to the branch we process,
13270+ * and then link(2) to it.
13271+ */
13272+ if (a->bdst < a->bsrc
13273+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
13274+ au_unpin(&a->pin);
13275+ di_write_unlock(a->parent);
13276+ err = au_cpup_before_link(src_dentry, a);
13277+ di_write_lock_parent(a->parent);
13278+ if (!err)
13279+ err = au_pin(&a->pin, dentry, a->bdst,
13280+ au_opt_udba(sb),
13281+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13282+ if (unlikely(err))
13283+ goto out_wh;
13284+ }
13285+ if (!err) {
13286+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13287+ err = -ENOENT;
13288+ if (h_src_dentry && h_src_dentry->d_inode)
13289+ err = vfsub_link(h_src_dentry,
13290+ au_pinned_h_dir(&a->pin),
13291+ &a->h_path);
13292+ }
13293+ }
13294+ if (unlikely(err))
13295+ goto out_unpin;
13296+
13297+ if (wh_dentry) {
13298+ a->h_path.dentry = wh_dentry;
13299+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
13300+ dentry);
13301+ if (unlikely(err))
13302+ goto out_revert;
13303+ }
13304+
13305+ dir->i_version++;
13306+ if (au_ibstart(dir) == au_dbstart(dentry))
13307+ au_cpup_attr_timesizes(dir);
13308+ inc_nlink(inode);
13309+ inode->i_ctime = dir->i_ctime;
13310+ if (!d_unhashed(a->h_path.dentry))
13311+ d_instantiate(dentry, au_igrab(inode));
13312+ else
13313+ /* some filesystem calls d_drop() */
13314+ d_drop(dentry);
13315+ goto out_unpin; /* success */
13316+
13317+ out_revert:
13318+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
13319+ if (!rerr)
13320+ goto out_dt;
13321+ AuIOErr("%.*s reverting failed(%d, %d)\n",
13322+ AuDLNPair(dentry), err, rerr);
13323+ err = -EIO;
13324+ out_dt:
13325+ d_drop(dentry);
13326+ au_dtime_revert(&dt);
13327+ out_unpin:
13328+ au_unpin(&a->pin);
13329+ out_wh:
13330+ dput(wh_dentry);
13331+ out_unlock:
13332+ if (unlikely(err)) {
13333+ au_update_dbstart(dentry);
13334+ d_drop(dentry);
13335+ }
13336+ di_write_unlock(a->parent);
13337+ dput(a->src_parent);
13338+ aufs_read_and_write_unlock2(dentry, src_dentry);
13339+ kfree(a);
13340+ out:
13341+ return err;
13342+}
13343+
13344+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
13345+{
13346+ int err, rerr;
13347+ aufs_bindex_t bindex;
13348+ unsigned char diropq;
13349+ struct path h_path;
13350+ struct dentry *wh_dentry, *parent, *opq_dentry;
13351+ struct mutex *h_mtx;
13352+ struct super_block *sb;
13353+ struct {
13354+ struct au_pin pin;
13355+ struct au_dtime dt;
13356+ } *a; /* reduce the stack usage */
13357+ struct au_wr_dir_args wr_dir_args = {
13358+ .force_btgt = -1,
13359+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
13360+ };
13361+
13362+ IMustLock(dir);
13363+
13364+ err = -ENOMEM;
13365+ a = kmalloc(sizeof(*a), GFP_NOFS);
13366+ if (unlikely(!a))
13367+ goto out;
13368+
13369+ aufs_read_lock(dentry, AuLock_DW);
13370+ parent = dentry->d_parent; /* dir inode is locked */
13371+ di_write_lock_parent(parent);
13372+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
13373+ &a->pin, &wr_dir_args);
13374+ err = PTR_ERR(wh_dentry);
13375+ if (IS_ERR(wh_dentry))
13376+ goto out_free;
13377+
13378+ sb = dentry->d_sb;
13379+ bindex = au_dbstart(dentry);
13380+ h_path.dentry = au_h_dptr(dentry, bindex);
13381+ h_path.mnt = au_sbr_mnt(sb, bindex);
13382+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
13383+ if (unlikely(err))
13384+ goto out_unlock;
13385+
13386+ /* make the dir opaque */
13387+ diropq = 0;
13388+ h_mtx = &h_path.dentry->d_inode->i_mutex;
13389+ if (wh_dentry
13390+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
13391+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13392+ opq_dentry = au_diropq_create(dentry, bindex);
13393+ mutex_unlock(h_mtx);
13394+ err = PTR_ERR(opq_dentry);
13395+ if (IS_ERR(opq_dentry))
13396+ goto out_dir;
13397+ dput(opq_dentry);
13398+ diropq = 1;
13399+ }
13400+
13401+ err = epilog(dir, bindex, wh_dentry, dentry);
13402+ if (!err) {
13403+ inc_nlink(dir);
13404+ goto out_unlock; /* success */
13405+ }
13406+
13407+ /* revert */
13408+ if (diropq) {
13409+ AuLabel(revert opq);
13410+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13411+ rerr = au_diropq_remove(dentry, bindex);
13412+ mutex_unlock(h_mtx);
13413+ if (rerr) {
13414+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
13415+ AuDLNPair(dentry), err, rerr);
13416+ err = -EIO;
13417+ }
13418+ }
13419+
13420+ out_dir:
13421+ AuLabel(revert dir);
13422+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
13423+ if (rerr) {
13424+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
13425+ AuDLNPair(dentry), err, rerr);
13426+ err = -EIO;
13427+ }
13428+ d_drop(dentry);
13429+ au_dtime_revert(&a->dt);
13430+ out_unlock:
13431+ au_unpin(&a->pin);
13432+ dput(wh_dentry);
13433+ out_free:
13434+ if (unlikely(err)) {
13435+ au_update_dbstart(dentry);
13436+ d_drop(dentry);
13437+ }
13438+ di_write_unlock(parent);
13439+ aufs_read_unlock(dentry, AuLock_DW);
13440+ kfree(a);
13441+ out:
13442+ return err;
13443+}
13444diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/i_op.c linux-2.6.34/fs/aufs/i_op.c
13445--- linux-2.6.34.org/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
13446+++ linux-2.6.34/fs/aufs/i_op.c 2010-05-31 22:15:32.000000000 +0200
13447@@ -0,0 +1,924 @@
13448+/*
13449+ * Copyright (C) 2005-2010 Junjiro R. Okajima
13450+ *
13451+ * This program, aufs is free software; you can redistribute it and/or modify
13452+ * it under the terms of the GNU General Public License as published by
13453+ * the Free Software Foundation; either version 2 of the License, or
13454+ * (at your option) any later version.
13455+ *
13456+ * This program is distributed in the hope that it will be useful,
13457+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13458+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13459+ * GNU General Public License for more details.
13460+ *
13461+ * You should have received a copy of the GNU General Public License
13462+ * along with this program; if not, write to the Free Software
13463+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13464+ */
1facf9fc 13465+
1308ab2a 13466+/*
4a4d8108 13467+ * inode operations (except add/del/rename)
1308ab2a 13468+ */
4a4d8108
AM
13469+
13470+#include <linux/device_cgroup.h>
13471+#include <linux/fs_stack.h>
13472+#include <linux/mm.h>
13473+#include <linux/namei.h>
13474+#include <linux/security.h>
13475+#include <linux/uaccess.h>
13476+#include "aufs.h"
13477+
13478+static int h_permission(struct inode *h_inode, int mask,
13479+ struct vfsmount *h_mnt, int brperm)
1facf9fc 13480+{
1308ab2a 13481+ int err;
4a4d8108 13482+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 13483+
4a4d8108
AM
13484+ err = -EACCES;
13485+ if ((write_mask && IS_IMMUTABLE(h_inode))
13486+ || ((mask & MAY_EXEC)
13487+ && S_ISREG(h_inode->i_mode)
13488+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
13489+ || !(h_inode->i_mode & S_IXUGO))))
13490+ goto out;
13491+
13492+ /*
13493+ * - skip the lower fs test in the case of write to ro branch.
13494+ * - nfs dir permission write check is optimized, but a policy for
13495+ * link/rename requires a real check.
13496+ */
13497+ if ((write_mask && !au_br_writable(brperm))
13498+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
13499+ && write_mask && !(mask & MAY_READ))
13500+ || !h_inode->i_op->permission) {
13501+ /* AuLabel(generic_permission); */
13502+ err = generic_permission(h_inode, mask,
13503+ h_inode->i_op->check_acl);
1308ab2a 13504+ } else {
4a4d8108
AM
13505+ /* AuLabel(h_inode->permission); */
13506+ err = h_inode->i_op->permission(h_inode, mask);
13507+ AuTraceErr(err);
13508+ }
1facf9fc 13509+
4a4d8108
AM
13510+ if (!err)
13511+ err = devcgroup_inode_permission(h_inode, mask);
13512+ if (!err) {
13513+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND);
13514+ err = security_inode_permission(h_inode, mask);
13515+ }
13516+
13517+#if 0
13518+ if (!err) {
13519+ /* todo: do we need to call ima_path_check()? */
13520+ struct path h_path = {
13521+ .dentry =
13522+ .mnt = h_mnt
13523+ };
13524+ err = ima_path_check(&h_path,
13525+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
13526+ IMA_COUNT_LEAVE);
1308ab2a 13527+ }
4a4d8108 13528+#endif
dece6358 13529+
4a4d8108 13530+ out:
1308ab2a 13531+ return err;
13532+}
dece6358 13533+
4a4d8108 13534+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 13535+{
13536+ int err;
4a4d8108
AM
13537+ aufs_bindex_t bindex, bend;
13538+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
13539+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
13540+ struct inode *h_inode;
13541+ struct super_block *sb;
13542+ struct au_branch *br;
1facf9fc 13543+
4a4d8108
AM
13544+ sb = inode->i_sb;
13545+ si_read_lock(sb, AuLock_FLUSH);
13546+ ii_read_lock_child(inode);
dece6358 13547+
4a4d8108
AM
13548+ if (!isdir || write_mask) {
13549+ err = au_busy_or_stale();
13550+ h_inode = au_h_iptr(inode, au_ibstart(inode));
13551+ if (unlikely(!h_inode
13552+ || (h_inode->i_mode & S_IFMT)
13553+ != (inode->i_mode & S_IFMT)))
13554+ goto out;
1facf9fc 13555+
4a4d8108
AM
13556+ err = 0;
13557+ bindex = au_ibstart(inode);
13558+ br = au_sbr(sb, bindex);
13559+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
13560+ if (write_mask
13561+ && !err
13562+ && !special_file(h_inode->i_mode)) {
13563+ /* test whether the upper writable branch exists */
13564+ err = -EROFS;
13565+ for (; bindex >= 0; bindex--)
13566+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
13567+ err = 0;
13568+ break;
13569+ }
13570+ }
13571+ goto out;
13572+ }
dece6358 13573+
4a4d8108 13574+ /* non-write to dir */
1308ab2a 13575+ err = 0;
4a4d8108
AM
13576+ bend = au_ibend(inode);
13577+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
13578+ h_inode = au_h_iptr(inode, bindex);
13579+ if (h_inode) {
13580+ err = au_busy_or_stale();
13581+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
13582+ break;
13583+
13584+ br = au_sbr(sb, bindex);
13585+ err = h_permission(h_inode, mask, br->br_mnt,
13586+ br->br_perm);
13587+ }
13588+ }
1308ab2a 13589+
4a4d8108
AM
13590+ out:
13591+ ii_read_unlock(inode);
13592+ si_read_unlock(sb);
1308ab2a 13593+ return err;
13594+}
13595+
4a4d8108 13596+/* ---------------------------------------------------------------------- */
1facf9fc 13597+
4a4d8108
AM
13598+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
13599+ struct nameidata *nd)
13600+{
13601+ struct dentry *ret, *parent;
13602+ struct inode *inode, *h_inode;
13603+ struct mutex *mtx;
13604+ struct super_block *sb;
13605+ int err, npositive;
13606+ aufs_bindex_t bstart;
dece6358 13607+
4a4d8108 13608+ IMustLock(dir);
1308ab2a 13609+
4a4d8108
AM
13610+ sb = dir->i_sb;
13611+ si_read_lock(sb, AuLock_FLUSH);
13612+ ret = ERR_PTR(-ENAMETOOLONG);
13613+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13614+ goto out;
13615+ err = au_di_init(dentry);
13616+ ret = ERR_PTR(err);
13617+ if (unlikely(err))
13618+ goto out;
1308ab2a 13619+
4a4d8108
AM
13620+ parent = dentry->d_parent; /* dir inode is locked */
13621+ di_read_lock_parent(parent, AuLock_IR);
13622+ npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
13623+ di_read_unlock(parent, AuLock_IR);
13624+ err = npositive;
13625+ ret = ERR_PTR(err);
13626+ if (unlikely(err < 0))
13627+ goto out_unlock;
1308ab2a 13628+
4a4d8108
AM
13629+ inode = NULL;
13630+ if (npositive) {
13631+ bstart = au_dbstart(dentry);
13632+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
13633+ if (!S_ISDIR(h_inode->i_mode)) {
13634+ /*
13635+ * stop 'race'-ing between hardlinks under different
13636+ * parents.
13637+ */
13638+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
13639+ mutex_lock(mtx);
13640+ inode = au_new_inode(dentry, /*must_new*/0);
13641+ mutex_unlock(mtx);
13642+ } else
13643+ inode = au_new_inode(dentry, /*must_new*/0);
13644+ ret = (void *)inode;
1facf9fc 13645+ }
4a4d8108
AM
13646+ if (IS_ERR(inode))
13647+ goto out_unlock;
13648+
13649+ ret = d_splice_alias(inode, dentry);
13650+ if (unlikely(IS_ERR(ret) && inode))
13651+ ii_write_unlock(inode);
1facf9fc 13652+
4a4d8108
AM
13653+ out_unlock:
13654+ di_write_unlock(dentry);
13655+ out:
13656+ si_read_unlock(sb);
13657+ return ret;
13658+}
1facf9fc 13659+
4a4d8108 13660+/* ---------------------------------------------------------------------- */
1facf9fc 13661+
4a4d8108
AM
13662+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
13663+ const unsigned char add_entry, aufs_bindex_t bcpup,
13664+ aufs_bindex_t bstart)
13665+{
13666+ int err;
13667+ struct dentry *h_parent;
13668+ struct inode *h_dir;
1facf9fc 13669+
4a4d8108
AM
13670+ if (add_entry) {
13671+ au_update_dbstart(dentry);
13672+ IMustLock(parent->d_inode);
13673+ } else
13674+ di_write_lock_parent(parent);
13675+
13676+ err = 0;
13677+ if (!au_h_dptr(parent, bcpup)) {
13678+ if (bstart < bcpup)
13679+ err = au_cpdown_dirs(dentry, bcpup);
13680+ else
13681+ err = au_cpup_dirs(dentry, bcpup);
13682+ }
13683+ if (!err && add_entry) {
13684+ h_parent = au_h_dptr(parent, bcpup);
13685+ h_dir = h_parent->d_inode;
13686+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
13687+ err = au_lkup_neg(dentry, bcpup);
13688+ /* todo: no unlock here */
13689+ mutex_unlock(&h_dir->i_mutex);
13690+ if (bstart < bcpup && au_dbstart(dentry) < 0) {
13691+ au_set_dbstart(dentry, 0);
13692+ au_update_dbrange(dentry, /*do_put_zero*/0);
13693+ }
1308ab2a 13694+ }
1facf9fc 13695+
4a4d8108
AM
13696+ if (!add_entry)
13697+ di_write_unlock(parent);
13698+ if (!err)
13699+ err = bcpup; /* success */
1308ab2a 13700+
4a4d8108
AM
13701+ return err;
13702+}
1facf9fc 13703+
4a4d8108
AM
13704+/*
13705+ * decide the branch and the parent dir where we will create a new entry.
13706+ * returns new bindex or an error.
13707+ * copyup the parent dir if needed.
13708+ */
13709+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
13710+ struct au_wr_dir_args *args)
13711+{
13712+ int err;
13713+ aufs_bindex_t bcpup, bstart, src_bstart;
13714+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
13715+ ADD_ENTRY);
13716+ struct super_block *sb;
13717+ struct dentry *parent;
13718+ struct au_sbinfo *sbinfo;
1facf9fc 13719+
4a4d8108
AM
13720+ sb = dentry->d_sb;
13721+ sbinfo = au_sbi(sb);
13722+ parent = dget_parent(dentry);
13723+ bstart = au_dbstart(dentry);
13724+ bcpup = bstart;
13725+ if (args->force_btgt < 0) {
13726+ if (src_dentry) {
13727+ src_bstart = au_dbstart(src_dentry);
13728+ if (src_bstart < bstart)
13729+ bcpup = src_bstart;
13730+ } else if (add_entry) {
13731+ err = AuWbrCreate(sbinfo, dentry,
13732+ au_ftest_wrdir(args->flags, ISDIR));
13733+ bcpup = err;
13734+ }
1facf9fc 13735+
4a4d8108
AM
13736+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
13737+ if (add_entry)
13738+ err = AuWbrCopyup(sbinfo, dentry);
13739+ else {
13740+ if (!IS_ROOT(dentry)) {
13741+ di_read_lock_parent(parent, !AuLock_IR);
13742+ err = AuWbrCopyup(sbinfo, dentry);
13743+ di_read_unlock(parent, !AuLock_IR);
13744+ } else
13745+ err = AuWbrCopyup(sbinfo, dentry);
13746+ }
13747+ bcpup = err;
13748+ if (unlikely(err < 0))
13749+ goto out;
13750+ }
13751+ } else {
13752+ bcpup = args->force_btgt;
13753+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 13754+ }
4a4d8108
AM
13755+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
13756+ err = bcpup;
13757+ if (bcpup == bstart)
13758+ goto out; /* success */
13759+ else if (bstart < bcpup)
13760+ au_update_dbrange(dentry, /*do_put_zero*/1);
13761+
13762+ /* copyup the new parent into the branch we process */
13763+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
13764+
dece6358 13765+ out:
4a4d8108 13766+ dput(parent);
dece6358
AM
13767+ return err;
13768+}
1facf9fc 13769+
1308ab2a 13770+/* ---------------------------------------------------------------------- */
13771+
4a4d8108 13772+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 13773+{
4a4d8108
AM
13774+ if (pin && pin->parent)
13775+ return au_h_dptr(pin->parent, pin->bindex);
13776+ return NULL;
dece6358 13777+}
1facf9fc 13778+
4a4d8108 13779+void au_unpin(struct au_pin *p)
dece6358 13780+{
4a4d8108
AM
13781+ if (au_ftest_pin(p->flags, MNT_WRITE))
13782+ mnt_drop_write(p->h_mnt);
13783+ if (!p->hdir)
13784+ return;
1facf9fc 13785+
4a4d8108
AM
13786+ au_hn_imtx_unlock(p->hdir);
13787+ if (!au_ftest_pin(p->flags, DI_LOCKED))
13788+ di_read_unlock(p->parent, AuLock_IR);
13789+ iput(p->hdir->hi_inode);
13790+ dput(p->parent);
13791+ p->parent = NULL;
13792+ p->hdir = NULL;
13793+ p->h_mnt = NULL;
13794+}
1308ab2a 13795+
4a4d8108
AM
13796+int au_do_pin(struct au_pin *p)
13797+{
13798+ int err;
13799+ struct super_block *sb;
13800+ struct dentry *h_dentry, *h_parent;
13801+ struct au_branch *br;
13802+ struct inode *h_dir;
13803+
13804+ err = 0;
13805+ sb = p->dentry->d_sb;
13806+ br = au_sbr(sb, p->bindex);
13807+ if (IS_ROOT(p->dentry)) {
13808+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
13809+ p->h_mnt = br->br_mnt;
13810+ err = mnt_want_write(p->h_mnt);
13811+ if (unlikely(err)) {
13812+ au_fclr_pin(p->flags, MNT_WRITE);
13813+ goto out_err;
13814+ }
13815+ }
dece6358 13816+ goto out;
1facf9fc 13817+ }
13818+
4a4d8108
AM
13819+ h_dentry = NULL;
13820+ if (p->bindex <= au_dbend(p->dentry))
13821+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 13822+
4a4d8108
AM
13823+ p->parent = dget_parent(p->dentry);
13824+ if (!au_ftest_pin(p->flags, DI_LOCKED))
13825+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 13826+
4a4d8108
AM
13827+ h_dir = NULL;
13828+ h_parent = au_h_dptr(p->parent, p->bindex);
13829+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
13830+ if (p->hdir)
13831+ h_dir = p->hdir->hi_inode;
dece6358 13832+
4a4d8108
AM
13833+ /* udba case */
13834+ if (unlikely(!p->hdir || !h_dir)) {
13835+ if (!au_ftest_pin(p->flags, DI_LOCKED))
13836+ di_read_unlock(p->parent, AuLock_IR);
13837+ dput(p->parent);
13838+ p->parent = NULL;
13839+ goto out_err;
13840+ }
1308ab2a 13841+
4a4d8108
AM
13842+ au_igrab(h_dir);
13843+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 13844+
4a4d8108
AM
13845+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
13846+ err = -EBUSY;
13847+ goto out_unpin;
13848+ }
13849+ if (h_dentry) {
13850+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
13851+ if (unlikely(err)) {
13852+ au_fclr_pin(p->flags, MNT_WRITE);
13853+ goto out_unpin;
13854+ }
1facf9fc 13855+ }
dece6358 13856+
4a4d8108
AM
13857+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
13858+ p->h_mnt = br->br_mnt;
13859+ err = mnt_want_write(p->h_mnt);
dece6358 13860+ if (unlikely(err)) {
4a4d8108
AM
13861+ au_fclr_pin(p->flags, MNT_WRITE);
13862+ goto out_unpin;
dece6358
AM
13863+ }
13864+ }
4a4d8108
AM
13865+ goto out; /* success */
13866+
13867+ out_unpin:
13868+ au_unpin(p);
13869+ out_err:
13870+ pr_err("err %d\n", err);
13871+ err = au_busy_or_stale();
1facf9fc 13872+ out:
13873+ return err;
13874+}
13875+
4a4d8108
AM
13876+void au_pin_init(struct au_pin *p, struct dentry *dentry,
13877+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
13878+ unsigned int udba, unsigned char flags)
13879+{
13880+ p->dentry = dentry;
13881+ p->udba = udba;
13882+ p->lsc_di = lsc_di;
13883+ p->lsc_hi = lsc_hi;
13884+ p->flags = flags;
13885+ p->bindex = bindex;
13886+
13887+ p->parent = NULL;
13888+ p->hdir = NULL;
13889+ p->h_mnt = NULL;
13890+}
13891+
13892+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
13893+ unsigned int udba, unsigned char flags)
13894+{
13895+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
13896+ udba, flags);
13897+ return au_do_pin(pin);
13898+}
13899+
dece6358
AM
13900+/* ---------------------------------------------------------------------- */
13901+
1308ab2a 13902+/*
4a4d8108
AM
13903+ * ->setattr() and ->getattr() are called in various cases.
13904+ * chmod, stat: dentry is revalidated.
13905+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
13906+ * unhashed.
13907+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 13908+ */
4a4d8108 13909+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 13910+{
4a4d8108
AM
13911+ int err;
13912+ struct inode *inode;
13913+ struct dentry *parent;
1facf9fc 13914+
1308ab2a 13915+ err = 0;
4a4d8108
AM
13916+ inode = dentry->d_inode;
13917+ if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
13918+ parent = dget_parent(dentry);
13919+ di_read_lock_parent(parent, AuLock_IR);
13920+ /* returns a number of positive dentries */
13921+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
13922+ if (err >= 0)
13923+ err = au_refresh_hinode(inode, dentry);
13924+ di_read_unlock(parent, AuLock_IR);
13925+ dput(parent);
dece6358 13926+ }
1facf9fc 13927+
4a4d8108 13928+ AuTraceErr(err);
1308ab2a 13929+ return err;
13930+}
dece6358 13931+
4a4d8108
AM
13932+#define AuIcpup_DID_CPUP 1
13933+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
13934+#define au_fset_icpup(flags, name) { (flags) |= AuIcpup_##name; }
13935+#define au_fclr_icpup(flags, name) { (flags) &= ~AuIcpup_##name; }
1308ab2a 13936+
4a4d8108
AM
13937+struct au_icpup_args {
13938+ unsigned char flags;
13939+ unsigned char pin_flags;
13940+ aufs_bindex_t btgt;
13941+ unsigned int udba;
13942+ struct au_pin pin;
13943+ struct path h_path;
13944+ struct inode *h_inode;
13945+};
1308ab2a 13946+
4a4d8108
AM
13947+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
13948+ struct au_icpup_args *a)
1308ab2a 13949+{
13950+ int err;
4a4d8108
AM
13951+ loff_t sz;
13952+ aufs_bindex_t bstart;
13953+ struct dentry *hi_wh, *parent;
13954+ struct inode *inode;
13955+ struct file *h_file;
13956+ struct au_wr_dir_args wr_dir_args = {
13957+ .force_btgt = -1,
13958+ .flags = 0
13959+ };
13960+
13961+ bstart = au_dbstart(dentry);
13962+ inode = dentry->d_inode;
13963+ if (S_ISDIR(inode->i_mode))
13964+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
13965+ /* plink or hi_wh() case */
13966+ if (bstart != au_ibstart(inode))
13967+ wr_dir_args.force_btgt = au_ibstart(inode);
13968+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
13969+ if (unlikely(err < 0))
13970+ goto out;
13971+ a->btgt = err;
13972+ if (err != bstart)
13973+ au_fset_icpup(a->flags, DID_CPUP);
13974+
13975+ err = 0;
13976+ a->pin_flags = AuPin_MNT_WRITE;
13977+ parent = NULL;
13978+ if (!IS_ROOT(dentry)) {
13979+ au_fset_pin(a->pin_flags, DI_LOCKED);
13980+ parent = dget_parent(dentry);
13981+ di_write_lock_parent(parent);
13982+ }
13983+
13984+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
13985+ if (unlikely(err))
13986+ goto out_parent;
13987+
13988+ a->h_path.dentry = au_h_dptr(dentry, bstart);
13989+ a->h_inode = a->h_path.dentry->d_inode;
13990+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
13991+ sz = -1;
13992+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
13993+ sz = ia->ia_size;
13994+
13995+ h_file = NULL;
13996+ hi_wh = NULL;
13997+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
13998+ hi_wh = au_hi_wh(inode, a->btgt);
13999+ if (!hi_wh) {
14000+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
14001+ if (unlikely(err))
14002+ goto out_unlock;
14003+ hi_wh = au_hi_wh(inode, a->btgt);
14004+ /* todo: revalidate hi_wh? */
14005+ }
14006+ }
14007+
14008+ if (parent) {
14009+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14010+ di_downgrade_lock(parent, AuLock_IR);
14011+ dput(parent);
14012+ parent = NULL;
14013+ }
14014+ if (!au_ftest_icpup(a->flags, DID_CPUP))
14015+ goto out; /* success */
14016+
14017+ if (!d_unhashed(dentry)) {
14018+ h_file = au_h_open_pre(dentry, bstart);
14019+ if (IS_ERR(h_file)) {
14020+ err = PTR_ERR(h_file);
14021+ h_file = NULL;
14022+ } else
14023+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
14024+ AuCpup_DTIME);
14025+ if (!err)
14026+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14027+ } else if (!hi_wh)
14028+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14029+ else
14030+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 14031+
4a4d8108
AM
14032+ out_unlock:
14033+ mutex_unlock(&a->h_inode->i_mutex);
14034+ au_h_open_post(dentry, bstart, h_file);
14035+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 14036+ if (!err) {
4a4d8108 14037+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 14038+ goto out; /* success */
1facf9fc 14039+ }
dece6358 14040+
4a4d8108
AM
14041+ au_unpin(&a->pin);
14042+ out_parent:
14043+ if (parent) {
14044+ di_write_unlock(parent);
14045+ dput(parent);
14046+ }
dece6358 14047+ out:
1facf9fc 14048+ return err;
14049+}
14050+
4a4d8108 14051+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 14052+{
4a4d8108
AM
14053+ int err;
14054+ struct inode *inode;
14055+ struct super_block *sb;
14056+ struct file *file;
14057+ struct au_icpup_args *a;
1facf9fc 14058+
4a4d8108
AM
14059+ inode = dentry->d_inode;
14060+ IMustLock(inode);
dece6358 14061+
4a4d8108
AM
14062+ err = -ENOMEM;
14063+ a = kzalloc(sizeof(*a), GFP_NOFS);
14064+ if (unlikely(!a))
14065+ goto out;
1facf9fc 14066+
4a4d8108
AM
14067+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
14068+ ia->ia_valid &= ~ATTR_MODE;
dece6358 14069+
4a4d8108
AM
14070+ file = NULL;
14071+ sb = dentry->d_sb;
14072+ si_read_lock(sb, AuLock_FLUSH);
14073+ if (ia->ia_valid & ATTR_FILE) {
14074+ /* currently ftruncate(2) only */
14075+ AuDebugOn(!S_ISREG(inode->i_mode));
14076+ file = ia->ia_file;
14077+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
14078+ if (unlikely(err))
14079+ goto out_si;
14080+ ia->ia_file = au_hf_top(file);
14081+ a->udba = AuOpt_UDBA_NONE;
14082+ } else {
14083+ /* fchmod() doesn't pass ia_file */
14084+ a->udba = au_opt_udba(sb);
14085+ if (d_unhashed(dentry))
14086+ a->udba = AuOpt_UDBA_NONE;
14087+ di_write_lock_child(dentry);
14088+ if (a->udba != AuOpt_UDBA_NONE) {
14089+ AuDebugOn(IS_ROOT(dentry));
14090+ err = au_reval_for_attr(dentry, au_sigen(sb));
14091+ if (unlikely(err))
14092+ goto out_dentry;
14093+ }
dece6358 14094+ }
dece6358 14095+
4a4d8108
AM
14096+ err = au_pin_and_icpup(dentry, ia, a);
14097+ if (unlikely(err < 0))
14098+ goto out_dentry;
14099+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
14100+ ia->ia_file = NULL;
14101+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 14102+ }
dece6358 14103+
4a4d8108
AM
14104+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
14105+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
14106+ == (ATTR_MODE | ATTR_CTIME)) {
14107+ err = security_path_chmod(a->h_path.dentry, a->h_path.mnt,
14108+ ia->ia_mode);
14109+ if (unlikely(err))
14110+ goto out_unlock;
14111+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
14112+ && (ia->ia_valid & ATTR_CTIME)) {
14113+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
14114+ if (unlikely(err))
14115+ goto out_unlock;
14116+ }
dece6358 14117+
4a4d8108
AM
14118+ if (ia->ia_valid & ATTR_SIZE) {
14119+ struct file *f;
1308ab2a 14120+
4a4d8108
AM
14121+ if (ia->ia_size < i_size_read(inode)) {
14122+ /* unmap only */
14123+ err = vmtruncate(inode, ia->ia_size);
14124+ if (unlikely(err))
14125+ goto out_unlock;
14126+ }
1308ab2a 14127+
4a4d8108
AM
14128+ f = NULL;
14129+ if (ia->ia_valid & ATTR_FILE)
14130+ f = ia->ia_file;
14131+ mutex_unlock(&a->h_inode->i_mutex);
14132+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
14133+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14134+ } else
14135+ err = vfsub_notify_change(&a->h_path, ia);
14136+ if (!err)
14137+ au_cpup_attr_changeable(inode);
1308ab2a 14138+
4a4d8108
AM
14139+ out_unlock:
14140+ mutex_unlock(&a->h_inode->i_mutex);
14141+ au_unpin(&a->pin);
14142+ out_dentry:
14143+ di_write_unlock(dentry);
14144+ if (file) {
14145+ fi_write_unlock(file);
14146+ ia->ia_file = file;
14147+ ia->ia_valid |= ATTR_FILE;
14148+ }
14149+ out_si:
14150+ si_read_unlock(sb);
14151+ kfree(a);
14152+ out:
14153+ AuTraceErr(err);
14154+ return err;
1facf9fc 14155+}
14156+
4a4d8108
AM
14157+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
14158+ unsigned int nlink)
1facf9fc 14159+{
4a4d8108
AM
14160+ inode->i_mode = st->mode;
14161+ inode->i_uid = st->uid;
14162+ inode->i_gid = st->gid;
14163+ inode->i_atime = st->atime;
14164+ inode->i_mtime = st->mtime;
14165+ inode->i_ctime = st->ctime;
1facf9fc 14166+
4a4d8108
AM
14167+ au_cpup_attr_nlink(inode, /*force*/0);
14168+ if (S_ISDIR(inode->i_mode)) {
14169+ inode->i_nlink -= nlink;
14170+ inode->i_nlink += st->nlink;
14171+ }
1facf9fc 14172+
4a4d8108
AM
14173+ spin_lock(&inode->i_lock);
14174+ inode->i_blocks = st->blocks;
14175+ i_size_write(inode, st->size);
14176+ spin_unlock(&inode->i_lock);
1facf9fc 14177+}
14178+
4a4d8108
AM
14179+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
14180+ struct dentry *dentry, struct kstat *st)
1facf9fc 14181+{
4a4d8108
AM
14182+ int err;
14183+ unsigned int mnt_flags;
14184+ aufs_bindex_t bindex;
14185+ unsigned char udba_none, positive;
14186+ struct super_block *sb, *h_sb;
14187+ struct inode *inode;
14188+ struct vfsmount *h_mnt;
14189+ struct dentry *h_dentry;
1facf9fc 14190+
4a4d8108
AM
14191+ err = 0;
14192+ sb = dentry->d_sb;
14193+ inode = dentry->d_inode;
14194+ si_read_lock(sb, AuLock_FLUSH);
14195+ mnt_flags = au_mntflags(sb);
14196+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 14197+
4a4d8108
AM
14198+ /* support fstat(2) */
14199+ if (!d_unhashed(dentry) && !udba_none) {
14200+ unsigned int sigen = au_sigen(sb);
14201+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
14202+ di_read_lock_child(dentry, AuLock_IR);
14203+ else {
14204+ AuDebugOn(IS_ROOT(dentry));
14205+ di_write_lock_child(dentry);
14206+ err = au_reval_for_attr(dentry, sigen);
14207+ di_downgrade_lock(dentry, AuLock_IR);
14208+ if (unlikely(err))
14209+ goto out;
14210+ }
14211+ } else
14212+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 14213+
4a4d8108
AM
14214+ bindex = au_ibstart(inode);
14215+ h_mnt = au_sbr_mnt(sb, bindex);
14216+ h_sb = h_mnt->mnt_sb;
14217+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
14218+ goto out_fill; /* success */
1facf9fc 14219+
4a4d8108
AM
14220+ h_dentry = NULL;
14221+ if (au_dbstart(dentry) == bindex)
14222+ h_dentry = dget(au_h_dptr(dentry, bindex));
14223+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
14224+ h_dentry = au_plink_lkup(inode, bindex);
14225+ if (IS_ERR(h_dentry))
14226+ goto out_fill; /* pretending success */
14227+ }
14228+ /* illegally overlapped or something */
14229+ if (unlikely(!h_dentry))
14230+ goto out_fill; /* pretending success */
14231+
14232+ positive = !!h_dentry->d_inode;
14233+ if (positive)
14234+ err = vfs_getattr(h_mnt, h_dentry, st);
14235+ dput(h_dentry);
14236+ if (!err) {
14237+ if (positive)
14238+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
14239+ goto out_fill; /* success */
1facf9fc 14240+ }
4a4d8108
AM
14241+ goto out;
14242+
14243+ out_fill:
14244+ generic_fillattr(inode, st);
14245+ out:
14246+ di_read_unlock(dentry, AuLock_IR);
14247+ si_read_unlock(sb);
14248+ return err;
1facf9fc 14249+}
14250+
14251+/* ---------------------------------------------------------------------- */
14252+
4a4d8108
AM
14253+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
14254+ int bufsiz)
1facf9fc 14255+{
14256+ int err;
4a4d8108
AM
14257+ struct super_block *sb;
14258+ struct dentry *h_dentry;
1facf9fc 14259+
4a4d8108
AM
14260+ err = -EINVAL;
14261+ h_dentry = au_h_dptr(dentry, bindex);
14262+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
14263+ goto out;
1facf9fc 14264+
4a4d8108
AM
14265+ err = security_inode_readlink(h_dentry);
14266+ if (unlikely(err))
dece6358 14267+ goto out;
1facf9fc 14268+
4a4d8108
AM
14269+ sb = dentry->d_sb;
14270+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
14271+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
14272+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 14273+ }
4a4d8108 14274+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 14275+
4a4d8108
AM
14276+ out:
14277+ return err;
14278+}
1facf9fc 14279+
4a4d8108
AM
14280+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
14281+{
14282+ int err;
1facf9fc 14283+
4a4d8108
AM
14284+ aufs_read_lock(dentry, AuLock_IR);
14285+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
14286+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14287+
4a4d8108
AM
14288+ return err;
14289+}
1facf9fc 14290+
4a4d8108
AM
14291+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
14292+{
14293+ int err;
14294+ char *buf;
14295+ mm_segment_t old_fs;
1facf9fc 14296+
4a4d8108
AM
14297+ err = -ENOMEM;
14298+ buf = __getname_gfp(GFP_NOFS);
14299+ if (unlikely(!buf))
14300+ goto out;
1facf9fc 14301+
4a4d8108
AM
14302+ aufs_read_lock(dentry, AuLock_IR);
14303+ old_fs = get_fs();
14304+ set_fs(KERNEL_DS);
14305+ err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
14306+ PATH_MAX);
14307+ set_fs(old_fs);
14308+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14309+
4a4d8108
AM
14310+ if (err >= 0) {
14311+ buf[err] = 0;
14312+ /* will be freed by put_link */
14313+ nd_set_link(nd, buf);
14314+ return NULL; /* success */
1308ab2a 14315+ }
4a4d8108 14316+ __putname(buf);
1facf9fc 14317+
4a4d8108
AM
14318+ out:
14319+ path_put(&nd->path);
14320+ AuTraceErr(err);
14321+ return ERR_PTR(err);
14322+}
1facf9fc 14323+
4a4d8108
AM
14324+static void aufs_put_link(struct dentry *dentry __maybe_unused,
14325+ struct nameidata *nd, void *cookie __maybe_unused)
14326+{
14327+ __putname(nd_get_link(nd));
14328+}
1facf9fc 14329+
4a4d8108 14330+/* ---------------------------------------------------------------------- */
1facf9fc 14331+
4a4d8108
AM
14332+static void aufs_truncate_range(struct inode *inode __maybe_unused,
14333+ loff_t start __maybe_unused,
14334+ loff_t end __maybe_unused)
14335+{
14336+ AuUnsupport();
14337+}
1facf9fc 14338+
4a4d8108 14339+/* ---------------------------------------------------------------------- */
1308ab2a 14340+
4a4d8108
AM
14341+struct inode_operations aufs_symlink_iop = {
14342+ .permission = aufs_permission,
14343+ .setattr = aufs_setattr,
14344+ .getattr = aufs_getattr,
14345+ .readlink = aufs_readlink,
14346+ .follow_link = aufs_follow_link,
14347+ .put_link = aufs_put_link
14348+};
14349+
14350+struct inode_operations aufs_dir_iop = {
14351+ .create = aufs_create,
14352+ .lookup = aufs_lookup,
14353+ .link = aufs_link,
14354+ .unlink = aufs_unlink,
14355+ .symlink = aufs_symlink,
14356+ .mkdir = aufs_mkdir,
14357+ .rmdir = aufs_rmdir,
14358+ .mknod = aufs_mknod,
14359+ .rename = aufs_rename,
14360+
14361+ .permission = aufs_permission,
14362+ .setattr = aufs_setattr,
14363+ .getattr = aufs_getattr
14364+};
14365+
14366+struct inode_operations aufs_iop = {
14367+ .permission = aufs_permission,
14368+ .setattr = aufs_setattr,
14369+ .getattr = aufs_getattr,
14370+ .truncate_range = aufs_truncate_range
14371+};
14372diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/i_op_del.c linux-2.6.34/fs/aufs/i_op_del.c
14373--- linux-2.6.34.org/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
14374+++ linux-2.6.34/fs/aufs/i_op_del.c 2010-05-31 22:15:32.000000000 +0200
14375@@ -0,0 +1,472 @@
1facf9fc 14376+/*
4a4d8108 14377+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 14378+ *
14379+ * This program, aufs is free software; you can redistribute it and/or modify
14380+ * it under the terms of the GNU General Public License as published by
14381+ * the Free Software Foundation; either version 2 of the License, or
14382+ * (at your option) any later version.
dece6358
AM
14383+ *
14384+ * This program is distributed in the hope that it will be useful,
14385+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14386+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14387+ * GNU General Public License for more details.
14388+ *
14389+ * You should have received a copy of the GNU General Public License
14390+ * along with this program; if not, write to the Free Software
14391+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14392+ */
14393+
14394+/*
4a4d8108 14395+ * inode operations (del entry)
1308ab2a 14396+ */
dece6358 14397+
1308ab2a 14398+#include "aufs.h"
dece6358 14399+
4a4d8108
AM
14400+/*
14401+ * decide if a new whiteout for @dentry is necessary or not.
14402+ * when it is necessary, prepare the parent dir for the upper branch whose
14403+ * branch index is @bcpup for creation. the actual creation of the whiteout will
14404+ * be done by caller.
14405+ * return value:
14406+ * 0: wh is unnecessary
14407+ * plus: wh is necessary
14408+ * minus: error
14409+ */
14410+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 14411+{
4a4d8108
AM
14412+ int need_wh, err;
14413+ aufs_bindex_t bstart;
14414+ struct super_block *sb;
dece6358 14415+
4a4d8108
AM
14416+ sb = dentry->d_sb;
14417+ bstart = au_dbstart(dentry);
14418+ if (*bcpup < 0) {
14419+ *bcpup = bstart;
14420+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
14421+ err = AuWbrCopyup(au_sbi(sb), dentry);
14422+ *bcpup = err;
14423+ if (unlikely(err < 0))
14424+ goto out;
14425+ }
14426+ } else
14427+ AuDebugOn(bstart < *bcpup
14428+ || au_test_ro(sb, *bcpup, dentry->d_inode));
14429+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 14430+
4a4d8108
AM
14431+ if (*bcpup != bstart) {
14432+ err = au_cpup_dirs(dentry, *bcpup);
14433+ if (unlikely(err))
14434+ goto out;
14435+ need_wh = 1;
14436+ } else {
14437+ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
14438+
14439+ old_bend = au_dbend(dentry);
14440+ if (isdir) {
14441+ bdiropq = au_dbdiropq(dentry);
14442+ au_set_dbdiropq(dentry, -1);
14443+ }
14444+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
14445+ /*nd*/NULL);
14446+ err = need_wh;
14447+ if (isdir)
14448+ au_set_dbdiropq(dentry, bdiropq);
14449+ if (unlikely(err < 0))
14450+ goto out;
14451+ new_bend = au_dbend(dentry);
14452+ if (!need_wh && old_bend != new_bend) {
14453+ au_set_h_dptr(dentry, new_bend, NULL);
14454+ au_set_dbend(dentry, old_bend);
14455+ }
14456+ }
14457+ AuDbg("need_wh %d\n", need_wh);
14458+ err = need_wh;
14459+
14460+ out:
14461+ return err;
1facf9fc 14462+}
14463+
4a4d8108
AM
14464+/*
14465+ * simple tests for the del-entry operations.
14466+ * following the checks in vfs, plus the parent-child relationship.
14467+ */
14468+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14469+ struct dentry *h_parent, int isdir)
1facf9fc 14470+{
4a4d8108
AM
14471+ int err;
14472+ umode_t h_mode;
14473+ struct dentry *h_dentry, *h_latest;
1308ab2a 14474+ struct inode *h_inode;
1facf9fc 14475+
4a4d8108
AM
14476+ h_dentry = au_h_dptr(dentry, bindex);
14477+ h_inode = h_dentry->d_inode;
14478+ if (dentry->d_inode) {
14479+ err = -ENOENT;
14480+ if (unlikely(!h_inode || !h_inode->i_nlink))
14481+ goto out;
1facf9fc 14482+
4a4d8108
AM
14483+ h_mode = h_inode->i_mode;
14484+ if (!isdir) {
14485+ err = -EISDIR;
14486+ if (unlikely(S_ISDIR(h_mode)))
14487+ goto out;
14488+ } else if (unlikely(!S_ISDIR(h_mode))) {
14489+ err = -ENOTDIR;
14490+ goto out;
14491+ }
14492+ } else {
14493+ /* rename(2) case */
14494+ err = -EIO;
14495+ if (unlikely(h_inode))
14496+ goto out;
14497+ }
1facf9fc 14498+
4a4d8108
AM
14499+ err = -ENOENT;
14500+ /* expected parent dir is locked */
14501+ if (unlikely(h_parent != h_dentry->d_parent))
14502+ goto out;
14503+ err = 0;
14504+
14505+ /*
14506+ * rmdir a dir may break the consistency on some filesystem.
14507+ * let's try heavy test.
14508+ */
14509+ err = -EACCES;
14510+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
14511+ goto out;
14512+
14513+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
14514+ au_sbr(dentry->d_sb, bindex));
14515+ err = -EIO;
14516+ if (IS_ERR(h_latest))
14517+ goto out;
14518+ if (h_latest == h_dentry)
14519+ err = 0;
14520+ dput(h_latest);
14521+
14522+ out:
14523+ return err;
1308ab2a 14524+}
1facf9fc 14525+
4a4d8108
AM
14526+/*
14527+ * decide the branch where we operate for @dentry. the branch index will be set
14528+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
14529+ * dir for reverting.
14530+ * when a new whiteout is necessary, create it.
14531+ */
14532+static struct dentry*
14533+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
14534+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 14535+{
4a4d8108
AM
14536+ struct dentry *wh_dentry;
14537+ struct super_block *sb;
14538+ struct path h_path;
14539+ int err, need_wh;
14540+ unsigned int udba;
14541+ aufs_bindex_t bcpup;
dece6358 14542+
4a4d8108
AM
14543+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
14544+ wh_dentry = ERR_PTR(need_wh);
14545+ if (unlikely(need_wh < 0))
14546+ goto out;
14547+
14548+ sb = dentry->d_sb;
14549+ udba = au_opt_udba(sb);
14550+ bcpup = *rbcpup;
14551+ err = au_pin(pin, dentry, bcpup, udba,
14552+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14553+ wh_dentry = ERR_PTR(err);
14554+ if (unlikely(err))
14555+ goto out;
14556+
14557+ h_path.dentry = au_pinned_h_parent(pin);
14558+ if (udba != AuOpt_UDBA_NONE
14559+ && au_dbstart(dentry) == bcpup) {
14560+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
14561+ wh_dentry = ERR_PTR(err);
14562+ if (unlikely(err))
14563+ goto out_unpin;
14564+ }
14565+
14566+ h_path.mnt = au_sbr_mnt(sb, bcpup);
14567+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
14568+ wh_dentry = NULL;
14569+ if (!need_wh)
14570+ goto out; /* success, no need to create whiteout */
14571+
14572+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
14573+ if (IS_ERR(wh_dentry))
14574+ goto out_unpin;
14575+
14576+ /* returns with the parent is locked and wh_dentry is dget-ed */
14577+ goto out; /* success */
14578+
14579+ out_unpin:
14580+ au_unpin(pin);
14581+ out:
14582+ return wh_dentry;
1facf9fc 14583+}
14584+
4a4d8108
AM
14585+/*
14586+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
14587+ * in order to be revertible and save time for removing many child whiteouts
14588+ * under the dir.
14589+ * returns 1 when there are too many child whiteout and caller should remove
14590+ * them asynchronously. returns 0 when the number of children is enough small to
14591+ * remove now or the branch fs is a remote fs.
14592+ * otherwise return an error.
14593+ */
14594+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
14595+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 14596+{
4a4d8108
AM
14597+ int rmdir_later, err, dirwh;
14598+ struct dentry *h_dentry;
14599+ struct super_block *sb;
14600+
14601+ sb = dentry->d_sb;
14602+ SiMustAnyLock(sb);
14603+ h_dentry = au_h_dptr(dentry, bindex);
14604+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
14605+ if (unlikely(err))
14606+ goto out;
14607+
14608+ /* stop monitoring */
14609+ au_hn_free(au_hi(dentry->d_inode, bindex));
14610+
14611+ if (!au_test_fs_remote(h_dentry->d_sb)) {
14612+ dirwh = au_sbi(sb)->si_dirwh;
14613+ rmdir_later = (dirwh <= 1);
14614+ if (!rmdir_later)
14615+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
14616+ dirwh);
14617+ if (rmdir_later)
14618+ return rmdir_later;
14619+ }
1facf9fc 14620+
4a4d8108
AM
14621+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
14622+ if (unlikely(err)) {
14623+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
14624+ AuDLNPair(h_dentry), bindex, err);
14625+ err = 0;
14626+ }
dece6358 14627+
4a4d8108
AM
14628+ out:
14629+ AuTraceErr(err);
14630+ return err;
14631+}
1308ab2a 14632+
4a4d8108
AM
14633+/*
14634+ * final procedure for deleting a entry.
14635+ * maintain dentry and iattr.
14636+ */
14637+static void epilog(struct inode *dir, struct dentry *dentry,
14638+ aufs_bindex_t bindex)
14639+{
14640+ struct inode *inode;
1308ab2a 14641+
4a4d8108
AM
14642+ inode = dentry->d_inode;
14643+ d_drop(dentry);
14644+ inode->i_ctime = dir->i_ctime;
1308ab2a 14645+
4a4d8108
AM
14646+ if (atomic_read(&dentry->d_count) == 1) {
14647+ au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
14648+ au_update_dbstart(dentry);
dece6358 14649+ }
4a4d8108
AM
14650+ if (au_ibstart(dir) == bindex)
14651+ au_cpup_attr_timesizes(dir);
14652+ dir->i_version++;
1facf9fc 14653+}
14654+
4a4d8108
AM
14655+/*
14656+ * when an error happened, remove the created whiteout and revert everything.
14657+ */
14658+static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
14659+ struct dentry *wh_dentry, struct dentry *dentry,
14660+ struct au_dtime *dt)
1facf9fc 14661+{
4a4d8108
AM
14662+ int rerr;
14663+ struct path h_path = {
14664+ .dentry = wh_dentry,
14665+ .mnt = au_sbr_mnt(dir->i_sb, bwh)
14666+ };
dece6358 14667+
4a4d8108
AM
14668+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
14669+ if (!rerr) {
14670+ au_set_dbwh(dentry, bwh);
14671+ au_dtime_revert(dt);
14672+ return 0;
14673+ }
dece6358 14674+
4a4d8108
AM
14675+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
14676+ AuDLNPair(dentry), err, rerr);
14677+ return -EIO;
1facf9fc 14678+}
14679+
4a4d8108 14680+/* ---------------------------------------------------------------------- */
1facf9fc 14681+
4a4d8108 14682+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 14683+{
4a4d8108
AM
14684+ int err;
14685+ aufs_bindex_t bwh, bindex, bstart;
14686+ struct au_dtime dt;
14687+ struct au_pin pin;
14688+ struct path h_path;
14689+ struct inode *inode, *h_dir;
14690+ struct dentry *parent, *wh_dentry;
1facf9fc 14691+
4a4d8108
AM
14692+ IMustLock(dir);
14693+ inode = dentry->d_inode;
14694+ if (unlikely(!inode))
14695+ return -ENOENT; /* possible? */
14696+ IMustLock(inode);
1facf9fc 14697+
4a4d8108
AM
14698+ aufs_read_lock(dentry, AuLock_DW);
14699+ parent = dentry->d_parent; /* dir inode is locked */
14700+ di_write_lock_parent(parent);
1facf9fc 14701+
4a4d8108
AM
14702+ bstart = au_dbstart(dentry);
14703+ bwh = au_dbwh(dentry);
14704+ bindex = -1;
14705+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
14706+ err = PTR_ERR(wh_dentry);
14707+ if (IS_ERR(wh_dentry))
14708+ goto out;
1facf9fc 14709+
4a4d8108
AM
14710+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
14711+ h_path.dentry = au_h_dptr(dentry, bstart);
14712+ dget(h_path.dentry);
14713+ if (bindex == bstart) {
14714+ h_dir = au_pinned_h_dir(&pin);
14715+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
14716+ } else {
14717+ /* dir inode is locked */
14718+ h_dir = wh_dentry->d_parent->d_inode;
14719+ IMustLock(h_dir);
14720+ err = 0;
14721+ }
dece6358 14722+
4a4d8108
AM
14723+ if (!err) {
14724+ drop_nlink(inode);
14725+ epilog(dir, dentry, bindex);
14726+
14727+ /* update target timestamps */
14728+ if (bindex == bstart) {
14729+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
14730+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
14731+ } else
14732+ /* todo: this timestamp may be reverted later */
14733+ inode->i_ctime = h_dir->i_ctime;
14734+ goto out_unlock; /* success */
1facf9fc 14735+ }
14736+
4a4d8108
AM
14737+ /* revert */
14738+ if (wh_dentry) {
14739+ int rerr;
14740+
14741+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
14742+ if (rerr)
14743+ err = rerr;
dece6358 14744+ }
1facf9fc 14745+
4a4d8108
AM
14746+ out_unlock:
14747+ au_unpin(&pin);
14748+ dput(wh_dentry);
14749+ dput(h_path.dentry);
14750+ out:
14751+ di_write_unlock(parent);
14752+ aufs_read_unlock(dentry, AuLock_DW);
14753+ return err;
dece6358
AM
14754+}
14755+
4a4d8108 14756+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 14757+{
4a4d8108
AM
14758+ int err, rmdir_later;
14759+ aufs_bindex_t bwh, bindex, bstart;
14760+ struct au_dtime dt;
14761+ struct au_pin pin;
14762+ struct inode *inode;
14763+ struct dentry *parent, *wh_dentry, *h_dentry;
14764+ struct au_whtmp_rmdir *args;
1facf9fc 14765+
4a4d8108
AM
14766+ IMustLock(dir);
14767+ inode = dentry->d_inode;
14768+ err = -ENOENT; /* possible? */
14769+ if (unlikely(!inode))
14770+ goto out;
14771+ IMustLock(inode);
dece6358 14772+
4a4d8108
AM
14773+ aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
14774+ err = -ENOMEM;
14775+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
14776+ if (unlikely(!args))
14777+ goto out_unlock;
dece6358 14778+
4a4d8108
AM
14779+ parent = dentry->d_parent; /* dir inode is locked */
14780+ di_write_lock_parent(parent);
14781+ err = au_test_empty(dentry, &args->whlist);
14782+ if (unlikely(err))
14783+ goto out_args;
1facf9fc 14784+
4a4d8108
AM
14785+ bstart = au_dbstart(dentry);
14786+ bwh = au_dbwh(dentry);
14787+ bindex = -1;
14788+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
14789+ err = PTR_ERR(wh_dentry);
14790+ if (IS_ERR(wh_dentry))
14791+ goto out_args;
1facf9fc 14792+
4a4d8108
AM
14793+ h_dentry = au_h_dptr(dentry, bstart);
14794+ dget(h_dentry);
14795+ rmdir_later = 0;
14796+ if (bindex == bstart) {
14797+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
14798+ if (err > 0) {
14799+ rmdir_later = err;
14800+ err = 0;
14801+ }
14802+ } else {
14803+ /* stop monitoring */
14804+ au_hn_free(au_hi(inode, bstart));
14805+
14806+ /* dir inode is locked */
14807+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 14808+ err = 0;
14809+ }
14810+
4a4d8108
AM
14811+ if (!err) {
14812+ clear_nlink(inode);
14813+ au_set_dbdiropq(dentry, -1);
14814+ epilog(dir, dentry, bindex);
1308ab2a 14815+
4a4d8108
AM
14816+ if (rmdir_later) {
14817+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
14818+ args = NULL;
14819+ }
1308ab2a 14820+
4a4d8108 14821+ goto out_unpin; /* success */
1facf9fc 14822+ }
14823+
4a4d8108
AM
14824+ /* revert */
14825+ AuLabel(revert);
14826+ if (wh_dentry) {
14827+ int rerr;
1308ab2a 14828+
4a4d8108
AM
14829+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
14830+ if (rerr)
14831+ err = rerr;
1facf9fc 14832+ }
14833+
4a4d8108
AM
14834+ out_unpin:
14835+ au_unpin(&pin);
14836+ dput(wh_dentry);
14837+ dput(h_dentry);
14838+ out_args:
14839+ di_write_unlock(parent);
14840+ if (args)
14841+ au_whtmp_rmdir_free(args);
14842+ out_unlock:
14843+ aufs_read_unlock(dentry, AuLock_DW);
14844+ out:
14845+ AuTraceErr(err);
14846+ return err;
dece6358 14847+}
4a4d8108
AM
14848diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/i_op_ren.c linux-2.6.34/fs/aufs/i_op_ren.c
14849--- linux-2.6.34.org/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
14850+++ linux-2.6.34/fs/aufs/i_op_ren.c 2010-05-31 22:15:32.000000000 +0200
14851@@ -0,0 +1,977 @@
1facf9fc 14852+/*
4a4d8108 14853+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 14854+ *
14855+ * This program, aufs is free software; you can redistribute it and/or modify
14856+ * it under the terms of the GNU General Public License as published by
14857+ * the Free Software Foundation; either version 2 of the License, or
14858+ * (at your option) any later version.
dece6358
AM
14859+ *
14860+ * This program is distributed in the hope that it will be useful,
14861+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14862+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14863+ * GNU General Public License for more details.
14864+ *
14865+ * You should have received a copy of the GNU General Public License
14866+ * along with this program; if not, write to the Free Software
14867+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14868+ */
14869+
14870+/*
4a4d8108
AM
14871+ * inode operation (rename entry)
14872+ * todo: this is crazy monster
1facf9fc 14873+ */
14874+
14875+#include "aufs.h"
14876+
4a4d8108
AM
14877+enum { AuSRC, AuDST, AuSrcDst };
14878+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 14879+
4a4d8108
AM
14880+#define AuRen_ISDIR 1
14881+#define AuRen_ISSAMEDIR (1 << 1)
14882+#define AuRen_WHSRC (1 << 2)
14883+#define AuRen_WHDST (1 << 3)
14884+#define AuRen_MNT_WRITE (1 << 4)
14885+#define AuRen_DT_DSTDIR (1 << 5)
14886+#define AuRen_DIROPQ (1 << 6)
14887+#define AuRen_CPUP (1 << 7)
14888+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
14889+#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
14890+#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
1facf9fc 14891+
4a4d8108
AM
14892+struct au_ren_args {
14893+ struct {
14894+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
14895+ *wh_dentry;
14896+ struct inode *dir, *inode;
14897+ struct au_hinode *hdir;
14898+ struct au_dtime dt[AuParentChild];
14899+ aufs_bindex_t bstart;
14900+ } sd[AuSrcDst];
1facf9fc 14901+
4a4d8108
AM
14902+#define src_dentry sd[AuSRC].dentry
14903+#define src_dir sd[AuSRC].dir
14904+#define src_inode sd[AuSRC].inode
14905+#define src_h_dentry sd[AuSRC].h_dentry
14906+#define src_parent sd[AuSRC].parent
14907+#define src_h_parent sd[AuSRC].h_parent
14908+#define src_wh_dentry sd[AuSRC].wh_dentry
14909+#define src_hdir sd[AuSRC].hdir
14910+#define src_h_dir sd[AuSRC].hdir->hi_inode
14911+#define src_dt sd[AuSRC].dt
14912+#define src_bstart sd[AuSRC].bstart
1facf9fc 14913+
4a4d8108
AM
14914+#define dst_dentry sd[AuDST].dentry
14915+#define dst_dir sd[AuDST].dir
14916+#define dst_inode sd[AuDST].inode
14917+#define dst_h_dentry sd[AuDST].h_dentry
14918+#define dst_parent sd[AuDST].parent
14919+#define dst_h_parent sd[AuDST].h_parent
14920+#define dst_wh_dentry sd[AuDST].wh_dentry
14921+#define dst_hdir sd[AuDST].hdir
14922+#define dst_h_dir sd[AuDST].hdir->hi_inode
14923+#define dst_dt sd[AuDST].dt
14924+#define dst_bstart sd[AuDST].bstart
14925+
14926+ struct dentry *h_trap;
14927+ struct au_branch *br;
14928+ struct au_hinode *src_hinode;
14929+ struct path h_path;
14930+ struct au_nhash whlist;
14931+ aufs_bindex_t btgt;
1facf9fc 14932+
1308ab2a 14933+ unsigned int flags;
1facf9fc 14934+
4a4d8108
AM
14935+ struct au_whtmp_rmdir *thargs;
14936+ struct dentry *h_dst;
14937+};
1308ab2a 14938+
4a4d8108 14939+/* ---------------------------------------------------------------------- */
1308ab2a 14940+
4a4d8108
AM
14941+/*
14942+ * functions for reverting.
14943+ * when an error happened in a single rename systemcall, we should revert
14944+ * everything as if nothing happend.
14945+ * we don't need to revert the copied-up/down the parent dir since they are
14946+ * harmless.
14947+ */
1facf9fc 14948+
4a4d8108
AM
14949+#define RevertFailure(fmt, ...) do { \
14950+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
14951+ ##__VA_ARGS__, err, rerr); \
14952+ err = -EIO; \
14953+} while (0)
1facf9fc 14954+
4a4d8108 14955+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 14956+{
4a4d8108 14957+ int rerr;
1facf9fc 14958+
4a4d8108
AM
14959+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
14960+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
14961+ au_hn_imtx_unlock(a->src_hinode);
14962+ if (rerr)
14963+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
14964+}
1facf9fc 14965+
4a4d8108
AM
14966+static void au_ren_rev_rename(int err, struct au_ren_args *a)
14967+{
14968+ int rerr;
1facf9fc 14969+
4a4d8108
AM
14970+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
14971+ a->br, /*nd*/NULL);
14972+ rerr = PTR_ERR(a->h_path.dentry);
14973+ if (IS_ERR(a->h_path.dentry)) {
14974+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
14975+ return;
1facf9fc 14976+ }
14977+
4a4d8108
AM
14978+ rerr = vfsub_rename(a->dst_h_dir,
14979+ au_h_dptr(a->src_dentry, a->btgt),
14980+ a->src_h_dir, &a->h_path);
14981+ d_drop(a->h_path.dentry);
14982+ dput(a->h_path.dentry);
14983+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
14984+ if (rerr)
14985+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 14986+}
14987+
4a4d8108 14988+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 14989+{
4a4d8108 14990+ int rerr;
1facf9fc 14991+
4a4d8108
AM
14992+ a->h_path.dentry = a->dst_h_dentry;
14993+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
14994+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
14995+ au_set_dbstart(a->src_dentry, a->src_bstart);
14996+ if (rerr)
14997+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 14998+}
14999+
4a4d8108 15000+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 15001+{
4a4d8108 15002+ int rerr;
dece6358 15003+
4a4d8108
AM
15004+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
15005+ a->br, /*nd*/NULL);
15006+ rerr = PTR_ERR(a->h_path.dentry);
15007+ if (IS_ERR(a->h_path.dentry)) {
15008+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
15009+ return;
15010+ }
15011+ if (a->h_path.dentry->d_inode) {
15012+ d_drop(a->h_path.dentry);
15013+ dput(a->h_path.dentry);
15014+ return;
dece6358
AM
15015+ }
15016+
4a4d8108
AM
15017+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
15018+ d_drop(a->h_path.dentry);
15019+ dput(a->h_path.dentry);
15020+ if (!rerr)
15021+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
15022+ else
15023+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
15024+}
1308ab2a 15025+
4a4d8108
AM
15026+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
15027+{
15028+ int rerr;
1308ab2a 15029+
4a4d8108
AM
15030+ a->h_path.dentry = a->src_wh_dentry;
15031+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
15032+ if (rerr)
15033+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
15034+}
1308ab2a 15035+
4a4d8108
AM
15036+static void au_ren_rev_drop(struct au_ren_args *a)
15037+{
15038+ struct dentry *d, *h_d;
15039+ int i;
15040+ aufs_bindex_t bend, bindex;
15041+
15042+ for (i = 0; i < AuSrcDst; i++) {
15043+ d = a->sd[i].dentry;
15044+ d_drop(d);
15045+ bend = au_dbend(d);
15046+ for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
15047+ h_d = au_h_dptr(d, bindex);
15048+ if (h_d)
15049+ d_drop(h_d);
15050+ }
1308ab2a 15051+ }
15052+
4a4d8108
AM
15053+ au_update_dbstart(a->dst_dentry);
15054+ if (a->thargs)
15055+ d_drop(a->h_dst);
1facf9fc 15056+}
4a4d8108 15057+#undef RevertFailure
1facf9fc 15058+
1308ab2a 15059+/* ---------------------------------------------------------------------- */
15060+
4a4d8108
AM
15061+/*
15062+ * when we have to copyup the renaming entry, do it with the rename-target name
15063+ * in order to minimize the cost (the later actual rename is unnecessary).
15064+ * otherwise rename it on the target branch.
15065+ */
15066+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 15067+{
dece6358 15068+ int err;
4a4d8108 15069+ struct dentry *d;
1facf9fc 15070+
4a4d8108
AM
15071+ d = a->src_dentry;
15072+ if (au_dbstart(d) == a->btgt) {
15073+ a->h_path.dentry = a->dst_h_dentry;
15074+ if (au_ftest_ren(a->flags, DIROPQ)
15075+ && au_dbdiropq(d) == a->btgt)
15076+ au_fclr_ren(a->flags, DIROPQ);
15077+ AuDebugOn(au_dbstart(d) != a->btgt);
15078+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
15079+ a->dst_h_dir, &a->h_path);
15080+ } else {
15081+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15082+ struct file *h_file;
1308ab2a 15083+
4a4d8108
AM
15084+ au_fset_ren(a->flags, CPUP);
15085+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15086+ au_set_dbstart(d, a->btgt);
15087+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
15088+ h_file = au_h_open_pre(d, a->src_bstart);
15089+ if (IS_ERR(h_file)) {
15090+ err = PTR_ERR(h_file);
15091+ h_file = NULL;
15092+ } else
15093+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
15094+ !AuCpup_DTIME, a->dst_parent);
15095+ mutex_unlock(h_mtx);
15096+ au_h_open_post(d, a->src_bstart, h_file);
15097+ if (!err) {
15098+ d = a->dst_dentry;
15099+ au_set_h_dptr(d, a->btgt, NULL);
15100+ au_update_dbstart(d);
15101+ } else {
15102+ au_set_h_dptr(d, a->btgt, NULL);
15103+ au_set_dbstart(d, a->src_bstart);
15104+ }
1308ab2a 15105+ }
1facf9fc 15106+
dece6358
AM
15107+ return err;
15108+}
1facf9fc 15109+
4a4d8108
AM
15110+/* cf. aufs_rmdir() */
15111+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 15112+{
4a4d8108
AM
15113+ int err;
15114+ struct inode *dir;
1facf9fc 15115+
4a4d8108
AM
15116+ dir = a->dst_dir;
15117+ SiMustAnyLock(dir->i_sb);
15118+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
15119+ au_sbi(dir->i_sb)->si_dirwh)
15120+ || au_test_fs_remote(a->h_dst->d_sb)) {
15121+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
15122+ if (unlikely(err))
15123+ pr_warning("failed removing whtmp dir %.*s (%d), "
15124+ "ignored.\n", AuDLNPair(a->h_dst), err);
15125+ } else {
15126+ au_nhash_wh_free(&a->thargs->whlist);
15127+ a->thargs->whlist = a->whlist;
15128+ a->whlist.nh_num = 0;
15129+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
15130+ dput(a->h_dst);
15131+ a->thargs = NULL;
15132+ }
15133+
15134+ return 0;
1308ab2a 15135+}
1facf9fc 15136+
4a4d8108
AM
15137+/* make it 'opaque' dir. */
15138+static int au_ren_diropq(struct au_ren_args *a)
15139+{
15140+ int err;
15141+ struct dentry *diropq;
1facf9fc 15142+
4a4d8108
AM
15143+ err = 0;
15144+ a->src_hinode = au_hi(a->src_inode, a->btgt);
15145+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15146+ diropq = au_diropq_create(a->src_dentry, a->btgt);
15147+ au_hn_imtx_unlock(a->src_hinode);
15148+ if (IS_ERR(diropq))
15149+ err = PTR_ERR(diropq);
15150+ dput(diropq);
1facf9fc 15151+
4a4d8108
AM
15152+ return err;
15153+}
1facf9fc 15154+
4a4d8108
AM
15155+static int do_rename(struct au_ren_args *a)
15156+{
15157+ int err;
15158+ struct dentry *d, *h_d;
1facf9fc 15159+
4a4d8108
AM
15160+ /* prepare workqueue args for asynchronous rmdir */
15161+ h_d = a->dst_h_dentry;
15162+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
15163+ err = -ENOMEM;
15164+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
15165+ if (unlikely(!a->thargs))
15166+ goto out;
15167+ a->h_dst = dget(h_d);
15168+ }
1facf9fc 15169+
4a4d8108
AM
15170+ /* create whiteout for src_dentry */
15171+ if (au_ftest_ren(a->flags, WHSRC)) {
15172+ a->src_wh_dentry
15173+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
15174+ err = PTR_ERR(a->src_wh_dentry);
15175+ if (IS_ERR(a->src_wh_dentry))
15176+ goto out_thargs;
15177+ }
1facf9fc 15178+
4a4d8108
AM
15179+ /* lookup whiteout for dentry */
15180+ if (au_ftest_ren(a->flags, WHDST)) {
15181+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
15182+ a->br);
15183+ err = PTR_ERR(h_d);
15184+ if (IS_ERR(h_d))
15185+ goto out_whsrc;
15186+ if (!h_d->d_inode)
15187+ dput(h_d);
15188+ else
15189+ a->dst_wh_dentry = h_d;
15190+ }
1facf9fc 15191+
4a4d8108
AM
15192+ /* rename dentry to tmpwh */
15193+ if (a->thargs) {
15194+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
15195+ if (unlikely(err))
15196+ goto out_whdst;
dece6358 15197+
4a4d8108
AM
15198+ d = a->dst_dentry;
15199+ au_set_h_dptr(d, a->btgt, NULL);
15200+ err = au_lkup_neg(d, a->btgt);
15201+ if (unlikely(err))
15202+ goto out_whtmp;
15203+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
15204+ }
1facf9fc 15205+
4a4d8108
AM
15206+ /* cpup src */
15207+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
15208+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15209+ struct file *h_file;
1facf9fc 15210+
4a4d8108
AM
15211+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15212+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
15213+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
15214+ if (IS_ERR(h_file)) {
15215+ err = PTR_ERR(h_file);
15216+ h_file = NULL;
15217+ } else
15218+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
15219+ !AuCpup_DTIME);
15220+ mutex_unlock(h_mtx);
15221+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
15222+ if (unlikely(err))
15223+ goto out_whtmp;
15224+ }
1facf9fc 15225+
4a4d8108
AM
15226+ /* rename by vfs_rename or cpup */
15227+ d = a->dst_dentry;
15228+ if (au_ftest_ren(a->flags, ISDIR)
15229+ && (a->dst_wh_dentry
15230+ || au_dbdiropq(d) == a->btgt
15231+ /* hide the lower to keep xino */
15232+ || a->btgt < au_dbend(d)
15233+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
15234+ au_fset_ren(a->flags, DIROPQ);
15235+ err = au_ren_or_cpup(a);
15236+ if (unlikely(err))
15237+ /* leave the copied-up one */
15238+ goto out_whtmp;
1308ab2a 15239+
4a4d8108
AM
15240+ /* make dir opaque */
15241+ if (au_ftest_ren(a->flags, DIROPQ)) {
15242+ err = au_ren_diropq(a);
15243+ if (unlikely(err))
15244+ goto out_rename;
15245+ }
1308ab2a 15246+
4a4d8108
AM
15247+ /* update target timestamps */
15248+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
15249+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
15250+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
15251+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 15252+
4a4d8108
AM
15253+ /* remove whiteout for dentry */
15254+ if (a->dst_wh_dentry) {
15255+ a->h_path.dentry = a->dst_wh_dentry;
15256+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
15257+ a->dst_dentry);
15258+ if (unlikely(err))
15259+ goto out_diropq;
15260+ }
1facf9fc 15261+
4a4d8108
AM
15262+ /* remove whtmp */
15263+ if (a->thargs)
15264+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 15265+
4a4d8108
AM
15266+ err = 0;
15267+ goto out_success;
15268+
15269+ out_diropq:
15270+ if (au_ftest_ren(a->flags, DIROPQ))
15271+ au_ren_rev_diropq(err, a);
15272+ out_rename:
15273+ if (!au_ftest_ren(a->flags, CPUP))
15274+ au_ren_rev_rename(err, a);
15275+ else
15276+ au_ren_rev_cpup(err, a);
15277+ out_whtmp:
15278+ if (a->thargs)
15279+ au_ren_rev_whtmp(err, a);
15280+ out_whdst:
15281+ dput(a->dst_wh_dentry);
15282+ a->dst_wh_dentry = NULL;
15283+ out_whsrc:
15284+ if (a->src_wh_dentry)
15285+ au_ren_rev_whsrc(err, a);
15286+ au_ren_rev_drop(a);
15287+ out_success:
15288+ dput(a->src_wh_dentry);
15289+ dput(a->dst_wh_dentry);
15290+ out_thargs:
15291+ if (a->thargs) {
15292+ dput(a->h_dst);
15293+ au_whtmp_rmdir_free(a->thargs);
15294+ a->thargs = NULL;
15295+ }
15296+ out:
15297+ return err;
dece6358 15298+}
1facf9fc 15299+
1308ab2a 15300+/* ---------------------------------------------------------------------- */
1facf9fc 15301+
4a4d8108
AM
15302+/*
15303+ * test if @dentry dir can be rename destination or not.
15304+ * success means, it is a logically empty dir.
15305+ */
15306+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 15307+{
4a4d8108 15308+ return au_test_empty(dentry, whlist);
1308ab2a 15309+}
1facf9fc 15310+
4a4d8108
AM
15311+/*
15312+ * test if @dentry dir can be rename source or not.
15313+ * if it can, return 0 and @children is filled.
15314+ * success means,
15315+ * - it is a logically empty dir.
15316+ * - or, it exists on writable branch and has no children including whiteouts
15317+ * on the lower branch.
15318+ */
15319+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
15320+{
15321+ int err;
15322+ unsigned int rdhash;
15323+ aufs_bindex_t bstart;
1facf9fc 15324+
4a4d8108
AM
15325+ bstart = au_dbstart(dentry);
15326+ if (bstart != btgt) {
15327+ struct au_nhash whlist;
dece6358 15328+
4a4d8108
AM
15329+ SiMustAnyLock(dentry->d_sb);
15330+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
15331+ if (!rdhash)
15332+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
15333+ dentry));
15334+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
15335+ if (unlikely(err))
15336+ goto out;
15337+ err = au_test_empty(dentry, &whlist);
15338+ au_nhash_wh_free(&whlist);
15339+ goto out;
15340+ }
dece6358 15341+
4a4d8108
AM
15342+ if (bstart == au_dbtaildir(dentry))
15343+ return 0; /* success */
dece6358 15344+
4a4d8108 15345+ err = au_test_empty_lower(dentry);
1facf9fc 15346+
4a4d8108
AM
15347+ out:
15348+ if (err == -ENOTEMPTY) {
15349+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
15350+ " is not supported\n");
15351+ err = -EXDEV;
15352+ }
15353+ return err;
15354+}
1308ab2a 15355+
4a4d8108
AM
15356+/* side effect: sets whlist and h_dentry */
15357+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 15358+{
4a4d8108
AM
15359+ int err;
15360+ unsigned int rdhash;
15361+ struct dentry *d;
1facf9fc 15362+
4a4d8108
AM
15363+ d = a->dst_dentry;
15364+ SiMustAnyLock(d->d_sb);
1facf9fc 15365+
4a4d8108
AM
15366+ err = 0;
15367+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
15368+ rdhash = au_sbi(d->d_sb)->si_rdhash;
15369+ if (!rdhash)
15370+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
15371+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
15372+ if (unlikely(err))
15373+ goto out;
1308ab2a 15374+
4a4d8108
AM
15375+ au_set_dbstart(d, a->dst_bstart);
15376+ err = may_rename_dstdir(d, &a->whlist);
15377+ au_set_dbstart(d, a->btgt);
15378+ }
15379+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
15380+ if (unlikely(err))
15381+ goto out;
15382+
15383+ d = a->src_dentry;
15384+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
15385+ if (au_ftest_ren(a->flags, ISDIR)) {
15386+ err = may_rename_srcdir(d, a->btgt);
15387+ if (unlikely(err)) {
15388+ au_nhash_wh_free(&a->whlist);
15389+ a->whlist.nh_num = 0;
15390+ }
15391+ }
15392+ out:
15393+ return err;
1facf9fc 15394+}
15395+
4a4d8108 15396+/* ---------------------------------------------------------------------- */
1facf9fc 15397+
4a4d8108
AM
15398+/*
15399+ * simple tests for rename.
15400+ * following the checks in vfs, plus the parent-child relationship.
15401+ */
15402+static int au_may_ren(struct au_ren_args *a)
15403+{
15404+ int err, isdir;
15405+ struct inode *h_inode;
1facf9fc 15406+
4a4d8108
AM
15407+ if (a->src_bstart == a->btgt) {
15408+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
15409+ au_ftest_ren(a->flags, ISDIR));
15410+ if (unlikely(err))
15411+ goto out;
15412+ err = -EINVAL;
15413+ if (unlikely(a->src_h_dentry == a->h_trap))
15414+ goto out;
15415+ }
1facf9fc 15416+
4a4d8108
AM
15417+ err = 0;
15418+ if (a->dst_bstart != a->btgt)
15419+ goto out;
1facf9fc 15420+
4a4d8108
AM
15421+ err = -EIO;
15422+ h_inode = a->dst_h_dentry->d_inode;
15423+ isdir = !!au_ftest_ren(a->flags, ISDIR);
15424+ if (!a->dst_dentry->d_inode) {
15425+ if (unlikely(h_inode))
15426+ goto out;
15427+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
15428+ isdir);
15429+ } else {
15430+ if (unlikely(!h_inode || !h_inode->i_nlink))
15431+ goto out;
15432+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
15433+ isdir);
15434+ if (unlikely(err))
15435+ goto out;
15436+ err = -ENOTEMPTY;
15437+ if (unlikely(a->dst_h_dentry == a->h_trap))
15438+ goto out;
15439+ err = 0;
15440+ }
1facf9fc 15441+
4a4d8108
AM
15442+ out:
15443+ if (unlikely(err == -ENOENT || err == -EEXIST))
15444+ err = -EIO;
15445+ AuTraceErr(err);
15446+ return err;
15447+}
1facf9fc 15448+
1308ab2a 15449+/* ---------------------------------------------------------------------- */
1facf9fc 15450+
4a4d8108
AM
15451+/*
15452+ * locking order
15453+ * (VFS)
15454+ * - src_dir and dir by lock_rename()
15455+ * - inode if exitsts
15456+ * (aufs)
15457+ * - lock all
15458+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
15459+ * + si_read_lock
15460+ * + di_write_lock2_child()
15461+ * + di_write_lock_child()
15462+ * + ii_write_lock_child()
15463+ * + di_write_lock_child2()
15464+ * + ii_write_lock_child2()
15465+ * + src_parent and parent
15466+ * + di_write_lock_parent()
15467+ * + ii_write_lock_parent()
15468+ * + di_write_lock_parent2()
15469+ * + ii_write_lock_parent2()
15470+ * + lower src_dir and dir by vfsub_lock_rename()
15471+ * + verify the every relationships between child and parent. if any
15472+ * of them failed, unlock all and return -EBUSY.
15473+ */
15474+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 15475+{
4a4d8108
AM
15476+ struct super_block *sb;
15477+
15478+ sb = a->dst_dentry->d_sb;
15479+ if (au_ftest_ren(a->flags, MNT_WRITE))
15480+ mnt_drop_write(a->br->br_mnt);
15481+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
15482+ a->dst_h_parent, a->dst_hdir);
1308ab2a 15483+}
15484+
4a4d8108 15485+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 15486+{
4a4d8108
AM
15487+ int err;
15488+ unsigned int udba;
1308ab2a 15489+
4a4d8108
AM
15490+ err = 0;
15491+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
15492+ a->src_hdir = au_hi(a->src_dir, a->btgt);
15493+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
15494+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
15495+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
15496+ a->dst_h_parent, a->dst_hdir);
15497+ udba = au_opt_udba(a->src_dentry->d_sb);
15498+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
15499+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
15500+ err = au_busy_or_stale();
15501+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
15502+ err = au_h_verify(a->src_h_dentry, udba,
15503+ a->src_h_parent->d_inode, a->src_h_parent,
15504+ a->br);
15505+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
15506+ err = au_h_verify(a->dst_h_dentry, udba,
15507+ a->dst_h_parent->d_inode, a->dst_h_parent,
15508+ a->br);
15509+ if (!err) {
15510+ err = mnt_want_write(a->br->br_mnt);
15511+ if (unlikely(err))
15512+ goto out_unlock;
15513+ au_fset_ren(a->flags, MNT_WRITE);
15514+ goto out; /* success */
15515+ }
15516+
15517+ err = au_busy_or_stale();
15518+
15519+ out_unlock:
15520+ au_ren_unlock(a);
15521+ out:
15522+ return err;
1facf9fc 15523+}
15524+
15525+/* ---------------------------------------------------------------------- */
15526+
4a4d8108 15527+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 15528+{
4a4d8108 15529+ struct inode *dir;
dece6358 15530+
4a4d8108
AM
15531+ dir = a->dst_dir;
15532+ dir->i_version++;
15533+ if (au_ftest_ren(a->flags, ISDIR)) {
15534+ /* is this updating defined in POSIX? */
15535+ au_cpup_attr_timesizes(a->src_inode);
15536+ au_cpup_attr_nlink(dir, /*force*/1);
15537+ if (a->dst_inode) {
15538+ clear_nlink(a->dst_inode);
15539+ au_cpup_attr_timesizes(a->dst_inode);
15540+ }
15541+ }
15542+ if (au_ibstart(dir) == a->btgt)
15543+ au_cpup_attr_timesizes(dir);
dece6358 15544+
4a4d8108
AM
15545+ if (au_ftest_ren(a->flags, ISSAMEDIR))
15546+ return;
dece6358 15547+
4a4d8108
AM
15548+ dir = a->src_dir;
15549+ dir->i_version++;
15550+ if (au_ftest_ren(a->flags, ISDIR))
15551+ au_cpup_attr_nlink(dir, /*force*/1);
15552+ if (au_ibstart(dir) == a->btgt)
15553+ au_cpup_attr_timesizes(dir);
1facf9fc 15554+}
15555+
4a4d8108 15556+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 15557+{
4a4d8108
AM
15558+ aufs_bindex_t bend, bindex;
15559+ struct dentry *d, *h_d;
15560+ struct inode *i, *h_i;
15561+ struct super_block *sb;
dece6358 15562+
4a4d8108
AM
15563+ d = a->src_dentry;
15564+ au_set_dbwh(d, -1);
15565+ bend = au_dbend(d);
15566+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
15567+ h_d = au_h_dptr(d, bindex);
15568+ if (h_d)
15569+ au_set_h_dptr(d, bindex, NULL);
15570+ }
15571+ au_set_dbend(d, a->btgt);
15572+
15573+ sb = d->d_sb;
15574+ i = a->src_inode;
15575+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
15576+ return; /* success */
15577+
15578+ bend = au_ibend(i);
15579+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
15580+ h_i = au_h_iptr(i, bindex);
15581+ if (h_i) {
15582+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
15583+ /* ignore this error */
15584+ au_set_h_iptr(i, bindex, NULL, 0);
15585+ }
15586+ }
15587+ au_set_ibend(i, a->btgt);
1308ab2a 15588+}
dece6358 15589+
4a4d8108
AM
15590+/* ---------------------------------------------------------------------- */
15591+
15592+/* mainly for link(2) and rename(2) */
15593+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 15594+{
4a4d8108
AM
15595+ aufs_bindex_t bdiropq, bwh;
15596+ struct dentry *parent;
15597+ struct au_branch *br;
15598+
15599+ parent = dentry->d_parent;
15600+ IMustLock(parent->d_inode); /* dir is locked */
15601+
15602+ bdiropq = au_dbdiropq(parent);
15603+ bwh = au_dbwh(dentry);
15604+ br = au_sbr(dentry->d_sb, btgt);
15605+ if (au_br_rdonly(br)
15606+ || (0 <= bdiropq && bdiropq < btgt)
15607+ || (0 <= bwh && bwh < btgt))
15608+ btgt = -1;
15609+
15610+ AuDbg("btgt %d\n", btgt);
15611+ return btgt;
1facf9fc 15612+}
15613+
4a4d8108
AM
15614+/* sets src_bstart, dst_bstart and btgt */
15615+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 15616+{
4a4d8108
AM
15617+ int err;
15618+ struct au_wr_dir_args wr_dir_args = {
15619+ /* .force_btgt = -1, */
15620+ .flags = AuWrDir_ADD_ENTRY
15621+ };
dece6358 15622+
4a4d8108
AM
15623+ a->src_bstart = au_dbstart(a->src_dentry);
15624+ a->dst_bstart = au_dbstart(a->dst_dentry);
15625+ if (au_ftest_ren(a->flags, ISDIR))
15626+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
15627+ wr_dir_args.force_btgt = a->src_bstart;
15628+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
15629+ wr_dir_args.force_btgt = a->dst_bstart;
15630+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
15631+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
15632+ a->btgt = err;
dece6358 15633+
4a4d8108 15634+ return err;
1facf9fc 15635+}
15636+
4a4d8108 15637+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 15638+{
4a4d8108
AM
15639+ a->h_path.dentry = a->src_h_parent;
15640+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
15641+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
15642+ a->h_path.dentry = a->dst_h_parent;
15643+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
15644+ }
1facf9fc 15645+
4a4d8108
AM
15646+ au_fclr_ren(a->flags, DT_DSTDIR);
15647+ if (!au_ftest_ren(a->flags, ISDIR))
15648+ return;
dece6358 15649+
4a4d8108
AM
15650+ a->h_path.dentry = a->src_h_dentry;
15651+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
15652+ if (a->dst_h_dentry->d_inode) {
15653+ au_fset_ren(a->flags, DT_DSTDIR);
15654+ a->h_path.dentry = a->dst_h_dentry;
15655+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
15656+ }
1308ab2a 15657+}
dece6358 15658+
4a4d8108 15659+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 15660+{
4a4d8108
AM
15661+ struct dentry *h_d;
15662+ struct mutex *h_mtx;
15663+
15664+ au_dtime_revert(a->src_dt + AuPARENT);
15665+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
15666+ au_dtime_revert(a->dst_dt + AuPARENT);
15667+
15668+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
15669+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
15670+ h_mtx = &h_d->d_inode->i_mutex;
15671+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15672+ au_dtime_revert(a->src_dt + AuCHILD);
15673+ mutex_unlock(h_mtx);
15674+
15675+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
15676+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
15677+ h_mtx = &h_d->d_inode->i_mutex;
15678+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15679+ au_dtime_revert(a->dst_dt + AuCHILD);
15680+ mutex_unlock(h_mtx);
1facf9fc 15681+ }
15682+ }
15683+}
15684+
4a4d8108
AM
15685+/* ---------------------------------------------------------------------- */
15686+
15687+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
15688+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 15689+{
4a4d8108
AM
15690+ int err;
15691+ /* reduce stack space */
15692+ struct au_ren_args *a;
15693+
15694+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
15695+ IMustLock(_src_dir);
15696+ IMustLock(_dst_dir);
15697+
15698+ err = -ENOMEM;
15699+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
15700+ a = kzalloc(sizeof(*a), GFP_NOFS);
15701+ if (unlikely(!a))
15702+ goto out;
15703+
15704+ a->src_dir = _src_dir;
15705+ a->src_dentry = _src_dentry;
15706+ a->src_inode = a->src_dentry->d_inode;
15707+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
15708+ a->dst_dir = _dst_dir;
15709+ a->dst_dentry = _dst_dentry;
15710+ a->dst_inode = a->dst_dentry->d_inode;
15711+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
15712+ if (a->dst_inode) {
15713+ IMustLock(a->dst_inode);
15714+ au_igrab(a->dst_inode);
1facf9fc 15715+ }
1facf9fc 15716+
4a4d8108
AM
15717+ err = -ENOTDIR;
15718+ if (S_ISDIR(a->src_inode->i_mode)) {
15719+ au_fset_ren(a->flags, ISDIR);
15720+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
15721+ goto out_free;
15722+ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
15723+ AuLock_DIR | AuLock_FLUSH);
15724+ } else
15725+ aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
15726+ AuLock_FLUSH);
1facf9fc 15727+
4a4d8108
AM
15728+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
15729+ di_write_lock_parent(a->dst_parent);
1facf9fc 15730+
4a4d8108
AM
15731+ /* which branch we process */
15732+ err = au_ren_wbr(a);
15733+ if (unlikely(err < 0))
15734+ goto out_unlock;
15735+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
15736+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 15737+
4a4d8108
AM
15738+ /* are they available to be renamed */
15739+ err = au_ren_may_dir(a);
15740+ if (unlikely(err))
15741+ goto out_children;
1facf9fc 15742+
4a4d8108
AM
15743+ /* prepare the writable parent dir on the same branch */
15744+ if (a->dst_bstart == a->btgt) {
15745+ au_fset_ren(a->flags, WHDST);
15746+ } else {
15747+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
15748+ if (unlikely(err))
15749+ goto out_children;
15750+ }
1facf9fc 15751+
4a4d8108
AM
15752+ if (a->src_dir != a->dst_dir) {
15753+ /*
15754+ * this temporary unlock is safe,
15755+ * because both dir->i_mutex are locked.
15756+ */
15757+ di_write_unlock(a->dst_parent);
15758+ di_write_lock_parent(a->src_parent);
15759+ err = au_wr_dir_need_wh(a->src_dentry,
15760+ au_ftest_ren(a->flags, ISDIR),
15761+ &a->btgt);
15762+ di_write_unlock(a->src_parent);
15763+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
15764+ au_fclr_ren(a->flags, ISSAMEDIR);
15765+ } else
15766+ err = au_wr_dir_need_wh(a->src_dentry,
15767+ au_ftest_ren(a->flags, ISDIR),
15768+ &a->btgt);
15769+ if (unlikely(err < 0))
15770+ goto out_children;
15771+ if (err)
15772+ au_fset_ren(a->flags, WHSRC);
1facf9fc 15773+
4a4d8108
AM
15774+ /* lock them all */
15775+ err = au_ren_lock(a);
15776+ if (unlikely(err))
15777+ goto out_children;
1facf9fc 15778+
4a4d8108
AM
15779+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
15780+ err = au_may_ren(a);
15781+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
15782+ err = -ENAMETOOLONG;
15783+ if (unlikely(err))
15784+ goto out_hdir;
1facf9fc 15785+
4a4d8108
AM
15786+ /* store timestamps to be revertible */
15787+ au_ren_dt(a);
1facf9fc 15788+
4a4d8108
AM
15789+ /* here we go */
15790+ err = do_rename(a);
15791+ if (unlikely(err))
15792+ goto out_dt;
15793+
15794+ /* update dir attributes */
15795+ au_ren_refresh_dir(a);
15796+
15797+ /* dput/iput all lower dentries */
15798+ au_ren_refresh(a);
15799+
15800+ goto out_hdir; /* success */
15801+
15802+ out_dt:
15803+ au_ren_rev_dt(err, a);
15804+ out_hdir:
15805+ au_ren_unlock(a);
15806+ out_children:
15807+ au_nhash_wh_free(&a->whlist);
15808+ out_unlock:
15809+ if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
15810+ au_update_dbstart(a->dst_dentry);
15811+ d_drop(a->dst_dentry);
15812+ }
15813+ if (!err)
15814+ d_move(a->src_dentry, a->dst_dentry);
15815+ if (au_ftest_ren(a->flags, ISSAMEDIR))
15816+ di_write_unlock(a->dst_parent);
15817+ else
15818+ di_write_unlock2(a->src_parent, a->dst_parent);
15819+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
15820+ out_free:
15821+ iput(a->dst_inode);
15822+ if (a->thargs)
15823+ au_whtmp_rmdir_free(a->thargs);
15824+ kfree(a);
15825+ out:
15826+ AuTraceErr(err);
15827+ return err;
1308ab2a 15828+}
4a4d8108
AM
15829diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/Kconfig linux-2.6.34/fs/aufs/Kconfig
15830--- linux-2.6.34.org/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
15831+++ linux-2.6.34/fs/aufs/Kconfig 2010-05-31 22:15:32.000000000 +0200
15832@@ -0,0 +1,175 @@
15833+config AUFS_FS
15834+ tristate "Aufs (Advanced multi layered unification filesystem) support"
15835+ depends on EXPERIMENTAL
15836+ help
15837+ Aufs is a stackable unification filesystem such as Unionfs,
15838+ which unifies several directories and provides a merged single
15839+ directory.
15840+ In the early days, aufs was entirely re-designed and
15841+ re-implemented Unionfs Version 1.x series. Introducing many
15842+ original ideas, approaches and improvements, it becomes totally
15843+ different from Unionfs while keeping the basic features.
1facf9fc 15844+
4a4d8108
AM
15845+if AUFS_FS
15846+choice
15847+ prompt "Maximum number of branches"
15848+ default AUFS_BRANCH_MAX_127
15849+ help
15850+ Specifies the maximum number of branches (or member directories)
15851+ in a single aufs. The larger value consumes more system
15852+ resources and has a minor impact to performance.
15853+config AUFS_BRANCH_MAX_127
15854+ bool "127"
15855+ help
15856+ Specifies the maximum number of branches (or member directories)
15857+ in a single aufs. The larger value consumes more system
15858+ resources and has a minor impact to performance.
15859+config AUFS_BRANCH_MAX_511
15860+ bool "511"
15861+ help
15862+ Specifies the maximum number of branches (or member directories)
15863+ in a single aufs. The larger value consumes more system
15864+ resources and has a minor impact to performance.
15865+config AUFS_BRANCH_MAX_1023
15866+ bool "1023"
15867+ help
15868+ Specifies the maximum number of branches (or member directories)
15869+ in a single aufs. The larger value consumes more system
15870+ resources and has a minor impact to performance.
15871+config AUFS_BRANCH_MAX_32767
15872+ bool "32767"
15873+ help
15874+ Specifies the maximum number of branches (or member directories)
15875+ in a single aufs. The larger value consumes more system
15876+ resources and has a minor impact to performance.
15877+endchoice
1facf9fc 15878+
4a4d8108
AM
15879+config AUFS_HNOTIFY
15880+ bool "Detect direct branch access (bypassing aufs)"
15881+ help
15882+ If you want to modify files on branches directly, eg. bypassing aufs,
15883+ and want aufs to detect the changes of them fully, then enable this
15884+ option and use 'udba=notify' mount option.
15885+ It will have a negative impact to the performance.
15886+ See detail in aufs.5.
dece6358 15887+
dece6358 15888+
4a4d8108
AM
15889+choice
15890+ prompt "method" if AUFS_HNOTIFY
15891+ default AUFS_HFSNOTIFY
15892+config AUFS_HFSNOTIFY
15893+ bool "fsnotify"
15894+ select FSNOTIFY
15895+config AUFS_HINOTIFY
15896+ bool "inotify (DEPRECATED)"
15897+ depends on INOTIFY
15898+endchoice
1facf9fc 15899+
4a4d8108
AM
15900+config AUFS_EXPORT
15901+ bool "NFS-exportable aufs"
15902+ depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
15903+ help
15904+ If you want to export your mounted aufs via NFS, then enable this
15905+ option. There are several requirements for this configuration.
15906+ See detail in aufs.5.
1facf9fc 15907+
4a4d8108
AM
15908+config AUFS_INO_T_64
15909+ bool
15910+ depends on AUFS_EXPORT
15911+ depends on 64BIT && !(ALPHA || S390)
15912+ default y
15913+ help
15914+ Automatic configuration for internal use.
15915+ /* typedef unsigned long/int __kernel_ino_t */
15916+ /* alpha and s390x are int */
1facf9fc 15917+
4a4d8108
AM
15918+config AUFS_RDU
15919+ bool "Readdir in userspace"
15920+ help
15921+ Aufs has two methods to provide a merged view for a directory,
15922+ by a user-space library and by kernel-space natively. The latter
15923+ is always enabled but sometimes large and slow.
15924+ If you enable this option, install the library in aufs2-util
15925+ package, and set some environment variables for your readdir(3),
15926+ then the work will be handled in user-space which generally
15927+ shows better performance in most cases.
15928+ See detail in aufs.5.
1facf9fc 15929+
4a4d8108
AM
15930+config AUFS_SP_IATTR
15931+ bool "Respect the attributes (mtime/ctime mainly) of special files"
15932+ help
15933+ When you write something to a special file, some attributes of it
15934+ (mtime/ctime mainly) may be updated. Generally such updates are
15935+ less important (actually some device drivers and NFS ignore
15936+ it). But some applications (such like test program) requires
15937+ such updates. If you need these updates, then enable this
15938+ configuration which introduces some overhead.
15939+ Currently this configuration handles FIFO only.
1facf9fc 15940+
4a4d8108
AM
15941+config AUFS_SHWH
15942+ bool "Show whiteouts"
15943+ help
15944+ If you want to make the whiteouts in aufs visible, then enable
15945+ this option and specify 'shwh' mount option. Although it may
15946+ sounds like philosophy or something, but in technically it
15947+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 15948+
4a4d8108
AM
15949+config AUFS_BR_RAMFS
15950+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
15951+ help
15952+ If you want to use ramfs as an aufs branch fs, then enable this
15953+ option. Generally tmpfs is recommended.
15954+ Aufs prohibited them to be a branch fs by default, because
15955+ initramfs becomes unusable after switch_root or something
15956+ generally. If you sets initramfs as an aufs branch and boot your
15957+ system by switch_root, you will meet a problem easily since the
15958+ files in initramfs may be inaccessible.
15959+ Unless you are going to use ramfs as an aufs branch fs without
15960+ switch_root or something, leave it N.
1facf9fc 15961+
4a4d8108
AM
15962+config AUFS_BR_FUSE
15963+ bool "Fuse fs as an aufs branch"
15964+ depends on FUSE_FS
15965+ select AUFS_POLL
15966+ help
15967+ If you want to use fuse-based userspace filesystem as an aufs
15968+ branch fs, then enable this option.
15969+ It implements the internal poll(2) operation which is
15970+ implemented by fuse only (curretnly).
1facf9fc 15971+
4a4d8108
AM
15972+config AUFS_POLL
15973+ bool
15974+ help
15975+ Automatic configuration for internal use.
1facf9fc 15976+
4a4d8108
AM
15977+config AUFS_BR_HFSPLUS
15978+ bool "Hfsplus as an aufs branch"
15979+ depends on HFSPLUS_FS
15980+ default y
15981+ help
15982+ If you want to use hfsplus fs as an aufs branch fs, then enable
15983+ this option. This option introduces a small overhead at
15984+ copying-up a file on hfsplus.
1facf9fc 15985+
4a4d8108
AM
15986+config AUFS_BDEV_LOOP
15987+ bool
15988+ depends on BLK_DEV_LOOP
15989+ default y
15990+ help
15991+ Automatic configuration for internal use.
15992+ Convert =[ym] into =y.
1308ab2a 15993+
4a4d8108
AM
15994+config AUFS_DEBUG
15995+ bool "Debug aufs"
15996+ help
15997+ Enable this to compile aufs internal debug code.
15998+ It will have a negative impact to the performance.
15999+
16000+config AUFS_MAGIC_SYSRQ
16001+ bool
16002+ depends on AUFS_DEBUG && MAGIC_SYSRQ
16003+ default y
16004+ help
16005+ Automatic configuration for internal use.
16006+ When aufs supports Magic SysRq, enabled automatically.
16007+endif
16008diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/loop.c linux-2.6.34/fs/aufs/loop.c
16009--- linux-2.6.34.org/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
16010+++ linux-2.6.34/fs/aufs/loop.c 2010-05-31 22:15:32.000000000 +0200
dece6358 16011@@ -0,0 +1,55 @@
1facf9fc 16012+/*
4a4d8108 16013+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16014+ *
16015+ * This program, aufs is free software; you can redistribute it and/or modify
16016+ * it under the terms of the GNU General Public License as published by
16017+ * the Free Software Foundation; either version 2 of the License, or
16018+ * (at your option) any later version.
dece6358
AM
16019+ *
16020+ * This program is distributed in the hope that it will be useful,
16021+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16022+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16023+ * GNU General Public License for more details.
16024+ *
16025+ * You should have received a copy of the GNU General Public License
16026+ * along with this program; if not, write to the Free Software
16027+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16028+ */
16029+
16030+/*
16031+ * support for loopback block device as a branch
16032+ */
16033+
16034+#include <linux/loop.h>
16035+#include "aufs.h"
16036+
16037+/*
16038+ * test if two lower dentries have overlapping branches.
16039+ */
16040+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
16041+ struct dentry *h_d2)
16042+{
16043+ struct inode *h_inode;
16044+ struct loop_device *l;
16045+
16046+ h_inode = h_d1->d_inode;
16047+ if (MAJOR(h_inode->i_sb->s_dev) != LOOP_MAJOR)
16048+ return 0;
16049+
16050+ l = h_inode->i_sb->s_bdev->bd_disk->private_data;
16051+ h_d1 = l->lo_backing_file->f_dentry;
16052+ /* h_d1 can be local NFS. in this case aufs cannot detect the loop */
16053+ if (unlikely(h_d1->d_sb == sb))
16054+ return 1;
4a4d8108 16055+ return au_test_subdir(h_d1, h_d2);
1facf9fc 16056+}
16057+
16058+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
16059+int au_test_loopback_kthread(void)
16060+{
16061+ const char c = current->comm[4];
16062+
16063+ return current->mm == NULL
16064+ && '0' <= c && c <= '9'
16065+ && strncmp(current->comm, "loop", 4) == 0;
16066+}
4a4d8108
AM
16067diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/loop.h linux-2.6.34/fs/aufs/loop.h
16068--- linux-2.6.34.org/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
16069+++ linux-2.6.34/fs/aufs/loop.h 2010-05-31 22:15:32.000000000 +0200
16070@@ -0,0 +1,43 @@
1facf9fc 16071+/*
4a4d8108 16072+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16073+ *
16074+ * This program, aufs is free software; you can redistribute it and/or modify
16075+ * it under the terms of the GNU General Public License as published by
16076+ * the Free Software Foundation; either version 2 of the License, or
16077+ * (at your option) any later version.
dece6358
AM
16078+ *
16079+ * This program is distributed in the hope that it will be useful,
16080+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16081+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16082+ * GNU General Public License for more details.
16083+ *
16084+ * You should have received a copy of the GNU General Public License
16085+ * along with this program; if not, write to the Free Software
16086+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16087+ */
16088+
16089+/*
16090+ * support for loopback mount as a branch
16091+ */
16092+
16093+#ifndef __AUFS_LOOP_H__
16094+#define __AUFS_LOOP_H__
16095+
16096+#ifdef __KERNEL__
16097+
dece6358
AM
16098+struct dentry;
16099+struct super_block;
1facf9fc 16100+
16101+#ifdef CONFIG_AUFS_BDEV_LOOP
16102+/* loop.c */
16103+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
16104+ struct dentry *h_d2);
16105+int au_test_loopback_kthread(void);
16106+#else
4a4d8108
AM
16107+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
16108+ struct dentry *h_d1, struct dentry *h_d2)
16109+AuStubInt0(au_test_loopback_kthread, void)
1facf9fc 16110+#endif /* BLK_DEV_LOOP */
16111+
16112+#endif /* __KERNEL__ */
16113+#endif /* __AUFS_LOOP_H__ */
4a4d8108
AM
16114diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/magic.mk linux-2.6.34/fs/aufs/magic.mk
16115--- linux-2.6.34.org/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
16116+++ linux-2.6.34/fs/aufs/magic.mk 2010-05-31 22:15:32.000000000 +0200
16117@@ -0,0 +1,54 @@
1facf9fc 16118+
16119+# defined in ${srctree}/fs/fuse/inode.c
16120+# tristate
16121+ifdef CONFIG_FUSE_FS
16122+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
16123+endif
16124+
16125+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
16126+# tristate
16127+ifdef CONFIG_OCFS2_FS
16128+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
16129+endif
16130+
16131+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
16132+# tristate
16133+ifdef CONFIG_OCFS2_FS_O2CB
16134+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
16135+endif
16136+
1facf9fc 16137+# defined in ${srctree}/fs/cifs/cifsfs.c
16138+# tristate
16139+ifdef CONFIG_CIFS_FS
16140+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
16141+endif
16142+
16143+# defined in ${srctree}/fs/xfs/xfs_sb.h
16144+# tristate
16145+ifdef CONFIG_XFS_FS
16146+ccflags-y += -DXFS_SB_MAGIC=0x58465342
16147+endif
16148+
16149+# defined in ${srctree}/fs/configfs/mount.c
16150+# tristate
16151+ifdef CONFIG_CONFIGFS_FS
16152+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
16153+endif
16154+
16155+# defined in ${srctree}/fs/9p/v9fs.h
16156+# tristate
16157+ifdef CONFIG_9P_FS
16158+ccflags-y += -DV9FS_MAGIC=0x01021997
16159+endif
16160+
16161+# defined in ${srctree}/fs/ubifs/ubifs.h
16162+# tristate
16163+ifdef CONFIG_UBIFS_FS
16164+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
16165+endif
4a4d8108
AM
16166+
16167+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
16168+# tristate
16169+ifdef CONFIG_HFSPLUS_FS
16170+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
16171+endif
16172diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/Makefile linux-2.6.34/fs/aufs/Makefile
16173--- linux-2.6.34.org/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
16174+++ linux-2.6.34/fs/aufs/Makefile 2010-05-31 22:15:32.000000000 +0200
16175@@ -0,0 +1,38 @@
16176+
16177+include ${src}/magic.mk
16178+ifeq (${CONFIG_AUFS_FS},m)
16179+include ${src}/conf.mk
16180+endif
16181+-include ${src}/priv_def.mk
16182+
16183+# cf. include/linux/kernel.h
16184+# enable pr_debug
16185+ccflags-y += -DDEBUG
16186+ccflags-y += -D'pr_fmt(fmt)="aufs %s:%d:%s[%d]: " fmt, \
16187+ __func__, __LINE__, current->comm, current->pid'
16188+
16189+obj-$(CONFIG_AUFS_FS) += aufs.o
16190+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
16191+ wkq.o vfsub.o dcsub.o \
16192+ cpup.o whout.o plink.o wbr_policy.o \
16193+ dinfo.o dentry.o \
16194+ dynop.o \
16195+ finfo.o file.o f_op.o \
16196+ dir.o vdir.o \
16197+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
16198+ ioctl.o
16199+
16200+# all are boolean
16201+aufs-$(CONFIG_SYSFS) += sysfs.o
16202+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
16203+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
16204+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
16205+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
16206+aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
16207+aufs-$(CONFIG_AUFS_EXPORT) += export.o
16208+aufs-$(CONFIG_AUFS_POLL) += poll.o
16209+aufs-$(CONFIG_AUFS_RDU) += rdu.o
16210+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
16211+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
16212+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
16213+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
16214diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/module.c linux-2.6.34/fs/aufs/module.c
16215--- linux-2.6.34.org/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
16216+++ linux-2.6.34/fs/aufs/module.c 2010-05-31 22:15:32.000000000 +0200
16217@@ -0,0 +1,171 @@
1facf9fc 16218+/*
4a4d8108 16219+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16220+ *
16221+ * This program, aufs is free software; you can redistribute it and/or modify
16222+ * it under the terms of the GNU General Public License as published by
16223+ * the Free Software Foundation; either version 2 of the License, or
16224+ * (at your option) any later version.
dece6358
AM
16225+ *
16226+ * This program is distributed in the hope that it will be useful,
16227+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16228+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16229+ * GNU General Public License for more details.
16230+ *
16231+ * You should have received a copy of the GNU General Public License
16232+ * along with this program; if not, write to the Free Software
16233+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16234+ */
16235+
16236+/*
16237+ * module global variables and operations
16238+ */
16239+
16240+#include <linux/module.h>
16241+#include <linux/seq_file.h>
16242+#include "aufs.h"
16243+
16244+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
16245+{
16246+ if (new_sz <= nused)
16247+ return p;
16248+
16249+ p = krealloc(p, new_sz, gfp);
16250+ if (p)
16251+ memset(p + nused, 0, new_sz - nused);
16252+ return p;
16253+}
16254+
16255+/* ---------------------------------------------------------------------- */
16256+
16257+/*
16258+ * aufs caches
16259+ */
16260+struct kmem_cache *au_cachep[AuCache_Last];
16261+static int __init au_cache_init(void)
16262+{
4a4d8108 16263+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 16264+ if (au_cachep[AuCache_DINFO])
4a4d8108
AM
16265+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
16266+ au_icntnr_init_once);
1facf9fc 16267+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
16268+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
16269+ au_fi_init_once);
1facf9fc 16270+ if (au_cachep[AuCache_FINFO])
16271+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
16272+ if (au_cachep[AuCache_VDIR])
16273+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
16274+ if (au_cachep[AuCache_DEHSTR])
16275+ return 0;
16276+
16277+ return -ENOMEM;
16278+}
16279+
16280+static void au_cache_fin(void)
16281+{
16282+ int i;
4a4d8108
AM
16283+
16284+ /* including AuCache_HNOTIFY */
1facf9fc 16285+ for (i = 0; i < AuCache_Last; i++)
16286+ if (au_cachep[i]) {
16287+ kmem_cache_destroy(au_cachep[i]);
16288+ au_cachep[i] = NULL;
16289+ }
16290+}
16291+
16292+/* ---------------------------------------------------------------------- */
16293+
16294+int au_dir_roflags;
16295+
16296+/*
16297+ * functions for module interface.
16298+ */
16299+MODULE_LICENSE("GPL");
16300+/* MODULE_LICENSE("GPL v2"); */
dece6358 16301+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 16302+MODULE_DESCRIPTION(AUFS_NAME
16303+ " -- Advanced multi layered unification filesystem");
16304+MODULE_VERSION(AUFS_VERSION);
16305+
1facf9fc 16306+/* this module parameter has no meaning when SYSFS is disabled */
16307+int sysaufs_brs = 1;
16308+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
16309+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
16310+
16311+/* ---------------------------------------------------------------------- */
16312+
16313+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
16314+
16315+int au_seq_path(struct seq_file *seq, struct path *path)
16316+{
16317+ return seq_path(seq, path, au_esc_chars);
16318+}
16319+
16320+/* ---------------------------------------------------------------------- */
16321+
16322+static int __init aufs_init(void)
16323+{
16324+ int err, i;
16325+ char *p;
16326+
16327+ p = au_esc_chars;
16328+ for (i = 1; i <= ' '; i++)
16329+ *p++ = i;
16330+ *p++ = '\\';
16331+ *p++ = '\x7f';
16332+ *p = 0;
16333+
16334+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
16335+
16336+ sysaufs_brs_init();
16337+ au_debug_init();
4a4d8108 16338+ au_dy_init();
1facf9fc 16339+ err = sysaufs_init();
16340+ if (unlikely(err))
16341+ goto out;
16342+ err = au_wkq_init();
16343+ if (unlikely(err))
16344+ goto out_sysaufs;
4a4d8108 16345+ err = au_hnotify_init();
1facf9fc 16346+ if (unlikely(err))
16347+ goto out_wkq;
16348+ err = au_sysrq_init();
16349+ if (unlikely(err))
16350+ goto out_hin;
16351+ err = au_cache_init();
16352+ if (unlikely(err))
16353+ goto out_sysrq;
16354+ err = register_filesystem(&aufs_fs_type);
16355+ if (unlikely(err))
16356+ goto out_cache;
4a4d8108
AM
16357+ /* since we define pr_fmt, call printk directly */
16358+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 16359+ goto out; /* success */
16360+
16361+ out_cache:
16362+ au_cache_fin();
16363+ out_sysrq:
16364+ au_sysrq_fin();
16365+ out_hin:
4a4d8108 16366+ au_hnotify_fin();
1facf9fc 16367+ out_wkq:
16368+ au_wkq_fin();
16369+ out_sysaufs:
16370+ sysaufs_fin();
4a4d8108 16371+ au_dy_fin();
1facf9fc 16372+ out:
16373+ return err;
16374+}
16375+
16376+static void __exit aufs_exit(void)
16377+{
16378+ unregister_filesystem(&aufs_fs_type);
16379+ au_cache_fin();
16380+ au_sysrq_fin();
4a4d8108 16381+ au_hnotify_fin();
1facf9fc 16382+ au_wkq_fin();
16383+ sysaufs_fin();
4a4d8108 16384+ au_dy_fin();
1facf9fc 16385+}
16386+
16387+module_init(aufs_init);
16388+module_exit(aufs_exit);
4a4d8108
AM
16389diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/module.h linux-2.6.34/fs/aufs/module.h
16390--- linux-2.6.34.org/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
16391+++ linux-2.6.34/fs/aufs/module.h 2010-05-31 22:15:32.000000000 +0200
16392@@ -0,0 +1,82 @@
1facf9fc 16393+/*
4a4d8108 16394+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16395+ *
16396+ * This program, aufs is free software; you can redistribute it and/or modify
16397+ * it under the terms of the GNU General Public License as published by
16398+ * the Free Software Foundation; either version 2 of the License, or
16399+ * (at your option) any later version.
dece6358
AM
16400+ *
16401+ * This program is distributed in the hope that it will be useful,
16402+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16403+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16404+ * GNU General Public License for more details.
16405+ *
16406+ * You should have received a copy of the GNU General Public License
16407+ * along with this program; if not, write to the Free Software
16408+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16409+ */
16410+
16411+/*
16412+ * module initialization and module-global
16413+ */
16414+
16415+#ifndef __AUFS_MODULE_H__
16416+#define __AUFS_MODULE_H__
16417+
16418+#ifdef __KERNEL__
16419+
16420+#include <linux/slab.h>
16421+
dece6358
AM
16422+struct path;
16423+struct seq_file;
16424+
1facf9fc 16425+/* module parameters */
1facf9fc 16426+extern int sysaufs_brs;
16427+
16428+/* ---------------------------------------------------------------------- */
16429+
16430+extern int au_dir_roflags;
16431+
16432+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
16433+int au_seq_path(struct seq_file *seq, struct path *path);
16434+
16435+/* ---------------------------------------------------------------------- */
16436+
16437+/* kmem cache */
16438+enum {
16439+ AuCache_DINFO,
16440+ AuCache_ICNTNR,
16441+ AuCache_FINFO,
16442+ AuCache_VDIR,
16443+ AuCache_DEHSTR,
4a4d8108
AM
16444+#ifdef CONFIG_AUFS_HNOTIFY
16445+ AuCache_HNOTIFY,
1facf9fc 16446+#endif
16447+ AuCache_Last
16448+};
16449+
4a4d8108
AM
16450+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
16451+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
16452+#define AuCacheCtor(type, ctor) \
16453+ kmem_cache_create(#type, sizeof(struct type), \
16454+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 16455+
16456+extern struct kmem_cache *au_cachep[];
16457+
16458+#define AuCacheFuncs(name, index) \
4a4d8108 16459+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 16460+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 16461+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 16462+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
16463+
16464+AuCacheFuncs(dinfo, DINFO);
16465+AuCacheFuncs(icntnr, ICNTNR);
16466+AuCacheFuncs(finfo, FINFO);
16467+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
16468+AuCacheFuncs(vdir_dehstr, DEHSTR);
16469+#ifdef CONFIG_AUFS_HNOTIFY
16470+AuCacheFuncs(hnotify, HNOTIFY);
16471+#endif
1facf9fc 16472+
4a4d8108
AM
16473+#endif /* __KERNEL__ */
16474+#endif /* __AUFS_MODULE_H__ */
16475diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/mtx.h linux-2.6.34/fs/aufs/mtx.h
16476--- linux-2.6.34.org/fs/aufs/mtx.h 1970-01-01 01:00:00.000000000 +0100
16477+++ linux-2.6.34/fs/aufs/mtx.h 2010-05-31 22:15:32.000000000 +0200
16478@@ -0,0 +1,48 @@
16479+/*
16480+ * Copyright (C) 2010 Junjiro R. Okajima
16481+ *
16482+ * This program, aufs is free software; you can redistribute it and/or modify
16483+ * it under the terms of the GNU General Public License as published by
16484+ * the Free Software Foundation; either version 2 of the License, or
16485+ * (at your option) any later version.
16486+ *
16487+ * This program is distributed in the hope that it will be useful,
16488+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16489+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16490+ * GNU General Public License for more details.
16491+ *
16492+ * You should have received a copy of the GNU General Public License
16493+ * along with this program; if not, write to the Free Software
16494+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16495+ */
16496+
16497+/*
16498+ * very ugly approach for aufs_mmap()
16499+ * never include this file from other than f_op.c.
16500+ * see f_op.c in detail.
16501+ */
16502+
16503+#ifndef __AUFS_MTX_H__
16504+#define __AUFS_MTX_H__
16505+
16506+#ifdef __KERNEL__
16507+
16508+/* copied from ../kernel/mutex{,-debug}.h */
16509+struct mutex;
16510+struct thread_info;
16511+#ifdef CONFIG_DEBUG_MUTEXES
16512+static inline void mutex_set_owner(struct mutex *lock)
16513+{
16514+ lock->owner = current_thread_info();
16515+}
16516+#else
16517+static inline void mutex_set_owner(struct mutex *lock)
16518+{
16519+#ifdef CONFIG_SMP
16520+ lock->owner = current_thread_info();
16521+#endif
16522+}
16523+#endif
1facf9fc 16524+
16525+#endif /* __KERNEL__ */
4a4d8108
AM
16526+#endif /* __AUFS_MTX_H__ */
16527diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/opts.c linux-2.6.34/fs/aufs/opts.c
16528--- linux-2.6.34.org/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
16529+++ linux-2.6.34/fs/aufs/opts.c 2010-05-31 22:15:32.000000000 +0200
16530@@ -0,0 +1,1585 @@
1facf9fc 16531+/*
4a4d8108 16532+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16533+ *
16534+ * This program, aufs is free software; you can redistribute it and/or modify
16535+ * it under the terms of the GNU General Public License as published by
16536+ * the Free Software Foundation; either version 2 of the License, or
16537+ * (at your option) any later version.
dece6358
AM
16538+ *
16539+ * This program is distributed in the hope that it will be useful,
16540+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16541+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16542+ * GNU General Public License for more details.
16543+ *
16544+ * You should have received a copy of the GNU General Public License
16545+ * along with this program; if not, write to the Free Software
16546+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16547+ */
16548+
16549+/*
16550+ * mount options/flags
16551+ */
16552+
dece6358
AM
16553+#include <linux/file.h>
16554+#include <linux/namei.h>
1facf9fc 16555+#include <linux/types.h> /* a distribution requires */
16556+#include <linux/parser.h>
16557+#include "aufs.h"
16558+
16559+/* ---------------------------------------------------------------------- */
16560+
16561+enum {
16562+ Opt_br,
16563+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
16564+ Opt_idel, Opt_imod, Opt_ireorder,
16565+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 16566+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 16567+ Opt_xino, Opt_zxino, Opt_noxino,
16568+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
16569+ Opt_trunc_xino_path, Opt_itrunc_xino,
16570+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 16571+ Opt_shwh, Opt_noshwh,
1facf9fc 16572+ Opt_plink, Opt_noplink, Opt_list_plink,
16573+ Opt_udba,
4a4d8108 16574+ Opt_dio, Opt_nodio,
1facf9fc 16575+ /* Opt_lock, Opt_unlock, */
16576+ Opt_cmd, Opt_cmd_args,
16577+ Opt_diropq_a, Opt_diropq_w,
16578+ Opt_warn_perm, Opt_nowarn_perm,
16579+ Opt_wbr_copyup, Opt_wbr_create,
16580+ Opt_refrof, Opt_norefrof,
16581+ Opt_verbose, Opt_noverbose,
16582+ Opt_sum, Opt_nosum, Opt_wsum,
16583+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
16584+};
16585+
16586+static match_table_t options = {
16587+ {Opt_br, "br=%s"},
16588+ {Opt_br, "br:%s"},
16589+
16590+ {Opt_add, "add=%d:%s"},
16591+ {Opt_add, "add:%d:%s"},
16592+ {Opt_add, "ins=%d:%s"},
16593+ {Opt_add, "ins:%d:%s"},
16594+ {Opt_append, "append=%s"},
16595+ {Opt_append, "append:%s"},
16596+ {Opt_prepend, "prepend=%s"},
16597+ {Opt_prepend, "prepend:%s"},
16598+
16599+ {Opt_del, "del=%s"},
16600+ {Opt_del, "del:%s"},
16601+ /* {Opt_idel, "idel:%d"}, */
16602+ {Opt_mod, "mod=%s"},
16603+ {Opt_mod, "mod:%s"},
16604+ /* {Opt_imod, "imod:%d:%s"}, */
16605+
16606+ {Opt_dirwh, "dirwh=%d"},
16607+
16608+ {Opt_xino, "xino=%s"},
16609+ {Opt_noxino, "noxino"},
16610+ {Opt_trunc_xino, "trunc_xino"},
16611+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
16612+ {Opt_notrunc_xino, "notrunc_xino"},
16613+ {Opt_trunc_xino_path, "trunc_xino=%s"},
16614+ {Opt_itrunc_xino, "itrunc_xino=%d"},
16615+ /* {Opt_zxino, "zxino=%s"}, */
16616+ {Opt_trunc_xib, "trunc_xib"},
16617+ {Opt_notrunc_xib, "notrunc_xib"},
16618+
16619+ {Opt_plink, "plink"},
16620+ {Opt_noplink, "noplink"},
16621+#ifdef CONFIG_AUFS_DEBUG
16622+ {Opt_list_plink, "list_plink"},
16623+#endif
16624+
16625+ {Opt_udba, "udba=%s"},
16626+
4a4d8108
AM
16627+ {Opt_dio, "dio"},
16628+ {Opt_nodio, "nodio"},
16629+
1facf9fc 16630+ {Opt_diropq_a, "diropq=always"},
16631+ {Opt_diropq_a, "diropq=a"},
16632+ {Opt_diropq_w, "diropq=whiteouted"},
16633+ {Opt_diropq_w, "diropq=w"},
16634+
16635+ {Opt_warn_perm, "warn_perm"},
16636+ {Opt_nowarn_perm, "nowarn_perm"},
16637+
16638+ /* keep them temporary */
16639+ {Opt_ignore_silent, "coo=%s"},
16640+ {Opt_ignore_silent, "nodlgt"},
16641+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 16642+ {Opt_ignore_silent, "clean_plink"},
16643+
dece6358
AM
16644+#ifdef CONFIG_AUFS_SHWH
16645+ {Opt_shwh, "shwh"},
16646+#endif
16647+ {Opt_noshwh, "noshwh"},
16648+
1facf9fc 16649+ {Opt_rendir, "rendir=%d"},
16650+
16651+ {Opt_refrof, "refrof"},
16652+ {Opt_norefrof, "norefrof"},
16653+
16654+ {Opt_verbose, "verbose"},
16655+ {Opt_verbose, "v"},
16656+ {Opt_noverbose, "noverbose"},
16657+ {Opt_noverbose, "quiet"},
16658+ {Opt_noverbose, "q"},
16659+ {Opt_noverbose, "silent"},
16660+
16661+ {Opt_sum, "sum"},
16662+ {Opt_nosum, "nosum"},
16663+ {Opt_wsum, "wsum"},
16664+
16665+ {Opt_rdcache, "rdcache=%d"},
16666+ {Opt_rdblk, "rdblk=%d"},
dece6358 16667+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 16668+ {Opt_rdhash, "rdhash=%d"},
dece6358 16669+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 16670+
16671+ {Opt_wbr_create, "create=%s"},
16672+ {Opt_wbr_create, "create_policy=%s"},
16673+ {Opt_wbr_copyup, "cpup=%s"},
16674+ {Opt_wbr_copyup, "copyup=%s"},
16675+ {Opt_wbr_copyup, "copyup_policy=%s"},
16676+
16677+ /* internal use for the scripts */
16678+ {Opt_ignore_silent, "si=%s"},
16679+
16680+ {Opt_br, "dirs=%s"},
16681+ {Opt_ignore, "debug=%d"},
16682+ {Opt_ignore, "delete=whiteout"},
16683+ {Opt_ignore, "delete=all"},
16684+ {Opt_ignore, "imap=%s"},
16685+
1308ab2a 16686+ /* temporary workaround, due to old mount(8)? */
16687+ {Opt_ignore_silent, "relatime"},
16688+
1facf9fc 16689+ {Opt_err, NULL}
16690+};
16691+
16692+/* ---------------------------------------------------------------------- */
16693+
16694+static const char *au_parser_pattern(int val, struct match_token *token)
16695+{
16696+ while (token->pattern) {
16697+ if (token->token == val)
16698+ return token->pattern;
16699+ token++;
16700+ }
16701+ BUG();
16702+ return "??";
16703+}
16704+
16705+/* ---------------------------------------------------------------------- */
16706+
16707+static match_table_t brperms = {
16708+ {AuBrPerm_RO, AUFS_BRPERM_RO},
16709+ {AuBrPerm_RR, AUFS_BRPERM_RR},
16710+ {AuBrPerm_RW, AUFS_BRPERM_RW},
16711+
16712+ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
16713+ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
16714+ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
16715+
16716+ {AuBrPerm_ROWH, "nfsro"},
16717+ {AuBrPerm_RO, NULL}
16718+};
16719+
4a4d8108 16720+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 16721+{
16722+ int val;
16723+ substring_t args[MAX_OPT_ARGS];
16724+
16725+ val = match_token(perm, brperms, args);
16726+ return val;
16727+}
16728+
16729+const char *au_optstr_br_perm(int brperm)
16730+{
16731+ return au_parser_pattern(brperm, (void *)brperms);
16732+}
16733+
16734+/* ---------------------------------------------------------------------- */
16735+
16736+static match_table_t udbalevel = {
16737+ {AuOpt_UDBA_REVAL, "reval"},
16738+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
16739+#ifdef CONFIG_AUFS_HNOTIFY
16740+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
16741+#ifdef CONFIG_AUFS_HFSNOTIFY
16742+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
16743+#else
16744+ {AuOpt_UDBA_HNOTIFY, "inotify"},
16745+#endif
1facf9fc 16746+#endif
16747+ {-1, NULL}
16748+};
16749+
4a4d8108
AM
16750+static void au_warn_inotify(int val, char *str)
16751+{
16752+#ifdef CONFIG_AUFS_HINOTIFY
16753+ if (val == AuOpt_UDBA_HNOTIFY
16754+ && !strcmp(str, "inotify"))
16755+ AuWarn1("udba=inotify is deprecated, use udba=notify\n");
16756+#endif
16757+}
16758+
16759+static int noinline_for_stack udba_val(char *str)
1facf9fc 16760+{
4a4d8108 16761+ int val;
1facf9fc 16762+ substring_t args[MAX_OPT_ARGS];
16763+
4a4d8108
AM
16764+ val = match_token(str, udbalevel, args);
16765+ au_warn_inotify(val, str);
16766+ return val;
1facf9fc 16767+}
16768+
16769+const char *au_optstr_udba(int udba)
16770+{
16771+ return au_parser_pattern(udba, (void *)udbalevel);
16772+}
16773+
16774+/* ---------------------------------------------------------------------- */
16775+
16776+static match_table_t au_wbr_create_policy = {
16777+ {AuWbrCreate_TDP, "tdp"},
16778+ {AuWbrCreate_TDP, "top-down-parent"},
16779+ {AuWbrCreate_RR, "rr"},
16780+ {AuWbrCreate_RR, "round-robin"},
16781+ {AuWbrCreate_MFS, "mfs"},
16782+ {AuWbrCreate_MFS, "most-free-space"},
16783+ {AuWbrCreate_MFSV, "mfs:%d"},
16784+ {AuWbrCreate_MFSV, "most-free-space:%d"},
16785+
16786+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
16787+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
16788+ {AuWbrCreate_PMFS, "pmfs"},
16789+ {AuWbrCreate_PMFSV, "pmfs:%d"},
16790+
16791+ {-1, NULL}
16792+};
16793+
dece6358
AM
16794+/*
16795+ * cf. linux/lib/parser.c and cmdline.c
16796+ * gave up calling memparse() since it uses simple_strtoull() instead of
16797+ * strict_...().
16798+ */
4a4d8108
AM
16799+static int noinline_for_stack
16800+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 16801+{
16802+ int err;
16803+ unsigned int len;
16804+ char a[32];
16805+
16806+ err = -ERANGE;
16807+ len = s->to - s->from;
16808+ if (len + 1 <= sizeof(a)) {
16809+ memcpy(a, s->from, len);
16810+ a[len] = '\0';
16811+ err = strict_strtoull(a, 0, result);
16812+ }
16813+ return err;
16814+}
16815+
16816+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
16817+ struct au_opt_wbr_create *create)
16818+{
16819+ int err;
16820+ unsigned long long ull;
16821+
16822+ err = 0;
16823+ if (!au_match_ull(arg, &ull))
16824+ create->mfsrr_watermark = ull;
16825+ else {
4a4d8108 16826+ pr_err("bad integer in %s\n", str);
1facf9fc 16827+ err = -EINVAL;
16828+ }
16829+
16830+ return err;
16831+}
16832+
16833+static int au_wbr_mfs_sec(substring_t *arg, char *str,
16834+ struct au_opt_wbr_create *create)
16835+{
16836+ int n, err;
16837+
16838+ err = 0;
16839+ if (!match_int(arg, &n) && 0 <= n)
16840+ create->mfs_second = n;
16841+ else {
4a4d8108 16842+ pr_err("bad integer in %s\n", str);
1facf9fc 16843+ err = -EINVAL;
16844+ }
16845+
16846+ return err;
16847+}
16848+
4a4d8108
AM
16849+static int noinline_for_stack
16850+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 16851+{
16852+ int err, e;
16853+ substring_t args[MAX_OPT_ARGS];
16854+
16855+ err = match_token(str, au_wbr_create_policy, args);
16856+ create->wbr_create = err;
16857+ switch (err) {
16858+ case AuWbrCreate_MFSRRV:
16859+ e = au_wbr_mfs_wmark(&args[0], str, create);
16860+ if (!e)
16861+ e = au_wbr_mfs_sec(&args[1], str, create);
16862+ if (unlikely(e))
16863+ err = e;
16864+ break;
16865+ case AuWbrCreate_MFSRR:
16866+ e = au_wbr_mfs_wmark(&args[0], str, create);
16867+ if (unlikely(e)) {
16868+ err = e;
16869+ break;
16870+ }
16871+ /*FALLTHROUGH*/
16872+ case AuWbrCreate_MFS:
16873+ case AuWbrCreate_PMFS:
16874+ create->mfs_second = AUFS_MFS_SECOND_DEF;
16875+ break;
16876+ case AuWbrCreate_MFSV:
16877+ case AuWbrCreate_PMFSV:
16878+ e = au_wbr_mfs_sec(&args[0], str, create);
16879+ if (unlikely(e))
16880+ err = e;
16881+ break;
16882+ }
16883+
16884+ return err;
16885+}
16886+
16887+const char *au_optstr_wbr_create(int wbr_create)
16888+{
16889+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
16890+}
16891+
16892+static match_table_t au_wbr_copyup_policy = {
16893+ {AuWbrCopyup_TDP, "tdp"},
16894+ {AuWbrCopyup_TDP, "top-down-parent"},
16895+ {AuWbrCopyup_BUP, "bup"},
16896+ {AuWbrCopyup_BUP, "bottom-up-parent"},
16897+ {AuWbrCopyup_BU, "bu"},
16898+ {AuWbrCopyup_BU, "bottom-up"},
16899+ {-1, NULL}
16900+};
16901+
4a4d8108 16902+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 16903+{
16904+ substring_t args[MAX_OPT_ARGS];
16905+
16906+ return match_token(str, au_wbr_copyup_policy, args);
16907+}
16908+
16909+const char *au_optstr_wbr_copyup(int wbr_copyup)
16910+{
16911+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
16912+}
16913+
16914+/* ---------------------------------------------------------------------- */
16915+
16916+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
16917+
16918+static void dump_opts(struct au_opts *opts)
16919+{
16920+#ifdef CONFIG_AUFS_DEBUG
16921+ /* reduce stack space */
16922+ union {
16923+ struct au_opt_add *add;
16924+ struct au_opt_del *del;
16925+ struct au_opt_mod *mod;
16926+ struct au_opt_xino *xino;
16927+ struct au_opt_xino_itrunc *xino_itrunc;
16928+ struct au_opt_wbr_create *create;
16929+ } u;
16930+ struct au_opt *opt;
16931+
16932+ opt = opts->opt;
16933+ while (opt->type != Opt_tail) {
16934+ switch (opt->type) {
16935+ case Opt_add:
16936+ u.add = &opt->add;
16937+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
16938+ u.add->bindex, u.add->pathname, u.add->perm,
16939+ u.add->path.dentry);
16940+ break;
16941+ case Opt_del:
16942+ case Opt_idel:
16943+ u.del = &opt->del;
16944+ AuDbg("del {%s, %p}\n",
16945+ u.del->pathname, u.del->h_path.dentry);
16946+ break;
16947+ case Opt_mod:
16948+ case Opt_imod:
16949+ u.mod = &opt->mod;
16950+ AuDbg("mod {%s, 0x%x, %p}\n",
16951+ u.mod->path, u.mod->perm, u.mod->h_root);
16952+ break;
16953+ case Opt_append:
16954+ u.add = &opt->add;
16955+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
16956+ u.add->bindex, u.add->pathname, u.add->perm,
16957+ u.add->path.dentry);
16958+ break;
16959+ case Opt_prepend:
16960+ u.add = &opt->add;
16961+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
16962+ u.add->bindex, u.add->pathname, u.add->perm,
16963+ u.add->path.dentry);
16964+ break;
16965+ case Opt_dirwh:
16966+ AuDbg("dirwh %d\n", opt->dirwh);
16967+ break;
16968+ case Opt_rdcache:
16969+ AuDbg("rdcache %d\n", opt->rdcache);
16970+ break;
16971+ case Opt_rdblk:
16972+ AuDbg("rdblk %u\n", opt->rdblk);
16973+ break;
dece6358
AM
16974+ case Opt_rdblk_def:
16975+ AuDbg("rdblk_def\n");
16976+ break;
1facf9fc 16977+ case Opt_rdhash:
16978+ AuDbg("rdhash %u\n", opt->rdhash);
16979+ break;
dece6358
AM
16980+ case Opt_rdhash_def:
16981+ AuDbg("rdhash_def\n");
16982+ break;
1facf9fc 16983+ case Opt_xino:
16984+ u.xino = &opt->xino;
16985+ AuDbg("xino {%s %.*s}\n",
16986+ u.xino->path,
16987+ AuDLNPair(u.xino->file->f_dentry));
16988+ break;
16989+ case Opt_trunc_xino:
16990+ AuLabel(trunc_xino);
16991+ break;
16992+ case Opt_notrunc_xino:
16993+ AuLabel(notrunc_xino);
16994+ break;
16995+ case Opt_trunc_xino_path:
16996+ case Opt_itrunc_xino:
16997+ u.xino_itrunc = &opt->xino_itrunc;
16998+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
16999+ break;
17000+
17001+ case Opt_noxino:
17002+ AuLabel(noxino);
17003+ break;
17004+ case Opt_trunc_xib:
17005+ AuLabel(trunc_xib);
17006+ break;
17007+ case Opt_notrunc_xib:
17008+ AuLabel(notrunc_xib);
17009+ break;
dece6358
AM
17010+ case Opt_shwh:
17011+ AuLabel(shwh);
17012+ break;
17013+ case Opt_noshwh:
17014+ AuLabel(noshwh);
17015+ break;
1facf9fc 17016+ case Opt_plink:
17017+ AuLabel(plink);
17018+ break;
17019+ case Opt_noplink:
17020+ AuLabel(noplink);
17021+ break;
17022+ case Opt_list_plink:
17023+ AuLabel(list_plink);
17024+ break;
17025+ case Opt_udba:
17026+ AuDbg("udba %d, %s\n",
17027+ opt->udba, au_optstr_udba(opt->udba));
17028+ break;
4a4d8108
AM
17029+ case Opt_dio:
17030+ AuLabel(dio);
17031+ break;
17032+ case Opt_nodio:
17033+ AuLabel(nodio);
17034+ break;
1facf9fc 17035+ case Opt_diropq_a:
17036+ AuLabel(diropq_a);
17037+ break;
17038+ case Opt_diropq_w:
17039+ AuLabel(diropq_w);
17040+ break;
17041+ case Opt_warn_perm:
17042+ AuLabel(warn_perm);
17043+ break;
17044+ case Opt_nowarn_perm:
17045+ AuLabel(nowarn_perm);
17046+ break;
17047+ case Opt_refrof:
17048+ AuLabel(refrof);
17049+ break;
17050+ case Opt_norefrof:
17051+ AuLabel(norefrof);
17052+ break;
17053+ case Opt_verbose:
17054+ AuLabel(verbose);
17055+ break;
17056+ case Opt_noverbose:
17057+ AuLabel(noverbose);
17058+ break;
17059+ case Opt_sum:
17060+ AuLabel(sum);
17061+ break;
17062+ case Opt_nosum:
17063+ AuLabel(nosum);
17064+ break;
17065+ case Opt_wsum:
17066+ AuLabel(wsum);
17067+ break;
17068+ case Opt_wbr_create:
17069+ u.create = &opt->wbr_create;
17070+ AuDbg("create %d, %s\n", u.create->wbr_create,
17071+ au_optstr_wbr_create(u.create->wbr_create));
17072+ switch (u.create->wbr_create) {
17073+ case AuWbrCreate_MFSV:
17074+ case AuWbrCreate_PMFSV:
17075+ AuDbg("%d sec\n", u.create->mfs_second);
17076+ break;
17077+ case AuWbrCreate_MFSRR:
17078+ AuDbg("%llu watermark\n",
17079+ u.create->mfsrr_watermark);
17080+ break;
17081+ case AuWbrCreate_MFSRRV:
17082+ AuDbg("%llu watermark, %d sec\n",
17083+ u.create->mfsrr_watermark,
17084+ u.create->mfs_second);
17085+ break;
17086+ }
17087+ break;
17088+ case Opt_wbr_copyup:
17089+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
17090+ au_optstr_wbr_copyup(opt->wbr_copyup));
17091+ break;
17092+ default:
17093+ BUG();
17094+ }
17095+ opt++;
17096+ }
17097+#endif
17098+}
17099+
17100+void au_opts_free(struct au_opts *opts)
17101+{
17102+ struct au_opt *opt;
17103+
17104+ opt = opts->opt;
17105+ while (opt->type != Opt_tail) {
17106+ switch (opt->type) {
17107+ case Opt_add:
17108+ case Opt_append:
17109+ case Opt_prepend:
17110+ path_put(&opt->add.path);
17111+ break;
17112+ case Opt_del:
17113+ case Opt_idel:
17114+ path_put(&opt->del.h_path);
17115+ break;
17116+ case Opt_mod:
17117+ case Opt_imod:
17118+ dput(opt->mod.h_root);
17119+ break;
17120+ case Opt_xino:
17121+ fput(opt->xino.file);
17122+ break;
17123+ }
17124+ opt++;
17125+ }
17126+}
17127+
17128+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
17129+ aufs_bindex_t bindex)
17130+{
17131+ int err;
17132+ struct au_opt_add *add = &opt->add;
17133+ char *p;
17134+
17135+ add->bindex = bindex;
17136+ add->perm = AuBrPerm_Last;
17137+ add->pathname = opt_str;
17138+ p = strchr(opt_str, '=');
17139+ if (p) {
17140+ *p++ = 0;
17141+ if (*p)
17142+ add->perm = br_perm_val(p);
17143+ }
17144+
17145+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
17146+ if (!err) {
17147+ if (!p) {
17148+ add->perm = AuBrPerm_RO;
17149+ if (au_test_fs_rr(add->path.dentry->d_sb))
17150+ add->perm = AuBrPerm_RR;
17151+ else if (!bindex && !(sb_flags & MS_RDONLY))
17152+ add->perm = AuBrPerm_RW;
17153+ }
17154+ opt->type = Opt_add;
17155+ goto out;
17156+ }
4a4d8108 17157+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 17158+ err = -EINVAL;
17159+
17160+ out:
17161+ return err;
17162+}
17163+
17164+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
17165+{
17166+ int err;
17167+
17168+ del->pathname = args[0].from;
17169+ AuDbg("del path %s\n", del->pathname);
17170+
17171+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
17172+ if (unlikely(err))
4a4d8108 17173+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 17174+
17175+ return err;
17176+}
17177+
17178+#if 0 /* reserved for future use */
17179+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
17180+ struct au_opt_del *del, substring_t args[])
17181+{
17182+ int err;
17183+ struct dentry *root;
17184+
17185+ err = -EINVAL;
17186+ root = sb->s_root;
17187+ aufs_read_lock(root, AuLock_FLUSH);
17188+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17189+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17190+ goto out;
17191+ }
17192+
17193+ err = 0;
17194+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
17195+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
17196+
17197+ out:
17198+ aufs_read_unlock(root, !AuLock_IR);
17199+ return err;
17200+}
17201+#endif
17202+
4a4d8108
AM
17203+static int noinline_for_stack
17204+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 17205+{
17206+ int err;
17207+ struct path path;
17208+ char *p;
17209+
17210+ err = -EINVAL;
17211+ mod->path = args[0].from;
17212+ p = strchr(mod->path, '=');
17213+ if (unlikely(!p)) {
4a4d8108 17214+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 17215+ goto out;
17216+ }
17217+
17218+ *p++ = 0;
17219+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
17220+ if (unlikely(err)) {
4a4d8108 17221+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 17222+ goto out;
17223+ }
17224+
17225+ mod->perm = br_perm_val(p);
17226+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
17227+ mod->h_root = dget(path.dentry);
17228+ path_put(&path);
17229+
17230+ out:
17231+ return err;
17232+}
17233+
17234+#if 0 /* reserved for future use */
17235+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
17236+ struct au_opt_mod *mod, substring_t args[])
17237+{
17238+ int err;
17239+ struct dentry *root;
17240+
17241+ err = -EINVAL;
17242+ root = sb->s_root;
17243+ aufs_read_lock(root, AuLock_FLUSH);
17244+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17245+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17246+ goto out;
17247+ }
17248+
17249+ err = 0;
17250+ mod->perm = br_perm_val(args[1].from);
17251+ AuDbg("mod path %s, perm 0x%x, %s\n",
17252+ mod->path, mod->perm, args[1].from);
17253+ mod->h_root = dget(au_h_dptr(root, bindex));
17254+
17255+ out:
17256+ aufs_read_unlock(root, !AuLock_IR);
17257+ return err;
17258+}
17259+#endif
17260+
17261+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
17262+ substring_t args[])
17263+{
17264+ int err;
17265+ struct file *file;
17266+
17267+ file = au_xino_create(sb, args[0].from, /*silent*/0);
17268+ err = PTR_ERR(file);
17269+ if (IS_ERR(file))
17270+ goto out;
17271+
17272+ err = -EINVAL;
17273+ if (unlikely(file->f_dentry->d_sb == sb)) {
17274+ fput(file);
4a4d8108 17275+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 17276+ goto out;
17277+ }
17278+
17279+ err = 0;
17280+ xino->file = file;
17281+ xino->path = args[0].from;
17282+
17283+ out:
17284+ return err;
17285+}
17286+
4a4d8108
AM
17287+static int noinline_for_stack
17288+au_opts_parse_xino_itrunc_path(struct super_block *sb,
17289+ struct au_opt_xino_itrunc *xino_itrunc,
17290+ substring_t args[])
1facf9fc 17291+{
17292+ int err;
17293+ aufs_bindex_t bend, bindex;
17294+ struct path path;
17295+ struct dentry *root;
17296+
17297+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
17298+ if (unlikely(err)) {
4a4d8108 17299+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 17300+ goto out;
17301+ }
17302+
17303+ xino_itrunc->bindex = -1;
17304+ root = sb->s_root;
17305+ aufs_read_lock(root, AuLock_FLUSH);
17306+ bend = au_sbend(sb);
17307+ for (bindex = 0; bindex <= bend; bindex++) {
17308+ if (au_h_dptr(root, bindex) == path.dentry) {
17309+ xino_itrunc->bindex = bindex;
17310+ break;
17311+ }
17312+ }
17313+ aufs_read_unlock(root, !AuLock_IR);
17314+ path_put(&path);
17315+
17316+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 17317+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 17318+ err = -EINVAL;
17319+ }
17320+
17321+ out:
17322+ return err;
17323+}
17324+
17325+/* called without aufs lock */
17326+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
17327+{
17328+ int err, n, token;
17329+ aufs_bindex_t bindex;
17330+ unsigned char skipped;
17331+ struct dentry *root;
17332+ struct au_opt *opt, *opt_tail;
17333+ char *opt_str;
17334+ /* reduce the stack space */
17335+ union {
17336+ struct au_opt_xino_itrunc *xino_itrunc;
17337+ struct au_opt_wbr_create *create;
17338+ } u;
17339+ struct {
17340+ substring_t args[MAX_OPT_ARGS];
17341+ } *a;
17342+
17343+ err = -ENOMEM;
17344+ a = kmalloc(sizeof(*a), GFP_NOFS);
17345+ if (unlikely(!a))
17346+ goto out;
17347+
17348+ root = sb->s_root;
17349+ err = 0;
17350+ bindex = 0;
17351+ opt = opts->opt;
17352+ opt_tail = opt + opts->max_opt - 1;
17353+ opt->type = Opt_tail;
17354+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
17355+ err = -EINVAL;
17356+ skipped = 0;
17357+ token = match_token(opt_str, options, a->args);
17358+ switch (token) {
17359+ case Opt_br:
17360+ err = 0;
17361+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
17362+ && *opt_str) {
17363+ err = opt_add(opt, opt_str, opts->sb_flags,
17364+ bindex++);
17365+ if (unlikely(!err && ++opt > opt_tail)) {
17366+ err = -E2BIG;
17367+ break;
17368+ }
17369+ opt->type = Opt_tail;
17370+ skipped = 1;
17371+ }
17372+ break;
17373+ case Opt_add:
17374+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17375+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17376+ break;
17377+ }
17378+ bindex = n;
17379+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
17380+ bindex);
17381+ if (!err)
17382+ opt->type = token;
17383+ break;
17384+ case Opt_append:
17385+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17386+ /*dummy bindex*/1);
17387+ if (!err)
17388+ opt->type = token;
17389+ break;
17390+ case Opt_prepend:
17391+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17392+ /*bindex*/0);
17393+ if (!err)
17394+ opt->type = token;
17395+ break;
17396+ case Opt_del:
17397+ err = au_opts_parse_del(&opt->del, a->args);
17398+ if (!err)
17399+ opt->type = token;
17400+ break;
17401+#if 0 /* reserved for future use */
17402+ case Opt_idel:
17403+ del->pathname = "(indexed)";
17404+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 17405+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17406+ break;
17407+ }
17408+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
17409+ if (!err)
17410+ opt->type = token;
17411+ break;
17412+#endif
17413+ case Opt_mod:
17414+ err = au_opts_parse_mod(&opt->mod, a->args);
17415+ if (!err)
17416+ opt->type = token;
17417+ break;
17418+#ifdef IMOD /* reserved for future use */
17419+ case Opt_imod:
17420+ u.mod->path = "(indexed)";
17421+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17422+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17423+ break;
17424+ }
17425+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
17426+ if (!err)
17427+ opt->type = token;
17428+ break;
17429+#endif
17430+ case Opt_xino:
17431+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
17432+ if (!err)
17433+ opt->type = token;
17434+ break;
17435+
17436+ case Opt_trunc_xino_path:
17437+ err = au_opts_parse_xino_itrunc_path
17438+ (sb, &opt->xino_itrunc, a->args);
17439+ if (!err)
17440+ opt->type = token;
17441+ break;
17442+
17443+ case Opt_itrunc_xino:
17444+ u.xino_itrunc = &opt->xino_itrunc;
17445+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17446+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17447+ break;
17448+ }
17449+ u.xino_itrunc->bindex = n;
17450+ aufs_read_lock(root, AuLock_FLUSH);
17451+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 17452+ pr_err("out of bounds, %d\n", n);
1facf9fc 17453+ aufs_read_unlock(root, !AuLock_IR);
17454+ break;
17455+ }
17456+ aufs_read_unlock(root, !AuLock_IR);
17457+ err = 0;
17458+ opt->type = token;
17459+ break;
17460+
17461+ case Opt_dirwh:
17462+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
17463+ break;
17464+ err = 0;
17465+ opt->type = token;
17466+ break;
17467+
17468+ case Opt_rdcache:
17469+ if (unlikely(match_int(&a->args[0], &opt->rdcache)))
17470+ break;
17471+ err = 0;
17472+ opt->type = token;
17473+ break;
17474+ case Opt_rdblk:
17475+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17476+ || n < 0
1facf9fc 17477+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 17478+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17479+ break;
17480+ }
1308ab2a 17481+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
17482+ pr_err("rdblk must be larger than %d\n",
17483+ NAME_MAX);
1facf9fc 17484+ break;
17485+ }
17486+ opt->rdblk = n;
17487+ err = 0;
17488+ opt->type = token;
17489+ break;
17490+ case Opt_rdhash:
17491+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17492+ || n < 0
1facf9fc 17493+ || n * sizeof(struct hlist_head)
17494+ > KMALLOC_MAX_SIZE)) {
4a4d8108 17495+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17496+ break;
17497+ }
17498+ opt->rdhash = n;
17499+ err = 0;
17500+ opt->type = token;
17501+ break;
17502+
17503+ case Opt_trunc_xino:
17504+ case Opt_notrunc_xino:
17505+ case Opt_noxino:
17506+ case Opt_trunc_xib:
17507+ case Opt_notrunc_xib:
dece6358
AM
17508+ case Opt_shwh:
17509+ case Opt_noshwh:
1facf9fc 17510+ case Opt_plink:
17511+ case Opt_noplink:
17512+ case Opt_list_plink:
4a4d8108
AM
17513+ case Opt_dio:
17514+ case Opt_nodio:
1facf9fc 17515+ case Opt_diropq_a:
17516+ case Opt_diropq_w:
17517+ case Opt_warn_perm:
17518+ case Opt_nowarn_perm:
17519+ case Opt_refrof:
17520+ case Opt_norefrof:
17521+ case Opt_verbose:
17522+ case Opt_noverbose:
17523+ case Opt_sum:
17524+ case Opt_nosum:
17525+ case Opt_wsum:
dece6358
AM
17526+ case Opt_rdblk_def:
17527+ case Opt_rdhash_def:
1facf9fc 17528+ err = 0;
17529+ opt->type = token;
17530+ break;
17531+
17532+ case Opt_udba:
17533+ opt->udba = udba_val(a->args[0].from);
17534+ if (opt->udba >= 0) {
17535+ err = 0;
17536+ opt->type = token;
17537+ } else
4a4d8108 17538+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17539+ break;
17540+
17541+ case Opt_wbr_create:
17542+ u.create = &opt->wbr_create;
17543+ u.create->wbr_create
17544+ = au_wbr_create_val(a->args[0].from, u.create);
17545+ if (u.create->wbr_create >= 0) {
17546+ err = 0;
17547+ opt->type = token;
17548+ } else
4a4d8108 17549+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17550+ break;
17551+ case Opt_wbr_copyup:
17552+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
17553+ if (opt->wbr_copyup >= 0) {
17554+ err = 0;
17555+ opt->type = token;
17556+ } else
4a4d8108 17557+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17558+ break;
17559+
17560+ case Opt_ignore:
4a4d8108 17561+ pr_warning("ignored %s\n", opt_str);
1facf9fc 17562+ /*FALLTHROUGH*/
17563+ case Opt_ignore_silent:
17564+ skipped = 1;
17565+ err = 0;
17566+ break;
17567+ case Opt_err:
4a4d8108 17568+ pr_err("unknown option %s\n", opt_str);
1facf9fc 17569+ break;
17570+ }
17571+
17572+ if (!err && !skipped) {
17573+ if (unlikely(++opt > opt_tail)) {
17574+ err = -E2BIG;
17575+ opt--;
17576+ opt->type = Opt_tail;
17577+ break;
17578+ }
17579+ opt->type = Opt_tail;
17580+ }
17581+ }
17582+
17583+ kfree(a);
17584+ dump_opts(opts);
17585+ if (unlikely(err))
17586+ au_opts_free(opts);
17587+
17588+ out:
17589+ return err;
17590+}
17591+
17592+static int au_opt_wbr_create(struct super_block *sb,
17593+ struct au_opt_wbr_create *create)
17594+{
17595+ int err;
17596+ struct au_sbinfo *sbinfo;
17597+
dece6358
AM
17598+ SiMustWriteLock(sb);
17599+
1facf9fc 17600+ err = 1; /* handled */
17601+ sbinfo = au_sbi(sb);
17602+ if (sbinfo->si_wbr_create_ops->fin) {
17603+ err = sbinfo->si_wbr_create_ops->fin(sb);
17604+ if (!err)
17605+ err = 1;
17606+ }
17607+
17608+ sbinfo->si_wbr_create = create->wbr_create;
17609+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
17610+ switch (create->wbr_create) {
17611+ case AuWbrCreate_MFSRRV:
17612+ case AuWbrCreate_MFSRR:
17613+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
17614+ /*FALLTHROUGH*/
17615+ case AuWbrCreate_MFS:
17616+ case AuWbrCreate_MFSV:
17617+ case AuWbrCreate_PMFS:
17618+ case AuWbrCreate_PMFSV:
17619+ sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
17620+ break;
17621+ }
17622+
17623+ if (sbinfo->si_wbr_create_ops->init)
17624+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
17625+
17626+ return err;
17627+}
17628+
17629+/*
17630+ * returns,
17631+ * plus: processed without an error
17632+ * zero: unprocessed
17633+ */
17634+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
17635+ struct au_opts *opts)
17636+{
17637+ int err;
17638+ struct au_sbinfo *sbinfo;
17639+
dece6358
AM
17640+ SiMustWriteLock(sb);
17641+
1facf9fc 17642+ err = 1; /* handled */
17643+ sbinfo = au_sbi(sb);
17644+ switch (opt->type) {
17645+ case Opt_udba:
17646+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
17647+ sbinfo->si_mntflags |= opt->udba;
17648+ opts->given_udba |= opt->udba;
17649+ break;
17650+
17651+ case Opt_plink:
17652+ au_opt_set(sbinfo->si_mntflags, PLINK);
17653+ break;
17654+ case Opt_noplink:
17655+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
17656+ au_plink_put(sb);
17657+ au_opt_clr(sbinfo->si_mntflags, PLINK);
17658+ break;
17659+ case Opt_list_plink:
17660+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
17661+ au_plink_list(sb);
17662+ break;
17663+
4a4d8108
AM
17664+ case Opt_dio:
17665+ au_opt_set(sbinfo->si_mntflags, DIO);
17666+ au_fset_opts(opts->flags, REFRESH_DYAOP);
17667+ break;
17668+ case Opt_nodio:
17669+ au_opt_clr(sbinfo->si_mntflags, DIO);
17670+ au_fset_opts(opts->flags, REFRESH_DYAOP);
17671+ break;
17672+
1facf9fc 17673+ case Opt_diropq_a:
17674+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
17675+ break;
17676+ case Opt_diropq_w:
17677+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
17678+ break;
17679+
17680+ case Opt_warn_perm:
17681+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
17682+ break;
17683+ case Opt_nowarn_perm:
17684+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
17685+ break;
17686+
17687+ case Opt_refrof:
17688+ au_opt_set(sbinfo->si_mntflags, REFROF);
17689+ break;
17690+ case Opt_norefrof:
17691+ au_opt_clr(sbinfo->si_mntflags, REFROF);
17692+ break;
17693+
17694+ case Opt_verbose:
17695+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
17696+ break;
17697+ case Opt_noverbose:
17698+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
17699+ break;
17700+
17701+ case Opt_sum:
17702+ au_opt_set(sbinfo->si_mntflags, SUM);
17703+ break;
17704+ case Opt_wsum:
17705+ au_opt_clr(sbinfo->si_mntflags, SUM);
17706+ au_opt_set(sbinfo->si_mntflags, SUM_W);
17707+ case Opt_nosum:
17708+ au_opt_clr(sbinfo->si_mntflags, SUM);
17709+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
17710+ break;
17711+
17712+ case Opt_wbr_create:
17713+ err = au_opt_wbr_create(sb, &opt->wbr_create);
17714+ break;
17715+ case Opt_wbr_copyup:
17716+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
17717+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
17718+ break;
17719+
17720+ case Opt_dirwh:
17721+ sbinfo->si_dirwh = opt->dirwh;
17722+ break;
17723+
17724+ case Opt_rdcache:
17725+ sbinfo->si_rdcache = opt->rdcache * HZ;
17726+ break;
17727+ case Opt_rdblk:
17728+ sbinfo->si_rdblk = opt->rdblk;
17729+ break;
dece6358
AM
17730+ case Opt_rdblk_def:
17731+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
17732+ break;
1facf9fc 17733+ case Opt_rdhash:
17734+ sbinfo->si_rdhash = opt->rdhash;
17735+ break;
dece6358
AM
17736+ case Opt_rdhash_def:
17737+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
17738+ break;
17739+
17740+ case Opt_shwh:
17741+ au_opt_set(sbinfo->si_mntflags, SHWH);
17742+ break;
17743+ case Opt_noshwh:
17744+ au_opt_clr(sbinfo->si_mntflags, SHWH);
17745+ break;
1facf9fc 17746+
17747+ case Opt_trunc_xino:
17748+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
17749+ break;
17750+ case Opt_notrunc_xino:
17751+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
17752+ break;
17753+
17754+ case Opt_trunc_xino_path:
17755+ case Opt_itrunc_xino:
17756+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
17757+ if (!err)
17758+ err = 1;
17759+ break;
17760+
17761+ case Opt_trunc_xib:
17762+ au_fset_opts(opts->flags, TRUNC_XIB);
17763+ break;
17764+ case Opt_notrunc_xib:
17765+ au_fclr_opts(opts->flags, TRUNC_XIB);
17766+ break;
17767+
17768+ default:
17769+ err = 0;
17770+ break;
17771+ }
17772+
17773+ return err;
17774+}
17775+
17776+/*
17777+ * returns tri-state.
17778+ * plus: processed without an error
17779+ * zero: unprocessed
17780+ * minus: error
17781+ */
17782+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
17783+ struct au_opts *opts)
17784+{
17785+ int err, do_refresh;
17786+
17787+ err = 0;
17788+ switch (opt->type) {
17789+ case Opt_append:
17790+ opt->add.bindex = au_sbend(sb) + 1;
17791+ if (opt->add.bindex < 0)
17792+ opt->add.bindex = 0;
17793+ goto add;
17794+ case Opt_prepend:
17795+ opt->add.bindex = 0;
17796+ add:
17797+ case Opt_add:
17798+ err = au_br_add(sb, &opt->add,
17799+ au_ftest_opts(opts->flags, REMOUNT));
17800+ if (!err) {
17801+ err = 1;
17802+ au_fset_opts(opts->flags, REFRESH_DIR);
4a4d8108 17803+ au_fset_opts(opts->flags, REFRESH_NONDIR);
1facf9fc 17804+ }
17805+ break;
17806+
17807+ case Opt_del:
17808+ case Opt_idel:
17809+ err = au_br_del(sb, &opt->del,
17810+ au_ftest_opts(opts->flags, REMOUNT));
17811+ if (!err) {
17812+ err = 1;
17813+ au_fset_opts(opts->flags, TRUNC_XIB);
17814+ au_fset_opts(opts->flags, REFRESH_DIR);
17815+ au_fset_opts(opts->flags, REFRESH_NONDIR);
17816+ }
17817+ break;
17818+
17819+ case Opt_mod:
17820+ case Opt_imod:
17821+ err = au_br_mod(sb, &opt->mod,
17822+ au_ftest_opts(opts->flags, REMOUNT),
17823+ &do_refresh);
17824+ if (!err) {
17825+ err = 1;
17826+ if (do_refresh) {
17827+ au_fset_opts(opts->flags, REFRESH_DIR);
17828+ au_fset_opts(opts->flags, REFRESH_NONDIR);
17829+ }
17830+ }
17831+ break;
17832+ }
17833+
17834+ return err;
17835+}
17836+
17837+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
17838+ struct au_opt_xino **opt_xino,
17839+ struct au_opts *opts)
17840+{
17841+ int err;
17842+ aufs_bindex_t bend, bindex;
17843+ struct dentry *root, *parent, *h_root;
17844+
17845+ err = 0;
17846+ switch (opt->type) {
17847+ case Opt_xino:
17848+ err = au_xino_set(sb, &opt->xino,
17849+ !!au_ftest_opts(opts->flags, REMOUNT));
17850+ if (unlikely(err))
17851+ break;
17852+
17853+ *opt_xino = &opt->xino;
17854+ au_xino_brid_set(sb, -1);
17855+
17856+ /* safe d_parent access */
17857+ parent = opt->xino.file->f_dentry->d_parent;
17858+ root = sb->s_root;
17859+ bend = au_sbend(sb);
17860+ for (bindex = 0; bindex <= bend; bindex++) {
17861+ h_root = au_h_dptr(root, bindex);
17862+ if (h_root == parent) {
17863+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
17864+ break;
17865+ }
17866+ }
17867+ break;
17868+
17869+ case Opt_noxino:
17870+ au_xino_clr(sb);
17871+ au_xino_brid_set(sb, -1);
17872+ *opt_xino = (void *)-1;
17873+ break;
17874+ }
17875+
17876+ return err;
17877+}
17878+
17879+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
17880+ unsigned int pending)
17881+{
17882+ int err;
17883+ aufs_bindex_t bindex, bend;
17884+ unsigned char do_plink, skip, do_free;
17885+ struct au_branch *br;
17886+ struct au_wbr *wbr;
17887+ struct dentry *root;
17888+ struct inode *dir, *h_dir;
17889+ struct au_sbinfo *sbinfo;
17890+ struct au_hinode *hdir;
17891+
dece6358
AM
17892+ SiMustAnyLock(sb);
17893+
1facf9fc 17894+ sbinfo = au_sbi(sb);
17895+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
17896+
dece6358
AM
17897+ if (!(sb_flags & MS_RDONLY)) {
17898+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
4a4d8108 17899+ pr_warning("first branch should be rw\n");
dece6358 17900+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
4a4d8108 17901+ pr_warning("shwh should be used with ro\n");
dece6358 17902+ }
1facf9fc 17903+
4a4d8108 17904+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 17905+ && !au_opt_test(sbinfo->si_mntflags, XINO))
4a4d8108 17906+ pr_warning("udba=*notify requires xino\n");
1facf9fc 17907+
17908+ err = 0;
17909+ root = sb->s_root;
4a4d8108 17910+ dir = root->d_inode;
1facf9fc 17911+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
17912+ bend = au_sbend(sb);
17913+ for (bindex = 0; !err && bindex <= bend; bindex++) {
17914+ skip = 0;
17915+ h_dir = au_h_iptr(dir, bindex);
17916+ br = au_sbr(sb, bindex);
17917+ do_free = 0;
17918+
17919+ wbr = br->br_wbr;
17920+ if (wbr)
17921+ wbr_wh_read_lock(wbr);
17922+
17923+ switch (br->br_perm) {
17924+ case AuBrPerm_RO:
17925+ case AuBrPerm_ROWH:
17926+ case AuBrPerm_RR:
17927+ case AuBrPerm_RRWH:
17928+ do_free = !!wbr;
17929+ skip = (!wbr
17930+ || (!wbr->wbr_whbase
17931+ && !wbr->wbr_plink
17932+ && !wbr->wbr_orph));
17933+ break;
17934+
17935+ case AuBrPerm_RWNoLinkWH:
17936+ /* skip = (!br->br_whbase && !br->br_orph); */
17937+ skip = (!wbr || !wbr->wbr_whbase);
17938+ if (skip && wbr) {
17939+ if (do_plink)
17940+ skip = !!wbr->wbr_plink;
17941+ else
17942+ skip = !wbr->wbr_plink;
17943+ }
17944+ break;
17945+
17946+ case AuBrPerm_RW:
17947+ /* skip = (br->br_whbase && br->br_ohph); */
17948+ skip = (wbr && wbr->wbr_whbase);
17949+ if (skip) {
17950+ if (do_plink)
17951+ skip = !!wbr->wbr_plink;
17952+ else
17953+ skip = !wbr->wbr_plink;
17954+ }
17955+ break;
17956+
17957+ default:
17958+ BUG();
17959+ }
17960+ if (wbr)
17961+ wbr_wh_read_unlock(wbr);
17962+
17963+ if (skip)
17964+ continue;
17965+
17966+ hdir = au_hi(dir, bindex);
4a4d8108 17967+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 17968+ if (wbr)
17969+ wbr_wh_write_lock(wbr);
17970+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
17971+ if (wbr)
17972+ wbr_wh_write_unlock(wbr);
4a4d8108 17973+ au_hn_imtx_unlock(hdir);
1facf9fc 17974+
17975+ if (!err && do_free) {
17976+ kfree(wbr);
17977+ br->br_wbr = NULL;
17978+ }
17979+ }
17980+
17981+ return err;
17982+}
17983+
17984+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
17985+{
17986+ int err;
17987+ unsigned int tmp;
17988+ aufs_bindex_t bend;
17989+ struct au_opt *opt;
17990+ struct au_opt_xino *opt_xino, xino;
17991+ struct au_sbinfo *sbinfo;
17992+
dece6358
AM
17993+ SiMustWriteLock(sb);
17994+
1facf9fc 17995+ err = 0;
17996+ opt_xino = NULL;
17997+ opt = opts->opt;
17998+ while (err >= 0 && opt->type != Opt_tail)
17999+ err = au_opt_simple(sb, opt++, opts);
18000+ if (err > 0)
18001+ err = 0;
18002+ else if (unlikely(err < 0))
18003+ goto out;
18004+
18005+ /* disable xino and udba temporary */
18006+ sbinfo = au_sbi(sb);
18007+ tmp = sbinfo->si_mntflags;
18008+ au_opt_clr(sbinfo->si_mntflags, XINO);
18009+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
18010+
18011+ opt = opts->opt;
18012+ while (err >= 0 && opt->type != Opt_tail)
18013+ err = au_opt_br(sb, opt++, opts);
18014+ if (err > 0)
18015+ err = 0;
18016+ else if (unlikely(err < 0))
18017+ goto out;
18018+
18019+ bend = au_sbend(sb);
18020+ if (unlikely(bend < 0)) {
18021+ err = -EINVAL;
4a4d8108 18022+ pr_err("no branches\n");
1facf9fc 18023+ goto out;
18024+ }
18025+
18026+ if (au_opt_test(tmp, XINO))
18027+ au_opt_set(sbinfo->si_mntflags, XINO);
18028+ opt = opts->opt;
18029+ while (!err && opt->type != Opt_tail)
18030+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
18031+ if (unlikely(err))
18032+ goto out;
18033+
18034+ err = au_opts_verify(sb, sb->s_flags, tmp);
18035+ if (unlikely(err))
18036+ goto out;
18037+
18038+ /* restore xino */
18039+ if (au_opt_test(tmp, XINO) && !opt_xino) {
18040+ xino.file = au_xino_def(sb);
18041+ err = PTR_ERR(xino.file);
18042+ if (IS_ERR(xino.file))
18043+ goto out;
18044+
18045+ err = au_xino_set(sb, &xino, /*remount*/0);
18046+ fput(xino.file);
18047+ if (unlikely(err))
18048+ goto out;
18049+ }
18050+
18051+ /* restore udba */
18052+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18053+ sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
4a4d8108 18054+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 18055+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 18056+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 18057+ }
18058+
18059+ out:
18060+ return err;
18061+}
18062+
18063+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
18064+{
18065+ int err, rerr;
18066+ struct inode *dir;
18067+ struct au_opt_xino *opt_xino;
18068+ struct au_opt *opt;
18069+ struct au_sbinfo *sbinfo;
18070+
dece6358
AM
18071+ SiMustWriteLock(sb);
18072+
1facf9fc 18073+ dir = sb->s_root->d_inode;
18074+ sbinfo = au_sbi(sb);
18075+ err = 0;
18076+ opt_xino = NULL;
18077+ opt = opts->opt;
18078+ while (err >= 0 && opt->type != Opt_tail) {
18079+ err = au_opt_simple(sb, opt, opts);
18080+ if (!err)
18081+ err = au_opt_br(sb, opt, opts);
18082+ if (!err)
18083+ err = au_opt_xino(sb, opt, &opt_xino, opts);
18084+ opt++;
18085+ }
18086+ if (err > 0)
18087+ err = 0;
18088+ AuTraceErr(err);
18089+ /* go on even err */
18090+
18091+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
18092+ if (unlikely(rerr && !err))
18093+ err = rerr;
18094+
18095+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
18096+ rerr = au_xib_trunc(sb);
18097+ if (unlikely(rerr && !err))
18098+ err = rerr;
18099+ }
18100+
18101+ /* will be handled by the caller */
18102+ if (!au_ftest_opts(opts->flags, REFRESH_DIR)
18103+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
18104+ au_fset_opts(opts->flags, REFRESH_DIR);
18105+
18106+ AuDbg("status 0x%x\n", opts->flags);
18107+ return err;
18108+}
18109+
18110+/* ---------------------------------------------------------------------- */
18111+
18112+unsigned int au_opt_udba(struct super_block *sb)
18113+{
18114+ return au_mntflags(sb) & AuOptMask_UDBA;
18115+}
4a4d8108
AM
18116diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/opts.h linux-2.6.34/fs/aufs/opts.h
18117--- linux-2.6.34.org/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
18118+++ linux-2.6.34/fs/aufs/opts.h 2010-05-31 22:15:32.000000000 +0200
18119@@ -0,0 +1,198 @@
1facf9fc 18120+/*
4a4d8108 18121+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18122+ *
18123+ * This program, aufs is free software; you can redistribute it and/or modify
18124+ * it under the terms of the GNU General Public License as published by
18125+ * the Free Software Foundation; either version 2 of the License, or
18126+ * (at your option) any later version.
dece6358
AM
18127+ *
18128+ * This program is distributed in the hope that it will be useful,
18129+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18130+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18131+ * GNU General Public License for more details.
18132+ *
18133+ * You should have received a copy of the GNU General Public License
18134+ * along with this program; if not, write to the Free Software
18135+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18136+ */
18137+
18138+/*
18139+ * mount options/flags
18140+ */
18141+
18142+#ifndef __AUFS_OPTS_H__
18143+#define __AUFS_OPTS_H__
18144+
18145+#ifdef __KERNEL__
18146+
dece6358 18147+#include <linux/path.h>
1facf9fc 18148+#include <linux/aufs_type.h>
18149+
dece6358
AM
18150+struct file;
18151+struct super_block;
18152+
1facf9fc 18153+/* ---------------------------------------------------------------------- */
18154+
18155+/* mount flags */
18156+#define AuOpt_XINO 1 /* external inode number bitmap
18157+ and translation table */
18158+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
18159+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
18160+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 18161+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
18162+#define AuOpt_SHWH (1 << 5) /* show whiteout */
18163+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
18164+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
18165+#define AuOpt_REFROF (1 << 8) /* unimplemented */
18166+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
18167+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
18168+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
18169+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
18170+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 18171+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 18172+
4a4d8108
AM
18173+#ifndef CONFIG_AUFS_HNOTIFY
18174+#undef AuOpt_UDBA_HNOTIFY
18175+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 18176+#endif
dece6358
AM
18177+#ifndef CONFIG_AUFS_SHWH
18178+#undef AuOpt_SHWH
18179+#define AuOpt_SHWH 0
18180+#endif
1facf9fc 18181+
18182+#define AuOpt_Def (AuOpt_XINO \
18183+ | AuOpt_UDBA_REVAL \
18184+ | AuOpt_PLINK \
18185+ /* | AuOpt_DIRPERM1 */ \
18186+ | AuOpt_WARN_PERM)
18187+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
18188+ | AuOpt_UDBA_REVAL \
4a4d8108 18189+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 18190+
18191+#define au_opt_test(flags, name) (flags & AuOpt_##name)
18192+#define au_opt_set(flags, name) do { \
18193+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
18194+ ((flags) |= AuOpt_##name); \
18195+} while (0)
18196+#define au_opt_set_udba(flags, name) do { \
18197+ (flags) &= ~AuOptMask_UDBA; \
18198+ ((flags) |= AuOpt_##name); \
18199+} while (0)
18200+#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
18201+
18202+/* ---------------------------------------------------------------------- */
18203+
18204+/* policies to select one among multiple writable branches */
18205+enum {
18206+ AuWbrCreate_TDP, /* top down parent */
18207+ AuWbrCreate_RR, /* round robin */
18208+ AuWbrCreate_MFS, /* most free space */
18209+ AuWbrCreate_MFSV, /* mfs with seconds */
18210+ AuWbrCreate_MFSRR, /* mfs then rr */
18211+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
18212+ AuWbrCreate_PMFS, /* parent and mfs */
18213+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
18214+
18215+ AuWbrCreate_Def = AuWbrCreate_TDP
18216+};
18217+
18218+enum {
18219+ AuWbrCopyup_TDP, /* top down parent */
18220+ AuWbrCopyup_BUP, /* bottom up parent */
18221+ AuWbrCopyup_BU, /* bottom up */
18222+
18223+ AuWbrCopyup_Def = AuWbrCopyup_TDP
18224+};
18225+
18226+/* ---------------------------------------------------------------------- */
18227+
18228+struct au_opt_add {
18229+ aufs_bindex_t bindex;
18230+ char *pathname;
18231+ int perm;
18232+ struct path path;
18233+};
18234+
18235+struct au_opt_del {
18236+ char *pathname;
18237+ struct path h_path;
18238+};
18239+
18240+struct au_opt_mod {
18241+ char *path;
18242+ int perm;
18243+ struct dentry *h_root;
18244+};
18245+
18246+struct au_opt_xino {
18247+ char *path;
18248+ struct file *file;
18249+};
18250+
18251+struct au_opt_xino_itrunc {
18252+ aufs_bindex_t bindex;
18253+};
18254+
18255+struct au_opt_wbr_create {
18256+ int wbr_create;
18257+ int mfs_second;
18258+ unsigned long long mfsrr_watermark;
18259+};
18260+
18261+struct au_opt {
18262+ int type;
18263+ union {
18264+ struct au_opt_xino xino;
18265+ struct au_opt_xino_itrunc xino_itrunc;
18266+ struct au_opt_add add;
18267+ struct au_opt_del del;
18268+ struct au_opt_mod mod;
18269+ int dirwh;
18270+ int rdcache;
18271+ unsigned int rdblk;
18272+ unsigned int rdhash;
18273+ int udba;
18274+ struct au_opt_wbr_create wbr_create;
18275+ int wbr_copyup;
18276+ };
18277+};
18278+
18279+/* opts flags */
18280+#define AuOpts_REMOUNT 1
18281+#define AuOpts_REFRESH_DIR (1 << 1)
18282+#define AuOpts_REFRESH_NONDIR (1 << 2)
18283+#define AuOpts_TRUNC_XIB (1 << 3)
4a4d8108 18284+#define AuOpts_REFRESH_DYAOP (1 << 4)
1facf9fc 18285+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
18286+#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
18287+#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
18288+
18289+struct au_opts {
18290+ struct au_opt *opt;
18291+ int max_opt;
18292+
18293+ unsigned int given_udba;
18294+ unsigned int flags;
18295+ unsigned long sb_flags;
18296+};
18297+
18298+/* ---------------------------------------------------------------------- */
18299+
18300+const char *au_optstr_br_perm(int brperm);
18301+const char *au_optstr_udba(int udba);
18302+const char *au_optstr_wbr_copyup(int wbr_copyup);
18303+const char *au_optstr_wbr_create(int wbr_create);
18304+
18305+void au_opts_free(struct au_opts *opts);
18306+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
18307+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18308+ unsigned int pending);
18309+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
18310+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
18311+
18312+unsigned int au_opt_udba(struct super_block *sb);
18313+
18314+/* ---------------------------------------------------------------------- */
18315+
18316+#endif /* __KERNEL__ */
18317+#endif /* __AUFS_OPTS_H__ */
4a4d8108
AM
18318diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/plink.c linux-2.6.34/fs/aufs/plink.c
18319--- linux-2.6.34.org/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
18320+++ linux-2.6.34/fs/aufs/plink.c 2010-05-31 22:15:32.000000000 +0200
18321@@ -0,0 +1,453 @@
1facf9fc 18322+/*
4a4d8108 18323+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18324+ *
18325+ * This program, aufs is free software; you can redistribute it and/or modify
18326+ * it under the terms of the GNU General Public License as published by
18327+ * the Free Software Foundation; either version 2 of the License, or
18328+ * (at your option) any later version.
dece6358
AM
18329+ *
18330+ * This program is distributed in the hope that it will be useful,
18331+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18332+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18333+ * GNU General Public License for more details.
18334+ *
18335+ * You should have received a copy of the GNU General Public License
18336+ * along with this program; if not, write to the Free Software
18337+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18338+ */
18339+
18340+/*
18341+ * pseudo-link
18342+ */
18343+
18344+#include "aufs.h"
18345+
18346+/*
18347+ * during a user process maintains the pseudo-links,
18348+ * prohibit adding a new plink and branch manipulation.
18349+ */
4a4d8108 18350+void au_plink_maint_block(struct super_block *sb)
1facf9fc 18351+{
18352+ struct au_sbinfo *sbi = au_sbi(sb);
dece6358
AM
18353+
18354+ SiMustAnyLock(sb);
18355+
1facf9fc 18356+ /* gave up wake_up_bit() */
4a4d8108
AM
18357+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint);
18358+}
18359+
18360+void au_plink_maint_leave(struct file *file)
18361+{
18362+ struct au_sbinfo *sbinfo;
18363+ int iam;
18364+
18365+ AuDebugOn(atomic_long_read(&file->f_count));
18366+
18367+ sbinfo = au_sbi(file->f_dentry->d_sb);
18368+ spin_lock(&sbinfo->si_plink_maint_lock);
18369+ iam = (sbinfo->si_plink_maint == file);
18370+ if (iam)
18371+ sbinfo->si_plink_maint = NULL;
18372+ spin_unlock(&sbinfo->si_plink_maint_lock);
18373+ if (iam)
18374+ wake_up_all(&sbinfo->si_plink_wq);
18375+}
18376+
18377+static int au_plink_maint_enter(struct file *file)
18378+{
18379+ int err;
18380+ struct super_block *sb;
18381+ struct au_sbinfo *sbinfo;
18382+
18383+ err = 0;
18384+ sb = file->f_dentry->d_sb;
18385+ sbinfo = au_sbi(sb);
18386+ /* make sure i am the only one in this fs */
18387+ si_write_lock(sb);
18388+ /* spin_lock(&sbinfo->si_plink_maint_lock); */
18389+ if (!sbinfo->si_plink_maint)
18390+ sbinfo->si_plink_maint = file;
18391+ else
18392+ err = -EBUSY;
18393+ /* spin_unlock(&sbinfo->si_plink_maint_lock); */
18394+ si_write_unlock(sb);
18395+
18396+ return err;
1facf9fc 18397+}
18398+
18399+/* ---------------------------------------------------------------------- */
18400+
18401+struct pseudo_link {
4a4d8108
AM
18402+ union {
18403+ struct list_head list;
18404+ struct rcu_head rcu;
18405+ };
1facf9fc 18406+ struct inode *inode;
18407+};
18408+
18409+#ifdef CONFIG_AUFS_DEBUG
18410+void au_plink_list(struct super_block *sb)
18411+{
18412+ struct au_sbinfo *sbinfo;
18413+ struct list_head *plink_list;
18414+ struct pseudo_link *plink;
18415+
dece6358
AM
18416+ SiMustAnyLock(sb);
18417+
1facf9fc 18418+ sbinfo = au_sbi(sb);
18419+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18420+
18421+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18422+ rcu_read_lock();
18423+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 18424+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 18425+ rcu_read_unlock();
1facf9fc 18426+}
18427+#endif
18428+
18429+/* is the inode pseudo-linked? */
18430+int au_plink_test(struct inode *inode)
18431+{
18432+ int found;
18433+ struct au_sbinfo *sbinfo;
18434+ struct list_head *plink_list;
18435+ struct pseudo_link *plink;
18436+
18437+ sbinfo = au_sbi(inode->i_sb);
dece6358 18438+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 18439+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
18440+
18441+ found = 0;
18442+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18443+ rcu_read_lock();
18444+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 18445+ if (plink->inode == inode) {
18446+ found = 1;
18447+ break;
18448+ }
4a4d8108 18449+ rcu_read_unlock();
1facf9fc 18450+ return found;
18451+}
18452+
18453+/* ---------------------------------------------------------------------- */
18454+
18455+/*
18456+ * generate a name for plink.
18457+ * the file will be stored under AUFS_WH_PLINKDIR.
18458+ */
18459+/* 20 is max digits length of ulong 64 */
18460+#define PLINK_NAME_LEN ((20 + 1) * 2)
18461+
18462+static int plink_name(char *name, int len, struct inode *inode,
18463+ aufs_bindex_t bindex)
18464+{
18465+ int rlen;
18466+ struct inode *h_inode;
18467+
18468+ h_inode = au_h_iptr(inode, bindex);
18469+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
18470+ return rlen;
18471+}
18472+
18473+/* lookup the plink-ed @inode under the branch at @bindex */
18474+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
18475+{
18476+ struct dentry *h_dentry, *h_parent;
18477+ struct au_branch *br;
18478+ struct inode *h_dir;
18479+ char a[PLINK_NAME_LEN];
18480+ struct qstr tgtname = {
18481+ .name = a
18482+ };
18483+
18484+ br = au_sbr(inode->i_sb, bindex);
18485+ h_parent = br->br_wbr->wbr_plink;
18486+ h_dir = h_parent->d_inode;
18487+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
18488+
18489+ /* always superio. */
18490+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
18491+ h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
18492+ mutex_unlock(&h_dir->i_mutex);
18493+ return h_dentry;
18494+}
18495+
18496+/* create a pseudo-link */
18497+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
18498+ struct dentry *h_dentry, struct au_branch *br)
18499+{
18500+ int err;
18501+ struct path h_path = {
18502+ .mnt = br->br_mnt
18503+ };
18504+ struct inode *h_dir;
18505+
18506+ h_dir = h_parent->d_inode;
18507+ again:
18508+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
18509+ err = PTR_ERR(h_path.dentry);
18510+ if (IS_ERR(h_path.dentry))
18511+ goto out;
18512+
18513+ err = 0;
18514+ /* wh.plink dir is not monitored */
18515+ if (h_path.dentry->d_inode
18516+ && h_path.dentry->d_inode != h_dentry->d_inode) {
18517+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
18518+ dput(h_path.dentry);
18519+ h_path.dentry = NULL;
18520+ if (!err)
18521+ goto again;
18522+ }
18523+ if (!err && !h_path.dentry->d_inode)
18524+ err = vfsub_link(h_dentry, h_dir, &h_path);
18525+ dput(h_path.dentry);
18526+
18527+ out:
18528+ return err;
18529+}
18530+
18531+struct do_whplink_args {
18532+ int *errp;
18533+ struct qstr *tgt;
18534+ struct dentry *h_parent;
18535+ struct dentry *h_dentry;
18536+ struct au_branch *br;
18537+};
18538+
18539+static void call_do_whplink(void *args)
18540+{
18541+ struct do_whplink_args *a = args;
18542+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
18543+}
18544+
18545+static int whplink(struct dentry *h_dentry, struct inode *inode,
18546+ aufs_bindex_t bindex, struct au_branch *br)
18547+{
18548+ int err, wkq_err;
18549+ struct au_wbr *wbr;
18550+ struct dentry *h_parent;
18551+ struct inode *h_dir;
18552+ char a[PLINK_NAME_LEN];
18553+ struct qstr tgtname = {
18554+ .name = a
18555+ };
18556+
18557+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
18558+ h_parent = wbr->wbr_plink;
18559+ h_dir = h_parent->d_inode;
18560+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
18561+
18562+ /* always superio. */
18563+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
18564+ if (!au_test_wkq(current)) {
18565+ struct do_whplink_args args = {
18566+ .errp = &err,
18567+ .tgt = &tgtname,
18568+ .h_parent = h_parent,
18569+ .h_dentry = h_dentry,
18570+ .br = br
18571+ };
18572+ wkq_err = au_wkq_wait(call_do_whplink, &args);
18573+ if (unlikely(wkq_err))
18574+ err = wkq_err;
18575+ } else
18576+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
18577+ mutex_unlock(&h_dir->i_mutex);
18578+
18579+ return err;
18580+}
18581+
18582+/* free a single plink */
18583+static void do_put_plink(struct pseudo_link *plink, int do_del)
18584+{
1facf9fc 18585+ if (do_del)
18586+ list_del(&plink->list);
4a4d8108
AM
18587+ iput(plink->inode);
18588+ kfree(plink);
18589+}
18590+
18591+static void do_put_plink_rcu(struct rcu_head *rcu)
18592+{
18593+ struct pseudo_link *plink;
18594+
18595+ plink = container_of(rcu, struct pseudo_link, rcu);
18596+ iput(plink->inode);
1facf9fc 18597+ kfree(plink);
18598+}
18599+
18600+/*
18601+ * create a new pseudo-link for @h_dentry on @bindex.
18602+ * the linked inode is held in aufs @inode.
18603+ */
18604+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
18605+ struct dentry *h_dentry)
18606+{
18607+ struct super_block *sb;
18608+ struct au_sbinfo *sbinfo;
18609+ struct list_head *plink_list;
4a4d8108 18610+ struct pseudo_link *plink, *tmp;
1facf9fc 18611+ int found, err, cnt;
18612+
18613+ sb = inode->i_sb;
18614+ sbinfo = au_sbi(sb);
18615+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18616+
1facf9fc 18617+ cnt = 0;
18618+ found = 0;
18619+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18620+ rcu_read_lock();
18621+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 18622+ cnt++;
18623+ if (plink->inode == inode) {
18624+ found = 1;
18625+ break;
18626+ }
18627+ }
4a4d8108
AM
18628+ rcu_read_unlock();
18629+ if (found)
1facf9fc 18630+ return;
4a4d8108
AM
18631+
18632+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
18633+ if (tmp)
18634+ tmp->inode = au_igrab(inode);
18635+ else {
18636+ err = -ENOMEM;
18637+ goto out;
1facf9fc 18638+ }
18639+
4a4d8108
AM
18640+ spin_lock(&sbinfo->si_plink.spin);
18641+ list_for_each_entry(plink, plink_list, list) {
18642+ if (plink->inode == inode) {
18643+ found = 1;
18644+ break;
18645+ }
1facf9fc 18646+ }
4a4d8108
AM
18647+ if (!found)
18648+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 18649+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
18650+ if (!found) {
18651+ cnt++;
18652+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
18653+ "unexpectedly many pseudo links, %d\n", cnt);
18654+ au_plink_maint_block(sb);
1facf9fc 18655+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
18656+ } else {
18657+ do_put_plink(tmp, 0);
18658+ return;
1facf9fc 18659+ }
18660+
4a4d8108 18661+out:
1facf9fc 18662+ if (unlikely(err)) {
4a4d8108
AM
18663+ pr_warning("err %d, damaged pseudo link.\n", err);
18664+ if (tmp) {
18665+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
18666+ call_rcu(&tmp->rcu, do_put_plink_rcu);
18667+ }
1facf9fc 18668+ }
18669+}
18670+
18671+/* free all plinks */
18672+void au_plink_put(struct super_block *sb)
18673+{
18674+ struct au_sbinfo *sbinfo;
18675+ struct list_head *plink_list;
18676+ struct pseudo_link *plink, *tmp;
18677+
dece6358
AM
18678+ SiMustWriteLock(sb);
18679+
1facf9fc 18680+ sbinfo = au_sbi(sb);
18681+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18682+
18683+ plink_list = &sbinfo->si_plink.head;
18684+ /* no spin_lock since sbinfo is write-locked */
18685+ list_for_each_entry_safe(plink, tmp, plink_list, list)
18686+ do_put_plink(plink, 0);
18687+ INIT_LIST_HEAD(plink_list);
18688+}
18689+
18690+/* free the plinks on a branch specified by @br_id */
18691+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
18692+{
18693+ struct au_sbinfo *sbinfo;
18694+ struct list_head *plink_list;
18695+ struct pseudo_link *plink, *tmp;
18696+ struct inode *inode;
18697+ aufs_bindex_t bstart, bend, bindex;
18698+ unsigned char do_put;
18699+
dece6358
AM
18700+ SiMustWriteLock(sb);
18701+
1facf9fc 18702+ sbinfo = au_sbi(sb);
18703+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
18704+
18705+ plink_list = &sbinfo->si_plink.head;
18706+ /* no spin_lock since sbinfo is write-locked */
18707+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
18708+ do_put = 0;
18709+ inode = au_igrab(plink->inode);
18710+ ii_write_lock_child(inode);
18711+ bstart = au_ibstart(inode);
18712+ bend = au_ibend(inode);
18713+ if (bstart >= 0) {
18714+ for (bindex = bstart; bindex <= bend; bindex++) {
18715+ if (!au_h_iptr(inode, bindex)
18716+ || au_ii_br_id(inode, bindex) != br_id)
18717+ continue;
18718+ au_set_h_iptr(inode, bindex, NULL, 0);
18719+ do_put = 1;
18720+ break;
18721+ }
18722+ } else
18723+ do_put_plink(plink, 1);
18724+
dece6358
AM
18725+ if (do_put) {
18726+ for (bindex = bstart; bindex <= bend; bindex++)
18727+ if (au_h_iptr(inode, bindex)) {
18728+ do_put = 0;
18729+ break;
18730+ }
18731+ if (do_put)
18732+ do_put_plink(plink, 1);
18733+ }
18734+ ii_write_unlock(inode);
18735+ iput(inode);
18736+ }
18737+}
1308ab2a 18738+
18739+/* ---------------------------------------------------------------------- */
18740+
18741+long au_plink_ioctl(struct file *file, unsigned int cmd)
18742+{
18743+ long err;
18744+ struct super_block *sb;
18745+ struct au_sbinfo *sbinfo;
18746+
18747+ err = -EACCES;
18748+ if (!capable(CAP_SYS_ADMIN))
18749+ goto out;
18750+
18751+ err = 0;
18752+ sb = file->f_dentry->d_sb;
18753+ sbinfo = au_sbi(sb);
18754+ switch (cmd) {
18755+ case AUFS_CTL_PLINK_MAINT:
18756+ /*
18757+ * pseudo-link maintenance mode,
18758+ * cleared by aufs_release_dir()
18759+ */
4a4d8108 18760+ err = au_plink_maint_enter(file);
1308ab2a 18761+ break;
18762+ case AUFS_CTL_PLINK_CLEAN:
18763+ aufs_write_lock(sb->s_root);
18764+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
18765+ au_plink_put(sb);
18766+ aufs_write_unlock(sb->s_root);
18767+ break;
18768+ default:
4a4d8108 18769+ /* err = -ENOTTY; */
1308ab2a 18770+ err = -EINVAL;
18771+ }
18772+ out:
18773+ return err;
18774+}
4a4d8108
AM
18775diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/poll.c linux-2.6.34/fs/aufs/poll.c
18776--- linux-2.6.34.org/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
18777+++ linux-2.6.34/fs/aufs/poll.c 2010-05-31 22:15:32.000000000 +0200
dece6358
AM
18778@@ -0,0 +1,56 @@
18779+/*
4a4d8108 18780+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
18781+ *
18782+ * This program, aufs is free software; you can redistribute it and/or modify
18783+ * it under the terms of the GNU General Public License as published by
18784+ * the Free Software Foundation; either version 2 of the License, or
18785+ * (at your option) any later version.
18786+ *
18787+ * This program is distributed in the hope that it will be useful,
18788+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18789+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18790+ * GNU General Public License for more details.
18791+ *
18792+ * You should have received a copy of the GNU General Public License
18793+ * along with this program; if not, write to the Free Software
18794+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18795+ */
18796+
1308ab2a 18797+/*
18798+ * poll operation
18799+ * There is only one filesystem which implements ->poll operation, currently.
18800+ */
18801+
18802+#include "aufs.h"
18803+
18804+unsigned int aufs_poll(struct file *file, poll_table *wait)
18805+{
18806+ unsigned int mask;
18807+ int err;
18808+ struct file *h_file;
18809+ struct dentry *dentry;
18810+ struct super_block *sb;
18811+
18812+ /* We should pretend an error happened. */
18813+ mask = POLLERR /* | POLLIN | POLLOUT */;
18814+ dentry = file->f_dentry;
18815+ sb = dentry->d_sb;
18816+ si_read_lock(sb, AuLock_FLUSH);
18817+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
18818+ if (unlikely(err))
18819+ goto out;
18820+
18821+ /* it is not an error if h_file has no operation */
18822+ mask = DEFAULT_POLLMASK;
4a4d8108 18823+ h_file = au_hf_top(file);
1308ab2a 18824+ if (h_file->f_op && h_file->f_op->poll)
18825+ mask = h_file->f_op->poll(h_file, wait);
18826+
18827+ di_read_unlock(dentry, AuLock_IR);
18828+ fi_read_unlock(file);
18829+
18830+ out:
18831+ si_read_unlock(sb);
18832+ AuTraceErr((int)mask);
18833+ return mask;
18834+}
4a4d8108
AM
18835diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/rdu.c linux-2.6.34/fs/aufs/rdu.c
18836--- linux-2.6.34.org/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
18837+++ linux-2.6.34/fs/aufs/rdu.c 2010-05-31 22:15:32.000000000 +0200
18838@@ -0,0 +1,330 @@
1308ab2a 18839+/*
4a4d8108 18840+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 18841+ *
18842+ * This program, aufs is free software; you can redistribute it and/or modify
18843+ * it under the terms of the GNU General Public License as published by
18844+ * the Free Software Foundation; either version 2 of the License, or
18845+ * (at your option) any later version.
18846+ *
18847+ * This program is distributed in the hope that it will be useful,
18848+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18849+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18850+ * GNU General Public License for more details.
18851+ *
18852+ * You should have received a copy of the GNU General Public License
18853+ * along with this program; if not, write to the Free Software
18854+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18855+ */
18856+
18857+/*
18858+ * readdir in userspace.
18859+ */
18860+
4a4d8108 18861+#include <linux/fs_stack.h>
1308ab2a 18862+#include <linux/security.h>
18863+#include <linux/uaccess.h>
18864+#include <linux/aufs_type.h>
18865+#include "aufs.h"
18866+
18867+/* bits for struct aufs_rdu.flags */
18868+#define AuRdu_CALLED 1
18869+#define AuRdu_CONT (1 << 1)
18870+#define AuRdu_FULL (1 << 2)
18871+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
18872+#define au_fset_rdu(flags, name) { (flags) |= AuRdu_##name; }
18873+#define au_fclr_rdu(flags, name) { (flags) &= ~AuRdu_##name; }
18874+
18875+struct au_rdu_arg {
18876+ struct aufs_rdu *rdu;
18877+ union au_rdu_ent_ul ent;
18878+ unsigned long end;
18879+
18880+ struct super_block *sb;
18881+ int err;
18882+};
18883+
18884+static int au_rdu_fill(void *__arg, const char *name, int nlen,
18885+ loff_t offset, u64 h_ino, unsigned int d_type)
18886+{
18887+ int err, len;
18888+ struct au_rdu_arg *arg = __arg;
18889+ struct aufs_rdu *rdu = arg->rdu;
18890+ struct au_rdu_ent ent;
18891+
18892+ err = 0;
18893+ arg->err = 0;
18894+ au_fset_rdu(rdu->cookie.flags, CALLED);
18895+ len = au_rdu_len(nlen);
18896+ if (arg->ent.ul + len < arg->end) {
18897+ ent.ino = h_ino;
18898+ ent.bindex = rdu->cookie.bindex;
18899+ ent.type = d_type;
18900+ ent.nlen = nlen;
4a4d8108
AM
18901+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
18902+ ent.type = DT_UNKNOWN;
1308ab2a 18903+
18904+ err = -EFAULT;
18905+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
18906+ goto out;
18907+ if (copy_to_user(arg->ent.e->name, name, nlen))
18908+ goto out;
18909+ /* the terminating NULL */
18910+ if (__put_user(0, arg->ent.e->name + nlen))
18911+ goto out;
18912+ err = 0;
18913+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
18914+ arg->ent.ul += len;
18915+ rdu->rent++;
18916+ } else {
18917+ err = -EFAULT;
18918+ au_fset_rdu(rdu->cookie.flags, FULL);
18919+ rdu->full = 1;
18920+ rdu->tail = arg->ent;
18921+ }
18922+
18923+ out:
18924+ /* AuTraceErr(err); */
18925+ return err;
18926+}
18927+
18928+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
18929+{
18930+ int err;
18931+ loff_t offset;
18932+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
18933+
18934+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
18935+ err = offset;
18936+ if (unlikely(offset != cookie->h_pos))
18937+ goto out;
18938+
18939+ err = 0;
18940+ do {
18941+ arg->err = 0;
18942+ au_fclr_rdu(cookie->flags, CALLED);
18943+ /* smp_mb(); */
18944+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
18945+ if (err >= 0)
18946+ err = arg->err;
18947+ } while (!err
18948+ && au_ftest_rdu(cookie->flags, CALLED)
18949+ && !au_ftest_rdu(cookie->flags, FULL));
18950+ cookie->h_pos = h_file->f_pos;
18951+
18952+ out:
18953+ AuTraceErr(err);
18954+ return err;
18955+}
18956+
18957+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
18958+{
18959+ int err;
18960+ aufs_bindex_t bend;
18961+ struct au_rdu_arg arg;
18962+ struct dentry *dentry;
18963+ struct inode *inode;
18964+ struct file *h_file;
18965+ struct au_rdu_cookie *cookie = &rdu->cookie;
18966+
18967+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
18968+ if (unlikely(err)) {
18969+ err = -EFAULT;
18970+ AuTraceErr(err);
18971+ goto out;
18972+ }
18973+ rdu->rent = 0;
18974+ rdu->tail = rdu->ent;
18975+ rdu->full = 0;
18976+ arg.rdu = rdu;
18977+ arg.ent = rdu->ent;
18978+ arg.end = arg.ent.ul;
18979+ arg.end += rdu->sz;
18980+
18981+ err = -ENOTDIR;
18982+ if (unlikely(!file->f_op || !file->f_op->readdir))
18983+ goto out;
18984+
18985+ err = security_file_permission(file, MAY_READ);
18986+ AuTraceErr(err);
18987+ if (unlikely(err))
18988+ goto out;
18989+
18990+ dentry = file->f_dentry;
18991+ inode = dentry->d_inode;
18992+#if 1
18993+ mutex_lock(&inode->i_mutex);
18994+#else
18995+ err = mutex_lock_killable(&inode->i_mutex);
18996+ AuTraceErr(err);
18997+ if (unlikely(err))
18998+ goto out;
18999+#endif
19000+ err = -ENOENT;
19001+ if (unlikely(IS_DEADDIR(inode)))
19002+ goto out_mtx;
19003+
19004+ arg.sb = inode->i_sb;
19005+ si_read_lock(arg.sb, AuLock_FLUSH);
19006+ fi_read_lock(file);
19007+
19008+ err = -EAGAIN;
19009+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
19010+ && cookie->generation != au_figen(file)))
19011+ goto out_unlock;
19012+
19013+ err = 0;
19014+ if (!rdu->blk) {
19015+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
19016+ if (!rdu->blk)
19017+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
19018+ }
19019+ bend = au_fbstart(file);
19020+ if (cookie->bindex < bend)
19021+ cookie->bindex = bend;
4a4d8108 19022+ bend = au_fbend_dir(file);
1308ab2a 19023+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
19024+ for (; !err && cookie->bindex <= bend;
19025+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 19026+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 19027+ if (!h_file)
19028+ continue;
19029+
19030+ au_fclr_rdu(cookie->flags, FULL);
19031+ err = au_rdu_do(h_file, &arg);
19032+ AuTraceErr(err);
19033+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
19034+ break;
19035+ }
19036+ AuDbg("rent %llu\n", rdu->rent);
19037+
19038+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
19039+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
19040+ au_fset_rdu(cookie->flags, CONT);
19041+ cookie->generation = au_figen(file);
19042+ }
19043+
19044+ ii_read_lock_child(inode);
19045+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
19046+ ii_read_unlock(inode);
19047+
19048+ out_unlock:
19049+ fi_read_unlock(file);
19050+ si_read_unlock(arg.sb);
19051+ out_mtx:
19052+ mutex_unlock(&inode->i_mutex);
19053+ out:
19054+ AuTraceErr(err);
19055+ return err;
19056+}
19057+
19058+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
19059+{
19060+ int err;
19061+ ino_t ino;
19062+ unsigned long long nent;
19063+ union au_rdu_ent_ul *u;
19064+ struct au_rdu_ent ent;
19065+ struct super_block *sb;
19066+
19067+ err = 0;
19068+ nent = rdu->nent;
19069+ u = &rdu->ent;
19070+ sb = file->f_dentry->d_sb;
19071+ si_read_lock(sb, AuLock_FLUSH);
19072+ while (nent-- > 0) {
1308ab2a 19073+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
19074+ if (!err)
19075+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 19076+ if (unlikely(err)) {
19077+ err = -EFAULT;
19078+ AuTraceErr(err);
19079+ break;
19080+ }
19081+
19082+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
19083+ if (!ent.wh)
19084+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
19085+ else
19086+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
19087+ &ino);
19088+ if (unlikely(err)) {
19089+ AuTraceErr(err);
19090+ break;
19091+ }
19092+
19093+ err = __put_user(ino, &u->e->ino);
19094+ if (unlikely(err)) {
19095+ err = -EFAULT;
19096+ AuTraceErr(err);
19097+ break;
19098+ }
19099+ u->ul += au_rdu_len(ent.nlen);
19100+ }
19101+ si_read_unlock(sb);
19102+
19103+ return err;
19104+}
19105+
19106+/* ---------------------------------------------------------------------- */
19107+
19108+static int au_rdu_verify(struct aufs_rdu *rdu)
19109+{
19110+ AuDbg("rdu{%llu, %p, (%u, %u) | %u | %llu, %u, %u | "
19111+ "%llu, b%d, 0x%x, g%u}\n",
19112+ rdu->sz, rdu->ent.e, rdu->verify[0], rdu->verify[1],
19113+ rdu->blk,
19114+ rdu->rent, rdu->shwh, rdu->full,
19115+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
19116+ rdu->cookie.generation);
dece6358 19117+
1308ab2a 19118+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu)
19119+ && rdu->verify[AufsCtlRduV_SZ_PTR] == sizeof(rdu))
19120+ return 0;
dece6358 19121+
1308ab2a 19122+ AuDbg("%u:%u, %u:%u\n",
19123+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu),
19124+ rdu->verify[AufsCtlRduV_SZ_PTR], (unsigned int)sizeof(rdu));
19125+ return -EINVAL;
19126+}
19127+
19128+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 19129+{
1308ab2a 19130+ long err, e;
19131+ struct aufs_rdu rdu;
19132+ void __user *p = (void __user *)arg;
dece6358 19133+
1308ab2a 19134+ err = copy_from_user(&rdu, p, sizeof(rdu));
19135+ if (unlikely(err)) {
19136+ err = -EFAULT;
19137+ AuTraceErr(err);
19138+ goto out;
19139+ }
19140+ err = au_rdu_verify(&rdu);
dece6358
AM
19141+ if (unlikely(err))
19142+ goto out;
19143+
1308ab2a 19144+ switch (cmd) {
19145+ case AUFS_CTL_RDU:
19146+ err = au_rdu(file, &rdu);
19147+ if (unlikely(err))
19148+ break;
dece6358 19149+
1308ab2a 19150+ e = copy_to_user(p, &rdu, sizeof(rdu));
19151+ if (unlikely(e)) {
19152+ err = -EFAULT;
19153+ AuTraceErr(err);
19154+ }
19155+ break;
19156+ case AUFS_CTL_RDU_INO:
19157+ err = au_rdu_ino(file, &rdu);
19158+ break;
19159+
19160+ default:
4a4d8108 19161+ /* err = -ENOTTY; */
1308ab2a 19162+ err = -EINVAL;
19163+ }
dece6358
AM
19164+
19165+ out:
1308ab2a 19166+ AuTraceErr(err);
19167+ return err;
1facf9fc 19168+}
4a4d8108
AM
19169diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/rwsem.h linux-2.6.34/fs/aufs/rwsem.h
19170--- linux-2.6.34.org/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
19171+++ linux-2.6.34/fs/aufs/rwsem.h 2010-05-31 22:15:32.000000000 +0200
19172@@ -0,0 +1,187 @@
1facf9fc 19173+/*
4a4d8108 19174+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19175+ *
19176+ * This program, aufs is free software; you can redistribute it and/or modify
19177+ * it under the terms of the GNU General Public License as published by
19178+ * the Free Software Foundation; either version 2 of the License, or
19179+ * (at your option) any later version.
dece6358
AM
19180+ *
19181+ * This program is distributed in the hope that it will be useful,
19182+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19183+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19184+ * GNU General Public License for more details.
19185+ *
19186+ * You should have received a copy of the GNU General Public License
19187+ * along with this program; if not, write to the Free Software
19188+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19189+ */
19190+
19191+/*
19192+ * simple read-write semaphore wrappers
19193+ */
19194+
19195+#ifndef __AUFS_RWSEM_H__
19196+#define __AUFS_RWSEM_H__
19197+
19198+#ifdef __KERNEL__
19199+
dece6358 19200+#include <linux/rwsem.h>
4a4d8108 19201+#include "debug.h"
dece6358
AM
19202+
19203+struct au_rwsem {
19204+ struct rw_semaphore rwsem;
19205+#ifdef CONFIG_AUFS_DEBUG
19206+ /* just for debugging, not almighty counter */
19207+ atomic_t rcnt, wcnt;
19208+#endif
19209+};
19210+
19211+#ifdef CONFIG_AUFS_DEBUG
19212+#define AuDbgCntInit(rw) do { \
19213+ atomic_set(&(rw)->rcnt, 0); \
19214+ atomic_set(&(rw)->wcnt, 0); \
19215+ smp_mb(); /* atomic set */ \
19216+} while (0)
19217+
19218+#define AuDbgRcntInc(rw) atomic_inc_return(&(rw)->rcnt)
19219+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
19220+#define AuDbgWcntInc(rw) WARN_ON(atomic_inc_return(&(rw)->wcnt) > 1)
19221+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
19222+#else
19223+#define AuDbgCntInit(rw) do {} while (0)
19224+#define AuDbgRcntInc(rw) do {} while (0)
19225+#define AuDbgRcntDec(rw) do {} while (0)
19226+#define AuDbgWcntInc(rw) do {} while (0)
19227+#define AuDbgWcntDec(rw) do {} while (0)
19228+#endif /* CONFIG_AUFS_DEBUG */
19229+
19230+/* to debug easier, do not make them inlined functions */
19231+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
19232+/* rwsem_is_locked() is unusable */
19233+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
19234+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
19235+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
19236+ && atomic_read(&(rw)->wcnt) <= 0)
19237+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
19238+ || atomic_read(&(rw)->wcnt))
19239+
19240+static inline void au_rw_init(struct au_rwsem *rw)
19241+{
19242+ AuDbgCntInit(rw);
19243+ init_rwsem(&rw->rwsem);
19244+}
19245+
19246+static inline void au_rw_init_wlock(struct au_rwsem *rw)
19247+{
19248+ au_rw_init(rw);
19249+ down_write(&rw->rwsem);
19250+ AuDbgWcntInc(rw);
19251+}
19252+
19253+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
19254+ unsigned int lsc)
19255+{
19256+ au_rw_init(rw);
19257+ down_write_nested(&rw->rwsem, lsc);
19258+ AuDbgWcntInc(rw);
19259+}
19260+
19261+static inline void au_rw_read_lock(struct au_rwsem *rw)
19262+{
19263+ down_read(&rw->rwsem);
19264+ AuDbgRcntInc(rw);
19265+}
19266+
19267+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
19268+{
19269+ down_read_nested(&rw->rwsem, lsc);
19270+ AuDbgRcntInc(rw);
19271+}
19272+
19273+static inline void au_rw_read_unlock(struct au_rwsem *rw)
19274+{
19275+ AuRwMustReadLock(rw);
19276+ AuDbgRcntDec(rw);
19277+ up_read(&rw->rwsem);
19278+}
19279+
19280+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
19281+{
19282+ AuRwMustWriteLock(rw);
19283+ AuDbgRcntInc(rw);
19284+ AuDbgWcntDec(rw);
19285+ downgrade_write(&rw->rwsem);
19286+}
19287+
19288+static inline void au_rw_write_lock(struct au_rwsem *rw)
19289+{
19290+ down_write(&rw->rwsem);
19291+ AuDbgWcntInc(rw);
19292+}
19293+
19294+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
19295+ unsigned int lsc)
19296+{
19297+ down_write_nested(&rw->rwsem, lsc);
19298+ AuDbgWcntInc(rw);
19299+}
1facf9fc 19300+
dece6358
AM
19301+static inline void au_rw_write_unlock(struct au_rwsem *rw)
19302+{
19303+ AuRwMustWriteLock(rw);
19304+ AuDbgWcntDec(rw);
19305+ up_write(&rw->rwsem);
19306+}
19307+
19308+/* why is not _nested version defined */
19309+static inline int au_rw_read_trylock(struct au_rwsem *rw)
19310+{
19311+ int ret = down_read_trylock(&rw->rwsem);
19312+ if (ret)
19313+ AuDbgRcntInc(rw);
19314+ return ret;
19315+}
19316+
19317+static inline int au_rw_write_trylock(struct au_rwsem *rw)
19318+{
19319+ int ret = down_write_trylock(&rw->rwsem);
19320+ if (ret)
19321+ AuDbgWcntInc(rw);
19322+ return ret;
19323+}
19324+
19325+#undef AuDbgCntInit
19326+#undef AuDbgRcntInc
19327+#undef AuDbgRcntDec
19328+#undef AuDbgWcntInc
19329+#undef AuDbgWcntDec
1facf9fc 19330+
19331+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
19332+static inline void prefix##_read_lock(param) \
dece6358 19333+{ au_rw_read_lock(rwsem); } \
1facf9fc 19334+static inline void prefix##_write_lock(param) \
dece6358 19335+{ au_rw_write_lock(rwsem); } \
1facf9fc 19336+static inline int prefix##_read_trylock(param) \
dece6358 19337+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 19338+static inline int prefix##_write_trylock(param) \
dece6358 19339+{ return au_rw_write_trylock(rwsem); }
1facf9fc 19340+/* why is not _nested version defined */
19341+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 19342+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 19343+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 19344+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 19345+
19346+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
19347+static inline void prefix##_read_unlock(param) \
dece6358 19348+{ au_rw_read_unlock(rwsem); } \
1facf9fc 19349+static inline void prefix##_write_unlock(param) \
dece6358 19350+{ au_rw_write_unlock(rwsem); } \
1facf9fc 19351+static inline void prefix##_downgrade_lock(param) \
dece6358 19352+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 19353+
19354+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
19355+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
19356+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
19357+
19358+#endif /* __KERNEL__ */
19359+#endif /* __AUFS_RWSEM_H__ */
4a4d8108
AM
19360diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/sbinfo.c linux-2.6.34/fs/aufs/sbinfo.c
19361--- linux-2.6.34.org/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
19362+++ linux-2.6.34/fs/aufs/sbinfo.c 2010-05-31 22:15:32.000000000 +0200
19363@@ -0,0 +1,202 @@
1facf9fc 19364+/*
4a4d8108 19365+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19366+ *
19367+ * This program, aufs is free software; you can redistribute it and/or modify
19368+ * it under the terms of the GNU General Public License as published by
19369+ * the Free Software Foundation; either version 2 of the License, or
19370+ * (at your option) any later version.
dece6358
AM
19371+ *
19372+ * This program is distributed in the hope that it will be useful,
19373+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19374+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19375+ * GNU General Public License for more details.
19376+ *
19377+ * You should have received a copy of the GNU General Public License
19378+ * along with this program; if not, write to the Free Software
19379+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19380+ */
19381+
19382+/*
19383+ * superblock private data
19384+ */
19385+
19386+#include "aufs.h"
19387+
19388+/*
19389+ * they are necessary regardless sysfs is disabled.
19390+ */
19391+void au_si_free(struct kobject *kobj)
19392+{
19393+ struct au_sbinfo *sbinfo;
19394+ struct super_block *sb;
19395+
19396+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
19397+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
4a4d8108 19398+ AuDebugOn(sbinfo->si_plink_maint);
1facf9fc 19399+
19400+ sb = sbinfo->si_sb;
19401+ si_write_lock(sb);
19402+ au_xino_clr(sb);
19403+ au_br_free(sbinfo);
19404+ kfree(sbinfo->si_branch);
19405+ mutex_destroy(&sbinfo->si_xib_mtx);
19406+ si_write_unlock(sb);
dece6358 19407+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 19408+
19409+ kfree(sbinfo);
19410+}
19411+
19412+int au_si_alloc(struct super_block *sb)
19413+{
19414+ int err;
19415+ struct au_sbinfo *sbinfo;
19416+
19417+ err = -ENOMEM;
4a4d8108 19418+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 19419+ if (unlikely(!sbinfo))
19420+ goto out;
19421+
19422+ /* will be reallocated separately */
19423+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
19424+ if (unlikely(!sbinfo->si_branch))
19425+ goto out_sbinfo;
19426+
1facf9fc 19427+ err = sysaufs_si_init(sbinfo);
19428+ if (unlikely(err))
19429+ goto out_br;
19430+
19431+ au_nwt_init(&sbinfo->si_nowait);
dece6358 19432+ au_rw_init_wlock(&sbinfo->si_rwsem);
1facf9fc 19433+ sbinfo->si_bend = -1;
1facf9fc 19434+
19435+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
19436+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
19437+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
19438+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 19439+
19440+ sbinfo->si_mntflags = AuOpt_Def;
19441+
1facf9fc 19442+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 19443+ sbinfo->si_xino_brid = -1;
19444+ /* leave si_xib_last_pindex and si_xib_next_bit */
19445+
19446+ sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
19447+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
19448+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
19449+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
19450+
19451+ au_spl_init(&sbinfo->si_plink);
19452+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 19453+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 19454+
19455+ /* leave other members for sysaufs and si_mnt. */
19456+ sbinfo->si_sb = sb;
19457+ sb->s_fs_info = sbinfo;
19458+ au_debug_sbinfo_init(sbinfo);
19459+ return 0; /* success */
19460+
19461+ out_br:
19462+ kfree(sbinfo->si_branch);
19463+ out_sbinfo:
19464+ kfree(sbinfo);
19465+ out:
19466+ return err;
19467+}
19468+
19469+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
19470+{
19471+ int err, sz;
19472+ struct au_branch **brp;
19473+
dece6358
AM
19474+ AuRwMustWriteLock(&sbinfo->si_rwsem);
19475+
1facf9fc 19476+ err = -ENOMEM;
19477+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
19478+ if (unlikely(!sz))
19479+ sz = sizeof(*brp);
19480+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
19481+ if (brp) {
19482+ sbinfo->si_branch = brp;
19483+ err = 0;
19484+ }
19485+
19486+ return err;
19487+}
19488+
19489+/* ---------------------------------------------------------------------- */
19490+
19491+unsigned int au_sigen_inc(struct super_block *sb)
19492+{
19493+ unsigned int gen;
19494+
dece6358
AM
19495+ SiMustWriteLock(sb);
19496+
1facf9fc 19497+ gen = ++au_sbi(sb)->si_generation;
19498+ au_update_digen(sb->s_root);
19499+ au_update_iigen(sb->s_root->d_inode);
19500+ sb->s_root->d_inode->i_version++;
19501+ return gen;
19502+}
19503+
19504+aufs_bindex_t au_new_br_id(struct super_block *sb)
19505+{
19506+ aufs_bindex_t br_id;
19507+ int i;
19508+ struct au_sbinfo *sbinfo;
19509+
dece6358
AM
19510+ SiMustWriteLock(sb);
19511+
1facf9fc 19512+ sbinfo = au_sbi(sb);
19513+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
19514+ br_id = ++sbinfo->si_last_br_id;
19515+ if (br_id && au_br_index(sb, br_id) < 0)
19516+ return br_id;
19517+ }
19518+
19519+ return -1;
19520+}
19521+
19522+/* ---------------------------------------------------------------------- */
19523+
19524+/* dentry and super_block lock. call at entry point */
19525+void aufs_read_lock(struct dentry *dentry, int flags)
19526+{
19527+ si_read_lock(dentry->d_sb, flags);
19528+ if (au_ftest_lock(flags, DW))
19529+ di_write_lock_child(dentry);
19530+ else
19531+ di_read_lock_child(dentry, flags);
19532+}
19533+
19534+void aufs_read_unlock(struct dentry *dentry, int flags)
19535+{
19536+ if (au_ftest_lock(flags, DW))
19537+ di_write_unlock(dentry);
19538+ else
19539+ di_read_unlock(dentry, flags);
19540+ si_read_unlock(dentry->d_sb);
19541+}
19542+
19543+void aufs_write_lock(struct dentry *dentry)
19544+{
19545+ si_write_lock(dentry->d_sb);
19546+ di_write_lock_child(dentry);
19547+}
19548+
19549+void aufs_write_unlock(struct dentry *dentry)
19550+{
19551+ di_write_unlock(dentry);
19552+ si_write_unlock(dentry->d_sb);
19553+}
19554+
19555+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
19556+{
19557+ si_read_lock(d1->d_sb, flags);
19558+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
19559+}
19560+
19561+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
19562+{
19563+ di_write_unlock2(d1, d2);
19564+ si_read_unlock(d1->d_sb);
19565+}
4a4d8108
AM
19566diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/spl.h linux-2.6.34/fs/aufs/spl.h
19567--- linux-2.6.34.org/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
19568+++ linux-2.6.34/fs/aufs/spl.h 2010-05-31 22:15:32.000000000 +0200
19569@@ -0,0 +1,66 @@
1facf9fc 19570+/*
4a4d8108 19571+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19572+ *
19573+ * This program, aufs is free software; you can redistribute it and/or modify
19574+ * it under the terms of the GNU General Public License as published by
19575+ * the Free Software Foundation; either version 2 of the License, or
19576+ * (at your option) any later version.
dece6358
AM
19577+ *
19578+ * This program is distributed in the hope that it will be useful,
19579+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19580+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19581+ * GNU General Public License for more details.
19582+ *
19583+ * You should have received a copy of the GNU General Public License
19584+ * along with this program; if not, write to the Free Software
19585+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19586+ */
19587+
19588+/*
19589+ * simple list protected by a spinlock
19590+ */
19591+
19592+#ifndef __AUFS_SPL_H__
19593+#define __AUFS_SPL_H__
19594+
19595+#ifdef __KERNEL__
19596+
dece6358
AM
19597+#include <linux/spinlock.h>
19598+#include <linux/list.h>
4a4d8108 19599+#include <linux/rculist.h>
1facf9fc 19600+
19601+struct au_splhead {
19602+ spinlock_t spin;
19603+ struct list_head head;
19604+};
19605+
19606+static inline void au_spl_init(struct au_splhead *spl)
19607+{
19608+ spin_lock_init(&spl->spin);
19609+ INIT_LIST_HEAD(&spl->head);
19610+}
19611+
19612+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
19613+{
19614+ spin_lock(&spl->spin);
19615+ list_add(list, &spl->head);
19616+ spin_unlock(&spl->spin);
19617+}
19618+
19619+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
19620+{
19621+ spin_lock(&spl->spin);
19622+ list_del(list);
19623+ spin_unlock(&spl->spin);
19624+}
19625+
4a4d8108
AM
19626+static inline void au_spl_del_rcu(struct list_head *list,
19627+ struct au_splhead *spl)
19628+{
19629+ spin_lock(&spl->spin);
19630+ list_del_rcu(list);
19631+ spin_unlock(&spl->spin);
19632+}
19633+
1facf9fc 19634+#endif /* __KERNEL__ */
19635+#endif /* __AUFS_SPL_H__ */
4a4d8108
AM
19636diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/super.c linux-2.6.34/fs/aufs/super.c
19637--- linux-2.6.34.org/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
19638+++ linux-2.6.34/fs/aufs/super.c 2010-05-31 22:15:32.000000000 +0200
19639@@ -0,0 +1,847 @@
1facf9fc 19640+/*
4a4d8108 19641+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19642+ *
19643+ * This program, aufs is free software; you can redistribute it and/or modify
19644+ * it under the terms of the GNU General Public License as published by
19645+ * the Free Software Foundation; either version 2 of the License, or
19646+ * (at your option) any later version.
dece6358
AM
19647+ *
19648+ * This program is distributed in the hope that it will be useful,
19649+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19650+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19651+ * GNU General Public License for more details.
19652+ *
19653+ * You should have received a copy of the GNU General Public License
19654+ * along with this program; if not, write to the Free Software
19655+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19656+ */
19657+
19658+/*
19659+ * mount and super_block operations
19660+ */
19661+
19662+#include <linux/buffer_head.h>
dece6358 19663+#include <linux/module.h>
1facf9fc 19664+#include <linux/seq_file.h>
19665+#include <linux/statfs.h>
19666+#include "aufs.h"
19667+
19668+/*
19669+ * super_operations
19670+ */
19671+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
19672+{
19673+ struct au_icntnr *c;
19674+
19675+ c = au_cache_alloc_icntnr();
19676+ if (c) {
1facf9fc 19677+ c->vfs_inode.i_version = 1; /* sigen(sb); */
19678+ c->iinfo.ii_hinode = NULL;
19679+ return &c->vfs_inode;
19680+ }
19681+ return NULL;
19682+}
19683+
19684+static void aufs_destroy_inode(struct inode *inode)
19685+{
19686+ au_iinfo_fin(inode);
19687+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
19688+}
19689+
19690+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
19691+{
19692+ struct inode *inode;
19693+ int err;
19694+
19695+ inode = iget_locked(sb, ino);
19696+ if (unlikely(!inode)) {
19697+ inode = ERR_PTR(-ENOMEM);
19698+ goto out;
19699+ }
19700+ if (!(inode->i_state & I_NEW))
19701+ goto out;
19702+
19703+ err = au_xigen_new(inode);
19704+ if (!err)
19705+ err = au_iinfo_init(inode);
19706+ if (!err)
19707+ inode->i_version++;
19708+ else {
19709+ iget_failed(inode);
19710+ inode = ERR_PTR(err);
19711+ }
19712+
19713+ out:
19714+ /* never return NULL */
19715+ AuDebugOn(!inode);
19716+ AuTraceErrPtr(inode);
19717+ return inode;
19718+}
19719+
19720+/* lock free root dinfo */
19721+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
19722+{
19723+ int err;
19724+ aufs_bindex_t bindex, bend;
19725+ struct path path;
4a4d8108 19726+ struct au_hdentry *hdp;
1facf9fc 19727+ struct au_branch *br;
19728+
19729+ err = 0;
19730+ bend = au_sbend(sb);
4a4d8108 19731+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 19732+ for (bindex = 0; !err && bindex <= bend; bindex++) {
19733+ br = au_sbr(sb, bindex);
19734+ path.mnt = br->br_mnt;
4a4d8108 19735+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 19736+ err = au_seq_path(seq, &path);
19737+ if (err > 0)
19738+ err = seq_printf(seq, "=%s",
19739+ au_optstr_br_perm(br->br_perm));
19740+ if (!err && bindex != bend)
19741+ err = seq_putc(seq, ':');
19742+ }
19743+
19744+ return err;
19745+}
19746+
19747+static void au_show_wbr_create(struct seq_file *m, int v,
19748+ struct au_sbinfo *sbinfo)
19749+{
19750+ const char *pat;
19751+
dece6358
AM
19752+ AuRwMustAnyLock(&sbinfo->si_rwsem);
19753+
1facf9fc 19754+ seq_printf(m, ",create=");
19755+ pat = au_optstr_wbr_create(v);
19756+ switch (v) {
19757+ case AuWbrCreate_TDP:
19758+ case AuWbrCreate_RR:
19759+ case AuWbrCreate_MFS:
19760+ case AuWbrCreate_PMFS:
19761+ seq_printf(m, pat);
19762+ break;
19763+ case AuWbrCreate_MFSV:
19764+ seq_printf(m, /*pat*/"mfs:%lu",
19765+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
19766+ break;
19767+ case AuWbrCreate_PMFSV:
19768+ seq_printf(m, /*pat*/"pmfs:%lu",
19769+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
19770+ break;
19771+ case AuWbrCreate_MFSRR:
19772+ seq_printf(m, /*pat*/"mfsrr:%llu",
19773+ sbinfo->si_wbr_mfs.mfsrr_watermark);
19774+ break;
19775+ case AuWbrCreate_MFSRRV:
19776+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
19777+ sbinfo->si_wbr_mfs.mfsrr_watermark,
19778+ sbinfo->si_wbr_mfs.mfs_expire / HZ);
19779+ break;
19780+ }
19781+}
19782+
19783+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
19784+{
19785+#ifdef CONFIG_SYSFS
19786+ return 0;
19787+#else
19788+ int err;
19789+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
19790+ aufs_bindex_t bindex, brid;
19791+ struct super_block *sb;
19792+ struct qstr *name;
19793+ struct file *f;
19794+ struct dentry *d, *h_root;
4a4d8108 19795+ struct au_hdentry *hdp;
1facf9fc 19796+
dece6358
AM
19797+ AuRwMustAnyLock(&sbinfo->si_rwsem);
19798+
1facf9fc 19799+ err = 0;
19800+ sb = mnt->mnt_sb;
19801+ f = au_sbi(sb)->si_xib;
19802+ if (!f)
19803+ goto out;
19804+
19805+ /* stop printing the default xino path on the first writable branch */
19806+ h_root = NULL;
19807+ brid = au_xino_brid(sb);
19808+ if (brid >= 0) {
19809+ bindex = au_br_index(sb, brid);
4a4d8108
AM
19810+ hdp = au_di(sb->s_root)->di_hdentry;
19811+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 19812+ }
19813+ d = f->f_dentry;
19814+ name = &d->d_name;
19815+ /* safe ->d_parent because the file is unlinked */
19816+ if (d->d_parent == h_root
19817+ && name->len == len
19818+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
19819+ goto out;
19820+
19821+ seq_puts(seq, ",xino=");
19822+ err = au_xino_path(seq, f);
19823+
19824+ out:
19825+ return err;
19826+#endif
19827+}
19828+
19829+/* seq_file will re-call me in case of too long string */
19830+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
19831+{
19832+ int err, n;
19833+ unsigned int mnt_flags, v;
19834+ struct super_block *sb;
19835+ struct au_sbinfo *sbinfo;
19836+
19837+#define AuBool(name, str) do { \
19838+ v = au_opt_test(mnt_flags, name); \
19839+ if (v != au_opt_test(AuOpt_Def, name)) \
19840+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
19841+} while (0)
19842+
19843+#define AuStr(name, str) do { \
19844+ v = mnt_flags & AuOptMask_##name; \
19845+ if (v != (AuOpt_Def & AuOptMask_##name)) \
19846+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
19847+} while (0)
19848+
19849+#define AuUInt(name, str, val) do { \
19850+ if (val != AUFS_##name##_DEF) \
19851+ seq_printf(m, "," #str "=%u", val); \
19852+} while (0)
19853+
19854+ /* lock free root dinfo */
19855+ sb = mnt->mnt_sb;
19856+ si_noflush_read_lock(sb);
19857+ sbinfo = au_sbi(sb);
19858+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
19859+
19860+ mnt_flags = au_mntflags(sb);
19861+ if (au_opt_test(mnt_flags, XINO)) {
19862+ err = au_show_xino(m, mnt);
19863+ if (unlikely(err))
19864+ goto out;
19865+ } else
19866+ seq_puts(m, ",noxino");
19867+
19868+ AuBool(TRUNC_XINO, trunc_xino);
19869+ AuStr(UDBA, udba);
dece6358 19870+ AuBool(SHWH, shwh);
1facf9fc 19871+ AuBool(PLINK, plink);
4a4d8108 19872+ AuBool(DIO, dio);
1facf9fc 19873+ /* AuBool(DIRPERM1, dirperm1); */
19874+ /* AuBool(REFROF, refrof); */
19875+
19876+ v = sbinfo->si_wbr_create;
19877+ if (v != AuWbrCreate_Def)
19878+ au_show_wbr_create(m, v, sbinfo);
19879+
19880+ v = sbinfo->si_wbr_copyup;
19881+ if (v != AuWbrCopyup_Def)
19882+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
19883+
19884+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
19885+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
19886+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
19887+
19888+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
19889+
19890+ n = sbinfo->si_rdcache / HZ;
19891+ AuUInt(RDCACHE, rdcache, n);
19892+
19893+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
19894+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
19895+
19896+ AuBool(SUM, sum);
19897+ /* AuBool(SUM_W, wsum); */
19898+ AuBool(WARN_PERM, warn_perm);
19899+ AuBool(VERBOSE, verbose);
19900+
19901+ out:
19902+ /* be sure to print "br:" last */
19903+ if (!sysaufs_brs) {
19904+ seq_puts(m, ",br:");
19905+ au_show_brs(m, sb);
19906+ }
19907+ si_read_unlock(sb);
19908+ return 0;
19909+
1facf9fc 19910+#undef AuBool
19911+#undef AuStr
4a4d8108 19912+#undef AuUInt
1facf9fc 19913+}
19914+
19915+/* ---------------------------------------------------------------------- */
19916+
19917+/* sum mode which returns the summation for statfs(2) */
19918+
19919+static u64 au_add_till_max(u64 a, u64 b)
19920+{
19921+ u64 old;
19922+
19923+ old = a;
19924+ a += b;
19925+ if (old < a)
19926+ return a;
19927+ return ULLONG_MAX;
19928+}
19929+
19930+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
19931+{
19932+ int err;
19933+ u64 blocks, bfree, bavail, files, ffree;
19934+ aufs_bindex_t bend, bindex, i;
19935+ unsigned char shared;
19936+ struct vfsmount *h_mnt;
19937+ struct super_block *h_sb;
19938+
19939+ blocks = 0;
19940+ bfree = 0;
19941+ bavail = 0;
19942+ files = 0;
19943+ ffree = 0;
19944+
19945+ err = 0;
19946+ bend = au_sbend(sb);
19947+ for (bindex = bend; bindex >= 0; bindex--) {
19948+ h_mnt = au_sbr_mnt(sb, bindex);
19949+ h_sb = h_mnt->mnt_sb;
19950+ shared = 0;
19951+ for (i = bindex + 1; !shared && i <= bend; i++)
19952+ shared = (au_sbr_sb(sb, i) == h_sb);
19953+ if (shared)
19954+ continue;
19955+
19956+ /* sb->s_root for NFS is unreliable */
19957+ err = vfs_statfs(h_mnt->mnt_root, buf);
19958+ if (unlikely(err))
19959+ goto out;
19960+
19961+ blocks = au_add_till_max(blocks, buf->f_blocks);
19962+ bfree = au_add_till_max(bfree, buf->f_bfree);
19963+ bavail = au_add_till_max(bavail, buf->f_bavail);
19964+ files = au_add_till_max(files, buf->f_files);
19965+ ffree = au_add_till_max(ffree, buf->f_ffree);
19966+ }
19967+
19968+ buf->f_blocks = blocks;
19969+ buf->f_bfree = bfree;
19970+ buf->f_bavail = bavail;
19971+ buf->f_files = files;
19972+ buf->f_ffree = ffree;
19973+
19974+ out:
19975+ return err;
19976+}
19977+
19978+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
19979+{
19980+ int err;
19981+ struct super_block *sb;
19982+
19983+ /* lock free root dinfo */
19984+ sb = dentry->d_sb;
19985+ si_noflush_read_lock(sb);
19986+ if (!au_opt_test(au_mntflags(sb), SUM))
19987+ /* sb->s_root for NFS is unreliable */
19988+ err = vfs_statfs(au_sbr_mnt(sb, 0)->mnt_root, buf);
19989+ else
19990+ err = au_statfs_sum(sb, buf);
19991+ si_read_unlock(sb);
19992+
19993+ if (!err) {
19994+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 19995+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 19996+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
19997+ }
19998+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
19999+
20000+ return err;
20001+}
20002+
20003+/* ---------------------------------------------------------------------- */
20004+
1facf9fc 20005+/*
20006+ * this IS NOT for super_operations.
20007+ * I guess it will be reverted someday.
20008+ */
20009+static void aufs_umount_begin(struct super_block *sb)
20010+{
20011+ struct au_sbinfo *sbinfo;
20012+
20013+ sbinfo = au_sbi(sb);
20014+ if (!sbinfo)
20015+ return;
20016+
20017+ si_write_lock(sb);
1facf9fc 20018+ if (au_opt_test(au_mntflags(sb), PLINK))
20019+ au_plink_put(sb);
20020+ if (sbinfo->si_wbr_create_ops->fin)
20021+ sbinfo->si_wbr_create_ops->fin(sb);
20022+ si_write_unlock(sb);
20023+}
20024+
20025+/* final actions when unmounting a file system */
20026+static void aufs_put_super(struct super_block *sb)
20027+{
20028+ struct au_sbinfo *sbinfo;
20029+
20030+ sbinfo = au_sbi(sb);
20031+ if (!sbinfo)
20032+ return;
20033+
20034+ aufs_umount_begin(sb);
20035+ dbgaufs_si_fin(sbinfo);
20036+ kobject_put(&sbinfo->si_kobj);
20037+}
20038+
20039+/* ---------------------------------------------------------------------- */
20040+
20041+/*
20042+ * refresh dentry and inode at remount time.
20043+ */
20044+static int do_refresh(struct dentry *dentry, mode_t type,
20045+ unsigned int dir_flags)
20046+{
20047+ int err;
20048+ struct dentry *parent;
20049+
20050+ di_write_lock_child(dentry);
20051+ parent = dget_parent(dentry);
20052+ di_read_lock_parent(parent, AuLock_IR);
20053+
20054+ /* returns the number of positive dentries */
20055+ err = au_refresh_hdentry(dentry, type);
20056+ if (err >= 0) {
20057+ struct inode *inode = dentry->d_inode;
20058+ err = au_refresh_hinode(inode, dentry);
20059+ if (!err && type == S_IFDIR)
4a4d8108 20060+ au_hn_reset(inode, dir_flags);
1facf9fc 20061+ }
20062+ if (unlikely(err))
4a4d8108
AM
20063+ pr_err("unrecoverable error %d, %.*s\n",
20064+ err, AuDLNPair(dentry));
1facf9fc 20065+
20066+ di_read_unlock(parent, AuLock_IR);
20067+ dput(parent);
20068+ di_write_unlock(dentry);
20069+
20070+ return err;
20071+}
20072+
20073+static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
20074+{
20075+ return S_ISDIR(dentry->d_inode->i_mode);
20076+}
20077+
20078+/* gave up consolidating with refresh_nondir() */
20079+static int refresh_dir(struct dentry *root, unsigned int sigen)
20080+{
20081+ int err, i, j, ndentry, e;
20082+ struct au_dcsub_pages dpages;
20083+ struct au_dpage *dpage;
20084+ struct dentry **dentries;
20085+ struct inode *inode;
20086+ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
20087+
20088+ err = 0;
20089+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20090+ if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20091+ ii_write_lock_child(inode);
20092+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
20093+ ii_write_unlock(inode);
20094+ if (unlikely(e)) {
20095+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
20096+ if (!err)
20097+ err = e;
20098+ /* go on even if err */
20099+ }
20100+ }
20101+
20102+ e = au_dpages_init(&dpages, GFP_NOFS);
20103+ if (unlikely(e)) {
20104+ if (!err)
20105+ err = e;
20106+ goto out;
20107+ }
20108+ e = au_dcsub_pages(&dpages, root, test_dir, NULL);
20109+ if (unlikely(e)) {
20110+ if (!err)
20111+ err = e;
20112+ goto out_dpages;
20113+ }
20114+
20115+ for (i = 0; !e && i < dpages.ndpage; i++) {
20116+ dpage = dpages.dpages + i;
20117+ dentries = dpage->dentries;
20118+ ndentry = dpage->ndentry;
20119+ for (j = 0; !e && j < ndentry; j++) {
20120+ struct dentry *d;
20121+
20122+ d = dentries[j];
20123+ au_dbg_verify_dir_parent(d, sigen);
20124+ if (au_digen(d) != sigen) {
20125+ e = do_refresh(d, S_IFDIR, flags);
20126+ if (unlikely(e && !err))
20127+ err = e;
20128+ /* break on err */
20129+ }
20130+ }
20131+ }
20132+
20133+ out_dpages:
20134+ au_dpages_free(&dpages);
20135+ out:
20136+ return err;
20137+}
20138+
20139+static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
20140+{
20141+ return !S_ISDIR(dentry->d_inode->i_mode);
20142+}
20143+
20144+static int refresh_nondir(struct dentry *root, unsigned int sigen,
20145+ int do_dentry)
20146+{
20147+ int err, i, j, ndentry, e;
20148+ struct au_dcsub_pages dpages;
20149+ struct au_dpage *dpage;
20150+ struct dentry **dentries;
20151+ struct inode *inode;
20152+
20153+ err = 0;
20154+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20155+ if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20156+ ii_write_lock_child(inode);
20157+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
20158+ ii_write_unlock(inode);
20159+ if (unlikely(e)) {
20160+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
20161+ if (!err)
20162+ err = e;
20163+ /* go on even if err */
20164+ }
20165+ }
20166+
20167+ if (!do_dentry)
20168+ goto out;
20169+
20170+ e = au_dpages_init(&dpages, GFP_NOFS);
20171+ if (unlikely(e)) {
20172+ if (!err)
20173+ err = e;
20174+ goto out;
20175+ }
20176+ e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
20177+ if (unlikely(e)) {
20178+ if (!err)
20179+ err = e;
20180+ goto out_dpages;
20181+ }
20182+
20183+ for (i = 0; i < dpages.ndpage; i++) {
20184+ dpage = dpages.dpages + i;
20185+ dentries = dpage->dentries;
20186+ ndentry = dpage->ndentry;
20187+ for (j = 0; j < ndentry; j++) {
20188+ struct dentry *d;
20189+
20190+ d = dentries[j];
20191+ au_dbg_verify_nondir_parent(d, sigen);
20192+ inode = d->d_inode;
20193+ if (inode && au_digen(d) != sigen) {
20194+ e = do_refresh(d, inode->i_mode & S_IFMT,
20195+ /*dir_flags*/0);
20196+ if (unlikely(e && !err))
20197+ err = e;
20198+ /* go on even err */
20199+ }
20200+ }
20201+ }
20202+
20203+ out_dpages:
20204+ au_dpages_free(&dpages);
20205+ out:
20206+ return err;
20207+}
20208+
20209+static void au_remount_refresh(struct super_block *sb, unsigned int flags)
20210+{
20211+ int err;
20212+ unsigned int sigen;
20213+ struct au_sbinfo *sbinfo;
20214+ struct dentry *root;
20215+ struct inode *inode;
20216+
20217+ au_sigen_inc(sb);
20218+ sigen = au_sigen(sb);
20219+ sbinfo = au_sbi(sb);
20220+ au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
20221+
20222+ root = sb->s_root;
20223+ DiMustNoWaiters(root);
20224+ inode = root->d_inode;
20225+ IiMustNoWaiters(inode);
4a4d8108 20226+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 20227+ di_write_unlock(root);
20228+
20229+ err = refresh_dir(root, sigen);
20230+ if (unlikely(err)) {
20231+ au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
4a4d8108
AM
20232+ pr_warning("Refreshing directories failed, ignored (%d)\n",
20233+ err);
1facf9fc 20234+ }
20235+
20236+ if (au_ftest_opts(flags, REFRESH_NONDIR)) {
20237+ err = refresh_nondir(root, sigen, !err);
20238+ if (unlikely(err))
4a4d8108
AM
20239+ pr_warning("Refreshing non-directories failed, ignored"
20240+ "(%d)\n", err);
1facf9fc 20241+ }
20242+
20243+ /* aufs_write_lock() calls ..._child() */
20244+ di_write_lock_child(root);
20245+ au_cpup_attr_all(root->d_inode, /*force*/1);
20246+}
20247+
20248+/* stop extra interpretation of errno in mount(8), and strange error messages */
20249+static int cvt_err(int err)
20250+{
20251+ AuTraceErr(err);
20252+
20253+ switch (err) {
20254+ case -ENOENT:
20255+ case -ENOTDIR:
20256+ case -EEXIST:
20257+ case -EIO:
20258+ err = -EINVAL;
20259+ }
20260+ return err;
20261+}
20262+
20263+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
20264+{
4a4d8108
AM
20265+ int err, do_dx;
20266+ unsigned int mntflags;
1facf9fc 20267+ struct au_opts opts;
20268+ struct dentry *root;
20269+ struct inode *inode;
20270+ struct au_sbinfo *sbinfo;
20271+
20272+ err = 0;
20273+ root = sb->s_root;
20274+ if (!data || !*data) {
20275+ aufs_write_lock(root);
20276+ err = au_opts_verify(sb, *flags, /*pending*/0);
1facf9fc 20277+ aufs_write_unlock(root);
20278+ goto out;
20279+ }
20280+
20281+ err = -ENOMEM;
20282+ memset(&opts, 0, sizeof(opts));
20283+ opts.opt = (void *)__get_free_page(GFP_NOFS);
20284+ if (unlikely(!opts.opt))
20285+ goto out;
20286+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
20287+ opts.flags = AuOpts_REMOUNT;
20288+ opts.sb_flags = *flags;
20289+
20290+ /* parse it before aufs lock */
20291+ err = au_opts_parse(sb, data, &opts);
20292+ if (unlikely(err))
20293+ goto out_opts;
20294+
20295+ sbinfo = au_sbi(sb);
20296+ inode = root->d_inode;
20297+ mutex_lock(&inode->i_mutex);
20298+ aufs_write_lock(root);
1facf9fc 20299+
20300+ /* au_opts_remount() may return an error */
20301+ err = au_opts_remount(sb, &opts);
20302+ au_opts_free(&opts);
20303+
20304+ if (au_ftest_opts(opts.flags, REFRESH_DIR)
20305+ || au_ftest_opts(opts.flags, REFRESH_NONDIR))
20306+ au_remount_refresh(sb, opts.flags);
20307+
4a4d8108
AM
20308+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
20309+ mntflags = au_mntflags(sb);
20310+ do_dx = !!au_opt_test(mntflags, DIO);
20311+ au_dy_arefresh(do_dx);
20312+ }
20313+
1facf9fc 20314+ aufs_write_unlock(root);
20315+ mutex_unlock(&inode->i_mutex);
20316+
20317+ out_opts:
20318+ free_page((unsigned long)opts.opt);
20319+ out:
20320+ err = cvt_err(err);
20321+ AuTraceErr(err);
20322+ return err;
20323+}
20324+
4a4d8108 20325+static const struct super_operations aufs_sop = {
1facf9fc 20326+ .alloc_inode = aufs_alloc_inode,
20327+ .destroy_inode = aufs_destroy_inode,
20328+ .drop_inode = generic_delete_inode,
20329+ .show_options = aufs_show_options,
20330+ .statfs = aufs_statfs,
20331+ .put_super = aufs_put_super,
20332+ .remount_fs = aufs_remount_fs
20333+};
20334+
20335+/* ---------------------------------------------------------------------- */
20336+
20337+static int alloc_root(struct super_block *sb)
20338+{
20339+ int err;
20340+ struct inode *inode;
20341+ struct dentry *root;
20342+
20343+ err = -ENOMEM;
20344+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
20345+ err = PTR_ERR(inode);
20346+ if (IS_ERR(inode))
20347+ goto out;
20348+
20349+ inode->i_op = &aufs_dir_iop;
20350+ inode->i_fop = &aufs_dir_fop;
20351+ inode->i_mode = S_IFDIR;
20352+ inode->i_nlink = 2;
20353+ unlock_new_inode(inode);
20354+
20355+ root = d_alloc_root(inode);
20356+ if (unlikely(!root))
20357+ goto out_iput;
20358+ err = PTR_ERR(root);
20359+ if (IS_ERR(root))
20360+ goto out_iput;
20361+
4a4d8108 20362+ err = au_di_init(root);
1facf9fc 20363+ if (!err) {
20364+ sb->s_root = root;
20365+ return 0; /* success */
20366+ }
20367+ dput(root);
20368+ goto out; /* do not iput */
20369+
20370+ out_iput:
20371+ iget_failed(inode);
20372+ iput(inode);
20373+ out:
20374+ return err;
20375+
20376+}
20377+
20378+static int aufs_fill_super(struct super_block *sb, void *raw_data,
20379+ int silent __maybe_unused)
20380+{
20381+ int err;
20382+ struct au_opts opts;
20383+ struct dentry *root;
20384+ struct inode *inode;
20385+ char *arg = raw_data;
20386+
20387+ if (unlikely(!arg || !*arg)) {
20388+ err = -EINVAL;
4a4d8108 20389+ pr_err("no arg\n");
1facf9fc 20390+ goto out;
20391+ }
20392+
20393+ err = -ENOMEM;
20394+ memset(&opts, 0, sizeof(opts));
20395+ opts.opt = (void *)__get_free_page(GFP_NOFS);
20396+ if (unlikely(!opts.opt))
20397+ goto out;
20398+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
20399+ opts.sb_flags = sb->s_flags;
20400+
20401+ err = au_si_alloc(sb);
20402+ if (unlikely(err))
20403+ goto out_opts;
20404+
20405+ /* all timestamps always follow the ones on the branch */
20406+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
20407+ sb->s_op = &aufs_sop;
20408+ sb->s_magic = AUFS_SUPER_MAGIC;
20409+ sb->s_maxbytes = 0;
20410+ au_export_init(sb);
20411+
20412+ err = alloc_root(sb);
20413+ if (unlikely(err)) {
20414+ si_write_unlock(sb);
20415+ goto out_info;
20416+ }
20417+ root = sb->s_root;
20418+ inode = root->d_inode;
20419+
20420+ /*
20421+ * actually we can parse options regardless aufs lock here.
20422+ * but at remount time, parsing must be done before aufs lock.
20423+ * so we follow the same rule.
20424+ */
20425+ ii_write_lock_parent(inode);
20426+ aufs_write_unlock(root);
20427+ err = au_opts_parse(sb, arg, &opts);
20428+ if (unlikely(err))
20429+ goto out_root;
20430+
20431+ /* lock vfs_inode first, then aufs. */
20432+ mutex_lock(&inode->i_mutex);
1facf9fc 20433+ aufs_write_lock(root);
20434+ err = au_opts_mount(sb, &opts);
20435+ au_opts_free(&opts);
1facf9fc 20436+ aufs_write_unlock(root);
20437+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
20438+ if (!err)
20439+ goto out_opts; /* success */
1facf9fc 20440+
1facf9fc 20441+ out_root:
20442+ dput(root);
20443+ sb->s_root = NULL;
20444+ out_info:
20445+ kobject_put(&au_sbi(sb)->si_kobj);
20446+ sb->s_fs_info = NULL;
20447+ out_opts:
20448+ free_page((unsigned long)opts.opt);
20449+ out:
20450+ AuTraceErr(err);
20451+ err = cvt_err(err);
20452+ AuTraceErr(err);
20453+ return err;
20454+}
20455+
20456+/* ---------------------------------------------------------------------- */
20457+
20458+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
20459+ const char *dev_name __maybe_unused, void *raw_data,
20460+ struct vfsmount *mnt)
20461+{
20462+ int err;
20463+ struct super_block *sb;
20464+
20465+ /* all timestamps always follow the ones on the branch */
20466+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
20467+ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
20468+ if (!err) {
20469+ sb = mnt->mnt_sb;
20470+ si_write_lock(sb);
20471+ sysaufs_brs_add(sb, 0);
20472+ si_write_unlock(sb);
20473+ }
20474+ return err;
20475+}
20476+
20477+struct file_system_type aufs_fs_type = {
20478+ .name = AUFS_FSTYPE,
20479+ .fs_flags =
20480+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
20481+ | FS_REVAL_DOT, /* for NFS branch and udba */
20482+ .get_sb = aufs_get_sb,
20483+ .kill_sb = generic_shutdown_super,
20484+ /* no need to __module_get() and module_put(). */
20485+ .owner = THIS_MODULE,
20486+};
4a4d8108
AM
20487diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/super.h linux-2.6.34/fs/aufs/super.h
20488--- linux-2.6.34.org/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
20489+++ linux-2.6.34/fs/aufs/super.h 2010-05-31 22:15:32.000000000 +0200
20490@@ -0,0 +1,361 @@
1facf9fc 20491+/*
4a4d8108 20492+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20493+ *
20494+ * This program, aufs is free software; you can redistribute it and/or modify
20495+ * it under the terms of the GNU General Public License as published by
20496+ * the Free Software Foundation; either version 2 of the License, or
20497+ * (at your option) any later version.
dece6358
AM
20498+ *
20499+ * This program is distributed in the hope that it will be useful,
20500+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20501+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20502+ * GNU General Public License for more details.
20503+ *
20504+ * You should have received a copy of the GNU General Public License
20505+ * along with this program; if not, write to the Free Software
20506+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20507+ */
20508+
20509+/*
20510+ * super_block operations
20511+ */
20512+
20513+#ifndef __AUFS_SUPER_H__
20514+#define __AUFS_SUPER_H__
20515+
20516+#ifdef __KERNEL__
20517+
20518+#include <linux/fs.h>
1facf9fc 20519+#include <linux/aufs_type.h>
20520+#include "rwsem.h"
20521+#include "spl.h"
20522+#include "wkq.h"
20523+
20524+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
20525+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
20526+ loff_t *);
20527+
20528+/* policies to select one among multiple writable branches */
20529+struct au_wbr_copyup_operations {
20530+ int (*copyup)(struct dentry *dentry);
20531+};
20532+
20533+struct au_wbr_create_operations {
20534+ int (*create)(struct dentry *dentry, int isdir);
20535+ int (*init)(struct super_block *sb);
20536+ int (*fin)(struct super_block *sb);
20537+};
20538+
20539+struct au_wbr_mfs {
20540+ struct mutex mfs_lock; /* protect this structure */
20541+ unsigned long mfs_jiffy;
20542+ unsigned long mfs_expire;
20543+ aufs_bindex_t mfs_bindex;
20544+
20545+ unsigned long long mfsrr_bytes;
20546+ unsigned long long mfsrr_watermark;
20547+};
20548+
1facf9fc 20549+struct au_branch;
20550+struct au_sbinfo {
20551+ /* nowait tasks in the system-wide workqueue */
20552+ struct au_nowait_tasks si_nowait;
20553+
dece6358 20554+ struct au_rwsem si_rwsem;
1facf9fc 20555+
20556+ /* branch management */
20557+ unsigned int si_generation;
20558+
20559+ /* see above flags */
20560+ unsigned char au_si_status;
20561+
20562+ aufs_bindex_t si_bend;
20563+ aufs_bindex_t si_last_br_id;
20564+ struct au_branch **si_branch;
20565+
20566+ /* policy to select a writable branch */
20567+ unsigned char si_wbr_copyup;
20568+ unsigned char si_wbr_create;
20569+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
20570+ struct au_wbr_create_operations *si_wbr_create_ops;
20571+
20572+ /* round robin */
20573+ atomic_t si_wbr_rr_next;
20574+
20575+ /* most free space */
20576+ struct au_wbr_mfs si_wbr_mfs;
20577+
20578+ /* mount flags */
20579+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
20580+ unsigned int si_mntflags;
20581+
20582+ /* external inode number (bitmap and translation table) */
20583+ au_readf_t si_xread;
20584+ au_writef_t si_xwrite;
20585+ struct file *si_xib;
20586+ struct mutex si_xib_mtx; /* protect xib members */
20587+ unsigned long *si_xib_buf;
20588+ unsigned long si_xib_last_pindex;
20589+ int si_xib_next_bit;
20590+ aufs_bindex_t si_xino_brid;
20591+ /* reserved for future use */
20592+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
20593+
20594+#ifdef CONFIG_AUFS_EXPORT
20595+ /* i_generation */
20596+ struct file *si_xigen;
20597+ atomic_t si_xigen_next;
20598+#endif
20599+
20600+ /* vdir parameters */
20601+ unsigned long si_rdcache; /* max cache time in HZ */
20602+ unsigned int si_rdblk; /* deblk size */
20603+ unsigned int si_rdhash; /* hash size */
20604+
20605+ /*
20606+ * If the number of whiteouts are larger than si_dirwh, leave all of
20607+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
20608+ * future fsck.aufs or kernel thread will remove them later.
20609+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
20610+ */
20611+ unsigned int si_dirwh;
20612+
20613+ /*
20614+ * rename(2) a directory with all children.
20615+ */
20616+ /* reserved for future use */
20617+ /* int si_rendir; */
20618+
20619+ /* pseudo_link list */
20620+ struct au_splhead si_plink;
20621+ wait_queue_head_t si_plink_wq;
4a4d8108
AM
20622+ spinlock_t si_plink_maint_lock;
20623+ struct file *si_plink_maint;
1facf9fc 20624+
20625+ /*
20626+ * sysfs and lifetime management.
20627+ * this is not a small structure and it may be a waste of memory in case
20628+ * of sysfs is disabled, particulary when many aufs-es are mounted.
20629+ * but using sysfs is majority.
20630+ */
20631+ struct kobject si_kobj;
20632+#ifdef CONFIG_DEBUG_FS
20633+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
20634+#ifdef CONFIG_AUFS_EXPORT
20635+ struct dentry *si_dbgaufs_xigen;
20636+#endif
20637+#endif
20638+
20639+ /* dirty, necessary for unmounting, sysfs and sysrq */
20640+ struct super_block *si_sb;
20641+};
20642+
dece6358
AM
20643+/* sbinfo status flags */
20644+/*
20645+ * set true when refresh_dirs() failed at remount time.
20646+ * then try refreshing dirs at access time again.
20647+ * if it is false, refreshing dirs at access time is unnecesary
20648+ */
20649+#define AuSi_FAILED_REFRESH_DIRS 1
dece6358
AM
20650+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
20651+ unsigned int flag)
20652+{
20653+ AuRwMustAnyLock(&sbi->si_rwsem);
20654+ return sbi->au_si_status & flag;
20655+}
20656+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
20657+#define au_fset_si(sbinfo, name) do { \
20658+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
20659+ (sbinfo)->au_si_status |= AuSi_##name; \
20660+} while (0)
20661+#define au_fclr_si(sbinfo, name) do { \
20662+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
20663+ (sbinfo)->au_si_status &= ~AuSi_##name; \
20664+} while (0)
20665+
1facf9fc 20666+/* ---------------------------------------------------------------------- */
20667+
20668+/* policy to select one among writable branches */
4a4d8108
AM
20669+#define AuWbrCopyup(sbinfo, ...) \
20670+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
20671+#define AuWbrCreate(sbinfo, ...) \
20672+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 20673+
20674+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
20675+#define AuLock_DW 1 /* write-lock dentry */
20676+#define AuLock_IR (1 << 1) /* read-lock inode */
20677+#define AuLock_IW (1 << 2) /* write-lock inode */
20678+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
20679+#define AuLock_DIR (1 << 4) /* target is a dir */
20680+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
20681+#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
20682+#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
20683+
20684+/* ---------------------------------------------------------------------- */
20685+
20686+/* super.c */
20687+extern struct file_system_type aufs_fs_type;
20688+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
20689+
20690+/* sbinfo.c */
20691+void au_si_free(struct kobject *kobj);
20692+int au_si_alloc(struct super_block *sb);
20693+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
20694+
20695+unsigned int au_sigen_inc(struct super_block *sb);
20696+aufs_bindex_t au_new_br_id(struct super_block *sb);
20697+
20698+void aufs_read_lock(struct dentry *dentry, int flags);
20699+void aufs_read_unlock(struct dentry *dentry, int flags);
20700+void aufs_write_lock(struct dentry *dentry);
20701+void aufs_write_unlock(struct dentry *dentry);
20702+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
20703+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
20704+
20705+/* wbr_policy.c */
20706+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
20707+extern struct au_wbr_create_operations au_wbr_create_ops[];
20708+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
20709+
20710+/* ---------------------------------------------------------------------- */
20711+
20712+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
20713+{
20714+ return sb->s_fs_info;
20715+}
20716+
20717+/* ---------------------------------------------------------------------- */
20718+
20719+#ifdef CONFIG_AUFS_EXPORT
20720+void au_export_init(struct super_block *sb);
20721+
20722+static inline int au_test_nfsd(struct task_struct *tsk)
20723+{
20724+ return !tsk->mm && !strcmp(tsk->comm, "nfsd");
20725+}
20726+
20727+int au_xigen_inc(struct inode *inode);
20728+int au_xigen_new(struct inode *inode);
20729+int au_xigen_set(struct super_block *sb, struct file *base);
20730+void au_xigen_clr(struct super_block *sb);
20731+
20732+static inline int au_busy_or_stale(void)
20733+{
20734+ if (!au_test_nfsd(current))
20735+ return -EBUSY;
20736+ return -ESTALE;
20737+}
20738+#else
4a4d8108
AM
20739+AuStubVoid(au_export_init, struct super_block *sb)
20740+AuStubInt0(au_test_nfsd, struct task_struct *tsk)
20741+AuStubInt0(au_xigen_inc, struct inode *inode)
20742+AuStubInt0(au_xigen_new, struct inode *inode)
20743+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
20744+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 20745+static inline int au_busy_or_stale(void)
20746+{
20747+ return -EBUSY;
20748+}
20749+#endif /* CONFIG_AUFS_EXPORT */
20750+
20751+/* ---------------------------------------------------------------------- */
20752+
20753+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
20754+{
dece6358
AM
20755+ /*
20756+ * This function is a dynamic '__init' fucntion actually,
20757+ * so the tiny check for si_rwsem is unnecessary.
20758+ */
20759+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 20760+#ifdef CONFIG_DEBUG_FS
20761+ sbinfo->si_dbgaufs = NULL;
20762+ sbinfo->si_dbgaufs_xib = NULL;
20763+#ifdef CONFIG_AUFS_EXPORT
20764+ sbinfo->si_dbgaufs_xigen = NULL;
20765+#endif
20766+#endif
20767+}
20768+
20769+/* ---------------------------------------------------------------------- */
20770+
20771+/* lock superblock. mainly for entry point functions */
20772+/*
20773+ * si_noflush_read_lock, si_noflush_write_lock,
20774+ * si_read_unlock, si_write_unlock, si_downgrade_lock
20775+ */
20776+AuSimpleLockRwsemFuncs(si_noflush, struct super_block *sb,
20777+ &au_sbi(sb)->si_rwsem);
20778+AuSimpleUnlockRwsemFuncs(si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
20779+
dece6358
AM
20780+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
20781+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
20782+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
20783+
1facf9fc 20784+static inline void si_read_lock(struct super_block *sb, int flags)
20785+{
20786+ if (au_ftest_lock(flags, FLUSH))
20787+ au_nwt_flush(&au_sbi(sb)->si_nowait);
20788+ si_noflush_read_lock(sb);
20789+}
20790+
20791+static inline void si_write_lock(struct super_block *sb)
20792+{
20793+ au_nwt_flush(&au_sbi(sb)->si_nowait);
20794+ si_noflush_write_lock(sb);
20795+}
20796+
20797+static inline int si_read_trylock(struct super_block *sb, int flags)
20798+{
20799+ if (au_ftest_lock(flags, FLUSH))
20800+ au_nwt_flush(&au_sbi(sb)->si_nowait);
20801+ return si_noflush_read_trylock(sb);
20802+}
20803+
20804+static inline int si_write_trylock(struct super_block *sb, int flags)
20805+{
20806+ if (au_ftest_lock(flags, FLUSH))
20807+ au_nwt_flush(&au_sbi(sb)->si_nowait);
20808+ return si_noflush_write_trylock(sb);
20809+}
20810+
20811+/* ---------------------------------------------------------------------- */
20812+
20813+static inline aufs_bindex_t au_sbend(struct super_block *sb)
20814+{
dece6358 20815+ SiMustAnyLock(sb);
1facf9fc 20816+ return au_sbi(sb)->si_bend;
20817+}
20818+
20819+static inline unsigned int au_mntflags(struct super_block *sb)
20820+{
dece6358 20821+ SiMustAnyLock(sb);
1facf9fc 20822+ return au_sbi(sb)->si_mntflags;
20823+}
20824+
20825+static inline unsigned int au_sigen(struct super_block *sb)
20826+{
dece6358 20827+ SiMustAnyLock(sb);
1facf9fc 20828+ return au_sbi(sb)->si_generation;
20829+}
20830+
20831+static inline struct au_branch *au_sbr(struct super_block *sb,
20832+ aufs_bindex_t bindex)
20833+{
dece6358 20834+ SiMustAnyLock(sb);
1facf9fc 20835+ return au_sbi(sb)->si_branch[0 + bindex];
20836+}
20837+
20838+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
20839+{
dece6358 20840+ SiMustWriteLock(sb);
1facf9fc 20841+ au_sbi(sb)->si_xino_brid = brid;
20842+}
20843+
20844+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
20845+{
dece6358 20846+ SiMustAnyLock(sb);
1facf9fc 20847+ return au_sbi(sb)->si_xino_brid;
20848+}
20849+
20850+#endif /* __KERNEL__ */
20851+#endif /* __AUFS_SUPER_H__ */
4a4d8108
AM
20852diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/sysaufs.c linux-2.6.34/fs/aufs/sysaufs.c
20853--- linux-2.6.34.org/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
20854+++ linux-2.6.34/fs/aufs/sysaufs.c 2010-05-31 22:15:32.000000000 +0200
20855@@ -0,0 +1,107 @@
1facf9fc 20856+/*
4a4d8108 20857+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20858+ *
20859+ * This program, aufs is free software; you can redistribute it and/or modify
20860+ * it under the terms of the GNU General Public License as published by
20861+ * the Free Software Foundation; either version 2 of the License, or
20862+ * (at your option) any later version.
dece6358
AM
20863+ *
20864+ * This program is distributed in the hope that it will be useful,
20865+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20866+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20867+ * GNU General Public License for more details.
20868+ *
20869+ * You should have received a copy of the GNU General Public License
20870+ * along with this program; if not, write to the Free Software
20871+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20872+ */
20873+
20874+/*
20875+ * sysfs interface and lifetime management
20876+ * they are necessary regardless sysfs is disabled.
20877+ */
20878+
20879+#include <linux/fs.h>
20880+#include <linux/random.h>
20881+#include <linux/sysfs.h>
20882+#include "aufs.h"
20883+
20884+unsigned long sysaufs_si_mask;
20885+struct kset *sysaufs_ket;
20886+
20887+#define AuSiAttr(_name) { \
20888+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
20889+ .show = sysaufs_si_##_name, \
20890+}
20891+
20892+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
20893+struct attribute *sysaufs_si_attrs[] = {
20894+ &sysaufs_si_attr_xi_path.attr,
20895+ NULL,
20896+};
20897+
4a4d8108 20898+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 20899+ .show = sysaufs_si_show
20900+};
20901+
20902+static struct kobj_type au_sbi_ktype = {
20903+ .release = au_si_free,
20904+ .sysfs_ops = &au_sbi_ops,
20905+ .default_attrs = sysaufs_si_attrs
20906+};
20907+
20908+/* ---------------------------------------------------------------------- */
20909+
20910+int sysaufs_si_init(struct au_sbinfo *sbinfo)
20911+{
20912+ int err;
20913+
20914+ sbinfo->si_kobj.kset = sysaufs_ket;
20915+ /* cf. sysaufs_name() */
20916+ err = kobject_init_and_add
20917+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->kobj*/NULL,
20918+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
20919+
20920+ dbgaufs_si_null(sbinfo);
20921+ if (!err) {
20922+ err = dbgaufs_si_init(sbinfo);
20923+ if (unlikely(err))
20924+ kobject_put(&sbinfo->si_kobj);
20925+ }
20926+ return err;
20927+}
20928+
20929+void sysaufs_fin(void)
20930+{
20931+ dbgaufs_fin();
20932+ sysfs_remove_group(&sysaufs_ket->kobj, sysaufs_attr_group);
20933+ kset_unregister(sysaufs_ket);
20934+}
20935+
20936+int __init sysaufs_init(void)
20937+{
20938+ int err;
20939+
20940+ do {
20941+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
20942+ } while (!sysaufs_si_mask);
20943+
4a4d8108 20944+ err = -EINVAL;
1facf9fc 20945+ sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
4a4d8108
AM
20946+ if (unlikely(!sysaufs_ket))
20947+ goto out;
1facf9fc 20948+ err = PTR_ERR(sysaufs_ket);
20949+ if (IS_ERR(sysaufs_ket))
20950+ goto out;
20951+ err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
20952+ if (unlikely(err)) {
20953+ kset_unregister(sysaufs_ket);
20954+ goto out;
20955+ }
20956+
20957+ err = dbgaufs_init();
20958+ if (unlikely(err))
20959+ sysaufs_fin();
20960+ out:
20961+ return err;
20962+}
4a4d8108
AM
20963diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/sysaufs.h linux-2.6.34/fs/aufs/sysaufs.h
20964--- linux-2.6.34.org/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
20965+++ linux-2.6.34/fs/aufs/sysaufs.h 2010-05-31 22:15:32.000000000 +0200
20966@@ -0,0 +1,105 @@
1facf9fc 20967+/*
4a4d8108 20968+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20969+ *
20970+ * This program, aufs is free software; you can redistribute it and/or modify
20971+ * it under the terms of the GNU General Public License as published by
20972+ * the Free Software Foundation; either version 2 of the License, or
20973+ * (at your option) any later version.
dece6358
AM
20974+ *
20975+ * This program is distributed in the hope that it will be useful,
20976+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20977+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20978+ * GNU General Public License for more details.
20979+ *
20980+ * You should have received a copy of the GNU General Public License
20981+ * along with this program; if not, write to the Free Software
20982+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20983+ */
20984+
20985+/*
20986+ * sysfs interface and mount lifetime management
20987+ */
20988+
20989+#ifndef __SYSAUFS_H__
20990+#define __SYSAUFS_H__
20991+
20992+#ifdef __KERNEL__
20993+
1facf9fc 20994+#include <linux/sysfs.h>
20995+#include <linux/aufs_type.h>
20996+#include "module.h"
20997+
dece6358
AM
20998+struct super_block;
20999+struct au_sbinfo;
21000+
1facf9fc 21001+struct sysaufs_si_attr {
21002+ struct attribute attr;
21003+ int (*show)(struct seq_file *seq, struct super_block *sb);
21004+};
21005+
21006+/* ---------------------------------------------------------------------- */
21007+
21008+/* sysaufs.c */
21009+extern unsigned long sysaufs_si_mask;
21010+extern struct kset *sysaufs_ket;
21011+extern struct attribute *sysaufs_si_attrs[];
21012+int sysaufs_si_init(struct au_sbinfo *sbinfo);
21013+int __init sysaufs_init(void);
21014+void sysaufs_fin(void);
21015+
21016+/* ---------------------------------------------------------------------- */
21017+
21018+/* some people doesn't like to show a pointer in kernel */
21019+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
21020+{
21021+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
21022+}
21023+
21024+#define SysaufsSiNamePrefix "si_"
21025+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
21026+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
21027+{
21028+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
21029+ sysaufs_si_id(sbinfo));
21030+}
21031+
21032+struct au_branch;
21033+#ifdef CONFIG_SYSFS
21034+/* sysfs.c */
21035+extern struct attribute_group *sysaufs_attr_group;
21036+
21037+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
21038+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
21039+ char *buf);
21040+
21041+void sysaufs_br_init(struct au_branch *br);
21042+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
21043+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
21044+
21045+#define sysaufs_brs_init() do {} while (0)
21046+
21047+#else
21048+#define sysaufs_attr_group NULL
21049+
4a4d8108 21050+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 21051+
21052+static inline
21053+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
21054+ char *buf)
21055+{
21056+ return 0;
21057+}
21058+
4a4d8108
AM
21059+AuStubVoid(sysaufs_br_init, struct au_branch *br)
21060+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
21061+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 21062+
21063+static inline void sysaufs_brs_init(void)
21064+{
21065+ sysaufs_brs = 0;
21066+}
21067+
21068+#endif /* CONFIG_SYSFS */
21069+
21070+#endif /* __KERNEL__ */
21071+#endif /* __SYSAUFS_H__ */
4a4d8108
AM
21072diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/sysfs.c linux-2.6.34/fs/aufs/sysfs.c
21073--- linux-2.6.34.org/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
21074+++ linux-2.6.34/fs/aufs/sysfs.c 2010-05-31 22:15:32.000000000 +0200
21075@@ -0,0 +1,251 @@
1facf9fc 21076+/*
4a4d8108 21077+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21078+ *
21079+ * This program, aufs is free software; you can redistribute it and/or modify
21080+ * it under the terms of the GNU General Public License as published by
21081+ * the Free Software Foundation; either version 2 of the License, or
21082+ * (at your option) any later version.
dece6358
AM
21083+ *
21084+ * This program is distributed in the hope that it will be useful,
21085+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21086+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21087+ * GNU General Public License for more details.
21088+ *
21089+ * You should have received a copy of the GNU General Public License
21090+ * along with this program; if not, write to the Free Software
21091+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21092+ */
21093+
21094+/*
21095+ * sysfs interface
21096+ */
21097+
21098+#include <linux/fs.h>
dece6358 21099+#include <linux/module.h>
1facf9fc 21100+#include <linux/seq_file.h>
21101+#include <linux/sysfs.h>
21102+#include "aufs.h"
21103+
4a4d8108
AM
21104+#ifdef CONFIG_AUFS_FS_MODULE
21105+/* this entry violates the "one line per file" policy of sysfs */
21106+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
21107+ char *buf)
21108+{
21109+ ssize_t err;
21110+ static char *conf =
21111+/* this file is generated at compiling */
21112+#include "conf.str"
21113+ ;
21114+
21115+ err = snprintf(buf, PAGE_SIZE, conf);
21116+ if (unlikely(err >= PAGE_SIZE))
21117+ err = -EFBIG;
21118+ return err;
21119+}
21120+
21121+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
21122+#endif
21123+
1facf9fc 21124+static struct attribute *au_attr[] = {
4a4d8108
AM
21125+#ifdef CONFIG_AUFS_FS_MODULE
21126+ &au_config_attr.attr,
21127+#endif
1facf9fc 21128+ NULL, /* need to NULL terminate the list of attributes */
21129+};
21130+
21131+static struct attribute_group sysaufs_attr_group_body = {
21132+ .attrs = au_attr
21133+};
21134+
21135+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
21136+
21137+/* ---------------------------------------------------------------------- */
21138+
21139+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
21140+{
21141+ int err;
21142+
dece6358
AM
21143+ SiMustAnyLock(sb);
21144+
1facf9fc 21145+ err = 0;
21146+ if (au_opt_test(au_mntflags(sb), XINO)) {
21147+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
21148+ seq_putc(seq, '\n');
21149+ }
21150+ return err;
21151+}
21152+
21153+/*
21154+ * the lifetime of branch is independent from the entry under sysfs.
21155+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
21156+ * unlinked.
21157+ */
21158+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
21159+ aufs_bindex_t bindex)
21160+{
21161+ struct path path;
21162+ struct dentry *root;
21163+ struct au_branch *br;
21164+
21165+ AuDbg("b%d\n", bindex);
21166+
21167+ root = sb->s_root;
21168+ di_read_lock_parent(root, !AuLock_IR);
21169+ br = au_sbr(sb, bindex);
21170+ path.mnt = br->br_mnt;
21171+ path.dentry = au_h_dptr(root, bindex);
21172+ au_seq_path(seq, &path);
21173+ di_read_unlock(root, !AuLock_IR);
21174+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
21175+ return 0;
21176+}
21177+
21178+/* ---------------------------------------------------------------------- */
21179+
21180+static struct seq_file *au_seq(char *p, ssize_t len)
21181+{
21182+ struct seq_file *seq;
21183+
21184+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
21185+ if (seq) {
21186+ /* mutex_init(&seq.lock); */
21187+ seq->buf = p;
21188+ seq->size = len;
21189+ return seq; /* success */
21190+ }
21191+
21192+ seq = ERR_PTR(-ENOMEM);
21193+ return seq;
21194+}
21195+
21196+#define SysaufsBr_PREFIX "br"
21197+
21198+/* todo: file size may exceed PAGE_SIZE */
21199+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 21200+ char *buf)
1facf9fc 21201+{
21202+ ssize_t err;
21203+ long l;
21204+ aufs_bindex_t bend;
21205+ struct au_sbinfo *sbinfo;
21206+ struct super_block *sb;
21207+ struct seq_file *seq;
21208+ char *name;
21209+ struct attribute **cattr;
21210+
21211+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
21212+ sb = sbinfo->si_sb;
1308ab2a 21213+
21214+ /*
21215+ * prevent a race condition between sysfs and aufs.
21216+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
21217+ * prohibits maintaining the sysfs entries.
21218+ * hew we acquire read lock after sysfs_get_active_two().
21219+ * on the other hand, the remount process may maintain the sysfs/aufs
21220+ * entries after acquiring write lock.
21221+ * it can cause a deadlock.
21222+ * simply we gave up processing read here.
21223+ */
21224+ err = -EBUSY;
21225+ if (unlikely(!si_noflush_read_trylock(sb)))
21226+ goto out;
1facf9fc 21227+
21228+ seq = au_seq(buf, PAGE_SIZE);
21229+ err = PTR_ERR(seq);
21230+ if (IS_ERR(seq))
1308ab2a 21231+ goto out_unlock;
1facf9fc 21232+
21233+ name = (void *)attr->name;
21234+ cattr = sysaufs_si_attrs;
21235+ while (*cattr) {
21236+ if (!strcmp(name, (*cattr)->name)) {
21237+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
21238+ ->show(seq, sb);
21239+ goto out_seq;
21240+ }
21241+ cattr++;
21242+ }
21243+
21244+ bend = au_sbend(sb);
21245+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
21246+ name += sizeof(SysaufsBr_PREFIX) - 1;
21247+ err = strict_strtol(name, 10, &l);
21248+ if (!err) {
21249+ if (l <= bend)
21250+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
21251+ else
21252+ err = -ENOENT;
21253+ }
21254+ goto out_seq;
21255+ }
21256+ BUG();
21257+
21258+ out_seq:
21259+ if (!err) {
21260+ err = seq->count;
21261+ /* sysfs limit */
21262+ if (unlikely(err == PAGE_SIZE))
21263+ err = -EFBIG;
21264+ }
21265+ kfree(seq);
1308ab2a 21266+ out_unlock:
1facf9fc 21267+ si_read_unlock(sb);
1308ab2a 21268+ out:
1facf9fc 21269+ return err;
21270+}
21271+
21272+/* ---------------------------------------------------------------------- */
21273+
21274+void sysaufs_br_init(struct au_branch *br)
21275+{
4a4d8108
AM
21276+ struct attribute *attr = &br->br_attr;
21277+
21278+ sysfs_attr_init(attr);
21279+ attr->name = br->br_name;
21280+ attr->mode = S_IRUGO;
21281+ attr->owner = THIS_MODULE;
1facf9fc 21282+}
21283+
21284+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
21285+{
21286+ struct au_branch *br;
21287+ struct kobject *kobj;
21288+ aufs_bindex_t bend;
21289+
21290+ dbgaufs_brs_del(sb, bindex);
21291+
21292+ if (!sysaufs_brs)
21293+ return;
21294+
21295+ kobj = &au_sbi(sb)->si_kobj;
21296+ bend = au_sbend(sb);
21297+ for (; bindex <= bend; bindex++) {
21298+ br = au_sbr(sb, bindex);
21299+ sysfs_remove_file(kobj, &br->br_attr);
21300+ }
21301+}
21302+
21303+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
21304+{
21305+ int err;
21306+ aufs_bindex_t bend;
21307+ struct kobject *kobj;
21308+ struct au_branch *br;
21309+
21310+ dbgaufs_brs_add(sb, bindex);
21311+
21312+ if (!sysaufs_brs)
21313+ return;
21314+
21315+ kobj = &au_sbi(sb)->si_kobj;
21316+ bend = au_sbend(sb);
21317+ for (; bindex <= bend; bindex++) {
21318+ br = au_sbr(sb, bindex);
21319+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
21320+ "%d", bindex);
21321+ err = sysfs_create_file(kobj, &br->br_attr);
21322+ if (unlikely(err))
4a4d8108
AM
21323+ pr_warning("failed %s under sysfs(%d)\n",
21324+ br->br_name, err);
1facf9fc 21325+ }
21326+}
4a4d8108
AM
21327diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/sysrq.c linux-2.6.34/fs/aufs/sysrq.c
21328--- linux-2.6.34.org/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
21329+++ linux-2.6.34/fs/aufs/sysrq.c 2010-05-31 22:15:32.000000000 +0200
21330@@ -0,0 +1,119 @@
1facf9fc 21331+/*
4a4d8108 21332+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21333+ *
21334+ * This program, aufs is free software; you can redistribute it and/or modify
21335+ * it under the terms of the GNU General Public License as published by
21336+ * the Free Software Foundation; either version 2 of the License, or
21337+ * (at your option) any later version.
dece6358
AM
21338+ *
21339+ * This program is distributed in the hope that it will be useful,
21340+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21341+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21342+ * GNU General Public License for more details.
21343+ *
21344+ * You should have received a copy of the GNU General Public License
21345+ * along with this program; if not, write to the Free Software
21346+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21347+ */
21348+
21349+/*
21350+ * magic sysrq hanlder
21351+ */
21352+
21353+#include <linux/fs.h>
21354+#include <linux/module.h>
21355+#include <linux/moduleparam.h>
21356+/* #include <linux/sysrq.h> */
21357+#include "aufs.h"
21358+
21359+/* ---------------------------------------------------------------------- */
21360+
21361+static void sysrq_sb(struct super_block *sb)
21362+{
21363+ char *plevel;
21364+ struct au_sbinfo *sbinfo;
21365+ struct file *file;
21366+
21367+ plevel = au_plevel;
21368+ au_plevel = KERN_WARNING;
21369+ au_debug(1);
21370+
21371+ sbinfo = au_sbi(sb);
4a4d8108
AM
21372+ /* since we define pr_fmt, call printk directly */
21373+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
21374+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 21375+ au_dpri_sb(sb);
4a4d8108 21376+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 21377+ au_dpri_dentry(sb->s_root);
4a4d8108 21378+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 21379+ au_dpri_inode(sb->s_root->d_inode);
21380+#if 0
21381+ struct inode *i;
4a4d8108 21382+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
1facf9fc 21383+ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
21384+ if (list_empty(&i->i_dentry))
21385+ au_dpri_inode(i);
21386+#endif
4a4d8108
AM
21387+ printk(KERN_WARNING AUFS_NAME ": files\n");
21388+ list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
21389+ umode_t mode;
21390+ mode = file->f_dentry->d_inode->i_mode;
21391+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 21392+ au_dpri_file(file);
4a4d8108 21393+ }
1facf9fc 21394+
21395+ au_plevel = plevel;
21396+ au_debug(0);
21397+}
21398+
21399+/* ---------------------------------------------------------------------- */
21400+
21401+/* module parameter */
21402+static char *aufs_sysrq_key = "a";
21403+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
21404+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
21405+
21406+static void au_sysrq(int key __maybe_unused,
21407+ struct tty_struct *tty __maybe_unused)
21408+{
21409+ struct kobject *kobj;
21410+ struct au_sbinfo *sbinfo;
21411+
21412+ /* spin_lock(&sysaufs_ket->list_lock); */
21413+ list_for_each_entry(kobj, &sysaufs_ket->list, entry) {
21414+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
21415+ sysrq_sb(sbinfo->si_sb);
21416+ }
21417+ /* spin_unlock(&sysaufs_ket->list_lock); */
21418+}
21419+
21420+static struct sysrq_key_op au_sysrq_op = {
21421+ .handler = au_sysrq,
21422+ .help_msg = "Aufs",
21423+ .action_msg = "Aufs",
21424+ .enable_mask = SYSRQ_ENABLE_DUMP
21425+};
21426+
21427+/* ---------------------------------------------------------------------- */
21428+
21429+int __init au_sysrq_init(void)
21430+{
21431+ int err;
21432+ char key;
21433+
21434+ err = -1;
21435+ key = *aufs_sysrq_key;
21436+ if ('a' <= key && key <= 'z')
21437+ err = register_sysrq_key(key, &au_sysrq_op);
21438+ if (unlikely(err))
4a4d8108 21439+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 21440+ return err;
21441+}
21442+
21443+void au_sysrq_fin(void)
21444+{
21445+ int err;
21446+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
21447+ if (unlikely(err))
4a4d8108 21448+ pr_err("err %d (ignored)\n", err);
1facf9fc 21449+}
4a4d8108
AM
21450diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/vdir.c linux-2.6.34/fs/aufs/vdir.c
21451--- linux-2.6.34.org/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
21452+++ linux-2.6.34/fs/aufs/vdir.c 2010-05-31 22:15:32.000000000 +0200
21453@@ -0,0 +1,884 @@
1facf9fc 21454+/*
4a4d8108 21455+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21456+ *
21457+ * This program, aufs is free software; you can redistribute it and/or modify
21458+ * it under the terms of the GNU General Public License as published by
21459+ * the Free Software Foundation; either version 2 of the License, or
21460+ * (at your option) any later version.
dece6358
AM
21461+ *
21462+ * This program is distributed in the hope that it will be useful,
21463+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21464+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21465+ * GNU General Public License for more details.
21466+ *
21467+ * You should have received a copy of the GNU General Public License
21468+ * along with this program; if not, write to the Free Software
21469+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21470+ */
21471+
21472+/*
21473+ * virtual or vertical directory
21474+ */
21475+
dece6358 21476+#include <linux/hash.h>
1facf9fc 21477+#include "aufs.h"
21478+
dece6358 21479+static unsigned int calc_size(int nlen)
1facf9fc 21480+{
dece6358 21481+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 21482+}
21483+
21484+static int set_deblk_end(union au_vdir_deblk_p *p,
21485+ union au_vdir_deblk_p *deblk_end)
21486+{
21487+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
21488+ p->de->de_str.len = 0;
21489+ /* smp_mb(); */
21490+ return 0;
21491+ }
21492+ return -1; /* error */
21493+}
21494+
21495+/* returns true or false */
21496+static int is_deblk_end(union au_vdir_deblk_p *p,
21497+ union au_vdir_deblk_p *deblk_end)
21498+{
21499+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
21500+ return !p->de->de_str.len;
21501+ return 1;
21502+}
21503+
21504+static unsigned char *last_deblk(struct au_vdir *vdir)
21505+{
21506+ return vdir->vd_deblk[vdir->vd_nblk - 1];
21507+}
21508+
21509+/* ---------------------------------------------------------------------- */
21510+
1308ab2a 21511+/* estimate the apropriate size for name hash table */
21512+unsigned int au_rdhash_est(loff_t sz)
21513+{
21514+ unsigned int n;
21515+
21516+ n = UINT_MAX;
21517+ sz >>= 10;
21518+ if (sz < n)
21519+ n = sz;
21520+ if (sz < AUFS_RDHASH_DEF)
21521+ n = AUFS_RDHASH_DEF;
4a4d8108 21522+ /* pr_info("n %u\n", n); */
1308ab2a 21523+ return n;
21524+}
21525+
1facf9fc 21526+/*
21527+ * the allocated memory has to be freed by
dece6358 21528+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 21529+ */
dece6358 21530+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 21531+{
1facf9fc 21532+ struct hlist_head *head;
dece6358 21533+ unsigned int u;
1facf9fc 21534+
dece6358
AM
21535+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
21536+ if (head) {
21537+ nhash->nh_num = num_hash;
21538+ nhash->nh_head = head;
21539+ for (u = 0; u < num_hash; u++)
1facf9fc 21540+ INIT_HLIST_HEAD(head++);
dece6358 21541+ return 0; /* success */
1facf9fc 21542+ }
1facf9fc 21543+
dece6358 21544+ return -ENOMEM;
1facf9fc 21545+}
21546+
dece6358
AM
21547+static void nhash_count(struct hlist_head *head)
21548+{
21549+#if 0
21550+ unsigned long n;
21551+ struct hlist_node *pos;
21552+
21553+ n = 0;
21554+ hlist_for_each(pos, head)
21555+ n++;
4a4d8108 21556+ pr_info("%lu\n", n);
dece6358
AM
21557+#endif
21558+}
21559+
21560+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 21561+{
1facf9fc 21562+ struct au_vdir_wh *tpos;
21563+ struct hlist_node *pos, *node;
21564+
dece6358
AM
21565+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
21566+ /* hlist_del(pos); */
21567+ kfree(tpos);
1facf9fc 21568+ }
21569+}
21570+
dece6358 21571+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 21572+{
dece6358
AM
21573+ struct au_vdir_dehstr *tpos;
21574+ struct hlist_node *pos, *node;
1facf9fc 21575+
dece6358
AM
21576+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
21577+ /* hlist_del(pos); */
4a4d8108 21578+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 21579+ }
1facf9fc 21580+}
21581+
dece6358
AM
21582+static void au_nhash_do_free(struct au_nhash *nhash,
21583+ void (*free)(struct hlist_head *head))
1facf9fc 21584+{
1308ab2a 21585+ unsigned int n;
1facf9fc 21586+ struct hlist_head *head;
1facf9fc 21587+
dece6358 21588+ n = nhash->nh_num;
1308ab2a 21589+ if (!n)
21590+ return;
21591+
dece6358 21592+ head = nhash->nh_head;
1308ab2a 21593+ while (n-- > 0) {
dece6358
AM
21594+ nhash_count(head);
21595+ free(head++);
1facf9fc 21596+ }
dece6358 21597+ kfree(nhash->nh_head);
1facf9fc 21598+}
21599+
dece6358 21600+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 21601+{
dece6358
AM
21602+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
21603+}
1facf9fc 21604+
dece6358
AM
21605+static void au_nhash_de_free(struct au_nhash *delist)
21606+{
21607+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 21608+}
21609+
21610+/* ---------------------------------------------------------------------- */
21611+
21612+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
21613+ int limit)
21614+{
21615+ int num;
21616+ unsigned int u, n;
21617+ struct hlist_head *head;
21618+ struct au_vdir_wh *tpos;
21619+ struct hlist_node *pos;
21620+
21621+ num = 0;
21622+ n = whlist->nh_num;
21623+ head = whlist->nh_head;
1308ab2a 21624+ for (u = 0; u < n; u++, head++)
1facf9fc 21625+ hlist_for_each_entry(tpos, pos, head, wh_hash)
21626+ if (tpos->wh_bindex == btgt && ++num > limit)
21627+ return 1;
1facf9fc 21628+ return 0;
21629+}
21630+
21631+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 21632+ unsigned char *name,
1facf9fc 21633+ unsigned int len)
21634+{
dece6358
AM
21635+ unsigned int v;
21636+ /* const unsigned int magic_bit = 12; */
21637+
1308ab2a 21638+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
21639+
dece6358
AM
21640+ v = 0;
21641+ while (len--)
21642+ v += *name++;
21643+ /* v = hash_long(v, magic_bit); */
21644+ v %= nhash->nh_num;
21645+ return nhash->nh_head + v;
21646+}
21647+
21648+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
21649+ int nlen)
21650+{
21651+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 21652+}
21653+
21654+/* returns found or not */
dece6358 21655+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 21656+{
21657+ struct hlist_head *head;
21658+ struct au_vdir_wh *tpos;
21659+ struct hlist_node *pos;
21660+ struct au_vdir_destr *str;
21661+
dece6358 21662+ head = au_name_hash(whlist, name, nlen);
1facf9fc 21663+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
21664+ str = &tpos->wh_str;
21665+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
21666+ if (au_nhash_test_name(str, name, nlen))
21667+ return 1;
21668+ }
21669+ return 0;
21670+}
21671+
21672+/* returns found(true) or not */
21673+static int test_known(struct au_nhash *delist, char *name, int nlen)
21674+{
21675+ struct hlist_head *head;
21676+ struct au_vdir_dehstr *tpos;
21677+ struct hlist_node *pos;
21678+ struct au_vdir_destr *str;
21679+
21680+ head = au_name_hash(delist, name, nlen);
21681+ hlist_for_each_entry(tpos, pos, head, hash) {
21682+ str = tpos->str;
21683+ AuDbg("%.*s\n", str->len, str->name);
21684+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 21685+ return 1;
21686+ }
21687+ return 0;
21688+}
21689+
dece6358
AM
21690+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
21691+ unsigned char d_type)
21692+{
21693+#ifdef CONFIG_AUFS_SHWH
21694+ wh->wh_ino = ino;
21695+ wh->wh_type = d_type;
21696+#endif
21697+}
21698+
21699+/* ---------------------------------------------------------------------- */
21700+
21701+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
21702+ unsigned int d_type, aufs_bindex_t bindex,
21703+ unsigned char shwh)
1facf9fc 21704+{
21705+ int err;
21706+ struct au_vdir_destr *str;
21707+ struct au_vdir_wh *wh;
21708+
dece6358 21709+ AuDbg("%.*s\n", nlen, name);
1308ab2a 21710+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
21711+
1facf9fc 21712+ err = -ENOMEM;
dece6358 21713+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 21714+ if (unlikely(!wh))
21715+ goto out;
21716+
21717+ err = 0;
21718+ wh->wh_bindex = bindex;
dece6358
AM
21719+ if (shwh)
21720+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 21721+ str = &wh->wh_str;
dece6358
AM
21722+ str->len = nlen;
21723+ memcpy(str->name, name, nlen);
21724+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 21725+ /* smp_mb(); */
21726+
21727+ out:
21728+ return err;
21729+}
21730+
1facf9fc 21731+static int append_deblk(struct au_vdir *vdir)
21732+{
21733+ int err;
dece6358 21734+ unsigned long ul;
1facf9fc 21735+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
21736+ union au_vdir_deblk_p p, deblk_end;
21737+ unsigned char **o;
21738+
21739+ err = -ENOMEM;
dece6358
AM
21740+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
21741+ GFP_NOFS);
1facf9fc 21742+ if (unlikely(!o))
21743+ goto out;
21744+
21745+ vdir->vd_deblk = o;
21746+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
21747+ if (p.deblk) {
21748+ ul = vdir->vd_nblk++;
21749+ vdir->vd_deblk[ul] = p.deblk;
21750+ vdir->vd_last.ul = ul;
21751+ vdir->vd_last.p.deblk = p.deblk;
21752+ deblk_end.deblk = p.deblk + deblk_sz;
21753+ err = set_deblk_end(&p, &deblk_end);
21754+ }
21755+
21756+ out:
21757+ return err;
21758+}
21759+
dece6358
AM
21760+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
21761+ unsigned int d_type, struct au_nhash *delist)
21762+{
21763+ int err;
21764+ unsigned int sz;
21765+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
21766+ union au_vdir_deblk_p p, *room, deblk_end;
21767+ struct au_vdir_dehstr *dehstr;
21768+
21769+ p.deblk = last_deblk(vdir);
21770+ deblk_end.deblk = p.deblk + deblk_sz;
21771+ room = &vdir->vd_last.p;
21772+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
21773+ || !is_deblk_end(room, &deblk_end));
21774+
21775+ sz = calc_size(nlen);
21776+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
21777+ err = append_deblk(vdir);
21778+ if (unlikely(err))
21779+ goto out;
21780+
21781+ p.deblk = last_deblk(vdir);
21782+ deblk_end.deblk = p.deblk + deblk_sz;
21783+ /* smp_mb(); */
21784+ AuDebugOn(room->deblk != p.deblk);
21785+ }
21786+
21787+ err = -ENOMEM;
4a4d8108 21788+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
21789+ if (unlikely(!dehstr))
21790+ goto out;
21791+
21792+ dehstr->str = &room->de->de_str;
21793+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
21794+ room->de->de_ino = ino;
21795+ room->de->de_type = d_type;
21796+ room->de->de_str.len = nlen;
21797+ memcpy(room->de->de_str.name, name, nlen);
21798+
21799+ err = 0;
21800+ room->deblk += sz;
21801+ if (unlikely(set_deblk_end(room, &deblk_end)))
21802+ err = append_deblk(vdir);
21803+ /* smp_mb(); */
21804+
21805+ out:
21806+ return err;
21807+}
21808+
21809+/* ---------------------------------------------------------------------- */
21810+
21811+void au_vdir_free(struct au_vdir *vdir)
21812+{
21813+ unsigned char **deblk;
21814+
21815+ deblk = vdir->vd_deblk;
21816+ while (vdir->vd_nblk--)
21817+ kfree(*deblk++);
21818+ kfree(vdir->vd_deblk);
21819+ au_cache_free_vdir(vdir);
21820+}
21821+
1308ab2a 21822+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 21823+{
21824+ struct au_vdir *vdir;
1308ab2a 21825+ struct super_block *sb;
1facf9fc 21826+ int err;
21827+
1308ab2a 21828+ sb = file->f_dentry->d_sb;
dece6358
AM
21829+ SiMustAnyLock(sb);
21830+
1facf9fc 21831+ err = -ENOMEM;
21832+ vdir = au_cache_alloc_vdir();
21833+ if (unlikely(!vdir))
21834+ goto out;
21835+
21836+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
21837+ if (unlikely(!vdir->vd_deblk))
21838+ goto out_free;
21839+
21840+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 21841+ if (!vdir->vd_deblk_sz) {
21842+ /* estimate the apropriate size for deblk */
21843+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 21844+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 21845+ }
1facf9fc 21846+ vdir->vd_nblk = 0;
21847+ vdir->vd_version = 0;
21848+ vdir->vd_jiffy = 0;
21849+ err = append_deblk(vdir);
21850+ if (!err)
21851+ return vdir; /* success */
21852+
21853+ kfree(vdir->vd_deblk);
21854+
21855+ out_free:
21856+ au_cache_free_vdir(vdir);
21857+ out:
21858+ vdir = ERR_PTR(err);
21859+ return vdir;
21860+}
21861+
21862+static int reinit_vdir(struct au_vdir *vdir)
21863+{
21864+ int err;
21865+ union au_vdir_deblk_p p, deblk_end;
21866+
21867+ while (vdir->vd_nblk > 1) {
21868+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
21869+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
21870+ vdir->vd_nblk--;
21871+ }
21872+ p.deblk = vdir->vd_deblk[0];
21873+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
21874+ err = set_deblk_end(&p, &deblk_end);
21875+ /* keep vd_dblk_sz */
21876+ vdir->vd_last.ul = 0;
21877+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
21878+ vdir->vd_version = 0;
21879+ vdir->vd_jiffy = 0;
21880+ /* smp_mb(); */
21881+ return err;
21882+}
21883+
21884+/* ---------------------------------------------------------------------- */
21885+
1facf9fc 21886+#define AuFillVdir_CALLED 1
21887+#define AuFillVdir_WHABLE (1 << 1)
dece6358 21888+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 21889+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
21890+#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
21891+#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
21892+
dece6358
AM
21893+#ifndef CONFIG_AUFS_SHWH
21894+#undef AuFillVdir_SHWH
21895+#define AuFillVdir_SHWH 0
21896+#endif
21897+
1facf9fc 21898+struct fillvdir_arg {
21899+ struct file *file;
21900+ struct au_vdir *vdir;
dece6358
AM
21901+ struct au_nhash delist;
21902+ struct au_nhash whlist;
1facf9fc 21903+ aufs_bindex_t bindex;
21904+ unsigned int flags;
21905+ int err;
21906+};
21907+
dece6358 21908+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 21909+ loff_t offset __maybe_unused, u64 h_ino,
21910+ unsigned int d_type)
21911+{
21912+ struct fillvdir_arg *arg = __arg;
21913+ char *name = (void *)__name;
21914+ struct super_block *sb;
1facf9fc 21915+ ino_t ino;
dece6358 21916+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 21917+
1facf9fc 21918+ arg->err = 0;
dece6358 21919+ sb = arg->file->f_dentry->d_sb;
1facf9fc 21920+ au_fset_fillvdir(arg->flags, CALLED);
21921+ /* smp_mb(); */
dece6358 21922+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 21923+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
21924+ if (test_known(&arg->delist, name, nlen)
21925+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
21926+ goto out; /* already exists or whiteouted */
1facf9fc 21927+
21928+ sb = arg->file->f_dentry->d_sb;
dece6358 21929+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
21930+ if (!arg->err) {
21931+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
21932+ d_type = DT_UNKNOWN;
dece6358
AM
21933+ arg->err = append_de(arg->vdir, name, nlen, ino,
21934+ d_type, &arg->delist);
4a4d8108 21935+ }
1facf9fc 21936+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
21937+ name += AUFS_WH_PFX_LEN;
dece6358
AM
21938+ nlen -= AUFS_WH_PFX_LEN;
21939+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
21940+ goto out; /* already whiteouted */
1facf9fc 21941+
dece6358
AM
21942+ if (shwh)
21943+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
21944+ &ino);
4a4d8108
AM
21945+ if (!arg->err) {
21946+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
21947+ d_type = DT_UNKNOWN;
1facf9fc 21948+ arg->err = au_nhash_append_wh
dece6358
AM
21949+ (&arg->whlist, name, nlen, ino, d_type,
21950+ arg->bindex, shwh);
4a4d8108 21951+ }
1facf9fc 21952+ }
21953+
21954+ out:
21955+ if (!arg->err)
21956+ arg->vdir->vd_jiffy = jiffies;
21957+ /* smp_mb(); */
21958+ AuTraceErr(arg->err);
21959+ return arg->err;
21960+}
21961+
dece6358
AM
21962+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
21963+ struct au_nhash *whlist, struct au_nhash *delist)
21964+{
21965+#ifdef CONFIG_AUFS_SHWH
21966+ int err;
21967+ unsigned int nh, u;
21968+ struct hlist_head *head;
21969+ struct au_vdir_wh *tpos;
21970+ struct hlist_node *pos, *n;
21971+ char *p, *o;
21972+ struct au_vdir_destr *destr;
21973+
21974+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
21975+
21976+ err = -ENOMEM;
4a4d8108 21977+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
21978+ if (unlikely(!p))
21979+ goto out;
21980+
21981+ err = 0;
21982+ nh = whlist->nh_num;
21983+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
21984+ p += AUFS_WH_PFX_LEN;
21985+ for (u = 0; u < nh; u++) {
21986+ head = whlist->nh_head + u;
21987+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
21988+ destr = &tpos->wh_str;
21989+ memcpy(p, destr->name, destr->len);
21990+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
21991+ tpos->wh_ino, tpos->wh_type, delist);
21992+ if (unlikely(err))
21993+ break;
21994+ }
21995+ }
21996+
21997+ __putname(o);
21998+
21999+ out:
22000+ AuTraceErr(err);
22001+ return err;
22002+#else
22003+ return 0;
22004+#endif
22005+}
22006+
1facf9fc 22007+static int au_do_read_vdir(struct fillvdir_arg *arg)
22008+{
22009+ int err;
dece6358 22010+ unsigned int rdhash;
1facf9fc 22011+ loff_t offset;
dece6358
AM
22012+ aufs_bindex_t bend, bindex, bstart;
22013+ unsigned char shwh;
1facf9fc 22014+ struct file *hf, *file;
22015+ struct super_block *sb;
22016+
1facf9fc 22017+ file = arg->file;
22018+ sb = file->f_dentry->d_sb;
dece6358
AM
22019+ SiMustAnyLock(sb);
22020+
22021+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 22022+ if (!rdhash)
22023+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
22024+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
22025+ if (unlikely(err))
1facf9fc 22026+ goto out;
dece6358
AM
22027+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
22028+ if (unlikely(err))
1facf9fc 22029+ goto out_delist;
22030+
22031+ err = 0;
22032+ arg->flags = 0;
dece6358
AM
22033+ shwh = 0;
22034+ if (au_opt_test(au_mntflags(sb), SHWH)) {
22035+ shwh = 1;
22036+ au_fset_fillvdir(arg->flags, SHWH);
22037+ }
22038+ bstart = au_fbstart(file);
4a4d8108 22039+ bend = au_fbend_dir(file);
dece6358 22040+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 22041+ hf = au_hf_dir(file, bindex);
1facf9fc 22042+ if (!hf)
22043+ continue;
22044+
22045+ offset = vfsub_llseek(hf, 0, SEEK_SET);
22046+ err = offset;
22047+ if (unlikely(offset))
22048+ break;
22049+
22050+ arg->bindex = bindex;
22051+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
22052+ if (shwh
22053+ || (bindex != bend
22054+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 22055+ au_fset_fillvdir(arg->flags, WHABLE);
22056+ do {
22057+ arg->err = 0;
22058+ au_fclr_fillvdir(arg->flags, CALLED);
22059+ /* smp_mb(); */
22060+ err = vfsub_readdir(hf, fillvdir, arg);
22061+ if (err >= 0)
22062+ err = arg->err;
22063+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
22064+ }
dece6358
AM
22065+
22066+ if (!err && shwh)
22067+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
22068+
22069+ au_nhash_wh_free(&arg->whlist);
1facf9fc 22070+
22071+ out_delist:
dece6358 22072+ au_nhash_de_free(&arg->delist);
1facf9fc 22073+ out:
22074+ return err;
22075+}
22076+
22077+static int read_vdir(struct file *file, int may_read)
22078+{
22079+ int err;
22080+ unsigned long expire;
22081+ unsigned char do_read;
22082+ struct fillvdir_arg arg;
22083+ struct inode *inode;
22084+ struct au_vdir *vdir, *allocated;
22085+
22086+ err = 0;
22087+ inode = file->f_dentry->d_inode;
22088+ IMustLock(inode);
dece6358
AM
22089+ SiMustAnyLock(inode->i_sb);
22090+
1facf9fc 22091+ allocated = NULL;
22092+ do_read = 0;
22093+ expire = au_sbi(inode->i_sb)->si_rdcache;
22094+ vdir = au_ivdir(inode);
22095+ if (!vdir) {
22096+ do_read = 1;
1308ab2a 22097+ vdir = alloc_vdir(file);
1facf9fc 22098+ err = PTR_ERR(vdir);
22099+ if (IS_ERR(vdir))
22100+ goto out;
22101+ err = 0;
22102+ allocated = vdir;
22103+ } else if (may_read
22104+ && (inode->i_version != vdir->vd_version
22105+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
22106+ do_read = 1;
22107+ err = reinit_vdir(vdir);
22108+ if (unlikely(err))
22109+ goto out;
22110+ }
22111+
22112+ if (!do_read)
22113+ return 0; /* success */
22114+
22115+ arg.file = file;
22116+ arg.vdir = vdir;
22117+ err = au_do_read_vdir(&arg);
22118+ if (!err) {
22119+ /* file->f_pos = 0; */
22120+ vdir->vd_version = inode->i_version;
22121+ vdir->vd_last.ul = 0;
22122+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
22123+ if (allocated)
22124+ au_set_ivdir(inode, allocated);
22125+ } else if (allocated)
22126+ au_vdir_free(allocated);
22127+
22128+ out:
22129+ return err;
22130+}
22131+
22132+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
22133+{
22134+ int err, rerr;
22135+ unsigned long ul, n;
22136+ const unsigned int deblk_sz = src->vd_deblk_sz;
22137+
22138+ AuDebugOn(tgt->vd_nblk != 1);
22139+
22140+ err = -ENOMEM;
22141+ if (tgt->vd_nblk < src->vd_nblk) {
22142+ unsigned char **p;
22143+
dece6358
AM
22144+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
22145+ GFP_NOFS);
1facf9fc 22146+ if (unlikely(!p))
22147+ goto out;
22148+ tgt->vd_deblk = p;
22149+ }
22150+
1308ab2a 22151+ if (tgt->vd_deblk_sz != deblk_sz) {
22152+ unsigned char *p;
22153+
22154+ tgt->vd_deblk_sz = deblk_sz;
22155+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
22156+ if (unlikely(!p))
22157+ goto out;
22158+ tgt->vd_deblk[0] = p;
22159+ }
1facf9fc 22160+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 22161+ tgt->vd_version = src->vd_version;
22162+ tgt->vd_jiffy = src->vd_jiffy;
22163+
22164+ n = src->vd_nblk;
22165+ for (ul = 1; ul < n; ul++) {
dece6358
AM
22166+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
22167+ GFP_NOFS);
22168+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 22169+ goto out;
1308ab2a 22170+ tgt->vd_nblk++;
1facf9fc 22171+ }
1308ab2a 22172+ tgt->vd_nblk = n;
22173+ tgt->vd_last.ul = tgt->vd_last.ul;
22174+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
22175+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
22176+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 22177+ /* smp_mb(); */
22178+ return 0; /* success */
22179+
22180+ out:
22181+ rerr = reinit_vdir(tgt);
22182+ BUG_ON(rerr);
22183+ return err;
22184+}
22185+
22186+int au_vdir_init(struct file *file)
22187+{
22188+ int err;
22189+ struct inode *inode;
22190+ struct au_vdir *vdir_cache, *allocated;
22191+
22192+ err = read_vdir(file, !file->f_pos);
22193+ if (unlikely(err))
22194+ goto out;
22195+
22196+ allocated = NULL;
22197+ vdir_cache = au_fvdir_cache(file);
22198+ if (!vdir_cache) {
1308ab2a 22199+ vdir_cache = alloc_vdir(file);
1facf9fc 22200+ err = PTR_ERR(vdir_cache);
22201+ if (IS_ERR(vdir_cache))
22202+ goto out;
22203+ allocated = vdir_cache;
22204+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
22205+ err = reinit_vdir(vdir_cache);
22206+ if (unlikely(err))
22207+ goto out;
22208+ } else
22209+ return 0; /* success */
22210+
22211+ inode = file->f_dentry->d_inode;
22212+ err = copy_vdir(vdir_cache, au_ivdir(inode));
22213+ if (!err) {
22214+ file->f_version = inode->i_version;
22215+ if (allocated)
22216+ au_set_fvdir_cache(file, allocated);
22217+ } else if (allocated)
22218+ au_vdir_free(allocated);
22219+
22220+ out:
22221+ return err;
22222+}
22223+
22224+static loff_t calc_offset(struct au_vdir *vdir)
22225+{
22226+ loff_t offset;
22227+ union au_vdir_deblk_p p;
22228+
22229+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
22230+ offset = vdir->vd_last.p.deblk - p.deblk;
22231+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
22232+ return offset;
22233+}
22234+
22235+/* returns true or false */
22236+static int seek_vdir(struct file *file)
22237+{
22238+ int valid;
22239+ unsigned int deblk_sz;
22240+ unsigned long ul, n;
22241+ loff_t offset;
22242+ union au_vdir_deblk_p p, deblk_end;
22243+ struct au_vdir *vdir_cache;
22244+
22245+ valid = 1;
22246+ vdir_cache = au_fvdir_cache(file);
22247+ offset = calc_offset(vdir_cache);
22248+ AuDbg("offset %lld\n", offset);
22249+ if (file->f_pos == offset)
22250+ goto out;
22251+
22252+ vdir_cache->vd_last.ul = 0;
22253+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
22254+ if (!file->f_pos)
22255+ goto out;
22256+
22257+ valid = 0;
22258+ deblk_sz = vdir_cache->vd_deblk_sz;
22259+ ul = div64_u64(file->f_pos, deblk_sz);
22260+ AuDbg("ul %lu\n", ul);
22261+ if (ul >= vdir_cache->vd_nblk)
22262+ goto out;
22263+
22264+ n = vdir_cache->vd_nblk;
22265+ for (; ul < n; ul++) {
22266+ p.deblk = vdir_cache->vd_deblk[ul];
22267+ deblk_end.deblk = p.deblk + deblk_sz;
22268+ offset = ul;
22269+ offset *= deblk_sz;
22270+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
22271+ unsigned int l;
22272+
22273+ l = calc_size(p.de->de_str.len);
22274+ offset += l;
22275+ p.deblk += l;
22276+ }
22277+ if (!is_deblk_end(&p, &deblk_end)) {
22278+ valid = 1;
22279+ vdir_cache->vd_last.ul = ul;
22280+ vdir_cache->vd_last.p = p;
22281+ break;
22282+ }
22283+ }
22284+
22285+ out:
22286+ /* smp_mb(); */
22287+ AuTraceErr(!valid);
22288+ return valid;
22289+}
22290+
22291+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
22292+{
22293+ int err;
22294+ unsigned int l, deblk_sz;
22295+ union au_vdir_deblk_p deblk_end;
22296+ struct au_vdir *vdir_cache;
22297+ struct au_vdir_de *de;
22298+
22299+ vdir_cache = au_fvdir_cache(file);
22300+ if (!seek_vdir(file))
22301+ return 0;
22302+
22303+ deblk_sz = vdir_cache->vd_deblk_sz;
22304+ while (1) {
22305+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
22306+ deblk_end.deblk += deblk_sz;
22307+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
22308+ de = vdir_cache->vd_last.p.de;
22309+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
22310+ de->de_str.len, de->de_str.name, file->f_pos,
22311+ (unsigned long)de->de_ino, de->de_type);
22312+ err = filldir(dirent, de->de_str.name, de->de_str.len,
22313+ file->f_pos, de->de_ino, de->de_type);
22314+ if (unlikely(err)) {
22315+ AuTraceErr(err);
22316+ /* todo: ignore the error caused by udba? */
22317+ /* return err; */
22318+ return 0;
22319+ }
22320+
22321+ l = calc_size(de->de_str.len);
22322+ vdir_cache->vd_last.p.deblk += l;
22323+ file->f_pos += l;
22324+ }
22325+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
22326+ vdir_cache->vd_last.ul++;
22327+ vdir_cache->vd_last.p.deblk
22328+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
22329+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
22330+ continue;
22331+ }
22332+ break;
22333+ }
22334+
22335+ /* smp_mb(); */
22336+ return 0;
22337+}
4a4d8108
AM
22338diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/vfsub.c linux-2.6.34/fs/aufs/vfsub.c
22339--- linux-2.6.34.org/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
22340+++ linux-2.6.34/fs/aufs/vfsub.c 2010-05-31 22:15:32.000000000 +0200
22341@@ -0,0 +1,805 @@
1facf9fc 22342+/*
4a4d8108 22343+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22344+ *
22345+ * This program, aufs is free software; you can redistribute it and/or modify
22346+ * it under the terms of the GNU General Public License as published by
22347+ * the Free Software Foundation; either version 2 of the License, or
22348+ * (at your option) any later version.
dece6358
AM
22349+ *
22350+ * This program is distributed in the hope that it will be useful,
22351+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22352+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22353+ * GNU General Public License for more details.
22354+ *
22355+ * You should have received a copy of the GNU General Public License
22356+ * along with this program; if not, write to the Free Software
22357+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22358+ */
22359+
22360+/*
22361+ * sub-routines for VFS
22362+ */
22363+
4a4d8108 22364+#include <linux/file.h>
1308ab2a 22365+#include <linux/ima.h>
dece6358
AM
22366+#include <linux/namei.h>
22367+#include <linux/security.h>
22368+#include <linux/splice.h>
1facf9fc 22369+#include <linux/uaccess.h>
22370+#include "aufs.h"
22371+
22372+int vfsub_update_h_iattr(struct path *h_path, int *did)
22373+{
22374+ int err;
22375+ struct kstat st;
22376+ struct super_block *h_sb;
22377+
22378+ /* for remote fs, leave work for its getattr or d_revalidate */
22379+ /* for bad i_attr fs, handle them in aufs_getattr() */
22380+ /* still some fs may acquire i_mutex. we need to skip them */
22381+ err = 0;
22382+ if (!did)
22383+ did = &err;
22384+ h_sb = h_path->dentry->d_sb;
22385+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
22386+ if (*did)
22387+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
22388+
22389+ return err;
22390+}
22391+
22392+/* ---------------------------------------------------------------------- */
22393+
4a4d8108
AM
22394+static int au_conv_oflags(int flags)
22395+{
22396+ int mask = 0;
22397+
22398+#ifdef CONFIG_IMA
22399+ fmode_t fmode;
22400+
22401+ /* mask = MAY_OPEN; */
22402+ fmode = OPEN_FMODE(flags);
22403+ if (fmode & FMODE_READ)
22404+ mask |= MAY_READ;
22405+ if ((fmode & FMODE_WRITE)
22406+ || (flags & O_TRUNC))
22407+ mask |= MAY_WRITE;
22408+ /*
22409+ * if (flags & O_APPEND)
22410+ * mask |= MAY_APPEND;
22411+ */
22412+ if (flags & vfsub_fmode_to_uint(FMODE_EXEC))
22413+ mask |= MAY_EXEC;
22414+
22415+ AuDbg("flags 0x%x, mask 0x%x\n", flags, mask);
22416+#endif
22417+
22418+ return mask;
22419+}
22420+
22421+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 22422+{
22423+ struct file *file;
4a4d8108 22424+ int err;
1308ab2a 22425+
4a4d8108
AM
22426+ path_get(path);
22427+ file = dentry_open(path->dentry, path->mnt, flags, current_cred());
1308ab2a 22428+ if (IS_ERR(file))
4a4d8108
AM
22429+ goto out;
22430+
22431+ err = ima_file_check(file, au_conv_oflags(flags));
22432+ if (unlikely(err)) {
22433+ fput(file);
22434+ file = ERR_PTR(err);
22435+ }
22436+out:
1308ab2a 22437+ return file;
22438+}
22439+
1facf9fc 22440+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
22441+{
22442+ struct file *file;
22443+
4a4d8108 22444+ /* lockdep_off(); */
1facf9fc 22445+ file = filp_open(path, oflags, mode);
4a4d8108 22446+ /* lockdep_on(); */
1facf9fc 22447+ if (IS_ERR(file))
22448+ goto out;
22449+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
22450+
22451+ out:
22452+ return file;
22453+}
22454+
22455+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
22456+{
22457+ int err;
22458+
22459+ /* lockdep_off(); */
22460+ err = kern_path(name, flags, path);
22461+ /* lockdep_on(); */
22462+ if (!err && path->dentry->d_inode)
22463+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
22464+ return err;
22465+}
22466+
22467+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
22468+ int len)
22469+{
22470+ struct path path = {
22471+ .mnt = NULL
22472+ };
22473+
1308ab2a 22474+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 22475+ IMustLock(parent->d_inode);
22476+
22477+ path.dentry = lookup_one_len(name, parent, len);
22478+ if (IS_ERR(path.dentry))
22479+ goto out;
22480+ if (path.dentry->d_inode)
22481+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
22482+
22483+ out:
4a4d8108 22484+ AuTraceErrPtr(path.dentry);
1facf9fc 22485+ return path.dentry;
22486+}
22487+
22488+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
22489+{
22490+ struct path path = {
22491+ .mnt = nd->path.mnt
22492+ };
22493+
22494+ IMustLock(nd->path.dentry->d_inode);
22495+
22496+ path.dentry = lookup_hash(nd);
4a4d8108
AM
22497+ if (IS_ERR(path.dentry))
22498+ goto out;
22499+ if (path.dentry->d_inode)
1facf9fc 22500+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
22501+
4a4d8108
AM
22502+ out:
22503+ AuTraceErrPtr(path.dentry);
1facf9fc 22504+ return path.dentry;
22505+}
22506+
22507+/* ---------------------------------------------------------------------- */
22508+
22509+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
22510+ struct dentry *d2, struct au_hinode *hdir2)
22511+{
22512+ struct dentry *d;
22513+
22514+ lockdep_off();
22515+ d = lock_rename(d1, d2);
22516+ lockdep_on();
4a4d8108 22517+ au_hn_suspend(hdir1);
1facf9fc 22518+ if (hdir1 != hdir2)
4a4d8108 22519+ au_hn_suspend(hdir2);
1facf9fc 22520+
22521+ return d;
22522+}
22523+
22524+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
22525+ struct dentry *d2, struct au_hinode *hdir2)
22526+{
4a4d8108 22527+ au_hn_resume(hdir1);
1facf9fc 22528+ if (hdir1 != hdir2)
4a4d8108 22529+ au_hn_resume(hdir2);
1facf9fc 22530+ lockdep_off();
22531+ unlock_rename(d1, d2);
22532+ lockdep_on();
22533+}
22534+
22535+/* ---------------------------------------------------------------------- */
22536+
22537+int vfsub_create(struct inode *dir, struct path *path, int mode)
22538+{
22539+ int err;
22540+ struct dentry *d;
22541+
22542+ IMustLock(dir);
22543+
22544+ d = path->dentry;
22545+ path->dentry = d->d_parent;
22546+ err = security_path_mknod(path, path->dentry, mode, 0);
22547+ path->dentry = d;
22548+ if (unlikely(err))
22549+ goto out;
22550+
22551+ if (au_test_fs_null_nd(dir->i_sb))
22552+ err = vfs_create(dir, path->dentry, mode, NULL);
22553+ else {
22554+ struct nameidata h_nd;
22555+
22556+ memset(&h_nd, 0, sizeof(h_nd));
22557+ h_nd.flags = LOOKUP_CREATE;
22558+ h_nd.intent.open.flags = O_CREAT
22559+ | vfsub_fmode_to_uint(FMODE_READ);
22560+ h_nd.intent.open.create_mode = mode;
22561+ h_nd.path.dentry = path->dentry->d_parent;
22562+ h_nd.path.mnt = path->mnt;
22563+ path_get(&h_nd.path);
22564+ err = vfs_create(dir, path->dentry, mode, &h_nd);
22565+ path_put(&h_nd.path);
22566+ }
22567+
22568+ if (!err) {
22569+ struct path tmp = *path;
22570+ int did;
22571+
22572+ vfsub_update_h_iattr(&tmp, &did);
22573+ if (did) {
22574+ tmp.dentry = path->dentry->d_parent;
22575+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
22576+ }
22577+ /*ignore*/
22578+ }
22579+
22580+ out:
22581+ return err;
22582+}
22583+
22584+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
22585+{
22586+ int err;
22587+ struct dentry *d;
22588+
22589+ IMustLock(dir);
22590+
22591+ d = path->dentry;
22592+ path->dentry = d->d_parent;
22593+ err = security_path_symlink(path, path->dentry, symname);
22594+ path->dentry = d;
22595+ if (unlikely(err))
22596+ goto out;
22597+
22598+ err = vfs_symlink(dir, path->dentry, symname);
22599+ if (!err) {
22600+ struct path tmp = *path;
22601+ int did;
22602+
22603+ vfsub_update_h_iattr(&tmp, &did);
22604+ if (did) {
22605+ tmp.dentry = path->dentry->d_parent;
22606+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
22607+ }
22608+ /*ignore*/
22609+ }
22610+
22611+ out:
22612+ return err;
22613+}
22614+
22615+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
22616+{
22617+ int err;
22618+ struct dentry *d;
22619+
22620+ IMustLock(dir);
22621+
22622+ d = path->dentry;
22623+ path->dentry = d->d_parent;
22624+ err = security_path_mknod(path, path->dentry, mode, dev);
22625+ path->dentry = d;
22626+ if (unlikely(err))
22627+ goto out;
22628+
22629+ err = vfs_mknod(dir, path->dentry, mode, dev);
22630+ if (!err) {
22631+ struct path tmp = *path;
22632+ int did;
22633+
22634+ vfsub_update_h_iattr(&tmp, &did);
22635+ if (did) {
22636+ tmp.dentry = path->dentry->d_parent;
22637+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
22638+ }
22639+ /*ignore*/
22640+ }
22641+
22642+ out:
22643+ return err;
22644+}
22645+
22646+static int au_test_nlink(struct inode *inode)
22647+{
22648+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
22649+
22650+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
22651+ || inode->i_nlink < link_max)
22652+ return 0;
22653+ return -EMLINK;
22654+}
22655+
22656+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
22657+{
22658+ int err;
22659+ struct dentry *d;
22660+
22661+ IMustLock(dir);
22662+
22663+ err = au_test_nlink(src_dentry->d_inode);
22664+ if (unlikely(err))
22665+ return err;
22666+
22667+ d = path->dentry;
22668+ path->dentry = d->d_parent;
22669+ err = security_path_link(src_dentry, path, path->dentry);
22670+ path->dentry = d;
22671+ if (unlikely(err))
22672+ goto out;
22673+
4a4d8108 22674+ /* lockdep_off(); */
1facf9fc 22675+ err = vfs_link(src_dentry, dir, path->dentry);
4a4d8108 22676+ /* lockdep_on(); */
1facf9fc 22677+ if (!err) {
22678+ struct path tmp = *path;
22679+ int did;
22680+
22681+ /* fuse has different memory inode for the same inumber */
22682+ vfsub_update_h_iattr(&tmp, &did);
22683+ if (did) {
22684+ tmp.dentry = path->dentry->d_parent;
22685+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
22686+ tmp.dentry = src_dentry;
22687+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
22688+ }
22689+ /*ignore*/
22690+ }
22691+
22692+ out:
22693+ return err;
22694+}
22695+
22696+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
22697+ struct inode *dir, struct path *path)
22698+{
22699+ int err;
22700+ struct path tmp = {
22701+ .mnt = path->mnt
22702+ };
22703+ struct dentry *d;
22704+
22705+ IMustLock(dir);
22706+ IMustLock(src_dir);
22707+
22708+ d = path->dentry;
22709+ path->dentry = d->d_parent;
22710+ tmp.dentry = src_dentry->d_parent;
22711+ err = security_path_rename(&tmp, src_dentry, path, path->dentry);
22712+ path->dentry = d;
22713+ if (unlikely(err))
22714+ goto out;
22715+
4a4d8108 22716+ /* lockdep_off(); */
1facf9fc 22717+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
4a4d8108 22718+ /* lockdep_on(); */
1facf9fc 22719+ if (!err) {
22720+ int did;
22721+
22722+ tmp.dentry = d->d_parent;
22723+ vfsub_update_h_iattr(&tmp, &did);
22724+ if (did) {
22725+ tmp.dentry = src_dentry;
22726+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
22727+ tmp.dentry = src_dentry->d_parent;
22728+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
22729+ }
22730+ /*ignore*/
22731+ }
22732+
22733+ out:
22734+ return err;
22735+}
22736+
22737+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
22738+{
22739+ int err;
22740+ struct dentry *d;
22741+
22742+ IMustLock(dir);
22743+
22744+ d = path->dentry;
22745+ path->dentry = d->d_parent;
22746+ err = security_path_mkdir(path, path->dentry, mode);
22747+ path->dentry = d;
22748+ if (unlikely(err))
22749+ goto out;
22750+
22751+ err = vfs_mkdir(dir, path->dentry, mode);
22752+ if (!err) {
22753+ struct path tmp = *path;
22754+ int did;
22755+
22756+ vfsub_update_h_iattr(&tmp, &did);
22757+ if (did) {
22758+ tmp.dentry = path->dentry->d_parent;
22759+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
22760+ }
22761+ /*ignore*/
22762+ }
22763+
22764+ out:
22765+ return err;
22766+}
22767+
22768+int vfsub_rmdir(struct inode *dir, struct path *path)
22769+{
22770+ int err;
22771+ struct dentry *d;
22772+
22773+ IMustLock(dir);
22774+
22775+ d = path->dentry;
22776+ path->dentry = d->d_parent;
22777+ err = security_path_rmdir(path, path->dentry);
22778+ path->dentry = d;
22779+ if (unlikely(err))
22780+ goto out;
22781+
4a4d8108 22782+ /* lockdep_off(); */
1facf9fc 22783+ err = vfs_rmdir(dir, path->dentry);
4a4d8108 22784+ /* lockdep_on(); */
1facf9fc 22785+ if (!err) {
22786+ struct path tmp = {
22787+ .dentry = path->dentry->d_parent,
22788+ .mnt = path->mnt
22789+ };
22790+
22791+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
22792+ }
22793+
22794+ out:
22795+ return err;
22796+}
22797+
22798+/* ---------------------------------------------------------------------- */
22799+
22800+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
22801+ loff_t *ppos)
22802+{
22803+ ssize_t err;
22804+
22805+ err = vfs_read(file, ubuf, count, ppos);
22806+ if (err >= 0)
22807+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
22808+ return err;
22809+}
22810+
22811+/* todo: kernel_read()? */
22812+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
22813+ loff_t *ppos)
22814+{
22815+ ssize_t err;
22816+ mm_segment_t oldfs;
22817+
22818+ oldfs = get_fs();
22819+ set_fs(KERNEL_DS);
22820+ err = vfsub_read_u(file, (char __user *)kbuf, count, ppos);
22821+ set_fs(oldfs);
22822+ return err;
22823+}
22824+
22825+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
22826+ loff_t *ppos)
22827+{
22828+ ssize_t err;
22829+
4a4d8108 22830+ /* lockdep_off(); */
1facf9fc 22831+ err = vfs_write(file, ubuf, count, ppos);
4a4d8108 22832+ /* lockdep_on(); */
1facf9fc 22833+ if (err >= 0)
22834+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
22835+ return err;
22836+}
22837+
22838+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
22839+{
22840+ ssize_t err;
22841+ mm_segment_t oldfs;
22842+
22843+ oldfs = get_fs();
22844+ set_fs(KERNEL_DS);
22845+ err = vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
22846+ set_fs(oldfs);
22847+ return err;
22848+}
22849+
4a4d8108
AM
22850+int vfsub_flush(struct file *file, fl_owner_t id)
22851+{
22852+ int err;
22853+
22854+ err = 0;
22855+ if (file->f_op && file->f_op->flush) {
22856+ err = file->f_op->flush(file, id);
22857+ if (!err)
22858+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
22859+ /*ignore*/
22860+ }
22861+ return err;
22862+}
22863+
1facf9fc 22864+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
22865+{
22866+ int err;
22867+
4a4d8108 22868+ /* lockdep_off(); */
1facf9fc 22869+ err = vfs_readdir(file, filldir, arg);
4a4d8108 22870+ /* lockdep_on(); */
1facf9fc 22871+ if (err >= 0)
22872+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
22873+ return err;
22874+}
22875+
22876+long vfsub_splice_to(struct file *in, loff_t *ppos,
22877+ struct pipe_inode_info *pipe, size_t len,
22878+ unsigned int flags)
22879+{
22880+ long err;
22881+
4a4d8108 22882+ /* lockdep_off(); */
0fc653ad 22883+ err = do_splice_to(in, ppos, pipe, len, flags);
4a4d8108
AM
22884+ /* lockdep_on(); */
22885+ file_accessed(in);
1facf9fc 22886+ if (err >= 0)
22887+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
22888+ return err;
22889+}
22890+
22891+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
22892+ loff_t *ppos, size_t len, unsigned int flags)
22893+{
22894+ long err;
22895+
4a4d8108 22896+ /* lockdep_off(); */
0fc653ad 22897+ err = do_splice_from(pipe, out, ppos, len, flags);
4a4d8108 22898+ /* lockdep_on(); */
1facf9fc 22899+ if (err >= 0)
22900+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
22901+ return err;
22902+}
22903+
22904+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
22905+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
22906+ struct file *h_file)
22907+{
22908+ int err;
22909+ struct inode *h_inode;
22910+
22911+ h_inode = h_path->dentry->d_inode;
22912+ if (!h_file) {
22913+ err = mnt_want_write(h_path->mnt);
22914+ if (err)
22915+ goto out;
22916+ err = inode_permission(h_inode, MAY_WRITE);
22917+ if (err)
22918+ goto out_mnt;
22919+ err = get_write_access(h_inode);
22920+ if (err)
22921+ goto out_mnt;
4a4d8108 22922+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 22923+ if (err)
22924+ goto out_inode;
22925+ }
22926+
22927+ err = locks_verify_truncate(h_inode, h_file, length);
22928+ if (!err)
22929+ err = security_path_truncate(h_path, length, attr);
22930+ if (!err) {
4a4d8108 22931+ /* lockdep_off(); */
1facf9fc 22932+ err = do_truncate(h_path->dentry, length, attr, h_file);
4a4d8108 22933+ /* lockdep_on(); */
1facf9fc 22934+ }
22935+
22936+ out_inode:
22937+ if (!h_file)
22938+ put_write_access(h_inode);
22939+ out_mnt:
22940+ if (!h_file)
22941+ mnt_drop_write(h_path->mnt);
22942+ out:
22943+ return err;
22944+}
22945+
22946+/* ---------------------------------------------------------------------- */
22947+
22948+struct au_vfsub_mkdir_args {
22949+ int *errp;
22950+ struct inode *dir;
22951+ struct path *path;
22952+ int mode;
22953+};
22954+
22955+static void au_call_vfsub_mkdir(void *args)
22956+{
22957+ struct au_vfsub_mkdir_args *a = args;
22958+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
22959+}
22960+
22961+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
22962+{
22963+ int err, do_sio, wkq_err;
22964+
22965+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
22966+ if (!do_sio)
22967+ err = vfsub_mkdir(dir, path, mode);
22968+ else {
22969+ struct au_vfsub_mkdir_args args = {
22970+ .errp = &err,
22971+ .dir = dir,
22972+ .path = path,
22973+ .mode = mode
22974+ };
22975+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
22976+ if (unlikely(wkq_err))
22977+ err = wkq_err;
22978+ }
22979+
22980+ return err;
22981+}
22982+
22983+struct au_vfsub_rmdir_args {
22984+ int *errp;
22985+ struct inode *dir;
22986+ struct path *path;
22987+};
22988+
22989+static void au_call_vfsub_rmdir(void *args)
22990+{
22991+ struct au_vfsub_rmdir_args *a = args;
22992+ *a->errp = vfsub_rmdir(a->dir, a->path);
22993+}
22994+
22995+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
22996+{
22997+ int err, do_sio, wkq_err;
22998+
22999+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
23000+ if (!do_sio)
23001+ err = vfsub_rmdir(dir, path);
23002+ else {
23003+ struct au_vfsub_rmdir_args args = {
23004+ .errp = &err,
23005+ .dir = dir,
23006+ .path = path
23007+ };
23008+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
23009+ if (unlikely(wkq_err))
23010+ err = wkq_err;
23011+ }
23012+
23013+ return err;
23014+}
23015+
23016+/* ---------------------------------------------------------------------- */
23017+
23018+struct notify_change_args {
23019+ int *errp;
23020+ struct path *path;
23021+ struct iattr *ia;
23022+};
23023+
23024+static void call_notify_change(void *args)
23025+{
23026+ struct notify_change_args *a = args;
23027+ struct inode *h_inode;
23028+
23029+ h_inode = a->path->dentry->d_inode;
23030+ IMustLock(h_inode);
23031+
23032+ *a->errp = -EPERM;
23033+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
4a4d8108 23034+ /* lockdep_off(); */
1facf9fc 23035+ *a->errp = notify_change(a->path->dentry, a->ia);
4a4d8108 23036+ /* lockdep_on(); */
1facf9fc 23037+ if (!*a->errp)
23038+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
23039+ }
23040+ AuTraceErr(*a->errp);
23041+}
23042+
23043+int vfsub_notify_change(struct path *path, struct iattr *ia)
23044+{
23045+ int err;
23046+ struct notify_change_args args = {
23047+ .errp = &err,
23048+ .path = path,
23049+ .ia = ia
23050+ };
23051+
23052+ call_notify_change(&args);
23053+
23054+ return err;
23055+}
23056+
23057+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
23058+{
23059+ int err, wkq_err;
23060+ struct notify_change_args args = {
23061+ .errp = &err,
23062+ .path = path,
23063+ .ia = ia
23064+ };
23065+
23066+ wkq_err = au_wkq_wait(call_notify_change, &args);
23067+ if (unlikely(wkq_err))
23068+ err = wkq_err;
23069+
23070+ return err;
23071+}
23072+
23073+/* ---------------------------------------------------------------------- */
23074+
23075+struct unlink_args {
23076+ int *errp;
23077+ struct inode *dir;
23078+ struct path *path;
23079+};
23080+
23081+static void call_unlink(void *args)
23082+{
23083+ struct unlink_args *a = args;
23084+ struct dentry *d = a->path->dentry;
23085+ struct inode *h_inode;
23086+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
23087+ && atomic_read(&d->d_count) == 1);
23088+
23089+ IMustLock(a->dir);
23090+
23091+ a->path->dentry = d->d_parent;
23092+ *a->errp = security_path_unlink(a->path, d);
23093+ a->path->dentry = d;
23094+ if (unlikely(*a->errp))
23095+ return;
23096+
23097+ if (!stop_sillyrename)
23098+ dget(d);
23099+ h_inode = d->d_inode;
23100+ if (h_inode)
23101+ atomic_inc(&h_inode->i_count);
23102+
4a4d8108 23103+ /* lockdep_off(); */
1facf9fc 23104+ *a->errp = vfs_unlink(a->dir, d);
4a4d8108 23105+ /* lockdep_on(); */
1facf9fc 23106+ if (!*a->errp) {
23107+ struct path tmp = {
23108+ .dentry = d->d_parent,
23109+ .mnt = a->path->mnt
23110+ };
23111+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
23112+ }
23113+
23114+ if (!stop_sillyrename)
23115+ dput(d);
23116+ if (h_inode)
23117+ iput(h_inode);
23118+
23119+ AuTraceErr(*a->errp);
23120+}
23121+
23122+/*
23123+ * @dir: must be locked.
23124+ * @dentry: target dentry.
23125+ */
23126+int vfsub_unlink(struct inode *dir, struct path *path, int force)
23127+{
23128+ int err;
23129+ struct unlink_args args = {
23130+ .errp = &err,
23131+ .dir = dir,
23132+ .path = path
23133+ };
23134+
23135+ if (!force)
23136+ call_unlink(&args);
23137+ else {
23138+ int wkq_err;
23139+
23140+ wkq_err = au_wkq_wait(call_unlink, &args);
23141+ if (unlikely(wkq_err))
23142+ err = wkq_err;
23143+ }
23144+
23145+ return err;
23146+}
4a4d8108
AM
23147diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/vfsub.h linux-2.6.34/fs/aufs/vfsub.h
23148--- linux-2.6.34.org/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
23149+++ linux-2.6.34/fs/aufs/vfsub.h 2010-05-31 22:15:32.000000000 +0200
23150@@ -0,0 +1,176 @@
1facf9fc 23151+/*
4a4d8108 23152+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 23153+ *
23154+ * This program, aufs is free software; you can redistribute it and/or modify
23155+ * it under the terms of the GNU General Public License as published by
23156+ * the Free Software Foundation; either version 2 of the License, or
23157+ * (at your option) any later version.
dece6358
AM
23158+ *
23159+ * This program is distributed in the hope that it will be useful,
23160+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23161+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23162+ * GNU General Public License for more details.
23163+ *
23164+ * You should have received a copy of the GNU General Public License
23165+ * along with this program; if not, write to the Free Software
23166+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23167+ */
23168+
23169+/*
23170+ * sub-routines for VFS
23171+ */
23172+
23173+#ifndef __AUFS_VFSUB_H__
23174+#define __AUFS_VFSUB_H__
23175+
23176+#ifdef __KERNEL__
23177+
23178+#include <linux/fs.h>
1facf9fc 23179+
23180+/* ---------------------------------------------------------------------- */
23181+
23182+/* lock subclass for lower inode */
23183+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
23184+/* reduce? gave up. */
23185+enum {
23186+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
23187+ AuLsc_I_PARENT, /* lower inode, parent first */
23188+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 23189+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 23190+ AuLsc_I_CHILD,
23191+ AuLsc_I_CHILD2,
23192+ AuLsc_I_End
23193+};
23194+
23195+/* to debug easier, do not make them inlined functions */
23196+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
23197+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
23198+
23199+/* ---------------------------------------------------------------------- */
23200+
1facf9fc 23201+int vfsub_update_h_iattr(struct path *h_path, int *did);
4a4d8108 23202+struct file *vfsub_dentry_open(struct path *path, int flags);
1facf9fc 23203+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
23204+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
23205+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
23206+ int len);
23207+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
23208+
23209+/* ---------------------------------------------------------------------- */
23210+
23211+struct au_hinode;
23212+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
23213+ struct dentry *d2, struct au_hinode *hdir2);
23214+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
23215+ struct dentry *d2, struct au_hinode *hdir2);
23216+
23217+int vfsub_create(struct inode *dir, struct path *path, int mode);
23218+int vfsub_symlink(struct inode *dir, struct path *path,
23219+ const char *symname);
23220+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
23221+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
23222+ struct path *path);
23223+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
23224+ struct inode *hdir, struct path *path);
23225+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
23226+int vfsub_rmdir(struct inode *dir, struct path *path);
23227+
23228+/* ---------------------------------------------------------------------- */
23229+
23230+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
23231+ loff_t *ppos);
23232+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
23233+ loff_t *ppos);
23234+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
23235+ loff_t *ppos);
23236+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
23237+ loff_t *ppos);
4a4d8108 23238+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 23239+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
23240+
4a4d8108
AM
23241+static inline unsigned int vfsub_file_flags(struct file *file)
23242+{
23243+ unsigned int flags;
23244+
23245+ spin_lock(&file->f_lock);
23246+ flags = file->f_flags;
23247+ spin_unlock(&file->f_lock);
23248+
23249+ return flags;
23250+}
1308ab2a 23251+
1facf9fc 23252+static inline void vfsub_file_accessed(struct file *h_file)
23253+{
23254+ file_accessed(h_file);
23255+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
23256+}
23257+
23258+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
23259+ struct dentry *h_dentry)
23260+{
23261+ struct path h_path = {
23262+ .dentry = h_dentry,
23263+ .mnt = h_mnt
23264+ };
23265+ touch_atime(h_mnt, h_dentry);
23266+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
23267+}
23268+
4a4d8108
AM
23269+long vfsub_splice_to(struct file *in, loff_t *ppos,
23270+ struct pipe_inode_info *pipe, size_t len,
23271+ unsigned int flags);
23272+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
23273+ loff_t *ppos, size_t len, unsigned int flags);
23274+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
23275+ struct file *h_file);
23276+
1facf9fc 23277+/* ---------------------------------------------------------------------- */
23278+
23279+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
23280+{
23281+ loff_t err;
23282+
4a4d8108 23283+ /* lockdep_off(); */
1facf9fc 23284+ err = vfs_llseek(file, offset, origin);
4a4d8108 23285+ /* lockdep_on(); */
1facf9fc 23286+ return err;
23287+}
23288+
23289+/* ---------------------------------------------------------------------- */
23290+
23291+/* dirty workaround for strict type of fmode_t */
23292+union vfsub_fmu {
23293+ fmode_t fm;
23294+ unsigned int ui;
23295+};
23296+
23297+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
23298+{
23299+ union vfsub_fmu u = {
23300+ .fm = fm
23301+ };
23302+
23303+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
23304+
23305+ return u.ui;
23306+}
23307+
23308+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
23309+{
23310+ union vfsub_fmu u = {
23311+ .ui = ui
23312+ };
23313+
23314+ return u.fm;
23315+}
23316+
4a4d8108
AM
23317+/* ---------------------------------------------------------------------- */
23318+
23319+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
23320+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
23321+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
23322+int vfsub_notify_change(struct path *path, struct iattr *ia);
23323+int vfsub_unlink(struct inode *dir, struct path *path, int force);
23324+
1facf9fc 23325+#endif /* __KERNEL__ */
23326+#endif /* __AUFS_VFSUB_H__ */
4a4d8108
AM
23327diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/wbr_policy.c linux-2.6.34/fs/aufs/wbr_policy.c
23328--- linux-2.6.34.org/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
23329+++ linux-2.6.34/fs/aufs/wbr_policy.c 2010-05-31 22:15:32.000000000 +0200
23330@@ -0,0 +1,696 @@
1facf9fc 23331+/*
4a4d8108 23332+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 23333+ *
23334+ * This program, aufs is free software; you can redistribute it and/or modify
23335+ * it under the terms of the GNU General Public License as published by
23336+ * the Free Software Foundation; either version 2 of the License, or
23337+ * (at your option) any later version.
dece6358
AM
23338+ *
23339+ * This program is distributed in the hope that it will be useful,
23340+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23341+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23342+ * GNU General Public License for more details.
23343+ *
23344+ * You should have received a copy of the GNU General Public License
23345+ * along with this program; if not, write to the Free Software
23346+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23347+ */
23348+
23349+/*
23350+ * policies for selecting one among multiple writable branches
23351+ */
23352+
23353+#include <linux/statfs.h>
23354+#include "aufs.h"
23355+
23356+/* subset of cpup_attr() */
23357+static noinline_for_stack
23358+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
23359+{
23360+ int err, sbits;
23361+ struct iattr ia;
23362+ struct inode *h_isrc;
23363+
23364+ h_isrc = h_src->d_inode;
23365+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
23366+ ia.ia_mode = h_isrc->i_mode;
23367+ ia.ia_uid = h_isrc->i_uid;
23368+ ia.ia_gid = h_isrc->i_gid;
23369+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
23370+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
23371+ err = vfsub_sio_notify_change(h_path, &ia);
23372+
23373+ /* is this nfs only? */
23374+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
23375+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
23376+ ia.ia_mode = h_isrc->i_mode;
23377+ err = vfsub_sio_notify_change(h_path, &ia);
23378+ }
23379+
23380+ return err;
23381+}
23382+
23383+#define AuCpdown_PARENT_OPQ 1
23384+#define AuCpdown_WHED (1 << 1)
23385+#define AuCpdown_MADE_DIR (1 << 2)
23386+#define AuCpdown_DIROPQ (1 << 3)
23387+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
23388+#define au_fset_cpdown(flags, name) { (flags) |= AuCpdown_##name; }
23389+#define au_fclr_cpdown(flags, name) { (flags) &= ~AuCpdown_##name; }
23390+
23391+struct au_cpdown_dir_args {
23392+ struct dentry *parent;
23393+ unsigned int flags;
23394+};
23395+
23396+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
23397+ struct au_cpdown_dir_args *a)
23398+{
23399+ int err;
23400+ struct dentry *opq_dentry;
23401+
23402+ opq_dentry = au_diropq_create(dentry, bdst);
23403+ err = PTR_ERR(opq_dentry);
23404+ if (IS_ERR(opq_dentry))
23405+ goto out;
23406+ dput(opq_dentry);
23407+ au_fset_cpdown(a->flags, DIROPQ);
23408+
23409+ out:
23410+ return err;
23411+}
23412+
23413+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
23414+ struct inode *dir, aufs_bindex_t bdst)
23415+{
23416+ int err;
23417+ struct path h_path;
23418+ struct au_branch *br;
23419+
23420+ br = au_sbr(dentry->d_sb, bdst);
23421+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
23422+ err = PTR_ERR(h_path.dentry);
23423+ if (IS_ERR(h_path.dentry))
23424+ goto out;
23425+
23426+ err = 0;
23427+ if (h_path.dentry->d_inode) {
23428+ h_path.mnt = br->br_mnt;
23429+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
23430+ dentry);
23431+ }
23432+ dput(h_path.dentry);
23433+
23434+ out:
23435+ return err;
23436+}
23437+
23438+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
23439+ struct dentry *h_parent, void *arg)
23440+{
23441+ int err, rerr;
4a4d8108 23442+ aufs_bindex_t bopq, bstart;
1facf9fc 23443+ struct path h_path;
23444+ struct dentry *parent;
23445+ struct inode *h_dir, *h_inode, *inode, *dir;
23446+ struct au_cpdown_dir_args *args = arg;
23447+
23448+ bstart = au_dbstart(dentry);
23449+ /* dentry is di-locked */
23450+ parent = dget_parent(dentry);
23451+ dir = parent->d_inode;
23452+ h_dir = h_parent->d_inode;
23453+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
23454+ IMustLock(h_dir);
23455+
23456+ err = au_lkup_neg(dentry, bdst);
23457+ if (unlikely(err < 0))
23458+ goto out;
23459+ h_path.dentry = au_h_dptr(dentry, bdst);
23460+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
23461+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
23462+ S_IRWXU | S_IRUGO | S_IXUGO);
23463+ if (unlikely(err))
23464+ goto out_put;
23465+ au_fset_cpdown(args->flags, MADE_DIR);
23466+
1facf9fc 23467+ bopq = au_dbdiropq(dentry);
23468+ au_fclr_cpdown(args->flags, WHED);
23469+ au_fclr_cpdown(args->flags, DIROPQ);
23470+ if (au_dbwh(dentry) == bdst)
23471+ au_fset_cpdown(args->flags, WHED);
23472+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
23473+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 23474+ h_inode = h_path.dentry->d_inode;
23475+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
23476+ if (au_ftest_cpdown(args->flags, WHED)) {
23477+ err = au_cpdown_dir_opq(dentry, bdst, args);
23478+ if (unlikely(err)) {
23479+ mutex_unlock(&h_inode->i_mutex);
23480+ goto out_dir;
23481+ }
23482+ }
23483+
23484+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
23485+ mutex_unlock(&h_inode->i_mutex);
23486+ if (unlikely(err))
23487+ goto out_opq;
23488+
23489+ if (au_ftest_cpdown(args->flags, WHED)) {
23490+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
23491+ if (unlikely(err))
23492+ goto out_opq;
23493+ }
23494+
23495+ inode = dentry->d_inode;
23496+ if (au_ibend(inode) < bdst)
23497+ au_set_ibend(inode, bdst);
23498+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
23499+ au_hi_flags(inode, /*isdir*/1));
23500+ goto out; /* success */
23501+
23502+ /* revert */
23503+ out_opq:
23504+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
23505+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
23506+ rerr = au_diropq_remove(dentry, bdst);
23507+ mutex_unlock(&h_inode->i_mutex);
23508+ if (unlikely(rerr)) {
23509+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
23510+ AuDLNPair(dentry), bdst, rerr);
23511+ err = -EIO;
23512+ goto out;
23513+ }
23514+ }
23515+ out_dir:
23516+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
23517+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
23518+ if (unlikely(rerr)) {
23519+ AuIOErr("failed removing %.*s b%d (%d)\n",
23520+ AuDLNPair(dentry), bdst, rerr);
23521+ err = -EIO;
23522+ }
23523+ }
23524+ out_put:
23525+ au_set_h_dptr(dentry, bdst, NULL);
23526+ if (au_dbend(dentry) == bdst)
23527+ au_update_dbend(dentry);
23528+ out:
23529+ dput(parent);
23530+ return err;
23531+}
23532+
23533+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
23534+{
23535+ int err;
23536+ struct au_cpdown_dir_args args = {
23537+ .parent = dget_parent(dentry),
23538+ .flags = 0
23539+ };
23540+
23541+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
23542+ dput(args.parent);
23543+
23544+ return err;
23545+}
23546+
23547+/* ---------------------------------------------------------------------- */
23548+
23549+/* policies for create */
23550+
4a4d8108
AM
23551+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
23552+{
23553+ int err, i, j, ndentry;
23554+ aufs_bindex_t bopq;
23555+ struct au_dcsub_pages dpages;
23556+ struct au_dpage *dpage;
23557+ struct dentry **dentries, *parent, *d;
23558+
23559+ err = au_dpages_init(&dpages, GFP_NOFS);
23560+ if (unlikely(err))
23561+ goto out;
23562+ parent = dget_parent(dentry);
23563+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/0, /*test*/NULL,
23564+ /*arg*/NULL);
23565+ if (unlikely(err))
23566+ goto out_free;
23567+
23568+ err = bindex;
23569+ for (i = 0; i < dpages.ndpage; i++) {
23570+ dpage = dpages.dpages + i;
23571+ dentries = dpage->dentries;
23572+ ndentry = dpage->ndentry;
23573+ for (j = 0; j < ndentry; j++) {
23574+ d = dentries[j];
23575+ di_read_lock_parent2(d, !AuLock_IR);
23576+ bopq = au_dbdiropq(d);
23577+ di_read_unlock(d, !AuLock_IR);
23578+ if (bopq >= 0 && bopq < err)
23579+ err = bopq;
23580+ }
23581+ }
23582+
23583+out_free:
23584+ dput(parent);
23585+ au_dpages_free(&dpages);
23586+out:
23587+ return err;
23588+}
23589+
1facf9fc 23590+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
23591+{
23592+ for (; bindex >= 0; bindex--)
23593+ if (!au_br_rdonly(au_sbr(sb, bindex)))
23594+ return bindex;
23595+ return -EROFS;
23596+}
23597+
23598+/* top down parent */
23599+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
23600+{
23601+ int err;
23602+ aufs_bindex_t bstart, bindex;
23603+ struct super_block *sb;
23604+ struct dentry *parent, *h_parent;
23605+
23606+ sb = dentry->d_sb;
23607+ bstart = au_dbstart(dentry);
23608+ err = bstart;
23609+ if (!au_br_rdonly(au_sbr(sb, bstart)))
23610+ goto out;
23611+
23612+ err = -EROFS;
23613+ parent = dget_parent(dentry);
23614+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
23615+ h_parent = au_h_dptr(parent, bindex);
23616+ if (!h_parent || !h_parent->d_inode)
23617+ continue;
23618+
23619+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
23620+ err = bindex;
23621+ break;
23622+ }
23623+ }
23624+ dput(parent);
23625+
23626+ /* bottom up here */
4a4d8108 23627+ if (unlikely(err < 0)) {
1facf9fc 23628+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
23629+ if (err >= 0)
23630+ err = au_wbr_nonopq(dentry, err);
23631+ }
1facf9fc 23632+
23633+ out:
23634+ AuDbg("b%d\n", err);
23635+ return err;
23636+}
23637+
23638+/* ---------------------------------------------------------------------- */
23639+
23640+/* an exception for the policy other than tdp */
23641+static int au_wbr_create_exp(struct dentry *dentry)
23642+{
23643+ int err;
23644+ aufs_bindex_t bwh, bdiropq;
23645+ struct dentry *parent;
23646+
23647+ err = -1;
23648+ bwh = au_dbwh(dentry);
23649+ parent = dget_parent(dentry);
23650+ bdiropq = au_dbdiropq(parent);
23651+ if (bwh >= 0) {
23652+ if (bdiropq >= 0)
23653+ err = min(bdiropq, bwh);
23654+ else
23655+ err = bwh;
23656+ AuDbg("%d\n", err);
23657+ } else if (bdiropq >= 0) {
23658+ err = bdiropq;
23659+ AuDbg("%d\n", err);
23660+ }
23661+ dput(parent);
23662+
4a4d8108
AM
23663+ if (err >= 0)
23664+ err = au_wbr_nonopq(dentry, err);
23665+
1facf9fc 23666+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
23667+ err = -1;
23668+
23669+ AuDbg("%d\n", err);
23670+ return err;
23671+}
23672+
23673+/* ---------------------------------------------------------------------- */
23674+
23675+/* round robin */
23676+static int au_wbr_create_init_rr(struct super_block *sb)
23677+{
23678+ int err;
23679+
23680+ err = au_wbr_bu(sb, au_sbend(sb));
23681+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 23682+ /* smp_mb(); */
1facf9fc 23683+
23684+ AuDbg("b%d\n", err);
23685+ return err;
23686+}
23687+
23688+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
23689+{
23690+ int err, nbr;
23691+ unsigned int u;
23692+ aufs_bindex_t bindex, bend;
23693+ struct super_block *sb;
23694+ atomic_t *next;
23695+
23696+ err = au_wbr_create_exp(dentry);
23697+ if (err >= 0)
23698+ goto out;
23699+
23700+ sb = dentry->d_sb;
23701+ next = &au_sbi(sb)->si_wbr_rr_next;
23702+ bend = au_sbend(sb);
23703+ nbr = bend + 1;
23704+ for (bindex = 0; bindex <= bend; bindex++) {
23705+ if (!isdir) {
23706+ err = atomic_dec_return(next) + 1;
23707+ /* modulo for 0 is meaningless */
23708+ if (unlikely(!err))
23709+ err = atomic_dec_return(next) + 1;
23710+ } else
23711+ err = atomic_read(next);
23712+ AuDbg("%d\n", err);
23713+ u = err;
23714+ err = u % nbr;
23715+ AuDbg("%d\n", err);
23716+ if (!au_br_rdonly(au_sbr(sb, err)))
23717+ break;
23718+ err = -EROFS;
23719+ }
23720+
4a4d8108
AM
23721+ if (err >= 0)
23722+ err = au_wbr_nonopq(dentry, err);
23723+
1facf9fc 23724+ out:
23725+ AuDbg("%d\n", err);
23726+ return err;
23727+}
23728+
23729+/* ---------------------------------------------------------------------- */
23730+
23731+/* most free space */
23732+static void au_mfs(struct dentry *dentry)
23733+{
23734+ struct super_block *sb;
23735+ struct au_branch *br;
23736+ struct au_wbr_mfs *mfs;
23737+ aufs_bindex_t bindex, bend;
23738+ int err;
23739+ unsigned long long b, bavail;
23740+ /* reduce the stack usage */
23741+ struct kstatfs *st;
23742+
23743+ st = kmalloc(sizeof(*st), GFP_NOFS);
23744+ if (unlikely(!st)) {
23745+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
23746+ return;
23747+ }
23748+
23749+ bavail = 0;
23750+ sb = dentry->d_sb;
23751+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 23752+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 23753+ mfs->mfs_bindex = -EROFS;
23754+ mfs->mfsrr_bytes = 0;
23755+ bend = au_sbend(sb);
23756+ for (bindex = 0; bindex <= bend; bindex++) {
23757+ br = au_sbr(sb, bindex);
23758+ if (au_br_rdonly(br))
23759+ continue;
23760+
23761+ /* sb->s_root for NFS is unreliable */
23762+ err = vfs_statfs(br->br_mnt->mnt_root, st);
23763+ if (unlikely(err)) {
23764+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
23765+ continue;
23766+ }
23767+
23768+ /* when the available size is equal, select the lower one */
23769+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
23770+ || sizeof(b) < sizeof(st->f_bsize));
23771+ b = st->f_bavail * st->f_bsize;
23772+ br->br_wbr->wbr_bytes = b;
23773+ if (b >= bavail) {
23774+ bavail = b;
23775+ mfs->mfs_bindex = bindex;
23776+ mfs->mfs_jiffy = jiffies;
23777+ }
23778+ }
23779+
23780+ mfs->mfsrr_bytes = bavail;
23781+ AuDbg("b%d\n", mfs->mfs_bindex);
23782+ kfree(st);
23783+}
23784+
23785+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
23786+{
23787+ int err;
23788+ struct super_block *sb;
23789+ struct au_wbr_mfs *mfs;
23790+
23791+ err = au_wbr_create_exp(dentry);
23792+ if (err >= 0)
23793+ goto out;
23794+
23795+ sb = dentry->d_sb;
23796+ mfs = &au_sbi(sb)->si_wbr_mfs;
23797+ mutex_lock(&mfs->mfs_lock);
23798+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
23799+ || mfs->mfs_bindex < 0
23800+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
23801+ au_mfs(dentry);
23802+ mutex_unlock(&mfs->mfs_lock);
23803+ err = mfs->mfs_bindex;
23804+
4a4d8108
AM
23805+ if (err >= 0)
23806+ err = au_wbr_nonopq(dentry, err);
23807+
1facf9fc 23808+ out:
23809+ AuDbg("b%d\n", err);
23810+ return err;
23811+}
23812+
23813+static int au_wbr_create_init_mfs(struct super_block *sb)
23814+{
23815+ struct au_wbr_mfs *mfs;
23816+
23817+ mfs = &au_sbi(sb)->si_wbr_mfs;
23818+ mutex_init(&mfs->mfs_lock);
23819+ mfs->mfs_jiffy = 0;
23820+ mfs->mfs_bindex = -EROFS;
23821+
23822+ return 0;
23823+}
23824+
23825+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
23826+{
23827+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
23828+ return 0;
23829+}
23830+
23831+/* ---------------------------------------------------------------------- */
23832+
23833+/* most free space and then round robin */
23834+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
23835+{
23836+ int err;
23837+ struct au_wbr_mfs *mfs;
23838+
23839+ err = au_wbr_create_mfs(dentry, isdir);
23840+ if (err >= 0) {
23841+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 23842+ mutex_lock(&mfs->mfs_lock);
1facf9fc 23843+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
23844+ err = au_wbr_create_rr(dentry, isdir);
dece6358 23845+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 23846+ }
23847+
23848+ AuDbg("b%d\n", err);
23849+ return err;
23850+}
23851+
23852+static int au_wbr_create_init_mfsrr(struct super_block *sb)
23853+{
23854+ int err;
23855+
23856+ au_wbr_create_init_mfs(sb); /* ignore */
23857+ err = au_wbr_create_init_rr(sb);
23858+
23859+ return err;
23860+}
23861+
23862+/* ---------------------------------------------------------------------- */
23863+
23864+/* top down parent and most free space */
23865+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
23866+{
23867+ int err, e2;
23868+ unsigned long long b;
23869+ aufs_bindex_t bindex, bstart, bend;
23870+ struct super_block *sb;
23871+ struct dentry *parent, *h_parent;
23872+ struct au_branch *br;
23873+
23874+ err = au_wbr_create_tdp(dentry, isdir);
23875+ if (unlikely(err < 0))
23876+ goto out;
23877+ parent = dget_parent(dentry);
23878+ bstart = au_dbstart(parent);
23879+ bend = au_dbtaildir(parent);
23880+ if (bstart == bend)
23881+ goto out_parent; /* success */
23882+
23883+ e2 = au_wbr_create_mfs(dentry, isdir);
23884+ if (e2 < 0)
23885+ goto out_parent; /* success */
23886+
23887+ /* when the available size is equal, select upper one */
23888+ sb = dentry->d_sb;
23889+ br = au_sbr(sb, err);
23890+ b = br->br_wbr->wbr_bytes;
23891+ AuDbg("b%d, %llu\n", err, b);
23892+
23893+ for (bindex = bstart; bindex <= bend; bindex++) {
23894+ h_parent = au_h_dptr(parent, bindex);
23895+ if (!h_parent || !h_parent->d_inode)
23896+ continue;
23897+
23898+ br = au_sbr(sb, bindex);
23899+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
23900+ b = br->br_wbr->wbr_bytes;
23901+ err = bindex;
23902+ AuDbg("b%d, %llu\n", err, b);
23903+ }
23904+ }
23905+
4a4d8108
AM
23906+ if (err >= 0)
23907+ err = au_wbr_nonopq(dentry, err);
23908+
1facf9fc 23909+ out_parent:
23910+ dput(parent);
23911+ out:
23912+ AuDbg("b%d\n", err);
23913+ return err;
23914+}
23915+
23916+/* ---------------------------------------------------------------------- */
23917+
23918+/* policies for copyup */
23919+
23920+/* top down parent */
23921+static int au_wbr_copyup_tdp(struct dentry *dentry)
23922+{
23923+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
23924+}
23925+
23926+/* bottom up parent */
23927+static int au_wbr_copyup_bup(struct dentry *dentry)
23928+{
23929+ int err;
23930+ aufs_bindex_t bindex, bstart;
23931+ struct dentry *parent, *h_parent;
23932+ struct super_block *sb;
23933+
23934+ err = -EROFS;
23935+ sb = dentry->d_sb;
23936+ parent = dget_parent(dentry);
23937+ bstart = au_dbstart(parent);
23938+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
23939+ h_parent = au_h_dptr(parent, bindex);
23940+ if (!h_parent || !h_parent->d_inode)
23941+ continue;
23942+
23943+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
23944+ err = bindex;
23945+ break;
23946+ }
23947+ }
23948+ dput(parent);
23949+
23950+ /* bottom up here */
23951+ if (unlikely(err < 0))
23952+ err = au_wbr_bu(sb, bstart - 1);
23953+
23954+ AuDbg("b%d\n", err);
23955+ return err;
23956+}
23957+
23958+/* bottom up */
23959+static int au_wbr_copyup_bu(struct dentry *dentry)
23960+{
23961+ int err;
4a4d8108 23962+ aufs_bindex_t bstart;
1facf9fc 23963+
4a4d8108
AM
23964+ bstart = au_dbstart(dentry);
23965+ err = au_wbr_bu(dentry->d_sb, bstart);
23966+ AuDbg("b%d\n", err);
23967+ if (err > bstart)
23968+ err = au_wbr_nonopq(dentry, err);
1facf9fc 23969+
23970+ AuDbg("b%d\n", err);
23971+ return err;
23972+}
23973+
23974+/* ---------------------------------------------------------------------- */
23975+
23976+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
23977+ [AuWbrCopyup_TDP] = {
23978+ .copyup = au_wbr_copyup_tdp
23979+ },
23980+ [AuWbrCopyup_BUP] = {
23981+ .copyup = au_wbr_copyup_bup
23982+ },
23983+ [AuWbrCopyup_BU] = {
23984+ .copyup = au_wbr_copyup_bu
23985+ }
23986+};
23987+
23988+struct au_wbr_create_operations au_wbr_create_ops[] = {
23989+ [AuWbrCreate_TDP] = {
23990+ .create = au_wbr_create_tdp
23991+ },
23992+ [AuWbrCreate_RR] = {
23993+ .create = au_wbr_create_rr,
23994+ .init = au_wbr_create_init_rr
23995+ },
23996+ [AuWbrCreate_MFS] = {
23997+ .create = au_wbr_create_mfs,
23998+ .init = au_wbr_create_init_mfs,
23999+ .fin = au_wbr_create_fin_mfs
24000+ },
24001+ [AuWbrCreate_MFSV] = {
24002+ .create = au_wbr_create_mfs,
24003+ .init = au_wbr_create_init_mfs,
24004+ .fin = au_wbr_create_fin_mfs
24005+ },
24006+ [AuWbrCreate_MFSRR] = {
24007+ .create = au_wbr_create_mfsrr,
24008+ .init = au_wbr_create_init_mfsrr,
24009+ .fin = au_wbr_create_fin_mfs
24010+ },
24011+ [AuWbrCreate_MFSRRV] = {
24012+ .create = au_wbr_create_mfsrr,
24013+ .init = au_wbr_create_init_mfsrr,
24014+ .fin = au_wbr_create_fin_mfs
24015+ },
24016+ [AuWbrCreate_PMFS] = {
24017+ .create = au_wbr_create_pmfs,
24018+ .init = au_wbr_create_init_mfs,
24019+ .fin = au_wbr_create_fin_mfs
24020+ },
24021+ [AuWbrCreate_PMFSV] = {
24022+ .create = au_wbr_create_pmfs,
24023+ .init = au_wbr_create_init_mfs,
24024+ .fin = au_wbr_create_fin_mfs
24025+ }
24026+};
4a4d8108
AM
24027diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/whout.c linux-2.6.34/fs/aufs/whout.c
24028--- linux-2.6.34.org/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
24029+++ linux-2.6.34/fs/aufs/whout.c 2010-05-31 22:15:32.000000000 +0200
1308ab2a 24030@@ -0,0 +1,1052 @@
1facf9fc 24031+/*
4a4d8108 24032+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 24033+ *
24034+ * This program, aufs is free software; you can redistribute it and/or modify
24035+ * it under the terms of the GNU General Public License as published by
24036+ * the Free Software Foundation; either version 2 of the License, or
24037+ * (at your option) any later version.
dece6358
AM
24038+ *
24039+ * This program is distributed in the hope that it will be useful,
24040+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24041+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24042+ * GNU General Public License for more details.
24043+ *
24044+ * You should have received a copy of the GNU General Public License
24045+ * along with this program; if not, write to the Free Software
24046+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24047+ */
24048+
24049+/*
24050+ * whiteout for logical deletion and opaque directory
24051+ */
24052+
24053+#include <linux/fs.h>
24054+#include "aufs.h"
24055+
24056+#define WH_MASK S_IRUGO
24057+
24058+/*
24059+ * If a directory contains this file, then it is opaque. We start with the
24060+ * .wh. flag so that it is blocked by lookup.
24061+ */
24062+static struct qstr diropq_name = {
24063+ .name = AUFS_WH_DIROPQ,
24064+ .len = sizeof(AUFS_WH_DIROPQ) - 1
24065+};
24066+
24067+/*
24068+ * generate whiteout name, which is NOT terminated by NULL.
24069+ * @name: original d_name.name
24070+ * @len: original d_name.len
24071+ * @wh: whiteout qstr
24072+ * returns zero when succeeds, otherwise error.
24073+ * succeeded value as wh->name should be freed by kfree().
24074+ */
24075+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
24076+{
24077+ char *p;
24078+
24079+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
24080+ return -ENAMETOOLONG;
24081+
24082+ wh->len = name->len + AUFS_WH_PFX_LEN;
24083+ p = kmalloc(wh->len, GFP_NOFS);
24084+ wh->name = p;
24085+ if (p) {
24086+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
24087+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
24088+ /* smp_mb(); */
24089+ return 0;
24090+ }
24091+ return -ENOMEM;
24092+}
24093+
24094+/* ---------------------------------------------------------------------- */
24095+
24096+/*
24097+ * test if the @wh_name exists under @h_parent.
24098+ * @try_sio specifies the necessary of super-io.
24099+ */
24100+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
24101+ struct au_branch *br, int try_sio)
24102+{
24103+ int err;
24104+ struct dentry *wh_dentry;
1facf9fc 24105+
1facf9fc 24106+ if (!try_sio)
24107+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
24108+ else
24109+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
24110+ err = PTR_ERR(wh_dentry);
24111+ if (IS_ERR(wh_dentry))
24112+ goto out;
24113+
24114+ err = 0;
24115+ if (!wh_dentry->d_inode)
24116+ goto out_wh; /* success */
24117+
24118+ err = 1;
24119+ if (S_ISREG(wh_dentry->d_inode->i_mode))
24120+ goto out_wh; /* success */
24121+
24122+ err = -EIO;
24123+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
24124+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
24125+
24126+ out_wh:
24127+ dput(wh_dentry);
24128+ out:
24129+ return err;
24130+}
24131+
24132+/*
24133+ * test if the @h_dentry sets opaque or not.
24134+ */
24135+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
24136+{
24137+ int err;
24138+ struct inode *h_dir;
24139+
24140+ h_dir = h_dentry->d_inode;
24141+ err = au_wh_test(h_dentry, &diropq_name, br,
24142+ au_test_h_perm_sio(h_dir, MAY_EXEC));
24143+ return err;
24144+}
24145+
24146+/*
24147+ * returns a negative dentry whose name is unique and temporary.
24148+ */
24149+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
24150+ struct qstr *prefix)
24151+{
1facf9fc 24152+ struct dentry *dentry;
24153+ int i;
4a4d8108
AM
24154+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN_MIN + 1],
24155+ *name, *p;
1facf9fc 24156+ static unsigned short cnt;
24157+ struct qstr qs;
24158+
4a4d8108
AM
24159+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
24160+
1facf9fc 24161+ name = defname;
24162+ qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
24163+ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
24164+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 24165+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 24166+ goto out;
24167+ dentry = ERR_PTR(-ENOMEM);
24168+ name = kmalloc(qs.len + 1, GFP_NOFS);
24169+ if (unlikely(!name))
24170+ goto out;
24171+ }
24172+
24173+ /* doubly whiteout-ed */
24174+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
24175+ p = name + AUFS_WH_PFX_LEN * 2;
24176+ memcpy(p, prefix->name, prefix->len);
24177+ p += prefix->len;
24178+ *p++ = '.';
4a4d8108 24179+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 24180+
24181+ qs.name = name;
24182+ for (i = 0; i < 3; i++) {
4a4d8108 24183+ sprintf(p, "%.*d", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 24184+ dentry = au_sio_lkup_one(&qs, h_parent, br);
24185+ if (IS_ERR(dentry) || !dentry->d_inode)
24186+ goto out_name;
24187+ dput(dentry);
24188+ }
4a4d8108 24189+ /* pr_warning("could not get random name\n"); */
1facf9fc 24190+ dentry = ERR_PTR(-EEXIST);
24191+ AuDbg("%.*s\n", AuLNPair(&qs));
24192+ BUG();
24193+
24194+ out_name:
24195+ if (name != defname)
24196+ kfree(name);
24197+ out:
4a4d8108 24198+ AuTraceErrPtr(dentry);
1facf9fc 24199+ return dentry;
1facf9fc 24200+}
24201+
24202+/*
24203+ * rename the @h_dentry on @br to the whiteouted temporary name.
24204+ */
24205+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
24206+{
24207+ int err;
24208+ struct path h_path = {
24209+ .mnt = br->br_mnt
24210+ };
24211+ struct inode *h_dir;
24212+ struct dentry *h_parent;
24213+
24214+ h_parent = h_dentry->d_parent; /* dir inode is locked */
24215+ h_dir = h_parent->d_inode;
24216+ IMustLock(h_dir);
24217+
24218+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
24219+ err = PTR_ERR(h_path.dentry);
24220+ if (IS_ERR(h_path.dentry))
24221+ goto out;
24222+
24223+ /* under the same dir, no need to lock_rename() */
24224+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
24225+ AuTraceErr(err);
24226+ dput(h_path.dentry);
24227+
24228+ out:
4a4d8108 24229+ AuTraceErr(err);
1facf9fc 24230+ return err;
24231+}
24232+
24233+/* ---------------------------------------------------------------------- */
24234+/*
24235+ * functions for removing a whiteout
24236+ */
24237+
24238+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
24239+{
24240+ int force;
24241+
24242+ /*
24243+ * forces superio when the dir has a sticky bit.
24244+ * this may be a violation of unix fs semantics.
24245+ */
24246+ force = (h_dir->i_mode & S_ISVTX)
24247+ && h_path->dentry->d_inode->i_uid != current_fsuid();
24248+ return vfsub_unlink(h_dir, h_path, force);
24249+}
24250+
24251+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
24252+ struct dentry *dentry)
24253+{
24254+ int err;
24255+
24256+ err = do_unlink_wh(h_dir, h_path);
24257+ if (!err && dentry)
24258+ au_set_dbwh(dentry, -1);
24259+
24260+ return err;
24261+}
24262+
24263+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
24264+ struct au_branch *br)
24265+{
24266+ int err;
24267+ struct path h_path = {
24268+ .mnt = br->br_mnt
24269+ };
24270+
24271+ err = 0;
24272+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
24273+ if (IS_ERR(h_path.dentry))
24274+ err = PTR_ERR(h_path.dentry);
24275+ else {
24276+ if (h_path.dentry->d_inode
24277+ && S_ISREG(h_path.dentry->d_inode->i_mode))
24278+ err = do_unlink_wh(h_parent->d_inode, &h_path);
24279+ dput(h_path.dentry);
24280+ }
24281+
24282+ return err;
24283+}
24284+
24285+/* ---------------------------------------------------------------------- */
24286+/*
24287+ * initialize/clean whiteout for a branch
24288+ */
24289+
24290+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
24291+ const int isdir)
24292+{
24293+ int err;
24294+
24295+ if (!whpath->dentry->d_inode)
24296+ return;
24297+
24298+ err = mnt_want_write(whpath->mnt);
24299+ if (!err) {
24300+ if (isdir)
24301+ err = vfsub_rmdir(h_dir, whpath);
24302+ else
24303+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
24304+ mnt_drop_write(whpath->mnt);
24305+ }
24306+ if (unlikely(err))
4a4d8108
AM
24307+ pr_warning("failed removing %.*s (%d), ignored.\n",
24308+ AuDLNPair(whpath->dentry), err);
1facf9fc 24309+}
24310+
24311+static int test_linkable(struct dentry *h_root)
24312+{
24313+ struct inode *h_dir = h_root->d_inode;
24314+
24315+ if (h_dir->i_op->link)
24316+ return 0;
24317+
4a4d8108
AM
24318+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
24319+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 24320+ return -ENOSYS;
24321+}
24322+
24323+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
24324+static int au_whdir(struct inode *h_dir, struct path *path)
24325+{
24326+ int err;
24327+
24328+ err = -EEXIST;
24329+ if (!path->dentry->d_inode) {
24330+ int mode = S_IRWXU;
24331+
24332+ if (au_test_nfs(path->dentry->d_sb))
24333+ mode |= S_IXUGO;
24334+ err = mnt_want_write(path->mnt);
24335+ if (!err) {
24336+ err = vfsub_mkdir(h_dir, path, mode);
24337+ mnt_drop_write(path->mnt);
24338+ }
24339+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
24340+ err = 0;
24341+ else
4a4d8108 24342+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 24343+
24344+ return err;
24345+}
24346+
24347+struct au_wh_base {
24348+ const struct qstr *name;
24349+ struct dentry *dentry;
24350+};
24351+
24352+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
24353+ struct path *h_path)
24354+{
24355+ h_path->dentry = base[AuBrWh_BASE].dentry;
24356+ au_wh_clean(h_dir, h_path, /*isdir*/0);
24357+ h_path->dentry = base[AuBrWh_PLINK].dentry;
24358+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24359+ h_path->dentry = base[AuBrWh_ORPH].dentry;
24360+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24361+}
24362+
24363+/*
24364+ * returns tri-state,
24365+ * minus: error, caller should print the mesage
24366+ * zero: succuess
24367+ * plus: error, caller should NOT print the mesage
24368+ */
24369+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
24370+ int do_plink, struct au_wh_base base[],
24371+ struct path *h_path)
24372+{
24373+ int err;
24374+ struct inode *h_dir;
24375+
24376+ h_dir = h_root->d_inode;
24377+ h_path->dentry = base[AuBrWh_BASE].dentry;
24378+ au_wh_clean(h_dir, h_path, /*isdir*/0);
24379+ h_path->dentry = base[AuBrWh_PLINK].dentry;
24380+ if (do_plink) {
24381+ err = test_linkable(h_root);
24382+ if (unlikely(err)) {
24383+ err = 1;
24384+ goto out;
24385+ }
24386+
24387+ err = au_whdir(h_dir, h_path);
24388+ if (unlikely(err))
24389+ goto out;
24390+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
24391+ } else
24392+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24393+ h_path->dentry = base[AuBrWh_ORPH].dentry;
24394+ err = au_whdir(h_dir, h_path);
24395+ if (unlikely(err))
24396+ goto out;
24397+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
24398+
24399+ out:
24400+ return err;
24401+}
24402+
24403+/*
24404+ * for the moment, aufs supports the branch filesystem which does not support
24405+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
24406+ * copyup failed. finally, such filesystem will not be used as the writable
24407+ * branch.
24408+ *
24409+ * returns tri-state, see above.
24410+ */
24411+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
24412+ int do_plink, struct au_wh_base base[],
24413+ struct path *h_path)
24414+{
24415+ int err;
24416+ struct inode *h_dir;
24417+
1308ab2a 24418+ WbrWhMustWriteLock(wbr);
24419+
1facf9fc 24420+ err = test_linkable(h_root);
24421+ if (unlikely(err)) {
24422+ err = 1;
24423+ goto out;
24424+ }
24425+
24426+ /*
24427+ * todo: should this create be done in /sbin/mount.aufs helper?
24428+ */
24429+ err = -EEXIST;
24430+ h_dir = h_root->d_inode;
24431+ if (!base[AuBrWh_BASE].dentry->d_inode) {
24432+ err = mnt_want_write(h_path->mnt);
24433+ if (!err) {
24434+ h_path->dentry = base[AuBrWh_BASE].dentry;
24435+ err = vfsub_create(h_dir, h_path, WH_MASK);
24436+ mnt_drop_write(h_path->mnt);
24437+ }
24438+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
24439+ err = 0;
24440+ else
4a4d8108
AM
24441+ pr_err("unknown %.*s/%.*s exists\n",
24442+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 24443+ if (unlikely(err))
24444+ goto out;
24445+
24446+ h_path->dentry = base[AuBrWh_PLINK].dentry;
24447+ if (do_plink) {
24448+ err = au_whdir(h_dir, h_path);
24449+ if (unlikely(err))
24450+ goto out;
24451+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
24452+ } else
24453+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24454+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
24455+
24456+ h_path->dentry = base[AuBrWh_ORPH].dentry;
24457+ err = au_whdir(h_dir, h_path);
24458+ if (unlikely(err))
24459+ goto out;
24460+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
24461+
24462+ out:
24463+ return err;
24464+}
24465+
24466+/*
24467+ * initialize the whiteout base file/dir for @br.
24468+ */
24469+int au_wh_init(struct dentry *h_root, struct au_branch *br,
24470+ struct super_block *sb)
24471+{
24472+ int err, i;
24473+ const unsigned char do_plink
24474+ = !!au_opt_test(au_mntflags(sb), PLINK);
24475+ struct path path = {
24476+ .mnt = br->br_mnt
24477+ };
24478+ struct inode *h_dir;
24479+ struct au_wbr *wbr = br->br_wbr;
24480+ static const struct qstr base_name[] = {
24481+ [AuBrWh_BASE] = {
24482+ .name = AUFS_BASE_NAME,
24483+ .len = sizeof(AUFS_BASE_NAME) - 1
24484+ },
24485+ [AuBrWh_PLINK] = {
24486+ .name = AUFS_PLINKDIR_NAME,
24487+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
24488+ },
24489+ [AuBrWh_ORPH] = {
24490+ .name = AUFS_ORPHDIR_NAME,
24491+ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
24492+ }
24493+ };
24494+ struct au_wh_base base[] = {
24495+ [AuBrWh_BASE] = {
24496+ .name = base_name + AuBrWh_BASE,
24497+ .dentry = NULL
24498+ },
24499+ [AuBrWh_PLINK] = {
24500+ .name = base_name + AuBrWh_PLINK,
24501+ .dentry = NULL
24502+ },
24503+ [AuBrWh_ORPH] = {
24504+ .name = base_name + AuBrWh_ORPH,
24505+ .dentry = NULL
24506+ }
24507+ };
24508+
1308ab2a 24509+ if (wbr)
24510+ WbrWhMustWriteLock(wbr);
1facf9fc 24511+
1facf9fc 24512+ for (i = 0; i < AuBrWh_Last; i++) {
24513+ /* doubly whiteouted */
24514+ struct dentry *d;
24515+
24516+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
24517+ err = PTR_ERR(d);
24518+ if (IS_ERR(d))
24519+ goto out;
24520+
24521+ base[i].dentry = d;
24522+ AuDebugOn(wbr
24523+ && wbr->wbr_wh[i]
24524+ && wbr->wbr_wh[i] != base[i].dentry);
24525+ }
24526+
24527+ if (wbr)
24528+ for (i = 0; i < AuBrWh_Last; i++) {
24529+ dput(wbr->wbr_wh[i]);
24530+ wbr->wbr_wh[i] = NULL;
24531+ }
24532+
24533+ err = 0;
1facf9fc 24534+ switch (br->br_perm) {
24535+ case AuBrPerm_RO:
24536+ case AuBrPerm_ROWH:
24537+ case AuBrPerm_RR:
24538+ case AuBrPerm_RRWH:
4a4d8108 24539+ h_dir = h_root->d_inode;
1facf9fc 24540+ au_wh_init_ro(h_dir, base, &path);
24541+ break;
24542+
24543+ case AuBrPerm_RWNoLinkWH:
24544+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
24545+ if (err > 0)
24546+ goto out;
24547+ else if (err)
24548+ goto out_err;
24549+ break;
24550+
24551+ case AuBrPerm_RW:
24552+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
24553+ if (err > 0)
24554+ goto out;
24555+ else if (err)
24556+ goto out_err;
24557+ break;
24558+
24559+ default:
24560+ BUG();
24561+ }
24562+ goto out; /* success */
24563+
24564+ out_err:
4a4d8108
AM
24565+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
24566+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 24567+ out:
24568+ for (i = 0; i < AuBrWh_Last; i++)
24569+ dput(base[i].dentry);
24570+ return err;
24571+}
24572+
24573+/* ---------------------------------------------------------------------- */
24574+/*
24575+ * whiteouts are all hard-linked usually.
24576+ * when its link count reaches a ceiling, we create a new whiteout base
24577+ * asynchronously.
24578+ */
24579+
24580+struct reinit_br_wh {
24581+ struct super_block *sb;
24582+ struct au_branch *br;
24583+};
24584+
24585+static void reinit_br_wh(void *arg)
24586+{
24587+ int err;
24588+ aufs_bindex_t bindex;
24589+ struct path h_path;
24590+ struct reinit_br_wh *a = arg;
24591+ struct au_wbr *wbr;
24592+ struct inode *dir;
24593+ struct dentry *h_root;
24594+ struct au_hinode *hdir;
24595+
24596+ err = 0;
24597+ wbr = a->br->br_wbr;
24598+ /* big aufs lock */
24599+ si_noflush_write_lock(a->sb);
24600+ if (!au_br_writable(a->br->br_perm))
24601+ goto out;
24602+ bindex = au_br_index(a->sb, a->br->br_id);
24603+ if (unlikely(bindex < 0))
24604+ goto out;
24605+
1308ab2a 24606+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 24607+ dir = a->sb->s_root->d_inode;
1facf9fc 24608+ hdir = au_hi(dir, bindex);
24609+ h_root = au_h_dptr(a->sb->s_root, bindex);
24610+
4a4d8108 24611+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 24612+ wbr_wh_write_lock(wbr);
24613+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
24614+ h_root, a->br);
24615+ if (!err) {
24616+ err = mnt_want_write(a->br->br_mnt);
24617+ if (!err) {
24618+ h_path.dentry = wbr->wbr_whbase;
24619+ h_path.mnt = a->br->br_mnt;
24620+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
24621+ mnt_drop_write(a->br->br_mnt);
24622+ }
24623+ } else {
4a4d8108
AM
24624+ pr_warning("%.*s is moved, ignored\n",
24625+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 24626+ err = 0;
24627+ }
24628+ dput(wbr->wbr_whbase);
24629+ wbr->wbr_whbase = NULL;
24630+ if (!err)
24631+ err = au_wh_init(h_root, a->br, a->sb);
24632+ wbr_wh_write_unlock(wbr);
4a4d8108 24633+ au_hn_imtx_unlock(hdir);
1308ab2a 24634+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 24635+
24636+ out:
24637+ if (wbr)
24638+ atomic_dec(&wbr->wbr_wh_running);
24639+ atomic_dec(&a->br->br_count);
24640+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
24641+ si_write_unlock(a->sb);
24642+ kfree(arg);
24643+ if (unlikely(err))
24644+ AuIOErr("err %d\n", err);
24645+}
24646+
24647+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
24648+{
24649+ int do_dec, wkq_err;
24650+ struct reinit_br_wh *arg;
24651+
24652+ do_dec = 1;
24653+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
24654+ goto out;
24655+
24656+ /* ignore ENOMEM */
24657+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
24658+ if (arg) {
24659+ /*
24660+ * dec(wh_running), kfree(arg) and dec(br_count)
24661+ * in reinit function
24662+ */
24663+ arg->sb = sb;
24664+ arg->br = br;
24665+ atomic_inc(&br->br_count);
24666+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
24667+ if (unlikely(wkq_err)) {
24668+ atomic_dec(&br->br_wbr->wbr_wh_running);
24669+ atomic_dec(&br->br_count);
24670+ kfree(arg);
24671+ }
24672+ do_dec = 0;
24673+ }
24674+
24675+ out:
24676+ if (do_dec)
24677+ atomic_dec(&br->br_wbr->wbr_wh_running);
24678+}
24679+
24680+/* ---------------------------------------------------------------------- */
24681+
24682+/*
24683+ * create the whiteout @wh.
24684+ */
24685+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
24686+ struct dentry *wh)
24687+{
24688+ int err;
24689+ struct path h_path = {
24690+ .dentry = wh
24691+ };
24692+ struct au_branch *br;
24693+ struct au_wbr *wbr;
24694+ struct dentry *h_parent;
24695+ struct inode *h_dir;
24696+
24697+ h_parent = wh->d_parent; /* dir inode is locked */
24698+ h_dir = h_parent->d_inode;
24699+ IMustLock(h_dir);
24700+
24701+ br = au_sbr(sb, bindex);
24702+ h_path.mnt = br->br_mnt;
24703+ wbr = br->br_wbr;
24704+ wbr_wh_read_lock(wbr);
24705+ if (wbr->wbr_whbase) {
24706+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
24707+ if (!err || err != -EMLINK)
24708+ goto out;
24709+
24710+ /* link count full. re-initialize br_whbase. */
24711+ kick_reinit_br_wh(sb, br);
24712+ }
24713+
24714+ /* return this error in this context */
24715+ err = vfsub_create(h_dir, &h_path, WH_MASK);
24716+
24717+ out:
24718+ wbr_wh_read_unlock(wbr);
24719+ return err;
24720+}
24721+
24722+/* ---------------------------------------------------------------------- */
24723+
24724+/*
24725+ * create or remove the diropq.
24726+ */
24727+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
24728+ unsigned int flags)
24729+{
24730+ struct dentry *opq_dentry, *h_dentry;
24731+ struct super_block *sb;
24732+ struct au_branch *br;
24733+ int err;
24734+
24735+ sb = dentry->d_sb;
24736+ br = au_sbr(sb, bindex);
24737+ h_dentry = au_h_dptr(dentry, bindex);
24738+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
24739+ if (IS_ERR(opq_dentry))
24740+ goto out;
24741+
24742+ if (au_ftest_diropq(flags, CREATE)) {
24743+ err = link_or_create_wh(sb, bindex, opq_dentry);
24744+ if (!err) {
24745+ au_set_dbdiropq(dentry, bindex);
24746+ goto out; /* success */
24747+ }
24748+ } else {
24749+ struct path tmp = {
24750+ .dentry = opq_dentry,
24751+ .mnt = br->br_mnt
24752+ };
24753+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
24754+ if (!err)
24755+ au_set_dbdiropq(dentry, -1);
24756+ }
24757+ dput(opq_dentry);
24758+ opq_dentry = ERR_PTR(err);
24759+
24760+ out:
24761+ return opq_dentry;
24762+}
24763+
24764+struct do_diropq_args {
24765+ struct dentry **errp;
24766+ struct dentry *dentry;
24767+ aufs_bindex_t bindex;
24768+ unsigned int flags;
24769+};
24770+
24771+static void call_do_diropq(void *args)
24772+{
24773+ struct do_diropq_args *a = args;
24774+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
24775+}
24776+
24777+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
24778+ unsigned int flags)
24779+{
24780+ struct dentry *diropq, *h_dentry;
24781+
24782+ h_dentry = au_h_dptr(dentry, bindex);
24783+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
24784+ diropq = do_diropq(dentry, bindex, flags);
24785+ else {
24786+ int wkq_err;
24787+ struct do_diropq_args args = {
24788+ .errp = &diropq,
24789+ .dentry = dentry,
24790+ .bindex = bindex,
24791+ .flags = flags
24792+ };
24793+
24794+ wkq_err = au_wkq_wait(call_do_diropq, &args);
24795+ if (unlikely(wkq_err))
24796+ diropq = ERR_PTR(wkq_err);
24797+ }
24798+
24799+ return diropq;
24800+}
24801+
24802+/* ---------------------------------------------------------------------- */
24803+
24804+/*
24805+ * lookup whiteout dentry.
24806+ * @h_parent: lower parent dentry which must exist and be locked
24807+ * @base_name: name of dentry which will be whiteouted
24808+ * returns dentry for whiteout.
24809+ */
24810+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
24811+ struct au_branch *br)
24812+{
24813+ int err;
24814+ struct qstr wh_name;
24815+ struct dentry *wh_dentry;
24816+
24817+ err = au_wh_name_alloc(&wh_name, base_name);
24818+ wh_dentry = ERR_PTR(err);
24819+ if (!err) {
24820+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
24821+ kfree(wh_name.name);
24822+ }
24823+ return wh_dentry;
24824+}
24825+
24826+/*
24827+ * link/create a whiteout for @dentry on @bindex.
24828+ */
24829+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
24830+ struct dentry *h_parent)
24831+{
24832+ struct dentry *wh_dentry;
24833+ struct super_block *sb;
24834+ int err;
24835+
24836+ sb = dentry->d_sb;
24837+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
24838+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
24839+ err = link_or_create_wh(sb, bindex, wh_dentry);
24840+ if (!err)
24841+ au_set_dbwh(dentry, bindex);
24842+ else {
24843+ dput(wh_dentry);
24844+ wh_dentry = ERR_PTR(err);
24845+ }
24846+ }
24847+
24848+ return wh_dentry;
24849+}
24850+
24851+/* ---------------------------------------------------------------------- */
24852+
24853+/* Delete all whiteouts in this directory on branch bindex. */
24854+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
24855+ aufs_bindex_t bindex, struct au_branch *br)
24856+{
24857+ int err;
24858+ unsigned long ul, n;
24859+ struct qstr wh_name;
24860+ char *p;
24861+ struct hlist_head *head;
24862+ struct au_vdir_wh *tpos;
24863+ struct hlist_node *pos;
24864+ struct au_vdir_destr *str;
24865+
24866+ err = -ENOMEM;
4a4d8108 24867+ p = __getname_gfp(GFP_NOFS);
1facf9fc 24868+ wh_name.name = p;
24869+ if (unlikely(!wh_name.name))
24870+ goto out;
24871+
24872+ err = 0;
24873+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
24874+ p += AUFS_WH_PFX_LEN;
24875+ n = whlist->nh_num;
24876+ head = whlist->nh_head;
24877+ for (ul = 0; !err && ul < n; ul++, head++) {
24878+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
24879+ if (tpos->wh_bindex != bindex)
24880+ continue;
24881+
24882+ str = &tpos->wh_str;
24883+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
24884+ memcpy(p, str->name, str->len);
24885+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
24886+ err = unlink_wh_name(h_dentry, &wh_name, br);
24887+ if (!err)
24888+ continue;
24889+ break;
24890+ }
24891+ AuIOErr("whiteout name too long %.*s\n",
24892+ str->len, str->name);
24893+ err = -EIO;
24894+ break;
24895+ }
24896+ }
24897+ __putname(wh_name.name);
24898+
24899+ out:
24900+ return err;
24901+}
24902+
24903+struct del_wh_children_args {
24904+ int *errp;
24905+ struct dentry *h_dentry;
1308ab2a 24906+ struct au_nhash *whlist;
1facf9fc 24907+ aufs_bindex_t bindex;
24908+ struct au_branch *br;
24909+};
24910+
24911+static void call_del_wh_children(void *args)
24912+{
24913+ struct del_wh_children_args *a = args;
1308ab2a 24914+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 24915+}
24916+
24917+/* ---------------------------------------------------------------------- */
24918+
24919+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
24920+{
24921+ struct au_whtmp_rmdir *whtmp;
dece6358 24922+ int err;
1308ab2a 24923+ unsigned int rdhash;
dece6358
AM
24924+
24925+ SiMustAnyLock(sb);
1facf9fc 24926+
24927+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
24928+ if (unlikely(!whtmp)) {
24929+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 24930+ goto out;
dece6358 24931+ }
1facf9fc 24932+
24933+ whtmp->dir = NULL;
24934+ whtmp->wh_dentry = NULL;
1308ab2a 24935+ /* no estimation for dir size */
24936+ rdhash = au_sbi(sb)->si_rdhash;
24937+ if (!rdhash)
24938+ rdhash = AUFS_RDHASH_DEF;
24939+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
24940+ if (unlikely(err)) {
24941+ kfree(whtmp);
24942+ whtmp = ERR_PTR(err);
24943+ }
dece6358 24944+
1facf9fc 24945+ out:
dece6358 24946+ return whtmp;
1facf9fc 24947+}
24948+
24949+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
24950+{
24951+ dput(whtmp->wh_dentry);
24952+ iput(whtmp->dir);
dece6358 24953+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 24954+ kfree(whtmp);
24955+}
24956+
24957+/*
24958+ * rmdir the whiteouted temporary named dir @h_dentry.
24959+ * @whlist: whiteouted children.
24960+ */
24961+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
24962+ struct dentry *wh_dentry, struct au_nhash *whlist)
24963+{
24964+ int err;
24965+ struct path h_tmp;
24966+ struct inode *wh_inode, *h_dir;
24967+ struct au_branch *br;
24968+
24969+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
24970+ IMustLock(h_dir);
24971+
24972+ br = au_sbr(dir->i_sb, bindex);
24973+ wh_inode = wh_dentry->d_inode;
24974+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
24975+
24976+ /*
24977+ * someone else might change some whiteouts while we were sleeping.
24978+ * it means this whlist may have an obsoleted entry.
24979+ */
24980+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
24981+ err = del_wh_children(wh_dentry, whlist, bindex, br);
24982+ else {
24983+ int wkq_err;
24984+ struct del_wh_children_args args = {
24985+ .errp = &err,
24986+ .h_dentry = wh_dentry,
1308ab2a 24987+ .whlist = whlist,
1facf9fc 24988+ .bindex = bindex,
24989+ .br = br
24990+ };
24991+
24992+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
24993+ if (unlikely(wkq_err))
24994+ err = wkq_err;
24995+ }
24996+ mutex_unlock(&wh_inode->i_mutex);
24997+
24998+ if (!err) {
24999+ h_tmp.dentry = wh_dentry;
25000+ h_tmp.mnt = br->br_mnt;
25001+ err = vfsub_rmdir(h_dir, &h_tmp);
25002+ /* d_drop(h_dentry); */
25003+ }
25004+
25005+ if (!err) {
25006+ if (au_ibstart(dir) == bindex) {
25007+ au_cpup_attr_timesizes(dir);
25008+ drop_nlink(dir);
25009+ }
25010+ return 0; /* success */
25011+ }
25012+
4a4d8108
AM
25013+ pr_warning("failed removing %.*s(%d), ignored\n",
25014+ AuDLNPair(wh_dentry), err);
1facf9fc 25015+ return err;
25016+}
25017+
25018+static void call_rmdir_whtmp(void *args)
25019+{
25020+ int err;
25021+ struct au_whtmp_rmdir *a = args;
25022+ struct super_block *sb;
25023+ struct dentry *h_parent;
25024+ struct inode *h_dir;
25025+ struct au_branch *br;
25026+ struct au_hinode *hdir;
25027+
25028+ /* rmdir by nfsd may cause deadlock with this i_mutex */
25029+ /* mutex_lock(&a->dir->i_mutex); */
25030+ sb = a->dir->i_sb;
25031+ si_noflush_read_lock(sb);
25032+ err = au_test_ro(sb, a->bindex, NULL);
25033+ if (unlikely(err))
25034+ goto out;
25035+
25036+ err = -EIO;
25037+ br = au_sbr(sb, a->bindex);
25038+ ii_write_lock_parent(a->dir);
25039+ h_parent = dget_parent(a->wh_dentry);
25040+ h_dir = h_parent->d_inode;
25041+ hdir = au_hi(a->dir, a->bindex);
4a4d8108 25042+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 25043+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, br);
25044+ if (!err) {
25045+ err = mnt_want_write(br->br_mnt);
25046+ if (!err) {
25047+ err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
dece6358 25048+ &a->whlist);
1facf9fc 25049+ mnt_drop_write(br->br_mnt);
25050+ }
25051+ }
4a4d8108 25052+ au_hn_imtx_unlock(hdir);
1facf9fc 25053+ dput(h_parent);
25054+ ii_write_unlock(a->dir);
25055+
25056+ out:
25057+ /* mutex_unlock(&a->dir->i_mutex); */
25058+ au_nwt_done(&au_sbi(sb)->si_nowait);
25059+ si_read_unlock(sb);
25060+ au_whtmp_rmdir_free(a);
25061+ if (unlikely(err))
25062+ AuIOErr("err %d\n", err);
25063+}
25064+
25065+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
25066+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
25067+{
25068+ int wkq_err;
25069+
25070+ IMustLock(dir);
25071+
25072+ /* all post-process will be done in do_rmdir_whtmp(). */
25073+ args->dir = au_igrab(dir);
25074+ args->bindex = bindex;
25075+ args->wh_dentry = dget(wh_dentry);
25076+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
25077+ if (unlikely(wkq_err)) {
4a4d8108
AM
25078+ pr_warning("rmdir error %.*s (%d), ignored\n",
25079+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 25080+ au_whtmp_rmdir_free(args);
25081+ }
25082+}
4a4d8108
AM
25083diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/whout.h linux-2.6.34/fs/aufs/whout.h
25084--- linux-2.6.34.org/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
25085+++ linux-2.6.34/fs/aufs/whout.h 2010-05-31 22:15:32.000000000 +0200
dece6358 25086@@ -0,0 +1,87 @@
1facf9fc 25087+/*
4a4d8108 25088+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25089+ *
25090+ * This program, aufs is free software; you can redistribute it and/or modify
25091+ * it under the terms of the GNU General Public License as published by
25092+ * the Free Software Foundation; either version 2 of the License, or
25093+ * (at your option) any later version.
dece6358
AM
25094+ *
25095+ * This program is distributed in the hope that it will be useful,
25096+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25097+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25098+ * GNU General Public License for more details.
25099+ *
25100+ * You should have received a copy of the GNU General Public License
25101+ * along with this program; if not, write to the Free Software
25102+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25103+ */
25104+
25105+/*
25106+ * whiteout for logical deletion and opaque directory
25107+ */
25108+
25109+#ifndef __AUFS_WHOUT_H__
25110+#define __AUFS_WHOUT_H__
25111+
25112+#ifdef __KERNEL__
25113+
1facf9fc 25114+#include <linux/aufs_type.h>
25115+#include "dir.h"
25116+
25117+/* whout.c */
25118+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
25119+struct au_branch;
25120+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
25121+ struct au_branch *br, int try_sio);
25122+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
25123+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
25124+ struct qstr *prefix);
25125+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
25126+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
25127+ struct dentry *dentry);
25128+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
25129+ struct super_block *sb);
25130+
25131+/* diropq flags */
25132+#define AuDiropq_CREATE 1
25133+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
25134+#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
25135+#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
25136+
25137+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
25138+ unsigned int flags);
25139+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
25140+ struct au_branch *br);
25141+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
25142+ struct dentry *h_parent);
25143+
25144+/* real rmdir for the whiteout-ed dir */
25145+struct au_whtmp_rmdir {
25146+ struct inode *dir;
25147+ aufs_bindex_t bindex;
25148+ struct dentry *wh_dentry;
dece6358 25149+ struct au_nhash whlist;
1facf9fc 25150+};
25151+
25152+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
25153+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
25154+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
25155+ struct dentry *wh_dentry, struct au_nhash *whlist);
25156+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
25157+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
25158+
25159+/* ---------------------------------------------------------------------- */
25160+
25161+static inline struct dentry *au_diropq_create(struct dentry *dentry,
25162+ aufs_bindex_t bindex)
25163+{
25164+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
25165+}
25166+
25167+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
25168+{
25169+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
25170+}
25171+
25172+#endif /* __KERNEL__ */
25173+#endif /* __AUFS_WHOUT_H__ */
4a4d8108
AM
25174diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/wkq.c linux-2.6.34/fs/aufs/wkq.c
25175--- linux-2.6.34.org/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
25176+++ linux-2.6.34/fs/aufs/wkq.c 2010-05-31 22:15:32.000000000 +0200
25177@@ -0,0 +1,183 @@
1facf9fc 25178+/*
4a4d8108 25179+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25180+ *
25181+ * This program, aufs is free software; you can redistribute it and/or modify
25182+ * it under the terms of the GNU General Public License as published by
25183+ * the Free Software Foundation; either version 2 of the License, or
25184+ * (at your option) any later version.
dece6358
AM
25185+ *
25186+ * This program is distributed in the hope that it will be useful,
25187+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25188+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25189+ * GNU General Public License for more details.
25190+ *
25191+ * You should have received a copy of the GNU General Public License
25192+ * along with this program; if not, write to the Free Software
25193+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25194+ */
25195+
25196+/*
25197+ * workqueue for asynchronous/super-io operations
25198+ * todo: try new dredential scheme
25199+ */
25200+
dece6358 25201+#include <linux/module.h>
1facf9fc 25202+#include "aufs.h"
25203+
25204+/* internal workqueue named AUFS_WKQ_NAME */
4a4d8108 25205+static struct workqueue_struct *au_wkq;
1facf9fc 25206+
25207+struct au_wkinfo {
25208+ struct work_struct wk;
25209+ struct super_block *sb;
25210+
25211+ unsigned int flags; /* see wkq.h */
25212+
25213+ au_wkq_func_t func;
25214+ void *args;
25215+
1facf9fc 25216+ struct completion *comp;
25217+};
25218+
25219+/* ---------------------------------------------------------------------- */
25220+
1facf9fc 25221+static void wkq_func(struct work_struct *wk)
25222+{
25223+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
25224+
25225+ wkinfo->func(wkinfo->args);
1facf9fc 25226+ if (au_ftest_wkq(wkinfo->flags, WAIT))
25227+ complete(wkinfo->comp);
25228+ else {
25229+ kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
25230+ module_put(THIS_MODULE);
25231+ kfree(wkinfo);
25232+ }
25233+}
25234+
25235+/*
25236+ * Since struct completion is large, try allocating it dynamically.
25237+ */
25238+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
25239+#define AuWkqCompDeclare(name) struct completion *comp = NULL
25240+
25241+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
25242+{
25243+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
25244+ if (*comp) {
25245+ init_completion(*comp);
25246+ wkinfo->comp = *comp;
25247+ return 0;
25248+ }
25249+ return -ENOMEM;
25250+}
25251+
25252+static void au_wkq_comp_free(struct completion *comp)
25253+{
25254+ kfree(comp);
25255+}
25256+
25257+#else
25258+
25259+/* no braces */
25260+#define AuWkqCompDeclare(name) \
25261+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
25262+ struct completion *comp = &_ ## name
25263+
25264+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
25265+{
25266+ wkinfo->comp = *comp;
25267+ return 0;
25268+}
25269+
25270+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
25271+{
25272+ /* empty */
25273+}
25274+#endif /* 4KSTACKS */
25275+
4a4d8108 25276+static void au_wkq_run(struct au_wkinfo *wkinfo, int do_wait)
1facf9fc 25277+{
25278+ au_dbg_verify_kthread();
4a4d8108
AM
25279+ if (do_wait) {
25280+ INIT_WORK_ON_STACK(&wkinfo->wk, wkq_func);
25281+ queue_work(au_wkq, &wkinfo->wk);
25282+ } else {
25283+ INIT_WORK(&wkinfo->wk, wkq_func);
25284+ schedule_work(&wkinfo->wk);
25285+ }
1facf9fc 25286+}
25287+
25288+int au_wkq_wait(au_wkq_func_t func, void *args)
25289+{
25290+ int err;
25291+ AuWkqCompDeclare(comp);
25292+ struct au_wkinfo wkinfo = {
25293+ .flags = AuWkq_WAIT,
25294+ .func = func,
25295+ .args = args
25296+ };
25297+
25298+ err = au_wkq_comp_alloc(&wkinfo, &comp);
25299+ if (!err) {
4a4d8108 25300+ au_wkq_run(&wkinfo, AuWkq_WAIT);
1facf9fc 25301+ /* no timeout, no interrupt */
25302+ wait_for_completion(wkinfo.comp);
25303+ au_wkq_comp_free(comp);
4a4d8108 25304+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 25305+ }
25306+
25307+ return err;
25308+
25309+}
25310+
25311+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
25312+{
25313+ int err;
25314+ struct au_wkinfo *wkinfo;
25315+
25316+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
25317+
25318+ /*
25319+ * wkq_func() must free this wkinfo.
25320+ * it highly depends upon the implementation of workqueue.
25321+ */
25322+ err = 0;
25323+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
25324+ if (wkinfo) {
25325+ wkinfo->sb = sb;
25326+ wkinfo->flags = !AuWkq_WAIT;
25327+ wkinfo->func = func;
25328+ wkinfo->args = args;
25329+ wkinfo->comp = NULL;
25330+ kobject_get(&au_sbi(sb)->si_kobj);
25331+ __module_get(THIS_MODULE);
25332+
4a4d8108 25333+ au_wkq_run(wkinfo, !AuWkq_WAIT);
1facf9fc 25334+ } else {
25335+ err = -ENOMEM;
25336+ atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
25337+ }
25338+
25339+ return err;
25340+}
25341+
25342+/* ---------------------------------------------------------------------- */
25343+
25344+void au_nwt_init(struct au_nowait_tasks *nwt)
25345+{
25346+ atomic_set(&nwt->nw_len, 0);
4a4d8108 25347+ /* smp_mb(); */ /* atomic_set */
1facf9fc 25348+ init_waitqueue_head(&nwt->nw_wq);
25349+}
25350+
25351+void au_wkq_fin(void)
25352+{
4a4d8108 25353+ destroy_workqueue(au_wkq);
1facf9fc 25354+}
25355+
25356+int __init au_wkq_init(void)
25357+{
4a4d8108
AM
25358+ au_wkq = create_workqueue(AUFS_WKQ_NAME);
25359+ return 0;
1facf9fc 25360+}
4a4d8108
AM
25361diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/wkq.h linux-2.6.34/fs/aufs/wkq.h
25362--- linux-2.6.34.org/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
25363+++ linux-2.6.34/fs/aufs/wkq.h 2010-05-31 22:15:32.000000000 +0200
25364@@ -0,0 +1,84 @@
1facf9fc 25365+/*
4a4d8108 25366+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25367+ *
25368+ * This program, aufs is free software; you can redistribute it and/or modify
25369+ * it under the terms of the GNU General Public License as published by
25370+ * the Free Software Foundation; either version 2 of the License, or
25371+ * (at your option) any later version.
dece6358
AM
25372+ *
25373+ * This program is distributed in the hope that it will be useful,
25374+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25375+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25376+ * GNU General Public License for more details.
25377+ *
25378+ * You should have received a copy of the GNU General Public License
25379+ * along with this program; if not, write to the Free Software
25380+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25381+ */
25382+
25383+/*
25384+ * workqueue for asynchronous/super-io operations
25385+ * todo: try new credentials management scheme
25386+ */
25387+
25388+#ifndef __AUFS_WKQ_H__
25389+#define __AUFS_WKQ_H__
25390+
25391+#ifdef __KERNEL__
25392+
1facf9fc 25393+#include <linux/sched.h>
dece6358 25394+#include <linux/wait.h>
1facf9fc 25395+#include <linux/aufs_type.h>
25396+
dece6358
AM
25397+struct super_block;
25398+
1facf9fc 25399+/* ---------------------------------------------------------------------- */
25400+
25401+/*
25402+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
25403+ */
25404+struct au_nowait_tasks {
25405+ atomic_t nw_len;
25406+ wait_queue_head_t nw_wq;
25407+};
25408+
25409+/* ---------------------------------------------------------------------- */
25410+
25411+typedef void (*au_wkq_func_t)(void *args);
25412+
25413+/* wkq flags */
25414+#define AuWkq_WAIT 1
25415+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
25416+#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
25417+#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
25418+
25419+/* wkq.c */
25420+int au_wkq_wait(au_wkq_func_t func, void *args);
25421+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
25422+void au_nwt_init(struct au_nowait_tasks *nwt);
25423+int __init au_wkq_init(void);
25424+void au_wkq_fin(void);
25425+
25426+/* ---------------------------------------------------------------------- */
25427+
25428+static inline int au_test_wkq(struct task_struct *tsk)
25429+{
4a4d8108
AM
25430+ return !tsk->mm
25431+ && !strncmp(tsk->comm, AUFS_WKQ_NAME "/",
25432+ sizeof(AUFS_WKQ_NAME));
1facf9fc 25433+}
25434+
25435+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
25436+{
25437+ if (!atomic_dec_return(&nwt->nw_len))
25438+ wake_up_all(&nwt->nw_wq);
25439+}
25440+
25441+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
25442+{
25443+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
25444+ return 0;
25445+}
25446+
25447+#endif /* __KERNEL__ */
25448+#endif /* __AUFS_WKQ_H__ */
4a4d8108
AM
25449diff -urN --exclude '*.orig' linux-2.6.34.org/fs/aufs/xino.c linux-2.6.34/fs/aufs/xino.c
25450--- linux-2.6.34.org/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
25451+++ linux-2.6.34/fs/aufs/xino.c 2010-05-31 22:15:32.000000000 +0200
25452@@ -0,0 +1,1202 @@
1facf9fc 25453+/*
4a4d8108 25454+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25455+ *
25456+ * This program, aufs is free software; you can redistribute it and/or modify
25457+ * it under the terms of the GNU General Public License as published by
25458+ * the Free Software Foundation; either version 2 of the License, or
25459+ * (at your option) any later version.
dece6358
AM
25460+ *
25461+ * This program is distributed in the hope that it will be useful,
25462+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25463+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25464+ * GNU General Public License for more details.
25465+ *
25466+ * You should have received a copy of the GNU General Public License
25467+ * along with this program; if not, write to the Free Software
25468+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25469+ */
25470+
25471+/*
25472+ * external inode number translation table and bitmap
25473+ */
25474+
dece6358 25475+#include <linux/file.h>
1facf9fc 25476+#include <linux/seq_file.h>
25477+#include <linux/uaccess.h>
25478+#include "aufs.h"
25479+
25480+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
25481+ loff_t *pos)
25482+{
25483+ ssize_t err;
25484+ mm_segment_t oldfs;
25485+
25486+ oldfs = get_fs();
25487+ set_fs(KERNEL_DS);
25488+ do {
25489+ /* todo: signal_pending? */
25490+ err = func(file, (char __user *)buf, size, pos);
25491+ } while (err == -EAGAIN || err == -EINTR);
25492+ set_fs(oldfs);
25493+
25494+#if 0 /* reserved for future use */
25495+ if (err > 0)
25496+ fsnotify_access(file->f_dentry);
25497+#endif
25498+
25499+ return err;
25500+}
25501+
25502+/* ---------------------------------------------------------------------- */
25503+
25504+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
25505+ size_t size, loff_t *pos)
25506+{
25507+ ssize_t err;
25508+ mm_segment_t oldfs;
25509+
25510+ oldfs = get_fs();
25511+ set_fs(KERNEL_DS);
4a4d8108 25512+ /* lockdep_off(); */
1facf9fc 25513+ do {
25514+ /* todo: signal_pending? */
25515+ err = func(file, (const char __user *)buf, size, pos);
25516+ } while (err == -EAGAIN || err == -EINTR);
4a4d8108 25517+ /* lockdep_on(); */
1facf9fc 25518+ set_fs(oldfs);
25519+
25520+#if 0 /* reserved for future use */
25521+ if (err > 0)
25522+ fsnotify_modify(file->f_dentry);
25523+#endif
25524+
25525+ return err;
25526+}
25527+
25528+struct do_xino_fwrite_args {
25529+ ssize_t *errp;
25530+ au_writef_t func;
25531+ struct file *file;
25532+ void *buf;
25533+ size_t size;
25534+ loff_t *pos;
25535+};
25536+
25537+static void call_do_xino_fwrite(void *args)
25538+{
25539+ struct do_xino_fwrite_args *a = args;
25540+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
25541+}
25542+
25543+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
25544+ loff_t *pos)
25545+{
25546+ ssize_t err;
25547+
25548+ /* todo: signal block and no wkq? */
25549+ /* todo: new credential scheme */
25550+ /*
25551+ * it breaks RLIMIT_FSIZE and normal user's limit,
25552+ * users should care about quota and real 'filesystem full.'
25553+ */
25554+ if (!au_test_wkq(current)) {
25555+ int wkq_err;
25556+ struct do_xino_fwrite_args args = {
25557+ .errp = &err,
25558+ .func = func,
25559+ .file = file,
25560+ .buf = buf,
25561+ .size = size,
25562+ .pos = pos
25563+ };
25564+
25565+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
25566+ if (unlikely(wkq_err))
25567+ err = wkq_err;
25568+ } else
25569+ err = do_xino_fwrite(func, file, buf, size, pos);
25570+
25571+ return err;
25572+}
25573+
25574+/* ---------------------------------------------------------------------- */
25575+
25576+/*
25577+ * create a new xinofile at the same place/path as @base_file.
25578+ */
25579+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
25580+{
25581+ struct file *file;
4a4d8108 25582+ struct dentry *base, *parent;
1facf9fc 25583+ struct inode *dir;
25584+ struct qstr *name;
1308ab2a 25585+ struct path path;
4a4d8108 25586+ int err;
1facf9fc 25587+
25588+ base = base_file->f_dentry;
25589+ parent = base->d_parent; /* dir inode is locked */
25590+ dir = parent->d_inode;
25591+ IMustLock(dir);
25592+
25593+ file = ERR_PTR(-EINVAL);
25594+ name = &base->d_name;
4a4d8108
AM
25595+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
25596+ if (IS_ERR(path.dentry)) {
25597+ file = (void *)path.dentry;
25598+ pr_err("%.*s lookup err %ld\n",
25599+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 25600+ goto out;
25601+ }
25602+
25603+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 25604+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 25605+ if (unlikely(err)) {
25606+ file = ERR_PTR(err);
4a4d8108 25607+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 25608+ goto out_dput;
25609+ }
25610+
1308ab2a 25611+ path.mnt = base_file->f_vfsmnt;
4a4d8108
AM
25612+ file = vfsub_dentry_open(&path,
25613+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
1facf9fc 25614+ if (IS_ERR(file)) {
4a4d8108 25615+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 25616+ goto out_dput;
25617+ }
25618+
25619+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
25620+ if (unlikely(err)) {
4a4d8108 25621+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 25622+ goto out_fput;
25623+ }
25624+
25625+ if (copy_src) {
25626+ /* no one can touch copy_src xino */
25627+ err = au_copy_file(file, copy_src,
25628+ i_size_read(copy_src->f_dentry->d_inode));
25629+ if (unlikely(err)) {
4a4d8108 25630+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 25631+ goto out_fput;
25632+ }
25633+ }
25634+ goto out_dput; /* success */
25635+
25636+ out_fput:
25637+ fput(file);
25638+ file = ERR_PTR(err);
25639+ out_dput:
4a4d8108 25640+ dput(path.dentry);
1facf9fc 25641+ out:
25642+ return file;
25643+}
25644+
25645+struct au_xino_lock_dir {
25646+ struct au_hinode *hdir;
25647+ struct dentry *parent;
25648+ struct mutex *mtx;
25649+};
25650+
25651+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
25652+ struct au_xino_lock_dir *ldir)
25653+{
25654+ aufs_bindex_t brid, bindex;
25655+
25656+ ldir->hdir = NULL;
25657+ bindex = -1;
25658+ brid = au_xino_brid(sb);
25659+ if (brid >= 0)
25660+ bindex = au_br_index(sb, brid);
25661+ if (bindex >= 0) {
25662+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 25663+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 25664+ } else {
25665+ ldir->parent = dget_parent(xino->f_dentry);
25666+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
25667+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
25668+ }
25669+}
25670+
25671+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
25672+{
25673+ if (ldir->hdir)
4a4d8108 25674+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 25675+ else {
25676+ mutex_unlock(ldir->mtx);
25677+ dput(ldir->parent);
25678+ }
25679+}
25680+
25681+/* ---------------------------------------------------------------------- */
25682+
25683+/* trucate xino files asynchronously */
25684+
25685+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
25686+{
25687+ int err;
25688+ aufs_bindex_t bi, bend;
25689+ struct au_branch *br;
25690+ struct file *new_xino, *file;
25691+ struct super_block *h_sb;
25692+ struct au_xino_lock_dir ldir;
25693+
25694+ err = -EINVAL;
25695+ bend = au_sbend(sb);
25696+ if (unlikely(bindex < 0 || bend < bindex))
25697+ goto out;
25698+ br = au_sbr(sb, bindex);
25699+ file = br->br_xino.xi_file;
25700+ if (!file)
25701+ goto out;
25702+
25703+ au_xino_lock_dir(sb, file, &ldir);
25704+ /* mnt_want_write() is unnecessary here */
25705+ new_xino = au_xino_create2(file, file);
25706+ au_xino_unlock_dir(&ldir);
25707+ err = PTR_ERR(new_xino);
25708+ if (IS_ERR(new_xino))
25709+ goto out;
25710+ err = 0;
25711+ fput(file);
25712+ br->br_xino.xi_file = new_xino;
25713+
25714+ h_sb = br->br_mnt->mnt_sb;
25715+ for (bi = 0; bi <= bend; bi++) {
25716+ if (unlikely(bi == bindex))
25717+ continue;
25718+ br = au_sbr(sb, bi);
25719+ if (br->br_mnt->mnt_sb != h_sb)
25720+ continue;
25721+
25722+ fput(br->br_xino.xi_file);
25723+ br->br_xino.xi_file = new_xino;
25724+ get_file(new_xino);
25725+ }
25726+
25727+ out:
25728+ return err;
25729+}
25730+
25731+struct xino_do_trunc_args {
25732+ struct super_block *sb;
25733+ struct au_branch *br;
25734+};
25735+
25736+static void xino_do_trunc(void *_args)
25737+{
25738+ struct xino_do_trunc_args *args = _args;
25739+ struct super_block *sb;
25740+ struct au_branch *br;
25741+ struct inode *dir;
25742+ int err;
25743+ aufs_bindex_t bindex;
25744+
25745+ err = 0;
25746+ sb = args->sb;
25747+ dir = sb->s_root->d_inode;
25748+ br = args->br;
25749+
25750+ si_noflush_write_lock(sb);
25751+ ii_read_lock_parent(dir);
25752+ bindex = au_br_index(sb, br->br_id);
25753+ err = au_xino_trunc(sb, bindex);
dece6358
AM
25754+ if (!err
25755+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 25756+ >= br->br_xino_upper)
25757+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
25758+
1facf9fc 25759+ ii_read_unlock(dir);
25760+ if (unlikely(err))
4a4d8108 25761+ pr_warning("err b%d, (%d)\n", bindex, err);
1facf9fc 25762+ atomic_dec(&br->br_xino_running);
25763+ atomic_dec(&br->br_count);
25764+ au_nwt_done(&au_sbi(sb)->si_nowait);
25765+ si_write_unlock(sb);
25766+ kfree(args);
25767+}
25768+
25769+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
25770+{
25771+ struct xino_do_trunc_args *args;
25772+ int wkq_err;
25773+
25774+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
25775+ < br->br_xino_upper)
25776+ return;
25777+
25778+ if (atomic_inc_return(&br->br_xino_running) > 1)
25779+ goto out;
25780+
25781+ /* lock and kfree() will be called in trunc_xino() */
25782+ args = kmalloc(sizeof(*args), GFP_NOFS);
25783+ if (unlikely(!args)) {
25784+ AuErr1("no memory\n");
25785+ goto out_args;
25786+ }
25787+
dece6358 25788+ atomic_inc_return(&br->br_count);
1facf9fc 25789+ args->sb = sb;
25790+ args->br = br;
25791+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
25792+ if (!wkq_err)
25793+ return; /* success */
25794+
4a4d8108 25795+ pr_err("wkq %d\n", wkq_err);
dece6358 25796+ atomic_dec_return(&br->br_count);
1facf9fc 25797+
25798+ out_args:
25799+ kfree(args);
25800+ out:
dece6358 25801+ atomic_dec_return(&br->br_xino_running);
1facf9fc 25802+}
25803+
25804+/* ---------------------------------------------------------------------- */
25805+
25806+static int au_xino_do_write(au_writef_t write, struct file *file,
25807+ ino_t h_ino, ino_t ino)
25808+{
25809+ loff_t pos;
25810+ ssize_t sz;
25811+
25812+ pos = h_ino;
25813+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
25814+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
25815+ return -EFBIG;
25816+ }
25817+ pos *= sizeof(ino);
25818+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
25819+ if (sz == sizeof(ino))
25820+ return 0; /* success */
25821+
25822+ AuIOErr("write failed (%zd)\n", sz);
25823+ return -EIO;
25824+}
25825+
25826+/*
25827+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
25828+ * at the position of @h_ino.
25829+ * even if @ino is zero, it is written to the xinofile and means no entry.
25830+ * if the size of the xino file on a specific filesystem exceeds the watermark,
25831+ * try truncating it.
25832+ */
25833+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
25834+ ino_t ino)
25835+{
25836+ int err;
25837+ unsigned int mnt_flags;
25838+ struct au_branch *br;
25839+
25840+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
25841+ || ((loff_t)-1) > 0);
dece6358 25842+ SiMustAnyLock(sb);
1facf9fc 25843+
25844+ mnt_flags = au_mntflags(sb);
25845+ if (!au_opt_test(mnt_flags, XINO))
25846+ return 0;
25847+
25848+ br = au_sbr(sb, bindex);
25849+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
25850+ h_ino, ino);
25851+ if (!err) {
25852+ if (au_opt_test(mnt_flags, TRUNC_XINO)
25853+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
25854+ xino_try_trunc(sb, br);
25855+ return 0; /* success */
25856+ }
25857+
25858+ AuIOErr("write failed (%d)\n", err);
25859+ return -EIO;
25860+}
25861+
25862+/* ---------------------------------------------------------------------- */
25863+
25864+/* aufs inode number bitmap */
25865+
25866+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
25867+static ino_t xib_calc_ino(unsigned long pindex, int bit)
25868+{
25869+ ino_t ino;
25870+
25871+ AuDebugOn(bit < 0 || page_bits <= bit);
25872+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
25873+ return ino;
25874+}
25875+
25876+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
25877+{
25878+ AuDebugOn(ino < AUFS_FIRST_INO);
25879+ ino -= AUFS_FIRST_INO;
25880+ *pindex = ino / page_bits;
25881+ *bit = ino % page_bits;
25882+}
25883+
25884+static int xib_pindex(struct super_block *sb, unsigned long pindex)
25885+{
25886+ int err;
25887+ loff_t pos;
25888+ ssize_t sz;
25889+ struct au_sbinfo *sbinfo;
25890+ struct file *xib;
25891+ unsigned long *p;
25892+
25893+ sbinfo = au_sbi(sb);
25894+ MtxMustLock(&sbinfo->si_xib_mtx);
25895+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
25896+ || !au_opt_test(sbinfo->si_mntflags, XINO));
25897+
25898+ if (pindex == sbinfo->si_xib_last_pindex)
25899+ return 0;
25900+
25901+ xib = sbinfo->si_xib;
25902+ p = sbinfo->si_xib_buf;
25903+ pos = sbinfo->si_xib_last_pindex;
25904+ pos *= PAGE_SIZE;
25905+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
25906+ if (unlikely(sz != PAGE_SIZE))
25907+ goto out;
25908+
25909+ pos = pindex;
25910+ pos *= PAGE_SIZE;
25911+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
25912+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
25913+ else {
25914+ memset(p, 0, PAGE_SIZE);
25915+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
25916+ }
25917+ if (sz == PAGE_SIZE) {
25918+ sbinfo->si_xib_last_pindex = pindex;
25919+ return 0; /* success */
25920+ }
25921+
25922+ out:
25923+ AuIOErr1("write failed (%zd)\n", sz);
25924+ err = sz;
25925+ if (sz >= 0)
25926+ err = -EIO;
25927+ return err;
25928+}
25929+
25930+/* ---------------------------------------------------------------------- */
25931+
25932+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
25933+ ino_t ino)
25934+{
25935+ int err, bit;
25936+ unsigned long pindex;
25937+ struct au_sbinfo *sbinfo;
25938+
25939+ if (!au_opt_test(au_mntflags(sb), XINO))
25940+ return 0;
25941+
25942+ err = 0;
25943+ if (ino) {
25944+ sbinfo = au_sbi(sb);
25945+ xib_calc_bit(ino, &pindex, &bit);
25946+ AuDebugOn(page_bits <= bit);
25947+ mutex_lock(&sbinfo->si_xib_mtx);
25948+ err = xib_pindex(sb, pindex);
25949+ if (!err) {
25950+ clear_bit(bit, sbinfo->si_xib_buf);
25951+ sbinfo->si_xib_next_bit = bit;
25952+ }
25953+ mutex_unlock(&sbinfo->si_xib_mtx);
25954+ }
25955+
25956+ if (!err)
25957+ err = au_xino_write(sb, bindex, h_ino, 0);
25958+ return err;
25959+}
25960+
25961+/* get an unused inode number from bitmap */
25962+ino_t au_xino_new_ino(struct super_block *sb)
25963+{
25964+ ino_t ino;
25965+ unsigned long *p, pindex, ul, pend;
25966+ struct au_sbinfo *sbinfo;
25967+ struct file *file;
25968+ int free_bit, err;
25969+
25970+ if (!au_opt_test(au_mntflags(sb), XINO))
25971+ return iunique(sb, AUFS_FIRST_INO);
25972+
25973+ sbinfo = au_sbi(sb);
25974+ mutex_lock(&sbinfo->si_xib_mtx);
25975+ p = sbinfo->si_xib_buf;
25976+ free_bit = sbinfo->si_xib_next_bit;
25977+ if (free_bit < page_bits && !test_bit(free_bit, p))
25978+ goto out; /* success */
25979+ free_bit = find_first_zero_bit(p, page_bits);
25980+ if (free_bit < page_bits)
25981+ goto out; /* success */
25982+
25983+ pindex = sbinfo->si_xib_last_pindex;
25984+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
25985+ err = xib_pindex(sb, ul);
25986+ if (unlikely(err))
25987+ goto out_err;
25988+ free_bit = find_first_zero_bit(p, page_bits);
25989+ if (free_bit < page_bits)
25990+ goto out; /* success */
25991+ }
25992+
25993+ file = sbinfo->si_xib;
25994+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
25995+ for (ul = pindex + 1; ul <= pend; ul++) {
25996+ err = xib_pindex(sb, ul);
25997+ if (unlikely(err))
25998+ goto out_err;
25999+ free_bit = find_first_zero_bit(p, page_bits);
26000+ if (free_bit < page_bits)
26001+ goto out; /* success */
26002+ }
26003+ BUG();
26004+
26005+ out:
26006+ set_bit(free_bit, p);
26007+ sbinfo->si_xib_next_bit++;
26008+ pindex = sbinfo->si_xib_last_pindex;
26009+ mutex_unlock(&sbinfo->si_xib_mtx);
26010+ ino = xib_calc_ino(pindex, free_bit);
26011+ AuDbg("i%lu\n", (unsigned long)ino);
26012+ return ino;
26013+ out_err:
26014+ mutex_unlock(&sbinfo->si_xib_mtx);
26015+ AuDbg("i0\n");
26016+ return 0;
26017+}
26018+
26019+/*
26020+ * read @ino from xinofile for the specified branch{@sb, @bindex}
26021+ * at the position of @h_ino.
26022+ * if @ino does not exist and @do_new is true, get new one.
26023+ */
26024+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
26025+ ino_t *ino)
26026+{
26027+ int err;
26028+ ssize_t sz;
26029+ loff_t pos;
26030+ struct file *file;
26031+ struct au_sbinfo *sbinfo;
26032+
26033+ *ino = 0;
26034+ if (!au_opt_test(au_mntflags(sb), XINO))
26035+ return 0; /* no xino */
26036+
26037+ err = 0;
26038+ sbinfo = au_sbi(sb);
26039+ pos = h_ino;
26040+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
26041+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
26042+ return -EFBIG;
26043+ }
26044+ pos *= sizeof(*ino);
26045+
26046+ file = au_sbr(sb, bindex)->br_xino.xi_file;
26047+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
26048+ return 0; /* no ino */
26049+
26050+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
26051+ if (sz == sizeof(*ino))
26052+ return 0; /* success */
26053+
26054+ err = sz;
26055+ if (unlikely(sz >= 0)) {
26056+ err = -EIO;
26057+ AuIOErr("xino read error (%zd)\n", sz);
26058+ }
26059+
26060+ return err;
26061+}
26062+
26063+/* ---------------------------------------------------------------------- */
26064+
26065+/* create and set a new xino file */
26066+
26067+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
26068+{
26069+ struct file *file;
26070+ struct dentry *h_parent, *d;
26071+ struct inode *h_dir;
26072+ int err;
26073+
26074+ /*
26075+ * at mount-time, and the xino file is the default path,
4a4d8108 26076+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 26077+ * when a user specified the xino, we cannot get au_hdir to be ignored.
26078+ */
26079+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
26080+ S_IRUGO | S_IWUGO);
26081+ if (IS_ERR(file)) {
26082+ if (!silent)
4a4d8108 26083+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 26084+ return file;
26085+ }
26086+
26087+ /* keep file count */
26088+ h_parent = dget_parent(file->f_dentry);
26089+ h_dir = h_parent->d_inode;
26090+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
26091+ /* mnt_want_write() is unnecessary here */
26092+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
26093+ mutex_unlock(&h_dir->i_mutex);
26094+ dput(h_parent);
26095+ if (unlikely(err)) {
26096+ if (!silent)
4a4d8108 26097+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 26098+ goto out;
26099+ }
26100+
26101+ err = -EINVAL;
26102+ d = file->f_dentry;
26103+ if (unlikely(sb == d->d_sb)) {
26104+ if (!silent)
4a4d8108 26105+ pr_err("%s must be outside\n", fname);
1facf9fc 26106+ goto out;
26107+ }
26108+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
26109+ if (!silent)
4a4d8108
AM
26110+ pr_err("xino doesn't support %s(%s)\n",
26111+ fname, au_sbtype(d->d_sb));
1facf9fc 26112+ goto out;
26113+ }
26114+ return file; /* success */
26115+
26116+ out:
26117+ fput(file);
26118+ file = ERR_PTR(err);
26119+ return file;
26120+}
26121+
26122+/*
26123+ * find another branch who is on the same filesystem of the specified
26124+ * branch{@btgt}. search until @bend.
26125+ */
26126+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
26127+ aufs_bindex_t bend)
26128+{
26129+ aufs_bindex_t bindex;
26130+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
26131+
26132+ for (bindex = 0; bindex < btgt; bindex++)
26133+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
26134+ return bindex;
26135+ for (bindex++; bindex <= bend; bindex++)
26136+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
26137+ return bindex;
26138+ return -1;
26139+}
26140+
26141+/* ---------------------------------------------------------------------- */
26142+
26143+/*
26144+ * initialize the xinofile for the specified branch @br
26145+ * at the place/path where @base_file indicates.
26146+ * test whether another branch is on the same filesystem or not,
26147+ * if @do_test is true.
26148+ */
26149+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
26150+ struct file *base_file, int do_test)
26151+{
26152+ int err;
26153+ ino_t ino;
26154+ aufs_bindex_t bend, bindex;
26155+ struct au_branch *shared_br, *b;
26156+ struct file *file;
26157+ struct super_block *tgt_sb;
26158+
26159+ shared_br = NULL;
26160+ bend = au_sbend(sb);
26161+ if (do_test) {
26162+ tgt_sb = br->br_mnt->mnt_sb;
26163+ for (bindex = 0; bindex <= bend; bindex++) {
26164+ b = au_sbr(sb, bindex);
26165+ if (tgt_sb == b->br_mnt->mnt_sb) {
26166+ shared_br = b;
26167+ break;
26168+ }
26169+ }
26170+ }
26171+
26172+ if (!shared_br || !shared_br->br_xino.xi_file) {
26173+ struct au_xino_lock_dir ldir;
26174+
26175+ au_xino_lock_dir(sb, base_file, &ldir);
26176+ /* mnt_want_write() is unnecessary here */
26177+ file = au_xino_create2(base_file, NULL);
26178+ au_xino_unlock_dir(&ldir);
26179+ err = PTR_ERR(file);
26180+ if (IS_ERR(file))
26181+ goto out;
26182+ br->br_xino.xi_file = file;
26183+ } else {
26184+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
26185+ get_file(br->br_xino.xi_file);
26186+ }
26187+
26188+ ino = AUFS_ROOT_INO;
26189+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
26190+ h_ino, ino);
26191+ if (!err)
26192+ return 0; /* success */
26193+
26194+
26195+ out:
26196+ return err;
26197+}
26198+
26199+/* ---------------------------------------------------------------------- */
26200+
26201+/* trucate a xino bitmap file */
26202+
26203+/* todo: slow */
26204+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
26205+{
26206+ int err, bit;
26207+ ssize_t sz;
26208+ unsigned long pindex;
26209+ loff_t pos, pend;
26210+ struct au_sbinfo *sbinfo;
26211+ au_readf_t func;
26212+ ino_t *ino;
26213+ unsigned long *p;
26214+
26215+ err = 0;
26216+ sbinfo = au_sbi(sb);
dece6358 26217+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 26218+ p = sbinfo->si_xib_buf;
26219+ func = sbinfo->si_xread;
26220+ pend = i_size_read(file->f_dentry->d_inode);
26221+ pos = 0;
26222+ while (pos < pend) {
26223+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
26224+ err = sz;
26225+ if (unlikely(sz <= 0))
26226+ goto out;
26227+
26228+ err = 0;
26229+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
26230+ if (unlikely(*ino < AUFS_FIRST_INO))
26231+ continue;
26232+
26233+ xib_calc_bit(*ino, &pindex, &bit);
26234+ AuDebugOn(page_bits <= bit);
26235+ err = xib_pindex(sb, pindex);
26236+ if (!err)
26237+ set_bit(bit, p);
26238+ else
26239+ goto out;
26240+ }
26241+ }
26242+
26243+ out:
26244+ return err;
26245+}
26246+
26247+static int xib_restore(struct super_block *sb)
26248+{
26249+ int err;
26250+ aufs_bindex_t bindex, bend;
26251+ void *page;
26252+
26253+ err = -ENOMEM;
26254+ page = (void *)__get_free_page(GFP_NOFS);
26255+ if (unlikely(!page))
26256+ goto out;
26257+
26258+ err = 0;
26259+ bend = au_sbend(sb);
26260+ for (bindex = 0; !err && bindex <= bend; bindex++)
26261+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
26262+ err = do_xib_restore
26263+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
26264+ else
26265+ AuDbg("b%d\n", bindex);
26266+ free_page((unsigned long)page);
26267+
26268+ out:
26269+ return err;
26270+}
26271+
26272+int au_xib_trunc(struct super_block *sb)
26273+{
26274+ int err;
26275+ ssize_t sz;
26276+ loff_t pos;
26277+ struct au_xino_lock_dir ldir;
26278+ struct au_sbinfo *sbinfo;
26279+ unsigned long *p;
26280+ struct file *file;
26281+
dece6358
AM
26282+ SiMustWriteLock(sb);
26283+
1facf9fc 26284+ err = 0;
26285+ sbinfo = au_sbi(sb);
26286+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
26287+ goto out;
26288+
26289+ file = sbinfo->si_xib;
26290+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
26291+ goto out;
26292+
26293+ au_xino_lock_dir(sb, file, &ldir);
26294+ /* mnt_want_write() is unnecessary here */
26295+ file = au_xino_create2(sbinfo->si_xib, NULL);
26296+ au_xino_unlock_dir(&ldir);
26297+ err = PTR_ERR(file);
26298+ if (IS_ERR(file))
26299+ goto out;
26300+ fput(sbinfo->si_xib);
26301+ sbinfo->si_xib = file;
26302+
26303+ p = sbinfo->si_xib_buf;
26304+ memset(p, 0, PAGE_SIZE);
26305+ pos = 0;
26306+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
26307+ if (unlikely(sz != PAGE_SIZE)) {
26308+ err = sz;
26309+ AuIOErr("err %d\n", err);
26310+ if (sz >= 0)
26311+ err = -EIO;
26312+ goto out;
26313+ }
26314+
26315+ mutex_lock(&sbinfo->si_xib_mtx);
26316+ /* mnt_want_write() is unnecessary here */
26317+ err = xib_restore(sb);
26318+ mutex_unlock(&sbinfo->si_xib_mtx);
26319+
26320+out:
26321+ return err;
26322+}
26323+
26324+/* ---------------------------------------------------------------------- */
26325+
26326+/*
26327+ * xino mount option handlers
26328+ */
26329+static au_readf_t find_readf(struct file *h_file)
26330+{
26331+ const struct file_operations *fop = h_file->f_op;
26332+
26333+ if (fop) {
26334+ if (fop->read)
26335+ return fop->read;
26336+ if (fop->aio_read)
26337+ return do_sync_read;
26338+ }
26339+ return ERR_PTR(-ENOSYS);
26340+}
26341+
26342+static au_writef_t find_writef(struct file *h_file)
26343+{
26344+ const struct file_operations *fop = h_file->f_op;
26345+
26346+ if (fop) {
26347+ if (fop->write)
26348+ return fop->write;
26349+ if (fop->aio_write)
26350+ return do_sync_write;
26351+ }
26352+ return ERR_PTR(-ENOSYS);
26353+}
26354+
26355+/* xino bitmap */
26356+static void xino_clear_xib(struct super_block *sb)
26357+{
26358+ struct au_sbinfo *sbinfo;
26359+
dece6358
AM
26360+ SiMustWriteLock(sb);
26361+
1facf9fc 26362+ sbinfo = au_sbi(sb);
26363+ sbinfo->si_xread = NULL;
26364+ sbinfo->si_xwrite = NULL;
26365+ if (sbinfo->si_xib)
26366+ fput(sbinfo->si_xib);
26367+ sbinfo->si_xib = NULL;
26368+ free_page((unsigned long)sbinfo->si_xib_buf);
26369+ sbinfo->si_xib_buf = NULL;
26370+}
26371+
26372+static int au_xino_set_xib(struct super_block *sb, struct file *base)
26373+{
26374+ int err;
26375+ loff_t pos;
26376+ struct au_sbinfo *sbinfo;
26377+ struct file *file;
26378+
dece6358
AM
26379+ SiMustWriteLock(sb);
26380+
1facf9fc 26381+ sbinfo = au_sbi(sb);
26382+ file = au_xino_create2(base, sbinfo->si_xib);
26383+ err = PTR_ERR(file);
26384+ if (IS_ERR(file))
26385+ goto out;
26386+ if (sbinfo->si_xib)
26387+ fput(sbinfo->si_xib);
26388+ sbinfo->si_xib = file;
26389+ sbinfo->si_xread = find_readf(file);
26390+ sbinfo->si_xwrite = find_writef(file);
26391+
26392+ err = -ENOMEM;
26393+ if (!sbinfo->si_xib_buf)
26394+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
26395+ if (unlikely(!sbinfo->si_xib_buf))
26396+ goto out_unset;
26397+
26398+ sbinfo->si_xib_last_pindex = 0;
26399+ sbinfo->si_xib_next_bit = 0;
26400+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
26401+ pos = 0;
26402+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
26403+ PAGE_SIZE, &pos);
26404+ if (unlikely(err != PAGE_SIZE))
26405+ goto out_free;
26406+ }
26407+ err = 0;
26408+ goto out; /* success */
26409+
26410+ out_free:
26411+ free_page((unsigned long)sbinfo->si_xib_buf);
26412+ sbinfo->si_xib_buf = NULL;
26413+ if (err >= 0)
26414+ err = -EIO;
26415+ out_unset:
26416+ fput(sbinfo->si_xib);
26417+ sbinfo->si_xib = NULL;
26418+ sbinfo->si_xread = NULL;
26419+ sbinfo->si_xwrite = NULL;
26420+ out:
26421+ return err;
26422+}
26423+
26424+/* xino for each branch */
26425+static void xino_clear_br(struct super_block *sb)
26426+{
26427+ aufs_bindex_t bindex, bend;
26428+ struct au_branch *br;
26429+
26430+ bend = au_sbend(sb);
26431+ for (bindex = 0; bindex <= bend; bindex++) {
26432+ br = au_sbr(sb, bindex);
26433+ if (!br || !br->br_xino.xi_file)
26434+ continue;
26435+
26436+ fput(br->br_xino.xi_file);
26437+ br->br_xino.xi_file = NULL;
26438+ }
26439+}
26440+
26441+static int au_xino_set_br(struct super_block *sb, struct file *base)
26442+{
26443+ int err;
26444+ ino_t ino;
26445+ aufs_bindex_t bindex, bend, bshared;
26446+ struct {
26447+ struct file *old, *new;
26448+ } *fpair, *p;
26449+ struct au_branch *br;
26450+ struct inode *inode;
26451+ au_writef_t writef;
26452+
dece6358
AM
26453+ SiMustWriteLock(sb);
26454+
1facf9fc 26455+ err = -ENOMEM;
26456+ bend = au_sbend(sb);
26457+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
26458+ if (unlikely(!fpair))
26459+ goto out;
26460+
26461+ inode = sb->s_root->d_inode;
26462+ ino = AUFS_ROOT_INO;
26463+ writef = au_sbi(sb)->si_xwrite;
26464+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
26465+ br = au_sbr(sb, bindex);
26466+ bshared = is_sb_shared(sb, bindex, bindex - 1);
26467+ if (bshared >= 0) {
26468+ /* shared xino */
26469+ *p = fpair[bshared];
26470+ get_file(p->new);
26471+ }
26472+
26473+ if (!p->new) {
26474+ /* new xino */
26475+ p->old = br->br_xino.xi_file;
26476+ p->new = au_xino_create2(base, br->br_xino.xi_file);
26477+ err = PTR_ERR(p->new);
26478+ if (IS_ERR(p->new)) {
26479+ p->new = NULL;
26480+ goto out_pair;
26481+ }
26482+ }
26483+
26484+ err = au_xino_do_write(writef, p->new,
26485+ au_h_iptr(inode, bindex)->i_ino, ino);
26486+ if (unlikely(err))
26487+ goto out_pair;
26488+ }
26489+
26490+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
26491+ br = au_sbr(sb, bindex);
26492+ if (br->br_xino.xi_file)
26493+ fput(br->br_xino.xi_file);
26494+ get_file(p->new);
26495+ br->br_xino.xi_file = p->new;
26496+ }
26497+
26498+ out_pair:
26499+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
26500+ if (p->new)
26501+ fput(p->new);
26502+ else
26503+ break;
26504+ kfree(fpair);
26505+ out:
26506+ return err;
26507+}
26508+
26509+void au_xino_clr(struct super_block *sb)
26510+{
26511+ struct au_sbinfo *sbinfo;
26512+
26513+ au_xigen_clr(sb);
26514+ xino_clear_xib(sb);
26515+ xino_clear_br(sb);
26516+ sbinfo = au_sbi(sb);
26517+ /* lvalue, do not call au_mntflags() */
26518+ au_opt_clr(sbinfo->si_mntflags, XINO);
26519+}
26520+
26521+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
26522+{
26523+ int err, skip;
26524+ struct dentry *parent, *cur_parent;
26525+ struct qstr *dname, *cur_name;
26526+ struct file *cur_xino;
26527+ struct inode *dir;
26528+ struct au_sbinfo *sbinfo;
26529+
dece6358
AM
26530+ SiMustWriteLock(sb);
26531+
1facf9fc 26532+ err = 0;
26533+ sbinfo = au_sbi(sb);
26534+ parent = dget_parent(xino->file->f_dentry);
26535+ if (remount) {
26536+ skip = 0;
26537+ dname = &xino->file->f_dentry->d_name;
26538+ cur_xino = sbinfo->si_xib;
26539+ if (cur_xino) {
26540+ cur_parent = dget_parent(cur_xino->f_dentry);
26541+ cur_name = &cur_xino->f_dentry->d_name;
26542+ skip = (cur_parent == parent
26543+ && dname->len == cur_name->len
26544+ && !memcmp(dname->name, cur_name->name,
26545+ dname->len));
26546+ dput(cur_parent);
26547+ }
26548+ if (skip)
26549+ goto out;
26550+ }
26551+
26552+ au_opt_set(sbinfo->si_mntflags, XINO);
26553+ dir = parent->d_inode;
26554+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
26555+ /* mnt_want_write() is unnecessary here */
26556+ err = au_xino_set_xib(sb, xino->file);
26557+ if (!err)
26558+ err = au_xigen_set(sb, xino->file);
26559+ if (!err)
26560+ err = au_xino_set_br(sb, xino->file);
26561+ mutex_unlock(&dir->i_mutex);
26562+ if (!err)
26563+ goto out; /* success */
26564+
26565+ /* reset all */
26566+ AuIOErr("failed creating xino(%d).\n", err);
26567+
26568+ out:
26569+ dput(parent);
26570+ return err;
26571+}
26572+
26573+/* ---------------------------------------------------------------------- */
26574+
26575+/*
26576+ * create a xinofile at the default place/path.
26577+ */
26578+struct file *au_xino_def(struct super_block *sb)
26579+{
26580+ struct file *file;
26581+ char *page, *p;
26582+ struct au_branch *br;
26583+ struct super_block *h_sb;
26584+ struct path path;
26585+ aufs_bindex_t bend, bindex, bwr;
26586+
26587+ br = NULL;
26588+ bend = au_sbend(sb);
26589+ bwr = -1;
26590+ for (bindex = 0; bindex <= bend; bindex++) {
26591+ br = au_sbr(sb, bindex);
26592+ if (au_br_writable(br->br_perm)
26593+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
26594+ bwr = bindex;
26595+ break;
26596+ }
26597+ }
26598+
26599+ if (bwr >= 0) {
26600+ file = ERR_PTR(-ENOMEM);
4a4d8108 26601+ page = __getname_gfp(GFP_NOFS);
1facf9fc 26602+ if (unlikely(!page))
26603+ goto out;
26604+ path.mnt = br->br_mnt;
26605+ path.dentry = au_h_dptr(sb->s_root, bwr);
26606+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
26607+ file = (void *)p;
26608+ if (!IS_ERR(p)) {
26609+ strcat(p, "/" AUFS_XINO_FNAME);
26610+ AuDbg("%s\n", p);
26611+ file = au_xino_create(sb, p, /*silent*/0);
26612+ if (!IS_ERR(file))
26613+ au_xino_brid_set(sb, br->br_id);
26614+ }
26615+ __putname(page);
26616+ } else {
26617+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
26618+ if (IS_ERR(file))
26619+ goto out;
26620+ h_sb = file->f_dentry->d_sb;
26621+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
4a4d8108
AM
26622+ pr_err("xino doesn't support %s(%s)\n",
26623+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
1facf9fc 26624+ fput(file);
26625+ file = ERR_PTR(-EINVAL);
26626+ }
26627+ if (!IS_ERR(file))
26628+ au_xino_brid_set(sb, -1);
26629+ }
26630+
26631+ out:
26632+ return file;
26633+}
26634+
26635+/* ---------------------------------------------------------------------- */
26636+
26637+int au_xino_path(struct seq_file *seq, struct file *file)
26638+{
26639+ int err;
26640+
26641+ err = au_seq_path(seq, &file->f_path);
26642+ if (unlikely(err < 0))
26643+ goto out;
26644+
26645+ err = 0;
26646+#define Deleted "\\040(deleted)"
26647+ seq->count -= sizeof(Deleted) - 1;
26648+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
26649+ sizeof(Deleted) - 1));
26650+#undef Deleted
26651+
26652+ out:
26653+ return err;
26654+}
4a4d8108
AM
26655diff -urN --exclude '*.orig' linux-2.6.34.org/fs/Kconfig linux-2.6.34/fs/Kconfig
26656--- linux-2.6.34.org/fs/Kconfig 2010-05-31 22:19:12.649639677 +0200
26657+++ linux-2.6.34/fs/Kconfig 2010-05-31 22:20:27.150695120 +0200
26658@@ -190,6 +190,7 @@
26659 source "fs/sysv/Kconfig"
26660 source "fs/ufs/Kconfig"
26661 source "fs/exofs/Kconfig"
26662+source "fs/aufs/Kconfig"
26663
26664 endif # MISC_FILESYSTEMS
26665
26666diff -urN --exclude '*.orig' linux-2.6.34.org/fs/Makefile linux-2.6.34/fs/Makefile
26667--- linux-2.6.34.org/fs/Makefile 2010-05-31 22:19:12.699737326 +0200
26668+++ linux-2.6.34/fs/Makefile 2010-05-31 22:20:27.207546162 +0200
26669@@ -127,3 +127,4 @@
26670 obj-$(CONFIG_GFS2_FS) += gfs2/
26671 obj-$(CONFIG_EXOFS_FS) += exofs/
26672 obj-$(CONFIG_CEPH_FS) += ceph/
26673+obj-$(CONFIG_AUFS_FS) += aufs/
26674diff -urN --exclude '*.orig' linux-2.6.34.org/fs/namei.c linux-2.6.34/fs/namei.c
26675--- linux-2.6.34.org/fs/namei.c 2010-05-16 23:17:36.000000000 +0200
26676+++ linux-2.6.34/fs/namei.c 2010-05-31 22:20:36.579878021 +0200
26677@@ -348,6 +348,7 @@
26678
26679 return 0;
26680 }
26681+EXPORT_SYMBOL(deny_write_access);
26682
26683 /**
26684 * path_get - get a reference to a path
26685@@ -1177,7 +1178,7 @@
1facf9fc 26686 * needs parent already locked. Doesn't follow mounts.
26687 * SMP-safe.
26688 */
26689-static struct dentry *lookup_hash(struct nameidata *nd)
26690+struct dentry *lookup_hash(struct nameidata *nd)
26691 {
26692 int err;
26693
4a4d8108
AM
26694@@ -1186,8 +1187,9 @@
26695 return ERR_PTR(err);
1facf9fc 26696 return __lookup_hash(&nd->last, nd->path.dentry, nd);
26697 }
4a4d8108 26698+EXPORT_SYMBOL(lookup_hash);
1facf9fc 26699
26700-static int __lookup_one_len(const char *name, struct qstr *this,
26701+int __lookup_one_len(const char *name, struct qstr *this,
26702 struct dentry *base, int len)
26703 {
26704 unsigned long hash;
4a4d8108
AM
26705@@ -1208,6 +1210,7 @@
26706 this->hash = end_name_hash(hash);
26707 return 0;
26708 }
26709+EXPORT_SYMBOL(__lookup_one_len);
26710
26711 /**
26712 * lookup_one_len - filesystem helper to lookup single pathname component
26713diff -urN --exclude '*.orig' linux-2.6.34.org/fs/namespace.c linux-2.6.34/fs/namespace.c
26714--- linux-2.6.34.org/fs/namespace.c 2010-05-16 23:17:36.000000000 +0200
26715+++ linux-2.6.34/fs/namespace.c 2010-05-31 22:20:36.586473532 +0200
26716@@ -1282,6 +1282,7 @@
26717 }
26718 return 0;
26719 }
26720+EXPORT_SYMBOL(iterate_mounts);
26721
26722 static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
26723 {
26724diff -urN --exclude '*.orig' linux-2.6.34.org/fs/notify/group.c linux-2.6.34/fs/notify/group.c
26725--- linux-2.6.34.org/fs/notify/group.c 2010-05-16 23:17:36.000000000 +0200
26726+++ linux-2.6.34/fs/notify/group.c 2010-05-31 22:20:36.589687896 +0200
26727@@ -22,6 +22,7 @@
26728 #include <linux/srcu.h>
26729 #include <linux/rculist.h>
26730 #include <linux/wait.h>
26731+#include <linux/module.h>
26732
26733 #include <linux/fsnotify_backend.h>
26734 #include "fsnotify.h"
26735@@ -169,6 +170,7 @@
26736 fsnotify_recalc_global_mask();
26737 fsnotify_destroy_group(group);
26738 }
26739+EXPORT_SYMBOL(fsnotify_put_group);
26740
26741 /*
26742 * Simply run the fsnotify_groups list and find a group which matches
26743@@ -252,3 +254,4 @@
26744
26745 return group;
26746 }
26747+EXPORT_SYMBOL(fsnotify_obtain_group);
26748diff -urN --exclude '*.orig' linux-2.6.34.org/fs/notify/inode_mark.c linux-2.6.34/fs/notify/inode_mark.c
26749--- linux-2.6.34.org/fs/notify/inode_mark.c 2010-05-16 23:17:36.000000000 +0200
26750+++ linux-2.6.34/fs/notify/inode_mark.c 2010-05-31 22:20:36.593009117 +0200
26751@@ -105,6 +105,7 @@
26752 if (atomic_dec_and_test(&entry->refcnt))
26753 entry->free_mark(entry);
26754 }
26755+EXPORT_SYMBOL(fsnotify_put_mark);
26756
26757 /*
26758 * Recalculate the mask of events relevant to a given inode locked.
26759@@ -215,6 +216,7 @@
26760 if (unlikely(atomic_dec_and_test(&group->num_marks)))
26761 fsnotify_final_destroy_group(group);
26762 }
26763+EXPORT_SYMBOL(fsnotify_destroy_mark_by_entry);
26764
26765 /*
26766 * Given a group, destroy all of the marks associated with that group.
26767@@ -281,6 +283,7 @@
26768 }
26769 return NULL;
26770 }
26771+EXPORT_SYMBOL(fsnotify_find_mark_entry);
26772
26773 /*
26774 * Nothing fancy, just initialize lists and locks and counters.
26775@@ -297,6 +300,7 @@
26776 entry->inode = NULL;
26777 entry->free_mark = free_mark;
26778 }
26779+EXPORT_SYMBOL(fsnotify_init_mark);
26780
26781 /*
26782 * Attach an initialized mark entry to a given group and inode.
26783@@ -352,6 +356,7 @@
26784
26785 return ret;
26786 }
26787+EXPORT_SYMBOL(fsnotify_add_mark);
26788
26789 /**
26790 * fsnotify_unmount_inodes - an sb is unmounting. handle any watched inodes.
26791diff -urN --exclude '*.orig' linux-2.6.34.org/fs/open.c linux-2.6.34/fs/open.c
26792--- linux-2.6.34.org/fs/open.c 2010-05-16 23:17:36.000000000 +0200
26793+++ linux-2.6.34/fs/open.c 2010-05-31 22:20:36.593009117 +0200
26794@@ -225,6 +225,7 @@
26795 mutex_unlock(&dentry->d_inode->i_mutex);
26796 return ret;
26797 }
26798+EXPORT_SYMBOL(do_truncate);
26799
26800 static long do_sys_truncate(const char __user *pathname, loff_t length)
26801 {
26802diff -urN --exclude '*.orig' linux-2.6.34.org/fs/splice.c linux-2.6.34/fs/splice.c
26803--- linux-2.6.34.org/fs/splice.c 2010-05-16 23:17:36.000000000 +0200
26804+++ linux-2.6.34/fs/splice.c 2010-05-31 22:20:36.593009117 +0200
26805@@ -1054,8 +1054,8 @@
0fc653ad 26806 /*
26807 * Attempt to initiate a splice from pipe to file.
26808 */
26809-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
26810- loff_t *ppos, size_t len, unsigned int flags)
26811+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
26812+ loff_t *ppos, size_t len, unsigned int flags)
26813 {
1308ab2a 26814 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
26815 loff_t *, size_t, unsigned int);
4a4d8108
AM
26816@@ -1078,13 +1078,14 @@
26817
26818 return splice_write(pipe, out, ppos, len, flags);
26819 }
26820+EXPORT_SYMBOL(do_splice_from);
26821
0fc653ad 26822 /*
26823 * Attempt to initiate a splice from a file to a pipe.
26824 */
26825-static long do_splice_to(struct file *in, loff_t *ppos,
26826- struct pipe_inode_info *pipe, size_t len,
26827- unsigned int flags)
26828+long do_splice_to(struct file *in, loff_t *ppos,
26829+ struct pipe_inode_info *pipe, size_t len,
26830+ unsigned int flags)
26831 {
1308ab2a 26832 ssize_t (*splice_read)(struct file *, loff_t *,
26833 struct pipe_inode_info *, size_t, unsigned int);
4a4d8108
AM
26834@@ -1104,6 +1105,7 @@
26835
26836 return splice_read(in, ppos, pipe, len, flags);
26837 }
26838+EXPORT_SYMBOL(do_splice_to);
26839
26840 /**
26841 * splice_direct_to_actor - splices data directly between two non-pipes
26842diff -urN --exclude '*.orig' linux-2.6.34.org/include/linux/aufs_type.h linux-2.6.34/include/linux/aufs_type.h
26843--- linux-2.6.34.org/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
26844+++ linux-2.6.34/include/linux/aufs_type.h 2010-05-31 22:15:32.000000000 +0200
26845@@ -0,0 +1,198 @@
1facf9fc 26846+/*
4a4d8108 26847+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26848+ *
26849+ * This program, aufs is free software; you can redistribute it and/or modify
26850+ * it under the terms of the GNU General Public License as published by
26851+ * the Free Software Foundation; either version 2 of the License, or
26852+ * (at your option) any later version.
dece6358
AM
26853+ *
26854+ * This program is distributed in the hope that it will be useful,
26855+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26856+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26857+ * GNU General Public License for more details.
26858+ *
26859+ * You should have received a copy of the GNU General Public License
26860+ * along with this program; if not, write to the Free Software
26861+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26862+ */
26863+
26864+#ifndef __AUFS_TYPE_H__
26865+#define __AUFS_TYPE_H__
26866+
26867+#include <linux/ioctl.h>
4a4d8108
AM
26868+/* for those who didn't "make headers_install" */
26869+#ifdef __KERNEL__
26870+#include <linux/kernel.h>
26871+#endif
26872+#include <linux/limits.h>
1308ab2a 26873+#include <linux/types.h>
1facf9fc 26874+
4a4d8108 26875+#define AUFS_VERSION "2-standalone.tree-34-20100531"
1facf9fc 26876+
26877+/* todo? move this to linux-2.6.19/include/magic.h */
26878+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
26879+
26880+/* ---------------------------------------------------------------------- */
26881+
26882+#ifdef CONFIG_AUFS_BRANCH_MAX_127
1308ab2a 26883+typedef __s8 aufs_bindex_t;
1facf9fc 26884+#define AUFS_BRANCH_MAX 127
26885+#else
1308ab2a 26886+typedef __s16 aufs_bindex_t;
1facf9fc 26887+#ifdef CONFIG_AUFS_BRANCH_MAX_511
26888+#define AUFS_BRANCH_MAX 511
26889+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
26890+#define AUFS_BRANCH_MAX 1023
26891+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
26892+#define AUFS_BRANCH_MAX 32767
26893+#endif
26894+#endif
26895+
26896+#ifdef __KERNEL__
26897+#ifndef AUFS_BRANCH_MAX
26898+#error unknown CONFIG_AUFS_BRANCH_MAX value
26899+#endif
26900+#endif /* __KERNEL__ */
26901+
26902+/* ---------------------------------------------------------------------- */
26903+
26904+#define AUFS_NAME "aufs"
26905+#define AUFS_FSTYPE AUFS_NAME
26906+
26907+#define AUFS_ROOT_INO 2
26908+#define AUFS_FIRST_INO 11
26909+
26910+#define AUFS_WH_PFX ".wh."
26911+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
4a4d8108
AM
26912+#define AUFS_WH_TMP_LEN 4
26913+/* a limit for rmdir/rename a dir */
26914+#define AUFS_MAX_NAMELEN (NAME_MAX \
26915+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
26916+ - 1 /* dot */\
26917+ - AUFS_WH_TMP_LEN) /* hex */
1facf9fc 26918+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
26919+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
26920+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
26921+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
26922+#define AUFS_DIRWH_DEF 3
26923+#define AUFS_RDCACHE_DEF 10 /* seconds */
26924+#define AUFS_RDBLK_DEF 512 /* bytes */
26925+#define AUFS_RDHASH_DEF 32
26926+#define AUFS_WKQ_NAME AUFS_NAME "d"
1facf9fc 26927+#define AUFS_MFS_SECOND_DEF 30 /* seconds */
26928+#define AUFS_PLINK_WARN 100 /* number of plinks */
26929+
26930+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
26931+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
26932+
26933+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
26934+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
26935+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
26936+
26937+/* doubly whiteouted */
26938+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
26939+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
26940+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
26941+
26942+/* branch permission */
26943+#define AUFS_BRPERM_RW "rw"
26944+#define AUFS_BRPERM_RO "ro"
26945+#define AUFS_BRPERM_RR "rr"
26946+#define AUFS_BRPERM_WH "wh"
26947+#define AUFS_BRPERM_NLWH "nolwh"
26948+#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
26949+#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
26950+#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
26951+
26952+/* ---------------------------------------------------------------------- */
26953+
26954+/* ioctl */
26955+enum {
26956+ AuCtl_PLINK_MAINT,
1308ab2a 26957+ AuCtl_PLINK_CLEAN,
26958+
26959+ /* readdir in userspace */
26960+ AuCtl_RDU,
4a4d8108
AM
26961+ AuCtl_RDU_INO,
26962+
26963+ /* pathconf wrapper */
26964+ AuCtl_WBR_FD
1308ab2a 26965+};
26966+
26967+/* borrowed from linux/include/linux/kernel.h */
26968+#ifndef ALIGN
26969+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
26970+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
26971+#endif
26972+
26973+/* borrowed from linux/include/linux/compiler-gcc3.h */
26974+#ifndef __aligned
26975+#define __aligned(x) __attribute__((aligned(x)))
26976+#define __packed __attribute__((packed))
26977+#endif
26978+
26979+struct au_rdu_cookie {
26980+ __u64 h_pos;
26981+ __s16 bindex;
26982+ __u8 flags;
26983+ __u8 pad;
26984+ __u32 generation;
26985+} __aligned(8);
26986+
26987+struct au_rdu_ent {
26988+ __u64 ino;
26989+ __s16 bindex;
26990+ __u8 type;
26991+ __u8 nlen;
26992+ __u8 wh;
26993+ char name[0];
26994+} __aligned(8);
26995+
26996+static inline int au_rdu_len(int nlen)
26997+{
26998+ /* include the terminating NULL */
26999+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
27000+ sizeof(__u64));
27001+}
27002+
27003+union au_rdu_ent_ul {
27004+ struct au_rdu_ent __user *e;
27005+ unsigned long ul;
27006+};
27007+
27008+enum {
27009+ AufsCtlRduV_SZ,
27010+ AufsCtlRduV_SZ_PTR,
27011+ AufsCtlRduV_End
1facf9fc 27012+};
27013+
1308ab2a 27014+struct aufs_rdu {
27015+ /* input */
27016+ union {
27017+ __u64 sz; /* AuCtl_RDU */
27018+ __u64 nent; /* AuCtl_RDU_INO */
27019+ };
27020+ union au_rdu_ent_ul ent;
27021+ __u16 verify[AufsCtlRduV_End];
27022+
27023+ /* input/output */
27024+ __u32 blk;
27025+
27026+ /* output */
27027+ union au_rdu_ent_ul tail;
27028+ /* number of entries which were added in a single call */
27029+ __u64 rent;
27030+ __u8 full;
27031+ __u8 shwh;
27032+
27033+ struct au_rdu_cookie cookie;
27034+} __aligned(8);
27035+
1facf9fc 27036+#define AuCtlType 'A'
27037+#define AUFS_CTL_PLINK_MAINT _IO(AuCtlType, AuCtl_PLINK_MAINT)
27038+#define AUFS_CTL_PLINK_CLEAN _IO(AuCtlType, AuCtl_PLINK_CLEAN)
1308ab2a 27039+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
27040+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
4a4d8108 27041+#define AUFS_CTL_WBR_FD _IO(AuCtlType, AuCtl_WBR_FD)
1facf9fc 27042+
27043+#endif /* __AUFS_TYPE_H__ */
4a4d8108
AM
27044diff -urN --exclude '*.orig' linux-2.6.34.org/include/linux/Kbuild linux-2.6.34/include/linux/Kbuild
27045--- linux-2.6.34.org/include/linux/Kbuild 2010-05-16 23:17:36.000000000 +0200
27046+++ linux-2.6.34/include/linux/Kbuild 2010-05-31 22:20:27.267087305 +0200
27047@@ -34,6 +34,7 @@
27048 header-y += atmsap.h
27049 header-y += atmsvc.h
27050 header-y += atm_zatm.h
27051+header-y += aufs_type.h
27052 header-y += auto_fs4.h
27053 header-y += ax25.h
27054 header-y += b1lli.h
27055diff -urN --exclude '*.orig' linux-2.6.34.org/include/linux/namei.h linux-2.6.34/include/linux/namei.h
27056--- linux-2.6.34.org/include/linux/namei.h 2010-05-16 23:17:36.000000000 +0200
27057+++ linux-2.6.34/include/linux/namei.h 2010-05-31 22:20:31.663379109 +0200
27058@@ -73,6 +73,9 @@
27059 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
27060 int (*open)(struct inode *, struct file *));
1facf9fc 27061
27062+extern struct dentry *lookup_hash(struct nameidata *nd);
27063+extern int __lookup_one_len(const char *name, struct qstr *this,
27064+ struct dentry *base, int len);
27065 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
1facf9fc 27066
4a4d8108
AM
27067 extern int follow_down(struct path *);
27068diff -urN --exclude '*.orig' linux-2.6.34.org/include/linux/splice.h linux-2.6.34/include/linux/splice.h
27069--- linux-2.6.34.org/include/linux/splice.h 2010-05-16 23:17:36.000000000 +0200
27070+++ linux-2.6.34/include/linux/splice.h 2010-05-31 22:20:31.666712433 +0200
27071@@ -82,4 +82,10 @@
1facf9fc 27072 extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
27073 splice_direct_actor *);
27074
0fc653ad 27075+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
1facf9fc 27076+ loff_t *ppos, size_t len, unsigned int flags);
0fc653ad 27077+extern long do_splice_to(struct file *in, loff_t *ppos,
1facf9fc 27078+ struct pipe_inode_info *pipe, size_t len,
27079+ unsigned int flags);
27080+
27081 #endif
4a4d8108
AM
27082diff -urN --exclude '*.orig' linux-2.6.34.org/security/commoncap.c linux-2.6.34/security/commoncap.c
27083--- linux-2.6.34.org/security/commoncap.c 2010-05-16 23:17:36.000000000 +0200
27084+++ linux-2.6.34/security/commoncap.c 2010-05-31 22:20:36.596333970 +0200
27085@@ -951,3 +951,4 @@
27086 }
27087 return ret;
27088 }
27089+EXPORT_SYMBOL(cap_file_mmap);
27090diff -urN --exclude '*.orig' linux-2.6.34.org/security/device_cgroup.c linux-2.6.34/security/device_cgroup.c
27091--- linux-2.6.34.org/security/device_cgroup.c 2010-05-16 23:17:36.000000000 +0200
27092+++ linux-2.6.34/security/device_cgroup.c 2010-05-31 22:20:36.596333970 +0200
27093@@ -515,6 +515,7 @@
27094
27095 return -EPERM;
27096 }
27097+EXPORT_SYMBOL(devcgroup_inode_permission);
27098
27099 int devcgroup_inode_mknod(int mode, dev_t dev)
27100 {
27101diff -urN --exclude '*.orig' linux-2.6.34.org/security/security.c linux-2.6.34/security/security.c
27102--- linux-2.6.34.org/security/security.c 2010-05-16 23:17:36.000000000 +0200
27103+++ linux-2.6.34/security/security.c 2010-05-31 22:20:36.596333970 +0200
27104@@ -411,6 +411,7 @@
27105 return 0;
27106 return security_ops->path_mkdir(dir, dentry, mode);
27107 }
27108+EXPORT_SYMBOL(security_path_mkdir);
27109
27110 int security_path_rmdir(struct path *dir, struct dentry *dentry)
27111 {
27112@@ -418,6 +419,7 @@
27113 return 0;
27114 return security_ops->path_rmdir(dir, dentry);
27115 }
27116+EXPORT_SYMBOL(security_path_rmdir);
27117
27118 int security_path_unlink(struct path *dir, struct dentry *dentry)
27119 {
27120@@ -425,6 +427,7 @@
27121 return 0;
27122 return security_ops->path_unlink(dir, dentry);
27123 }
27124+EXPORT_SYMBOL(security_path_unlink);
27125
27126 int security_path_symlink(struct path *dir, struct dentry *dentry,
27127 const char *old_name)
27128@@ -433,6 +436,7 @@
27129 return 0;
27130 return security_ops->path_symlink(dir, dentry, old_name);
27131 }
27132+EXPORT_SYMBOL(security_path_symlink);
27133
27134 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
27135 struct dentry *new_dentry)
27136@@ -441,6 +445,7 @@
27137 return 0;
27138 return security_ops->path_link(old_dentry, new_dir, new_dentry);
27139 }
27140+EXPORT_SYMBOL(security_path_link);
27141
27142 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
27143 struct path *new_dir, struct dentry *new_dentry)
27144@@ -451,6 +456,7 @@
27145 return security_ops->path_rename(old_dir, old_dentry, new_dir,
27146 new_dentry);
27147 }
27148+EXPORT_SYMBOL(security_path_rename);
27149
27150 int security_path_truncate(struct path *path, loff_t length,
27151 unsigned int time_attrs)
27152@@ -459,6 +465,7 @@
27153 return 0;
27154 return security_ops->path_truncate(path, length, time_attrs);
27155 }
27156+EXPORT_SYMBOL(security_path_truncate);
27157
27158 int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
27159 mode_t mode)
27160@@ -467,6 +474,7 @@
27161 return 0;
27162 return security_ops->path_chmod(dentry, mnt, mode);
27163 }
27164+EXPORT_SYMBOL(security_path_chmod);
27165
27166 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
27167 {
27168@@ -474,6 +482,7 @@
27169 return 0;
27170 return security_ops->path_chown(path, uid, gid);
27171 }
27172+EXPORT_SYMBOL(security_path_chown);
27173
27174 int security_path_chroot(struct path *path)
27175 {
27176@@ -550,6 +559,7 @@
27177 return 0;
27178 return security_ops->inode_readlink(dentry);
27179 }
27180+EXPORT_SYMBOL(security_inode_readlink);
27181
27182 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
27183 {
27184@@ -564,6 +574,7 @@
27185 return 0;
27186 return security_ops->inode_permission(inode, mask);
27187 }
27188+EXPORT_SYMBOL(security_inode_permission);
27189
27190 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
27191 {
27192@@ -664,6 +675,7 @@
27193 {
27194 return security_ops->file_permission(file, mask);
27195 }
27196+EXPORT_SYMBOL(security_file_permission);
27197
27198 int security_file_alloc(struct file *file)
27199 {
27200@@ -691,6 +703,7 @@
27201 return ret;
27202 return ima_file_mmap(file, prot);
27203 }
27204+EXPORT_SYMBOL(security_file_mmap);
27205
27206 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
27207 unsigned long prot)
This page took 7.634639 seconds and 4 git commands to generate.