]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs2.patch
- mount devtmpfs by default
[packages/kernel.git] / kernel-aufs2.patch
CommitLineData
e49829fe 1--- /dev/null
0c5527e5 2+++ linux-2.6/Documentation/ABI/testing/debugfs-aufs 2010-10-25 14:20:44.000000000 +0200
4a4d8108 3@@ -0,0 +1,37 @@
1facf9fc 4+What: /debug/aufs/si_<id>/
5+Date: March 2009
6+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
7+Description:
8+ Under /debug/aufs, a directory named si_<id> is created
9+ per aufs mount, where <id> is a unique id generated
10+ internally.
11+
12+What: /debug/aufs/si_<id>/xib
13+Date: March 2009
14+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
15+Description:
16+ It shows the consumed blocks by xib (External Inode Number
17+ Bitmap), its block size and file size.
18+ When the aufs mount option 'noxino' is specified, it
4a4d8108 19+ will be empty. About XINO files, see the aufs manual.
1facf9fc 20+
21+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
22+Date: March 2009
23+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
24+Description:
25+ It shows the consumed blocks by xino (External Inode Number
26+ Translation Table), its link count, block size and file
27+ size.
28+ When the aufs mount option 'noxino' is specified, it
4a4d8108 29+ will be empty. About XINO files, see the aufs manual.
1facf9fc 30+
31+What: /debug/aufs/si_<id>/xigen
32+Date: March 2009
33+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
34+Description:
35+ It shows the consumed blocks by xigen (External Inode
36+ Generation Table), its block size and file size.
37+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
38+ be created.
39+ When the aufs mount option 'noxino' is specified, it
4a4d8108 40+ will be empty. About XINO files, see the aufs manual.
e49829fe 41--- /dev/null
0c5527e5 42+++ linux-2.6/Documentation/ABI/testing/sysfs-aufs 2010-10-25 14:20:44.000000000 +0200
4a4d8108 43@@ -0,0 +1,24 @@
1facf9fc 44+What: /sys/fs/aufs/si_<id>/
45+Date: March 2009
46+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
47+Description:
48+ Under /sys/fs/aufs, a directory named si_<id> is created
49+ per aufs mount, where <id> is a unique id generated
50+ internally.
51+
52+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
53+Date: March 2009
54+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
55+Description:
56+ It shows the abolute path of a member directory (which
57+ is called branch) in aufs, and its permission.
58+
59+What: /sys/fs/aufs/si_<id>/xi_path
60+Date: March 2009
61+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
62+Description:
63+ It shows the abolute path of XINO (External Inode Number
64+ Bitmap, Translation Table and Generation Table) file
65+ even if it is the default path.
66+ When the aufs mount option 'noxino' is specified, it
4a4d8108 67+ will be empty. About XINO files, see the aufs manual.
e49829fe 68--- /dev/null
0c5527e5 69+++ linux-2.6/fs/aufs/aufs.h 2010-10-25 14:20:44.000000000 +0200
4a4d8108 70@@ -0,0 +1,61 @@
1facf9fc 71+/*
4a4d8108 72+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 73+ *
74+ * This program, aufs is free software; you can redistribute it and/or modify
75+ * it under the terms of the GNU General Public License as published by
76+ * the Free Software Foundation; either version 2 of the License, or
77+ * (at your option) any later version.
dece6358
AM
78+ *
79+ * This program is distributed in the hope that it will be useful,
80+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
81+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82+ * GNU General Public License for more details.
83+ *
84+ * You should have received a copy of the GNU General Public License
85+ * along with this program; if not, write to the Free Software
86+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 87+ */
88+
89+/*
90+ * all header files
91+ */
92+
93+#ifndef __AUFS_H__
94+#define __AUFS_H__
95+
96+#ifdef __KERNEL__
97+
4a4d8108
AM
98+#define AuStub(type, name, body, ...) \
99+ static inline type name(__VA_ARGS__) { body; }
100+
101+#define AuStubVoid(name, ...) \
102+ AuStub(void, name, , __VA_ARGS__)
103+#define AuStubInt0(name, ...) \
104+ AuStub(int, name, return 0, __VA_ARGS__)
105+
1facf9fc 106+#include "debug.h"
107+
108+#include "branch.h"
109+#include "cpup.h"
110+#include "dcsub.h"
111+#include "dbgaufs.h"
112+#include "dentry.h"
113+#include "dir.h"
4a4d8108 114+#include "dynop.h"
1facf9fc 115+#include "file.h"
116+#include "fstype.h"
117+#include "inode.h"
118+#include "loop.h"
119+#include "module.h"
4a4d8108 120+/* never include ./mtx.h */
1facf9fc 121+#include "opts.h"
122+#include "rwsem.h"
123+#include "spl.h"
124+#include "super.h"
125+#include "sysaufs.h"
126+#include "vfsub.h"
127+#include "whout.h"
128+#include "wkq.h"
129+
130+#endif /* __KERNEL__ */
131+#endif /* __AUFS_H__ */
e49829fe 132--- /dev/null
0c5527e5
AM
133+++ linux-2.6/fs/aufs/branch.c 2010-11-03 09:26:13.000000000 +0100
134@@ -0,0 +1,1008 @@
1facf9fc 135+/*
4a4d8108 136+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 137+ *
138+ * This program, aufs is free software; you can redistribute it and/or modify
139+ * it under the terms of the GNU General Public License as published by
140+ * the Free Software Foundation; either version 2 of the License, or
141+ * (at your option) any later version.
dece6358
AM
142+ *
143+ * This program is distributed in the hope that it will be useful,
144+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
145+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
146+ * GNU General Public License for more details.
147+ *
148+ * You should have received a copy of the GNU General Public License
149+ * along with this program; if not, write to the Free Software
150+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 151+ */
152+
153+/*
154+ * branch management
155+ */
156+
dece6358 157+#include <linux/file.h>
4a4d8108 158+#include <linux/statfs.h>
1facf9fc 159+#include "aufs.h"
160+
161+/*
162+ * free a single branch
163+ */
164+static void au_br_do_free(struct au_branch *br)
165+{
166+ int i;
167+ struct au_wbr *wbr;
4a4d8108 168+ struct au_dykey **key;
1facf9fc 169+
170+ if (br->br_xino.xi_file)
171+ fput(br->br_xino.xi_file);
172+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
173+
174+ AuDebugOn(atomic_read(&br->br_count));
175+
176+ wbr = br->br_wbr;
177+ if (wbr) {
178+ for (i = 0; i < AuBrWh_Last; i++)
179+ dput(wbr->wbr_wh[i]);
180+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 181+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 182+ }
183+
4a4d8108
AM
184+ key = br->br_dykey;
185+ for (i = 0; i < AuBrDynOp; i++, key++)
186+ if (*key)
187+ au_dy_put(*key);
188+ else
189+ break;
190+
1facf9fc 191+ mntput(br->br_mnt);
1facf9fc 192+ kfree(wbr);
193+ kfree(br);
194+}
195+
196+/*
197+ * frees all branches
198+ */
199+void au_br_free(struct au_sbinfo *sbinfo)
200+{
201+ aufs_bindex_t bmax;
202+ struct au_branch **br;
203+
dece6358
AM
204+ AuRwMustWriteLock(&sbinfo->si_rwsem);
205+
1facf9fc 206+ bmax = sbinfo->si_bend + 1;
207+ br = sbinfo->si_branch;
208+ while (bmax--)
209+ au_br_do_free(*br++);
210+}
211+
212+/*
213+ * find the index of a branch which is specified by @br_id.
214+ */
215+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
216+{
217+ aufs_bindex_t bindex, bend;
218+
219+ bend = au_sbend(sb);
220+ for (bindex = 0; bindex <= bend; bindex++)
221+ if (au_sbr_id(sb, bindex) == br_id)
222+ return bindex;
223+ return -1;
224+}
225+
226+/* ---------------------------------------------------------------------- */
227+
228+/*
229+ * add a branch
230+ */
231+
b752ccd1
AM
232+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
233+ struct dentry *h_root)
1facf9fc 234+{
b752ccd1
AM
235+ if (unlikely(h_adding == h_root
236+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 237+ return 1;
b752ccd1
AM
238+ if (h_adding->d_sb != h_root->d_sb)
239+ return 0;
240+ return au_test_subdir(h_adding, h_root)
241+ || au_test_subdir(h_root, h_adding);
1facf9fc 242+}
243+
244+/*
245+ * returns a newly allocated branch. @new_nbranch is a number of branches
246+ * after adding a branch.
247+ */
248+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
249+ int perm)
250+{
251+ struct au_branch *add_branch;
252+ struct dentry *root;
4a4d8108 253+ int err;
1facf9fc 254+
4a4d8108 255+ err = -ENOMEM;
1facf9fc 256+ root = sb->s_root;
257+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
258+ if (unlikely(!add_branch))
259+ goto out;
260+
261+ add_branch->br_wbr = NULL;
262+ if (au_br_writable(perm)) {
263+ /* may be freed separately at changing the branch permission */
264+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
265+ GFP_NOFS);
266+ if (unlikely(!add_branch->br_wbr))
267+ goto out_br;
268+ }
269+
4a4d8108
AM
270+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
271+ if (!err)
272+ err = au_di_realloc(au_di(root), new_nbranch);
273+ if (!err)
274+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
275+ if (!err)
276+ return add_branch; /* success */
1facf9fc 277+
1facf9fc 278+ kfree(add_branch->br_wbr);
4a4d8108 279+
4f0767ce 280+out_br:
1facf9fc 281+ kfree(add_branch);
4f0767ce 282+out:
4a4d8108 283+ return ERR_PTR(err);
1facf9fc 284+}
285+
286+/*
287+ * test if the branch permission is legal or not.
288+ */
289+static int test_br(struct inode *inode, int brperm, char *path)
290+{
291+ int err;
292+
4a4d8108
AM
293+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
294+ if (!err)
295+ goto out;
1facf9fc 296+
4a4d8108
AM
297+ err = -EINVAL;
298+ pr_err("write permission for readonly mount or inode, %s\n", path);
299+
4f0767ce 300+out:
1facf9fc 301+ return err;
302+}
303+
304+/*
305+ * returns:
306+ * 0: success, the caller will add it
307+ * plus: success, it is already unified, the caller should ignore it
308+ * minus: error
309+ */
310+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
311+{
312+ int err;
313+ aufs_bindex_t bend, bindex;
314+ struct dentry *root;
315+ struct inode *inode, *h_inode;
316+
317+ root = sb->s_root;
318+ bend = au_sbend(sb);
319+ if (unlikely(bend >= 0
320+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
321+ err = 1;
322+ if (!remount) {
323+ err = -EINVAL;
4a4d8108 324+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 325+ }
326+ goto out;
327+ }
328+
329+ err = -ENOSPC; /* -E2BIG; */
330+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
331+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 332+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 333+ goto out;
334+ }
335+
336+ err = -EDOM;
337+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 338+ pr_err("bad index %d\n", add->bindex);
1facf9fc 339+ goto out;
340+ }
341+
342+ inode = add->path.dentry->d_inode;
343+ err = -ENOENT;
344+ if (unlikely(!inode->i_nlink)) {
4a4d8108 345+ pr_err("no existence %s\n", add->pathname);
1facf9fc 346+ goto out;
347+ }
348+
349+ err = -EINVAL;
350+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 351+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 352+ goto out;
353+ }
354+
355+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
356+ pr_err("unsupported filesystem, %s (%s)\n",
357+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 358+ goto out;
359+ }
360+
361+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
362+ if (unlikely(err))
363+ goto out;
364+
365+ if (bend < 0)
366+ return 0; /* success */
367+
368+ err = -EINVAL;
369+ for (bindex = 0; bindex <= bend; bindex++)
370+ if (unlikely(test_overlap(sb, add->path.dentry,
371+ au_h_dptr(root, bindex)))) {
4a4d8108 372+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 373+ goto out;
374+ }
375+
376+ err = 0;
377+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
378+ h_inode = au_h_dptr(root, 0)->d_inode;
379+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
380+ || h_inode->i_uid != inode->i_uid
381+ || h_inode->i_gid != inode->i_gid)
4a4d8108
AM
382+ pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
383+ add->pathname,
384+ inode->i_uid, inode->i_gid,
385+ (inode->i_mode & S_IALLUGO),
386+ h_inode->i_uid, h_inode->i_gid,
387+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 388+ }
389+
4f0767ce 390+out:
1facf9fc 391+ return err;
392+}
393+
394+/*
395+ * initialize or clean the whiteouts for an adding branch
396+ */
397+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
398+ int new_perm, struct dentry *h_root)
399+{
400+ int err, old_perm;
401+ aufs_bindex_t bindex;
402+ struct mutex *h_mtx;
403+ struct au_wbr *wbr;
404+ struct au_hinode *hdir;
405+
406+ wbr = br->br_wbr;
407+ old_perm = br->br_perm;
408+ br->br_perm = new_perm;
409+ hdir = NULL;
410+ h_mtx = NULL;
411+ bindex = au_br_index(sb, br->br_id);
412+ if (0 <= bindex) {
413+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 414+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 415+ } else {
416+ h_mtx = &h_root->d_inode->i_mutex;
417+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
418+ }
419+ if (!wbr)
420+ err = au_wh_init(h_root, br, sb);
421+ else {
422+ wbr_wh_write_lock(wbr);
423+ err = au_wh_init(h_root, br, sb);
424+ wbr_wh_write_unlock(wbr);
425+ }
426+ if (hdir)
4a4d8108 427+ au_hn_imtx_unlock(hdir);
1facf9fc 428+ else
429+ mutex_unlock(h_mtx);
430+ br->br_perm = old_perm;
431+
432+ if (!err && wbr && !au_br_writable(new_perm)) {
433+ kfree(wbr);
434+ br->br_wbr = NULL;
435+ }
436+
437+ return err;
438+}
439+
440+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
441+ int perm, struct path *path)
442+{
443+ int err;
4a4d8108 444+ struct kstatfs kst;
1facf9fc 445+ struct au_wbr *wbr;
4a4d8108 446+ struct dentry *h_dentry;
1facf9fc 447+
448+ wbr = br->br_wbr;
dece6358 449+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 450+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
451+ atomic_set(&wbr->wbr_wh_running, 0);
452+ wbr->wbr_bytes = 0;
453+
4a4d8108
AM
454+ /*
455+ * a limit for rmdir/rename a dir
456+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
457+ */
e49829fe 458+ h_dentry = path->dentry;
0c5527e5 459+ err = statfs_by_dentry(h_dentry, &kst);
4a4d8108
AM
460+ if (unlikely(err))
461+ goto out;
462+ err = -EINVAL;
463+ if (kst.f_namelen >= NAME_MAX)
464+ err = au_br_init_wh(sb, br, perm, h_dentry);
465+ else
466+ pr_err("%.*s(%s), unsupported namelen %ld\n",
467+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
468+ kst.f_namelen);
1facf9fc 469+
4f0767ce 470+out:
1facf9fc 471+ return err;
472+}
473+
474+/* intialize a new branch */
475+static int au_br_init(struct au_branch *br, struct super_block *sb,
476+ struct au_opt_add *add)
477+{
478+ int err;
479+
480+ err = 0;
481+ memset(&br->br_xino, 0, sizeof(br->br_xino));
482+ mutex_init(&br->br_xino.xi_nondir_mtx);
483+ br->br_perm = add->perm;
484+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
485+ spin_lock_init(&br->br_dykey_lock);
486+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 487+ atomic_set(&br->br_count, 0);
488+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
489+ atomic_set(&br->br_xino_running, 0);
490+ br->br_id = au_new_br_id(sb);
491+
492+ if (au_br_writable(add->perm)) {
493+ err = au_wbr_init(br, sb, add->perm, &add->path);
494+ if (unlikely(err))
b752ccd1 495+ goto out_err;
1facf9fc 496+ }
497+
498+ if (au_opt_test(au_mntflags(sb), XINO)) {
499+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
500+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
501+ if (unlikely(err)) {
502+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 503+ goto out_err;
1facf9fc 504+ }
505+ }
506+
507+ sysaufs_br_init(br);
508+ mntget(add->path.mnt);
b752ccd1 509+ goto out; /* success */
1facf9fc 510+
4f0767ce 511+out_err:
b752ccd1 512+ br->br_mnt = NULL;
4f0767ce 513+out:
1facf9fc 514+ return err;
515+}
516+
517+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
518+ struct au_branch *br, aufs_bindex_t bend,
519+ aufs_bindex_t amount)
520+{
521+ struct au_branch **brp;
522+
dece6358
AM
523+ AuRwMustWriteLock(&sbinfo->si_rwsem);
524+
1facf9fc 525+ brp = sbinfo->si_branch + bindex;
526+ memmove(brp + 1, brp, sizeof(*brp) * amount);
527+ *brp = br;
528+ sbinfo->si_bend++;
529+ if (unlikely(bend < 0))
530+ sbinfo->si_bend = 0;
531+}
532+
533+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
534+ aufs_bindex_t bend, aufs_bindex_t amount)
535+{
536+ struct au_hdentry *hdp;
537+
1308ab2a 538+ AuRwMustWriteLock(&dinfo->di_rwsem);
539+
1facf9fc 540+ hdp = dinfo->di_hdentry + bindex;
541+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
542+ au_h_dentry_init(hdp);
543+ dinfo->di_bend++;
544+ if (unlikely(bend < 0))
545+ dinfo->di_bstart = 0;
546+}
547+
548+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
549+ aufs_bindex_t bend, aufs_bindex_t amount)
550+{
551+ struct au_hinode *hip;
552+
1308ab2a 553+ AuRwMustWriteLock(&iinfo->ii_rwsem);
554+
1facf9fc 555+ hip = iinfo->ii_hinode + bindex;
556+ memmove(hip + 1, hip, sizeof(*hip) * amount);
557+ hip->hi_inode = NULL;
4a4d8108 558+ au_hn_init(hip);
1facf9fc 559+ iinfo->ii_bend++;
560+ if (unlikely(bend < 0))
561+ iinfo->ii_bstart = 0;
562+}
563+
564+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
565+ struct au_branch *br, aufs_bindex_t bindex)
566+{
567+ struct dentry *root;
568+ struct inode *root_inode;
569+ aufs_bindex_t bend, amount;
570+
571+ root = sb->s_root;
572+ root_inode = root->d_inode;
1facf9fc 573+ bend = au_sbend(sb);
574+ amount = bend + 1 - bindex;
575+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
576+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
577+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
578+ au_set_h_dptr(root, bindex, dget(h_dentry));
579+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
580+ /*flags*/0);
581+}
582+
583+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
584+{
585+ int err;
1facf9fc 586+ aufs_bindex_t bend, add_bindex;
587+ struct dentry *root, *h_dentry;
588+ struct inode *root_inode;
589+ struct au_branch *add_branch;
590+
591+ root = sb->s_root;
592+ root_inode = root->d_inode;
593+ IMustLock(root_inode);
594+ err = test_add(sb, add, remount);
595+ if (unlikely(err < 0))
596+ goto out;
597+ if (err) {
598+ err = 0;
599+ goto out; /* success */
600+ }
601+
602+ bend = au_sbend(sb);
603+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
604+ err = PTR_ERR(add_branch);
605+ if (IS_ERR(add_branch))
606+ goto out;
607+
608+ err = au_br_init(add_branch, sb, add);
609+ if (unlikely(err)) {
610+ au_br_do_free(add_branch);
611+ goto out;
612+ }
613+
614+ add_bindex = add->bindex;
615+ h_dentry = add->path.dentry;
616+ if (!remount)
617+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
618+ else {
619+ sysaufs_brs_del(sb, add_bindex);
620+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
621+ sysaufs_brs_add(sb, add_bindex);
622+ }
623+
1308ab2a 624+ if (!add_bindex) {
1facf9fc 625+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 626+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
627+ } else
1facf9fc 628+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 629+
630+ /*
4a4d8108 631+ * this test/set prevents aufs from handling unnecesary notify events
1facf9fc 632+ * of xino files, in a case of re-adding a writable branch which was
633+ * once detached from aufs.
634+ */
635+ if (au_xino_brid(sb) < 0
636+ && au_br_writable(add_branch->br_perm)
637+ && !au_test_fs_bad_xino(h_dentry->d_sb)
638+ && add_branch->br_xino.xi_file
639+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
640+ au_xino_brid_set(sb, add_branch->br_id);
641+
4f0767ce 642+out:
1facf9fc 643+ return err;
644+}
645+
646+/* ---------------------------------------------------------------------- */
647+
648+/*
649+ * delete a branch
650+ */
651+
652+/* to show the line number, do not make it inlined function */
4a4d8108 653+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 654+ if (do_info) \
4a4d8108 655+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 656+} while (0)
657+
658+/*
659+ * test if the branch is deletable or not.
660+ */
661+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 662+ unsigned int sigen, const unsigned int verbose)
1facf9fc 663+{
664+ int err, i, j, ndentry;
665+ aufs_bindex_t bstart, bend;
1facf9fc 666+ struct au_dcsub_pages dpages;
667+ struct au_dpage *dpage;
668+ struct dentry *d;
669+ struct inode *inode;
670+
671+ err = au_dpages_init(&dpages, GFP_NOFS);
672+ if (unlikely(err))
673+ goto out;
674+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
675+ if (unlikely(err))
676+ goto out_dpages;
677+
1facf9fc 678+ for (i = 0; !err && i < dpages.ndpage; i++) {
679+ dpage = dpages.dpages + i;
680+ ndentry = dpage->ndentry;
681+ for (j = 0; !err && j < ndentry; j++) {
682+ d = dpage->dentries[j];
683+ AuDebugOn(!atomic_read(&d->d_count));
684+ inode = d->d_inode;
685+ if (au_digen(d) == sigen && au_iigen(inode) == sigen)
686+ di_read_lock_child(d, AuLock_IR);
687+ else {
688+ di_write_lock_child(d);
689+ err = au_reval_dpath(d, sigen);
690+ if (!err)
691+ di_downgrade_lock(d, AuLock_IR);
692+ else {
693+ di_write_unlock(d);
694+ break;
695+ }
696+ }
697+
698+ bstart = au_dbstart(d);
699+ bend = au_dbend(d);
700+ if (bstart <= bindex
701+ && bindex <= bend
702+ && au_h_dptr(d, bindex)
703+ && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
704+ err = -EBUSY;
705+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
706+ }
707+ di_read_unlock(d, AuLock_IR);
708+ }
709+ }
710+
4f0767ce 711+out_dpages:
1facf9fc 712+ au_dpages_free(&dpages);
4f0767ce 713+out:
1facf9fc 714+ return err;
715+}
716+
717+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 718+ unsigned int sigen, const unsigned int verbose)
1facf9fc 719+{
720+ int err;
721+ struct inode *i;
722+ aufs_bindex_t bstart, bend;
1facf9fc 723+
724+ err = 0;
1facf9fc 725+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
726+ AuDebugOn(!atomic_read(&i->i_count));
727+ if (!list_empty(&i->i_dentry))
728+ continue;
729+
730+ if (au_iigen(i) == sigen)
731+ ii_read_lock_child(i);
732+ else {
733+ ii_write_lock_child(i);
734+ err = au_refresh_hinode_self(i, /*do_attr*/1);
735+ if (!err)
736+ ii_downgrade_lock(i);
737+ else {
738+ ii_write_unlock(i);
739+ break;
740+ }
741+ }
742+
743+ bstart = au_ibstart(i);
744+ bend = au_ibend(i);
745+ if (bstart <= bindex
746+ && bindex <= bend
747+ && au_h_iptr(i, bindex)
748+ && (!S_ISDIR(i->i_mode) || bstart == bend)) {
749+ err = -EBUSY;
750+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
751+ ii_read_unlock(i);
752+ break;
753+ }
754+ ii_read_unlock(i);
755+ }
756+
757+ return err;
758+}
759+
b752ccd1
AM
760+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
761+ const unsigned int verbose)
1facf9fc 762+{
763+ int err;
764+ unsigned int sigen;
765+
766+ sigen = au_sigen(root->d_sb);
767+ DiMustNoWaiters(root);
768+ IiMustNoWaiters(root->d_inode);
769+ di_write_unlock(root);
b752ccd1 770+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 771+ if (!err)
b752ccd1 772+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 773+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
774+
775+ return err;
776+}
777+
778+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
779+ const aufs_bindex_t bindex,
780+ const aufs_bindex_t bend)
781+{
782+ struct au_branch **brp, **p;
783+
dece6358
AM
784+ AuRwMustWriteLock(&sbinfo->si_rwsem);
785+
1facf9fc 786+ brp = sbinfo->si_branch + bindex;
787+ if (bindex < bend)
788+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
789+ sbinfo->si_branch[0 + bend] = NULL;
790+ sbinfo->si_bend--;
791+
792+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
793+ if (p)
794+ sbinfo->si_branch = p;
4a4d8108 795+ /* harmless error */
1facf9fc 796+}
797+
798+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
799+ const aufs_bindex_t bend)
800+{
801+ struct au_hdentry *hdp, *p;
802+
1308ab2a 803+ AuRwMustWriteLock(&dinfo->di_rwsem);
804+
4a4d8108 805+ hdp = dinfo->di_hdentry;
1facf9fc 806+ if (bindex < bend)
4a4d8108
AM
807+ memmove(hdp + bindex, hdp + bindex + 1,
808+ sizeof(*hdp) * (bend - bindex));
809+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 810+ dinfo->di_bend--;
811+
4a4d8108 812+ p = krealloc(hdp, sizeof(*p) * bend, GFP_NOFS);
1facf9fc 813+ if (p)
814+ dinfo->di_hdentry = p;
4a4d8108 815+ /* harmless error */
1facf9fc 816+}
817+
818+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
819+ const aufs_bindex_t bend)
820+{
821+ struct au_hinode *hip, *p;
822+
1308ab2a 823+ AuRwMustWriteLock(&iinfo->ii_rwsem);
824+
1facf9fc 825+ hip = iinfo->ii_hinode + bindex;
826+ if (bindex < bend)
827+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
828+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 829+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 830+ iinfo->ii_bend--;
831+
832+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
833+ if (p)
834+ iinfo->ii_hinode = p;
4a4d8108 835+ /* harmless error */
1facf9fc 836+}
837+
838+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
839+ struct au_branch *br)
840+{
841+ aufs_bindex_t bend;
842+ struct au_sbinfo *sbinfo;
843+ struct dentry *root;
844+ struct inode *inode;
845+
dece6358
AM
846+ SiMustWriteLock(sb);
847+
1facf9fc 848+ root = sb->s_root;
849+ inode = root->d_inode;
1facf9fc 850+ sbinfo = au_sbi(sb);
851+ bend = sbinfo->si_bend;
852+
853+ dput(au_h_dptr(root, bindex));
854+ au_hiput(au_hi(inode, bindex));
855+ au_br_do_free(br);
856+
857+ au_br_do_del_brp(sbinfo, bindex, bend);
858+ au_br_do_del_hdp(au_di(root), bindex, bend);
859+ au_br_do_del_hip(au_ii(inode), bindex, bend);
860+}
861+
862+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
863+{
864+ int err, rerr, i;
865+ unsigned int mnt_flags;
866+ aufs_bindex_t bindex, bend, br_id;
867+ unsigned char do_wh, verbose;
868+ struct au_branch *br;
869+ struct au_wbr *wbr;
870+
871+ err = 0;
872+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
873+ if (bindex < 0) {
874+ if (remount)
875+ goto out; /* success */
876+ err = -ENOENT;
4a4d8108 877+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 878+ goto out;
879+ }
880+ AuDbg("bindex b%d\n", bindex);
881+
882+ err = -EBUSY;
883+ mnt_flags = au_mntflags(sb);
884+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
885+ bend = au_sbend(sb);
886+ if (unlikely(!bend)) {
887+ AuVerbose(verbose, "no more branches left\n");
888+ goto out;
889+ }
890+ br = au_sbr(sb, bindex);
891+ i = atomic_read(&br->br_count);
892+ if (unlikely(i)) {
893+ AuVerbose(verbose, "%d file(s) opened\n", i);
e49829fe 894+ goto out;
1facf9fc 895+ }
896+
897+ wbr = br->br_wbr;
898+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
899+ if (do_wh) {
1308ab2a 900+ /* instead of WbrWhMustWriteLock(wbr) */
901+ SiMustWriteLock(sb);
1facf9fc 902+ for (i = 0; i < AuBrWh_Last; i++) {
903+ dput(wbr->wbr_wh[i]);
904+ wbr->wbr_wh[i] = NULL;
905+ }
906+ }
907+
b752ccd1 908+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 909+ if (unlikely(err)) {
910+ if (do_wh)
911+ goto out_wh;
912+ goto out;
913+ }
914+
915+ err = 0;
916+ br_id = br->br_id;
917+ if (!remount)
918+ au_br_do_del(sb, bindex, br);
919+ else {
920+ sysaufs_brs_del(sb, bindex);
921+ au_br_do_del(sb, bindex, br);
922+ sysaufs_brs_add(sb, bindex);
923+ }
924+
1308ab2a 925+ if (!bindex) {
1facf9fc 926+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 927+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
928+ } else
1facf9fc 929+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
930+ if (au_opt_test(mnt_flags, PLINK))
931+ au_plink_half_refresh(sb, br_id);
932+
b752ccd1 933+ if (au_xino_brid(sb) == br_id)
1facf9fc 934+ au_xino_brid_set(sb, -1);
935+ goto out; /* success */
936+
4f0767ce 937+out_wh:
1facf9fc 938+ /* revert */
939+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
940+ if (rerr)
4a4d8108
AM
941+ pr_warning("failed re-creating base whiteout, %s. (%d)\n",
942+ del->pathname, rerr);
4f0767ce 943+out:
1facf9fc 944+ return err;
945+}
946+
947+/* ---------------------------------------------------------------------- */
948+
949+/*
950+ * change a branch permission
951+ */
952+
dece6358
AM
953+static void au_warn_ima(void)
954+{
955+#ifdef CONFIG_IMA
1308ab2a 956+ /* since it doesn't support mark_files_ro() */
e49829fe 957+ AuWarn1("RW -> RO makes IMA to produce wrong message");
dece6358
AM
958+#endif
959+}
960+
1facf9fc 961+static int do_need_sigen_inc(int a, int b)
962+{
963+ return au_br_whable(a) && !au_br_whable(b);
964+}
965+
966+static int need_sigen_inc(int old, int new)
967+{
968+ return do_need_sigen_inc(old, new)
969+ || do_need_sigen_inc(new, old);
970+}
971+
972+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
973+{
974+ int err;
975+ unsigned long n, ul, bytes, files;
e49829fe 976+ aufs_bindex_t br_id;
1facf9fc 977+ struct file *file, *hf, **a;
e49829fe
JR
978+ struct dentry *dentry;
979+ struct inode *inode;
980+ struct au_hfile *hfile;
1facf9fc 981+ const int step_bytes = 1024, /* memory allocation unit */
982+ step_files = step_bytes / sizeof(*a);
983+
984+ err = -ENOMEM;
985+ n = 0;
986+ bytes = step_bytes;
987+ files = step_files;
988+ a = kmalloc(bytes, GFP_NOFS);
989+ if (unlikely(!a))
990+ goto out;
991+
992+ /* no need file_list_lock() since sbinfo is locked? defered? */
e49829fe 993+ br_id = au_sbr_id(sb, bindex);
0c5527e5 994+ do_file_list_for_each_entry(sb, file) {
1facf9fc 995+ if (special_file(file->f_dentry->d_inode->i_mode))
996+ continue;
e49829fe
JR
997+ dentry = file->f_dentry;
998+ inode = dentry->d_inode;
1facf9fc 999+
1000+ AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
1001+ fi_read_lock(file);
1002+ if (unlikely(au_test_mmapped(file))) {
1003+ err = -EBUSY;
1004+ FiMustNoWaiters(file);
1005+ fi_read_unlock(file);
1006+ goto out_free;
1007+ }
1008+
e49829fe
JR
1009+ hfile = &au_fi(file)->fi_htop;
1010+ hf = hfile->hf_file;
1011+ if (!S_ISREG(inode->i_mode)
1facf9fc 1012+ || !(file->f_mode & FMODE_WRITE)
e49829fe
JR
1013+ || hfile->hf_br->br_id != br_id
1014+ || !(hf->f_mode & FMODE_WRITE)) {
1facf9fc 1015+ FiMustNoWaiters(file);
1016+ fi_read_unlock(file);
1017+ continue;
1018+ }
1019+
1facf9fc 1020+ FiMustNoWaiters(file);
1021+ fi_read_unlock(file);
1022+
1023+ if (n < files)
1024+ a[n++] = hf;
1025+ else {
1026+ void *p;
1027+
1028+ err = -ENOMEM;
1029+ bytes += step_bytes;
1030+ files += step_files;
1031+ p = krealloc(a, bytes, GFP_NOFS);
1032+ if (p) {
1033+ a = p;
1034+ a[n++] = hf;
1035+ } else
1036+ goto out_free;
1037+ }
0c5527e5 1038+ } while_file_list_for_each_entry;
1facf9fc 1039+
1040+ err = 0;
dece6358
AM
1041+ if (n)
1042+ au_warn_ima();
1facf9fc 1043+ for (ul = 0; ul < n; ul++) {
1044+ /* todo: already flushed? */
1045+ /* cf. fs/super.c:mark_files_ro() */
1046+ hf = a[ul];
1047+ hf->f_mode &= ~FMODE_WRITE;
1048+ if (!file_check_writeable(hf)) {
1049+ file_release_write(hf);
1050+ mnt_drop_write(hf->f_vfsmnt);
1051+ }
1052+ }
1053+
4f0767ce 1054+out_free:
1facf9fc 1055+ kfree(a);
4f0767ce 1056+out:
1facf9fc 1057+ return err;
1058+}
1059+
1060+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1061+ int *do_update)
1062+{
1063+ int err, rerr;
1064+ aufs_bindex_t bindex;
1308ab2a 1065+ struct path path;
1facf9fc 1066+ struct dentry *root;
1067+ struct au_branch *br;
1068+
1069+ root = sb->s_root;
1facf9fc 1070+ bindex = au_find_dbindex(root, mod->h_root);
1071+ if (bindex < 0) {
1072+ if (remount)
1073+ return 0; /* success */
1074+ err = -ENOENT;
4a4d8108 1075+ pr_err("%s no such branch\n", mod->path);
1facf9fc 1076+ goto out;
1077+ }
1078+ AuDbg("bindex b%d\n", bindex);
1079+
1080+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
1081+ if (unlikely(err))
1082+ goto out;
1083+
1084+ br = au_sbr(sb, bindex);
1085+ if (br->br_perm == mod->perm)
1086+ return 0; /* success */
1087+
1088+ if (au_br_writable(br->br_perm)) {
1089+ /* remove whiteout base */
1090+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
1091+ if (unlikely(err))
1092+ goto out;
1093+
1094+ if (!au_br_writable(mod->perm)) {
1095+ /* rw --> ro, file might be mmapped */
1096+ DiMustNoWaiters(root);
1097+ IiMustNoWaiters(root->d_inode);
1098+ di_write_unlock(root);
1099+ err = au_br_mod_files_ro(sb, bindex);
1100+ /* aufs_write_lock() calls ..._child() */
1101+ di_write_lock_child(root);
1102+
1103+ if (unlikely(err)) {
1104+ rerr = -ENOMEM;
1105+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
1106+ GFP_NOFS);
1308ab2a 1107+ if (br->br_wbr) {
1108+ path.mnt = br->br_mnt;
1109+ path.dentry = mod->h_root;
1110+ rerr = au_wbr_init(br, sb, br->br_perm,
1111+ &path);
1112+ }
1facf9fc 1113+ if (unlikely(rerr)) {
1114+ AuIOErr("nested error %d (%d)\n",
1115+ rerr, err);
1116+ br->br_perm = mod->perm;
1117+ }
1118+ }
1119+ }
1120+ } else if (au_br_writable(mod->perm)) {
1121+ /* ro --> rw */
1122+ err = -ENOMEM;
1123+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1124+ if (br->br_wbr) {
1308ab2a 1125+ path.mnt = br->br_mnt;
1126+ path.dentry = mod->h_root;
1facf9fc 1127+ err = au_wbr_init(br, sb, mod->perm, &path);
1128+ if (unlikely(err)) {
1129+ kfree(br->br_wbr);
1130+ br->br_wbr = NULL;
1131+ }
1132+ }
1133+ }
1134+
1135+ if (!err) {
1136+ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
1137+ br->br_perm = mod->perm;
1138+ }
1139+
4f0767ce 1140+out:
1facf9fc 1141+ return err;
1142+}
e49829fe 1143--- /dev/null
0c5527e5 1144+++ linux-2.6/fs/aufs/branch.h 2010-10-25 14:20:44.000000000 +0200
b752ccd1 1145@@ -0,0 +1,224 @@
1facf9fc 1146+/*
4a4d8108 1147+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1148+ *
1149+ * This program, aufs is free software; you can redistribute it and/or modify
1150+ * it under the terms of the GNU General Public License as published by
1151+ * the Free Software Foundation; either version 2 of the License, or
1152+ * (at your option) any later version.
dece6358
AM
1153+ *
1154+ * This program is distributed in the hope that it will be useful,
1155+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1156+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1157+ * GNU General Public License for more details.
1158+ *
1159+ * You should have received a copy of the GNU General Public License
1160+ * along with this program; if not, write to the Free Software
1161+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1162+ */
1163+
1164+/*
1165+ * branch filesystems and xino for them
1166+ */
1167+
1168+#ifndef __AUFS_BRANCH_H__
1169+#define __AUFS_BRANCH_H__
1170+
1171+#ifdef __KERNEL__
1172+
1173+#include <linux/fs.h>
1174+#include <linux/mount.h>
1facf9fc 1175+#include <linux/aufs_type.h>
4a4d8108 1176+#include "dynop.h"
1facf9fc 1177+#include "rwsem.h"
1178+#include "super.h"
1179+
1180+/* ---------------------------------------------------------------------- */
1181+
1182+/* a xino file */
1183+struct au_xino_file {
1184+ struct file *xi_file;
1185+ struct mutex xi_nondir_mtx;
1186+
1187+ /* todo: make xino files an array to support huge inode number */
1188+
1189+#ifdef CONFIG_DEBUG_FS
1190+ struct dentry *xi_dbgaufs;
1191+#endif
1192+};
1193+
1194+/* members for writable branch only */
1195+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
1196+struct au_wbr {
dece6358 1197+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 1198+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 1199+ atomic_t wbr_wh_running;
1facf9fc 1200+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
1201+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
1202+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
1203+
1204+ /* mfs mode */
1205+ unsigned long long wbr_bytes;
1206+};
1207+
4a4d8108
AM
1208+/* ext2 has 3 types of operations at least, ext3 has 4 */
1209+#define AuBrDynOp (AuDyLast * 4)
1210+
1facf9fc 1211+/* protected by superblock rwsem */
1212+struct au_branch {
1213+ struct au_xino_file br_xino;
1214+
1215+ aufs_bindex_t br_id;
1216+
1217+ int br_perm;
1218+ struct vfsmount *br_mnt;
4a4d8108
AM
1219+ spinlock_t br_dykey_lock;
1220+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 1221+ atomic_t br_count;
1222+
1223+ struct au_wbr *br_wbr;
1224+
1225+ /* xino truncation */
1226+ blkcnt_t br_xino_upper; /* watermark in blocks */
1227+ atomic_t br_xino_running;
1228+
1229+#ifdef CONFIG_SYSFS
1230+ /* an entry under sysfs per mount-point */
1231+ char br_name[8];
1232+ struct attribute br_attr;
1233+#endif
1234+};
1235+
1236+/* ---------------------------------------------------------------------- */
1237+
1238+/* branch permission and attribute */
1239+enum {
1240+ AuBrPerm_RW, /* writable, linkable wh */
1241+ AuBrPerm_RO, /* readonly, no wh */
1242+ AuBrPerm_RR, /* natively readonly, no wh */
1243+
1244+ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
1245+
1246+ AuBrPerm_ROWH, /* whiteout-able */
1247+ AuBrPerm_RRWH, /* whiteout-able */
1248+
1249+ AuBrPerm_Last
1250+};
1251+
1252+static inline int au_br_writable(int brperm)
1253+{
1254+ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1255+}
1256+
1257+static inline int au_br_whable(int brperm)
1258+{
1259+ return brperm == AuBrPerm_RW
1260+ || brperm == AuBrPerm_ROWH
1261+ || brperm == AuBrPerm_RRWH;
1262+}
1263+
1264+static inline int au_br_rdonly(struct au_branch *br)
1265+{
1266+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1267+ || !au_br_writable(br->br_perm))
1268+ ? -EROFS : 0;
1269+}
1270+
4a4d8108 1271+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 1272+{
4a4d8108 1273+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 1274+ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1275+#else
1276+ return 0;
1277+#endif
1278+}
1279+
1280+/* ---------------------------------------------------------------------- */
1281+
1282+/* branch.c */
1283+struct au_sbinfo;
1284+void au_br_free(struct au_sbinfo *sinfo);
1285+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1286+struct au_opt_add;
1287+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1288+struct au_opt_del;
1289+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
1290+struct au_opt_mod;
1291+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
1292+ int *do_update);
1293+
1294+/* xino.c */
1295+static const loff_t au_loff_max = LLONG_MAX;
1296+
1297+int au_xib_trunc(struct super_block *sb);
1298+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1299+ loff_t *pos);
1300+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1301+ loff_t *pos);
1302+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
1303+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1304+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 1305+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 1306+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1307+ ino_t ino);
1308+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1309+ ino_t *ino);
1310+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1311+ struct file *base_file, int do_test);
1312+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1313+
1314+struct au_opt_xino;
1315+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1316+void au_xino_clr(struct super_block *sb);
1317+struct file *au_xino_def(struct super_block *sb);
1318+int au_xino_path(struct seq_file *seq, struct file *file);
1319+
1320+/* ---------------------------------------------------------------------- */
1321+
1322+/* Superblock to branch */
1323+static inline
1324+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1325+{
1326+ return au_sbr(sb, bindex)->br_id;
1327+}
1328+
1329+static inline
1330+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1331+{
1332+ return au_sbr(sb, bindex)->br_mnt;
1333+}
1334+
1335+static inline
1336+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1337+{
1338+ return au_sbr_mnt(sb, bindex)->mnt_sb;
1339+}
1340+
1341+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1342+{
e49829fe 1343+ atomic_dec(&au_sbr(sb, bindex)->br_count);
1facf9fc 1344+}
1345+
1346+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1347+{
1348+ return au_sbr(sb, bindex)->br_perm;
1349+}
1350+
1351+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1352+{
1353+ return au_br_whable(au_sbr_perm(sb, bindex));
1354+}
1355+
1356+/* ---------------------------------------------------------------------- */
1357+
1358+/*
1359+ * wbr_wh_read_lock, wbr_wh_write_lock
1360+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
1361+ */
1362+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
1363+
dece6358
AM
1364+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
1365+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
1366+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
1367+
1facf9fc 1368+#endif /* __KERNEL__ */
1369+#endif /* __AUFS_BRANCH_H__ */
e49829fe 1370--- /dev/null
0c5527e5 1371+++ linux-2.6/fs/aufs/conf.mk 2010-10-25 14:20:44.000000000 +0200
e49829fe 1372@@ -0,0 +1,37 @@
4a4d8108
AM
1373+
1374+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
1375+
1376+define AuConf
1377+ifdef ${1}
1378+AuConfStr += ${1}=${${1}}
1379+endif
1380+endef
1381+
b752ccd1 1382+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe
JR
1383+ SBILIST \
1384+ HNOTIFY HFSNOTIFY HINOTIFY \
4a4d8108
AM
1385+ EXPORT INO_T_64 \
1386+ RDU \
1387+ SP_IATTR \
1388+ SHWH \
1389+ BR_RAMFS \
1390+ BR_FUSE POLL \
1391+ BR_HFSPLUS \
1392+ BDEV_LOOP \
b752ccd1
AM
1393+ DEBUG MAGIC_SYSRQ
1394+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
1395+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
1396+
1397+AuConfName = ${obj}/conf.str
1398+${AuConfName}.tmp: FORCE
1399+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
1400+${AuConfName}: ${AuConfName}.tmp
1401+ @diff -q $< $@ > /dev/null 2>&1 || { \
1402+ echo ' GEN ' $@; \
1403+ cp -p $< $@; \
1404+ }
1405+FORCE:
1406+clean-files += ${AuConfName} ${AuConfName}.tmp
1407+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
1408+
1409+-include ${srctree}/${src}/conf_priv.mk
e49829fe 1410--- /dev/null
0c5527e5 1411+++ linux-2.6/fs/aufs/cpup.c 2010-10-25 14:20:44.000000000 +0200
b752ccd1 1412@@ -0,0 +1,1059 @@
1facf9fc 1413+/*
4a4d8108 1414+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 1415+ *
1416+ * This program, aufs is free software; you can redistribute it and/or modify
1417+ * it under the terms of the GNU General Public License as published by
1418+ * the Free Software Foundation; either version 2 of the License, or
1419+ * (at your option) any later version.
dece6358
AM
1420+ *
1421+ * This program is distributed in the hope that it will be useful,
1422+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1423+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1424+ * GNU General Public License for more details.
1425+ *
1426+ * You should have received a copy of the GNU General Public License
1427+ * along with this program; if not, write to the Free Software
1428+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1429+ */
1430+
1431+/*
1432+ * copy-up functions, see wbr_policy.c for copy-down
1433+ */
1434+
dece6358 1435+#include <linux/file.h>
1facf9fc 1436+#include <linux/fs_stack.h>
dece6358 1437+#include <linux/mm.h>
1facf9fc 1438+#include <linux/uaccess.h>
1439+#include "aufs.h"
1440+
1441+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
1442+{
1443+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
1444+ | S_NOATIME | S_NOCMTIME;
1445+
1446+ dst->i_flags |= src->i_flags & ~mask;
1447+ if (au_test_fs_notime(dst->i_sb))
1448+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
1449+}
1450+
1451+void au_cpup_attr_timesizes(struct inode *inode)
1452+{
1453+ struct inode *h_inode;
1454+
1455+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1456+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 1457+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 1458+}
1459+
1460+void au_cpup_attr_nlink(struct inode *inode, int force)
1461+{
1462+ struct inode *h_inode;
1463+ struct super_block *sb;
1464+ aufs_bindex_t bindex, bend;
1465+
1466+ sb = inode->i_sb;
1467+ bindex = au_ibstart(inode);
1468+ h_inode = au_h_iptr(inode, bindex);
1469+ if (!force
1470+ && !S_ISDIR(h_inode->i_mode)
1471+ && au_opt_test(au_mntflags(sb), PLINK)
1472+ && au_plink_test(inode))
1473+ return;
1474+
1475+ inode->i_nlink = h_inode->i_nlink;
1476+
1477+ /*
1478+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
1479+ * it may includes whplink directory.
1480+ */
1481+ if (S_ISDIR(h_inode->i_mode)) {
1482+ bend = au_ibend(inode);
1483+ for (bindex++; bindex <= bend; bindex++) {
1484+ h_inode = au_h_iptr(inode, bindex);
1485+ if (h_inode)
1486+ au_add_nlink(inode, h_inode);
1487+ }
1488+ }
1489+}
1490+
1491+void au_cpup_attr_changeable(struct inode *inode)
1492+{
1493+ struct inode *h_inode;
1494+
1495+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1496+ inode->i_mode = h_inode->i_mode;
1497+ inode->i_uid = h_inode->i_uid;
1498+ inode->i_gid = h_inode->i_gid;
1499+ au_cpup_attr_timesizes(inode);
1500+ au_cpup_attr_flags(inode, h_inode);
1501+}
1502+
1503+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
1504+{
1505+ struct au_iinfo *iinfo = au_ii(inode);
1506+
1308ab2a 1507+ IiMustWriteLock(inode);
1508+
1facf9fc 1509+ iinfo->ii_higen = h_inode->i_generation;
1510+ iinfo->ii_hsb1 = h_inode->i_sb;
1511+}
1512+
1513+void au_cpup_attr_all(struct inode *inode, int force)
1514+{
1515+ struct inode *h_inode;
1516+
1517+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1518+ au_cpup_attr_changeable(inode);
1519+ if (inode->i_nlink > 0)
1520+ au_cpup_attr_nlink(inode, force);
1521+ inode->i_rdev = h_inode->i_rdev;
1522+ inode->i_blkbits = h_inode->i_blkbits;
1523+ au_cpup_igen(inode, h_inode);
1524+}
1525+
1526+/* ---------------------------------------------------------------------- */
1527+
1528+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
1529+
1530+/* keep the timestamps of the parent dir when cpup */
1531+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
1532+ struct path *h_path)
1533+{
1534+ struct inode *h_inode;
1535+
1536+ dt->dt_dentry = dentry;
1537+ dt->dt_h_path = *h_path;
1538+ h_inode = h_path->dentry->d_inode;
1539+ dt->dt_atime = h_inode->i_atime;
1540+ dt->dt_mtime = h_inode->i_mtime;
1541+ /* smp_mb(); */
1542+}
1543+
1544+void au_dtime_revert(struct au_dtime *dt)
1545+{
1546+ struct iattr attr;
1547+ int err;
1548+
1549+ attr.ia_atime = dt->dt_atime;
1550+ attr.ia_mtime = dt->dt_mtime;
1551+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
1552+ | ATTR_ATIME | ATTR_ATIME_SET;
1553+
1554+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
1555+ if (unlikely(err))
4a4d8108 1556+ pr_warning("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 1557+}
1558+
1559+/* ---------------------------------------------------------------------- */
1560+
1561+static noinline_for_stack
1562+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
1563+{
1564+ int err, sbits;
1565+ struct iattr ia;
1566+ struct path h_path;
1308ab2a 1567+ struct inode *h_isrc, *h_idst;
1facf9fc 1568+
1569+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 1570+ h_idst = h_path.dentry->d_inode;
1facf9fc 1571+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
1572+ h_isrc = h_src->d_inode;
1308ab2a 1573+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 1574+ | ATTR_ATIME | ATTR_MTIME
1575+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 1576+ ia.ia_uid = h_isrc->i_uid;
1577+ ia.ia_gid = h_isrc->i_gid;
1578+ ia.ia_atime = h_isrc->i_atime;
1579+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 1580+ if (h_idst->i_mode != h_isrc->i_mode
1581+ && !S_ISLNK(h_idst->i_mode)) {
1582+ ia.ia_valid |= ATTR_MODE;
1583+ ia.ia_mode = h_isrc->i_mode;
1584+ }
1585+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
1586+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 1587+ err = vfsub_notify_change(&h_path, &ia);
1588+
1589+ /* is this nfs only? */
1590+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
1591+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
1592+ ia.ia_mode = h_isrc->i_mode;
1593+ err = vfsub_notify_change(&h_path, &ia);
1594+ }
1595+
1596+ return err;
1597+}
1598+
1599+/* ---------------------------------------------------------------------- */
1600+
1601+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
1602+ char *buf, unsigned long blksize)
1603+{
1604+ int err;
1605+ size_t sz, rbytes, wbytes;
1606+ unsigned char all_zero;
1607+ char *p, *zp;
1608+ struct mutex *h_mtx;
1609+ /* reduce stack usage */
1610+ struct iattr *ia;
1611+
1612+ zp = page_address(ZERO_PAGE(0));
1613+ if (unlikely(!zp))
1614+ return -ENOMEM; /* possible? */
1615+
1616+ err = 0;
1617+ all_zero = 0;
1618+ while (len) {
1619+ AuDbg("len %lld\n", len);
1620+ sz = blksize;
1621+ if (len < blksize)
1622+ sz = len;
1623+
1624+ rbytes = 0;
1625+ /* todo: signal_pending? */
1626+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
1627+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
1628+ err = rbytes;
1629+ }
1630+ if (unlikely(err < 0))
1631+ break;
1632+
1633+ all_zero = 0;
1634+ if (len >= rbytes && rbytes == blksize)
1635+ all_zero = !memcmp(buf, zp, rbytes);
1636+ if (!all_zero) {
1637+ wbytes = rbytes;
1638+ p = buf;
1639+ while (wbytes) {
1640+ size_t b;
1641+
1642+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
1643+ err = b;
1644+ /* todo: signal_pending? */
1645+ if (unlikely(err == -EAGAIN || err == -EINTR))
1646+ continue;
1647+ if (unlikely(err < 0))
1648+ break;
1649+ wbytes -= b;
1650+ p += b;
1651+ }
1652+ } else {
1653+ loff_t res;
1654+
1655+ AuLabel(hole);
1656+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
1657+ err = res;
1658+ if (unlikely(res < 0))
1659+ break;
1660+ }
1661+ len -= rbytes;
1662+ err = 0;
1663+ }
1664+
1665+ /* the last block may be a hole */
1666+ if (!err && all_zero) {
1667+ AuLabel(last hole);
1668+
1669+ err = 1;
1670+ if (au_test_nfs(dst->f_dentry->d_sb)) {
1671+ /* nfs requires this step to make last hole */
1672+ /* is this only nfs? */
1673+ do {
1674+ /* todo: signal_pending? */
1675+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
1676+ } while (err == -EAGAIN || err == -EINTR);
1677+ if (err == 1)
1678+ dst->f_pos--;
1679+ }
1680+
1681+ if (err == 1) {
1682+ ia = (void *)buf;
1683+ ia->ia_size = dst->f_pos;
1684+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
1685+ ia->ia_file = dst;
1686+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
1687+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
1688+ err = vfsub_notify_change(&dst->f_path, ia);
1689+ mutex_unlock(h_mtx);
1690+ }
1691+ }
1692+
1693+ return err;
1694+}
1695+
1696+int au_copy_file(struct file *dst, struct file *src, loff_t len)
1697+{
1698+ int err;
1699+ unsigned long blksize;
1700+ unsigned char do_kfree;
1701+ char *buf;
1702+
1703+ err = -ENOMEM;
1704+ blksize = dst->f_dentry->d_sb->s_blocksize;
1705+ if (!blksize || PAGE_SIZE < blksize)
1706+ blksize = PAGE_SIZE;
1707+ AuDbg("blksize %lu\n", blksize);
1708+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
1709+ if (do_kfree)
1710+ buf = kmalloc(blksize, GFP_NOFS);
1711+ else
1712+ buf = (void *)__get_free_page(GFP_NOFS);
1713+ if (unlikely(!buf))
1714+ goto out;
1715+
1716+ if (len > (1 << 22))
1717+ AuDbg("copying a large file %lld\n", (long long)len);
1718+
1719+ src->f_pos = 0;
1720+ dst->f_pos = 0;
1721+ err = au_do_copy_file(dst, src, len, buf, blksize);
1722+ if (do_kfree)
1723+ kfree(buf);
1724+ else
1725+ free_page((unsigned long)buf);
1726+
4f0767ce 1727+out:
1facf9fc 1728+ return err;
1729+}
1730+
1731+/*
1732+ * to support a sparse file which is opened with O_APPEND,
1733+ * we need to close the file.
1734+ */
1735+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 1736+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 1737+{
1738+ int err, i;
1739+ enum { SRC, DST };
1740+ struct {
1741+ aufs_bindex_t bindex;
1742+ unsigned int flags;
1743+ struct dentry *dentry;
1744+ struct file *file;
1745+ void *label, *label_file;
1746+ } *f, file[] = {
1747+ {
1748+ .bindex = bsrc,
1749+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
1750+ .file = NULL,
1751+ .label = &&out,
1752+ .label_file = &&out_src
1753+ },
1754+ {
1755+ .bindex = bdst,
1756+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
1757+ .file = NULL,
1758+ .label = &&out_src,
1759+ .label_file = &&out_dst
1760+ }
1761+ };
1762+ struct super_block *sb;
1763+
1764+ /* bsrc branch can be ro/rw. */
1765+ sb = dentry->d_sb;
1766+ f = file;
1767+ for (i = 0; i < 2; i++, f++) {
1768+ f->dentry = au_h_dptr(dentry, f->bindex);
1769+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
1770+ err = PTR_ERR(f->file);
1771+ if (IS_ERR(f->file))
1772+ goto *f->label;
1773+ err = -EINVAL;
1774+ if (unlikely(!f->file->f_op))
1775+ goto *f->label_file;
1776+ }
1777+
1778+ /* try stopping to update while we copyup */
1779+ IMustLock(file[SRC].dentry->d_inode);
1780+ err = au_copy_file(file[DST].file, file[SRC].file, len);
1781+
4f0767ce 1782+out_dst:
1facf9fc 1783+ fput(file[DST].file);
1784+ au_sbr_put(sb, file[DST].bindex);
4f0767ce 1785+out_src:
1facf9fc 1786+ fput(file[SRC].file);
1787+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 1788+out:
1facf9fc 1789+ return err;
1790+}
1791+
1792+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
1793+ aufs_bindex_t bsrc, loff_t len,
1794+ struct inode *h_dir, struct path *h_path)
1795+{
1796+ int err, rerr;
1797+ loff_t l;
1798+
1799+ err = 0;
1800+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
1801+ if (len == -1 || l < len)
1802+ len = l;
1803+ if (len)
1804+ err = au_cp_regular(dentry, bdst, bsrc, len);
1805+ if (!err)
1806+ goto out; /* success */
1807+
1808+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
1809+ if (rerr) {
1810+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
1811+ AuDLNPair(h_path->dentry), err, rerr);
1812+ err = -EIO;
1813+ }
1814+
4f0767ce 1815+out:
1facf9fc 1816+ return err;
1817+}
1818+
1819+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
1820+ struct inode *h_dir)
1821+{
1822+ int err, symlen;
1823+ mm_segment_t old_fs;
b752ccd1
AM
1824+ union {
1825+ char *k;
1826+ char __user *u;
1827+ } sym;
1facf9fc 1828+
1829+ err = -ENOSYS;
1830+ if (unlikely(!h_src->d_inode->i_op->readlink))
1831+ goto out;
1832+
1833+ err = -ENOMEM;
b752ccd1
AM
1834+ sym.k = __getname_gfp(GFP_NOFS);
1835+ if (unlikely(!sym.k))
1facf9fc 1836+ goto out;
1837+
1838+ old_fs = get_fs();
1839+ set_fs(KERNEL_DS);
b752ccd1 1840+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 1841+ err = symlen;
1842+ set_fs(old_fs);
1843+
1844+ if (symlen > 0) {
b752ccd1
AM
1845+ sym.k[symlen] = 0;
1846+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 1847+ }
b752ccd1 1848+ __putname(sym.k);
1facf9fc 1849+
4f0767ce 1850+out:
1facf9fc 1851+ return err;
1852+}
1853+
1854+/* return with the lower dst inode is locked */
1855+static noinline_for_stack
1856+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
1857+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
1858+ struct dentry *dst_parent)
1859+{
1860+ int err;
1861+ umode_t mode;
1862+ unsigned int mnt_flags;
1863+ unsigned char isdir;
1864+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
1865+ struct au_dtime dt;
1866+ struct path h_path;
1867+ struct dentry *h_src, *h_dst, *h_parent;
1868+ struct inode *h_inode, *h_dir;
1869+ struct super_block *sb;
1870+
1871+ /* bsrc branch can be ro/rw. */
1872+ h_src = au_h_dptr(dentry, bsrc);
1873+ h_inode = h_src->d_inode;
1874+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
1875+
1876+ /* try stopping to be referenced while we are creating */
1877+ h_dst = au_h_dptr(dentry, bdst);
1878+ h_parent = h_dst->d_parent; /* dir inode is locked */
1879+ h_dir = h_parent->d_inode;
1880+ IMustLock(h_dir);
1881+ AuDebugOn(h_parent != h_dst->d_parent);
1882+
1883+ sb = dentry->d_sb;
1884+ h_path.mnt = au_sbr_mnt(sb, bdst);
1885+ if (do_dt) {
1886+ h_path.dentry = h_parent;
1887+ au_dtime_store(&dt, dst_parent, &h_path);
1888+ }
1889+ h_path.dentry = h_dst;
1890+
1891+ isdir = 0;
1892+ mode = h_inode->i_mode;
1893+ switch (mode & S_IFMT) {
1894+ case S_IFREG:
1895+ /* try stopping to update while we are referencing */
1896+ IMustLock(h_inode);
1897+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
1898+ if (!err)
1899+ err = au_do_cpup_regular
1900+ (dentry, bdst, bsrc, len,
1901+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
1902+ break;
1903+ case S_IFDIR:
1904+ isdir = 1;
1905+ err = vfsub_mkdir(h_dir, &h_path, mode);
1906+ if (!err) {
1907+ /*
1908+ * strange behaviour from the users view,
1909+ * particularry setattr case
1910+ */
1911+ if (au_ibstart(dst_parent->d_inode) == bdst)
1912+ au_cpup_attr_nlink(dst_parent->d_inode,
1913+ /*force*/1);
1914+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
1915+ }
1916+ break;
1917+ case S_IFLNK:
1918+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
1919+ break;
1920+ case S_IFCHR:
1921+ case S_IFBLK:
1922+ AuDebugOn(!capable(CAP_MKNOD));
1923+ /*FALLTHROUGH*/
1924+ case S_IFIFO:
1925+ case S_IFSOCK:
1926+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
1927+ break;
1928+ default:
1929+ AuIOErr("Unknown inode type 0%o\n", mode);
1930+ err = -EIO;
1931+ }
1932+
1933+ mnt_flags = au_mntflags(sb);
1934+ if (!au_opt_test(mnt_flags, UDBA_NONE)
1935+ && !isdir
1936+ && au_opt_test(mnt_flags, XINO)
1937+ && h_inode->i_nlink == 1
1938+ /* todo: unnecessary? */
1939+ /* && dentry->d_inode->i_nlink == 1 */
1940+ && bdst < bsrc
1941+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 1942+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 1943+ /* ignore this error */
1944+
1945+ if (do_dt)
1946+ au_dtime_revert(&dt);
1947+ return err;
1948+}
1949+
1950+/*
1951+ * copyup the @dentry from @bsrc to @bdst.
1952+ * the caller must set the both of lower dentries.
1953+ * @len is for truncating when it is -1 copyup the entire file.
1954+ * in link/rename cases, @dst_parent may be different from the real one.
1955+ */
1956+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
1957+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
1958+ struct dentry *dst_parent)
1959+{
1960+ int err, rerr;
1961+ aufs_bindex_t old_ibstart;
1962+ unsigned char isdir, plink;
1963+ struct au_dtime dt;
1964+ struct path h_path;
1965+ struct dentry *h_src, *h_dst, *h_parent;
1966+ struct inode *dst_inode, *h_dir, *inode;
1967+ struct super_block *sb;
1968+
1969+ AuDebugOn(bsrc <= bdst);
1970+
1971+ sb = dentry->d_sb;
1972+ h_path.mnt = au_sbr_mnt(sb, bdst);
1973+ h_dst = au_h_dptr(dentry, bdst);
1974+ h_parent = h_dst->d_parent; /* dir inode is locked */
1975+ h_dir = h_parent->d_inode;
1976+ IMustLock(h_dir);
1977+
1978+ h_src = au_h_dptr(dentry, bsrc);
1979+ inode = dentry->d_inode;
1980+
1981+ if (!dst_parent)
1982+ dst_parent = dget_parent(dentry);
1983+ else
1984+ dget(dst_parent);
1985+
1986+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
1987+ dst_inode = au_h_iptr(inode, bdst);
1988+ if (dst_inode) {
1989+ if (unlikely(!plink)) {
1990+ err = -EIO;
1991+ AuIOErr("i%lu exists on a upper branch "
1992+ "but plink is disabled\n", inode->i_ino);
1993+ goto out;
1994+ }
1995+
1996+ if (dst_inode->i_nlink) {
1997+ const int do_dt = au_ftest_cpup(flags, DTIME);
1998+
1999+ h_src = au_plink_lkup(inode, bdst);
2000+ err = PTR_ERR(h_src);
2001+ if (IS_ERR(h_src))
2002+ goto out;
2003+ if (unlikely(!h_src->d_inode)) {
2004+ err = -EIO;
2005+ AuIOErr("i%lu exists on a upper branch "
2006+ "but plink is broken\n", inode->i_ino);
2007+ dput(h_src);
2008+ goto out;
2009+ }
2010+
2011+ if (do_dt) {
2012+ h_path.dentry = h_parent;
2013+ au_dtime_store(&dt, dst_parent, &h_path);
2014+ }
2015+ h_path.dentry = h_dst;
2016+ err = vfsub_link(h_src, h_dir, &h_path);
2017+ if (do_dt)
2018+ au_dtime_revert(&dt);
2019+ dput(h_src);
2020+ goto out;
2021+ } else
2022+ /* todo: cpup_wh_file? */
2023+ /* udba work */
4a4d8108 2024+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 2025+ }
2026+
2027+ old_ibstart = au_ibstart(inode);
2028+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
2029+ if (unlikely(err))
2030+ goto out;
2031+ dst_inode = h_dst->d_inode;
2032+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
2033+
2034+ err = cpup_iattr(dentry, bdst, h_src);
2035+ isdir = S_ISDIR(dst_inode->i_mode);
2036+ if (!err) {
4a4d8108
AM
2037+ if (bdst < old_ibstart) {
2038+ if (S_ISREG(inode->i_mode)) {
2039+ err = au_dy_iaop(inode, bdst, dst_inode);
2040+ if (unlikely(err))
2041+ goto out_rev;
2042+ }
1facf9fc 2043+ au_set_ibstart(inode, bdst);
4a4d8108 2044+ }
1facf9fc 2045+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
2046+ au_hi_flags(inode, isdir));
2047+ mutex_unlock(&dst_inode->i_mutex);
2048+ if (!isdir
2049+ && h_src->d_inode->i_nlink > 1
2050+ && plink)
2051+ au_plink_append(inode, bdst, h_dst);
2052+ goto out; /* success */
2053+ }
2054+
2055+ /* revert */
4a4d8108 2056+out_rev:
1facf9fc 2057+ h_path.dentry = h_parent;
2058+ mutex_unlock(&dst_inode->i_mutex);
2059+ au_dtime_store(&dt, dst_parent, &h_path);
2060+ h_path.dentry = h_dst;
2061+ if (!isdir)
2062+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
2063+ else
2064+ rerr = vfsub_rmdir(h_dir, &h_path);
2065+ au_dtime_revert(&dt);
2066+ if (rerr) {
2067+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
2068+ err = -EIO;
2069+ }
2070+
4f0767ce 2071+out:
1facf9fc 2072+ dput(dst_parent);
2073+ return err;
2074+}
2075+
2076+struct au_cpup_single_args {
2077+ int *errp;
2078+ struct dentry *dentry;
2079+ aufs_bindex_t bdst, bsrc;
2080+ loff_t len;
2081+ unsigned int flags;
2082+ struct dentry *dst_parent;
2083+};
2084+
2085+static void au_call_cpup_single(void *args)
2086+{
2087+ struct au_cpup_single_args *a = args;
2088+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
2089+ a->flags, a->dst_parent);
2090+}
2091+
2092+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2093+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2094+ struct dentry *dst_parent)
2095+{
2096+ int err, wkq_err;
2097+ umode_t mode;
2098+ struct dentry *h_dentry;
2099+
2100+ h_dentry = au_h_dptr(dentry, bsrc);
2101+ mode = h_dentry->d_inode->i_mode & S_IFMT;
2102+ if ((mode != S_IFCHR && mode != S_IFBLK)
2103+ || capable(CAP_MKNOD))
2104+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2105+ dst_parent);
2106+ else {
2107+ struct au_cpup_single_args args = {
2108+ .errp = &err,
2109+ .dentry = dentry,
2110+ .bdst = bdst,
2111+ .bsrc = bsrc,
2112+ .len = len,
2113+ .flags = flags,
2114+ .dst_parent = dst_parent
2115+ };
2116+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
2117+ if (unlikely(wkq_err))
2118+ err = wkq_err;
2119+ }
2120+
2121+ return err;
2122+}
2123+
2124+/*
2125+ * copyup the @dentry from the first active lower branch to @bdst,
2126+ * using au_cpup_single().
2127+ */
2128+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2129+ unsigned int flags)
2130+{
2131+ int err;
2132+ aufs_bindex_t bsrc, bend;
2133+
2134+ bend = au_dbend(dentry);
2135+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2136+ if (au_h_dptr(dentry, bsrc))
2137+ break;
2138+
2139+ err = au_lkup_neg(dentry, bdst);
2140+ if (!err) {
2141+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
2142+ if (!err)
2143+ return 0; /* success */
2144+
2145+ /* revert */
2146+ au_set_h_dptr(dentry, bdst, NULL);
2147+ au_set_dbstart(dentry, bsrc);
2148+ }
2149+
2150+ return err;
2151+}
2152+
2153+struct au_cpup_simple_args {
2154+ int *errp;
2155+ struct dentry *dentry;
2156+ aufs_bindex_t bdst;
2157+ loff_t len;
2158+ unsigned int flags;
2159+};
2160+
2161+static void au_call_cpup_simple(void *args)
2162+{
2163+ struct au_cpup_simple_args *a = args;
2164+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
2165+}
2166+
2167+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2168+ unsigned int flags)
2169+{
2170+ int err, wkq_err;
2171+ unsigned char do_sio;
2172+ struct dentry *parent;
2173+ struct inode *h_dir;
2174+
2175+ parent = dget_parent(dentry);
2176+ h_dir = au_h_iptr(parent->d_inode, bdst);
2177+ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
2178+ if (!do_sio) {
2179+ /*
2180+ * testing CAP_MKNOD is for generic fs,
2181+ * but CAP_FSETID is for xfs only, currently.
2182+ */
2183+ umode_t mode = dentry->d_inode->i_mode;
2184+ do_sio = (((mode & (S_IFCHR | S_IFBLK))
2185+ && !capable(CAP_MKNOD))
2186+ || ((mode & (S_ISUID | S_ISGID))
2187+ && !capable(CAP_FSETID)));
2188+ }
2189+ if (!do_sio)
2190+ err = au_cpup_simple(dentry, bdst, len, flags);
2191+ else {
2192+ struct au_cpup_simple_args args = {
2193+ .errp = &err,
2194+ .dentry = dentry,
2195+ .bdst = bdst,
2196+ .len = len,
2197+ .flags = flags
2198+ };
2199+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
2200+ if (unlikely(wkq_err))
2201+ err = wkq_err;
2202+ }
2203+
2204+ dput(parent);
2205+ return err;
2206+}
2207+
2208+/* ---------------------------------------------------------------------- */
2209+
2210+/*
2211+ * copyup the deleted file for writing.
2212+ */
2213+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2214+ struct dentry *wh_dentry, struct file *file,
2215+ loff_t len)
2216+{
2217+ int err;
2218+ aufs_bindex_t bstart;
2219+ struct au_dinfo *dinfo;
2220+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 2221+ struct au_hdentry *hdp;
1facf9fc 2222+
2223+ dinfo = au_di(dentry);
1308ab2a 2224+ AuRwMustWriteLock(&dinfo->di_rwsem);
2225+
1facf9fc 2226+ bstart = dinfo->di_bstart;
4a4d8108
AM
2227+ hdp = dinfo->di_hdentry;
2228+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 2229+ dinfo->di_bstart = bdst;
4a4d8108
AM
2230+ hdp[0 + bdst].hd_dentry = wh_dentry;
2231+ h_d_start = hdp[0 + bstart].hd_dentry;
1facf9fc 2232+ if (file)
4a4d8108 2233+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2234+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2235+ /*h_parent*/NULL);
2236+ if (!err && file) {
2237+ err = au_reopen_nondir(file);
4a4d8108 2238+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 2239+ }
4a4d8108 2240+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 2241+ dinfo->di_bstart = bstart;
2242+
2243+ return err;
2244+}
2245+
2246+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2247+ struct file *file)
2248+{
2249+ int err;
2250+ struct au_dtime dt;
2251+ struct dentry *parent, *h_parent, *wh_dentry;
2252+ struct au_branch *br;
2253+ struct path h_path;
2254+
2255+ br = au_sbr(dentry->d_sb, bdst);
2256+ parent = dget_parent(dentry);
2257+ h_parent = au_h_dptr(parent, bdst);
2258+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
2259+ err = PTR_ERR(wh_dentry);
2260+ if (IS_ERR(wh_dentry))
2261+ goto out;
2262+
2263+ h_path.dentry = h_parent;
2264+ h_path.mnt = br->br_mnt;
2265+ au_dtime_store(&dt, parent, &h_path);
2266+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
2267+ if (unlikely(err))
2268+ goto out_wh;
2269+
2270+ dget(wh_dentry);
2271+ h_path.dentry = wh_dentry;
4a4d8108
AM
2272+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
2273+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
2274+ else
2275+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 2276+ if (unlikely(err)) {
2277+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2278+ AuDLNPair(wh_dentry), err);
2279+ err = -EIO;
2280+ }
2281+ au_dtime_revert(&dt);
2282+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2283+
4f0767ce 2284+out_wh:
1facf9fc 2285+ dput(wh_dentry);
4f0767ce 2286+out:
1facf9fc 2287+ dput(parent);
2288+ return err;
2289+}
2290+
2291+struct au_cpup_wh_args {
2292+ int *errp;
2293+ struct dentry *dentry;
2294+ aufs_bindex_t bdst;
2295+ loff_t len;
2296+ struct file *file;
2297+};
2298+
2299+static void au_call_cpup_wh(void *args)
2300+{
2301+ struct au_cpup_wh_args *a = args;
2302+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
2303+}
2304+
2305+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2306+ struct file *file)
2307+{
2308+ int err, wkq_err;
2309+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
2310+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
2311+ struct au_wbr *wbr;
2312+
2313+ parent = dget_parent(dentry);
2314+ dir = parent->d_inode;
2315+ h_orph = NULL;
2316+ h_parent = NULL;
2317+ h_dir = au_igrab(au_h_iptr(dir, bdst));
2318+ h_tmpdir = h_dir;
2319+ if (!h_dir->i_nlink) {
2320+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
2321+ h_orph = wbr->wbr_orph;
2322+
2323+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 2324+ au_set_h_dptr(parent, bdst, dget(h_orph));
2325+ h_tmpdir = h_orph->d_inode;
1facf9fc 2326+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
2327+
2328+ /* this temporary unlock is safe */
2329+ if (file)
4a4d8108 2330+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2331+ else
2332+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
2333+ h_inode = h_dentry->d_inode;
2334+ IMustLock(h_inode);
2335+ mutex_unlock(&h_inode->i_mutex);
dece6358 2336+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 2337+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 2338+ /* todo: au_h_open_pre()? */
1facf9fc 2339+ }
2340+
2341+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
2342+ err = au_cpup_wh(dentry, bdst, len, file);
2343+ else {
2344+ struct au_cpup_wh_args args = {
2345+ .errp = &err,
2346+ .dentry = dentry,
2347+ .bdst = bdst,
2348+ .len = len,
2349+ .file = file
2350+ };
2351+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
2352+ if (unlikely(wkq_err))
2353+ err = wkq_err;
2354+ }
2355+
2356+ if (h_orph) {
2357+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 2358+ /* todo: au_h_open_post()? */
1facf9fc 2359+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 2360+ au_set_h_dptr(parent, bdst, h_parent);
2361+ }
2362+ iput(h_dir);
2363+ dput(parent);
2364+
2365+ return err;
2366+}
2367+
2368+/* ---------------------------------------------------------------------- */
2369+
2370+/*
2371+ * generic routine for both of copy-up and copy-down.
2372+ */
2373+/* cf. revalidate function in file.c */
2374+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2375+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2376+ struct dentry *h_parent, void *arg),
2377+ void *arg)
2378+{
2379+ int err;
2380+ struct au_pin pin;
2381+ struct dentry *d, *parent, *h_parent, *real_parent;
2382+
2383+ err = 0;
2384+ parent = dget_parent(dentry);
2385+ if (IS_ROOT(parent))
2386+ goto out;
2387+
2388+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
2389+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
2390+
2391+ /* do not use au_dpage */
2392+ real_parent = parent;
2393+ while (1) {
2394+ dput(parent);
2395+ parent = dget_parent(dentry);
2396+ h_parent = au_h_dptr(parent, bdst);
2397+ if (h_parent)
2398+ goto out; /* success */
2399+
2400+ /* find top dir which is necessary to cpup */
2401+ do {
2402+ d = parent;
2403+ dput(parent);
2404+ parent = dget_parent(d);
2405+ di_read_lock_parent3(parent, !AuLock_IR);
2406+ h_parent = au_h_dptr(parent, bdst);
2407+ di_read_unlock(parent, !AuLock_IR);
2408+ } while (!h_parent);
2409+
2410+ if (d != real_parent)
2411+ di_write_lock_child3(d);
2412+
2413+ /* somebody else might create while we were sleeping */
2414+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
2415+ if (au_h_dptr(d, bdst))
2416+ au_update_dbstart(d);
2417+
2418+ au_pin_set_dentry(&pin, d);
2419+ err = au_do_pin(&pin);
2420+ if (!err) {
2421+ err = cp(d, bdst, h_parent, arg);
2422+ au_unpin(&pin);
2423+ }
2424+ }
2425+
2426+ if (d != real_parent)
2427+ di_write_unlock(d);
2428+ if (unlikely(err))
2429+ break;
2430+ }
2431+
4f0767ce 2432+out:
1facf9fc 2433+ dput(parent);
2434+ return err;
2435+}
2436+
2437+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
2438+ struct dentry *h_parent __maybe_unused ,
2439+ void *arg __maybe_unused)
2440+{
2441+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
2442+}
2443+
2444+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2445+{
2446+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
2447+}
2448+
2449+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2450+{
2451+ int err;
2452+ struct dentry *parent;
2453+ struct inode *dir;
2454+
2455+ parent = dget_parent(dentry);
2456+ dir = parent->d_inode;
2457+ err = 0;
2458+ if (au_h_iptr(dir, bdst))
2459+ goto out;
2460+
2461+ di_read_unlock(parent, AuLock_IR);
2462+ di_write_lock_parent(parent);
2463+ /* someone else might change our inode while we were sleeping */
2464+ if (!au_h_iptr(dir, bdst))
2465+ err = au_cpup_dirs(dentry, bdst);
2466+ di_downgrade_lock(parent, AuLock_IR);
2467+
4f0767ce 2468+out:
1facf9fc 2469+ dput(parent);
2470+ return err;
2471+}
e49829fe 2472--- /dev/null
0c5527e5 2473+++ linux-2.6/fs/aufs/cpup.h 2010-10-25 14:20:44.000000000 +0200
dece6358 2474@@ -0,0 +1,81 @@
1facf9fc 2475+/*
4a4d8108 2476+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2477+ *
2478+ * This program, aufs is free software; you can redistribute it and/or modify
2479+ * it under the terms of the GNU General Public License as published by
2480+ * the Free Software Foundation; either version 2 of the License, or
2481+ * (at your option) any later version.
dece6358
AM
2482+ *
2483+ * This program is distributed in the hope that it will be useful,
2484+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2485+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2486+ * GNU General Public License for more details.
2487+ *
2488+ * You should have received a copy of the GNU General Public License
2489+ * along with this program; if not, write to the Free Software
2490+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2491+ */
2492+
2493+/*
2494+ * copy-up/down functions
2495+ */
2496+
2497+#ifndef __AUFS_CPUP_H__
2498+#define __AUFS_CPUP_H__
2499+
2500+#ifdef __KERNEL__
2501+
dece6358
AM
2502+#include <linux/path.h>
2503+#include <linux/time.h>
1facf9fc 2504+#include <linux/aufs_type.h>
2505+
dece6358
AM
2506+struct inode;
2507+struct file;
2508+
1facf9fc 2509+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
2510+void au_cpup_attr_timesizes(struct inode *inode);
2511+void au_cpup_attr_nlink(struct inode *inode, int force);
2512+void au_cpup_attr_changeable(struct inode *inode);
2513+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
2514+void au_cpup_attr_all(struct inode *inode, int force);
2515+
2516+/* ---------------------------------------------------------------------- */
2517+
2518+/* cpup flags */
2519+#define AuCpup_DTIME 1 /* do dtime_store/revert */
2520+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
2521+ for link(2) */
2522+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
2523+#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; }
2524+#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; }
2525+
2526+int au_copy_file(struct file *dst, struct file *src, loff_t len);
2527+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2528+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2529+ struct dentry *dst_parent);
2530+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2531+ unsigned int flags);
2532+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2533+ struct file *file);
2534+
2535+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2536+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2537+ struct dentry *h_parent, void *arg),
2538+ void *arg);
2539+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2540+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
2541+
2542+/* ---------------------------------------------------------------------- */
2543+
2544+/* keep timestamps when copyup */
2545+struct au_dtime {
2546+ struct dentry *dt_dentry;
2547+ struct path dt_h_path;
2548+ struct timespec dt_atime, dt_mtime;
2549+};
2550+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
2551+ struct path *h_path);
2552+void au_dtime_revert(struct au_dtime *dt);
2553+
2554+#endif /* __KERNEL__ */
2555+#endif /* __AUFS_CPUP_H__ */
e49829fe 2556--- /dev/null
0c5527e5 2557+++ linux-2.6/fs/aufs/dbgaufs.c 2010-10-25 14:20:44.000000000 +0200
4a4d8108 2558@@ -0,0 +1,334 @@
1facf9fc 2559+/*
4a4d8108 2560+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2561+ *
2562+ * This program, aufs is free software; you can redistribute it and/or modify
2563+ * it under the terms of the GNU General Public License as published by
2564+ * the Free Software Foundation; either version 2 of the License, or
2565+ * (at your option) any later version.
dece6358
AM
2566+ *
2567+ * This program is distributed in the hope that it will be useful,
2568+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2569+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2570+ * GNU General Public License for more details.
2571+ *
2572+ * You should have received a copy of the GNU General Public License
2573+ * along with this program; if not, write to the Free Software
2574+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2575+ */
2576+
2577+/*
2578+ * debugfs interface
2579+ */
2580+
2581+#include <linux/debugfs.h>
2582+#include "aufs.h"
2583+
2584+#ifndef CONFIG_SYSFS
2585+#error DEBUG_FS depends upon SYSFS
2586+#endif
2587+
2588+static struct dentry *dbgaufs;
2589+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
2590+
2591+/* 20 is max digits length of ulong 64 */
2592+struct dbgaufs_arg {
2593+ int n;
2594+ char a[20 * 4];
2595+};
2596+
2597+/*
2598+ * common function for all XINO files
2599+ */
2600+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
2601+ struct file *file)
2602+{
2603+ kfree(file->private_data);
2604+ return 0;
2605+}
2606+
2607+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
2608+{
2609+ int err;
2610+ struct kstat st;
2611+ struct dbgaufs_arg *p;
2612+
2613+ err = -ENOMEM;
2614+ p = kmalloc(sizeof(*p), GFP_NOFS);
2615+ if (unlikely(!p))
2616+ goto out;
2617+
2618+ err = 0;
2619+ p->n = 0;
2620+ file->private_data = p;
2621+ if (!xf)
2622+ goto out;
2623+
2624+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
2625+ if (!err) {
2626+ if (do_fcnt)
2627+ p->n = snprintf
2628+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
2629+ (long)file_count(xf), st.blocks, st.blksize,
2630+ (long long)st.size);
2631+ else
2632+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
2633+ st.blocks, st.blksize,
2634+ (long long)st.size);
2635+ AuDebugOn(p->n >= sizeof(p->a));
2636+ } else {
2637+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
2638+ err = 0;
2639+ }
2640+
4f0767ce 2641+out:
1facf9fc 2642+ return err;
2643+
2644+}
2645+
2646+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
2647+ size_t count, loff_t *ppos)
2648+{
2649+ struct dbgaufs_arg *p;
2650+
2651+ p = file->private_data;
2652+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
2653+}
2654+
2655+/* ---------------------------------------------------------------------- */
2656+
2657+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
2658+{
2659+ int err;
2660+ struct au_sbinfo *sbinfo;
2661+ struct super_block *sb;
2662+
2663+ sbinfo = inode->i_private;
2664+ sb = sbinfo->si_sb;
2665+ si_noflush_read_lock(sb);
2666+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
2667+ si_read_unlock(sb);
2668+ return err;
2669+}
2670+
2671+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 2672+ .owner = THIS_MODULE,
1facf9fc 2673+ .open = dbgaufs_xib_open,
2674+ .release = dbgaufs_xi_release,
2675+ .read = dbgaufs_xi_read
2676+};
2677+
2678+/* ---------------------------------------------------------------------- */
2679+
2680+#define DbgaufsXi_PREFIX "xi"
2681+
2682+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
2683+{
2684+ int err;
2685+ long l;
2686+ struct au_sbinfo *sbinfo;
2687+ struct super_block *sb;
2688+ struct file *xf;
2689+ struct qstr *name;
2690+
2691+ err = -ENOENT;
2692+ xf = NULL;
2693+ name = &file->f_dentry->d_name;
2694+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
2695+ || memcmp(name->name, DbgaufsXi_PREFIX,
2696+ sizeof(DbgaufsXi_PREFIX) - 1)))
2697+ goto out;
2698+ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
2699+ if (unlikely(err))
2700+ goto out;
2701+
2702+ sbinfo = inode->i_private;
2703+ sb = sbinfo->si_sb;
2704+ si_noflush_read_lock(sb);
2705+ if (l <= au_sbend(sb)) {
2706+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
2707+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
2708+ } else
2709+ err = -ENOENT;
2710+ si_read_unlock(sb);
2711+
4f0767ce 2712+out:
1facf9fc 2713+ return err;
2714+}
2715+
2716+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 2717+ .owner = THIS_MODULE,
1facf9fc 2718+ .open = dbgaufs_xino_open,
2719+ .release = dbgaufs_xi_release,
2720+ .read = dbgaufs_xi_read
2721+};
2722+
2723+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
2724+{
2725+ aufs_bindex_t bend;
2726+ struct au_branch *br;
2727+ struct au_xino_file *xi;
2728+
2729+ if (!au_sbi(sb)->si_dbgaufs)
2730+ return;
2731+
2732+ bend = au_sbend(sb);
2733+ for (; bindex <= bend; bindex++) {
2734+ br = au_sbr(sb, bindex);
2735+ xi = &br->br_xino;
2736+ if (xi->xi_dbgaufs) {
2737+ debugfs_remove(xi->xi_dbgaufs);
2738+ xi->xi_dbgaufs = NULL;
2739+ }
2740+ }
2741+}
2742+
2743+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
2744+{
2745+ struct au_sbinfo *sbinfo;
2746+ struct dentry *parent;
2747+ struct au_branch *br;
2748+ struct au_xino_file *xi;
2749+ aufs_bindex_t bend;
2750+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
2751+
2752+ sbinfo = au_sbi(sb);
2753+ parent = sbinfo->si_dbgaufs;
2754+ if (!parent)
2755+ return;
2756+
2757+ bend = au_sbend(sb);
2758+ for (; bindex <= bend; bindex++) {
2759+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
2760+ br = au_sbr(sb, bindex);
2761+ xi = &br->br_xino;
2762+ AuDebugOn(xi->xi_dbgaufs);
2763+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
2764+ sbinfo, &dbgaufs_xino_fop);
2765+ /* ignore an error */
2766+ if (unlikely(!xi->xi_dbgaufs))
2767+ AuWarn1("failed %s under debugfs\n", name);
2768+ }
2769+}
2770+
2771+/* ---------------------------------------------------------------------- */
2772+
2773+#ifdef CONFIG_AUFS_EXPORT
2774+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
2775+{
2776+ int err;
2777+ struct au_sbinfo *sbinfo;
2778+ struct super_block *sb;
2779+
2780+ sbinfo = inode->i_private;
2781+ sb = sbinfo->si_sb;
2782+ si_noflush_read_lock(sb);
2783+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
2784+ si_read_unlock(sb);
2785+ return err;
2786+}
2787+
2788+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 2789+ .owner = THIS_MODULE,
1facf9fc 2790+ .open = dbgaufs_xigen_open,
2791+ .release = dbgaufs_xi_release,
2792+ .read = dbgaufs_xi_read
2793+};
2794+
2795+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
2796+{
2797+ int err;
2798+
dece6358
AM
2799+ /*
2800+ * This function is a dynamic '__init' fucntion actually,
2801+ * so the tiny check for si_rwsem is unnecessary.
2802+ */
2803+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
2804+
1facf9fc 2805+ err = -EIO;
2806+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
2807+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
2808+ &dbgaufs_xigen_fop);
2809+ if (sbinfo->si_dbgaufs_xigen)
2810+ err = 0;
2811+
2812+ return err;
2813+}
2814+#else
2815+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
2816+{
2817+ return 0;
2818+}
2819+#endif /* CONFIG_AUFS_EXPORT */
2820+
2821+/* ---------------------------------------------------------------------- */
2822+
2823+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
2824+{
dece6358
AM
2825+ /*
2826+ * This function is a dynamic '__init' fucntion actually,
2827+ * so the tiny check for si_rwsem is unnecessary.
2828+ */
2829+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
2830+
1facf9fc 2831+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
2832+ sbinfo->si_dbgaufs = NULL;
2833+ kobject_put(&sbinfo->si_kobj);
2834+}
2835+
2836+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
2837+{
2838+ int err;
2839+ char name[SysaufsSiNameLen];
2840+
dece6358
AM
2841+ /*
2842+ * This function is a dynamic '__init' fucntion actually,
2843+ * so the tiny check for si_rwsem is unnecessary.
2844+ */
2845+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
2846+
1facf9fc 2847+ err = -ENOENT;
2848+ if (!dbgaufs) {
2849+ AuErr1("/debug/aufs is uninitialized\n");
2850+ goto out;
2851+ }
2852+
2853+ err = -EIO;
2854+ sysaufs_name(sbinfo, name);
2855+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
2856+ if (unlikely(!sbinfo->si_dbgaufs))
2857+ goto out;
2858+ kobject_get(&sbinfo->si_kobj);
2859+
2860+ sbinfo->si_dbgaufs_xib = debugfs_create_file
2861+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
2862+ &dbgaufs_xib_fop);
2863+ if (unlikely(!sbinfo->si_dbgaufs_xib))
2864+ goto out_dir;
2865+
2866+ err = dbgaufs_xigen_init(sbinfo);
2867+ if (!err)
2868+ goto out; /* success */
2869+
4f0767ce 2870+out_dir:
1facf9fc 2871+ dbgaufs_si_fin(sbinfo);
4f0767ce 2872+out:
1facf9fc 2873+ return err;
2874+}
2875+
2876+/* ---------------------------------------------------------------------- */
2877+
2878+void dbgaufs_fin(void)
2879+{
2880+ debugfs_remove(dbgaufs);
2881+}
2882+
2883+int __init dbgaufs_init(void)
2884+{
2885+ int err;
2886+
2887+ err = -EIO;
2888+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
2889+ if (dbgaufs)
2890+ err = 0;
2891+ return err;
2892+}
e49829fe 2893--- /dev/null
0c5527e5 2894+++ linux-2.6/fs/aufs/dbgaufs.h 2010-10-25 14:20:44.000000000 +0200
4a4d8108 2895@@ -0,0 +1,52 @@
1facf9fc 2896+/*
4a4d8108 2897+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2898+ *
2899+ * This program, aufs is free software; you can redistribute it and/or modify
2900+ * it under the terms of the GNU General Public License as published by
2901+ * the Free Software Foundation; either version 2 of the License, or
2902+ * (at your option) any later version.
dece6358
AM
2903+ *
2904+ * This program is distributed in the hope that it will be useful,
2905+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2906+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2907+ * GNU General Public License for more details.
2908+ *
2909+ * You should have received a copy of the GNU General Public License
2910+ * along with this program; if not, write to the Free Software
2911+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2912+ */
2913+
2914+/*
2915+ * debugfs interface
2916+ */
2917+
2918+#ifndef __DBGAUFS_H__
2919+#define __DBGAUFS_H__
2920+
2921+#ifdef __KERNEL__
2922+
dece6358 2923+#include <linux/init.h>
1facf9fc 2924+#include <linux/aufs_type.h>
2925+
dece6358 2926+struct super_block;
1facf9fc 2927+struct au_sbinfo;
dece6358 2928+
1facf9fc 2929+#ifdef CONFIG_DEBUG_FS
2930+/* dbgaufs.c */
2931+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
2932+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
2933+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
2934+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
2935+void dbgaufs_fin(void);
2936+int __init dbgaufs_init(void);
1facf9fc 2937+#else
4a4d8108
AM
2938+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
2939+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
2940+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
2941+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
2942+AuStubVoid(dbgaufs_fin, void)
2943+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 2944+#endif /* CONFIG_DEBUG_FS */
2945+
2946+#endif /* __KERNEL__ */
2947+#endif /* __DBGAUFS_H__ */
e49829fe 2948--- /dev/null
0c5527e5 2949+++ linux-2.6/fs/aufs/dcsub.c 2010-10-25 14:20:44.000000000 +0200
4a4d8108 2950@@ -0,0 +1,200 @@
1facf9fc 2951+/*
4a4d8108 2952+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 2953+ *
2954+ * This program, aufs is free software; you can redistribute it and/or modify
2955+ * it under the terms of the GNU General Public License as published by
2956+ * the Free Software Foundation; either version 2 of the License, or
2957+ * (at your option) any later version.
dece6358
AM
2958+ *
2959+ * This program is distributed in the hope that it will be useful,
2960+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2961+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2962+ * GNU General Public License for more details.
2963+ *
2964+ * You should have received a copy of the GNU General Public License
2965+ * along with this program; if not, write to the Free Software
2966+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 2967+ */
2968+
2969+/*
2970+ * sub-routines for dentry cache
2971+ */
2972+
2973+#include "aufs.h"
2974+
2975+static void au_dpage_free(struct au_dpage *dpage)
2976+{
2977+ int i;
2978+ struct dentry **p;
2979+
2980+ p = dpage->dentries;
2981+ for (i = 0; i < dpage->ndentry; i++)
2982+ dput(*p++);
2983+ free_page((unsigned long)dpage->dentries);
2984+}
2985+
2986+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
2987+{
2988+ int err;
2989+ void *p;
2990+
2991+ err = -ENOMEM;
2992+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
2993+ if (unlikely(!dpages->dpages))
2994+ goto out;
2995+
2996+ p = (void *)__get_free_page(gfp);
2997+ if (unlikely(!p))
2998+ goto out_dpages;
2999+
3000+ dpages->dpages[0].ndentry = 0;
3001+ dpages->dpages[0].dentries = p;
3002+ dpages->ndpage = 1;
3003+ return 0; /* success */
3004+
4f0767ce 3005+out_dpages:
1facf9fc 3006+ kfree(dpages->dpages);
4f0767ce 3007+out:
1facf9fc 3008+ return err;
3009+}
3010+
3011+void au_dpages_free(struct au_dcsub_pages *dpages)
3012+{
3013+ int i;
3014+ struct au_dpage *p;
3015+
3016+ p = dpages->dpages;
3017+ for (i = 0; i < dpages->ndpage; i++)
3018+ au_dpage_free(p++);
3019+ kfree(dpages->dpages);
3020+}
3021+
3022+static int au_dpages_append(struct au_dcsub_pages *dpages,
3023+ struct dentry *dentry, gfp_t gfp)
3024+{
3025+ int err, sz;
3026+ struct au_dpage *dpage;
3027+ void *p;
3028+
3029+ dpage = dpages->dpages + dpages->ndpage - 1;
3030+ sz = PAGE_SIZE / sizeof(dentry);
3031+ if (unlikely(dpage->ndentry >= sz)) {
3032+ AuLabel(new dpage);
3033+ err = -ENOMEM;
3034+ sz = dpages->ndpage * sizeof(*dpages->dpages);
3035+ p = au_kzrealloc(dpages->dpages, sz,
3036+ sz + sizeof(*dpages->dpages), gfp);
3037+ if (unlikely(!p))
3038+ goto out;
3039+
3040+ dpages->dpages = p;
3041+ dpage = dpages->dpages + dpages->ndpage;
3042+ p = (void *)__get_free_page(gfp);
3043+ if (unlikely(!p))
3044+ goto out;
3045+
3046+ dpage->ndentry = 0;
3047+ dpage->dentries = p;
3048+ dpages->ndpage++;
3049+ }
3050+
3051+ dpage->dentries[dpage->ndentry++] = dget(dentry);
3052+ return 0; /* success */
3053+
4f0767ce 3054+out:
1facf9fc 3055+ return err;
3056+}
3057+
3058+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3059+ au_dpages_test test, void *arg)
3060+{
3061+ int err;
3062+ struct dentry *this_parent = root;
3063+ struct list_head *next;
3064+ struct super_block *sb = root->d_sb;
3065+
3066+ err = 0;
3067+ spin_lock(&dcache_lock);
4f0767ce 3068+repeat:
1facf9fc 3069+ next = this_parent->d_subdirs.next;
4f0767ce 3070+resume:
1facf9fc 3071+ if (this_parent->d_sb == sb
3072+ && !IS_ROOT(this_parent)
3073+ && atomic_read(&this_parent->d_count)
3074+ && this_parent->d_inode
3075+ && (!test || test(this_parent, arg))) {
3076+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3077+ if (unlikely(err))
3078+ goto out;
3079+ }
3080+
3081+ while (next != &this_parent->d_subdirs) {
3082+ struct list_head *tmp = next;
3083+ struct dentry *dentry = list_entry(tmp, struct dentry,
3084+ d_u.d_child);
3085+ next = tmp->next;
3086+ if (/*d_unhashed(dentry) || */!dentry->d_inode)
3087+ continue;
3088+ if (!list_empty(&dentry->d_subdirs)) {
3089+ this_parent = dentry;
3090+ goto repeat;
3091+ }
3092+ if (dentry->d_sb == sb
3093+ && atomic_read(&dentry->d_count)
3094+ && (!test || test(dentry, arg))) {
3095+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3096+ if (unlikely(err))
3097+ goto out;
3098+ }
3099+ }
3100+
3101+ if (this_parent != root) {
3102+ next = this_parent->d_u.d_child.next;
3103+ this_parent = this_parent->d_parent; /* dcache_lock is locked */
3104+ goto resume;
3105+ }
4f0767ce 3106+out:
1facf9fc 3107+ spin_unlock(&dcache_lock);
3108+ return err;
3109+}
3110+
3111+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3112+ int do_include, au_dpages_test test, void *arg)
3113+{
3114+ int err;
3115+
3116+ err = 0;
3117+ spin_lock(&dcache_lock);
3118+ if (do_include && (!test || test(dentry, arg))) {
3119+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3120+ if (unlikely(err))
3121+ goto out;
3122+ }
3123+ while (!IS_ROOT(dentry)) {
3124+ dentry = dentry->d_parent; /* dcache_lock is locked */
3125+ if (!test || test(dentry, arg)) {
3126+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
3127+ if (unlikely(err))
3128+ break;
3129+ }
3130+ }
3131+
4f0767ce 3132+out:
1facf9fc 3133+ spin_unlock(&dcache_lock);
3134+
3135+ return err;
3136+}
3137+
4a4d8108 3138+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 3139+{
4a4d8108
AM
3140+ struct path path[2] = {
3141+ {
3142+ .dentry = d1
3143+ },
3144+ {
3145+ .dentry = d2
3146+ }
3147+ };
1facf9fc 3148+
4a4d8108 3149+ return path_is_under(path + 0, path + 1);
1facf9fc 3150+}
e49829fe 3151--- /dev/null
0c5527e5 3152+++ linux-2.6/fs/aufs/dcsub.h 2010-10-25 14:20:44.000000000 +0200
dece6358 3153@@ -0,0 +1,54 @@
1facf9fc 3154+/*
4a4d8108 3155+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3156+ *
3157+ * This program, aufs is free software; you can redistribute it and/or modify
3158+ * it under the terms of the GNU General Public License as published by
3159+ * the Free Software Foundation; either version 2 of the License, or
3160+ * (at your option) any later version.
dece6358
AM
3161+ *
3162+ * This program is distributed in the hope that it will be useful,
3163+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3164+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3165+ * GNU General Public License for more details.
3166+ *
3167+ * You should have received a copy of the GNU General Public License
3168+ * along with this program; if not, write to the Free Software
3169+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3170+ */
3171+
3172+/*
3173+ * sub-routines for dentry cache
3174+ */
3175+
3176+#ifndef __AUFS_DCSUB_H__
3177+#define __AUFS_DCSUB_H__
3178+
3179+#ifdef __KERNEL__
3180+
dece6358
AM
3181+#include <linux/types.h>
3182+
3183+struct dentry;
1facf9fc 3184+
3185+struct au_dpage {
3186+ int ndentry;
3187+ struct dentry **dentries;
3188+};
3189+
3190+struct au_dcsub_pages {
3191+ int ndpage;
3192+ struct au_dpage *dpages;
3193+};
3194+
3195+/* ---------------------------------------------------------------------- */
3196+
3197+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3198+void au_dpages_free(struct au_dcsub_pages *dpages);
3199+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3200+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3201+ au_dpages_test test, void *arg);
3202+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3203+ int do_include, au_dpages_test test, void *arg);
4a4d8108 3204+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 3205+
3206+#endif /* __KERNEL__ */
3207+#endif /* __AUFS_DCSUB_H__ */
e49829fe 3208--- /dev/null
0c5527e5
AM
3209+++ linux-2.6/fs/aufs/debug.c 2010-10-26 21:35:34.000000000 +0200
3210@@ -0,0 +1,442 @@
1facf9fc 3211+/*
4a4d8108 3212+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3213+ *
3214+ * This program, aufs is free software; you can redistribute it and/or modify
3215+ * it under the terms of the GNU General Public License as published by
3216+ * the Free Software Foundation; either version 2 of the License, or
3217+ * (at your option) any later version.
dece6358
AM
3218+ *
3219+ * This program is distributed in the hope that it will be useful,
3220+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3221+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3222+ * GNU General Public License for more details.
3223+ *
3224+ * You should have received a copy of the GNU General Public License
3225+ * along with this program; if not, write to the Free Software
3226+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3227+ */
3228+
3229+/*
3230+ * debug print functions
3231+ */
3232+
dece6358 3233+#include <linux/module.h>
1facf9fc 3234+#include "aufs.h"
3235+
3236+int aufs_debug;
3237+MODULE_PARM_DESC(debug, "debug print");
3238+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
3239+
3240+char *au_plevel = KERN_DEBUG;
e49829fe
JR
3241+#define dpri(fmt, ...) do { \
3242+ if ((au_plevel \
3243+ && strcmp(au_plevel, KERN_DEBUG)) \
3244+ || au_debug_test()) \
3245+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 3246+} while (0)
3247+
3248+/* ---------------------------------------------------------------------- */
3249+
3250+void au_dpri_whlist(struct au_nhash *whlist)
3251+{
3252+ unsigned long ul, n;
3253+ struct hlist_head *head;
3254+ struct au_vdir_wh *tpos;
3255+ struct hlist_node *pos;
3256+
3257+ n = whlist->nh_num;
3258+ head = whlist->nh_head;
3259+ for (ul = 0; ul < n; ul++) {
3260+ hlist_for_each_entry(tpos, pos, head, wh_hash)
3261+ dpri("b%d, %.*s, %d\n",
3262+ tpos->wh_bindex,
3263+ tpos->wh_str.len, tpos->wh_str.name,
3264+ tpos->wh_str.len);
3265+ head++;
3266+ }
3267+}
3268+
3269+void au_dpri_vdir(struct au_vdir *vdir)
3270+{
3271+ unsigned long ul;
3272+ union au_vdir_deblk_p p;
3273+ unsigned char *o;
3274+
3275+ if (!vdir || IS_ERR(vdir)) {
3276+ dpri("err %ld\n", PTR_ERR(vdir));
3277+ return;
3278+ }
3279+
3280+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
3281+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
3282+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
3283+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
3284+ p.deblk = vdir->vd_deblk[ul];
3285+ o = p.deblk;
3286+ dpri("[%lu]: %p\n", ul, o);
3287+ }
3288+}
3289+
3290+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3291+ struct dentry *wh)
3292+{
3293+ char *n = NULL;
3294+ int l = 0;
3295+
3296+ if (!inode || IS_ERR(inode)) {
3297+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3298+ return -1;
3299+ }
3300+
3301+ /* the type of i_blocks depends upon CONFIG_LSF */
3302+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3303+ && sizeof(inode->i_blocks) != sizeof(u64));
3304+ if (wh) {
3305+ n = (void *)wh->d_name.name;
3306+ l = wh->d_name.len;
3307+ }
3308+
3309+ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
b752ccd1 3310+ " ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
1facf9fc 3311+ bindex,
3312+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3313+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3314+ i_size_read(inode), (unsigned long long)inode->i_blocks,
3315+ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3316+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
3317+ inode->i_state, inode->i_flags, inode->i_version,
3318+ inode->i_generation,
1facf9fc 3319+ l ? ", wh " : "", l, n);
3320+ return 0;
3321+}
3322+
3323+void au_dpri_inode(struct inode *inode)
3324+{
3325+ struct au_iinfo *iinfo;
3326+ aufs_bindex_t bindex;
3327+ int err;
3328+
3329+ err = do_pri_inode(-1, inode, NULL);
3330+ if (err || !au_test_aufs(inode->i_sb))
3331+ return;
3332+
3333+ iinfo = au_ii(inode);
3334+ if (!iinfo)
3335+ return;
3336+ dpri("i-1: bstart %d, bend %d, gen %d\n",
3337+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
3338+ if (iinfo->ii_bstart < 0)
3339+ return;
3340+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
3341+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
3342+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
3343+}
3344+
3345+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
3346+{
3347+ struct dentry *wh = NULL;
3348+
3349+ if (!dentry || IS_ERR(dentry)) {
3350+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
3351+ return -1;
3352+ }
3353+ /* do not call dget_parent() here */
3354+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
3355+ bindex,
3356+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
3357+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
3358+ atomic_read(&dentry->d_count), dentry->d_flags);
3359+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
3360+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
3361+ if (iinfo)
3362+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
3363+ }
3364+ do_pri_inode(bindex, dentry->d_inode, wh);
3365+ return 0;
3366+}
3367+
3368+void au_dpri_dentry(struct dentry *dentry)
3369+{
3370+ struct au_dinfo *dinfo;
3371+ aufs_bindex_t bindex;
3372+ int err;
4a4d8108 3373+ struct au_hdentry *hdp;
1facf9fc 3374+
3375+ err = do_pri_dentry(-1, dentry);
3376+ if (err || !au_test_aufs(dentry->d_sb))
3377+ return;
3378+
3379+ dinfo = au_di(dentry);
3380+ if (!dinfo)
3381+ return;
3382+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
3383+ dinfo->di_bstart, dinfo->di_bend,
3384+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
3385+ if (dinfo->di_bstart < 0)
3386+ return;
4a4d8108 3387+ hdp = dinfo->di_hdentry;
1facf9fc 3388+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 3389+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 3390+}
3391+
3392+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
3393+{
3394+ char a[32];
3395+
3396+ if (!file || IS_ERR(file)) {
3397+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
3398+ return -1;
3399+ }
3400+ a[0] = 0;
3401+ if (bindex < 0
3402+ && file->f_dentry
3403+ && au_test_aufs(file->f_dentry->d_sb)
3404+ && au_fi(file))
e49829fe
JR
3405+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
3406+ au_figen(file), !!au_fi(file)->fi_hvmop);
b752ccd1 3407+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 3408+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 3409+ file->f_version, file->f_pos, a);
1facf9fc 3410+ if (file->f_dentry)
3411+ do_pri_dentry(bindex, file->f_dentry);
3412+ return 0;
3413+}
3414+
3415+void au_dpri_file(struct file *file)
3416+{
3417+ struct au_finfo *finfo;
4a4d8108
AM
3418+ struct au_fidir *fidir;
3419+ struct au_hfile *hfile;
1facf9fc 3420+ aufs_bindex_t bindex;
3421+ int err;
3422+
3423+ err = do_pri_file(-1, file);
3424+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
3425+ return;
3426+
3427+ finfo = au_fi(file);
3428+ if (!finfo)
3429+ return;
4a4d8108 3430+ if (finfo->fi_btop < 0)
1facf9fc 3431+ return;
4a4d8108
AM
3432+ fidir = finfo->fi_hdir;
3433+ if (!fidir)
3434+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
3435+ else
e49829fe
JR
3436+ for (bindex = finfo->fi_btop;
3437+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
3438+ bindex++) {
3439+ hfile = fidir->fd_hfile + bindex;
3440+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
3441+ }
1facf9fc 3442+}
3443+
3444+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
3445+{
3446+ struct vfsmount *mnt;
3447+ struct super_block *sb;
3448+
3449+ if (!br || IS_ERR(br))
3450+ goto out;
3451+ mnt = br->br_mnt;
3452+ if (!mnt || IS_ERR(mnt))
3453+ goto out;
3454+ sb = mnt->mnt_sb;
3455+ if (!sb || IS_ERR(sb))
3456+ goto out;
3457+
3458+ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
b752ccd1 3459+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 3460+ "xino %d\n",
3461+ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
3462+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 3463+ sb->s_flags, sb->s_count,
1facf9fc 3464+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
3465+ return 0;
3466+
4f0767ce 3467+out:
1facf9fc 3468+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
3469+ return -1;
3470+}
3471+
3472+void au_dpri_sb(struct super_block *sb)
3473+{
3474+ struct au_sbinfo *sbinfo;
3475+ aufs_bindex_t bindex;
3476+ int err;
3477+ /* to reuduce stack size */
3478+ struct {
3479+ struct vfsmount mnt;
3480+ struct au_branch fake;
3481+ } *a;
3482+
3483+ /* this function can be called from magic sysrq */
3484+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
3485+ if (unlikely(!a)) {
3486+ dpri("no memory\n");
3487+ return;
3488+ }
3489+
3490+ a->mnt.mnt_sb = sb;
3491+ a->fake.br_perm = 0;
3492+ a->fake.br_mnt = &a->mnt;
3493+ a->fake.br_xino.xi_file = NULL;
3494+ atomic_set(&a->fake.br_count, 0);
3495+ smp_mb(); /* atomic_set */
3496+ err = do_pri_br(-1, &a->fake);
3497+ kfree(a);
3498+ dpri("dev 0x%x\n", sb->s_dev);
3499+ if (err || !au_test_aufs(sb))
3500+ return;
3501+
3502+ sbinfo = au_sbi(sb);
3503+ if (!sbinfo)
3504+ return;
3505+ dpri("nw %d, gen %u, kobj %d\n",
3506+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
3507+ atomic_read(&sbinfo->si_kobj.kref.refcount));
3508+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
3509+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
3510+}
3511+
3512+/* ---------------------------------------------------------------------- */
3513+
3514+void au_dbg_sleep_jiffy(int jiffy)
3515+{
3516+ while (jiffy)
3517+ jiffy = schedule_timeout_uninterruptible(jiffy);
3518+}
3519+
3520+void au_dbg_iattr(struct iattr *ia)
3521+{
3522+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
3523+ dpri(#name "\n")
3524+ AuBit(MODE);
3525+ AuBit(UID);
3526+ AuBit(GID);
3527+ AuBit(SIZE);
3528+ AuBit(ATIME);
3529+ AuBit(MTIME);
3530+ AuBit(CTIME);
3531+ AuBit(ATIME_SET);
3532+ AuBit(MTIME_SET);
3533+ AuBit(FORCE);
3534+ AuBit(ATTR_FLAG);
3535+ AuBit(KILL_SUID);
3536+ AuBit(KILL_SGID);
3537+ AuBit(FILE);
3538+ AuBit(KILL_PRIV);
3539+ AuBit(OPEN);
3540+ AuBit(TIMES_SET);
3541+#undef AuBit
3542+ dpri("ia_file %p\n", ia->ia_file);
3543+}
3544+
3545+/* ---------------------------------------------------------------------- */
3546+
3547+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
3548+{
3549+ struct dentry *parent;
3550+
3551+ parent = dget_parent(dentry);
3552+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
3553+ || IS_ROOT(dentry)
3554+ || au_digen(parent) != sigen);
3555+ dput(parent);
3556+}
3557+
3558+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
3559+{
3560+ struct dentry *parent;
3561+
3562+ parent = dget_parent(dentry);
3563+ AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
3564+ || au_digen(parent) != sigen);
3565+ dput(parent);
3566+}
3567+
3568+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
3569+{
3570+ int err, i, j;
3571+ struct au_dcsub_pages dpages;
3572+ struct au_dpage *dpage;
3573+ struct dentry **dentries;
3574+
3575+ err = au_dpages_init(&dpages, GFP_NOFS);
3576+ AuDebugOn(err);
3577+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
3578+ AuDebugOn(err);
3579+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
3580+ dpage = dpages.dpages + i;
3581+ dentries = dpage->dentries;
3582+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
3583+ AuDebugOn(au_digen(dentries[j]) != sigen);
3584+ }
3585+ au_dpages_free(&dpages);
3586+}
3587+
1facf9fc 3588+void au_dbg_verify_kthread(void)
3589+{
e49829fe
JR
3590+ struct task_struct *tsk = current;
3591+
3592+ if ((tsk->flags & PF_KTHREAD)
3593+ && !strncmp(tsk->comm, AUFS_WKQ_NAME "/", sizeof(AUFS_WKQ_NAME))) {
1facf9fc 3594+ au_dbg_blocked();
e49829fe 3595+ BUG();
1facf9fc 3596+ }
3597+}
3598+
e49829fe
JR
3599+static void au_dbg_do_verify_wkq(void *args)
3600+{
3601+ BUG_ON(current_fsuid());
3602+ BUG_ON(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
3603+}
3604+
3605+void au_dbg_verify_wkq(void)
3606+{
3607+ au_wkq_wait(au_dbg_do_verify_wkq, NULL);
3608+}
3609+
1facf9fc 3610+/* ---------------------------------------------------------------------- */
3611+
3612+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
3613+{
3614+#ifdef AuForceNoPlink
3615+ au_opt_clr(sbinfo->si_mntflags, PLINK);
3616+#endif
3617+#ifdef AuForceNoXino
3618+ au_opt_clr(sbinfo->si_mntflags, XINO);
3619+#endif
3620+#ifdef AuForceNoRefrof
3621+ au_opt_clr(sbinfo->si_mntflags, REFROF);
3622+#endif
4a4d8108
AM
3623+#ifdef AuForceHnotify
3624+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 3625+#endif
1308ab2a 3626+#ifdef AuForceRd0
3627+ sbinfo->si_rdblk = 0;
3628+ sbinfo->si_rdhash = 0;
3629+#endif
1facf9fc 3630+}
3631+
3632+int __init au_debug_init(void)
3633+{
3634+ aufs_bindex_t bindex;
3635+ struct au_vdir_destr destr;
3636+
3637+ bindex = -1;
3638+ AuDebugOn(bindex >= 0);
3639+
3640+ destr.len = -1;
3641+ AuDebugOn(destr.len < NAME_MAX);
3642+
3643+#ifdef CONFIG_4KSTACKS
4a4d8108 3644+ pr_warning("CONFIG_4KSTACKS is defined.\n");
1facf9fc 3645+#endif
3646+
3647+#ifdef AuForceNoBrs
3648+ sysaufs_brs = 0;
3649+#endif
3650+
3651+ return 0;
3652+}
e49829fe 3653--- /dev/null
0c5527e5
AM
3654+++ linux-2.6/fs/aufs/debug.h 2010-10-26 21:35:59.000000000 +0200
3655@@ -0,0 +1,241 @@
1facf9fc 3656+/*
4a4d8108 3657+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3658+ *
3659+ * This program, aufs is free software; you can redistribute it and/or modify
3660+ * it under the terms of the GNU General Public License as published by
3661+ * the Free Software Foundation; either version 2 of the License, or
3662+ * (at your option) any later version.
dece6358
AM
3663+ *
3664+ * This program is distributed in the hope that it will be useful,
3665+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3666+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3667+ * GNU General Public License for more details.
3668+ *
3669+ * You should have received a copy of the GNU General Public License
3670+ * along with this program; if not, write to the Free Software
3671+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3672+ */
3673+
3674+/*
3675+ * debug print functions
3676+ */
3677+
3678+#ifndef __AUFS_DEBUG_H__
3679+#define __AUFS_DEBUG_H__
3680+
3681+#ifdef __KERNEL__
3682+
1308ab2a 3683+#include <asm/system.h>
dece6358 3684+#include <linux/bug.h>
1308ab2a 3685+#include <linux/init.h>
4a4d8108
AM
3686+#include <linux/module.h>
3687+#include <linux/kallsyms.h>
1facf9fc 3688+#include <linux/delay.h>
1facf9fc 3689+#include <linux/sysrq.h>
3690+#include <linux/aufs_type.h>
3691+
4a4d8108
AM
3692+#include <asm/system.h>
3693+
1facf9fc 3694+#ifdef CONFIG_AUFS_DEBUG
3695+#define AuDebugOn(a) BUG_ON(a)
3696+
3697+/* module parameter */
3698+extern int aufs_debug;
3699+static inline void au_debug(int n)
3700+{
3701+ aufs_debug = n;
3702+ smp_mb();
3703+}
3704+
3705+static inline int au_debug_test(void)
3706+{
3707+ return aufs_debug;
3708+}
3709+#else
3710+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
3711+AuStubVoid(au_debug, int n)
3712+AuStubInt0(au_debug_test, void)
1facf9fc 3713+#endif /* CONFIG_AUFS_DEBUG */
3714+
3715+/* ---------------------------------------------------------------------- */
3716+
3717+/* debug print */
3718+
4a4d8108 3719+#define AuDbg(fmt, ...) do { \
1facf9fc 3720+ if (au_debug_test()) \
4a4d8108 3721+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 3722+} while (0)
4a4d8108
AM
3723+#define AuLabel(l) AuDbg(#l "\n")
3724+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
3725+#define AuWarn1(fmt, ...) do { \
1facf9fc 3726+ static unsigned char _c; \
3727+ if (!_c++) \
4a4d8108 3728+ pr_warning(fmt, ##__VA_ARGS__); \
1facf9fc 3729+} while (0)
3730+
4a4d8108 3731+#define AuErr1(fmt, ...) do { \
1facf9fc 3732+ static unsigned char _c; \
3733+ if (!_c++) \
4a4d8108 3734+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 3735+} while (0)
3736+
4a4d8108 3737+#define AuIOErr1(fmt, ...) do { \
1facf9fc 3738+ static unsigned char _c; \
3739+ if (!_c++) \
4a4d8108 3740+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 3741+} while (0)
3742+
3743+#define AuUnsupportMsg "This operation is not supported." \
3744+ " Please report this application to aufs-users ML."
4a4d8108
AM
3745+#define AuUnsupport(fmt, ...) do { \
3746+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 3747+ dump_stack(); \
3748+} while (0)
3749+
3750+#define AuTraceErr(e) do { \
3751+ if (unlikely((e) < 0)) \
3752+ AuDbg("err %d\n", (int)(e)); \
3753+} while (0)
3754+
3755+#define AuTraceErrPtr(p) do { \
3756+ if (IS_ERR(p)) \
3757+ AuDbg("err %ld\n", PTR_ERR(p)); \
3758+} while (0)
3759+
3760+/* dirty macros for debug print, use with "%.*s" and caution */
3761+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
3762+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
3763+
3764+/* ---------------------------------------------------------------------- */
3765+
3766+struct au_sbinfo;
3767+struct au_finfo;
dece6358 3768+struct dentry;
1facf9fc 3769+#ifdef CONFIG_AUFS_DEBUG
3770+extern char *au_plevel;
3771+struct au_nhash;
3772+void au_dpri_whlist(struct au_nhash *whlist);
3773+struct au_vdir;
3774+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 3775+struct inode;
1facf9fc 3776+void au_dpri_inode(struct inode *inode);
3777+void au_dpri_dentry(struct dentry *dentry);
dece6358 3778+struct file;
1facf9fc 3779+void au_dpri_file(struct file *filp);
dece6358 3780+struct super_block;
1facf9fc 3781+void au_dpri_sb(struct super_block *sb);
3782+
3783+void au_dbg_sleep_jiffy(int jiffy);
dece6358 3784+struct iattr;
1facf9fc 3785+void au_dbg_iattr(struct iattr *ia);
3786+
3787+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
3788+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
3789+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 3790+void au_dbg_verify_kthread(void);
e49829fe 3791+void au_dbg_verify_wkq(void);
1facf9fc 3792+
3793+int __init au_debug_init(void);
3794+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
3795+#define AuDbgWhlist(w) do { \
3796+ AuDbg(#w "\n"); \
3797+ au_dpri_whlist(w); \
3798+} while (0)
3799+
3800+#define AuDbgVdir(v) do { \
3801+ AuDbg(#v "\n"); \
3802+ au_dpri_vdir(v); \
3803+} while (0)
3804+
3805+#define AuDbgInode(i) do { \
3806+ AuDbg(#i "\n"); \
3807+ au_dpri_inode(i); \
3808+} while (0)
3809+
3810+#define AuDbgDentry(d) do { \
3811+ AuDbg(#d "\n"); \
3812+ au_dpri_dentry(d); \
3813+} while (0)
3814+
3815+#define AuDbgFile(f) do { \
3816+ AuDbg(#f "\n"); \
3817+ au_dpri_file(f); \
3818+} while (0)
3819+
3820+#define AuDbgSb(sb) do { \
3821+ AuDbg(#sb "\n"); \
3822+ au_dpri_sb(sb); \
3823+} while (0)
3824+
3825+#define AuDbgSleep(sec) do { \
3826+ AuDbg("sleep %d sec\n", sec); \
3827+ ssleep(sec); \
3828+} while (0)
3829+
3830+#define AuDbgSleepJiffy(jiffy) do { \
3831+ AuDbg("sleep %d jiffies\n", jiffy); \
3832+ au_dbg_sleep_jiffy(jiffy); \
3833+} while (0)
3834+
3835+#define AuDbgIAttr(ia) do { \
3836+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
3837+ au_dbg_iattr(ia); \
3838+} while (0)
4a4d8108
AM
3839+
3840+#define AuDbgSym(addr) do { \
3841+ char sym[KSYM_SYMBOL_LEN]; \
3842+ sprint_symbol(sym, (unsigned long)addr); \
3843+ AuDbg("%s\n", sym); \
3844+} while (0)
3845+
3846+#define AuInfoSym(addr) do { \
3847+ char sym[KSYM_SYMBOL_LEN]; \
3848+ sprint_symbol(sym, (unsigned long)addr); \
3849+ AuInfo("%s\n", sym); \
3850+} while (0)
1facf9fc 3851+#else
4a4d8108
AM
3852+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
3853+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
3854+ unsigned int sigen)
3855+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
3856+AuStubVoid(au_dbg_verify_kthread, void)
e49829fe 3857+AuStubVoid(au_dbg_verify_wkq, void)
4a4d8108
AM
3858+AuStubInt0(__init au_debug_init, void)
3859+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 3860+
1facf9fc 3861+#define AuDbgWhlist(w) do {} while (0)
3862+#define AuDbgVdir(v) do {} while (0)
3863+#define AuDbgInode(i) do {} while (0)
3864+#define AuDbgDentry(d) do {} while (0)
3865+#define AuDbgFile(f) do {} while (0)
3866+#define AuDbgSb(sb) do {} while (0)
3867+#define AuDbgSleep(sec) do {} while (0)
3868+#define AuDbgSleepJiffy(jiffy) do {} while (0)
3869+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
3870+#define AuDbgSym(addr) do {} while (0)
3871+#define AuInfoSym(addr) do {} while (0)
1facf9fc 3872+#endif /* CONFIG_AUFS_DEBUG */
3873+
3874+/* ---------------------------------------------------------------------- */
3875+
3876+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
3877+int __init au_sysrq_init(void);
3878+void au_sysrq_fin(void);
3879+
3880+#ifdef CONFIG_HW_CONSOLE
3881+#define au_dbg_blocked() do { \
3882+ WARN_ON(1); \
0c5527e5 3883+ handle_sysrq('w'); \
1facf9fc 3884+} while (0)
3885+#else
4a4d8108 3886+AuStubVoid(au_dbg_blocked, void)
1facf9fc 3887+#endif
3888+
3889+#else
4a4d8108
AM
3890+AuStubInt0(__init au_sysrq_init, void)
3891+AuStubVoid(au_sysrq_fin, void)
3892+AuStubVoid(au_dbg_blocked, void)
1facf9fc 3893+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
3894+
3895+#endif /* __KERNEL__ */
3896+#endif /* __AUFS_DEBUG_H__ */
e49829fe 3897--- /dev/null
0c5527e5 3898+++ linux-2.6/fs/aufs/dentry.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 3899@@ -0,0 +1,860 @@
1facf9fc 3900+/*
4a4d8108 3901+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 3902+ *
3903+ * This program, aufs is free software; you can redistribute it and/or modify
3904+ * it under the terms of the GNU General Public License as published by
3905+ * the Free Software Foundation; either version 2 of the License, or
3906+ * (at your option) any later version.
dece6358
AM
3907+ *
3908+ * This program is distributed in the hope that it will be useful,
3909+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3910+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3911+ * GNU General Public License for more details.
3912+ *
3913+ * You should have received a copy of the GNU General Public License
3914+ * along with this program; if not, write to the Free Software
3915+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3916+ */
3917+
3918+/*
3919+ * lookup and dentry operations
3920+ */
3921+
dece6358 3922+#include <linux/namei.h>
1facf9fc 3923+#include "aufs.h"
3924+
3925+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
3926+{
3927+ if (nd) {
3928+ *h_nd = *nd;
3929+
3930+ /*
3931+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
3932+ * due to whiteout and branch permission.
3933+ */
3934+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
b752ccd1 3935+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
1facf9fc 3936+ /* unnecessary? */
3937+ h_nd->intent.open.file = NULL;
3938+ } else
3939+ memset(h_nd, 0, sizeof(*h_nd));
3940+}
3941+
3942+struct au_lkup_one_args {
3943+ struct dentry **errp;
3944+ struct qstr *name;
3945+ struct dentry *h_parent;
3946+ struct au_branch *br;
3947+ struct nameidata *nd;
3948+};
3949+
3950+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
3951+ struct au_branch *br, struct nameidata *nd)
3952+{
3953+ struct dentry *h_dentry;
3954+ int err;
3955+ struct nameidata h_nd;
3956+
3957+ if (au_test_fs_null_nd(h_parent->d_sb))
3958+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
3959+
3960+ au_h_nd(&h_nd, nd);
3961+ h_nd.path.dentry = h_parent;
3962+ h_nd.path.mnt = br->br_mnt;
3963+
3964+ err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
3965+ h_dentry = ERR_PTR(err);
3966+ if (!err) {
3967+ path_get(&h_nd.path);
3968+ h_dentry = vfsub_lookup_hash(&h_nd);
3969+ path_put(&h_nd.path);
3970+ }
3971+
4a4d8108 3972+ AuTraceErrPtr(h_dentry);
1facf9fc 3973+ return h_dentry;
3974+}
3975+
3976+static void au_call_lkup_one(void *args)
3977+{
3978+ struct au_lkup_one_args *a = args;
3979+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
3980+}
3981+
3982+#define AuLkup_ALLOW_NEG 1
3983+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
3984+#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; }
3985+#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; }
3986+
3987+struct au_do_lookup_args {
3988+ unsigned int flags;
3989+ mode_t type;
3990+ struct nameidata *nd;
3991+};
3992+
3993+/*
3994+ * returns positive/negative dentry, NULL or an error.
3995+ * NULL means whiteout-ed or not-found.
3996+ */
3997+static struct dentry*
3998+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
3999+ aufs_bindex_t bindex, struct qstr *wh_name,
4000+ struct au_do_lookup_args *args)
4001+{
4002+ struct dentry *h_dentry;
4003+ struct inode *h_inode, *inode;
1facf9fc 4004+ struct au_branch *br;
4005+ int wh_found, opq;
4006+ unsigned char wh_able;
4007+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
4008+
1facf9fc 4009+ wh_found = 0;
4010+ br = au_sbr(dentry->d_sb, bindex);
4011+ wh_able = !!au_br_whable(br->br_perm);
4012+ if (wh_able)
4013+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
4014+ h_dentry = ERR_PTR(wh_found);
4015+ if (!wh_found)
4016+ goto real_lookup;
4017+ if (unlikely(wh_found < 0))
4018+ goto out;
4019+
4020+ /* We found a whiteout */
4021+ /* au_set_dbend(dentry, bindex); */
4022+ au_set_dbwh(dentry, bindex);
4023+ if (!allow_neg)
4024+ return NULL; /* success */
4025+
4f0767ce 4026+real_lookup:
4a4d8108 4027+ h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
1facf9fc 4028+ if (IS_ERR(h_dentry))
4029+ goto out;
4030+
4031+ h_inode = h_dentry->d_inode;
4032+ if (!h_inode) {
4033+ if (!allow_neg)
4034+ goto out_neg;
4035+ } else if (wh_found
4036+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
4037+ goto out_neg;
4038+
4039+ if (au_dbend(dentry) <= bindex)
4040+ au_set_dbend(dentry, bindex);
4041+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4042+ au_set_dbstart(dentry, bindex);
4043+ au_set_h_dptr(dentry, bindex, h_dentry);
4044+
4045+ inode = dentry->d_inode;
4046+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4047+ || (inode && !S_ISDIR(inode->i_mode)))
4048+ goto out; /* success */
4049+
4050+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4051+ opq = au_diropq_test(h_dentry, br);
4052+ mutex_unlock(&h_inode->i_mutex);
4053+ if (opq > 0)
4054+ au_set_dbdiropq(dentry, bindex);
4055+ else if (unlikely(opq < 0)) {
4056+ au_set_h_dptr(dentry, bindex, NULL);
4057+ h_dentry = ERR_PTR(opq);
4058+ }
4059+ goto out;
4060+
4f0767ce 4061+out_neg:
1facf9fc 4062+ dput(h_dentry);
4063+ h_dentry = NULL;
4f0767ce 4064+out:
1facf9fc 4065+ return h_dentry;
4066+}
4067+
dece6358
AM
4068+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
4069+{
4070+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
4071+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
4072+ return -EPERM;
4073+ return 0;
4074+}
4075+
1facf9fc 4076+/*
4077+ * returns the number of lower positive dentries,
4078+ * otherwise an error.
4079+ * can be called at unlinking with @type is zero.
4080+ */
4081+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4082+ struct nameidata *nd)
4083+{
4084+ int npositive, err;
4085+ aufs_bindex_t bindex, btail, bdiropq;
4086+ unsigned char isdir;
4087+ struct qstr whname;
4088+ struct au_do_lookup_args args = {
4089+ .flags = 0,
4090+ .type = type,
4091+ .nd = nd
4092+ };
4093+ const struct qstr *name = &dentry->d_name;
4094+ struct dentry *parent;
4095+ struct inode *inode;
4096+
dece6358
AM
4097+ err = au_test_shwh(dentry->d_sb, name);
4098+ if (unlikely(err))
1facf9fc 4099+ goto out;
4100+
4101+ err = au_wh_name_alloc(&whname, name);
4102+ if (unlikely(err))
4103+ goto out;
4104+
4105+ inode = dentry->d_inode;
4106+ isdir = !!(inode && S_ISDIR(inode->i_mode));
4107+ if (!type)
4108+ au_fset_lkup(args.flags, ALLOW_NEG);
4109+
4110+ npositive = 0;
4a4d8108 4111+ parent = dget_parent(dentry);
1facf9fc 4112+ btail = au_dbtaildir(parent);
4113+ for (bindex = bstart; bindex <= btail; bindex++) {
4114+ struct dentry *h_parent, *h_dentry;
4115+ struct inode *h_inode, *h_dir;
4116+
4117+ h_dentry = au_h_dptr(dentry, bindex);
4118+ if (h_dentry) {
4119+ if (h_dentry->d_inode)
4120+ npositive++;
4121+ if (type != S_IFDIR)
4122+ break;
4123+ continue;
4124+ }
4125+ h_parent = au_h_dptr(parent, bindex);
4126+ if (!h_parent)
4127+ continue;
4128+ h_dir = h_parent->d_inode;
4129+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
4130+ continue;
4131+
4132+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4133+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4134+ &args);
4135+ mutex_unlock(&h_dir->i_mutex);
4136+ err = PTR_ERR(h_dentry);
4137+ if (IS_ERR(h_dentry))
4a4d8108 4138+ goto out_parent;
1facf9fc 4139+ au_fclr_lkup(args.flags, ALLOW_NEG);
4140+
4141+ if (au_dbwh(dentry) >= 0)
4142+ break;
4143+ if (!h_dentry)
4144+ continue;
4145+ h_inode = h_dentry->d_inode;
4146+ if (!h_inode)
4147+ continue;
4148+ npositive++;
4149+ if (!args.type)
4150+ args.type = h_inode->i_mode & S_IFMT;
4151+ if (args.type != S_IFDIR)
4152+ break;
4153+ else if (isdir) {
4154+ /* the type of lower may be different */
4155+ bdiropq = au_dbdiropq(dentry);
4156+ if (bdiropq >= 0 && bdiropq <= bindex)
4157+ break;
4158+ }
4159+ }
4160+
4161+ if (npositive) {
4162+ AuLabel(positive);
4163+ au_update_dbstart(dentry);
4164+ }
4165+ err = npositive;
4166+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
4167+ && au_dbstart(dentry) < 0))
4168+ /* both of real entry and whiteout found */
4169+ err = -EIO;
4170+
4f0767ce 4171+out_parent:
4a4d8108 4172+ dput(parent);
1facf9fc 4173+ kfree(whname.name);
4f0767ce 4174+out:
1facf9fc 4175+ return err;
4176+}
4177+
4178+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4179+ struct au_branch *br)
4180+{
4181+ struct dentry *dentry;
4182+ int wkq_err;
4183+
4184+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
4185+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
4186+ else {
4187+ struct au_lkup_one_args args = {
4188+ .errp = &dentry,
4189+ .name = name,
4190+ .h_parent = parent,
4191+ .br = br,
4192+ .nd = NULL
4193+ };
4194+
4195+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
4196+ if (unlikely(wkq_err))
4197+ dentry = ERR_PTR(wkq_err);
4198+ }
4199+
4200+ return dentry;
4201+}
4202+
4203+/*
4204+ * lookup @dentry on @bindex which should be negative.
4205+ */
4206+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4207+{
4208+ int err;
4209+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 4210+
1facf9fc 4211+ parent = dget_parent(dentry);
4212+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 4213+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 4214+ au_sbr(dentry->d_sb, bindex));
4215+ err = PTR_ERR(h_dentry);
4216+ if (IS_ERR(h_dentry))
4217+ goto out;
4218+ if (unlikely(h_dentry->d_inode)) {
4219+ err = -EIO;
4220+ AuIOErr("b%d %.*s should be negative.\n",
4221+ bindex, AuDLNPair(h_dentry));
4222+ dput(h_dentry);
4223+ goto out;
4224+ }
4225+
4a4d8108 4226+ err = 0;
1facf9fc 4227+ if (bindex < au_dbstart(dentry))
4228+ au_set_dbstart(dentry, bindex);
4229+ if (au_dbend(dentry) < bindex)
4230+ au_set_dbend(dentry, bindex);
4231+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 4232+
4f0767ce 4233+out:
1facf9fc 4234+ dput(parent);
4235+ return err;
4236+}
4237+
4238+/* ---------------------------------------------------------------------- */
4239+
4240+/* subset of struct inode */
4241+struct au_iattr {
4242+ unsigned long i_ino;
4243+ /* unsigned int i_nlink; */
4244+ uid_t i_uid;
4245+ gid_t i_gid;
4246+ u64 i_version;
4247+/*
4248+ loff_t i_size;
4249+ blkcnt_t i_blocks;
4250+*/
4251+ umode_t i_mode;
4252+};
4253+
4254+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
4255+{
4256+ ia->i_ino = h_inode->i_ino;
4257+ /* ia->i_nlink = h_inode->i_nlink; */
4258+ ia->i_uid = h_inode->i_uid;
4259+ ia->i_gid = h_inode->i_gid;
4260+ ia->i_version = h_inode->i_version;
4261+/*
4262+ ia->i_size = h_inode->i_size;
4263+ ia->i_blocks = h_inode->i_blocks;
4264+*/
4265+ ia->i_mode = (h_inode->i_mode & S_IFMT);
4266+}
4267+
4268+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
4269+{
4270+ return ia->i_ino != h_inode->i_ino
4271+ /* || ia->i_nlink != h_inode->i_nlink */
4272+ || ia->i_uid != h_inode->i_uid
4273+ || ia->i_gid != h_inode->i_gid
4274+ || ia->i_version != h_inode->i_version
4275+/*
4276+ || ia->i_size != h_inode->i_size
4277+ || ia->i_blocks != h_inode->i_blocks
4278+*/
4279+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
4280+}
4281+
4282+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
4283+ struct au_branch *br)
4284+{
4285+ int err;
4286+ struct au_iattr ia;
4287+ struct inode *h_inode;
4288+ struct dentry *h_d;
4289+ struct super_block *h_sb;
4290+
4291+ err = 0;
4292+ memset(&ia, -1, sizeof(ia));
4293+ h_sb = h_dentry->d_sb;
4294+ h_inode = h_dentry->d_inode;
4295+ if (h_inode)
4296+ au_iattr_save(&ia, h_inode);
4297+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
4298+ /* nfs d_revalidate may return 0 for negative dentry */
4299+ /* fuse d_revalidate always return 0 for negative dentry */
4300+ goto out;
4301+
4302+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
4303+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
4304+ err = PTR_ERR(h_d);
4305+ if (IS_ERR(h_d))
4306+ goto out;
4307+
4308+ err = 0;
4309+ if (unlikely(h_d != h_dentry
4310+ || h_d->d_inode != h_inode
4311+ || (h_inode && au_iattr_test(&ia, h_inode))))
4312+ err = au_busy_or_stale();
4313+ dput(h_d);
4314+
4f0767ce 4315+out:
1facf9fc 4316+ AuTraceErr(err);
4317+ return err;
4318+}
4319+
4320+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
4321+ struct dentry *h_parent, struct au_branch *br)
4322+{
4323+ int err;
4324+
4325+ err = 0;
4326+ if (udba == AuOpt_UDBA_REVAL) {
4327+ IMustLock(h_dir);
4328+ err = (h_dentry->d_parent->d_inode != h_dir);
4a4d8108 4329+ } else if (udba == AuOpt_UDBA_HNOTIFY)
1facf9fc 4330+ err = au_h_verify_dentry(h_dentry, h_parent, br);
4331+
4332+ return err;
4333+}
4334+
4335+/* ---------------------------------------------------------------------- */
4336+
4337+static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
4338+ struct dentry *parent)
4339+{
4340+ struct dentry *h_d, *h_dp;
4341+ struct au_hdentry tmp, *q;
4342+ struct super_block *sb;
4343+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
4344+
1308ab2a 4345+ AuRwMustWriteLock(&dinfo->di_rwsem);
4346+
1facf9fc 4347+ bend = dinfo->di_bend;
4348+ bwh = dinfo->di_bwh;
4349+ bdiropq = dinfo->di_bdiropq;
4350+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
4351+ h_d = p->hd_dentry;
4352+ if (!h_d)
4353+ continue;
4354+
4355+ h_dp = dget_parent(h_d);
4356+ if (h_dp == au_h_dptr(parent, bindex)) {
4357+ dput(h_dp);
4358+ continue;
4359+ }
4360+
4361+ new_bindex = au_find_dbindex(parent, h_dp);
4362+ dput(h_dp);
4363+ if (dinfo->di_bwh == bindex)
4364+ bwh = new_bindex;
4365+ if (dinfo->di_bdiropq == bindex)
4366+ bdiropq = new_bindex;
4367+ if (new_bindex < 0) {
4368+ au_hdput(p);
4369+ p->hd_dentry = NULL;
4370+ continue;
4371+ }
4372+
4373+ /* swap two lower dentries, and loop again */
4374+ q = dinfo->di_hdentry + new_bindex;
4375+ tmp = *q;
4376+ *q = *p;
4377+ *p = tmp;
4378+ if (tmp.hd_dentry) {
4379+ bindex--;
4380+ p--;
4381+ }
4382+ }
4383+
4384+ sb = parent->d_sb;
4385+ dinfo->di_bwh = -1;
4386+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
4387+ dinfo->di_bwh = bwh;
4388+
4389+ dinfo->di_bdiropq = -1;
4390+ if (bdiropq >= 0
4391+ && bdiropq <= au_sbend(sb)
4392+ && au_sbr_whable(sb, bdiropq))
4393+ dinfo->di_bdiropq = bdiropq;
4394+
4395+ bend = au_dbend(parent);
4396+ p = dinfo->di_hdentry;
4397+ for (bindex = 0; bindex <= bend; bindex++, p++)
4398+ if (p->hd_dentry) {
4399+ dinfo->di_bstart = bindex;
4400+ break;
4401+ }
4402+
4403+ p = dinfo->di_hdentry + bend;
4404+ for (bindex = bend; bindex >= 0; bindex--, p--)
4405+ if (p->hd_dentry) {
4406+ dinfo->di_bend = bindex;
4407+ break;
4408+ }
4409+}
4410+
4411+/*
4412+ * returns the number of found lower positive dentries,
4413+ * otherwise an error.
4414+ */
4415+int au_refresh_hdentry(struct dentry *dentry, mode_t type)
4416+{
4417+ int npositive, err;
4418+ unsigned int sigen;
4419+ aufs_bindex_t bstart;
4420+ struct au_dinfo *dinfo;
4421+ struct super_block *sb;
4422+ struct dentry *parent;
4423+
1308ab2a 4424+ DiMustWriteLock(dentry);
4425+
1facf9fc 4426+ sb = dentry->d_sb;
4427+ AuDebugOn(IS_ROOT(dentry));
4428+ sigen = au_sigen(sb);
4429+ parent = dget_parent(dentry);
4430+ AuDebugOn(au_digen(parent) != sigen
4431+ || au_iigen(parent->d_inode) != sigen);
4432+
4433+ dinfo = au_di(dentry);
4434+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
4435+ npositive = err;
4436+ if (unlikely(err))
4437+ goto out;
4438+ au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
4439+ parent);
4440+
4441+ npositive = 0;
4442+ bstart = au_dbstart(parent);
4443+ if (type != S_IFDIR && dinfo->di_bstart == bstart)
4444+ goto out_dgen; /* success */
4445+
4446+ npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
4447+ if (npositive < 0)
4448+ goto out;
4449+ if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
4450+ d_drop(dentry);
4451+
4f0767ce 4452+out_dgen:
1facf9fc 4453+ au_update_digen(dentry);
4f0767ce 4454+out:
1facf9fc 4455+ dput(parent);
4456+ AuTraceErr(npositive);
4457+ return npositive;
4458+}
4459+
4460+static noinline_for_stack
4461+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
4462+ struct dentry *dentry, aufs_bindex_t bindex)
4463+{
4464+ int err, valid;
4465+ int (*reval)(struct dentry *, struct nameidata *);
4466+
4467+ err = 0;
4468+ reval = NULL;
4469+ if (h_dentry->d_op)
4470+ reval = h_dentry->d_op->d_revalidate;
4471+ if (!reval)
4472+ goto out;
4473+
4474+ AuDbg("b%d\n", bindex);
4475+ if (au_test_fs_null_nd(h_dentry->d_sb))
4476+ /* it may return tri-state */
4477+ valid = reval(h_dentry, NULL);
4478+ else {
4479+ struct nameidata h_nd;
4480+ int locked;
4481+ struct dentry *parent;
4482+
4483+ au_h_nd(&h_nd, nd);
4484+ parent = nd->path.dentry;
4485+ locked = (nd && nd->path.dentry != dentry);
4486+ if (locked)
4487+ di_read_lock_parent(parent, AuLock_IR);
4488+ BUG_ON(bindex > au_dbend(parent));
4489+ h_nd.path.dentry = au_h_dptr(parent, bindex);
4490+ BUG_ON(!h_nd.path.dentry);
4491+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
4492+ path_get(&h_nd.path);
4493+ valid = reval(h_dentry, &h_nd);
4494+ path_put(&h_nd.path);
4495+ if (locked)
4496+ di_read_unlock(parent, AuLock_IR);
4497+ }
4498+
4499+ if (unlikely(valid < 0))
4500+ err = valid;
4501+ else if (!valid)
4502+ err = -EINVAL;
4503+
4f0767ce 4504+out:
1facf9fc 4505+ AuTraceErr(err);
4506+ return err;
4507+}
4508+
4509+/* todo: remove this */
4510+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
4511+ struct nameidata *nd, int do_udba)
4512+{
4513+ int err;
4514+ umode_t mode, h_mode;
4515+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
4516+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 4517+ struct inode *h_inode, *h_cached_inode;
1facf9fc 4518+ struct dentry *h_dentry;
4519+ struct qstr *name, *h_name;
4520+
4521+ err = 0;
4522+ plus = 0;
4523+ mode = 0;
1facf9fc 4524+ ibs = -1;
4525+ ibe = -1;
4526+ unhashed = !!d_unhashed(dentry);
4527+ is_root = !!IS_ROOT(dentry);
4528+ name = &dentry->d_name;
4529+
4530+ /*
e49829fe
JR
4531+ * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
4532+ * But inotify doesn't fire some necessary events,
1facf9fc 4533+ * IN_ATTRIB for atime/nlink/pageio
4534+ * IN_DELETE for NFS dentry
4535+ * Let's do REVAL test too.
4536+ */
4537+ if (do_udba && inode) {
4538+ mode = (inode->i_mode & S_IFMT);
4539+ plus = (inode->i_nlink > 0);
1facf9fc 4540+ ibs = au_ibstart(inode);
4541+ ibe = au_ibend(inode);
4542+ }
4543+
4544+ bstart = au_dbstart(dentry);
4545+ btail = bstart;
4546+ if (inode && S_ISDIR(inode->i_mode))
4547+ btail = au_dbtaildir(dentry);
4548+ for (bindex = bstart; bindex <= btail; bindex++) {
4549+ h_dentry = au_h_dptr(dentry, bindex);
4550+ if (!h_dentry)
4551+ continue;
4552+
4553+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
4554+ h_name = &h_dentry->d_name;
4555+ if (unlikely(do_udba
4556+ && !is_root
4557+ && (unhashed != !!d_unhashed(h_dentry)
4558+ || name->len != h_name->len
4559+ || memcmp(name->name, h_name->name, name->len))
4560+ )) {
4561+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
4562+ unhashed, d_unhashed(h_dentry),
4563+ AuDLNPair(dentry), AuDLNPair(h_dentry));
4564+ goto err;
4565+ }
4566+
4567+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
4568+ if (unlikely(err))
4569+ /* do not goto err, to keep the errno */
4570+ break;
4571+
4572+ /* todo: plink too? */
4573+ if (!do_udba)
4574+ continue;
4575+
4576+ /* UDBA tests */
4577+ h_inode = h_dentry->d_inode;
4578+ if (unlikely(!!inode != !!h_inode))
4579+ goto err;
4580+
4581+ h_plus = plus;
4582+ h_mode = mode;
4583+ h_cached_inode = h_inode;
4584+ if (h_inode) {
4585+ h_mode = (h_inode->i_mode & S_IFMT);
4586+ h_plus = (h_inode->i_nlink > 0);
4587+ }
4588+ if (inode && ibs <= bindex && bindex <= ibe)
4589+ h_cached_inode = au_h_iptr(inode, bindex);
4590+
4591+ if (unlikely(plus != h_plus
4592+ || mode != h_mode
4593+ || h_cached_inode != h_inode))
4594+ goto err;
4595+ continue;
4596+
4597+ err:
4598+ err = -EINVAL;
4599+ break;
4600+ }
4601+
4602+ return err;
4603+}
4604+
4605+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
4606+{
4607+ int err;
4608+ struct dentry *parent;
4609+ struct inode *inode;
4610+
4611+ inode = dentry->d_inode;
4612+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
4613+ return 0;
4614+
4615+ parent = dget_parent(dentry);
4616+ di_read_lock_parent(parent, AuLock_IR);
4617+ AuDebugOn(au_digen(parent) != sigen
4618+ || au_iigen(parent->d_inode) != sigen);
4619+ au_dbg_verify_gen(parent, sigen);
4620+
4621+ /* returns a number of positive dentries */
4622+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
4623+ if (err >= 0)
4624+ err = au_refresh_hinode(inode, dentry);
4625+
4626+ di_read_unlock(parent, AuLock_IR);
4627+ dput(parent);
4628+ return err;
4629+}
4630+
4631+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
4632+{
4633+ int err;
4634+ struct dentry *d, *parent;
4635+ struct inode *inode;
4636+
4637+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
4638+ return simple_reval_dpath(dentry, sigen);
4639+
4640+ /* slow loop, keep it simple and stupid */
4641+ /* cf: au_cpup_dirs() */
4642+ err = 0;
4643+ parent = NULL;
4644+ while (au_digen(dentry) != sigen
4645+ || au_iigen(dentry->d_inode) != sigen) {
4646+ d = dentry;
4647+ while (1) {
4648+ dput(parent);
4649+ parent = dget_parent(d);
4650+ if (au_digen(parent) == sigen
4651+ && au_iigen(parent->d_inode) == sigen)
4652+ break;
4653+ d = parent;
4654+ }
4655+
4656+ inode = d->d_inode;
4657+ if (d != dentry)
4658+ di_write_lock_child(d);
4659+
4660+ /* someone might update our dentry while we were sleeping */
4661+ if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
4662+ di_read_lock_parent(parent, AuLock_IR);
4663+ /* returns a number of positive dentries */
4664+ err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
4665+ if (err >= 0)
4666+ err = au_refresh_hinode(inode, d);
4667+ di_read_unlock(parent, AuLock_IR);
4668+ }
4669+
4670+ if (d != dentry)
4671+ di_write_unlock(d);
4672+ dput(parent);
4673+ if (unlikely(err))
4674+ break;
4675+ }
4676+
4677+ return err;
4678+}
4679+
4680+/*
4681+ * if valid returns 1, otherwise 0.
4682+ */
4683+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
4684+{
4685+ int valid, err;
4686+ unsigned int sigen;
4687+ unsigned char do_udba;
4688+ struct super_block *sb;
4689+ struct inode *inode;
4690+
e49829fe 4691+ valid = 1;
1facf9fc 4692+ sb = dentry->d_sb;
4693+ inode = dentry->d_inode;
e49829fe
JR
4694+ /*
4695+ * todo: very ugly
4696+ * i_mutex of parent dir may be held,
4697+ * but we should not return 'invalid' due to busy.
4698+ */
4699+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
4700+ if (unlikely(err)) {
4701+ valid = err;
4702+ goto out;
4703+ }
1facf9fc 4704+ sigen = au_sigen(sb);
4705+ if (au_digen(dentry) != sigen) {
4706+ AuDebugOn(IS_ROOT(dentry));
4707+ if (inode)
4708+ err = au_reval_dpath(dentry, sigen);
4709+ if (unlikely(err))
4710+ goto out_dgrade;
1facf9fc 4711+ }
4712+ if (inode && au_iigen(inode) != sigen) {
4713+ AuDebugOn(IS_ROOT(dentry));
4714+ err = au_refresh_hinode(inode, dentry);
4715+ if (unlikely(err))
4716+ goto out_dgrade;
1facf9fc 4717+ }
4718+ di_downgrade_lock(dentry, AuLock_IR);
4719+
1facf9fc 4720+ err = -EINVAL;
4721+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
4722+ if (do_udba && inode) {
4723+ aufs_bindex_t bstart = au_ibstart(inode);
4724+
4725+ if (bstart >= 0
4726+ && au_test_higen(inode, au_h_iptr(inode, bstart)))
e49829fe 4727+ goto out_inval;
1facf9fc 4728+ }
4729+
4730+ err = h_d_revalidate(dentry, inode, nd, do_udba);
4731+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
4732+ /* both of real entry and whiteout found */
4733+ err = -EIO;
e49829fe 4734+ goto out_inval;
1facf9fc 4735+
4f0767ce 4736+out_dgrade:
1facf9fc 4737+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 4738+out_inval:
1facf9fc 4739+ aufs_read_unlock(dentry, AuLock_IR);
4740+ AuTraceErr(err);
4741+ valid = !err;
e49829fe 4742+out:
1facf9fc 4743+ if (!valid)
e49829fe 4744+ AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid);
1facf9fc 4745+ return valid;
4746+}
4747+
4748+static void aufs_d_release(struct dentry *dentry)
4749+{
4a4d8108
AM
4750+ if (dentry->d_fsdata) {
4751+ au_di_fin(dentry);
4752+ au_hn_di_reinit(dentry);
1facf9fc 4753+ }
1facf9fc 4754+}
4755+
4a4d8108 4756+const struct dentry_operations aufs_dop = {
1facf9fc 4757+ .d_revalidate = aufs_d_revalidate,
4758+ .d_release = aufs_d_release
4759+};
e49829fe 4760--- /dev/null
0c5527e5 4761+++ linux-2.6/fs/aufs/dentry.h 2010-10-25 14:20:44.000000000 +0200
1308ab2a 4762@@ -0,0 +1,231 @@
1facf9fc 4763+/*
4a4d8108 4764+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4765+ *
4766+ * This program, aufs is free software; you can redistribute it and/or modify
4767+ * it under the terms of the GNU General Public License as published by
4768+ * the Free Software Foundation; either version 2 of the License, or
4769+ * (at your option) any later version.
dece6358
AM
4770+ *
4771+ * This program is distributed in the hope that it will be useful,
4772+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4773+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4774+ * GNU General Public License for more details.
4775+ *
4776+ * You should have received a copy of the GNU General Public License
4777+ * along with this program; if not, write to the Free Software
4778+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4779+ */
4780+
4781+/*
4782+ * lookup and dentry operations
4783+ */
4784+
4785+#ifndef __AUFS_DENTRY_H__
4786+#define __AUFS_DENTRY_H__
4787+
4788+#ifdef __KERNEL__
4789+
dece6358 4790+#include <linux/dcache.h>
1facf9fc 4791+#include <linux/aufs_type.h>
4792+#include "rwsem.h"
4793+
4794+/* make a single member structure for future use */
4795+/* todo: remove this structure */
4796+struct au_hdentry {
4797+ struct dentry *hd_dentry;
4798+};
4799+
4800+struct au_dinfo {
4801+ atomic_t di_generation;
4802+
dece6358 4803+ struct au_rwsem di_rwsem;
1facf9fc 4804+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
4805+ struct au_hdentry *di_hdentry;
4a4d8108 4806+} ____cacheline_aligned_in_smp;
1facf9fc 4807+
4808+/* ---------------------------------------------------------------------- */
4809+
4810+/* dentry.c */
4a4d8108 4811+extern const struct dentry_operations aufs_dop;
1facf9fc 4812+struct au_branch;
4813+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
4814+ struct au_branch *br, struct nameidata *nd);
4815+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4816+ struct au_branch *br);
4817+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
4818+ struct dentry *h_parent, struct au_branch *br);
4819+
4820+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4821+ struct nameidata *nd);
4822+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
4823+int au_refresh_hdentry(struct dentry *dentry, mode_t type);
4824+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
4825+
4826+/* dinfo.c */
4a4d8108
AM
4827+void au_di_init_once(void *_di);
4828+int au_di_init(struct dentry *dentry);
4829+void au_di_fin(struct dentry *dentry);
1facf9fc 4830+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
4831+
4832+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
4833+void di_read_unlock(struct dentry *d, int flags);
4834+void di_downgrade_lock(struct dentry *d, int flags);
4835+void di_write_lock(struct dentry *d, unsigned int lsc);
4836+void di_write_unlock(struct dentry *d);
4837+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
4838+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
4839+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
4840+
4841+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
4842+aufs_bindex_t au_dbtail(struct dentry *dentry);
4843+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
4844+
4845+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
4846+ struct dentry *h_dentry);
4847+void au_update_digen(struct dentry *dentry);
4848+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
4849+void au_update_dbstart(struct dentry *dentry);
4850+void au_update_dbend(struct dentry *dentry);
4851+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
4852+
4853+/* ---------------------------------------------------------------------- */
4854+
4855+static inline struct au_dinfo *au_di(struct dentry *dentry)
4856+{
4857+ return dentry->d_fsdata;
4858+}
4859+
4860+/* ---------------------------------------------------------------------- */
4861+
4862+/* lock subclass for dinfo */
4863+enum {
4864+ AuLsc_DI_CHILD, /* child first */
4a4d8108 4865+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 4866+ AuLsc_DI_CHILD3, /* copyup dirs */
4867+ AuLsc_DI_PARENT,
4868+ AuLsc_DI_PARENT2,
4869+ AuLsc_DI_PARENT3
4870+};
4871+
4872+/*
4873+ * di_read_lock_child, di_write_lock_child,
4874+ * di_read_lock_child2, di_write_lock_child2,
4875+ * di_read_lock_child3, di_write_lock_child3,
4876+ * di_read_lock_parent, di_write_lock_parent,
4877+ * di_read_lock_parent2, di_write_lock_parent2,
4878+ * di_read_lock_parent3, di_write_lock_parent3,
4879+ */
4880+#define AuReadLockFunc(name, lsc) \
4881+static inline void di_read_lock_##name(struct dentry *d, int flags) \
4882+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
4883+
4884+#define AuWriteLockFunc(name, lsc) \
4885+static inline void di_write_lock_##name(struct dentry *d) \
4886+{ di_write_lock(d, AuLsc_DI_##lsc); }
4887+
4888+#define AuRWLockFuncs(name, lsc) \
4889+ AuReadLockFunc(name, lsc) \
4890+ AuWriteLockFunc(name, lsc)
4891+
4892+AuRWLockFuncs(child, CHILD);
4893+AuRWLockFuncs(child2, CHILD2);
4894+AuRWLockFuncs(child3, CHILD3);
4895+AuRWLockFuncs(parent, PARENT);
4896+AuRWLockFuncs(parent2, PARENT2);
4897+AuRWLockFuncs(parent3, PARENT3);
4898+
4899+#undef AuReadLockFunc
4900+#undef AuWriteLockFunc
4901+#undef AuRWLockFuncs
4902+
4903+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
4904+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
4905+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 4906+
4907+/* ---------------------------------------------------------------------- */
4908+
4909+/* todo: memory barrier? */
4910+static inline unsigned int au_digen(struct dentry *d)
4911+{
4912+ return atomic_read(&au_di(d)->di_generation);
4913+}
4914+
4915+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
4916+{
4917+ hdentry->hd_dentry = NULL;
4918+}
4919+
4920+static inline void au_hdput(struct au_hdentry *hd)
4921+{
4a4d8108
AM
4922+ if (hd)
4923+ dput(hd->hd_dentry);
1facf9fc 4924+}
4925+
4926+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
4927+{
1308ab2a 4928+ DiMustAnyLock(dentry);
1facf9fc 4929+ return au_di(dentry)->di_bstart;
4930+}
4931+
4932+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
4933+{
1308ab2a 4934+ DiMustAnyLock(dentry);
1facf9fc 4935+ return au_di(dentry)->di_bend;
4936+}
4937+
4938+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
4939+{
1308ab2a 4940+ DiMustAnyLock(dentry);
1facf9fc 4941+ return au_di(dentry)->di_bwh;
4942+}
4943+
4944+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
4945+{
1308ab2a 4946+ DiMustAnyLock(dentry);
1facf9fc 4947+ return au_di(dentry)->di_bdiropq;
4948+}
4949+
4950+/* todo: hard/soft set? */
4951+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
4952+{
1308ab2a 4953+ DiMustWriteLock(dentry);
1facf9fc 4954+ au_di(dentry)->di_bstart = bindex;
4955+}
4956+
4957+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
4958+{
1308ab2a 4959+ DiMustWriteLock(dentry);
1facf9fc 4960+ au_di(dentry)->di_bend = bindex;
4961+}
4962+
4963+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
4964+{
1308ab2a 4965+ DiMustWriteLock(dentry);
1facf9fc 4966+ /* dbwh can be outside of bstart - bend range */
4967+ au_di(dentry)->di_bwh = bindex;
4968+}
4969+
4970+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
4971+{
1308ab2a 4972+ DiMustWriteLock(dentry);
1facf9fc 4973+ au_di(dentry)->di_bdiropq = bindex;
4974+}
4975+
4976+/* ---------------------------------------------------------------------- */
4977+
4a4d8108 4978+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 4979+static inline void au_digen_dec(struct dentry *d)
4980+{
e49829fe 4981+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 4982+}
4983+
4a4d8108 4984+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 4985+{
4986+ dentry->d_fsdata = NULL;
4987+}
4988+#else
4a4d8108
AM
4989+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
4990+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 4991+
4992+#endif /* __KERNEL__ */
4993+#endif /* __AUFS_DENTRY_H__ */
e49829fe 4994--- /dev/null
0c5527e5 4995+++ linux-2.6/fs/aufs/dinfo.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 4996@@ -0,0 +1,397 @@
1facf9fc 4997+/*
4a4d8108 4998+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 4999+ *
5000+ * This program, aufs is free software; you can redistribute it and/or modify
5001+ * it under the terms of the GNU General Public License as published by
5002+ * the Free Software Foundation; either version 2 of the License, or
5003+ * (at your option) any later version.
dece6358
AM
5004+ *
5005+ * This program is distributed in the hope that it will be useful,
5006+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5007+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5008+ * GNU General Public License for more details.
5009+ *
5010+ * You should have received a copy of the GNU General Public License
5011+ * along with this program; if not, write to the Free Software
5012+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5013+ */
5014+
5015+/*
5016+ * dentry private data
5017+ */
5018+
5019+#include "aufs.h"
5020+
e49829fe 5021+void au_di_init_once(void *_dinfo)
4a4d8108 5022+{
e49829fe
JR
5023+ struct au_dinfo *dinfo = _dinfo;
5024+ static struct lock_class_key aufs_di;
4a4d8108 5025+
e49829fe
JR
5026+ au_rw_init(&dinfo->di_rwsem);
5027+ au_rw_class(&dinfo->di_rwsem, &aufs_di);
4a4d8108
AM
5028+}
5029+
5030+int au_di_init(struct dentry *dentry)
1facf9fc 5031+{
5032+ struct au_dinfo *dinfo;
5033+ struct super_block *sb;
5034+ int nbr;
5035+
5036+ dinfo = au_cache_alloc_dinfo();
5037+ if (unlikely(!dinfo))
5038+ goto out;
5039+
5040+ sb = dentry->d_sb;
5041+ nbr = au_sbend(sb) + 1;
5042+ if (nbr <= 0)
5043+ nbr = 1;
5044+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
5045+ if (unlikely(!dinfo->di_hdentry))
5046+ goto out_dinfo;
5047+
5048+ atomic_set(&dinfo->di_generation, au_sigen(sb));
5049+ /* smp_mb(); */ /* atomic_set */
4a4d8108 5050+ au_rw_write_lock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
1facf9fc 5051+ dinfo->di_bstart = -1;
5052+ dinfo->di_bend = -1;
5053+ dinfo->di_bwh = -1;
5054+ dinfo->di_bdiropq = -1;
5055+
5056+ dentry->d_fsdata = dinfo;
5057+ dentry->d_op = &aufs_dop;
5058+ return 0; /* success */
5059+
4f0767ce 5060+out_dinfo:
1facf9fc 5061+ au_cache_free_dinfo(dinfo);
4f0767ce 5062+out:
1facf9fc 5063+ return -ENOMEM;
5064+}
5065+
4a4d8108
AM
5066+void au_di_fin(struct dentry *dentry)
5067+{
5068+ struct au_dinfo *di;
5069+ struct au_hdentry *p;
5070+ aufs_bindex_t bend, bindex;
5071+
5072+ /* dentry may not be revalidated */
5073+ di = dentry->d_fsdata;
5074+ bindex = di->di_bstart;
5075+ if (bindex >= 0) {
5076+ bend = di->di_bend;
5077+ p = di->di_hdentry + bindex;
5078+ while (bindex++ <= bend)
5079+ au_hdput(p++);
5080+ }
5081+ kfree(di->di_hdentry);
5082+ AuRwDestroy(&di->di_rwsem);
5083+ au_cache_free_dinfo(di);
5084+}
5085+
1facf9fc 5086+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
5087+{
5088+ int err, sz;
5089+ struct au_hdentry *hdp;
5090+
1308ab2a 5091+ AuRwMustWriteLock(&dinfo->di_rwsem);
5092+
1facf9fc 5093+ err = -ENOMEM;
5094+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
5095+ if (!sz)
5096+ sz = sizeof(*hdp);
5097+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
5098+ if (hdp) {
5099+ dinfo->di_hdentry = hdp;
5100+ err = 0;
5101+ }
5102+
5103+ return err;
5104+}
5105+
5106+/* ---------------------------------------------------------------------- */
5107+
5108+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
5109+{
5110+ switch (lsc) {
5111+ case AuLsc_DI_CHILD:
5112+ ii_write_lock_child(inode);
5113+ break;
5114+ case AuLsc_DI_CHILD2:
5115+ ii_write_lock_child2(inode);
5116+ break;
5117+ case AuLsc_DI_CHILD3:
5118+ ii_write_lock_child3(inode);
5119+ break;
5120+ case AuLsc_DI_PARENT:
5121+ ii_write_lock_parent(inode);
5122+ break;
5123+ case AuLsc_DI_PARENT2:
5124+ ii_write_lock_parent2(inode);
5125+ break;
5126+ case AuLsc_DI_PARENT3:
5127+ ii_write_lock_parent3(inode);
5128+ break;
5129+ default:
5130+ BUG();
5131+ }
5132+}
5133+
5134+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
5135+{
5136+ switch (lsc) {
5137+ case AuLsc_DI_CHILD:
5138+ ii_read_lock_child(inode);
5139+ break;
5140+ case AuLsc_DI_CHILD2:
5141+ ii_read_lock_child2(inode);
5142+ break;
5143+ case AuLsc_DI_CHILD3:
5144+ ii_read_lock_child3(inode);
5145+ break;
5146+ case AuLsc_DI_PARENT:
5147+ ii_read_lock_parent(inode);
5148+ break;
5149+ case AuLsc_DI_PARENT2:
5150+ ii_read_lock_parent2(inode);
5151+ break;
5152+ case AuLsc_DI_PARENT3:
5153+ ii_read_lock_parent3(inode);
5154+ break;
5155+ default:
5156+ BUG();
5157+ }
5158+}
5159+
5160+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
5161+{
dece6358 5162+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5163+ if (d->d_inode) {
5164+ if (au_ftest_lock(flags, IW))
5165+ do_ii_write_lock(d->d_inode, lsc);
5166+ else if (au_ftest_lock(flags, IR))
5167+ do_ii_read_lock(d->d_inode, lsc);
5168+ }
5169+}
5170+
5171+void di_read_unlock(struct dentry *d, int flags)
5172+{
5173+ if (d->d_inode) {
5174+ if (au_ftest_lock(flags, IW))
5175+ ii_write_unlock(d->d_inode);
5176+ else if (au_ftest_lock(flags, IR))
5177+ ii_read_unlock(d->d_inode);
5178+ }
dece6358 5179+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 5180+}
5181+
5182+void di_downgrade_lock(struct dentry *d, int flags)
5183+{
1facf9fc 5184+ if (d->d_inode && au_ftest_lock(flags, IR))
5185+ ii_downgrade_lock(d->d_inode);
dece6358 5186+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 5187+}
5188+
5189+void di_write_lock(struct dentry *d, unsigned int lsc)
5190+{
dece6358 5191+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 5192+ if (d->d_inode)
5193+ do_ii_write_lock(d->d_inode, lsc);
5194+}
5195+
5196+void di_write_unlock(struct dentry *d)
5197+{
5198+ if (d->d_inode)
5199+ ii_write_unlock(d->d_inode);
dece6358 5200+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 5201+}
5202+
5203+void di_write_lock2_child(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_child(d1);
5211+ di_write_lock_child2(d2);
5212+ } else {
5213+ /* there should be no races */
5214+ di_write_lock_child(d2);
5215+ di_write_lock_child2(d1);
5216+ }
5217+}
5218+
5219+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
5220+{
5221+ AuDebugOn(d1 == d2
5222+ || d1->d_inode == d2->d_inode
5223+ || d1->d_sb != d2->d_sb);
5224+
5225+ if (isdir && au_test_subdir(d1, d2)) {
5226+ di_write_lock_parent(d1);
5227+ di_write_lock_parent2(d2);
5228+ } else {
5229+ /* there should be no races */
5230+ di_write_lock_parent(d2);
5231+ di_write_lock_parent2(d1);
5232+ }
5233+}
5234+
5235+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
5236+{
5237+ di_write_unlock(d1);
5238+ if (d1->d_inode == d2->d_inode)
dece6358 5239+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 5240+ else
5241+ di_write_unlock(d2);
5242+}
5243+
5244+/* ---------------------------------------------------------------------- */
5245+
5246+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
5247+{
5248+ struct dentry *d;
5249+
1308ab2a 5250+ DiMustAnyLock(dentry);
5251+
1facf9fc 5252+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
5253+ return NULL;
5254+ AuDebugOn(bindex < 0);
5255+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
5256+ AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
5257+ return d;
5258+}
5259+
5260+aufs_bindex_t au_dbtail(struct dentry *dentry)
5261+{
5262+ aufs_bindex_t bend, bwh;
5263+
5264+ bend = au_dbend(dentry);
5265+ if (0 <= bend) {
5266+ bwh = au_dbwh(dentry);
5267+ if (!bwh)
5268+ return bwh;
5269+ if (0 < bwh && bwh < bend)
5270+ return bwh - 1;
5271+ }
5272+ return bend;
5273+}
5274+
5275+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
5276+{
5277+ aufs_bindex_t bend, bopq;
5278+
5279+ bend = au_dbtail(dentry);
5280+ if (0 <= bend) {
5281+ bopq = au_dbdiropq(dentry);
5282+ if (0 <= bopq && bopq < bend)
5283+ bend = bopq;
5284+ }
5285+ return bend;
5286+}
5287+
5288+/* ---------------------------------------------------------------------- */
5289+
5290+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5291+ struct dentry *h_dentry)
5292+{
5293+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
5294+
1308ab2a 5295+ DiMustWriteLock(dentry);
5296+
4a4d8108 5297+ au_hdput(hd);
1facf9fc 5298+ hd->hd_dentry = h_dentry;
5299+}
5300+
5301+void au_update_digen(struct dentry *dentry)
5302+{
5303+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
5304+ /* smp_mb(); */ /* atomic_set */
5305+}
5306+
5307+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
5308+{
5309+ struct au_dinfo *dinfo;
5310+ struct dentry *h_d;
4a4d8108 5311+ struct au_hdentry *hdp;
1facf9fc 5312+
1308ab2a 5313+ DiMustWriteLock(dentry);
5314+
1facf9fc 5315+ dinfo = au_di(dentry);
5316+ if (!dinfo || dinfo->di_bstart < 0)
5317+ return;
5318+
4a4d8108 5319+ hdp = dinfo->di_hdentry;
1facf9fc 5320+ if (do_put_zero) {
5321+ aufs_bindex_t bindex, bend;
5322+
5323+ bend = dinfo->di_bend;
5324+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 5325+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 5326+ if (h_d && !h_d->d_inode)
5327+ au_set_h_dptr(dentry, bindex, NULL);
5328+ }
5329+ }
5330+
5331+ dinfo->di_bstart = -1;
5332+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 5333+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 5334+ break;
5335+ if (dinfo->di_bstart > dinfo->di_bend) {
5336+ dinfo->di_bstart = -1;
5337+ dinfo->di_bend = -1;
5338+ return;
5339+ }
5340+
5341+ dinfo->di_bend++;
5342+ while (0 <= --dinfo->di_bend)
4a4d8108 5343+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 5344+ break;
5345+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
5346+}
5347+
5348+void au_update_dbstart(struct dentry *dentry)
5349+{
5350+ aufs_bindex_t bindex, bend;
5351+ struct dentry *h_dentry;
5352+
5353+ bend = au_dbend(dentry);
5354+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
5355+ h_dentry = au_h_dptr(dentry, bindex);
5356+ if (!h_dentry)
5357+ continue;
5358+ if (h_dentry->d_inode) {
5359+ au_set_dbstart(dentry, bindex);
5360+ return;
5361+ }
5362+ au_set_h_dptr(dentry, bindex, NULL);
5363+ }
5364+}
5365+
5366+void au_update_dbend(struct dentry *dentry)
5367+{
5368+ aufs_bindex_t bindex, bstart;
5369+ struct dentry *h_dentry;
5370+
5371+ bstart = au_dbstart(dentry);
5372+ for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
5373+ h_dentry = au_h_dptr(dentry, bindex);
5374+ if (!h_dentry)
5375+ continue;
5376+ if (h_dentry->d_inode) {
5377+ au_set_dbend(dentry, bindex);
5378+ return;
5379+ }
5380+ au_set_h_dptr(dentry, bindex, NULL);
5381+ }
5382+}
5383+
5384+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
5385+{
5386+ aufs_bindex_t bindex, bend;
5387+
5388+ bend = au_dbend(dentry);
5389+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
5390+ if (au_h_dptr(dentry, bindex) == h_dentry)
5391+ return bindex;
5392+ return -1;
5393+}
e49829fe 5394--- /dev/null
0c5527e5 5395+++ linux-2.6/fs/aufs/dir.c 2010-10-26 21:41:15.000000000 +0200
953406b4 5396@@ -0,0 +1,638 @@
1facf9fc 5397+/*
4a4d8108 5398+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 5399+ *
5400+ * This program, aufs is free software; you can redistribute it and/or modify
5401+ * it under the terms of the GNU General Public License as published by
5402+ * the Free Software Foundation; either version 2 of the License, or
5403+ * (at your option) any later version.
dece6358
AM
5404+ *
5405+ * This program is distributed in the hope that it will be useful,
5406+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5407+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5408+ * GNU General Public License for more details.
5409+ *
5410+ * You should have received a copy of the GNU General Public License
5411+ * along with this program; if not, write to the Free Software
5412+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5413+ */
5414+
5415+/*
5416+ * directory operations
5417+ */
5418+
dece6358 5419+#include <linux/file.h>
1facf9fc 5420+#include <linux/fs_stack.h>
5421+#include "aufs.h"
5422+
5423+void au_add_nlink(struct inode *dir, struct inode *h_dir)
5424+{
5425+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5426+
5427+ dir->i_nlink += h_dir->i_nlink - 2;
5428+ if (h_dir->i_nlink < 2)
5429+ dir->i_nlink += 2;
5430+}
5431+
5432+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
5433+{
5434+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
5435+
5436+ dir->i_nlink -= h_dir->i_nlink - 2;
5437+ if (h_dir->i_nlink < 2)
5438+ dir->i_nlink -= 2;
5439+}
5440+
1308ab2a 5441+loff_t au_dir_size(struct file *file, struct dentry *dentry)
5442+{
5443+ loff_t sz;
5444+ aufs_bindex_t bindex, bend;
5445+ struct file *h_file;
5446+ struct dentry *h_dentry;
5447+
5448+ sz = 0;
5449+ if (file) {
5450+ AuDebugOn(!file->f_dentry);
5451+ AuDebugOn(!file->f_dentry->d_inode);
5452+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
5453+
4a4d8108 5454+ bend = au_fbend_dir(file);
1308ab2a 5455+ for (bindex = au_fbstart(file);
5456+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5457+ bindex++) {
4a4d8108 5458+ h_file = au_hf_dir(file, bindex);
1308ab2a 5459+ if (h_file
5460+ && h_file->f_dentry
5461+ && h_file->f_dentry->d_inode)
5462+ sz += i_size_read(h_file->f_dentry->d_inode);
5463+ }
5464+ } else {
5465+ AuDebugOn(!dentry);
5466+ AuDebugOn(!dentry->d_inode);
5467+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
5468+
5469+ bend = au_dbtaildir(dentry);
5470+ for (bindex = au_dbstart(dentry);
5471+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
5472+ bindex++) {
5473+ h_dentry = au_h_dptr(dentry, bindex);
5474+ if (h_dentry && h_dentry->d_inode)
5475+ sz += i_size_read(h_dentry->d_inode);
5476+ }
5477+ }
5478+ if (sz < KMALLOC_MAX_SIZE)
5479+ sz = roundup_pow_of_two(sz);
5480+ if (sz > KMALLOC_MAX_SIZE)
5481+ sz = KMALLOC_MAX_SIZE;
5482+ else if (sz < NAME_MAX) {
5483+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
5484+ sz = AUFS_RDBLK_DEF;
5485+ }
5486+ return sz;
5487+}
5488+
1facf9fc 5489+/* ---------------------------------------------------------------------- */
5490+
5491+static int reopen_dir(struct file *file)
5492+{
5493+ int err;
5494+ unsigned int flags;
5495+ aufs_bindex_t bindex, btail, bstart;
5496+ struct dentry *dentry, *h_dentry;
5497+ struct file *h_file;
5498+
5499+ /* open all lower dirs */
5500+ dentry = file->f_dentry;
5501+ bstart = au_dbstart(dentry);
5502+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
5503+ au_set_h_fptr(file, bindex, NULL);
5504+ au_set_fbstart(file, bstart);
5505+
5506+ btail = au_dbtaildir(dentry);
4a4d8108 5507+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 5508+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 5509+ au_set_fbend_dir(file, btail);
1facf9fc 5510+
4a4d8108 5511+ flags = vfsub_file_flags(file);
1facf9fc 5512+ for (bindex = bstart; bindex <= btail; bindex++) {
5513+ h_dentry = au_h_dptr(dentry, bindex);
5514+ if (!h_dentry)
5515+ continue;
4a4d8108 5516+ h_file = au_hf_dir(file, bindex);
1facf9fc 5517+ if (h_file)
5518+ continue;
5519+
5520+ h_file = au_h_open(dentry, bindex, flags, file);
5521+ err = PTR_ERR(h_file);
5522+ if (IS_ERR(h_file))
5523+ goto out; /* close all? */
5524+ au_set_h_fptr(file, bindex, h_file);
5525+ }
5526+ au_update_figen(file);
5527+ /* todo: necessary? */
5528+ /* file->f_ra = h_file->f_ra; */
5529+ err = 0;
5530+
4f0767ce 5531+out:
1facf9fc 5532+ return err;
5533+}
5534+
5535+static int do_open_dir(struct file *file, int flags)
5536+{
5537+ int err;
5538+ aufs_bindex_t bindex, btail;
5539+ struct dentry *dentry, *h_dentry;
5540+ struct file *h_file;
5541+
1308ab2a 5542+ FiMustWriteLock(file);
5543+
1facf9fc 5544+ err = 0;
5545+ dentry = file->f_dentry;
1facf9fc 5546+ file->f_version = dentry->d_inode->i_version;
5547+ bindex = au_dbstart(dentry);
5548+ au_set_fbstart(file, bindex);
5549+ btail = au_dbtaildir(dentry);
4a4d8108 5550+ au_set_fbend_dir(file, btail);
1facf9fc 5551+ for (; !err && bindex <= btail; bindex++) {
5552+ h_dentry = au_h_dptr(dentry, bindex);
5553+ if (!h_dentry)
5554+ continue;
5555+
5556+ h_file = au_h_open(dentry, bindex, flags, file);
5557+ if (IS_ERR(h_file)) {
5558+ err = PTR_ERR(h_file);
5559+ break;
5560+ }
5561+ au_set_h_fptr(file, bindex, h_file);
5562+ }
5563+ au_update_figen(file);
5564+ /* todo: necessary? */
5565+ /* file->f_ra = h_file->f_ra; */
5566+ if (!err)
5567+ return 0; /* success */
5568+
5569+ /* close all */
5570+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
5571+ au_set_h_fptr(file, bindex, NULL);
5572+ au_set_fbstart(file, -1);
4a4d8108
AM
5573+ au_set_fbend_dir(file, -1);
5574+
1facf9fc 5575+ return err;
5576+}
5577+
5578+static int aufs_open_dir(struct inode *inode __maybe_unused,
5579+ struct file *file)
5580+{
4a4d8108
AM
5581+ int err;
5582+ struct super_block *sb;
5583+ struct au_fidir *fidir;
5584+
5585+ err = -ENOMEM;
5586+ sb = file->f_dentry->d_sb;
5587+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 5588+ fidir = au_fidir_alloc(sb);
4a4d8108
AM
5589+ if (fidir) {
5590+ err = au_do_open(file, do_open_dir, fidir);
5591+ if (unlikely(err))
5592+ kfree(fidir);
5593+ }
5594+ si_read_unlock(sb);
5595+ return err;
1facf9fc 5596+}
5597+
5598+static int aufs_release_dir(struct inode *inode __maybe_unused,
5599+ struct file *file)
5600+{
5601+ struct au_vdir *vdir_cache;
4a4d8108
AM
5602+ struct au_finfo *finfo;
5603+ struct au_fidir *fidir;
5604+ aufs_bindex_t bindex, bend;
1facf9fc 5605+
4a4d8108
AM
5606+ finfo = au_fi(file);
5607+ fidir = finfo->fi_hdir;
5608+ if (fidir) {
0c5527e5
AM
5609+ /* remove me from sb->s_files */
5610+ file_sb_list_del(file);
5611+
4a4d8108
AM
5612+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
5613+ if (vdir_cache)
5614+ au_vdir_free(vdir_cache);
5615+
5616+ bindex = finfo->fi_btop;
5617+ if (bindex >= 0) {
5618+ /*
5619+ * calls fput() instead of filp_close(),
5620+ * since no dnotify or lock for the lower file.
5621+ */
5622+ bend = fidir->fd_bbot;
5623+ for (; bindex <= bend; bindex++)
5624+ au_set_h_fptr(file, bindex, NULL);
5625+ }
5626+ kfree(fidir);
5627+ finfo->fi_hdir = NULL;
1facf9fc 5628+ }
1facf9fc 5629+ au_finfo_fin(file);
1facf9fc 5630+ return 0;
5631+}
5632+
5633+/* ---------------------------------------------------------------------- */
5634+
4a4d8108
AM
5635+static int au_do_flush_dir(struct file *file, fl_owner_t id)
5636+{
5637+ int err;
5638+ aufs_bindex_t bindex, bend;
5639+ struct file *h_file;
5640+
5641+ err = 0;
5642+ bend = au_fbend_dir(file);
5643+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
5644+ h_file = au_hf_dir(file, bindex);
5645+ if (h_file)
5646+ err = vfsub_flush(h_file, id);
5647+ }
5648+ return err;
5649+}
5650+
5651+static int aufs_flush_dir(struct file *file, fl_owner_t id)
5652+{
5653+ return au_do_flush(file, id, au_do_flush_dir);
5654+}
5655+
5656+/* ---------------------------------------------------------------------- */
5657+
1facf9fc 5658+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
5659+{
5660+ int err;
5661+ aufs_bindex_t bend, bindex;
5662+ struct inode *inode;
5663+ struct super_block *sb;
5664+
5665+ err = 0;
5666+ sb = dentry->d_sb;
5667+ inode = dentry->d_inode;
5668+ IMustLock(inode);
5669+ bend = au_dbend(dentry);
5670+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
5671+ struct path h_path;
5672+ struct inode *h_inode;
5673+
5674+ if (au_test_ro(sb, bindex, inode))
5675+ continue;
5676+ h_path.dentry = au_h_dptr(dentry, bindex);
5677+ if (!h_path.dentry)
5678+ continue;
5679+ h_inode = h_path.dentry->d_inode;
5680+ if (!h_inode)
5681+ continue;
5682+
5683+ /* no mnt_want_write() */
5684+ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
5685+ /* todo: inotiry fired? */
5686+ h_path.mnt = au_sbr_mnt(sb, bindex);
5687+ mutex_lock(&h_inode->i_mutex);
5688+ err = filemap_fdatawrite(h_inode->i_mapping);
5689+ AuDebugOn(!h_inode->i_fop);
5690+ if (!err && h_inode->i_fop->fsync)
b752ccd1 5691+ err = h_inode->i_fop->fsync(NULL, datasync);
1facf9fc 5692+ if (!err)
5693+ err = filemap_fdatawrite(h_inode->i_mapping);
5694+ if (!err)
5695+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
5696+ mutex_unlock(&h_inode->i_mutex);
5697+ }
5698+
5699+ return err;
5700+}
5701+
5702+static int au_do_fsync_dir(struct file *file, int datasync)
5703+{
5704+ int err;
5705+ aufs_bindex_t bend, bindex;
5706+ struct file *h_file;
5707+ struct super_block *sb;
5708+ struct inode *inode;
5709+ struct mutex *h_mtx;
5710+
5711+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
5712+ if (unlikely(err))
5713+ goto out;
5714+
5715+ sb = file->f_dentry->d_sb;
5716+ inode = file->f_dentry->d_inode;
4a4d8108 5717+ bend = au_fbend_dir(file);
1facf9fc 5718+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 5719+ h_file = au_hf_dir(file, bindex);
1facf9fc 5720+ if (!h_file || au_test_ro(sb, bindex, inode))
5721+ continue;
5722+
b752ccd1 5723+ err = vfs_fsync(h_file, datasync);
1facf9fc 5724+ if (!err) {
5725+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
5726+ mutex_lock(h_mtx);
5727+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
5728+ /*ignore*/
5729+ mutex_unlock(h_mtx);
5730+ }
5731+ }
5732+
4f0767ce 5733+out:
1facf9fc 5734+ return err;
5735+}
5736+
5737+/*
5738+ * @file may be NULL
5739+ */
b752ccd1 5740+static int aufs_fsync_dir(struct file *file, int datasync)
1facf9fc 5741+{
5742+ int err;
b752ccd1 5743+ struct dentry *dentry;
1facf9fc 5744+ struct super_block *sb;
5745+
b752ccd1 5746+ dentry = file->f_dentry;
1facf9fc 5747+ IMustLock(dentry->d_inode);
5748+
5749+ err = 0;
5750+ sb = dentry->d_sb;
5751+ si_noflush_read_lock(sb);
5752+ if (file)
5753+ err = au_do_fsync_dir(file, datasync);
5754+ else {
5755+ di_write_lock_child(dentry);
5756+ err = au_do_fsync_dir_no_file(dentry, datasync);
5757+ }
5758+ au_cpup_attr_timesizes(dentry->d_inode);
5759+ di_write_unlock(dentry);
5760+ if (file)
5761+ fi_write_unlock(file);
5762+
5763+ si_read_unlock(sb);
5764+ return err;
5765+}
5766+
5767+/* ---------------------------------------------------------------------- */
5768+
5769+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
5770+{
5771+ int err;
5772+ struct dentry *dentry;
5773+ struct inode *inode;
5774+ struct super_block *sb;
5775+
5776+ dentry = file->f_dentry;
5777+ inode = dentry->d_inode;
5778+ IMustLock(inode);
5779+
5780+ sb = dentry->d_sb;
5781+ si_read_lock(sb, AuLock_FLUSH);
5782+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
5783+ if (unlikely(err))
5784+ goto out;
5785+ err = au_vdir_init(file);
5786+ di_downgrade_lock(dentry, AuLock_IR);
5787+ if (unlikely(err))
5788+ goto out_unlock;
5789+
b752ccd1 5790+ if (!au_test_nfsd()) {
1facf9fc 5791+ err = au_vdir_fill_de(file, dirent, filldir);
5792+ fsstack_copy_attr_atime(inode,
5793+ au_h_iptr(inode, au_ibstart(inode)));
5794+ } else {
5795+ /*
5796+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
5797+ * encode_fh() and others.
5798+ */
5799+ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
5800+
5801+ di_read_unlock(dentry, AuLock_IR);
5802+ si_read_unlock(sb);
1facf9fc 5803+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 5804+ fsstack_copy_attr_atime(inode, h_inode);
5805+ fi_write_unlock(file);
5806+
5807+ AuTraceErr(err);
5808+ return err;
5809+ }
5810+
4f0767ce 5811+out_unlock:
1facf9fc 5812+ di_read_unlock(dentry, AuLock_IR);
5813+ fi_write_unlock(file);
4f0767ce 5814+out:
1facf9fc 5815+ si_read_unlock(sb);
5816+ return err;
5817+}
5818+
5819+/* ---------------------------------------------------------------------- */
5820+
5821+#define AuTestEmpty_WHONLY 1
dece6358
AM
5822+#define AuTestEmpty_CALLED (1 << 1)
5823+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 5824+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
5825+#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
5826+#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
5827+
dece6358
AM
5828+#ifndef CONFIG_AUFS_SHWH
5829+#undef AuTestEmpty_SHWH
5830+#define AuTestEmpty_SHWH 0
5831+#endif
5832+
1facf9fc 5833+struct test_empty_arg {
1308ab2a 5834+ struct au_nhash *whlist;
1facf9fc 5835+ unsigned int flags;
5836+ int err;
5837+ aufs_bindex_t bindex;
5838+};
5839+
5840+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
5841+ loff_t offset __maybe_unused, u64 ino,
5842+ unsigned int d_type)
1facf9fc 5843+{
5844+ struct test_empty_arg *arg = __arg;
5845+ char *name = (void *)__name;
5846+
5847+ arg->err = 0;
5848+ au_fset_testempty(arg->flags, CALLED);
5849+ /* smp_mb(); */
5850+ if (name[0] == '.'
5851+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
5852+ goto out; /* success */
5853+
5854+ if (namelen <= AUFS_WH_PFX_LEN
5855+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
5856+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 5857+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 5858+ arg->err = -ENOTEMPTY;
5859+ goto out;
5860+ }
5861+
5862+ name += AUFS_WH_PFX_LEN;
5863+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 5864+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 5865+ arg->err = au_nhash_append_wh
1308ab2a 5866+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 5867+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 5868+
4f0767ce 5869+out:
1facf9fc 5870+ /* smp_mb(); */
5871+ AuTraceErr(arg->err);
5872+ return arg->err;
5873+}
5874+
5875+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
5876+{
5877+ int err;
5878+ struct file *h_file;
5879+
5880+ h_file = au_h_open(dentry, arg->bindex,
5881+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
5882+ /*file*/NULL);
5883+ err = PTR_ERR(h_file);
5884+ if (IS_ERR(h_file))
5885+ goto out;
5886+
5887+ err = 0;
5888+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
5889+ && !h_file->f_dentry->d_inode->i_nlink)
5890+ goto out_put;
5891+
5892+ do {
5893+ arg->err = 0;
5894+ au_fclr_testempty(arg->flags, CALLED);
5895+ /* smp_mb(); */
5896+ err = vfsub_readdir(h_file, test_empty_cb, arg);
5897+ if (err >= 0)
5898+ err = arg->err;
5899+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
5900+
4f0767ce 5901+out_put:
1facf9fc 5902+ fput(h_file);
5903+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 5904+out:
1facf9fc 5905+ return err;
5906+}
5907+
5908+struct do_test_empty_args {
5909+ int *errp;
5910+ struct dentry *dentry;
5911+ struct test_empty_arg *arg;
5912+};
5913+
5914+static void call_do_test_empty(void *args)
5915+{
5916+ struct do_test_empty_args *a = args;
5917+ *a->errp = do_test_empty(a->dentry, a->arg);
5918+}
5919+
5920+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
5921+{
5922+ int err, wkq_err;
5923+ struct dentry *h_dentry;
5924+ struct inode *h_inode;
5925+
5926+ h_dentry = au_h_dptr(dentry, arg->bindex);
5927+ h_inode = h_dentry->d_inode;
5928+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
5929+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
5930+ mutex_unlock(&h_inode->i_mutex);
5931+ if (!err)
5932+ err = do_test_empty(dentry, arg);
5933+ else {
5934+ struct do_test_empty_args args = {
5935+ .errp = &err,
5936+ .dentry = dentry,
5937+ .arg = arg
5938+ };
5939+ unsigned int flags = arg->flags;
5940+
5941+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
5942+ if (unlikely(wkq_err))
5943+ err = wkq_err;
5944+ arg->flags = flags;
5945+ }
5946+
5947+ return err;
5948+}
5949+
5950+int au_test_empty_lower(struct dentry *dentry)
5951+{
5952+ int err;
1308ab2a 5953+ unsigned int rdhash;
1facf9fc 5954+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 5955+ struct au_nhash whlist;
1facf9fc 5956+ struct test_empty_arg arg;
1facf9fc 5957+
dece6358
AM
5958+ SiMustAnyLock(dentry->d_sb);
5959+
1308ab2a 5960+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
5961+ if (!rdhash)
5962+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
5963+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 5964+ if (unlikely(err))
1facf9fc 5965+ goto out;
5966+
1facf9fc 5967+ arg.flags = 0;
1308ab2a 5968+ arg.whlist = &whlist;
5969+ bstart = au_dbstart(dentry);
dece6358
AM
5970+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
5971+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 5972+ arg.bindex = bstart;
5973+ err = do_test_empty(dentry, &arg);
5974+ if (unlikely(err))
5975+ goto out_whlist;
5976+
5977+ au_fset_testempty(arg.flags, WHONLY);
5978+ btail = au_dbtaildir(dentry);
5979+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
5980+ struct dentry *h_dentry;
5981+
5982+ h_dentry = au_h_dptr(dentry, bindex);
5983+ if (h_dentry && h_dentry->d_inode) {
5984+ arg.bindex = bindex;
5985+ err = do_test_empty(dentry, &arg);
5986+ }
5987+ }
5988+
4f0767ce 5989+out_whlist:
1308ab2a 5990+ au_nhash_wh_free(&whlist);
4f0767ce 5991+out:
1facf9fc 5992+ return err;
5993+}
5994+
5995+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
5996+{
5997+ int err;
5998+ struct test_empty_arg arg;
5999+ aufs_bindex_t bindex, btail;
6000+
6001+ err = 0;
1308ab2a 6002+ arg.whlist = whlist;
1facf9fc 6003+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
6004+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
6005+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 6006+ btail = au_dbtaildir(dentry);
6007+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
6008+ struct dentry *h_dentry;
6009+
6010+ h_dentry = au_h_dptr(dentry, bindex);
6011+ if (h_dentry && h_dentry->d_inode) {
6012+ arg.bindex = bindex;
6013+ err = sio_test_empty(dentry, &arg);
6014+ }
6015+ }
6016+
6017+ return err;
6018+}
6019+
6020+/* ---------------------------------------------------------------------- */
6021+
6022+const struct file_operations aufs_dir_fop = {
4a4d8108 6023+ .owner = THIS_MODULE,
1facf9fc 6024+ .read = generic_read_dir,
6025+ .readdir = aufs_readdir,
6026+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
6027+#ifdef CONFIG_COMPAT
6028+ .compat_ioctl = aufs_compat_ioctl_dir,
6029+#endif
1facf9fc 6030+ .open = aufs_open_dir,
6031+ .release = aufs_release_dir,
4a4d8108 6032+ .flush = aufs_flush_dir,
1facf9fc 6033+ .fsync = aufs_fsync_dir
6034+};
e49829fe 6035--- /dev/null
0c5527e5 6036+++ linux-2.6/fs/aufs/dir.h 2010-10-25 14:20:44.000000000 +0200
b752ccd1 6037@@ -0,0 +1,138 @@
1facf9fc 6038+/*
4a4d8108 6039+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 6040+ *
6041+ * This program, aufs is free software; you can redistribute it and/or modify
6042+ * it under the terms of the GNU General Public License as published by
6043+ * the Free Software Foundation; either version 2 of the License, or
6044+ * (at your option) any later version.
dece6358
AM
6045+ *
6046+ * This program is distributed in the hope that it will be useful,
6047+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6048+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6049+ * GNU General Public License for more details.
6050+ *
6051+ * You should have received a copy of the GNU General Public License
6052+ * along with this program; if not, write to the Free Software
6053+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6054+ */
6055+
6056+/*
6057+ * directory operations
6058+ */
6059+
6060+#ifndef __AUFS_DIR_H__
6061+#define __AUFS_DIR_H__
6062+
6063+#ifdef __KERNEL__
6064+
6065+#include <linux/fs.h>
6066+#include <linux/aufs_type.h>
6067+
6068+/* ---------------------------------------------------------------------- */
6069+
6070+/* need to be faster and smaller */
6071+
6072+struct au_nhash {
dece6358
AM
6073+ unsigned int nh_num;
6074+ struct hlist_head *nh_head;
1facf9fc 6075+};
6076+
6077+struct au_vdir_destr {
6078+ unsigned char len;
6079+ unsigned char name[0];
6080+} __packed;
6081+
6082+struct au_vdir_dehstr {
6083+ struct hlist_node hash;
6084+ struct au_vdir_destr *str;
4a4d8108 6085+} ____cacheline_aligned_in_smp;
1facf9fc 6086+
6087+struct au_vdir_de {
6088+ ino_t de_ino;
6089+ unsigned char de_type;
6090+ /* caution: packed */
6091+ struct au_vdir_destr de_str;
6092+} __packed;
6093+
6094+struct au_vdir_wh {
6095+ struct hlist_node wh_hash;
dece6358
AM
6096+#ifdef CONFIG_AUFS_SHWH
6097+ ino_t wh_ino;
1facf9fc 6098+ aufs_bindex_t wh_bindex;
dece6358
AM
6099+ unsigned char wh_type;
6100+#else
6101+ aufs_bindex_t wh_bindex;
6102+#endif
6103+ /* caution: packed */
1facf9fc 6104+ struct au_vdir_destr wh_str;
6105+} __packed;
6106+
6107+union au_vdir_deblk_p {
6108+ unsigned char *deblk;
6109+ struct au_vdir_de *de;
6110+};
6111+
6112+struct au_vdir {
6113+ unsigned char **vd_deblk;
6114+ unsigned long vd_nblk;
1facf9fc 6115+ struct {
6116+ unsigned long ul;
6117+ union au_vdir_deblk_p p;
6118+ } vd_last;
6119+
6120+ unsigned long vd_version;
dece6358 6121+ unsigned int vd_deblk_sz;
1facf9fc 6122+ unsigned long vd_jiffy;
4a4d8108 6123+} ____cacheline_aligned_in_smp;
1facf9fc 6124+
6125+/* ---------------------------------------------------------------------- */
6126+
6127+/* dir.c */
6128+extern const struct file_operations aufs_dir_fop;
6129+void au_add_nlink(struct inode *dir, struct inode *h_dir);
6130+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 6131+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 6132+int au_test_empty_lower(struct dentry *dentry);
6133+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
6134+
6135+/* vdir.c */
1308ab2a 6136+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
6137+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
6138+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 6139+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
6140+ int limit);
dece6358
AM
6141+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
6142+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
6143+ unsigned int d_type, aufs_bindex_t bindex,
6144+ unsigned char shwh);
1facf9fc 6145+void au_vdir_free(struct au_vdir *vdir);
6146+int au_vdir_init(struct file *file);
6147+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
6148+
6149+/* ioctl.c */
6150+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
6151+
1308ab2a 6152+#ifdef CONFIG_AUFS_RDU
6153+/* rdu.c */
6154+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
6155+#ifdef CONFIG_COMPAT
6156+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6157+ unsigned long arg);
6158+#endif
1308ab2a 6159+#else
6160+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
6161+ unsigned long arg)
6162+{
6163+ return -EINVAL;
6164+}
b752ccd1
AM
6165+#ifdef CONFIG_COMPAT
6166+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
6167+ unsigned long arg)
6168+{
6169+ return -EINVAL;
6170+}
6171+#endif
1308ab2a 6172+#endif
6173+
1facf9fc 6174+#endif /* __KERNEL__ */
6175+#endif /* __AUFS_DIR_H__ */
e49829fe 6176--- /dev/null
0c5527e5 6177+++ linux-2.6/fs/aufs/dynop.c 2010-10-25 14:20:44.000000000 +0200
b752ccd1 6178@@ -0,0 +1,425 @@
1facf9fc 6179+/*
4a4d8108 6180+ * Copyright (C) 2010 Junjiro R. Okajima
1facf9fc 6181+ *
6182+ * This program, aufs is free software; you can redistribute it and/or modify
6183+ * it under the terms of the GNU General Public License as published by
6184+ * the Free Software Foundation; either version 2 of the License, or
6185+ * (at your option) any later version.
dece6358
AM
6186+ *
6187+ * This program is distributed in the hope that it will be useful,
6188+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6189+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6190+ * GNU General Public License for more details.
6191+ *
6192+ * You should have received a copy of the GNU General Public License
6193+ * along with this program; if not, write to the Free Software
6194+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6195+ */
6196+
6197+/*
4a4d8108 6198+ * dynamically customizable operations for regular files
1facf9fc 6199+ */
6200+
1facf9fc 6201+#include "aufs.h"
6202+
4a4d8108 6203+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 6204+
4a4d8108
AM
6205+/*
6206+ * How large will these lists be?
6207+ * Usually just a few elements, 20-30 at most for each, I guess.
6208+ */
6209+static struct au_splhead dynop[AuDyLast];
6210+
6211+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 6212+{
4a4d8108
AM
6213+ struct au_dykey *key, *tmp;
6214+ struct list_head *head;
1facf9fc 6215+
4a4d8108
AM
6216+ key = NULL;
6217+ head = &spl->head;
6218+ rcu_read_lock();
6219+ list_for_each_entry_rcu(tmp, head, dk_list)
6220+ if (tmp->dk_op.dy_hop == h_op) {
6221+ key = tmp;
6222+ kref_get(&key->dk_kref);
6223+ break;
6224+ }
6225+ rcu_read_unlock();
6226+
6227+ return key;
1facf9fc 6228+}
6229+
4a4d8108 6230+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 6231+{
4a4d8108
AM
6232+ struct au_dykey **k, *found;
6233+ const void *h_op = key->dk_op.dy_hop;
6234+ int i;
1facf9fc 6235+
4a4d8108
AM
6236+ found = NULL;
6237+ k = br->br_dykey;
6238+ for (i = 0; i < AuBrDynOp; i++)
6239+ if (k[i]) {
6240+ if (k[i]->dk_op.dy_hop == h_op) {
6241+ found = k[i];
6242+ break;
6243+ }
6244+ } else
6245+ break;
6246+ if (!found) {
6247+ spin_lock(&br->br_dykey_lock);
6248+ for (; i < AuBrDynOp; i++)
6249+ if (k[i]) {
6250+ if (k[i]->dk_op.dy_hop == h_op) {
6251+ found = k[i];
6252+ break;
6253+ }
6254+ } else {
6255+ k[i] = key;
6256+ break;
6257+ }
6258+ spin_unlock(&br->br_dykey_lock);
6259+ BUG_ON(i == AuBrDynOp); /* expand the array */
6260+ }
6261+
6262+ return found;
1facf9fc 6263+}
6264+
4a4d8108
AM
6265+/* kref_get() if @key is already added */
6266+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
6267+{
6268+ struct au_dykey *tmp, *found;
6269+ struct list_head *head;
6270+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 6271+
4a4d8108
AM
6272+ found = NULL;
6273+ head = &spl->head;
6274+ spin_lock(&spl->spin);
6275+ list_for_each_entry(tmp, head, dk_list)
6276+ if (tmp->dk_op.dy_hop == h_op) {
6277+ kref_get(&tmp->dk_kref);
6278+ found = tmp;
6279+ break;
6280+ }
6281+ if (!found)
6282+ list_add_rcu(&key->dk_list, head);
6283+ spin_unlock(&spl->spin);
1facf9fc 6284+
4a4d8108
AM
6285+ if (!found)
6286+ DyPrSym(key);
6287+ return found;
6288+}
6289+
6290+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 6291+{
4a4d8108
AM
6292+ struct au_dykey *key;
6293+
6294+ key = container_of(rcu, struct au_dykey, dk_rcu);
6295+ DyPrSym(key);
6296+ kfree(key);
1facf9fc 6297+}
6298+
4a4d8108
AM
6299+static void dy_free(struct kref *kref)
6300+{
6301+ struct au_dykey *key;
6302+ struct au_splhead *spl;
1facf9fc 6303+
4a4d8108
AM
6304+ key = container_of(kref, struct au_dykey, dk_kref);
6305+ spl = dynop + key->dk_op.dy_type;
6306+ au_spl_del_rcu(&key->dk_list, spl);
6307+ call_rcu(&key->dk_rcu, dy_free_rcu);
6308+}
6309+
6310+void au_dy_put(struct au_dykey *key)
1facf9fc 6311+{
4a4d8108
AM
6312+ kref_put(&key->dk_kref, dy_free);
6313+}
1facf9fc 6314+
4a4d8108
AM
6315+/* ---------------------------------------------------------------------- */
6316+
6317+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
6318+
6319+#ifdef CONFIG_AUFS_DEBUG
6320+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 6321+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
6322+#else
6323+#define DyDbgDeclare(cnt) do {} while (0)
6324+#define DyDbgInc(cnt) do {} while (0)
6325+#endif
6326+
6327+#define DySet(func, dst, src, h_op, h_sb) do { \
6328+ DyDbgInc(cnt); \
6329+ if (h_op->func) { \
6330+ if (src.func) \
6331+ dst.func = src.func; \
6332+ else \
6333+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
6334+ } \
6335+} while (0)
6336+
6337+#define DySetForce(func, dst, src) do { \
6338+ AuDebugOn(!src.func); \
6339+ DyDbgInc(cnt); \
6340+ dst.func = src.func; \
6341+} while (0)
6342+
6343+#define DySetAop(func) \
6344+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
6345+#define DySetAopForce(func) \
6346+ DySetForce(func, dyaop->da_op, aufs_aop)
6347+
6348+static void dy_aop(struct au_dykey *key, const void *h_op,
6349+ struct super_block *h_sb __maybe_unused)
6350+{
6351+ struct au_dyaop *dyaop = (void *)key;
6352+ const struct address_space_operations *h_aop = h_op;
6353+ DyDbgDeclare(cnt);
6354+
6355+ AuDbg("%s\n", au_sbtype(h_sb));
6356+
6357+ DySetAop(writepage);
6358+ DySetAopForce(readpage); /* force */
6359+ DySetAop(sync_page);
6360+ DySetAop(writepages);
6361+ DySetAop(set_page_dirty);
6362+ DySetAop(readpages);
6363+ DySetAop(write_begin);
6364+ DySetAop(write_end);
6365+ DySetAop(bmap);
6366+ DySetAop(invalidatepage);
6367+ DySetAop(releasepage);
6368+ /* these two will be changed according to an aufs mount option */
6369+ DySetAop(direct_IO);
6370+ DySetAop(get_xip_mem);
6371+ DySetAop(migratepage);
6372+ DySetAop(launder_page);
6373+ DySetAop(is_partially_uptodate);
6374+ DySetAop(error_remove_page);
6375+
6376+ DyDbgSize(cnt, *h_aop);
6377+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
6378+}
6379+
6380+#define DySetVmop(func) \
6381+ DySet(func, dyvmop->dv_op, aufs_vm_ops, h_vmop, h_sb)
6382+#define DySetVmopForce(func) \
6383+ DySetForce(func, dyvmop->dv_op, aufs_vm_ops)
6384+
6385+static void dy_vmop(struct au_dykey *key, const void *h_op,
6386+ struct super_block *h_sb __maybe_unused)
6387+{
6388+ struct au_dyvmop *dyvmop = (void *)key;
6389+ const struct vm_operations_struct *h_vmop = h_op;
6390+ DyDbgDeclare(cnt);
6391+
6392+ AuDbg("%s\n", au_sbtype(h_sb));
6393+
6394+ DySetVmop(open);
6395+ DySetVmop(close);
6396+ DySetVmop(fault);
6397+ DySetVmop(page_mkwrite);
6398+ DySetVmop(access);
6399+#ifdef CONFIG_NUMA
6400+ DySetVmop(set_policy);
6401+ DySetVmop(get_policy);
6402+ DySetVmop(migrate);
6403+#endif
6404+
6405+ DyDbgSize(cnt, *h_vmop);
6406+}
6407+
6408+/* ---------------------------------------------------------------------- */
6409+
6410+static void dy_bug(struct kref *kref)
6411+{
6412+ BUG();
6413+}
6414+
6415+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
6416+{
6417+ struct au_dykey *key, *old;
6418+ struct au_splhead *spl;
b752ccd1 6419+ struct op {
4a4d8108 6420+ unsigned int sz;
b752ccd1
AM
6421+ void (*set)(struct au_dykey *key, const void *h_op,
6422+ struct super_block *h_sb __maybe_unused);
6423+ };
6424+ static const struct op a[] = {
4a4d8108
AM
6425+ [AuDy_AOP] = {
6426+ .sz = sizeof(struct au_dyaop),
b752ccd1 6427+ .set = dy_aop
4a4d8108
AM
6428+ },
6429+ [AuDy_VMOP] = {
6430+ .sz = sizeof(struct au_dyvmop),
b752ccd1 6431+ .set = dy_vmop
4a4d8108 6432+ }
b752ccd1
AM
6433+ };
6434+ const struct op *p;
4a4d8108
AM
6435+
6436+ spl = dynop + op->dy_type;
6437+ key = dy_gfind_get(spl, op->dy_hop);
6438+ if (key)
6439+ goto out_add; /* success */
6440+
6441+ p = a + op->dy_type;
6442+ key = kzalloc(p->sz, GFP_NOFS);
6443+ if (unlikely(!key)) {
6444+ key = ERR_PTR(-ENOMEM);
6445+ goto out;
6446+ }
6447+
6448+ key->dk_op.dy_hop = op->dy_hop;
6449+ kref_init(&key->dk_kref);
b752ccd1 6450+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
6451+ old = dy_gadd(spl, key);
6452+ if (old) {
6453+ kfree(key);
6454+ key = old;
6455+ }
6456+
6457+out_add:
6458+ old = dy_bradd(br, key);
6459+ if (old)
6460+ /* its ref-count should never be zero here */
6461+ kref_put(&key->dk_kref, dy_bug);
6462+out:
6463+ return key;
6464+}
6465+
6466+/* ---------------------------------------------------------------------- */
6467+/*
6468+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
6469+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
6470+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
6471+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
6472+ * See the aufs manual in detail.
6473+ *
6474+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
6475+ * performance of fadvise() and madvise() may be affected.
6476+ */
6477+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
6478+{
6479+ if (!do_dx) {
6480+ dyaop->da_op.direct_IO = NULL;
6481+ dyaop->da_op.get_xip_mem = NULL;
6482+ } else {
6483+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
6484+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
6485+ if (!dyaop->da_get_xip_mem)
6486+ dyaop->da_op.get_xip_mem = NULL;
6487+ }
6488+}
6489+
6490+static struct au_dyaop *dy_aget(struct au_branch *br,
6491+ const struct address_space_operations *h_aop,
6492+ int do_dx)
6493+{
6494+ struct au_dyaop *dyaop;
6495+ struct au_dynop op;
6496+
6497+ op.dy_type = AuDy_AOP;
6498+ op.dy_haop = h_aop;
6499+ dyaop = (void *)dy_get(&op, br);
6500+ if (IS_ERR(dyaop))
6501+ goto out;
6502+ dy_adx(dyaop, do_dx);
6503+
6504+out:
6505+ return dyaop;
6506+}
6507+
6508+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
6509+ struct inode *h_inode)
6510+{
6511+ int err, do_dx;
6512+ struct super_block *sb;
6513+ struct au_branch *br;
6514+ struct au_dyaop *dyaop;
6515+
6516+ AuDebugOn(!S_ISREG(h_inode->i_mode));
6517+ IiMustWriteLock(inode);
6518+
6519+ sb = inode->i_sb;
6520+ br = au_sbr(sb, bindex);
6521+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
6522+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
6523+ err = PTR_ERR(dyaop);
6524+ if (IS_ERR(dyaop))
6525+ /* unnecessary to call dy_fput() */
6526+ goto out;
6527+
6528+ err = 0;
6529+ inode->i_mapping->a_ops = &dyaop->da_op;
6530+
6531+out:
6532+ return err;
6533+}
6534+
b752ccd1
AM
6535+/*
6536+ * Is it safe to replace a_ops during the inode/file is in operation?
6537+ * Yes, I hope so.
6538+ */
6539+int au_dy_irefresh(struct inode *inode)
6540+{
6541+ int err;
6542+ aufs_bindex_t bstart;
6543+ struct inode *h_inode;
6544+
6545+ err = 0;
6546+ if (S_ISREG(inode->i_mode)) {
6547+ bstart = au_ibstart(inode);
6548+ h_inode = au_h_iptr(inode, bstart);
6549+ err = au_dy_iaop(inode, bstart, h_inode);
6550+ }
6551+ return err;
6552+}
6553+
4a4d8108
AM
6554+void au_dy_arefresh(int do_dx)
6555+{
6556+ struct au_splhead *spl;
6557+ struct list_head *head;
6558+ struct au_dykey *key;
6559+
6560+ spl = dynop + AuDy_AOP;
6561+ head = &spl->head;
6562+ spin_lock(&spl->spin);
6563+ list_for_each_entry(key, head, dk_list)
6564+ dy_adx((void *)key, do_dx);
6565+ spin_unlock(&spl->spin);
6566+}
6567+
6568+const struct vm_operations_struct *
6569+au_dy_vmop(struct file *file, struct au_branch *br,
6570+ const struct vm_operations_struct *h_vmop)
6571+{
6572+ struct au_dyvmop *dyvmop;
6573+ struct au_dynop op;
6574+
6575+ op.dy_type = AuDy_VMOP;
6576+ op.dy_hvmop = h_vmop;
6577+ dyvmop = (void *)dy_get(&op, br);
6578+ if (IS_ERR(dyvmop))
6579+ return (void *)dyvmop;
6580+ return &dyvmop->dv_op;
6581+}
6582+
6583+/* ---------------------------------------------------------------------- */
6584+
6585+void __init au_dy_init(void)
6586+{
6587+ int i;
6588+
6589+ /* make sure that 'struct au_dykey *' can be any type */
6590+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
6591+ BUILD_BUG_ON(offsetof(struct au_dyvmop, dv_key));
6592+
6593+ for (i = 0; i < AuDyLast; i++)
6594+ au_spl_init(dynop + i);
6595+}
6596+
6597+void au_dy_fin(void)
6598+{
6599+ int i;
6600+
6601+ for (i = 0; i < AuDyLast; i++)
6602+ WARN_ON(!list_empty(&dynop[i].head));
6603+}
e49829fe 6604--- /dev/null
0c5527e5 6605+++ linux-2.6/fs/aufs/dynop.h 2010-10-25 14:20:44.000000000 +0200
b752ccd1 6606@@ -0,0 +1,89 @@
4a4d8108
AM
6607+/*
6608+ * Copyright (C) 2010 Junjiro R. Okajima
6609+ *
6610+ * This program, aufs is free software; you can redistribute it and/or modify
6611+ * it under the terms of the GNU General Public License as published by
6612+ * the Free Software Foundation; either version 2 of the License, or
6613+ * (at your option) any later version.
6614+ *
6615+ * This program is distributed in the hope that it will be useful,
6616+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6617+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6618+ * GNU General Public License for more details.
6619+ *
6620+ * You should have received a copy of the GNU General Public License
6621+ * along with this program; if not, write to the Free Software
6622+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6623+ */
6624+
6625+/*
6626+ * dynamically customizable operations (for regular files only)
6627+ */
6628+
6629+#ifndef __AUFS_DYNOP_H__
6630+#define __AUFS_DYNOP_H__
6631+
6632+#ifdef __KERNEL__
6633+
6634+#include <linux/fs.h>
6635+#include <linux/mm.h>
6636+#include <linux/rcupdate.h>
6637+#include <linux/aufs_type.h>
6638+#include "inode.h"
6639+
6640+enum {AuDy_AOP, AuDy_VMOP, AuDyLast};
6641+
6642+struct au_dynop {
6643+ int dy_type;
6644+ union {
6645+ const void *dy_hop;
6646+ const struct address_space_operations *dy_haop;
6647+ const struct vm_operations_struct *dy_hvmop;
6648+ };
6649+};
6650+
6651+struct au_dykey {
6652+ union {
6653+ struct list_head dk_list;
6654+ struct rcu_head dk_rcu;
6655+ };
6656+ struct au_dynop dk_op;
6657+
6658+ /*
6659+ * during I am in the branch local array, kref is gotten. when the
6660+ * branch is removed, kref is put.
6661+ */
6662+ struct kref dk_kref;
6663+};
6664+
6665+/* stop unioning since their sizes are very different from each other */
6666+struct au_dyaop {
6667+ struct au_dykey da_key;
6668+ struct address_space_operations da_op; /* not const */
6669+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
6670+ void **, unsigned long *);
6671+};
6672+
6673+struct au_dyvmop {
6674+ struct au_dykey dv_key;
6675+ struct vm_operations_struct dv_op; /* not const */
6676+};
6677+
6678+/* ---------------------------------------------------------------------- */
6679+
6680+/* dynop.c */
6681+struct au_branch;
6682+void au_dy_put(struct au_dykey *key);
6683+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
6684+ struct inode *h_inode);
b752ccd1 6685+int au_dy_irefresh(struct inode *inode);
4a4d8108
AM
6686+void au_dy_arefresh(int do_dio);
6687+const struct vm_operations_struct *
6688+au_dy_vmop(struct file *file, struct au_branch *br,
6689+ const struct vm_operations_struct *h_vmop);
6690+
6691+void __init au_dy_init(void);
6692+void au_dy_fin(void);
6693+
4a4d8108
AM
6694+#endif /* __KERNEL__ */
6695+#endif /* __AUFS_DYNOP_H__ */
e49829fe 6696--- /dev/null
0c5527e5
AM
6697+++ linux-2.6/fs/aufs/export.c 2010-10-26 21:38:27.000000000 +0200
6698@@ -0,0 +1,790 @@
4a4d8108
AM
6699+/*
6700+ * Copyright (C) 2005-2010 Junjiro R. Okajima
6701+ *
6702+ * This program, aufs is free software; you can redistribute it and/or modify
6703+ * it under the terms of the GNU General Public License as published by
6704+ * the Free Software Foundation; either version 2 of the License, or
6705+ * (at your option) any later version.
6706+ *
6707+ * This program is distributed in the hope that it will be useful,
6708+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6709+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6710+ * GNU General Public License for more details.
6711+ *
6712+ * You should have received a copy of the GNU General Public License
6713+ * along with this program; if not, write to the Free Software
6714+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
6715+ */
6716+
6717+/*
6718+ * export via nfs
6719+ */
6720+
6721+#include <linux/exportfs.h>
6722+#include <linux/file.h>
6723+#include <linux/mnt_namespace.h>
6724+#include <linux/namei.h>
6725+#include <linux/nsproxy.h>
6726+#include <linux/random.h>
6727+#include <linux/writeback.h>
6728+#include "aufs.h"
6729+
6730+union conv {
6731+#ifdef CONFIG_AUFS_INO_T_64
6732+ __u32 a[2];
6733+#else
6734+ __u32 a[1];
6735+#endif
6736+ ino_t ino;
6737+};
6738+
6739+static ino_t decode_ino(__u32 *a)
6740+{
6741+ union conv u;
6742+
6743+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
6744+ u.a[0] = a[0];
6745+#ifdef CONFIG_AUFS_INO_T_64
6746+ u.a[1] = a[1];
6747+#endif
6748+ return u.ino;
6749+}
6750+
6751+static void encode_ino(__u32 *a, ino_t ino)
6752+{
6753+ union conv u;
6754+
6755+ u.ino = ino;
6756+ a[0] = u.a[0];
6757+#ifdef CONFIG_AUFS_INO_T_64
6758+ a[1] = u.a[1];
6759+#endif
6760+}
6761+
6762+/* NFS file handle */
6763+enum {
6764+ Fh_br_id,
6765+ Fh_sigen,
6766+#ifdef CONFIG_AUFS_INO_T_64
6767+ /* support 64bit inode number */
6768+ Fh_ino1,
6769+ Fh_ino2,
6770+ Fh_dir_ino1,
6771+ Fh_dir_ino2,
6772+#else
6773+ Fh_ino1,
6774+ Fh_dir_ino1,
6775+#endif
6776+ Fh_igen,
6777+ Fh_h_type,
6778+ Fh_tail,
6779+
6780+ Fh_ino = Fh_ino1,
6781+ Fh_dir_ino = Fh_dir_ino1
6782+};
6783+
6784+static int au_test_anon(struct dentry *dentry)
6785+{
6786+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
6787+}
6788+
6789+/* ---------------------------------------------------------------------- */
6790+/* inode generation external table */
6791+
b752ccd1 6792+void au_xigen_inc(struct inode *inode)
4a4d8108 6793+{
4a4d8108
AM
6794+ loff_t pos;
6795+ ssize_t sz;
6796+ __u32 igen;
6797+ struct super_block *sb;
6798+ struct au_sbinfo *sbinfo;
6799+
4a4d8108 6800+ sb = inode->i_sb;
b752ccd1 6801+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 6802+
b752ccd1 6803+ sbinfo = au_sbi(sb);
1facf9fc 6804+ pos = inode->i_ino;
6805+ pos *= sizeof(igen);
6806+ igen = inode->i_generation + 1;
1facf9fc 6807+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
6808+ sizeof(igen), &pos);
6809+ if (sz == sizeof(igen))
b752ccd1 6810+ return; /* success */
1facf9fc 6811+
b752ccd1 6812+ if (unlikely(sz >= 0))
1facf9fc 6813+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 6814+}
6815+
6816+int au_xigen_new(struct inode *inode)
6817+{
6818+ int err;
6819+ loff_t pos;
6820+ ssize_t sz;
6821+ struct super_block *sb;
6822+ struct au_sbinfo *sbinfo;
6823+ struct file *file;
6824+
6825+ err = 0;
6826+ /* todo: dirty, at mount time */
6827+ if (inode->i_ino == AUFS_ROOT_INO)
6828+ goto out;
6829+ sb = inode->i_sb;
dece6358 6830+ SiMustAnyLock(sb);
1facf9fc 6831+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
6832+ goto out;
6833+
6834+ err = -EFBIG;
6835+ pos = inode->i_ino;
6836+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
6837+ AuIOErr1("too large i%lld\n", pos);
6838+ goto out;
6839+ }
6840+ pos *= sizeof(inode->i_generation);
6841+
6842+ err = 0;
6843+ sbinfo = au_sbi(sb);
6844+ file = sbinfo->si_xigen;
6845+ BUG_ON(!file);
6846+
6847+ if (i_size_read(file->f_dentry->d_inode)
6848+ < pos + sizeof(inode->i_generation)) {
6849+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
6850+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
6851+ sizeof(inode->i_generation), &pos);
6852+ } else
6853+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
6854+ sizeof(inode->i_generation), &pos);
6855+ if (sz == sizeof(inode->i_generation))
6856+ goto out; /* success */
6857+
6858+ err = sz;
6859+ if (unlikely(sz >= 0)) {
6860+ err = -EIO;
6861+ AuIOErr("xigen error (%zd)\n", sz);
6862+ }
6863+
4f0767ce 6864+out:
1facf9fc 6865+ return err;
6866+}
6867+
6868+int au_xigen_set(struct super_block *sb, struct file *base)
6869+{
6870+ int err;
6871+ struct au_sbinfo *sbinfo;
6872+ struct file *file;
6873+
dece6358
AM
6874+ SiMustWriteLock(sb);
6875+
1facf9fc 6876+ sbinfo = au_sbi(sb);
6877+ file = au_xino_create2(base, sbinfo->si_xigen);
6878+ err = PTR_ERR(file);
6879+ if (IS_ERR(file))
6880+ goto out;
6881+ err = 0;
6882+ if (sbinfo->si_xigen)
6883+ fput(sbinfo->si_xigen);
6884+ sbinfo->si_xigen = file;
6885+
4f0767ce 6886+out:
1facf9fc 6887+ return err;
6888+}
6889+
6890+void au_xigen_clr(struct super_block *sb)
6891+{
6892+ struct au_sbinfo *sbinfo;
6893+
dece6358
AM
6894+ SiMustWriteLock(sb);
6895+
1facf9fc 6896+ sbinfo = au_sbi(sb);
6897+ if (sbinfo->si_xigen) {
6898+ fput(sbinfo->si_xigen);
6899+ sbinfo->si_xigen = NULL;
6900+ }
6901+}
6902+
6903+/* ---------------------------------------------------------------------- */
6904+
6905+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
6906+ ino_t dir_ino)
6907+{
6908+ struct dentry *dentry, *d;
6909+ struct inode *inode;
6910+ unsigned int sigen;
6911+
6912+ dentry = NULL;
6913+ inode = ilookup(sb, ino);
6914+ if (!inode)
6915+ goto out;
6916+
6917+ dentry = ERR_PTR(-ESTALE);
6918+ sigen = au_sigen(sb);
6919+ if (unlikely(is_bad_inode(inode)
6920+ || IS_DEADDIR(inode)
6921+ || sigen != au_iigen(inode)))
6922+ goto out_iput;
6923+
6924+ dentry = NULL;
6925+ if (!dir_ino || S_ISDIR(inode->i_mode))
6926+ dentry = d_find_alias(inode);
6927+ else {
6928+ spin_lock(&dcache_lock);
6929+ list_for_each_entry(d, &inode->i_dentry, d_alias)
6930+ if (!au_test_anon(d)
6931+ && d->d_parent->d_inode->i_ino == dir_ino) {
6932+ dentry = dget_locked(d);
6933+ break;
6934+ }
6935+ spin_unlock(&dcache_lock);
6936+ }
6937+ if (unlikely(dentry && sigen != au_digen(dentry))) {
6938+ dput(dentry);
6939+ dentry = ERR_PTR(-ESTALE);
6940+ }
6941+
4f0767ce 6942+out_iput:
1facf9fc 6943+ iput(inode);
4f0767ce 6944+out:
1facf9fc 6945+ return dentry;
6946+}
6947+
6948+/* ---------------------------------------------------------------------- */
6949+
6950+/* todo: dirty? */
6951+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
6952+
6953+struct au_compare_mnt_args {
6954+ /* input */
6955+ struct super_block *sb;
6956+
6957+ /* output */
6958+ struct vfsmount *mnt;
6959+};
6960+
6961+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
6962+{
6963+ struct au_compare_mnt_args *a = arg;
6964+
6965+ if (mnt->mnt_sb != a->sb)
6966+ return 0;
6967+ a->mnt = mntget(mnt);
6968+ return 1;
6969+}
6970+
1facf9fc 6971+static struct vfsmount *au_mnt_get(struct super_block *sb)
6972+{
4a4d8108
AM
6973+ int err;
6974+ struct au_compare_mnt_args args = {
6975+ .sb = sb
6976+ };
1facf9fc 6977+ struct mnt_namespace *ns;
1facf9fc 6978+
0c5527e5 6979+ br_read_lock(vfsmount_lock);
1facf9fc 6980+ /* no get/put ?? */
6981+ AuDebugOn(!current->nsproxy);
6982+ ns = current->nsproxy->mnt_ns;
6983+ AuDebugOn(!ns);
4a4d8108 6984+ err = iterate_mounts(au_compare_mnt, &args, ns->root);
0c5527e5 6985+ br_read_unlock(vfsmount_lock);
4a4d8108
AM
6986+ AuDebugOn(!err);
6987+ AuDebugOn(!args.mnt);
6988+ return args.mnt;
1facf9fc 6989+}
6990+
6991+struct au_nfsd_si_lock {
4a4d8108
AM
6992+ unsigned int sigen;
6993+ aufs_bindex_t br_id;
1facf9fc 6994+ unsigned char force_lock;
6995+};
6996+
6997+static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
6998+ struct au_nfsd_si_lock *nsi_lock)
6999+{
7000+ aufs_bindex_t bindex;
7001+
7002+ si_read_lock(sb, AuLock_FLUSH);
7003+
7004+ /* branch id may be wrapped around */
7005+ bindex = au_br_index(sb, nsi_lock->br_id);
7006+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
7007+ goto out; /* success */
7008+
7009+ if (!nsi_lock->force_lock)
7010+ si_read_unlock(sb);
7011+ bindex = -1;
7012+
4f0767ce 7013+out:
1facf9fc 7014+ return bindex;
7015+}
7016+
7017+struct find_name_by_ino {
7018+ int called, found;
7019+ ino_t ino;
7020+ char *name;
7021+ int namelen;
7022+};
7023+
7024+static int
7025+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
7026+ u64 ino, unsigned int d_type)
7027+{
7028+ struct find_name_by_ino *a = arg;
7029+
7030+ a->called++;
7031+ if (a->ino != ino)
7032+ return 0;
7033+
7034+ memcpy(a->name, name, namelen);
7035+ a->namelen = namelen;
7036+ a->found = 1;
7037+ return 1;
7038+}
7039+
7040+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
7041+ struct au_nfsd_si_lock *nsi_lock)
7042+{
7043+ struct dentry *dentry, *parent;
7044+ struct file *file;
7045+ struct inode *dir;
7046+ struct find_name_by_ino arg;
7047+ int err;
7048+
7049+ parent = path->dentry;
7050+ if (nsi_lock)
7051+ si_read_unlock(parent->d_sb);
4a4d8108 7052+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 7053+ dentry = (void *)file;
7054+ if (IS_ERR(file))
7055+ goto out;
7056+
7057+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 7058+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 7059+ if (unlikely(!arg.name))
7060+ goto out_file;
7061+ arg.ino = ino;
7062+ arg.found = 0;
7063+ do {
7064+ arg.called = 0;
7065+ /* smp_mb(); */
7066+ err = vfsub_readdir(file, find_name_by_ino, &arg);
7067+ } while (!err && !arg.found && arg.called);
7068+ dentry = ERR_PTR(err);
7069+ if (unlikely(err))
7070+ goto out_name;
7071+ dentry = ERR_PTR(-ENOENT);
7072+ if (!arg.found)
7073+ goto out_name;
7074+
7075+ /* do not call au_lkup_one() */
7076+ dir = parent->d_inode;
7077+ mutex_lock(&dir->i_mutex);
7078+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
7079+ mutex_unlock(&dir->i_mutex);
7080+ AuTraceErrPtr(dentry);
7081+ if (IS_ERR(dentry))
7082+ goto out_name;
7083+ AuDebugOn(au_test_anon(dentry));
7084+ if (unlikely(!dentry->d_inode)) {
7085+ dput(dentry);
7086+ dentry = ERR_PTR(-ENOENT);
7087+ }
7088+
4f0767ce 7089+out_name:
1facf9fc 7090+ __putname(arg.name);
4f0767ce 7091+out_file:
1facf9fc 7092+ fput(file);
4f0767ce 7093+out:
1facf9fc 7094+ if (unlikely(nsi_lock
7095+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
7096+ if (!IS_ERR(dentry)) {
7097+ dput(dentry);
7098+ dentry = ERR_PTR(-ESTALE);
7099+ }
7100+ AuTraceErrPtr(dentry);
7101+ return dentry;
7102+}
7103+
7104+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
7105+ ino_t dir_ino,
7106+ struct au_nfsd_si_lock *nsi_lock)
7107+{
7108+ struct dentry *dentry;
7109+ struct path path;
7110+
7111+ if (dir_ino != AUFS_ROOT_INO) {
7112+ path.dentry = decode_by_ino(sb, dir_ino, 0);
7113+ dentry = path.dentry;
7114+ if (!path.dentry || IS_ERR(path.dentry))
7115+ goto out;
7116+ AuDebugOn(au_test_anon(path.dentry));
7117+ } else
7118+ path.dentry = dget(sb->s_root);
7119+
7120+ path.mnt = au_mnt_get(sb);
7121+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
7122+ path_put(&path);
7123+
4f0767ce 7124+out:
1facf9fc 7125+ AuTraceErrPtr(dentry);
7126+ return dentry;
7127+}
7128+
7129+/* ---------------------------------------------------------------------- */
7130+
7131+static int h_acceptable(void *expv, struct dentry *dentry)
7132+{
7133+ return 1;
7134+}
7135+
7136+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
7137+ char *buf, int len, struct super_block *sb)
7138+{
7139+ char *p;
7140+ int n;
7141+ struct path path;
7142+
7143+ p = d_path(h_rootpath, buf, len);
7144+ if (IS_ERR(p))
7145+ goto out;
7146+ n = strlen(p);
7147+
7148+ path.mnt = h_rootpath->mnt;
7149+ path.dentry = h_parent;
7150+ p = d_path(&path, buf, len);
7151+ if (IS_ERR(p))
7152+ goto out;
7153+ if (n != 1)
7154+ p += n;
7155+
7156+ path.mnt = au_mnt_get(sb);
7157+ path.dentry = sb->s_root;
7158+ p = d_path(&path, buf, len - strlen(p));
7159+ mntput(path.mnt);
7160+ if (IS_ERR(p))
7161+ goto out;
7162+ if (n != 1)
7163+ p[strlen(p)] = '/';
7164+
4f0767ce 7165+out:
1facf9fc 7166+ AuTraceErrPtr(p);
7167+ return p;
7168+}
7169+
7170+static
7171+struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
7172+ ino_t ino, __u32 *fh, int fh_len,
7173+ struct au_nfsd_si_lock *nsi_lock)
7174+{
7175+ struct dentry *dentry, *h_parent, *root;
7176+ struct super_block *h_sb;
7177+ char *pathname, *p;
7178+ struct vfsmount *h_mnt;
7179+ struct au_branch *br;
7180+ int err;
7181+ struct path path;
7182+
7183+ br = au_sbr(sb, bindex);
7184+ /* au_br_get(br); */
7185+ h_mnt = br->br_mnt;
7186+ h_sb = h_mnt->mnt_sb;
7187+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
7188+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
7189+ fh_len - Fh_tail, fh[Fh_h_type],
7190+ h_acceptable, /*context*/NULL);
7191+ dentry = h_parent;
7192+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
7193+ AuWarn1("%s decode_fh failed, %ld\n",
7194+ au_sbtype(h_sb), PTR_ERR(h_parent));
7195+ goto out;
7196+ }
7197+ dentry = NULL;
7198+ if (unlikely(au_test_anon(h_parent))) {
7199+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
7200+ au_sbtype(h_sb));
7201+ goto out_h_parent;
7202+ }
7203+
7204+ dentry = ERR_PTR(-ENOMEM);
7205+ pathname = (void *)__get_free_page(GFP_NOFS);
7206+ if (unlikely(!pathname))
7207+ goto out_h_parent;
7208+
7209+ root = sb->s_root;
7210+ path.mnt = h_mnt;
7211+ di_read_lock_parent(root, !AuLock_IR);
7212+ path.dentry = au_h_dptr(root, bindex);
7213+ di_read_unlock(root, !AuLock_IR);
7214+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
7215+ dentry = (void *)p;
7216+ if (IS_ERR(p))
7217+ goto out_pathname;
7218+
7219+ si_read_unlock(sb);
7220+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
7221+ dentry = ERR_PTR(err);
7222+ if (unlikely(err))
7223+ goto out_relock;
7224+
7225+ dentry = ERR_PTR(-ENOENT);
7226+ AuDebugOn(au_test_anon(path.dentry));
7227+ if (unlikely(!path.dentry->d_inode))
7228+ goto out_path;
7229+
7230+ if (ino != path.dentry->d_inode->i_ino)
7231+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
7232+ else
7233+ dentry = dget(path.dentry);
7234+
4f0767ce 7235+out_path:
1facf9fc 7236+ path_put(&path);
4f0767ce 7237+out_relock:
1facf9fc 7238+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
7239+ if (!IS_ERR(dentry)) {
7240+ dput(dentry);
7241+ dentry = ERR_PTR(-ESTALE);
7242+ }
4f0767ce 7243+out_pathname:
1facf9fc 7244+ free_page((unsigned long)pathname);
4f0767ce 7245+out_h_parent:
1facf9fc 7246+ dput(h_parent);
4f0767ce 7247+out:
1facf9fc 7248+ /* au_br_put(br); */
7249+ AuTraceErrPtr(dentry);
7250+ return dentry;
7251+}
7252+
7253+/* ---------------------------------------------------------------------- */
7254+
7255+static struct dentry *
7256+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
7257+ int fh_type)
7258+{
7259+ struct dentry *dentry;
7260+ __u32 *fh = fid->raw;
7261+ ino_t ino, dir_ino;
7262+ aufs_bindex_t bindex;
7263+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 7264+ .force_lock = 0
7265+ };
7266+
1facf9fc 7267+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
7268+ /* it should never happen, but the file handle is unreliable */
7269+ if (unlikely(fh_len < Fh_tail))
7270+ goto out;
7271+ nsi_lock.sigen = fh[Fh_sigen];
7272+ nsi_lock.br_id = fh[Fh_br_id];
7273+
1facf9fc 7274+ /* branch id may be wrapped around */
7275+ bindex = si_nfsd_read_lock(sb, &nsi_lock);
7276+ if (unlikely(bindex < 0))
7277+ goto out;
7278+ nsi_lock.force_lock = 1;
7279+
7280+ /* is this inode still cached? */
7281+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
7282+ /* it should never happen */
7283+ if (unlikely(ino == AUFS_ROOT_INO))
7284+ goto out;
7285+
1facf9fc 7286+ dir_ino = decode_ino(fh + Fh_dir_ino);
7287+ dentry = decode_by_ino(sb, ino, dir_ino);
7288+ if (IS_ERR(dentry))
7289+ goto out_unlock;
7290+ if (dentry)
7291+ goto accept;
7292+
7293+ /* is the parent dir cached? */
7294+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
7295+ if (IS_ERR(dentry))
7296+ goto out_unlock;
7297+ if (dentry)
7298+ goto accept;
7299+
7300+ /* lookup path */
7301+ dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
7302+ if (IS_ERR(dentry))
7303+ goto out_unlock;
7304+ if (unlikely(!dentry))
7305+ /* todo?: make it ESTALE */
7306+ goto out_unlock;
7307+
4f0767ce 7308+accept:
1facf9fc 7309+ if (dentry->d_inode->i_generation == fh[Fh_igen])
7310+ goto out_unlock; /* success */
7311+
7312+ dput(dentry);
7313+ dentry = ERR_PTR(-ESTALE);
4f0767ce 7314+out_unlock:
1facf9fc 7315+ si_read_unlock(sb);
4f0767ce 7316+out:
1facf9fc 7317+ AuTraceErrPtr(dentry);
7318+ return dentry;
7319+}
7320+
7321+#if 0 /* reserved for future use */
7322+/* support subtreecheck option */
7323+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
7324+ int fh_len, int fh_type)
7325+{
7326+ struct dentry *parent;
7327+ __u32 *fh = fid->raw;
7328+ ino_t dir_ino;
7329+
7330+ dir_ino = decode_ino(fh + Fh_dir_ino);
7331+ parent = decode_by_ino(sb, dir_ino, 0);
7332+ if (IS_ERR(parent))
7333+ goto out;
7334+ if (!parent)
7335+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
7336+ dir_ino, fh, fh_len);
7337+
4f0767ce 7338+out:
1facf9fc 7339+ AuTraceErrPtr(parent);
7340+ return parent;
7341+}
7342+#endif
7343+
7344+/* ---------------------------------------------------------------------- */
7345+
7346+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
7347+ int connectable)
7348+{
7349+ int err;
7350+ aufs_bindex_t bindex, bend;
7351+ struct super_block *sb, *h_sb;
7352+ struct inode *inode;
7353+ struct dentry *parent, *h_parent;
7354+ struct au_branch *br;
7355+
7356+ AuDebugOn(au_test_anon(dentry));
7357+
7358+ parent = NULL;
7359+ err = -ENOSPC;
7360+ if (unlikely(*max_len <= Fh_tail)) {
7361+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
7362+ goto out;
7363+ }
7364+
7365+ err = FILEID_ROOT;
7366+ if (IS_ROOT(dentry)) {
7367+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
7368+ goto out;
7369+ }
7370+
7371+ err = -EIO;
7372+ h_parent = NULL;
7373+ sb = dentry->d_sb;
7374+ aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
7375+ parent = dget_parent(dentry);
7376+ di_read_lock_parent(parent, !AuLock_IR);
7377+ inode = dentry->d_inode;
7378+ AuDebugOn(!inode);
7379+#ifdef CONFIG_AUFS_DEBUG
7380+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7381+ AuWarn1("NFS-exporting requires xino\n");
7382+#endif
7383+
7384+ bend = au_dbtaildir(parent);
7385+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
7386+ h_parent = au_h_dptr(parent, bindex);
7387+ if (h_parent) {
7388+ dget(h_parent);
7389+ break;
7390+ }
7391+ }
7392+ if (unlikely(!h_parent))
7393+ goto out_unlock;
7394+
7395+ err = -EPERM;
7396+ br = au_sbr(sb, bindex);
7397+ h_sb = br->br_mnt->mnt_sb;
7398+ if (unlikely(!h_sb->s_export_op)) {
7399+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
7400+ goto out_dput;
7401+ }
7402+
7403+ fh[Fh_br_id] = br->br_id;
7404+ fh[Fh_sigen] = au_sigen(sb);
7405+ encode_ino(fh + Fh_ino, inode->i_ino);
7406+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
7407+ fh[Fh_igen] = inode->i_generation;
7408+
7409+ *max_len -= Fh_tail;
7410+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
7411+ max_len,
7412+ /*connectable or subtreecheck*/0);
7413+ err = fh[Fh_h_type];
7414+ *max_len += Fh_tail;
7415+ /* todo: macros? */
7416+ if (err != 255)
7417+ err = 99;
7418+ else
7419+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
7420+
4f0767ce 7421+out_dput:
1facf9fc 7422+ dput(h_parent);
4f0767ce 7423+out_unlock:
1facf9fc 7424+ di_read_unlock(parent, !AuLock_IR);
7425+ dput(parent);
7426+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 7427+out:
1facf9fc 7428+ if (unlikely(err < 0))
7429+ err = 255;
7430+ return err;
7431+}
7432+
7433+/* ---------------------------------------------------------------------- */
7434+
4a4d8108
AM
7435+static int aufs_commit_metadata(struct inode *inode)
7436+{
7437+ int err;
7438+ aufs_bindex_t bindex;
7439+ struct super_block *sb;
7440+ struct inode *h_inode;
7441+ int (*f)(struct inode *inode);
7442+
7443+ sb = inode->i_sb;
e49829fe 7444+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
7445+ ii_write_lock_child(inode);
7446+ bindex = au_ibstart(inode);
7447+ AuDebugOn(bindex < 0);
7448+ h_inode = au_h_iptr(inode, bindex);
7449+
7450+ f = h_inode->i_sb->s_export_op->commit_metadata;
7451+ if (f)
7452+ err = f(h_inode);
7453+ else {
7454+ struct writeback_control wbc = {
7455+ .sync_mode = WB_SYNC_ALL,
7456+ .nr_to_write = 0 /* metadata only */
7457+ };
7458+
7459+ err = sync_inode(h_inode, &wbc);
7460+ }
7461+
7462+ au_cpup_attr_timesizes(inode);
7463+ ii_write_unlock(inode);
7464+ si_read_unlock(sb);
7465+ return err;
7466+}
7467+
7468+/* ---------------------------------------------------------------------- */
7469+
1facf9fc 7470+static struct export_operations aufs_export_op = {
4a4d8108 7471+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 7472+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
7473+ .encode_fh = aufs_encode_fh,
7474+ .commit_metadata = aufs_commit_metadata
1facf9fc 7475+};
7476+
7477+void au_export_init(struct super_block *sb)
7478+{
7479+ struct au_sbinfo *sbinfo;
7480+ __u32 u;
7481+
7482+ sb->s_export_op = &aufs_export_op;
7483+ sbinfo = au_sbi(sb);
7484+ sbinfo->si_xigen = NULL;
7485+ get_random_bytes(&u, sizeof(u));
7486+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
7487+ atomic_set(&sbinfo->si_xigen_next, u);
7488+}
e49829fe 7489--- /dev/null
0c5527e5 7490+++ linux-2.6/fs/aufs/file.c 2010-10-25 14:20:44.000000000 +0200
4a4d8108 7491@@ -0,0 +1,652 @@
1facf9fc 7492+/*
4a4d8108 7493+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 7494+ *
7495+ * This program, aufs is free software; you can redistribute it and/or modify
7496+ * it under the terms of the GNU General Public License as published by
7497+ * the Free Software Foundation; either version 2 of the License, or
7498+ * (at your option) any later version.
dece6358
AM
7499+ *
7500+ * This program is distributed in the hope that it will be useful,
7501+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7502+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7503+ * GNU General Public License for more details.
7504+ *
7505+ * You should have received a copy of the GNU General Public License
7506+ * along with this program; if not, write to the Free Software
7507+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7508+ */
7509+
7510+/*
4a4d8108 7511+ * handling file/dir, and address_space operation
1facf9fc 7512+ */
7513+
dece6358 7514+#include <linux/file.h>
4a4d8108
AM
7515+#include <linux/fsnotify.h>
7516+#include <linux/namei.h>
7517+#include <linux/pagemap.h>
1facf9fc 7518+#include "aufs.h"
7519+
4a4d8108
AM
7520+/* drop flags for writing */
7521+unsigned int au_file_roflags(unsigned int flags)
7522+{
7523+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
7524+ flags |= O_RDONLY | O_NOATIME;
7525+ return flags;
7526+}
7527+
7528+/* common functions to regular file and dir */
7529+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
7530+ struct file *file)
1facf9fc 7531+{
1308ab2a 7532+ struct file *h_file;
4a4d8108
AM
7533+ struct dentry *h_dentry;
7534+ struct inode *h_inode;
7535+ struct super_block *sb;
7536+ struct au_branch *br;
7537+ struct path h_path;
7538+ int err, exec_flag;
1facf9fc 7539+
4a4d8108
AM
7540+ /* a race condition can happen between open and unlink/rmdir */
7541+ h_file = ERR_PTR(-ENOENT);
7542+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 7543+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
7544+ goto out;
7545+ h_inode = h_dentry->d_inode;
b752ccd1 7546+ if (au_test_nfsd() && !h_inode)
4a4d8108
AM
7547+ goto out;
7548+ if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
7549+ || !h_inode))
7550+ goto out;
1facf9fc 7551+
4a4d8108
AM
7552+ sb = dentry->d_sb;
7553+ br = au_sbr(sb, bindex);
7554+ h_file = ERR_PTR(-EACCES);
7555+ exec_flag = flags & vfsub_fmode_to_uint(FMODE_EXEC);
7556+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
7557+ goto out;
1facf9fc 7558+
4a4d8108
AM
7559+ /* drop flags for writing */
7560+ if (au_test_ro(sb, bindex, dentry->d_inode))
7561+ flags = au_file_roflags(flags);
7562+ flags &= ~O_CREAT;
7563+ atomic_inc(&br->br_count);
7564+ h_path.dentry = h_dentry;
7565+ h_path.mnt = br->br_mnt;
7566+ if (!au_special_file(h_inode->i_mode))
7567+ h_file = vfsub_dentry_open(&h_path, flags);
7568+ else {
7569+ /* this block depends upon the configuration */
7570+ di_read_unlock(dentry, AuLock_IR);
7571+ fi_write_unlock(file);
7572+ si_read_unlock(sb);
7573+ h_file = vfsub_dentry_open(&h_path, flags);
7574+ si_noflush_read_lock(sb);
7575+ fi_write_lock(file);
7576+ di_read_lock_child(dentry, AuLock_IR);
dece6358 7577+ }
4a4d8108
AM
7578+ if (IS_ERR(h_file))
7579+ goto out_br;
dece6358 7580+
4a4d8108
AM
7581+ if (exec_flag) {
7582+ err = deny_write_access(h_file);
7583+ if (unlikely(err)) {
7584+ fput(h_file);
7585+ h_file = ERR_PTR(err);
7586+ goto out_br;
7587+ }
7588+ }
953406b4 7589+ fsnotify_open(h_file);
4a4d8108 7590+ goto out; /* success */
1facf9fc 7591+
4f0767ce 7592+out_br:
4a4d8108 7593+ atomic_dec(&br->br_count);
4f0767ce 7594+out:
4a4d8108
AM
7595+ return h_file;
7596+}
1308ab2a 7597+
4a4d8108
AM
7598+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
7599+ struct au_fidir *fidir)
1facf9fc 7600+{
dece6358 7601+ int err;
1facf9fc 7602+ struct dentry *dentry;
1308ab2a 7603+
4a4d8108
AM
7604+ err = au_finfo_init(file, fidir);
7605+ if (unlikely(err))
7606+ goto out;
1facf9fc 7607+
7608+ dentry = file->f_dentry;
4a4d8108
AM
7609+ di_read_lock_child(dentry, AuLock_IR);
7610+ err = open(file, vfsub_file_flags(file));
7611+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 7612+
4a4d8108
AM
7613+ fi_write_unlock(file);
7614+ if (unlikely(err)) {
7615+ au_fi(file)->fi_hdir = NULL;
7616+ au_finfo_fin(file);
1308ab2a 7617+ }
4a4d8108 7618+
4f0767ce 7619+out:
1308ab2a 7620+ return err;
7621+}
dece6358 7622+
4a4d8108 7623+int au_reopen_nondir(struct file *file)
1308ab2a 7624+{
4a4d8108
AM
7625+ int err;
7626+ aufs_bindex_t bstart;
7627+ struct dentry *dentry;
7628+ struct file *h_file, *h_file_tmp;
1308ab2a 7629+
4a4d8108
AM
7630+ dentry = file->f_dentry;
7631+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
7632+ bstart = au_dbstart(dentry);
7633+ h_file_tmp = NULL;
7634+ if (au_fbstart(file) == bstart) {
7635+ h_file = au_hf_top(file);
7636+ if (file->f_mode == h_file->f_mode)
7637+ return 0; /* success */
7638+ h_file_tmp = h_file;
7639+ get_file(h_file_tmp);
7640+ au_set_h_fptr(file, bstart, NULL);
7641+ }
7642+ AuDebugOn(au_fi(file)->fi_hdir);
7643+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 7644+
4a4d8108
AM
7645+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
7646+ file);
7647+ err = PTR_ERR(h_file);
7648+ if (IS_ERR(h_file))
7649+ goto out; /* todo: close all? */
7650+
7651+ err = 0;
7652+ au_set_fbstart(file, bstart);
7653+ au_set_h_fptr(file, bstart, h_file);
7654+ au_update_figen(file);
7655+ /* todo: necessary? */
7656+ /* file->f_ra = h_file->f_ra; */
7657+
4f0767ce 7658+out:
4a4d8108
AM
7659+ if (h_file_tmp)
7660+ fput(h_file_tmp);
7661+ return err;
1facf9fc 7662+}
7663+
1308ab2a 7664+/* ---------------------------------------------------------------------- */
7665+
4a4d8108
AM
7666+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
7667+ struct dentry *hi_wh)
1facf9fc 7668+{
4a4d8108
AM
7669+ int err;
7670+ aufs_bindex_t bstart;
7671+ struct au_dinfo *dinfo;
7672+ struct dentry *h_dentry;
7673+ struct au_hdentry *hdp;
1facf9fc 7674+
4a4d8108
AM
7675+ dinfo = au_di(file->f_dentry);
7676+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 7677+
4a4d8108
AM
7678+ bstart = dinfo->di_bstart;
7679+ dinfo->di_bstart = btgt;
7680+ hdp = dinfo->di_hdentry;
7681+ h_dentry = hdp[0 + btgt].hd_dentry;
7682+ hdp[0 + btgt].hd_dentry = hi_wh;
7683+ err = au_reopen_nondir(file);
7684+ hdp[0 + btgt].hd_dentry = h_dentry;
7685+ dinfo->di_bstart = bstart;
1facf9fc 7686+
1facf9fc 7687+ return err;
7688+}
7689+
4a4d8108
AM
7690+static int au_ready_to_write_wh(struct file *file, loff_t len,
7691+ aufs_bindex_t bcpup)
1facf9fc 7692+{
4a4d8108 7693+ int err;
dece6358 7694+ struct inode *inode;
4a4d8108 7695+ struct dentry *dentry, *hi_wh;
1facf9fc 7696+
dece6358 7697+ dentry = file->f_dentry;
4a4d8108 7698+ au_update_dbstart(dentry);
dece6358 7699+ inode = dentry->d_inode;
4a4d8108
AM
7700+ hi_wh = au_hi_wh(inode, bcpup);
7701+ if (!hi_wh)
7702+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
7703+ else
7704+ /* already copied-up after unlink */
7705+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 7706+
4a4d8108
AM
7707+ if (!err
7708+ && inode->i_nlink > 1
7709+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
7710+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 7711+
dece6358 7712+ return err;
1facf9fc 7713+}
7714+
4a4d8108
AM
7715+/*
7716+ * prepare the @file for writing.
7717+ */
7718+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 7719+{
4a4d8108
AM
7720+ int err;
7721+ aufs_bindex_t bstart, bcpup;
7722+ struct dentry *dentry, *parent, *h_dentry;
7723+ struct inode *h_inode, *inode;
1facf9fc 7724+ struct super_block *sb;
4a4d8108 7725+ struct file *h_file;
1facf9fc 7726+
7727+ dentry = file->f_dentry;
1facf9fc 7728+ sb = dentry->d_sb;
4a4d8108
AM
7729+ inode = dentry->d_inode;
7730+ AuDebugOn(au_special_file(inode->i_mode));
7731+ bstart = au_fbstart(file);
7732+ err = au_test_ro(sb, bstart, inode);
7733+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
7734+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 7735+ goto out;
4a4d8108 7736+ }
1facf9fc 7737+
4a4d8108
AM
7738+ /* need to cpup */
7739+ parent = dget_parent(dentry);
7740+ di_write_lock_parent(parent);
7741+ err = AuWbrCopyup(au_sbi(sb), dentry);
7742+ bcpup = err;
7743+ if (unlikely(err < 0))
7744+ goto out_dgrade;
7745+ err = 0;
7746+
7747+ if (!au_h_dptr(parent, bcpup)) {
7748+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 7749+ if (unlikely(err))
4a4d8108
AM
7750+ goto out_dgrade;
7751+ }
7752+
7753+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
7754+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
7755+ if (unlikely(err))
7756+ goto out_dgrade;
7757+
7758+ h_dentry = au_hf_top(file)->f_dentry;
7759+ h_inode = h_dentry->d_inode;
7760+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
7761+ h_file = au_h_open_pre(dentry, bstart);
7762+ if (IS_ERR(h_file)) {
7763+ err = PTR_ERR(h_file);
7764+ h_file = NULL;
7765+ } else if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
7766+ /* || !h_inode->i_nlink */) {
7767+ err = au_ready_to_write_wh(file, len, bcpup);
7768+ di_downgrade_lock(parent, AuLock_IR);
7769+ } else {
7770+ di_downgrade_lock(parent, AuLock_IR);
7771+ if (!au_h_dptr(dentry, bcpup))
7772+ err = au_sio_cpup_simple(dentry, bcpup, len,
7773+ AuCpup_DTIME);
7774+ if (!err)
7775+ err = au_reopen_nondir(file);
7776+ }
7777+ mutex_unlock(&h_inode->i_mutex);
7778+ au_h_open_post(dentry, bstart, h_file);
7779+
7780+ if (!err) {
7781+ au_pin_set_parent_lflag(pin, /*lflag*/0);
7782+ goto out_dput; /* success */
7783+ }
7784+ au_unpin(pin);
7785+ goto out_unlock;
1facf9fc 7786+
4f0767ce 7787+out_dgrade:
4a4d8108 7788+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 7789+out_unlock:
4a4d8108 7790+ di_read_unlock(parent, AuLock_IR);
4f0767ce 7791+out_dput:
4a4d8108 7792+ dput(parent);
4f0767ce 7793+out:
1facf9fc 7794+ return err;
7795+}
7796+
4a4d8108
AM
7797+/* ---------------------------------------------------------------------- */
7798+
7799+int au_do_flush(struct file *file, fl_owner_t id,
7800+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 7801+{
4a4d8108 7802+ int err;
1308ab2a 7803+ struct dentry *dentry;
1facf9fc 7804+ struct super_block *sb;
4a4d8108 7805+ struct inode *inode;
1facf9fc 7806+
1facf9fc 7807+ dentry = file->f_dentry;
7808+ sb = dentry->d_sb;
dece6358 7809+ inode = dentry->d_inode;
4a4d8108
AM
7810+ si_noflush_read_lock(sb);
7811+ fi_read_lock(file);
b752ccd1 7812+ ii_read_lock_child(inode);
1facf9fc 7813+
4a4d8108
AM
7814+ err = flush(file, id);
7815+ au_cpup_attr_timesizes(inode);
1facf9fc 7816+
b752ccd1 7817+ ii_read_unlock(inode);
4a4d8108 7818+ fi_read_unlock(file);
1308ab2a 7819+ si_read_unlock(sb);
dece6358 7820+ return err;
1facf9fc 7821+}
7822+
4a4d8108
AM
7823+/* ---------------------------------------------------------------------- */
7824+
7825+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 7826+{
4a4d8108
AM
7827+ int err;
7828+ aufs_bindex_t bstart;
7829+ struct au_pin pin;
7830+ struct au_finfo *finfo;
7831+ struct dentry *dentry, *parent, *hi_wh;
7832+ struct inode *inode;
1facf9fc 7833+ struct super_block *sb;
7834+
4a4d8108
AM
7835+ FiMustWriteLock(file);
7836+
7837+ err = 0;
7838+ finfo = au_fi(file);
1308ab2a 7839+ dentry = file->f_dentry;
7840+ sb = dentry->d_sb;
4a4d8108
AM
7841+ inode = dentry->d_inode;
7842+ bstart = au_ibstart(inode);
7843+ if (bstart == finfo->fi_btop)
1308ab2a 7844+ goto out;
dece6358 7845+
4a4d8108
AM
7846+ parent = dget_parent(dentry);
7847+ if (au_test_ro(sb, bstart, inode)) {
7848+ di_read_lock_parent(parent, !AuLock_IR);
7849+ err = AuWbrCopyup(au_sbi(sb), dentry);
7850+ bstart = err;
7851+ di_read_unlock(parent, !AuLock_IR);
7852+ if (unlikely(err < 0))
7853+ goto out_parent;
7854+ err = 0;
1facf9fc 7855+ }
1facf9fc 7856+
4a4d8108
AM
7857+ di_read_lock_parent(parent, AuLock_IR);
7858+ hi_wh = au_hi_wh(inode, bstart);
7859+ if (au_opt_test(au_mntflags(sb), PLINK)
7860+ && au_plink_test(inode)
7861+ && !d_unhashed(dentry)) {
7862+ err = au_test_and_cpup_dirs(dentry, bstart);
7863+ if (unlikely(err))
7864+ goto out_unlock;
7865+
7866+ /* always superio. */
7867+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
7868+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
7869+ if (!err)
7870+ err = au_sio_cpup_simple(dentry, bstart, -1,
7871+ AuCpup_DTIME);
7872+ au_unpin(&pin);
7873+ } else if (hi_wh) {
7874+ /* already copied-up after unlink */
7875+ err = au_reopen_wh(file, bstart, hi_wh);
7876+ *need_reopen = 0;
7877+ }
1facf9fc 7878+
4f0767ce 7879+out_unlock:
4a4d8108 7880+ di_read_unlock(parent, AuLock_IR);
4f0767ce 7881+out_parent:
4a4d8108 7882+ dput(parent);
4f0767ce 7883+out:
1308ab2a 7884+ return err;
dece6358 7885+}
1facf9fc 7886+
4a4d8108 7887+static void au_do_refresh_dir(struct file *file)
dece6358 7888+{
4a4d8108
AM
7889+ aufs_bindex_t bindex, bend, new_bindex, brid;
7890+ struct au_hfile *p, tmp, *q;
7891+ struct au_finfo *finfo;
1308ab2a 7892+ struct super_block *sb;
4a4d8108 7893+ struct au_fidir *fidir;
1facf9fc 7894+
4a4d8108 7895+ FiMustWriteLock(file);
1facf9fc 7896+
4a4d8108
AM
7897+ sb = file->f_dentry->d_sb;
7898+ finfo = au_fi(file);
7899+ fidir = finfo->fi_hdir;
7900+ AuDebugOn(!fidir);
7901+ p = fidir->fd_hfile + finfo->fi_btop;
7902+ brid = p->hf_br->br_id;
7903+ bend = fidir->fd_bbot;
7904+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
7905+ if (!p->hf_file)
7906+ continue;
1308ab2a 7907+
4a4d8108
AM
7908+ new_bindex = au_br_index(sb, p->hf_br->br_id);
7909+ if (new_bindex == bindex)
7910+ continue;
7911+ if (new_bindex < 0) {
7912+ au_set_h_fptr(file, bindex, NULL);
7913+ continue;
7914+ }
1308ab2a 7915+
4a4d8108
AM
7916+ /* swap two lower inode, and loop again */
7917+ q = fidir->fd_hfile + new_bindex;
7918+ tmp = *q;
7919+ *q = *p;
7920+ *p = tmp;
7921+ if (tmp.hf_file) {
7922+ bindex--;
7923+ p--;
7924+ }
7925+ }
1308ab2a 7926+
4a4d8108
AM
7927+ p = fidir->fd_hfile;
7928+ if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
7929+ bend = au_sbend(sb);
7930+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
7931+ finfo->fi_btop++, p++)
7932+ if (p->hf_file) {
7933+ if (p->hf_file->f_dentry
7934+ && p->hf_file->f_dentry->d_inode)
7935+ break;
7936+ else
7937+ au_hfput(p, file);
7938+ }
7939+ } else {
7940+ bend = au_br_index(sb, brid);
7941+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
7942+ finfo->fi_btop++, p++)
7943+ if (p->hf_file)
7944+ au_hfput(p, file);
7945+ bend = au_sbend(sb);
7946+ }
1308ab2a 7947+
4a4d8108
AM
7948+ p = fidir->fd_hfile + bend;
7949+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
7950+ fidir->fd_bbot--, p--)
7951+ if (p->hf_file) {
7952+ if (p->hf_file->f_dentry
7953+ && p->hf_file->f_dentry->d_inode)
7954+ break;
7955+ else
7956+ au_hfput(p, file);
7957+ }
7958+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 7959+}
7960+
4a4d8108
AM
7961+/*
7962+ * after branch manipulating, refresh the file.
7963+ */
7964+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 7965+{
4a4d8108
AM
7966+ int err, need_reopen;
7967+ aufs_bindex_t bend, bindex;
7968+ struct dentry *dentry;
1308ab2a 7969+ struct au_finfo *finfo;
4a4d8108 7970+ struct au_hfile *hfile;
1facf9fc 7971+
4a4d8108 7972+ dentry = file->f_dentry;
1308ab2a 7973+ finfo = au_fi(file);
4a4d8108
AM
7974+ if (!finfo->fi_hdir) {
7975+ hfile = &finfo->fi_htop;
7976+ AuDebugOn(!hfile->hf_file);
7977+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
7978+ AuDebugOn(bindex < 0);
7979+ if (bindex != finfo->fi_btop)
7980+ au_set_fbstart(file, bindex);
7981+ } else {
7982+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
7983+ if (unlikely(err))
7984+ goto out;
7985+ au_do_refresh_dir(file);
7986+ }
1facf9fc 7987+
4a4d8108
AM
7988+ err = 0;
7989+ need_reopen = 1;
7990+ if (!au_test_mmapped(file))
7991+ err = au_file_refresh_by_inode(file, &need_reopen);
7992+ if (!err && need_reopen && !d_unhashed(dentry))
7993+ err = reopen(file);
7994+ if (!err) {
7995+ au_update_figen(file);
7996+ goto out; /* success */
7997+ }
7998+
7999+ /* error, close all lower files */
8000+ if (finfo->fi_hdir) {
8001+ bend = au_fbend_dir(file);
8002+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
8003+ au_set_h_fptr(file, bindex, NULL);
8004+ }
1facf9fc 8005+
4f0767ce 8006+out:
1facf9fc 8007+ return err;
8008+}
8009+
4a4d8108
AM
8010+/* common function to regular file and dir */
8011+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8012+ int wlock)
dece6358 8013+{
1308ab2a 8014+ int err;
4a4d8108
AM
8015+ unsigned int sigen, figen;
8016+ aufs_bindex_t bstart;
8017+ unsigned char pseudo_link;
8018+ struct dentry *dentry;
8019+ struct inode *inode;
1facf9fc 8020+
4a4d8108
AM
8021+ err = 0;
8022+ dentry = file->f_dentry;
8023+ inode = dentry->d_inode;
8024+ AuDebugOn(au_special_file(inode->i_mode));
8025+ sigen = au_sigen(dentry->d_sb);
8026+ fi_write_lock(file);
8027+ figen = au_figen(file);
8028+ di_write_lock_child(dentry);
8029+ bstart = au_dbstart(dentry);
8030+ pseudo_link = (bstart != au_ibstart(inode));
8031+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
8032+ if (!wlock) {
8033+ di_downgrade_lock(dentry, AuLock_IR);
8034+ fi_downgrade_lock(file);
8035+ }
8036+ goto out; /* success */
8037+ }
dece6358 8038+
4a4d8108
AM
8039+ AuDbg("sigen %d, figen %d\n", sigen, figen);
8040+ if (sigen != au_digen(dentry)
8041+ || sigen != au_iigen(inode)) {
8042+ err = au_reval_dpath(dentry, sigen);
8043+ if (unlikely(err < 0))
8044+ goto out;
8045+ AuDebugOn(au_digen(dentry) != sigen
8046+ || au_iigen(inode) != sigen);
8047+ }
dece6358 8048+
4a4d8108
AM
8049+ err = refresh_file(file, reopen);
8050+ if (!err) {
8051+ if (!wlock) {
8052+ di_downgrade_lock(dentry, AuLock_IR);
8053+ fi_downgrade_lock(file);
8054+ }
8055+ } else {
8056+ di_write_unlock(dentry);
8057+ fi_write_unlock(file);
8058+ }
1facf9fc 8059+
4f0767ce 8060+out:
1308ab2a 8061+ return err;
8062+}
1facf9fc 8063+
4a4d8108
AM
8064+/* ---------------------------------------------------------------------- */
8065+
8066+/* cf. aufs_nopage() */
8067+/* for madvise(2) */
8068+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 8069+{
4a4d8108
AM
8070+ unlock_page(page);
8071+ return 0;
8072+}
1facf9fc 8073+
4a4d8108
AM
8074+/* it will never be called, but necessary to support O_DIRECT */
8075+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
8076+ const struct iovec *iov, loff_t offset,
8077+ unsigned long nr_segs)
8078+{ BUG(); return 0; }
1facf9fc 8079+
4a4d8108
AM
8080+/*
8081+ * it will never be called, but madvise and fadvise behaves differently
8082+ * when get_xip_mem is defined
8083+ */
8084+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
8085+ int create, void **kmem, unsigned long *pfn)
8086+{ BUG(); return 0; }
1facf9fc 8087+
4a4d8108
AM
8088+/* they will never be called. */
8089+#ifdef CONFIG_AUFS_DEBUG
8090+static int aufs_write_begin(struct file *file, struct address_space *mapping,
8091+ loff_t pos, unsigned len, unsigned flags,
8092+ struct page **pagep, void **fsdata)
8093+{ AuUnsupport(); return 0; }
8094+static int aufs_write_end(struct file *file, struct address_space *mapping,
8095+ loff_t pos, unsigned len, unsigned copied,
8096+ struct page *page, void *fsdata)
8097+{ AuUnsupport(); return 0; }
8098+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
8099+{ AuUnsupport(); return 0; }
8100+static void aufs_sync_page(struct page *page)
8101+{ AuUnsupport(); }
1308ab2a 8102+
4a4d8108
AM
8103+static int aufs_set_page_dirty(struct page *page)
8104+{ AuUnsupport(); return 0; }
8105+static void aufs_invalidatepage(struct page *page, unsigned long offset)
8106+{ AuUnsupport(); }
8107+static int aufs_releasepage(struct page *page, gfp_t gfp)
8108+{ AuUnsupport(); return 0; }
8109+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
8110+ struct page *page)
8111+{ AuUnsupport(); return 0; }
8112+static int aufs_launder_page(struct page *page)
8113+{ AuUnsupport(); return 0; }
8114+static int aufs_is_partially_uptodate(struct page *page,
8115+ read_descriptor_t *desc,
8116+ unsigned long from)
8117+{ AuUnsupport(); return 0; }
8118+static int aufs_error_remove_page(struct address_space *mapping,
8119+ struct page *page)
8120+{ AuUnsupport(); return 0; }
8121+#endif /* CONFIG_AUFS_DEBUG */
8122+
8123+const struct address_space_operations aufs_aop = {
8124+ .readpage = aufs_readpage,
8125+ .direct_IO = aufs_direct_IO,
8126+ .get_xip_mem = aufs_get_xip_mem,
8127+#ifdef CONFIG_AUFS_DEBUG
8128+ .writepage = aufs_writepage,
8129+ .sync_page = aufs_sync_page,
8130+ /* no writepages, because of writepage */
8131+ .set_page_dirty = aufs_set_page_dirty,
8132+ /* no readpages, because of readpage */
8133+ .write_begin = aufs_write_begin,
8134+ .write_end = aufs_write_end,
8135+ /* no bmap, no block device */
8136+ .invalidatepage = aufs_invalidatepage,
8137+ .releasepage = aufs_releasepage,
8138+ .migratepage = aufs_migratepage,
8139+ .launder_page = aufs_launder_page,
8140+ .is_partially_uptodate = aufs_is_partially_uptodate,
8141+ .error_remove_page = aufs_error_remove_page
8142+#endif /* CONFIG_AUFS_DEBUG */
dece6358 8143+};
e49829fe 8144--- /dev/null
0c5527e5 8145+++ linux-2.6/fs/aufs/file.h 2010-10-25 14:20:44.000000000 +0200
b752ccd1 8146@@ -0,0 +1,238 @@
4a4d8108
AM
8147+/*
8148+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8149+ *
8150+ * This program, aufs is free software; you can redistribute it and/or modify
8151+ * it under the terms of the GNU General Public License as published by
8152+ * the Free Software Foundation; either version 2 of the License, or
8153+ * (at your option) any later version.
8154+ *
8155+ * This program is distributed in the hope that it will be useful,
8156+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8157+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8158+ * GNU General Public License for more details.
8159+ *
8160+ * You should have received a copy of the GNU General Public License
8161+ * along with this program; if not, write to the Free Software
8162+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8163+ */
1facf9fc 8164+
4a4d8108
AM
8165+/*
8166+ * file operations
8167+ */
1facf9fc 8168+
4a4d8108
AM
8169+#ifndef __AUFS_FILE_H__
8170+#define __AUFS_FILE_H__
1facf9fc 8171+
4a4d8108 8172+#ifdef __KERNEL__
1facf9fc 8173+
4a4d8108
AM
8174+#include <linux/fs.h>
8175+#include <linux/poll.h>
8176+#include <linux/aufs_type.h>
8177+#include "rwsem.h"
1facf9fc 8178+
4a4d8108
AM
8179+struct au_branch;
8180+struct au_hfile {
8181+ struct file *hf_file;
8182+ struct au_branch *hf_br;
8183+};
1facf9fc 8184+
4a4d8108
AM
8185+struct au_vdir;
8186+struct au_fidir {
8187+ aufs_bindex_t fd_bbot;
8188+ aufs_bindex_t fd_nent;
8189+ struct au_vdir *fd_vdir_cache;
8190+ struct au_hfile fd_hfile[];
8191+};
1facf9fc 8192+
4a4d8108 8193+static inline int au_fidir_sz(int nent)
dece6358 8194+{
4f0767ce
JR
8195+ AuDebugOn(nent < 0);
8196+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 8197+}
1facf9fc 8198+
4a4d8108
AM
8199+struct au_finfo {
8200+ atomic_t fi_generation;
dece6358 8201+
4a4d8108
AM
8202+ struct au_rwsem fi_rwsem;
8203+ aufs_bindex_t fi_btop;
8204+
8205+ /* do not union them */
8206+ struct { /* for non-dir */
8207+ struct au_hfile fi_htop;
8208+ struct vm_operations_struct *fi_hvmop;
8209+ struct mutex fi_vm_mtx;
8210+ struct mutex fi_mmap;
8211+ };
8212+ struct au_fidir *fi_hdir; /* for dir only */
8213+} ____cacheline_aligned_in_smp;
1facf9fc 8214+
4a4d8108 8215+/* ---------------------------------------------------------------------- */
1facf9fc 8216+
4a4d8108
AM
8217+/* file.c */
8218+extern const struct address_space_operations aufs_aop;
8219+unsigned int au_file_roflags(unsigned int flags);
8220+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8221+ struct file *file);
8222+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8223+ struct au_fidir *fidir);
8224+int au_reopen_nondir(struct file *file);
8225+struct au_pin;
8226+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
8227+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
8228+ int wlock);
8229+int au_do_flush(struct file *file, fl_owner_t id,
8230+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 8231+
4a4d8108
AM
8232+/* poll.c */
8233+#ifdef CONFIG_AUFS_POLL
8234+unsigned int aufs_poll(struct file *file, poll_table *wait);
8235+#endif
1facf9fc 8236+
4a4d8108
AM
8237+#ifdef CONFIG_AUFS_BR_HFSPLUS
8238+/* hfsplus.c */
8239+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
8240+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
8241+ struct file *h_file);
8242+#else
8243+static inline
8244+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 8245+{
4a4d8108
AM
8246+ return NULL;
8247+}
1facf9fc 8248+
4a4d8108
AM
8249+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
8250+ struct file *h_file);
8251+#endif
1facf9fc 8252+
4a4d8108
AM
8253+/* f_op.c */
8254+extern const struct file_operations aufs_file_fop;
8255+extern const struct vm_operations_struct aufs_vm_ops;
8256+int au_do_open_nondir(struct file *file, int flags);
8257+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
8258+
8259+#ifdef CONFIG_AUFS_SP_IATTR
8260+/* f_op_sp.c */
8261+int au_special_file(umode_t mode);
8262+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
8263+#else
8264+AuStubInt0(au_special_file, umode_t mode)
8265+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
8266+ dev_t rdev)
8267+{
8268+ init_special_inode(inode, mode, rdev);
8269+}
8270+#endif
1facf9fc 8271+
4a4d8108
AM
8272+/* finfo.c */
8273+void au_hfput(struct au_hfile *hf, struct file *file);
8274+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
8275+ struct file *h_file);
1facf9fc 8276+
4a4d8108
AM
8277+void au_update_figen(struct file *file);
8278+void au_fi_mmap_lock(struct file *file);
8279+void au_fi_mmap_unlock(struct file *file);
8280+struct au_fidir *au_fidir_alloc(struct super_block *sb);
8281+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 8282+
4a4d8108
AM
8283+void au_fi_init_once(void *_fi);
8284+void au_finfo_fin(struct file *file);
8285+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 8286+
4a4d8108
AM
8287+/* ioctl.c */
8288+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
8289+#ifdef CONFIG_COMPAT
8290+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
8291+ unsigned long arg);
8292+#endif
1facf9fc 8293+
4a4d8108 8294+/* ---------------------------------------------------------------------- */
1facf9fc 8295+
4a4d8108
AM
8296+static inline struct au_finfo *au_fi(struct file *file)
8297+{
8298+ return file->private_data;
8299+}
1facf9fc 8300+
4a4d8108 8301+/* ---------------------------------------------------------------------- */
1facf9fc 8302+
4a4d8108
AM
8303+/*
8304+ * fi_read_lock, fi_write_lock,
8305+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
8306+ */
8307+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 8308+
4a4d8108
AM
8309+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
8310+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
8311+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 8312+
1308ab2a 8313+/* ---------------------------------------------------------------------- */
8314+
4a4d8108
AM
8315+/* todo: hard/soft set? */
8316+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 8317+{
4a4d8108
AM
8318+ FiMustAnyLock(file);
8319+ return au_fi(file)->fi_btop;
8320+}
dece6358 8321+
4a4d8108
AM
8322+static inline aufs_bindex_t au_fbend_dir(struct file *file)
8323+{
8324+ FiMustAnyLock(file);
8325+ AuDebugOn(!au_fi(file)->fi_hdir);
8326+ return au_fi(file)->fi_hdir->fd_bbot;
8327+}
1facf9fc 8328+
4a4d8108
AM
8329+static inline struct au_vdir *au_fvdir_cache(struct file *file)
8330+{
8331+ FiMustAnyLock(file);
8332+ AuDebugOn(!au_fi(file)->fi_hdir);
8333+ return au_fi(file)->fi_hdir->fd_vdir_cache;
8334+}
1facf9fc 8335+
4a4d8108
AM
8336+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
8337+{
8338+ FiMustWriteLock(file);
8339+ au_fi(file)->fi_btop = bindex;
8340+}
1facf9fc 8341+
4a4d8108
AM
8342+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
8343+{
8344+ FiMustWriteLock(file);
8345+ AuDebugOn(!au_fi(file)->fi_hdir);
8346+ au_fi(file)->fi_hdir->fd_bbot = bindex;
8347+}
1308ab2a 8348+
4a4d8108
AM
8349+static inline void au_set_fvdir_cache(struct file *file,
8350+ struct au_vdir *vdir_cache)
8351+{
8352+ FiMustWriteLock(file);
8353+ AuDebugOn(!au_fi(file)->fi_hdir);
8354+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
8355+}
dece6358 8356+
4a4d8108
AM
8357+static inline struct file *au_hf_top(struct file *file)
8358+{
8359+ FiMustAnyLock(file);
8360+ AuDebugOn(au_fi(file)->fi_hdir);
8361+ return au_fi(file)->fi_htop.hf_file;
8362+}
1facf9fc 8363+
4a4d8108
AM
8364+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
8365+{
8366+ FiMustAnyLock(file);
8367+ AuDebugOn(!au_fi(file)->fi_hdir);
8368+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
8369+}
8370+
4a4d8108
AM
8371+/* todo: memory barrier? */
8372+static inline unsigned int au_figen(struct file *f)
dece6358 8373+{
4a4d8108
AM
8374+ return atomic_read(&au_fi(f)->fi_generation);
8375+}
dece6358 8376+
4a4d8108
AM
8377+static inline int au_test_mmapped(struct file *f)
8378+{
8379+ FiMustAnyLock(f);
8380+ return !!(au_fi(f)->fi_hvmop);
8381+}
1308ab2a 8382+
4a4d8108
AM
8383+#endif /* __KERNEL__ */
8384+#endif /* __AUFS_FILE_H__ */
e49829fe 8385--- /dev/null
0c5527e5 8386+++ linux-2.6/fs/aufs/finfo.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 8387@@ -0,0 +1,171 @@
4a4d8108
AM
8388+/*
8389+ * Copyright (C) 2005-2010 Junjiro R. Okajima
8390+ *
8391+ * This program, aufs is free software; you can redistribute it and/or modify
8392+ * it under the terms of the GNU General Public License as published by
8393+ * the Free Software Foundation; either version 2 of the License, or
8394+ * (at your option) any later version.
8395+ *
8396+ * This program is distributed in the hope that it will be useful,
8397+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8398+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8399+ * GNU General Public License for more details.
8400+ *
8401+ * You should have received a copy of the GNU General Public License
8402+ * along with this program; if not, write to the Free Software
8403+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8404+ */
1308ab2a 8405+
4a4d8108
AM
8406+/*
8407+ * file private data
8408+ */
1facf9fc 8409+
4a4d8108
AM
8410+#include <linux/file.h>
8411+#include "aufs.h"
1facf9fc 8412+
4a4d8108
AM
8413+void au_hfput(struct au_hfile *hf, struct file *file)
8414+{
8415+ /* todo: direct access f_flags */
8416+ if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC))
8417+ allow_write_access(hf->hf_file);
8418+ fput(hf->hf_file);
8419+ hf->hf_file = NULL;
e49829fe 8420+ atomic_dec(&hf->hf_br->br_count);
4a4d8108
AM
8421+ hf->hf_br = NULL;
8422+}
1facf9fc 8423+
4a4d8108
AM
8424+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
8425+{
8426+ struct au_finfo *finfo = au_fi(file);
8427+ struct au_hfile *hf;
8428+ struct au_fidir *fidir;
8429+
8430+ fidir = finfo->fi_hdir;
8431+ if (!fidir) {
8432+ AuDebugOn(finfo->fi_btop != bindex);
8433+ hf = &finfo->fi_htop;
8434+ } else
8435+ hf = fidir->fd_hfile + bindex;
8436+
8437+ if (hf && hf->hf_file)
8438+ au_hfput(hf, file);
8439+ if (val) {
8440+ FiMustWriteLock(file);
8441+ hf->hf_file = val;
8442+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 8443+ }
4a4d8108 8444+}
1facf9fc 8445+
4a4d8108
AM
8446+void au_update_figen(struct file *file)
8447+{
8448+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
8449+ /* smp_mb(); */ /* atomic_set */
1facf9fc 8450+}
8451+
4a4d8108
AM
8452+/* ---------------------------------------------------------------------- */
8453+
8454+void au_fi_mmap_lock(struct file *file)
1facf9fc 8455+{
4a4d8108
AM
8456+ FiMustWriteLock(file);
8457+ lockdep_off();
8458+ mutex_lock(&au_fi(file)->fi_mmap);
8459+ lockdep_on();
8460+}
1facf9fc 8461+
4a4d8108
AM
8462+void au_fi_mmap_unlock(struct file *file)
8463+{
8464+ lockdep_off();
8465+ mutex_unlock(&au_fi(file)->fi_mmap);
8466+ lockdep_on();
8467+}
1308ab2a 8468+
4a4d8108 8469+/* ---------------------------------------------------------------------- */
1308ab2a 8470+
4a4d8108
AM
8471+struct au_fidir *au_fidir_alloc(struct super_block *sb)
8472+{
8473+ struct au_fidir *fidir;
8474+ int nbr;
8475+
8476+ nbr = au_sbend(sb) + 1;
8477+ if (nbr < 2)
8478+ nbr = 2; /* initial allocate for 2 branches */
8479+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
8480+ if (fidir) {
8481+ fidir->fd_bbot = -1;
8482+ fidir->fd_nent = nbr;
8483+ fidir->fd_vdir_cache = NULL;
8484+ }
8485+
8486+ return fidir;
8487+}
8488+
8489+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
8490+{
8491+ int err;
8492+ struct au_fidir *fidir, *p;
8493+
8494+ AuRwMustWriteLock(&finfo->fi_rwsem);
8495+ fidir = finfo->fi_hdir;
8496+ AuDebugOn(!fidir);
8497+
8498+ err = -ENOMEM;
8499+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
8500+ GFP_NOFS);
8501+ if (p) {
8502+ p->fd_nent = nbr;
8503+ finfo->fi_hdir = p;
8504+ err = 0;
8505+ }
1facf9fc 8506+
dece6358 8507+ return err;
1facf9fc 8508+}
1308ab2a 8509+
8510+/* ---------------------------------------------------------------------- */
8511+
4a4d8108 8512+void au_finfo_fin(struct file *file)
1308ab2a 8513+{
4a4d8108
AM
8514+ struct au_finfo *finfo;
8515+
8516+ finfo = au_fi(file);
8517+ AuDebugOn(finfo->fi_hdir);
8518+ AuRwDestroy(&finfo->fi_rwsem);
8519+ au_cache_free_finfo(finfo);
1308ab2a 8520+}
1308ab2a 8521+
e49829fe 8522+void au_fi_init_once(void *_finfo)
4a4d8108 8523+{
e49829fe
JR
8524+ struct au_finfo *finfo = _finfo;
8525+ static struct lock_class_key aufs_fi, aufs_fi_vm, aufs_fi_mmap;
1308ab2a 8526+
e49829fe
JR
8527+ au_rw_init(&finfo->fi_rwsem);
8528+ au_rw_class(&finfo->fi_rwsem, &aufs_fi);
8529+ mutex_init(&finfo->fi_vm_mtx);
8530+ lockdep_set_class(&finfo->fi_vm_mtx, &aufs_fi_vm);
8531+ mutex_init(&finfo->fi_mmap);
8532+ lockdep_set_class(&finfo->fi_mmap, &aufs_fi_mmap);
4a4d8108 8533+}
1308ab2a 8534+
4a4d8108
AM
8535+int au_finfo_init(struct file *file, struct au_fidir *fidir)
8536+{
8537+ int err;
8538+ struct au_finfo *finfo;
8539+ struct dentry *dentry;
8540+
8541+ err = -ENOMEM;
8542+ dentry = file->f_dentry;
8543+ finfo = au_cache_alloc_finfo();
8544+ if (unlikely(!finfo))
8545+ goto out;
8546+
8547+ err = 0;
8548+ au_rw_write_lock(&finfo->fi_rwsem);
8549+ finfo->fi_btop = -1;
8550+ finfo->fi_hdir = fidir;
8551+ atomic_set(&finfo->fi_generation, au_digen(dentry));
8552+ /* smp_mb(); */ /* atomic_set */
8553+
8554+ file->private_data = finfo;
8555+
8556+out:
8557+ return err;
8558+}
e49829fe 8559--- /dev/null
0c5527e5
AM
8560+++ linux-2.6/fs/aufs/f_op.c 2010-10-26 21:39:38.000000000 +0200
8561@@ -0,0 +1,900 @@
dece6358 8562+/*
4a4d8108 8563+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
8564+ *
8565+ * This program, aufs is free software; you can redistribute it and/or modify
8566+ * it under the terms of the GNU General Public License as published by
8567+ * the Free Software Foundation; either version 2 of the License, or
8568+ * (at your option) any later version.
8569+ *
8570+ * This program is distributed in the hope that it will be useful,
8571+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8572+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8573+ * GNU General Public License for more details.
8574+ *
8575+ * You should have received a copy of the GNU General Public License
8576+ * along with this program; if not, write to the Free Software
8577+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8578+ */
1facf9fc 8579+
8580+/*
4a4d8108 8581+ * file and vm operations
1facf9fc 8582+ */
dece6358
AM
8583+
8584+#include <linux/file.h>
4a4d8108
AM
8585+#include <linux/fs_stack.h>
8586+#include <linux/mman.h>
8587+#include <linux/mm.h>
8588+#include <linux/security.h>
dece6358
AM
8589+#include "aufs.h"
8590+
4a4d8108 8591+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 8592+{
4a4d8108
AM
8593+ int err;
8594+ aufs_bindex_t bindex;
8595+ struct file *h_file;
8596+ struct dentry *dentry;
8597+ struct au_finfo *finfo;
8598+
8599+ FiMustWriteLock(file);
8600+
8601+ err = 0;
8602+ dentry = file->f_dentry;
8603+ finfo = au_fi(file);
8604+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
8605+ finfo->fi_hvmop = NULL;
8606+ bindex = au_dbstart(dentry);
8607+ h_file = au_h_open(dentry, bindex, flags, file);
8608+ if (IS_ERR(h_file))
8609+ err = PTR_ERR(h_file);
8610+ else {
8611+ au_set_fbstart(file, bindex);
8612+ au_set_h_fptr(file, bindex, h_file);
8613+ au_update_figen(file);
8614+ /* todo: necessary? */
8615+ /* file->f_ra = h_file->f_ra; */
8616+ }
8617+ return err;
1facf9fc 8618+}
8619+
4a4d8108
AM
8620+static int aufs_open_nondir(struct inode *inode __maybe_unused,
8621+ struct file *file)
1facf9fc 8622+{
4a4d8108 8623+ int err;
1308ab2a 8624+ struct super_block *sb;
1facf9fc 8625+
4a4d8108
AM
8626+ AuDbg("%.*s, f_ flags 0x%x, f_mode 0x%x\n",
8627+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
8628+ file->f_mode);
1facf9fc 8629+
4a4d8108
AM
8630+ sb = file->f_dentry->d_sb;
8631+ si_read_lock(sb, AuLock_FLUSH);
8632+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
8633+ si_read_unlock(sb);
8634+ return err;
8635+}
1facf9fc 8636+
4a4d8108
AM
8637+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
8638+{
8639+ struct au_finfo *finfo;
8640+ aufs_bindex_t bindex;
1facf9fc 8641+
4a4d8108
AM
8642+ finfo = au_fi(file);
8643+ bindex = finfo->fi_btop;
0c5527e5
AM
8644+ if (bindex >= 0) {
8645+ /* remove me from sb->s_files */
8646+ file_sb_list_del(file);
4a4d8108 8647+ au_set_h_fptr(file, bindex, NULL);
0c5527e5 8648+ }
4a4d8108
AM
8649+ au_finfo_fin(file);
8650+ return 0;
1facf9fc 8651+}
8652+
4a4d8108
AM
8653+/* ---------------------------------------------------------------------- */
8654+
8655+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 8656+{
1308ab2a 8657+ int err;
4a4d8108
AM
8658+ struct file *h_file;
8659+
8660+ err = 0;
8661+ h_file = au_hf_top(file);
8662+ if (h_file)
8663+ err = vfsub_flush(h_file, id);
8664+ return err;
8665+}
8666+
8667+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
8668+{
8669+ return au_do_flush(file, id, au_do_flush_nondir);
8670+}
8671+
8672+/* ---------------------------------------------------------------------- */
8673+
8674+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
8675+ loff_t *ppos)
8676+{
8677+ ssize_t err;
dece6358 8678+ struct dentry *dentry;
4a4d8108 8679+ struct file *h_file;
dece6358 8680+ struct super_block *sb;
1facf9fc 8681+
dece6358
AM
8682+ dentry = file->f_dentry;
8683+ sb = dentry->d_sb;
e49829fe 8684+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 8685+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
8686+ if (unlikely(err))
8687+ goto out;
1facf9fc 8688+
4a4d8108
AM
8689+ h_file = au_hf_top(file);
8690+ err = vfsub_read_u(h_file, buf, count, ppos);
8691+ /* todo: necessary? */
8692+ /* file->f_ra = h_file->f_ra; */
8693+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1308ab2a 8694+
4a4d8108
AM
8695+ di_read_unlock(dentry, AuLock_IR);
8696+ fi_read_unlock(file);
4f0767ce 8697+out:
dece6358
AM
8698+ si_read_unlock(sb);
8699+ return err;
8700+}
1facf9fc 8701+
e49829fe
JR
8702+/*
8703+ * todo: very ugly
8704+ * it locks both of i_mutex and si_rwsem for read in safe.
8705+ * if the plink maintenance mode continues forever (that is the problem),
8706+ * may loop forever.
8707+ */
8708+static void au_mtx_and_read_lock(struct inode *inode)
8709+{
8710+ int err;
8711+ struct super_block *sb = inode->i_sb;
8712+
8713+ while (1) {
8714+ mutex_lock(&inode->i_mutex);
8715+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
8716+ if (!err)
8717+ break;
8718+ mutex_unlock(&inode->i_mutex);
8719+ si_read_lock(sb, AuLock_NOPLMW);
8720+ si_read_unlock(sb);
8721+ }
8722+}
8723+
4a4d8108
AM
8724+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
8725+ size_t count, loff_t *ppos)
dece6358 8726+{
4a4d8108
AM
8727+ ssize_t err;
8728+ struct au_pin pin;
dece6358 8729+ struct dentry *dentry;
4a4d8108 8730+ struct inode *inode;
4a4d8108
AM
8731+ struct file *h_file;
8732+ char __user *buf = (char __user *)ubuf;
1facf9fc 8733+
dece6358 8734+ dentry = file->f_dentry;
4a4d8108 8735+ inode = dentry->d_inode;
e49829fe 8736+ au_mtx_and_read_lock(inode);
1facf9fc 8737+
4a4d8108
AM
8738+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
8739+ if (unlikely(err))
8740+ goto out;
1facf9fc 8741+
4a4d8108
AM
8742+ err = au_ready_to_write(file, -1, &pin);
8743+ di_downgrade_lock(dentry, AuLock_IR);
8744+ if (unlikely(err))
8745+ goto out_unlock;
1facf9fc 8746+
4a4d8108
AM
8747+ h_file = au_hf_top(file);
8748+ au_unpin(&pin);
8749+ err = vfsub_write_u(h_file, buf, count, ppos);
8750+ au_cpup_attr_timesizes(inode);
8751+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 8752+
4f0767ce 8753+out_unlock:
4a4d8108
AM
8754+ di_read_unlock(dentry, AuLock_IR);
8755+ fi_write_unlock(file);
4f0767ce 8756+out:
e49829fe 8757+ si_read_unlock(inode->i_sb);
4a4d8108 8758+ mutex_unlock(&inode->i_mutex);
dece6358
AM
8759+ return err;
8760+}
1facf9fc 8761+
4a4d8108
AM
8762+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
8763+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 8764+{
4a4d8108
AM
8765+ ssize_t err;
8766+ struct file *file;
8767+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
8768+ loff_t);
1facf9fc 8769+
4a4d8108
AM
8770+ err = security_file_permission(h_file, rw);
8771+ if (unlikely(err))
8772+ goto out;
1facf9fc 8773+
4a4d8108
AM
8774+ err = -ENOSYS;
8775+ func = NULL;
8776+ if (rw == MAY_READ)
8777+ func = h_file->f_op->aio_read;
8778+ else if (rw == MAY_WRITE)
8779+ func = h_file->f_op->aio_write;
8780+ if (func) {
8781+ file = kio->ki_filp;
8782+ kio->ki_filp = h_file;
8783+ err = func(kio, iov, nv, pos);
8784+ kio->ki_filp = file;
8785+ } else
8786+ /* currently there is no such fs */
8787+ WARN_ON_ONCE(1);
1facf9fc 8788+
4f0767ce 8789+out:
dece6358
AM
8790+ return err;
8791+}
1facf9fc 8792+
4a4d8108
AM
8793+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
8794+ unsigned long nv, loff_t pos)
1facf9fc 8795+{
4a4d8108
AM
8796+ ssize_t err;
8797+ struct file *file, *h_file;
8798+ struct dentry *dentry;
dece6358 8799+ struct super_block *sb;
1facf9fc 8800+
4a4d8108 8801+ file = kio->ki_filp;
dece6358 8802+ dentry = file->f_dentry;
1308ab2a 8803+ sb = dentry->d_sb;
e49829fe 8804+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
8805+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
8806+ if (unlikely(err))
8807+ goto out;
8808+
8809+ h_file = au_hf_top(file);
8810+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
8811+ /* todo: necessary? */
8812+ /* file->f_ra = h_file->f_ra; */
8813+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
8814+ di_read_unlock(dentry, AuLock_IR);
8815+ fi_read_unlock(file);
1facf9fc 8816+
4f0767ce 8817+out:
4a4d8108 8818+ si_read_unlock(sb);
1308ab2a 8819+ return err;
8820+}
1facf9fc 8821+
4a4d8108
AM
8822+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
8823+ unsigned long nv, loff_t pos)
1308ab2a 8824+{
4a4d8108
AM
8825+ ssize_t err;
8826+ struct au_pin pin;
8827+ struct dentry *dentry;
8828+ struct inode *inode;
4a4d8108 8829+ struct file *file, *h_file;
1308ab2a 8830+
4a4d8108 8831+ file = kio->ki_filp;
1308ab2a 8832+ dentry = file->f_dentry;
1308ab2a 8833+ inode = dentry->d_inode;
e49829fe
JR
8834+ au_mtx_and_read_lock(inode);
8835+
4a4d8108
AM
8836+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
8837+ if (unlikely(err))
1308ab2a 8838+ goto out;
1facf9fc 8839+
4a4d8108
AM
8840+ err = au_ready_to_write(file, -1, &pin);
8841+ di_downgrade_lock(dentry, AuLock_IR);
dece6358 8842+ if (unlikely(err))
4a4d8108 8843+ goto out_unlock;
1facf9fc 8844+
4a4d8108
AM
8845+ au_unpin(&pin);
8846+ h_file = au_hf_top(file);
8847+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
8848+ au_cpup_attr_timesizes(inode);
8849+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 8850+
4f0767ce 8851+out_unlock:
4a4d8108
AM
8852+ di_read_unlock(dentry, AuLock_IR);
8853+ fi_write_unlock(file);
4f0767ce 8854+out:
e49829fe 8855+ si_read_unlock(inode->i_sb);
4a4d8108 8856+ mutex_unlock(&inode->i_mutex);
dece6358 8857+ return err;
1facf9fc 8858+}
8859+
4a4d8108
AM
8860+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
8861+ struct pipe_inode_info *pipe, size_t len,
8862+ unsigned int flags)
1facf9fc 8863+{
4a4d8108
AM
8864+ ssize_t err;
8865+ struct file *h_file;
8866+ struct dentry *dentry;
dece6358 8867+ struct super_block *sb;
1facf9fc 8868+
dece6358 8869+ dentry = file->f_dentry;
dece6358 8870+ sb = dentry->d_sb;
e49829fe 8871+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
8872+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
8873+ if (unlikely(err))
dece6358 8874+ goto out;
1facf9fc 8875+
4a4d8108
AM
8876+ err = -EINVAL;
8877+ h_file = au_hf_top(file);
8878+ if (au_test_loopback_kthread()) {
8879+ file->f_mapping = h_file->f_mapping;
8880+ smp_mb(); /* unnecessary? */
1308ab2a 8881+ }
4a4d8108
AM
8882+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
8883+ /* todo: necessasry? */
8884+ /* file->f_ra = h_file->f_ra; */
8885+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 8886+
4a4d8108
AM
8887+ di_read_unlock(dentry, AuLock_IR);
8888+ fi_read_unlock(file);
1facf9fc 8889+
4f0767ce 8890+out:
4a4d8108 8891+ si_read_unlock(sb);
dece6358 8892+ return err;
1facf9fc 8893+}
8894+
4a4d8108
AM
8895+static ssize_t
8896+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
8897+ size_t len, unsigned int flags)
1facf9fc 8898+{
4a4d8108
AM
8899+ ssize_t err;
8900+ struct au_pin pin;
8901+ struct dentry *dentry;
8902+ struct inode *inode;
4a4d8108 8903+ struct file *h_file;
1facf9fc 8904+
4a4d8108
AM
8905+ dentry = file->f_dentry;
8906+ inode = dentry->d_inode;
e49829fe 8907+ au_mtx_and_read_lock(inode);
4a4d8108
AM
8908+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
8909+ if (unlikely(err))
8910+ goto out;
1facf9fc 8911+
4a4d8108
AM
8912+ err = au_ready_to_write(file, -1, &pin);
8913+ di_downgrade_lock(dentry, AuLock_IR);
8914+ if (unlikely(err))
8915+ goto out_unlock;
1facf9fc 8916+
4a4d8108
AM
8917+ h_file = au_hf_top(file);
8918+ au_unpin(&pin);
8919+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
8920+ au_cpup_attr_timesizes(inode);
8921+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 8922+
4f0767ce 8923+out_unlock:
4a4d8108
AM
8924+ di_read_unlock(dentry, AuLock_IR);
8925+ fi_write_unlock(file);
4f0767ce 8926+out:
e49829fe 8927+ si_read_unlock(inode->i_sb);
4a4d8108
AM
8928+ mutex_unlock(&inode->i_mutex);
8929+ return err;
8930+}
1facf9fc 8931+
4a4d8108
AM
8932+/* ---------------------------------------------------------------------- */
8933+
8934+static struct file *au_safe_file(struct vm_area_struct *vma)
8935+{
8936+ struct file *file;
8937+
8938+ file = vma->vm_file;
8939+ if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
8940+ return file;
8941+ return NULL;
1facf9fc 8942+}
8943+
4a4d8108 8944+static void au_reset_file(struct vm_area_struct *vma, struct file *file)
1facf9fc 8945+{
4a4d8108
AM
8946+ vma->vm_file = file;
8947+ /* smp_mb(); */ /* flush vm_file */
8948+}
1facf9fc 8949+
4a4d8108
AM
8950+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
8951+{
8952+ int err;
8953+ static DECLARE_WAIT_QUEUE_HEAD(wq);
8954+ struct file *file, *h_file;
8955+ struct au_finfo *finfo;
1facf9fc 8956+
4a4d8108
AM
8957+ /* todo: non-robr mode, user vm_file as it is? */
8958+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 8959+
4a4d8108
AM
8960+ /* do not revalidate, no si lock */
8961+ finfo = au_fi(file);
8962+ AuDebugOn(finfo->fi_hdir);
8963+ h_file = finfo->fi_htop.hf_file;
8964+ AuDebugOn(!h_file || !finfo->fi_hvmop);
8965+
8966+ mutex_lock(&finfo->fi_vm_mtx);
8967+ vma->vm_file = h_file;
8968+ err = finfo->fi_hvmop->fault(vma, vmf);
8969+ /* todo: necessary? */
8970+ /* file->f_ra = h_file->f_ra; */
8971+ au_reset_file(vma, file);
8972+ mutex_unlock(&finfo->fi_vm_mtx);
8973+#if 0 /* def CONFIG_SMP */
8974+ /* wake_up_nr(&wq, online_cpu - 1); */
8975+ wake_up_all(&wq);
8976+#else
8977+ wake_up(&wq);
8978+#endif
1facf9fc 8979+
dece6358 8980+ return err;
1facf9fc 8981+}
8982+
4a4d8108 8983+static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
1facf9fc 8984+{
dece6358 8985+ int err;
4a4d8108
AM
8986+ static DECLARE_WAIT_QUEUE_HEAD(wq);
8987+ struct file *file, *h_file;
8988+ struct au_finfo *finfo;
1facf9fc 8989+
4a4d8108 8990+ wait_event(wq, (file = au_safe_file(vma)));
1facf9fc 8991+
4a4d8108
AM
8992+ finfo = au_fi(file);
8993+ AuDebugOn(finfo->fi_hdir);
8994+ h_file = finfo->fi_htop.hf_file;
8995+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 8996+
4a4d8108
AM
8997+ mutex_lock(&finfo->fi_vm_mtx);
8998+ vma->vm_file = h_file;
8999+ err = finfo->fi_hvmop->page_mkwrite(vma, vmf);
9000+ au_reset_file(vma, file);
9001+ mutex_unlock(&finfo->fi_vm_mtx);
9002+ wake_up(&wq);
1308ab2a 9003+
dece6358 9004+ return err;
1facf9fc 9005+}
9006+
4a4d8108 9007+static void aufs_vm_close(struct vm_area_struct *vma)
1facf9fc 9008+{
4a4d8108
AM
9009+ static DECLARE_WAIT_QUEUE_HEAD(wq);
9010+ struct file *file, *h_file;
9011+ struct au_finfo *finfo;
dece6358 9012+
4a4d8108 9013+ wait_event(wq, (file = au_safe_file(vma)));
dece6358 9014+
4a4d8108
AM
9015+ finfo = au_fi(file);
9016+ AuDebugOn(finfo->fi_hdir);
9017+ h_file = finfo->fi_htop.hf_file;
9018+ AuDebugOn(!h_file || !finfo->fi_hvmop);
1facf9fc 9019+
4a4d8108
AM
9020+ mutex_lock(&finfo->fi_vm_mtx);
9021+ vma->vm_file = h_file;
9022+ finfo->fi_hvmop->close(vma);
9023+ au_reset_file(vma, file);
9024+ mutex_unlock(&finfo->fi_vm_mtx);
9025+ wake_up(&wq);
9026+}
1facf9fc 9027+
4a4d8108
AM
9028+const struct vm_operations_struct aufs_vm_ops = {
9029+ .close = aufs_vm_close,
9030+ .fault = aufs_fault,
9031+ .page_mkwrite = aufs_page_mkwrite
1308ab2a 9032+};
dece6358 9033+
1308ab2a 9034+/* ---------------------------------------------------------------------- */
1facf9fc 9035+
4a4d8108
AM
9036+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
9037+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
1308ab2a 9038+
4a4d8108 9039+static unsigned long au_arch_prot_conv(unsigned long flags)
dece6358 9040+{
4a4d8108
AM
9041+ /* currently ppc64 only */
9042+#ifdef CONFIG_PPC64
9043+ /* cf. linux/arch/powerpc/include/asm/mman.h */
9044+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
9045+ return AuConv_VM_PROT(flags, SAO);
9046+#else
9047+ AuDebugOn(arch_calc_vm_prot_bits(-1));
9048+ return 0;
9049+#endif
dece6358
AM
9050+}
9051+
4a4d8108 9052+static unsigned long au_prot_conv(unsigned long flags)
dece6358 9053+{
4a4d8108
AM
9054+ return AuConv_VM_PROT(flags, READ)
9055+ | AuConv_VM_PROT(flags, WRITE)
9056+ | AuConv_VM_PROT(flags, EXEC)
9057+ | au_arch_prot_conv(flags);
dece6358
AM
9058+}
9059+
4a4d8108
AM
9060+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
9061+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
dece6358 9062+
4a4d8108 9063+static unsigned long au_flag_conv(unsigned long flags)
dece6358 9064+{
4a4d8108
AM
9065+ return AuConv_VM_MAP(flags, GROWSDOWN)
9066+ | AuConv_VM_MAP(flags, DENYWRITE)
9067+ | AuConv_VM_MAP(flags, EXECUTABLE)
9068+ | AuConv_VM_MAP(flags, LOCKED);
dece6358
AM
9069+}
9070+
4a4d8108
AM
9071+static struct vm_operations_struct *
9072+au_hvmop(struct file *h_file, struct vm_area_struct *vma, unsigned long *flags)
dece6358 9073+{
4a4d8108
AM
9074+ struct vm_operations_struct *h_vmop;
9075+ unsigned long prot;
9076+ int err;
dece6358 9077+
4a4d8108
AM
9078+ h_vmop = ERR_PTR(-ENODEV);
9079+ if (!h_file->f_op || !h_file->f_op->mmap)
9080+ goto out;
dece6358 9081+
4a4d8108
AM
9082+ prot = au_prot_conv(vma->vm_flags);
9083+ err = security_file_mmap(h_file, /*reqprot*/prot, prot,
9084+ au_flag_conv(vma->vm_flags), vma->vm_start, 0);
9085+ h_vmop = ERR_PTR(err);
9086+ if (unlikely(err))
9087+ goto out;
dece6358 9088+
4a4d8108
AM
9089+ err = h_file->f_op->mmap(h_file, vma);
9090+ h_vmop = ERR_PTR(err);
9091+ if (unlikely(err))
9092+ goto out;
dece6358 9093+
4a4d8108
AM
9094+ /* oops, it became 'const' */
9095+ h_vmop = (struct vm_operations_struct *)vma->vm_ops;
9096+ *flags = vma->vm_flags;
9097+ err = do_munmap(current->mm, vma->vm_start,
9098+ vma->vm_end - vma->vm_start);
9099+ if (unlikely(err)) {
9100+ AuIOErr("failed internal unmapping %.*s, %d\n",
9101+ AuDLNPair(h_file->f_dentry), err);
9102+ h_vmop = ERR_PTR(-EIO);
9103+ }
dece6358 9104+
4f0767ce 9105+out:
4a4d8108 9106+ return h_vmop;
dece6358
AM
9107+}
9108+
1308ab2a 9109+/*
4a4d8108
AM
9110+ * This is another ugly approach to keep the lock order, particularly
9111+ * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
9112+ * find it in git-log, if you want.
1308ab2a 9113+ *
4a4d8108
AM
9114+ * native readdir: i_mutex, copy_to_user, mmap_sem
9115+ * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
1308ab2a 9116+ *
4a4d8108
AM
9117+ * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
9118+ * acquire aufs rwsem. It introduces a circular locking dependency.
9119+ * To address this problem, aufs_mmap() delegates the part which requires aufs
9120+ * rwsem to its internal workqueue.
1308ab2a 9121+ */
9122+
4a4d8108
AM
9123+/* very ugly approach */
9124+#include "mtx.h"
1308ab2a 9125+
4a4d8108
AM
9126+struct au_mmap_pre_args {
9127+ /* input */
9128+ struct file *file;
9129+ struct vm_area_struct *vma;
1308ab2a 9130+
4a4d8108
AM
9131+ /* output */
9132+ int *errp;
9133+ struct file *h_file;
9134+ struct au_branch *br;
9135+ int mmapped;
9136+};
dece6358 9137+
4a4d8108
AM
9138+static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
9139+ struct file **h_file, struct au_branch **br,
9140+ int *mmapped)
dece6358 9141+{
4a4d8108
AM
9142+ int err;
9143+ aufs_bindex_t bstart;
9144+ const unsigned char wlock
9145+ = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
9146+ struct dentry *dentry;
9147+ struct super_block *sb;
1308ab2a 9148+
4a4d8108
AM
9149+ dentry = file->f_dentry;
9150+ sb = dentry->d_sb;
e49829fe 9151+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108
AM
9152+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9153+ if (unlikely(err))
9154+ goto out;
9155+
9156+ *mmapped = !!au_test_mmapped(file);
9157+ if (wlock) {
9158+ struct au_pin pin;
9159+
9160+ err = au_ready_to_write(file, -1, &pin);
9161+ di_write_unlock(dentry);
9162+ if (unlikely(err))
9163+ goto out_unlock;
9164+ au_unpin(&pin);
9165+ } else
9166+ di_write_unlock(dentry);
9167+ bstart = au_fbstart(file);
9168+ *br = au_sbr(sb, bstart);
9169+ *h_file = au_hf_top(file);
9170+ get_file(*h_file);
9171+ au_fi_mmap_lock(file);
9172+
9173+out_unlock:
9174+ fi_write_unlock(file);
9175+out:
9176+ si_read_unlock(sb);
9177+ return err;
dece6358
AM
9178+}
9179+
4a4d8108 9180+static void au_call_mmap_pre(void *args)
dece6358 9181+{
4a4d8108
AM
9182+ struct au_mmap_pre_args *a = args;
9183+ *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->br,
9184+ &a->mmapped);
dece6358
AM
9185+}
9186+
4a4d8108 9187+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 9188+{
4a4d8108
AM
9189+ int err, wkq_err;
9190+ unsigned long h_vmflags;
1308ab2a 9191+ struct au_finfo *finfo;
4a4d8108
AM
9192+ struct dentry *h_dentry;
9193+ struct vm_operations_struct *h_vmop, *vmop;
9194+ struct au_mmap_pre_args args = {
9195+ .file = file,
9196+ .vma = vma,
9197+ .errp = &err
9198+ };
9199+
b752ccd1 9200+ wkq_err = au_wkq_wait_pre(au_call_mmap_pre, &args);
4a4d8108
AM
9201+ if (unlikely(wkq_err))
9202+ err = wkq_err;
9203+ if (unlikely(err))
9204+ goto out;
9205+ finfo = au_fi(file);
9206+ mutex_set_owner(&finfo->fi_mmap);
9207+
9208+ h_dentry = args.h_file->f_dentry;
9209+ if (!args.mmapped && au_test_fs_bad_mapping(h_dentry->d_sb)) {
1308ab2a 9210+ /*
4a4d8108
AM
9211+ * by this assignment, f_mapping will differs from aufs inode
9212+ * i_mapping.
9213+ * if someone else mixes the use of f_dentry->d_inode and
9214+ * f_mapping->host, then a problem may arise.
1308ab2a 9215+ */
4a4d8108
AM
9216+ file->f_mapping = args.h_file->f_mapping;
9217+ }
1308ab2a 9218+
4a4d8108
AM
9219+ /* always try this internal mmap to get vma flags */
9220+ h_vmflags = 0; /* gcc warning */
9221+ h_vmop = au_hvmop(args.h_file, vma, &h_vmflags);
9222+ err = PTR_ERR(h_vmop);
9223+ if (IS_ERR(h_vmop))
9224+ goto out_unlock;
9225+ AuDebugOn(args.mmapped && h_vmop != finfo->fi_hvmop);
9226+
9227+ vmop = (void *)au_dy_vmop(file, args.br, h_vmop);
9228+ err = PTR_ERR(vmop);
9229+ if (IS_ERR(vmop))
9230+ goto out_unlock;
9231+
9232+ /*
9233+ * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
9234+ * currently MAP_DENYWRITE from userspace is ignored, but elf loader
9235+ * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
9236+ * both of the aufs file and the lower file is deny_write_access()-ed.
9237+ * finally I hope we can skip handlling MAP_DENYWRITE here.
9238+ */
9239+ err = generic_file_mmap(file, vma);
9240+ if (unlikely(err))
9241+ goto out_unlock;
9242+
9243+ vma->vm_ops = vmop;
9244+ vma->vm_flags = h_vmflags;
9245+ if (!args.mmapped)
9246+ finfo->fi_hvmop = h_vmop;
9247+
9248+ vfsub_file_accessed(args.h_file);
9249+ /* update without lock, I don't think it a problem */
9250+ fsstack_copy_attr_atime(file->f_dentry->d_inode, h_dentry->d_inode);
9251+
4f0767ce 9252+out_unlock:
4a4d8108
AM
9253+ au_fi_mmap_unlock(file);
9254+ fput(args.h_file);
4f0767ce 9255+out:
4a4d8108
AM
9256+ return err;
9257+}
9258+
9259+/* ---------------------------------------------------------------------- */
9260+
b752ccd1 9261+static int aufs_fsync_nondir(struct file *file, int datasync)
4a4d8108
AM
9262+{
9263+ int err;
9264+ struct au_pin pin;
b752ccd1 9265+ struct dentry *dentry;
4a4d8108
AM
9266+ struct inode *inode;
9267+ struct file *h_file;
9268+ struct super_block *sb;
9269+
b752ccd1 9270+ dentry = file->f_dentry;
4a4d8108
AM
9271+ inode = dentry->d_inode;
9272+ IMustLock(file->f_mapping->host);
9273+ if (inode != file->f_mapping->host) {
9274+ mutex_unlock(&file->f_mapping->host->i_mutex);
9275+ mutex_lock(&inode->i_mutex);
9276+ }
9277+ IMustLock(inode);
9278+
9279+ sb = dentry->d_sb;
e49829fe
JR
9280+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
9281+ if (unlikely(err))
9282+ goto out;
4a4d8108
AM
9283+
9284+ err = 0; /* -EBADF; */ /* posix? */
9285+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
e49829fe 9286+ goto out_si;
4a4d8108
AM
9287+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9288+ if (unlikely(err))
e49829fe 9289+ goto out_si;
4a4d8108
AM
9290+
9291+ err = au_ready_to_write(file, -1, &pin);
9292+ di_downgrade_lock(dentry, AuLock_IR);
9293+ if (unlikely(err))
9294+ goto out_unlock;
9295+ au_unpin(&pin);
9296+
9297+ err = -EINVAL;
9298+ h_file = au_hf_top(file);
9299+ if (h_file->f_op && h_file->f_op->fsync) {
4a4d8108
AM
9300+ struct mutex *h_mtx;
9301+
9302+ /*
9303+ * no filemap_fdatawrite() since aufs file has no its own
9304+ * mapping, but dir.
9305+ */
b752ccd1 9306+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
4a4d8108 9307+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
b752ccd1 9308+ err = h_file->f_op->fsync(h_file, datasync);
4a4d8108
AM
9309+ if (!err)
9310+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9311+ /*ignore*/
9312+ au_cpup_attr_timesizes(inode);
9313+ mutex_unlock(h_mtx);
9314+ }
9315+
4f0767ce 9316+out_unlock:
4a4d8108 9317+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 9318+ fi_write_unlock(file);
e49829fe 9319+out_si:
953406b4 9320+ si_read_unlock(sb);
e49829fe 9321+out:
4a4d8108
AM
9322+ if (inode != file->f_mapping->host) {
9323+ mutex_unlock(&inode->i_mutex);
9324+ mutex_lock(&file->f_mapping->host->i_mutex);
9325+ }
9326+ return err;
dece6358
AM
9327+}
9328+
4a4d8108
AM
9329+/* no one supports this operation, currently */
9330+#if 0
9331+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 9332+{
4a4d8108
AM
9333+ int err;
9334+ struct au_pin pin;
1308ab2a 9335+ struct dentry *dentry;
4a4d8108
AM
9336+ struct inode *inode;
9337+ struct file *file, *h_file;
1308ab2a 9338+
4a4d8108 9339+ file = kio->ki_filp;
1308ab2a 9340+ dentry = file->f_dentry;
4a4d8108 9341+ inode = dentry->d_inode;
e49829fe 9342+ au_mtx_and_read_lock(inode);
4a4d8108
AM
9343+
9344+ err = 0; /* -EBADF; */ /* posix? */
9345+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
9346+ goto out;
9347+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9348+ if (unlikely(err))
1308ab2a 9349+ goto out;
9350+
4a4d8108
AM
9351+ err = au_ready_to_write(file, -1, &pin);
9352+ di_downgrade_lock(dentry, AuLock_IR);
9353+ if (unlikely(err))
9354+ goto out_unlock;
9355+ au_unpin(&pin);
1308ab2a 9356+
4a4d8108
AM
9357+ err = -ENOSYS;
9358+ h_file = au_hf_top(file);
9359+ if (h_file->f_op && h_file->f_op->aio_fsync) {
9360+ struct dentry *h_d;
9361+ struct mutex *h_mtx;
1308ab2a 9362+
4a4d8108
AM
9363+ h_d = h_file->f_dentry;
9364+ h_mtx = &h_d->d_inode->i_mutex;
9365+ if (!is_sync_kiocb(kio)) {
9366+ get_file(h_file);
9367+ fput(file);
9368+ }
9369+ kio->ki_filp = h_file;
9370+ err = h_file->f_op->aio_fsync(kio, datasync);
9371+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
9372+ if (!err)
9373+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
9374+ /*ignore*/
9375+ au_cpup_attr_timesizes(inode);
9376+ mutex_unlock(h_mtx);
9377+ }
1308ab2a 9378+
4f0767ce 9379+out_unlock:
4a4d8108
AM
9380+ di_read_unlock(dentry, AuLock_IR);
9381+ fi_write_unlock(file);
4f0767ce 9382+out:
e49829fe 9383+ si_read_unlock(inode->sb);
4a4d8108
AM
9384+ mutex_unlock(&inode->i_mutex);
9385+ return err;
dece6358 9386+}
4a4d8108 9387+#endif
dece6358 9388+
4a4d8108 9389+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 9390+{
4a4d8108
AM
9391+ int err;
9392+ struct file *h_file;
9393+ struct dentry *dentry;
9394+ struct super_block *sb;
1308ab2a 9395+
4a4d8108
AM
9396+ dentry = file->f_dentry;
9397+ sb = dentry->d_sb;
e49829fe 9398+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9399+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9400+ if (unlikely(err))
9401+ goto out;
9402+
9403+ h_file = au_hf_top(file);
9404+ if (h_file->f_op && h_file->f_op->fasync)
9405+ err = h_file->f_op->fasync(fd, h_file, flag);
9406+
9407+ di_read_unlock(dentry, AuLock_IR);
9408+ fi_read_unlock(file);
1308ab2a 9409+
4f0767ce 9410+out:
4a4d8108 9411+ si_read_unlock(sb);
1308ab2a 9412+ return err;
dece6358 9413+}
4a4d8108
AM
9414+
9415+/* ---------------------------------------------------------------------- */
9416+
9417+/* no one supports this operation, currently */
9418+#if 0
9419+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
9420+ size_t len, loff_t *pos , int more)
9421+{
9422+}
9423+#endif
9424+
9425+/* ---------------------------------------------------------------------- */
9426+
9427+const struct file_operations aufs_file_fop = {
9428+ .owner = THIS_MODULE,
9429+ /*
9430+ * while generic_file_llseek/_unlocked() don't use BKL,
9431+ * don't use it since it operates file->f_mapping->host.
9432+ * in aufs, it may be a real file and may confuse users by UDBA.
9433+ */
9434+ /* .llseek = generic_file_llseek, */
9435+
9436+ .read = aufs_read,
9437+ .write = aufs_write,
9438+ .aio_read = aufs_aio_read,
9439+ .aio_write = aufs_aio_write,
9440+#ifdef CONFIG_AUFS_POLL
9441+ .poll = aufs_poll,
9442+#endif
9443+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
9444+#ifdef CONFIG_COMPAT
9445+ .compat_ioctl = aufs_ioctl_nondir, /* same */
9446+#endif
4a4d8108
AM
9447+ .mmap = aufs_mmap,
9448+ .open = aufs_open_nondir,
9449+ .flush = aufs_flush_nondir,
9450+ .release = aufs_release_nondir,
9451+ .fsync = aufs_fsync_nondir,
9452+ /* .aio_fsync = aufs_aio_fsync_nondir, */
9453+ .fasync = aufs_fasync,
9454+ /* .sendpage = aufs_sendpage, */
9455+ .splice_write = aufs_splice_write,
9456+ .splice_read = aufs_splice_read,
9457+#if 0
9458+ .aio_splice_write = aufs_aio_splice_write,
9459+ .aio_splice_read = aufs_aio_splice_read
9460+#endif
9461+};
e49829fe 9462--- /dev/null
0c5527e5 9463+++ linux-2.6/fs/aufs/f_op_sp.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 9464@@ -0,0 +1,299 @@
1308ab2a 9465+/*
4a4d8108 9466+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 9467+ *
9468+ * This program, aufs is free software; you can redistribute it and/or modify
9469+ * it under the terms of the GNU General Public License as published by
9470+ * the Free Software Foundation; either version 2 of the License, or
9471+ * (at your option) any later version.
9472+ *
9473+ * This program is distributed in the hope that it will be useful,
9474+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9475+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9476+ * GNU General Public License for more details.
9477+ *
9478+ * You should have received a copy of the GNU General Public License
9479+ * along with this program; if not, write to the Free Software
9480+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9481+ */
dece6358 9482+
1308ab2a 9483+/*
4a4d8108
AM
9484+ * file operations for special files.
9485+ * while they exist in aufs virtually,
9486+ * their file I/O is handled out of aufs.
1308ab2a 9487+ */
9488+
4a4d8108
AM
9489+#include <linux/fs_stack.h>
9490+#include "aufs.h"
1308ab2a 9491+
4a4d8108
AM
9492+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
9493+ unsigned long nv, loff_t pos)
dece6358 9494+{
4a4d8108
AM
9495+ ssize_t err;
9496+ aufs_bindex_t bstart;
9497+ unsigned char wbr;
9498+ struct file *file, *h_file;
9499+ struct super_block *sb;
1308ab2a 9500+
4a4d8108
AM
9501+ file = kio->ki_filp;
9502+ sb = file->f_dentry->d_sb;
9503+ si_read_lock(sb, AuLock_FLUSH);
9504+ fi_read_lock(file);
9505+ bstart = au_fbstart(file);
9506+ h_file = au_hf_top(file);
9507+ fi_read_unlock(file);
9508+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9509+ si_read_unlock(sb);
9510+
9511+ /* do not change the file in kio */
9512+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
9513+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
9514+ if (err > 0 && wbr)
9515+ file_accessed(h_file);
9516+
9517+ return err;
9518+}
9519+
9520+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
9521+ unsigned long nv, loff_t pos)
9522+{
9523+ ssize_t err;
9524+ aufs_bindex_t bstart;
9525+ unsigned char wbr;
9526+ struct super_block *sb;
9527+ struct file *file, *h_file;
9528+
9529+ file = kio->ki_filp;
9530+ sb = file->f_dentry->d_sb;
9531+ si_read_lock(sb, AuLock_FLUSH);
9532+ fi_read_lock(file);
9533+ bstart = au_fbstart(file);
9534+ h_file = au_hf_top(file);
9535+ fi_read_unlock(file);
9536+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
9537+ si_read_unlock(sb);
9538+
9539+ /* do not change the file in kio */
9540+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
9541+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
9542+ if (err > 0 && wbr)
9543+ file_update_time(h_file);
9544+
9545+ return err;
9546+}
9547+
9548+/* ---------------------------------------------------------------------- */
9549+
9550+static int aufs_release_sp(struct inode *inode, struct file *file)
9551+{
9552+ int err;
9553+ struct file *h_file;
9554+
9555+ fi_read_lock(file);
9556+ h_file = au_hf_top(file);
9557+ fi_read_unlock(file);
9558+ /* close this fifo in aufs */
9559+ err = h_file->f_op->release(inode, file); /* ignore */
9560+ aufs_release_nondir(inode, file); /* ignore */
9561+ return err;
9562+}
9563+
9564+/* ---------------------------------------------------------------------- */
9565+
9566+/* currently, support only FIFO */
4f0767ce
JR
9567+enum {
9568+ AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
9569+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
9570+ AuSp_Last
9571+};
4a4d8108
AM
9572+static int aufs_open_sp(struct inode *inode, struct file *file);
9573+static struct au_sp_fop {
9574+ int done;
9575+ struct file_operations fop; /* not 'const' */
9576+ spinlock_t spin;
9577+} au_sp_fop[AuSp_Last] = {
9578+ [AuSp_FIFO] = {
9579+ .fop = {
9580+ .owner = THIS_MODULE,
9581+ .open = aufs_open_sp
9582+ }
9583+ }
9584+};
9585+
9586+static void au_init_fop_sp(struct file *file)
9587+{
9588+ struct au_sp_fop *p;
9589+ int i;
9590+ struct file *h_file;
9591+
9592+ p = au_sp_fop;
9593+ if (unlikely(!p->done)) {
9594+ /* initialize first time only */
9595+ static DEFINE_SPINLOCK(spin);
9596+
9597+ spin_lock(&spin);
9598+ if (!p->done) {
9599+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
9600+ != AuSp_Last);
9601+ for (i = 0; i < AuSp_Last; i++)
9602+ spin_lock_init(&p[i].spin);
9603+ p->done = 1;
9604+ }
9605+ spin_unlock(&spin);
9606+ }
9607+
9608+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
9609+ case FMODE_READ:
9610+ i = AuSp_FIFO_R;
9611+ break;
9612+ case FMODE_WRITE:
9613+ i = AuSp_FIFO_W;
9614+ break;
9615+ case FMODE_READ | FMODE_WRITE:
9616+ i = AuSp_FIFO_RW;
9617+ break;
9618+ default:
9619+ BUG();
9620+ }
9621+
9622+ p += i;
9623+ if (unlikely(!p->done)) {
9624+ /* initialize first time only */
9625+ h_file = au_hf_top(file);
9626+ spin_lock(&p->spin);
9627+ if (!p->done) {
9628+ p->fop = *h_file->f_op;
9629+ p->fop.owner = THIS_MODULE;
9630+ if (p->fop.aio_read)
9631+ p->fop.aio_read = aufs_aio_read_sp;
9632+ if (p->fop.aio_write)
9633+ p->fop.aio_write = aufs_aio_write_sp;
9634+ p->fop.release = aufs_release_sp;
9635+ p->done = 1;
9636+ }
9637+ spin_unlock(&p->spin);
9638+ }
9639+ file->f_op = &p->fop;
9640+}
9641+
9642+static int au_cpup_sp(struct dentry *dentry)
9643+{
9644+ int err;
9645+ aufs_bindex_t bcpup;
9646+ struct au_pin pin;
9647+ struct au_wr_dir_args wr_dir_args = {
9648+ .force_btgt = -1,
9649+ .flags = 0
9650+ };
9651+
9652+ AuDbg("%.*s\n", AuDLNPair(dentry));
9653+
9654+ di_read_unlock(dentry, AuLock_IR);
9655+ di_write_lock_child(dentry);
9656+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
9657+ if (unlikely(err < 0))
9658+ goto out;
9659+ bcpup = err;
9660+ err = 0;
9661+ if (bcpup == au_dbstart(dentry))
9662+ goto out; /* success */
9663+
9664+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
9665+ AuPin_MNT_WRITE);
9666+ if (!err) {
9667+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
9668+ au_unpin(&pin);
9669+ }
9670+
4f0767ce 9671+out:
4a4d8108
AM
9672+ di_downgrade_lock(dentry, AuLock_IR);
9673+ return err;
9674+}
9675+
9676+static int au_do_open_sp(struct file *file, int flags)
9677+{
9678+ int err;
9679+ struct dentry *dentry;
9680+ struct super_block *sb;
9681+ struct file *h_file;
9682+ struct inode *h_inode;
9683+
9684+ dentry = file->f_dentry;
9685+ AuDbg("%.*s\n", AuDLNPair(dentry));
9686+
9687+ /*
9688+ * try copying-up.
9689+ * operate on the ro branch is not an error.
9690+ */
9691+ au_cpup_sp(dentry); /* ignore */
9692+
9693+ /* prepare h_file */
9694+ err = au_do_open_nondir(file, vfsub_file_flags(file));
9695+ if (unlikely(err))
9696+ goto out;
9697+
9698+ sb = dentry->d_sb;
9699+ h_file = au_hf_top(file);
9700+ h_inode = h_file->f_dentry->d_inode;
9701+ di_read_unlock(dentry, AuLock_IR);
9702+ fi_write_unlock(file);
9703+ si_read_unlock(sb);
9704+ /* open this fifo in aufs */
9705+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
9706+ si_noflush_read_lock(sb);
9707+ fi_write_lock(file);
9708+ di_read_lock_child(dentry, AuLock_IR);
9709+ if (!err)
9710+ au_init_fop_sp(file);
4a4d8108 9711+
4f0767ce 9712+out:
4a4d8108
AM
9713+ return err;
9714+}
9715+
9716+static int aufs_open_sp(struct inode *inode, struct file *file)
9717+{
9718+ int err;
9719+ struct super_block *sb;
9720+
9721+ sb = file->f_dentry->d_sb;
9722+ si_read_lock(sb, AuLock_FLUSH);
9723+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
9724+ si_read_unlock(sb);
9725+ return err;
9726+}
9727+
9728+/* ---------------------------------------------------------------------- */
9729+
9730+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
9731+{
9732+ init_special_inode(inode, mode, rdev);
9733+
9734+ switch (mode & S_IFMT) {
9735+ case S_IFIFO:
9736+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
9737+ /*FALLTHROUGH*/
9738+ case S_IFCHR:
9739+ case S_IFBLK:
9740+ case S_IFSOCK:
9741+ break;
9742+ default:
9743+ AuDebugOn(1);
9744+ }
9745+}
9746+
9747+int au_special_file(umode_t mode)
9748+{
9749+ int ret;
9750+
9751+ ret = 0;
9752+ switch (mode & S_IFMT) {
9753+ case S_IFIFO:
9754+#if 0
9755+ case S_IFCHR:
9756+ case S_IFBLK:
9757+ case S_IFSOCK:
9758+#endif
9759+ ret = 1;
9760+ }
9761+
9762+ return ret;
9763+}
e49829fe 9764--- /dev/null
0c5527e5 9765+++ linux-2.6/fs/aufs/fstype.h 2010-10-25 14:20:44.000000000 +0200
4a4d8108
AM
9766@@ -0,0 +1,497 @@
9767+/*
9768+ * Copyright (C) 2005-2010 Junjiro R. Okajima
9769+ *
9770+ * This program, aufs is free software; you can redistribute it and/or modify
9771+ * it under the terms of the GNU General Public License as published by
9772+ * the Free Software Foundation; either version 2 of the License, or
9773+ * (at your option) any later version.
9774+ *
9775+ * This program is distributed in the hope that it will be useful,
9776+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9777+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9778+ * GNU General Public License for more details.
9779+ *
9780+ * You should have received a copy of the GNU General Public License
9781+ * along with this program; if not, write to the Free Software
9782+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9783+ */
9784+
9785+/*
9786+ * judging filesystem type
9787+ */
9788+
9789+#ifndef __AUFS_FSTYPE_H__
9790+#define __AUFS_FSTYPE_H__
9791+
9792+#ifdef __KERNEL__
9793+
9794+#include <linux/fs.h>
9795+#include <linux/magic.h>
9796+#include <linux/romfs_fs.h>
9797+#include <linux/aufs_type.h>
9798+
9799+static inline int au_test_aufs(struct super_block *sb)
9800+{
9801+ return sb->s_magic == AUFS_SUPER_MAGIC;
9802+}
9803+
9804+static inline const char *au_sbtype(struct super_block *sb)
9805+{
9806+ return sb->s_type->name;
9807+}
1308ab2a 9808+
9809+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
9810+{
9811+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
9812+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
9813+#else
9814+ return 0;
9815+#endif
9816+}
9817+
1308ab2a 9818+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 9819+{
1308ab2a 9820+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
9821+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
9822+#else
9823+ return 0;
9824+#endif
9825+}
9826+
1308ab2a 9827+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 9828+{
1308ab2a 9829+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
9830+ return sb->s_magic == CRAMFS_MAGIC;
9831+#endif
9832+ return 0;
9833+}
9834+
9835+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
9836+{
9837+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
9838+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
9839+#else
9840+ return 0;
9841+#endif
9842+}
9843+
1308ab2a 9844+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 9845+{
1308ab2a 9846+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
9847+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
9848+#else
9849+ return 0;
9850+#endif
9851+}
9852+
1308ab2a 9853+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 9854+{
1308ab2a 9855+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
9856+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
9857+#else
9858+ return 0;
9859+#endif
9860+}
9861+
1308ab2a 9862+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 9863+{
1308ab2a 9864+#ifdef CONFIG_TMPFS
9865+ return sb->s_magic == TMPFS_MAGIC;
9866+#else
9867+ return 0;
dece6358 9868+#endif
dece6358
AM
9869+}
9870+
1308ab2a 9871+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 9872+{
1308ab2a 9873+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
9874+ return !strcmp(au_sbtype(sb), "ecryptfs");
9875+#else
9876+ return 0;
9877+#endif
1facf9fc 9878+}
9879+
1308ab2a 9880+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 9881+{
1308ab2a 9882+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
9883+ return sb->s_magic == SMB_SUPER_MAGIC;
9884+#else
9885+ return 0;
1facf9fc 9886+#endif
1facf9fc 9887+}
9888+
1308ab2a 9889+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 9890+{
1308ab2a 9891+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
9892+ return sb->s_magic == OCFS2_SUPER_MAGIC;
9893+#else
9894+ return 0;
9895+#endif
1facf9fc 9896+}
9897+
1308ab2a 9898+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 9899+{
1308ab2a 9900+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
9901+ return sb->s_magic == DLMFS_MAGIC;
9902+#else
9903+ return 0;
9904+#endif
1facf9fc 9905+}
9906+
1308ab2a 9907+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 9908+{
1308ab2a 9909+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
9910+ return sb->s_magic == CODA_SUPER_MAGIC;
9911+#else
9912+ return 0;
9913+#endif
9914+}
9915+
9916+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
9917+{
9918+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
9919+ return sb->s_magic == V9FS_MAGIC;
9920+#else
9921+ return 0;
9922+#endif
9923+}
9924+
9925+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
9926+{
9927+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
9928+ return sb->s_magic == EXT4_SUPER_MAGIC;
9929+#else
9930+ return 0;
9931+#endif
9932+}
9933+
9934+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
9935+{
9936+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
9937+ return !strcmp(au_sbtype(sb), "sysv");
9938+#else
9939+ return 0;
9940+#endif
9941+}
9942+
9943+static inline int au_test_ramfs(struct super_block *sb)
9944+{
9945+ return sb->s_magic == RAMFS_MAGIC;
9946+}
9947+
9948+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
9949+{
9950+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
9951+ return sb->s_magic == UBIFS_SUPER_MAGIC;
9952+#else
9953+ return 0;
9954+#endif
9955+}
9956+
9957+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
9958+{
9959+#ifdef CONFIG_PROC_FS
9960+ return sb->s_magic == PROC_SUPER_MAGIC;
9961+#else
9962+ return 0;
9963+#endif
9964+}
9965+
9966+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
9967+{
9968+#ifdef CONFIG_SYSFS
9969+ return sb->s_magic == SYSFS_MAGIC;
9970+#else
9971+ return 0;
9972+#endif
9973+}
9974+
9975+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
9976+{
9977+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
9978+ return sb->s_magic == CONFIGFS_MAGIC;
9979+#else
9980+ return 0;
9981+#endif
9982+}
9983+
9984+static inline int au_test_minix(struct super_block *sb __maybe_unused)
9985+{
9986+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
9987+ return sb->s_magic == MINIX3_SUPER_MAGIC
9988+ || sb->s_magic == MINIX2_SUPER_MAGIC
9989+ || sb->s_magic == MINIX2_SUPER_MAGIC2
9990+ || sb->s_magic == MINIX_SUPER_MAGIC
9991+ || sb->s_magic == MINIX_SUPER_MAGIC2;
9992+#else
9993+ return 0;
9994+#endif
9995+}
9996+
9997+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
9998+{
9999+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
10000+ return sb->s_magic == CIFS_MAGIC_NUMBER;
10001+#else
10002+ return 0;
10003+#endif
10004+}
10005+
10006+static inline int au_test_fat(struct super_block *sb __maybe_unused)
10007+{
10008+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
10009+ return sb->s_magic == MSDOS_SUPER_MAGIC;
10010+#else
10011+ return 0;
10012+#endif
10013+}
10014+
10015+static inline int au_test_msdos(struct super_block *sb)
10016+{
10017+ return au_test_fat(sb);
10018+}
10019+
10020+static inline int au_test_vfat(struct super_block *sb)
10021+{
10022+ return au_test_fat(sb);
10023+}
10024+
10025+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
10026+{
10027+#ifdef CONFIG_SECURITYFS
10028+ return sb->s_magic == SECURITYFS_MAGIC;
10029+#else
10030+ return 0;
10031+#endif
10032+}
10033+
10034+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
10035+{
10036+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
10037+ return sb->s_magic == SQUASHFS_MAGIC;
10038+#else
10039+ return 0;
10040+#endif
10041+}
10042+
10043+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
10044+{
10045+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
10046+ return sb->s_magic == BTRFS_SUPER_MAGIC;
10047+#else
10048+ return 0;
10049+#endif
10050+}
10051+
10052+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
10053+{
10054+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
10055+ return sb->s_magic == XENFS_SUPER_MAGIC;
10056+#else
10057+ return 0;
10058+#endif
10059+}
10060+
10061+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
10062+{
10063+#ifdef CONFIG_DEBUG_FS
10064+ return sb->s_magic == DEBUGFS_MAGIC;
10065+#else
10066+ return 0;
10067+#endif
10068+}
10069+
10070+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
10071+{
10072+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
10073+ return sb->s_magic == NILFS_SUPER_MAGIC;
10074+#else
10075+ return 0;
10076+#endif
10077+}
10078+
4a4d8108
AM
10079+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
10080+{
10081+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
10082+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
10083+#else
10084+ return 0;
10085+#endif
10086+}
10087+
1308ab2a 10088+/* ---------------------------------------------------------------------- */
10089+/*
10090+ * they can't be an aufs branch.
10091+ */
10092+static inline int au_test_fs_unsuppoted(struct super_block *sb)
10093+{
10094+ return
10095+#ifndef CONFIG_AUFS_BR_RAMFS
10096+ au_test_ramfs(sb) ||
10097+#endif
10098+ au_test_procfs(sb)
10099+ || au_test_sysfs(sb)
10100+ || au_test_configfs(sb)
10101+ || au_test_debugfs(sb)
10102+ || au_test_securityfs(sb)
10103+ || au_test_xenfs(sb)
10104+ || au_test_ecryptfs(sb)
10105+ /* || !strcmp(au_sbtype(sb), "unionfs") */
10106+ || au_test_aufs(sb); /* will be supported in next version */
10107+}
10108+
10109+/*
10110+ * If the filesystem supports NFS-export, then it has to support NULL as
10111+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
10112+ * We can apply this principle when we handle a lower filesystem.
10113+ */
10114+static inline int au_test_fs_null_nd(struct super_block *sb)
10115+{
10116+ return !!sb->s_export_op;
10117+}
10118+
10119+static inline int au_test_fs_remote(struct super_block *sb)
10120+{
10121+ return !au_test_tmpfs(sb)
10122+#ifdef CONFIG_AUFS_BR_RAMFS
10123+ && !au_test_ramfs(sb)
10124+#endif
10125+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
10126+}
10127+
10128+/* ---------------------------------------------------------------------- */
10129+
10130+/*
10131+ * Note: these functions (below) are created after reading ->getattr() in all
10132+ * filesystems under linux/fs. it means we have to do so in every update...
10133+ */
10134+
10135+/*
10136+ * some filesystems require getattr to refresh the inode attributes before
10137+ * referencing.
10138+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
10139+ * and leave the work for d_revalidate()
10140+ */
10141+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
10142+{
10143+ return au_test_nfs(sb)
10144+ || au_test_fuse(sb)
10145+ /* || au_test_smbfs(sb) */ /* untested */
10146+ /* || au_test_ocfs2(sb) */ /* untested */
10147+ /* || au_test_btrfs(sb) */ /* untested */
10148+ /* || au_test_coda(sb) */ /* untested */
10149+ /* || au_test_v9fs(sb) */ /* untested */
10150+ ;
10151+}
10152+
10153+/*
10154+ * filesystems which don't maintain i_size or i_blocks.
10155+ */
10156+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
10157+{
10158+ return au_test_xfs(sb)
4a4d8108
AM
10159+ || au_test_btrfs(sb)
10160+ || au_test_ubifs(sb)
10161+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 10162+ /* || au_test_ext4(sb) */ /* untested */
10163+ /* || au_test_ocfs2(sb) */ /* untested */
10164+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
10165+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 10166+ /* || au_test_minix(sb) */ /* untested */
10167+ ;
10168+}
10169+
10170+/*
10171+ * filesystems which don't store the correct value in some of their inode
10172+ * attributes.
10173+ */
10174+static inline int au_test_fs_bad_iattr(struct super_block *sb)
10175+{
10176+ return au_test_fs_bad_iattr_size(sb)
10177+ /* || au_test_cifs(sb) */ /* untested */
10178+ || au_test_fat(sb)
10179+ || au_test_msdos(sb)
10180+ || au_test_vfat(sb);
1facf9fc 10181+}
10182+
10183+/* they don't check i_nlink in link(2) */
10184+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
10185+{
10186+ return au_test_tmpfs(sb)
10187+#ifdef CONFIG_AUFS_BR_RAMFS
10188+ || au_test_ramfs(sb)
10189+#endif
4a4d8108
AM
10190+ || au_test_ubifs(sb)
10191+ || au_test_btrfs(sb)
10192+ || au_test_hfsplus(sb);
1facf9fc 10193+}
10194+
10195+/*
10196+ * filesystems which sets S_NOATIME and S_NOCMTIME.
10197+ */
10198+static inline int au_test_fs_notime(struct super_block *sb)
10199+{
10200+ return au_test_nfs(sb)
10201+ || au_test_fuse(sb)
dece6358 10202+ || au_test_ubifs(sb)
1facf9fc 10203+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 10204+ ;
10205+}
10206+
10207+/*
10208+ * filesystems which requires replacing i_mapping.
10209+ */
10210+static inline int au_test_fs_bad_mapping(struct super_block *sb)
10211+{
dece6358
AM
10212+ return au_test_fuse(sb)
10213+ || au_test_ubifs(sb);
1facf9fc 10214+}
10215+
10216+/* temporary support for i#1 in cramfs */
10217+static inline int au_test_fs_unique_ino(struct inode *inode)
10218+{
10219+ if (au_test_cramfs(inode->i_sb))
10220+ return inode->i_ino != 1;
10221+ return 1;
10222+}
10223+
10224+/* ---------------------------------------------------------------------- */
10225+
10226+/*
10227+ * the filesystem where the xino files placed must support i/o after unlink and
10228+ * maintain i_size and i_blocks.
10229+ */
10230+static inline int au_test_fs_bad_xino(struct super_block *sb)
10231+{
10232+ return au_test_fs_remote(sb)
10233+ || au_test_fs_bad_iattr_size(sb)
10234+#ifdef CONFIG_AUFS_BR_RAMFS
10235+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
10236+#else
10237+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
10238+#endif
10239+ /* don't want unnecessary work for xino */
10240+ || au_test_aufs(sb)
1308ab2a 10241+ || au_test_ecryptfs(sb)
10242+ || au_test_nilfs(sb);
1facf9fc 10243+}
10244+
10245+static inline int au_test_fs_trunc_xino(struct super_block *sb)
10246+{
10247+ return au_test_tmpfs(sb)
10248+ || au_test_ramfs(sb);
10249+}
10250+
10251+/*
10252+ * test if the @sb is real-readonly.
10253+ */
10254+static inline int au_test_fs_rr(struct super_block *sb)
10255+{
10256+ return au_test_squashfs(sb)
10257+ || au_test_iso9660(sb)
10258+ || au_test_cramfs(sb)
10259+ || au_test_romfs(sb);
10260+}
10261+
10262+#endif /* __KERNEL__ */
10263+#endif /* __AUFS_FSTYPE_H__ */
e49829fe 10264--- /dev/null
0c5527e5
AM
10265+++ linux-2.6/fs/aufs/hfsnotify.c 2010-10-26 10:55:35.000000000 +0200
10266@@ -0,0 +1,213 @@
1facf9fc 10267+/*
4a4d8108 10268+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 10269+ *
10270+ * This program, aufs is free software; you can redistribute it and/or modify
10271+ * it under the terms of the GNU General Public License as published by
10272+ * the Free Software Foundation; either version 2 of the License, or
10273+ * (at your option) any later version.
dece6358
AM
10274+ *
10275+ * This program is distributed in the hope that it will be useful,
10276+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10277+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10278+ * GNU General Public License for more details.
10279+ *
10280+ * You should have received a copy of the GNU General Public License
10281+ * along with this program; if not, write to the Free Software
10282+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 10283+ */
10284+
10285+/*
4a4d8108 10286+ * fsnotify for the lower directories
1facf9fc 10287+ */
10288+
10289+#include "aufs.h"
10290+
4a4d8108
AM
10291+/* FS_IN_IGNORED is unnecessary */
10292+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
10293+ | FS_CREATE | FS_EVENT_ON_CHILD);
10294+static struct fsnotify_group *au_hfsn_group;
1facf9fc 10295+
0c5527e5 10296+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 10297+{
e49829fe 10298+#if 0
0c5527e5
AM
10299+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
10300+ hn_mark);
e49829fe
JR
10301+ au_cache_free_hnotify(hn);
10302+#endif
4a4d8108
AM
10303+ AuDbg("here\n");
10304+}
1facf9fc 10305+
4a4d8108
AM
10306+static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode)
10307+{
0c5527e5 10308+ struct fsnotify_mark *mark;
1facf9fc 10309+
0c5527e5
AM
10310+ mark = &hn->hn_mark;
10311+ fsnotify_init_mark(mark, au_hfsn_free_mark);
10312+ mark->mask = AuHfsnMask;
10313+ return fsnotify_add_mark(mark, au_hfsn_group, h_inode, NULL, 1);
1facf9fc 10314+}
10315+
4a4d8108 10316+static void au_hfsn_free(struct au_hnotify *hn)
1facf9fc 10317+{
0c5527e5 10318+ struct fsnotify_mark *mark;
953406b4 10319+
0c5527e5
AM
10320+ mark = &hn->hn_mark;
10321+ fsnotify_destroy_mark(mark);
10322+ fsnotify_put_mark(mark);
1facf9fc 10323+}
10324+
10325+/* ---------------------------------------------------------------------- */
10326+
4a4d8108 10327+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 10328+{
0c5527e5 10329+ struct fsnotify_mark *mark;
1facf9fc 10330+
0c5527e5
AM
10331+ mark = &hinode->hi_notify->hn_mark;
10332+ spin_lock(&mark->lock);
1facf9fc 10333+ if (do_set) {
0c5527e5
AM
10334+ AuDebugOn(mark->mask & AuHfsnMask);
10335+ mark->mask |= AuHfsnMask;
1facf9fc 10336+ } else {
0c5527e5
AM
10337+ AuDebugOn(!(mark->mask & AuHfsnMask));
10338+ mark->mask &= ~AuHfsnMask;
1facf9fc 10339+ }
0c5527e5 10340+ spin_unlock(&mark->lock);
4a4d8108 10341+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 10342+}
10343+
4a4d8108 10344+/* ---------------------------------------------------------------------- */
1facf9fc 10345+
4a4d8108
AM
10346+/* #define AuDbgHnotify */
10347+#ifdef AuDbgHnotify
10348+static char *au_hfsn_name(u32 mask)
10349+{
10350+#ifdef CONFIG_AUFS_DEBUG
10351+#define test_ret(flag) if (mask & flag) \
10352+ return #flag;
10353+ test_ret(FS_ACCESS);
10354+ test_ret(FS_MODIFY);
10355+ test_ret(FS_ATTRIB);
10356+ test_ret(FS_CLOSE_WRITE);
10357+ test_ret(FS_CLOSE_NOWRITE);
10358+ test_ret(FS_OPEN);
10359+ test_ret(FS_MOVED_FROM);
10360+ test_ret(FS_MOVED_TO);
10361+ test_ret(FS_CREATE);
10362+ test_ret(FS_DELETE);
10363+ test_ret(FS_DELETE_SELF);
10364+ test_ret(FS_MOVE_SELF);
10365+ test_ret(FS_UNMOUNT);
10366+ test_ret(FS_Q_OVERFLOW);
10367+ test_ret(FS_IN_IGNORED);
10368+ test_ret(FS_IN_ISDIR);
10369+ test_ret(FS_IN_ONESHOT);
10370+ test_ret(FS_EVENT_ON_CHILD);
10371+ return "";
10372+#undef test_ret
10373+#else
10374+ return "??";
10375+#endif
1facf9fc 10376+}
4a4d8108 10377+#endif
1facf9fc 10378+
10379+/* ---------------------------------------------------------------------- */
10380+
4a4d8108 10381+static int au_hfsn_handle_event(struct fsnotify_group *group,
0c5527e5
AM
10382+ struct fsnotify_mark *inode_mark,
10383+ struct fsnotify_mark *vfsmount_mark,
4a4d8108 10384+ struct fsnotify_event *event)
1facf9fc 10385+{
10386+ int err;
4a4d8108
AM
10387+ struct au_hnotify *hnotify;
10388+ struct inode *h_dir, *h_inode;
10389+ __u32 mask;
4a4d8108
AM
10390+ struct qstr h_child_qstr = {
10391+ .name = event->file_name,
10392+ .len = event->name_len
10393+ };
10394+
10395+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 10396+
10397+ err = 0;
0c5527e5 10398+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108
AM
10399+ mask = event->mask;
10400+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 10401+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 10402+ goto out;
1facf9fc 10403+
4a4d8108
AM
10404+ h_dir = event->to_tell;
10405+ h_inode = event->inode;
10406+#ifdef AuDbgHnotify
10407+ au_debug(1);
10408+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
10409+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
10410+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
10411+ h_dir->i_ino, mask, au_hfsn_name(mask),
10412+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
10413+ /* WARN_ON(1); */
1facf9fc 10414+ }
4a4d8108 10415+ au_debug(0);
1facf9fc 10416+#endif
4a4d8108 10417+
0c5527e5
AM
10418+ AuDebugOn(!inode_mark);
10419+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
10420+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
10421+ fsnotify_put_mark(inode_mark);
1facf9fc 10422+
4a4d8108
AM
10423+out:
10424+ return err;
10425+}
1facf9fc 10426+
0c5527e5 10427+/* copied from linux/fs/notify/inotify/inotify_fsnotify.c */
4a4d8108 10428+/* it should be exported to modules */
0c5527e5
AM
10429+static bool au_hfsn_should_send_event(struct fsnotify_group *group, struct inode *inode,
10430+ struct fsnotify_mark *inode_mark,
10431+ struct fsnotify_mark *vfsmount_mark,
10432+ __u32 mask, void *data, int data_type)
4a4d8108 10433+{
e49829fe
JR
10434+ bool send;
10435+
4a4d8108 10436+ mask = (mask & ~FS_EVENT_ON_CHILD);
0c5527e5 10437+ send = (inode_mark->mask & mask);
e49829fe
JR
10438+
10439+ /* find took a reference */
0c5527e5 10440+ fsnotify_put_mark(inode_mark);
e49829fe
JR
10441+
10442+ return send;
4a4d8108
AM
10443+}
10444+
10445+static struct fsnotify_ops au_hfsn_ops = {
10446+ .should_send_event = au_hfsn_should_send_event,
10447+ .handle_event = au_hfsn_handle_event
10448+};
10449+
10450+/* ---------------------------------------------------------------------- */
10451+
10452+static int __init au_hfsn_init(void)
10453+{
10454+ int err;
1facf9fc 10455+
4a4d8108 10456+ err = 0;
0c5527e5 10457+ au_hfsn_group = fsnotify_alloc_group(&au_hfsn_ops);
4a4d8108 10458+ if (IS_ERR(au_hfsn_group)) {
4a4d8108 10459+ err = PTR_ERR(au_hfsn_group);
0c5527e5 10460+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
4a4d8108 10461+ }
1facf9fc 10462+
1facf9fc 10463+ AuTraceErr(err);
10464+ return err;
10465+}
10466+
4a4d8108 10467+static void au_hfsn_fin(void)
1facf9fc 10468+{
4a4d8108
AM
10469+ fsnotify_put_group(au_hfsn_group);
10470+}
1facf9fc 10471+
4a4d8108
AM
10472+const struct au_hnotify_op au_hnotify_op = {
10473+ .ctl = au_hfsn_ctl,
10474+ .alloc = au_hfsn_alloc,
10475+ .free = au_hfsn_free,
1facf9fc 10476+
4a4d8108
AM
10477+ .fin = au_hfsn_fin,
10478+ .init = au_hfsn_init
10479+};
e49829fe 10480--- /dev/null
0c5527e5 10481+++ linux-2.6/fs/aufs/hfsplus.c 2010-10-25 14:20:44.000000000 +0200
4a4d8108
AM
10482@@ -0,0 +1,58 @@
10483+/*
10484+ * Copyright (C) 2010 Junjiro R. Okajima
10485+ *
10486+ * This program, aufs is free software; you can redistribute it and/or modify
10487+ * it under the terms of the GNU General Public License as published by
10488+ * the Free Software Foundation; either version 2 of the License, or
10489+ * (at your option) any later version.
10490+ *
10491+ * This program is distributed in the hope that it will be useful,
10492+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10493+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10494+ * GNU General Public License for more details.
10495+ *
10496+ * You should have received a copy of the GNU General Public License
10497+ * along with this program; if not, write to the Free Software
10498+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10499+ */
1facf9fc 10500+
4a4d8108
AM
10501+/*
10502+ * special support for filesystems which aqucires an inode mutex
10503+ * at final closing a file, eg, hfsplus.
10504+ *
10505+ * This trick is very simple and stupid, just to open the file before really
10506+ * neceeary open to tell hfsplus that this is not the final closing.
10507+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
10508+ * and au_h_open_post() after releasing it.
10509+ */
1facf9fc 10510+
4a4d8108
AM
10511+#include <linux/file.h>
10512+#include "aufs.h"
1facf9fc 10513+
4a4d8108
AM
10514+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
10515+{
10516+ struct file *h_file;
10517+ struct dentry *h_dentry;
1facf9fc 10518+
4a4d8108
AM
10519+ h_dentry = au_h_dptr(dentry, bindex);
10520+ AuDebugOn(!h_dentry);
10521+ AuDebugOn(!h_dentry->d_inode);
10522+ IMustLock(h_dentry->d_inode);
10523+
10524+ h_file = NULL;
10525+ if (au_test_hfsplus(h_dentry->d_sb)
10526+ && S_ISREG(h_dentry->d_inode->i_mode))
10527+ h_file = au_h_open(dentry, bindex,
10528+ O_RDONLY | O_NOATIME | O_LARGEFILE,
10529+ /*file*/NULL);
10530+ return h_file;
1facf9fc 10531+}
10532+
4a4d8108
AM
10533+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
10534+ struct file *h_file)
10535+{
10536+ if (h_file) {
10537+ fput(h_file);
10538+ au_sbr_put(dentry->d_sb, bindex);
10539+ }
10540+}
e49829fe 10541--- /dev/null
0c5527e5 10542+++ linux-2.6/fs/aufs/hinotify.c 2010-10-25 14:20:44.000000000 +0200
e49829fe
JR
10543@@ -0,0 +1,231 @@
10544+/*
10545+ * Copyright (C) 2005-2010 Junjiro R. Okajima
10546+ *
10547+ * This program, aufs is free software; you can redistribute it and/or modify
10548+ * it under the terms of the GNU General Public License as published by
10549+ * the Free Software Foundation; either version 2 of the License, or
10550+ * (at your option) any later version.
10551+ *
10552+ * This program is distributed in the hope that it will be useful,
10553+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10554+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10555+ * GNU General Public License for more details.
10556+ *
10557+ * You should have received a copy of the GNU General Public License
10558+ * along with this program; if not, write to the Free Software
10559+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10560+ */
10561+
10562+/*
10563+ * inotify for the lower directories (deprecated)
10564+ */
10565+
10566+#include "aufs.h"
10567+
10568+static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
10569+static struct inotify_handle *au_hin_handle;
10570+
10571+/* ---------------------------------------------------------------------- */
10572+
10573+static int au_hin_alloc(struct au_hnotify *hn, struct inode *h_inode)
10574+{
10575+ int err;
10576+ s32 wd;
10577+ struct inotify_watch *watch;
10578+
10579+ err = -EEXIST;
10580+ wd = inotify_find_watch(au_hin_handle, h_inode, &watch);
10581+ if (wd >= 0) {
10582+ put_inotify_watch(watch);
10583+ goto out;
10584+ }
10585+
10586+ err = 0;
10587+ inotify_init_watch(&hn->hn_watch);
10588+ wd = inotify_add_watch(au_hin_handle, &hn->hn_watch, h_inode,
10589+ AuHinMask);
10590+ if (unlikely(wd < 0)) {
10591+ err = wd;
10592+ put_inotify_watch(&hn->hn_watch);
10593+ }
10594+
10595+out:
10596+ return err;
10597+}
10598+
10599+static void au_hin_free(struct au_hnotify *hn)
10600+{
10601+ int err;
10602+
10603+ err = 0;
10604+ if (atomic_read(&hn->hn_watch.count))
10605+ err = inotify_rm_watch(au_hin_handle, &hn->hn_watch);
10606+ if (unlikely(err))
10607+ /* it means the watch is already removed */
10608+ pr_warning("failed inotify_rm_watch() %d\n", err);
10609+}
10610+
10611+/* ---------------------------------------------------------------------- */
10612+
10613+static void au_hin_ctl(struct au_hinode *hinode, int do_set)
10614+{
10615+ struct inode *h_inode;
10616+ struct inotify_watch *watch;
10617+
10618+ h_inode = hinode->hi_inode;
10619+ IMustLock(h_inode);
10620+
10621+ /* todo: try inotify_find_update_watch()? */
10622+ watch = &hinode->hi_notify->hn_watch;
10623+ mutex_lock(&h_inode->inotify_mutex);
10624+ /* mutex_lock(&watch->ih->mutex); */
10625+ if (do_set) {
10626+ AuDebugOn(watch->mask & AuHinMask);
10627+ watch->mask |= AuHinMask;
10628+ } else {
10629+ AuDebugOn(!(watch->mask & AuHinMask));
10630+ watch->mask &= ~AuHinMask;
10631+ }
10632+ /* mutex_unlock(&watch->ih->mutex); */
10633+ mutex_unlock(&h_inode->inotify_mutex);
10634+}
10635+
10636+/* ---------------------------------------------------------------------- */
10637+
10638+#ifdef AuDbgHnotify
10639+static char *in_name(u32 mask)
10640+{
10641+#ifdef CONFIG_AUFS_DEBUG
10642+#define test_ret(flag) if (mask & flag) \
10643+ return #flag;
10644+ test_ret(IN_ACCESS);
10645+ test_ret(IN_MODIFY);
10646+ test_ret(IN_ATTRIB);
10647+ test_ret(IN_CLOSE_WRITE);
10648+ test_ret(IN_CLOSE_NOWRITE);
10649+ test_ret(IN_OPEN);
10650+ test_ret(IN_MOVED_FROM);
10651+ test_ret(IN_MOVED_TO);
10652+ test_ret(IN_CREATE);
10653+ test_ret(IN_DELETE);
10654+ test_ret(IN_DELETE_SELF);
10655+ test_ret(IN_MOVE_SELF);
10656+ test_ret(IN_UNMOUNT);
10657+ test_ret(IN_Q_OVERFLOW);
10658+ test_ret(IN_IGNORED);
10659+ return "";
10660+#undef test_ret
10661+#else
10662+ return "??";
10663+#endif
10664+}
10665+#endif
10666+
10667+static u32 au_hin_conv_mask(u32 mask)
10668+{
10669+ u32 conv;
10670+
10671+ conv = 0;
10672+#define do_conv(flag) do { \
10673+ conv |= (mask & IN_ ## flag) ? FS_ ## flag : 0; \
10674+ } while (0)
10675+ do_conv(ACCESS);
10676+ do_conv(MODIFY);
10677+ do_conv(ATTRIB);
10678+ do_conv(CLOSE_WRITE);
10679+ do_conv(CLOSE_NOWRITE);
10680+ do_conv(OPEN);
10681+ do_conv(MOVED_FROM);
10682+ do_conv(MOVED_TO);
10683+ do_conv(CREATE);
10684+ do_conv(DELETE);
10685+ do_conv(DELETE_SELF);
10686+ do_conv(MOVE_SELF);
10687+ do_conv(UNMOUNT);
10688+ do_conv(Q_OVERFLOW);
10689+#undef do_conv
10690+#define do_conv(flag) do { \
10691+ conv |= (mask & IN_ ## flag) ? FS_IN_ ## flag : 0; \
10692+ } while (0)
10693+ do_conv(IGNORED);
10694+ /* do_conv(ISDIR); */
10695+ /* do_conv(ONESHOT); */
10696+#undef do_conv
10697+
10698+ return conv;
10699+}
10700+
10701+static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
10702+ u32 mask, u32 cookie __maybe_unused,
10703+ const char *h_child_name, struct inode *h_child_inode)
10704+{
10705+ struct au_hnotify *hnotify;
10706+ struct qstr h_child_qstr = {
10707+ .name = h_child_name
10708+ };
10709+
10710+ /* if IN_UNMOUNT happens, there must be another bug */
10711+ AuDebugOn(mask & IN_UNMOUNT);
10712+ if (mask & (IN_IGNORED | IN_UNMOUNT)) {
10713+ put_inotify_watch(watch);
10714+ return;
10715+ }
10716+
10717+#ifdef AuDbgHnotify
10718+ au_debug(1);
10719+ if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
10720+ AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
10721+ " hi%lu\n",
10722+ watch->inode->i_ino, wd, mask, in_name(mask), cookie,
10723+ h_child_name ? h_child_name : "",
10724+ h_child_inode ? h_child_inode->i_ino : 0);
10725+ WARN_ON(1);
10726+ }
10727+ au_debug(0);
10728+#endif
10729+
10730+ if (h_child_name)
10731+ h_child_qstr.len = strlen(h_child_name);
10732+ hnotify = container_of(watch, struct au_hnotify, hn_watch);
10733+ mask = au_hin_conv_mask(mask);
10734+ au_hnotify(watch->inode, hnotify, mask, &h_child_qstr, h_child_inode);
10735+}
10736+
10737+static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
10738+{
10739+ return;
10740+}
10741+
10742+static struct inotify_operations aufs_inotify_ops = {
10743+ .handle_event = aufs_inotify,
10744+ .destroy_watch = aufs_inotify_destroy
10745+};
10746+
10747+/* ---------------------------------------------------------------------- */
10748+
10749+static int __init au_hin_init(void)
10750+{
10751+ int err;
10752+
10753+ err = 0;
10754+ au_hin_handle = inotify_init(&aufs_inotify_ops);
10755+ if (IS_ERR(au_hin_handle))
10756+ err = PTR_ERR(au_hin_handle);
10757+
10758+ AuTraceErr(err);
10759+ return err;
10760+}
10761+
10762+static void au_hin_fin(void)
10763+{
10764+ inotify_destroy(au_hin_handle);
10765+}
10766+
10767+const struct au_hnotify_op au_hnotify_op = {
10768+ .ctl = au_hin_ctl,
10769+ .alloc = au_hin_alloc,
10770+ .free = au_hin_free,
10771+
10772+ .fin = au_hin_fin,
10773+ .init = au_hin_init
10774+};
10775--- /dev/null
0c5527e5 10776+++ linux-2.6/fs/aufs/hnotify.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 10777@@ -0,0 +1,662 @@
1facf9fc 10778+/*
4a4d8108 10779+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 10780+ *
10781+ * This program, aufs is free software; you can redistribute it and/or modify
10782+ * it under the terms of the GNU General Public License as published by
10783+ * the Free Software Foundation; either version 2 of the License, or
10784+ * (at your option) any later version.
dece6358
AM
10785+ *
10786+ * This program is distributed in the hope that it will be useful,
10787+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10788+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10789+ * GNU General Public License for more details.
10790+ *
10791+ * You should have received a copy of the GNU General Public License
10792+ * along with this program; if not, write to the Free Software
10793+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 10794+ */
10795+
10796+/*
4a4d8108 10797+ * abstraction to notify the direct changes on lower directories
1facf9fc 10798+ */
10799+
1308ab2a 10800+#include "aufs.h"
1facf9fc 10801+
4a4d8108
AM
10802+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
10803+ struct inode *h_inode)
dece6358 10804+{
1308ab2a 10805+ int err;
4a4d8108 10806+ struct au_hnotify *hn;
1facf9fc 10807+
4a4d8108
AM
10808+ err = -ENOMEM;
10809+ hn = au_cache_alloc_hnotify();
10810+ if (hn) {
10811+ hn->hn_aufs_inode = inode;
10812+ err = au_hnotify_op.alloc(hn, h_inode);
10813+ if (!err)
10814+ hinode->hi_notify = hn;
10815+ else {
10816+ au_cache_free_hnotify(hn);
10817+ /*
10818+ * The upper dir was removed by udba, but the same named
10819+ * dir left. In this case, aufs assignes a new inode
10820+ * number and set the monitor again.
10821+ * For the lower dir, the old monitnor is still left.
10822+ */
10823+ if (err == -EEXIST)
10824+ err = 0;
10825+ }
1308ab2a 10826+ }
1308ab2a 10827+
1308ab2a 10828+ return err;
dece6358 10829+}
1facf9fc 10830+
4a4d8108 10831+void au_hn_free(struct au_hinode *hinode)
dece6358 10832+{
4a4d8108 10833+ struct au_hnotify *hn;
1facf9fc 10834+
4a4d8108
AM
10835+ hn = hinode->hi_notify;
10836+ if (hn) {
10837+ au_hnotify_op.free(hn);
10838+ au_cache_free_hnotify(hn);
10839+ hinode->hi_notify = NULL;
10840+ }
10841+}
dece6358 10842+
4a4d8108 10843+/* ---------------------------------------------------------------------- */
dece6358 10844+
4a4d8108
AM
10845+void au_hn_ctl(struct au_hinode *hinode, int do_set)
10846+{
10847+ if (hinode->hi_notify)
10848+ au_hnotify_op.ctl(hinode, do_set);
10849+}
10850+
10851+void au_hn_reset(struct inode *inode, unsigned int flags)
10852+{
10853+ aufs_bindex_t bindex, bend;
10854+ struct inode *hi;
10855+ struct dentry *iwhdentry;
1facf9fc 10856+
1308ab2a 10857+ bend = au_ibend(inode);
4a4d8108
AM
10858+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
10859+ hi = au_h_iptr(inode, bindex);
10860+ if (!hi)
10861+ continue;
1308ab2a 10862+
4a4d8108
AM
10863+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
10864+ iwhdentry = au_hi_wh(inode, bindex);
10865+ if (iwhdentry)
10866+ dget(iwhdentry);
10867+ au_igrab(hi);
10868+ au_set_h_iptr(inode, bindex, NULL, 0);
10869+ au_set_h_iptr(inode, bindex, au_igrab(hi),
10870+ flags & ~AuHi_XINO);
10871+ iput(hi);
10872+ dput(iwhdentry);
10873+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 10874+ }
1facf9fc 10875+}
10876+
1308ab2a 10877+/* ---------------------------------------------------------------------- */
1facf9fc 10878+
4a4d8108 10879+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 10880+{
4a4d8108
AM
10881+ int err;
10882+ aufs_bindex_t bindex, bend, bfound, bstart;
10883+ struct inode *h_i;
1facf9fc 10884+
4a4d8108
AM
10885+ err = 0;
10886+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
10887+ pr_warning("branch root dir was changed\n");
10888+ goto out;
10889+ }
1facf9fc 10890+
4a4d8108
AM
10891+ bfound = -1;
10892+ bend = au_ibend(inode);
10893+ bstart = au_ibstart(inode);
10894+#if 0 /* reserved for future use */
10895+ if (bindex == bend) {
10896+ /* keep this ino in rename case */
10897+ goto out;
10898+ }
10899+#endif
10900+ for (bindex = bstart; bindex <= bend; bindex++)
10901+ if (au_h_iptr(inode, bindex) == h_inode) {
10902+ bfound = bindex;
10903+ break;
10904+ }
10905+ if (bfound < 0)
1308ab2a 10906+ goto out;
1facf9fc 10907+
4a4d8108
AM
10908+ for (bindex = bstart; bindex <= bend; bindex++) {
10909+ h_i = au_h_iptr(inode, bindex);
10910+ if (!h_i)
10911+ continue;
1facf9fc 10912+
4a4d8108
AM
10913+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
10914+ /* ignore this error */
10915+ /* bad action? */
1facf9fc 10916+ }
1facf9fc 10917+
4a4d8108 10918+ /* children inode number will be broken */
1facf9fc 10919+
4f0767ce 10920+out:
4a4d8108
AM
10921+ AuTraceErr(err);
10922+ return err;
1facf9fc 10923+}
10924+
4a4d8108 10925+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 10926+{
4a4d8108
AM
10927+ int err, i, j, ndentry;
10928+ struct au_dcsub_pages dpages;
10929+ struct au_dpage *dpage;
10930+ struct dentry **dentries;
1facf9fc 10931+
4a4d8108
AM
10932+ err = au_dpages_init(&dpages, GFP_NOFS);
10933+ if (unlikely(err))
10934+ goto out;
10935+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
10936+ if (unlikely(err))
10937+ goto out_dpages;
1facf9fc 10938+
4a4d8108
AM
10939+ for (i = 0; i < dpages.ndpage; i++) {
10940+ dpage = dpages.dpages + i;
10941+ dentries = dpage->dentries;
10942+ ndentry = dpage->ndentry;
10943+ for (j = 0; j < ndentry; j++) {
10944+ struct dentry *d;
10945+
10946+ d = dentries[j];
10947+ if (IS_ROOT(d))
10948+ continue;
10949+
10950+ d_drop(d);
10951+ au_digen_dec(d);
10952+ if (d->d_inode)
10953+ /* todo: reset children xino?
10954+ cached children only? */
10955+ au_iigen_dec(d->d_inode);
1308ab2a 10956+ }
dece6358 10957+ }
1facf9fc 10958+
4f0767ce 10959+out_dpages:
4a4d8108 10960+ au_dpages_free(&dpages);
dece6358 10961+
4a4d8108
AM
10962+ /* discard children */
10963+ dentry_unhash(dentry);
10964+ dput(dentry);
4f0767ce 10965+out:
dece6358
AM
10966+ return err;
10967+}
10968+
1308ab2a 10969+/*
4a4d8108 10970+ * return 0 if processed.
1308ab2a 10971+ */
4a4d8108
AM
10972+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
10973+ const unsigned int isdir)
dece6358 10974+{
1308ab2a 10975+ int err;
4a4d8108
AM
10976+ struct dentry *d;
10977+ struct qstr *dname;
1facf9fc 10978+
4a4d8108
AM
10979+ err = 1;
10980+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
10981+ pr_warning("branch root dir was changed\n");
10982+ err = 0;
10983+ goto out;
10984+ }
dece6358 10985+
4a4d8108
AM
10986+ if (!isdir) {
10987+ AuDebugOn(!name);
10988+ au_iigen_dec(inode);
10989+ spin_lock(&dcache_lock);
10990+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
10991+ dname = &d->d_name;
10992+ if (dname->len != nlen
10993+ && memcmp(dname->name, name, nlen))
10994+ continue;
10995+ err = 0;
10996+ spin_lock(&d->d_lock);
10997+ __d_drop(d);
10998+ au_digen_dec(d);
10999+ spin_unlock(&d->d_lock);
11000+ break;
1facf9fc 11001+ }
4a4d8108 11002+ spin_unlock(&dcache_lock);
1308ab2a 11003+ } else {
4a4d8108
AM
11004+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
11005+ d = d_find_alias(inode);
11006+ if (!d) {
11007+ au_iigen_dec(inode);
11008+ goto out;
11009+ }
1facf9fc 11010+
4a4d8108
AM
11011+ dname = &d->d_name;
11012+ if (dname->len == nlen && !memcmp(dname->name, name, nlen))
11013+ err = hn_gen_tree(d);
11014+ dput(d);
11015+ }
1facf9fc 11016+
4f0767ce 11017+out:
4a4d8108 11018+ AuTraceErr(err);
1308ab2a 11019+ return err;
11020+}
dece6358 11021+
4a4d8108 11022+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 11023+{
4a4d8108
AM
11024+ int err;
11025+ struct inode *inode;
1facf9fc 11026+
4a4d8108
AM
11027+ inode = dentry->d_inode;
11028+ if (IS_ROOT(dentry)
11029+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
11030+ ) {
11031+ pr_warning("branch root dir was changed\n");
11032+ return 0;
11033+ }
1308ab2a 11034+
4a4d8108
AM
11035+ err = 0;
11036+ if (!isdir) {
11037+ d_drop(dentry);
11038+ au_digen_dec(dentry);
11039+ if (inode)
11040+ au_iigen_dec(inode);
11041+ } else {
11042+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
11043+ if (inode)
11044+ err = hn_gen_tree(dentry);
11045+ }
11046+
11047+ AuTraceErr(err);
11048+ return err;
1facf9fc 11049+}
11050+
4a4d8108 11051+/* ---------------------------------------------------------------------- */
1facf9fc 11052+
4a4d8108
AM
11053+/* hnotify job flags */
11054+#define AuHnJob_XINO0 1
11055+#define AuHnJob_GEN (1 << 1)
11056+#define AuHnJob_DIRENT (1 << 2)
11057+#define AuHnJob_ISDIR (1 << 3)
11058+#define AuHnJob_TRYXINO0 (1 << 4)
11059+#define AuHnJob_MNTPNT (1 << 5)
11060+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
11061+#define au_fset_hnjob(flags, name) { (flags) |= AuHnJob_##name; }
11062+#define au_fclr_hnjob(flags, name) { (flags) &= ~AuHnJob_##name; }
1facf9fc 11063+
4a4d8108
AM
11064+enum {
11065+ AuHn_CHILD,
11066+ AuHn_PARENT,
11067+ AuHnLast
11068+};
1facf9fc 11069+
4a4d8108
AM
11070+struct au_hnotify_args {
11071+ struct inode *h_dir, *dir, *h_child_inode;
11072+ u32 mask;
11073+ unsigned int flags[AuHnLast];
11074+ unsigned int h_child_nlen;
11075+ char h_child_name[];
11076+};
1facf9fc 11077+
4a4d8108
AM
11078+struct hn_job_args {
11079+ unsigned int flags;
11080+ struct inode *inode, *h_inode, *dir, *h_dir;
11081+ struct dentry *dentry;
11082+ char *h_name;
11083+ int h_nlen;
11084+};
1308ab2a 11085+
4a4d8108
AM
11086+static int hn_job(struct hn_job_args *a)
11087+{
11088+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 11089+
4a4d8108
AM
11090+ /* reset xino */
11091+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
11092+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 11093+
4a4d8108
AM
11094+ if (au_ftest_hnjob(a->flags, TRYXINO0)
11095+ && a->inode
11096+ && a->h_inode) {
11097+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11098+ if (!a->h_inode->i_nlink)
11099+ hn_xino(a->inode, a->h_inode); /* ignore this error */
11100+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 11101+ }
1facf9fc 11102+
4a4d8108
AM
11103+ /* make the generation obsolete */
11104+ if (au_ftest_hnjob(a->flags, GEN)) {
11105+ int err = -1;
11106+ if (a->inode)
11107+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
11108+ isdir);
11109+ if (err && a->dentry)
11110+ hn_gen_by_name(a->dentry, isdir);
11111+ /* ignore this error */
1facf9fc 11112+ }
1facf9fc 11113+
4a4d8108
AM
11114+ /* make dir entries obsolete */
11115+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
11116+ struct au_vdir *vdir;
1facf9fc 11117+
4a4d8108
AM
11118+ vdir = au_ivdir(a->inode);
11119+ if (vdir)
11120+ vdir->vd_jiffy = 0;
11121+ /* IMustLock(a->inode); */
11122+ /* a->inode->i_version++; */
11123+ }
1facf9fc 11124+
4a4d8108
AM
11125+ /* can do nothing but warn */
11126+ if (au_ftest_hnjob(a->flags, MNTPNT)
11127+ && a->dentry
11128+ && d_mountpoint(a->dentry))
11129+ pr_warning("mount-point %.*s is removed or renamed\n",
11130+ AuDLNPair(a->dentry));
1facf9fc 11131+
4a4d8108 11132+ return 0;
1308ab2a 11133+}
1facf9fc 11134+
1308ab2a 11135+/* ---------------------------------------------------------------------- */
1facf9fc 11136+
4a4d8108
AM
11137+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
11138+ struct inode *dir)
1308ab2a 11139+{
4a4d8108
AM
11140+ struct dentry *dentry, *d, *parent;
11141+ struct qstr *dname;
1308ab2a 11142+
4a4d8108
AM
11143+ parent = d_find_alias(dir);
11144+ if (!parent)
11145+ return NULL;
1308ab2a 11146+
4a4d8108
AM
11147+ dentry = NULL;
11148+ spin_lock(&dcache_lock);
11149+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
11150+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
11151+ dname = &d->d_name;
11152+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
11153+ continue;
11154+ if (!atomic_read(&d->d_count) || !d->d_fsdata) {
11155+ spin_lock(&d->d_lock);
11156+ __d_drop(d);
11157+ spin_unlock(&d->d_lock);
11158+ continue;
dece6358 11159+ }
1facf9fc 11160+
4a4d8108
AM
11161+ dentry = dget(d);
11162+ break;
1308ab2a 11163+ }
4a4d8108
AM
11164+ spin_unlock(&dcache_lock);
11165+ dput(parent);
1facf9fc 11166+
4a4d8108
AM
11167+ if (dentry)
11168+ di_write_lock_child(dentry);
1308ab2a 11169+
4a4d8108
AM
11170+ return dentry;
11171+}
dece6358 11172+
4a4d8108
AM
11173+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
11174+ aufs_bindex_t bindex, ino_t h_ino)
11175+{
11176+ struct inode *inode;
11177+ ino_t ino;
11178+ int err;
11179+
11180+ inode = NULL;
11181+ err = au_xino_read(sb, bindex, h_ino, &ino);
11182+ if (!err && ino)
11183+ inode = ilookup(sb, ino);
11184+ if (!inode)
11185+ goto out;
11186+
11187+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11188+ pr_warning("wrong root branch\n");
11189+ iput(inode);
11190+ inode = NULL;
11191+ goto out;
1308ab2a 11192+ }
11193+
4a4d8108 11194+ ii_write_lock_child(inode);
1308ab2a 11195+
4f0767ce 11196+out:
4a4d8108 11197+ return inode;
dece6358
AM
11198+}
11199+
4a4d8108 11200+static void au_hn_bh(void *_args)
1facf9fc 11201+{
4a4d8108
AM
11202+ struct au_hnotify_args *a = _args;
11203+ struct super_block *sb;
11204+ aufs_bindex_t bindex, bend, bfound;
11205+ unsigned char xino, try_iput;
1facf9fc 11206+ int err;
1308ab2a 11207+ struct inode *inode;
4a4d8108
AM
11208+ ino_t h_ino;
11209+ struct hn_job_args args;
11210+ struct dentry *dentry;
11211+ struct au_sbinfo *sbinfo;
1facf9fc 11212+
4a4d8108
AM
11213+ AuDebugOn(!_args);
11214+ AuDebugOn(!a->h_dir);
11215+ AuDebugOn(!a->dir);
11216+ AuDebugOn(!a->mask);
11217+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
11218+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
11219+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 11220+
4a4d8108
AM
11221+ inode = NULL;
11222+ dentry = NULL;
11223+ /*
11224+ * do not lock a->dir->i_mutex here
11225+ * because of d_revalidate() may cause a deadlock.
11226+ */
11227+ sb = a->dir->i_sb;
11228+ AuDebugOn(!sb);
11229+ sbinfo = au_sbi(sb);
11230+ AuDebugOn(!sbinfo);
e49829fe 11231+ si_write_lock(sb, !AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 11232+
4a4d8108
AM
11233+ ii_read_lock_parent(a->dir);
11234+ bfound = -1;
11235+ bend = au_ibend(a->dir);
11236+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
11237+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
11238+ bfound = bindex;
11239+ break;
11240+ }
11241+ ii_read_unlock(a->dir);
11242+ if (unlikely(bfound < 0))
11243+ goto out;
1facf9fc 11244+
4a4d8108
AM
11245+ xino = !!au_opt_test(au_mntflags(sb), XINO);
11246+ h_ino = 0;
11247+ if (a->h_child_inode)
11248+ h_ino = a->h_child_inode->i_ino;
1facf9fc 11249+
4a4d8108
AM
11250+ if (a->h_child_nlen
11251+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
11252+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
11253+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
11254+ a->dir);
11255+ try_iput = 0;
11256+ if (dentry)
11257+ inode = dentry->d_inode;
11258+ if (xino && !inode && h_ino
11259+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
11260+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
11261+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
11262+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
11263+ try_iput = 1;
11264+ }
1facf9fc 11265+
4a4d8108
AM
11266+ args.flags = a->flags[AuHn_CHILD];
11267+ args.dentry = dentry;
11268+ args.inode = inode;
11269+ args.h_inode = a->h_child_inode;
11270+ args.dir = a->dir;
11271+ args.h_dir = a->h_dir;
11272+ args.h_name = a->h_child_name;
11273+ args.h_nlen = a->h_child_nlen;
11274+ err = hn_job(&args);
11275+ if (dentry) {
11276+ if (dentry->d_fsdata)
11277+ di_write_unlock(dentry);
11278+ dput(dentry);
11279+ }
11280+ if (inode && try_iput) {
11281+ ii_write_unlock(inode);
11282+ iput(inode);
11283+ }
1facf9fc 11284+
4a4d8108
AM
11285+ ii_write_lock_parent(a->dir);
11286+ args.flags = a->flags[AuHn_PARENT];
11287+ args.dentry = NULL;
11288+ args.inode = a->dir;
11289+ args.h_inode = a->h_dir;
11290+ args.dir = NULL;
11291+ args.h_dir = NULL;
11292+ args.h_name = NULL;
11293+ args.h_nlen = 0;
11294+ err = hn_job(&args);
11295+ ii_write_unlock(a->dir);
1facf9fc 11296+
4f0767ce 11297+out:
4a4d8108
AM
11298+ au_nwt_done(&sbinfo->si_nowait);
11299+ si_write_unlock(sb);
1308ab2a 11300+
4a4d8108
AM
11301+ iput(a->h_child_inode);
11302+ iput(a->h_dir);
11303+ iput(a->dir);
1308ab2a 11304+ kfree(a);
dece6358 11305+}
1facf9fc 11306+
4a4d8108
AM
11307+/* ---------------------------------------------------------------------- */
11308+
11309+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
11310+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 11311+{
4a4d8108
AM
11312+ int err, len;
11313+ unsigned int flags[AuHnLast];
11314+ unsigned char isdir, isroot, wh;
11315+ struct inode *dir;
11316+ struct au_hnotify_args *args;
11317+ char *p, *h_child_name;
dece6358 11318+
1308ab2a 11319+ err = 0;
4a4d8108
AM
11320+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
11321+ dir = igrab(hnotify->hn_aufs_inode);
11322+ if (!dir)
11323+ goto out;
1facf9fc 11324+
4a4d8108
AM
11325+ isroot = (dir->i_ino == AUFS_ROOT_INO);
11326+ wh = 0;
11327+ h_child_name = (void *)h_child_qstr->name;
11328+ len = h_child_qstr->len;
11329+ if (h_child_name) {
11330+ if (len > AUFS_WH_PFX_LEN
11331+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
11332+ h_child_name += AUFS_WH_PFX_LEN;
11333+ len -= AUFS_WH_PFX_LEN;
11334+ wh = 1;
11335+ }
1facf9fc 11336+ }
dece6358 11337+
4a4d8108
AM
11338+ isdir = 0;
11339+ if (h_child_inode)
11340+ isdir = !!S_ISDIR(h_child_inode->i_mode);
11341+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
11342+ flags[AuHn_CHILD] = 0;
11343+ if (isdir)
11344+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
11345+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
11346+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
11347+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
11348+ case FS_MOVED_FROM:
11349+ case FS_MOVED_TO:
11350+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
11351+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11352+ /*FALLTHROUGH*/
11353+ case FS_CREATE:
11354+ AuDebugOn(!h_child_name || !h_child_inode);
11355+ break;
1facf9fc 11356+
4a4d8108
AM
11357+ case FS_DELETE:
11358+ /*
11359+ * aufs never be able to get this child inode.
11360+ * revalidation should be in d_revalidate()
11361+ * by checking i_nlink, i_generation or d_unhashed().
11362+ */
11363+ AuDebugOn(!h_child_name);
11364+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
11365+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
11366+ break;
dece6358 11367+
4a4d8108
AM
11368+ default:
11369+ AuDebugOn(1);
11370+ }
1308ab2a 11371+
4a4d8108
AM
11372+ if (wh)
11373+ h_child_inode = NULL;
1308ab2a 11374+
4a4d8108
AM
11375+ err = -ENOMEM;
11376+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 11377+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
11378+ if (unlikely(!args)) {
11379+ AuErr1("no memory\n");
11380+ iput(dir);
11381+ goto out;
11382+ }
11383+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
11384+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
11385+ args->mask = mask;
11386+ args->dir = dir;
11387+ args->h_dir = igrab(h_dir);
11388+ if (h_child_inode)
11389+ h_child_inode = igrab(h_child_inode); /* can be NULL */
11390+ args->h_child_inode = h_child_inode;
11391+ args->h_child_nlen = len;
11392+ if (len) {
11393+ p = (void *)args;
11394+ p += sizeof(*args);
11395+ memcpy(p, h_child_name, len);
11396+ p[len] = 0;
1308ab2a 11397+ }
1308ab2a 11398+
4a4d8108 11399+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
4a4d8108
AM
11400+ if (unlikely(err)) {
11401+ pr_err("wkq %d\n", err);
11402+ iput(args->h_child_inode);
11403+ iput(args->h_dir);
11404+ iput(args->dir);
11405+ kfree(args);
1facf9fc 11406+ }
1facf9fc 11407+
4a4d8108 11408+out:
1facf9fc 11409+ return err;
11410+}
11411+
4a4d8108
AM
11412+static void au_hn_destroy_cache(void)
11413+{
11414+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
11415+ au_cachep[AuCache_HNOTIFY] = NULL;
11416+}
1308ab2a 11417+
4a4d8108 11418+int __init au_hnotify_init(void)
1facf9fc 11419+{
1308ab2a 11420+ int err;
1308ab2a 11421+
4a4d8108
AM
11422+ err = -ENOMEM;
11423+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
11424+ if (au_cachep[AuCache_HNOTIFY]) {
11425+ err = au_hnotify_op.init();
11426+ if (unlikely(err))
11427+ au_hn_destroy_cache();
1308ab2a 11428+ }
1308ab2a 11429+ AuTraceErr(err);
4a4d8108 11430+ return err;
1308ab2a 11431+}
11432+
4a4d8108 11433+void au_hnotify_fin(void)
1308ab2a 11434+{
4a4d8108
AM
11435+ au_hnotify_op.fin();
11436+ /* cf. au_cache_fin() */
11437+ if (au_cachep[AuCache_HNOTIFY])
11438+ au_hn_destroy_cache();
dece6358 11439+}
e49829fe 11440--- /dev/null
0c5527e5 11441+++ linux-2.6/fs/aufs/iinfo.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 11442@@ -0,0 +1,259 @@
dece6358 11443+/*
4a4d8108 11444+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
11445+ *
11446+ * This program, aufs is free software; you can redistribute it and/or modify
11447+ * it under the terms of the GNU General Public License as published by
11448+ * the Free Software Foundation; either version 2 of the License, or
11449+ * (at your option) any later version.
11450+ *
11451+ * This program is distributed in the hope that it will be useful,
11452+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11453+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11454+ * GNU General Public License for more details.
11455+ *
11456+ * You should have received a copy of the GNU General Public License
11457+ * along with this program; if not, write to the Free Software
11458+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11459+ */
1facf9fc 11460+
dece6358 11461+/*
4a4d8108 11462+ * inode private data
dece6358 11463+ */
1facf9fc 11464+
1308ab2a 11465+#include "aufs.h"
1facf9fc 11466+
4a4d8108 11467+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 11468+{
4a4d8108 11469+ struct inode *h_inode;
1facf9fc 11470+
4a4d8108 11471+ IiMustAnyLock(inode);
1facf9fc 11472+
4a4d8108
AM
11473+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
11474+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11475+ return h_inode;
11476+}
1facf9fc 11477+
4a4d8108
AM
11478+/* todo: hard/soft set? */
11479+void au_hiput(struct au_hinode *hinode)
11480+{
11481+ au_hn_free(hinode);
11482+ dput(hinode->hi_whdentry);
11483+ iput(hinode->hi_inode);
11484+}
1facf9fc 11485+
4a4d8108
AM
11486+unsigned int au_hi_flags(struct inode *inode, int isdir)
11487+{
11488+ unsigned int flags;
11489+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 11490+
4a4d8108
AM
11491+ flags = 0;
11492+ if (au_opt_test(mnt_flags, XINO))
11493+ au_fset_hi(flags, XINO);
11494+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
11495+ au_fset_hi(flags, HNOTIFY);
11496+ return flags;
1facf9fc 11497+}
11498+
4a4d8108
AM
11499+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
11500+ struct inode *h_inode, unsigned int flags)
1308ab2a 11501+{
4a4d8108
AM
11502+ struct au_hinode *hinode;
11503+ struct inode *hi;
11504+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 11505+
4a4d8108 11506+ IiMustWriteLock(inode);
dece6358 11507+
4a4d8108
AM
11508+ hinode = iinfo->ii_hinode + bindex;
11509+ hi = hinode->hi_inode;
11510+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
11511+
11512+ if (hi)
11513+ au_hiput(hinode);
11514+ hinode->hi_inode = h_inode;
11515+ if (h_inode) {
11516+ int err;
11517+ struct super_block *sb = inode->i_sb;
11518+ struct au_branch *br;
11519+
11520+ if (bindex == iinfo->ii_bstart)
11521+ au_cpup_igen(inode, h_inode);
11522+ br = au_sbr(sb, bindex);
11523+ hinode->hi_id = br->br_id;
11524+ if (au_ftest_hi(flags, XINO)) {
11525+ err = au_xino_write(sb, bindex, h_inode->i_ino,
11526+ inode->i_ino);
11527+ if (unlikely(err))
11528+ AuIOErr1("failed au_xino_write() %d\n", err);
11529+ }
11530+
11531+ if (au_ftest_hi(flags, HNOTIFY)
11532+ && au_br_hnotifyable(br->br_perm)) {
11533+ err = au_hn_alloc(hinode, inode, h_inode);
11534+ if (unlikely(err))
11535+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 11536+ }
11537+ }
4a4d8108 11538+}
dece6358 11539+
4a4d8108
AM
11540+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
11541+ struct dentry *h_wh)
11542+{
11543+ struct au_hinode *hinode;
dece6358 11544+
4a4d8108
AM
11545+ IiMustWriteLock(inode);
11546+
11547+ hinode = au_ii(inode)->ii_hinode + bindex;
11548+ AuDebugOn(hinode->hi_whdentry);
11549+ hinode->hi_whdentry = h_wh;
1facf9fc 11550+}
11551+
4a4d8108 11552+void au_update_iigen(struct inode *inode)
1308ab2a 11553+{
4a4d8108
AM
11554+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
11555+ /* smp_mb(); */ /* atomic_set */
11556+}
1facf9fc 11557+
4a4d8108
AM
11558+/* it may be called at remount time, too */
11559+void au_update_ibrange(struct inode *inode, int do_put_zero)
11560+{
11561+ struct au_iinfo *iinfo;
1facf9fc 11562+
4a4d8108
AM
11563+ iinfo = au_ii(inode);
11564+ if (!iinfo || iinfo->ii_bstart < 0)
11565+ return;
1facf9fc 11566+
4a4d8108 11567+ IiMustWriteLock(inode);
1facf9fc 11568+
4a4d8108
AM
11569+ if (do_put_zero) {
11570+ aufs_bindex_t bindex;
1facf9fc 11571+
4a4d8108
AM
11572+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
11573+ bindex++) {
11574+ struct inode *h_i;
1facf9fc 11575+
4a4d8108
AM
11576+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
11577+ if (h_i && !h_i->i_nlink)
11578+ au_set_h_iptr(inode, bindex, NULL, 0);
11579+ }
11580+ }
1308ab2a 11581+
4a4d8108
AM
11582+ iinfo->ii_bstart = -1;
11583+ while (++iinfo->ii_bstart <= iinfo->ii_bend)
11584+ if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
11585+ break;
11586+ if (iinfo->ii_bstart > iinfo->ii_bend) {
11587+ iinfo->ii_bstart = -1;
11588+ iinfo->ii_bend = -1;
11589+ return;
11590+ }
11591+
11592+ iinfo->ii_bend++;
11593+ while (0 <= --iinfo->ii_bend)
11594+ if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
11595+ break;
11596+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
1308ab2a 11597+}
1facf9fc 11598+
dece6358 11599+/* ---------------------------------------------------------------------- */
1facf9fc 11600+
4a4d8108 11601+void au_icntnr_init_once(void *_c)
dece6358 11602+{
4a4d8108
AM
11603+ struct au_icntnr *c = _c;
11604+ struct au_iinfo *iinfo = &c->iinfo;
e49829fe 11605+ static struct lock_class_key aufs_ii;
1facf9fc 11606+
4a4d8108 11607+ au_rw_init(&iinfo->ii_rwsem);
e49829fe 11608+ au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
4a4d8108
AM
11609+ inode_init_once(&c->vfs_inode);
11610+}
1facf9fc 11611+
4a4d8108
AM
11612+int au_iinfo_init(struct inode *inode)
11613+{
11614+ struct au_iinfo *iinfo;
11615+ struct super_block *sb;
11616+ int nbr, i;
1facf9fc 11617+
4a4d8108
AM
11618+ sb = inode->i_sb;
11619+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
11620+ nbr = au_sbend(sb) + 1;
11621+ if (unlikely(nbr <= 0))
11622+ nbr = 1;
11623+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
11624+ if (iinfo->ii_hinode) {
11625+ for (i = 0; i < nbr; i++)
11626+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 11627+
4a4d8108
AM
11628+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
11629+ /* smp_mb(); */ /* atomic_set */
11630+ iinfo->ii_bstart = -1;
11631+ iinfo->ii_bend = -1;
11632+ iinfo->ii_vdir = NULL;
11633+ return 0;
1308ab2a 11634+ }
4a4d8108
AM
11635+ return -ENOMEM;
11636+}
1facf9fc 11637+
4a4d8108
AM
11638+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
11639+{
11640+ int err, sz;
11641+ struct au_hinode *hip;
1facf9fc 11642+
4a4d8108
AM
11643+ AuRwMustWriteLock(&iinfo->ii_rwsem);
11644+
11645+ err = -ENOMEM;
11646+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
11647+ if (!sz)
11648+ sz = sizeof(*hip);
11649+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
11650+ if (hip) {
11651+ iinfo->ii_hinode = hip;
11652+ err = 0;
1308ab2a 11653+ }
4a4d8108 11654+
1308ab2a 11655+ return err;
1facf9fc 11656+}
11657+
4a4d8108 11658+void au_iinfo_fin(struct inode *inode)
1facf9fc 11659+{
4a4d8108
AM
11660+ struct au_iinfo *iinfo;
11661+ struct au_hinode *hi;
11662+ struct super_block *sb;
b752ccd1
AM
11663+ aufs_bindex_t bindex, bend;
11664+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 11665+
4a4d8108
AM
11666+ iinfo = au_ii(inode);
11667+ /* bad_inode case */
11668+ if (!iinfo)
11669+ return;
1308ab2a 11670+
b752ccd1
AM
11671+ sb = inode->i_sb;
11672+ if (si_pid_test(sb))
11673+ au_xino_delete_inode(inode, unlinked);
11674+ else {
11675+ /*
11676+ * it is safe to hide the dependency between sbinfo and
11677+ * sb->s_umount.
11678+ */
11679+ lockdep_off();
11680+ si_noflush_read_lock(sb);
11681+ au_xino_delete_inode(inode, unlinked);
11682+ si_read_unlock(sb);
11683+ lockdep_on();
11684+ }
11685+
4a4d8108
AM
11686+ if (iinfo->ii_vdir)
11687+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 11688+
b752ccd1
AM
11689+ bindex = iinfo->ii_bstart;
11690+ if (bindex >= 0) {
11691+ hi = iinfo->ii_hinode + bindex;
4a4d8108 11692+ bend = iinfo->ii_bend;
b752ccd1
AM
11693+ while (bindex++ <= bend) {
11694+ if (hi->hi_inode)
4a4d8108 11695+ au_hiput(hi);
4a4d8108
AM
11696+ hi++;
11697+ }
11698+ }
4a4d8108
AM
11699+ kfree(iinfo->ii_hinode);
11700+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 11701+}
e49829fe 11702--- /dev/null
0c5527e5 11703+++ linux-2.6/fs/aufs/inode.c 2010-10-25 14:20:44.000000000 +0200
b752ccd1 11704@@ -0,0 +1,443 @@
4a4d8108
AM
11705+/*
11706+ * Copyright (C) 2005-2010 Junjiro R. Okajima
11707+ *
11708+ * This program, aufs is free software; you can redistribute it and/or modify
11709+ * it under the terms of the GNU General Public License as published by
11710+ * the Free Software Foundation; either version 2 of the License, or
11711+ * (at your option) any later version.
11712+ *
11713+ * This program is distributed in the hope that it will be useful,
11714+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11715+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11716+ * GNU General Public License for more details.
11717+ *
11718+ * You should have received a copy of the GNU General Public License
11719+ * along with this program; if not, write to the Free Software
11720+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11721+ */
1facf9fc 11722+
4a4d8108
AM
11723+/*
11724+ * inode functions
11725+ */
1facf9fc 11726+
4a4d8108 11727+#include "aufs.h"
1308ab2a 11728+
4a4d8108
AM
11729+struct inode *au_igrab(struct inode *inode)
11730+{
11731+ if (inode) {
11732+ AuDebugOn(!atomic_read(&inode->i_count));
e49829fe 11733+ atomic_inc(&inode->i_count);
1facf9fc 11734+ }
4a4d8108
AM
11735+ return inode;
11736+}
1facf9fc 11737+
4a4d8108
AM
11738+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
11739+{
11740+ au_cpup_attr_all(inode, /*force*/0);
11741+ au_update_iigen(inode);
11742+ if (do_version)
11743+ inode->i_version++;
dece6358 11744+}
1facf9fc 11745+
4a4d8108 11746+int au_refresh_hinode_self(struct inode *inode, int do_attr)
dece6358 11747+{
4a4d8108
AM
11748+ int err, e;
11749+ aufs_bindex_t bindex, new_bindex;
11750+ unsigned char update;
11751+ struct au_hinode *p, *q, tmp;
1308ab2a 11752+ struct super_block *sb;
4a4d8108 11753+ struct au_iinfo *iinfo;
1facf9fc 11754+
4a4d8108 11755+ IiMustWriteLock(inode);
1facf9fc 11756+
4a4d8108
AM
11757+ update = 0;
11758+ sb = inode->i_sb;
11759+ iinfo = au_ii(inode);
11760+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
11761+ if (unlikely(err))
1308ab2a 11762+ goto out;
1facf9fc 11763+
4a4d8108
AM
11764+ p = iinfo->ii_hinode + iinfo->ii_bstart;
11765+ err = 0;
11766+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
11767+ bindex++, p++) {
11768+ if (!p->hi_inode)
11769+ continue;
1facf9fc 11770+
4a4d8108
AM
11771+ new_bindex = au_br_index(sb, p->hi_id);
11772+ if (new_bindex == bindex)
11773+ continue;
1facf9fc 11774+
4a4d8108
AM
11775+ if (new_bindex < 0) {
11776+ update = 1;
11777+ au_hiput(p);
11778+ p->hi_inode = NULL;
11779+ continue;
1308ab2a 11780+ }
4a4d8108
AM
11781+
11782+ if (new_bindex < iinfo->ii_bstart)
11783+ iinfo->ii_bstart = new_bindex;
11784+ if (iinfo->ii_bend < new_bindex)
11785+ iinfo->ii_bend = new_bindex;
11786+ /* swap two lower inode, and loop again */
11787+ q = iinfo->ii_hinode + new_bindex;
11788+ tmp = *q;
11789+ *q = *p;
11790+ *p = tmp;
11791+ if (tmp.hi_inode) {
11792+ bindex--;
11793+ p--;
1308ab2a 11794+ }
11795+ }
4a4d8108
AM
11796+ au_update_ibrange(inode, /*do_put_zero*/0);
11797+ e = au_dy_irefresh(inode);
11798+ if (unlikely(e && !err))
11799+ err = e;
11800+ if (do_attr)
11801+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
1facf9fc 11802+
4f0767ce 11803+out:
4a4d8108
AM
11804+ return err;
11805+}
1facf9fc 11806+
4a4d8108
AM
11807+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
11808+{
11809+ int err, e;
11810+ unsigned int flags;
11811+ aufs_bindex_t bindex, bend;
11812+ unsigned char isdir, update;
11813+ struct au_hinode *p;
11814+ struct au_iinfo *iinfo;
1facf9fc 11815+
4a4d8108
AM
11816+ err = au_refresh_hinode_self(inode, /*do_attr*/0);
11817+ if (unlikely(err))
11818+ goto out;
11819+
11820+ update = 0;
11821+ iinfo = au_ii(inode);
11822+ p = iinfo->ii_hinode + iinfo->ii_bstart;
11823+ isdir = S_ISDIR(inode->i_mode);
11824+ flags = au_hi_flags(inode, isdir);
11825+ bend = au_dbend(dentry);
11826+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
11827+ struct inode *h_i;
11828+ struct dentry *h_d;
11829+
11830+ h_d = au_h_dptr(dentry, bindex);
11831+ if (!h_d || !h_d->d_inode)
11832+ continue;
11833+
11834+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
11835+ h_i = au_h_iptr(inode, bindex);
11836+ if (h_i) {
11837+ if (h_i == h_d->d_inode)
11838+ continue;
11839+ err = -EIO;
11840+ break;
11841+ }
11842+ }
11843+ if (bindex < iinfo->ii_bstart)
11844+ iinfo->ii_bstart = bindex;
11845+ if (iinfo->ii_bend < bindex)
11846+ iinfo->ii_bend = bindex;
11847+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
11848+ update = 1;
1308ab2a 11849+ }
4a4d8108
AM
11850+ au_update_ibrange(inode, /*do_put_zero*/0);
11851+ e = au_dy_irefresh(inode);
11852+ if (unlikely(e && !err))
11853+ err = e;
11854+ au_refresh_hinode_attr(inode, update && isdir);
11855+
4f0767ce 11856+out:
4a4d8108 11857+ AuTraceErr(err);
1308ab2a 11858+ return err;
dece6358
AM
11859+}
11860+
4a4d8108 11861+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 11862+{
4a4d8108
AM
11863+ int err;
11864+ unsigned int flags;
11865+ umode_t mode;
11866+ aufs_bindex_t bindex, bstart, btail;
11867+ unsigned char isdir;
11868+ struct dentry *h_dentry;
11869+ struct inode *h_inode;
11870+ struct au_iinfo *iinfo;
dece6358 11871+
4a4d8108 11872+ IiMustWriteLock(inode);
dece6358 11873+
4a4d8108
AM
11874+ err = 0;
11875+ isdir = 0;
11876+ bstart = au_dbstart(dentry);
11877+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
11878+ mode = h_inode->i_mode;
11879+ switch (mode & S_IFMT) {
11880+ case S_IFREG:
11881+ btail = au_dbtail(dentry);
11882+ inode->i_op = &aufs_iop;
11883+ inode->i_fop = &aufs_file_fop;
11884+ err = au_dy_iaop(inode, bstart, h_inode);
11885+ if (unlikely(err))
11886+ goto out;
11887+ break;
11888+ case S_IFDIR:
11889+ isdir = 1;
11890+ btail = au_dbtaildir(dentry);
11891+ inode->i_op = &aufs_dir_iop;
11892+ inode->i_fop = &aufs_dir_fop;
11893+ break;
11894+ case S_IFLNK:
11895+ btail = au_dbtail(dentry);
11896+ inode->i_op = &aufs_symlink_iop;
11897+ break;
11898+ case S_IFBLK:
11899+ case S_IFCHR:
11900+ case S_IFIFO:
11901+ case S_IFSOCK:
11902+ btail = au_dbtail(dentry);
11903+ inode->i_op = &aufs_iop;
11904+ au_init_special_fop(inode, mode, h_inode->i_rdev);
11905+ break;
11906+ default:
11907+ AuIOErr("Unknown file type 0%o\n", mode);
11908+ err = -EIO;
1308ab2a 11909+ goto out;
4a4d8108 11910+ }
dece6358 11911+
4a4d8108
AM
11912+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
11913+ flags = au_hi_flags(inode, isdir);
11914+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
11915+ && au_ftest_hi(flags, HNOTIFY)
11916+ && dentry->d_name.len > AUFS_WH_PFX_LEN
11917+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
11918+ au_fclr_hi(flags, HNOTIFY);
11919+ iinfo = au_ii(inode);
11920+ iinfo->ii_bstart = bstart;
11921+ iinfo->ii_bend = btail;
11922+ for (bindex = bstart; bindex <= btail; bindex++) {
11923+ h_dentry = au_h_dptr(dentry, bindex);
11924+ if (h_dentry)
11925+ au_set_h_iptr(inode, bindex,
11926+ au_igrab(h_dentry->d_inode), flags);
11927+ }
11928+ au_cpup_attr_all(inode, /*force*/1);
dece6358 11929+
4f0767ce 11930+out:
4a4d8108
AM
11931+ return err;
11932+}
dece6358 11933+
4a4d8108
AM
11934+/* successful returns with iinfo write_locked */
11935+static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
11936+{
11937+ int err;
11938+ aufs_bindex_t bindex, bend;
11939+ struct inode *h_inode, *h_dinode;
dece6358 11940+
4a4d8108 11941+ *matched = 0;
dece6358 11942+
4a4d8108
AM
11943+ /*
11944+ * before this function, if aufs got any iinfo lock, it must be only
11945+ * one, the parent dir.
11946+ * it can happen by UDBA and the obsoleted inode number.
11947+ */
11948+ err = -EIO;
11949+ if (unlikely(inode->i_ino == parent_ino(dentry)))
11950+ goto out;
11951+
11952+ err = 0;
11953+ ii_write_lock_new_child(inode);
11954+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
11955+ bend = au_ibend(inode);
11956+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
11957+ h_inode = au_h_iptr(inode, bindex);
11958+ if (h_inode && h_inode == h_dinode) {
11959+ *matched = 1;
11960+ err = 0;
11961+ if (au_iigen(inode) != au_digen(dentry))
11962+ err = au_refresh_hinode(inode, dentry);
11963+ break;
1308ab2a 11964+ }
1facf9fc 11965+ }
dece6358 11966+
4a4d8108
AM
11967+ if (unlikely(err))
11968+ ii_write_unlock(inode);
4f0767ce 11969+out:
1facf9fc 11970+ return err;
11971+}
1facf9fc 11972+
4a4d8108
AM
11973+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
11974+ unsigned int d_type, ino_t *ino)
1facf9fc 11975+{
4a4d8108
AM
11976+ int err;
11977+ struct mutex *mtx;
1facf9fc 11978+
b752ccd1 11979+ /* prevent hardlinked inode number from race condition */
4a4d8108 11980+ mtx = NULL;
b752ccd1 11981+ if (d_type != DT_DIR) {
4a4d8108
AM
11982+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
11983+ mutex_lock(mtx);
11984+ }
11985+ err = au_xino_read(sb, bindex, h_ino, ino);
11986+ if (unlikely(err))
11987+ goto out;
1308ab2a 11988+
4a4d8108
AM
11989+ if (!*ino) {
11990+ err = -EIO;
11991+ *ino = au_xino_new_ino(sb);
11992+ if (unlikely(!*ino))
1facf9fc 11993+ goto out;
4a4d8108
AM
11994+ err = au_xino_write(sb, bindex, h_ino, *ino);
11995+ if (unlikely(err))
1308ab2a 11996+ goto out;
1308ab2a 11997+ }
1facf9fc 11998+
4f0767ce 11999+out:
b752ccd1 12000+ if (mtx)
4a4d8108 12001+ mutex_unlock(mtx);
1facf9fc 12002+ return err;
12003+}
12004+
4a4d8108
AM
12005+/* successful returns with iinfo write_locked */
12006+/* todo: return with unlocked? */
12007+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 12008+{
b752ccd1 12009+ struct inode *inode, *h_inode;
4a4d8108
AM
12010+ struct dentry *h_dentry;
12011+ struct super_block *sb;
b752ccd1 12012+ struct mutex *mtx;
4a4d8108
AM
12013+ ino_t h_ino, ino;
12014+ int err, match;
12015+ aufs_bindex_t bstart;
1facf9fc 12016+
4a4d8108
AM
12017+ sb = dentry->d_sb;
12018+ bstart = au_dbstart(dentry);
12019+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
12020+ h_inode = h_dentry->d_inode;
12021+ h_ino = h_inode->i_ino;
12022+
12023+ /*
12024+ * stop 'race'-ing between hardlinks under different
12025+ * parents.
12026+ */
12027+ mtx = NULL;
12028+ if (!S_ISDIR(h_inode->i_mode))
12029+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
12030+
4f0767ce 12031+new_ino:
b752ccd1
AM
12032+ if (mtx)
12033+ mutex_lock(mtx);
4a4d8108
AM
12034+ err = au_xino_read(sb, bstart, h_ino, &ino);
12035+ inode = ERR_PTR(err);
12036+ if (unlikely(err))
12037+ goto out;
b752ccd1 12038+
4a4d8108
AM
12039+ if (!ino) {
12040+ ino = au_xino_new_ino(sb);
12041+ if (unlikely(!ino)) {
12042+ inode = ERR_PTR(-EIO);
dece6358
AM
12043+ goto out;
12044+ }
12045+ }
1facf9fc 12046+
4a4d8108
AM
12047+ AuDbg("i%lu\n", (unsigned long)ino);
12048+ inode = au_iget_locked(sb, ino);
12049+ err = PTR_ERR(inode);
12050+ if (IS_ERR(inode))
1facf9fc 12051+ goto out;
1facf9fc 12052+
4a4d8108
AM
12053+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
12054+ if (inode->i_state & I_NEW) {
12055+ ii_write_lock_new_child(inode);
12056+ err = set_inode(inode, dentry);
12057+ if (!err) {
12058+ unlock_new_inode(inode);
12059+ goto out; /* success */
12060+ }
1308ab2a 12061+
4a4d8108
AM
12062+ ii_write_unlock(inode);
12063+ iget_failed(inode);
12064+ goto out_err;
12065+ } else if (!must_new) {
b752ccd1
AM
12066+ /*
12067+ * horrible race condition between lookup, readdir and copyup
12068+ * (or something).
12069+ */
12070+ if (mtx)
12071+ mutex_unlock(mtx);
4a4d8108 12072+ err = reval_inode(inode, dentry, &match);
b752ccd1
AM
12073+ if (!err) {
12074+ mtx = NULL;
4a4d8108 12075+ goto out; /* success */
b752ccd1
AM
12076+ } else if (match) {
12077+ mtx = NULL;
4a4d8108 12078+ goto out_iput;
b752ccd1
AM
12079+ } else if (mtx)
12080+ mutex_lock(mtx);
4a4d8108
AM
12081+ }
12082+
12083+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
12084+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
12085+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
12086+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
12087+ (unsigned long)h_ino, (unsigned long)ino);
12088+ ino = 0;
12089+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
12090+ if (!err) {
12091+ iput(inode);
b752ccd1
AM
12092+ if (mtx)
12093+ mutex_unlock(mtx);
4a4d8108
AM
12094+ goto new_ino;
12095+ }
1308ab2a 12096+
4f0767ce 12097+out_iput:
4a4d8108 12098+ iput(inode);
4f0767ce 12099+out_err:
4a4d8108 12100+ inode = ERR_PTR(err);
4f0767ce 12101+out:
b752ccd1
AM
12102+ if (mtx)
12103+ mutex_unlock(mtx);
4a4d8108 12104+ return inode;
1facf9fc 12105+}
12106+
4a4d8108 12107+/* ---------------------------------------------------------------------- */
1facf9fc 12108+
4a4d8108
AM
12109+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12110+ struct inode *inode)
12111+{
12112+ int err;
1facf9fc 12113+
4a4d8108 12114+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 12115+
4a4d8108
AM
12116+ /* pseudo-link after flushed may happen out of bounds */
12117+ if (!err
12118+ && inode
12119+ && au_ibstart(inode) <= bindex
12120+ && bindex <= au_ibend(inode)) {
12121+ /*
12122+ * permission check is unnecessary since vfsub routine
12123+ * will be called later
12124+ */
12125+ struct inode *hi = au_h_iptr(inode, bindex);
12126+ if (hi)
12127+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 12128+ }
12129+
4a4d8108
AM
12130+ return err;
12131+}
dece6358 12132+
4a4d8108
AM
12133+int au_test_h_perm(struct inode *h_inode, int mask)
12134+{
12135+ if (!current_fsuid())
12136+ return 0;
12137+ return inode_permission(h_inode, mask);
12138+}
1facf9fc 12139+
4a4d8108
AM
12140+int au_test_h_perm_sio(struct inode *h_inode, int mask)
12141+{
12142+ if (au_test_nfs(h_inode->i_sb)
12143+ && (mask & MAY_WRITE)
12144+ && S_ISDIR(h_inode->i_mode))
12145+ mask |= MAY_READ; /* force permission check */
12146+ return au_test_h_perm(h_inode, mask);
1facf9fc 12147+}
e49829fe 12148--- /dev/null
0c5527e5 12149+++ linux-2.6/fs/aufs/inode.h 2010-10-26 10:58:14.000000000 +0200
e49829fe 12150@@ -0,0 +1,514 @@
4a4d8108
AM
12151+/*
12152+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12153+ *
12154+ * This program, aufs is free software; you can redistribute it and/or modify
12155+ * it under the terms of the GNU General Public License as published by
12156+ * the Free Software Foundation; either version 2 of the License, or
12157+ * (at your option) any later version.
12158+ *
12159+ * This program is distributed in the hope that it will be useful,
12160+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12161+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12162+ * GNU General Public License for more details.
12163+ *
12164+ * You should have received a copy of the GNU General Public License
12165+ * along with this program; if not, write to the Free Software
12166+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12167+ */
1facf9fc 12168+
1308ab2a 12169+/*
4a4d8108 12170+ * inode operations
1308ab2a 12171+ */
dece6358 12172+
4a4d8108
AM
12173+#ifndef __AUFS_INODE_H__
12174+#define __AUFS_INODE_H__
dece6358 12175+
4a4d8108 12176+#ifdef __KERNEL__
1308ab2a 12177+
4a4d8108
AM
12178+#include <linux/fs.h>
12179+#include <linux/fsnotify.h>
12180+#include <linux/aufs_type.h>
12181+#include "rwsem.h"
1308ab2a 12182+
4a4d8108 12183+struct vfsmount;
1facf9fc 12184+
4a4d8108
AM
12185+struct au_hnotify {
12186+#ifdef CONFIG_AUFS_HNOTIFY
12187+#ifdef CONFIG_AUFS_HFSNOTIFY
0c5527e5 12188+ struct fsnotify_mark hn_mark;
e49829fe
JR
12189+#else
12190+ struct inotify_watch hn_watch;
4a4d8108 12191+#endif
0c5527e5 12192+ struct inode *hn_aufs_inode; /* no get/put */
4a4d8108
AM
12193+#endif
12194+} ____cacheline_aligned_in_smp;
1facf9fc 12195+
4a4d8108
AM
12196+struct au_hinode {
12197+ struct inode *hi_inode;
12198+ aufs_bindex_t hi_id;
12199+#ifdef CONFIG_AUFS_HNOTIFY
12200+ struct au_hnotify *hi_notify;
12201+#endif
dece6358 12202+
4a4d8108
AM
12203+ /* reference to the copied-up whiteout with get/put */
12204+ struct dentry *hi_whdentry;
12205+};
dece6358 12206+
4a4d8108
AM
12207+struct au_vdir;
12208+struct au_iinfo {
12209+ atomic_t ii_generation;
12210+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 12211+
4a4d8108
AM
12212+ struct au_rwsem ii_rwsem;
12213+ aufs_bindex_t ii_bstart, ii_bend;
12214+ __u32 ii_higen;
12215+ struct au_hinode *ii_hinode;
12216+ struct au_vdir *ii_vdir;
12217+};
1facf9fc 12218+
4a4d8108
AM
12219+struct au_icntnr {
12220+ struct au_iinfo iinfo;
12221+ struct inode vfs_inode;
12222+} ____cacheline_aligned_in_smp;
1308ab2a 12223+
4a4d8108
AM
12224+/* au_pin flags */
12225+#define AuPin_DI_LOCKED 1
12226+#define AuPin_MNT_WRITE (1 << 1)
12227+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
12228+#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
12229+#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
12230+
12231+struct au_pin {
12232+ /* input */
12233+ struct dentry *dentry;
12234+ unsigned int udba;
12235+ unsigned char lsc_di, lsc_hi, flags;
12236+ aufs_bindex_t bindex;
12237+
12238+ /* output */
12239+ struct dentry *parent;
12240+ struct au_hinode *hdir;
12241+ struct vfsmount *h_mnt;
12242+};
1facf9fc 12243+
1308ab2a 12244+/* ---------------------------------------------------------------------- */
12245+
4a4d8108 12246+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 12247+{
4a4d8108 12248+ struct au_iinfo *iinfo;
1facf9fc 12249+
4a4d8108
AM
12250+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12251+ if (iinfo->ii_hinode)
12252+ return iinfo;
12253+ return NULL; /* debugging bad_inode case */
12254+}
1facf9fc 12255+
4a4d8108 12256+/* ---------------------------------------------------------------------- */
1facf9fc 12257+
4a4d8108
AM
12258+/* inode.c */
12259+struct inode *au_igrab(struct inode *inode);
12260+int au_refresh_hinode_self(struct inode *inode, int do_attr);
12261+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
12262+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12263+ unsigned int d_type, ino_t *ino);
12264+struct inode *au_new_inode(struct dentry *dentry, int must_new);
12265+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12266+ struct inode *inode);
12267+int au_test_h_perm(struct inode *h_inode, int mask);
12268+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 12269+
4a4d8108
AM
12270+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
12271+ ino_t h_ino, unsigned int d_type, ino_t *ino)
12272+{
12273+#ifdef CONFIG_AUFS_SHWH
12274+ return au_ino(sb, bindex, h_ino, d_type, ino);
12275+#else
12276+ return 0;
12277+#endif
12278+}
1facf9fc 12279+
4a4d8108
AM
12280+/* i_op.c */
12281+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 12282+
4a4d8108
AM
12283+/* au_wr_dir flags */
12284+#define AuWrDir_ADD_ENTRY 1
12285+#define AuWrDir_ISDIR (1 << 1)
12286+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
12287+#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
12288+#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
1facf9fc 12289+
4a4d8108
AM
12290+struct au_wr_dir_args {
12291+ aufs_bindex_t force_btgt;
12292+ unsigned char flags;
12293+};
12294+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
12295+ struct au_wr_dir_args *args);
dece6358 12296+
4a4d8108
AM
12297+struct dentry *au_pinned_h_parent(struct au_pin *pin);
12298+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
12299+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
12300+ unsigned int udba, unsigned char flags);
12301+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
12302+ unsigned int udba, unsigned char flags) __must_check;
12303+int au_do_pin(struct au_pin *pin) __must_check;
12304+void au_unpin(struct au_pin *pin);
1facf9fc 12305+
4a4d8108
AM
12306+/* i_op_add.c */
12307+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
12308+ struct dentry *h_parent, int isdir);
12309+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
12310+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
12311+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
12312+ struct nameidata *nd);
12313+int aufs_link(struct dentry *src_dentry, struct inode *dir,
12314+ struct dentry *dentry);
12315+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
1facf9fc 12316+
4a4d8108
AM
12317+/* i_op_del.c */
12318+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
12319+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
12320+ struct dentry *h_parent, int isdir);
12321+int aufs_unlink(struct inode *dir, struct dentry *dentry);
12322+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 12323+
4a4d8108
AM
12324+/* i_op_ren.c */
12325+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
12326+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
12327+ struct inode *dir, struct dentry *dentry);
1facf9fc 12328+
4a4d8108
AM
12329+/* iinfo.c */
12330+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
12331+void au_hiput(struct au_hinode *hinode);
12332+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12333+ struct dentry *h_wh);
12334+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 12335+
4a4d8108
AM
12336+/* hinode flags */
12337+#define AuHi_XINO 1
12338+#define AuHi_HNOTIFY (1 << 1)
12339+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
12340+#define au_fset_hi(flags, name) { (flags) |= AuHi_##name; }
12341+#define au_fclr_hi(flags, name) { (flags) &= ~AuHi_##name; }
1facf9fc 12342+
4a4d8108
AM
12343+#ifndef CONFIG_AUFS_HNOTIFY
12344+#undef AuHi_HNOTIFY
12345+#define AuHi_HNOTIFY 0
12346+#endif
1facf9fc 12347+
4a4d8108
AM
12348+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12349+ struct inode *h_inode, unsigned int flags);
1facf9fc 12350+
4a4d8108
AM
12351+void au_update_iigen(struct inode *inode);
12352+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 12353+
4a4d8108
AM
12354+void au_icntnr_init_once(void *_c);
12355+int au_iinfo_init(struct inode *inode);
12356+void au_iinfo_fin(struct inode *inode);
12357+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 12358+
e49829fe 12359+#ifdef CONFIG_PROC_FS
4a4d8108 12360+/* plink.c */
e49829fe
JR
12361+int au_plink_maint(struct super_block *sb, int flags);
12362+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
12363+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
12364+#ifdef CONFIG_AUFS_DEBUG
12365+void au_plink_list(struct super_block *sb);
12366+#else
12367+AuStubVoid(au_plink_list, struct super_block *sb)
12368+#endif
12369+int au_plink_test(struct inode *inode);
12370+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
12371+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
12372+ struct dentry *h_dentry);
e49829fe
JR
12373+void au_plink_put(struct super_block *sb, int verbose);
12374+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 12375+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
12376+#else
12377+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
12378+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
12379+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
12380+AuStubVoid(au_plink_list, struct super_block *sb);
12381+AuStubInt0(au_plink_test, struct inode *inode);
12382+AuStub(struct dentry *, au_plink_lkup, return NULL,
12383+ struct inode *inode, aufs_bindex_t bindex);
12384+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
12385+ struct dentry *h_dentry);
12386+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
12387+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
12388+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
12389+#endif /* CONFIG_PROC_FS */
1facf9fc 12390+
4a4d8108 12391+/* ---------------------------------------------------------------------- */
1308ab2a 12392+
4a4d8108
AM
12393+/* lock subclass for iinfo */
12394+enum {
12395+ AuLsc_II_CHILD, /* child first */
12396+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
12397+ AuLsc_II_CHILD3, /* copyup dirs */
12398+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
12399+ AuLsc_II_PARENT2,
12400+ AuLsc_II_PARENT3, /* copyup dirs */
12401+ AuLsc_II_NEW_CHILD
12402+};
1308ab2a 12403+
1facf9fc 12404+/*
4a4d8108
AM
12405+ * ii_read_lock_child, ii_write_lock_child,
12406+ * ii_read_lock_child2, ii_write_lock_child2,
12407+ * ii_read_lock_child3, ii_write_lock_child3,
12408+ * ii_read_lock_parent, ii_write_lock_parent,
12409+ * ii_read_lock_parent2, ii_write_lock_parent2,
12410+ * ii_read_lock_parent3, ii_write_lock_parent3,
12411+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 12412+ */
4a4d8108
AM
12413+#define AuReadLockFunc(name, lsc) \
12414+static inline void ii_read_lock_##name(struct inode *i) \
12415+{ \
12416+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12417+}
12418+
12419+#define AuWriteLockFunc(name, lsc) \
12420+static inline void ii_write_lock_##name(struct inode *i) \
12421+{ \
12422+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
12423+}
12424+
12425+#define AuRWLockFuncs(name, lsc) \
12426+ AuReadLockFunc(name, lsc) \
12427+ AuWriteLockFunc(name, lsc)
12428+
12429+AuRWLockFuncs(child, CHILD);
12430+AuRWLockFuncs(child2, CHILD2);
12431+AuRWLockFuncs(child3, CHILD3);
12432+AuRWLockFuncs(parent, PARENT);
12433+AuRWLockFuncs(parent2, PARENT2);
12434+AuRWLockFuncs(parent3, PARENT3);
12435+AuRWLockFuncs(new_child, NEW_CHILD);
12436+
12437+#undef AuReadLockFunc
12438+#undef AuWriteLockFunc
12439+#undef AuRWLockFuncs
1facf9fc 12440+
12441+/*
4a4d8108 12442+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 12443+ */
4a4d8108 12444+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 12445+
4a4d8108
AM
12446+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
12447+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
12448+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 12449+
4a4d8108 12450+/* ---------------------------------------------------------------------- */
1308ab2a 12451+
4a4d8108
AM
12452+static inline unsigned int au_iigen(struct inode *inode)
12453+{
12454+ return atomic_read(&au_ii(inode)->ii_generation);
12455+}
1308ab2a 12456+
4a4d8108
AM
12457+/* tiny test for inode number */
12458+/* tmpfs generation is too rough */
12459+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
12460+{
12461+ struct au_iinfo *iinfo;
1308ab2a 12462+
4a4d8108
AM
12463+ iinfo = au_ii(inode);
12464+ AuRwMustAnyLock(&iinfo->ii_rwsem);
12465+ return !(iinfo->ii_hsb1 == h_inode->i_sb
12466+ && iinfo->ii_higen == h_inode->i_generation);
12467+}
1308ab2a 12468+
4a4d8108
AM
12469+static inline void au_iigen_dec(struct inode *inode)
12470+{
12471+#ifdef CONFIG_AUFS_HNOTIFY
e49829fe 12472+ atomic_dec(&au_ii(inode)->ii_generation);
4a4d8108
AM
12473+#endif
12474+}
1308ab2a 12475+
4a4d8108 12476+/* ---------------------------------------------------------------------- */
1308ab2a 12477+
4a4d8108
AM
12478+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
12479+ aufs_bindex_t bindex)
12480+{
12481+ IiMustAnyLock(inode);
12482+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
12483+}
1308ab2a 12484+
4a4d8108
AM
12485+static inline aufs_bindex_t au_ibstart(struct inode *inode)
12486+{
12487+ IiMustAnyLock(inode);
12488+ return au_ii(inode)->ii_bstart;
12489+}
1308ab2a 12490+
4a4d8108
AM
12491+static inline aufs_bindex_t au_ibend(struct inode *inode)
12492+{
12493+ IiMustAnyLock(inode);
12494+ return au_ii(inode)->ii_bend;
12495+}
1308ab2a 12496+
4a4d8108
AM
12497+static inline struct au_vdir *au_ivdir(struct inode *inode)
12498+{
12499+ IiMustAnyLock(inode);
12500+ return au_ii(inode)->ii_vdir;
12501+}
1308ab2a 12502+
4a4d8108
AM
12503+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
12504+{
12505+ IiMustAnyLock(inode);
12506+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
12507+}
1308ab2a 12508+
4a4d8108 12509+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12510+{
4a4d8108
AM
12511+ IiMustWriteLock(inode);
12512+ au_ii(inode)->ii_bstart = bindex;
12513+}
1308ab2a 12514+
4a4d8108
AM
12515+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
12516+{
12517+ IiMustWriteLock(inode);
12518+ au_ii(inode)->ii_bend = bindex;
1308ab2a 12519+}
12520+
4a4d8108
AM
12521+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
12522+{
12523+ IiMustWriteLock(inode);
12524+ au_ii(inode)->ii_vdir = vdir;
12525+}
1facf9fc 12526+
4a4d8108 12527+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12528+{
4a4d8108
AM
12529+ IiMustAnyLock(inode);
12530+ return au_ii(inode)->ii_hinode + bindex;
12531+}
dece6358 12532+
4a4d8108 12533+/* ---------------------------------------------------------------------- */
1facf9fc 12534+
4a4d8108
AM
12535+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
12536+{
12537+ if (pin)
12538+ return pin->parent;
12539+ return NULL;
1facf9fc 12540+}
12541+
4a4d8108 12542+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 12543+{
4a4d8108
AM
12544+ if (pin && pin->hdir)
12545+ return pin->hdir->hi_inode;
12546+ return NULL;
1308ab2a 12547+}
1facf9fc 12548+
4a4d8108
AM
12549+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
12550+{
12551+ if (pin)
12552+ return pin->hdir;
12553+ return NULL;
12554+}
1facf9fc 12555+
4a4d8108 12556+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 12557+{
4a4d8108
AM
12558+ if (pin)
12559+ pin->dentry = dentry;
12560+}
1308ab2a 12561+
4a4d8108
AM
12562+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
12563+ unsigned char lflag)
12564+{
12565+ if (pin) {
12566+ /* dirty macros require brackets */
12567+ if (lflag) {
12568+ au_fset_pin(pin->flags, DI_LOCKED);
12569+ } else {
12570+ au_fclr_pin(pin->flags, DI_LOCKED);
12571+ }
1308ab2a 12572+ }
4a4d8108
AM
12573+}
12574+
12575+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
12576+{
12577+ if (pin) {
12578+ dput(pin->parent);
12579+ pin->parent = dget(parent);
1facf9fc 12580+ }
4a4d8108 12581+}
1facf9fc 12582+
4a4d8108
AM
12583+/* ---------------------------------------------------------------------- */
12584+
12585+#ifdef CONFIG_AUFS_HNOTIFY
12586+struct au_hnotify_op {
12587+ void (*ctl)(struct au_hinode *hinode, int do_set);
12588+ int (*alloc)(struct au_hnotify *hn, struct inode *h_inode);
12589+ void (*free)(struct au_hnotify *hn);
12590+
12591+ void (*fin)(void);
12592+ int (*init)(void);
12593+};
12594+
12595+/* hnotify.c */
12596+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
12597+ struct inode *h_inode);
12598+void au_hn_free(struct au_hinode *hinode);
12599+void au_hn_ctl(struct au_hinode *hinode, int do_set);
12600+void au_hn_reset(struct inode *inode, unsigned int flags);
12601+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
12602+ struct qstr *h_child_qstr, struct inode *h_child_inode);
12603+int __init au_hnotify_init(void);
12604+void au_hnotify_fin(void);
12605+
e49829fe 12606+/* hinotify.c */
4a4d8108
AM
12607+extern const struct au_hnotify_op au_hnotify_op;
12608+
12609+static inline
12610+void au_hn_init(struct au_hinode *hinode)
12611+{
12612+ hinode->hi_notify = NULL;
1308ab2a 12613+}
12614+
4a4d8108
AM
12615+#else
12616+static inline
12617+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
12618+ struct inode *inode __maybe_unused,
12619+ struct inode *h_inode __maybe_unused)
1308ab2a 12620+{
4a4d8108
AM
12621+ return -EOPNOTSUPP;
12622+}
1308ab2a 12623+
4a4d8108
AM
12624+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
12625+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
12626+ int do_set __maybe_unused)
12627+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
12628+ unsigned int flags __maybe_unused)
12629+AuStubInt0(__init au_hnotify_init, void)
12630+AuStubVoid(au_hnotify_fin, void)
12631+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
12632+#endif /* CONFIG_AUFS_HNOTIFY */
12633+
12634+static inline void au_hn_suspend(struct au_hinode *hdir)
12635+{
12636+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 12637+}
12638+
4a4d8108 12639+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 12640+{
4a4d8108
AM
12641+ au_hn_ctl(hdir, /*do_set*/1);
12642+}
1308ab2a 12643+
4a4d8108
AM
12644+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
12645+{
12646+ mutex_lock(&hdir->hi_inode->i_mutex);
12647+ au_hn_suspend(hdir);
12648+}
dece6358 12649+
4a4d8108
AM
12650+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
12651+ unsigned int sc __maybe_unused)
12652+{
12653+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
12654+ au_hn_suspend(hdir);
1facf9fc 12655+}
1facf9fc 12656+
4a4d8108
AM
12657+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
12658+{
12659+ au_hn_resume(hdir);
12660+ mutex_unlock(&hdir->hi_inode->i_mutex);
12661+}
12662+
12663+#endif /* __KERNEL__ */
12664+#endif /* __AUFS_INODE_H__ */
e49829fe 12665--- /dev/null
0c5527e5 12666+++ linux-2.6/fs/aufs/ioctl.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 12667@@ -0,0 +1,150 @@
4a4d8108
AM
12668+/*
12669+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12670+ *
12671+ * This program, aufs is free software; you can redistribute it and/or modify
12672+ * it under the terms of the GNU General Public License as published by
12673+ * the Free Software Foundation; either version 2 of the License, or
12674+ * (at your option) any later version.
12675+ *
12676+ * This program is distributed in the hope that it will be useful,
12677+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12678+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12679+ * GNU General Public License for more details.
12680+ *
12681+ * You should have received a copy of the GNU General Public License
12682+ * along with this program; if not, write to the Free Software
12683+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12684+ */
12685+
12686+/*
12687+ * ioctl
12688+ * plink-management and readdir in userspace.
12689+ * assist the pathconf(3) wrapper library.
12690+ */
12691+
12692+#include <linux/file.h>
12693+#include "aufs.h"
12694+
12695+static int au_wbr_fd(struct path *path)
12696+{
12697+ int err, fd;
12698+ aufs_bindex_t wbi, bindex, bend;
12699+ struct file *h_file;
12700+ struct super_block *sb;
12701+ struct dentry *root;
12702+ struct au_branch *wbr;
12703+
12704+ err = get_unused_fd();
12705+ if (unlikely(err < 0))
12706+ goto out;
12707+ fd = err;
12708+
12709+ wbi = 0;
12710+ sb = path->dentry->d_sb;
12711+ root = sb->s_root;
12712+ aufs_read_lock(root, AuLock_IR);
12713+ wbr = au_sbr(sb, wbi);
12714+ if (!(path->mnt->mnt_flags & MNT_READONLY)
12715+ && !au_br_writable(wbr->br_perm)) {
12716+ bend = au_sbend(sb);
12717+ for (bindex = 1; bindex <= bend; bindex++) {
12718+ wbr = au_sbr(sb, bindex);
12719+ if (au_br_writable(wbr->br_perm)) {
12720+ wbi = bindex;
12721+ break;
12722+ }
12723+ }
12724+ wbr = au_sbr(sb, wbi);
12725+ }
12726+ AuDbg("wbi %d\n", wbi);
12727+ h_file = au_h_open(root, wbi, O_RDONLY | O_DIRECTORY | O_LARGEFILE,
12728+ NULL);
12729+ aufs_read_unlock(root, AuLock_IR);
12730+ err = PTR_ERR(h_file);
12731+ if (IS_ERR(h_file))
12732+ goto out_fd;
12733+
12734+ atomic_dec(&wbr->br_count); /* cf. au_h_open() */
12735+ fd_install(fd, h_file);
12736+ err = fd;
12737+ goto out; /* success */
12738+
4f0767ce 12739+out_fd:
4a4d8108 12740+ put_unused_fd(fd);
4f0767ce 12741+out:
4a4d8108
AM
12742+ return err;
12743+}
12744+
12745+/* ---------------------------------------------------------------------- */
12746+
12747+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
12748+{
12749+ long err;
12750+
12751+ switch (cmd) {
4a4d8108
AM
12752+ case AUFS_CTL_RDU:
12753+ case AUFS_CTL_RDU_INO:
12754+ err = au_rdu_ioctl(file, cmd, arg);
12755+ break;
12756+
12757+ case AUFS_CTL_WBR_FD:
12758+ err = au_wbr_fd(&file->f_path);
12759+ break;
12760+
12761+ default:
12762+ /* do not call the lower */
12763+ AuDbg("0x%x\n", cmd);
12764+ err = -ENOTTY;
12765+ }
12766+
12767+ AuTraceErr(err);
12768+ return err;
12769+}
12770+
12771+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
12772+{
12773+ long err;
12774+
12775+ switch (cmd) {
12776+ case AUFS_CTL_WBR_FD:
12777+ err = au_wbr_fd(&file->f_path);
12778+ break;
12779+
12780+ default:
12781+ /* do not call the lower */
12782+ AuDbg("0x%x\n", cmd);
12783+ err = -ENOTTY;
12784+ }
12785+
12786+ AuTraceErr(err);
12787+ return err;
12788+}
b752ccd1
AM
12789+
12790+#ifdef CONFIG_COMPAT
12791+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
12792+ unsigned long arg)
12793+{
12794+ long err;
12795+
12796+ switch (cmd) {
12797+ case AUFS_CTL_RDU:
12798+ case AUFS_CTL_RDU_INO:
12799+ err = au_rdu_compat_ioctl(file, cmd, arg);
12800+ break;
12801+
12802+ default:
12803+ err = aufs_ioctl_dir(file, cmd, arg);
12804+ }
12805+
12806+ AuTraceErr(err);
12807+ return err;
12808+}
12809+
12810+#if 0 /* unused yet */
12811+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
12812+ unsigned long arg)
12813+{
12814+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
12815+}
12816+#endif
12817+#endif
e49829fe 12818--- /dev/null
0c5527e5 12819+++ linux-2.6/fs/aufs/i_op_add.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 12820@@ -0,0 +1,676 @@
4a4d8108
AM
12821+/*
12822+ * Copyright (C) 2005-2010 Junjiro R. Okajima
12823+ *
12824+ * This program, aufs is free software; you can redistribute it and/or modify
12825+ * it under the terms of the GNU General Public License as published by
12826+ * the Free Software Foundation; either version 2 of the License, or
12827+ * (at your option) any later version.
12828+ *
12829+ * This program is distributed in the hope that it will be useful,
12830+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12831+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12832+ * GNU General Public License for more details.
12833+ *
12834+ * You should have received a copy of the GNU General Public License
12835+ * along with this program; if not, write to the Free Software
12836+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12837+ */
12838+
12839+/*
12840+ * inode operations (add entry)
12841+ */
12842+
12843+#include "aufs.h"
12844+
12845+/*
12846+ * final procedure of adding a new entry, except link(2).
12847+ * remove whiteout, instantiate, copyup the parent dir's times and size
12848+ * and update version.
12849+ * if it failed, re-create the removed whiteout.
12850+ */
12851+static int epilog(struct inode *dir, aufs_bindex_t bindex,
12852+ struct dentry *wh_dentry, struct dentry *dentry)
12853+{
12854+ int err, rerr;
12855+ aufs_bindex_t bwh;
12856+ struct path h_path;
12857+ struct inode *inode, *h_dir;
12858+ struct dentry *wh;
12859+
12860+ bwh = -1;
12861+ if (wh_dentry) {
12862+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
12863+ IMustLock(h_dir);
12864+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
12865+ bwh = au_dbwh(dentry);
12866+ h_path.dentry = wh_dentry;
12867+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
12868+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
12869+ dentry);
12870+ if (unlikely(err))
12871+ goto out;
12872+ }
12873+
12874+ inode = au_new_inode(dentry, /*must_new*/1);
12875+ if (!IS_ERR(inode)) {
12876+ d_instantiate(dentry, inode);
12877+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
12878+ IMustLock(dir);
12879+ if (au_ibstart(dir) == au_dbstart(dentry))
12880+ au_cpup_attr_timesizes(dir);
12881+ dir->i_version++;
12882+ return 0; /* success */
12883+ }
12884+
12885+ err = PTR_ERR(inode);
12886+ if (!wh_dentry)
12887+ goto out;
12888+
12889+ /* revert */
12890+ /* dir inode is locked */
12891+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
12892+ rerr = PTR_ERR(wh);
12893+ if (IS_ERR(wh)) {
12894+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
12895+ AuDLNPair(dentry), err, rerr);
12896+ err = -EIO;
12897+ } else
12898+ dput(wh);
12899+
4f0767ce 12900+out:
4a4d8108
AM
12901+ return err;
12902+}
12903+
12904+/*
12905+ * simple tests for the adding inode operations.
12906+ * following the checks in vfs, plus the parent-child relationship.
12907+ */
12908+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
12909+ struct dentry *h_parent, int isdir)
12910+{
12911+ int err;
12912+ umode_t h_mode;
12913+ struct dentry *h_dentry;
12914+ struct inode *h_inode;
12915+
12916+ err = -ENAMETOOLONG;
12917+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
12918+ goto out;
12919+
12920+ h_dentry = au_h_dptr(dentry, bindex);
12921+ h_inode = h_dentry->d_inode;
12922+ if (!dentry->d_inode) {
12923+ err = -EEXIST;
12924+ if (unlikely(h_inode))
12925+ goto out;
12926+ } else {
12927+ /* rename(2) case */
12928+ err = -EIO;
12929+ if (unlikely(!h_inode || !h_inode->i_nlink))
12930+ goto out;
12931+
12932+ h_mode = h_inode->i_mode;
12933+ if (!isdir) {
12934+ err = -EISDIR;
12935+ if (unlikely(S_ISDIR(h_mode)))
12936+ goto out;
12937+ } else if (unlikely(!S_ISDIR(h_mode))) {
12938+ err = -ENOTDIR;
12939+ goto out;
12940+ }
12941+ }
12942+
12943+ err = 0;
12944+ /* expected parent dir is locked */
12945+ if (unlikely(h_parent != h_dentry->d_parent))
12946+ err = -EIO;
12947+
4f0767ce 12948+out:
4a4d8108
AM
12949+ AuTraceErr(err);
12950+ return err;
12951+}
12952+
12953+/*
12954+ * initial procedure of adding a new entry.
12955+ * prepare writable branch and the parent dir, lock it,
12956+ * and lookup whiteout for the new entry.
12957+ */
12958+static struct dentry*
12959+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
12960+ struct dentry *src_dentry, struct au_pin *pin,
12961+ struct au_wr_dir_args *wr_dir_args)
12962+{
12963+ struct dentry *wh_dentry, *h_parent;
12964+ struct super_block *sb;
12965+ struct au_branch *br;
12966+ int err;
12967+ unsigned int udba;
12968+ aufs_bindex_t bcpup;
12969+
12970+ AuDbg("%.*s\n", AuDLNPair(dentry));
12971+
12972+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
12973+ bcpup = err;
12974+ wh_dentry = ERR_PTR(err);
12975+ if (unlikely(err < 0))
12976+ goto out;
12977+
12978+ sb = dentry->d_sb;
12979+ udba = au_opt_udba(sb);
12980+ err = au_pin(pin, dentry, bcpup, udba,
12981+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
12982+ wh_dentry = ERR_PTR(err);
12983+ if (unlikely(err))
12984+ goto out;
12985+
12986+ h_parent = au_pinned_h_parent(pin);
12987+ if (udba != AuOpt_UDBA_NONE
12988+ && au_dbstart(dentry) == bcpup)
12989+ err = au_may_add(dentry, bcpup, h_parent,
12990+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
12991+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
12992+ err = -ENAMETOOLONG;
12993+ wh_dentry = ERR_PTR(err);
12994+ if (unlikely(err))
12995+ goto out_unpin;
12996+
12997+ br = au_sbr(sb, bcpup);
12998+ if (dt) {
12999+ struct path tmp = {
13000+ .dentry = h_parent,
13001+ .mnt = br->br_mnt
13002+ };
13003+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
13004+ }
13005+
13006+ wh_dentry = NULL;
13007+ if (bcpup != au_dbwh(dentry))
13008+ goto out; /* success */
13009+
13010+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
13011+
4f0767ce 13012+out_unpin:
4a4d8108
AM
13013+ if (IS_ERR(wh_dentry))
13014+ au_unpin(pin);
4f0767ce 13015+out:
4a4d8108
AM
13016+ return wh_dentry;
13017+}
13018+
13019+/* ---------------------------------------------------------------------- */
13020+
13021+enum { Mknod, Symlink, Creat };
13022+struct simple_arg {
13023+ int type;
13024+ union {
13025+ struct {
13026+ int mode;
13027+ struct nameidata *nd;
13028+ } c;
13029+ struct {
13030+ const char *symname;
13031+ } s;
13032+ struct {
13033+ int mode;
13034+ dev_t dev;
13035+ } m;
13036+ } u;
13037+};
13038+
13039+static int add_simple(struct inode *dir, struct dentry *dentry,
13040+ struct simple_arg *arg)
13041+{
13042+ int err;
13043+ aufs_bindex_t bstart;
13044+ unsigned char created;
13045+ struct au_dtime dt;
13046+ struct au_pin pin;
13047+ struct path h_path;
13048+ struct dentry *wh_dentry, *parent;
13049+ struct inode *h_dir;
13050+ struct au_wr_dir_args wr_dir_args = {
13051+ .force_btgt = -1,
13052+ .flags = AuWrDir_ADD_ENTRY
13053+ };
13054+
13055+ AuDbg("%.*s\n", AuDLNPair(dentry));
13056+ IMustLock(dir);
13057+
13058+ parent = dentry->d_parent; /* dir inode is locked */
13059+ aufs_read_lock(dentry, AuLock_DW);
13060+ di_write_lock_parent(parent);
13061+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
13062+ &wr_dir_args);
13063+ err = PTR_ERR(wh_dentry);
13064+ if (IS_ERR(wh_dentry))
13065+ goto out;
13066+
13067+ bstart = au_dbstart(dentry);
13068+ h_path.dentry = au_h_dptr(dentry, bstart);
13069+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
13070+ h_dir = au_pinned_h_dir(&pin);
13071+ switch (arg->type) {
13072+ case Creat:
13073+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
13074+ break;
13075+ case Symlink:
13076+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
13077+ break;
13078+ case Mknod:
13079+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
13080+ break;
13081+ default:
13082+ BUG();
13083+ }
13084+ created = !err;
13085+ if (!err)
13086+ err = epilog(dir, bstart, wh_dentry, dentry);
13087+
13088+ /* revert */
13089+ if (unlikely(created && err && h_path.dentry->d_inode)) {
13090+ int rerr;
13091+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
13092+ if (rerr) {
13093+ AuIOErr("%.*s revert failure(%d, %d)\n",
13094+ AuDLNPair(dentry), err, rerr);
13095+ err = -EIO;
13096+ }
13097+ au_dtime_revert(&dt);
13098+ d_drop(dentry);
13099+ }
13100+
13101+ au_unpin(&pin);
13102+ dput(wh_dentry);
13103+
4f0767ce 13104+out:
4a4d8108
AM
13105+ if (unlikely(err)) {
13106+ au_update_dbstart(dentry);
13107+ d_drop(dentry);
13108+ }
13109+ di_write_unlock(parent);
13110+ aufs_read_unlock(dentry, AuLock_DW);
13111+ return err;
13112+}
13113+
13114+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
13115+{
13116+ struct simple_arg arg = {
13117+ .type = Mknod,
13118+ .u.m = {
13119+ .mode = mode,
13120+ .dev = dev
13121+ }
13122+ };
13123+ return add_simple(dir, dentry, &arg);
13124+}
13125+
13126+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
13127+{
13128+ struct simple_arg arg = {
13129+ .type = Symlink,
13130+ .u.s.symname = symname
13131+ };
13132+ return add_simple(dir, dentry, &arg);
13133+}
13134+
13135+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13136+ struct nameidata *nd)
13137+{
13138+ struct simple_arg arg = {
13139+ .type = Creat,
13140+ .u.c = {
13141+ .mode = mode,
13142+ .nd = nd
13143+ }
13144+ };
13145+ return add_simple(dir, dentry, &arg);
13146+}
13147+
13148+/* ---------------------------------------------------------------------- */
13149+
13150+struct au_link_args {
13151+ aufs_bindex_t bdst, bsrc;
13152+ struct au_pin pin;
13153+ struct path h_path;
13154+ struct dentry *src_parent, *parent;
13155+};
13156+
13157+static int au_cpup_before_link(struct dentry *src_dentry,
13158+ struct au_link_args *a)
13159+{
13160+ int err;
13161+ struct dentry *h_src_dentry;
13162+ struct mutex *h_mtx;
13163+ struct file *h_file;
13164+
13165+ di_read_lock_parent(a->src_parent, AuLock_IR);
13166+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
13167+ if (unlikely(err))
13168+ goto out;
13169+
13170+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
13171+ h_mtx = &h_src_dentry->d_inode->i_mutex;
13172+ err = au_pin(&a->pin, src_dentry, a->bdst,
13173+ au_opt_udba(src_dentry->d_sb),
13174+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13175+ if (unlikely(err))
13176+ goto out;
13177+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13178+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13179+ if (IS_ERR(h_file)) {
13180+ err = PTR_ERR(h_file);
13181+ h_file = NULL;
13182+ } else
13183+ err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
13184+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
13185+ mutex_unlock(h_mtx);
13186+ au_h_open_post(src_dentry, a->bsrc, h_file);
13187+ au_unpin(&a->pin);
13188+
4f0767ce 13189+out:
4a4d8108
AM
13190+ di_read_unlock(a->src_parent, AuLock_IR);
13191+ return err;
13192+}
13193+
13194+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
13195+{
13196+ int err;
13197+ unsigned char plink;
13198+ struct inode *h_inode, *inode;
13199+ struct dentry *h_src_dentry;
13200+ struct super_block *sb;
13201+ struct file *h_file;
13202+
13203+ plink = 0;
13204+ h_inode = NULL;
13205+ sb = src_dentry->d_sb;
13206+ inode = src_dentry->d_inode;
13207+ if (au_ibstart(inode) <= a->bdst)
13208+ h_inode = au_h_iptr(inode, a->bdst);
13209+ if (!h_inode || !h_inode->i_nlink) {
13210+ /* copyup src_dentry as the name of dentry. */
13211+ au_set_dbstart(src_dentry, a->bdst);
13212+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
13213+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
13214+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
13215+ h_file = au_h_open_pre(src_dentry, a->bsrc);
13216+ if (IS_ERR(h_file)) {
13217+ err = PTR_ERR(h_file);
13218+ h_file = NULL;
13219+ } else
13220+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
13221+ -1, AuCpup_KEEPLINO,
13222+ a->parent);
13223+ mutex_unlock(&h_inode->i_mutex);
13224+ au_h_open_post(src_dentry, a->bsrc, h_file);
13225+ au_set_h_dptr(src_dentry, a->bdst, NULL);
13226+ au_set_dbstart(src_dentry, a->bsrc);
13227+ } else {
13228+ /* the inode of src_dentry already exists on a.bdst branch */
13229+ h_src_dentry = d_find_alias(h_inode);
13230+ if (!h_src_dentry && au_plink_test(inode)) {
13231+ plink = 1;
13232+ h_src_dentry = au_plink_lkup(inode, a->bdst);
13233+ err = PTR_ERR(h_src_dentry);
13234+ if (IS_ERR(h_src_dentry))
13235+ goto out;
13236+
13237+ if (unlikely(!h_src_dentry->d_inode)) {
13238+ dput(h_src_dentry);
13239+ h_src_dentry = NULL;
13240+ }
13241+
13242+ }
13243+ if (h_src_dentry) {
13244+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13245+ &a->h_path);
13246+ dput(h_src_dentry);
13247+ } else {
13248+ AuIOErr("no dentry found for hi%lu on b%d\n",
13249+ h_inode->i_ino, a->bdst);
13250+ err = -EIO;
13251+ }
13252+ }
13253+
13254+ if (!err && !plink)
13255+ au_plink_append(inode, a->bdst, a->h_path.dentry);
13256+
13257+out:
13258+ return err;
13259+}
13260+
13261+int aufs_link(struct dentry *src_dentry, struct inode *dir,
13262+ struct dentry *dentry)
13263+{
13264+ int err, rerr;
13265+ struct au_dtime dt;
13266+ struct au_link_args *a;
13267+ struct dentry *wh_dentry, *h_src_dentry;
13268+ struct inode *inode;
13269+ struct super_block *sb;
13270+ struct au_wr_dir_args wr_dir_args = {
13271+ /* .force_btgt = -1, */
13272+ .flags = AuWrDir_ADD_ENTRY
13273+ };
13274+
13275+ IMustLock(dir);
13276+ inode = src_dentry->d_inode;
13277+ IMustLock(inode);
13278+
13279+ err = -ENOENT;
13280+ if (unlikely(!inode->i_nlink))
13281+ goto out;
13282+
13283+ err = -ENOMEM;
13284+ a = kzalloc(sizeof(*a), GFP_NOFS);
13285+ if (unlikely(!a))
13286+ goto out;
13287+
13288+ a->parent = dentry->d_parent; /* dir inode is locked */
e49829fe
JR
13289+ err = aufs_read_and_write_lock2(dentry, src_dentry, AuLock_NOPLM);
13290+ if (unlikely(err))
13291+ goto out_kfree;
13292+
4a4d8108
AM
13293+ a->src_parent = dget_parent(src_dentry);
13294+ wr_dir_args.force_btgt = au_dbstart(src_dentry);
13295+
13296+ di_write_lock_parent(a->parent);
13297+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
13298+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
13299+ &wr_dir_args);
13300+ err = PTR_ERR(wh_dentry);
13301+ if (IS_ERR(wh_dentry))
13302+ goto out_unlock;
13303+
13304+ err = 0;
13305+ sb = dentry->d_sb;
13306+ a->bdst = au_dbstart(dentry);
13307+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
13308+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
13309+ a->bsrc = au_dbstart(src_dentry);
13310+ if (au_opt_test(au_mntflags(sb), PLINK)) {
13311+ if (a->bdst < a->bsrc
13312+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
13313+ err = au_cpup_or_link(src_dentry, a);
13314+ else {
13315+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13316+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
13317+ &a->h_path);
13318+ }
13319+ } else {
13320+ /*
13321+ * copyup src_dentry to the branch we process,
13322+ * and then link(2) to it.
13323+ */
13324+ if (a->bdst < a->bsrc
13325+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
13326+ au_unpin(&a->pin);
13327+ di_write_unlock(a->parent);
13328+ err = au_cpup_before_link(src_dentry, a);
13329+ di_write_lock_parent(a->parent);
13330+ if (!err)
13331+ err = au_pin(&a->pin, dentry, a->bdst,
13332+ au_opt_udba(sb),
13333+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13334+ if (unlikely(err))
13335+ goto out_wh;
13336+ }
13337+ if (!err) {
13338+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
13339+ err = -ENOENT;
13340+ if (h_src_dentry && h_src_dentry->d_inode)
13341+ err = vfsub_link(h_src_dentry,
13342+ au_pinned_h_dir(&a->pin),
13343+ &a->h_path);
13344+ }
13345+ }
13346+ if (unlikely(err))
13347+ goto out_unpin;
13348+
13349+ if (wh_dentry) {
13350+ a->h_path.dentry = wh_dentry;
13351+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
13352+ dentry);
13353+ if (unlikely(err))
13354+ goto out_revert;
13355+ }
13356+
13357+ dir->i_version++;
13358+ if (au_ibstart(dir) == au_dbstart(dentry))
13359+ au_cpup_attr_timesizes(dir);
13360+ inc_nlink(inode);
13361+ inode->i_ctime = dir->i_ctime;
13362+ if (!d_unhashed(a->h_path.dentry))
13363+ d_instantiate(dentry, au_igrab(inode));
13364+ else
13365+ /* some filesystem calls d_drop() */
13366+ d_drop(dentry);
13367+ goto out_unpin; /* success */
13368+
4f0767ce 13369+out_revert:
4a4d8108
AM
13370+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
13371+ if (!rerr)
13372+ goto out_dt;
13373+ AuIOErr("%.*s reverting failed(%d, %d)\n",
13374+ AuDLNPair(dentry), err, rerr);
13375+ err = -EIO;
4f0767ce 13376+out_dt:
4a4d8108
AM
13377+ d_drop(dentry);
13378+ au_dtime_revert(&dt);
4f0767ce 13379+out_unpin:
4a4d8108 13380+ au_unpin(&a->pin);
4f0767ce 13381+out_wh:
4a4d8108 13382+ dput(wh_dentry);
4f0767ce 13383+out_unlock:
4a4d8108
AM
13384+ if (unlikely(err)) {
13385+ au_update_dbstart(dentry);
13386+ d_drop(dentry);
13387+ }
13388+ di_write_unlock(a->parent);
13389+ dput(a->src_parent);
13390+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 13391+out_kfree:
4a4d8108 13392+ kfree(a);
4f0767ce 13393+out:
4a4d8108
AM
13394+ return err;
13395+}
13396+
13397+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
13398+{
13399+ int err, rerr;
13400+ aufs_bindex_t bindex;
13401+ unsigned char diropq;
13402+ struct path h_path;
13403+ struct dentry *wh_dentry, *parent, *opq_dentry;
13404+ struct mutex *h_mtx;
13405+ struct super_block *sb;
13406+ struct {
13407+ struct au_pin pin;
13408+ struct au_dtime dt;
13409+ } *a; /* reduce the stack usage */
13410+ struct au_wr_dir_args wr_dir_args = {
13411+ .force_btgt = -1,
13412+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
13413+ };
13414+
13415+ IMustLock(dir);
13416+
13417+ err = -ENOMEM;
13418+ a = kmalloc(sizeof(*a), GFP_NOFS);
13419+ if (unlikely(!a))
13420+ goto out;
13421+
13422+ aufs_read_lock(dentry, AuLock_DW);
13423+ parent = dentry->d_parent; /* dir inode is locked */
13424+ di_write_lock_parent(parent);
13425+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
13426+ &a->pin, &wr_dir_args);
13427+ err = PTR_ERR(wh_dentry);
13428+ if (IS_ERR(wh_dentry))
13429+ goto out_free;
13430+
13431+ sb = dentry->d_sb;
13432+ bindex = au_dbstart(dentry);
13433+ h_path.dentry = au_h_dptr(dentry, bindex);
13434+ h_path.mnt = au_sbr_mnt(sb, bindex);
13435+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
13436+ if (unlikely(err))
13437+ goto out_unlock;
13438+
13439+ /* make the dir opaque */
13440+ diropq = 0;
13441+ h_mtx = &h_path.dentry->d_inode->i_mutex;
13442+ if (wh_dentry
13443+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
13444+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13445+ opq_dentry = au_diropq_create(dentry, bindex);
13446+ mutex_unlock(h_mtx);
13447+ err = PTR_ERR(opq_dentry);
13448+ if (IS_ERR(opq_dentry))
13449+ goto out_dir;
13450+ dput(opq_dentry);
13451+ diropq = 1;
13452+ }
13453+
13454+ err = epilog(dir, bindex, wh_dentry, dentry);
13455+ if (!err) {
13456+ inc_nlink(dir);
13457+ goto out_unlock; /* success */
13458+ }
13459+
13460+ /* revert */
13461+ if (diropq) {
13462+ AuLabel(revert opq);
13463+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
13464+ rerr = au_diropq_remove(dentry, bindex);
13465+ mutex_unlock(h_mtx);
13466+ if (rerr) {
13467+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
13468+ AuDLNPair(dentry), err, rerr);
13469+ err = -EIO;
13470+ }
13471+ }
13472+
4f0767ce 13473+out_dir:
4a4d8108
AM
13474+ AuLabel(revert dir);
13475+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
13476+ if (rerr) {
13477+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
13478+ AuDLNPair(dentry), err, rerr);
13479+ err = -EIO;
13480+ }
13481+ d_drop(dentry);
13482+ au_dtime_revert(&a->dt);
4f0767ce 13483+out_unlock:
4a4d8108
AM
13484+ au_unpin(&a->pin);
13485+ dput(wh_dentry);
4f0767ce 13486+out_free:
4a4d8108
AM
13487+ if (unlikely(err)) {
13488+ au_update_dbstart(dentry);
13489+ d_drop(dentry);
13490+ }
13491+ di_write_unlock(parent);
13492+ aufs_read_unlock(dentry, AuLock_DW);
13493+ kfree(a);
4f0767ce 13494+out:
4a4d8108
AM
13495+ return err;
13496+}
e49829fe 13497--- /dev/null
0c5527e5 13498+++ linux-2.6/fs/aufs/i_op.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 13499@@ -0,0 +1,919 @@
4a4d8108
AM
13500+/*
13501+ * Copyright (C) 2005-2010 Junjiro R. Okajima
13502+ *
13503+ * This program, aufs is free software; you can redistribute it and/or modify
13504+ * it under the terms of the GNU General Public License as published by
13505+ * the Free Software Foundation; either version 2 of the License, or
13506+ * (at your option) any later version.
13507+ *
13508+ * This program is distributed in the hope that it will be useful,
13509+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13510+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13511+ * GNU General Public License for more details.
13512+ *
13513+ * You should have received a copy of the GNU General Public License
13514+ * along with this program; if not, write to the Free Software
13515+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13516+ */
1facf9fc 13517+
1308ab2a 13518+/*
4a4d8108 13519+ * inode operations (except add/del/rename)
1308ab2a 13520+ */
4a4d8108
AM
13521+
13522+#include <linux/device_cgroup.h>
13523+#include <linux/fs_stack.h>
13524+#include <linux/mm.h>
13525+#include <linux/namei.h>
13526+#include <linux/security.h>
13527+#include <linux/uaccess.h>
13528+#include "aufs.h"
13529+
13530+static int h_permission(struct inode *h_inode, int mask,
13531+ struct vfsmount *h_mnt, int brperm)
1facf9fc 13532+{
1308ab2a 13533+ int err;
4a4d8108 13534+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 13535+
4a4d8108
AM
13536+ err = -EACCES;
13537+ if ((write_mask && IS_IMMUTABLE(h_inode))
13538+ || ((mask & MAY_EXEC)
13539+ && S_ISREG(h_inode->i_mode)
13540+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
13541+ || !(h_inode->i_mode & S_IXUGO))))
13542+ goto out;
13543+
13544+ /*
13545+ * - skip the lower fs test in the case of write to ro branch.
13546+ * - nfs dir permission write check is optimized, but a policy for
13547+ * link/rename requires a real check.
13548+ */
13549+ if ((write_mask && !au_br_writable(brperm))
13550+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
13551+ && write_mask && !(mask & MAY_READ))
13552+ || !h_inode->i_op->permission) {
13553+ /* AuLabel(generic_permission); */
13554+ err = generic_permission(h_inode, mask,
13555+ h_inode->i_op->check_acl);
1308ab2a 13556+ } else {
4a4d8108
AM
13557+ /* AuLabel(h_inode->permission); */
13558+ err = h_inode->i_op->permission(h_inode, mask);
13559+ AuTraceErr(err);
13560+ }
1facf9fc 13561+
4a4d8108
AM
13562+ if (!err)
13563+ err = devcgroup_inode_permission(h_inode, mask);
e49829fe
JR
13564+ if (!err) {
13565+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND);
4a4d8108 13566+ err = security_inode_permission(h_inode, mask);
e49829fe 13567+ }
4a4d8108
AM
13568+
13569+#if 0
13570+ if (!err) {
13571+ /* todo: do we need to call ima_path_check()? */
13572+ struct path h_path = {
13573+ .dentry =
13574+ .mnt = h_mnt
13575+ };
13576+ err = ima_path_check(&h_path,
13577+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
13578+ IMA_COUNT_LEAVE);
1308ab2a 13579+ }
4a4d8108 13580+#endif
dece6358 13581+
4f0767ce 13582+out:
1308ab2a 13583+ return err;
13584+}
dece6358 13585+
4a4d8108 13586+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 13587+{
13588+ int err;
4a4d8108
AM
13589+ aufs_bindex_t bindex, bend;
13590+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
13591+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
13592+ struct inode *h_inode;
13593+ struct super_block *sb;
13594+ struct au_branch *br;
1facf9fc 13595+
4a4d8108
AM
13596+ sb = inode->i_sb;
13597+ si_read_lock(sb, AuLock_FLUSH);
13598+ ii_read_lock_child(inode);
dece6358 13599+
4a4d8108
AM
13600+ if (!isdir || write_mask) {
13601+ err = au_busy_or_stale();
13602+ h_inode = au_h_iptr(inode, au_ibstart(inode));
13603+ if (unlikely(!h_inode
13604+ || (h_inode->i_mode & S_IFMT)
13605+ != (inode->i_mode & S_IFMT)))
13606+ goto out;
1facf9fc 13607+
4a4d8108
AM
13608+ err = 0;
13609+ bindex = au_ibstart(inode);
13610+ br = au_sbr(sb, bindex);
13611+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
13612+ if (write_mask
13613+ && !err
13614+ && !special_file(h_inode->i_mode)) {
13615+ /* test whether the upper writable branch exists */
13616+ err = -EROFS;
13617+ for (; bindex >= 0; bindex--)
13618+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
13619+ err = 0;
13620+ break;
13621+ }
13622+ }
13623+ goto out;
13624+ }
dece6358 13625+
4a4d8108 13626+ /* non-write to dir */
1308ab2a 13627+ err = 0;
4a4d8108
AM
13628+ bend = au_ibend(inode);
13629+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
13630+ h_inode = au_h_iptr(inode, bindex);
13631+ if (h_inode) {
13632+ err = au_busy_or_stale();
13633+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
13634+ break;
13635+
13636+ br = au_sbr(sb, bindex);
13637+ err = h_permission(h_inode, mask, br->br_mnt,
13638+ br->br_perm);
13639+ }
13640+ }
1308ab2a 13641+
4f0767ce 13642+out:
4a4d8108
AM
13643+ ii_read_unlock(inode);
13644+ si_read_unlock(sb);
1308ab2a 13645+ return err;
13646+}
13647+
4a4d8108 13648+/* ---------------------------------------------------------------------- */
1facf9fc 13649+
4a4d8108
AM
13650+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
13651+ struct nameidata *nd)
13652+{
13653+ struct dentry *ret, *parent;
b752ccd1 13654+ struct inode *inode;
4a4d8108
AM
13655+ struct super_block *sb;
13656+ int err, npositive;
dece6358 13657+
4a4d8108 13658+ IMustLock(dir);
1308ab2a 13659+
4a4d8108
AM
13660+ sb = dir->i_sb;
13661+ si_read_lock(sb, AuLock_FLUSH);
13662+ ret = ERR_PTR(-ENAMETOOLONG);
13663+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13664+ goto out;
13665+ err = au_di_init(dentry);
13666+ ret = ERR_PTR(err);
13667+ if (unlikely(err))
13668+ goto out;
1308ab2a 13669+
4a4d8108
AM
13670+ parent = dentry->d_parent; /* dir inode is locked */
13671+ di_read_lock_parent(parent, AuLock_IR);
13672+ npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
13673+ di_read_unlock(parent, AuLock_IR);
13674+ err = npositive;
13675+ ret = ERR_PTR(err);
13676+ if (unlikely(err < 0))
13677+ goto out_unlock;
1308ab2a 13678+
4a4d8108
AM
13679+ inode = NULL;
13680+ if (npositive) {
b752ccd1 13681+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 13682+ ret = (void *)inode;
1facf9fc 13683+ }
4a4d8108
AM
13684+ if (IS_ERR(inode))
13685+ goto out_unlock;
13686+
13687+ ret = d_splice_alias(inode, dentry);
13688+ if (unlikely(IS_ERR(ret) && inode))
13689+ ii_write_unlock(inode);
1facf9fc 13690+
4f0767ce 13691+out_unlock:
4a4d8108 13692+ di_write_unlock(dentry);
4f0767ce 13693+out:
4a4d8108
AM
13694+ si_read_unlock(sb);
13695+ return ret;
13696+}
1facf9fc 13697+
4a4d8108 13698+/* ---------------------------------------------------------------------- */
1facf9fc 13699+
4a4d8108
AM
13700+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
13701+ const unsigned char add_entry, aufs_bindex_t bcpup,
13702+ aufs_bindex_t bstart)
13703+{
13704+ int err;
13705+ struct dentry *h_parent;
13706+ struct inode *h_dir;
1facf9fc 13707+
4a4d8108
AM
13708+ if (add_entry) {
13709+ au_update_dbstart(dentry);
13710+ IMustLock(parent->d_inode);
13711+ } else
13712+ di_write_lock_parent(parent);
13713+
13714+ err = 0;
13715+ if (!au_h_dptr(parent, bcpup)) {
13716+ if (bstart < bcpup)
13717+ err = au_cpdown_dirs(dentry, bcpup);
13718+ else
13719+ err = au_cpup_dirs(dentry, bcpup);
13720+ }
13721+ if (!err && add_entry) {
13722+ h_parent = au_h_dptr(parent, bcpup);
13723+ h_dir = h_parent->d_inode;
13724+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
13725+ err = au_lkup_neg(dentry, bcpup);
13726+ /* todo: no unlock here */
13727+ mutex_unlock(&h_dir->i_mutex);
13728+ if (bstart < bcpup && au_dbstart(dentry) < 0) {
13729+ au_set_dbstart(dentry, 0);
13730+ au_update_dbrange(dentry, /*do_put_zero*/0);
13731+ }
1308ab2a 13732+ }
1facf9fc 13733+
4a4d8108
AM
13734+ if (!add_entry)
13735+ di_write_unlock(parent);
13736+ if (!err)
13737+ err = bcpup; /* success */
1308ab2a 13738+
4a4d8108
AM
13739+ return err;
13740+}
1facf9fc 13741+
4a4d8108
AM
13742+/*
13743+ * decide the branch and the parent dir where we will create a new entry.
13744+ * returns new bindex or an error.
13745+ * copyup the parent dir if needed.
13746+ */
13747+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
13748+ struct au_wr_dir_args *args)
13749+{
13750+ int err;
13751+ aufs_bindex_t bcpup, bstart, src_bstart;
13752+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
13753+ ADD_ENTRY);
13754+ struct super_block *sb;
13755+ struct dentry *parent;
13756+ struct au_sbinfo *sbinfo;
1facf9fc 13757+
4a4d8108
AM
13758+ sb = dentry->d_sb;
13759+ sbinfo = au_sbi(sb);
13760+ parent = dget_parent(dentry);
13761+ bstart = au_dbstart(dentry);
13762+ bcpup = bstart;
13763+ if (args->force_btgt < 0) {
13764+ if (src_dentry) {
13765+ src_bstart = au_dbstart(src_dentry);
13766+ if (src_bstart < bstart)
13767+ bcpup = src_bstart;
13768+ } else if (add_entry) {
13769+ err = AuWbrCreate(sbinfo, dentry,
13770+ au_ftest_wrdir(args->flags, ISDIR));
13771+ bcpup = err;
13772+ }
1facf9fc 13773+
4a4d8108
AM
13774+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
13775+ if (add_entry)
13776+ err = AuWbrCopyup(sbinfo, dentry);
13777+ else {
13778+ if (!IS_ROOT(dentry)) {
13779+ di_read_lock_parent(parent, !AuLock_IR);
13780+ err = AuWbrCopyup(sbinfo, dentry);
13781+ di_read_unlock(parent, !AuLock_IR);
13782+ } else
13783+ err = AuWbrCopyup(sbinfo, dentry);
13784+ }
13785+ bcpup = err;
13786+ if (unlikely(err < 0))
13787+ goto out;
13788+ }
13789+ } else {
13790+ bcpup = args->force_btgt;
13791+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 13792+ }
4a4d8108
AM
13793+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
13794+ err = bcpup;
13795+ if (bcpup == bstart)
13796+ goto out; /* success */
13797+ else if (bstart < bcpup)
13798+ au_update_dbrange(dentry, /*do_put_zero*/1);
13799+
13800+ /* copyup the new parent into the branch we process */
13801+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
13802+
4f0767ce 13803+out:
4a4d8108 13804+ dput(parent);
dece6358
AM
13805+ return err;
13806+}
1facf9fc 13807+
1308ab2a 13808+/* ---------------------------------------------------------------------- */
13809+
4a4d8108 13810+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 13811+{
4a4d8108
AM
13812+ if (pin && pin->parent)
13813+ return au_h_dptr(pin->parent, pin->bindex);
13814+ return NULL;
dece6358 13815+}
1facf9fc 13816+
4a4d8108 13817+void au_unpin(struct au_pin *p)
dece6358 13818+{
e49829fe 13819+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
4a4d8108
AM
13820+ mnt_drop_write(p->h_mnt);
13821+ if (!p->hdir)
13822+ return;
1facf9fc 13823+
4a4d8108
AM
13824+ au_hn_imtx_unlock(p->hdir);
13825+ if (!au_ftest_pin(p->flags, DI_LOCKED))
13826+ di_read_unlock(p->parent, AuLock_IR);
13827+ iput(p->hdir->hi_inode);
13828+ dput(p->parent);
13829+ p->parent = NULL;
13830+ p->hdir = NULL;
13831+ p->h_mnt = NULL;
13832+}
1308ab2a 13833+
4a4d8108
AM
13834+int au_do_pin(struct au_pin *p)
13835+{
13836+ int err;
13837+ struct super_block *sb;
13838+ struct dentry *h_dentry, *h_parent;
13839+ struct au_branch *br;
13840+ struct inode *h_dir;
13841+
13842+ err = 0;
13843+ sb = p->dentry->d_sb;
13844+ br = au_sbr(sb, p->bindex);
13845+ if (IS_ROOT(p->dentry)) {
13846+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
13847+ p->h_mnt = br->br_mnt;
13848+ err = mnt_want_write(p->h_mnt);
13849+ if (unlikely(err)) {
13850+ au_fclr_pin(p->flags, MNT_WRITE);
13851+ goto out_err;
13852+ }
13853+ }
dece6358 13854+ goto out;
1facf9fc 13855+ }
13856+
4a4d8108
AM
13857+ h_dentry = NULL;
13858+ if (p->bindex <= au_dbend(p->dentry))
13859+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 13860+
4a4d8108
AM
13861+ p->parent = dget_parent(p->dentry);
13862+ if (!au_ftest_pin(p->flags, DI_LOCKED))
13863+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 13864+
4a4d8108
AM
13865+ h_dir = NULL;
13866+ h_parent = au_h_dptr(p->parent, p->bindex);
13867+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
13868+ if (p->hdir)
13869+ h_dir = p->hdir->hi_inode;
dece6358 13870+
b752ccd1
AM
13871+ /*
13872+ * udba case, or
13873+ * if DI_LOCKED is not set, then p->parent may be different
13874+ * and h_parent can be NULL.
13875+ */
13876+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
e49829fe 13877+ err = -EBUSY;
4a4d8108
AM
13878+ if (!au_ftest_pin(p->flags, DI_LOCKED))
13879+ di_read_unlock(p->parent, AuLock_IR);
13880+ dput(p->parent);
13881+ p->parent = NULL;
13882+ goto out_err;
13883+ }
1308ab2a 13884+
4a4d8108
AM
13885+ au_igrab(h_dir);
13886+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 13887+
4a4d8108
AM
13888+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
13889+ err = -EBUSY;
13890+ goto out_unpin;
13891+ }
13892+ if (h_dentry) {
13893+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
13894+ if (unlikely(err)) {
13895+ au_fclr_pin(p->flags, MNT_WRITE);
13896+ goto out_unpin;
13897+ }
1facf9fc 13898+ }
dece6358 13899+
4a4d8108
AM
13900+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
13901+ p->h_mnt = br->br_mnt;
13902+ err = mnt_want_write(p->h_mnt);
dece6358 13903+ if (unlikely(err)) {
4a4d8108
AM
13904+ au_fclr_pin(p->flags, MNT_WRITE);
13905+ goto out_unpin;
dece6358
AM
13906+ }
13907+ }
4a4d8108
AM
13908+ goto out; /* success */
13909+
4f0767ce 13910+out_unpin:
4a4d8108 13911+ au_unpin(p);
4f0767ce 13912+out_err:
4a4d8108
AM
13913+ pr_err("err %d\n", err);
13914+ err = au_busy_or_stale();
4f0767ce 13915+out:
1facf9fc 13916+ return err;
13917+}
13918+
4a4d8108
AM
13919+void au_pin_init(struct au_pin *p, struct dentry *dentry,
13920+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
13921+ unsigned int udba, unsigned char flags)
13922+{
13923+ p->dentry = dentry;
13924+ p->udba = udba;
13925+ p->lsc_di = lsc_di;
13926+ p->lsc_hi = lsc_hi;
13927+ p->flags = flags;
13928+ p->bindex = bindex;
13929+
13930+ p->parent = NULL;
13931+ p->hdir = NULL;
13932+ p->h_mnt = NULL;
13933+}
13934+
13935+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
13936+ unsigned int udba, unsigned char flags)
13937+{
13938+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
13939+ udba, flags);
13940+ return au_do_pin(pin);
13941+}
13942+
dece6358
AM
13943+/* ---------------------------------------------------------------------- */
13944+
1308ab2a 13945+/*
4a4d8108
AM
13946+ * ->setattr() and ->getattr() are called in various cases.
13947+ * chmod, stat: dentry is revalidated.
13948+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
13949+ * unhashed.
13950+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 13951+ */
4a4d8108 13952+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 13953+{
4a4d8108
AM
13954+ int err;
13955+ struct inode *inode;
13956+ struct dentry *parent;
1facf9fc 13957+
1308ab2a 13958+ err = 0;
4a4d8108
AM
13959+ inode = dentry->d_inode;
13960+ if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
13961+ parent = dget_parent(dentry);
13962+ di_read_lock_parent(parent, AuLock_IR);
13963+ /* returns a number of positive dentries */
13964+ err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
13965+ if (err >= 0)
13966+ err = au_refresh_hinode(inode, dentry);
13967+ di_read_unlock(parent, AuLock_IR);
13968+ dput(parent);
dece6358 13969+ }
1facf9fc 13970+
4a4d8108 13971+ AuTraceErr(err);
1308ab2a 13972+ return err;
13973+}
dece6358 13974+
4a4d8108
AM
13975+#define AuIcpup_DID_CPUP 1
13976+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
13977+#define au_fset_icpup(flags, name) { (flags) |= AuIcpup_##name; }
13978+#define au_fclr_icpup(flags, name) { (flags) &= ~AuIcpup_##name; }
1308ab2a 13979+
4a4d8108
AM
13980+struct au_icpup_args {
13981+ unsigned char flags;
13982+ unsigned char pin_flags;
13983+ aufs_bindex_t btgt;
13984+ unsigned int udba;
13985+ struct au_pin pin;
13986+ struct path h_path;
13987+ struct inode *h_inode;
13988+};
1308ab2a 13989+
4a4d8108
AM
13990+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
13991+ struct au_icpup_args *a)
1308ab2a 13992+{
13993+ int err;
4a4d8108 13994+ loff_t sz;
e49829fe 13995+ aufs_bindex_t bstart, ibstart;
4a4d8108
AM
13996+ struct dentry *hi_wh, *parent;
13997+ struct inode *inode;
13998+ struct file *h_file;
13999+ struct au_wr_dir_args wr_dir_args = {
14000+ .force_btgt = -1,
14001+ .flags = 0
14002+ };
14003+
14004+ bstart = au_dbstart(dentry);
14005+ inode = dentry->d_inode;
14006+ if (S_ISDIR(inode->i_mode))
14007+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
14008+ /* plink or hi_wh() case */
e49829fe
JR
14009+ ibstart = au_ibstart(inode);
14010+ if (bstart != ibstart)
14011+ wr_dir_args.force_btgt = ibstart;
4a4d8108
AM
14012+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
14013+ if (unlikely(err < 0))
14014+ goto out;
14015+ a->btgt = err;
14016+ if (err != bstart)
14017+ au_fset_icpup(a->flags, DID_CPUP);
14018+
14019+ err = 0;
14020+ a->pin_flags = AuPin_MNT_WRITE;
14021+ parent = NULL;
14022+ if (!IS_ROOT(dentry)) {
14023+ au_fset_pin(a->pin_flags, DI_LOCKED);
14024+ parent = dget_parent(dentry);
14025+ di_write_lock_parent(parent);
14026+ }
14027+
14028+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
14029+ if (unlikely(err))
14030+ goto out_parent;
14031+
14032+ a->h_path.dentry = au_h_dptr(dentry, bstart);
14033+ a->h_inode = a->h_path.dentry->d_inode;
14034+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14035+ sz = -1;
14036+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
14037+ sz = ia->ia_size;
14038+
14039+ h_file = NULL;
14040+ hi_wh = NULL;
14041+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
14042+ hi_wh = au_hi_wh(inode, a->btgt);
14043+ if (!hi_wh) {
14044+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
14045+ if (unlikely(err))
14046+ goto out_unlock;
14047+ hi_wh = au_hi_wh(inode, a->btgt);
14048+ /* todo: revalidate hi_wh? */
14049+ }
14050+ }
14051+
14052+ if (parent) {
14053+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
14054+ di_downgrade_lock(parent, AuLock_IR);
14055+ dput(parent);
14056+ parent = NULL;
14057+ }
14058+ if (!au_ftest_icpup(a->flags, DID_CPUP))
14059+ goto out; /* success */
14060+
14061+ if (!d_unhashed(dentry)) {
14062+ h_file = au_h_open_pre(dentry, bstart);
14063+ if (IS_ERR(h_file)) {
14064+ err = PTR_ERR(h_file);
14065+ h_file = NULL;
14066+ } else
14067+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
14068+ AuCpup_DTIME);
14069+ if (!err)
14070+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14071+ } else if (!hi_wh)
14072+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
14073+ else
14074+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 14075+
4f0767ce 14076+out_unlock:
4a4d8108
AM
14077+ mutex_unlock(&a->h_inode->i_mutex);
14078+ au_h_open_post(dentry, bstart, h_file);
14079+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 14080+ if (!err) {
4a4d8108 14081+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 14082+ goto out; /* success */
1facf9fc 14083+ }
dece6358 14084+
4a4d8108 14085+ au_unpin(&a->pin);
4f0767ce 14086+out_parent:
4a4d8108
AM
14087+ if (parent) {
14088+ di_write_unlock(parent);
14089+ dput(parent);
14090+ }
4f0767ce 14091+out:
1facf9fc 14092+ return err;
14093+}
14094+
4a4d8108 14095+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 14096+{
4a4d8108
AM
14097+ int err;
14098+ struct inode *inode;
14099+ struct super_block *sb;
14100+ struct file *file;
14101+ struct au_icpup_args *a;
1facf9fc 14102+
4a4d8108
AM
14103+ inode = dentry->d_inode;
14104+ IMustLock(inode);
dece6358 14105+
4a4d8108
AM
14106+ err = -ENOMEM;
14107+ a = kzalloc(sizeof(*a), GFP_NOFS);
14108+ if (unlikely(!a))
14109+ goto out;
1facf9fc 14110+
4a4d8108
AM
14111+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
14112+ ia->ia_valid &= ~ATTR_MODE;
dece6358 14113+
4a4d8108
AM
14114+ file = NULL;
14115+ sb = dentry->d_sb;
e49829fe
JR
14116+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
14117+ if (unlikely(err))
14118+ goto out_kfree;
14119+
4a4d8108
AM
14120+ if (ia->ia_valid & ATTR_FILE) {
14121+ /* currently ftruncate(2) only */
14122+ AuDebugOn(!S_ISREG(inode->i_mode));
14123+ file = ia->ia_file;
14124+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
14125+ if (unlikely(err))
14126+ goto out_si;
14127+ ia->ia_file = au_hf_top(file);
14128+ a->udba = AuOpt_UDBA_NONE;
14129+ } else {
14130+ /* fchmod() doesn't pass ia_file */
14131+ a->udba = au_opt_udba(sb);
14132+ if (d_unhashed(dentry))
14133+ a->udba = AuOpt_UDBA_NONE;
14134+ di_write_lock_child(dentry);
14135+ if (a->udba != AuOpt_UDBA_NONE) {
14136+ AuDebugOn(IS_ROOT(dentry));
14137+ err = au_reval_for_attr(dentry, au_sigen(sb));
14138+ if (unlikely(err))
14139+ goto out_dentry;
14140+ }
dece6358 14141+ }
dece6358 14142+
4a4d8108
AM
14143+ err = au_pin_and_icpup(dentry, ia, a);
14144+ if (unlikely(err < 0))
14145+ goto out_dentry;
14146+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
14147+ ia->ia_file = NULL;
14148+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 14149+ }
dece6358 14150+
4a4d8108
AM
14151+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
14152+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
14153+ == (ATTR_MODE | ATTR_CTIME)) {
14154+ err = security_path_chmod(a->h_path.dentry, a->h_path.mnt,
14155+ ia->ia_mode);
14156+ if (unlikely(err))
14157+ goto out_unlock;
14158+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
14159+ && (ia->ia_valid & ATTR_CTIME)) {
14160+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
14161+ if (unlikely(err))
14162+ goto out_unlock;
14163+ }
dece6358 14164+
4a4d8108
AM
14165+ if (ia->ia_valid & ATTR_SIZE) {
14166+ struct file *f;
1308ab2a 14167+
953406b4 14168+ if (ia->ia_size < i_size_read(inode))
4a4d8108 14169+ /* unmap only */
953406b4 14170+ truncate_setsize(inode, ia->ia_size);
1308ab2a 14171+
4a4d8108
AM
14172+ f = NULL;
14173+ if (ia->ia_valid & ATTR_FILE)
14174+ f = ia->ia_file;
14175+ mutex_unlock(&a->h_inode->i_mutex);
14176+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
14177+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
14178+ } else
14179+ err = vfsub_notify_change(&a->h_path, ia);
14180+ if (!err)
14181+ au_cpup_attr_changeable(inode);
1308ab2a 14182+
4f0767ce 14183+out_unlock:
4a4d8108
AM
14184+ mutex_unlock(&a->h_inode->i_mutex);
14185+ au_unpin(&a->pin);
4f0767ce 14186+out_dentry:
4a4d8108
AM
14187+ di_write_unlock(dentry);
14188+ if (file) {
14189+ fi_write_unlock(file);
14190+ ia->ia_file = file;
14191+ ia->ia_valid |= ATTR_FILE;
14192+ }
4f0767ce 14193+out_si:
4a4d8108 14194+ si_read_unlock(sb);
e49829fe 14195+out_kfree:
4a4d8108 14196+ kfree(a);
4f0767ce 14197+out:
4a4d8108
AM
14198+ AuTraceErr(err);
14199+ return err;
1facf9fc 14200+}
14201+
4a4d8108
AM
14202+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
14203+ unsigned int nlink)
1facf9fc 14204+{
4a4d8108
AM
14205+ inode->i_mode = st->mode;
14206+ inode->i_uid = st->uid;
14207+ inode->i_gid = st->gid;
14208+ inode->i_atime = st->atime;
14209+ inode->i_mtime = st->mtime;
14210+ inode->i_ctime = st->ctime;
1facf9fc 14211+
4a4d8108
AM
14212+ au_cpup_attr_nlink(inode, /*force*/0);
14213+ if (S_ISDIR(inode->i_mode)) {
14214+ inode->i_nlink -= nlink;
14215+ inode->i_nlink += st->nlink;
14216+ }
1facf9fc 14217+
4a4d8108
AM
14218+ spin_lock(&inode->i_lock);
14219+ inode->i_blocks = st->blocks;
14220+ i_size_write(inode, st->size);
14221+ spin_unlock(&inode->i_lock);
1facf9fc 14222+}
14223+
4a4d8108
AM
14224+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
14225+ struct dentry *dentry, struct kstat *st)
1facf9fc 14226+{
4a4d8108
AM
14227+ int err;
14228+ unsigned int mnt_flags;
14229+ aufs_bindex_t bindex;
14230+ unsigned char udba_none, positive;
14231+ struct super_block *sb, *h_sb;
14232+ struct inode *inode;
14233+ struct vfsmount *h_mnt;
14234+ struct dentry *h_dentry;
1facf9fc 14235+
4a4d8108
AM
14236+ err = 0;
14237+ sb = dentry->d_sb;
14238+ inode = dentry->d_inode;
e49829fe 14239+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
14240+ mnt_flags = au_mntflags(sb);
14241+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 14242+
4a4d8108
AM
14243+ /* support fstat(2) */
14244+ if (!d_unhashed(dentry) && !udba_none) {
14245+ unsigned int sigen = au_sigen(sb);
14246+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
14247+ di_read_lock_child(dentry, AuLock_IR);
14248+ else {
14249+ AuDebugOn(IS_ROOT(dentry));
14250+ di_write_lock_child(dentry);
14251+ err = au_reval_for_attr(dentry, sigen);
14252+ di_downgrade_lock(dentry, AuLock_IR);
14253+ if (unlikely(err))
14254+ goto out;
14255+ }
14256+ } else
14257+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 14258+
4a4d8108
AM
14259+ bindex = au_ibstart(inode);
14260+ h_mnt = au_sbr_mnt(sb, bindex);
14261+ h_sb = h_mnt->mnt_sb;
14262+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
14263+ goto out_fill; /* success */
1facf9fc 14264+
4a4d8108
AM
14265+ h_dentry = NULL;
14266+ if (au_dbstart(dentry) == bindex)
14267+ h_dentry = dget(au_h_dptr(dentry, bindex));
14268+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
14269+ h_dentry = au_plink_lkup(inode, bindex);
14270+ if (IS_ERR(h_dentry))
14271+ goto out_fill; /* pretending success */
14272+ }
14273+ /* illegally overlapped or something */
14274+ if (unlikely(!h_dentry))
14275+ goto out_fill; /* pretending success */
14276+
14277+ positive = !!h_dentry->d_inode;
14278+ if (positive)
14279+ err = vfs_getattr(h_mnt, h_dentry, st);
14280+ dput(h_dentry);
14281+ if (!err) {
14282+ if (positive)
14283+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
14284+ goto out_fill; /* success */
1facf9fc 14285+ }
4a4d8108
AM
14286+ goto out;
14287+
4f0767ce 14288+out_fill:
4a4d8108 14289+ generic_fillattr(inode, st);
4f0767ce 14290+out:
4a4d8108
AM
14291+ di_read_unlock(dentry, AuLock_IR);
14292+ si_read_unlock(sb);
14293+ return err;
1facf9fc 14294+}
14295+
14296+/* ---------------------------------------------------------------------- */
14297+
4a4d8108
AM
14298+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
14299+ int bufsiz)
1facf9fc 14300+{
14301+ int err;
4a4d8108
AM
14302+ struct super_block *sb;
14303+ struct dentry *h_dentry;
1facf9fc 14304+
4a4d8108
AM
14305+ err = -EINVAL;
14306+ h_dentry = au_h_dptr(dentry, bindex);
14307+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
14308+ goto out;
1facf9fc 14309+
4a4d8108
AM
14310+ err = security_inode_readlink(h_dentry);
14311+ if (unlikely(err))
dece6358 14312+ goto out;
1facf9fc 14313+
4a4d8108
AM
14314+ sb = dentry->d_sb;
14315+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
14316+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
14317+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 14318+ }
4a4d8108 14319+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 14320+
4f0767ce 14321+out:
4a4d8108
AM
14322+ return err;
14323+}
1facf9fc 14324+
4a4d8108
AM
14325+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
14326+{
14327+ int err;
1facf9fc 14328+
4a4d8108
AM
14329+ aufs_read_lock(dentry, AuLock_IR);
14330+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
14331+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14332+
4a4d8108
AM
14333+ return err;
14334+}
1facf9fc 14335+
4a4d8108
AM
14336+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
14337+{
14338+ int err;
4a4d8108 14339+ mm_segment_t old_fs;
b752ccd1
AM
14340+ union {
14341+ char *k;
14342+ char __user *u;
14343+ } buf;
1facf9fc 14344+
4a4d8108 14345+ err = -ENOMEM;
b752ccd1
AM
14346+ buf.k = __getname_gfp(GFP_NOFS);
14347+ if (unlikely(!buf.k))
4a4d8108 14348+ goto out;
1facf9fc 14349+
4a4d8108
AM
14350+ aufs_read_lock(dentry, AuLock_IR);
14351+ old_fs = get_fs();
14352+ set_fs(KERNEL_DS);
b752ccd1 14353+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
4a4d8108
AM
14354+ set_fs(old_fs);
14355+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 14356+
4a4d8108 14357+ if (err >= 0) {
b752ccd1 14358+ buf.k[err] = 0;
4a4d8108 14359+ /* will be freed by put_link */
b752ccd1 14360+ nd_set_link(nd, buf.k);
4a4d8108 14361+ return NULL; /* success */
1308ab2a 14362+ }
b752ccd1 14363+ __putname(buf.k);
1facf9fc 14364+
4f0767ce 14365+out:
4a4d8108
AM
14366+ path_put(&nd->path);
14367+ AuTraceErr(err);
14368+ return ERR_PTR(err);
14369+}
1facf9fc 14370+
4a4d8108
AM
14371+static void aufs_put_link(struct dentry *dentry __maybe_unused,
14372+ struct nameidata *nd, void *cookie __maybe_unused)
14373+{
14374+ __putname(nd_get_link(nd));
14375+}
1facf9fc 14376+
4a4d8108 14377+/* ---------------------------------------------------------------------- */
1facf9fc 14378+
4a4d8108
AM
14379+static void aufs_truncate_range(struct inode *inode __maybe_unused,
14380+ loff_t start __maybe_unused,
14381+ loff_t end __maybe_unused)
14382+{
14383+ AuUnsupport();
14384+}
1facf9fc 14385+
4a4d8108 14386+/* ---------------------------------------------------------------------- */
1308ab2a 14387+
4a4d8108
AM
14388+struct inode_operations aufs_symlink_iop = {
14389+ .permission = aufs_permission,
14390+ .setattr = aufs_setattr,
14391+ .getattr = aufs_getattr,
14392+ .readlink = aufs_readlink,
14393+ .follow_link = aufs_follow_link,
14394+ .put_link = aufs_put_link
14395+};
14396+
14397+struct inode_operations aufs_dir_iop = {
14398+ .create = aufs_create,
14399+ .lookup = aufs_lookup,
14400+ .link = aufs_link,
14401+ .unlink = aufs_unlink,
14402+ .symlink = aufs_symlink,
14403+ .mkdir = aufs_mkdir,
14404+ .rmdir = aufs_rmdir,
14405+ .mknod = aufs_mknod,
14406+ .rename = aufs_rename,
14407+
14408+ .permission = aufs_permission,
14409+ .setattr = aufs_setattr,
14410+ .getattr = aufs_getattr
14411+};
14412+
14413+struct inode_operations aufs_iop = {
14414+ .permission = aufs_permission,
14415+ .setattr = aufs_setattr,
14416+ .getattr = aufs_getattr,
14417+ .truncate_range = aufs_truncate_range
14418+};
e49829fe 14419--- /dev/null
0c5527e5 14420+++ linux-2.6/fs/aufs/i_op_del.c 2010-10-25 14:20:44.000000000 +0200
4a4d8108 14421@@ -0,0 +1,472 @@
1facf9fc 14422+/*
4a4d8108 14423+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 14424+ *
14425+ * This program, aufs is free software; you can redistribute it and/or modify
14426+ * it under the terms of the GNU General Public License as published by
14427+ * the Free Software Foundation; either version 2 of the License, or
14428+ * (at your option) any later version.
dece6358
AM
14429+ *
14430+ * This program is distributed in the hope that it will be useful,
14431+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14432+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14433+ * GNU General Public License for more details.
14434+ *
14435+ * You should have received a copy of the GNU General Public License
14436+ * along with this program; if not, write to the Free Software
14437+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14438+ */
14439+
14440+/*
4a4d8108 14441+ * inode operations (del entry)
1308ab2a 14442+ */
dece6358 14443+
1308ab2a 14444+#include "aufs.h"
dece6358 14445+
4a4d8108
AM
14446+/*
14447+ * decide if a new whiteout for @dentry is necessary or not.
14448+ * when it is necessary, prepare the parent dir for the upper branch whose
14449+ * branch index is @bcpup for creation. the actual creation of the whiteout will
14450+ * be done by caller.
14451+ * return value:
14452+ * 0: wh is unnecessary
14453+ * plus: wh is necessary
14454+ * minus: error
14455+ */
14456+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 14457+{
4a4d8108
AM
14458+ int need_wh, err;
14459+ aufs_bindex_t bstart;
14460+ struct super_block *sb;
dece6358 14461+
4a4d8108
AM
14462+ sb = dentry->d_sb;
14463+ bstart = au_dbstart(dentry);
14464+ if (*bcpup < 0) {
14465+ *bcpup = bstart;
14466+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
14467+ err = AuWbrCopyup(au_sbi(sb), dentry);
14468+ *bcpup = err;
14469+ if (unlikely(err < 0))
14470+ goto out;
14471+ }
14472+ } else
14473+ AuDebugOn(bstart < *bcpup
14474+ || au_test_ro(sb, *bcpup, dentry->d_inode));
14475+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 14476+
4a4d8108
AM
14477+ if (*bcpup != bstart) {
14478+ err = au_cpup_dirs(dentry, *bcpup);
14479+ if (unlikely(err))
14480+ goto out;
14481+ need_wh = 1;
14482+ } else {
14483+ aufs_bindex_t old_bend, new_bend, bdiropq = -1;
14484+
14485+ old_bend = au_dbend(dentry);
14486+ if (isdir) {
14487+ bdiropq = au_dbdiropq(dentry);
14488+ au_set_dbdiropq(dentry, -1);
14489+ }
14490+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
14491+ /*nd*/NULL);
14492+ err = need_wh;
14493+ if (isdir)
14494+ au_set_dbdiropq(dentry, bdiropq);
14495+ if (unlikely(err < 0))
14496+ goto out;
14497+ new_bend = au_dbend(dentry);
14498+ if (!need_wh && old_bend != new_bend) {
14499+ au_set_h_dptr(dentry, new_bend, NULL);
14500+ au_set_dbend(dentry, old_bend);
14501+ }
14502+ }
14503+ AuDbg("need_wh %d\n", need_wh);
14504+ err = need_wh;
14505+
4f0767ce 14506+out:
4a4d8108 14507+ return err;
1facf9fc 14508+}
14509+
4a4d8108
AM
14510+/*
14511+ * simple tests for the del-entry operations.
14512+ * following the checks in vfs, plus the parent-child relationship.
14513+ */
14514+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14515+ struct dentry *h_parent, int isdir)
1facf9fc 14516+{
4a4d8108
AM
14517+ int err;
14518+ umode_t h_mode;
14519+ struct dentry *h_dentry, *h_latest;
1308ab2a 14520+ struct inode *h_inode;
1facf9fc 14521+
4a4d8108
AM
14522+ h_dentry = au_h_dptr(dentry, bindex);
14523+ h_inode = h_dentry->d_inode;
14524+ if (dentry->d_inode) {
14525+ err = -ENOENT;
14526+ if (unlikely(!h_inode || !h_inode->i_nlink))
14527+ goto out;
1facf9fc 14528+
4a4d8108
AM
14529+ h_mode = h_inode->i_mode;
14530+ if (!isdir) {
14531+ err = -EISDIR;
14532+ if (unlikely(S_ISDIR(h_mode)))
14533+ goto out;
14534+ } else if (unlikely(!S_ISDIR(h_mode))) {
14535+ err = -ENOTDIR;
14536+ goto out;
14537+ }
14538+ } else {
14539+ /* rename(2) case */
14540+ err = -EIO;
14541+ if (unlikely(h_inode))
14542+ goto out;
14543+ }
1facf9fc 14544+
4a4d8108
AM
14545+ err = -ENOENT;
14546+ /* expected parent dir is locked */
14547+ if (unlikely(h_parent != h_dentry->d_parent))
14548+ goto out;
14549+ err = 0;
14550+
14551+ /*
14552+ * rmdir a dir may break the consistency on some filesystem.
14553+ * let's try heavy test.
14554+ */
14555+ err = -EACCES;
14556+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
14557+ goto out;
14558+
14559+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
14560+ au_sbr(dentry->d_sb, bindex));
14561+ err = -EIO;
14562+ if (IS_ERR(h_latest))
14563+ goto out;
14564+ if (h_latest == h_dentry)
14565+ err = 0;
14566+ dput(h_latest);
14567+
4f0767ce 14568+out:
4a4d8108 14569+ return err;
1308ab2a 14570+}
1facf9fc 14571+
4a4d8108
AM
14572+/*
14573+ * decide the branch where we operate for @dentry. the branch index will be set
14574+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
14575+ * dir for reverting.
14576+ * when a new whiteout is necessary, create it.
14577+ */
14578+static struct dentry*
14579+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
14580+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 14581+{
4a4d8108
AM
14582+ struct dentry *wh_dentry;
14583+ struct super_block *sb;
14584+ struct path h_path;
14585+ int err, need_wh;
14586+ unsigned int udba;
14587+ aufs_bindex_t bcpup;
dece6358 14588+
4a4d8108
AM
14589+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
14590+ wh_dentry = ERR_PTR(need_wh);
14591+ if (unlikely(need_wh < 0))
14592+ goto out;
14593+
14594+ sb = dentry->d_sb;
14595+ udba = au_opt_udba(sb);
14596+ bcpup = *rbcpup;
14597+ err = au_pin(pin, dentry, bcpup, udba,
14598+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14599+ wh_dentry = ERR_PTR(err);
14600+ if (unlikely(err))
14601+ goto out;
14602+
14603+ h_path.dentry = au_pinned_h_parent(pin);
14604+ if (udba != AuOpt_UDBA_NONE
14605+ && au_dbstart(dentry) == bcpup) {
14606+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
14607+ wh_dentry = ERR_PTR(err);
14608+ if (unlikely(err))
14609+ goto out_unpin;
14610+ }
14611+
14612+ h_path.mnt = au_sbr_mnt(sb, bcpup);
14613+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
14614+ wh_dentry = NULL;
14615+ if (!need_wh)
14616+ goto out; /* success, no need to create whiteout */
14617+
14618+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
14619+ if (IS_ERR(wh_dentry))
14620+ goto out_unpin;
14621+
14622+ /* returns with the parent is locked and wh_dentry is dget-ed */
14623+ goto out; /* success */
14624+
4f0767ce 14625+out_unpin:
4a4d8108 14626+ au_unpin(pin);
4f0767ce 14627+out:
4a4d8108 14628+ return wh_dentry;
1facf9fc 14629+}
14630+
4a4d8108
AM
14631+/*
14632+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
14633+ * in order to be revertible and save time for removing many child whiteouts
14634+ * under the dir.
14635+ * returns 1 when there are too many child whiteout and caller should remove
14636+ * them asynchronously. returns 0 when the number of children is enough small to
14637+ * remove now or the branch fs is a remote fs.
14638+ * otherwise return an error.
14639+ */
14640+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
14641+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 14642+{
4a4d8108
AM
14643+ int rmdir_later, err, dirwh;
14644+ struct dentry *h_dentry;
14645+ struct super_block *sb;
14646+
14647+ sb = dentry->d_sb;
14648+ SiMustAnyLock(sb);
14649+ h_dentry = au_h_dptr(dentry, bindex);
14650+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
14651+ if (unlikely(err))
14652+ goto out;
14653+
14654+ /* stop monitoring */
14655+ au_hn_free(au_hi(dentry->d_inode, bindex));
14656+
14657+ if (!au_test_fs_remote(h_dentry->d_sb)) {
14658+ dirwh = au_sbi(sb)->si_dirwh;
14659+ rmdir_later = (dirwh <= 1);
14660+ if (!rmdir_later)
14661+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
14662+ dirwh);
14663+ if (rmdir_later)
14664+ return rmdir_later;
14665+ }
1facf9fc 14666+
4a4d8108
AM
14667+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
14668+ if (unlikely(err)) {
14669+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
14670+ AuDLNPair(h_dentry), bindex, err);
14671+ err = 0;
14672+ }
dece6358 14673+
4f0767ce 14674+out:
4a4d8108
AM
14675+ AuTraceErr(err);
14676+ return err;
14677+}
1308ab2a 14678+
4a4d8108
AM
14679+/*
14680+ * final procedure for deleting a entry.
14681+ * maintain dentry and iattr.
14682+ */
14683+static void epilog(struct inode *dir, struct dentry *dentry,
14684+ aufs_bindex_t bindex)
14685+{
14686+ struct inode *inode;
1308ab2a 14687+
4a4d8108
AM
14688+ inode = dentry->d_inode;
14689+ d_drop(dentry);
14690+ inode->i_ctime = dir->i_ctime;
1308ab2a 14691+
4a4d8108
AM
14692+ if (atomic_read(&dentry->d_count) == 1) {
14693+ au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
14694+ au_update_dbstart(dentry);
dece6358 14695+ }
4a4d8108
AM
14696+ if (au_ibstart(dir) == bindex)
14697+ au_cpup_attr_timesizes(dir);
14698+ dir->i_version++;
1facf9fc 14699+}
14700+
4a4d8108
AM
14701+/*
14702+ * when an error happened, remove the created whiteout and revert everything.
14703+ */
14704+static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
14705+ struct dentry *wh_dentry, struct dentry *dentry,
14706+ struct au_dtime *dt)
1facf9fc 14707+{
4a4d8108
AM
14708+ int rerr;
14709+ struct path h_path = {
14710+ .dentry = wh_dentry,
14711+ .mnt = au_sbr_mnt(dir->i_sb, bwh)
14712+ };
dece6358 14713+
4a4d8108
AM
14714+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
14715+ if (!rerr) {
14716+ au_set_dbwh(dentry, bwh);
14717+ au_dtime_revert(dt);
14718+ return 0;
14719+ }
dece6358 14720+
4a4d8108
AM
14721+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
14722+ AuDLNPair(dentry), err, rerr);
14723+ return -EIO;
1facf9fc 14724+}
14725+
4a4d8108 14726+/* ---------------------------------------------------------------------- */
1facf9fc 14727+
4a4d8108 14728+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 14729+{
4a4d8108
AM
14730+ int err;
14731+ aufs_bindex_t bwh, bindex, bstart;
14732+ struct au_dtime dt;
14733+ struct au_pin pin;
14734+ struct path h_path;
14735+ struct inode *inode, *h_dir;
14736+ struct dentry *parent, *wh_dentry;
1facf9fc 14737+
4a4d8108
AM
14738+ IMustLock(dir);
14739+ inode = dentry->d_inode;
14740+ if (unlikely(!inode))
14741+ return -ENOENT; /* possible? */
14742+ IMustLock(inode);
1facf9fc 14743+
4a4d8108
AM
14744+ aufs_read_lock(dentry, AuLock_DW);
14745+ parent = dentry->d_parent; /* dir inode is locked */
14746+ di_write_lock_parent(parent);
1facf9fc 14747+
4a4d8108
AM
14748+ bstart = au_dbstart(dentry);
14749+ bwh = au_dbwh(dentry);
14750+ bindex = -1;
14751+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
14752+ err = PTR_ERR(wh_dentry);
14753+ if (IS_ERR(wh_dentry))
14754+ goto out;
1facf9fc 14755+
4a4d8108
AM
14756+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
14757+ h_path.dentry = au_h_dptr(dentry, bstart);
14758+ dget(h_path.dentry);
14759+ if (bindex == bstart) {
14760+ h_dir = au_pinned_h_dir(&pin);
14761+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
14762+ } else {
14763+ /* dir inode is locked */
14764+ h_dir = wh_dentry->d_parent->d_inode;
14765+ IMustLock(h_dir);
14766+ err = 0;
14767+ }
dece6358 14768+
4a4d8108
AM
14769+ if (!err) {
14770+ drop_nlink(inode);
14771+ epilog(dir, dentry, bindex);
14772+
14773+ /* update target timestamps */
14774+ if (bindex == bstart) {
14775+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
14776+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
14777+ } else
14778+ /* todo: this timestamp may be reverted later */
14779+ inode->i_ctime = h_dir->i_ctime;
14780+ goto out_unlock; /* success */
1facf9fc 14781+ }
14782+
4a4d8108
AM
14783+ /* revert */
14784+ if (wh_dentry) {
14785+ int rerr;
14786+
14787+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
14788+ if (rerr)
14789+ err = rerr;
dece6358 14790+ }
1facf9fc 14791+
4f0767ce 14792+out_unlock:
4a4d8108
AM
14793+ au_unpin(&pin);
14794+ dput(wh_dentry);
14795+ dput(h_path.dentry);
4f0767ce 14796+out:
4a4d8108
AM
14797+ di_write_unlock(parent);
14798+ aufs_read_unlock(dentry, AuLock_DW);
14799+ return err;
dece6358
AM
14800+}
14801+
4a4d8108 14802+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 14803+{
4a4d8108
AM
14804+ int err, rmdir_later;
14805+ aufs_bindex_t bwh, bindex, bstart;
14806+ struct au_dtime dt;
14807+ struct au_pin pin;
14808+ struct inode *inode;
14809+ struct dentry *parent, *wh_dentry, *h_dentry;
14810+ struct au_whtmp_rmdir *args;
1facf9fc 14811+
4a4d8108
AM
14812+ IMustLock(dir);
14813+ inode = dentry->d_inode;
14814+ err = -ENOENT; /* possible? */
14815+ if (unlikely(!inode))
14816+ goto out;
14817+ IMustLock(inode);
dece6358 14818+
4a4d8108
AM
14819+ aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
14820+ err = -ENOMEM;
14821+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
14822+ if (unlikely(!args))
14823+ goto out_unlock;
dece6358 14824+
4a4d8108
AM
14825+ parent = dentry->d_parent; /* dir inode is locked */
14826+ di_write_lock_parent(parent);
14827+ err = au_test_empty(dentry, &args->whlist);
14828+ if (unlikely(err))
14829+ goto out_args;
1facf9fc 14830+
4a4d8108
AM
14831+ bstart = au_dbstart(dentry);
14832+ bwh = au_dbwh(dentry);
14833+ bindex = -1;
14834+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
14835+ err = PTR_ERR(wh_dentry);
14836+ if (IS_ERR(wh_dentry))
14837+ goto out_args;
1facf9fc 14838+
4a4d8108
AM
14839+ h_dentry = au_h_dptr(dentry, bstart);
14840+ dget(h_dentry);
14841+ rmdir_later = 0;
14842+ if (bindex == bstart) {
14843+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
14844+ if (err > 0) {
14845+ rmdir_later = err;
14846+ err = 0;
14847+ }
14848+ } else {
14849+ /* stop monitoring */
14850+ au_hn_free(au_hi(inode, bstart));
14851+
14852+ /* dir inode is locked */
14853+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 14854+ err = 0;
14855+ }
14856+
4a4d8108
AM
14857+ if (!err) {
14858+ clear_nlink(inode);
14859+ au_set_dbdiropq(dentry, -1);
14860+ epilog(dir, dentry, bindex);
1308ab2a 14861+
4a4d8108
AM
14862+ if (rmdir_later) {
14863+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
14864+ args = NULL;
14865+ }
1308ab2a 14866+
4a4d8108 14867+ goto out_unpin; /* success */
1facf9fc 14868+ }
14869+
4a4d8108
AM
14870+ /* revert */
14871+ AuLabel(revert);
14872+ if (wh_dentry) {
14873+ int rerr;
1308ab2a 14874+
4a4d8108
AM
14875+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
14876+ if (rerr)
14877+ err = rerr;
1facf9fc 14878+ }
14879+
4f0767ce 14880+out_unpin:
4a4d8108
AM
14881+ au_unpin(&pin);
14882+ dput(wh_dentry);
14883+ dput(h_dentry);
4f0767ce 14884+out_args:
4a4d8108
AM
14885+ di_write_unlock(parent);
14886+ if (args)
14887+ au_whtmp_rmdir_free(args);
4f0767ce 14888+out_unlock:
4a4d8108 14889+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 14890+out:
4a4d8108
AM
14891+ AuTraceErr(err);
14892+ return err;
dece6358 14893+}
e49829fe 14894--- /dev/null
0c5527e5 14895+++ linux-2.6/fs/aufs/i_op_ren.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 14896@@ -0,0 +1,980 @@
1facf9fc 14897+/*
4a4d8108 14898+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 14899+ *
14900+ * This program, aufs is free software; you can redistribute it and/or modify
14901+ * it under the terms of the GNU General Public License as published by
14902+ * the Free Software Foundation; either version 2 of the License, or
14903+ * (at your option) any later version.
dece6358
AM
14904+ *
14905+ * This program is distributed in the hope that it will be useful,
14906+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14907+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14908+ * GNU General Public License for more details.
14909+ *
14910+ * You should have received a copy of the GNU General Public License
14911+ * along with this program; if not, write to the Free Software
14912+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 14913+ */
14914+
14915+/*
4a4d8108
AM
14916+ * inode operation (rename entry)
14917+ * todo: this is crazy monster
1facf9fc 14918+ */
14919+
14920+#include "aufs.h"
14921+
4a4d8108
AM
14922+enum { AuSRC, AuDST, AuSrcDst };
14923+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 14924+
4a4d8108
AM
14925+#define AuRen_ISDIR 1
14926+#define AuRen_ISSAMEDIR (1 << 1)
14927+#define AuRen_WHSRC (1 << 2)
14928+#define AuRen_WHDST (1 << 3)
14929+#define AuRen_MNT_WRITE (1 << 4)
14930+#define AuRen_DT_DSTDIR (1 << 5)
14931+#define AuRen_DIROPQ (1 << 6)
14932+#define AuRen_CPUP (1 << 7)
14933+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
14934+#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
14935+#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
1facf9fc 14936+
4a4d8108
AM
14937+struct au_ren_args {
14938+ struct {
14939+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
14940+ *wh_dentry;
14941+ struct inode *dir, *inode;
14942+ struct au_hinode *hdir;
14943+ struct au_dtime dt[AuParentChild];
14944+ aufs_bindex_t bstart;
14945+ } sd[AuSrcDst];
1facf9fc 14946+
4a4d8108
AM
14947+#define src_dentry sd[AuSRC].dentry
14948+#define src_dir sd[AuSRC].dir
14949+#define src_inode sd[AuSRC].inode
14950+#define src_h_dentry sd[AuSRC].h_dentry
14951+#define src_parent sd[AuSRC].parent
14952+#define src_h_parent sd[AuSRC].h_parent
14953+#define src_wh_dentry sd[AuSRC].wh_dentry
14954+#define src_hdir sd[AuSRC].hdir
14955+#define src_h_dir sd[AuSRC].hdir->hi_inode
14956+#define src_dt sd[AuSRC].dt
14957+#define src_bstart sd[AuSRC].bstart
1facf9fc 14958+
4a4d8108
AM
14959+#define dst_dentry sd[AuDST].dentry
14960+#define dst_dir sd[AuDST].dir
14961+#define dst_inode sd[AuDST].inode
14962+#define dst_h_dentry sd[AuDST].h_dentry
14963+#define dst_parent sd[AuDST].parent
14964+#define dst_h_parent sd[AuDST].h_parent
14965+#define dst_wh_dentry sd[AuDST].wh_dentry
14966+#define dst_hdir sd[AuDST].hdir
14967+#define dst_h_dir sd[AuDST].hdir->hi_inode
14968+#define dst_dt sd[AuDST].dt
14969+#define dst_bstart sd[AuDST].bstart
14970+
14971+ struct dentry *h_trap;
14972+ struct au_branch *br;
14973+ struct au_hinode *src_hinode;
14974+ struct path h_path;
14975+ struct au_nhash whlist;
14976+ aufs_bindex_t btgt;
1facf9fc 14977+
1308ab2a 14978+ unsigned int flags;
1facf9fc 14979+
4a4d8108
AM
14980+ struct au_whtmp_rmdir *thargs;
14981+ struct dentry *h_dst;
14982+};
1308ab2a 14983+
4a4d8108 14984+/* ---------------------------------------------------------------------- */
1308ab2a 14985+
4a4d8108
AM
14986+/*
14987+ * functions for reverting.
14988+ * when an error happened in a single rename systemcall, we should revert
14989+ * everything as if nothing happend.
14990+ * we don't need to revert the copied-up/down the parent dir since they are
14991+ * harmless.
14992+ */
1facf9fc 14993+
4a4d8108
AM
14994+#define RevertFailure(fmt, ...) do { \
14995+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
14996+ ##__VA_ARGS__, err, rerr); \
14997+ err = -EIO; \
14998+} while (0)
1facf9fc 14999+
4a4d8108 15000+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 15001+{
4a4d8108 15002+ int rerr;
1facf9fc 15003+
4a4d8108
AM
15004+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15005+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
15006+ au_hn_imtx_unlock(a->src_hinode);
15007+ if (rerr)
15008+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
15009+}
1facf9fc 15010+
4a4d8108
AM
15011+static void au_ren_rev_rename(int err, struct au_ren_args *a)
15012+{
15013+ int rerr;
1facf9fc 15014+
4a4d8108
AM
15015+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
15016+ a->br, /*nd*/NULL);
15017+ rerr = PTR_ERR(a->h_path.dentry);
15018+ if (IS_ERR(a->h_path.dentry)) {
15019+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
15020+ return;
1facf9fc 15021+ }
15022+
4a4d8108
AM
15023+ rerr = vfsub_rename(a->dst_h_dir,
15024+ au_h_dptr(a->src_dentry, a->btgt),
15025+ a->src_h_dir, &a->h_path);
15026+ d_drop(a->h_path.dentry);
15027+ dput(a->h_path.dentry);
15028+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
15029+ if (rerr)
15030+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 15031+}
15032+
4a4d8108 15033+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 15034+{
4a4d8108 15035+ int rerr;
1facf9fc 15036+
4a4d8108
AM
15037+ a->h_path.dentry = a->dst_h_dentry;
15038+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
15039+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
15040+ au_set_dbstart(a->src_dentry, a->src_bstart);
15041+ if (rerr)
15042+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 15043+}
15044+
4a4d8108 15045+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 15046+{
4a4d8108 15047+ int rerr;
dece6358 15048+
4a4d8108
AM
15049+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
15050+ a->br, /*nd*/NULL);
15051+ rerr = PTR_ERR(a->h_path.dentry);
15052+ if (IS_ERR(a->h_path.dentry)) {
15053+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
15054+ return;
15055+ }
15056+ if (a->h_path.dentry->d_inode) {
15057+ d_drop(a->h_path.dentry);
15058+ dput(a->h_path.dentry);
15059+ return;
dece6358
AM
15060+ }
15061+
4a4d8108
AM
15062+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
15063+ d_drop(a->h_path.dentry);
15064+ dput(a->h_path.dentry);
15065+ if (!rerr)
15066+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
15067+ else
15068+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
15069+}
1308ab2a 15070+
4a4d8108
AM
15071+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
15072+{
15073+ int rerr;
1308ab2a 15074+
4a4d8108
AM
15075+ a->h_path.dentry = a->src_wh_dentry;
15076+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
15077+ if (rerr)
15078+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
15079+}
1308ab2a 15080+
4a4d8108
AM
15081+static void au_ren_rev_drop(struct au_ren_args *a)
15082+{
15083+ struct dentry *d, *h_d;
15084+ int i;
15085+ aufs_bindex_t bend, bindex;
15086+
15087+ for (i = 0; i < AuSrcDst; i++) {
15088+ d = a->sd[i].dentry;
15089+ d_drop(d);
15090+ bend = au_dbend(d);
15091+ for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
15092+ h_d = au_h_dptr(d, bindex);
15093+ if (h_d)
15094+ d_drop(h_d);
15095+ }
1308ab2a 15096+ }
15097+
4a4d8108
AM
15098+ au_update_dbstart(a->dst_dentry);
15099+ if (a->thargs)
15100+ d_drop(a->h_dst);
1facf9fc 15101+}
4a4d8108 15102+#undef RevertFailure
1facf9fc 15103+
1308ab2a 15104+/* ---------------------------------------------------------------------- */
15105+
4a4d8108
AM
15106+/*
15107+ * when we have to copyup the renaming entry, do it with the rename-target name
15108+ * in order to minimize the cost (the later actual rename is unnecessary).
15109+ * otherwise rename it on the target branch.
15110+ */
15111+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 15112+{
dece6358 15113+ int err;
4a4d8108 15114+ struct dentry *d;
1facf9fc 15115+
4a4d8108
AM
15116+ d = a->src_dentry;
15117+ if (au_dbstart(d) == a->btgt) {
15118+ a->h_path.dentry = a->dst_h_dentry;
15119+ if (au_ftest_ren(a->flags, DIROPQ)
15120+ && au_dbdiropq(d) == a->btgt)
15121+ au_fclr_ren(a->flags, DIROPQ);
15122+ AuDebugOn(au_dbstart(d) != a->btgt);
15123+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
15124+ a->dst_h_dir, &a->h_path);
15125+ } else {
15126+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15127+ struct file *h_file;
1308ab2a 15128+
4a4d8108
AM
15129+ au_fset_ren(a->flags, CPUP);
15130+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15131+ au_set_dbstart(d, a->btgt);
15132+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
15133+ h_file = au_h_open_pre(d, a->src_bstart);
15134+ if (IS_ERR(h_file)) {
15135+ err = PTR_ERR(h_file);
15136+ h_file = NULL;
15137+ } else
15138+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
15139+ !AuCpup_DTIME, a->dst_parent);
15140+ mutex_unlock(h_mtx);
15141+ au_h_open_post(d, a->src_bstart, h_file);
15142+ if (!err) {
15143+ d = a->dst_dentry;
15144+ au_set_h_dptr(d, a->btgt, NULL);
15145+ au_update_dbstart(d);
15146+ } else {
15147+ au_set_h_dptr(d, a->btgt, NULL);
15148+ au_set_dbstart(d, a->src_bstart);
15149+ }
1308ab2a 15150+ }
1facf9fc 15151+
dece6358
AM
15152+ return err;
15153+}
1facf9fc 15154+
4a4d8108
AM
15155+/* cf. aufs_rmdir() */
15156+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 15157+{
4a4d8108
AM
15158+ int err;
15159+ struct inode *dir;
1facf9fc 15160+
4a4d8108
AM
15161+ dir = a->dst_dir;
15162+ SiMustAnyLock(dir->i_sb);
15163+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
15164+ au_sbi(dir->i_sb)->si_dirwh)
15165+ || au_test_fs_remote(a->h_dst->d_sb)) {
15166+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
15167+ if (unlikely(err))
15168+ pr_warning("failed removing whtmp dir %.*s (%d), "
15169+ "ignored.\n", AuDLNPair(a->h_dst), err);
15170+ } else {
15171+ au_nhash_wh_free(&a->thargs->whlist);
15172+ a->thargs->whlist = a->whlist;
15173+ a->whlist.nh_num = 0;
15174+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
15175+ dput(a->h_dst);
15176+ a->thargs = NULL;
15177+ }
15178+
15179+ return 0;
1308ab2a 15180+}
1facf9fc 15181+
4a4d8108
AM
15182+/* make it 'opaque' dir. */
15183+static int au_ren_diropq(struct au_ren_args *a)
15184+{
15185+ int err;
15186+ struct dentry *diropq;
1facf9fc 15187+
4a4d8108
AM
15188+ err = 0;
15189+ a->src_hinode = au_hi(a->src_inode, a->btgt);
15190+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
15191+ diropq = au_diropq_create(a->src_dentry, a->btgt);
15192+ au_hn_imtx_unlock(a->src_hinode);
15193+ if (IS_ERR(diropq))
15194+ err = PTR_ERR(diropq);
15195+ dput(diropq);
1facf9fc 15196+
4a4d8108
AM
15197+ return err;
15198+}
1facf9fc 15199+
4a4d8108
AM
15200+static int do_rename(struct au_ren_args *a)
15201+{
15202+ int err;
15203+ struct dentry *d, *h_d;
1facf9fc 15204+
4a4d8108
AM
15205+ /* prepare workqueue args for asynchronous rmdir */
15206+ h_d = a->dst_h_dentry;
15207+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
15208+ err = -ENOMEM;
15209+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
15210+ if (unlikely(!a->thargs))
15211+ goto out;
15212+ a->h_dst = dget(h_d);
15213+ }
1facf9fc 15214+
4a4d8108
AM
15215+ /* create whiteout for src_dentry */
15216+ if (au_ftest_ren(a->flags, WHSRC)) {
15217+ a->src_wh_dentry
15218+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
15219+ err = PTR_ERR(a->src_wh_dentry);
15220+ if (IS_ERR(a->src_wh_dentry))
15221+ goto out_thargs;
15222+ }
1facf9fc 15223+
4a4d8108
AM
15224+ /* lookup whiteout for dentry */
15225+ if (au_ftest_ren(a->flags, WHDST)) {
15226+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
15227+ a->br);
15228+ err = PTR_ERR(h_d);
15229+ if (IS_ERR(h_d))
15230+ goto out_whsrc;
15231+ if (!h_d->d_inode)
15232+ dput(h_d);
15233+ else
15234+ a->dst_wh_dentry = h_d;
15235+ }
1facf9fc 15236+
4a4d8108
AM
15237+ /* rename dentry to tmpwh */
15238+ if (a->thargs) {
15239+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
15240+ if (unlikely(err))
15241+ goto out_whdst;
dece6358 15242+
4a4d8108
AM
15243+ d = a->dst_dentry;
15244+ au_set_h_dptr(d, a->btgt, NULL);
15245+ err = au_lkup_neg(d, a->btgt);
15246+ if (unlikely(err))
15247+ goto out_whtmp;
15248+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
15249+ }
1facf9fc 15250+
4a4d8108
AM
15251+ /* cpup src */
15252+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
15253+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
15254+ struct file *h_file;
1facf9fc 15255+
4a4d8108
AM
15256+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15257+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
15258+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
15259+ if (IS_ERR(h_file)) {
15260+ err = PTR_ERR(h_file);
15261+ h_file = NULL;
15262+ } else
15263+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
15264+ !AuCpup_DTIME);
15265+ mutex_unlock(h_mtx);
15266+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
15267+ if (unlikely(err))
15268+ goto out_whtmp;
15269+ }
1facf9fc 15270+
4a4d8108
AM
15271+ /* rename by vfs_rename or cpup */
15272+ d = a->dst_dentry;
15273+ if (au_ftest_ren(a->flags, ISDIR)
15274+ && (a->dst_wh_dentry
15275+ || au_dbdiropq(d) == a->btgt
15276+ /* hide the lower to keep xino */
15277+ || a->btgt < au_dbend(d)
15278+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
15279+ au_fset_ren(a->flags, DIROPQ);
15280+ err = au_ren_or_cpup(a);
15281+ if (unlikely(err))
15282+ /* leave the copied-up one */
15283+ goto out_whtmp;
1308ab2a 15284+
4a4d8108
AM
15285+ /* make dir opaque */
15286+ if (au_ftest_ren(a->flags, DIROPQ)) {
15287+ err = au_ren_diropq(a);
15288+ if (unlikely(err))
15289+ goto out_rename;
15290+ }
1308ab2a 15291+
4a4d8108
AM
15292+ /* update target timestamps */
15293+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
15294+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
15295+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
15296+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 15297+
4a4d8108
AM
15298+ /* remove whiteout for dentry */
15299+ if (a->dst_wh_dentry) {
15300+ a->h_path.dentry = a->dst_wh_dentry;
15301+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
15302+ a->dst_dentry);
15303+ if (unlikely(err))
15304+ goto out_diropq;
15305+ }
1facf9fc 15306+
4a4d8108
AM
15307+ /* remove whtmp */
15308+ if (a->thargs)
15309+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 15310+
4a4d8108
AM
15311+ err = 0;
15312+ goto out_success;
15313+
4f0767ce 15314+out_diropq:
4a4d8108
AM
15315+ if (au_ftest_ren(a->flags, DIROPQ))
15316+ au_ren_rev_diropq(err, a);
4f0767ce 15317+out_rename:
4a4d8108
AM
15318+ if (!au_ftest_ren(a->flags, CPUP))
15319+ au_ren_rev_rename(err, a);
15320+ else
15321+ au_ren_rev_cpup(err, a);
4f0767ce 15322+out_whtmp:
4a4d8108
AM
15323+ if (a->thargs)
15324+ au_ren_rev_whtmp(err, a);
4f0767ce 15325+out_whdst:
4a4d8108
AM
15326+ dput(a->dst_wh_dentry);
15327+ a->dst_wh_dentry = NULL;
4f0767ce 15328+out_whsrc:
4a4d8108
AM
15329+ if (a->src_wh_dentry)
15330+ au_ren_rev_whsrc(err, a);
15331+ au_ren_rev_drop(a);
4f0767ce 15332+out_success:
4a4d8108
AM
15333+ dput(a->src_wh_dentry);
15334+ dput(a->dst_wh_dentry);
4f0767ce 15335+out_thargs:
4a4d8108
AM
15336+ if (a->thargs) {
15337+ dput(a->h_dst);
15338+ au_whtmp_rmdir_free(a->thargs);
15339+ a->thargs = NULL;
15340+ }
4f0767ce 15341+out:
4a4d8108 15342+ return err;
dece6358 15343+}
1facf9fc 15344+
1308ab2a 15345+/* ---------------------------------------------------------------------- */
1facf9fc 15346+
4a4d8108
AM
15347+/*
15348+ * test if @dentry dir can be rename destination or not.
15349+ * success means, it is a logically empty dir.
15350+ */
15351+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 15352+{
4a4d8108 15353+ return au_test_empty(dentry, whlist);
1308ab2a 15354+}
1facf9fc 15355+
4a4d8108
AM
15356+/*
15357+ * test if @dentry dir can be rename source or not.
15358+ * if it can, return 0 and @children is filled.
15359+ * success means,
15360+ * - it is a logically empty dir.
15361+ * - or, it exists on writable branch and has no children including whiteouts
15362+ * on the lower branch.
15363+ */
15364+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
15365+{
15366+ int err;
15367+ unsigned int rdhash;
15368+ aufs_bindex_t bstart;
1facf9fc 15369+
4a4d8108
AM
15370+ bstart = au_dbstart(dentry);
15371+ if (bstart != btgt) {
15372+ struct au_nhash whlist;
dece6358 15373+
4a4d8108
AM
15374+ SiMustAnyLock(dentry->d_sb);
15375+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
15376+ if (!rdhash)
15377+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
15378+ dentry));
15379+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
15380+ if (unlikely(err))
15381+ goto out;
15382+ err = au_test_empty(dentry, &whlist);
15383+ au_nhash_wh_free(&whlist);
15384+ goto out;
15385+ }
dece6358 15386+
4a4d8108
AM
15387+ if (bstart == au_dbtaildir(dentry))
15388+ return 0; /* success */
dece6358 15389+
4a4d8108 15390+ err = au_test_empty_lower(dentry);
1facf9fc 15391+
4f0767ce 15392+out:
4a4d8108
AM
15393+ if (err == -ENOTEMPTY) {
15394+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
15395+ " is not supported\n");
15396+ err = -EXDEV;
15397+ }
15398+ return err;
15399+}
1308ab2a 15400+
4a4d8108
AM
15401+/* side effect: sets whlist and h_dentry */
15402+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 15403+{
4a4d8108
AM
15404+ int err;
15405+ unsigned int rdhash;
15406+ struct dentry *d;
1facf9fc 15407+
4a4d8108
AM
15408+ d = a->dst_dentry;
15409+ SiMustAnyLock(d->d_sb);
1facf9fc 15410+
4a4d8108
AM
15411+ err = 0;
15412+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
15413+ rdhash = au_sbi(d->d_sb)->si_rdhash;
15414+ if (!rdhash)
15415+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
15416+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
15417+ if (unlikely(err))
15418+ goto out;
1308ab2a 15419+
4a4d8108
AM
15420+ au_set_dbstart(d, a->dst_bstart);
15421+ err = may_rename_dstdir(d, &a->whlist);
15422+ au_set_dbstart(d, a->btgt);
15423+ }
15424+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
15425+ if (unlikely(err))
15426+ goto out;
15427+
15428+ d = a->src_dentry;
15429+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
15430+ if (au_ftest_ren(a->flags, ISDIR)) {
15431+ err = may_rename_srcdir(d, a->btgt);
15432+ if (unlikely(err)) {
15433+ au_nhash_wh_free(&a->whlist);
15434+ a->whlist.nh_num = 0;
15435+ }
15436+ }
4f0767ce 15437+out:
4a4d8108 15438+ return err;
1facf9fc 15439+}
15440+
4a4d8108 15441+/* ---------------------------------------------------------------------- */
1facf9fc 15442+
4a4d8108
AM
15443+/*
15444+ * simple tests for rename.
15445+ * following the checks in vfs, plus the parent-child relationship.
15446+ */
15447+static int au_may_ren(struct au_ren_args *a)
15448+{
15449+ int err, isdir;
15450+ struct inode *h_inode;
1facf9fc 15451+
4a4d8108
AM
15452+ if (a->src_bstart == a->btgt) {
15453+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
15454+ au_ftest_ren(a->flags, ISDIR));
15455+ if (unlikely(err))
15456+ goto out;
15457+ err = -EINVAL;
15458+ if (unlikely(a->src_h_dentry == a->h_trap))
15459+ goto out;
15460+ }
1facf9fc 15461+
4a4d8108
AM
15462+ err = 0;
15463+ if (a->dst_bstart != a->btgt)
15464+ goto out;
1facf9fc 15465+
4a4d8108
AM
15466+ err = -EIO;
15467+ h_inode = a->dst_h_dentry->d_inode;
15468+ isdir = !!au_ftest_ren(a->flags, ISDIR);
15469+ if (!a->dst_dentry->d_inode) {
15470+ if (unlikely(h_inode))
15471+ goto out;
15472+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
15473+ isdir);
15474+ } else {
15475+ if (unlikely(!h_inode || !h_inode->i_nlink))
15476+ goto out;
15477+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
15478+ isdir);
15479+ if (unlikely(err))
15480+ goto out;
15481+ err = -ENOTEMPTY;
15482+ if (unlikely(a->dst_h_dentry == a->h_trap))
15483+ goto out;
15484+ err = 0;
15485+ }
1facf9fc 15486+
4f0767ce 15487+out:
4a4d8108
AM
15488+ if (unlikely(err == -ENOENT || err == -EEXIST))
15489+ err = -EIO;
15490+ AuTraceErr(err);
15491+ return err;
15492+}
1facf9fc 15493+
1308ab2a 15494+/* ---------------------------------------------------------------------- */
1facf9fc 15495+
4a4d8108
AM
15496+/*
15497+ * locking order
15498+ * (VFS)
15499+ * - src_dir and dir by lock_rename()
15500+ * - inode if exitsts
15501+ * (aufs)
15502+ * - lock all
15503+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
15504+ * + si_read_lock
15505+ * + di_write_lock2_child()
15506+ * + di_write_lock_child()
15507+ * + ii_write_lock_child()
15508+ * + di_write_lock_child2()
15509+ * + ii_write_lock_child2()
15510+ * + src_parent and parent
15511+ * + di_write_lock_parent()
15512+ * + ii_write_lock_parent()
15513+ * + di_write_lock_parent2()
15514+ * + ii_write_lock_parent2()
15515+ * + lower src_dir and dir by vfsub_lock_rename()
15516+ * + verify the every relationships between child and parent. if any
15517+ * of them failed, unlock all and return -EBUSY.
15518+ */
15519+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 15520+{
4a4d8108
AM
15521+ struct super_block *sb;
15522+
15523+ sb = a->dst_dentry->d_sb;
15524+ if (au_ftest_ren(a->flags, MNT_WRITE))
15525+ mnt_drop_write(a->br->br_mnt);
15526+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
15527+ a->dst_h_parent, a->dst_hdir);
1308ab2a 15528+}
15529+
4a4d8108 15530+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 15531+{
4a4d8108
AM
15532+ int err;
15533+ unsigned int udba;
1308ab2a 15534+
4a4d8108
AM
15535+ err = 0;
15536+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
15537+ a->src_hdir = au_hi(a->src_dir, a->btgt);
15538+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
15539+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
15540+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
15541+ a->dst_h_parent, a->dst_hdir);
15542+ udba = au_opt_udba(a->src_dentry->d_sb);
15543+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
15544+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
15545+ err = au_busy_or_stale();
15546+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
15547+ err = au_h_verify(a->src_h_dentry, udba,
15548+ a->src_h_parent->d_inode, a->src_h_parent,
15549+ a->br);
15550+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
15551+ err = au_h_verify(a->dst_h_dentry, udba,
15552+ a->dst_h_parent->d_inode, a->dst_h_parent,
15553+ a->br);
15554+ if (!err) {
15555+ err = mnt_want_write(a->br->br_mnt);
15556+ if (unlikely(err))
15557+ goto out_unlock;
15558+ au_fset_ren(a->flags, MNT_WRITE);
15559+ goto out; /* success */
15560+ }
15561+
15562+ err = au_busy_or_stale();
15563+
4f0767ce 15564+out_unlock:
4a4d8108 15565+ au_ren_unlock(a);
4f0767ce 15566+out:
4a4d8108 15567+ return err;
1facf9fc 15568+}
15569+
15570+/* ---------------------------------------------------------------------- */
15571+
4a4d8108 15572+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 15573+{
4a4d8108 15574+ struct inode *dir;
dece6358 15575+
4a4d8108
AM
15576+ dir = a->dst_dir;
15577+ dir->i_version++;
15578+ if (au_ftest_ren(a->flags, ISDIR)) {
15579+ /* is this updating defined in POSIX? */
15580+ au_cpup_attr_timesizes(a->src_inode);
15581+ au_cpup_attr_nlink(dir, /*force*/1);
15582+ if (a->dst_inode) {
15583+ clear_nlink(a->dst_inode);
15584+ au_cpup_attr_timesizes(a->dst_inode);
15585+ }
15586+ }
15587+ if (au_ibstart(dir) == a->btgt)
15588+ au_cpup_attr_timesizes(dir);
dece6358 15589+
4a4d8108
AM
15590+ if (au_ftest_ren(a->flags, ISSAMEDIR))
15591+ return;
dece6358 15592+
4a4d8108
AM
15593+ dir = a->src_dir;
15594+ dir->i_version++;
15595+ if (au_ftest_ren(a->flags, ISDIR))
15596+ au_cpup_attr_nlink(dir, /*force*/1);
15597+ if (au_ibstart(dir) == a->btgt)
15598+ au_cpup_attr_timesizes(dir);
1facf9fc 15599+}
15600+
4a4d8108 15601+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 15602+{
4a4d8108
AM
15603+ aufs_bindex_t bend, bindex;
15604+ struct dentry *d, *h_d;
15605+ struct inode *i, *h_i;
15606+ struct super_block *sb;
dece6358 15607+
4a4d8108
AM
15608+ d = a->src_dentry;
15609+ au_set_dbwh(d, -1);
15610+ bend = au_dbend(d);
15611+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
15612+ h_d = au_h_dptr(d, bindex);
15613+ if (h_d)
15614+ au_set_h_dptr(d, bindex, NULL);
15615+ }
15616+ au_set_dbend(d, a->btgt);
15617+
15618+ sb = d->d_sb;
15619+ i = a->src_inode;
15620+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
15621+ return; /* success */
15622+
15623+ bend = au_ibend(i);
15624+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
15625+ h_i = au_h_iptr(i, bindex);
15626+ if (h_i) {
15627+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
15628+ /* ignore this error */
15629+ au_set_h_iptr(i, bindex, NULL, 0);
15630+ }
15631+ }
15632+ au_set_ibend(i, a->btgt);
1308ab2a 15633+}
dece6358 15634+
4a4d8108
AM
15635+/* ---------------------------------------------------------------------- */
15636+
15637+/* mainly for link(2) and rename(2) */
15638+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 15639+{
4a4d8108
AM
15640+ aufs_bindex_t bdiropq, bwh;
15641+ struct dentry *parent;
15642+ struct au_branch *br;
15643+
15644+ parent = dentry->d_parent;
15645+ IMustLock(parent->d_inode); /* dir is locked */
15646+
15647+ bdiropq = au_dbdiropq(parent);
15648+ bwh = au_dbwh(dentry);
15649+ br = au_sbr(dentry->d_sb, btgt);
15650+ if (au_br_rdonly(br)
15651+ || (0 <= bdiropq && bdiropq < btgt)
15652+ || (0 <= bwh && bwh < btgt))
15653+ btgt = -1;
15654+
15655+ AuDbg("btgt %d\n", btgt);
15656+ return btgt;
1facf9fc 15657+}
15658+
4a4d8108
AM
15659+/* sets src_bstart, dst_bstart and btgt */
15660+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 15661+{
4a4d8108
AM
15662+ int err;
15663+ struct au_wr_dir_args wr_dir_args = {
15664+ /* .force_btgt = -1, */
15665+ .flags = AuWrDir_ADD_ENTRY
15666+ };
dece6358 15667+
4a4d8108
AM
15668+ a->src_bstart = au_dbstart(a->src_dentry);
15669+ a->dst_bstart = au_dbstart(a->dst_dentry);
15670+ if (au_ftest_ren(a->flags, ISDIR))
15671+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
15672+ wr_dir_args.force_btgt = a->src_bstart;
15673+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
15674+ wr_dir_args.force_btgt = a->dst_bstart;
15675+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
15676+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
15677+ a->btgt = err;
dece6358 15678+
4a4d8108 15679+ return err;
1facf9fc 15680+}
15681+
4a4d8108 15682+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 15683+{
4a4d8108
AM
15684+ a->h_path.dentry = a->src_h_parent;
15685+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
15686+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
15687+ a->h_path.dentry = a->dst_h_parent;
15688+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
15689+ }
1facf9fc 15690+
4a4d8108
AM
15691+ au_fclr_ren(a->flags, DT_DSTDIR);
15692+ if (!au_ftest_ren(a->flags, ISDIR))
15693+ return;
dece6358 15694+
4a4d8108
AM
15695+ a->h_path.dentry = a->src_h_dentry;
15696+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
15697+ if (a->dst_h_dentry->d_inode) {
15698+ au_fset_ren(a->flags, DT_DSTDIR);
15699+ a->h_path.dentry = a->dst_h_dentry;
15700+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
15701+ }
1308ab2a 15702+}
dece6358 15703+
4a4d8108 15704+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 15705+{
4a4d8108
AM
15706+ struct dentry *h_d;
15707+ struct mutex *h_mtx;
15708+
15709+ au_dtime_revert(a->src_dt + AuPARENT);
15710+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
15711+ au_dtime_revert(a->dst_dt + AuPARENT);
15712+
15713+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
15714+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
15715+ h_mtx = &h_d->d_inode->i_mutex;
15716+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15717+ au_dtime_revert(a->src_dt + AuCHILD);
15718+ mutex_unlock(h_mtx);
15719+
15720+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
15721+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
15722+ h_mtx = &h_d->d_inode->i_mutex;
15723+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15724+ au_dtime_revert(a->dst_dt + AuCHILD);
15725+ mutex_unlock(h_mtx);
1facf9fc 15726+ }
15727+ }
15728+}
15729+
4a4d8108
AM
15730+/* ---------------------------------------------------------------------- */
15731+
15732+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
15733+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 15734+{
e49829fe 15735+ int err, flags;
4a4d8108
AM
15736+ /* reduce stack space */
15737+ struct au_ren_args *a;
15738+
15739+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
15740+ IMustLock(_src_dir);
15741+ IMustLock(_dst_dir);
15742+
15743+ err = -ENOMEM;
15744+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
15745+ a = kzalloc(sizeof(*a), GFP_NOFS);
15746+ if (unlikely(!a))
15747+ goto out;
15748+
15749+ a->src_dir = _src_dir;
15750+ a->src_dentry = _src_dentry;
15751+ a->src_inode = a->src_dentry->d_inode;
15752+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
15753+ a->dst_dir = _dst_dir;
15754+ a->dst_dentry = _dst_dentry;
15755+ a->dst_inode = a->dst_dentry->d_inode;
15756+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
15757+ if (a->dst_inode) {
15758+ IMustLock(a->dst_inode);
15759+ au_igrab(a->dst_inode);
1facf9fc 15760+ }
1facf9fc 15761+
4a4d8108 15762+ err = -ENOTDIR;
e49829fe 15763+ flags = AuLock_FLUSH | AuLock_NOPLM;
4a4d8108
AM
15764+ if (S_ISDIR(a->src_inode->i_mode)) {
15765+ au_fset_ren(a->flags, ISDIR);
15766+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
15767+ goto out_free;
e49829fe
JR
15768+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
15769+ AuLock_DIR | flags);
4a4d8108 15770+ } else
e49829fe
JR
15771+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
15772+ flags);
15773+ if (unlikely(err))
15774+ goto out_free;
1facf9fc 15775+
4a4d8108
AM
15776+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
15777+ di_write_lock_parent(a->dst_parent);
1facf9fc 15778+
4a4d8108
AM
15779+ /* which branch we process */
15780+ err = au_ren_wbr(a);
15781+ if (unlikely(err < 0))
15782+ goto out_unlock;
15783+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
15784+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 15785+
4a4d8108
AM
15786+ /* are they available to be renamed */
15787+ err = au_ren_may_dir(a);
15788+ if (unlikely(err))
15789+ goto out_children;
1facf9fc 15790+
4a4d8108
AM
15791+ /* prepare the writable parent dir on the same branch */
15792+ if (a->dst_bstart == a->btgt) {
15793+ au_fset_ren(a->flags, WHDST);
15794+ } else {
15795+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
15796+ if (unlikely(err))
15797+ goto out_children;
15798+ }
1facf9fc 15799+
4a4d8108
AM
15800+ if (a->src_dir != a->dst_dir) {
15801+ /*
15802+ * this temporary unlock is safe,
15803+ * because both dir->i_mutex are locked.
15804+ */
15805+ di_write_unlock(a->dst_parent);
15806+ di_write_lock_parent(a->src_parent);
15807+ err = au_wr_dir_need_wh(a->src_dentry,
15808+ au_ftest_ren(a->flags, ISDIR),
15809+ &a->btgt);
15810+ di_write_unlock(a->src_parent);
15811+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
15812+ au_fclr_ren(a->flags, ISSAMEDIR);
15813+ } else
15814+ err = au_wr_dir_need_wh(a->src_dentry,
15815+ au_ftest_ren(a->flags, ISDIR),
15816+ &a->btgt);
15817+ if (unlikely(err < 0))
15818+ goto out_children;
15819+ if (err)
15820+ au_fset_ren(a->flags, WHSRC);
1facf9fc 15821+
4a4d8108
AM
15822+ /* lock them all */
15823+ err = au_ren_lock(a);
15824+ if (unlikely(err))
15825+ goto out_children;
1facf9fc 15826+
4a4d8108
AM
15827+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
15828+ err = au_may_ren(a);
15829+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
15830+ err = -ENAMETOOLONG;
15831+ if (unlikely(err))
15832+ goto out_hdir;
1facf9fc 15833+
4a4d8108
AM
15834+ /* store timestamps to be revertible */
15835+ au_ren_dt(a);
1facf9fc 15836+
4a4d8108
AM
15837+ /* here we go */
15838+ err = do_rename(a);
15839+ if (unlikely(err))
15840+ goto out_dt;
15841+
15842+ /* update dir attributes */
15843+ au_ren_refresh_dir(a);
15844+
15845+ /* dput/iput all lower dentries */
15846+ au_ren_refresh(a);
15847+
15848+ goto out_hdir; /* success */
15849+
4f0767ce 15850+out_dt:
4a4d8108 15851+ au_ren_rev_dt(err, a);
4f0767ce 15852+out_hdir:
4a4d8108 15853+ au_ren_unlock(a);
4f0767ce 15854+out_children:
4a4d8108 15855+ au_nhash_wh_free(&a->whlist);
4f0767ce 15856+out_unlock:
4a4d8108
AM
15857+ if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
15858+ au_update_dbstart(a->dst_dentry);
15859+ d_drop(a->dst_dentry);
15860+ }
15861+ if (!err)
15862+ d_move(a->src_dentry, a->dst_dentry);
15863+ if (au_ftest_ren(a->flags, ISSAMEDIR))
15864+ di_write_unlock(a->dst_parent);
15865+ else
15866+ di_write_unlock2(a->src_parent, a->dst_parent);
15867+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 15868+out_free:
4a4d8108
AM
15869+ iput(a->dst_inode);
15870+ if (a->thargs)
15871+ au_whtmp_rmdir_free(a->thargs);
15872+ kfree(a);
4f0767ce 15873+out:
4a4d8108
AM
15874+ AuTraceErr(err);
15875+ return err;
1308ab2a 15876+}
e49829fe 15877--- /dev/null
0c5527e5 15878+++ linux-2.6/fs/aufs/Kconfig 2010-10-25 14:20:44.000000000 +0200
e49829fe 15879@@ -0,0 +1,182 @@
4a4d8108
AM
15880+config AUFS_FS
15881+ tristate "Aufs (Advanced multi layered unification filesystem) support"
15882+ depends on EXPERIMENTAL
15883+ help
15884+ Aufs is a stackable unification filesystem such as Unionfs,
15885+ which unifies several directories and provides a merged single
15886+ directory.
15887+ In the early days, aufs was entirely re-designed and
15888+ re-implemented Unionfs Version 1.x series. Introducing many
15889+ original ideas, approaches and improvements, it becomes totally
15890+ different from Unionfs while keeping the basic features.
1facf9fc 15891+
4a4d8108
AM
15892+if AUFS_FS
15893+choice
15894+ prompt "Maximum number of branches"
15895+ default AUFS_BRANCH_MAX_127
15896+ help
15897+ Specifies the maximum number of branches (or member directories)
15898+ in a single aufs. The larger value consumes more system
15899+ resources and has a minor impact to performance.
15900+config AUFS_BRANCH_MAX_127
15901+ bool "127"
15902+ help
15903+ Specifies the maximum number of branches (or member directories)
15904+ in a single aufs. The larger value consumes more system
15905+ resources and has a minor impact to performance.
15906+config AUFS_BRANCH_MAX_511
15907+ bool "511"
15908+ help
15909+ Specifies the maximum number of branches (or member directories)
15910+ in a single aufs. The larger value consumes more system
15911+ resources and has a minor impact to performance.
15912+config AUFS_BRANCH_MAX_1023
15913+ bool "1023"
15914+ help
15915+ Specifies the maximum number of branches (or member directories)
15916+ in a single aufs. The larger value consumes more system
15917+ resources and has a minor impact to performance.
15918+config AUFS_BRANCH_MAX_32767
15919+ bool "32767"
15920+ help
15921+ Specifies the maximum number of branches (or member directories)
15922+ in a single aufs. The larger value consumes more system
15923+ resources and has a minor impact to performance.
15924+endchoice
1facf9fc 15925+
e49829fe
JR
15926+config AUFS_SBILIST
15927+ bool
15928+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
15929+ default y
15930+ help
15931+ Automatic configuration for internal use.
15932+ When aufs supports Magic SysRq or /proc, enabled automatically.
15933+
4a4d8108
AM
15934+config AUFS_HNOTIFY
15935+ bool "Detect direct branch access (bypassing aufs)"
15936+ help
15937+ If you want to modify files on branches directly, eg. bypassing aufs,
15938+ and want aufs to detect the changes of them fully, then enable this
15939+ option and use 'udba=notify' mount option.
15940+ It will have a negative impact to the performance.
15941+ See detail in aufs.5.
dece6358 15942+
4a4d8108
AM
15943+choice
15944+ prompt "method" if AUFS_HNOTIFY
15945+ default AUFS_HFSNOTIFY
15946+config AUFS_HFSNOTIFY
15947+ bool "fsnotify"
15948+ select FSNOTIFY
e49829fe
JR
15949+config AUFS_HINOTIFY
15950+ bool "inotify (DEPRECATED)"
15951+ depends on INOTIFY
4a4d8108 15952+endchoice
1facf9fc 15953+
4a4d8108
AM
15954+config AUFS_EXPORT
15955+ bool "NFS-exportable aufs"
15956+ depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
15957+ help
15958+ If you want to export your mounted aufs via NFS, then enable this
15959+ option. There are several requirements for this configuration.
15960+ See detail in aufs.5.
1facf9fc 15961+
4a4d8108
AM
15962+config AUFS_INO_T_64
15963+ bool
15964+ depends on AUFS_EXPORT
15965+ depends on 64BIT && !(ALPHA || S390)
15966+ default y
15967+ help
15968+ Automatic configuration for internal use.
15969+ /* typedef unsigned long/int __kernel_ino_t */
15970+ /* alpha and s390x are int */
1facf9fc 15971+
4a4d8108
AM
15972+config AUFS_RDU
15973+ bool "Readdir in userspace"
15974+ help
15975+ Aufs has two methods to provide a merged view for a directory,
15976+ by a user-space library and by kernel-space natively. The latter
15977+ is always enabled but sometimes large and slow.
15978+ If you enable this option, install the library in aufs2-util
15979+ package, and set some environment variables for your readdir(3),
15980+ then the work will be handled in user-space which generally
15981+ shows better performance in most cases.
15982+ See detail in aufs.5.
1facf9fc 15983+
4a4d8108
AM
15984+config AUFS_SP_IATTR
15985+ bool "Respect the attributes (mtime/ctime mainly) of special files"
15986+ help
15987+ When you write something to a special file, some attributes of it
15988+ (mtime/ctime mainly) may be updated. Generally such updates are
15989+ less important (actually some device drivers and NFS ignore
15990+ it). But some applications (such like test program) requires
15991+ such updates. If you need these updates, then enable this
15992+ configuration which introduces some overhead.
15993+ Currently this configuration handles FIFO only.
1facf9fc 15994+
4a4d8108
AM
15995+config AUFS_SHWH
15996+ bool "Show whiteouts"
15997+ help
15998+ If you want to make the whiteouts in aufs visible, then enable
15999+ this option and specify 'shwh' mount option. Although it may
16000+ sounds like philosophy or something, but in technically it
16001+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 16002+
4a4d8108
AM
16003+config AUFS_BR_RAMFS
16004+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
16005+ help
16006+ If you want to use ramfs as an aufs branch fs, then enable this
16007+ option. Generally tmpfs is recommended.
16008+ Aufs prohibited them to be a branch fs by default, because
16009+ initramfs becomes unusable after switch_root or something
16010+ generally. If you sets initramfs as an aufs branch and boot your
16011+ system by switch_root, you will meet a problem easily since the
16012+ files in initramfs may be inaccessible.
16013+ Unless you are going to use ramfs as an aufs branch fs without
16014+ switch_root or something, leave it N.
1facf9fc 16015+
4a4d8108
AM
16016+config AUFS_BR_FUSE
16017+ bool "Fuse fs as an aufs branch"
16018+ depends on FUSE_FS
16019+ select AUFS_POLL
16020+ help
16021+ If you want to use fuse-based userspace filesystem as an aufs
16022+ branch fs, then enable this option.
16023+ It implements the internal poll(2) operation which is
16024+ implemented by fuse only (curretnly).
1facf9fc 16025+
4a4d8108
AM
16026+config AUFS_POLL
16027+ bool
16028+ help
16029+ Automatic configuration for internal use.
1facf9fc 16030+
4a4d8108
AM
16031+config AUFS_BR_HFSPLUS
16032+ bool "Hfsplus as an aufs branch"
16033+ depends on HFSPLUS_FS
16034+ default y
16035+ help
16036+ If you want to use hfsplus fs as an aufs branch fs, then enable
16037+ this option. This option introduces a small overhead at
16038+ copying-up a file on hfsplus.
1facf9fc 16039+
4a4d8108
AM
16040+config AUFS_BDEV_LOOP
16041+ bool
16042+ depends on BLK_DEV_LOOP
16043+ default y
16044+ help
16045+ Automatic configuration for internal use.
16046+ Convert =[ym] into =y.
1308ab2a 16047+
4a4d8108
AM
16048+config AUFS_DEBUG
16049+ bool "Debug aufs"
16050+ help
16051+ Enable this to compile aufs internal debug code.
16052+ It will have a negative impact to the performance.
16053+
16054+config AUFS_MAGIC_SYSRQ
16055+ bool
16056+ depends on AUFS_DEBUG && MAGIC_SYSRQ
16057+ default y
16058+ help
16059+ Automatic configuration for internal use.
16060+ When aufs supports Magic SysRq, enabled automatically.
16061+endif
e49829fe 16062--- /dev/null
0c5527e5 16063+++ linux-2.6/fs/aufs/loop.c 2010-10-25 14:20:44.000000000 +0200
b752ccd1 16064@@ -0,0 +1,63 @@
1facf9fc 16065+/*
4a4d8108 16066+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16067+ *
16068+ * This program, aufs is free software; you can redistribute it and/or modify
16069+ * it under the terms of the GNU General Public License as published by
16070+ * the Free Software Foundation; either version 2 of the License, or
16071+ * (at your option) any later version.
dece6358
AM
16072+ *
16073+ * This program is distributed in the hope that it will be useful,
16074+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16075+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16076+ * GNU General Public License for more details.
16077+ *
16078+ * You should have received a copy of the GNU General Public License
16079+ * along with this program; if not, write to the Free Software
16080+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16081+ */
16082+
16083+/*
16084+ * support for loopback block device as a branch
16085+ */
16086+
16087+#include <linux/loop.h>
16088+#include "aufs.h"
16089+
16090+/*
16091+ * test if two lower dentries have overlapping branches.
16092+ */
b752ccd1 16093+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 16094+{
b752ccd1 16095+ struct super_block *h_sb;
1facf9fc 16096+ struct loop_device *l;
16097+
b752ccd1
AM
16098+ h_sb = h_adding->d_sb;
16099+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 16100+ return 0;
16101+
b752ccd1
AM
16102+ l = h_sb->s_bdev->bd_disk->private_data;
16103+ h_adding = l->lo_backing_file->f_dentry;
16104+ /*
16105+ * h_adding can be local NFS.
16106+ * in this case aufs cannot detect the loop.
16107+ */
16108+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 16109+ return 1;
b752ccd1 16110+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 16111+}
16112+
16113+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
16114+int au_test_loopback_kthread(void)
16115+{
b752ccd1
AM
16116+ int ret;
16117+ struct task_struct *tsk = current;
16118+
16119+ ret = 0;
16120+ if (tsk->flags & PF_KTHREAD) {
16121+ const char c = tsk->comm[4];
16122+ ret = ('0' <= c && c <= '9'
16123+ && !strncmp(tsk->comm, "loop", 4));
16124+ }
1facf9fc 16125+
b752ccd1 16126+ return ret;
1facf9fc 16127+}
e49829fe 16128--- /dev/null
0c5527e5 16129+++ linux-2.6/fs/aufs/loop.h 2010-10-25 14:20:44.000000000 +0200
b752ccd1 16130@@ -0,0 +1,42 @@
1facf9fc 16131+/*
4a4d8108 16132+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16133+ *
16134+ * This program, aufs is free software; you can redistribute it and/or modify
16135+ * it under the terms of the GNU General Public License as published by
16136+ * the Free Software Foundation; either version 2 of the License, or
16137+ * (at your option) any later version.
dece6358
AM
16138+ *
16139+ * This program is distributed in the hope that it will be useful,
16140+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16141+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16142+ * GNU General Public License for more details.
16143+ *
16144+ * You should have received a copy of the GNU General Public License
16145+ * along with this program; if not, write to the Free Software
16146+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16147+ */
16148+
16149+/*
16150+ * support for loopback mount as a branch
16151+ */
16152+
16153+#ifndef __AUFS_LOOP_H__
16154+#define __AUFS_LOOP_H__
16155+
16156+#ifdef __KERNEL__
16157+
dece6358
AM
16158+struct dentry;
16159+struct super_block;
1facf9fc 16160+
16161+#ifdef CONFIG_AUFS_BDEV_LOOP
16162+/* loop.c */
b752ccd1 16163+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 16164+int au_test_loopback_kthread(void);
16165+#else
4a4d8108 16166+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 16167+ struct dentry *h_adding)
4a4d8108 16168+AuStubInt0(au_test_loopback_kthread, void)
1facf9fc 16169+#endif /* BLK_DEV_LOOP */
16170+
16171+#endif /* __KERNEL__ */
16172+#endif /* __AUFS_LOOP_H__ */
e49829fe 16173--- /dev/null
0c5527e5 16174+++ linux-2.6/fs/aufs/magic.mk 2010-10-25 14:20:44.000000000 +0200
4a4d8108 16175@@ -0,0 +1,54 @@
1facf9fc 16176+
16177+# defined in ${srctree}/fs/fuse/inode.c
16178+# tristate
16179+ifdef CONFIG_FUSE_FS
16180+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
16181+endif
16182+
16183+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
16184+# tristate
16185+ifdef CONFIG_OCFS2_FS
16186+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
16187+endif
16188+
16189+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
16190+# tristate
16191+ifdef CONFIG_OCFS2_FS_O2CB
16192+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
16193+endif
16194+
1facf9fc 16195+# defined in ${srctree}/fs/cifs/cifsfs.c
16196+# tristate
16197+ifdef CONFIG_CIFS_FS
16198+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
16199+endif
16200+
16201+# defined in ${srctree}/fs/xfs/xfs_sb.h
16202+# tristate
16203+ifdef CONFIG_XFS_FS
16204+ccflags-y += -DXFS_SB_MAGIC=0x58465342
16205+endif
16206+
16207+# defined in ${srctree}/fs/configfs/mount.c
16208+# tristate
16209+ifdef CONFIG_CONFIGFS_FS
16210+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
16211+endif
16212+
16213+# defined in ${srctree}/fs/9p/v9fs.h
16214+# tristate
16215+ifdef CONFIG_9P_FS
16216+ccflags-y += -DV9FS_MAGIC=0x01021997
16217+endif
16218+
16219+# defined in ${srctree}/fs/ubifs/ubifs.h
16220+# tristate
16221+ifdef CONFIG_UBIFS_FS
16222+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
16223+endif
4a4d8108
AM
16224+
16225+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
16226+# tristate
16227+ifdef CONFIG_HFSPLUS_FS
16228+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
16229+endif
e49829fe 16230--- /dev/null
0c5527e5 16231+++ linux-2.6/fs/aufs/Makefile 2010-10-25 14:20:44.000000000 +0200
e49829fe 16232@@ -0,0 +1,39 @@
4a4d8108
AM
16233+
16234+include ${src}/magic.mk
16235+ifeq (${CONFIG_AUFS_FS},m)
16236+include ${src}/conf.mk
16237+endif
16238+-include ${src}/priv_def.mk
16239+
16240+# cf. include/linux/kernel.h
16241+# enable pr_debug
16242+ccflags-y += -DDEBUG
16243+ccflags-y += -D'pr_fmt(fmt)="aufs %s:%d:%s[%d]: " fmt, \
16244+ __func__, __LINE__, current->comm, current->pid'
16245+
16246+obj-$(CONFIG_AUFS_FS) += aufs.o
16247+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
16248+ wkq.o vfsub.o dcsub.o \
e49829fe 16249+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
16250+ dinfo.o dentry.o \
16251+ dynop.o \
16252+ finfo.o file.o f_op.o \
16253+ dir.o vdir.o \
16254+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
16255+ ioctl.o
16256+
16257+# all are boolean
e49829fe 16258+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
16259+aufs-$(CONFIG_SYSFS) += sysfs.o
16260+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
16261+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
16262+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
16263+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
e49829fe 16264+aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
4a4d8108
AM
16265+aufs-$(CONFIG_AUFS_EXPORT) += export.o
16266+aufs-$(CONFIG_AUFS_POLL) += poll.o
16267+aufs-$(CONFIG_AUFS_RDU) += rdu.o
16268+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
16269+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
16270+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
16271+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
e49829fe 16272--- /dev/null
0c5527e5 16273+++ linux-2.6/fs/aufs/module.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 16274@@ -0,0 +1,182 @@
1facf9fc 16275+/*
4a4d8108 16276+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16277+ *
16278+ * This program, aufs is free software; you can redistribute it and/or modify
16279+ * it under the terms of the GNU General Public License as published by
16280+ * the Free Software Foundation; either version 2 of the License, or
16281+ * (at your option) any later version.
dece6358
AM
16282+ *
16283+ * This program is distributed in the hope that it will be useful,
16284+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16285+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16286+ * GNU General Public License for more details.
16287+ *
16288+ * You should have received a copy of the GNU General Public License
16289+ * along with this program; if not, write to the Free Software
16290+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16291+ */
16292+
16293+/*
16294+ * module global variables and operations
16295+ */
16296+
16297+#include <linux/module.h>
16298+#include <linux/seq_file.h>
16299+#include "aufs.h"
16300+
16301+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
16302+{
16303+ if (new_sz <= nused)
16304+ return p;
16305+
16306+ p = krealloc(p, new_sz, gfp);
16307+ if (p)
16308+ memset(p + nused, 0, new_sz - nused);
16309+ return p;
16310+}
16311+
16312+/* ---------------------------------------------------------------------- */
16313+
16314+/*
16315+ * aufs caches
16316+ */
16317+struct kmem_cache *au_cachep[AuCache_Last];
16318+static int __init au_cache_init(void)
16319+{
4a4d8108 16320+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 16321+ if (au_cachep[AuCache_DINFO])
4a4d8108
AM
16322+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
16323+ au_icntnr_init_once);
1facf9fc 16324+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
16325+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
16326+ au_fi_init_once);
1facf9fc 16327+ if (au_cachep[AuCache_FINFO])
16328+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
16329+ if (au_cachep[AuCache_VDIR])
16330+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
16331+ if (au_cachep[AuCache_DEHSTR])
16332+ return 0;
16333+
16334+ return -ENOMEM;
16335+}
16336+
16337+static void au_cache_fin(void)
16338+{
16339+ int i;
4a4d8108
AM
16340+
16341+ /* including AuCache_HNOTIFY */
1facf9fc 16342+ for (i = 0; i < AuCache_Last; i++)
16343+ if (au_cachep[i]) {
16344+ kmem_cache_destroy(au_cachep[i]);
16345+ au_cachep[i] = NULL;
16346+ }
16347+}
16348+
16349+/* ---------------------------------------------------------------------- */
16350+
16351+int au_dir_roflags;
16352+
e49829fe
JR
16353+#ifdef CONFIG_AUFS_SBILIST
16354+struct au_splhead au_sbilist;
16355+#endif
16356+
1facf9fc 16357+/*
16358+ * functions for module interface.
16359+ */
16360+MODULE_LICENSE("GPL");
16361+/* MODULE_LICENSE("GPL v2"); */
dece6358 16362+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 16363+MODULE_DESCRIPTION(AUFS_NAME
16364+ " -- Advanced multi layered unification filesystem");
16365+MODULE_VERSION(AUFS_VERSION);
16366+
1facf9fc 16367+/* this module parameter has no meaning when SYSFS is disabled */
16368+int sysaufs_brs = 1;
16369+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
16370+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
16371+
16372+/* ---------------------------------------------------------------------- */
16373+
16374+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
16375+
16376+int au_seq_path(struct seq_file *seq, struct path *path)
16377+{
16378+ return seq_path(seq, path, au_esc_chars);
16379+}
16380+
16381+/* ---------------------------------------------------------------------- */
16382+
16383+static int __init aufs_init(void)
16384+{
16385+ int err, i;
16386+ char *p;
16387+
16388+ p = au_esc_chars;
16389+ for (i = 1; i <= ' '; i++)
16390+ *p++ = i;
16391+ *p++ = '\\';
16392+ *p++ = '\x7f';
16393+ *p = 0;
16394+
16395+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
16396+
e49829fe 16397+ au_sbilist_init();
1facf9fc 16398+ sysaufs_brs_init();
16399+ au_debug_init();
4a4d8108 16400+ au_dy_init();
1facf9fc 16401+ err = sysaufs_init();
16402+ if (unlikely(err))
16403+ goto out;
e49829fe 16404+ err = au_procfs_init();
4f0767ce 16405+ if (unlikely(err))
953406b4 16406+ goto out_sysaufs;
e49829fe
JR
16407+ err = au_wkq_init();
16408+ if (unlikely(err))
16409+ goto out_procfs;
4a4d8108 16410+ err = au_hnotify_init();
1facf9fc 16411+ if (unlikely(err))
16412+ goto out_wkq;
16413+ err = au_sysrq_init();
16414+ if (unlikely(err))
16415+ goto out_hin;
16416+ err = au_cache_init();
16417+ if (unlikely(err))
16418+ goto out_sysrq;
16419+ err = register_filesystem(&aufs_fs_type);
16420+ if (unlikely(err))
16421+ goto out_cache;
4a4d8108
AM
16422+ /* since we define pr_fmt, call printk directly */
16423+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 16424+ goto out; /* success */
16425+
4f0767ce 16426+out_cache:
1facf9fc 16427+ au_cache_fin();
4f0767ce 16428+out_sysrq:
1facf9fc 16429+ au_sysrq_fin();
4f0767ce 16430+out_hin:
4a4d8108 16431+ au_hnotify_fin();
4f0767ce 16432+out_wkq:
1facf9fc 16433+ au_wkq_fin();
e49829fe
JR
16434+out_procfs:
16435+ au_procfs_fin();
4f0767ce 16436+out_sysaufs:
1facf9fc 16437+ sysaufs_fin();
4a4d8108 16438+ au_dy_fin();
4f0767ce 16439+out:
1facf9fc 16440+ return err;
16441+}
16442+
16443+static void __exit aufs_exit(void)
16444+{
16445+ unregister_filesystem(&aufs_fs_type);
16446+ au_cache_fin();
16447+ au_sysrq_fin();
4a4d8108 16448+ au_hnotify_fin();
1facf9fc 16449+ au_wkq_fin();
e49829fe 16450+ au_procfs_fin();
1facf9fc 16451+ sysaufs_fin();
4a4d8108 16452+ au_dy_fin();
1facf9fc 16453+}
16454+
16455+module_init(aufs_init);
16456+module_exit(aufs_exit);
e49829fe 16457--- /dev/null
0c5527e5 16458+++ linux-2.6/fs/aufs/module.h 2010-10-25 14:20:44.000000000 +0200
e49829fe 16459@@ -0,0 +1,91 @@
1facf9fc 16460+/*
4a4d8108 16461+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16462+ *
16463+ * This program, aufs is free software; you can redistribute it and/or modify
16464+ * it under the terms of the GNU General Public License as published by
16465+ * the Free Software Foundation; either version 2 of the License, or
16466+ * (at your option) any later version.
dece6358
AM
16467+ *
16468+ * This program is distributed in the hope that it will be useful,
16469+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16470+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16471+ * GNU General Public License for more details.
16472+ *
16473+ * You should have received a copy of the GNU General Public License
16474+ * along with this program; if not, write to the Free Software
16475+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16476+ */
16477+
16478+/*
16479+ * module initialization and module-global
16480+ */
16481+
16482+#ifndef __AUFS_MODULE_H__
16483+#define __AUFS_MODULE_H__
16484+
16485+#ifdef __KERNEL__
16486+
16487+#include <linux/slab.h>
16488+
dece6358
AM
16489+struct path;
16490+struct seq_file;
16491+
1facf9fc 16492+/* module parameters */
1facf9fc 16493+extern int sysaufs_brs;
16494+
16495+/* ---------------------------------------------------------------------- */
16496+
16497+extern int au_dir_roflags;
16498+
16499+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
16500+int au_seq_path(struct seq_file *seq, struct path *path);
16501+
e49829fe
JR
16502+#ifdef CONFIG_PROC_FS
16503+/* procfs.c */
16504+int __init au_procfs_init(void);
16505+void au_procfs_fin(void);
16506+#else
16507+AuStubInt0(au_procfs_init, void);
16508+AuStubVoid(au_procfs_fin, void);
16509+#endif
16510+
4f0767ce
JR
16511+/* ---------------------------------------------------------------------- */
16512+
16513+/* kmem cache */
1facf9fc 16514+enum {
16515+ AuCache_DINFO,
16516+ AuCache_ICNTNR,
16517+ AuCache_FINFO,
16518+ AuCache_VDIR,
16519+ AuCache_DEHSTR,
4a4d8108
AM
16520+#ifdef CONFIG_AUFS_HNOTIFY
16521+ AuCache_HNOTIFY,
1facf9fc 16522+#endif
16523+ AuCache_Last
16524+};
16525+
4a4d8108
AM
16526+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
16527+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
16528+#define AuCacheCtor(type, ctor) \
16529+ kmem_cache_create(#type, sizeof(struct type), \
16530+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 16531+
16532+extern struct kmem_cache *au_cachep[];
16533+
16534+#define AuCacheFuncs(name, index) \
4a4d8108 16535+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 16536+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 16537+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 16538+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
16539+
16540+AuCacheFuncs(dinfo, DINFO);
16541+AuCacheFuncs(icntnr, ICNTNR);
16542+AuCacheFuncs(finfo, FINFO);
16543+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
16544+AuCacheFuncs(vdir_dehstr, DEHSTR);
16545+#ifdef CONFIG_AUFS_HNOTIFY
16546+AuCacheFuncs(hnotify, HNOTIFY);
16547+#endif
1facf9fc 16548+
4a4d8108
AM
16549+#endif /* __KERNEL__ */
16550+#endif /* __AUFS_MODULE_H__ */
e49829fe 16551--- /dev/null
0c5527e5 16552+++ linux-2.6/fs/aufs/mtx.h 2010-10-25 14:20:44.000000000 +0200
4a4d8108
AM
16553@@ -0,0 +1,48 @@
16554+/*
16555+ * Copyright (C) 2010 Junjiro R. Okajima
16556+ *
16557+ * This program, aufs is free software; you can redistribute it and/or modify
16558+ * it under the terms of the GNU General Public License as published by
16559+ * the Free Software Foundation; either version 2 of the License, or
16560+ * (at your option) any later version.
16561+ *
16562+ * This program is distributed in the hope that it will be useful,
16563+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16564+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16565+ * GNU General Public License for more details.
16566+ *
16567+ * You should have received a copy of the GNU General Public License
16568+ * along with this program; if not, write to the Free Software
16569+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16570+ */
16571+
16572+/*
16573+ * very ugly approach for aufs_mmap()
16574+ * never include this file from other than f_op.c.
16575+ * see f_op.c in detail.
16576+ */
16577+
16578+#ifndef __AUFS_MTX_H__
16579+#define __AUFS_MTX_H__
16580+
16581+#ifdef __KERNEL__
16582+
16583+/* copied from ../kernel/mutex{,-debug}.h */
16584+struct mutex;
16585+struct thread_info;
16586+#ifdef CONFIG_DEBUG_MUTEXES
16587+static inline void mutex_set_owner(struct mutex *lock)
16588+{
16589+ lock->owner = current_thread_info();
16590+}
16591+#else
16592+static inline void mutex_set_owner(struct mutex *lock)
16593+{
16594+#ifdef CONFIG_SMP
16595+ lock->owner = current_thread_info();
16596+#endif
16597+}
16598+#endif
1facf9fc 16599+
16600+#endif /* __KERNEL__ */
4a4d8108 16601+#endif /* __AUFS_MTX_H__ */
e49829fe 16602--- /dev/null
0c5527e5 16603+++ linux-2.6/fs/aufs/opts.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 16604@@ -0,0 +1,1595 @@
1facf9fc 16605+/*
4a4d8108 16606+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 16607+ *
16608+ * This program, aufs is free software; you can redistribute it and/or modify
16609+ * it under the terms of the GNU General Public License as published by
16610+ * the Free Software Foundation; either version 2 of the License, or
16611+ * (at your option) any later version.
dece6358
AM
16612+ *
16613+ * This program is distributed in the hope that it will be useful,
16614+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16615+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16616+ * GNU General Public License for more details.
16617+ *
16618+ * You should have received a copy of the GNU General Public License
16619+ * along with this program; if not, write to the Free Software
16620+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16621+ */
16622+
16623+/*
16624+ * mount options/flags
16625+ */
16626+
dece6358 16627+#include <linux/file.h>
e49829fe 16628+#include <linux/jiffies.h>
dece6358 16629+#include <linux/namei.h>
1facf9fc 16630+#include <linux/types.h> /* a distribution requires */
16631+#include <linux/parser.h>
16632+#include "aufs.h"
16633+
16634+/* ---------------------------------------------------------------------- */
16635+
16636+enum {
16637+ Opt_br,
16638+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
16639+ Opt_idel, Opt_imod, Opt_ireorder,
16640+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 16641+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 16642+ Opt_xino, Opt_zxino, Opt_noxino,
16643+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
16644+ Opt_trunc_xino_path, Opt_itrunc_xino,
16645+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 16646+ Opt_shwh, Opt_noshwh,
1facf9fc 16647+ Opt_plink, Opt_noplink, Opt_list_plink,
16648+ Opt_udba,
4a4d8108 16649+ Opt_dio, Opt_nodio,
1facf9fc 16650+ /* Opt_lock, Opt_unlock, */
16651+ Opt_cmd, Opt_cmd_args,
16652+ Opt_diropq_a, Opt_diropq_w,
16653+ Opt_warn_perm, Opt_nowarn_perm,
16654+ Opt_wbr_copyup, Opt_wbr_create,
16655+ Opt_refrof, Opt_norefrof,
16656+ Opt_verbose, Opt_noverbose,
16657+ Opt_sum, Opt_nosum, Opt_wsum,
16658+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
16659+};
16660+
16661+static match_table_t options = {
16662+ {Opt_br, "br=%s"},
16663+ {Opt_br, "br:%s"},
16664+
16665+ {Opt_add, "add=%d:%s"},
16666+ {Opt_add, "add:%d:%s"},
16667+ {Opt_add, "ins=%d:%s"},
16668+ {Opt_add, "ins:%d:%s"},
16669+ {Opt_append, "append=%s"},
16670+ {Opt_append, "append:%s"},
16671+ {Opt_prepend, "prepend=%s"},
16672+ {Opt_prepend, "prepend:%s"},
16673+
16674+ {Opt_del, "del=%s"},
16675+ {Opt_del, "del:%s"},
16676+ /* {Opt_idel, "idel:%d"}, */
16677+ {Opt_mod, "mod=%s"},
16678+ {Opt_mod, "mod:%s"},
16679+ /* {Opt_imod, "imod:%d:%s"}, */
16680+
16681+ {Opt_dirwh, "dirwh=%d"},
16682+
16683+ {Opt_xino, "xino=%s"},
16684+ {Opt_noxino, "noxino"},
16685+ {Opt_trunc_xino, "trunc_xino"},
16686+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
16687+ {Opt_notrunc_xino, "notrunc_xino"},
16688+ {Opt_trunc_xino_path, "trunc_xino=%s"},
16689+ {Opt_itrunc_xino, "itrunc_xino=%d"},
16690+ /* {Opt_zxino, "zxino=%s"}, */
16691+ {Opt_trunc_xib, "trunc_xib"},
16692+ {Opt_notrunc_xib, "notrunc_xib"},
16693+
e49829fe 16694+#ifdef CONFIG_PROC_FS
1facf9fc 16695+ {Opt_plink, "plink"},
e49829fe
JR
16696+#else
16697+ {Opt_ignore_silent, "plink"},
16698+#endif
16699+
1facf9fc 16700+ {Opt_noplink, "noplink"},
e49829fe 16701+
1facf9fc 16702+#ifdef CONFIG_AUFS_DEBUG
16703+ {Opt_list_plink, "list_plink"},
16704+#endif
16705+
16706+ {Opt_udba, "udba=%s"},
16707+
4a4d8108
AM
16708+ {Opt_dio, "dio"},
16709+ {Opt_nodio, "nodio"},
16710+
1facf9fc 16711+ {Opt_diropq_a, "diropq=always"},
16712+ {Opt_diropq_a, "diropq=a"},
16713+ {Opt_diropq_w, "diropq=whiteouted"},
16714+ {Opt_diropq_w, "diropq=w"},
16715+
16716+ {Opt_warn_perm, "warn_perm"},
16717+ {Opt_nowarn_perm, "nowarn_perm"},
16718+
16719+ /* keep them temporary */
16720+ {Opt_ignore_silent, "coo=%s"},
16721+ {Opt_ignore_silent, "nodlgt"},
16722+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 16723+ {Opt_ignore_silent, "clean_plink"},
16724+
dece6358
AM
16725+#ifdef CONFIG_AUFS_SHWH
16726+ {Opt_shwh, "shwh"},
16727+#endif
16728+ {Opt_noshwh, "noshwh"},
16729+
1facf9fc 16730+ {Opt_rendir, "rendir=%d"},
16731+
16732+ {Opt_refrof, "refrof"},
16733+ {Opt_norefrof, "norefrof"},
16734+
16735+ {Opt_verbose, "verbose"},
16736+ {Opt_verbose, "v"},
16737+ {Opt_noverbose, "noverbose"},
16738+ {Opt_noverbose, "quiet"},
16739+ {Opt_noverbose, "q"},
16740+ {Opt_noverbose, "silent"},
16741+
16742+ {Opt_sum, "sum"},
16743+ {Opt_nosum, "nosum"},
16744+ {Opt_wsum, "wsum"},
16745+
16746+ {Opt_rdcache, "rdcache=%d"},
16747+ {Opt_rdblk, "rdblk=%d"},
dece6358 16748+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 16749+ {Opt_rdhash, "rdhash=%d"},
dece6358 16750+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 16751+
16752+ {Opt_wbr_create, "create=%s"},
16753+ {Opt_wbr_create, "create_policy=%s"},
16754+ {Opt_wbr_copyup, "cpup=%s"},
16755+ {Opt_wbr_copyup, "copyup=%s"},
16756+ {Opt_wbr_copyup, "copyup_policy=%s"},
16757+
16758+ /* internal use for the scripts */
16759+ {Opt_ignore_silent, "si=%s"},
16760+
16761+ {Opt_br, "dirs=%s"},
16762+ {Opt_ignore, "debug=%d"},
16763+ {Opt_ignore, "delete=whiteout"},
16764+ {Opt_ignore, "delete=all"},
16765+ {Opt_ignore, "imap=%s"},
16766+
1308ab2a 16767+ /* temporary workaround, due to old mount(8)? */
16768+ {Opt_ignore_silent, "relatime"},
16769+
1facf9fc 16770+ {Opt_err, NULL}
16771+};
16772+
16773+/* ---------------------------------------------------------------------- */
16774+
16775+static const char *au_parser_pattern(int val, struct match_token *token)
16776+{
16777+ while (token->pattern) {
16778+ if (token->token == val)
16779+ return token->pattern;
16780+ token++;
16781+ }
16782+ BUG();
16783+ return "??";
16784+}
16785+
16786+/* ---------------------------------------------------------------------- */
16787+
16788+static match_table_t brperms = {
16789+ {AuBrPerm_RO, AUFS_BRPERM_RO},
16790+ {AuBrPerm_RR, AUFS_BRPERM_RR},
16791+ {AuBrPerm_RW, AUFS_BRPERM_RW},
16792+
16793+ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
16794+ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
16795+ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
16796+
16797+ {AuBrPerm_ROWH, "nfsro"},
16798+ {AuBrPerm_RO, NULL}
16799+};
16800+
4a4d8108 16801+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 16802+{
16803+ int val;
16804+ substring_t args[MAX_OPT_ARGS];
16805+
16806+ val = match_token(perm, brperms, args);
16807+ return val;
16808+}
16809+
16810+const char *au_optstr_br_perm(int brperm)
16811+{
16812+ return au_parser_pattern(brperm, (void *)brperms);
16813+}
16814+
16815+/* ---------------------------------------------------------------------- */
16816+
16817+static match_table_t udbalevel = {
16818+ {AuOpt_UDBA_REVAL, "reval"},
16819+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
16820+#ifdef CONFIG_AUFS_HNOTIFY
16821+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
16822+#ifdef CONFIG_AUFS_HFSNOTIFY
16823+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
e49829fe
JR
16824+#else
16825+ {AuOpt_UDBA_HNOTIFY, "inotify"},
4a4d8108 16826+#endif
1facf9fc 16827+#endif
16828+ {-1, NULL}
16829+};
16830+
e49829fe
JR
16831+static void au_warn_inotify(int val, char *str)
16832+{
16833+#ifdef CONFIG_AUFS_HINOTIFY
16834+ if (val == AuOpt_UDBA_HNOTIFY
16835+ && !strcmp(str, "inotify"))
16836+ AuWarn1("udba=inotify is deprecated, use udba=notify\n");
16837+#endif
16838+}
16839+
4a4d8108 16840+static int noinline_for_stack udba_val(char *str)
1facf9fc 16841+{
e49829fe 16842+ int val;
1facf9fc 16843+ substring_t args[MAX_OPT_ARGS];
16844+
e49829fe
JR
16845+ val = match_token(str, udbalevel, args);
16846+ au_warn_inotify(val, str);
16847+ return val;
1facf9fc 16848+}
16849+
16850+const char *au_optstr_udba(int udba)
16851+{
16852+ return au_parser_pattern(udba, (void *)udbalevel);
16853+}
16854+
16855+/* ---------------------------------------------------------------------- */
16856+
16857+static match_table_t au_wbr_create_policy = {
16858+ {AuWbrCreate_TDP, "tdp"},
16859+ {AuWbrCreate_TDP, "top-down-parent"},
16860+ {AuWbrCreate_RR, "rr"},
16861+ {AuWbrCreate_RR, "round-robin"},
16862+ {AuWbrCreate_MFS, "mfs"},
16863+ {AuWbrCreate_MFS, "most-free-space"},
16864+ {AuWbrCreate_MFSV, "mfs:%d"},
16865+ {AuWbrCreate_MFSV, "most-free-space:%d"},
16866+
16867+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
16868+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
16869+ {AuWbrCreate_PMFS, "pmfs"},
16870+ {AuWbrCreate_PMFSV, "pmfs:%d"},
16871+
16872+ {-1, NULL}
16873+};
16874+
dece6358
AM
16875+/*
16876+ * cf. linux/lib/parser.c and cmdline.c
16877+ * gave up calling memparse() since it uses simple_strtoull() instead of
16878+ * strict_...().
16879+ */
4a4d8108
AM
16880+static int noinline_for_stack
16881+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 16882+{
16883+ int err;
16884+ unsigned int len;
16885+ char a[32];
16886+
16887+ err = -ERANGE;
16888+ len = s->to - s->from;
16889+ if (len + 1 <= sizeof(a)) {
16890+ memcpy(a, s->from, len);
16891+ a[len] = '\0';
16892+ err = strict_strtoull(a, 0, result);
16893+ }
16894+ return err;
16895+}
16896+
16897+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
16898+ struct au_opt_wbr_create *create)
16899+{
16900+ int err;
16901+ unsigned long long ull;
16902+
16903+ err = 0;
16904+ if (!au_match_ull(arg, &ull))
16905+ create->mfsrr_watermark = ull;
16906+ else {
4a4d8108 16907+ pr_err("bad integer in %s\n", str);
1facf9fc 16908+ err = -EINVAL;
16909+ }
16910+
16911+ return err;
16912+}
16913+
16914+static int au_wbr_mfs_sec(substring_t *arg, char *str,
16915+ struct au_opt_wbr_create *create)
16916+{
16917+ int n, err;
16918+
16919+ err = 0;
e49829fe 16920+ if (!match_int(arg, &n) && 0 <= n && n <= MAX_SEC_IN_JIFFIES)
1facf9fc 16921+ create->mfs_second = n;
16922+ else {
4a4d8108 16923+ pr_err("bad integer in %s\n", str);
1facf9fc 16924+ err = -EINVAL;
16925+ }
16926+
16927+ return err;
16928+}
16929+
4a4d8108
AM
16930+static int noinline_for_stack
16931+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 16932+{
16933+ int err, e;
16934+ substring_t args[MAX_OPT_ARGS];
16935+
16936+ err = match_token(str, au_wbr_create_policy, args);
16937+ create->wbr_create = err;
16938+ switch (err) {
16939+ case AuWbrCreate_MFSRRV:
16940+ e = au_wbr_mfs_wmark(&args[0], str, create);
16941+ if (!e)
16942+ e = au_wbr_mfs_sec(&args[1], str, create);
16943+ if (unlikely(e))
16944+ err = e;
16945+ break;
16946+ case AuWbrCreate_MFSRR:
16947+ e = au_wbr_mfs_wmark(&args[0], str, create);
16948+ if (unlikely(e)) {
16949+ err = e;
16950+ break;
16951+ }
16952+ /*FALLTHROUGH*/
16953+ case AuWbrCreate_MFS:
16954+ case AuWbrCreate_PMFS:
16955+ create->mfs_second = AUFS_MFS_SECOND_DEF;
16956+ break;
16957+ case AuWbrCreate_MFSV:
16958+ case AuWbrCreate_PMFSV:
16959+ e = au_wbr_mfs_sec(&args[0], str, create);
16960+ if (unlikely(e))
16961+ err = e;
16962+ break;
16963+ }
16964+
16965+ return err;
16966+}
16967+
16968+const char *au_optstr_wbr_create(int wbr_create)
16969+{
16970+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
16971+}
16972+
16973+static match_table_t au_wbr_copyup_policy = {
16974+ {AuWbrCopyup_TDP, "tdp"},
16975+ {AuWbrCopyup_TDP, "top-down-parent"},
16976+ {AuWbrCopyup_BUP, "bup"},
16977+ {AuWbrCopyup_BUP, "bottom-up-parent"},
16978+ {AuWbrCopyup_BU, "bu"},
16979+ {AuWbrCopyup_BU, "bottom-up"},
16980+ {-1, NULL}
16981+};
16982+
4a4d8108 16983+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 16984+{
16985+ substring_t args[MAX_OPT_ARGS];
16986+
16987+ return match_token(str, au_wbr_copyup_policy, args);
16988+}
16989+
16990+const char *au_optstr_wbr_copyup(int wbr_copyup)
16991+{
16992+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
16993+}
16994+
16995+/* ---------------------------------------------------------------------- */
16996+
16997+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
16998+
16999+static void dump_opts(struct au_opts *opts)
17000+{
17001+#ifdef CONFIG_AUFS_DEBUG
17002+ /* reduce stack space */
17003+ union {
17004+ struct au_opt_add *add;
17005+ struct au_opt_del *del;
17006+ struct au_opt_mod *mod;
17007+ struct au_opt_xino *xino;
17008+ struct au_opt_xino_itrunc *xino_itrunc;
17009+ struct au_opt_wbr_create *create;
17010+ } u;
17011+ struct au_opt *opt;
17012+
17013+ opt = opts->opt;
17014+ while (opt->type != Opt_tail) {
17015+ switch (opt->type) {
17016+ case Opt_add:
17017+ u.add = &opt->add;
17018+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
17019+ u.add->bindex, u.add->pathname, u.add->perm,
17020+ u.add->path.dentry);
17021+ break;
17022+ case Opt_del:
17023+ case Opt_idel:
17024+ u.del = &opt->del;
17025+ AuDbg("del {%s, %p}\n",
17026+ u.del->pathname, u.del->h_path.dentry);
17027+ break;
17028+ case Opt_mod:
17029+ case Opt_imod:
17030+ u.mod = &opt->mod;
17031+ AuDbg("mod {%s, 0x%x, %p}\n",
17032+ u.mod->path, u.mod->perm, u.mod->h_root);
17033+ break;
17034+ case Opt_append:
17035+ u.add = &opt->add;
17036+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
17037+ u.add->bindex, u.add->pathname, u.add->perm,
17038+ u.add->path.dentry);
17039+ break;
17040+ case Opt_prepend:
17041+ u.add = &opt->add;
17042+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
17043+ u.add->bindex, u.add->pathname, u.add->perm,
17044+ u.add->path.dentry);
17045+ break;
17046+ case Opt_dirwh:
17047+ AuDbg("dirwh %d\n", opt->dirwh);
17048+ break;
17049+ case Opt_rdcache:
17050+ AuDbg("rdcache %d\n", opt->rdcache);
17051+ break;
17052+ case Opt_rdblk:
17053+ AuDbg("rdblk %u\n", opt->rdblk);
17054+ break;
dece6358
AM
17055+ case Opt_rdblk_def:
17056+ AuDbg("rdblk_def\n");
17057+ break;
1facf9fc 17058+ case Opt_rdhash:
17059+ AuDbg("rdhash %u\n", opt->rdhash);
17060+ break;
dece6358
AM
17061+ case Opt_rdhash_def:
17062+ AuDbg("rdhash_def\n");
17063+ break;
1facf9fc 17064+ case Opt_xino:
17065+ u.xino = &opt->xino;
17066+ AuDbg("xino {%s %.*s}\n",
17067+ u.xino->path,
17068+ AuDLNPair(u.xino->file->f_dentry));
17069+ break;
17070+ case Opt_trunc_xino:
17071+ AuLabel(trunc_xino);
17072+ break;
17073+ case Opt_notrunc_xino:
17074+ AuLabel(notrunc_xino);
17075+ break;
17076+ case Opt_trunc_xino_path:
17077+ case Opt_itrunc_xino:
17078+ u.xino_itrunc = &opt->xino_itrunc;
17079+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
17080+ break;
17081+
17082+ case Opt_noxino:
17083+ AuLabel(noxino);
17084+ break;
17085+ case Opt_trunc_xib:
17086+ AuLabel(trunc_xib);
17087+ break;
17088+ case Opt_notrunc_xib:
17089+ AuLabel(notrunc_xib);
17090+ break;
dece6358
AM
17091+ case Opt_shwh:
17092+ AuLabel(shwh);
17093+ break;
17094+ case Opt_noshwh:
17095+ AuLabel(noshwh);
17096+ break;
1facf9fc 17097+ case Opt_plink:
17098+ AuLabel(plink);
17099+ break;
17100+ case Opt_noplink:
17101+ AuLabel(noplink);
17102+ break;
17103+ case Opt_list_plink:
17104+ AuLabel(list_plink);
17105+ break;
17106+ case Opt_udba:
17107+ AuDbg("udba %d, %s\n",
17108+ opt->udba, au_optstr_udba(opt->udba));
17109+ break;
4a4d8108
AM
17110+ case Opt_dio:
17111+ AuLabel(dio);
17112+ break;
17113+ case Opt_nodio:
17114+ AuLabel(nodio);
17115+ break;
1facf9fc 17116+ case Opt_diropq_a:
17117+ AuLabel(diropq_a);
17118+ break;
17119+ case Opt_diropq_w:
17120+ AuLabel(diropq_w);
17121+ break;
17122+ case Opt_warn_perm:
17123+ AuLabel(warn_perm);
17124+ break;
17125+ case Opt_nowarn_perm:
17126+ AuLabel(nowarn_perm);
17127+ break;
17128+ case Opt_refrof:
17129+ AuLabel(refrof);
17130+ break;
17131+ case Opt_norefrof:
17132+ AuLabel(norefrof);
17133+ break;
17134+ case Opt_verbose:
17135+ AuLabel(verbose);
17136+ break;
17137+ case Opt_noverbose:
17138+ AuLabel(noverbose);
17139+ break;
17140+ case Opt_sum:
17141+ AuLabel(sum);
17142+ break;
17143+ case Opt_nosum:
17144+ AuLabel(nosum);
17145+ break;
17146+ case Opt_wsum:
17147+ AuLabel(wsum);
17148+ break;
17149+ case Opt_wbr_create:
17150+ u.create = &opt->wbr_create;
17151+ AuDbg("create %d, %s\n", u.create->wbr_create,
17152+ au_optstr_wbr_create(u.create->wbr_create));
17153+ switch (u.create->wbr_create) {
17154+ case AuWbrCreate_MFSV:
17155+ case AuWbrCreate_PMFSV:
17156+ AuDbg("%d sec\n", u.create->mfs_second);
17157+ break;
17158+ case AuWbrCreate_MFSRR:
17159+ AuDbg("%llu watermark\n",
17160+ u.create->mfsrr_watermark);
17161+ break;
17162+ case AuWbrCreate_MFSRRV:
17163+ AuDbg("%llu watermark, %d sec\n",
17164+ u.create->mfsrr_watermark,
17165+ u.create->mfs_second);
17166+ break;
17167+ }
17168+ break;
17169+ case Opt_wbr_copyup:
17170+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
17171+ au_optstr_wbr_copyup(opt->wbr_copyup));
17172+ break;
17173+ default:
17174+ BUG();
17175+ }
17176+ opt++;
17177+ }
17178+#endif
17179+}
17180+
17181+void au_opts_free(struct au_opts *opts)
17182+{
17183+ struct au_opt *opt;
17184+
17185+ opt = opts->opt;
17186+ while (opt->type != Opt_tail) {
17187+ switch (opt->type) {
17188+ case Opt_add:
17189+ case Opt_append:
17190+ case Opt_prepend:
17191+ path_put(&opt->add.path);
17192+ break;
17193+ case Opt_del:
17194+ case Opt_idel:
17195+ path_put(&opt->del.h_path);
17196+ break;
17197+ case Opt_mod:
17198+ case Opt_imod:
17199+ dput(opt->mod.h_root);
17200+ break;
17201+ case Opt_xino:
17202+ fput(opt->xino.file);
17203+ break;
17204+ }
17205+ opt++;
17206+ }
17207+}
17208+
17209+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
17210+ aufs_bindex_t bindex)
17211+{
17212+ int err;
17213+ struct au_opt_add *add = &opt->add;
17214+ char *p;
17215+
17216+ add->bindex = bindex;
17217+ add->perm = AuBrPerm_Last;
17218+ add->pathname = opt_str;
17219+ p = strchr(opt_str, '=');
17220+ if (p) {
17221+ *p++ = 0;
17222+ if (*p)
17223+ add->perm = br_perm_val(p);
17224+ }
17225+
17226+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
17227+ if (!err) {
17228+ if (!p) {
17229+ add->perm = AuBrPerm_RO;
17230+ if (au_test_fs_rr(add->path.dentry->d_sb))
17231+ add->perm = AuBrPerm_RR;
17232+ else if (!bindex && !(sb_flags & MS_RDONLY))
17233+ add->perm = AuBrPerm_RW;
17234+ }
17235+ opt->type = Opt_add;
17236+ goto out;
17237+ }
4a4d8108 17238+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 17239+ err = -EINVAL;
17240+
4f0767ce 17241+out:
1facf9fc 17242+ return err;
17243+}
17244+
17245+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
17246+{
17247+ int err;
17248+
17249+ del->pathname = args[0].from;
17250+ AuDbg("del path %s\n", del->pathname);
17251+
17252+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
17253+ if (unlikely(err))
4a4d8108 17254+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 17255+
17256+ return err;
17257+}
17258+
17259+#if 0 /* reserved for future use */
17260+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
17261+ struct au_opt_del *del, substring_t args[])
17262+{
17263+ int err;
17264+ struct dentry *root;
17265+
17266+ err = -EINVAL;
17267+ root = sb->s_root;
17268+ aufs_read_lock(root, AuLock_FLUSH);
17269+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17270+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17271+ goto out;
17272+ }
17273+
17274+ err = 0;
17275+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
17276+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
17277+
4f0767ce 17278+out:
1facf9fc 17279+ aufs_read_unlock(root, !AuLock_IR);
17280+ return err;
17281+}
17282+#endif
17283+
4a4d8108
AM
17284+static int noinline_for_stack
17285+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 17286+{
17287+ int err;
17288+ struct path path;
17289+ char *p;
17290+
17291+ err = -EINVAL;
17292+ mod->path = args[0].from;
17293+ p = strchr(mod->path, '=');
17294+ if (unlikely(!p)) {
4a4d8108 17295+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 17296+ goto out;
17297+ }
17298+
17299+ *p++ = 0;
17300+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
17301+ if (unlikely(err)) {
4a4d8108 17302+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 17303+ goto out;
17304+ }
17305+
17306+ mod->perm = br_perm_val(p);
17307+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
17308+ mod->h_root = dget(path.dentry);
17309+ path_put(&path);
17310+
4f0767ce 17311+out:
1facf9fc 17312+ return err;
17313+}
17314+
17315+#if 0 /* reserved for future use */
17316+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
17317+ struct au_opt_mod *mod, substring_t args[])
17318+{
17319+ int err;
17320+ struct dentry *root;
17321+
17322+ err = -EINVAL;
17323+ root = sb->s_root;
17324+ aufs_read_lock(root, AuLock_FLUSH);
17325+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 17326+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 17327+ goto out;
17328+ }
17329+
17330+ err = 0;
17331+ mod->perm = br_perm_val(args[1].from);
17332+ AuDbg("mod path %s, perm 0x%x, %s\n",
17333+ mod->path, mod->perm, args[1].from);
17334+ mod->h_root = dget(au_h_dptr(root, bindex));
17335+
4f0767ce 17336+out:
1facf9fc 17337+ aufs_read_unlock(root, !AuLock_IR);
17338+ return err;
17339+}
17340+#endif
17341+
17342+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
17343+ substring_t args[])
17344+{
17345+ int err;
17346+ struct file *file;
17347+
17348+ file = au_xino_create(sb, args[0].from, /*silent*/0);
17349+ err = PTR_ERR(file);
17350+ if (IS_ERR(file))
17351+ goto out;
17352+
17353+ err = -EINVAL;
17354+ if (unlikely(file->f_dentry->d_sb == sb)) {
17355+ fput(file);
4a4d8108 17356+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 17357+ goto out;
17358+ }
17359+
17360+ err = 0;
17361+ xino->file = file;
17362+ xino->path = args[0].from;
17363+
4f0767ce 17364+out:
1facf9fc 17365+ return err;
17366+}
17367+
4a4d8108
AM
17368+static int noinline_for_stack
17369+au_opts_parse_xino_itrunc_path(struct super_block *sb,
17370+ struct au_opt_xino_itrunc *xino_itrunc,
17371+ substring_t args[])
1facf9fc 17372+{
17373+ int err;
17374+ aufs_bindex_t bend, bindex;
17375+ struct path path;
17376+ struct dentry *root;
17377+
17378+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
17379+ if (unlikely(err)) {
4a4d8108 17380+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 17381+ goto out;
17382+ }
17383+
17384+ xino_itrunc->bindex = -1;
17385+ root = sb->s_root;
17386+ aufs_read_lock(root, AuLock_FLUSH);
17387+ bend = au_sbend(sb);
17388+ for (bindex = 0; bindex <= bend; bindex++) {
17389+ if (au_h_dptr(root, bindex) == path.dentry) {
17390+ xino_itrunc->bindex = bindex;
17391+ break;
17392+ }
17393+ }
17394+ aufs_read_unlock(root, !AuLock_IR);
17395+ path_put(&path);
17396+
17397+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 17398+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 17399+ err = -EINVAL;
17400+ }
17401+
4f0767ce 17402+out:
1facf9fc 17403+ return err;
17404+}
17405+
17406+/* called without aufs lock */
17407+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
17408+{
17409+ int err, n, token;
17410+ aufs_bindex_t bindex;
17411+ unsigned char skipped;
17412+ struct dentry *root;
17413+ struct au_opt *opt, *opt_tail;
17414+ char *opt_str;
17415+ /* reduce the stack space */
17416+ union {
17417+ struct au_opt_xino_itrunc *xino_itrunc;
17418+ struct au_opt_wbr_create *create;
17419+ } u;
17420+ struct {
17421+ substring_t args[MAX_OPT_ARGS];
17422+ } *a;
17423+
17424+ err = -ENOMEM;
17425+ a = kmalloc(sizeof(*a), GFP_NOFS);
17426+ if (unlikely(!a))
17427+ goto out;
17428+
17429+ root = sb->s_root;
17430+ err = 0;
17431+ bindex = 0;
17432+ opt = opts->opt;
17433+ opt_tail = opt + opts->max_opt - 1;
17434+ opt->type = Opt_tail;
17435+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
17436+ err = -EINVAL;
17437+ skipped = 0;
17438+ token = match_token(opt_str, options, a->args);
17439+ switch (token) {
17440+ case Opt_br:
17441+ err = 0;
17442+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
17443+ && *opt_str) {
17444+ err = opt_add(opt, opt_str, opts->sb_flags,
17445+ bindex++);
17446+ if (unlikely(!err && ++opt > opt_tail)) {
17447+ err = -E2BIG;
17448+ break;
17449+ }
17450+ opt->type = Opt_tail;
17451+ skipped = 1;
17452+ }
17453+ break;
17454+ case Opt_add:
17455+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17456+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17457+ break;
17458+ }
17459+ bindex = n;
17460+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
17461+ bindex);
17462+ if (!err)
17463+ opt->type = token;
17464+ break;
17465+ case Opt_append:
17466+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17467+ /*dummy bindex*/1);
17468+ if (!err)
17469+ opt->type = token;
17470+ break;
17471+ case Opt_prepend:
17472+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
17473+ /*bindex*/0);
17474+ if (!err)
17475+ opt->type = token;
17476+ break;
17477+ case Opt_del:
17478+ err = au_opts_parse_del(&opt->del, a->args);
17479+ if (!err)
17480+ opt->type = token;
17481+ break;
17482+#if 0 /* reserved for future use */
17483+ case Opt_idel:
17484+ del->pathname = "(indexed)";
17485+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 17486+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17487+ break;
17488+ }
17489+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
17490+ if (!err)
17491+ opt->type = token;
17492+ break;
17493+#endif
17494+ case Opt_mod:
17495+ err = au_opts_parse_mod(&opt->mod, a->args);
17496+ if (!err)
17497+ opt->type = token;
17498+ break;
17499+#ifdef IMOD /* reserved for future use */
17500+ case Opt_imod:
17501+ u.mod->path = "(indexed)";
17502+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17503+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17504+ break;
17505+ }
17506+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
17507+ if (!err)
17508+ opt->type = token;
17509+ break;
17510+#endif
17511+ case Opt_xino:
17512+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
17513+ if (!err)
17514+ opt->type = token;
17515+ break;
17516+
17517+ case Opt_trunc_xino_path:
17518+ err = au_opts_parse_xino_itrunc_path
17519+ (sb, &opt->xino_itrunc, a->args);
17520+ if (!err)
17521+ opt->type = token;
17522+ break;
17523+
17524+ case Opt_itrunc_xino:
17525+ u.xino_itrunc = &opt->xino_itrunc;
17526+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 17527+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17528+ break;
17529+ }
17530+ u.xino_itrunc->bindex = n;
17531+ aufs_read_lock(root, AuLock_FLUSH);
17532+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 17533+ pr_err("out of bounds, %d\n", n);
1facf9fc 17534+ aufs_read_unlock(root, !AuLock_IR);
17535+ break;
17536+ }
17537+ aufs_read_unlock(root, !AuLock_IR);
17538+ err = 0;
17539+ opt->type = token;
17540+ break;
17541+
17542+ case Opt_dirwh:
17543+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
17544+ break;
17545+ err = 0;
17546+ opt->type = token;
17547+ break;
17548+
17549+ case Opt_rdcache:
e49829fe
JR
17550+ if (unlikely(match_int(&a->args[0], &opt->rdcache)
17551+ || opt->rdcache > MAX_SEC_IN_JIFFIES))
1facf9fc 17552+ break;
17553+ err = 0;
17554+ opt->type = token;
17555+ break;
17556+ case Opt_rdblk:
17557+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17558+ || n < 0
1facf9fc 17559+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 17560+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17561+ break;
17562+ }
1308ab2a 17563+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
17564+ pr_err("rdblk must be larger than %d\n",
17565+ NAME_MAX);
1facf9fc 17566+ break;
17567+ }
17568+ opt->rdblk = n;
17569+ err = 0;
17570+ opt->type = token;
17571+ break;
17572+ case Opt_rdhash:
17573+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 17574+ || n < 0
1facf9fc 17575+ || n * sizeof(struct hlist_head)
17576+ > KMALLOC_MAX_SIZE)) {
4a4d8108 17577+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 17578+ break;
17579+ }
17580+ opt->rdhash = n;
17581+ err = 0;
17582+ opt->type = token;
17583+ break;
17584+
17585+ case Opt_trunc_xino:
17586+ case Opt_notrunc_xino:
17587+ case Opt_noxino:
17588+ case Opt_trunc_xib:
17589+ case Opt_notrunc_xib:
dece6358
AM
17590+ case Opt_shwh:
17591+ case Opt_noshwh:
1facf9fc 17592+ case Opt_plink:
17593+ case Opt_noplink:
17594+ case Opt_list_plink:
4a4d8108
AM
17595+ case Opt_dio:
17596+ case Opt_nodio:
1facf9fc 17597+ case Opt_diropq_a:
17598+ case Opt_diropq_w:
17599+ case Opt_warn_perm:
17600+ case Opt_nowarn_perm:
17601+ case Opt_refrof:
17602+ case Opt_norefrof:
17603+ case Opt_verbose:
17604+ case Opt_noverbose:
17605+ case Opt_sum:
17606+ case Opt_nosum:
17607+ case Opt_wsum:
dece6358
AM
17608+ case Opt_rdblk_def:
17609+ case Opt_rdhash_def:
1facf9fc 17610+ err = 0;
17611+ opt->type = token;
17612+ break;
17613+
17614+ case Opt_udba:
17615+ opt->udba = udba_val(a->args[0].from);
17616+ if (opt->udba >= 0) {
17617+ err = 0;
17618+ opt->type = token;
17619+ } else
4a4d8108 17620+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17621+ break;
17622+
17623+ case Opt_wbr_create:
17624+ u.create = &opt->wbr_create;
17625+ u.create->wbr_create
17626+ = au_wbr_create_val(a->args[0].from, u.create);
17627+ if (u.create->wbr_create >= 0) {
17628+ err = 0;
17629+ opt->type = token;
17630+ } else
4a4d8108 17631+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17632+ break;
17633+ case Opt_wbr_copyup:
17634+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
17635+ if (opt->wbr_copyup >= 0) {
17636+ err = 0;
17637+ opt->type = token;
17638+ } else
4a4d8108 17639+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 17640+ break;
17641+
17642+ case Opt_ignore:
4a4d8108 17643+ pr_warning("ignored %s\n", opt_str);
1facf9fc 17644+ /*FALLTHROUGH*/
17645+ case Opt_ignore_silent:
17646+ skipped = 1;
17647+ err = 0;
17648+ break;
17649+ case Opt_err:
4a4d8108 17650+ pr_err("unknown option %s\n", opt_str);
1facf9fc 17651+ break;
17652+ }
17653+
17654+ if (!err && !skipped) {
17655+ if (unlikely(++opt > opt_tail)) {
17656+ err = -E2BIG;
17657+ opt--;
17658+ opt->type = Opt_tail;
17659+ break;
17660+ }
17661+ opt->type = Opt_tail;
17662+ }
17663+ }
17664+
17665+ kfree(a);
17666+ dump_opts(opts);
17667+ if (unlikely(err))
17668+ au_opts_free(opts);
17669+
4f0767ce 17670+out:
1facf9fc 17671+ return err;
17672+}
17673+
17674+static int au_opt_wbr_create(struct super_block *sb,
17675+ struct au_opt_wbr_create *create)
17676+{
17677+ int err;
17678+ struct au_sbinfo *sbinfo;
17679+
dece6358
AM
17680+ SiMustWriteLock(sb);
17681+
1facf9fc 17682+ err = 1; /* handled */
17683+ sbinfo = au_sbi(sb);
17684+ if (sbinfo->si_wbr_create_ops->fin) {
17685+ err = sbinfo->si_wbr_create_ops->fin(sb);
17686+ if (!err)
17687+ err = 1;
17688+ }
17689+
17690+ sbinfo->si_wbr_create = create->wbr_create;
17691+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
17692+ switch (create->wbr_create) {
17693+ case AuWbrCreate_MFSRRV:
17694+ case AuWbrCreate_MFSRR:
17695+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
17696+ /*FALLTHROUGH*/
17697+ case AuWbrCreate_MFS:
17698+ case AuWbrCreate_MFSV:
17699+ case AuWbrCreate_PMFS:
17700+ case AuWbrCreate_PMFSV:
e49829fe
JR
17701+ sbinfo->si_wbr_mfs.mfs_expire
17702+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 17703+ break;
17704+ }
17705+
17706+ if (sbinfo->si_wbr_create_ops->init)
17707+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
17708+
17709+ return err;
17710+}
17711+
17712+/*
17713+ * returns,
17714+ * plus: processed without an error
17715+ * zero: unprocessed
17716+ */
17717+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
17718+ struct au_opts *opts)
17719+{
17720+ int err;
17721+ struct au_sbinfo *sbinfo;
17722+
dece6358
AM
17723+ SiMustWriteLock(sb);
17724+
1facf9fc 17725+ err = 1; /* handled */
17726+ sbinfo = au_sbi(sb);
17727+ switch (opt->type) {
17728+ case Opt_udba:
17729+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
17730+ sbinfo->si_mntflags |= opt->udba;
17731+ opts->given_udba |= opt->udba;
17732+ break;
17733+
17734+ case Opt_plink:
17735+ au_opt_set(sbinfo->si_mntflags, PLINK);
17736+ break;
17737+ case Opt_noplink:
17738+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 17739+ au_plink_put(sb, /*verbose*/1);
1facf9fc 17740+ au_opt_clr(sbinfo->si_mntflags, PLINK);
17741+ break;
17742+ case Opt_list_plink:
17743+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
17744+ au_plink_list(sb);
17745+ break;
17746+
4a4d8108
AM
17747+ case Opt_dio:
17748+ au_opt_set(sbinfo->si_mntflags, DIO);
17749+ au_fset_opts(opts->flags, REFRESH_DYAOP);
17750+ break;
17751+ case Opt_nodio:
17752+ au_opt_clr(sbinfo->si_mntflags, DIO);
17753+ au_fset_opts(opts->flags, REFRESH_DYAOP);
17754+ break;
17755+
1facf9fc 17756+ case Opt_diropq_a:
17757+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
17758+ break;
17759+ case Opt_diropq_w:
17760+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
17761+ break;
17762+
17763+ case Opt_warn_perm:
17764+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
17765+ break;
17766+ case Opt_nowarn_perm:
17767+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
17768+ break;
17769+
17770+ case Opt_refrof:
17771+ au_opt_set(sbinfo->si_mntflags, REFROF);
17772+ break;
17773+ case Opt_norefrof:
17774+ au_opt_clr(sbinfo->si_mntflags, REFROF);
17775+ break;
17776+
17777+ case Opt_verbose:
17778+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
17779+ break;
17780+ case Opt_noverbose:
17781+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
17782+ break;
17783+
17784+ case Opt_sum:
17785+ au_opt_set(sbinfo->si_mntflags, SUM);
17786+ break;
17787+ case Opt_wsum:
17788+ au_opt_clr(sbinfo->si_mntflags, SUM);
17789+ au_opt_set(sbinfo->si_mntflags, SUM_W);
17790+ case Opt_nosum:
17791+ au_opt_clr(sbinfo->si_mntflags, SUM);
17792+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
17793+ break;
17794+
17795+ case Opt_wbr_create:
17796+ err = au_opt_wbr_create(sb, &opt->wbr_create);
17797+ break;
17798+ case Opt_wbr_copyup:
17799+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
17800+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
17801+ break;
17802+
17803+ case Opt_dirwh:
17804+ sbinfo->si_dirwh = opt->dirwh;
17805+ break;
17806+
17807+ case Opt_rdcache:
e49829fe
JR
17808+ sbinfo->si_rdcache
17809+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 17810+ break;
17811+ case Opt_rdblk:
17812+ sbinfo->si_rdblk = opt->rdblk;
17813+ break;
dece6358
AM
17814+ case Opt_rdblk_def:
17815+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
17816+ break;
1facf9fc 17817+ case Opt_rdhash:
17818+ sbinfo->si_rdhash = opt->rdhash;
17819+ break;
dece6358
AM
17820+ case Opt_rdhash_def:
17821+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
17822+ break;
17823+
17824+ case Opt_shwh:
17825+ au_opt_set(sbinfo->si_mntflags, SHWH);
17826+ break;
17827+ case Opt_noshwh:
17828+ au_opt_clr(sbinfo->si_mntflags, SHWH);
17829+ break;
1facf9fc 17830+
17831+ case Opt_trunc_xino:
17832+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
17833+ break;
17834+ case Opt_notrunc_xino:
17835+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
17836+ break;
17837+
17838+ case Opt_trunc_xino_path:
17839+ case Opt_itrunc_xino:
17840+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
17841+ if (!err)
17842+ err = 1;
17843+ break;
17844+
17845+ case Opt_trunc_xib:
17846+ au_fset_opts(opts->flags, TRUNC_XIB);
17847+ break;
17848+ case Opt_notrunc_xib:
17849+ au_fclr_opts(opts->flags, TRUNC_XIB);
17850+ break;
17851+
17852+ default:
17853+ err = 0;
17854+ break;
17855+ }
17856+
17857+ return err;
17858+}
17859+
17860+/*
17861+ * returns tri-state.
17862+ * plus: processed without an error
17863+ * zero: unprocessed
17864+ * minus: error
17865+ */
17866+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
17867+ struct au_opts *opts)
17868+{
17869+ int err, do_refresh;
17870+
17871+ err = 0;
17872+ switch (opt->type) {
17873+ case Opt_append:
17874+ opt->add.bindex = au_sbend(sb) + 1;
17875+ if (opt->add.bindex < 0)
17876+ opt->add.bindex = 0;
17877+ goto add;
17878+ case Opt_prepend:
17879+ opt->add.bindex = 0;
17880+ add:
17881+ case Opt_add:
17882+ err = au_br_add(sb, &opt->add,
17883+ au_ftest_opts(opts->flags, REMOUNT));
17884+ if (!err) {
17885+ err = 1;
17886+ au_fset_opts(opts->flags, REFRESH_DIR);
4a4d8108 17887+ au_fset_opts(opts->flags, REFRESH_NONDIR);
1facf9fc 17888+ }
17889+ break;
17890+
17891+ case Opt_del:
17892+ case Opt_idel:
17893+ err = au_br_del(sb, &opt->del,
17894+ au_ftest_opts(opts->flags, REMOUNT));
17895+ if (!err) {
17896+ err = 1;
17897+ au_fset_opts(opts->flags, TRUNC_XIB);
17898+ au_fset_opts(opts->flags, REFRESH_DIR);
17899+ au_fset_opts(opts->flags, REFRESH_NONDIR);
17900+ }
17901+ break;
17902+
17903+ case Opt_mod:
17904+ case Opt_imod:
17905+ err = au_br_mod(sb, &opt->mod,
17906+ au_ftest_opts(opts->flags, REMOUNT),
17907+ &do_refresh);
17908+ if (!err) {
17909+ err = 1;
17910+ if (do_refresh) {
17911+ au_fset_opts(opts->flags, REFRESH_DIR);
17912+ au_fset_opts(opts->flags, REFRESH_NONDIR);
17913+ }
17914+ }
17915+ break;
17916+ }
17917+
17918+ return err;
17919+}
17920+
17921+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
17922+ struct au_opt_xino **opt_xino,
17923+ struct au_opts *opts)
17924+{
17925+ int err;
17926+ aufs_bindex_t bend, bindex;
17927+ struct dentry *root, *parent, *h_root;
17928+
17929+ err = 0;
17930+ switch (opt->type) {
17931+ case Opt_xino:
17932+ err = au_xino_set(sb, &opt->xino,
17933+ !!au_ftest_opts(opts->flags, REMOUNT));
17934+ if (unlikely(err))
17935+ break;
17936+
17937+ *opt_xino = &opt->xino;
17938+ au_xino_brid_set(sb, -1);
17939+
17940+ /* safe d_parent access */
17941+ parent = opt->xino.file->f_dentry->d_parent;
17942+ root = sb->s_root;
17943+ bend = au_sbend(sb);
17944+ for (bindex = 0; bindex <= bend; bindex++) {
17945+ h_root = au_h_dptr(root, bindex);
17946+ if (h_root == parent) {
17947+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
17948+ break;
17949+ }
17950+ }
17951+ break;
17952+
17953+ case Opt_noxino:
17954+ au_xino_clr(sb);
17955+ au_xino_brid_set(sb, -1);
17956+ *opt_xino = (void *)-1;
17957+ break;
17958+ }
17959+
17960+ return err;
17961+}
17962+
17963+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
17964+ unsigned int pending)
17965+{
17966+ int err;
17967+ aufs_bindex_t bindex, bend;
17968+ unsigned char do_plink, skip, do_free;
17969+ struct au_branch *br;
17970+ struct au_wbr *wbr;
17971+ struct dentry *root;
17972+ struct inode *dir, *h_dir;
17973+ struct au_sbinfo *sbinfo;
17974+ struct au_hinode *hdir;
17975+
dece6358
AM
17976+ SiMustAnyLock(sb);
17977+
1facf9fc 17978+ sbinfo = au_sbi(sb);
17979+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
17980+
dece6358
AM
17981+ if (!(sb_flags & MS_RDONLY)) {
17982+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
4a4d8108 17983+ pr_warning("first branch should be rw\n");
dece6358 17984+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
4a4d8108 17985+ pr_warning("shwh should be used with ro\n");
dece6358 17986+ }
1facf9fc 17987+
4a4d8108 17988+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 17989+ && !au_opt_test(sbinfo->si_mntflags, XINO))
4a4d8108 17990+ pr_warning("udba=*notify requires xino\n");
1facf9fc 17991+
17992+ err = 0;
17993+ root = sb->s_root;
4a4d8108 17994+ dir = root->d_inode;
1facf9fc 17995+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
17996+ bend = au_sbend(sb);
17997+ for (bindex = 0; !err && bindex <= bend; bindex++) {
17998+ skip = 0;
17999+ h_dir = au_h_iptr(dir, bindex);
18000+ br = au_sbr(sb, bindex);
18001+ do_free = 0;
18002+
18003+ wbr = br->br_wbr;
18004+ if (wbr)
18005+ wbr_wh_read_lock(wbr);
18006+
18007+ switch (br->br_perm) {
18008+ case AuBrPerm_RO:
18009+ case AuBrPerm_ROWH:
18010+ case AuBrPerm_RR:
18011+ case AuBrPerm_RRWH:
18012+ do_free = !!wbr;
18013+ skip = (!wbr
18014+ || (!wbr->wbr_whbase
18015+ && !wbr->wbr_plink
18016+ && !wbr->wbr_orph));
18017+ break;
18018+
18019+ case AuBrPerm_RWNoLinkWH:
18020+ /* skip = (!br->br_whbase && !br->br_orph); */
18021+ skip = (!wbr || !wbr->wbr_whbase);
18022+ if (skip && wbr) {
18023+ if (do_plink)
18024+ skip = !!wbr->wbr_plink;
18025+ else
18026+ skip = !wbr->wbr_plink;
18027+ }
18028+ break;
18029+
18030+ case AuBrPerm_RW:
18031+ /* skip = (br->br_whbase && br->br_ohph); */
18032+ skip = (wbr && wbr->wbr_whbase);
18033+ if (skip) {
18034+ if (do_plink)
18035+ skip = !!wbr->wbr_plink;
18036+ else
18037+ skip = !wbr->wbr_plink;
18038+ }
18039+ break;
18040+
18041+ default:
18042+ BUG();
18043+ }
18044+ if (wbr)
18045+ wbr_wh_read_unlock(wbr);
18046+
18047+ if (skip)
18048+ continue;
18049+
18050+ hdir = au_hi(dir, bindex);
4a4d8108 18051+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 18052+ if (wbr)
18053+ wbr_wh_write_lock(wbr);
18054+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
18055+ if (wbr)
18056+ wbr_wh_write_unlock(wbr);
4a4d8108 18057+ au_hn_imtx_unlock(hdir);
1facf9fc 18058+
18059+ if (!err && do_free) {
18060+ kfree(wbr);
18061+ br->br_wbr = NULL;
18062+ }
18063+ }
18064+
18065+ return err;
18066+}
18067+
18068+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
18069+{
18070+ int err;
18071+ unsigned int tmp;
18072+ aufs_bindex_t bend;
18073+ struct au_opt *opt;
18074+ struct au_opt_xino *opt_xino, xino;
18075+ struct au_sbinfo *sbinfo;
18076+
dece6358
AM
18077+ SiMustWriteLock(sb);
18078+
1facf9fc 18079+ err = 0;
18080+ opt_xino = NULL;
18081+ opt = opts->opt;
18082+ while (err >= 0 && opt->type != Opt_tail)
18083+ err = au_opt_simple(sb, opt++, opts);
18084+ if (err > 0)
18085+ err = 0;
18086+ else if (unlikely(err < 0))
18087+ goto out;
18088+
18089+ /* disable xino and udba temporary */
18090+ sbinfo = au_sbi(sb);
18091+ tmp = sbinfo->si_mntflags;
18092+ au_opt_clr(sbinfo->si_mntflags, XINO);
18093+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
18094+
18095+ opt = opts->opt;
18096+ while (err >= 0 && opt->type != Opt_tail)
18097+ err = au_opt_br(sb, opt++, opts);
18098+ if (err > 0)
18099+ err = 0;
18100+ else if (unlikely(err < 0))
18101+ goto out;
18102+
18103+ bend = au_sbend(sb);
18104+ if (unlikely(bend < 0)) {
18105+ err = -EINVAL;
4a4d8108 18106+ pr_err("no branches\n");
1facf9fc 18107+ goto out;
18108+ }
18109+
18110+ if (au_opt_test(tmp, XINO))
18111+ au_opt_set(sbinfo->si_mntflags, XINO);
18112+ opt = opts->opt;
18113+ while (!err && opt->type != Opt_tail)
18114+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
18115+ if (unlikely(err))
18116+ goto out;
18117+
18118+ err = au_opts_verify(sb, sb->s_flags, tmp);
18119+ if (unlikely(err))
18120+ goto out;
18121+
18122+ /* restore xino */
18123+ if (au_opt_test(tmp, XINO) && !opt_xino) {
18124+ xino.file = au_xino_def(sb);
18125+ err = PTR_ERR(xino.file);
18126+ if (IS_ERR(xino.file))
18127+ goto out;
18128+
18129+ err = au_xino_set(sb, &xino, /*remount*/0);
18130+ fput(xino.file);
18131+ if (unlikely(err))
18132+ goto out;
18133+ }
18134+
18135+ /* restore udba */
18136+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18137+ sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
4a4d8108 18138+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 18139+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 18140+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 18141+ }
18142+
4f0767ce 18143+out:
1facf9fc 18144+ return err;
18145+}
18146+
18147+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
18148+{
18149+ int err, rerr;
18150+ struct inode *dir;
18151+ struct au_opt_xino *opt_xino;
18152+ struct au_opt *opt;
18153+ struct au_sbinfo *sbinfo;
18154+
dece6358
AM
18155+ SiMustWriteLock(sb);
18156+
1facf9fc 18157+ dir = sb->s_root->d_inode;
18158+ sbinfo = au_sbi(sb);
18159+ err = 0;
18160+ opt_xino = NULL;
18161+ opt = opts->opt;
18162+ while (err >= 0 && opt->type != Opt_tail) {
18163+ err = au_opt_simple(sb, opt, opts);
18164+ if (!err)
18165+ err = au_opt_br(sb, opt, opts);
18166+ if (!err)
18167+ err = au_opt_xino(sb, opt, &opt_xino, opts);
18168+ opt++;
18169+ }
18170+ if (err > 0)
18171+ err = 0;
18172+ AuTraceErr(err);
18173+ /* go on even err */
18174+
18175+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
18176+ if (unlikely(rerr && !err))
18177+ err = rerr;
18178+
18179+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
18180+ rerr = au_xib_trunc(sb);
18181+ if (unlikely(rerr && !err))
18182+ err = rerr;
18183+ }
18184+
18185+ /* will be handled by the caller */
18186+ if (!au_ftest_opts(opts->flags, REFRESH_DIR)
18187+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
18188+ au_fset_opts(opts->flags, REFRESH_DIR);
18189+
18190+ AuDbg("status 0x%x\n", opts->flags);
18191+ return err;
18192+}
18193+
18194+/* ---------------------------------------------------------------------- */
18195+
18196+unsigned int au_opt_udba(struct super_block *sb)
18197+{
18198+ return au_mntflags(sb) & AuOptMask_UDBA;
18199+}
e49829fe 18200--- /dev/null
0c5527e5 18201+++ linux-2.6/fs/aufs/opts.h 2010-10-25 14:20:44.000000000 +0200
e49829fe 18202@@ -0,0 +1,207 @@
1facf9fc 18203+/*
4a4d8108 18204+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18205+ *
18206+ * This program, aufs is free software; you can redistribute it and/or modify
18207+ * it under the terms of the GNU General Public License as published by
18208+ * the Free Software Foundation; either version 2 of the License, or
18209+ * (at your option) any later version.
dece6358
AM
18210+ *
18211+ * This program is distributed in the hope that it will be useful,
18212+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18213+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18214+ * GNU General Public License for more details.
18215+ *
18216+ * You should have received a copy of the GNU General Public License
18217+ * along with this program; if not, write to the Free Software
18218+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18219+ */
18220+
18221+/*
18222+ * mount options/flags
18223+ */
18224+
18225+#ifndef __AUFS_OPTS_H__
18226+#define __AUFS_OPTS_H__
18227+
18228+#ifdef __KERNEL__
18229+
dece6358 18230+#include <linux/path.h>
1facf9fc 18231+#include <linux/aufs_type.h>
18232+
dece6358
AM
18233+struct file;
18234+struct super_block;
18235+
1facf9fc 18236+/* ---------------------------------------------------------------------- */
18237+
18238+/* mount flags */
18239+#define AuOpt_XINO 1 /* external inode number bitmap
18240+ and translation table */
18241+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
18242+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
18243+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 18244+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
18245+#define AuOpt_SHWH (1 << 5) /* show whiteout */
18246+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
18247+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
18248+#define AuOpt_REFROF (1 << 8) /* unimplemented */
18249+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
18250+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
18251+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
18252+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
18253+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 18254+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 18255+
4a4d8108
AM
18256+#ifndef CONFIG_AUFS_HNOTIFY
18257+#undef AuOpt_UDBA_HNOTIFY
18258+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 18259+#endif
dece6358
AM
18260+#ifndef CONFIG_AUFS_SHWH
18261+#undef AuOpt_SHWH
18262+#define AuOpt_SHWH 0
18263+#endif
1facf9fc 18264+
18265+#define AuOpt_Def (AuOpt_XINO \
18266+ | AuOpt_UDBA_REVAL \
18267+ | AuOpt_PLINK \
18268+ /* | AuOpt_DIRPERM1 */ \
18269+ | AuOpt_WARN_PERM)
18270+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
18271+ | AuOpt_UDBA_REVAL \
4a4d8108 18272+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 18273+
18274+#define au_opt_test(flags, name) (flags & AuOpt_##name)
18275+#define au_opt_set(flags, name) do { \
18276+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
18277+ ((flags) |= AuOpt_##name); \
18278+} while (0)
18279+#define au_opt_set_udba(flags, name) do { \
18280+ (flags) &= ~AuOptMask_UDBA; \
18281+ ((flags) |= AuOpt_##name); \
18282+} while (0)
18283+#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
18284+
e49829fe
JR
18285+static inline unsigned int au_opts_plink(unsigned int mntflags)
18286+{
18287+#ifdef CONFIG_PROC_FS
18288+ return mntflags;
18289+#else
18290+ return mntflags & ~AuOpt_PLINK;
18291+#endif
18292+}
18293+
1facf9fc 18294+/* ---------------------------------------------------------------------- */
18295+
18296+/* policies to select one among multiple writable branches */
18297+enum {
18298+ AuWbrCreate_TDP, /* top down parent */
18299+ AuWbrCreate_RR, /* round robin */
18300+ AuWbrCreate_MFS, /* most free space */
18301+ AuWbrCreate_MFSV, /* mfs with seconds */
18302+ AuWbrCreate_MFSRR, /* mfs then rr */
18303+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
18304+ AuWbrCreate_PMFS, /* parent and mfs */
18305+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
18306+
18307+ AuWbrCreate_Def = AuWbrCreate_TDP
18308+};
18309+
18310+enum {
18311+ AuWbrCopyup_TDP, /* top down parent */
18312+ AuWbrCopyup_BUP, /* bottom up parent */
18313+ AuWbrCopyup_BU, /* bottom up */
18314+
18315+ AuWbrCopyup_Def = AuWbrCopyup_TDP
18316+};
18317+
18318+/* ---------------------------------------------------------------------- */
18319+
18320+struct au_opt_add {
18321+ aufs_bindex_t bindex;
18322+ char *pathname;
18323+ int perm;
18324+ struct path path;
18325+};
18326+
18327+struct au_opt_del {
18328+ char *pathname;
18329+ struct path h_path;
18330+};
18331+
18332+struct au_opt_mod {
18333+ char *path;
18334+ int perm;
18335+ struct dentry *h_root;
18336+};
18337+
18338+struct au_opt_xino {
18339+ char *path;
18340+ struct file *file;
18341+};
18342+
18343+struct au_opt_xino_itrunc {
18344+ aufs_bindex_t bindex;
18345+};
18346+
18347+struct au_opt_wbr_create {
18348+ int wbr_create;
18349+ int mfs_second;
18350+ unsigned long long mfsrr_watermark;
18351+};
18352+
18353+struct au_opt {
18354+ int type;
18355+ union {
18356+ struct au_opt_xino xino;
18357+ struct au_opt_xino_itrunc xino_itrunc;
18358+ struct au_opt_add add;
18359+ struct au_opt_del del;
18360+ struct au_opt_mod mod;
18361+ int dirwh;
18362+ int rdcache;
18363+ unsigned int rdblk;
18364+ unsigned int rdhash;
18365+ int udba;
18366+ struct au_opt_wbr_create wbr_create;
18367+ int wbr_copyup;
18368+ };
18369+};
18370+
18371+/* opts flags */
18372+#define AuOpts_REMOUNT 1
18373+#define AuOpts_REFRESH_DIR (1 << 1)
18374+#define AuOpts_REFRESH_NONDIR (1 << 2)
18375+#define AuOpts_TRUNC_XIB (1 << 3)
4a4d8108 18376+#define AuOpts_REFRESH_DYAOP (1 << 4)
1facf9fc 18377+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
18378+#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
18379+#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
18380+
18381+struct au_opts {
18382+ struct au_opt *opt;
18383+ int max_opt;
18384+
18385+ unsigned int given_udba;
18386+ unsigned int flags;
18387+ unsigned long sb_flags;
18388+};
18389+
18390+/* ---------------------------------------------------------------------- */
18391+
18392+const char *au_optstr_br_perm(int brperm);
18393+const char *au_optstr_udba(int udba);
18394+const char *au_optstr_wbr_copyup(int wbr_copyup);
18395+const char *au_optstr_wbr_create(int wbr_create);
18396+
18397+void au_opts_free(struct au_opts *opts);
18398+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
18399+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18400+ unsigned int pending);
18401+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
18402+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
18403+
18404+unsigned int au_opt_udba(struct super_block *sb);
18405+
18406+/* ---------------------------------------------------------------------- */
18407+
18408+#endif /* __KERNEL__ */
18409+#endif /* __AUFS_OPTS_H__ */
e49829fe 18410--- /dev/null
0c5527e5 18411+++ linux-2.6/fs/aufs/plink.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 18412@@ -0,0 +1,483 @@
1facf9fc 18413+/*
4a4d8108 18414+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 18415+ *
18416+ * This program, aufs is free software; you can redistribute it and/or modify
18417+ * it under the terms of the GNU General Public License as published by
18418+ * the Free Software Foundation; either version 2 of the License, or
18419+ * (at your option) any later version.
dece6358
AM
18420+ *
18421+ * This program is distributed in the hope that it will be useful,
18422+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18423+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18424+ * GNU General Public License for more details.
18425+ *
18426+ * You should have received a copy of the GNU General Public License
18427+ * along with this program; if not, write to the Free Software
18428+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18429+ */
18430+
18431+/*
18432+ * pseudo-link
18433+ */
18434+
18435+#include "aufs.h"
18436+
18437+/*
e49829fe 18438+ * the pseudo-link maintenance mode.
1facf9fc 18439+ * during a user process maintains the pseudo-links,
18440+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
18441+ *
18442+ * Flags
18443+ * NOPLM:
18444+ * For entry functions which will handle plink, and i_mutex is already held
18445+ * in VFS.
18446+ * They cannot wait and should return an error at once.
18447+ * Callers has to check the error.
18448+ * NOPLMW:
18449+ * For entry functions which will handle plink, but i_mutex is not held
18450+ * in VFS.
18451+ * They can wait the plink maintenance mode to finish.
18452+ *
18453+ * They behave like F_SETLK and F_SETLKW.
18454+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 18455+ */
e49829fe
JR
18456+
18457+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 18458+{
e49829fe
JR
18459+ int err;
18460+ pid_t pid, ppid;
18461+ struct au_sbinfo *sbi;
dece6358
AM
18462+
18463+ SiMustAnyLock(sb);
18464+
e49829fe
JR
18465+ err = 0;
18466+ if (!au_opt_test(au_mntflags(sb), PLINK))
18467+ goto out;
18468+
18469+ sbi = au_sbi(sb);
18470+ pid = sbi->si_plink_maint_pid;
18471+ if (!pid || pid == current->pid)
18472+ goto out;
18473+
18474+ /* todo: it highly depends upon /sbin/mount.aufs */
18475+ rcu_read_lock();
18476+ ppid = task_pid_vnr(rcu_dereference(current->real_parent));
18477+ rcu_read_unlock();
18478+ if (pid == ppid)
18479+ goto out;
18480+
18481+ if (au_ftest_lock(flags, NOPLMW)) {
18482+ /*
18483+ * todo: debug by lockdep, if there is no i_mutex lock in VFS,
18484+ * we don't need to wait.
18485+ */
18486+ while (sbi->si_plink_maint_pid) {
18487+ si_read_unlock(sb);
18488+ /* gave up wake_up_bit() */
18489+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
18490+
18491+ if (au_ftest_lock(flags, FLUSH))
18492+ au_nwt_flush(&sbi->si_nowait);
18493+ si_noflush_read_lock(sb);
18494+ }
18495+ } else if (au_ftest_lock(flags, NOPLM)) {
18496+ AuDbg("ppid %d, pid %d\n", ppid, pid);
18497+ err = -EAGAIN;
18498+ }
18499+
18500+out:
18501+ return err;
4a4d8108
AM
18502+}
18503+
e49829fe 18504+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 18505+{
4a4d8108
AM
18506+ int iam;
18507+
4a4d8108 18508+ spin_lock(&sbinfo->si_plink_maint_lock);
e49829fe 18509+ iam = (sbinfo->si_plink_maint_pid == current->pid);
4a4d8108 18510+ if (iam)
e49829fe 18511+ sbinfo->si_plink_maint_pid = 0;
4a4d8108
AM
18512+ spin_unlock(&sbinfo->si_plink_maint_lock);
18513+ if (iam)
18514+ wake_up_all(&sbinfo->si_plink_wq);
18515+}
18516+
e49829fe 18517+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
18518+{
18519+ int err;
4a4d8108
AM
18520+ struct au_sbinfo *sbinfo;
18521+
18522+ err = 0;
4a4d8108
AM
18523+ sbinfo = au_sbi(sb);
18524+ /* make sure i am the only one in this fs */
e49829fe
JR
18525+ si_write_lock(sb, AuLock_FLUSH);
18526+ if (au_opt_test(au_mntflags(sb), PLINK)) {
18527+ spin_lock(&sbinfo->si_plink_maint_lock);
18528+ if (!sbinfo->si_plink_maint_pid)
18529+ sbinfo->si_plink_maint_pid = current->pid;
18530+ else
18531+ err = -EBUSY;
18532+ spin_unlock(&sbinfo->si_plink_maint_lock);
18533+ }
4a4d8108
AM
18534+ si_write_unlock(sb);
18535+
18536+ return err;
1facf9fc 18537+}
18538+
18539+/* ---------------------------------------------------------------------- */
18540+
18541+struct pseudo_link {
4a4d8108
AM
18542+ union {
18543+ struct list_head list;
18544+ struct rcu_head rcu;
18545+ };
1facf9fc 18546+ struct inode *inode;
18547+};
18548+
18549+#ifdef CONFIG_AUFS_DEBUG
18550+void au_plink_list(struct super_block *sb)
18551+{
18552+ struct au_sbinfo *sbinfo;
18553+ struct list_head *plink_list;
18554+ struct pseudo_link *plink;
18555+
dece6358
AM
18556+ SiMustAnyLock(sb);
18557+
1facf9fc 18558+ sbinfo = au_sbi(sb);
18559+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 18560+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 18561+
18562+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18563+ rcu_read_lock();
18564+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 18565+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 18566+ rcu_read_unlock();
1facf9fc 18567+}
18568+#endif
18569+
18570+/* is the inode pseudo-linked? */
18571+int au_plink_test(struct inode *inode)
18572+{
18573+ int found;
18574+ struct au_sbinfo *sbinfo;
18575+ struct list_head *plink_list;
18576+ struct pseudo_link *plink;
18577+
18578+ sbinfo = au_sbi(inode->i_sb);
dece6358 18579+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 18580+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 18581+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 18582+
18583+ found = 0;
18584+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18585+ rcu_read_lock();
18586+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 18587+ if (plink->inode == inode) {
18588+ found = 1;
18589+ break;
18590+ }
4a4d8108 18591+ rcu_read_unlock();
1facf9fc 18592+ return found;
18593+}
18594+
18595+/* ---------------------------------------------------------------------- */
18596+
18597+/*
18598+ * generate a name for plink.
18599+ * the file will be stored under AUFS_WH_PLINKDIR.
18600+ */
18601+/* 20 is max digits length of ulong 64 */
18602+#define PLINK_NAME_LEN ((20 + 1) * 2)
18603+
18604+static int plink_name(char *name, int len, struct inode *inode,
18605+ aufs_bindex_t bindex)
18606+{
18607+ int rlen;
18608+ struct inode *h_inode;
18609+
18610+ h_inode = au_h_iptr(inode, bindex);
18611+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
18612+ return rlen;
18613+}
18614+
18615+/* lookup the plink-ed @inode under the branch at @bindex */
18616+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
18617+{
18618+ struct dentry *h_dentry, *h_parent;
18619+ struct au_branch *br;
18620+ struct inode *h_dir;
18621+ char a[PLINK_NAME_LEN];
18622+ struct qstr tgtname = {
18623+ .name = a
18624+ };
18625+
e49829fe
JR
18626+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
18627+
1facf9fc 18628+ br = au_sbr(inode->i_sb, bindex);
18629+ h_parent = br->br_wbr->wbr_plink;
18630+ h_dir = h_parent->d_inode;
18631+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
18632+
18633+ /* always superio. */
18634+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
18635+ h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
18636+ mutex_unlock(&h_dir->i_mutex);
18637+ return h_dentry;
18638+}
18639+
18640+/* create a pseudo-link */
18641+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
18642+ struct dentry *h_dentry, struct au_branch *br)
18643+{
18644+ int err;
18645+ struct path h_path = {
18646+ .mnt = br->br_mnt
18647+ };
18648+ struct inode *h_dir;
18649+
18650+ h_dir = h_parent->d_inode;
4f0767ce 18651+again:
1facf9fc 18652+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
18653+ err = PTR_ERR(h_path.dentry);
18654+ if (IS_ERR(h_path.dentry))
18655+ goto out;
18656+
18657+ err = 0;
18658+ /* wh.plink dir is not monitored */
18659+ if (h_path.dentry->d_inode
18660+ && h_path.dentry->d_inode != h_dentry->d_inode) {
18661+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
18662+ dput(h_path.dentry);
18663+ h_path.dentry = NULL;
18664+ if (!err)
18665+ goto again;
18666+ }
18667+ if (!err && !h_path.dentry->d_inode)
18668+ err = vfsub_link(h_dentry, h_dir, &h_path);
18669+ dput(h_path.dentry);
18670+
4f0767ce 18671+out:
1facf9fc 18672+ return err;
18673+}
18674+
18675+struct do_whplink_args {
18676+ int *errp;
18677+ struct qstr *tgt;
18678+ struct dentry *h_parent;
18679+ struct dentry *h_dentry;
18680+ struct au_branch *br;
18681+};
18682+
18683+static void call_do_whplink(void *args)
18684+{
18685+ struct do_whplink_args *a = args;
18686+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
18687+}
18688+
18689+static int whplink(struct dentry *h_dentry, struct inode *inode,
18690+ aufs_bindex_t bindex, struct au_branch *br)
18691+{
18692+ int err, wkq_err;
18693+ struct au_wbr *wbr;
18694+ struct dentry *h_parent;
18695+ struct inode *h_dir;
18696+ char a[PLINK_NAME_LEN];
18697+ struct qstr tgtname = {
18698+ .name = a
18699+ };
18700+
18701+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
18702+ h_parent = wbr->wbr_plink;
18703+ h_dir = h_parent->d_inode;
18704+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
18705+
18706+ /* always superio. */
18707+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
b752ccd1 18708+ if (current_fsuid()) {
1facf9fc 18709+ struct do_whplink_args args = {
18710+ .errp = &err,
18711+ .tgt = &tgtname,
18712+ .h_parent = h_parent,
18713+ .h_dentry = h_dentry,
18714+ .br = br
18715+ };
18716+ wkq_err = au_wkq_wait(call_do_whplink, &args);
18717+ if (unlikely(wkq_err))
18718+ err = wkq_err;
18719+ } else
18720+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
18721+ mutex_unlock(&h_dir->i_mutex);
18722+
18723+ return err;
18724+}
18725+
18726+/* free a single plink */
18727+static void do_put_plink(struct pseudo_link *plink, int do_del)
18728+{
1facf9fc 18729+ if (do_del)
18730+ list_del(&plink->list);
4a4d8108
AM
18731+ iput(plink->inode);
18732+ kfree(plink);
18733+}
18734+
18735+static void do_put_plink_rcu(struct rcu_head *rcu)
18736+{
18737+ struct pseudo_link *plink;
18738+
18739+ plink = container_of(rcu, struct pseudo_link, rcu);
18740+ iput(plink->inode);
1facf9fc 18741+ kfree(plink);
18742+}
18743+
18744+/*
18745+ * create a new pseudo-link for @h_dentry on @bindex.
18746+ * the linked inode is held in aufs @inode.
18747+ */
18748+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
18749+ struct dentry *h_dentry)
18750+{
18751+ struct super_block *sb;
18752+ struct au_sbinfo *sbinfo;
18753+ struct list_head *plink_list;
4a4d8108 18754+ struct pseudo_link *plink, *tmp;
1facf9fc 18755+ int found, err, cnt;
18756+
18757+ sb = inode->i_sb;
18758+ sbinfo = au_sbi(sb);
18759+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 18760+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 18761+
1facf9fc 18762+ cnt = 0;
18763+ found = 0;
18764+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
18765+ rcu_read_lock();
18766+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 18767+ cnt++;
18768+ if (plink->inode == inode) {
18769+ found = 1;
18770+ break;
18771+ }
18772+ }
4a4d8108
AM
18773+ rcu_read_unlock();
18774+ if (found)
1facf9fc 18775+ return;
4a4d8108
AM
18776+
18777+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
18778+ if (tmp)
18779+ tmp->inode = au_igrab(inode);
18780+ else {
18781+ err = -ENOMEM;
18782+ goto out;
1facf9fc 18783+ }
18784+
4a4d8108
AM
18785+ spin_lock(&sbinfo->si_plink.spin);
18786+ list_for_each_entry(plink, plink_list, list) {
18787+ if (plink->inode == inode) {
18788+ found = 1;
18789+ break;
18790+ }
1facf9fc 18791+ }
4a4d8108
AM
18792+ if (!found)
18793+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 18794+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
18795+ if (!found) {
18796+ cnt++;
18797+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
18798+ "unexpectedly many pseudo links, %d\n", cnt);
1facf9fc 18799+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
18800+ } else {
18801+ do_put_plink(tmp, 0);
18802+ return;
1facf9fc 18803+ }
18804+
4a4d8108 18805+out:
1facf9fc 18806+ if (unlikely(err)) {
4a4d8108
AM
18807+ pr_warning("err %d, damaged pseudo link.\n", err);
18808+ if (tmp) {
18809+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
18810+ call_rcu(&tmp->rcu, do_put_plink_rcu);
18811+ }
1facf9fc 18812+ }
18813+}
18814+
18815+/* free all plinks */
e49829fe 18816+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 18817+{
18818+ struct au_sbinfo *sbinfo;
18819+ struct list_head *plink_list;
18820+ struct pseudo_link *plink, *tmp;
18821+
dece6358
AM
18822+ SiMustWriteLock(sb);
18823+
1facf9fc 18824+ sbinfo = au_sbi(sb);
18825+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 18826+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 18827+
18828+ plink_list = &sbinfo->si_plink.head;
18829+ /* no spin_lock since sbinfo is write-locked */
e49829fe 18830+ WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
1facf9fc 18831+ list_for_each_entry_safe(plink, tmp, plink_list, list)
18832+ do_put_plink(plink, 0);
18833+ INIT_LIST_HEAD(plink_list);
18834+}
18835+
e49829fe
JR
18836+void au_plink_clean(struct super_block *sb, int verbose)
18837+{
18838+ struct dentry *root;
18839+
18840+ root = sb->s_root;
18841+ aufs_write_lock(root);
18842+ if (au_opt_test(au_mntflags(sb), PLINK))
18843+ au_plink_put(sb, verbose);
18844+ aufs_write_unlock(root);
18845+}
18846+
1facf9fc 18847+/* free the plinks on a branch specified by @br_id */
18848+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
18849+{
18850+ struct au_sbinfo *sbinfo;
18851+ struct list_head *plink_list;
18852+ struct pseudo_link *plink, *tmp;
18853+ struct inode *inode;
18854+ aufs_bindex_t bstart, bend, bindex;
18855+ unsigned char do_put;
18856+
dece6358
AM
18857+ SiMustWriteLock(sb);
18858+
1facf9fc 18859+ sbinfo = au_sbi(sb);
18860+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 18861+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 18862+
18863+ plink_list = &sbinfo->si_plink.head;
18864+ /* no spin_lock since sbinfo is write-locked */
18865+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
18866+ do_put = 0;
18867+ inode = au_igrab(plink->inode);
18868+ ii_write_lock_child(inode);
18869+ bstart = au_ibstart(inode);
18870+ bend = au_ibend(inode);
18871+ if (bstart >= 0) {
18872+ for (bindex = bstart; bindex <= bend; bindex++) {
18873+ if (!au_h_iptr(inode, bindex)
18874+ || au_ii_br_id(inode, bindex) != br_id)
18875+ continue;
18876+ au_set_h_iptr(inode, bindex, NULL, 0);
18877+ do_put = 1;
18878+ break;
18879+ }
18880+ } else
18881+ do_put_plink(plink, 1);
18882+
dece6358
AM
18883+ if (do_put) {
18884+ for (bindex = bstart; bindex <= bend; bindex++)
18885+ if (au_h_iptr(inode, bindex)) {
18886+ do_put = 0;
18887+ break;
18888+ }
18889+ if (do_put)
18890+ do_put_plink(plink, 1);
18891+ }
18892+ ii_write_unlock(inode);
18893+ iput(inode);
18894+ }
18895+}
e49829fe 18896--- /dev/null
0c5527e5 18897+++ linux-2.6/fs/aufs/poll.c 2010-10-25 14:20:44.000000000 +0200
dece6358
AM
18898@@ -0,0 +1,56 @@
18899+/*
4a4d8108 18900+ * Copyright (C) 2005-2010 Junjiro R. Okajima
dece6358
AM
18901+ *
18902+ * This program, aufs is free software; you can redistribute it and/or modify
18903+ * it under the terms of the GNU General Public License as published by
18904+ * the Free Software Foundation; either version 2 of the License, or
18905+ * (at your option) any later version.
18906+ *
18907+ * This program is distributed in the hope that it will be useful,
18908+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18909+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18910+ * GNU General Public License for more details.
18911+ *
18912+ * You should have received a copy of the GNU General Public License
18913+ * along with this program; if not, write to the Free Software
18914+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18915+ */
18916+
1308ab2a 18917+/*
18918+ * poll operation
18919+ * There is only one filesystem which implements ->poll operation, currently.
18920+ */
18921+
18922+#include "aufs.h"
18923+
18924+unsigned int aufs_poll(struct file *file, poll_table *wait)
18925+{
18926+ unsigned int mask;
18927+ int err;
18928+ struct file *h_file;
18929+ struct dentry *dentry;
18930+ struct super_block *sb;
18931+
18932+ /* We should pretend an error happened. */
18933+ mask = POLLERR /* | POLLIN | POLLOUT */;
18934+ dentry = file->f_dentry;
18935+ sb = dentry->d_sb;
e49829fe 18936+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 18937+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
18938+ if (unlikely(err))
18939+ goto out;
18940+
18941+ /* it is not an error if h_file has no operation */
18942+ mask = DEFAULT_POLLMASK;
4a4d8108 18943+ h_file = au_hf_top(file);
1308ab2a 18944+ if (h_file->f_op && h_file->f_op->poll)
18945+ mask = h_file->f_op->poll(h_file, wait);
18946+
18947+ di_read_unlock(dentry, AuLock_IR);
18948+ fi_read_unlock(file);
18949+
4f0767ce 18950+out:
1308ab2a 18951+ si_read_unlock(sb);
18952+ AuTraceErr((int)mask);
18953+ return mask;
18954+}
e49829fe 18955--- /dev/null
0c5527e5 18956+++ linux-2.6/fs/aufs/procfs.c 2010-10-25 14:20:44.000000000 +0200
e49829fe
JR
18957@@ -0,0 +1,169 @@
18958+/*
18959+ * Copyright (C) 2010 Junjiro R. Okajima
18960+ *
18961+ * This program, aufs is free software; you can redistribute it and/or modify
18962+ * it under the terms of the GNU General Public License as published by
18963+ * the Free Software Foundation; either version 2 of the License, or
18964+ * (at your option) any later version.
18965+ *
18966+ * This program is distributed in the hope that it will be useful,
18967+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18968+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18969+ * GNU General Public License for more details.
18970+ *
18971+ * You should have received a copy of the GNU General Public License
18972+ * along with this program; if not, write to the Free Software
18973+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18974+ */
18975+
18976+/*
18977+ * procfs interfaces
18978+ */
18979+
18980+#include <linux/proc_fs.h>
18981+#include "aufs.h"
18982+
18983+static int au_procfs_plm_release(struct inode *inode, struct file *file)
18984+{
18985+ struct au_sbinfo *sbinfo;
18986+
18987+ sbinfo = file->private_data;
18988+ if (sbinfo) {
18989+ au_plink_maint_leave(sbinfo);
18990+ kobject_put(&sbinfo->si_kobj);
18991+ }
18992+
18993+ return 0;
18994+}
18995+
18996+static void au_procfs_plm_write_clean(struct file *file)
18997+{
18998+ struct au_sbinfo *sbinfo;
18999+
19000+ sbinfo = file->private_data;
19001+ if (sbinfo)
19002+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
19003+}
19004+
19005+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
19006+{
19007+ int err;
19008+ struct super_block *sb;
19009+ struct au_sbinfo *sbinfo;
19010+
19011+ err = -EBUSY;
19012+ if (unlikely(file->private_data))
19013+ goto out;
19014+
19015+ sb = NULL;
19016+ spin_lock(&au_sbilist.spin);
19017+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
19018+ if (id == sysaufs_si_id(sbinfo)) {
19019+ kobject_get(&sbinfo->si_kobj);
19020+ sb = sbinfo->si_sb;
19021+ break;
19022+ }
19023+ spin_unlock(&au_sbilist.spin);
19024+
19025+ err = -EINVAL;
19026+ if (unlikely(!sb))
19027+ goto out;
19028+
19029+ err = au_plink_maint_enter(sb);
19030+ if (!err)
19031+ /* keep kobject_get() */
19032+ file->private_data = sbinfo;
19033+ else
19034+ kobject_put(&sbinfo->si_kobj);
19035+out:
19036+ return err;
19037+}
19038+
19039+/*
19040+ * Accept a valid "si=xxxx" only.
19041+ * Once it is accepted successfully, accept "clean" too.
19042+ */
19043+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
19044+ size_t count, loff_t *ppos)
19045+{
19046+ ssize_t err;
19047+ unsigned long id;
19048+ /* last newline is allowed */
19049+ char buf[3 + sizeof(unsigned long) * 2 + 1];
19050+
19051+ err = -EACCES;
19052+ if (unlikely(!capable(CAP_SYS_ADMIN)))
19053+ goto out;
19054+
19055+ err = -EINVAL;
19056+ if (unlikely(count > sizeof(buf)))
19057+ goto out;
19058+
19059+ err = copy_from_user(buf, ubuf, count);
19060+ if (unlikely(err)) {
19061+ err = -EFAULT;
19062+ goto out;
19063+ }
19064+ buf[count] = 0;
19065+
19066+ err = -EINVAL;
19067+ if (!strcmp("clean", buf)) {
19068+ au_procfs_plm_write_clean(file);
19069+ goto out_success;
19070+ } else if (unlikely(strncmp("si=", buf, 3)))
19071+ goto out;
19072+
19073+ err = strict_strtoul(buf + 3, 16, &id);
19074+ if (unlikely(err))
19075+ goto out;
19076+
19077+ err = au_procfs_plm_write_si(file, id);
19078+ if (unlikely(err))
19079+ goto out;
19080+
19081+out_success:
19082+ err = count; /* success */
19083+out:
19084+ return err;
19085+}
19086+
19087+static const struct file_operations au_procfs_plm_fop = {
19088+ .write = au_procfs_plm_write,
19089+ .release = au_procfs_plm_release,
19090+ .owner = THIS_MODULE
19091+};
19092+
19093+/* ---------------------------------------------------------------------- */
19094+
19095+static struct proc_dir_entry *au_procfs_dir;
19096+
19097+void au_procfs_fin(void)
19098+{
19099+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
19100+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
19101+}
19102+
19103+int __init au_procfs_init(void)
19104+{
19105+ int err;
19106+ struct proc_dir_entry *entry;
19107+
19108+ err = -ENOMEM;
19109+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
19110+ if (unlikely(!au_procfs_dir))
19111+ goto out;
19112+
19113+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
19114+ au_procfs_dir, &au_procfs_plm_fop);
19115+ if (unlikely(!entry))
19116+ goto out_dir;
19117+
19118+ err = 0;
19119+ goto out; /* success */
19120+
19121+
19122+out_dir:
19123+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
19124+out:
19125+ return err;
19126+}
19127--- /dev/null
0c5527e5 19128+++ linux-2.6/fs/aufs/rdu.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 19129@@ -0,0 +1,380 @@
1308ab2a 19130+/*
4a4d8108 19131+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1308ab2a 19132+ *
19133+ * This program, aufs is free software; you can redistribute it and/or modify
19134+ * it under the terms of the GNU General Public License as published by
19135+ * the Free Software Foundation; either version 2 of the License, or
19136+ * (at your option) any later version.
19137+ *
19138+ * This program is distributed in the hope that it will be useful,
19139+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19140+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19141+ * GNU General Public License for more details.
19142+ *
19143+ * You should have received a copy of the GNU General Public License
19144+ * along with this program; if not, write to the Free Software
19145+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19146+ */
19147+
19148+/*
19149+ * readdir in userspace.
19150+ */
19151+
b752ccd1 19152+#include <linux/compat.h>
4a4d8108 19153+#include <linux/fs_stack.h>
1308ab2a 19154+#include <linux/security.h>
19155+#include <linux/uaccess.h>
19156+#include <linux/aufs_type.h>
19157+#include "aufs.h"
19158+
19159+/* bits for struct aufs_rdu.flags */
19160+#define AuRdu_CALLED 1
19161+#define AuRdu_CONT (1 << 1)
19162+#define AuRdu_FULL (1 << 2)
19163+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
19164+#define au_fset_rdu(flags, name) { (flags) |= AuRdu_##name; }
19165+#define au_fclr_rdu(flags, name) { (flags) &= ~AuRdu_##name; }
19166+
19167+struct au_rdu_arg {
19168+ struct aufs_rdu *rdu;
19169+ union au_rdu_ent_ul ent;
19170+ unsigned long end;
19171+
19172+ struct super_block *sb;
19173+ int err;
19174+};
19175+
19176+static int au_rdu_fill(void *__arg, const char *name, int nlen,
19177+ loff_t offset, u64 h_ino, unsigned int d_type)
19178+{
19179+ int err, len;
19180+ struct au_rdu_arg *arg = __arg;
19181+ struct aufs_rdu *rdu = arg->rdu;
19182+ struct au_rdu_ent ent;
19183+
19184+ err = 0;
19185+ arg->err = 0;
19186+ au_fset_rdu(rdu->cookie.flags, CALLED);
19187+ len = au_rdu_len(nlen);
19188+ if (arg->ent.ul + len < arg->end) {
19189+ ent.ino = h_ino;
19190+ ent.bindex = rdu->cookie.bindex;
19191+ ent.type = d_type;
19192+ ent.nlen = nlen;
4a4d8108
AM
19193+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
19194+ ent.type = DT_UNKNOWN;
1308ab2a 19195+
19196+ err = -EFAULT;
19197+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
19198+ goto out;
19199+ if (copy_to_user(arg->ent.e->name, name, nlen))
19200+ goto out;
19201+ /* the terminating NULL */
19202+ if (__put_user(0, arg->ent.e->name + nlen))
19203+ goto out;
19204+ err = 0;
19205+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
19206+ arg->ent.ul += len;
19207+ rdu->rent++;
19208+ } else {
19209+ err = -EFAULT;
19210+ au_fset_rdu(rdu->cookie.flags, FULL);
19211+ rdu->full = 1;
19212+ rdu->tail = arg->ent;
19213+ }
19214+
4f0767ce 19215+out:
1308ab2a 19216+ /* AuTraceErr(err); */
19217+ return err;
19218+}
19219+
19220+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
19221+{
19222+ int err;
19223+ loff_t offset;
19224+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
19225+
19226+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
19227+ err = offset;
19228+ if (unlikely(offset != cookie->h_pos))
19229+ goto out;
19230+
19231+ err = 0;
19232+ do {
19233+ arg->err = 0;
19234+ au_fclr_rdu(cookie->flags, CALLED);
19235+ /* smp_mb(); */
19236+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
19237+ if (err >= 0)
19238+ err = arg->err;
19239+ } while (!err
19240+ && au_ftest_rdu(cookie->flags, CALLED)
19241+ && !au_ftest_rdu(cookie->flags, FULL));
19242+ cookie->h_pos = h_file->f_pos;
19243+
4f0767ce 19244+out:
1308ab2a 19245+ AuTraceErr(err);
19246+ return err;
19247+}
19248+
19249+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
19250+{
19251+ int err;
19252+ aufs_bindex_t bend;
19253+ struct au_rdu_arg arg;
19254+ struct dentry *dentry;
19255+ struct inode *inode;
19256+ struct file *h_file;
19257+ struct au_rdu_cookie *cookie = &rdu->cookie;
19258+
19259+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
19260+ if (unlikely(err)) {
19261+ err = -EFAULT;
19262+ AuTraceErr(err);
19263+ goto out;
19264+ }
19265+ rdu->rent = 0;
19266+ rdu->tail = rdu->ent;
19267+ rdu->full = 0;
19268+ arg.rdu = rdu;
19269+ arg.ent = rdu->ent;
19270+ arg.end = arg.ent.ul;
19271+ arg.end += rdu->sz;
19272+
19273+ err = -ENOTDIR;
19274+ if (unlikely(!file->f_op || !file->f_op->readdir))
19275+ goto out;
19276+
19277+ err = security_file_permission(file, MAY_READ);
19278+ AuTraceErr(err);
19279+ if (unlikely(err))
19280+ goto out;
19281+
19282+ dentry = file->f_dentry;
19283+ inode = dentry->d_inode;
19284+#if 1
19285+ mutex_lock(&inode->i_mutex);
19286+#else
19287+ err = mutex_lock_killable(&inode->i_mutex);
19288+ AuTraceErr(err);
19289+ if (unlikely(err))
19290+ goto out;
19291+#endif
19292+ err = -ENOENT;
19293+ if (unlikely(IS_DEADDIR(inode)))
19294+ goto out_mtx;
19295+
19296+ arg.sb = inode->i_sb;
e49829fe
JR
19297+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
19298+ if (unlikely(err))
19299+ goto out_mtx;
19300+ /* todo: reval? */
1308ab2a 19301+ fi_read_lock(file);
19302+
19303+ err = -EAGAIN;
19304+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
19305+ && cookie->generation != au_figen(file)))
19306+ goto out_unlock;
19307+
19308+ err = 0;
19309+ if (!rdu->blk) {
19310+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
19311+ if (!rdu->blk)
19312+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
19313+ }
19314+ bend = au_fbstart(file);
19315+ if (cookie->bindex < bend)
19316+ cookie->bindex = bend;
4a4d8108 19317+ bend = au_fbend_dir(file);
1308ab2a 19318+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
19319+ for (; !err && cookie->bindex <= bend;
19320+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 19321+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 19322+ if (!h_file)
19323+ continue;
19324+
19325+ au_fclr_rdu(cookie->flags, FULL);
19326+ err = au_rdu_do(h_file, &arg);
19327+ AuTraceErr(err);
19328+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
19329+ break;
19330+ }
19331+ AuDbg("rent %llu\n", rdu->rent);
19332+
19333+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
19334+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
19335+ au_fset_rdu(cookie->flags, CONT);
19336+ cookie->generation = au_figen(file);
19337+ }
19338+
19339+ ii_read_lock_child(inode);
19340+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
19341+ ii_read_unlock(inode);
19342+
4f0767ce 19343+out_unlock:
1308ab2a 19344+ fi_read_unlock(file);
19345+ si_read_unlock(arg.sb);
4f0767ce 19346+out_mtx:
1308ab2a 19347+ mutex_unlock(&inode->i_mutex);
4f0767ce 19348+out:
1308ab2a 19349+ AuTraceErr(err);
19350+ return err;
19351+}
19352+
19353+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
19354+{
19355+ int err;
19356+ ino_t ino;
19357+ unsigned long long nent;
19358+ union au_rdu_ent_ul *u;
19359+ struct au_rdu_ent ent;
19360+ struct super_block *sb;
19361+
19362+ err = 0;
19363+ nent = rdu->nent;
19364+ u = &rdu->ent;
19365+ sb = file->f_dentry->d_sb;
19366+ si_read_lock(sb, AuLock_FLUSH);
19367+ while (nent-- > 0) {
1308ab2a 19368+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
19369+ if (!err)
19370+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 19371+ if (unlikely(err)) {
19372+ err = -EFAULT;
19373+ AuTraceErr(err);
19374+ break;
19375+ }
19376+
19377+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
19378+ if (!ent.wh)
19379+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
19380+ else
19381+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
19382+ &ino);
19383+ if (unlikely(err)) {
19384+ AuTraceErr(err);
19385+ break;
19386+ }
19387+
19388+ err = __put_user(ino, &u->e->ino);
19389+ if (unlikely(err)) {
19390+ err = -EFAULT;
19391+ AuTraceErr(err);
19392+ break;
19393+ }
19394+ u->ul += au_rdu_len(ent.nlen);
19395+ }
19396+ si_read_unlock(sb);
19397+
19398+ return err;
19399+}
19400+
19401+/* ---------------------------------------------------------------------- */
19402+
19403+static int au_rdu_verify(struct aufs_rdu *rdu)
19404+{
b752ccd1 19405+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 19406+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 19407+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 19408+ rdu->blk,
19409+ rdu->rent, rdu->shwh, rdu->full,
19410+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
19411+ rdu->cookie.generation);
dece6358 19412+
b752ccd1 19413+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 19414+ return 0;
dece6358 19415+
b752ccd1
AM
19416+ AuDbg("%u:%u\n",
19417+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 19418+ return -EINVAL;
19419+}
19420+
19421+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 19422+{
1308ab2a 19423+ long err, e;
19424+ struct aufs_rdu rdu;
19425+ void __user *p = (void __user *)arg;
dece6358 19426+
1308ab2a 19427+ err = copy_from_user(&rdu, p, sizeof(rdu));
19428+ if (unlikely(err)) {
19429+ err = -EFAULT;
19430+ AuTraceErr(err);
19431+ goto out;
19432+ }
19433+ err = au_rdu_verify(&rdu);
dece6358
AM
19434+ if (unlikely(err))
19435+ goto out;
19436+
1308ab2a 19437+ switch (cmd) {
19438+ case AUFS_CTL_RDU:
19439+ err = au_rdu(file, &rdu);
19440+ if (unlikely(err))
19441+ break;
dece6358 19442+
1308ab2a 19443+ e = copy_to_user(p, &rdu, sizeof(rdu));
19444+ if (unlikely(e)) {
19445+ err = -EFAULT;
19446+ AuTraceErr(err);
19447+ }
19448+ break;
19449+ case AUFS_CTL_RDU_INO:
19450+ err = au_rdu_ino(file, &rdu);
19451+ break;
19452+
19453+ default:
4a4d8108 19454+ /* err = -ENOTTY; */
1308ab2a 19455+ err = -EINVAL;
19456+ }
dece6358 19457+
4f0767ce 19458+out:
1308ab2a 19459+ AuTraceErr(err);
19460+ return err;
1facf9fc 19461+}
b752ccd1
AM
19462+
19463+#ifdef CONFIG_COMPAT
19464+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
19465+{
19466+ long err, e;
19467+ struct aufs_rdu rdu;
19468+ void __user *p = compat_ptr(arg);
19469+
19470+ /* todo: get_user()? */
19471+ err = copy_from_user(&rdu, p, sizeof(rdu));
19472+ if (unlikely(err)) {
19473+ err = -EFAULT;
19474+ AuTraceErr(err);
19475+ goto out;
19476+ }
19477+ rdu.ent.e = compat_ptr(rdu.ent.ul);
19478+ err = au_rdu_verify(&rdu);
19479+ if (unlikely(err))
19480+ goto out;
19481+
19482+ switch (cmd) {
19483+ case AUFS_CTL_RDU:
19484+ err = au_rdu(file, &rdu);
19485+ if (unlikely(err))
19486+ break;
19487+
19488+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
19489+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
19490+ e = copy_to_user(p, &rdu, sizeof(rdu));
19491+ if (unlikely(e)) {
19492+ err = -EFAULT;
19493+ AuTraceErr(err);
19494+ }
19495+ break;
19496+ case AUFS_CTL_RDU_INO:
19497+ err = au_rdu_ino(file, &rdu);
19498+ break;
19499+
19500+ default:
19501+ /* err = -ENOTTY; */
19502+ err = -EINVAL;
19503+ }
19504+
4f0767ce 19505+out:
b752ccd1
AM
19506+ AuTraceErr(err);
19507+ return err;
19508+}
19509+#endif
e49829fe 19510--- /dev/null
0c5527e5 19511+++ linux-2.6/fs/aufs/rwsem.h 2010-10-25 14:20:44.000000000 +0200
e49829fe 19512@@ -0,0 +1,189 @@
1facf9fc 19513+/*
4a4d8108 19514+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19515+ *
19516+ * This program, aufs is free software; you can redistribute it and/or modify
19517+ * it under the terms of the GNU General Public License as published by
19518+ * the Free Software Foundation; either version 2 of the License, or
19519+ * (at your option) any later version.
dece6358
AM
19520+ *
19521+ * This program is distributed in the hope that it will be useful,
19522+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19523+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19524+ * GNU General Public License for more details.
19525+ *
19526+ * You should have received a copy of the GNU General Public License
19527+ * along with this program; if not, write to the Free Software
19528+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19529+ */
19530+
19531+/*
19532+ * simple read-write semaphore wrappers
19533+ */
19534+
19535+#ifndef __AUFS_RWSEM_H__
19536+#define __AUFS_RWSEM_H__
19537+
19538+#ifdef __KERNEL__
19539+
dece6358 19540+#include <linux/rwsem.h>
4a4d8108 19541+#include "debug.h"
dece6358
AM
19542+
19543+struct au_rwsem {
19544+ struct rw_semaphore rwsem;
19545+#ifdef CONFIG_AUFS_DEBUG
19546+ /* just for debugging, not almighty counter */
19547+ atomic_t rcnt, wcnt;
19548+#endif
19549+};
19550+
19551+#ifdef CONFIG_AUFS_DEBUG
19552+#define AuDbgCntInit(rw) do { \
19553+ atomic_set(&(rw)->rcnt, 0); \
19554+ atomic_set(&(rw)->wcnt, 0); \
19555+ smp_mb(); /* atomic set */ \
19556+} while (0)
19557+
e49829fe 19558+#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
dece6358 19559+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
e49829fe 19560+#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
dece6358
AM
19561+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
19562+#else
19563+#define AuDbgCntInit(rw) do {} while (0)
19564+#define AuDbgRcntInc(rw) do {} while (0)
19565+#define AuDbgRcntDec(rw) do {} while (0)
19566+#define AuDbgWcntInc(rw) do {} while (0)
19567+#define AuDbgWcntDec(rw) do {} while (0)
19568+#endif /* CONFIG_AUFS_DEBUG */
19569+
19570+/* to debug easier, do not make them inlined functions */
19571+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
19572+/* rwsem_is_locked() is unusable */
19573+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
19574+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
19575+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
19576+ && atomic_read(&(rw)->wcnt) <= 0)
19577+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
19578+ || atomic_read(&(rw)->wcnt))
19579+
e49829fe
JR
19580+#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
19581+
dece6358
AM
19582+static inline void au_rw_init(struct au_rwsem *rw)
19583+{
19584+ AuDbgCntInit(rw);
19585+ init_rwsem(&rw->rwsem);
19586+}
19587+
19588+static inline void au_rw_init_wlock(struct au_rwsem *rw)
19589+{
19590+ au_rw_init(rw);
19591+ down_write(&rw->rwsem);
19592+ AuDbgWcntInc(rw);
19593+}
19594+
19595+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
19596+ unsigned int lsc)
19597+{
19598+ au_rw_init(rw);
19599+ down_write_nested(&rw->rwsem, lsc);
19600+ AuDbgWcntInc(rw);
19601+}
19602+
19603+static inline void au_rw_read_lock(struct au_rwsem *rw)
19604+{
19605+ down_read(&rw->rwsem);
19606+ AuDbgRcntInc(rw);
19607+}
19608+
19609+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
19610+{
19611+ down_read_nested(&rw->rwsem, lsc);
19612+ AuDbgRcntInc(rw);
19613+}
19614+
19615+static inline void au_rw_read_unlock(struct au_rwsem *rw)
19616+{
19617+ AuRwMustReadLock(rw);
19618+ AuDbgRcntDec(rw);
19619+ up_read(&rw->rwsem);
19620+}
19621+
19622+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
19623+{
19624+ AuRwMustWriteLock(rw);
19625+ AuDbgRcntInc(rw);
19626+ AuDbgWcntDec(rw);
19627+ downgrade_write(&rw->rwsem);
19628+}
19629+
19630+static inline void au_rw_write_lock(struct au_rwsem *rw)
19631+{
19632+ down_write(&rw->rwsem);
19633+ AuDbgWcntInc(rw);
19634+}
19635+
19636+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
19637+ unsigned int lsc)
19638+{
19639+ down_write_nested(&rw->rwsem, lsc);
19640+ AuDbgWcntInc(rw);
19641+}
1facf9fc 19642+
dece6358
AM
19643+static inline void au_rw_write_unlock(struct au_rwsem *rw)
19644+{
19645+ AuRwMustWriteLock(rw);
19646+ AuDbgWcntDec(rw);
19647+ up_write(&rw->rwsem);
19648+}
19649+
19650+/* why is not _nested version defined */
19651+static inline int au_rw_read_trylock(struct au_rwsem *rw)
19652+{
19653+ int ret = down_read_trylock(&rw->rwsem);
19654+ if (ret)
19655+ AuDbgRcntInc(rw);
19656+ return ret;
19657+}
19658+
19659+static inline int au_rw_write_trylock(struct au_rwsem *rw)
19660+{
19661+ int ret = down_write_trylock(&rw->rwsem);
19662+ if (ret)
19663+ AuDbgWcntInc(rw);
19664+ return ret;
19665+}
19666+
19667+#undef AuDbgCntInit
19668+#undef AuDbgRcntInc
19669+#undef AuDbgRcntDec
19670+#undef AuDbgWcntInc
19671+#undef AuDbgWcntDec
1facf9fc 19672+
19673+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
19674+static inline void prefix##_read_lock(param) \
dece6358 19675+{ au_rw_read_lock(rwsem); } \
1facf9fc 19676+static inline void prefix##_write_lock(param) \
dece6358 19677+{ au_rw_write_lock(rwsem); } \
1facf9fc 19678+static inline int prefix##_read_trylock(param) \
dece6358 19679+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 19680+static inline int prefix##_write_trylock(param) \
dece6358 19681+{ return au_rw_write_trylock(rwsem); }
1facf9fc 19682+/* why is not _nested version defined */
19683+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 19684+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 19685+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 19686+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 19687+
19688+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
19689+static inline void prefix##_read_unlock(param) \
dece6358 19690+{ au_rw_read_unlock(rwsem); } \
1facf9fc 19691+static inline void prefix##_write_unlock(param) \
dece6358 19692+{ au_rw_write_unlock(rwsem); } \
1facf9fc 19693+static inline void prefix##_downgrade_lock(param) \
dece6358 19694+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 19695+
19696+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
19697+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
19698+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
19699+
19700+#endif /* __KERNEL__ */
19701+#endif /* __AUFS_RWSEM_H__ */
e49829fe 19702--- /dev/null
0c5527e5 19703+++ linux-2.6/fs/aufs/sbinfo.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 19704@@ -0,0 +1,311 @@
1facf9fc 19705+/*
4a4d8108 19706+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 19707+ *
19708+ * This program, aufs is free software; you can redistribute it and/or modify
19709+ * it under the terms of the GNU General Public License as published by
19710+ * the Free Software Foundation; either version 2 of the License, or
19711+ * (at your option) any later version.
dece6358
AM
19712+ *
19713+ * This program is distributed in the hope that it will be useful,
19714+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19715+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19716+ * GNU General Public License for more details.
19717+ *
19718+ * You should have received a copy of the GNU General Public License
19719+ * along with this program; if not, write to the Free Software
19720+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19721+ */
19722+
19723+/*
19724+ * superblock private data
19725+ */
19726+
e49829fe 19727+#include <linux/jiffies.h>
1facf9fc 19728+#include "aufs.h"
19729+
19730+/*
19731+ * they are necessary regardless sysfs is disabled.
19732+ */
19733+void au_si_free(struct kobject *kobj)
19734+{
19735+ struct au_sbinfo *sbinfo;
b752ccd1 19736+ char *locked __maybe_unused; /* debug only */
1facf9fc 19737+
19738+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
19739+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
e49829fe 19740+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
1facf9fc 19741+
e49829fe 19742+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 19743+ au_br_free(sbinfo);
e49829fe 19744+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1
AM
19745+
19746+ AuDebugOn(radix_tree_gang_lookup
19747+ (&sbinfo->au_si_pid.tree, (void **)&locked,
19748+ /*first_index*/PID_MAX_DEFAULT - 1,
19749+ /*max_items*/sizeof(locked)/sizeof(*locked)));
19750+
1facf9fc 19751+ kfree(sbinfo->si_branch);
b752ccd1 19752+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 19753+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 19754+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 19755+
19756+ kfree(sbinfo);
19757+}
19758+
19759+int au_si_alloc(struct super_block *sb)
19760+{
19761+ int err;
19762+ struct au_sbinfo *sbinfo;
e49829fe 19763+ static struct lock_class_key aufs_si;
1facf9fc 19764+
19765+ err = -ENOMEM;
4a4d8108 19766+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 19767+ if (unlikely(!sbinfo))
19768+ goto out;
19769+
b752ccd1
AM
19770+ BUILD_BUG_ON(sizeof(unsigned long) !=
19771+ sizeof(*sbinfo->au_si_pid.bitmap));
19772+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
19773+ sizeof(*sbinfo->au_si_pid.bitmap),
19774+ GFP_NOFS);
19775+ if (unlikely(!sbinfo->au_si_pid.bitmap))
19776+ goto out_sbinfo;
19777+
1facf9fc 19778+ /* will be reallocated separately */
19779+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
19780+ if (unlikely(!sbinfo->si_branch))
b752ccd1 19781+ goto out_pidmap;
1facf9fc 19782+
1facf9fc 19783+ err = sysaufs_si_init(sbinfo);
19784+ if (unlikely(err))
19785+ goto out_br;
19786+
19787+ au_nwt_init(&sbinfo->si_nowait);
dece6358 19788+ au_rw_init_wlock(&sbinfo->si_rwsem);
e49829fe 19789+ au_rw_class(&sbinfo->si_rwsem, &aufs_si);
b752ccd1
AM
19790+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
19791+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
19792+
1facf9fc 19793+ sbinfo->si_bend = -1;
1facf9fc 19794+
19795+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
19796+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
19797+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
19798+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 19799+
e49829fe 19800+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 19801+
1facf9fc 19802+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 19803+ sbinfo->si_xino_brid = -1;
19804+ /* leave si_xib_last_pindex and si_xib_next_bit */
19805+
e49829fe 19806+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 19807+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
19808+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
19809+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
19810+
19811+ au_spl_init(&sbinfo->si_plink);
19812+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 19813+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 19814+
19815+ /* leave other members for sysaufs and si_mnt. */
19816+ sbinfo->si_sb = sb;
19817+ sb->s_fs_info = sbinfo;
b752ccd1 19818+ si_pid_set(sb);
1facf9fc 19819+ au_debug_sbinfo_init(sbinfo);
19820+ return 0; /* success */
19821+
4f0767ce 19822+out_br:
1facf9fc 19823+ kfree(sbinfo->si_branch);
4f0767ce 19824+out_pidmap:
b752ccd1 19825+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 19826+out_sbinfo:
1facf9fc 19827+ kfree(sbinfo);
4f0767ce 19828+out:
1facf9fc 19829+ return err;
19830+}
19831+
19832+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
19833+{
19834+ int err, sz;
19835+ struct au_branch **brp;
19836+
dece6358
AM
19837+ AuRwMustWriteLock(&sbinfo->si_rwsem);
19838+
1facf9fc 19839+ err = -ENOMEM;
19840+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
19841+ if (unlikely(!sz))
19842+ sz = sizeof(*brp);
19843+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
19844+ if (brp) {
19845+ sbinfo->si_branch = brp;
19846+ err = 0;
19847+ }
19848+
19849+ return err;
19850+}
19851+
19852+/* ---------------------------------------------------------------------- */
19853+
19854+unsigned int au_sigen_inc(struct super_block *sb)
19855+{
19856+ unsigned int gen;
19857+
dece6358
AM
19858+ SiMustWriteLock(sb);
19859+
1facf9fc 19860+ gen = ++au_sbi(sb)->si_generation;
19861+ au_update_digen(sb->s_root);
19862+ au_update_iigen(sb->s_root->d_inode);
19863+ sb->s_root->d_inode->i_version++;
19864+ return gen;
19865+}
19866+
19867+aufs_bindex_t au_new_br_id(struct super_block *sb)
19868+{
19869+ aufs_bindex_t br_id;
19870+ int i;
19871+ struct au_sbinfo *sbinfo;
19872+
dece6358
AM
19873+ SiMustWriteLock(sb);
19874+
1facf9fc 19875+ sbinfo = au_sbi(sb);
19876+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
19877+ br_id = ++sbinfo->si_last_br_id;
19878+ if (br_id && au_br_index(sb, br_id) < 0)
19879+ return br_id;
19880+ }
19881+
19882+ return -1;
19883+}
19884+
19885+/* ---------------------------------------------------------------------- */
19886+
e49829fe
JR
19887+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
19888+int si_read_lock(struct super_block *sb, int flags)
19889+{
19890+ int err;
19891+
19892+ err = 0;
19893+ if (au_ftest_lock(flags, FLUSH))
19894+ au_nwt_flush(&au_sbi(sb)->si_nowait);
19895+
19896+ si_noflush_read_lock(sb);
19897+ err = au_plink_maint(sb, flags);
19898+ if (unlikely(err))
19899+ si_read_unlock(sb);
19900+
19901+ return err;
19902+}
19903+
19904+int si_write_lock(struct super_block *sb, int flags)
19905+{
19906+ int err;
19907+
19908+ if (au_ftest_lock(flags, FLUSH))
19909+ au_nwt_flush(&au_sbi(sb)->si_nowait);
19910+
19911+ si_noflush_write_lock(sb);
19912+ err = au_plink_maint(sb, flags);
19913+ if (unlikely(err))
19914+ si_write_unlock(sb);
19915+
19916+ return err;
19917+}
19918+
1facf9fc 19919+/* dentry and super_block lock. call at entry point */
e49829fe 19920+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 19921+{
e49829fe
JR
19922+ int err;
19923+
19924+ err = si_read_lock(dentry->d_sb, flags);
19925+ if (!err) {
19926+ if (au_ftest_lock(flags, DW))
19927+ di_write_lock_child(dentry);
19928+ else
19929+ di_read_lock_child(dentry, flags);
19930+ }
19931+
19932+ return err;
1facf9fc 19933+}
19934+
19935+void aufs_read_unlock(struct dentry *dentry, int flags)
19936+{
19937+ if (au_ftest_lock(flags, DW))
19938+ di_write_unlock(dentry);
19939+ else
19940+ di_read_unlock(dentry, flags);
19941+ si_read_unlock(dentry->d_sb);
19942+}
19943+
19944+void aufs_write_lock(struct dentry *dentry)
19945+{
e49829fe 19946+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 19947+ di_write_lock_child(dentry);
19948+}
19949+
19950+void aufs_write_unlock(struct dentry *dentry)
19951+{
19952+ di_write_unlock(dentry);
19953+ si_write_unlock(dentry->d_sb);
19954+}
19955+
e49829fe 19956+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 19957+{
e49829fe
JR
19958+ int err;
19959+
19960+ err = si_read_lock(d1->d_sb, flags);
19961+ if (!err)
19962+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
19963+ return err;
1facf9fc 19964+}
19965+
19966+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
19967+{
19968+ di_write_unlock2(d1, d2);
19969+ si_read_unlock(d1->d_sb);
19970+}
b752ccd1
AM
19971+
19972+/* ---------------------------------------------------------------------- */
19973+
19974+int si_pid_test_slow(struct super_block *sb)
19975+{
19976+ void *p;
19977+
19978+ rcu_read_lock();
19979+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
19980+ rcu_read_unlock();
19981+
19982+ return (long)p;
19983+}
19984+
19985+void si_pid_set_slow(struct super_block *sb)
19986+{
19987+ int err;
19988+ struct au_sbinfo *sbinfo;
19989+
19990+ AuDebugOn(si_pid_test_slow(sb));
19991+
19992+ sbinfo = au_sbi(sb);
19993+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
19994+ AuDebugOn(err);
19995+ spin_lock(&sbinfo->au_si_pid.tree_lock);
19996+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
19997+ (void *)1);
19998+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
19999+ AuDebugOn(err);
20000+ radix_tree_preload_end();
20001+}
20002+
20003+void si_pid_clr_slow(struct super_block *sb)
20004+{
20005+ void *p;
20006+ struct au_sbinfo *sbinfo;
20007+
20008+ AuDebugOn(!si_pid_test_slow(sb));
20009+
20010+ sbinfo = au_sbi(sb);
20011+ spin_lock(&sbinfo->au_si_pid.tree_lock);
20012+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
20013+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
20014+ AuDebugOn(1 != (long)p);
20015+}
e49829fe 20016--- /dev/null
0c5527e5 20017+++ linux-2.6/fs/aufs/spl.h 2010-10-25 14:20:44.000000000 +0200
4a4d8108 20018@@ -0,0 +1,66 @@
1facf9fc 20019+/*
4a4d8108 20020+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20021+ *
20022+ * This program, aufs is free software; you can redistribute it and/or modify
20023+ * it under the terms of the GNU General Public License as published by
20024+ * the Free Software Foundation; either version 2 of the License, or
20025+ * (at your option) any later version.
dece6358
AM
20026+ *
20027+ * This program is distributed in the hope that it will be useful,
20028+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20029+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20030+ * GNU General Public License for more details.
20031+ *
20032+ * You should have received a copy of the GNU General Public License
20033+ * along with this program; if not, write to the Free Software
20034+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20035+ */
20036+
20037+/*
20038+ * simple list protected by a spinlock
20039+ */
20040+
20041+#ifndef __AUFS_SPL_H__
20042+#define __AUFS_SPL_H__
20043+
20044+#ifdef __KERNEL__
20045+
dece6358
AM
20046+#include <linux/spinlock.h>
20047+#include <linux/list.h>
4a4d8108 20048+#include <linux/rculist.h>
1facf9fc 20049+
20050+struct au_splhead {
20051+ spinlock_t spin;
20052+ struct list_head head;
20053+};
20054+
20055+static inline void au_spl_init(struct au_splhead *spl)
20056+{
20057+ spin_lock_init(&spl->spin);
20058+ INIT_LIST_HEAD(&spl->head);
20059+}
20060+
20061+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
20062+{
20063+ spin_lock(&spl->spin);
20064+ list_add(list, &spl->head);
20065+ spin_unlock(&spl->spin);
20066+}
20067+
20068+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
20069+{
20070+ spin_lock(&spl->spin);
20071+ list_del(list);
20072+ spin_unlock(&spl->spin);
20073+}
20074+
4a4d8108
AM
20075+static inline void au_spl_del_rcu(struct list_head *list,
20076+ struct au_splhead *spl)
20077+{
20078+ spin_lock(&spl->spin);
20079+ list_del_rcu(list);
20080+ spin_unlock(&spl->spin);
20081+}
20082+
1facf9fc 20083+#endif /* __KERNEL__ */
20084+#endif /* __AUFS_SPL_H__ */
e49829fe 20085--- /dev/null
0c5527e5
AM
20086+++ linux-2.6/fs/aufs/super.c 2010-11-02 08:23:34.000000000 +0100
20087@@ -0,0 +1,863 @@
1facf9fc 20088+/*
4a4d8108 20089+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20090+ *
20091+ * This program, aufs is free software; you can redistribute it and/or modify
20092+ * it under the terms of the GNU General Public License as published by
20093+ * the Free Software Foundation; either version 2 of the License, or
20094+ * (at your option) any later version.
dece6358
AM
20095+ *
20096+ * This program is distributed in the hope that it will be useful,
20097+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20098+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20099+ * GNU General Public License for more details.
20100+ *
20101+ * You should have received a copy of the GNU General Public License
20102+ * along with this program; if not, write to the Free Software
20103+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20104+ */
20105+
20106+/*
20107+ * mount and super_block operations
20108+ */
20109+
20110+#include <linux/buffer_head.h>
e49829fe 20111+#include <linux/jiffies.h>
dece6358 20112+#include <linux/module.h>
1facf9fc 20113+#include <linux/seq_file.h>
20114+#include <linux/statfs.h>
20115+#include "aufs.h"
20116+
20117+/*
20118+ * super_operations
20119+ */
20120+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
20121+{
20122+ struct au_icntnr *c;
20123+
20124+ c = au_cache_alloc_icntnr();
20125+ if (c) {
1facf9fc 20126+ c->vfs_inode.i_version = 1; /* sigen(sb); */
20127+ c->iinfo.ii_hinode = NULL;
20128+ return &c->vfs_inode;
20129+ }
20130+ return NULL;
20131+}
20132+
20133+static void aufs_destroy_inode(struct inode *inode)
20134+{
20135+ au_iinfo_fin(inode);
20136+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
20137+}
20138+
20139+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
20140+{
20141+ struct inode *inode;
20142+ int err;
20143+
20144+ inode = iget_locked(sb, ino);
20145+ if (unlikely(!inode)) {
20146+ inode = ERR_PTR(-ENOMEM);
20147+ goto out;
20148+ }
20149+ if (!(inode->i_state & I_NEW))
20150+ goto out;
20151+
20152+ err = au_xigen_new(inode);
20153+ if (!err)
20154+ err = au_iinfo_init(inode);
20155+ if (!err)
20156+ inode->i_version++;
20157+ else {
20158+ iget_failed(inode);
20159+ inode = ERR_PTR(err);
20160+ }
20161+
4f0767ce 20162+out:
1facf9fc 20163+ /* never return NULL */
20164+ AuDebugOn(!inode);
20165+ AuTraceErrPtr(inode);
20166+ return inode;
20167+}
20168+
20169+/* lock free root dinfo */
20170+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
20171+{
20172+ int err;
20173+ aufs_bindex_t bindex, bend;
20174+ struct path path;
4a4d8108 20175+ struct au_hdentry *hdp;
1facf9fc 20176+ struct au_branch *br;
20177+
20178+ err = 0;
20179+ bend = au_sbend(sb);
4a4d8108 20180+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 20181+ for (bindex = 0; !err && bindex <= bend; bindex++) {
20182+ br = au_sbr(sb, bindex);
20183+ path.mnt = br->br_mnt;
4a4d8108 20184+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 20185+ err = au_seq_path(seq, &path);
20186+ if (err > 0)
20187+ err = seq_printf(seq, "=%s",
20188+ au_optstr_br_perm(br->br_perm));
20189+ if (!err && bindex != bend)
20190+ err = seq_putc(seq, ':');
20191+ }
20192+
20193+ return err;
20194+}
20195+
20196+static void au_show_wbr_create(struct seq_file *m, int v,
20197+ struct au_sbinfo *sbinfo)
20198+{
20199+ const char *pat;
20200+
dece6358
AM
20201+ AuRwMustAnyLock(&sbinfo->si_rwsem);
20202+
1facf9fc 20203+ seq_printf(m, ",create=");
20204+ pat = au_optstr_wbr_create(v);
20205+ switch (v) {
20206+ case AuWbrCreate_TDP:
20207+ case AuWbrCreate_RR:
20208+ case AuWbrCreate_MFS:
20209+ case AuWbrCreate_PMFS:
20210+ seq_printf(m, pat);
20211+ break;
20212+ case AuWbrCreate_MFSV:
20213+ seq_printf(m, /*pat*/"mfs:%lu",
e49829fe
JR
20214+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
20215+ / MSEC_PER_SEC);
1facf9fc 20216+ break;
20217+ case AuWbrCreate_PMFSV:
20218+ seq_printf(m, /*pat*/"pmfs:%lu",
e49829fe
JR
20219+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
20220+ / MSEC_PER_SEC);
1facf9fc 20221+ break;
20222+ case AuWbrCreate_MFSRR:
20223+ seq_printf(m, /*pat*/"mfsrr:%llu",
20224+ sbinfo->si_wbr_mfs.mfsrr_watermark);
20225+ break;
20226+ case AuWbrCreate_MFSRRV:
20227+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
20228+ sbinfo->si_wbr_mfs.mfsrr_watermark,
e49829fe
JR
20229+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
20230+ / MSEC_PER_SEC);
1facf9fc 20231+ break;
20232+ }
20233+}
20234+
20235+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
20236+{
20237+#ifdef CONFIG_SYSFS
20238+ return 0;
20239+#else
20240+ int err;
20241+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
20242+ aufs_bindex_t bindex, brid;
20243+ struct super_block *sb;
20244+ struct qstr *name;
20245+ struct file *f;
20246+ struct dentry *d, *h_root;
4a4d8108 20247+ struct au_hdentry *hdp;
1facf9fc 20248+
dece6358
AM
20249+ AuRwMustAnyLock(&sbinfo->si_rwsem);
20250+
1facf9fc 20251+ err = 0;
20252+ sb = mnt->mnt_sb;
20253+ f = au_sbi(sb)->si_xib;
20254+ if (!f)
20255+ goto out;
20256+
20257+ /* stop printing the default xino path on the first writable branch */
20258+ h_root = NULL;
20259+ brid = au_xino_brid(sb);
20260+ if (brid >= 0) {
20261+ bindex = au_br_index(sb, brid);
4a4d8108
AM
20262+ hdp = au_di(sb->s_root)->di_hdentry;
20263+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 20264+ }
20265+ d = f->f_dentry;
20266+ name = &d->d_name;
20267+ /* safe ->d_parent because the file is unlinked */
20268+ if (d->d_parent == h_root
20269+ && name->len == len
20270+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
20271+ goto out;
20272+
20273+ seq_puts(seq, ",xino=");
20274+ err = au_xino_path(seq, f);
20275+
4f0767ce 20276+out:
1facf9fc 20277+ return err;
20278+#endif
20279+}
20280+
20281+/* seq_file will re-call me in case of too long string */
20282+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
20283+{
20284+ int err, n;
20285+ unsigned int mnt_flags, v;
20286+ struct super_block *sb;
20287+ struct au_sbinfo *sbinfo;
20288+
20289+#define AuBool(name, str) do { \
20290+ v = au_opt_test(mnt_flags, name); \
20291+ if (v != au_opt_test(AuOpt_Def, name)) \
20292+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
20293+} while (0)
20294+
20295+#define AuStr(name, str) do { \
20296+ v = mnt_flags & AuOptMask_##name; \
20297+ if (v != (AuOpt_Def & AuOptMask_##name)) \
20298+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
20299+} while (0)
20300+
20301+#define AuUInt(name, str, val) do { \
20302+ if (val != AUFS_##name##_DEF) \
20303+ seq_printf(m, "," #str "=%u", val); \
20304+} while (0)
20305+
20306+ /* lock free root dinfo */
20307+ sb = mnt->mnt_sb;
20308+ si_noflush_read_lock(sb);
20309+ sbinfo = au_sbi(sb);
20310+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
20311+
20312+ mnt_flags = au_mntflags(sb);
20313+ if (au_opt_test(mnt_flags, XINO)) {
20314+ err = au_show_xino(m, mnt);
20315+ if (unlikely(err))
20316+ goto out;
20317+ } else
20318+ seq_puts(m, ",noxino");
20319+
20320+ AuBool(TRUNC_XINO, trunc_xino);
20321+ AuStr(UDBA, udba);
dece6358 20322+ AuBool(SHWH, shwh);
1facf9fc 20323+ AuBool(PLINK, plink);
4a4d8108 20324+ AuBool(DIO, dio);
1facf9fc 20325+ /* AuBool(DIRPERM1, dirperm1); */
20326+ /* AuBool(REFROF, refrof); */
20327+
20328+ v = sbinfo->si_wbr_create;
20329+ if (v != AuWbrCreate_Def)
20330+ au_show_wbr_create(m, v, sbinfo);
20331+
20332+ v = sbinfo->si_wbr_copyup;
20333+ if (v != AuWbrCopyup_Def)
20334+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
20335+
20336+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
20337+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
20338+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
20339+
20340+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
20341+
e49829fe 20342+ n = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
1facf9fc 20343+ AuUInt(RDCACHE, rdcache, n);
20344+
20345+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
20346+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
20347+
20348+ AuBool(SUM, sum);
20349+ /* AuBool(SUM_W, wsum); */
20350+ AuBool(WARN_PERM, warn_perm);
20351+ AuBool(VERBOSE, verbose);
20352+
4f0767ce 20353+out:
1facf9fc 20354+ /* be sure to print "br:" last */
20355+ if (!sysaufs_brs) {
20356+ seq_puts(m, ",br:");
20357+ au_show_brs(m, sb);
20358+ }
20359+ si_read_unlock(sb);
20360+ return 0;
20361+
1facf9fc 20362+#undef AuBool
20363+#undef AuStr
4a4d8108 20364+#undef AuUInt
1facf9fc 20365+}
20366+
20367+/* ---------------------------------------------------------------------- */
20368+
20369+/* sum mode which returns the summation for statfs(2) */
20370+
20371+static u64 au_add_till_max(u64 a, u64 b)
20372+{
20373+ u64 old;
20374+
20375+ old = a;
20376+ a += b;
20377+ if (old < a)
20378+ return a;
20379+ return ULLONG_MAX;
20380+}
20381+
20382+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
20383+{
20384+ int err;
20385+ u64 blocks, bfree, bavail, files, ffree;
20386+ aufs_bindex_t bend, bindex, i;
20387+ unsigned char shared;
0c5527e5 20388+ struct vfsmount *h_mnt;
1facf9fc 20389+ struct super_block *h_sb;
20390+
20391+ blocks = 0;
20392+ bfree = 0;
20393+ bavail = 0;
20394+ files = 0;
20395+ ffree = 0;
20396+
20397+ err = 0;
20398+ bend = au_sbend(sb);
20399+ for (bindex = bend; bindex >= 0; bindex--) {
0c5527e5
AM
20400+ h_mnt = au_sbr_mnt(sb, bindex);
20401+ h_sb = h_mnt->mnt_sb;
1facf9fc 20402+ shared = 0;
20403+ for (i = bindex + 1; !shared && i <= bend; i++)
20404+ shared = (au_sbr_sb(sb, i) == h_sb);
20405+ if (shared)
20406+ continue;
20407+
20408+ /* sb->s_root for NFS is unreliable */
0c5527e5 20409+ err = statfs_by_dentry(h_mnt->mnt_root, buf);
1facf9fc 20410+ if (unlikely(err))
20411+ goto out;
20412+
20413+ blocks = au_add_till_max(blocks, buf->f_blocks);
20414+ bfree = au_add_till_max(bfree, buf->f_bfree);
20415+ bavail = au_add_till_max(bavail, buf->f_bavail);
20416+ files = au_add_till_max(files, buf->f_files);
20417+ ffree = au_add_till_max(ffree, buf->f_ffree);
20418+ }
20419+
20420+ buf->f_blocks = blocks;
20421+ buf->f_bfree = bfree;
20422+ buf->f_bavail = bavail;
20423+ buf->f_files = files;
20424+ buf->f_ffree = ffree;
20425+
4f0767ce 20426+out:
1facf9fc 20427+ return err;
20428+}
20429+
20430+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
20431+{
20432+ int err;
20433+ struct super_block *sb;
20434+
20435+ /* lock free root dinfo */
20436+ sb = dentry->d_sb;
20437+ si_noflush_read_lock(sb);
0c5527e5 20438+ if (!au_opt_test(au_mntflags(sb), SUM))
1facf9fc 20439+ /* sb->s_root for NFS is unreliable */
0c5527e5
AM
20440+ err = statfs_by_dentry(au_sbr_mnt(sb, 0)->mnt_root, buf);
20441+ else
1facf9fc 20442+ err = au_statfs_sum(sb, buf);
20443+ si_read_unlock(sb);
20444+
20445+ if (!err) {
20446+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 20447+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 20448+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
20449+ }
20450+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
20451+
20452+ return err;
20453+}
20454+
20455+/* ---------------------------------------------------------------------- */
20456+
1facf9fc 20457+/* final actions when unmounting a file system */
20458+static void aufs_put_super(struct super_block *sb)
20459+{
20460+ struct au_sbinfo *sbinfo;
20461+
20462+ sbinfo = au_sbi(sb);
20463+ if (!sbinfo)
20464+ return;
20465+
1facf9fc 20466+ dbgaufs_si_fin(sbinfo);
20467+ kobject_put(&sbinfo->si_kobj);
20468+}
20469+
20470+/* ---------------------------------------------------------------------- */
20471+
20472+/*
20473+ * refresh dentry and inode at remount time.
20474+ */
20475+static int do_refresh(struct dentry *dentry, mode_t type,
20476+ unsigned int dir_flags)
20477+{
20478+ int err;
20479+ struct dentry *parent;
20480+
20481+ di_write_lock_child(dentry);
20482+ parent = dget_parent(dentry);
20483+ di_read_lock_parent(parent, AuLock_IR);
20484+
20485+ /* returns the number of positive dentries */
20486+ err = au_refresh_hdentry(dentry, type);
20487+ if (err >= 0) {
20488+ struct inode *inode = dentry->d_inode;
20489+ err = au_refresh_hinode(inode, dentry);
20490+ if (!err && type == S_IFDIR)
4a4d8108 20491+ au_hn_reset(inode, dir_flags);
1facf9fc 20492+ }
20493+ if (unlikely(err))
4a4d8108
AM
20494+ pr_err("unrecoverable error %d, %.*s\n",
20495+ err, AuDLNPair(dentry));
1facf9fc 20496+
20497+ di_read_unlock(parent, AuLock_IR);
20498+ dput(parent);
20499+ di_write_unlock(dentry);
20500+
20501+ return err;
20502+}
20503+
20504+static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
20505+{
20506+ return S_ISDIR(dentry->d_inode->i_mode);
20507+}
20508+
20509+/* gave up consolidating with refresh_nondir() */
20510+static int refresh_dir(struct dentry *root, unsigned int sigen)
20511+{
20512+ int err, i, j, ndentry, e;
20513+ struct au_dcsub_pages dpages;
20514+ struct au_dpage *dpage;
20515+ struct dentry **dentries;
20516+ struct inode *inode;
20517+ const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
20518+
20519+ err = 0;
20520+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20521+ if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20522+ ii_write_lock_child(inode);
20523+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
20524+ ii_write_unlock(inode);
20525+ if (unlikely(e)) {
20526+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
20527+ if (!err)
20528+ err = e;
20529+ /* go on even if err */
20530+ }
20531+ }
20532+
20533+ e = au_dpages_init(&dpages, GFP_NOFS);
20534+ if (unlikely(e)) {
20535+ if (!err)
20536+ err = e;
20537+ goto out;
20538+ }
20539+ e = au_dcsub_pages(&dpages, root, test_dir, NULL);
20540+ if (unlikely(e)) {
20541+ if (!err)
20542+ err = e;
20543+ goto out_dpages;
20544+ }
20545+
20546+ for (i = 0; !e && i < dpages.ndpage; i++) {
20547+ dpage = dpages.dpages + i;
20548+ dentries = dpage->dentries;
20549+ ndentry = dpage->ndentry;
20550+ for (j = 0; !e && j < ndentry; j++) {
20551+ struct dentry *d;
20552+
20553+ d = dentries[j];
20554+ au_dbg_verify_dir_parent(d, sigen);
20555+ if (au_digen(d) != sigen) {
20556+ e = do_refresh(d, S_IFDIR, flags);
20557+ if (unlikely(e && !err))
20558+ err = e;
20559+ /* break on err */
20560+ }
20561+ }
20562+ }
20563+
4f0767ce 20564+out_dpages:
1facf9fc 20565+ au_dpages_free(&dpages);
4f0767ce 20566+out:
1facf9fc 20567+ return err;
20568+}
20569+
20570+static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
20571+{
20572+ return !S_ISDIR(dentry->d_inode->i_mode);
20573+}
20574+
20575+static int refresh_nondir(struct dentry *root, unsigned int sigen,
20576+ int do_dentry)
20577+{
20578+ int err, i, j, ndentry, e;
20579+ struct au_dcsub_pages dpages;
20580+ struct au_dpage *dpage;
20581+ struct dentry **dentries;
20582+ struct inode *inode;
20583+
20584+ err = 0;
20585+ list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
20586+ if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
20587+ ii_write_lock_child(inode);
20588+ e = au_refresh_hinode_self(inode, /*do_attr*/1);
20589+ ii_write_unlock(inode);
20590+ if (unlikely(e)) {
20591+ AuDbg("e %d, i%lu\n", e, inode->i_ino);
20592+ if (!err)
20593+ err = e;
20594+ /* go on even if err */
20595+ }
20596+ }
20597+
20598+ if (!do_dentry)
20599+ goto out;
20600+
20601+ e = au_dpages_init(&dpages, GFP_NOFS);
20602+ if (unlikely(e)) {
20603+ if (!err)
20604+ err = e;
20605+ goto out;
20606+ }
20607+ e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
20608+ if (unlikely(e)) {
20609+ if (!err)
20610+ err = e;
20611+ goto out_dpages;
20612+ }
20613+
20614+ for (i = 0; i < dpages.ndpage; i++) {
20615+ dpage = dpages.dpages + i;
20616+ dentries = dpage->dentries;
20617+ ndentry = dpage->ndentry;
20618+ for (j = 0; j < ndentry; j++) {
20619+ struct dentry *d;
20620+
20621+ d = dentries[j];
20622+ au_dbg_verify_nondir_parent(d, sigen);
20623+ inode = d->d_inode;
20624+ if (inode && au_digen(d) != sigen) {
20625+ e = do_refresh(d, inode->i_mode & S_IFMT,
20626+ /*dir_flags*/0);
20627+ if (unlikely(e && !err))
20628+ err = e;
20629+ /* go on even err */
20630+ }
20631+ }
20632+ }
20633+
4f0767ce 20634+out_dpages:
1facf9fc 20635+ au_dpages_free(&dpages);
4f0767ce 20636+out:
1facf9fc 20637+ return err;
20638+}
20639+
20640+static void au_remount_refresh(struct super_block *sb, unsigned int flags)
20641+{
20642+ int err;
20643+ unsigned int sigen;
20644+ struct au_sbinfo *sbinfo;
20645+ struct dentry *root;
20646+ struct inode *inode;
20647+
20648+ au_sigen_inc(sb);
20649+ sigen = au_sigen(sb);
20650+ sbinfo = au_sbi(sb);
20651+ au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
20652+
20653+ root = sb->s_root;
20654+ DiMustNoWaiters(root);
20655+ inode = root->d_inode;
20656+ IiMustNoWaiters(inode);
4a4d8108 20657+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 20658+ di_write_unlock(root);
20659+
20660+ err = refresh_dir(root, sigen);
20661+ if (unlikely(err)) {
20662+ au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
4a4d8108
AM
20663+ pr_warning("Refreshing directories failed, ignored (%d)\n",
20664+ err);
1facf9fc 20665+ }
20666+
20667+ if (au_ftest_opts(flags, REFRESH_NONDIR)) {
20668+ err = refresh_nondir(root, sigen, !err);
20669+ if (unlikely(err))
4a4d8108
AM
20670+ pr_warning("Refreshing non-directories failed, ignored"
20671+ "(%d)\n", err);
1facf9fc 20672+ }
20673+
20674+ /* aufs_write_lock() calls ..._child() */
20675+ di_write_lock_child(root);
20676+ au_cpup_attr_all(root->d_inode, /*force*/1);
20677+}
20678+
20679+/* stop extra interpretation of errno in mount(8), and strange error messages */
20680+static int cvt_err(int err)
20681+{
20682+ AuTraceErr(err);
20683+
20684+ switch (err) {
20685+ case -ENOENT:
20686+ case -ENOTDIR:
20687+ case -EEXIST:
20688+ case -EIO:
20689+ err = -EINVAL;
20690+ }
20691+ return err;
20692+}
20693+
20694+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
20695+{
4a4d8108
AM
20696+ int err, do_dx;
20697+ unsigned int mntflags;
1facf9fc 20698+ struct au_opts opts;
20699+ struct dentry *root;
20700+ struct inode *inode;
20701+ struct au_sbinfo *sbinfo;
20702+
20703+ err = 0;
20704+ root = sb->s_root;
20705+ if (!data || !*data) {
e49829fe
JR
20706+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
20707+ if (!err) {
20708+ di_write_lock_child(root);
20709+ err = au_opts_verify(sb, *flags, /*pending*/0);
20710+ aufs_write_unlock(root);
20711+ }
1facf9fc 20712+ goto out;
20713+ }
20714+
20715+ err = -ENOMEM;
20716+ memset(&opts, 0, sizeof(opts));
20717+ opts.opt = (void *)__get_free_page(GFP_NOFS);
20718+ if (unlikely(!opts.opt))
20719+ goto out;
20720+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
20721+ opts.flags = AuOpts_REMOUNT;
20722+ opts.sb_flags = *flags;
20723+
20724+ /* parse it before aufs lock */
20725+ err = au_opts_parse(sb, data, &opts);
20726+ if (unlikely(err))
20727+ goto out_opts;
20728+
20729+ sbinfo = au_sbi(sb);
20730+ inode = root->d_inode;
20731+ mutex_lock(&inode->i_mutex);
e49829fe
JR
20732+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
20733+ if (unlikely(err))
20734+ goto out_mtx;
20735+ di_write_lock_child(root);
1facf9fc 20736+
20737+ /* au_opts_remount() may return an error */
20738+ err = au_opts_remount(sb, &opts);
20739+ au_opts_free(&opts);
20740+
20741+ if (au_ftest_opts(opts.flags, REFRESH_DIR)
20742+ || au_ftest_opts(opts.flags, REFRESH_NONDIR))
20743+ au_remount_refresh(sb, opts.flags);
20744+
4a4d8108
AM
20745+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
20746+ mntflags = au_mntflags(sb);
20747+ do_dx = !!au_opt_test(mntflags, DIO);
20748+ au_dy_arefresh(do_dx);
20749+ }
20750+
1facf9fc 20751+ aufs_write_unlock(root);
953406b4 20752+
e49829fe
JR
20753+out_mtx:
20754+ mutex_unlock(&inode->i_mutex);
4f0767ce 20755+out_opts:
1facf9fc 20756+ free_page((unsigned long)opts.opt);
4f0767ce 20757+out:
1facf9fc 20758+ err = cvt_err(err);
20759+ AuTraceErr(err);
20760+ return err;
20761+}
20762+
4a4d8108 20763+static const struct super_operations aufs_sop = {
1facf9fc 20764+ .alloc_inode = aufs_alloc_inode,
20765+ .destroy_inode = aufs_destroy_inode,
b752ccd1 20766+ /* always deleting, no clearing */
1facf9fc 20767+ .drop_inode = generic_delete_inode,
20768+ .show_options = aufs_show_options,
20769+ .statfs = aufs_statfs,
20770+ .put_super = aufs_put_super,
20771+ .remount_fs = aufs_remount_fs
20772+};
20773+
20774+/* ---------------------------------------------------------------------- */
20775+
20776+static int alloc_root(struct super_block *sb)
20777+{
20778+ int err;
20779+ struct inode *inode;
20780+ struct dentry *root;
20781+
20782+ err = -ENOMEM;
20783+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
20784+ err = PTR_ERR(inode);
20785+ if (IS_ERR(inode))
20786+ goto out;
20787+
20788+ inode->i_op = &aufs_dir_iop;
20789+ inode->i_fop = &aufs_dir_fop;
20790+ inode->i_mode = S_IFDIR;
20791+ inode->i_nlink = 2;
20792+ unlock_new_inode(inode);
20793+
20794+ root = d_alloc_root(inode);
20795+ if (unlikely(!root))
20796+ goto out_iput;
20797+ err = PTR_ERR(root);
20798+ if (IS_ERR(root))
20799+ goto out_iput;
20800+
4a4d8108 20801+ err = au_di_init(root);
1facf9fc 20802+ if (!err) {
20803+ sb->s_root = root;
20804+ return 0; /* success */
20805+ }
20806+ dput(root);
20807+ goto out; /* do not iput */
20808+
4f0767ce 20809+out_iput:
1facf9fc 20810+ iget_failed(inode);
4f0767ce 20811+out:
1facf9fc 20812+ return err;
20813+
20814+}
20815+
20816+static int aufs_fill_super(struct super_block *sb, void *raw_data,
20817+ int silent __maybe_unused)
20818+{
20819+ int err;
20820+ struct au_opts opts;
20821+ struct dentry *root;
20822+ struct inode *inode;
20823+ char *arg = raw_data;
20824+
20825+ if (unlikely(!arg || !*arg)) {
20826+ err = -EINVAL;
4a4d8108 20827+ pr_err("no arg\n");
1facf9fc 20828+ goto out;
20829+ }
20830+
20831+ err = -ENOMEM;
20832+ memset(&opts, 0, sizeof(opts));
20833+ opts.opt = (void *)__get_free_page(GFP_NOFS);
20834+ if (unlikely(!opts.opt))
20835+ goto out;
20836+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
20837+ opts.sb_flags = sb->s_flags;
20838+
20839+ err = au_si_alloc(sb);
20840+ if (unlikely(err))
20841+ goto out_opts;
20842+
20843+ /* all timestamps always follow the ones on the branch */
20844+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
20845+ sb->s_op = &aufs_sop;
20846+ sb->s_magic = AUFS_SUPER_MAGIC;
20847+ sb->s_maxbytes = 0;
20848+ au_export_init(sb);
20849+
20850+ err = alloc_root(sb);
20851+ if (unlikely(err)) {
20852+ si_write_unlock(sb);
20853+ goto out_info;
20854+ }
20855+ root = sb->s_root;
20856+ inode = root->d_inode;
20857+
20858+ /*
20859+ * actually we can parse options regardless aufs lock here.
20860+ * but at remount time, parsing must be done before aufs lock.
20861+ * so we follow the same rule.
20862+ */
20863+ ii_write_lock_parent(inode);
20864+ aufs_write_unlock(root);
20865+ err = au_opts_parse(sb, arg, &opts);
20866+ if (unlikely(err))
20867+ goto out_root;
20868+
20869+ /* lock vfs_inode first, then aufs. */
20870+ mutex_lock(&inode->i_mutex);
1facf9fc 20871+ aufs_write_lock(root);
20872+ err = au_opts_mount(sb, &opts);
20873+ au_opts_free(&opts);
1facf9fc 20874+ aufs_write_unlock(root);
20875+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
20876+ if (!err)
20877+ goto out_opts; /* success */
1facf9fc 20878+
4f0767ce 20879+out_root:
1facf9fc 20880+ dput(root);
20881+ sb->s_root = NULL;
4f0767ce 20882+out_info:
1facf9fc 20883+ kobject_put(&au_sbi(sb)->si_kobj);
20884+ sb->s_fs_info = NULL;
4f0767ce 20885+out_opts:
1facf9fc 20886+ free_page((unsigned long)opts.opt);
4f0767ce 20887+out:
1facf9fc 20888+ AuTraceErr(err);
20889+ err = cvt_err(err);
20890+ AuTraceErr(err);
20891+ return err;
20892+}
20893+
20894+/* ---------------------------------------------------------------------- */
20895+
20896+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
20897+ const char *dev_name __maybe_unused, void *raw_data,
20898+ struct vfsmount *mnt)
20899+{
20900+ int err;
20901+ struct super_block *sb;
20902+
20903+ /* all timestamps always follow the ones on the branch */
20904+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
20905+ err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
20906+ if (!err) {
20907+ sb = mnt->mnt_sb;
e49829fe 20908+ si_write_lock(sb, !AuLock_FLUSH);
1facf9fc 20909+ sysaufs_brs_add(sb, 0);
20910+ si_write_unlock(sb);
e49829fe 20911+ au_sbilist_add(sb);
1facf9fc 20912+ }
20913+ return err;
20914+}
20915+
e49829fe
JR
20916+static void aufs_kill_sb(struct super_block *sb)
20917+{
20918+ struct au_sbinfo *sbinfo;
20919+
20920+ sbinfo = au_sbi(sb);
20921+ if (sbinfo) {
20922+ au_sbilist_del(sb);
20923+ aufs_write_lock(sb->s_root);
20924+ if (sbinfo->si_wbr_create_ops->fin)
20925+ sbinfo->si_wbr_create_ops->fin(sb);
20926+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
20927+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
20928+ au_remount_refresh(sb, /*flags*/0);
20929+ }
20930+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
20931+ au_plink_put(sb, /*verbose*/1);
20932+ au_xino_clr(sb);
20933+ aufs_write_unlock(sb->s_root);
20934+
20935+ au_plink_maint_leave(sbinfo);
20936+ au_nwt_flush(&sbinfo->si_nowait);
20937+ }
20938+ generic_shutdown_super(sb);
20939+}
20940+
1facf9fc 20941+struct file_system_type aufs_fs_type = {
20942+ .name = AUFS_FSTYPE,
20943+ .fs_flags =
20944+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
20945+ | FS_REVAL_DOT, /* for NFS branch and udba */
20946+ .get_sb = aufs_get_sb,
e49829fe 20947+ .kill_sb = aufs_kill_sb,
1facf9fc 20948+ /* no need to __module_get() and module_put(). */
20949+ .owner = THIS_MODULE,
20950+};
e49829fe 20951--- /dev/null
0c5527e5 20952+++ linux-2.6/fs/aufs/super.h 2010-10-25 14:20:44.000000000 +0200
e49829fe 20953@@ -0,0 +1,488 @@
1facf9fc 20954+/*
4a4d8108 20955+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 20956+ *
20957+ * This program, aufs is free software; you can redistribute it and/or modify
20958+ * it under the terms of the GNU General Public License as published by
20959+ * the Free Software Foundation; either version 2 of the License, or
20960+ * (at your option) any later version.
dece6358
AM
20961+ *
20962+ * This program is distributed in the hope that it will be useful,
20963+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20964+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20965+ * GNU General Public License for more details.
20966+ *
20967+ * You should have received a copy of the GNU General Public License
20968+ * along with this program; if not, write to the Free Software
20969+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20970+ */
20971+
20972+/*
20973+ * super_block operations
20974+ */
20975+
20976+#ifndef __AUFS_SUPER_H__
20977+#define __AUFS_SUPER_H__
20978+
20979+#ifdef __KERNEL__
20980+
20981+#include <linux/fs.h>
1facf9fc 20982+#include <linux/aufs_type.h>
20983+#include "rwsem.h"
20984+#include "spl.h"
20985+#include "wkq.h"
20986+
20987+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
20988+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
20989+ loff_t *);
20990+
20991+/* policies to select one among multiple writable branches */
20992+struct au_wbr_copyup_operations {
20993+ int (*copyup)(struct dentry *dentry);
20994+};
20995+
20996+struct au_wbr_create_operations {
20997+ int (*create)(struct dentry *dentry, int isdir);
20998+ int (*init)(struct super_block *sb);
20999+ int (*fin)(struct super_block *sb);
21000+};
21001+
21002+struct au_wbr_mfs {
21003+ struct mutex mfs_lock; /* protect this structure */
21004+ unsigned long mfs_jiffy;
21005+ unsigned long mfs_expire;
21006+ aufs_bindex_t mfs_bindex;
21007+
21008+ unsigned long long mfsrr_bytes;
21009+ unsigned long long mfsrr_watermark;
21010+};
21011+
1facf9fc 21012+struct au_branch;
21013+struct au_sbinfo {
21014+ /* nowait tasks in the system-wide workqueue */
21015+ struct au_nowait_tasks si_nowait;
21016+
b752ccd1
AM
21017+ /*
21018+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
21019+ * rwsem for au_sbinfo is necessary.
21020+ */
dece6358 21021+ struct au_rwsem si_rwsem;
1facf9fc 21022+
b752ccd1
AM
21023+ /* prevent recursive locking in deleting inode */
21024+ struct {
21025+ unsigned long *bitmap;
21026+ spinlock_t tree_lock;
21027+ struct radix_tree_root tree;
21028+ } au_si_pid;
21029+
1facf9fc 21030+ /* branch management */
21031+ unsigned int si_generation;
21032+
21033+ /* see above flags */
21034+ unsigned char au_si_status;
21035+
21036+ aufs_bindex_t si_bend;
21037+ aufs_bindex_t si_last_br_id;
21038+ struct au_branch **si_branch;
21039+
21040+ /* policy to select a writable branch */
21041+ unsigned char si_wbr_copyup;
21042+ unsigned char si_wbr_create;
21043+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
21044+ struct au_wbr_create_operations *si_wbr_create_ops;
21045+
21046+ /* round robin */
21047+ atomic_t si_wbr_rr_next;
21048+
21049+ /* most free space */
21050+ struct au_wbr_mfs si_wbr_mfs;
21051+
21052+ /* mount flags */
21053+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
21054+ unsigned int si_mntflags;
21055+
21056+ /* external inode number (bitmap and translation table) */
21057+ au_readf_t si_xread;
21058+ au_writef_t si_xwrite;
21059+ struct file *si_xib;
21060+ struct mutex si_xib_mtx; /* protect xib members */
21061+ unsigned long *si_xib_buf;
21062+ unsigned long si_xib_last_pindex;
21063+ int si_xib_next_bit;
21064+ aufs_bindex_t si_xino_brid;
21065+ /* reserved for future use */
21066+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
21067+
21068+#ifdef CONFIG_AUFS_EXPORT
21069+ /* i_generation */
21070+ struct file *si_xigen;
21071+ atomic_t si_xigen_next;
21072+#endif
21073+
21074+ /* vdir parameters */
e49829fe 21075+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 21076+ unsigned int si_rdblk; /* deblk size */
21077+ unsigned int si_rdhash; /* hash size */
21078+
21079+ /*
21080+ * If the number of whiteouts are larger than si_dirwh, leave all of
21081+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
21082+ * future fsck.aufs or kernel thread will remove them later.
21083+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
21084+ */
21085+ unsigned int si_dirwh;
21086+
21087+ /*
21088+ * rename(2) a directory with all children.
21089+ */
21090+ /* reserved for future use */
21091+ /* int si_rendir; */
21092+
21093+ /* pseudo_link list */
21094+ struct au_splhead si_plink;
21095+ wait_queue_head_t si_plink_wq;
4a4d8108 21096+ spinlock_t si_plink_maint_lock;
e49829fe 21097+ pid_t si_plink_maint_pid;
1facf9fc 21098+
21099+ /*
21100+ * sysfs and lifetime management.
21101+ * this is not a small structure and it may be a waste of memory in case
21102+ * of sysfs is disabled, particulary when many aufs-es are mounted.
21103+ * but using sysfs is majority.
21104+ */
21105+ struct kobject si_kobj;
21106+#ifdef CONFIG_DEBUG_FS
21107+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
21108+#ifdef CONFIG_AUFS_EXPORT
21109+ struct dentry *si_dbgaufs_xigen;
21110+#endif
21111+#endif
21112+
e49829fe
JR
21113+#ifdef CONFIG_AUFS_SBILIST
21114+ struct list_head si_list;
21115+#endif
21116+
1facf9fc 21117+ /* dirty, necessary for unmounting, sysfs and sysrq */
21118+ struct super_block *si_sb;
21119+};
21120+
dece6358
AM
21121+/* sbinfo status flags */
21122+/*
21123+ * set true when refresh_dirs() failed at remount time.
21124+ * then try refreshing dirs at access time again.
21125+ * if it is false, refreshing dirs at access time is unnecesary
21126+ */
21127+#define AuSi_FAILED_REFRESH_DIRS 1
dece6358
AM
21128+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
21129+ unsigned int flag)
21130+{
21131+ AuRwMustAnyLock(&sbi->si_rwsem);
21132+ return sbi->au_si_status & flag;
21133+}
21134+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
21135+#define au_fset_si(sbinfo, name) do { \
21136+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
21137+ (sbinfo)->au_si_status |= AuSi_##name; \
21138+} while (0)
21139+#define au_fclr_si(sbinfo, name) do { \
21140+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
21141+ (sbinfo)->au_si_status &= ~AuSi_##name; \
21142+} while (0)
21143+
1facf9fc 21144+/* ---------------------------------------------------------------------- */
21145+
21146+/* policy to select one among writable branches */
4a4d8108
AM
21147+#define AuWbrCopyup(sbinfo, ...) \
21148+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
21149+#define AuWbrCreate(sbinfo, ...) \
21150+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 21151+
21152+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
21153+#define AuLock_DW 1 /* write-lock dentry */
21154+#define AuLock_IR (1 << 1) /* read-lock inode */
21155+#define AuLock_IW (1 << 2) /* write-lock inode */
21156+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
21157+#define AuLock_DIR (1 << 4) /* target is a dir */
e49829fe
JR
21158+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
21159+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
1facf9fc 21160+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
21161+#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
21162+#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
21163+
21164+/* ---------------------------------------------------------------------- */
21165+
21166+/* super.c */
21167+extern struct file_system_type aufs_fs_type;
21168+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
21169+
21170+/* sbinfo.c */
21171+void au_si_free(struct kobject *kobj);
21172+int au_si_alloc(struct super_block *sb);
21173+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
21174+
21175+unsigned int au_sigen_inc(struct super_block *sb);
21176+aufs_bindex_t au_new_br_id(struct super_block *sb);
21177+
e49829fe
JR
21178+int si_read_lock(struct super_block *sb, int flags);
21179+int si_write_lock(struct super_block *sb, int flags);
21180+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 21181+void aufs_read_unlock(struct dentry *dentry, int flags);
21182+void aufs_write_lock(struct dentry *dentry);
21183+void aufs_write_unlock(struct dentry *dentry);
e49829fe 21184+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 21185+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
21186+
b752ccd1
AM
21187+int si_pid_test_slow(struct super_block *sb);
21188+void si_pid_set_slow(struct super_block *sb);
21189+void si_pid_clr_slow(struct super_block *sb);
21190+
1facf9fc 21191+/* wbr_policy.c */
21192+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
21193+extern struct au_wbr_create_operations au_wbr_create_ops[];
21194+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
21195+
21196+/* ---------------------------------------------------------------------- */
21197+
21198+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
21199+{
21200+ return sb->s_fs_info;
21201+}
21202+
21203+/* ---------------------------------------------------------------------- */
21204+
21205+#ifdef CONFIG_AUFS_EXPORT
21206+void au_export_init(struct super_block *sb);
21207+
b752ccd1 21208+static inline int au_test_nfsd(void)
1facf9fc 21209+{
b752ccd1
AM
21210+ struct task_struct *tsk = current;
21211+
21212+ return (tsk->flags & PF_KTHREAD)
21213+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 21214+}
21215+
b752ccd1 21216+void au_xigen_inc(struct inode *inode);
1facf9fc 21217+int au_xigen_new(struct inode *inode);
21218+int au_xigen_set(struct super_block *sb, struct file *base);
21219+void au_xigen_clr(struct super_block *sb);
21220+
21221+static inline int au_busy_or_stale(void)
21222+{
b752ccd1 21223+ if (!au_test_nfsd())
1facf9fc 21224+ return -EBUSY;
21225+ return -ESTALE;
21226+}
21227+#else
4a4d8108 21228+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
21229+AuStubInt0(au_test_nfsd, void)
21230+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
21231+AuStubInt0(au_xigen_new, struct inode *inode)
21232+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
21233+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 21234+static inline int au_busy_or_stale(void)
21235+{
21236+ return -EBUSY;
21237+}
21238+#endif /* CONFIG_AUFS_EXPORT */
21239+
21240+/* ---------------------------------------------------------------------- */
21241+
e49829fe
JR
21242+#ifdef CONFIG_AUFS_SBILIST
21243+/* module.c */
21244+extern struct au_splhead au_sbilist;
21245+
21246+static inline void au_sbilist_init(void)
21247+{
21248+ au_spl_init(&au_sbilist);
21249+}
21250+
21251+static inline void au_sbilist_add(struct super_block *sb)
21252+{
21253+ au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
21254+}
21255+
21256+static inline void au_sbilist_del(struct super_block *sb)
21257+{
21258+ au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
21259+}
21260+#else
21261+AuStubVoid(au_sbilist_init, void)
21262+AuStubVoid(au_sbilist_add, struct super_block*)
21263+AuStubVoid(au_sbilist_del, struct super_block*)
21264+#endif
21265+
21266+/* ---------------------------------------------------------------------- */
21267+
1facf9fc 21268+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
21269+{
dece6358
AM
21270+ /*
21271+ * This function is a dynamic '__init' fucntion actually,
21272+ * so the tiny check for si_rwsem is unnecessary.
21273+ */
21274+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 21275+#ifdef CONFIG_DEBUG_FS
21276+ sbinfo->si_dbgaufs = NULL;
21277+ sbinfo->si_dbgaufs_xib = NULL;
21278+#ifdef CONFIG_AUFS_EXPORT
21279+ sbinfo->si_dbgaufs_xigen = NULL;
21280+#endif
21281+#endif
21282+}
21283+
21284+/* ---------------------------------------------------------------------- */
21285+
b752ccd1
AM
21286+static inline pid_t si_pid_bit(void)
21287+{
21288+ /* the origin of pid is 1, but the bitmap's is 0 */
21289+ return current->pid - 1;
21290+}
21291+
21292+static inline int si_pid_test(struct super_block *sb)
21293+{
21294+ pid_t bit = si_pid_bit();
21295+ if (bit < PID_MAX_DEFAULT)
21296+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21297+ else
21298+ return si_pid_test_slow(sb);
21299+}
21300+
21301+static inline void si_pid_set(struct super_block *sb)
21302+{
21303+ pid_t bit = si_pid_bit();
21304+ if (bit < PID_MAX_DEFAULT) {
21305+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21306+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21307+ /* smp_mb(); */
21308+ } else
21309+ si_pid_set_slow(sb);
21310+}
21311+
21312+static inline void si_pid_clr(struct super_block *sb)
21313+{
21314+ pid_t bit = si_pid_bit();
21315+ if (bit < PID_MAX_DEFAULT) {
21316+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
21317+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
21318+ /* smp_mb(); */
21319+ } else
21320+ si_pid_clr_slow(sb);
21321+}
21322+
21323+/* ---------------------------------------------------------------------- */
21324+
1facf9fc 21325+/* lock superblock. mainly for entry point functions */
21326+/*
b752ccd1
AM
21327+ * __si_read_lock, __si_write_lock,
21328+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 21329+ */
b752ccd1 21330+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 21331+
dece6358
AM
21332+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
21333+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
21334+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
21335+
b752ccd1
AM
21336+static inline void si_noflush_read_lock(struct super_block *sb)
21337+{
21338+ __si_read_lock(sb);
21339+ si_pid_set(sb);
21340+}
21341+
21342+static inline int si_noflush_read_trylock(struct super_block *sb)
21343+{
21344+ int locked = __si_read_trylock(sb);
21345+ if (locked)
21346+ si_pid_set(sb);
21347+ return locked;
21348+}
21349+
21350+static inline void si_noflush_write_lock(struct super_block *sb)
21351+{
21352+ __si_write_lock(sb);
21353+ si_pid_set(sb);
21354+}
21355+
21356+static inline int si_noflush_write_trylock(struct super_block *sb)
21357+{
21358+ int locked = __si_write_trylock(sb);
21359+ if (locked)
21360+ si_pid_set(sb);
21361+ return locked;
21362+}
21363+
e49829fe 21364+#if 0 /* unused */
1facf9fc 21365+static inline int si_read_trylock(struct super_block *sb, int flags)
21366+{
21367+ if (au_ftest_lock(flags, FLUSH))
21368+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21369+ return si_noflush_read_trylock(sb);
21370+}
e49829fe 21371+#endif
1facf9fc 21372+
b752ccd1
AM
21373+static inline void si_read_unlock(struct super_block *sb)
21374+{
21375+ si_pid_clr(sb);
21376+ __si_read_unlock(sb);
21377+}
21378+
b752ccd1 21379+#if 0 /* unused */
1facf9fc 21380+static inline int si_write_trylock(struct super_block *sb, int flags)
21381+{
21382+ if (au_ftest_lock(flags, FLUSH))
21383+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21384+ return si_noflush_write_trylock(sb);
21385+}
b752ccd1
AM
21386+#endif
21387+
21388+static inline void si_write_unlock(struct super_block *sb)
21389+{
21390+ si_pid_clr(sb);
21391+ __si_write_unlock(sb);
21392+}
21393+
21394+#if 0 /* unused */
21395+static inline void si_downgrade_lock(struct super_block *sb)
21396+{
21397+ __si_downgrade_lock(sb);
21398+}
21399+#endif
1facf9fc 21400+
21401+/* ---------------------------------------------------------------------- */
21402+
21403+static inline aufs_bindex_t au_sbend(struct super_block *sb)
21404+{
dece6358 21405+ SiMustAnyLock(sb);
1facf9fc 21406+ return au_sbi(sb)->si_bend;
21407+}
21408+
21409+static inline unsigned int au_mntflags(struct super_block *sb)
21410+{
dece6358 21411+ SiMustAnyLock(sb);
1facf9fc 21412+ return au_sbi(sb)->si_mntflags;
21413+}
21414+
21415+static inline unsigned int au_sigen(struct super_block *sb)
21416+{
dece6358 21417+ SiMustAnyLock(sb);
1facf9fc 21418+ return au_sbi(sb)->si_generation;
21419+}
21420+
21421+static inline struct au_branch *au_sbr(struct super_block *sb,
21422+ aufs_bindex_t bindex)
21423+{
dece6358 21424+ SiMustAnyLock(sb);
1facf9fc 21425+ return au_sbi(sb)->si_branch[0 + bindex];
21426+}
21427+
21428+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
21429+{
dece6358 21430+ SiMustWriteLock(sb);
1facf9fc 21431+ au_sbi(sb)->si_xino_brid = brid;
21432+}
21433+
21434+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
21435+{
dece6358 21436+ SiMustAnyLock(sb);
1facf9fc 21437+ return au_sbi(sb)->si_xino_brid;
21438+}
21439+
21440+#endif /* __KERNEL__ */
21441+#endif /* __AUFS_SUPER_H__ */
e49829fe 21442--- /dev/null
0c5527e5 21443+++ linux-2.6/fs/aufs/sysaufs.c 2010-10-25 14:20:44.000000000 +0200
4a4d8108 21444@@ -0,0 +1,107 @@
1facf9fc 21445+/*
4a4d8108 21446+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21447+ *
21448+ * This program, aufs is free software; you can redistribute it and/or modify
21449+ * it under the terms of the GNU General Public License as published by
21450+ * the Free Software Foundation; either version 2 of the License, or
21451+ * (at your option) any later version.
dece6358
AM
21452+ *
21453+ * This program is distributed in the hope that it will be useful,
21454+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21455+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21456+ * GNU General Public License for more details.
21457+ *
21458+ * You should have received a copy of the GNU General Public License
21459+ * along with this program; if not, write to the Free Software
21460+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21461+ */
21462+
21463+/*
21464+ * sysfs interface and lifetime management
21465+ * they are necessary regardless sysfs is disabled.
21466+ */
21467+
21468+#include <linux/fs.h>
21469+#include <linux/random.h>
21470+#include <linux/sysfs.h>
21471+#include "aufs.h"
21472+
21473+unsigned long sysaufs_si_mask;
e49829fe 21474+struct kset *sysaufs_kset;
1facf9fc 21475+
21476+#define AuSiAttr(_name) { \
21477+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
21478+ .show = sysaufs_si_##_name, \
21479+}
21480+
21481+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
21482+struct attribute *sysaufs_si_attrs[] = {
21483+ &sysaufs_si_attr_xi_path.attr,
21484+ NULL,
21485+};
21486+
4a4d8108 21487+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 21488+ .show = sysaufs_si_show
21489+};
21490+
21491+static struct kobj_type au_sbi_ktype = {
21492+ .release = au_si_free,
21493+ .sysfs_ops = &au_sbi_ops,
21494+ .default_attrs = sysaufs_si_attrs
21495+};
21496+
21497+/* ---------------------------------------------------------------------- */
21498+
21499+int sysaufs_si_init(struct au_sbinfo *sbinfo)
21500+{
21501+ int err;
21502+
e49829fe 21503+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 21504+ /* cf. sysaufs_name() */
21505+ err = kobject_init_and_add
e49829fe 21506+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 21507+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
21508+
21509+ dbgaufs_si_null(sbinfo);
21510+ if (!err) {
21511+ err = dbgaufs_si_init(sbinfo);
21512+ if (unlikely(err))
21513+ kobject_put(&sbinfo->si_kobj);
21514+ }
21515+ return err;
21516+}
21517+
21518+void sysaufs_fin(void)
21519+{
21520+ dbgaufs_fin();
e49829fe
JR
21521+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
21522+ kset_unregister(sysaufs_kset);
1facf9fc 21523+}
21524+
21525+int __init sysaufs_init(void)
21526+{
21527+ int err;
21528+
21529+ do {
21530+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
21531+ } while (!sysaufs_si_mask);
21532+
4a4d8108 21533+ err = -EINVAL;
e49829fe
JR
21534+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
21535+ if (unlikely(!sysaufs_kset))
4a4d8108 21536+ goto out;
e49829fe
JR
21537+ err = PTR_ERR(sysaufs_kset);
21538+ if (IS_ERR(sysaufs_kset))
1facf9fc 21539+ goto out;
e49829fe 21540+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 21541+ if (unlikely(err)) {
e49829fe 21542+ kset_unregister(sysaufs_kset);
1facf9fc 21543+ goto out;
21544+ }
21545+
21546+ err = dbgaufs_init();
21547+ if (unlikely(err))
21548+ sysaufs_fin();
4f0767ce 21549+out:
1facf9fc 21550+ return err;
21551+}
e49829fe 21552--- /dev/null
0c5527e5 21553+++ linux-2.6/fs/aufs/sysaufs.h 2010-10-25 14:20:44.000000000 +0200
4a4d8108 21554@@ -0,0 +1,105 @@
1facf9fc 21555+/*
4a4d8108 21556+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21557+ *
21558+ * This program, aufs is free software; you can redistribute it and/or modify
21559+ * it under the terms of the GNU General Public License as published by
21560+ * the Free Software Foundation; either version 2 of the License, or
21561+ * (at your option) any later version.
dece6358
AM
21562+ *
21563+ * This program is distributed in the hope that it will be useful,
21564+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21565+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21566+ * GNU General Public License for more details.
21567+ *
21568+ * You should have received a copy of the GNU General Public License
21569+ * along with this program; if not, write to the Free Software
21570+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21571+ */
21572+
21573+/*
21574+ * sysfs interface and mount lifetime management
21575+ */
21576+
21577+#ifndef __SYSAUFS_H__
21578+#define __SYSAUFS_H__
21579+
21580+#ifdef __KERNEL__
21581+
1facf9fc 21582+#include <linux/sysfs.h>
21583+#include <linux/aufs_type.h>
21584+#include "module.h"
21585+
dece6358
AM
21586+struct super_block;
21587+struct au_sbinfo;
21588+
1facf9fc 21589+struct sysaufs_si_attr {
21590+ struct attribute attr;
21591+ int (*show)(struct seq_file *seq, struct super_block *sb);
21592+};
21593+
21594+/* ---------------------------------------------------------------------- */
21595+
21596+/* sysaufs.c */
21597+extern unsigned long sysaufs_si_mask;
e49829fe 21598+extern struct kset *sysaufs_kset;
1facf9fc 21599+extern struct attribute *sysaufs_si_attrs[];
21600+int sysaufs_si_init(struct au_sbinfo *sbinfo);
21601+int __init sysaufs_init(void);
21602+void sysaufs_fin(void);
21603+
21604+/* ---------------------------------------------------------------------- */
21605+
21606+/* some people doesn't like to show a pointer in kernel */
21607+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
21608+{
21609+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
21610+}
21611+
21612+#define SysaufsSiNamePrefix "si_"
21613+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
21614+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
21615+{
21616+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
21617+ sysaufs_si_id(sbinfo));
21618+}
21619+
21620+struct au_branch;
21621+#ifdef CONFIG_SYSFS
21622+/* sysfs.c */
21623+extern struct attribute_group *sysaufs_attr_group;
21624+
21625+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
21626+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
21627+ char *buf);
21628+
21629+void sysaufs_br_init(struct au_branch *br);
21630+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
21631+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
21632+
21633+#define sysaufs_brs_init() do {} while (0)
21634+
21635+#else
21636+#define sysaufs_attr_group NULL
21637+
4a4d8108 21638+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 21639+
21640+static inline
21641+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
21642+ char *buf)
21643+{
21644+ return 0;
21645+}
21646+
4a4d8108
AM
21647+AuStubVoid(sysaufs_br_init, struct au_branch *br)
21648+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
21649+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 21650+
21651+static inline void sysaufs_brs_init(void)
21652+{
21653+ sysaufs_brs = 0;
21654+}
21655+
21656+#endif /* CONFIG_SYSFS */
21657+
21658+#endif /* __KERNEL__ */
21659+#endif /* __SYSAUFS_H__ */
e49829fe 21660--- /dev/null
0c5527e5 21661+++ linux-2.6/fs/aufs/sysfs.c 2010-10-25 14:20:44.000000000 +0200
953406b4 21662@@ -0,0 +1,250 @@
1facf9fc 21663+/*
4a4d8108 21664+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21665+ *
21666+ * This program, aufs is free software; you can redistribute it and/or modify
21667+ * it under the terms of the GNU General Public License as published by
21668+ * the Free Software Foundation; either version 2 of the License, or
21669+ * (at your option) any later version.
dece6358
AM
21670+ *
21671+ * This program is distributed in the hope that it will be useful,
21672+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21673+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21674+ * GNU General Public License for more details.
21675+ *
21676+ * You should have received a copy of the GNU General Public License
21677+ * along with this program; if not, write to the Free Software
21678+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21679+ */
21680+
21681+/*
21682+ * sysfs interface
21683+ */
21684+
21685+#include <linux/fs.h>
dece6358 21686+#include <linux/module.h>
1facf9fc 21687+#include <linux/seq_file.h>
21688+#include <linux/sysfs.h>
21689+#include "aufs.h"
21690+
4a4d8108
AM
21691+#ifdef CONFIG_AUFS_FS_MODULE
21692+/* this entry violates the "one line per file" policy of sysfs */
21693+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
21694+ char *buf)
21695+{
21696+ ssize_t err;
21697+ static char *conf =
21698+/* this file is generated at compiling */
21699+#include "conf.str"
21700+ ;
21701+
21702+ err = snprintf(buf, PAGE_SIZE, conf);
21703+ if (unlikely(err >= PAGE_SIZE))
21704+ err = -EFBIG;
21705+ return err;
21706+}
21707+
21708+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
21709+#endif
21710+
1facf9fc 21711+static struct attribute *au_attr[] = {
4a4d8108
AM
21712+#ifdef CONFIG_AUFS_FS_MODULE
21713+ &au_config_attr.attr,
21714+#endif
1facf9fc 21715+ NULL, /* need to NULL terminate the list of attributes */
21716+};
21717+
21718+static struct attribute_group sysaufs_attr_group_body = {
21719+ .attrs = au_attr
21720+};
21721+
21722+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
21723+
21724+/* ---------------------------------------------------------------------- */
21725+
21726+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
21727+{
21728+ int err;
21729+
dece6358
AM
21730+ SiMustAnyLock(sb);
21731+
1facf9fc 21732+ err = 0;
21733+ if (au_opt_test(au_mntflags(sb), XINO)) {
21734+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
21735+ seq_putc(seq, '\n');
21736+ }
21737+ return err;
21738+}
21739+
21740+/*
21741+ * the lifetime of branch is independent from the entry under sysfs.
21742+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
21743+ * unlinked.
21744+ */
21745+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
21746+ aufs_bindex_t bindex)
21747+{
21748+ struct path path;
21749+ struct dentry *root;
21750+ struct au_branch *br;
21751+
21752+ AuDbg("b%d\n", bindex);
21753+
21754+ root = sb->s_root;
21755+ di_read_lock_parent(root, !AuLock_IR);
21756+ br = au_sbr(sb, bindex);
21757+ path.mnt = br->br_mnt;
21758+ path.dentry = au_h_dptr(root, bindex);
21759+ au_seq_path(seq, &path);
21760+ di_read_unlock(root, !AuLock_IR);
21761+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
21762+ return 0;
21763+}
21764+
21765+/* ---------------------------------------------------------------------- */
21766+
21767+static struct seq_file *au_seq(char *p, ssize_t len)
21768+{
21769+ struct seq_file *seq;
21770+
21771+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
21772+ if (seq) {
21773+ /* mutex_init(&seq.lock); */
21774+ seq->buf = p;
21775+ seq->size = len;
21776+ return seq; /* success */
21777+ }
21778+
21779+ seq = ERR_PTR(-ENOMEM);
21780+ return seq;
21781+}
21782+
21783+#define SysaufsBr_PREFIX "br"
21784+
21785+/* todo: file size may exceed PAGE_SIZE */
21786+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 21787+ char *buf)
1facf9fc 21788+{
21789+ ssize_t err;
21790+ long l;
21791+ aufs_bindex_t bend;
21792+ struct au_sbinfo *sbinfo;
21793+ struct super_block *sb;
21794+ struct seq_file *seq;
21795+ char *name;
21796+ struct attribute **cattr;
21797+
21798+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
21799+ sb = sbinfo->si_sb;
1308ab2a 21800+
21801+ /*
21802+ * prevent a race condition between sysfs and aufs.
21803+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
21804+ * prohibits maintaining the sysfs entries.
21805+ * hew we acquire read lock after sysfs_get_active_two().
21806+ * on the other hand, the remount process may maintain the sysfs/aufs
21807+ * entries after acquiring write lock.
21808+ * it can cause a deadlock.
21809+ * simply we gave up processing read here.
21810+ */
21811+ err = -EBUSY;
21812+ if (unlikely(!si_noflush_read_trylock(sb)))
21813+ goto out;
1facf9fc 21814+
21815+ seq = au_seq(buf, PAGE_SIZE);
21816+ err = PTR_ERR(seq);
21817+ if (IS_ERR(seq))
1308ab2a 21818+ goto out_unlock;
1facf9fc 21819+
21820+ name = (void *)attr->name;
21821+ cattr = sysaufs_si_attrs;
21822+ while (*cattr) {
21823+ if (!strcmp(name, (*cattr)->name)) {
21824+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
21825+ ->show(seq, sb);
21826+ goto out_seq;
21827+ }
21828+ cattr++;
21829+ }
21830+
21831+ bend = au_sbend(sb);
21832+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
21833+ name += sizeof(SysaufsBr_PREFIX) - 1;
21834+ err = strict_strtol(name, 10, &l);
21835+ if (!err) {
21836+ if (l <= bend)
21837+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
21838+ else
21839+ err = -ENOENT;
21840+ }
21841+ goto out_seq;
21842+ }
21843+ BUG();
21844+
4f0767ce 21845+out_seq:
1facf9fc 21846+ if (!err) {
21847+ err = seq->count;
21848+ /* sysfs limit */
21849+ if (unlikely(err == PAGE_SIZE))
21850+ err = -EFBIG;
21851+ }
21852+ kfree(seq);
4f0767ce 21853+out_unlock:
1facf9fc 21854+ si_read_unlock(sb);
4f0767ce 21855+out:
1facf9fc 21856+ return err;
21857+}
21858+
21859+/* ---------------------------------------------------------------------- */
21860+
21861+void sysaufs_br_init(struct au_branch *br)
21862+{
4a4d8108
AM
21863+ struct attribute *attr = &br->br_attr;
21864+
21865+ sysfs_attr_init(attr);
21866+ attr->name = br->br_name;
21867+ attr->mode = S_IRUGO;
1facf9fc 21868+}
21869+
21870+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
21871+{
21872+ struct au_branch *br;
21873+ struct kobject *kobj;
21874+ aufs_bindex_t bend;
21875+
21876+ dbgaufs_brs_del(sb, bindex);
21877+
21878+ if (!sysaufs_brs)
21879+ return;
21880+
21881+ kobj = &au_sbi(sb)->si_kobj;
21882+ bend = au_sbend(sb);
21883+ for (; bindex <= bend; bindex++) {
21884+ br = au_sbr(sb, bindex);
21885+ sysfs_remove_file(kobj, &br->br_attr);
21886+ }
21887+}
21888+
21889+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
21890+{
21891+ int err;
21892+ aufs_bindex_t bend;
21893+ struct kobject *kobj;
21894+ struct au_branch *br;
21895+
21896+ dbgaufs_brs_add(sb, bindex);
21897+
21898+ if (!sysaufs_brs)
21899+ return;
21900+
21901+ kobj = &au_sbi(sb)->si_kobj;
21902+ bend = au_sbend(sb);
21903+ for (; bindex <= bend; bindex++) {
21904+ br = au_sbr(sb, bindex);
21905+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
21906+ "%d", bindex);
21907+ err = sysfs_create_file(kobj, &br->br_attr);
21908+ if (unlikely(err))
4a4d8108
AM
21909+ pr_warning("failed %s under sysfs(%d)\n",
21910+ br->br_name, err);
1facf9fc 21911+ }
21912+}
e49829fe 21913--- /dev/null
0c5527e5
AM
21914+++ linux-2.6/fs/aufs/sysrq.c 2010-10-26 21:43:12.000000000 +0200
21915@@ -0,0 +1,118 @@
1facf9fc 21916+/*
4a4d8108 21917+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 21918+ *
21919+ * This program, aufs is free software; you can redistribute it and/or modify
21920+ * it under the terms of the GNU General Public License as published by
21921+ * the Free Software Foundation; either version 2 of the License, or
21922+ * (at your option) any later version.
dece6358
AM
21923+ *
21924+ * This program is distributed in the hope that it will be useful,
21925+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21926+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21927+ * GNU General Public License for more details.
21928+ *
21929+ * You should have received a copy of the GNU General Public License
21930+ * along with this program; if not, write to the Free Software
21931+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21932+ */
21933+
21934+/*
21935+ * magic sysrq hanlder
21936+ */
21937+
21938+#include <linux/fs.h>
21939+#include <linux/module.h>
21940+#include <linux/moduleparam.h>
21941+/* #include <linux/sysrq.h> */
21942+#include "aufs.h"
21943+
21944+/* ---------------------------------------------------------------------- */
21945+
21946+static void sysrq_sb(struct super_block *sb)
21947+{
21948+ char *plevel;
21949+ struct au_sbinfo *sbinfo;
21950+ struct file *file;
21951+
21952+ plevel = au_plevel;
21953+ au_plevel = KERN_WARNING;
1facf9fc 21954+
21955+ sbinfo = au_sbi(sb);
4a4d8108
AM
21956+ /* since we define pr_fmt, call printk directly */
21957+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
21958+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 21959+ au_dpri_sb(sb);
4a4d8108 21960+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 21961+ au_dpri_dentry(sb->s_root);
4a4d8108 21962+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 21963+ au_dpri_inode(sb->s_root->d_inode);
21964+#if 0
21965+ struct inode *i;
4a4d8108 21966+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
e49829fe 21967+ spin_lock(&inode_lock);
1facf9fc 21968+ list_for_each_entry(i, &sb->s_inodes, i_sb_list)
21969+ if (list_empty(&i->i_dentry))
21970+ au_dpri_inode(i);
e49829fe 21971+ spin_unlock(&inode_lock);
1facf9fc 21972+#endif
4a4d8108 21973+ printk(KERN_WARNING AUFS_NAME ": files\n");
0c5527e5
AM
21974+ lg_global_lock(files_lglock);
21975+ do_file_list_for_each_entry(sb, file) {
4a4d8108
AM
21976+ umode_t mode;
21977+ mode = file->f_dentry->d_inode->i_mode;
21978+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 21979+ au_dpri_file(file);
0c5527e5
AM
21980+ } while_file_list_for_each_entry;
21981+ lg_global_unlock(files_lglock);
e49829fe 21982+ printk(KERN_WARNING AUFS_NAME ": done\n");
1facf9fc 21983+
21984+ au_plevel = plevel;
1facf9fc 21985+}
21986+
21987+/* ---------------------------------------------------------------------- */
21988+
21989+/* module parameter */
21990+static char *aufs_sysrq_key = "a";
21991+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
21992+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
21993+
0c5527e5 21994+static void au_sysrq(int key __maybe_unused)
1facf9fc 21995+{
1facf9fc 21996+ struct au_sbinfo *sbinfo;
21997+
e49829fe
JR
21998+ spin_lock(&au_sbilist.spin);
21999+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
1facf9fc 22000+ sysrq_sb(sbinfo->si_sb);
e49829fe 22001+ spin_unlock(&au_sbilist.spin);
1facf9fc 22002+}
22003+
22004+static struct sysrq_key_op au_sysrq_op = {
22005+ .handler = au_sysrq,
22006+ .help_msg = "Aufs",
22007+ .action_msg = "Aufs",
22008+ .enable_mask = SYSRQ_ENABLE_DUMP
22009+};
22010+
22011+/* ---------------------------------------------------------------------- */
22012+
22013+int __init au_sysrq_init(void)
22014+{
22015+ int err;
22016+ char key;
22017+
22018+ err = -1;
22019+ key = *aufs_sysrq_key;
22020+ if ('a' <= key && key <= 'z')
22021+ err = register_sysrq_key(key, &au_sysrq_op);
22022+ if (unlikely(err))
4a4d8108 22023+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 22024+ return err;
22025+}
22026+
22027+void au_sysrq_fin(void)
22028+{
22029+ int err;
22030+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
22031+ if (unlikely(err))
4a4d8108 22032+ pr_err("err %d (ignored)\n", err);
1facf9fc 22033+}
e49829fe 22034--- /dev/null
0c5527e5 22035+++ linux-2.6/fs/aufs/vdir.c 2010-10-25 14:20:44.000000000 +0200
4a4d8108 22036@@ -0,0 +1,884 @@
1facf9fc 22037+/*
4a4d8108 22038+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22039+ *
22040+ * This program, aufs is free software; you can redistribute it and/or modify
22041+ * it under the terms of the GNU General Public License as published by
22042+ * the Free Software Foundation; either version 2 of the License, or
22043+ * (at your option) any later version.
dece6358
AM
22044+ *
22045+ * This program is distributed in the hope that it will be useful,
22046+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22047+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22048+ * GNU General Public License for more details.
22049+ *
22050+ * You should have received a copy of the GNU General Public License
22051+ * along with this program; if not, write to the Free Software
22052+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22053+ */
22054+
22055+/*
22056+ * virtual or vertical directory
22057+ */
22058+
dece6358 22059+#include <linux/hash.h>
1facf9fc 22060+#include "aufs.h"
22061+
dece6358 22062+static unsigned int calc_size(int nlen)
1facf9fc 22063+{
dece6358 22064+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 22065+}
22066+
22067+static int set_deblk_end(union au_vdir_deblk_p *p,
22068+ union au_vdir_deblk_p *deblk_end)
22069+{
22070+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
22071+ p->de->de_str.len = 0;
22072+ /* smp_mb(); */
22073+ return 0;
22074+ }
22075+ return -1; /* error */
22076+}
22077+
22078+/* returns true or false */
22079+static int is_deblk_end(union au_vdir_deblk_p *p,
22080+ union au_vdir_deblk_p *deblk_end)
22081+{
22082+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
22083+ return !p->de->de_str.len;
22084+ return 1;
22085+}
22086+
22087+static unsigned char *last_deblk(struct au_vdir *vdir)
22088+{
22089+ return vdir->vd_deblk[vdir->vd_nblk - 1];
22090+}
22091+
22092+/* ---------------------------------------------------------------------- */
22093+
1308ab2a 22094+/* estimate the apropriate size for name hash table */
22095+unsigned int au_rdhash_est(loff_t sz)
22096+{
22097+ unsigned int n;
22098+
22099+ n = UINT_MAX;
22100+ sz >>= 10;
22101+ if (sz < n)
22102+ n = sz;
22103+ if (sz < AUFS_RDHASH_DEF)
22104+ n = AUFS_RDHASH_DEF;
4a4d8108 22105+ /* pr_info("n %u\n", n); */
1308ab2a 22106+ return n;
22107+}
22108+
1facf9fc 22109+/*
22110+ * the allocated memory has to be freed by
dece6358 22111+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 22112+ */
dece6358 22113+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 22114+{
1facf9fc 22115+ struct hlist_head *head;
dece6358 22116+ unsigned int u;
1facf9fc 22117+
dece6358
AM
22118+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
22119+ if (head) {
22120+ nhash->nh_num = num_hash;
22121+ nhash->nh_head = head;
22122+ for (u = 0; u < num_hash; u++)
1facf9fc 22123+ INIT_HLIST_HEAD(head++);
dece6358 22124+ return 0; /* success */
1facf9fc 22125+ }
1facf9fc 22126+
dece6358 22127+ return -ENOMEM;
1facf9fc 22128+}
22129+
dece6358
AM
22130+static void nhash_count(struct hlist_head *head)
22131+{
22132+#if 0
22133+ unsigned long n;
22134+ struct hlist_node *pos;
22135+
22136+ n = 0;
22137+ hlist_for_each(pos, head)
22138+ n++;
4a4d8108 22139+ pr_info("%lu\n", n);
dece6358
AM
22140+#endif
22141+}
22142+
22143+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 22144+{
1facf9fc 22145+ struct au_vdir_wh *tpos;
22146+ struct hlist_node *pos, *node;
22147+
dece6358
AM
22148+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
22149+ /* hlist_del(pos); */
22150+ kfree(tpos);
1facf9fc 22151+ }
22152+}
22153+
dece6358 22154+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 22155+{
dece6358
AM
22156+ struct au_vdir_dehstr *tpos;
22157+ struct hlist_node *pos, *node;
1facf9fc 22158+
dece6358
AM
22159+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
22160+ /* hlist_del(pos); */
4a4d8108 22161+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 22162+ }
1facf9fc 22163+}
22164+
dece6358
AM
22165+static void au_nhash_do_free(struct au_nhash *nhash,
22166+ void (*free)(struct hlist_head *head))
1facf9fc 22167+{
1308ab2a 22168+ unsigned int n;
1facf9fc 22169+ struct hlist_head *head;
1facf9fc 22170+
dece6358 22171+ n = nhash->nh_num;
1308ab2a 22172+ if (!n)
22173+ return;
22174+
dece6358 22175+ head = nhash->nh_head;
1308ab2a 22176+ while (n-- > 0) {
dece6358
AM
22177+ nhash_count(head);
22178+ free(head++);
1facf9fc 22179+ }
dece6358 22180+ kfree(nhash->nh_head);
1facf9fc 22181+}
22182+
dece6358 22183+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 22184+{
dece6358
AM
22185+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
22186+}
1facf9fc 22187+
dece6358
AM
22188+static void au_nhash_de_free(struct au_nhash *delist)
22189+{
22190+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 22191+}
22192+
22193+/* ---------------------------------------------------------------------- */
22194+
22195+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
22196+ int limit)
22197+{
22198+ int num;
22199+ unsigned int u, n;
22200+ struct hlist_head *head;
22201+ struct au_vdir_wh *tpos;
22202+ struct hlist_node *pos;
22203+
22204+ num = 0;
22205+ n = whlist->nh_num;
22206+ head = whlist->nh_head;
1308ab2a 22207+ for (u = 0; u < n; u++, head++)
1facf9fc 22208+ hlist_for_each_entry(tpos, pos, head, wh_hash)
22209+ if (tpos->wh_bindex == btgt && ++num > limit)
22210+ return 1;
1facf9fc 22211+ return 0;
22212+}
22213+
22214+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 22215+ unsigned char *name,
1facf9fc 22216+ unsigned int len)
22217+{
dece6358
AM
22218+ unsigned int v;
22219+ /* const unsigned int magic_bit = 12; */
22220+
1308ab2a 22221+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
22222+
dece6358
AM
22223+ v = 0;
22224+ while (len--)
22225+ v += *name++;
22226+ /* v = hash_long(v, magic_bit); */
22227+ v %= nhash->nh_num;
22228+ return nhash->nh_head + v;
22229+}
22230+
22231+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
22232+ int nlen)
22233+{
22234+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 22235+}
22236+
22237+/* returns found or not */
dece6358 22238+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 22239+{
22240+ struct hlist_head *head;
22241+ struct au_vdir_wh *tpos;
22242+ struct hlist_node *pos;
22243+ struct au_vdir_destr *str;
22244+
dece6358 22245+ head = au_name_hash(whlist, name, nlen);
1facf9fc 22246+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
22247+ str = &tpos->wh_str;
22248+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
22249+ if (au_nhash_test_name(str, name, nlen))
22250+ return 1;
22251+ }
22252+ return 0;
22253+}
22254+
22255+/* returns found(true) or not */
22256+static int test_known(struct au_nhash *delist, char *name, int nlen)
22257+{
22258+ struct hlist_head *head;
22259+ struct au_vdir_dehstr *tpos;
22260+ struct hlist_node *pos;
22261+ struct au_vdir_destr *str;
22262+
22263+ head = au_name_hash(delist, name, nlen);
22264+ hlist_for_each_entry(tpos, pos, head, hash) {
22265+ str = tpos->str;
22266+ AuDbg("%.*s\n", str->len, str->name);
22267+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 22268+ return 1;
22269+ }
22270+ return 0;
22271+}
22272+
dece6358
AM
22273+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
22274+ unsigned char d_type)
22275+{
22276+#ifdef CONFIG_AUFS_SHWH
22277+ wh->wh_ino = ino;
22278+ wh->wh_type = d_type;
22279+#endif
22280+}
22281+
22282+/* ---------------------------------------------------------------------- */
22283+
22284+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
22285+ unsigned int d_type, aufs_bindex_t bindex,
22286+ unsigned char shwh)
1facf9fc 22287+{
22288+ int err;
22289+ struct au_vdir_destr *str;
22290+ struct au_vdir_wh *wh;
22291+
dece6358 22292+ AuDbg("%.*s\n", nlen, name);
1308ab2a 22293+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
22294+
1facf9fc 22295+ err = -ENOMEM;
dece6358 22296+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 22297+ if (unlikely(!wh))
22298+ goto out;
22299+
22300+ err = 0;
22301+ wh->wh_bindex = bindex;
dece6358
AM
22302+ if (shwh)
22303+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 22304+ str = &wh->wh_str;
dece6358
AM
22305+ str->len = nlen;
22306+ memcpy(str->name, name, nlen);
22307+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 22308+ /* smp_mb(); */
22309+
4f0767ce 22310+out:
1facf9fc 22311+ return err;
22312+}
22313+
1facf9fc 22314+static int append_deblk(struct au_vdir *vdir)
22315+{
22316+ int err;
dece6358 22317+ unsigned long ul;
1facf9fc 22318+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
22319+ union au_vdir_deblk_p p, deblk_end;
22320+ unsigned char **o;
22321+
22322+ err = -ENOMEM;
dece6358
AM
22323+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
22324+ GFP_NOFS);
1facf9fc 22325+ if (unlikely(!o))
22326+ goto out;
22327+
22328+ vdir->vd_deblk = o;
22329+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
22330+ if (p.deblk) {
22331+ ul = vdir->vd_nblk++;
22332+ vdir->vd_deblk[ul] = p.deblk;
22333+ vdir->vd_last.ul = ul;
22334+ vdir->vd_last.p.deblk = p.deblk;
22335+ deblk_end.deblk = p.deblk + deblk_sz;
22336+ err = set_deblk_end(&p, &deblk_end);
22337+ }
22338+
4f0767ce 22339+out:
1facf9fc 22340+ return err;
22341+}
22342+
dece6358
AM
22343+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
22344+ unsigned int d_type, struct au_nhash *delist)
22345+{
22346+ int err;
22347+ unsigned int sz;
22348+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
22349+ union au_vdir_deblk_p p, *room, deblk_end;
22350+ struct au_vdir_dehstr *dehstr;
22351+
22352+ p.deblk = last_deblk(vdir);
22353+ deblk_end.deblk = p.deblk + deblk_sz;
22354+ room = &vdir->vd_last.p;
22355+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
22356+ || !is_deblk_end(room, &deblk_end));
22357+
22358+ sz = calc_size(nlen);
22359+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
22360+ err = append_deblk(vdir);
22361+ if (unlikely(err))
22362+ goto out;
22363+
22364+ p.deblk = last_deblk(vdir);
22365+ deblk_end.deblk = p.deblk + deblk_sz;
22366+ /* smp_mb(); */
22367+ AuDebugOn(room->deblk != p.deblk);
22368+ }
22369+
22370+ err = -ENOMEM;
4a4d8108 22371+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
22372+ if (unlikely(!dehstr))
22373+ goto out;
22374+
22375+ dehstr->str = &room->de->de_str;
22376+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
22377+ room->de->de_ino = ino;
22378+ room->de->de_type = d_type;
22379+ room->de->de_str.len = nlen;
22380+ memcpy(room->de->de_str.name, name, nlen);
22381+
22382+ err = 0;
22383+ room->deblk += sz;
22384+ if (unlikely(set_deblk_end(room, &deblk_end)))
22385+ err = append_deblk(vdir);
22386+ /* smp_mb(); */
22387+
4f0767ce 22388+out:
dece6358
AM
22389+ return err;
22390+}
22391+
22392+/* ---------------------------------------------------------------------- */
22393+
22394+void au_vdir_free(struct au_vdir *vdir)
22395+{
22396+ unsigned char **deblk;
22397+
22398+ deblk = vdir->vd_deblk;
22399+ while (vdir->vd_nblk--)
22400+ kfree(*deblk++);
22401+ kfree(vdir->vd_deblk);
22402+ au_cache_free_vdir(vdir);
22403+}
22404+
1308ab2a 22405+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 22406+{
22407+ struct au_vdir *vdir;
1308ab2a 22408+ struct super_block *sb;
1facf9fc 22409+ int err;
22410+
1308ab2a 22411+ sb = file->f_dentry->d_sb;
dece6358
AM
22412+ SiMustAnyLock(sb);
22413+
1facf9fc 22414+ err = -ENOMEM;
22415+ vdir = au_cache_alloc_vdir();
22416+ if (unlikely(!vdir))
22417+ goto out;
22418+
22419+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
22420+ if (unlikely(!vdir->vd_deblk))
22421+ goto out_free;
22422+
22423+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 22424+ if (!vdir->vd_deblk_sz) {
22425+ /* estimate the apropriate size for deblk */
22426+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 22427+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 22428+ }
1facf9fc 22429+ vdir->vd_nblk = 0;
22430+ vdir->vd_version = 0;
22431+ vdir->vd_jiffy = 0;
22432+ err = append_deblk(vdir);
22433+ if (!err)
22434+ return vdir; /* success */
22435+
22436+ kfree(vdir->vd_deblk);
22437+
4f0767ce 22438+out_free:
1facf9fc 22439+ au_cache_free_vdir(vdir);
4f0767ce 22440+out:
1facf9fc 22441+ vdir = ERR_PTR(err);
22442+ return vdir;
22443+}
22444+
22445+static int reinit_vdir(struct au_vdir *vdir)
22446+{
22447+ int err;
22448+ union au_vdir_deblk_p p, deblk_end;
22449+
22450+ while (vdir->vd_nblk > 1) {
22451+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
22452+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
22453+ vdir->vd_nblk--;
22454+ }
22455+ p.deblk = vdir->vd_deblk[0];
22456+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
22457+ err = set_deblk_end(&p, &deblk_end);
22458+ /* keep vd_dblk_sz */
22459+ vdir->vd_last.ul = 0;
22460+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
22461+ vdir->vd_version = 0;
22462+ vdir->vd_jiffy = 0;
22463+ /* smp_mb(); */
22464+ return err;
22465+}
22466+
22467+/* ---------------------------------------------------------------------- */
22468+
1facf9fc 22469+#define AuFillVdir_CALLED 1
22470+#define AuFillVdir_WHABLE (1 << 1)
dece6358 22471+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 22472+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
22473+#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
22474+#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
22475+
dece6358
AM
22476+#ifndef CONFIG_AUFS_SHWH
22477+#undef AuFillVdir_SHWH
22478+#define AuFillVdir_SHWH 0
22479+#endif
22480+
1facf9fc 22481+struct fillvdir_arg {
22482+ struct file *file;
22483+ struct au_vdir *vdir;
dece6358
AM
22484+ struct au_nhash delist;
22485+ struct au_nhash whlist;
1facf9fc 22486+ aufs_bindex_t bindex;
22487+ unsigned int flags;
22488+ int err;
22489+};
22490+
dece6358 22491+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 22492+ loff_t offset __maybe_unused, u64 h_ino,
22493+ unsigned int d_type)
22494+{
22495+ struct fillvdir_arg *arg = __arg;
22496+ char *name = (void *)__name;
22497+ struct super_block *sb;
1facf9fc 22498+ ino_t ino;
dece6358 22499+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 22500+
1facf9fc 22501+ arg->err = 0;
dece6358 22502+ sb = arg->file->f_dentry->d_sb;
1facf9fc 22503+ au_fset_fillvdir(arg->flags, CALLED);
22504+ /* smp_mb(); */
dece6358 22505+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 22506+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
22507+ if (test_known(&arg->delist, name, nlen)
22508+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
22509+ goto out; /* already exists or whiteouted */
1facf9fc 22510+
22511+ sb = arg->file->f_dentry->d_sb;
dece6358 22512+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
22513+ if (!arg->err) {
22514+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
22515+ d_type = DT_UNKNOWN;
dece6358
AM
22516+ arg->err = append_de(arg->vdir, name, nlen, ino,
22517+ d_type, &arg->delist);
4a4d8108 22518+ }
1facf9fc 22519+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
22520+ name += AUFS_WH_PFX_LEN;
dece6358
AM
22521+ nlen -= AUFS_WH_PFX_LEN;
22522+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
22523+ goto out; /* already whiteouted */
1facf9fc 22524+
dece6358
AM
22525+ if (shwh)
22526+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
22527+ &ino);
4a4d8108
AM
22528+ if (!arg->err) {
22529+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
22530+ d_type = DT_UNKNOWN;
1facf9fc 22531+ arg->err = au_nhash_append_wh
dece6358
AM
22532+ (&arg->whlist, name, nlen, ino, d_type,
22533+ arg->bindex, shwh);
4a4d8108 22534+ }
1facf9fc 22535+ }
22536+
4f0767ce 22537+out:
1facf9fc 22538+ if (!arg->err)
22539+ arg->vdir->vd_jiffy = jiffies;
22540+ /* smp_mb(); */
22541+ AuTraceErr(arg->err);
22542+ return arg->err;
22543+}
22544+
dece6358
AM
22545+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
22546+ struct au_nhash *whlist, struct au_nhash *delist)
22547+{
22548+#ifdef CONFIG_AUFS_SHWH
22549+ int err;
22550+ unsigned int nh, u;
22551+ struct hlist_head *head;
22552+ struct au_vdir_wh *tpos;
22553+ struct hlist_node *pos, *n;
22554+ char *p, *o;
22555+ struct au_vdir_destr *destr;
22556+
22557+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
22558+
22559+ err = -ENOMEM;
4a4d8108 22560+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
22561+ if (unlikely(!p))
22562+ goto out;
22563+
22564+ err = 0;
22565+ nh = whlist->nh_num;
22566+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
22567+ p += AUFS_WH_PFX_LEN;
22568+ for (u = 0; u < nh; u++) {
22569+ head = whlist->nh_head + u;
22570+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
22571+ destr = &tpos->wh_str;
22572+ memcpy(p, destr->name, destr->len);
22573+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
22574+ tpos->wh_ino, tpos->wh_type, delist);
22575+ if (unlikely(err))
22576+ break;
22577+ }
22578+ }
22579+
22580+ __putname(o);
22581+
4f0767ce 22582+out:
dece6358
AM
22583+ AuTraceErr(err);
22584+ return err;
22585+#else
22586+ return 0;
22587+#endif
22588+}
22589+
1facf9fc 22590+static int au_do_read_vdir(struct fillvdir_arg *arg)
22591+{
22592+ int err;
dece6358 22593+ unsigned int rdhash;
1facf9fc 22594+ loff_t offset;
dece6358
AM
22595+ aufs_bindex_t bend, bindex, bstart;
22596+ unsigned char shwh;
1facf9fc 22597+ struct file *hf, *file;
22598+ struct super_block *sb;
22599+
1facf9fc 22600+ file = arg->file;
22601+ sb = file->f_dentry->d_sb;
dece6358
AM
22602+ SiMustAnyLock(sb);
22603+
22604+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 22605+ if (!rdhash)
22606+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
22607+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
22608+ if (unlikely(err))
1facf9fc 22609+ goto out;
dece6358
AM
22610+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
22611+ if (unlikely(err))
1facf9fc 22612+ goto out_delist;
22613+
22614+ err = 0;
22615+ arg->flags = 0;
dece6358
AM
22616+ shwh = 0;
22617+ if (au_opt_test(au_mntflags(sb), SHWH)) {
22618+ shwh = 1;
22619+ au_fset_fillvdir(arg->flags, SHWH);
22620+ }
22621+ bstart = au_fbstart(file);
4a4d8108 22622+ bend = au_fbend_dir(file);
dece6358 22623+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 22624+ hf = au_hf_dir(file, bindex);
1facf9fc 22625+ if (!hf)
22626+ continue;
22627+
22628+ offset = vfsub_llseek(hf, 0, SEEK_SET);
22629+ err = offset;
22630+ if (unlikely(offset))
22631+ break;
22632+
22633+ arg->bindex = bindex;
22634+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
22635+ if (shwh
22636+ || (bindex != bend
22637+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 22638+ au_fset_fillvdir(arg->flags, WHABLE);
22639+ do {
22640+ arg->err = 0;
22641+ au_fclr_fillvdir(arg->flags, CALLED);
22642+ /* smp_mb(); */
22643+ err = vfsub_readdir(hf, fillvdir, arg);
22644+ if (err >= 0)
22645+ err = arg->err;
22646+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
22647+ }
dece6358
AM
22648+
22649+ if (!err && shwh)
22650+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
22651+
22652+ au_nhash_wh_free(&arg->whlist);
1facf9fc 22653+
4f0767ce 22654+out_delist:
dece6358 22655+ au_nhash_de_free(&arg->delist);
4f0767ce 22656+out:
1facf9fc 22657+ return err;
22658+}
22659+
22660+static int read_vdir(struct file *file, int may_read)
22661+{
22662+ int err;
22663+ unsigned long expire;
22664+ unsigned char do_read;
22665+ struct fillvdir_arg arg;
22666+ struct inode *inode;
22667+ struct au_vdir *vdir, *allocated;
22668+
22669+ err = 0;
22670+ inode = file->f_dentry->d_inode;
22671+ IMustLock(inode);
dece6358
AM
22672+ SiMustAnyLock(inode->i_sb);
22673+
1facf9fc 22674+ allocated = NULL;
22675+ do_read = 0;
22676+ expire = au_sbi(inode->i_sb)->si_rdcache;
22677+ vdir = au_ivdir(inode);
22678+ if (!vdir) {
22679+ do_read = 1;
1308ab2a 22680+ vdir = alloc_vdir(file);
1facf9fc 22681+ err = PTR_ERR(vdir);
22682+ if (IS_ERR(vdir))
22683+ goto out;
22684+ err = 0;
22685+ allocated = vdir;
22686+ } else if (may_read
22687+ && (inode->i_version != vdir->vd_version
22688+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
22689+ do_read = 1;
22690+ err = reinit_vdir(vdir);
22691+ if (unlikely(err))
22692+ goto out;
22693+ }
22694+
22695+ if (!do_read)
22696+ return 0; /* success */
22697+
22698+ arg.file = file;
22699+ arg.vdir = vdir;
22700+ err = au_do_read_vdir(&arg);
22701+ if (!err) {
22702+ /* file->f_pos = 0; */
22703+ vdir->vd_version = inode->i_version;
22704+ vdir->vd_last.ul = 0;
22705+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
22706+ if (allocated)
22707+ au_set_ivdir(inode, allocated);
22708+ } else if (allocated)
22709+ au_vdir_free(allocated);
22710+
4f0767ce 22711+out:
1facf9fc 22712+ return err;
22713+}
22714+
22715+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
22716+{
22717+ int err, rerr;
22718+ unsigned long ul, n;
22719+ const unsigned int deblk_sz = src->vd_deblk_sz;
22720+
22721+ AuDebugOn(tgt->vd_nblk != 1);
22722+
22723+ err = -ENOMEM;
22724+ if (tgt->vd_nblk < src->vd_nblk) {
22725+ unsigned char **p;
22726+
dece6358
AM
22727+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
22728+ GFP_NOFS);
1facf9fc 22729+ if (unlikely(!p))
22730+ goto out;
22731+ tgt->vd_deblk = p;
22732+ }
22733+
1308ab2a 22734+ if (tgt->vd_deblk_sz != deblk_sz) {
22735+ unsigned char *p;
22736+
22737+ tgt->vd_deblk_sz = deblk_sz;
22738+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
22739+ if (unlikely(!p))
22740+ goto out;
22741+ tgt->vd_deblk[0] = p;
22742+ }
1facf9fc 22743+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 22744+ tgt->vd_version = src->vd_version;
22745+ tgt->vd_jiffy = src->vd_jiffy;
22746+
22747+ n = src->vd_nblk;
22748+ for (ul = 1; ul < n; ul++) {
dece6358
AM
22749+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
22750+ GFP_NOFS);
22751+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 22752+ goto out;
1308ab2a 22753+ tgt->vd_nblk++;
1facf9fc 22754+ }
1308ab2a 22755+ tgt->vd_nblk = n;
22756+ tgt->vd_last.ul = tgt->vd_last.ul;
22757+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
22758+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
22759+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 22760+ /* smp_mb(); */
22761+ return 0; /* success */
22762+
4f0767ce 22763+out:
1facf9fc 22764+ rerr = reinit_vdir(tgt);
22765+ BUG_ON(rerr);
22766+ return err;
22767+}
22768+
22769+int au_vdir_init(struct file *file)
22770+{
22771+ int err;
22772+ struct inode *inode;
22773+ struct au_vdir *vdir_cache, *allocated;
22774+
22775+ err = read_vdir(file, !file->f_pos);
22776+ if (unlikely(err))
22777+ goto out;
22778+
22779+ allocated = NULL;
22780+ vdir_cache = au_fvdir_cache(file);
22781+ if (!vdir_cache) {
1308ab2a 22782+ vdir_cache = alloc_vdir(file);
1facf9fc 22783+ err = PTR_ERR(vdir_cache);
22784+ if (IS_ERR(vdir_cache))
22785+ goto out;
22786+ allocated = vdir_cache;
22787+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
22788+ err = reinit_vdir(vdir_cache);
22789+ if (unlikely(err))
22790+ goto out;
22791+ } else
22792+ return 0; /* success */
22793+
22794+ inode = file->f_dentry->d_inode;
22795+ err = copy_vdir(vdir_cache, au_ivdir(inode));
22796+ if (!err) {
22797+ file->f_version = inode->i_version;
22798+ if (allocated)
22799+ au_set_fvdir_cache(file, allocated);
22800+ } else if (allocated)
22801+ au_vdir_free(allocated);
22802+
4f0767ce 22803+out:
1facf9fc 22804+ return err;
22805+}
22806+
22807+static loff_t calc_offset(struct au_vdir *vdir)
22808+{
22809+ loff_t offset;
22810+ union au_vdir_deblk_p p;
22811+
22812+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
22813+ offset = vdir->vd_last.p.deblk - p.deblk;
22814+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
22815+ return offset;
22816+}
22817+
22818+/* returns true or false */
22819+static int seek_vdir(struct file *file)
22820+{
22821+ int valid;
22822+ unsigned int deblk_sz;
22823+ unsigned long ul, n;
22824+ loff_t offset;
22825+ union au_vdir_deblk_p p, deblk_end;
22826+ struct au_vdir *vdir_cache;
22827+
22828+ valid = 1;
22829+ vdir_cache = au_fvdir_cache(file);
22830+ offset = calc_offset(vdir_cache);
22831+ AuDbg("offset %lld\n", offset);
22832+ if (file->f_pos == offset)
22833+ goto out;
22834+
22835+ vdir_cache->vd_last.ul = 0;
22836+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
22837+ if (!file->f_pos)
22838+ goto out;
22839+
22840+ valid = 0;
22841+ deblk_sz = vdir_cache->vd_deblk_sz;
22842+ ul = div64_u64(file->f_pos, deblk_sz);
22843+ AuDbg("ul %lu\n", ul);
22844+ if (ul >= vdir_cache->vd_nblk)
22845+ goto out;
22846+
22847+ n = vdir_cache->vd_nblk;
22848+ for (; ul < n; ul++) {
22849+ p.deblk = vdir_cache->vd_deblk[ul];
22850+ deblk_end.deblk = p.deblk + deblk_sz;
22851+ offset = ul;
22852+ offset *= deblk_sz;
22853+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
22854+ unsigned int l;
22855+
22856+ l = calc_size(p.de->de_str.len);
22857+ offset += l;
22858+ p.deblk += l;
22859+ }
22860+ if (!is_deblk_end(&p, &deblk_end)) {
22861+ valid = 1;
22862+ vdir_cache->vd_last.ul = ul;
22863+ vdir_cache->vd_last.p = p;
22864+ break;
22865+ }
22866+ }
22867+
4f0767ce 22868+out:
1facf9fc 22869+ /* smp_mb(); */
22870+ AuTraceErr(!valid);
22871+ return valid;
22872+}
22873+
22874+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
22875+{
22876+ int err;
22877+ unsigned int l, deblk_sz;
22878+ union au_vdir_deblk_p deblk_end;
22879+ struct au_vdir *vdir_cache;
22880+ struct au_vdir_de *de;
22881+
22882+ vdir_cache = au_fvdir_cache(file);
22883+ if (!seek_vdir(file))
22884+ return 0;
22885+
22886+ deblk_sz = vdir_cache->vd_deblk_sz;
22887+ while (1) {
22888+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
22889+ deblk_end.deblk += deblk_sz;
22890+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
22891+ de = vdir_cache->vd_last.p.de;
22892+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
22893+ de->de_str.len, de->de_str.name, file->f_pos,
22894+ (unsigned long)de->de_ino, de->de_type);
22895+ err = filldir(dirent, de->de_str.name, de->de_str.len,
22896+ file->f_pos, de->de_ino, de->de_type);
22897+ if (unlikely(err)) {
22898+ AuTraceErr(err);
22899+ /* todo: ignore the error caused by udba? */
22900+ /* return err; */
22901+ return 0;
22902+ }
22903+
22904+ l = calc_size(de->de_str.len);
22905+ vdir_cache->vd_last.p.deblk += l;
22906+ file->f_pos += l;
22907+ }
22908+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
22909+ vdir_cache->vd_last.ul++;
22910+ vdir_cache->vd_last.p.deblk
22911+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
22912+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
22913+ continue;
22914+ }
22915+ break;
22916+ }
22917+
22918+ /* smp_mb(); */
22919+ return 0;
22920+}
e49829fe 22921--- /dev/null
0c5527e5
AM
22922+++ linux-2.6/fs/aufs/vfsub.c 2010-10-26 21:45:14.000000000 +0200
22923@@ -0,0 +1,789 @@
1facf9fc 22924+/*
4a4d8108 22925+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 22926+ *
22927+ * This program, aufs is free software; you can redistribute it and/or modify
22928+ * it under the terms of the GNU General Public License as published by
22929+ * the Free Software Foundation; either version 2 of the License, or
22930+ * (at your option) any later version.
dece6358
AM
22931+ *
22932+ * This program is distributed in the hope that it will be useful,
22933+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22934+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22935+ * GNU General Public License for more details.
22936+ *
22937+ * You should have received a copy of the GNU General Public License
22938+ * along with this program; if not, write to the Free Software
22939+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22940+ */
22941+
22942+/*
22943+ * sub-routines for VFS
22944+ */
22945+
4a4d8108 22946+#include <linux/file.h>
1308ab2a 22947+#include <linux/ima.h>
dece6358
AM
22948+#include <linux/namei.h>
22949+#include <linux/security.h>
22950+#include <linux/splice.h>
1facf9fc 22951+#include <linux/uaccess.h>
22952+#include "aufs.h"
22953+
22954+int vfsub_update_h_iattr(struct path *h_path, int *did)
22955+{
22956+ int err;
22957+ struct kstat st;
22958+ struct super_block *h_sb;
22959+
22960+ /* for remote fs, leave work for its getattr or d_revalidate */
22961+ /* for bad i_attr fs, handle them in aufs_getattr() */
22962+ /* still some fs may acquire i_mutex. we need to skip them */
22963+ err = 0;
22964+ if (!did)
22965+ did = &err;
22966+ h_sb = h_path->dentry->d_sb;
22967+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
22968+ if (*did)
22969+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
22970+
22971+ return err;
22972+}
22973+
22974+/* ---------------------------------------------------------------------- */
22975+
4a4d8108
AM
22976+static int au_conv_oflags(int flags)
22977+{
22978+ int mask = 0;
22979+
22980+#ifdef CONFIG_IMA
22981+ fmode_t fmode;
22982+
22983+ /* mask = MAY_OPEN; */
22984+ fmode = OPEN_FMODE(flags);
22985+ if (fmode & FMODE_READ)
22986+ mask |= MAY_READ;
22987+ if ((fmode & FMODE_WRITE)
22988+ || (flags & O_TRUNC))
22989+ mask |= MAY_WRITE;
22990+ /*
22991+ * if (flags & O_APPEND)
22992+ * mask |= MAY_APPEND;
22993+ */
22994+ if (flags & vfsub_fmode_to_uint(FMODE_EXEC))
22995+ mask |= MAY_EXEC;
22996+
22997+ AuDbg("flags 0x%x, mask 0x%x\n", flags, mask);
22998+#endif
22999+
23000+ return mask;
23001+}
23002+
23003+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 23004+{
23005+ struct file *file;
4a4d8108 23006+ int err;
1308ab2a 23007+
4a4d8108 23008+ path_get(path);
0c5527e5
AM
23009+ file = dentry_open(path->dentry, path->mnt,
23010+ flags | vfsub_fmode_to_uint(FMODE_NONOTIFY),
23011+ current_cred());
1308ab2a 23012+ if (IS_ERR(file))
4a4d8108
AM
23013+ goto out;
23014+
23015+ err = ima_file_check(file, au_conv_oflags(flags));
23016+ if (unlikely(err)) {
23017+ fput(file);
23018+ file = ERR_PTR(err);
23019+ }
23020+out:
1308ab2a 23021+ return file;
23022+}
23023+
1facf9fc 23024+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
23025+{
23026+ struct file *file;
23027+
0c5527e5
AM
23028+ file = filp_open(path, oflags | vfsub_fmode_to_uint(FMODE_NONOTIFY),
23029+ mode);
1facf9fc 23030+ if (IS_ERR(file))
23031+ goto out;
23032+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23033+
4f0767ce 23034+out:
1facf9fc 23035+ return file;
23036+}
23037+
23038+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
23039+{
23040+ int err;
23041+
1facf9fc 23042+ err = kern_path(name, flags, path);
1facf9fc 23043+ if (!err && path->dentry->d_inode)
23044+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
23045+ return err;
23046+}
23047+
23048+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
23049+ int len)
23050+{
23051+ struct path path = {
23052+ .mnt = NULL
23053+ };
23054+
1308ab2a 23055+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 23056+ IMustLock(parent->d_inode);
23057+
23058+ path.dentry = lookup_one_len(name, parent, len);
23059+ if (IS_ERR(path.dentry))
23060+ goto out;
23061+ if (path.dentry->d_inode)
23062+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
23063+
4f0767ce 23064+out:
4a4d8108 23065+ AuTraceErrPtr(path.dentry);
1facf9fc 23066+ return path.dentry;
23067+}
23068+
23069+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
23070+{
23071+ struct path path = {
23072+ .mnt = nd->path.mnt
23073+ };
23074+
23075+ IMustLock(nd->path.dentry->d_inode);
23076+
23077+ path.dentry = lookup_hash(nd);
4a4d8108
AM
23078+ if (IS_ERR(path.dentry))
23079+ goto out;
23080+ if (path.dentry->d_inode)
1facf9fc 23081+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
23082+
4f0767ce 23083+out:
4a4d8108 23084+ AuTraceErrPtr(path.dentry);
1facf9fc 23085+ return path.dentry;
23086+}
23087+
23088+/* ---------------------------------------------------------------------- */
23089+
23090+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
23091+ struct dentry *d2, struct au_hinode *hdir2)
23092+{
23093+ struct dentry *d;
23094+
1facf9fc 23095+ d = lock_rename(d1, d2);
4a4d8108 23096+ au_hn_suspend(hdir1);
1facf9fc 23097+ if (hdir1 != hdir2)
4a4d8108 23098+ au_hn_suspend(hdir2);
1facf9fc 23099+
23100+ return d;
23101+}
23102+
23103+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
23104+ struct dentry *d2, struct au_hinode *hdir2)
23105+{
4a4d8108 23106+ au_hn_resume(hdir1);
1facf9fc 23107+ if (hdir1 != hdir2)
4a4d8108 23108+ au_hn_resume(hdir2);
1facf9fc 23109+ unlock_rename(d1, d2);
1facf9fc 23110+}
23111+
23112+/* ---------------------------------------------------------------------- */
23113+
23114+int vfsub_create(struct inode *dir, struct path *path, int mode)
23115+{
23116+ int err;
23117+ struct dentry *d;
23118+
23119+ IMustLock(dir);
23120+
23121+ d = path->dentry;
23122+ path->dentry = d->d_parent;
b752ccd1 23123+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 23124+ path->dentry = d;
23125+ if (unlikely(err))
23126+ goto out;
23127+
23128+ if (au_test_fs_null_nd(dir->i_sb))
23129+ err = vfs_create(dir, path->dentry, mode, NULL);
23130+ else {
23131+ struct nameidata h_nd;
23132+
23133+ memset(&h_nd, 0, sizeof(h_nd));
23134+ h_nd.flags = LOOKUP_CREATE;
23135+ h_nd.intent.open.flags = O_CREAT
23136+ | vfsub_fmode_to_uint(FMODE_READ);
23137+ h_nd.intent.open.create_mode = mode;
23138+ h_nd.path.dentry = path->dentry->d_parent;
23139+ h_nd.path.mnt = path->mnt;
23140+ path_get(&h_nd.path);
23141+ err = vfs_create(dir, path->dentry, mode, &h_nd);
23142+ path_put(&h_nd.path);
23143+ }
23144+
23145+ if (!err) {
23146+ struct path tmp = *path;
23147+ int did;
23148+
23149+ vfsub_update_h_iattr(&tmp, &did);
23150+ if (did) {
23151+ tmp.dentry = path->dentry->d_parent;
23152+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23153+ }
23154+ /*ignore*/
23155+ }
23156+
4f0767ce 23157+out:
1facf9fc 23158+ return err;
23159+}
23160+
23161+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
23162+{
23163+ int err;
23164+ struct dentry *d;
23165+
23166+ IMustLock(dir);
23167+
23168+ d = path->dentry;
23169+ path->dentry = d->d_parent;
b752ccd1 23170+ err = security_path_symlink(path, d, symname);
1facf9fc 23171+ path->dentry = d;
23172+ if (unlikely(err))
23173+ goto out;
23174+
23175+ err = vfs_symlink(dir, path->dentry, symname);
23176+ if (!err) {
23177+ struct path tmp = *path;
23178+ int did;
23179+
23180+ vfsub_update_h_iattr(&tmp, &did);
23181+ if (did) {
23182+ tmp.dentry = path->dentry->d_parent;
23183+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23184+ }
23185+ /*ignore*/
23186+ }
23187+
4f0767ce 23188+out:
1facf9fc 23189+ return err;
23190+}
23191+
23192+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
23193+{
23194+ int err;
23195+ struct dentry *d;
23196+
23197+ IMustLock(dir);
23198+
23199+ d = path->dentry;
23200+ path->dentry = d->d_parent;
b752ccd1 23201+ err = security_path_mknod(path, d, mode, dev);
1facf9fc 23202+ path->dentry = d;
23203+ if (unlikely(err))
23204+ goto out;
23205+
23206+ err = vfs_mknod(dir, path->dentry, mode, dev);
23207+ if (!err) {
23208+ struct path tmp = *path;
23209+ int did;
23210+
23211+ vfsub_update_h_iattr(&tmp, &did);
23212+ if (did) {
23213+ tmp.dentry = path->dentry->d_parent;
23214+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23215+ }
23216+ /*ignore*/
23217+ }
23218+
4f0767ce 23219+out:
1facf9fc 23220+ return err;
23221+}
23222+
23223+static int au_test_nlink(struct inode *inode)
23224+{
23225+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
23226+
23227+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
23228+ || inode->i_nlink < link_max)
23229+ return 0;
23230+ return -EMLINK;
23231+}
23232+
23233+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
23234+{
23235+ int err;
23236+ struct dentry *d;
23237+
23238+ IMustLock(dir);
23239+
23240+ err = au_test_nlink(src_dentry->d_inode);
23241+ if (unlikely(err))
23242+ return err;
23243+
23244+ d = path->dentry;
23245+ path->dentry = d->d_parent;
b752ccd1 23246+ err = security_path_link(src_dentry, path, d);
1facf9fc 23247+ path->dentry = d;
23248+ if (unlikely(err))
23249+ goto out;
23250+
1facf9fc 23251+ err = vfs_link(src_dentry, dir, path->dentry);
1facf9fc 23252+ if (!err) {
23253+ struct path tmp = *path;
23254+ int did;
23255+
23256+ /* fuse has different memory inode for the same inumber */
23257+ vfsub_update_h_iattr(&tmp, &did);
23258+ if (did) {
23259+ tmp.dentry = path->dentry->d_parent;
23260+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23261+ tmp.dentry = src_dentry;
23262+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23263+ }
23264+ /*ignore*/
23265+ }
23266+
4f0767ce 23267+out:
1facf9fc 23268+ return err;
23269+}
23270+
23271+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
23272+ struct inode *dir, struct path *path)
23273+{
23274+ int err;
23275+ struct path tmp = {
23276+ .mnt = path->mnt
23277+ };
23278+ struct dentry *d;
23279+
23280+ IMustLock(dir);
23281+ IMustLock(src_dir);
23282+
23283+ d = path->dentry;
23284+ path->dentry = d->d_parent;
23285+ tmp.dentry = src_dentry->d_parent;
b752ccd1 23286+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 23287+ path->dentry = d;
23288+ if (unlikely(err))
23289+ goto out;
23290+
1facf9fc 23291+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
1facf9fc 23292+ if (!err) {
23293+ int did;
23294+
23295+ tmp.dentry = d->d_parent;
23296+ vfsub_update_h_iattr(&tmp, &did);
23297+ if (did) {
23298+ tmp.dentry = src_dentry;
23299+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23300+ tmp.dentry = src_dentry->d_parent;
23301+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23302+ }
23303+ /*ignore*/
23304+ }
23305+
4f0767ce 23306+out:
1facf9fc 23307+ return err;
23308+}
23309+
23310+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
23311+{
23312+ int err;
23313+ struct dentry *d;
23314+
23315+ IMustLock(dir);
23316+
23317+ d = path->dentry;
23318+ path->dentry = d->d_parent;
b752ccd1 23319+ err = security_path_mkdir(path, d, mode);
1facf9fc 23320+ path->dentry = d;
23321+ if (unlikely(err))
23322+ goto out;
23323+
23324+ err = vfs_mkdir(dir, path->dentry, mode);
23325+ if (!err) {
23326+ struct path tmp = *path;
23327+ int did;
23328+
23329+ vfsub_update_h_iattr(&tmp, &did);
23330+ if (did) {
23331+ tmp.dentry = path->dentry->d_parent;
23332+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
23333+ }
23334+ /*ignore*/
23335+ }
23336+
4f0767ce 23337+out:
1facf9fc 23338+ return err;
23339+}
23340+
23341+int vfsub_rmdir(struct inode *dir, struct path *path)
23342+{
23343+ int err;
23344+ struct dentry *d;
23345+
23346+ IMustLock(dir);
23347+
23348+ d = path->dentry;
23349+ path->dentry = d->d_parent;
b752ccd1 23350+ err = security_path_rmdir(path, d);
1facf9fc 23351+ path->dentry = d;
23352+ if (unlikely(err))
23353+ goto out;
23354+
1facf9fc 23355+ err = vfs_rmdir(dir, path->dentry);
1facf9fc 23356+ if (!err) {
23357+ struct path tmp = {
23358+ .dentry = path->dentry->d_parent,
23359+ .mnt = path->mnt
23360+ };
23361+
23362+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
23363+ }
23364+
4f0767ce 23365+out:
1facf9fc 23366+ return err;
23367+}
23368+
23369+/* ---------------------------------------------------------------------- */
23370+
23371+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
23372+ loff_t *ppos)
23373+{
23374+ ssize_t err;
23375+
23376+ err = vfs_read(file, ubuf, count, ppos);
23377+ if (err >= 0)
23378+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23379+ return err;
23380+}
23381+
23382+/* todo: kernel_read()? */
23383+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
23384+ loff_t *ppos)
23385+{
23386+ ssize_t err;
23387+ mm_segment_t oldfs;
b752ccd1
AM
23388+ union {
23389+ void *k;
23390+ char __user *u;
23391+ } buf;
1facf9fc 23392+
b752ccd1 23393+ buf.k = kbuf;
1facf9fc 23394+ oldfs = get_fs();
23395+ set_fs(KERNEL_DS);
b752ccd1 23396+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 23397+ set_fs(oldfs);
23398+ return err;
23399+}
23400+
23401+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
23402+ loff_t *ppos)
23403+{
23404+ ssize_t err;
23405+
1facf9fc 23406+ err = vfs_write(file, ubuf, count, ppos);
1facf9fc 23407+ if (err >= 0)
23408+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23409+ return err;
23410+}
23411+
23412+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
23413+{
23414+ ssize_t err;
23415+ mm_segment_t oldfs;
b752ccd1
AM
23416+ union {
23417+ void *k;
23418+ const char __user *u;
23419+ } buf;
1facf9fc 23420+
b752ccd1 23421+ buf.k = kbuf;
1facf9fc 23422+ oldfs = get_fs();
23423+ set_fs(KERNEL_DS);
b752ccd1 23424+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 23425+ set_fs(oldfs);
23426+ return err;
23427+}
23428+
4a4d8108
AM
23429+int vfsub_flush(struct file *file, fl_owner_t id)
23430+{
23431+ int err;
23432+
23433+ err = 0;
23434+ if (file->f_op && file->f_op->flush) {
23435+ err = file->f_op->flush(file, id);
23436+ if (!err)
23437+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
23438+ /*ignore*/
23439+ }
23440+ return err;
23441+}
23442+
1facf9fc 23443+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
23444+{
23445+ int err;
23446+
1facf9fc 23447+ err = vfs_readdir(file, filldir, arg);
1facf9fc 23448+ if (err >= 0)
23449+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
23450+ return err;
23451+}
23452+
23453+long vfsub_splice_to(struct file *in, loff_t *ppos,
23454+ struct pipe_inode_info *pipe, size_t len,
23455+ unsigned int flags)
23456+{
23457+ long err;
23458+
0fc653ad 23459+ err = do_splice_to(in, ppos, pipe, len, flags);
4a4d8108 23460+ file_accessed(in);
1facf9fc 23461+ if (err >= 0)
23462+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
23463+ return err;
23464+}
23465+
23466+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
23467+ loff_t *ppos, size_t len, unsigned int flags)
23468+{
23469+ long err;
23470+
0fc653ad 23471+ err = do_splice_from(pipe, out, ppos, len, flags);
1facf9fc 23472+ if (err >= 0)
23473+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
23474+ return err;
23475+}
23476+
23477+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
23478+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
23479+ struct file *h_file)
23480+{
23481+ int err;
23482+ struct inode *h_inode;
23483+
23484+ h_inode = h_path->dentry->d_inode;
23485+ if (!h_file) {
23486+ err = mnt_want_write(h_path->mnt);
23487+ if (err)
23488+ goto out;
23489+ err = inode_permission(h_inode, MAY_WRITE);
23490+ if (err)
23491+ goto out_mnt;
23492+ err = get_write_access(h_inode);
23493+ if (err)
23494+ goto out_mnt;
4a4d8108 23495+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 23496+ if (err)
23497+ goto out_inode;
23498+ }
23499+
23500+ err = locks_verify_truncate(h_inode, h_file, length);
23501+ if (!err)
953406b4 23502+ err = security_path_truncate(h_path);
b752ccd1 23503+ if (!err)
1facf9fc 23504+ err = do_truncate(h_path->dentry, length, attr, h_file);
1facf9fc 23505+
4f0767ce 23506+out_inode:
1facf9fc 23507+ if (!h_file)
23508+ put_write_access(h_inode);
4f0767ce 23509+out_mnt:
1facf9fc 23510+ if (!h_file)
23511+ mnt_drop_write(h_path->mnt);
4f0767ce 23512+out:
1facf9fc 23513+ return err;
23514+}
23515+
23516+/* ---------------------------------------------------------------------- */
23517+
23518+struct au_vfsub_mkdir_args {
23519+ int *errp;
23520+ struct inode *dir;
23521+ struct path *path;
23522+ int mode;
23523+};
23524+
23525+static void au_call_vfsub_mkdir(void *args)
23526+{
23527+ struct au_vfsub_mkdir_args *a = args;
23528+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
23529+}
23530+
23531+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
23532+{
23533+ int err, do_sio, wkq_err;
23534+
23535+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
23536+ if (!do_sio)
23537+ err = vfsub_mkdir(dir, path, mode);
23538+ else {
23539+ struct au_vfsub_mkdir_args args = {
23540+ .errp = &err,
23541+ .dir = dir,
23542+ .path = path,
23543+ .mode = mode
23544+ };
23545+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
23546+ if (unlikely(wkq_err))
23547+ err = wkq_err;
23548+ }
23549+
23550+ return err;
23551+}
23552+
23553+struct au_vfsub_rmdir_args {
23554+ int *errp;
23555+ struct inode *dir;
23556+ struct path *path;
23557+};
23558+
23559+static void au_call_vfsub_rmdir(void *args)
23560+{
23561+ struct au_vfsub_rmdir_args *a = args;
23562+ *a->errp = vfsub_rmdir(a->dir, a->path);
23563+}
23564+
23565+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
23566+{
23567+ int err, do_sio, wkq_err;
23568+
23569+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
23570+ if (!do_sio)
23571+ err = vfsub_rmdir(dir, path);
23572+ else {
23573+ struct au_vfsub_rmdir_args args = {
23574+ .errp = &err,
23575+ .dir = dir,
23576+ .path = path
23577+ };
23578+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
23579+ if (unlikely(wkq_err))
23580+ err = wkq_err;
23581+ }
23582+
23583+ return err;
23584+}
23585+
23586+/* ---------------------------------------------------------------------- */
23587+
23588+struct notify_change_args {
23589+ int *errp;
23590+ struct path *path;
23591+ struct iattr *ia;
23592+};
23593+
23594+static void call_notify_change(void *args)
23595+{
23596+ struct notify_change_args *a = args;
23597+ struct inode *h_inode;
23598+
23599+ h_inode = a->path->dentry->d_inode;
23600+ IMustLock(h_inode);
23601+
23602+ *a->errp = -EPERM;
23603+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 23604+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 23605+ if (!*a->errp)
23606+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
23607+ }
23608+ AuTraceErr(*a->errp);
23609+}
23610+
23611+int vfsub_notify_change(struct path *path, struct iattr *ia)
23612+{
23613+ int err;
23614+ struct notify_change_args args = {
23615+ .errp = &err,
23616+ .path = path,
23617+ .ia = ia
23618+ };
23619+
23620+ call_notify_change(&args);
23621+
23622+ return err;
23623+}
23624+
23625+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
23626+{
23627+ int err, wkq_err;
23628+ struct notify_change_args args = {
23629+ .errp = &err,
23630+ .path = path,
23631+ .ia = ia
23632+ };
23633+
23634+ wkq_err = au_wkq_wait(call_notify_change, &args);
23635+ if (unlikely(wkq_err))
23636+ err = wkq_err;
23637+
23638+ return err;
23639+}
23640+
23641+/* ---------------------------------------------------------------------- */
23642+
23643+struct unlink_args {
23644+ int *errp;
23645+ struct inode *dir;
23646+ struct path *path;
23647+};
23648+
23649+static void call_unlink(void *args)
23650+{
23651+ struct unlink_args *a = args;
23652+ struct dentry *d = a->path->dentry;
23653+ struct inode *h_inode;
23654+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
23655+ && atomic_read(&d->d_count) == 1);
23656+
23657+ IMustLock(a->dir);
23658+
23659+ a->path->dentry = d->d_parent;
23660+ *a->errp = security_path_unlink(a->path, d);
23661+ a->path->dentry = d;
23662+ if (unlikely(*a->errp))
23663+ return;
23664+
23665+ if (!stop_sillyrename)
23666+ dget(d);
23667+ h_inode = d->d_inode;
23668+ if (h_inode)
23669+ atomic_inc(&h_inode->i_count);
23670+
1facf9fc 23671+ *a->errp = vfs_unlink(a->dir, d);
1facf9fc 23672+ if (!*a->errp) {
23673+ struct path tmp = {
23674+ .dentry = d->d_parent,
23675+ .mnt = a->path->mnt
23676+ };
23677+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
23678+ }
23679+
23680+ if (!stop_sillyrename)
23681+ dput(d);
23682+ if (h_inode)
23683+ iput(h_inode);
23684+
23685+ AuTraceErr(*a->errp);
23686+}
23687+
23688+/*
23689+ * @dir: must be locked.
23690+ * @dentry: target dentry.
23691+ */
23692+int vfsub_unlink(struct inode *dir, struct path *path, int force)
23693+{
23694+ int err;
23695+ struct unlink_args args = {
23696+ .errp = &err,
23697+ .dir = dir,
23698+ .path = path
23699+ };
23700+
23701+ if (!force)
23702+ call_unlink(&args);
23703+ else {
23704+ int wkq_err;
23705+
23706+ wkq_err = au_wkq_wait(call_unlink, &args);
23707+ if (unlikely(wkq_err))
23708+ err = wkq_err;
23709+ }
23710+
23711+ return err;
23712+}
e49829fe 23713--- /dev/null
0c5527e5
AM
23714+++ linux-2.6/fs/aufs/vfsub.h 2010-11-02 08:19:59.000000000 +0100
23715@@ -0,0 +1,208 @@
1facf9fc 23716+/*
4a4d8108 23717+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 23718+ *
23719+ * This program, aufs is free software; you can redistribute it and/or modify
23720+ * it under the terms of the GNU General Public License as published by
23721+ * the Free Software Foundation; either version 2 of the License, or
23722+ * (at your option) any later version.
dece6358
AM
23723+ *
23724+ * This program is distributed in the hope that it will be useful,
23725+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23726+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23727+ * GNU General Public License for more details.
23728+ *
23729+ * You should have received a copy of the GNU General Public License
23730+ * along with this program; if not, write to the Free Software
23731+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23732+ */
23733+
23734+/*
23735+ * sub-routines for VFS
23736+ */
23737+
23738+#ifndef __AUFS_VFSUB_H__
23739+#define __AUFS_VFSUB_H__
23740+
23741+#ifdef __KERNEL__
23742+
23743+#include <linux/fs.h>
0c5527e5 23744+#include <linux/lglock.h>
1facf9fc 23745+
23746+/* ---------------------------------------------------------------------- */
0c5527e5
AM
23747+DECLARE_BRLOCK(vfsmount_lock);
23748+DECLARE_LGLOCK(files_lglock);
23749+extern void file_sb_list_del(struct file *f);
23750+
23751+/* copied from fs/file_table.c */
23752+#ifdef CONFIG_SMP
23753+/*
23754+ * These macros iterate all files on all CPUs for a given superblock.
23755+ * files_lglock must be held globally.
23756+ */
23757+#define do_file_list_for_each_entry(__sb, __file) \
23758+{ \
23759+ int i; \
23760+ for_each_possible_cpu(i) { \
23761+ struct list_head *list; \
23762+ list = per_cpu_ptr((__sb)->s_files, i); \
23763+ list_for_each_entry((__file), list, f_u.fu_list)
23764+
23765+#define while_file_list_for_each_entry \
23766+ } \
23767+}
23768+
23769+#else
23770+
23771+#define do_file_list_for_each_entry(__sb, __file) \
23772+{ \
23773+ struct list_head *list; \
23774+ list = &(sb)->s_files; \
23775+ list_for_each_entry((__file), list, f_u.fu_list)
23776+
23777+#define while_file_list_for_each_entry \
23778+}
23779+#endif /* CONFIG_SMP */
1facf9fc 23780+
23781+/* lock subclass for lower inode */
23782+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
23783+/* reduce? gave up. */
23784+enum {
23785+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
23786+ AuLsc_I_PARENT, /* lower inode, parent first */
23787+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 23788+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 23789+ AuLsc_I_CHILD,
23790+ AuLsc_I_CHILD2,
23791+ AuLsc_I_End
23792+};
23793+
23794+/* to debug easier, do not make them inlined functions */
23795+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
23796+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
23797+
23798+/* ---------------------------------------------------------------------- */
23799+
1facf9fc 23800+int vfsub_update_h_iattr(struct path *h_path, int *did);
4a4d8108 23801+struct file *vfsub_dentry_open(struct path *path, int flags);
1facf9fc 23802+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
23803+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
23804+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
23805+ int len);
23806+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
23807+
23808+/* ---------------------------------------------------------------------- */
23809+
23810+struct au_hinode;
23811+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
23812+ struct dentry *d2, struct au_hinode *hdir2);
23813+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
23814+ struct dentry *d2, struct au_hinode *hdir2);
23815+
23816+int vfsub_create(struct inode *dir, struct path *path, int mode);
23817+int vfsub_symlink(struct inode *dir, struct path *path,
23818+ const char *symname);
23819+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
23820+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
23821+ struct path *path);
23822+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
23823+ struct inode *hdir, struct path *path);
23824+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
23825+int vfsub_rmdir(struct inode *dir, struct path *path);
23826+
23827+/* ---------------------------------------------------------------------- */
23828+
23829+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
23830+ loff_t *ppos);
23831+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
23832+ loff_t *ppos);
23833+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
23834+ loff_t *ppos);
23835+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
23836+ loff_t *ppos);
4a4d8108 23837+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 23838+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
23839+
4a4d8108
AM
23840+static inline unsigned int vfsub_file_flags(struct file *file)
23841+{
23842+ unsigned int flags;
23843+
23844+ spin_lock(&file->f_lock);
23845+ flags = file->f_flags;
23846+ spin_unlock(&file->f_lock);
23847+
23848+ return flags;
23849+}
1308ab2a 23850+
1facf9fc 23851+static inline void vfsub_file_accessed(struct file *h_file)
23852+{
23853+ file_accessed(h_file);
23854+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
23855+}
23856+
23857+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
23858+ struct dentry *h_dentry)
23859+{
23860+ struct path h_path = {
23861+ .dentry = h_dentry,
23862+ .mnt = h_mnt
23863+ };
23864+ touch_atime(h_mnt, h_dentry);
23865+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
23866+}
23867+
4a4d8108
AM
23868+long vfsub_splice_to(struct file *in, loff_t *ppos,
23869+ struct pipe_inode_info *pipe, size_t len,
23870+ unsigned int flags);
23871+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
23872+ loff_t *ppos, size_t len, unsigned int flags);
23873+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
23874+ struct file *h_file);
23875+
1facf9fc 23876+/* ---------------------------------------------------------------------- */
23877+
23878+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
23879+{
23880+ loff_t err;
23881+
1facf9fc 23882+ err = vfs_llseek(file, offset, origin);
1facf9fc 23883+ return err;
23884+}
23885+
23886+/* ---------------------------------------------------------------------- */
23887+
23888+/* dirty workaround for strict type of fmode_t */
23889+union vfsub_fmu {
23890+ fmode_t fm;
23891+ unsigned int ui;
23892+};
23893+
23894+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
23895+{
23896+ union vfsub_fmu u = {
23897+ .fm = fm
23898+ };
23899+
23900+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
23901+
23902+ return u.ui;
23903+}
23904+
23905+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
23906+{
23907+ union vfsub_fmu u = {
23908+ .ui = ui
23909+ };
23910+
23911+ return u.fm;
23912+}
23913+
4a4d8108
AM
23914+/* ---------------------------------------------------------------------- */
23915+
23916+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
23917+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
23918+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
23919+int vfsub_notify_change(struct path *path, struct iattr *ia);
23920+int vfsub_unlink(struct inode *dir, struct path *path, int force);
23921+
1facf9fc 23922+#endif /* __KERNEL__ */
23923+#endif /* __AUFS_VFSUB_H__ */
e49829fe 23924--- /dev/null
0c5527e5
AM
23925+++ linux-2.6/fs/aufs/wbr_policy.c 2010-11-02 08:24:52.000000000 +0100
23926@@ -0,0 +1,696 @@
1facf9fc 23927+/*
4a4d8108 23928+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 23929+ *
23930+ * This program, aufs is free software; you can redistribute it and/or modify
23931+ * it under the terms of the GNU General Public License as published by
23932+ * the Free Software Foundation; either version 2 of the License, or
23933+ * (at your option) any later version.
dece6358
AM
23934+ *
23935+ * This program is distributed in the hope that it will be useful,
23936+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23937+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23938+ * GNU General Public License for more details.
23939+ *
23940+ * You should have received a copy of the GNU General Public License
23941+ * along with this program; if not, write to the Free Software
23942+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23943+ */
23944+
23945+/*
23946+ * policies for selecting one among multiple writable branches
23947+ */
23948+
23949+#include <linux/statfs.h>
23950+#include "aufs.h"
23951+
23952+/* subset of cpup_attr() */
23953+static noinline_for_stack
23954+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
23955+{
23956+ int err, sbits;
23957+ struct iattr ia;
23958+ struct inode *h_isrc;
23959+
23960+ h_isrc = h_src->d_inode;
23961+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
23962+ ia.ia_mode = h_isrc->i_mode;
23963+ ia.ia_uid = h_isrc->i_uid;
23964+ ia.ia_gid = h_isrc->i_gid;
23965+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
23966+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
23967+ err = vfsub_sio_notify_change(h_path, &ia);
23968+
23969+ /* is this nfs only? */
23970+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
23971+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
23972+ ia.ia_mode = h_isrc->i_mode;
23973+ err = vfsub_sio_notify_change(h_path, &ia);
23974+ }
23975+
23976+ return err;
23977+}
23978+
23979+#define AuCpdown_PARENT_OPQ 1
23980+#define AuCpdown_WHED (1 << 1)
23981+#define AuCpdown_MADE_DIR (1 << 2)
23982+#define AuCpdown_DIROPQ (1 << 3)
23983+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
23984+#define au_fset_cpdown(flags, name) { (flags) |= AuCpdown_##name; }
23985+#define au_fclr_cpdown(flags, name) { (flags) &= ~AuCpdown_##name; }
23986+
23987+struct au_cpdown_dir_args {
23988+ struct dentry *parent;
23989+ unsigned int flags;
23990+};
23991+
23992+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
23993+ struct au_cpdown_dir_args *a)
23994+{
23995+ int err;
23996+ struct dentry *opq_dentry;
23997+
23998+ opq_dentry = au_diropq_create(dentry, bdst);
23999+ err = PTR_ERR(opq_dentry);
24000+ if (IS_ERR(opq_dentry))
24001+ goto out;
24002+ dput(opq_dentry);
24003+ au_fset_cpdown(a->flags, DIROPQ);
24004+
4f0767ce 24005+out:
1facf9fc 24006+ return err;
24007+}
24008+
24009+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
24010+ struct inode *dir, aufs_bindex_t bdst)
24011+{
24012+ int err;
24013+ struct path h_path;
24014+ struct au_branch *br;
24015+
24016+ br = au_sbr(dentry->d_sb, bdst);
24017+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
24018+ err = PTR_ERR(h_path.dentry);
24019+ if (IS_ERR(h_path.dentry))
24020+ goto out;
24021+
24022+ err = 0;
24023+ if (h_path.dentry->d_inode) {
24024+ h_path.mnt = br->br_mnt;
24025+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
24026+ dentry);
24027+ }
24028+ dput(h_path.dentry);
24029+
4f0767ce 24030+out:
1facf9fc 24031+ return err;
24032+}
24033+
24034+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
24035+ struct dentry *h_parent, void *arg)
24036+{
24037+ int err, rerr;
4a4d8108 24038+ aufs_bindex_t bopq, bstart;
1facf9fc 24039+ struct path h_path;
24040+ struct dentry *parent;
24041+ struct inode *h_dir, *h_inode, *inode, *dir;
24042+ struct au_cpdown_dir_args *args = arg;
24043+
24044+ bstart = au_dbstart(dentry);
24045+ /* dentry is di-locked */
24046+ parent = dget_parent(dentry);
24047+ dir = parent->d_inode;
24048+ h_dir = h_parent->d_inode;
24049+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
24050+ IMustLock(h_dir);
24051+
24052+ err = au_lkup_neg(dentry, bdst);
24053+ if (unlikely(err < 0))
24054+ goto out;
24055+ h_path.dentry = au_h_dptr(dentry, bdst);
24056+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
24057+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
24058+ S_IRWXU | S_IRUGO | S_IXUGO);
24059+ if (unlikely(err))
24060+ goto out_put;
24061+ au_fset_cpdown(args->flags, MADE_DIR);
24062+
1facf9fc 24063+ bopq = au_dbdiropq(dentry);
24064+ au_fclr_cpdown(args->flags, WHED);
24065+ au_fclr_cpdown(args->flags, DIROPQ);
24066+ if (au_dbwh(dentry) == bdst)
24067+ au_fset_cpdown(args->flags, WHED);
24068+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
24069+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 24070+ h_inode = h_path.dentry->d_inode;
24071+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
24072+ if (au_ftest_cpdown(args->flags, WHED)) {
24073+ err = au_cpdown_dir_opq(dentry, bdst, args);
24074+ if (unlikely(err)) {
24075+ mutex_unlock(&h_inode->i_mutex);
24076+ goto out_dir;
24077+ }
24078+ }
24079+
24080+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
24081+ mutex_unlock(&h_inode->i_mutex);
24082+ if (unlikely(err))
24083+ goto out_opq;
24084+
24085+ if (au_ftest_cpdown(args->flags, WHED)) {
24086+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
24087+ if (unlikely(err))
24088+ goto out_opq;
24089+ }
24090+
24091+ inode = dentry->d_inode;
24092+ if (au_ibend(inode) < bdst)
24093+ au_set_ibend(inode, bdst);
24094+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
24095+ au_hi_flags(inode, /*isdir*/1));
24096+ goto out; /* success */
24097+
24098+ /* revert */
4f0767ce 24099+out_opq:
1facf9fc 24100+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
24101+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
24102+ rerr = au_diropq_remove(dentry, bdst);
24103+ mutex_unlock(&h_inode->i_mutex);
24104+ if (unlikely(rerr)) {
24105+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
24106+ AuDLNPair(dentry), bdst, rerr);
24107+ err = -EIO;
24108+ goto out;
24109+ }
24110+ }
4f0767ce 24111+out_dir:
1facf9fc 24112+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
24113+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
24114+ if (unlikely(rerr)) {
24115+ AuIOErr("failed removing %.*s b%d (%d)\n",
24116+ AuDLNPair(dentry), bdst, rerr);
24117+ err = -EIO;
24118+ }
24119+ }
4f0767ce 24120+out_put:
1facf9fc 24121+ au_set_h_dptr(dentry, bdst, NULL);
24122+ if (au_dbend(dentry) == bdst)
24123+ au_update_dbend(dentry);
4f0767ce 24124+out:
1facf9fc 24125+ dput(parent);
24126+ return err;
24127+}
24128+
24129+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
24130+{
24131+ int err;
24132+ struct au_cpdown_dir_args args = {
24133+ .parent = dget_parent(dentry),
24134+ .flags = 0
24135+ };
24136+
24137+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
24138+ dput(args.parent);
24139+
24140+ return err;
24141+}
24142+
24143+/* ---------------------------------------------------------------------- */
24144+
24145+/* policies for create */
24146+
4a4d8108
AM
24147+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
24148+{
24149+ int err, i, j, ndentry;
24150+ aufs_bindex_t bopq;
24151+ struct au_dcsub_pages dpages;
24152+ struct au_dpage *dpage;
24153+ struct dentry **dentries, *parent, *d;
24154+
24155+ err = au_dpages_init(&dpages, GFP_NOFS);
24156+ if (unlikely(err))
24157+ goto out;
24158+ parent = dget_parent(dentry);
24159+ err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/0, /*test*/NULL,
24160+ /*arg*/NULL);
24161+ if (unlikely(err))
24162+ goto out_free;
24163+
24164+ err = bindex;
24165+ for (i = 0; i < dpages.ndpage; i++) {
24166+ dpage = dpages.dpages + i;
24167+ dentries = dpage->dentries;
24168+ ndentry = dpage->ndentry;
24169+ for (j = 0; j < ndentry; j++) {
24170+ d = dentries[j];
24171+ di_read_lock_parent2(d, !AuLock_IR);
24172+ bopq = au_dbdiropq(d);
24173+ di_read_unlock(d, !AuLock_IR);
24174+ if (bopq >= 0 && bopq < err)
24175+ err = bopq;
24176+ }
24177+ }
24178+
24179+out_free:
24180+ dput(parent);
24181+ au_dpages_free(&dpages);
24182+out:
24183+ return err;
24184+}
24185+
1facf9fc 24186+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
24187+{
24188+ for (; bindex >= 0; bindex--)
24189+ if (!au_br_rdonly(au_sbr(sb, bindex)))
24190+ return bindex;
24191+ return -EROFS;
24192+}
24193+
24194+/* top down parent */
24195+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
24196+{
24197+ int err;
24198+ aufs_bindex_t bstart, bindex;
24199+ struct super_block *sb;
24200+ struct dentry *parent, *h_parent;
24201+
24202+ sb = dentry->d_sb;
24203+ bstart = au_dbstart(dentry);
24204+ err = bstart;
24205+ if (!au_br_rdonly(au_sbr(sb, bstart)))
24206+ goto out;
24207+
24208+ err = -EROFS;
24209+ parent = dget_parent(dentry);
24210+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
24211+ h_parent = au_h_dptr(parent, bindex);
24212+ if (!h_parent || !h_parent->d_inode)
24213+ continue;
24214+
24215+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
24216+ err = bindex;
24217+ break;
24218+ }
24219+ }
24220+ dput(parent);
24221+
24222+ /* bottom up here */
4a4d8108 24223+ if (unlikely(err < 0)) {
1facf9fc 24224+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
24225+ if (err >= 0)
24226+ err = au_wbr_nonopq(dentry, err);
24227+ }
1facf9fc 24228+
4f0767ce 24229+out:
1facf9fc 24230+ AuDbg("b%d\n", err);
24231+ return err;
24232+}
24233+
24234+/* ---------------------------------------------------------------------- */
24235+
24236+/* an exception for the policy other than tdp */
24237+static int au_wbr_create_exp(struct dentry *dentry)
24238+{
24239+ int err;
24240+ aufs_bindex_t bwh, bdiropq;
24241+ struct dentry *parent;
24242+
24243+ err = -1;
24244+ bwh = au_dbwh(dentry);
24245+ parent = dget_parent(dentry);
24246+ bdiropq = au_dbdiropq(parent);
24247+ if (bwh >= 0) {
24248+ if (bdiropq >= 0)
24249+ err = min(bdiropq, bwh);
24250+ else
24251+ err = bwh;
24252+ AuDbg("%d\n", err);
24253+ } else if (bdiropq >= 0) {
24254+ err = bdiropq;
24255+ AuDbg("%d\n", err);
24256+ }
24257+ dput(parent);
24258+
4a4d8108
AM
24259+ if (err >= 0)
24260+ err = au_wbr_nonopq(dentry, err);
24261+
1facf9fc 24262+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
24263+ err = -1;
24264+
24265+ AuDbg("%d\n", err);
24266+ return err;
24267+}
24268+
24269+/* ---------------------------------------------------------------------- */
24270+
24271+/* round robin */
24272+static int au_wbr_create_init_rr(struct super_block *sb)
24273+{
24274+ int err;
24275+
24276+ err = au_wbr_bu(sb, au_sbend(sb));
24277+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 24278+ /* smp_mb(); */
1facf9fc 24279+
24280+ AuDbg("b%d\n", err);
24281+ return err;
24282+}
24283+
24284+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
24285+{
24286+ int err, nbr;
24287+ unsigned int u;
24288+ aufs_bindex_t bindex, bend;
24289+ struct super_block *sb;
24290+ atomic_t *next;
24291+
24292+ err = au_wbr_create_exp(dentry);
24293+ if (err >= 0)
24294+ goto out;
24295+
24296+ sb = dentry->d_sb;
24297+ next = &au_sbi(sb)->si_wbr_rr_next;
24298+ bend = au_sbend(sb);
24299+ nbr = bend + 1;
24300+ for (bindex = 0; bindex <= bend; bindex++) {
24301+ if (!isdir) {
24302+ err = atomic_dec_return(next) + 1;
24303+ /* modulo for 0 is meaningless */
24304+ if (unlikely(!err))
24305+ err = atomic_dec_return(next) + 1;
24306+ } else
24307+ err = atomic_read(next);
24308+ AuDbg("%d\n", err);
24309+ u = err;
24310+ err = u % nbr;
24311+ AuDbg("%d\n", err);
24312+ if (!au_br_rdonly(au_sbr(sb, err)))
24313+ break;
24314+ err = -EROFS;
24315+ }
24316+
4a4d8108
AM
24317+ if (err >= 0)
24318+ err = au_wbr_nonopq(dentry, err);
24319+
4f0767ce 24320+out:
1facf9fc 24321+ AuDbg("%d\n", err);
24322+ return err;
24323+}
24324+
24325+/* ---------------------------------------------------------------------- */
24326+
24327+/* most free space */
24328+static void au_mfs(struct dentry *dentry)
24329+{
24330+ struct super_block *sb;
24331+ struct au_branch *br;
24332+ struct au_wbr_mfs *mfs;
24333+ aufs_bindex_t bindex, bend;
24334+ int err;
24335+ unsigned long long b, bavail;
24336+ /* reduce the stack usage */
24337+ struct kstatfs *st;
24338+
24339+ st = kmalloc(sizeof(*st), GFP_NOFS);
24340+ if (unlikely(!st)) {
24341+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
24342+ return;
24343+ }
24344+
24345+ bavail = 0;
24346+ sb = dentry->d_sb;
24347+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 24348+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 24349+ mfs->mfs_bindex = -EROFS;
24350+ mfs->mfsrr_bytes = 0;
24351+ bend = au_sbend(sb);
24352+ for (bindex = 0; bindex <= bend; bindex++) {
24353+ br = au_sbr(sb, bindex);
24354+ if (au_br_rdonly(br))
24355+ continue;
24356+
24357+ /* sb->s_root for NFS is unreliable */
0c5527e5 24358+ err = statfs_by_dentry(br->br_mnt->mnt_root, st);
1facf9fc 24359+ if (unlikely(err)) {
24360+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
24361+ continue;
24362+ }
24363+
24364+ /* when the available size is equal, select the lower one */
24365+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
24366+ || sizeof(b) < sizeof(st->f_bsize));
24367+ b = st->f_bavail * st->f_bsize;
24368+ br->br_wbr->wbr_bytes = b;
24369+ if (b >= bavail) {
24370+ bavail = b;
24371+ mfs->mfs_bindex = bindex;
24372+ mfs->mfs_jiffy = jiffies;
24373+ }
24374+ }
24375+
24376+ mfs->mfsrr_bytes = bavail;
24377+ AuDbg("b%d\n", mfs->mfs_bindex);
24378+ kfree(st);
24379+}
24380+
24381+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
24382+{
24383+ int err;
24384+ struct super_block *sb;
24385+ struct au_wbr_mfs *mfs;
24386+
24387+ err = au_wbr_create_exp(dentry);
24388+ if (err >= 0)
24389+ goto out;
24390+
24391+ sb = dentry->d_sb;
24392+ mfs = &au_sbi(sb)->si_wbr_mfs;
24393+ mutex_lock(&mfs->mfs_lock);
24394+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
24395+ || mfs->mfs_bindex < 0
24396+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
24397+ au_mfs(dentry);
24398+ mutex_unlock(&mfs->mfs_lock);
24399+ err = mfs->mfs_bindex;
24400+
4a4d8108
AM
24401+ if (err >= 0)
24402+ err = au_wbr_nonopq(dentry, err);
24403+
4f0767ce 24404+out:
1facf9fc 24405+ AuDbg("b%d\n", err);
24406+ return err;
24407+}
24408+
24409+static int au_wbr_create_init_mfs(struct super_block *sb)
24410+{
24411+ struct au_wbr_mfs *mfs;
24412+
24413+ mfs = &au_sbi(sb)->si_wbr_mfs;
24414+ mutex_init(&mfs->mfs_lock);
24415+ mfs->mfs_jiffy = 0;
24416+ mfs->mfs_bindex = -EROFS;
24417+
24418+ return 0;
24419+}
24420+
24421+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
24422+{
24423+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
24424+ return 0;
24425+}
24426+
24427+/* ---------------------------------------------------------------------- */
24428+
24429+/* most free space and then round robin */
24430+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
24431+{
24432+ int err;
24433+ struct au_wbr_mfs *mfs;
24434+
24435+ err = au_wbr_create_mfs(dentry, isdir);
24436+ if (err >= 0) {
24437+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 24438+ mutex_lock(&mfs->mfs_lock);
1facf9fc 24439+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
24440+ err = au_wbr_create_rr(dentry, isdir);
dece6358 24441+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 24442+ }
24443+
24444+ AuDbg("b%d\n", err);
24445+ return err;
24446+}
24447+
24448+static int au_wbr_create_init_mfsrr(struct super_block *sb)
24449+{
24450+ int err;
24451+
24452+ au_wbr_create_init_mfs(sb); /* ignore */
24453+ err = au_wbr_create_init_rr(sb);
24454+
24455+ return err;
24456+}
24457+
24458+/* ---------------------------------------------------------------------- */
24459+
24460+/* top down parent and most free space */
24461+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
24462+{
24463+ int err, e2;
24464+ unsigned long long b;
24465+ aufs_bindex_t bindex, bstart, bend;
24466+ struct super_block *sb;
24467+ struct dentry *parent, *h_parent;
24468+ struct au_branch *br;
24469+
24470+ err = au_wbr_create_tdp(dentry, isdir);
24471+ if (unlikely(err < 0))
24472+ goto out;
24473+ parent = dget_parent(dentry);
24474+ bstart = au_dbstart(parent);
24475+ bend = au_dbtaildir(parent);
24476+ if (bstart == bend)
24477+ goto out_parent; /* success */
24478+
24479+ e2 = au_wbr_create_mfs(dentry, isdir);
24480+ if (e2 < 0)
24481+ goto out_parent; /* success */
24482+
24483+ /* when the available size is equal, select upper one */
24484+ sb = dentry->d_sb;
24485+ br = au_sbr(sb, err);
24486+ b = br->br_wbr->wbr_bytes;
24487+ AuDbg("b%d, %llu\n", err, b);
24488+
24489+ for (bindex = bstart; bindex <= bend; bindex++) {
24490+ h_parent = au_h_dptr(parent, bindex);
24491+ if (!h_parent || !h_parent->d_inode)
24492+ continue;
24493+
24494+ br = au_sbr(sb, bindex);
24495+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
24496+ b = br->br_wbr->wbr_bytes;
24497+ err = bindex;
24498+ AuDbg("b%d, %llu\n", err, b);
24499+ }
24500+ }
24501+
4a4d8108
AM
24502+ if (err >= 0)
24503+ err = au_wbr_nonopq(dentry, err);
24504+
4f0767ce 24505+out_parent:
1facf9fc 24506+ dput(parent);
4f0767ce 24507+out:
1facf9fc 24508+ AuDbg("b%d\n", err);
24509+ return err;
24510+}
24511+
24512+/* ---------------------------------------------------------------------- */
24513+
24514+/* policies for copyup */
24515+
24516+/* top down parent */
24517+static int au_wbr_copyup_tdp(struct dentry *dentry)
24518+{
24519+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
24520+}
24521+
24522+/* bottom up parent */
24523+static int au_wbr_copyup_bup(struct dentry *dentry)
24524+{
24525+ int err;
24526+ aufs_bindex_t bindex, bstart;
24527+ struct dentry *parent, *h_parent;
24528+ struct super_block *sb;
24529+
24530+ err = -EROFS;
24531+ sb = dentry->d_sb;
24532+ parent = dget_parent(dentry);
24533+ bstart = au_dbstart(parent);
24534+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
24535+ h_parent = au_h_dptr(parent, bindex);
24536+ if (!h_parent || !h_parent->d_inode)
24537+ continue;
24538+
24539+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
24540+ err = bindex;
24541+ break;
24542+ }
24543+ }
24544+ dput(parent);
24545+
24546+ /* bottom up here */
24547+ if (unlikely(err < 0))
24548+ err = au_wbr_bu(sb, bstart - 1);
24549+
24550+ AuDbg("b%d\n", err);
24551+ return err;
24552+}
24553+
24554+/* bottom up */
24555+static int au_wbr_copyup_bu(struct dentry *dentry)
24556+{
24557+ int err;
4a4d8108 24558+ aufs_bindex_t bstart;
1facf9fc 24559+
4a4d8108
AM
24560+ bstart = au_dbstart(dentry);
24561+ err = au_wbr_bu(dentry->d_sb, bstart);
24562+ AuDbg("b%d\n", err);
24563+ if (err > bstart)
24564+ err = au_wbr_nonopq(dentry, err);
1facf9fc 24565+
24566+ AuDbg("b%d\n", err);
24567+ return err;
24568+}
24569+
24570+/* ---------------------------------------------------------------------- */
24571+
24572+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
24573+ [AuWbrCopyup_TDP] = {
24574+ .copyup = au_wbr_copyup_tdp
24575+ },
24576+ [AuWbrCopyup_BUP] = {
24577+ .copyup = au_wbr_copyup_bup
24578+ },
24579+ [AuWbrCopyup_BU] = {
24580+ .copyup = au_wbr_copyup_bu
24581+ }
24582+};
24583+
24584+struct au_wbr_create_operations au_wbr_create_ops[] = {
24585+ [AuWbrCreate_TDP] = {
24586+ .create = au_wbr_create_tdp
24587+ },
24588+ [AuWbrCreate_RR] = {
24589+ .create = au_wbr_create_rr,
24590+ .init = au_wbr_create_init_rr
24591+ },
24592+ [AuWbrCreate_MFS] = {
24593+ .create = au_wbr_create_mfs,
24594+ .init = au_wbr_create_init_mfs,
24595+ .fin = au_wbr_create_fin_mfs
24596+ },
24597+ [AuWbrCreate_MFSV] = {
24598+ .create = au_wbr_create_mfs,
24599+ .init = au_wbr_create_init_mfs,
24600+ .fin = au_wbr_create_fin_mfs
24601+ },
24602+ [AuWbrCreate_MFSRR] = {
24603+ .create = au_wbr_create_mfsrr,
24604+ .init = au_wbr_create_init_mfsrr,
24605+ .fin = au_wbr_create_fin_mfs
24606+ },
24607+ [AuWbrCreate_MFSRRV] = {
24608+ .create = au_wbr_create_mfsrr,
24609+ .init = au_wbr_create_init_mfsrr,
24610+ .fin = au_wbr_create_fin_mfs
24611+ },
24612+ [AuWbrCreate_PMFS] = {
24613+ .create = au_wbr_create_pmfs,
24614+ .init = au_wbr_create_init_mfs,
24615+ .fin = au_wbr_create_fin_mfs
24616+ },
24617+ [AuWbrCreate_PMFSV] = {
24618+ .create = au_wbr_create_pmfs,
24619+ .init = au_wbr_create_init_mfs,
24620+ .fin = au_wbr_create_fin_mfs
24621+ }
24622+};
e49829fe 24623--- /dev/null
0c5527e5 24624+++ linux-2.6/fs/aufs/whout.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 24625@@ -0,0 +1,1059 @@
1facf9fc 24626+/*
4a4d8108 24627+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 24628+ *
24629+ * This program, aufs is free software; you can redistribute it and/or modify
24630+ * it under the terms of the GNU General Public License as published by
24631+ * the Free Software Foundation; either version 2 of the License, or
24632+ * (at your option) any later version.
dece6358
AM
24633+ *
24634+ * This program is distributed in the hope that it will be useful,
24635+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24636+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24637+ * GNU General Public License for more details.
24638+ *
24639+ * You should have received a copy of the GNU General Public License
24640+ * along with this program; if not, write to the Free Software
24641+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24642+ */
24643+
24644+/*
24645+ * whiteout for logical deletion and opaque directory
24646+ */
24647+
24648+#include <linux/fs.h>
24649+#include "aufs.h"
24650+
24651+#define WH_MASK S_IRUGO
24652+
24653+/*
24654+ * If a directory contains this file, then it is opaque. We start with the
24655+ * .wh. flag so that it is blocked by lookup.
24656+ */
24657+static struct qstr diropq_name = {
24658+ .name = AUFS_WH_DIROPQ,
24659+ .len = sizeof(AUFS_WH_DIROPQ) - 1
24660+};
24661+
24662+/*
24663+ * generate whiteout name, which is NOT terminated by NULL.
24664+ * @name: original d_name.name
24665+ * @len: original d_name.len
24666+ * @wh: whiteout qstr
24667+ * returns zero when succeeds, otherwise error.
24668+ * succeeded value as wh->name should be freed by kfree().
24669+ */
24670+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
24671+{
24672+ char *p;
24673+
24674+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
24675+ return -ENAMETOOLONG;
24676+
24677+ wh->len = name->len + AUFS_WH_PFX_LEN;
24678+ p = kmalloc(wh->len, GFP_NOFS);
24679+ wh->name = p;
24680+ if (p) {
24681+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
24682+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
24683+ /* smp_mb(); */
24684+ return 0;
24685+ }
24686+ return -ENOMEM;
24687+}
24688+
24689+/* ---------------------------------------------------------------------- */
24690+
24691+/*
24692+ * test if the @wh_name exists under @h_parent.
24693+ * @try_sio specifies the necessary of super-io.
24694+ */
24695+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
24696+ struct au_branch *br, int try_sio)
24697+{
24698+ int err;
24699+ struct dentry *wh_dentry;
1facf9fc 24700+
1facf9fc 24701+ if (!try_sio)
24702+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
24703+ else
24704+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
24705+ err = PTR_ERR(wh_dentry);
24706+ if (IS_ERR(wh_dentry))
24707+ goto out;
24708+
24709+ err = 0;
24710+ if (!wh_dentry->d_inode)
24711+ goto out_wh; /* success */
24712+
24713+ err = 1;
24714+ if (S_ISREG(wh_dentry->d_inode->i_mode))
24715+ goto out_wh; /* success */
24716+
24717+ err = -EIO;
24718+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
24719+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
24720+
4f0767ce 24721+out_wh:
1facf9fc 24722+ dput(wh_dentry);
4f0767ce 24723+out:
1facf9fc 24724+ return err;
24725+}
24726+
24727+/*
24728+ * test if the @h_dentry sets opaque or not.
24729+ */
24730+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
24731+{
24732+ int err;
24733+ struct inode *h_dir;
24734+
24735+ h_dir = h_dentry->d_inode;
24736+ err = au_wh_test(h_dentry, &diropq_name, br,
24737+ au_test_h_perm_sio(h_dir, MAY_EXEC));
24738+ return err;
24739+}
24740+
24741+/*
24742+ * returns a negative dentry whose name is unique and temporary.
24743+ */
24744+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
24745+ struct qstr *prefix)
24746+{
1facf9fc 24747+ struct dentry *dentry;
24748+ int i;
4a4d8108
AM
24749+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN_MIN + 1],
24750+ *name, *p;
1facf9fc 24751+ static unsigned short cnt;
24752+ struct qstr qs;
24753+
4a4d8108
AM
24754+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
24755+
1facf9fc 24756+ name = defname;
24757+ qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
24758+ if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
24759+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 24760+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 24761+ goto out;
24762+ dentry = ERR_PTR(-ENOMEM);
24763+ name = kmalloc(qs.len + 1, GFP_NOFS);
24764+ if (unlikely(!name))
24765+ goto out;
24766+ }
24767+
24768+ /* doubly whiteout-ed */
24769+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
24770+ p = name + AUFS_WH_PFX_LEN * 2;
24771+ memcpy(p, prefix->name, prefix->len);
24772+ p += prefix->len;
24773+ *p++ = '.';
4a4d8108 24774+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 24775+
24776+ qs.name = name;
24777+ for (i = 0; i < 3; i++) {
b752ccd1 24778+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 24779+ dentry = au_sio_lkup_one(&qs, h_parent, br);
24780+ if (IS_ERR(dentry) || !dentry->d_inode)
24781+ goto out_name;
24782+ dput(dentry);
24783+ }
4a4d8108 24784+ /* pr_warning("could not get random name\n"); */
1facf9fc 24785+ dentry = ERR_PTR(-EEXIST);
24786+ AuDbg("%.*s\n", AuLNPair(&qs));
24787+ BUG();
24788+
4f0767ce 24789+out_name:
1facf9fc 24790+ if (name != defname)
24791+ kfree(name);
4f0767ce 24792+out:
4a4d8108 24793+ AuTraceErrPtr(dentry);
1facf9fc 24794+ return dentry;
1facf9fc 24795+}
24796+
24797+/*
24798+ * rename the @h_dentry on @br to the whiteouted temporary name.
24799+ */
24800+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
24801+{
24802+ int err;
24803+ struct path h_path = {
24804+ .mnt = br->br_mnt
24805+ };
24806+ struct inode *h_dir;
24807+ struct dentry *h_parent;
24808+
24809+ h_parent = h_dentry->d_parent; /* dir inode is locked */
24810+ h_dir = h_parent->d_inode;
24811+ IMustLock(h_dir);
24812+
24813+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
24814+ err = PTR_ERR(h_path.dentry);
24815+ if (IS_ERR(h_path.dentry))
24816+ goto out;
24817+
24818+ /* under the same dir, no need to lock_rename() */
24819+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
24820+ AuTraceErr(err);
24821+ dput(h_path.dentry);
24822+
4f0767ce 24823+out:
4a4d8108 24824+ AuTraceErr(err);
1facf9fc 24825+ return err;
24826+}
24827+
24828+/* ---------------------------------------------------------------------- */
24829+/*
24830+ * functions for removing a whiteout
24831+ */
24832+
24833+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
24834+{
24835+ int force;
24836+
24837+ /*
24838+ * forces superio when the dir has a sticky bit.
24839+ * this may be a violation of unix fs semantics.
24840+ */
24841+ force = (h_dir->i_mode & S_ISVTX)
24842+ && h_path->dentry->d_inode->i_uid != current_fsuid();
24843+ return vfsub_unlink(h_dir, h_path, force);
24844+}
24845+
24846+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
24847+ struct dentry *dentry)
24848+{
24849+ int err;
24850+
24851+ err = do_unlink_wh(h_dir, h_path);
24852+ if (!err && dentry)
24853+ au_set_dbwh(dentry, -1);
24854+
24855+ return err;
24856+}
24857+
24858+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
24859+ struct au_branch *br)
24860+{
24861+ int err;
24862+ struct path h_path = {
24863+ .mnt = br->br_mnt
24864+ };
24865+
24866+ err = 0;
24867+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
24868+ if (IS_ERR(h_path.dentry))
24869+ err = PTR_ERR(h_path.dentry);
24870+ else {
24871+ if (h_path.dentry->d_inode
24872+ && S_ISREG(h_path.dentry->d_inode->i_mode))
24873+ err = do_unlink_wh(h_parent->d_inode, &h_path);
24874+ dput(h_path.dentry);
24875+ }
24876+
24877+ return err;
24878+}
24879+
24880+/* ---------------------------------------------------------------------- */
24881+/*
24882+ * initialize/clean whiteout for a branch
24883+ */
24884+
24885+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
24886+ const int isdir)
24887+{
24888+ int err;
24889+
24890+ if (!whpath->dentry->d_inode)
24891+ return;
24892+
24893+ err = mnt_want_write(whpath->mnt);
24894+ if (!err) {
24895+ if (isdir)
24896+ err = vfsub_rmdir(h_dir, whpath);
24897+ else
24898+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
24899+ mnt_drop_write(whpath->mnt);
24900+ }
24901+ if (unlikely(err))
4a4d8108
AM
24902+ pr_warning("failed removing %.*s (%d), ignored.\n",
24903+ AuDLNPair(whpath->dentry), err);
1facf9fc 24904+}
24905+
24906+static int test_linkable(struct dentry *h_root)
24907+{
24908+ struct inode *h_dir = h_root->d_inode;
24909+
24910+ if (h_dir->i_op->link)
24911+ return 0;
24912+
4a4d8108
AM
24913+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
24914+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 24915+ return -ENOSYS;
24916+}
24917+
24918+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
24919+static int au_whdir(struct inode *h_dir, struct path *path)
24920+{
24921+ int err;
24922+
24923+ err = -EEXIST;
24924+ if (!path->dentry->d_inode) {
24925+ int mode = S_IRWXU;
24926+
24927+ if (au_test_nfs(path->dentry->d_sb))
24928+ mode |= S_IXUGO;
24929+ err = mnt_want_write(path->mnt);
24930+ if (!err) {
24931+ err = vfsub_mkdir(h_dir, path, mode);
24932+ mnt_drop_write(path->mnt);
24933+ }
24934+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
24935+ err = 0;
24936+ else
4a4d8108 24937+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 24938+
24939+ return err;
24940+}
24941+
24942+struct au_wh_base {
24943+ const struct qstr *name;
24944+ struct dentry *dentry;
24945+};
24946+
24947+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
24948+ struct path *h_path)
24949+{
24950+ h_path->dentry = base[AuBrWh_BASE].dentry;
24951+ au_wh_clean(h_dir, h_path, /*isdir*/0);
24952+ h_path->dentry = base[AuBrWh_PLINK].dentry;
24953+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24954+ h_path->dentry = base[AuBrWh_ORPH].dentry;
24955+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24956+}
24957+
24958+/*
24959+ * returns tri-state,
24960+ * minus: error, caller should print the mesage
24961+ * zero: succuess
24962+ * plus: error, caller should NOT print the mesage
24963+ */
24964+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
24965+ int do_plink, struct au_wh_base base[],
24966+ struct path *h_path)
24967+{
24968+ int err;
24969+ struct inode *h_dir;
24970+
24971+ h_dir = h_root->d_inode;
24972+ h_path->dentry = base[AuBrWh_BASE].dentry;
24973+ au_wh_clean(h_dir, h_path, /*isdir*/0);
24974+ h_path->dentry = base[AuBrWh_PLINK].dentry;
24975+ if (do_plink) {
24976+ err = test_linkable(h_root);
24977+ if (unlikely(err)) {
24978+ err = 1;
24979+ goto out;
24980+ }
24981+
24982+ err = au_whdir(h_dir, h_path);
24983+ if (unlikely(err))
24984+ goto out;
24985+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
24986+ } else
24987+ au_wh_clean(h_dir, h_path, /*isdir*/1);
24988+ h_path->dentry = base[AuBrWh_ORPH].dentry;
24989+ err = au_whdir(h_dir, h_path);
24990+ if (unlikely(err))
24991+ goto out;
24992+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
24993+
4f0767ce 24994+out:
1facf9fc 24995+ return err;
24996+}
24997+
24998+/*
24999+ * for the moment, aufs supports the branch filesystem which does not support
25000+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
25001+ * copyup failed. finally, such filesystem will not be used as the writable
25002+ * branch.
25003+ *
25004+ * returns tri-state, see above.
25005+ */
25006+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
25007+ int do_plink, struct au_wh_base base[],
25008+ struct path *h_path)
25009+{
25010+ int err;
25011+ struct inode *h_dir;
25012+
1308ab2a 25013+ WbrWhMustWriteLock(wbr);
25014+
1facf9fc 25015+ err = test_linkable(h_root);
25016+ if (unlikely(err)) {
25017+ err = 1;
25018+ goto out;
25019+ }
25020+
25021+ /*
25022+ * todo: should this create be done in /sbin/mount.aufs helper?
25023+ */
25024+ err = -EEXIST;
25025+ h_dir = h_root->d_inode;
25026+ if (!base[AuBrWh_BASE].dentry->d_inode) {
25027+ err = mnt_want_write(h_path->mnt);
25028+ if (!err) {
25029+ h_path->dentry = base[AuBrWh_BASE].dentry;
25030+ err = vfsub_create(h_dir, h_path, WH_MASK);
25031+ mnt_drop_write(h_path->mnt);
25032+ }
25033+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
25034+ err = 0;
25035+ else
4a4d8108
AM
25036+ pr_err("unknown %.*s/%.*s exists\n",
25037+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 25038+ if (unlikely(err))
25039+ goto out;
25040+
25041+ h_path->dentry = base[AuBrWh_PLINK].dentry;
25042+ if (do_plink) {
25043+ err = au_whdir(h_dir, h_path);
25044+ if (unlikely(err))
25045+ goto out;
25046+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
25047+ } else
25048+ au_wh_clean(h_dir, h_path, /*isdir*/1);
25049+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
25050+
25051+ h_path->dentry = base[AuBrWh_ORPH].dentry;
25052+ err = au_whdir(h_dir, h_path);
25053+ if (unlikely(err))
25054+ goto out;
25055+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
25056+
4f0767ce 25057+out:
1facf9fc 25058+ return err;
25059+}
25060+
25061+/*
25062+ * initialize the whiteout base file/dir for @br.
25063+ */
25064+int au_wh_init(struct dentry *h_root, struct au_branch *br,
25065+ struct super_block *sb)
25066+{
25067+ int err, i;
25068+ const unsigned char do_plink
25069+ = !!au_opt_test(au_mntflags(sb), PLINK);
25070+ struct path path = {
25071+ .mnt = br->br_mnt
25072+ };
25073+ struct inode *h_dir;
25074+ struct au_wbr *wbr = br->br_wbr;
25075+ static const struct qstr base_name[] = {
25076+ [AuBrWh_BASE] = {
25077+ .name = AUFS_BASE_NAME,
25078+ .len = sizeof(AUFS_BASE_NAME) - 1
25079+ },
25080+ [AuBrWh_PLINK] = {
25081+ .name = AUFS_PLINKDIR_NAME,
25082+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
25083+ },
25084+ [AuBrWh_ORPH] = {
25085+ .name = AUFS_ORPHDIR_NAME,
25086+ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
25087+ }
25088+ };
25089+ struct au_wh_base base[] = {
25090+ [AuBrWh_BASE] = {
25091+ .name = base_name + AuBrWh_BASE,
25092+ .dentry = NULL
25093+ },
25094+ [AuBrWh_PLINK] = {
25095+ .name = base_name + AuBrWh_PLINK,
25096+ .dentry = NULL
25097+ },
25098+ [AuBrWh_ORPH] = {
25099+ .name = base_name + AuBrWh_ORPH,
25100+ .dentry = NULL
25101+ }
25102+ };
25103+
1308ab2a 25104+ if (wbr)
25105+ WbrWhMustWriteLock(wbr);
1facf9fc 25106+
1facf9fc 25107+ for (i = 0; i < AuBrWh_Last; i++) {
25108+ /* doubly whiteouted */
25109+ struct dentry *d;
25110+
25111+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
25112+ err = PTR_ERR(d);
25113+ if (IS_ERR(d))
25114+ goto out;
25115+
25116+ base[i].dentry = d;
25117+ AuDebugOn(wbr
25118+ && wbr->wbr_wh[i]
25119+ && wbr->wbr_wh[i] != base[i].dentry);
25120+ }
25121+
25122+ if (wbr)
25123+ for (i = 0; i < AuBrWh_Last; i++) {
25124+ dput(wbr->wbr_wh[i]);
25125+ wbr->wbr_wh[i] = NULL;
25126+ }
25127+
25128+ err = 0;
1facf9fc 25129+ switch (br->br_perm) {
25130+ case AuBrPerm_RO:
25131+ case AuBrPerm_ROWH:
25132+ case AuBrPerm_RR:
25133+ case AuBrPerm_RRWH:
4a4d8108 25134+ h_dir = h_root->d_inode;
1facf9fc 25135+ au_wh_init_ro(h_dir, base, &path);
25136+ break;
25137+
25138+ case AuBrPerm_RWNoLinkWH:
25139+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
25140+ if (err > 0)
25141+ goto out;
25142+ else if (err)
25143+ goto out_err;
25144+ break;
25145+
25146+ case AuBrPerm_RW:
25147+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
25148+ if (err > 0)
25149+ goto out;
25150+ else if (err)
25151+ goto out_err;
25152+ break;
25153+
25154+ default:
25155+ BUG();
25156+ }
25157+ goto out; /* success */
25158+
4f0767ce 25159+out_err:
4a4d8108
AM
25160+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
25161+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 25162+out:
1facf9fc 25163+ for (i = 0; i < AuBrWh_Last; i++)
25164+ dput(base[i].dentry);
25165+ return err;
25166+}
25167+
25168+/* ---------------------------------------------------------------------- */
25169+/*
25170+ * whiteouts are all hard-linked usually.
25171+ * when its link count reaches a ceiling, we create a new whiteout base
25172+ * asynchronously.
25173+ */
25174+
25175+struct reinit_br_wh {
25176+ struct super_block *sb;
25177+ struct au_branch *br;
25178+};
25179+
25180+static void reinit_br_wh(void *arg)
25181+{
25182+ int err;
25183+ aufs_bindex_t bindex;
25184+ struct path h_path;
25185+ struct reinit_br_wh *a = arg;
25186+ struct au_wbr *wbr;
25187+ struct inode *dir;
25188+ struct dentry *h_root;
25189+ struct au_hinode *hdir;
25190+
25191+ err = 0;
25192+ wbr = a->br->br_wbr;
25193+ /* big aufs lock */
25194+ si_noflush_write_lock(a->sb);
25195+ if (!au_br_writable(a->br->br_perm))
25196+ goto out;
25197+ bindex = au_br_index(a->sb, a->br->br_id);
25198+ if (unlikely(bindex < 0))
25199+ goto out;
25200+
1308ab2a 25201+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 25202+ dir = a->sb->s_root->d_inode;
1facf9fc 25203+ hdir = au_hi(dir, bindex);
25204+ h_root = au_h_dptr(a->sb->s_root, bindex);
25205+
4a4d8108 25206+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 25207+ wbr_wh_write_lock(wbr);
25208+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
25209+ h_root, a->br);
25210+ if (!err) {
25211+ err = mnt_want_write(a->br->br_mnt);
25212+ if (!err) {
25213+ h_path.dentry = wbr->wbr_whbase;
25214+ h_path.mnt = a->br->br_mnt;
25215+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
25216+ mnt_drop_write(a->br->br_mnt);
25217+ }
25218+ } else {
4a4d8108
AM
25219+ pr_warning("%.*s is moved, ignored\n",
25220+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 25221+ err = 0;
25222+ }
25223+ dput(wbr->wbr_whbase);
25224+ wbr->wbr_whbase = NULL;
25225+ if (!err)
25226+ err = au_wh_init(h_root, a->br, a->sb);
25227+ wbr_wh_write_unlock(wbr);
4a4d8108 25228+ au_hn_imtx_unlock(hdir);
1308ab2a 25229+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 25230+
4f0767ce 25231+out:
1facf9fc 25232+ if (wbr)
25233+ atomic_dec(&wbr->wbr_wh_running);
25234+ atomic_dec(&a->br->br_count);
25235+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
25236+ si_write_unlock(a->sb);
25237+ kfree(arg);
25238+ if (unlikely(err))
25239+ AuIOErr("err %d\n", err);
25240+}
25241+
25242+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
25243+{
25244+ int do_dec, wkq_err;
25245+ struct reinit_br_wh *arg;
25246+
25247+ do_dec = 1;
25248+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
25249+ goto out;
25250+
25251+ /* ignore ENOMEM */
25252+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
25253+ if (arg) {
25254+ /*
25255+ * dec(wh_running), kfree(arg) and dec(br_count)
25256+ * in reinit function
25257+ */
25258+ arg->sb = sb;
25259+ arg->br = br;
25260+ atomic_inc(&br->br_count);
25261+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
25262+ if (unlikely(wkq_err)) {
25263+ atomic_dec(&br->br_wbr->wbr_wh_running);
25264+ atomic_dec(&br->br_count);
25265+ kfree(arg);
25266+ }
25267+ do_dec = 0;
25268+ }
25269+
4f0767ce 25270+out:
1facf9fc 25271+ if (do_dec)
25272+ atomic_dec(&br->br_wbr->wbr_wh_running);
25273+}
25274+
25275+/* ---------------------------------------------------------------------- */
25276+
25277+/*
25278+ * create the whiteout @wh.
25279+ */
25280+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
25281+ struct dentry *wh)
25282+{
25283+ int err;
25284+ struct path h_path = {
25285+ .dentry = wh
25286+ };
25287+ struct au_branch *br;
25288+ struct au_wbr *wbr;
25289+ struct dentry *h_parent;
25290+ struct inode *h_dir;
25291+
25292+ h_parent = wh->d_parent; /* dir inode is locked */
25293+ h_dir = h_parent->d_inode;
25294+ IMustLock(h_dir);
25295+
25296+ br = au_sbr(sb, bindex);
25297+ h_path.mnt = br->br_mnt;
25298+ wbr = br->br_wbr;
25299+ wbr_wh_read_lock(wbr);
25300+ if (wbr->wbr_whbase) {
25301+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
25302+ if (!err || err != -EMLINK)
25303+ goto out;
25304+
25305+ /* link count full. re-initialize br_whbase. */
25306+ kick_reinit_br_wh(sb, br);
25307+ }
25308+
25309+ /* return this error in this context */
25310+ err = vfsub_create(h_dir, &h_path, WH_MASK);
25311+
4f0767ce 25312+out:
1facf9fc 25313+ wbr_wh_read_unlock(wbr);
25314+ return err;
25315+}
25316+
25317+/* ---------------------------------------------------------------------- */
25318+
25319+/*
25320+ * create or remove the diropq.
25321+ */
25322+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
25323+ unsigned int flags)
25324+{
25325+ struct dentry *opq_dentry, *h_dentry;
25326+ struct super_block *sb;
25327+ struct au_branch *br;
25328+ int err;
25329+
25330+ sb = dentry->d_sb;
25331+ br = au_sbr(sb, bindex);
25332+ h_dentry = au_h_dptr(dentry, bindex);
25333+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
25334+ if (IS_ERR(opq_dentry))
25335+ goto out;
25336+
25337+ if (au_ftest_diropq(flags, CREATE)) {
25338+ err = link_or_create_wh(sb, bindex, opq_dentry);
25339+ if (!err) {
25340+ au_set_dbdiropq(dentry, bindex);
25341+ goto out; /* success */
25342+ }
25343+ } else {
25344+ struct path tmp = {
25345+ .dentry = opq_dentry,
25346+ .mnt = br->br_mnt
25347+ };
25348+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
25349+ if (!err)
25350+ au_set_dbdiropq(dentry, -1);
25351+ }
25352+ dput(opq_dentry);
25353+ opq_dentry = ERR_PTR(err);
25354+
4f0767ce 25355+out:
1facf9fc 25356+ return opq_dentry;
25357+}
25358+
25359+struct do_diropq_args {
25360+ struct dentry **errp;
25361+ struct dentry *dentry;
25362+ aufs_bindex_t bindex;
25363+ unsigned int flags;
25364+};
25365+
25366+static void call_do_diropq(void *args)
25367+{
25368+ struct do_diropq_args *a = args;
25369+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
25370+}
25371+
25372+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
25373+ unsigned int flags)
25374+{
25375+ struct dentry *diropq, *h_dentry;
25376+
25377+ h_dentry = au_h_dptr(dentry, bindex);
25378+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
25379+ diropq = do_diropq(dentry, bindex, flags);
25380+ else {
25381+ int wkq_err;
25382+ struct do_diropq_args args = {
25383+ .errp = &diropq,
25384+ .dentry = dentry,
25385+ .bindex = bindex,
25386+ .flags = flags
25387+ };
25388+
25389+ wkq_err = au_wkq_wait(call_do_diropq, &args);
25390+ if (unlikely(wkq_err))
25391+ diropq = ERR_PTR(wkq_err);
25392+ }
25393+
25394+ return diropq;
25395+}
25396+
25397+/* ---------------------------------------------------------------------- */
25398+
25399+/*
25400+ * lookup whiteout dentry.
25401+ * @h_parent: lower parent dentry which must exist and be locked
25402+ * @base_name: name of dentry which will be whiteouted
25403+ * returns dentry for whiteout.
25404+ */
25405+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
25406+ struct au_branch *br)
25407+{
25408+ int err;
25409+ struct qstr wh_name;
25410+ struct dentry *wh_dentry;
25411+
25412+ err = au_wh_name_alloc(&wh_name, base_name);
25413+ wh_dentry = ERR_PTR(err);
25414+ if (!err) {
25415+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
25416+ kfree(wh_name.name);
25417+ }
25418+ return wh_dentry;
25419+}
25420+
25421+/*
25422+ * link/create a whiteout for @dentry on @bindex.
25423+ */
25424+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
25425+ struct dentry *h_parent)
25426+{
25427+ struct dentry *wh_dentry;
25428+ struct super_block *sb;
25429+ int err;
25430+
25431+ sb = dentry->d_sb;
25432+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
25433+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
25434+ err = link_or_create_wh(sb, bindex, wh_dentry);
25435+ if (!err)
25436+ au_set_dbwh(dentry, bindex);
25437+ else {
25438+ dput(wh_dentry);
25439+ wh_dentry = ERR_PTR(err);
25440+ }
25441+ }
25442+
25443+ return wh_dentry;
25444+}
25445+
25446+/* ---------------------------------------------------------------------- */
25447+
25448+/* Delete all whiteouts in this directory on branch bindex. */
25449+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
25450+ aufs_bindex_t bindex, struct au_branch *br)
25451+{
25452+ int err;
25453+ unsigned long ul, n;
25454+ struct qstr wh_name;
25455+ char *p;
25456+ struct hlist_head *head;
25457+ struct au_vdir_wh *tpos;
25458+ struct hlist_node *pos;
25459+ struct au_vdir_destr *str;
25460+
25461+ err = -ENOMEM;
4a4d8108 25462+ p = __getname_gfp(GFP_NOFS);
1facf9fc 25463+ wh_name.name = p;
25464+ if (unlikely(!wh_name.name))
25465+ goto out;
25466+
25467+ err = 0;
25468+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25469+ p += AUFS_WH_PFX_LEN;
25470+ n = whlist->nh_num;
25471+ head = whlist->nh_head;
25472+ for (ul = 0; !err && ul < n; ul++, head++) {
25473+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
25474+ if (tpos->wh_bindex != bindex)
25475+ continue;
25476+
25477+ str = &tpos->wh_str;
25478+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
25479+ memcpy(p, str->name, str->len);
25480+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
25481+ err = unlink_wh_name(h_dentry, &wh_name, br);
25482+ if (!err)
25483+ continue;
25484+ break;
25485+ }
25486+ AuIOErr("whiteout name too long %.*s\n",
25487+ str->len, str->name);
25488+ err = -EIO;
25489+ break;
25490+ }
25491+ }
25492+ __putname(wh_name.name);
25493+
4f0767ce 25494+out:
1facf9fc 25495+ return err;
25496+}
25497+
25498+struct del_wh_children_args {
25499+ int *errp;
25500+ struct dentry *h_dentry;
1308ab2a 25501+ struct au_nhash *whlist;
1facf9fc 25502+ aufs_bindex_t bindex;
25503+ struct au_branch *br;
25504+};
25505+
25506+static void call_del_wh_children(void *args)
25507+{
25508+ struct del_wh_children_args *a = args;
1308ab2a 25509+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 25510+}
25511+
25512+/* ---------------------------------------------------------------------- */
25513+
25514+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
25515+{
25516+ struct au_whtmp_rmdir *whtmp;
dece6358 25517+ int err;
1308ab2a 25518+ unsigned int rdhash;
dece6358
AM
25519+
25520+ SiMustAnyLock(sb);
1facf9fc 25521+
25522+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
25523+ if (unlikely(!whtmp)) {
25524+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 25525+ goto out;
dece6358 25526+ }
1facf9fc 25527+
25528+ whtmp->dir = NULL;
25529+ whtmp->wh_dentry = NULL;
1308ab2a 25530+ /* no estimation for dir size */
25531+ rdhash = au_sbi(sb)->si_rdhash;
25532+ if (!rdhash)
25533+ rdhash = AUFS_RDHASH_DEF;
25534+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
25535+ if (unlikely(err)) {
25536+ kfree(whtmp);
25537+ whtmp = ERR_PTR(err);
25538+ }
dece6358 25539+
4f0767ce 25540+out:
dece6358 25541+ return whtmp;
1facf9fc 25542+}
25543+
25544+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
25545+{
25546+ dput(whtmp->wh_dentry);
25547+ iput(whtmp->dir);
dece6358 25548+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 25549+ kfree(whtmp);
25550+}
25551+
25552+/*
25553+ * rmdir the whiteouted temporary named dir @h_dentry.
25554+ * @whlist: whiteouted children.
25555+ */
25556+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
25557+ struct dentry *wh_dentry, struct au_nhash *whlist)
25558+{
25559+ int err;
25560+ struct path h_tmp;
25561+ struct inode *wh_inode, *h_dir;
25562+ struct au_branch *br;
25563+
25564+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
25565+ IMustLock(h_dir);
25566+
25567+ br = au_sbr(dir->i_sb, bindex);
25568+ wh_inode = wh_dentry->d_inode;
25569+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
25570+
25571+ /*
25572+ * someone else might change some whiteouts while we were sleeping.
25573+ * it means this whlist may have an obsoleted entry.
25574+ */
25575+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
25576+ err = del_wh_children(wh_dentry, whlist, bindex, br);
25577+ else {
25578+ int wkq_err;
25579+ struct del_wh_children_args args = {
25580+ .errp = &err,
25581+ .h_dentry = wh_dentry,
1308ab2a 25582+ .whlist = whlist,
1facf9fc 25583+ .bindex = bindex,
25584+ .br = br
25585+ };
25586+
25587+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
25588+ if (unlikely(wkq_err))
25589+ err = wkq_err;
25590+ }
25591+ mutex_unlock(&wh_inode->i_mutex);
25592+
25593+ if (!err) {
25594+ h_tmp.dentry = wh_dentry;
25595+ h_tmp.mnt = br->br_mnt;
25596+ err = vfsub_rmdir(h_dir, &h_tmp);
25597+ /* d_drop(h_dentry); */
25598+ }
25599+
25600+ if (!err) {
25601+ if (au_ibstart(dir) == bindex) {
25602+ au_cpup_attr_timesizes(dir);
25603+ drop_nlink(dir);
25604+ }
25605+ return 0; /* success */
25606+ }
25607+
4a4d8108
AM
25608+ pr_warning("failed removing %.*s(%d), ignored\n",
25609+ AuDLNPair(wh_dentry), err);
1facf9fc 25610+ return err;
25611+}
25612+
25613+static void call_rmdir_whtmp(void *args)
25614+{
25615+ int err;
e49829fe 25616+ aufs_bindex_t bindex;
1facf9fc 25617+ struct au_whtmp_rmdir *a = args;
25618+ struct super_block *sb;
25619+ struct dentry *h_parent;
25620+ struct inode *h_dir;
1facf9fc 25621+ struct au_hinode *hdir;
25622+
25623+ /* rmdir by nfsd may cause deadlock with this i_mutex */
25624+ /* mutex_lock(&a->dir->i_mutex); */
e49829fe 25625+ err = -EROFS;
1facf9fc 25626+ sb = a->dir->i_sb;
e49829fe
JR
25627+ si_read_lock(sb, !AuLock_FLUSH);
25628+ if (!au_br_writable(a->br->br_perm))
25629+ goto out;
25630+ bindex = au_br_index(sb, a->br->br_id);
25631+ if (unlikely(bindex < 0))
1facf9fc 25632+ goto out;
25633+
25634+ err = -EIO;
1facf9fc 25635+ ii_write_lock_parent(a->dir);
25636+ h_parent = dget_parent(a->wh_dentry);
25637+ h_dir = h_parent->d_inode;
e49829fe 25638+ hdir = au_hi(a->dir, bindex);
4a4d8108 25639+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
25640+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
25641+ a->br);
1facf9fc 25642+ if (!err) {
e49829fe 25643+ err = mnt_want_write(a->br->br_mnt);
1facf9fc 25644+ if (!err) {
e49829fe 25645+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
dece6358 25646+ &a->whlist);
e49829fe 25647+ mnt_drop_write(a->br->br_mnt);
1facf9fc 25648+ }
25649+ }
4a4d8108 25650+ au_hn_imtx_unlock(hdir);
1facf9fc 25651+ dput(h_parent);
25652+ ii_write_unlock(a->dir);
25653+
4f0767ce 25654+out:
1facf9fc 25655+ /* mutex_unlock(&a->dir->i_mutex); */
e49829fe 25656+ atomic_dec(&a->br->br_count);
1facf9fc 25657+ au_nwt_done(&au_sbi(sb)->si_nowait);
25658+ si_read_unlock(sb);
25659+ au_whtmp_rmdir_free(a);
25660+ if (unlikely(err))
25661+ AuIOErr("err %d\n", err);
25662+}
25663+
25664+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
25665+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
25666+{
25667+ int wkq_err;
e49829fe 25668+ struct super_block *sb;
1facf9fc 25669+
25670+ IMustLock(dir);
25671+
25672+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 25673+ sb = dir->i_sb;
1facf9fc 25674+ args->dir = au_igrab(dir);
e49829fe
JR
25675+ args->br = au_sbr(sb, bindex);
25676+ atomic_inc(&args->br->br_count);
1facf9fc 25677+ args->wh_dentry = dget(wh_dentry);
e49829fe 25678+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb);
1facf9fc 25679+ if (unlikely(wkq_err)) {
4a4d8108
AM
25680+ pr_warning("rmdir error %.*s (%d), ignored\n",
25681+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 25682+ au_whtmp_rmdir_free(args);
25683+ }
25684+}
e49829fe 25685--- /dev/null
0c5527e5 25686+++ linux-2.6/fs/aufs/whout.h 2010-10-25 14:20:44.000000000 +0200
dece6358 25687@@ -0,0 +1,87 @@
1facf9fc 25688+/*
4a4d8108 25689+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25690+ *
25691+ * This program, aufs is free software; you can redistribute it and/or modify
25692+ * it under the terms of the GNU General Public License as published by
25693+ * the Free Software Foundation; either version 2 of the License, or
25694+ * (at your option) any later version.
dece6358
AM
25695+ *
25696+ * This program is distributed in the hope that it will be useful,
25697+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25698+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25699+ * GNU General Public License for more details.
25700+ *
25701+ * You should have received a copy of the GNU General Public License
25702+ * along with this program; if not, write to the Free Software
25703+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25704+ */
25705+
25706+/*
25707+ * whiteout for logical deletion and opaque directory
25708+ */
25709+
25710+#ifndef __AUFS_WHOUT_H__
25711+#define __AUFS_WHOUT_H__
25712+
25713+#ifdef __KERNEL__
25714+
1facf9fc 25715+#include <linux/aufs_type.h>
25716+#include "dir.h"
25717+
25718+/* whout.c */
25719+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
25720+struct au_branch;
25721+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
25722+ struct au_branch *br, int try_sio);
25723+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
25724+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
25725+ struct qstr *prefix);
25726+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
25727+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
25728+ struct dentry *dentry);
25729+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
25730+ struct super_block *sb);
25731+
25732+/* diropq flags */
25733+#define AuDiropq_CREATE 1
25734+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
25735+#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
25736+#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
25737+
25738+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
25739+ unsigned int flags);
25740+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
25741+ struct au_branch *br);
25742+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
25743+ struct dentry *h_parent);
25744+
25745+/* real rmdir for the whiteout-ed dir */
25746+struct au_whtmp_rmdir {
25747+ struct inode *dir;
e49829fe 25748+ struct au_branch *br;
1facf9fc 25749+ struct dentry *wh_dentry;
dece6358 25750+ struct au_nhash whlist;
1facf9fc 25751+};
25752+
25753+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
25754+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
25755+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
25756+ struct dentry *wh_dentry, struct au_nhash *whlist);
25757+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
25758+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
25759+
25760+/* ---------------------------------------------------------------------- */
25761+
25762+static inline struct dentry *au_diropq_create(struct dentry *dentry,
25763+ aufs_bindex_t bindex)
25764+{
25765+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
25766+}
25767+
25768+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
25769+{
25770+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
25771+}
25772+
25773+#endif /* __KERNEL__ */
25774+#endif /* __AUFS_WHOUT_H__ */
e49829fe 25775--- /dev/null
0c5527e5 25776+++ linux-2.6/fs/aufs/wkq.c 2010-10-25 14:20:44.000000000 +0200
e49829fe 25777@@ -0,0 +1,223 @@
1facf9fc 25778+/*
4a4d8108 25779+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 25780+ *
25781+ * This program, aufs is free software; you can redistribute it and/or modify
25782+ * it under the terms of the GNU General Public License as published by
25783+ * the Free Software Foundation; either version 2 of the License, or
25784+ * (at your option) any later version.
dece6358
AM
25785+ *
25786+ * This program is distributed in the hope that it will be useful,
25787+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25788+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25789+ * GNU General Public License for more details.
25790+ *
25791+ * You should have received a copy of the GNU General Public License
25792+ * along with this program; if not, write to the Free Software
25793+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25794+ */
25795+
25796+/*
25797+ * workqueue for asynchronous/super-io operations
25798+ * todo: try new dredential scheme
25799+ */
25800+
dece6358 25801+#include <linux/module.h>
1facf9fc 25802+#include "aufs.h"
25803+
b752ccd1
AM
25804+/* internal workqueue named AUFS_WKQ_NAME and AUFS_WKQ_PRE_NAME */
25805+enum {
25806+ AuWkq_INORMAL,
25807+ AuWkq_IPRE
25808+};
25809+
25810+static struct {
25811+ char *name;
25812+ struct workqueue_struct *wkq;
25813+} au_wkq[] = {
25814+ [AuWkq_INORMAL] = {
25815+ .name = AUFS_WKQ_NAME
25816+ },
25817+ [AuWkq_IPRE] = {
25818+ .name = AUFS_WKQ_PRE_NAME
25819+ }
25820+};
1facf9fc 25821+
25822+struct au_wkinfo {
25823+ struct work_struct wk;
25824+ struct super_block *sb;
25825+
25826+ unsigned int flags; /* see wkq.h */
25827+
25828+ au_wkq_func_t func;
25829+ void *args;
25830+
1facf9fc 25831+ struct completion *comp;
25832+};
25833+
25834+/* ---------------------------------------------------------------------- */
25835+
1facf9fc 25836+static void wkq_func(struct work_struct *wk)
25837+{
25838+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
25839+
25840+ wkinfo->func(wkinfo->args);
1facf9fc 25841+ if (au_ftest_wkq(wkinfo->flags, WAIT))
25842+ complete(wkinfo->comp);
25843+ else {
25844+ kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
25845+ module_put(THIS_MODULE);
25846+ kfree(wkinfo);
25847+ }
25848+}
25849+
25850+/*
25851+ * Since struct completion is large, try allocating it dynamically.
25852+ */
25853+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
25854+#define AuWkqCompDeclare(name) struct completion *comp = NULL
25855+
25856+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
25857+{
25858+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
25859+ if (*comp) {
25860+ init_completion(*comp);
25861+ wkinfo->comp = *comp;
25862+ return 0;
25863+ }
25864+ return -ENOMEM;
25865+}
25866+
25867+static void au_wkq_comp_free(struct completion *comp)
25868+{
25869+ kfree(comp);
25870+}
25871+
25872+#else
25873+
25874+/* no braces */
25875+#define AuWkqCompDeclare(name) \
25876+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
25877+ struct completion *comp = &_ ## name
25878+
25879+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
25880+{
25881+ wkinfo->comp = *comp;
25882+ return 0;
25883+}
25884+
25885+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
25886+{
25887+ /* empty */
25888+}
25889+#endif /* 4KSTACKS */
25890+
b752ccd1 25891+static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags)
1facf9fc 25892+{
b752ccd1
AM
25893+ struct workqueue_struct *wkq;
25894+
1facf9fc 25895+ au_dbg_verify_kthread();
b752ccd1 25896+ if (flags & AuWkq_WAIT) {
4a4d8108 25897+ INIT_WORK_ON_STACK(&wkinfo->wk, wkq_func);
b752ccd1
AM
25898+ wkq = au_wkq[AuWkq_INORMAL].wkq;
25899+ if (flags & AuWkq_PRE)
25900+ wkq = au_wkq[AuWkq_IPRE].wkq;
25901+ queue_work(wkq, &wkinfo->wk);
4a4d8108
AM
25902+ } else {
25903+ INIT_WORK(&wkinfo->wk, wkq_func);
25904+ schedule_work(&wkinfo->wk);
25905+ }
1facf9fc 25906+}
25907+
b752ccd1 25908+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 25909+{
25910+ int err;
25911+ AuWkqCompDeclare(comp);
25912+ struct au_wkinfo wkinfo = {
b752ccd1 25913+ .flags = flags,
1facf9fc 25914+ .func = func,
25915+ .args = args
25916+ };
25917+
25918+ err = au_wkq_comp_alloc(&wkinfo, &comp);
25919+ if (!err) {
b752ccd1 25920+ au_wkq_run(&wkinfo, flags);
1facf9fc 25921+ /* no timeout, no interrupt */
25922+ wait_for_completion(wkinfo.comp);
25923+ au_wkq_comp_free(comp);
4a4d8108 25924+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 25925+ }
25926+
25927+ return err;
25928+
25929+}
25930+
25931+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
25932+{
25933+ int err;
25934+ struct au_wkinfo *wkinfo;
25935+
25936+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
25937+
25938+ /*
25939+ * wkq_func() must free this wkinfo.
25940+ * it highly depends upon the implementation of workqueue.
25941+ */
25942+ err = 0;
25943+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
25944+ if (wkinfo) {
25945+ wkinfo->sb = sb;
25946+ wkinfo->flags = !AuWkq_WAIT;
25947+ wkinfo->func = func;
25948+ wkinfo->args = args;
25949+ wkinfo->comp = NULL;
25950+ kobject_get(&au_sbi(sb)->si_kobj);
25951+ __module_get(THIS_MODULE);
25952+
4a4d8108 25953+ au_wkq_run(wkinfo, !AuWkq_WAIT);
1facf9fc 25954+ } else {
25955+ err = -ENOMEM;
e49829fe 25956+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 25957+ }
25958+
25959+ return err;
25960+}
25961+
25962+/* ---------------------------------------------------------------------- */
25963+
25964+void au_nwt_init(struct au_nowait_tasks *nwt)
25965+{
25966+ atomic_set(&nwt->nw_len, 0);
4a4d8108 25967+ /* smp_mb(); */ /* atomic_set */
1facf9fc 25968+ init_waitqueue_head(&nwt->nw_wq);
25969+}
25970+
25971+void au_wkq_fin(void)
25972+{
b752ccd1
AM
25973+ int i;
25974+
25975+ for (i = 0; i < ARRAY_SIZE(au_wkq); i++)
25976+ if (au_wkq[i].wkq)
25977+ destroy_workqueue(au_wkq[i].wkq);
1facf9fc 25978+}
25979+
25980+int __init au_wkq_init(void)
25981+{
b752ccd1
AM
25982+ int err, i;
25983+
25984+ err = 0;
25985+ for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
e49829fe 25986+ au_wkq[i].wkq = create_workqueue(au_wkq[i].name);
b752ccd1
AM
25987+ if (IS_ERR(au_wkq[i].wkq))
25988+ err = PTR_ERR(au_wkq[i].wkq);
25989+ else if (!au_wkq[i].wkq)
25990+ err = -ENOMEM;
25991+ if (unlikely(err))
25992+ au_wkq[i].wkq = NULL;
25993+ }
e49829fe
JR
25994+ if (!err)
25995+ au_dbg_verify_wkq();
25996+ else
b752ccd1
AM
25997+ au_wkq_fin();
25998+
25999+ return err;
1facf9fc 26000+}
e49829fe 26001--- /dev/null
0c5527e5 26002+++ linux-2.6/fs/aufs/wkq.h 2010-10-25 14:20:44.000000000 +0200
b752ccd1 26003@@ -0,0 +1,88 @@
1facf9fc 26004+/*
4a4d8108 26005+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26006+ *
26007+ * This program, aufs is free software; you can redistribute it and/or modify
26008+ * it under the terms of the GNU General Public License as published by
26009+ * the Free Software Foundation; either version 2 of the License, or
26010+ * (at your option) any later version.
dece6358
AM
26011+ *
26012+ * This program is distributed in the hope that it will be useful,
26013+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26014+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26015+ * GNU General Public License for more details.
26016+ *
26017+ * You should have received a copy of the GNU General Public License
26018+ * along with this program; if not, write to the Free Software
26019+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26020+ */
26021+
26022+/*
26023+ * workqueue for asynchronous/super-io operations
26024+ * todo: try new credentials management scheme
26025+ */
26026+
26027+#ifndef __AUFS_WKQ_H__
26028+#define __AUFS_WKQ_H__
26029+
26030+#ifdef __KERNEL__
26031+
1facf9fc 26032+#include <linux/sched.h>
dece6358 26033+#include <linux/wait.h>
1facf9fc 26034+#include <linux/aufs_type.h>
26035+
dece6358
AM
26036+struct super_block;
26037+
1facf9fc 26038+/* ---------------------------------------------------------------------- */
26039+
26040+/*
26041+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
26042+ */
26043+struct au_nowait_tasks {
26044+ atomic_t nw_len;
26045+ wait_queue_head_t nw_wq;
26046+};
26047+
26048+/* ---------------------------------------------------------------------- */
26049+
26050+typedef void (*au_wkq_func_t)(void *args);
26051+
26052+/* wkq flags */
26053+#define AuWkq_WAIT 1
b752ccd1 26054+#define AuWkq_PRE (1 << 1)
1facf9fc 26055+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
26056+#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
26057+#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
26058+
26059+/* wkq.c */
b752ccd1 26060+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
1facf9fc 26061+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
26062+void au_nwt_init(struct au_nowait_tasks *nwt);
26063+int __init au_wkq_init(void);
26064+void au_wkq_fin(void);
26065+
26066+/* ---------------------------------------------------------------------- */
26067+
b752ccd1
AM
26068+static inline int au_wkq_wait_pre(au_wkq_func_t func, void *args)
26069+{
26070+ return au_wkq_do_wait(AuWkq_WAIT | AuWkq_PRE, func, args);
26071+}
26072+
26073+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 26074+{
b752ccd1 26075+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 26076+}
26077+
26078+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
26079+{
e49829fe 26080+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 26081+ wake_up_all(&nwt->nw_wq);
26082+}
26083+
26084+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
26085+{
26086+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
26087+ return 0;
26088+}
26089+
26090+#endif /* __KERNEL__ */
26091+#endif /* __AUFS_WKQ_H__ */
e49829fe 26092--- /dev/null
0c5527e5 26093+++ linux-2.6/fs/aufs/xino.c 2010-10-25 14:20:44.000000000 +0200
b752ccd1 26094@@ -0,0 +1,1263 @@
1facf9fc 26095+/*
4a4d8108 26096+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 26097+ *
26098+ * This program, aufs is free software; you can redistribute it and/or modify
26099+ * it under the terms of the GNU General Public License as published by
26100+ * the Free Software Foundation; either version 2 of the License, or
26101+ * (at your option) any later version.
dece6358
AM
26102+ *
26103+ * This program is distributed in the hope that it will be useful,
26104+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26105+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26106+ * GNU General Public License for more details.
26107+ *
26108+ * You should have received a copy of the GNU General Public License
26109+ * along with this program; if not, write to the Free Software
26110+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26111+ */
26112+
26113+/*
26114+ * external inode number translation table and bitmap
26115+ */
26116+
dece6358 26117+#include <linux/file.h>
1facf9fc 26118+#include <linux/seq_file.h>
26119+#include <linux/uaccess.h>
26120+#include "aufs.h"
26121+
b752ccd1 26122+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 26123+ loff_t *pos)
26124+{
26125+ ssize_t err;
26126+ mm_segment_t oldfs;
b752ccd1
AM
26127+ union {
26128+ void *k;
26129+ char __user *u;
26130+ } buf;
1facf9fc 26131+
b752ccd1 26132+ buf.k = kbuf;
1facf9fc 26133+ oldfs = get_fs();
26134+ set_fs(KERNEL_DS);
26135+ do {
26136+ /* todo: signal_pending? */
b752ccd1 26137+ err = func(file, buf.u, size, pos);
1facf9fc 26138+ } while (err == -EAGAIN || err == -EINTR);
26139+ set_fs(oldfs);
26140+
26141+#if 0 /* reserved for future use */
26142+ if (err > 0)
26143+ fsnotify_access(file->f_dentry);
26144+#endif
26145+
26146+ return err;
26147+}
26148+
26149+/* ---------------------------------------------------------------------- */
26150+
b752ccd1 26151+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 26152+ size_t size, loff_t *pos)
26153+{
26154+ ssize_t err;
26155+ mm_segment_t oldfs;
b752ccd1
AM
26156+ union {
26157+ void *k;
26158+ const char __user *u;
26159+ } buf;
1facf9fc 26160+
b752ccd1 26161+ buf.k = kbuf;
1facf9fc 26162+ oldfs = get_fs();
26163+ set_fs(KERNEL_DS);
1facf9fc 26164+ do {
26165+ /* todo: signal_pending? */
b752ccd1 26166+ err = func(file, buf.u, size, pos);
1facf9fc 26167+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 26168+ set_fs(oldfs);
26169+
26170+#if 0 /* reserved for future use */
26171+ if (err > 0)
26172+ fsnotify_modify(file->f_dentry);
26173+#endif
26174+
26175+ return err;
26176+}
26177+
26178+struct do_xino_fwrite_args {
26179+ ssize_t *errp;
26180+ au_writef_t func;
26181+ struct file *file;
26182+ void *buf;
26183+ size_t size;
26184+ loff_t *pos;
26185+};
26186+
26187+static void call_do_xino_fwrite(void *args)
26188+{
26189+ struct do_xino_fwrite_args *a = args;
26190+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
26191+}
26192+
26193+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
26194+ loff_t *pos)
26195+{
26196+ ssize_t err;
26197+
26198+ /* todo: signal block and no wkq? */
b752ccd1
AM
26199+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
26200+ lockdep_off();
26201+ err = do_xino_fwrite(func, file, buf, size, pos);
26202+ lockdep_on();
26203+ } else {
26204+ /*
26205+ * it breaks RLIMIT_FSIZE and normal user's limit,
26206+ * users should care about quota and real 'filesystem full.'
26207+ */
1facf9fc 26208+ int wkq_err;
26209+ struct do_xino_fwrite_args args = {
26210+ .errp = &err,
26211+ .func = func,
26212+ .file = file,
26213+ .buf = buf,
26214+ .size = size,
26215+ .pos = pos
26216+ };
26217+
26218+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
26219+ if (unlikely(wkq_err))
26220+ err = wkq_err;
b752ccd1 26221+ }
1facf9fc 26222+
26223+ return err;
26224+}
26225+
26226+/* ---------------------------------------------------------------------- */
26227+
26228+/*
26229+ * create a new xinofile at the same place/path as @base_file.
26230+ */
26231+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
26232+{
26233+ struct file *file;
4a4d8108 26234+ struct dentry *base, *parent;
1facf9fc 26235+ struct inode *dir;
26236+ struct qstr *name;
1308ab2a 26237+ struct path path;
4a4d8108 26238+ int err;
1facf9fc 26239+
26240+ base = base_file->f_dentry;
26241+ parent = base->d_parent; /* dir inode is locked */
26242+ dir = parent->d_inode;
26243+ IMustLock(dir);
26244+
26245+ file = ERR_PTR(-EINVAL);
26246+ name = &base->d_name;
4a4d8108
AM
26247+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
26248+ if (IS_ERR(path.dentry)) {
26249+ file = (void *)path.dentry;
26250+ pr_err("%.*s lookup err %ld\n",
26251+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 26252+ goto out;
26253+ }
26254+
26255+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 26256+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 26257+ if (unlikely(err)) {
26258+ file = ERR_PTR(err);
4a4d8108 26259+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 26260+ goto out_dput;
26261+ }
26262+
1308ab2a 26263+ path.mnt = base_file->f_vfsmnt;
4a4d8108
AM
26264+ file = vfsub_dentry_open(&path,
26265+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
1facf9fc 26266+ if (IS_ERR(file)) {
4a4d8108 26267+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 26268+ goto out_dput;
26269+ }
26270+
26271+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
26272+ if (unlikely(err)) {
4a4d8108 26273+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 26274+ goto out_fput;
26275+ }
26276+
26277+ if (copy_src) {
26278+ /* no one can touch copy_src xino */
26279+ err = au_copy_file(file, copy_src,
26280+ i_size_read(copy_src->f_dentry->d_inode));
26281+ if (unlikely(err)) {
4a4d8108 26282+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 26283+ goto out_fput;
26284+ }
26285+ }
26286+ goto out_dput; /* success */
26287+
4f0767ce 26288+out_fput:
1facf9fc 26289+ fput(file);
26290+ file = ERR_PTR(err);
4f0767ce 26291+out_dput:
4a4d8108 26292+ dput(path.dentry);
4f0767ce 26293+out:
1facf9fc 26294+ return file;
26295+}
26296+
26297+struct au_xino_lock_dir {
26298+ struct au_hinode *hdir;
26299+ struct dentry *parent;
26300+ struct mutex *mtx;
26301+};
26302+
26303+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
26304+ struct au_xino_lock_dir *ldir)
26305+{
26306+ aufs_bindex_t brid, bindex;
26307+
26308+ ldir->hdir = NULL;
26309+ bindex = -1;
26310+ brid = au_xino_brid(sb);
26311+ if (brid >= 0)
26312+ bindex = au_br_index(sb, brid);
26313+ if (bindex >= 0) {
26314+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 26315+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 26316+ } else {
26317+ ldir->parent = dget_parent(xino->f_dentry);
26318+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
26319+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
26320+ }
26321+}
26322+
26323+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
26324+{
26325+ if (ldir->hdir)
4a4d8108 26326+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 26327+ else {
26328+ mutex_unlock(ldir->mtx);
26329+ dput(ldir->parent);
26330+ }
26331+}
26332+
26333+/* ---------------------------------------------------------------------- */
26334+
26335+/* trucate xino files asynchronously */
26336+
26337+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
26338+{
26339+ int err;
26340+ aufs_bindex_t bi, bend;
26341+ struct au_branch *br;
26342+ struct file *new_xino, *file;
26343+ struct super_block *h_sb;
26344+ struct au_xino_lock_dir ldir;
26345+
26346+ err = -EINVAL;
26347+ bend = au_sbend(sb);
26348+ if (unlikely(bindex < 0 || bend < bindex))
26349+ goto out;
26350+ br = au_sbr(sb, bindex);
26351+ file = br->br_xino.xi_file;
26352+ if (!file)
26353+ goto out;
26354+
26355+ au_xino_lock_dir(sb, file, &ldir);
26356+ /* mnt_want_write() is unnecessary here */
26357+ new_xino = au_xino_create2(file, file);
26358+ au_xino_unlock_dir(&ldir);
26359+ err = PTR_ERR(new_xino);
26360+ if (IS_ERR(new_xino))
26361+ goto out;
26362+ err = 0;
26363+ fput(file);
26364+ br->br_xino.xi_file = new_xino;
26365+
26366+ h_sb = br->br_mnt->mnt_sb;
26367+ for (bi = 0; bi <= bend; bi++) {
26368+ if (unlikely(bi == bindex))
26369+ continue;
26370+ br = au_sbr(sb, bi);
26371+ if (br->br_mnt->mnt_sb != h_sb)
26372+ continue;
26373+
26374+ fput(br->br_xino.xi_file);
26375+ br->br_xino.xi_file = new_xino;
26376+ get_file(new_xino);
26377+ }
26378+
4f0767ce 26379+out:
1facf9fc 26380+ return err;
26381+}
26382+
26383+struct xino_do_trunc_args {
26384+ struct super_block *sb;
26385+ struct au_branch *br;
26386+};
26387+
26388+static void xino_do_trunc(void *_args)
26389+{
26390+ struct xino_do_trunc_args *args = _args;
26391+ struct super_block *sb;
26392+ struct au_branch *br;
26393+ struct inode *dir;
26394+ int err;
26395+ aufs_bindex_t bindex;
26396+
26397+ err = 0;
26398+ sb = args->sb;
26399+ dir = sb->s_root->d_inode;
26400+ br = args->br;
26401+
26402+ si_noflush_write_lock(sb);
26403+ ii_read_lock_parent(dir);
26404+ bindex = au_br_index(sb, br->br_id);
26405+ err = au_xino_trunc(sb, bindex);
dece6358
AM
26406+ if (!err
26407+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 26408+ >= br->br_xino_upper)
26409+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
26410+
1facf9fc 26411+ ii_read_unlock(dir);
26412+ if (unlikely(err))
4a4d8108 26413+ pr_warning("err b%d, (%d)\n", bindex, err);
1facf9fc 26414+ atomic_dec(&br->br_xino_running);
26415+ atomic_dec(&br->br_count);
26416+ au_nwt_done(&au_sbi(sb)->si_nowait);
26417+ si_write_unlock(sb);
26418+ kfree(args);
26419+}
26420+
26421+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
26422+{
26423+ struct xino_do_trunc_args *args;
26424+ int wkq_err;
26425+
26426+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
26427+ < br->br_xino_upper)
26428+ return;
26429+
26430+ if (atomic_inc_return(&br->br_xino_running) > 1)
26431+ goto out;
26432+
26433+ /* lock and kfree() will be called in trunc_xino() */
26434+ args = kmalloc(sizeof(*args), GFP_NOFS);
26435+ if (unlikely(!args)) {
26436+ AuErr1("no memory\n");
26437+ goto out_args;
26438+ }
26439+
e49829fe 26440+ atomic_inc(&br->br_count);
1facf9fc 26441+ args->sb = sb;
26442+ args->br = br;
26443+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
26444+ if (!wkq_err)
26445+ return; /* success */
26446+
4a4d8108 26447+ pr_err("wkq %d\n", wkq_err);
e49829fe 26448+ atomic_dec(&br->br_count);
1facf9fc 26449+
4f0767ce 26450+out_args:
1facf9fc 26451+ kfree(args);
4f0767ce 26452+out:
e49829fe 26453+ atomic_dec(&br->br_xino_running);
1facf9fc 26454+}
26455+
26456+/* ---------------------------------------------------------------------- */
26457+
26458+static int au_xino_do_write(au_writef_t write, struct file *file,
26459+ ino_t h_ino, ino_t ino)
26460+{
26461+ loff_t pos;
26462+ ssize_t sz;
26463+
26464+ pos = h_ino;
26465+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
26466+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
26467+ return -EFBIG;
26468+ }
26469+ pos *= sizeof(ino);
26470+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
26471+ if (sz == sizeof(ino))
26472+ return 0; /* success */
26473+
26474+ AuIOErr("write failed (%zd)\n", sz);
26475+ return -EIO;
26476+}
26477+
26478+/*
26479+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
26480+ * at the position of @h_ino.
26481+ * even if @ino is zero, it is written to the xinofile and means no entry.
26482+ * if the size of the xino file on a specific filesystem exceeds the watermark,
26483+ * try truncating it.
26484+ */
26485+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
26486+ ino_t ino)
26487+{
26488+ int err;
26489+ unsigned int mnt_flags;
26490+ struct au_branch *br;
26491+
26492+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
26493+ || ((loff_t)-1) > 0);
dece6358 26494+ SiMustAnyLock(sb);
1facf9fc 26495+
26496+ mnt_flags = au_mntflags(sb);
26497+ if (!au_opt_test(mnt_flags, XINO))
26498+ return 0;
26499+
26500+ br = au_sbr(sb, bindex);
26501+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
26502+ h_ino, ino);
26503+ if (!err) {
26504+ if (au_opt_test(mnt_flags, TRUNC_XINO)
26505+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
26506+ xino_try_trunc(sb, br);
26507+ return 0; /* success */
26508+ }
26509+
26510+ AuIOErr("write failed (%d)\n", err);
26511+ return -EIO;
26512+}
26513+
26514+/* ---------------------------------------------------------------------- */
26515+
26516+/* aufs inode number bitmap */
26517+
26518+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
26519+static ino_t xib_calc_ino(unsigned long pindex, int bit)
26520+{
26521+ ino_t ino;
26522+
26523+ AuDebugOn(bit < 0 || page_bits <= bit);
26524+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
26525+ return ino;
26526+}
26527+
26528+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
26529+{
26530+ AuDebugOn(ino < AUFS_FIRST_INO);
26531+ ino -= AUFS_FIRST_INO;
26532+ *pindex = ino / page_bits;
26533+ *bit = ino % page_bits;
26534+}
26535+
26536+static int xib_pindex(struct super_block *sb, unsigned long pindex)
26537+{
26538+ int err;
26539+ loff_t pos;
26540+ ssize_t sz;
26541+ struct au_sbinfo *sbinfo;
26542+ struct file *xib;
26543+ unsigned long *p;
26544+
26545+ sbinfo = au_sbi(sb);
26546+ MtxMustLock(&sbinfo->si_xib_mtx);
26547+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
26548+ || !au_opt_test(sbinfo->si_mntflags, XINO));
26549+
26550+ if (pindex == sbinfo->si_xib_last_pindex)
26551+ return 0;
26552+
26553+ xib = sbinfo->si_xib;
26554+ p = sbinfo->si_xib_buf;
26555+ pos = sbinfo->si_xib_last_pindex;
26556+ pos *= PAGE_SIZE;
26557+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
26558+ if (unlikely(sz != PAGE_SIZE))
26559+ goto out;
26560+
26561+ pos = pindex;
26562+ pos *= PAGE_SIZE;
26563+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
26564+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
26565+ else {
26566+ memset(p, 0, PAGE_SIZE);
26567+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
26568+ }
26569+ if (sz == PAGE_SIZE) {
26570+ sbinfo->si_xib_last_pindex = pindex;
26571+ return 0; /* success */
26572+ }
26573+
4f0767ce 26574+out:
b752ccd1
AM
26575+ AuIOErr1("write failed (%zd)\n", sz);
26576+ err = sz;
26577+ if (sz >= 0)
26578+ err = -EIO;
26579+ return err;
26580+}
26581+
26582+/* ---------------------------------------------------------------------- */
26583+
26584+static void au_xib_clear_bit(struct inode *inode)
26585+{
26586+ int err, bit;
26587+ unsigned long pindex;
26588+ struct super_block *sb;
26589+ struct au_sbinfo *sbinfo;
26590+
26591+ AuDebugOn(inode->i_nlink);
26592+
26593+ sb = inode->i_sb;
26594+ xib_calc_bit(inode->i_ino, &pindex, &bit);
26595+ AuDebugOn(page_bits <= bit);
26596+ sbinfo = au_sbi(sb);
26597+ mutex_lock(&sbinfo->si_xib_mtx);
26598+ err = xib_pindex(sb, pindex);
26599+ if (!err) {
26600+ clear_bit(bit, sbinfo->si_xib_buf);
26601+ sbinfo->si_xib_next_bit = bit;
26602+ }
26603+ mutex_unlock(&sbinfo->si_xib_mtx);
26604+}
26605+
26606+/* for s_op->delete_inode() */
26607+void au_xino_delete_inode(struct inode *inode, const int unlinked)
26608+{
26609+ int err;
26610+ unsigned int mnt_flags;
26611+ aufs_bindex_t bindex, bend, bi;
26612+ unsigned char try_trunc;
26613+ struct au_iinfo *iinfo;
26614+ struct super_block *sb;
26615+ struct au_hinode *hi;
26616+ struct inode *h_inode;
26617+ struct au_branch *br;
26618+ au_writef_t xwrite;
26619+
26620+ sb = inode->i_sb;
26621+ mnt_flags = au_mntflags(sb);
26622+ if (!au_opt_test(mnt_flags, XINO)
26623+ || inode->i_ino == AUFS_ROOT_INO)
26624+ return;
26625+
26626+ if (unlinked) {
26627+ au_xigen_inc(inode);
26628+ au_xib_clear_bit(inode);
26629+ }
26630+
26631+ iinfo = au_ii(inode);
26632+ if (!iinfo)
26633+ return;
1facf9fc 26634+
b752ccd1
AM
26635+ bindex = iinfo->ii_bstart;
26636+ if (bindex < 0)
26637+ return;
1facf9fc 26638+
b752ccd1
AM
26639+ xwrite = au_sbi(sb)->si_xwrite;
26640+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
26641+ hi = iinfo->ii_hinode + bindex;
26642+ bend = iinfo->ii_bend;
26643+ for (; bindex <= bend; bindex++, hi++) {
26644+ h_inode = hi->hi_inode;
26645+ if (!h_inode
26646+ || (!unlinked && h_inode->i_nlink))
26647+ continue;
1facf9fc 26648+
b752ccd1
AM
26649+ /* inode may not be revalidated */
26650+ bi = au_br_index(sb, hi->hi_id);
26651+ if (bi < 0)
26652+ continue;
1facf9fc 26653+
b752ccd1
AM
26654+ br = au_sbr(sb, bi);
26655+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
26656+ h_inode->i_ino, /*ino*/0);
26657+ if (!err && try_trunc
26658+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
26659+ xino_try_trunc(sb, br);
1facf9fc 26660+ }
1facf9fc 26661+}
26662+
26663+/* get an unused inode number from bitmap */
26664+ino_t au_xino_new_ino(struct super_block *sb)
26665+{
26666+ ino_t ino;
26667+ unsigned long *p, pindex, ul, pend;
26668+ struct au_sbinfo *sbinfo;
26669+ struct file *file;
26670+ int free_bit, err;
26671+
26672+ if (!au_opt_test(au_mntflags(sb), XINO))
26673+ return iunique(sb, AUFS_FIRST_INO);
26674+
26675+ sbinfo = au_sbi(sb);
26676+ mutex_lock(&sbinfo->si_xib_mtx);
26677+ p = sbinfo->si_xib_buf;
26678+ free_bit = sbinfo->si_xib_next_bit;
26679+ if (free_bit < page_bits && !test_bit(free_bit, p))
26680+ goto out; /* success */
26681+ free_bit = find_first_zero_bit(p, page_bits);
26682+ if (free_bit < page_bits)
26683+ goto out; /* success */
26684+
26685+ pindex = sbinfo->si_xib_last_pindex;
26686+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
26687+ err = xib_pindex(sb, ul);
26688+ if (unlikely(err))
26689+ goto out_err;
26690+ free_bit = find_first_zero_bit(p, page_bits);
26691+ if (free_bit < page_bits)
26692+ goto out; /* success */
26693+ }
26694+
26695+ file = sbinfo->si_xib;
26696+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
26697+ for (ul = pindex + 1; ul <= pend; ul++) {
26698+ err = xib_pindex(sb, ul);
26699+ if (unlikely(err))
26700+ goto out_err;
26701+ free_bit = find_first_zero_bit(p, page_bits);
26702+ if (free_bit < page_bits)
26703+ goto out; /* success */
26704+ }
26705+ BUG();
26706+
4f0767ce 26707+out:
1facf9fc 26708+ set_bit(free_bit, p);
26709+ sbinfo->si_xib_next_bit++;
26710+ pindex = sbinfo->si_xib_last_pindex;
26711+ mutex_unlock(&sbinfo->si_xib_mtx);
26712+ ino = xib_calc_ino(pindex, free_bit);
26713+ AuDbg("i%lu\n", (unsigned long)ino);
26714+ return ino;
4f0767ce 26715+out_err:
1facf9fc 26716+ mutex_unlock(&sbinfo->si_xib_mtx);
26717+ AuDbg("i0\n");
26718+ return 0;
26719+}
26720+
26721+/*
26722+ * read @ino from xinofile for the specified branch{@sb, @bindex}
26723+ * at the position of @h_ino.
26724+ * if @ino does not exist and @do_new is true, get new one.
26725+ */
26726+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
26727+ ino_t *ino)
26728+{
26729+ int err;
26730+ ssize_t sz;
26731+ loff_t pos;
26732+ struct file *file;
26733+ struct au_sbinfo *sbinfo;
26734+
26735+ *ino = 0;
26736+ if (!au_opt_test(au_mntflags(sb), XINO))
26737+ return 0; /* no xino */
26738+
26739+ err = 0;
26740+ sbinfo = au_sbi(sb);
26741+ pos = h_ino;
26742+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
26743+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
26744+ return -EFBIG;
26745+ }
26746+ pos *= sizeof(*ino);
26747+
26748+ file = au_sbr(sb, bindex)->br_xino.xi_file;
26749+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
26750+ return 0; /* no ino */
26751+
26752+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
26753+ if (sz == sizeof(*ino))
26754+ return 0; /* success */
26755+
26756+ err = sz;
26757+ if (unlikely(sz >= 0)) {
26758+ err = -EIO;
26759+ AuIOErr("xino read error (%zd)\n", sz);
26760+ }
26761+
26762+ return err;
26763+}
26764+
26765+/* ---------------------------------------------------------------------- */
26766+
26767+/* create and set a new xino file */
26768+
26769+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
26770+{
26771+ struct file *file;
26772+ struct dentry *h_parent, *d;
26773+ struct inode *h_dir;
26774+ int err;
26775+
26776+ /*
26777+ * at mount-time, and the xino file is the default path,
4a4d8108 26778+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 26779+ * when a user specified the xino, we cannot get au_hdir to be ignored.
26780+ */
26781+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
26782+ S_IRUGO | S_IWUGO);
26783+ if (IS_ERR(file)) {
26784+ if (!silent)
4a4d8108 26785+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 26786+ return file;
26787+ }
26788+
26789+ /* keep file count */
26790+ h_parent = dget_parent(file->f_dentry);
26791+ h_dir = h_parent->d_inode;
26792+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
26793+ /* mnt_want_write() is unnecessary here */
26794+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
26795+ mutex_unlock(&h_dir->i_mutex);
26796+ dput(h_parent);
26797+ if (unlikely(err)) {
26798+ if (!silent)
4a4d8108 26799+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 26800+ goto out;
26801+ }
26802+
26803+ err = -EINVAL;
26804+ d = file->f_dentry;
26805+ if (unlikely(sb == d->d_sb)) {
26806+ if (!silent)
4a4d8108 26807+ pr_err("%s must be outside\n", fname);
1facf9fc 26808+ goto out;
26809+ }
26810+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
26811+ if (!silent)
4a4d8108
AM
26812+ pr_err("xino doesn't support %s(%s)\n",
26813+ fname, au_sbtype(d->d_sb));
1facf9fc 26814+ goto out;
26815+ }
26816+ return file; /* success */
26817+
4f0767ce 26818+out:
1facf9fc 26819+ fput(file);
26820+ file = ERR_PTR(err);
26821+ return file;
26822+}
26823+
26824+/*
26825+ * find another branch who is on the same filesystem of the specified
26826+ * branch{@btgt}. search until @bend.
26827+ */
26828+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
26829+ aufs_bindex_t bend)
26830+{
26831+ aufs_bindex_t bindex;
26832+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
26833+
26834+ for (bindex = 0; bindex < btgt; bindex++)
26835+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
26836+ return bindex;
26837+ for (bindex++; bindex <= bend; bindex++)
26838+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
26839+ return bindex;
26840+ return -1;
26841+}
26842+
26843+/* ---------------------------------------------------------------------- */
26844+
26845+/*
26846+ * initialize the xinofile for the specified branch @br
26847+ * at the place/path where @base_file indicates.
26848+ * test whether another branch is on the same filesystem or not,
26849+ * if @do_test is true.
26850+ */
26851+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
26852+ struct file *base_file, int do_test)
26853+{
26854+ int err;
26855+ ino_t ino;
26856+ aufs_bindex_t bend, bindex;
26857+ struct au_branch *shared_br, *b;
26858+ struct file *file;
26859+ struct super_block *tgt_sb;
26860+
26861+ shared_br = NULL;
26862+ bend = au_sbend(sb);
26863+ if (do_test) {
26864+ tgt_sb = br->br_mnt->mnt_sb;
26865+ for (bindex = 0; bindex <= bend; bindex++) {
26866+ b = au_sbr(sb, bindex);
26867+ if (tgt_sb == b->br_mnt->mnt_sb) {
26868+ shared_br = b;
26869+ break;
26870+ }
26871+ }
26872+ }
26873+
26874+ if (!shared_br || !shared_br->br_xino.xi_file) {
26875+ struct au_xino_lock_dir ldir;
26876+
26877+ au_xino_lock_dir(sb, base_file, &ldir);
26878+ /* mnt_want_write() is unnecessary here */
26879+ file = au_xino_create2(base_file, NULL);
26880+ au_xino_unlock_dir(&ldir);
26881+ err = PTR_ERR(file);
26882+ if (IS_ERR(file))
26883+ goto out;
26884+ br->br_xino.xi_file = file;
26885+ } else {
26886+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
26887+ get_file(br->br_xino.xi_file);
26888+ }
26889+
26890+ ino = AUFS_ROOT_INO;
26891+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
26892+ h_ino, ino);
b752ccd1
AM
26893+ if (unlikely(err)) {
26894+ fput(br->br_xino.xi_file);
26895+ br->br_xino.xi_file = NULL;
26896+ }
1facf9fc 26897+
4f0767ce 26898+out:
1facf9fc 26899+ return err;
26900+}
26901+
26902+/* ---------------------------------------------------------------------- */
26903+
26904+/* trucate a xino bitmap file */
26905+
26906+/* todo: slow */
26907+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
26908+{
26909+ int err, bit;
26910+ ssize_t sz;
26911+ unsigned long pindex;
26912+ loff_t pos, pend;
26913+ struct au_sbinfo *sbinfo;
26914+ au_readf_t func;
26915+ ino_t *ino;
26916+ unsigned long *p;
26917+
26918+ err = 0;
26919+ sbinfo = au_sbi(sb);
dece6358 26920+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 26921+ p = sbinfo->si_xib_buf;
26922+ func = sbinfo->si_xread;
26923+ pend = i_size_read(file->f_dentry->d_inode);
26924+ pos = 0;
26925+ while (pos < pend) {
26926+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
26927+ err = sz;
26928+ if (unlikely(sz <= 0))
26929+ goto out;
26930+
26931+ err = 0;
26932+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
26933+ if (unlikely(*ino < AUFS_FIRST_INO))
26934+ continue;
26935+
26936+ xib_calc_bit(*ino, &pindex, &bit);
26937+ AuDebugOn(page_bits <= bit);
26938+ err = xib_pindex(sb, pindex);
26939+ if (!err)
26940+ set_bit(bit, p);
26941+ else
26942+ goto out;
26943+ }
26944+ }
26945+
4f0767ce 26946+out:
1facf9fc 26947+ return err;
26948+}
26949+
26950+static int xib_restore(struct super_block *sb)
26951+{
26952+ int err;
26953+ aufs_bindex_t bindex, bend;
26954+ void *page;
26955+
26956+ err = -ENOMEM;
26957+ page = (void *)__get_free_page(GFP_NOFS);
26958+ if (unlikely(!page))
26959+ goto out;
26960+
26961+ err = 0;
26962+ bend = au_sbend(sb);
26963+ for (bindex = 0; !err && bindex <= bend; bindex++)
26964+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
26965+ err = do_xib_restore
26966+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
26967+ else
26968+ AuDbg("b%d\n", bindex);
26969+ free_page((unsigned long)page);
26970+
4f0767ce 26971+out:
1facf9fc 26972+ return err;
26973+}
26974+
26975+int au_xib_trunc(struct super_block *sb)
26976+{
26977+ int err;
26978+ ssize_t sz;
26979+ loff_t pos;
26980+ struct au_xino_lock_dir ldir;
26981+ struct au_sbinfo *sbinfo;
26982+ unsigned long *p;
26983+ struct file *file;
26984+
dece6358
AM
26985+ SiMustWriteLock(sb);
26986+
1facf9fc 26987+ err = 0;
26988+ sbinfo = au_sbi(sb);
26989+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
26990+ goto out;
26991+
26992+ file = sbinfo->si_xib;
26993+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
26994+ goto out;
26995+
26996+ au_xino_lock_dir(sb, file, &ldir);
26997+ /* mnt_want_write() is unnecessary here */
26998+ file = au_xino_create2(sbinfo->si_xib, NULL);
26999+ au_xino_unlock_dir(&ldir);
27000+ err = PTR_ERR(file);
27001+ if (IS_ERR(file))
27002+ goto out;
27003+ fput(sbinfo->si_xib);
27004+ sbinfo->si_xib = file;
27005+
27006+ p = sbinfo->si_xib_buf;
27007+ memset(p, 0, PAGE_SIZE);
27008+ pos = 0;
27009+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
27010+ if (unlikely(sz != PAGE_SIZE)) {
27011+ err = sz;
27012+ AuIOErr("err %d\n", err);
27013+ if (sz >= 0)
27014+ err = -EIO;
27015+ goto out;
27016+ }
27017+
27018+ mutex_lock(&sbinfo->si_xib_mtx);
27019+ /* mnt_want_write() is unnecessary here */
27020+ err = xib_restore(sb);
27021+ mutex_unlock(&sbinfo->si_xib_mtx);
27022+
27023+out:
27024+ return err;
27025+}
27026+
27027+/* ---------------------------------------------------------------------- */
27028+
27029+/*
27030+ * xino mount option handlers
27031+ */
27032+static au_readf_t find_readf(struct file *h_file)
27033+{
27034+ const struct file_operations *fop = h_file->f_op;
27035+
27036+ if (fop) {
27037+ if (fop->read)
27038+ return fop->read;
27039+ if (fop->aio_read)
27040+ return do_sync_read;
27041+ }
27042+ return ERR_PTR(-ENOSYS);
27043+}
27044+
27045+static au_writef_t find_writef(struct file *h_file)
27046+{
27047+ const struct file_operations *fop = h_file->f_op;
27048+
27049+ if (fop) {
27050+ if (fop->write)
27051+ return fop->write;
27052+ if (fop->aio_write)
27053+ return do_sync_write;
27054+ }
27055+ return ERR_PTR(-ENOSYS);
27056+}
27057+
27058+/* xino bitmap */
27059+static void xino_clear_xib(struct super_block *sb)
27060+{
27061+ struct au_sbinfo *sbinfo;
27062+
dece6358
AM
27063+ SiMustWriteLock(sb);
27064+
1facf9fc 27065+ sbinfo = au_sbi(sb);
27066+ sbinfo->si_xread = NULL;
27067+ sbinfo->si_xwrite = NULL;
27068+ if (sbinfo->si_xib)
27069+ fput(sbinfo->si_xib);
27070+ sbinfo->si_xib = NULL;
27071+ free_page((unsigned long)sbinfo->si_xib_buf);
27072+ sbinfo->si_xib_buf = NULL;
27073+}
27074+
27075+static int au_xino_set_xib(struct super_block *sb, struct file *base)
27076+{
27077+ int err;
27078+ loff_t pos;
27079+ struct au_sbinfo *sbinfo;
27080+ struct file *file;
27081+
dece6358
AM
27082+ SiMustWriteLock(sb);
27083+
1facf9fc 27084+ sbinfo = au_sbi(sb);
27085+ file = au_xino_create2(base, sbinfo->si_xib);
27086+ err = PTR_ERR(file);
27087+ if (IS_ERR(file))
27088+ goto out;
27089+ if (sbinfo->si_xib)
27090+ fput(sbinfo->si_xib);
27091+ sbinfo->si_xib = file;
27092+ sbinfo->si_xread = find_readf(file);
27093+ sbinfo->si_xwrite = find_writef(file);
27094+
27095+ err = -ENOMEM;
27096+ if (!sbinfo->si_xib_buf)
27097+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
27098+ if (unlikely(!sbinfo->si_xib_buf))
27099+ goto out_unset;
27100+
27101+ sbinfo->si_xib_last_pindex = 0;
27102+ sbinfo->si_xib_next_bit = 0;
27103+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
27104+ pos = 0;
27105+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
27106+ PAGE_SIZE, &pos);
27107+ if (unlikely(err != PAGE_SIZE))
27108+ goto out_free;
27109+ }
27110+ err = 0;
27111+ goto out; /* success */
27112+
4f0767ce 27113+out_free:
1facf9fc 27114+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
27115+ sbinfo->si_xib_buf = NULL;
27116+ if (err >= 0)
27117+ err = -EIO;
4f0767ce 27118+out_unset:
b752ccd1
AM
27119+ fput(sbinfo->si_xib);
27120+ sbinfo->si_xib = NULL;
27121+ sbinfo->si_xread = NULL;
27122+ sbinfo->si_xwrite = NULL;
4f0767ce 27123+out:
b752ccd1 27124+ return err;
1facf9fc 27125+}
27126+
b752ccd1
AM
27127+/* xino for each branch */
27128+static void xino_clear_br(struct super_block *sb)
27129+{
27130+ aufs_bindex_t bindex, bend;
27131+ struct au_branch *br;
1facf9fc 27132+
b752ccd1
AM
27133+ bend = au_sbend(sb);
27134+ for (bindex = 0; bindex <= bend; bindex++) {
27135+ br = au_sbr(sb, bindex);
27136+ if (!br || !br->br_xino.xi_file)
27137+ continue;
27138+
27139+ fput(br->br_xino.xi_file);
27140+ br->br_xino.xi_file = NULL;
27141+ }
27142+}
27143+
27144+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 27145+{
27146+ int err;
b752ccd1
AM
27147+ ino_t ino;
27148+ aufs_bindex_t bindex, bend, bshared;
27149+ struct {
27150+ struct file *old, *new;
27151+ } *fpair, *p;
27152+ struct au_branch *br;
27153+ struct inode *inode;
27154+ au_writef_t writef;
1facf9fc 27155+
b752ccd1
AM
27156+ SiMustWriteLock(sb);
27157+
27158+ err = -ENOMEM;
27159+ bend = au_sbend(sb);
27160+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
27161+ if (unlikely(!fpair))
1facf9fc 27162+ goto out;
27163+
b752ccd1
AM
27164+ inode = sb->s_root->d_inode;
27165+ ino = AUFS_ROOT_INO;
27166+ writef = au_sbi(sb)->si_xwrite;
27167+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
27168+ br = au_sbr(sb, bindex);
27169+ bshared = is_sb_shared(sb, bindex, bindex - 1);
27170+ if (bshared >= 0) {
27171+ /* shared xino */
27172+ *p = fpair[bshared];
27173+ get_file(p->new);
27174+ }
27175+
27176+ if (!p->new) {
27177+ /* new xino */
27178+ p->old = br->br_xino.xi_file;
27179+ p->new = au_xino_create2(base, br->br_xino.xi_file);
27180+ err = PTR_ERR(p->new);
27181+ if (IS_ERR(p->new)) {
27182+ p->new = NULL;
27183+ goto out_pair;
27184+ }
27185+ }
27186+
27187+ err = au_xino_do_write(writef, p->new,
27188+ au_h_iptr(inode, bindex)->i_ino, ino);
27189+ if (unlikely(err))
27190+ goto out_pair;
27191+ }
27192+
27193+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
27194+ br = au_sbr(sb, bindex);
27195+ if (br->br_xino.xi_file)
27196+ fput(br->br_xino.xi_file);
27197+ get_file(p->new);
27198+ br->br_xino.xi_file = p->new;
27199+ }
1facf9fc 27200+
4f0767ce 27201+out_pair:
b752ccd1
AM
27202+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
27203+ if (p->new)
27204+ fput(p->new);
27205+ else
27206+ break;
27207+ kfree(fpair);
4f0767ce 27208+out:
1facf9fc 27209+ return err;
27210+}
b752ccd1
AM
27211+
27212+void au_xino_clr(struct super_block *sb)
27213+{
27214+ struct au_sbinfo *sbinfo;
27215+
27216+ au_xigen_clr(sb);
27217+ xino_clear_xib(sb);
27218+ xino_clear_br(sb);
27219+ sbinfo = au_sbi(sb);
27220+ /* lvalue, do not call au_mntflags() */
27221+ au_opt_clr(sbinfo->si_mntflags, XINO);
27222+}
27223+
27224+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
27225+{
27226+ int err, skip;
27227+ struct dentry *parent, *cur_parent;
27228+ struct qstr *dname, *cur_name;
27229+ struct file *cur_xino;
27230+ struct inode *dir;
27231+ struct au_sbinfo *sbinfo;
27232+
27233+ SiMustWriteLock(sb);
27234+
27235+ err = 0;
27236+ sbinfo = au_sbi(sb);
27237+ parent = dget_parent(xino->file->f_dentry);
27238+ if (remount) {
27239+ skip = 0;
27240+ dname = &xino->file->f_dentry->d_name;
27241+ cur_xino = sbinfo->si_xib;
27242+ if (cur_xino) {
27243+ cur_parent = dget_parent(cur_xino->f_dentry);
27244+ cur_name = &cur_xino->f_dentry->d_name;
27245+ skip = (cur_parent == parent
27246+ && dname->len == cur_name->len
27247+ && !memcmp(dname->name, cur_name->name,
27248+ dname->len));
27249+ dput(cur_parent);
27250+ }
27251+ if (skip)
27252+ goto out;
27253+ }
27254+
27255+ au_opt_set(sbinfo->si_mntflags, XINO);
27256+ dir = parent->d_inode;
27257+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
27258+ /* mnt_want_write() is unnecessary here */
27259+ err = au_xino_set_xib(sb, xino->file);
27260+ if (!err)
27261+ err = au_xigen_set(sb, xino->file);
27262+ if (!err)
27263+ err = au_xino_set_br(sb, xino->file);
27264+ mutex_unlock(&dir->i_mutex);
27265+ if (!err)
27266+ goto out; /* success */
27267+
27268+ /* reset all */
27269+ AuIOErr("failed creating xino(%d).\n", err);
27270+
4f0767ce 27271+out:
b752ccd1
AM
27272+ dput(parent);
27273+ return err;
27274+}
27275+
27276+/* ---------------------------------------------------------------------- */
27277+
27278+/*
27279+ * create a xinofile at the default place/path.
27280+ */
27281+struct file *au_xino_def(struct super_block *sb)
27282+{
27283+ struct file *file;
27284+ char *page, *p;
27285+ struct au_branch *br;
27286+ struct super_block *h_sb;
27287+ struct path path;
27288+ aufs_bindex_t bend, bindex, bwr;
27289+
27290+ br = NULL;
27291+ bend = au_sbend(sb);
27292+ bwr = -1;
27293+ for (bindex = 0; bindex <= bend; bindex++) {
27294+ br = au_sbr(sb, bindex);
27295+ if (au_br_writable(br->br_perm)
27296+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
27297+ bwr = bindex;
27298+ break;
27299+ }
27300+ }
27301+
27302+ if (bwr >= 0) {
27303+ file = ERR_PTR(-ENOMEM);
27304+ page = __getname_gfp(GFP_NOFS);
27305+ if (unlikely(!page))
27306+ goto out;
27307+ path.mnt = br->br_mnt;
27308+ path.dentry = au_h_dptr(sb->s_root, bwr);
27309+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
27310+ file = (void *)p;
27311+ if (!IS_ERR(p)) {
27312+ strcat(p, "/" AUFS_XINO_FNAME);
27313+ AuDbg("%s\n", p);
27314+ file = au_xino_create(sb, p, /*silent*/0);
27315+ if (!IS_ERR(file))
27316+ au_xino_brid_set(sb, br->br_id);
27317+ }
27318+ __putname(page);
27319+ } else {
27320+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
27321+ if (IS_ERR(file))
27322+ goto out;
27323+ h_sb = file->f_dentry->d_sb;
27324+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
27325+ pr_err("xino doesn't support %s(%s)\n",
27326+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
27327+ fput(file);
27328+ file = ERR_PTR(-EINVAL);
27329+ }
27330+ if (!IS_ERR(file))
27331+ au_xino_brid_set(sb, -1);
27332+ }
27333+
4f0767ce 27334+out:
b752ccd1
AM
27335+ return file;
27336+}
27337+
27338+/* ---------------------------------------------------------------------- */
27339+
27340+int au_xino_path(struct seq_file *seq, struct file *file)
27341+{
27342+ int err;
27343+
27344+ err = au_seq_path(seq, &file->f_path);
27345+ if (unlikely(err < 0))
27346+ goto out;
27347+
27348+ err = 0;
27349+#define Deleted "\\040(deleted)"
27350+ seq->count -= sizeof(Deleted) - 1;
27351+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
27352+ sizeof(Deleted) - 1));
27353+#undef Deleted
27354+
4f0767ce 27355+out:
b752ccd1
AM
27356+ return err;
27357+}
e49829fe 27358--- /dev/null
0c5527e5 27359+++ linux-2.6/include/linux/aufs_type.h 2010-11-03 09:30:26.000000000 +0100
953406b4 27360@@ -0,0 +1,198 @@
1facf9fc 27361+/*
4a4d8108 27362+ * Copyright (C) 2005-2010 Junjiro R. Okajima
1facf9fc 27363+ *
27364+ * This program, aufs is free software; you can redistribute it and/or modify
27365+ * it under the terms of the GNU General Public License as published by
27366+ * the Free Software Foundation; either version 2 of the License, or
27367+ * (at your option) any later version.
dece6358
AM
27368+ *
27369+ * This program is distributed in the hope that it will be useful,
27370+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27371+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27372+ * GNU General Public License for more details.
27373+ *
27374+ * You should have received a copy of the GNU General Public License
27375+ * along with this program; if not, write to the Free Software
27376+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27377+ */
27378+
27379+#ifndef __AUFS_TYPE_H__
27380+#define __AUFS_TYPE_H__
27381+
27382+#include <linux/ioctl.h>
953406b4
AM
27383+/* for those who didn't "make headers_install" */
27384+#ifdef __KERNEL__
4a4d8108 27385+#include <linux/kernel.h>
953406b4 27386+#endif
4a4d8108 27387+#include <linux/limits.h>
1308ab2a 27388+#include <linux/types.h>
1facf9fc 27389+
0c5527e5 27390+#define AUFS_VERSION "2.1-standalone.tree-36-UNRELEASED-20101103"
1facf9fc 27391+
27392+/* todo? move this to linux-2.6.19/include/magic.h */
27393+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
27394+
27395+/* ---------------------------------------------------------------------- */
27396+
27397+#ifdef CONFIG_AUFS_BRANCH_MAX_127
1308ab2a 27398+typedef __s8 aufs_bindex_t;
1facf9fc 27399+#define AUFS_BRANCH_MAX 127
27400+#else
1308ab2a 27401+typedef __s16 aufs_bindex_t;
1facf9fc 27402+#ifdef CONFIG_AUFS_BRANCH_MAX_511
27403+#define AUFS_BRANCH_MAX 511
27404+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
27405+#define AUFS_BRANCH_MAX 1023
27406+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
27407+#define AUFS_BRANCH_MAX 32767
27408+#endif
27409+#endif
27410+
27411+#ifdef __KERNEL__
27412+#ifndef AUFS_BRANCH_MAX
27413+#error unknown CONFIG_AUFS_BRANCH_MAX value
27414+#endif
27415+#endif /* __KERNEL__ */
27416+
27417+/* ---------------------------------------------------------------------- */
27418+
27419+#define AUFS_NAME "aufs"
27420+#define AUFS_FSTYPE AUFS_NAME
27421+
27422+#define AUFS_ROOT_INO 2
27423+#define AUFS_FIRST_INO 11
27424+
27425+#define AUFS_WH_PFX ".wh."
27426+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
4a4d8108
AM
27427+#define AUFS_WH_TMP_LEN 4
27428+/* a limit for rmdir/rename a dir */
27429+#define AUFS_MAX_NAMELEN (NAME_MAX \
27430+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
27431+ - 1 /* dot */\
27432+ - AUFS_WH_TMP_LEN) /* hex */
1facf9fc 27433+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
27434+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
27435+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
27436+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
27437+#define AUFS_DIRWH_DEF 3
27438+#define AUFS_RDCACHE_DEF 10 /* seconds */
27439+#define AUFS_RDBLK_DEF 512 /* bytes */
27440+#define AUFS_RDHASH_DEF 32
27441+#define AUFS_WKQ_NAME AUFS_NAME "d"
b752ccd1 27442+#define AUFS_WKQ_PRE_NAME AUFS_WKQ_NAME "_pre"
1facf9fc 27443+#define AUFS_MFS_SECOND_DEF 30 /* seconds */
27444+#define AUFS_PLINK_WARN 100 /* number of plinks */
27445+
e49829fe
JR
27446+/* pseudo-link maintenace under /proc */
27447+#define AUFS_PLINK_MAINT_NAME "plink_maint"
27448+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
27449+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
27450+
1facf9fc 27451+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
27452+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
27453+
27454+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
27455+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
27456+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
27457+
27458+/* doubly whiteouted */
27459+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
27460+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
27461+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
27462+
27463+/* branch permission */
27464+#define AUFS_BRPERM_RW "rw"
27465+#define AUFS_BRPERM_RO "ro"
27466+#define AUFS_BRPERM_RR "rr"
27467+#define AUFS_BRPERM_WH "wh"
27468+#define AUFS_BRPERM_NLWH "nolwh"
27469+#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
27470+#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
27471+#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
27472+
27473+/* ---------------------------------------------------------------------- */
27474+
27475+/* ioctl */
27476+enum {
1308ab2a 27477+ /* readdir in userspace */
27478+ AuCtl_RDU,
4a4d8108
AM
27479+ AuCtl_RDU_INO,
27480+
27481+ /* pathconf wrapper */
27482+ AuCtl_WBR_FD
1308ab2a 27483+};
27484+
27485+/* borrowed from linux/include/linux/kernel.h */
27486+#ifndef ALIGN
27487+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
27488+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
27489+#endif
27490+
27491+/* borrowed from linux/include/linux/compiler-gcc3.h */
27492+#ifndef __aligned
27493+#define __aligned(x) __attribute__((aligned(x)))
27494+#define __packed __attribute__((packed))
27495+#endif
27496+
27497+struct au_rdu_cookie {
27498+ __u64 h_pos;
27499+ __s16 bindex;
27500+ __u8 flags;
27501+ __u8 pad;
27502+ __u32 generation;
27503+} __aligned(8);
27504+
27505+struct au_rdu_ent {
27506+ __u64 ino;
27507+ __s16 bindex;
27508+ __u8 type;
27509+ __u8 nlen;
27510+ __u8 wh;
27511+ char name[0];
27512+} __aligned(8);
27513+
27514+static inline int au_rdu_len(int nlen)
27515+{
27516+ /* include the terminating NULL */
27517+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
27518+ sizeof(__u64));
27519+}
27520+
27521+union au_rdu_ent_ul {
27522+ struct au_rdu_ent __user *e;
b752ccd1 27523+ __u64 ul;
1308ab2a 27524+};
27525+
27526+enum {
27527+ AufsCtlRduV_SZ,
1308ab2a 27528+ AufsCtlRduV_End
1facf9fc 27529+};
27530+
1308ab2a 27531+struct aufs_rdu {
27532+ /* input */
27533+ union {
27534+ __u64 sz; /* AuCtl_RDU */
27535+ __u64 nent; /* AuCtl_RDU_INO */
27536+ };
27537+ union au_rdu_ent_ul ent;
27538+ __u16 verify[AufsCtlRduV_End];
27539+
27540+ /* input/output */
27541+ __u32 blk;
27542+
27543+ /* output */
27544+ union au_rdu_ent_ul tail;
27545+ /* number of entries which were added in a single call */
27546+ __u64 rent;
27547+ __u8 full;
27548+ __u8 shwh;
27549+
27550+ struct au_rdu_cookie cookie;
27551+} __aligned(8);
27552+
1facf9fc 27553+#define AuCtlType 'A'
1308ab2a 27554+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
27555+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
4a4d8108 27556+#define AUFS_CTL_WBR_FD _IO(AuCtlType, AuCtl_WBR_FD)
1facf9fc 27557+
0c5527e5
AM
27558+#endif /* __AUFS_TYPE_H__ */
27559aufs2.1 base patch for linux-2.6.35
27560
27561diff --git a/fs/namei.c b/fs/namei.c
27562index 868d0cb..6e92c81 100644
27563--- a/fs/namei.c
27564+++ b/fs/namei.c
27565@@ -1178,7 +1178,7 @@ out:
27566 * needs parent already locked. Doesn't follow mounts.
27567 * SMP-safe.
27568 */
27569-static struct dentry *lookup_hash(struct nameidata *nd)
27570+struct dentry *lookup_hash(struct nameidata *nd)
27571 {
27572 int err;
27573
27574@@ -1188,7 +1188,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
27575 return __lookup_hash(&nd->last, nd->path.dentry, nd);
27576 }
27577
27578-static int __lookup_one_len(const char *name, struct qstr *this,
27579+int __lookup_one_len(const char *name, struct qstr *this,
27580 struct dentry *base, int len)
27581 {
27582 unsigned long hash;
27583diff --git a/fs/splice.c b/fs/splice.c
27584index efdbfec..e01a51e 100644
27585--- a/fs/splice.c
27586+++ b/fs/splice.c
27587@@ -1104,8 +1104,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
27588 /*
27589 * Attempt to initiate a splice from pipe to file.
27590 */
27591-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
27592- loff_t *ppos, size_t len, unsigned int flags)
27593+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
27594+ loff_t *ppos, size_t len, unsigned int flags)
27595 {
27596 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
27597 loff_t *, size_t, unsigned int);
27598@@ -1132,9 +1132,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
27599 /*
27600 * Attempt to initiate a splice from a file to a pipe.
27601 */
27602-static long do_splice_to(struct file *in, loff_t *ppos,
27603- struct pipe_inode_info *pipe, size_t len,
27604- unsigned int flags)
27605+long do_splice_to(struct file *in, loff_t *ppos,
27606+ struct pipe_inode_info *pipe, size_t len,
27607+ unsigned int flags)
27608 {
27609 ssize_t (*splice_read)(struct file *, loff_t *,
27610 struct pipe_inode_info *, size_t, unsigned int);
27611diff --git a/include/linux/namei.h b/include/linux/namei.h
27612index 05b441d..91bc74e 100644
27613--- a/include/linux/namei.h
27614+++ b/include/linux/namei.h
27615@@ -73,6 +73,9 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
27616 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
27617 int (*open)(struct inode *, struct file *));
27618
27619+extern struct dentry *lookup_hash(struct nameidata *nd);
27620+extern int __lookup_one_len(const char *name, struct qstr *this,
27621+ struct dentry *base, int len);
27622 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
27623
27624 extern int follow_down(struct path *);
27625diff --git a/include/linux/splice.h b/include/linux/splice.h
27626index 997c3b4..be9a153 100644
27627--- a/include/linux/splice.h
27628+++ b/include/linux/splice.h
27629@@ -89,4 +89,10 @@ extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *);
27630 extern void splice_shrink_spd(struct pipe_inode_info *,
27631 struct splice_pipe_desc *);
27632
27633+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
27634+ loff_t *ppos, size_t len, unsigned int flags);
27635+extern long do_splice_to(struct file *in, loff_t *ppos,
27636+ struct pipe_inode_info *pipe, size_t len,
27637+ unsigned int flags);
27638+
27639 #endif
27640aufs2.1 kbuild patch for linux-2.6.36
27641
27642diff --git a/fs/Kconfig b/fs/Kconfig
27643index 3d18530..8f582e1 100644
27644--- a/fs/Kconfig
27645+++ b/fs/Kconfig
27646@@ -189,6 +189,7 @@ source "fs/romfs/Kconfig"
27647 source "fs/sysv/Kconfig"
27648 source "fs/ufs/Kconfig"
27649 source "fs/exofs/Kconfig"
27650+source "fs/aufs/Kconfig"
27651
27652 endif # MISC_FILESYSTEMS
27653
27654diff --git a/fs/Makefile b/fs/Makefile
27655index e6ec1d3..b0d795a 100644
27656--- a/fs/Makefile
27657+++ b/fs/Makefile
27658@@ -126,3 +126,4 @@ obj-$(CONFIG_BTRFS_FS) += btrfs/
27659 obj-$(CONFIG_GFS2_FS) += gfs2/
27660 obj-$(CONFIG_EXOFS_FS) += exofs/
27661 obj-$(CONFIG_CEPH_FS) += ceph/
27662+obj-$(CONFIG_AUFS_FS) += aufs/
27663diff --git a/include/linux/Kbuild b/include/linux/Kbuild
27664index 626b629..a841231 100644
27665--- a/include/linux/Kbuild
27666+++ b/include/linux/Kbuild
27667@@ -60,6 +60,7 @@ header-y += atmppp.h
27668 header-y += atmsap.h
27669 header-y += atmsvc.h
27670 header-y += audit.h
27671+header-y += aufs_type.h
27672 header-y += auto_fs.h
27673 header-y += auto_fs4.h
27674 header-y += auxvec.h
27675aufs2.1 standalone patch for linux-2.6.36
27676
27677diff --git a/fs/inode.c b/fs/inode.c
27678index 722860b..bfb0698 100644
27679--- a/fs/inode.c
27680+++ b/fs/inode.c
27681@@ -84,6 +84,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
27682 * the i_state of an inode while it is in use..
27683 */
27684 DEFINE_SPINLOCK(inode_lock);
27685+EXPORT_SYMBOL_GPL(inode_lock);
27686
27687 /*
27688 * iprune_sem provides exclusion between the kswapd or try_to_free_pages
27689diff --git a/fs/namei.c b/fs/namei.c
27690index 56e8ece..ba75f28 100644
27691--- a/fs/namei.c
27692+++ b/fs/namei.c
27693@@ -347,6 +347,7 @@ int deny_write_access(struct file * file)
27694
27695 return 0;
27696 }
27697+EXPORT_SYMBOL_GPL(deny_write_access);
27698
27699 /**
27700 * path_get - get a reference to a path
27701@@ -1177,6 +1178,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
27702 return ERR_PTR(err);
27703 return __lookup_hash(&nd->last, nd->path.dentry, nd);
27704 }
27705+EXPORT_SYMBOL_GPL(lookup_hash);
27706
27707 int __lookup_one_len(const char *name, struct qstr *this,
27708 struct dentry *base, int len)
27709@@ -1199,6 +1201,7 @@ int __lookup_one_len(const char *name, struct qstr *this,
27710 this->hash = end_name_hash(hash);
27711 return 0;
27712 }
27713+EXPORT_SYMBOL_GPL(__lookup_one_len);
27714
27715 /**
27716 * lookup_one_len - filesystem helper to lookup single pathname component
27717diff --git a/fs/namespace.c b/fs/namespace.c
27718index 2e10cb1..8fa77c4 100644
27719--- a/fs/namespace.c
27720+++ b/fs/namespace.c
27721@@ -1283,6 +1283,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
27722 }
27723 return 0;
27724 }
27725+EXPORT_SYMBOL_GPL(iterate_mounts);
27726
27727 static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
27728 {
27729diff --git a/fs/notify/group.c b/fs/notify/group.c
27730index d309f38..f0e9568 100644
27731--- a/fs/notify/group.c
27732+++ b/fs/notify/group.c
27733@@ -22,6 +22,7 @@
27734 #include <linux/srcu.h>
27735 #include <linux/rculist.h>
27736 #include <linux/wait.h>
27737+#include <linux/module.h>
27738
27739 #include <linux/fsnotify_backend.h>
27740 #include "fsnotify.h"
27741@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
27742 if (atomic_dec_and_test(&group->refcnt))
27743 fsnotify_destroy_group(group);
27744 }
27745+EXPORT_SYMBOL_GPL(fsnotify_put_group);
27746
27747 /*
27748 * Create a new fsnotify_group and hold a reference for the group returned.
27749@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
27750
27751 return group;
27752 }
27753+EXPORT_SYMBOL_GPL(fsnotify_alloc_group);
27754diff --git a/fs/notify/mark.c b/fs/notify/mark.c
27755index 325185e..adede09 100644
27756--- a/fs/notify/mark.c
27757+++ b/fs/notify/mark.c
27758@@ -113,6 +113,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
27759 if (atomic_dec_and_test(&mark->refcnt))
27760 mark->free_mark(mark);
27761 }
27762+EXPORT_SYMBOL_GPL(fsnotify_put_mark);
27763
27764 /*
27765 * Any time a mark is getting freed we end up here.
27766@@ -190,6 +191,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
27767 if (unlikely(atomic_dec_and_test(&group->num_marks)))
27768 fsnotify_final_destroy_group(group);
27769 }
27770+EXPORT_SYMBOL_GPL(fsnotify_destroy_mark);
27771
27772 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
27773 {
27774@@ -277,6 +279,7 @@ err:
27775
27776 return ret;
27777 }
27778+EXPORT_SYMBOL_GPL(fsnotify_add_mark);
27779
27780 /*
27781 * clear any marks in a group in which mark->flags & flags is true
27782@@ -332,6 +335,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
27783 atomic_set(&mark->refcnt, 1);
27784 mark->free_mark = free_mark;
27785 }
27786+EXPORT_SYMBOL_GPL(fsnotify_init_mark);
27787
27788 static int fsnotify_mark_destroy(void *ignored)
27789 {
27790diff --git a/fs/open.c b/fs/open.c
27791index 630715f..1c864c7 100644
27792--- a/fs/open.c
27793+++ b/fs/open.c
27794@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
27795 mutex_unlock(&dentry->d_inode->i_mutex);
27796 return ret;
27797 }
27798+EXPORT_SYMBOL_GPL(do_truncate);
27799
27800 static long do_sys_truncate(const char __user *pathname, loff_t length)
27801 {
27802diff --git a/fs/splice.c b/fs/splice.c
27803index 278c94f..033f7ac 100644
27804--- a/fs/splice.c
27805+++ b/fs/splice.c
27806@@ -1116,6 +1116,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
27807
27808 return splice_write(pipe, out, ppos, len, flags);
27809 }
27810+EXPORT_SYMBOL_GPL(do_splice_from);
27811
27812 /*
27813 * Attempt to initiate a splice from a file to a pipe.
27814@@ -1142,6 +1143,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
27815
27816 return splice_read(in, ppos, pipe, len, flags);
27817 }
27818+EXPORT_SYMBOL_GPL(do_splice_to);
27819
27820 /**
27821 * splice_direct_to_actor - splices data directly between two non-pipes
27822diff --git a/security/commoncap.c b/security/commoncap.c
27823index 4e01599..3611e1b 100644
27824--- a/security/commoncap.c
27825+++ b/security/commoncap.c
27826@@ -951,3 +951,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
27827 }
27828 return ret;
27829 }
27830+EXPORT_SYMBOL_GPL(cap_file_mmap);
27831diff --git a/security/device_cgroup.c b/security/device_cgroup.c
27832index 8d9c48f..29108aa 100644
27833--- a/security/device_cgroup.c
27834+++ b/security/device_cgroup.c
27835@@ -515,6 +515,7 @@ found:
27836
27837 return -EPERM;
27838 }
27839+EXPORT_SYMBOL_GPL(devcgroup_inode_permission);
27840
27841 int devcgroup_inode_mknod(int mode, dev_t dev)
27842 {
27843diff --git a/security/security.c b/security/security.c
27844index c53949f..0ae5b91 100644
27845--- a/security/security.c
27846+++ b/security/security.c
27847@@ -376,6 +376,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
27848 return 0;
27849 return security_ops->path_mkdir(dir, dentry, mode);
27850 }
27851+EXPORT_SYMBOL_GPL(security_path_mkdir);
27852
27853 int security_path_rmdir(struct path *dir, struct dentry *dentry)
27854 {
27855@@ -383,6 +384,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
27856 return 0;
27857 return security_ops->path_rmdir(dir, dentry);
27858 }
27859+EXPORT_SYMBOL_GPL(security_path_rmdir);
27860
27861 int security_path_unlink(struct path *dir, struct dentry *dentry)
27862 {
27863@@ -390,6 +392,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
27864 return 0;
27865 return security_ops->path_unlink(dir, dentry);
27866 }
27867+EXPORT_SYMBOL_GPL(security_path_unlink);
27868
27869 int security_path_symlink(struct path *dir, struct dentry *dentry,
27870 const char *old_name)
27871@@ -398,6 +401,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
27872 return 0;
27873 return security_ops->path_symlink(dir, dentry, old_name);
27874 }
27875+EXPORT_SYMBOL_GPL(security_path_symlink);
27876
27877 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
27878 struct dentry *new_dentry)
27879@@ -406,6 +410,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
27880 return 0;
27881 return security_ops->path_link(old_dentry, new_dir, new_dentry);
27882 }
27883+EXPORT_SYMBOL_GPL(security_path_link);
27884
27885 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
27886 struct path *new_dir, struct dentry *new_dentry)
27887@@ -416,6 +421,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
27888 return security_ops->path_rename(old_dir, old_dentry, new_dir,
27889 new_dentry);
27890 }
27891+EXPORT_SYMBOL_GPL(security_path_rename);
27892
27893 int security_path_truncate(struct path *path)
27894 {
27895@@ -423,6 +429,7 @@ int security_path_truncate(struct path *path)
27896 return 0;
27897 return security_ops->path_truncate(path);
27898 }
27899+EXPORT_SYMBOL_GPL(security_path_truncate);
27900
27901 int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
27902 mode_t mode)
27903@@ -431,6 +438,7 @@ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
27904 return 0;
27905 return security_ops->path_chmod(dentry, mnt, mode);
27906 }
27907+EXPORT_SYMBOL_GPL(security_path_chmod);
27908
27909 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
27910 {
27911@@ -438,6 +446,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
27912 return 0;
27913 return security_ops->path_chown(path, uid, gid);
27914 }
27915+EXPORT_SYMBOL_GPL(security_path_chown);
27916
27917 int security_path_chroot(struct path *path)
27918 {
27919@@ -514,6 +523,7 @@ int security_inode_readlink(struct dentry *dentry)
27920 return 0;
27921 return security_ops->inode_readlink(dentry);
27922 }
27923+EXPORT_SYMBOL_GPL(security_inode_readlink);
27924
27925 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
27926 {
27927@@ -528,6 +538,7 @@ int security_inode_permission(struct inode *inode, int mask)
27928 return 0;
27929 return security_ops->inode_permission(inode, mask);
27930 }
27931+EXPORT_SYMBOL_GPL(security_inode_permission);
27932
27933 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
27934 {
27935@@ -627,6 +638,7 @@ int security_file_permission(struct file *file, int mask)
27936
27937 return fsnotify_perm(file, mask);
27938 }
27939+EXPORT_SYMBOL_GPL(security_file_permission);
27940
27941 int security_file_alloc(struct file *file)
27942 {
27943@@ -654,6 +666,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
27944 return ret;
27945 return ima_file_mmap(file, prot);
27946 }
27947+EXPORT_SYMBOL_GPL(security_file_mmap);
27948
27949 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
27950 unsigned long prot)
27951diff --git a/fs/file_table.c b/fs/file_table.c
27952index 44abf87..4081dda 100644
27953--- a/fs/file_table.c
27954+++ b/fs/file_table.c
27955@@ -395,6 +395,8 @@ void file_sb_list_del(struct file *file)
27956 }
27957 }
27958
27959+EXPORT_SYMBOL_GPL(file_sb_list_del);
27960+
27961 #ifdef CONFIG_SMP
27962
27963 /*
27964diff --git a/fs/statfs.c b/fs/statfs.c
27965index 30ea8c8..9025c98 100644
27966--- a/fs/statfs.c
27967+++ b/fs/statfs.c
27968@@ -61,6 +61,7 @@ int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
27969 buf->f_frsize = buf->f_bsize;
27970 return retval;
27971 }
27972+EXPORT_SYMBOL_GPL(statfs_by_dentry);
27973
27974 int vfs_statfs(struct path *path, struct kstatfs *buf)
27975 {
This page took 4.054451 seconds and 4 git commands to generate.